1e24404dcc
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: 7029dffd027f53e08917
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: da782d6cdf5889ce65f5
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: 27c0a6ec0838f79543dc
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: 3fcf84a9a247791442a0
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: 855cf97130b458934ac4
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: cb79778a30f287cc25d6
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: 66e87f9bb3598386ef90
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: 91e985a877c9ff8cbab9
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: 89e9d426e92fc0fbcf7e
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: 87b616414a6bd744c4b3
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: 90a7666655f4e46b0da7
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: 623d54a7f72319ea53a9
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: 52c3ddfae6d88dc9b2e5
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.
907 lines
30 KiB
C
907 lines
30 KiB
C
/****************************************************************************
|
|
* net/sixlowpan/sixlowpan_input.c
|
|
* 6LoWPAN implementation (RFC4944 and draft-ietf-6LoWPAN-hc-06)
|
|
*
|
|
* Copyright (C) 2017, Gregory Nutt, all rights reserved
|
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
|
*
|
|
* Derives in large part 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>
|
|
|
|
#ifdef CONFIG_NET_6LOWPAN_FRAG
|
|
# include "nuttx/clock.h"
|
|
#endif
|
|
|
|
#include "nuttx/net/netdev.h"
|
|
#include "nuttx/net/ip.h"
|
|
#include "nuttx/net/icmpv6.h"
|
|
#include "nuttx/net/sixlowpan.h"
|
|
#include "nuttx/wireless/ieee802154/ieee802154_mac.h"
|
|
|
|
#ifdef CONFIG_NET_PKT
|
|
# include "pkt/pkt.h"
|
|
#endif
|
|
|
|
#include "sixlowpan/sixlowpan_internal.h"
|
|
|
|
#ifdef CONFIG_NET_6LOWPAN
|
|
|
|
/****************************************************************************
|
|
* Pre-processor Definitions
|
|
****************************************************************************/
|
|
|
|
/* Success return values from sixlowpan_frame_process */
|
|
|
|
#define INPUT_PARTIAL 0 /* Frame processed successful, packet incomplete */
|
|
#define INPUT_COMPLETE 1 /* Frame processed successful, packet complete */
|
|
|
|
/* Re-assembly timeout in clock ticks */
|
|
|
|
#define NET_6LOWPAN_TIMEOUT SEC2TICK(CONFIG_NET_6LOWPAN_MAXAGE)
|
|
|
|
/* This is the size of a buffer large enough to hold the largest uncompressed
|
|
* HC06 or HC1 headers.
|
|
*/
|
|
|
|
#ifdef CONFIG_NET_TCP
|
|
/* The basic TCP header length is TCP_HDRLEN but could include up to 16
|
|
* additional 32-bit words of optional data.
|
|
*/
|
|
|
|
# define UNCOMP_MAXHDR (IPv6_HDRLEN + TCP_HDRLEN + 16*sizeof(uint32_t))
|
|
|
|
#elif defined(CONFIG_NET_UDP)
|
|
/* The UDP header length is always 8 bytes */
|
|
|
|
# define UNCOMP_MAXHDR (IPv6_HDRLEN + UDP_HDRLEN)
|
|
|
|
#elif defined(CONFIG_NET_ICMPv6)
|
|
/* The ICMPv6 header length is a mere 4 bytes */
|
|
|
|
# define UNCOMP_MAXHDR (IPv6_HDRLEN + ICMPv6_HDRLEN)
|
|
|
|
#else
|
|
/* No other header type is handled. */
|
|
|
|
# define UNCOMP_MAXHDR IPv6_HDRLEN
|
|
#endif
|
|
|
|
/* Buffer access helpers */
|
|
|
|
#define IPv6BUF(dev) ((FAR struct ipv6_hdr_s *)((dev)->d_buf))
|
|
#define TCPBUF(dev) ((FAR struct tcp_hdr_s *)&(dev)->d_buf[IPv6_HDRLEN])
|
|
|
|
/****************************************************************************
|
|
* Private Data
|
|
****************************************************************************/
|
|
|
|
#ifdef CONFIG_NET_6LOWPAN_FRAG
|
|
/* This big buffer could be avoided with a little more effort */
|
|
|
|
static uint8_t g_bitbucket[UNCOMP_MAXHDR];
|
|
#endif
|
|
|
|
/****************************************************************************
|
|
* Private Functions
|
|
****************************************************************************/
|
|
|
|
/****************************************************************************
|
|
* Name: sixlowpan_compare_fragsrc
|
|
*
|
|
* Description:
|
|
* Check if the fragment that we just received is from the same source as
|
|
* the previosly received fragements.
|
|
*
|
|
* Input Parameters:
|
|
* radio - Radio network device driver state instance
|
|
* metadata - Characteristics of the newly received frame
|
|
*
|
|
* Returned Value:
|
|
* true if the sources are the same.
|
|
*
|
|
****************************************************************************/
|
|
|
|
static bool sixlowpan_compare_fragsrc(FAR struct sixlowpan_driver_s *radio,
|
|
FAR const void *metadata)
|
|
{
|
|
struct netdev_varaddr_s fragsrc;
|
|
int ret;
|
|
|
|
/* Extract the source address from the 'metadata' */
|
|
|
|
ret = sixlowpan_extract_srcaddr(radio, metadata, &fragsrc);
|
|
if (ret < 0)
|
|
{
|
|
nerr("ERROR: sixlowpan_extract_srcaddr failed: %d\n", ret);
|
|
return false;
|
|
}
|
|
|
|
/* The addresses cannot match if they are not the same size */
|
|
|
|
if (fragsrc.nv_addrlen == radio->r_fragsrc.nv_addrlen)
|
|
{
|
|
/* The are the same sizer, return the address comparisson */
|
|
|
|
return (memcmp(fragsrc.nv_addr, radio->r_fragsrc.nv_addr,
|
|
fragsrc.nv_addrlen) == 0);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* 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:
|
|
* fptr - Pointer to the beginning of the frame under construction
|
|
* bptr - Output goes here. Normally this is a known offset into d_buf,
|
|
* may be redirected to g_bitbucket on the case of FRAGN frames.
|
|
*
|
|
* Returned Value:
|
|
* None
|
|
*
|
|
****************************************************************************/
|
|
|
|
static void sixlowpan_uncompress_ipv6hdr(FAR uint8_t *fptr, FAR uint8_t *bptr)
|
|
{
|
|
FAR struct ipv6_hdr_s *ipv6 = (FAR struct ipv6_hdr_s *)bptr;
|
|
uint16_t protosize;
|
|
|
|
/* Put uncompressed IPv6 header in d_buf. */
|
|
|
|
g_frame_hdrlen += SIXLOWPAN_IPV6_HDR_LEN;
|
|
memcpy(ipv6, fptr + g_frame_hdrlen, IPv6_HDRLEN);
|
|
|
|
/* Update g_uncomp_hdrlen and g_frame_hdrlen. */
|
|
|
|
g_frame_hdrlen += IPv6_HDRLEN;
|
|
g_uncomp_hdrlen += IPv6_HDRLEN;
|
|
|
|
/* Copy the following protocol header, */
|
|
|
|
switch (ipv6->proto)
|
|
{
|
|
#ifdef CONFIG_NET_TCP
|
|
case IP_PROTO_TCP:
|
|
{
|
|
FAR struct tcp_hdr_s *tcp =
|
|
(FAR struct tcp_hdr_s *)(fptr + g_frame_hdrlen);
|
|
|
|
/* 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 = sizeof(struct udp_hdr_s);
|
|
break;
|
|
#endif
|
|
|
|
#ifdef CONFIG_NET_ICMPv6
|
|
case IP_PROTO_ICMP6:
|
|
protosize = sizeof(struct icmpv6_hdr_s);
|
|
break;
|
|
#endif
|
|
|
|
default:
|
|
nwarn("WARNING: Unrecognized proto: %u\n", ipv6->proto);
|
|
return;
|
|
}
|
|
|
|
/* Copy the protocol header. */
|
|
|
|
memcpy((FAR uint8_t *)ipv6 + g_uncomp_hdrlen, fptr + g_frame_hdrlen,
|
|
protosize);
|
|
|
|
g_frame_hdrlen += protosize;
|
|
g_uncomp_hdrlen += protosize;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Public Functions
|
|
****************************************************************************/
|
|
|
|
/****************************************************************************
|
|
* Name: sixlowpan_frame_process
|
|
*
|
|
* Description:
|
|
* Process an incoming 6LoWPAN frame in 'iob'.
|
|
*
|
|
* If its a FRAG1 or a non-fragmented frame we first uncompress the IP
|
|
* header. The 6LoWPAN payload and possibly the uncompressed IP header
|
|
* are then copied into d_buf. An indication is returned if the packet
|
|
* in d_buf is complete (i.e., non-fragmented frame or and the last
|
|
* FRAGN frame).
|
|
*
|
|
* NOTE: We do not check for overlapping sixlowpan fragments (that is a
|
|
* SHALL in the RFC 4944 and should never happen)
|
|
*
|
|
* Input Parameters:
|
|
* radio - The radio network device driver interface.
|
|
* metadata - Metadata characterizing the received frame.
|
|
* iob - The IOB containing the frame.
|
|
*
|
|
* Returned Value:
|
|
* On success, a value greater than equal to zero is returned, either:
|
|
*
|
|
* INPUT_PARTIAL Frame processed successful, packet incomplete
|
|
* INPUT_COMPLETE Frame processed successful, packet complete
|
|
*
|
|
* Othewise a negated errno value is returned to indicate the nature of the
|
|
* failure.
|
|
*
|
|
* Assumptions:
|
|
* Network is locked
|
|
*
|
|
****************************************************************************/
|
|
|
|
static int sixlowpan_frame_process(FAR struct sixlowpan_driver_s *radio,
|
|
FAR const void *metadata, FAR struct iob_s *iob)
|
|
{
|
|
FAR uint8_t *fptr; /* Convenience pointer to beginning of the frame */
|
|
FAR uint8_t *bptr; /* Used to redirect uncompressed header to the bitbucket */
|
|
FAR uint8_t *hc1; /* Convenience pointer to HC1 data */
|
|
uint16_t fragsize = 0; /* Size of the IP packet (read from fragment) */
|
|
uint16_t paysize; /* Size of the data payload */
|
|
uint8_t fragoffset = 0; /* Offset of the fragment in the IP packet */
|
|
int reqsize; /* Required buffer size */
|
|
int hdrsize; /* Size of the IEEE802.15.4 header */
|
|
|
|
#ifdef CONFIG_NET_6LOWPAN_FRAG
|
|
FAR uint8_t *fragptr; /* Pointer to the fragmentation header */
|
|
bool isfrag = false;
|
|
bool isfirstfrag = false;
|
|
uint16_t fragtag = 0; /* Tag of the fragment */
|
|
systime_t elapsed; /* Elapsed time */
|
|
int ret;
|
|
#endif /* CONFIG_NET_6LOWPAN_FRAG */
|
|
|
|
/* Get a pointer to the payload following the IEEE802.15.4 frame header(s).
|
|
* This size includes both fragmentation and FCF headers.
|
|
*/
|
|
|
|
fptr = iob->io_data; /* Frame data is in I/O buffer */
|
|
hdrsize = iob->io_offset; /* Offset past the MAC header */
|
|
|
|
DEBUGASSERT((unsigned)hdrsize < iob->io_len);
|
|
|
|
/* 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 = hdrsize;
|
|
|
|
#ifdef CONFIG_NET_6LOWPAN_FRAG
|
|
/* Since we don't support the mesh and broadcast header, the first header
|
|
* we look for is the fragmentation header. NOTE that g_frame_hdrlen
|
|
* already includes the fragementation header, if presetn.
|
|
*/
|
|
|
|
fragptr = fptr + hdrsize;
|
|
switch ((GETUINT16(fragptr, SIXLOWPAN_FRAG_DISPATCH_SIZE) & 0xf800) >> 8)
|
|
{
|
|
/* First fragment of new reassembly */
|
|
|
|
case SIXLOWPAN_DISPATCH_FRAG1:
|
|
{
|
|
/* Set up for the reassembly */
|
|
|
|
fragsize = GETUINT16(fragptr, SIXLOWPAN_FRAG_DISPATCH_SIZE) & 0x07ff;
|
|
fragtag = GETUINT16(fragptr, SIXLOWPAN_FRAG_TAG);
|
|
g_frame_hdrlen += SIXLOWPAN_FRAG1_HDR_LEN;
|
|
|
|
ninfo("FRAG1: fragsize=%d fragtag=%d fragoffset=%d\n",
|
|
fragsize, fragtag, fragoffset);
|
|
|
|
/* Indicate the first fragment of the reassembly */
|
|
|
|
isfirstfrag = true;
|
|
isfrag = true;
|
|
}
|
|
break;
|
|
|
|
case SIXLOWPAN_DISPATCH_FRAGN:
|
|
{
|
|
/* Set offset, tag, size. Offset is in units of 8 bytes. */
|
|
|
|
fragoffset = fragptr[SIXLOWPAN_FRAG_OFFSET];
|
|
fragtag = GETUINT16(fragptr, SIXLOWPAN_FRAG_TAG);
|
|
fragsize = GETUINT16(fragptr, SIXLOWPAN_FRAG_DISPATCH_SIZE) & 0x07ff;
|
|
g_frame_hdrlen += SIXLOWPAN_FRAGN_HDR_LEN;
|
|
|
|
ninfo("FRAGN: fragsize=%d fragtag=%d fragoffset=%d\n",
|
|
fragsize, fragtag, fragoffset);
|
|
ninfo("FRAGN: r_accumlen=%d paysize=%u fragsize=%u\n",
|
|
radio->r_accumlen, iob->io_len - g_frame_hdrlen, fragsize);
|
|
|
|
/* Indicate that this frame is a another fragment for reassembly */
|
|
|
|
isfrag = true;
|
|
}
|
|
break;
|
|
|
|
/* Not a fragment */
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
/* Check if we are currently reassembling a packet */
|
|
|
|
bptr = radio->r_dev.d_buf;
|
|
if (radio->r_accumlen > 0)
|
|
{
|
|
/* If reassembly timed out, cancel it */
|
|
|
|
elapsed = clock_systimer() - radio->r_time;
|
|
if (elapsed > NET_6LOWPAN_TIMEOUT)
|
|
{
|
|
nwarn("WARNING: Reassembly timed out\n");
|
|
radio->r_pktlen = 0;
|
|
radio->r_accumlen = 0;
|
|
}
|
|
|
|
/* In this case what we expect is that the next frame will hold the
|
|
* next FRAGN of the sequence. We have to handle a few exeptional
|
|
* cases that we need to handle:
|
|
*
|
|
* 1. If we are currently reassembling a packet, but have just received
|
|
* the first fragment of another packet. We can either ignore it and
|
|
* hope to receive the rest of the under-reassembly packet fragments,
|
|
* or we can discard the previous packet altogether, and start
|
|
* reassembling the new packet. Here we discard the previous packet,
|
|
* and start reassembling the new packet.
|
|
* 2. The new frame is not a fragment. We should be able to handle this
|
|
* case, but we cannot because that would require two packet buffers.
|
|
* It could be handled with a more extensive design.
|
|
* 3. The fragment came from a different sender. What would this mean?
|
|
*
|
|
*/
|
|
|
|
else if (!isfrag)
|
|
{
|
|
/* Discard the partially assembled packet */
|
|
|
|
nwarn("WARNING: Non-fragment frame received during reassembly\n");
|
|
radio->r_pktlen = 0;
|
|
radio->r_accumlen = 0;
|
|
}
|
|
|
|
/* It is a fragment of some kind. Drop any zero length fragments */
|
|
|
|
else if (fragsize == 0)
|
|
{
|
|
nwarn("WARNING: Dropping zero-length 6LoWPAN fragment\n");
|
|
return INPUT_PARTIAL;
|
|
}
|
|
|
|
/* A non-zero, first fragement received while we are in the middle of
|
|
* rassembly. Discard the partially assembled packet and start over.
|
|
*/
|
|
|
|
else if (isfirstfrag)
|
|
{
|
|
nwarn("WARNING: First fragment frame received during reassembly\n");
|
|
radio->r_pktlen = 0;
|
|
radio->r_accumlen = 0;
|
|
}
|
|
|
|
/* Verify that this fragment is part of that reassembly sequence */
|
|
|
|
else if (fragsize != radio->r_pktlen || radio->r_reasstag != fragtag ||
|
|
!sixlowpan_compare_fragsrc(radio, metadata))
|
|
{
|
|
/* The packet is a fragment that does not belong to the packet
|
|
* being reassembled or the packet is not a fragment.
|
|
*/
|
|
|
|
nwarn("WARNING: Dropping 6LoWPAN packet that is not a fragment of "
|
|
"the packet currently being reassembled\n");
|
|
return -EPERM;
|
|
}
|
|
else
|
|
{
|
|
/* Looks good. We are currently processing a reassembling sequence
|
|
* and we recieved a valid FRAGN fragment. Redirect the header
|
|
* uncompression to our bitbucket.
|
|
*/
|
|
|
|
bptr = g_bitbucket;
|
|
}
|
|
}
|
|
|
|
/* There is no reassembly in progress. Check if we received a fragment */
|
|
|
|
else if (isfrag)
|
|
{
|
|
/* Another case that we have to handle is if a FRAGN fragment of a
|
|
* reassembly is received, but we are not currently reassembling a
|
|
* packet. I think we have no choice but to drop the packet in this
|
|
* case.
|
|
*/
|
|
|
|
if (!isfirstfrag)
|
|
{
|
|
nwarn("WARNING: FRAGN 6LoWPAN fragment while not reassembling\n");
|
|
return -EPERM;
|
|
}
|
|
|
|
/* Drop the packet if it cannot fit into the d_buf */
|
|
|
|
if (fragsize > CONFIG_NET_6LOWPAN_MTU)
|
|
{
|
|
nwarn("WARNING: Reassembled packet size exeeds CONFIG_NET_6LOWPAN_MTU\n");
|
|
return -ENOSPC;
|
|
}
|
|
|
|
radio->r_pktlen = fragsize;
|
|
radio->r_reasstag = fragtag;
|
|
radio->r_time = clock_systimer();
|
|
|
|
ninfo("Starting reassembly: r_pktlen %u, r_reasstag %d\n",
|
|
radio->r_pktlen, radio->r_reasstag);
|
|
|
|
/* Extract the source address from the 'metadata'. NOTE that the size
|
|
* of the source address may be different than our local, destination
|
|
* address.
|
|
*/
|
|
|
|
ret = sixlowpan_extract_srcaddr(radio, metadata, &radio->r_fragsrc);
|
|
if (ret < 0)
|
|
{
|
|
nerr("ERROR: sixlowpan_extract_srcaddr failed: %d\n", ret);
|
|
return ret;
|
|
}
|
|
}
|
|
#endif /* CONFIG_NET_6LOWPAN_FRAG */
|
|
|
|
/* Process next dispatch and headers */
|
|
|
|
hc1 = fptr + g_frame_hdrlen;
|
|
|
|
#ifdef CONFIG_NET_6LOWPAN_COMPRESSION_HC06
|
|
if ((hc1[SIXLOWPAN_HC1_DISPATCH] & SIXLOWPAN_DISPATCH_IPHC_MASK) == SIXLOWPAN_DISPATCH_IPHC)
|
|
{
|
|
ninfo("IPHC Dispatch\n");
|
|
sixlowpan_uncompresshdr_hc06(radio, metadata, fragsize, iob, fptr, bptr);
|
|
}
|
|
else
|
|
#endif /* CONFIG_NET_6LOWPAN_COMPRESSION_HC06 */
|
|
|
|
#ifdef CONFIG_NET_6LOWPAN_COMPRESSION_HC1
|
|
if (hc1[SIXLOWPAN_HC1_DISPATCH] == SIXLOWPAN_DISPATCH_HC1)
|
|
{
|
|
ninfo("HC1 Dispatch\n");
|
|
sixlowpan_uncompresshdr_hc1(radio, metadata, fragsize, iob, fptr, bptr);
|
|
}
|
|
else
|
|
#endif /* CONFIG_NET_6LOWPAN_COMPRESSION_HC1 */
|
|
|
|
if (hc1[SIXLOWPAN_HC1_DISPATCH] == SIXLOWPAN_DISPATCH_IPV6)
|
|
{
|
|
ninfo("IPv6 Dispatch\n");
|
|
sixlowpan_uncompress_ipv6hdr(fptr, bptr);
|
|
}
|
|
else
|
|
{
|
|
/* Unknown or unsupported header */
|
|
|
|
nwarn("WARNING: Unknown dispatch: %u\n", hc1[SIXLOWPAN_HC1_DISPATCH]);
|
|
return -ENOSYS;
|
|
}
|
|
|
|
#ifdef CONFIG_NET_6LOWPAN_FRAG
|
|
/* Is this the first fragment is a sequence? */
|
|
|
|
if (isfirstfrag)
|
|
{
|
|
/* Yes.. Remember the offset from the beginning of d_buf where we
|
|
* begin placing the data payload.
|
|
*/
|
|
|
|
radio->r_boffset = g_uncomp_hdrlen;
|
|
}
|
|
|
|
/* No.. is this a subsequent fragment in the same sequence? */
|
|
|
|
else if (isfrag)
|
|
{
|
|
/* Yes, recover the offset from the beginning of the d_buf where
|
|
* we began placing payload data.
|
|
*/
|
|
|
|
g_uncomp_hdrlen = radio->r_boffset;
|
|
}
|
|
#endif /* CONFIG_NET_6LOWPAN_FRAG */
|
|
|
|
/* Copy "payload" from the frame buffer to the IEEE802.15.4 MAC driver's
|
|
* packet buffer, d_buf. If this frame is a first fragment or not part of
|
|
* a fragmented packet, we have already copied the compressed headers,
|
|
* g_uncomp_hdrlen and g_frame_hdrlen are non-zerio, fragoffset is.
|
|
*/
|
|
|
|
paysize = iob->io_len - g_frame_hdrlen;
|
|
if (paysize > CONFIG_NET_6LOWPAN_MTU)
|
|
{
|
|
nwarn("WARNING: Packet dropped due to payload (%u) > packet buffer (%u)\n",
|
|
paysize, CONFIG_NET_6LOWPAN_MTU);
|
|
return -ENOSPC;
|
|
}
|
|
|
|
/* Sanity-check size of incoming packet to avoid buffer overflow */
|
|
|
|
reqsize = g_uncomp_hdrlen + (fragoffset << 3) + paysize;
|
|
if (reqsize > CONFIG_NET_6LOWPAN_MTU)
|
|
{
|
|
nwarn("WARNING: Required buffer size: %u+%u+%u=%u Available=%u\n",
|
|
g_uncomp_hdrlen, (fragoffset << 3), paysize,
|
|
reqsize, CONFIG_NET_6LOWPAN_MTU);
|
|
return -ENOMEM;
|
|
}
|
|
|
|
memcpy(radio->r_dev.d_buf + g_uncomp_hdrlen + (fragoffset << 3),
|
|
fptr + g_frame_hdrlen, paysize);
|
|
|
|
#ifdef CONFIG_NET_6LOWPAN_FRAG
|
|
/* Update radio->r_accumlen if the frame is a fragment, radio->r_pktlen
|
|
* otherwise.
|
|
*/
|
|
|
|
if (isfrag)
|
|
{
|
|
/* Check if it is the last fragment to be processed.
|
|
*
|
|
* If this is the last fragment, we may shave off any extrenous
|
|
* bytes at the end. We must be liberal in what we accept.
|
|
*/
|
|
|
|
radio->r_accumlen = g_uncomp_hdrlen + (fragoffset << 3) + paysize;
|
|
}
|
|
else
|
|
{
|
|
radio->r_pktlen = paysize + g_uncomp_hdrlen;
|
|
}
|
|
|
|
/* If we have a full IP packet in sixlowpan_buf, deliver it to
|
|
* the IP stack
|
|
*/
|
|
|
|
ninfo("r_accumlen=%d r_pktlen=%d paysize=%d\n",
|
|
radio->r_accumlen, radio->r_pktlen, paysize);
|
|
|
|
if (radio->r_accumlen == 0 || radio->r_accumlen >= radio->r_pktlen)
|
|
{
|
|
ninfo("IP packet ready (length %d)\n", radio->r_pktlen);
|
|
|
|
radio->r_dev.d_len = radio->r_pktlen;
|
|
radio->r_pktlen = 0;
|
|
radio->r_accumlen = 0;
|
|
return INPUT_COMPLETE;
|
|
}
|
|
|
|
return INPUT_PARTIAL;
|
|
#else
|
|
/* Deliver the packet to the IP stack */
|
|
|
|
radio->r_dev.d_len = paysize + g_uncomp_hdrlen;
|
|
return INPUT_COMPLETE;
|
|
#endif /* CONFIG_NET_6LOWPAN_FRAG */
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: sixlowpan_dispatch
|
|
*
|
|
* Description:
|
|
* Inject the packet in d_buf into the network for normal packet processing.
|
|
*
|
|
* Input Parmeters
|
|
* radio - The IEEE802.15.4 MAC network driver interface.
|
|
*
|
|
* Returned Value:
|
|
* None
|
|
*
|
|
****************************************************************************/
|
|
|
|
static int sixlowpan_dispatch(FAR struct sixlowpan_driver_s *radio)
|
|
{
|
|
sixlowpan_dumpbuffer("Incoming packet",
|
|
(FAR const uint8_t *)IPv6BUF(&radio->r_dev),
|
|
radio->r_dev.d_len);
|
|
|
|
#ifdef CONFIG_NET_PKT
|
|
/* When packet sockets are enabled, feed the frame into the packet tap */
|
|
|
|
ninfo("Packet tap\n");
|
|
pkt_input(&radio->r_dev);
|
|
#endif
|
|
|
|
/* We only accept IPv6 packets. */
|
|
|
|
ninfo("IPv6 packet dispatch\n");
|
|
NETDEV_RXIPV6(&radio->r_dev);
|
|
|
|
/* Give the IPv6 packet to the network layer. NOTE: If there is a
|
|
* problem with IPv6 header, it will be silently dropped and d_len will
|
|
* be set to zero. Oddly, ipv6_input() will return OK in this case.
|
|
*/
|
|
|
|
return ipv6_input(&radio->r_dev);
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Public Functions
|
|
****************************************************************************/
|
|
|
|
/****************************************************************************
|
|
* Name: sixlowpan_input
|
|
*
|
|
* Description:
|
|
* Process an incoming 6LoWPAN frame.
|
|
*
|
|
* This function is called when the radio device driver has received an
|
|
* frame from the network. The frame from the device driver must be
|
|
* provided in by the IOB frame argument of the function call:
|
|
*
|
|
* - The frame data is in the IOB io_data[] buffer,
|
|
* - The length of the frame is in the IOB io_len field, and
|
|
* - The offset past and radio MAC header is provided in the io_offset
|
|
* field.
|
|
*
|
|
* The frame argument may refer to a single frame (a list of length one)
|
|
* or may it be the head of a list of multiple frames.
|
|
*
|
|
* - The io_flink field points to the next frame in the list (if enable)
|
|
* - The last frame in the list will have io_flink == NULL.
|
|
*
|
|
* An non-NULL d_buf of size CONFIG_NET_6LOWPAN_MTU + CONFIG_NET_GUARDSIZE
|
|
* must also be provided. The frame will be decompressed and placed in
|
|
* the d_buf. Fragmented packets will also be reassembled in the d_buf as
|
|
* they are received (meaning for the driver, that two packet buffers are
|
|
* required: One for reassembly of RX packets and one used for TX polling).
|
|
*
|
|
* After each frame is processed into d_buf, the IOB is deallocated. If
|
|
* reassembly is incomplete, the partially reassembled packet must be
|
|
* preserved by the radio network drvier and provided again when the next
|
|
* frame is received.
|
|
*
|
|
* When the packet in the d_buf is fully reassembled, it will be provided
|
|
* to the network as with any other received packet. d_len will be set
|
|
* the length of the uncompressed, reassembled packet.
|
|
*
|
|
* After the network processes the packet, d_len will be set to zero.
|
|
* Network logic may also decide to send a response to the packet. In
|
|
* that case, the outgoing network packet will be placed in d_buf and
|
|
* d_len will be set to a non-zero value. That case is handled by this
|
|
* function.
|
|
*
|
|
* If that case occurs, the packet will be converted to a list of
|
|
* compressed and possibly fragmented frames and provided to the MAC
|
|
* network driver via the req_data() method as with other TX operations.
|
|
*
|
|
* Input Parameters:
|
|
* radio The radio network driver interface.
|
|
* framelist - The head of an incoming list of frames. Normally this
|
|
* would be a single frame. A list may be provided if
|
|
* appropriate, however.
|
|
* metadata - Meta data characterizing the received packet. The specific
|
|
* type of this metadata is obfuscated and depends on the
|
|
* type of the radio driver. This could be be either
|
|
* (1) struct ieee802154_data_ind_s for an IEEE 802.15.4
|
|
* radio, or (2) struct pktradio_metadata_s for a non-standard
|
|
* packet radio.
|
|
*
|
|
* If there are multilple frames in the list, this metadata
|
|
* must apply to all of the frames in the list.
|
|
*
|
|
* Returned Value:
|
|
* Ok is returned on success; Othewise a negated errno value is returned.
|
|
*
|
|
****************************************************************************/
|
|
|
|
int sixlowpan_input(FAR struct sixlowpan_driver_s *radio,
|
|
FAR struct iob_s *framelist, FAR const void *metadata)
|
|
{
|
|
int ret = -EINVAL;
|
|
|
|
DEBUGASSERT(radio != NULL && framelist != NULL);
|
|
|
|
/* Verify that an frame has been provided. */
|
|
|
|
while (framelist != NULL)
|
|
{
|
|
FAR struct iob_s *iob;
|
|
|
|
/* Remove the IOB containing the frame from the device structure */
|
|
|
|
iob = framelist;
|
|
framelist = iob->io_flink;
|
|
|
|
sixlowpan_dumpbuffer("Incoming frame", iob->io_data, iob->io_len);
|
|
|
|
/* Process the frame, decompressing it into the packet buffer */
|
|
|
|
ret = sixlowpan_frame_process(radio, metadata, iob);
|
|
|
|
/* Free the IOB the held the consumed frame */
|
|
|
|
iob_free(iob);
|
|
|
|
/* Was the frame successfully processed? Is the packet in d_buf fully
|
|
* reassembled?
|
|
*/
|
|
|
|
if (ret == INPUT_COMPLETE)
|
|
{
|
|
/* Inject the uncompressed, reassembled packet into the network */
|
|
|
|
ret = sixlowpan_dispatch(radio);
|
|
if (ret >= 0)
|
|
{
|
|
/* Check if this resulted in a request to send an outgoing
|
|
* packet.
|
|
*/
|
|
|
|
if (radio->r_dev.d_len > 0)
|
|
{
|
|
FAR struct ipv6_hdr_s *ipv6hdr;
|
|
FAR uint8_t *buffer;
|
|
struct netdev_varaddr_s destmac;
|
|
size_t hdrlen;
|
|
size_t buflen;
|
|
|
|
/* The IPv6 header followed by TCP or UDP headers should
|
|
* lie at the beginning of d_buf since there is no link
|
|
* layer protocol header.
|
|
*/
|
|
|
|
ipv6hdr = IPv6BUF(&radio->r_dev);
|
|
|
|
/* Get the IEEE 802.15.4 MAC address of the destination.
|
|
* This assumes an encoding of the MAC address in the IPv6
|
|
* address.
|
|
*/
|
|
|
|
ret = sixlowpan_destaddrfromip(radio, ipv6hdr->destipaddr,
|
|
&destmac);
|
|
if (ret < 0)
|
|
{
|
|
nerr("ERROR: Failed to dest MAC address: %d\n", ret);
|
|
goto drop;
|
|
}
|
|
|
|
/* The data payload should follow the IPv6 header plus
|
|
* the protocol header.
|
|
*/
|
|
|
|
switch (ipv6hdr->proto)
|
|
{
|
|
#ifdef CONFIG_NET_TCP
|
|
case IP_PROTO_TCP:
|
|
{
|
|
FAR struct tcp_hdr_s *tcp = TCPBUF(&radio->r_dev);
|
|
uint16_t tcplen;
|
|
|
|
/* The TCP header length is encoded in the top 4 bits
|
|
* of the tcpoffset field (in units of 32-bit words).
|
|
*/
|
|
|
|
tcplen = ((uint16_t)tcp->tcpoffset >> 4) << 2;
|
|
hdrlen = IPv6_HDRLEN + tcplen;
|
|
}
|
|
break;
|
|
#endif
|
|
#ifdef CONFIG_NET_UDP
|
|
case IP_PROTO_UDP:
|
|
{
|
|
hdrlen = IPv6_HDRLEN + UDP_HDRLEN;
|
|
}
|
|
break;
|
|
#endif
|
|
#ifdef CONFIG_NET_ICMPv6
|
|
case IP_PROTO_ICMP6:
|
|
{
|
|
hdrlen = IPv6_HDRLEN + ICMPv6_HDRLEN;
|
|
}
|
|
break;
|
|
#endif
|
|
default:
|
|
{
|
|
nwarn("WARNING: Unsupported protoype: %u\n",
|
|
ipv6hdr->proto);
|
|
ret = -EPROTO;
|
|
goto drop;
|
|
}
|
|
}
|
|
|
|
if (hdrlen < radio->r_dev.d_len)
|
|
{
|
|
nwarn("WARNING: Packet to small: Have %u need >%u\n",
|
|
radio->r_dev.d_len, hdrlen);
|
|
ret = -ENOBUFS;
|
|
goto drop;
|
|
}
|
|
|
|
/* Convert the outgoing packet into a frame list. */
|
|
|
|
buffer = radio->r_dev.d_buf + hdrlen;
|
|
buflen = radio->r_dev.d_len - hdrlen;
|
|
|
|
ret = sixlowpan_queue_frames(radio, ipv6hdr, buffer, buflen,
|
|
&destmac);
|
|
drop:
|
|
radio->r_dev.d_len = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
#endif /* CONFIG_NET_6LOWPAN */
|