mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-11-08 12:18:42 +00:00
Nest: EVPN net type - preliminary support
This commit is contained in:
parent
32d6855a3f
commit
b32c279606
@ -242,7 +242,19 @@ WHITE [ \t]
|
|||||||
return IP4;
|
return IP4;
|
||||||
}
|
}
|
||||||
|
|
||||||
({XIGIT}{2}){16,}|{XIGIT}{2}(:{XIGIT}{2}){15,}|hex:({XIGIT}{2}*|{XIGIT}{2}(:{XIGIT}{2})*) {
|
{XIGIT}{2}(:{XIGIT}{2}){5} {
|
||||||
|
mac_addr mac;
|
||||||
|
char *s = yytext;
|
||||||
|
|
||||||
|
int len = bstrhextobin(s, mac.addr);
|
||||||
|
if (len != 6)
|
||||||
|
cf_error("Invalid MAC address");
|
||||||
|
|
||||||
|
cf_lval.mac = mac;
|
||||||
|
return MAC_;
|
||||||
|
}
|
||||||
|
|
||||||
|
({XIGIT}{2}){10,}|{XIGIT}{2}(:{XIGIT}{2}){9,}|hex:({XIGIT}{2}*|{XIGIT}{2}(:{XIGIT}{2})*) {
|
||||||
char *s = yytext;
|
char *s = yytext;
|
||||||
struct adata *bs;
|
struct adata *bs;
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@ CF_HDR
|
|||||||
#include "lib/socket.h"
|
#include "lib/socket.h"
|
||||||
#include "lib/timer.h"
|
#include "lib/timer.h"
|
||||||
#include "lib/string.h"
|
#include "lib/string.h"
|
||||||
|
#include "lib/evpn.h"
|
||||||
#include "nest/protocol.h"
|
#include "nest/protocol.h"
|
||||||
#include "nest/iface.h"
|
#include "nest/iface.h"
|
||||||
#include "nest/route.h"
|
#include "nest/route.h"
|
||||||
@ -60,7 +61,9 @@ CF_DECLS
|
|||||||
ip_addr a;
|
ip_addr a;
|
||||||
ip4_addr ip4;
|
ip4_addr ip4;
|
||||||
ip6_addr ip6;
|
ip6_addr ip6;
|
||||||
|
mac_addr mac;
|
||||||
net_addr net;
|
net_addr net;
|
||||||
|
evpn_esi esi;
|
||||||
net_addr *net_ptr;
|
net_addr *net_ptr;
|
||||||
struct symbol *s;
|
struct symbol *s;
|
||||||
struct keyword *kw;
|
struct keyword *kw;
|
||||||
@ -107,6 +110,7 @@ CF_DECLS
|
|||||||
%token <i> NUM ENUM
|
%token <i> NUM ENUM
|
||||||
%token <ip4> IP4
|
%token <ip4> IP4
|
||||||
%token <ip6> IP6
|
%token <ip6> IP6
|
||||||
|
%token <mac> MAC_
|
||||||
%token <i64> VPN_RD
|
%token <i64> VPN_RD
|
||||||
%token <s> CF_SYM_KNOWN CF_SYM_UNDEFINED CF_SYM_METHOD_BARE CF_SYM_METHOD_ARGS
|
%token <s> CF_SYM_KNOWN CF_SYM_UNDEFINED CF_SYM_METHOD_BARE CF_SYM_METHOD_ARGS
|
||||||
%token <t> TEXT
|
%token <t> TEXT
|
||||||
@ -118,7 +122,9 @@ CF_DECLS
|
|||||||
%type <a> ipa
|
%type <a> ipa
|
||||||
%type <net> net_ip4_ net_ip4 net_ip6_ net_ip6 net_ip_ net_ip net_or_ipa
|
%type <net> net_ip4_ net_ip4 net_ip6_ net_ip6 net_ip_ net_ip net_or_ipa
|
||||||
%type <net_ptr> net_ net_any net_vpn4_ net_vpn6_ net_vpn_ net_roa4_ net_roa6_ net_roa_ net_ip6_sadr_ net_mpls_
|
%type <net_ptr> net_ net_any net_vpn4_ net_vpn6_ net_vpn_ net_roa4_ net_roa6_ net_roa_ net_ip6_sadr_ net_mpls_
|
||||||
|
%type <net_ptr> net_evpn_ net_evpn_ead_ net_evpn_mac_ net_evpn_mac_ip_ net_evpn_imet_ net_evpn_es_
|
||||||
%type <mls> label_stack_start label_stack
|
%type <mls> label_stack_start label_stack
|
||||||
|
%type <esi> evpn_esi
|
||||||
|
|
||||||
%type <t> text opttext
|
%type <t> text opttext
|
||||||
%type <bs> bytestring
|
%type <bs> bytestring
|
||||||
@ -138,6 +144,7 @@ CF_DECLS
|
|||||||
%start config
|
%start config
|
||||||
|
|
||||||
CF_KEYWORDS(DEFINE, ON, OFF, YES, NO, S, MS, US, PORT, VPN, MPLS, FROM, MAX, AS)
|
CF_KEYWORDS(DEFINE, ON, OFF, YES, NO, S, MS, US, PORT, VPN, MPLS, FROM, MAX, AS)
|
||||||
|
CF_KEYWORDS(EVPN, EAD, MAC, IMET, ES)
|
||||||
|
|
||||||
CF_GRAMMAR
|
CF_GRAMMAR
|
||||||
|
|
||||||
@ -298,6 +305,46 @@ net_mpls_: MPLS NUM
|
|||||||
net_fill_mpls($$, $2);
|
net_fill_mpls($$, $2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
evpn_esi: bytestring
|
||||||
|
{
|
||||||
|
if ($1->length != 10)
|
||||||
|
cf_error("Invalid ESI length %u", (uint) $1->length);
|
||||||
|
|
||||||
|
memcpy(&$$, $1->data, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
net_evpn_ead_: EVPN EAD VPN_RD NUM evpn_esi
|
||||||
|
{
|
||||||
|
$$ = cfg_alloc(sizeof(net_addr_evpn_ead));
|
||||||
|
net_fill_evpn_ead($$, $3, $4, $5);
|
||||||
|
}
|
||||||
|
|
||||||
|
net_evpn_mac_: EVPN MAC VPN_RD NUM MAC_ '*'
|
||||||
|
{
|
||||||
|
$$ = cfg_alloc(sizeof(net_addr_evpn_mac));
|
||||||
|
net_fill_evpn_mac($$, $3, $4, $5);
|
||||||
|
}
|
||||||
|
|
||||||
|
net_evpn_mac_ip_: EVPN MAC VPN_RD NUM MAC_ ipa
|
||||||
|
{
|
||||||
|
$$ = cfg_alloc(sizeof(net_addr_evpn_mac_ip));
|
||||||
|
net_fill_evpn_mac_ip($$, $3, $4, $5, $6);
|
||||||
|
}
|
||||||
|
|
||||||
|
net_evpn_imet_: EVPN IMET VPN_RD NUM ipa
|
||||||
|
{
|
||||||
|
$$ = cfg_alloc(sizeof(net_addr_evpn_imet));
|
||||||
|
net_fill_evpn_imet($$, $3, $4, $5);
|
||||||
|
}
|
||||||
|
|
||||||
|
net_evpn_es_: EVPN ES VPN_RD evpn_esi ipa
|
||||||
|
{
|
||||||
|
$$ = cfg_alloc(sizeof(net_addr_evpn_es));
|
||||||
|
net_fill_evpn_es($$, $3, $4, $5);
|
||||||
|
}
|
||||||
|
|
||||||
|
net_evpn_: net_evpn_ead_ | net_evpn_mac_ | net_evpn_mac_ip_ | net_evpn_imet_ | net_evpn_es_ ;
|
||||||
|
|
||||||
net_ip_: net_ip4_ | net_ip6_ ;
|
net_ip_: net_ip4_ | net_ip6_ ;
|
||||||
net_vpn_: net_vpn4_ | net_vpn6_ ;
|
net_vpn_: net_vpn4_ | net_vpn6_ ;
|
||||||
net_roa_: net_roa4_ | net_roa6_ ;
|
net_roa_: net_roa4_ | net_roa6_ ;
|
||||||
@ -309,6 +356,7 @@ net_:
|
|||||||
| net_flow_
|
| net_flow_
|
||||||
| net_ip6_sadr_
|
| net_ip6_sadr_
|
||||||
| net_mpls_
|
| net_mpls_
|
||||||
|
| net_evpn_
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
src := bitmap.c bitops.c blake2s.c blake2b.c checksum.c event.c flowspec.c idm.c ip.c lists.c mac.c md5.c mempool.c net.c patmatch.c printf.c resource.c sha1.c sha256.c sha512.c slab.c slists.c strtoul.c tbf.c timer.c xmalloc.c
|
src := bitmap.c bitops.c blake2s.c blake2b.c checksum.c event.c evpn.c flowspec.c idm.c ip.c lists.c mac.c md5.c mempool.c net.c patmatch.c printf.c resource.c sha1.c sha256.c sha512.c slab.c slists.c strtoul.c tbf.c timer.c xmalloc.c
|
||||||
obj := $(src-o-files)
|
obj := $(src-o-files)
|
||||||
$(all-daemon)
|
$(all-daemon)
|
||||||
|
|
||||||
|
38
lib/evpn.c
Normal file
38
lib/evpn.c
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* BIRD Internet Routing Daemon -- EVPN Net Type
|
||||||
|
*
|
||||||
|
* (c) 2023 Ondrej Zajicek <santiago@crfreenet.org>
|
||||||
|
* (c) 2023 CZ.NIC z.s.p.o.
|
||||||
|
*
|
||||||
|
* Can be freely distributed and used under the terms of the GNU GPL.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "nest/bird.h"
|
||||||
|
#include "lib/net.h"
|
||||||
|
|
||||||
|
uint
|
||||||
|
evpn_format(char *buf, uint blen, const net_addr_evpn *n)
|
||||||
|
{
|
||||||
|
char rds[32];
|
||||||
|
rd_format(n->rd, rds, 32);
|
||||||
|
|
||||||
|
switch (n->subtype)
|
||||||
|
{
|
||||||
|
case NET_EVPN_EAD:
|
||||||
|
return bsnprintf(buf, blen, "evpn ead %s %u %10b", rds, n->tag, &n->ead.esi);
|
||||||
|
|
||||||
|
case NET_EVPN_MAC:
|
||||||
|
if (n->length < sizeof(net_addr_evpn_mac_ip))
|
||||||
|
return bsnprintf(buf, blen, "evpn mac %s %u %6b *", rds, n->tag, &n->mac.mac);
|
||||||
|
else
|
||||||
|
return bsnprintf(buf, blen, "evpn mac %s %u %6b %I", rds, n->tag, &n->mac_ip.mac, n->mac_ip.ip);
|
||||||
|
|
||||||
|
case NET_EVPN_IMET:
|
||||||
|
return bsnprintf(buf, blen, "evpn imet %s %u %I", rds, n->tag, n->imet.rtr);
|
||||||
|
|
||||||
|
case NET_EVPN_ES:
|
||||||
|
return bsnprintf(buf, blen, "evpn es %s %10b %I", rds, &n->es.esi, n->es.rtr);
|
||||||
|
}
|
||||||
|
|
||||||
|
bug("unknown EVPN type %d", n->subtype);
|
||||||
|
}
|
50
lib/evpn.h
Normal file
50
lib/evpn.h
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* BIRD Internet Routing Daemon -- EVPN Net Type
|
||||||
|
*
|
||||||
|
* (c) 2023 Ondrej Zajicek <santiago@crfreenet.org>
|
||||||
|
* (c) 2023 CZ.NIC z.s.p.o.
|
||||||
|
*
|
||||||
|
* Can be freely distributed and used under the terms of the GNU GPL.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _BIRD_EVPN_NET_H_
|
||||||
|
#define _BIRD_EVPN_NET_H_
|
||||||
|
|
||||||
|
enum evpn_net_type {
|
||||||
|
NET_EVPN_EAD = 1,
|
||||||
|
NET_EVPN_MAC = 2,
|
||||||
|
NET_EVPN_IMET = 3,
|
||||||
|
NET_EVPN_ES = 4,
|
||||||
|
NET_EVPN_MAX
|
||||||
|
};
|
||||||
|
|
||||||
|
enum evpn_esi_type {
|
||||||
|
EVPN_ESI_MANUAL = 0,
|
||||||
|
EVPN_ESI_LACP = 1,
|
||||||
|
EVPN_ESI_MAX
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct evpn_esi {
|
||||||
|
u8 type;
|
||||||
|
u8 value[9];
|
||||||
|
} evpn_esi;
|
||||||
|
|
||||||
|
typedef struct mac_addr {
|
||||||
|
u8 addr[6];
|
||||||
|
} mac_addr;
|
||||||
|
|
||||||
|
#define MAC_NONE ((mac_addr){ })
|
||||||
|
|
||||||
|
static inline int mac_zero(mac_addr a)
|
||||||
|
{ return !memcmp(&a, &MAC_NONE, sizeof(mac_addr)); }
|
||||||
|
|
||||||
|
static inline int mac_nonzero(mac_addr a)
|
||||||
|
{ return !mac_zero(a); }
|
||||||
|
|
||||||
|
static inline int mac_compare(mac_addr a, mac_addr b)
|
||||||
|
{ return memcmp(&a, &b, sizeof(mac_addr)); }
|
||||||
|
|
||||||
|
union net_addr_evpn;
|
||||||
|
uint evpn_format(char *buf, uint blen, const union net_addr_evpn *n);
|
||||||
|
|
||||||
|
#endif
|
21
lib/net.c
21
lib/net.c
@ -16,6 +16,7 @@ const char * const net_label[] = {
|
|||||||
[NET_FLOW6] = "flow6",
|
[NET_FLOW6] = "flow6",
|
||||||
[NET_IP6_SADR]= "ipv6-sadr",
|
[NET_IP6_SADR]= "ipv6-sadr",
|
||||||
[NET_MPLS] = "mpls",
|
[NET_MPLS] = "mpls",
|
||||||
|
[NET_EVPN] = "evpn",
|
||||||
};
|
};
|
||||||
|
|
||||||
const u16 net_addr_length[] = {
|
const u16 net_addr_length[] = {
|
||||||
@ -29,6 +30,7 @@ const u16 net_addr_length[] = {
|
|||||||
[NET_FLOW6] = 0,
|
[NET_FLOW6] = 0,
|
||||||
[NET_IP6_SADR]= sizeof(net_addr_ip6_sadr),
|
[NET_IP6_SADR]= sizeof(net_addr_ip6_sadr),
|
||||||
[NET_MPLS] = sizeof(net_addr_mpls),
|
[NET_MPLS] = sizeof(net_addr_mpls),
|
||||||
|
[NET_EVPN] = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
const u8 net_max_prefix_length[] = {
|
const u8 net_max_prefix_length[] = {
|
||||||
@ -42,6 +44,7 @@ const u8 net_max_prefix_length[] = {
|
|||||||
[NET_FLOW6] = IP6_MAX_PREFIX_LENGTH,
|
[NET_FLOW6] = IP6_MAX_PREFIX_LENGTH,
|
||||||
[NET_IP6_SADR]= IP6_MAX_PREFIX_LENGTH,
|
[NET_IP6_SADR]= IP6_MAX_PREFIX_LENGTH,
|
||||||
[NET_MPLS] = 0,
|
[NET_MPLS] = 0,
|
||||||
|
[NET_EVPN] = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
const u16 net_max_text_length[] = {
|
const u16 net_max_text_length[] = {
|
||||||
@ -55,6 +58,7 @@ const u16 net_max_text_length[] = {
|
|||||||
[NET_FLOW6] = 0, /* "flow6 { ... }" */
|
[NET_FLOW6] = 0, /* "flow6 { ... }" */
|
||||||
[NET_IP6_SADR]= 92, /* "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128 from ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128" */
|
[NET_IP6_SADR]= 92, /* "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128 from ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128" */
|
||||||
[NET_MPLS] = 7, /* "1048575" */
|
[NET_MPLS] = 7, /* "1048575" */
|
||||||
|
[NET_EVPN] = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* There should be no implicit padding in net_addr structures */
|
/* There should be no implicit padding in net_addr structures */
|
||||||
@ -70,6 +74,13 @@ STATIC_ASSERT(sizeof(net_addr_flow6) == 20);
|
|||||||
STATIC_ASSERT(sizeof(net_addr_ip6_sadr) == 40);
|
STATIC_ASSERT(sizeof(net_addr_ip6_sadr) == 40);
|
||||||
STATIC_ASSERT(sizeof(net_addr_mpls) == 8);
|
STATIC_ASSERT(sizeof(net_addr_mpls) == 8);
|
||||||
|
|
||||||
|
STATIC_ASSERT(sizeof(net_addr_evpn_ead) == 32);
|
||||||
|
STATIC_ASSERT(sizeof(net_addr_evpn_mac) == 24);
|
||||||
|
STATIC_ASSERT(sizeof(net_addr_evpn_mac_ip) == 40);
|
||||||
|
STATIC_ASSERT(sizeof(net_addr_evpn_imet) == 32);
|
||||||
|
STATIC_ASSERT(sizeof(net_addr_evpn_es) == 48);
|
||||||
|
STATIC_ASSERT(sizeof(net_addr_evpn) == 48);
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
rd_format(const u64 rd, char *buf, int buflen)
|
rd_format(const u64 rd, char *buf, int buflen)
|
||||||
@ -123,6 +134,8 @@ net_format(const net_addr *N, char *buf, int buflen)
|
|||||||
return bsnprintf(buf, buflen, "%I6/%d from %I6/%d", n->ip6_sadr.dst_prefix, n->ip6_sadr.dst_pxlen, n->ip6_sadr.src_prefix, n->ip6_sadr.src_pxlen);
|
return bsnprintf(buf, buflen, "%I6/%d from %I6/%d", n->ip6_sadr.dst_prefix, n->ip6_sadr.dst_pxlen, n->ip6_sadr.src_prefix, n->ip6_sadr.src_pxlen);
|
||||||
case NET_MPLS:
|
case NET_MPLS:
|
||||||
return bsnprintf(buf, buflen, "%u", n->mpls.label);
|
return bsnprintf(buf, buflen, "%u", n->mpls.label);
|
||||||
|
case NET_EVPN:
|
||||||
|
return evpn_format(buf, buflen, &n->evpn);;
|
||||||
}
|
}
|
||||||
|
|
||||||
bug("unknown network type");
|
bug("unknown network type");
|
||||||
@ -147,6 +160,7 @@ net_pxmask(const net_addr *a)
|
|||||||
return ipa_from_ip6(ip6_mkmask(net6_pxlen(a)));
|
return ipa_from_ip6(ip6_mkmask(net6_pxlen(a)));
|
||||||
|
|
||||||
case NET_MPLS:
|
case NET_MPLS:
|
||||||
|
case NET_EVPN:
|
||||||
default:
|
default:
|
||||||
return IPA_NONE;
|
return IPA_NONE;
|
||||||
}
|
}
|
||||||
@ -180,6 +194,8 @@ net_compare(const net_addr *a, const net_addr *b)
|
|||||||
return net_compare_ip6_sadr((const net_addr_ip6_sadr *) a, (const net_addr_ip6_sadr *) b);
|
return net_compare_ip6_sadr((const net_addr_ip6_sadr *) a, (const net_addr_ip6_sadr *) b);
|
||||||
case NET_MPLS:
|
case NET_MPLS:
|
||||||
return net_compare_mpls((const net_addr_mpls *) a, (const net_addr_mpls *) b);
|
return net_compare_mpls((const net_addr_mpls *) a, (const net_addr_mpls *) b);
|
||||||
|
case NET_EVPN:
|
||||||
|
return net_compare_evpn((const net_addr_evpn *) a, (const net_addr_evpn *) b);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -201,6 +217,7 @@ net_hash(const net_addr *n)
|
|||||||
case NET_FLOW6: return NET_HASH(n, flow6);
|
case NET_FLOW6: return NET_HASH(n, flow6);
|
||||||
case NET_IP6_SADR: return NET_HASH(n, ip6_sadr);
|
case NET_IP6_SADR: return NET_HASH(n, ip6_sadr);
|
||||||
case NET_MPLS: return NET_HASH(n, mpls);
|
case NET_MPLS: return NET_HASH(n, mpls);
|
||||||
|
case NET_EVPN: return NET_HASH(n, evpn);
|
||||||
default: bug("invalid type");
|
default: bug("invalid type");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -223,6 +240,7 @@ net_validate(const net_addr *n)
|
|||||||
case NET_FLOW6: return NET_VALIDATE(n, flow6);
|
case NET_FLOW6: return NET_VALIDATE(n, flow6);
|
||||||
case NET_IP6_SADR: return NET_VALIDATE(n, ip6_sadr);
|
case NET_IP6_SADR: return NET_VALIDATE(n, ip6_sadr);
|
||||||
case NET_MPLS: return NET_VALIDATE(n, mpls);
|
case NET_MPLS: return NET_VALIDATE(n, mpls);
|
||||||
|
case NET_EVPN: return NET_VALIDATE(n, evpn);
|
||||||
default: return 0;
|
default: return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -250,6 +268,7 @@ net_normalize(net_addr *N)
|
|||||||
return net_normalize_ip6_sadr(&n->ip6_sadr);
|
return net_normalize_ip6_sadr(&n->ip6_sadr);
|
||||||
|
|
||||||
case NET_MPLS:
|
case NET_MPLS:
|
||||||
|
case NET_EVPN:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -277,6 +296,7 @@ net_classify(const net_addr *N)
|
|||||||
return ip6_zero(n->ip6_sadr.dst_prefix) ? (IADDR_HOST | SCOPE_UNIVERSE) : ip6_classify(&n->ip6_sadr.dst_prefix);
|
return ip6_zero(n->ip6_sadr.dst_prefix) ? (IADDR_HOST | SCOPE_UNIVERSE) : ip6_classify(&n->ip6_sadr.dst_prefix);
|
||||||
|
|
||||||
case NET_MPLS:
|
case NET_MPLS:
|
||||||
|
case NET_EVPN: /* ?? */
|
||||||
return IADDR_HOST | SCOPE_UNIVERSE;
|
return IADDR_HOST | SCOPE_UNIVERSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -310,6 +330,7 @@ ipa_in_netX(const ip_addr a, const net_addr *n)
|
|||||||
ip6_mkmask(net6_pxlen(n))));
|
ip6_mkmask(net6_pxlen(n))));
|
||||||
|
|
||||||
case NET_MPLS:
|
case NET_MPLS:
|
||||||
|
case NET_EVPN:
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
136
lib/net.h
136
lib/net.h
@ -11,6 +11,8 @@
|
|||||||
#define _BIRD_NET_H_
|
#define _BIRD_NET_H_
|
||||||
|
|
||||||
#include "lib/ip.h"
|
#include "lib/ip.h"
|
||||||
|
#include "lib/evpn.h"
|
||||||
|
#include "lib/hash.h"
|
||||||
|
|
||||||
|
|
||||||
#define NET_IP4 1
|
#define NET_IP4 1
|
||||||
@ -23,7 +25,8 @@
|
|||||||
#define NET_FLOW6 8
|
#define NET_FLOW6 8
|
||||||
#define NET_IP6_SADR 9
|
#define NET_IP6_SADR 9
|
||||||
#define NET_MPLS 10
|
#define NET_MPLS 10
|
||||||
#define NET_MAX 11
|
#define NET_EVPN 11
|
||||||
|
#define NET_MAX 12
|
||||||
|
|
||||||
#define NB_IP4 (1 << NET_IP4)
|
#define NB_IP4 (1 << NET_IP4)
|
||||||
#define NB_IP6 (1 << NET_IP6)
|
#define NB_IP6 (1 << NET_IP6)
|
||||||
@ -35,12 +38,13 @@
|
|||||||
#define NB_FLOW6 (1 << NET_FLOW6)
|
#define NB_FLOW6 (1 << NET_FLOW6)
|
||||||
#define NB_IP6_SADR (1 << NET_IP6_SADR)
|
#define NB_IP6_SADR (1 << NET_IP6_SADR)
|
||||||
#define NB_MPLS (1 << NET_MPLS)
|
#define NB_MPLS (1 << NET_MPLS)
|
||||||
|
#define NB_EVPN (1 << NET_EVPN)
|
||||||
|
|
||||||
#define NB_IP (NB_IP4 | NB_IP6)
|
#define NB_IP (NB_IP4 | NB_IP6)
|
||||||
#define NB_VPN (NB_VPN4 | NB_VPN6)
|
#define NB_VPN (NB_VPN4 | NB_VPN6)
|
||||||
#define NB_ROA (NB_ROA4 | NB_ROA6)
|
#define NB_ROA (NB_ROA4 | NB_ROA6)
|
||||||
#define NB_FLOW (NB_FLOW4 | NB_FLOW6)
|
#define NB_FLOW (NB_FLOW4 | NB_FLOW6)
|
||||||
#define NB_DEST (NB_IP | NB_IP6_SADR | NB_VPN | NB_MPLS)
|
#define NB_DEST (NB_IP | NB_IP6_SADR | NB_VPN | NB_MPLS | NB_EVPN)
|
||||||
#define NB_ANY 0xffffffff
|
#define NB_ANY 0xffffffff
|
||||||
|
|
||||||
|
|
||||||
@ -133,6 +137,78 @@ typedef struct net_addr_ip6_sadr {
|
|||||||
ip6_addr src_prefix;
|
ip6_addr src_prefix;
|
||||||
} net_addr_ip6_sadr;
|
} net_addr_ip6_sadr;
|
||||||
|
|
||||||
|
typedef struct net_addr_evpn_ead {
|
||||||
|
u8 type;
|
||||||
|
u8 subtype;
|
||||||
|
u16 length;
|
||||||
|
u32 tag;
|
||||||
|
u64 rd;
|
||||||
|
|
||||||
|
evpn_esi esi;
|
||||||
|
u8 padding[6];
|
||||||
|
} net_addr_evpn_ead;
|
||||||
|
|
||||||
|
typedef struct net_addr_evpn_mac {
|
||||||
|
u8 type;
|
||||||
|
u8 subtype;
|
||||||
|
u16 length;
|
||||||
|
u32 tag;
|
||||||
|
u64 rd;
|
||||||
|
|
||||||
|
mac_addr mac;
|
||||||
|
u16 padding;
|
||||||
|
} net_addr_evpn_mac;
|
||||||
|
|
||||||
|
typedef struct net_addr_evpn_mac_ip {
|
||||||
|
u8 type;
|
||||||
|
u8 subtype;
|
||||||
|
u16 length;
|
||||||
|
u32 tag;
|
||||||
|
u64 rd;
|
||||||
|
|
||||||
|
mac_addr mac;
|
||||||
|
u16 padding0;
|
||||||
|
ip_addr ip;
|
||||||
|
} net_addr_evpn_mac_ip;
|
||||||
|
|
||||||
|
typedef struct net_addr_evpn_imet {
|
||||||
|
u8 type;
|
||||||
|
u8 subtype;
|
||||||
|
u16 length;
|
||||||
|
u32 tag;
|
||||||
|
u64 rd;
|
||||||
|
|
||||||
|
ip_addr rtr;
|
||||||
|
} net_addr_evpn_imet;
|
||||||
|
|
||||||
|
typedef struct net_addr_evpn_es {
|
||||||
|
u8 type;
|
||||||
|
u8 subtype;
|
||||||
|
u16 length;
|
||||||
|
u32 tag; /* unused */
|
||||||
|
u64 rd;
|
||||||
|
|
||||||
|
evpn_esi esi;
|
||||||
|
u8 padding[6];
|
||||||
|
ip_addr rtr;
|
||||||
|
} net_addr_evpn_es;
|
||||||
|
|
||||||
|
typedef union net_addr_evpn {
|
||||||
|
struct {
|
||||||
|
u8 type;
|
||||||
|
u8 subtype;
|
||||||
|
u16 length;
|
||||||
|
u32 tag;
|
||||||
|
u64 rd;
|
||||||
|
byte data[0];
|
||||||
|
};
|
||||||
|
net_addr_evpn_ead ead;
|
||||||
|
net_addr_evpn_mac mac;
|
||||||
|
net_addr_evpn_mac_ip mac_ip;
|
||||||
|
net_addr_evpn_imet imet;
|
||||||
|
net_addr_evpn_es es;
|
||||||
|
} net_addr_evpn;
|
||||||
|
|
||||||
typedef union net_addr_union {
|
typedef union net_addr_union {
|
||||||
net_addr n;
|
net_addr n;
|
||||||
net_addr_ip4 ip4;
|
net_addr_ip4 ip4;
|
||||||
@ -145,6 +221,7 @@ typedef union net_addr_union {
|
|||||||
net_addr_flow6 flow6;
|
net_addr_flow6 flow6;
|
||||||
net_addr_ip6_sadr ip6_sadr;
|
net_addr_ip6_sadr ip6_sadr;
|
||||||
net_addr_mpls mpls;
|
net_addr_mpls mpls;
|
||||||
|
net_addr_evpn evpn;
|
||||||
} net_addr_union;
|
} net_addr_union;
|
||||||
|
|
||||||
|
|
||||||
@ -187,6 +264,22 @@ extern const u16 net_max_text_length[];
|
|||||||
((net_addr_mpls) { NET_MPLS, 20, sizeof(net_addr_mpls), label })
|
((net_addr_mpls) { NET_MPLS, 20, sizeof(net_addr_mpls), label })
|
||||||
|
|
||||||
|
|
||||||
|
#define NET_ADDR_EVPN_EAD(rd, tag, esi) \
|
||||||
|
((net_addr_evpn_ead) { NET_EVPN, NET_EVPN_EAD, sizeof(net_addr_evpn_ead), tag, rd, .esi = esi })
|
||||||
|
|
||||||
|
#define NET_ADDR_EVPN_MAC(rd, tag, mac) \
|
||||||
|
((net_addr_evpn_mac) { NET_EVPN, NET_EVPN_MAC, sizeof(net_addr_evpn_mac), tag, rd, .mac = mac })
|
||||||
|
|
||||||
|
#define NET_ADDR_EVPN_MAC_IP(rd, tag, mac, ip) \
|
||||||
|
((net_addr_evpn_mac_ip) { NET_EVPN, NET_EVPN_MAC, sizeof(net_addr_evpn_mac_ip), tag, rd, .mac = mac, .ip = ip })
|
||||||
|
|
||||||
|
#define NET_ADDR_EVPN_IMET(rd, tag, rtr) \
|
||||||
|
((net_addr_evpn_imet) { NET_EVPN, NET_EVPN_IMET, sizeof(net_addr_evpn_imet), tag, rd, .rtr = rtr })
|
||||||
|
|
||||||
|
#define NET_ADDR_EVPN_ES(rd, esi, rtr) \
|
||||||
|
((net_addr_evpn_es) { NET_EVPN, NET_EVPN_ES, sizeof(net_addr_evpn_es), 0, rd, .esi = esi, .rtr = rtr })
|
||||||
|
|
||||||
|
|
||||||
static inline void net_fill_ip4(net_addr *a, ip4_addr prefix, uint pxlen)
|
static inline void net_fill_ip4(net_addr *a, ip4_addr prefix, uint pxlen)
|
||||||
{ *(net_addr_ip4 *)a = NET_ADDR_IP4(prefix, pxlen); }
|
{ *(net_addr_ip4 *)a = NET_ADDR_IP4(prefix, pxlen); }
|
||||||
|
|
||||||
@ -211,6 +304,23 @@ static inline void net_fill_ip6_sadr(net_addr *a, ip6_addr dst_prefix, uint dst_
|
|||||||
static inline void net_fill_mpls(net_addr *a, u32 label)
|
static inline void net_fill_mpls(net_addr *a, u32 label)
|
||||||
{ *(net_addr_mpls *)a = NET_ADDR_MPLS(label); }
|
{ *(net_addr_mpls *)a = NET_ADDR_MPLS(label); }
|
||||||
|
|
||||||
|
|
||||||
|
static inline void net_fill_evpn_ead(net_addr *a, u64 rd, u32 tag, evpn_esi esi)
|
||||||
|
{ *(net_addr_evpn_ead *)a = NET_ADDR_EVPN_EAD(rd, tag, esi); }
|
||||||
|
|
||||||
|
static inline void net_fill_evpn_mac(net_addr *a, u64 rd, u32 tag, mac_addr mac)
|
||||||
|
{ *(net_addr_evpn_mac *)a = NET_ADDR_EVPN_MAC(rd, tag, mac); }
|
||||||
|
|
||||||
|
static inline void net_fill_evpn_mac_ip(net_addr *a, u64 rd, u32 tag, mac_addr mac, ip_addr ip)
|
||||||
|
{ *(net_addr_evpn_mac_ip *)a = NET_ADDR_EVPN_MAC_IP(rd, tag, mac, ip); }
|
||||||
|
|
||||||
|
static inline void net_fill_evpn_imet(net_addr *a, u64 rd, u32 tag, ip_addr rtr)
|
||||||
|
{ *(net_addr_evpn_imet *)a = NET_ADDR_EVPN_IMET(rd, tag, rtr); }
|
||||||
|
|
||||||
|
static inline void net_fill_evpn_es(net_addr *a, u64 rd, evpn_esi esi, ip_addr rtr)
|
||||||
|
{ *(net_addr_evpn_es *)a = NET_ADDR_EVPN_ES(rd, esi, rtr); }
|
||||||
|
|
||||||
|
|
||||||
static inline void net_fill_ipa(net_addr *a, ip_addr prefix, uint pxlen)
|
static inline void net_fill_ipa(net_addr *a, ip_addr prefix, uint pxlen)
|
||||||
{
|
{
|
||||||
if (ipa_is_ip4(prefix))
|
if (ipa_is_ip4(prefix))
|
||||||
@ -296,6 +406,7 @@ static inline ip_addr net_prefix(const net_addr *a)
|
|||||||
return ipa_from_ip6(net6_prefix(a));
|
return ipa_from_ip6(net6_prefix(a));
|
||||||
|
|
||||||
case NET_MPLS:
|
case NET_MPLS:
|
||||||
|
case NET_EVPN:
|
||||||
default:
|
default:
|
||||||
return IPA_NONE;
|
return IPA_NONE;
|
||||||
}
|
}
|
||||||
@ -328,6 +439,8 @@ static inline u64 net_rd(const net_addr *a)
|
|||||||
return ((net_addr_vpn4 *)a)->rd;
|
return ((net_addr_vpn4 *)a)->rd;
|
||||||
case NET_VPN6:
|
case NET_VPN6:
|
||||||
return ((net_addr_vpn6 *)a)->rd;
|
return ((net_addr_vpn6 *)a)->rd;
|
||||||
|
case NET_EVPN:
|
||||||
|
return ((net_addr_evpn *)a)->rd;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -366,6 +479,9 @@ static inline int net_equal_ip6_sadr(const net_addr_ip6_sadr *a, const net_addr_
|
|||||||
static inline int net_equal_mpls(const net_addr_mpls *a, const net_addr_mpls *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)); }
|
{ return !memcmp(a, b, sizeof(net_addr_mpls)); }
|
||||||
|
|
||||||
|
static inline int net_equal_evpn(const net_addr_evpn *a, const net_addr_evpn *b)
|
||||||
|
{ return net_equal((const net_addr *) a, (const net_addr *) b); }
|
||||||
|
|
||||||
|
|
||||||
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); }
|
||||||
@ -442,6 +558,13 @@ static inline int net_compare_ip6_sadr(const net_addr_ip6_sadr *a, const net_add
|
|||||||
static inline int net_compare_mpls(const net_addr_mpls *a, const net_addr_mpls *b)
|
static inline int net_compare_mpls(const net_addr_mpls *a, const net_addr_mpls *b)
|
||||||
{ return uint_cmp(a->label, b->label); }
|
{ return uint_cmp(a->label, b->label); }
|
||||||
|
|
||||||
|
static inline int net_compare_evpn(const net_addr_evpn *a, const net_addr_evpn *b)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
uint_cmp(a->subtype, b->subtype) ?: u64_cmp(a->rd, b->rd) ?: uint_cmp(a->tag, b->tag) ?:
|
||||||
|
uint_cmp(a->length, b->length) ?: memcmp(a->data, b->data, a->length - OFFSETOF(net_addr_evpn, data));
|
||||||
|
}
|
||||||
|
|
||||||
int net_compare(const net_addr *a, const net_addr *b);
|
int net_compare(const net_addr *a, const net_addr *b);
|
||||||
|
|
||||||
|
|
||||||
@ -478,6 +601,9 @@ static inline void net_copy_ip6_sadr(net_addr_ip6_sadr *dst, const net_addr_ip6_
|
|||||||
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)); }
|
||||||
|
|
||||||
|
static inline void net_copy_evpn(net_addr_evpn *dst, const net_addr_evpn *src)
|
||||||
|
{ memcpy(dst, src, src->length); }
|
||||||
|
|
||||||
|
|
||||||
static inline u32 px4_hash(ip4_addr prefix, u32 pxlen)
|
static inline u32 px4_hash(ip4_addr prefix, u32 pxlen)
|
||||||
{ return ip4_hash(prefix) ^ (pxlen << 26); }
|
{ return ip4_hash(prefix) ^ (pxlen << 26); }
|
||||||
@ -521,6 +647,9 @@ static inline u32 net_hash_ip6_sadr(const net_addr_ip6_sadr *n)
|
|||||||
static inline u32 net_hash_mpls(const net_addr_mpls *n)
|
static inline u32 net_hash_mpls(const net_addr_mpls *n)
|
||||||
{ return u32_hash(n->label); }
|
{ return u32_hash(n->label); }
|
||||||
|
|
||||||
|
static inline u32 net_hash_evpn(const net_addr_evpn *n)
|
||||||
|
{ return mem_hash(&n->tag, n->length - OFFSETOF(net_addr_evpn, tag)); }
|
||||||
|
|
||||||
u32 net_hash(const net_addr *a);
|
u32 net_hash(const net_addr *a);
|
||||||
|
|
||||||
|
|
||||||
@ -570,6 +699,9 @@ static inline int net_validate_flow6(const net_addr_flow6 *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); }
|
||||||
|
|
||||||
|
static inline int net_validate_evpn(const net_addr_evpn *n UNUSED)
|
||||||
|
{ return 1; /* XXX */ }
|
||||||
|
|
||||||
static inline int net_validate_ip6_sadr(const net_addr_ip6_sadr *n)
|
static inline int net_validate_ip6_sadr(const net_addr_ip6_sadr *n)
|
||||||
{ return net_validate_px6(n->dst_prefix, n->dst_pxlen) && net_validate_px6(n->src_prefix, n->src_pxlen); }
|
{ return net_validate_px6(n->dst_prefix, n->dst_pxlen) && net_validate_px6(n->src_prefix, n->src_pxlen); }
|
||||||
|
|
||||||
|
@ -140,6 +140,7 @@ CF_ENUM(T_ENUM_RTD, RTD_, UNICAST, BLACKHOLE, UNREACHABLE, PROHIBIT)
|
|||||||
CF_ENUM(T_ENUM_ROA, ROA_, UNKNOWN, VALID, INVALID)
|
CF_ENUM(T_ENUM_ROA, ROA_, UNKNOWN, VALID, INVALID)
|
||||||
CF_ENUM_PX(T_ENUM_AF, AF_, AFI_, IPV4, IPV6)
|
CF_ENUM_PX(T_ENUM_AF, AF_, AFI_, IPV4, IPV6)
|
||||||
CF_ENUM(T_ENUM_MPLS_POLICY, MPLS_POLICY_, NONE, STATIC, PREFIX, AGGREGATE, VRF)
|
CF_ENUM(T_ENUM_MPLS_POLICY, MPLS_POLICY_, NONE, STATIC, PREFIX, AGGREGATE, VRF)
|
||||||
|
CF_ENUM(T_ENUM_NET_EVPN, NET_EVPN_, EAD, MAC, IMET, ES)
|
||||||
|
|
||||||
%type <i32> idval
|
%type <i32> idval
|
||||||
%type <f> imexport
|
%type <f> imexport
|
||||||
@ -202,6 +203,7 @@ net_type_base:
|
|||||||
| ROA6 { $$ = NET_ROA6; }
|
| ROA6 { $$ = NET_ROA6; }
|
||||||
| FLOW4{ $$ = NET_FLOW4; }
|
| FLOW4{ $$ = NET_FLOW4; }
|
||||||
| FLOW6{ $$ = NET_FLOW6; }
|
| FLOW6{ $$ = NET_FLOW6; }
|
||||||
|
| EVPN { $$ = NET_EVPN; }
|
||||||
;
|
;
|
||||||
|
|
||||||
net_type:
|
net_type:
|
||||||
@ -209,7 +211,7 @@ net_type:
|
|||||||
| MPLS { $$ = NET_MPLS; }
|
| MPLS { $$ = NET_MPLS; }
|
||||||
;
|
;
|
||||||
|
|
||||||
CF_ENUM(T_ENUM_NETTYPE, NET_, IP4, IP6, VPN4, VPN6, ROA4, ROA6, FLOW4, FLOW6, IP6_SADR, MPLS)
|
CF_ENUM(T_ENUM_NETTYPE, NET_, IP4, IP6, VPN4, VPN6, ROA4, ROA6, FLOW4, FLOW6, IP6_SADR, MPLS, EVPN)
|
||||||
|
|
||||||
|
|
||||||
/* Creation of routing tables */
|
/* Creation of routing tables */
|
||||||
|
@ -279,6 +279,7 @@ fib_find(struct fib *f, const net_addr *a)
|
|||||||
case NET_FLOW6: return FIB_FIND(f, a, flow6);
|
case NET_FLOW6: return FIB_FIND(f, a, flow6);
|
||||||
case NET_IP6_SADR: return FIB_FIND(f, a, ip6_sadr);
|
case NET_IP6_SADR: return FIB_FIND(f, a, ip6_sadr);
|
||||||
case NET_MPLS: return FIB_FIND(f, a, mpls);
|
case NET_MPLS: return FIB_FIND(f, a, mpls);
|
||||||
|
case NET_EVPN: return FIB_FIND(f, a, evpn);
|
||||||
default: bug("invalid type");
|
default: bug("invalid type");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -300,6 +301,7 @@ fib_insert(struct fib *f, const net_addr *a, struct fib_node *e)
|
|||||||
case NET_FLOW6: FIB_INSERT(f, a, e, flow6); return;
|
case NET_FLOW6: FIB_INSERT(f, a, e, flow6); return;
|
||||||
case NET_IP6_SADR: FIB_INSERT(f, a, e, ip6_sadr); return;
|
case NET_IP6_SADR: FIB_INSERT(f, a, e, ip6_sadr); return;
|
||||||
case NET_MPLS: FIB_INSERT(f, a, e, mpls); return;
|
case NET_MPLS: FIB_INSERT(f, a, e, mpls); return;
|
||||||
|
case NET_EVPN: FIB_INSERT(f, a, e, evpn); return;
|
||||||
default: bug("invalid type");
|
default: bug("invalid type");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user