6loWPAN: Replace frame buffer with a list of IOBs.

This commit is contained in:
Gregory Nutt 2017-03-31 07:54:58 -06:00
parent 9d13a2463f
commit 0427d6c726
6 changed files with 178 additions and 101 deletions

View File

@ -372,19 +372,19 @@
#define _LOOPIOCVALID(c) (_IOC_TYPE(c)==_LOOPBASE)
#define _LOOPIOC(nr) _IOC(_LOOPBASE,nr)
/* Modem driver ioctl definitions ********************************************/
/* Modem driver ioctl definitions *******************************************/
/* see nuttx/include/modem/ioctl.h */
#define _MODEMIOCVALID(c) (_IOC_TYPE(c)==_MODEMBASE)
#define _MODEMIOC(nr) _IOC(_MODEMBASE,nr)
/* I2C driver ioctl definitions **********************************************/
/* I2C driver ioctl definitions *********************************************/
/* see nuttx/include/i2c/i2c_master.h */
#define _I2CIOCVALID(c) (_IOC_TYPE(c)==_I2CBASE)
#define _I2CIOC(nr) _IOC(_I2CBASE,nr)
/* SPI driver ioctl definitions **********************************************/
/* SPI driver ioctl definitions *********************************************/
/* see nuttx/include/spi/spi_transfer.h */
#define _SPIIOCVALID(c) (_IOC_TYPE(c)==_SPIBASE)
@ -396,7 +396,7 @@
#define _GPIOCVALID(c) (_IOC_TYPE(c)==_GPIOBASE)
#define _GPIOC(nr) _IOC(_GPIOBASE,nr)
/* Contactless driver ioctl definitions ****************************************/
/* Contactless driver ioctl definitions *************************************/
/* (see nuttx/include/contactless/ioctl.h */
#define _CLIOCVALID(c) (_IOC_TYPE(c)==_CLIOCBASE)

View File

@ -53,6 +53,7 @@
#include <stdint.h>
#include <nuttx/net/iob.h>
#include <nuttx/net/netdev.h>
/****************************************************************************
@ -280,7 +281,7 @@
#define PACKETBUF_NUM_ATTRS 24
/* Addresses (indices into i_pktaddr) */
/* Addresses (indices into i_pktaddr) */
#define PACKETBUF_ADDR_SENDER 0
#define PACKETBUF_ADDR_RECEIVER 1
@ -289,6 +290,62 @@
#define PACKETBUF_NUM_ADDRS 4
/* 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/net/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)->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
****************************************************************************/
@ -305,18 +362,20 @@ struct rimeaddr_s
* 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 smaller frame buffer, i_frame.
* Rather, it uses a list smaller frame buffers, i_framelist.
*
* - The packet fragment data is provided to the i_frame buffer each time
* that the IEEE802.15.4 MAC needs to send more data. The length of
* the frame is provided in i_frame.
* - 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.
*
* In this case, the d_buf holds the packet data yet to be sent; d_len
* holds the size of entire packet.
* 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 i_frame with length i_framelen for reassembly in d_buf; d_len
* will hold the size of the reassembled packet.
* 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.
*
* In this case, a d_buf of size CONFIG_NET_6LOWPAN_MTU must be provided.
*
* This is accomplished by "inheriting" the standard 'struct net_driver_s'
* and appending the frame buffer as well as other metadata needed to
@ -328,26 +387,49 @@ struct rimeaddr_s
* 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
* 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.
* 4) On network TX poll operations, the IEEE802.15.4 MAC needs to provide
* the i_frame buffer with size greater than or equal to
* CONFIG_NET_6LOWPAN_FRAMELEN. No dev.d_buf need be provided in this
* case. The entire is TX is performed using only the i_frame buffer.
* 5) On network input RX oprations, both buffers must be provided. The size
* of the i_frame buffer is, again, greater than or equal to
* CONFIG_NET_6LOWPAN_FRAMELEN. 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.
*
* Frame Organization:
* 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.
*
* 4. 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.
*
* 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.
*
* 5. 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).
*
* 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.
*
* The MAC driver should then inform the network of the by calling
* sixlowpan_input().
*
* Frame Organization. The IOB data is retained in the io_data[] field of the
* IOB structure like:
*
* Content Offset
* +------------------+ 0
@ -355,7 +437,7 @@ struct rimeaddr_s
* +------------------+ i_dataoffset
* | Procotol Headers |
* | Data Payload |
* +------------------+ i_framelen
* +------------------+ io_len
* | Unused |
* +------------------+ CONFIG_NET_6LOWPAN_FRAMELEN
*/
@ -370,31 +452,21 @@ struct ieee802154_driver_s
/* IEEE802.15.4 MAC-specific definitions follow. */
/* The i_frame array is used to hold outgoing frame. When the
* IEEE802.15.4 device polls for new data, the outgoing frame containing
* the next fragment is placed in i_frame.
/* 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 network will handle only a single outgong frame at a time. The
* IEEE802.15.4 MAC driver design may be concurrently sending and
* requesting new framesusing break-off fram buffers. That frame buffer
* management must be controlled by the IEEE802.15.4 MAC driver.
* 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().
*
* Driver provided frame buffers should of size CONFIG_NET_6LOWPAN_FRAMELEN
* and should be 16-bit aligned.
* 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.
*/
FAR uint8_t *i_frame;
/* The length of valid data in the i_frame buffer.
*
* When the network device driver calls the network input function,
* i_framelen should be set to zero. If there is frame to be sent
* by the network, i_framelen will be set to indicate the size of
* frame to be sent. The value zero means that there is no frame
* to be sent.
*/
uint16_t i_framelen;
FAR struct iob_s *i_framelist;
/* 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

View File

@ -277,9 +277,10 @@ static int sixlowpan_802154_hdrlen(FAR struct frame802154_s *finfo)
*
* Input parameters:
* ieee - A reference IEEE802.15.4 MAC network device structure.
* params - Where to put the parmeters
* 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.
* params - Where to put the parmeters
*
* Returned Value:
* None.
@ -287,8 +288,8 @@ static int sixlowpan_802154_hdrlen(FAR struct frame802154_s *finfo)
****************************************************************************/
static void sixlowpan_setup_params(FAR struct ieee802154_driver_s *ieee,
FAR struct frame802154_s *params,
uint16_t dest_panid)
FAR struct iob_s *iob, uint16_t dest_panid,
FAR struct frame802154_s *params)
{
bool rcvrnull;
@ -298,7 +299,6 @@ static void sixlowpan_setup_params(FAR struct ieee802154_driver_s *ieee,
/* Reset to an empty frame */
ieee->i_framelen = 0;
ieee->i_dataoffset = 0;
/* Build the FCF (Only non-zero elements need to be initialized). */
@ -370,10 +370,13 @@ static void sixlowpan_setup_params(FAR struct ieee802154_driver_s *ieee,
rimeaddr_copy((struct rimeaddr_s *)&params->src_addr, &ieee->i_nodeaddr.u8);
/* Configure the payload address and length */
/* Configure the (optional) payload address and length */
params->payload = FRAME_DATA_START(ieee);
params->payload_len = FRAME_DATA_SIZE(ieee);
if (iob != NULL)
{
params->payload = FRAME_DATA_START(ieee, iob);
params->payload_len = FRAME_DATA_SIZE(ieee, iob);
}
}
/****************************************************************************
@ -406,7 +409,7 @@ int sixlowpan_hdrlen(FAR struct ieee802154_driver_s *ieee,
/* Set up the frame parameters */
sixlowpan_setup_params(ieee, &params, dest_panid);
sixlowpan_setup_params(ieee, NULL, dest_panid, &params);
/* Return the length of the header */
@ -521,6 +524,7 @@ int sixlowpan_802154_framecreate(FAR struct frame802154_s *finfo,
*
* 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.
*
@ -531,7 +535,7 @@ int sixlowpan_802154_framecreate(FAR struct frame802154_s *finfo,
****************************************************************************/
int sixlowpan_framecreate(FAR struct ieee802154_driver_s *ieee,
uint16_t dest_panid)
FAR struct iob_s *iob, uint16_t dest_panid)
{
struct frame802154_s params;
int len;
@ -539,7 +543,7 @@ int sixlowpan_framecreate(FAR struct ieee802154_driver_s *ieee,
/* Set up the frame parameters */
sixlowpan_setup_params(ieee, &params, dest_panid);
sixlowpan_setup_params(ieee, iob, dest_panid, &params);
/* Get the length of the header */
@ -547,7 +551,7 @@ int sixlowpan_framecreate(FAR struct ieee802154_driver_s *ieee,
/* Allocate space for the header in the frame buffer */
ret = sixlowpan_frame_hdralloc(ieee, len);
ret = sixlowpan_frame_hdralloc(ieee, iob, len);
if (ret < 0)
{
wlerr("ERROR: Header too large: %u\n", len);
@ -556,11 +560,11 @@ int sixlowpan_framecreate(FAR struct ieee802154_driver_s *ieee,
/* Then create the frame */
sixlowpan_802154_framecreate(&params, FRAME_HDR_START(ieee), len);
sixlowpan_802154_framecreate(&params, FRAME_HDR_START(ieee, iob), len);
wlinfo("Frame type: %02x Data len: %d %u (%u)\n",
params.fcf.frame_type, len, FRAME_DATA_SIZE(ieee),
FRAME_SIZE(ieee));
params.fcf.frame_type, len, FRAME_DATA_SIZE(ieee, iob),
FRAME_SIZE(ieee, iob));
#if CONFIG_NET_6LOWPAN_RIMEADDR_SIZE == 2
wlinfo("Dest address: %02x:%02x\n",
params.dest_addr[0], params.dest_addr[1]);

View File

@ -87,24 +87,23 @@
do \
{ \
(ieee)->i_dataoffset = 0; \
(ieee)->i_framelen = 0; \
} \
while (0)
#define FRAME_HDR_START(ieee) \
((ieee)->i_frame)
#define FRAME_HDR_SIZE(ieee) \
#define FRAME_HDR_START(ieee,iob) \
((iob)->io_data)
#define FRAME_HDR_SIZE(ieee,iob) \
((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_DATA_START(ieee,iob) \
((FAR uint8_t *)((iob)->io_data) + (ieee)->i_dataoffset)
#define FRAME_DATA_SIZE(ieee,iob) \
((iob)->io_len - (ieee)->i_dataoffset)
#define FRAME_REMAINING(ieee) \
(CONFIG_NET_6LOWPAN_FRAMELEN - (ieee)->i_framelen)
#define FRAME_SIZE(ieee) \
((ieee)->i_framelen)
#define FRAME_REMAINING(ieee,iob) \
(CONFIG_NET_6LOWPAN_FRAMELEN - (iob)->io_len)
#define FRAME_SIZE(ieee,iob) \
((iob)->io_len)
/* These are some definitions of element values used in the FCF. See the
* IEEE802.15.4 spec for details.
@ -254,6 +253,7 @@ extern FAR struct sixlowpan_rime_sniffer_s *g_sixlowpan_sniffer;
struct net_driver_s; /* Forward reference */
struct ieee802154_driver_s; /* Forward reference */
struct rimeaddr_s; /* Forward reference */
struct iob_s; /* Forward reference */
/****************************************************************************
* Name: sixlowpan_send
@ -263,12 +263,11 @@ struct rimeaddr_s; /* Forward reference */
* 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'.
* Compressed headers will be added and if necessary the packet is
* fragmented. The resulting packet/fragments are put in dev->d_buf and
* the first frame will be delivered to the 802.15.4 MAC. via ieee->i_frame.
*
* Input Parmeters:
* The payload data is in the caller 'buf' and is of length 'len'.
* 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.
*
* Input Parameters:
* dev - The IEEE802.15.4 MAC network driver interface.
@ -323,6 +322,7 @@ int sixlowpan_hdrlen(FAR struct ieee802154_driver_s *ieee,
*
* 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.
*
@ -333,7 +333,7 @@ int sixlowpan_hdrlen(FAR struct ieee802154_driver_s *ieee,
****************************************************************************/
int sixlowpan_framecreate(FAR struct ieee802154_driver_s *ieee,
uint16_t dest_panid);
FAR struct iob_s *iob, uint16_t dest_panid);
/****************************************************************************
* Name: sixlowpan_hc06_initialize
@ -474,12 +474,12 @@ void sixlowpan_uncompresshdr_hc1(FAR struct net_driver_s *dev,
* Name: sixlowpan_frame_hdralloc
*
* Description:
* Allocate space for a header within the frame buffer (i_frame).
* Allocate space for a header within the frame buffer (IOB).
*
****************************************************************************/
int sixlowpan_frame_hdralloc(FAR struct ieee802154_driver_s *ieee,
int size);
FAR struct iob_s *iob, int size);
#endif /* CONFIG_NET_6LOWPAN */
#endif /* _NET_SIXLOWPAN_SIXLOWPAN_INTERNAL_H */

View File

@ -218,7 +218,7 @@ static int sixlowpan_send_frame(FAR struct ieee802154_driver_s *ieee,
#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;
iob->io_len = 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 */
@ -240,12 +240,11 @@ static int sixlowpan_send_frame(FAR struct ieee802154_driver_s *ieee,
* 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'.
* Compressed headers will be added and if necessary the packet is
* fragmented. The resulting packet/fragments are put in dev->d_buf and
* the first frame will be delivered to the 802.15.4 MAC. via ieee->i_frame.
*
* Input Parmeters:
* The payload data is in the caller 'buf' and is of length 'len'.
* 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.
*
* Input Parameters:
* dev - The IEEE802.15.4 MAC network driver interface.
@ -380,7 +379,7 @@ int sixlowpan_send(FAR struct net_driver_s *dev,
{
/* Failed to determine the size of the header failed. */
nerr("ERROR: sixlowpan_framecreate() failed: %d\n", framer_hdrlen);
nerr("ERROR: sixlowpan_hdrlen() failed: %d\n", framer_hdrlen);
return framer_hdrlen;
}

View File

@ -44,7 +44,9 @@
* SUCH DAMAGE.
*
****************************************************************************/
/* Frame Organization:
/* Frame Organization. The IOB data is retained in the io_data[] field of the
* IOB structure like:
*
* Content Offset
* +------------------+ 0
@ -52,7 +54,7 @@
* +------------------+ i_dataoffset
* | Procotol Headers |
* | Data Payload |
* +------------------+ i_framelen
* +------------------+ io_len
* | Unused |
* +------------------+ CONFIG_NET_6LOWPAN_FRAMELEN
*/
@ -85,12 +87,12 @@
****************************************************************************/
int sixlowpan_frame_hdralloc(FAR struct ieee802154_driver_s *ieee,
int size)
FAR struct iob_s *iob, int size)
{
if (size <= FRAME_REMAINING(ieee))
if (size <= FRAME_REMAINING(ieee, iob))
{
ieee->i_dataoffset += size;
ieee->i_framelen += size;
iob->io_len += size;
return OK;
}