mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2025-04-20 22:14:38 +00:00
Merge commit 'e063365590b9b857a5bd0acfa519783eba639bbf' into stable-v3.0
This commit is contained in:
commit
5c3eff5645
@ -160,7 +160,7 @@ WHITE [ \t]
|
||||
|
||||
{DIGIT}+:{DIGIT}+ {
|
||||
uint len1 UNUSED, len2;
|
||||
u64 l;
|
||||
u64 l, v;
|
||||
char *e;
|
||||
|
||||
errno = 0;
|
||||
@ -172,76 +172,80 @@ WHITE [ \t]
|
||||
{
|
||||
len1 = 32;
|
||||
len2 = 16;
|
||||
cf_lval.i64 = (2ULL << 48) | (((u64) l) << len2);
|
||||
v = (2ULL << 48) | (((u64) l) << len2);
|
||||
}
|
||||
else
|
||||
{
|
||||
len1 = 16;
|
||||
len2 = 32;
|
||||
cf_lval.i64 = 0 | (((u64) l) << len2);
|
||||
v = 0 | (((u64) l) << len2);
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
l = bstrtoul10(e+1, &e);
|
||||
if (!e || *e || (errno == ERANGE) || (l >> len2))
|
||||
cf_error("Number out of range");
|
||||
cf_lval.i64 |= l;
|
||||
v |= l;
|
||||
|
||||
cf_lval.rd = rd_from_u64(v);
|
||||
return VPN_RD;
|
||||
}
|
||||
|
||||
[02]:{DIGIT}+:{DIGIT}+ {
|
||||
uint len1, len2;
|
||||
u64 l;
|
||||
u64 l, v;
|
||||
char *e;
|
||||
|
||||
if (yytext[0] == '0')
|
||||
{
|
||||
cf_lval.i64 = 0;
|
||||
len1 = 16;
|
||||
len2 = 32;
|
||||
v = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
cf_lval.i64 = 2ULL << 48;
|
||||
len1 = 32;
|
||||
len2 = 16;
|
||||
v = 2ULL << 48;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
l = bstrtoul10(yytext+2, &e);
|
||||
if (!e || (*e != ':') || (errno == ERANGE) || (l >> len1))
|
||||
cf_error("ASN out of range");
|
||||
cf_lval.i64 |= ((u64) l) << len2;
|
||||
v |= ((u64) l) << len2;
|
||||
|
||||
errno = 0;
|
||||
l = bstrtoul10(e+1, &e);
|
||||
if (!e || *e || (errno == ERANGE) || (l >> len2))
|
||||
cf_error("Number out of range");
|
||||
cf_lval.i64 |= l;
|
||||
v |= l;
|
||||
|
||||
cf_lval.rd = rd_from_u64(v);
|
||||
return VPN_RD;
|
||||
}
|
||||
|
||||
{DIGIT}+\.{DIGIT}+\.{DIGIT}+\.{DIGIT}+:{DIGIT}+ {
|
||||
unsigned long int l;
|
||||
ip4_addr ip4;
|
||||
u64 v;
|
||||
char *e;
|
||||
|
||||
cf_lval.i64 = 1ULL << 48;
|
||||
v = 1ULL << 48;
|
||||
|
||||
e = strchr(yytext, ':');
|
||||
*e++ = '\0';
|
||||
if (!ip4_pton(yytext, &ip4))
|
||||
cf_error("Invalid IPv4 address %s in Route Distinguisher", yytext);
|
||||
cf_lval.i64 |= ((u64) ip4_to_u32(ip4)) << 16;
|
||||
v |= ((u64) ip4_to_u32(ip4)) << 16;
|
||||
|
||||
errno = 0;
|
||||
l = bstrtoul10(e, &e);
|
||||
if (!e || *e || (errno == ERANGE) || (l >> 16))
|
||||
cf_error("Number out of range");
|
||||
cf_lval.i64 |= l;
|
||||
v |= l;
|
||||
|
||||
cf_lval.rd = rd_from_u64(v);
|
||||
return VPN_RD;
|
||||
}
|
||||
|
||||
|
@ -60,6 +60,7 @@ CF_DECLS
|
||||
uint i;
|
||||
u32 i32;
|
||||
u64 i64;
|
||||
vpn_rd rd;
|
||||
ip_addr a;
|
||||
ip4_addr ip4;
|
||||
ip6_addr ip6;
|
||||
@ -114,7 +115,7 @@ CF_DECLS
|
||||
%token <i> NUM ENUM_TOKEN
|
||||
%token <ip4> IP4
|
||||
%token <ip6> IP6
|
||||
%token <i64> VPN_RD
|
||||
%token <rd> VPN_RD
|
||||
%token <s> CF_SYM_KNOWN CF_SYM_UNDEFINED CF_SYM_METHOD_BARE CF_SYM_METHOD_ARGS
|
||||
%token <t> TEXT
|
||||
%token <bs> BYTETEXT
|
||||
|
@ -677,7 +677,7 @@ fipa:
|
||||
set_atom0:
|
||||
NUM { $$.type = T_INT; $$.val.i = $1; }
|
||||
| fipa { $$ = $1; }
|
||||
| VPN_RD { $$.type = T_RD; $$.val.ec = $1; }
|
||||
| VPN_RD { $$.type = T_RD; $$.val.rd = $1; }
|
||||
| ENUM_TOKEN { $$.type = pair_a($1); $$.val.i = pair_b($1); }
|
||||
| '(' term ')' {
|
||||
$$ = cf_eval_tmp($2, T_VOID);
|
||||
@ -837,7 +837,7 @@ constant:
|
||||
| TEXT { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_STRING, .val.s = $1, }); }
|
||||
| BYTETEXT { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_BYTESTRING, .val.bs = $1, }); }
|
||||
| fipa { $$ = f_new_inst(FI_CONSTANT, $1); }
|
||||
| VPN_RD { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_RD, .val.ec = $1, }); }
|
||||
| VPN_RD { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_RD, .val.rd = $1, }); }
|
||||
| net_ { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_NET, .val.net = $1, }); }
|
||||
| '[' ']' { $$ = f_new_inst(FI_CONSTANT, (struct f_val) { .type = T_SET, .val.t = NULL, }); }
|
||||
| '[' set_items ']' {
|
||||
|
@ -707,7 +707,7 @@ val_format(const struct f_val *v, buffer *buf)
|
||||
case T_QUAD: buffer_print(buf, "%R", v->val.i); return;
|
||||
case T_EC: ec_format(buf2, v->val.ec); buffer_print(buf, "%s", buf2); return;
|
||||
case T_LC: lc_format(buf2, v->val.lc); buffer_print(buf, "%s", buf2); return;
|
||||
case T_RD: rd_format(v->val.ec, buf2, 1024); buffer_print(buf, "%s", buf2); return;
|
||||
case T_RD: rd_format(v->val.rd, buf2, 1024); buffer_print(buf, "%s", buf2); return;
|
||||
case T_PREFIX_SET: trie_format(v->val.ti, buf); return;
|
||||
case T_SET: tree_format(v->val.t, buf); return;
|
||||
case T_ENUM: buffer_print(buf, "(enum %x)%u", v->type, v->val.i); return;
|
||||
|
@ -1063,7 +1063,7 @@
|
||||
METHOD_CONSTRUCTOR("rd");
|
||||
if (!net_is_vpn(v1.val.net))
|
||||
runtime( "VPN address expected" );
|
||||
RESULT(T_RD, ec, net_rd(v1.val.net));
|
||||
RESULT(T_RD, rd, net_rd(v1.val.net));
|
||||
}
|
||||
|
||||
/* Get first ASN from AS PATH */
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "lib/macro.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdalign.h>
|
||||
|
||||
/* Ugly structure offset handling macros */
|
||||
|
||||
|
110
lib/ip.h
110
lib/ip.h
@ -392,36 +392,6 @@ static inline ip6_addr ip6_hton(ip6_addr a)
|
||||
static inline ip6_addr ip6_ntoh(ip6_addr a)
|
||||
{ return _MI6(ntohl(_I0(a)), ntohl(_I1(a)), ntohl(_I2(a)), ntohl(_I3(a))); }
|
||||
|
||||
#define MPLS_MAX_LABEL 0x100000
|
||||
|
||||
#define MPLS_MAX_LABEL_STACK 8
|
||||
#define MPLS_MAX_LABEL_STRING MPLS_MAX_LABEL_STACK*12 + 5
|
||||
typedef struct mpls_label_stack {
|
||||
uint len;
|
||||
u32 stack[MPLS_MAX_LABEL_STACK];
|
||||
} mpls_label_stack;
|
||||
|
||||
static inline int ACCESS_READ(1, 2)
|
||||
mpls_get(const char *buf, int buflen, u32 *stack)
|
||||
{
|
||||
for (int i=0; (i<MPLS_MAX_LABEL_STACK) && (i*4+3 < buflen); i++)
|
||||
{
|
||||
u32 s = get_u32(buf + i*4);
|
||||
stack[i] = s >> 12;
|
||||
if (s & 0x100)
|
||||
return i+1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int
|
||||
mpls_put(char *buf, int len, u32 *stack)
|
||||
{
|
||||
for (int i=0; i<len; i++)
|
||||
put_u32(buf + i*4, stack[i] << 12 | (i+1 == len ? 0x100 : 0));
|
||||
|
||||
return len*4;
|
||||
}
|
||||
|
||||
/*
|
||||
* Unaligned data access (in network order)
|
||||
@ -481,4 +451,84 @@ int ip6_pton(const char *a, ip6_addr *o);
|
||||
|
||||
char *ip_scope_text(uint);
|
||||
|
||||
|
||||
/*
|
||||
* MPLS labels
|
||||
*/
|
||||
|
||||
#define MPLS_MAX_LABEL 0x100000
|
||||
|
||||
#define MPLS_MAX_LABEL_STACK 8
|
||||
#define MPLS_MAX_LABEL_STRING MPLS_MAX_LABEL_STACK*12 + 5
|
||||
typedef struct mpls_label_stack {
|
||||
uint len;
|
||||
u32 stack[MPLS_MAX_LABEL_STACK];
|
||||
} mpls_label_stack;
|
||||
|
||||
static inline int ACCESS_READ(1, 2)
|
||||
mpls_get(const char *buf, int buflen, u32 *stack)
|
||||
{
|
||||
for (int i=0; (i<MPLS_MAX_LABEL_STACK) && (i*4+3 < buflen); i++)
|
||||
{
|
||||
u32 s = get_u32(buf + i*4);
|
||||
stack[i] = s >> 12;
|
||||
if (s & 0x100)
|
||||
return i+1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int
|
||||
mpls_put(char *buf, int len, u32 *stack)
|
||||
{
|
||||
for (int i=0; i<len; i++)
|
||||
put_u32(buf + i*4, stack[i] << 12 | (i+1 == len ? 0x100 : 0));
|
||||
|
||||
return len*4;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* VPN route distinguishers
|
||||
*/
|
||||
|
||||
/* Using 2x u32 to avoid u64 alignment */
|
||||
typedef struct vpn_rd {
|
||||
u32 hi;
|
||||
u32 lo;
|
||||
} vpn_rd;
|
||||
|
||||
#define RD_NONE (vpn_rd){}
|
||||
|
||||
static inline vpn_rd rd_from_u64(u64 val)
|
||||
{ return (vpn_rd){.hi = val >> 32, .lo = val }; }
|
||||
|
||||
static inline u64 rd_to_u64(vpn_rd rd)
|
||||
{ return (((u64) rd.hi) << 32) | rd.lo; }
|
||||
|
||||
static inline int rd_equal(vpn_rd a, vpn_rd b)
|
||||
{ return a.hi == b.hi && a.lo == b.lo; }
|
||||
|
||||
static inline int rd_zero(vpn_rd a)
|
||||
{ return !a.hi && !a.lo; }
|
||||
|
||||
static inline int rd_nonzero(vpn_rd a)
|
||||
{ return a.hi || a.lo; }
|
||||
|
||||
static inline int rd_compare(vpn_rd a, vpn_rd b)
|
||||
{ return uint_cmp(a.hi, b.hi) ?: uint_cmp(a.lo, b.lo); }
|
||||
|
||||
static inline u64 rd_hash0(vpn_rd rd, u32 p, u64 acc)
|
||||
{ return u32_hash0(rd.hi, p, u32_hash0(rd.lo, p, acc)); }
|
||||
|
||||
static inline vpn_rd get_rd(const void *buf)
|
||||
{ return (vpn_rd) { .hi = get_u32(buf), .lo = get_u32(buf + 4) }; }
|
||||
|
||||
static inline void * put_rd(void *buf, vpn_rd rd)
|
||||
{
|
||||
put_u32(buf, rd.hi);
|
||||
put_u32(buf+4, rd.lo);
|
||||
return buf+8;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
19
lib/net.c
19
lib/net.c
@ -75,10 +75,27 @@ STATIC_ASSERT(sizeof(net_addr_ip6_sadr) == 40);
|
||||
STATIC_ASSERT(sizeof(net_addr_mpls) == 8);
|
||||
STATIC_ASSERT(sizeof(net_addr_aspa) == 8);
|
||||
|
||||
/* Ensure that all net_addr structures have the same alignment */
|
||||
STATIC_ASSERT(alignof(net_addr_ip4) == alignof(net_addr));
|
||||
STATIC_ASSERT(alignof(net_addr_ip6) == alignof(net_addr));
|
||||
STATIC_ASSERT(alignof(net_addr_vpn4) == alignof(net_addr));
|
||||
STATIC_ASSERT(alignof(net_addr_vpn6) == alignof(net_addr));
|
||||
STATIC_ASSERT(alignof(net_addr_roa4) == alignof(net_addr));
|
||||
STATIC_ASSERT(alignof(net_addr_roa6) == alignof(net_addr));
|
||||
STATIC_ASSERT(alignof(net_addr_flow4) == alignof(net_addr));
|
||||
STATIC_ASSERT(alignof(net_addr_flow6) == alignof(net_addr));
|
||||
STATIC_ASSERT(alignof(net_addr_flow4) == alignof(net_addr));
|
||||
STATIC_ASSERT(alignof(net_addr_flow6) == alignof(net_addr));
|
||||
STATIC_ASSERT(alignof(net_addr_ip6_sadr) == alignof(net_addr));
|
||||
STATIC_ASSERT(alignof(net_addr_mpls) == alignof(net_addr));
|
||||
STATIC_ASSERT(alignof(net_addr_aspa) == alignof(net_addr));
|
||||
|
||||
|
||||
int
|
||||
rd_format(const u64 rd, char *buf, int buflen)
|
||||
rd_format(const vpn_rd rd_, char *buf, int buflen)
|
||||
{
|
||||
u64 rd = rd_to_u64(rd_);
|
||||
|
||||
switch (rd >> 48)
|
||||
{
|
||||
case 0: return bsnprintf(buf, buflen, "%u:%u", (u32) (rd >> 32), (u32) rd);
|
||||
|
28
lib/net.h
28
lib/net.h
@ -51,7 +51,7 @@ typedef struct net_addr {
|
||||
u8 pxlen;
|
||||
u16 length;
|
||||
u8 data[20];
|
||||
u64 align[0];
|
||||
u32 align[0];
|
||||
} net_addr;
|
||||
|
||||
typedef struct net_addr_ip4 {
|
||||
@ -73,7 +73,7 @@ typedef struct net_addr_vpn4 {
|
||||
u8 pxlen;
|
||||
u16 length;
|
||||
ip4_addr prefix;
|
||||
u64 rd;
|
||||
vpn_rd rd;
|
||||
} net_addr_vpn4;
|
||||
|
||||
typedef struct net_addr_vpn6 {
|
||||
@ -82,7 +82,7 @@ typedef struct net_addr_vpn6 {
|
||||
u16 length;
|
||||
ip6_addr prefix;
|
||||
u32 padding;
|
||||
u64 rd;
|
||||
vpn_rd rd;
|
||||
} net_addr_vpn6;
|
||||
|
||||
typedef struct net_addr_roa4 {
|
||||
@ -224,10 +224,10 @@ static inline void net_fill_ip4(net_addr *a, ip4_addr prefix, uint 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)
|
||||
static inline void net_fill_vpn4(net_addr *a, ip4_addr prefix, uint pxlen, vpn_rd 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)
|
||||
static inline void net_fill_vpn6(net_addr *a, ip6_addr prefix, uint pxlen, vpn_rd rd)
|
||||
{ *(net_addr_vpn6 *)a = NET_ADDR_VPN6(prefix, pxlen, rd); }
|
||||
|
||||
static inline void net_fill_roa4(net_addr *a, ip4_addr prefix, uint pxlen, uint max_pxlen, u32 asn)
|
||||
@ -358,7 +358,7 @@ static inline uint net_pxlen(const net_addr *a)
|
||||
|
||||
ip_addr net_pxmask(const net_addr *a);
|
||||
|
||||
static inline u64 net_rd(const net_addr *a)
|
||||
static inline vpn_rd net_rd(const net_addr *a)
|
||||
{
|
||||
switch (a->type)
|
||||
{
|
||||
@ -367,7 +367,7 @@ static inline u64 net_rd(const net_addr *a)
|
||||
case NET_VPN6:
|
||||
return ((net_addr_vpn6 *)a)->rd;
|
||||
}
|
||||
return 0;
|
||||
return RD_NONE;
|
||||
}
|
||||
|
||||
|
||||
@ -428,10 +428,10 @@ 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; }
|
||||
{ return !a->pxlen && ip4_zero(a->prefix) && rd_zero(a->rd); }
|
||||
|
||||
static inline int net_zero_vpn6(const net_addr_vpn6 *a)
|
||||
{ return !a->pxlen && ip6_zero(a->prefix) && !a->rd; }
|
||||
{ return !a->pxlen && ip6_zero(a->prefix) && rd_zero(a->rd); }
|
||||
|
||||
static inline int net_zero_roa4(const net_addr_roa4 *a)
|
||||
{ return !a->pxlen && ip4_zero(a->prefix) && !a->max_pxlen && !a->asn; }
|
||||
@ -459,10 +459,10 @@ static inline int net_compare_ip6(const net_addr_ip6 *a, const net_addr_ip6 *b)
|
||||
{ return ip6_compare(a->prefix, b->prefix) ?: uint_cmp(a->pxlen, b->pxlen); }
|
||||
|
||||
static inline int net_compare_vpn4(const net_addr_vpn4 *a, const net_addr_vpn4 *b)
|
||||
{ return u64_cmp(a->rd, b->rd) ?: ip4_compare(a->prefix, b->prefix) ?: uint_cmp(a->pxlen, b->pxlen); }
|
||||
{ return rd_compare(a->rd, b->rd) ?: ip4_compare(a->prefix, b->prefix) ?: uint_cmp(a->pxlen, b->pxlen); }
|
||||
|
||||
static inline int net_compare_vpn6(const net_addr_vpn6 *a, const net_addr_vpn6 *b)
|
||||
{ return u64_cmp(a->rd, b->rd) ?: ip6_compare(a->prefix, b->prefix) ?: uint_cmp(a->pxlen, b->pxlen); }
|
||||
{ return rd_compare(a->rd, b->rd) ?: ip6_compare(a->prefix, b->prefix) ?: uint_cmp(a->pxlen, b->pxlen); }
|
||||
|
||||
static inline int net_compare_roa4(const net_addr_roa4 *a, const net_addr_roa4 *b)
|
||||
{ return ip4_compare(a->prefix, b->prefix) ?: uint_cmp(a->pxlen, b->pxlen) ?: uint_cmp(a->max_pxlen, b->max_pxlen) ?: uint_cmp(a->asn, b->asn); }
|
||||
@ -544,13 +544,13 @@ static inline u32 net_hash_ip6(const net_addr_ip6 *n)
|
||||
static inline u32 net_hash_vpn4(const net_addr_vpn4 *n)
|
||||
{
|
||||
u64 acc = ip4_hash0(n->prefix, HASH_PARAM, 0) ^ (n->pxlen << 26);
|
||||
return hash_value(u64_hash0(n->rd, HASH_PARAM, acc));
|
||||
return hash_value(rd_hash0(n->rd, HASH_PARAM, acc));
|
||||
}
|
||||
|
||||
static inline u32 net_hash_vpn6(const net_addr_vpn6 *n)
|
||||
{
|
||||
u64 acc = ip6_hash0(n->prefix, HASH_PARAM, 0) ^ (n->pxlen << 26);
|
||||
return hash_value(u64_hash0(n->rd, HASH_PARAM, acc));
|
||||
return hash_value(rd_hash0(n->rd, HASH_PARAM, acc));
|
||||
}
|
||||
|
||||
static inline u32 net_hash_roa4(const net_addr_roa4 *n)
|
||||
@ -655,7 +655,7 @@ void net_normalize(net_addr *N);
|
||||
|
||||
int net_classify(const net_addr *N);
|
||||
int net_format(const net_addr *N, char *buf, int buflen) ACCESS_WRITE(2, 3);
|
||||
int rd_format(const u64 rd, char *buf, int buflen) ACCESS_WRITE(2, 3);
|
||||
int rd_format(const vpn_rd rd, char *buf, int buflen) ACCESS_WRITE(2, 3);
|
||||
|
||||
static inline int ipa_in_px4(ip4_addr a, ip4_addr prefix, uint pxlen)
|
||||
{ return ip4_zero(ip4_and(ip4_xor(a, prefix), ip4_mkmask(pxlen))); }
|
||||
|
@ -35,6 +35,7 @@ union bval_long {
|
||||
|
||||
u64 ec;
|
||||
lcomm lc;
|
||||
vpn_rd rd;
|
||||
ip_addr ip;
|
||||
const net_addr *net;
|
||||
const char *s;
|
||||
|
@ -1014,7 +1014,7 @@ babel_send_update_(struct babel_iface *ifa, btime changed, struct fib *rtable)
|
||||
|
||||
/* Our own seqno might have changed, in which case we update the routes we
|
||||
originate. */
|
||||
if ((e->router_id == p->router_id) && (e->seqno < p->update_seqno))
|
||||
if ((e->router_id == p->router_id) && gt_mod64k(p->update_seqno, e->seqno))
|
||||
{
|
||||
e->seqno = p->update_seqno;
|
||||
e->updated = current_time();
|
||||
|
@ -1820,7 +1820,7 @@ bgp_encode_nlri_vpn4(struct bgp_write_state *s, struct bgp_bucket *buck, byte *b
|
||||
bgp_encode_mpls_labels(s, s->mpls_labels, &pos, &size, pos - 1);
|
||||
|
||||
/* Encode route distinguisher */
|
||||
put_u64(pos, net->rd);
|
||||
put_rd(pos, net->rd);
|
||||
ADVANCE(pos, size, 8);
|
||||
|
||||
/* Encode prefix body */
|
||||
@ -1869,7 +1869,7 @@ bgp_decode_nlri_vpn4(struct bgp_parse_state *s, byte *pos, uint len, ea_list *a)
|
||||
if (l < 64)
|
||||
bgp_parse_error(s, 1);
|
||||
|
||||
u64 rd = get_u64(pos);
|
||||
vpn_rd rd = get_rd(pos);
|
||||
ADVANCE(pos, len, 8);
|
||||
l -= 64;
|
||||
|
||||
@ -1918,7 +1918,7 @@ bgp_encode_nlri_vpn6(struct bgp_write_state *s, struct bgp_bucket *buck, byte *b
|
||||
bgp_encode_mpls_labels(s, s->mpls_labels, &pos, &size, pos - 1);
|
||||
|
||||
/* Encode route distinguisher */
|
||||
put_u64(pos, net->rd);
|
||||
put_rd(pos, net->rd);
|
||||
ADVANCE(pos, size, 8);
|
||||
|
||||
/* Encode prefix body */
|
||||
@ -1967,7 +1967,7 @@ bgp_decode_nlri_vpn6(struct bgp_parse_state *s, byte *pos, uint len, ea_list *a)
|
||||
if (l < 64)
|
||||
bgp_parse_error(s, 1);
|
||||
|
||||
u64 rd = get_u64(pos);
|
||||
vpn_rd rd = get_rd(pos);
|
||||
ADVANCE(pos, len, 8);
|
||||
l -= 64;
|
||||
|
||||
|
@ -175,14 +175,14 @@ l3vpn_rt_notify(struct proto *P, struct channel *c0, const net_addr *n0, rte *ne
|
||||
|
||||
case NET_VPN4:
|
||||
net_fill_ip4(n, net4_prefix(n0), net4_pxlen(n0));
|
||||
src = rt_get_source(&p->p, ((const net_addr_vpn4 *) n0)->rd);
|
||||
src = rt_get_source(&p->p, rd_to_u64(((const net_addr_vpn4 *) n0)->rd));
|
||||
dst = p->ip4_channel;
|
||||
export = 0;
|
||||
break;
|
||||
|
||||
case NET_VPN6:
|
||||
net_fill_ip6(n, net6_prefix(n0), net6_pxlen(n0));
|
||||
src = rt_get_source(&p->p, ((const net_addr_vpn6 *) n0)->rd);
|
||||
src = rt_get_source(&p->p, rd_to_u64(((const net_addr_vpn6 *) n0)->rd));
|
||||
dst = p->ip6_channel;
|
||||
export = 0;
|
||||
break;
|
||||
@ -347,7 +347,7 @@ l3vpn_postconfig(struct proto_config *CF)
|
||||
if (!proto_cf_find_channel(CF, NET_MPLS))
|
||||
cf_error("MPLS channel not specified");
|
||||
|
||||
if (!cf->rd)
|
||||
if (rd_zero(cf->rd))
|
||||
cf_error("Route distinguisher not specified");
|
||||
|
||||
if (!cf->import_target && !cf->export_target)
|
||||
@ -435,7 +435,7 @@ l3vpn_reconfigure(struct proto *P, struct proto_config *CF)
|
||||
!proto_configure_mpls_channel(P, CF, RTS_L3VPN))
|
||||
return 0;
|
||||
|
||||
if (p->rd != cf->rd)
|
||||
if (!rd_equal(p->rd, cf->rd))
|
||||
return 0;
|
||||
|
||||
int import_changed = !same_tree(p->import_target, cf->import_target);
|
||||
|
@ -13,7 +13,7 @@
|
||||
struct l3vpn_config {
|
||||
struct proto_config c;
|
||||
|
||||
u64 rd;
|
||||
vpn_rd rd;
|
||||
struct f_tree *import_target;
|
||||
struct f_tree *export_target;
|
||||
};
|
||||
@ -25,7 +25,7 @@ struct l3vpn_proto {
|
||||
struct channel *vpn4_channel;
|
||||
struct channel *vpn6_channel;
|
||||
|
||||
u64 rd;
|
||||
vpn_rd rd;
|
||||
struct f_tree *import_target;
|
||||
struct f_tree *export_target;
|
||||
u32 *export_target_data;
|
||||
|
@ -406,30 +406,6 @@ krt_replace_rte(struct krt_proto *p, const net_addr *n UNUSED, rte *new, const r
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* krt_assume_onlink - check if routes on interface are considered onlink
|
||||
* @iface: The interface of the next hop
|
||||
* @ipv6: Switch to only consider IPv6 or IPv4 addresses.
|
||||
*
|
||||
* The BSD kernel does not support an onlink flag. If the interface has only
|
||||
* host addresses configured, all routes should be considered as onlink and
|
||||
* the function returns 1.
|
||||
*/
|
||||
static int
|
||||
krt_assume_onlink(struct iface *iface, int ipv6)
|
||||
{
|
||||
const u8 type = ipv6 ? NET_IP6 : NET_IP4;
|
||||
|
||||
struct ifa *ifa;
|
||||
WALK_LIST(ifa, iface->addrs)
|
||||
{
|
||||
if ((ifa->prefix.type == type) && !(ifa->flags & IA_HOST))
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define SKIP(ARG...) do { DBG("KRT: Ignoring route - " ARG); return; } while(0)
|
||||
|
||||
static void
|
||||
|
@ -5,6 +5,7 @@ CONFIG_AUTO_ROUTES Device routes are added automagically by the kernel
|
||||
CONFIG_SELF_CONSCIOUS We're able to recognize whether route was installed by us
|
||||
CONFIG_MULTIPLE_TABLES The kernel supports multiple routing tables
|
||||
CONFIG_SINGLE_ROUTE There is only one route per network
|
||||
CONFIG_ASSUME_ONLINK Assume ONLINK flag on scanned routes based on a heuristic
|
||||
|
||||
CONFIG_MC_PROPER_SRC Multicast packets have source address according to socket saddr field
|
||||
CONFIG_SKIP_MC_BIND Don't call bind on multicast socket (def for *BSD)
|
||||
|
@ -10,6 +10,7 @@
|
||||
#define CONFIG_SELF_CONSCIOUS
|
||||
#define CONFIG_MULTIPLE_TABLES
|
||||
#define CONFIG_SINGLE_ROUTE
|
||||
#define CONFIG_ASSUME_ONLINK
|
||||
|
||||
#define CONFIG_SKIP_MC_BIND
|
||||
#define CONFIG_NO_IFACE_BIND
|
||||
|
@ -10,6 +10,7 @@
|
||||
#define CONFIG_SELF_CONSCIOUS
|
||||
#define CONFIG_MULTIPLE_TABLES
|
||||
#define CONFIG_SINGLE_ROUTE
|
||||
#define CONFIG_ASSUME_ONLINK
|
||||
|
||||
#define CONFIG_SKIP_MC_BIND
|
||||
#define CONFIG_NO_IFACE_BIND
|
||||
|
@ -915,6 +915,11 @@ nl_parse_multipath(struct nl_parse_state *s, struct krt_proto *p, const net_addr
|
||||
|
||||
if (ipa_nonzero(rv->gw))
|
||||
{
|
||||
#ifdef CONFIG_ASSUME_ONLINK
|
||||
if (krt_assume_onlink(rv->iface, ipa_is_ip6(rv->gw)))
|
||||
rv->flags |= RNF_ONLINK;
|
||||
#endif
|
||||
|
||||
neighbor *nbr;
|
||||
nbr = neigh_find(&p->p, rv->gw, rv->iface,
|
||||
(rv->flags & RNF_ONLINK) ? NEF_ONLINK : 0);
|
||||
@ -1858,6 +1863,11 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h)
|
||||
if ((i->rtm_family == AF_INET6) && ipa_in_netX(nhad.nh.gw, (net_addr *) &sit))
|
||||
return;
|
||||
|
||||
#ifdef CONFIG_ASSUME_ONLINK
|
||||
if (krt_assume_onlink(ra->nh.iface, ipa_is_ip6(ra->nh.gw)))
|
||||
ra->nh.flags |= RNF_ONLINK;
|
||||
#endif
|
||||
|
||||
neighbor *nbr;
|
||||
nbr = neigh_find(&p->p, nhad.nh.gw, nhad.nh.iface,
|
||||
(nhad.nh.flags & RNF_ONLINK) ? NEF_ONLINK : 0);
|
||||
|
@ -647,6 +647,30 @@ krt_scan_timer_kick(struct krt_proto *p)
|
||||
tm_start(p->scan_timer, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* krt_assume_onlink - check if routes on interface are considered onlink
|
||||
* @iface: The interface of the next hop
|
||||
* @ipv6: Switch to only consider IPv6 or IPv4 addresses.
|
||||
*
|
||||
* The BSD kernel does not support an onlink flag. If the interface has only
|
||||
* host addresses configured, all routes should be considered as onlink and
|
||||
* the function returns 1. This is used when CONFIG_ASSUME_ONLINK is set.
|
||||
*/
|
||||
int
|
||||
krt_assume_onlink(struct iface *iface, int ipv6)
|
||||
{
|
||||
const u8 type = ipv6 ? NET_IP6 : NET_IP4;
|
||||
|
||||
struct ifa *ifa;
|
||||
WALK_LIST(ifa, iface->addrs)
|
||||
{
|
||||
if ((ifa->prefix.type == type) && !(ifa->flags & IA_HOST))
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Updates
|
||||
|
@ -82,6 +82,7 @@ void kif_request_scan(void);
|
||||
void krt_use_shared_scan(void);
|
||||
void krt_got_route(struct krt_proto *p, struct rte *e, s8 src);
|
||||
void krt_got_route_async(struct krt_proto *p, struct rte *e, int new, s8 src);
|
||||
int krt_assume_onlink(struct iface *iface, int ipv6);
|
||||
|
||||
static inline int
|
||||
krt_get_sync_error(struct krt_proto *p, struct rte *e)
|
||||
|
Loading…
x
Reference in New Issue
Block a user