41 #include "net/nbr-table.h"
47 static void handle_periodic_timer(
void *ptr);
48 static struct ctimer periodic_timer;
49 static uint8_t initialized = 0;
50 static void print_table();
51 #define PRINTF(...) printf(__VA_ARGS__)
59 #ifdef NBR_TABLE_FIND_REMOVABLE
60 const linkaddr_t *NBR_TABLE_FIND_REMOVABLE(nbr_table_reason_t reason,
void *data);
65 typedef struct nbr_table_key {
66 struct nbr_table_key *next;
72 static uint8_t used_map[NBR_TABLE_MAX_NEIGHBORS];
74 static uint8_t locked_map[NBR_TABLE_MAX_NEIGHBORS];
76 #define MAX_NUM_TABLES 8
78 static struct nbr_table *all_tables[MAX_NUM_TABLES];
80 static unsigned num_tables;
83 MEMB(neighbor_addr_mem, nbr_table_key_t, NBR_TABLE_MAX_NEIGHBORS);
88 static nbr_table_key_t *
89 key_from_index(
int index)
91 return index != -1 ? &((nbr_table_key_t *)neighbor_addr_mem.mem)[index] :
NULL;
95 static nbr_table_item_t *
96 item_from_index(nbr_table_t *table,
int index)
98 return table !=
NULL && index != -1 ? (
char *)table->data + index * table->item_size :
NULL;
103 index_from_key(nbr_table_key_t *key)
105 return key !=
NULL ? key - (nbr_table_key_t *)neighbor_addr_mem.mem : -1;
110 index_from_item(nbr_table_t *table,
const nbr_table_item_t *item)
112 return table !=
NULL && item !=
NULL ? ((int)((
char *)item - (
char *)table->data)) / table->item_size : -1;
116 static nbr_table_item_t *
117 item_from_key(nbr_table_t *table, nbr_table_key_t *key)
119 return item_from_index(table, index_from_key(key));
123 static nbr_table_key_t *
124 key_from_item(nbr_table_t *table,
const nbr_table_item_t *item)
126 return key_from_index(index_from_item(table, item));
131 index_from_lladdr(
const linkaddr_t *lladdr)
133 nbr_table_key_t *key;
142 return index_from_key(key);
151 nbr_get_bit(uint8_t *bitmap, nbr_table_t *table, nbr_table_item_t *item)
153 int item_index = index_from_item(table, item);
154 if(table !=
NULL && item_index != -1) {
155 return (bitmap[item_index] & (1 << table->index)) != 0;
164 nbr_set_bit(uint8_t *bitmap, nbr_table_t *table, nbr_table_item_t *item,
int value)
166 int item_index = index_from_item(table, item);
168 if(table !=
NULL && item_index != -1) {
170 bitmap[item_index] |= 1 << table->index;
172 bitmap[item_index] &= ~(1 << table->index);
182 remove_key(nbr_table_key_t *least_used_key)
185 for(i = 0; i < MAX_NUM_TABLES; i++) {
186 if(all_tables[i] !=
NULL && all_tables[i]->callback !=
NULL) {
188 nbr_table_item_t *removed_item = item_from_key(all_tables[i], least_used_key);
189 if(nbr_get_bit(used_map, all_tables[i], removed_item) == 1) {
190 all_tables[i]->callback(removed_item);
195 used_map[index_from_key(least_used_key)] = 0;
200 static nbr_table_key_t *
201 nbr_table_allocate(nbr_table_reason_t reason,
void *data)
203 nbr_table_key_t *key;
204 int least_used_count = 0;
205 nbr_table_key_t *least_used_key =
NULL;
211 #ifdef NBR_TABLE_FIND_REMOVABLE
212 const linkaddr_t *lladdr;
213 lladdr = NBR_TABLE_FIND_REMOVABLE(reason, data);
216 PRINTF(
"*** Not removing entry to allocate new\n");
222 if((index = index_from_lladdr(lladdr)) != -1) {
223 least_used_key = key_from_index(index);
224 locked = locked_map[index];
227 if(least_used_key !=
NULL && locked) {
228 PRINTF(
"Deleting locked item!\n");
229 locked_map[index] = 0;
234 if(least_used_key ==
NULL) {
244 int item_index = index_from_key(key);
245 int locked = locked_map[item_index];
248 int used = used_map[item_index];
252 if((used & 1) == 1) {
258 if(least_used_key ==
NULL || used_count < least_used_count) {
259 least_used_key = key;
260 least_used_count = used_count;
261 if(used_count == 0) {
270 if(least_used_key ==
NULL) {
275 remove_key(least_used_key);
276 return least_used_key;
284 nbr_table_register(nbr_table_t *table, nbr_table_callback *callback)
293 if(num_tables < MAX_NUM_TABLES) {
294 table->index = num_tables++;
295 table->callback = callback;
296 all_tables[table->index] = table;
306 nbr_table_head(nbr_table_t *table)
309 nbr_table_item_t *item = item_from_key(table,
list_head(nbr_table_keys));
311 if(nbr_get_bit(used_map, table, item)) {
314 return nbr_table_next(table, item);
320 nbr_table_next(nbr_table_t *table, nbr_table_item_t *item)
323 void *key = key_from_item(table, item);
326 item = item_from_key(table, key);
327 }
while(item && !nbr_get_bit(used_map, table, item));
333 nbr_table_add_lladdr(nbr_table_t *table,
const linkaddr_t *lladdr, nbr_table_reason_t reason,
void *data)
336 nbr_table_item_t *item;
337 nbr_table_key_t *key;
345 if((index = index_from_lladdr(lladdr)) == -1) {
347 key = nbr_table_allocate(reason, data);
358 index = index_from_key(key);
365 item = item_from_index(table, index);
368 memset(item, 0, table->item_size);
369 nbr_set_bit(used_map, table, item, 1);
379 nbr_table_get_from_lladdr(nbr_table_t *table,
const linkaddr_t *lladdr)
381 void *item = item_from_index(table, index_from_lladdr(lladdr));
382 return nbr_get_bit(used_map, table, item) ? item :
NULL;
387 nbr_table_remove(nbr_table_t *table,
void *item)
389 int ret = nbr_set_bit(used_map, table, item, 0);
390 nbr_set_bit(locked_map, table, item, 0);
396 nbr_table_lock(nbr_table_t *table,
void *item)
399 int i = index_from_item(table, item);
400 PRINTF(
"*** Lock %d\n", i);
402 return nbr_set_bit(locked_map, table, item, 1);
407 nbr_table_unlock(nbr_table_t *table,
void *item)
410 int i = index_from_item(table, item);
411 PRINTF(
"*** Unlock %d\n", i);
413 return nbr_set_bit(locked_map, table, item, 0);
418 nbr_table_get_lladdr(nbr_table_t *table,
const void *item)
420 nbr_table_key_t *key = key_from_item(table, item);
421 return key !=
NULL ? &key->lladdr :
NULL;
426 nbr_table_update_lladdr(
const linkaddr_t *old_addr,
const linkaddr_t *new_addr,
427 int remove_if_duplicate)
431 nbr_table_key_t *key;
432 index = index_from_lladdr(old_addr);
437 if((new_index = index_from_lladdr(new_addr)) != -1) {
439 if(new_index == index) {
443 if(remove_if_duplicate) {
444 remove_key(key_from_index(index));
448 key = key_from_index(index);
453 memcpy(&key->lladdr, new_addr,
sizeof(linkaddr_t));
463 PRINTF(
"NBR TABLE:\n");
464 for(i = 0; i < NBR_TABLE_MAX_NEIGHBORS; i++) {
465 if(used_map[i] > 0) {
466 PRINTF(
" %02d %02d",i , key_from_index(i)->lladdr.u8[LINKADDR_SIZE - 1]);
467 for(j = 0; j < num_tables; j++) {
468 PRINTF(
" [%d:%d]", (used_map[i] & (1 << j)) != 0,
469 (locked_map[i] & (1 << j)) != 0);
477 handle_periodic_timer(
void *ptr)
void list_remove(list_t list, void *item)
Remove a specific element from a list.
#define LIST(name)
Declare a linked list.
#define MEMB(name, structure, num)
Declare a memory block.
void * list_item_next(void *item)
Get the next item following this item.
const linkaddr_t linkaddr_null
The null Rime address.
void * list_head(list_t list)
Get a pointer to the first element of a list.
Header file for the callback timer
#define NULL
The null pointer.
void list_add(list_t list, void *item)
Add an item at the end of a list.
#define CLOCK_SECOND
A second, measured in system clock time.
Linked list manipulation routines.
void ctimer_set(struct ctimer *c, clock_time_t t, void(*f)(void *), void *ptr)
Set a callback timer.
Memory block allocation routines.
int linkaddr_cmp(const linkaddr_t *addr1, const linkaddr_t *addr2)
Compare two Rime addresses.
void linkaddr_copy(linkaddr_t *dest, const linkaddr_t *src)
Copy a Rime address.
void ctimer_reset(struct ctimer *c)
Reset a callback timer with the same interval as was previously set.
void * memb_alloc(struct memb *m)
Allocate a memory block from a block of memory declared with MEMB().