summaryrefslogtreecommitdiff
path: root/nest
diff options
context:
space:
mode:
Diffstat (limited to 'nest')
-rw-r--r--nest/config.Y19
-rw-r--r--nest/neighbor.c3
-rw-r--r--nest/route.h9
-rw-r--r--nest/rt-attr.c9
-rw-r--r--nest/rt-fib.c43
-rw-r--r--nest/rt-table.c104
6 files changed, 106 insertions, 81 deletions
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);