Initial commit on integrated BIRD

New data types net_addr and variants (in lib/net.h) describing
network addresses (prefix/pxlen). Modifications of FIB structures
to handle these data types and changing everything to use these
data types instead of prefix/pxlen pairs where possible.

The commit is WiP, some protocols are not yet updated (BGP, Kernel),
and the code contains some temporary scaffolding.

Comments are welcome.
This commit is contained in:
Ondrej Zajicek (work) 2015-11-05 12:48:52 +01:00
parent 8eb8e546dc
commit fe9f1a6ded
42 changed files with 875 additions and 500 deletions

View file

@ -123,27 +123,15 @@ include ^{WHITE}*include{WHITE}*\".*\"{WHITE}*;
} }
{DIGIT}+\.{DIGIT}+\.{DIGIT}+\.{DIGIT}+ { {DIGIT}+\.{DIGIT}+\.{DIGIT}+\.{DIGIT}+ {
ip4_addr a; if (!ip4_pton(yytext, &cf_lval.ip4))
if (!ip4_pton(yytext, &a))
cf_error("Invalid IPv4 address %s", yytext); cf_error("Invalid IPv4 address %s", yytext);
return IP4;
#ifdef IPV6
cf_lval.i32 = ip4_to_u32(a);
return RTRID;
#else
cf_lval.a = ipa_from_ip4(a);
return IPA;
#endif
} }
({XIGIT}*::|({XIGIT}*:){3,})({XIGIT}*|{DIGIT}+\.{DIGIT}+\.{DIGIT}+\.{DIGIT}+) { ({XIGIT}*::|({XIGIT}*:){3,})({XIGIT}*|{DIGIT}+\.{DIGIT}+\.{DIGIT}+\.{DIGIT}+) {
#ifdef IPV6 if (!ip6_pton(yytext, &cf_lval.ip6))
if (ipa_pton(yytext, &cf_lval.a)) cf_error("Invalid IPv6 address %s", yytext);
return IPA; return IP6;
cf_error("Invalid IPv6 address %s", yytext);
#else
cf_error("This is an IPv4 router, therefore IPv6 addresses are not supported");
#endif
} }
0x{XIGIT}+ { 0x{XIGIT}+ {

View file

@ -133,10 +133,10 @@ config_parse(struct config *c)
protos_postconfig(c); protos_postconfig(c);
if (EMPTY_LIST(c->protos)) if (EMPTY_LIST(c->protos))
cf_error("No protocol is specified in the config file"); cf_error("No protocol is specified in the config file");
#ifdef IPV6 /* XXXX */
if (!c->router_id) if (!c->router_id)
cf_error("Router ID must be configured manually on IPv6 routers"); cf_error("Router ID must be configured manually");
#endif
return 1; return 1;
} }

View file

@ -39,6 +39,8 @@ CF_DECLS
int i; int i;
u32 i32; u32 i32;
ip_addr a; ip_addr a;
ip4_addr ip4;
ip6_addr ip6;
struct symbol *s; struct symbol *s;
char *t; char *t;
struct rtable_config *r; struct rtable_config *r;
@ -66,8 +68,8 @@ CF_DECLS
%token GEQ LEQ NEQ AND OR %token GEQ LEQ NEQ AND OR
%token PO PC %token PO PC
%token <i> NUM ENUM %token <i> NUM ENUM
%token <i32> RTRID %token <ip4> IP4
%token <a> IPA %token <ip6> IP6
%token <s> SYM %token <s> SYM
%token <t> TEXT %token <t> TEXT
%type <iface> ipa_scope %type <iface> ipa_scope
@ -75,10 +77,11 @@ CF_DECLS
%type <i> expr bool pxlen %type <i> expr bool pxlen
%type <i32> expr_us %type <i32> expr_us
%type <time> datetime %type <time> datetime
%type <a> ipa %type <a> ipa ipa_raw
%type <px> prefix prefix_or_ipa %type <px> prefix prefix_or_ipa
%type <t> text %type <t> text
%type <t> text_or_none %type <t> text_or_none
%type <t> opttext
%nonassoc PREFIX_DUMMY %nonassoc PREFIX_DUMMY
%left AND OR %left AND OR
@ -148,8 +151,13 @@ bool:
/* Addresses, prefixes and netmasks */ /* Addresses, prefixes and netmasks */
ipa_raw:
IP4 { $$ = ipa_from_ip4($1); }
| IP6 { $$ = ipa_from_ip6($1); }
;
ipa: ipa:
IPA ipa_raw
| SYM { | SYM {
if ($1->class != (SYM_CONSTANT | T_IP)) cf_error("IP address expected"); if ($1->class != (SYM_CONSTANT | T_IP)) cf_error("IP address expected");
$$ = SYM_VAL($1).px.ip; $$ = SYM_VAL($1).px.ip;
@ -205,6 +213,12 @@ text_or_none:
| { $$ = NULL; } | { $$ = NULL; }
; ;
opttext:
TEXT
| /* empty */ { $$ = NULL; }
;
CF_CODE CF_CODE
CF_END CF_END

View file

@ -205,7 +205,7 @@ fi
AC_SUBST(iproutedir) AC_SUBST(iproutedir)
all_protocols="$proto_bfd bgp ospf pipe $proto_radv rip static" all_protocols="$proto_bfd ospf pipe $proto_radv rip static"
all_protocols=`echo $all_protocols | sed 's/ /,/g'` all_protocols=`echo $all_protocols | sed 's/ /,/g'`
if test "$with_protocols" = all ; then if test "$with_protocols" = all ; then

View file

@ -477,7 +477,7 @@ block:
* Complex types, their bison value is struct f_val * Complex types, their bison value is struct f_val
*/ */
fipa: fipa:
IPA %prec PREFIX_DUMMY { $$.type = T_IP; $$.val.px.ip = $1; } ipa_raw %prec PREFIX_DUMMY { $$.type = T_IP; $$.val.px.ip = $1; }
; ;
@ -491,7 +491,6 @@ fipa:
set_atom: set_atom:
NUM { $$.type = T_INT; $$.val.i = $1; } NUM { $$.type = T_INT; $$.val.i = $1; }
| RTRID { $$.type = T_QUAD; $$.val.i = $1; }
| fipa { $$ = $1; } | fipa { $$ = $1; }
| ENUM { $$.type = pair_a($1); $$.val.i = pair_b($1); } | ENUM { $$.type = pair_a($1); $$.val.i = pair_b($1); }
| '(' term ')' { | '(' term ')' {
@ -508,7 +507,6 @@ set_atom:
switch_atom: switch_atom:
NUM { $$.type = T_INT; $$.val.i = $1; } NUM { $$.type = T_INT; $$.val.i = $1; }
| '(' term ')' { $$.type = T_INT; $$.val.i = f_eval_int($2); } | '(' term ')' { $$.type = T_INT; $$.val.i = f_eval_int($2); }
| RTRID { $$.type = T_QUAD; $$.val.i = $1; }
| fipa { $$ = $1; } | fipa { $$ = $1; }
| ENUM { $$.type = pair_a($1); $$.val.i = pair_b($1); } | ENUM { $$.type = pair_a($1); $$.val.i = pair_b($1); }
; ;
@ -575,7 +573,7 @@ switch_items:
; ;
fprefix_s: fprefix_s:
IPA '/' NUM %prec '/' { ipa_raw '/' NUM %prec '/' {
if (($3 < 0) || ($3 > MAX_PREFIX_LENGTH) || !ip_is_prefix($1, $3)) cf_error("Invalid network prefix: %I/%d.", $1, $3); if (($3 < 0) || ($3 > MAX_PREFIX_LENGTH) || !ip_is_prefix($1, $3)) cf_error("Invalid network prefix: %I/%d.", $1, $3);
$$.type = T_PREFIX; $$.val.px.ip = $1; $$.val.px.len = $3; $$.type = T_PREFIX; $$.val.px.ip = $1; $$.val.px.len = $3;
} }
@ -646,7 +644,6 @@ constant:
| TEXT { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_STRING; $$->a2.p = $1; } | TEXT { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_STRING; $$->a2.p = $1; }
| fipa { NEW_F_VAL; $$ = f_new_inst(); $$->code = 'C'; $$->a1.p = val; *val = $1; } | fipa { NEW_F_VAL; $$ = f_new_inst(); $$->code = 'C'; $$->a1.p = val; *val = $1; }
| fprefix_s {NEW_F_VAL; $$ = f_new_inst(); $$->code = 'C'; $$->a1.p = val; *val = $1; } | fprefix_s {NEW_F_VAL; $$ = f_new_inst(); $$->code = 'C'; $$->a1.p = val; *val = $1; }
| RTRID { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_QUAD; $$->a2.i = $1; }
| '[' set_items ']' { DBG( "We've got a set here..." ); $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_SET; $$->a2.p = build_tree($2); DBG( "ook\n" ); } | '[' set_items ']' { DBG( "We've got a set here..." ); $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_SET; $$->a2.p = build_tree($2); DBG( "ook\n" ); }
| '[' fprefix_set ']' { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_PREFIX_SET; $$->a2.p = $2; } | '[' fprefix_set ']' { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_PREFIX_SET; $$->a2.p = $2; }
| ENUM { $$ = f_new_inst(); $$->code = 'c'; $$->aux = $1 >> 16; $$->a2.i = $1 & 0xffff; } | ENUM { $$ = f_new_inst(); $$->code = 'c'; $$->aux = $1 >> 16; $$->a2.i = $1 & 0xffff; }

View file

@ -792,8 +792,8 @@ interpret(struct f_inst *what)
{ {
case SA_FROM: res.val.px.ip = rta->from; break; case SA_FROM: res.val.px.ip = rta->from; break;
case SA_GW: res.val.px.ip = rta->gw; break; case SA_GW: res.val.px.ip = rta->gw; break;
case SA_NET: res.val.px.ip = (*f_rte)->net->n.prefix; case SA_NET: res.val.px.ip = net_prefix((*f_rte)->net->n.addr);
res.val.px.len = (*f_rte)->net->n.pxlen; break; res.val.px.len = net_pxlen((*f_rte)->net->n.addr); break;
case SA_PROTO: res.val.s = rta->src->proto->name; break; case SA_PROTO: res.val.s = rta->src->proto->name; break;
case SA_SOURCE: res.val.i = rta->source; break; case SA_SOURCE: res.val.i = rta->source; break;
case SA_SCOPE: res.val.i = rta->scope; break; case SA_SCOPE: res.val.i = rta->scope; break;
@ -1292,8 +1292,8 @@ interpret(struct f_inst *what)
else else
{ {
ACCESS_RTE; ACCESS_RTE;
v1.val.px.ip = (*f_rte)->net->n.prefix; v1.val.px.ip = net_prefix((*f_rte)->net->n.addr);
v1.val.px.len = (*f_rte)->net->n.pxlen; v1.val.px.len = net_pxlen((*f_rte)->net->n.addr);
/* We ignore temporary attributes, probably not a problem here */ /* We ignore temporary attributes, probably not a problem here */
/* 0x02 is a value of BA_AS_PATH, we don't want to include BGP headers */ /* 0x02 is a value of BA_AS_PATH, we don't want to include BGP headers */

View file

@ -28,15 +28,15 @@ u32_mkmask(uint n)
* *
* This function checks whether the given integer @x represents * This function checks whether the given integer @x represents
* a valid bit mask (binary representation contains first ones, then * a valid bit mask (binary representation contains first ones, then
* zeroes) and returns the number of ones or -1 if the mask is invalid. * zeroes) and returns the number of ones or 255 if the mask is invalid.
*/ */
int uint
u32_masklen(u32 x) u32_masklen(u32 x)
{ {
int l = 0; int l = 0;
u32 n = ~x; u32 n = ~x;
if (n & (n+1)) return -1; if (n & (n+1)) return 255;
if (x & 0x0000ffff) { x &= 0x0000ffff; l += 16; } if (x & 0x0000ffff) { x &= 0x0000ffff; l += 16; }
if (x & 0x00ff00ff) { x &= 0x00ff00ff; l += 8; } if (x & 0x00ff00ff) { x &= 0x00ff00ff; l += 8; }
if (x & 0x0f0f0f0f) { x &= 0x0f0f0f0f; l += 4; } if (x & 0x0f0f0f0f) { x &= 0x0f0f0f0f; l += 4; }

View file

@ -19,7 +19,7 @@
*/ */
u32 u32_mkmask(uint n); u32 u32_mkmask(uint n);
int u32_masklen(u32 x); uint u32_masklen(u32 x);
u32 u32_log2(u32 v); u32 u32_log2(u32 v);

View file

@ -58,7 +58,7 @@ ip6_mkmask(uint n)
return a; return a;
} }
int uint
ip6_masklen(ip6_addr *a) ip6_masklen(ip6_addr *a)
{ {
int i, j, n; int i, j, n;
@ -72,7 +72,7 @@ ip6_masklen(ip6_addr *a)
n += j; n += j;
while (++i < 4) while (++i < 4)
if (a->addr[i]) if (a->addr[i])
return -1; return 255;
break; break;
} }

View file

@ -30,6 +30,9 @@
#define IP4_NONE _MI4(0) #define IP4_NONE _MI4(0)
#define IP6_NONE _MI6(0,0,0,0) #define IP6_NONE _MI6(0,0,0,0)
#define IP4_MAX_PREFIX_LENGTH 32
#define IP6_MAX_PREFIX_LENGTH 128
#define IP4_MIN_MTU 576 #define IP4_MIN_MTU 576
#define IP6_MIN_MTU 1280 #define IP6_MIN_MTU 1280
@ -39,17 +42,14 @@
#define IP6_HEADER_LENGTH 40 #define IP6_HEADER_LENGTH 40
#define UDP_HEADER_LENGTH 8 #define UDP_HEADER_LENGTH 8
#ifdef IPV6 #ifdef IPV6
#define MAX_PREFIX_LENGTH 128 #define MAX_PREFIX_LENGTH 128
#define BITS_PER_IP_ADDRESS 128 #define BITS_PER_IP_ADDRESS 128
#define STD_ADDRESS_P_LENGTH 39 #define STD_ADDRESS_P_LENGTH 39
#define SIZE_OF_IP_HEADER 40
#else #else
#define MAX_PREFIX_LENGTH 32 #define MAX_PREFIX_LENGTH 32
#define BITS_PER_IP_ADDRESS 32 #define BITS_PER_IP_ADDRESS 32
#define STD_ADDRESS_P_LENGTH 15 #define STD_ADDRESS_P_LENGTH 15
#define SIZE_OF_IP_HEADER 24
#endif #endif
@ -319,11 +319,11 @@ static inline int ipa_classify_net(ip_addr a)
static inline ip4_addr ip4_mkmask(uint n) static inline ip4_addr ip4_mkmask(uint n)
{ return _MI4(u32_mkmask(n)); } { return _MI4(u32_mkmask(n)); }
static inline int ip4_masklen(ip4_addr a) static inline uint ip4_masklen(ip4_addr a)
{ return u32_masklen(_I(a)); } { return u32_masklen(_I(a)); }
ip6_addr ip6_mkmask(uint n); ip6_addr ip6_mkmask(uint n);
int ip6_masklen(ip6_addr *a); uint ip6_masklen(ip6_addr *a);
/* ipX_pxlen() requires that x != y */ /* ipX_pxlen() requires that x != y */
static inline uint ip4_pxlen(ip4_addr a, ip4_addr b) static inline uint ip4_pxlen(ip4_addr a, ip4_addr b)
@ -345,6 +345,18 @@ static inline u32 ip4_getbit(ip4_addr a, uint pos)
static inline u32 ip6_getbit(ip6_addr a, uint pos) static inline u32 ip6_getbit(ip6_addr a, uint pos)
{ return a.addr[pos / 32] & (0x80000000 >> (pos % 32)); } { return a.addr[pos / 32] & (0x80000000 >> (pos % 32)); }
static inline u32 ip4_setbit(ip4_addr *a, uint pos)
{ return _I(*a) |= (0x80000000 >> pos); }
static inline u32 ip6_setbit(ip6_addr *a, uint pos)
{ return a->addr[pos / 32] |= (0x80000000 >> (pos % 32)); }
static inline u32 ip4_clrbit(ip4_addr *a, uint pos)
{ return _I(*a) &= ~(0x80000000 >> pos); }
static inline u32 ip6_clrbit(ip6_addr *a, uint pos)
{ return a->addr[pos / 32] &= ~(0x80000000 >> (pos % 32)); }
static inline ip4_addr ip4_opposite_m1(ip4_addr a) static inline ip4_addr ip4_opposite_m1(ip4_addr a)
{ return _MI4(_I(a) ^ 1); } { return _MI4(_I(a) ^ 1); }
@ -364,6 +376,8 @@ ip4_addr ip4_class_mask(ip4_addr ad);
#define ipa_masklen(x) ip6_masklen(&x) #define ipa_masklen(x) ip6_masklen(&x)
#define ipa_pxlen(x,y) ip6_pxlen(x,y) #define ipa_pxlen(x,y) ip6_pxlen(x,y)
#define ipa_getbit(x,n) ip6_getbit(x,n) #define ipa_getbit(x,n) ip6_getbit(x,n)
#define ipa_setbit(x,n) ip6_setbit(x,n)
#define ipa_clrbit(x,n) ip6_clrbit(x,n)
#define ipa_opposite_m1(x) ip6_opposite_m1(x) #define ipa_opposite_m1(x) ip6_opposite_m1(x)
#define ipa_opposite_m2(x) ip6_opposite_m2(x) #define ipa_opposite_m2(x) ip6_opposite_m2(x)
#else #else
@ -371,6 +385,8 @@ ip4_addr ip4_class_mask(ip4_addr ad);
#define ipa_masklen(x) ip4_masklen(x) #define ipa_masklen(x) ip4_masklen(x)
#define ipa_pxlen(x,y) ip4_pxlen(x,y) #define ipa_pxlen(x,y) ip4_pxlen(x,y)
#define ipa_getbit(x,n) ip4_getbit(x,n) #define ipa_getbit(x,n) ip4_getbit(x,n)
#define ipa_setbit(x,n) ip4_setbit(x,n)
#define ipa_clrbit(x,n) ip4_clrbit(x,n)
#define ipa_opposite_m1(x) ip4_opposite_m1(x) #define ipa_opposite_m1(x) ip4_opposite_m1(x)
#define ipa_opposite_m2(x) ip4_opposite_m2(x) #define ipa_opposite_m2(x) ip4_opposite_m2(x)
#endif #endif

47
lib/net.c Normal file
View file

@ -0,0 +1,47 @@
#include "nest/bird.h"
#include "lib/ip.h"
#include "lib/net.h"
const u16 net_addr_length[] = {
[NET_IP4] = sizeof(net_addr_ip4),
[NET_IP6] = sizeof(net_addr_ip6),
[NET_VPN4] = sizeof(net_addr_vpn4),
[NET_VPN6] = sizeof(net_addr_vpn6)
}
char *
net_format(const net_addr *N, char *buf, int buflen)
{
net_addr_union *n = (void *) N;
/* FIXME: quick hack */
switch (n->n.type)
{
case NET_IP4:
return bsnprintf(buf, buflen, "%I/%d", n->ip4.prefix, n->ip4.pxlen);
case NET_IP6:
return bsnprintf(buf, buflen, "%I/%d", n->ip6.prefix, n->ip6.pxlen);
case NET_VPN4:
return bsnprintf(buf, buflen, "%u:%u %I/%d", (u32) (n->vpn4.rd >> 32), (u32) n->vpn4.rd, n->vpn4.prefix, n->vpn4.pxlen);
case NET_VPN6:
return bsnprintf(buf, buflen, "%u:%u %I/%d", (u32) (n->vpn6.rd >> 32), (u32) n->vpn6.rd, n->vpn6.prefix, n->vpn6.pxlen);
}
}
int
net_classify(const net_addr *N)
{
net_addr_union *n = (void *) N;
switch (n->n.type)
{
case NET_IP4:
case NET_VPN4:
return ip4_zero(n->ip4.prefix) ? (IADDR_HOST | SCOPE_UNIVERSE) : ip4_classify(n->ip4.prefix);
case NET_IP6:
case NET_VPN6:
return ip6_zero(n->ip6.prefix) ? (IADDR_HOST | SCOPE_UNIVERSE) : ip6_classify(n->ip6.prefix);
}
}

214
lib/net.h Normal file
View file

@ -0,0 +1,214 @@
/*
* BIRD Internet Routing Daemon -- Network addresses
*
* (c) 2015 Ondrej Zajicek <santiago@crfreenet.org>
* (c) 2015 CZ.NIC z.s.p.o.
*
* Can be freely distributed and used under the terms of the GNU GPL.
*/
#ifndef _BIRD_NET_H_
#define _BIRD_NET_H_
#include "lib/ip.h"
#define NET_IP4 1
#define NET_IP6 2
#define NET_VPN4 3
#define NET_VPN6 4
#define NET_MAX 5
typedef struct net_addr {
u8 type;
u8 pxlen;
u16 length;
u64 align[0];
u32 space[4];
} net_addr;
typedef struct net_addr_ip4 {
u8 type;
u8 pxlen;
u16 length;
ip4_addr prefix;
} net_addr_ip4;
typedef struct net_addr_ip6 {
u8 type;
u8 pxlen;
u16 length;
ip6_addr prefix;
} net_addr_ip6;
typedef struct net_addr_vpn4 {
u8 type;
u8 pxlen;
u16 length;
ip4_addr prefix;
u64 rd;
} net_addr_vpn4;
typedef struct net_addr_vpn6 {
u8 type;
u8 pxlen;
u16 length;
ip6_addr prefix;
u64 rd;
} net_addr_vpn6;
typedef union net_addr_union {
net_addr n;
net_addr_ip4 ip4;
net_addr_ip6 ip6;
net_addr_vpn4 vpn4;
net_addr_vpn6 vpn6;
} net_addr_union;
extern const u16 net_addr_length[];
#define NET_ADDR_IP4(prefix,pxlen) \
((net_addr_ip4) { NET_IP4, pxlen, sizeof(net_addr_ip4), prefix })
#define NET_ADDR_IP6(prefix,pxlen) \
((net_addr_ip6) { NET_IP6, pxlen, sizeof(net_addr_ip6), prefix })
#define NET_ADDR_VPN4(prefix,pxlen,rd) \
((net_addr_vpn4) { NET_VPN4, pxlen, sizeof(net_addr_vpn4), prefix, rd })
#define NET_ADDR_VPN6(prefix,pxlen,rd) \
((net_addr_vpn6) { NET_VPN6, pxlen, sizeof(net_addr_vpn6), prefix, rd })
static inline void net_fill_ip4(net_addr *a, ip4_addr prefix, uint pxlen)
{ *(net_addr_ip4 *)a = NET_ADDR_IP4(prefix, pxlen); }
static inline void net_fill_ip6(net_addr *a, ip6_addr prefix, uint pxlen)
{ *(net_addr_ip6 *)a = NET_ADDR_IP6(prefix, pxlen); }
static inline void net_fill_vpn4(net_addr *a, ip4_addr prefix, uint pxlen, u64 rd)
{ *(net_addr_vpn4 *)a = NET_ADDR_VPN4(prefix, pxlen, rd); }
static inline void net_fill_vpn6(net_addr *a, ip6_addr prefix, uint pxlen, u64 rd)
{ *(net_addr_vpn6 *)a = NET_ADDR_VPN6(prefix, pxlen, rd); }
static inline void net_fill_ipa(net_addr *a, ip_addr prefix, uint pxlen)
{
if (ipa_is_ip4(prefix))
net_fill_ip4(a, ipa_to_ip4(prefix), pxlen);
else
net_fill_ip6(a, ipa_to_ip6(prefix), pxlen);
}
static inline ip4_addr net4_prefix(const net_addr *a)
{ return ((net_addr_ip4 *) a)->prefix; }
static inline ip6_addr net6_prefix(const net_addr *a)
{ return ((net_addr_ip6 *) a)->prefix; }
static inline ip_addr net_prefix(const net_addr *a)
{
switch (a->type)
{
case NET_IP4:
case NET_VPN4: return ipa_from_ip4(net4_prefix(a));
case NET_IP6:
case NET_VPN6: return ipa_from_ip6(net6_prefix(a));
default: return IPA_NONE;
}
}
static inline uint net4_pxlen(const net_addr *a)
{ return a->pxlen; }
static inline uint net6_pxlen(const net_addr *a)
{ return a->pxlen; }
static inline uint net_pxlen(const net_addr *a)
{ return a->pxlen; }
static inline int net_equal(const net_addr *a, const net_addr *b)
{ return (a->length == b->length) && !memcmp(a, b, a->length); }
static inline int net_equal_ip4(const net_addr_ip4 *a, const net_addr_ip4 *b)
{ return !memcmp(a, b, sizeof(net_addr_ip4)); }
static inline int net_equal_ip6(const net_addr_ip6 *a, const net_addr_ip6 *b)
{ return !memcmp(a, b, sizeof(net_addr_ip6)); }
static inline int net_equal_vpn4(const net_addr_vpn4 *a, const net_addr_vpn4 *b)
{ return !memcmp(a, b, sizeof(net_addr_vpn4)); }
static inline int net_equal_vpn6(const net_addr_vpn6 *a, const net_addr_vpn6 *b)
{ return !memcmp(a, b, sizeof(net_addr_vpn6)); }
static inline int net_zero_ip4(const net_addr_ip4 *a)
{ return !a->pxlen && ip4_zero(a->prefix); }
static inline int net_zero_ip6(const net_addr_ip6 *a)
{ return !a->pxlen && ip6_zero(a->prefix); }
static inline int net_zero_vpn4(const net_addr_vpn4 *a)
{ return !a->pxlen && ip4_zero(a->prefix) && !a->rd; }
static inline int net_zero_vpn6(const net_addr_vpn6 *a)
{ return !a->pxlen && ip6_zero(a->prefix) && !a->rd; }
static inline void net_copy(net_addr *dst, const net_addr *src)
{ memcpy(dst, src, src->length); }
static inline void net_copy_ip4(net_addr_ip4 *dst, const net_addr_ip4 *src)
{ memcpy(dst, src, sizeof(net_addr_ip4)); }
static inline void net_copy_ip6(net_addr_ip6 *dst, const net_addr_ip6 *src)
{ memcpy(dst, src, sizeof(net_addr_ip6)); }
static inline void net_copy_vpn4(net_addr_vpn4 *dst, const net_addr_vpn4 *src)
{ memcpy(dst, src, sizeof(net_addr_vpn4)); }
static inline void net_copy_vpn6(net_addr_vpn6 *dst, const net_addr_vpn6 *src)
{ memcpy(dst, src, sizeof(net_addr_vpn6)); }
static inline u32 net_hash_ip4(const net_addr_ip4 *n)
{ return ip4_hash(n->prefix) ^ ((u32) n->pxlen << 26); }
static inline u32 net_hash_ip6(const net_addr_ip6 *n)
{ return ip6_hash(n->prefix) ^ ((u32) n->pxlen << 26); }
/* XXXX */
static inline u32 u64_hash(u32 a)
{ return u32_hash(a); }
static inline u32 net_hash_vpn4(const net_addr_vpn4 *n)
{ return ip4_hash(n->prefix) ^ ((u32) n->pxlen << 26) ^ u64_hash(n->rd); }
static inline u32 net_hash_vpn6(const net_addr_vpn6 *n)
{ return ip6_hash(n->prefix) ^ ((u32) n->pxlen << 26) ^ u64_hash(n->rd); }
static inline void net_normalize_ip4(net_addr_ip4 *n)
{ n->prefix = ip4_and(n->prefix, ip4_mkmask(n->pxlen)); }
static inline void net_normalize_ip6(net_addr_ip6 *n)
{ n->prefix = ip6_and(n->prefix, ip6_mkmask(n->pxlen)); }
void net_normalize(net_addr *N);
int net_validate(const net_addr *N);
int net_classify(const net_addr *N);
char * net_format(const net_addr *N, char *buf, int buflen);
#endif

View file

@ -236,6 +236,12 @@ int bvsnprintf(char *buf, int size, const char *fmt, va_list args)
case 'M': case 'M':
s = strerror(va_arg(args, int)); s = strerror(va_arg(args, int));
goto str; goto str;
case 'N':
if (field_width == 1)
field_width = STD_ADDRESS_P_LENGTH; /* XXXX */
net_format(va_arg(args, net_addr *), ipbuf, sizeof(ipbuf));
s = ipbuf;
goto str;
case 's': case 's':
s = va_arg(args, char *); s = va_arg(args, char *);
if (!s) if (!s)

View file

@ -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 a-path.c a-set.c
root-rel=../ root-rel=../
dir-name=nest dir-name=nest

View file

@ -12,5 +12,6 @@
#include "sysdep/config.h" #include "sysdep/config.h"
#include "lib/birdlib.h" #include "lib/birdlib.h"
#include "lib/ip.h" #include "lib/ip.h"
#include "lib/net.h"
#endif #endif

View file

@ -55,6 +55,7 @@ CF_DECLS
CF_KEYWORDS(ROUTER, ID, PROTOCOL, TEMPLATE, PREFERENCE, DISABLED, DEBUG, ALL, OFF, DIRECT) 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(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(RECEIVE, LIMIT, ACTION, WARN, BLOCK, RESTART, DISABLE, KEEP, FILTERED)
CF_KEYWORDS(PASSWORD, FROM, PASSIVE, TO, ID, EVENTS, PACKETS, PROTOCOLS, INTERFACES) CF_KEYWORDS(PASSWORD, FROM, PASSIVE, TO, ID, EVENTS, PACKETS, PROTOCOLS, INTERFACES)
CF_KEYWORDS(PRIMARY, STATS, COUNT, FOR, COMMANDS, PREEXPORT, NOEXPORT, GENERATE, ROA) 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 <ro> roa_args
%type <rot> roa_table_arg %type <rot> roa_table_arg
%type <sd> sym_args %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 <ps> proto_patt proto_patt2
%type <g> limit_spec %type <g> limit_spec
@ -95,14 +96,7 @@ rtrid:
idval: idval:
NUM { $$ = $1; } NUM { $$ = $1; }
| '(' term ')' { $$ = f_eval_int($2); } | '(' term ')' { $$ = f_eval_int($2); }
| RTRID | IP4 { $$ = ip4_to_u32($1); }
| 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
}
| SYM { | SYM {
if ($1->class == (SYM_CONSTANT | T_INT) || $1->class == (SYM_CONSTANT | T_QUAD)) if ($1->class == (SYM_CONSTANT | T_INT) || $1->class == (SYM_CONSTANT | T_QUAD))
$$ = SYM_VAL($1).i; $$ = SYM_VAL($1).i;
@ -140,17 +134,25 @@ gr_opts: GRACEFUL RESTART WAIT expr ';' { new_config->gr_wait = $4; } ;
/* Creation of routing tables */ /* 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; } { $$ = 0; }
| SORTED { $$ = 1; } | SORTED { $$ = 1; }
; ;
CF_ADDTO(conf, newtab) table: table_type TABLE SYM table_sorted {
newtab: TABLE SYM tab_sorted {
struct rtable_config *cf; struct rtable_config *cf;
cf = rt_new_table($2); cf = rt_new_table($3, $1);
cf->sorted = $3; cf->sorted = $4;
} }
; ;

View file

@ -35,11 +35,9 @@ struct cli;
struct fib_node { struct fib_node {
struct fib_node *next; /* Next in hash chain */ struct fib_node *next; /* Next in hash chain */
struct fib_iterator *readers; /* List of readers of this node */ struct fib_iterator *readers; /* List of readers of this node */
byte pxlen; byte flags; /* User-defined, will be removed */
byte flags; /* User-defined */ u32 uid; /* Unique ID based on hash, will be removed */
byte x0, x1; /* User-defined */ net_addr addr[0];
u32 uid; /* Unique ID based on hash */
ip_addr prefix; /* In host order */
}; };
struct fib_iterator { /* See lib/slists.h for an explanation */ 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; uint hash;
}; };
typedef void (*fib_init_func)(struct fib_node *); typedef void (*fib_init_fn)(void *);
struct fib { struct fib {
pool *fib_pool; /* Pool holding all our data */ 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_size; /* Number of hash table entries (a power of two) */
uint hash_order; /* Binary logarithm of hash_size */ uint hash_order; /* Binary logarithm of hash_size */
uint hash_shift; /* 16 - hash_log */ 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; /* Number of entries */
uint entries_min, entries_max; /* Entry count limits (else start rehashing) */ 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_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 *, ip_addr *, int); /* Find or return NULL if doesn't exist */ void *fib_find(struct fib *, net_addr *); /* Find or return NULL if doesn't exist */
void *fib_get(struct fib *, ip_addr *, int); /* Find or create new if nonexistent */ void *fib_get(struct fib *, net_addr *); /* Find or create new if nonexistent */
void *fib_route(struct fib *, ip_addr, int); /* Longest-match routing lookup */ void *fib_route(struct fib *, net_addr *); /* 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 */
@ -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(struct fib_iterator *, struct fib_node *);
void fit_put_next(struct fib *f, struct fib_iterator *i, struct fib_node *n, uint hpos); 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 { \ #define FIB_WALK(fib, z) do { \
struct fib_node *z, **ff = (fib)->hash_table; \ struct fib_node *z, **ff = (fib)->hash_table; \
uint count = (fib)->hash_size; \ uint count = (fib)->hash_size; \
@ -126,6 +127,7 @@ struct rtable_config {
char *name; char *name;
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 */
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_max_ops; /* Maximum number of operations before GC is run */
int gc_min_time; /* Minimum time between two consecutive GC runs */ int gc_min_time; /* Minimum time between two consecutive GC runs */
byte sorted; /* Routes of network are sorted according to rte_better() */ byte sorted; /* Routes of network are sorted according to rte_better() */
@ -136,6 +138,7 @@ typedef struct rtable {
struct fib fib; struct fib fib;
char *name; /* Name of this table */ char *name; /* Name of this table */
list hooks; /* List of announcement hooks */ list hooks; /* List of announcement hooks */
uint addr_type; /* Type of address data stored in table (NET_*) */
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 */
struct hostcache *hostcache; struct hostcache *hostcache;
@ -160,8 +163,8 @@ typedef struct rtable {
#define RPS_RUNNING 2 #define RPS_RUNNING 2
typedef struct network { typedef struct network {
struct fib_node n; /* FIB flags reserved for kernel syncer */
struct rte *routes; /* Available routes for this network */ struct rte *routes; /* Available routes for this network */
struct fib_node n; /* FIB flags reserved for kernel syncer */
} net; } net;
struct hostcache { struct hostcache {
@ -262,14 +265,20 @@ void rt_commit(struct config *new, struct config *old);
void rt_lock_table(rtable *); void rt_lock_table(rtable *);
void rt_unlock_table(rtable *); void rt_unlock_table(rtable *);
void rt_setup(pool *, rtable *, char *, struct rtable_config *); 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_find(rtable *tab, net_addr *addr) { return (net *) fib_find(&tab->fib, addr); }
static inline net *net_get(rtable *tab, ip_addr addr, unsigned len) { return (net *) fib_get(&tab->fib, &addr, len); } 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_find(net *net, struct rte_src *src);
rte *rte_get_temp(struct rta *); rte *rte_get_temp(struct rta *);
void rte_update2(struct announce_hook *ah, net *net, rte *new, struct rte_src *src); 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); } 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); 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); 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_begin(rtable *t, struct announce_hook *ah);
void rt_refresh_end(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); int rt_feed_baby(struct proto *p);
void rt_feed_baby_abort(struct proto *p); void rt_feed_baby_abort(struct proto *p);
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, uint addr_type);
static inline void static inline void
rt_mark_for_prune(rtable *tab) rt_mark_for_prune(rtable *tab)

View file

@ -45,7 +45,7 @@ dev_ifa_notify(struct proto *p, unsigned c, struct ifa *ad)
net *n; net *n;
DBG("dev_if_notify: %s:%I going down\n", ad->iface->name, ad->ip); 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_ipa(p->table, ad->prefix, ad->pxlen);
if (!n) if (!n)
{ {
DBG("dev_if_notify: device shutdown: prefix not found\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); a = rta_lookup(&a0);
n = net_get(p->table, ad->prefix, ad->pxlen); n = net_get_ipa(p->table, ad->prefix, ad->pxlen);
e = rte_get_temp(a); e = rte_get_temp(a);
e->net = n; e->net = n;
e->pflags = 0; e->pflags = 0;

View file

@ -48,6 +48,13 @@
#define HASH_LO_STEP 2 #define HASH_LO_STEP 2
#define HASH_LO_MIN 10 #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 static void
fib_ht_alloc(struct fib *f) fib_ht_alloc(struct fib *f)
{ {
@ -72,16 +79,9 @@ fib_ht_free(struct fib_node **h)
mb_free(h); mb_free(h);
} }
static inline unsigned
fib_hash(struct fib *f, ip_addr *a)
{
return ipa_hash(*a) >> f->hash_shift;
}
static void static u32
fib_dummy_init(struct fib_node *dummy UNUSED) fib_hash(struct fib *f, net_addr *a);
{
}
/** /**
* fib_init - initialize a new FIB * 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. * This function initializes a newly allocated FIB and prepares it for use.
*/ */
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, 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) if (!hash_order)
hash_order = HASH_DEF_ORDER; hash_order = HASH_DEF_ORDER;
f->fib_pool = p; 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; 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->entries = 0; f->entries = 0;
f->entries_min = 0; f->entries_min = 0;
f->init = init ? : fib_dummy_init; f->init = init;
} }
static void static void
@ -133,7 +138,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, e->addr);
while (nh > ni) while (nh > ni)
{ {
*t = NULL; *t = NULL;
@ -153,6 +158,76 @@ fib_rehash(struct fib *f, int step)
fib_ht_free(m); 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 * fib_find - search for FIB node by prefix
* @f: FIB to search in * @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 * Search for a FIB node corresponding to the given prefix, return
* 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, net_addr *a)
{ {
struct fib_node *e = f->hash_table[fib_hash(f, 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; e = e->next;
return e; 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. * 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, net_addr *a)
{ {
uint h = ipa_hash(*a); char *b = fib_find(f, a);
struct fib_node **ee = f->hash_table + (h >> f->hash_shift); if (b)
struct fib_node *g, *e = *ee; return b;
u32 uid = h << 16;
while (e && (e->pxlen != len || !ipa_equal(*a, e->prefix))) if (f->fib_slab)
e = e->next; b = sl_alloc(f->fib_slab);
if (e) else
return e; b = mb_alloc(f->fib_pool, f->node_size + a->length);
#ifdef DEBUGGING
if (len < 0 || len > BITS_PER_IP_ADDRESS || !ip_is_prefix(*a,len))
bug("fib_get() called for invalid address");
#endif
while ((g = *ee) && g->uid < uid) struct fib_node *e = (void *) (b + f->node_offset);
ee = &g->next;
while ((g = *ee) && g->uid == uid)
{
ee = &g->next;
uid++;
}
if ((uid >> 16) != 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->pxlen = len;
e->next = *ee;
e->uid = uid;
*ee = e;
e->readers = NULL; e->readers = NULL;
f->init(e); e->flags = 0;
e->uid = 0;
fib_insert(f, a, e);
memset(b, 0, f->node_offset);
if (f->init)
f->init(b);
if (f->entries++ > f->entries_max) if (f->entries++ > f->entries_max)
fib_rehash(f, HASH_HI_STEP); 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 * network, that is a node which a CIDR router would use for routing
* that network. * that network.
*/ */
/*
void * void *
fib_route(struct fib *f, ip_addr a, int len) 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; return NULL;
} }
*/
static inline void static inline void
fib_merge_readers(struct fib_iterator *i, struct fib_node *to) 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 void
fib_delete(struct fib *f, void *E) fib_delete(struct fib *f, void *E)
{ {
struct fib_node *e = E; struct fib_node *e = fib_user_to_node(f, E);
uint h = fib_hash(f, &e->prefix); uint h = fib_hash(f, e->addr);
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, n->addr);
return n; return n;
} }
@ -498,6 +539,28 @@ fib_check(struct fib *f)
bug("fib_check: invalid entry count (%d != %d)", ec, f->entries); 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 #endif
#ifdef TEST #ifdef TEST
@ -517,7 +580,7 @@ void dump(char *m)
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 %08x %p %N", i, ipa_hash(n->prefix), n, n->addr);
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

@ -69,6 +69,7 @@ make_tmp_attrs(struct rte *rt, struct linpool *pool)
} }
/* Like fib_route(), but skips empty net entries */ /* Like fib_route(), but skips empty net entries */
/*
static net * static net *
net_route(rtable *tab, ip_addr a, int len) net_route(rtable *tab, ip_addr a, int len)
{ {
@ -85,15 +86,7 @@ net_route(rtable *tab, ip_addr a, int len)
} }
return NULL; 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 * 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]; 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 %N %s", p->name, dir, msg, e->net->n.addr, via);
} }
static inline void static inline void
@ -788,20 +781,21 @@ 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)) // (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 %I/%d received via %s", {
n->n.prefix, n->n.pxlen, e->sender->proto->name); log(L_WARN "Ignoring bogus prefix %N received via %s",
return 0; 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)) 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 %N received via %s",
n->n.prefix, n->n.pxlen, e->sender->proto->name); n->n.addr, e->sender->proto->name);
return 0; return 0;
} }
return 1; return 1;
} }
@ -870,8 +864,8 @@ rte_recalculate(struct announce_hook *ah, net *net, rte *new, struct rte_src *sr
{ {
if (new) if (new)
{ {
log_rl(&rl_pipe, L_ERR "Pipe collision detected when sending %I/%d to table %s", log_rl(&rl_pipe, L_ERR "Pipe collision detected when sending %N to table %s",
net->n.prefix, net->n.pxlen, table->name); net->n.addr, table->name);
rte_free_quick(new); rte_free_quick(new);
} }
return; 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 */ /* Check rtable for best route to given net whether it would be exported do p */
int 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; rte *rt = n ? n->routes : NULL;
if (!rte_is_valid(rt)) if (!rte_is_valid(rt))
@ -1376,7 +1370,7 @@ void
rte_dump(rte *e) rte_dump(rte *e)
{ {
net *n = e->net; 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); debug("KF=%02x PF=%02x pref=%d lm=%d ", n->n.flags, e->pflags, e->pref, now-e->lastmod);
rta_dump(e->attrs); rta_dump(e->attrs);
if (e->attrs->src->proto->proto->dump_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) rt_setup(pool *p, rtable *t, char *name, struct rtable_config *cf)
{ {
bzero(t, sizeof(*t)); bzero(t, sizeof(*t));
fib_init(&t->fib, p, sizeof(net), 0, rte_init);
t->name = name; t->name = name;
t->config = cf; 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); init_list(&t->hooks);
if (cf) if (cf)
{ {
@ -1660,7 +1655,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, NET_IP4);
} }
@ -1817,7 +1812,7 @@ rt_next_hop_update(rtable *tab)
struct rtable_config * 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 */ /* Hack that allows to 'redefine' the master table */
if ((s->class == SYM_TABLE) && (s->def == new_config->master_rtc)) 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); 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;
@ -2196,8 +2192,9 @@ 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)) // XXXX
rt_schedule_hcu(tab); // if (trie_match_prefix(hc->trie, net->n.prefix, net->n.pxlen))
// rt_schedule_hcu(tab);
} }
static int static int
@ -2253,18 +2250,20 @@ rt_update_hostentry(rtable *tab, struct hostentry *he)
he->dest = RTD_UNREACHABLE; he->dest = RTD_UNREACHABLE;
he->igp_metric = 0; 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) if (n)
{ {
rte *e = n->routes; rte *e = n->routes;
rta *a = e->attrs; rta *a = e->attrs;
pxlen = n->n.pxlen; pxlen = n->n.addr->pxlen;
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 %N",
he->addr, n->n.prefix, pxlen); he->addr, n->n.addr);
goto done; goto done;
} }
@ -2425,7 +2424,7 @@ rt_show_net(struct cli *c, net *n, struct rt_show_data *d)
int first = 1; int first = 1;
int pass = 0; int pass = 0;
bsprintf(ia, "%I/%d", n->n.prefix, n->n.pxlen); bsprintf(ia, "%N", n->n.addr);
if (d->export_mode) if (d->export_mode)
{ {
@ -2589,10 +2588,13 @@ rt_show(struct rt_show_data *d)
} }
else else
{ {
/* XXXX
if (d->show_for) if (d->show_for)
n = net_route(d->table, d->prefix, d->pxlen); n = net_route(d->table, d->prefix, d->pxlen);
else else
n = net_find(d->table, d->prefix, d->pxlen); n = net_find(d->table, d->prefix, d->pxlen);
*/
n = NULL;
if (n) if (n)
rt_show_net(this_cli, n, d); rt_show_net(this_cli, n, d);
@ -2613,26 +2615,24 @@ rt_show(struct rt_show_data *d)
* net_find - find a network entry * net_find - find a network entry
* @tab: a routing table * @tab: a routing table
* @addr: address of the network * @addr: address of the network
* @len: length of the network prefix
* *
* net_find() looks up the given network in routing table @tab and * 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 * returns a pointer to its &net entry or %NULL if no such network
* exists. * exists.
*/ */
static inline net *net_find(rtable *tab, ip_addr addr, unsigned len) static inline net *net_find(rtable *tab, net_addr *addr)
{ DUMMY; } { DUMMY; }
/** /**
* net_get - obtain a network entry * net_get - obtain a network entry
* @tab: a routing table * @tab: a routing table
* @addr: address of the network * @addr: address of the network
* @len: length of the network prefix
* *
* net_get() looks up the given network in routing table @tab and * 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 * returns a pointer to its &net entry. If no such entry exists, it's
* created. * created.
*/ */
static inline net *net_get(rtable *tab, ip_addr addr, unsigned len) static inline net *net_get(rtable *tab, net_addr *addr)
{ DUMMY; } { DUMMY; }
/** /**

View file

@ -132,7 +132,6 @@ CF_KEYWORDS(WAIT, DELAY, LSADB, ECMP, LIMIT, WEIGHT, NSSA, TRANSLATOR, STABILITY
CF_KEYWORDS(GLOBAL, LSID, ROUTER, SELF, INSTANCE, REAL, NETMASK, TX, PRIORITY, LENGTH) CF_KEYWORDS(GLOBAL, LSID, ROUTER, SELF, INSTANCE, REAL, NETMASK, TX, PRIORITY, LENGTH)
CF_KEYWORDS(SECONDARY, MERGE, LSA, SUPPRESSION) CF_KEYWORDS(SECONDARY, MERGE, LSA, SUPPRESSION)
%type <t> opttext
%type <ld> lsadb_args %type <ld> lsadb_args
%type <i> nbma_eligible %type <i> nbma_eligible
@ -401,11 +400,6 @@ ospf_iface:
ospf_iface_start ospf_iface_patt_list ospf_iface_opt_list { ospf_iface_finish(); } ospf_iface_start ospf_iface_patt_list ospf_iface_opt_list { ospf_iface_finish(); }
; ;
opttext:
TEXT
| /* empty */ { $$ = NULL; }
;
CF_ADDTO(dynamic_attr, OSPF_METRIC1 { $$ = f_new_dynamic_attr(EAF_TYPE_INT | EAF_TEMP, T_INT, EA_OSPF_METRIC1); }) CF_ADDTO(dynamic_attr, OSPF_METRIC1 { $$ = f_new_dynamic_attr(EAF_TYPE_INT | EAF_TEMP, T_INT, EA_OSPF_METRIC1); })
CF_ADDTO(dynamic_attr, OSPF_METRIC2 { $$ = f_new_dynamic_attr(EAF_TYPE_INT | EAF_TEMP, T_INT, EA_OSPF_METRIC2); }) CF_ADDTO(dynamic_attr, OSPF_METRIC2 { $$ = f_new_dynamic_attr(EAF_TYPE_INT | EAF_TEMP, T_INT, EA_OSPF_METRIC2); })
CF_ADDTO(dynamic_attr, OSPF_TAG { $$ = f_new_dynamic_attr(EAF_TYPE_INT | EAF_TEMP, T_INT, EA_OSPF_TAG); }) CF_ADDTO(dynamic_attr, OSPF_TAG { $$ = f_new_dynamic_attr(EAF_TYPE_INT | EAF_TEMP, T_INT, EA_OSPF_TAG); })

View file

@ -105,7 +105,7 @@ ospf_send_hello(struct ospf_iface *ifa, int kind, struct ospf_neighbor *dirn)
} }
i = 0; i = 0;
max = (ospf_pkt_maxsize(ifa) - length) / sizeof(u32); max = (ospf_pkt_maxsize(p, ifa) - length) / sizeof(u32);
/* Fill all neighbors */ /* Fill all neighbors */
if (kind != OHS_SHUTDOWN) if (kind != OHS_SHUTDOWN)

View file

@ -67,7 +67,9 @@ ifa_flood_queue_size(struct ospf_iface *ifa)
int int
ospf_iface_assure_bufsize(struct ospf_iface *ifa, uint plen) ospf_iface_assure_bufsize(struct ospf_iface *ifa, uint plen)
{ {
plen += SIZE_OF_IP_HEADER; struct ospf_proto *p = ifa->oa->po;
plen += ospf_is_v2(p) ? IP4_HEADER_LENGTH : IP6_HEADER_LENGTH;
/* This is relevant just for OSPFv2 */ /* This is relevant just for OSPFv2 */
if (ifa->autype == OSPF_AUTH_CRYPT) if (ifa->autype == OSPF_AUTH_CRYPT)

View file

@ -280,21 +280,19 @@ lsa_walk_rt(struct ospf_lsa_rt_walk *rt)
void void
lsa_parse_sum_net(struct top_hash_entry *en, int ospf2, ip_addr *ip, int *pxlen, u8 *pxopts, u32 *metric) lsa_parse_sum_net(struct top_hash_entry *en, int ospf2, net_addr *net, u8 *pxopts, u32 *metric)
{ {
if (ospf2) if (ospf2)
{ {
struct ospf_lsa_sum2 *ls = en->lsa_body; struct ospf_lsa_sum2 *ls = en->lsa_body;
*ip = ipa_from_u32(en->lsa.id & ls->netmask); net_fill_ip4(net, ip4_from_u32(en->lsa.id & ls->netmask), u32_masklen(ls->netmask));
*pxlen = u32_masklen(ls->netmask);
*pxopts = 0; *pxopts = 0;
*metric = ls->metric & LSA_METRIC_MASK; *metric = ls->metric & LSA_METRIC_MASK;
} }
else else
{ {
struct ospf_lsa_sum3_net *ls = en->lsa_body; struct ospf_lsa_sum3_net *ls = en->lsa_body;
u16 rest; ospf_get_ipv6_prefix(ls->prefix, net, pxopts, NULL);
lsa_get_ipv6_prefix(ls->prefix, ip, pxlen, pxopts, &rest);
*metric = ls->metric & LSA_METRIC_MASK; *metric = ls->metric & LSA_METRIC_MASK;
} }
} }
@ -324,8 +322,9 @@ lsa_parse_ext(struct top_hash_entry *en, int ospf2, struct ospf_lsa_ext_local *r
if (ospf2) if (ospf2)
{ {
struct ospf_lsa_ext2 *ext = en->lsa_body; struct ospf_lsa_ext2 *ext = en->lsa_body;
rt->ip = ipa_from_u32(en->lsa.id & ext->netmask); net_fill_ip4(&rt->net,
rt->pxlen = u32_masklen(ext->netmask); ip4_from_u32(en->lsa.id & ext->netmask),
u32_masklen(ext->netmask));
rt->pxopts = 0; rt->pxopts = 0;
rt->metric = ext->metric & LSA_METRIC_MASK; rt->metric = ext->metric & LSA_METRIC_MASK;
rt->ebit = ext->metric & LSA_EXT2_EBIT; rt->ebit = ext->metric & LSA_EXT2_EBIT;
@ -339,14 +338,13 @@ lsa_parse_ext(struct top_hash_entry *en, int ospf2, struct ospf_lsa_ext_local *r
else else
{ {
struct ospf_lsa_ext3 *ext = en->lsa_body; struct ospf_lsa_ext3 *ext = en->lsa_body;
u16 rest; u32 *buf = ospf_get_ipv6_prefix(ext->rest, &rt->net, &rt->pxopts, NULL);
u32 *buf = lsa_get_ipv6_prefix(ext->rest, &rt->ip, &rt->pxlen, &rt->pxopts, &rest);
rt->metric = ext->metric & LSA_METRIC_MASK; rt->metric = ext->metric & LSA_METRIC_MASK;
rt->ebit = ext->metric & LSA_EXT3_EBIT; rt->ebit = ext->metric & LSA_EXT3_EBIT;
rt->fbit = ext->metric & LSA_EXT3_FBIT; rt->fbit = ext->metric & LSA_EXT3_FBIT;
if (rt->fbit) if (rt->fbit)
buf = lsa_get_ipv6_addr(buf, &rt->fwaddr); buf = ospf_get_ipv6_addr(buf, &rt->fwaddr);
else else
rt->fwaddr = IPA_NONE; rt->fwaddr = IPA_NONE;
@ -452,7 +450,7 @@ lsa_validate_sum3_net(struct ospf_lsa_header *lsa, struct ospf_lsa_sum3_net *bod
return 0; return 0;
u8 pxl = pxlen(body->prefix); u8 pxl = pxlen(body->prefix);
if (pxl > MAX_PREFIX_LENGTH) if (pxl > IP6_MAX_PREFIX_LENGTH)
return 0; return 0;
if (lsa->length != (HDRLEN + sizeof(struct ospf_lsa_sum3_net) + if (lsa->length != (HDRLEN + sizeof(struct ospf_lsa_sum3_net) +
@ -491,7 +489,7 @@ lsa_validate_ext3(struct ospf_lsa_header *lsa, struct ospf_lsa_ext3 *body)
return 0; return 0;
u8 pxl = pxlen(body->rest); u8 pxl = pxlen(body->rest);
if (pxl > MAX_PREFIX_LENGTH) if (pxl > IP6_MAX_PREFIX_LENGTH)
return 0; return 0;
int len = IPV6_PREFIX_SPACE(pxl); int len = IPV6_PREFIX_SPACE(pxl);
@ -520,7 +518,7 @@ lsa_validate_pxlist(struct ospf_lsa_header *lsa, u32 pxcount, uint offset, u8 *p
return 0; return 0;
u8 pxl = pxlen((u32 *) (pbuf + offset)); u8 pxl = pxlen((u32 *) (pbuf + offset));
if (pxl > MAX_PREFIX_LENGTH) if (pxl > IP6_MAX_PREFIX_LENGTH)
return 0; return 0;
offset += IPV6_PREFIX_SPACE(pxl); offset += IPV6_PREFIX_SPACE(pxl);

View file

@ -55,7 +55,7 @@ u16 lsa_verify_checksum(const void *lsa_n, int lsa_len);
int lsa_comp(struct ospf_lsa_header *l1, struct ospf_lsa_header *l2); int lsa_comp(struct ospf_lsa_header *l1, struct ospf_lsa_header *l2);
void lsa_walk_rt_init(struct ospf_proto *po, struct top_hash_entry *act, struct ospf_lsa_rt_walk *rt); void lsa_walk_rt_init(struct ospf_proto *po, struct top_hash_entry *act, struct ospf_lsa_rt_walk *rt);
int lsa_walk_rt(struct ospf_lsa_rt_walk *rt); int lsa_walk_rt(struct ospf_lsa_rt_walk *rt);
void lsa_parse_sum_net(struct top_hash_entry *en, int ospf2, ip_addr *ip, int *pxlen, u8 *pxopts, u32 *metric); void lsa_parse_sum_net(struct top_hash_entry *en, int ospf2, net_addr *net, u8 *pxopts, u32 *metric);
void lsa_parse_sum_rt(struct top_hash_entry *en, int ospf2, u32 *drid, u32 *metric, u32 *options); void lsa_parse_sum_rt(struct top_hash_entry *en, int ospf2, u32 *drid, u32 *metric, u32 *options);
void lsa_parse_ext(struct top_hash_entry *en, int ospf2, struct ospf_lsa_ext_local *rt); void lsa_parse_ext(struct top_hash_entry *en, int ospf2, struct ospf_lsa_ext_local *rt);
int lsa_validate(struct ospf_lsa_header *lsa, u32 lsa_type, int ospf2, void *body); int lsa_validate(struct ospf_lsa_header *lsa, u32 lsa_type, int ospf2, void *body);

View file

@ -330,7 +330,7 @@ ospf_prepare_lsupd(struct ospf_proto *p, struct ospf_iface *ifa,
pkt = ospf_tx_buffer(ifa); pkt = ospf_tx_buffer(ifa);
hlen = ospf_lsupd_hdrlen(p); hlen = ospf_lsupd_hdrlen(p);
maxsize = ospf_pkt_maxsize(ifa); maxsize = ospf_pkt_maxsize(p, ifa);
ospf_pkt_fill_hdr(ifa, pkt, LSUPD_P); ospf_pkt_fill_hdr(ifa, pkt, LSUPD_P);
pos = hlen; pos = hlen;

View file

@ -107,13 +107,6 @@ static int ospf_rte_better(struct rte *new, struct rte *old);
static int ospf_rte_same(struct rte *new, struct rte *old); static int ospf_rte_same(struct rte *new, struct rte *old);
static void ospf_disp(timer *timer); static void ospf_disp(timer *timer);
static void
ospf_area_initfib(struct fib_node *fn)
{
struct area_net *an = (struct area_net *) fn;
an->hidden = 0;
an->active = 0;
}
static void static void
add_area_nets(struct ospf_area *oa, struct ospf_area_config *ac) add_area_nets(struct ospf_area *oa, struct ospf_area_config *ac)
@ -121,19 +114,26 @@ add_area_nets(struct ospf_area *oa, struct ospf_area_config *ac)
struct ospf_proto *p = oa->po; struct ospf_proto *p = oa->po;
struct area_net_config *anc; struct area_net_config *anc;
struct area_net *an; struct area_net *an;
net_addr net;
fib_init(&oa->net_fib, p->p.pool, sizeof(struct area_net), 0, ospf_area_initfib); fib_init(&oa->net_fib, p->p.pool, ospf_is_v2(p) ? NET_IP4 : NET_IP6,
fib_init(&oa->enet_fib, p->p.pool, sizeof(struct area_net), 0, ospf_area_initfib); sizeof(struct area_net), OFFSETOF(struct area_net, fn), 0, NULL);
fib_init(&oa->enet_fib, p->p.pool, ospf_is_v2(p) ? NET_IP4 : NET_IP6,
sizeof(struct area_net), OFFSETOF(struct area_net, fn), 0, NULL);
WALK_LIST(anc, ac->net_list) WALK_LIST(anc, ac->net_list)
{ {
an = (struct area_net *) fib_get(&oa->net_fib, &anc->px.addr, anc->px.len); /* XXXX we should dispatch by ospf version, not by px.addr */
net_fill_ipa(&net, anc->px.addr, anc->px.len);
an = fib_get(&oa->net_fib, &net);
an->hidden = anc->hidden; an->hidden = anc->hidden;
} }
WALK_LIST(anc, ac->enet_list) WALK_LIST(anc, ac->enet_list)
{ {
an = (struct area_net *) fib_get(&oa->enet_fib, &anc->px.addr, anc->px.len); /* XXXX ditto */
net_fill_ipa(&net, anc->px.addr, anc->px.len);
an = fib_get(&oa->enet_fib, &net);
an->hidden = anc->hidden; an->hidden = anc->hidden;
an->tag = anc->tag; an->tag = anc->tag;
} }
@ -154,7 +154,7 @@ ospf_area_add(struct ospf_proto *p, struct ospf_area_config *ac)
oa->areaid = ac->areaid; oa->areaid = ac->areaid;
oa->rt = NULL; oa->rt = NULL;
oa->po = p; oa->po = p;
fib_init(&oa->rtr, p->p.pool, sizeof(ort), 0, ospf_rt_initort); fib_init(&oa->rtr, p->p.pool, NET_IP4, sizeof(ort), OFFSETOF(ort, fn), 0, NULL);
add_area_nets(oa, ac); add_area_nets(oa, ac);
if (oa->areaid == 0) if (oa->areaid == 0)
@ -243,7 +243,8 @@ ospf_start(struct proto *P)
p->nhpool = lp_new(P->pool, 12*sizeof(struct mpnh)); p->nhpool = lp_new(P->pool, 12*sizeof(struct mpnh));
init_list(&(p->iface_list)); init_list(&(p->iface_list));
init_list(&(p->area_list)); init_list(&(p->area_list));
fib_init(&p->rtf, P->pool, sizeof(ort), 0, ospf_rt_initort); fib_init(&p->rtf, P->pool, p->ospf2 ? NET_IP4 : NET_IP6,
sizeof(ort), OFFSETOF(ort, fn), 0, NULL);
p->areano = 0; p->areano = 0;
p->gr = ospf_top_new(p, P->pool); p->gr = ospf_top_new(p, P->pool);
s_init_list(&(p->lsal)); s_init_list(&(p->lsal));
@ -803,7 +804,7 @@ ospf_sh(struct proto *P)
cli_msg(-1014, "\t\tArea networks:"); cli_msg(-1014, "\t\tArea networks:");
firstfib = 0; firstfib = 0;
} }
cli_msg(-1014, "\t\t\t%1I/%u\t%s\t%s", anet->fn.prefix, anet->fn.pxlen, cli_msg(-1014, "\t\t\t%1N\t%s\t%s", anet->fn.addr,
anet->hidden ? "Hidden" : "Advertise", anet->active ? "Active" : ""); anet->hidden ? "Hidden" : "Advertise", anet->active ? "Active" : "");
} }
FIB_WALK_END; FIB_WALK_END;
@ -817,7 +818,7 @@ ospf_sh(struct proto *P)
cli_msg(-1014, "\t\tArea external networks:"); cli_msg(-1014, "\t\tArea external networks:");
firstfib = 0; firstfib = 0;
} }
cli_msg(-1014, "\t\t\t%1I/%u\t%s\t%s", anet->fn.prefix, anet->fn.pxlen, cli_msg(-1014, "\t\t\t%1N\t%s\t%s", anet->fn.addr,
anet->hidden ? "Hidden" : "Advertise", anet->active ? "Active" : ""); anet->hidden ? "Hidden" : "Advertise", anet->active ? "Active" : "");
} }
FIB_WALK_END; FIB_WALK_END;
@ -1074,13 +1075,12 @@ show_lsa_network(struct top_hash_entry *he, int ospf2)
static inline void static inline void
show_lsa_sum_net(struct top_hash_entry *he, int ospf2) show_lsa_sum_net(struct top_hash_entry *he, int ospf2)
{ {
ip_addr ip; net_addr net;
int pxlen;
u8 pxopts; u8 pxopts;
u32 metric; u32 metric;
lsa_parse_sum_net(he, ospf2, &ip, &pxlen, &pxopts, &metric); lsa_parse_sum_net(he, ospf2, &net, &pxopts, &metric);
cli_msg(-1016, "\t\txnetwork %I/%d metric %u", ip, pxlen, metric); cli_msg(-1016, "\t\txnetwork %N metric %u", &net, metric);
} }
static inline void static inline void
@ -1113,19 +1113,15 @@ show_lsa_external(struct top_hash_entry *he, int ospf2)
if (rt.tag) if (rt.tag)
bsprintf(str_tag, " tag %08x", rt.tag); bsprintf(str_tag, " tag %08x", rt.tag);
cli_msg(-1016, "\t\t%s %I/%d metric%s %u%s%s", cli_msg(-1016, "\t\t%s %N metric%s %u%s%s",
(he->lsa_type == LSA_T_NSSA) ? "nssa-ext" : "external", (he->lsa_type == LSA_T_NSSA) ? "nssa-ext" : "external",
rt.ip, rt.pxlen, rt.ebit ? "2" : "", rt.metric, str_via, str_tag); &rt.net, rt.ebit ? "2" : "", rt.metric, str_via, str_tag);
} }
static inline void static inline void
show_lsa_prefix(struct top_hash_entry *he, struct top_hash_entry *cnode) show_lsa_prefix(struct top_hash_entry *he, struct top_hash_entry *cnode)
{ {
struct ospf_lsa_prefix *px = he->lsa_body; struct ospf_lsa_prefix *px = he->lsa_body;
ip_addr pxa;
int pxlen;
u8 pxopts;
u16 metric;
u32 *buf; u32 *buf;
int i; int i;
@ -1141,14 +1137,18 @@ show_lsa_prefix(struct top_hash_entry *he, struct top_hash_entry *cnode)
buf = px->rest; buf = px->rest;
for (i = 0; i < px->pxcount; i++) for (i = 0; i < px->pxcount; i++)
{ {
buf = lsa_get_ipv6_prefix(buf, &pxa, &pxlen, &pxopts, &metric); net_addr net;
u8 pxopts;
u16 metric;
if (px->ref_type == LSA_T_RT) buf = ospf_get_ipv6_prefix(buf, &net, &pxopts, &metric);
cli_msg(-1016, "\t\tstubnet %I/%d metric %u", pxa, pxlen, metric);
else if (px->ref_type == LSA_T_RT)
cli_msg(-1016, "\t\taddress %I/%d", pxa, pxlen); cli_msg(-1016, "\t\tstubnet %N metric %u", &net, metric);
} else
cli_msg(-1016, "\t\taddress %N", &net);
}
} }
void void

View file

@ -132,11 +132,11 @@ struct area_net_config
struct area_net struct area_net
{ {
struct fib_node fn;
u32 metric; /* With possible LSA_EXT3_EBIT for NSSA area nets */ u32 metric; /* With possible LSA_EXT3_EBIT for NSSA area nets */
u32 tag; u32 tag;
u8 hidden; u8 hidden;
u8 active; u8 active;
struct fib_node fn;
}; };
struct ospf_stubnet_config struct ospf_stubnet_config
@ -681,8 +681,8 @@ struct ospf_lsa_ext3
struct ospf_lsa_ext_local struct ospf_lsa_ext_local
{ {
ip_addr ip, fwaddr; net_addr net;
int pxlen; ip_addr fwaddr;
u32 metric, ebit, fbit, tag, propagate; u32 metric, ebit, fbit, tag, propagate;
u8 pxopts; u8 pxopts;
}; };
@ -720,8 +720,8 @@ lsa_net_count(struct ospf_lsa_header *lsa)
/* In ospf_area->rtr we store paths to routers, but we use RID (and not IP address) /* In ospf_area->rtr we store paths to routers, but we use RID (and not IP address)
as index, so we need to encapsulate RID to IP address */ as index, so we need to encapsulate RID to IP address */
#define ipa_from_rid(x) ipa_from_u32(x) #define net_from_rid(x) NET_ADDR_IP4(ip4_from_u32(x), IP4_MAX_PREFIX_LENGTH)
#define ipa_to_rid(x) ipa_to_u32(x) #define rid_from_net(x) ip4_to_u32(((net_addr_ip4 *) x)->prefix)
#define IPV6_PREFIX_SPACE(x) ((((x) + 63) / 32) * 4) #define IPV6_PREFIX_SPACE(x) ((((x) + 63) / 32) * 4)
#define IPV6_PREFIX_WORDS(x) (((x) + 63) / 32) #define IPV6_PREFIX_WORDS(x) (((x) + 63) / 32)
@ -730,63 +730,63 @@ lsa_net_count(struct ospf_lsa_header *lsa)
also should be named as ospf3_* instead of *_ipv6_* */ also should be named as ospf3_* instead of *_ipv6_* */
static inline u32 * static inline u32 *
lsa_get_ipv6_prefix(u32 *buf, ip_addr *addr, int *pxlen, u8 *pxopts, u16 *rest) ospf_get_ipv6_prefix(u32 *buf, net_addr *N, u8 *pxopts, u16 *rest)
{ {
u8 pxl = (*buf >> 24); net_addr_ip6 *net = (void *) N;
*pxopts = (*buf >> 16); u8 pxlen = (*buf >> 24);
*rest = *buf; *pxopts = (*buf >> 16) & 0xff;
*pxlen = pxl; if (rest) *rest = *buf & 0xffff;
buf++; buf++;
*addr = IPA_NONE; *net = NET_ADDR_IP6(IP6_NONE, pxlen);
#ifdef IPV6 if (pxlen > 0)
if (pxl > 0) _I0(net->prefix) = *buf++;
_I0(*addr) = *buf++; if (pxlen > 32)
if (pxl > 32) _I1(net->prefix) = *buf++;
_I1(*addr) = *buf++; if (pxlen > 64)
if (pxl > 64) _I2(net->prefix) = *buf++;
_I2(*addr) = *buf++; if (pxlen > 96)
if (pxl > 96) _I3(net->prefix) = *buf++;
_I3(*addr) = *buf++;
/* Clean up remaining bits */ /* Clean up remaining bits */
if (pxl < 128) if (pxlen < 128)
addr->addr[pxl / 32] &= u32_mkmask(pxl % 32); net->prefix.addr[pxlen / 32] &= u32_mkmask(pxlen % 32);
#endif
return buf; return buf;
} }
static inline u32 * static inline u32 *
lsa_get_ipv6_addr(u32 *buf, ip_addr *addr) ospf_get_ipv6_addr(u32 *buf, ip_addr *addr)
{ {
*addr = *(ip_addr *) buf; *addr = ipa_from_ip6(*(ip6_addr *) buf);
return buf + 4; return buf + 4;
} }
static inline u32 * static inline u32 *
put_ipv6_prefix(u32 *buf, ip_addr addr, u8 pxlen, u8 pxopts, u16 lh) ospf_put_ipv6_prefix(u32 *buf, net_addr *N, u8 pxopts, u16 rest)
{ {
#ifdef IPV6 net_addr_ip6 *net = (void *) N;
*buf++ = ((pxlen << 24) | (pxopts << 16) | lh); u32 pxlen = net->pxlen;
*buf++ = ((pxlen << 24) | (pxopts << 16) | rest);
if (pxlen > 0) if (pxlen > 0)
*buf++ = _I0(addr); *buf++ = _I0(net->prefix);
if (pxlen > 32) if (pxlen > 32)
*buf++ = _I1(addr); *buf++ = _I1(net->prefix);
if (pxlen > 64) if (pxlen > 64)
*buf++ = _I2(addr); *buf++ = _I2(net->prefix);
if (pxlen > 96) if (pxlen > 96)
*buf++ = _I3(addr); *buf++ = _I3(net->prefix);
#endif
return buf; return buf;
} }
static inline u32 * static inline u32 *
put_ipv6_addr(u32 *buf, ip_addr addr) ospf_put_ipv6_addr(u32 *buf, ip_addr addr)
{ {
*(ip_addr *) buf = addr; *(ip6_addr *) buf = ipa_to_ip6(addr);
return buf + 4; return buf + 4;
} }
@ -896,7 +896,7 @@ void ospf_sh_neigh_info(struct ospf_neighbor *n);
/* packet.c */ /* packet.c */
void ospf_pkt_fill_hdr(struct ospf_iface *ifa, void *buf, u8 h_type); void ospf_pkt_fill_hdr(struct ospf_iface *ifa, void *buf, u8 h_type);
uint ospf_pkt_maxsize(struct ospf_iface *ifa); uint ospf_pkt_maxsize(struct ospf_proto *p, struct ospf_iface *ifa);
int ospf_rx_hook(sock * sk, int size); int ospf_rx_hook(sock * sk, int size);
// void ospf_tx_hook(sock * sk); // void ospf_tx_hook(sock * sk);
void ospf_err_hook(sock * sk, int err); void ospf_err_hook(sock * sk, int err);

View file

@ -22,7 +22,7 @@ ospf_pkt_fill_hdr(struct ospf_iface *ifa, void *buf, u8 h_type)
pkt->version = ospf_get_version(p); pkt->version = ospf_get_version(p);
pkt->type = h_type; pkt->type = h_type;
pkt->length = htons(ospf_pkt_maxsize(ifa)); pkt->length = htons(ospf_pkt_maxsize(p, ifa));
pkt->routerid = htonl(p->router_id); pkt->routerid = htonl(p->router_id);
pkt->areaid = htonl(ifa->oa->areaid); pkt->areaid = htonl(ifa->oa->areaid);
pkt->checksum = 0; pkt->checksum = 0;
@ -31,9 +31,9 @@ ospf_pkt_fill_hdr(struct ospf_iface *ifa, void *buf, u8 h_type)
} }
uint uint
ospf_pkt_maxsize(struct ospf_iface *ifa) ospf_pkt_maxsize(struct ospf_proto *p, struct ospf_iface *ifa)
{ {
uint headers = SIZE_OF_IP_HEADER; uint headers = ospf_is_v2(p) ? IP4_HEADER_LENGTH : IP6_HEADER_LENGTH;
/* Relevant just for OSPFv2 */ /* Relevant just for OSPFv2 */
if (ifa->autype == OSPF_AUTH_CRYPT) if (ifa->autype == OSPF_AUTH_CRYPT)

View file

@ -21,15 +21,6 @@ static inline void reset_ri(ort *ort)
bzero(&ort->n, sizeof(orta)); bzero(&ort->n, sizeof(orta));
} }
void
ospf_rt_initort(struct fib_node *fn)
{
ort *ri = (ort *) fn;
reset_ri(ri);
ri->old_rta = NULL;
ri->fn.flags = 0;
}
static inline int static inline int
nh_is_vlink(struct mpnh *nhs) nh_is_vlink(struct mpnh *nhs)
{ {
@ -334,9 +325,9 @@ ort_merge_ext(struct ospf_proto *p, ort *o, const orta *new)
static inline void static inline void
ri_install_net(struct ospf_proto *p, ip_addr prefix, int pxlen, const orta *new) ri_install_net(struct ospf_proto *p, net_addr *net, const orta *new)
{ {
ort *old = (ort *) fib_get(&p->rtf, &prefix, pxlen); ort *old = fib_get(&p->rtf, net);
int cmp = orta_compare(p, new, &old->n); int cmp = orta_compare(p, new, &old->n);
if (cmp > 0) if (cmp > 0)
@ -348,8 +339,8 @@ ri_install_net(struct ospf_proto *p, ip_addr prefix, int pxlen, const orta *new)
static inline void static inline void
ri_install_rt(struct ospf_area *oa, u32 rid, const orta *new) ri_install_rt(struct ospf_area *oa, u32 rid, const orta *new)
{ {
ip_addr addr = ipa_from_rid(rid); net_addr_ip4 nrid = net_from_rid(rid);
ort *old = (ort *) fib_get(&oa->rtr, &addr, MAX_PREFIX_LENGTH); ort *old = fib_get(&oa->rtr, (net_addr *) &nrid);
int cmp = orta_compare(oa->po, new, &old->n); int cmp = orta_compare(oa->po, new, &old->n);
if (cmp > 0) if (cmp > 0)
@ -359,17 +350,19 @@ ri_install_rt(struct ospf_area *oa, u32 rid, const orta *new)
} }
static inline void static inline void
ri_install_asbr(struct ospf_proto *p, ip_addr *addr, const orta *new) ri_install_asbr(struct ospf_proto *p, u32 rid, const orta *new)
{ {
ort *old = (ort *) fib_get(&p->backbone->rtr, addr, MAX_PREFIX_LENGTH); net_addr_ip4 nrid = net_from_rid(rid);
ort *old = fib_get(&p->backbone->rtr, (net_addr *) &nrid);
if (orta_compare_asbr(p, new, &old->n) > 0) if (orta_compare_asbr(p, new, &old->n) > 0)
ort_replace(old, new); ort_replace(old, new);
} }
static inline void static inline void
ri_install_ext(struct ospf_proto *p, ip_addr prefix, int pxlen, const orta *new) ri_install_ext(struct ospf_proto *p, net_addr *net, const orta *new)
{ {
ort *old = (ort *) fib_get(&p->rtf, &prefix, pxlen); ort *old = fib_get(&p->rtf, net);
int cmp = orta_compare_ext(p, new, &old->n); int cmp = orta_compare_ext(p, new, &old->n);
if (cmp > 0) if (cmp > 0)
@ -404,7 +397,7 @@ px_pos_to_ifa(struct ospf_area *oa, int pos)
static void static void
add_network(struct ospf_area *oa, ip_addr px, int pxlen, int metric, struct top_hash_entry *en, int pos) add_network(struct ospf_area *oa, net_addr *net, int metric, struct top_hash_entry *en, int pos)
{ {
struct ospf_proto *p = oa->po; struct ospf_proto *p = oa->po;
@ -419,7 +412,7 @@ add_network(struct ospf_area *oa, ip_addr px, int pxlen, int metric, struct top_
.nhs = en->nhs .nhs = en->nhs
}; };
if (pxlen < 0 || pxlen > MAX_PREFIX_LENGTH) if (net->pxlen > MAX_PREFIX_LENGTH)
{ {
log(L_WARN "%s: Invalid prefix in LSA (Type: %04x, Id: %R, Rt: %R)", log(L_WARN "%s: Invalid prefix in LSA (Type: %04x, Id: %R, Rt: %R)",
p->p.name, en->lsa_type, en->lsa.id, en->lsa.rt); p->p.name, en->lsa_type, en->lsa.id, en->lsa.rt);
@ -441,7 +434,7 @@ add_network(struct ospf_area *oa, ip_addr px, int pxlen, int metric, struct top_
nf.nhs = ifa ? new_nexthop(p, IPA_NONE, ifa->iface, ifa->ecmp_weight) : NULL; nf.nhs = ifa ? new_nexthop(p, IPA_NONE, ifa->iface, ifa->ecmp_weight) : NULL;
} }
ri_install_net(p, px, pxlen, &nf); ri_install_net(p, net, &nf);
} }
@ -452,8 +445,7 @@ spfa_process_rt(struct ospf_proto *p, struct ospf_area *oa, struct top_hash_entr
struct ospf_lsa_rt *rt = act->lsa_body; struct ospf_lsa_rt *rt = act->lsa_body;
struct ospf_lsa_rt_walk rtl; struct ospf_lsa_rt_walk rtl;
struct top_hash_entry *tmp; struct top_hash_entry *tmp;
ip_addr prefix; int i;
int pxlen, i;
if (rt->options & OPT_RT_V) if (rt->options & OPT_RT_V)
oa->trcap = 1; oa->trcap = 1;
@ -503,9 +495,10 @@ spfa_process_rt(struct ospf_proto *p, struct ospf_area *oa, struct top_hash_entr
* the same result by handing them here because add_network() * the same result by handing them here because add_network()
* will keep the best (not the first) found route. * will keep the best (not the first) found route.
*/ */
prefix = ipa_from_u32(rtl.id & rtl.data); net_addr_ip4 net =
pxlen = u32_masklen(rtl.data); NET_ADDR_IP4(ip4_from_u32(rtl.id & rtl.data), u32_masklen(rtl.data));
add_network(oa, prefix, pxlen, act->dist + rtl.metric, act, i);
add_network(oa, (net_addr *) &net, act->dist + rtl.metric, act, i);
break; break;
case LSART_NET: case LSART_NET:
@ -527,14 +520,14 @@ spfa_process_net(struct ospf_proto *p, struct ospf_area *oa, struct top_hash_ent
{ {
struct ospf_lsa_net *ln = act->lsa_body; struct ospf_lsa_net *ln = act->lsa_body;
struct top_hash_entry *tmp; struct top_hash_entry *tmp;
ip_addr prefix; int i, cnt;
int pxlen, i, cnt;
if (ospf_is_v2(p)) if (ospf_is_v2(p))
{ {
prefix = ipa_from_u32(act->lsa.id & ln->optx); net_addr_ip4 net =
pxlen = u32_masklen(ln->optx); NET_ADDR_IP4(ip4_from_u32(act->lsa.id & ln->optx), u32_masklen(ln->optx));
add_network(oa, prefix, pxlen, act->dist, act, -1);
add_network(oa, (net_addr *) &net, act->dist, act, -1);
} }
cnt = lsa_net_count(&act->lsa); cnt = lsa_net_count(&act->lsa);
@ -550,10 +543,6 @@ spfa_process_prefixes(struct ospf_proto *p, struct ospf_area *oa)
{ {
struct top_hash_entry *en, *src; struct top_hash_entry *en, *src;
struct ospf_lsa_prefix *px; struct ospf_lsa_prefix *px;
ip_addr pxa;
int pxlen;
u8 pxopts;
u16 metric;
u32 *buf; u32 *buf;
int i; int i;
@ -588,18 +577,22 @@ spfa_process_prefixes(struct ospf_proto *p, struct ospf_area *oa)
buf = px->rest; buf = px->rest;
for (i = 0; i < px->pxcount; i++) for (i = 0; i < px->pxcount; i++)
{ {
buf = lsa_get_ipv6_prefix(buf, &pxa, &pxlen, &pxopts, &metric); net_addr_ip6 net;
u8 pxopts;
u16 metric;
if (pxopts & OPT_PX_NU) buf = ospf_get_ipv6_prefix(buf, (net_addr *) &net, &pxopts, &metric);
continue;
/* Store the first global address to use it later as a vlink endpoint */ if (pxopts & OPT_PX_NU)
if ((pxopts & OPT_PX_LA) && ipa_zero(src->lb)) continue;
src->lb = pxa;
add_network(oa, pxa, pxlen, src->dist + metric, src, i); /* Store the first global address to use it later as a vlink endpoint */
} if ((pxopts & OPT_PX_LA) && ipa_zero(src->lb))
src->lb = ipa_from_ip6(net.prefix);
add_network(oa, (net_addr *) &net, src->dist + metric, src, i);
}
} }
} }
@ -742,13 +735,12 @@ ospf_rt_sum(struct ospf_area *oa)
{ {
struct ospf_proto *p = oa->po; struct ospf_proto *p = oa->po;
struct top_hash_entry *en; struct top_hash_entry *en;
ip_addr ip, abrip; net_addr net;
u32 dst_rid, metric, options; u32 dst_rid, metric, options;
ort *abr; ort *abr;
int pxlen = -1, type = -1; int type;
u8 pxopts; u8 pxopts;
OSPF_TRACE(D_EVENTS, "Starting routing table calculation for inter-area (area %R)", oa->areaid); OSPF_TRACE(D_EVENTS, "Starting routing table calculation for inter-area (area %R)", oa->areaid);
WALK_SLIST(en, p->lsal) WALK_SLIST(en, p->lsal)
@ -771,12 +763,12 @@ ospf_rt_sum(struct ospf_area *oa)
if (en->lsa_type == LSA_T_SUM_NET) if (en->lsa_type == LSA_T_SUM_NET)
{ {
lsa_parse_sum_net(en, ospf_is_v2(p), &ip, &pxlen, &pxopts, &metric); lsa_parse_sum_net(en, ospf_is_v2(p), &net, &pxopts, &metric);
if (pxopts & OPT_PX_NU) if (pxopts & OPT_PX_NU)
continue; continue;
if (pxlen < 0 || pxlen > MAX_PREFIX_LENGTH) if (net.pxlen > MAX_PREFIX_LENGTH)
{ {
log(L_WARN "%s: Invalid prefix in LSA (Type: %04x, Id: %R, Rt: %R)", log(L_WARN "%s: Invalid prefix in LSA (Type: %04x, Id: %R, Rt: %R)",
p->p.name, en->lsa_type, en->lsa.id, en->lsa.rt); p->p.name, en->lsa_type, en->lsa.id, en->lsa.rt);
@ -803,8 +795,8 @@ ospf_rt_sum(struct ospf_area *oa)
continue; continue;
/* 16.2. (4) */ /* 16.2. (4) */
abrip = ipa_from_rid(en->lsa.rt); net_addr_ip4 nrid = net_from_rid(en->lsa.rt);
abr = (ort *) fib_find(&oa->rtr, &abrip, MAX_PREFIX_LENGTH); abr = fib_find(&oa->rtr, (net_addr *) &nrid);
if (!abr || !abr->n.type) if (!abr || !abr->n.type)
continue; continue;
@ -828,7 +820,7 @@ ospf_rt_sum(struct ospf_area *oa)
}; };
if (type == ORT_NET) if (type == ORT_NET)
ri_install_net(p, ip, pxlen, &nf); ri_install_net(p, &net, &nf);
else else
ri_install_rt(oa, dst_rid, &nf); ri_install_rt(oa, dst_rid, &nf);
} }
@ -842,11 +834,7 @@ ospf_rt_sum_tr(struct ospf_area *oa)
struct ospf_area *bb = p->backbone; struct ospf_area *bb = p->backbone;
struct top_hash_entry *en; struct top_hash_entry *en;
ort *re, *abr; ort *re, *abr;
ip_addr ip, abrip; u32 metric;
u32 dst_rid, metric, options;
int pxlen;
u8 pxopts;
if (!bb) if (!bb)
return; return;
@ -869,26 +857,31 @@ ospf_rt_sum_tr(struct ospf_area *oa)
if (en->lsa_type == LSA_T_SUM_NET) if (en->lsa_type == LSA_T_SUM_NET)
{ {
lsa_parse_sum_net(en, ospf_is_v2(p), &ip, &pxlen, &pxopts, &metric); net_addr net;
u8 pxopts;
lsa_parse_sum_net(en, ospf_is_v2(p), &net, &pxopts, &metric);
if (pxopts & OPT_PX_NU) if (pxopts & OPT_PX_NU)
continue; continue;
if (pxlen < 0 || pxlen > MAX_PREFIX_LENGTH) if (net.pxlen > MAX_PREFIX_LENGTH)
{ {
log(L_WARN "%s: Invalid prefix in LSA (Type: %04x, Id: %R, Rt: %R)", log(L_WARN "%s: Invalid prefix in LSA (Type: %04x, Id: %R, Rt: %R)",
p->p.name, en->lsa_type, en->lsa.id, en->lsa.rt); p->p.name, en->lsa_type, en->lsa.id, en->lsa.rt);
continue; continue;
} }
re = fib_find(&p->rtf, &ip, pxlen); re = fib_find(&p->rtf, &net);
} }
else // en->lsa_type == LSA_T_SUM_RT else // en->lsa_type == LSA_T_SUM_RT
{ {
u32 dst_rid, options;
lsa_parse_sum_rt(en, ospf_is_v2(p), &dst_rid, &metric, &options); lsa_parse_sum_rt(en, ospf_is_v2(p), &dst_rid, &metric, &options);
ip = ipa_from_rid(dst_rid); net_addr_ip4 nrid = net_from_rid(dst_rid);
re = fib_find(&bb->rtr, &ip, MAX_PREFIX_LENGTH); re = fib_find(&bb->rtr, (net_addr *) &nrid);
} }
/* 16.3 (1b) */ /* 16.3 (1b) */
@ -906,8 +899,8 @@ ospf_rt_sum_tr(struct ospf_area *oa)
continue; continue;
/* 16.3. (4) */ /* 16.3. (4) */
abrip = ipa_from_rid(en->lsa.rt); net_addr_ip4 nrid = net_from_rid(en->lsa.rt);
abr = fib_find(&oa->rtr, &abrip, MAX_PREFIX_LENGTH); abr = fib_find(&oa->rtr, (net_addr *) &nrid);
if (!abr || !abr->n.type) if (!abr || !abr->n.type)
continue; continue;
@ -998,7 +991,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.addr);
/* Condensed area network found */ /* Condensed area network found */
if (anet) if (anet)
@ -1017,13 +1010,13 @@ check_sum_net_lsa(struct ospf_proto *p, ort *nf)
if (nf->area_net) if (nf->area_net)
{ {
/* 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.addr->pxlen == 0)
return; return;
/* Find that area network */ /* Find that area network */
WALK_LIST(anet_oa, p->area_list) WALK_LIST(anet_oa, p->area_list)
{ {
anet = (struct area_net *) fib_find(&anet_oa->net_fib, &nf->fn.prefix, nf->fn.pxlen); anet = fib_find(&anet_oa->net_fib, nf->fn.addr);
if (anet) if (anet)
break; break;
} }
@ -1042,10 +1035,12 @@ check_sum_net_lsa(struct ospf_proto *p, ort *nf)
static inline void static inline void
check_sum_rt_lsa(struct ospf_proto *p, ort *nf) check_sum_rt_lsa(struct ospf_proto *p, ort *nf)
{ {
u32 rid = rid_from_net(nf->fn.addr);
struct ospf_area *oa; struct ospf_area *oa;
WALK_LIST(oa, p->area_list) WALK_LIST(oa, p->area_list)
if (decide_sum_lsa(oa, nf, ORT_ROUTER)) if (decide_sum_lsa(oa, nf, ORT_ROUTER))
ospf_originate_sum_rt_lsa(p, oa, nf, nf->n.metric1, nf->n.options); ospf_originate_sum_rt_lsa(p, oa, rid, nf->n.metric1, nf->n.options);
} }
static inline int static inline int
@ -1058,7 +1053,7 @@ decide_nssa_lsa(struct ospf_proto *p, ort *nf, struct ospf_lsa_ext_local *rt)
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.addr))
return 0; return 0;
if (!en || (en->lsa_type != LSA_T_NSSA)) if (!en || (en->lsa_type != LSA_T_NSSA))
@ -1093,7 +1088,7 @@ check_nssa_lsa(struct ospf_proto *p, ort *nf)
/* Find that area network */ /* Find that area network */
WALK_LIST(oa, p->area_list) WALK_LIST(oa, p->area_list)
{ {
anet = (struct area_net *) fib_find(&oa->enet_fib, &nf->fn.prefix, nf->fn.pxlen); anet = fib_find(&oa->enet_fib, nf->fn.addr);
if (anet) if (anet)
break; break;
} }
@ -1164,6 +1159,7 @@ ospf_rt_abr1(struct ospf_proto *p)
{ {
struct area_net *anet; struct area_net *anet;
ort *nf, *default_nf; ort *nf, *default_nf;
net_addr default_net;
/* RFC 2328 G.3 - incomplete resolution of virtual next hops - routers */ /* RFC 2328 G.3 - incomplete resolution of virtual next hops - routers */
FIB_WALK(&p->backbone->rtr, nftmp) FIB_WALK(&p->backbone->rtr, nftmp)
@ -1189,7 +1185,7 @@ ospf_rt_abr1(struct ospf_proto *p)
/* 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.addr);
if (anet) if (anet)
{ {
if (!anet->active) if (!anet->active)
@ -1197,7 +1193,7 @@ ospf_rt_abr1(struct ospf_proto *p)
anet->active = 1; anet->active = 1;
/* 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(&p->rtf, &anet->fn.prefix, anet->fn.pxlen); ort *nfi = fib_get(&p->rtf, anet->fn.addr);
nfi->area_net = 1; nfi->area_net = 1;
/* 16.2. (3) */ /* 16.2. (3) */
@ -1212,8 +1208,13 @@ ospf_rt_abr1(struct ospf_proto *p)
} }
FIB_WALK_END; FIB_WALK_END;
ip_addr addr = IPA_NONE;
default_nf = (ort *) fib_get(&p->rtf, &addr, 0); if (ospf_is_v2(p))
net_fill_ip4(&default_net, IP4_NONE, 0);
else
net_fill_ip6(&default_net, IP6_NONE, 0);
default_nf = fib_get(&p->rtf, &default_net);
default_nf->area_net = 1; default_nf->area_net = 1;
struct ospf_area *oa; struct ospf_area *oa;
@ -1244,7 +1245,7 @@ ospf_rt_abr1(struct ospf_proto *p)
{ {
nf = (ort *) nftmp; nf = (ort *) nftmp;
if (nf->n.options & ORTA_ASBR) if (nf->n.options & ORTA_ASBR)
ri_install_asbr(p, &nf->fn.prefix, &nf->n); ri_install_asbr(p, rid_from_net(nf->fn.addr), &nf->n);
} }
FIB_WALK_END; FIB_WALK_END;
} }
@ -1300,7 +1301,7 @@ ospf_rt_abr2(struct ospf_proto *p)
if (!nf->n.type || !(nf->n.options & ORTA_ABR)) if (!nf->n.type || !(nf->n.options & ORTA_ABR))
continue; continue;
nf2 = fib_find(&bb->rtr, &nf->fn.prefix, MAX_PREFIX_LENGTH); nf2 = fib_find(&bb->rtr, nf->fn.addr);
if (!nf2 || !nf2->n.type || !(nf2->n.options & ORTA_ABR)) if (!nf2 || !nf2->n.type || !(nf2->n.options & ORTA_ABR))
continue; continue;
@ -1346,7 +1347,7 @@ ospf_rt_abr2(struct ospf_proto *p)
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.addr);
if (anet) if (anet)
{ {
@ -1355,7 +1356,7 @@ ospf_rt_abr2(struct ospf_proto *p)
anet->active = 1; anet->active = 1;
/* 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(&p->rtf, &anet->fn.prefix, anet->fn.pxlen); nf2 = fib_get(&p->rtf, anet->fn.addr);
nf2->area_net = 1; nf2->area_net = 1;
} }
@ -1383,22 +1384,57 @@ ospf_rt_abr2(struct ospf_proto *p)
/* Like fib_route(), but ignores dummy rt entries */ /* Like fib_route(), but ignores dummy rt entries */
static void * static void *
ospf_fib_route(struct fib *f, ip_addr a, int len) ospf_fib_route_ip4(struct fib *f, ip4_addr a, int len)
{ {
ip_addr a0; net_addr_ip4 net = NET_ADDR_IP4(a, len);
ort *nf; ort *nf;
while (len >= 0) loop:
nf = fib_find(f, (net_addr *) &net);
if (nf && nf->n.type)
return nf;
if (net.pxlen > 0)
{ {
a0 = ipa_and(a, ipa_mkmask(len)); net.pxlen--;
nf = fib_find(f, &a0, len); ip4_clrbit(&net.prefix, net.pxlen);
if (nf && nf->n.type) goto loop;
return nf;
len--;
} }
return NULL; return NULL;
} }
static void *
ospf_fib_route_ip6(struct fib *f, ip6_addr a, int len)
{
net_addr_ip6 net = NET_ADDR_IP6(a, len);
ort *nf;
loop:
nf = fib_find(f, (net_addr *) &net);
if (nf && nf->n.type)
return nf;
if (net.pxlen > 0)
{
net.pxlen--;
ip6_clrbit(&net.prefix, net.pxlen);
goto loop;
}
return NULL;
}
static void *
ospf_fib_route(struct fib *f, ip_addr a)
{
if (ospf_is_v2(p))
return ospf_fib_route_ip4(f, ipa_to_ip4(a), IP4_MAX_PREFIX_LENGTH);
else
return ospf_fib_route_ip6(f, ipa_to_ip6(a), IP6_MAX_PREFIX_LENGTH);
}
/* RFC 2328 16.4. calculating external routes */ /* RFC 2328 16.4. calculating external routes */
static void static void
ospf_ext_spf(struct ospf_proto *p) ospf_ext_spf(struct ospf_proto *p)
@ -1407,7 +1443,6 @@ ospf_ext_spf(struct ospf_proto *p)
struct ospf_lsa_ext_local rt; struct ospf_lsa_ext_local rt;
ort *nf1, *nf2; ort *nf1, *nf2;
orta nfa = {}; orta nfa = {};
ip_addr rtid;
u32 br_metric; u32 br_metric;
struct ospf_area *atmp; struct ospf_area *atmp;
@ -1437,7 +1472,7 @@ ospf_ext_spf(struct ospf_proto *p)
if (rt.pxopts & OPT_PX_NU) if (rt.pxopts & OPT_PX_NU)
continue; continue;
if (rt.pxlen < 0 || rt.pxlen > MAX_PREFIX_LENGTH) if (rt.net.pxlen > MAX_PREFIX_LENGTH)
{ {
log(L_WARN "%s: Invalid prefix in LSA (Type: %04x, Id: %R, Rt: %R)", log(L_WARN "%s: Invalid prefix in LSA (Type: %04x, Id: %R, Rt: %R)",
p->p.name, en->lsa_type, en->lsa.id, en->lsa.rt); p->p.name, en->lsa_type, en->lsa.id, en->lsa.rt);
@ -1457,8 +1492,8 @@ ospf_ext_spf(struct ospf_proto *p)
if (!atmp) if (!atmp)
continue; /* Should not happen */ continue; /* Should not happen */
rtid = ipa_from_rid(en->lsa.rt); net_addr_ip4 nrid = net_from_rid(en->lsa.rt);
nf1 = fib_find(&atmp->rtr, &rtid, MAX_PREFIX_LENGTH); nf1 = fib_find(&atmp->rtr, (net_addr *) &nrid);
if (!nf1 || !nf1->n.type) if (!nf1 || !nf1->n.type)
continue; /* No AS boundary router found */ continue; /* No AS boundary router found */
@ -1468,7 +1503,7 @@ ospf_ext_spf(struct ospf_proto *p)
/* 16.4. (3) NSSA - special rule for default routes */ /* 16.4. (3) NSSA - special rule for default routes */
/* ABR should use default only if P-bit is set and summaries are active */ /* ABR should use default only if P-bit is set and summaries are active */
if ((en->lsa_type == LSA_T_NSSA) && ipa_zero(rt.ip) && (rt.pxlen == 0) && if ((en->lsa_type == LSA_T_NSSA) && (rt.net.pxlen == 0) &&
(p->areano > 1) && !(rt.propagate && atmp->ac->summary)) (p->areano > 1) && !(rt.propagate && atmp->ac->summary))
continue; continue;
@ -1480,7 +1515,7 @@ ospf_ext_spf(struct ospf_proto *p)
} }
else else
{ {
nf2 = ospf_fib_route(&p->rtf, rt.fwaddr, MAX_PREFIX_LENGTH); nf2 = ospf_fib_route(&p->rtf, rt.fwaddr);
if (!nf2) if (!nf2)
continue; continue;
@ -1542,7 +1577,7 @@ ospf_ext_spf(struct ospf_proto *p)
nfa.oa = atmp; /* undefined in RFC 2328 */ nfa.oa = atmp; /* undefined in RFC 2328 */
nfa.en = en; /* store LSA for later (NSSA processing) */ nfa.en = en; /* store LSA for later (NSSA processing) */
ri_install_ext(p, rt.ip, rt.pxlen, &nfa); ri_install_ext(p, &rt.net, &nfa);
} }
} }
@ -1961,7 +1996,7 @@ again1:
if (reload || ort_changed(nf, &a0)) if (reload || ort_changed(nf, &a0))
{ {
net *ne = net_get(p->p.table, nf->fn.prefix, nf->fn.pxlen); net *ne = net_get(p->p.table, nf->fn.addr);
rta *a = rta_lookup(&a0); rta *a = rta_lookup(&a0);
rte *e = rte_get_temp(a); rte *e = rte_get_temp(a);
@ -1975,8 +2010,8 @@ again1:
e->net = ne; e->net = ne;
e->pref = p->p.preference; e->pref = p->p.preference;
DBG("Mod rte type %d - %I/%d via %I on iface %s, met %d\n", DBG("Mod rte type %d - %N via %I on iface %s, met %d\n",
a0.source, nf->fn.prefix, nf->fn.pxlen, a0.gw, a0.iface ? a0.iface->name : "(none)", nf->n.metric1); a0.source, nf->fn.addr, a0.gw, a0.iface ? a0.iface->name : "(none)", nf->n.metric1);
rte_update(&p->p, ne, e); rte_update(&p->p, ne, e);
} }
} }
@ -1986,7 +2021,7 @@ again1:
rta_free(nf->old_rta); rta_free(nf->old_rta);
nf->old_rta = NULL; nf->old_rta = NULL;
net *ne = net_get(p->p.table, nf->fn.prefix, nf->fn.pxlen); net *ne = net_get(p->p.table, nf->fn.addr);
rte_update(&p->p, ne, NULL); rte_update(&p->p, ne, NULL);
} }

View file

@ -78,12 +78,13 @@ typedef struct ort
* route was not in the last update, in that case other old_* values are not * route was not in the last update, in that case other old_* values are not
* valid. * valid.
*/ */
struct fib_node fn;
orta n; orta n;
u32 old_metric1, old_metric2, old_tag, old_rid; u32 old_metric1, old_metric2, old_tag, old_rid;
rta *old_rta; rta *old_rta;
u8 external_rte; u8 external_rte;
u8 area_net; u8 area_net;
struct fib_node fn;
} }
ort; ort;

View file

@ -283,8 +283,8 @@ ospf_originate_lsa(struct ospf_proto *p, struct ospf_new_lsa *lsa)
if (en->nf != lsa->nf) if (en->nf != lsa->nf)
{ {
log(L_ERR "%s: LSA ID collision for %I/%d", log(L_ERR "%s: LSA ID collision for %N",
p->p.name, lsa->nf->fn.prefix, lsa->nf->fn.pxlen); p->p.name, lsa->nf->fn.addr);
en = NULL; en = NULL;
goto drop; goto drop;
@ -520,8 +520,8 @@ ort_to_lsaid(struct ospf_proto *p, ort *nf)
/* /*
* In OSPFv2, We have to map IP prefixes to u32 in such manner that resulting * In OSPFv2, We have to map IP prefixes to u32 in such manner that resulting
* u32 interpreted as IP address is a member of given prefix. Therefore, /32 * u32 interpreted as IP address is a member of given prefix. Therefore, /32
* prefix have to be mapped on itself. All received prefixes have to be * prefix has to be mapped on itself. All received prefixes have to be mapped
* mapped on different u32s. * on different u32s.
* *
* We have an assumption that if there is nontrivial (non-/32) network prefix, * We have an assumption that if there is nontrivial (non-/32) network prefix,
* then there is not /32 prefix for the first and the last IP address of the * then there is not /32 prefix for the first and the last IP address of the
@ -551,8 +551,9 @@ ort_to_lsaid(struct ospf_proto *p, ort *nf)
if (ospf_is_v3(p)) if (ospf_is_v3(p))
return nf->fn.uid; return nf->fn.uid;
u32 id = ipa_to_u32(nf->fn.prefix); net_addr_ip4 *net = (void *) nf->fn.addr;
int pxlen = nf->fn.pxlen; u32 id = ip4_to_u32(net->prefix);
int pxlen = net->pxlen;
if ((pxlen == 0) || (pxlen == 32)) if ((pxlen == 0) || (pxlen == 32))
return id; return id;
@ -999,9 +1000,10 @@ prepare_sum3_net_lsa_body(struct ospf_proto *p, ort *nf, u32 metric)
{ {
struct ospf_lsa_sum3_net *sum; struct ospf_lsa_sum3_net *sum;
sum = lsab_allocz(p, sizeof(struct ospf_lsa_sum3_net) + IPV6_PREFIX_SPACE(nf->fn.pxlen)); sum = lsab_allocz(p, sizeof(struct ospf_lsa_sum3_net) +
IPV6_PREFIX_SPACE(nf->fn.addr->pxlen));
sum->metric = metric; sum->metric = metric;
put_ipv6_prefix(sum->prefix, nf->fn.prefix, nf->fn.pxlen, 0, 0); ospf_put_ipv6_prefix(sum->prefix, nf->fn.addr, 0, 0);
} }
static inline void static inline void
@ -1028,7 +1030,7 @@ ospf_originate_sum_net_lsa(struct ospf_proto *p, struct ospf_area *oa, ort *nf,
}; };
if (ospf_is_v2(p)) if (ospf_is_v2(p))
prepare_sum2_lsa_body(p, nf->fn.pxlen, metric); prepare_sum2_lsa_body(p, nf->fn.addr->pxlen, metric);
else else
prepare_sum3_net_lsa_body(p, nf, metric); prepare_sum3_net_lsa_body(p, nf, metric);
@ -1036,20 +1038,20 @@ ospf_originate_sum_net_lsa(struct ospf_proto *p, struct ospf_area *oa, ort *nf,
} }
void void
ospf_originate_sum_rt_lsa(struct ospf_proto *p, struct ospf_area *oa, ort *nf, int metric, u32 options) ospf_originate_sum_rt_lsa(struct ospf_proto *p, struct ospf_area *oa, u32 drid, int metric, u32 options)
{ {
struct ospf_new_lsa lsa = { struct ospf_new_lsa lsa = {
.type = LSA_T_SUM_RT, .type = LSA_T_SUM_RT,
.mode = LSA_M_RTCALC, .mode = LSA_M_RTCALC,
.dom = oa->areaid, .dom = oa->areaid,
.id = ipa_to_rid(nf->fn.prefix), /* Router ID of ASBR, irrelevant for OSPFv3 */ .id = drid, /* Router ID of ASBR, irrelevant for OSPFv3 */
.opts = oa->options .opts = oa->options
}; };
if (ospf_is_v2(p)) if (ospf_is_v2(p))
prepare_sum2_lsa_body(p, 0, metric); prepare_sum2_lsa_body(p, 0, metric);
else else
prepare_sum3_rt_lsa_body(p, lsa.id, metric, options & LSA_OPTIONS_MASK); prepare_sum3_rt_lsa_body(p, drid, metric, options & LSA_OPTIONS_MASK);
ospf_originate_lsa(p, &lsa); ospf_originate_lsa(p, &lsa);
} }
@ -1082,7 +1084,7 @@ prepare_ext3_lsa_body(struct ospf_proto *p, ort *nf,
{ {
struct ospf_lsa_ext3 *ext; struct ospf_lsa_ext3 *ext;
int bsize = sizeof(struct ospf_lsa_ext3) int bsize = sizeof(struct ospf_lsa_ext3)
+ IPV6_PREFIX_SPACE(nf->fn.pxlen) + IPV6_PREFIX_SPACE(nf->fn.addr->pxlen)
+ (ipa_nonzero(fwaddr) ? 16 : 0) + (ipa_nonzero(fwaddr) ? 16 : 0)
+ (tag ? 4 : 0); + (tag ? 4 : 0);
@ -1090,7 +1092,7 @@ prepare_ext3_lsa_body(struct ospf_proto *p, ort *nf,
ext->metric = metric & LSA_METRIC_MASK; ext->metric = metric & LSA_METRIC_MASK;
u32 *buf = ext->rest; u32 *buf = ext->rest;
buf = put_ipv6_prefix(buf, nf->fn.prefix, nf->fn.pxlen, pbit ? OPT_PX_P : 0, 0); buf = ospf_put_ipv6_prefix(buf, nf->fn.addr, pbit ? OPT_PX_P : 0, 0);
if (ebit) if (ebit)
ext->metric |= LSA_EXT3_EBIT; ext->metric |= LSA_EXT3_EBIT;
@ -1098,7 +1100,7 @@ prepare_ext3_lsa_body(struct ospf_proto *p, ort *nf,
if (ipa_nonzero(fwaddr)) if (ipa_nonzero(fwaddr))
{ {
ext->metric |= LSA_EXT3_FBIT; ext->metric |= LSA_EXT3_FBIT;
buf = put_ipv6_addr(buf, fwaddr); buf = ospf_put_ipv6_addr(buf, fwaddr);
} }
if (tag) if (tag)
@ -1140,7 +1142,7 @@ ospf_originate_ext_lsa(struct ospf_proto *p, struct ospf_area *oa, ort *nf, u8 m
}; };
if (ospf_is_v2(p)) if (ospf_is_v2(p))
prepare_ext2_lsa_body(p, nf->fn.pxlen, metric, ebit, fwaddr, tag); prepare_ext2_lsa_body(p, nf->fn.addr->pxlen, metric, ebit, fwaddr, tag);
else else
prepare_ext3_lsa_body(p, nf, metric, ebit, fwaddr, tag, oa && pbit); prepare_ext3_lsa_body(p, nf, metric, ebit, fwaddr, tag, oa && pbit);
@ -1253,7 +1255,7 @@ ospf_rt_notify(struct proto *P, rtable *tbl UNUSED, net *n, rte *new, rte *old U
if (!new) if (!new)
{ {
nf = (ort *) fib_find(&p->rtf, &n->n.prefix, n->n.pxlen); nf = fib_find(&p->rtf, n->n.addr);
if (!nf || !nf->external_rte) if (!nf || !nf->external_rte)
return; return;
@ -1290,13 +1292,13 @@ ospf_rt_notify(struct proto *P, rtable *tbl UNUSED, net *n, rte *new, rte *old U
if (ipa_zero(fwd)) if (ipa_zero(fwd))
{ {
log(L_ERR "%s: Cannot find forwarding address for NSSA-LSA %I/%d", log(L_ERR "%s: Cannot find forwarding address for NSSA-LSA %N",
p->p.name, n->n.prefix, n->n.pxlen); p->p.name, n->n.addr);
return; return;
} }
} }
nf = (ort *) fib_get(&p->rtf, &n->n.prefix, n->n.pxlen); nf = fib_get(&p->rtf, n->n.addr);
ospf_originate_ext_lsa(p, oa, nf, LSA_M_EXPORT, metric, ebit, fwd, tag, 1); ospf_originate_ext_lsa(p, oa, nf, LSA_M_EXPORT, metric, ebit, fwd, tag, 1);
nf->external_rte = 1; nf->external_rte = 1;
} }
@ -1308,11 +1310,12 @@ ospf_rt_notify(struct proto *P, rtable *tbl UNUSED, net *n, rte *new, rte *old U
*/ */
static inline void static inline void
lsab_put_prefix(struct ospf_proto *p, ip_addr prefix, u32 pxlen, u32 cost) lsab_put_prefix(struct ospf_proto *p, ip6_addr prefix, u32 pxlen, u32 cost)
{ {
net_addr_ip6 net = NET_ADDR_IP6(prefix, pxlen);
void *buf = lsab_alloc(p, IPV6_PREFIX_SPACE(pxlen)); void *buf = lsab_alloc(p, IPV6_PREFIX_SPACE(pxlen));
u8 flags = (pxlen < MAX_PREFIX_LENGTH) ? 0 : OPT_PX_LA; u8 flags = (pxlen < IP6_MAX_PREFIX_LENGTH) ? 0 : OPT_PX_LA;
put_ipv6_prefix(buf, prefix, pxlen, flags, cost); ospf_put_ipv6_prefix(buf, (net_addr *) &net, flags, cost);
} }
static void static void
@ -1406,7 +1409,7 @@ prepare_prefix_rt_lsa_body(struct ospf_proto *p, struct ospf_area *oa)
(a->scope <= SCOPE_LINK)) (a->scope <= SCOPE_LINK))
continue; continue;
if (((a->pxlen < MAX_PREFIX_LENGTH) && net_lsa) || if (((a->pxlen < IP6_MAX_PREFIX_LENGTH) && net_lsa) ||
configured_stubnet(oa, a)) configured_stubnet(oa, a))
continue; continue;
@ -1414,7 +1417,7 @@ prepare_prefix_rt_lsa_body(struct ospf_proto *p, struct ospf_area *oa)
(ifa->state == OSPF_IS_LOOP) || (ifa->state == OSPF_IS_LOOP) ||
(ifa->type == OSPF_IT_PTMP)) (ifa->type == OSPF_IT_PTMP))
{ {
lsab_put_prefix(p, a->ip, MAX_PREFIX_LENGTH, 0); lsab_put_prefix(p, a->ip, IP6_MAX_PREFIX_LENGTH, 0);
host_addr = 1; host_addr = 1;
} }
else else
@ -1430,7 +1433,7 @@ prepare_prefix_rt_lsa_body(struct ospf_proto *p, struct ospf_area *oa)
if (!sn->hidden) if (!sn->hidden)
{ {
lsab_put_prefix(p, sn->px.addr, sn->px.len, sn->cost); lsab_put_prefix(p, sn->px.addr, sn->px.len, sn->cost);
if (sn->px.len == MAX_PREFIX_LENGTH) if (sn->px.len == IP6_MAX_PREFIX_LENGTH)
host_addr = 1; host_addr = 1;
i++; i++;
} }
@ -1451,7 +1454,7 @@ prepare_prefix_rt_lsa_body(struct ospf_proto *p, struct ospf_area *oa)
continue; continue;
/* Found some IP */ /* Found some IP */
lsab_put_prefix(p, a->ip, MAX_PREFIX_LENGTH, 0); lsab_put_prefix(p, a->ip, IP6_MAX_PREFIX_LENGTH, 0);
i++; i++;
goto done; goto done;
} }

View file

@ -185,7 +185,7 @@ static inline void ospf_flush2_lsa(struct ospf_proto *p, struct top_hash_entry *
{ if (*en) { ospf_flush_lsa(p, *en); *en = NULL; } } { if (*en) { ospf_flush_lsa(p, *en); *en = NULL; } }
void ospf_originate_sum_net_lsa(struct ospf_proto *p, struct ospf_area *oa, ort *nf, int metric); void ospf_originate_sum_net_lsa(struct ospf_proto *p, struct ospf_area *oa, ort *nf, int metric);
void ospf_originate_sum_rt_lsa(struct ospf_proto *p, struct ospf_area *oa, ort *nf, int metric, u32 options); void ospf_originate_sum_rt_lsa(struct ospf_proto *p, struct ospf_area *oa, u32 drid, int metric, u32 options);
void ospf_originate_ext_lsa(struct ospf_proto *p, struct ospf_area *oa, ort *nf, u8 mode, u32 metric, u32 ebit, ip_addr fwaddr, u32 tag, int pbit); void ospf_originate_ext_lsa(struct ospf_proto *p, struct ospf_area *oa, ort *nf, u8 mode, u32 metric, u32 ebit, ip_addr fwaddr, u32 tag, int pbit);
void ospf_rt_notify(struct proto *P, rtable *tbl, net *n, rte *new, rte *old, ea_list *attrs); void ospf_rt_notify(struct proto *P, rtable *tbl, net *n, rte *new, rte *old, ea_list *attrs);

View file

@ -60,12 +60,12 @@ pipe_rt_notify(struct proto *P, rtable *src_table, net *n, rte *new, rte *old, e
if (dst_table->pipe_busy) if (dst_table->pipe_busy)
{ {
log(L_ERR "Pipe loop detected when sending %I/%d to table %s", log(L_ERR "Pipe loop detected when sending %N to table %s",
n->n.prefix, n->n.pxlen, dst_table->name); n->n.addr, dst_table->name);
return; return;
} }
nn = net_get(dst_table, n->n.prefix, n->n.pxlen); nn = net_get(dst_table, n->n.addr);
if (new) if (new)
{ {
memcpy(&a, new->attrs, sizeof(rta)); memcpy(&a, new->attrs, sizeof(rta));

View file

@ -258,9 +258,7 @@ radv_ifa_notify(struct proto *p, unsigned flags, struct ifa *a)
static inline int radv_net_match_trigger(struct radv_config *cf, net *n) static inline int radv_net_match_trigger(struct radv_config *cf, net *n)
{ {
return cf->trigger_valid && return cf->trigger_valid && net_equal(n->n.addr, cf->trigger);
(n->n.pxlen == cf->trigger_pxlen) &&
ipa_equal(n->n.prefix, cf->trigger_prefix);
} }
int int
@ -306,8 +304,7 @@ radv_check_active(struct proto_radv *ra)
if (! cf->trigger_valid) if (! cf->trigger_valid)
return 1; return 1;
return rt_examine(ra->p.table, cf->trigger_prefix, cf->trigger_pxlen, return rt_examine(ra->p.table, cf->trigger, &ra->p, ra->p.cf->out_filter);
&(ra->p), ra->p.cf->out_filter);
} }
static struct proto * static struct proto *

View file

@ -50,8 +50,7 @@ struct radv_config
list rdnss_list; /* Global list of RDNSS configs (struct radv_rdnss_config) */ list rdnss_list; /* Global list of RDNSS configs (struct radv_rdnss_config) */
list dnssl_list; /* Global list of DNSSL configs (struct radv_dnssl_config) */ list dnssl_list; /* Global list of DNSSL configs (struct radv_dnssl_config) */
ip_addr trigger_prefix; /* Prefix of a trigger route, if defined */ net_addr *trigger; /* Prefix of a trigger route, if defined */
u8 trigger_pxlen; /* Pxlen of a trigger route, if defined */
u8 trigger_valid; /* Whether a trigger route is defined */ u8 trigger_valid; /* Whether a trigger route is defined */
}; };

View file

@ -78,8 +78,7 @@ struct rip_auth_tail
/* Internal representation of RTE block data */ /* Internal representation of RTE block data */
struct rip_block struct rip_block
{ {
ip_addr prefix; net_addr net;
int pxlen;
u32 metric; u32 metric;
u16 tag; u16 tag;
u16 no_af; u16 no_af;
@ -115,17 +114,17 @@ rip_put_block(struct rip_proto *p, byte *pos, struct rip_block *rte)
struct rip_block_v2 *block = (void *) pos; struct rip_block_v2 *block = (void *) pos;
block->family = rte->no_af ? 0 : htons(RIP_AF_IPV4); block->family = rte->no_af ? 0 : htons(RIP_AF_IPV4);
block->tag = htons(rte->tag); block->tag = htons(rte->tag);
block->network = ip4_hton(ipa_to_ip4(rte->prefix)); block->network = ip4_hton(net4_prefix(&rte->net));
block->netmask = ip4_hton(ip4_mkmask(rte->pxlen)); block->netmask = ip4_hton(ip4_mkmask(net4_pxlen(&rte->net)));
block->next_hop = ip4_hton(ipa_to_ip4(rte->next_hop)); block->next_hop = ip4_hton(ipa_to_ip4(rte->next_hop));
block->metric = htonl(rte->metric); block->metric = htonl(rte->metric);
} }
else /* RIPng */ else /* RIPng */
{ {
struct rip_block_ng *block = (void *) pos; struct rip_block_ng *block = (void *) pos;
block->prefix = ip6_hton(ipa_to_ip6(rte->prefix)); block->prefix = ip6_hton(net6_prefix(&rte->net));
block->tag = htons(rte->tag); block->tag = htons(rte->tag);
block->pxlen = rte->pxlen; block->pxlen = net6_pxlen(&rte->net);
block->metric = rte->metric; block->metric = rte->metric;
} }
} }
@ -151,8 +150,8 @@ rip_get_block(struct rip_proto *p, byte *pos, struct rip_block *rte)
if (block->family != (rte->no_af ? 0 : htons(RIP_AF_IPV4))) if (block->family != (rte->no_af ? 0 : htons(RIP_AF_IPV4)))
return 0; return 0;
rte->prefix = ipa_from_ip4(ip4_ntoh(block->network)); uint pxlen = ip4_masklen(ip4_ntoh(block->netmask));
rte->pxlen = ip4_masklen(ip4_ntoh(block->netmask)); net_fill_ip4(&rte->net, ip4_ntoh(block->network), pxlen);
rte->metric = ntohl(block->metric); rte->metric = ntohl(block->metric);
rte->tag = ntohs(block->tag); rte->tag = ntohs(block->tag);
rte->next_hop = ipa_from_ip4(ip4_ntoh(block->next_hop)); rte->next_hop = ipa_from_ip4(ip4_ntoh(block->next_hop));
@ -171,8 +170,8 @@ rip_get_block(struct rip_proto *p, byte *pos, struct rip_block *rte)
return 0; return 0;
} }
rte->prefix = ipa_from_ip6(ip6_ntoh(block->prefix)); uint pxlen = (block->pxlen < IP6_MAX_PREFIX_LENGTH) ? block->pxlen : 255;
rte->pxlen = block->pxlen; net_fill_ip6(&rte->net, ip6_ntoh(block->prefix), pxlen);
rte->metric = block->metric; rte->metric = block->metric;
rte->tag = ntohs(block->tag); rte->tag = ntohs(block->tag);
/* rte->next_hop is deliberately kept unmodified */; /* rte->next_hop is deliberately kept unmodified */;
@ -385,8 +384,9 @@ rip_receive_request(struct rip_proto *p, struct rip_iface *ifa, struct rip_packe
if (!rip_get_block(p, pos, &b)) if (!rip_get_block(p, pos, &b))
return; return;
/* Special case - zero prefix, infinity metric */ /* Special case - infinity metric, for RIPng also zero prefix */
if (ipa_nonzero(b.prefix) || b.pxlen || (b.metric != p->infinity)) if ((b.metric != p->infinity) ||
(rip_is_ng(p) && !net_zero_ip6((net_addr_ip6 *) &b.net)))
return; return;
/* We do nothing if TX is already active */ /* We do nothing if TX is already active */
@ -444,23 +444,23 @@ rip_send_response(struct rip_proto *p, struct rip_iface *ifa)
} }
struct rip_block rte = { struct rip_block rte = {
.prefix = en->n.prefix,
.pxlen = en->n.pxlen,
.metric = en->metric, .metric = en->metric,
.tag = en->tag .tag = en->tag
}; };
net_copy(&rte.net, en->n.addr);
if (en->iface == ifa->iface) if (en->iface == ifa->iface)
rte.next_hop = en->next_hop; rte.next_hop = en->next_hop;
if (rip_is_v2(p) && (ifa->cf->version == RIP_V1)) if (rip_is_v2(p) && (ifa->cf->version == RIP_V1))
{ {
/* Skipping subnets (i.e. not hosts, classful networks or default route) */ /* Skipping subnets (i.e. not hosts, classful networks or default route) */
if (ip4_masklen(ip4_class_mask(ipa_to_ip4(en->n.prefix))) != en->n.pxlen) if (ip4_masklen(ip4_class_mask(net4_prefix(&rte.net))) != rte.net.pxlen)
goto next_entry; goto next_entry;
rte.tag = 0; rte.tag = 0;
rte.pxlen = 0; rte.net.pxlen = 0;
rte.next_hop = IPA_NONE; rte.next_hop = IPA_NONE;
} }
@ -476,7 +476,7 @@ rip_send_response(struct rip_proto *p, struct rip_iface *ifa)
goto next_entry; goto next_entry;
} }
// TRACE(D_PACKETS, " %I/%d -> %I metric %d", rte.prefix, rte.pxlen, rte.next_hop, rte.metric); // TRACE(D_PACKETS, " %N -> %I metric %d", &rte.net, rte.next_hop, rte.metric);
/* RIPng next hop entry */ /* RIPng next hop entry */
if (rip_is_ng(p) && !ipa_equal(rte.next_hop, last_next_hop)) if (rip_is_ng(p) && !ipa_equal(rte.next_hop, last_next_hop))
@ -577,23 +577,25 @@ rip_receive_response(struct rip_proto *p, struct rip_iface *ifa, struct rip_pack
if (!rip_get_block(p, pos, &rte)) if (!rip_get_block(p, pos, &rte))
continue; continue;
int c = ipa_classify_net(rte.prefix);
if ((c < 0) || !(c & IADDR_HOST) || ((c & IADDR_SCOPE_MASK) <= SCOPE_LINK))
SKIP("invalid prefix");
if (rip_is_v2(p) && (pkt->version == RIP_V1)) if (rip_is_v2(p) && (pkt->version == RIP_V1))
{ {
if (ifa->cf->check_zero && (rte.tag || rte.pxlen || ipa_nonzero(rte.next_hop))) if (ifa->cf->check_zero && (rte.tag || rte.net.pxlen || ipa_nonzero(rte.next_hop)))
SKIP("RIPv1 reserved field is nonzero"); SKIP("RIPv1 reserved field is nonzero");
rte.tag = 0; rte.tag = 0;
rte.pxlen = ip4_masklen(ip4_class_mask(ipa_to_ip4(rte.prefix))); rte.net.pxlen = ip4_masklen(ip4_class_mask(net4_prefix(&rte.net)));
rte.next_hop = IPA_NONE; rte.next_hop = IPA_NONE;
} }
if ((rte.pxlen < 0) || (rte.pxlen > MAX_PREFIX_LENGTH)) if (rte.net.pxlen == 255)
SKIP("invalid prefix length"); SKIP("invalid prefix length");
net_normalize(&rte.net);
int c = net_classify(&rte.net);
if ((c < 0) || !(c & IADDR_HOST) || ((c & IADDR_SCOPE_MASK) <= SCOPE_LINK))
SKIP("invalid prefix");
if (rte.metric > p->infinity) if (rte.metric > p->infinity)
SKIP("invalid metric"); SKIP("invalid metric");
@ -604,7 +606,7 @@ rip_receive_response(struct rip_proto *p, struct rip_iface *ifa, struct rip_pack
rte.next_hop = IPA_NONE; rte.next_hop = IPA_NONE;
} }
// TRACE(D_PACKETS, " %I/%d -> %I metric %d", rte.prefix, rte.pxlen, rte.next_hop, rte.metric); // TRACE(D_PACKETS, " %N -> %I metric %d", &rte.net.n, rte.next_hop, rte.metric);
rte.metric += ifa->cf->metric; rte.metric += ifa->cf->metric;
@ -618,16 +620,16 @@ rip_receive_response(struct rip_proto *p, struct rip_iface *ifa, struct rip_pack
.expires = now + ifa->cf->timeout_time .expires = now + ifa->cf->timeout_time
}; };
rip_update_rte(p, &rte.prefix, rte.pxlen, &new); rip_update_rte(p, &rte.net, &new);
} }
else else
rip_withdraw_rte(p, &rte.prefix, rte.pxlen, from); rip_withdraw_rte(p, &rte.net, from);
continue; continue;
skip: skip:
LOG_RTE("Ignoring route %I/%d received from %I - %s", LOG_RTE("Ignoring route %N received from %I - %s",
rte.prefix, rte.pxlen, from->nbr->addr, err_dsc); &rte.net, from->nbr->addr, err_dsc);
} }
} }

View file

@ -92,15 +92,6 @@ static void rip_trigger_update(struct rip_proto *p);
* RIP routes * RIP routes
*/ */
static void
rip_init_entry(struct fib_node *fn)
{
// struct rip_entry *en = (void) *fn;
const uint offset = OFFSETOF(struct rip_entry, routes);
memset((byte *)fn + offset, 0, sizeof(struct rip_entry) - offset);
}
static struct rip_rte * static struct rip_rte *
rip_add_rte(struct rip_proto *p, struct rip_rte **rp, struct rip_rte *src) rip_add_rte(struct rip_proto *p, struct rip_rte **rp, struct rip_rte *src)
{ {
@ -152,7 +143,7 @@ rip_announce_rte(struct rip_proto *p, struct rip_entry *en)
if (rt) if (rt)
{ {
/* Update */ /* Update */
net *n = net_get(p->p.table, en->n.prefix, en->n.pxlen); net *n = net_get(p->p.table, en->n.addr);
rta a0 = { rta a0 = {
.src = p->p.main_source, .src = p->p.main_source,
@ -221,7 +212,7 @@ rip_announce_rte(struct rip_proto *p, struct rip_entry *en)
else else
{ {
/* Withdraw */ /* Withdraw */
net *n = net_find(p->p.table, en->n.prefix, en->n.pxlen); net *n = net_find(p->p.table, en->n.addr);
rte_update(&p->p, n, NULL); rte_update(&p->p, n, NULL);
} }
} }
@ -229,8 +220,7 @@ rip_announce_rte(struct rip_proto *p, struct rip_entry *en)
/** /**
* rip_update_rte - enter a route update to RIP routing table * rip_update_rte - enter a route update to RIP routing table
* @p: RIP instance * @p: RIP instance
* @prefix: network prefix * @addr: network address
* @pxlen: network prefix length
* @new: a &rip_rte representing the new route * @new: a &rip_rte representing the new route
* *
* The function is called by the RIP packet processing code whenever it receives * The function is called by the RIP packet processing code whenever it receives
@ -240,9 +230,9 @@ rip_announce_rte(struct rip_proto *p, struct rip_entry *en)
* rip_withdraw_rte() should be called instead of rip_update_rte(). * rip_withdraw_rte() should be called instead of rip_update_rte().
*/ */
void void
rip_update_rte(struct rip_proto *p, ip_addr *prefix, int pxlen, struct rip_rte *new) rip_update_rte(struct rip_proto *p, net_addr *n, struct rip_rte *new)
{ {
struct rip_entry *en = fib_get(&p->rtable, prefix, pxlen); struct rip_entry *en = fib_get(&p->rtable, n);
struct rip_rte *rt, **rp; struct rip_rte *rt, **rp;
int changed = 0; int changed = 0;
@ -282,8 +272,7 @@ rip_update_rte(struct rip_proto *p, ip_addr *prefix, int pxlen, struct rip_rte *
/** /**
* rip_withdraw_rte - enter a route withdraw to RIP routing table * rip_withdraw_rte - enter a route withdraw to RIP routing table
* @p: RIP instance * @p: RIP instance
* @prefix: network prefix * @addr: network address
* @pxlen: network prefix length
* @from: a &rip_neighbor propagating the withdraw * @from: a &rip_neighbor propagating the withdraw
* *
* The function is called by the RIP packet processing code whenever it receives * The function is called by the RIP packet processing code whenever it receives
@ -291,9 +280,9 @@ rip_update_rte(struct rip_proto *p, ip_addr *prefix, int pxlen, struct rip_rte *
* removed. Eventually, the change is also propagated by rip_announce_rte(). * removed. Eventually, the change is also propagated by rip_announce_rte().
*/ */
void void
rip_withdraw_rte(struct rip_proto *p, ip_addr *prefix, int pxlen, struct rip_neighbor *from) rip_withdraw_rte(struct rip_proto *p, net_addr *n, struct rip_neighbor *from)
{ {
struct rip_entry *en = fib_find(&p->rtable, prefix, pxlen); struct rip_entry *en = fib_find(&p->rtable, n);
struct rip_rte *rt, **rp; struct rip_rte *rt, **rp;
if (!en) if (!en)
@ -335,15 +324,15 @@ rip_rt_notify(struct proto *P, struct rtable *table UNUSED, struct network *net,
if (rt_metric > p->infinity) if (rt_metric > p->infinity)
{ {
log(L_WARN "%s: Invalid rip_metric value %u for route %I/%d", log(L_WARN "%s: Invalid rip_metric value %u for route %N",
p->p.name, rt_metric, net->n.prefix, net->n.pxlen); p->p.name, rt_metric, net->n.addr);
rt_metric = p->infinity; rt_metric = p->infinity;
} }
if (rt_tag > 0xffff) if (rt_tag > 0xffff)
{ {
log(L_WARN "%s: Invalid rip_tag value %u for route %I/%d", log(L_WARN "%s: Invalid rip_tag value %u for route %N",
p->p.name, rt_tag, net->n.prefix, net->n.pxlen); p->p.name, rt_tag, net->n.addr);
rt_metric = p->infinity; rt_metric = p->infinity;
rt_tag = 0; rt_tag = 0;
} }
@ -355,7 +344,7 @@ rip_rt_notify(struct proto *P, struct rtable *table UNUSED, struct network *net,
* collection. * collection.
*/ */
en = fib_get(&p->rtable, &net->n.prefix, net->n.pxlen); en = fib_get(&p->rtable, net->n.addr);
old_metric = en->valid ? en->metric : -1; old_metric = en->valid ? en->metric : -1;
@ -369,7 +358,7 @@ rip_rt_notify(struct proto *P, struct rtable *table UNUSED, struct network *net,
else else
{ {
/* Withdraw */ /* Withdraw */
en = fib_find(&p->rtable, &net->n.prefix, net->n.pxlen); en = fib_find(&p->rtable, net->n.addr);
if (!en || en->valid != RIP_ENTRY_VALID) if (!en || en->valid != RIP_ENTRY_VALID)
return; return;
@ -875,7 +864,7 @@ rip_timer(timer *t)
if (expires <= now) if (expires <= now)
{ {
// TRACE(D_EVENTS, "entry is too old: %I/%d", en->n.prefix, en->n.pxlen); // TRACE(D_EVENTS, "entry is too old: %N", en->n.addr);
en->valid = 0; en->valid = 0;
} }
else else
@ -1108,7 +1097,8 @@ rip_start(struct proto *P)
struct rip_config *cf = (void *) (P->cf); struct rip_config *cf = (void *) (P->cf);
init_list(&p->iface_list); init_list(&p->iface_list);
fib_init(&p->rtable, P->pool, sizeof(struct rip_entry), 0, rip_init_entry); fib_init(&p->rtable, P->pool, rip_is_v2(p) ? NET_IP4 : NET_IP6,
sizeof(struct rip_entry), OFFSETOF(struct rip_entry, n), 0, NULL);
p->rte_slab = sl_new(P->pool, sizeof(struct rip_rte)); p->rte_slab = sl_new(P->pool, sizeof(struct rip_rte));
p->timer = tm_new_set(P->pool, rip_timer, p, 0, 0); p->timer = tm_new_set(P->pool, rip_timer, p, 0, 0);
@ -1257,8 +1247,8 @@ rip_dump(struct proto *P)
FIB_WALK(&p->rtable, e) FIB_WALK(&p->rtable, e)
{ {
struct rip_entry *en = (struct rip_entry *) e; struct rip_entry *en = (struct rip_entry *) e;
debug("RIP: entry #%d: %I/%d via %I dev %s valid %d metric %d age %d s\n", debug("RIP: entry #%d: %N via %I dev %s valid %d metric %d age %d s\n",
i++, en->n.prefix, en->n.pxlen, en->next_hop, en->iface->name, i++, en->n.addr, en->next_hop, en->iface->name,
en->valid, en->metric, now - en->changed); en->valid, en->metric, now - en->changed);
} }
FIB_WALK_END; FIB_WALK_END;

View file

@ -149,7 +149,6 @@ struct rip_neighbor
struct rip_entry struct rip_entry
{ {
struct fib_node n;
struct rip_rte *routes; /* List of incoming routes */ struct rip_rte *routes; /* List of incoming routes */
u8 valid; /* Entry validity state (RIP_ENTRY_*) */ u8 valid; /* Entry validity state (RIP_ENTRY_*) */
@ -160,6 +159,8 @@ struct rip_entry
ip_addr next_hop; /* Outgoing route next hop */ ip_addr next_hop; /* Outgoing route next hop */
bird_clock_t changed; /* Last time when the outgoing route metric changed */ bird_clock_t changed; /* Last time when the outgoing route metric changed */
struct fib_node n;
}; };
struct rip_rte struct rip_rte
@ -211,8 +212,8 @@ rip_reset_tx_session(struct rip_proto *p, struct rip_iface *ifa)
} }
/* rip.c */ /* rip.c */
void rip_update_rte(struct rip_proto *p, ip_addr *prefix, int pxlen, struct rip_rte *new); void rip_update_rte(struct rip_proto *p, net_addr *n, struct rip_rte *new);
void rip_withdraw_rte(struct rip_proto *p, ip_addr *prefix, int pxlen, struct rip_neighbor *from); void rip_withdraw_rte(struct rip_proto *p, net_addr *n, struct rip_neighbor *from);
struct rip_neighbor * rip_get_neighbor(struct rip_proto *p, ip_addr *a, struct rip_iface *ifa); struct rip_neighbor * rip_get_neighbor(struct rip_proto *p, ip_addr *a, struct rip_iface *ifa);
void rip_update_bfd(struct rip_proto *p, struct rip_neighbor *n); void rip_update_bfd(struct rip_proto *p, struct rip_neighbor *n);
void rip_show_interfaces(struct proto *P, char *iff); void rip_show_interfaces(struct proto *P, char *iff);

View file

@ -112,7 +112,7 @@ static_install(struct proto *p, struct static_route *r, struct iface *ifa)
/* We skip rta_lookup() here */ /* We skip rta_lookup() here */
n = net_get(p->table, r->net, r->masklen); n = net_get_ipa(p->table, r->net, r->masklen);
e = rte_get_temp(&a); e = rte_get_temp(&a);
e->net = n; e->net = n;
e->pflags = 0; e->pflags = 0;
@ -136,7 +136,7 @@ static_remove(struct proto *p, struct static_route *r)
return; return;
DBG("Removing static route %I/%d via %I\n", r->net, r->masklen, r->via); DBG("Removing static route %I/%d via %I\n", r->net, r->masklen, r->via);
n = net_find(p->table, r->net, r->masklen); n = net_find_ipa(p->table, r->net, r->masklen);
rte_update(p, n, NULL); rte_update(p, n, NULL);
r->installed = 0; r->installed = 0;
} }

View file

@ -911,8 +911,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 %N", net->n.addr);
net->n.prefix, net->n.pxlen);
return; return;
} }
@ -922,8 +921,7 @@ 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 %N with unknown ifindex %u", net->n.addr, oif);
net->n.prefix, net->n.pxlen, oif);
return; return;
} }
@ -944,8 +942,7 @@ 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 %N with strange next-hop %I", net->n.addr, ra.gw);
net->n.prefix, net->n.pxlen, ra.gw);
return; return;
} }
} }
@ -1020,8 +1017,7 @@ nl_parse_route(struct nlmsghdr *h, int scan)
if (nl_parse_metrics(a[RTA_METRICS], metrics, ARRAY_SIZE(metrics)) < 0) if (nl_parse_metrics(a[RTA_METRICS], metrics, ARRAY_SIZE(metrics)) < 0)
{ {
log(L_ERR "KRT: Received route %I/%d with strange RTA_METRICS attribute", log(L_ERR "KRT: Received route %N with strange RTA_METRICS attribute", net->n.addr);
net->n.prefix, net->n.pxlen);
return; return;
} }

View file

@ -297,14 +297,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: %N: %s", p->p.name, e->net->n.addr, msg);
} }
static inline void static inline void
krt_trace_in_rl(struct tbf *f, struct krt_proto *p, rte *e, char *msg) krt_trace_in_rl(struct tbf *f, struct krt_proto *p, rte *e, char *msg)
{ {
if (p->p.debug & D_PACKETS) if (p->p.debug & D_PACKETS)
log_rl(f, L_TRACE "%s: %I/%d: %s", p->p.name, e->net->n.prefix, e->net->n.pxlen, msg); log_rl(f, L_TRACE "%s: %N: %s", p->p.name, e->net->n.addr, msg);
} }
/* /*
@ -347,7 +347,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 = net_get(p->p.table, n->n.addr);
ee->net = nn; ee->net = nn;
ee->pflags = 0; ee->pflags = 0;
ee->pref = p->p.preference; ee->pref = p->p.preference;
@ -358,7 +358,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 = net_find(p->p.table, n->n.addr);
rte_update(&p->p, n, NULL); rte_update(&p->p, n, NULL);
} }
@ -367,7 +367,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 = net_get(&p->krt_table, n0->n.addr);
rte *m, **mm; rte *m, **mm;
e->attrs = rta_lookup(e->attrs); e->attrs = rta_lookup(e->attrs);
@ -469,7 +469,7 @@ 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); net *n = net_get(&p->krt_table, n0->n.addr);
rte *g, **gg, *best, **bestp, *old_best; rte *g, **gg, *best, **bestp, *old_best;
e->attrs = rta_lookup(e->attrs); e->attrs = rta_lookup(e->attrs);