takashi kadono / Mbed OS Nucleo_446

Dependencies:   ssd1331

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