Several minor fixes
This commit is contained in:
parent
d311368bc5
commit
62e64905b7
22 changed files with 251 additions and 259 deletions
|
@ -124,39 +124,56 @@ include ^{WHITE}*include{WHITE}*\".*\"{WHITE}*;
|
||||||
}
|
}
|
||||||
|
|
||||||
[02]:{DIGIT}+:{DIGIT}+ {
|
[02]:{DIGIT}+:{DIGIT}+ {
|
||||||
|
unsigned long int l, len1, len2;
|
||||||
char *e;
|
char *e;
|
||||||
unsigned long int l;
|
|
||||||
|
|
||||||
if (yytext[0] == '0')
|
if (yytext[0] == '0')
|
||||||
|
{
|
||||||
cf_lval.i64 = 0;
|
cf_lval.i64 = 0;
|
||||||
|
len1 = 16;
|
||||||
|
len2 = 32;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
cf_lval.i64 = 0x2000000000000ULL;
|
{
|
||||||
|
cf_lval.i64 = 2ULL << 48;
|
||||||
|
len1 = 32;
|
||||||
|
len2 = 16;
|
||||||
|
}
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
l = strtoul(yytext+2, &e, 10);
|
l = strtoul(yytext+2, &e, 10);
|
||||||
if (e && (*e != ':') || errno == ERANGE || (yytext[0] == '0') && (l >= (1<<16)))
|
if (e && (*e != ':') || (errno == ERANGE) || (l >> len1))
|
||||||
cf_error("ASN out of range");
|
cf_error("ASN out of range");
|
||||||
cf_lval.i64 |= (((u64) l) << 32);
|
cf_lval.i64 |= ((u64) l) << len2;
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
l = strtoul(e+1, &e, 10);
|
l = strtoul(e+1, &e, 10);
|
||||||
if (e && *e || errno == ERANGE || (yytext[0] == '2') && (l >= (1<<16)))
|
if (e && *e || (errno == ERANGE) || (l >> len2))
|
||||||
cf_error("Assigned number out of range");
|
cf_error("Number out of range");
|
||||||
cf_lval.i64 |= l;
|
cf_lval.i64 |= l;
|
||||||
|
|
||||||
return VPN_RD;
|
return VPN_RD;
|
||||||
}
|
}
|
||||||
|
|
||||||
1:{DIGIT}+\.{DIGIT}+\.{DIGIT}+\.{DIGIT}+:{DIGIT}+ {
|
1:{DIGIT}+\.{DIGIT}+\.{DIGIT}+\.{DIGIT}+:{DIGIT}+ {
|
||||||
unsigned long int l;
|
unsigned long int l;
|
||||||
char *e = strchr(yytext+2, ':');
|
|
||||||
*e++ = '\0';
|
|
||||||
ip4_addr ip4;
|
ip4_addr ip4;
|
||||||
|
char *e;
|
||||||
|
|
||||||
|
cf_lval.i64 = 1ULL << 48;
|
||||||
|
|
||||||
|
e = strchr(yytext+2, ':');
|
||||||
|
*e++ = '\0';
|
||||||
if (!ip4_pton(yytext+2, &ip4))
|
if (!ip4_pton(yytext+2, &ip4))
|
||||||
cf_error("Invalid IPv4 address %s in Route Distinguisher", yytext+2);
|
cf_error("Invalid IPv4 address %s in Route Distinguisher", yytext+2);
|
||||||
|
cf_lval.i64 |= ((u64) ip4_to_u32(ip4)) << 16;
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
l = strtoul(e, &e, 10);
|
l = strtoul(e, &e, 10);
|
||||||
if (e && *e || errno == ERANGE || (l >= (1<<16)))
|
if (e && *e || (errno == ERANGE) || (l >> 16))
|
||||||
cf_error("Assigned number out of range");
|
cf_error("Number out of range");
|
||||||
cf_lval.i64 = (1ULL<<48) | (((u64)ip4_to_u32(ip4)) << 16) | ((u64)l);
|
cf_lval.i64 |= l;
|
||||||
|
|
||||||
return VPN_RD;
|
return VPN_RD;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -203,13 +203,13 @@ net_ip6_: IP6 '/' NUM
|
||||||
net_vpn4_: VPN_RD net_ip4_
|
net_vpn4_: VPN_RD net_ip4_
|
||||||
{
|
{
|
||||||
$$ = cfg_alloc(sizeof(net_addr_vpn4));
|
$$ = cfg_alloc(sizeof(net_addr_vpn4));
|
||||||
net_fill_vpn4($$, ((net_addr_ip4 *)&$2)->prefix, $2.pxlen, $1);
|
net_fill_vpn4($$, net4_prefix(&$2), net4_pxlen(&$2), $1);
|
||||||
}
|
}
|
||||||
|
|
||||||
net_vpn6_: VPN_RD net_ip6_
|
net_vpn6_: VPN_RD net_ip6_
|
||||||
{
|
{
|
||||||
$$ = cfg_alloc(sizeof(net_addr_vpn6));
|
$$ = cfg_alloc(sizeof(net_addr_vpn6));
|
||||||
net_fill_vpn6($$, ((net_addr_ip6 *)&$2)->prefix, $2.pxlen, $1);
|
net_fill_vpn6($$, net6_prefix(&$2), net6_pxlen(&$2), $1);
|
||||||
}
|
}
|
||||||
|
|
||||||
net_roa4_: net_ip4_ MAX NUM AS NUM
|
net_roa4_: net_ip4_ MAX NUM AS NUM
|
||||||
|
@ -229,8 +229,8 @@ net_roa6_: net_ip6_ MAX NUM AS NUM
|
||||||
};
|
};
|
||||||
|
|
||||||
net_ip_: net_ip4_ | net_ip6_ ;
|
net_ip_: net_ip4_ | net_ip6_ ;
|
||||||
net_roa_: net_roa4_ | net_roa6_ ;
|
|
||||||
net_vpn_: net_vpn4_ | net_vpn6_ ;
|
net_vpn_: net_vpn4_ | net_vpn6_ ;
|
||||||
|
net_roa_: net_roa4_ | net_roa6_ ;
|
||||||
|
|
||||||
net_:
|
net_:
|
||||||
net_ip_ { $$ = cfg_alloc($1.length); net_copy($$, &($1)); }
|
net_ip_ { $$ = cfg_alloc($1.length); net_copy($$, &($1)); }
|
||||||
|
@ -297,8 +297,9 @@ label_stack:
|
||||||
label_stack_start
|
label_stack_start
|
||||||
| label_stack '/' NUM {
|
| label_stack '/' NUM {
|
||||||
if ($1[0] >= MPLS_MAX_LABEL_STACK)
|
if ($1[0] >= MPLS_MAX_LABEL_STACK)
|
||||||
cf_error("Too many labels in stack.");
|
cf_error("Too many labels in stack");
|
||||||
$1[++$1[0]] = $3;
|
$1[0]++;
|
||||||
|
$1[*$1] = $3;
|
||||||
$$ = $1;
|
$$ = $1;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
|
@ -4140,12 +4140,12 @@ return packets as undeliverable if they are in your IP block, you don't have any
|
||||||
specific destination for them and you don't want to send them out through the
|
specific destination for them and you don't want to send them out through the
|
||||||
default route to prevent routing loops).
|
default route to prevent routing loops).
|
||||||
|
|
||||||
<p>There are five types of static routes: `classical' routes telling to forward
|
<p>There are four types of static routes: `classical' routes telling to forward
|
||||||
packets to a neighboring router (single path or multipath, possibly weighted),
|
packets to a neighboring router (single path or multipath, possibly weighted),
|
||||||
device routes specifying forwarding to hosts on a
|
device routes specifying forwarding to hosts on a directly connected network,
|
||||||
directly connected network, recursive routes computing their nexthops by doing
|
recursive routes computing their nexthops by doing route table lookups for a
|
||||||
route table lookups for a given IP, and special routes (sink, blackhole etc.)
|
given IP, and special routes (sink, blackhole etc.) which specify a special
|
||||||
which specify a special action to be done instead of forwarding the packet.
|
action to be done instead of forwarding the packet.
|
||||||
|
|
||||||
<p>When the particular destination is not available (the interface is down or
|
<p>When the particular destination is not available (the interface is down or
|
||||||
the next hop of the route is not a neighbor at the moment), Static just
|
the next hop of the route is not a neighbor at the moment), Static just
|
||||||
|
|
|
@ -174,9 +174,9 @@ void val_format(struct f_val v, buffer *buf);
|
||||||
#define SA_PROTO 4
|
#define SA_PROTO 4
|
||||||
#define SA_SOURCE 5
|
#define SA_SOURCE 5
|
||||||
#define SA_SCOPE 6
|
#define SA_SCOPE 6
|
||||||
#define SA_DEST 8
|
#define SA_DEST 7
|
||||||
#define SA_IFNAME 9
|
#define SA_IFNAME 8
|
||||||
#define SA_IFINDEX 10
|
#define SA_IFINDEX 9
|
||||||
|
|
||||||
|
|
||||||
struct f_tree {
|
struct f_tree {
|
||||||
|
|
|
@ -15,4 +15,6 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define allocz(len) ({ void *_x = alloca(len); memset(_x, 0, len); _x; })
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
19
lib/net.c
19
lib/net.c
|
@ -69,21 +69,20 @@ net_format(const net_addr *N, char *buf, int buflen)
|
||||||
case NET_VPN4:
|
case NET_VPN4:
|
||||||
switch (n->vpn4.rd >> 48)
|
switch (n->vpn4.rd >> 48)
|
||||||
{
|
{
|
||||||
case 0: return bsnprintf(buf, buflen, "0:%u:%u %I4/%d", (u32) (n->vpn4.rd >> 32), (u32) n->vpn4.rd, n->vpn4.prefix, n->vpn4.pxlen);
|
case 0: return bsnprintf(buf, buflen, "0:%u:%u %I4/%d", (u32) (n->vpn4.rd >> 32), (u32) n->vpn4.rd, n->vpn4.prefix, n->vpn4.pxlen);
|
||||||
case 1: return bsnprintf(buf, buflen, "1:%I4:%u %I4/%d", ip4_from_u32(n->vpn4.rd >> 16), (u32) (n->vpn4.rd & 0xffff), n->vpn4.prefix, n->vpn4.pxlen);
|
case 1: return bsnprintf(buf, buflen, "1:%I4:%u %I4/%d", ip4_from_u32(n->vpn4.rd >> 16), (u32) (n->vpn4.rd & 0xffff), n->vpn4.prefix, n->vpn4.pxlen);
|
||||||
case 2: return bsnprintf(buf, buflen, "2:%u:%u %I4/%d", (u32) (n->vpn4.rd >> 16), (u32) (n->vpn4.rd & 0xffff), n->vpn4.prefix, n->vpn4.pxlen);
|
case 2: return bsnprintf(buf, buflen, "2:%u:%u %I4/%d", (u32) (n->vpn4.rd >> 16), (u32) (n->vpn4.rd & 0xffff), n->vpn4.prefix, n->vpn4.pxlen);
|
||||||
|
default: return bsnprintf(buf, buflen, "X:%08x:%08x %I4/%d", (u32) (n->vpn4.rd >> 32), (u32) n->vpn4.rd, n->vpn4.prefix, n->vpn4.pxlen);
|
||||||
}
|
}
|
||||||
return bsnprintf(buf, buflen, "X: %016x %I4/%d", (n->vpn4.rd), n->vpn4.prefix, n->vpn4.pxlen);
|
|
||||||
|
|
||||||
/* XXX: RD format is specified for VPN4; not found any for VPN6, reusing the same as for VPN4. */
|
|
||||||
case NET_VPN6:
|
case NET_VPN6:
|
||||||
|
/* XXX: RD format is specified for VPN4; not found any for VPN6, reusing the same as for VPN4 */
|
||||||
switch (n->vpn6.rd >> 48)
|
switch (n->vpn6.rd >> 48)
|
||||||
{
|
{
|
||||||
case 0: return bsnprintf(buf, buflen, "0:%u:%u %I6/%d", (u32) (n->vpn6.rd >> 32), (u32) n->vpn6.rd, n->vpn6.prefix, n->vpn6.pxlen);
|
case 0: return bsnprintf(buf, buflen, "0:%u:%u %I6/%d", (u32) (n->vpn6.rd >> 32), (u32) n->vpn6.rd, n->vpn6.prefix, n->vpn6.pxlen);
|
||||||
case 1: return bsnprintf(buf, buflen, "1:%I4:%u %I6/%d", ip4_from_u32(n->vpn6.rd >> 16), (u32) (n->vpn6.rd & 0xffff), n->vpn6.prefix, n->vpn6.pxlen);
|
case 1: return bsnprintf(buf, buflen, "1:%I4:%u %I6/%d", ip4_from_u32(n->vpn6.rd >> 16), (u32) (n->vpn6.rd & 0xffff), n->vpn6.prefix, n->vpn6.pxlen);
|
||||||
case 2: return bsnprintf(buf, buflen, "2:%u:%u %I6/%d", (u32) (n->vpn6.rd >> 16), (u32) (n->vpn6.rd & 0xffff), n->vpn6.prefix, n->vpn6.pxlen);
|
case 2: return bsnprintf(buf, buflen, "2:%u:%u %I6/%d", (u32) (n->vpn6.rd >> 16), (u32) (n->vpn6.rd & 0xffff), n->vpn6.prefix, n->vpn6.pxlen);
|
||||||
|
default: return bsnprintf(buf, buflen, "X:%08x:%08x %I6/%d", (u32) (n->vpn6.rd >> 32), (u32) n->vpn6.rd, n->vpn6.prefix, n->vpn6.pxlen);
|
||||||
}
|
}
|
||||||
return bsnprintf(buf, buflen, "X: %016x %I6/%d", (n->vpn6.rd), n->vpn6.prefix, n->vpn6.pxlen);
|
|
||||||
case NET_ROA4:
|
case NET_ROA4:
|
||||||
return bsnprintf(buf, buflen, "%I4/%u-%u AS%u", n->roa4.prefix, n->roa4.pxlen, n->roa4.max_pxlen, n->roa4.asn);
|
return bsnprintf(buf, buflen, "%I4/%u-%u AS%u", n->roa4.prefix, n->roa4.pxlen, n->roa4.max_pxlen, n->roa4.asn);
|
||||||
case NET_ROA6:
|
case NET_ROA6:
|
||||||
|
|
16
lib/net.h
16
lib/net.h
|
@ -306,6 +306,9 @@ static inline int net_equal_flow4(const net_addr_flow4 *a, const net_addr_flow4
|
||||||
static inline int net_equal_flow6(const net_addr_flow6 *a, const net_addr_flow6 *b)
|
static inline int net_equal_flow6(const net_addr_flow6 *a, const net_addr_flow6 *b)
|
||||||
{ return net_equal((const net_addr *) a, (const net_addr *) b); }
|
{ return net_equal((const net_addr *) a, (const net_addr *) b); }
|
||||||
|
|
||||||
|
static inline int net_equal_mpls(const net_addr_mpls *a, const net_addr_mpls *b)
|
||||||
|
{ return !memcmp(a, b, sizeof(net_addr_mpls)); }
|
||||||
|
|
||||||
|
|
||||||
static inline int net_equal_prefix_roa4(const net_addr_roa4 *a, const net_addr_roa4 *b)
|
static inline int net_equal_prefix_roa4(const net_addr_roa4 *a, const net_addr_roa4 *b)
|
||||||
{ return ip4_equal(a->prefix, b->prefix) && (a->pxlen == b->pxlen); }
|
{ return ip4_equal(a->prefix, b->prefix) && (a->pxlen == b->pxlen); }
|
||||||
|
@ -313,8 +316,6 @@ static inline int net_equal_prefix_roa4(const net_addr_roa4 *a, const net_addr_r
|
||||||
static inline int net_equal_prefix_roa6(const net_addr_roa6 *a, const net_addr_roa6 *b)
|
static inline int net_equal_prefix_roa6(const net_addr_roa6 *a, const net_addr_roa6 *b)
|
||||||
{ return ip6_equal(a->prefix, b->prefix) && (a->pxlen == b->pxlen); }
|
{ return ip6_equal(a->prefix, b->prefix) && (a->pxlen == b->pxlen); }
|
||||||
|
|
||||||
static inline int net_equal_mpls(const net_addr_mpls *a, const net_addr_mpls *b)
|
|
||||||
{ return !memcmp(a, b, sizeof(net_addr_mpls)); }
|
|
||||||
|
|
||||||
static inline int net_zero_ip4(const net_addr_ip4 *a)
|
static inline int net_zero_ip4(const net_addr_ip4 *a)
|
||||||
{ return !a->pxlen && ip4_zero(a->prefix); }
|
{ return !a->pxlen && ip4_zero(a->prefix); }
|
||||||
|
@ -404,16 +405,17 @@ static inline void net_copy_flow6(net_addr_flow6 *dst, const net_addr_flow6 *src
|
||||||
static inline void net_copy_mpls(net_addr_mpls *dst, const net_addr_mpls *src)
|
static inline void net_copy_mpls(net_addr_mpls *dst, const net_addr_mpls *src)
|
||||||
{ memcpy(dst, src, sizeof(net_addr_mpls)); }
|
{ memcpy(dst, src, sizeof(net_addr_mpls)); }
|
||||||
|
|
||||||
|
|
||||||
|
/* XXXX */
|
||||||
|
static inline u32 u64_hash(u64 a)
|
||||||
|
{ return u32_hash(a); }
|
||||||
|
|
||||||
static inline u32 net_hash_ip4(const net_addr_ip4 *n)
|
static inline u32 net_hash_ip4(const net_addr_ip4 *n)
|
||||||
{ return ip4_hash(n->prefix) ^ ((u32) n->pxlen << 26); }
|
{ return ip4_hash(n->prefix) ^ ((u32) n->pxlen << 26); }
|
||||||
|
|
||||||
static inline u32 net_hash_ip6(const net_addr_ip6 *n)
|
static inline u32 net_hash_ip6(const net_addr_ip6 *n)
|
||||||
{ return ip6_hash(n->prefix) ^ ((u32) n->pxlen << 26); }
|
{ return ip6_hash(n->prefix) ^ ((u32) n->pxlen << 26); }
|
||||||
|
|
||||||
/* XXXX */
|
|
||||||
static inline u32 u64_hash(u64 a)
|
|
||||||
{ return u32_hash(a); }
|
|
||||||
|
|
||||||
static inline u32 net_hash_vpn4(const net_addr_vpn4 *n)
|
static inline u32 net_hash_vpn4(const net_addr_vpn4 *n)
|
||||||
{ return ip4_hash(n->prefix) ^ ((u32) n->pxlen << 26) ^ u64_hash(n->rd); }
|
{ return ip4_hash(n->prefix) ^ ((u32) n->pxlen << 26) ^ u64_hash(n->rd); }
|
||||||
|
|
||||||
|
@ -452,7 +454,7 @@ static inline int net_validate_ip6(const net_addr_ip6 *n)
|
||||||
|
|
||||||
static inline int net_validate_mpls(const net_addr_mpls *n)
|
static inline int net_validate_mpls(const net_addr_mpls *n)
|
||||||
{
|
{
|
||||||
return n->label < (1<<20);
|
return n->label < (1 << 20);
|
||||||
}
|
}
|
||||||
|
|
||||||
int net_validate(const net_addr *N);
|
int net_validate(const net_addr *N);
|
||||||
|
|
|
@ -390,11 +390,11 @@ typedef struct rta {
|
||||||
#define RTC_MULTICAST 2
|
#define RTC_MULTICAST 2
|
||||||
#define RTC_ANYCAST 3 /* IPv6 Anycast */
|
#define RTC_ANYCAST 3 /* IPv6 Anycast */
|
||||||
|
|
||||||
#define RTD_UNICAST 0 /* Next hop is neighbor router */
|
#define RTD_NONE 0 /* Undefined next hop */
|
||||||
|
#define RTD_UNICAST 1 /* Next hop is neighbor router */
|
||||||
#define RTD_BLACKHOLE 2 /* Silently drop packets */
|
#define RTD_BLACKHOLE 2 /* Silently drop packets */
|
||||||
#define RTD_UNREACHABLE 3 /* Reject as unreachable */
|
#define RTD_UNREACHABLE 3 /* Reject as unreachable */
|
||||||
#define RTD_PROHIBIT 4 /* Administratively prohibited */
|
#define RTD_PROHIBIT 4 /* Administratively prohibited */
|
||||||
#define RTD_NONE 6 /* Invalid RTD */
|
|
||||||
|
|
||||||
/* Flags for net->n.flags, used by kernel syncer */
|
/* Flags for net->n.flags, used by kernel syncer */
|
||||||
#define KRF_INSTALLED 0x80 /* This route should be installed in the kernel */
|
#define KRF_INSTALLED 0x80 /* This route should be installed in the kernel */
|
||||||
|
@ -408,7 +408,7 @@ typedef struct rta {
|
||||||
|
|
||||||
/* Route has regular, reachable nexthop (i.e. not RTD_UNREACHABLE and like) */
|
/* Route has regular, reachable nexthop (i.e. not RTD_UNREACHABLE and like) */
|
||||||
static inline int rte_is_reachable(rte *r)
|
static inline int rte_is_reachable(rte *r)
|
||||||
{ uint d = r->attrs->dest; return (d == RTD_UNICAST); }
|
{ return r->attrs->dest == RTD_UNICAST; }
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -523,7 +523,7 @@ static inline int nexthop_same(struct nexthop *x, struct nexthop *y)
|
||||||
struct nexthop *nexthop_merge(struct nexthop *x, struct nexthop *y, int rx, int ry, int max, linpool *lp);
|
struct nexthop *nexthop_merge(struct nexthop *x, struct nexthop *y, int rx, int ry, int max, linpool *lp);
|
||||||
static inline void nexthop_link(struct rta *a, struct nexthop *from)
|
static inline void nexthop_link(struct rta *a, struct nexthop *from)
|
||||||
{ memcpy(&a->nh, from, nexthop_size(from)); }
|
{ memcpy(&a->nh, from, nexthop_size(from)); }
|
||||||
void nexthop_insert(struct nexthop *n, struct nexthop *y);
|
void nexthop_insert(struct nexthop **n, struct nexthop *y);
|
||||||
int nexthop_is_sorted(struct nexthop *x);
|
int nexthop_is_sorted(struct nexthop *x);
|
||||||
|
|
||||||
void rta_init(void);
|
void rta_init(void);
|
||||||
|
|
|
@ -150,7 +150,8 @@ nexthop_hash(struct nexthop *x)
|
||||||
for (; x; x = x->next)
|
for (; x; x = x->next)
|
||||||
{
|
{
|
||||||
h ^= ipa_hash(x->gw) ^ (h << 5) ^ (h >> 9);
|
h ^= ipa_hash(x->gw) ^ (h << 5) ^ (h >> 9);
|
||||||
for (int i=0; i<x->labels; i++)
|
|
||||||
|
for (int i = 0; i < x->labels; i++)
|
||||||
h ^= x->label[i] ^ (h << 6) ^ (h >> 7);
|
h ^= x->label[i] ^ (h << 6) ^ (h >> 7);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -164,12 +165,13 @@ nexthop__same(struct nexthop *x, struct nexthop *y)
|
||||||
{
|
{
|
||||||
if (!ipa_equal(x->gw, y->gw) || (x->iface != y->iface) || (x->weight != y->weight) || (x->labels != y->labels))
|
if (!ipa_equal(x->gw, y->gw) || (x->iface != y->iface) || (x->weight != y->weight) || (x->labels != y->labels))
|
||||||
return 0;
|
return 0;
|
||||||
for (int i=0; i<x->labels; i++)
|
|
||||||
|
for (int i = 0; i < x->labels; i++)
|
||||||
if (x->label[i] != y->label[i])
|
if (x->label[i] != y->label[i])
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return x == y;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -195,7 +197,7 @@ nexthop_compare_node(struct nexthop *x, struct nexthop *y)
|
||||||
if (r)
|
if (r)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
for (int i=0; i<y->labels; i++)
|
for (int i = 0; i < y->labels; i++)
|
||||||
{
|
{
|
||||||
r = ((int) y->label[i]) - ((int) x->label[i]);
|
r = ((int) y->label[i]) - ((int) x->label[i]);
|
||||||
if (r)
|
if (r)
|
||||||
|
@ -271,34 +273,22 @@ nexthop_merge(struct nexthop *x, struct nexthop *y, int rx, int ry, int max, lin
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
nexthop_insert(struct nexthop *n, struct nexthop *x)
|
nexthop_insert(struct nexthop **n, struct nexthop *x)
|
||||||
{
|
{
|
||||||
struct nexthop tmp;
|
for (; *n; n = &((*n)->next))
|
||||||
memcpy(&tmp, n, sizeof(struct nexthop));
|
|
||||||
if (nexthop_compare_node(n, x) > 0) /* Insert to the included nexthop */
|
|
||||||
{
|
{
|
||||||
memcpy(n, x, sizeof(struct nexthop));
|
int cmp = nexthop_compare_node(*n, x);
|
||||||
memcpy(x, &tmp, sizeof(struct nexthop));
|
|
||||||
n->next = x;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (struct nexthop **nn = &(n->next); *nn; nn = &((*nn)->next))
|
|
||||||
{
|
|
||||||
int cmp = nexthop_compare_node(*nn, x);
|
|
||||||
|
|
||||||
if (cmp < 0)
|
if (cmp < 0)
|
||||||
continue;
|
continue;
|
||||||
|
else if (cmp > 0)
|
||||||
if (cmp > 0)
|
break;
|
||||||
{
|
else
|
||||||
x->next = *nn;
|
return;
|
||||||
*nn = x;
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
x->next = *n;
|
||||||
|
*n = x;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -314,7 +304,7 @@ nexthop_is_sorted(struct nexthop *x)
|
||||||
static inline slab *
|
static inline slab *
|
||||||
nexthop_slab(struct nexthop *nh)
|
nexthop_slab(struct nexthop *nh)
|
||||||
{
|
{
|
||||||
return nexthop_slab_[nh->labels > 2 ? 3 : nh->labels];
|
return nexthop_slab_[MIN(nh->labels, 3)];
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct nexthop *
|
static struct nexthop *
|
||||||
|
|
|
@ -79,9 +79,7 @@ dev_ifa_notify(struct proto *P, uint flags, struct ifa *ad)
|
||||||
.source = RTS_DEVICE,
|
.source = RTS_DEVICE,
|
||||||
.scope = SCOPE_UNIVERSE,
|
.scope = SCOPE_UNIVERSE,
|
||||||
.dest = RTD_UNICAST,
|
.dest = RTD_UNICAST,
|
||||||
.nh = {
|
.nh.iface = ad->iface,
|
||||||
.iface = ad->iface
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
a = rta_lookup(&a0);
|
a = rta_lookup(&a0);
|
||||||
|
|
|
@ -1768,7 +1768,6 @@ static inline void
|
||||||
rta_apply_hostentry(rta *a, struct hostentry *he)
|
rta_apply_hostentry(rta *a, struct hostentry *he)
|
||||||
{
|
{
|
||||||
a->hostentry = he;
|
a->hostentry = he;
|
||||||
|
|
||||||
a->dest = he->dest;
|
a->dest = he->dest;
|
||||||
a->igp_metric = he->igp_metric;
|
a->igp_metric = he->igp_metric;
|
||||||
|
|
||||||
|
@ -1810,14 +1809,14 @@ rta_apply_hostentry(rta *a, struct hostentry *he)
|
||||||
static inline rte *
|
static inline rte *
|
||||||
rt_next_hop_update_rte(rtable *tab UNUSED, rte *old)
|
rt_next_hop_update_rte(rtable *tab UNUSED, rte *old)
|
||||||
{
|
{
|
||||||
rta *ap = alloca(RTA_MAX_SIZE);
|
rta *a = alloca(RTA_MAX_SIZE);
|
||||||
memcpy(ap, old->attrs, rta_size(old->attrs));
|
memcpy(a, old->attrs, rta_size(old->attrs));
|
||||||
rta_apply_hostentry(ap, old->attrs->hostentry);
|
rta_apply_hostentry(a, old->attrs->hostentry);
|
||||||
ap->aflags = 0;
|
a->aflags = 0;
|
||||||
|
|
||||||
rte *e = sl_alloc(rte_slab);
|
rte *e = sl_alloc(rte_slab);
|
||||||
memcpy(e, old, sizeof(rte));
|
memcpy(e, old, sizeof(rte));
|
||||||
e->attrs = rta_lookup(ap);
|
e->attrs = rta_lookup(a);
|
||||||
|
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
@ -2373,7 +2372,8 @@ rt_update_hostentry(rtable *tab, struct hostentry *he)
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((a->dest == RTD_UNICAST) && ipa_zero(a->nh.gw) && !a->next)
|
if ((a->dest == RTD_UNICAST) && ipa_zero(a->nh.gw) && !a->next)
|
||||||
{ /* We have singlepath device route */
|
{
|
||||||
|
/* We have singlepath device route */
|
||||||
if (if_local_addr(he->addr, a->nh.iface))
|
if (if_local_addr(he->addr, a->nh.iface))
|
||||||
{
|
{
|
||||||
/* The host address is a local address, this is not valid */
|
/* The host address is a local address, this is not valid */
|
||||||
|
@ -2389,7 +2389,7 @@ rt_update_hostentry(rtable *tab, struct hostentry *he)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* The host is reachable through some route entry */
|
/* The host is reachable through some route entry */
|
||||||
he->nh = (&a->nh);
|
he->nh = &(a->nh);
|
||||||
he->dest = a->dest;
|
he->dest = a->dest;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1461,8 +1461,7 @@ bgp_get_neighbor(rte *r)
|
||||||
static inline int
|
static inline int
|
||||||
rte_resolvable(rte *rt)
|
rte_resolvable(rte *rt)
|
||||||
{
|
{
|
||||||
int rd = rt->attrs->dest;
|
return rt->attrs->dest == RTD_UNICAST;
|
||||||
return (rd == RTD_UNICAST);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|
|
@ -700,9 +700,7 @@ bgp_apply_next_hop(struct bgp_parse_state *s, rta *a, ip_addr gw, ip_addr ll)
|
||||||
WITHDRAW(BAD_NEXT_HOP);
|
WITHDRAW(BAD_NEXT_HOP);
|
||||||
|
|
||||||
a->dest = RTD_UNICAST;
|
a->dest = RTD_UNICAST;
|
||||||
a->nh.gw = nbr->addr;
|
a->nh = (struct nexthop){ .gw = nbr->addr, .iface = nbr->iface };
|
||||||
a->nh.iface = nbr->iface;
|
|
||||||
a->nh.next = NULL;
|
|
||||||
a->hostentry = NULL;
|
a->hostentry = NULL;
|
||||||
a->igp_metric = 0;
|
a->igp_metric = 0;
|
||||||
}
|
}
|
||||||
|
@ -749,8 +747,8 @@ bgp_use_gateway(struct bgp_export_state *s)
|
||||||
if (s->channel->cf->next_hop_self)
|
if (s->channel->cf->next_hop_self)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* We need valid global gateway */
|
/* We need one valid global gateway */
|
||||||
if ((ra->dest != RTD_UNICAST) || (ra->nh.next) || ipa_zero(ra->nh.gw) || ipa_is_link_local(ra->nh.gw))
|
if ((ra->dest != RTD_UNICAST) || ra->nh.next || ipa_zero(ra->nh.gw) || ipa_is_link_local(ra->nh.gw))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Use it when exported to internal peers */
|
/* Use it when exported to internal peers */
|
||||||
|
@ -1434,12 +1432,10 @@ bgp_decode_nlri(struct bgp_parse_state *s, u32 afi, byte *nlri, uint len, ea_lis
|
||||||
|
|
||||||
if (ea)
|
if (ea)
|
||||||
{
|
{
|
||||||
a = alloca(sizeof(struct rta));
|
a = allocz(sizeof(struct rta));
|
||||||
memset(a, 0, sizeof(struct rta));
|
|
||||||
|
|
||||||
a->source = RTS_BGP;
|
a->source = RTS_BGP;
|
||||||
a->scope = SCOPE_UNIVERSE;
|
a->scope = SCOPE_UNIVERSE;
|
||||||
a->dest = RTD_UNREACHABLE;
|
|
||||||
a->from = s->proto->cf->remote_ip;
|
a->from = s->proto->cf->remote_ip;
|
||||||
a->eattrs = ea;
|
a->eattrs = ea;
|
||||||
|
|
||||||
|
|
|
@ -36,11 +36,9 @@ unresolved_vlink(ort *ort)
|
||||||
static inline struct nexthop *
|
static inline struct nexthop *
|
||||||
new_nexthop(struct ospf_proto *p, ip_addr gw, struct iface *iface, byte weight)
|
new_nexthop(struct ospf_proto *p, ip_addr gw, struct iface *iface, byte weight)
|
||||||
{
|
{
|
||||||
struct nexthop *nh = lp_alloc(p->nhpool, sizeof(struct nexthop));
|
struct nexthop *nh = lp_allocz(p->nhpool, sizeof(struct nexthop));
|
||||||
nh->labels = 0;
|
|
||||||
nh->gw = gw;
|
nh->gw = gw;
|
||||||
nh->iface = iface;
|
nh->iface = iface;
|
||||||
nh->next = NULL;
|
|
||||||
nh->weight = weight;
|
nh->weight = weight;
|
||||||
return nh;
|
return nh;
|
||||||
}
|
}
|
||||||
|
@ -1907,7 +1905,6 @@ ort_changed(ort *nf, rta *nr)
|
||||||
(nf->n.metric1 != nf->old_metric1) || (nf->n.metric2 != nf->old_metric2) ||
|
(nf->n.metric1 != nf->old_metric1) || (nf->n.metric2 != nf->old_metric2) ||
|
||||||
(nf->n.tag != nf->old_tag) || (nf->n.rid != nf->old_rid) ||
|
(nf->n.tag != nf->old_tag) || (nf->n.rid != nf->old_rid) ||
|
||||||
(nr->source != or->source) || (nr->dest != or->dest) ||
|
(nr->source != or->source) || (nr->dest != or->dest) ||
|
||||||
(nr->nh.iface != or->nh.iface) || !ipa_equal(nr->nh.gw, or->nh.gw) ||
|
|
||||||
!nexthop_same(&(nr->nh), &(or->nh));
|
!nexthop_same(&(nr->nh), &(or->nh));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1952,11 +1949,10 @@ again1:
|
||||||
.src = p->p.main_source,
|
.src = p->p.main_source,
|
||||||
.source = nf->n.type,
|
.source = nf->n.type,
|
||||||
.scope = SCOPE_UNIVERSE,
|
.scope = SCOPE_UNIVERSE,
|
||||||
|
.dest = RTD_UNICAST,
|
||||||
|
.nh = *(nf->n.nhs),
|
||||||
};
|
};
|
||||||
|
|
||||||
nexthop_link(&a0, nf->n.nhs);
|
|
||||||
a0.dest = RTD_UNICAST;
|
|
||||||
|
|
||||||
if (reload || ort_changed(nf, &a0))
|
if (reload || ort_changed(nf, &a0))
|
||||||
{
|
{
|
||||||
rta *a = rta_lookup(&a0);
|
rta *a = rta_lookup(&a0);
|
||||||
|
|
|
@ -43,8 +43,6 @@
|
||||||
|
|
||||||
#include "pipe.h"
|
#include "pipe.h"
|
||||||
|
|
||||||
#include <alloca.h>
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
pipe_rt_notify(struct proto *P, struct channel *src_ch, net *n, rte *new, rte *old, ea_list *attrs)
|
pipe_rt_notify(struct proto *P, struct channel *src_ch, net *n, rte *new, rte *old, ea_list *attrs)
|
||||||
{
|
{
|
||||||
|
|
|
@ -147,20 +147,16 @@ rip_announce_rte(struct rip_proto *p, struct rip_entry *en)
|
||||||
.src = p->p.main_source,
|
.src = p->p.main_source,
|
||||||
.source = RTS_RIP,
|
.source = RTS_RIP,
|
||||||
.scope = SCOPE_UNIVERSE,
|
.scope = SCOPE_UNIVERSE,
|
||||||
|
.dest = RTD_UNICAST,
|
||||||
};
|
};
|
||||||
|
|
||||||
u8 rt_metric = rt->metric;
|
u8 rt_metric = rt->metric;
|
||||||
u16 rt_tag = rt->tag;
|
u16 rt_tag = rt->tag;
|
||||||
struct rip_rte *rt2 = rt->next;
|
|
||||||
|
|
||||||
/* Find second valid rte */
|
if (p->ecmp)
|
||||||
while (rt2 && !rip_valid_rte(rt2))
|
|
||||||
rt2 = rt2->next;
|
|
||||||
|
|
||||||
a0.dest = RTD_UNICAST;
|
|
||||||
if (p->ecmp && rt2)
|
|
||||||
{
|
{
|
||||||
/* ECMP route */
|
/* ECMP route */
|
||||||
|
struct nexthop *nhs = NULL;
|
||||||
int num = 0;
|
int num = 0;
|
||||||
|
|
||||||
for (rt = en->routes; rt && (num < p->ecmp); rt = rt->next)
|
for (rt = en->routes; rt && (num < p->ecmp); rt = rt->next)
|
||||||
|
@ -168,28 +164,27 @@ rip_announce_rte(struct rip_proto *p, struct rip_entry *en)
|
||||||
if (!rip_valid_rte(rt))
|
if (!rip_valid_rte(rt))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
struct nexthop *nh = (a0.nh.next ? &(a0.nh) : alloca(sizeof(struct nexthop)));
|
struct nexthop *nh = allocz(sizeof(struct nexthop));
|
||||||
|
|
||||||
nh->gw = rt->next_hop;
|
nh->gw = rt->next_hop;
|
||||||
nh->iface = rt->from->nbr->iface;
|
nh->iface = rt->from->nbr->iface;
|
||||||
nh->weight = rt->from->ifa->cf->ecmp_weight;
|
nh->weight = rt->from->ifa->cf->ecmp_weight;
|
||||||
|
|
||||||
if (a0.nh.next)
|
nexthop_insert(&nhs, nh);
|
||||||
nexthop_insert(&(a0.nh), nh);
|
|
||||||
|
|
||||||
num++;
|
num++;
|
||||||
|
|
||||||
if (rt->tag != rt_tag)
|
if (rt->tag != rt_tag)
|
||||||
rt_tag = 0;
|
rt_tag = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
a0.nh = *nhs;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Unipath route */
|
/* Unipath route */
|
||||||
a0.nh.next = NULL;
|
a0.from = rt->from->nbr->addr;
|
||||||
a0.nh.gw = rt->next_hop;
|
a0.nh.gw = rt->next_hop;
|
||||||
a0.nh.iface = rt->from->nbr->iface;
|
a0.nh.iface = rt->from->nbr->iface;
|
||||||
a0.from = rt->from->nbr->addr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rta *a = rta_lookup(&a0);
|
rta *a = rta_lookup(&a0);
|
||||||
|
|
|
@ -124,7 +124,7 @@ rpki_table_add_roa(struct rpki_cache *cache, struct channel *channel, const net_
|
||||||
.src = p->p.main_source,
|
.src = p->p.main_source,
|
||||||
.source = RTS_RPKI,
|
.source = RTS_RPKI,
|
||||||
.scope = SCOPE_UNIVERSE,
|
.scope = SCOPE_UNIVERSE,
|
||||||
.dest = RTD_BLACKHOLE,
|
.dest = RTD_NONE,
|
||||||
};
|
};
|
||||||
|
|
||||||
rta *a = rta_lookup(&a0);
|
rta *a = rta_lookup(&a0);
|
||||||
|
|
|
@ -13,9 +13,33 @@ CF_HDR
|
||||||
CF_DEFINES
|
CF_DEFINES
|
||||||
|
|
||||||
#define STATIC_CFG ((struct static_config *) this_proto)
|
#define STATIC_CFG ((struct static_config *) this_proto)
|
||||||
static struct static_route *this_srt, *last_srt;
|
static struct static_route *this_srt, *this_snh;
|
||||||
static struct f_inst **this_srt_last_cmd;
|
static struct f_inst **this_srt_last_cmd;
|
||||||
|
|
||||||
|
static struct static_route *
|
||||||
|
static_nexthop_new(void)
|
||||||
|
{
|
||||||
|
struct static_route *nh;
|
||||||
|
|
||||||
|
if (!this_snh)
|
||||||
|
{
|
||||||
|
/* First next hop */
|
||||||
|
nh = this_srt;
|
||||||
|
rem_node(&this_srt->n);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Additional next hop */
|
||||||
|
nh = cfg_allocz(sizeof(struct static_route));
|
||||||
|
nh->net = this_srt->net;
|
||||||
|
this_snh->mp_next = nh;
|
||||||
|
}
|
||||||
|
|
||||||
|
nh->dest = RTD_UNICAST;
|
||||||
|
nh->mp_head = this_srt;
|
||||||
|
return nh;
|
||||||
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
static_route_finish(void)
|
static_route_finish(void)
|
||||||
{ }
|
{ }
|
||||||
|
@ -45,48 +69,35 @@ static_proto:
|
||||||
| static_proto stat_route stat_route_opt_list ';' { static_route_finish(); }
|
| static_proto stat_route stat_route_opt_list ';' { static_route_finish(); }
|
||||||
;
|
;
|
||||||
|
|
||||||
stat_nexthop_via: VIA
|
stat_nexthop:
|
||||||
{
|
VIA ipa ipa_scope {
|
||||||
if (last_srt)
|
this_snh = static_nexthop_new();
|
||||||
{
|
this_snh->via = $2;
|
||||||
last_srt = (last_srt->mp_next = cfg_allocz(sizeof(struct static_route)));
|
this_snh->iface = $3;
|
||||||
last_srt->net = this_srt->net;
|
add_tail(&STATIC_CFG->neigh_routes, &this_snh->n);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
last_srt = this_srt;
|
|
||||||
rem_node(&this_srt->n);
|
|
||||||
}
|
|
||||||
|
|
||||||
last_srt->mp_head = this_srt;
|
|
||||||
last_srt->dest = RTD_UNICAST;
|
|
||||||
};
|
|
||||||
|
|
||||||
stat_nexthop_ident:
|
|
||||||
stat_nexthop_via ipa ipa_scope {
|
|
||||||
last_srt->via = $2;
|
|
||||||
last_srt->iface = $3;
|
|
||||||
add_tail(&STATIC_CFG->neigh_routes, &last_srt->n);
|
|
||||||
}
|
}
|
||||||
| stat_nexthop_via TEXT {
|
| VIA TEXT {
|
||||||
last_srt->via = IPA_NONE;
|
this_snh = static_nexthop_new();
|
||||||
last_srt->if_name = $2;
|
this_snh->via = IPA_NONE;
|
||||||
add_tail(&STATIC_CFG->iface_routes, &last_srt->n);
|
this_snh->if_name = $2;
|
||||||
|
add_tail(&STATIC_CFG->iface_routes, &this_snh->n);
|
||||||
}
|
}
|
||||||
| stat_nexthop_ident MPLS label_stack {
|
| stat_nexthop MPLS label_stack {
|
||||||
last_srt->label_count = $3[0];
|
this_snh->label_count = $3[0];
|
||||||
last_srt->label_stack = &($3[1]);
|
this_snh->label_stack = &($3[1]);
|
||||||
}
|
}
|
||||||
| stat_nexthop_ident WEIGHT expr {
|
| stat_nexthop WEIGHT expr {
|
||||||
last_srt->weight = $3 - 1;
|
this_snh->weight = $3 - 1;
|
||||||
if (($3<1) || ($3>256)) cf_error("Weight must be in range 1-256");
|
if (($3<1) || ($3>256)) cf_error("Weight must be in range 1-256");
|
||||||
}
|
}
|
||||||
| stat_nexthop_ident BFD bool { last_srt->use_bfd = $3; cf_check_bfd($3); }
|
| stat_nexthop BFD bool {
|
||||||
|
this_snh->use_bfd = $3; cf_check_bfd($3);
|
||||||
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
stat_nexthop:
|
stat_nexthops:
|
||||||
stat_nexthop_ident
|
stat_nexthop
|
||||||
| stat_nexthop stat_nexthop_ident
|
| stat_nexthops stat_nexthop
|
||||||
;
|
;
|
||||||
|
|
||||||
stat_route0: ROUTE net_any {
|
stat_route0: ROUTE net_any {
|
||||||
|
@ -95,12 +106,12 @@ stat_route0: ROUTE net_any {
|
||||||
this_srt->net = $2;
|
this_srt->net = $2;
|
||||||
this_srt_last_cmd = &(this_srt->cmds);
|
this_srt_last_cmd = &(this_srt->cmds);
|
||||||
this_srt->mp_next = NULL;
|
this_srt->mp_next = NULL;
|
||||||
last_srt = NULL;
|
this_snh = NULL;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
stat_route:
|
stat_route:
|
||||||
stat_route0 stat_nexthop
|
stat_route0 stat_nexthops
|
||||||
| stat_route0 RECURSIVE ipa {
|
| stat_route0 RECURSIVE ipa {
|
||||||
this_srt->dest = RTDX_RECURSIVE;
|
this_srt->dest = RTDX_RECURSIVE;
|
||||||
this_srt->via = $3;
|
this_srt->via = $3;
|
||||||
|
|
|
@ -60,54 +60,44 @@ p_igp_table(struct proto *p)
|
||||||
static void
|
static void
|
||||||
static_install(struct proto *p, struct static_route *r)
|
static_install(struct proto *p, struct static_route *r)
|
||||||
{
|
{
|
||||||
rta *ap = alloca(RTA_MAX_SIZE);
|
rta *ap = allocz(RTA_MAX_SIZE);
|
||||||
rte *e;
|
rte *e;
|
||||||
|
|
||||||
if (!(r->state & STS_WANT) && (r->state & (STS_INSTALLED | STS_FORCE)) && r->dest != RTD_UNICAST)
|
if (!(r->state & STS_WANT) && (r->state & (STS_INSTALLED | STS_FORCE)) && r->dest != RTD_UNICAST)
|
||||||
goto drop;
|
goto drop;
|
||||||
|
|
||||||
DBG("Installing static route %N, rtd=%d\n", r->net, r->dest);
|
DBG("Installing static route %N, rtd=%d\n", r->net, r->dest);
|
||||||
bzero(ap, RTA_MAX_SIZE);
|
|
||||||
ap->src = p->main_source;
|
ap->src = p->main_source;
|
||||||
ap->source = ((r->dest == RTD_UNICAST) && ipa_zero(r->via)) ? RTS_STATIC_DEVICE : RTS_STATIC;
|
ap->source = RTS_STATIC;
|
||||||
ap->scope = SCOPE_UNIVERSE;
|
ap->scope = SCOPE_UNIVERSE;
|
||||||
ap->dest = r->dest;
|
ap->dest = r->dest;
|
||||||
|
|
||||||
if (r->dest == RTD_UNICAST)
|
if (r->dest == RTD_UNICAST)
|
||||||
{
|
{
|
||||||
|
struct nexthop *nhs = NULL;
|
||||||
struct static_route *r2;
|
struct static_route *r2;
|
||||||
int num = 0, update = 0;
|
int update = 0;
|
||||||
|
|
||||||
|
r = r->mp_head;
|
||||||
for (r2 = r; r2; r2 = r2->mp_next)
|
for (r2 = r; r2; r2 = r2->mp_next)
|
||||||
{
|
{
|
||||||
|
|
||||||
if ((r2->state & STS_FORCE) ||
|
if ((r2->state & STS_FORCE) ||
|
||||||
(!!(r2->state & STS_INSTALLED) != !!(r2->state & STS_WANT)))
|
(!!(r2->state & STS_INSTALLED) != !!(r2->state & STS_WANT)))
|
||||||
update++;
|
update++;
|
||||||
|
|
||||||
if (r2->state & STS_WANT)
|
if (r2->state & STS_WANT)
|
||||||
{
|
{
|
||||||
struct nexthop *nh = (ap->nh.next) ? alloca(NEXTHOP_MAX_SIZE) : &(ap->nh);
|
struct nexthop *nh = allocz(NEXTHOP_MAX_SIZE);
|
||||||
if (ipa_zero(r2->via)) // Device nexthop
|
|
||||||
{
|
|
||||||
nh->gw = IPA_NONE;
|
|
||||||
nh->iface = r2->iface;
|
|
||||||
}
|
|
||||||
else // Router nexthop
|
|
||||||
{
|
|
||||||
nh->gw = r2->via;
|
|
||||||
nh->iface = r2->neigh->iface;
|
|
||||||
}
|
|
||||||
nh->weight = r2->weight;
|
|
||||||
nh->labels = r2->label_count;
|
|
||||||
for (int i=0; i<nh->labels; i++)
|
|
||||||
nh->label[i] = r2->label_stack[i];
|
|
||||||
|
|
||||||
if (ap->nh.next)
|
nh->gw = r2->via;
|
||||||
nexthop_insert(&(ap->nh), nh);
|
nh->iface = r2->neigh ? r2->neigh->iface : r2->iface;
|
||||||
r2->state |= STS_INSTALLED;
|
nh->weight = r2->weight;
|
||||||
num++;
|
nh->labels = r2->label_count;
|
||||||
}
|
memcpy(nh->label, r2->label_stack, r2->label_count * sizeof(u32));
|
||||||
|
|
||||||
|
r2->state |= STS_INSTALLED;
|
||||||
|
nexthop_insert(&nhs, nh);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
r2->state = 0;
|
r2->state = 0;
|
||||||
}
|
}
|
||||||
|
@ -115,14 +105,15 @@ static_install(struct proto *p, struct static_route *r)
|
||||||
if (!update) // Nothing changed
|
if (!update) // Nothing changed
|
||||||
return;
|
return;
|
||||||
|
|
||||||
r = r->mp_head;
|
if (!nhs) // No nexthop to install
|
||||||
|
|
||||||
if (!num) // No nexthop to install
|
|
||||||
{
|
{
|
||||||
drop:
|
drop:
|
||||||
rte_update(p, r->net, NULL);
|
rte_update(p, r->net, NULL);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ap->dest = RTD_UNICAST;
|
||||||
|
nexthop_link(ap, nhs);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
r->state |= STS_INSTALLED;
|
r->state |= STS_INSTALLED;
|
||||||
|
|
|
@ -193,7 +193,6 @@ krt_send_route(struct krt_proto *p, int cmd, rte *e)
|
||||||
struct ks_msg msg;
|
struct ks_msg msg;
|
||||||
char *body = (char *)msg.buf;
|
char *body = (char *)msg.buf;
|
||||||
sockaddr gate, mask, dst;
|
sockaddr gate, mask, dst;
|
||||||
ip_addr gw;
|
|
||||||
|
|
||||||
DBG("krt-sock: send %I/%d via %I\n", net->n.prefix, net->n.pxlen, a->gw);
|
DBG("krt-sock: send %I/%d via %I\n", net->n.prefix, net->n.pxlen, a->gw);
|
||||||
|
|
||||||
|
@ -223,14 +222,12 @@ krt_send_route(struct krt_proto *p, int cmd, rte *e)
|
||||||
msg.rtm.rtm_flags |= RTF_BLACKHOLE;
|
msg.rtm.rtm_flags |= RTF_BLACKHOLE;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* This is really very nasty, but I'm not able
|
/*
|
||||||
* to add "(reject|blackhole)" route without
|
* This is really very nasty, but I'm not able to add reject/blackhole route
|
||||||
* gateway set
|
* without gateway address.
|
||||||
*/
|
*/
|
||||||
if(!i)
|
if (!i)
|
||||||
{
|
{
|
||||||
i = HEAD(iface_list);
|
|
||||||
|
|
||||||
WALK_LIST(j, iface_list)
|
WALK_LIST(j, iface_list)
|
||||||
{
|
{
|
||||||
if (j->flags & IF_LOOPBACK)
|
if (j->flags & IF_LOOPBACK)
|
||||||
|
@ -239,14 +236,14 @@ krt_send_route(struct krt_proto *p, int cmd, rte *e)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!i)
|
||||||
|
{
|
||||||
|
log(L_ERR "KRT: Cannot find loopback iface");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gw = a->nh.gw;
|
|
||||||
|
|
||||||
/* Embed interface ID to link-local address */
|
|
||||||
if (ipa_is_link_local(gw))
|
|
||||||
_I0(gw) = 0xfe800000 | (i->index & 0x0000ffff);
|
|
||||||
|
|
||||||
int af = AF_UNSPEC;
|
int af = AF_UNSPEC;
|
||||||
|
|
||||||
switch (net->n.addr->type) {
|
switch (net->n.addr->type) {
|
||||||
|
@ -261,45 +258,51 @@ krt_send_route(struct krt_proto *p, int cmd, rte *e)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
sockaddr_fill(&dst, af, net_prefix(net->n.addr), NULL, 0);
|
sockaddr_fill(&dst, af, net_prefix(net->n.addr), NULL, 0);
|
||||||
sockaddr_fill(&mask, af, net_pxmask(net->n.addr), NULL, 0);
|
sockaddr_fill(&mask, af, net_pxmask(net->n.addr), NULL, 0);
|
||||||
sockaddr_fill(&gate, af, gw, NULL, 0);
|
|
||||||
|
|
||||||
switch (a->dest)
|
switch (a->dest)
|
||||||
{
|
{
|
||||||
case RTD_UNICAST:
|
case RTD_UNICAST:
|
||||||
if (ipa_zero(gw))
|
if (ipa_nonzero(a->nh.gw))
|
||||||
{
|
{
|
||||||
if(i)
|
ip_addr gw = a->nh.gw;
|
||||||
{
|
|
||||||
#ifdef RTF_CLONING
|
|
||||||
if (cmd == RTM_ADD && (i->flags & IF_MULTIACCESS) != IF_MULTIACCESS) /* PTP */
|
|
||||||
msg.rtm.rtm_flags |= RTF_CLONING;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if(!i->addr) {
|
/* Embed interface ID to link-local address */
|
||||||
log(L_ERR "KRT: interface %s has no IP addess", i->name);
|
if (ipa_is_link_local(gw))
|
||||||
return -1;
|
_I0(gw) = 0xfe800000 | (i->index & 0x0000ffff);
|
||||||
}
|
|
||||||
|
|
||||||
sockaddr_fill(&gate, ipa_is_ip4(i->addr->ip) ? AF_INET : AF_INET6, i->addr->ip, NULL, 0);
|
sockaddr_fill(&gate, af, gw, NULL, 0);
|
||||||
msg.rtm.rtm_addrs |= RTA_GATEWAY;
|
msg.rtm.rtm_flags |= RTF_GATEWAY;
|
||||||
}
|
msg.rtm.rtm_addrs |= RTA_GATEWAY;
|
||||||
} else {
|
|
||||||
msg.rtm.rtm_flags |= RTF_GATEWAY;
|
|
||||||
msg.rtm.rtm_addrs |= RTA_GATEWAY;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef RTF_REJECT
|
#ifdef RTF_REJECT
|
||||||
case RTD_UNREACHABLE:
|
case RTD_UNREACHABLE:
|
||||||
#endif
|
#endif
|
||||||
#ifdef RTF_BLACKHOLE
|
#ifdef RTF_BLACKHOLE
|
||||||
case RTD_BLACKHOLE:
|
case RTD_BLACKHOLE:
|
||||||
#endif
|
#endif
|
||||||
default:
|
{
|
||||||
bug("krt-sock: unknown flags, but not filtered");
|
/* Fallback for all other valid cases */
|
||||||
|
if (!i->addr)
|
||||||
|
{
|
||||||
|
log(L_ERR "KRT: interface %s has no IP addess", i->name);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef RTF_CLONING
|
||||||
|
if (cmd == RTM_ADD && (i->flags & IF_MULTIACCESS) != IF_MULTIACCESS) /* PTP */
|
||||||
|
msg.rtm.rtm_flags |= RTF_CLONING;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
sockaddr_fill(&gate, ipa_is_ip4(i->addr->ip) ? AF_INET : AF_INET6, i->addr->ip, NULL, 0);
|
||||||
|
msg.rtm.rtm_addrs |= RTA_GATEWAY;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
bug("krt-sock: unknown flags, but not filtered");
|
||||||
}
|
}
|
||||||
|
|
||||||
msg.rtm.rtm_index = i->index;
|
msg.rtm.rtm_index = i->index;
|
||||||
|
@ -497,7 +500,6 @@ krt_read_route(struct ks_msg *msg, struct krt_proto *p, int scan)
|
||||||
}
|
}
|
||||||
|
|
||||||
a.dest = RTD_UNICAST;
|
a.dest = RTD_UNICAST;
|
||||||
a.nh.next = NULL;
|
|
||||||
if (flags & RTF_GATEWAY)
|
if (flags & RTF_GATEWAY)
|
||||||
{
|
{
|
||||||
neighbor *ng;
|
neighbor *ng;
|
||||||
|
@ -520,8 +522,6 @@ krt_read_route(struct ks_msg *msg, struct krt_proto *p, int scan)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
a.nh.gw = IPA_NONE;
|
|
||||||
|
|
||||||
done:
|
done:
|
||||||
e = rte_get_temp(&a);
|
e = rte_get_temp(&a);
|
||||||
|
|
|
@ -320,6 +320,7 @@ static struct nl_want_attrs ifa_attr_want4[BIRD_IFA_MAX] = {
|
||||||
[IFA_ADDRESS] = { 1, 1, sizeof(ip4_addr) },
|
[IFA_ADDRESS] = { 1, 1, sizeof(ip4_addr) },
|
||||||
[IFA_LOCAL] = { 1, 1, sizeof(ip4_addr) },
|
[IFA_LOCAL] = { 1, 1, sizeof(ip4_addr) },
|
||||||
[IFA_BROADCAST] = { 1, 1, sizeof(ip4_addr) },
|
[IFA_BROADCAST] = { 1, 1, sizeof(ip4_addr) },
|
||||||
|
[IFA_FLAGS] = { 1, 1, sizeof(u32) },
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct nl_want_attrs ifa_attr_want6[BIRD_IFA_MAX] = {
|
static struct nl_want_attrs ifa_attr_want6[BIRD_IFA_MAX] = {
|
||||||
|
@ -543,18 +544,17 @@ nl_add_attr_via(struct nlmsghdr *h, uint bufsize, ip_addr ipa)
|
||||||
|
|
||||||
h->nlmsg_len += sizeof(*via);
|
h->nlmsg_len += sizeof(*via);
|
||||||
|
|
||||||
if (ipa_is_ip4(ipa)) {
|
if (ipa_is_ip4(ipa))
|
||||||
ip4_addr ip4 = ipa_to_ip4(ipa);
|
{
|
||||||
ip4 = ip4_hton(ip4);
|
|
||||||
via->rtvia_family = AF_INET;
|
via->rtvia_family = AF_INET;
|
||||||
memcpy(via->rtvia_addr, &ip4, sizeof(ip4));
|
put_ip4(via->rtvia_addr, ipa_to_ip4(ipa));
|
||||||
h->nlmsg_len += sizeof(ip4);
|
h->nlmsg_len += sizeof(ip4_addr);
|
||||||
} else {
|
}
|
||||||
ip6_addr ip6 = ipa_to_ip6(ipa);
|
else
|
||||||
ip6 = ip6_hton(ip6);
|
{
|
||||||
via->rtvia_family = AF_INET6;
|
via->rtvia_family = AF_INET6;
|
||||||
memcpy(via->rtvia_addr, &ip6, sizeof(ip6));
|
put_ip6(via->rtvia_addr, ipa_to_ip6(ipa));
|
||||||
h->nlmsg_len += sizeof(ip6);
|
h->nlmsg_len += sizeof(ip6_addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
nl_close_attr(h, nest);
|
nl_close_attr(h, nest);
|
||||||
|
@ -669,6 +669,7 @@ nl_parse_multipath(struct krt_proto *p, struct rtattr *ra)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
rv->gw = IPA_NONE;
|
rv->gw = IPA_NONE;
|
||||||
|
|
||||||
if (a[RTA_ENCAP_TYPE])
|
if (a[RTA_ENCAP_TYPE])
|
||||||
{
|
{
|
||||||
if (rta_get_u16(a[RTA_ENCAP_TYPE]) != LWTUNNEL_ENCAP_MPLS) {
|
if (rta_get_u16(a[RTA_ENCAP_TYPE]) != LWTUNNEL_ENCAP_MPLS) {
|
||||||
|
@ -1092,20 +1093,16 @@ krt_capable(rte *e)
|
||||||
rta *a = e->attrs;
|
rta *a = e->attrs;
|
||||||
|
|
||||||
switch (a->dest)
|
switch (a->dest)
|
||||||
{
|
{
|
||||||
case RTD_UNICAST:
|
case RTD_UNICAST:
|
||||||
for (struct nexthop *nh = &(a->nh); nh; nh = nh->next)
|
|
||||||
if (nh->iface)
|
|
||||||
return 1;
|
|
||||||
return 0;
|
|
||||||
case RTD_BLACKHOLE:
|
case RTD_BLACKHOLE:
|
||||||
case RTD_UNREACHABLE:
|
case RTD_UNREACHABLE:
|
||||||
case RTD_PROHIBIT:
|
case RTD_PROHIBIT:
|
||||||
break;
|
return 1;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
|
@ -1210,7 +1207,6 @@ nl_send_route(struct krt_proto *p, rte *e, struct ea_list *eattrs, int op, int d
|
||||||
|
|
||||||
|
|
||||||
dest:
|
dest:
|
||||||
/* a->iface != NULL checked in krt_capable() for router and device routes */
|
|
||||||
switch (dest)
|
switch (dest)
|
||||||
{
|
{
|
||||||
case RTD_UNICAST:
|
case RTD_UNICAST:
|
||||||
|
@ -1502,6 +1498,7 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h)
|
||||||
switch (i->rtm_type)
|
switch (i->rtm_type)
|
||||||
{
|
{
|
||||||
case RTN_UNICAST:
|
case RTN_UNICAST:
|
||||||
|
ra->dest = RTD_UNICAST;
|
||||||
|
|
||||||
if (a[RTA_MULTIPATH] && (i->rtm_family == AF_INET))
|
if (a[RTA_MULTIPATH] && (i->rtm_family == AF_INET))
|
||||||
{
|
{
|
||||||
|
@ -1512,7 +1509,7 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
nexthop_link(ra, nh);
|
ra->nh = *nh;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1698,9 +1695,20 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Merge next hops with the stored route */
|
/* Merge next hops with the stored route */
|
||||||
rta *a = s->attrs;
|
rta *oa = s->attrs;
|
||||||
|
|
||||||
nexthop_insert(&a->nh, &ra->nh);
|
struct nexthop *nhs = &oa->nh;
|
||||||
|
nexthop_insert(&nhs, &ra->nh);
|
||||||
|
|
||||||
|
/* Perhaps new nexthop is inserted at the first position */
|
||||||
|
if (nhs == &ra->nh)
|
||||||
|
{
|
||||||
|
/* Swap rtas */
|
||||||
|
s->attrs = ra;
|
||||||
|
|
||||||
|
/* Keep old eattrs */
|
||||||
|
ra->eattrs = oa->eattrs;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -984,7 +984,7 @@ krt_store_tmp_attrs(rte *rt, struct ea_list *attrs)
|
||||||
static int
|
static int
|
||||||
krt_import_control(struct proto *P, rte **new, ea_list **attrs UNUSED, struct linpool *pool UNUSED)
|
krt_import_control(struct proto *P, rte **new, ea_list **attrs UNUSED, struct linpool *pool UNUSED)
|
||||||
{
|
{
|
||||||
struct krt_proto *p = (struct krt_proto *) P;
|
// struct krt_proto *p = (struct krt_proto *) P;
|
||||||
rte *e = *new;
|
rte *e = *new;
|
||||||
|
|
||||||
if (e->attrs->src->proto == P)
|
if (e->attrs->src->proto == P)
|
||||||
|
@ -1005,17 +1005,6 @@ krt_import_control(struct proto *P, rte **new, ea_list **attrs UNUSED, struct li
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!KRT_CF->devroutes && (e->attrs->source != RTS_STATIC_DEVICE))
|
|
||||||
{
|
|
||||||
struct nexthop *nh = &(e->attrs->nh);
|
|
||||||
for (; nh; nh = nh->next)
|
|
||||||
if (ipa_nonzero(nh->gw))
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (!nh) /* Gone through all the nexthops and no explicit GW found */
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!krt_capable(e))
|
if (!krt_capable(e))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue