iot_pbuffer.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467
  1. /**
  2. * Copyright (c) 2014 - 2018, Nordic Semiconductor ASA
  3. *
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without modification,
  7. * are permitted provided that the following conditions are met:
  8. *
  9. * 1. Redistributions of source code must retain the above copyright notice, this
  10. * list of conditions and the following disclaimer.
  11. *
  12. * 2. Redistributions in binary form, except as embedded into a Nordic
  13. * Semiconductor ASA integrated circuit in a product or a software update for
  14. * such product, must reproduce the above copyright notice, this list of
  15. * conditions and the following disclaimer in the documentation and/or other
  16. * materials provided with the distribution.
  17. *
  18. * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
  19. * contributors may be used to endorse or promote products derived from this
  20. * software without specific prior written permission.
  21. *
  22. * 4. This software, with or without modification, must only be used with a
  23. * Nordic Semiconductor ASA integrated circuit.
  24. *
  25. * 5. Any software provided in binary form under this license must not be reverse
  26. * engineered, decompiled, modified and/or disassembled.
  27. *
  28. * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
  29. * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  30. * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
  31. * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
  32. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  33. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
  34. * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  35. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  36. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  37. * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  38. *
  39. */
  40. #include "nrf_soc.h"
  41. #include "nordic_common.h"
  42. #include "sdk_common.h"
  43. #include "sdk_config.h"
  44. #include "iot_common.h"
  45. #include "iot_pbuffer.h"
  46. #include "mem_manager.h"
  47. #if IOT_PBUFFER_CONFIG_LOG_ENABLED
  48. #define NRF_LOG_MODULE_NAME pbuffer
  49. #define NRF_LOG_LEVEL IOT_PBUFFER_CONFIG_LOG_LEVEL
  50. #define NRF_LOG_INFO_COLOR IOT_PBUFFER_CONFIG_INFO_COLOR
  51. #define NRF_LOG_DEBUG_COLOR IOT_PBUFFER_CONFIG_DEBUG_COLOR
  52. #include "nrf_log.h"
  53. NRF_LOG_MODULE_REGISTER();
  54. #define PBUFFER_TRC NRF_LOG_DEBUG /**< Used for getting trace of execution in the module. */
  55. #define PBUFFER_ERR NRF_LOG_ERROR /**< Used for logging errors in the module. */
  56. #define PBUFFER_DUMP NRF_LOG_HEXDUMP_DEBUG /**< Used for dumping octet information to get details of bond information etc. */
  57. #define PBUFFER_ENTRY() PBUFFER_TRC(">> %s", __func__)
  58. #define PBUFFER_EXIT() PBUFFER_TRC("<< %s", __func__)
  59. #else // IOT_PBUFFER_CONFIG_LOG_ENABLED
  60. #define PBUFFER_TRC(...) /**< Disables traces. */
  61. #define PBUFFER_DUMP(...) /**< Disables dumping of octet streams. */
  62. #define PBUFFER_ERR(...) /**< Disables error logs. */
  63. #define PBUFFER_ENTRY(...)
  64. #define PBUFFER_EXIT(...)
  65. #endif // IOT_PBUFFER_CONFIG_LOG_ENABLED
  66. /**
  67. * @defgroup api_param_check API Parameters check macros.
  68. *
  69. * @details Macros that verify parameters passed to the module in the APIs. These macros
  70. * could be mapped to nothing in final versions of code to save execution and size.
  71. * BLE_HPS_DISABLE_API_PARAM_CHECK should be defined to disable these checks.
  72. *
  73. * @{
  74. */
  75. #if (IOT_PBUFFER_DISABLE_API_PARAM_CHECK == 0)
  76. /**@brief Macro to check is module is initialized before requesting one of the module procedures. */
  77. #define VERIFY_MODULE_IS_INITIALIZED() \
  78. if (m_initialization_state == false) \
  79. { \
  80. return (SDK_ERR_MODULE_NOT_INITIALIZED | IOT_PBUFFER_ERR_BASE); \
  81. }
  82. /**@brief Macro to check is module is initialized before requesting one of the module
  83. procedures but does not use any return code. */
  84. #define VERIFY_MODULE_IS_INITIALIZED_VOID() \
  85. if (m_initialization_state == false) \
  86. { \
  87. return; \
  88. }
  89. /**
  90. * @brief Verify NULL parameters are not passed to API by application.
  91. */
  92. #define NULL_PARAM_CHECK(PARAM) \
  93. if ((PARAM) == NULL) \
  94. { \
  95. return (NRF_ERROR_NULL | IOT_PBUFFER_ERR_BASE); \
  96. }
  97. /**
  98. * @brief Verify Type field has valid value.
  99. */
  100. #define VERIFY_PBUFFER_TYPE(TYPE) \
  101. if (((TYPE) == 0) || ((TYPE) > COAP_PACKET_TYPE)) \
  102. { \
  103. return (NRF_ERROR_INVALID_PARAM | IOT_PBUFFER_ERR_BASE); \
  104. }
  105. /**
  106. * @brief Verify flags field has valid value.
  107. */
  108. #define VERIFY_PBUFFER_FLAGS(FLAG) \
  109. if ((uint32_t)(FLAG) > PBUFFER_FLAG_NO_MEM_ALLOCATION) \
  110. { \
  111. return (NRF_ERROR_INVALID_PARAM | IOT_PBUFFER_ERR_BASE); \
  112. }
  113. /**
  114. * @brief Verify flags field has valid value.
  115. */
  116. #define VERIFY_NON_ZERO_LENGTH(LEN) \
  117. if ((LEN) ==0) \
  118. { \
  119. return (NRF_ERROR_INVALID_LENGTH | IOT_PBUFFER_ERR_BASE); \
  120. }
  121. #else //IOT_PBUFFER_DISABLE_API_PARAM_CHECK
  122. #define VERIFY_MODULE_IS_INITIALIZED()
  123. #define VERIFY_MODULE_IS_INITIALIZED_VOID()
  124. #define NULL_PARAM_CHECK(PARAM)
  125. #define VERIFY_PBUFFER_TYPE(TYPE)
  126. #define VERIFY_PBUFFER_FLAGS(FLAG)
  127. #define VERIFY_NON_ZERO_LENGTH(LEN)
  128. #endif //IOT_PBUFFER_DISABLE_API_PARAM_CHECK
  129. /**
  130. * @defgroup ble_ipsp_mutex_lock_unlock Module's Mutex Lock/Unlock Macros.
  131. *
  132. * @details Macros used to lock and unlock modules. Currently, SDK does not use mutexes but
  133. * framework is provided in case need arises to use an alternative architecture.
  134. * @{
  135. */
  136. #define PBUFFER_MUTEX_LOCK() SDK_MUTEX_LOCK(m_pbuffer_mutex) /**< Lock module using mutex */
  137. #define PBUFFER_MUTEX_UNLOCK() SDK_MUTEX_UNLOCK(m_pbuffer_mutex) /**< Unlock module using mutex */
  138. /** @} */
  139. /** @brief Packet buffer type managed by the module. */
  140. typedef struct
  141. {
  142. iot_pbuffer_t buffer; /**< Packet buffer being managed. */
  143. uint32_t allocated_length; /**< Length allocated for the buffer. */
  144. }pbuffer_t;
  145. SDK_MUTEX_DEFINE(m_pbuffer_mutex) /**< Mutex variable. Currently unused, this declaration does not occupy any space in RAM. */
  146. static bool m_initialization_state = false; /**< Variable to maintain module initialization state. */
  147. static pbuffer_t m_pbuffer[IOT_PBUFFER_MAX_COUNT]; /**< Table of packet buffers managed by the module. */
  148. /**@brief Initializes packet buffer. */
  149. static void pbuffer_init(pbuffer_t * p_buffer)
  150. {
  151. p_buffer->buffer.p_memory = NULL;
  152. p_buffer->buffer.p_payload = NULL;
  153. p_buffer->buffer.length = 0;
  154. p_buffer->buffer.type = UNASSIGNED_TYPE;
  155. p_buffer->allocated_length = 0;
  156. }
  157. /**@brief Get size of offset to be used based on the requested type. */
  158. static uint32_t type_offset_get(iot_pbuffer_type_t type)
  159. {
  160. uint32_t offset = 0;
  161. switch (type)
  162. {
  163. case RAW_PACKET_TYPE:
  164. {
  165. offset = 0;
  166. break;
  167. }
  168. case IPV6_PACKET_TYPE:
  169. {
  170. offset = IPV6_IP_HEADER_SIZE;
  171. break;
  172. }
  173. case ICMP6_PACKET_TYPE:
  174. {
  175. offset = IPV6_IP_HEADER_SIZE + ICMP6_HEADER_SIZE;
  176. break;
  177. }
  178. case UDP6_PACKET_TYPE: // Fall through.
  179. {
  180. offset = IPV6_IP_HEADER_SIZE + UDP_HEADER_SIZE;
  181. break;
  182. }
  183. case COAP_PACKET_TYPE:
  184. {
  185. offset = IPV6_IP_HEADER_SIZE + UDP_HEADER_SIZE + COAP_HEADER_SIZE;
  186. break;
  187. }
  188. default:
  189. {
  190. // Should never happen.
  191. break;
  192. }
  193. }
  194. return offset;
  195. }
  196. /**@brief Allocates 'length' sized packet buffer. */
  197. static uint32_t pbuffer_allocate(pbuffer_t ** pp_buffer, uint32_t length, iot_pbuffer_flags_t flags)
  198. {
  199. uint32_t index;
  200. uint32_t err_code = (NRF_ERROR_NO_MEM | IOT_PBUFFER_ERR_BASE);
  201. for (index = 0; index < IOT_PBUFFER_MAX_COUNT; index ++)
  202. {
  203. if (m_pbuffer[index].allocated_length == 0)
  204. {
  205. // Found a free buffer, allocate.
  206. PBUFFER_TRC("Found free buffer. Requesting memory allocation.");
  207. m_pbuffer[index].allocated_length = length;
  208. if (flags == PBUFFER_FLAG_DEFAULT)
  209. {
  210. err_code = nrf_mem_reserve(&m_pbuffer[index].buffer.p_memory, &m_pbuffer[index].allocated_length);
  211. if (err_code == NRF_SUCCESS)
  212. {
  213. PBUFFER_TRC("Allocated pbuffer at index 0x%08lX", index);
  214. (*pp_buffer) = &m_pbuffer[index];
  215. }
  216. else
  217. {
  218. PBUFFER_ERR("Failed to allocate memory for packet buffer of size %ld", length);
  219. m_pbuffer[index].allocated_length = 0;
  220. }
  221. }
  222. else
  223. {
  224. PBUFFER_TRC("Allocated pbuffer at index 0x%08lX without any memory allocation.", index);
  225. (*pp_buffer) = &m_pbuffer[index];
  226. err_code = NRF_SUCCESS;
  227. }
  228. break;
  229. }
  230. }
  231. return err_code;
  232. }
  233. /**@brief Finds the internal buffer based on the external iot_pbuffer_t. */
  234. static uint32_t pbuffer_find(pbuffer_t ** p_internal_buffer, iot_pbuffer_t * p_buffer)
  235. {
  236. const uint32_t size = sizeof (pbuffer_t);
  237. const uint32_t diff = (((uint32_t)p_buffer) - ((uint32_t)m_pbuffer));
  238. if ((diff > (size * IOT_PBUFFER_MAX_COUNT)) ||
  239. ((diff % size) != 0))
  240. {
  241. return (NRF_ERROR_INVALID_ADDR | IOT_PBUFFER_ERR_BASE);
  242. }
  243. (*p_internal_buffer) = (pbuffer_t *) p_buffer;
  244. return NRF_SUCCESS;
  245. }
  246. uint32_t iot_pbuffer_init(void)
  247. {
  248. uint32_t index;
  249. PBUFFER_ENTRY();
  250. SDK_MUTEX_INIT(m_pbuffer_mutex);
  251. PBUFFER_MUTEX_LOCK();
  252. for (index = 0; index < IOT_PBUFFER_MAX_COUNT; index++)
  253. {
  254. pbuffer_init(&m_pbuffer[index]);
  255. }
  256. m_initialization_state = true;
  257. PBUFFER_EXIT();
  258. PBUFFER_MUTEX_UNLOCK();
  259. return NRF_SUCCESS;
  260. }
  261. uint32_t iot_pbuffer_allocate(iot_pbuffer_alloc_param_t * p_param,
  262. iot_pbuffer_t ** pp_pbuffer)
  263. {
  264. VERIFY_MODULE_IS_INITIALIZED();
  265. NULL_PARAM_CHECK(p_param);
  266. NULL_PARAM_CHECK(pp_pbuffer);
  267. VERIFY_PBUFFER_TYPE(p_param->type);
  268. VERIFY_PBUFFER_FLAGS(p_param->flags);
  269. VERIFY_NON_ZERO_LENGTH(p_param->length);
  270. PBUFFER_ENTRY();
  271. PBUFFER_MUTEX_LOCK();
  272. uint32_t err_code;
  273. uint32_t offset;
  274. pbuffer_t * p_alloc_buffer;
  275. // Get offset to be added to length.
  276. offset = type_offset_get(p_param->type);
  277. err_code = pbuffer_allocate(&p_alloc_buffer, ((p_param->length) + offset), p_param->flags);
  278. if (err_code == NRF_SUCCESS)
  279. {
  280. p_alloc_buffer->buffer.length = p_param->length;
  281. p_alloc_buffer->buffer.type = p_param->type;
  282. if (p_param->flags != PBUFFER_FLAG_NO_MEM_ALLOCATION)
  283. {
  284. p_alloc_buffer->buffer.p_payload = ((p_alloc_buffer->buffer.p_memory) + offset);
  285. }
  286. (*pp_pbuffer) = &p_alloc_buffer->buffer;
  287. }
  288. PBUFFER_MUTEX_UNLOCK();
  289. PBUFFER_EXIT();
  290. return err_code;
  291. }
  292. uint32_t iot_pbuffer_reallocate(iot_pbuffer_alloc_param_t * p_param,
  293. iot_pbuffer_t * p_pbuffer)
  294. {
  295. VERIFY_MODULE_IS_INITIALIZED();
  296. NULL_PARAM_CHECK(p_param);
  297. NULL_PARAM_CHECK(p_pbuffer);
  298. VERIFY_PBUFFER_TYPE(p_param->type);
  299. VERIFY_PBUFFER_FLAGS(p_param->flags);
  300. VERIFY_NON_ZERO_LENGTH(p_param->length);
  301. PBUFFER_ENTRY();
  302. PBUFFER_MUTEX_LOCK();
  303. uint32_t err_code;
  304. uint32_t realloc_len;
  305. pbuffer_t * p_alloc_buffer;
  306. // Ensure pointer provided is in the ranged managed by the module.
  307. err_code = pbuffer_find(&p_alloc_buffer, p_pbuffer);
  308. if (err_code == NRF_SUCCESS)
  309. {
  310. // Get realloc_len to be added to length.
  311. const uint32_t offset = type_offset_get(p_param->type);
  312. realloc_len = p_param->length + offset;
  313. // Check if requested length cannot be accommodated in the allocated buffer.
  314. if (realloc_len > p_alloc_buffer->allocated_length)
  315. {
  316. // No, it cannot be, request a new buffer.
  317. uint8_t * p_new_mem;
  318. if (p_param->flags != PBUFFER_FLAG_NO_MEM_ALLOCATION)
  319. {
  320. err_code = nrf_mem_reserve(&p_new_mem, &realloc_len);
  321. if (err_code == NRF_SUCCESS)
  322. {
  323. // Copy data into the new buffer.
  324. memcpy (p_new_mem,
  325. p_pbuffer->p_memory,
  326. p_alloc_buffer->allocated_length);
  327. // Now free the old buffer. Perform the free
  328. nrf_free(p_alloc_buffer->buffer.p_memory);
  329. p_alloc_buffer->allocated_length = realloc_len;
  330. p_alloc_buffer->buffer.p_memory = p_new_mem;
  331. p_alloc_buffer->buffer.length = p_param->length;
  332. }
  333. }
  334. }
  335. if (err_code == NRF_SUCCESS)
  336. {
  337. p_alloc_buffer->buffer.length = p_param->length;
  338. p_alloc_buffer->buffer.type = p_param->type;
  339. if (p_param->flags == PBUFFER_FLAG_DEFAULT)
  340. {
  341. p_alloc_buffer->buffer.p_payload = (p_alloc_buffer->buffer.p_memory + offset);
  342. }
  343. }
  344. }
  345. else
  346. {
  347. PBUFFER_ERR("Cannot find buffer to be freed.");
  348. }
  349. PBUFFER_MUTEX_UNLOCK();
  350. PBUFFER_EXIT();
  351. return err_code;
  352. }
  353. uint32_t iot_pbuffer_free(iot_pbuffer_t * p_pbuffer, bool free_flag)
  354. {
  355. VERIFY_MODULE_IS_INITIALIZED();
  356. NULL_PARAM_CHECK(p_pbuffer);
  357. PBUFFER_ENTRY();
  358. PBUFFER_MUTEX_LOCK();
  359. uint32_t err_code;
  360. pbuffer_t * p_alloc_buffer;
  361. // Ensure pointer provided is in the ranged managed by the module.
  362. err_code = pbuffer_find(&p_alloc_buffer, p_pbuffer);
  363. if (err_code == NRF_SUCCESS)
  364. {
  365. if (free_flag == true)
  366. {
  367. nrf_free(p_alloc_buffer->buffer.p_memory);
  368. }
  369. pbuffer_init(p_alloc_buffer);
  370. }
  371. else
  372. {
  373. PBUFFER_ERR("Cannot find buffer to be freed.");
  374. }
  375. PBUFFER_MUTEX_UNLOCK();
  376. PBUFFER_EXIT();
  377. return err_code;
  378. }