]> git.proxmox.com Git - mirror_frr.git/commitdiff
bgpd: Adding new bgp evpn cli's for ip-prefix lookup
authorLakshman Krishnamoorthy <lkrishnamoor@vmware.com>
Wed, 11 Sep 2019 07:01:39 +0000 (00:01 -0700)
committerLakshman Krishnamoorthy <lkrishnamoor@vmware.com>
Fri, 27 Sep 2019 17:58:46 +0000 (10:58 -0700)
Implement CLIs for the following, to filter for a prefix within
evpn type 5 route
1) show bgp l2vpn evpn A.B.C.D
2) show bgp l2vpn evpn A.B.C.D json
3) show bgp l2vpn evpn A.B.C.D/M
4) show bgp l2vpn evpn A.B.C.D/M json
5) show bgp l2vpn evpn X:X::X:X
6) show bgp l2vpn evpn X:X::X:X json
7) show bgp l2vpn evpn X:X::X:X/M
8) show bgp l2vpn evpn X:X::X:X/M json

Sample output provided here: https://github.com/FRRouting/frr/pull/4850

Signed-off-by: Lakshman Krishnamoorthy <lkrishnamoor@vmware.com>
bgpd/bgp_evpn.c
bgpd/bgp_evpn.h
bgpd/bgp_route.c
lib/prefix.c
lib/prefix.h

index 50fef00a96c94952f191878609a0457c24df22d9..bb3ebbcf9a75e494bc9c59971e633a78c1def74b 100644 (file)
@@ -4700,59 +4700,60 @@ void bgp_evpn_route2json(struct prefix_evpn *p, json_object *json)
 {
        char buf1[ETHER_ADDR_STRLEN];
        char buf2[PREFIX2STR_BUFFER];
+       uint8_t family;
+       uint8_t prefixlen;
 
        if (!json)
                return;
 
-       if (p->prefix.route_type == BGP_EVPN_IMET_ROUTE) {
-               json_object_int_add(json, "routeType", p->prefix.route_type);
+       json_object_int_add(json, "routeType", p->prefix.route_type);
+
+       switch (p->prefix.route_type) {
+       case BGP_EVPN_MAC_IP_ROUTE:
                json_object_int_add(json, "ethTag",
-                                   p->prefix.imet_addr.eth_tag);
-               json_object_int_add(json, "ipLen",
-                                   is_evpn_prefix_ipaddr_v4(p)
-                                           ? IPV4_MAX_BITLEN
-                                           : IPV6_MAX_BITLEN);
-               json_object_string_add(json, "ip",
-                                      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)) {
-                       json_object_int_add(json, "routeType",
-                                           p->prefix.route_type);
-                       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.macip_addr.mac,
-                                                             buf1,
-                                                             sizeof(buf1)));
-               } else {
-                       uint8_t family;
+                       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.macip_addr.mac, buf1,
+                       sizeof(buf1)));
+
+               if (!is_evpn_prefix_ipaddr_none(p)) {
+                       family = is_evpn_prefix_ipaddr_v4(p) ? AF_INET :
+                               AF_INET6;
+                       prefixlen = (family == AF_INET) ?
+                               IPV4_MAX_BITLEN : IPV6_MAX_BITLEN;
+                       inet_ntop(family, &p->prefix.macip_addr.ip.ip.addr,
+                               buf2, PREFIX2STR_BUFFER);
+                       json_object_int_add(json, "ipLen", prefixlen);
+                       json_object_string_add(json, "ip", buf2);
+               }
+       break;
 
-                       family = is_evpn_prefix_ipaddr_v4(p) ? AF_INET
-                                                            : AF_INET6;
+       case BGP_EVPN_IMET_ROUTE:
+               json_object_int_add(json, "ethTag",
+                       p->prefix.imet_addr.eth_tag);
+               family = is_evpn_prefix_ipaddr_v4(p) ? AF_INET : AF_INET6;
+               prefixlen = (family == AF_INET) ?  IPV4_MAX_BITLEN :
+                       IPV6_MAX_BITLEN;
+               inet_ntop(family, &p->prefix.imet_addr.ip.ip.addr, buf2,
+                       PREFIX2STR_BUFFER);
+               json_object_int_add(json, "ipLen", prefixlen);
+               json_object_string_add(json, "ip", buf2);
+       break;
 
-                       json_object_int_add(json, "routeType",
-                                           p->prefix.route_type);
-                       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.macip_addr.mac,
-                                                             buf1,
-                                                             sizeof(buf1)));
-                       json_object_int_add(json, "ipLen",
-                                           is_evpn_prefix_ipaddr_v4(p)
-                                                   ? IPV4_MAX_BITLEN
-                                                   : IPV6_MAX_BITLEN);
-                       json_object_string_add(
-                               json, "ip",
-                               inet_ntop(family,
-                                         &p->prefix.macip_addr.ip.ip.addr,
-                                         buf2,
-                                         PREFIX2STR_BUFFER));
-               }
-       } else {
-               /* Currently, this is to cater to other AF_ETHERNET code. */
+       case BGP_EVPN_IP_PREFIX_ROUTE:
+               json_object_int_add(json, "ethTag",
+                       p->prefix.prefix_addr.eth_tag);
+               family = is_evpn_prefix_ipaddr_v4(p) ? AF_INET : AF_INET6;
+               inet_ntop(family, &p->prefix.prefix_addr.ip.ip.addr,
+                         buf2, sizeof(buf2));
+               json_object_int_add(json, "ipLen",
+                                   p->prefix.prefix_addr.ip_prefix_length);
+               json_object_string_add(json, "ip", buf2);
+       break;
+
+       default:
+       break;
        }
 }
 
@@ -6011,3 +6012,19 @@ void bgp_evpn_vrf_delete(struct bgp *bgp_vrf)
 {
        bgp_evpn_unmap_vrf_from_its_rts(bgp_vrf);
 }
+
+/*
+ * Get the prefixlen of the ip prefix carried within the type5 evpn route.
+ */
+int bgp_evpn_get_type5_prefixlen(struct prefix *pfx)
+{
+       struct prefix_evpn *evp = (struct prefix_evpn *)pfx;
+
+       if (!pfx || pfx->family != AF_EVPN)
+               return 0;
+
+       if (evp->prefix.route_type != BGP_EVPN_IP_PREFIX_ROUTE)
+               return 0;
+
+       return evp->prefix.prefix_addr.ip_prefix_length;
+}
index 4ad8e95bee05e402218c730f618b337aee86ef00..6d1e8cd31b313056928c479d3cd0f6d97f7d06f0 100644 (file)
@@ -190,5 +190,6 @@ extern void bgp_evpn_flood_control_change(struct bgp *bgp);
 extern void bgp_evpn_cleanup_on_disable(struct bgp *bgp);
 extern void bgp_evpn_cleanup(struct bgp *bgp);
 extern void bgp_evpn_init(struct bgp *bgp);
+extern int bgp_evpn_get_type5_prefixlen(struct prefix *pfx);
 
 #endif /* _QUAGGA_BGP_EVPN_H */
index d083586c93cc781b8576babe916da214c45448fb..4c8e3f3dd44227e39618d65a6d20f46783c12f44 100644 (file)
@@ -8235,7 +8235,7 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp,
                json_nexthop_global = json_object_new_object();
        }
 
-       if (!json_paths && path->extra) {
+       if (path->extra) {
                char tag_buf[30];
 
                buf2[0] = '\0';
@@ -8246,15 +8246,21 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp,
                                           sizeof(tag_buf));
                }
                if (safi == SAFI_EVPN) {
-                       bgp_evpn_route2str((struct prefix_evpn *)&bn->p,
-                                          buf2, sizeof(buf2));
-                       vty_out(vty, "  Route %s", buf2);
-                       if (tag_buf[0] != '\0')
-                               vty_out(vty, " VNI %s", tag_buf);
-                       vty_out(vty, "\n");
+                       if (!json_paths) {
+                               bgp_evpn_route2str((struct prefix_evpn *)&bn->p,
+                                                  buf2, sizeof(buf2));
+                               vty_out(vty, "  Route %s", buf2);
+                               if (tag_buf[0] != '\0')
+                                       vty_out(vty, " VNI %s", tag_buf);
+                               vty_out(vty, "\n");
+                       } else {
+                               if (tag_buf[0])
+                                       json_object_string_add(json_path, "VNI",
+                                                              tag_buf);
+                       }
                }
 
-               if (path->extra && path->extra->parent) {
+               if (path->extra && path->extra->parent && !json_paths) {
                        struct bgp_path_info *parent_ri;
                        struct bgp_node *rn, *prn;
 
@@ -9630,37 +9636,47 @@ void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
        if (has_valid_label)
                label = label_pton(&rn->local_label);
 
-       if (json) {
-               if (has_valid_label)
-                       json_object_int_add(json, "localLabel", label);
+       if (safi == SAFI_EVPN) {
 
-               json_object_string_add(
-                       json, "prefix",
-                       prefix2str(p, prefix_str, sizeof(prefix_str)));
-       } else {
-               if (safi == SAFI_EVPN)
+               if (!json) {
                        vty_out(vty, "BGP routing table entry for %s%s%s\n",
                                prd ? prefix_rd2str(prd, buf1, sizeof(buf1))
-                                   : "",
-                               prd ? ":" : "",
+                               : "", prd ? ":" : "",
                                bgp_evpn_route2str((struct prefix_evpn *)p,
-                                                  buf3, sizeof(buf3)));
-               else
+                               buf3, sizeof(buf3)));
+               } else {
+                       json_object_string_add(json, "rd",
+                               prd ? prefix_rd2str(prd, buf1, sizeof(buf1)) :
+                               "");
+                       bgp_evpn_route2json((struct prefix_evpn *)p, json);
+               }
+       } else {
+               if (!json) {
                        vty_out(vty, "BGP routing table entry for %s%s%s/%d\n",
                                ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
-                                        ? prefix_rd2str(prd, buf1,
-                                                        sizeof(buf1))
-                                        : ""),
+                                ? prefix_rd2str(prd, buf1,
+                                        sizeof(buf1))
+                                : ""),
                                safi == SAFI_MPLS_VPN ? ":" : "",
                                inet_ntop(p->family, &p->u.prefix, buf2,
-                                         INET6_ADDRSTRLEN),
+                                       INET6_ADDRSTRLEN),
                                p->prefixlen);
 
-               if (has_valid_label)
+               } else
+                       json_object_string_add(json, "prefix",
+                               prefix2str(p, prefix_str, sizeof(prefix_str)));
+       }
+
+       if (has_valid_label) {
+               if (json)
+                       json_object_int_add(json, "localLabel", label);
+               else
                        vty_out(vty, "Local label: %d\n", label);
+       }
+
+       if (!json)
                if (bgp_labeled_safi(safi) && safi != SAFI_EVPN)
                        vty_out(vty, "not allocated\n");
-       }
 
        for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
                count++;
@@ -9792,6 +9808,58 @@ void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
        }
 }
 
+static void bgp_show_path_info(struct prefix_rd *pfx_rd,
+                              struct bgp_node *bgp_node, struct vty *vty,
+                              struct bgp *bgp, afi_t afi,
+                              safi_t safi, json_object *json,
+                              enum bgp_path_type pathtype, int *display)
+{
+       struct bgp_path_info *pi;
+       int header = 1;
+       char rdbuf[RD_ADDRSTRLEN];
+       json_object *json_header = NULL;
+       json_object *json_paths = NULL;
+
+       for (pi = bgp_node_get_bgp_path_info(bgp_node); pi;
+            pi = pi->next) {
+
+               if (json && !json_paths) {
+                       /* Instantiate json_paths only if path is valid */
+                       json_paths = json_object_new_array();
+                       if (pfx_rd) {
+                               prefix_rd2str(pfx_rd, rdbuf, sizeof(rdbuf));
+                               json_header = json_object_new_object();
+                       } else
+                               json_header = json;
+               }
+
+               if (header) {
+                       route_vty_out_detail_header(
+                               vty, bgp, bgp_node, pfx_rd,
+                               AFI_IP, safi, json_header);
+                       header = 0;
+               }
+               (*display)++;
+
+               if (pathtype == BGP_PATH_SHOW_ALL
+                   || (pathtype == BGP_PATH_SHOW_BESTPATH
+                       && CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
+                   || (pathtype == BGP_PATH_SHOW_MULTIPATH
+                       && (CHECK_FLAG(pi->flags, BGP_PATH_MULTIPATH)
+                           || CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))))
+                       route_vty_out_detail(vty, bgp, bgp_node,
+                                            pi, AFI_IP, safi,
+                                            json_paths);
+       }
+
+       if (json && json_paths) {
+               json_object_object_add(json_header, "paths", json_paths);
+
+               if (pfx_rd)
+                       json_object_object_add(json, rdbuf, json_header);
+       }
+}
+
 /* Display specified route of BGP table. */
 static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
                                   struct bgp_table *rib, const char *ip_str,
@@ -9800,12 +9868,10 @@ static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
                                   enum bgp_path_type pathtype, bool use_json)
 {
        int ret;
-       int header;
        int display = 0;
        struct prefix match;
        struct bgp_node *rn;
        struct bgp_node *rm;
-       struct bgp_path_info *pi;
        struct bgp_table *table;
        json_object *json = NULL;
        json_object *json_paths = NULL;
@@ -9819,12 +9885,10 @@ static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
 
        match.family = afi2family(afi);
 
-       if (use_json) {
+       if (use_json)
                json = json_object_new_object();
-               json_paths = json_object_new_array();
-       }
 
-       if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
+       if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) {
                for (rn = bgp_table_top(rib); rn; rn = bgp_route_next(rn)) {
                        if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0)
                                continue;
@@ -9832,8 +9896,6 @@ static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
                        if (!table)
                                continue;
 
-                       header = 1;
-
                        if ((rm = bgp_node_match(table, &match)) == NULL)
                                continue;
 
@@ -9843,73 +9905,83 @@ static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
                                continue;
                        }
 
-                       for (pi = bgp_node_get_bgp_path_info(rm); pi;
-                            pi = pi->next) {
-                               if (header) {
-                                       route_vty_out_detail_header(
-                                               vty, bgp, rm,
-                                               (struct prefix_rd *)&rn->p,
-                                               AFI_IP, safi, json);
-                                       header = 0;
+                       bgp_show_path_info((struct prefix_rd *)&rn->p, rm,
+                                          vty, bgp, afi, safi, json,
+                                          pathtype, &display);
+
+                       bgp_unlock_node(rm);
+               }
+       } else if (safi == SAFI_EVPN) {
+               struct bgp_node *longest_pfx;
+               bool is_exact_pfxlen_match = FALSE;
+
+               for (rn = bgp_table_top(rib); rn; rn = bgp_route_next(rn)) {
+                       if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0)
+                               continue;
+                       table = bgp_node_get_bgp_table_info(rn);
+                       if (!table)
+                               continue;
+
+                       longest_pfx = NULL;
+                       is_exact_pfxlen_match = FALSE;
+                       /*
+                        * Search through all the prefixes for a match.  The
+                        * pfx's are enumerated in ascending order of pfxlens.
+                        * So, the last pfx match is the longest match.  Set
+                        * is_exact_pfxlen_match when we get exact pfxlen match
+                        */
+                       for (rm = bgp_table_top(table); rm;
+                               rm = bgp_route_next(rm)) {
+                               /*
+                                * Get prefixlen of the ip-prefix within type5
+                                * evpn route
+                                */
+                               if (evpn_type5_prefix_match(&rm->p,
+                                       &match) && rm->info) {
+                                       longest_pfx = rm;
+                                       int type5_pfxlen =
+                                          bgp_evpn_get_type5_prefixlen(&rm->p);
+                                       if (type5_pfxlen == match.prefixlen) {
+                                               is_exact_pfxlen_match = TRUE;
+                                               bgp_unlock_node(rm);
+                                               break;
+                                       }
                                }
-                               display++;
-
-                               if (pathtype == BGP_PATH_SHOW_ALL
-                                   || (pathtype == BGP_PATH_SHOW_BESTPATH
-                                       && CHECK_FLAG(pi->flags,
-                                                     BGP_PATH_SELECTED))
-                                   || (pathtype == BGP_PATH_SHOW_MULTIPATH
-                                       && (CHECK_FLAG(pi->flags,
-                                                      BGP_PATH_MULTIPATH)
-                                           || CHECK_FLAG(pi->flags,
-                                                         BGP_PATH_SELECTED))))
-                                       route_vty_out_detail(vty, bgp, rm,
-                                                            pi, AFI_IP, safi,
-                                                            json_paths);
                        }
 
+                       if (!longest_pfx)
+                               continue;
+
+                       if (prefix_check && !is_exact_pfxlen_match)
+                               continue;
+
+                       rm = longest_pfx;
+                       bgp_lock_node(rm);
+
+                       bgp_show_path_info((struct prefix_rd *)&rn->p, rm,
+                                          vty, bgp, afi, safi, json,
+                                          pathtype, &display);
+
                        bgp_unlock_node(rm);
                }
        } else if (safi == SAFI_FLOWSPEC) {
+               if (use_json)
+                       json_paths = json_object_new_array();
+
                display = bgp_flowspec_display_match_per_ip(afi, rib,
                                           &match, prefix_check,
                                           vty,
                                           use_json,
                                           json_paths);
+               if (use_json && display)
+                       json_object_object_add(json, "paths", json_paths);
        } else {
-               header = 1;
-
                if ((rn = bgp_node_match(rib, &match)) != NULL) {
                        if (!prefix_check
                            || rn->p.prefixlen == match.prefixlen) {
-                               for (pi = bgp_node_get_bgp_path_info(rn); pi;
-                                    pi = pi->next) {
-                                       if (header) {
-                                               route_vty_out_detail_header(
-                                                       vty, bgp, rn, NULL, afi,
-                                                       safi, json);
-                                               header = 0;
-                                       }
-                                       display++;
-
-                                       if (pathtype == BGP_PATH_SHOW_ALL
-                                           || (pathtype
-                                                       == BGP_PATH_SHOW_BESTPATH
-                                               && CHECK_FLAG(
-                                                          pi->flags,
-                                                          BGP_PATH_SELECTED))
-                                           || (pathtype
-                                                       == BGP_PATH_SHOW_MULTIPATH
-                                               && (CHECK_FLAG(
-                                                           pi->flags,
-                                                           BGP_PATH_MULTIPATH)
-                                                   || CHECK_FLAG(
-                                                              pi->flags,
-                                                              BGP_PATH_SELECTED))))
-                                               route_vty_out_detail(
-                                                       vty, bgp, rn, pi,
-                                                       afi, safi, json_paths);
-                               }
+                               bgp_show_path_info(NULL, rn, vty, bgp, afi,
+                                                  safi, json,
+                                                  pathtype, &display);
                        }
 
                        bgp_unlock_node(rn);
@@ -9917,11 +9989,9 @@ static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp,
        }
 
        if (use_json) {
-               if (display)
-                       json_object_object_add(json, "paths", json_paths);
-
                vty_out(vty, "%s\n", json_object_to_json_string_ext(
-                                            json, JSON_C_TO_STRING_PRETTY));
+                                            json, JSON_C_TO_STRING_PRETTY |
+                                            JSON_C_TO_STRING_NOSLASHESCAPE));
                json_object_free(json);
        } else {
                if (!display) {
@@ -11115,32 +11185,37 @@ DEFUN (show_ip_bgp_vpn_all_route_prefix,
 }
 #endif /* KEEP_OLD_VPN_COMMANDS */
 
-DEFUN (show_ip_bgp_l2vpn_evpn_all_route_prefix,
-       show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd,
-       "show [ip] bgp l2vpn evpn all <A.B.C.D|A.B.C.D/M> [json]",
+DEFUN (show_bgp_l2vpn_evpn_route_prefix,
+       show_bgp_l2vpn_evpn_route_prefix_cmd,
+       "show bgp l2vpn evpn <A.B.C.D|A.B.C.D/M|X:X::X:X|X:X::X:X/M> [json]",
        SHOW_STR
-       IP_STR
        BGP_STR
        L2VPN_HELP_STR
        EVPN_HELP_STR
-       "Display information about all EVPN NLRIs\n"
+       "Network in the BGP routing table to display\n"
+       "Network in the BGP routing table to display\n"
        "Network in the BGP routing table to display\n"
        "Network in the BGP routing table to display\n"
        JSON_STR)
 {
        int idx = 0;
        char *network = NULL;
+       int prefix_check = 0;
 
-       if (argv_find(argv, argc, "A.B.C.D", &idx))
+       if (argv_find(argv, argc, "A.B.C.D", &idx) ||
+               argv_find(argv, argc, "X:X::X:X", &idx))
                network = argv[idx]->arg;
-       else if (argv_find(argv, argc, "A.B.C.D/M", &idx))
+       else if (argv_find(argv, argc, "A.B.C.D/M", &idx) ||
+               argv_find(argv, argc, "A.B.C.D/M", &idx)) {
                network = argv[idx]->arg;
-       else {
+               prefix_check = 1;
+       } else {
                vty_out(vty, "Unable to figure out Network\n");
                return CMD_WARNING;
        }
-       return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL, 0,
-                             BGP_PATH_SHOW_ALL, use_json(argc, argv));
+       return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL,
+                             prefix_check, BGP_PATH_SHOW_ALL,
+                             use_json(argc, argv));
 }
 
 static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi,
@@ -12637,7 +12712,7 @@ void bgp_route_init(void)
 #endif /* KEEP_OLD_VPN_COMMANDS */
        install_element(VIEW_NODE, &show_bgp_afi_vpn_rd_route_cmd);
        install_element(VIEW_NODE,
-                       &show_ip_bgp_l2vpn_evpn_all_route_prefix_cmd);
+                       &show_bgp_l2vpn_evpn_route_prefix_cmd);
 
        /* BGP dampening clear commands */
        install_element(ENABLE_NODE, &clear_ip_bgp_dampening_cmd);
index 35b679ab90fbef48a76c2c3f74cb96f3be95307f..a34921956f180b8936145961ad89b125c59fa4cb 100644 (file)
@@ -601,6 +601,53 @@ int prefix_match(const struct prefix *n, const struct prefix *p)
                if (np[offset] != pp[offset])
                        return 0;
        return 1;
+
+}
+
+/*
+ * n is a type5 evpn prefix. This function tries to see if there is an
+ * ip-prefix within n which matches prefix p
+ * If n includes p prefix then return 1 else return 0.
+ */
+int evpn_type5_prefix_match(const struct prefix *n, const struct prefix *p)
+{
+       int offset;
+       int shift;
+       int prefixlen;
+       const uint8_t *np, *pp;
+       struct prefix_evpn *evp;
+
+       if (n->family != AF_EVPN)
+               return 0;
+
+       evp = (struct prefix_evpn *)n;
+       pp = p->u.val;
+
+       if ((evp->prefix.route_type != 5) ||
+           (p->family == AF_INET6 && !is_evpn_prefix_ipaddr_v6(evp)) ||
+           (p->family == AF_INET && !is_evpn_prefix_ipaddr_v4(evp)) ||
+           (is_evpn_prefix_ipaddr_none(evp)))
+               return 0;
+
+       prefixlen = evp->prefix.prefix_addr.ip_prefix_length;
+       np = &evp->prefix.prefix_addr.ip.ip.addr;
+
+       /* If n's prefix is longer than p's one return 0. */
+       if (prefixlen > p->prefixlen)
+               return 0;
+
+       offset = prefixlen / PNBBY;
+       shift = prefixlen % PNBBY;
+
+       if (shift)
+               if (maskbit[shift] & (np[offset] ^ pp[offset]))
+                       return 0;
+
+       while (offset--)
+               if (np[offset] != pp[offset])
+                       return 0;
+       return 1;
+
 }
 
 /* If n includes p then return 1 else return 0. Prefix mask is not considered */
index 24c146e02221db0a17a5baadf93cda3574104daf..784927616a3445b3255f5172a81212784622bbe1 100644 (file)
@@ -407,6 +407,8 @@ extern void prefix_mcast_inet4_dump(const char *onfail, struct in_addr addr,
                                char *buf, int buf_size);
 extern const char *prefix_sg2str(const struct prefix_sg *sg, char *str);
 extern const char *prefix2str(union prefixconstptr, char *, int);
+extern int evpn_type5_prefix_match(const struct prefix *evpn_pfx,
+                                  const struct prefix *match_pfx);
 extern int prefix_match(const struct prefix *, const struct prefix *);
 extern int prefix_match_network_statement(const struct prefix *,
                                          const struct prefix *);