Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of OmniWheels by
buffer_dyn.c
00001 /* 00002 * Copyright (c) 2011-2017, Arm Limited and affiliates. 00003 * SPDX-License-Identifier: Apache-2.0 00004 * 00005 * Licensed under the Apache License, Version 2.0 (the "License"); 00006 * you may not use this file except in compliance with the License. 00007 * You may obtain a copy of the License at 00008 * 00009 * http://www.apache.org/licenses/LICENSE-2.0 00010 * 00011 * Unless required by applicable law or agreed to in writing, software 00012 * distributed under the License is distributed on an "AS IS" BASIS, 00013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 * See the License for the specific language governing permissions and 00015 * limitations under the License. 00016 */ 00017 00018 #include "nsconfig.h" 00019 #include "string.h" 00020 #include "ns_types.h" 00021 #include "nsdynmemLIB.h" 00022 #include "Core/include/address.h" 00023 #include "Core/include/ns_buffer.h" 00024 #include "Core/include/socket.h" 00025 #include "ns_trace.h" 00026 #include "platform/arm_hal_interrupt.h" 00027 #include "NWK_INTERFACE/Include/protocol_stats.h" 00028 #include "ip_fsc.h" 00029 #include "net_interface.h" 00030 00031 #define TRACE_GROUP "buff" 00032 00033 volatile unsigned int buffer_count = 0; 00034 00035 uint8_t *(buffer_corrupt_check)(buffer_t *buf) 00036 { 00037 if (buf == NULL) { 00038 return NULL; 00039 } 00040 00041 if (buf->buf_ptr > buf->buf_end ) { 00042 tr_error("Buffer pointer end not set"); 00043 } else if (buffer_data_length(buf) < 0) { 00044 tr_error("Buffer length overflow"); 00045 while (1); 00046 } else if (buf->buf_end > buf->size || buf->buf_ptr > buf->size ) { 00047 tr_error("buffer pointer overridden"); 00048 while (1); 00049 } 00050 return buffer_data_pointer(buf); 00051 } 00052 00053 buffer_t *buffer_get(uint16_t size) 00054 { 00055 return buffer_get_specific(BUFFER_DEFAULT_HEADROOM, size, BUFFER_DEFAULT_MIN_SIZE); 00056 } 00057 00058 buffer_t *buffer_get_minimal(uint16_t size) 00059 { 00060 return buffer_get_specific(0, size, 0); 00061 } 00062 00063 /** 00064 * Get pointer to a buffer_t structure and reserve memory for it from the dynamic heap. 00065 * 00066 * \param headroom required headroom in addition to basic size 00067 * \param size basic size of data allocate memory for 00068 * \param minspace minimum size of buffer 00069 * \return a pointer of type buffer_t to the allocated memory area 00070 * 00071 */ 00072 buffer_t *buffer_get_specific(uint16_t headroom, uint16_t size, uint16_t minspace) 00073 { 00074 buffer_t *buf; 00075 uint16_t total_size; 00076 00077 total_size = headroom + size; 00078 if (total_size < minspace) { 00079 total_size = minspace; 00080 } 00081 00082 /* Round total size up to at least be a neat multiple - allocation must 00083 * anyway be this much aligned. */ 00084 total_size = (total_size + 3) &~ 3; 00085 00086 // Note - as well as this alloc+init, buffers can also be "realloced" 00087 // in buffer_headroom() 00088 00089 buf = ns_dyn_mem_temporary_alloc(sizeof(buffer_t) + total_size); 00090 if (buf) { 00091 platform_enter_critical(); 00092 buffer_count++; 00093 platform_exit_critical(); 00094 memset(buf, 0, sizeof(buffer_t)); 00095 buf->buf_ptr = total_size - size; 00096 buf->buf_end = buf->buf_ptr ; 00097 buf->socket = NULL; 00098 buf->interface = NULL; 00099 //buf->bad_channel = 0xffff; 00100 //buf->bc_sending_superframe = 0xff; 00101 buf->rpl_instance = 0xff; 00102 // Socket TX always overrides this, so this is the default for non-socket buffers. 00103 // Setting it to 0 would remove flow labels on internal ICMP messages without affecting sockets. 00104 buf->options .flow_label = IPV6_FLOW_UNSPECIFIED; 00105 buf->options .hop_limit = 255; 00106 buf->options .mpl_permitted = true; 00107 buf->link_specific.ieee802_15_4.useDefaultPanId = true; 00108 #ifndef NO_IPV6_PMTUD 00109 buf->options .ipv6_use_min_mtu = -1; 00110 #endif 00111 buf->size = total_size; 00112 } else { 00113 tr_error("buffer_get failed: alloc(%zd)", sizeof(buffer_t) + total_size); 00114 } 00115 00116 protocol_stats_update(STATS_BUFFER_ALLOC, 1); 00117 return (buf); 00118 } 00119 00120 /** 00121 * Make sure buffer has enough room for header. 00122 * 00123 * \param buf buffer to check 00124 * \param size required header space 00125 * \return a pointer of type buffer_t to the newly allocated buffer (or the original one) 00126 * 00127 */ 00128 buffer_t *buffer_headroom(buffer_t *buf, uint16_t size) 00129 { 00130 uint16_t curr_len = buffer_data_length(buf); 00131 00132 if (buf->size < (curr_len + size)) { 00133 /* This buffer isn't big enough at all - allocate a new block */ 00134 // TODO - should we be giving them extra? probably 00135 uint16_t new_total = (curr_len + size + 3) &~ 3; 00136 buffer_t *restrict new_buf = ns_dyn_mem_temporary_alloc(sizeof(buffer_t) + new_total); 00137 if (new_buf) { 00138 // Copy the buffer_t header 00139 *new_buf = *buf; 00140 // Set new pointers, leaving specified headroom 00141 new_buf->buf_ptr = size; 00142 new_buf->buf_end = size + curr_len; 00143 new_buf->size = new_total; 00144 // Copy the current data 00145 memcpy(buffer_data_pointer(new_buf), buffer_data_pointer(buf), curr_len); 00146 protocol_stats_update(STATS_BUFFER_HEADROOM_REALLOC, 1); 00147 ns_dyn_mem_free(buf); 00148 buf = new_buf; 00149 } else { 00150 tr_error("HeadRoom Fail"); 00151 protocol_stats_update(STATS_BUFFER_HEADROOM_FAIL, 1); 00152 socket_tx_buffer_event_and_free(buf, SOCKET_NO_RAM); 00153 buf = NULL; 00154 } 00155 } else if (buf->buf_ptr < size) { 00156 /* This buffer is big enough, but not enough headroom - shuffle */ 00157 // TODO - surely better to shuffle all the way to the end in one go? 00158 uint8_t *orig_ptr = buffer_data_pointer(buf); 00159 buf->buf_ptr = size; 00160 buf->buf_end = size + curr_len; 00161 if (curr_len != 0) { 00162 memmove(buffer_data_pointer(buf), orig_ptr, curr_len); 00163 protocol_stats_update(STATS_BUFFER_HEADROOM_SHUFFLE, 1); 00164 } 00165 } 00166 buffer_corrupt_check(buf); 00167 return buf; 00168 } 00169 00170 buffer_t *buffer_free_route(buffer_t *buf) 00171 { 00172 if (buf->route) { 00173 if (--buf->route->ref_count == 0) { 00174 ns_dyn_mem_free(buf->route); 00175 } 00176 buf->route = NULL; 00177 } 00178 return buf; 00179 } 00180 00181 /** 00182 * Free a memory block from the heap. 00183 * 00184 * \param buf pointer to buffer to be freed 00185 * \return (buffer_t *) NULL 00186 * 00187 */ 00188 buffer_t *buffer_free(buffer_t *buf) 00189 { 00190 if (buf) { 00191 platform_enter_critical(); 00192 if (buffer_count) { 00193 buffer_count--; 00194 } else { 00195 tr_error("bc neg"); 00196 } 00197 platform_exit_critical(); 00198 00199 buf = buffer_free_route(buf); 00200 socket_dereference(buf->socket ); 00201 ns_dyn_mem_free(buf->predecessor ); 00202 ns_dyn_mem_free(buf->rpl_option); 00203 ns_dyn_mem_free(buf); 00204 00205 } else { 00206 tr_error("nullp F"); 00207 } 00208 return NULL; 00209 } 00210 00211 void buffer_free_list(buffer_list_t *list) 00212 { 00213 ns_list_foreach_safe(buffer_t, buf, list) { 00214 ns_list_remove(list, buf); 00215 buffer_free(buf); 00216 } 00217 } 00218 00219 /* Prepare a buffer that came from a received packet for use as a new 00220 * transmission (eg ICMP error response). Kill fields which should not be 00221 * carried over. This is distinct from a packet we are forwarding. 00222 */ 00223 buffer_t *buffer_turnaround(buffer_t *buf) 00224 { 00225 if (buf->predecessor ) { 00226 ns_dyn_mem_free(buf->predecessor ); 00227 buf->predecessor = NULL; 00228 } 00229 00230 if (buf->rpl_option) { 00231 ns_dyn_mem_free(buf->rpl_option); 00232 buf->rpl_option = NULL; 00233 } 00234 buf->options .tunnelled = false; 00235 buf->rpl_flag_error = 0; 00236 buf->rpl_instance_known = false; 00237 buf->link_specific.ieee802_15_4.useDefaultPanId = true; 00238 00239 buffer_socket_set(buf, NULL); 00240 00241 /* Most cases this will be a response to an RX, so no existing routing 00242 * info, but in the case of TX resolution failure, we're reversing and 00243 * need to re-evaluate routing. 00244 */ 00245 return buffer_free_route(buf); 00246 } 00247 00248 void buffer_note_predecessor(buffer_t *buf, const sockaddr_t *addr) 00249 { 00250 if (buf->options .need_predecessor && !buf->predecessor ) { 00251 buf->predecessor = ns_dyn_mem_temporary_alloc(sizeof *buf->predecessor ); 00252 if (buf->predecessor ) { 00253 memcpy(buf->predecessor , addr, sizeof *buf->predecessor ); 00254 } 00255 } 00256 } 00257 00258 socket_t *buffer_socket_set(buffer_t *buf, socket_t *socket) 00259 { 00260 buf->socket = socket_dereference(buf->socket ); 00261 buf->socket = socket_reference(socket); 00262 return buf->socket ; 00263 } 00264 00265 /* Copy metadata information from src into dst. 00266 * 00267 * Data size and pointers left unmodified in destination. 00268 * Other in-buffer metadata copied from src. 00269 * Any route information pointer cloned from src (reference count increased). 00270 * Other metadata pointers transfered either to dst or left in src, as requested 00271 */ 00272 void buffer_copy_metadata(buffer_t *dst, buffer_t *src, bool non_clonable_to_dst) 00273 { 00274 uint16_t buf_size = dst->size ; 00275 uint16_t buf_end = dst->buf_end ; 00276 uint16_t buf_ptr = dst->buf_ptr ; 00277 *dst = *src; 00278 if (dst->route) { 00279 dst->route->ref_count++; 00280 } 00281 dst->size = buf_size; 00282 dst->buf_ptr = buf_ptr; 00283 dst->buf_end = buf_end; 00284 00285 /* Extra data pointers now attached to both buffers - there can be only one */ 00286 buffer_t *to_wipe = non_clonable_to_dst ? src : dst; 00287 to_wipe->rpl_option = NULL; 00288 to_wipe->predecessor = NULL; 00289 to_wipe->socket = NULL; 00290 } 00291 00292 /** 00293 * Add buffer at the end of data. 00294 * 00295 * \param buf pointer to buffer where data is added 00296 * \param data_ptr data pointer where data is copied 00297 * \data_len length of data copied. 00298 * 00299 */ 00300 void buffer_data_add(buffer_t *buf, const uint8_t *data_ptr, uint16_t data_len) 00301 { 00302 memcpy(buffer_data_end(buf), data_ptr, data_len); 00303 buffer_data_end_set(buf, buffer_data_end(buf) + data_len); 00304 #ifdef EXTRA_CONSISTENCY_CHECKS 00305 buffer_corrupt_check(buf); 00306 #endif 00307 return; 00308 } 00309 00310 /** 00311 * Create new buffer that has the same data and fields. 00312 * 00313 * \param buf pointer to buffer to be freed 00314 * \return (buffer_t *) new clone. 00315 * 00316 */ 00317 buffer_t *buffer_clone(buffer_t *buf) 00318 { 00319 buffer_t *result_ptr = NULL; 00320 00321 if (buf == NULL) { 00322 return NULL; 00323 } 00324 00325 result_ptr = buffer_get(buffer_data_length(buf)); 00326 00327 if (result_ptr == NULL) { 00328 return NULL; 00329 } 00330 00331 uint16_t buf_ptr = result_ptr->buf_ptr ; 00332 uint16_t buf_end = result_ptr->buf_end ; 00333 uint16_t size = result_ptr->size ; 00334 00335 *result_ptr = *buf; 00336 result_ptr->predecessor = NULL; 00337 result_ptr->route = NULL; // Don't clone routing info 00338 result_ptr->socket = NULL; // Don't clone Socket info 00339 result_ptr->options .multicast_loop = false; // Don't loop back more copies! 00340 result_ptr->rpl_option = NULL; 00341 result_ptr->buf_ptr = buf_ptr; 00342 result_ptr->buf_end = buf_end; 00343 result_ptr->size = size; 00344 buffer_data_add(result_ptr, buffer_data_pointer(buf), buffer_data_length(buf)); 00345 00346 return result_ptr; 00347 } 00348 00349 uint16_t buffer_ipv6_fcf(const buffer_t *buf, uint8_t next_header) 00350 { 00351 return ipv6_fcf(buf->src_sa .address , buf->dst_sa .address , 00352 buffer_data_length(buf), buffer_data_pointer(buf), 00353 next_header); 00354 }
Generated on Fri Jul 22 2022 04:53:45 by
 1.7.2 
    