123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442 |
- /****************************************************************************
- * 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 <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)
- {
- /* 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;
- }
- 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
- }
- /* If the reassembly buffer structure was provided by the driver, nothing
- * needs to be freed.
- */
- }
|