14fb37c995
ieee802154: Simplifies notify() and rxframe() calls to a single notify() call. dataind's and all other "notifs" are now "primitives" which aligns with standard terminology * mac802154: Adds missing breaks from case statement * sixlowpan: Fixes bad logic where ACK is not requested if address is not a broadcast * ieee802154: Simplification of "notifs" and "datainds" to generic primitives passed via a single notify call to the layer above the MAC * Directories.mk should reference CONFIG_WIRELESS instead of CONFIG_DRIVERS_WIRELESS * xbee_netdev: Network must be locked when calling sixlowpan_input * sixlowpan: Reassembly buffer can't be freed if provided by radio driver * sixlowpan: Don't free IOB if there is an error processing it as the MAC will try to pass it along to another receiver * ieee802154: Adds basic logging to ieee802154_primitive.c * Minor fixes after rebase * xbee: Adds AT query timeout to retry if XBee doesn't respond to request * same70-xplained: Adds Xbee support. Makes mikroBus slot Kconfig 'choice' * mac802154: Removes unused function declaration * drivers/mrf24j40: Fixes compilation error using . operator rather than -> operator * mac802154_device: Changes a few mac802154_primtive_free's to ieee802154_primitive_free() and changes notif to primitive in a couple places. * mac802154: Adds promiscous mode logic to bypass parsing of incoming frames. MAC char device also checks for promiscous mode and passes whole frames including header and FCS to the application if promiscous mode is enabled. * sixlowpan: Fixes logic to correctly check if packet is large enough to include header. This would cause packets to be considered too small when they are sufficiently sized. * sixlowpan: Fixes forwarding logic to use forwarding device rather than received device to look up destination link layer address * net/ipforward: Fixes typo that caused build error when IP forwarding was enabled with CONFIG_NET_ICMPv6_NEIGHBOR enabled as well. * configs/same70-xplained: Simple spelling fix Approved-by: Gregory Nutt <gnutt@nuttx.org>
459 lines
13 KiB
C
459 lines
13 KiB
C
/****************************************************************************
|
|
* net/sixlowpan/sixlowpan_reassbuf.c
|
|
*
|
|
* Copyright (C) 2017 Gregory Nutt. All rights reserved.
|
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
|
*
|
|
* 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 NuttX 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.
|
|
*
|
|
****************************************************************************/
|
|
|
|
/****************************************************************************
|
|
* Included Files
|
|
****************************************************************************/
|
|
|
|
#include <nuttx/config.h>
|
|
|
|
#include <stdint.h>
|
|
#include <stdbool.h>
|
|
#include <string.h>
|
|
#include <semaphore.h>
|
|
#include <assert.h>
|
|
#include <errno.h>
|
|
|
|
#include <nuttx/clock.h>
|
|
#include <nuttx/kmalloc.h>
|
|
#include <nuttx/mm/iob.h>
|
|
|
|
#include "sixlowpan_internal.h"
|
|
|
|
/****************************************************************************
|
|
* Pre-processor Definitions
|
|
****************************************************************************/
|
|
|
|
/* Re-assembly timeout in clock ticks */
|
|
|
|
#define NET_6LOWPAN_TIMEOUT SEC2TICK(CONFIG_NET_6LOWPAN_MAXAGE)
|
|
|
|
/****************************************************************************
|
|
* Private Data
|
|
****************************************************************************/
|
|
|
|
/* The g_free_reass is a list of reassembly buffer structures that are available for
|
|
* general use. The number of messages in this list is a system configuration
|
|
* item. Protected only by the network lock.
|
|
*/
|
|
|
|
static FAR struct sixlowpan_reassbuf_s *g_free_reass;
|
|
|
|
/* This is a list of active, allocated reassemby buffers */
|
|
|
|
static FAR struct sixlowpan_reassbuf_s *g_active_reass;
|
|
|
|
/* Pool of pre-allocated reassembly buffer stuctures */
|
|
|
|
static struct sixlowpan_reassbuf_s g_metadata_pool[CONFIG_NET_6LOWPAN_NREASSBUF];
|
|
|
|
/****************************************************************************
|
|
* Public Functions
|
|
****************************************************************************/
|
|
|
|
/****************************************************************************
|
|
* Name: sixlowpan_compare_fragsrc
|
|
*
|
|
* Description:
|
|
* Check if the fragment that we just received is from the same source as
|
|
* the previosly received fragements.
|
|
*
|
|
* Input Parameters:
|
|
* radio - Radio network device driver state instance
|
|
* fragsrc - The source address of the fragment.
|
|
*
|
|
* Returned Value:
|
|
* true if the sources are the same.
|
|
*
|
|
****************************************************************************/
|
|
|
|
static bool sixlowpan_compare_fragsrc(FAR struct sixlowpan_reassbuf_s *reass,
|
|
FAR const struct netdev_varaddr_s *fragsrc)
|
|
{
|
|
/* The addresses cannot match if they are not the same size */
|
|
|
|
if (fragsrc->nv_addrlen == reass->rb_fragsrc.nv_addrlen)
|
|
{
|
|
/* The are the same size, return the address comparison */
|
|
|
|
return (memcmp(fragsrc->nv_addr, reass->rb_fragsrc.nv_addr,
|
|
fragsrc->nv_addrlen) == 0);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: sixlowpan_reass_expire
|
|
*
|
|
* Description:
|
|
* Free all expired or inactive reassembly buffers.
|
|
*
|
|
* Inputs:
|
|
* None
|
|
*
|
|
* Return Value:
|
|
* None
|
|
*
|
|
* Assumptions:
|
|
* The network is locked.
|
|
*
|
|
****************************************************************************/
|
|
|
|
static void sixlowpan_reass_expire(void)
|
|
{
|
|
FAR struct sixlowpan_reassbuf_s *reass;
|
|
FAR struct sixlowpan_reassbuf_s *next;
|
|
systime_t elapsed;
|
|
|
|
/* If reassembly timed out, cancel it */
|
|
|
|
for (reass = g_active_reass; reass != NULL; reass = next)
|
|
{
|
|
/* Needed if 'reass' is freed */
|
|
|
|
next = reass->rb_flink;
|
|
|
|
/* Free any inactive reassembly buffers. This is done because the life
|
|
* the reassembly buffer is not cerain.
|
|
*/
|
|
|
|
if (!reass->rb_active)
|
|
{
|
|
sixlowpan_reass_free(reass);
|
|
}
|
|
else
|
|
{
|
|
/* Get the elpased time of the reassembly */
|
|
|
|
elapsed = clock_systimer() - reass->rb_time;
|
|
|
|
/* If the reassembly has expired, then free the reassembly buffer */
|
|
|
|
if (elapsed > NET_6LOWPAN_TIMEOUT)
|
|
{
|
|
nwarn("WARNING: Reassembly timed out\n");
|
|
sixlowpan_reass_free(reass);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: sixlowpan_remove_active
|
|
*
|
|
* Description:
|
|
* Remove a reassembly buffer from the active reassembly buffer list.
|
|
*
|
|
* Inputs:
|
|
* reass - The reassembly buffer to be removed.
|
|
*
|
|
* Return Value:
|
|
* None
|
|
*
|
|
* Assumptions:
|
|
* The network is locked.
|
|
*
|
|
****************************************************************************/
|
|
|
|
static void sixlowpan_remove_active(FAR struct sixlowpan_reassbuf_s *reass)
|
|
{
|
|
FAR struct sixlowpan_reassbuf_s *curr;
|
|
FAR struct sixlowpan_reassbuf_s *prev;
|
|
|
|
/* Find the reassembly buffer in the list of active reassembly buffers */
|
|
|
|
for (prev = NULL, curr = g_active_reass;
|
|
curr != NULL && curr != reass;
|
|
prev = curr, curr = curr->rb_flink)
|
|
{
|
|
}
|
|
|
|
/* Did we find it? */
|
|
|
|
if (curr != NULL)
|
|
{
|
|
/* Yes.. remove it from the active reassembly buffer list */
|
|
|
|
if (prev == NULL)
|
|
{
|
|
g_active_reass = reass->rb_flink;
|
|
}
|
|
else
|
|
{
|
|
prev->rb_flink = reass->rb_flink;
|
|
}
|
|
}
|
|
|
|
reass->rb_flink = NULL;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Public Functions
|
|
****************************************************************************/
|
|
|
|
/****************************************************************************
|
|
* Name: sixlowpan_reass_initialize
|
|
*
|
|
* Description:
|
|
* This function initializes the reassembly buffer allocator. This
|
|
* function must be called early in the initialization sequence before
|
|
* any radios begin operation.
|
|
*
|
|
* Called only once during network initialization.
|
|
*
|
|
* Inputs:
|
|
* None
|
|
*
|
|
* Return Value:
|
|
* None
|
|
*
|
|
****************************************************************************/
|
|
|
|
void sixlowpan_reass_initialize(void)
|
|
{
|
|
FAR struct sixlowpan_reassbuf_s *reass;
|
|
int i;
|
|
|
|
/* Initialize g_free_reass, the list of reassembly buffer structures that are
|
|
* available for allocation.
|
|
*/
|
|
|
|
g_free_reass = NULL;
|
|
for (i = 0, reass = g_metadata_pool;
|
|
i < CONFIG_NET_6LOWPAN_NREASSBUF;
|
|
i++, reass++)
|
|
{
|
|
/* Add the next meta data structure from the pool to the list of
|
|
* general structures.
|
|
*/
|
|
|
|
reass->rb_flink = g_free_reass;
|
|
g_free_reass = reass;
|
|
}
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: sixlowpan_reass_allocate
|
|
*
|
|
* Description:
|
|
* The sixlowpan_reass_allocate function will get a free reassembly buffer
|
|
* structure for use by 6LoWPAN.
|
|
*
|
|
* This function will first attempt to allocate from the g_free_reass
|
|
* list. If that the list is empty, then the reassembly buffer structure
|
|
* will be allocated from the dynamic memory pool.
|
|
*
|
|
* Inputs:
|
|
* reasstag - The reassembly tag for subsequent lookup.
|
|
* fragsrc - The source address of the fragment.
|
|
*
|
|
* Return Value:
|
|
* A reference to the allocated reass structure. All fields used by the
|
|
* reasembly logic have been zeroed. On a failure to allocate, NULL is
|
|
* returned.
|
|
*
|
|
* Assumptions:
|
|
* The network is locked.
|
|
*
|
|
****************************************************************************/
|
|
|
|
FAR struct sixlowpan_reassbuf_s *
|
|
sixlowpan_reass_allocate(uint16_t reasstag,
|
|
FAR const struct netdev_varaddr_s *fragsrc)
|
|
{
|
|
FAR struct sixlowpan_reassbuf_s *reass;
|
|
uint8_t pool;
|
|
|
|
/* First, removed any expired or inactive reassembly buffers. This might
|
|
* free up a pre-allocated buffer for this allocation.
|
|
*/
|
|
|
|
sixlowpan_reass_expire();
|
|
|
|
/* Now, try the free list first */
|
|
|
|
if (g_free_reass != NULL)
|
|
{
|
|
reass = g_free_reass;
|
|
g_free_reass = reass->rb_flink;
|
|
pool = REASS_POOL_PREALLOCATED;
|
|
}
|
|
else
|
|
{
|
|
#ifdef CONFIG_NET_6LOWPAN_REASS_STATIC
|
|
reass = NULL;
|
|
#else
|
|
/* If we cannot get a reassembly buffer instance from the free list, then we
|
|
* will have to allocate one from the kernal memory pool.
|
|
*/
|
|
|
|
reass = (FAR struct sixlowpan_reassbuf_s *)
|
|
kmm_malloc((sizeof (struct sixlowpan_reassbuf_s)));
|
|
pool = REASS_POOL_DYNAMIC;
|
|
#endif
|
|
}
|
|
|
|
/* We have successfully allocated memory from some source? */
|
|
|
|
if (reass != NULL)
|
|
{
|
|
/* Zero and tag the allocated reassembly buffer structure. */
|
|
|
|
memset(reass, 0, sizeof(struct sixlowpan_reassbuf_s));
|
|
memcpy(&reass->rb_fragsrc, fragsrc, sizeof(struct netdev_varaddr_s));
|
|
reass->rb_pool = pool;
|
|
reass->rb_active = true;
|
|
reass->rb_reasstag = reasstag;
|
|
reass->rb_time = clock_systimer();
|
|
|
|
/* Add the reassembly buffer to the list of active reassembly buffers */
|
|
|
|
reass->rb_flink = g_active_reass;
|
|
g_active_reass = reass;
|
|
}
|
|
|
|
return reass;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: sixlowpan_reass_find
|
|
*
|
|
* Description:
|
|
* Find a previously allocated, active reassembly buffer with the specified
|
|
* reassembly tag.
|
|
*
|
|
* Inputs:
|
|
* reasstag - The reassembly tag to match.
|
|
* fragsrc - The source address of the fragment.
|
|
*
|
|
* Return Value:
|
|
* A reference to the matching reass structure.
|
|
*
|
|
* Assumptions:
|
|
* The network is locked.
|
|
*
|
|
****************************************************************************/
|
|
|
|
FAR struct sixlowpan_reassbuf_s *
|
|
sixlowpan_reass_find(uint16_t reasstag,
|
|
FAR const struct netdev_varaddr_s *fragsrc)
|
|
{
|
|
FAR struct sixlowpan_reassbuf_s *reass;
|
|
|
|
/* First, removed any expired or inactive reassembly buffers (we don't want
|
|
* to return old reassembly buffer with the same tag)
|
|
*/
|
|
|
|
sixlowpan_reass_expire();
|
|
|
|
/* Now search for the matching reassembly buffer in the remainng, active
|
|
* reassembly buffers.
|
|
*/
|
|
|
|
for (reass = g_active_reass; reass != NULL; reass = reass->rb_flink)
|
|
{
|
|
/* In order to be a match, it must have the same reassembly tag as
|
|
* well as source address (different sources might use the same
|
|
* reassembly tag).
|
|
*/
|
|
|
|
if (reass->rb_reasstag == reasstag &&
|
|
sixlowpan_compare_fragsrc(reass, fragsrc))
|
|
{
|
|
return reass;
|
|
}
|
|
}
|
|
|
|
/* Not found */
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: sixlowpan_reass_free
|
|
*
|
|
* Description:
|
|
* The sixlowpan_reass_free function will return a reass structure
|
|
* to the free list of messages if it was a pre-allocated reass
|
|
* structure. If the reass structure was allocated dynamically it will
|
|
* be deallocated.
|
|
*
|
|
* Inputs:
|
|
* reass - reass structure to free
|
|
*
|
|
* Return Value:
|
|
* None
|
|
*
|
|
* Assumptions:
|
|
* The network is locked.
|
|
*
|
|
****************************************************************************/
|
|
|
|
void sixlowpan_reass_free(FAR struct sixlowpan_reassbuf_s *reass)
|
|
{
|
|
/* First, remove the reassembly buffer from the list of active reassembly
|
|
* buffers.
|
|
*/
|
|
|
|
sixlowpan_remove_active(reass);
|
|
|
|
/* If this is a pre-allocated reassembly buffer structure, then just put it back
|
|
* in the free list.
|
|
*/
|
|
|
|
if (reass->rb_pool == REASS_POOL_PREALLOCATED)
|
|
{
|
|
reass->rb_flink = g_free_reass;
|
|
g_free_reass = reass;
|
|
}
|
|
else if (reass->rb_pool == REASS_POOL_DYNAMIC)
|
|
{
|
|
#ifdef CONFIG_NET_6LOWPAN_REASS_STATIC
|
|
DEBUGPANIC();
|
|
#else
|
|
DEBUGASSERT(reass->rb_pool == REASS_POOL_DYNAMIC);
|
|
|
|
/* Otherwise, deallocate it. */
|
|
|
|
sched_kfree(reass);
|
|
#endif
|
|
}
|
|
|
|
/* If the reassembly buffer structure was provided by the driver, nothing
|
|
* needs to be freed.
|
|
*/
|
|
}
|