41 #include "net/nbr-table.h" 43 #define DEBUG DEBUG_NONE 48 static void handle_periodic_timer(
void *ptr);
49 static struct ctimer periodic_timer;
50 static uint8_t initialized = 0;
51 static void print_table();
52 #define PRINTF(...) printf(__VA_ARGS__) 59 static uint8_t used_map[NBR_TABLE_MAX_NEIGHBORS];
61 static uint8_t locked_map[NBR_TABLE_MAX_NEIGHBORS];
63 #define MAX_NUM_TABLES 8 65 static struct nbr_table *all_tables[MAX_NUM_TABLES];
67 static unsigned num_tables;
70 MEMB(neighbor_addr_mem, nbr_table_key_t, NBR_TABLE_MAX_NEIGHBORS);
74 static void remove_key(nbr_table_key_t *key,
bool do_free);
77 static nbr_table_key_t *
78 key_from_index(
int index)
80 return index != -1 ? &((nbr_table_key_t *)neighbor_addr_mem.mem)[index] : NULL;
84 static nbr_table_item_t *
85 item_from_index(nbr_table_t *table,
int index)
87 return table != NULL && index != -1 ? (
char *)table->data + index * table->item_size : NULL;
92 index_from_key(nbr_table_key_t *key)
94 return key != NULL ? key - (nbr_table_key_t *)neighbor_addr_mem.mem : -1;
99 index_from_item(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;
105 static nbr_table_item_t *
106 item_from_key(nbr_table_t *table, nbr_table_key_t *key)
108 return item_from_index(table, index_from_key(key));
112 static nbr_table_key_t *
113 key_from_item(nbr_table_t *table,
const nbr_table_item_t *item)
115 return key_from_index(index_from_item(table, item));
120 index_from_lladdr(
const linkaddr_t *lladdr)
122 nbr_table_key_t *key;
131 return index_from_key(key);
140 nbr_get_bit(uint8_t *bitmap, nbr_table_t *table, nbr_table_item_t *item)
142 int item_index = index_from_item(table, item);
143 if(table != NULL && item_index != -1) {
144 return (bitmap[item_index] & (1 << table->index)) != 0;
153 nbr_set_bit(uint8_t *bitmap, nbr_table_t *table, nbr_table_item_t *item,
int value)
155 int item_index = index_from_item(table, item);
157 if(table != NULL && item_index != -1) {
159 bitmap[item_index] |= 1 << table->index;
161 bitmap[item_index] &= ~(1 << table->index);
171 remove_key(nbr_table_key_t *key,
bool do_free)
174 for(i = 0; i < MAX_NUM_TABLES; i++) {
175 if(all_tables[i] != NULL && all_tables[i]->callback != NULL) {
177 nbr_table_item_t *removed_item = item_from_key(all_tables[i], key);
178 if(nbr_get_bit(used_map, all_tables[i], removed_item) == 1) {
179 all_tables[i]->callback(removed_item);
184 used_map[index_from_key(key)] = 0;
185 locked_map[index_from_key(key)] = 0;
195 nbr_table_count_entries(
void)
199 for(i = 0; i < NBR_TABLE_MAX_NEIGHBORS; i++) {
200 if(used_map[i] > 0) {
208 used_count(
const linkaddr_t *lladdr)
210 int item_index = index_from_lladdr(lladdr);
212 if(item_index != -1) {
213 int used = used_map[item_index];
216 if((used & 1) == 1) {
226 nbr_table_gc_get_worst(
const linkaddr_t *lladdr1,
const linkaddr_t *lladdr2)
228 return used_count(lladdr2) < used_count(lladdr1) ? lladdr2 : lladdr1;
232 nbr_table_can_accept_new(
const linkaddr_t *
new,
const linkaddr_t *candidate_for_removal,
233 nbr_table_reason_t reason,
void *data)
239 static const linkaddr_t *
240 select_for_removal(
const linkaddr_t *
new, nbr_table_reason_t reason,
void *data)
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)) {
268 entry_is_allowed(nbr_table_t *table,
const linkaddr_t *lladdr,
269 nbr_table_reason_t reason,
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;
295 nbr_table_entry_is_allowed(nbr_table_t *table,
const linkaddr_t *lladdr,
296 nbr_table_reason_t reason,
void *data)
298 return entry_is_allowed(table, lladdr, reason, data, NULL);
301 static nbr_table_key_t *
302 nbr_table_allocate(nbr_table_reason_t reason,
void *data,
const linkaddr_t *to_be_removed_lladdr)
304 nbr_table_key_t *
new =
memb_alloc(&neighbor_addr_mem);
308 if(to_be_removed_lladdr == NULL) {
312 nbr_table_key_t *to_be_removed = key_from_index(index_from_lladdr(to_be_removed_lladdr));
314 remove_key(to_be_removed,
false);
315 return to_be_removed;
323 nbr_table_register(nbr_table_t *table, nbr_table_callback *callback)
333 if(nbr_table_is_registered(table)) {
335 table->callback = callback;
339 if(num_tables < MAX_NUM_TABLES) {
340 table->index = num_tables++;
341 table->callback = callback;
342 all_tables[table->index] = table;
352 nbr_table_is_registered(nbr_table_t *table)
354 if(table != NULL && table->index >= 0 && table->index < MAX_NUM_TABLES
355 && all_tables[table->index] == table) {
363 nbr_table_head(nbr_table_t *table)
366 nbr_table_item_t *item = item_from_key(table,
list_head(nbr_table_keys));
368 if(nbr_get_bit(used_map, table, item)) {
371 return nbr_table_next(table, item);
377 nbr_table_next(nbr_table_t *table, nbr_table_item_t *item)
380 void *key = key_from_item(table, item);
383 item = item_from_key(table, key);
384 }
while(item && !nbr_get_bit(used_map, table, item));
390 nbr_table_add_lladdr(nbr_table_t *table,
const linkaddr_t *lladdr, nbr_table_reason_t reason,
void *data)
393 nbr_table_item_t *item;
394 nbr_table_key_t *key;
395 const linkaddr_t *to_be_removed;
407 if(!entry_is_allowed(table, lladdr, reason, data, &to_be_removed)) {
411 if((index = index_from_lladdr(lladdr)) == -1) {
413 key = nbr_table_allocate(reason, data, to_be_removed);
425 index = index_from_key(key);
432 item = item_from_index(table, index);
435 memset(item, 0, table->item_size);
436 nbr_set_bit(used_map, table, item, 1);
446 nbr_table_get_from_lladdr(nbr_table_t *table,
const linkaddr_t *lladdr)
448 void *item = item_from_index(table, index_from_lladdr(lladdr));
449 return nbr_get_bit(used_map, table, item) ? item : NULL;
454 nbr_table_remove(nbr_table_t *table,
void *item)
456 int ret = nbr_set_bit(used_map, table, item, 0);
457 nbr_set_bit(locked_map, table, item, 0);
463 nbr_table_lock(nbr_table_t *table,
void *item)
466 int i = index_from_item(table, item);
467 PRINTF(
"*** Lock %d\n", i);
469 return nbr_set_bit(locked_map, table, item, 1);
474 nbr_table_unlock(nbr_table_t *table,
void *item)
477 int i = index_from_item(table, item);
478 PRINTF(
"*** Unlock %d\n", i);
480 return nbr_set_bit(locked_map, table, item, 0);
485 nbr_table_get_lladdr(nbr_table_t *table,
const void *item)
487 nbr_table_key_t *key = key_from_item(table, item);
488 return key != NULL ? &key->lladdr : NULL;
492 nbr_table_clear(
void)
502 nbr_table_key_head(
void)
508 nbr_table_key_next(nbr_table_key_t *key)
519 PRINTF(
"NBR TABLE:\n");
520 for(i = 0; i < NBR_TABLE_MAX_NEIGHBORS; i++) {
521 if(used_map[i] > 0) {
522 PRINTF(
" %02d %02d",i , key_from_index(i)->lladdr.u8[LINKADDR_SIZE - 1]);
523 for(j = 0; j < num_tables; j++) {
524 PRINTF(
" [%d:%d]", (used_map[i] & (1 << j)) != 0,
525 (locked_map[i] & (1 << j)) != 0);
533 handle_periodic_timer(
void *ptr)
static volatile uint64_t count
Num.
int memb_free(struct memb *m, void *ptr)
Deallocate a memory block from a memory block previously declared with MEMB().
A set of debugging macros for the IP stack
void ctimer_reset(struct ctimer *c)
Reset a callback timer with the same interval as was previously set.
const linkaddr_t linkaddr_null
The null link-layer address.
#define CLOCK_SECOND
A second, measured in system clock time.
Header file for the callback timer
Linked list manipulation routines.
void * list_head(list_t list)
Get a pointer to the first element of a list.
void ctimer_set(struct ctimer *c, clock_time_t t, void(*f)(void *), void *ptr)
Set a callback timer.
Memory block allocation routines.
void linkaddr_copy(linkaddr_t *dest, const linkaddr_t *src)
Copy a link-layer address.
void list_add(list_t list, void *item)
Add an item at the end of a list.
int linkaddr_cmp(const linkaddr_t *addr1, const linkaddr_t *addr2)
Compare two link-layer addresses.
#define LIST(name)
Declare a linked list.
void * memb_alloc(struct memb *m)
Allocate a memory block from a block of memory declared with MEMB().
int memb_numfree(struct memb *m)
Count free memory blocks.
void list_remove(list_t list, void *item)
Remove a specific element from a list.
void * list_item_next(void *item)
Get the next item following this item.
#define MEMB(name, structure, num)
Declare a memory block.