sixlowpan_reassbuf.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442
  1. /****************************************************************************
  2. * net/sixlowpan/sixlowpan_reassbuf.c
  3. *
  4. * Licensed to the Apache Software Foundation (ASF) under one or more
  5. * contributor license agreements. See the NOTICE file distributed with
  6. * this work for additional information regarding copyright ownership. The
  7. * ASF licenses this file to you under the Apache License, Version 2.0 (the
  8. * "License"); you may not use this file except in compliance with the
  9. * License. You may obtain a copy of the License at
  10. *
  11. * http://www.apache.org/licenses/LICENSE-2.0
  12. *
  13. * Unless required by applicable law or agreed to in writing, software
  14. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  15. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  16. * License for the specific language governing permissions and limitations
  17. * under the License.
  18. *
  19. ****************************************************************************/
  20. /****************************************************************************
  21. * Included Files
  22. ****************************************************************************/
  23. #include <nuttx/config.h>
  24. #include <stdint.h>
  25. #include <stdbool.h>
  26. #include <string.h>
  27. #include <assert.h>
  28. #include <errno.h>
  29. #include <nuttx/kmalloc.h>
  30. #include <nuttx/mm/iob.h>
  31. #include "sixlowpan_internal.h"
  32. /****************************************************************************
  33. * Pre-processor Definitions
  34. ****************************************************************************/
  35. /* Re-assembly timeout in clock ticks */
  36. #define NET_6LOWPAN_TIMEOUT SEC2TICK(CONFIG_NET_6LOWPAN_MAXAGE)
  37. /****************************************************************************
  38. * Private Data
  39. ****************************************************************************/
  40. /* The g_free_reass is a list of reassembly buffer structures that are
  41. * available for general use. The number of messages in this list is a
  42. * system configuration item. Protected only by the network lock.
  43. */
  44. static FAR struct sixlowpan_reassbuf_s *g_free_reass;
  45. /* This is a list of active, allocated reassemby buffers */
  46. static FAR struct sixlowpan_reassbuf_s *g_active_reass;
  47. /* Pool of pre-allocated reassembly buffer structures */
  48. static struct sixlowpan_reassbuf_s
  49. g_metadata_pool[CONFIG_NET_6LOWPAN_NREASSBUF];
  50. /****************************************************************************
  51. * Public Functions
  52. ****************************************************************************/
  53. /****************************************************************************
  54. * Name: sixlowpan_compare_fragsrc
  55. *
  56. * Description:
  57. * Check if the fragment that we just received is from the same source as
  58. * the previously received fragments.
  59. *
  60. * Input Parameters:
  61. * radio - Radio network device driver state instance
  62. * fragsrc - The source address of the fragment.
  63. *
  64. * Returned Value:
  65. * true if the sources are the same.
  66. *
  67. ****************************************************************************/
  68. static bool sixlowpan_compare_fragsrc(FAR struct sixlowpan_reassbuf_s *reass,
  69. FAR const struct netdev_varaddr_s *fragsrc)
  70. {
  71. /* The addresses cannot match if they are not the same size */
  72. if (fragsrc->nv_addrlen == reass->rb_fragsrc.nv_addrlen)
  73. {
  74. /* The are the same size, return the address comparison */
  75. return (memcmp(fragsrc->nv_addr, reass->rb_fragsrc.nv_addr,
  76. fragsrc->nv_addrlen) == 0);
  77. }
  78. return false;
  79. }
  80. /****************************************************************************
  81. * Name: sixlowpan_reass_expire
  82. *
  83. * Description:
  84. * Free all expired or inactive reassembly buffers.
  85. *
  86. * Input Parameters:
  87. * None
  88. *
  89. * Returned Value:
  90. * None
  91. *
  92. * Assumptions:
  93. * The network is locked.
  94. *
  95. ****************************************************************************/
  96. static void sixlowpan_reass_expire(void)
  97. {
  98. FAR struct sixlowpan_reassbuf_s *reass;
  99. FAR struct sixlowpan_reassbuf_s *next;
  100. clock_t elapsed;
  101. /* If reassembly timed out, cancel it */
  102. for (reass = g_active_reass; reass != NULL; reass = next)
  103. {
  104. /* Needed if 'reass' is freed */
  105. next = reass->rb_flink;
  106. /* Free any inactive reassembly buffers. This is done because the life
  107. * the reassembly buffer is not cerain.
  108. */
  109. if (!reass->rb_active)
  110. {
  111. sixlowpan_reass_free(reass);
  112. }
  113. else
  114. {
  115. /* Get the elpased time of the reassembly */
  116. elapsed = clock_systime_ticks() - reass->rb_time;
  117. /* If the reassembly has expired, then free the reassembly buffer */
  118. if (elapsed >= NET_6LOWPAN_TIMEOUT)
  119. {
  120. nwarn("WARNING: Reassembly timed out\n");
  121. sixlowpan_reass_free(reass);
  122. }
  123. }
  124. }
  125. }
  126. /****************************************************************************
  127. * Name: sixlowpan_remove_active
  128. *
  129. * Description:
  130. * Remove a reassembly buffer from the active reassembly buffer list.
  131. *
  132. * Input Parameters:
  133. * reass - The reassembly buffer to be removed.
  134. *
  135. * Returned Value:
  136. * None
  137. *
  138. * Assumptions:
  139. * The network is locked.
  140. *
  141. ****************************************************************************/
  142. static void sixlowpan_remove_active(FAR struct sixlowpan_reassbuf_s *reass)
  143. {
  144. FAR struct sixlowpan_reassbuf_s *curr;
  145. FAR struct sixlowpan_reassbuf_s *prev;
  146. /* Find the reassembly buffer in the list of active reassembly buffers */
  147. for (prev = NULL, curr = g_active_reass;
  148. curr != NULL && curr != reass;
  149. prev = curr, curr = curr->rb_flink)
  150. {
  151. }
  152. /* Did we find it? */
  153. if (curr != NULL)
  154. {
  155. /* Yes.. remove it from the active reassembly buffer list */
  156. if (prev == NULL)
  157. {
  158. g_active_reass = reass->rb_flink;
  159. }
  160. else
  161. {
  162. prev->rb_flink = reass->rb_flink;
  163. }
  164. }
  165. reass->rb_flink = NULL;
  166. }
  167. /****************************************************************************
  168. * Public Functions
  169. ****************************************************************************/
  170. /****************************************************************************
  171. * Name: sixlowpan_reass_initialize
  172. *
  173. * Description:
  174. * This function initializes the reassembly buffer allocator. This
  175. * function must be called early in the initialization sequence before
  176. * any radios begin operation.
  177. *
  178. * Called only once during network initialization.
  179. *
  180. * Input Parameters:
  181. * None
  182. *
  183. * Returned Value:
  184. * None
  185. *
  186. ****************************************************************************/
  187. void sixlowpan_reass_initialize(void)
  188. {
  189. FAR struct sixlowpan_reassbuf_s *reass;
  190. int i;
  191. /* Initialize g_free_reass, the list of reassembly buffer structures that
  192. * are available for allocation.
  193. */
  194. g_free_reass = NULL;
  195. for (i = 0, reass = g_metadata_pool;
  196. i < CONFIG_NET_6LOWPAN_NREASSBUF;
  197. i++, reass++)
  198. {
  199. /* Add the next meta data structure from the pool to the list of
  200. * general structures.
  201. */
  202. reass->rb_flink = g_free_reass;
  203. g_free_reass = reass;
  204. }
  205. }
  206. /****************************************************************************
  207. * Name: sixlowpan_reass_allocate
  208. *
  209. * Description:
  210. * The sixlowpan_reass_allocate function will get a free reassembly buffer
  211. * structure for use by 6LoWPAN.
  212. *
  213. * This function will first attempt to allocate from the g_free_reass
  214. * list. If that the list is empty, then the reassembly buffer structure
  215. * will be allocated from the dynamic memory pool.
  216. *
  217. * Input Parameters:
  218. * reasstag - The reassembly tag for subsequent lookup.
  219. * fragsrc - The source address of the fragment.
  220. *
  221. * Returned Value:
  222. * A reference to the allocated reass structure. All fields used by the
  223. * reasembly logic have been zeroed. On a failure to allocate, NULL is
  224. * returned.
  225. *
  226. * Assumptions:
  227. * The network is locked.
  228. *
  229. ****************************************************************************/
  230. FAR struct sixlowpan_reassbuf_s *
  231. sixlowpan_reass_allocate(uint16_t reasstag,
  232. FAR const struct netdev_varaddr_s *fragsrc)
  233. {
  234. FAR struct sixlowpan_reassbuf_s *reass;
  235. uint8_t pool;
  236. /* First, removed any expired or inactive reassembly buffers. This might
  237. * free up a pre-allocated buffer for this allocation.
  238. */
  239. sixlowpan_reass_expire();
  240. /* Now, try the free list first */
  241. if (g_free_reass != NULL)
  242. {
  243. reass = g_free_reass;
  244. g_free_reass = reass->rb_flink;
  245. pool = REASS_POOL_PREALLOCATED;
  246. }
  247. else
  248. {
  249. #ifdef CONFIG_NET_6LOWPAN_REASS_STATIC
  250. reass = NULL;
  251. #else
  252. /* If we cannot get a reassembly buffer instance from the free list,
  253. * then we will have to allocate one from the kernel memory pool.
  254. */
  255. reass = (FAR struct sixlowpan_reassbuf_s *)
  256. kmm_malloc((sizeof (struct sixlowpan_reassbuf_s)));
  257. pool = REASS_POOL_DYNAMIC;
  258. #endif
  259. }
  260. /* We have successfully allocated memory from some source? */
  261. if (reass != NULL)
  262. {
  263. /* Zero and tag the allocated reassembly buffer structure. */
  264. memset(reass, 0, sizeof(struct sixlowpan_reassbuf_s));
  265. memcpy(&reass->rb_fragsrc, fragsrc, sizeof(struct netdev_varaddr_s));
  266. reass->rb_pool = pool;
  267. reass->rb_active = true;
  268. reass->rb_reasstag = reasstag;
  269. reass->rb_time = clock_systime_ticks();
  270. /* Add the reassembly buffer to the list of active reassembly buffers */
  271. reass->rb_flink = g_active_reass;
  272. g_active_reass = reass;
  273. }
  274. return reass;
  275. }
  276. /****************************************************************************
  277. * Name: sixlowpan_reass_find
  278. *
  279. * Description:
  280. * Find a previously allocated, active reassembly buffer with the specified
  281. * reassembly tag.
  282. *
  283. * Input Parameters:
  284. * reasstag - The reassembly tag to match.
  285. * fragsrc - The source address of the fragment.
  286. *
  287. * Returned Value:
  288. * A reference to the matching reass structure.
  289. *
  290. * Assumptions:
  291. * The network is locked.
  292. *
  293. ****************************************************************************/
  294. FAR struct sixlowpan_reassbuf_s *
  295. sixlowpan_reass_find(uint16_t reasstag,
  296. FAR const struct netdev_varaddr_s *fragsrc)
  297. {
  298. FAR struct sixlowpan_reassbuf_s *reass;
  299. /* First, removed any expired or inactive reassembly buffers (we don't want
  300. * to return old reassembly buffer with the same tag)
  301. */
  302. sixlowpan_reass_expire();
  303. /* Now search for the matching reassembly buffer in the remainng, active
  304. * reassembly buffers.
  305. */
  306. for (reass = g_active_reass; reass != NULL; reass = reass->rb_flink)
  307. {
  308. /* In order to be a match, it must have the same reassembly tag as
  309. * well as source address (different sources might use the same
  310. * reassembly tag).
  311. */
  312. if (reass->rb_reasstag == reasstag &&
  313. sixlowpan_compare_fragsrc(reass, fragsrc))
  314. {
  315. return reass;
  316. }
  317. }
  318. /* Not found */
  319. return NULL;
  320. }
  321. /****************************************************************************
  322. * Name: sixlowpan_reass_free
  323. *
  324. * Description:
  325. * The sixlowpan_reass_free function will return a reass structure
  326. * to the free list of messages if it was a pre-allocated reass
  327. * structure. If the reass structure was allocated dynamically it will
  328. * be deallocated.
  329. *
  330. * Input Parameters:
  331. * reass - reass structure to free
  332. *
  333. * Returned Value:
  334. * None
  335. *
  336. * Assumptions:
  337. * The network is locked.
  338. *
  339. ****************************************************************************/
  340. void sixlowpan_reass_free(FAR struct sixlowpan_reassbuf_s *reass)
  341. {
  342. /* First, remove the reassembly buffer from the list of active reassembly
  343. * buffers.
  344. */
  345. sixlowpan_remove_active(reass);
  346. /* If this is a pre-allocated reassembly buffer structure, then just put it
  347. * back in the free list.
  348. */
  349. if (reass->rb_pool == REASS_POOL_PREALLOCATED)
  350. {
  351. reass->rb_flink = g_free_reass;
  352. g_free_reass = reass;
  353. }
  354. else if (reass->rb_pool == REASS_POOL_DYNAMIC)
  355. {
  356. #ifdef CONFIG_NET_6LOWPAN_REASS_STATIC
  357. DEBUGPANIC();
  358. #else
  359. DEBUGASSERT(reass->rb_pool == REASS_POOL_DYNAMIC);
  360. /* Otherwise, deallocate it. */
  361. kmm_free(reass);
  362. #endif
  363. }
  364. /* If the reassembly buffer structure was provided by the driver, nothing
  365. * needs to be freed.
  366. */
  367. }