/************************************************************************ * NAME: fnet_netbuf_free * * DESCRIPTION: Frees the memory, which was allocated by net_buf 'nb' and * returns pointer to the next net_buf. *************************************************************************/ fnet_netbuf_t *fnet_netbuf_free( fnet_netbuf_t *nb ) { fnet_netbuf_t *tmp_nb; if(nb != 0) { if(((fnet_uint32_t *)nb->data)[0] == 1u) /* If nobody uses this data buffer. */ { fnet_free_netbuf(nb->data); } else /* else decrement reference counter */ { ((fnet_uint32_t *)nb->data)[0] = ((fnet_uint32_t *)nb->data)[0] - 1u; } tmp_nb = nb->next; fnet_free_netbuf(nb); return (tmp_nb); } else { return (0); } }
/************************************************************************ * NAME: fnet_netbuf_free_chain * * DESCRIPTION: Frees the memory, which was allocated by all net_bufs * in the chain beginning from the buffer 'nb' *************************************************************************/ void fnet_netbuf_free_chain( fnet_netbuf_t *nb ) { fnet_netbuf_t *tmp_nb; while(nb != 0) { tmp_nb = nb->next; if(((int *)nb->data)[0] == 1) /* If nobody uses this data buffer. */ fnet_free_netbuf(nb->data); else /* Else decrement reference counter */ ((int *)nb->data)[0] = ((int *)nb->data)[0] - 1; fnet_free_netbuf(nb); nb = tmp_nb; } }
/************************************************************************ * NAME: fnet_netbuf_new * * DESCRIPTION: Creates a new net_buf and allocates memory * for a new data buffer. *************************************************************************/ fnet_netbuf_t *fnet_netbuf_new( int len, int drain ) { fnet_netbuf_t *nb; void *nb_d; if(len < 0) return (fnet_netbuf_t *)0; nb = (fnet_netbuf_t *)fnet_malloc_netbuf(sizeof(fnet_netbuf_t)); if((nb == 0) && drain) { fnet_prot_drain(); nb = (fnet_netbuf_t *)fnet_malloc_netbuf(sizeof(fnet_netbuf_t)); } if(nb == 0) /* If FNET_NETBUF_MALLOC_NOWAIT and no free memory for a new net_buf*/ { return (fnet_netbuf_t *)0; } nb_d = fnet_malloc_netbuf((unsigned int)len + sizeof(int)/* For reference_counter */); if((nb_d == 0) && drain ) { fnet_prot_drain(); nb_d = fnet_malloc_netbuf((unsigned int)len + sizeof(int)/* For reference_counter */); } if(nb_d == 0) /* If FNET_NETBUF_MALLOC_NOWAIT and no free memory for data.*/ { fnet_free_netbuf(nb); return (fnet_netbuf_t *)0; } nb->next = (fnet_netbuf_t *)0; nb->next_chain = (fnet_netbuf_t *)0; /* In memory net_buf's data is after the descriptor "data".*/ ((int *)nb_d)[0] = 1; /* First element is used by the reference_counter.*/ nb->data = &((int *)nb_d)[0]; nb->data_ptr = &((int *)nb_d)[1]; nb->length = (unsigned long)len; nb->total_length = (unsigned long)len; nb->flags = 0; return (nb); }
/************************************************************************ * NAME: fnet_netbuf_pullup * * DESCRIPTION: Create a data buffer for the first net_buf with the * length len *************************************************************************/ fnet_return_t fnet_netbuf_pullup( fnet_netbuf_t **nb_ptr, fnet_size_t len) { fnet_netbuf_t *nb = *nb_ptr; fnet_size_t tot_len = 0u; fnet_size_t offset; fnet_netbuf_t *tmp_nb; fnet_netbuf_t *nb_run; void *new_buf; /* Check length*/ if(nb->total_length < len) { return FNET_OK; } if((nb->length >= len) || (len == 0u) || (nb == 0)) { /* if function shouldn't do anything*/ return FNET_OK; } tmp_nb = nb; tot_len += tmp_nb->length; /* search of the last buffer, from which the data have to be copied*/ while((tot_len < len) && tmp_nb) { tmp_nb = tmp_nb->next; tot_len += tmp_nb->length; } new_buf = (struct net_buf_data *)fnet_malloc_netbuf((fnet_size_t)len + sizeof(fnet_uint32_t)/* For reference_counter */); if(new_buf == 0) { return FNET_ERR; } ((fnet_uint32_t *)new_buf)[0] = 1u; /* First element is used by the reference_counter.*/ /* Copy into it the contents of first data buffer. Skip the reference counter (placed in the first bytes). */ fnet_memcpy(&((fnet_uint32_t *)new_buf)[1], nb->data_ptr, nb->length); offset = nb->length; /* Free old data buffer (for the first net_buf) */ if(((fnet_uint32_t *)nb->data)[0] == 1u) /* If nobody uses this data buffer. */ { fnet_free_netbuf(nb->data); } else /* Else decrement reference counter */ { ((fnet_uint32_t *)nb->data)[0] = ((fnet_uint32_t *)nb->data)[0] - 1u; } /* Currently data buffer contains the contents of the first buffer */ nb->data = &((fnet_uint32_t *)new_buf)[0]; nb->data_ptr = &((fnet_uint32_t *)new_buf)[1]; nb_run = nb->next; /* Let's start from the next buffer */ while(nb_run != tmp_nb) /* Copy full data buffers */ { fnet_memcpy((fnet_uint8_t *)nb->data_ptr + offset, nb_run->data_ptr, nb_run->length); if(nb_run != tmp_nb) { offset += nb_run->length; nb_run = fnet_netbuf_free(nb_run); } } tot_len = len - offset; /* Copy the remaining part and change data pointer and length of the * last net_buf, which is the source for the first net_buf */ fnet_memcpy((fnet_uint8_t *)nb->data_ptr + offset, nb_run->data_ptr, tot_len); nb_run->length -= tot_len; if(nb_run->length == 0u) { nb_run = fnet_netbuf_free(nb_run); } else { nb_run->data_ptr = (fnet_uint8_t *)nb_run->data_ptr + tot_len; } /* Setting up the params of the first net_buf.*/ nb->next = nb_run; nb->length = (fnet_size_t)len; *nb_ptr = nb; return FNET_OK; }
/************************************************************************ * NAME: fnet_netbuf_copy * * DESCRIPTION: Creates a new net_buf using data buffer, * which was created before for another net_buf. *************************************************************************/ fnet_netbuf_t *fnet_netbuf_copy( fnet_netbuf_t *nb, fnet_size_t offset, fnet_size_t len, fnet_bool_t drain ) { fnet_netbuf_t *loc_nb, *loc_nb_head, *tmp_nb; fnet_int32_t tot_len = 0; fnet_size_t tot_offset = 0u; tmp_nb = nb; do /* Calculate the total length of the buf for current net_buf chain.*/ { tot_len += (fnet_int32_t)tmp_nb->length; tmp_nb = tmp_nb->next; } while (tmp_nb); if(len == FNET_NETBUF_COPYALL) { tot_len -= (fnet_int32_t)offset; len = (fnet_size_t)tot_len; } else { if(((len + offset) > (fnet_size_t)tot_len ) || ((fnet_size_t)tot_len < offset)) { return (fnet_netbuf_t *)0; } } /* In tot_len finally - the size of required net_buf data*/ tmp_nb = nb; loc_nb = (fnet_netbuf_t *)fnet_malloc_netbuf(sizeof(fnet_netbuf_t)); if((loc_nb == 0) && drain) { fnet_prot_drain(); loc_nb = (fnet_netbuf_t *)fnet_malloc_netbuf(sizeof(fnet_netbuf_t)); } if(loc_nb == 0) { return (fnet_netbuf_t *)0; } loc_nb_head = loc_nb; /* Save the head of net_buf chain.*/ loc_nb->next_chain = (fnet_netbuf_t *)0; loc_nb->total_length = (fnet_size_t)len; loc_nb->flags = nb->flags; if(tmp_nb->length > offset) /* If offset less than size of 1st net_buf.*/ { tot_offset = offset; } else /* Find corresponding net_buf and calculate the offset in it.*/ { while((tot_offset += tmp_nb->length) <= offset) { tmp_nb = tmp_nb->next; } tot_offset = (tmp_nb->length + offset - tot_offset); } loc_nb->data = tmp_nb->data; loc_nb->data_ptr = (fnet_uint8_t *)tmp_nb->data_ptr + tot_offset; ((fnet_uint32_t *)loc_nb->data)[0] = ((fnet_uint32_t *)loc_nb->data)[0] + 1u; /* Increment the the reference_counter.*/ tot_len = (fnet_int32_t)(len - (tmp_nb->length - tot_offset)); if(tot_len <= 0) /* If only one net_buf required.*/ { loc_nb->length = (fnet_size_t)len; } else { loc_nb->length = tmp_nb->length - tot_offset; do { loc_nb->next = (fnet_netbuf_t *)fnet_malloc_netbuf(sizeof(fnet_netbuf_t)); if((loc_nb->next == 0) && drain ) { fnet_prot_drain(); loc_nb->next = (fnet_netbuf_t *)fnet_malloc_netbuf(sizeof(fnet_netbuf_t)); } if(loc_nb->next == 0) /* there is a need to erase all buffers,*/ { /* which were created earlier.*/ loc_nb_head = fnet_netbuf_free(loc_nb_head); while(loc_nb_head != loc_nb->next) { tmp_nb = loc_nb_head->next; fnet_free_netbuf(loc_nb_head); loc_nb_head = tmp_nb; } return (fnet_netbuf_t *)0; } loc_nb = loc_nb->next; loc_nb->next_chain = (fnet_netbuf_t *)0; tmp_nb = tmp_nb->next; loc_nb->data = tmp_nb->data; loc_nb->flags = tmp_nb->flags; ((fnet_uint32_t *)loc_nb->data)[0] = ((fnet_uint32_t *)loc_nb->data)[0] + 1u; /* Increment the the reference_counter.*/ loc_nb->data_ptr = tmp_nb->data_ptr; tot_len -= (fnet_int32_t)tmp_nb->length; if(tot_len < 0) /* for correct calculation of length */ { loc_nb->length = (fnet_size_t)(tot_len + (fnet_int32_t)tmp_nb->length); } else { loc_nb->length = tmp_nb->length; } } while (tot_len > 0); } loc_nb->next = (fnet_netbuf_t *)0; return (loc_nb_head); }