diff options
-rw-r--r-- | conf/confbase.Y | 106 | ||||
-rw-r--r-- | filter/config.Y | 19 | ||||
-rw-r--r-- | filter/filter.h | 2 | ||||
-rw-r--r-- | filter/test.conf | 16 | ||||
-rw-r--r-- | lib/ip.c | 2 | ||||
-rw-r--r-- | lib/ip.h | 24 | ||||
-rw-r--r-- | lib/net.h | 21 | ||||
-rw-r--r-- | nest/config.Y | 19 | ||||
-rw-r--r-- | nest/neighbor.c | 3 | ||||
-rw-r--r-- | nest/route.h | 9 | ||||
-rw-r--r-- | nest/rt-attr.c | 9 | ||||
-rw-r--r-- | nest/rt-fib.c | 43 | ||||
-rw-r--r-- | nest/rt-table.c | 104 | ||||
-rw-r--r-- | proto/bfd/bfd.c | 2 | ||||
-rw-r--r-- | proto/ospf/config.Y | 4 | ||||
-rw-r--r-- | proto/ospf/iface.c | 3 | ||||
-rw-r--r-- | proto/ospf/neighbor.c | 5 | ||||
-rw-r--r-- | proto/ospf/packet.c | 4 | ||||
-rw-r--r-- | proto/radv/config.Y | 2 | ||||
-rw-r--r-- | sysdep/unix/krt.Y | 2 |
20 files changed, 235 insertions, 164 deletions
diff --git a/conf/confbase.Y b/conf/confbase.Y index 467ce5a4..06698833 100644 --- a/conf/confbase.Y +++ b/conf/confbase.Y @@ -41,7 +41,7 @@ CF_DECLS ip_addr a; ip4_addr ip4; ip6_addr ip6; - net_addr_union net; + net_addr net; net_addr *net_ptr; struct symbol *s; char *t; @@ -76,12 +76,12 @@ CF_DECLS %token <t> TEXT %type <iface> ipa_scope -%type <i> expr bool pxlen4 pxlen6 +%type <i> expr bool pxlen4 %type <i32> expr_us %type <time> datetime -%type <a> ipa ipa_raw -%type <net> net_ip4 net_ip6 net_ip net_or_ipa -%type <net_ptr> net_any +%type <a> ipa +%type <net> net_ip4_ net_ip6_ net_ip6 net_ip_ net_ip net_or_ipa +%type <net_ptr> net_ net_any %type <t> text opttext @@ -151,15 +151,12 @@ bool: | /* Silence means agreement */ { $$ = 1; } ; -/* Addresses, prefixes and netmasks */ -ipa_raw: - IP4 { $$ = ipa_from_ip4($1); } - | IP6 { $$ = ipa_from_ip6($1); } - ; +/* Addresses */ ipa: - ipa_raw + IP4 { $$ = ipa_from_ip4($1); } + | IP6 { $$ = ipa_from_ip6($1); } | SYM { if ($1->class != (SYM_CONSTANT | T_IP)) cf_error("IP address expected"); $$ = SYM_VAL($1).ip; @@ -172,42 +169,85 @@ ipa_scope: ; -/* XXXX - symbols and tests */ +/* Networks - internal */ -net_ip4: IP4 pxlen4 { $$.ip4 = NET_ADDR_IP4($1, $2); } +pxlen4: + '/' NUM { + if ($2 < 0 || $2 > IP4_MAX_PREFIX_LENGTH) cf_error("Invalid prefix length %d", $2); + $$ = $2; + } + | ':' IP4 { + $$ = ip4_masklen($2); + if ($$ == 255) cf_error("Invalid netmask %I", $2); /* XXXX */ + } + ; -net_ip6: IP6 pxlen6 { $$.ip6 = NET_ADDR_IP6($1, $2); } +net_ip4_: IP4 pxlen4 +{ + net_fill_ip4(&($$), $1, $2); + if (!net_validate_ip4((net_addr_ip4 *) &($$))) + cf_error("Invalid IPv4 prefix"); +}; -net_ip: net_ip4 | net_ip6 ; +net_ip6_: IP6 '/' NUM +{ + net_fill_ip6(&($$), $1, $3); + if ($3 < 0 || $3 > IP6_MAX_PREFIX_LENGTH) + cf_error("Invalid prefix length %d", $3); + if (!net_validate_ip6((net_addr_ip6 *) &($$))) + cf_error("Invalid IPv6 prefix"); +}; -net_any: net_ip { $$ = cfg_alloc($1.n.length); net_copy($$, &($1.n)); } +net_ip_: net_ip4_ | net_ip6_ ; -net_or_ipa: - net_ip4 - | net_ip6 - | IP4 { $$.ip4 = NET_ADDR_IP4($1, IP4_MAX_PREFIX_LENGTH); } - | IP6 { $$.ip6 = NET_ADDR_IP6($1, IP6_MAX_PREFIX_LENGTH); } - ; +net_: net_ip_ { $$ = cfg_alloc($1.length); net_copy($$, &($1)); } ; -pxlen4: - '/' expr { - if ($2 < 0 || $2 > IP4_MAX_PREFIX_LENGTH) cf_error("Invalid prefix length %d", $2); - $$ = $2; +/* Networks - regular */ + +net_ip6: + net_ip6_ + | SYM { + if (($1->class != (SYM_CONSTANT | T_NET)) || (SYM_VAL($1).net->type != NET_IP6)) + cf_error("IPv6 network expected"); + $$ = * SYM_VAL($1).net; } - | ':' IP4 { - $$ = ip4_masklen($2); - if ($$ < 0) cf_error("Invalid netmask %I", $2); + ; + +net_ip: + net_ip_ + | SYM { + if (($1->class != (SYM_CONSTANT | T_NET)) || !net_is_ip(SYM_VAL($1).net)) + cf_error("IP network expected"); + $$ = * SYM_VAL($1).net; } ; -pxlen6: - '/' expr { - if ($2 < 0 || $2 > IP6_MAX_PREFIX_LENGTH) cf_error("Invalid prefix length %d", $2); - $$ = $2; +net_any: + net_ + | SYM { + if ($1->class != (SYM_CONSTANT | T_NET)) + cf_error("Network expected"); + $$ = (net_addr *) SYM_VAL($1).net; /* Avoid const warning */ + } + ; + +net_or_ipa: + net_ip4_ + | net_ip6_ + | IP4 { net_fill_ip4(&($$), $1, IP4_MAX_PREFIX_LENGTH); } + | IP6 { net_fill_ip6(&($$), $1, IP6_MAX_PREFIX_LENGTH); } + | SYM { + if ($1->class == (SYM_CONSTANT | T_IP)) + net_fill_ip_host(&($$), SYM_VAL($1).ip); + else if (($1->class == (SYM_CONSTANT | T_NET)) && net_is_ip(SYM_VAL($1).net)) + $$ = * SYM_VAL($1).net; + else + cf_error("IP address or network expected"); } ; + datetime: TEXT { $$ = tm_parse_datetime($1); diff --git a/filter/config.Y b/filter/config.Y index 7e9f4104..6efc14f5 100644 --- a/filter/config.Y +++ b/filter/config.Y @@ -475,7 +475,8 @@ block: * Complex types, their bison value is struct f_val */ fipa: - ipa_raw %prec PREFIX_DUMMY { $$.type = T_IP; $$.val.ip = $1; } + IP4 %prec PREFIX_DUMMY { $$.type = T_IP; $$.val.ip = ipa_from_ip4($1); } + | IP6 %prec PREFIX_DUMMY { $$.type = T_IP; $$.val.ip = ipa_from_ip6($1); } ; @@ -571,19 +572,19 @@ switch_items: ; fprefix: - net_ip { $$.net = $1; $$.lo = $1.n.pxlen; $$.hi = $1.n.pxlen; } - | net_ip '+' { $$.net = $1; $$.lo = $1.n.pxlen; $$.hi = net_max_prefix_length[$1.n.type]; } - | net_ip '-' { $$.net = $1; $$.lo = 0; $$.hi = $1.n.pxlen; } - | net_ip '{' NUM ',' NUM '}' { + net_ip_ { $$.net = $1; $$.lo = $1.pxlen; $$.hi = $1.pxlen; } + | net_ip_ '+' { $$.net = $1; $$.lo = $1.pxlen; $$.hi = net_max_prefix_length[$1.type]; } + | net_ip_ '-' { $$.net = $1; $$.lo = 0; $$.hi = $1.pxlen; } + | net_ip_ '{' NUM ',' NUM '}' { $$.net = $1; $$.lo = $3; $$.hi = $5; - if ((0 > $3) || ($3 > $5) || ($5 > net_max_prefix_length[$1.n.type])) + if ((0 > $3) || ($3 > $5) || ($5 > net_max_prefix_length[$1.type])) cf_error("Invalid prefix pattern range: {%d, %d}", $3, $5); } ; fprefix_set: - fprefix { $$ = f_new_trie(cfg_mem, sizeof(struct f_trie_node)); trie_add_prefix($$, &($1.net.n), $1.lo, $1.hi); } - | fprefix_set ',' fprefix { $$ = $1; trie_add_prefix($$, &($3.net.n), $3.lo, $3.hi); } + fprefix { $$ = f_new_trie(cfg_mem, sizeof(struct f_trie_node)); trie_add_prefix($$, &($1.net), $1.lo, $1.hi); } + | fprefix_set ',' fprefix { $$ = $1; trie_add_prefix($$, &($3.net), $3.lo, $3.hi); } ; switch_body: /* EMPTY */ { $$ = NULL; } @@ -635,7 +636,7 @@ constant: | FALSE { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_BOOL; $$->a2.i = 0; } | TEXT { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_STRING; $$->a2.p = $1; } | fipa { NEW_F_VAL; $$ = f_new_inst(); $$->code = 'C'; $$->a1.p = val; *val = $1; } - | net_any { NEW_F_VAL; $$ = f_new_inst(); $$->code = 'C'; val->type = T_NET; val->val.net = $1; $$->a1.p = val; } + | net_ { NEW_F_VAL; $$ = f_new_inst(); $$->code = 'C'; val->type = T_NET; val->val.net = $1; $$->a1.p = val; } | '[' set_items ']' { DBG( "We've got a set here..." ); $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_SET; $$->a2.p = build_tree($2); DBG( "ook\n" ); } | '[' fprefix_set ']' { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_PREFIX_SET; $$->a2.p = $2; } | ENUM { $$ = f_new_inst(); $$->code = 'c'; $$->aux = $1 >> 16; $$->a2.i = $1 & 0xffff; } diff --git a/filter/filter.h b/filter/filter.h index 1052f8c8..c100a79a 100644 --- a/filter/filter.h +++ b/filter/filter.h @@ -39,7 +39,7 @@ struct f_inst_roa_check { }; struct f_prefix { - net_addr_union net; + net_addr net; u8 lo, hi; }; diff --git a/filter/test.conf b/filter/test.conf index a99d0a51..c3f74d94 100644 --- a/filter/test.conf +++ b/filter/test.conf @@ -16,6 +16,10 @@ define ten = 10; define p23 = (2, 3); define ip1222 = 1.2.2.2; +define net10 = 10.0.0.0/8; +define netdoc = 2001:db8::/32; + + function onef(int a) { return 1; @@ -55,6 +59,7 @@ function fifteen() return 15; } +/* roa table rl { roa 10.110.0.0/16 max 16 as 1000; @@ -80,6 +85,7 @@ function test_roa() " ", roa_check(rl, 10.130.30.0/24, 3000) = ROA_INVALID, " ", roa_check(rl, 10.130.130.0/24, 3000) = ROA_VALID; } +*/ function path_test() bgpmask pm1; @@ -232,7 +238,7 @@ function __test2() function test_pxset(prefix set pxs) { print pxs; - print " must be true: ", 10.0.0.0/8 ~ pxs, ",", 10.0.0.0/10 ~ pxs, ",", 10.0.0.0/12 ~ pxs, ",", + print " must be true: ", net10 ~ pxs, ",", 10.0.0.0/10 ~ pxs, ",", 10.0.0.0/12 ~ pxs, ",", 20.0.0.0/24 ~ pxs, ",", 20.0.40.0/24 ~ pxs, ",", 20.0.0.0/26 ~ pxs, ",", 20.0.100.0/26 ~ pxs, ",", 20.0.0.0/28 ~ pxs, ",", 20.0.255.0/28 ~ pxs; print " must be false: ", 10.0.0.0/7 ~ pxs, ",", 10.0.0.0/13 ~ pxs, ",", 10.0.0.0/16 ~ pxs, ",", @@ -312,12 +318,12 @@ string st; px = 1.2.0.0/18; print "Testing prefixes: 1.2.0.0/18 = ", px; - print " must be true: ", 192.168.0.0/16 ~ 192.168.0.0/16, " ", 192.168.0.0/17 ~ 192.168.0.0/16, " ", 192.168.254.0/24 ~ 192.168.0.0/16; - print " must be false: ", 192.168.0.0/15 ~ 192.168.0.0/16, " ", 192.160.0.0/17 ~ 192.168.0.0/16; + print " must be true: ", 192.168.0.0/16 ~ 192.168.0.0/16, " ", 192.168.0.0/17 ~ 192.168.0.0/16, " ", 192.168.254.0/24 ~ 192.168.0.0/16, " ", netdoc ~ 2001::/16; + print " must be false: ", 192.168.0.0/15 ~ 192.168.0.0/16, " ", 192.160.0.0/17 ~ 192.168.0.0/16, " ", px ~ netdoc; p = 127.1.2.3; print "Testing mask : 127.0.0.0 = ", p.mask(8); - + pp = (1, 2); print "Testing pairs: (1,2) = ", (1,2), " = ", pp, " = ", (1,1+1), " = ", 'mkpair-a'(2); print " must be true: ", (1,2) = (1,1+1); @@ -397,7 +403,7 @@ string st; print "1.2.3.4 = ", onetwo; i = 4200000000; - print "4200000000 = ", i, " false: ", i = 4200000000, " ", i > 4100000000, " false: ", i > 4250000000; + print "4200000000 = ", i, " true: ", i = 4200000000, " ", i > 4100000000, " false: ", i > 4250000000; test_undef(2); test_undef(3); @@ -67,7 +67,7 @@ ip6_masklen(ip6_addr *a) if (a->addr[i] != ~0U) { j = u32_masklen(a->addr[i]); - if (j < 0) + if (j == 255) return j; n += j; while (++i < 4) @@ -91,6 +91,9 @@ typedef ip6_addr ip_addr; #define ipa_is_ip4(a) ip6_is_v4mapped(a) +#define IPA_NONE4 ipa_from_ip4(IP4_NONE) +#define IPA_NONE6 ipa_from_ip6(IP6_NONE) + /* * Public constructors @@ -180,16 +183,7 @@ static inline int ipa_nonzero2(ip_addr a) * Hash and compare functions */ -static inline uint ip4_hash(ip4_addr a) -{ - /* Returns a 16-bit value */ - u32 x = _I(a); - x ^= x >> 16; - x ^= x << 10; - return x & 0xffff; -} - -static inline u32 ip4_hash32(ip4_addr a) +static inline u32 ip4_hash(ip4_addr a) { /* Returns a 32-bit value, although low-order bits are not mixed */ u32 x = _I(a); @@ -198,14 +192,7 @@ static inline u32 ip4_hash32(ip4_addr a) return x; } -static inline uint ip6_hash(ip6_addr a) -{ - /* Returns a 16-bit hash key */ - u32 x = _I0(a) ^ _I1(a) ^ _I2(a) ^ _I3(a); - return (x ^ (x >> 16) ^ (x >> 8)) & 0xffff; -} - -static inline u32 ip6_hash32(ip6_addr a) +static inline u32 ip6_hash(ip6_addr a) { /* Returns a 32-bit hash key, although low-order bits are not mixed */ u32 x = _I0(a) ^ _I1(a) ^ _I2(a) ^ _I3(a); @@ -218,7 +205,6 @@ static inline int ip4_compare(ip4_addr a, ip4_addr b) int ip6_compare(ip6_addr a, ip6_addr b); #define ipa_hash(x) ip6_hash(x) -#define ipa_hash32(x) ip6_hash32(x) #define ipa_compare(x,y) ip6_compare(x,y) @@ -107,6 +107,17 @@ static inline void net_fill_ipa(net_addr *a, ip_addr prefix, uint pxlen) net_fill_ip6(a, ipa_to_ip6(prefix), pxlen); } +static inline void net_fill_ip_host(net_addr *a, ip_addr prefix) +{ + if (ipa_is_ip4(prefix)) + net_fill_ip4(a, ipa_to_ip4(prefix), IP4_MAX_PREFIX_LENGTH); + else + net_fill_ip6(a, ipa_to_ip6(prefix), IP6_MAX_PREFIX_LENGTH); +} + +static inline int net_is_ip(const net_addr *a) +{ return (a->type == NET_IP4) || (a->type == NET_IP6); } + static inline ip4_addr net4_prefix(const net_addr *a) { return ((net_addr_ip4 *) a)->prefix; } @@ -199,20 +210,20 @@ static inline void net_copy_vpn6(net_addr_vpn6 *dst, const net_addr_vpn6 *src) static inline u32 net_hash_ip4(const net_addr_ip4 *n) -{ return ip4_hash32(n->prefix) ^ ((u32) n->pxlen << 26); } +{ return ip4_hash(n->prefix) ^ ((u32) n->pxlen << 26); } static inline u32 net_hash_ip6(const net_addr_ip6 *n) -{ return ip6_hash32(n->prefix) ^ ((u32) n->pxlen << 26); } +{ return ip6_hash(n->prefix) ^ ((u32) n->pxlen << 26); } /* XXXX */ -static inline u32 u64_hash(u32 a) +static inline u32 u64_hash(u64 a) { return u32_hash(a); } static inline u32 net_hash_vpn4(const net_addr_vpn4 *n) -{ return ip4_hash32(n->prefix) ^ ((u32) n->pxlen << 26) ^ u64_hash(n->rd); } +{ return ip4_hash(n->prefix) ^ ((u32) n->pxlen << 26) ^ u64_hash(n->rd); } static inline u32 net_hash_vpn6(const net_addr_vpn6 *n) -{ return ip6_hash32(n->prefix) ^ ((u32) n->pxlen << 26) ^ u64_hash(n->rd); } +{ return ip6_hash(n->prefix) ^ ((u32) n->pxlen << 26) ^ u64_hash(n->rd); } static inline int net_validate_ip4(const net_addr_ip4 *n) diff --git a/nest/config.Y b/nest/config.Y index 9d20dd48..963393cc 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->prefix.pxlen) /* XXXX */ + if (!pn->pattern || pn->prefix.type) cf_error("Interface name/mask expected, not IP prefix"); } @@ -85,7 +85,7 @@ CF_GRAMMAR CF_ADDTO(conf, rtrid) -rtrid: +rtrid: ROUTER ID idval ';' { new_config->router_id = $3; } | ROUTER ID FROM iface_patt ';' { new_config->router_id_from = this_ipatt; } ; @@ -261,8 +261,8 @@ iface_patt_node_init: ; iface_patt_node_body: - 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; } + TEXT { this_ipn->pattern = $1; /* this_ipn->prefix stays zero */ } + | opttext net_or_ipa { this_ipn->pattern = $1; this_ipn->prefix = $2; } ; iface_negate: @@ -271,7 +271,7 @@ iface_negate: ; iface_patt_node: - iface_patt_node_init iface_negate iface_patt_node_body + iface_patt_node_init iface_negate iface_patt_node_body ; @@ -450,14 +450,15 @@ r_args: } | r_args net_any { $$ = $1; - if ($$->prefix) cf_error("Only one prefix expected"); - $$->prefix = $2; + if ($$->addr) cf_error("Only one prefix expected"); + $$->addr = $2; } | r_args FOR net_or_ipa { $$ = $1; - if ($$->prefix) cf_error("Only one prefix expected"); - $$->prefix = &($3.n); + if ($$->addr) cf_error("Only one prefix expected"); $$->show_for = 1; + $$->addr = cfg_alloc($3.length); + net_copy($$->addr, &($3)); } | r_args TABLE SYM { $$ = $1; diff --git a/nest/neighbor.c b/nest/neighbor.c index 5b525fa9..74c3c664 100644 --- a/nest/neighbor.c +++ b/nest/neighbor.c @@ -45,6 +45,7 @@ #include "lib/resource.h" #define NEIGH_HASH_SIZE 256 +#define NEIGH_HASH_OFFSET 24 static slab *neigh_slab; static list sticky_neigh_list, neigh_hash_table[NEIGH_HASH_SIZE]; @@ -52,7 +53,7 @@ static list sticky_neigh_list, neigh_hash_table[NEIGH_HASH_SIZE]; static inline uint neigh_hash(struct proto *p, ip_addr *a) { - return (p->hash_key ^ ipa_hash(*a)) & (NEIGH_HASH_SIZE-1); + return (p->hash_key ^ ipa_hash(*a)) >> NEIGH_HASH_OFFSET; } static int diff --git a/nest/route.h b/nest/route.h index a30a3880..fbafe293 100644 --- a/nest/route.h +++ b/nest/route.h @@ -56,7 +56,7 @@ struct fib { struct fib_node **hash_table; /* Node hash table */ 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 hash_shift; /* 32 - hash_order */ uint addr_type; /* Type of address data stored in fib (NET_*) */ uint node_size; /* XXXX */ uint node_offset; /* XXXX */ @@ -277,11 +277,6 @@ void rt_setup(pool *, rtable *, char *, struct rtable_config *); 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); @@ -313,7 +308,7 @@ rt_mark_for_prune(rtable *tab) } struct rt_show_data { - net_addr *prefix; + net_addr *addr; rtable *table; struct filter *filter; int verbose; diff --git a/nest/rt-attr.c b/nest/rt-attr.c index 7fa05d6d..d100c537 100644 --- a/nest/rt-attr.c +++ b/nest/rt-attr.c @@ -195,10 +195,10 @@ rt_prune_sources(void) * Multipath Next Hop */ -static inline uint +static inline u32 mpnh_hash(struct mpnh *x) { - uint h = 0; + u32 h = 0; for (; x; x = x->next) h ^= ipa_hash(x->gw); @@ -1008,8 +1008,9 @@ rta_alloc_hash(void) static inline uint rta_hash(rta *a) { - return (((uint) (uintptr_t) a->src) ^ ipa_hash(a->gw) ^ - mpnh_hash(a->nexthops) ^ ea_hash(a->eattrs)) & 0xffff; + /* XXXX fully convert to u32 hashing */ + return (((uint) (uintptr_t) a->src) ^ (ipa_hash(a->gw) >> 16) ^ + (mpnh_hash(a->nexthops) >> 16) ^ ea_hash(a->eattrs)) & 0xffff; } static inline int diff --git a/nest/rt-fib.c b/nest/rt-fib.c index c12d0519..c83ae171 100644 --- a/nest/rt-fib.c +++ b/nest/rt-fib.c @@ -43,7 +43,7 @@ #define HASH_DEF_ORDER 10 #define HASH_HI_MARK *4 #define HASH_HI_STEP 2 -#define HASH_HI_MAX 16 /* Must be at most 16 */ +#define HASH_HI_MAX 16 #define HASH_LO_MARK /5 #define HASH_LO_STEP 2 #define HASH_LO_MIN 10 @@ -266,38 +266,32 @@ fib_get(struct fib *f, const net_addr *a) return b; } -static void * -fib_route_ip4(struct fib *f, const net_addr *n0) +static inline void * +fib_route_ip4(struct fib *f, net_addr_ip4 *n) { - net_addr net; - net_addr_ip4 *n = (net_addr_ip4 *) &net; - void *b; + void *r; - net_copy(&net, n0); - while (!(b = fib_find(f, &net)) && (n->pxlen > 0)) + while (!(r = fib_find(f, (net_addr *) n)) && (n->pxlen > 0)) { n->pxlen--; ip4_clrbit(&n->prefix, n->pxlen); } - return b; + return r; } -static void * -fib_route_ip6(struct fib *f, const net_addr *n0) +static inline void * +fib_route_ip6(struct fib *f, net_addr_ip6 *n) { - net_addr net; - net_addr_ip6 *n = (net_addr_ip6 *) &net; - void *b; + void *r; - net_copy(&net, n0); - while (!(b = fib_find(f, &net)) && (n->pxlen > 0)) + while (!(r = fib_find(f, (net_addr *) n)) && (n->pxlen > 0)) { n->pxlen--; ip6_clrbit(&n->prefix, n->pxlen); } - return b; + return r; } /** @@ -314,21 +308,25 @@ fib_route(struct fib *f, const net_addr *n) { ASSERT(f->addr_type == n->type); + net_addr *n0 = alloca(n->length); + net_copy(n0, n); + switch (n->type) { case NET_IP4: case NET_VPN4: - return fib_route_ip4(f, n); + return fib_route_ip4(f, (net_addr_ip4 *) n0); case NET_IP6: case NET_VPN6: - return fib_route_ip6(f, n); + return fib_route_ip6(f, (net_addr_ip6 *) n0); default: return NULL; } } + static inline void fib_merge_readers(struct fib_iterator *i, struct fib_node *to) { @@ -398,7 +396,12 @@ fib_delete(struct fib *f, void *E) } fib_merge_readers(it, l); } - sl_free(f->fib_slab, e); + + if (f->fib_slab) + sl_free(f->fib_slab, E); + else + mb_free(E); + if (f->entries-- < f->entries_min) fib_rehash(f, -HASH_LO_STEP); return; diff --git a/nest/rt-table.c b/nest/rt-table.c index 963c8fbd..7c72aa4a 100644 --- a/nest/rt-table.c +++ b/nest/rt-table.c @@ -68,25 +68,60 @@ make_tmp_attrs(struct rte *rt, struct linpool *pool) return mta ? mta(rt, rte_update_pool) : NULL; } + /* Like fib_route(), but skips empty net entries */ -/* -static net * -net_route(rtable *tab, ip_addr a, int len) +static inline void * +net_route_ip4(struct fib *f, net_addr_ip4 *n) { - ip_addr a0; - net *n; + net *r; - while (len >= 0) - { - a0 = ipa_and(a, ipa_mkmask(len)); - n = fib_find(&tab->fib, &a0, len); - if (n && rte_is_valid(n->routes)) - return n; - len--; - } - return NULL; + while (r = fib_find(f, (net_addr *) n), + !(r && rte_is_valid(r->routes)) && (n->pxlen > 0)) + { + n->pxlen--; + ip4_clrbit(&n->prefix, n->pxlen); + } + + return r; +} + +static inline void * +net_route_ip6(struct fib *f, net_addr_ip6 *n) +{ + net *r; + + while (r = fib_find(f, (net_addr *) n), + !(r && rte_is_valid(r->routes)) && (n->pxlen > 0)) + { + n->pxlen--; + ip6_clrbit(&n->prefix, n->pxlen); + } + + return r; +} + +void * +net_route(rtable *tab, const net_addr *n) +{ + ASSERT(f->addr_type == n->type); + + net_addr *n0 = alloca(n->length); + net_copy(n0, n); + + switch (n->type) + { + case NET_IP4: + case NET_VPN4: + return net_route_ip4(&tab->fib, (net_addr_ip4 *) n0); + + case NET_IP6: + case NET_VPN6: + return net_route_ip6(&tab->fib, (net_addr_ip6 *) n0); + + default: + return NULL; + } } -*/ /** * rte_find - find a route @@ -2040,10 +2075,10 @@ ptr_hash(void *ptr) return p ^ (p << 8) ^ (p >> 16); } -static inline unsigned +static inline u32 hc_hash(ip_addr a, rtable *dep) { - return (ipa_hash(a) ^ ptr_hash(dep)) & 0xffff; + return ipa_hash(a) ^ ptr_hash(dep); } static inline void @@ -2077,7 +2112,7 @@ hc_alloc_table(struct hostcache *hc, unsigned order) { unsigned hsize = 1 << order; hc->hash_order = order; - hc->hash_shift = 16 - order; + hc->hash_shift = 32 - order; hc->hash_max = (order >= HC_HI_ORDER) ? ~0 : (hsize HC_HI_MARK); hc->hash_min = (order <= HC_LO_ORDER) ? 0 : (hsize HC_LO_MARK); @@ -2178,14 +2213,11 @@ rt_free_hostcache(rtable *tab) static void rt_notify_hostcache(rtable *tab, net *net) { - struct hostcache *hc = tab->hostcache; - if (tab->hcu_scheduled) return; - // XXXX - // if (trie_match_prefix(hc->trie, net->n.prefix, net->n.pxlen)) - // rt_schedule_hcu(tab); + if (trie_match_net(tab->hostcache->trie, net->n.addr)) + rt_schedule_hcu(tab); } static int @@ -2235,15 +2267,15 @@ rt_update_hostentry(rtable *tab, struct hostentry *he) rta *old_src = he->src; int pxlen = 0; - /* Reset the hostentry */ + /* Reset the hostentry */ he->src = NULL; he->gw = IPA_NONE; he->dest = RTD_UNREACHABLE; he->igp_metric = 0; - // XXXX - // net *n = net_route(tab, he->addr, MAX_PREFIX_LENGTH); - net *n = NULL; + net_addr he_addr; + net_fill_ip_host(&he_addr, he->addr); + net *n = net_route(tab, &he_addr); if (n) { rte *e = n->routes; @@ -2285,12 +2317,7 @@ rt_update_hostentry(rtable *tab, struct hostentry *he) done: /* Add a prefix range to the trie */ - /* XXXX - if (ipa_is_ip4(he->addr)) - trie_add_prefix(tab->hostcache->trie, he->addr, IP4_MAX_PREFIX_LENGTH, pxlen, IP4_MAX_PREFIX_LENGTH); - else - trie_add_prefix(tab->hostcache->trie, he->addr, IP6_MAX_PREFIX_LENGTH, pxlen, IP6_MAX_PREFIX_LENGTH); - */ + trie_add_prefix(tab->hostcache->trie, &he_addr, pxlen, he_addr.pxlen); rta_free(old_src); return old_src != he->src; @@ -2331,7 +2358,7 @@ rt_get_hostentry(rtable *tab, ip_addr a, ip_addr ll, rtable *dep) if (!tab->hostcache) rt_init_hostcache(tab); - uint k = hc_hash(a, dep); + u32 k = hc_hash(a, dep); struct hostcache *hc = tab->hostcache; for (he = hc->hash_table[k >> hc->hash_shift]; he != NULL; he = he->next) if (ipa_equal(he->addr, a) && (he->tab == dep)) @@ -2575,7 +2602,7 @@ rt_show(struct rt_show_data *d) if (d->filtered && (d->export_mode || d->primary_only)) cli_msg(0, ""); - if (!d->prefix) + if (!d->addr) { FIB_ITERATE_INIT(&d->fit, &d->table->fib); this_cli->cont = rt_show_cont; @@ -2584,13 +2611,10 @@ rt_show(struct rt_show_data *d) } else { - /* XXXX if (d->show_for) - n = net_route(d->table, d->prefix, d->pxlen); + n = net_route(d->table, d->addr); else - n = net_find(d->table, d->prefix, d->pxlen); - */ - n = NULL; + n = net_find(d->table, d->addr); if (n) rt_show_net(this_cli, n, d); diff --git a/proto/bfd/bfd.c b/proto/bfd/bfd.c index 7a085791..3ba3a5d9 100644 --- a/proto/bfd/bfd.c +++ b/proto/bfd/bfd.c @@ -112,7 +112,7 @@ #define HASH_IP_KEY(n) n->addr #define HASH_IP_NEXT(n) n->next_ip #define HASH_IP_EQ(a,b) ipa_equal(a,b) -#define HASH_IP_FN(k) ipa_hash32(k) +#define HASH_IP_FN(k) ipa_hash(k) static list bfd_proto_list; static list bfd_wait_list; diff --git a/proto/ospf/config.Y b/proto/ospf/config.Y index 5673ef60..881ec781 100644 --- a/proto/ospf/config.Y +++ b/proto/ospf/config.Y @@ -220,7 +220,7 @@ ospf_stubnet_start: net_ip { this_stubnet = cfg_allocz(sizeof(struct ospf_stubnet_config)); add_tail(&this_area->stubnet_list, NODE this_stubnet); - this_stubnet->prefix = $1.n; + this_stubnet->prefix = $1; this_stubnet->cost = COST_D; } ; @@ -330,7 +330,7 @@ pref_base: net_ip { this_pref = cfg_allocz(sizeof(struct area_net_config)); add_tail(this_nets, NODE this_pref); - this_pref->prefix = $1.n; + this_pref->prefix = $1; } ; diff --git a/proto/ospf/iface.c b/proto/ospf/iface.c index 442cec3a..8c997ced 100644 --- a/proto/ospf/iface.c +++ b/proto/ospf/iface.c @@ -581,6 +581,7 @@ ospf_iface_new(struct ospf_area *oa, struct ifa *addr, struct ospf_iface_patt *i if (ip->ptp_netmask < 2) ifa->ptp_netmask = ip->ptp_netmask; + ifa->drip = ifa->bdrip = ospf_is_v2(p) ? IPA_NONE4 : IPA_NONE6; ifa->type = ospf_iface_classify(ip->type, addr); @@ -1333,7 +1334,7 @@ ospf_iface_info(struct ospf_iface *ifa) else if (ifa->addr->flags & IA_PEER) cli_msg(-1015, "Interface %s (peer %I)", ifa->ifname, ifa->addr->opposite); else - cli_msg(-1015, "Interface %s (%N)", ifa->ifname, ifa->addr->prefix); + cli_msg(-1015, "Interface %s (%N)", ifa->ifname, &ifa->addr->prefix); cli_msg(-1015, "\tType: %s%s", ospf_it[ifa->type], more); cli_msg(-1015, "\tArea: %R (%u)", ifa->oa->areaid, ifa->oa->areaid); diff --git a/proto/ospf/neighbor.c b/proto/ospf/neighbor.c index c5d44dec..b30b0438 100644 --- a/proto/ospf/neighbor.c +++ b/proto/ospf/neighbor.c @@ -506,13 +506,14 @@ ospf_dr_election(struct ospf_iface *ifa) u32 old_drid = ifa->drid; u32 old_bdrid = ifa->bdrid; + ip_addr none = ospf_is_v2(p) ? IPA_NONE4 : IPA_NONE6; ifa->drid = ndr ? ndr->rid : 0; - ifa->drip = ndr ? ndr->ip : IPA_NONE; + ifa->drip = ndr ? ndr->ip : none; ifa->dr_iface_id = ndr ? ndr->iface_id : 0; ifa->bdrid = nbdr ? nbdr->rid : 0; - ifa->bdrip = nbdr ? nbdr->ip : IPA_NONE; + ifa->bdrip = nbdr ? nbdr->ip : none; DBG("DR=%R, BDR=%R\n", ifa->drid, ifa->bdrid); diff --git a/proto/ospf/packet.c b/proto/ospf/packet.c index 9690c28a..35ef7c6e 100644 --- a/proto/ospf/packet.c +++ b/proto/ospf/packet.c @@ -500,8 +500,8 @@ ospf_send_to_agt(struct ospf_iface *ifa, u8 state) void ospf_send_to_bdr(struct ospf_iface *ifa) { - if (ipa_nonzero(ifa->drip)) + if (ipa_nonzero2(ifa->drip)) ospf_send_to(ifa, ifa->drip); - if (ipa_nonzero(ifa->bdrip)) + if (ipa_nonzero2(ifa->bdrip)) ospf_send_to(ifa, ifa->bdrip); } diff --git a/proto/radv/config.Y b/proto/radv/config.Y index efb474a6..5e655de4 100644 --- a/proto/radv/config.Y +++ b/proto/radv/config.Y @@ -150,7 +150,7 @@ radv_iface: radv_prefix_start: net_ip6 { this_radv_prefix = cfg_allocz(sizeof(struct radv_prefix_config)); - RADV_PREFIX->prefix = $1.ip6; + RADV_PREFIX->prefix = *(net_addr_ip6 *) &($1); RADV_PREFIX->onlink = 1; RADV_PREFIX->autonomous = 1; diff --git a/sysdep/unix/krt.Y b/sysdep/unix/krt.Y index eb0ae109..80bf97ec 100644 --- a/sysdep/unix/krt.Y +++ b/sysdep/unix/krt.Y @@ -69,7 +69,7 @@ kif_item: } | PRIMARY opttext net_or_ipa { struct kif_primary_item *kpi = cfg_alloc(sizeof (struct kif_primary_item)); - kpi->addr = $3.n; + kpi->addr = $3; add_tail(&THIS_KIF->primary, &kpi->n); } ; |