]> git.proxmox.com Git - mirror_frr.git/commitdiff
Merge pull request #2173 from chiragshah6/ospfv3_dev
authorRuss White <russ@riw.us>
Wed, 9 May 2018 00:03:48 +0000 (20:03 -0400)
committerGitHub <noreply@github.com>
Wed, 9 May 2018 00:03:48 +0000 (20:03 -0400)
ospf6d: fix area border router duplicate

bgpd/bgp_attr.c
bgpd/bgp_attr.h
bgpd/bgp_attr_evpn.c
bgpd/bgp_evpn.c
bgpd/bgp_evpn_private.h
bgpd/bgp_route.c
bgpd/bgp_routemap.c
lib/prefix.c
lib/prefix.h
tests/bgpd/test_mp_attr.c

index b6e9ee3cb233e85730b8dde983e0b96c544982cc..276a7054e37ae4007de403875b4f9ca32d191bad 100644 (file)
@@ -2021,36 +2021,32 @@ static int bgp_attr_encap(uint8_t type, struct peer *peer, /* IN */
        return 0;
 }
 
-/* Prefix SID attribute
- * draft-ietf-idr-bgp-prefix-sid-05
+/*
+ * Read an individual SID value returning how much data we have read
+ * Returns 0 if there was an error that needs to be passed up the stack
  */
-static bgp_attr_parse_ret_t
-bgp_attr_prefix_sid(struct bgp_attr_parser_args *args,
-                   struct bgp_nlri *mp_update)
+static bgp_attr_parse_ret_t bgp_attr_psid_sub(int32_t type,
+                                             int32_t length,
+                                             struct bgp_attr_parser_args *args,
+                                             struct bgp_nlri *mp_update)
 {
        struct peer *const peer = args->peer;
        struct attr *const attr = args->attr;
-       int type;
-       int length;
        uint32_t label_index;
        struct in6_addr ipv6_sid;
        uint32_t srgb_base;
        uint32_t srgb_range;
        int srgb_count;
 
-       attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
-
-       type = stream_getc(peer->curr);
-       length = stream_getw(peer->curr);
-
        if (type == BGP_PREFIX_SID_LABEL_INDEX) {
                if (length != BGP_PREFIX_SID_LABEL_INDEX_LENGTH) {
                        zlog_err(
-                               "Prefix SID label index length is %d instead of %d",
-                               length, BGP_PREFIX_SID_LABEL_INDEX_LENGTH);
-                       return bgp_attr_malformed(
-                               args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
-                               args->total);
+                                "Prefix SID label index length is %d instead of %d",
+                                length,
+                                BGP_PREFIX_SID_LABEL_INDEX_LENGTH);
+                       return bgp_attr_malformed(args,
+                                                 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
+                                                 args->total);
                }
 
                /* Ignore flags and reserved */
@@ -2060,9 +2056,8 @@ bgp_attr_prefix_sid(struct bgp_attr_parser_args *args,
                /* Fetch the label index and see if it is valid. */
                label_index = stream_getl(peer->curr);
                if (label_index == BGP_INVALID_LABEL_INDEX)
-                       return bgp_attr_malformed(
-                               args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
-                               args->total);
+                       return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
+                                                 args->total);
 
                /* Store label index; subsequently, we'll check on
                 * address-family */
@@ -2083,9 +2078,9 @@ bgp_attr_prefix_sid(struct bgp_attr_parser_args *args,
                if (length != BGP_PREFIX_SID_IPV6_LENGTH) {
                        zlog_err("Prefix SID IPv6 length is %d instead of %d",
                                 length, BGP_PREFIX_SID_IPV6_LENGTH);
-                       return bgp_attr_malformed(
-                               args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
-                               args->total);
+                       return bgp_attr_malformed(args,
+                                                 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
+                                                 args->total);
                }
 
                /* Ignore reserved */
@@ -2122,6 +2117,47 @@ bgp_attr_prefix_sid(struct bgp_attr_parser_args *args,
        return BGP_ATTR_PARSE_PROCEED;
 }
 
+/* Prefix SID attribute
+ * draft-ietf-idr-bgp-prefix-sid-05
+ */
+bgp_attr_parse_ret_t
+bgp_attr_prefix_sid(int32_t tlength, struct bgp_attr_parser_args *args,
+                   struct bgp_nlri *mp_update)
+{
+       struct peer *const peer = args->peer;
+       struct attr *const attr = args->attr;
+       bgp_attr_parse_ret_t ret;
+
+       attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
+
+       while (tlength) {
+               int32_t type, length;
+
+               type = stream_getc(peer->curr);
+               length = stream_getw(peer->curr);
+
+               ret = bgp_attr_psid_sub(type, length, args, mp_update);
+
+               if (ret != BGP_ATTR_PARSE_PROCEED)
+                       return ret;
+               /*
+                * Subtract length + the T and the L
+                * since length is the Vector portion
+                */
+               tlength -= length + 3;
+
+               if (tlength < 0) {
+                       zlog_err("Prefix SID internal length %d causes us to read beyond the total Prefix SID length",
+                                length);
+                       return bgp_attr_malformed(args,
+                                                 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR,
+                                                 args->total);
+               }
+       }
+
+       return BGP_ATTR_PARSE_PROCEED;
+}
+
 /* PMSI tunnel attribute (RFC 6514)
  * Basic validation checks done here.
  */
@@ -2498,7 +2534,8 @@ bgp_attr_parse_ret_t bgp_attr_parse(struct peer *peer, struct attr *attr,
                                             startp);
                        break;
                case BGP_ATTR_PREFIX_SID:
-                       ret = bgp_attr_prefix_sid(&attr_args, mp_update);
+                       ret = bgp_attr_prefix_sid(length,
+                                                 &attr_args, mp_update);
                        break;
                case BGP_ATTR_PMSI_TUNNEL:
                        ret = bgp_attr_pmsi_tunnel(&attr_args);
index d59eae5f14749ad3d642edc7a1ce7c078bb8ff13..f17c2a68e4533780614a99586205adfb62667412 100644 (file)
@@ -308,6 +308,9 @@ extern int bgp_mp_reach_parse(struct bgp_attr_parser_args *args,
                              struct bgp_nlri *);
 extern int bgp_mp_unreach_parse(struct bgp_attr_parser_args *args,
                                struct bgp_nlri *);
+extern bgp_attr_parse_ret_t
+bgp_attr_prefix_sid(int32_t tlength, struct bgp_attr_parser_args *args,
+                   struct bgp_nlri *mp_update);
 
 extern struct bgp_attr_encap_subtlv *
 encap_tlv_dup(struct bgp_attr_encap_subtlv *orig);
index d2a61b93fe2cacb5585c4bcc55c5bb0d50f628b2..14ff01ada54c09eb56466857557959c30f71d90d 100644 (file)
@@ -227,16 +227,18 @@ extern int bgp_build_evpn_prefix(int evpn_type, uint32_t eth_tag,
        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;
-               p_evpn_p->ip_prefix_length = p2.prefixlen;
+               p_evpn_p->prefix_addr.eth_tag = eth_tag;
+               p_evpn_p->prefix_addr.ip_prefix_length = p2.prefixlen;
                if (src->family == AF_INET) {
-                       SET_IPADDR_V4(&p_evpn_p->ip);
-                       memcpy(&p_evpn_p->ip.ipaddr_v4, &src->u.prefix4,
+                       SET_IPADDR_V4(&p_evpn_p->prefix_addr.ip);
+                       memcpy(&p_evpn_p->prefix_addr.ip.ipaddr_v4,
+                              &src->u.prefix4,
                               sizeof(struct in_addr));
                        dst->prefixlen = (uint8_t)PREFIX_LEN_ROUTE_TYPE_5_IPV4;
                } else {
-                       SET_IPADDR_V6(&p_evpn_p->ip);
-                       memcpy(&p_evpn_p->ip.ipaddr_v6, &src->u.prefix6,
+                       SET_IPADDR_V6(&p_evpn_p->prefix_addr.ip);
+                       memcpy(&p_evpn_p->prefix_addr.ip.ipaddr_v6,
+                              &src->u.prefix6,
                               sizeof(struct in6_addr));
                        dst->prefixlen = (uint8_t)PREFIX_LEN_ROUTE_TYPE_5_IPV6;
                }
index 49808e7cdd370436972a4869802a5bfd6448e02d..ad45da84eb207d36faa26c6b5994649b6584df7c 100644 (file)
@@ -510,15 +510,15 @@ static int bgp_zebra_send_remote_macip(struct bgp *bgp, struct bgpevpn *vpn,
                s, add ? ZEBRA_REMOTE_MACIP_ADD : ZEBRA_REMOTE_MACIP_DEL,
                bgp->vrf_id);
        stream_putl(s, vpn->vni);
-       stream_put(s, &p->prefix.mac.octet, ETH_ALEN); /* Mac Addr */
+       stream_put(s, &p->prefix.macip_addr.mac.octet, ETH_ALEN); /* Mac Addr */
        /* IP address length and IP address, if any. */
-       if (IS_EVPN_PREFIX_IPADDR_NONE(p))
+       if (is_evpn_prefix_ipaddr_none(p))
                stream_putl(s, 0);
        else {
-               ipa_len = IS_EVPN_PREFIX_IPADDR_V4(p) ? IPV4_MAX_BYTELEN
+               ipa_len = is_evpn_prefix_ipaddr_v4(p) ? IPV4_MAX_BYTELEN
                                                      : IPV6_MAX_BYTELEN;
                stream_putl(s, ipa_len);
-               stream_put(s, &p->prefix.ip.ip.addr, ipa_len);
+               stream_put(s, &p->prefix.macip_addr.ip.ip.addr, ipa_len);
        }
        stream_put_in_addr(s, &remote_vtep_ip);
 
@@ -532,8 +532,10 @@ static int bgp_zebra_send_remote_macip(struct bgp *bgp, struct bgpevpn *vpn,
                zlog_debug(
                        "Tx %s MACIP, VNI %u MAC %s IP %s (flags: 0x%x) remote VTEP %s",
                        add ? "ADD" : "DEL", vpn->vni,
-                       prefix_mac2str(&p->prefix.mac, buf1, sizeof(buf1)),
-                       ipaddr2str(&p->prefix.ip, buf3, sizeof(buf3)), flags,
+                       prefix_mac2str(&p->prefix.macip_addr.mac,
+                                      buf1, sizeof(buf1)),
+                       ipaddr2str(&p->prefix.macip_addr.ip,
+                                  buf3, sizeof(buf3)), flags,
                        inet_ntop(AF_INET, &remote_vtep_ip, buf2,
                                  sizeof(buf2)));
 
@@ -563,9 +565,9 @@ static int bgp_zebra_send_remote_vtep(struct bgp *bgp, struct bgpevpn *vpn,
                s, add ? ZEBRA_REMOTE_VTEP_ADD : ZEBRA_REMOTE_VTEP_DEL,
                bgp->vrf_id);
        stream_putl(s, vpn->vni);
-       if (IS_EVPN_PREFIX_IPADDR_V4(p))
-               stream_put_in_addr(s, &p->prefix.ip.ipaddr_v4);
-       else if (IS_EVPN_PREFIX_IPADDR_V6(p)) {
+       if (is_evpn_prefix_ipaddr_v4(p))
+               stream_put_in_addr(s, &p->prefix.imet_addr.ip.ipaddr_v4);
+       else if (is_evpn_prefix_ipaddr_v6(p)) {
                zlog_err(
                        "Bad remote IP when trying to %s remote VTEP for VNI %u",
                        add ? "ADD" : "DEL", vpn->vni);
@@ -577,7 +579,7 @@ static int bgp_zebra_send_remote_vtep(struct bgp *bgp, struct bgpevpn *vpn,
        if (bgp_debug_zebra(NULL))
                zlog_debug("Tx %s Remote VTEP, VNI %u remote VTEP %s",
                           add ? "ADD" : "DEL", vpn->vni,
-                          inet_ntoa(p->prefix.ip.ipaddr_v4));
+                          inet_ntoa(p->prefix.imet_addr.ip.ipaddr_v4));
 
        return zclient_send_message(zclient);
 }
@@ -1293,8 +1295,8 @@ static int update_evpn_route(struct bgp *bgp, struct bgpevpn *vpn,
         * these routes.
         */
        if (p->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE &&
-           (IS_EVPN_PREFIX_IPADDR_V4(p) ||
-            !IN6_IS_ADDR_LINKLOCAL(&p->prefix.ip.ipaddr_v6)) &&
+           (is_evpn_prefix_ipaddr_v4(p) ||
+            !IN6_IS_ADDR_LINKLOCAL(&p->prefix.macip_addr.ip.ipaddr_v6)) &&
            CHECK_FLAG(vpn->flags, VNI_FLAG_USE_TWO_LABELS))
                add_l3_ecomm = 1;
 
@@ -1539,8 +1541,8 @@ static int update_all_type2_routes(struct bgp *bgp, struct bgpevpn *vpn)
                if (evp->prefix.route_type != BGP_EVPN_MAC_IP_ROUTE)
                        continue;
 
-               if (IS_EVPN_PREFIX_IPADDR_V6(evp) &&
-                   IN6_IS_ADDR_LINKLOCAL(&evp->prefix.ip.ipaddr_v6))
+               if (is_evpn_prefix_ipaddr_v6(evp) &&
+                   IN6_IS_ADDR_LINKLOCAL(&evp->prefix.macip_addr.ip.ipaddr_v6))
                        update_evpn_route_entry(bgp, vpn, afi, safi, rn,
                                                &attr_ip6_ll, 0, 1, &ri, 0);
                else {
@@ -1792,10 +1794,7 @@ static int install_evpn_route_entry_in_vrf(struct bgp *bgp_vrf,
        char buf1[PREFIX_STRLEN];
 
        memset(pp, 0, sizeof(struct prefix));
-       if (evp->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE)
-               ip_prefix_from_type2_prefix(evp, pp);
-       else if (evp->prefix.route_type == BGP_EVPN_IP_PREFIX_ROUTE)
-               ip_prefix_from_type5_prefix(evp, pp);
+       ip_prefix_from_evpn_prefix(evp, pp);
 
        if (bgp_debug_zebra(NULL)) {
                zlog_debug(
@@ -1807,11 +1806,11 @@ static int install_evpn_route_entry_in_vrf(struct bgp *bgp_vrf,
 
        /* Create (or fetch) route within the VRF. */
        /* NOTE: There is no RD here. */
-       if (IS_EVPN_PREFIX_IPADDR_V4(evp)) {
+       if (is_evpn_prefix_ipaddr_v4(evp)) {
                afi = AFI_IP;
                safi = SAFI_UNICAST;
                rn = bgp_node_get(bgp_vrf->rib[afi][safi], pp);
-       } else if (IS_EVPN_PREFIX_IPADDR_V6(evp)) {
+       } else if (is_evpn_prefix_ipaddr_v6(evp)) {
                afi = AFI_IP6;
                safi = SAFI_UNICAST;
                rn = bgp_node_get(bgp_vrf->rib[afi][safi], pp);
@@ -1970,10 +1969,7 @@ static int uninstall_evpn_route_entry_in_vrf(struct bgp *bgp_vrf,
        char buf1[PREFIX_STRLEN];
 
        memset(pp, 0, sizeof(struct prefix));
-       if (evp->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE)
-               ip_prefix_from_type2_prefix(evp, pp);
-       else if (evp->prefix.route_type == BGP_EVPN_IP_PREFIX_ROUTE)
-               ip_prefix_from_type5_prefix(evp, pp);
+       ip_prefix_from_evpn_prefix(evp, pp);
 
        if (bgp_debug_zebra(NULL)) {
                zlog_debug(
@@ -1985,7 +1981,7 @@ static int uninstall_evpn_route_entry_in_vrf(struct bgp *bgp_vrf,
 
        /* Locate route within the VRF. */
        /* NOTE: There is no RD here. */
-       if (IS_EVPN_PREFIX_IPADDR_V4(evp)) {
+       if (is_evpn_prefix_ipaddr_v4(evp)) {
                afi = AFI_IP;
                safi = SAFI_UNICAST;
                rn = bgp_node_lookup(bgp_vrf->rib[afi][safi], pp);
@@ -2232,8 +2228,8 @@ static int install_uninstall_routes_for_vrf(struct bgp *bgp_vrf, int install)
                                continue;
 
                        /* if not a mac+ip route skip this route */
-                       if (!(IS_EVPN_PREFIX_IPADDR_V4(evp)
-                             || IS_EVPN_PREFIX_IPADDR_V6(evp)))
+                       if (!(is_evpn_prefix_ipaddr_v4(evp)
+                             || is_evpn_prefix_ipaddr_v6(evp)))
                                continue;
 
                        for (ri = rn->info; ri; ri = ri->next) {
@@ -2423,8 +2419,8 @@ static int install_uninstall_route_in_vrfs(struct bgp *bgp_def, afi_t afi,
 
        /* if it is type-2 route and not a mac+ip route skip this route */
        if ((evp->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE)
-           && !(IS_EVPN_PREFIX_IPADDR_V4(evp)
-                || IS_EVPN_PREFIX_IPADDR_V6(evp)))
+           && !(is_evpn_prefix_ipaddr_v4(evp)
+                || is_evpn_prefix_ipaddr_v6(evp)))
                return 0;
 
        for (ALL_LIST_ELEMENTS(vrfs, node, nnode, bgp_vrf)) {
@@ -2850,7 +2846,7 @@ static int process_type2_route(struct peer *peer, afi_t afi, safi_t safi,
 
        /* Copy Ethernet Tag */
        memcpy(&eth_tag, pfx, 4);
-       p.prefix.eth_tag = ntohl(eth_tag);
+       p.prefix.macip_addr.eth_tag = ntohl(eth_tag);
        pfx += 4;
 
        /* Get the MAC Addr len */
@@ -2858,7 +2854,7 @@ static int process_type2_route(struct peer *peer, afi_t afi, safi_t safi,
 
        /* Get the MAC Addr */
        if (macaddr_len == (ETH_ALEN * 8)) {
-               memcpy(&p.prefix.mac.octet, pfx, ETH_ALEN);
+               memcpy(&p.prefix.macip_addr.mac.octet, pfx, ETH_ALEN);
                pfx += ETH_ALEN;
        } else {
                zlog_err(
@@ -2880,10 +2876,10 @@ static int process_type2_route(struct peer *peer, afi_t afi, safi_t safi,
 
        if (ipaddr_len) {
                ipaddr_len /= 8; /* Convert to bytes. */
-               p.prefix.ip.ipa_type = (ipaddr_len == IPV4_MAX_BYTELEN)
+               p.prefix.macip_addr.ip.ipa_type = (ipaddr_len == IPV4_MAX_BYTELEN)
                                               ? IPADDR_V4
                                               : IPADDR_V6;
-               memcpy(&p.prefix.ip.ip.addr, pfx, ipaddr_len);
+               memcpy(&p.prefix.macip_addr.ip.ip.addr, pfx, ipaddr_len);
        }
        pfx += ipaddr_len;
 
@@ -2965,14 +2961,14 @@ static int process_type3_route(struct peer *peer, afi_t afi, safi_t safi,
 
        /* Copy Ethernet Tag */
        memcpy(&eth_tag, pfx, 4);
-       p.prefix.eth_tag = ntohl(eth_tag);
+       p.prefix.imet_addr.eth_tag = ntohl(eth_tag);
        pfx += 4;
 
        /* Get the IP. */
        ipaddr_len = *pfx++;
        if (ipaddr_len == IPV4_MAX_BITLEN) {
-               p.prefix.ip.ipa_type = IPADDR_V4;
-               memcpy(&p.prefix.ip.ip.addr, pfx, IPV4_MAX_BYTELEN);
+               p.prefix.imet_addr.ip.ipa_type = IPADDR_V4;
+               memcpy(&p.prefix.imet_addr.ip.ip.addr, pfx, IPV4_MAX_BYTELEN);
        } else {
                zlog_err(
                        "%u:%s - Rx EVPN Type-3 NLRI with unsupported IP address length %d",
@@ -3039,7 +3035,7 @@ static int process_type5_route(struct peer *peer, afi_t afi, safi_t safi,
 
        /* Fetch Ethernet Tag. */
        memcpy(&eth_tag, pfx, 4);
-       p.prefix.eth_tag = ntohl(eth_tag);
+       p.prefix.prefix_addr.eth_tag = ntohl(eth_tag);
        pfx += 4;
 
        /* Fetch IP prefix length. */
@@ -3050,21 +3046,21 @@ static int process_type5_route(struct peer *peer, afi_t afi, safi_t safi,
                        peer->bgp->vrf_id, peer->host, ippfx_len);
                return -1;
        }
-       p.prefix.ip_prefix_length = ippfx_len;
+       p.prefix.prefix_addr.ip_prefix_length = ippfx_len;
 
        /* Determine IPv4 or IPv6 prefix */
        /* Since the address and GW are from the same family, this just becomes
         * a simple check on the total size.
         */
        if (psize == 34) {
-               SET_IPADDR_V4(&p.prefix.ip);
-               memcpy(&p.prefix.ip.ipaddr_v4, pfx, 4);
+               SET_IPADDR_V4(&p.prefix.prefix_addr.ip);
+               memcpy(&p.prefix.prefix_addr.ip.ipaddr_v4, pfx, 4);
                pfx += 4;
                memcpy(&evpn.gw_ip.ipv4, pfx, 4);
                pfx += 4;
        } else {
-               SET_IPADDR_V6(&p.prefix.ip);
-               memcpy(&p.prefix.ip.ipaddr_v6, pfx, 16);
+               SET_IPADDR_V6(&p.prefix.prefix_addr.ip);
+               memcpy(&p.prefix.prefix_addr.ip.ipaddr_v6, pfx, 16);
                pfx += 16;
                memcpy(&evpn.gw_ip.ipv6, pfx, 16);
                pfx += 16;
@@ -3109,7 +3105,7 @@ static void evpn_mpattr_encode_type5(struct stream *s, struct prefix *p,
        /* len denites the total len of IP and GW-IP in the route
           IP and GW-IP have to be both ipv4 or ipv6
         */
-       if (IS_IPADDR_V4(&p_evpn_p->ip))
+       if (IS_IPADDR_V4(&p_evpn_p->prefix_addr.ip))
                len = 8; /* IP and GWIP are both ipv4 */
        else
                len = 32; /* IP and GWIP are both ipv6 */
@@ -3120,20 +3116,20 @@ static void evpn_mpattr_encode_type5(struct stream *s, struct prefix *p,
                stream_put(s, &(attr->evpn_overlay.eth_s_id), 10);
        else
                stream_put(s, &temp, 10);
-       stream_putl(s, p_evpn_p->eth_tag);
-       stream_putc(s, p_evpn_p->ip_prefix_length);
-       if (IS_IPADDR_V4(&p_evpn_p->ip))
-               stream_put_ipv4(s, p_evpn_p->ip.ipaddr_v4.s_addr);
+       stream_putl(s, p_evpn_p->prefix_addr.eth_tag);
+       stream_putc(s, p_evpn_p->prefix_addr.ip_prefix_length);
+       if (IS_IPADDR_V4(&p_evpn_p->prefix_addr.ip))
+               stream_put_ipv4(s, p_evpn_p->prefix_addr.ip.ipaddr_v4.s_addr);
        else
-               stream_put(s, &p_evpn_p->ip.ipaddr_v6, 16);
+               stream_put(s, &p_evpn_p->prefix_addr.ip.ipaddr_v6, 16);
        if (attr) {
-               if (IS_IPADDR_V4(&p_evpn_p->ip))
+               if (IS_IPADDR_V4(&p_evpn_p->prefix_addr.ip))
                        stream_put_ipv4(s,
                                        attr->evpn_overlay.gw_ip.ipv4.s_addr);
                else
                        stream_put(s, &(attr->evpn_overlay.gw_ip.ipv6), 16);
        } else {
-               if (IS_IPADDR_V4(&p_evpn_p->ip))
+               if (IS_IPADDR_V4(&p_evpn_p->prefix_addr.ip))
                        stream_put_ipv4(s, 0);
                else
                        stream_put(s, &temp, 16);
@@ -3583,44 +3579,49 @@ void bgp_evpn_route2json(struct prefix_evpn *p, json_object *json)
 
        if (p->prefix.route_type == BGP_EVPN_IMET_ROUTE) {
                json_object_int_add(json, "routeType", p->prefix.route_type);
-               json_object_int_add(json, "ethTag", p->prefix.eth_tag);
+               json_object_int_add(json, "ethTag",
+                                   p->prefix.imet_addr.eth_tag);
                json_object_int_add(json, "ipLen",
-                                   IS_EVPN_PREFIX_IPADDR_V4(p)
+                                   is_evpn_prefix_ipaddr_v4(p)
                                            ? IPV4_MAX_BITLEN
                                            : IPV6_MAX_BITLEN);
                json_object_string_add(json, "ip",
-                                      inet_ntoa(p->prefix.ip.ipaddr_v4));
+                                      inet_ntoa(p->prefix.imet_addr.ip.ipaddr_v4));
        } else if (p->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE) {
-               if (IS_EVPN_PREFIX_IPADDR_NONE(p)) {
+               if (is_evpn_prefix_ipaddr_none(p)) {
                        json_object_int_add(json, "routeType",
                                            p->prefix.route_type);
-                       json_object_int_add(json, "ethTag", p->prefix.eth_tag);
+                       json_object_int_add(json, "ethTag",
+                                           p->prefix.macip_addr.eth_tag);
                        json_object_int_add(json, "macLen", 8 * ETH_ALEN);
                        json_object_string_add(json, "mac",
-                                              prefix_mac2str(&p->prefix.mac,
+                                              prefix_mac2str(&p->prefix.macip_addr.mac,
                                                              buf1,
                                                              sizeof(buf1)));
                } else {
                        uint8_t family;
 
-                       family = IS_EVPN_PREFIX_IPADDR_V4(p) ? AF_INET
+                       family = is_evpn_prefix_ipaddr_v4(p) ? AF_INET
                                                             : AF_INET6;
 
                        json_object_int_add(json, "routeType",
                                            p->prefix.route_type);
-                       json_object_int_add(json, "ethTag", p->prefix.eth_tag);
+                       json_object_int_add(json, "ethTag",
+                                           p->prefix.macip_addr.eth_tag);
                        json_object_int_add(json, "macLen", 8 * ETH_ALEN);
                        json_object_string_add(json, "mac",
-                                              prefix_mac2str(&p->prefix.mac,
+                                              prefix_mac2str(&p->prefix.macip_addr.mac,
                                                              buf1,
                                                              sizeof(buf1)));
                        json_object_int_add(json, "ipLen",
-                                           IS_EVPN_PREFIX_IPADDR_V4(p)
+                                           is_evpn_prefix_ipaddr_v4(p)
                                                    ? IPV4_MAX_BITLEN
                                                    : IPV6_MAX_BITLEN);
                        json_object_string_add(
                                json, "ip",
-                               inet_ntop(family, &p->prefix.ip.ip.addr, buf2,
+                               inet_ntop(family,
+                                         &p->prefix.macip_addr.ip.ip.addr,
+                                         buf2,
                                          PREFIX2STR_BUFFER));
                }
        } else {
@@ -3639,42 +3640,44 @@ char *bgp_evpn_route2str(struct prefix_evpn *p, char *buf, int len)
 
        if (p->prefix.route_type == BGP_EVPN_IMET_ROUTE) {
                snprintf(buf, len, "[%d]:[%d]:[%d]:[%s]", p->prefix.route_type,
-                        p->prefix.eth_tag,
-                        IS_EVPN_PREFIX_IPADDR_V4(p) ? IPV4_MAX_BITLEN
+                        p->prefix.imet_addr.eth_tag,
+                        is_evpn_prefix_ipaddr_v4(p) ? IPV4_MAX_BITLEN
                                                     : IPV6_MAX_BITLEN,
-                        inet_ntoa(p->prefix.ip.ipaddr_v4));
+                        inet_ntoa(p->prefix.imet_addr.ip.ipaddr_v4));
        } else if (p->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE) {
-               if (IS_EVPN_PREFIX_IPADDR_NONE(p))
+               if (is_evpn_prefix_ipaddr_none(p))
                        snprintf(buf, len, "[%d]:[%d]:[%d]:[%s]",
                                 p->prefix.route_type,
-                                p->prefix.eth_tag,
+                                p->prefix.macip_addr.eth_tag,
                                 8 * ETH_ALEN,
-                                prefix_mac2str(&p->prefix.mac, buf1,
+                                prefix_mac2str(&p->prefix.macip_addr.mac, buf1,
                                                sizeof(buf1)));
                else {
                        uint8_t family;
 
-                       family = IS_EVPN_PREFIX_IPADDR_V4(p) ? AF_INET
+                       family = is_evpn_prefix_ipaddr_v4(p) ? AF_INET
                                                             : AF_INET6;
                        snprintf(buf, len, "[%d]:[%d]:[%d]:[%s]:[%d]:[%s]",
                                 p->prefix.route_type,
-                                p->prefix.eth_tag,
+                                p->prefix.macip_addr.eth_tag,
                                 8 * ETH_ALEN,
-                                prefix_mac2str(&p->prefix.mac, buf1,
+                                prefix_mac2str(&p->prefix.macip_addr.mac, buf1,
                                                sizeof(buf1)),
                                 family == AF_INET ? IPV4_MAX_BITLEN
                                                   : IPV6_MAX_BITLEN,
-                                inet_ntop(family, &p->prefix.ip.ip.addr, buf2,
+                                inet_ntop(family,
+                                          &p->prefix.macip_addr.ip.ip.addr,
+                                          buf2,
                                           PREFIX2STR_BUFFER));
                }
        } else if (p->prefix.route_type == BGP_EVPN_IP_PREFIX_ROUTE) {
                snprintf(buf, len, "[%d]:[%d]:[%d]:[%s]",
                         p->prefix.route_type,
-                        p->prefix.eth_tag,
-                        p->prefix.ip_prefix_length,
-                        IS_EVPN_PREFIX_IPADDR_V4(p)
-                                ? inet_ntoa(p->prefix.ip.ipaddr_v4)
-                                : inet6_ntoa(p->prefix.ip.ipaddr_v6));
+                        p->prefix.prefix_addr.eth_tag,
+                        p->prefix.prefix_addr.ip_prefix_length,
+                        is_evpn_prefix_ipaddr_v4(p)
+                                ? inet_ntoa(p->prefix.prefix_addr.ip.ipaddr_v4)
+                                : inet6_ntoa(p->prefix.prefix_addr.ip.ipaddr_v6));
        } else {
                /* For EVPN route types not supported yet. */
                snprintf(buf, len, "(unsupported route type %d)",
@@ -3703,9 +3706,9 @@ void bgp_evpn_encode_prefix(struct stream *s, struct prefix *p,
 
        switch (evp->prefix.route_type) {
        case BGP_EVPN_MAC_IP_ROUTE:
-               if (IS_EVPN_PREFIX_IPADDR_V4(evp))
+               if (is_evpn_prefix_ipaddr_v4(evp))
                        ipa_len = IPV4_MAX_BYTELEN;
-               else if (IS_EVPN_PREFIX_IPADDR_V6(evp))
+               else if (is_evpn_prefix_ipaddr_v6(evp))
                        ipa_len = IPV6_MAX_BYTELEN;
                /* RD, ESI, EthTag, MAC+len, IP len, [IP], 1 VNI */
                len = 8 + 10 + 4 + 1 + 6 + 1 + ipa_len + 3;
@@ -3717,12 +3720,13 @@ void bgp_evpn_encode_prefix(struct stream *s, struct prefix *p,
                        stream_put(s, &attr->evpn_overlay.eth_s_id, ESI_LEN);
                else
                        stream_put(s, 0, 10);
-               stream_putl(s, evp->prefix.eth_tag);        /* Ethernet Tag ID */
+               stream_putl(s, evp->prefix.macip_addr.eth_tag); /* Ethernet Tag ID */
                stream_putc(s, 8 * ETH_ALEN); /* Mac Addr Len - bits */
-               stream_put(s, evp->prefix.mac.octet, 6); /* Mac Addr */
-               stream_putc(s, 8 * ipa_len);             /* IP address Length */
-               if (ipa_len)                             /* IP */
-                       stream_put(s, &evp->prefix.ip.ip.addr, ipa_len);
+               stream_put(s, evp->prefix.macip_addr.mac.octet, 6); /* Mac Addr */
+               stream_putc(s, 8 * ipa_len); /* IP address Length */
+               if (ipa_len) /* IP */
+                       stream_put(s, &evp->prefix.macip_addr.ip.ip.addr,
+                                  ipa_len);
                /* 1st label is the L2 VNI */
                stream_put(s, label, BGP_LABEL_BYTES);
                /* Include 2nd label (L3 VNI) if advertising MAC+IP */
@@ -3733,10 +3737,10 @@ void 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, evp->prefix.eth_tag);             /* Ethernet Tag ID */
+               stream_putl(s, evp->prefix.imet_addr.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.ipaddr_v4);
+               stream_put_in_addr(s, &evp->prefix.imet_addr.ip.ipaddr_v4);
                break;
 
        case BGP_EVPN_IP_PREFIX_ROUTE:
index 1eecb9ecf7e47372bc1f7efca12f5ebc24dd4a02..1efde3a71934c0c56312fd55b92dc9d7faeb9537 100644 (file)
@@ -272,15 +272,15 @@ static inline void ip_prefix_from_type5_prefix(struct prefix_evpn *evp,
                                               struct prefix *ip)
 {
        memset(ip, 0, sizeof(struct prefix));
-       if (IS_EVPN_PREFIX_IPADDR_V4(evp)) {
+       if (is_evpn_prefix_ipaddr_v4(evp)) {
                ip->family = AF_INET;
-               ip->prefixlen = evp->prefix.ip_prefix_length;
-               memcpy(&(ip->u.prefix4), &(evp->prefix.ip.ip),
+               ip->prefixlen = evp->prefix.prefix_addr.ip_prefix_length;
+               memcpy(&(ip->u.prefix4), &(evp->prefix.prefix_addr.ip.ip),
                       IPV4_MAX_BYTELEN);
-       } else if (IS_EVPN_PREFIX_IPADDR_V6(evp)) {
+       } else if (is_evpn_prefix_ipaddr_v6(evp)) {
                ip->family = AF_INET6;
-               ip->prefixlen = evp->prefix.ip_prefix_length;
-               memcpy(&(ip->u.prefix6), &(evp->prefix.ip.ip),
+               ip->prefixlen = evp->prefix.prefix_addr.ip_prefix_length;
+               memcpy(&(ip->u.prefix6), &(evp->prefix.prefix_addr.ip.ip),
                       IPV6_MAX_BYTELEN);
        }
 }
@@ -290,26 +290,36 @@ static inline int is_evpn_prefix_default(struct prefix *evp)
        if (evp->family != AF_EVPN)
                return 0;
 
-       return ((evp->u.prefix_evpn.ip_prefix_length  == 0) ? 1 : 0);
+       return ((evp->u.prefix_evpn.prefix_addr.ip_prefix_length  == 0) ?
+               1 : 0);
 }
 
 static inline void ip_prefix_from_type2_prefix(struct prefix_evpn *evp,
                                               struct prefix *ip)
 {
        memset(ip, 0, sizeof(struct prefix));
-       if (IS_EVPN_PREFIX_IPADDR_V4(evp)) {
+       if (is_evpn_prefix_ipaddr_v4(evp)) {
                ip->family = AF_INET;
                ip->prefixlen = IPV4_MAX_BITLEN;
-               memcpy(&(ip->u.prefix4), &(evp->prefix.ip.ip),
+               memcpy(&(ip->u.prefix4), &(evp->prefix.macip_addr.ip.ip),
                       IPV4_MAX_BYTELEN);
-       } else if (IS_EVPN_PREFIX_IPADDR_V6(evp)) {
+       } else if (is_evpn_prefix_ipaddr_v6(evp)) {
                ip->family = AF_INET6;
                ip->prefixlen = IPV6_MAX_BITLEN;
-               memcpy(&(ip->u.prefix6), &(evp->prefix.ip.ip),
+               memcpy(&(ip->u.prefix6), &(evp->prefix.macip_addr.ip.ip),
                       IPV6_MAX_BYTELEN);
        }
 }
 
+static inline void ip_prefix_from_evpn_prefix(struct prefix_evpn *evp,
+                                             struct prefix *ip)
+{
+       if (evp->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE)
+               ip_prefix_from_type2_prefix(evp, ip);
+       else if (evp->prefix.route_type == BGP_EVPN_IP_PREFIX_ROUTE)
+               ip_prefix_from_type5_prefix(evp, ip);
+}
+
 static inline void build_evpn_type2_prefix(struct prefix_evpn *p,
                                           struct ethaddr *mac,
                                           struct ipaddr *ip)
@@ -318,10 +328,10 @@ static inline void build_evpn_type2_prefix(struct prefix_evpn *p,
        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);
-       p->prefix.ip.ipa_type = IPADDR_NONE;
+       memcpy(&p->prefix.macip_addr.mac.octet, mac->octet, ETH_ALEN);
+       p->prefix.macip_addr.ip.ipa_type = IPADDR_NONE;
        if (ip)
-               memcpy(&p->prefix.ip, ip, sizeof(*ip));
+               memcpy(&p->prefix.macip_addr.ip, ip, sizeof(*ip));
 }
 
 static inline void build_type5_prefix_from_ip_prefix(struct prefix_evpn *evp,
@@ -343,10 +353,10 @@ static inline void build_type5_prefix_from_ip_prefix(struct prefix_evpn *evp,
        memset(evp, 0, sizeof(struct prefix_evpn));
        evp->family = AF_EVPN;
        evp->prefixlen = EVPN_TYPE_5_ROUTE_PREFIXLEN;
-       evp->prefix.ip_prefix_length = ip_prefix->prefixlen;
        evp->prefix.route_type = BGP_EVPN_IP_PREFIX_ROUTE;
-       evp->prefix.ip.ipa_type = ip.ipa_type;
-       memcpy(&evp->prefix.ip, &ip, sizeof(struct ipaddr));
+       evp->prefix.prefix_addr.ip_prefix_length = ip_prefix->prefixlen;
+       evp->prefix.prefix_addr.ip.ipa_type = ip.ipa_type;
+       memcpy(&evp->prefix.prefix_addr.ip, &ip, sizeof(struct ipaddr));
 }
 
 static inline void build_evpn_type3_prefix(struct prefix_evpn *p,
@@ -356,8 +366,8 @@ static inline void build_evpn_type3_prefix(struct prefix_evpn *p,
        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;
-       p->prefix.ip.ipaddr_v4 = originator_ip;
+       p->prefix.imet_addr.ip.ipa_type = IPADDR_V4;
+       p->prefix.imet_addr.ip.ipaddr_v4 = originator_ip;
 }
 
 static inline int evpn_default_originate_set(struct bgp *bgp, afi_t afi,
index 4802a4caa54895cb89e026f7b0364ee54885d1e6..cfaa04a8c971d01df863feac01c11d0ad105f90b 100644 (file)
@@ -4626,7 +4626,7 @@ static void bgp_static_update_safi(struct bgp *bgp, struct prefix *p,
                if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) {
                        struct bgp_encap_type_vxlan bet;
                        memset(&bet, 0, sizeof(struct bgp_encap_type_vxlan));
-                       bet.vnid = p->u.prefix_evpn.eth_tag;
+                       bet.vnid = p->u.prefix_evpn.prefix_addr.eth_tag;
                        bgp_encap_type_vxlan_to_tlv(&bet, &attr);
                }
                if (bgp_static->router_mac) {
@@ -5101,10 +5101,10 @@ int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
                                return CMD_WARNING_CONFIG_FAILED;
                        }
                        if ((gw_ip.family == AF_INET
-                            && IS_EVPN_PREFIX_IPADDR_V6(
+                            && is_evpn_prefix_ipaddr_v6(
                                        (struct prefix_evpn *)&p))
                            || (gw_ip.family == AF_INET6
-                               && IS_EVPN_PREFIX_IPADDR_V4(
+                               && is_evpn_prefix_ipaddr_v4(
                                           (struct prefix_evpn *)&p))) {
                                vty_out(vty,
                                        "%% GatewayIp family differs with IP prefix\n");
@@ -7129,10 +7129,10 @@ void route_vty_out_overlay(struct vty *vty, struct prefix *p,
                vty_out(vty, "%s", str);
                XFREE(MTYPE_TMP, str);
 
-               if (IS_EVPN_PREFIX_IPADDR_V4((struct prefix_evpn *)p)) {
+               if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn *)p)) {
                        vty_out(vty, "/%s",
                                inet_ntoa(attr->evpn_overlay.gw_ip.ipv4));
-               } else if (IS_EVPN_PREFIX_IPADDR_V6((struct prefix_evpn *)p)) {
+               } else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn *)p)) {
                        vty_out(vty, "/%s",
                                inet_ntop(AF_INET6,
                                          &(attr->evpn_overlay.gw_ip.ipv6), buf,
@@ -11398,14 +11398,15 @@ static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
                        prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
                        if (p->u.prefix_evpn.route_type == 5) {
                                char local_buf[PREFIX_STRLEN];
-                               uint8_t family = IS_EVPN_PREFIX_IPADDR_V4((
+                               uint8_t family = is_evpn_prefix_ipaddr_v4((
                                                         struct prefix_evpn *)p)
                                                         ? AF_INET
                                                         : AF_INET6;
-                               inet_ntop(family, &p->u.prefix_evpn.ip.ip.addr,
+                               inet_ntop(family,
+                                         &p->u.prefix_evpn.prefix_addr.ip.ip.addr,
                                          local_buf, PREFIX_STRLEN);
                                sprintf(buf, "%s/%u", local_buf,
-                                       p->u.prefix_evpn.ip_prefix_length);
+                                       p->u.prefix_evpn.prefix_addr.ip_prefix_length);
                        } else {
                                prefix2str(p, buf, sizeof(buf));
                        }
@@ -11417,7 +11418,8 @@ static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
                                          sizeof(buf2));
                        vty_out(vty,
                                "  network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
-                               buf, rdbuf, p->u.prefix_evpn.eth_tag,
+                               buf, rdbuf,
+                               p->u.prefix_evpn.prefix_addr.eth_tag,
                                decode_label(&bgp_static->label), esi, buf2,
                                macrouter);
 
index 4cc889286ea031860b95f27ec1f04e1d458acafe..63400f7d313ce61acfb422128cc9e1e7aaeb0a52 100644 (file)
@@ -635,7 +635,7 @@ static route_map_result_t route_match_mac_address(void *rule,
 
                p.family = AF_ETHERNET;
                p.prefixlen = ETH_ALEN * 8;
-               p.u.prefix_eth = prefix->u.prefix_evpn.mac;
+               p.u.prefix_eth = prefix->u.prefix_evpn.macip_addr.mac;
 
                return (access_list_apply(alist, &p) == FILTER_DENY
                                ? RMAP_NOMATCH
index b38dd94589bd988ee6767431e2941a930bfaea4a..05af190e9daa5b59db64d3015142a4933dd3685b 100644 (file)
@@ -1206,54 +1206,104 @@ int str2prefix(const char *str, struct prefix *p)
        return 0;
 }
 
-static const char *prefixevpn2str(const struct prefix *p, char *str, int size)
+static const char *prefixevpn_ead2str(const struct prefix_evpn *p, char *str,
+                                     int size)
+{
+       snprintf(str, size, "Unsupported EVPN prefix");
+       return str;
+}
+
+static const char *prefixevpn_macip2str(const struct prefix_evpn *p, char *str,
+                                       int size)
 {
        uint8_t 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),
+       if (is_evpn_prefix_ipaddr_none(p))
+               snprintf(str, size, "[%d]:[%s]/%d",
+                        p->prefix.route_type,
+                        prefix_mac2str(&p->prefix.macip_addr.mac,
+                                       buf2, sizeof(buf2)),
                         p->prefixlen);
-       } else if (p->u.prefix_evpn.route_type == 5) {
-               family = IS_EVPN_PREFIX_IPADDR_V4((struct prefix_evpn *)p)
+       else {
+               family = is_evpn_prefix_ipaddr_v4(p)
                                 ? AF_INET
                                 : AF_INET6;
-               snprintf(str, size, "[%d]:[%u][%s/%d]/%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->u.prefix_evpn.ip_prefix_length, p->prefixlen);
-       } else {
-               sprintf(str, "Unsupported EVPN route type %d",
-                       p->u.prefix_evpn.route_type);
+               snprintf(str, size, "[%d]:[%s]:[%s]/%d",
+                        p->prefix.route_type,
+                        prefix_mac2str(&p->prefix.macip_addr.mac,
+                                       buf2, sizeof(buf2)),
+                        inet_ntop(family,
+                                  &p->prefix.macip_addr.ip.ip.addr,
+                                  buf, PREFIX2STR_BUFFER),
+                        p->prefixlen);
        }
+       return str;
+}
+
+static const char *prefixevpn_imet2str(const struct prefix_evpn *p, char *str,
+                                      int size)
+{
+       uint8_t family;
+       char buf[PREFIX2STR_BUFFER];
+
+       family = is_evpn_prefix_ipaddr_v4(p)
+                        ? AF_INET
+                        : AF_INET6;
+       snprintf(str, size, "[%d]:[%s]/%d", p->prefix.route_type,
+                inet_ntop(family,
+                          &p->prefix.imet_addr.ip.ip.addr, buf,
+                          PREFIX2STR_BUFFER),
+                p->prefixlen);
+       return str;
+}
 
+static const char *prefixevpn_es2str(const struct prefix_evpn *p, char *str,
+                                    int size)
+{
+       snprintf(str, size, "Unsupported EVPN prefix");
+       return str;
+}
+
+static const char *prefixevpn_prefix2str(const struct prefix_evpn *p, char *str,
+                                        int size)
+{
+       uint8_t family;
+       char buf[PREFIX2STR_BUFFER];
+
+       family = is_evpn_prefix_ipaddr_v4(p)
+                        ? AF_INET
+                        : AF_INET6;
+       snprintf(str, size, "[%d]:[%u][%s/%d]/%d",
+                p->prefix.route_type,
+                p->prefix.prefix_addr.eth_tag,
+                inet_ntop(family,
+                          &p->prefix.prefix_addr.ip.ip.addr, buf,
+                          PREFIX2STR_BUFFER),
+                p->prefix.prefix_addr.ip_prefix_length,
+                p->prefixlen);
+       return str;
+}
+
+static const char *prefixevpn2str(const struct prefix_evpn *p, char *str,
+                                 int size)
+{
+       switch (p->prefix.route_type) {
+       case 1:
+               return prefixevpn_ead2str(p, str, size);
+       case 2:
+               return prefixevpn_macip2str(p, str, size);
+       case 3:
+               return prefixevpn_imet2str(p, str, size);
+       case 4:
+               return prefixevpn_es2str(p, str, size);
+       case 5:
+               return prefixevpn_prefix2str(p, str, size);
+       default:
+               snprintf(str, size, "Unsupported EVPN prefix");
+               break;
+       }
        return str;
 }
 
@@ -1277,7 +1327,7 @@ const char *prefix2str(union prefixconstptr pu, char *str, int size)
                break;
 
        case AF_EVPN:
-               prefixevpn2str(p, str, size);
+               prefixevpn2str((const struct prefix_evpn *)p, str, size);
                break;
 
        case AF_FLOWSPEC:
index f01c85b811918079ce603ff8492166d39930d2f6..ab3c05ae744a740ee19ed9fc3c0d54466f519a47 100644 (file)
@@ -56,26 +56,56 @@ struct ethaddr {
 #define PREFIX_LEN_ROUTE_TYPE_5_IPV4 (18*8)
 #define PREFIX_LEN_ROUTE_TYPE_5_IPV6 (30*8)
 
-/* EVPN address (RFC 7432) */
-struct evpn_addr {
-       uint8_t route_type;
+typedef struct esi_t_ {
+       uint8_t val[10];
+} esi_t;
+
+struct evpn_ead_addr {
+       esi_t esi;
+       uint32_t eth_tag;
+};
+
+struct evpn_macip_addr {
+       uint32_t eth_tag;
        uint8_t ip_prefix_length;
        struct ethaddr mac;
+       struct ipaddr ip;
+};
+
+struct evpn_imet_addr {
        uint32_t eth_tag;
+       uint8_t ip_prefix_length;
        struct ipaddr ip;
-#if 0
-  union
-  {
-    uint8_t addr;
-    struct in_addr v4_addr;
-    struct in6_addr v6_addr;
-  } ip;
-#endif
 };
 
-#define IS_EVPN_PREFIX_IPADDR_NONE(evp)  IS_IPADDR_NONE(&(evp)->prefix.ip)
-#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)
+struct evpn_es_addr {
+       esi_t esi;
+       uint8_t ip_prefix_length;
+       struct ipaddr ip;
+};
+
+struct evpn_prefix_addr {
+       uint32_t eth_tag;
+       uint8_t ip_prefix_length;
+       struct ipaddr ip;
+};
+
+/* EVPN address (RFC 7432) */
+struct evpn_addr {
+       uint8_t route_type;
+       union {
+               struct evpn_ead_addr _ead_addr;
+               struct evpn_macip_addr _macip_addr;
+               struct evpn_imet_addr _imet_addr;
+               struct evpn_es_addr _es_addr;
+               struct evpn_prefix_addr _prefix_addr;
+       } u;
+#define ead_addr u._ead_addr
+#define macip_addr u._macip_addr
+#define imet_addr u._imet_addr
+#define es_addr u._es_addr
+#define prefix_addr u._prefix_addr
+};
 
 /*
  * A struct prefix contains an address family, a prefix length, and an
@@ -177,6 +207,39 @@ struct prefix_evpn {
        struct evpn_addr prefix __attribute__((aligned(8)));
 };
 
+static inline int is_evpn_prefix_ipaddr_none(const struct prefix_evpn *evp)
+{
+       if (evp->prefix.route_type == 2)
+               return IS_IPADDR_NONE(&(evp)->prefix.macip_addr.ip);
+       if (evp->prefix.route_type == 3)
+               return IS_IPADDR_NONE(&(evp)->prefix.imet_addr.ip);
+       if (evp->prefix.route_type == 5)
+               return IS_IPADDR_NONE(&(evp)->prefix.prefix_addr.ip);
+       return 0;
+}
+
+static inline int is_evpn_prefix_ipaddr_v4(const struct prefix_evpn *evp)
+{
+       if (evp->prefix.route_type == 2)
+               return IS_IPADDR_V4(&(evp)->prefix.macip_addr.ip);
+       if (evp->prefix.route_type == 3)
+               return IS_IPADDR_V4(&(evp)->prefix.imet_addr.ip);
+       if (evp->prefix.route_type == 5)
+               return IS_IPADDR_V4(&(evp)->prefix.prefix_addr.ip);
+       return 0;
+}
+
+static inline int is_evpn_prefix_ipaddr_v6(const struct prefix_evpn *evp)
+{
+       if (evp->prefix.route_type == 2)
+               return IS_IPADDR_V6(&(evp)->prefix.macip_addr.ip);
+       if (evp->prefix.route_type == 3)
+               return IS_IPADDR_V6(&(evp)->prefix.imet_addr.ip);
+       if (evp->prefix.route_type == 5)
+               return IS_IPADDR_V6(&(evp)->prefix.prefix_addr.ip);
+       return 0;
+}
+
 /* Prefix for a generic pointer */
 struct prefix_ptr {
        uint8_t family;
index 9e0cb1f5ca61cf3e7bb5af2e5bd621690f24324f..8db1cb2ca1d385edea51cae5fdaf26d4f1693114 100644 (file)
@@ -945,6 +945,24 @@ static struct test_segment mp_unreach_segments[] = {
        },
        {NULL, NULL, {0}, 0, 0}};
 
+static struct test_segment mp_prefix_sid[] = {
+       {
+               "PREFIX-SID",
+               "PREFIX-SID Test 1",
+               {
+                       0x01, 0x00, 0x07,
+                       0x00, 0x00, 0x00, 0x00,
+                       0x00, 0x00, 0x02,
+                       0x03, 0x00, 0x08, 0x00,
+                       0x00, 0x0a, 0x1b, 0xfe,
+                       0x00, 0x00, 0x0a
+               },
+               .len = 21,
+               .parses = SHOULD_PARSE,
+       },
+       {NULL, NULL, { 0 }, 0, 0},
+};
+
 /* nlri_parse indicates 0 on successful parse, and -1 otherwise.
  * attr_parse indicates BGP_ATTR_PARSE_PROCEED/0 on success,
  * and BGP_ATTR_PARSE_ERROR/-1 or lower negative ret on err.
@@ -1000,10 +1018,20 @@ static void parse_test(struct peer *peer, struct test_segment *t, int type)
 
        printf("%s: %s\n", t->name, t->desc);
 
-       if (type == BGP_ATTR_MP_REACH_NLRI)
+       switch (type) {
+       case BGP_ATTR_MP_REACH_NLRI:
                parse_ret = bgp_mp_reach_parse(&attr_args, &nlri);
-       else
+               break;
+       case BGP_ATTR_MP_UNREACH_NLRI:
                parse_ret = bgp_mp_unreach_parse(&attr_args, &nlri);
+               break;
+       case BGP_ATTR_PREFIX_SID:
+               parse_ret = bgp_attr_prefix_sid(t->len, &attr_args, &nlri);
+               break;
+       default:
+               printf("unknown type");
+               return;
+       }
        if (!parse_ret) {
                iana_afi_t pkt_afi;
                iana_safi_t pkt_safi;
@@ -1022,7 +1050,7 @@ static void parse_test(struct peer *peer, struct test_segment *t, int type)
        if (!parse_ret) {
                if (type == BGP_ATTR_MP_REACH_NLRI)
                        nlri_ret = bgp_nlri_parse(peer, &attr, &nlri, 0);
-               else
+               else if (type == BGP_ATTR_MP_UNREACH_NLRI)
                        nlri_ret = bgp_nlri_parse(peer, &attr, &nlri, 1);
        }
        handle_result(peer, t, parse_ret, nlri_ret);
@@ -1085,6 +1113,10 @@ int main(void)
                parse_test(peer, &mp_unreach_segments[i++],
                           BGP_ATTR_MP_UNREACH_NLRI);
 
+       i = 0;
+       while (mp_prefix_sid[i].name)
+               parse_test(peer, &mp_prefix_sid[i++],
+                          BGP_ATTR_PREFIX_SID);
        printf("failures: %d\n", failed);
        return failed;
 }