nuttx/net/sixlowpan/sixlowpan_reassbuf.c

444 lines
12 KiB
C
Raw Normal View History

/****************************************************************************
* net/sixlowpan/sixlowpan_reassbuf.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <assert.h>
#include <debug.h>
#include <errno.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 structures */
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 previously received fragments.
*
* 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)
{
2017-08-26 19:50:41 +02:00
/* 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.
*
* Input Parameters:
* None
*
* Returned 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;
clock_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_systime_ticks() - 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.
*
* Input Parameters:
* reass - The reassembly buffer to be removed.
*
* Returned 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.
*
* Input Parameters:
* None
*
* Returned 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.
*
* Input Parameters:
* reasstag - The reassembly tag for subsequent lookup.
* fragsrc - The source address of the fragment.
*
* Returned 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 kernel 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_systime_ticks();
/* 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.
*
* Input Parameters:
* reasstag - The reassembly tag to match.
* fragsrc - The source address of the fragment.
*
* Returned 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.
*
* Input Parameters:
* reass - reass structure to free
*
* Returned 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;
}
Merged in antmerlino/nuttx/sixlowpan-mac802154 (pull request #526) 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>
2017-11-01 21:15:21 +01:00
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. */
kmm_free(reass);
#endif
}
Merged in antmerlino/nuttx/sixlowpan-mac802154 (pull request #526) 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>
2017-11-01 21:15:21 +01:00
/* If the reassembly buffer structure was provided by the driver, nothing
* needs to be freed.
*/
}