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.
Dependents: cobaLCDJoyMotor_Thread odometry_omni_3roda_v3 odometry_omni_3roda_v1 odometry_omni_3roda_v2 ... more
adaptation_interface.c
00001 /* 00002 * Copyright (c) 2016-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 "ns_types.h" 00020 #include "eventOS_event.h" 00021 #include "string.h" 00022 #include "ns_trace.h" 00023 #include "ns_list.h" 00024 #include "randLIB.h" 00025 #include "nsdynmemLIB.h" 00026 #include "Core/include/address.h" 00027 #include "Core/include/socket.h" 00028 #include "mac_api.h" 00029 #include "mac_mcps.h" 00030 #include "mac_common_defines.h" 00031 #include "common_functions.h" 00032 #include "NWK_INTERFACE/Include/protocol.h" 00033 #include "NWK_INTERFACE/Include/protocol_stats.h" 00034 #include "6LoWPAN/IPHC_Decode/cipv6.h" 00035 #include "NWK_INTERFACE/Include/protocol_timer.h" 00036 #include "Service_Libs/etx/etx.h" 00037 #include "6LoWPAN/MAC/mac_helper.h" 00038 #include "6LoWPAN/Mesh/mesh.h" 00039 #include "6LoWPAN/IPHC_Decode/iphc_decompress.h" 00040 #include "lowpan_adaptation_interface.h" 00041 #include "MLE/mle.h" 00042 #ifdef HAVE_RPL 00043 #include "RPL/rpl_data.h" 00044 #endif 00045 00046 #define TRACE_GROUP "6lAd" 00047 00048 typedef struct { 00049 uint16_t tag; /*!< Fragmentation datagram TAG ID */ 00050 uint16_t size; /*!< Datagram Total Size (uncompressed) */ 00051 uint16_t orig_size; /*!< Datagram Original Size (compressed) */ 00052 uint16_t frag_max; /*!< Maximum fragment size (MAC payload) */ 00053 uint16_t offset; /*!< Data offset from datagram start */ 00054 int16_t pattern; /*!< Size of compressed LoWPAN headers */ 00055 uint16_t unfrag_ptr; /*!< Offset within buf of headers that precede the FRAG header */ 00056 uint16_t frag_len; 00057 uint8_t unfrag_len; /*!< Length of headers that precede the FRAG header */ 00058 bool fragmented_data:1; 00059 bool first_fragment:1; 00060 bool indirectData:1; 00061 buffer_t *buf; 00062 uint8_t *fragmenter_buf; 00063 ns_list_link_t link; /*!< List link entry */ 00064 } fragmenter_tx_entry_t; 00065 00066 00067 typedef NS_LIST_HEAD (fragmenter_tx_entry_t, link) fragmenter_tx_list_t; 00068 00069 typedef struct { 00070 int8_t interface_id; 00071 uint16_t local_frag_tag; 00072 uint8_t msduHandle; 00073 fragmenter_tx_list_t indirect_tx_queue; 00074 uint8_t *fragment_indirect_tx_buffer; //Used for write fragmentation header 00075 uint16_t mtu_size; 00076 fragmenter_tx_entry_t active_unicast_tx_buf; //Current active direct unicast tx process 00077 fragmenter_tx_entry_t active_broadcast_tx_buf; //Current active direct broadcast tx process 00078 buffer_list_t directTxQueue; //Waiting free tx process 00079 uint16_t indirect_big_packet_threshold; 00080 uint16_t max_indirect_big_packets_total; 00081 uint16_t max_indirect_small_packets_per_child; 00082 bool fragmenter_active; /*!< Fragmenter state */ 00083 ns_list_link_t link; /*!< List link entry */ 00084 } fragmenter_interface_t; 00085 00086 static NS_LIST_DEFINE(fragmenter_interface_list, fragmenter_interface_t, link); 00087 00088 /* Adaptation interface local functions */ 00089 static fragmenter_interface_t *lowpan_adaptation_interface_discover(int8_t interfaceId); 00090 00091 /* Interface direct message pending queue functions */ 00092 static void lowpan_adaptation_tx_queue_write(fragmenter_interface_t *interface_ptr , buffer_t *buf); 00093 static buffer_t * lowpan_adaptation_tx_queue_read(fragmenter_interface_t *interface_ptr, protocol_interface_info_entry_t *cur); 00094 00095 /* Data direction and message length validation */ 00096 static bool lowpan_adaptation_indirect_data_request(mle_neigh_table_entry_t *mle_entry); 00097 static bool lowpan_adaptation_request_longer_than_mtu(protocol_interface_info_entry_t *cur, buffer_t *buf); 00098 00099 /* Common data tx request process functions */ 00100 static void lowpan_active_buffer_state_reset(fragmenter_tx_entry_t *tx_buffer); 00101 static uint8_t lowpan_data_request_unique_handle_get(fragmenter_interface_t *interface_ptr); 00102 static fragmenter_tx_entry_t *lowpan_indirect_entry_allocate(uint16_t fragment_buffer_size); 00103 static fragmenter_tx_entry_t * lowpan_adaptation_tx_process_init(fragmenter_interface_t *interface_ptr, bool indirect, bool fragmented, bool is_unicast); 00104 static void lowpan_adaptation_data_request_primitiv_set(const buffer_t *buf, mcps_data_req_t *dataReq, protocol_interface_info_entry_t *cur); 00105 static void lowpan_data_request_to_mac(protocol_interface_info_entry_t *cur, buffer_t *buf, fragmenter_tx_entry_t *tx_ptr); 00106 00107 /* Tx confirmation local functions */ 00108 static bool lowpan_active_tx_handle_verify(uint8_t handle, buffer_t *buf); 00109 static fragmenter_tx_entry_t * lowpan_indirect_tx_handle_verify(uint8_t handle, fragmenter_tx_list_t *indirect_tx_queue); 00110 static void lowpan_adaptation_data_process_clean(fragmenter_interface_t *interface_ptr, fragmenter_tx_entry_t *tx_ptr, uint8_t socket_event); 00111 static uint8_t map_mlme_status_to_socket_event(uint8_t mlme_status); 00112 static bool lowpan_adaptation_tx_process_ready(fragmenter_tx_entry_t *tx_ptr); 00113 00114 /* Fragmentation local functions */ 00115 static int8_t lowpan_message_fragmentation_init(buffer_t *buf, fragmenter_tx_entry_t *frag_entry, protocol_interface_info_entry_t *cur); 00116 static bool lowpan_message_fragmentation_message_write(const fragmenter_tx_entry_t *frag_entry, mcps_data_req_t *dataReq); 00117 static void lowpan_adaptation_indirect_queue_free_message(struct protocol_interface_info_entry *cur, fragmenter_interface_t *interface_ptr, fragmenter_tx_entry_t *tx_ptr); 00118 00119 //Discover 00120 static fragmenter_interface_t *lowpan_adaptation_interface_discover(int8_t interfaceId) 00121 { 00122 00123 ns_list_foreach(fragmenter_interface_t, interface_ptr, &fragmenter_interface_list) { 00124 if (interfaceId == interface_ptr->interface_id) { 00125 return interface_ptr; 00126 } 00127 } 00128 00129 return NULL; 00130 } 00131 00132 00133 static void lowpan_adaptation_tx_queue_write(fragmenter_interface_t *interface_ptr , buffer_t *buf) 00134 { 00135 buffer_t *lower_priority_buf = NULL; 00136 00137 ns_list_foreach(buffer_t, cur, &interface_ptr->directTxQueue) { 00138 if (cur->priority < buf->priority) { 00139 lower_priority_buf = cur; 00140 break; 00141 } 00142 } 00143 00144 if (lower_priority_buf) { 00145 ns_list_add_before(&interface_ptr->directTxQueue, lower_priority_buf, buf); 00146 } else { 00147 ns_list_add_to_end(&interface_ptr->directTxQueue, buf); 00148 } 00149 } 00150 00151 static buffer_t * lowpan_adaptation_tx_queue_read(fragmenter_interface_t *interface_ptr, protocol_interface_info_entry_t *cur) 00152 { 00153 /* Currently this function is called only when data confirm is received for previously sent packet. 00154 * Data confirm has freed the corresponding "active buffer" and this function will look for new buffer to be set as active buffer. 00155 */ 00156 ns_list_foreach_safe(buffer_t, buf, &interface_ptr->directTxQueue) { 00157 bool fragmented_needed = lowpan_adaptation_request_longer_than_mtu(cur, buf); 00158 //Check that we not trig second active fragmentation process 00159 if (fragmented_needed && interface_ptr->fragmenter_active) { 00160 tr_debug("Do not trig Second active fragmentation"); 00161 } else if ((buf->link_specific.ieee802_15_4.requestAck && !interface_ptr->active_unicast_tx_buf.buf) 00162 || (!buf->link_specific.ieee802_15_4.requestAck && !interface_ptr->active_broadcast_tx_buf.buf)) { 00163 ns_list_remove(&interface_ptr->directTxQueue, buf); 00164 return buf; 00165 } 00166 } 00167 return NULL; 00168 } 00169 00170 //fragmentation needed 00171 00172 static bool lowpan_adaptation_request_longer_than_mtu(protocol_interface_info_entry_t *cur, buffer_t *buf) 00173 { 00174 uint_fast8_t overhead = mac_helper_frame_overhead(cur, buf); 00175 00176 00177 if (buffer_data_length(buf) > (int16_t)mac_helper_max_payload_size(cur, overhead)) { 00178 return true; 00179 } else { 00180 return false; 00181 } 00182 } 00183 00184 static bool lowpan_adaptation_indirect_data_request(mle_neigh_table_entry_t *mle_entry) 00185 { 00186 if (mle_entry && !(mle_entry->mode & MLE_RX_ON_IDLE)) { 00187 return true; 00188 } 00189 return false; 00190 } 00191 00192 00193 static void lowpan_active_buffer_state_reset(fragmenter_tx_entry_t *tx_buffer) 00194 { 00195 if (tx_buffer->buf) { 00196 buffer_free(tx_buffer->buf); 00197 tx_buffer->buf = NULL; 00198 } 00199 tx_buffer->fragmented_data = false; 00200 tx_buffer->first_fragment = true; 00201 } 00202 00203 static bool lowpan_active_tx_handle_verify(uint8_t handle, buffer_t *buf) 00204 { 00205 00206 if (buf && buf->seq == handle) { 00207 return true; 00208 } 00209 00210 00211 return false; 00212 } 00213 00214 00215 00216 static fragmenter_tx_entry_t * lowpan_indirect_tx_handle_verify(uint8_t handle, fragmenter_tx_list_t *indirect_tx_queue) 00217 { 00218 ns_list_foreach(fragmenter_tx_entry_t, entry, indirect_tx_queue) { 00219 if (entry->buf->seq == handle) { 00220 return entry; 00221 } 00222 } 00223 return NULL; 00224 } 00225 00226 00227 00228 static uint8_t lowpan_data_request_unique_handle_get(fragmenter_interface_t *interface_ptr) 00229 { 00230 bool valid_info = false; 00231 uint8_t handle; 00232 while(!valid_info) { 00233 handle = interface_ptr->msduHandle++; 00234 if (!lowpan_active_tx_handle_verify(handle,interface_ptr->active_unicast_tx_buf.buf) 00235 && !lowpan_active_tx_handle_verify(handle,interface_ptr->active_broadcast_tx_buf.buf) 00236 && !lowpan_indirect_tx_handle_verify(handle, &interface_ptr->indirect_tx_queue)) { 00237 valid_info = true; 00238 } 00239 } 00240 return handle; 00241 00242 } 00243 00244 static void lowpan_indirect_entry_free(fragmenter_tx_list_t *list , fragmenter_tx_entry_t *entry) 00245 { 00246 ns_list_remove(list, entry); 00247 if (entry->buf) { 00248 buffer_free(entry->buf); 00249 } 00250 ns_dyn_mem_free(entry->fragmenter_buf); 00251 ns_dyn_mem_free(entry); 00252 } 00253 00254 static void lowpan_indirect_queue_free(fragmenter_tx_list_t *list) 00255 { 00256 while(!ns_list_is_empty(list)) { 00257 fragmenter_tx_entry_t *entry = ns_list_get_first(list); 00258 lowpan_indirect_entry_free(list, entry); 00259 } 00260 } 00261 00262 00263 int8_t lowpan_adaptation_interface_init(int8_t interface_id, uint16_t mac_mtu_size) 00264 { 00265 if (mac_mtu_size == 0) { 00266 return -2; 00267 } 00268 //Remove old interface 00269 lowpan_adaptation_interface_free(interface_id); 00270 00271 //Allocate new 00272 fragmenter_interface_t *interface_ptr = ns_dyn_mem_alloc(sizeof(fragmenter_interface_t)); 00273 uint8_t *tx_buffer = ns_dyn_mem_alloc(mac_mtu_size); 00274 if (!interface_ptr || !tx_buffer) { 00275 ns_dyn_mem_free(interface_ptr); 00276 ns_dyn_mem_free(tx_buffer); 00277 return -1; 00278 } 00279 00280 memset(interface_ptr, 0 ,sizeof(fragmenter_interface_t)); 00281 interface_ptr->interface_id = interface_id; 00282 interface_ptr->fragment_indirect_tx_buffer = tx_buffer; 00283 interface_ptr->mtu_size = mac_mtu_size; 00284 interface_ptr->msduHandle = randLIB_get_8bit(); 00285 interface_ptr->local_frag_tag = randLIB_get_16bit(); 00286 00287 ns_list_init(&interface_ptr->indirect_tx_queue); 00288 ns_list_init(&interface_ptr->directTxQueue); 00289 00290 ns_list_add_to_end(&fragmenter_interface_list, interface_ptr); 00291 00292 return 0; 00293 } 00294 00295 int8_t lowpan_adaptation_interface_free(int8_t interface_id) 00296 { 00297 //Discover 00298 fragmenter_interface_t *interface_ptr = lowpan_adaptation_interface_discover(interface_id); 00299 if (!interface_ptr) { 00300 return -1; 00301 } 00302 00303 ns_list_remove(&fragmenter_interface_list, interface_ptr); 00304 //free active tx process 00305 lowpan_active_buffer_state_reset(&interface_ptr->active_unicast_tx_buf); 00306 lowpan_active_buffer_state_reset(&interface_ptr->active_broadcast_tx_buf); 00307 00308 //Free Indirect entry 00309 lowpan_indirect_queue_free(&interface_ptr->indirect_tx_queue); 00310 00311 buffer_free_list(&interface_ptr->directTxQueue); 00312 00313 //Free Dynamic allocated entries 00314 ns_dyn_mem_free(interface_ptr->fragment_indirect_tx_buffer); 00315 ns_dyn_mem_free(interface_ptr); 00316 00317 return 0; 00318 } 00319 00320 00321 int8_t lowpan_adaptation_interface_reset(int8_t interface_id) 00322 { 00323 //Discover 00324 fragmenter_interface_t *interface_ptr = lowpan_adaptation_interface_discover(interface_id); 00325 if (!interface_ptr) { 00326 return -1; 00327 } 00328 00329 //free active tx process 00330 lowpan_active_buffer_state_reset(&interface_ptr->active_unicast_tx_buf); 00331 lowpan_active_buffer_state_reset(&interface_ptr->active_broadcast_tx_buf); 00332 //Clean fragmented message flag 00333 interface_ptr->fragmenter_active = false; 00334 00335 //Free Indirect entry 00336 lowpan_indirect_queue_free(&interface_ptr->indirect_tx_queue); 00337 00338 buffer_free_list(&interface_ptr->directTxQueue); 00339 00340 return 0; 00341 } 00342 00343 00344 static fragmenter_tx_entry_t *lowpan_indirect_entry_allocate(uint16_t fragment_buffer_size) 00345 { 00346 fragmenter_tx_entry_t *indirec_entry = ns_dyn_mem_temporary_alloc(sizeof(fragmenter_tx_entry_t)); 00347 if (!indirec_entry) { 00348 return NULL; 00349 } 00350 00351 if (fragment_buffer_size) { 00352 indirec_entry->fragmenter_buf = ns_dyn_mem_temporary_alloc(fragment_buffer_size); 00353 if (!indirec_entry->fragmenter_buf) { 00354 ns_dyn_mem_free(indirec_entry); 00355 return NULL; 00356 } 00357 } else { 00358 indirec_entry->fragmenter_buf = NULL; 00359 } 00360 00361 00362 indirec_entry->buf = NULL; 00363 indirec_entry->fragmented_data = false; 00364 indirec_entry->first_fragment = true; 00365 00366 return indirec_entry; 00367 } 00368 00369 static int8_t lowpan_message_fragmentation_init(buffer_t *buf, fragmenter_tx_entry_t *frag_entry, protocol_interface_info_entry_t *cur) 00370 { 00371 uint8_t *ptr; 00372 uint16_t uncompressed_size; 00373 00374 /* Look for pre-fragmentation headers - strip off and store away */ 00375 frag_entry->unfrag_ptr = buf->buf_ptr ; 00376 frag_entry->unfrag_len = 0; 00377 ptr = buffer_data_pointer(buf); 00378 00379 if ((ptr[0] & LOWPAN_MESH_MASK) == LOWPAN_MESH) { 00380 uint_fast8_t size = mesh_header_len_from_type_byte(ptr[0]); 00381 ptr += size; 00382 buf->buf_ptr += size; 00383 } 00384 00385 if (ptr[0] == LOWPAN_DISPATCH_BC0) { 00386 ptr += 2; 00387 buf->buf_ptr += 2; 00388 } 00389 00390 frag_entry->unfrag_len = buf->buf_ptr - frag_entry->unfrag_ptr; 00391 00392 frag_entry->pattern = iphc_header_scan(buf, &uncompressed_size); 00393 frag_entry->size = buffer_data_length(buf); 00394 frag_entry->orig_size = frag_entry->size; 00395 frag_entry->size += (uncompressed_size - frag_entry->pattern); 00396 00397 uint_fast8_t overhead = mac_helper_frame_overhead(cur, buf); 00398 frag_entry->frag_max = mac_helper_max_payload_size(cur, overhead); 00399 00400 00401 /* RFC 4944 says MTU and hence maximum size here is 1280, but that's 00402 * arbitrary, and some have argued that 6LoWPAN should have a larger 00403 * MTU, to avoid the need for IP fragmentation. So we don't enforce 00404 * that, leaving MTU decisions to upper layer config, and only look 00405 * for the "real" MTU from the FRAG header format, which would allow up 00406 * to 0x7FF (2047). 00407 */ 00408 if (frag_entry->size > LOWPAN_HARD_MTU_LIMIT) { 00409 tr_error("Packet too big"); 00410 return -1; 00411 } 00412 00413 frag_entry->offset = uncompressed_size / 8; 00414 frag_entry->frag_len = frag_entry->pattern; 00415 if (frag_entry->unfrag_len + 4 + frag_entry->frag_len > frag_entry->frag_max) { 00416 tr_error("Too long 6LoWPAN header for fragment"); 00417 return -1; 00418 } 00419 00420 /* Now, frag_len is compressed payload bytes (just IPHC headers), and 00421 * frag_ptr->offset is uncompressed payload 8-octet units (just uncompressed 00422 * IPHC headers). Add post-IPHC payload to bring total compressed size up 00423 * to maximum fragment size. 00424 */ 00425 while (frag_entry->unfrag_len + 4 + frag_entry->frag_len + 8 <= frag_entry->frag_max) { 00426 frag_entry->offset++; 00427 frag_entry->frag_len += 8; 00428 } 00429 frag_entry->fragmented_data = true; 00430 00431 return 0; 00432 00433 } 00434 00435 /** 00436 * Return true when there is more fragmented packet for this message 00437 */ 00438 static bool lowpan_message_fragmentation_message_write(const fragmenter_tx_entry_t *frag_entry, mcps_data_req_t *dataReq) 00439 { 00440 uint8_t *ptr = dataReq->msdu; 00441 if (frag_entry->unfrag_len) { 00442 memcpy(ptr, frag_entry->buf->buf + frag_entry->unfrag_ptr, frag_entry->unfrag_len); 00443 ptr += frag_entry->unfrag_len; 00444 } 00445 if (frag_entry->first_fragment) { 00446 ptr = common_write_16_bit(((uint16_t) LOWPAN_FRAG1 << 8) | frag_entry->size, ptr); 00447 ptr = common_write_16_bit(frag_entry->tag, ptr); 00448 } else { 00449 ptr = common_write_16_bit(((uint16_t) LOWPAN_FRAGN << 8) | frag_entry->size, ptr); 00450 ptr = common_write_16_bit(frag_entry->tag, ptr); 00451 *ptr++ = frag_entry->offset; 00452 } 00453 memcpy(ptr, buffer_data_pointer(frag_entry->buf), frag_entry->frag_len); 00454 ptr += frag_entry->frag_len; 00455 dataReq->msduLength = ptr - dataReq->msdu; 00456 return frag_entry->offset * 8 + frag_entry->frag_len < frag_entry->size; 00457 } 00458 00459 static fragmenter_tx_entry_t * lowpan_adaptation_tx_process_init(fragmenter_interface_t *interface_ptr, bool indirect, bool fragmented, bool is_unicast) 00460 { 00461 fragmenter_tx_entry_t *tx_entry; 00462 if (!indirect) { 00463 if (is_unicast) { 00464 tx_entry = &interface_ptr->active_unicast_tx_buf; 00465 } else { 00466 tx_entry = &interface_ptr->active_broadcast_tx_buf; 00467 } 00468 tx_entry->fragmenter_buf = interface_ptr->fragment_indirect_tx_buffer; 00469 } else { 00470 if (fragmented) { 00471 tx_entry = lowpan_indirect_entry_allocate(interface_ptr->mtu_size); 00472 } else { 00473 tx_entry = lowpan_indirect_entry_allocate(0); 00474 } 00475 } 00476 00477 if (!tx_entry) { 00478 return NULL; 00479 } 00480 00481 lowpan_active_buffer_state_reset(tx_entry); 00482 00483 tx_entry->indirectData = indirect; 00484 00485 return tx_entry; 00486 } 00487 00488 buffer_t * lowpan_adaptation_data_process_tx_preprocess(protocol_interface_info_entry_t *cur, buffer_t *buf) 00489 { 00490 //Validate is link known and set indirect, datareq and security key id mode 00491 if (buf->dst_sa .addr_type == ADDR_NONE ) { 00492 goto tx_error_handler; 00493 } 00494 00495 mle_neigh_table_entry_t *mle_entry = NULL; 00496 /* If MLE is enabled, we will talk if we have an MLE association */ 00497 if (buf->dst_sa .addr_type == ADDR_802_15_4_LONG ) { 00498 mle_entry = mle_class_get_by_link_address(cur->id, buf->dst_sa .address + 2, buf->dst_sa .addr_type ); 00499 00500 } else if(buf->dst_sa .addr_type == ADDR_802_15_4_SHORT && (common_read_16_bit(buf->dst_sa .address + 2)) != 0xffff) { 00501 mle_entry = mle_class_get_by_link_address(cur->id, buf->dst_sa .address + 2, buf->dst_sa .addr_type ); 00502 } 00503 00504 //Validate neighbour 00505 if (!buf->options .ll_security_bypass_tx && mle_entry) { 00506 00507 if (mle_entry->handshakeReady || mle_entry->thread_commission) { 00508 00509 } else { 00510 //tr_warn("Drop TX to unassociated %s", trace_sockaddr(&buf->dst_sa, true)); 00511 goto tx_error_handler; 00512 } 00513 } 00514 00515 //Check indirect 00516 00517 00518 if (addr_check_broadcast(buf->dst_sa .address , buf->dst_sa .addr_type ) == eOK) { 00519 buf->dst_sa .addr_type = ADDR_802_15_4_SHORT ; 00520 buf->dst_sa .address [2] = 0xff; 00521 buf->dst_sa .address [3] = 0xff; 00522 buf->link_specific.ieee802_15_4.indirectTxProcess = false; 00523 buf->link_specific.ieee802_15_4.requestAck = false; 00524 } else { 00525 buf->link_specific.ieee802_15_4.requestAck = true; 00526 buf->link_specific.ieee802_15_4.indirectTxProcess = lowpan_adaptation_indirect_data_request(mle_entry); 00527 } 00528 00529 if (buf->link_specific.ieee802_15_4.key_id_mode != B_SECURITY_KEY_ID_2) { 00530 00531 if (!buf->link_specific.ieee802_15_4.requestAck ) { 00532 buf->link_specific.ieee802_15_4.key_id_mode = B_SECURITY_KEY_ID_MODE_DEFAULT; 00533 } else if (mle_entry && !mle_entry->thread_commission) { 00534 buf->link_specific.ieee802_15_4.key_id_mode = B_SECURITY_KEY_ID_MODE_DEFAULT; 00535 } else { 00536 buf->link_specific.ieee802_15_4.key_id_mode = B_SECURITY_KEY_ID_IMPLICIT; 00537 } 00538 } 00539 00540 return buf; 00541 00542 tx_error_handler: 00543 socket_tx_buffer_event_and_free(buf, SOCKET_TX_FAIL); 00544 return NULL; 00545 00546 } 00547 00548 static void lowpan_adaptation_data_request_primitiv_set(const buffer_t *buf, mcps_data_req_t *dataReq, protocol_interface_info_entry_t *cur) 00549 { 00550 memset(dataReq, 0, sizeof(mcps_data_req_t)); 00551 00552 //Check do we need fragmentation 00553 00554 dataReq->InDirectTx = buf->link_specific.ieee802_15_4.indirectTxProcess; 00555 dataReq->TxAckReq = buf->link_specific.ieee802_15_4.requestAck; 00556 dataReq->SrcAddrMode = buf->src_sa .addr_type ; 00557 dataReq->DstAddrMode = buf->dst_sa .addr_type ; 00558 memcpy(dataReq->DstAddr, &buf->dst_sa .address [2], 8); 00559 00560 if (buf->link_specific.ieee802_15_4.useDefaultPanId) { 00561 dataReq->DstPANId = mac_helper_panid_get(cur); 00562 } else { 00563 dataReq->DstPANId = buf->link_specific.ieee802_15_4.dstPanId; 00564 } 00565 00566 //Allocate message msdu handle 00567 dataReq->msduHandle = buf->seq ; 00568 00569 //Set Messages 00570 if (!buf->options .ll_security_bypass_tx ) { 00571 dataReq->Key.SecurityLevel = mac_helper_default_security_level_get(cur); 00572 if (dataReq->Key.SecurityLevel) { 00573 switch (buf->link_specific.ieee802_15_4.key_id_mode) { 00574 case B_SECURITY_KEY_ID_MODE_DEFAULT: 00575 dataReq->Key.KeyIndex = mac_helper_default_key_index_get(cur); 00576 dataReq->Key.KeyIdMode = mac_helper_default_security_key_id_mode_get(cur); 00577 break; 00578 case B_SECURITY_KEY_ID_IMPLICIT: 00579 dataReq->Key.KeyIdMode = MAC_KEY_ID_MODE_IMPLICIT; 00580 break; 00581 00582 case B_SECURITY_KEY_ID_2: 00583 dataReq->Key.KeyIndex = 0xff; 00584 dataReq->Key.KeyIdMode = MAC_KEY_ID_MODE_SRC4_IDX; 00585 common_write_32_bit(0xffffffff, dataReq->Key.Keysource); 00586 break; 00587 } 00588 } 00589 } 00590 } 00591 00592 static void lowpan_adaptation_make_room_for_small_packet(protocol_interface_info_entry_t *cur, fragmenter_interface_t *interface_ptr, mle_neigh_table_entry_t *neighbour_to_count) 00593 { 00594 if (interface_ptr->max_indirect_small_packets_per_child == 0) { 00595 return; 00596 } 00597 00598 uint_fast16_t count = 0; 00599 00600 ns_list_foreach_reverse_safe(fragmenter_tx_entry_t, tx_entry, &interface_ptr->indirect_tx_queue) { 00601 mle_neigh_table_entry_t *tx_neighbour = mle_class_get_by_link_address(cur->id, tx_entry->buf->dst_sa.address + 2, tx_entry->buf->dst_sa.addr_type); 00602 if (tx_neighbour == neighbour_to_count && buffer_data_length(tx_entry->buf) <= interface_ptr->indirect_big_packet_threshold) { 00603 if (++count >= interface_ptr->max_indirect_small_packets_per_child) { 00604 lowpan_adaptation_indirect_queue_free_message(cur, interface_ptr, tx_entry); 00605 } 00606 } 00607 } 00608 } 00609 00610 static void lowpan_adaptation_make_room_for_big_packet(struct protocol_interface_info_entry *cur, fragmenter_interface_t *interface_ptr) 00611 { 00612 if (interface_ptr->max_indirect_big_packets_total == 0) { 00613 return; 00614 } 00615 00616 uint_fast16_t count = 0; 00617 00618 ns_list_foreach_reverse_safe(fragmenter_tx_entry_t, tx_entry, &interface_ptr->indirect_tx_queue) { 00619 if (buffer_data_length(tx_entry->buf) > interface_ptr->indirect_big_packet_threshold) { 00620 if (++count >= interface_ptr->max_indirect_big_packets_total) { 00621 lowpan_adaptation_indirect_queue_free_message(cur, interface_ptr, tx_entry); 00622 } 00623 } 00624 } 00625 } 00626 00627 static void lowpan_data_request_to_mac(protocol_interface_info_entry_t *cur, buffer_t *buf, fragmenter_tx_entry_t *tx_ptr) 00628 { 00629 mcps_data_req_t dataReq; 00630 00631 lowpan_adaptation_data_request_primitiv_set(buf, &dataReq, cur); 00632 if (tx_ptr->fragmented_data) { 00633 dataReq.msdu = tx_ptr->fragmenter_buf; 00634 //Call fragmenter 00635 bool more_fragments = lowpan_message_fragmentation_message_write(tx_ptr, &dataReq); 00636 if (dataReq.InDirectTx) { 00637 dataReq.PendingBit |= more_fragments; 00638 } 00639 } else { 00640 dataReq.msduLength = buffer_data_length(buf); 00641 dataReq.msdu = buffer_data_pointer(buf); 00642 } 00643 if (buf->link_specific.ieee802_15_4.rf_channel_switch) { 00644 //Switch channel if selected channel is different 00645 if (cur->mac_parameters->mac_channel != buf->link_specific.ieee802_15_4.selected_channel) { 00646 uint8_t channel = cur->mac_parameters->mac_channel; 00647 mac_helper_mac_channel_set(cur, buf->link_specific.ieee802_15_4.selected_channel); 00648 buf->link_specific.ieee802_15_4.selected_channel = channel; 00649 } else { 00650 buf->link_specific.ieee802_15_4.rf_channel_switch = false; 00651 } 00652 } 00653 00654 cur->mac_api->mcps_data_req(cur->mac_api, &dataReq); 00655 } 00656 00657 int8_t lowpan_adaptation_interface_tx(protocol_interface_info_entry_t *cur, buffer_t *buf) 00658 { 00659 if (!buf) { 00660 return -1; 00661 } 00662 00663 if (!cur || !cur->mac_api || !cur->mac_api->mcps_data_req) { 00664 goto tx_error_handler; 00665 } 00666 00667 fragmenter_interface_t *interface_ptr = lowpan_adaptation_interface_discover(cur->id); 00668 if (!interface_ptr) { 00669 goto tx_error_handler; 00670 } 00671 00672 //Check packet size 00673 bool fragmented_needed = lowpan_adaptation_request_longer_than_mtu(cur, buf); 00674 bool is_unicast = buf->link_specific.ieee802_15_4.requestAck; 00675 bool indirect = buf->link_specific.ieee802_15_4.indirectTxProcess; 00676 if (!indirect) { 00677 if (((is_unicast && interface_ptr->active_unicast_tx_buf.buf) || (!is_unicast && interface_ptr->active_broadcast_tx_buf.buf)) || (fragmented_needed && interface_ptr->fragmenter_active)) { 00678 lowpan_adaptation_tx_queue_write(interface_ptr, buf); 00679 return 0; //Return here 00680 } 00681 } 00682 00683 //Allocate Handle 00684 buf->seq = lowpan_data_request_unique_handle_get(interface_ptr); 00685 00686 if (buf->options .ll_sec_bypass_frag_deny && fragmented_needed) { 00687 // force security for fragmented packets 00688 buf->options .ll_security_bypass_tx = false; 00689 } 00690 00691 fragmenter_tx_entry_t *tx_ptr = lowpan_adaptation_tx_process_init(interface_ptr, indirect, fragmented_needed, is_unicast); 00692 if (!tx_ptr) { 00693 goto tx_error_handler; 00694 } 00695 00696 tx_ptr->buf = buf; 00697 00698 if (fragmented_needed) { 00699 //Fragmentation init 00700 if (lowpan_message_fragmentation_init(buf, tx_ptr, cur) ) { 00701 tr_error("Fragment init fail"); 00702 if (indirect) { 00703 ns_dyn_mem_free(tx_ptr->fragmenter_buf); 00704 ns_dyn_mem_free(tx_ptr); 00705 } 00706 goto tx_error_handler; 00707 } 00708 00709 tx_ptr->tag = interface_ptr->local_frag_tag++; 00710 if (!indirect) { 00711 interface_ptr->fragmenter_active = true; 00712 } 00713 } 00714 00715 if (indirect) { 00716 //Add to indirectQUue 00717 mle_neigh_table_entry_t *mle_entry = mle_class_get_by_link_address(cur->id, buf->dst_sa .address + 2, buf->dst_sa .addr_type ); 00718 00719 if (buffer_data_length(buf) <= interface_ptr->indirect_big_packet_threshold) { 00720 lowpan_adaptation_make_room_for_small_packet(cur, interface_ptr, mle_entry); 00721 } else { 00722 lowpan_adaptation_make_room_for_big_packet(cur, interface_ptr); 00723 } 00724 00725 ns_list_add_to_end(&interface_ptr->indirect_tx_queue, tx_ptr); 00726 if (mle_entry) { 00727 buf->link_specific.ieee802_15_4.indirectTTL = (uint32_t) mle_entry->timeout_rx * MLE_TIMER_TICKS_MS; 00728 } else { 00729 buf->link_specific.ieee802_15_4.indirectTTL = cur->mac_parameters->mac_in_direct_entry_timeout; 00730 } 00731 00732 } 00733 00734 lowpan_data_request_to_mac(cur, buf, tx_ptr); 00735 return 0; 00736 00737 00738 tx_error_handler: 00739 socket_tx_buffer_event_and_free(buf, SOCKET_NO_RAM); 00740 return -1; 00741 00742 } 00743 00744 00745 static bool lowpan_adaptation_tx_process_ready(fragmenter_tx_entry_t *tx_ptr) 00746 { 00747 if (!tx_ptr->fragmented_data) { 00748 if (tx_ptr->buf->ip_routed_up) { 00749 protocol_stats_update(STATS_IP_ROUTE_UP, buffer_data_length(tx_ptr->buf)); 00750 } else { 00751 protocol_stats_update(STATS_IP_TX_COUNT, buffer_data_length(tx_ptr->buf)); 00752 } 00753 return true; 00754 } 00755 00756 00757 00758 //Update data pointer by last packet length 00759 buffer_data_strip_header(tx_ptr->buf, tx_ptr->frag_len); 00760 //Update offset 00761 if (!tx_ptr->first_fragment) { 00762 tx_ptr->offset += tx_ptr->frag_len / 8; 00763 } else { 00764 tx_ptr->first_fragment = false; 00765 } 00766 00767 /* Check Is still Data what have to send */ 00768 tx_ptr->frag_len = buffer_data_length(tx_ptr->buf); 00769 00770 00771 if (tx_ptr->frag_len == 0) { 00772 //Release current data 00773 if (tx_ptr->buf->ip_routed_up) { 00774 protocol_stats_update(STATS_IP_ROUTE_UP, tx_ptr->orig_size); 00775 } else { 00776 protocol_stats_update(STATS_IP_TX_COUNT, tx_ptr->orig_size); 00777 } 00778 return true; 00779 } 00780 00781 //Continue Process 00782 00783 if (tx_ptr->unfrag_len + 5 + tx_ptr->frag_len > tx_ptr->frag_max) { 00784 tx_ptr->frag_len = tx_ptr->frag_max - 5 - tx_ptr->unfrag_len; 00785 tx_ptr->frag_len &= ~7; 00786 } 00787 00788 return false; 00789 } 00790 00791 static void lowpan_adaptation_data_process_clean(fragmenter_interface_t *interface_ptr, fragmenter_tx_entry_t *tx_ptr, uint8_t socket_event) 00792 { 00793 buffer_t *buf = tx_ptr->buf ; 00794 tx_ptr->buf = NULL; 00795 if (buf->link_specific.ieee802_15_4.indirectTxProcess) { 00796 //release from list and free entry 00797 lowpan_indirect_entry_free(&interface_ptr->indirect_tx_queue, tx_ptr); 00798 } 00799 00800 socket_tx_buffer_event_and_free(buf, socket_event); 00801 } 00802 00803 00804 int8_t lowpan_adaptation_interface_tx_confirm(protocol_interface_info_entry_t *cur, const mcps_data_conf_t *confirm) 00805 { 00806 if( !cur || !confirm ){ 00807 return -1; 00808 } 00809 00810 fragmenter_interface_t *interface_ptr = lowpan_adaptation_interface_discover(cur->id); 00811 if (!interface_ptr) { 00812 return -1; 00813 } 00814 00815 //Check first 00816 fragmenter_tx_entry_t *tx_ptr; 00817 bool active_direct_confirm; 00818 bool is_unicast = true; 00819 00820 if (lowpan_active_tx_handle_verify(confirm->msduHandle,interface_ptr->active_unicast_tx_buf.buf)) { 00821 active_direct_confirm = true; 00822 tx_ptr = &interface_ptr->active_unicast_tx_buf; 00823 } else if (lowpan_active_tx_handle_verify(confirm->msduHandle,interface_ptr->active_broadcast_tx_buf.buf)) { 00824 active_direct_confirm = true; 00825 tx_ptr = &interface_ptr->active_broadcast_tx_buf; 00826 is_unicast = false; 00827 } else { 00828 active_direct_confirm = false; 00829 tx_ptr = lowpan_indirect_tx_handle_verify(confirm->msduHandle, &interface_ptr->indirect_tx_queue); 00830 } 00831 00832 if (!tx_ptr) { 00833 tr_error("No data request for this confirmation %u", confirm->msduHandle); 00834 return -1; 00835 } 00836 00837 //Check status for 00838 buffer_t *buf = tx_ptr->buf ; 00839 00840 //Indirect data expiration 00841 if (confirm->status == MLME_TRANSACTION_EXPIRED && !active_direct_confirm) { 00842 if (buf->link_specific.ieee802_15_4.indirectTTL > 7000) 00843 { 00844 buf->link_specific.ieee802_15_4.indirectTTL -= 7000; 00845 //Push Back to MAC 00846 lowpan_data_request_to_mac(cur, buf, tx_ptr); 00847 return 0; 00848 } 00849 } 00850 00851 switch (confirm->status) { 00852 case MLME_TX_NO_ACK: 00853 case MLME_NO_DATA: 00854 case MLME_SUCCESS: 00855 if (buf->link_specific.ieee802_15_4.requestAck) { 00856 bool success = false; 00857 if (confirm->status == MLME_SUCCESS) { 00858 success = true; 00859 } 00860 etx_transm_attempts_update(cur->id, 1 + confirm->tx_retries , success, buf->dst_sa .addr_type , buf->dst_sa .address ); 00861 } 00862 break; 00863 default: 00864 00865 break; 00866 00867 } 00868 //Switch original channel back 00869 if (buf->link_specific.ieee802_15_4.rf_channel_switch) { 00870 mac_helper_mac_channel_set(cur, buf->link_specific.ieee802_15_4.selected_channel); 00871 buf->link_specific.ieee802_15_4.rf_channel_switch = false; 00872 } 00873 00874 switch (confirm->status) { 00875 00876 case MLME_BUSY_CHAN: 00877 lowpan_data_request_to_mac(cur, buf, tx_ptr); 00878 break; 00879 case MLME_SUCCESS: 00880 00881 //Check is there more packets 00882 if (lowpan_adaptation_tx_process_ready(tx_ptr)) { 00883 if (tx_ptr->fragmented_data && active_direct_confirm) { 00884 //Clean 00885 interface_ptr->fragmenter_active = false; 00886 } 00887 lowpan_adaptation_data_process_clean(interface_ptr, tx_ptr, map_mlme_status_to_socket_event(confirm->status)); 00888 } else { 00889 lowpan_data_request_to_mac(cur, buf, tx_ptr); 00890 } 00891 00892 break; 00893 case MLME_TX_NO_ACK: 00894 case MLME_SECURITY_FAIL: 00895 case MLME_TRANSACTION_EXPIRED: 00896 default: 00897 tr_error("MCPS Data fail by status %u", confirm->status); 00898 #ifdef HAVE_RPL 00899 if (confirm->status == MLME_TX_NO_ACK) { 00900 if (buf->route && rpl_data_is_rpl_parent_route(buf->route->route_info.source)) { 00901 protocol_stats_update(STATS_RPL_PARENT_TX_FAIL, 1); 00902 } 00903 } 00904 #endif 00905 if (tx_ptr->fragmented_data) { 00906 tx_ptr->buf->buf_ptr = tx_ptr->buf->buf_end; 00907 tx_ptr->buf->buf_ptr -= tx_ptr->orig_size; 00908 if (active_direct_confirm) { 00909 interface_ptr->fragmenter_active = false; 00910 } 00911 } 00912 00913 lowpan_adaptation_data_process_clean(interface_ptr, tx_ptr, map_mlme_status_to_socket_event(confirm->status)); 00914 break; 00915 00916 } 00917 00918 if ((is_unicast && !interface_ptr->active_unicast_tx_buf.buf) || (!is_unicast && !interface_ptr->active_broadcast_tx_buf.buf)) { 00919 //Read Buffer and trig next direct request 00920 lowpan_adaptation_interface_tx(cur, lowpan_adaptation_tx_queue_read(interface_ptr, cur)); 00921 } 00922 00923 return 0; 00924 00925 } 00926 00927 static uint8_t map_mlme_status_to_socket_event(uint8_t mlme_status) 00928 { 00929 uint8_t socket_event; 00930 00931 switch (mlme_status) { 00932 case MLME_SUCCESS: 00933 socket_event = SOCKET_TX_DONE; 00934 break; 00935 case MLME_TX_NO_ACK: 00936 case MLME_SECURITY_FAIL: 00937 case MLME_TRANSACTION_EXPIRED: 00938 default: 00939 socket_event = SOCKET_TX_FAIL; 00940 break; 00941 } 00942 00943 return (socket_event); 00944 } 00945 00946 bool lowpan_adaptation_tx_active(int8_t interface_id) 00947 { 00948 fragmenter_interface_t *interface_ptr = lowpan_adaptation_interface_discover(interface_id); 00949 00950 if (!interface_ptr || (!interface_ptr->active_unicast_tx_buf.buf && !interface_ptr->active_broadcast_tx_buf.buf)) { 00951 return false; 00952 } 00953 return true; 00954 } 00955 00956 static bool lowpan_tx_buffer_address_compare(sockaddr_t *dst_sa, uint8_t *address_ptr, addrtype_t adr_type) 00957 { 00958 00959 if (dst_sa->addr_type != adr_type) { 00960 return false; 00961 } 00962 00963 uint8_t compare_length; 00964 switch (adr_type) { 00965 case ADDR_802_15_4_SHORT : 00966 compare_length = 2; 00967 break; 00968 case ADDR_802_15_4_LONG : 00969 compare_length = 8; 00970 break; 00971 default: 00972 return false; 00973 } 00974 00975 00976 if (memcmp(&dst_sa->address [2], address_ptr, compare_length)) { 00977 return false; 00978 } 00979 return true; 00980 } 00981 00982 static void lowpan_adaptation_purge_from_mac(struct protocol_interface_info_entry *cur, uint8_t msduhandle) 00983 { 00984 mcps_purge_t purge_req; 00985 purge_req.msduHandle = msduhandle; 00986 cur->mac_api->mcps_purge_req(cur->mac_api, &purge_req); 00987 } 00988 00989 static void lowpan_adaptation_indirect_queue_free_message(struct protocol_interface_info_entry *cur, fragmenter_interface_t *interface_ptr, fragmenter_tx_entry_t *tx_ptr) 00990 { 00991 tr_debug("Purge from indirect handle %u", tx_ptr->buf->seq); 00992 if (cur->mac_api->mcps_purge_req) { 00993 lowpan_adaptation_purge_from_mac(cur, tx_ptr->buf->seq); 00994 } 00995 lowpan_adaptation_data_process_clean(interface_ptr, tx_ptr, SOCKET_TX_FAIL); 00996 } 00997 00998 int8_t lowpan_adaptation_indirect_free_messages_from_queues_by_address(struct protocol_interface_info_entry *cur, uint8_t *address_ptr, addrtype_t adr_type) 00999 { 01000 fragmenter_interface_t *interface_ptr = lowpan_adaptation_interface_discover(cur->id); 01001 01002 if (!interface_ptr ) { 01003 return -1; 01004 } 01005 01006 //Check first indirect queue 01007 ns_list_foreach_safe(fragmenter_tx_entry_t, entry, &interface_ptr->indirect_tx_queue) { 01008 01009 if (lowpan_tx_buffer_address_compare(&entry->buf->dst_sa, address_ptr, adr_type)) { 01010 //Purge from mac 01011 lowpan_adaptation_indirect_queue_free_message(cur, interface_ptr, entry); 01012 } 01013 } 01014 01015 return 0; 01016 01017 } 01018 01019 int8_t lowpan_adaptation_indirect_queue_params_set(struct protocol_interface_info_entry *cur, uint16_t indirect_big_packet_threshold, uint16_t max_indirect_big_packets_total, uint16_t max_indirect_small_packets_per_child) 01020 { 01021 fragmenter_interface_t *interface_ptr = lowpan_adaptation_interface_discover(cur->id); 01022 01023 if (!interface_ptr) { 01024 return -1; 01025 } 01026 01027 interface_ptr->indirect_big_packet_threshold = indirect_big_packet_threshold; 01028 interface_ptr->max_indirect_big_packets_total = max_indirect_big_packets_total; 01029 interface_ptr->max_indirect_small_packets_per_child = max_indirect_small_packets_per_child; 01030 01031 return 0; 01032 }
Generated on Tue Jul 12 2022 13:02:39 by
