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: TYBLE16_simple_data_logger TYBLE16_MP3_Air
ws_llc_data_service.c
00001 /* 00002 * Copyright (c) 2018-2019, 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 "ns_list.h" 00022 #include "ns_trace.h" 00023 #include "nsdynmemLIB.h" 00024 #include "mac_common_defines.h" 00025 #include "mac_api.h" 00026 #include "mac_mcps.h" 00027 #include "common_functions.h" 00028 #include "NWK_INTERFACE/Include/protocol.h" 00029 #include "6LoWPAN/MAC/mac_helper.h" 00030 #include "6LoWPAN/MAC/mpx_api.h" 00031 #include "6LoWPAN/MAC/mac_ie_lib.h" 00032 #include "6LoWPAN/ws/ws_common_defines.h" 00033 #include "6LoWPAN/ws/ws_common.h" 00034 #include "6LoWPAN/ws/ws_bootstrap.h" 00035 #include "6LoWPAN/ws/ws_ie_lib.h" 00036 #include "6LoWPAN/ws/ws_llc.h" 00037 #include "6LoWPAN/ws/ws_mpx_header.h" 00038 #include "6LoWPAN/ws/ws_pae_controller.h" 00039 #include "Security/PANA/pana_eap_header.h" 00040 #include "Security/eapol/eapol_helper.h" 00041 #include "Service_Libs/etx/etx.h" 00042 #include "fhss_ws_extension.h " 00043 00044 #ifdef HAVE_WS 00045 00046 #define TRACE_GROUP "wllc" 00047 00048 #define LLC_MESSAGE_QUEUE_LIST_SIZE_MAX 16 //Do not config over 30 never 00049 #define MPX_USER_SIZE 2 00050 00051 typedef struct { 00052 uint16_t user_id; /**< User ID for identify MPX User */ 00053 mpx_data_confirm *data_confirm; /**< User registred MPX Data confirmation call back */ 00054 mpx_data_indication *data_ind; /**< User registred MPX Data indication call back */ 00055 } mpx_user_t; 00056 00057 00058 typedef struct { 00059 mpx_api_t mpx_api; /**< API for MPX user like Stack and EAPOL */ 00060 mpx_user_t mpx_user_table[MPX_USER_SIZE]; /**< MPX user list include registered call back pointers and user id's */ 00061 unsigned mpx_id: 4; /**< MPX class sequence number */ 00062 } mpx_class_t; 00063 00064 00065 typedef struct { 00066 uint16_t supported_channels; /**< Configured Channel count. This will define Channel infor mask length to some information element */ 00067 uint16_t network_name_length; /**< Network name length */ 00068 uint16_t vendor_payload_length; /**< Vendor spesific payload length */ 00069 uint8_t vendor_header_length; /**< Vendor spesific header length */ 00070 uint8_t gtkhash_length; /**< GTK hash length */ 00071 ws_pan_information_t *pan_congiguration; /**< Pan configururation */ 00072 struct ws_hopping_schedule_s *hopping_schedule;/**< Channel hopping schedule */ 00073 uint8_t *gtkhash; /**< Pointer to GTK HASH user must give pointer which include 4 64-bit HASH array */ 00074 uint8_t *network_name; /**< Network name */ 00075 uint8_t *vendor_header_data; /**< Vendor spesific header data */ 00076 uint8_t *vendor_payload; /**< Vendor spesific payload data */ 00077 } llc_ie_params_t; 00078 00079 typedef struct { 00080 uint8_t dst_address[8]; /**< Destination address */ 00081 unsigned messsage_type: 3; /**< Frame type to UTT */ 00082 unsigned mpx_id: 5; /**< MPX sequence */ 00083 bool ack_requested: 1; /**< ACK requested */ 00084 unsigned dst_address_type: 2; /**< Destination address type */ 00085 uint8_t msg_handle; /**< LLC genetaed unique MAC handle */ 00086 uint8_t mpx_user_handle; /**< This MPX user defined handle */ 00087 ns_ie_iovec_t ie_vector_list[3]; /**< IE vectors: 1 for Header's, 1 for Payload and for MPX payload */ 00088 mcps_data_req_ie_list_t ie_ext; 00089 ns_list_link_t link; /**< List link entry */ 00090 uint8_t ie_buffer[]; /**< Trailing buffer data */ 00091 } llc_message_t; 00092 00093 /** get pointer to Mac header start point*/ 00094 #define ws_message_buffer_ptr_get(x) (&(x)->ie_buffer[0]) 00095 00096 typedef NS_LIST_HEAD (llc_message_t, link) llc_message_list_t; 00097 00098 #define MAX_NEIGH_TEMPORRY_MULTICAST_SIZE 5 00099 00100 typedef struct { 00101 ws_neighbor_temp_class_t neighbour_temporary_table[MAX_NEIGH_TEMPORRY_MULTICAST_SIZE]; 00102 ws_neighbor_temp_list_t active_temp_neigh; 00103 ws_neighbor_temp_list_t free_temp_neigh; 00104 } temp_entriest_t; 00105 00106 typedef struct { 00107 uint8_t mac_handle_base; /**< Mac handle id base this will be updated by 1 after use */ 00108 uint8_t llc_message_list_size; /**< llc_message_list list size */ 00109 mpx_class_t mpx_data_base; /**< MPX data be including USER API Class and user call backs */ 00110 llc_message_list_t llc_message_list; /**< Active Message list */ 00111 llc_ie_params_t ie_params; /**< LLC IE header and Payload data configuration */ 00112 temp_entriest_t *temp_entries; 00113 00114 ws_asynch_ind *asynch_ind; /**< LLC Asynch data indication call back configured by user */ 00115 ws_asynch_confirm *asynch_confirm; /**< LLC Asynch data confirmation call back configured by user */ 00116 ws_neighbor_info_request *ws_neighbor_info_request_cb; /**< LLC Neighbour discover API*/ 00117 uint8_t ws_enhanced_ack_elements[WH_IE_ELEMENT_HEADER_LENGTH + 4 + WH_IE_ELEMENT_HEADER_LENGTH + 1]; 00118 ns_ie_iovec_t ws_header_vector; 00119 protocol_interface_info_entry_t *interface_ptr; /**< List link entry */ 00120 00121 ns_list_link_t link; /**< List link entry */ 00122 } llc_data_base_t; 00123 00124 static NS_LIST_DEFINE(llc_data_base_list, llc_data_base_t, link); 00125 00126 static uint16_t ws_wp_nested_message_length(wp_nested_ie_sub_list_t requested_list, llc_ie_params_t *params); 00127 static uint16_t ws_wh_headers_length(wh_ie_sub_list_t requested_list, llc_ie_params_t *params); 00128 00129 /** LLC message local functions */ 00130 static llc_message_t *llc_message_discover_by_mac_handle(uint8_t handle, llc_message_list_t *list); 00131 static llc_message_t *llc_message_discover_by_mpx_id(uint8_t handle, llc_message_list_t *list); 00132 static llc_message_t *llc_message_discover_mpx_user_id(uint8_t handle, uint16_t user_id, llc_message_list_t *list); 00133 static void llc_message_free(llc_message_t *message, llc_data_base_t *llc_base); 00134 static llc_message_t *llc_message_allocate(uint16_t ie_buffer_size, llc_data_base_t *llc_base, bool mpx_user); 00135 00136 /** LLC interface sepesific local functions */ 00137 static llc_data_base_t *ws_llc_discover_by_interface(struct protocol_interface_info_entry *interface); 00138 static llc_data_base_t *ws_llc_discover_by_mac(const mac_api_t *api); 00139 static llc_data_base_t *ws_llc_discover_by_mpx(const mpx_api_t *api); 00140 00141 static mpx_user_t *ws_llc_mpx_user_discover(mpx_class_t *mpx_class, uint16_t user_id); 00142 static llc_data_base_t *ws_llc_base_allocate(void); 00143 static void ws_llc_mac_confirm_cb(const mac_api_t *api, const mcps_data_conf_t *data, const mcps_data_conf_payload_t *conf_data); 00144 static void ws_llc_mac_indication_cb(const mac_api_t *api, const mcps_data_ind_t *data, const mcps_data_ie_list_t *ie_ext); 00145 static uint16_t ws_mpx_header_size_get(llc_data_base_t *base, uint16_t user_id); 00146 static void ws_llc_mpx_data_request(const mpx_api_t *api, const struct mcps_data_req_s *data, uint16_t user_id); 00147 static int8_t ws_llc_mpx_data_cb_register(const mpx_api_t *api, mpx_data_confirm *confirm_cb, mpx_data_indication *indication_cb, uint16_t user_id); 00148 static uint16_t ws_llc_mpx_header_size_get(const mpx_api_t *api, uint16_t user_id); 00149 static uint8_t ws_llc_mpx_data_purge_request(const mpx_api_t *api, struct mcps_purge_s *purge, uint16_t user_id); 00150 static void ws_llc_mpx_init(mpx_class_t *mpx_class); 00151 00152 static void ws_llc_temp_neigh_info_table_reset(temp_entriest_t *base); 00153 static ws_neighbor_temp_class_t *ws_allocate_multicast_temp_entry(temp_entriest_t *base, const uint8_t *mac64); 00154 00155 /** Discover Message by message handle id */ 00156 static llc_message_t *llc_message_discover_by_mac_handle(uint8_t handle, llc_message_list_t *list) 00157 { 00158 ns_list_foreach(llc_message_t, message, list) { 00159 if (message->msg_handle == handle) { 00160 return message; 00161 } 00162 } 00163 return NULL; 00164 } 00165 00166 static llc_message_t *llc_message_discover_by_mpx_id(uint8_t handle, llc_message_list_t *list) 00167 { 00168 ns_list_foreach(llc_message_t, message, list) { 00169 if ((message->messsage_type == WS_FT_DATA || message->messsage_type == WS_FT_EAPOL) && message->mpx_id == handle) { 00170 return message; 00171 } 00172 } 00173 return NULL; 00174 } 00175 00176 00177 static llc_message_t *llc_message_discover_mpx_user_id(uint8_t handle, uint16_t user_id, llc_message_list_t *list) 00178 { 00179 uint8_t message_type; 00180 if (user_id == MPX_LOWPAN_ENC_USER_ID) { 00181 message_type = WS_FT_DATA; 00182 } else { 00183 message_type = WS_FT_EAPOL; 00184 } 00185 00186 ns_list_foreach(llc_message_t, message, list) { 00187 if (message->messsage_type == message_type && message->mpx_user_handle == handle) { 00188 return message; 00189 } 00190 } 00191 return NULL; 00192 } 00193 00194 00195 00196 00197 //Free message and delete from list 00198 static void llc_message_free(llc_message_t *message, llc_data_base_t *llc_base) 00199 { 00200 ns_list_remove(&llc_base->llc_message_list, message); 00201 ns_dyn_mem_free(message); 00202 llc_base->llc_message_list_size--; 00203 } 00204 00205 static llc_message_t *llc_message_allocate(uint16_t ie_buffer_size, llc_data_base_t *llc_base, bool mpx_user) 00206 { 00207 if (llc_base->llc_message_list_size >= LLC_MESSAGE_QUEUE_LIST_SIZE_MAX) { 00208 return NULL; 00209 } 00210 00211 llc_message_t *message = ns_dyn_mem_temporary_alloc(sizeof(llc_message_t) + ie_buffer_size); 00212 if (!message) { 00213 return NULL; 00214 } 00215 message->ack_requested = false; 00216 00217 //Guarantee 00218 while (1) { 00219 if (llc_message_discover_by_mac_handle(llc_base->mac_handle_base, &llc_base->llc_message_list)) { 00220 llc_base->mac_handle_base++; 00221 } else { 00222 break; 00223 } 00224 } 00225 if (mpx_user) { 00226 while (1) { 00227 if (llc_message_discover_by_mpx_id(llc_base->mpx_data_base.mpx_id, &llc_base->llc_message_list)) { 00228 llc_base->mpx_data_base.mpx_id++; 00229 } else { 00230 break; 00231 } 00232 } 00233 } 00234 00235 //Storage handle and update base 00236 message->msg_handle = llc_base->mac_handle_base++; 00237 if (mpx_user) { 00238 message->mpx_id = llc_base->mpx_data_base.mpx_id++; 00239 } 00240 llc_base->llc_message_list_size++; 00241 ns_list_add_to_end(&llc_base->llc_message_list, message); 00242 return message; 00243 } 00244 00245 static llc_data_base_t *ws_llc_discover_by_interface(struct protocol_interface_info_entry *interface) 00246 { 00247 ns_list_foreach(llc_data_base_t, base, &llc_data_base_list) { 00248 if (base->interface_ptr == interface) { 00249 return base; 00250 } 00251 } 00252 return NULL; 00253 } 00254 00255 static llc_data_base_t *ws_llc_discover_by_mac(const mac_api_t *api) 00256 { 00257 ns_list_foreach(llc_data_base_t, base, &llc_data_base_list) { 00258 if (base->interface_ptr->mac_api == api) { 00259 return base; 00260 } 00261 } 00262 return NULL; 00263 } 00264 00265 static llc_data_base_t *ws_llc_discover_by_mpx(const mpx_api_t *api) 00266 { 00267 ns_list_foreach(llc_data_base_t, base, &llc_data_base_list) { 00268 if (&base->mpx_data_base.mpx_api == api) { 00269 return base; 00270 } 00271 } 00272 return NULL; 00273 } 00274 00275 static uint16_t ws_wh_headers_length(wh_ie_sub_list_t requested_list, llc_ie_params_t *params) 00276 { 00277 uint16_t length = 0; 00278 if (requested_list.utt_ie) { 00279 //Static 4 bytes allways UTT 00280 length += WH_IE_ELEMENT_HEADER_LENGTH + 4; 00281 } 00282 00283 if (requested_list.bt_ie) { 00284 //Static 5 bytes allways 00285 length += WH_IE_ELEMENT_HEADER_LENGTH + 5; 00286 } 00287 00288 if (requested_list.fc_ie) { 00289 //Static 1 bytes allways 00290 length += WH_IE_ELEMENT_HEADER_LENGTH + 1; 00291 } 00292 00293 if (requested_list.rsl_ie) { 00294 //Static 1 bytes allways 00295 length += WH_IE_ELEMENT_HEADER_LENGTH + 1; 00296 } 00297 00298 if (requested_list.vh_ie) { 00299 //Dynamic length 00300 length += WH_IE_ELEMENT_HEADER_LENGTH + params->vendor_header_length; 00301 } 00302 00303 if (requested_list.ea_ie) { 00304 length += WH_IE_ELEMENT_HEADER_LENGTH + 8; 00305 } 00306 00307 return length; 00308 } 00309 00310 static uint16_t ws_wp_nested_message_length(wp_nested_ie_sub_list_t requested_list, llc_ie_params_t *params) 00311 { 00312 uint16_t length = 0; 00313 if (requested_list.gtkhash_ie) { 00314 //Static 32 bytes allways 00315 length += WS_WP_SUB_IE_ELEMENT_HEADER_LENGTH + params->gtkhash_length; 00316 } 00317 00318 if (requested_list.net_name_ie) { 00319 //Dynamic length 00320 length += WS_WP_SUB_IE_ELEMENT_HEADER_LENGTH + params->network_name_length; 00321 } 00322 00323 if (requested_list.vp_ie && params->vendor_payload_length) { 00324 //Dynamic length 00325 length += WS_WP_SUB_IE_ELEMENT_HEADER_LENGTH + params->vendor_payload_length; 00326 } 00327 00328 if (requested_list.pan_ie) { 00329 //Static 5 bytes allways 00330 length += WS_WP_SUB_IE_ELEMENT_HEADER_LENGTH; 00331 if (params->pan_congiguration) { 00332 length += 5; 00333 } 00334 } 00335 00336 if (requested_list.pan_version_ie) { 00337 //Static 2 bytes allways 00338 length += WS_WP_SUB_IE_ELEMENT_HEADER_LENGTH; 00339 if (params->pan_congiguration) { 00340 length += 2; 00341 } 00342 } 00343 00344 if (requested_list.bs_ie) { 00345 ///Dynamic length 00346 length += WS_WP_SUB_IE_ELEMENT_HEADER_LENGTH + ws_wp_nested_hopping_schedule_length(params->hopping_schedule, false); 00347 } 00348 00349 if (requested_list.us_ie) { 00350 //Dynamic length 00351 length += WS_WP_SUB_IE_ELEMENT_HEADER_LENGTH + ws_wp_nested_hopping_schedule_length(params->hopping_schedule, true); 00352 } 00353 00354 return length; 00355 } 00356 00357 static mpx_user_t *ws_llc_mpx_user_discover(mpx_class_t *mpx_class, uint16_t user_id) 00358 { 00359 for (int i = 0; i < MPX_USER_SIZE; i++) { 00360 if (mpx_class->mpx_user_table[i].user_id == user_id) { 00361 return &mpx_class->mpx_user_table[i]; 00362 } 00363 } 00364 return NULL; 00365 } 00366 00367 static llc_data_base_t *ws_llc_base_allocate(void) 00368 { 00369 llc_data_base_t *base = ns_dyn_mem_alloc(sizeof(llc_data_base_t)); 00370 temp_entriest_t *temp_entries = ns_dyn_mem_alloc(sizeof(temp_entriest_t)); 00371 if (!base || !temp_entries) { 00372 ns_dyn_mem_free(base); 00373 ns_dyn_mem_free(temp_entries); 00374 return NULL; 00375 } 00376 memset(base, 0, sizeof(llc_data_base_t)); 00377 memset(temp_entries, 0, sizeof(temp_entriest_t)); 00378 ns_list_init(&temp_entries->active_temp_neigh); 00379 ns_list_init(&temp_entries->free_temp_neigh); 00380 00381 base->temp_entries = temp_entries; 00382 00383 ns_list_init(&base->llc_message_list); 00384 ns_list_add_to_end(&llc_data_base_list, base); 00385 return base; 00386 } 00387 00388 /** WS LLC MAC data extension confirmation */ 00389 static void ws_llc_mac_confirm_cb(const mac_api_t *api, const mcps_data_conf_t *data, const mcps_data_conf_payload_t *conf_data) 00390 { 00391 (void) conf_data; 00392 llc_data_base_t *base = ws_llc_discover_by_mac(api); 00393 if (!base) { 00394 return; 00395 } 00396 00397 protocol_interface_info_entry_t *interface = base->interface_ptr; 00398 00399 llc_message_t *message = llc_message_discover_by_mac_handle(data->msduHandle, &base->llc_message_list); 00400 if (!message) { 00401 return; 00402 } 00403 00404 uint8_t messsage_type = message->messsage_type; 00405 uint8_t mpx_user_handle = message->mpx_user_handle; 00406 //ETX update 00407 if (message->ack_requested && messsage_type == WS_FT_DATA) { 00408 llc_neighbour_req_t neighbor_info; 00409 bool success = false; 00410 00411 switch (data->status) { 00412 case MLME_SUCCESS: 00413 case MLME_TX_NO_ACK: 00414 case MLME_NO_DATA: 00415 if (data->status == MLME_SUCCESS || data->status == MLME_NO_DATA) { 00416 success = true; 00417 } 00418 00419 if (message->dst_address_type == MAC_ADDR_MODE_64_BIT && base->ws_neighbor_info_request_cb(interface, message->dst_address, &neighbor_info, false)) { 00420 etx_transm_attempts_update(interface->id, 1 + data->tx_retries, success, neighbor_info.neighbor->index ); 00421 //TODO discover RSL from Enchanced ACK Header IE elements 00422 ws_utt_ie_t ws_utt; 00423 if (ws_wh_utt_read(conf_data->headerIeList, conf_data->headerIeListLength, &ws_utt)) { 00424 //UTT header 00425 if (success) { 00426 neighbor_info.neighbor->lifetime = neighbor_info.neighbor->link_lifetime ; 00427 } 00428 00429 ws_neighbor_class_neighbor_unicast_time_info_update(neighbor_info.ws_neighbor, &ws_utt, data->timestamp); 00430 } 00431 00432 int8_t rsl; 00433 if (ws_wh_rsl_read(conf_data->headerIeList, conf_data->headerIeListLength, &rsl)) { 00434 ws_neighbor_class_rsl_out_calculate(neighbor_info.ws_neighbor, rsl); 00435 } 00436 } 00437 00438 break; 00439 default: 00440 break; 00441 } 00442 } 00443 //Free message 00444 llc_message_free(message, base); 00445 00446 if (messsage_type == WS_FT_DATA || messsage_type == WS_FT_EAPOL) { 00447 mpx_user_t *user_cb; 00448 uint16_t mpx_user_id; 00449 if (messsage_type == WS_FT_DATA) { 00450 mpx_user_id = MPX_LOWPAN_ENC_USER_ID; 00451 } else { 00452 mpx_user_id = MPX_KEY_MANAGEMENT_ENC_USER_ID; 00453 } 00454 00455 user_cb = ws_llc_mpx_user_discover(&base->mpx_data_base, mpx_user_id); 00456 if (user_cb && user_cb->data_confirm) { 00457 //Call MPX registered call back 00458 mcps_data_conf_t data_conf = *data; 00459 data_conf.msduHandle = mpx_user_handle; 00460 user_cb->data_confirm(&base->mpx_data_base.mpx_api, &data_conf); 00461 } 00462 return; 00463 } 00464 //Async message Confirmation 00465 base->asynch_confirm(base->interface_ptr, messsage_type); 00466 00467 } 00468 00469 static void ws_llc_ack_data_req_ext(const mac_api_t *api, mcps_ack_data_payload_t *data, int8_t rssi, uint8_t lqi) 00470 { 00471 (void) lqi; 00472 llc_data_base_t *base = ws_llc_discover_by_mac(api); 00473 if (!base) { 00474 return; 00475 } 00476 /* Init all by zero */ 00477 memset(data, 0, sizeof(mcps_ack_data_payload_t)); 00478 //Add just 2 header elements to inside 1 block 00479 data->ie_elements.headerIeVectorList = &base->ws_header_vector; 00480 base->ws_header_vector.ieBase = base->ws_enhanced_ack_elements; 00481 base->ws_header_vector.iovLen = sizeof(base->ws_enhanced_ack_elements); 00482 data->ie_elements.headerIovLength = 1; 00483 00484 //Write Data to block 00485 uint8_t *ptr = base->ws_enhanced_ack_elements; 00486 ptr = ws_wh_utt_write(ptr, WS_FT_ACK); 00487 ws_wh_rsl_write(ptr, ws_neighbor_class_rsl_from_dbm_calculate(rssi)); 00488 } 00489 00490 /** WS LLC MAC data extension indication */ 00491 static void ws_llc_mac_indication_cb(const mac_api_t *api, const mcps_data_ind_t *data, const mcps_data_ie_list_t *ie_ext) 00492 { 00493 llc_data_base_t *base = ws_llc_discover_by_mac(api); 00494 if (!base) { 00495 return; 00496 } 00497 00498 //Discover Header WH_IE_UTT_TYPE 00499 ws_utt_ie_t ws_utt; 00500 if (!ws_wh_utt_read(ie_ext->headerIeList, ie_ext->headerIeListLength, &ws_utt)) { 00501 // NO UTT header 00502 return; 00503 } 00504 00505 protocol_interface_info_entry_t *interface = base->interface_ptr; 00506 if (!base->ie_params.gtkhash && ws_utt.message_type == WS_FT_DATA) { 00507 return; 00508 } 00509 00510 //Discover 2 Payload Heder 00511 if (ws_utt.message_type == WS_FT_DATA || ws_utt.message_type == WS_FT_EAPOL) { 00512 00513 if (data->SrcAddrMode != ADDR_802_15_4_LONG ) { 00514 return; 00515 } 00516 00517 if (interface->mac_parameters->pan_id != 0xffff && data->SrcPANId != interface->mac_parameters->pan_id) { 00518 //Drop wrong PAN-id messages in this phase. 00519 return; 00520 } 00521 00522 mpx_user_t *user_cb; 00523 mac_payload_IE_t mpx_ie; 00524 mpx_ie.id = MAC_PAYLOAD_MPX_IE_GROUP_ID; 00525 if (mac_ie_payload_discover(ie_ext->payloadIeList, ie_ext->payloadIeListLength, &mpx_ie) < 1) { 00526 // NO MPX 00527 return; 00528 } 00529 //Validate MPX header 00530 mpx_msg_t mpx_frame; 00531 if (!ws_llc_mpx_header_frame_parse(mpx_ie.content_ptr, mpx_ie.length, &mpx_frame)) { 00532 return; 00533 } 00534 00535 if (mpx_frame.transfer_type != MPX_FT_FULL_FRAME) { 00536 return; //Support only FULL Frame's 00537 } 00538 00539 mac_payload_IE_t ws_wp_nested; 00540 ws_us_ie_t us_ie; 00541 bool us_ie_inline = false; 00542 bool bs_ie_inline = false; 00543 ws_wp_nested.id = WS_WP_NESTED_IE; 00544 ws_bs_ie_t ws_bs_ie; 00545 if (mac_ie_payload_discover(ie_ext->payloadIeList, ie_ext->payloadIeListLength, &ws_wp_nested) > 2) { 00546 us_ie_inline = ws_wp_nested_us_read(ws_wp_nested.content_ptr, ws_wp_nested.length, &us_ie); 00547 bs_ie_inline = ws_wp_nested_bs_read(ws_wp_nested.content_ptr, ws_wp_nested.length, &ws_bs_ie); 00548 } 00549 00550 llc_neighbour_req_t neighbor_info; 00551 bool multicast; 00552 bool request_new_entry; 00553 if (data->DstAddrMode == ADDR_802_15_4_LONG ) { 00554 multicast = false; 00555 request_new_entry = us_ie_inline; 00556 } else { 00557 multicast = true; 00558 request_new_entry = false; 00559 } 00560 00561 if (!base->ws_neighbor_info_request_cb(interface, data->SrcAddr, &neighbor_info, request_new_entry)) { 00562 if (!multicast || ws_utt.message_type == WS_FT_EAPOL) { 00563 tr_debug("Drop message no neighbor"); 00564 return; 00565 } else { 00566 //Allocate temporary entry 00567 ws_neighbor_temp_class_t *temp_entry = ws_allocate_multicast_temp_entry(base->temp_entries, data->SrcAddr); 00568 neighbor_info.ws_neighbor = &temp_entry->neigh_info_list ; 00569 //Storage Signal info for future ETX update possibility 00570 temp_entry->mpduLinkQuality = data->mpduLinkQuality; 00571 temp_entry->signal_dbm = data->signal_dbm; 00572 } 00573 } 00574 00575 ws_neighbor_class_neighbor_unicast_time_info_update(neighbor_info.ws_neighbor, &ws_utt, data->timestamp); 00576 if (us_ie_inline) { 00577 ws_neighbor_class_neighbor_unicast_schedule_set(neighbor_info.ws_neighbor, &us_ie); 00578 } 00579 //Update BS if it is part of message 00580 if (bs_ie_inline) { 00581 ws_neighbor_class_neighbor_broadcast_schedule_set(neighbor_info.ws_neighbor, &ws_bs_ie); 00582 } 00583 00584 if (ws_utt.message_type == WS_FT_EAPOL) { 00585 uint8_t auth_eui64[8]; 00586 //Discover and write Auhtenticator EUI-64 00587 if (ws_wh_ea_read(ie_ext->headerIeList, ie_ext->headerIeListLength, auth_eui64)) { 00588 ws_pae_controller_border_router_addr_write(base->interface_ptr, auth_eui64); 00589 } 00590 } 00591 00592 00593 //Update BT if it is part of message 00594 ws_bt_ie_t ws_bt; 00595 if (ws_wh_bt_read(ie_ext->headerIeList, ie_ext->headerIeListLength, &ws_bt)) { 00596 ws_neighbor_class_neighbor_broadcast_time_info_update(neighbor_info.ws_neighbor, &ws_bt, data->timestamp); 00597 if (neighbor_info.neighbor) { 00598 if (neighbor_info.neighbor->link_role == PRIORITY_PARENT_NEIGHBOUR) { 00599 // We have broadcast schedule set up set the broadcast parent schedule 00600 ns_fhss_ws_set_parent(interface->ws_info->fhss_api, neighbor_info.neighbor->mac64 , &neighbor_info.ws_neighbor->fhss_data.bc_timing_info, false); 00601 } else if (ws_utt.message_type == WS_FT_EAPOL) { 00602 ws_bootstrap_eapol_parent_synch(interface, &neighbor_info); 00603 } 00604 } 00605 } 00606 00607 if (ws_utt.message_type == WS_FT_DATA) { 00608 00609 if (data->DstAddrMode == ADDR_802_15_4_LONG ) { 00610 neighbor_info.ws_neighbor->unicast_data_rx = true; 00611 } 00612 00613 // Calculate RSL for all UDATA packages heard 00614 ws_neighbor_class_rsl_in_calculate(neighbor_info.ws_neighbor, data->signal_dbm); 00615 00616 if (neighbor_info.neighbor) { 00617 //Refresh ETX dbm 00618 etx_lqi_dbm_update(interface->id, data->mpduLinkQuality, data->signal_dbm, neighbor_info.neighbor->index ); 00619 if (data->Key.SecurityLevel) { 00620 //SET trusted state 00621 mac_neighbor_table_trusted_neighbor(mac_neighbor_info(interface), neighbor_info.neighbor, true); 00622 } 00623 } 00624 } 00625 00626 00627 // Discover MPX 00628 user_cb = ws_llc_mpx_user_discover(&base->mpx_data_base, mpx_frame.multiplex_id); 00629 if (user_cb && user_cb->data_ind) { 00630 mcps_data_ind_t data_ind = *data; 00631 if (!neighbor_info.neighbor) { 00632 data_ind.Key.SecurityLevel = 0; //Mark unknow device 00633 } 00634 data_ind.msdu_ptr = mpx_frame.frame_ptr; 00635 data_ind.msduLength = mpx_frame.frame_length; 00636 user_cb->data_ind(&base->mpx_data_base.mpx_api, &data_ind); 00637 } 00638 return; 00639 } 00640 00641 //Asynch Message 00642 if (ws_utt.message_type < WS_FT_DATA && base->asynch_ind) { 00643 mac_payload_IE_t ws_wp_nested; 00644 00645 ws_wp_nested.id = WS_WP_NESTED_IE; 00646 if (mac_ie_payload_discover(ie_ext->payloadIeList, ie_ext->payloadIeListLength, &ws_wp_nested) < 2) { 00647 // NO WS_WP_NESTED_IE Payload 00648 return; 00649 } 00650 00651 mcps_data_ie_list_t asynch_ie_list; 00652 asynch_ie_list.headerIeList = ie_ext->headerIeList, 00653 asynch_ie_list.headerIeListLength = ie_ext->headerIeListLength; 00654 asynch_ie_list.payloadIeList = ws_wp_nested.content_ptr; 00655 asynch_ie_list.payloadIeListLength = ws_wp_nested.length; 00656 base->asynch_ind(interface, data, &asynch_ie_list, ws_utt.message_type); 00657 } 00658 00659 } 00660 00661 static uint16_t ws_mpx_header_size_get(llc_data_base_t *base, uint16_t user_id) 00662 { 00663 //TODO add WS_WP_NESTED_IE support 00664 uint16_t header_size = 0; 00665 if (user_id == MPX_LOWPAN_ENC_USER_ID) { 00666 header_size += 7 + 8 + 5 + 2; //UTT+BTT+ MPX + Padding 00667 if (base->ie_params.vendor_header_length) { 00668 header_size += base->ie_params.vendor_header_length + 3; 00669 } 00670 00671 if (base->ie_params.vendor_payload_length) { 00672 header_size += base->ie_params.vendor_payload_length + 2; 00673 } 00674 00675 //Dynamic length 00676 header_size += 2 + WS_WP_SUB_IE_ELEMENT_HEADER_LENGTH + ws_wp_nested_hopping_schedule_length(base->ie_params.hopping_schedule, true) + ws_wp_nested_hopping_schedule_length(base->ie_params.hopping_schedule, false); 00677 00678 } else if (MPX_KEY_MANAGEMENT_ENC_USER_ID) { 00679 header_size += 7 + 5 + 2; 00680 //Dynamic length 00681 header_size += 2 + WS_WP_SUB_IE_ELEMENT_HEADER_LENGTH + ws_wp_nested_hopping_schedule_length(base->ie_params.hopping_schedule, true); 00682 } 00683 return header_size; 00684 } 00685 00686 static bool ws_eapol_handshake_first_msg(uint8_t *pdu, uint16_t length, protocol_interface_info_entry_t *cur) 00687 { 00688 if (!ws_eapol_relay_state_active(cur)) { 00689 return false; 00690 } 00691 00692 eapol_pdu_t eapol_pdu; 00693 uint8_t kmp_type = *pdu++; 00694 length--; 00695 if (!eapol_parse_pdu_header(pdu, length, &eapol_pdu)) { 00696 return false; 00697 } 00698 if (eapol_pdu.packet_type == EAPOL_EAP_TYPE) { 00699 if (eapol_pdu.msg.eap.eap_code == EAP_REQ && eapol_pdu.msg.eap.type == EAP_IDENTITY) { 00700 return true; 00701 } 00702 } else { 00703 00704 uint8_t key_mask = eapol_pdu_key_mask_get(&eapol_pdu); 00705 if (kmp_type == 6 && key_mask == KEY_INFO_KEY_ACK) { 00706 //FWK first message validation 00707 return true; 00708 } else if (kmp_type == 7 && key_mask == (KEY_INFO_KEY_ACK | KEY_INFO_KEY_MIC | KEY_INFO_SECURED_KEY_FRAME)) { 00709 //GWK first message validation 00710 return true; 00711 } 00712 } 00713 00714 return false; 00715 } 00716 00717 static void ws_llc_mpx_data_request(const mpx_api_t *api, const struct mcps_data_req_s *data, uint16_t user_id) 00718 { 00719 llc_data_base_t *base = ws_llc_discover_by_mpx(api); 00720 if (!base) { 00721 return; 00722 } 00723 00724 mpx_user_t *user_cb = ws_llc_mpx_user_discover(&base->mpx_data_base, user_id); 00725 if (!user_cb || !user_cb->data_confirm || !user_cb->data_ind) { 00726 return; 00727 } 00728 00729 wh_ie_sub_list_t ie_header_mask; 00730 memset(&ie_header_mask, 0, sizeof(wh_ie_sub_list_t)); 00731 00732 wp_nested_ie_sub_list_t nested_wp_id; 00733 memset(&nested_wp_id, 0, sizeof(wp_nested_ie_sub_list_t)); 00734 ie_header_mask.utt_ie = true; 00735 00736 if (user_id == MPX_LOWPAN_ENC_USER_ID) { 00737 ie_header_mask.bt_ie = true; 00738 if (base->ie_params.vendor_header_length) { 00739 ie_header_mask.vh_ie = true; 00740 } 00741 00742 if (base->ie_params.vendor_payload_length) { 00743 nested_wp_id.vp_ie = true; 00744 } 00745 00746 if (!data->TxAckReq) { 00747 nested_wp_id.bs_ie = true; 00748 } 00749 00750 } else if (user_id == MPX_KEY_MANAGEMENT_ENC_USER_ID) { 00751 ie_header_mask.bt_ie = ws_eapol_relay_state_active(base->interface_ptr); 00752 ie_header_mask.ea_ie = ws_eapol_handshake_first_msg(data->msdu, data->msduLength, base->interface_ptr); 00753 nested_wp_id.bs_ie = ie_header_mask.ea_ie; 00754 00755 } 00756 00757 nested_wp_id.us_ie = true; 00758 00759 uint16_t ie_header_length = ws_wh_headers_length(ie_header_mask, &base->ie_params); 00760 uint16_t nested_ie_length = ws_wp_nested_message_length(nested_wp_id, &base->ie_params); 00761 00762 uint16_t over_head_size = ie_header_length; 00763 if (nested_ie_length) { 00764 over_head_size += nested_ie_length + 2; 00765 } 00766 //Mpx header size 00767 over_head_size += 5; //MPX FuLL frame 3 bytes + IE header 2 bytes 00768 00769 //Allocate Message 00770 llc_message_t *message = llc_message_allocate(over_head_size, base, true); 00771 if (!message) { 00772 mcps_data_conf_t data_conf; 00773 memset(&data_conf, 0, sizeof(mcps_data_conf_t)); 00774 data_conf.msduHandle = data->msduHandle; 00775 data_conf.status = MLME_TRANSACTION_OVERFLOW; 00776 user_cb->data_confirm(&base->mpx_data_base.mpx_api, &data_conf); 00777 return; 00778 } 00779 mcps_data_req_t data_req; 00780 message->mpx_user_handle = data->msduHandle; 00781 message->ack_requested = data->TxAckReq; 00782 if (data->TxAckReq) { 00783 message->dst_address_type = data->DstAddrMode; 00784 memcpy(message->dst_address, data->DstAddr, 8); 00785 } 00786 data_req = *data; 00787 data_req.msdu = NULL; 00788 data_req.msduLength = 0; 00789 data_req.msduHandle = message->msg_handle; 00790 00791 if (!data->TxAckReq) { 00792 data_req.PanIdSuppressed = false; 00793 data_req.DstAddrMode = MAC_ADDR_MODE_NONE; 00794 } else { 00795 data_req.PanIdSuppressed = true; 00796 } 00797 00798 uint8_t *ptr = ws_message_buffer_ptr_get(message); 00799 if (user_id == MPX_LOWPAN_ENC_USER_ID) { 00800 message->messsage_type = WS_FT_DATA; 00801 } else { 00802 message->messsage_type = WS_FT_EAPOL; 00803 } 00804 00805 message->ie_vector_list[0].ieBase = ptr; 00806 //Write UTT 00807 00808 ptr = ws_wh_utt_write(ptr, message->messsage_type); 00809 if (ie_header_mask.bt_ie) { 00810 ptr = ws_wh_bt_write(ptr); 00811 } 00812 00813 if (user_id == MPX_LOWPAN_ENC_USER_ID) { 00814 if (ie_header_mask.vh_ie) { 00815 ptr = ws_wh_vh_write(ptr, base->ie_params.vendor_header_data, base->ie_params.vendor_header_length); 00816 } 00817 } else if (user_id == MPX_KEY_MANAGEMENT_ENC_USER_ID) { 00818 if (ie_header_mask.ea_ie) { 00819 uint8_t eapol_auth_eui64[8]; 00820 ws_pae_controller_border_router_addr_read(base->interface_ptr, eapol_auth_eui64); 00821 ptr = ws_wh_ea_write(ptr, eapol_auth_eui64); 00822 } 00823 } 00824 00825 00826 00827 message->ie_vector_list[0].iovLen = ie_header_length; 00828 message->ie_ext.headerIeVectorList = &message->ie_vector_list[0]; 00829 message->ie_ext.headerIovLength = 1; 00830 message->ie_ext.payloadIeVectorList = &message->ie_vector_list[1]; 00831 message->ie_ext.payloadIovLength = 2; 00832 message->ie_vector_list[1].ieBase = ptr; 00833 00834 if (nested_ie_length) { 00835 ptr = ws_wp_base_write(ptr, nested_ie_length); 00836 //Write unicast schedule 00837 ptr = ws_wp_nested_hopping_schedule_write(ptr, base->ie_params.hopping_schedule, true); 00838 00839 if (nested_wp_id.bs_ie) { 00840 //Write Broadcastcast schedule 00841 ptr = ws_wp_nested_hopping_schedule_write(ptr, base->ie_params.hopping_schedule, false); 00842 } 00843 } 00844 00845 00846 ptr = mac_ie_payload_base_write(ptr, MAC_PAYLOAD_MPX_IE_GROUP_ID, data->msduLength + 3); 00847 mpx_msg_t mpx_header; 00848 mpx_header.transfer_type = MPX_FT_FULL_FRAME; 00849 mpx_header.transaction_id = message->mpx_id; 00850 mpx_header.multiplex_id = user_id; 00851 ptr = ws_llc_mpx_header_write(ptr, &mpx_header); 00852 message->ie_vector_list[1].iovLen = ptr - (uint8_t *)message->ie_vector_list[1].ieBase; 00853 message->ie_vector_list[2].ieBase = data->msdu; 00854 message->ie_vector_list[2].iovLen = data->msduLength; 00855 base->interface_ptr->mac_api->mcps_data_req_ext(base->interface_ptr->mac_api, &data_req, &message->ie_ext, NULL); 00856 00857 } 00858 00859 00860 static int8_t ws_llc_mpx_data_cb_register(const mpx_api_t *api, mpx_data_confirm *confirm_cb, mpx_data_indication *indication_cb, uint16_t user_id) 00861 { 00862 llc_data_base_t *base = ws_llc_discover_by_mpx(api); 00863 if (!base) { 00864 return -1; 00865 } 00866 00867 mpx_user_t *user_cb = ws_llc_mpx_user_discover(&base->mpx_data_base, user_id); 00868 if (!user_cb) { 00869 return -1; 00870 } 00871 user_cb->data_confirm = confirm_cb; 00872 user_cb->data_ind = indication_cb; 00873 return 0; 00874 } 00875 00876 static uint16_t ws_llc_mpx_header_size_get(const mpx_api_t *api, uint16_t user_id) 00877 { 00878 llc_data_base_t *base = ws_llc_discover_by_mpx(api); 00879 if (!base) { 00880 return 0; 00881 } 00882 00883 return ws_mpx_header_size_get(base, user_id); 00884 } 00885 00886 static uint8_t ws_llc_mpx_data_purge_request(const mpx_api_t *api, struct mcps_purge_s *purge, uint16_t user_id) 00887 { 00888 llc_data_base_t *base = ws_llc_discover_by_mpx(api); 00889 if (!base) { 00890 return MLME_INVALID_HANDLE; 00891 } 00892 llc_message_t *message = llc_message_discover_mpx_user_id(purge->msduHandle, user_id, &base->llc_message_list); 00893 if (!message) { 00894 return MLME_INVALID_HANDLE; 00895 } 00896 00897 mcps_purge_t purge_req; 00898 uint8_t purge_status; 00899 purge_req.msduHandle = message->msg_handle; 00900 purge_status = base->interface_ptr->mac_api->mcps_purge_req(base->interface_ptr->mac_api, &purge_req); 00901 if (purge_status == 0) { 00902 llc_message_free(message, base); 00903 } 00904 00905 return purge_status; 00906 } 00907 00908 static void ws_llc_mpx_init(mpx_class_t *mpx_class) 00909 { 00910 //Init Mbed Class and API 00911 mpx_class->mpx_user_table[0].user_id = MPX_LOWPAN_ENC_USER_ID; 00912 mpx_class->mpx_user_table[1].user_id = MPX_KEY_MANAGEMENT_ENC_USER_ID; 00913 mpx_class->mpx_api.mpx_headroom_size_get = &ws_llc_mpx_header_size_get; 00914 mpx_class->mpx_api.mpx_user_registration = &ws_llc_mpx_data_cb_register; 00915 mpx_class->mpx_api.mpx_data_request = &ws_llc_mpx_data_request; 00916 mpx_class->mpx_api.mpx_data_purge = &ws_llc_mpx_data_purge_request; 00917 } 00918 00919 static void ws_llc_clean(llc_data_base_t *base) 00920 { 00921 //Clean Message queue's 00922 mcps_purge_t purge_req; 00923 ns_list_foreach_safe(llc_message_t, message, &base->llc_message_list) { 00924 purge_req.msduHandle = message->msg_handle; 00925 llc_message_free(message, base); 00926 base->interface_ptr->mac_api->mcps_purge_req(base->interface_ptr->mac_api, &purge_req); 00927 00928 } 00929 memset(&base->ie_params, 0, sizeof(llc_ie_params_t)); 00930 00931 ws_llc_temp_neigh_info_table_reset(base->temp_entries); 00932 } 00933 00934 static void ws_llc_temp_neigh_info_table_reset(temp_entriest_t *base) 00935 { 00936 //Empty active list 00937 ns_list_init(&base->active_temp_neigh); 00938 ns_list_init(&base->free_temp_neigh); 00939 00940 //Add to free list to full 00941 for (int i = 0; i < MAX_NEIGH_TEMPORRY_MULTICAST_SIZE; i++) { 00942 ns_list_add_to_end(&base->free_temp_neigh, &base->neighbour_temporary_table[i]); 00943 } 00944 } 00945 00946 static ws_neighbor_temp_class_t *ws_llc_discover_temp_entry(temp_entriest_t *base, const uint8_t *mac64) 00947 { 00948 ns_list_foreach_safe(ws_neighbor_temp_class_t, entry, &base->active_temp_neigh) { 00949 if (memcmp(entry->mac64, mac64, 8) == 0) { 00950 return entry; 00951 } 00952 } 00953 return NULL; 00954 } 00955 00956 ws_neighbor_temp_class_t *ws_llc_get_multicast_temp_entry(protocol_interface_info_entry_t *interface, const uint8_t *mac64) 00957 { 00958 llc_data_base_t *base = ws_llc_discover_by_interface(interface); 00959 if (!base) { 00960 return NULL; 00961 } 00962 00963 return ws_llc_discover_temp_entry(base->temp_entries, mac64); 00964 } 00965 00966 00967 00968 00969 static ws_neighbor_temp_class_t *ws_allocate_multicast_temp_entry(temp_entriest_t *base, const uint8_t *mac64) 00970 { 00971 00972 ws_neighbor_temp_class_t *entry = ws_llc_discover_temp_entry(base, mac64); 00973 if (entry) { 00974 ns_list_remove(&base->active_temp_neigh, entry); 00975 ns_list_add_to_start(&base->active_temp_neigh, entry); 00976 return entry; 00977 } 00978 00979 entry = ns_list_get_first(&base->free_temp_neigh); 00980 00981 if (entry) { 00982 ns_list_remove(&base->free_temp_neigh, entry); 00983 } else { 00984 //Replace last entry and put it to first 00985 entry = ns_list_get_last(&base->active_temp_neigh); 00986 ns_list_remove(&base->active_temp_neigh, entry); 00987 } 00988 //Add to list 00989 ns_list_add_to_start(&base->active_temp_neigh, entry); 00990 //Clear Old data 00991 memset(&entry->neigh_info_list , 0, sizeof(ws_neighbor_class_entry_t)); 00992 entry->neigh_info_list .rsl_in = RSL_UNITITIALIZED; 00993 entry->neigh_info_list .rsl_out = RSL_UNITITIALIZED; 00994 memcpy(entry->mac64, mac64, 8); 00995 return entry; 00996 } 00997 00998 void ws_llc_free_multicast_temp_entry(protocol_interface_info_entry_t *cur, ws_neighbor_temp_class_t *neighbor) 00999 { 01000 llc_data_base_t *base = ws_llc_discover_by_interface(cur); 01001 if (!base) { 01002 return; 01003 } 01004 ns_list_remove(&base->temp_entries->active_temp_neigh, neighbor); 01005 ns_list_add_to_end(&base->temp_entries->free_temp_neigh, neighbor); 01006 } 01007 01008 01009 int8_t ws_llc_create(struct protocol_interface_info_entry *interface, ws_asynch_ind *asynch_ind_cb, ws_asynch_confirm *asynch_cnf_cb, ws_neighbor_info_request *ws_neighbor_info_request_cb) 01010 { 01011 llc_data_base_t *base = ws_llc_discover_by_interface(interface); 01012 if (base) { 01013 ws_llc_clean(base); 01014 return 0; 01015 } 01016 01017 //Allocate Data base 01018 base = ws_llc_base_allocate(); 01019 if (!base) { 01020 return -2; 01021 } 01022 01023 base->interface_ptr = interface; 01024 base->asynch_ind = asynch_ind_cb; 01025 base->asynch_confirm = asynch_cnf_cb; 01026 base->ws_neighbor_info_request_cb = ws_neighbor_info_request_cb; 01027 //Register MAC Extensions 01028 base->interface_ptr->mac_api->mac_mcps_extension_enable(base->interface_ptr->mac_api, &ws_llc_mac_indication_cb, &ws_llc_mac_confirm_cb, &ws_llc_ack_data_req_ext); 01029 //Init MPX class 01030 ws_llc_mpx_init(&base->mpx_data_base); 01031 ws_llc_temp_neigh_info_table_reset(base->temp_entries); 01032 return 0; 01033 } 01034 01035 int8_t ws_llc_delete(struct protocol_interface_info_entry *interface) 01036 { 01037 llc_data_base_t *base = ws_llc_discover_by_interface(interface); 01038 if (!base) { 01039 return -1; 01040 } 01041 01042 ws_llc_clean(base); 01043 01044 ns_list_remove(&llc_data_base_list, base); 01045 //Disable Mac extension 01046 base->interface_ptr->mac_api->mac_mcps_extension_enable(base->interface_ptr->mac_api, NULL, NULL, NULL); 01047 ns_dyn_mem_free(base->temp_entries); 01048 ns_dyn_mem_free(base); 01049 return 0; 01050 } 01051 01052 01053 01054 void ws_llc_reset(struct protocol_interface_info_entry *interface) 01055 { 01056 llc_data_base_t *base = ws_llc_discover_by_interface(interface); 01057 if (!base) { 01058 return; 01059 } 01060 ws_llc_clean(base); 01061 } 01062 01063 mpx_api_t *ws_llc_mpx_api_get(struct protocol_interface_info_entry *interface) 01064 { 01065 llc_data_base_t *base = ws_llc_discover_by_interface(interface); 01066 if (!base) { 01067 return NULL; 01068 } 01069 return &base->mpx_data_base.mpx_api; 01070 } 01071 01072 int8_t ws_llc_asynch_request(struct protocol_interface_info_entry *interface, asynch_request_t *request) 01073 { 01074 llc_data_base_t *base = ws_llc_discover_by_interface(interface); 01075 if (!base) { 01076 return -1; 01077 } 01078 01079 //Calculate IE Buffer size 01080 request->wh_requested_ie_list.fc_ie = false; //Never should not be a part Asynch message 01081 request->wh_requested_ie_list.rsl_ie = false; //Never should not be a part Asynch message 01082 request->wh_requested_ie_list.vh_ie = false; 01083 uint16_t header_buffer_length = ws_wh_headers_length(request->wh_requested_ie_list, &base->ie_params); 01084 uint16_t wp_nested_payload_length = ws_wp_nested_message_length(request->wp_requested_nested_ie_list, &base->ie_params); 01085 01086 //Allocated 01087 uint16_t total_length = header_buffer_length; 01088 if (wp_nested_payload_length) { 01089 total_length += 2 + wp_nested_payload_length; 01090 } 01091 //Allocate LLC message pointer 01092 01093 llc_message_t *message = llc_message_allocate(total_length, base, false); 01094 if (!message) { 01095 if (base->asynch_confirm) { 01096 base->asynch_confirm(interface, request->message_type); 01097 } 01098 return 0; 01099 } 01100 message->messsage_type = request->message_type; 01101 01102 mcps_data_req_t data_req; 01103 memset(&data_req, 0, sizeof(mcps_data_req_t)); 01104 data_req.SeqNumSuppressed = true; 01105 data_req.SrcAddrMode = MAC_ADDR_MODE_64_BIT; 01106 data_req.Key = request->security; 01107 data_req.msduHandle = message->msg_handle; 01108 if (request->message_type == WS_FT_PAN_ADVERT_SOL) { 01109 // PANID not know yet must be supressed 01110 data_req.PanIdSuppressed = true; 01111 } 01112 01113 uint8_t *ptr = ws_message_buffer_ptr_get(message); 01114 01115 message->ie_vector_list[0].ieBase = ptr; 01116 message->ie_vector_list[0].iovLen = header_buffer_length; 01117 01118 message->ie_ext.headerIeVectorList = &message->ie_vector_list[0]; 01119 message->ie_ext.headerIovLength = 1; 01120 01121 01122 //Write UTT 01123 if (request->wh_requested_ie_list.utt_ie) { 01124 ptr = ws_wh_utt_write(ptr, message->messsage_type); 01125 } 01126 01127 if (request->wh_requested_ie_list.bt_ie) { 01128 //Static 5 bytes allways 01129 ptr = ws_wh_bt_write(ptr); 01130 } 01131 01132 if (wp_nested_payload_length) { 01133 message->ie_vector_list[1].ieBase = ptr; 01134 message->ie_vector_list[1].iovLen = 2 + wp_nested_payload_length; 01135 message->ie_ext.payloadIeVectorList = &message->ie_vector_list[1]; 01136 message->ie_ext.payloadIovLength = 1; 01137 ptr = ws_wp_base_write(ptr, wp_nested_payload_length); 01138 01139 if (request->wp_requested_nested_ie_list.us_ie) { 01140 //Write unicast schedule 01141 ptr = ws_wp_nested_hopping_schedule_write(ptr, base->ie_params.hopping_schedule, true); 01142 } 01143 01144 if (request->wp_requested_nested_ie_list.bs_ie) { 01145 //Write Broadcastcast schedule 01146 ptr = ws_wp_nested_hopping_schedule_write(ptr, base->ie_params.hopping_schedule, false); 01147 } 01148 01149 if (request->wp_requested_nested_ie_list.pan_ie) { 01150 //Write Pan information 01151 ptr = ws_wp_nested_pan_info_write(ptr, base->ie_params.pan_congiguration); 01152 } 01153 01154 if (request->wp_requested_nested_ie_list.net_name_ie) { 01155 //Write network name 01156 ptr = ws_wp_nested_netname_write(ptr, base->ie_params.network_name, base->ie_params.network_name_length); 01157 } 01158 01159 if (request->wp_requested_nested_ie_list.pan_version_ie) { 01160 //Write pan version 01161 ptr = ws_wp_nested_pan_ver_write(ptr, base->ie_params.pan_congiguration); 01162 } 01163 01164 if (request->wp_requested_nested_ie_list.gtkhash_ie) { 01165 //Write GTKHASH 01166 ptr = ws_wp_nested_gtkhash_write(ptr, base->ie_params.gtkhash, base->ie_params.gtkhash_length); 01167 } 01168 01169 if (request->wp_requested_nested_ie_list.vp_ie) { 01170 //Write Vendor spesific payload 01171 ptr = ws_wp_nested_vp_write(ptr, base->ie_params.vendor_payload, base->ie_params.vendor_payload_length); 01172 } 01173 } 01174 01175 base->interface_ptr->mac_api->mcps_data_req_ext(base->interface_ptr->mac_api, &data_req, &message->ie_ext, &request->channel_list); 01176 01177 return 0; 01178 } 01179 01180 01181 void ws_llc_set_vendor_header_data(struct protocol_interface_info_entry *interface, uint8_t *vendor_header, uint8_t vendor_header_length) 01182 { 01183 llc_data_base_t *base = ws_llc_discover_by_interface(interface); 01184 if (!base) { 01185 return; 01186 } 01187 base->ie_params.vendor_header_data = vendor_header; 01188 base->ie_params.vendor_header_length = vendor_header_length; 01189 } 01190 01191 01192 void ws_llc_set_vendor_payload_data(struct protocol_interface_info_entry *interface, uint8_t *vendor_payload, uint8_t vendor_payload_length) 01193 { 01194 llc_data_base_t *base = ws_llc_discover_by_interface(interface); 01195 if (!base) { 01196 return; 01197 } 01198 01199 base->ie_params.vendor_payload = vendor_payload; 01200 base->ie_params.vendor_payload_length = vendor_payload_length; 01201 } 01202 01203 01204 void ws_llc_set_network_name(struct protocol_interface_info_entry *interface, uint8_t *name, uint8_t name_length) 01205 { 01206 llc_data_base_t *base = ws_llc_discover_by_interface(interface); 01207 if (!base) { 01208 return; 01209 } 01210 01211 base->ie_params.network_name = name; 01212 base->ie_params.network_name_length = name_length; 01213 } 01214 01215 void ws_llc_set_gtkhash(struct protocol_interface_info_entry *interface, uint8_t *gtkhash) 01216 { 01217 llc_data_base_t *base = ws_llc_discover_by_interface(interface); 01218 if (!base) { 01219 return; 01220 } 01221 01222 base->ie_params.gtkhash = gtkhash; 01223 if (base->ie_params.gtkhash) { 01224 base->ie_params.gtkhash_length = 32; 01225 } else { 01226 base->ie_params.gtkhash_length = 0; 01227 } 01228 } 01229 01230 01231 01232 void ws_llc_set_pan_information_pointer(struct protocol_interface_info_entry *interface, struct ws_pan_information_s *pan_information_pointer) 01233 { 01234 llc_data_base_t *base = ws_llc_discover_by_interface(interface); 01235 if (!base) { 01236 return; 01237 } 01238 01239 base->ie_params.pan_congiguration = pan_information_pointer; 01240 } 01241 01242 void ws_llc_hopping_schedule_config(struct protocol_interface_info_entry *interface, struct ws_hopping_schedule_s *hopping_schedule) 01243 { 01244 llc_data_base_t *base = ws_llc_discover_by_interface(interface); 01245 if (!base) { 01246 return; 01247 } 01248 base->ie_params.hopping_schedule = hopping_schedule; 01249 } 01250 #endif
Generated on Tue Jul 12 2022 13:55:04 by
1.7.2