Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ws_llc_data_service.c Source File

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