From: Donald Sharp Date: Tue, 8 Aug 2017 14:16:12 +0000 (-0400) Subject: lib, bgpd: Distinguish between AF_EVPN and AF_ETHERNET X-Git-Tag: frr-4.0-dev~431^2~2 X-Git-Url: https://git.puffer.fish/?a=commitdiff_plain;h=b03b88986e529eeb0cd7de1ce9a07d8d2a83b6d3;p=mirror%2Ffrr.git lib, bgpd: Distinguish between AF_EVPN and AF_ETHERNET Create AF_EVPN for internal use and start using it. Signed-off-by: Vivek Venkatraman --- 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))); };