41#include "net/nbr-table.h"
43#define DEBUG DEBUG_NONE
48static void handle_periodic_timer(
void *ptr);
49static struct ctimer periodic_timer;
50static uint8_t initialized = 0;
51static void print_table();
52#define PRINTF(...) printf(__VA_ARGS__)
59static uint8_t used_map[NBR_TABLE_MAX_NEIGHBORS];
61static uint8_t locked_map[NBR_TABLE_MAX_NEIGHBORS];
63#define MAX_NUM_TABLES 8
65static struct nbr_table *all_tables[MAX_NUM_TABLES];
67static unsigned num_tables;
70MEMB(neighbor_addr_mem, nbr_table_key_t, NBR_TABLE_MAX_NEIGHBORS);
74static void remove_key(nbr_table_key_t *key,
bool do_free);
77static nbr_table_key_t *
78key_from_index(
int index)
80 return index != -1 ? &((nbr_table_key_t *)neighbor_addr_mem.mem)[index] : NULL;
84static nbr_table_item_t *
85item_from_index(
const nbr_table_t *table,
int index)
87 return table != NULL && index != -1 ? (
char *)table->data + index * table->item_size : NULL;
92index_from_key(
const nbr_table_key_t *key)
94 return key != NULL ? key - (nbr_table_key_t *)neighbor_addr_mem.mem : -1;
99index_from_item(
const nbr_table_t *table,
const nbr_table_item_t *item)
101 return table != NULL && item != NULL ? ((int)((
char *)item - (
char *)table->data)) / table->item_size : -1;
105static nbr_table_item_t *
106item_from_key(
const nbr_table_t *table,
const nbr_table_key_t *key)
108 return item_from_index(table, index_from_key(key));
112static nbr_table_key_t *
113key_from_item(
const nbr_table_t *table,
const nbr_table_item_t *item)
115 return key_from_index(index_from_item(table, item));
120index_from_lladdr(
const linkaddr_t *lladdr)
122 nbr_table_key_t *key;
131 return index_from_key(key);
140nbr_get_bit(
const uint8_t *bitmap,
const nbr_table_t *table,
141 const nbr_table_item_t *item)
143 int item_index = index_from_item(table, item);
144 if(item_index != -1) {
145 return (bitmap[item_index] & (1 << table->index)) != 0;
152nbr_set_bit(uint8_t *bitmap,
const nbr_table_t *table,
153 const nbr_table_item_t *item,
int value)
155 int item_index = index_from_item(table, item);
157 if(item_index != -1) {
159 bitmap[item_index] |= 1 << table->index;
161 bitmap[item_index] &= ~(1 << table->index);
169remove_key(nbr_table_key_t *key,
bool do_free)
172 for(i = 0; i < MAX_NUM_TABLES; i++) {
173 if(all_tables[i] != NULL && all_tables[i]->callback != NULL) {
175 nbr_table_item_t *removed_item = item_from_key(all_tables[i], key);
176 if(nbr_get_bit(used_map, all_tables[i], removed_item) == 1) {
177 all_tables[i]->callback(removed_item);
182 used_map[index_from_key(key)] = 0;
183 locked_map[index_from_key(key)] = 0;
193nbr_table_count_entries(
void)
197 for(i = 0; i < NBR_TABLE_MAX_NEIGHBORS; i++) {
198 if(used_map[i] > 0) {
206used_count(
const linkaddr_t *lladdr)
208 int item_index = index_from_lladdr(lladdr);
210 if(item_index != -1) {
211 int used = used_map[item_index];
214 if((used & 1) == 1) {
224nbr_table_gc_get_worst(
const linkaddr_t *lladdr1,
const linkaddr_t *lladdr2)
226 return used_count(lladdr2) < used_count(lladdr1) ? lladdr2 : lladdr1;
230nbr_table_can_accept_new(
const linkaddr_t *
new,
231 const linkaddr_t *candidate_for_removal,
232 nbr_table_reason_t reason,
const void *data)
238static const linkaddr_t *
239select_for_removal(
const linkaddr_t *
new, nbr_table_reason_t reason,
243 const linkaddr_t *worst_lladdr = NULL;
247 int item_index = index_from_key(k);
248 int locked = locked_map[item_index];
251 if(worst_lladdr == NULL) {
252 worst_lladdr = &k->lladdr;
254 worst_lladdr = NBR_TABLE_GC_GET_WORST(worst_lladdr, &k->lladdr);
260 if(worst_lladdr != NULL && NBR_TABLE_CAN_ACCEPT_NEW(
new, worst_lladdr, reason, data)) {
268entry_is_allowed(
const nbr_table_t *table,
const linkaddr_t *lladdr,
269 nbr_table_reason_t reason,
const void *data,
270 const linkaddr_t **to_be_removed_ptr)
273 const linkaddr_t *to_be_removed = NULL;
275 if(nbr_table_get_from_lladdr(table, lladdr) != NULL) {
279 if(index_from_lladdr(lladdr) != -1
283 ret = NBR_TABLE_CAN_ACCEPT_NEW(lladdr, NULL, reason, data);
285 ret = (to_be_removed = select_for_removal(lladdr, reason, data)) != NULL;
288 if(to_be_removed_ptr != NULL) {
289 *to_be_removed_ptr = to_be_removed;
295nbr_table_entry_is_allowed(
const nbr_table_t *table,
const linkaddr_t *lladdr,
296 nbr_table_reason_t reason,
const void *data)
298 return entry_is_allowed(table, lladdr, reason, data, NULL);
301static nbr_table_key_t *
302nbr_table_allocate(nbr_table_reason_t reason,
const void *data,
303 const linkaddr_t *to_be_removed_lladdr)
305 nbr_table_key_t *
new =
memb_alloc(&neighbor_addr_mem);
309 if(to_be_removed_lladdr == NULL) {
313 nbr_table_key_t *to_be_removed = key_from_index(index_from_lladdr(to_be_removed_lladdr));
314 if(to_be_removed == NULL) {
318 remove_key(to_be_removed,
false);
319 return to_be_removed;
326nbr_table_register(nbr_table_t *table, nbr_table_callback *callback)
336 if(nbr_table_is_registered(table)) {
338 table->callback = callback;
342 if(num_tables < MAX_NUM_TABLES) {
343 table->index = num_tables++;
344 table->callback = callback;
345 all_tables[table->index] = table;
355nbr_table_is_registered(
const nbr_table_t *table)
357 if(table != NULL && table->index >= 0 && table->index < MAX_NUM_TABLES
358 && all_tables[table->index] == table) {
366nbr_table_head(
const nbr_table_t *table)
369 nbr_table_item_t *item = item_from_key(table,
list_head(nbr_table_keys));
371 if(nbr_get_bit(used_map, table, item)) {
374 return nbr_table_next(table, item);
380nbr_table_next(
const nbr_table_t *table, nbr_table_item_t *item)
383 void *key = key_from_item(table, item);
386 item = item_from_key(table, key);
387 }
while(item && !nbr_get_bit(used_map, table, item));
393nbr_table_add_lladdr(
const nbr_table_t *table,
const linkaddr_t *lladdr,
394 nbr_table_reason_t reason,
const void *data)
397 nbr_table_item_t *item;
398 nbr_table_key_t *key;
399 const linkaddr_t *to_be_removed;
411 if(!entry_is_allowed(table, lladdr, reason, data, &to_be_removed)) {
415 if((index = index_from_lladdr(lladdr)) == -1) {
417 key = nbr_table_allocate(reason, data, to_be_removed);
429 index = index_from_key(key);
436 item = item_from_index(table, index);
439 memset(item, 0, table->item_size);
440 nbr_set_bit(used_map, table, item, 1);
450nbr_table_get_from_lladdr(
const nbr_table_t *table,
const linkaddr_t *lladdr)
452 void *item = item_from_index(table, index_from_lladdr(lladdr));
453 return nbr_get_bit(used_map, table, item) ? item : NULL;
458nbr_table_remove(
const nbr_table_t *table,
const void *item)
460 int ret = nbr_set_bit(used_map, table, item, 0);
461 nbr_set_bit(locked_map, table, item, 0);
467nbr_table_lock(
const nbr_table_t *table,
const void *item)
470 int i = index_from_item(table, item);
471 PRINTF(
"*** Lock %d\n", i);
473 return nbr_set_bit(locked_map, table, item, 1);
478nbr_table_unlock(
const nbr_table_t *table,
const void *item)
481 int i = index_from_item(table, item);
482 PRINTF(
"*** Unlock %d\n", i);
484 return nbr_set_bit(locked_map, table, item, 0);
489nbr_table_get_lladdr(
const nbr_table_t *table,
const void *item)
491 nbr_table_key_t *key = key_from_item(table, item);
492 return key != NULL ? &key->lladdr : NULL;
506nbr_table_key_head(
void)
512nbr_table_key_next(
const nbr_table_key_t *key)
523 PRINTF(
"NBR TABLE:\n");
524 for(i = 0; i < NBR_TABLE_MAX_NEIGHBORS; i++) {
525 if(used_map[i] > 0) {
526 PRINTF(
" %02d %02d",i , key_from_index(i)->lladdr.u8[LINKADDR_SIZE - 1]);
527 for(j = 0; j < num_tables; j++) {
528 PRINTF(
" [%d:%d]", (used_map[i] & (1 << j)) != 0,
529 (locked_map[i] & (1 << j)) != 0);
537handle_periodic_timer(
void *ptr)
Header file for the callback timer.
static volatile uint64_t count
Num.
#define CLOCK_SECOND
A second, measured in system clock time.
void ctimer_reset(struct ctimer *c)
Reset a callback timer with the same interval as was previously set.
static void ctimer_set(struct ctimer *c, clock_time_t t, void(*f)(void *), void *ptr)
Set a callback timer.
void linkaddr_copy(linkaddr_t *dest, const linkaddr_t *src)
Copy a link-layer address.
bool linkaddr_cmp(const linkaddr_t *addr1, const linkaddr_t *addr2)
Compare two link-layer addresses.
const linkaddr_t linkaddr_null
The null link-layer address.
#define LIST(name)
Declare a linked list.
static void * list_item_next(const void *item)
Get the next item following this item.
void list_add(list_t list, void *item)
Add an item at the end of a list.
void list_remove(list_t list, const void *item)
Remove a specific element from a list.
static void * list_head(const_list_t list)
Get a pointer to the first element of a list.
int memb_free(struct memb *m, void *ptr)
Deallocate a memory block from a memory block previously declared with MEMB().
size_t memb_numfree(struct memb *m)
Count free memory blocks.
void * memb_alloc(struct memb *m)
Allocate a memory block from a block of memory declared with MEMB().
#define MEMB(name, structure, num)
Declare a memory block.
Linked list manipulation routines.
Memory block allocation routines.
A set of debugging macros for the IP stack.