summaryrefslogtreecommitdiff
path: root/nest
diff options
context:
space:
mode:
Diffstat (limited to 'nest')
-rw-r--r--nest/Makefile2
-rw-r--r--nest/bird.h1
-rw-r--r--nest/config.Y45
-rw-r--r--nest/iface.c31
-rw-r--r--nest/iface.h6
-rw-r--r--nest/neighbor.c2
-rw-r--r--nest/route.h43
-rw-r--r--nest/rt-dev.c4
-rw-r--r--nest/rt-fib.c207
-rw-r--r--nest/rt-table.c82
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; }
/**