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 */ case T_STRING: /* Warning: this is a special case for proto attribute */
res.val.s = rta->proto->name; res.val.s = rta->proto->name;
break; 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.ip = (*f_rte)->net->n.prefix;
res.val.px.len = (*f_rte)->net->n.pxlen; res.val.px.len = (*f_rte)->net->n.pxlen;

View File

@ -349,7 +349,23 @@ ip_scope_text(unsigned scope)
return scope_table[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 #if 0

View File

@ -390,6 +390,8 @@ static inline int ipa_classify_net(ip_addr a)
#define STD_ADDRESS_P_LENGTH 39 #define STD_ADDRESS_P_LENGTH 39
#define SIZE_OF_IP_HEADER 40 #define SIZE_OF_IP_HEADER 40
#define MAX_ADDRESS_P_LENGTH 40
#define ipa_class_mask(x) _MI4(ipv4_class_mask(_I(x))) #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); u32 ipv4_class_mask(u32);
byte *ipv4_skip_header(byte *, int *); 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; u32 x;
char *str, *start; char *str, *start;
const char *s; const char *s;
char ipbuf[STD_ADDRESS_P_LENGTH+1]; char ipbuf[MAX_ADDRESS_P_LENGTH];
struct iface *iface; struct iface *iface;
int flags; /* flags to number() */ int flags; /* flags to number() */
@ -298,6 +298,12 @@ int bvsnprintf(char *buf, int size, const char *fmt, va_list args)
s = iface->name; s = iface->name;
goto str; 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 */ /* Router/Network ID - essentially IPv4 address in u32 value */
case 'R': case 'R':
x = va_arg(args, u32); x = va_arg(args, u32);

View File

@ -36,6 +36,16 @@ get_u32(void *p)
return ntohl(x); 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 static inline void
put_u16(void *p, u16 x) put_u16(void *p, u16 x)
{ {
@ -50,4 +60,15 @@ put_u32(void *p, u32 x)
memcpy(p, &x, 4); 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 #endif

View File

@ -108,7 +108,7 @@ listen_opt:
CF_ADDTO(conf, newtab) CF_ADDTO(conf, newtab)
newtab: TABLE SYM { 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 */ struct fib_iterator *readers; /* List of readers of this node */
byte pxlen; byte pxlen;
byte flags; /* User-defined */ 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 */ 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 */ 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; unsigned int hash;
}; };
struct fib;
typedef void (*fib_init_func)(struct fib_node *); typedef void (*fib_init_func)(struct fib_node *);
typedef u32 (*fib_hash_func)(struct fib *, void *);
struct fib { struct fib {
pool *fib_pool; /* Pool holding all our data */ 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_size; /* Number of hash table entries (a power of two) */
unsigned int hash_order; /* Binary logarithm of hash_size */ unsigned int hash_order; /* Binary logarithm of hash_size */
unsigned int hash_shift; /* 16 - hash_log */ 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; /* Number of entries */
unsigned int entries_min, entries_max;/* Entry count limits (else start rehashing) */ unsigned int entries_min, entries_max;/* Entry count limits (else start rehashing) */
fib_init_func init; /* Constructor */ 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_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 fib2_init(struct fib *, pool *, unsigned node_size, unsigned int addr_type, unsigned int addr_size, \
void *fib_get(struct fib *, ip_addr *, int); /* Find or create new if nonexistent */ unsigned hash_order, fib_init_func init, fib_hash_func hash_f);
void *fib_route(struct fib *, ip_addr, int); /* Longest-match routing lookup */ 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_delete(struct fib *, void *); /* Remove fib entry */
void fib_free(struct fib *); /* Destroy the fib */ void fib_free(struct fib *); /* Destroy the fib */
void fib_check(struct fib *); /* Consistency check for debugging */ 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 */ void fit_init(struct fib_iterator *, struct fib *); /* Internal functions, don't call */
struct fib_node *fit_get(struct fib *, struct fib_iterator *); struct fib_node *fit_get(struct fib *, struct fib_iterator *);
void fit_put(struct fib_iterator *, struct fib_node *); 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 { \ #define FIB_WALK(fib, z) do { \
struct fib_node *z, **ff = (fib)->hash_table; \ struct fib_node *z, **ff = (fib)->hash_table; \
unsigned int count = (fib)->hash_size; \ unsigned int count = (fib)->hash_size; \
@ -117,6 +135,7 @@ void fit_put(struct fib_iterator *, struct fib_node *);
struct rtable_config { struct rtable_config {
node n; node n;
char *name; char *name;
int addr_type; /* Type of address data stored in table (IPv46, VPNv46, etc..) */
struct rtable *table; struct rtable *table;
struct proto_config *krt_attached; /* Kernel syncer attached to this table */ struct proto_config *krt_attached; /* Kernel syncer attached to this table */
int gc_max_ops; /* Maximum number of operations before GC is run */ 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 */ node n; /* Node in list of all tables */
struct fib fib; struct fib fib;
char *name; /* Name of this table */ 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 */ list hooks; /* List of announcement hooks */
int pipe_busy; /* Pipe loop detection */ int pipe_busy; /* Pipe loop detection */
int use_count; /* Number of protocols using this table */ int use_count; /* Number of protocols using this table */
@ -221,9 +241,29 @@ typedef struct rte {
#define REF_COW 1 /* Copy this rte on write */ #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 */ /* Types of route announcement, also used as flags */
#define RA_OPTIMAL 1 /* Announcement of optimal route change */ #define RA_OPTIMAL 1 /* Announcement of optimal route change */
#define RA_ANY 2 /* Announcement of any route change */ #define RA_ANY 2 /* Announcement of any route change */
struct config; struct config;
@ -250,7 +290,9 @@ int rt_feed_baby(struct proto *p);
void rt_feed_baby_abort(struct proto *p); void rt_feed_baby_abort(struct proto *p);
void rt_schedule_prune_all(void); void rt_schedule_prune_all(void);
int rt_prune_loop(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 { struct rt_show_data {
ip_addr prefix; ip_addr prefix;

View File

@ -72,10 +72,10 @@ fib_ht_free(struct fib_node **h)
mb_free(h); mb_free(h);
} }
static inline unsigned u32
fib_hash(struct fib *f, ip_addr *a) 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 static void
@ -97,17 +97,53 @@ fib_dummy_init(struct fib_node *dummy UNUSED)
*/ */
void 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, 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) if (!hash_order)
hash_order = HASH_DEF_ORDER; hash_order = HASH_DEF_ORDER;
f->fib_pool = p; 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->fib_slab = sl_new(p, node_size);
f->hash_order = hash_order; f->hash_order = hash_order;
fib_ht_alloc(f); fib_ht_alloc(f);
bzero(f->hash_table, f->hash_size * sizeof(struct fib_node *)); 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 = 0;
f->entries_min = 0; f->entries_min = 0;
f->init = init ? : fib_dummy_init; f->init = init ? : fib_dummy_init;
f->hash_f = hash_f;
} }
static void static void
@ -133,7 +169,7 @@ fib_rehash(struct fib *f, int step)
while (e = x) while (e = x)
{ {
x = e->next; x = e->next;
nh = fib_hash(f, &e->prefix); nh = fib_hash(f, FPREFIX(e));
while (nh > ni) while (nh > ni)
{ {
*t = NULL; *t = NULL;
@ -163,11 +199,11 @@ fib_rehash(struct fib *f, int step)
* a pointer to it or %NULL if no such node exists. * a pointer to it or %NULL if no such node exists.
*/ */
void * 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)]; 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; e = e->next;
return e; return e;
} }
@ -197,26 +233,26 @@ fib_histogram(struct fib *f)
/** /**
* fib_get - find or create a FIB node * fib_get - find or create a FIB node
* @f: FIB to work with * @f: FIB to work with
* @a: pointer to IP address of the prefix * @a: pointer to IP (or other family) address of the prefix
* @len: prefix length * @len: prefix length (if address family requires it)
* *
* Search for a FIB node corresponding to the given prefix and * Search for a FIB node corresponding to the given prefix and
* return a pointer to it. If no such node exists, create it. * return a pointer to it. If no such node exists, create it.
*/ */
void * 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); unsigned int h = fib_hash(f, a);
struct fib_node **ee = f->hash_table + (h >> f->hash_shift); struct fib_node **ee = f->hash_table + h;
struct fib_node *g, *e = *ee; 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; e = e->next;
if (e) if (e)
return e; return e;
#ifdef DEBUGGING #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"); bug("fib_get() called for invalid address");
#endif #endif
@ -228,13 +264,15 @@ fib_get(struct fib *f, ip_addr *a, int len)
uid++; uid++;
} }
if ((uid >> 16) != h) if ((uid >> (16 + f->hash_shift)) != h)
log(L_ERR "FIB hash table chains are too long"); log(L_ERR "FIB hash table chains are too long");
// log (L_WARN "FIB_GET %I %x %x", *a, h, uid); // log (L_WARN "FIB_GET %I %x %x", *a, h, uid);
e = sl_alloc(f->fib_slab); 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->pxlen = len;
e->next = *ee; e->next = *ee;
e->uid = uid; e->uid = uid;
@ -250,22 +288,25 @@ fib_get(struct fib *f, ip_addr *a, int len)
/** /**
* fib_route - CIDR routing lookup * fib_route - CIDR routing lookup
* @f: FIB to search in * @f: FIB to search in
* @a: pointer to IP address of the prefix * @a: pointer to IP (or other family) address of the prefix
* @len: prefix length * @len: prefix length (if address family requires)
* *
* Search for a FIB node with longest prefix matching the given * Search for a FIB node with longest prefix matching the given
* network, that is a node which a CIDR router would use for routing * 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 * void *
fib_route(struct fib *f, ip_addr a, int len) fib_route(struct fib *f, ip_addr *a, int len)
{ {
ip_addr a0; ip_addr a0;
void *t; void *t;
if (f->addr_type != RT_IP)
return NULL;
while (len >= 0) while (len >= 0)
{ {
a0 = ipa_and(a, ipa_mkmask(len)); a0 = ipa_and(*a, ipa_mkmask(len));
t = fib_find(f, &a0, len); t = fib_find(f, &a0, len);
if (t) if (t)
return t; return t;
@ -321,7 +362,7 @@ void
fib_delete(struct fib *f, void *E) fib_delete(struct fib *f, void *E)
{ {
struct fib_node *e = 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_node **ee = f->hash_table + h;
struct fib_iterator *it; struct fib_iterator *it;
@ -413,7 +454,7 @@ fit_get(struct fib *f, struct fib_iterator *i)
if (k = i->next) if (k = i->next)
k->prev = j; k->prev = j;
j->next = k; j->next = k;
i->hash = fib_hash(f, &n->prefix); i->hash = fib_hash(f, FPREFIX(n));
return n; return n;
} }
@ -452,7 +493,7 @@ fib_check(struct fib *f)
for(n=f->hash_table[i]; n; n=n->next) for(n=f->hash_table[i]; n; n=n->next)
{ {
struct fib_iterator *j, *j0; struct fib_iterator *j, *j0;
unsigned int h0 = ipa_hash(n->prefix); unsigned int h0 = fib_hash(f, FPREFIX(n));
if (h0 < lo) if (h0 < lo)
bug("fib_check: discord in hash chains"); bug("fib_check: discord in hash chains");
lo = h0; lo = h0;
@ -491,14 +532,15 @@ void dump(char *m)
{ {
unsigned int i; 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++) for(i=0; i<f.hash_size; i++)
{ {
struct fib_node *n; struct fib_node *n;
struct fib_iterator *j; struct fib_iterator *j;
for(n=f.hash_table[i]; n; n=n->next) 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) for(j=n->readers; j; j=j->next)
debug(" %p[%p]", j, j->node); debug(" %p[%p]", j, j->node);
debug("\n"); debug("\n");

View File

@ -65,6 +65,9 @@ net_route(rtable *tab, ip_addr a, int len)
ip_addr a0; ip_addr a0;
net *n; net *n;
if (tab->fib.addr_type != RT_IP)
return NULL;
while (len >= 0) while (len >= 0)
{ {
a0 = ipa_and(a, ipa_mkmask(len)); 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]; byte via[STD_ADDRESS_P_LENGTH+32];
rt_format_via(e, via); 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 static inline void
@ -416,18 +419,22 @@ rte_validate(rte *e)
int c; int c;
net *n = e->net; 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", log(L_WARN "Ignoring bogus prefix %F received via %s",
n->n.prefix, n->n.pxlen, e->sender->proto->name); &n->n, e->sender->proto->name);
return 0; 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)) if ((c < 0) || !(c & IADDR_HOST) || ((c & IADDR_SCOPE_MASK) <= SCOPE_LINK))
{ {
log(L_WARN "Ignoring bogus route %I/%d received via %s", log(L_WARN "Ignoring bogus route %F received via %s",
n->n.prefix, n->n.pxlen, e->sender->proto->name); &n->n, e->sender->proto->name);
return 0; return 0;
} }
@ -494,8 +501,8 @@ rte_recalculate(struct announce_hook *ah, net *net, rte *new, ea_list *tmpa, str
{ {
if (new) if (new)
{ {
log(L_ERR "Pipe collision detected when sending %I/%d to table %s", log(L_ERR "Pipe collision detected when sending %F to table %s",
net->n.prefix, net->n.pxlen, table->name); &net->n, table->name);
rte_free_quick(new); rte_free_quick(new);
} }
return; return;
@ -820,7 +827,7 @@ rt_dump(rtable *t)
net *n; net *n;
struct announce_hook *a; 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 #ifdef DEBUGGING
fib_check(&t->fib); fib_check(&t->fib);
#endif #endif
@ -927,11 +934,66 @@ rt_event(void *ptr)
rt_prune_nets(tab); 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 void
rt_setup(pool *p, rtable *t, char *name, struct rtable_config *cf) rt_setup(pool *p, rtable *t, char *name, struct rtable_config *cf)
{ {
fib_hash_func f;
bzero(t, sizeof(*t)); 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->name = name;
t->config = cf; t->config = cf;
init_list(&t->hooks); init_list(&t->hooks);
@ -1058,7 +1120,7 @@ rt_preconfig(struct config *c)
struct symbol *s = cf_find_symbol("master"); struct symbol *s = cf_find_symbol("master");
init_list(&c->tables); 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 * 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)); struct rtable_config *c = cfg_allocz(sizeof(struct rtable_config));
cf_define_symbol(s, SYM_TABLE, c); cf_define_symbol(s, SYM_TABLE, c);
c->name = s->name; c->name = s->name;
c->addr_type = addr_type;
add_tail(&new_config->tables, &c->n); add_tail(&new_config->tables, &c->n);
c->gc_max_ops = 1000; c->gc_max_ops = 1000;
c->gc_min_time = 5; c->gc_min_time = 5;
@ -1575,7 +1638,7 @@ rt_notify_hostcache(rtable *tab, net *net)
if (tab->hcu_scheduled) if (tab->hcu_scheduled)
return; 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); rt_schedule_hcu(tab);
} }
@ -1626,6 +1689,8 @@ rt_update_hostentry(rtable *tab, struct hostentry *he)
rta *old_src = he->src; rta *old_src = he->src;
int pxlen = 0; int pxlen = 0;
/* XXXX: check for non-IP address families ? */
/* Reset the hostentry */ /* Reset the hostentry */
he->src = NULL; he->src = NULL;
he->gw = IPA_NONE; he->gw = IPA_NONE;
@ -1641,8 +1706,8 @@ rt_update_hostentry(rtable *tab, struct hostentry *he)
if (a->hostentry) if (a->hostentry)
{ {
/* Recursive route should not depend on another recursive route */ /* Recursive route should not depend on another recursive route */
log(L_WARN "Next hop address %I resolvable through recursive route for %I/%d", log(L_WARN "Next hop address %I resolvable through recursive route for %F",
he->addr, n->n.prefix, pxlen); he->addr, &n->n);
goto done; goto done;
} }
@ -1725,9 +1790,23 @@ rt_find_hostentry(rtable *tab, ip_addr a, ip_addr ll, rtable *dep)
return he; 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 void
rta_set_recursive_next_hop(rtable *dep, rta *a, rtable *tab, ip_addr *gw, ip_addr *ll) 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)); rta_apply_hostentry(a, rt_find_hostentry(tab, *gw, *ll, dep));
} }
@ -1753,7 +1832,7 @@ rt_format_via(rte *e, byte *via)
} }
static void 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 via[STD_ADDRESS_P_LENGTH+32], from[STD_ADDRESS_P_LENGTH+8];
byte tm[TM_DATETIME_BUFFER_SIZE], info[256]; 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); a->proto->proto->get_route_info(e, info, tmpa);
else else
bsprintf(info, " (%d)", e->pref); 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); tm, from, primary ? (sync_error ? " !" : " *") : "", info);
for (nh = a->nexthops; nh; nh = nh->next) 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); 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) rt_show_net(struct cli *c, net *n, struct rt_show_data *d)
{ {
rte *e, *ee; rte *e, *ee;
byte ia[STD_ADDRESS_P_LENGTH+8]; byte prefix[MAX_ADDRESS_P_LENGTH];
struct announce_hook *a; struct announce_hook *a;
int ok; int ok;
bsprintf(ia, "%I/%d", n->n.prefix, n->n.pxlen); fn_print(prefix, sizeof(prefix), &n->n);
if (n->routes) if (n->routes)
d->net_counter++; d->net_counter++;
for(e=n->routes; e; e=e->next) 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++; d->show_counter++;
if (d->stats < 2) if (d->stats < 2)
rt_show_rte(c, ia, e, d, tmpa); rt_show_rte(c, prefix, e, d, tmpa);
ia[0] = 0; prefix[0] = '\0';
} }
if (e != ee) if (e != ee)
{ {
@ -1927,6 +2006,7 @@ rt_show(struct rt_show_data *d)
} }
} }
/* /*
* Documentation for functions declared inline in route.h * 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++) for(i=0; i<ARRAY_SIZE(bgp_mandatory_attrs); i++)
if (!(seen & (1 << 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; 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)); 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)) 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; 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); 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) if (px->bucket_node.next)
{ {
DBG("\tRemoving old entry.\n"); 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))) while (!EMPTY_LIST(buck->prefixes) && remains >= (1+sizeof(ip_addr)))
{ {
struct bgp_prefix *px = SKIP_BACK(struct bgp_prefix, bucket_node, HEAD(buck->prefixes)); 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; *w++ = px->n.pxlen;
bytes = (px->n.pxlen + 7) / 8; bytes = (px->n.pxlen + 7) / 8;
a = px->n.prefix; a = *FPREFIX_IP(&px->n);
ipa_hton(a); ipa_hton(a);
memcpy(w, &a, bytes); memcpy(w, &a, bytes);
w += bytes; w += bytes;
@ -242,7 +242,7 @@ bgp_flush_prefixes(struct bgp_proto *p, struct bgp_bucket *buck)
while (!EMPTY_LIST(buck->prefixes)) while (!EMPTY_LIST(buck->prefixes))
{ {
struct bgp_prefix *px = SKIP_BACK(struct bgp_prefix, bucket_node, HEAD(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); rem_node(&px->bucket_node);
fib_delete(&p->prefix_fib, px); 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 (!new)
{ {
if (fn->x1 != EXT_EXPORT) if (! (fn->flags & OSPF_RT_EXPORT))
return; return;
flush_ext_lsa(oa, fn); flush_ext_lsa(oa, fn, 1);
/* Old external route might blocked some NSSA translation */ /* Old external route might blocked some NSSA translation */
if (po->areano > 1) if (po->areano > 1)

View File

@ -33,7 +33,7 @@ ospf_rt_initort(struct fib_node *fn)
ort *ri = (ort *) fn; ort *ri = (ort *) fn;
reset_ri(ri); reset_ri(ri);
ri->old_rta = NULL; ri->old_rta = NULL;
ri->fn.x0 = ri->fn.x1 = 0; ri->fn.flags = 0;
} }
static inline int static inline int
@ -921,7 +921,7 @@ decide_sum_lsa(struct ospf_area *oa, ort *nf, int dest)
return 1; return 1;
struct area_net *anet = (struct area_net *) 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 */ /* Condensed area network found */
if (anet) if (anet)
@ -938,7 +938,7 @@ check_sum_net_lsa(struct proto_ospf *po, ort *nf)
struct ospf_area *anet_oa = NULL; struct ospf_area *anet_oa = NULL;
/* RT entry marked as area network */ /* 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() */ /* It is a default route for stub areas, handled entirely in ospf_rt_abr() */
if (nf->fn.pxlen == 0) 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; return 0;
/* Condensed area network found */ /* 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; return 0;
if (!en || (en->lsa.type != LSA_T_NSSA)) 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; ip_addr rt_fwaddr;
/* Do not translate LSA if there is already the external LSA from route export */ /* 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; return;
/* RT entry marked as area network */ /* RT entry marked as area network */
if (fn->x0) if (fn->flags & OSPF_RT_PERSISTENT)
{ {
/* Find that area network */ /* Find that area network */
WALK_LIST(oa, po->area_list) 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)) 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); originate_ext_lsa(po->backbone, fn, EXT_NSSA, rt_metric, rt_fwaddr, rt_tag, 0);
else if (fn->x1 == EXT_NSSA) else if (fn->flags & OSPF_RT_NSSA)
flush_ext_lsa(po->backbone, fn); flush_ext_lsa(po->backbone, fn, 1);
} }
/* RFC 2328 16.7. p2 - find new/lost vlink endpoints */ /* 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 */ /* Compute condensed area networks */
if (nf->n.type == RTS_OSPF) 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)
{ {
if (!anet->active) 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 */ /* 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); 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) */ /* 16.2. (3) */
if (nfi->n.type == RTS_OSPF_IA) if (nfi->n.type == RTS_OSPF_IA)
@ -1165,7 +1165,7 @@ ospf_rt_abr1(struct proto_ospf *po)
ip_addr addr = IPA_NONE; ip_addr addr = IPA_NONE;
default_nf = (ort *) fib_get(&po->rtf, &addr, 0); 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; struct ospf_area *oa;
WALK_LIST(oa, po->area_list) 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) 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); originate_ext_lsa(oa, &default_nf->fn, 0, oa->ac->default_cost, IPA_NONE, 0, 0);
else 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 */ /* 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)) if (rt_is_nssa(nf) && (nf->n.options & ORTA_PROP))
{ {
struct area_net *anet = (struct area_net *) 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) 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 */ /* 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 = (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) ? u32 metric = (nf->n.type == RTS_OSPF_EXT1) ?
@ -1545,7 +1545,7 @@ ospf_rt_reset(struct proto_ospf *po)
FIB_WALK(&po->rtf, nftmp) FIB_WALK(&po->rtf, nftmp)
{ {
ri = (ort *) nftmp; ri = (ort *) nftmp;
ri->fn.x0 = 0; ri->fn.flags &= ~OSPF_RT_PERSISTENT;
reset_ri(ri); reset_ri(ri);
} }
FIB_WALK_END; FIB_WALK_END;
@ -2041,8 +2041,8 @@ again1:
rte_update(p->table, ne, p, p, NULL); rte_update(p->table, ne, p, p, NULL);
} }
/* Remove unused rt entry. Entries with fn.x0 == 1 are persistent. */ /* Remove unused rt entry. Entries with any flags are persistent. */
if (!nf->n.type && !nf->fn.x0 && !nf->fn.x1) if (!nf->n.type && !nf->fn.flags)
{ {
FIB_ITERATE_PUT(&fit, nftmp); FIB_ITERATE_PUT(&fit, nftmp);
fib_delete(fib, nftmp); fib_delete(fib, nftmp);

View File

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

View File

@ -1114,8 +1114,11 @@ originate_ext_lsa(struct ospf_area *oa, struct fib_node *fn, int src,
body = originate_ext_lsa_body(po, &lsa.length, fn, metric, fwaddr, tag, pbit); body = originate_ext_lsa_body(po, &lsa.length, fn, metric, fwaddr, tag, pbit);
lsasum_calculate(&lsa, body); lsasum_calculate(&lsa, body);
if (src) if (src)
fn->x1 = src; {
fn->flags &= ~OSPF_RT_SRC;
fn->flags |= src;
}
lsa_install_new(po, &lsa, dom, body); lsa_install_new(po, &lsa, dom, body);
ospf_lsupd_flood(po, NULL, NULL, &lsa, dom, 1); 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 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_ospf *po = oa->po;
struct proto *p = &po->proto; struct proto *p = &po->proto;
@ -1154,7 +1157,9 @@ flush_ext_lsa(struct ospf_area *oa, struct fib_node *fn)
return; return;
} }
fn->x1 = 0; /* Clean up source bits */
if (src)
fn->flags &= ~OSPF_RT_SRC;
ospf_lsupd_flush_nlsa(po, en); 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 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 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 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 #ifdef OSPFv2

View File

@ -93,7 +93,7 @@ krt_sock_send(int cmd, rte *e)
sockaddr gate, mask, dst; sockaddr gate, mask, dst;
ip_addr gw; 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)); bzero(&msg,sizeof (struct rt_msghdr));
msg.rtm.rtm_version = RTM_VERSION; 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_addrs = RTA_DST;
msg.rtm.rtm_flags = RTF_UP | RTF_PROTO1; 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 #ifdef RTF_REJECT
if(a->dest == RTD_UNREACHABLE) if(a->dest == RTD_UNREACHABLE)
msg.rtm.rtm_flags |= RTF_REJECT; 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(&dst, net->n.prefix, NULL, 0);
fill_in_sockaddr(&mask, ipa_mkmask(net->n.pxlen), NULL, 0); fill_in_sockaddr(&mask, ipa_mkmask(net->n.pxlen), NULL, 0);
fill_in_sockaddr(&gate, gw, 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) switch (a->dest)
{ {
@ -193,7 +198,7 @@ krt_sock_send(int cmd, rte *e)
msg.rtm.rtm_msglen = l; msg.rtm.rtm_msglen = l;
if ((l = write(rt_sock, (char *)&msg, l)) < 0) { 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; 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); a.iface = if_find_by_index(msg->rtm.rtm_index);
if (!a.iface) if (!a.iface)
{ {
log(L_ERR "KRT: Received route %I/%d with unknown ifindex %u", log(L_ERR "KRT: Received route %F with unknown ifindex %u",
net->n.prefix, net->n.pxlen, msg->rtm.rtm_index); &net->n, msg->rtm.rtm_index);
return; 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)) if (ipa_classify(a.gw) == (IADDR_HOST | SCOPE_HOST))
return; return;
log(L_ERR "KRT: Received route %I/%d with strange next-hop %I", log(L_ERR "KRT: Received route %F with strange next-hop %I",
net->n.prefix, net->n.pxlen, a.gw); &net->n, a.gw);
return; 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)]; char buf[128 + nh_bufsize(a->nexthops)];
} r; } 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.h, sizeof(r.h));
bzero(&r.r, sizeof(r.r)); 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_table = KRT_CF->sys.table_id;
r.r.rtm_protocol = RTPROT_BIRD; r.r.rtm_protocol = RTPROT_BIRD;
r.r.rtm_scope = RT_SCOPE_UNIVERSE; 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; u32 metric = 0;
if (new && e->attrs->source == RTS_INHERIT) 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]); ra.nexthops = nl_parse_multipath(p, a[RTA_MULTIPATH]);
if (!ra.nexthops) if (!ra.nexthops)
{ {
log(L_ERR "KRT: Received strange multipath route %I/%d", log(L_ERR "KRT: Received strange multipath route %F", &net->n);
net->n.prefix, net->n.pxlen);
return; return;
} }
@ -848,8 +847,8 @@ nl_parse_route(struct nlmsghdr *h, int scan)
ra.iface = if_find_by_index(oif); ra.iface = if_find_by_index(oif);
if (!ra.iface) if (!ra.iface)
{ {
log(L_ERR "KRT: Received route %I/%d with unknown ifindex %u", log(L_ERR "KRT: Received route %F with unknown ifindex %u",
net->n.prefix, net->n.pxlen, oif); &net->n, oif);
return; return;
} }
@ -868,8 +867,8 @@ nl_parse_route(struct nlmsghdr *h, int scan)
(i->rtm_flags & RTNH_F_ONLINK) ? NEF_ONLINK : 0); (i->rtm_flags & RTNH_F_ONLINK) ? NEF_ONLINK : 0);
if (!ng || (ng->scope == SCOPE_HOST)) if (!ng || (ng->scope == SCOPE_HOST))
{ {
log(L_ERR "KRT: Received route %I/%d with strange next-hop %I", log(L_ERR "KRT: Received route %F with strange next-hop %I",
net->n.prefix, net->n.pxlen, ra.gw); &net->n, ra.gw);
return; return;
} }
} }

View File

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