0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2025-01-03 07:31:54 +00:00

Temporary integrated commit.

This one mostly merges patches from Alexander Chernikov.
This commit is contained in:
Ondrej Zajicek 2012-06-23 10:13:32 +02:00
parent b9c8061b19
commit ed6c144066
19 changed files with 356 additions and 127 deletions

View File

@ -833,7 +833,7 @@ interpret(struct f_inst *what)
case T_STRING: /* Warning: this is a special case for proto attribute */
res.val.s = rta->proto->name;
break;
case T_PREFIX: /* Warning: this works only for prefix of network */
case T_PREFIX: /* Warning: this works only for RT_IP prefix of network */
{
res.val.px.ip = (*f_rte)->net->n.prefix;
res.val.px.len = (*f_rte)->net->n.pxlen;

View File

@ -349,7 +349,23 @@ ip_scope_text(unsigned scope)
return scope_table[scope];
}
#include "nest/route.h"
void
fn_print(char *buf, int buflen, struct fib_node *n)
{
// XXXX temporary
switch (n->addr_type)
{
case RT_IPV4:
case RT_IPV6:
bsprintf(buf, "%I/%d", n->prefix, n->pxlen);
break;
default:
bsprintf(buf, "???");
break;
}
}
#if 0

View File

@ -390,6 +390,8 @@ static inline int ipa_classify_net(ip_addr a)
#define STD_ADDRESS_P_LENGTH 39
#define SIZE_OF_IP_HEADER 40
#define MAX_ADDRESS_P_LENGTH 40
#define ipa_class_mask(x) _MI4(ipv4_class_mask(_I(x)))
@ -402,6 +404,8 @@ static inline int ipa_classify_net(ip_addr a)
u32 ipv4_class_mask(u32);
byte *ipv4_skip_header(byte *, int *);
struct fib_node;
void fn_print(char *buf, int buflen, struct fib_node *n);

View File

@ -139,7 +139,7 @@ int bvsnprintf(char *buf, int size, const char *fmt, va_list args)
u32 x;
char *str, *start;
const char *s;
char ipbuf[STD_ADDRESS_P_LENGTH+1];
char ipbuf[MAX_ADDRESS_P_LENGTH];
struct iface *iface;
int flags; /* flags to number() */
@ -298,6 +298,12 @@ int bvsnprintf(char *buf, int size, const char *fmt, va_list args)
s = iface->name;
goto str;
/* Generic address - pointer to fib_node */
case 'F': // XXXX probably remove/replace
fn_print(ipbuf, sizeof(ipbuf), va_arg(args, struct fib_node *));
s = ipbuf;
goto str;
/* Router/Network ID - essentially IPv4 address in u32 value */
case 'R':
x = va_arg(args, u32);

View File

@ -36,6 +36,16 @@ get_u32(void *p)
return ntohl(x);
}
static inline u64
get_u64(void *p)
{
u32 xh, xl;
memcpy(&xh, p, 4);
memcpy(&xl, p+4, 4);
return (((u64) ntohl(xh)) << 32) | ntohl(xl);
}
static inline void
put_u16(void *p, u16 x)
{
@ -50,4 +60,15 @@ put_u32(void *p, u32 x)
memcpy(p, &x, 4);
}
static inline void
put_u64(void *p, u64 x)
{
u32 xh, xl;
xh = htonl(x >> 32);
xl = htonl((u32) x);
memcpy(p, &xh, 4);
memcpy(p+4, &xl, 4);
}
#endif

View File

@ -108,7 +108,7 @@ listen_opt:
CF_ADDTO(conf, newtab)
newtab: TABLE SYM {
rt_new_table($2);
rt_new_table($2, RT_IP);
}
;

View File

@ -37,9 +37,10 @@ struct fib_node {
struct fib_iterator *readers; /* List of readers of this node */
byte pxlen;
byte flags; /* User-defined */
byte x0, x1; /* User-defined */
byte addr_type; /* User-defined */
byte addr_off; /* address data offset */
u32 uid; /* Unique ID based on hash */
ip_addr prefix; /* In host order */
ip_addr prefix; /* Address data in host order (if it fits in ip_addr length) */
};
struct fib_iterator { /* See lib/slists.h for an explanation */
@ -50,7 +51,9 @@ struct fib_iterator { /* See lib/slists.h for an explanation */
unsigned int hash;
};
struct fib;
typedef void (*fib_init_func)(struct fib_node *);
typedef u32 (*fib_hash_func)(struct fib *, void *);
struct fib {
pool *fib_pool; /* Pool holding all our data */
@ -59,23 +62,38 @@ struct fib {
unsigned int hash_size; /* Number of hash table entries (a power of two) */
unsigned int hash_order; /* Binary logarithm of hash_size */
unsigned int hash_shift; /* 16 - hash_log */
unsigned int addr_type; /* Type of adresses stored in fib (IPv46, VPNv46, MPLS, etc..)*/
unsigned int addr_size; /* Size of address data */
unsigned int addr_off; /* Address data offset from the structure beginning */
unsigned int entries; /* Number of entries */
unsigned int entries_min, entries_max;/* Entry count limits (else start rehashing) */
fib_init_func init; /* Constructor */
fib_hash_func hash_f; /* Optional hash function */
};
void fib_init(struct fib *, pool *, unsigned node_size, unsigned hash_order, fib_init_func init);
void *fib_find(struct fib *, ip_addr *, int); /* Find or return NULL if doesn't exist */
void *fib_get(struct fib *, ip_addr *, int); /* Find or create new if nonexistent */
void *fib_route(struct fib *, ip_addr, int); /* Longest-match routing lookup */
void fib2_init(struct fib *, pool *, unsigned node_size, unsigned int addr_type, unsigned int addr_size, \
unsigned hash_order, fib_init_func init, fib_hash_func hash_f);
void *fib_find(struct fib *, void *, int); /* Find or return NULL if doesn't exist */
void *fib_get(struct fib *, void *, int); /* Find or create new if nonexistent */
void *fib_route(struct fib *, ip_addr *, int); /* Longest-match routing lookup */
void fib_delete(struct fib *, void *); /* Remove fib entry */
void fib_free(struct fib *); /* Destroy the fib */
void fib_check(struct fib *); /* Consistency check for debugging */
u32 ip_hash(struct fib *f, void *a); /* Hashing function for RT_IP fib types */
// u32 vpn_hash(struct fib *f, void *a); /* Hashing function for RT_VPN fib types */
void fit_init(struct fib_iterator *, struct fib *); /* Internal functions, don't call */
struct fib_node *fit_get(struct fib *, struct fib_iterator *);
void fit_put(struct fib_iterator *, struct fib_node *);
#define fib_hash(f, a) (f)->hash_f(f, a)
#define FPREFIX(n) ((void *)(((char *)(n)) + (n)->addr_off))
#define FPREFIX_IP(n) (&(n)->prefix)
// XXXX define FPREFIX_VPN(n) ((vpn_addr *)FPREFIX(n))
#define PROTO_FIB(x) ((x)->table->fib.addr_type)
#define FIB_WALK(fib, z) do { \
struct fib_node *z, **ff = (fib)->hash_table; \
unsigned int count = (fib)->hash_size; \
@ -117,6 +135,7 @@ void fit_put(struct fib_iterator *, struct fib_node *);
struct rtable_config {
node n;
char *name;
int addr_type; /* Type of address data stored in table (IPv46, VPNv46, etc..) */
struct rtable *table;
struct proto_config *krt_attached; /* Kernel syncer attached to this table */
int gc_max_ops; /* Maximum number of operations before GC is run */
@ -127,6 +146,7 @@ typedef struct rtable {
node n; /* Node in list of all tables */
struct fib fib;
char *name; /* Name of this table */
int addr_type; /* Type of address data stored in table (IPv46, VPNv46, etc..) */
list hooks; /* List of announcement hooks */
int pipe_busy; /* Pipe loop detection */
int use_count; /* Number of protocols using this table */
@ -221,6 +241,26 @@ typedef struct rte {
#define REF_COW 1 /* Copy this rte on write */
/* Types of routing tables/entries */
#define RT_IPV4 1
#define RT_IPV6 2
#define RT_VPN4 3
#define RT_VPN6 4
#define RT_MPLS 5
#define RT_MAX 6
/* Same tables using bit positions. Used for appropriate table linking on protocol init */
#define RTB_IPV4 (1 << RT_IPV4)
#define RTB_IPV6 (1 << RT_IPV6)
#define RTB_VPN4 (1 << RT_VPN4)
#define RTB_VPN6 (1 << RT_VPN6)
#define RTB_MPLS (1 << RT_MPLS)
#define RT_IP RT_IPV6
#define RTB_IP RTB_IPV6
/* Types of route announcement, also used as flags */
#define RA_OPTIMAL 1 /* Announcement of optimal route change */
#define RA_ANY 2 /* Announcement of any route change */
@ -250,7 +290,9 @@ int rt_feed_baby(struct proto *p);
void rt_feed_baby_abort(struct proto *p);
void rt_schedule_prune_all(void);
int rt_prune_loop(void);
struct rtable_config *rt_new_table(struct symbol *s);
struct rtable_config *rt_new_table(struct symbol *s, int addr_type);
int rt_addrsize(int addr_type); // XXXX needed?
struct rt_show_data {
ip_addr prefix;

View File

@ -72,10 +72,10 @@ fib_ht_free(struct fib_node **h)
mb_free(h);
}
static inline unsigned
fib_hash(struct fib *f, ip_addr *a)
u32
ip_hash(struct fib *f, void *a)
{
return ipa_hash(*a) >> f->hash_shift;
return ipa_hash(*((ip_addr *)a)) >> f->hash_shift;
}
static void
@ -97,17 +97,53 @@ fib_dummy_init(struct fib_node *dummy UNUSED)
*/
void
fib_init(struct fib *f, pool *p, unsigned node_size, unsigned hash_order, fib_init_func init)
{
fib2_init(f, p, node_size, RT_IP, sizeof(ip_addr), hash_order, init, ip_hash);
}
/**
* fib2_init - initialize a new FIB
* @f: the FIB to be initialized (the structure itself being allocated by the caller)
* @p: pool to allocate the nodes in
* @node_size: total node size to be used (each node consists of a standard header &fib_node
* followed by user data)
* @addr_type: type of addresses stored in fib (RT_*)
* @addr_size: size of address data
* @hash_order: initial hash order (a binary logarithm of hash table size), 0 to use default order
* (recommended)
* @init: pointer a function to be called to initialize a newly created node
* @hash_p: mandatory pointer a function to be called to hash node
*
* This function initializes a newly allocated FIB and prepares it for use. Note node_size
* cannot exceed 255 bytes for address types not fitting into ip_addr
*/
void
fib2_init(struct fib *f, pool *p, unsigned node_size, unsigned int addr_type, unsigned int addr_size, \
unsigned hash_order, fib_init_func init, fib_hash_func hash_f)
{
if (!hash_order)
hash_order = HASH_DEF_ORDER;
f->fib_pool = p;
if (addr_size > sizeof(ip_addr))
{
node_size = BIRD_ALIGN(node_size, CPU_STRUCT_ALIGN);
f->addr_off = node_size;
node_size += addr_size;
}
else
f->addr_off = OFFSETOF(struct fib_node, prefix);
f->fib_slab = sl_new(p, node_size);
f->hash_order = hash_order;
fib_ht_alloc(f);
bzero(f->hash_table, f->hash_size * sizeof(struct fib_node *));
f->addr_type = addr_type;
f->addr_size = addr_size;
f->entries = 0;
f->entries_min = 0;
f->init = init ? : fib_dummy_init;
f->hash_f = hash_f;
}
static void
@ -133,7 +169,7 @@ fib_rehash(struct fib *f, int step)
while (e = x)
{
x = e->next;
nh = fib_hash(f, &e->prefix);
nh = fib_hash(f, FPREFIX(e));
while (nh > ni)
{
*t = NULL;
@ -163,11 +199,11 @@ fib_rehash(struct fib *f, int step)
* a pointer to it or %NULL if no such node exists.
*/
void *
fib_find(struct fib *f, ip_addr *a, int len)
fib_find(struct fib *f, void *a, int len)
{
struct fib_node *e = f->hash_table[fib_hash(f, a)];
while (e && (e->pxlen != len || !ipa_equal(*a, e->prefix)))
while (e && (e->pxlen != len || memcmp(a, FPREFIX(e), f->addr_size)))
e = e->next;
return e;
}
@ -197,26 +233,26 @@ fib_histogram(struct fib *f)
/**
* fib_get - find or create a FIB node
* @f: FIB to work with
* @a: pointer to IP address of the prefix
* @len: prefix length
* @a: pointer to IP (or other family) address of the prefix
* @len: prefix length (if address family requires it)
*
* Search for a FIB node corresponding to the given prefix and
* return a pointer to it. If no such node exists, create it.
*/
void *
fib_get(struct fib *f, ip_addr *a, int len)
fib_get(struct fib *f, void *a, int len)
{
unsigned int h = ipa_hash(*a);
struct fib_node **ee = f->hash_table + (h >> f->hash_shift);
unsigned int h = fib_hash(f, a);
struct fib_node **ee = f->hash_table + h;
struct fib_node *g, *e = *ee;
u32 uid = h << 16;
u32 uid = h << (16 + f->hash_shift);
while (e && (e->pxlen != len || !ipa_equal(*a, e->prefix)))
while (e && (e->pxlen != len || memcmp(a, FPREFIX(e), f->addr_size)))
e = e->next;
if (e)
return e;
#ifdef DEBUGGING
if (len < 0 || len > BITS_PER_IP_ADDRESS || !ip_is_prefix(*a,len))
if ((f->addr_type == RT_IP) && (len < 0 || len > BITS_PER_IP_ADDRESS || !ip_is_prefix(*((ip_addr *)a),len)))
bug("fib_get() called for invalid address");
#endif
@ -228,13 +264,15 @@ fib_get(struct fib *f, ip_addr *a, int len)
uid++;
}
if ((uid >> 16) != h)
if ((uid >> (16 + f->hash_shift)) != h)
log(L_ERR "FIB hash table chains are too long");
// log (L_WARN "FIB_GET %I %x %x", *a, h, uid);
e = sl_alloc(f->fib_slab);
e->prefix = *a;
e->addr_type = f->addr_type;
e->addr_off = f->addr_off;
memcpy(FPREFIX(e), a, f->addr_size);
e->pxlen = len;
e->next = *ee;
e->uid = uid;
@ -250,22 +288,25 @@ fib_get(struct fib *f, ip_addr *a, int len)
/**
* fib_route - CIDR routing lookup
* @f: FIB to search in
* @a: pointer to IP address of the prefix
* @len: prefix length
* @a: pointer to IP (or other family) address of the prefix
* @len: prefix length (if address family requires)
*
* Search for a FIB node with longest prefix matching the given
* network, that is a node which a CIDR router would use for routing
* that network.
* that network. Function should be called for IPv4/IPv6 routes only
*/
void *
fib_route(struct fib *f, ip_addr a, int len)
fib_route(struct fib *f, ip_addr *a, int len)
{
ip_addr a0;
void *t;
if (f->addr_type != RT_IP)
return NULL;
while (len >= 0)
{
a0 = ipa_and(a, ipa_mkmask(len));
a0 = ipa_and(*a, ipa_mkmask(len));
t = fib_find(f, &a0, len);
if (t)
return t;
@ -321,7 +362,7 @@ void
fib_delete(struct fib *f, void *E)
{
struct fib_node *e = E;
unsigned int h = fib_hash(f, &e->prefix);
unsigned int h = fib_hash(f, FPREFIX(e));
struct fib_node **ee = f->hash_table + h;
struct fib_iterator *it;
@ -413,7 +454,7 @@ fit_get(struct fib *f, struct fib_iterator *i)
if (k = i->next)
k->prev = j;
j->next = k;
i->hash = fib_hash(f, &n->prefix);
i->hash = fib_hash(f, FPREFIX(n));
return n;
}
@ -452,7 +493,7 @@ fib_check(struct fib *f)
for(n=f->hash_table[i]; n; n=n->next)
{
struct fib_iterator *j, *j0;
unsigned int h0 = ipa_hash(n->prefix);
unsigned int h0 = fib_hash(f, FPREFIX(n));
if (h0 < lo)
bug("fib_check: discord in hash chains");
lo = h0;
@ -491,14 +532,15 @@ void dump(char *m)
{
unsigned int i;
debug("%s ... order=%d, size=%d, entries=%d\n", m, f.hash_order, f.hash_size, f.hash_size);
debug("%s ... type=%d order=%d, size=%d, entries=%d\n", m, f.addr_type, f.hash_order, f.hash_size, f.hash_size);
for(i=0; i<f.hash_size; i++)
{
struct fib_node *n;
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 %04x %p %s", i, fib_hash(&f, FPREFIX(n)) << f->hash_shift, n, fn_print(&f, n));
for(j=n->readers; j; j=j->next)
debug(" %p[%p]", j, j->node);
debug("\n");

View File

@ -65,6 +65,9 @@ net_route(rtable *tab, ip_addr a, int len)
ip_addr a0;
net *n;
if (tab->fib.addr_type != RT_IP)
return NULL;
while (len >= 0)
{
a0 = ipa_and(a, ipa_mkmask(len));
@ -165,7 +168,7 @@ rte_trace(struct proto *p, rte *e, int dir, char *msg)
byte via[STD_ADDRESS_P_LENGTH+32];
rt_format_via(e, via);
log(L_TRACE "%s %c %s %I/%d %s", p->name, dir, msg, e->net->n.prefix, e->net->n.pxlen, via);
log(L_TRACE "%s %c %s %F %s", p->name, dir, msg, &e->net->n, via);
}
static inline void
@ -416,18 +419,22 @@ rte_validate(rte *e)
int c;
net *n = e->net;
if ((n->n.pxlen > BITS_PER_IP_ADDRESS) || !ip_is_prefix(n->n.prefix,n->n.pxlen))
// XXXX: Do not bother checking non-IP routes at the moment
if (n->n.addr_type != RT_IP)
return 1;
if ((n->n.pxlen > BITS_PER_IP_ADDRESS) || !ip_is_prefix(*FPREFIX_IP(&n->n),n->n.pxlen))
{
log(L_WARN "Ignoring bogus prefix %I/%d received via %s",
n->n.prefix, n->n.pxlen, e->sender->proto->name);
log(L_WARN "Ignoring bogus prefix %F received via %s",
&n->n, e->sender->proto->name);
return 0;
}
c = ipa_classify_net(n->n.prefix);
c = ipa_classify_net(*FPREFIX_IP(&n->n));
if ((c < 0) || !(c & IADDR_HOST) || ((c & IADDR_SCOPE_MASK) <= SCOPE_LINK))
{
log(L_WARN "Ignoring bogus route %I/%d received via %s",
n->n.prefix, n->n.pxlen, e->sender->proto->name);
log(L_WARN "Ignoring bogus route %F received via %s",
&n->n, e->sender->proto->name);
return 0;
}
@ -494,8 +501,8 @@ rte_recalculate(struct announce_hook *ah, net *net, rte *new, ea_list *tmpa, str
{
if (new)
{
log(L_ERR "Pipe collision detected when sending %I/%d to table %s",
net->n.prefix, net->n.pxlen, table->name);
log(L_ERR "Pipe collision detected when sending %F to table %s",
&net->n, table->name);
rte_free_quick(new);
}
return;
@ -820,7 +827,7 @@ rt_dump(rtable *t)
net *n;
struct announce_hook *a;
debug("Dump of routing table <%s>\n", t->name);
debug("Dump of routing table <%s>:%d\n", t->name, t->fib.addr_type);
#ifdef DEBUGGING
fib_check(&t->fib);
#endif
@ -927,11 +934,66 @@ rt_event(void *ptr)
rt_prune_nets(tab);
}
/**
* rt_addrsize - returns (host format) size of address of given type
* @addr_type: address type
*
* Returns sizeof() appropriate structure or sizeof(ip_addr) if
* address type is unknown
*
*/
int
rt_addrsize(int addr_type)
{
switch (addr_type)
{
#ifdef MPLS_VPN
case RT_VPNV4:
return sizeof(vpn4_addr);
case RT_VPNV6:
return sizeof(vpn6_addr);
#endif
case RT_IPV4:
return sizeof(ip4_addr);
case RT_IPV6:
return sizeof(ip6_addr);
}
return sizeof(ip_addr);
}
/**
* rt_setup - initialize routing table
*
* This function is called to set up rtable (hooks, lists, fib, ..)
*/
void
rt_setup(pool *p, rtable *t, char *name, struct rtable_config *cf)
{
fib_hash_func f;
bzero(t, sizeof(*t));
fib_init(&t->fib, p, sizeof(net), 0, rte_init);
t->addr_type = cf ? cf->addr_type : RT_IP;
/* Select hashing function depending on table type */
switch (t->addr_type)
{
case RT_IP:
f = ip_hash;
break;
#ifdef XXXX
case RT_VPN:
f = vpn_hash;
break;
#endif
default:
f = ip_hash;
break;
}
fib2_init(&t->fib, p, sizeof(net), t->addr_type, rt_addrsize(t->addr_type), 0, rte_init, f);
t->name = name;
t->config = cf;
init_list(&t->hooks);
@ -1058,7 +1120,7 @@ rt_preconfig(struct config *c)
struct symbol *s = cf_find_symbol("master");
init_list(&c->tables);
c->master_rtc = rt_new_table(s);
c->master_rtc = rt_new_table(s, RT_IP);
}
@ -1212,12 +1274,13 @@ rt_next_hop_update(rtable *tab)
struct rtable_config *
rt_new_table(struct symbol *s)
rt_new_table(struct symbol *s, int addr_type)
{
struct rtable_config *c = cfg_allocz(sizeof(struct rtable_config));
cf_define_symbol(s, SYM_TABLE, c);
c->name = s->name;
c->addr_type = addr_type;
add_tail(&new_config->tables, &c->n);
c->gc_max_ops = 1000;
c->gc_min_time = 5;
@ -1575,7 +1638,7 @@ rt_notify_hostcache(rtable *tab, net *net)
if (tab->hcu_scheduled)
return;
if (trie_match_prefix(hc->trie, net->n.prefix, net->n.pxlen))
if (trie_match_prefix(hc->trie, *FPREFIX_IP(&net->n), net->n.pxlen))
rt_schedule_hcu(tab);
}
@ -1626,6 +1689,8 @@ rt_update_hostentry(rtable *tab, struct hostentry *he)
rta *old_src = he->src;
int pxlen = 0;
/* XXXX: check for non-IP address families ? */
/* Reset the hostentry */
he->src = NULL;
he->gw = IPA_NONE;
@ -1641,8 +1706,8 @@ rt_update_hostentry(rtable *tab, struct hostentry *he)
if (a->hostentry)
{
/* Recursive route should not depend on another recursive route */
log(L_WARN "Next hop address %I resolvable through recursive route for %I/%d",
he->addr, n->n.prefix, pxlen);
log(L_WARN "Next hop address %I resolvable through recursive route for %F",
he->addr, &n->n);
goto done;
}
@ -1725,9 +1790,23 @@ rt_find_hostentry(rtable *tab, ip_addr a, ip_addr ll, rtable *dep)
return he;
}
/**
* rta_set_recursive_next_hop - notify table about recursive nexthop
* @dep: table with non-directly reachable route
* @a: pointer to route attributes
* @tab: table where nexthop should be resolved
* @gw: nexthop to resolve
* @ll: link-local nexthop address (IPv6 case)
*
* Search for a FIB node corresponding to the given prefix and
* return a pointer to it. If no such node exists, create it.
*/
void
rta_set_recursive_next_hop(rtable *dep, rta *a, rtable *tab, ip_addr *gw, ip_addr *ll)
{
if (tab->addr_type != RT_IP)
return;
rta_apply_hostentry(a, rt_find_hostentry(tab, *gw, *ll, dep));
}
@ -1753,7 +1832,7 @@ rt_format_via(rte *e, byte *via)
}
static void
rt_show_rte(struct cli *c, byte *ia, rte *e, struct rt_show_data *d, ea_list *tmpa)
rt_show_rte(struct cli *c, byte *prefix, rte *e, struct rt_show_data *d, ea_list *tmpa)
{
byte via[STD_ADDRESS_P_LENGTH+32], from[STD_ADDRESS_P_LENGTH+8];
byte tm[TM_DATETIME_BUFFER_SIZE], info[256];
@ -1781,7 +1860,7 @@ rt_show_rte(struct cli *c, byte *ia, rte *e, struct rt_show_data *d, ea_list *tm
a->proto->proto->get_route_info(e, info, tmpa);
else
bsprintf(info, " (%d)", e->pref);
cli_printf(c, -1007, "%-18s %s [%s %s%s]%s%s", ia, via, a->proto->name,
cli_printf(c, -1007, "%-18s %s [%s %s%s]%s%s", prefix, via, a->proto->name,
tm, from, primary ? (sync_error ? " !" : " *") : "", info);
for (nh = a->nexthops; nh; nh = nh->next)
cli_printf(c, -1007, "\tvia %I on %s weight %d", nh->gw, nh->iface->name, nh->weight + 1);
@ -1793,11 +1872,11 @@ static void
rt_show_net(struct cli *c, net *n, struct rt_show_data *d)
{
rte *e, *ee;
byte ia[STD_ADDRESS_P_LENGTH+8];
byte prefix[MAX_ADDRESS_P_LENGTH];
struct announce_hook *a;
int ok;
bsprintf(ia, "%I/%d", n->n.prefix, n->n.pxlen);
fn_print(prefix, sizeof(prefix), &n->n);
if (n->routes)
d->net_counter++;
for(e=n->routes; e; e=e->next)
@ -1833,8 +1912,8 @@ rt_show_net(struct cli *c, net *n, struct rt_show_data *d)
{
d->show_counter++;
if (d->stats < 2)
rt_show_rte(c, ia, e, d, tmpa);
ia[0] = 0;
rt_show_rte(c, prefix, e, d, tmpa);
prefix[0] = '\0';
}
if (e != ee)
{
@ -1927,6 +2006,7 @@ rt_show(struct rt_show_data *d)
}
}
/*
* Documentation for functions declared inline in route.h
*/

View File

@ -841,7 +841,7 @@ bgp_get_bucket(struct bgp_proto *p, net *n, ea_list *attrs, int originate)
for(i=0; i<ARRAY_SIZE(bgp_mandatory_attrs); i++)
if (!(seen & (1 << bgp_mandatory_attrs[i])))
{
log(L_ERR "%s: Mandatory attribute %s missing in route %I/%d", p->p.name, bgp_attr_table[bgp_mandatory_attrs[i]].name, n->n.prefix, n->n.pxlen);
log(L_ERR "%s: Mandatory attribute %s missing in route %F", p->p.name, bgp_attr_table[bgp_mandatory_attrs[i]].name, &n->n);
return NULL;
}
@ -849,7 +849,7 @@ bgp_get_bucket(struct bgp_proto *p, net *n, ea_list *attrs, int originate)
a = ea_find(new, EA_CODE(EAP_BGP, BA_NEXT_HOP));
if (!a || ipa_equal(p->cf->remote_ip, *(ip_addr *)a->u.ptr->data))
{
log(L_ERR "%s: Invalid NEXT_HOP attribute in route %I/%d", p->p.name, n->n.prefix, n->n.pxlen);
log(L_ERR "%s: Invalid NEXT_HOP attribute in route %F", p->p.name, &n->n);
return NULL;
}
@ -893,7 +893,7 @@ bgp_rt_notify(struct proto *P, rtable *tbl UNUSED, net *n, rte *new, rte *old UN
init_list(&buck->prefixes);
}
}
px = fib_get(&p->prefix_fib, &n->n.prefix, n->n.pxlen);
px = fib_get(&p->prefix_fib, FPREFIX(&n->n), n->n.pxlen);
if (px->bucket_node.next)
{
DBG("\tRemoving old entry.\n");

View File

@ -222,10 +222,10 @@ bgp_encode_prefixes(struct bgp_proto *p, byte *w, struct bgp_bucket *buck, unsig
while (!EMPTY_LIST(buck->prefixes) && remains >= (1+sizeof(ip_addr)))
{
struct bgp_prefix *px = SKIP_BACK(struct bgp_prefix, bucket_node, HEAD(buck->prefixes));
DBG("\tDequeued route %I/%d\n", px->n.prefix, px->n.pxlen);
DBG("\tDequeued route %F\n", &px->n);
*w++ = px->n.pxlen;
bytes = (px->n.pxlen + 7) / 8;
a = px->n.prefix;
a = *FPREFIX_IP(&px->n);
ipa_hton(a);
memcpy(w, &a, bytes);
w += bytes;
@ -242,7 +242,7 @@ bgp_flush_prefixes(struct bgp_proto *p, struct bgp_bucket *buck)
while (!EMPTY_LIST(buck->prefixes))
{
struct bgp_prefix *px = SKIP_BACK(struct bgp_prefix, bucket_node, HEAD(buck->prefixes));
log(L_ERR "%s: - route %I/%d skipped", p->p.name, px->n.prefix, px->n.pxlen);
log(L_ERR "%s: - route %F skipped", p->p.name, &px->n);
rem_node(&px->bucket_node);
fib_delete(&p->prefix_fib, px);
}

View File

@ -572,10 +572,10 @@ ospf_rt_notify(struct proto *p, rtable *tbl UNUSED, net * n, rte * new, rte * ol
if (!new)
{
if (fn->x1 != EXT_EXPORT)
if (! (fn->flags & OSPF_RT_EXPORT))
return;
flush_ext_lsa(oa, fn);
flush_ext_lsa(oa, fn, 1);
/* Old external route might blocked some NSSA translation */
if (po->areano > 1)

View File

@ -33,7 +33,7 @@ ospf_rt_initort(struct fib_node *fn)
ort *ri = (ort *) fn;
reset_ri(ri);
ri->old_rta = NULL;
ri->fn.x0 = ri->fn.x1 = 0;
ri->fn.flags = 0;
}
static inline int
@ -921,7 +921,7 @@ decide_sum_lsa(struct ospf_area *oa, ort *nf, int dest)
return 1;
struct area_net *anet = (struct area_net *)
fib_route(&nf->n.oa->net_fib, nf->fn.prefix, nf->fn.pxlen);
fib_route(&nf->n.oa->net_fib, &nf->fn.prefix, nf->fn.pxlen);
/* Condensed area network found */
if (anet)
@ -938,7 +938,7 @@ check_sum_net_lsa(struct proto_ospf *po, ort *nf)
struct ospf_area *anet_oa = NULL;
/* RT entry marked as area network */
if (nf->fn.x0)
if (nf->fn.flags & OSPF_RT_PERSISTENT)
{
/* It is a default route for stub areas, handled entirely in ospf_rt_abr() */
if (nf->fn.pxlen == 0)
@ -989,7 +989,7 @@ decide_nssa_lsa(ort *nf, u32 *rt_metric, ip_addr *rt_fwaddr, u32 *rt_tag)
return 0;
/* Condensed area network found */
if (fib_route(&oa->enet_fib, nf->fn.prefix, nf->fn.pxlen))
if (fib_route(&oa->enet_fib, &nf->fn.prefix, nf->fn.pxlen))
return 0;
if (!en || (en->lsa.type != LSA_T_NSSA))
@ -1042,11 +1042,11 @@ check_nssa_lsa(struct proto_ospf *po, ort *nf)
ip_addr rt_fwaddr;
/* Do not translate LSA if there is already the external LSA from route export */
if (fn->x1 == EXT_EXPORT)
if (fn->flags & OSPF_RT_EXPORT)
return;
/* RT entry marked as area network */
if (fn->x0)
if (fn->flags & OSPF_RT_PERSISTENT)
{
/* Find that area network */
WALK_LIST(oa, po->area_list)
@ -1065,8 +1065,8 @@ check_nssa_lsa(struct proto_ospf *po, ort *nf)
else if (decide_nssa_lsa(nf, &rt_metric, &rt_fwaddr, &rt_tag))
originate_ext_lsa(po->backbone, fn, EXT_NSSA, rt_metric, rt_fwaddr, rt_tag, 0);
else if (fn->x1 == EXT_NSSA)
flush_ext_lsa(po->backbone, fn);
else if (fn->flags & OSPF_RT_NSSA)
flush_ext_lsa(po->backbone, fn, 1);
}
/* RFC 2328 16.7. p2 - find new/lost vlink endpoints */
@ -1140,7 +1140,7 @@ ospf_rt_abr1(struct proto_ospf *po)
/* Compute condensed area networks */
if (nf->n.type == RTS_OSPF)
{
anet = (struct area_net *) fib_route(&nf->n.oa->net_fib, nf->fn.prefix, nf->fn.pxlen);
anet = (struct area_net *) fib_route(&nf->n.oa->net_fib, &nf->fn.prefix, nf->fn.pxlen);
if (anet)
{
if (!anet->active)
@ -1149,7 +1149,7 @@ ospf_rt_abr1(struct proto_ospf *po)
/* Get a RT entry and mark it to know that it is an area network */
ort *nfi = (ort *) fib_get(&po->rtf, &anet->fn.prefix, anet->fn.pxlen);
nfi->fn.x0 = 1; /* mark and keep persistent, to have stable UID */
nfi->fn.flags |= OSPF_RT_PERSISTENT; /* mark persistent, to have stable UID */
/* 16.2. (3) */
if (nfi->n.type == RTS_OSPF_IA)
@ -1165,7 +1165,7 @@ ospf_rt_abr1(struct proto_ospf *po)
ip_addr addr = IPA_NONE;
default_nf = (ort *) fib_get(&po->rtf, &addr, 0);
default_nf->fn.x0 = 1; /* keep persistent */
default_nf->fn.flags |= OSPF_RT_PERSISTENT; /* keep persistent */
struct ospf_area *oa;
WALK_LIST(oa, po->area_list)
@ -1189,7 +1189,7 @@ ospf_rt_abr1(struct proto_ospf *po)
if (oa_is_nssa(oa) && oa->ac->default_nssa)
originate_ext_lsa(oa, &default_nf->fn, 0, oa->ac->default_cost, IPA_NONE, 0, 0);
else
flush_ext_lsa(oa, &default_nf->fn);
flush_ext_lsa(oa, &default_nf->fn, 0);
/* RFC 2328 16.4. (3) - precompute preferred ASBR entries */
@ -1301,7 +1301,7 @@ ospf_rt_abr2(struct proto_ospf *po)
if (rt_is_nssa(nf) && (nf->n.options & ORTA_PROP))
{
struct area_net *anet = (struct area_net *)
fib_route(&nf->n.oa->enet_fib, nf->fn.prefix, nf->fn.pxlen);
fib_route(&nf->n.oa->enet_fib, &nf->fn.prefix, nf->fn.pxlen);
if (anet)
{
@ -1311,7 +1311,7 @@ ospf_rt_abr2(struct proto_ospf *po)
/* Get a RT entry and mark it to know that it is an area network */
nf2 = (ort *) fib_get(&po->rtf, &anet->fn.prefix, anet->fn.pxlen);
nf2->fn.x0 = 1;
nf2->fn.flags |= OSPF_RT_PERSISTENT; /* keep persistent */
}
u32 metric = (nf->n.type == RTS_OSPF_EXT1) ?
@ -1545,7 +1545,7 @@ ospf_rt_reset(struct proto_ospf *po)
FIB_WALK(&po->rtf, nftmp)
{
ri = (ort *) nftmp;
ri->fn.x0 = 0;
ri->fn.flags &= ~OSPF_RT_PERSISTENT;
reset_ri(ri);
}
FIB_WALK_END;
@ -2041,8 +2041,8 @@ again1:
rte_update(p->table, ne, p, p, NULL);
}
/* Remove unused rt entry. Entries with fn.x0 == 1 are persistent. */
if (!nf->n.type && !nf->fn.x0 && !nf->fn.x1)
/* Remove unused rt entry. Entries with any flags are persistent. */
if (!nf->n.type && !nf->fn.flags)
{
FIB_ITERATE_PUT(&fit, nftmp);
fib_delete(fib, nftmp);

View File

@ -50,16 +50,25 @@ typedef struct orta
}
orta;
/* Values for fn.flags in struct ort */
#define OSPF_RT_PERSISTENT 0x01
#define OSPF_RT_EXPORT 0x02
#define OSPF_RT_NSSA 0x04
#define OSPF_RT_SRC (0x02 | 0x04)
typedef struct ort
{
/*
* We use fn.x0 to mark persistent rt entries, that are needed for summary
* LSAs that don't have 'proper' rt entry (area networks + default to stubs)
* to keep uid stable (used for LSA ID in OSPFv3 - see fibnode_to_lsaid()).
* We use OSPF_RT_PERSISTENT to mark persistent rt entries, that are
* needed for summary LSAs that don't have 'proper' rt entry (area
* networks + default to stubs) to keep uid stable (used for LSA ID
* in OSPFv3 - see fibnode_to_lsaid()).
*
* We use fn.x1 to note whether the external route was originated
* from the route export (in ospf_rt_notify()) or from the NSSA
* route translation (in check_nssa_lsa()).
* We use ORT_RT_EXPORT and ORT_RT_NSSA to note whether the
* external/NSSA route was originated from the route export (in
* ospf_rt_notify()) or from the NSSA route translation (in
* check_nssa_lsa()).
*
* old_* values are here to represent the last route update. old_rta
* is cached (we keep reference), mainly for multipath nexthops.

View File

@ -1115,7 +1115,10 @@ originate_ext_lsa(struct ospf_area *oa, struct fib_node *fn, int src,
lsasum_calculate(&lsa, body);
if (src)
fn->x1 = src;
{
fn->flags &= ~OSPF_RT_SRC;
fn->flags |= src;
}
lsa_install_new(po, &lsa, dom, body);
ospf_lsupd_flood(po, NULL, NULL, &lsa, dom, 1);
@ -1131,7 +1134,7 @@ originate_ext_lsa(struct ospf_area *oa, struct fib_node *fn, int src,
}
void
flush_ext_lsa(struct ospf_area *oa, struct fib_node *fn)
flush_ext_lsa(struct ospf_area *oa, struct fib_node *fn, int src)
{
struct proto_ospf *po = oa->po;
struct proto *p = &po->proto;
@ -1154,7 +1157,9 @@ flush_ext_lsa(struct ospf_area *oa, struct fib_node *fn)
return;
}
fn->x1 = 0;
/* Clean up source bits */
if (src)
fn->flags &= ~OSPF_RT_SRC;
ospf_lsupd_flush_nlsa(po, en);
}
}

View File

@ -72,7 +72,7 @@ void originate_sum_net_lsa(struct ospf_area *oa, struct fib_node *fn, int metric
void originate_sum_rt_lsa(struct ospf_area *oa, struct fib_node *fn, int metric, u32 options UNUSED);
void flush_sum_lsa(struct ospf_area *oa, struct fib_node *fn, int type);
void originate_ext_lsa(struct ospf_area *oa, struct fib_node *fn, int src, u32 metric, ip_addr fwaddr, u32 tag, int pbit);
void flush_ext_lsa(struct ospf_area *oa, struct fib_node *fn);
void flush_ext_lsa(struct ospf_area *oa, struct fib_node *fn, int src);
#ifdef OSPFv2

View File

@ -93,7 +93,7 @@ krt_sock_send(int cmd, rte *e)
sockaddr gate, mask, dst;
ip_addr gw;
DBG("krt-sock: send %I/%d via %I\n", net->n.prefix, net->n.pxlen, a->gw);
DBG("krt-sock: send %F via %I\n", &net->n, a->gw);
bzero(&msg,sizeof (struct rt_msghdr));
msg.rtm.rtm_version = RTM_VERSION;
@ -102,15 +102,6 @@ krt_sock_send(int cmd, rte *e)
msg.rtm.rtm_addrs = RTA_DST;
msg.rtm.rtm_flags = RTF_UP | RTF_PROTO1;
if (net->n.pxlen == MAX_PREFIX_LENGTH)
{
msg.rtm.rtm_flags |= RTF_HOST;
}
else
{
msg.rtm.rtm_addrs |= RTA_NETMASK;
}
#ifdef RTF_REJECT
if(a->dest == RTD_UNREACHABLE)
msg.rtm.rtm_flags |= RTF_REJECT;
@ -149,6 +140,20 @@ krt_sock_send(int cmd, rte *e)
fill_in_sockaddr(&dst, net->n.prefix, NULL, 0);
fill_in_sockaddr(&mask, ipa_mkmask(net->n.pxlen), NULL, 0);
fill_in_sockaddr(&gate, gw, NULL, 0);
/* XXXX from patch
if (net->n.addr_type == RT_IP)
{
fill_in_sockaddr(&dst, *FPREFIX_IP(&net->n), 0);
fill_in_sockaddr(&mask, ipa_mkmask(net->n.pxlen), 0);
if (net->n.pxlen == MAX_PREFIX_LENGTH)
msg.rtm.rtm_flags |= RTF_HOST;
else
msg.rtm.rtm_addrs |= RTA_NETMASK;
}
*/
switch (a->dest)
{
@ -193,7 +198,7 @@ krt_sock_send(int cmd, rte *e)
msg.rtm.rtm_msglen = l;
if ((l = write(rt_sock, (char *)&msg, l)) < 0) {
log(L_ERR "KRT: Error sending route %I/%d to kernel: %m", net->n.prefix, net->n.pxlen);
log(L_ERR "KRT: Error sending route %F to kernel: %m", &net->n);
return -1;
}
@ -340,8 +345,8 @@ krt_read_rt(struct ks_msg *msg, struct krt_proto *p, int scan)
a.iface = if_find_by_index(msg->rtm.rtm_index);
if (!a.iface)
{
log(L_ERR "KRT: Received route %I/%d with unknown ifindex %u",
net->n.prefix, net->n.pxlen, msg->rtm.rtm_index);
log(L_ERR "KRT: Received route %F with unknown ifindex %u",
&net->n, msg->rtm.rtm_index);
return;
}
@ -365,8 +370,8 @@ krt_read_rt(struct ks_msg *msg, struct krt_proto *p, int scan)
if (ipa_classify(a.gw) == (IADDR_HOST | SCOPE_HOST))
return;
log(L_ERR "KRT: Received route %I/%d with strange next-hop %I",
net->n.prefix, net->n.pxlen, a.gw);
log(L_ERR "KRT: Received route %F with strange next-hop %I",
&net->n, a.gw);
return;
}
}

View File

@ -640,7 +640,7 @@ nl_send_route(struct krt_proto *p, rte *e, struct ea_list *eattrs, int new)
char buf[128 + nh_bufsize(a->nexthops)];
} r;
DBG("nl_send_route(%I/%d,new=%d)\n", net->n.prefix, net->n.pxlen, new);
DBG("nl_send_route(%F,new=%d)\n", &net->n, new);
bzero(&r.h, sizeof(r.h));
bzero(&r.r, sizeof(r.r));
@ -654,7 +654,7 @@ nl_send_route(struct krt_proto *p, rte *e, struct ea_list *eattrs, int new)
r.r.rtm_table = KRT_CF->sys.table_id;
r.r.rtm_protocol = RTPROT_BIRD;
r.r.rtm_scope = RT_SCOPE_UNIVERSE;
nl_add_attr_ipa(&r.h, sizeof(r), RTA_DST, net->n.prefix);
nl_add_attr_ipa(&r.h, sizeof(r), RTA_DST, *FPREFIX_IP(&net->n));
u32 metric = 0;
if (new && e->attrs->source == RTS_INHERIT)
@ -837,8 +837,7 @@ nl_parse_route(struct nlmsghdr *h, int scan)
ra.nexthops = nl_parse_multipath(p, a[RTA_MULTIPATH]);
if (!ra.nexthops)
{
log(L_ERR "KRT: Received strange multipath route %I/%d",
net->n.prefix, net->n.pxlen);
log(L_ERR "KRT: Received strange multipath route %F", &net->n);
return;
}
@ -848,8 +847,8 @@ nl_parse_route(struct nlmsghdr *h, int scan)
ra.iface = if_find_by_index(oif);
if (!ra.iface)
{
log(L_ERR "KRT: Received route %I/%d with unknown ifindex %u",
net->n.prefix, net->n.pxlen, oif);
log(L_ERR "KRT: Received route %F with unknown ifindex %u",
&net->n, oif);
return;
}
@ -868,8 +867,8 @@ nl_parse_route(struct nlmsghdr *h, int scan)
(i->rtm_flags & RTNH_F_ONLINK) ? NEF_ONLINK : 0);
if (!ng || (ng->scope == SCOPE_HOST))
{
log(L_ERR "KRT: Received route %I/%d with strange next-hop %I",
net->n.prefix, net->n.pxlen, ra.gw);
log(L_ERR "KRT: Received route %F with strange next-hop %I",
&net->n, ra.gw);
return;
}
}

View File

@ -285,14 +285,14 @@ static inline void
krt_trace_in(struct krt_proto *p, rte *e, char *msg)
{
if (p->p.debug & D_PACKETS)
log(L_TRACE "%s: %I/%d: %s", p->p.name, e->net->n.prefix, e->net->n.pxlen, msg);
log(L_TRACE "%s: %F: %s", p->p.name, &e->net->n, msg);
}
static inline void
krt_trace_in_rl(struct rate_limit *rl, struct krt_proto *p, rte *e, char *msg)
{
if (p->p.debug & D_PACKETS)
log_rl(rl, L_TRACE "%s: %I/%d: %s", p->p.name, e->net->n.prefix, e->net->n.pxlen, msg);
log_rl(rl, L_TRACE "%s: %F: %s", p->p.name, &e->net->n, msg);
}
/*
@ -335,7 +335,7 @@ krt_learn_announce_update(struct krt_proto *p, rte *e)
net *n = e->net;
rta *aa = rta_clone(e->attrs);
rte *ee = rte_get_temp(aa);
net *nn = net_get(p->p.table, n->n.prefix, n->n.pxlen);
net *nn = fib_get(&p->p.table->fib, FPREFIX(&n->n), n->n.pxlen);
ee->net = nn;
ee->pflags = 0;
ee->pref = p->p.preference;
@ -346,7 +346,7 @@ krt_learn_announce_update(struct krt_proto *p, rte *e)
static void
krt_learn_announce_delete(struct krt_proto *p, net *n)
{
n = net_find(p->p.table, n->n.prefix, n->n.pxlen);
n = fib_find(&p->p.table->fib, FPREFIX(&n->n), n->n.pxlen);
if (n)
rte_update(p->p.table, n, &p->p, &p->p, NULL);
}
@ -356,7 +356,7 @@ static void
krt_learn_scan(struct krt_proto *p, rte *e)
{
net *n0 = e->net;
net *n = net_get(&p->krt_table, n0->n.prefix, n0->n.pxlen);
net *n = fib_get(&p->krt_table.fib, FPREFIX(&n0->n), n0->n.pxlen);
rte *m, **mm;
e->attrs = rta_lookup(e->attrs);
@ -427,7 +427,7 @@ again:
}
if (!n->routes)
{
DBG("%I/%d: deleting\n", n->n.prefix, n->n.pxlen);
DBG("%F: deleting\n", &n->n);
if (old_best)
{
krt_learn_announce_delete(p, n);
@ -442,12 +442,12 @@ again:
n->routes = best;
if (best != old_best || !(n->n.flags & KRF_INSTALLED))
{
DBG("%I/%d: announcing (metric=%d)\n", n->n.prefix, n->n.pxlen, best->u.krt.metric);
DBG("%F: announcing (metric=%d)\n", &n->n, best->u.krt.metric);
krt_learn_announce_update(p, best);
n->n.flags |= KRF_INSTALLED;
}
else
DBG("%I/%d: uptodate (metric=%d)\n", n->n.prefix, n->n.pxlen, best->u.krt.metric);
DBG("%F: uptodate (metric=%d)\n", &n->n, best->u.krt.metric);
}
FIB_ITERATE_END(f);
}
@ -456,8 +456,8 @@ static void
krt_learn_async(struct krt_proto *p, rte *e, int new)
{
net *n0 = e->net;
net *n = net_get(&p->krt_table, n0->n.prefix, n0->n.pxlen);
rte *g, **gg, *best, **bestp, *old_best;
net *n = fib_get(&p->krt_table.fib, FPREFIX(&n0->n), n0->n.pxlen);
e->attrs = rta_lookup(e->attrs);