diff options
| author | Donatas Abraitis <donatas@opensourcerouting.org> | 2022-11-17 16:46:58 +0200 | 
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-11-17 16:46:58 +0200 | 
| commit | f8d69be43fe6c19fd66d2c65c178e4692dc25aed (patch) | |
| tree | b5c40ab8a88878d1c21d0d374a70fd137d1b751a /bgpd/bgp_evpn_vty.c | |
| parent | 1e5e7934eabc39831f79c113bb1c0b8b9a74c499 (diff) | |
| parent | d950d2246db240816162bbade29f4fb6cea14988 (diff) | |
Merge pull request #12081 from sworleys/EMM-upstream
Rework of Various Handling in EVPN for Extended Mac Mobility
Diffstat (limited to 'bgpd/bgp_evpn_vty.c')
| -rw-r--r-- | bgpd/bgp_evpn_vty.c | 750 | 
1 files changed, 692 insertions, 58 deletions
diff --git a/bgpd/bgp_evpn_vty.c b/bgpd/bgp_evpn_vty.c index 0f2ade8737..88c1329f48 100644 --- a/bgpd/bgp_evpn_vty.c +++ b/bgpd/bgp_evpn_vty.c @@ -57,6 +57,8 @@ struct vni_walk_ctx {  	struct in_addr vtep_ip;  	json_object *json;  	int detail; +	int type; +	bool mac_table;  };  int argv_find_and_parse_oly_idx(struct cmd_token **argv, int argc, int *oly_idx, @@ -517,7 +519,7 @@ static void display_vni(struct vty *vty, struct bgpevpn *vpn, json_object *json)  			json, "sviInterface",  			ifindex2ifname(vpn->svi_ifindex, vpn->tenant_vrf_id));  	} else { -		vty_out(vty, "VNI: %d", vpn->vni); +		vty_out(vty, "VNI: %u", vpn->vni);  		if (is_vni_live(vpn))  			vty_out(vty, " (known to the kernel)");  		vty_out(vty, "\n"); @@ -735,7 +737,8 @@ static void bgp_evpn_show_routes_mac_ip_es(struct vty *vty, esi_t *esi,  			if (detail)  				route_vty_out_detail( -					vty, bgp, rn, pi, AFI_L2VPN, SAFI_EVPN, +					vty, bgp, rn, bgp_dest_get_prefix(rn), +					pi, AFI_L2VPN, SAFI_EVPN,  					RPKI_NOT_BEING_USED, json_path);  			else  				route_vty_out(vty, &rn->p, pi, 0, SAFI_EVPN, @@ -770,9 +773,10 @@ static void bgp_evpn_show_routes_mac_ip_global_es(struct vty *vty, esi_t *esi,  	bgp_evpn_show_routes_mac_ip_es(vty, esi, json, detail, true);  } -static void show_vni_routes(struct bgp *bgp, struct bgpevpn *vpn, int type, -			    struct vty *vty, struct in_addr vtep_ip, -			    json_object *json, int detail) +static void show_vni_routes(struct bgp *bgp, struct bgpevpn *vpn, +			    struct vty *vty, int type, bool mac_table, +			    struct in_addr vtep_ip, json_object *json, +			    int detail)  {  	struct bgp_dest *dest;  	struct bgp_path_info *pi; @@ -783,7 +787,11 @@ static void show_vni_routes(struct bgp *bgp, struct bgpevpn *vpn, int type,  	prefix_cnt = path_cnt = 0; -	table = vpn->route_table; +	if (mac_table) +		table = vpn->mac_table; +	else +		table = vpn->ip_table; +  	tbl_ver = table->version;  	for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {  		const struct prefix_evpn *evp = @@ -818,6 +826,7 @@ static void show_vni_routes(struct bgp *bgp, struct bgpevpn *vpn, int type,  		 * with code that already exists).  		 */  		for (; pi; pi = pi->next) { +			struct prefix tmp_p;  			json_object *json_path = NULL;  			if (vtep_ip.s_addr != INADDR_ANY @@ -825,16 +834,43 @@ static void show_vni_routes(struct bgp *bgp, struct bgpevpn *vpn, int type,  					       &(pi->attr->nexthop)))  				continue; +			if (evp->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE) { +				/* +				 * VNI IP/MAC table prefixes don't have MAC/IP +				 * respectively so make sure it's set from path +				 * info here. +				 */ +				if (is_evpn_prefix_ipaddr_none(evp)) { +					/* VNI MAC -> Global */ +					evpn_type2_prefix_global_copy( +						(struct prefix_evpn *)&tmp_p, +						evp, NULL /* mac */, +						evpn_type2_path_info_get_ip( +							pi)); +				} else { +					/* VNI IP -> Global */ +					evpn_type2_prefix_global_copy( +						(struct prefix_evpn *)&tmp_p, +						evp, +						evpn_type2_path_info_get_mac( +							pi), +						NULL /* ip */); +				} +			} else +				memcpy(&tmp_p, p, sizeof(tmp_p)); + +  			if (json)  				json_path = json_object_new_array();  			if (detail) -				route_vty_out_detail(vty, bgp, dest, pi, +				route_vty_out_detail(vty, bgp, dest, &tmp_p, pi,  						     AFI_L2VPN, SAFI_EVPN,  						     RPKI_NOT_BEING_USED,  						     json_path); +  			else -				route_vty_out(vty, p, pi, 0, SAFI_EVPN, +				route_vty_out(vty, &tmp_p, pi, 0, SAFI_EVPN,  					      json_path, false);  			if (json) @@ -887,19 +923,55 @@ static void show_vni_routes_hash(struct hash_bucket *bucket, void *arg)  	json_object *json_vni = NULL;  	char vni_str[VNI_STR_LEN]; -	snprintf(vni_str, sizeof(vni_str), "%d", vpn->vni); +	snprintf(vni_str, sizeof(vni_str), "%u", vpn->vni); +	if (json) { +		json_vni = json_object_new_object(); +		json_object_int_add(json_vni, "vni", vpn->vni); +	} else { +		vty_out(vty, "\nVNI: %u\n\n", vpn->vni); +	} + +	show_vni_routes(wctx->bgp, vpn, wctx->vty, wctx->type, wctx->mac_table, +			wctx->vtep_ip, json_vni, wctx->detail); + +	if (json) +		json_object_object_add(json, vni_str, json_vni); +} + +static void show_vni_routes_all_hash(struct hash_bucket *bucket, void *arg) +{ +	struct bgpevpn *vpn = (struct bgpevpn *)bucket->data; +	struct vni_walk_ctx *wctx = arg; +	struct vty *vty = wctx->vty; +	json_object *json = wctx->json; +	json_object *json_vni = NULL; +	json_object *json_vni_mac = NULL; +	char vni_str[VNI_STR_LEN]; + +	snprintf(vni_str, sizeof(vni_str), "%u", vpn->vni);  	if (json) {  		json_vni = json_object_new_object();  		json_object_int_add(json_vni, "vni", vpn->vni);  	} else { -		vty_out(vty, "\nVNI: %d\n\n", vpn->vni); +		vty_out(vty, "\nVNI: %u\n\n", vpn->vni);  	} -	show_vni_routes(wctx->bgp, vpn, 0, wctx->vty, wctx->vtep_ip, json_vni, -			wctx->detail); +	show_vni_routes(wctx->bgp, vpn, wctx->vty, 0, false, wctx->vtep_ip, +			json_vni, wctx->detail);  	if (json)  		json_object_object_add(json, vni_str, json_vni); + +	if (json) +		json_vni_mac = json_object_new_object(); +	else +		vty_out(vty, "\nVNI: %u MAC Table\n\n", vpn->vni); + +	show_vni_routes(wctx->bgp, vpn, wctx->vty, 0, true, wctx->vtep_ip, +			json_vni_mac, wctx->detail); + +	if (json) +		json_object_object_add(json_vni, "macTable", json_vni_mac);  }  static void show_l3vni_entry(struct vty *vty, struct bgp *bgp, @@ -2322,9 +2394,9 @@ static void evpn_show_import_rts(struct vty *vty, struct bgp *bgp,  /*   * Display EVPN routes for all VNIs - vty handler.   */ -static void evpn_show_routes_vni_all(struct vty *vty, struct bgp *bgp, -				     struct in_addr vtep_ip, json_object *json, -				     int detail) +static void evpn_show_routes_vni_all(struct vty *vty, struct bgp *bgp, int type, +				     bool mac_table, struct in_addr vtep_ip, +				     json_object *json, int detail)  {  	uint32_t num_vnis;  	struct vni_walk_ctx wctx; @@ -2335,6 +2407,8 @@ static void evpn_show_routes_vni_all(struct vty *vty, struct bgp *bgp,  	memset(&wctx, 0, sizeof(wctx));  	wctx.bgp = bgp;  	wctx.vty = vty; +	wctx.type = type; +	wctx.mac_table = mac_table;  	wctx.vtep_ip = vtep_ip;  	wctx.json = json;  	wctx.detail = detail; @@ -2344,6 +2418,32 @@ static void evpn_show_routes_vni_all(struct vty *vty, struct bgp *bgp,  }  /* + * Display EVPN routes for all VNIs & all types - vty handler. + */ +static void evpn_show_routes_vni_all_type_all(struct vty *vty, struct bgp *bgp, +					      struct in_addr vtep_ip, +					      json_object *json, int detail) +{ +	uint32_t num_vnis; +	struct vni_walk_ctx wctx; + +	num_vnis = hashcount(bgp->vnihash); +	if (!num_vnis) +		return; + +	memset(&wctx, 0, sizeof(struct vni_walk_ctx)); +	wctx.bgp = bgp; +	wctx.vty = vty; +	wctx.vtep_ip = vtep_ip; +	wctx.json = json; +	wctx.detail = detail; +	hash_iterate(bgp->vnihash, +		     (void (*)(struct hash_bucket *, +			       void *))show_vni_routes_all_hash, +		     &wctx); +} + +/*   * Display EVPN routes for a VNI -- for specific type-3 route (vty handler).   */  static void evpn_show_route_vni_multicast(struct vty *vty, struct bgp *bgp, @@ -2371,7 +2471,7 @@ static void evpn_show_route_vni_multicast(struct vty *vty, struct bgp *bgp,  	/* See if route exists. */  	build_evpn_type3_prefix(&p, orig_ip); -	dest = bgp_node_lookup(vpn->route_table, (struct prefix *)&p); +	dest = bgp_evpn_vni_node_lookup(vpn, &p, NULL);  	if (!dest || !bgp_dest_has_bgp_path_info_data(dest)) {  		if (!json)  			vty_out(vty, "%% Network not in table\n"); @@ -2386,7 +2486,8 @@ static void evpn_show_route_vni_multicast(struct vty *vty, struct bgp *bgp,  		json_paths = json_object_new_array();  	/* Prefix and num paths displayed once per prefix. */ -	route_vty_out_detail_header(vty, bgp, dest, NULL, afi, safi, json); +	route_vty_out_detail_header(vty, bgp, dest, bgp_dest_get_prefix(dest), +				    NULL, afi, safi, json);  	/* Display each path for this prefix. */  	for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) { @@ -2395,8 +2496,9 @@ static void evpn_show_route_vni_multicast(struct vty *vty, struct bgp *bgp,  		if (json)  			json_path = json_object_new_array(); -		route_vty_out_detail(vty, bgp, dest, pi, afi, safi, -				     RPKI_NOT_BEING_USED, json_path); +		route_vty_out_detail(vty, bgp, dest, bgp_dest_get_prefix(dest), +				     pi, afi, safi, RPKI_NOT_BEING_USED, +				     json_path);  		if (json)  			json_object_array_add(json_paths, json_path); @@ -2427,12 +2529,15 @@ static void evpn_show_route_vni_macip(struct vty *vty, struct bgp *bgp,  {  	struct bgpevpn *vpn;  	struct prefix_evpn p; +	struct prefix_evpn tmp_p;  	struct bgp_dest *dest;  	struct bgp_path_info *pi;  	uint32_t path_cnt = 0;  	afi_t afi;  	safi_t safi;  	json_object *json_paths = NULL; +	struct ethaddr empty_mac = {}; +	const struct prefix_evpn *evp;  	afi = AFI_L2VPN;  	safi = SAFI_EVPN; @@ -2445,9 +2550,10 @@ static void evpn_show_route_vni_macip(struct vty *vty, struct bgp *bgp,  		return;  	} +	build_evpn_type2_prefix(&p, mac ? mac : &empty_mac, ip); +  	/* See if route exists. Look for both non-sticky and sticky. */ -	build_evpn_type2_prefix(&p, mac, ip); -	dest = bgp_node_lookup(vpn->route_table, (struct prefix *)&p); +	dest = bgp_evpn_vni_node_lookup(vpn, &p, NULL);  	if (!dest || !bgp_dest_has_bgp_path_info_data(dest)) {  		if (!json)  			vty_out(vty, "%% Network not in table\n"); @@ -2458,21 +2564,68 @@ static void evpn_show_route_vni_macip(struct vty *vty, struct bgp *bgp,  		return;  	} +	/* +	 * MAC is per-path, we have to walk the path_info's and look for it +	 * first here. +	 */ +	if (ip && mac) { +		for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) { +			if (memcmp(mac, evpn_type2_path_info_get_mac(pi), +				   sizeof(*mac)) == 0) +				break; +		} + +		if (!pi) { +			if (!json) +				vty_out(vty, "%% Network not in table\n"); +			return; +		} +	} +  	if (json)  		json_paths = json_object_new_array();  	/* Prefix and num paths displayed once per prefix. */ -	route_vty_out_detail_header(vty, bgp, dest, NULL, afi, safi, json); +	route_vty_out_detail_header(vty, bgp, dest, (struct prefix *)&p, NULL, +				    afi, safi, json); + +	evp = (const struct prefix_evpn *)bgp_dest_get_prefix(dest);  	/* Display each path for this prefix. */  	for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {  		json_object *json_path = NULL; +		/* skip non-matching MACs */ +		if (ip && mac && +		    memcmp(mac, evpn_type2_path_info_get_mac(pi), +			   sizeof(*mac)) != 0) +			continue; +  		if (json)  			json_path = json_object_new_array(); -		route_vty_out_detail(vty, bgp, dest, pi, afi, safi, -				     RPKI_NOT_BEING_USED, json_path); +		/* +		 * VNI table MAC-IP prefixes don't have MAC so +		 * make sure it's set from path info +		 * here. +		 */ +		if (is_evpn_prefix_ipaddr_none(evp)) { +			/* VNI MAC -> Global */ +			evpn_type2_prefix_global_copy( +				(struct prefix_evpn *)&tmp_p, evp, +				NULL /* mac */, +				evpn_type2_path_info_get_ip(pi)); +		} else { +			/* VNI IP -> Global */ +			evpn_type2_prefix_global_copy( +				(struct prefix_evpn *)&tmp_p, evp, +				evpn_type2_path_info_get_mac(pi), +				NULL /* ip */); +		} + +		route_vty_out_detail(vty, bgp, dest, (struct prefix *)&tmp_p, +				     pi, afi, safi, RPKI_NOT_BEING_USED, +				     json_path);  		if (json)  			json_object_array_add(json_paths, json_path); @@ -2516,8 +2669,8 @@ static void evpn_show_routes_esi(struct vty *vty, struct bgp *bgp,   * If the vtep_ip is non zero, only routes behind that vtep are shown   */  static void evpn_show_routes_vni(struct vty *vty, struct bgp *bgp, vni_t vni, -				 int type, struct in_addr vtep_ip, -				 json_object *json) +				 int type, bool mac_table, +				 struct in_addr vtep_ip, json_object *json)  {  	struct bgpevpn *vpn; @@ -2530,7 +2683,7 @@ static void evpn_show_routes_vni(struct vty *vty, struct bgp *bgp, vni_t vni,  	}  	/* Walk this VNI's route table and display appropriate routes. */ -	show_vni_routes(bgp, vpn, type, vty, vtep_ip, json, 0); +	show_vni_routes(bgp, vpn, vty, type, mac_table, vtep_ip, json, 0);  }  /* @@ -2568,7 +2721,8 @@ static void evpn_show_route_rd_macip(struct vty *vty, struct bgp *bgp,  	}  	/* Prefix and num paths displayed once per prefix. */ -	route_vty_out_detail_header(vty, bgp, dest, prd, afi, safi, json); +	route_vty_out_detail_header(vty, bgp, dest, bgp_dest_get_prefix(dest), +				    prd, afi, safi, json);  	if (json)  		json_paths = json_object_new_array(); @@ -2580,8 +2734,9 @@ static void evpn_show_route_rd_macip(struct vty *vty, struct bgp *bgp,  		if (json)  			json_path = json_object_new_array(); -		route_vty_out_detail(vty, bgp, dest, pi, afi, safi, -				     RPKI_NOT_BEING_USED, json_path); +		route_vty_out_detail(vty, bgp, dest, bgp_dest_get_prefix(dest), +				     pi, afi, safi, RPKI_NOT_BEING_USED, +				     json_path);  		if (json)  			json_object_array_add(json_paths, json_path); @@ -2673,8 +2828,9 @@ static void evpn_show_route_rd(struct vty *vty, struct bgp *bgp,  			}  			/* Prefix and num paths displayed once per prefix. */ -			route_vty_out_detail_header(vty, bgp, dest, prd, afi, -						    safi, json_prefix); +			route_vty_out_detail_header( +				vty, bgp, dest, bgp_dest_get_prefix(dest), prd, +				afi, safi, json_prefix);  			prefix_cnt++;  		} @@ -2689,8 +2845,9 @@ static void evpn_show_route_rd(struct vty *vty, struct bgp *bgp,  			if (json)  				json_path = json_object_new_array(); -			route_vty_out_detail(vty, bgp, dest, pi, afi, safi, -					     RPKI_NOT_BEING_USED, json_path); +			route_vty_out_detail( +				vty, bgp, dest, bgp_dest_get_prefix(dest), pi, +				afi, safi, RPKI_NOT_BEING_USED, json_path);  			if (json)  				json_object_array_add(json_paths, json_path); @@ -2807,7 +2964,7 @@ static void evpn_show_route_rd_all_macip(struct vty *vty, struct bgp *bgp,  		} else  			/* Prefix and num paths displayed once per prefix. */  			route_vty_out_detail_header( -				vty, bgp, dest, (struct prefix_rd *)rd_destp, +				vty, bgp, dest, p, (struct prefix_rd *)rd_destp,  				AFI_L2VPN, SAFI_EVPN, json_prefix);  		/* For EVPN, the prefix is displayed for each path (to @@ -2822,7 +2979,7 @@ static void evpn_show_route_rd_all_macip(struct vty *vty, struct bgp *bgp,  			if (json)  				json_path = json_object_new_array(); -			route_vty_out_detail(vty, bgp, dest, pi, AFI_L2VPN, +			route_vty_out_detail(vty, bgp, dest, p, pi, AFI_L2VPN,  					     SAFI_EVPN, RPKI_NOT_BEING_USED,  					     json_path); @@ -2960,6 +3117,7 @@ static void evpn_show_all_routes(struct vty *vty, struct bgp *bgp, int type,  			if (detail)  				route_vty_out_detail_header(  					vty, bgp, dest, +					bgp_dest_get_prefix(dest),  					(struct prefix_rd *)rd_destp, AFI_L2VPN,  					SAFI_EVPN, json_prefix); @@ -2979,9 +3137,10 @@ static void evpn_show_all_routes(struct vty *vty, struct bgp *bgp, int type,  				if (detail) {  					route_vty_out_detail( -						vty, bgp, dest, pi, AFI_L2VPN, -						SAFI_EVPN, RPKI_NOT_BEING_USED, -						json_path); +						vty, bgp, dest, +						bgp_dest_get_prefix(dest), pi, +						AFI_L2VPN, SAFI_EVPN, +						RPKI_NOT_BEING_USED, json_path);  				} else  					route_vty_out(vty, p, pi, 0, SAFI_EVPN,  						      json_path, false); @@ -3297,7 +3456,7 @@ static void write_vni_config(struct vty *vty, struct bgpevpn *vpn)  	struct ecommunity *ecom;  	if (is_vni_configured(vpn)) { -		vty_out(vty, "  vni %d\n", vpn->vni); +		vty_out(vty, "  vni %u\n", vpn->vni);  		if (is_rd_configured(vpn))  			vty_out(vty, "   rd %pRD\n", &vpn->prd); @@ -4562,28 +4721,32 @@ DEFUN(show_bgp_l2vpn_evpn_summary, show_bgp_l2vpn_evpn_summary_cmd,  				    as_type, as, show_flags);  } +static int bgp_evpn_cli_parse_type_cmp(int *type, const char *type_str) +{ +	if ((strncmp(type_str, "ma", 2) == 0) || (strmatch(type_str, "2"))) +		*type = BGP_EVPN_MAC_IP_ROUTE; +	else if ((strncmp(type_str, "mu", 2) == 0) || (strmatch(type_str, "3"))) +		*type = BGP_EVPN_IMET_ROUTE; +	else if ((strncmp(type_str, "es", 2) == 0) || (strmatch(type_str, "4"))) +		*type = BGP_EVPN_ES_ROUTE; +	else if ((strncmp(type_str, "ea", 2) == 0) || (strmatch(type_str, "1"))) +		*type = BGP_EVPN_AD_ROUTE; +	else if ((strncmp(type_str, "p", 1) == 0) || (strmatch(type_str, "5"))) +		*type = BGP_EVPN_IP_PREFIX_ROUTE; +	else +		return -1; + +	return 0; +} +  int bgp_evpn_cli_parse_type(int *type, struct cmd_token **argv, int argc)  {  	int type_idx = 0;  	if (argv_find(argv, argc, "type", &type_idx)) {  		/* Specific type is requested */ -		if ((strncmp(argv[type_idx + 1]->arg, "ma", 2) == 0) -		    || (strmatch(argv[type_idx + 1]->arg, "2"))) -			*type = BGP_EVPN_MAC_IP_ROUTE; -		else if ((strncmp(argv[type_idx + 1]->arg, "mu", 2) == 0) -			 || (strmatch(argv[type_idx + 1]->arg, "3"))) -			*type = BGP_EVPN_IMET_ROUTE; -		else if ((strncmp(argv[type_idx + 1]->arg, "es", 2) == 0) -			 || (strmatch(argv[type_idx + 1]->arg, "4"))) -			*type = BGP_EVPN_ES_ROUTE; -		else if ((strncmp(argv[type_idx + 1]->arg, "ea", 2) == 0) -			 || (strmatch(argv[type_idx + 1]->arg, "1"))) -			*type = BGP_EVPN_AD_ROUTE; -		else if ((strncmp(argv[type_idx + 1]->arg, "p", 1) == 0) -			 || (strmatch(argv[type_idx + 1]->arg, "5"))) -			*type = BGP_EVPN_IP_PREFIX_ROUTE; -		else +		if (bgp_evpn_cli_parse_type_cmp(type, +						argv[type_idx + 1]->arg) != 0)  			return -1;  	} @@ -4881,7 +5044,7 @@ DEFUN(show_bgp_l2vpn_evpn_route_vni, show_bgp_l2vpn_evpn_route_vni_cmd,  		}  	} -	evpn_show_routes_vni(vty, bgp, vni, type, vtep_ip, json); +	evpn_show_routes_vni(vty, bgp, vni, type, false, vtep_ip, json);  	if (uj)  		vty_json(vty, json); @@ -5063,7 +5226,464 @@ DEFUN(show_bgp_l2vpn_evpn_route_vni_all,  		}  	} -	evpn_show_routes_vni_all(vty, bgp, vtep_ip, json, da); +	evpn_show_routes_vni_all(vty, bgp, 0, false, vtep_ip, json, da); + +	if (uj) { +		vty_json(vty, json); +		json_object_free(json); +	} + +	return CMD_SUCCESS; +} + +/* + * Display per-VNI EVPN ALL routing tables - for all VNIs. + */ +DEFPY(show_bgp_vni_all, +      show_bgp_vni_all_cmd, +      "show bgp vni all [vtep A.B.C.D$addr] [detail$detail] [json$uj]", +      SHOW_STR +      BGP_STR +      VNI_HELP_STR +      VNI_ALL_HELP_STR +      VTEP_HELP_STR +      VTEP_IP_HELP_STR +      DETAIL_HELP_STR +      JSON_STR) +{ +	struct bgp *bgp; +	json_object *json = NULL; + +	bgp = bgp_get_evpn(); +	if (!bgp) +		return CMD_WARNING; + +	/* check if we need json output */ +	if (uj) +		json = json_object_new_object(); + +	evpn_show_routes_vni_all_type_all(vty, bgp, addr, json, !!detail); + +	if (uj) +		vty_json(vty, json); + +	return CMD_SUCCESS; +} + +/* + * Display per-VNI EVPN EAD routing table - for all VNIs. + */ +DEFPY(show_bgp_vni_all_ead, +      show_bgp_vni_all_ead_cmd, +      "show bgp vni all type <1|ead> [vtep A.B.C.D$addr] [<detail$detail|json$uj>]", +      SHOW_STR +      BGP_STR +      VNI_HELP_STR +      VNI_ALL_HELP_STR +      EVPN_TYPE_HELP_STR +      EVPN_TYPE_1_HELP_STR +      EVPN_TYPE_1_HELP_STR +      VTEP_HELP_STR +      VTEP_IP_HELP_STR +      DETAIL_HELP_STR +      JSON_STR) +{ +	struct bgp *bgp; +	json_object *json = NULL; + +	bgp = bgp_get_evpn(); +	if (!bgp) +		return CMD_WARNING; + +	/* check if we need json output */ +	if (uj) +		json = json_object_new_object(); + +	evpn_show_routes_vni_all(vty, bgp, BGP_EVPN_AD_ROUTE, false, addr, json, +				 !!detail); + +	if (uj) +		vty_json(vty, json); + +	return CMD_SUCCESS; +} + +/* + * Display per-VNI EVPN MAC routing table - for all VNIs. + */ +DEFPY(show_bgp_vni_all_macip_mac, +      show_bgp_vni_all_macip_mac_cmd, +      "show bgp vni all type <2|macip> mac [vtep A.B.C.D$addr] [<detail$detail|json$uj>]", +      SHOW_STR +      BGP_STR +      VNI_HELP_STR +      VNI_ALL_HELP_STR +      EVPN_TYPE_HELP_STR +      EVPN_TYPE_2_HELP_STR +      EVPN_TYPE_2_HELP_STR +      "MAC Table\n" +      VTEP_HELP_STR +      VTEP_IP_HELP_STR +      DETAIL_HELP_STR +      JSON_STR) +{ +	struct bgp *bgp; +	json_object *json = NULL; + +	bgp = bgp_get_evpn(); +	if (!bgp) +		return CMD_WARNING; + +	/* check if we need json output */ +	if (uj) +		json = json_object_new_object(); + +	evpn_show_routes_vni_all(vty, bgp, BGP_EVPN_MAC_IP_ROUTE, true, addr, +				 json, !!detail); + +	if (uj) +		vty_json(vty, json); + +	return CMD_SUCCESS; +} + +/* + * Display per-VNI EVPN IP routing table - for all VNIs. + */ +DEFPY(show_bgp_vni_all_macip_ip, +      show_bgp_vni_all_macip_ip_cmd, +      "show bgp vni all type <2|macip> ip [vtep A.B.C.D$addr] [<detail$detail|json$uj>]", +      SHOW_STR +      BGP_STR +      VNI_HELP_STR +      VNI_ALL_HELP_STR +      EVPN_TYPE_HELP_STR +      EVPN_TYPE_2_HELP_STR +      EVPN_TYPE_2_HELP_STR +      "IP Table\n" +      VTEP_HELP_STR +      VTEP_IP_HELP_STR +      DETAIL_HELP_STR +      JSON_STR) +{ +	struct bgp *bgp; +	json_object *json = NULL; + +	bgp = bgp_get_evpn(); +	if (!bgp) +		return CMD_WARNING; + +	/* check if we need json output */ +	if (uj) +		json = json_object_new_object(); + +	evpn_show_routes_vni_all(vty, bgp, BGP_EVPN_MAC_IP_ROUTE, false, addr, +				 json, !!detail); + +	if (uj) +		vty_json(vty, json); + +	return CMD_SUCCESS; +} + +/* + * Display per-VNI EVPN Multicast routing table - for all VNIs. + */ +DEFPY(show_bgp_vni_all_imet, +      show_bgp_vni_all_imet_cmd, +      "show bgp vni all type <3|multicast> [vtep A.B.C.D$addr] [<detail$detail|json$uj>]", +      SHOW_STR +      BGP_STR +      VNI_HELP_STR +      VNI_ALL_HELP_STR +      EVPN_TYPE_HELP_STR +      EVPN_TYPE_3_HELP_STR +      EVPN_TYPE_3_HELP_STR +      VTEP_HELP_STR +      VTEP_IP_HELP_STR +      DETAIL_HELP_STR +      JSON_STR) +{ +	struct bgp *bgp; +	json_object *json = NULL; + +	bgp = bgp_get_evpn(); +	if (!bgp) +		return CMD_WARNING; + +	/* check if we need json output */ +	if (uj) +		json = json_object_new_object(); + +	evpn_show_routes_vni_all(vty, bgp, BGP_EVPN_IMET_ROUTE, false, addr, +				 json, !!detail); + +	if (uj) +		vty_json(vty, json); + +	return CMD_SUCCESS; +} + +/* + * Display per-VNI EVPN ALL routing tables - for select VNI + */ +DEFPY(show_bgp_vni, +      show_bgp_vni_cmd, +      "show bgp vni "CMD_VNI_RANGE"$vni [vtep A.B.C.D$addr] [json$uj]", +      SHOW_STR +      BGP_STR +      VNI_HELP_STR +      VNI_NUM_HELP_STR +      VTEP_HELP_STR +      VTEP_IP_HELP_STR +      JSON_STR) +{ +	struct bgp *bgp; +	json_object *json = NULL; +	json_object *json_mac = NULL; + +	bgp = bgp_get_evpn(); +	if (!bgp) +		return CMD_WARNING; + +	/* check if we need json output */ +	if (uj) { +		json = json_object_new_object(); +		json_mac = json_object_new_object(); +	} + +	evpn_show_routes_vni(vty, bgp, vni, 0, false, addr, json); + +	if (!uj) +		vty_out(vty, "\n\nMAC Table:\n\n"); + +	evpn_show_routes_vni(vty, bgp, vni, 0, true, addr, json_mac); + +	if (uj) { +		json_object_object_add(json, "macTable", json_mac); +		vty_json(vty, json); +	} + +	return CMD_SUCCESS; +} + +/* + * Display per-VNI EVPN EAD routing table - for select VNI + */ +DEFPY(show_bgp_vni_ead, +      show_bgp_vni_ead_cmd, +      "show bgp vni "CMD_VNI_RANGE"$vni type <1|ead> [vtep A.B.C.D$addr] [json$uj]", +      SHOW_STR +      BGP_STR +      VNI_HELP_STR +      VNI_NUM_HELP_STR +      EVPN_TYPE_HELP_STR +      EVPN_TYPE_1_HELP_STR +      EVPN_TYPE_1_HELP_STR +      VTEP_HELP_STR +      VTEP_IP_HELP_STR +      JSON_STR) +{ +	struct bgp *bgp; +	json_object *json = NULL; + +	bgp = bgp_get_evpn(); +	if (!bgp) +		return CMD_WARNING; + +	/* check if we need json output */ +	if (uj) +		json = json_object_new_object(); + +	evpn_show_routes_vni(vty, bgp, vni, BGP_EVPN_AD_ROUTE, false, addr, +			     json); + +	if (uj) +		vty_json(vty, json); + +	return CMD_SUCCESS; +} + +/* + * Display per-VNI EVPN MAC-IP MAC routing table - for select VNI + */ +DEFPY(show_bgp_vni_macip_mac, +      show_bgp_vni_macip_mac_cmd, +      "show bgp vni "CMD_VNI_RANGE"$vni type <2|macip> mac [vtep A.B.C.D$addr] [json$uj]", +      SHOW_STR +      BGP_STR +      VNI_HELP_STR +      VNI_NUM_HELP_STR +      EVPN_TYPE_HELP_STR +      EVPN_TYPE_2_HELP_STR +      EVPN_TYPE_2_HELP_STR +      "MAC Table\n" +      VTEP_HELP_STR +      VTEP_IP_HELP_STR +      JSON_STR) +{ +	struct bgp *bgp; +	json_object *json = NULL; + +	bgp = bgp_get_evpn(); +	if (!bgp) +		return CMD_WARNING; + +	/* check if we need json output */ +	if (uj) +		json = json_object_new_object(); + +	evpn_show_routes_vni(vty, bgp, vni, BGP_EVPN_MAC_IP_ROUTE, true, addr, +			     json); + +	if (uj) +		vty_json(vty, json); + +	return CMD_SUCCESS; +} + +/* + * Display per-VNI EVPN MAC-IP IP routing table - for select VNI + */ +DEFPY(show_bgp_vni_macip_ip, +      show_bgp_vni_macip_ip_cmd, +      "show bgp vni "CMD_VNI_RANGE"$vni type <2|macip> ip [vtep A.B.C.D$addr] [json$uj]", +      SHOW_STR +      BGP_STR +      VNI_HELP_STR +      VNI_NUM_HELP_STR +      EVPN_TYPE_HELP_STR +      EVPN_TYPE_2_HELP_STR +      EVPN_TYPE_2_HELP_STR +      "IP Table\n" +      VTEP_HELP_STR +      VTEP_IP_HELP_STR +      JSON_STR) +{ +	struct bgp *bgp; +	json_object *json = NULL; + +	bgp = bgp_get_evpn(); +	if (!bgp) +		return CMD_WARNING; + +	/* check if we need json output */ +	if (uj) +		json = json_object_new_object(); + +	evpn_show_routes_vni(vty, bgp, vni, BGP_EVPN_MAC_IP_ROUTE, false, addr, +			     json); + +	if (uj) +		vty_json(vty, json); + +	return CMD_SUCCESS; +} + +/* + * Display per-VNI EVPN Multicast routing table - for select VNI + */ +DEFPY(show_bgp_vni_imet, +      show_bgp_vni_imet_cmd, +      "show bgp vni "CMD_VNI_RANGE"$vni type <3|multicast> [vtep A.B.C.D$addr] [json$uj]", +      SHOW_STR +      BGP_STR +      VNI_HELP_STR +      VNI_NUM_HELP_STR +      EVPN_TYPE_HELP_STR +      EVPN_TYPE_3_HELP_STR +      EVPN_TYPE_3_HELP_STR +      VTEP_HELP_STR +      VTEP_IP_HELP_STR +      JSON_STR) +{ +	struct bgp *bgp; +	json_object *json = NULL; + +	bgp = bgp_get_evpn(); +	if (!bgp) +		return CMD_WARNING; + +	/* check if we need json output */ +	if (uj) +		json = json_object_new_object(); + +	evpn_show_routes_vni(vty, bgp, vni, BGP_EVPN_IMET_ROUTE, false, addr, +			     json); + +	if (uj) +		vty_json(vty, json); + +	return CMD_SUCCESS; +} + +/* + * Display per-VNI EVPN MACIP MAC routing table - for select VNI & MAC + */ +DEFPY(show_bgp_vni_macip_mac_addr, +      show_bgp_vni_macip_mac_addr_cmd, +      "show bgp vni "CMD_VNI_RANGE"$vni type <2|macip> mac X:X:X:X:X:X [json$uj]", +      SHOW_STR +      BGP_STR +      VNI_HELP_STR +      VNI_NUM_HELP_STR +      EVPN_TYPE_HELP_STR +      EVPN_TYPE_2_HELP_STR +      EVPN_TYPE_2_HELP_STR +      "MAC Table\n" +      MAC_STR +      JSON_STR) +{ +	struct bgp *bgp; +	json_object *json = NULL; + +	bgp = bgp_get_evpn(); +	if (!bgp) +		return CMD_WARNING; + +	/* check if we need json output */ +	if (uj) +		json = json_object_new_object(); + +	evpn_show_route_vni_macip(vty, bgp, vni, &mac->eth_addr, NULL, json); + +	if (uj) +		vty_json(vty, json); + +	return CMD_SUCCESS; +} + +/* + * Display per-VNI EVPN MACIP IP routing table - for select VNI & IP + */ +DEFPY(show_bgp_vni_macip_ip_addr, show_bgp_vni_macip_ip_addr_cmd, +      "show bgp vni " CMD_VNI_RANGE +      "$vni type <2|macip> ip <A.B.C.D|X:X::X:X> [json$uj]", +      SHOW_STR BGP_STR VNI_HELP_STR VNI_NUM_HELP_STR EVPN_TYPE_HELP_STR +	      EVPN_TYPE_2_HELP_STR EVPN_TYPE_2_HELP_STR +      "IP Table\n" IP_ADDR_STR IP6_ADDR_STR JSON_STR) +{ +	struct bgp *bgp; +	json_object *json = NULL; +	struct ipaddr ip_addr = {.ipa_type = IPADDR_NONE}; + +	bgp = bgp_get_evpn(); +	if (!bgp) +		return CMD_WARNING; + +	/* check if we need json output */ +	if (uj) +		json = json_object_new_object(); + +	if (sockunion_family(ip) == AF_INET) { +		ip_addr.ipa_type = IPADDR_V4; +		ip_addr.ipaddr_v4.s_addr = sockunion2ip(ip); +	} else { +		ip_addr.ipa_type = IPADDR_V6; +		memcpy(&ip_addr.ipaddr_v6, &ip->sin6.sin6_addr, +		       sizeof(struct in6_addr)); +	} +	evpn_show_route_vni_macip(vty, bgp, vni, NULL, &ip_addr, json);  	if (uj)  		vty_json(vty, json); @@ -6755,6 +7375,20 @@ void bgp_ethernetvpn_init(void)  	install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_import_rt_cmd);  	install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_vrf_import_rt_cmd); +	/* "show bgp vni" commands. */ +	install_element(VIEW_NODE, &show_bgp_vni_all_cmd); +	install_element(VIEW_NODE, &show_bgp_vni_all_ead_cmd); +	install_element(VIEW_NODE, &show_bgp_vni_all_macip_mac_cmd); +	install_element(VIEW_NODE, &show_bgp_vni_all_macip_ip_cmd); +	install_element(VIEW_NODE, &show_bgp_vni_all_imet_cmd); +	install_element(VIEW_NODE, &show_bgp_vni_cmd); +	install_element(VIEW_NODE, &show_bgp_vni_ead_cmd); +	install_element(VIEW_NODE, &show_bgp_vni_macip_mac_cmd); +	install_element(VIEW_NODE, &show_bgp_vni_macip_ip_cmd); +	install_element(VIEW_NODE, &show_bgp_vni_imet_cmd); +	install_element(VIEW_NODE, &show_bgp_vni_macip_mac_addr_cmd); +	install_element(VIEW_NODE, &show_bgp_vni_macip_ip_addr_cmd); +  	/* "show bgp evpn" commands. */  	install_element(VIEW_NODE, &show_bgp_evpn_vni_cmd);  	install_element(VIEW_NODE, &show_bgp_evpn_summary_cmd);  | 
