Skip to content

Commit

Permalink
Generic mesh neighbor table class.
Browse files Browse the repository at this point in the history
This class will remove MLE protocol based neighbor table.
  • Loading branch information
Juha Heiskanen authored and juhhei01 committed Mar 1, 2018
1 parent 4b81978 commit fc4c97b
Show file tree
Hide file tree
Showing 3 changed files with 422 additions and 0 deletions.
230 changes: 230 additions & 0 deletions source/Service_Libs/mac_neighbor_table/mac_neighbor_table.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,230 @@
/*
* Copyright (c) 2018, Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/


#include "nsconfig.h"
#include "string.h"
#include "ns_types.h"
#include "ns_trace.h"
#include "common_functions.h"
#include "nsdynmemLIB.h"
#include "Service_Libs/mac_neighbor_table/mac_neighbor_table.h"

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, uint32_t nud_threshold)
{
mac_neighbor_table_t *table_class = ns_dyn_mem_alloc(sizeof(mac_neighbor_table_t) + sizeof(mac_neighbor_table_entry_t) * table_size);
if (!table_class) {
return NULL;
}
memset(table_class, 0, sizeof(mac_neighbor_table_t));

mac_neighbor_table_entry_t *cur_ptr = &table_class->neighbor_entry_buffer[0];
table_class->list_total_size = table_size;
table_class->nud_threshold = nud_threshold;
table_class->table_user_identifier = user_indentifier;
table_class->user_nud_notify_cb = nud_cb;
table_class->user_remove_notify_cb = remove_cb;
ns_list_init(&table_class->neighbour_list);
ns_list_init(&table_class->free_list);
for (uint8_t i = 0; i< table_size; i++) {
memset(cur_ptr, 0, sizeof(mac_neighbor_table_entry_t));
cur_ptr->index = i;
//Add to list
ns_list_add_to_end(&table_class->free_list,cur_ptr);
cur_ptr++;
}

return table_class;

}

void mac_neighbor_table_delete(mac_neighbor_table_t *table_class)
{
ns_dyn_mem_free(table_class);
}

static void neighbor_table_class_remove_entry(mac_neighbor_table_t *table_class, mac_neighbor_table_entry_t *entry)
{
ns_list_remove(&table_class->neighbour_list, entry);
table_class->neighbour_list_size--;
if (entry->nud_active) {
entry->nud_active = false;
table_class->active_nud_process--;
}

if (table_class->user_remove_notify_cb) {
table_class->user_remove_notify_cb(entry, table_class->table_user_identifier);
}


uint8_t index = entry->index;
memset(entry, 0, sizeof(mac_neighbor_table_entry_t));
entry->index = index;
ns_list_add_to_end(&table_class->free_list,entry);
}

void mac_neighbor_table_neighbor_list_clean(mac_neighbor_table_t *table_class)
{
ns_list_foreach_safe(mac_neighbor_table_entry_t, cur, &table_class->neighbour_list) {
neighbor_table_class_remove_entry(table_class, cur);
}
}


void mac_neighbor_table_neighbor_timeout_update(mac_neighbor_table_t *table_class, uint32_t time_update)
{
bool nud_is_enabled = false;
if (table_class->nud_threshold && table_class->user_nud_notify_cb) {
nud_is_enabled = true;
}
ns_list_foreach_safe(mac_neighbor_table_entry_t, cur, &table_class->neighbour_list) {

if (cur->lifetime > time_update) {
cur->lifetime -= time_update;
if (!nud_is_enabled || cur->nud_active || !cur->rx_on_idle) {
continue;
}

uint32_t time_from_start = cur->link_lifetime - cur->lifetime;
bool activate_nud = false;
if ((table_class->nud_threshold > cur->link_lifetime) && (time_from_start > cur->link_lifetime / 2)) {
//Trig allways at middle way
activate_nud = true;
} else if (time_from_start > table_class->nud_threshold) {
activate_nud = true;
}

if (activate_nud) {
if (table_class->user_nud_notify_cb(cur, table_class->table_user_identifier)) {
table_class->active_nud_process++;
cur->nud_active = true;
}
}

} else {
neighbor_table_class_remove_entry(table_class, cur);
}
}
}


mac_neighbor_table_entry_t *mac_neighbor_table_entry_allocate(mac_neighbor_table_t *table_class, const uint8_t *mac64)
{
mac_neighbor_table_entry_t *entry = ns_list_get_first(&table_class->free_list);
if (!entry) {
return NULL;
}
//Remove from the list
ns_list_remove(&table_class->free_list, entry);
//Add to list
ns_list_add_to_end(&table_class->neighbour_list,entry);
table_class->neighbour_list_size++;
memcpy(entry->mac64, mac64, 8);
entry->mac16 = 0xffff;
entry->rx_on_idle = true;
entry->ffd_device = true;
entry->lifetime = NEIGHBOR_CLASS_LINK_DEFAULT_LIFETIME;
entry->link_lifetime = NEIGHBOR_CLASS_LINK_DEFAULT_LIFETIME;
return entry;
}

static mac_neighbor_table_entry_t *neighbor_table_class_entry_validate(mac_neighbor_table_t *table_class, mac_neighbor_table_entry_t *neighbor_entry)
{
ns_list_foreach(mac_neighbor_table_entry_t, cur, &table_class->neighbour_list) {
if (cur == neighbor_entry) {
return cur;
}
}
return NULL;

}

void mac_neighbor_table_neighbor_remove(mac_neighbor_table_t *table_class, mac_neighbor_table_entry_t *neighbor_entry)
{
mac_neighbor_table_entry_t *entry = neighbor_table_class_entry_validate(table_class, neighbor_entry);
if (entry) {
neighbor_table_class_remove_entry(table_class, entry);
}
}


void mac_neighbor_table_neighbor_refresh(mac_neighbor_table_t *table_class, mac_neighbor_table_entry_t *neighbor_entry, uint32_t life_time)
{
mac_neighbor_table_entry_t *entry = neighbor_table_class_entry_validate(table_class, neighbor_entry);
if (entry) {
entry->lifetime = life_time;
entry->link_lifetime = life_time;
if (entry->nud_active) {
entry->nud_active = false;
table_class->active_nud_process--;
}
}
}

void mac_neighbor_table_neighbor_connected(mac_neighbor_table_t *table_class, mac_neighbor_table_entry_t *neighbor_entry)
{
mac_neighbor_table_entry_t *entry = neighbor_table_class_entry_validate(table_class, neighbor_entry);
if (entry) {
entry->connected_device = true;
}
}

void mac_neighbor_table_trusted_neighbor(mac_neighbor_table_t *table_class, mac_neighbor_table_entry_t *neighbor_entry, bool trusted_device)
{
mac_neighbor_table_entry_t *entry = neighbor_table_class_entry_validate(table_class, neighbor_entry);
if (entry) {
entry->trusted_device = trusted_device;
}
}


mac_neighbor_table_entry_t *mac_neighbor_table_address_discover(mac_neighbor_table_t *table_class, const uint8_t *address, uint8_t address_type)
{
uint16_t short_address;
if (address_type == 2) {
short_address = common_read_16_bit(address);
} else if (address_type == 3) {

} else {
return NULL;
}

ns_list_foreach(mac_neighbor_table_entry_t, cur, &table_class->neighbour_list) {
if (address_type == 2) {
if (cur->mac16 != 0xffff && cur->mac16 == short_address) {
return cur;
}
} else {
if (memcmp(cur->mac64, address, 8) == 0) {
return cur;
}
}
}

return NULL;
}

mac_neighbor_table_entry_t *mac_neighbor_table_attribute_discover(mac_neighbor_table_t *table_class, uint8_t index)
{
ns_list_foreach(mac_neighbor_table_entry_t, cur, &table_class->neighbour_list) {

if (cur->index == index) {
return cur;
}
}
return NULL;
}
Loading

0 comments on commit fc4c97b

Please sign in to comment.