1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

gnrc_pktbuf: allow for 0-sized payload snips

This commit is contained in:
Martine Lenders 2016-07-26 19:53:48 +02:00 committed by Martine Lenders
parent 3feb38611b
commit 5dad8f1edd
2 changed files with 53 additions and 36 deletions

View File

@ -71,16 +71,19 @@ void gnrc_pktbuf_init(void);
* function externally. This will most likely create memory leaks or * function externally. This will most likely create memory leaks or
* not allowed memory access. * not allowed memory access.
* *
* @pre size < GNRC_PKTBUF_SIZE
*
* @param[in] next Next gnrc_pktsnip_t in the packet. Leave NULL if you * @param[in] next Next gnrc_pktsnip_t in the packet. Leave NULL if you
* want to create a new packet. * want to create a new packet.
* @param[in] data Data of the new gnrc_pktsnip_t. If @p data is NULL no data * @param[in] data Data of the new gnrc_pktsnip_t. If @p data is NULL no data
* will be inserted into `result`. * will be inserted into `result`.
* @param[in] size Length of @p data. May not be 0. * @param[in] size Length of @p data. If this value is 0 the
* gnrc_pktsnip::data field of the newly created snip will
* be NULL.
* @param[in] type Protocol type of the gnrc_pktsnip_t. * @param[in] type Protocol type of the gnrc_pktsnip_t.
* *
* @return Pointer to the packet part that represents the new gnrc_pktsnip_t. * @return Pointer to the packet part that represents the new gnrc_pktsnip_t.
* @return NULL, if no space is left in the packet buffer. * @return NULL, if no space is left in the packet buffer.
* @return NULL, if @p size == 0.
*/ */
gnrc_pktsnip_t *gnrc_pktbuf_add(gnrc_pktsnip_t *next, void *data, size_t size, gnrc_pktsnip_t *gnrc_pktbuf_add(gnrc_pktsnip_t *next, void *data, size_t size,
gnrc_nettype_t type); gnrc_nettype_t type);
@ -89,8 +92,9 @@ gnrc_pktsnip_t *gnrc_pktbuf_add(gnrc_pktsnip_t *next, void *data, size_t size,
* @brief Marks the first @p size bytes in a received packet with a new * @brief Marks the first @p size bytes in a received packet with a new
* packet snip that is appended to the packet. * packet snip that is appended to the packet.
* *
* Graphically this can be represented as follows: * Graphically this can be represented as follows:
* @code *
* ~~~~~~~~~~~~~~~~~~~
* Before After * Before After
* ====== ===== * ====== =====
* (next) * (next)
@ -99,7 +103,10 @@ gnrc_pktsnip_t *gnrc_pktbuf_add(gnrc_pktsnip_t *next, void *data, size_t size,
* +--------------------------------+ +----------------+---------------+ * +--------------------------------+ +----------------+---------------+
* +--------------------------------+ +----------------+---------------+ * +--------------------------------+ +----------------+---------------+
* \__________pkt->size___________/ \_result->size_/ \__pkt->size__/ * \__________pkt->size___________/ \_result->size_/ \__pkt->size__/
* @endcode * ~~~~~~~~~~~~~~~~~~~
*
* If `size == pkt->size` then the resulting snip will point to NULL in its
* gnrc_pktsnip_t::data field and its gnrc_pktsnip_t::size field will be 0.
* *
* @pre @p pkt != NULL && @p size != 0 * @pre @p pkt != NULL && @p size != 0
* *
@ -117,7 +124,9 @@ gnrc_pktsnip_t *gnrc_pktbuf_mark(gnrc_pktsnip_t *pkt, size_t size, gnrc_nettype_
* @brief Reallocates gnrc_pktsnip_t::data of @p pkt in the packet buffer, without * @brief Reallocates gnrc_pktsnip_t::data of @p pkt in the packet buffer, without
* changing the content. * changing the content.
* *
* @pre gnrc_pktsnip_t::data of @p pkt is in the packet buffer. * @pre `pkt != NULL`
* @pre `(pkt->size > 0) <=> (pkt->data != NULL)`
* @pre gnrc_pktsnip_t::data of @p pkt is in the packet buffer if it is not NULL.
* *
* @details If enough memory is available behind it or @p size is smaller than * @details If enough memory is available behind it or @p size is smaller than
* the original size of the packet then gnrc_pktsnip_t::data of @p pkt will * the original size of the packet then gnrc_pktsnip_t::data of @p pkt will
@ -128,7 +137,7 @@ gnrc_pktsnip_t *gnrc_pktbuf_mark(gnrc_pktsnip_t *pkt, size_t size, gnrc_nettype_
* @param[in] size The size for @p pkt. * @param[in] size The size for @p pkt.
* *
* @return 0, on success * @return 0, on success
* @return ENOMEM, if no space is left in the packet buffer or size was 0. * @return ENOMEM, if no space is left in the packet buffer.
*/ */
int gnrc_pktbuf_realloc_data(gnrc_pktsnip_t *pkt, size_t size); int gnrc_pktbuf_realloc_data(gnrc_pktsnip_t *pkt, size_t size);

View File

@ -94,8 +94,8 @@ gnrc_pktsnip_t *gnrc_pktbuf_add(gnrc_pktsnip_t *next, void *data, size_t size,
{ {
gnrc_pktsnip_t *pkt; gnrc_pktsnip_t *pkt;
if ((size == 0) || (size > GNRC_PKTBUF_SIZE)) { if (size > GNRC_PKTBUF_SIZE) {
DEBUG("pktbuf: size (%u) == 0 || size == GNRC_PKTBUF_SIZE (%u)\n", DEBUG("pktbuf: size (%u) > GNRC_PKTBUF_SIZE (%u)\n",
(unsigned)size, GNRC_PKTBUF_SIZE); (unsigned)size, GNRC_PKTBUF_SIZE);
return NULL; return NULL;
} }
@ -122,19 +122,17 @@ gnrc_pktsnip_t *gnrc_pktbuf_mark(gnrc_pktsnip_t *pkt, size_t size, gnrc_nettype_
mutex_unlock(&_mutex); mutex_unlock(&_mutex);
return NULL; return NULL;
} }
else if (size == pkt->size) { /* create new snip descriptor for marked data */
pkt->type = type;
mutex_unlock(&_mutex);
return pkt;
}
marked_snip = _pktbuf_alloc(sizeof(gnrc_pktsnip_t)); marked_snip = _pktbuf_alloc(sizeof(gnrc_pktsnip_t));
if (marked_snip == NULL) { if (marked_snip == NULL) {
DEBUG("pktbuf: could not reallocate marked section.\n"); DEBUG("pktbuf: could not reallocate marked section.\n");
mutex_unlock(&_mutex); mutex_unlock(&_mutex);
return NULL; return NULL;
} }
/* would not fit unused marker => move data around */ /* marked data would not fit _unused_t marker => move data around to allow
if ((size < required_new_size) || ((pkt->size - size) < sizeof(_unused_t))) { * for proper free */
if ((pkt->size != size) &&
((size < required_new_size) || ((pkt->size - size) < sizeof(_unused_t)))) {
void *new_data_rest; void *new_data_rest;
new_data_marked = _pktbuf_alloc(size); new_data_marked = _pktbuf_alloc(size);
if (new_data_marked == NULL) { if (new_data_marked == NULL) {
@ -159,7 +157,9 @@ gnrc_pktsnip_t *gnrc_pktbuf_mark(gnrc_pktsnip_t *pkt, size_t size, gnrc_nettype_
} }
else { else {
new_data_marked = pkt->data; new_data_marked = pkt->data;
pkt->data = ((uint8_t *)pkt->data) + size; /* if (pkt->size - size) != 0 take remainder of data, otherwise set NULL */
pkt->data = (pkt->size != size) ? (((uint8_t *)pkt->data) + size) :
NULL;
} }
pkt->size -= size; pkt->size -= size;
_set_pktsnip(marked_snip, pkt->next, new_data_marked, size, type); _set_pktsnip(marked_snip, pkt->next, new_data_marked, size, type);
@ -174,17 +174,23 @@ int gnrc_pktbuf_realloc_data(gnrc_pktsnip_t *pkt, size_t size)
_align(sizeof(_unused_t)) : _align(size); _align(sizeof(_unused_t)) : _align(size);
mutex_lock(&_mutex); mutex_lock(&_mutex);
assert((pkt != NULL) && (pkt->data != NULL) && _pktbuf_contains(pkt->data)); assert(pkt != NULL);
if (size == 0) { assert(((pkt->size == 0) && (pkt->data == NULL)) ||
DEBUG("pktbuf: size == 0\n"); ((pkt->size > 0) && (pkt->data != NULL) && _pktbuf_contains(pkt->data)));
mutex_unlock(&_mutex); /* new size and old size are equal */
return ENOMEM;
}
if (size == pkt->size) { if (size == pkt->size) {
/* nothing to do */
mutex_unlock(&_mutex); mutex_unlock(&_mutex);
return 0; return 0;
} }
if ((size > pkt->size) || /* new size does not fit */ /* new size is 0 and data pointer isn't already NULL */
if ((size == 0) && (pkt->data != NULL)) {
/* set data pointer to NULL */
_pktbuf_free(pkt->data, pkt->size);
pkt->data = NULL;
}
/* if new size is bigger than old size */
else if ((size > pkt->size) || /* new size does not fit */
((pkt->size - aligned_size) < sizeof(_unused_t))) { /* resulting hole would not fit marker */ ((pkt->size - aligned_size) < sizeof(_unused_t))) { /* resulting hole would not fit marker */
void *new_data = _pktbuf_alloc(size); void *new_data = _pktbuf_alloc(size);
if (new_data == NULL) { if (new_data == NULL) {
@ -192,15 +198,15 @@ int gnrc_pktbuf_realloc_data(gnrc_pktsnip_t *pkt, size_t size)
mutex_unlock(&_mutex); mutex_unlock(&_mutex);
return ENOMEM; return ENOMEM;
} }
memcpy(new_data, pkt->data, (pkt->size < size) ? pkt->size : size); if (pkt->data != NULL) { /* if old data exist */
memcpy(new_data, pkt->data, (pkt->size < size) ? pkt->size : size);
}
_pktbuf_free(pkt->data, pkt->size); _pktbuf_free(pkt->data, pkt->size);
pkt->data = new_data; pkt->data = new_data;
} }
else { else if (_align(pkt->size) > aligned_size) {
if (_align(pkt->size) > aligned_size) { _pktbuf_free(((uint8_t *)pkt->data) + aligned_size,
_pktbuf_free(((uint8_t *)pkt->data) + aligned_size, pkt->size - aligned_size);
pkt->size - aligned_size);
}
} }
pkt->size = size; pkt->size = size;
mutex_unlock(&_mutex); mutex_unlock(&_mutex);
@ -397,17 +403,19 @@ static gnrc_pktsnip_t *_create_snip(gnrc_pktsnip_t *next, void *data, size_t siz
gnrc_nettype_t type) gnrc_nettype_t type)
{ {
gnrc_pktsnip_t *pkt = _pktbuf_alloc(sizeof(gnrc_pktsnip_t)); gnrc_pktsnip_t *pkt = _pktbuf_alloc(sizeof(gnrc_pktsnip_t));
void *_data; void *_data = NULL;
if (pkt == NULL) { if (pkt == NULL) {
DEBUG("pktbuf: error allocating new packet snip\n"); DEBUG("pktbuf: error allocating new packet snip\n");
return NULL; return NULL;
} }
_data = _pktbuf_alloc(size); if (size > 0) {
if (_data == NULL) { _data = _pktbuf_alloc(size);
DEBUG("pktbuf: error allocating data for new packet snip\n"); if (_data == NULL) {
_pktbuf_free(pkt, sizeof(gnrc_pktsnip_t)); DEBUG("pktbuf: error allocating data for new packet snip\n");
return NULL; _pktbuf_free(pkt, sizeof(gnrc_pktsnip_t));
return NULL;
}
} }
_set_pktsnip(pkt, next, _data, size, type); _set_pktsnip(pkt, next, _data, size, type);
if (data != NULL) { if (data != NULL) {