Permalink
Browse files

bgpd: add basic support for ETI for BGP EVPN

Ethernet Tag ID (ETI) is part of the prefix. It cannot just be ignored
as it needs to be used when checking for prefix uniqueness. Moreover,
when using Quagga as a route reflector, we need to keep its
value. Therefore, we correctly parse and encode it. ESI is still
ignored while it should be reflected correctly.
  • Loading branch information...
vincentbernat committed Apr 13, 2018
1 parent 472f46b commit 53f9a8357d4a45236cc13d93b5250fb805cbf535
Showing with 27 additions and 13 deletions.
  1. +22 −10 bgpd/bgp_evpn.c
  2. +2 −2 bgpd/bgp_evpn_ui.c
  3. +3 −1 lib/prefix.h
@@ -1747,6 +1747,7 @@ process_type2_route (struct peer *peer, afi_t afi, safi_t safi,
u_char ipaddr_len;
u_char macaddr_len;
u_char *tagpnt;
uint32_t eth_tag;
int ret;

/* Type-2 route should be either 33, 37 or 49 bytes or an
@@ -1778,7 +1779,9 @@ process_type2_route (struct peer *peer, afi_t afi, safi_t safi,
/* Skip over Ethernet Seg Identifier for now. */
pfx += 10;

/* Skip over Ethernet Tag for now. */
/* Copy Ethernet Tag */
memcpy(&eth_tag, pfx, 4);
p.prefix.eth_tag = ntohl(eth_tag);
pfx += 4;

/* Get the MAC Addr len */
@@ -1843,6 +1846,7 @@ process_type3_route (struct peer *peer, afi_t afi, safi_t safi,
struct prefix_rd prd;
struct prefix_evpn p;
u_char ipaddr_len;
uint32_t eth_tag;
int ret;

/* Type-3 route should be either 17 or 29 bytes: RD (8), Eth Tag (4),
@@ -1867,7 +1871,9 @@ process_type3_route (struct peer *peer, afi_t afi, safi_t safi,
p.prefixlen = EVPN_TYPE_3_ROUTE_PREFIXLEN;
p.prefix.route_type = BGP_EVPN_IMET_ROUTE;

/* Skip over Ethernet Tag for now. */
/* Copy Ethernet Tag */
memcpy(&eth_tag, pfx, 4);
p.prefix.eth_tag = ntohl(eth_tag);
pfx += 4;

/* Get the IP. */
@@ -1923,25 +1929,31 @@ bgp_evpn_route2str (struct prefix_evpn *p, char *buf, int len)

if (p->prefix.route_type == BGP_EVPN_IMET_ROUTE)
{
snprintf (buf, len, "[%d]:[0]:[%d]:[%s]",
p->prefix.route_type, IS_EVPN_PREFIX_IPADDR_V4(p) ? \
snprintf (buf, len, "[%d]:[%d]:[%d]:[%s]",
p->prefix.route_type,
p->prefix.eth_tag,
IS_EVPN_PREFIX_IPADDR_V4(p) ? \
IPV4_MAX_BITLEN : IPV6_MAX_BITLEN,
inet_ntoa(p->prefix.ip.ip.v4_addr));
}
if (p->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE)
{
if (IS_EVPN_PREFIX_IPADDR_NONE(p))
snprintf (buf, len, "[%d]:[0]:[0]:[%d]:[%s]",
p->prefix.route_type, 8*ETHER_ADDR_LEN,
snprintf (buf, len, "[%d]:[%d]:[%d]:[%s]",
p->prefix.route_type,
p->prefix.eth_tag,
8*ETHER_ADDR_LEN,
mac2str (&p->prefix.mac, buf1, sizeof(buf1)));
else
{
u_char family;

family = IS_EVPN_PREFIX_IPADDR_V4(p) ? \
AF_INET : AF_INET6;
snprintf (buf, len, "[%d]:[0]:[0]:[%d]:[%s]:[%d]:[%s]",
p->prefix.route_type, 8*ETHER_ADDR_LEN,
snprintf (buf, len, "[%d]:[%d]:[%d]:[%s]:[%d]:[%s]",
p->prefix.route_type,
p->prefix.eth_tag,
8*ETHER_ADDR_LEN,
mac2str (&p->prefix.mac, buf1, sizeof(buf1)),
family == AF_INET ? IPV4_MAX_BITLEN : IPV6_MAX_BITLEN,
inet_ntop (family, &p->prefix.ip.ip.addr,
@@ -2170,7 +2182,7 @@ bgp_evpn_encode_prefix (struct stream *s, struct prefix *p,
case BGP_EVPN_IMET_ROUTE:
stream_putc (s, 17); // TODO: length - assumes IPv4 address
stream_put (s, prd->val, 8); /* RD */
stream_putl (s, 0); /* Ethernet Tag ID */
stream_putl (s, evp->prefix.eth_tag); /* Ethernet Tag ID */
stream_putc (s, IPV4_MAX_BITLEN); /* IP address Length - bits */
/* Originating Router's IP Addr */
stream_put_in_addr (s, &evp->prefix.ip.ip.v4_addr);
@@ -2184,7 +2196,7 @@ bgp_evpn_encode_prefix (struct stream *s, struct prefix *p,
stream_putc (s, 33 + ipa_len); // 1 VNI
stream_put (s, prd->val, 8); /* RD */
stream_put (s, 0, 10); /* ESI */
stream_putl (s, 0); /* Ethernet Tag ID */
stream_putl (s, evp->prefix.eth_tag); /* Ethernet Tag ID */
stream_putc (s, 8*ETHER_ADDR_LEN); /* Mac Addr Len - bits */
stream_put (s, evp->prefix.mac.octet, 6); /* Mac Addr */
stream_putc (s, 8*ipa_len); /* IP address Length */
@@ -250,7 +250,7 @@ bgp_evpn_show_route_header (struct vty *vty, struct bgp *bgp)
"* valid, > best, i - internal%s", VTY_NEWLINE);
vty_out (vty, "Origin codes: i - IGP, e - EGP, ? - incomplete%s",
VTY_NEWLINE);
vty_out (vty, "EVPN type-2 prefix: [2]:[ESI]:[EthTag]:[MAClen]:[MAC]%s",
vty_out (vty, "EVPN type-2 prefix: [2]:[EthTag]:[MAClen]:[MAC]%s",
VTY_NEWLINE);
vty_out (vty, "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]%s%s",
VTY_NEWLINE, VTY_NEWLINE);
@@ -976,7 +976,7 @@ bgp_evpn_show_route_rd (struct vty *vty, struct bgp *bgp,
/* RD header and legend - once overall. */
if (rd_header)
{
vty_out (vty, "EVPN type-2 prefix: [2]:[ESI]:[EthTag]:[MAClen]:"
vty_out (vty, "EVPN type-2 prefix: [2]:[EthTag]:[MAClen]:"
"[MAC]%s", VTY_NEWLINE);
vty_out (vty, "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:"
"[OrigIP]%s%s", VTY_NEWLINE, VTY_NEWLINE);
@@ -60,8 +60,10 @@ struct ethaddr {
/* EVPN address (RFC 7432) */
struct evpn_addr
{
u_char route_type;
uint8_t route_type;
uint8_t ip_prefix_length;
struct ethaddr mac;
uint32_t eth_tag;
struct ipaddr ip;
};

0 comments on commit 53f9a83

Please sign in to comment.