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.
adaptation_interface.c
00001 /* 00002 * Copyright (c) 2016-2018, 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/MAC/mpx_api.h" 00039 #include "6LoWPAN/Mesh/mesh.h" 00040 #include "6LoWPAN/IPHC_Decode/iphc_decompress.h" 00041 #include "lowpan_adaptation_interface.h" 00042 #include "MLE/mle.h" 00043 #ifdef HAVE_RPL 00044 #include "RPL/rpl_data.h" 00045 #endif 00046 #include "6LoWPAN/ws/ws_common.h" 00047 #include "Service_Libs/mac_neighbor_table/mac_neighbor_table.h" 00048 #include "6LoWPAN/Thread/thread_common.h" 00049 #include "6LoWPAN/ws/ws_common.h" 00050 00051 #define TRACE_GROUP "6lAd" 00052 00053 typedef void (adaptation_etx_update_cb)(protocol_interface_info_entry_t *cur, buffer_t *buf, const mcps_data_conf_t *confirm); 00054 00055 // #define EXTRA_DEBUG_EXTRA 00056 #ifdef EXTRA_DEBUG_EXTRA 00057 #define tr_debug_extra(...) tr_debug(__VA_ARGS__) 00058 #else 00059 #define tr_debug_extra(...) 00060 #endif 00061 00062 typedef struct { 00063 uint16_t tag; /*!< Fragmentation datagram TAG ID */ 00064 uint16_t size; /*!< Datagram Total Size (uncompressed) */ 00065 uint16_t orig_size; /*!< Datagram Original Size (compressed) */ 00066 uint16_t frag_max; /*!< Maximum fragment size (MAC payload) */ 00067 uint16_t offset; /*!< Data offset from datagram start */ 00068 int16_t pattern; /*!< Size of compressed LoWPAN headers */ 00069 uint16_t unfrag_ptr; /*!< Offset within buf of headers that precede the FRAG header */ 00070 uint16_t frag_len; 00071 uint8_t unfrag_len; /*!< Length of headers that precede the FRAG header */ 00072 bool fragmented_data:1; 00073 bool first_fragment:1; 00074 bool indirect_data:1; 00075 bool indirect_data_cached:1; /* Data cached for delayed transmission as mac request is already active */ 00076 buffer_t *buf; 00077 uint8_t *fragmenter_buf; 00078 ns_list_link_t link; /*!< List link entry */ 00079 } fragmenter_tx_entry_t; 00080 00081 00082 typedef NS_LIST_HEAD (fragmenter_tx_entry_t, link) fragmenter_tx_list_t; 00083 00084 typedef struct { 00085 int8_t interface_id; 00086 uint16_t local_frag_tag; 00087 uint8_t msduHandle; 00088 fragmenter_tx_list_t indirect_tx_queue; 00089 uint8_t *fragment_indirect_tx_buffer; //Used for write fragmentation header 00090 uint16_t mtu_size; 00091 fragmenter_tx_entry_t active_unicast_tx_buf; //Current active direct unicast tx process 00092 fragmenter_tx_entry_t active_broadcast_tx_buf; //Current active direct broadcast tx process 00093 buffer_list_t directTxQueue; //Waiting free tx process 00094 uint16_t indirect_big_packet_threshold; 00095 uint16_t max_indirect_big_packets_total; 00096 uint16_t max_indirect_small_packets_per_child; 00097 bool fragmenter_active; /*!< Fragmenter state */ 00098 adaptation_etx_update_cb *etx_update_cb; 00099 mpx_api_t *mpx_api; 00100 uint16_t mpx_user_id; 00101 ns_list_link_t link; /*!< List link entry */ 00102 } fragmenter_interface_t; 00103 00104 static NS_LIST_DEFINE(fragmenter_interface_list, fragmenter_interface_t, link); 00105 00106 /* Adaptation interface local functions */ 00107 static fragmenter_interface_t *lowpan_adaptation_interface_discover(int8_t interfaceId); 00108 00109 /* Interface direct message pending queue functions */ 00110 static void lowpan_adaptation_tx_queue_write(fragmenter_interface_t *interface_ptr , buffer_t *buf); 00111 static buffer_t * lowpan_adaptation_tx_queue_read(fragmenter_interface_t *interface_ptr, protocol_interface_info_entry_t *cur); 00112 00113 /* Data direction and message length validation */ 00114 static bool lowpan_adaptation_indirect_data_request(mac_neighbor_table_entry_t *mle_entry); 00115 static bool lowpan_adaptation_request_longer_than_mtu(protocol_interface_info_entry_t *cur, buffer_t *buf, fragmenter_interface_t *interface_ptr); 00116 00117 /* Common data tx request process functions */ 00118 static void lowpan_active_buffer_state_reset(fragmenter_tx_entry_t *tx_buffer); 00119 static uint8_t lowpan_data_request_unique_handle_get(fragmenter_interface_t *interface_ptr); 00120 static fragmenter_tx_entry_t *lowpan_indirect_entry_allocate(uint16_t fragment_buffer_size); 00121 static fragmenter_tx_entry_t * lowpan_adaptation_tx_process_init(fragmenter_interface_t *interface_ptr, bool indirect, bool fragmented, bool is_unicast); 00122 static void lowpan_adaptation_data_request_primitiv_set(const buffer_t *buf, mcps_data_req_t *dataReq, protocol_interface_info_entry_t *cur); 00123 static void lowpan_data_request_to_mac(protocol_interface_info_entry_t *cur, buffer_t *buf, fragmenter_tx_entry_t *tx_ptr, fragmenter_interface_t *interface_ptr); 00124 00125 /* Tx confirmation local functions */ 00126 static bool lowpan_active_tx_handle_verify(uint8_t handle, buffer_t *buf); 00127 static fragmenter_tx_entry_t * lowpan_indirect_tx_handle_verify(uint8_t handle, fragmenter_tx_list_t *indirect_tx_queue); 00128 static void lowpan_adaptation_data_process_clean(fragmenter_interface_t *interface_ptr, fragmenter_tx_entry_t *tx_ptr, uint8_t socket_event); 00129 static uint8_t map_mlme_status_to_socket_event(uint8_t mlme_status); 00130 static bool lowpan_adaptation_tx_process_ready(fragmenter_tx_entry_t *tx_ptr); 00131 00132 /* Fragmentation local functions */ 00133 static int8_t lowpan_message_fragmentation_init(buffer_t *buf, fragmenter_tx_entry_t *frag_entry, protocol_interface_info_entry_t *cur, fragmenter_interface_t *interface_ptr); 00134 static bool lowpan_message_fragmentation_message_write(const fragmenter_tx_entry_t *frag_entry, mcps_data_req_t *dataReq); 00135 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); 00136 00137 static fragmenter_tx_entry_t* lowpan_adaptation_indirect_mac_data_request_active(fragmenter_interface_t *interface_ptr, fragmenter_tx_entry_t *tx_ptr); 00138 00139 static void lowpan_adaptation_etx_update_cb(protocol_interface_info_entry_t *cur, buffer_t *buf, const mcps_data_conf_t *confirm) 00140 { 00141 switch (confirm->status) { 00142 case MLME_TX_NO_ACK: 00143 case MLME_NO_DATA: 00144 case MLME_SUCCESS: 00145 if (buf->link_specific.ieee802_15_4.requestAck) { 00146 if (cur->lowpan_info & INTERFACE_NWK_BOOTSRAP_MLE) { 00147 bool success = false; 00148 if (confirm->status == MLME_SUCCESS) { 00149 success = true; 00150 } 00151 // Gets table entry 00152 mac_neighbor_table_entry_t *neigh_table_ptr = mac_neighbor_table_address_discover(mac_neighbor_info(cur), buf->dst_sa .address + PAN_ID_LEN, buf->dst_sa .addr_type ); 00153 if (neigh_table_ptr) { 00154 etx_transm_attempts_update(cur->id, 1 + confirm->tx_retries , success, neigh_table_ptr->index ); 00155 // Updates ETX statistics 00156 etx_storage_t * etx_entry = etx_storage_entry_get(cur->id, neigh_table_ptr->index ); 00157 if (etx_entry) { 00158 if (neigh_table_ptr->link_role == PRIORITY_PARENT_NEIGHBOUR) { 00159 protocol_stats_update(STATS_ETX_1ST_PARENT, etx_entry->etx >> 4); 00160 } else if (neigh_table_ptr->link_role == SECONDARY_PARENT_NEIGHBOUR) { 00161 protocol_stats_update(STATS_ETX_2ND_PARENT, etx_entry->etx >> 4); 00162 } 00163 } 00164 } 00165 } 00166 } 00167 break; 00168 default: 00169 00170 break; 00171 00172 } 00173 } 00174 00175 00176 //Discover 00177 static fragmenter_interface_t *lowpan_adaptation_interface_discover(int8_t interfaceId) 00178 { 00179 00180 ns_list_foreach(fragmenter_interface_t, interface_ptr, &fragmenter_interface_list) { 00181 if (interfaceId == interface_ptr->interface_id) { 00182 return interface_ptr; 00183 } 00184 } 00185 00186 return NULL; 00187 } 00188 00189 static struct protocol_interface_info_entry *lowpan_adaptation_network_interface_discover(const mpx_api_t* api) 00190 { 00191 00192 ns_list_foreach(fragmenter_interface_t, interface_ptr, &fragmenter_interface_list) { 00193 if (api == interface_ptr->mpx_api) { 00194 return protocol_stack_interface_info_get_by_id(interface_ptr->interface_id); 00195 } 00196 } 00197 00198 return NULL; 00199 } 00200 00201 00202 static void lowpan_adaptation_tx_queue_write(fragmenter_interface_t *interface_ptr , buffer_t *buf) 00203 { 00204 buffer_t *lower_priority_buf = NULL; 00205 00206 ns_list_foreach(buffer_t, cur, &interface_ptr->directTxQueue) { 00207 if (cur->priority < buf->priority) { 00208 lower_priority_buf = cur; 00209 break; 00210 } 00211 } 00212 00213 if (lower_priority_buf) { 00214 ns_list_add_before(&interface_ptr->directTxQueue, lower_priority_buf, buf); 00215 } else { 00216 ns_list_add_to_end(&interface_ptr->directTxQueue, buf); 00217 } 00218 } 00219 00220 static buffer_t * lowpan_adaptation_tx_queue_read(fragmenter_interface_t *interface_ptr, protocol_interface_info_entry_t *cur) 00221 { 00222 /* Currently this function is called only when data confirm is received for previously sent packet. 00223 * Data confirm has freed the corresponding "active buffer" and this function will look for new buffer to be set as active buffer. 00224 */ 00225 ns_list_foreach_safe(buffer_t, buf, &interface_ptr->directTxQueue) { 00226 bool fragmented_needed = lowpan_adaptation_request_longer_than_mtu(cur, buf, interface_ptr); 00227 //Check that we not trig second active fragmentation process 00228 if (fragmented_needed && interface_ptr->fragmenter_active) { 00229 tr_debug("Do not trig Second active fragmentation"); 00230 } else if ((buf->link_specific.ieee802_15_4.requestAck && !interface_ptr->active_unicast_tx_buf.buf) 00231 || (!buf->link_specific.ieee802_15_4.requestAck && !interface_ptr->active_broadcast_tx_buf.buf)) { 00232 ns_list_remove(&interface_ptr->directTxQueue, buf); 00233 return buf; 00234 } 00235 } 00236 return NULL; 00237 } 00238 00239 //fragmentation needed 00240 00241 static bool lowpan_adaptation_request_longer_than_mtu(protocol_interface_info_entry_t *cur, buffer_t *buf, fragmenter_interface_t *interface_ptr) 00242 { 00243 uint_fast16_t overhead = mac_helper_frame_overhead(cur, buf); 00244 00245 if (interface_ptr->mpx_api) { 00246 overhead += interface_ptr->mpx_api->mpx_headroom_size_get(interface_ptr->mpx_api, interface_ptr->mpx_user_id); 00247 } 00248 00249 00250 if (buffer_data_length(buf) > (int16_t)mac_helper_max_payload_size(cur, overhead)) { 00251 return true; 00252 } else { 00253 return false; 00254 } 00255 } 00256 00257 static bool lowpan_adaptation_indirect_data_request(mac_neighbor_table_entry_t *entry_ptr) 00258 { 00259 if (entry_ptr && !(entry_ptr->rx_on_idle )) { 00260 return true; 00261 } 00262 return false; 00263 } 00264 00265 00266 static void lowpan_active_buffer_state_reset(fragmenter_tx_entry_t *tx_buffer) 00267 { 00268 if (tx_buffer->buf) { 00269 buffer_free(tx_buffer->buf); 00270 tx_buffer->buf = NULL; 00271 } 00272 tx_buffer->fragmented_data = false; 00273 tx_buffer->first_fragment = true; 00274 } 00275 00276 static bool lowpan_active_tx_handle_verify(uint8_t handle, buffer_t *buf) 00277 { 00278 00279 if (buf && buf->seq == handle) { 00280 return true; 00281 } 00282 00283 00284 return false; 00285 } 00286 00287 00288 00289 static fragmenter_tx_entry_t * lowpan_indirect_tx_handle_verify(uint8_t handle, fragmenter_tx_list_t *indirect_tx_queue) 00290 { 00291 ns_list_foreach(fragmenter_tx_entry_t, entry, indirect_tx_queue) { 00292 if (entry->buf->seq == handle) { 00293 return entry; 00294 } 00295 } 00296 return NULL; 00297 } 00298 00299 00300 00301 static uint8_t lowpan_data_request_unique_handle_get(fragmenter_interface_t *interface_ptr) 00302 { 00303 bool valid_info = false; 00304 uint8_t handle; 00305 while(!valid_info) { 00306 handle = interface_ptr->msduHandle++; 00307 if (!lowpan_active_tx_handle_verify(handle,interface_ptr->active_unicast_tx_buf.buf) 00308 && !lowpan_active_tx_handle_verify(handle,interface_ptr->active_broadcast_tx_buf.buf) 00309 && !lowpan_indirect_tx_handle_verify(handle, &interface_ptr->indirect_tx_queue)) { 00310 valid_info = true; 00311 } 00312 } 00313 return handle; 00314 00315 } 00316 00317 static void lowpan_indirect_entry_free(fragmenter_tx_list_t *list , fragmenter_tx_entry_t *entry) 00318 { 00319 ns_list_remove(list, entry); 00320 if (entry->buf) { 00321 buffer_free(entry->buf); 00322 } 00323 ns_dyn_mem_free(entry->fragmenter_buf); 00324 ns_dyn_mem_free(entry); 00325 } 00326 00327 static void lowpan_indirect_queue_free(fragmenter_tx_list_t *list) 00328 { 00329 while(!ns_list_is_empty(list)) { 00330 fragmenter_tx_entry_t *entry = ns_list_get_first(list); 00331 lowpan_indirect_entry_free(list, entry); 00332 } 00333 } 00334 00335 00336 int8_t lowpan_adaptation_interface_init(int8_t interface_id, uint16_t mac_mtu_size) 00337 { 00338 if (mac_mtu_size == 0) { 00339 return -2; 00340 } 00341 //Remove old interface 00342 lowpan_adaptation_interface_free(interface_id); 00343 00344 //Allocate new 00345 fragmenter_interface_t *interface_ptr = ns_dyn_mem_alloc(sizeof(fragmenter_interface_t)); 00346 uint8_t *tx_buffer = ns_dyn_mem_alloc(mac_mtu_size); 00347 if (!interface_ptr || !tx_buffer) { 00348 ns_dyn_mem_free(interface_ptr); 00349 ns_dyn_mem_free(tx_buffer); 00350 return -1; 00351 } 00352 00353 memset(interface_ptr, 0 ,sizeof(fragmenter_interface_t)); 00354 interface_ptr->interface_id = interface_id; 00355 interface_ptr->fragment_indirect_tx_buffer = tx_buffer; 00356 interface_ptr->mtu_size = mac_mtu_size; 00357 interface_ptr->msduHandle = randLIB_get_8bit(); 00358 interface_ptr->local_frag_tag = randLIB_get_16bit(); 00359 00360 ns_list_init(&interface_ptr->indirect_tx_queue); 00361 ns_list_init(&interface_ptr->directTxQueue); 00362 00363 ns_list_add_to_end(&fragmenter_interface_list, interface_ptr); 00364 00365 return 0; 00366 } 00367 00368 void lowpan_adaptation_interface_etx_update_enable(int8_t interface_id) 00369 { 00370 fragmenter_interface_t *interface_ptr = lowpan_adaptation_interface_discover(interface_id); 00371 if (interface_ptr) { 00372 interface_ptr->etx_update_cb = lowpan_adaptation_etx_update_cb; 00373 } 00374 } 00375 00376 int8_t lowpan_adaptation_interface_free(int8_t interface_id) 00377 { 00378 //Discover 00379 fragmenter_interface_t *interface_ptr = lowpan_adaptation_interface_discover(interface_id); 00380 if (!interface_ptr) { 00381 return -1; 00382 } 00383 00384 ns_list_remove(&fragmenter_interface_list, interface_ptr); 00385 //free active tx process 00386 lowpan_active_buffer_state_reset(&interface_ptr->active_unicast_tx_buf); 00387 lowpan_active_buffer_state_reset(&interface_ptr->active_broadcast_tx_buf); 00388 00389 //Free Indirect entry 00390 lowpan_indirect_queue_free(&interface_ptr->indirect_tx_queue); 00391 00392 buffer_free_list(&interface_ptr->directTxQueue); 00393 00394 //Free Dynamic allocated entries 00395 ns_dyn_mem_free(interface_ptr->fragment_indirect_tx_buffer); 00396 ns_dyn_mem_free(interface_ptr); 00397 00398 return 0; 00399 } 00400 00401 00402 int8_t lowpan_adaptation_interface_reset(int8_t interface_id) 00403 { 00404 //Discover 00405 fragmenter_interface_t *interface_ptr = lowpan_adaptation_interface_discover(interface_id); 00406 if (!interface_ptr) { 00407 return -1; 00408 } 00409 00410 //free active tx process 00411 lowpan_active_buffer_state_reset(&interface_ptr->active_unicast_tx_buf); 00412 lowpan_active_buffer_state_reset(&interface_ptr->active_broadcast_tx_buf); 00413 //Clean fragmented message flag 00414 interface_ptr->fragmenter_active = false; 00415 00416 //Free Indirect entry 00417 lowpan_indirect_queue_free(&interface_ptr->indirect_tx_queue); 00418 00419 buffer_free_list(&interface_ptr->directTxQueue); 00420 00421 return 0; 00422 } 00423 00424 static void lowpan_adaptation_mpx_data_confirm(const mpx_api_t* api, const struct mcps_data_conf_s *data) 00425 { 00426 protocol_interface_info_entry_t * interface = lowpan_adaptation_network_interface_discover(api); 00427 00428 lowpan_adaptation_interface_tx_confirm(interface, data); 00429 } 00430 00431 static void lowpan_adaptation_mpx_data_indication(const mpx_api_t* api, const struct mcps_data_ind_s *data) 00432 { 00433 protocol_interface_info_entry_t * interface = lowpan_adaptation_network_interface_discover(api); 00434 lowpan_adaptation_interface_data_ind(interface, data); 00435 } 00436 00437 00438 00439 00440 int8_t lowpan_adaptation_interface_mpx_register(int8_t interface_id, struct mpx_api_s *mpx_api, uint16_t mpx_user_id) 00441 { 00442 //Discover 00443 fragmenter_interface_t *interface_ptr = lowpan_adaptation_interface_discover(interface_id); 00444 if (!interface_ptr) { 00445 return -1; 00446 } 00447 if (!mpx_api && interface_ptr->mpx_api) { 00448 //Disable Data Callbacks from MPX Class 00449 interface_ptr->mpx_api->mpx_user_registration(interface_ptr->mpx_api, NULL, NULL, interface_ptr->mpx_user_id); 00450 } 00451 00452 interface_ptr->mpx_api = mpx_api; 00453 interface_ptr->mpx_user_id = mpx_user_id; 00454 00455 if (interface_ptr->mpx_api) { 00456 //Register MPX callbacks: confirmation and indication 00457 interface_ptr->mpx_api->mpx_user_registration(interface_ptr->mpx_api, lowpan_adaptation_mpx_data_confirm, lowpan_adaptation_mpx_data_indication, interface_ptr->mpx_user_id); 00458 } 00459 return 0; 00460 } 00461 00462 00463 static fragmenter_tx_entry_t *lowpan_indirect_entry_allocate(uint16_t fragment_buffer_size) 00464 { 00465 fragmenter_tx_entry_t *indirec_entry = ns_dyn_mem_temporary_alloc(sizeof(fragmenter_tx_entry_t)); 00466 if (!indirec_entry) { 00467 return NULL; 00468 } 00469 00470 if (fragment_buffer_size) { 00471 indirec_entry->fragmenter_buf = ns_dyn_mem_temporary_alloc(fragment_buffer_size); 00472 if (!indirec_entry->fragmenter_buf) { 00473 ns_dyn_mem_free(indirec_entry); 00474 return NULL; 00475 } 00476 } else { 00477 indirec_entry->fragmenter_buf = NULL; 00478 } 00479 00480 00481 indirec_entry->buf = NULL; 00482 indirec_entry->fragmented_data = false; 00483 indirec_entry->first_fragment = true; 00484 indirec_entry->indirect_data_cached = false; 00485 00486 return indirec_entry; 00487 } 00488 00489 static int8_t lowpan_message_fragmentation_init(buffer_t *buf, fragmenter_tx_entry_t *frag_entry, protocol_interface_info_entry_t *cur, fragmenter_interface_t *interface_ptr) 00490 { 00491 uint8_t *ptr; 00492 uint16_t uncompressed_size; 00493 00494 /* Look for pre-fragmentation headers - strip off and store away */ 00495 frag_entry->unfrag_ptr = buf->buf_ptr ; 00496 frag_entry->unfrag_len = 0; 00497 ptr = buffer_data_pointer(buf); 00498 00499 if ((ptr[0] & LOWPAN_MESH_MASK) == LOWPAN_MESH) { 00500 uint_fast8_t size = mesh_header_len_from_type_byte(ptr[0]); 00501 ptr += size; 00502 buf->buf_ptr += size; 00503 } 00504 00505 if (ptr[0] == LOWPAN_DISPATCH_BC0) { 00506 ptr += 2; 00507 buf->buf_ptr += 2; 00508 } 00509 00510 frag_entry->unfrag_len = buf->buf_ptr - frag_entry->unfrag_ptr; 00511 00512 frag_entry->pattern = iphc_header_scan(buf, &uncompressed_size); 00513 frag_entry->size = buffer_data_length(buf); 00514 frag_entry->orig_size = frag_entry->size; 00515 frag_entry->size += (uncompressed_size - frag_entry->pattern); 00516 00517 uint_fast16_t overhead = mac_helper_frame_overhead(cur, buf); 00518 if (interface_ptr->mpx_api) { 00519 overhead += interface_ptr->mpx_api->mpx_headroom_size_get(interface_ptr->mpx_api, interface_ptr->mpx_user_id); 00520 } 00521 00522 frag_entry->frag_max = mac_helper_max_payload_size(cur, overhead); 00523 00524 00525 /* RFC 4944 says MTU and hence maximum size here is 1280, but that's 00526 * arbitrary, and some have argued that 6LoWPAN should have a larger 00527 * MTU, to avoid the need for IP fragmentation. So we don't enforce 00528 * that, leaving MTU decisions to upper layer config, and only look 00529 * for the "real" MTU from the FRAG header format, which would allow up 00530 * to 0x7FF (2047). 00531 */ 00532 if (frag_entry->size > LOWPAN_HARD_MTU_LIMIT) { 00533 tr_error("Packet too big"); 00534 return -1; 00535 } 00536 00537 frag_entry->offset = uncompressed_size / 8; 00538 frag_entry->frag_len = frag_entry->pattern; 00539 if (frag_entry->unfrag_len + 4 + frag_entry->frag_len > frag_entry->frag_max) { 00540 tr_error("Too long 6LoWPAN header for fragment"); 00541 return -1; 00542 } 00543 00544 /* Now, frag_len is compressed payload bytes (just IPHC headers), and 00545 * frag_ptr->offset is uncompressed payload 8-octet units (just uncompressed 00546 * IPHC headers). Add post-IPHC payload to bring total compressed size up 00547 * to maximum fragment size. 00548 */ 00549 while (frag_entry->unfrag_len + 4 + frag_entry->frag_len + 8 <= frag_entry->frag_max) { 00550 frag_entry->offset++; 00551 frag_entry->frag_len += 8; 00552 } 00553 frag_entry->fragmented_data = true; 00554 00555 return 0; 00556 00557 } 00558 00559 /** 00560 * Return true when there is more fragmented packet for this message 00561 */ 00562 static bool lowpan_message_fragmentation_message_write(const fragmenter_tx_entry_t *frag_entry, mcps_data_req_t *dataReq) 00563 { 00564 uint8_t *ptr = dataReq->msdu; 00565 if (frag_entry->unfrag_len) { 00566 memcpy(ptr, frag_entry->buf->buf + frag_entry->unfrag_ptr, frag_entry->unfrag_len); 00567 ptr += frag_entry->unfrag_len; 00568 } 00569 if (frag_entry->first_fragment) { 00570 ptr = common_write_16_bit(((uint16_t) LOWPAN_FRAG1 << 8) | frag_entry->size, ptr); 00571 ptr = common_write_16_bit(frag_entry->tag, ptr); 00572 } else { 00573 ptr = common_write_16_bit(((uint16_t) LOWPAN_FRAGN << 8) | frag_entry->size, ptr); 00574 ptr = common_write_16_bit(frag_entry->tag, ptr); 00575 *ptr++ = frag_entry->offset; 00576 } 00577 memcpy(ptr, buffer_data_pointer(frag_entry->buf), frag_entry->frag_len); 00578 ptr += frag_entry->frag_len; 00579 dataReq->msduLength = ptr - dataReq->msdu; 00580 return frag_entry->offset * 8 + frag_entry->frag_len < frag_entry->size; 00581 } 00582 00583 static fragmenter_tx_entry_t * lowpan_adaptation_tx_process_init(fragmenter_interface_t *interface_ptr, bool indirect, bool fragmented, bool is_unicast) 00584 { 00585 fragmenter_tx_entry_t *tx_entry; 00586 if (!indirect) { 00587 if (is_unicast) { 00588 tx_entry = &interface_ptr->active_unicast_tx_buf; 00589 } else { 00590 tx_entry = &interface_ptr->active_broadcast_tx_buf; 00591 } 00592 tx_entry->fragmenter_buf = interface_ptr->fragment_indirect_tx_buffer; 00593 } else { 00594 if (fragmented) { 00595 tx_entry = lowpan_indirect_entry_allocate(interface_ptr->mtu_size); 00596 } else { 00597 tx_entry = lowpan_indirect_entry_allocate(0); 00598 } 00599 } 00600 00601 if (!tx_entry) { 00602 return NULL; 00603 } 00604 00605 lowpan_active_buffer_state_reset(tx_entry); 00606 00607 tx_entry->indirect_data = indirect; 00608 00609 return tx_entry; 00610 } 00611 00612 buffer_t * lowpan_adaptation_data_process_tx_preprocess(protocol_interface_info_entry_t *cur, buffer_t *buf) 00613 { 00614 mac_neighbor_table_entry_t *neigh_entry_ptr = NULL; 00615 00616 //Validate is link known and set indirect, datareq and security key id mode 00617 if (buf->dst_sa .addr_type == ADDR_NONE ) { 00618 goto tx_error_handler; 00619 } 00620 00621 /* If MLE is enabled, we will talk if we have an MLE association */ 00622 if (buf->dst_sa .addr_type == ADDR_802_15_4_LONG ) { 00623 neigh_entry_ptr = mac_neighbor_table_address_discover(mac_neighbor_info(cur), buf->dst_sa .address + 2, buf->dst_sa .addr_type ); 00624 00625 } else if(buf->dst_sa .addr_type == ADDR_802_15_4_SHORT && (common_read_16_bit(buf->dst_sa .address + 2)) != 0xffff) { 00626 neigh_entry_ptr = mac_neighbor_table_address_discover(mac_neighbor_info(cur), buf->dst_sa .address + 2, buf->dst_sa .addr_type ); 00627 } 00628 00629 //Validate neighbour 00630 if (!buf->options .ll_security_bypass_tx && neigh_entry_ptr) { 00631 00632 if (neigh_entry_ptr->connected_device || neigh_entry_ptr->trusted_device ) { 00633 00634 } else { 00635 //tr_warn("Drop TX to unassociated %s", trace_sockaddr(&buf->dst_sa, true)); 00636 goto tx_error_handler; 00637 } 00638 } 00639 00640 //Check indirect 00641 00642 00643 if (addr_check_broadcast(buf->dst_sa .address , buf->dst_sa .addr_type ) == eOK) { 00644 buf->dst_sa .addr_type = ADDR_802_15_4_SHORT ; 00645 buf->dst_sa .address [2] = 0xff; 00646 buf->dst_sa .address [3] = 0xff; 00647 buf->link_specific.ieee802_15_4.indirectTxProcess = false; 00648 buf->link_specific.ieee802_15_4.requestAck = false; 00649 } else { 00650 buf->link_specific.ieee802_15_4.requestAck = true; 00651 buf->link_specific.ieee802_15_4.indirectTxProcess = lowpan_adaptation_indirect_data_request(neigh_entry_ptr); 00652 } 00653 00654 if (buf->link_specific.ieee802_15_4.key_id_mode != B_SECURITY_KEY_ID_2) { 00655 00656 if (!buf->link_specific.ieee802_15_4.requestAck ) { 00657 buf->link_specific.ieee802_15_4.key_id_mode = B_SECURITY_KEY_ID_MODE_DEFAULT; 00658 } else if (ws_info(cur) || (neigh_entry_ptr && !neigh_entry_ptr->trusted_device )) { 00659 buf->link_specific.ieee802_15_4.key_id_mode = B_SECURITY_KEY_ID_MODE_DEFAULT; 00660 } else { 00661 buf->link_specific.ieee802_15_4.key_id_mode = B_SECURITY_KEY_ID_IMPLICIT; 00662 } 00663 } 00664 00665 return buf; 00666 00667 tx_error_handler: 00668 if (neigh_entry_ptr && neigh_entry_ptr->nud_active ) { 00669 mac_neighbor_info(cur)->active_nud_process--; 00670 neigh_entry_ptr->nud_active = false; 00671 00672 } 00673 socket_tx_buffer_event_and_free(buf, SOCKET_TX_FAIL); 00674 return NULL; 00675 00676 } 00677 00678 static void lowpan_adaptation_data_request_primitiv_set(const buffer_t *buf, mcps_data_req_t *dataReq, protocol_interface_info_entry_t *cur) 00679 { 00680 memset(dataReq, 0, sizeof(mcps_data_req_t)); 00681 00682 //Check do we need fragmentation 00683 00684 dataReq->InDirectTx = buf->link_specific.ieee802_15_4.indirectTxProcess; 00685 dataReq->TxAckReq = buf->link_specific.ieee802_15_4.requestAck; 00686 dataReq->SrcAddrMode = buf->src_sa .addr_type ; 00687 dataReq->DstAddrMode = buf->dst_sa .addr_type ; 00688 memcpy(dataReq->DstAddr, &buf->dst_sa .address [2], 8); 00689 00690 if (buf->link_specific.ieee802_15_4.useDefaultPanId) { 00691 dataReq->DstPANId = mac_helper_panid_get(cur); 00692 } else { 00693 dataReq->DstPANId = buf->link_specific.ieee802_15_4.dstPanId; 00694 } 00695 00696 //Allocate message msdu handle 00697 dataReq->msduHandle = buf->seq ; 00698 00699 //Set Messages 00700 if (!buf->options .ll_security_bypass_tx ) { 00701 dataReq->Key.SecurityLevel = mac_helper_default_security_level_get(cur); 00702 if (dataReq->Key.SecurityLevel) { 00703 switch (buf->link_specific.ieee802_15_4.key_id_mode) { 00704 case B_SECURITY_KEY_ID_MODE_DEFAULT: 00705 dataReq->Key.KeyIndex = mac_helper_default_key_index_get(cur); 00706 dataReq->Key.KeyIdMode = mac_helper_default_security_key_id_mode_get(cur); 00707 break; 00708 case B_SECURITY_KEY_ID_IMPLICIT: 00709 dataReq->Key.KeyIdMode = MAC_KEY_ID_MODE_IMPLICIT; 00710 break; 00711 00712 case B_SECURITY_KEY_ID_2: 00713 dataReq->Key.KeyIndex = 0xff; 00714 dataReq->Key.KeyIdMode = MAC_KEY_ID_MODE_SRC4_IDX; 00715 common_write_32_bit(0xffffffff, dataReq->Key.Keysource); 00716 break; 00717 } 00718 } 00719 } 00720 } 00721 00722 static bool lowpan_adaptation_indirect_cache_sanity_check(protocol_interface_info_entry_t *cur, fragmenter_interface_t *interface_ptr) 00723 { 00724 fragmenter_tx_entry_t *active_tx_entry; 00725 ns_list_foreach(fragmenter_tx_entry_t, fragmenter_tx_entry, &interface_ptr->indirect_tx_queue) { 00726 if (fragmenter_tx_entry->indirect_data_cached == false) { 00727 // active entry, jump to next one 00728 continue; 00729 } 00730 00731 // cached entry found, check if it has pending data reguest 00732 active_tx_entry = lowpan_adaptation_indirect_mac_data_request_active(interface_ptr, fragmenter_tx_entry); 00733 00734 if (active_tx_entry == NULL) { 00735 // entry is in cache and is not sent to mac => trigger this 00736 tr_debug_extra("sanity check, push seq %d to addr %s", fragmenter_tx_entry->buf->seq, trace_ipv6(fragmenter_tx_entry->buf->dst_sa.address)); 00737 fragmenter_tx_entry->indirect_data_cached = false; 00738 lowpan_data_request_to_mac(cur, fragmenter_tx_entry->buf, fragmenter_tx_entry, interface_ptr); 00739 return true; 00740 } 00741 } 00742 00743 return false; 00744 } 00745 00746 static bool lowpan_adaptation_indirect_cache_trigger(protocol_interface_info_entry_t *cur, fragmenter_interface_t *interface_ptr, fragmenter_tx_entry_t *tx_ptr) 00747 { 00748 tr_debug_extra("lowpan_adaptation_indirect_cache_trigger()"); 00749 00750 if (ns_list_count(&interface_ptr->indirect_tx_queue) == 0) { 00751 return false; 00752 } 00753 00754 /* Trigger first cached entry */ 00755 ns_list_foreach(fragmenter_tx_entry_t, fragmenter_tx_entry, &interface_ptr->indirect_tx_queue) { 00756 if (fragmenter_tx_entry->indirect_data_cached) { 00757 if (addr_ipv6_equal(tx_ptr->buf->dst_sa.address, fragmenter_tx_entry->buf->dst_sa.address)) { 00758 tr_debug_extra("pushing seq %d to addr %s", fragmenter_tx_entry->buf->seq, trace_ipv6(fragmenter_tx_entry->buf->dst_sa.address)); 00759 fragmenter_tx_entry->indirect_data_cached = false; 00760 lowpan_data_request_to_mac(cur, fragmenter_tx_entry->buf, fragmenter_tx_entry, interface_ptr); 00761 return true; 00762 } 00763 } 00764 } 00765 00766 /* Sanity check, If nothing can be triggered from own address, check cache queue */ 00767 return lowpan_adaptation_indirect_cache_sanity_check(cur, interface_ptr); 00768 } 00769 00770 static fragmenter_tx_entry_t* lowpan_adaptation_indirect_mac_data_request_active(fragmenter_interface_t *interface_ptr, fragmenter_tx_entry_t *tx_ptr) 00771 { 00772 ns_list_foreach(fragmenter_tx_entry_t, fragmenter_tx_entry, &interface_ptr->indirect_tx_queue) { 00773 if (fragmenter_tx_entry->indirect_data_cached == false) { 00774 if (addr_ipv6_equal(tx_ptr->buf->dst_sa.address, fragmenter_tx_entry->buf->dst_sa.address)) { 00775 tr_debug_extra("active seq: %d", fragmenter_tx_entry->buf->seq); 00776 return fragmenter_tx_entry; 00777 } 00778 } 00779 } 00780 return NULL; 00781 } 00782 00783 static fragmenter_tx_entry_t* lowpan_adaptation_indirect_first_cached_request_get(fragmenter_interface_t *interface_ptr, fragmenter_tx_entry_t *tx_ptr) 00784 { 00785 ns_list_foreach(fragmenter_tx_entry_t, fragmenter_tx_entry, &interface_ptr->indirect_tx_queue) { 00786 if (fragmenter_tx_entry->indirect_data_cached == true) { 00787 if (addr_ipv6_equal(tx_ptr->buf->dst_sa.address, fragmenter_tx_entry->buf->dst_sa.address)) { 00788 tr_debug_extra("first cached seq: %d", fragmenter_tx_entry->buf->seq); 00789 return fragmenter_tx_entry; 00790 } 00791 } 00792 } 00793 return NULL; 00794 } 00795 00796 static void lowpan_adaptation_make_room_for_small_packet(protocol_interface_info_entry_t *cur, fragmenter_interface_t *interface_ptr, mac_neighbor_table_entry_t *neighbour_to_count) 00797 { 00798 if (interface_ptr->max_indirect_small_packets_per_child == 0) { 00799 return; 00800 } 00801 00802 uint_fast16_t count = 0; 00803 00804 ns_list_foreach_reverse_safe(fragmenter_tx_entry_t, tx_entry, &interface_ptr->indirect_tx_queue) { 00805 mac_neighbor_table_entry_t *tx_neighbour = mac_neighbor_table_address_discover(mac_neighbor_info(cur), tx_entry->buf->dst_sa.address + 2, tx_entry->buf->dst_sa.addr_type); 00806 if (tx_neighbour == neighbour_to_count && buffer_data_length(tx_entry->buf) <= interface_ptr->indirect_big_packet_threshold) { 00807 if (++count >= interface_ptr->max_indirect_small_packets_per_child) { 00808 lowpan_adaptation_indirect_queue_free_message(cur, interface_ptr, tx_entry); 00809 } 00810 } 00811 } 00812 } 00813 00814 static void lowpan_adaptation_make_room_for_big_packet(struct protocol_interface_info_entry *cur, fragmenter_interface_t *interface_ptr) 00815 { 00816 if (interface_ptr->max_indirect_big_packets_total == 0) { 00817 return; 00818 } 00819 00820 uint_fast16_t count = 0; 00821 00822 ns_list_foreach_reverse_safe(fragmenter_tx_entry_t, tx_entry, &interface_ptr->indirect_tx_queue) { 00823 if (buffer_data_length(tx_entry->buf) > interface_ptr->indirect_big_packet_threshold) { 00824 if (++count >= interface_ptr->max_indirect_big_packets_total) { 00825 tr_debug_extra("free seq: %d", tx_entry->buf->seq); 00826 lowpan_adaptation_indirect_queue_free_message(cur, interface_ptr, tx_entry); 00827 } 00828 } 00829 } 00830 } 00831 00832 static void lowpan_data_request_to_mac(protocol_interface_info_entry_t *cur, buffer_t *buf, fragmenter_tx_entry_t *tx_ptr, fragmenter_interface_t *interface_ptr) 00833 { 00834 mcps_data_req_t dataReq; 00835 00836 lowpan_adaptation_data_request_primitiv_set(buf, &dataReq, cur); 00837 if (tx_ptr->fragmented_data) { 00838 dataReq.msdu = tx_ptr->fragmenter_buf; 00839 //Call fragmenter 00840 bool more_fragments = lowpan_message_fragmentation_message_write(tx_ptr, &dataReq); 00841 if (dataReq.InDirectTx) { 00842 dataReq.PendingBit |= more_fragments; 00843 } 00844 } else { 00845 dataReq.msduLength = buffer_data_length(buf); 00846 dataReq.msdu = buffer_data_pointer(buf); 00847 } 00848 if (buf->link_specific.ieee802_15_4.rf_channel_switch) { 00849 //Switch channel if selected channel is different 00850 if (cur->mac_parameters->mac_channel != buf->link_specific.ieee802_15_4.selected_channel) { 00851 uint8_t channel = cur->mac_parameters->mac_channel; 00852 mac_helper_mac_channel_set(cur, buf->link_specific.ieee802_15_4.selected_channel); 00853 buf->link_specific.ieee802_15_4.selected_channel = channel; 00854 } else { 00855 buf->link_specific.ieee802_15_4.rf_channel_switch = false; 00856 } 00857 } 00858 00859 if (interface_ptr->mpx_api) { 00860 interface_ptr->mpx_api->mpx_data_request(interface_ptr->mpx_api, &dataReq, interface_ptr->mpx_user_id); 00861 } else { 00862 cur->mac_api->mcps_data_req(cur->mac_api, &dataReq); 00863 } 00864 } 00865 00866 int8_t lowpan_adaptation_interface_tx(protocol_interface_info_entry_t *cur, buffer_t *buf) 00867 { 00868 if (!buf) { 00869 return -1; 00870 } 00871 00872 if (!cur || !cur->mac_api || !cur->mac_api->mcps_data_req) { 00873 goto tx_error_handler; 00874 } 00875 00876 fragmenter_interface_t *interface_ptr = lowpan_adaptation_interface_discover(cur->id); 00877 if (!interface_ptr) { 00878 goto tx_error_handler; 00879 } 00880 00881 //Check packet size 00882 bool fragmented_needed = lowpan_adaptation_request_longer_than_mtu(cur, buf, interface_ptr); 00883 bool is_unicast = buf->link_specific.ieee802_15_4.requestAck; 00884 bool indirect = buf->link_specific.ieee802_15_4.indirectTxProcess; 00885 if (!indirect) { 00886 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)) { 00887 lowpan_adaptation_tx_queue_write(interface_ptr, buf); 00888 return 0; //Return here 00889 } 00890 } 00891 00892 //Allocate Handle 00893 buf->seq = lowpan_data_request_unique_handle_get(interface_ptr); 00894 00895 if (buf->options .ll_sec_bypass_frag_deny && fragmented_needed) { 00896 // force security for fragmented packets 00897 buf->options .ll_security_bypass_tx = false; 00898 } 00899 00900 fragmenter_tx_entry_t *tx_ptr = lowpan_adaptation_tx_process_init(interface_ptr, indirect, fragmented_needed, is_unicast); 00901 if (!tx_ptr) { 00902 goto tx_error_handler; 00903 } 00904 00905 tx_ptr->buf = buf; 00906 00907 if (fragmented_needed) { 00908 //Fragmentation init 00909 if (lowpan_message_fragmentation_init(buf, tx_ptr, cur, interface_ptr) ) { 00910 tr_error("Fragment init fail"); 00911 if (indirect) { 00912 ns_dyn_mem_free(tx_ptr->fragmenter_buf); 00913 ns_dyn_mem_free(tx_ptr); 00914 } 00915 goto tx_error_handler; 00916 } 00917 00918 tx_ptr->tag = interface_ptr->local_frag_tag++; 00919 if (!indirect) { 00920 interface_ptr->fragmenter_active = true; 00921 } 00922 } 00923 00924 if (indirect) { 00925 //Add to indirectQUue 00926 fragmenter_tx_entry_t *tx_ptr_cached; 00927 mac_neighbor_table_entry_t *neigh_entry_ptr = mac_neighbor_table_address_discover(mac_neighbor_info(cur), buf->dst_sa .address + PAN_ID_LEN, buf->dst_sa .addr_type ); 00928 if (neigh_entry_ptr) { 00929 buf->link_specific.ieee802_15_4.indirectTTL = (uint32_t) neigh_entry_ptr->link_lifetime * 1000; 00930 } else { 00931 buf->link_specific.ieee802_15_4.indirectTTL = cur->mac_parameters->mac_in_direct_entry_timeout; 00932 } 00933 00934 tr_debug_extra("indirect seq: %d, addr=%s", tx_ptr->buf->seq, trace_ipv6(buf->dst_sa .address )); 00935 00936 // Make room for new message if needed */ 00937 if (buffer_data_length(buf) <= interface_ptr->indirect_big_packet_threshold) { 00938 lowpan_adaptation_make_room_for_small_packet(cur, interface_ptr, neigh_entry_ptr); 00939 } else { 00940 lowpan_adaptation_make_room_for_big_packet(cur, interface_ptr); 00941 } 00942 00943 if (lowpan_adaptation_indirect_mac_data_request_active(interface_ptr, tx_ptr)) { 00944 // mac is handling previous data request, add new one to be cached */ 00945 tr_debug_extra("caching seq: %d", tx_ptr->buf->seq); 00946 tx_ptr->indirect_data_cached = true; 00947 } 00948 00949 ns_list_add_to_end(&interface_ptr->indirect_tx_queue, tx_ptr); 00950 00951 // Check if current message can be delivered to MAC or should some cached message be delivered first 00952 tx_ptr_cached = lowpan_adaptation_indirect_first_cached_request_get(interface_ptr, tx_ptr); 00953 if (tx_ptr->indirect_data_cached == false && tx_ptr_cached) { 00954 tr_debug_extra("sending cached seq: %d", tx_ptr_cached->buf->seq); 00955 // set current message to cache 00956 tx_ptr->indirect_data_cached = true; 00957 // swap entries 00958 tx_ptr = tx_ptr_cached; 00959 tx_ptr->indirect_data_cached = false; 00960 buf = tx_ptr_cached->buf ; 00961 } else if (tx_ptr->indirect_data_cached == true) { 00962 // There is mac data request ongoing and new req was sent to cache 00963 return 0; 00964 } 00965 } 00966 00967 lowpan_data_request_to_mac(cur, buf, tx_ptr, interface_ptr); 00968 return 0; 00969 00970 00971 tx_error_handler: 00972 socket_tx_buffer_event_and_free(buf, SOCKET_NO_RAM); 00973 return -1; 00974 00975 } 00976 00977 static bool lowpan_adaptation_tx_process_ready(fragmenter_tx_entry_t *tx_ptr) 00978 { 00979 if (!tx_ptr->fragmented_data) { 00980 if (tx_ptr->buf->ip_routed_up) { 00981 protocol_stats_update(STATS_IP_ROUTE_UP, buffer_data_length(tx_ptr->buf)); 00982 } else { 00983 protocol_stats_update(STATS_IP_TX_COUNT, buffer_data_length(tx_ptr->buf)); 00984 } 00985 return true; 00986 } 00987 00988 00989 00990 //Update data pointer by last packet length 00991 buffer_data_strip_header(tx_ptr->buf, tx_ptr->frag_len); 00992 //Update offset 00993 if (!tx_ptr->first_fragment) { 00994 tx_ptr->offset += tx_ptr->frag_len / 8; 00995 } else { 00996 tx_ptr->first_fragment = false; 00997 } 00998 00999 /* Check Is still Data what have to send */ 01000 tx_ptr->frag_len = buffer_data_length(tx_ptr->buf); 01001 01002 01003 if (tx_ptr->frag_len == 0) { 01004 //Release current data 01005 if (tx_ptr->buf->ip_routed_up) { 01006 protocol_stats_update(STATS_IP_ROUTE_UP, tx_ptr->orig_size); 01007 } else { 01008 protocol_stats_update(STATS_IP_TX_COUNT, tx_ptr->orig_size); 01009 } 01010 return true; 01011 } 01012 01013 //Continue Process 01014 01015 if (tx_ptr->unfrag_len + 5 + tx_ptr->frag_len > tx_ptr->frag_max) { 01016 tx_ptr->frag_len = tx_ptr->frag_max - 5 - tx_ptr->unfrag_len; 01017 tx_ptr->frag_len &= ~7; 01018 } 01019 01020 return false; 01021 } 01022 01023 static void lowpan_adaptation_data_process_clean(fragmenter_interface_t *interface_ptr, fragmenter_tx_entry_t *tx_ptr, uint8_t socket_event) 01024 { 01025 buffer_t *buf = tx_ptr->buf ; 01026 tx_ptr->buf = NULL; 01027 if (buf->link_specific.ieee802_15_4.indirectTxProcess) { 01028 //release from list and free entry 01029 lowpan_indirect_entry_free(&interface_ptr->indirect_tx_queue, tx_ptr); 01030 } 01031 01032 socket_tx_buffer_event_and_free(buf, socket_event); 01033 } 01034 01035 01036 int8_t lowpan_adaptation_interface_tx_confirm(protocol_interface_info_entry_t *cur, const mcps_data_conf_t *confirm) 01037 { 01038 if( !cur || !confirm ){ 01039 return -1; 01040 } 01041 01042 fragmenter_interface_t *interface_ptr = lowpan_adaptation_interface_discover(cur->id); 01043 if (!interface_ptr) { 01044 return -1; 01045 } 01046 01047 //Check first 01048 fragmenter_tx_entry_t *tx_ptr; 01049 bool active_direct_confirm; 01050 bool is_unicast = true; 01051 01052 if (lowpan_active_tx_handle_verify(confirm->msduHandle,interface_ptr->active_unicast_tx_buf.buf)) { 01053 active_direct_confirm = true; 01054 tx_ptr = &interface_ptr->active_unicast_tx_buf; 01055 } else if (lowpan_active_tx_handle_verify(confirm->msduHandle,interface_ptr->active_broadcast_tx_buf.buf)) { 01056 active_direct_confirm = true; 01057 tx_ptr = &interface_ptr->active_broadcast_tx_buf; 01058 is_unicast = false; 01059 } else { 01060 active_direct_confirm = false; 01061 tx_ptr = lowpan_indirect_tx_handle_verify(confirm->msduHandle, &interface_ptr->indirect_tx_queue); 01062 } 01063 01064 if (!tx_ptr) { 01065 tr_error("No data request for this confirmation %u", confirm->msduHandle); 01066 return -1; 01067 } 01068 01069 //Check status for 01070 buffer_t *buf = tx_ptr->buf ; 01071 01072 //Indirect data expiration 01073 if (confirm->status == MLME_TRANSACTION_EXPIRED && !active_direct_confirm) { 01074 if (buf->link_specific.ieee802_15_4.indirectTTL > 7000) 01075 { 01076 buf->link_specific.ieee802_15_4.indirectTTL -= 7000; 01077 //Push Back to MAC 01078 lowpan_data_request_to_mac(cur, buf, tx_ptr, interface_ptr); 01079 return 0; 01080 } 01081 } 01082 01083 if (interface_ptr->etx_update_cb) { 01084 interface_ptr->etx_update_cb(cur, buf, confirm); 01085 } 01086 01087 //Switch original channel back 01088 if (buf->link_specific.ieee802_15_4.rf_channel_switch) { 01089 mac_helper_mac_channel_set(cur, buf->link_specific.ieee802_15_4.selected_channel); 01090 buf->link_specific.ieee802_15_4.rf_channel_switch = false; 01091 } 01092 01093 switch (confirm->status) { 01094 01095 case MLME_BUSY_CHAN: 01096 lowpan_data_request_to_mac(cur, buf, tx_ptr, interface_ptr); 01097 break; 01098 case MLME_SUCCESS: 01099 01100 //Check is there more packets 01101 if (lowpan_adaptation_tx_process_ready(tx_ptr)) { 01102 bool triggered_from_indirect_cache = false; 01103 if (tx_ptr->fragmented_data && active_direct_confirm) { 01104 //Clean 01105 interface_ptr->fragmenter_active = false; 01106 } 01107 01108 if (tx_ptr->buf->link_specific.ieee802_15_4.indirectTxProcess) { 01109 triggered_from_indirect_cache = lowpan_adaptation_indirect_cache_trigger(cur, interface_ptr, tx_ptr); 01110 } 01111 01112 lowpan_adaptation_data_process_clean(interface_ptr, tx_ptr, map_mlme_status_to_socket_event(confirm->status)); 01113 01114 if (triggered_from_indirect_cache) { 01115 return 0; 01116 } 01117 } else { 01118 lowpan_data_request_to_mac(cur, buf, tx_ptr, interface_ptr); 01119 } 01120 01121 break; 01122 case MLME_TX_NO_ACK: 01123 case MLME_SECURITY_FAIL: 01124 case MLME_TRANSACTION_EXPIRED: 01125 default: 01126 tr_error("MCPS Data fail by status %u", confirm->status); 01127 if (buf->dst_sa .addr_type == ADDR_802_15_4_SHORT ) { 01128 tr_info("Dest addr: %x", common_read_16_bit(buf->dst_sa .address +2)); 01129 } else if (buf->dst_sa .addr_type == ADDR_802_15_4_LONG ) { 01130 tr_info("Dest addr: %s", trace_array(buf->dst_sa .address +2, 8)); 01131 } 01132 01133 #ifdef HAVE_RPL 01134 if (confirm->status == MLME_TX_NO_ACK) { 01135 if (buf->route && rpl_data_is_rpl_parent_route(buf->route->route_info.source)) { 01136 protocol_stats_update(STATS_RPL_PARENT_TX_FAIL, 1); 01137 } 01138 } 01139 #endif 01140 if (tx_ptr->fragmented_data) { 01141 tx_ptr->buf->buf_ptr = tx_ptr->buf->buf_end; 01142 tx_ptr->buf->buf_ptr -= tx_ptr->orig_size; 01143 if (active_direct_confirm) { 01144 interface_ptr->fragmenter_active = false; 01145 } 01146 } 01147 01148 lowpan_adaptation_data_process_clean(interface_ptr, tx_ptr, map_mlme_status_to_socket_event(confirm->status)); 01149 break; 01150 01151 } 01152 01153 if ((is_unicast && !interface_ptr->active_unicast_tx_buf.buf) || (!is_unicast && !interface_ptr->active_broadcast_tx_buf.buf)) { 01154 //Read Buffer and trig next direct request 01155 lowpan_adaptation_interface_tx(cur, lowpan_adaptation_tx_queue_read(interface_ptr, cur)); 01156 } 01157 01158 return 0; 01159 01160 } 01161 01162 static bool mac_data_is_broadcast_addr(const sockaddr_t *addr) 01163 { 01164 return (addr->addr_type == ADDR_802_15_4_SHORT ) && 01165 (addr->address [2] == 0xFF && addr->address [3] == 0xFF); 01166 } 01167 01168 static bool mcps_data_indication_neighbor_validate(protocol_interface_info_entry_t *cur, const sockaddr_t *addr) 01169 { 01170 if (thread_info(cur) || ws_info(cur) || (cur->lowpan_info & INTERFACE_NWK_BOOTSRAP_MLE)) { 01171 mac_neighbor_table_entry_t * neighbor = mac_neighbor_table_address_discover(mac_neighbor_info(cur), addr->address + 2, addr->addr_type ); 01172 if (neighbor && (neighbor->connected_device || neighbor->trusted_device )) { 01173 return true; 01174 } 01175 01176 /* Otherwise, we don't know them */ 01177 return false; 01178 } else { 01179 //6lowpan without MLE don't can't do validation 01180 return true; 01181 } 01182 01183 } 01184 01185 void lowpan_adaptation_interface_data_ind(protocol_interface_info_entry_t *cur, const mcps_data_ind_t *data_ind) 01186 { 01187 buffer_t *buf = buffer_get(data_ind->msduLength); 01188 if (!buf || !cur) { 01189 return; 01190 } 01191 uint8_t *ptr; 01192 buffer_data_add(buf, data_ind->msdu_ptr, data_ind->msduLength); 01193 //tr_debug("MAC Paylod size %u %s",data_ind->msduLength, trace_array(data_ind->msdu_ptr, 8)); 01194 buf->options .lqi = data_ind->mpduLinkQuality; 01195 buf->options .dbm = data_ind->signal_dbm; 01196 buf->src_sa .addr_type = (addrtype_t)data_ind->SrcAddrMode; 01197 ptr = common_write_16_bit(data_ind->SrcPANId, buf->src_sa .address ); 01198 memcpy(ptr, data_ind->SrcAddr, 8); 01199 buf->dst_sa .addr_type = (addrtype_t)data_ind->DstAddrMode; 01200 ptr = common_write_16_bit(data_ind->DstPANId, buf->dst_sa .address ); 01201 memcpy(ptr, data_ind->DstAddr, 8); 01202 //Set Link spesific stuff to seperately 01203 buf->link_specific.ieee802_15_4.srcPanId = data_ind->SrcPANId; 01204 buf->link_specific.ieee802_15_4.dstPanId = data_ind->DstPANId; 01205 01206 if (mac_data_is_broadcast_addr(&buf->dst_sa )) { 01207 buf->options .ll_broadcast_rx = true; 01208 } 01209 buf->interface = cur; 01210 if (data_ind->Key.SecurityLevel) { 01211 buf->link_specific.ieee802_15_4.fc_security = true; 01212 01213 if (cur->mac_security_key_usage_update_cb) { 01214 cur->mac_security_key_usage_update_cb(cur, &data_ind->Key); 01215 } 01216 } else { 01217 buf->link_specific.ieee802_15_4.fc_security = false; 01218 if (mac_helper_default_security_level_get(cur) || 01219 !mcps_data_indication_neighbor_validate(cur, &buf->src_sa )) { 01220 //SET By Pass 01221 buf->options .ll_security_bypass_rx = true; 01222 } 01223 } 01224 01225 buf->info = (buffer_info_t)(B_TO_IPV6_TXRX | B_FROM_MAC | B_DIR_UP); 01226 protocol_push(buf); 01227 } 01228 01229 static uint8_t map_mlme_status_to_socket_event(uint8_t mlme_status) 01230 { 01231 uint8_t socket_event; 01232 01233 switch (mlme_status) { 01234 case MLME_SUCCESS: 01235 socket_event = SOCKET_TX_DONE; 01236 break; 01237 case MLME_TX_NO_ACK: 01238 case MLME_SECURITY_FAIL: 01239 case MLME_TRANSACTION_EXPIRED: 01240 default: 01241 socket_event = SOCKET_TX_FAIL; 01242 break; 01243 } 01244 01245 return (socket_event); 01246 } 01247 01248 bool lowpan_adaptation_tx_active(int8_t interface_id) 01249 { 01250 fragmenter_interface_t *interface_ptr = lowpan_adaptation_interface_discover(interface_id); 01251 01252 if (!interface_ptr || (!interface_ptr->active_unicast_tx_buf.buf && !interface_ptr->active_broadcast_tx_buf.buf)) { 01253 return false; 01254 } 01255 return true; 01256 } 01257 01258 static bool lowpan_tx_buffer_address_compare(sockaddr_t *dst_sa, uint8_t *address_ptr, addrtype_t adr_type) 01259 { 01260 01261 if (dst_sa->addr_type != adr_type) { 01262 return false; 01263 } 01264 01265 uint8_t compare_length; 01266 switch (adr_type) { 01267 case ADDR_802_15_4_SHORT : 01268 compare_length = 2; 01269 break; 01270 case ADDR_802_15_4_LONG : 01271 compare_length = 8; 01272 break; 01273 default: 01274 return false; 01275 } 01276 01277 01278 if (memcmp(&dst_sa->address [2], address_ptr, compare_length)) { 01279 return false; 01280 } 01281 return true; 01282 } 01283 01284 static void lowpan_adaptation_purge_from_mac(struct protocol_interface_info_entry *cur, fragmenter_interface_t *interface_ptr, uint8_t msduhandle) 01285 { 01286 mcps_purge_t purge_req; 01287 purge_req.msduHandle = msduhandle; 01288 if (interface_ptr->mpx_api) { 01289 interface_ptr->mpx_api->mpx_data_purge(interface_ptr->mpx_api, &purge_req, interface_ptr->mpx_user_id); 01290 } else { 01291 if (cur->mac_api->mcps_purge_req) { 01292 cur->mac_api->mcps_purge_req(cur->mac_api, &purge_req); 01293 } 01294 } 01295 } 01296 01297 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) 01298 { 01299 tr_debug("Purge from indirect handle %u", tx_ptr->buf->seq); 01300 lowpan_adaptation_purge_from_mac(cur, interface_ptr, tx_ptr->buf->seq); 01301 lowpan_adaptation_data_process_clean(interface_ptr, tx_ptr, SOCKET_TX_FAIL); 01302 } 01303 01304 void lowpan_adaptation_remove_free_indirect_table(protocol_interface_info_entry_t *cur_interface, mac_neighbor_table_entry_t *entry_ptr) 01305 { 01306 //Free firts by defined short address 01307 if (entry_ptr->mac16 < 0xfffe) { 01308 uint8_t temp_address[2]; 01309 common_write_16_bit(entry_ptr->mac16 , temp_address); 01310 lowpan_adaptation_indirect_free_messages_from_queues_by_address(cur_interface, temp_address, ADDR_802_15_4_SHORT ); 01311 } 01312 lowpan_adaptation_indirect_free_messages_from_queues_by_address(cur_interface, entry_ptr->mac64 , ADDR_802_15_4_LONG ); 01313 } 01314 01315 01316 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) 01317 { 01318 fragmenter_interface_t *interface_ptr = lowpan_adaptation_interface_discover(cur->id); 01319 01320 if (!interface_ptr ) { 01321 return -1; 01322 } 01323 01324 //Check first indirect queue 01325 ns_list_foreach_safe(fragmenter_tx_entry_t, entry, &interface_ptr->indirect_tx_queue) { 01326 01327 if (lowpan_tx_buffer_address_compare(&entry->buf->dst_sa, address_ptr, adr_type)) { 01328 //Purge from mac 01329 lowpan_adaptation_indirect_queue_free_message(cur, interface_ptr, entry); 01330 } 01331 } 01332 01333 return 0; 01334 01335 } 01336 01337 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) 01338 { 01339 fragmenter_interface_t *interface_ptr = lowpan_adaptation_interface_discover(cur->id); 01340 01341 if (!interface_ptr) { 01342 return -1; 01343 } 01344 01345 interface_ptr->indirect_big_packet_threshold = indirect_big_packet_threshold; 01346 interface_ptr->max_indirect_big_packets_total = max_indirect_big_packets_total; 01347 interface_ptr->max_indirect_small_packets_per_child = max_indirect_small_packets_per_child; 01348 01349 return 0; 01350 }
Generated on Tue Aug 9 2022 00:37:00 by
1.7.2