2017-08-26 18:00:47 +02:00
|
|
|
/****************************************************************************
|
2021-03-08 22:39:04 +01:00
|
|
|
* net/sixlowpan/sixlowpan_reassbuf.c
|
2017-08-26 18:00:47 +02:00
|
|
|
*
|
2021-02-19 12:45:37 +01:00
|
|
|
* 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
|
2017-08-26 18:00:47 +02:00
|
|
|
*
|
2021-02-19 12:45:37 +01:00
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
2017-08-26 18:00:47 +02:00
|
|
|
*
|
2021-02-19 12:45:37 +01:00
|
|
|
* 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.
|
2017-08-26 18:00:47 +02:00
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Included Files
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
#include <nuttx/config.h>
|
|
|
|
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <stdbool.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <assert.h>
|
2021-05-14 04:45:57 +02:00
|
|
|
#include <debug.h>
|
2017-08-26 18:00:47 +02:00
|
|
|
#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
|
|
|
|
****************************************************************************/
|
|
|
|
|
2020-04-09 14:46:24 +02:00
|
|
|
/* 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.
|
2017-08-26 18:00:47 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
2020-02-23 09:50:23 +01:00
|
|
|
/* Pool of pre-allocated reassembly buffer structures */
|
2017-08-26 18:00:47 +02:00
|
|
|
|
2020-04-09 14:46:24 +02:00
|
|
|
static struct sixlowpan_reassbuf_s
|
|
|
|
g_metadata_pool[CONFIG_NET_6LOWPAN_NREASSBUF];
|
2017-08-26 18:00:47 +02:00
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Public Functions
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* Name: sixlowpan_compare_fragsrc
|
|
|
|
*
|
|
|
|
* Description:
|
|
|
|
* Check if the fragment that we just received is from the same source as
|
2020-02-23 09:50:23 +01:00
|
|
|
* the previously received fragments.
|
2017-08-26 18:00:47 +02:00
|
|
|
*
|
|
|
|
* 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,
|
2020-04-09 14:46:24 +02:00
|
|
|
FAR const struct netdev_varaddr_s *fragsrc)
|
2017-08-26 18:00:47 +02:00
|
|
|
{
|
|
|
|
/* 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 */
|
2017-08-26 18:00:47 +02:00
|
|
|
|
|
|
|
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.
|
|
|
|
*
|
2018-02-01 17:00:02 +01:00
|
|
|
* Input Parameters:
|
2017-08-26 18:00:47 +02:00
|
|
|
* None
|
|
|
|
*
|
2018-02-01 17:00:02 +01:00
|
|
|
* Returned Value:
|
2017-08-26 18:00:47 +02:00
|
|
|
* None
|
|
|
|
*
|
|
|
|
* Assumptions:
|
|
|
|
* The network is locked.
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
static void sixlowpan_reass_expire(void)
|
|
|
|
{
|
|
|
|
FAR struct sixlowpan_reassbuf_s *reass;
|
|
|
|
FAR struct sixlowpan_reassbuf_s *next;
|
2018-06-16 20:16:13 +02:00
|
|
|
clock_t elapsed;
|
2017-08-26 18:00:47 +02:00
|
|
|
|
|
|
|
/* 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 */
|
|
|
|
|
2020-05-04 16:15:10 +02:00
|
|
|
elapsed = clock_systime_ticks() - reass->rb_time;
|
2017-08-26 18:00:47 +02:00
|
|
|
|
|
|
|
/* If the reassembly has expired, then free the reassembly buffer */
|
|
|
|
|
2020-01-04 11:37:46 +01:00
|
|
|
if (elapsed >= NET_6LOWPAN_TIMEOUT)
|
2017-08-26 18:00:47 +02:00
|
|
|
{
|
|
|
|
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.
|
|
|
|
*
|
2018-02-01 17:00:02 +01:00
|
|
|
* Input Parameters:
|
2017-08-26 18:00:47 +02:00
|
|
|
* reass - The reassembly buffer to be removed.
|
|
|
|
*
|
2018-02-01 17:00:02 +01:00
|
|
|
* Returned Value:
|
2017-08-26 18:00:47 +02:00
|
|
|
* 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.
|
|
|
|
*
|
2018-02-01 17:00:02 +01:00
|
|
|
* Input Parameters:
|
2017-08-26 18:00:47 +02:00
|
|
|
* None
|
|
|
|
*
|
2018-02-01 17:00:02 +01:00
|
|
|
* Returned Value:
|
2017-08-26 18:00:47 +02:00
|
|
|
* None
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
void sixlowpan_reass_initialize(void)
|
|
|
|
{
|
|
|
|
FAR struct sixlowpan_reassbuf_s *reass;
|
|
|
|
int i;
|
|
|
|
|
2020-04-09 14:46:24 +02:00
|
|
|
/* Initialize g_free_reass, the list of reassembly buffer structures that
|
|
|
|
* are available for allocation.
|
2017-08-26 18:00:47 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
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.
|
|
|
|
*
|
2018-02-01 17:00:02 +01:00
|
|
|
* Input Parameters:
|
2017-08-26 18:00:47 +02:00
|
|
|
* reasstag - The reassembly tag for subsequent lookup.
|
|
|
|
* fragsrc - The source address of the fragment.
|
|
|
|
*
|
2018-02-01 17:00:02 +01:00
|
|
|
* Returned Value:
|
2017-08-26 18:00:47 +02:00
|
|
|
* 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
|
2020-04-09 14:46:24 +02:00
|
|
|
/* If we cannot get a reassembly buffer instance from the free list,
|
|
|
|
* then we will have to allocate one from the kernel memory pool.
|
2017-08-26 18:00:47 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
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;
|
2020-05-04 16:15:10 +02:00
|
|
|
reass->rb_time = clock_systime_ticks();
|
2017-08-26 18:00:47 +02:00
|
|
|
|
|
|
|
/* 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.
|
|
|
|
*
|
2018-02-01 17:00:02 +01:00
|
|
|
* Input Parameters:
|
2017-08-26 18:00:47 +02:00
|
|
|
* reasstag - The reassembly tag to match.
|
|
|
|
* fragsrc - The source address of the fragment.
|
|
|
|
*
|
2018-02-01 17:00:02 +01:00
|
|
|
* Returned Value:
|
2017-08-26 18:00:47 +02:00
|
|
|
* 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.
|
|
|
|
*
|
2018-02-01 17:00:02 +01:00
|
|
|
* Input Parameters:
|
2017-08-26 18:00:47 +02:00
|
|
|
* reass - reass structure to free
|
|
|
|
*
|
2018-02-01 17:00:02 +01:00
|
|
|
* Returned Value:
|
2017-08-26 18:00:47 +02:00
|
|
|
* 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);
|
|
|
|
|
2020-04-09 14:46:24 +02:00
|
|
|
/* If this is a pre-allocated reassembly buffer structure, then just put it
|
|
|
|
* back in the free list.
|
2017-08-26 18:00:47 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
if (reass->rb_pool == REASS_POOL_PREALLOCATED)
|
|
|
|
{
|
|
|
|
reass->rb_flink = g_free_reass;
|
|
|
|
g_free_reass = reass;
|
|
|
|
}
|
2017-11-01 21:15:21 +01:00
|
|
|
else if (reass->rb_pool == REASS_POOL_DYNAMIC)
|
2017-08-26 18:00:47 +02:00
|
|
|
{
|
|
|
|
#ifdef CONFIG_NET_6LOWPAN_REASS_STATIC
|
|
|
|
DEBUGPANIC();
|
|
|
|
#else
|
|
|
|
DEBUGASSERT(reass->rb_pool == REASS_POOL_DYNAMIC);
|
|
|
|
|
|
|
|
/* Otherwise, deallocate it. */
|
|
|
|
|
2020-04-07 16:31:47 +02:00
|
|
|
kmm_free(reass);
|
2017-08-26 18:00:47 +02:00
|
|
|
#endif
|
|
|
|
}
|
2017-11-01 21:15:21 +01:00
|
|
|
|
|
|
|
/* If the reassembly buffer structure was provided by the driver, nothing
|
|
|
|
* needs to be freed.
|
|
|
|
*/
|
2017-08-26 18:00:47 +02:00
|
|
|
}
|