123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278 |
- /****************************************************************************
- * net/sixlowpan/sixlowpan_send.c
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership. The
- * ASF licenses this file to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance with the
- * License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations
- * under the License.
- *
- ****************************************************************************/
- /****************************************************************************
- * Included Files
- ****************************************************************************/
- #include <nuttx/config.h>
- #include <assert.h>
- #include <errno.h>
- #include <debug.h>
- #include <nuttx/semaphore.h>
- #include <nuttx/net/net.h>
- #include <nuttx/net/radiodev.h>
- #include "netdev/netdev.h"
- #include "devif/devif.h"
- #include "sixlowpan/sixlowpan_internal.h"
- #ifdef CONFIG_NET_6LOWPAN
- /****************************************************************************
- * Pre-processor Definitions
- ****************************************************************************/
- /* These are temporary stubs. Something like this would be needed to
- * monitor the health of a IPv6 neighbor.
- */
- #define neighbor_reachable(dev)
- #define neighbor_notreachable(dev)
- /****************************************************************************
- * Private Types
- ****************************************************************************/
- /* This is the state data provided to the send event handler. No actions
- * can be taken until the until we receive the TX poll, then we can call
- * sixlowpan_queue_frames() with this data strurcture.
- */
- struct sixlowpan_send_s
- {
- FAR struct devif_callback_s *s_cb; /* Reference to callback
- * instance */
- sem_t s_waitsem; /* Supports waiting for
- * driver events */
- int s_result; /* The result of the transfer */
- FAR const struct ipv6_hdr_s *s_ipv6hdr; /* IPv6 header, followed by
- * UDP or ICMP header. */
- FAR const struct netdev_varaddr_s *s_destmac; /* Destination MAC address */
- FAR const void *s_buf; /* Data to send */
- size_t s_len; /* Length of data in buf */
- };
- /****************************************************************************
- * Private Functions
- ****************************************************************************/
- /****************************************************************************
- * Name: send_eventhandler
- *
- * Description:
- * This function is called with the network locked to perform the actual
- * send operation when polled by the lower, device interfacing layer.
- *
- * Input Parameters:
- * dev - The structure of the network driver that generated the event.
- * conn - The connection structure associated with the socket
- * flags - Set of events describing why the callback was invoked
- *
- * Returned Value:
- * None
- *
- * Assumptions:
- * The network is locked.
- *
- ****************************************************************************/
- static uint16_t send_eventhandler(FAR struct net_driver_s *dev,
- FAR void *pvconn,
- FAR void *pvpriv, uint16_t flags)
- {
- FAR struct sixlowpan_send_s *sinfo = (FAR struct sixlowpan_send_s *)pvpriv;
- ninfo("flags: %04x\n", flags);
- /* Verify that this is a compatible network driver. */
- if (dev->d_lltype != NET_LL_IEEE802154 &&
- dev->d_lltype != NET_LL_PKTRADIO)
- {
- ninfo("Not a compatible network device\n");
- return flags;
- }
- /* REVISIT: Verify that this is the correct IEEE802.15.4 network driver to
- * route the outgoing frame(s). Chances are that there is only one
- * IEEE802.15.4 network driver
- */
- /* Check if the IEEE802.15.4 network driver went down */
- if ((flags & NETDEV_DOWN) != 0)
- {
- nwarn("WARNING: Device is down\n");
- sinfo->s_result = -ENOTCONN;
- goto end_wait;
- }
- /* Check for a poll for TX data. */
- if ((flags & WPAN_NEWDATA) == 0)
- {
- DEBUGASSERT((flags & WPAN_POLL) != 0);
- /* Transfer the frame list to the IEEE802.15.4 MAC device */
- sinfo->s_result =
- sixlowpan_queue_frames((FAR struct radio_driver_s *)dev,
- sinfo->s_ipv6hdr, sinfo->s_buf, sinfo->s_len,
- sinfo->s_destmac);
- flags &= ~WPAN_POLL;
- neighbor_reachable(dev);
- goto end_wait;
- }
- /* Continue waiting */
- return flags;
- end_wait:
- /* Do not allow any further callbacks */
- sinfo->s_cb->flags = 0;
- sinfo->s_cb->priv = NULL;
- sinfo->s_cb->event = NULL;
- /* Wake up the waiting thread */
- nxsem_post(&sinfo->s_waitsem);
- return flags;
- }
- /****************************************************************************
- * Public Functions
- ****************************************************************************/
- /****************************************************************************
- * Name: sixlowpan_send
- *
- * Description:
- * Process an outgoing UDP or ICMPv6 packet. Takes an IP packet and
- * formats it to be sent on an 802.15.4 network using 6lowpan. Called
- * from common UDP/ICMPv6 send logic.
- *
- * The payload data is in the caller 'buf' and is of length 'buflen'.
- * Compressed headers will be added and if necessary the packet is
- * fragmented. The resulting packet/fragments are submitted to the MAC
- * via the network driver r_req_data method.
- *
- * Input Parameters:
- * dev - The IEEE802.15.4 MAC network driver interface.
- * list - Head of callback list for send events
- * ipv6hdr - IPv6 header followed by UDP or ICMPv6 header.
- * buf - Data to send
- * len - Length of data to send
- * destmac - The IEEE802.15.4 MAC address of the destination
- * timeout - Send timeout in milliseconds
- *
- * Returned Value:
- * Ok is returned on success; Otherwise a negated errno value is returned.
- * This function is expected to fail if the driver is not an IEEE802.15.4
- * MAC network driver. In that case, the logic will fall back to normal
- * IPv4/IPv6 formatting.
- *
- * Assumptions:
- * Called with the network locked.
- *
- ****************************************************************************/
- int sixlowpan_send(FAR struct net_driver_s *dev,
- FAR struct devif_callback_s **list,
- FAR const struct ipv6_hdr_s *ipv6hdr, FAR const void *buf,
- size_t len, FAR const struct netdev_varaddr_s *destmac,
- unsigned int timeout)
- {
- struct sixlowpan_send_s sinfo;
- ninfo("len=%lu timeout=%u\n", (unsigned long)len, timeout);
- /* Initialize the send state structure */
- nxsem_init(&sinfo.s_waitsem, 0, 0);
- nxsem_set_protocol(&sinfo.s_waitsem, SEM_PRIO_NONE);
- sinfo.s_result = -EBUSY;
- sinfo.s_ipv6hdr = ipv6hdr;
- sinfo.s_destmac = destmac;
- sinfo.s_buf = buf;
- sinfo.s_len = len;
- net_lock();
- if (len > 0)
- {
- /* Allocate resources to receive a callback.
- *
- * The second parameter is NULL meaning that we can get only
- * device related events, no connect-related events.
- */
- sinfo.s_cb = devif_callback_alloc(dev, list);
- if (sinfo.s_cb != NULL)
- {
- int ret;
- /* Set up the callback in the connection */
- sinfo.s_cb->flags = (NETDEV_DOWN | WPAN_POLL);
- sinfo.s_cb->priv = (FAR void *)&sinfo;
- sinfo.s_cb->event = send_eventhandler;
- /* Notify the IEEE802.15.4 MAC that we have data to send. */
- netdev_txnotify_dev(dev);
- /* Wait for the send to complete or an error to occur.
- * net_timedwait will also terminate if a signal is received.
- */
- ninfo("Wait for send complete\n");
- ret = net_timedwait(&sinfo.s_waitsem, timeout);
- if (ret < 0)
- {
- if (ret == -ETIMEDOUT)
- {
- neighbor_notreachable(dev);
- }
- sinfo.s_result = ret;
- }
- /* Make sure that no further events are processed */
- devif_conn_callback_free(dev, sinfo.s_cb, list);
- }
- }
- nxsem_destroy(&sinfo.s_waitsem);
- net_unlock();
- return (sinfo.s_result < 0 ? sinfo.s_result : len);
- }
- #endif /* CONFIG_NET_6LOWPAN */
|