lib: Refine EVPN prefix definition

Modify EVPN prefix to use the generic IP address structure. Add support
for EVPN type-2 and type-3 prefix dump. Fix references to modified fields
as needed.

Signed-off-by: Vivek Venkatraman <vivek@cumulusnetworks.com>
Reviewed-by:   Donald Sharp <sharpd@cumulusnetworks.com>
This commit is contained in:
vivek 2017-05-14 22:20:33 -07:00
parent 482c0fb076
commit 86f1ef44f7
5 changed files with 99 additions and 54 deletions

View File

@ -125,13 +125,13 @@ bgp_build_evpn_prefix(int evpn_type, uint32_t eth_tag, struct prefix *dst)
p_evpn_p->eth_tag = eth_tag; p_evpn_p->eth_tag = eth_tag;
p_evpn_p->ip_prefix_length = p2.prefixlen; p_evpn_p->ip_prefix_length = p2.prefixlen;
if (src->family == AF_INET) { if (src->family == AF_INET) {
p_evpn_p->flags = IP_PREFIX_V4; SET_IPADDR_V4 (&p_evpn_p->ip);
memcpy(&p_evpn_p->ip.v4_addr, &src->u.prefix4, memcpy(&p_evpn_p->ip.ipaddr_v4, &src->u.prefix4,
sizeof(struct in_addr)); sizeof(struct in_addr));
dst->prefixlen = (u_char) PREFIX_LEN_ROUTE_TYPE_5_IPV4; dst->prefixlen = (u_char) PREFIX_LEN_ROUTE_TYPE_5_IPV4;
} else { } else {
p_evpn_p->flags = IP_PREFIX_V6; SET_IPADDR_V6 (&p_evpn_p->ip);
memcpy(&p_evpn_p->ip.v6_addr, &src->u.prefix6, memcpy(&p_evpn_p->ip.ipaddr_v6, &src->u.prefix6,
sizeof(struct in6_addr)); sizeof(struct in6_addr));
dst->prefixlen = (u_char) PREFIX_LEN_ROUTE_TYPE_5_IPV6; dst->prefixlen = (u_char) PREFIX_LEN_ROUTE_TYPE_5_IPV6;
} }

View File

@ -124,20 +124,20 @@ bgp_nlri_parse_evpn(struct peer *peer, struct attr *attr,
/* determine IPv4 or IPv6 prefix */ /* determine IPv4 or IPv6 prefix */
if (route_length - 4 - 10 - 8 - if (route_length - 4 - 10 - 8 -
3 /* label to be read */ >= 32) { 3 /* label to be read */ >= 32) {
p_evpn_p->flags = IP_PREFIX_V6; SET_IPADDR_V6 (&p_evpn_p->ip);
memcpy(&(p_evpn_p->ip.v6_addr), pnt, 16); memcpy(&(p_evpn_p->ip.ipaddr_v6), pnt, 16);
pnt += 16; pnt += 16;
memcpy(&evpn.gw_ip.ipv6, pnt, 16); memcpy(&evpn.gw_ip.ipv6, pnt, 16);
pnt += 16; pnt += 16;
} else { } else {
p_evpn_p->flags = IP_PREFIX_V4; SET_IPADDR_V4 (&p_evpn_p->ip);
memcpy(&(p_evpn_p->ip.v4_addr), pnt, 4); memcpy(&(p_evpn_p->ip.ipaddr_v4), pnt, 4);
pnt += 4; pnt += 4;
memcpy(&evpn.gw_ip.ipv4, pnt, 4); memcpy(&evpn.gw_ip.ipv4, pnt, 4);
pnt += 4; pnt += 4;
} }
p.family = AFI_L2VPN; p.family = AFI_L2VPN;
if (p_evpn_p->flags == IP_PREFIX_V4) if (IS_IPADDR_V4(&p_evpn_p->ip))
p.prefixlen = p.prefixlen =
(u_char) PREFIX_LEN_ROUTE_TYPE_5_IPV4; (u_char) PREFIX_LEN_ROUTE_TYPE_5_IPV4;
else else
@ -184,7 +184,7 @@ bgp_packet_mpattr_route_type_5(struct stream *s,
if (p->family != AF_ETHERNET) if (p->family != AF_ETHERNET)
return; return;
p_evpn_p = &(p->u.prefix_evpn); p_evpn_p = &(p->u.prefix_evpn);
if (p_evpn_p->flags & IP_PREFIX_V4) if (IS_IPADDR_V4(&p_evpn_p->ip))
len = 8; /* ipv4 */ len = 8; /* ipv4 */
else else
len = 32; /* ipv6 */ len = 32; /* ipv6 */
@ -199,12 +199,12 @@ bgp_packet_mpattr_route_type_5(struct stream *s,
stream_put(s, &temp, 10); stream_put(s, &temp, 10);
stream_putl(s, p_evpn_p->eth_tag); stream_putl(s, p_evpn_p->eth_tag);
stream_putc(s, p_evpn_p->ip_prefix_length); stream_putc(s, p_evpn_p->ip_prefix_length);
if (p_evpn_p->flags & IP_PREFIX_V4) if (IS_IPADDR_V4(&p_evpn_p->ip))
stream_put_ipv4(s, p_evpn_p->ip.v4_addr.s_addr); stream_put_ipv4(s, p_evpn_p->ip.ipaddr_v4.s_addr);
else else
stream_put(s, &p_evpn_p->ip.v6_addr, 16); stream_put(s, &p_evpn_p->ip.ipaddr_v6, 16);
if (attr && attr->extra) { if (attr && attr->extra) {
if (p_evpn_p->flags & IP_PREFIX_V4) if (IS_IPADDR_V4(&p_evpn_p->ip))
stream_put_ipv4(s, stream_put_ipv4(s,
attr->extra->evpn_overlay.gw_ip.ipv4. attr->extra->evpn_overlay.gw_ip.ipv4.
s_addr); s_addr);
@ -212,7 +212,7 @@ bgp_packet_mpattr_route_type_5(struct stream *s,
stream_put(s, &(attr->extra->evpn_overlay.gw_ip.ipv6), stream_put(s, &(attr->extra->evpn_overlay.gw_ip.ipv6),
16); 16);
} else { } else {
if (p_evpn_p->flags & IP_PREFIX_V4) if (IS_IPADDR_V4(&p_evpn_p->ip))
stream_put_ipv4(s, 0); stream_put_ipv4(s, 0);
else else
stream_put(s, &temp, 16); stream_put(s, &temp, 16);

View File

@ -4608,8 +4608,10 @@ bgp_static_set_safi (afi_t afi, safi_t safi, struct vty *vty, const char *ip_str
vty_out (vty, "%% Malformed GatewayIp%s", VTY_NEWLINE); vty_out (vty, "%% Malformed GatewayIp%s", VTY_NEWLINE);
return CMD_WARNING; return CMD_WARNING;
} }
if((gw_ip.family == AF_INET && (p.u.prefix_evpn.flags & IP_PREFIX_V6)) if((gw_ip.family == AF_INET &&
|| (gw_ip.family == AF_INET6 && (p.u.prefix_evpn.flags & IP_PREFIX_V4))) IS_EVPN_PREFIX_IPADDR_V6((struct prefix_evpn *)&p)) ||
(gw_ip.family == AF_INET6 &&
IS_EVPN_PREFIX_IPADDR_V4((struct prefix_evpn *)&p)))
{ {
vty_out (vty, "%% GatewayIp family differs with IP prefix%s", VTY_NEWLINE); vty_out (vty, "%% GatewayIp family differs with IP prefix%s", VTY_NEWLINE);
return CMD_WARNING; return CMD_WARNING;
@ -6815,11 +6817,11 @@ route_vty_out_overlay (struct vty *vty, struct prefix *p,
char *str = esi2str(id); char *str = esi2str(id);
vty_out (vty, "%s", str); vty_out (vty, "%s", str);
XFREE (MTYPE_TMP, str); XFREE (MTYPE_TMP, str);
if (p->u.prefix_evpn.flags & IP_PREFIX_V4) if (IS_EVPN_PREFIX_IPADDR_V4((struct prefix_evpn *)p))
{ {
vty_out (vty, "/%s", inet_ntoa (attr->extra->evpn_overlay.gw_ip.ipv4)); vty_out (vty, "/%s", inet_ntoa (attr->extra->evpn_overlay.gw_ip.ipv4));
} }
else if (p->u.prefix_evpn.flags & IP_PREFIX_V6) else if (IS_EVPN_PREFIX_IPADDR_V6((struct prefix_evpn *)p))
{ {
vty_out (vty, "/%s", vty_out (vty, "/%s",
inet_ntop (AF_INET6, &(attr->extra->evpn_overlay.gw_ip.ipv6), inet_ntop (AF_INET6, &(attr->extra->evpn_overlay.gw_ip.ipv6),

View File

@ -852,6 +852,66 @@ str2prefix (const char *str, struct prefix *p)
return 0; return 0;
} }
static const char *
prefixeth2str (const struct prefix *p, char *str, int size)
{
u_char family;
char buf[PREFIX2STR_BUFFER];
char buf2[ETHER_ADDR_STRLEN];
if (p->u.prefix_evpn.route_type == 2)
{
if (IS_EVPN_PREFIX_IPADDR_NONE((struct prefix_evpn *)p))
snprintf (str, size, "[%d]:[%s]/%d",
p->u.prefix_evpn.route_type,
prefix_mac2str (&p->u.prefix_evpn.mac, buf2, sizeof (buf2)),
p->prefixlen);
else
{
family = IS_EVPN_PREFIX_IPADDR_V4((struct prefix_evpn *)p) ? \
AF_INET : AF_INET6;
snprintf (str, size, "[%d]:[%s]:[%s]/%d",
p->u.prefix_evpn.route_type,
prefix_mac2str (&p->u.prefix_evpn.mac, buf2, sizeof (buf2)),
inet_ntop (family, &p->u.prefix_evpn.ip.ip.addr,
buf, PREFIX2STR_BUFFER),
p->prefixlen);
}
}
else if (p->u.prefix_evpn.route_type == 3)
{
family = IS_EVPN_PREFIX_IPADDR_V4((struct prefix_evpn *)p) ? \
AF_INET : AF_INET6;
snprintf (str, size, "[%d]:[%s]/%d",
p->u.prefix_evpn.route_type,
inet_ntop (family, &p->u.prefix_evpn.ip.ip.addr,
buf, PREFIX2STR_BUFFER),
p->prefixlen);
}
else if (p->u.prefix_evpn.route_type == 5)
{
family = IS_EVPN_PREFIX_IPADDR_V4((struct prefix_evpn *)p) ? \
AF_INET : AF_INET6;
snprintf (str, size, "[%d]:[%u][%s]/%d",
p->u.prefix_evpn.route_type,
p->u.prefix_evpn.eth_tag,
inet_ntop (family, &p->u.prefix_evpn.ip.ip.addr,
buf, PREFIX2STR_BUFFER),
p->prefixlen);
}
else
{
sprintf (str, "UNK AF_ETHER prefix");
snprintf(str, size, "%02x:%02x:%02x:%02x:%02x:%02x/%d",
p->u.prefix_eth.octet[0], p->u.prefix_eth.octet[1],
p->u.prefix_eth.octet[2], p->u.prefix_eth.octet[3],
p->u.prefix_eth.octet[4], p->u.prefix_eth.octet[5],
p->prefixlen);
}
return str;
}
const char * const char *
prefix2str (union prefixconstptr pu, char *str, int size) prefix2str (union prefixconstptr pu, char *str, int size)
{ {
@ -868,28 +928,9 @@ prefix2str (union prefixconstptr pu, char *str, int size)
break; break;
case AF_ETHERNET: case AF_ETHERNET:
if (p->u.prefix_evpn.route_type == 5) prefixeth2str (p, str, size);
{
u_char family;
family = (p->u.prefix_evpn.flags & (IP_ADDR_V4 | IP_PREFIX_V4)) ?
AF_INET : AF_INET6;
snprintf (str, size, "[%d]:[%u][%s]/%d",
p->u.prefix_evpn.route_type,
p->u.prefix_evpn.eth_tag,
inet_ntop (family, &p->u.prefix_evpn.ip.addr,
buf, PREFIX2STR_BUFFER),
p->prefixlen);
}
else
{
sprintf (str, "UNK AF_ETHER prefix");
snprintf(str, size, "%02x:%02x:%02x:%02x:%02x:%02x/%d",
p->u.prefix_eth.octet[0], p->u.prefix_eth.octet[1],
p->u.prefix_eth.octet[2], p->u.prefix_eth.octet[3],
p->u.prefix_eth.octet[4], p->u.prefix_eth.octet[5],
p->prefixlen);
}
break; break;
default: default:
sprintf (str, "UNK prefix"); sprintf (str, "UNK prefix");
break; break;

View File

@ -32,6 +32,7 @@
# endif # endif
#endif #endif
#include "sockunion.h" #include "sockunion.h"
#include "ipaddr.h"
#ifndef ETHER_ADDR_LEN #ifndef ETHER_ADDR_LEN
#ifdef ETHERADDRL #ifdef ETHERADDRL
@ -62,30 +63,23 @@ struct ethaddr {
struct evpn_addr struct evpn_addr
{ {
u_char route_type; u_char route_type;
u_char flags; u_char ip_prefix_length;
#define IP_ADDR_NONE 0x0
#define IP_ADDR_V4 0x1
#define IP_ADDR_V6 0x2
#define IP_PREFIX_V4 0x4
#define IP_PREFIX_V6 0x8
struct ethaddr mac; struct ethaddr mac;
uint32_t eth_tag; uint32_t eth_tag;
u_char ip_prefix_length; ipaddr_t ip;
#if 0
union union
{ {
u_char addr; u_char addr;
struct in_addr v4_addr; struct in_addr v4_addr;
struct in6_addr v6_addr; struct in6_addr v6_addr;
} ip; } ip;
#endif
}; };
/* EVPN prefix structure. */ #define IS_EVPN_PREFIX_IPADDR_NONE(evp) IS_IPADDR_NONE(&(evp)->prefix.ip)
struct prefix_evpn #define IS_EVPN_PREFIX_IPADDR_V4(evp) IS_IPADDR_V4(&(evp)->prefix.ip)
{ #define IS_EVPN_PREFIX_IPADDR_V6(evp) IS_IPADDR_V6(&(evp)->prefix.ip)
u_char family;
u_char prefixlen;
struct evpn_addr prefix __attribute__ ((aligned (8)));
};
/* /*
* A struct prefix contains an address family, a prefix length, and an * A struct prefix contains an address family, a prefix length, and an
@ -167,6 +161,14 @@ struct prefix_eth
struct ethaddr eth_addr __attribute__ ((aligned (8))); /* AF_ETHERNET */ struct ethaddr eth_addr __attribute__ ((aligned (8))); /* AF_ETHERNET */
}; };
/* EVPN prefix structure. */
struct prefix_evpn
{
u_char family;
u_char prefixlen;
struct evpn_addr prefix __attribute__ ((aligned (8)));
};
/* Prefix for a generic pointer */ /* Prefix for a generic pointer */
struct prefix_ptr struct prefix_ptr
{ {