sixlowpan_send.c 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. /****************************************************************************
  2. * net/sixlowpan/sixlowpan_send.c
  3. *
  4. * Licensed to the Apache Software Foundation (ASF) under one or more
  5. * contributor license agreements. See the NOTICE file distributed with
  6. * this work for additional information regarding copyright ownership. The
  7. * ASF licenses this file to you under the Apache License, Version 2.0 (the
  8. * "License"); you may not use this file except in compliance with the
  9. * License. You may obtain a copy of the License at
  10. *
  11. * http://www.apache.org/licenses/LICENSE-2.0
  12. *
  13. * Unless required by applicable law or agreed to in writing, software
  14. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  15. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  16. * License for the specific language governing permissions and limitations
  17. * under the License.
  18. *
  19. ****************************************************************************/
  20. /****************************************************************************
  21. * Included Files
  22. ****************************************************************************/
  23. #include <nuttx/config.h>
  24. #include <assert.h>
  25. #include <errno.h>
  26. #include <debug.h>
  27. #include <nuttx/semaphore.h>
  28. #include <nuttx/net/net.h>
  29. #include <nuttx/net/radiodev.h>
  30. #include "netdev/netdev.h"
  31. #include "devif/devif.h"
  32. #include "sixlowpan/sixlowpan_internal.h"
  33. #ifdef CONFIG_NET_6LOWPAN
  34. /****************************************************************************
  35. * Pre-processor Definitions
  36. ****************************************************************************/
  37. /* These are temporary stubs. Something like this would be needed to
  38. * monitor the health of a IPv6 neighbor.
  39. */
  40. #define neighbor_reachable(dev)
  41. #define neighbor_notreachable(dev)
  42. /****************************************************************************
  43. * Private Types
  44. ****************************************************************************/
  45. /* This is the state data provided to the send event handler. No actions
  46. * can be taken until the until we receive the TX poll, then we can call
  47. * sixlowpan_queue_frames() with this data strurcture.
  48. */
  49. struct sixlowpan_send_s
  50. {
  51. FAR struct devif_callback_s *s_cb; /* Reference to callback
  52. * instance */
  53. sem_t s_waitsem; /* Supports waiting for
  54. * driver events */
  55. int s_result; /* The result of the transfer */
  56. FAR const struct ipv6_hdr_s *s_ipv6hdr; /* IPv6 header, followed by
  57. * UDP or ICMP header. */
  58. FAR const struct netdev_varaddr_s *s_destmac; /* Destination MAC address */
  59. FAR const void *s_buf; /* Data to send */
  60. size_t s_len; /* Length of data in buf */
  61. };
  62. /****************************************************************************
  63. * Private Functions
  64. ****************************************************************************/
  65. /****************************************************************************
  66. * Name: send_eventhandler
  67. *
  68. * Description:
  69. * This function is called with the network locked to perform the actual
  70. * send operation when polled by the lower, device interfacing layer.
  71. *
  72. * Input Parameters:
  73. * dev - The structure of the network driver that generated the event.
  74. * conn - The connection structure associated with the socket
  75. * flags - Set of events describing why the callback was invoked
  76. *
  77. * Returned Value:
  78. * None
  79. *
  80. * Assumptions:
  81. * The network is locked.
  82. *
  83. ****************************************************************************/
  84. static uint16_t send_eventhandler(FAR struct net_driver_s *dev,
  85. FAR void *pvconn,
  86. FAR void *pvpriv, uint16_t flags)
  87. {
  88. FAR struct sixlowpan_send_s *sinfo = (FAR struct sixlowpan_send_s *)pvpriv;
  89. ninfo("flags: %04x\n", flags);
  90. /* Verify that this is a compatible network driver. */
  91. if (dev->d_lltype != NET_LL_IEEE802154 &&
  92. dev->d_lltype != NET_LL_PKTRADIO)
  93. {
  94. ninfo("Not a compatible network device\n");
  95. return flags;
  96. }
  97. /* REVISIT: Verify that this is the correct IEEE802.15.4 network driver to
  98. * route the outgoing frame(s). Chances are that there is only one
  99. * IEEE802.15.4 network driver
  100. */
  101. /* Check if the IEEE802.15.4 network driver went down */
  102. if ((flags & NETDEV_DOWN) != 0)
  103. {
  104. nwarn("WARNING: Device is down\n");
  105. sinfo->s_result = -ENOTCONN;
  106. goto end_wait;
  107. }
  108. /* Check for a poll for TX data. */
  109. if ((flags & WPAN_NEWDATA) == 0)
  110. {
  111. DEBUGASSERT((flags & WPAN_POLL) != 0);
  112. /* Transfer the frame list to the IEEE802.15.4 MAC device */
  113. sinfo->s_result =
  114. sixlowpan_queue_frames((FAR struct radio_driver_s *)dev,
  115. sinfo->s_ipv6hdr, sinfo->s_buf, sinfo->s_len,
  116. sinfo->s_destmac);
  117. flags &= ~WPAN_POLL;
  118. neighbor_reachable(dev);
  119. goto end_wait;
  120. }
  121. /* Continue waiting */
  122. return flags;
  123. end_wait:
  124. /* Do not allow any further callbacks */
  125. sinfo->s_cb->flags = 0;
  126. sinfo->s_cb->priv = NULL;
  127. sinfo->s_cb->event = NULL;
  128. /* Wake up the waiting thread */
  129. nxsem_post(&sinfo->s_waitsem);
  130. return flags;
  131. }
  132. /****************************************************************************
  133. * Public Functions
  134. ****************************************************************************/
  135. /****************************************************************************
  136. * Name: sixlowpan_send
  137. *
  138. * Description:
  139. * Process an outgoing UDP or ICMPv6 packet. Takes an IP packet and
  140. * formats it to be sent on an 802.15.4 network using 6lowpan. Called
  141. * from common UDP/ICMPv6 send logic.
  142. *
  143. * The payload data is in the caller 'buf' and is of length 'buflen'.
  144. * Compressed headers will be added and if necessary the packet is
  145. * fragmented. The resulting packet/fragments are submitted to the MAC
  146. * via the network driver r_req_data method.
  147. *
  148. * Input Parameters:
  149. * dev - The IEEE802.15.4 MAC network driver interface.
  150. * list - Head of callback list for send events
  151. * ipv6hdr - IPv6 header followed by UDP or ICMPv6 header.
  152. * buf - Data to send
  153. * len - Length of data to send
  154. * destmac - The IEEE802.15.4 MAC address of the destination
  155. * timeout - Send timeout in milliseconds
  156. *
  157. * Returned Value:
  158. * Ok is returned on success; Otherwise a negated errno value is returned.
  159. * This function is expected to fail if the driver is not an IEEE802.15.4
  160. * MAC network driver. In that case, the logic will fall back to normal
  161. * IPv4/IPv6 formatting.
  162. *
  163. * Assumptions:
  164. * Called with the network locked.
  165. *
  166. ****************************************************************************/
  167. int sixlowpan_send(FAR struct net_driver_s *dev,
  168. FAR struct devif_callback_s **list,
  169. FAR const struct ipv6_hdr_s *ipv6hdr, FAR const void *buf,
  170. size_t len, FAR const struct netdev_varaddr_s *destmac,
  171. unsigned int timeout)
  172. {
  173. struct sixlowpan_send_s sinfo;
  174. ninfo("len=%lu timeout=%u\n", (unsigned long)len, timeout);
  175. /* Initialize the send state structure */
  176. nxsem_init(&sinfo.s_waitsem, 0, 0);
  177. nxsem_set_protocol(&sinfo.s_waitsem, SEM_PRIO_NONE);
  178. sinfo.s_result = -EBUSY;
  179. sinfo.s_ipv6hdr = ipv6hdr;
  180. sinfo.s_destmac = destmac;
  181. sinfo.s_buf = buf;
  182. sinfo.s_len = len;
  183. net_lock();
  184. if (len > 0)
  185. {
  186. /* Allocate resources to receive a callback.
  187. *
  188. * The second parameter is NULL meaning that we can get only
  189. * device related events, no connect-related events.
  190. */
  191. sinfo.s_cb = devif_callback_alloc(dev, list);
  192. if (sinfo.s_cb != NULL)
  193. {
  194. int ret;
  195. /* Set up the callback in the connection */
  196. sinfo.s_cb->flags = (NETDEV_DOWN | WPAN_POLL);
  197. sinfo.s_cb->priv = (FAR void *)&sinfo;
  198. sinfo.s_cb->event = send_eventhandler;
  199. /* Notify the IEEE802.15.4 MAC that we have data to send. */
  200. netdev_txnotify_dev(dev);
  201. /* Wait for the send to complete or an error to occur.
  202. * net_timedwait will also terminate if a signal is received.
  203. */
  204. ninfo("Wait for send complete\n");
  205. ret = net_timedwait(&sinfo.s_waitsem, timeout);
  206. if (ret < 0)
  207. {
  208. if (ret == -ETIMEDOUT)
  209. {
  210. neighbor_notreachable(dev);
  211. }
  212. sinfo.s_result = ret;
  213. }
  214. /* Make sure that no further events are processed */
  215. devif_conn_callback_free(dev, sinfo.s_cb, list);
  216. }
  217. }
  218. nxsem_destroy(&sinfo.s_waitsem);
  219. net_unlock();
  220. return (sinfo.s_result < 0 ? sinfo.s_result : len);
  221. }
  222. #endif /* CONFIG_NET_6LOWPAN */