diff --git a/include/nuttx/net/sixlowpan.h b/include/nuttx/net/sixlowpan.h index 376fbf2d9c..0d403d25bb 100644 --- a/include/nuttx/net/sixlowpan.h +++ b/include/nuttx/net/sixlowpan.h @@ -323,6 +323,27 @@ struct rimeaddr_s * manage the fragmentation. 'struct ieee802154_driver_s' is cast * compatible with 'struct net_driver_s' when CONFIG_NET_MULTINIC is not * defined or when dev->d_lltype == NET_LL_IEEE802154. + * + * The IEEE802.15.4 MAC network driver has reponsibility for initializing + * this structure. In general, all fields must be set to NULL. In + * addtion: + * + * 1) i_panid must be set to identify the network. It may be set to 0xfff + * if the device is not associated. + * 2) i_dsn must be set to a random value. After that, it will be managed + * by the network. + * 3) i_nodeaddr must be set after the MAC is assigned an address. + * + * Frame Organization: + * + * Content Offset + * +----------------+ 0 + * | Frame Header | + * +----------------+ i_dataoffset + * | Data | + * +----------------+ i_framelen + * | Unused | + * +----------------+ CONFIG_NET_6LOWPAN_FRAMELEN */ struct ieee802154_driver_s @@ -344,7 +365,8 @@ struct ieee802154_driver_s * requesting new framesusing break-off fram buffers. That frame buffer * management must be controlled by the IEEE802.15.4 MAC driver. * - * Driver provied frame buffers should be 16-bit aligned. + * Driver provided frame buffers should of size CONFIG_NET_6LOWPAN_FRAMELEN + * and should be 16-bit aligned. */ FAR uint8_t *i_frame; @@ -360,6 +382,31 @@ struct ieee802154_driver_s uint16_t i_framelen; + /* i_panid. The PAN ID is 16-bit number that identifies the network. It + * must be unique to differentiate a network. All the nodes in the same + * network should have the same PAN ID. This value must be provided to + * the network from the IEEE802.15.4 MAC driver. + * + * If this value is 0xffff, the device is not associated. + */ + + uint16_t i_panid; + + /* i_node_addr. The address assigned to this node. */ + + struct rimeaddr_s i_nodeaddr; + + /* i_dsn. The sequence number in the range 0x00-0xff added to the + * transmitted data or MAC command frame. The default is a random value + * within that range. + * + * This field must be initialized to a random number by the IEEE802.15.4 + * MAC driver. It sill be subsequently incremented on each frame by the + * network logic. + */ + + uint8_t i_dsn; + /* The following fields are device-specific metadata used by the 6loWPAN * stack and should not be modified by the IEEE802.15.4 MAC network drvier. */ @@ -385,9 +432,9 @@ struct ieee802154_driver_s uint8_t i_rime_hdrlen; - /* Next available pointer into header */ + /* Offset first available byte for the payload after header region. */ - uint8_t i_hdrptr; + uint8_t i_dataoffset; /* Packet buffer metadata: Attributes and addresses */ diff --git a/net/sixlowpan/Kconfig b/net/sixlowpan/Kconfig index 7031f21e62..bbbdeb1b13 100644 --- a/net/sixlowpan/Kconfig +++ b/net/sixlowpan/Kconfig @@ -136,7 +136,7 @@ config NET_6LOWPAN_RIMEADDR_SIZE ---help--- Only the values 2 and 8 are supported -config NET_SIXLOWPAN_MAXAGE +config NET_6LOWPAN_MAXAGE int "Packet reassembly timeout" default 20 ---help--- @@ -150,11 +150,11 @@ config NET_6LOWPAN_MAX_MACTRANSMITS layer should resend packets if no link-layer ACK wasreceived. This only makes sense with the csma_driver. -config NET_SIXLOWPAN_MAXPAYLOAD +config NET_6LOWPAN_MAXPAYLOAD int "Max packet size" default 102 ---help--- - CONFIG_NET_SIXLOWPAN_MAXPAYLOAD specifies the maximum size of packets + NET_6LOWPAN_MAXPAYLOAD specifies the maximum size of packets before they get fragmented. The default is 127 bytes (the maximum size of a 802.15.4 frame) - 25 bytes (for the 802.15.4 MAClayer header). This can be increased for systems with larger packet sizes. diff --git a/net/sixlowpan/Make.defs b/net/sixlowpan/Make.defs index 68b1ec5ef9..e0370185e6 100644 --- a/net/sixlowpan/Make.defs +++ b/net/sixlowpan/Make.defs @@ -40,7 +40,7 @@ ifeq ($(CONFIG_NET_6LOWPAN),y) # Include IEEE 802.15.4 file in the build NET_CSRCS += sixlowpan_initialize.c sixlowpan_globals.c sixlowpan_utils.c -NET_CSRCS += sixlowpan_input.c sixlowpan_send.c +NET_CSRCS += sixlowpan_input.c sixlowpan_send.c sixlowpan_framer.c NET_CSRCS += sixlowpan_compressor.c ifeq ($(CONFIG_NET_TCP),y) diff --git a/net/sixlowpan/sixlowpan_framer.c b/net/sixlowpan/sixlowpan_framer.c new file mode 100644 index 0000000000..611e204a9f --- /dev/null +++ b/net/sixlowpan/sixlowpan_framer.c @@ -0,0 +1,606 @@ +/**************************************************************************** + * net/sixlowpan/sixlowpan_framer.c + * + * Copyright (C) 2017 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Derives from Contiki: + * + * Copyright (c) 2008, Swedish Institute of Computer Science. + * All rights reserved. + * Authors: Adam Dunkels + * Nicolas Tsiftes + * Niclas Finne + * Mathilde Durvy + * Julien Abeille + * Joakim Eriksson + * Joel Hoglund + * + * 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 + +#include +#include +#include +#include + +#include "nuttx/net/net.h" +#include "nuttx/net/sixlowpan.h" + +#include "sixlowpan/sixlowpan_internal.h" + +#ifdef CONFIG_NET_6LOWPAN + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* Structure that contains the lengths of the various addressing and + * security fields in the 802.15.4 header. + */ + +struct field_length_s +{ + uint8_t dest_pid_len; /**< Length (in bytes) of destination PAN ID field */ + uint8_t dest_addr_len; /**< Length (in bytes) of destination address field */ + uint8_t src_pid_len; /**< Length (in bytes) of source PAN ID field */ + uint8_t src_addr_len; /**< Length (in bytes) of source address field */ + uint8_t aux_sec_len; /**< Length (in bytes) of aux security header field */ +}; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: sixlowpan_addrlen + * + * Description: + * Return the address length associated with a 2-bit address mode + * + * Input parameters: + * addrmode - The address mode + * + * Returned Value: + * The address length associated with the address mode. + * + ****************************************************************************/ + +static inline uint8_t sixlowpan_addrlen(uint8_t addrmode) +{ + switch (addrmode) + { + case FRAME802154_SHORTADDRMODE: /* 16-bit address */ + return 2; + case FRAME802154_LONGADDRMODE: /* 64-bit address */ + return 8; + default: + return 0; + } +} + +/**************************************************************************** + * Function: sixlowpan_isbroadcast + * + * Description: + * Return the address length associated with a 2-bit address mode + * + * Input parameters: + * addrmode - The address mode + * + * Returned Value: + * The address length associated with the address mode. + * + ****************************************************************************/ + +static bool sixlowpan_isbroadcast(uint8_t mode, FAR uint8_t *addr) +{ + int i = ((mode == FRAME802154_SHORTADDRMODE) ? 2 : 8); + + while (i-- > 0) + { + if (addr[i] != 0xff) + { + return false; + } + } + + return true; +} + +/**************************************************************************** + * Function: sixlowpan_addrnull + * + * Description: + * If the output address is NULL in the Rime buf, then it is broadcast + * on the 802.15.4 network. + * + * Input parameters: + * addrmode - The address mode + * + * Returned Value: + * The address length associated with the address mode. + * + ****************************************************************************/ + +static bool sixlowpan_addrnull(FAR uint8_t *addr) +{ +#if CONFIG_NET_6LOWPAN_RIMEADDR_SIZE == 2 + int i = 2; +#else + int i = 8; +#endif + + while (i-- > 0) + { + if (addr[i] != 0x00) + { + return false; + } + } + + return true; +} + + +/**************************************************************************** + * Function: sixlowpan_fieldlengths + * + * Description: + * Return the lengths associated fields of the IEEE802.15.4 header. + * + * Input parameters: + * finfo - IEEE802.15.4 header info (input) + * flen - Field length info (output) + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void sixlowpan_fieldlengths(FAR struct frame802154_s *finfo, + FAR struct field_length_s *flen) +{ + /* Initialize to all zero */ + + memset(flen, 0, sizeof(struct field_length_s)); + + /* Determine lengths of each field based on fcf and other args */ + + if ((finfo->fcf.dest_addr_mode & 3) != 0) + { + flen->dest_pid_len = 2; + } + + if ((finfo->fcf.src_addr_mode & 3) != 0) + { + flen->src_pid_len = 2; + } + + /* Set PAN ID compression bit if src pan id matches dest pan id. */ + + if ((finfo->fcf.dest_addr_mode & 3) != 0 && + (finfo->fcf.src_addr_mode & 3) != 0 && + finfo->src_pid == finfo->dest_pid) + { + finfo->fcf.panid_compression = 1; + + /* Compressed header, only do dest pid */ + /* flen->src_pid_len = 0; */ + } + + /* Determine address lengths */ + + flen->dest_addr_len = sixlowpan_addrlen(finfo->fcf.dest_addr_mode & 3); + flen->src_addr_len = sixlowpan_addrlen(finfo->fcf.src_addr_mode & 3); + + /* Aux security header */ + +#if 0 /* TODO Aux security header not yet implemented */ + if ((finfo->fcf.security_enabled & 1) != 0) + { + switch(finfo->aux_hdr.security_control.key_id_mode) + { + case 0: + flen->aux_sec_len = 5; /* Minimum value */ + break; + + case 1: + flen->aux_sec_len = 6; + break; + + case 2: + flen->aux_sec_len = 10; + break; + + case 3: + flen->aux_sec_len = 14; + break; + + default: + break; + } + } +#endif +} + +/**************************************************************************** + * Function: sixlowpan_fieldlengths + * + * Description: + * Return the lengths associated fields of the IEEE802.15.4 header. + * + * Input parameters: + * finfo - IEEE802.15.4 header info (input) + * flen - Field length info (output) + * + * Returned Value: + * None + * + ****************************************************************************/ + +static int sixlowpan_flen_hdrlen(FAR const struct field_length_s *flen) +{ + return 3 + flen->dest_pid_len + flen->dest_addr_len + + flen->src_pid_len + flen->src_addr_len + flen->aux_sec_len; +} + +/**************************************************************************** + * Function: sixlowpan_802154_hdrlen + * + * Description: + * Calculates the length of the frame header. This function is meant to + * be called by a higher level function, that interfaces to a MAC. + * + * Input parameters: + * finfo - IEEE802.15.4 header info that specifies the frame to send. + * + * Returned Value: + * The length of the frame header. + * + ****************************************************************************/ + +static int sixlowpan_802154_hdrlen(FAR struct frame802154_s *finfo) +{ + struct field_length_s flen; + + sixlowpan_fieldlengths(finfo, &flen); + return sixlowpan_flen_hdrlen(&flen); +} + +/**************************************************************************** + * Function: sixlowpan_setup_params + * + * Description: + * Configure frame parmeters structure. + * + * Input parameters: + * ieee - A reference IEEE802.15.4 MAC network device structure. + * params - Where to put the parmeters + * dest_panid - PAN ID of the destination. May be 0xffff if the destination + * is not associated. + * + * Returned Value: + * None. + * + ****************************************************************************/ + +static void sixlowpan_setup_params(FAR struct ieee802154_driver_s *ieee, + FAR struct frame802154_s *params, + uint16_t dest_panid) +{ + bool rcvrnull; + + /* Initialize all prameters to all zero */ + + memset(¶ms, 0, sizeof(params)); + + /* Reset to an empty frame */ + + ieee->i_framelen = 0; + ieee->i_dataoffset = 0; + + /* Build the FCF (Only non-zero elements need to be initialized). */ + + params->fcf.frame_type = FRAME802154_DATAFRAME; + params->fcf.frame_pending = ieee->i_pktattrs[PACKETBUF_ATTR_PENDING]; + + /* If the output address is NULL in the Rime buf, then it is broadcast + * on the 802.15.4 network. + */ + + rcvrnull = sixlowpan_addrnull(ieee->i_pktaddrs[PACKETBUF_ADDR_RECEIVER].u8); + if (rcvrnull) + { + params->fcf.ack_required = ieee->i_pktattrs[PACKETBUF_ATTR_MAC_ACK]; + } + + /* Insert IEEE 802.15.4 (2003) version bit. */ + + params->fcf.frame_version = FRAME802154_IEEE802154_2003; + + /* Increment and set the data sequence number. */ + + if (ieee->i_pktattrs[PACKETBUF_ATTR_MAC_SEQNO] != 0) + { + params->seq = ieee->i_pktattrs[PACKETBUF_ATTR_MAC_SEQNO]; + } + else + { + params->seq = ieee->i_dsn++; + ieee->i_pktattrs[PACKETBUF_ATTR_MAC_SEQNO] = params->seq; + } + + /* Complete the addressing fields. */ + /* Set the source and destination PAN ID. */ + + params->src_pid = ieee->i_panid; + params->dest_pid = dest_panid; + + /* If the output address is NULL in the Rime buf, then it is broadcast + * on the 802.15.4 network. + */ + + if (rcvrnull) + { + /* Broadcast requires short address mode. */ + + params->fcf.dest_addr_mode = FRAME802154_SHORTADDRMODE; + params->dest_addr[0] = 0xff; + params->dest_addr[1] = 0xff; + } + else + { + /* Copy the destination address */ + + rimeaddr_copy((struct rimeaddr_s *)¶ms->dest_addr, + ieee->i_pktaddrs[PACKETBUF_ADDR_RECEIVER].u8); + + /* Use short address mode if so configured */ + +#if CONFIG_NET_6LOWPAN_RIMEADDR_SIZE == 2 + params->fcf.dest_addr_mode = FRAME802154_SHORTADDRMODE; +#else + params->fcf.dest_addr_mode = FRAME802154_LONGADDRMODE; +#endif + } + + /* Set the source address to the node address assigned to the device */ + + rimeaddr_copy((struct rimeaddr_s *)¶ms->src_addr, &ieee->i_nodeaddr.u8); + + /* Configure the payload address and length */ + + params->payload = FRAME_DATA_START(ieee); + params->payload_len = FRAME_DATA_SIZE(ieee); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: sixlowpan_hdrlen + * + * Description: + * This function is before the first frame has been sent in order to + * determine what the size of the IEEE802.15.4 header will be. No frame + * buffer is required to make this determination. + * + * Input parameters: + * ieee - A reference IEEE802.15.4 MAC network device structure. + * dest_panid - PAN ID of the destination. May be 0xffff if the destination + * is not associated. + * + * Returned Value: + * The frame header length is returnd on success; otherwise, a negated + * errno value is return on failure. + * + ****************************************************************************/ + +int sixlowpan_hdrlen(FAR struct ieee802154_driver_s *ieee, + uint16_t dest_panid) +{ + struct frame802154_s params; + + /* Set up the frame parameters */ + + sixlowpan_setup_params(ieee, ¶ms, dest_panid); + + /* Return the length of the header */ + + return sixlowpan_802154_hdrlen(¶ms); +} + +/**************************************************************************** + * Function: sixlowpan_802154_framecreate + * + * Description: + * Creates a frame for transmission over the air. This function is meant + * to be called by a higher level function, that interfaces to a MAC. + * + * Input parameters: + * finfo - Pointer to struct EEE802.15.4 header structure that specifies + * the frame to send. + * buf - Pointer to the buffer to use for the frame. + * buflen - The length of the buffer to use for the frame. + * finfo - I that specifies the frame to send. + * + * Returned Value: + * The length of the frame header or 0 if there was insufficient space in + * the buffer for the frame headers. + * + ****************************************************************************/ + +int sixlowpan_802154_framecreate(FAR struct frame802154_s *finfo, + FAR uint8_t *buf, int buflen) +{ + struct field_length_s flen; + uint8_t pos; + int hdrlen; + int i; + + sixlowpan_fieldlengths(finfo, &flen); + + hdrlen = sixlowpan_flen_hdrlen(&flen); + if (hdrlen > buflen) + { + /* Too little space for headers. */ + + return 0; + } + + /* OK, now we have field lengths. Time to actually construct + * the outgoing frame, and store it in the provided buffer + */ + + buf[0] = (finfo->fcf.frame_type & 7) | + ((finfo->fcf.security_enabled & 1) << 3) | + ((finfo->fcf.frame_pending & 1) << 4) | + ((finfo->fcf.ack_required & 1) << 5) | + ((finfo->fcf.panid_compression & 1) << 6); + buf[1] = ((finfo->fcf.dest_addr_mode & 3) << 2) | + ((finfo->fcf.frame_version & 3) << 4) | + ((finfo->fcf.src_addr_mode & 3) << 6); + + /* Sequence number */ + + buf[2] = finfo->seq; + pos = 3; + + /* Destination PAN ID */ + + if (flen.dest_pid_len == 2) + { + buf[pos++] = finfo->dest_pid & 0xff; + buf[pos++] = (finfo->dest_pid >> 8) & 0xff; + } + + /* Destination address */ + + for (i = flen.dest_addr_len; i > 0; i--) + { + buf[pos++] = finfo->dest_addr[i - 1]; + } + + /* Source PAN ID */ + + if (flen.src_pid_len == 2) + { + buf[pos++] = finfo->src_pid & 0xff; + buf[pos++] = (finfo->src_pid >> 8) & 0xff; + } + + /* Source address */ + + for (i = flen.src_addr_len; i > 0; i--) + { + buf[pos++] = finfo->src_addr[i - 1]; + } + + /* Aux header */ + +#if 0 /* TODO Aux security header not yet implemented */ + if (flen.aux_sec_len) + { + pos += flen.aux_sec_len; + } +#endif + + DEBUGASSERT(pos == hdrlen); + return (int)pos; +} + +/**************************************************************************** + * Function: sixlowpan_framecreate + * + * Description: + * This function is called after the IEEE802.15.4 MAC driver polls for + * TX data. It creates the IEEE802.15.4 header in the frame buffer. + * + * Input parameters: + * ieee - A reference IEEE802.15.4 MAC network device structure. + * dest_panid - PAN ID of the destination. May be 0xffff if the destination + * is not associated. + * + * Returned Value: + * The frame header length is returnd on success; otherwise, a negated + * errno value is return on failure. + * + ****************************************************************************/ + +int sixlowpan_framecreate(FAR struct ieee802154_driver_s *ieee, + uint16_t dest_panid) +{ + struct frame802154_s params; + int len; + int ret; + + /* Set up the frame parameters */ + + sixlowpan_setup_params(ieee, ¶ms, dest_panid); + + /* Get the length of the header */ + + len = sixlowpan_802154_hdrlen(¶ms); + + /* Allocate space for the header in the frame buffer */ + + ret = sixlowpan_frame_hdralloc(ieee, len); + if (ret < 0) + { + wlerr("ERROR: Header too large: %u\n", len); + return ret; + } + + /* Then create the frame */ + + sixlowpan_802154_framecreate(¶ms, FRAME_HDR_START(ieee), len); + + wlinfo("Frame type: %02x Data len: %d %u (%u)\n", + params.fcf.frame_type, len, FRAME_DATA_SIZE(ieee), + FRAME_SIZE(ieee)); +#if CONFIG_NET_6LOWPAN_RIMEADDR_SIZE == 2 + wlinfo("Dest address: %02x:%02x\n", + params.dest_addr[0], params.dest_addr[1]); +#else + wlinfo("Dest address: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", + params.dest_addr[0], params.dest_addr[1], params.dest_addr[2], + params.dest_addr[3], params.dest_addr[4], params.dest_addr[5], + params.dest_addr[6], params.dest_addr[7]); +#endif + + return len; +} + +#endif /* CONFIG_NET_6LOWPAN */ diff --git a/net/sixlowpan/sixlowpan_hc06.c b/net/sixlowpan/sixlowpan_hc06.c index b270413143..534cb1adbf 100644 --- a/net/sixlowpan/sixlowpan_hc06.c +++ b/net/sixlowpan/sixlowpan_hc06.c @@ -20,6 +20,7 @@ * 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 @@ -44,7 +45,7 @@ ****************************************************************************/ /* FOR HC-06 COMPLIANCE TODO: - * + * * -Add compression options to UDP, currently only supports * both ports compressed or both ports elided * -Verify TC/FL compression works diff --git a/net/sixlowpan/sixlowpan_internal.h b/net/sixlowpan/sixlowpan_internal.h index 453d340dba..6828c14128 100644 --- a/net/sixlowpan/sixlowpan_internal.h +++ b/net/sixlowpan/sixlowpan_internal.h @@ -4,9 +4,28 @@ * Copyright (C) 2017 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * + * Parts of this file derive from Contiki: + * + * Copyright (c) 2008, Swedish Institute of Computer Science + * All rights reserved. + * + * Additional fixes for AVR contributed by: + * Colin O'Flynn coflynn@newae.com + * Eric Gnoske egnoske@gmail.com + * Blake Leverett bleverett@gmail.com + * Mike Vidales mavida404@gmail.com + * Kevin Brown kbrown3@uccs.edu + * Nate Bohlmann nate@elfwerks.com + * + * Additional fixes for MSP430 contributed by: + * Joakim Eriksson + * Niclas Finne + * Nicolas Tsiftes + * + * All rights reserved. + * * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: + * 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. @@ -14,23 +33,21 @@ * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. - * 3. Neither the name NuttX nor the names of its contributors may be - * used to endorse or promote products derived from this software - * without specific prior written permission. + * 3. Neither the name of the copyright holders nor the names of + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 - * COPYRIGHT OWNER 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 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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. - * ****************************************************************************/ #ifndef _NET_SIXLOWPAN_SIXLOWPAN_INTERNAL_H @@ -64,11 +81,64 @@ #define rimeaddr_cmp(addr1,addr2) \ (memcmp(addr1, addr2, CONFIG_NET_6LOWPAN_RIMEADDR_SIZE) == 0) +/* Frame buffer helpers */ + +#define FRAME_RESET(ieee) \ + do \ + { \ + (ieee)->i_dataoffset = 0; \ + (ieee)->i_framelen = 0; \ + } \ + while (0) + +#define FRAME_HDR_START(ieee) \ + ((ieee)->i_frame) +#define FRAME_HDR_SIZE(ieee) \ + ((ieee)->i_dataoffset) + +#define FRAME_DATA_START(ieee) \ + ((FAR uint8_t *)((ieee)->i_frame) + (ieee)->i_dataoffset) +#define FRAME_DATA_SIZE(ieee) \ + ((ieee)->i_framelen - (ieee)->i_dataoffset) + +#define FRAME_REMAINING(ieee) \ + (CONFIG_NET_6LOWPAN_FRAMELEN - (ieee)->i_framelen) +#define FRAME_SIZE(ieee) \ + ((ieee)->i_framelen) + +/* These are some definitions of element values used in the FCF. See the + * IEEE802.15.4 spec for details. + */ + +#define FRAME802154_BEACONFRAME 0x00 +#define FRAME802154_DATAFRAME 0x01 +#define FRAME802154_ACKFRAME 0x02 +#define FRAME802154_CMDFRAME 0x03 + +#define FRAME802154_BEACONREQ 0x07 + +#define FRAME802154_IEEERESERVED 0x00 +#define FRAME802154_NOADDR 0x00 /* Only valid for ACK or Beacon frames */ +#define FRAME802154_SHORTADDRMODE 0x02 +#define FRAME802154_LONGADDRMODE 0x03 + +#define FRAME802154_NOBEACONS 0x0f + +#define FRAME802154_BROADCASTADDR 0xffff +#define FRAME802154_BROADCASTPANDID 0xffff + +#define FRAME802154_IEEE802154_2003 0x00 +#define FRAME802154_IEEE802154_2006 0x01 + +#define FRAME802154_SECURITY_LEVEL_NONE 0 +#define FRAME802154_SECURITY_LEVEL_128 3 + /**************************************************************************** * Public Types ****************************************************************************/ -/* IPv6 + TCP header */ +/* IPv^ TCP/UDP Definitions *************************************************/ +/* IPv6 + TCP header. Cast compatible based on IPv6 protocol field. */ struct ipv6tcp_hdr_s { @@ -92,6 +162,71 @@ struct ipv6icmp_hdr_s struct icmpv6_iphdr_s icmp; }; +/* IEEE802.15.4 Frame Definitions *******************************************/ +/* The IEEE 802.15.4 frame has a number of constant/fixed fields that can be + * counted to make frame construction and max payload calculations easier. + * These include: + * + * 1. FCF - 2 bytes - Fixed + * 2. Sequence number - 1 byte - Fixed + * 3. Addressing fields - 4 - 20 bytes - Variable + * 4. Aux security header - 0 - 14 bytes - Variable + * 5. CRC - 2 bytes - Fixed +*/ + +/* Defines the bitfields of the frame control field (FCF). */ + +struct frame802154_fcf_s +{ + uint8_t frame_type; /* 3 bit. Frame type field, see 802.15.4 */ + uint8_t security_enabled; /* 1 bit. True if security is used in this frame */ + uint8_t frame_pending; /* 1 bit. True if sender has more data to send */ + uint8_t ack_required; /* 1 bit. Is an ack frame required? */ + uint8_t panid_compression; /* 1 bit. Is this a compressed header? */ + /* 3 bit. Unused bits */ + uint8_t dest_addr_mode; /* 2 bit. Destination address mode, see 802.15.4 */ + uint8_t frame_version; /* 2 bit. 802.15.4 frame version */ + uint8_t src_addr_mode; /* 2 bit. Source address mode, see 802.15.4 */ +}; + +/* 802.15.4 security control bitfield. See section 7.6.2.2.1 in 802.15.4 + * specification. + */ + +struct frame802154_scf_s +{ + uint8_t security_level; /* 3 bit. security level */ + uint8_t key_id_mode; /* 2 bit. Key identifier mode */ + uint8_t reserved; /* 3 bit. Reserved bits */ +}; + +/* 802.15.4 Aux security header */ + +struct frame802154_aux_hdr_s +{ + struct frame802154_scf_s security_control; /* Security control bitfield */ + uint32_t frame_counter; /* Frame counter, used for security */ + uint8_t key[9]; /* The key itself, or an index to the key */ +}; + +/* Parameters used by the frame802154_create() function. These parameters + * are used in the 802.15.4 frame header. See the 802.15.4 specification + * for details. + */ + +struct frame802154_s +{ + struct frame802154_fcf_s fcf; /* Frame control field */ + uint8_t seq; /* Sequence number */ + uint16_t dest_pid; /* Destination PAN ID */ + uint8_t dest_addr[8]; /* Destination address */ + uint16_t src_pid; /* Source PAN ID */ + uint8_t src_addr[8]; /* Source address */ + struct frame802154_aux_hdr_s aux_hdr; /* Aux security header */ + uint8_t *payload; /* Pointer to 802.15.4 frame payload */ + uint8_t payload_len; /* Length of payload field */ +}; + /**************************************************************************** * Public Data ****************************************************************************/ @@ -157,6 +292,49 @@ int sixlowpan_send(FAR struct net_driver_s *dev, FAR const struct ipv6_hdr_s *ipv6, FAR const void *buf, size_t len, FAR const struct rimeaddr_s *raddr); +/**************************************************************************** + * Function: sixlowpan_hdrlen + * + * Description: + * This function is before the first frame has been sent in order to + * determine what the size of the IEEE802.15.4 header will be. No frame + * buffer is required to make this determination. + * + * Input parameters: + * ieee - A reference IEEE802.15.4 MAC network device structure. + * dest_panid - PAN ID of the destination. May be 0xffff if the destination + * is not associated. + * + * Returned Value: + * The frame header length is returnd on success; otherwise, a negated + * errno value is return on failure. + * + ****************************************************************************/ + +int sixlowpan_hdrlen(FAR struct ieee802154_driver_s *ieee, + uint16_t dest_panid); + +/**************************************************************************** + * Function: sixlowpan_framecreate + * + * Description: + * This function is called after the IEEE802.15.4 MAC driver polls for + * TX data. It creates the IEEE802.15.4 header in the frame buffer. + * + * Input parameters: + * ieee - A reference IEEE802.15.4 MAC network device structure. + * dest_panid - PAN ID of the destination. May be 0xffff if the destination + * is not associated. + * + * Returned Value: + * The frame header length is returnd on success; otherwise, a negated + * errno value is return on failure. + * + ****************************************************************************/ + +int sixlowpan_framecreate(FAR struct ieee802154_driver_s *ieee, + uint16_t dest_panid); + /**************************************************************************** * Name: sixlowpan_hc06_initialize * @@ -293,15 +471,15 @@ void sixlowpan_uncompresshdr_hc1(FAR struct net_driver_s *dev, #endif /**************************************************************************** - * Name: sixlowpan_pktbuf_reset + * Name: sixlowpan_frame_hdralloc * * Description: - * Reset all attributes and addresses in the packet buffer metadata in the - * provided IEEE802.15.4 MAC driver structure. + * Allocate space for a header within the frame buffer (i_frame). * ****************************************************************************/ -void sixlowpan_pktbuf_reset(FAR struct ieee802154_driver_s *ieee); +int sixlowpan_frame_hdralloc(FAR struct ieee802154_driver_s *ieee, + int size); #endif /* CONFIG_NET_6LOWPAN */ #endif /* _NET_SIXLOWPAN_SIXLOWPAN_INTERNAL_H */ diff --git a/net/sixlowpan/sixlowpan_send.c b/net/sixlowpan/sixlowpan_send.c index d204e5eeca..9a7b0095cd 100644 --- a/net/sixlowpan/sixlowpan_send.c +++ b/net/sixlowpan/sixlowpan_send.c @@ -4,6 +4,18 @@ * Copyright (C) 2017 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * + * Parts of this file derive from Contiki: + * + * Copyright (c) 2008, Swedish Institute of Computer Science. + * All rights reserved. + * Authors: Adam Dunkels + * Nicolas Tsiftes + * Niclas Finne + * Mathilde Durvy + * Julien Abeille + * Joakim Eriksson + * Joel Hoglund + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -11,25 +23,23 @@ * 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 NuttX nor the names of its contributors may be - * used to endorse or promote products derived from this software + * 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 COPYRIGHT HOLDERS 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 - * COPYRIGHT OWNER 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. + * 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. * ****************************************************************************/ @@ -68,6 +78,7 @@ * * Description: * Setup some packet buffer attributes + * * Input Parameters: * ieee - Pointer to IEEE802.15.4 MAC driver structure. * ipv6 - Pointer to the IPv6 header to "compress" @@ -158,6 +169,42 @@ static void sixlowpan_compress_ipv6hdr(FAR struct ieee802154_driver_s *ieee, ieee->i_uncomp_hdrlen += IPv6_HDRLEN; } +/**************************************************************************** + * Name: sixlowpan_send_frame + * + * Description: + * Send one frame when the IEEE802.15.4 MAC device next polls. + * + * Input Parameters: + * ieee - Pointer to IEEE802.15.4 MAC driver structure. + * ipv6 - Pointer to the IPv6 header to "compress" + * + * Returned Value: + * None + * + ****************************************************************************/ + +static int sixlowpan_send_frame(FAR struct ieee802154_driver_s *ieee) +{ + /* Prepare the frame */ +#warning Missing logic + /* Set up for the TX poll */ + /* When polled, then we need to call sixlowpan_framecreate() to create the + * frame and copy the payload data into the frame. + */ +#if 0 /* Just some notes of what needs to be done in interrupt handler */ + framer_hdrlen = sixlowpan_createframe(ieee, ieee->i_panid); + memcpy(ieee->i_rimeptr + ieee->i_rime_hdrlen, (uint8_t *)ipv6 + ieee->i_uncomp_hdrlen, len - ieee->i_uncomp_hdrlen); + dev->i_framelen = len - ieee->i_uncomp_hdrlen + ieee->i_rime_hdrlen; +#endif +#warning Missing logic + /* Notify the IEEE802.14.5 MAC driver that we have data to be sent */ +#warning Missing logic + /* Wait for the transfer to complete */ +#warning Missing logic + return -ENOSYS; +} + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -203,29 +250,49 @@ int sixlowpan_send(FAR struct net_driver_s *dev, int framer_hdrlen; /* Framer header length */ struct rimeaddr_s dest; /* The MAC address of the destination of the packet */ - uint16_t outlen; /* Number of bytes processed. */ + uint16_t outlen = 0; /* Number of bytes processed. */ /* Initialize device-specific data */ + FRAME_RESET(ieee); ieee->i_uncomp_hdrlen = 0; ieee->i_rime_hdrlen = 0; + /* REVISIT: Do I need this rimeptr? */ + ieee->i_rimeptr = &dev->d_buf[PACKETBUF_HDR_SIZE]; /* Reset rime buffer, packet buffer metatadata */ - sixlowpan_pktbuf_reset(ieee); + memset(ieee->i_pktattrs, 0, PACKETBUF_NUM_ATTRS * sizeof(uint16_t)); + memset(ieee->i_pktaddrs, 0, PACKETBUF_NUM_ADDRS * sizeof(struct rimeaddr_s)); - ieee->i_rimeptr = &dev->d_buf[PACKETBUF_HDR_SIZE]; - ieee->i_pktattrs[PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS] = CONFIG_NET_6LOWPAN_MAX_MACTRANSMITS; + ieee->i_pktattrs[PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS] = + CONFIG_NET_6LOWPAN_MAX_MACTRANSMITS; #ifdef CONFIG_NET_6LOWPAN_SNIFFER if (g_sixlowpan_sniffer != NULL) { + /* Reset rime buffer, packet buffer metatadata */ + + memset(ieee->i_pktattrs, 0, PACKETBUF_NUM_ATTRS * sizeof(uint16_t)); + memset(ieee->i_pktaddrs, 0, PACKETBUF_NUM_ADDRS * sizeof(struct rimeaddr_s)); + + ieee->i_pktattrs[PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS] = + CONFIG_NET_6LOWPAN_MAX_MACTRANSMITS; + /* Call the attribution when the callback comes, but set attributes here */ sixlowpan_set_pktattrs(ieee, ipv6); } #endif + /* Reset rime buffer, packet buffer metatadata */ + + memset(ieee->i_pktattrs, 0, PACKETBUF_NUM_ATTRS * sizeof(uint16_t)); + memset(ieee->i_pktaddrs, 0, PACKETBUF_NUM_ADDRS * sizeof(struct rimeaddr_s)); + + ieee->i_pktattrs[PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS] = + CONFIG_NET_6LOWPAN_MAX_MACTRANSMITS; + /* Set stream mode for all TCP packets, except FIN packets. */ if (ipv6->proto == IP_PROTO_TCP) @@ -281,8 +348,94 @@ int sixlowpan_send(FAR struct net_driver_s *dev, ninfo("Header of len %d\n", ieee->i_rime_hdrlen); - /* Calculate frame header length. */ -#warning Missing logic + rimeaddr_copy(&ieee->i_pktaddrs[PACKETBUF_ADDR_RECEIVER], &dest); + + /* Pre-calculate frame header length. */ + + framer_hdrlen = sixlowpan_hdrlen(ieee, ieee->i_panid); + if (framer_hdrlen < 0) + { + /* Failed to determine the size of the header failed. */ + + nerr("ERROR: sixlowpan_framecreate() failed: %d\n", framer_hdrlen); + return framer_hdrlen; + } + + /* Check if we need to fragment the packet into several frames */ + + if ((int)len - (int)ieee->i_uncomp_hdrlen > + (int)CONFIG_NET_6LOWPAN_MAXPAYLOAD - framer_hdrlen - + (int)ieee->i_rime_hdrlen) + { +#if CONFIG_NET_6LOWPAN_FRAG + /* 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("Fragmentation sending packet len %d\n", len); + + /* Create 1st Fragment */ +# warning Missing logic + + /* Move HC1/HC06/IPv6 header */ +# warning Missing logic + + /* FRAG1 dispatch + header + * Note that the length is in units of 8 bytes + */ +# warning Missing logic + + /* Copy payload and send */ +# warning Missing logic + + /* Check TX result. */ +# warning Missing logic + + /* Set outlen to what we already sent from the IP payload */ +# warning Missing logic + + /* Create following fragments + * Datagram tag is already in the buffer, we need to set the + * FRAGN dispatch and for each fragment, the offset + */ +# warning Missing logic + + while (outlen < len) + { + /* Copy payload and send */ +# warning Missing logic + + ninfo("sixlowpan output: fragment offset %d, len %d, tag %d\n", + outlen >> 3, g_rime_payloadlen, g_mytag); + +# warning Missing logic + sixlowpan_send_frame(ieee); + + /* Check tx result. */ +# warning Missing logic + } + + return -ENOSYS; +#else + nerr("ERROR: Packet too large: %d\n", len); + 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. + */ + + return sixlowpan_send_frame(ieee); + } + return -ENOSYS; } diff --git a/net/sixlowpan/sixlowpan_utils.c b/net/sixlowpan/sixlowpan_utils.c index 5df1b3439c..a12394407f 100644 --- a/net/sixlowpan/sixlowpan_utils.c +++ b/net/sixlowpan/sixlowpan_utils.c @@ -44,6 +44,17 @@ * SUCH DAMAGE. * ****************************************************************************/ +/* Frame Organization: + * + * Content Offset + * +----------------+ 0 + * | Frame Header | + * +----------------+ i_dataoffset + * | Data | + * +----------------+ i_framelen + * | Unused | + * +----------------+ CONFIG_NET_6LOWPAN_FRAMELEN + */ /**************************************************************************** * Included Files @@ -52,6 +63,7 @@ #include #include +#include #include "nuttx/net/sixlowpan.h" @@ -64,22 +76,24 @@ ****************************************************************************/ /**************************************************************************** - * Name: sixlowpan_pktbuf_reset + * Name: sixlowpan_frame_hdralloc * * Description: - * Reset all attributes and addresses in the packet buffer metadata in the - * provided IEEE802.15.4 MAC driver structure. + * Allocate space for a header within the packet buffer (dev->d_buf). * ****************************************************************************/ -void sixlowpan_pktbuf_reset(FAR struct ieee802154_driver_s *ieee) +int sixlowpan_frame_hdralloc(FAR struct ieee802154_driver_s *ieee, + int size) { - ieee->i_dev.d_len = 0; - ieee->i_rimeptr = 0; - ieee->i_hdrptr = PACKETBUF_HDR_SIZE; + if (size <= FRAME_REMAINING(ieee)) + { + ieee->i_dataoffset += size; + ieee->i_framelen += size; + return OK; + } - memset(ieee->i_pktattrs, 0, PACKETBUF_NUM_ATTRS * sizeof(uint16_t)); - memset(ieee->i_pktaddrs, 0, PACKETBUF_NUM_ADDRS * sizeof(struct rimeaddr_s)); + return -ENOMEM; } #endif /* CONFIG_NET_6LOWPAN */