diff options
Diffstat (limited to 'nest')
-rw-r--r-- | nest/Makefile | 2 | ||||
-rw-r--r-- | nest/bird.h | 1 | ||||
-rw-r--r-- | nest/config.Y | 45 | ||||
-rw-r--r-- | nest/iface.c | 31 | ||||
-rw-r--r-- | nest/iface.h | 6 | ||||
-rw-r--r-- | nest/neighbor.c | 2 | ||||
-rw-r--r-- | nest/route.h | 43 | ||||
-rw-r--r-- | nest/rt-dev.c | 4 | ||||
-rw-r--r-- | nest/rt-fib.c | 207 | ||||
-rw-r--r-- | nest/rt-table.c | 82 |
10 files changed, 245 insertions, 178 deletions
diff --git a/nest/Makefile b/nest/Makefile index e6928668..478a82b7 100644 --- a/nest/Makefile +++ b/nest/Makefile @@ -1,4 +1,4 @@ -source=rt-table.c rt-fib.c rt-attr.c rt-roa.c proto.c iface.c rt-dev.c password.c cli.c locks.c cmds.c neighbor.c \ +source=rt-table.c rt-fib.c rt-attr.c proto.c iface.c rt-dev.c password.c cli.c locks.c cmds.c neighbor.c \ a-path.c a-set.c root-rel=../ dir-name=nest diff --git a/nest/bird.h b/nest/bird.h index 3c7d749b..55712abe 100644 --- a/nest/bird.h +++ b/nest/bird.h @@ -12,5 +12,6 @@ #include "sysdep/config.h" #include "lib/birdlib.h" #include "lib/ip.h" +#include "lib/net.h" #endif diff --git a/nest/config.Y b/nest/config.Y index 799a09f9..537a363c 100644 --- a/nest/config.Y +++ b/nest/config.Y @@ -30,7 +30,7 @@ iface_patt_check(void) struct iface_patt_node *pn; WALK_LIST(pn, this_ipatt->ipn_list) - if (!pn->pattern || pn->pxlen) + if (!pn->pattern || pn->prefix.pxlen) /* XXXX */ cf_error("Interface name/mask expected, not IP prefix"); } @@ -55,6 +55,7 @@ CF_DECLS CF_KEYWORDS(ROUTER, ID, PROTOCOL, TEMPLATE, PREFERENCE, DISABLED, DEBUG, ALL, OFF, DIRECT) CF_KEYWORDS(INTERFACE, IMPORT, EXPORT, FILTER, NONE, TABLE, STATES, ROUTES, FILTERS) +CF_KEYWORDS(IPV4, IPVX, VPN4, VPN6) CF_KEYWORDS(RECEIVE, LIMIT, ACTION, WARN, BLOCK, RESTART, DISABLE, KEEP, FILTERED) CF_KEYWORDS(PASSWORD, FROM, PASSIVE, TO, ID, EVENTS, PACKETS, PROTOCOLS, INTERFACES) CF_KEYWORDS(PRIMARY, STATS, COUNT, FOR, COMMANDS, PREEXPORT, NOEXPORT, GENERATE, ROA) @@ -77,7 +78,7 @@ CF_ENUM(T_ENUM_ROA, ROA_, UNKNOWN, VALID, INVALID) %type <ro> roa_args %type <rot> roa_table_arg %type <sd> sym_args -%type <i> proto_start echo_mask echo_size debug_mask debug_list debug_flag mrtdump_mask mrtdump_list mrtdump_flag export_mode roa_mode limit_action tab_sorted tos +%type <i> proto_start echo_mask echo_size debug_mask debug_list debug_flag mrtdump_mask mrtdump_list mrtdump_flag export_mode roa_mode limit_action table_type table_sorted tos %type <ps> proto_patt proto_patt2 %type <g> limit_spec @@ -95,14 +96,7 @@ rtrid: idval: NUM { $$ = $1; } | '(' term ')' { $$ = f_eval_int($2); } - | RTRID - | IPA { -#ifndef IPV6 - $$ = ipa_to_u32($1); -#else - cf_error("Router IDs must be entered as hexadecimal numbers or IPv4 addresses in IPv6 version"); -#endif - } + | IP4 { $$ = ip4_to_u32($1); } | SYM { if ($1->class == (SYM_CONSTANT | T_INT) || $1->class == (SYM_CONSTANT | T_QUAD)) $$ = SYM_VAL($1).i; @@ -140,17 +134,25 @@ gr_opts: GRACEFUL RESTART WAIT expr ';' { new_config->gr_wait = $4; } ; /* Creation of routing tables */ -tab_sorted: +CF_ADDTO(conf, table) + +table_type: + /* empty */ { $$ = NET_IP4; } + | IPV4 { $$ = NET_IP4; } + | IPVX { $$ = NET_IP6; } /* XXXX */ + | VPN4 { $$ = NET_VPN4; } + | VPN6 { $$ = NET_VPN6; } + ; + +table_sorted: { $$ = 0; } | SORTED { $$ = 1; } ; -CF_ADDTO(conf, newtab) - -newtab: TABLE SYM tab_sorted { +table: table_type TABLE SYM table_sorted { struct rtable_config *cf; - cf = rt_new_table($2); - cf->sorted = $3; + cf = rt_new_table($3, $1); + cf->sorted = $4; } ; @@ -282,9 +284,8 @@ iface_patt_node_init: ; iface_patt_node_body: - TEXT { this_ipn->pattern = $1; this_ipn->prefix = IPA_NONE; this_ipn->pxlen = 0; } - | prefix_or_ipa { this_ipn->pattern = NULL; this_ipn->prefix = $1.addr; this_ipn->pxlen = $1.len; } - | TEXT prefix_or_ipa { this_ipn->pattern = $1; this_ipn->prefix = $2.addr; this_ipn->pxlen = $2.len; } + TEXT { this_ipn->pattern = $1; net_fill_ip6(&this_ipn->prefix, IP6_NONE, 0); /* XXXX */ } + | opttext net_or_ipa { this_ipn->pattern = $1; this_ipn->prefix = $2.n; } ; iface_negate: @@ -477,11 +478,11 @@ r_args: $$->prefix = $2.addr; $$->pxlen = $2.len; } - | r_args FOR prefix_or_ipa { + | r_args FOR net_or_ipa { $$ = $1; if ($$->pxlen != 256) cf_error("Only one prefix expected"); - $$->prefix = $3.addr; - $$->pxlen = $3.len; + $$->prefix = IPA_NONE; /* XXXX */ + $$->pxlen = 0; /* XXXX */ $$->show_for = 1; } | r_args TABLE SYM { diff --git a/nest/iface.c b/nest/iface.c index 4d73c2a4..5d3c0e60 100644 --- a/nest/iface.c +++ b/nest/iface.c @@ -46,7 +46,7 @@ list iface_list; void ifa_dump(struct ifa *a) { - debug("\t%I, net %I/%-2d bc %I -> %I%s%s%s\n", a->ip, a->prefix, a->pxlen, a->brd, a->opposite, + debug("\t%I, net %N bc %I -> %I%s%s%s\n", a->ip, &a->prefix, a->brd, a->opposite, (a->flags & IF_UP) ? "" : " DOWN", (a->flags & IA_PRIMARY) ? "" : " SEC", (a->flags & IA_PEER) ? "PEER" : ""); @@ -141,10 +141,9 @@ ifa_send_notify(struct proto *p, unsigned c, struct ifa *a) if (p->ifa_notify) { if (p->debug & D_IFACES) - log(L_TRACE "%s < %s address %I/%d on interface %s %s", + log(L_TRACE "%s < %s address %N on interface %s %s", p->name, (a->flags & IA_PRIMARY) ? "primary" : "secondary", - a->prefix, a->pxlen, a->iface->name, - (c & IF_CHANGE_UP) ? "added" : "removed"); + &a->prefix, a->iface->name, (c & IF_CHANGE_UP) ? "added" : "removed"); p->ifa_notify(p, c, a); } } @@ -500,8 +499,7 @@ ifa_recalc_all_primary_addresses(void) static inline int ifa_same(struct ifa *a, struct ifa *b) { - return ipa_equal(a->ip, b->ip) && ipa_equal(a->prefix, b->prefix) && - a->pxlen == b->pxlen; + return ipa_equal(a->ip, b->ip) && net_equal(&a->prefix, &b->prefix); } @@ -586,7 +584,6 @@ ifa_delete(struct ifa *a) u32 if_choose_router_id(struct iface_patt *mask, u32 old_id) { -#ifndef IPV6 struct iface *i; struct ifa *a, *b; @@ -599,6 +596,9 @@ if_choose_router_id(struct iface_patt *mask, u32 old_id) WALK_LIST(a, i->addrs) { + if (a->prefix.type != NET_IP4) + continue; + if (a->flags & IA_SECONDARY) continue; @@ -623,10 +623,6 @@ if_choose_router_id(struct iface_patt *mask, u32 old_id) log(L_INFO "Chosen router ID %R according to interface %s", id, b->iface->name); return id; - -#else - return 0; -#endif } /** @@ -669,17 +665,17 @@ iface_patt_match(struct iface_patt *ifp, struct iface *i, struct ifa *a) continue; } - if (p->pxlen == 0) + if (p->prefix.pxlen == 0) return pos; if (!a) continue; - if (ipa_in_net(a->ip, p->prefix, p->pxlen)) + if (ipa_in_netX(a->ip, &p->prefix)) return pos; if ((a->flags & IA_PEER) && - ipa_in_net(a->opposite, p->prefix, p->pxlen)) + ipa_in_netX(a->opposite, &p->prefix)) return pos; continue; @@ -713,8 +709,7 @@ iface_plists_equal(struct iface_patt *pa, struct iface_patt *pb) (!x->pattern && y->pattern) || /* This nasty lines where written by me... :-( Feela */ (!y->pattern && x->pattern) || ((x->pattern != y->pattern) && strcmp(x->pattern, y->pattern)) || - !ipa_equal(x->prefix, y->prefix) || - (x->pxlen != y->pxlen)) + !net_equal(&x->prefix, &y->prefix)) return 0; x = (void *) x->n.next; y = (void *) y->n.next; @@ -754,7 +749,7 @@ if_show_addr(struct ifa *a) else opp[0] = 0; cli_msg(-1003, "\t%I/%d (%s%s, scope %s)", - a->ip, a->pxlen, + a->ip, a->prefix.pxlen, (a->flags & IA_PRIMARY) ? "Primary" : (a->flags & IA_SECONDARY) ? "Secondary" : "Unselected", opp, ip_scope_text(a->scope)); } @@ -804,7 +799,7 @@ if_show_summary(void) WALK_LIST(i, iface_list) { if (i->addr) - bsprintf(addr, "%I/%d", i->addr->ip, i->addr->pxlen); + bsprintf(addr, "%I/%d", i->addr->ip, i->addr->prefix.pxlen); else addr[0] = 0; cli_msg(-1005, "%-9s %-5s %s", i->name, (i->flags & IF_UP) ? "up" : "DOWN", addr); diff --git a/nest/iface.h b/nest/iface.h index 56710e4a..c4f414ec 100644 --- a/nest/iface.h +++ b/nest/iface.h @@ -19,9 +19,8 @@ struct pool; struct ifa { /* Interface address */ node n; struct iface *iface; /* Interface this address belongs to */ + net_addr prefix; /* Network prefix */ ip_addr ip; /* IP address of this host */ - ip_addr prefix; /* Network prefix */ - unsigned pxlen; /* Prefix length */ ip_addr brd; /* Broadcast address */ ip_addr opposite; /* Opposite end of a point-to-point link */ unsigned scope; /* Interface address scope */ @@ -148,8 +147,7 @@ struct iface_patt_node { node n; int positive; byte *pattern; - ip_addr prefix; - int pxlen; + net_addr prefix; }; struct iface_patt { diff --git a/nest/neighbor.c b/nest/neighbor.c index 1685d67e..b8832f2f 100644 --- a/nest/neighbor.c +++ b/nest/neighbor.c @@ -79,7 +79,7 @@ if_connected(ip_addr *a, struct iface *i, struct ifa **ap) } else { - if (ipa_in_net(*a, b->prefix, b->pxlen)) + if (ipa_in_netX(*a, &b->prefix)) { #ifndef IPV6 if ((b->pxlen < (BITS_PER_IP_ADDRESS - 1)) && diff --git a/nest/route.h b/nest/route.h index c435b9e0..4480d17b 100644 --- a/nest/route.h +++ b/nest/route.h @@ -35,11 +35,9 @@ struct cli; struct fib_node { struct fib_node *next; /* Next in hash chain */ struct fib_iterator *readers; /* List of readers of this node */ - byte pxlen; - byte flags; /* User-defined */ - byte x0, x1; /* User-defined */ - u32 uid; /* Unique ID based on hash */ - ip_addr prefix; /* In host order */ + byte flags; /* User-defined, will be removed */ + u32 uid; /* Unique ID based on hash, will be removed */ + net_addr addr[0]; }; struct fib_iterator { /* See lib/slists.h for an explanation */ @@ -50,7 +48,7 @@ struct fib_iterator { /* See lib/slists.h for an explanation */ uint hash; }; -typedef void (*fib_init_func)(struct fib_node *); +typedef void (*fib_init_fn)(void *); struct fib { pool *fib_pool; /* Pool holding all our data */ @@ -59,15 +57,18 @@ struct fib { uint hash_size; /* Number of hash table entries (a power of two) */ uint hash_order; /* Binary logarithm of hash_size */ uint hash_shift; /* 16 - hash_log */ + uint addr_type; /* Type of address data stored in fib (NET_*) */ + uint node_size; /* XXXX */ + uint node_offset; /* XXXX */ uint entries; /* Number of entries */ uint entries_min, entries_max; /* Entry count limits (else start rehashing) */ - fib_init_func init; /* Constructor */ + fib_init_fn init; /* Constructor */ }; -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 fib_init(struct fib *f, pool *p, uint addr_type, uint node_size, uint node_offset, uint hash_order, fib_init_fn init); +void *fib_find(struct fib *, net_addr *); /* Find or return NULL if doesn't exist */ +void *fib_get(struct fib *, net_addr *); /* Find or create new if nonexistent */ +void *fib_route(struct fib *, net_addr *); /* 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 */ @@ -77,7 +78,7 @@ struct fib_node *fit_get(struct fib *, struct fib_iterator *); void fit_put(struct fib_iterator *, struct fib_node *); void fit_put_next(struct fib *f, struct fib_iterator *i, struct fib_node *n, uint hpos); - +/* XXXX: return user entries */ #define FIB_WALK(fib, z) do { \ struct fib_node *z, **ff = (fib)->hash_table; \ uint count = (fib)->hash_size; \ @@ -126,6 +127,7 @@ struct rtable_config { char *name; struct rtable *table; struct proto_config *krt_attached; /* Kernel syncer attached to this table */ + uint addr_type; /* Type of address data stored in table (NET_*) */ int gc_max_ops; /* Maximum number of operations before GC is run */ int gc_min_time; /* Minimum time between two consecutive GC runs */ byte sorted; /* Routes of network are sorted according to rte_better() */ @@ -136,6 +138,7 @@ typedef struct rtable { struct fib fib; char *name; /* Name of this table */ list hooks; /* List of announcement hooks */ + uint addr_type; /* Type of address data stored in table (NET_*) */ int pipe_busy; /* Pipe loop detection */ int use_count; /* Number of protocols using this table */ struct hostcache *hostcache; @@ -160,8 +163,8 @@ typedef struct rtable { #define RPS_RUNNING 2 typedef struct network { - struct fib_node n; /* FIB flags reserved for kernel syncer */ struct rte *routes; /* Available routes for this network */ + struct fib_node n; /* FIB flags reserved for kernel syncer */ } net; struct hostcache { @@ -262,14 +265,20 @@ void rt_commit(struct config *new, struct config *old); void rt_lock_table(rtable *); void rt_unlock_table(rtable *); void rt_setup(pool *, rtable *, char *, struct rtable_config *); -static inline net *net_find(rtable *tab, ip_addr addr, unsigned len) { return (net *) fib_find(&tab->fib, &addr, len); } -static inline net *net_get(rtable *tab, ip_addr addr, unsigned len) { return (net *) fib_get(&tab->fib, &addr, len); } +static inline net *net_find(rtable *tab, net_addr *addr) { return (net *) fib_find(&tab->fib, addr); } +static inline net *net_get(rtable *tab, net_addr *addr) { return (net *) fib_get(&tab->fib, addr); } + +static inline net *net_find_ipa(rtable *tab, ip_addr px, uint pxlen) +{ net_addr addr; net_fill_ipa(&addr, px, pxlen); return (net *) fib_find(&tab->fib, &addr); } +static inline net *net_get_ipa(rtable *tab, ip_addr px, uint pxlen) +{ net_addr addr; net_fill_ipa(&addr, px, pxlen); return (net *) fib_get(&tab->fib, &addr); } + rte *rte_find(net *net, struct rte_src *src); rte *rte_get_temp(struct rta *); void rte_update2(struct announce_hook *ah, net *net, rte *new, struct rte_src *src); static inline void rte_update(struct proto *p, net *net, rte *new) { rte_update2(p->main_ahook, net, new, p->main_source); } void rte_discard(rtable *tab, rte *old); -int rt_examine(rtable *t, ip_addr prefix, int pxlen, struct proto *p, struct filter *filter); +int rt_examine(rtable *t, net_addr *a, struct proto *p, struct filter *filter); rte *rt_export_merged(struct announce_hook *ah, net *net, rte **rt_free, struct ea_list **tmpa, int silent); void rt_refresh_begin(rtable *t, struct announce_hook *ah); void rt_refresh_end(rtable *t, struct announce_hook *ah); @@ -283,7 +292,7 @@ void rt_dump_all(void); int rt_feed_baby(struct proto *p); void rt_feed_baby_abort(struct proto *p); int rt_prune_loop(void); -struct rtable_config *rt_new_table(struct symbol *s); +struct rtable_config *rt_new_table(struct symbol *s, uint addr_type); static inline void rt_mark_for_prune(rtable *tab) diff --git a/nest/rt-dev.c b/nest/rt-dev.c index f6bc1432..f94933d5 100644 --- a/nest/rt-dev.c +++ b/nest/rt-dev.c @@ -45,7 +45,7 @@ dev_ifa_notify(struct proto *p, unsigned c, struct ifa *ad) net *n; DBG("dev_if_notify: %s:%I going down\n", ad->iface->name, ad->ip); - n = net_find(p->table, ad->prefix, ad->pxlen); + n = net_find(p->table, &ad->prefix); if (!n) { DBG("dev_if_notify: device shutdown: prefix not found\n"); @@ -77,7 +77,7 @@ dev_ifa_notify(struct proto *p, unsigned c, struct ifa *ad) }; a = rta_lookup(&a0); - n = net_get(p->table, ad->prefix, ad->pxlen); + n = net_get(p->table, &ad->prefix); e = rte_get_temp(a); e->net = n; e->pflags = 0; diff --git a/nest/rt-fib.c b/nest/rt-fib.c index a73de1fd..d726714b 100644 --- a/nest/rt-fib.c +++ b/nest/rt-fib.c @@ -48,6 +48,13 @@ #define HASH_LO_STEP 2 #define HASH_LO_MIN 10 + +static inline void * fib_node_to_user(struct fib *f, struct fib_node *e) +{ return (void *) ((char *) e - f->node_offset); } + +static inline struct fib_node * fib_user_to_node(struct fib *f, void *e) +{ return (void *) ((char *) e + f->node_offset); } + static void fib_ht_alloc(struct fib *f) { @@ -72,16 +79,9 @@ fib_ht_free(struct fib_node **h) mb_free(h); } -static inline unsigned -fib_hash(struct fib *f, ip_addr *a) -{ - return ipa_hash(*a) >> f->hash_shift; -} -static void -fib_dummy_init(struct fib_node *dummy UNUSED) -{ -} +static u32 +fib_hash(struct fib *f, net_addr *a); /** * fib_init - initialize a new FIB @@ -96,18 +96,23 @@ fib_dummy_init(struct fib_node *dummy UNUSED) * This function initializes a newly allocated FIB and prepares it for use. */ void -fib_init(struct fib *f, pool *p, unsigned node_size, unsigned hash_order, fib_init_func init) +fib_init(struct fib *f, pool *p, uint addr_type, uint node_size, uint node_offset, uint hash_order, fib_init_fn init) { + uint addr_length = net_addr_length[addr_type]; + if (!hash_order) hash_order = HASH_DEF_ORDER; f->fib_pool = p; - f->fib_slab = sl_new(p, node_size); + f->fib_slab = addr_length ? sl_new(p, node_size + addr_length) : NULL; + f->addr_type = addr_type; + f->node_size = node_size; + f->node_offset = node_offset; f->hash_order = hash_order; fib_ht_alloc(f); bzero(f->hash_table, f->hash_size * sizeof(struct fib_node *)); f->entries = 0; f->entries_min = 0; - f->init = init ? : fib_dummy_init; + f->init = init; } static void @@ -133,7 +138,7 @@ fib_rehash(struct fib *f, int step) while (e = x) { x = e->next; - nh = fib_hash(f, &e->prefix); + nh = fib_hash(f, e->addr); while (nh > ni) { *t = NULL; @@ -153,6 +158,76 @@ fib_rehash(struct fib *f, int step) fib_ht_free(m); } +#define CAST(t) (net_addr_##t *) + +#define FIB_HASH(f,a,t) (net_hash_##t(CAST(t) a) >> f->hash_shift) + +#define FIB_FIND(f,a,t) \ + ({ \ + struct fib_node *e = f->hash_table[FIB_HASH(f, a, t)]; \ + while (e && !net_equal_##t(CAST(t) e->addr, CAST(t) a)) \ + e = e->next; \ + fib_node_to_user(f, e); \ + }) + +#define FIB_INSERT(f,a,e,t) \ + ({ \ + u32 h = net_hash_##t(CAST(t) a); \ + struct fib_node **ee = f->hash_table + (h >> f->hash_shift); \ + struct fib_node *g; \ + \ + while ((g = *ee) && (net_hash_##t(CAST(t) g->addr) < h)) \ + ee = &g->next; \ + \ + net_copy_##t(CAST(t) e->addr, CAST(t) a); \ + e->next = *ee; \ + *ee = e; \ + }) + + +static u32 +fib_hash(struct fib *f, net_addr *a) +{ + switch (f->addr_type) + { + case NET_IP4: return FIB_HASH(f, a, ip4); + case NET_IP6: return FIB_HASH(f, a, ip6); + case NET_VPN4: return FIB_HASH(f, a, vpn4); + case NET_VPN6: return FIB_HASH(f, a, vpn6); + default: bug("invalid type"); + } +} + +void * +fib_find(struct fib *f, net_addr *a) +{ + ASSERT(f->addr_type == a->type); + + switch (f->addr_type) + { + case NET_IP4: return FIB_FIND(f, a, ip4); + case NET_IP6: return FIB_FIND(f, a, ip6); + case NET_VPN4: return FIB_FIND(f, a, vpn4); + case NET_VPN6: return FIB_FIND(f, a, vpn6); + default: bug("invalid type"); + } +} + +static void +fib_insert(struct fib *f, net_addr *a, struct fib_node *e) +{ + switch (f->addr_type) + { + case NET_IP4: FIB_INSERT(f, a, e, ip4); return; + case NET_IP6: FIB_INSERT(f, a, e, ip6); return; + case NET_VPN4: FIB_INSERT(f, a, e, vpn4); return; + case NET_VPN6: FIB_INSERT(f, a, e, vpn6); return; + default: bug("invalid type"); + } +} + + + /** * fib_find - search for FIB node by prefix * @f: FIB to search in @@ -162,8 +237,9 @@ fib_rehash(struct fib *f, int step) * Search for a FIB node corresponding to the given prefix, return * 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, net_addr *a) { struct fib_node *e = f->hash_table[fib_hash(f, a)]; @@ -171,27 +247,6 @@ fib_find(struct fib *f, ip_addr *a, int len) e = e->next; return e; } - -/* -int -fib_histogram(struct fib *f) -{ - log(L_WARN "Histogram dump start %d %d", f->hash_size, f->entries); - - int i, j; - struct fib_node *e; - - for (i = 0; i < f->hash_size; i++) - { - j = 0; - for (e = f->hash_table[i]; e != NULL; e = e->next) - j++; - if (j > 0) - log(L_WARN "Histogram line %d: %d", i, j); - } - - log(L_WARN "Histogram dump end"); -} */ /** @@ -204,47 +259,31 @@ fib_histogram(struct fib *f) * 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, net_addr *a) { - uint h = ipa_hash(*a); - struct fib_node **ee = f->hash_table + (h >> f->hash_shift); - struct fib_node *g, *e = *ee; - u32 uid = h << 16; - - while (e && (e->pxlen != len || !ipa_equal(*a, e->prefix))) - e = e->next; - if (e) - return e; -#ifdef DEBUGGING - if (len < 0 || len > BITS_PER_IP_ADDRESS || !ip_is_prefix(*a,len)) - bug("fib_get() called for invalid address"); -#endif + char *b = fib_find(f, a); + if (b) + return b; - while ((g = *ee) && g->uid < uid) - ee = &g->next; - while ((g = *ee) && g->uid == uid) - { - ee = &g->next; - uid++; - } + if (f->fib_slab) + b = sl_alloc(f->fib_slab); + else + b = mb_alloc(f->fib_pool, f->node_size + a->length); - if ((uid >> 16) != h) - log(L_ERR "FIB hash table chains are too long"); + struct fib_node *e = (void *) (b + f->node_offset); + e->readers = NULL; + e->flags = 0; + e->uid = 0; + fib_insert(f, a, e); - // log (L_WARN "FIB_GET %I %x %x", *a, h, uid); + memset(b, 0, f->node_offset); + if (f->init) + f->init(b); - e = sl_alloc(f->fib_slab); - e->prefix = *a; - e->pxlen = len; - e->next = *ee; - e->uid = uid; - *ee = e; - e->readers = NULL; - f->init(e); if (f->entries++ > f->entries_max) fib_rehash(f, HASH_HI_STEP); - return e; + return b; } /** @@ -257,6 +296,7 @@ fib_get(struct fib *f, ip_addr *a, int len) * network, that is a node which a CIDR router would use for routing * that network. */ +/* void * fib_route(struct fib *f, ip_addr a, int len) { @@ -273,6 +313,7 @@ fib_route(struct fib *f, ip_addr a, int len) } return NULL; } +*/ static inline void fib_merge_readers(struct fib_iterator *i, struct fib_node *to) @@ -320,8 +361,8 @@ fib_merge_readers(struct fib_iterator *i, struct fib_node *to) void fib_delete(struct fib *f, void *E) { - struct fib_node *e = E; - uint h = fib_hash(f, &e->prefix); + struct fib_node *e = fib_user_to_node(f, E); + uint h = fib_hash(f, e->addr); 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, n->addr); return n; } @@ -498,6 +539,28 @@ fib_check(struct fib *f) bug("fib_check: invalid entry count (%d != %d)", ec, f->entries); } +/* +int +fib_histogram(struct fib *f) +{ + log(L_WARN "Histogram dump start %d %d", f->hash_size, f->entries); + + int i, j; + struct fib_node *e; + + for (i = 0; i < f->hash_size; i++) + { + j = 0; + for (e = f->hash_table[i]; e != NULL; e = e->next) + j++; + if (j > 0) + log(L_WARN "Histogram line %d: %d", i, j); + } + + log(L_WARN "Histogram dump end"); +} +*/ + #endif #ifdef TEST @@ -517,7 +580,7 @@ void dump(char *m) struct fib_iterator *j; for(n=f.hash_table[i]; n; n=n->next) { - debug("%04x %04x %p %I/%2d", i, ipa_hash(n->prefix), n, n->prefix, n->pxlen); + debug("%04x %08x %p %N", i, ipa_hash(n->prefix), n, n->addr); 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 57c8b8e0..0a148f45 100644 --- a/nest/rt-table.c +++ b/nest/rt-table.c @@ -69,6 +69,7 @@ make_tmp_attrs(struct rte *rt, struct linpool *pool) } /* Like fib_route(), but skips empty net entries */ +/* static net * net_route(rtable *tab, ip_addr a, int len) { @@ -85,15 +86,7 @@ net_route(rtable *tab, ip_addr a, int len) } return NULL; } - -static void -rte_init(struct fib_node *N) -{ - net *n = (net *) N; - - N->flags = 0; - n->routes = NULL; -} +*/ /** * rte_find - find a route @@ -230,7 +223,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 %N %s", p->name, dir, msg, e->net->n.addr, via); } static inline void @@ -788,20 +781,21 @@ 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)) - { - log(L_WARN "Ignoring bogus prefix %I/%d received via %s", - n->n.prefix, n->n.pxlen, e->sender->proto->name); - return 0; - } + // (n->n.pxlen > BITS_PER_IP_ADDRESS) || !ip_is_prefix(n->n.prefix,n->n.pxlen)) + if (!net_validate(n->n.addr)) + { + log(L_WARN "Ignoring bogus prefix %N received via %s", + n->n.addr, e->sender->proto->name); + return 0; + } - c = ipa_classify_net(n->n.prefix); + c = net_classify(n->n.addr); 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); - return 0; - } + { + log(L_WARN "Ignoring bogus route %N received via %s", + n->n.addr, e->sender->proto->name); + return 0; + } return 1; } @@ -870,8 +864,8 @@ rte_recalculate(struct announce_hook *ah, net *net, rte *new, struct rte_src *sr { if (new) { - log_rl(&rl_pipe, L_ERR "Pipe collision detected when sending %I/%d to table %s", - net->n.prefix, net->n.pxlen, table->name); + log_rl(&rl_pipe, L_ERR "Pipe collision detected when sending %N to table %s", + net->n.addr, table->name); rte_free_quick(new); } return; @@ -1278,9 +1272,9 @@ rte_discard(rtable *t, rte *old) /* Non-filtered route deletion, used during gar /* Check rtable for best route to given net whether it would be exported do p */ int -rt_examine(rtable *t, ip_addr prefix, int pxlen, struct proto *p, struct filter *filter) +rt_examine(rtable *t, net_addr *a, struct proto *p, struct filter *filter) { - net *n = net_find(t, prefix, pxlen); + net *n = net_find(t, a); rte *rt = n ? n->routes : NULL; if (!rte_is_valid(rt)) @@ -1376,7 +1370,7 @@ void rte_dump(rte *e) { net *n = e->net; - debug("%-1I/%2d ", n->n.prefix, n->n.pxlen); + debug("%-1N ", n->n.addr); debug("KF=%02x PF=%02x pref=%d lm=%d ", n->n.flags, e->pflags, e->pref, now-e->lastmod); rta_dump(e->attrs); if (e->attrs->src->proto->proto->dump_attrs) @@ -1527,9 +1521,10 @@ void rt_setup(pool *p, rtable *t, char *name, struct rtable_config *cf) { bzero(t, sizeof(*t)); - fib_init(&t->fib, p, sizeof(net), 0, rte_init); t->name = name; t->config = cf; + t->addr_type = cf ? cf->addr_type : NET_IP4; + fib_init(&t->fib, p, t->addr_type, sizeof(net), OFFSETOF(net, n), 0, NULL); init_list(&t->hooks); if (cf) { @@ -1660,7 +1655,7 @@ rt_preconfig(struct config *c) struct symbol *s = cf_get_symbol("master"); init_list(&c->tables); - c->master_rtc = rt_new_table(s); + c->master_rtc = rt_new_table(s, NET_IP4); } @@ -1817,7 +1812,7 @@ rt_next_hop_update(rtable *tab) struct rtable_config * -rt_new_table(struct symbol *s) +rt_new_table(struct symbol *s, uint addr_type) { /* Hack that allows to 'redefine' the master table */ if ((s->class == SYM_TABLE) && (s->def == new_config->master_rtc)) @@ -1827,6 +1822,7 @@ rt_new_table(struct symbol *s) 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; @@ -2197,8 +2193,9 @@ rt_notify_hostcache(rtable *tab, net *net) if (tab->hcu_scheduled) return; - if (trie_match_prefix(hc->trie, net->n.prefix, net->n.pxlen)) - rt_schedule_hcu(tab); + // XXXX + // if (trie_match_prefix(hc->trie, net->n.prefix, net->n.pxlen)) + // rt_schedule_hcu(tab); } static int @@ -2254,18 +2251,20 @@ rt_update_hostentry(rtable *tab, struct hostentry *he) he->dest = RTD_UNREACHABLE; he->igp_metric = 0; - net *n = net_route(tab, he->addr, MAX_PREFIX_LENGTH); + // XXXX + // net *n = net_route(tab, he->addr, MAX_PREFIX_LENGTH); + net *n = NULL; if (n) { rte *e = n->routes; rta *a = e->attrs; - pxlen = n->n.pxlen; + pxlen = n->n.addr->pxlen; 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 %N", + he->addr, n->n.addr); goto done; } @@ -2426,7 +2425,7 @@ rt_show_net(struct cli *c, net *n, struct rt_show_data *d) int first = 1; int pass = 0; - bsprintf(ia, "%I/%d", n->n.prefix, n->n.pxlen); + bsprintf(ia, "%N", n->n.addr); if (d->export_mode) { @@ -2590,10 +2589,13 @@ rt_show(struct rt_show_data *d) } else { + /* XXXX if (d->show_for) n = net_route(d->table, d->prefix, d->pxlen); else n = net_find(d->table, d->prefix, d->pxlen); + */ + n = NULL; if (n) rt_show_net(this_cli, n, d); @@ -2614,26 +2616,24 @@ rt_show(struct rt_show_data *d) * net_find - find a network entry * @tab: a routing table * @addr: address of the network - * @len: length of the network prefix * * net_find() looks up the given network in routing table @tab and * returns a pointer to its &net entry or %NULL if no such network * exists. */ -static inline net *net_find(rtable *tab, ip_addr addr, unsigned len) +static inline net *net_find(rtable *tab, net_addr *addr) { DUMMY; } /** * net_get - obtain a network entry * @tab: a routing table * @addr: address of the network - * @len: length of the network prefix * * net_get() looks up the given network in routing table @tab and * returns a pointer to its &net entry. If no such entry exists, it's * created. */ -static inline net *net_get(rtable *tab, ip_addr addr, unsigned len) +static inline net *net_get(rtable *tab, net_addr *addr) { DUMMY; } /** |