diff --git a/include/nuttx/net/netdev.h b/include/nuttx/net/netdev.h index eb84a7774fd..7f8e4041f45 100644 --- a/include/nuttx/net/netdev.h +++ b/include/nuttx/net/netdev.h @@ -437,7 +437,9 @@ int ipv6_input(FAR struct net_driver_s *dev); #ifdef CONFIG_NET_6LOWPAN struct ieee802154_driver_s; /* See sixlowpan.h */ -int sixlowpan_input(FAR struct ieee802154_driver_s *ieee); +struct iob_s; /* See iob.h */ +int sixlowpan_input(FAR struct ieee802154_driver_s *ieee, + FAR struct iob_s *framelist); #endif /**************************************************************************** @@ -513,7 +515,7 @@ int devif_timer(FAR struct net_driver_s *dev, devif_poll_callback_t callback); * * If no Neighbor Table entry is found for the destination IPv6 address, * the packet in the d_buf[] is replaced by an ICMPv6 Neighbor Solict - * request packet for the IPv6 address. The IPv6 packet is dropped and + * request packet for the IPv6 address. The IPv6 packet is dropped and * it is assumed that the higher level protocols (e.g., TCP) eventually * will retransmit the dropped packet. * diff --git a/include/nuttx/net/sixlowpan.h b/include/nuttx/net/sixlowpan.h index 2e65199513f..85c95329dca 100644 --- a/include/nuttx/net/sixlowpan.h +++ b/include/nuttx/net/sixlowpan.h @@ -1,6 +1,7 @@ /**************************************************************************** * include/nuttx/net/sixlowpan.h - * Header file for the 6lowpan implementation (RFC4944 and draft-hui-6lowpan-hc-01) + * Header file for the 6lowpan implementation (RFC4944 and + * draft-hui-6lowpan-hc-01) * * Copyright (C) 2017, Gregory Nutt, all rights reserved * Author: Gregory Nutt @@ -271,61 +272,6 @@ (a)[4] == 0 && (a)[5] == 0 && (a)[6] == 0 && \ (((a)[7] & HTONS(0xff00)) == 0x0000)) -/* Frame buffer helper macros ***********************************************/ -/* The IEEE802.15.4 MAC driver structures includes a list of IOB - * structures, i_framelist, containing frames to be sent by the driver or - * that were received by the driver. The IOB structure is defined in - * include/nuttx/drivers/iob.h. The length of data in the IOB is provided by - * the io_len field of the IOB structure. - * - * NOTE that IOBs must be configured such that CONFIG_IOB_BUFSIZE >= - * CONFIG_NET_6LOWPAN_FRAMELEN - * - * 1. On a TX poll, the IEEE802.15.4 MAC driver should provide its driver - * structure with i_framelist set to NULL. At the conclusion of the - * poll, if there are frames to be sent, they will have been added to - * the i_framelist. The non-empty frame list is the indication that - * there is data to be sent. - * - * The IEEE802.15.4 may use the FRAME_IOB_EMPTY() macro to determine - * if there there frames to be sent. If so, it should remove each - * frame from the frame list using the FRAME_IOB_REMOVE() macro and send - * it. That macro will return NULL when all of the frames have been - * sent. - * - * After sending each frame, the driver must return the IOB to the pool - * of free IOBs using the FROM_IOB_FREE() macro. - */ - - -#define FRAME_IOB_EMPTY(ieee) ((ieee)->i_framelist == NULL) -#define FRAME_IOB_REMOVE(ieee, iob) \ - do \ - { \ - (iob) = (ieee)->i_framelist; \ - (ieee)->i_framelist = (iob)->io_flink; \ - (iob)->io_flink = NULL; \ - } \ - while (0) -#define FRAME_IOB_FREE(iob) iob_free(iob) - -/* 2. When receiving data, the IEEE802.15.4 MAC driver should receive the - * frame data directly into the payload area of an IOB structure. That - * IOB structure may be obtained using the FRAME_IOB_ALLOC() macro. The - * single frame should be added to the frame list using FRAME_IOB_ADD() - * (it will be a list of length one) . The MAC driver should then inform - * the network of the by calling sixlowpan_input(). - */ - -#define FRAME_IOB_ALLOC() iob_alloc(false) -#define FRAME_IOB_ADD(ieee, iob) \ - do \ - { \ - (iob)->io_flink = (ieee)->i_framelist; \ - (ieee)->i_framelist = (iob); \ - } \ - while (0) - /**************************************************************************** * Public Types ****************************************************************************/ @@ -335,18 +281,21 @@ * difference is that fragmentation must be supported. * * The IEEE802.15.4 MAC does not use the d_buf packet buffer directly. - * Rather, it uses a list smaller frame buffers, i_framelist. + * Rather, it uses a list smaller frame buffers. * - * - The packet fragment data is provided to an IOB in the i_framelist - * buffer each time that the IEEE802.15.4 MAC needs to send more data. - * The length of the frame is provided in the io_len field of the IOB. + * - The packet fragment data is provided in an IOB in the via the + * i_req_data() interface method each time that the IEEE802.15.4 MAC + * needs to send more data. The length of the frame is provided in the + * io_len field of the IOB. * * In this case, the d_buf is not used at all and, if fact, may be * NULL. * * - Received frames are provided by IEEE802.15.4 MAC to the network - * via and IOB in i_framelist with length io_len for reassembly in - * d_buf; d_len will hold the size of the reassembled packet. + * via an IOB parameter in the sixlowpan_submit() interface. The + * length of the frawme is io_len and will be uncompressed and possibly + * reassembled in the d_buf; d_len will hold the size of the + * reassembled packet. * * In this case, a d_buf of size CONFIG_NET_6LOWPAN_MTU must be provided. * @@ -360,49 +309,40 @@ * this structure. In general, all fields must be set to NULL. In * addtion: * - * 1. i_dsn must be set to a random value. After that, it will be managed - * by the network. + * 1. On a TX poll, the IEEE802.15.4 MAC driver should provide its driver + * structure. During the course of the poll, the networking layer may + * generate outgoing frames. These frames will by provided to the MAC + * driver via the req_data() method. * - * 2. On a TX poll, the IEEE802.15.4 MAC driver should provide its driver - * structure with i_framelist set to NULL. At the conclusion of the - * poll, if there are frames to be sent, they will have been added to - * the i_framelist. The non-empty frame list at the conclusion of the - * TX poll is the indication that is data to be sent. + * After sending each frame through the radio, the MAC driver must + * return the frame to the pool of free IOBs using the iob_free(). * - * The IEEE802.15.4 may use the FRAME_IOB_EMPTY() macro to determine - * if there there frames to be sent. If so, it should remove each - * frame from the frame list using the FRAME_IOB_REMOVE() macro and send - * it. That macro will return NULL when all of the frames have been - * sent. - * - * After sending each frame, the driver must return the IOB to the pool - * of free IOBs using the FROM_IOB_FREE() macro. - * - * 3. When receiving data both buffers must be provided: + * 2. When receiving data both buffers must be provided: * * The IEEE802.15.4 MAC driver should receive the frame data directly - * into the payload area of an IOB structure. That IOB structure may be - * obtained using the FRAME_IOB_ALLOC() macro. The single frame should - * be added to the frame list using FRAME_IOB_ADD() (it will be a list of - * length one). + * into the payload area of an IOB frame structure. That IOB structure + * may be obtained using the iob_alloc() function. * * The larger dev.d_buf must have a size of at least the advertised MTU - * of the protocol, CONFIG_NET_6LOWPAN_MTU. If fragmentation is enabled, - * then the logical packet size may be significantly larger than the - * size of the frame buffer. The dev.d_buf is used for de-compressing - * each frame and reassembling any fragmented packets to create the full - * input packet that is provided to the application. + * of the protocol, CONFIG_NET_6LOWPAN_MTU, plus CONFIG_NET_GUARDSIZE. + * If fragmentation is enabled, then the logical packet size may be + * significantly larger than the size of the frame buffer. The dev.d_buf + * is used for de-compressing each frame and reassembling any fragmented + * packets to create the full input packet that is provided to the + * application. * * The MAC driver should then inform the network of the by calling - * sixlowpan_input(). + * sixlowpan_input(). That single frame (or, perhaps, list of frames) + * should be provided as second argument of that call. * - * Normally, the network will free the IOB and will nullify the frame - * list. But ss a complexity, the result of receiving a frame may be - * that the network may respond provide an outgoing frames in the - * frame list. + * The network will free the IOB by calling iob_free after it has + * processed the incoming frame. As a complexity, the result of + * receiving a frame may be that the network may respond provide an + * outgoing frames in the via a nested calle to the req_data() method. */ struct ieee802154_frame_meta_s; /* Forward reference */ +struct iob_s; /* Forward reference */ struct ieee802154_driver_s { @@ -414,33 +354,22 @@ struct ieee802154_driver_s /* IEEE802.15.4 MAC-specific definitions follow. */ - /* The i_framelist is used to hold a outgoing frames contained in IOB - * structures. When the IEEE802.15.4 device polls for new TX data, the - * outgoing frame(s) containing the packet fragments are placed in IOBs - * and queued in i_framelist. + /* The msdu_handle is basically an id for the frame. The standard just + * says that the next highest layer should determine it. It is used in + * three places * - * The i_framelist is similary used to hold incoming frames in IOB - * structures. The IEEE802.15.4 MAC driver must receive frames in an IOB, - * place the IOB in the i_framelist, and call sixlowpan_input(). + * 1. When you do that data request + * 2. When the transmission is complete, the conf_data is called with + * that handle so that the user can be notified of the frames success/ + * failure + * 3. For a req_purge, to basically "cancel" the transaction. This is + * often particularly useful on a coordinator that has indirect data + * waiting to be requested from another device * - * The IEEE802.15.4 MAC driver design may be concurrently sending and - * requesting new frames using lists of IOBs. That IOB frame buffer - * management must be managed by the IEEE802.15.4 MAC driver. + * Here is a simple frame counter. */ - FAR struct iob_s *i_framelist; - - /* Driver Configuration ***************************************************/ - /* 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; + uint8_t i_msdu_handle; #if CONFIG_NET_6LOWPAN_FRAG /* Fragmentation Support *************************************************/ @@ -511,7 +440,7 @@ struct ieee802154_driver_s **************************************************************************/ CODE int (*i_get_mhrlen)(FAR struct ieee802154_driver_s *netdev, - FAR struct ieee802154_frame_meta_s *meta); + FAR const struct ieee802154_frame_meta_s *meta); /************************************************************************** * Name: mac802154_req_data @@ -525,7 +454,7 @@ struct ieee802154_driver_s **************************************************************************/ CODE int (*i_req_data)(FAR struct ieee802154_driver_s *netdev, - FAR struct ieee802154_frame_meta_s *meta, + FAR const struct ieee802154_frame_meta_s *meta, FAR struct iob_s *frames); }; @@ -539,25 +468,32 @@ struct ieee802154_driver_s * Description: * Process an incoming 6loWPAN frame. * - * This function is called when the device driver has received a 6loWPAN - * frame from the network. The frame from the device driver must be - * provided in a IOB present in the i_framelist: The frame data is in the - * IOB io_data[] buffer and the length of the frame is in the IOB io_len - * field. Only a single IOB is expected in the i_framelist. This incoming - * data will be processed one frame at a time. + * This function is called when the device driver has received an + * IEEE802.15.4 frame from the network. The frame from the device + * driver must be provided in by the IOB frame argument of the + * function call: * - * An non-NULL d_buf of size CONFIG_NET_6LOWPAN_MTU 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). + * - 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 the IEEE802.15.4 MAC header is provided in the + * io_offset field. * - * After each frame is processed into d_buf, the IOB is removed and - * deallocated. i_framelist will be nullified. If reassembly is - * incomplete, this function will return to called with i_framelist - * equal to NULL. The partially reassembled packet must be preserved by - * the IEEE802.15.4 MAC and provided again when the next frame is - * received. + * 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 IEEE802.15.4 MAC network drvier sand 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 @@ -565,28 +501,25 @@ struct ieee802154_driver_s * * 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 the - * d_buf and d_len will be set to a non-zero value. That case is handled - * by this function. + * 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 in i_framelist as with other - * TX operations. - * - * So from the standpoint of the IEEE802.15.4 MAC driver, there are two - * possible results: (1) i_framelist is NULL meaning that the frame - * was fully processed and freed, or (2) i_framelist is non-NULL meaning - * that there are outgoing frame(s) to be sent. + * compressed and possibly fragmented frames and provided to the MAC + * network driver via the req_data() method as with other TX operations. * * Input Parameters: - * ieee - The IEEE802.15.4 MAC network driver interface. + * ieee - The IEEE802.15.4 MAC network driver interface. + * framelist - The head of an incoming list of frames. * * Returned Value: * Ok is returned on success; Othewise a negated errno value is returned. * ****************************************************************************/ -int sixlowpan_input(FAR struct ieee802154_driver_s *ieee); +int sixlowpan_input(FAR struct ieee802154_driver_s *ieee, + FAR struct iob_s *framelist); #endif /* CONFIG_NET_6LOWPAN */ #endif /* __INCLUDE_NUTTX_NET_SIXLOWPAN_H */ diff --git a/net/sixlowpan/sixlowpan_framelist.c b/net/sixlowpan/sixlowpan_framelist.c index 91e3369b819..e4e769c0ce3 100644 --- a/net/sixlowpan/sixlowpan_framelist.c +++ b/net/sixlowpan/sixlowpan_framelist.c @@ -55,6 +55,7 @@ #include #include +#include #include "sixlowpan/sixlowpan_internal.h" @@ -183,9 +184,8 @@ static void sixlowpan_compress_ipv6hdr(FAR const struct ipv6_hdr_s *ipv6hdr, * * 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 put in ieee->i_framelist - * and the entire list of frames will be delivered to the 802.15.4 MAC via - * ieee->i_framelist. + * fragmented. The resulting packet/fragments are submitted to the MAC + * where they are queue for transfer. * * Input Parameters: * ieee - The IEEE802.15.4 MAC driver instance @@ -211,6 +211,7 @@ int sixlowpan_queue_frames(FAR struct ieee802154_driver_s *ieee, FAR const void *buf, size_t buflen, FAR const struct rimeaddr_s *destmac) { + struct ieee802154_frame_meta_s meta; FAR struct iob_s *iob; FAR uint8_t *fptr; int framer_hdrlen; @@ -221,6 +222,7 @@ int sixlowpan_queue_frames(FAR struct ieee802154_driver_s *ieee, #ifdef CONFIG_NET_6LOWPAN_FRAG uint16_t outlen = 0; #endif + int ret; /* Initialize global data. Locking the network guarantees that we have * exclusive use of the global values for intermediate calculations. @@ -297,18 +299,33 @@ int sixlowpan_queue_frames(FAR struct ieee802154_driver_s *ieee, dest_panid = 0xffff; (void)sixlowpan_src_panid(ieee, &dest_panid); + /* Based on the collected attributes and addresses, construct the MAC meta + * data structure that we need to interface with the IEEE802.15.4 MAC. + */ + + ret = sixlowpan_meta_data(dest_panid, &meta); + if (ret < 0) + { + nerr("ERROR: sixlowpan_meta_data() failed: %d\n", ret); + } + /* Pre-calculate frame header length. */ - framer_hdrlen = sixlowpan_send_hdrlen(ieee, dest_panid); + framer_hdrlen = sixlowpan_frame_hdrlen(ieee, &meta); if (framer_hdrlen < 0) { /* Failed to determine the size of the header failed. */ - nerr("ERROR: sixlowpan_send_hdrlen() failed: %d\n", framer_hdrlen); + nerr("ERROR: sixlowpan_frame_hdrlen() failed: %d\n", framer_hdrlen); return framer_hdrlen; } - g_frame_hdrlen = 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) @@ -338,15 +355,15 @@ int sixlowpan_queue_frames(FAR struct ieee802154_driver_s *ieee, if (buflen > (CONFIG_NET_6LOWPAN_FRAMELEN - g_frame_hdrlen)) { #ifdef CONFIG_NET_6LOWPAN_FRAG - /* ieee->i_framelist will hold the generated frames; frames will be + /* 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; - int verify; /* 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. @@ -358,13 +375,6 @@ int sixlowpan_queue_frames(FAR struct ieee802154_driver_s *ieee, ninfo("Sending fragmented packet length %d\n", buflen); /* Create 1st Fragment */ - /* Add the frame header using the pre-allocated IOB using the DSN - * selected by sixlowpan_send_hdrlen(). - */ - - verify = sixlowpan_framecreate(ieee, iob, dest_panid); - DEBUGASSERT(verify == framer_hdrlen); - UNUSED(verify); /* Move HC1/HC06/IPv6 header to make space for the FRAG1 header at the * beginning of the frame. @@ -405,8 +415,8 @@ int sixlowpan_queue_frames(FAR struct ieee802154_driver_s *ieee, /* Set outlen to what we already sent from the IP payload */ - iob->io_len = paysize + g_frame_hdrlen; - outlen = paysize; + iob->io_len = paysize + g_frame_hdrlen; + outlen = paysize; ninfo("First fragment: length %d, tag %d\n", paysize, ieee->i_dgramtag); @@ -415,17 +425,17 @@ int sixlowpan_queue_frames(FAR struct ieee802154_driver_s *ieee, /* Add the first frame to the IOB queue */ - ieee->i_framelist = iob; - qtail = iob; + qhead = iob; + qtail = iob; /* Keep track of the total amount of data queue */ - iob->io_pktlen = iob->io_len; + iob->io_pktlen = iob->io_len; /* Create following fragments */ - frame1 = iob->io_data; - frag1_hdrlen = g_frame_hdrlen; + frame1 = iob->io_data; + frag1_hdrlen = g_frame_hdrlen; while (outlen < buflen) { @@ -442,20 +452,10 @@ int sixlowpan_queue_frames(FAR struct ieee802154_driver_s *ieee, iob->io_flink = NULL; iob->io_len = 0; - iob->io_offset = 0; + iob->io_offset = framer_hdrlen; iob->io_pktlen = 0; fptr = iob->io_data; - /* Add a new frame header to the IOB (same as the first but with a - * different DSN). - */ - - g_pktattrs[PACKETBUF_ATTR_MAC_SEQNO] = 0; - - verify = sixlowpan_framecreate(ieee, iob, dest_panid); - DEBUGASSERT(verify == framer_hdrlen); - UNUSED(verify); - /* Copy the HC1/HC06/IPv6 header the frame header from first * frame, into the correct location after the FRAGN header * of subsequent frames. @@ -508,9 +508,23 @@ int sixlowpan_queue_frames(FAR struct ieee802154_driver_s *ieee, /* Keep track of the total amount of data queue */ - ieee->i_framelist->io_pktlen += iob->io_len; + qhead->io_pktlen += iob->io_len; } + /* Submit all of the fragments to the MAC */ + + while (qhead != NULL) + { + iob = qhead; + qhead = iob->io_flink; + + ret = sixlowpan_frame_submit(ieee, &meta, iob); + if (ret < 0) + { + nerr("ERROR: sixlowpan_frame_submit() failed: %d\n", ret); + } + } + /* Update the datagram TAG value */ ieee->i_dgramtag++; @@ -524,34 +538,27 @@ int sixlowpan_queue_frames(FAR struct ieee802154_driver_s *ieee, } else { - int verify; - /* The packet does not need to be fragmented just copy the "payload" * and send in one frame. */ - /* Add the frame header to the preallocated IOB. */ - - verify = sixlowpan_framecreate(ieee, iob, dest_panid); - DEBUGASSERT(verify == framer_hdrlen); - UNUSED(verify); - - /* Copy the payload and queue */ + /* Copy the payload into the frame. */ memcpy(fptr + g_frame_hdrlen, buf, buflen); - iob->io_len = buflen + g_frame_hdrlen; + iob->io_len = buflen + g_frame_hdrlen; + 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); - /* Add the first frame to the IOB queue */ + /* Submit the frame to the MAC */ - ieee->i_framelist = iob; - - /* Keep track of the total amount of data queue */ - - iob->io_pktlen = iob->io_len; + ret = sixlowpan_frame_submit(ieee, &meta, iob); + if (ret < 0) + { + nerr("ERROR: sixlowpan_frame_submit() failed: %d\n", ret); + } } return OK; diff --git a/net/sixlowpan/sixlowpan_framer.c b/net/sixlowpan/sixlowpan_framer.c index b85819993e4..9a32310d026 100644 --- a/net/sixlowpan/sixlowpan_framer.c +++ b/net/sixlowpan/sixlowpan_framer.c @@ -52,31 +52,16 @@ #include #include #include +#include #include #include "nuttx/net/net.h" +#include "nuttx/wireless/ieee802154/ieee802154_mac.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 ****************************************************************************/ @@ -138,172 +123,47 @@ static bool sixlowpan_addrnull(FAR uint8_t *addr) return true; } - /**************************************************************************** - * Name: 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 - * + * Public Functions ****************************************************************************/ -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) - { - /* Indicate source PANID compression */ - - finfo->fcf.panid_compression = 1; - - /* Compressed header, only do dest pid. - * - * REVISIT: This was commented out in corresponding Contiki logic, but - * is needed to match sixlowpan_recv_hdrlen(). - */ - - 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 -} - /**************************************************************************** - * Name: sixlowpan_fieldlengths + * Name: sixlowpan_meta_data * * Description: - * Return the lengths associated fields of the IEEE802.15.4 header. + * Based on the collected attributes and addresses, construct the MAC meta + * data structure that we need to interface with the IEEE802.15.4 MAC. * - * 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; -} - -/**************************************************************************** - * Name: 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); -} - -/**************************************************************************** - * Name: sixlowpan_setup_params - * - * Description: - * Configure frame parmeters structure. - * - * Input parameters: - * ieee - A reference IEEE802.15.4 MAC network device structure. - * iob - The IOB in which to create the frame. + * Input Parameters: * dest_panid - PAN ID of the destination. May be 0xffff if the destination * is not associated. - * params - Where to put the parmeters + * meta - Location to return the corresponding meta data. * * Returned Value: - * None. + * Ok is returned on success; Othewise a negated errno value is returned. + * + * Assumptions: + * Called with the network locked. * ****************************************************************************/ -static void sixlowpan_setup_params(FAR struct ieee802154_driver_s *ieee, - uint16_t dest_panid, - FAR struct frame802154_s *params) +int sixlowpan_meta_data(uint16_t dest_panid, + FAR struct ieee802154_frame_meta_s *meta) { +#if 0 /* To be provided */ + /* Set up the frame parameters */ + uint16_t src_panid; bool rcvrnull; /* Initialize all prameters to all zero */ - memset(params, 0, sizeof(params)); + memset(meta, 0, sizeof(struct ieee802154_frame_meta_s)); /* Build the FCF (Only non-zero elements need to be initialized). */ - params->fcf.frame_type = FRAME802154_DATAFRAME; - params->fcf.frame_pending = g_pktattrs[PACKETBUF_ATTR_PENDING]; + meta->fcf.frame_type = FRAME802154_DATAFRAME; + meta->fcf.frame_pending = g_pktattrs[PACKETBUF_ATTR_PENDING]; /* If the output address is NULL in the Rime buf, then it is broadcast * on the 802.15.4 network. @@ -312,24 +172,12 @@ static void sixlowpan_setup_params(FAR struct ieee802154_driver_s *ieee, rcvrnull = sixlowpan_addrnull(g_pktaddrs[PACKETBUF_ADDR_RECEIVER].u8); if (rcvrnull) { - params->fcf.ack_required = g_pktattrs[PACKETBUF_ATTR_MAC_ACK]; + meta->fcf.ack_required = g_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 (g_pktattrs[PACKETBUF_ATTR_MAC_SEQNO] != 0) - { - params->seq = g_pktattrs[PACKETBUF_ATTR_MAC_SEQNO] & 0xff; - } - else - { - params->seq = ieee->i_dsn++; - g_pktattrs[PACKETBUF_ATTR_MAC_SEQNO] = params->seq | 0x100; - } + meta->fcf.frame_version = FRAME802154_IEEE802154_2003; /* Complete the addressing fields. */ /* Get the source PAN ID from the IEEE802.15.4 radio driver */ @@ -339,8 +187,8 @@ static void sixlowpan_setup_params(FAR struct ieee802154_driver_s *ieee, /* Set the source and destination PAN ID. */ - params->src_pid = src_panid; - params->dest_pid = dest_panid; + meta->src_pid = src_panid; + meta->dest_pid = dest_panid; /* If the output address is NULL in the Rime buf, then it is broadcast * on the 802.15.4 network. @@ -350,46 +198,46 @@ static void sixlowpan_setup_params(FAR struct ieee802154_driver_s *ieee, { /* Broadcast requires short address mode. */ - params->fcf.dest_addr_mode = FRAME802154_SHORTADDRMODE; - params->dest_addr[0] = 0xff; - params->dest_addr[1] = 0xff; + meta->fcf.dest_addr_mode = FRAME802154_SHORTADDRMODE; + meta->dest_addr[0] = 0xff; + meta->dest_addr[1] = 0xff; } else { /* Copy the destination address */ - rimeaddr_copy((struct rimeaddr_s *)¶ms->dest_addr, + rimeaddr_copy((struct rimeaddr_s *)&meta->dest_addr, g_pktaddrs[PACKETBUF_ADDR_RECEIVER].u8); /* Use short destination address mode if so configured */ #ifdef CONFIG_NET_6LOWPAN_RIMEADDR_EXTENDED - params->fcf.dest_addr_mode = FRAME802154_LONGADDRMODE; + meta->fcf.dest_addr_mode = FRAME802154_LONGADDRMODE; #else - params->fcf.dest_addr_mode = FRAME802154_SHORTADDRMODE; + meta->fcf.dest_addr_mode = FRAME802154_SHORTADDRMODE; #endif } /* Set the source address to the node address assigned to the device */ - rimeaddr_copy((struct rimeaddr_s *)¶ms->src_addr, + rimeaddr_copy((struct rimeaddr_s *)&meta->src_addr, &ieee->i_dev.d_mac.ieee802154); /* Use short soruce address mode if so configured */ #ifdef CONFIG_NET_6LOWPAN_RIMEADDR_EXTENDED - params->fcf.src_addr_mode = FRAME802154_LONGADDRMODE; + meta->fcf.src_addr_mode = FRAME802154_LONGADDRMODE; #else - params->fcf.src_addr_mode = FRAME802154_SHORTADDRMODE; + meta->fcf.src_addr_mode = FRAME802154_SHORTADDRMODE; #endif +#endif + +#warning Missing logic + return -ENOSYS; } /**************************************************************************** - * Public Functions - ****************************************************************************/ - -/**************************************************************************** - * Name: sixlowpan_send_hdrlen + * Name: sixlowpan_frame_hdrlen * * Description: * This function is before the first frame has been sent in order to @@ -397,9 +245,8 @@ static void sixlowpan_setup_params(FAR struct ieee802154_driver_s *ieee, * 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. + * ieee - A reference IEEE802.15.4 MAC network device structure. + * meta - Meta data that describes the MAC header * * Returned Value: * The frame header length is returnd on success; otherwise, a negated @@ -407,171 +254,37 @@ static void sixlowpan_setup_params(FAR struct ieee802154_driver_s *ieee, * ****************************************************************************/ -int sixlowpan_send_hdrlen(FAR struct ieee802154_driver_s *ieee, - uint16_t dest_panid) +int sixlowpan_frame_hdrlen(FAR struct ieee802154_driver_s *ieee, + FAR const struct ieee802154_frame_meta_s *meta) { - struct frame802154_s params; - - /* Set up the frame parameters */ - - sixlowpan_setup_params(ieee, dest_panid, ¶ms); - - /* Return the length of the header */ - - return sixlowpan_802154_hdrlen(¶ms); + return ieee->i_get_mhrlen(ieee, meta); } /**************************************************************************** - * Name: 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 - 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) << FRAME802154_FRAMETYPE_SHIFT) | - ((finfo->fcf.security_enabled & 1) << FRAME802154_SECENABLED_SHIFT) | - ((finfo->fcf.frame_pending & 1) << FRAME802154_FRAMEPENDING_SHIFT) | - ((finfo->fcf.ack_required & 1) << FRAME802154_ACKREQUEST_SHIFT) | - ((finfo->fcf.panid_compression & 1) << FRAME802154_PANIDCOMP_SHIFT); - buf[1] = ((finfo->fcf.dest_addr_mode & 3) << FRAME802154_DSTADDR_SHIFT) | - ((finfo->fcf.frame_version & 3) << FRAME802154_VERSION_SHIFT) | - ((finfo->fcf.src_addr_mode & 3) << FRAME802154_SRCADDR_SHIFT); - - /* 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; -} - -/**************************************************************************** - * Name: sixlowpan_framecreate + * Name: sixlowpan_frame_submit * * Description: * This function is called after eiether (1) the IEEE802.15.4 MAC driver - * polls for TX data or (2) after the IEEE802.15.4 MAC driver provides an - * in frame and the network responds with an outgoing packet. It creates - * the IEEE802.15.4 header in the frame buffer. + * polls for TX data or (2) after the IEEE802.15.4 MAC driver provides a + * new incoming frame and the network responds with an outgoing packet. It + * submits any new outgoing frame to the MAC. * * Input parameters: - * ieee - A reference IEEE802.15.4 MAC network device structure. - * iob - The IOB in which to create the frame. - * dest_panid - PAN ID of the destination. May be 0xffff if the destination - * is not associated. + * ieee - A reference IEEE802.15.4 MAC network device structure. + * meta - Meta data that describes the MAC header + * frame - The IOB containing the frame to be submitted. * * Returned Value: - * The frame header length is returnd on success; otherwise, a negated - * errno value is return on failure. + * Zero (OK) is returned on success; otherwise, a negated errno value is + * return on any failure. * ****************************************************************************/ -int sixlowpan_framecreate(FAR struct ieee802154_driver_s *ieee, - FAR struct iob_s *iob, uint16_t dest_panid) +int sixlowpan_frame_submit(FAR struct ieee802154_driver_s *ieee, + FAR const struct ieee802154_frame_meta_s *meta, + FAR struct iob_s *frame) { - struct frame802154_s params; - int hdrlen; - - /* Set up the frame parameters */ - - sixlowpan_setup_params(ieee, dest_panid, ¶ms); - - /* Get the length of the header */ - - hdrlen = sixlowpan_802154_hdrlen(¶ms); - - /* Then create the frame */ - - sixlowpan_802154_framecreate(¶ms, iob->io_data, hdrlen); - - wlinfo("Frame type: %02x hdrlen: %d\n", - params.fcf.frame_type, hdrlen); -#ifdef CONFIG_NET_6LOWPAN_RIMEADDR_EXTENDED - 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]); -#else - wlinfo("Dest address: %02x:%02x\n", - params.dest_addr[0], params.dest_addr[1]); -#endif - - return hdrlen; + return ieee->i_req_data(ieee, meta, frame); } #endif /* CONFIG_NET_6LOWPAN */ diff --git a/net/sixlowpan/sixlowpan_input.c b/net/sixlowpan/sixlowpan_input.c index bccd97677b7..0c573913d92 100644 --- a/net/sixlowpan/sixlowpan_input.c +++ b/net/sixlowpan/sixlowpan_input.c @@ -129,92 +129,6 @@ static uint8_t g_bitbucket[UNCOMP_MAXHDR]; * Private Functions ****************************************************************************/ -/**************************************************************************** - * Name: sixlowpan_recv_hdrlen - * - * Description: - * Get the length of the IEEE802.15.4 FCF header on the received frame. - * - * Input Parameters: - * ieee - The IEEE802.15.4 MAC network driver interface. - * iob - The IOB containing the frame. - * - * Returned Value: - * Ok is returned on success; Othewise a negated errno value is returned. - * - * Assumptions: - * Network is locked - * - ****************************************************************************/ - -int sixlowpan_recv_hdrlen(FAR const uint8_t *fptr) -{ - uint16_t hdrlen; - uint8_t addrmode; - - /* Minimum header: 2 byte FCF + 1 byte sequence number */ - - hdrlen = 3; - - /* Account for destination address size */ - - addrmode = (fptr[1] & FRAME802154_DSTADDR_MASK) >> FRAME802154_DSTADDR_SHIFT; - if (addrmode == FRAME802154_SHORTADDRMODE) - { - /* 2 byte dest PAN + 2 byte dest short address */ - - hdrlen += 4; - } - else if (addrmode == FRAME802154_LONGADDRMODE) - { - /* 2 byte dest PAN + 8 byte dest long address */ - - hdrlen += 10; - } - else if (addrmode != FRAME802154_NOADDR) - { - nwarn("WARNING: Unrecognized address mode\n"); - - return -ENOSYS; - } - else if ((fptr[0] & (1 << FRAME802154_PANIDCOMP_SHIFT)) != 0) - { - nwarn("WARNING: PAN compression, but no destination address\n"); - - return -EINVAL; - } - - /* Account for source address size */ - - addrmode = (fptr[1] & FRAME802154_SRCADDR_MASK) >> FRAME802154_SRCADDR_SHIFT; - if (addrmode == FRAME802154_NOADDR) - { - return hdrlen; - } - else - { - /* Add source PANID if PANIDs are not compressed */ - - if ((fptr[0] & (1 << FRAME802154_PANIDCOMP_SHIFT)) == 0) - { - hdrlen += 2; - } - - /* Add the length of the source address */ - - if (addrmode == FRAME802154_SHORTADDRMODE) - { - return hdrlen + 2; - } - else if (addrmode == FRAME802154_LONGADDRMODE) - { - return hdrlen + 8; - } - } - - return 0; -} - /**************************************************************************** * Name: sixlowpan_compress_ipv6hdr * @@ -245,7 +159,7 @@ 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; @@ -355,8 +269,8 @@ static int sixlowpan_frame_process(FAR struct ieee802154_driver_s *ieee, * This size includes both fragmentation and FCF headers. */ - fptr = iob->io_data; - hdrsize = sixlowpan_recv_hdrlen(fptr); + fptr = iob->io_data; /* Frame data is in I/O buffer */ + hdrsize = iob->io_offset; /* Offset past the MAC header */ if (hdrsize < 0) { nwarn("Invalid IEEE802.15.2 header: %d\n", hdrsize); @@ -729,25 +643,32 @@ static int sixlowpan_dispatch(FAR struct ieee802154_driver_s *ieee) * Description: * Process an incoming 6loWPAN frame. * - * This function is called when the device driver has received a 6loWPAN - * frame from the network. The frame from the device driver must be - * provided in a IOB present in the i_framelist: The frame data is in the - * IOB io_data[] buffer and the length of the frame is in the IOB io_len - * field. Only a single IOB is expected in the i_framelist. This incoming - * data will be processed one frame at a time. + * This function is called when the device driver has received an + * IEEE802.15.4 frame from the network. The frame from the device + * driver must be provided in by the IOB frame argument of the + * function call: * - * An non-NULL d_buf of size CONFIG_NET_6LOWPAN_MTU 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). + * - 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 the IEEE802.15.4 MAC header is provided in the + * io_offset field. * - * After each frame is processed into d_buf, the IOB is removed and - * deallocated. i_framelist will be nullified. If reassembly is - * incomplete, this function will return to called with i_framelist - * equal to NULL. The partially reassembled packet must be preserved by - * the IEEE802.15.4 MAC and provided again when the next frame is - * received. + * 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 IEEE802.15.4 MAC network drvier sand 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 @@ -755,43 +676,40 @@ static int sixlowpan_dispatch(FAR struct ieee802154_driver_s *ieee) * * 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 the - * d_buf and d_len will be set to a non-zero value. That case is handled - * by this function. + * 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 in i_framelist as with other - * TX operations. - * - * So from the standpoint of the IEEE802.15.4 MAC driver, there are two - * possible results: (1) i_framelist is NULL meaning that the frame - * was fully processed and freed, or (2) i_framelist is non-NULL meaning - * that there are outgoing frame(s) to be sent. + * compressed and possibly fragmented frames and provided to the MAC + * network driver via the req_data() method as with other TX operations. * * Input Parameters: - * ieee - The IEEE802.15.4 MAC network driver interface. + * ieee - The IEEE802.15.4 MAC network driver interface. + * framelist - The head of an incoming list of frames. * * Returned Value: * Ok is returned on success; Othewise a negated errno value is returned. * ****************************************************************************/ -int sixlowpan_input(FAR struct ieee802154_driver_s *ieee) +int sixlowpan_input(FAR struct ieee802154_driver_s *ieee, + FAR struct iob_s *framelist) { int ret = -EINVAL; - DEBUGASSERT(ieee != NULL && !FRAME_IOB_EMPTY(ieee)); + DEBUGASSERT(ieee != NULL && framelist != NULL); - /* Verify that an IOB is provided in the device structure */ + /* Verify that an frame has been provided. */ - while (!FRAME_IOB_EMPTY(ieee)) + while (framelist != NULL) { FAR struct iob_s *iob; /* Remove the IOB containing the frame from the device structure */ - FRAME_IOB_REMOVE(ieee, iob); - DEBUGASSERT(iob != NULL); + iob = framelist; + framelist = iob->io_flink; sixlowpan_dumpbuffer("Incoming frame", iob->io_data, iob->io_len); diff --git a/net/sixlowpan/sixlowpan_internal.h b/net/sixlowpan/sixlowpan_internal.h index 08b2fc445cb..8eecb3b49b7 100644 --- a/net/sixlowpan/sixlowpan_internal.h +++ b/net/sixlowpan/sixlowpan_internal.h @@ -107,28 +107,27 @@ #define PACKETBUF_ATTR_LISTEN_TIME 7 #define PACKETBUF_ATTR_TRANSMIT_TIME 8 #define PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS 9 -#define PACKETBUF_ATTR_MAC_SEQNO 10 -#define PACKETBUF_ATTR_MAC_ACK 11 +#define PACKETBUF_ATTR_MAC_ACK 10 /* Scope 1 attributes: used between two neighbors only. */ -#define PACKETBUF_ATTR_RELIABLE 12 -#define PACKETBUF_ATTR_PACKET_ID 13 -#define PACKETBUF_ATTR_PACKET_TYPE 14 -#define PACKETBUF_ATTR_REXMIT 15 -#define PACKETBUF_ATTR_MAX_REXMIT 16 -#define PACKETBUF_ATTR_NUM_REXMIT 17 -#define PACKETBUF_ATTR_PENDING 18 +#define PACKETBUF_ATTR_RELIABLE 11 +#define PACKETBUF_ATTR_PACKET_ID 12 +#define PACKETBUF_ATTR_PACKET_TYPE 13 +#define PACKETBUF_ATTR_REXMIT 14 +#define PACKETBUF_ATTR_MAX_REXMIT 15 +#define PACKETBUF_ATTR_NUM_REXMIT 16 +#define PACKETBUF_ATTR_PENDING 17 /* Scope 2 attributes: used between end-to-end nodes. */ -#define PACKETBUF_ATTR_HOPS 11 -#define PACKETBUF_ATTR_TTL 20 -#define PACKETBUF_ATTR_EPACKET_ID 21 -#define PACKETBUF_ATTR_EPACKET_TYPE 22 -#define PACKETBUF_ATTR_ERELIABLE 23 +#define PACKETBUF_ATTR_HOPS 18 +#define PACKETBUF_ATTR_TTL 19 +#define PACKETBUF_ATTR_EPACKET_ID 20 +#define PACKETBUF_ATTR_EPACKET_TYPE 21 +#define PACKETBUF_ATTR_ERELIABLE 22 -#define PACKETBUF_NUM_ATTRS 24 +#define PACKETBUF_NUM_ATTRS 23 /* Addresses (indices into g_pktaddrs) */ @@ -188,69 +187,6 @@ 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 */ -}; - /**************************************************************************** * Public Data ****************************************************************************/ @@ -313,9 +249,8 @@ struct iob_s; /* Forward reference */ * * 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 put in ieee->i_framelist - * and the entire list of frames will be delivered to the 802.15.4 MAC via - * ieee->i_framelist. + * fragmented. The resulting packet/fragments are submitted to the MAC + * via the network driver i_req_data method. * * Input Parameters: * dev - The IEEE802.15.4 MAC network driver interface. @@ -344,7 +279,30 @@ int sixlowpan_send(FAR struct net_driver_s *dev, uint16_t timeout); /**************************************************************************** - * Name: sixlowpan_send_hdrlen + * Name: sixlowpan_meta_data + * + * Description: + * Based on the collected attributes and addresses, construct the MAC meta + * data structure that we need to interface with the IEEE802.15.4 MAC. + * + * Input Parameters: + * dest_panid - PAN ID of the destination. May be 0xffff if the destination + * is not associated. + * meta - Location to return the corresponding meta data. + * + * Returned Value: + * Ok is returned on success; Othewise a negated errno value is returned. + * + * Assumptions: + * Called with the network locked. + * + ****************************************************************************/ + +int sixlowpan_meta_data(uint16_t dest_panid, + FAR struct ieee802154_frame_meta_s *meta); + +/**************************************************************************** + * Name: sixlowpan_frame_hdrlen * * Description: * This function is before the first frame has been sent in order to @@ -352,9 +310,8 @@ int sixlowpan_send(FAR struct net_driver_s *dev, * 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. + * ieee - A reference IEEE802.15.4 MAC network device structure. + * meta - Meta data that describes the MAC header * * Returned Value: * The frame header length is returnd on success; otherwise, a negated @@ -362,30 +319,32 @@ int sixlowpan_send(FAR struct net_driver_s *dev, * ****************************************************************************/ -int sixlowpan_send_hdrlen(FAR struct ieee802154_driver_s *ieee, - uint16_t dest_panid); +int sixlowpan_frame_hdrlen(FAR struct ieee802154_driver_s *ieee, + FAR const struct ieee802154_frame_meta_s *meta); /**************************************************************************** - * Name: sixlowpan_framecreate + * Name: sixlowpan_frame_submit * * 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. + * This function is called after eiether (1) the IEEE802.15.4 MAC driver + * polls for TX data or (2) after the IEEE802.15.4 MAC driver provides a + * new incoming frame and the network responds with an outgoing packet. It + * submits any new outgoing frame to the MAC. * * Input parameters: - * ieee - A reference IEEE802.15.4 MAC network device structure. - * iob - The IOB in which to create the frame. - * dest_panid - PAN ID of the destination. May be 0xffff if the destination - * is not associated. + * ieee - A reference IEEE802.15.4 MAC network device structure. + * meta - Meta data that describes the MAC header + * frame - The IOB containing the frame to be submitted. * * Returned Value: - * The frame header length is returnd on success; otherwise, a negated - * errno value is return on failure. + * Zero (OK) is returned on success; otherwise, a negated errno value is + * return on any failure. * ****************************************************************************/ -int sixlowpan_framecreate(FAR struct ieee802154_driver_s *ieee, - FAR struct iob_s *iob, uint16_t dest_panid); +int sixlowpan_frame_submit(FAR struct ieee802154_driver_s *ieee, + FAR const struct ieee802154_frame_meta_s *meta, + FAR struct iob_s *frame); /**************************************************************************** * Name: sixlowpan_queue_frames @@ -397,9 +356,8 @@ int sixlowpan_framecreate(FAR struct ieee802154_driver_s *ieee, * * 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 put in ieee->i_framelist - * and the entire list of frames will be delivered to the 802.15.4 MAC via - * ieee->i_framelist. + * fragmented. The resulting packet/fragments are submitted to the MAC + * via the network driver i_req_data method. * * Input Parameters: * ieee - The IEEE802.15.4 MAC driver instance diff --git a/net/sixlowpan/sixlowpan_send.c b/net/sixlowpan/sixlowpan_send.c index 3ad68554aec..64b7088735e 100644 --- a/net/sixlowpan/sixlowpan_send.c +++ b/net/sixlowpan/sixlowpan_send.c @@ -246,11 +246,10 @@ end_wait: * it to be sent on an 802.15.4 network using 6lowpan. Called from common * UDP/TCP send logic. * - * The payload data is in the caller 'buf' and is of length 'len'. + * 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 put in ieee->i_framelist - * and the entire list of frames will be delivered to the 802.15.4 MAC via - * ieee->i_framelist. + * fragmented. The resulting packet/fragments are submitted to the MAC + * via the network driver i_req_data method. * * Input Parameters: * dev - The IEEE802.15.4 MAC network driver interface. diff --git a/wireless/ieee802154/mac802154_loopback.c b/wireless/ieee802154/mac802154_loopback.c index 92a30d35194..3d2fcf144f3 100644 --- a/wireless/ieee802154/mac802154_loopback.c +++ b/wireless/ieee802154/mac802154_loopback.c @@ -102,8 +102,8 @@ struct lo_driver_s uint16_t lo_panid; /* Fake PAN ID for testing */ WDOG_ID lo_polldog; /* TX poll timer */ struct work_s lo_work; /* For deferring poll work to the work queue */ - FAR struct iob_s *head; /* Head of IOBs queued for loopback */ - FAR struct iob_s *tail; /* Tail of IOBs queued for loopback */ + FAR struct iob_s *lo_head; /* Head of IOBs queued for loopback */ + FAR struct iob_s *lo_tail; /* Tail of IOBs queued for loopback */ /* This holds the information visible to the NuttX network */ @@ -145,9 +145,9 @@ static int lo_ioctl(FAR struct net_driver_s *dev, int cmd, unsigned long arg); #endif static int lo_get_mhrlen(FAR struct ieee802154_driver_s *netdev, - FAR struct ieee802154_frame_meta_s *meta); + FAR const struct ieee802154_frame_meta_s *meta); static int lo_req_data(FAR struct ieee802154_driver_s *netdev, - FAR struct ieee802154_frame_meta_s *meta, + FAR const struct ieee802154_frame_meta_s *meta, FAR struct iob_s *frames); /**************************************************************************** @@ -177,43 +177,15 @@ static int lo_req_data(FAR struct ieee802154_driver_s *netdev, static int lo_loopback(FAR struct net_driver_s *dev) { FAR struct lo_driver_s *priv = (FAR struct lo_driver_s *)dev->d_private; - FAR struct iob_s *head; - FAR struct iob_s *tail; FAR struct iob_s *iob; int ret; - if (dev->d_len > 0 || priv->lo_ieee.i_framelist != NULL) - { - ninfo("d_len: %u i_framelist: %p\n", - dev->d_len, priv->lo_ieee.i_framelist); - - /* The only two valid settings are: - * - * 1. Nothing to send: - * dev->d_len == 0 && priv->lo_ieee.i_framelist == NULL - * 2. Outgoing packet has been converted to IEEE802.15.4 frames: - * dev->d_len == 0 && priv->lo_ieee.i_framelist != NULL - */ - - DEBUGASSERT(dev->d_len == 0 && priv->lo_ieee.i_framelist != NULL); - } - - /* Remove the queued IOBs from driver structure */ - - head = priv->lo_ieee.i_framelist; - - /* Find the tail of the IOB queue */ - - for (tail = NULL, iob = head; - iob != NULL; - tail = iob, iob = iob->io_flink); - - /* Loop while there frames to be sent, i.e., while the IOB list is not - * emtpy. Sending, of course, just means relaying back through the network + /* Loop while there frames to be sent, i.e., while the freme list is not + * emtpy. Sending, of course, just means relaying back through the network * for this driver. */ - while (head != NULL) + while (priv->lo_head != NULL) { /* Increment statistics */ @@ -221,24 +193,23 @@ static int lo_loopback(FAR struct net_driver_s *dev) /* Remove the IOB from the queue */ - iob = head; - head = iob->io_flink; + iob = priv->lo_head; + priv->lo_head = iob->io_flink; iob->io_flink = NULL; - /* Is the queue now empty? */ + /* Did the framelist become empty? */ - if (head == NULL) + if (priv->lo_head == NULL) { - tail = NULL; + priv->lo_tail = NULL; } /* Return the next frame to the network */ - iob->io_flink = NULL; - priv->lo_ieee.i_framelist = iob; + ninfo("Send frame %p to the network: Offset=%u Length=%u\n", + iob, iob->io_offset, iob->io_len); - ninfo("Send frame %p to the network. Length=%u\n", iob, iob->io_len); - ret = sixlowpan_input(&priv->lo_ieee); + ret = sixlowpan_input(&priv->lo_ieee, iob); /* Increment statistics */ @@ -250,33 +221,6 @@ static int lo_loopback(FAR struct net_driver_s *dev) NETDEV_TXERRORS(&priv->lo_ieee.i_dev); NETDEV_ERRORS(&priv->lo_ieee.i_dev); } - - /* What if the network responds with more frames to send? */ - - if (priv->lo_ieee.i_framelist != NULL) - { - /* Append the new list to the tail of the queue */ - - iob = priv->lo_ieee.i_framelist; - priv->lo_ieee.i_framelist = NULL; - - if (tail == NULL) - { - head = iob; - } - else - { - tail->io_flink = iob; - } - - /* Find the new tail of the IOB queue */ - - for (tail = iob, iob = iob->io_flink; - iob != NULL; - tail = iob, iob = iob->io_flink); - } - - priv->lo_txdone = true; } return 0; @@ -693,7 +637,7 @@ static int lo_ioctl(FAR struct net_driver_s *dev, int cmd, ****************************************************************************/ static int lo_get_mhrlen(FAR struct ieee802154_driver_s *netdev, - FAR struct ieee802154_frame_meta_s *meta) + FAR const struct ieee802154_frame_meta_s *meta) { return MAC_HDRLEN; } @@ -710,13 +654,14 @@ static int lo_get_mhrlen(FAR struct ieee802154_driver_s *netdev, ****************************************************************************/ static int lo_req_data(FAR struct ieee802154_driver_s *netdev, - FAR struct ieee802154_frame_meta_s *meta, + FAR const struct ieee802154_frame_meta_s *meta, FAR struct iob_s *frames) { FAR struct lo_driver_s *priv; FAR struct iob_s *iob; - DEBUGASSERT(netdev != NULL && netdev->i_dev.d_private != NULL && iob != NULL); + DEBUGASSERT(netdev != NULL && netdev->i_dev.d_private != NULL && + frames != NULL); priv = (FAR struct lo_driver_s *)netdev->i_dev.d_private; /* Add the incoming list of frames to queue of frames to loopback */ @@ -737,22 +682,18 @@ static int lo_req_data(FAR struct ieee802154_driver_s *netdev, DEBUGASSERT(iob->io_offset == MAC_HDRLEN); memset(iob->io_data, 0, MAC_HDRLEN); - /* Add the IOB to the tail of teh queue of frames to be looped back */ + /* Add the IOB to the tail of the queue of frames to be looped back */ - if (priv->tail == NULL) + if (priv->lo_tail == NULL) { - priv->head = iob; + priv->lo_head = iob; } else { - priv->tail->io_flink = iob; + priv->lo_tail->io_flink = iob; } - /* Find the new tail of the IOB queue */ - - for (priv->tail = iob, iob = iob->io_flink; - iob != NULL; - priv->tail = iob, iob = iob->io_flink); + priv->lo_tail = iob; } /* Is our single work structure available? It may not be if there are @@ -821,10 +762,6 @@ int ieee8021514_loopback(void) dev->d_buf = g_iobuffer; /* Attach the IO buffer */ dev->d_private = (FAR void *)priv; /* Used to recover private state from dev */ - /* Initialize the DSN to a "random" value */ - - ieee->i_dsn = 42; - /* Initialize the Network frame-related callbacks */ ieee->i_get_mhrlen = lo_get_mhrlen; /* Get MAC header length */ diff --git a/wireless/ieee802154/mac802154_netdev.c b/wireless/ieee802154/mac802154_netdev.c index f0e4f43cbea..a5816205e4d 100644 --- a/wireless/ieee802154/mac802154_netdev.c +++ b/wireless/ieee802154/mac802154_netdev.c @@ -140,16 +140,6 @@ struct macnet_driver_s WDOG_ID md_txtimeout; /* TX timeout timer */ struct work_s md_irqwork; /* Defer interupt work to the work queue */ struct work_s md_pollwork; /* Defer poll work to the work queue */ - - /* This is queue of outgoing, ready-to-send frames that will be sent - * indirectly. This list should only be used by a MAC acting as a - * coordinator. These transactions will stay here until the data is - * extracted by the destination device sending a Data Request MAC - * command or if too much time passes. - */ - - FAR volatile struct iob_s *md_head; - FAR volatile struct iob_s *md_tail; }; /**************************************************************************** @@ -258,9 +248,9 @@ static int macnet_ioctl(FAR struct net_driver_s *dev, int cmd, unsigned long arg); #endif static int macnet_get_mhrlen(FAR struct ieee802154_driver_s *netdev, - FAR struct ieee802154_frame_meta_s *meta); + FAR const struct ieee802154_frame_meta_s *meta); static int macnet_req_data(FAR struct ieee802154_driver_s *netdev, - FAR struct ieee802154_frame_meta_s *meta, + FAR const struct ieee802154_frame_meta_s *meta, FAR struct iob_s *frames); /**************************************************************************** @@ -654,57 +644,6 @@ static int macnet_transmit(FAR struct macnet_driver_s *priv) return OK; } -/**************************************************************************** - * Name: macnet_txqueue - * - * Description: - * Add new frames from the network to the list of outgoing frames. - * - * Parameters: - * dev - Reference to the NuttX driver state structure - * - * Returned Value: - * OK on success; a negated errno on failure - * - * Assumptions: - * May or may not be called from an interrupt handler. In either case, - * the network is locked. - * - ****************************************************************************/ - -static void macnet_txqueue(FAR struct net_driver_s *dev) -{ - /* Check if there is a new list of outgoing frames from the network. */ - - if (priv->lo_ieee.i_framelist != NULL) - { - /* Yes.. Remove the frame list from the driver structure */ - - iob = priv->lo_ieee.i_framelist; - priv->lo_ieee.i_framelist = NULL; - - /* Append the new list to the tail of the queue of outgoing frames. */ - - if (priv->md_tail == NULL) - { - priv->md_head = iob; - } - else - { - priv->md_tail->io_flink = iob; - } - - /* Find the new tail of the outgoing frame queue */ - - for (priv->md_tail = iob, iob = iob->io_flink; - iob != NULL; - priv->md_tail = iob, iob = iob->io_flink); - - /* Notify the radio driver that there is data available */ -#warning Missing logic - } -} - /**************************************************************************** * Name: macnet_txpoll * @@ -724,30 +663,12 @@ static void macnet_txqueue(FAR struct net_driver_s *dev) * OK on success; a negated errno on failure * * Assumptions: - * May or may not be called from an interrupt handler. In either case, - * the network is locked. + * The network is locked. * ****************************************************************************/ static int macnet_txpoll(FAR struct net_driver_s *dev) { - FAR struct macnet_driver_s *priv = - (FAR struct macnet_driver_s *)dev->d_private; - FAR struct iob_s *iob; - - /* If the polling resulted in data that should be sent out, the field - * i_framelist will set to a new, outgoing list of frames. - */ - - if (priv->lo_ieee.i_framelist != NULL) - { - /* Remove the frame list from the driver structure and append it to - * the tail of the ist of outgoing frames. - */ - - macnet_txqueue(priv); - } - /* If zero is returned, the polling will continue until all connections have * been examined. */ @@ -781,6 +702,7 @@ static void macnet_receive(FAR struct macnet_driver_s *priv) net_lock(); iob = iob_alloc(false); +#warning Allocated by radio layer, right? if (iob == NULL) { nerr("ERROR: Failed to allocate an IOB\n") @@ -796,22 +718,7 @@ static void macnet_receive(FAR struct macnet_driver_s *priv) /* Transfer the frame to the network logic */ - priv->md_dev.framelist = iob; - sixlowpan_input(&priv->md_dev); - - /* If the above function invocation resulted in data that should be sent - * out, the field i_framelist will have been set to a new, outgoing list - * of frames. - */ - - if (priv->md_dev.i_framelist != NULL) - { - /* Remove the frame list from the driver structure and append it to - * the tail of the ist of outgoing frames. - */ - - macnet_txqueue(priv); - } + sixlowpan_input(&priv->md_dev, iob); } /**************************************************************************** @@ -1508,7 +1415,7 @@ static int macnet_ioctl(FAR struct net_driver_s *dev, int cmd, ****************************************************************************/ static int macnet_get_mhrlen(FAR struct ieee802154_driver_s *netdev, - FAR struct ieee802154_frame_meta_s *meta) + FAR const struct ieee802154_frame_meta_s *meta) { FAR struct macnet_driver_s *priv; @@ -1530,7 +1437,7 @@ static int macnet_get_mhrlen(FAR struct ieee802154_driver_s *netdev, ****************************************************************************/ static int macnet_req_data(FAR struct ieee802154_driver_s *netdev, - FAR struct ieee802154_frame_meta_s *meta, + FAR const struct ieee802154_frame_meta_s *meta, FAR struct iob_s *frames) { FAR struct macnet_driver_s *priv;