Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers mac_neighbor_table.c Source File

mac_neighbor_table.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 
00019 #include "nsconfig.h"
00020 #include "string.h"
00021 #include "ns_types.h"
00022 #include "ns_trace.h"
00023 #include "common_functions.h"
00024 #include "nsdynmemLIB.h"
00025 #include "Service_Libs/mac_neighbor_table/mac_neighbor_table.h"
00026 #include "Core/include/ns_address_internal.h"
00027 #include "platform/topo_trace.h"
00028 
00029 mac_neighbor_table_t *mac_neighbor_table_create(uint8_t table_size, neighbor_entry_remove_notify *remove_cb, neighbor_entry_nud_notify *nud_cb, void *user_indentifier)
00030 {
00031     mac_neighbor_table_t *table_class = ns_dyn_mem_alloc(sizeof(mac_neighbor_table_t) + sizeof(mac_neighbor_table_entry_t) * table_size);
00032     if (!table_class) {
00033         return NULL;
00034     }
00035     memset(table_class, 0, sizeof(mac_neighbor_table_t));
00036 
00037     mac_neighbor_table_entry_t *cur_ptr = &table_class->neighbor_entry_buffer [0];
00038     table_class->list_total_size  = table_size;
00039     table_class->table_user_identifier  = user_indentifier;
00040     table_class->user_nud_notify_cb  = nud_cb;
00041     table_class->user_remove_notify_cb  = remove_cb;
00042     ns_list_init(&table_class->neighbour_list );
00043     ns_list_init(&table_class->free_list );
00044     for (uint8_t i = 0; i < table_size; i++) {
00045         memset(cur_ptr, 0, sizeof(mac_neighbor_table_entry_t));
00046         cur_ptr->index  = i;
00047         //Add to list
00048         ns_list_add_to_end(&table_class->free_list , cur_ptr);
00049         cur_ptr++;
00050     }
00051 
00052     return table_class;
00053 
00054 }
00055 
00056 void mac_neighbor_table_delete(mac_neighbor_table_t *table_class)
00057 {
00058     mac_neighbor_table_neighbor_list_clean(table_class);
00059     ns_dyn_mem_free(table_class);
00060 }
00061 
00062 static void neighbor_table_class_remove_entry(mac_neighbor_table_t *table_class, mac_neighbor_table_entry_t *entry)
00063 {
00064     ns_list_remove(&table_class->neighbour_list , entry);
00065     table_class->neighbour_list_size --;
00066     if (entry->nud_active ) {
00067         entry->nud_active  = false;
00068         table_class->active_nud_process --;
00069     }
00070 
00071     if (table_class->user_remove_notify_cb ) {
00072         table_class->user_remove_notify_cb (entry, table_class->table_user_identifier );
00073     }
00074     topo_trace(TOPOLOGY_MLE, entry->mac64 , TOPO_REMOVE);
00075 
00076 
00077     uint8_t index = entry->index ;
00078     memset(entry, 0, sizeof(mac_neighbor_table_entry_t));
00079     entry->index  = index;
00080     ns_list_add_to_end(&table_class->free_list , entry);
00081 }
00082 
00083 void mac_neighbor_table_neighbor_list_clean(mac_neighbor_table_t *table_class)
00084 {
00085     if (!table_class) {
00086         return;
00087     }
00088     ns_list_foreach_safe(mac_neighbor_table_entry_t, cur, &table_class->neighbour_list ) {
00089         neighbor_table_class_remove_entry(table_class, cur);
00090     }
00091     topo_trace(TOPOLOGY_MLE, NULL, TOPO_CLEAR);
00092 }
00093 
00094 
00095 void mac_neighbor_table_neighbor_timeout_update(mac_neighbor_table_t *table_class, uint32_t time_update)
00096 {
00097     if (!table_class) {
00098         return;
00099     }
00100 
00101     ns_list_foreach_safe(mac_neighbor_table_entry_t, cur, &table_class->neighbour_list ) {
00102 
00103         if (cur->lifetime > time_update) {
00104             cur->lifetime -= time_update;
00105             if (!table_class->user_nud_notify_cb  ||  table_class->active_nud_process  > ACTIVE_NUD_PROCESS_MAX || cur->nud_active || !cur->rx_on_idle) {
00106                 continue;
00107             }
00108 
00109             if (table_class->user_nud_notify_cb (cur, table_class->table_user_identifier )) {
00110                 table_class->active_nud_process ++;
00111                 cur->nud_active = true;
00112             }
00113 
00114         } else {
00115             neighbor_table_class_remove_entry(table_class, cur);
00116         }
00117     }
00118 }
00119 
00120 
00121 mac_neighbor_table_entry_t *mac_neighbor_table_entry_allocate(mac_neighbor_table_t *table_class, const uint8_t *mac64)
00122 {
00123     if (!table_class) {
00124         return NULL;
00125     }
00126     mac_neighbor_table_entry_t *entry = ns_list_get_first(&table_class->free_list );
00127     if (!entry) {
00128         return NULL;
00129     }
00130     //Remove from the list
00131     ns_list_remove(&table_class->free_list , entry);
00132     //Add to list
00133     ns_list_add_to_end(&table_class->neighbour_list , entry);
00134     table_class->neighbour_list_size ++;
00135     memcpy(entry->mac64 , mac64, 8);
00136     entry->mac16  = 0xffff;
00137     entry->rx_on_idle  = true;
00138     entry->ffd_device  = true;
00139     entry->nud_active  = false;
00140     entry->advertisment = false;
00141     entry->connected_device  = false;
00142     entry->trusted_device  = false;
00143     entry->lifetime  = NEIGHBOR_CLASS_LINK_DEFAULT_LIFETIME;
00144     entry->link_lifetime  = NEIGHBOR_CLASS_LINK_DEFAULT_LIFETIME;
00145     entry->link_role  = NORMAL_NEIGHBOUR;
00146     topo_trace(TOPOLOGY_MLE, mac64, TOPO_ADD);
00147     return entry;
00148 }
00149 
00150 static mac_neighbor_table_entry_t *neighbor_table_class_entry_validate(mac_neighbor_table_t *table_class, mac_neighbor_table_entry_t *neighbor_entry)
00151 {
00152     ns_list_foreach(mac_neighbor_table_entry_t, cur, &table_class->neighbour_list ) {
00153         if (cur == neighbor_entry) {
00154             return cur;
00155         }
00156     }
00157     return NULL;
00158 
00159 }
00160 
00161 void mac_neighbor_table_neighbor_remove(mac_neighbor_table_t *table_class, mac_neighbor_table_entry_t *neighbor_entry)
00162 {
00163     mac_neighbor_table_entry_t *entry = neighbor_table_class_entry_validate(table_class, neighbor_entry);
00164     if (entry) {
00165         neighbor_table_class_remove_entry(table_class, entry);
00166     }
00167 }
00168 
00169 
00170 void mac_neighbor_table_neighbor_refresh(mac_neighbor_table_t *table_class, mac_neighbor_table_entry_t *neighbor_entry, uint32_t life_time)
00171 {
00172     neighbor_entry->lifetime  = life_time;
00173     neighbor_entry->link_lifetime  = life_time;
00174     if (neighbor_entry->nud_active ) {
00175         neighbor_entry->nud_active  = false;
00176         table_class->active_nud_process --;
00177     }
00178 
00179 }
00180 
00181 void mac_neighbor_table_neighbor_connected(mac_neighbor_table_t *table_class, mac_neighbor_table_entry_t *neighbor_entry)
00182 {
00183     (void)table_class;
00184     neighbor_entry->connected_device  = true;
00185 }
00186 
00187 void mac_neighbor_table_trusted_neighbor(mac_neighbor_table_t *table_class, mac_neighbor_table_entry_t *neighbor_entry, bool trusted_device)
00188 {
00189     (void)table_class;
00190     if (!neighbor_entry->trusted_device  && trusted_device) {
00191         neighbor_entry->lifetime  = neighbor_entry->link_lifetime ;
00192     }
00193     neighbor_entry->trusted_device  = trusted_device;
00194 }
00195 
00196 mac_neighbor_table_entry_t *mac_neighbor_table_address_discover(mac_neighbor_table_t *table_class, const uint8_t *address, uint8_t address_type)
00197 {
00198     if (!table_class) {
00199         return NULL;
00200     }
00201     uint16_t short_address;
00202     if (address_type == ADDR_802_15_4_SHORT ) {
00203         short_address = common_read_16_bit(address);
00204     } else if (address_type == ADDR_802_15_4_LONG ) {
00205 
00206     } else {
00207         return NULL;
00208     }
00209 
00210     ns_list_foreach(mac_neighbor_table_entry_t, cur, &table_class->neighbour_list ) {
00211         if (address_type == ADDR_802_15_4_SHORT ) {
00212             if (cur->mac16 != 0xffff && cur->mac16 == short_address) {
00213                 return cur;
00214             }
00215         } else {
00216             if (memcmp(cur->mac64, address, 8) == 0) {
00217                 return cur;
00218             }
00219         }
00220     }
00221 
00222     return NULL;
00223 }
00224 
00225 mac_neighbor_table_entry_t *mac_neighbor_table_attribute_discover(mac_neighbor_table_t *table_class, uint8_t index)
00226 {
00227     ns_list_foreach(mac_neighbor_table_entry_t, cur, &table_class->neighbour_list ) {
00228 
00229         if (cur->index == index) {
00230             return cur;
00231         }
00232     }
00233     return NULL;
00234 }
00235 
00236 mac_neighbor_table_entry_t *mac_neighbor_entry_get_by_ll64(mac_neighbor_table_t *table_class, const uint8_t *ipv6Address, bool allocateNew, bool *new_entry_allocated)
00237 {
00238     // Check it really is LL64 (not LL16)
00239     if (memcmp(ipv6Address, ADDR_LINK_LOCAL_PREFIX, 8) != 0) {
00240         return NULL;    //Mot Link Local Address
00241     }
00242 
00243     if (memcmp((ipv6Address + 8), ADDR_SHORT_ADR_SUFFIC, 6) == 0) {
00244         return NULL;
00245     }
00246     // map
00247     uint8_t temporary_mac64[8];
00248     memcpy(temporary_mac64, (ipv6Address + 8), 8);
00249     temporary_mac64[0] ^= 2;
00250 
00251     return mac_neighbor_entry_get_by_mac64(table_class, temporary_mac64, allocateNew, new_entry_allocated);
00252 
00253 }
00254 
00255 mac_neighbor_table_entry_t *mac_neighbor_entry_get_by_mac64(mac_neighbor_table_t *table_class, const uint8_t *mac64, bool allocateNew, bool *new_entry_allocated)
00256 {
00257     mac_neighbor_table_entry_t *entry = mac_neighbor_table_address_discover(table_class, mac64, ADDR_802_15_4_LONG );
00258     if (entry || !allocateNew) {
00259         if (new_entry_allocated) {
00260             *new_entry_allocated = false;
00261         }
00262         return entry;
00263     }
00264 
00265     if (new_entry_allocated) {
00266         *new_entry_allocated = true;
00267     }
00268 
00269     return mac_neighbor_table_entry_allocate(table_class, mac64);
00270 }
00271 
00272 mac_neighbor_table_entry_t *mac_neighbor_entry_get_priority(mac_neighbor_table_t *table_class)
00273 {
00274 
00275     ns_list_foreach(mac_neighbor_table_entry_t, entry, &table_class->neighbour_list ) {
00276         if (entry->link_role  == PRIORITY_PARENT_NEIGHBOUR) {
00277             return entry;
00278         }
00279     }
00280     return NULL;
00281 }