diff --git a/filter/filter.c b/filter/filter.c index 49b67391..a06fe5bf 100644 --- a/filter/filter.c +++ b/filter/filter.c @@ -833,7 +833,7 @@ interpret(struct f_inst *what) case T_STRING: /* Warning: this is a special case for proto attribute */ res.val.s = rta->proto->name; break; - case T_PREFIX: /* Warning: this works only for prefix of network */ + case T_PREFIX: /* Warning: this works only for RT_IP prefix of network */ { res.val.px.ip = (*f_rte)->net->n.prefix; res.val.px.len = (*f_rte)->net->n.pxlen; diff --git a/lib/ip.c b/lib/ip.c index 3c959fea..95a01f91 100644 --- a/lib/ip.c +++ b/lib/ip.c @@ -349,7 +349,23 @@ ip_scope_text(unsigned scope) return scope_table[scope]; } +#include "nest/route.h" +void +fn_print(char *buf, int buflen, struct fib_node *n) +{ + // XXXX temporary + switch (n->addr_type) + { + case RT_IPV4: + case RT_IPV6: + bsprintf(buf, "%I/%d", n->prefix, n->pxlen); + break; + default: + bsprintf(buf, "???"); + break; + } +} #if 0 diff --git a/lib/ip.h b/lib/ip.h index 706bbcf5..6ddd1620 100644 --- a/lib/ip.h +++ b/lib/ip.h @@ -390,6 +390,8 @@ static inline int ipa_classify_net(ip_addr a) #define STD_ADDRESS_P_LENGTH 39 #define SIZE_OF_IP_HEADER 40 +#define MAX_ADDRESS_P_LENGTH 40 + #define ipa_class_mask(x) _MI4(ipv4_class_mask(_I(x))) @@ -402,6 +404,8 @@ static inline int ipa_classify_net(ip_addr a) u32 ipv4_class_mask(u32); byte *ipv4_skip_header(byte *, int *); +struct fib_node; +void fn_print(char *buf, int buflen, struct fib_node *n); diff --git a/lib/printf.c b/lib/printf.c index 562844b3..488d5ffb 100644 --- a/lib/printf.c +++ b/lib/printf.c @@ -139,7 +139,7 @@ int bvsnprintf(char *buf, int size, const char *fmt, va_list args) u32 x; char *str, *start; const char *s; - char ipbuf[STD_ADDRESS_P_LENGTH+1]; + char ipbuf[MAX_ADDRESS_P_LENGTH]; struct iface *iface; int flags; /* flags to number() */ @@ -298,6 +298,12 @@ int bvsnprintf(char *buf, int size, const char *fmt, va_list args) s = iface->name; goto str; + /* Generic address - pointer to fib_node */ + case 'F': // XXXX probably remove/replace + fn_print(ipbuf, sizeof(ipbuf), va_arg(args, struct fib_node *)); + s = ipbuf; + goto str; + /* Router/Network ID - essentially IPv4 address in u32 value */ case 'R': x = va_arg(args, u32); diff --git a/lib/unaligned.h b/lib/unaligned.h index 1f418cd9..62bf7c75 100644 --- a/lib/unaligned.h +++ b/lib/unaligned.h @@ -36,6 +36,16 @@ get_u32(void *p) return ntohl(x); } +static inline u64 +get_u64(void *p) +{ + u32 xh, xl; + memcpy(&xh, p, 4); + memcpy(&xl, p+4, 4); + return (((u64) ntohl(xh)) << 32) | ntohl(xl); +} + + static inline void put_u16(void *p, u16 x) { @@ -50,4 +60,15 @@ put_u32(void *p, u32 x) memcpy(p, &x, 4); } + +static inline void +put_u64(void *p, u64 x) +{ + u32 xh, xl; + xh = htonl(x >> 32); + xl = htonl((u32) x); + memcpy(p, &xh, 4); + memcpy(p+4, &xl, 4); +} + #endif diff --git a/nest/config.Y b/nest/config.Y index 420f0213..39cb504e 100644 --- a/nest/config.Y +++ b/nest/config.Y @@ -108,7 +108,7 @@ listen_opt: CF_ADDTO(conf, newtab) newtab: TABLE SYM { - rt_new_table($2); + rt_new_table($2, RT_IP); } ; diff --git a/nest/route.h b/nest/route.h index 34536609..e560acf5 100644 --- a/nest/route.h +++ b/nest/route.h @@ -37,9 +37,10 @@ struct fib_node { struct fib_iterator *readers; /* List of readers of this node */ byte pxlen; byte flags; /* User-defined */ - byte x0, x1; /* User-defined */ + byte addr_type; /* User-defined */ + byte addr_off; /* address data offset */ u32 uid; /* Unique ID based on hash */ - ip_addr prefix; /* In host order */ + ip_addr prefix; /* Address data in host order (if it fits in ip_addr length) */ }; struct fib_iterator { /* See lib/slists.h for an explanation */ @@ -50,7 +51,9 @@ struct fib_iterator { /* See lib/slists.h for an explanation */ unsigned int hash; }; +struct fib; typedef void (*fib_init_func)(struct fib_node *); +typedef u32 (*fib_hash_func)(struct fib *, void *); struct fib { pool *fib_pool; /* Pool holding all our data */ @@ -59,23 +62,38 @@ struct fib { unsigned int hash_size; /* Number of hash table entries (a power of two) */ unsigned int hash_order; /* Binary logarithm of hash_size */ unsigned int hash_shift; /* 16 - hash_log */ + unsigned int addr_type; /* Type of adresses stored in fib (IPv46, VPNv46, MPLS, etc..)*/ + unsigned int addr_size; /* Size of address data */ + unsigned int addr_off; /* Address data offset from the structure beginning */ unsigned int entries; /* Number of entries */ unsigned int entries_min, entries_max;/* Entry count limits (else start rehashing) */ fib_init_func init; /* Constructor */ + fib_hash_func hash_f; /* Optional hash function */ }; void fib_init(struct fib *, pool *, unsigned node_size, unsigned hash_order, fib_init_func init); -void *fib_find(struct fib *, ip_addr *, int); /* Find or return NULL if doesn't exist */ -void *fib_get(struct fib *, ip_addr *, int); /* Find or create new if nonexistent */ -void *fib_route(struct fib *, ip_addr, int); /* Longest-match routing lookup */ +void fib2_init(struct fib *, pool *, unsigned node_size, unsigned int addr_type, unsigned int addr_size, \ + unsigned hash_order, fib_init_func init, fib_hash_func hash_f); +void *fib_find(struct fib *, void *, int); /* Find or return NULL if doesn't exist */ +void *fib_get(struct fib *, void *, int); /* Find or create new if nonexistent */ +void *fib_route(struct fib *, ip_addr *, int); /* Longest-match routing lookup */ void fib_delete(struct fib *, void *); /* Remove fib entry */ void fib_free(struct fib *); /* Destroy the fib */ void fib_check(struct fib *); /* Consistency check for debugging */ +u32 ip_hash(struct fib *f, void *a); /* Hashing function for RT_IP fib types */ +// u32 vpn_hash(struct fib *f, void *a); /* Hashing function for RT_VPN fib types */ void fit_init(struct fib_iterator *, struct fib *); /* Internal functions, don't call */ struct fib_node *fit_get(struct fib *, struct fib_iterator *); void fit_put(struct fib_iterator *, struct fib_node *); +#define fib_hash(f, a) (f)->hash_f(f, a) + +#define FPREFIX(n) ((void *)(((char *)(n)) + (n)->addr_off)) +#define FPREFIX_IP(n) (&(n)->prefix) +// XXXX define FPREFIX_VPN(n) ((vpn_addr *)FPREFIX(n)) +#define PROTO_FIB(x) ((x)->table->fib.addr_type) + #define FIB_WALK(fib, z) do { \ struct fib_node *z, **ff = (fib)->hash_table; \ unsigned int count = (fib)->hash_size; \ @@ -117,6 +135,7 @@ void fit_put(struct fib_iterator *, struct fib_node *); struct rtable_config { node n; char *name; + int addr_type; /* Type of address data stored in table (IPv46, VPNv46, etc..) */ struct rtable *table; struct proto_config *krt_attached; /* Kernel syncer attached to this table */ int gc_max_ops; /* Maximum number of operations before GC is run */ @@ -127,6 +146,7 @@ typedef struct rtable { node n; /* Node in list of all tables */ struct fib fib; char *name; /* Name of this table */ + int addr_type; /* Type of address data stored in table (IPv46, VPNv46, etc..) */ list hooks; /* List of announcement hooks */ int pipe_busy; /* Pipe loop detection */ int use_count; /* Number of protocols using this table */ @@ -221,9 +241,29 @@ typedef struct rte { #define REF_COW 1 /* Copy this rte on write */ +/* Types of routing tables/entries */ +#define RT_IPV4 1 +#define RT_IPV6 2 +#define RT_VPN4 3 +#define RT_VPN6 4 +#define RT_MPLS 5 + +#define RT_MAX 6 + +/* Same tables using bit positions. Used for appropriate table linking on protocol init */ +#define RTB_IPV4 (1 << RT_IPV4) +#define RTB_IPV6 (1 << RT_IPV6) +#define RTB_VPN4 (1 << RT_VPN4) +#define RTB_VPN6 (1 << RT_VPN6) +#define RTB_MPLS (1 << RT_MPLS) + +#define RT_IP RT_IPV6 +#define RTB_IP RTB_IPV6 + + /* Types of route announcement, also used as flags */ -#define RA_OPTIMAL 1 /* Announcement of optimal route change */ -#define RA_ANY 2 /* Announcement of any route change */ +#define RA_OPTIMAL 1 /* Announcement of optimal route change */ +#define RA_ANY 2 /* Announcement of any route change */ struct config; @@ -250,7 +290,9 @@ int rt_feed_baby(struct proto *p); void rt_feed_baby_abort(struct proto *p); void rt_schedule_prune_all(void); int rt_prune_loop(void); -struct rtable_config *rt_new_table(struct symbol *s); +struct rtable_config *rt_new_table(struct symbol *s, int addr_type); +int rt_addrsize(int addr_type); // XXXX needed? + struct rt_show_data { ip_addr prefix; diff --git a/nest/rt-fib.c b/nest/rt-fib.c index 510aa76b..9959f304 100644 --- a/nest/rt-fib.c +++ b/nest/rt-fib.c @@ -72,10 +72,10 @@ fib_ht_free(struct fib_node **h) mb_free(h); } -static inline unsigned -fib_hash(struct fib *f, ip_addr *a) +u32 +ip_hash(struct fib *f, void *a) { - return ipa_hash(*a) >> f->hash_shift; + return ipa_hash(*((ip_addr *)a)) >> f->hash_shift; } static void @@ -97,17 +97,53 @@ fib_dummy_init(struct fib_node *dummy UNUSED) */ void fib_init(struct fib *f, pool *p, unsigned node_size, unsigned hash_order, fib_init_func init) +{ + fib2_init(f, p, node_size, RT_IP, sizeof(ip_addr), hash_order, init, ip_hash); +} + +/** + * fib2_init - initialize a new FIB + * @f: the FIB to be initialized (the structure itself being allocated by the caller) + * @p: pool to allocate the nodes in + * @node_size: total node size to be used (each node consists of a standard header &fib_node + * followed by user data) + * @addr_type: type of addresses stored in fib (RT_*) + * @addr_size: size of address data + * @hash_order: initial hash order (a binary logarithm of hash table size), 0 to use default order + * (recommended) + * @init: pointer a function to be called to initialize a newly created node + * @hash_p: mandatory pointer a function to be called to hash node + * + * This function initializes a newly allocated FIB and prepares it for use. Note node_size + * cannot exceed 255 bytes for address types not fitting into ip_addr + */ +void +fib2_init(struct fib *f, pool *p, unsigned node_size, unsigned int addr_type, unsigned int addr_size, \ + unsigned hash_order, fib_init_func init, fib_hash_func hash_f) { if (!hash_order) hash_order = HASH_DEF_ORDER; f->fib_pool = p; + if (addr_size > sizeof(ip_addr)) + { + node_size = BIRD_ALIGN(node_size, CPU_STRUCT_ALIGN); + f->addr_off = node_size; + + node_size += addr_size; + } + else + f->addr_off = OFFSETOF(struct fib_node, prefix); + f->fib_slab = sl_new(p, node_size); f->hash_order = hash_order; fib_ht_alloc(f); bzero(f->hash_table, f->hash_size * sizeof(struct fib_node *)); + f->addr_type = addr_type; + f->addr_size = addr_size; f->entries = 0; f->entries_min = 0; f->init = init ? : fib_dummy_init; + f->hash_f = hash_f; } static void @@ -133,7 +169,7 @@ fib_rehash(struct fib *f, int step) while (e = x) { x = e->next; - nh = fib_hash(f, &e->prefix); + nh = fib_hash(f, FPREFIX(e)); while (nh > ni) { *t = NULL; @@ -163,11 +199,11 @@ fib_rehash(struct fib *f, int step) * a pointer to it or %NULL if no such node exists. */ void * -fib_find(struct fib *f, ip_addr *a, int len) +fib_find(struct fib *f, void *a, int len) { struct fib_node *e = f->hash_table[fib_hash(f, a)]; - while (e && (e->pxlen != len || !ipa_equal(*a, e->prefix))) + while (e && (e->pxlen != len || memcmp(a, FPREFIX(e), f->addr_size))) e = e->next; return e; } @@ -197,26 +233,26 @@ fib_histogram(struct fib *f) /** * fib_get - find or create a FIB node * @f: FIB to work with - * @a: pointer to IP address of the prefix - * @len: prefix length + * @a: pointer to IP (or other family) address of the prefix + * @len: prefix length (if address family requires it) * * Search for a FIB node corresponding to the given prefix and * return a pointer to it. If no such node exists, create it. */ void * -fib_get(struct fib *f, ip_addr *a, int len) +fib_get(struct fib *f, void *a, int len) { - unsigned int h = ipa_hash(*a); - struct fib_node **ee = f->hash_table + (h >> f->hash_shift); + unsigned int h = fib_hash(f, a); + struct fib_node **ee = f->hash_table + h; struct fib_node *g, *e = *ee; - u32 uid = h << 16; + u32 uid = h << (16 + f->hash_shift); - while (e && (e->pxlen != len || !ipa_equal(*a, e->prefix))) + while (e && (e->pxlen != len || memcmp(a, FPREFIX(e), f->addr_size))) e = e->next; if (e) return e; #ifdef DEBUGGING - if (len < 0 || len > BITS_PER_IP_ADDRESS || !ip_is_prefix(*a,len)) + if ((f->addr_type == RT_IP) && (len < 0 || len > BITS_PER_IP_ADDRESS || !ip_is_prefix(*((ip_addr *)a),len))) bug("fib_get() called for invalid address"); #endif @@ -228,13 +264,15 @@ fib_get(struct fib *f, ip_addr *a, int len) uid++; } - if ((uid >> 16) != h) + if ((uid >> (16 + f->hash_shift)) != h) log(L_ERR "FIB hash table chains are too long"); // log (L_WARN "FIB_GET %I %x %x", *a, h, uid); e = sl_alloc(f->fib_slab); - e->prefix = *a; + e->addr_type = f->addr_type; + e->addr_off = f->addr_off; + memcpy(FPREFIX(e), a, f->addr_size); e->pxlen = len; e->next = *ee; e->uid = uid; @@ -250,22 +288,25 @@ fib_get(struct fib *f, ip_addr *a, int len) /** * fib_route - CIDR routing lookup * @f: FIB to search in - * @a: pointer to IP address of the prefix - * @len: prefix length + * @a: pointer to IP (or other family) address of the prefix + * @len: prefix length (if address family requires) * * Search for a FIB node with longest prefix matching the given * network, that is a node which a CIDR router would use for routing - * that network. + * that network. Function should be called for IPv4/IPv6 routes only */ void * -fib_route(struct fib *f, ip_addr a, int len) +fib_route(struct fib *f, ip_addr *a, int len) { ip_addr a0; void *t; + if (f->addr_type != RT_IP) + return NULL; + while (len >= 0) { - a0 = ipa_and(a, ipa_mkmask(len)); + a0 = ipa_and(*a, ipa_mkmask(len)); t = fib_find(f, &a0, len); if (t) return t; @@ -321,7 +362,7 @@ void fib_delete(struct fib *f, void *E) { struct fib_node *e = E; - unsigned int h = fib_hash(f, &e->prefix); + unsigned int h = fib_hash(f, FPREFIX(e)); struct fib_node **ee = f->hash_table + h; struct fib_iterator *it; @@ -413,7 +454,7 @@ fit_get(struct fib *f, struct fib_iterator *i) if (k = i->next) k->prev = j; j->next = k; - i->hash = fib_hash(f, &n->prefix); + i->hash = fib_hash(f, FPREFIX(n)); return n; } @@ -452,7 +493,7 @@ fib_check(struct fib *f) for(n=f->hash_table[i]; n; n=n->next) { struct fib_iterator *j, *j0; - unsigned int h0 = ipa_hash(n->prefix); + unsigned int h0 = fib_hash(f, FPREFIX(n)); if (h0 < lo) bug("fib_check: discord in hash chains"); lo = h0; @@ -491,14 +532,15 @@ void dump(char *m) { unsigned int i; - debug("%s ... order=%d, size=%d, entries=%d\n", m, f.hash_order, f.hash_size, f.hash_size); + debug("%s ... type=%d order=%d, size=%d, entries=%d\n", m, f.addr_type, f.hash_order, f.hash_size, f.hash_size); for(i=0; inext) { - debug("%04x %04x %p %I/%2d", i, ipa_hash(n->prefix), n, n->prefix, n->pxlen); + debug("%04x %04x %p %s", i, fib_hash(&f, FPREFIX(n)) << f->hash_shift, n, fn_print(&f, n)); + for(j=n->readers; j; j=j->next) debug(" %p[%p]", j, j->node); debug("\n"); diff --git a/nest/rt-table.c b/nest/rt-table.c index fdc767e7..5fcfc6c1 100644 --- a/nest/rt-table.c +++ b/nest/rt-table.c @@ -65,6 +65,9 @@ net_route(rtable *tab, ip_addr a, int len) ip_addr a0; net *n; + if (tab->fib.addr_type != RT_IP) + return NULL; + while (len >= 0) { a0 = ipa_and(a, ipa_mkmask(len)); @@ -165,7 +168,7 @@ rte_trace(struct proto *p, rte *e, int dir, char *msg) byte via[STD_ADDRESS_P_LENGTH+32]; rt_format_via(e, via); - log(L_TRACE "%s %c %s %I/%d %s", p->name, dir, msg, e->net->n.prefix, e->net->n.pxlen, via); + log(L_TRACE "%s %c %s %F %s", p->name, dir, msg, &e->net->n, via); } static inline void @@ -416,18 +419,22 @@ rte_validate(rte *e) int c; net *n = e->net; - if ((n->n.pxlen > BITS_PER_IP_ADDRESS) || !ip_is_prefix(n->n.prefix,n->n.pxlen)) + // XXXX: Do not bother checking non-IP routes at the moment + if (n->n.addr_type != RT_IP) + return 1; + + if ((n->n.pxlen > BITS_PER_IP_ADDRESS) || !ip_is_prefix(*FPREFIX_IP(&n->n),n->n.pxlen)) { - log(L_WARN "Ignoring bogus prefix %I/%d received via %s", - n->n.prefix, n->n.pxlen, e->sender->proto->name); + log(L_WARN "Ignoring bogus prefix %F received via %s", + &n->n, e->sender->proto->name); return 0; } - c = ipa_classify_net(n->n.prefix); + c = ipa_classify_net(*FPREFIX_IP(&n->n)); if ((c < 0) || !(c & IADDR_HOST) || ((c & IADDR_SCOPE_MASK) <= SCOPE_LINK)) { - log(L_WARN "Ignoring bogus route %I/%d received via %s", - n->n.prefix, n->n.pxlen, e->sender->proto->name); + log(L_WARN "Ignoring bogus route %F received via %s", + &n->n, e->sender->proto->name); return 0; } @@ -494,8 +501,8 @@ rte_recalculate(struct announce_hook *ah, net *net, rte *new, ea_list *tmpa, str { if (new) { - log(L_ERR "Pipe collision detected when sending %I/%d to table %s", - net->n.prefix, net->n.pxlen, table->name); + log(L_ERR "Pipe collision detected when sending %F to table %s", + &net->n, table->name); rte_free_quick(new); } return; @@ -820,7 +827,7 @@ rt_dump(rtable *t) net *n; struct announce_hook *a; - debug("Dump of routing table <%s>\n", t->name); + debug("Dump of routing table <%s>:%d\n", t->name, t->fib.addr_type); #ifdef DEBUGGING fib_check(&t->fib); #endif @@ -927,11 +934,66 @@ rt_event(void *ptr) rt_prune_nets(tab); } +/** + * rt_addrsize - returns (host format) size of address of given type + * @addr_type: address type + * + * Returns sizeof() appropriate structure or sizeof(ip_addr) if + * address type is unknown + * + */ +int +rt_addrsize(int addr_type) +{ + switch (addr_type) + { +#ifdef MPLS_VPN + case RT_VPNV4: + return sizeof(vpn4_addr); + case RT_VPNV6: + return sizeof(vpn6_addr); +#endif + case RT_IPV4: + return sizeof(ip4_addr); + case RT_IPV6: + return sizeof(ip6_addr); + } + + return sizeof(ip_addr); +} + + +/** + * rt_setup - initialize routing table + * + * This function is called to set up rtable (hooks, lists, fib, ..) + */ void rt_setup(pool *p, rtable *t, char *name, struct rtable_config *cf) { + fib_hash_func f; + bzero(t, sizeof(*t)); - fib_init(&t->fib, p, sizeof(net), 0, rte_init); + t->addr_type = cf ? cf->addr_type : RT_IP; + /* Select hashing function depending on table type */ + switch (t->addr_type) + { + case RT_IP: + f = ip_hash; + break; + +#ifdef XXXX + case RT_VPN: + f = vpn_hash; + break; +#endif + + default: + f = ip_hash; + break; + } + + fib2_init(&t->fib, p, sizeof(net), t->addr_type, rt_addrsize(t->addr_type), 0, rte_init, f); t->name = name; t->config = cf; init_list(&t->hooks); @@ -1058,7 +1120,7 @@ rt_preconfig(struct config *c) struct symbol *s = cf_find_symbol("master"); init_list(&c->tables); - c->master_rtc = rt_new_table(s); + c->master_rtc = rt_new_table(s, RT_IP); } @@ -1212,12 +1274,13 @@ rt_next_hop_update(rtable *tab) struct rtable_config * -rt_new_table(struct symbol *s) +rt_new_table(struct symbol *s, int addr_type) { struct rtable_config *c = cfg_allocz(sizeof(struct rtable_config)); cf_define_symbol(s, SYM_TABLE, c); c->name = s->name; + c->addr_type = addr_type; add_tail(&new_config->tables, &c->n); c->gc_max_ops = 1000; c->gc_min_time = 5; @@ -1575,7 +1638,7 @@ rt_notify_hostcache(rtable *tab, net *net) if (tab->hcu_scheduled) return; - if (trie_match_prefix(hc->trie, net->n.prefix, net->n.pxlen)) + if (trie_match_prefix(hc->trie, *FPREFIX_IP(&net->n), net->n.pxlen)) rt_schedule_hcu(tab); } @@ -1626,6 +1689,8 @@ rt_update_hostentry(rtable *tab, struct hostentry *he) rta *old_src = he->src; int pxlen = 0; + /* XXXX: check for non-IP address families ? */ + /* Reset the hostentry */ he->src = NULL; he->gw = IPA_NONE; @@ -1641,8 +1706,8 @@ rt_update_hostentry(rtable *tab, struct hostentry *he) if (a->hostentry) { /* Recursive route should not depend on another recursive route */ - log(L_WARN "Next hop address %I resolvable through recursive route for %I/%d", - he->addr, n->n.prefix, pxlen); + log(L_WARN "Next hop address %I resolvable through recursive route for %F", + he->addr, &n->n); goto done; } @@ -1725,9 +1790,23 @@ rt_find_hostentry(rtable *tab, ip_addr a, ip_addr ll, rtable *dep) return he; } +/** + * rta_set_recursive_next_hop - notify table about recursive nexthop + * @dep: table with non-directly reachable route + * @a: pointer to route attributes + * @tab: table where nexthop should be resolved + * @gw: nexthop to resolve + * @ll: link-local nexthop address (IPv6 case) + * + * Search for a FIB node corresponding to the given prefix and + * return a pointer to it. If no such node exists, create it. + */ void rta_set_recursive_next_hop(rtable *dep, rta *a, rtable *tab, ip_addr *gw, ip_addr *ll) { + if (tab->addr_type != RT_IP) + return; + rta_apply_hostentry(a, rt_find_hostentry(tab, *gw, *ll, dep)); } @@ -1753,7 +1832,7 @@ rt_format_via(rte *e, byte *via) } static void -rt_show_rte(struct cli *c, byte *ia, rte *e, struct rt_show_data *d, ea_list *tmpa) +rt_show_rte(struct cli *c, byte *prefix, rte *e, struct rt_show_data *d, ea_list *tmpa) { byte via[STD_ADDRESS_P_LENGTH+32], from[STD_ADDRESS_P_LENGTH+8]; byte tm[TM_DATETIME_BUFFER_SIZE], info[256]; @@ -1781,7 +1860,7 @@ rt_show_rte(struct cli *c, byte *ia, rte *e, struct rt_show_data *d, ea_list *tm a->proto->proto->get_route_info(e, info, tmpa); else bsprintf(info, " (%d)", e->pref); - cli_printf(c, -1007, "%-18s %s [%s %s%s]%s%s", ia, via, a->proto->name, + cli_printf(c, -1007, "%-18s %s [%s %s%s]%s%s", prefix, via, a->proto->name, tm, from, primary ? (sync_error ? " !" : " *") : "", info); for (nh = a->nexthops; nh; nh = nh->next) cli_printf(c, -1007, "\tvia %I on %s weight %d", nh->gw, nh->iface->name, nh->weight + 1); @@ -1793,11 +1872,11 @@ static void rt_show_net(struct cli *c, net *n, struct rt_show_data *d) { rte *e, *ee; - byte ia[STD_ADDRESS_P_LENGTH+8]; + byte prefix[MAX_ADDRESS_P_LENGTH]; struct announce_hook *a; int ok; - bsprintf(ia, "%I/%d", n->n.prefix, n->n.pxlen); + fn_print(prefix, sizeof(prefix), &n->n); if (n->routes) d->net_counter++; for(e=n->routes; e; e=e->next) @@ -1833,8 +1912,8 @@ rt_show_net(struct cli *c, net *n, struct rt_show_data *d) { d->show_counter++; if (d->stats < 2) - rt_show_rte(c, ia, e, d, tmpa); - ia[0] = 0; + rt_show_rte(c, prefix, e, d, tmpa); + prefix[0] = '\0'; } if (e != ee) { @@ -1927,6 +2006,7 @@ rt_show(struct rt_show_data *d) } } + /* * Documentation for functions declared inline in route.h */ diff --git a/proto/bgp/attrs.c b/proto/bgp/attrs.c index 4495c039..329bd4f0 100644 --- a/proto/bgp/attrs.c +++ b/proto/bgp/attrs.c @@ -841,7 +841,7 @@ bgp_get_bucket(struct bgp_proto *p, net *n, ea_list *attrs, int originate) for(i=0; ip.name, bgp_attr_table[bgp_mandatory_attrs[i]].name, n->n.prefix, n->n.pxlen); + log(L_ERR "%s: Mandatory attribute %s missing in route %F", p->p.name, bgp_attr_table[bgp_mandatory_attrs[i]].name, &n->n); return NULL; } @@ -849,7 +849,7 @@ bgp_get_bucket(struct bgp_proto *p, net *n, ea_list *attrs, int originate) a = ea_find(new, EA_CODE(EAP_BGP, BA_NEXT_HOP)); if (!a || ipa_equal(p->cf->remote_ip, *(ip_addr *)a->u.ptr->data)) { - log(L_ERR "%s: Invalid NEXT_HOP attribute in route %I/%d", p->p.name, n->n.prefix, n->n.pxlen); + log(L_ERR "%s: Invalid NEXT_HOP attribute in route %F", p->p.name, &n->n); return NULL; } @@ -893,7 +893,7 @@ bgp_rt_notify(struct proto *P, rtable *tbl UNUSED, net *n, rte *new, rte *old UN init_list(&buck->prefixes); } } - px = fib_get(&p->prefix_fib, &n->n.prefix, n->n.pxlen); + px = fib_get(&p->prefix_fib, FPREFIX(&n->n), n->n.pxlen); if (px->bucket_node.next) { DBG("\tRemoving old entry.\n"); diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c index cfa37fb5..300930b9 100644 --- a/proto/bgp/packets.c +++ b/proto/bgp/packets.c @@ -222,10 +222,10 @@ bgp_encode_prefixes(struct bgp_proto *p, byte *w, struct bgp_bucket *buck, unsig while (!EMPTY_LIST(buck->prefixes) && remains >= (1+sizeof(ip_addr))) { struct bgp_prefix *px = SKIP_BACK(struct bgp_prefix, bucket_node, HEAD(buck->prefixes)); - DBG("\tDequeued route %I/%d\n", px->n.prefix, px->n.pxlen); + DBG("\tDequeued route %F\n", &px->n); *w++ = px->n.pxlen; bytes = (px->n.pxlen + 7) / 8; - a = px->n.prefix; + a = *FPREFIX_IP(&px->n); ipa_hton(a); memcpy(w, &a, bytes); w += bytes; @@ -242,7 +242,7 @@ bgp_flush_prefixes(struct bgp_proto *p, struct bgp_bucket *buck) while (!EMPTY_LIST(buck->prefixes)) { struct bgp_prefix *px = SKIP_BACK(struct bgp_prefix, bucket_node, HEAD(buck->prefixes)); - log(L_ERR "%s: - route %I/%d skipped", p->p.name, px->n.prefix, px->n.pxlen); + log(L_ERR "%s: - route %F skipped", p->p.name, &px->n); rem_node(&px->bucket_node); fib_delete(&p->prefix_fib, px); } diff --git a/proto/ospf/ospf.c b/proto/ospf/ospf.c index ef7b0363..44dd7fef 100644 --- a/proto/ospf/ospf.c +++ b/proto/ospf/ospf.c @@ -572,10 +572,10 @@ ospf_rt_notify(struct proto *p, rtable *tbl UNUSED, net * n, rte * new, rte * ol if (!new) { - if (fn->x1 != EXT_EXPORT) + if (! (fn->flags & OSPF_RT_EXPORT)) return; - flush_ext_lsa(oa, fn); + flush_ext_lsa(oa, fn, 1); /* Old external route might blocked some NSSA translation */ if (po->areano > 1) diff --git a/proto/ospf/rt.c b/proto/ospf/rt.c index 42c54dfd..4ef8f416 100644 --- a/proto/ospf/rt.c +++ b/proto/ospf/rt.c @@ -33,7 +33,7 @@ ospf_rt_initort(struct fib_node *fn) ort *ri = (ort *) fn; reset_ri(ri); ri->old_rta = NULL; - ri->fn.x0 = ri->fn.x1 = 0; + ri->fn.flags = 0; } static inline int @@ -921,7 +921,7 @@ decide_sum_lsa(struct ospf_area *oa, ort *nf, int dest) return 1; struct area_net *anet = (struct area_net *) - fib_route(&nf->n.oa->net_fib, nf->fn.prefix, nf->fn.pxlen); + fib_route(&nf->n.oa->net_fib, &nf->fn.prefix, nf->fn.pxlen); /* Condensed area network found */ if (anet) @@ -938,7 +938,7 @@ check_sum_net_lsa(struct proto_ospf *po, ort *nf) struct ospf_area *anet_oa = NULL; /* RT entry marked as area network */ - if (nf->fn.x0) + if (nf->fn.flags & OSPF_RT_PERSISTENT) { /* It is a default route for stub areas, handled entirely in ospf_rt_abr() */ if (nf->fn.pxlen == 0) @@ -989,7 +989,7 @@ decide_nssa_lsa(ort *nf, u32 *rt_metric, ip_addr *rt_fwaddr, u32 *rt_tag) return 0; /* Condensed area network found */ - if (fib_route(&oa->enet_fib, nf->fn.prefix, nf->fn.pxlen)) + if (fib_route(&oa->enet_fib, &nf->fn.prefix, nf->fn.pxlen)) return 0; if (!en || (en->lsa.type != LSA_T_NSSA)) @@ -1042,11 +1042,11 @@ check_nssa_lsa(struct proto_ospf *po, ort *nf) ip_addr rt_fwaddr; /* Do not translate LSA if there is already the external LSA from route export */ - if (fn->x1 == EXT_EXPORT) + if (fn->flags & OSPF_RT_EXPORT) return; /* RT entry marked as area network */ - if (fn->x0) + if (fn->flags & OSPF_RT_PERSISTENT) { /* Find that area network */ WALK_LIST(oa, po->area_list) @@ -1065,8 +1065,8 @@ check_nssa_lsa(struct proto_ospf *po, ort *nf) else if (decide_nssa_lsa(nf, &rt_metric, &rt_fwaddr, &rt_tag)) originate_ext_lsa(po->backbone, fn, EXT_NSSA, rt_metric, rt_fwaddr, rt_tag, 0); - else if (fn->x1 == EXT_NSSA) - flush_ext_lsa(po->backbone, fn); + else if (fn->flags & OSPF_RT_NSSA) + flush_ext_lsa(po->backbone, fn, 1); } /* RFC 2328 16.7. p2 - find new/lost vlink endpoints */ @@ -1140,7 +1140,7 @@ ospf_rt_abr1(struct proto_ospf *po) /* Compute condensed area networks */ if (nf->n.type == RTS_OSPF) { - anet = (struct area_net *) fib_route(&nf->n.oa->net_fib, nf->fn.prefix, nf->fn.pxlen); + anet = (struct area_net *) fib_route(&nf->n.oa->net_fib, &nf->fn.prefix, nf->fn.pxlen); if (anet) { if (!anet->active) @@ -1149,7 +1149,7 @@ ospf_rt_abr1(struct proto_ospf *po) /* Get a RT entry and mark it to know that it is an area network */ ort *nfi = (ort *) fib_get(&po->rtf, &anet->fn.prefix, anet->fn.pxlen); - nfi->fn.x0 = 1; /* mark and keep persistent, to have stable UID */ + nfi->fn.flags |= OSPF_RT_PERSISTENT; /* mark persistent, to have stable UID */ /* 16.2. (3) */ if (nfi->n.type == RTS_OSPF_IA) @@ -1165,7 +1165,7 @@ ospf_rt_abr1(struct proto_ospf *po) ip_addr addr = IPA_NONE; default_nf = (ort *) fib_get(&po->rtf, &addr, 0); - default_nf->fn.x0 = 1; /* keep persistent */ + default_nf->fn.flags |= OSPF_RT_PERSISTENT; /* keep persistent */ struct ospf_area *oa; WALK_LIST(oa, po->area_list) @@ -1189,7 +1189,7 @@ ospf_rt_abr1(struct proto_ospf *po) if (oa_is_nssa(oa) && oa->ac->default_nssa) originate_ext_lsa(oa, &default_nf->fn, 0, oa->ac->default_cost, IPA_NONE, 0, 0); else - flush_ext_lsa(oa, &default_nf->fn); + flush_ext_lsa(oa, &default_nf->fn, 0); /* RFC 2328 16.4. (3) - precompute preferred ASBR entries */ @@ -1301,7 +1301,7 @@ ospf_rt_abr2(struct proto_ospf *po) if (rt_is_nssa(nf) && (nf->n.options & ORTA_PROP)) { struct area_net *anet = (struct area_net *) - fib_route(&nf->n.oa->enet_fib, nf->fn.prefix, nf->fn.pxlen); + fib_route(&nf->n.oa->enet_fib, &nf->fn.prefix, nf->fn.pxlen); if (anet) { @@ -1311,7 +1311,7 @@ ospf_rt_abr2(struct proto_ospf *po) /* Get a RT entry and mark it to know that it is an area network */ nf2 = (ort *) fib_get(&po->rtf, &anet->fn.prefix, anet->fn.pxlen); - nf2->fn.x0 = 1; + nf2->fn.flags |= OSPF_RT_PERSISTENT; /* keep persistent */ } u32 metric = (nf->n.type == RTS_OSPF_EXT1) ? @@ -1545,7 +1545,7 @@ ospf_rt_reset(struct proto_ospf *po) FIB_WALK(&po->rtf, nftmp) { ri = (ort *) nftmp; - ri->fn.x0 = 0; + ri->fn.flags &= ~OSPF_RT_PERSISTENT; reset_ri(ri); } FIB_WALK_END; @@ -2041,8 +2041,8 @@ again1: rte_update(p->table, ne, p, p, NULL); } - /* Remove unused rt entry. Entries with fn.x0 == 1 are persistent. */ - if (!nf->n.type && !nf->fn.x0 && !nf->fn.x1) + /* Remove unused rt entry. Entries with any flags are persistent. */ + if (!nf->n.type && !nf->fn.flags) { FIB_ITERATE_PUT(&fit, nftmp); fib_delete(fib, nftmp); diff --git a/proto/ospf/rt.h b/proto/ospf/rt.h index 1ba76e3c..b36da09a 100644 --- a/proto/ospf/rt.h +++ b/proto/ospf/rt.h @@ -50,16 +50,25 @@ typedef struct orta } orta; + +/* Values for fn.flags in struct ort */ +#define OSPF_RT_PERSISTENT 0x01 +#define OSPF_RT_EXPORT 0x02 +#define OSPF_RT_NSSA 0x04 +#define OSPF_RT_SRC (0x02 | 0x04) + typedef struct ort { /* - * We use fn.x0 to mark persistent rt entries, that are needed for summary - * LSAs that don't have 'proper' rt entry (area networks + default to stubs) - * to keep uid stable (used for LSA ID in OSPFv3 - see fibnode_to_lsaid()). + * We use OSPF_RT_PERSISTENT to mark persistent rt entries, that are + * needed for summary LSAs that don't have 'proper' rt entry (area + * networks + default to stubs) to keep uid stable (used for LSA ID + * in OSPFv3 - see fibnode_to_lsaid()). * - * We use fn.x1 to note whether the external route was originated - * from the route export (in ospf_rt_notify()) or from the NSSA - * route translation (in check_nssa_lsa()). + * We use ORT_RT_EXPORT and ORT_RT_NSSA to note whether the + * external/NSSA route was originated from the route export (in + * ospf_rt_notify()) or from the NSSA route translation (in + * check_nssa_lsa()). * * old_* values are here to represent the last route update. old_rta * is cached (we keep reference), mainly for multipath nexthops. diff --git a/proto/ospf/topology.c b/proto/ospf/topology.c index 7e9bad50..9ae620fb 100644 --- a/proto/ospf/topology.c +++ b/proto/ospf/topology.c @@ -1114,8 +1114,11 @@ originate_ext_lsa(struct ospf_area *oa, struct fib_node *fn, int src, body = originate_ext_lsa_body(po, &lsa.length, fn, metric, fwaddr, tag, pbit); lsasum_calculate(&lsa, body); - if (src) - fn->x1 = src; + if (src) + { + fn->flags &= ~OSPF_RT_SRC; + fn->flags |= src; + } lsa_install_new(po, &lsa, dom, body); ospf_lsupd_flood(po, NULL, NULL, &lsa, dom, 1); @@ -1131,7 +1134,7 @@ originate_ext_lsa(struct ospf_area *oa, struct fib_node *fn, int src, } void -flush_ext_lsa(struct ospf_area *oa, struct fib_node *fn) +flush_ext_lsa(struct ospf_area *oa, struct fib_node *fn, int src) { struct proto_ospf *po = oa->po; struct proto *p = &po->proto; @@ -1154,7 +1157,9 @@ flush_ext_lsa(struct ospf_area *oa, struct fib_node *fn) return; } - fn->x1 = 0; + /* Clean up source bits */ + if (src) + fn->flags &= ~OSPF_RT_SRC; ospf_lsupd_flush_nlsa(po, en); } } diff --git a/proto/ospf/topology.h b/proto/ospf/topology.h index b9bc9cf6..1e954444 100644 --- a/proto/ospf/topology.h +++ b/proto/ospf/topology.h @@ -72,7 +72,7 @@ void originate_sum_net_lsa(struct ospf_area *oa, struct fib_node *fn, int metric void originate_sum_rt_lsa(struct ospf_area *oa, struct fib_node *fn, int metric, u32 options UNUSED); void flush_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type); void originate_ext_lsa(struct ospf_area *oa, struct fib_node *fn, int src, u32 metric, ip_addr fwaddr, u32 tag, int pbit); -void flush_ext_lsa(struct ospf_area *oa, struct fib_node *fn); +void flush_ext_lsa(struct ospf_area *oa, struct fib_node *fn, int src); #ifdef OSPFv2 diff --git a/sysdep/bsd/krt-sock.c b/sysdep/bsd/krt-sock.c index e970d6bd..1b09984f 100644 --- a/sysdep/bsd/krt-sock.c +++ b/sysdep/bsd/krt-sock.c @@ -93,7 +93,7 @@ krt_sock_send(int cmd, rte *e) sockaddr gate, mask, dst; ip_addr gw; - DBG("krt-sock: send %I/%d via %I\n", net->n.prefix, net->n.pxlen, a->gw); + DBG("krt-sock: send %F via %I\n", &net->n, a->gw); bzero(&msg,sizeof (struct rt_msghdr)); msg.rtm.rtm_version = RTM_VERSION; @@ -102,15 +102,6 @@ krt_sock_send(int cmd, rte *e) msg.rtm.rtm_addrs = RTA_DST; msg.rtm.rtm_flags = RTF_UP | RTF_PROTO1; - if (net->n.pxlen == MAX_PREFIX_LENGTH) - { - msg.rtm.rtm_flags |= RTF_HOST; - } - else - { - msg.rtm.rtm_addrs |= RTA_NETMASK; - } - #ifdef RTF_REJECT if(a->dest == RTD_UNREACHABLE) msg.rtm.rtm_flags |= RTF_REJECT; @@ -149,6 +140,20 @@ krt_sock_send(int cmd, rte *e) fill_in_sockaddr(&dst, net->n.prefix, NULL, 0); fill_in_sockaddr(&mask, ipa_mkmask(net->n.pxlen), NULL, 0); fill_in_sockaddr(&gate, gw, NULL, 0); + /* XXXX from patch + if (net->n.addr_type == RT_IP) + { + fill_in_sockaddr(&dst, *FPREFIX_IP(&net->n), 0); + fill_in_sockaddr(&mask, ipa_mkmask(net->n.pxlen), 0); + + if (net->n.pxlen == MAX_PREFIX_LENGTH) + msg.rtm.rtm_flags |= RTF_HOST; + else + msg.rtm.rtm_addrs |= RTA_NETMASK; + } + */ + + switch (a->dest) { @@ -193,7 +198,7 @@ krt_sock_send(int cmd, rte *e) msg.rtm.rtm_msglen = l; if ((l = write(rt_sock, (char *)&msg, l)) < 0) { - log(L_ERR "KRT: Error sending route %I/%d to kernel: %m", net->n.prefix, net->n.pxlen); + log(L_ERR "KRT: Error sending route %F to kernel: %m", &net->n); return -1; } @@ -340,8 +345,8 @@ krt_read_rt(struct ks_msg *msg, struct krt_proto *p, int scan) a.iface = if_find_by_index(msg->rtm.rtm_index); if (!a.iface) { - log(L_ERR "KRT: Received route %I/%d with unknown ifindex %u", - net->n.prefix, net->n.pxlen, msg->rtm.rtm_index); + log(L_ERR "KRT: Received route %F with unknown ifindex %u", + &net->n, msg->rtm.rtm_index); return; } @@ -365,8 +370,8 @@ krt_read_rt(struct ks_msg *msg, struct krt_proto *p, int scan) if (ipa_classify(a.gw) == (IADDR_HOST | SCOPE_HOST)) return; - log(L_ERR "KRT: Received route %I/%d with strange next-hop %I", - net->n.prefix, net->n.pxlen, a.gw); + log(L_ERR "KRT: Received route %F with strange next-hop %I", + &net->n, a.gw); return; } } diff --git a/sysdep/linux/netlink.c b/sysdep/linux/netlink.c index 2c511519..fbbc3dbd 100644 --- a/sysdep/linux/netlink.c +++ b/sysdep/linux/netlink.c @@ -640,7 +640,7 @@ nl_send_route(struct krt_proto *p, rte *e, struct ea_list *eattrs, int new) char buf[128 + nh_bufsize(a->nexthops)]; } r; - DBG("nl_send_route(%I/%d,new=%d)\n", net->n.prefix, net->n.pxlen, new); + DBG("nl_send_route(%F,new=%d)\n", &net->n, new); bzero(&r.h, sizeof(r.h)); bzero(&r.r, sizeof(r.r)); @@ -654,7 +654,7 @@ nl_send_route(struct krt_proto *p, rte *e, struct ea_list *eattrs, int new) r.r.rtm_table = KRT_CF->sys.table_id; r.r.rtm_protocol = RTPROT_BIRD; r.r.rtm_scope = RT_SCOPE_UNIVERSE; - nl_add_attr_ipa(&r.h, sizeof(r), RTA_DST, net->n.prefix); + nl_add_attr_ipa(&r.h, sizeof(r), RTA_DST, *FPREFIX_IP(&net->n)); u32 metric = 0; if (new && e->attrs->source == RTS_INHERIT) @@ -837,8 +837,7 @@ nl_parse_route(struct nlmsghdr *h, int scan) ra.nexthops = nl_parse_multipath(p, a[RTA_MULTIPATH]); if (!ra.nexthops) { - log(L_ERR "KRT: Received strange multipath route %I/%d", - net->n.prefix, net->n.pxlen); + log(L_ERR "KRT: Received strange multipath route %F", &net->n); return; } @@ -848,8 +847,8 @@ nl_parse_route(struct nlmsghdr *h, int scan) ra.iface = if_find_by_index(oif); if (!ra.iface) { - log(L_ERR "KRT: Received route %I/%d with unknown ifindex %u", - net->n.prefix, net->n.pxlen, oif); + log(L_ERR "KRT: Received route %F with unknown ifindex %u", + &net->n, oif); return; } @@ -868,8 +867,8 @@ nl_parse_route(struct nlmsghdr *h, int scan) (i->rtm_flags & RTNH_F_ONLINK) ? NEF_ONLINK : 0); if (!ng || (ng->scope == SCOPE_HOST)) { - log(L_ERR "KRT: Received route %I/%d with strange next-hop %I", - net->n.prefix, net->n.pxlen, ra.gw); + log(L_ERR "KRT: Received route %F with strange next-hop %I", + &net->n, ra.gw); return; } } diff --git a/sysdep/unix/krt.c b/sysdep/unix/krt.c index 2bd1bc44..2d70a5c3 100644 --- a/sysdep/unix/krt.c +++ b/sysdep/unix/krt.c @@ -285,14 +285,14 @@ static inline void krt_trace_in(struct krt_proto *p, rte *e, char *msg) { if (p->p.debug & D_PACKETS) - log(L_TRACE "%s: %I/%d: %s", p->p.name, e->net->n.prefix, e->net->n.pxlen, msg); + log(L_TRACE "%s: %F: %s", p->p.name, &e->net->n, msg); } static inline void krt_trace_in_rl(struct rate_limit *rl, struct krt_proto *p, rte *e, char *msg) { if (p->p.debug & D_PACKETS) - log_rl(rl, L_TRACE "%s: %I/%d: %s", p->p.name, e->net->n.prefix, e->net->n.pxlen, msg); + log_rl(rl, L_TRACE "%s: %F: %s", p->p.name, &e->net->n, msg); } /* @@ -335,7 +335,7 @@ krt_learn_announce_update(struct krt_proto *p, rte *e) net *n = e->net; rta *aa = rta_clone(e->attrs); rte *ee = rte_get_temp(aa); - net *nn = net_get(p->p.table, n->n.prefix, n->n.pxlen); + net *nn = fib_get(&p->p.table->fib, FPREFIX(&n->n), n->n.pxlen); ee->net = nn; ee->pflags = 0; ee->pref = p->p.preference; @@ -346,7 +346,7 @@ krt_learn_announce_update(struct krt_proto *p, rte *e) static void krt_learn_announce_delete(struct krt_proto *p, net *n) { - n = net_find(p->p.table, n->n.prefix, n->n.pxlen); + n = fib_find(&p->p.table->fib, FPREFIX(&n->n), n->n.pxlen); if (n) rte_update(p->p.table, n, &p->p, &p->p, NULL); } @@ -356,7 +356,7 @@ static void krt_learn_scan(struct krt_proto *p, rte *e) { net *n0 = e->net; - net *n = net_get(&p->krt_table, n0->n.prefix, n0->n.pxlen); + net *n = fib_get(&p->krt_table.fib, FPREFIX(&n0->n), n0->n.pxlen); rte *m, **mm; e->attrs = rta_lookup(e->attrs); @@ -427,7 +427,7 @@ again: } if (!n->routes) { - DBG("%I/%d: deleting\n", n->n.prefix, n->n.pxlen); + DBG("%F: deleting\n", &n->n); if (old_best) { krt_learn_announce_delete(p, n); @@ -442,12 +442,12 @@ again: n->routes = best; if (best != old_best || !(n->n.flags & KRF_INSTALLED)) { - DBG("%I/%d: announcing (metric=%d)\n", n->n.prefix, n->n.pxlen, best->u.krt.metric); + DBG("%F: announcing (metric=%d)\n", &n->n, best->u.krt.metric); krt_learn_announce_update(p, best); n->n.flags |= KRF_INSTALLED; } else - DBG("%I/%d: uptodate (metric=%d)\n", n->n.prefix, n->n.pxlen, best->u.krt.metric); + DBG("%F: uptodate (metric=%d)\n", &n->n, best->u.krt.metric); } FIB_ITERATE_END(f); } @@ -456,8 +456,8 @@ static void krt_learn_async(struct krt_proto *p, rte *e, int new) { net *n0 = e->net; - net *n = net_get(&p->krt_table, n0->n.prefix, n0->n.pxlen); rte *g, **gg, *best, **bestp, *old_best; + net *n = fib_get(&p->krt_table.fib, FPREFIX(&n0->n), n0->n.pxlen); e->attrs = rta_lookup(e->attrs);