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)
294 if(nbr_table_is_registered(table)) {
296 table->callback = callback;
300 if(num_tables < MAX_NUM_TABLES) {
301 table->index = num_tables++;
302 table->callback = callback;
303 all_tables[table->index] = table;
313 nbr_table_is_registered(nbr_table_t *table)
315 if(table != NULL && table->index >= 0 && table->index < MAX_NUM_TABLES
316 && all_tables[table->index] == table) {
324 nbr_table_head(nbr_table_t *table)
327 nbr_table_item_t *item = item_from_key(table,
list_head(nbr_table_keys));
329 if(nbr_get_bit(used_map, table, item)) {
332 return nbr_table_next(table, item);
338 nbr_table_next(nbr_table_t *table, nbr_table_item_t *item)
341 void *key = key_from_item(table, item);
344 item = item_from_key(table, key);
345 }
while(item && !nbr_get_bit(used_map, table, item));
351 nbr_table_add_lladdr(nbr_table_t *table,
const linkaddr_t *lladdr, nbr_table_reason_t reason,
void *data)
354 nbr_table_item_t *item;
355 nbr_table_key_t *key;
363 if((index = index_from_lladdr(lladdr)) == -1) {
365 key = nbr_table_allocate(reason, data);
376 index = index_from_key(key);
383 item = item_from_index(table, index);
386 memset(item, 0, table->item_size);
387 nbr_set_bit(used_map, table, item, 1);
397 nbr_table_get_from_lladdr(nbr_table_t *table,
const linkaddr_t *lladdr)
399 void *item = item_from_index(table, index_from_lladdr(lladdr));
400 return nbr_get_bit(used_map, table, item) ? item : NULL;
405 nbr_table_remove(nbr_table_t *table,
void *item)
407 int ret = nbr_set_bit(used_map, table, item, 0);
408 nbr_set_bit(locked_map, table, item, 0);
414 nbr_table_lock(nbr_table_t *table,
void *item)
417 int i = index_from_item(table, item);
418 PRINTF(
"*** Lock %d\n", i);
420 return nbr_set_bit(locked_map, table, item, 1);
425 nbr_table_unlock(nbr_table_t *table,
void *item)
428 int i = index_from_item(table, item);
429 PRINTF(
"*** Unlock %d\n", i);
431 return nbr_set_bit(locked_map, table, item, 0);
436 nbr_table_get_lladdr(nbr_table_t *table,
const void *item)
438 nbr_table_key_t *key = key_from_item(table, item);
439 return key != NULL ? &key->lladdr : NULL;
448 PRINTF(
"NBR TABLE:\n");
449 for(i = 0; i < NBR_TABLE_MAX_NEIGHBORS; i++) {
450 if(used_map[i] > 0) {
451 PRINTF(
" %02d %02d",i , key_from_index(i)->lladdr.u8[LINKADDR_SIZE - 1]);
452 for(j = 0; j < num_tables; j++) {
453 PRINTF(
" [%d:%d]", (used_map[i] & (1 << j)) != 0,
454 (locked_map[i] & (1 << j)) != 0);
462 handle_periodic_timer(
void *ptr)
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().
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.