routing-table.c (2499B)
1 #include <linux/if_ether.h> 2 /* #include <stdio.h> */ 3 /* #include <stdlib.h> */ 4 #include <string.h> 5 6 #include "finwo/mindex.h" 7 8 #include "config.h" 9 #include "routing-table.h" 10 11 static int rt_compare(const void *a, const void *b, void *udata) { 12 struct pmlag_rt_entry *ta = (struct pmlag_rt_entry *)a; 13 struct pmlag_rt_entry *tb = (struct pmlag_rt_entry *)b; 14 if (a == b) return 0; 15 return memcmp(ta->mac, tb->mac, ETH_ALEN); 16 } 17 18 static void rt_purge(void *item, void *udata) { 19 struct pmlag_rt_entry *rt_entry = (struct pmlag_rt_entry *)item; 20 if (!rt_entry) return; 21 if (rt_entry->iface) free(rt_entry->iface); 22 if (rt_entry->mac) free(rt_entry->mac); 23 free(rt_entry); 24 } 25 26 struct mindex_t * rt_init(void *udata) { 27 return mindex_init(rt_compare, rt_purge, udata); 28 } 29 30 int rt_upsert( 31 struct mindex_t *rt, 32 struct pmlag_iface *iface, 33 unsigned char *mac, 34 int16_t bcidx 35 ) { 36 struct pmlag_rt_entry *rt_entry; 37 int i, isnew = 0; 38 int iface_found = 0; 39 40 // Attempt to fetch the rt entry 41 rt_entry = mindex_get(rt, &((struct pmlag_rt_entry){ .mac = mac })); 42 43 // None given, build new one 44 if (!rt_entry) { 45 rt_entry = calloc(1, sizeof(struct pmlag_rt_entry)); 46 rt_entry->mac = malloc(ETH_ALEN); 47 rt_entry->bcidx = bcidx; 48 rt_entry->iface = calloc(iface->bond->iface_count, sizeof(struct pmlag_iface *)); 49 rt_entry->iface_count = 0; 50 memcpy(rt_entry->mac, mac, ETH_ALEN); 51 isnew = 1; 52 } 53 54 // Clear interface list if bcidx is different 55 if (rt_entry->bcidx != bcidx) { 56 rt_entry->iface_count = 0; 57 rt_entry->bcidx = bcidx; 58 } 59 60 // Register the interface on the rt_entry 61 for( i = 0 ; i < rt_entry->iface_count ; i++ ) { 62 if (rt_entry->iface[i] != iface) continue; 63 iface_found = 1; 64 break; 65 } 66 if (!iface_found) { 67 rt_entry->iface[rt_entry->iface_count] = iface; 68 rt_entry->iface_count++; 69 } 70 71 // The actual upsert part 72 if (isnew) { 73 mindex_set(rt, rt_entry); 74 // Keep rt size in check 75 if (rt->length > PMLAG_RT_MAX) { 76 mindex_delete(rt, mindex_rand(rt)); 77 } 78 } 79 80 return 0; 81 } 82 83 struct pmlag_iface * rt_find( 84 struct mindex_t *rt, 85 unsigned char *mac 86 ) { 87 struct pmlag_rt_entry *rt_entry; 88 89 // Attempt to fetch the rt entry 90 rt_entry = mindex_get(rt, &((struct pmlag_rt_entry){ .mac = mac })); 91 if (!rt_entry) return NULL; 92 93 // Unlock the routing table again 94 struct pmlag_iface *iface = rt_entry->iface[rand() % rt_entry->iface_count]; 95 return iface; 96 }