1 /* Zebra VTY functions
2  * Copyright (C) 2002 Kunihiro Ishiguro
3  *
4  * This file is part of GNU Zebra.
5  *
6  * GNU Zebra is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License as published by the
8  * Free Software Foundation; either version 2, or (at your option) any
9  * later version.
10  *
11  * GNU Zebra is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with this program; see the file COPYING; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 #include <zebra.h>
22 
23 #include "memory.h"
24 #include "zebra_memory.h"
25 #include "if.h"
26 #include "prefix.h"
27 #include "command.h"
28 #include "table.h"
29 #include "rib.h"
30 #include "nexthop.h"
31 #include "vrf.h"
32 #include "linklist.h"
33 #include "mpls.h"
34 #include "routemap.h"
35 #include "srcdest_table.h"
36 #include "vxlan.h"
37 
38 #include "zebra/zebra_router.h"
39 #include "zebra/zserv.h"
40 #include "zebra/zebra_vrf.h"
41 #include "zebra/zebra_mpls.h"
42 #include "zebra/zebra_rnh.h"
43 #include "zebra/redistribute.h"
44 #include "zebra/zebra_routemap.h"
45 #include "lib/json.h"
46 #include "zebra/zebra_vxlan.h"
47 #include "zebra/zebra_evpn_mh.h"
48 #ifndef VTYSH_EXTRACT_PL
49 #include "zebra/zebra_vty_clippy.c"
50 #endif
51 #include "zebra/zserv.h"
52 #include "zebra/router-id.h"
53 #include "zebra/ipforward.h"
54 #include "zebra/zebra_vxlan_private.h"
55 #include "zebra/zebra_pbr.h"
56 #include "zebra/zebra_nhg.h"
57 #include "zebra/interface.h"
58 #include "northbound_cli.h"
59 #include "zebra/zebra_nb.h"
60 #include "zebra/kernel_netlink.h"
61 
62 extern int allow_delete;
63 
64 /* context to manage dumps in multiple tables or vrfs */
65 struct route_show_ctx {
66 	bool multi;       /* dump multiple tables or vrf */
67 	bool header_done; /* common header already displayed */
68 };
69 
70 static int do_show_ip_route(struct vty *vty, const char *vrf_name, afi_t afi,
71 			    safi_t safi, bool use_fib, bool use_json,
72 			    route_tag_t tag,
73 			    const struct prefix *longer_prefix_p,
74 			    bool supernets_only, int type,
75 			    unsigned short ospf_instance_id, uint32_t tableid,
76 			    struct route_show_ctx *ctx);
77 static void vty_show_ip_route_detail(struct vty *vty, struct route_node *rn,
78 				     int mcast, bool use_fib, bool show_ng);
79 static void vty_show_ip_route_summary(struct vty *vty,
80 				      struct route_table *table, bool use_json);
81 static void vty_show_ip_route_summary_prefix(struct vty *vty,
82 					     struct route_table *table,
83 					     bool use_json);
84 /* Helper api to format a nexthop in the 'detailed' output path. */
85 static void show_nexthop_detail_helper(struct vty *vty,
86 				       const struct route_entry *re,
87 				       const struct nexthop *nexthop,
88 				       bool is_backup);
89 
90 
91 DEFUN (ip_multicast_mode,
92        ip_multicast_mode_cmd,
93        "ip multicast rpf-lookup-mode <urib-only|mrib-only|mrib-then-urib|lower-distance|longer-prefix>",
94        IP_STR
95        "Multicast options\n"
96        "RPF lookup behavior\n"
97        "Lookup in unicast RIB only\n"
98        "Lookup in multicast RIB only\n"
99        "Try multicast RIB first, fall back to unicast RIB\n"
100        "Lookup both, use entry with lower distance\n"
101        "Lookup both, use entry with longer prefix\n")
102 {
103 	char *mode = argv[3]->text;
104 
105 	if (strmatch(mode, "urib-only"))
106 		multicast_mode_ipv4_set(MCAST_URIB_ONLY);
107 	else if (strmatch(mode, "mrib-only"))
108 		multicast_mode_ipv4_set(MCAST_MRIB_ONLY);
109 	else if (strmatch(mode, "mrib-then-urib"))
110 		multicast_mode_ipv4_set(MCAST_MIX_MRIB_FIRST);
111 	else if (strmatch(mode, "lower-distance"))
112 		multicast_mode_ipv4_set(MCAST_MIX_DISTANCE);
113 	else if (strmatch(mode, "longer-prefix"))
114 		multicast_mode_ipv4_set(MCAST_MIX_PFXLEN);
115 	else {
116 		vty_out(vty, "Invalid mode specified\n");
117 		return CMD_WARNING_CONFIG_FAILED;
118 	}
119 
120 	return CMD_SUCCESS;
121 }
122 
123 DEFUN (no_ip_multicast_mode,
124        no_ip_multicast_mode_cmd,
125        "no ip multicast rpf-lookup-mode [<urib-only|mrib-only|mrib-then-urib|lower-distance|longer-prefix>]",
126        NO_STR
127        IP_STR
128        "Multicast options\n"
129        "RPF lookup behavior\n"
130        "Lookup in unicast RIB only\n"
131        "Lookup in multicast RIB only\n"
132        "Try multicast RIB first, fall back to unicast RIB\n"
133        "Lookup both, use entry with lower distance\n"
134        "Lookup both, use entry with longer prefix\n")
135 {
136 	multicast_mode_ipv4_set(MCAST_NO_CONFIG);
137 	return CMD_SUCCESS;
138 }
139 
140 
141 DEFUN (show_ip_rpf,
142        show_ip_rpf_cmd,
143        "show ip rpf [json]",
144        SHOW_STR
145        IP_STR
146        "Display RPF information for multicast source\n"
147        JSON_STR)
148 {
149 	bool uj = use_json(argc, argv);
150 	struct route_show_ctx ctx = {
151 		.multi = false,
152 	};
153 
154 	return do_show_ip_route(vty, VRF_DEFAULT_NAME, AFI_IP, SAFI_MULTICAST,
155 				false, uj, 0, NULL, false, 0, 0, 0, &ctx);
156 }
157 
158 DEFUN (show_ip_rpf_addr,
159        show_ip_rpf_addr_cmd,
160        "show ip rpf A.B.C.D",
161        SHOW_STR
162        IP_STR
163        "Display RPF information for multicast source\n"
164        "IP multicast source address (e.g. 10.0.0.0)\n")
165 {
166 	int idx_ipv4 = 3;
167 	struct in_addr addr;
168 	struct route_node *rn;
169 	struct route_entry *re;
170 	int ret;
171 
172 	ret = inet_aton(argv[idx_ipv4]->arg, &addr);
173 	if (ret == 0) {
174 		vty_out(vty, "%% Malformed address\n");
175 		return CMD_WARNING;
176 	}
177 
178 	re = rib_match_ipv4_multicast(VRF_DEFAULT, addr, &rn);
179 
180 	if (re)
181 		vty_show_ip_route_detail(vty, rn, 1, false, false);
182 	else
183 		vty_out(vty, "%% No match for RPF lookup\n");
184 
185 	return CMD_SUCCESS;
186 }
187 
re_status_output_char(const struct route_entry * re,const struct nexthop * nhop,bool is_fib)188 static char re_status_output_char(const struct route_entry *re,
189 				  const struct nexthop *nhop,
190 				  bool is_fib)
191 {
192 	if (CHECK_FLAG(re->status, ROUTE_ENTRY_INSTALLED)) {
193 		bool star_p = false;
194 
195 		if (nhop &&
196 		    !CHECK_FLAG(nhop->flags, NEXTHOP_FLAG_DUPLICATE) &&
197 		    !CHECK_FLAG(nhop->flags, NEXTHOP_FLAG_RECURSIVE)) {
198 			/* More-specific test for 'fib' output */
199 			if (is_fib) {
200 				star_p = !!CHECK_FLAG(nhop->flags,
201 						      NEXTHOP_FLAG_FIB);
202 			} else
203 				star_p = true;
204 		}
205 
206 		if (star_p)
207 			return '*';
208 		else
209 			return ' ';
210 	}
211 
212 	if (CHECK_FLAG(re->status, ROUTE_ENTRY_FAILED)) {
213 		if (CHECK_FLAG(re->status, ROUTE_ENTRY_QUEUED))
214 			return 'q';
215 
216 		return 'r';
217 	}
218 
219 	if (CHECK_FLAG(re->status, ROUTE_ENTRY_QUEUED))
220 		return 'q';
221 
222 	return ' ';
223 }
224 
225 /*
226  * Show backup nexthop info, in the 'detailed' output path
227  */
show_nh_backup_helper(struct vty * vty,const struct route_entry * re,const struct nexthop * nexthop)228 static void show_nh_backup_helper(struct vty *vty,
229 				  const struct route_entry *re,
230 				  const struct nexthop *nexthop)
231 {
232 	const struct nexthop *start, *backup, *temp;
233 	int i, idx;
234 
235 	/* Double-check that there _is_ a backup */
236 	if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP) ||
237 	    re->nhe->backup_info == NULL || re->nhe->backup_info->nhe == NULL ||
238 	    re->nhe->backup_info->nhe->nhg.nexthop == NULL)
239 		return;
240 
241 	/* Locate the backup nexthop(s) */
242 	start = re->nhe->backup_info->nhe->nhg.nexthop;
243 	for (i = 0; i < nexthop->backup_num; i++) {
244 		/* Format the backup(s) (indented) */
245 		backup = start;
246 		for (idx = 0; idx < nexthop->backup_idx[i]; idx++) {
247 			backup = backup->next;
248 			if (backup == NULL)
249 				break;
250 		}
251 
252 		/* It's possible for backups to be recursive too,
253 		 * so walk the recursive resolution list if present.
254 		 */
255 		temp = backup;
256 		while (backup) {
257 			vty_out(vty, "  ");
258 			show_nexthop_detail_helper(vty, re, backup,
259 						   true /*backup*/);
260 			vty_out(vty, "\n");
261 
262 			if (backup->resolved && temp == backup)
263 				backup = backup->resolved;
264 			else
265 				backup = nexthop_next(backup);
266 
267 			if (backup == temp->next)
268 				break;
269 		}
270 	}
271 
272 }
273 
274 /*
275  * Helper api to format output for a nexthop, used in the 'detailed'
276  * output path.
277  */
show_nexthop_detail_helper(struct vty * vty,const struct route_entry * re,const struct nexthop * nexthop,bool is_backup)278 static void show_nexthop_detail_helper(struct vty *vty,
279 				       const struct route_entry *re,
280 				       const struct nexthop *nexthop,
281 				       bool is_backup)
282 {
283 	char addrstr[32];
284 	char buf[MPLS_LABEL_STRLEN];
285 	int i;
286 
287 	if (is_backup)
288 		vty_out(vty, "    b%s",
289 			nexthop->rparent ? "  " : "");
290 	else
291 		vty_out(vty, "  %c%s",
292 			re_status_output_char(re, nexthop, false),
293 			nexthop->rparent ? "  " : "");
294 
295 	switch (nexthop->type) {
296 	case NEXTHOP_TYPE_IPV4:
297 	case NEXTHOP_TYPE_IPV4_IFINDEX:
298 		vty_out(vty, " %s",
299 			inet_ntoa(nexthop->gate.ipv4));
300 		if (nexthop->ifindex)
301 			vty_out(vty, ", via %s",
302 				ifindex2ifname(
303 					nexthop->ifindex,
304 					nexthop->vrf_id));
305 		break;
306 	case NEXTHOP_TYPE_IPV6:
307 	case NEXTHOP_TYPE_IPV6_IFINDEX:
308 		vty_out(vty, " %s",
309 			inet_ntop(AF_INET6, &nexthop->gate.ipv6,
310 				  buf, sizeof(buf)));
311 		if (nexthop->ifindex)
312 			vty_out(vty, ", via %s",
313 				ifindex2ifname(
314 					nexthop->ifindex,
315 					nexthop->vrf_id));
316 		break;
317 
318 	case NEXTHOP_TYPE_IFINDEX:
319 		vty_out(vty, " directly connected, %s",
320 			ifindex2ifname(nexthop->ifindex,
321 				       nexthop->vrf_id));
322 		break;
323 	case NEXTHOP_TYPE_BLACKHOLE:
324 		vty_out(vty, " unreachable");
325 		switch (nexthop->bh_type) {
326 		case BLACKHOLE_REJECT:
327 			vty_out(vty, " (ICMP unreachable)");
328 			break;
329 		case BLACKHOLE_ADMINPROHIB:
330 			vty_out(vty,
331 				" (ICMP admin-prohibited)");
332 			break;
333 		case BLACKHOLE_NULL:
334 			vty_out(vty, " (blackhole)");
335 			break;
336 		case BLACKHOLE_UNSPEC:
337 			break;
338 		}
339 		break;
340 	default:
341 		break;
342 	}
343 
344 	if ((re->vrf_id != nexthop->vrf_id)
345 	    && (nexthop->type != NEXTHOP_TYPE_BLACKHOLE))
346 		vty_out(vty, "(vrf %s)", vrf_id_to_name(nexthop->vrf_id));
347 
348 	if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_DUPLICATE))
349 		vty_out(vty, " (duplicate nexthop removed)");
350 
351 	if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
352 		vty_out(vty, " inactive");
353 
354 	if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK))
355 		vty_out(vty, " onlink");
356 
357 	if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
358 		vty_out(vty, " (recursive)");
359 
360 	/* Source specified? */
361 	switch (nexthop->type) {
362 	case NEXTHOP_TYPE_IPV4:
363 	case NEXTHOP_TYPE_IPV4_IFINDEX:
364 		if (nexthop->src.ipv4.s_addr) {
365 			if (inet_ntop(AF_INET, &nexthop->src.ipv4,
366 				      addrstr, sizeof(addrstr)))
367 				vty_out(vty, ", src %s",
368 					addrstr);
369 		}
370 		break;
371 
372 	case NEXTHOP_TYPE_IPV6:
373 	case NEXTHOP_TYPE_IPV6_IFINDEX:
374 		if (!IPV6_ADDR_SAME(&nexthop->src.ipv6,
375 				    &in6addr_any)) {
376 			if (inet_ntop(AF_INET6, &nexthop->src.ipv6,
377 				      addrstr, sizeof(addrstr)))
378 				vty_out(vty, ", src %s",
379 					addrstr);
380 		}
381 		break;
382 
383 	default:
384 		break;
385 	}
386 
387 	if (re->nexthop_mtu)
388 		vty_out(vty, ", mtu %u", re->nexthop_mtu);
389 
390 	/* Label information */
391 	if (nexthop->nh_label && nexthop->nh_label->num_labels) {
392 		vty_out(vty, ", label %s",
393 			mpls_label2str(nexthop->nh_label->num_labels,
394 				       nexthop->nh_label->label, buf,
395 				       sizeof(buf), 1 /*pretty*/));
396 	}
397 
398 	if (nexthop->weight)
399 		vty_out(vty, ", weight %u", nexthop->weight);
400 
401 	if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP)) {
402 		vty_out(vty, ", backup %d", nexthop->backup_idx[0]);
403 
404 		for (i = 1; i < nexthop->backup_num; i++)
405 			vty_out(vty, ",%d", nexthop->backup_idx[i]);
406 	}
407 }
408 
409 /* New RIB.  Detailed information for IPv4 route. */
vty_show_ip_route_detail(struct vty * vty,struct route_node * rn,int mcast,bool use_fib,bool show_ng)410 static void vty_show_ip_route_detail(struct vty *vty, struct route_node *rn,
411 				     int mcast, bool use_fib, bool show_ng)
412 {
413 	struct route_entry *re;
414 	struct nexthop *nexthop;
415 	char buf[SRCDEST2STR_BUFFER];
416 	struct zebra_vrf *zvrf;
417 	rib_dest_t *dest;
418 
419 	dest = rib_dest_from_rnode(rn);
420 
421 	RNODE_FOREACH_RE (rn, re) {
422 		/*
423 		 * If re not selected for forwarding, skip re
424 		 * for "show ip/ipv6 fib <prefix>"
425 		 */
426 		if (use_fib && re != dest->selected_fib)
427 			continue;
428 
429 		const char *mcast_info = "";
430 		if (mcast) {
431 			struct rib_table_info *info =
432 				srcdest_rnode_table_info(rn);
433 			mcast_info = (info->safi == SAFI_MULTICAST)
434 					     ? " using Multicast RIB"
435 					     : " using Unicast RIB";
436 		}
437 
438 		vty_out(vty, "Routing entry for %s%s\n",
439 			srcdest_rnode2str(rn, buf, sizeof(buf)), mcast_info);
440 		vty_out(vty, "  Known via \"%s", zebra_route_string(re->type));
441 		if (re->instance)
442 			vty_out(vty, "[%d]", re->instance);
443 		vty_out(vty, "\"");
444 		vty_out(vty, ", distance %u, metric %u", re->distance,
445 			re->metric);
446 		if (re->tag) {
447 			vty_out(vty, ", tag %u", re->tag);
448 #if defined(SUPPORT_REALMS)
449 			if (re->tag > 0 && re->tag <= 255)
450 				vty_out(vty, "(realm)");
451 #endif
452 		}
453 		if (re->mtu)
454 			vty_out(vty, ", mtu %u", re->mtu);
455 		if (re->vrf_id != VRF_DEFAULT) {
456 			zvrf = vrf_info_lookup(re->vrf_id);
457 			vty_out(vty, ", vrf %s", zvrf_name(zvrf));
458 		}
459 		if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED))
460 			vty_out(vty, ", best");
461 		vty_out(vty, "\n");
462 
463 		time_t uptime;
464 
465 		uptime = monotime(NULL);
466 		uptime -= re->uptime;
467 
468 		frrtime_to_interval(uptime, buf, sizeof(buf));
469 
470 		vty_out(vty, "  Last update %s ago\n", buf);
471 
472 		if (show_ng)
473 			vty_out(vty, "  Nexthop Group ID: %u\n", re->nhe_id);
474 
475 		for (ALL_NEXTHOPS(re->nhe->nhg, nexthop)) {
476 			/* Use helper to format each nexthop */
477 			show_nexthop_detail_helper(vty, re, nexthop,
478 						   false /*not backup*/);
479 			vty_out(vty, "\n");
480 
481 			/* Include backup(s), if present */
482 			if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP))
483 				show_nh_backup_helper(vty, re, nexthop);
484 		}
485 		vty_out(vty, "\n");
486 	}
487 }
488 
489 /*
490  * Helper for nexthop output, used in the 'show ip route' path
491  */
show_route_nexthop_helper(struct vty * vty,const struct route_entry * re,const struct nexthop * nexthop)492 static void show_route_nexthop_helper(struct vty *vty,
493 				      const struct route_entry *re,
494 				      const struct nexthop *nexthop)
495 {
496 	char buf[MPLS_LABEL_STRLEN];
497 	int i;
498 
499 	switch (nexthop->type) {
500 	case NEXTHOP_TYPE_IPV4:
501 	case NEXTHOP_TYPE_IPV4_IFINDEX:
502 		vty_out(vty, " via %s", inet_ntoa(nexthop->gate.ipv4));
503 		if (nexthop->ifindex)
504 			vty_out(vty, ", %s",
505 				ifindex2ifname(nexthop->ifindex,
506 					       nexthop->vrf_id));
507 		break;
508 	case NEXTHOP_TYPE_IPV6:
509 	case NEXTHOP_TYPE_IPV6_IFINDEX:
510 		vty_out(vty, " via %s",
511 			inet_ntop(AF_INET6, &nexthop->gate.ipv6, buf,
512 				  sizeof(buf)));
513 		if (nexthop->ifindex)
514 			vty_out(vty, ", %s",
515 				ifindex2ifname(nexthop->ifindex,
516 					       nexthop->vrf_id));
517 		break;
518 
519 	case NEXTHOP_TYPE_IFINDEX:
520 		vty_out(vty, " is directly connected, %s",
521 			ifindex2ifname(nexthop->ifindex,
522 				       nexthop->vrf_id));
523 		break;
524 	case NEXTHOP_TYPE_BLACKHOLE:
525 		vty_out(vty, " unreachable");
526 		switch (nexthop->bh_type) {
527 		case BLACKHOLE_REJECT:
528 			vty_out(vty, " (ICMP unreachable)");
529 			break;
530 		case BLACKHOLE_ADMINPROHIB:
531 			vty_out(vty, " (ICMP admin-prohibited)");
532 			break;
533 		case BLACKHOLE_NULL:
534 			vty_out(vty, " (blackhole)");
535 			break;
536 		case BLACKHOLE_UNSPEC:
537 			break;
538 		}
539 		break;
540 	default:
541 		break;
542 	}
543 
544 	if ((re == NULL || (nexthop->vrf_id != re->vrf_id))
545 	    && (nexthop->type != NEXTHOP_TYPE_BLACKHOLE))
546 		vty_out(vty, " (vrf %s)", vrf_id_to_name(nexthop->vrf_id));
547 
548 	if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
549 		vty_out(vty, " inactive");
550 
551 	if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK))
552 		vty_out(vty, " onlink");
553 
554 	if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
555 		vty_out(vty, " (recursive)");
556 
557 	switch (nexthop->type) {
558 	case NEXTHOP_TYPE_IPV4:
559 	case NEXTHOP_TYPE_IPV4_IFINDEX:
560 		if (nexthop->src.ipv4.s_addr) {
561 			if (inet_ntop(AF_INET, &nexthop->src.ipv4, buf,
562 				      sizeof(buf)))
563 				vty_out(vty, ", src %s", buf);
564 			/* SR-TE information */
565 			if (nexthop->srte_color)
566 				vty_out(vty, ", SR-TE color %u",
567 					nexthop->srte_color);
568 		}
569 		break;
570 	case NEXTHOP_TYPE_IPV6:
571 	case NEXTHOP_TYPE_IPV6_IFINDEX:
572 		if (!IPV6_ADDR_SAME(&nexthop->src.ipv6, &in6addr_any)) {
573 			if (inet_ntop(AF_INET6, &nexthop->src.ipv6, buf,
574 				      sizeof(buf)))
575 				vty_out(vty, ", src %s", buf);
576 		}
577 		break;
578 	default:
579 		break;
580 	}
581 
582 	/* Label information */
583 	if (nexthop->nh_label && nexthop->nh_label->num_labels) {
584 		vty_out(vty, ", label %s",
585 			mpls_label2str(nexthop->nh_label->num_labels,
586 				       nexthop->nh_label->label, buf,
587 				       sizeof(buf), 1));
588 	}
589 
590 	if (nexthop->weight)
591 		vty_out(vty, ", weight %u", nexthop->weight);
592 
593 	if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP)) {
594 		vty_out(vty, ", backup %d", nexthop->backup_idx[0]);
595 
596 		for (i = 1; i < nexthop->backup_num; i++)
597 			vty_out(vty, ",%d", nexthop->backup_idx[i]);
598 	}
599 }
600 
601 /*
602  * Render a nexthop into a json object; the caller allocates and owns
603  * the json object memory.
604  */
show_nexthop_json_helper(json_object * json_nexthop,const struct nexthop * nexthop,const struct route_entry * re)605 static void show_nexthop_json_helper(json_object *json_nexthop,
606 				     const struct nexthop *nexthop,
607 				     const struct route_entry *re)
608 {
609 	char buf[SRCDEST2STR_BUFFER];
610 	json_object *json_labels = NULL;
611 	json_object *json_backups = NULL;
612 	int i;
613 
614 	json_object_int_add(json_nexthop, "flags",
615 			    nexthop->flags);
616 
617 	if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_DUPLICATE))
618 		json_object_boolean_true_add(json_nexthop,
619 					     "duplicate");
620 
621 	if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB))
622 		json_object_boolean_true_add(json_nexthop,
623 					     "fib");
624 
625 	switch (nexthop->type) {
626 	case NEXTHOP_TYPE_IPV4:
627 	case NEXTHOP_TYPE_IPV4_IFINDEX:
628 		json_object_string_add(
629 			json_nexthop, "ip",
630 			inet_ntoa(nexthop->gate.ipv4));
631 		json_object_string_add(json_nexthop, "afi",
632 				       "ipv4");
633 
634 		if (nexthop->ifindex) {
635 			json_object_int_add(json_nexthop,
636 					    "interfaceIndex",
637 					    nexthop->ifindex);
638 			json_object_string_add(
639 				json_nexthop, "interfaceName",
640 				ifindex2ifname(
641 					nexthop->ifindex,
642 					nexthop->vrf_id));
643 		}
644 		break;
645 	case NEXTHOP_TYPE_IPV6:
646 	case NEXTHOP_TYPE_IPV6_IFINDEX:
647 		json_object_string_add(
648 			json_nexthop, "ip",
649 			inet_ntop(AF_INET6, &nexthop->gate.ipv6,
650 				  buf, sizeof(buf)));
651 		json_object_string_add(json_nexthop, "afi",
652 				       "ipv6");
653 
654 		if (nexthop->ifindex) {
655 			json_object_int_add(json_nexthop,
656 					    "interfaceIndex",
657 					    nexthop->ifindex);
658 			json_object_string_add(
659 				json_nexthop, "interfaceName",
660 				ifindex2ifname(
661 					nexthop->ifindex,
662 					nexthop->vrf_id));
663 		}
664 		break;
665 
666 	case NEXTHOP_TYPE_IFINDEX:
667 		json_object_boolean_true_add(
668 			json_nexthop, "directlyConnected");
669 		json_object_int_add(json_nexthop,
670 				    "interfaceIndex",
671 				    nexthop->ifindex);
672 		json_object_string_add(
673 			json_nexthop, "interfaceName",
674 			ifindex2ifname(nexthop->ifindex,
675 				       nexthop->vrf_id));
676 		break;
677 	case NEXTHOP_TYPE_BLACKHOLE:
678 		json_object_boolean_true_add(json_nexthop,
679 					     "unreachable");
680 		switch (nexthop->bh_type) {
681 		case BLACKHOLE_REJECT:
682 			json_object_boolean_true_add(
683 				json_nexthop, "reject");
684 			break;
685 		case BLACKHOLE_ADMINPROHIB:
686 			json_object_boolean_true_add(
687 				json_nexthop,
688 				"admin-prohibited");
689 			break;
690 		case BLACKHOLE_NULL:
691 			json_object_boolean_true_add(
692 				json_nexthop, "blackhole");
693 			break;
694 		case BLACKHOLE_UNSPEC:
695 			break;
696 		}
697 		break;
698 	default:
699 		break;
700 	}
701 
702 	if ((nexthop->vrf_id != re->vrf_id)
703 	    && (nexthop->type != NEXTHOP_TYPE_BLACKHOLE))
704 		json_object_string_add(json_nexthop, "vrf",
705 				       vrf_id_to_name(nexthop->vrf_id));
706 
707 	if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_DUPLICATE))
708 		json_object_boolean_true_add(json_nexthop,
709 					     "duplicate");
710 
711 	if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
712 		json_object_boolean_true_add(json_nexthop,
713 					     "active");
714 
715 	if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK))
716 		json_object_boolean_true_add(json_nexthop,
717 					     "onLink");
718 
719 	if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
720 		json_object_boolean_true_add(json_nexthop,
721 					     "recursive");
722 
723 	if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP)) {
724 		json_backups = json_object_new_array();
725 		for (i = 0; i < nexthop->backup_num; i++) {
726 			json_object_array_add(
727 				json_backups,
728 				json_object_new_int(nexthop->backup_idx[i]));
729 		}
730 
731 		json_object_object_add(json_nexthop, "backupIndex",
732 				       json_backups);
733 	}
734 
735 	switch (nexthop->type) {
736 	case NEXTHOP_TYPE_IPV4:
737 	case NEXTHOP_TYPE_IPV4_IFINDEX:
738 		if (nexthop->src.ipv4.s_addr) {
739 			if (inet_ntop(AF_INET,
740 				      &nexthop->src.ipv4, buf,
741 				      sizeof(buf)))
742 				json_object_string_add(
743 					json_nexthop, "source",
744 					buf);
745 		}
746 		break;
747 	case NEXTHOP_TYPE_IPV6:
748 	case NEXTHOP_TYPE_IPV6_IFINDEX:
749 		if (!IPV6_ADDR_SAME(&nexthop->src.ipv6,
750 				    &in6addr_any)) {
751 			if (inet_ntop(AF_INET6,
752 				      &nexthop->src.ipv6, buf,
753 				      sizeof(buf)))
754 				json_object_string_add(
755 					json_nexthop, "source",
756 					buf);
757 		}
758 		break;
759 	default:
760 		break;
761 	}
762 
763 	if (nexthop->nh_label
764 	    && nexthop->nh_label->num_labels) {
765 		json_labels = json_object_new_array();
766 
767 		for (int label_index = 0;
768 		     label_index
769 			     < nexthop->nh_label->num_labels;
770 		     label_index++)
771 			json_object_array_add(
772 				json_labels,
773 				json_object_new_int(
774 					nexthop->nh_label->label
775 					[label_index]));
776 
777 		json_object_object_add(json_nexthop, "labels",
778 				       json_labels);
779 	}
780 
781 	if (nexthop->weight)
782 		json_object_int_add(json_nexthop, "weight",
783 				    nexthop->weight);
784 
785 	if (nexthop->srte_color)
786 		json_object_int_add(json_nexthop, "srteColor",
787 				    nexthop->srte_color);
788 }
789 
vty_show_ip_route(struct vty * vty,struct route_node * rn,struct route_entry * re,json_object * json,bool is_fib)790 static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
791 			      struct route_entry *re, json_object *json,
792 			      bool is_fib)
793 {
794 	const struct nexthop *nexthop;
795 	int len = 0;
796 	char buf[SRCDEST2STR_BUFFER];
797 	json_object *json_nexthops = NULL;
798 	json_object *json_nexthop = NULL;
799 	json_object *json_route = NULL;
800 	time_t uptime;
801 	const rib_dest_t *dest = rib_dest_from_rnode(rn);
802 	const struct nexthop_group *nhg;
803 	char up_str[MONOTIME_STRLEN];
804 	bool first_p = true;
805 	bool nhg_from_backup = false;
806 
807 	uptime = monotime(NULL);
808 	uptime -= re->uptime;
809 
810 	frrtime_to_interval(uptime, up_str, sizeof(up_str));
811 
812 	/* If showing fib information, use the fib view of the
813 	 * nexthops.
814 	 */
815 	if (is_fib)
816 		nhg = rib_get_fib_nhg(re);
817 	else
818 		nhg = &(re->nhe->nhg);
819 
820 	if (json) {
821 		json_route = json_object_new_object();
822 		json_nexthops = json_object_new_array();
823 
824 		json_object_string_add(json_route, "prefix",
825 				       srcdest_rnode2str(rn, buf, sizeof(buf)));
826 		json_object_string_add(json_route, "protocol",
827 				       zebra_route_string(re->type));
828 
829 		if (re->instance)
830 			json_object_int_add(json_route, "instance",
831 					    re->instance);
832 
833 		json_object_int_add(json_route, "vrfId", re->vrf_id);
834 		json_object_string_add(json_route, "vrfName",
835 				       vrf_id_to_name(re->vrf_id));
836 
837 		if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED))
838 			json_object_boolean_true_add(json_route, "selected");
839 
840 		if (dest->selected_fib == re)
841 			json_object_boolean_true_add(json_route,
842 						     "destSelected");
843 
844 		json_object_int_add(json_route, "distance",
845 				    re->distance);
846 		json_object_int_add(json_route, "metric", re->metric);
847 
848 		if (CHECK_FLAG(re->status, ROUTE_ENTRY_INSTALLED))
849 			json_object_boolean_true_add(json_route, "installed");
850 
851 		if (CHECK_FLAG(re->status, ROUTE_ENTRY_FAILED))
852 			json_object_boolean_true_add(json_route, "failed");
853 
854 		if (CHECK_FLAG(re->status, ROUTE_ENTRY_QUEUED))
855 			json_object_boolean_true_add(json_route, "queued");
856 
857 		if (re->tag)
858 			json_object_int_add(json_route, "tag", re->tag);
859 
860 		if (re->table)
861 			json_object_int_add(json_route, "table", re->table);
862 
863 		json_object_int_add(json_route, "internalStatus",
864 				    re->status);
865 		json_object_int_add(json_route, "internalFlags",
866 				    re->flags);
867 		json_object_int_add(json_route, "internalNextHopNum",
868 				    nexthop_group_nexthop_num(&(re->nhe->nhg)));
869 		json_object_int_add(json_route, "internalNextHopActiveNum",
870 				    nexthop_group_active_nexthop_num(
871 					    &(re->nhe->nhg)));
872 
873 		json_object_string_add(json_route, "uptime", up_str);
874 
875 		for (ALL_NEXTHOPS_PTR(nhg, nexthop)) {
876 			json_nexthop = json_object_new_object();
877 			show_nexthop_json_helper(json_nexthop,
878 						 nexthop, re);
879 
880 			json_object_array_add(json_nexthops,
881 					      json_nexthop);
882 		}
883 
884 		json_object_object_add(json_route, "nexthops", json_nexthops);
885 
886 		/* If there are backup nexthops, include them */
887 		if (is_fib)
888 			nhg = rib_get_fib_backup_nhg(re);
889 		else
890 			nhg = zebra_nhg_get_backup_nhg(re->nhe);
891 
892 		if (nhg && nhg->nexthop) {
893 			json_nexthops = json_object_new_array();
894 
895 			for (ALL_NEXTHOPS_PTR(nhg, nexthop)) {
896 				json_nexthop = json_object_new_object();
897 
898 				show_nexthop_json_helper(json_nexthop,
899 							 nexthop, re);
900 				json_object_array_add(json_nexthops,
901 						      json_nexthop);
902 			}
903 
904 			json_object_object_add(json_route, "backupNexthops",
905 					       json_nexthops);
906 		}
907 
908 		json_object_array_add(json, json_route);
909 		return;
910 	}
911 
912 	/* Prefix information, and first nexthop. If we're showing 'fib',
913 	 * and there are no installed primary nexthops, see if there are any
914 	 * backup nexthops and start with those.
915 	 */
916 	if (is_fib && nhg->nexthop == NULL) {
917 		nhg = rib_get_fib_backup_nhg(re);
918 		nhg_from_backup = true;
919 	}
920 
921 	len = vty_out(vty, "%c", zebra_route_char(re->type));
922 	if (re->instance)
923 		len += vty_out(vty, "[%d]", re->instance);
924 	if (nhg_from_backup && nhg->nexthop) {
925 		len += vty_out(
926 			vty, "%cb%c %s",
927 			CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED) ? '>' : ' ',
928 			re_status_output_char(re, nhg->nexthop, is_fib),
929 			srcdest_rnode2str(rn, buf, sizeof(buf)));
930 	} else {
931 		len += vty_out(
932 			vty, "%c%c %s",
933 			CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED) ? '>' : ' ',
934 			re_status_output_char(re, nhg->nexthop, is_fib),
935 			srcdest_rnode2str(rn, buf, sizeof(buf)));
936 	}
937 
938 	/* Distance and metric display. */
939 	if (((re->type == ZEBRA_ROUTE_CONNECT) &&
940 	     (re->distance || re->metric)) ||
941 	    (re->type != ZEBRA_ROUTE_CONNECT))
942 		len += vty_out(vty, " [%u/%u]", re->distance,
943 			       re->metric);
944 
945 	/* Nexthop information. */
946 	for (ALL_NEXTHOPS_PTR(nhg, nexthop)) {
947 		if (first_p) {
948 			first_p = false;
949 		} else if (nhg_from_backup) {
950 			vty_out(vty, "  b%c%*c",
951 				re_status_output_char(re, nexthop, is_fib),
952 				len - 3 + (2 * nexthop_level(nexthop)), ' ');
953 		} else {
954 			vty_out(vty, "  %c%*c",
955 				re_status_output_char(re, nexthop, is_fib),
956 				len - 3 + (2 * nexthop_level(nexthop)), ' ');
957 		}
958 
959 		show_route_nexthop_helper(vty, re, nexthop);
960 		vty_out(vty, ", %s\n", up_str);
961 	}
962 
963 	/* If we only had backup nexthops, we're done */
964 	if (nhg_from_backup)
965 		return;
966 
967 	/* Check for backup nexthop info if present */
968 	if (is_fib)
969 		nhg = rib_get_fib_backup_nhg(re);
970 	else
971 		nhg = zebra_nhg_get_backup_nhg(re->nhe);
972 
973 	if (nhg == NULL)
974 		return;
975 
976 	/* Print backup info */
977 	for (ALL_NEXTHOPS_PTR(nhg, nexthop)) {
978 		bool star_p = false;
979 
980 		if (is_fib)
981 			star_p = CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
982 
983 		/* TODO -- it'd be nice to be able to include
984 		 * the entire list of backups, *and* include the
985 		 * real installation state.
986 		 */
987 		vty_out(vty, "  b%c %*c",
988 			(star_p ? '*' : ' '),
989 			len - 3 + (2 * nexthop_level(nexthop)),	' ');
990 		show_route_nexthop_helper(vty, re, nexthop);
991 		vty_out(vty, "\n");
992 	}
993 
994 }
995 
vty_show_ip_route_detail_json(struct vty * vty,struct route_node * rn,bool use_fib)996 static void vty_show_ip_route_detail_json(struct vty *vty,
997 					  struct route_node *rn, bool use_fib)
998 {
999 	json_object *json = NULL;
1000 	json_object *json_prefix = NULL;
1001 	struct route_entry *re;
1002 	char buf[BUFSIZ];
1003 	rib_dest_t *dest;
1004 
1005 	dest = rib_dest_from_rnode(rn);
1006 
1007 	json = json_object_new_object();
1008 	json_prefix = json_object_new_array();
1009 
1010 	RNODE_FOREACH_RE (rn, re) {
1011 		/*
1012 		 * If re not selected for forwarding, skip re
1013 		 * for "show ip/ipv6 fib <prefix> json"
1014 		 */
1015 		if (use_fib && re != dest->selected_fib)
1016 			continue;
1017 		vty_show_ip_route(vty, rn, re, json_prefix, use_fib);
1018 	}
1019 
1020 	prefix2str(&rn->p, buf, sizeof(buf));
1021 	json_object_object_add(json, buf, json_prefix);
1022 	vty_out(vty, "%s\n", json_object_to_json_string_ext(
1023 					     json, JSON_C_TO_STRING_PRETTY));
1024 	json_object_free(json);
1025 }
1026 
do_show_route_helper(struct vty * vty,struct zebra_vrf * zvrf,struct route_table * table,afi_t afi,bool use_fib,route_tag_t tag,const struct prefix * longer_prefix_p,bool supernets_only,int type,unsigned short ospf_instance_id,bool use_json,uint32_t tableid,struct route_show_ctx * ctx)1027 static void do_show_route_helper(struct vty *vty, struct zebra_vrf *zvrf,
1028 				 struct route_table *table, afi_t afi,
1029 				 bool use_fib, route_tag_t tag,
1030 				 const struct prefix *longer_prefix_p,
1031 				 bool supernets_only, int type,
1032 				 unsigned short ospf_instance_id, bool use_json,
1033 				 uint32_t tableid, struct route_show_ctx *ctx)
1034 {
1035 	struct route_node *rn;
1036 	struct route_entry *re;
1037 	int first = 1;
1038 	rib_dest_t *dest;
1039 	json_object *json = NULL;
1040 	json_object *json_prefix = NULL;
1041 	uint32_t addr;
1042 	char buf[BUFSIZ];
1043 
1044 	/*
1045 	 * ctx->multi indicates if we are dumping multiple tables or vrfs.
1046 	 * if set:
1047 	 *   => display the common header at most once
1048 	 *   => add newline at each call except first
1049 	 *   => always display the VRF and table
1050 	 * else:
1051 	 *   => display the common header if at least one entry is found
1052 	 *   => display the VRF and table if specific
1053 	 */
1054 
1055 	if (use_json)
1056 		json = json_object_new_object();
1057 
1058 	/* Show all routes. */
1059 	for (rn = route_top(table); rn; rn = srcdest_route_next(rn)) {
1060 		dest = rib_dest_from_rnode(rn);
1061 
1062 		RNODE_FOREACH_RE (rn, re) {
1063 			if (use_fib && re != dest->selected_fib)
1064 				continue;
1065 
1066 			if (tag && re->tag != tag)
1067 				continue;
1068 
1069 			if (longer_prefix_p
1070 			    && !prefix_match(longer_prefix_p, &rn->p))
1071 				continue;
1072 
1073 			/* This can only be true when the afi is IPv4 */
1074 			if (supernets_only) {
1075 				addr = ntohl(rn->p.u.prefix4.s_addr);
1076 
1077 				if (IN_CLASSC(addr) && rn->p.prefixlen >= 24)
1078 					continue;
1079 
1080 				if (IN_CLASSB(addr) && rn->p.prefixlen >= 16)
1081 					continue;
1082 
1083 				if (IN_CLASSA(addr) && rn->p.prefixlen >= 8)
1084 					continue;
1085 			}
1086 
1087 			if (type && re->type != type)
1088 				continue;
1089 
1090 			if (ospf_instance_id
1091 			    && (re->type != ZEBRA_ROUTE_OSPF
1092 				|| re->instance != ospf_instance_id))
1093 				continue;
1094 
1095 			if (use_json) {
1096 				if (!json_prefix)
1097 					json_prefix = json_object_new_array();
1098 			} else if (first) {
1099 				if (!ctx->header_done) {
1100 					if (afi == AFI_IP)
1101 						vty_out(vty,
1102 							SHOW_ROUTE_V4_HEADER);
1103 					else
1104 						vty_out(vty,
1105 							SHOW_ROUTE_V6_HEADER);
1106 				}
1107 				if (ctx->multi && ctx->header_done)
1108 					vty_out(vty, "\n");
1109 				if (ctx->multi || zvrf_id(zvrf) != VRF_DEFAULT
1110 				    || tableid) {
1111 					if (!tableid)
1112 						vty_out(vty, "VRF %s:\n",
1113 							zvrf_name(zvrf));
1114 					else
1115 						vty_out(vty,
1116 							"VRF %s table %u:\n",
1117 							zvrf_name(zvrf),
1118 							tableid);
1119 				}
1120 				ctx->header_done = true;
1121 				first = 0;
1122 			}
1123 
1124 			vty_show_ip_route(vty, rn, re, json_prefix, use_fib);
1125 		}
1126 
1127 		if (json_prefix) {
1128 			prefix2str(&rn->p, buf, sizeof(buf));
1129 			json_object_object_add(json, buf, json_prefix);
1130 			json_prefix = NULL;
1131 		}
1132 	}
1133 
1134 	if (use_json) {
1135 		vty_out(vty, "%s\n", json_object_to_json_string_ext(json,
1136 						JSON_C_TO_STRING_PRETTY));
1137 		json_object_free(json);
1138 	}
1139 }
1140 
do_show_ip_route_all(struct vty * vty,struct zebra_vrf * zvrf,afi_t afi,bool use_fib,bool use_json,route_tag_t tag,const struct prefix * longer_prefix_p,bool supernets_only,int type,unsigned short ospf_instance_id,struct route_show_ctx * ctx)1141 static void do_show_ip_route_all(struct vty *vty, struct zebra_vrf *zvrf,
1142 				 afi_t afi, bool use_fib, bool use_json,
1143 				 route_tag_t tag,
1144 				 const struct prefix *longer_prefix_p,
1145 				 bool supernets_only, int type,
1146 				 unsigned short ospf_instance_id,
1147 				 struct route_show_ctx *ctx)
1148 {
1149 	struct zebra_router_table *zrt;
1150 	struct rib_table_info *info;
1151 
1152 	RB_FOREACH (zrt, zebra_router_table_head,
1153 		    &zrouter.tables) {
1154 		info = route_table_get_info(zrt->table);
1155 
1156 		if (zvrf != info->zvrf)
1157 			continue;
1158 		if (zrt->afi != afi ||
1159 		    zrt->safi != SAFI_UNICAST)
1160 			continue;
1161 
1162 		do_show_ip_route(vty, zvrf_name(zvrf), afi, SAFI_UNICAST,
1163 				 use_fib, use_json, tag, longer_prefix_p,
1164 				 supernets_only, type, ospf_instance_id,
1165 				 zrt->tableid, ctx);
1166 	}
1167 }
1168 
do_show_ip_route(struct vty * vty,const char * vrf_name,afi_t afi,safi_t safi,bool use_fib,bool use_json,route_tag_t tag,const struct prefix * longer_prefix_p,bool supernets_only,int type,unsigned short ospf_instance_id,uint32_t tableid,struct route_show_ctx * ctx)1169 static int do_show_ip_route(struct vty *vty, const char *vrf_name, afi_t afi,
1170 			    safi_t safi, bool use_fib, bool use_json,
1171 			    route_tag_t tag,
1172 			    const struct prefix *longer_prefix_p,
1173 			    bool supernets_only, int type,
1174 			    unsigned short ospf_instance_id, uint32_t tableid,
1175 			    struct route_show_ctx *ctx)
1176 {
1177 	struct route_table *table;
1178 	struct zebra_vrf *zvrf = NULL;
1179 
1180 	if (!(zvrf = zebra_vrf_lookup_by_name(vrf_name))) {
1181 		if (use_json)
1182 			vty_out(vty, "{}\n");
1183 		else
1184 			vty_out(vty, "vrf %s not defined\n", vrf_name);
1185 		return CMD_SUCCESS;
1186 	}
1187 
1188 	if (zvrf_id(zvrf) == VRF_UNKNOWN) {
1189 		if (use_json)
1190 			vty_out(vty, "{}\n");
1191 		else
1192 			vty_out(vty, "vrf %s inactive\n", vrf_name);
1193 		return CMD_SUCCESS;
1194 	}
1195 
1196 	if (tableid)
1197 		table = zebra_router_find_table(zvrf, tableid, afi, SAFI_UNICAST);
1198 	else
1199 		table = zebra_vrf_table(afi, safi, zvrf_id(zvrf));
1200 	if (!table) {
1201 		if (use_json)
1202 			vty_out(vty, "{}\n");
1203 		return CMD_SUCCESS;
1204 	}
1205 
1206 	do_show_route_helper(vty, zvrf, table, afi, use_fib, tag,
1207 			     longer_prefix_p, supernets_only, type,
1208 			     ospf_instance_id, use_json, tableid, ctx);
1209 
1210 	return CMD_SUCCESS;
1211 }
1212 
1213 DEFPY (show_ip_nht,
1214        show_ip_nht_cmd,
1215        "show <ip$ipv4|ipv6$ipv6> <nht|import-check>$type [<A.B.C.D|X:X::X:X>$addr|vrf NAME$vrf_name [<A.B.C.D|X:X::X:X>$addr]|vrf all$vrf_all]",
1216        SHOW_STR
1217        IP_STR
1218        IP6_STR
1219        "IP nexthop tracking table\n"
1220        "IP import check tracking table\n"
1221        "IPv4 Address\n"
1222        "IPv6 Address\n"
1223        VRF_CMD_HELP_STR
1224        "IPv4 Address\n"
1225        "IPv6 Address\n"
1226        VRF_ALL_CMD_HELP_STR)
1227 {
1228 	afi_t afi = ipv4 ? AFI_IP : AFI_IP6;
1229 	vrf_id_t vrf_id = VRF_DEFAULT;
1230 	struct prefix prefix, *p = NULL;
1231 	enum rnh_type rtype;
1232 
1233 	if (strcmp(type, "nht") == 0)
1234 		rtype = RNH_NEXTHOP_TYPE;
1235 	else
1236 		rtype = RNH_IMPORT_CHECK_TYPE;
1237 
1238 	if (vrf_all) {
1239 		struct vrf *vrf;
1240 		struct zebra_vrf *zvrf;
1241 
1242 		RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name)
1243 			if ((zvrf = vrf->info) != NULL) {
1244 				vty_out(vty, "\nVRF %s:\n", zvrf_name(zvrf));
1245 				zebra_print_rnh_table(zvrf_id(zvrf), afi, vty,
1246 						      rtype, NULL);
1247 			}
1248 		return CMD_SUCCESS;
1249 	}
1250 	if (vrf_name)
1251 		VRF_GET_ID(vrf_id, vrf_name, false);
1252 
1253 	memset(&prefix, 0, sizeof(prefix));
1254 	if (addr)
1255 		p = sockunion2hostprefix(addr, &prefix);
1256 
1257 	zebra_print_rnh_table(vrf_id, afi, vty, rtype, p);
1258 	return CMD_SUCCESS;
1259 }
1260 
1261 DEFUN (ip_nht_default_route,
1262        ip_nht_default_route_cmd,
1263        "ip nht resolve-via-default",
1264        IP_STR
1265        "Filter Next Hop tracking route resolution\n"
1266        "Resolve via default route\n")
1267 {
1268 	ZEBRA_DECLVAR_CONTEXT(vrf, zvrf);
1269 
1270 	if (!zvrf)
1271 		return CMD_WARNING;
1272 
1273 	if (zvrf->zebra_rnh_ip_default_route)
1274 		return CMD_SUCCESS;
1275 
1276 	zvrf->zebra_rnh_ip_default_route = 1;
1277 
1278 	zebra_evaluate_rnh(zvrf, AFI_IP, 0, RNH_NEXTHOP_TYPE, NULL);
1279 	return CMD_SUCCESS;
1280 }
1281 
show_nexthop_group_out(struct vty * vty,struct nhg_hash_entry * nhe)1282 static void show_nexthop_group_out(struct vty *vty, struct nhg_hash_entry *nhe)
1283 {
1284 	struct nexthop *nexthop = NULL;
1285 	struct nhg_connected *rb_node_dep = NULL;
1286 	struct nexthop_group *backup_nhg;
1287 
1288 	vty_out(vty, "ID: %u\n", nhe->id);
1289 	vty_out(vty, "     RefCnt: %d\n", nhe->refcnt);
1290 	vty_out(vty, "     VRF: %s\n", vrf_id_to_name(nhe->vrf_id));
1291 
1292 	if (CHECK_FLAG(nhe->flags, NEXTHOP_GROUP_UNHASHABLE))
1293 		vty_out(vty, "     Duplicate - from kernel not hashable\n");
1294 
1295 	if (CHECK_FLAG(nhe->flags, NEXTHOP_GROUP_VALID)) {
1296 		vty_out(vty, "     Valid");
1297 		if (CHECK_FLAG(nhe->flags, NEXTHOP_GROUP_INSTALLED))
1298 			vty_out(vty, ", Installed");
1299 		vty_out(vty, "\n");
1300 	}
1301 	if (nhe->ifp)
1302 		vty_out(vty, "     Interface Index: %d\n", nhe->ifp->ifindex);
1303 
1304 	if (!zebra_nhg_depends_is_empty(nhe)) {
1305 		vty_out(vty, "     Depends:");
1306 		frr_each(nhg_connected_tree, &nhe->nhg_depends, rb_node_dep) {
1307 			vty_out(vty, " (%u)", rb_node_dep->nhe->id);
1308 		}
1309 		vty_out(vty, "\n");
1310 	}
1311 
1312 	/* Output nexthops */
1313 	for (ALL_NEXTHOPS(nhe->nhg, nexthop)) {
1314 		if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
1315 			vty_out(vty, "          ");
1316 		else
1317 			/* Make recursive nexthops a bit more clear */
1318 			vty_out(vty, "       ");
1319 
1320 		show_route_nexthop_helper(vty, NULL, nexthop);
1321 
1322 		if (nhe->backup_info == NULL || nhe->backup_info->nhe == NULL) {
1323 			if (CHECK_FLAG(nexthop->flags,
1324 				       NEXTHOP_FLAG_HAS_BACKUP))
1325 				vty_out(vty, " [backup %d]",
1326 					nexthop->backup_idx[0]);
1327 
1328 			vty_out(vty, "\n");
1329 			continue;
1330 		}
1331 
1332 		/* TODO -- print more useful backup info */
1333 		if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP)) {
1334 			int i;
1335 
1336 			vty_out(vty, "[backup");
1337 			for (i = 0; i < nexthop->backup_num; i++)
1338 				vty_out(vty, " %d", nexthop->backup_idx[i]);
1339 
1340 			vty_out(vty, "]");
1341 		}
1342 
1343 		vty_out(vty, "\n");
1344 	}
1345 
1346 	/* Output backup nexthops (if any) */
1347 	backup_nhg = zebra_nhg_get_backup_nhg(nhe);
1348 	if (backup_nhg) {
1349 		vty_out(vty, "     Backups:\n");
1350 
1351 		for (ALL_NEXTHOPS_PTR(backup_nhg, nexthop)) {
1352 			if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
1353 				vty_out(vty, "          ");
1354 			else
1355 				/* Make recursive nexthops a bit more clear */
1356 				vty_out(vty, "       ");
1357 
1358 			show_route_nexthop_helper(vty, NULL, nexthop);
1359 			vty_out(vty, "\n");
1360 		}
1361 	}
1362 
1363 	if (!zebra_nhg_dependents_is_empty(nhe)) {
1364 		vty_out(vty, "     Dependents:");
1365 		frr_each(nhg_connected_tree, &nhe->nhg_dependents,
1366 			  rb_node_dep) {
1367 			vty_out(vty, " (%u)", rb_node_dep->nhe->id);
1368 		}
1369 		vty_out(vty, "\n");
1370 	}
1371 
1372 }
1373 
show_nexthop_group_id_cmd_helper(struct vty * vty,uint32_t id)1374 static int show_nexthop_group_id_cmd_helper(struct vty *vty, uint32_t id)
1375 {
1376 	struct nhg_hash_entry *nhe = NULL;
1377 
1378 	nhe = zebra_nhg_lookup_id(id);
1379 
1380 	if (nhe)
1381 		show_nexthop_group_out(vty, nhe);
1382 	else {
1383 		vty_out(vty, "Nexthop Group ID: %u does not exist\n", id);
1384 		return CMD_WARNING;
1385 	}
1386 	return CMD_SUCCESS;
1387 }
1388 
1389 /* Helper function for iteration through the hash of nexthop-groups/nhe-s */
1390 
1391 struct nhe_show_context {
1392 	struct vty *vty;
1393 	vrf_id_t vrf_id;
1394 	afi_t afi;
1395 };
1396 
nhe_show_walker(struct hash_bucket * bucket,void * arg)1397 static int nhe_show_walker(struct hash_bucket *bucket, void *arg)
1398 {
1399 	struct nhe_show_context *ctx = arg;
1400 	struct nhg_hash_entry *nhe;
1401 
1402 	nhe = bucket->data; /* We won't be offered NULL buckets */
1403 
1404 	if (ctx->afi && nhe->afi != ctx->afi)
1405 		goto done;
1406 
1407 	if (ctx->vrf_id && nhe->vrf_id != ctx->vrf_id)
1408 		goto done;
1409 
1410 	show_nexthop_group_out(ctx->vty, nhe);
1411 
1412 done:
1413 	return HASHWALK_CONTINUE;
1414 }
1415 
show_nexthop_group_cmd_helper(struct vty * vty,struct zebra_vrf * zvrf,afi_t afi)1416 static void show_nexthop_group_cmd_helper(struct vty *vty,
1417 					  struct zebra_vrf *zvrf,
1418 					  afi_t afi)
1419 {
1420 	struct nhe_show_context ctx;
1421 
1422 	ctx.vty = vty;
1423 	ctx.afi = afi;
1424 	ctx.vrf_id = zvrf->vrf->vrf_id;
1425 
1426 	hash_walk(zrouter.nhgs_id, nhe_show_walker, &ctx);
1427 }
1428 
if_nexthop_group_dump_vty(struct vty * vty,struct interface * ifp)1429 static void if_nexthop_group_dump_vty(struct vty *vty, struct interface *ifp)
1430 {
1431 	struct zebra_if *zebra_if = NULL;
1432 	struct nhg_connected *rb_node_dep = NULL;
1433 
1434 	zebra_if = ifp->info;
1435 
1436 	if (!if_nhg_dependents_is_empty(ifp)) {
1437 		vty_out(vty, "Interface %s:\n", ifp->name);
1438 
1439 		frr_each(nhg_connected_tree, &zebra_if->nhg_dependents,
1440 			  rb_node_dep) {
1441 			vty_out(vty, "   ");
1442 			show_nexthop_group_out(vty, rb_node_dep->nhe);
1443 		}
1444 	}
1445 }
1446 
1447 DEFPY (show_interface_nexthop_group,
1448        show_interface_nexthop_group_cmd,
1449        "show interface [IFNAME$if_name] nexthop-group",
1450        SHOW_STR
1451        "Interface status and configuration\n"
1452        "Interface name\n"
1453        "Show Nexthop Groups\n")
1454 {
1455 	struct vrf *vrf = NULL;
1456 	struct interface *ifp = NULL;
1457 	bool found = false;
1458 
1459 	RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
1460 		if (if_name) {
1461 			ifp = if_lookup_by_name(if_name, vrf->vrf_id);
1462 			if (ifp) {
1463 				if_nexthop_group_dump_vty(vty, ifp);
1464 				found = true;
1465 			}
1466 		} else {
1467 			FOR_ALL_INTERFACES (vrf, ifp)
1468 				if_nexthop_group_dump_vty(vty, ifp);
1469 			found = true;
1470 		}
1471 	}
1472 
1473 	if (!found) {
1474 		vty_out(vty, "%% Can't find interface %s\n", if_name);
1475 		return CMD_WARNING;
1476 	}
1477 
1478 	return CMD_SUCCESS;
1479 }
1480 
1481 DEFPY (show_nexthop_group,
1482        show_nexthop_group_cmd,
1483        "show nexthop-group rib <(0-4294967295)$id|[singleton <ip$v4|ipv6$v6>] [vrf <NAME$vrf_name|all$vrf_all>]>",
1484        SHOW_STR
1485        "Show Nexthop Groups\n"
1486        "RIB information\n"
1487        "Nexthop Group ID\n"
1488        "Show Singleton Nexthop-Groups\n"
1489        IP_STR
1490        IP6_STR
1491        VRF_FULL_CMD_HELP_STR)
1492 {
1493 
1494 	struct zebra_vrf *zvrf = NULL;
1495 	afi_t afi = AFI_UNSPEC;
1496 
1497 	if (id)
1498 		return show_nexthop_group_id_cmd_helper(vty, id);
1499 
1500 	if (v4)
1501 		afi = AFI_IP;
1502 	else if (v6)
1503 		afi = AFI_IP6;
1504 
1505 	if (!vrf_is_backend_netns() && (vrf_name || vrf_all)) {
1506 		vty_out(vty,
1507 			"VRF subcommand does not make any sense in l3mdev based vrf's\n");
1508 		return CMD_WARNING;
1509 	}
1510 
1511 	if (vrf_all) {
1512 		struct vrf *vrf;
1513 
1514 		RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
1515 			struct zebra_vrf *zvrf;
1516 
1517 			zvrf = vrf->info;
1518 			if (!zvrf)
1519 				continue;
1520 
1521 			vty_out(vty, "VRF: %s\n", vrf->name);
1522 			show_nexthop_group_cmd_helper(vty, zvrf, afi);
1523 		}
1524 
1525 		return CMD_SUCCESS;
1526 	}
1527 
1528 	if (vrf_name)
1529 		zvrf = zebra_vrf_lookup_by_name(vrf_name);
1530 	else
1531 		zvrf = zebra_vrf_lookup_by_name(VRF_DEFAULT_NAME);
1532 
1533 	if (!zvrf) {
1534 		vty_out(vty, "%% VRF '%s' specified does not exist\n",
1535 			vrf_name);
1536 		return CMD_WARNING;
1537 	}
1538 
1539 	show_nexthop_group_cmd_helper(vty, zvrf, afi);
1540 
1541 	return CMD_SUCCESS;
1542 }
1543 
1544 DEFPY_HIDDEN(nexthop_group_use_enable,
1545 	     nexthop_group_use_enable_cmd,
1546 	     "[no] zebra nexthop kernel enable",
1547 	     NO_STR
1548 	     ZEBRA_STR
1549 	     "Nexthop configuration \n"
1550 	     "Configure use of kernel nexthops\n"
1551 	     "Enable kernel nexthops\n")
1552 {
1553 	zebra_nhg_enable_kernel_nexthops(!no);
1554 	return CMD_SUCCESS;
1555 }
1556 
1557 DEFUN (no_ip_nht_default_route,
1558        no_ip_nht_default_route_cmd,
1559        "no ip nht resolve-via-default",
1560        NO_STR
1561        IP_STR
1562        "Filter Next Hop tracking route resolution\n"
1563        "Resolve via default route\n")
1564 {
1565 	ZEBRA_DECLVAR_CONTEXT(vrf, zvrf);
1566 
1567 	if (!zvrf)
1568 		return CMD_WARNING;
1569 
1570 	if (!zvrf->zebra_rnh_ip_default_route)
1571 		return CMD_SUCCESS;
1572 
1573 	zvrf->zebra_rnh_ip_default_route = 0;
1574 	zebra_evaluate_rnh(zvrf, AFI_IP, 0, RNH_NEXTHOP_TYPE, NULL);
1575 	return CMD_SUCCESS;
1576 }
1577 
1578 DEFUN (ipv6_nht_default_route,
1579        ipv6_nht_default_route_cmd,
1580        "ipv6 nht resolve-via-default",
1581        IP6_STR
1582        "Filter Next Hop tracking route resolution\n"
1583        "Resolve via default route\n")
1584 {
1585 	ZEBRA_DECLVAR_CONTEXT(vrf, zvrf);
1586 
1587 	if (!zvrf)
1588 		return CMD_WARNING;
1589 
1590 	if (zvrf->zebra_rnh_ipv6_default_route)
1591 		return CMD_SUCCESS;
1592 
1593 	zvrf->zebra_rnh_ipv6_default_route = 1;
1594 	zebra_evaluate_rnh(zvrf, AFI_IP6, 0, RNH_NEXTHOP_TYPE, NULL);
1595 	return CMD_SUCCESS;
1596 }
1597 
1598 DEFUN (no_ipv6_nht_default_route,
1599        no_ipv6_nht_default_route_cmd,
1600        "no ipv6 nht resolve-via-default",
1601        NO_STR
1602        IP6_STR
1603        "Filter Next Hop tracking route resolution\n"
1604        "Resolve via default route\n")
1605 {
1606 
1607 	ZEBRA_DECLVAR_CONTEXT(vrf, zvrf);
1608 
1609 	if (!zvrf)
1610 		return CMD_WARNING;
1611 
1612 	if (!zvrf->zebra_rnh_ipv6_default_route)
1613 		return CMD_SUCCESS;
1614 
1615 	zvrf->zebra_rnh_ipv6_default_route = 0;
1616 	zebra_evaluate_rnh(zvrf, AFI_IP6, 0, RNH_NEXTHOP_TYPE, NULL);
1617 	return CMD_SUCCESS;
1618 }
1619 
1620 DEFPY (show_route,
1621        show_route_cmd,
1622        "show\
1623          <\
1624 	  ip$ipv4 <fib$fib|route> [table <(1-4294967295)$table|all$table_all>]\
1625 	  [vrf <NAME$vrf_name|all$vrf_all>]\
1626 	   [{\
1627 	    tag (1-4294967295)\
1628 	    |A.B.C.D/M$prefix longer-prefixes\
1629 	    |supernets-only$supernets_only\
1630 	   }]\
1631 	   [<\
1632 	    " FRR_IP_REDIST_STR_ZEBRA "$type_str\
1633 	    |ospf$type_str (1-65535)$ospf_instance_id\
1634 	   >]\
1635           |ipv6$ipv6 <fib$fib|route> [table <(1-4294967295)$table|all$table_all>]\
1636 	  [vrf <NAME$vrf_name|all$vrf_all>]\
1637 	   [{\
1638 	    tag (1-4294967295)\
1639 	    |X:X::X:X/M$prefix longer-prefixes\
1640 	   }]\
1641 	   [" FRR_IP6_REDIST_STR_ZEBRA "$type_str]\
1642 	 >\
1643         [json$json]",
1644        SHOW_STR
1645        IP_STR
1646        "IP forwarding table\n"
1647        "IP routing table\n"
1648        "Table to display\n"
1649        "The table number to display\n"
1650        "All tables\n"
1651        VRF_FULL_CMD_HELP_STR
1652        "Show only routes with tag\n"
1653        "Tag value\n"
1654        "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
1655        "Show route matching the specified Network/Mask pair only\n"
1656        "Show supernet entries only\n"
1657        FRR_IP_REDIST_HELP_STR_ZEBRA
1658        "Open Shortest Path First (OSPFv2)\n"
1659        "Instance ID\n"
1660        IPV6_STR
1661        "IP forwarding table\n"
1662        "IP routing table\n"
1663        "Table to display\n"
1664        "The table number to display\n"
1665        "All tables\n"
1666        VRF_FULL_CMD_HELP_STR
1667        "Show only routes with tag\n"
1668        "Tag value\n"
1669        "IPv6 prefix\n"
1670        "Show route matching the specified Network/Mask pair only\n"
1671        FRR_IP6_REDIST_HELP_STR_ZEBRA
1672        JSON_STR)
1673 {
1674 	afi_t afi = ipv4 ? AFI_IP : AFI_IP6;
1675 	struct vrf *vrf;
1676 	int type = 0;
1677 	struct zebra_vrf *zvrf;
1678 	struct route_show_ctx ctx = {
1679 		.multi = vrf_all || table_all,
1680 	};
1681 
1682 	if (!vrf_is_backend_netns()) {
1683 		if ((vrf_all || vrf_name) && (table || table_all)) {
1684 			if (!!json)
1685 				vty_out(vty, "{}\n");
1686 			else {
1687 				vty_out(vty, "Linux vrf backend already points to table id\n");
1688 				vty_out(vty, "Either remove table parameter or vrf parameter\n");
1689 			}
1690 			return CMD_SUCCESS;
1691 		}
1692 	}
1693 	if (type_str) {
1694 		type = proto_redistnum(afi, type_str);
1695 		if (type < 0) {
1696 			vty_out(vty, "Unknown route type\n");
1697 			return CMD_WARNING;
1698 		}
1699 	}
1700 
1701 	if (vrf_all) {
1702 		RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
1703 			if ((zvrf = vrf->info) == NULL
1704 			    || (zvrf->table[afi][SAFI_UNICAST] == NULL))
1705 				continue;
1706 
1707 			if (table_all)
1708 				do_show_ip_route_all(vty, zvrf, afi, !!fib,
1709 						     !!json, tag,
1710 						     prefix_str ? prefix : NULL,
1711 						     !!supernets_only, type,
1712 						     ospf_instance_id, &ctx);
1713 			else
1714 				do_show_ip_route(vty, zvrf_name(zvrf), afi,
1715 						 SAFI_UNICAST, !!fib, !!json,
1716 						 tag,
1717 						 prefix_str ? prefix : NULL,
1718 						 !!supernets_only, type,
1719 						 ospf_instance_id, table, &ctx);
1720 		}
1721 	} else {
1722 		vrf_id_t vrf_id = VRF_DEFAULT;
1723 
1724 		if (vrf_name)
1725 			VRF_GET_ID(vrf_id, vrf_name, !!json);
1726 		vrf = vrf_lookup_by_id(vrf_id);
1727 		if (vrf)
1728 			zvrf = vrf->info;
1729 		if (!vrf || !zvrf)
1730 			return CMD_SUCCESS;
1731 
1732 		if (table_all)
1733 			do_show_ip_route_all(vty, zvrf, afi, !!fib, !!json, tag,
1734 					     prefix_str ? prefix : NULL,
1735 					     !!supernets_only, type,
1736 					     ospf_instance_id, &ctx);
1737 		else
1738 			do_show_ip_route(vty, vrf->name, afi, SAFI_UNICAST,
1739 					 !!fib, !!json, tag,
1740 					 prefix_str ? prefix : NULL,
1741 					 !!supernets_only, type,
1742 					 ospf_instance_id, table, &ctx);
1743 	}
1744 
1745 	return CMD_SUCCESS;
1746 }
1747 
1748 ALIAS_HIDDEN (show_route,
1749               show_ro_cmd,
1750               "show <ip$ipv4|ipv6$ipv6> ro",
1751               SHOW_STR
1752               IP_STR
1753               IPV6_STR
1754               "IP routing table\n");
1755 
1756 
1757 DEFPY (show_route_detail,
1758        show_route_detail_cmd,
1759        "show\
1760          <\
1761           ip$ipv4 <fib$fib|route> [vrf <NAME$vrf_name|all$vrf_all>]\
1762           <\
1763 	   A.B.C.D$address\
1764 	   |A.B.C.D/M$prefix\
1765 	  >\
1766           |ipv6$ipv6 <fib$fib|route> [vrf <NAME$vrf_name|all$vrf_all>]\
1767           <\
1768 	   X:X::X:X$address\
1769 	   |X:X::X:X/M$prefix\
1770 	  >\
1771 	 >\
1772 	 [json$json] [nexthop-group$ng]",
1773        SHOW_STR
1774        IP_STR
1775        "IPv6 forwarding table\n"
1776        "IP routing table\n"
1777        VRF_FULL_CMD_HELP_STR
1778        "Network in the IP routing table to display\n"
1779        "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
1780        IP6_STR
1781        "IPv6 forwarding table\n"
1782        "IPv6 routing table\n"
1783        VRF_FULL_CMD_HELP_STR
1784        "IPv6 Address\n"
1785        "IPv6 prefix\n"
1786        JSON_STR
1787        "Nexthop Group Information\n")
1788 {
1789 	afi_t afi = ipv4 ? AFI_IP : AFI_IP6;
1790 	struct route_table *table;
1791 	struct prefix p;
1792 	struct route_node *rn;
1793 	bool use_fib = !!fib;
1794 	rib_dest_t *dest;
1795 	bool network_found = false;
1796 	bool show_ng = !!ng;
1797 
1798 	if (address_str)
1799 		prefix_str = address_str;
1800 	if (str2prefix(prefix_str, &p) < 0) {
1801 		vty_out(vty, "%% Malformed address\n");
1802 		return CMD_WARNING;
1803 	}
1804 
1805 	if (vrf_all) {
1806 		struct vrf *vrf;
1807 		struct zebra_vrf *zvrf;
1808 
1809 		RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
1810 			if ((zvrf = vrf->info) == NULL
1811 			    || (table = zvrf->table[afi][SAFI_UNICAST]) == NULL)
1812 				continue;
1813 
1814 			rn = route_node_match(table, &p);
1815 			if (!rn)
1816 				continue;
1817 			if (!address_str && rn->p.prefixlen != p.prefixlen) {
1818 				route_unlock_node(rn);
1819 				continue;
1820 			}
1821 
1822 			dest = rib_dest_from_rnode(rn);
1823 			if (use_fib && !dest->selected_fib) {
1824 				route_unlock_node(rn);
1825 				continue;
1826 			}
1827 
1828 			network_found = true;
1829 			if (json)
1830 				vty_show_ip_route_detail_json(vty, rn, use_fib);
1831 			else
1832 				vty_show_ip_route_detail(vty, rn, 0, use_fib,
1833 							 show_ng);
1834 
1835 			route_unlock_node(rn);
1836 		}
1837 
1838 		if (!network_found) {
1839 			if (json)
1840 				vty_out(vty, "{}\n");
1841 			else {
1842 				if (use_fib)
1843 					vty_out(vty,
1844 						"%% Network not in FIB\n");
1845 				else
1846 					vty_out(vty,
1847 						"%% Network not in RIB\n");
1848 			}
1849 			return CMD_WARNING;
1850 		}
1851 	} else {
1852 		vrf_id_t vrf_id = VRF_DEFAULT;
1853 
1854 		if (vrf_name)
1855 			VRF_GET_ID(vrf_id, vrf_name, false);
1856 
1857 		table = zebra_vrf_table(afi, SAFI_UNICAST, vrf_id);
1858 		if (!table)
1859 			return CMD_SUCCESS;
1860 
1861 		rn = route_node_match(table, &p);
1862 		if (rn)
1863 			dest = rib_dest_from_rnode(rn);
1864 
1865 		if (!rn || (!address_str && rn->p.prefixlen != p.prefixlen) ||
1866 			(use_fib && dest && !dest->selected_fib)) {
1867 			if (json)
1868 				vty_out(vty, "{}\n");
1869 			else {
1870 				if (use_fib)
1871 					vty_out(vty,
1872 						"%% Network not in FIB\n");
1873 				else
1874 					vty_out(vty,
1875 						"%% Network not in table\n");
1876 			}
1877 			if (rn)
1878 				route_unlock_node(rn);
1879 			return CMD_WARNING;
1880 		}
1881 
1882 		if (json)
1883 			vty_show_ip_route_detail_json(vty, rn, use_fib);
1884 		else
1885 			vty_show_ip_route_detail(vty, rn, 0, use_fib, show_ng);
1886 
1887 		route_unlock_node(rn);
1888 	}
1889 
1890 	return CMD_SUCCESS;
1891 }
1892 
1893 DEFPY (show_route_summary,
1894        show_route_summary_cmd,
1895        "show <ip$ipv4|ipv6$ipv6> route [vrf <NAME$vrf_name|all$vrf_all>] \
1896             summary [table (1-4294967295)$table_id] [prefix$prefix] [json]",
1897        SHOW_STR
1898        IP_STR
1899        IP6_STR
1900        "IP routing table\n"
1901        VRF_FULL_CMD_HELP_STR
1902        "Summary of all routes\n"
1903        "Table to display summary for\n"
1904        "The table number\n"
1905        "Prefix routes\n"
1906        JSON_STR)
1907 {
1908 	afi_t afi = ipv4 ? AFI_IP : AFI_IP6;
1909 	struct route_table *table;
1910 	bool uj = use_json(argc, argv);
1911 
1912 	if (vrf_all) {
1913 		struct vrf *vrf;
1914 		struct zebra_vrf *zvrf;
1915 
1916 		RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
1917 			if ((zvrf = vrf->info) == NULL)
1918 				continue;
1919 
1920 			if (table_id == 0)
1921 				table = zebra_vrf_table(afi, SAFI_UNICAST,
1922 							zvrf->vrf->vrf_id);
1923 			else
1924 				table = zebra_vrf_lookup_table_with_table_id(
1925 					afi, SAFI_UNICAST, zvrf->vrf->vrf_id,
1926 					table_id);
1927 
1928 			if (!table)
1929 				continue;
1930 
1931 			if (prefix)
1932 				vty_show_ip_route_summary_prefix(vty, table,
1933 								 uj);
1934 			else
1935 				vty_show_ip_route_summary(vty, table, uj);
1936 		}
1937 	} else {
1938 		vrf_id_t vrf_id = VRF_DEFAULT;
1939 
1940 		if (vrf_name)
1941 			VRF_GET_ID(vrf_id, vrf_name, false);
1942 
1943 		if (table_id == 0)
1944 			table = zebra_vrf_table(afi, SAFI_UNICAST, vrf_id);
1945 		else
1946 			table = zebra_vrf_lookup_table_with_table_id(
1947 				afi, SAFI_UNICAST, vrf_id, table_id);
1948 		if (!table)
1949 			return CMD_SUCCESS;
1950 
1951 		if (prefix)
1952 			vty_show_ip_route_summary_prefix(vty, table, uj);
1953 		else
1954 			vty_show_ip_route_summary(vty, table, uj);
1955 	}
1956 
1957 	return CMD_SUCCESS;
1958 }
1959 
vty_show_ip_route_summary(struct vty * vty,struct route_table * table,bool use_json)1960 static void vty_show_ip_route_summary(struct vty *vty,
1961 				      struct route_table *table, bool use_json)
1962 {
1963 	struct route_node *rn;
1964 	struct route_entry *re;
1965 #define ZEBRA_ROUTE_IBGP  ZEBRA_ROUTE_MAX
1966 #define ZEBRA_ROUTE_TOTAL (ZEBRA_ROUTE_IBGP + 1)
1967 	uint32_t rib_cnt[ZEBRA_ROUTE_TOTAL + 1];
1968 	uint32_t fib_cnt[ZEBRA_ROUTE_TOTAL + 1];
1969 	uint32_t i;
1970 	uint32_t is_ibgp;
1971 	json_object *json_route_summary = NULL;
1972 	json_object *json_route_routes = NULL;
1973 
1974 	memset(&rib_cnt, 0, sizeof(rib_cnt));
1975 	memset(&fib_cnt, 0, sizeof(fib_cnt));
1976 
1977 	if (use_json) {
1978 		json_route_summary = json_object_new_object();
1979 		json_route_routes = json_object_new_array();
1980 		json_object_object_add(json_route_summary, "routes",
1981 				       json_route_routes);
1982 	}
1983 
1984 	for (rn = route_top(table); rn; rn = srcdest_route_next(rn))
1985 		RNODE_FOREACH_RE (rn, re) {
1986 			is_ibgp = (re->type == ZEBRA_ROUTE_BGP
1987 				   && CHECK_FLAG(re->flags, ZEBRA_FLAG_IBGP));
1988 
1989 			rib_cnt[ZEBRA_ROUTE_TOTAL]++;
1990 			if (is_ibgp)
1991 				rib_cnt[ZEBRA_ROUTE_IBGP]++;
1992 			else
1993 				rib_cnt[re->type]++;
1994 
1995 			if (CHECK_FLAG(re->status, ROUTE_ENTRY_INSTALLED)) {
1996 				fib_cnt[ZEBRA_ROUTE_TOTAL]++;
1997 
1998 				if (is_ibgp)
1999 					fib_cnt[ZEBRA_ROUTE_IBGP]++;
2000 				else
2001 					fib_cnt[re->type]++;
2002 			}
2003 		}
2004 
2005 	if (!use_json)
2006 		vty_out(vty, "%-20s %-20s %s  (vrf %s)\n", "Route Source",
2007 			"Routes", "FIB",
2008 			zvrf_name(((struct rib_table_info *)
2009 					   route_table_get_info(table))
2010 					  ->zvrf));
2011 
2012 	for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
2013 		if ((rib_cnt[i] > 0) || (i == ZEBRA_ROUTE_BGP
2014 					 && rib_cnt[ZEBRA_ROUTE_IBGP] > 0)) {
2015 			if (i == ZEBRA_ROUTE_BGP) {
2016 				if (use_json) {
2017 					json_object *json_route_ebgp =
2018 						json_object_new_object();
2019 
2020 					json_object_int_add(
2021 						json_route_ebgp, "fib",
2022 						fib_cnt[ZEBRA_ROUTE_BGP]);
2023 					json_object_int_add(
2024 						json_route_ebgp, "rib",
2025 						rib_cnt[ZEBRA_ROUTE_BGP]);
2026 					json_object_string_add(json_route_ebgp,
2027 							       "type", "ebgp");
2028 					json_object_array_add(json_route_routes,
2029 							      json_route_ebgp);
2030 
2031 					json_object *json_route_ibgp =
2032 						json_object_new_object();
2033 
2034 					json_object_int_add(
2035 						json_route_ibgp, "fib",
2036 						fib_cnt[ZEBRA_ROUTE_IBGP]);
2037 					json_object_int_add(
2038 						json_route_ibgp, "rib",
2039 						rib_cnt[ZEBRA_ROUTE_IBGP]);
2040 					json_object_string_add(json_route_ibgp,
2041 							       "type", "ibgp");
2042 					json_object_array_add(json_route_routes,
2043 							      json_route_ibgp);
2044 				} else {
2045 					vty_out(vty, "%-20s %-20d %-20d \n",
2046 						"ebgp",
2047 						rib_cnt[ZEBRA_ROUTE_BGP],
2048 						fib_cnt[ZEBRA_ROUTE_BGP]);
2049 					vty_out(vty, "%-20s %-20d %-20d \n",
2050 						"ibgp",
2051 						rib_cnt[ZEBRA_ROUTE_IBGP],
2052 						fib_cnt[ZEBRA_ROUTE_IBGP]);
2053 				}
2054 			} else {
2055 				if (use_json) {
2056 					json_object *json_route_type =
2057 						json_object_new_object();
2058 
2059 					json_object_int_add(json_route_type,
2060 							    "fib", fib_cnt[i]);
2061 					json_object_int_add(json_route_type,
2062 							    "rib", rib_cnt[i]);
2063 					json_object_string_add(
2064 						json_route_type, "type",
2065 						zebra_route_string(i));
2066 					json_object_array_add(json_route_routes,
2067 							      json_route_type);
2068 				} else
2069 					vty_out(vty, "%-20s %-20d %-20d \n",
2070 						zebra_route_string(i),
2071 						rib_cnt[i], fib_cnt[i]);
2072 			}
2073 		}
2074 	}
2075 
2076 	if (use_json) {
2077 		json_object_int_add(json_route_summary, "routesTotal",
2078 				    rib_cnt[ZEBRA_ROUTE_TOTAL]);
2079 		json_object_int_add(json_route_summary, "routesTotalFib",
2080 				    fib_cnt[ZEBRA_ROUTE_TOTAL]);
2081 
2082 		vty_out(vty, "%s\n",
2083 			json_object_to_json_string_ext(
2084 				json_route_summary, JSON_C_TO_STRING_PRETTY));
2085 		json_object_free(json_route_summary);
2086 	} else {
2087 		vty_out(vty, "------\n");
2088 		vty_out(vty, "%-20s %-20d %-20d \n", "Totals",
2089 			rib_cnt[ZEBRA_ROUTE_TOTAL], fib_cnt[ZEBRA_ROUTE_TOTAL]);
2090 		vty_out(vty, "\n");
2091 	}
2092 }
2093 
2094 /*
2095  * Implementation of the ip route summary prefix command.
2096  *
2097  * This command prints the primary prefixes that have been installed by various
2098  * protocols on the box.
2099  *
2100  */
vty_show_ip_route_summary_prefix(struct vty * vty,struct route_table * table,bool use_json)2101 static void vty_show_ip_route_summary_prefix(struct vty *vty,
2102 					     struct route_table *table,
2103 					     bool use_json)
2104 {
2105 	struct route_node *rn;
2106 	struct route_entry *re;
2107 	struct nexthop *nexthop;
2108 #define ZEBRA_ROUTE_IBGP  ZEBRA_ROUTE_MAX
2109 #define ZEBRA_ROUTE_TOTAL (ZEBRA_ROUTE_IBGP + 1)
2110 	uint32_t rib_cnt[ZEBRA_ROUTE_TOTAL + 1];
2111 	uint32_t fib_cnt[ZEBRA_ROUTE_TOTAL + 1];
2112 	uint32_t i;
2113 	int cnt;
2114 	json_object *json_route_summary = NULL;
2115 	json_object *json_route_routes = NULL;
2116 
2117 	memset(&rib_cnt, 0, sizeof(rib_cnt));
2118 	memset(&fib_cnt, 0, sizeof(fib_cnt));
2119 
2120 	if (use_json) {
2121 		json_route_summary = json_object_new_object();
2122 		json_route_routes = json_object_new_array();
2123 		json_object_object_add(json_route_summary, "prefixRoutes",
2124 				       json_route_routes);
2125 	}
2126 
2127 	for (rn = route_top(table); rn; rn = srcdest_route_next(rn))
2128 		RNODE_FOREACH_RE (rn, re) {
2129 
2130 			/*
2131 			 * In case of ECMP, count only once.
2132 			 */
2133 			cnt = 0;
2134 			if (CHECK_FLAG(re->status, ROUTE_ENTRY_INSTALLED)) {
2135 				fib_cnt[ZEBRA_ROUTE_TOTAL]++;
2136 				fib_cnt[re->type]++;
2137 			}
2138 			for (nexthop = re->nhe->nhg.nexthop; (!cnt && nexthop);
2139 			     nexthop = nexthop->next) {
2140 				cnt++;
2141 				rib_cnt[ZEBRA_ROUTE_TOTAL]++;
2142 				rib_cnt[re->type]++;
2143 				if (re->type == ZEBRA_ROUTE_BGP
2144 				    && CHECK_FLAG(re->flags, ZEBRA_FLAG_IBGP)) {
2145 					rib_cnt[ZEBRA_ROUTE_IBGP]++;
2146 					if (CHECK_FLAG(re->status,
2147 						       ROUTE_ENTRY_INSTALLED))
2148 						fib_cnt[ZEBRA_ROUTE_IBGP]++;
2149 				}
2150 			}
2151 		}
2152 
2153 	if (!use_json)
2154 		vty_out(vty, "%-20s %-20s %s  (vrf %s)\n", "Route Source",
2155 			"Prefix Routes", "FIB",
2156 			zvrf_name(((struct rib_table_info *)
2157 					   route_table_get_info(table))
2158 					  ->zvrf));
2159 
2160 	for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
2161 		if (rib_cnt[i] > 0) {
2162 			if (i == ZEBRA_ROUTE_BGP) {
2163 				if (use_json) {
2164 					json_object *json_route_ebgp =
2165 						json_object_new_object();
2166 
2167 					json_object_int_add(
2168 						json_route_ebgp, "fib",
2169 						fib_cnt[ZEBRA_ROUTE_BGP]
2170 							- fib_cnt[ZEBRA_ROUTE_IBGP]);
2171 					json_object_int_add(
2172 						json_route_ebgp, "rib",
2173 						rib_cnt[ZEBRA_ROUTE_BGP]
2174 							- rib_cnt[ZEBRA_ROUTE_IBGP]);
2175 					json_object_string_add(json_route_ebgp,
2176 							       "type", "ebgp");
2177 					json_object_array_add(json_route_routes,
2178 							      json_route_ebgp);
2179 
2180 					json_object *json_route_ibgp =
2181 						json_object_new_object();
2182 
2183 					json_object_int_add(
2184 						json_route_ibgp, "fib",
2185 						fib_cnt[ZEBRA_ROUTE_IBGP]);
2186 					json_object_int_add(
2187 						json_route_ibgp, "rib",
2188 						rib_cnt[ZEBRA_ROUTE_IBGP]);
2189 					json_object_string_add(json_route_ibgp,
2190 							       "type", "ibgp");
2191 					json_object_array_add(json_route_routes,
2192 							      json_route_ibgp);
2193 				} else {
2194 					vty_out(vty, "%-20s %-20d %-20d \n",
2195 						"ebgp",
2196 						rib_cnt[ZEBRA_ROUTE_BGP]
2197 							- rib_cnt[ZEBRA_ROUTE_IBGP],
2198 						fib_cnt[ZEBRA_ROUTE_BGP]
2199 							- fib_cnt[ZEBRA_ROUTE_IBGP]);
2200 					vty_out(vty, "%-20s %-20d %-20d \n",
2201 						"ibgp",
2202 						rib_cnt[ZEBRA_ROUTE_IBGP],
2203 						fib_cnt[ZEBRA_ROUTE_IBGP]);
2204 				}
2205 			} else {
2206 				if (use_json) {
2207 					json_object *json_route_type =
2208 						json_object_new_object();
2209 
2210 					json_object_int_add(json_route_type,
2211 							    "fib", fib_cnt[i]);
2212 					json_object_int_add(json_route_type,
2213 							    "rib", rib_cnt[i]);
2214 					json_object_string_add(
2215 						json_route_type, "type",
2216 						zebra_route_string(i));
2217 					json_object_array_add(json_route_routes,
2218 							      json_route_type);
2219 				} else
2220 					vty_out(vty, "%-20s %-20d %-20d \n",
2221 						zebra_route_string(i),
2222 						rib_cnt[i], fib_cnt[i]);
2223 			}
2224 		}
2225 	}
2226 
2227 	if (use_json) {
2228 		json_object_int_add(json_route_summary, "prefixRoutesTotal",
2229 				    rib_cnt[ZEBRA_ROUTE_TOTAL]);
2230 		json_object_int_add(json_route_summary, "prefixRoutesTotalFib",
2231 				    fib_cnt[ZEBRA_ROUTE_TOTAL]);
2232 
2233 		vty_out(vty, "%s\n",
2234 			json_object_to_json_string_ext(
2235 				json_route_summary, JSON_C_TO_STRING_PRETTY));
2236 		json_object_free(json_route_summary);
2237 	} else {
2238 		vty_out(vty, "------\n");
2239 		vty_out(vty, "%-20s %-20d %-20d \n", "Totals",
2240 			rib_cnt[ZEBRA_ROUTE_TOTAL], fib_cnt[ZEBRA_ROUTE_TOTAL]);
2241 		vty_out(vty, "\n");
2242 	}
2243 }
2244 
2245 /*
2246  * Show IPv6 mroute command.Used to dump
2247  * the Multicast routing table.
2248  */
2249 DEFUN (show_ipv6_mroute,
2250        show_ipv6_mroute_cmd,
2251        "show ipv6 mroute [vrf NAME]",
2252        SHOW_STR
2253        IP_STR
2254        "IPv6 Multicast routing table\n"
2255        VRF_CMD_HELP_STR)
2256 {
2257 	struct route_table *table;
2258 	struct route_node *rn;
2259 	struct route_entry *re;
2260 	int first = 1;
2261 	vrf_id_t vrf_id = VRF_DEFAULT;
2262 
2263 	if (argc == 5)
2264 		VRF_GET_ID(vrf_id, argv[4]->arg, false);
2265 
2266 	table = zebra_vrf_table(AFI_IP6, SAFI_MULTICAST, vrf_id);
2267 	if (!table)
2268 		return CMD_SUCCESS;
2269 
2270 	/* Show all IPv6 route. */
2271 	for (rn = route_top(table); rn; rn = srcdest_route_next(rn))
RNODE_FOREACH_RE(rn,re)2272 		RNODE_FOREACH_RE (rn, re) {
2273 			if (first) {
2274 				vty_out(vty, SHOW_ROUTE_V6_HEADER);
2275 				first = 0;
2276 			}
2277 			vty_show_ip_route(vty, rn, re, NULL, false);
2278 		}
2279 	return CMD_SUCCESS;
2280 }
2281 
2282 DEFUN (show_ipv6_mroute_vrf_all,
2283        show_ipv6_mroute_vrf_all_cmd,
2284        "show ipv6 mroute vrf all",
2285        SHOW_STR
2286        IP_STR
2287        "IPv6 Multicast routing table\n"
2288        VRF_ALL_CMD_HELP_STR)
2289 {
2290 	struct route_table *table;
2291 	struct route_node *rn;
2292 	struct route_entry *re;
2293 	struct vrf *vrf;
2294 	struct zebra_vrf *zvrf;
2295 	int first = 1;
2296 
2297 	RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
2298 		if ((zvrf = vrf->info) == NULL
2299 		    || (table = zvrf->table[AFI_IP6][SAFI_MULTICAST]) == NULL)
2300 			continue;
2301 
2302 		/* Show all IPv6 route. */
2303 		for (rn = route_top(table); rn; rn = srcdest_route_next(rn))
RNODE_FOREACH_RE(rn,re)2304 			RNODE_FOREACH_RE (rn, re) {
2305 				if (first) {
2306 					vty_out(vty, SHOW_ROUTE_V6_HEADER);
2307 					first = 0;
2308 				}
2309 				vty_show_ip_route(vty, rn, re, NULL, false);
2310 			}
2311 	}
2312 	return CMD_SUCCESS;
2313 }
2314 
2315 DEFUN (allow_external_route_update,
2316        allow_external_route_update_cmd,
2317        "allow-external-route-update",
2318        "Allow FRR routes to be overwritten by external processes\n")
2319 {
2320 	allow_delete = 1;
2321 
2322 	return CMD_SUCCESS;
2323 }
2324 
2325 DEFUN (no_allow_external_route_update,
2326        no_allow_external_route_update_cmd,
2327        "no allow-external-route-update",
2328        NO_STR
2329        "Allow FRR routes to be overwritten by external processes\n")
2330 {
2331 	allow_delete = 0;
2332 
2333 	return CMD_SUCCESS;
2334 }
2335 
2336 /* show vrf */
2337 DEFUN (show_vrf,
2338        show_vrf_cmd,
2339        "show vrf",
2340        SHOW_STR
2341        "VRF\n")
2342 {
2343 	struct vrf *vrf;
2344 	struct zebra_vrf *zvrf;
2345 
2346 	if (vrf_is_backend_netns())
2347 		vty_out(vty, "netns-based vrfs\n");
2348 
2349 	RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
2350 		if (!(zvrf = vrf->info))
2351 			continue;
2352 		if (zvrf_id(zvrf) == VRF_DEFAULT)
2353 			continue;
2354 
2355 		vty_out(vty, "vrf %s ", zvrf_name(zvrf));
2356 		if (zvrf_id(zvrf) == VRF_UNKNOWN || !zvrf_is_active(zvrf))
2357 			vty_out(vty, "inactive");
2358 		else if (zvrf_ns_name(zvrf))
2359 			vty_out(vty, "id %u netns %s", zvrf_id(zvrf),
2360 				zvrf_ns_name(zvrf));
2361 		else
2362 			vty_out(vty, "id %u table %u", zvrf_id(zvrf),
2363 				zvrf->table_id);
2364 		if (vrf_is_user_cfged(vrf))
2365 			vty_out(vty, " (configured)");
2366 		vty_out(vty, "\n");
2367 	}
2368 
2369 	return CMD_SUCCESS;
2370 }
2371 
2372 DEFUN (default_vrf_vni_mapping,
2373        default_vrf_vni_mapping_cmd,
2374        "vni " CMD_VNI_RANGE "[prefix-routes-only]",
2375        "VNI corresponding to the DEFAULT VRF\n"
2376        "VNI-ID\n"
2377        "Prefix routes only \n")
2378 {
2379 	int ret = 0;
2380 	char err[ERR_STR_SZ];
2381 	struct zebra_vrf *zvrf = NULL;
2382 	vni_t vni = strtoul(argv[1]->arg, NULL, 10);
2383 	int filter = 0;
2384 
2385 	zvrf = vrf_info_lookup(VRF_DEFAULT);
2386 	if (!zvrf)
2387 		return CMD_WARNING;
2388 
2389 	if (argc == 3)
2390 		filter = 1;
2391 
2392 	ret = zebra_vxlan_process_vrf_vni_cmd(zvrf, vni, err, ERR_STR_SZ,
2393 					      filter, 1);
2394 	if (ret != 0) {
2395 		vty_out(vty, "%s\n", err);
2396 		return CMD_WARNING;
2397 	}
2398 
2399 	return CMD_SUCCESS;
2400 }
2401 
2402 DEFUN (no_default_vrf_vni_mapping,
2403        no_default_vrf_vni_mapping_cmd,
2404        "no vni " CMD_VNI_RANGE,
2405        NO_STR
2406        "VNI corresponding to DEFAULT VRF\n"
2407        "VNI-ID")
2408 {
2409 	int ret = 0;
2410 	char err[ERR_STR_SZ];
2411 	vni_t vni = strtoul(argv[2]->arg, NULL, 10);
2412 	struct zebra_vrf *zvrf = NULL;
2413 
2414 	zvrf = vrf_info_lookup(VRF_DEFAULT);
2415 	if (!zvrf)
2416 		return CMD_WARNING;
2417 
2418 	ret = zebra_vxlan_process_vrf_vni_cmd(zvrf, vni, err, ERR_STR_SZ, 0, 0);
2419 	if (ret != 0) {
2420 		vty_out(vty, "%s\n", err);
2421 		return CMD_WARNING;
2422 	}
2423 
2424 	return CMD_SUCCESS;
2425 }
2426 
2427 DEFUN (vrf_vni_mapping,
2428        vrf_vni_mapping_cmd,
2429        "vni " CMD_VNI_RANGE "[prefix-routes-only]",
2430        "VNI corresponding to tenant VRF\n"
2431        "VNI-ID\n"
2432        "prefix-routes-only\n")
2433 {
2434 	int filter = 0;
2435 
2436 	ZEBRA_DECLVAR_CONTEXT(vrf, zvrf);
2437 
2438 	assert(vrf);
2439 	assert(zvrf);
2440 
2441 	if (argc == 3)
2442 		filter = 1;
2443 
2444 	nb_cli_enqueue_change(vty, "./frr-zebra:zebra", NB_OP_CREATE, NULL);
2445 	nb_cli_enqueue_change(vty, "./frr-zebra:zebra/l3vni-id", NB_OP_MODIFY,
2446 			      argv[1]->arg);
2447 
2448 	if (filter)
2449 		nb_cli_enqueue_change(vty, "./frr-zebra:zebra/prefix-only",
2450 				      NB_OP_MODIFY, "true");
2451 
2452 	nb_cli_apply_changes(vty, NULL);
2453 
2454 	return CMD_SUCCESS;
2455 }
2456 
2457 DEFUN (no_vrf_vni_mapping,
2458        no_vrf_vni_mapping_cmd,
2459        "no vni " CMD_VNI_RANGE "[prefix-routes-only]",
2460        NO_STR
2461        "VNI corresponding to tenant VRF\n"
2462        "VNI-ID\n"
2463        "prefix-routes-only\n")
2464 {
2465 	int filter = 0;
2466 
2467 	ZEBRA_DECLVAR_CONTEXT(vrf, zvrf);
2468 	vni_t vni = strtoul(argv[2]->arg, NULL, 10);
2469 
2470 	assert(vrf);
2471 	assert(zvrf);
2472 
2473 	if (argc == 4)
2474 		filter = 1;
2475 
2476 	if (zvrf->l3vni != vni) {
2477 		vty_out(vty, "VNI %d doesn't exist in VRF: %s \n", vni,
2478 			zvrf->vrf->name);
2479 		return CMD_WARNING;
2480 	}
2481 
2482 	nb_cli_enqueue_change(vty, "./frr-zebra:zebra/l3vni-id", NB_OP_DESTROY,
2483 			      argv[2]->arg);
2484 
2485 	if (filter)
2486 		nb_cli_enqueue_change(vty, "./frr-zebra:zebra/prefix-only",
2487 				      NB_OP_DESTROY, "true");
2488 
2489 	nb_cli_enqueue_change(vty, "./frr-zebra:zebra", NB_OP_DESTROY, NULL);
2490 
2491 	nb_cli_apply_changes(vty, NULL);
2492 
2493 	return CMD_SUCCESS;
2494 }
2495 
2496 /* show vrf */
2497 DEFUN (show_vrf_vni,
2498        show_vrf_vni_cmd,
2499        "show vrf vni [json]",
2500        SHOW_STR
2501        "VRF\n"
2502        "VNI\n"
2503        JSON_STR)
2504 {
2505 	struct vrf *vrf;
2506 	struct zebra_vrf *zvrf;
2507 	json_object *json = NULL;
2508 	json_object *json_vrfs = NULL;
2509 	bool uj = use_json(argc, argv);
2510 
2511 	if (uj) {
2512 		json = json_object_new_object();
2513 		json_vrfs = json_object_new_array();
2514 	}
2515 
2516 	if (!uj)
2517 		vty_out(vty, "%-37s %-10s %-20s %-20s %-5s %-18s\n", "VRF",
2518 			"VNI", "VxLAN IF", "L3-SVI", "State", "Rmac");
2519 
2520 	RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
2521 		zvrf = vrf->info;
2522 		if (!zvrf)
2523 			continue;
2524 
2525 		zebra_vxlan_print_vrf_vni(vty, zvrf, json_vrfs);
2526 	}
2527 
2528 	if (uj) {
2529 		json_object_object_add(json, "vrfs", json_vrfs);
2530 		vty_out(vty, "%s\n", json_object_to_json_string_ext(
2531 					     json, JSON_C_TO_STRING_PRETTY));
2532 		json_object_free(json);
2533 	}
2534 
2535 	return CMD_SUCCESS;
2536 }
2537 
2538 DEFUN (show_evpn_global,
2539        show_evpn_global_cmd,
2540        "show evpn [json]",
2541        SHOW_STR
2542        "EVPN\n"
2543        JSON_STR)
2544 {
2545 	bool uj = use_json(argc, argv);
2546 
2547 	zebra_vxlan_print_evpn(vty, uj);
2548 	return CMD_SUCCESS;
2549 }
2550 
2551 DEFPY(show_evpn_es,
2552       show_evpn_es_cmd,
2553       "show evpn es [NAME$esi_str] [json$json] [detail$detail]",
2554       SHOW_STR
2555       "EVPN\n"
2556       "Ethernet Segment\n"
2557       "ES ID\n"
2558       JSON_STR
2559       "Detailed information\n")
2560 {
2561 	esi_t esi;
2562 	bool uj = !!json;
2563 
2564 	if (esi_str) {
2565 		if (!str_to_esi(esi_str, &esi)) {
2566 			vty_out(vty, "%% Malformed ESI\n");
2567 			return CMD_WARNING;
2568 		}
2569 		zebra_evpn_es_show_esi(vty, uj, &esi);
2570 	} else {
2571 		if (detail)
2572 			zebra_evpn_es_show_detail(vty, uj);
2573 		else
2574 			zebra_evpn_es_show(vty, uj);
2575 	}
2576 
2577 	return CMD_SUCCESS;
2578 }
2579 
2580 DEFPY(show_evpn_es_evi,
2581       show_evpn_es_evi_cmd,
2582       "show evpn es-evi [vni (1-16777215)$vni] [json$json] [detail$detail]",
2583       SHOW_STR
2584       "EVPN\n"
2585       "Ethernet Segment per EVI\n"
2586       "VxLAN Network Identifier\n"
2587       "VNI\n"
2588       JSON_STR
2589       "Detailed information\n")
2590 {
2591 	bool uj = !!json;
2592 	bool ud = !!detail;
2593 
2594 	if (vni)
2595 		zebra_evpn_es_evi_show_vni(vty, uj, vni, ud);
2596 	else
2597 		zebra_evpn_es_evi_show(vty, uj, ud);
2598 
2599 	return CMD_SUCCESS;
2600 }
2601 
2602 DEFPY(show_evpn_access_vlan,
2603       show_evpn_access_vlan_cmd,
2604       "show evpn access-vlan [(1-4094)$vid] [json$json] [detail$detail]",
2605       SHOW_STR
2606       "EVPN\n"
2607       "Access VLANs\n"
2608       "VLAN ID\n"
2609       JSON_STR
2610       "Detailed information\n")
2611 {
2612 	bool uj = !!json;
2613 
2614 	if (vid) {
2615 		zebra_evpn_acc_vl_show_vid(vty, uj, vid);
2616 	} else {
2617 		if (detail)
2618 			zebra_evpn_acc_vl_show_detail(vty, uj);
2619 		else
2620 			zebra_evpn_acc_vl_show(vty, uj);
2621 	}
2622 
2623 	return CMD_SUCCESS;
2624 }
2625 
2626 DEFUN (show_evpn_vni,
2627        show_evpn_vni_cmd,
2628        "show evpn vni [json]",
2629        SHOW_STR
2630        "EVPN\n"
2631        "VxLAN Network Identifier\n"
2632        JSON_STR)
2633 {
2634 	struct zebra_vrf *zvrf;
2635 	bool uj = use_json(argc, argv);
2636 
2637 	zvrf = zebra_vrf_get_evpn();
2638 	zebra_vxlan_print_vnis(vty, zvrf, uj);
2639 	return CMD_SUCCESS;
2640 }
2641 
2642 DEFUN (show_evpn_vni_detail, show_evpn_vni_detail_cmd,
2643        "show evpn vni detail [json]",
2644        SHOW_STR
2645        "EVPN\n"
2646        "VxLAN Network Identifier\n"
2647        "Detailed Information On Each VNI\n"
2648        JSON_STR)
2649 {
2650 	struct zebra_vrf *zvrf;
2651 	bool uj = use_json(argc, argv);
2652 
2653 	zvrf = zebra_vrf_get_evpn();
2654 	zebra_vxlan_print_vnis_detail(vty, zvrf, uj);
2655 	return CMD_SUCCESS;
2656 }
2657 
2658 DEFUN (show_evpn_vni_vni,
2659        show_evpn_vni_vni_cmd,
2660        "show evpn vni " CMD_VNI_RANGE "[json]",
2661        SHOW_STR
2662        "EVPN\n"
2663        "VxLAN Network Identifier\n"
2664        "VNI number\n"
2665        JSON_STR)
2666 {
2667 	struct zebra_vrf *zvrf;
2668 	vni_t vni;
2669 	bool uj = use_json(argc, argv);
2670 
2671 	vni = strtoul(argv[3]->arg, NULL, 10);
2672 	zvrf = zebra_vrf_get_evpn();
2673 	zebra_vxlan_print_vni(vty, zvrf, vni, uj, NULL);
2674 	return CMD_SUCCESS;
2675 }
2676 
2677 DEFUN (show_evpn_rmac_vni_mac,
2678        show_evpn_rmac_vni_mac_cmd,
2679        "show evpn rmac vni " CMD_VNI_RANGE " mac WORD [json]",
2680        SHOW_STR
2681        "EVPN\n"
2682        "RMAC\n"
2683        "L3 VNI\n"
2684        "VNI number\n"
2685        "MAC\n"
2686        "mac-address (e.g. 0a:0a:0a:0a:0a:0a)\n"
2687        JSON_STR)
2688 {
2689 	vni_t l3vni = 0;
2690 	struct ethaddr mac;
2691 	bool uj = use_json(argc, argv);
2692 
2693 	l3vni = strtoul(argv[4]->arg, NULL, 10);
2694 	if (!prefix_str2mac(argv[6]->arg, &mac)) {
2695 		vty_out(vty, "%% Malformed MAC address\n");
2696 		return CMD_WARNING;
2697 	}
2698 	zebra_vxlan_print_specific_rmac_l3vni(vty, l3vni, &mac, uj);
2699 	return CMD_SUCCESS;
2700 }
2701 
2702 DEFUN (show_evpn_rmac_vni,
2703        show_evpn_rmac_vni_cmd,
2704        "show evpn rmac vni " CMD_VNI_RANGE "[json]",
2705        SHOW_STR
2706        "EVPN\n"
2707        "RMAC\n"
2708        "L3 VNI\n"
2709        "VNI number\n"
2710        JSON_STR)
2711 {
2712 	vni_t l3vni = 0;
2713 	bool uj = use_json(argc, argv);
2714 
2715 	l3vni = strtoul(argv[4]->arg, NULL, 10);
2716 	zebra_vxlan_print_rmacs_l3vni(vty, l3vni, uj);
2717 
2718 	return CMD_SUCCESS;
2719 }
2720 
2721 DEFUN (show_evpn_rmac_vni_all,
2722        show_evpn_rmac_vni_all_cmd,
2723        "show evpn rmac vni all [json]",
2724        SHOW_STR
2725        "EVPN\n"
2726        "RMAC addresses\n"
2727        "L3 VNI\n"
2728        "All VNIs\n"
2729        JSON_STR)
2730 {
2731 	bool uj = use_json(argc, argv);
2732 
2733 	zebra_vxlan_print_rmacs_all_l3vni(vty, uj);
2734 
2735 	return CMD_SUCCESS;
2736 }
2737 
2738 DEFUN (show_evpn_nh_vni_ip,
2739        show_evpn_nh_vni_ip_cmd,
2740        "show evpn next-hops vni " CMD_VNI_RANGE " ip WORD [json]",
2741        SHOW_STR
2742        "EVPN\n"
2743        "Remote Vteps\n"
2744        "L3 VNI\n"
2745        "VNI number\n"
2746        "Ip address\n"
2747        "Host address (ipv4 or ipv6)\n"
2748        JSON_STR)
2749 {
2750 	vni_t l3vni;
2751 	struct ipaddr ip;
2752 	bool uj = use_json(argc, argv);
2753 
2754 	l3vni = strtoul(argv[4]->arg, NULL, 10);
2755 	if (str2ipaddr(argv[6]->arg, &ip) != 0) {
2756 		if (!uj)
2757 			vty_out(vty, "%% Malformed Neighbor address\n");
2758 		return CMD_WARNING;
2759 	}
2760 	zebra_vxlan_print_specific_nh_l3vni(vty, l3vni, &ip, uj);
2761 
2762 	return CMD_SUCCESS;
2763 }
2764 
2765 DEFUN (show_evpn_nh_vni,
2766        show_evpn_nh_vni_cmd,
2767        "show evpn next-hops vni " CMD_VNI_RANGE "[json]",
2768        SHOW_STR
2769        "EVPN\n"
2770        "Remote Vteps\n"
2771        "L3 VNI\n"
2772        "VNI number\n"
2773        JSON_STR)
2774 {
2775 	vni_t l3vni;
2776 	bool uj = use_json(argc, argv);
2777 
2778 	l3vni = strtoul(argv[4]->arg, NULL, 10);
2779 	zebra_vxlan_print_nh_l3vni(vty, l3vni, uj);
2780 
2781 	return CMD_SUCCESS;
2782 }
2783 
2784 DEFUN (show_evpn_nh_vni_all,
2785        show_evpn_nh_vni_all_cmd,
2786        "show evpn next-hops vni all [json]",
2787        SHOW_STR
2788        "EVPN\n"
2789        "Remote VTEPs\n"
2790        "L3 VNI\n"
2791        "All VNIs\n"
2792        JSON_STR)
2793 {
2794 	bool uj = use_json(argc, argv);
2795 
2796 	zebra_vxlan_print_nh_all_l3vni(vty, uj);
2797 
2798 	return CMD_SUCCESS;
2799 }
2800 
2801 DEFUN (show_evpn_mac_vni,
2802        show_evpn_mac_vni_cmd,
2803        "show evpn mac vni " CMD_VNI_RANGE "[json]",
2804        SHOW_STR
2805        "EVPN\n"
2806        "MAC addresses\n"
2807        "VxLAN Network Identifier\n"
2808        "VNI number\n"
2809        JSON_STR)
2810 {
2811 	struct zebra_vrf *zvrf;
2812 	vni_t vni;
2813 	bool uj = use_json(argc, argv);
2814 
2815 	vni = strtoul(argv[4]->arg, NULL, 10);
2816 	zvrf = zebra_vrf_get_evpn();
2817 	zebra_vxlan_print_macs_vni(vty, zvrf, vni, uj);
2818 	return CMD_SUCCESS;
2819 }
2820 
2821 DEFUN (show_evpn_mac_vni_all,
2822        show_evpn_mac_vni_all_cmd,
2823        "show evpn mac vni all [json]",
2824        SHOW_STR
2825        "EVPN\n"
2826        "MAC addresses\n"
2827        "VxLAN Network Identifier\n"
2828        "All VNIs\n"
2829        JSON_STR)
2830 {
2831 	struct zebra_vrf *zvrf;
2832 	bool uj = use_json(argc, argv);
2833 
2834 	zvrf = zebra_vrf_get_evpn();
2835 	zebra_vxlan_print_macs_all_vni(vty, zvrf, false, uj);
2836 	return CMD_SUCCESS;
2837 }
2838 
2839 DEFUN (show_evpn_mac_vni_all_detail, show_evpn_mac_vni_all_detail_cmd,
2840        "show evpn mac vni all detail [json]",
2841        SHOW_STR
2842        "EVPN\n"
2843        "MAC addresses\n"
2844        "VxLAN Network Identifier\n"
2845        "All VNIs\n"
2846        "Detailed Information On Each VNI MAC\n"
2847        JSON_STR)
2848 {
2849 	struct zebra_vrf *zvrf;
2850 	bool uj = use_json(argc, argv);
2851 
2852 	zvrf = zebra_vrf_get_evpn();
2853 	zebra_vxlan_print_macs_all_vni_detail(vty, zvrf, false, uj);
2854 	return CMD_SUCCESS;
2855 }
2856 
2857 DEFUN (show_evpn_mac_vni_all_vtep,
2858        show_evpn_mac_vni_all_vtep_cmd,
2859        "show evpn mac vni all vtep A.B.C.D [json]",
2860        SHOW_STR
2861        "EVPN\n"
2862        "MAC addresses\n"
2863        "VxLAN Network Identifier\n"
2864        "All VNIs\n"
2865        "Remote VTEP\n"
2866        "Remote VTEP IP address\n"
2867        JSON_STR)
2868 {
2869 	struct zebra_vrf *zvrf;
2870 	struct in_addr vtep_ip;
2871 	bool uj = use_json(argc, argv);
2872 
2873 	if (!inet_aton(argv[6]->arg, &vtep_ip)) {
2874 		if (!uj)
2875 			vty_out(vty, "%% Malformed VTEP IP address\n");
2876 		return CMD_WARNING;
2877 	}
2878 	zvrf = zebra_vrf_get_evpn();
2879 	zebra_vxlan_print_macs_all_vni_vtep(vty, zvrf, vtep_ip, uj);
2880 
2881 	return CMD_SUCCESS;
2882 }
2883 
2884 
2885 DEFUN (show_evpn_mac_vni_mac,
2886        show_evpn_mac_vni_mac_cmd,
2887        "show evpn mac vni " CMD_VNI_RANGE " mac WORD [json]",
2888        SHOW_STR
2889        "EVPN\n"
2890        "MAC addresses\n"
2891        "VxLAN Network Identifier\n"
2892        "VNI number\n"
2893        "MAC\n"
2894        "MAC address (e.g., 00:e0:ec:20:12:62)\n"
2895        JSON_STR)
2896 
2897 {
2898 	struct zebra_vrf *zvrf;
2899 	vni_t vni;
2900 	struct ethaddr mac;
2901 	bool uj = use_json(argc, argv);
2902 
2903 	vni = strtoul(argv[4]->arg, NULL, 10);
2904 	if (!prefix_str2mac(argv[6]->arg, &mac)) {
2905 		vty_out(vty, "%% Malformed MAC address");
2906 		return CMD_WARNING;
2907 	}
2908 	zvrf = zebra_vrf_get_evpn();
2909 	zebra_vxlan_print_specific_mac_vni(vty, zvrf, vni, &mac, uj);
2910 	return CMD_SUCCESS;
2911 }
2912 
2913 DEFUN (show_evpn_mac_vni_vtep,
2914        show_evpn_mac_vni_vtep_cmd,
2915        "show evpn mac vni " CMD_VNI_RANGE " vtep A.B.C.D" "[json]",
2916        SHOW_STR
2917        "EVPN\n"
2918        "MAC addresses\n"
2919        "VxLAN Network Identifier\n"
2920        "VNI number\n"
2921        "Remote VTEP\n"
2922        "Remote VTEP IP address\n"
2923        JSON_STR)
2924 {
2925 	struct zebra_vrf *zvrf;
2926 	vni_t vni;
2927 	struct in_addr vtep_ip;
2928 	bool uj = use_json(argc, argv);
2929 
2930 	vni = strtoul(argv[4]->arg, NULL, 10);
2931 	if (!inet_aton(argv[6]->arg, &vtep_ip)) {
2932 		if (!uj)
2933 			vty_out(vty, "%% Malformed VTEP IP address\n");
2934 		return CMD_WARNING;
2935 	}
2936 
2937 	zvrf = zebra_vrf_get_evpn();
2938 	zebra_vxlan_print_macs_vni_vtep(vty, zvrf, vni, vtep_ip, uj);
2939 	return CMD_SUCCESS;
2940 }
2941 
2942 DEFPY (show_evpn_mac_vni_all_dad,
2943        show_evpn_mac_vni_all_dad_cmd,
2944        "show evpn mac vni all duplicate [json]",
2945        SHOW_STR
2946        "EVPN\n"
2947        "MAC addresses\n"
2948        "VxLAN Network Identifier\n"
2949        "All VNIs\n"
2950        "Duplicate address list\n"
2951        JSON_STR)
2952 {
2953 	struct zebra_vrf *zvrf;
2954 	bool uj = use_json(argc, argv);
2955 
2956 	zvrf = zebra_vrf_get_evpn();
2957 	zebra_vxlan_print_macs_all_vni(vty, zvrf, true, uj);
2958 	return CMD_SUCCESS;
2959 }
2960 
2961 
2962 DEFPY (show_evpn_mac_vni_dad,
2963        show_evpn_mac_vni_dad_cmd,
2964        "show evpn mac vni " CMD_VNI_RANGE " duplicate [json]",
2965        SHOW_STR
2966        "EVPN\n"
2967        "MAC addresses\n"
2968        "VxLAN Network Identifier\n"
2969        "VNI number\n"
2970        "Duplicate address list\n"
2971        JSON_STR)
2972 {
2973 	struct zebra_vrf *zvrf;
2974 	bool uj = use_json(argc, argv);
2975 
2976 	zvrf = zebra_vrf_get_evpn();
2977 
2978 	zebra_vxlan_print_macs_vni_dad(vty, zvrf, vni, uj);
2979 
2980 	return CMD_SUCCESS;
2981 }
2982 
2983 DEFPY (show_evpn_neigh_vni_dad,
2984        show_evpn_neigh_vni_dad_cmd,
2985        "show evpn arp-cache vni " CMD_VNI_RANGE "duplicate [json]",
2986        SHOW_STR
2987        "EVPN\n"
2988        "ARP and ND cache\n"
2989        "VxLAN Network Identifier\n"
2990        "VNI number\n"
2991        "Duplicate address list\n"
2992        JSON_STR)
2993 {
2994 	struct zebra_vrf *zvrf;
2995 	bool uj = use_json(argc, argv);
2996 
2997 	zvrf = zebra_vrf_get_evpn();
2998 	zebra_vxlan_print_neigh_vni_dad(vty, zvrf, vni, uj);
2999 	return CMD_SUCCESS;
3000 }
3001 
3002 DEFPY (show_evpn_neigh_vni_all_dad,
3003        show_evpn_neigh_vni_all_dad_cmd,
3004        "show evpn arp-cache vni all duplicate [json]",
3005        SHOW_STR
3006        "EVPN\n"
3007        "ARP and ND cache\n"
3008        "VxLAN Network Identifier\n"
3009        "All VNIs\n"
3010        "Duplicate address list\n"
3011        JSON_STR)
3012 {
3013 	struct zebra_vrf *zvrf;
3014 	bool uj = use_json(argc, argv);
3015 
3016 	zvrf = zebra_vrf_get_evpn();
3017 	zebra_vxlan_print_neigh_all_vni(vty, zvrf, true, uj);
3018 	return CMD_SUCCESS;
3019 }
3020 
3021 
3022 DEFUN (show_evpn_neigh_vni,
3023        show_evpn_neigh_vni_cmd,
3024        "show evpn arp-cache vni " CMD_VNI_RANGE "[json]",
3025        SHOW_STR
3026        "EVPN\n"
3027        "ARP and ND cache\n"
3028        "VxLAN Network Identifier\n"
3029        "VNI number\n"
3030        JSON_STR)
3031 {
3032 	struct zebra_vrf *zvrf;
3033 	vni_t vni;
3034 	bool uj = use_json(argc, argv);
3035 
3036 	vni = strtoul(argv[4]->arg, NULL, 10);
3037 	zvrf = zebra_vrf_get_evpn();
3038 	zebra_vxlan_print_neigh_vni(vty, zvrf, vni, uj);
3039 	return CMD_SUCCESS;
3040 }
3041 
3042 DEFUN (show_evpn_neigh_vni_all,
3043        show_evpn_neigh_vni_all_cmd,
3044        "show evpn arp-cache vni all [json]",
3045        SHOW_STR
3046        "EVPN\n"
3047        "ARP and ND cache\n"
3048        "VxLAN Network Identifier\n"
3049        "All VNIs\n"
3050        JSON_STR)
3051 {
3052 	struct zebra_vrf *zvrf;
3053 	bool uj = use_json(argc, argv);
3054 
3055 	zvrf = zebra_vrf_get_evpn();
3056 	zebra_vxlan_print_neigh_all_vni(vty, zvrf, false, uj);
3057 	return CMD_SUCCESS;
3058 }
3059 
3060 DEFUN (show_evpn_neigh_vni_all_detail, show_evpn_neigh_vni_all_detail_cmd,
3061        "show evpn arp-cache vni all detail [json]",
3062        SHOW_STR
3063        "EVPN\n"
3064        "ARP and ND cache\n"
3065        "VxLAN Network Identifier\n"
3066        "All VNIs\n"
3067        "Neighbor details for all vnis in detail\n" JSON_STR)
3068 {
3069 	struct zebra_vrf *zvrf;
3070 	bool uj = use_json(argc, argv);
3071 
3072 	zvrf = zebra_vrf_get_evpn();
3073 	zebra_vxlan_print_neigh_all_vni_detail(vty, zvrf, false, uj);
3074 	return CMD_SUCCESS;
3075 }
3076 
3077 DEFUN (show_evpn_neigh_vni_neigh,
3078        show_evpn_neigh_vni_neigh_cmd,
3079        "show evpn arp-cache vni " CMD_VNI_RANGE " ip WORD [json]",
3080        SHOW_STR
3081        "EVPN\n"
3082        "ARP and ND cache\n"
3083        "VxLAN Network Identifier\n"
3084        "VNI number\n"
3085        "Neighbor\n"
3086        "Neighbor address (IPv4 or IPv6 address)\n"
3087        JSON_STR)
3088 {
3089 	struct zebra_vrf *zvrf;
3090 	vni_t vni;
3091 	struct ipaddr ip;
3092 	bool uj = use_json(argc, argv);
3093 
3094 	vni = strtoul(argv[4]->arg, NULL, 10);
3095 	if (str2ipaddr(argv[6]->arg, &ip) != 0) {
3096 		if (!uj)
3097 			vty_out(vty, "%% Malformed Neighbor address\n");
3098 		return CMD_WARNING;
3099 	}
3100 	zvrf = zebra_vrf_get_evpn();
3101 	zebra_vxlan_print_specific_neigh_vni(vty, zvrf, vni, &ip, uj);
3102 	return CMD_SUCCESS;
3103 }
3104 
3105 DEFUN (show_evpn_neigh_vni_vtep,
3106        show_evpn_neigh_vni_vtep_cmd,
3107        "show evpn arp-cache vni " CMD_VNI_RANGE " vtep A.B.C.D [json]",
3108        SHOW_STR
3109        "EVPN\n"
3110        "ARP and ND cache\n"
3111        "VxLAN Network Identifier\n"
3112        "VNI number\n"
3113        "Remote VTEP\n"
3114        "Remote VTEP IP address\n"
3115        JSON_STR)
3116 {
3117 	struct zebra_vrf *zvrf;
3118 	vni_t vni;
3119 	struct in_addr vtep_ip;
3120 	bool uj = use_json(argc, argv);
3121 
3122 	vni = strtoul(argv[4]->arg, NULL, 10);
3123 	if (!inet_aton(argv[6]->arg, &vtep_ip)) {
3124 		if (!uj)
3125 			vty_out(vty, "%% Malformed VTEP IP address\n");
3126 		return CMD_WARNING;
3127 	}
3128 
3129 	zvrf = zebra_vrf_get_evpn();
3130 	zebra_vxlan_print_neigh_vni_vtep(vty, zvrf, vni, vtep_ip, uj);
3131 	return CMD_SUCCESS;
3132 }
3133 
3134 /* policy routing contexts */
3135 DEFUN (show_pbr_ipset,
3136        show_pbr_ipset_cmd,
3137        "show pbr ipset [WORD]",
3138        SHOW_STR
3139        "Policy-Based Routing\n"
3140        "IPset Context information\n"
3141        "IPset Name information\n")
3142 {
3143 	int idx = 0;
3144 	int found = 0;
3145 	found = argv_find(argv, argc, "WORD", &idx);
3146 	if (!found)
3147 		zebra_pbr_show_ipset_list(vty, NULL);
3148 	else
3149 		zebra_pbr_show_ipset_list(vty, argv[idx]->arg);
3150 	return CMD_SUCCESS;
3151 }
3152 
3153 /* policy routing contexts */
3154 DEFUN (show_pbr_iptable,
3155        show_pbr_iptable_cmd,
3156        "show pbr iptable [WORD]",
3157        SHOW_STR
3158        "Policy-Based Routing\n"
3159        "IPtable Context information\n"
3160        "IPtable Name information\n")
3161 {
3162 	int idx = 0;
3163 	int found = 0;
3164 
3165 	found = argv_find(argv, argc, "WORD", &idx);
3166 	if (!found)
3167 		zebra_pbr_show_iptable(vty, NULL);
3168 	else
3169 		zebra_pbr_show_iptable(vty, argv[idx]->arg);
3170 	return CMD_SUCCESS;
3171 }
3172 
3173 DEFPY (clear_evpn_dup_addr,
3174        clear_evpn_dup_addr_cmd,
3175        "clear evpn dup-addr vni <all$vni_all |" CMD_VNI_RANGE"$vni [mac X:X:X:X:X:X | ip <A.B.C.D|X:X::X:X>]>",
3176        CLEAR_STR
3177        "EVPN\n"
3178        "Duplicate address \n"
3179        "VxLAN Network Identifier\n"
3180        "VNI number\n"
3181        "All VNIs\n"
3182        "MAC\n"
3183        "MAC address (e.g., 00:e0:ec:20:12:62)\n"
3184        "IP\n"
3185        "IPv4 address\n"
3186        "IPv6 address\n")
3187 {
3188 	struct ipaddr host_ip = {.ipa_type = IPADDR_NONE };
3189 	int ret = CMD_SUCCESS;
3190 	struct list *input;
3191 	struct yang_data *yang_dup = NULL, *yang_dup_ip = NULL,
3192 			 *yang_dup_mac = NULL;
3193 
3194 	input = list_new();
3195 
3196 	if (!vni_str) {
3197 		yang_dup = yang_data_new(
3198 			"/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice",
3199 			"all-case");
3200 	} else {
3201 		yang_dup = yang_data_new_uint32(
3202 			"/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice/single-case/vni-id",
3203 			vni);
3204 		if (!is_zero_mac(&mac->eth_addr)) {
3205 			yang_dup_mac = yang_data_new_mac(
3206 				"/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice/single-case/vni-id/mac-addr",
3207 				&mac->eth_addr);
3208 			if (yang_dup_mac)
3209 				listnode_add(input, yang_dup_mac);
3210 		} else if (ip) {
3211 			if (sockunion_family(ip) == AF_INET) {
3212 				host_ip.ipa_type = IPADDR_V4;
3213 				host_ip.ipaddr_v4.s_addr = sockunion2ip(ip);
3214 			} else {
3215 				host_ip.ipa_type = IPADDR_V6;
3216 				memcpy(&host_ip.ipaddr_v6, &ip->sin6.sin6_addr,
3217 				       sizeof(struct in6_addr));
3218 			}
3219 
3220 			yang_dup_ip = yang_data_new_ip(
3221 				"/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice/single-case/vni-id/vni-ipaddr",
3222 				&host_ip);
3223 
3224 			if (yang_dup_ip)
3225 				listnode_add(input, yang_dup_ip);
3226 		}
3227 	}
3228 
3229 	if (yang_dup) {
3230 		listnode_add(input, yang_dup);
3231 		ret = nb_cli_rpc("/frr-zebra:clear-evpn-dup-addr", input, NULL);
3232 	}
3233 
3234 	list_delete(&input);
3235 
3236 	return ret;
3237 }
3238 
3239 /* Static ip route configuration write function. */
zebra_ip_config(struct vty * vty)3240 static int zebra_ip_config(struct vty *vty)
3241 {
3242 	int write = 0;
3243 
3244 	write += zebra_import_table_config(vty, VRF_DEFAULT);
3245 
3246 	return write;
3247 }
3248 
3249 DEFUN (ip_zebra_import_table_distance,
3250        ip_zebra_import_table_distance_cmd,
3251        "ip import-table (1-252) [distance (1-255)] [route-map WORD]",
3252        IP_STR
3253        "import routes from non-main kernel table\n"
3254        "kernel routing table id\n"
3255        "Distance for imported routes\n"
3256        "Default distance value\n"
3257        "route-map for filtering\n"
3258        "route-map name\n")
3259 {
3260 	uint32_t table_id = 0;
3261 
3262 	table_id = strtoul(argv[2]->arg, NULL, 10);
3263 	int distance = ZEBRA_TABLE_DISTANCE_DEFAULT;
3264 	char *rmap =
3265 		strmatch(argv[argc - 2]->text, "route-map")
3266 			? XSTRDUP(MTYPE_ROUTE_MAP_NAME, argv[argc - 1]->arg)
3267 			: NULL;
3268 	int ret;
3269 
3270 	if (argc == 7 || (argc == 5 && !rmap))
3271 		distance = strtoul(argv[4]->arg, NULL, 10);
3272 
3273 	if (!is_zebra_valid_kernel_table(table_id)) {
3274 		vty_out(vty,
3275 			"Invalid routing table ID, %d. Must be in range 1-252\n",
3276 			table_id);
3277 		if (rmap)
3278 			XFREE(MTYPE_ROUTE_MAP_NAME, rmap);
3279 		return CMD_WARNING;
3280 	}
3281 
3282 	if (is_zebra_main_routing_table(table_id)) {
3283 		vty_out(vty,
3284 			"Invalid routing table ID, %d. Must be non-default table\n",
3285 			table_id);
3286 		if (rmap)
3287 			XFREE(MTYPE_ROUTE_MAP_NAME, rmap);
3288 		return CMD_WARNING;
3289 	}
3290 
3291 	ret = zebra_import_table(AFI_IP, VRF_DEFAULT, table_id,
3292 				 distance, rmap, 1);
3293 	if (rmap)
3294 		XFREE(MTYPE_ROUTE_MAP_NAME, rmap);
3295 
3296 	return ret;
3297 }
3298 
3299 DEFUN_HIDDEN (zebra_packet_process,
3300 	      zebra_packet_process_cmd,
3301 	      "zebra zapi-packets (1-10000)",
3302 	      ZEBRA_STR
3303 	      "Zapi Protocol\n"
3304 	      "Number of packets to process before relinquishing thread\n")
3305 {
3306 	uint32_t packets = strtoul(argv[2]->arg, NULL, 10);
3307 
3308 	atomic_store_explicit(&zrouter.packets_to_process, packets,
3309 			      memory_order_relaxed);
3310 
3311 	return CMD_SUCCESS;
3312 }
3313 
3314 DEFUN_HIDDEN (no_zebra_packet_process,
3315 	      no_zebra_packet_process_cmd,
3316 	      "no zebra zapi-packets [(1-10000)]",
3317 	      NO_STR
3318 	      ZEBRA_STR
3319 	      "Zapi Protocol\n"
3320 	      "Number of packets to process before relinquishing thread\n")
3321 {
3322 	atomic_store_explicit(&zrouter.packets_to_process,
3323 			      ZEBRA_ZAPI_PACKETS_TO_PROCESS,
3324 			      memory_order_relaxed);
3325 
3326 	return CMD_SUCCESS;
3327 }
3328 
3329 DEFUN_HIDDEN (zebra_workqueue_timer,
3330 	      zebra_workqueue_timer_cmd,
3331 	      "zebra work-queue (0-10000)",
3332 	      ZEBRA_STR
3333 	      "Work Queue\n"
3334 	      "Time in milliseconds\n")
3335 {
3336 	uint32_t timer = strtoul(argv[2]->arg, NULL, 10);
3337 	zrouter.ribq->spec.hold = timer;
3338 
3339 	return CMD_SUCCESS;
3340 }
3341 
3342 DEFUN_HIDDEN (no_zebra_workqueue_timer,
3343 	      no_zebra_workqueue_timer_cmd,
3344 	      "no zebra work-queue [(0-10000)]",
3345 	      NO_STR
3346 	      ZEBRA_STR
3347 	      "Work Queue\n"
3348 	      "Time in milliseconds\n")
3349 {
3350 	zrouter.ribq->spec.hold = ZEBRA_RIB_PROCESS_HOLD_TIME;
3351 
3352 	return CMD_SUCCESS;
3353 }
3354 
3355 DEFUN (no_ip_zebra_import_table,
3356        no_ip_zebra_import_table_cmd,
3357        "no ip import-table (1-252) [distance (1-255)] [route-map NAME]",
3358        NO_STR
3359        IP_STR
3360        "import routes from non-main kernel table\n"
3361        "kernel routing table id\n"
3362        "Distance for imported routes\n"
3363        "Default distance value\n"
3364        "route-map for filtering\n"
3365        "route-map name\n")
3366 {
3367 	uint32_t table_id = 0;
3368 	table_id = strtoul(argv[3]->arg, NULL, 10);
3369 
3370 	if (!is_zebra_valid_kernel_table(table_id)) {
3371 		vty_out(vty,
3372 			"Invalid routing table ID. Must be in range 1-252\n");
3373 		return CMD_WARNING;
3374 	}
3375 
3376 	if (is_zebra_main_routing_table(table_id)) {
3377 		vty_out(vty,
3378 			"Invalid routing table ID, %d. Must be non-default table\n",
3379 			table_id);
3380 		return CMD_WARNING;
3381 	}
3382 
3383 	if (!is_zebra_import_table_enabled(AFI_IP, VRF_DEFAULT, table_id))
3384 		return CMD_SUCCESS;
3385 
3386 	return (zebra_import_table(AFI_IP, VRF_DEFAULT, table_id, 0, NULL, 0));
3387 }
3388 
config_write_protocol(struct vty * vty)3389 static int config_write_protocol(struct vty *vty)
3390 {
3391 	if (allow_delete)
3392 		vty_out(vty, "allow-external-route-update\n");
3393 
3394 	if (zrouter.ribq->spec.hold != ZEBRA_RIB_PROCESS_HOLD_TIME)
3395 		vty_out(vty, "zebra work-queue %u\n", zrouter.ribq->spec.hold);
3396 
3397 	if (zrouter.packets_to_process != ZEBRA_ZAPI_PACKETS_TO_PROCESS)
3398 		vty_out(vty, "zebra zapi-packets %u\n",
3399 			zrouter.packets_to_process);
3400 
3401 	enum multicast_mode ipv4_multicast_mode = multicast_mode_ipv4_get();
3402 
3403 	if (ipv4_multicast_mode != MCAST_NO_CONFIG)
3404 		vty_out(vty, "ip multicast rpf-lookup-mode %s\n",
3405 			ipv4_multicast_mode == MCAST_URIB_ONLY
3406 				? "urib-only"
3407 				: ipv4_multicast_mode == MCAST_MRIB_ONLY
3408 					  ? "mrib-only"
3409 					  : ipv4_multicast_mode
3410 							    == MCAST_MIX_MRIB_FIRST
3411 						    ? "mrib-then-urib"
3412 						    : ipv4_multicast_mode
3413 								      == MCAST_MIX_DISTANCE
3414 							      ? "lower-distance"
3415 							      : "longer-prefix");
3416 
3417 	/* Include dataplane info */
3418 	dplane_config_write_helper(vty);
3419 
3420 	/* Include nexthop-group config */
3421 	if (!zebra_nhg_kernel_nexthops_enabled())
3422 		vty_out(vty, "no zebra nexthop kernel enable\n");
3423 
3424 #ifdef HAVE_NETLINK
3425 	/* Include netlink info */
3426 	netlink_config_write_helper(vty);
3427 #endif /* HAVE_NETLINK */
3428 
3429 	return 1;
3430 }
3431 
3432 DEFUN (show_zebra,
3433        show_zebra_cmd,
3434        "show zebra",
3435        SHOW_STR
3436        ZEBRA_STR)
3437 {
3438 	struct vrf *vrf;
3439 
3440 	vty_out(vty,
3441 		"                            Route      Route      Neighbor   LSP        LSP\n");
3442 	vty_out(vty,
3443 		"VRF                         Installs   Removals    Updates   Installs   Removals\n");
3444 
3445 	RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
3446 		struct zebra_vrf *zvrf = vrf->info;
3447 
3448 		vty_out(vty, "%-25s %10" PRIu64 " %10" PRIu64 " %10" PRIu64" %10" PRIu64 " %10" PRIu64 "\n",
3449 			vrf->name, zvrf->installs, zvrf->removals,
3450 			zvrf->neigh_updates, zvrf->lsp_installs,
3451 			zvrf->lsp_removals);
3452 	}
3453 
3454 	return CMD_SUCCESS;
3455 }
3456 
3457 DEFUN (ip_forwarding,
3458        ip_forwarding_cmd,
3459        "ip forwarding",
3460        IP_STR
3461        "Turn on IP forwarding\n")
3462 {
3463 	int ret;
3464 
3465 	ret = ipforward();
3466 	if (ret == 0)
3467 		ret = ipforward_on();
3468 
3469 	if (ret == 0) {
3470 		vty_out(vty, "Can't turn on IP forwarding\n");
3471 		return CMD_WARNING_CONFIG_FAILED;
3472 	}
3473 
3474 	return CMD_SUCCESS;
3475 }
3476 
3477 DEFUN (no_ip_forwarding,
3478        no_ip_forwarding_cmd,
3479        "no ip forwarding",
3480        NO_STR
3481        IP_STR
3482        "Turn off IP forwarding\n")
3483 {
3484 	int ret;
3485 
3486 	ret = ipforward();
3487 	if (ret != 0)
3488 		ret = ipforward_off();
3489 
3490 	if (ret != 0) {
3491 		vty_out(vty, "Can't turn off IP forwarding\n");
3492 		return CMD_WARNING_CONFIG_FAILED;
3493 	}
3494 
3495 	return CMD_SUCCESS;
3496 }
3497 
3498 /* Only display ip forwarding is enabled or not. */
3499 DEFUN (show_ip_forwarding,
3500        show_ip_forwarding_cmd,
3501        "show ip forwarding",
3502        SHOW_STR
3503        IP_STR
3504        "IP forwarding status\n")
3505 {
3506 	int ret;
3507 
3508 	ret = ipforward();
3509 
3510 	if (ret == 0)
3511 		vty_out(vty, "IP forwarding is off\n");
3512 	else
3513 		vty_out(vty, "IP forwarding is on\n");
3514 	return CMD_SUCCESS;
3515 }
3516 
3517 /* Only display ipv6 forwarding is enabled or not. */
3518 DEFUN (show_ipv6_forwarding,
3519        show_ipv6_forwarding_cmd,
3520        "show ipv6 forwarding",
3521        SHOW_STR
3522        "IPv6 information\n"
3523        "Forwarding status\n")
3524 {
3525 	int ret;
3526 
3527 	ret = ipforward_ipv6();
3528 
3529 	switch (ret) {
3530 	case -1:
3531 		vty_out(vty, "ipv6 forwarding is unknown\n");
3532 		break;
3533 	case 0:
3534 		vty_out(vty, "ipv6 forwarding is %s\n", "off");
3535 		break;
3536 	case 1:
3537 		vty_out(vty, "ipv6 forwarding is %s\n", "on");
3538 		break;
3539 	default:
3540 		vty_out(vty, "ipv6 forwarding is %s\n", "off");
3541 		break;
3542 	}
3543 	return CMD_SUCCESS;
3544 }
3545 
3546 DEFUN (ipv6_forwarding,
3547        ipv6_forwarding_cmd,
3548        "ipv6 forwarding",
3549        IPV6_STR
3550        "Turn on IPv6 forwarding\n")
3551 {
3552 	int ret;
3553 
3554 	ret = ipforward_ipv6();
3555 	if (ret == 0)
3556 		ret = ipforward_ipv6_on();
3557 
3558 	if (ret == 0) {
3559 		vty_out(vty, "Can't turn on IPv6 forwarding\n");
3560 		return CMD_WARNING_CONFIG_FAILED;
3561 	}
3562 
3563 	return CMD_SUCCESS;
3564 }
3565 
3566 DEFUN (no_ipv6_forwarding,
3567        no_ipv6_forwarding_cmd,
3568        "no ipv6 forwarding",
3569        NO_STR
3570        IPV6_STR
3571        "Turn off IPv6 forwarding\n")
3572 {
3573 	int ret;
3574 
3575 	ret = ipforward_ipv6();
3576 	if (ret != 0)
3577 		ret = ipforward_ipv6_off();
3578 
3579 	if (ret != 0) {
3580 		vty_out(vty, "Can't turn off IPv6 forwarding\n");
3581 		return CMD_WARNING_CONFIG_FAILED;
3582 	}
3583 
3584 	return CMD_SUCCESS;
3585 }
3586 
3587 /* Display dataplane info */
3588 DEFUN (show_dataplane,
3589        show_dataplane_cmd,
3590        "show zebra dplane [detailed]",
3591        SHOW_STR
3592        ZEBRA_STR
3593        "Zebra dataplane information\n"
3594        "Detailed output\n")
3595 {
3596 	int idx = 0;
3597 	bool detailed = false;
3598 
3599 	if (argv_find(argv, argc, "detailed", &idx))
3600 		detailed = true;
3601 
3602 	return dplane_show_helper(vty, detailed);
3603 }
3604 
3605 /* Display dataplane providers info */
3606 DEFUN (show_dataplane_providers,
3607        show_dataplane_providers_cmd,
3608        "show zebra dplane providers [detailed]",
3609        SHOW_STR
3610        ZEBRA_STR
3611        "Zebra dataplane information\n"
3612        "Zebra dataplane provider information\n"
3613        "Detailed output\n")
3614 {
3615 	int idx = 0;
3616 	bool detailed = false;
3617 
3618 	if (argv_find(argv, argc, "detailed", &idx))
3619 		detailed = true;
3620 
3621 	return dplane_show_provs_helper(vty, detailed);
3622 }
3623 
3624 /* Configure dataplane incoming queue limit */
3625 DEFUN (zebra_dplane_queue_limit,
3626        zebra_dplane_queue_limit_cmd,
3627        "zebra dplane limit (0-10000)",
3628        ZEBRA_STR
3629        "Zebra dataplane\n"
3630        "Limit incoming queued updates\n"
3631        "Number of queued updates\n")
3632 {
3633 	uint32_t limit = 0;
3634 
3635 	limit = strtoul(argv[3]->arg, NULL, 10);
3636 
3637 	dplane_set_in_queue_limit(limit, true);
3638 
3639 	return CMD_SUCCESS;
3640 }
3641 
3642 /* Reset dataplane queue limit to default value */
3643 DEFUN (no_zebra_dplane_queue_limit,
3644        no_zebra_dplane_queue_limit_cmd,
3645        "no zebra dplane limit [(0-10000)]",
3646        NO_STR
3647        ZEBRA_STR
3648        "Zebra dataplane\n"
3649        "Limit incoming queued updates\n"
3650        "Number of queued updates\n")
3651 {
3652 	dplane_set_in_queue_limit(0, false);
3653 
3654 	return CMD_SUCCESS;
3655 }
3656 
3657 DEFUN (zebra_show_routing_tables_summary,
3658        zebra_show_routing_tables_summary_cmd,
3659        "show zebra router table summary",
3660        SHOW_STR
3661        ZEBRA_STR
3662        "The Zebra Router Information\n"
3663        "Table Information about this Zebra Router\n"
3664        "Summary Information\n")
3665 {
3666 	zebra_router_show_table_summary(vty);
3667 
3668 	return CMD_SUCCESS;
3669 }
3670 
3671 /* Table configuration write function. */
config_write_table(struct vty * vty)3672 static int config_write_table(struct vty *vty)
3673 {
3674 	return 0;
3675 }
3676 
3677 /* IPForwarding configuration write function. */
config_write_forwarding(struct vty * vty)3678 static int config_write_forwarding(struct vty *vty)
3679 {
3680 	if (!ipforward())
3681 		vty_out(vty, "no ip forwarding\n");
3682 	if (!ipforward_ipv6())
3683 		vty_out(vty, "no ipv6 forwarding\n");
3684 	vty_out(vty, "!\n");
3685 	return 0;
3686 }
3687 
3688 DEFUN_HIDDEN (show_frr,
3689 	      show_frr_cmd,
3690 	      "show frr",
3691 	      SHOW_STR
3692 	      "FRR\n")
3693 {
3694 	vty_out(vty, "........ .. .  .. . ..... ...77:................................................\n");
3695 	vty_out(vty, ".............................7777:..............................................\n");
3696 	vty_out(vty, ".............................777777,............................................\n");
3697 	vty_out(vty, "... .........................77777777,..........................................\n");
3698 	vty_out(vty, "............................=7777777777:........................................\n");
3699 	vty_out(vty, "........................:7777777777777777,......................................\n");
3700 	vty_out(vty, ".................... ~7777777777777?~,..........................................\n");
3701 	vty_out(vty, "...................I7777777777+.................................................\n");
3702 	vty_out(vty, "................,777777777?............  .......................................\n");
3703 	vty_out(vty, "..............:77777777?..........~?77777.......................................\n");
3704 	vty_out(vty, ".............77777777~........=7777777777.......................................\n");
3705 	vty_out(vty, ".......... +7777777,.......?7777777777777.......................................\n");
3706 	vty_out(vty, "..........7777777~......:7777777777777777......77?,.............................\n");
3707 	vty_out(vty, "........:777777?......+777777777777777777......777777I,.........................\n");
3708 	vty_out(vty, ".......?777777,.....+77777777777777777777......777777777?.......................\n");
3709 	vty_out(vty, "......?777777......7777777777777777777777......,?777777777?.....................\n");
3710 	vty_out(vty, ".....?77777?.....=7777777777777777777I~............,I7777777~...................\n");
3711 	vty_out(vty, "....+77777+.....I77777777777777777:...................+777777I..................\n");
3712 	vty_out(vty, "...~77777+.....7777777777777777=........................?777777......    .......\n");
3713 	vty_out(vty, "...77777I.....I77777777777777~.........:?................,777777.....I777.......\n");
3714 	vty_out(vty, "..777777.....I7777777777777I .......?7777..................777777.....777?......\n");
3715 	vty_out(vty, ".~77777,....=7777777777777:......,7777777..................,77777+....+777......\n");
3716 	vty_out(vty, ".77777I.....7777777777777,......777777777.......ONNNN.......=77777.....777~.....\n");
3717 	vty_out(vty, ",77777.....I777777777777,.....:7777777777......DNNNNNN.......77777+ ...7777.....\n");
3718 	vty_out(vty, "I7777I.....777777777777=.....~77777777777......NNNNNNN~......=7777I....=777.....\n");
3719 	vty_out(vty, "77777:....=777777777777.....,777777777777......$NNNNND ......:77777....:777.....\n");
3720 	vty_out(vty, "77777. ...777777777777~.....7777777777777........7DZ,........:77777.....777.....\n");
3721 	vty_out(vty, "????? . ..777777777777.....,7777777777777....................:77777I....777.....\n");
3722 	vty_out(vty, "....... ..777777777777.....+7777777777777....................=7777777+...?7.....\n");
3723 	vty_out(vty, "..........77777777777I.....I7777777777777....................7777777777:........\n");
3724 	vty_out(vty, "..........77777777777I.....?7777777777777...................~777777777777.......\n");
3725 	vty_out(vty, "..........777777777777.....~7777777777777..................,77777777777777+.....\n");
3726 	vty_out(vty, "..........777777777777......7777777777777..................77777777777777777,...\n");
3727 	vty_out(vty, "..... ....?77777777777I.....~777777777777................,777777.....,:+77777I..\n");
3728 	vty_out(vty, "........ .:777777777777,.....?77777777777...............?777777..............,:=\n");
3729 	vty_out(vty, ".......... 7777777777777..... ?7777777777.............=7777777.....~777I........\n");
3730 	vty_out(vty, "...........:777777777777I......~777777777...........I7777777~.....+777I.........\n");
3731 	vty_out(vty, "..... ......7777777777777I.......I7777777.......+777777777I......7777I..........\n");
3732 	vty_out(vty, ".............77777777777777........?77777......777777777?......=7777=...........\n");
3733 	vty_out(vty, ".............,77777777777777+.........~77......777777I,......:77777.............\n");
3734 	vty_out(vty, "..............~777777777777777~................777777......:77777=..............\n");
3735 	vty_out(vty, "...............:7777777777777777?..............:777777,.....=77=................\n");
3736 	vty_out(vty, "................,777777777777777777?,...........,777777:.....,..................\n");
3737 	vty_out(vty, "........... ......I777777777777777777777I.........777777~.......................\n");
3738 	vty_out(vty, "...................,777777777777777777777..........777777+......................\n");
3739 	vty_out(vty, ".....................+7777777777777777777...........777777?.....................\n");
3740 	vty_out(vty, ".......................=77777777777777777............777777I....................\n");
3741 	vty_out(vty, ".........................:777777777777777.............I77777I...................\n");
3742 	vty_out(vty, "............................~777777777777..............+777777..................\n");
3743 	vty_out(vty, "................................~77777777...............=777777.................\n");
3744 	vty_out(vty, ".....................................:=?I................~777777................\n");
3745 	vty_out(vty, "..........................................................:777777,..............\n");
3746 	vty_out(vty, ".... ... ... .  . .... ....... ....... ....................:777777..............\n");
3747 
3748 	return CMD_SUCCESS;
3749 }
3750 
3751 #ifdef HAVE_NETLINK
3752 DEFUN_HIDDEN(zebra_kernel_netlink_batch_tx_buf,
3753 	     zebra_kernel_netlink_batch_tx_buf_cmd,
3754 	     "zebra kernel netlink batch-tx-buf (1-1048576) (1-1048576)",
3755 	     ZEBRA_STR
3756 	     "Zebra kernel interface\n"
3757 	     "Set Netlink parameters\n"
3758 	     "Set batch buffer size and send threshold\n"
3759 	     "Size of the buffer\n"
3760 	     "Send threshold\n")
3761 {
3762 	uint32_t bufsize = 0, threshold = 0;
3763 
3764 	bufsize = strtoul(argv[4]->arg, NULL, 10);
3765 	threshold = strtoul(argv[5]->arg, NULL, 10);
3766 
3767 	netlink_set_batch_buffer_size(bufsize, threshold, true);
3768 
3769 	return CMD_SUCCESS;
3770 }
3771 
3772 DEFUN_HIDDEN(no_zebra_kernel_netlink_batch_tx_buf,
3773 	     no_zebra_kernel_netlink_batch_tx_buf_cmd,
3774 	     "no zebra kernel netlink batch-tx-buf [(0-1048576)] [(0-1048576)]",
3775 	     NO_STR ZEBRA_STR
3776 	     "Zebra kernel interface\n"
3777 	     "Set Netlink parameters\n"
3778 	     "Set batch buffer size and send threshold\n"
3779 	     "Size of the buffer\n"
3780 	     "Send threshold\n")
3781 {
3782 	netlink_set_batch_buffer_size(0, 0, false);
3783 
3784 	return CMD_SUCCESS;
3785 }
3786 
3787 #endif /* HAVE_NETLINK */
3788 
3789 /* IP node for static routes. */
3790 static int zebra_ip_config(struct vty *vty);
3791 static struct cmd_node ip_node = {
3792 	.name = "static ip",
3793 	.node = IP_NODE,
3794 	.prompt = "",
3795 	.config_write = zebra_ip_config,
3796 };
3797 static int config_write_protocol(struct vty *vty);
3798 static struct cmd_node protocol_node = {
3799 	.name = "protocol",
3800 	.node = PROTOCOL_NODE,
3801 	.prompt = "",
3802 	.config_write = config_write_protocol,
3803 };
3804 /* table node for routing tables. */
3805 static int config_write_table(struct vty *vty);
3806 static struct cmd_node table_node = {
3807 	.name = "table",
3808 	.node = TABLE_NODE,
3809 	.prompt = "",
3810 	.config_write = config_write_table,
3811 };
3812 static int config_write_forwarding(struct vty *vty);
3813 static struct cmd_node forwarding_node = {
3814 	.name = "forwarding",
3815 	.node = FORWARDING_NODE,
3816 	.prompt = "",
3817 	.config_write = config_write_forwarding,
3818 };
3819 
3820 /* Route VTY.  */
zebra_vty_init(void)3821 void zebra_vty_init(void)
3822 {
3823 	/* Install configuration write function. */
3824 	install_node(&table_node);
3825 	install_node(&forwarding_node);
3826 
3827 	install_element(VIEW_NODE, &show_ip_forwarding_cmd);
3828 	install_element(CONFIG_NODE, &ip_forwarding_cmd);
3829 	install_element(CONFIG_NODE, &no_ip_forwarding_cmd);
3830 	install_element(ENABLE_NODE, &show_zebra_cmd);
3831 
3832 	install_element(VIEW_NODE, &show_ipv6_forwarding_cmd);
3833 	install_element(CONFIG_NODE, &ipv6_forwarding_cmd);
3834 	install_element(CONFIG_NODE, &no_ipv6_forwarding_cmd);
3835 
3836 	/* Route-map */
3837 	zebra_route_map_init();
3838 
3839 	install_node(&ip_node);
3840 	install_node(&protocol_node);
3841 
3842 	install_element(CONFIG_NODE, &allow_external_route_update_cmd);
3843 	install_element(CONFIG_NODE, &no_allow_external_route_update_cmd);
3844 
3845 	install_element(CONFIG_NODE, &ip_multicast_mode_cmd);
3846 	install_element(CONFIG_NODE, &no_ip_multicast_mode_cmd);
3847 
3848 	install_element(CONFIG_NODE, &ip_zebra_import_table_distance_cmd);
3849 	install_element(CONFIG_NODE, &no_ip_zebra_import_table_cmd);
3850 	install_element(CONFIG_NODE, &zebra_workqueue_timer_cmd);
3851 	install_element(CONFIG_NODE, &no_zebra_workqueue_timer_cmd);
3852 	install_element(CONFIG_NODE, &zebra_packet_process_cmd);
3853 	install_element(CONFIG_NODE, &no_zebra_packet_process_cmd);
3854 	install_element(CONFIG_NODE, &nexthop_group_use_enable_cmd);
3855 
3856 	install_element(VIEW_NODE, &show_nexthop_group_cmd);
3857 	install_element(VIEW_NODE, &show_interface_nexthop_group_cmd);
3858 
3859 	install_element(VIEW_NODE, &show_vrf_cmd);
3860 	install_element(VIEW_NODE, &show_vrf_vni_cmd);
3861 	install_element(VIEW_NODE, &show_route_cmd);
3862 	install_element(VIEW_NODE, &show_ro_cmd);
3863 	install_element(VIEW_NODE, &show_route_detail_cmd);
3864 	install_element(VIEW_NODE, &show_route_summary_cmd);
3865 	install_element(VIEW_NODE, &show_ip_nht_cmd);
3866 
3867 	install_element(VIEW_NODE, &show_ip_rpf_cmd);
3868 	install_element(VIEW_NODE, &show_ip_rpf_addr_cmd);
3869 
3870 	install_element(CONFIG_NODE, &ip_nht_default_route_cmd);
3871 	install_element(CONFIG_NODE, &no_ip_nht_default_route_cmd);
3872 	install_element(CONFIG_NODE, &ipv6_nht_default_route_cmd);
3873 	install_element(CONFIG_NODE, &no_ipv6_nht_default_route_cmd);
3874 	install_element(VRF_NODE, &ip_nht_default_route_cmd);
3875 	install_element(VRF_NODE, &no_ip_nht_default_route_cmd);
3876 	install_element(VRF_NODE, &ipv6_nht_default_route_cmd);
3877 	install_element(VRF_NODE, &no_ipv6_nht_default_route_cmd);
3878 	install_element(VIEW_NODE, &show_ipv6_mroute_cmd);
3879 
3880 	/* Commands for VRF */
3881 	install_element(VIEW_NODE, &show_ipv6_mroute_vrf_all_cmd);
3882 
3883 	install_element(VIEW_NODE, &show_frr_cmd);
3884 	install_element(VIEW_NODE, &show_evpn_global_cmd);
3885 	install_element(VIEW_NODE, &show_evpn_vni_cmd);
3886 	install_element(VIEW_NODE, &show_evpn_vni_detail_cmd);
3887 	install_element(VIEW_NODE, &show_evpn_vni_vni_cmd);
3888 	install_element(VIEW_NODE, &show_evpn_es_cmd);
3889 	install_element(VIEW_NODE, &show_evpn_es_evi_cmd);
3890 	install_element(VIEW_NODE, &show_evpn_access_vlan_cmd);
3891 	install_element(VIEW_NODE, &show_evpn_rmac_vni_mac_cmd);
3892 	install_element(VIEW_NODE, &show_evpn_rmac_vni_cmd);
3893 	install_element(VIEW_NODE, &show_evpn_rmac_vni_all_cmd);
3894 	install_element(VIEW_NODE, &show_evpn_nh_vni_ip_cmd);
3895 	install_element(VIEW_NODE, &show_evpn_nh_vni_cmd);
3896 	install_element(VIEW_NODE, &show_evpn_nh_vni_all_cmd);
3897 	install_element(VIEW_NODE, &show_evpn_mac_vni_cmd);
3898 	install_element(VIEW_NODE, &show_evpn_mac_vni_all_cmd);
3899 	install_element(VIEW_NODE, &show_evpn_mac_vni_all_detail_cmd);
3900 	install_element(VIEW_NODE, &show_evpn_mac_vni_all_vtep_cmd);
3901 	install_element(VIEW_NODE, &show_evpn_mac_vni_mac_cmd);
3902 	install_element(VIEW_NODE, &show_evpn_mac_vni_vtep_cmd);
3903 	install_element(VIEW_NODE, &show_evpn_mac_vni_dad_cmd);
3904 	install_element(VIEW_NODE, &show_evpn_mac_vni_all_dad_cmd);
3905 	install_element(VIEW_NODE, &show_evpn_neigh_vni_cmd);
3906 	install_element(VIEW_NODE, &show_evpn_neigh_vni_all_cmd);
3907 	install_element(VIEW_NODE, &show_evpn_neigh_vni_all_detail_cmd);
3908 	install_element(VIEW_NODE, &show_evpn_neigh_vni_neigh_cmd);
3909 	install_element(VIEW_NODE, &show_evpn_neigh_vni_vtep_cmd);
3910 	install_element(VIEW_NODE, &show_evpn_neigh_vni_dad_cmd);
3911 	install_element(VIEW_NODE, &show_evpn_neigh_vni_all_dad_cmd);
3912 	install_element(ENABLE_NODE, &clear_evpn_dup_addr_cmd);
3913 
3914 	install_element(VIEW_NODE, &show_pbr_ipset_cmd);
3915 	install_element(VIEW_NODE, &show_pbr_iptable_cmd);
3916 
3917 	install_element(CONFIG_NODE, &default_vrf_vni_mapping_cmd);
3918 	install_element(CONFIG_NODE, &no_default_vrf_vni_mapping_cmd);
3919 	install_element(VRF_NODE, &vrf_vni_mapping_cmd);
3920 	install_element(VRF_NODE, &no_vrf_vni_mapping_cmd);
3921 
3922 	install_element(VIEW_NODE, &show_dataplane_cmd);
3923 	install_element(VIEW_NODE, &show_dataplane_providers_cmd);
3924 	install_element(CONFIG_NODE, &zebra_dplane_queue_limit_cmd);
3925 	install_element(CONFIG_NODE, &no_zebra_dplane_queue_limit_cmd);
3926 
3927 #ifdef HAVE_NETLINK
3928 	install_element(CONFIG_NODE, &zebra_kernel_netlink_batch_tx_buf_cmd);
3929 	install_element(CONFIG_NODE, &no_zebra_kernel_netlink_batch_tx_buf_cmd);
3930 #endif /* HAVE_NETLINK */
3931 
3932 	install_element(VIEW_NODE, &zebra_show_routing_tables_summary_cmd);
3933 }
3934