summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDonald Sharp <sharpd@cumulusnetworks.com>2017-08-08 10:16:12 -0400
committerDonald Sharp <sharpd@cumulusnetworks.com>2017-08-08 10:34:31 -0400
commitb03b88986e529eeb0cd7de1ce9a07d8d2a83b6d3 (patch)
treec402bb8a37a4d02d0bdc71fd454eda541fbbb106
parentb34fd35d3ad5089ef2aecff06879d2f3ca471947 (diff)
lib, bgpd: Distinguish between AF_EVPN and AF_ETHERNET
Create AF_EVPN for internal use and start using it. Signed-off-by: Vivek Venkatraman <vivek@cumulusnetworks.com>
-rw-r--r--bgpd/bgp_attr_evpn.c2
-rw-r--r--bgpd/bgp_evpn.c10
-rw-r--r--bgpd/bgp_evpn_private.h4
-rw-r--r--bgpd/bgp_route.c10
-rw-r--r--lib/prefix.c35
-rw-r--r--lib/prefix.h15
6 files changed, 54 insertions, 22 deletions
diff --git a/bgpd/bgp_attr_evpn.c b/bgpd/bgp_attr_evpn.c
index 2f0b566ccf..6ead059261 100644
--- a/bgpd/bgp_attr_evpn.c
+++ b/bgpd/bgp_attr_evpn.c
@@ -169,7 +169,7 @@ extern int bgp_build_evpn_prefix(int evpn_type, uint32_t eth_tag,
prefix_copy(src, dst);
memset(dst, 0, sizeof(struct prefix));
p_evpn_p = &(dst->u.prefix_evpn);
- dst->family = AF_ETHERNET;
+ dst->family = AF_EVPN;
p_evpn_p->route_type = evpn_type;
if (evpn_type == BGP_EVPN_IP_PREFIX_ROUTE) {
p_evpn_p->eth_tag = eth_tag;
diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c
index 67484efe12..0560dc46f9 100644
--- a/bgpd/bgp_evpn.c
+++ b/bgpd/bgp_evpn.c
@@ -1807,7 +1807,7 @@ static int process_type2_route(struct peer *peer, afi_t afi, safi_t safi,
/* Make EVPN prefix. */
memset(&p, 0, sizeof(struct prefix_evpn));
- p.family = AF_ETHERNET;
+ p.family = AF_EVPN;
p.prefixlen = EVPN_TYPE_2_ROUTE_PREFIXLEN;
p.prefix.route_type = BGP_EVPN_MAC_IP_ROUTE;
@@ -1896,7 +1896,7 @@ static int process_type3_route(struct peer *peer, afi_t afi, safi_t safi,
/* Make EVPN prefix. */
memset(&p, 0, sizeof(struct prefix_evpn));
- p.family = AF_ETHERNET;
+ p.family = AF_EVPN;
p.prefixlen = EVPN_TYPE_3_ROUTE_PREFIXLEN;
p.prefix.route_type = BGP_EVPN_IMET_ROUTE;
@@ -1961,7 +1961,7 @@ static int process_type5_route(struct peer *peer, afi_t afi, safi_t safi,
/* Make EVPN prefix. */
memset(&p, 0, sizeof(struct prefix_evpn));
- p.family = AF_ETHERNET;
+ p.family = AF_EVPN;
p.prefix.route_type = BGP_EVPN_IP_PREFIX_ROUTE;
/* Additional information outside of prefix - ESI and GW IP */
@@ -2030,7 +2030,7 @@ static void evpn_mpattr_encode_type5(struct stream *s, struct prefix *p,
struct evpn_addr *p_evpn_p;
memset(&temp, 0, 16);
- if (p->family != AF_ETHERNET)
+ if (p->family != AF_EVPN)
return;
p_evpn_p = &(p->u.prefix_evpn);
@@ -2213,7 +2213,7 @@ char *bgp_evpn_route2str(struct prefix_evpn *p, char *buf, int len)
PREFIX2STR_BUFFER));
}
} else {
- /* Currently, this is to cater to other AF_ETHERNET code. */
+ /* For EVPN route types not supported yet. */
}
return (buf);
diff --git a/bgpd/bgp_evpn_private.h b/bgpd/bgp_evpn_private.h
index e6f6301405..9dc459cd4e 100644
--- a/bgpd/bgp_evpn_private.h
+++ b/bgpd/bgp_evpn_private.h
@@ -174,7 +174,7 @@ static inline void build_evpn_type2_prefix(struct prefix_evpn *p,
struct ipaddr *ip)
{
memset(p, 0, sizeof(struct prefix_evpn));
- p->family = AF_ETHERNET;
+ p->family = AF_EVPN;
p->prefixlen = EVPN_TYPE_2_ROUTE_PREFIXLEN;
p->prefix.route_type = BGP_EVPN_MAC_IP_ROUTE;
memcpy(&p->prefix.mac.octet, mac->octet, ETH_ALEN);
@@ -187,7 +187,7 @@ static inline void build_evpn_type3_prefix(struct prefix_evpn *p,
struct in_addr originator_ip)
{
memset(p, 0, sizeof(struct prefix_evpn));
- p->family = AF_ETHERNET;
+ p->family = AF_EVPN;
p->prefixlen = EVPN_TYPE_3_ROUTE_PREFIXLEN;
p->prefix.route_type = BGP_EVPN_IMET_ROUTE;
p->prefix.ip.ipa_type = IPADDR_V4;
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index bce54ab2d0..35f793f861 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -6246,6 +6246,9 @@ static void route_vty_out_route(struct prefix *p, struct vty *vty)
} else
len += vty_out(vty, "/%d", p->prefixlen);
} else if (p->family == AF_ETHERNET) {
+ prefix2str(p, buf, PREFIX_STRLEN);
+ len = vty_out(vty, "%s", buf);
+ } else if (p->family == AF_EVPN) {
#if defined(HAVE_CUMULUS)
len = vty_out(vty, "%s",
bgp_evpn_route2str((struct prefix_evpn *)p, buf,
@@ -6808,7 +6811,7 @@ void route_vty_out_tag(struct vty *vty, struct prefix *p,
if (attr) {
if (((p->family == AF_INET)
&& ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
- || (safi == SAFI_EVPN && p->family == AF_ETHERNET
+ || (safi == SAFI_EVPN
&& !BGP_ATTR_NEXTHOP_AFI_IP6(attr))
|| (!BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
@@ -6833,7 +6836,7 @@ void route_vty_out_tag(struct vty *vty, struct prefix *p,
}
} else if (((p->family == AF_INET6)
&& ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
- || (safi == SAFI_EVPN && p->family == AF_ETHERNET
+ || (safi == SAFI_EVPN
&& BGP_ATTR_NEXTHOP_AFI_IP6(attr))
|| (BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
char buf_a[BUFSIZ];
@@ -7333,7 +7336,8 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct prefix *p,
/* Line2 display Next-hop, Neighbor, Router-id */
/* Display the nexthop */
- if ((p->family == AF_INET || p->family == AF_ETHERNET)
+ if ((p->family == AF_INET || p->family == AF_ETHERNET ||
+ p->family == AF_EVPN)
&& (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
|| safi == SAFI_EVPN
|| !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
diff --git a/lib/prefix.c b/lib/prefix.c
index edfc22fb42..df638b0fc8 100644
--- a/lib/prefix.c
+++ b/lib/prefix.c
@@ -334,6 +334,8 @@ int str2family(const char *string)
return AF_INET6;
else if (!strcmp("ethernet", string))
return AF_ETHERNET;
+ else if (!strcmp("evpn", string))
+ return AF_EVPN;
return -1;
}
@@ -346,6 +348,7 @@ int afi2family(afi_t afi)
return AF_INET6;
else if (afi == AFI_L2VPN)
return AF_ETHERNET;
+ /* NOTE: EVPN code should NOT use this interface. */
return 0;
}
@@ -355,7 +358,7 @@ afi_t family2afi(int family)
return AFI_IP;
else if (family == AF_INET6)
return AFI_IP6;
- else if (family == AF_ETHERNET)
+ else if (family == AF_ETHERNET || family == AF_EVPN)
return AFI_L2VPN;
return 0;
}
@@ -461,6 +464,9 @@ void prefix_copy(struct prefix *dest, const struct prefix *src)
else if (src->family == AF_INET6)
dest->u.prefix6 = src->u.prefix6;
else if (src->family == AF_ETHERNET) {
+ memcpy(&dest->u.prefix_eth, &src->u.prefix_eth,
+ sizeof(struct ethaddr));
+ } else if (src->family == AF_EVPN) {
memcpy(&dest->u.prefix_evpn, &src->u.prefix_evpn,
sizeof(struct evpn_addr));
} else if (src->family == AF_UNSPEC) {
@@ -517,6 +523,10 @@ int prefix_same(const struct prefix *p1, const struct prefix *p2)
&p2->u.prefix6.s6_addr))
return 1;
if (p1->family == AF_ETHERNET)
+ if (!memcmp(&p1->u.prefix_eth, &p2->u.prefix_eth,
+ sizeof(struct ethaddr)))
+ return 1;
+ if (p1->family == AF_EVPN)
if (!memcmp(&p1->u.prefix_evpn, &p2->u.prefix_evpn,
sizeof(struct evpn_addr)))
return 1;
@@ -581,6 +591,8 @@ int prefix_common_bits(const struct prefix *p1, const struct prefix *p2)
if (p1->family == AF_INET6)
length = IPV6_MAX_BYTELEN;
if (p1->family == AF_ETHERNET)
+ length = ETH_ALEN;
+ if (p1->family == AF_EVPN)
length = 8 * sizeof(struct evpn_addr);
if (p1->family != p2->family || !length)
@@ -609,6 +621,8 @@ const char *prefix_family_str(const struct prefix *p)
return "inet6";
if (p->family == AF_ETHERNET)
return "ether";
+ if (p->family == AF_EVPN)
+ return "evpn";
return "unspec";
}
@@ -965,6 +979,7 @@ int prefix_blen(const struct prefix *p)
break;
case AF_ETHERNET:
return ETH_ALEN;
+ break;
}
return 0;
}
@@ -992,7 +1007,7 @@ int str2prefix(const char *str, struct prefix *p)
return 0;
}
-static const char *prefixeth2str(const struct prefix *p, char *str, int size)
+static const char *prefixevpn2str(const struct prefix *p, char *str, int size)
{
u_char family;
char buf[PREFIX2STR_BUFFER];
@@ -1036,12 +1051,8 @@ static const char *prefixeth2str(const struct prefix *p, char *str, int size)
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);
+ sprintf(str, "Unsupported EVPN route type %d",
+ p->u.prefix_evpn.route_type);
}
return str;
@@ -1061,7 +1072,13 @@ const char *prefix2str(union prefixconstptr pu, char *str, int size)
break;
case AF_ETHERNET:
- prefixeth2str(p, str, size);
+ snprintf(str, size, "%s/%d",
+ prefix_mac2str(&p->u.prefix_eth, buf, sizeof(buf)),
+ p->prefixlen);
+ break;
+
+ case AF_EVPN:
+ prefixevpn2str(p, str, size);
break;
default:
diff --git a/lib/prefix.h b/lib/prefix.h
index f665f55dfd..3ebf615468 100644
--- a/lib/prefix.h
+++ b/lib/prefix.h
@@ -116,7 +116,18 @@ struct evpn_addr {
#endif
#endif
-/* IPv4 and IPv6 unified prefix structure. */
+/* The 'family' in the prefix structure is internal to FRR and need not
+ * map to standard OS AF_ definitions except where needed for interacting
+ * with the kernel. However, AF_ definitions are currently in use and
+ * prevalent across the code. Define a new FRR-specific AF for EVPN to
+ * distinguish between 'ethernet' (MAC-only) and 'evpn' prefixes and
+ * ensure it does not conflict with any OS AF_ definition.
+ */
+#if !defined(AF_EVPN)
+#define AF_EVPN (AF_MAX + 1)
+#endif
+
+/* FRR generic prefix structure. */
struct prefix {
u_char family;
u_char prefixlen;
@@ -131,7 +142,7 @@ struct prefix {
struct ethaddr prefix_eth; /* AF_ETHERNET */
u_char val[8];
uintptr_t ptr;
- struct evpn_addr prefix_evpn;
+ struct evpn_addr prefix_evpn; /* AF_EVPN */
} u __attribute__((aligned(8)));
};