nuttx/net/sixlowpan/sixlowpan_framelist.c
Gregory Nutt 1e24404dcc Squashed commit of the following:
commit f97da3a546f9d6e1b858cfc45538a06b62396034
Author: Gregory Nutt <gnutt@nuttx.org>
Date:   Sun Jul 30 19:09:46 2017 -0600

    Network: Condition out some types that depend on definitions that are only available with 6LoWPAN is enabled.

commit 312e9dc1195527100e12bf6be8b629f5b29be1f6
Author: Gregory Nutt <gnutt@nuttx.org>
Date:   Sun Jul 30 18:57:23 2017 -0600

    6LoWPAN: Fix case where source and destination IP address were backward.  Fix some compile issues when star topology support is enabled.

commit 3b0e71c5807194fbb006d0560bb2c98133055ba3
Author: Gregory Nutt <gnutt@nuttx.org>
Date:   Sun Jul 30 16:01:48 2017 -0600

    6LoWPAN PktRadio:  Finishes up all logic; Lots of misc changes from build testing.

commit cc118f8cb335e1c48354fd7112e20be57de50b68
Author: Gregory Nutt <gnutt@nuttx.org>
Date:   Sun Jul 30 12:41:18 2017 -0600

    6LoWPAN: Remove explicate type struct ieee802154_frame_meta_s from derive interface methods.  Replace with a opaque void * type so that other radio meta data structures may use the interfaces.  Add a new radion interface to get properties of the radio.  Spirit:  Finish packet I/O interface with the network.

commit 1aa0a63e8341ca5f9f88c294f96d1740459146d4
Author: Gregory Nutt <gnutt@nuttx.org>
Date:   Sun Jul 30 07:57:15 2017 -0600

    6LoWPAN: Replace metadata input parameter type from struct ieee802154_data_ind_s to void*.  This permits radios with different MAC metadata to interact with 6LoWPAN.  Includes many changes to handle variable length radio addresses.  No longer just short and exteneded; any length.

commit 46266ace61ae6246123873935436d864c7de31e0
Author: Gregory Nutt <gnutt@nuttx.org>
Date:   Sat Jul 29 17:50:42 2017 -0600

    Spirit: Fix typos in SPI debug code.

commit 27c6b235f6a2d3b2f08da4920b224a40e9991f59
Merge: 7029dffd02 7f53e08917
Author: Gregory Nutt <gnutt@nuttx.org>
Date:   Sat Jul 29 13:43:02 2017 -0600

    Merge remote-tracking branch 'origin/master' into spirit

commit 7029dffd02156bcbfa84262671c2ca766a117191
Author: Gregory Nutt <gnutt@nuttx.org>
Date:   Sat Jul 29 12:02:13 2017 -0600

    6LoWPAN PktRadio: Add missing MetaData-related prototypes and initialization logic.  Perform a major renaming to make room in the 6LoWPAN name space for packet radios.

commit e2012f7c1df14155c0bfd45d7f1cb3f71b259f48
Author: Gregory Nutt <gnutt@nuttx.org>
Date:   Sat Jul 29 10:16:23 2017 -0600

    6LoWPAN PktRadio:  Some initial changes to support raw packet radios without IEEE 802.15.4 with 6LoWPAN.

commit c6dbf9178539b7da75e492ffd1d1f93c9c326299
Merge: da782d6cdf 5889ce65f5
Author: Gregory Nutt <gnutt@nuttx.org>
Date:   Sat Jul 29 07:30:08 2017 -0600

    Merge remote-tracking branch 'origin/master' into spirit

commit da782d6cdff5980d71aaa2da5f9c28ab3438d085
Author: Gregory Nutt <gnutt@nuttx.org>
Date:   Sat Jul 29 07:26:48 2017 -0600

    Spirit:  Completes port of the spirit radio library to NuttX.

commit 63f3595c47dca13952d28b518c7f0a8d6ae9037a
Author: Gregory Nutt <gnutt@nuttx.org>
Date:   Fri Jul 28 17:42:51 2017 -0600

    Spirit:  Bring in a couple ore more radio interface functions.

commit 692a27da396b7683749790923d8fa085091764f1
Merge: 27c0a6ec08 38f79543dc
Author: Gregory Nutt <gnutt@nuttx.org>
Date:   Fri Jul 28 15:49:37 2017 -0600

    Merge remote-tracking branch 'origin/master' into spirit

commit 27c0a6ec0813187f125922c81189a70cf04d83d4
Author: Gregory Nutt <gnutt@nuttx.org>
Date:   Fri Jul 28 15:47:27 2017 -0600

    Spirit:  Bring in a couple ore more radio interface functions.

commit 96657af2831487724723a60084831619257fd953
Author: Gregory Nutt <gnutt@nuttx.org>
Date:   Fri Jul 28 14:20:14 2017 -0600

    Spirit:  Bring in more radio interface functions.

commit 640d55399b54a019be68825668fca1446abd082f
Merge: 3fcf84a9a2 47791442a0
Author: Gregory Nutt <gnutt@nuttx.org>
Date:   Fri Jul 28 12:01:43 2017 -0600

    Merge remote-tracking branch 'origin/master' into spirit

commit 3fcf84a9a2673e1e1466ce5b114d7b73c257e515
Author: Gregory Nutt <gnutt@nuttx.org>
Date:   Fri Jul 28 12:00:31 2017 -0600

    Spirit: Brings in the last of the PktCommon interfaces.

commit d26ebd901ba4ba84910e99b4e728b98c30fa4c0b
Author: Gregory Nutt <gnutt@nuttx.org>
Date:   Fri Jul 28 09:54:52 2017 -0600

    Spirit: Add a few more PktCommon interfaces.

commit b5cb8041d50233a4abb8fb4d1dcef5428ae2c2b2
Author: Gregory Nutt <gnutt@nuttx.org>
Date:   Fri Jul 28 09:33:31 2017 -0600

    libc/termios:  Remember block comments before empty file sections.

commit 0fcab2c1c8c74442d40bd5e8c6af50a34f8a5821
Author: Sebastien Lorquet <sebastien@lorquet.fr>
Date:   Fri Jul 28 09:31:00 2017 -0600

    tcdrain implementation based on a new term ioctl

commit 797d4adf7d41068c671f0217d369b797b269de1a
Author: Stefan Kolb <Stefan.Kolb@avat.de>
Date:   Fri Jul 28 09:19:04 2017 -0600

    We discovered a problem with the samv7 mcan driver which results, under some circumstances, in a very high CPU load.

    The problem occurs, and is easily reproducible, if the device is connected to a CAN network with a wrongly configured CAN speed (baud rate). In our tests we set the CAN speed of the device to 1000000 and the speed of the other CAN nodes to 500000. The device is restarted and sends a CANopen “bootup message” to the CAN network. This results in huge amount of errors messages on the CAN bus, probably because of the CAN feature for acknowledging error messages. The error messages can’t be read by the device because of the misconfigured CAN speed, instead the CAN chip reports lots of errors, which are reported to the application which uses the CAN driver (CONFIG_CAN_ERRORS is enabled).

    The CAN errors are reported from the CAN chip via interrupts and thus the interrupt load is very high in this scenario. To fix the problem the driver now disables each RX error interrupt after it is occurred. The RX error interrupts are turned back on if at least one CAN message is received successfully.

commit e298f48e96d9e34017dcab8e4d87032862ae9322
Author: Gregory Nutt <gnutt@nuttx.org>
Date:   Fri Jul 28 09:06:26 2017 -0600

    Spirit:  Bring in PktStack interfaces.

commit 4a0f00a7058312dcf6ac392689b9f69112f613ec
Merge: 855cf97130 b458934ac4
Author: Gregory Nutt <gnutt@nuttx.org>
Date:   Thu Jul 27 18:05:02 2017 -0600

    Merge remote-tracking branch 'origin/master' into spirit

commit 855cf9713052a851a1daeb3842db2edd6ff6f658
Author: Gregory Nutt <gnutt@nuttx.org>
Date:   Thu Jul 27 18:03:56 2017 -0600

    Spirit Network Driver:  Add some hooks that will eventually support address filtering.

commit 3b3fb24ea86cf8233b034871d5c550f47ab852e6
Author: Gregory Nutt <gnutt@nuttx.org>
Date:   Thu Jul 27 17:13:21 2017 -0600

    Spirit: Add a PktStack header file.

commit 705e8fff6a21264ab751fb34c107cb109430ac89
Author: Gregory Nutt <gnutt@nuttx.org>
Date:   Thu Jul 27 15:00:03 2017 -0600

    Spirit:  Bring in last of timer interfaces.

commit f8984b2f82e165f5bba132d6b099222d1beb1fbd
Merge: cb79778a30 f287cc25d6
Author: Gregory Nutt <gnutt@nuttx.org>
Date:   Thu Jul 27 11:57:01 2017 -0600

    Merge remote-tracking branch 'origin/master' into spirit

commit cb79778a3044ae97a1cc615dfa24099144f04bd0
Author: Gregory Nutt <gnutt@nuttx.org>
Date:   Thu Jul 27 11:46:31 2017 -0600

    Spirit:  Bring in last of QI interfaces.

commit 0245b330a33aa73531b82ae261b1312be9922e0f
Author: Gregory Nutt <gnutt@nuttx.org>
Date:   Thu Jul 27 10:14:34 2017 -0600

    Spirit:  Add general interfaces.

commit 121845a8f229ec2c88e5721da5512135f6624ee5
Author: Gregory Nutt <gnutt@nuttx.org>
Date:   Thu Jul 27 09:41:23 2017 -0600

    Spirit:  Bring in last of GPIO interfaces.

commit 279bfcc92bcd0cfa48c0ed7862fa2b75fbee99b8
Author: Gregory Nutt <gnutt@nuttx.org>
Date:   Wed Jul 26 17:09:19 2017 -0600

    Spirit: Add some missing configuration options: Add register -level debug options.

commit 4be89324a5908e35afc70373c279f4d05f62b48f
Merge: 66e87f9bb3 598386ef90
Author: Gregory Nutt <gnutt@nuttx.org>
Date:   Wed Jul 26 15:36:20 2017 -0600

    Merge remote-tracking branch 'origin/master' into spirit

commit 66e87f9bb3ef75fddf25400bc08475c5e6ad4c30
Author: Gregory Nutt <gnutt@nuttx.org>
Date:   Wed Jul 26 15:19:56 2017 -0600

    Spirit:  Brings in last of PktBasic logic.

commit 8b4c89d6a103003fa04363e2c2ae7b9ee390bf49
Author: Gregory Nutt <gnutt@nuttx.org>
Date:   Wed Jul 26 11:55:50 2017 -0600

    Spirit:  Bring in AES and MBUS logic.

commit d00022d39ab0ce839de29386949481e5c24feff3
Author: Gregory Nutt <gnutt@nuttx.org>
Date:   Wed Jul 26 09:22:03 2017 -0600

    Spirit:  Bring in remainder of calibration interfaces.

commit 40b4b2f902e04293f8940551a97a9a24a48988dd
Author: Gregory Nutt <gnutt@nuttx.org>
Date:   Wed Jul 26 08:44:32 2017 -0600

    Spirit:  Bring in DirectRF interfaces.

commit 7c109608e1a2989f3edbc2fd939a2d225fff382a
Author: Gregory Nutt <gnutt@nuttx.org>
Date:   Wed Jul 26 07:46:19 2017 -0600

    Spirit: Add CSMA support.

commit 0f88896595d162c4ac6138e7b1af2fc35c865b3d
Author: Gregory Nutt <gnutt@nuttx.org>
Date:   Tue Jul 25 18:57:43 2017 -0600

    Spirit:  Add some initial TX logic to network driver.

commit 4dc7058dfcdcf40980578680b7e1a4206dea4ea2
Author: Gregory Nutt <gnutt@nuttx.org>
Date:   Tue Jul 25 17:02:11 2017 -0600

    Spirit: Completes ports of spirit_management.* files

commit c904eef51d929e041b87d0c8aff6fa3c2f895341
Merge: 91e985a877 c9ff8cbab9
Author: Gregory Nutt <gnutt@nuttx.org>
Date:   Tue Jul 25 15:15:04 2017 -0600

    Merge remote-tracking branch 'origin/master' into spirit

commit 91e985a87729017a66d19276c4d47681064f95ea
Author: Gregory Nutt <gnutt@nuttx.org>
Date:   Tue Jul 25 15:13:54 2017 -0600

    Spirit:  Add a few more functions that will soon be needed for packet transmission.

commit b5981d29983907c2194fbc26af4b72ad532bee78
Author: Gregory Nutt <gnutt@nuttx.org>
Date:   Tue Jul 25 13:30:07 2017 -0600

    Spirit:  Finish off some initialization issues; Started some interrupt handling logic.

commit c21073e0bc2870b3d9ba40bdfdfd5151ce4f5890
Author: Gregory Nutt <gnutt@nuttx.org>
Date:   Tue Jul 25 09:35:52 2017 -0600

    Spirit:  Completes very basic radio initialization for network driver

commit 1b544334361c54f46bcf0ba313c125932e8dafc6
Author: Gregory Nutt <gnutt@nuttx.org>
Date:   Tue Jul 25 07:58:30 2017 -0600

    Spirit: Add more radio initialization logic... getting closer.

commit 45d1047db60843c57d394ec910c63e7c127671e0
Author: Gregory Nutt <gnutt@nuttx.org>
Date:   Mon Jul 24 19:15:33 2017 -0600

    Spirit: add some CSMA initialization logic

commit bcf55c71336d48947fe19bb09a799169852301c2
Merge: 89e9d426e9 2fc0fbcf7e
Author: Gregory Nutt <gnutt@nuttx.org>
Date:   Mon Jul 24 16:47:11 2017 -0600

    Merge remote-tracking branch 'origin/master' into spirit

commit 89e9d426e91c056e659fccf5e5c4392618f8f777
Author: Gregory Nutt <gnutt@nuttx.org>
Date:   Mon Jul 24 16:44:19 2017 -0600

    Update some comments

commit 9c5d8a5833350006ed389e898b11c8c8a20e5f4f
Author: Gregory Nutt <gnutt@nuttx.org>
Date:   Mon Jul 24 16:15:54 2017 -0600

    Spirit:  Rename drivers/wireless/spirit/src to lib.  Move Spirit network driver out of IEEE802.15.4 into drivers/wireless/spirit/drivers

commit cabc0ec9e6eb558dcb715ab17264383aa0105e7a
Merge: 87b616414a 6bd744c4b3
Author: Gregory Nutt <gnutt@nuttx.org>
Date:   Mon Jul 24 15:38:40 2017 -0600

    Merge remote-tracking branch 'origin/master' into spirit

commit 87b616414a79c01a71acea78f8258e05325c1996
Author: Gregory Nutt <gnutt@nuttx.org>
Date:   Mon Jul 24 15:37:27 2017 -0600

    Spirit radio driver is mutating into a standalone network driver.

commit 507798233868a661ae8adad3e3aa117075a7a146
Author: Gregory Nutt <gnutt@nuttx.org>
Date:   Mon Jul 24 13:32:08 2017 -0600

    Spirit: More radio initialization logic

commit 33af25704ce9ca83d576300d153cfe31cc6d2576
Author: Gregory Nutt <gnutt@nuttx.org>
Date:   Mon Jul 24 12:19:14 2017 -0600

    Spirit:  Beginning of radio initialization logic

commit 97b20014c016e55952a8f9d8f4ae29e2cc555b23
Author: Gregory Nutt <gnutt@nuttx.org>
Date:   Mon Jul 24 09:42:06 2017 -0600

    Spirit: More initialization logic.

commit 295d8e27824c0417fccea2344b30bb5c93ffbabe
Author: Gregory Nutt <gnutt@nuttx.org>
Date:   Sun Jul 23 15:39:53 2017 -0600

    Spirit:  Add header file containing enumeration of commands.

commit 8a2d9dd8eb9cc70cbcdd1b913fc9022b9c9ec8da
Author: Gregory Nutt <gnutt@nuttx.org>
Date:   Sun Jul 23 11:33:50 2017 -0600

    Spirit:  Add GPIO initialization logic

commit 8b6d80c44f92024c45a6ba63ba1af3fdafe94dc3
Author: Gregory Nutt <gnutt@nuttx.org>
Date:   Sun Jul 23 10:07:25 2017 -0600

    Spirit:  Add interrupt control logic.

commit 423f846fe5c914f92a4bfea4d9d1fa33de1c77a5
Author: Gregory Nutt <gnutt@nuttx.org>
Date:   Sat Jul 22 19:06:52 2017 -0600

    Spirit: Yet a little more radio initialization logic.

commit 5895b979823e51ddde5ad52e6de66a8ad662e883
Author: Gregory Nutt <gnutt@nuttx.org>
Date:   Sat Jul 22 15:36:05 2017 -0600

    Spirit: A little more radio initialization logic.

commit 86311ab30aad386203c181c792847dd1d37f9a02
Author: Gregory Nutt <gnutt@nuttx.org>
Date:   Sat Jul 22 13:02:32 2017 -0600

    Spirit: A miniscule amount of radio initialization logic.

commit ad55e89d5ee12ea1eeea95fcd38ff3da0db4416a
Merge: 90a7666655 f4e46b0da7
Author: Gregory Nutt <gnutt@nuttx.org>
Date:   Sat Jul 22 10:56:30 2017 -0600

    Merge remote-tracking branch 'origin/master' into spirit

commit 90a766665534b05da0157dbc383cb06a98c86a79
Author: Gregory Nutt <gnutt@nuttx.org>
Date:   Sat Jul 22 10:52:52 2017 -0600

    Spirit1:  A few fixes for a clean build of initial configuration (not much there yet)

commit bbbf04c223230a52a7705a2161128265cfbaa480
Merge: 623d54a7f7 2319ea53a9
Author: Gregory Nutt <gnutt@nuttx.org>
Date:   Sat Jul 22 09:53:57 2017 -0600

    Merge remote-tracking branch 'origin/master' into spirit

commit 623d54a7f719e9032099f88f38203efee4b80722
Author: Gregory Nutt <gnutt@nuttx.org>
Date:   Sat Jul 22 09:43:52 2017 -0600

    b-l475e-iot01a: Add a configuration for testing sprit radio.

commit d309d73d9f4665f9d870eb03531f450043d9389d
Merge: 52c3ddfae6 d88dc9b2e5
Author: Gregory Nutt <gnutt@nuttx.org>
Date:   Sat Jul 22 09:02:06 2017 -0600

    Merge remote-tracking branch 'origin/master' into spirit

commit 52c3ddfae6802e111c2b5cf1207baf21a61dd00b
Author: Gregory Nutt <gnutt@nuttx.org>
Date:   Sat Jul 22 08:33:04 2017 -0600

    Spirit:  Add register definition header file.

commit 8d842ab5e8f9ca653b42f9ee88dc279f06b4fa98
Author: Gregory Nutt <gnutt@nuttx.org>
Date:   Fri Jul 21 17:27:03 2017 -0600

    b-l475e-iot01a: Add initial, unverified support for the SPSRGF/Spirit1 module.

commit 73d902a1048616fb9c2dd2147cabcd8ee78e19ac
Author: Gregory Nutt <gnutt@nuttx.org>
Date:   Fri Jul 21 15:49:43 2017 -0600

    Spirit: Fixes to get skeleton IEEE 802.15.4 driver build.

commit ebc5a8387bb94f0cc3827533795f3e4a33207e67
Author: Gregory Nutt <gnutt@nuttx.org>
Date:   Fri Jul 21 15:16:29 2017 -0600

    Spirit1:  Add framework for IEEE 802.15.4 driver.  Does not yet build.

commit 52e195a7ae14ddb18bdd56258f4877381d2501ca
Author: Gregory Nutt <gnutt@nuttx.org>
Date:   Fri Jul 21 14:02:42 2017 -0600

    Spirit:  A little more SPI logic.

commit 90048d0c5b8a5af4d81a15d99535c84ed38d8ae9
Author: Gregory Nutt <gnutt@nuttx.org>
Date:   Fri Jul 21 11:19:06 2017 -0600

    Spirit: Build directories setup.  Some initial files added, mostly just to verify build.

commit 8273a381ac1f6bb081b292b5e73226185e9e634c
Author: Gregory Nutt <gnutt@nuttx.org>
Date:   Fri Jul 21 08:34:04 2017 -0600

    USB composite:  Remove references to CDC/ACM and USB MSC from composite logic.  They are no longer coupled.
2017-07-30 19:11:23 -06:00

747 lines
24 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/****************************************************************************
* net/sixlowpan/sixlowpan_framelist.c
*
* Copyright (C) 2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Parts of this file derive from Contiki:
*
* Copyright (c) 2008, Swedish Institute of Computer Science.
* All rights reserved.
* Authors: Adam Dunkels <adam@sics.se>
* Nicolas Tsiftes <nvt@sics.se>
* Niclas Finne <nfi@sics.se>
* Mathilde Durvy <mdurvy@cisco.com>
* Julien Abeille <jabeille@cisco.com>
* Joakim Eriksson <joakime@sics.se>
* Joel Hoglund <joel@sics.se>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <string.h>
#include <assert.h>
#include <errno.h>
#include <debug.h>
#include <nuttx/net/netdev.h>
#include <nuttx/wireless/ieee802154/ieee802154_mac.h>
#include "sixlowpan/sixlowpan_internal.h"
#ifdef CONFIG_NET_6LOWPAN
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Configuration ************************************************************/
/* A single IOB must be big enough to hold a full frame */
#if CONFIG_IOB_BUFSIZE < CONFIG_NET_6LOWPAN_FRAMELEN
# error IOBs must be large enough to hold full IEEE802.14.5 frame
#endif
/* A IOB must also be big enought to hold the maximum MAC header (25 bytes?)
* plus the FCS and have some amount of space left for the payload.
*/
#if CONFIG_NET_6LOWPAN_FRAMELEN < (SIXLOWPAN_MAC_FCSSIZE + 25)
# error CONFIG_NET_6LOWPAN_FRAMELEN too small to hold a IEEE802.14.5 frame
#endif
/* We must reserve space at the end of the frame for a 2-byte FCS */
#define SIXLOWPAN_FRAMELEN (CONFIG_NET_6LOWPAN_FRAMELEN - SIXLOWPAN_MAC_FCSSIZE)
/* There must be at least enough IOBs to hold the full MTU. Probably still
* won't work unless there are a few more.
*/
#if CONFIG_NET_6LOWPAN_MTU > (CONFIG_IOB_BUFSIZE * CONFIG_IOB_NBUFFERS)
# error Not enough IOBs to hold one full 6LoWPAN packet
#endif
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: sixlowpan_compress_ipv6hdr
*
* Description:
* IPv6 dispatch "compression" function. Packets "Compression" when only
* IPv6 dispatch is used
*
* There is no compression in this case, all fields are sent
* inline. We just add the IPv6 dispatch byte before the packet.
*
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | IPv6 Dsp | IPv6 header and payload ...
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*
* Input Parameters:
* ipv6hdr - Pointer to the IPv6 header to "compress"
* fptr - Pointer to the beginning of the frame under construction
*
* Returned Value:
* None
*
****************************************************************************/
static int sixlowpan_compress_ipv6hdr(FAR const struct ipv6_hdr_s *ipv6hdr,
FAR uint8_t *fptr)
{
/* Indicate the IPv6 dispatch and length */
fptr[g_frame_hdrlen] = SIXLOWPAN_DISPATCH_IPV6;
g_frame_hdrlen += SIXLOWPAN_IPV6_HDR_LEN;
/* Copy the IPv6 header and adjust pointers */
memcpy(&fptr[g_frame_hdrlen], ipv6hdr, IPv6_HDRLEN);
g_frame_hdrlen += IPv6_HDRLEN;
g_uncomp_hdrlen += IPv6_HDRLEN;
return COMPRESS_HDR_INLINE;
}
/****************************************************************************
* Name: sixlowpan_protosize
*
* Description:
* Get the size of any uncompresssed protocol header that follows the
* IPv6 header.
*
****************************************************************************/
static uint16_t sixlowpan_protosize(FAR const struct ipv6_hdr_s *ipv6hdr,
FAR uint8_t *fptr)
{
uint16_t protosize;
/* Copy the following protocol header, */
switch (ipv6hdr->proto)
{
#ifdef CONFIG_NET_TCP
case IP_PROTO_TCP:
{
FAR struct tcp_hdr_s *tcp =
&((FAR struct ipv6tcp_hdr_s *)ipv6hdr)->tcp;
/* The TCP header length is encoded in the top 4 bits of the
* tcpoffset field (in units of 32-bit words).
*/
protosize = ((uint16_t)tcp->tcpoffset >> 4) << 2;
}
break;
#endif
#ifdef CONFIG_NET_UDP
case IP_PROTO_UDP:
protosize = UDP_HDRLEN;
break;
#endif
#ifdef CONFIG_NET_ICMPv6
case IP_PROTO_ICMP6:
protosize = ICMPv6_HDRLEN;
break;
#endif
default:
nwarn("WARNING: Unrecognized proto: %u\n", ipv6hdr->proto);
protosize = 0;
break;
}
return protosize;
}
/****************************************************************************
* Name: sixlowpan_ieee802154_metadata
*
* Description:
* Create the meta data that describes the IEEE 802.15.4 MAC header.
*
* Input Parameters:
* radio - The radio network driver instance
* destmac - The IEEE802.15.4 MAC address of the destination
* meta - Location to return the final metadata.
*
* Returned value
* OK is returned on success; Othewise a negated errno value is returned.
*
****************************************************************************/
#ifdef CONFIG_WIRELESS_IEEE802154
static int sixlowpan_ieee802154_metadata(FAR struct sixlowpan_driver_s *radio,
FAR const struct netdev_varaddr_s *destmac,
FAR union sixlowpan_metadata_u *meta)
{
struct ieee802_txmetadata_s pktmeta;
int ret;
/* Reset frame meta data */
memset(&pktmeta, 0, sizeof(struct ieee802_txmetadata_s));
pktmeta.xmits = CONFIG_NET_6LOWPAN_MAX_MACTRANSMITS;
/* Set stream mode for all TCP packets, except FIN packets. */
#if 0 /* Currently the frame type is always data */
if (ipv6->proto == IP_PROTO_TCP)
{
FAR const struct tcp_hdr_s *tcp =
&((FAR const struct ipv6tcp_hdr_s *)ipv6)->tcp;
if ((tcp->flags & TCP_FIN) == 0 &&
(tcp->flags & TCP_CTL) != TCP_ACK)
{
pktmeta.type = FRAME_ATTR_TYPE_STREAM;
}
else if ((tcp->flags & TCP_FIN) == TCP_FIN)
{
pktmeta.type = FRAME_ATTR_TYPE_STREAM_END;
}
}
#endif
/* Set the source and destination address. The source MAC address
* is a fixed size, determined by a configuration setting. The
* destination MAC address many be either short or extended.
*/
#ifdef CONFIG_NET_6LOWPAN_EXTENDEDADDR
pktmeta.sextended = TRUE;
sixlowpan_eaddrcopy(pktmeta.source.nm_addr,
&radio->r_dev.d_mac.sixlowpan.nv_addr);
#else
sixlowpan_saddrcopy(pktmeta.source.nm_addr,
&radio->r_dev.d_mac.sixlowpan.nv_addr);
#endif
/* Copy the destination node address into the meta data */
if (destmac->nv_addrlen == NET_6LOWPAN_EADDRSIZE)
{
pktmeta.dextended = TRUE;
sixlowpan_eaddrcopy(pktmeta.dest.nm_addr, destmac->nv_addr);
}
else
{
DEBUGASSERT(destmac->nv_addrlen == NET_6LOWPAN_SADDRSIZE);
sixlowpan_saddrcopy(pktmeta.dest.nm_addr, destmac->nv_addr);
}
/* Get the destination PAN ID.
*
* REVISIT: For now I am assuming that the source and destination
* PAN IDs are the same.
*/
(void)sixlowpan_src_panid(radio, pktmeta.dpanid);
/* Based on the collected attributes and addresses, construct the MAC meta
* data structure that we need to interface with the IEEE802.15.4 MAC (we
* will update the MSDU payload size when the IOB has been setup).
*/
ret = sixlowpan_meta_data(radio, &pktmeta, &meta->ieee802154, 0);
if (ret < 0)
{
nerr("ERROR: sixlowpan_meta_data() failed: %d\n", ret);
}
return ret;
}
#endif
/****************************************************************************
* Name: sixlowpan_pktradio_metadata
*
* Description:
* Create the meta data that describes the MAC header for a generic radio.
*
* Input Parameters:
* radio - The radio network driver instance
* destmac - The radio-specific MAC address of the destination
* meta - Location to return the final metadata.
*
* Returned value
* OK is returned on success; Othewise a negated errno value is returned.
*
****************************************************************************/
#ifdef CONFIG_WIRELESS_PKTRADIO
static int sixlowpan_pktradio_metadata(FAR struct sixlowpan_driver_s *radio,
FAR const struct netdev_varaddr_s *destmac,
FAR union sixlowpan_metadata_u *meta)
{
FAR struct pktradio_metadata_s *pktmeta = &meta->pktradio;
/* Reset the meta data */
memset(&pktmeta, 0, sizeof(struct pktradio_metadata_s));
/* Set the source address */
pktmeta->pm_src.pa_addrlen = radio->r_dev.d_mac.sixlowpan.nv_addrlen;
memcpy(pktmeta->pm_src.pa_addr,
radio->r_dev.d_mac.sixlowpan.nv_addr,
radio->r_dev.d_mac.sixlowpan.nv_addrlen);
/* Set the destination address */
pktmeta->pm_dest.pa_addrlen = destmac->nv_addrlen;
memcpy(pktmeta->pm_dest.pa_addr, destmac->nv_addr, destmac->nv_addrlen);
return OK;
}
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: sixlowpan_queue_frames
*
* Description:
* Process an outgoing UDP, TCP, or ICMPv6 packet. This function is
* called from send interrupt logic when a TX poll is received. It
* formats the list of frames to be sent by the IEEE802.15.4 MAC driver.
*
* 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
* where they are queue for transfer.
*
* Input Parameters:
* radio - The radio network driver instance
* ipv6 - IPv6 header followed by TCP, UDP, or ICMPv6 header.
* buf - Beginning of the packet packet to send (with IPv6 + protocol
* headers)
* buflen - Length of data to send (include IPv6 and protocol headers)
* destmac - The IEEE802.15.4 MAC address of the destination
*
* Returned Value:
* Ok is returned on success; Othewise 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 UDP/TCP will fall back to normal
* IPv4/IPv6 formatting.
*
* Assumptions:
* Called with the network locked.
*
****************************************************************************/
int sixlowpan_queue_frames(FAR struct sixlowpan_driver_s *radio,
FAR const struct ipv6_hdr_s *ipv6,
FAR const void *buf, size_t buflen,
FAR const struct netdev_varaddr_s *destmac)
{
union sixlowpan_metadata_u meta;
FAR struct iob_s *iob;
FAR uint8_t *fptr;
int framer_hdrlen;
struct netdev_varaddr_s bcastmac;
uint16_t pktlen;
uint16_t paysize;
#ifdef CONFIG_NET_6LOWPAN_FRAG
uint16_t outlen = 0;
#endif
uint8_t protosize;
int ret;
ninfo("buflen=%lu\n", (unsigned long)buflen);
/* Initialize global data. Locking the network guarantees that we have
* exclusive use of the global values for intermediate calculations.
*/
g_uncomp_hdrlen = 0;
g_frame_hdrlen = 0;
protosize = 0;
/* The destination address will be tagged to each outbound packet. If the
* argument destmac is NULL, we are sending a broadcast packet.
*/
if (destmac == NULL)
{
memset(&bcastmac, 0, sizeof(struct netdev_varaddr_s));
destmac = &bcastmac;
}
/* Pre-allocate the IOB to hold frame or the first fragment, waiting if
* necessary.
*/
iob = iob_alloc(false);
DEBUGASSERT(iob != NULL);
/* Initialize the IOB */
iob->io_flink = NULL;
iob->io_len = 0;
iob->io_offset = 0;
iob->io_pktlen = 0;
fptr = iob->io_data;
ninfo("Sending packet length %d\n", buflen);
/* Get the metadata that describes the MAC header on the packet */
#ifdef CONFIG_WIRELESS_IEEE802154
#ifdef CONFIG_WIRELESS_PKTRADIO
if (radio->r_dev.d_lltype == NET_LL_IEEE802154)
#endif
{
ret = sixlowpan_ieee802154_metadata(radio, destmac, &meta);
}
#endif
#ifdef CONFIG_WIRELESS_PKTRADIO
#ifdef CONFIG_WIRELESS_IEEE802154
else
#endif
{
ret = sixlowpan_pktradio_metadata(radio, destmac, &meta);
}
#endif
/* Pre-calculate frame header length. */
framer_hdrlen = sixlowpan_frame_hdrlen(radio, &meta);
if (framer_hdrlen < 0)
{
/* Failed to determine the size of the header failed. */
nerr("ERROR: sixlowpan_frame_hdrlen() failed: %d\n", framer_hdrlen);
return framer_hdrlen;
}
/* This sill be the initial offset into io_data. Valid data begins at
* this offset and must be reflected in io_offset.
*/
g_frame_hdrlen = framer_hdrlen;
iob->io_offset = framer_hdrlen;
#ifndef CONFIG_NET_6LOWPAN_COMPRESSION_IPv6
if (buflen >= CONFIG_NET_6LOWPAN_COMPRESSION_THRESHOLD)
{
/* Try to compress the headers */
#if defined(CONFIG_NET_6LOWPAN_COMPRESSION_HC1)
ret = sixlowpan_compresshdr_hc1(radio, ipv6, destmac, fptr);
#elif defined(CONFIG_NET_6LOWPAN_COMPRESSION_HC06)
ret = sixlowpan_compresshdr_hc06(radio, ipv6, destmac, fptr);
#else
# error No compression specified
#endif
}
else
#endif /* !CONFIG_NET_6LOWPAN_COMPRESSION_IPv6 */
{
/* Small.. use IPv6 dispatch (no compression) */
ret = sixlowpan_compress_ipv6hdr(ipv6, fptr);
}
/* Get the size of any uncompressed protocol headers */
if (ret == COMPRESS_HDR_INLINE)
{
protosize = sixlowpan_protosize(ipv6, fptr);
}
ninfo("Header of length=%u protosize=%u\n", g_frame_hdrlen, protosize);
/* Check if we need to fragment the packet into several frames */
if (buflen > (SIXLOWPAN_FRAMELEN - g_frame_hdrlen - protosize))
{
#ifdef CONFIG_NET_6LOWPAN_FRAG
/* qhead will hold the generated frame list; frames will be
* added at qtail.
*/
FAR struct iob_s *qhead;
FAR struct iob_s *qtail;
FAR uint8_t *frame1;
FAR uint8_t *fragptr;
uint16_t frag1_hdrlen;
/* The outbound IPv6 packet is too large to fit into a single 15.4
* packet, so we fragment it into multiple packets and send them.
* The first fragment contains frag1 dispatch, then
* IPv6/HC1/HC06/HC_UDP dispatchs/headers.
* The following fragments contain only the fragn dispatch.
*/
ninfo("Sending fragmented packet length %d\n", buflen);
/* Create 1st Fragment */
/* Move HC1/HC06/IPv6 header to make space for the FRAG1 header at the
* beginning of the frame.
*/
fragptr = fptr + framer_hdrlen;
memmove(fragptr + SIXLOWPAN_FRAG1_HDR_LEN, fragptr,
g_frame_hdrlen - framer_hdrlen);
/* Setup up the fragment header.
*
* The fragment header contains three fields: Datagram size, datagram
* tag and datagram offset:
*
* 1. Datagram size describes the total (un-fragmented) payload.
* 2. Datagram tag identifies the set of fragments and is used to
* match fragments of the same payload.
* 3. Datagram offset identifies the fragments offset within the un-
* fragmented payload.
*
* The fragment header length is 4 bytes for the first header and 5
* bytes for all subsequent headers.
*/
pktlen = buflen + g_uncomp_hdrlen + protosize;
PUTHOST16(fragptr, SIXLOWPAN_FRAG_DISPATCH_SIZE,
((SIXLOWPAN_DISPATCH_FRAG1 << 8) | pktlen));
PUTHOST16(fragptr, SIXLOWPAN_FRAG_TAG, radio->r_dgramtag);
g_frame_hdrlen += SIXLOWPAN_FRAG1_HDR_LEN;
/* Copy any uncompressed protocol headers that must appear only in th
* first fragment.
*/
if (protosize > 0)
{
FAR uint8_t *src = (FAR uint8_t *)ipv6 + IPv6_HDRLEN;
memcpy(fptr + g_frame_hdrlen, src, protosize);
}
/* Copy payload and enqueue. NOTE that the size is a multiple of eight
* bytes.
*/
paysize = (SIXLOWPAN_FRAMELEN - g_frame_hdrlen) & ~7;
memcpy(fptr + g_frame_hdrlen + protosize, buf, paysize - protosize);
/* Set outlen to what we already sent from the IP payload */
iob->io_len = paysize + g_frame_hdrlen;
outlen = paysize;
ninfo("First fragment: length %d, tag %d\n",
paysize, radio->r_dgramtag);
sixlowpan_dumpbuffer("Outgoing frame",
(FAR const uint8_t *)iob->io_data, iob->io_len);
/* Add the first frame to the IOB queue */
ninfo("Queuing frame io_len=%u io_offset=%u\n",
iob->io_len, iob->io_offset);
qhead = iob;
qtail = iob;
/* Keep track of the total amount of data queue */
iob->io_pktlen = iob->io_len;
/* Create following fragments */
frame1 = iob->io_data;
frag1_hdrlen = g_frame_hdrlen;
while (outlen < (buflen + protosize))
{
uint16_t fragn_hdrlen;
/* Allocate an IOB to hold the next fragment, waiting if
* necessary.
*/
iob = iob_alloc(false);
DEBUGASSERT(iob != NULL);
/* Initialize the IOB */
iob->io_flink = NULL;
iob->io_len = 0;
iob->io_offset = framer_hdrlen;
iob->io_pktlen = 0;
fptr = iob->io_data;
/* Copy the HC1/HC06/IPv6 header the frame header from first
* frame, into the correct location after the FRAGN header
* of subsequent frames.
*/
fragptr = fptr + framer_hdrlen;
memcpy(fragptr + SIXLOWPAN_FRAGN_HDR_LEN,
frame1 + framer_hdrlen + SIXLOWPAN_FRAG1_HDR_LEN,
frag1_hdrlen - framer_hdrlen);
fragn_hdrlen = frag1_hdrlen - SIXLOWPAN_FRAG1_HDR_LEN;
/* Setup up the FRAGN header after the frame header. */
PUTHOST16(fragptr, SIXLOWPAN_FRAG_DISPATCH_SIZE,
((SIXLOWPAN_DISPATCH_FRAGN << 8) | pktlen));
PUTHOST16(fragptr, SIXLOWPAN_FRAG_TAG, radio->r_dgramtag);
fragptr[SIXLOWPAN_FRAG_OFFSET] = outlen >> 3;
fragn_hdrlen += SIXLOWPAN_FRAGN_HDR_LEN;
/* Copy payload and enqueue */
/* Check for the last fragment */
paysize = (SIXLOWPAN_FRAMELEN - fragn_hdrlen) &
SIXLOWPAN_DISPATCH_FRAG_MASK;
if (paysize > buflen - outlen + protosize)
{
/* Last fragment, truncate to the correct length */
paysize = buflen - outlen + protosize;
}
memcpy(fptr + fragn_hdrlen, buf + outlen - protosize, paysize);
/* Set outlen to what we already sent from the IP payload */
iob->io_len = paysize + fragn_hdrlen;
outlen += paysize;
ninfo("Fragment offset=%d, paysize=%d, r_dgramtag=%d\n",
outlen >> 3, paysize, radio->r_dgramtag);
sixlowpan_dumpbuffer("Outgoing frame",
(FAR const uint8_t *)iob->io_data,
iob->io_len);
/* Add the next frame to the tail of the IOB queue */
ninfo("Queuing frame io_len=%u io_offset=%u\n",
iob->io_len, iob->io_offset);
qtail->io_flink = iob;
qtail = iob;
/* Keep track of the total amount of data queue */
qhead->io_pktlen += iob->io_len;
}
/* Submit all of the fragments to the MAC. We send all frames back-
* to-back like this to minimize any possible condition where some
* frame which is not a fragment from this sequence from intervening.
*/
for (iob = qhead; iob != NULL; iob = qhead)
{
/* Remove the IOB containing the frame from the list */
qhead = iob->io_flink;
iob->io_flink = NULL;
/* And submit the frame to the MAC */
ninfo("Submitting frame\n");
ret = sixlowpan_frame_submit(radio, &meta, iob);
if (ret < 0)
{
nerr("ERROR: sixlowpan_frame_submit() failed: %d\n", ret);
}
}
/* Update the datagram TAG value */
radio->r_dgramtag++;
#else
nerr("ERROR: Packet too large: %d\n", buflen);
nerr(" Cannot to be sent without fragmentation support\n");
nerr(" dropping packet\n");
return -E2BIG;
#endif
}
else
{
/* The packet does not need to be fragmented just copy the "payload"
* and send in one frame.
*/
/* Copy any uncompressed protocol headers that must appear only in th
* first fragment.
*/
if (protosize > 0)
{
FAR uint8_t *src = (FAR uint8_t *)ipv6 + IPv6_HDRLEN;
memcpy(fptr + g_frame_hdrlen, src, protosize);
}
/* Copy the payload into the frame. */
memcpy(fptr + g_frame_hdrlen + protosize, buf, buflen);
iob->io_len = buflen + g_frame_hdrlen + protosize;
iob->io_pktlen = iob->io_len;
ninfo("Non-fragmented: length %d\n", iob->io_len);
sixlowpan_dumpbuffer("Outgoing frame",
(FAR const uint8_t *)iob->io_data, iob->io_len);
/* And submit the frame to the MAC */
ninfo("Submitting frame length=%u io_offset=%u\n",
iob->io_len, iob->io_offset);
ret = sixlowpan_frame_submit(radio, &meta, iob);
if (ret < 0)
{
nerr("ERROR: sixlowpan_frame_submit() failed: %d\n", ret);
}
}
return OK;
}
#endif /* CONFIG_NET_6LOWPAN */