Commit fe9f1a6d authored by Ondřej Zajíček's avatar Ondřej Zajíček

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.
parent 8eb8e546
......@@ -123,27 +123,15 @@ include ^{WHITE}*include{WHITE}*\".*\"{WHITE}*;
}
{DIGIT}+\.{DIGIT}+\.{DIGIT}+\.{DIGIT}+ {
ip4_addr a;
if (!ip4_pton(yytext, &a))
if (!ip4_pton(yytext, &cf_lval.ip4))
cf_error("Invalid IPv4 address %s", yytext);
#ifdef IPV6
cf_lval.i32 = ip4_to_u32(a);
return RTRID;
#else
cf_lval.a = ipa_from_ip4(a);
return IPA;
#endif
return IP4;
}
({XIGIT}*::|({XIGIT}*:){3,})({XIGIT}*|{DIGIT}+\.{DIGIT}+\.{DIGIT}+\.{DIGIT}+) {
#ifdef IPV6
if (ipa_pton(yytext, &cf_lval.a))
return IPA;
cf_error("Invalid IPv6 address %s", yytext);
#else
cf_error("This is an IPv4 router, therefore IPv6 addresses are not supported");
#endif
if (!ip6_pton(yytext, &cf_lval.ip6))
cf_error("Invalid IPv6 address %s", yytext);
return IP6;
}
0x{XIGIT}+ {
......
......@@ -133,10 +133,10 @@ config_parse(struct config *c)
protos_postconfig(c);
if (EMPTY_LIST(c->protos))
cf_error("No protocol is specified in the config file");
#ifdef IPV6
/* XXXX */
if (!c->router_id)
cf_error("Router ID must be configured manually on IPv6 routers");
#endif
cf_error("Router ID must be configured manually");
return 1;
}
......
......@@ -39,6 +39,8 @@ CF_DECLS
int i;
u32 i32;
ip_addr a;
ip4_addr ip4;
ip6_addr ip6;
struct symbol *s;
char *t;
struct rtable_config *r;
......@@ -66,8 +68,8 @@ CF_DECLS
%token GEQ LEQ NEQ AND OR
%token PO PC
%token <i> NUM ENUM
%token <i32> RTRID
%token <a> IPA
%token <ip4> IP4
%token <ip6> IP6
%token <s> SYM
%token <t> TEXT
%type <iface> ipa_scope
......@@ -75,10 +77,11 @@ CF_DECLS
%type <i> expr bool pxlen
%type <i32> expr_us
%type <time> datetime
%type <a> ipa
%type <a> ipa ipa_raw
%type <px> prefix prefix_or_ipa
%type <t> text
%type <t> text_or_none
%type <t> opttext
%nonassoc PREFIX_DUMMY
%left AND OR
......@@ -148,8 +151,13 @@ bool:
/* Addresses, prefixes and netmasks */
ipa_raw:
IP4 { $$ = ipa_from_ip4($1); }
| IP6 { $$ = ipa_from_ip6($1); }
;
ipa:
IPA
ipa_raw
| SYM {
if ($1->class != (SYM_CONSTANT | T_IP)) cf_error("IP address expected");
$$ = SYM_VAL($1).px.ip;
......@@ -205,6 +213,12 @@ text_or_none:
| { $$ = NULL; }
;
opttext:
TEXT
| /* empty */ { $$ = NULL; }
;
CF_CODE
CF_END
......@@ -205,7 +205,7 @@ fi
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'`
if test "$with_protocols" = all ; then
......
......@@ -477,7 +477,7 @@ block:
* Complex types, their bison value is struct f_val
*/
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:
NUM { $$.type = T_INT; $$.val.i = $1; }
| RTRID { $$.type = T_QUAD; $$.val.i = $1; }
| fipa { $$ = $1; }
| ENUM { $$.type = pair_a($1); $$.val.i = pair_b($1); }
| '(' term ')' {
......@@ -508,7 +507,6 @@ set_atom:
switch_atom:
NUM { $$.type = T_INT; $$.val.i = $1; }
| '(' term ')' { $$.type = T_INT; $$.val.i = f_eval_int($2); }
| RTRID { $$.type = T_QUAD; $$.val.i = $1; }
| fipa { $$ = $1; }
| ENUM { $$.type = pair_a($1); $$.val.i = pair_b($1); }
;
......@@ -575,7 +573,7 @@ switch_items:
;
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);
$$.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; }
| 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; }
| 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" ); }
| '[' 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; }
......
......@@ -792,8 +792,8 @@ interpret(struct f_inst *what)
{
case SA_FROM: res.val.px.ip = rta->from; break;
case SA_GW: res.val.px.ip = rta->gw; break;
case SA_NET: res.val.px.ip = (*f_rte)->net->n.prefix;
res.val.px.len = (*f_rte)->net->n.pxlen; break;
case SA_NET: res.val.px.ip = net_prefix((*f_rte)->net->n.addr);
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_SOURCE: res.val.i = rta->source; break;
case SA_SCOPE: res.val.i = rta->scope; break;
......@@ -1292,8 +1292,8 @@ interpret(struct f_inst *what)
else
{
ACCESS_RTE;
v1.val.px.ip = (*f_rte)->net->n.prefix;
v1.val.px.len = (*f_rte)->net->n.pxlen;
v1.val.px.ip = net_prefix((*f_rte)->net->n.addr);
v1.val.px.len = net_pxlen((*f_rte)->net->n.addr);
/* 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 */
......
......@@ -28,15 +28,15 @@ u32_mkmask(uint n)
*
* This function checks whether the given integer @x represents
* 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)
{
int l = 0;
u32 n = ~x;
if (n & (n+1)) return -1;
if (n & (n+1)) return 255;
if (x & 0x0000ffff) { x &= 0x0000ffff; l += 16; }
if (x & 0x00ff00ff) { x &= 0x00ff00ff; l += 8; }
if (x & 0x0f0f0f0f) { x &= 0x0f0f0f0f; l += 4; }
......
......@@ -19,7 +19,7 @@
*/
u32 u32_mkmask(uint n);
int u32_masklen(u32 x);
uint u32_masklen(u32 x);
u32 u32_log2(u32 v);
......
......@@ -58,7 +58,7 @@ ip6_mkmask(uint n)
return a;
}
int
uint
ip6_masklen(ip6_addr *a)
{
int i, j, n;
......@@ -72,7 +72,7 @@ ip6_masklen(ip6_addr *a)
n += j;
while (++i < 4)
if (a->addr[i])
return -1;
return 255;
break;
}
......
......@@ -30,6 +30,9 @@
#define IP4_NONE _MI4(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 IP6_MIN_MTU 1280
......@@ -39,17 +42,14 @@
#define IP6_HEADER_LENGTH 40
#define UDP_HEADER_LENGTH 8
#ifdef IPV6
#define MAX_PREFIX_LENGTH 128
#define BITS_PER_IP_ADDRESS 128
#define STD_ADDRESS_P_LENGTH 39
#define SIZE_OF_IP_HEADER 40
#else
#define MAX_PREFIX_LENGTH 32
#define BITS_PER_IP_ADDRESS 32
#define STD_ADDRESS_P_LENGTH 15
#define SIZE_OF_IP_HEADER 24
#endif
......@@ -319,11 +319,11 @@ static inline int ipa_classify_net(ip_addr a)
static inline ip4_addr ip4_mkmask(uint 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)); }
ip6_addr ip6_mkmask(uint n);
int ip6_masklen(ip6_addr *a);
uint ip6_masklen(ip6_addr *a);
/* ipX_pxlen() requires that x != y */
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)
{ 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)
{ 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_pxlen(x,y) ip6_pxlen(x,y)
#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_m2(x) ip6_opposite_m2(x)
#else
......@@ -371,6 +385,8 @@ ip4_addr ip4_class_mask(ip4_addr ad);
#define ipa_masklen(x) ip4_masklen(x)
#define ipa_pxlen(x,y) ip4_pxlen(x,y)
#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_m2(x) ip4_opposite_m2(x)
#endif
......
#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);
}
}
/*
* 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
......@@ -236,6 +236,12 @@ int bvsnprintf(char *buf, int size, const char *fmt, va_list args)
case 'M':
s = strerror(va_arg(args, int));
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':
s = va_arg(args, char *);
if (!s)
......
source=rt-table.c rt-fib.c rt-attr.c rt-roa.c proto.c iface.c rt-dev.c password.c cli.c locks.c cmds.c neighbor.c \
source=rt-table.c rt-fib.c rt-attr.c proto.c iface.c rt-dev.c password.c cli.c locks.c cmds.c neighbor.c \
a-path.c a-set.c
root-rel=../
dir-name=nest
......
......@@ -12,5 +12,6 @@
#include "sysdep/config.h"
#include "lib/birdlib.h"
#include "lib/ip.h"
#include "lib/net.h"
#endif
......@@ -55,6 +55,7 @@ CF_DECLS
CF_KEYWORDS(ROUTER, ID, PROTOCOL, TEMPLATE, PREFERENCE, DISABLED, DEBUG, ALL, OFF, DIRECT)
CF_KEYWORDS(INTERFACE, IMPORT, EXPORT, FILTER, NONE, TABLE, STATES, ROUTES, FILTERS)
CF_KEYWORDS(IPV4, IPVX, VPN4, VPN6)
CF_KEYWORDS(RECEIVE, LIMIT, ACTION, WARN, BLOCK, RESTART, DISABLE, KEEP, FILTERED)
CF_KEYWORDS(PASSWORD, FROM, PASSIVE, TO, ID, EVENTS, PACKETS, PROTOCOLS, INTERFACES)
CF_KEYWORDS(PRIMARY, STATS, COUNT, FOR, COMMANDS, PREEXPORT, NOEXPORT, GENERATE, ROA)
......@@ -77,7 +78,7 @@ CF_ENUM(T_ENUM_ROA, ROA_, UNKNOWN, VALID, INVALID)
%type <ro> roa_args
%type <rot> roa_table_arg
%type <sd> sym_args
%type <i> proto_start echo_mask echo_size debug_mask debug_list debug_flag mrtdump_mask mrtdump_list mrtdump_flag export_mode roa_mode limit_action tab_sorted tos
%type <i> proto_start echo_mask echo_size debug_mask debug_list debug_flag mrtdump_mask mrtdump_list mrtdump_flag export_mode roa_mode limit_action table_type table_sorted tos
%type <ps> proto_patt proto_patt2
%type <g> limit_spec
......@@ -95,14 +96,7 @@ rtrid:
idval:
NUM { $$ = $1; }
| '(' term ')' { $$ = f_eval_int($2); }
| RTRID
| IPA {
#ifndef IPV6
$$ = ipa_to_u32($1);
#else
cf_error("Router IDs must be entered as hexadecimal numbers or IPv4 addresses in IPv6 version");
#endif
}
| IP4 { $$ = ip4_to_u32($1); }
| SYM {
if ($1->class == (SYM_CONSTANT | T_INT) || $1->class == (SYM_CONSTANT | T_QUAD))
$$ = SYM_VAL($1).i;
......@@ -140,17 +134,25 @@ gr_opts: GRACEFUL RESTART WAIT expr ';' { new_config->gr_wait = $4; } ;
/* Creation of routing tables */
tab_sorted:
CF_ADDTO(conf, table)
table_type:
/* empty */ { $$ = NET_IP4; }
| IPV4 { $$ = NET_IP4; }
| IPVX { $$ = NET_IP6; } /* XXXX */
| VPN4 { $$ = NET_VPN4; }
| VPN6 { $$ = NET_VPN6; }
;
table_sorted:
{ $$ = 0; }
| SORTED { $$ = 1; }
;
CF_ADDTO(conf, newtab)
newtab: TABLE SYM tab_sorted {
table: table_type TABLE SYM table_sorted {
struct rtable_config *cf;
cf = rt_new_table($2);
cf->sorted = $3;
cf = rt_new_table($3, $1);
cf->sorted = $4;
}
;
......
......@@ -35,11 +35,9 @@ struct cli;
struct fib_node {
struct fib_node *next; /* Next in hash chain */
struct fib_iterator *readers; /* List of readers of this node */
byte pxlen;
byte flags; /* User-defined */
byte x0, x1; /* User-defined */
u32 uid; /* Unique ID based on hash */
ip_addr prefix; /* In host order */
byte flags; /* User-defined, will be removed */
u32 uid; /* Unique ID based on hash, will be removed */
net_addr addr[0];
};
struct fib_iterator { /* See lib/slists.h for an explanation */
......@@ -50,7 +48,7 @@ struct fib_iterator { /* See lib/slists.h for an explanation */
uint hash;
};
typedef void (*fib_init_func)(struct fib_node *);
typedef void (*fib_init_fn)(void *);
struct fib {
pool *fib_pool; /* Pool holding all our data */
......@@ -59,15 +57,18 @@ struct fib {
uint hash_size; /* Number of hash table entries (a power of two) */
uint hash_order; /* Binary logarithm of hash_size */
uint hash_shift; /* 16 - hash_log */
uint addr_type; /* Type of address data stored in fib (NET_*) */
uint node_size; /* XXXX */
uint node_offset; /* XXXX */
uint entries; /* Number of entries */
uint entries_min, entries_max; /* Entry count limits (else start rehashing) */
fib_init_func init; /* Constructor */
fib_init_fn init; /* Constructor */
};
void fib_init(struct fib *, pool *, unsigned node_size, unsigned hash_order, fib_init_func init);
void *fib_find(struct fib *, ip_addr *, int); /* Find or return NULL if doesn't exist */
void *fib_get(struct fib *, ip_addr *, int); /* Find or create new if nonexistent */
void *fib_route(struct fib *, ip_addr, int); /* Longest-match routing lookup */
void fib_init(struct fib *f, pool *p, uint addr_type, uint node_size, uint node_offset, uint hash_order, fib_init_fn init);
void *fib_find(struct fib *, net_addr *); /* Find or return NULL if doesn't exist */
void *fib_get(struct fib *, net_addr *); /* Find or create new if nonexistent */
void *fib_route(struct fib *, net_addr *); /* Longest-match routing lookup */
void fib_delete(struct fib *, void *); /* Remove fib entry */
void fib_free(struct fib *); /* Destroy the fib */
void fib_check(struct fib *); /* Consistency check for debugging */
......@@ -77,7 +78,7 @@ struct fib_node *fit_get(struct fib *, struct fib_iterator *);
void fit_put(struct fib_iterator *, struct fib_node *);
void fit_put_next(struct fib *f, struct fib_iterator *i, struct fib_node *n, uint hpos);
/* XXXX: return user entries */
#define FIB_WALK(fib, z) do { \
struct fib_node *z, **ff = (fib)->hash_table; \
uint count = (fib)->hash_size; \
......@@ -126,6 +127,7 @@ struct rtable_config {
char *name;
struct rtable *table;
struct proto_config *krt_attached; /* Kernel syncer attached to this table */
uint addr_type; /* Type of address data stored in table (NET_*) */
int gc_max_ops; /* Maximum number of operations before GC is run */
int gc_min_time; /* Minimum time between two consecutive GC runs */
byte sorted; /* Routes of network are sorted according to rte_better() */
......@@ -136,6 +138,7 @@ typedef struct rtable {
struct fib fib;
char *name; /* Name of this table */
list hooks; /* List of announcement hooks */
uint addr_type; /* Type of address data stored in table (NET_*) */
int pipe_busy; /* Pipe loop detection */
int use_count; /* Number of protocols using this table */
struct hostcache *hostcache;
......@@ -160,8 +163,8 @@ typedef struct rtable {
#define RPS_RUNNING 2
typedef struct network {
struct fib_node n; /* FIB flags reserved for kernel syncer */
struct rte *routes; /* Available routes for this network */
struct fib_node n; /* FIB flags reserved for kernel syncer */
} net;
struct hostcache {
......@@ -262,14 +265,20 @@ void rt_commit(struct config *new, struct config *old);
void rt_lock_table(rtable *);
void rt_unlock_table(rtable *);
void rt_setup(pool *, rtable *, char *, struct rtable_config *);
static inline net *net_find(rtable *tab, ip_addr addr, unsigned len) { return (net *) fib_find(&tab->fib, &addr, len); }
static inline net *net_get(rtable *tab, ip_addr addr, unsigned len) { return (net *) fib_get(&tab->fib, &addr, len); }
static inline net *net_find(rtable *tab, net_addr *addr)