diff options
| author | Lakshman Krishnamoorthy <lkrishnamoor@vmware.com> | 2019-09-11 00:01:39 -0700 | 
|---|---|---|
| committer | Lakshman Krishnamoorthy <lkrishnamoor@vmware.com> | 2019-09-27 10:58:46 -0700 | 
| commit | 44c69747481cc7be3568baef9a58cfc72dd06668 (patch) | |
| tree | ed68b7653d52ef793fde6114ef9c1f1f0afb530c | |
| parent | 5c256b572ca09b5d15b67ba0236c8a2678dda19c (diff) | |
bgpd: Adding new bgp evpn cli's for ip-prefix lookup
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>
| -rw-r--r-- | bgpd/bgp_evpn.c | 109 | ||||
| -rw-r--r-- | bgpd/bgp_evpn.h | 1 | ||||
| -rw-r--r-- | bgpd/bgp_route.c | 277 | ||||
| -rw-r--r-- | lib/prefix.c | 47 | ||||
| -rw-r--r-- | lib/prefix.h | 2 | 
5 files changed, 289 insertions, 147 deletions
diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c index 50fef00a96..bb3ebbcf9a 100644 --- a/bgpd/bgp_evpn.c +++ b/bgpd/bgp_evpn.c @@ -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; +} diff --git a/bgpd/bgp_evpn.h b/bgpd/bgp_evpn.h index 4ad8e95bee..6d1e8cd31b 100644 --- a/bgpd/bgp_evpn.h +++ b/bgpd/bgp_evpn.h @@ -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 */ diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index d083586c93..4c8e3f3dd4 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -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); diff --git a/lib/prefix.c b/lib/prefix.c index 35b679ab90..a34921956f 100644 --- a/lib/prefix.c +++ b/lib/prefix.c @@ -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 */ diff --git a/lib/prefix.h b/lib/prefix.h index 24c146e022..784927616a 100644 --- a/lib/prefix.h +++ b/lib/prefix.h @@ -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 *);  | 
