]> git.proxmox.com Git - mirror_frr.git/blob - zebra/zebra_vty.c
zebra: enhance show vrf for netns and fixing
[mirror_frr.git] / zebra / zebra_vty.c
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 "mpls.h"
33 #include "routemap.h"
34 #include "srcdest_table.h"
35 #include "vxlan.h"
36
37 #include "zebra/zserv.h"
38 #include "zebra/zebra_vrf.h"
39 #include "zebra/zebra_mpls.h"
40 #include "zebra/zebra_rnh.h"
41 #include "zebra/redistribute.h"
42 #include "zebra/zebra_routemap.h"
43 #include "zebra/zebra_static.h"
44 #include "lib/json.h"
45 #include "zebra/zebra_vxlan.h"
46 #ifndef VTYSH_EXTRACT_PL
47 #include "zebra/zebra_vty_clippy.c"
48 #endif
49 #include "zebra/zserv.h"
50 #include "zebra/router-id.h"
51 #include "zebra/ipforward.h"
52 #include "zebra/zebra_vxlan_private.h"
53
54 extern int allow_delete;
55
56 static int do_show_ip_route(struct vty *vty, const char *vrf_name, afi_t afi,
57 safi_t safi, bool use_fib, u_char use_json,
58 route_tag_t tag,
59 const struct prefix *longer_prefix_p,
60 bool supernets_only, int type,
61 u_short ospf_instance_id);
62 static void vty_show_ip_route_detail(struct vty *vty, struct route_node *rn,
63 int mcast);
64 static void vty_show_ip_route_summary(struct vty *vty,
65 struct route_table *table);
66 static void vty_show_ip_route_summary_prefix(struct vty *vty,
67 struct route_table *table);
68
69 /*
70 * special macro to allow us to get the correct zebra_vrf
71 */
72 #define ZEBRA_DECLVAR_CONTEXT(A, B) \
73 struct vrf *A = VTY_GET_CONTEXT(vrf); \
74 struct zebra_vrf *B = \
75 (vrf) ? vrf->info : NULL; \
76
77 /* VNI range as per RFC 7432 */
78 #define CMD_VNI_RANGE "(1-16777215)"
79
80 /* General function for static route. */
81 static int zebra_static_route_leak(struct vty *vty,
82 struct zebra_vrf *zvrf,
83 struct zebra_vrf *nh_zvrf,
84 afi_t afi, safi_t safi,
85 const char *negate, const char *dest_str,
86 const char *mask_str, const char *src_str,
87 const char *gate_str, const char *ifname,
88 const char *flag_str, const char *tag_str,
89 const char *distance_str,
90 const char *label_str)
91 {
92 int ret;
93 u_char distance;
94 struct prefix p, src;
95 struct prefix_ipv6 *src_p = NULL;
96 union g_addr gate;
97 union g_addr *gatep = NULL;
98 struct in_addr mask;
99 enum static_blackhole_type bh_type = 0;
100 route_tag_t tag = 0;
101 u_char type;
102 struct static_nh_label snh_label;
103
104 ret = str2prefix(dest_str, &p);
105 if (ret <= 0) {
106 vty_out(vty, "%% Malformed address\n");
107 return CMD_WARNING_CONFIG_FAILED;
108 }
109
110 switch (afi) {
111 case AFI_IP:
112 /* Cisco like mask notation. */
113 if (mask_str) {
114 ret = inet_aton(mask_str, &mask);
115 if (ret == 0) {
116 vty_out(vty, "%% Malformed address\n");
117 return CMD_WARNING_CONFIG_FAILED;
118 }
119 p.prefixlen = ip_masklen(mask);
120 }
121 break;
122 case AFI_IP6:
123 /* srcdest routing */
124 if (src_str) {
125 ret = str2prefix(src_str, &src);
126 if (ret <= 0 || src.family != AF_INET6) {
127 vty_out(vty, "%% Malformed source address\n");
128 return CMD_WARNING_CONFIG_FAILED;
129 }
130 src_p = (struct prefix_ipv6 *)&src;
131 }
132 break;
133 default:
134 break;
135 }
136
137 /* Apply mask for given prefix. */
138 apply_mask(&p);
139
140 /* Administrative distance. */
141 if (distance_str)
142 distance = atoi(distance_str);
143 else
144 distance = ZEBRA_STATIC_DISTANCE_DEFAULT;
145
146 /* tag */
147 if (tag_str)
148 tag = strtoul(tag_str, NULL, 10);
149
150 /* Labels */
151 memset(&snh_label, 0, sizeof(struct static_nh_label));
152 if (label_str) {
153 if (!mpls_enabled) {
154 vty_out(vty,
155 "%% MPLS not turned on in kernel, ignoring command\n");
156 return CMD_WARNING_CONFIG_FAILED;
157 }
158 int rc = mpls_str2label(label_str, &snh_label.num_labels,
159 snh_label.label);
160 if (rc < 0) {
161 switch (rc) {
162 case -1:
163 vty_out(vty, "%% Malformed label(s)\n");
164 break;
165 case -2:
166 vty_out(vty,
167 "%% Cannot use reserved label(s) (%d-%d)\n",
168 MPLS_LABEL_RESERVED_MIN,
169 MPLS_LABEL_RESERVED_MAX);
170 break;
171 case -3:
172 vty_out(vty,
173 "%% Too many labels. Enter %d or fewer\n",
174 MPLS_MAX_LABELS);
175 break;
176 }
177 return CMD_WARNING_CONFIG_FAILED;
178 }
179 }
180
181 /* Null0 static route. */
182 if (ifname != NULL) {
183 if (strncasecmp(ifname, "Null0", strlen(ifname)) == 0 ||
184 strncasecmp(ifname, "reject", strlen(ifname)) == 0 ||
185 strncasecmp(ifname, "blackhole", strlen(ifname)) == 0) {
186 vty_out(vty, "%% Nexthop interface cannot be Null0, reject or blackhole\n");
187 return CMD_WARNING_CONFIG_FAILED;
188 }
189 }
190
191 /* Route flags */
192 if (flag_str) {
193 switch (flag_str[0]) {
194 case 'r':
195 bh_type = STATIC_BLACKHOLE_REJECT;
196 break;
197 case 'b':
198 bh_type = STATIC_BLACKHOLE_DROP;
199 break;
200 case 'N':
201 bh_type = STATIC_BLACKHOLE_NULL;
202 break;
203 default:
204 vty_out(vty, "%% Malformed flag %s \n", flag_str);
205 return CMD_WARNING_CONFIG_FAILED;
206 }
207 }
208
209 if (gate_str) {
210 if (inet_pton(afi2family(afi), gate_str, &gate) != 1) {
211 vty_out(vty, "%% Malformed nexthop address %s\n",
212 gate_str);
213 return CMD_WARNING_CONFIG_FAILED;
214 }
215 gatep = &gate;
216 }
217
218 if (gate_str == NULL && ifname == NULL)
219 type = STATIC_BLACKHOLE;
220 else if (gate_str && ifname) {
221 if (afi == AFI_IP)
222 type = STATIC_IPV4_GATEWAY_IFNAME;
223 else
224 type = STATIC_IPV6_GATEWAY_IFNAME;
225 } else if (ifname)
226 type = STATIC_IFNAME;
227 else {
228 if (afi == AFI_IP)
229 type = STATIC_IPV4_GATEWAY;
230 else
231 type = STATIC_IPV6_GATEWAY;
232 }
233
234 if (!negate) {
235 static_add_route(afi, safi, type, &p, src_p, gatep, ifname,
236 bh_type, tag, distance, zvrf, nh_zvrf,
237 &snh_label);
238 /* Mark as having FRR configuration */
239 vrf_set_user_cfged(zvrf->vrf);
240 } else {
241 static_delete_route(afi, safi, type, &p, src_p, gatep, ifname,
242 tag, distance, zvrf, &snh_label);
243 /* If no other FRR config for this VRF, mark accordingly. */
244 if (!zebra_vrf_has_config(zvrf))
245 vrf_reset_user_cfged(zvrf->vrf);
246 }
247
248 return CMD_SUCCESS;
249 }
250
251 static int zebra_static_route(struct vty *vty, afi_t afi, safi_t safi,
252 const char *negate, const char *dest_str,
253 const char *mask_str, const char *src_str,
254 const char *gate_str, const char *ifname,
255 const char *flag_str, const char *tag_str,
256 const char *distance_str, const char *vrf_name,
257 const char *label_str)
258 {
259 struct zebra_vrf *zvrf;
260 struct vrf *vrf;
261
262 /* VRF id */
263 zvrf = zebra_vrf_lookup_by_name(vrf_name);
264
265 /* When trying to delete, the VRF must exist. */
266 if (negate && !zvrf) {
267 vty_out(vty, "%% vrf %s is not defined\n", vrf_name);
268 return CMD_WARNING_CONFIG_FAILED;
269 }
270
271 /* When trying to create, create the VRF if it doesn't exist.
272 * Note: The VRF isn't active until we hear about it from the kernel.
273 */
274 if (!zvrf) {
275 vrf = vrf_get(VRF_UNKNOWN, vrf_name);
276 if (!vrf) {
277 vty_out(vty, "%% Could not create vrf %s\n", vrf_name);
278 return CMD_WARNING_CONFIG_FAILED;
279 }
280 zvrf = vrf->info;
281 if (!zvrf) {
282 vty_out(vty, "%% Could not create vrf-info %s\n",
283 vrf_name);
284 return CMD_WARNING_CONFIG_FAILED;
285 }
286 /* Mark as having FRR configuration */
287 vrf_set_user_cfged(vrf);
288 }
289 return zebra_static_route_leak(vty, zvrf, zvrf, afi, safi,
290 negate, dest_str, mask_str, src_str,
291 gate_str, ifname, flag_str, tag_str,
292 distance_str, label_str);
293 }
294
295
296 /* Static unicast routes for multicast RPF lookup. */
297 DEFPY (ip_mroute_dist,
298 ip_mroute_dist_cmd,
299 "[no] ip mroute A.B.C.D/M$prefix <A.B.C.D$gate|INTERFACE$ifname> [(1-255)$distance]",
300 NO_STR
301 IP_STR
302 "Configure static unicast route into MRIB for multicast RPF lookup\n"
303 "IP destination prefix (e.g. 10.0.0.0/8)\n"
304 "Nexthop address\n"
305 "Nexthop interface name\n"
306 "Distance\n")
307 {
308 return zebra_static_route(vty, AFI_IP, SAFI_MULTICAST, no, prefix_str,
309 NULL, NULL, gate_str, ifname, NULL, NULL,
310 distance_str, NULL, NULL);
311 }
312
313 DEFUN (ip_multicast_mode,
314 ip_multicast_mode_cmd,
315 "ip multicast rpf-lookup-mode <urib-only|mrib-only|mrib-then-urib|lower-distance|longer-prefix>",
316 IP_STR
317 "Multicast options\n"
318 "RPF lookup behavior\n"
319 "Lookup in unicast RIB only\n"
320 "Lookup in multicast RIB only\n"
321 "Try multicast RIB first, fall back to unicast RIB\n"
322 "Lookup both, use entry with lower distance\n"
323 "Lookup both, use entry with longer prefix\n")
324 {
325 char *mode = argv[3]->text;
326
327 if (strmatch(mode, "urib-only"))
328 multicast_mode_ipv4_set(MCAST_URIB_ONLY);
329 else if (strmatch(mode, "mrib-only"))
330 multicast_mode_ipv4_set(MCAST_MRIB_ONLY);
331 else if (strmatch(mode, "mrib-then-urib"))
332 multicast_mode_ipv4_set(MCAST_MIX_MRIB_FIRST);
333 else if (strmatch(mode, "lower-distance"))
334 multicast_mode_ipv4_set(MCAST_MIX_DISTANCE);
335 else if (strmatch(mode, "longer-prefix"))
336 multicast_mode_ipv4_set(MCAST_MIX_PFXLEN);
337 else {
338 vty_out(vty, "Invalid mode specified\n");
339 return CMD_WARNING_CONFIG_FAILED;
340 }
341
342 return CMD_SUCCESS;
343 }
344
345 DEFUN (no_ip_multicast_mode,
346 no_ip_multicast_mode_cmd,
347 "no ip multicast rpf-lookup-mode [<urib-only|mrib-only|mrib-then-urib|lower-distance|longer-prefix>]",
348 NO_STR
349 IP_STR
350 "Multicast options\n"
351 "RPF lookup behavior\n"
352 "Lookup in unicast RIB only\n"
353 "Lookup in multicast RIB only\n"
354 "Try multicast RIB first, fall back to unicast RIB\n"
355 "Lookup both, use entry with lower distance\n"
356 "Lookup both, use entry with longer prefix\n")
357 {
358 multicast_mode_ipv4_set(MCAST_NO_CONFIG);
359 return CMD_SUCCESS;
360 }
361
362
363 DEFUN (show_ip_rpf,
364 show_ip_rpf_cmd,
365 "show ip rpf [json]",
366 SHOW_STR
367 IP_STR
368 "Display RPF information for multicast source\n"
369 JSON_STR)
370 {
371 int uj = use_json(argc, argv);
372 return do_show_ip_route(vty, VRF_DEFAULT_NAME, AFI_IP, SAFI_MULTICAST,
373 false, uj, 0, NULL, false, 0, 0);
374 }
375
376 DEFUN (show_ip_rpf_addr,
377 show_ip_rpf_addr_cmd,
378 "show ip rpf A.B.C.D",
379 SHOW_STR
380 IP_STR
381 "Display RPF information for multicast source\n"
382 "IP multicast source address (e.g. 10.0.0.0)\n")
383 {
384 int idx_ipv4 = 3;
385 struct in_addr addr;
386 struct route_node *rn;
387 struct route_entry *re;
388 int ret;
389
390 ret = inet_aton(argv[idx_ipv4]->arg, &addr);
391 if (ret == 0) {
392 vty_out(vty, "%% Malformed address\n");
393 return CMD_WARNING;
394 }
395
396 re = rib_match_ipv4_multicast(VRF_DEFAULT, addr, &rn);
397
398 if (re)
399 vty_show_ip_route_detail(vty, rn, 1);
400 else
401 vty_out(vty, "%% No match for RPF lookup\n");
402
403 return CMD_SUCCESS;
404 }
405
406 /* Static route configuration. */
407 DEFPY(ip_route_blackhole,
408 ip_route_blackhole_cmd,
409 "[no] ip route\
410 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
411 <reject|blackhole>$flag \
412 [{ \
413 tag (1-4294967295) \
414 |(1-255)$distance \
415 |vrf NAME \
416 |label WORD \
417 }]",
418 NO_STR IP_STR
419 "Establish static routes\n"
420 "IP destination prefix (e.g. 10.0.0.0/8)\n"
421 "IP destination prefix\n"
422 "IP destination prefix mask\n"
423 "Emit an ICMP unreachable when matched\n"
424 "Silently discard pkts when matched\n"
425 "Set tag for this route\n"
426 "Tag value\n"
427 "Distance value for this route\n"
428 VRF_CMD_HELP_STR
429 MPLS_LABEL_HELPSTR)
430 {
431 return zebra_static_route(vty, AFI_IP, SAFI_UNICAST, no, prefix,
432 mask_str, NULL, NULL, NULL, flag,
433 tag_str, distance_str, vrf, label);
434 }
435
436 DEFPY(ip_route_blackhole_vrf,
437 ip_route_blackhole_vrf_cmd,
438 "[no] ip route\
439 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
440 <reject|blackhole>$flag \
441 [{ \
442 tag (1-4294967295) \
443 |(1-255)$distance \
444 |label WORD \
445 }]",
446 NO_STR IP_STR
447 "Establish static routes\n"
448 "IP destination prefix (e.g. 10.0.0.0/8)\n"
449 "IP destination prefix\n"
450 "IP destination prefix mask\n"
451 "Emit an ICMP unreachable when matched\n"
452 "Silently discard pkts when matched\n"
453 "Set tag for this route\n"
454 "Tag value\n"
455 "Distance value for this route\n"
456 MPLS_LABEL_HELPSTR)
457 {
458 VTY_DECLVAR_CONTEXT(vrf, vrf);
459 struct zebra_vrf *zvrf = vrf->info;
460
461 /*
462 * Coverity is complaining that prefix could
463 * be dereferenced, but we know that prefix will
464 * valid. Add an assert to make it happy
465 */
466 assert(prefix);
467 return zebra_static_route_leak(vty, zvrf, zvrf,
468 AFI_IP, SAFI_UNICAST, no, prefix,
469 mask_str, NULL, NULL, NULL, flag,
470 tag_str, distance_str, label);
471 }
472
473 DEFPY(ip_route_address_interface,
474 ip_route_address_interface_cmd,
475 "[no] ip route\
476 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
477 A.B.C.D$gate \
478 INTERFACE$ifname \
479 [{ \
480 tag (1-4294967295) \
481 |(1-255)$distance \
482 |vrf NAME \
483 |label WORD \
484 |nexthop-vrf NAME \
485 }]",
486 NO_STR IP_STR
487 "Establish static routes\n"
488 "IP destination prefix (e.g. 10.0.0.0/8)\n"
489 "IP destination prefix\n"
490 "IP destination prefix mask\n"
491 "IP gateway address\n"
492 "IP gateway interface name. Specify 'Null0' (case-insensitive) for a \
493 null route.\n"
494 "Set tag for this route\n"
495 "Tag value\n"
496 "Distance value for this route\n"
497 VRF_CMD_HELP_STR
498 MPLS_LABEL_HELPSTR
499 VRF_CMD_HELP_STR)
500 {
501 struct zebra_vrf *zvrf;
502 struct zebra_vrf *nh_zvrf;
503
504 const char *flag = NULL;
505 if (ifname && !strncasecmp(ifname, "Null0", 5)) {
506 flag = "Null0";
507 ifname = NULL;
508 }
509
510 zvrf = zebra_vrf_lookup_by_name(vrf);
511 if (!zvrf) {
512 vty_out(vty, "%% vrf %s is not defined\n",
513 vrf);
514 return CMD_WARNING_CONFIG_FAILED;
515 }
516
517 if (nexthop_vrf)
518 nh_zvrf = zebra_vrf_lookup_by_name(nexthop_vrf);
519 else
520 nh_zvrf = zvrf;
521
522 if (!nh_zvrf) {
523 vty_out(vty, "%% nexthop vrf %s is not defined\n",
524 nexthop_vrf);
525 return CMD_WARNING_CONFIG_FAILED;
526 }
527
528 return zebra_static_route_leak(vty, zvrf, nh_zvrf,
529 AFI_IP, SAFI_UNICAST, no, prefix,
530 mask_str, NULL, gate_str, ifname, flag,
531 tag_str, distance_str, label);
532 }
533
534 DEFPY(ip_route_address_interface_vrf,
535 ip_route_address_interface_vrf_cmd,
536 "[no] ip route\
537 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
538 A.B.C.D$gate \
539 INTERFACE$ifname \
540 [{ \
541 tag (1-4294967295) \
542 |(1-255)$distance \
543 |label WORD \
544 |nexthop-vrf NAME \
545 }]",
546 NO_STR IP_STR
547 "Establish static routes\n"
548 "IP destination prefix (e.g. 10.0.0.0/8)\n"
549 "IP destination prefix\n"
550 "IP destination prefix mask\n"
551 "IP gateway address\n"
552 "IP gateway interface name. Specify 'Null0' (case-insensitive) for a \
553 null route.\n"
554 "Set tag for this route\n"
555 "Tag value\n"
556 "Distance value for this route\n"
557 MPLS_LABEL_HELPSTR
558 VRF_CMD_HELP_STR)
559 {
560 VTY_DECLVAR_CONTEXT(vrf, vrf);
561 const char *flag = NULL;
562 struct zebra_vrf *zvrf = vrf->info;
563 struct zebra_vrf *nh_zvrf;
564
565 if (ifname && !strncasecmp(ifname, "Null0", 5)) {
566 flag = "Null0";
567 ifname = NULL;
568 }
569
570 if (nexthop_vrf)
571 nh_zvrf = zebra_vrf_lookup_by_name(nexthop_vrf);
572 else
573 nh_zvrf = zvrf;
574
575 if (!nh_zvrf) {
576 vty_out(vty, "%% nexthop vrf %s is not defined\n",
577 nexthop_vrf);
578 return CMD_WARNING_CONFIG_FAILED;
579 }
580
581 return zebra_static_route_leak(vty, zvrf, nh_zvrf,
582 AFI_IP, SAFI_UNICAST, no, prefix,
583 mask_str, NULL, gate_str, ifname, flag,
584 tag_str, distance_str, label);
585 }
586
587 DEFPY(ip_route,
588 ip_route_cmd,
589 "[no] ip route\
590 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
591 <A.B.C.D$gate|INTERFACE$ifname> \
592 [{ \
593 tag (1-4294967295) \
594 |(1-255)$distance \
595 |vrf NAME \
596 |label WORD \
597 |nexthop-vrf NAME \
598 }]",
599 NO_STR IP_STR
600 "Establish static routes\n"
601 "IP destination prefix (e.g. 10.0.0.0/8)\n"
602 "IP destination prefix\n"
603 "IP destination prefix mask\n"
604 "IP gateway address\n"
605 "IP gateway interface name\n"
606 "Set tag for this route\n"
607 "Tag value\n"
608 "Distance value for this route\n"
609 VRF_CMD_HELP_STR
610 MPLS_LABEL_HELPSTR
611 VRF_CMD_HELP_STR)
612 {
613 struct zebra_vrf *zvrf;
614 struct zebra_vrf *nh_zvrf;
615 const char *flag = NULL;
616
617 if (ifname && !strncasecmp(ifname, "Null0", 5)) {
618 flag = "Null0";
619 ifname = NULL;
620 }
621
622 zvrf = zebra_vrf_lookup_by_name(vrf);
623 if (!zvrf) {
624 vty_out(vty, "%% vrf %s is not defined\n",
625 vrf);
626 return CMD_WARNING_CONFIG_FAILED;
627 }
628
629 if (nexthop_vrf)
630 nh_zvrf = zebra_vrf_lookup_by_name(nexthop_vrf);
631 else
632 nh_zvrf = zvrf;
633
634 if (!nh_zvrf) {
635 vty_out(vty, "%% nexthop vrf %s is not defined\n",
636 nexthop_vrf);
637 return CMD_WARNING_CONFIG_FAILED;
638 }
639
640
641 return zebra_static_route_leak(vty, zvrf, nh_zvrf,
642 AFI_IP, SAFI_UNICAST, no, prefix,
643 mask_str, NULL, gate_str, ifname, flag,
644 tag_str, distance_str, label);
645 }
646
647 DEFPY(ip_route_vrf,
648 ip_route_vrf_cmd,
649 "[no] ip route\
650 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
651 <A.B.C.D$gate|INTERFACE$ifname> \
652 [{ \
653 tag (1-4294967295) \
654 |(1-255)$distance \
655 |label WORD \
656 |nexthop-vrf NAME \
657 }]",
658 NO_STR IP_STR
659 "Establish static routes\n"
660 "IP destination prefix (e.g. 10.0.0.0/8)\n"
661 "IP destination prefix\n"
662 "IP destination prefix mask\n"
663 "IP gateway address\n"
664 "IP gateway interface name\n"
665 "Set tag for this route\n"
666 "Tag value\n"
667 "Distance value for this route\n"
668 MPLS_LABEL_HELPSTR
669 VRF_CMD_HELP_STR)
670 {
671 VTY_DECLVAR_CONTEXT(vrf, vrf);
672 struct zebra_vrf *zvrf = vrf->info;
673 struct zebra_vrf *nh_zvrf;
674
675 const char *flag = NULL;
676 if (ifname && !strncasecmp(ifname, "Null0", 5)) {
677 flag = "Null0";
678 ifname = NULL;
679 }
680
681 if (nexthop_vrf)
682 nh_zvrf = zebra_vrf_lookup_by_name(nexthop_vrf);
683 else
684 nh_zvrf = zvrf;
685
686 if (!nh_zvrf) {
687 vty_out(vty, "%% nexthop vrf %s is not defined\n",
688 nexthop_vrf);
689 return CMD_WARNING_CONFIG_FAILED;
690 }
691
692 return zebra_static_route_leak(vty, zvrf, nh_zvrf,
693 AFI_IP, SAFI_UNICAST, no, prefix,
694 mask_str, NULL, gate_str, ifname, flag,
695 tag_str, distance_str, label);
696 }
697
698 /* New RIB. Detailed information for IPv4 route. */
699 static void vty_show_ip_route_detail(struct vty *vty, struct route_node *rn,
700 int mcast)
701 {
702 struct route_entry *re;
703 struct nexthop *nexthop;
704 char buf[SRCDEST2STR_BUFFER];
705 struct zebra_vrf *zvrf;
706
707 RNODE_FOREACH_RE (rn, re) {
708 const char *mcast_info = "";
709 if (mcast) {
710 rib_table_info_t *info = srcdest_rnode_table_info(rn);
711 mcast_info = (info->safi == SAFI_MULTICAST)
712 ? " using Multicast RIB"
713 : " using Unicast RIB";
714 }
715
716 vty_out(vty, "Routing entry for %s%s\n",
717 srcdest_rnode2str(rn, buf, sizeof(buf)), mcast_info);
718 vty_out(vty, " Known via \"%s", zebra_route_string(re->type));
719 if (re->instance)
720 vty_out(vty, "[%d]", re->instance);
721 vty_out(vty, "\"");
722 vty_out(vty, ", distance %u, metric %u", re->distance,
723 re->metric);
724 if (re->tag) {
725 vty_out(vty, ", tag %u", re->tag);
726 #if defined(SUPPORT_REALMS)
727 if (re->tag > 0 && re->tag <= 255)
728 vty_out(vty, "(realm)");
729 #endif
730 }
731 if (re->mtu)
732 vty_out(vty, ", mtu %u", re->mtu);
733 if (re->vrf_id != VRF_DEFAULT) {
734 zvrf = vrf_info_lookup(re->vrf_id);
735 vty_out(vty, ", vrf %s", zvrf_name(zvrf));
736 }
737 if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED))
738 vty_out(vty, ", best");
739 vty_out(vty, "\n");
740
741 time_t uptime;
742 struct tm *tm;
743
744 uptime = time(NULL);
745 uptime -= re->uptime;
746 tm = gmtime(&uptime);
747
748 vty_out(vty, " Last update ");
749
750 if (uptime < ONE_DAY_SECOND)
751 vty_out(vty, "%02d:%02d:%02d", tm->tm_hour,
752 tm->tm_min, tm->tm_sec);
753 else if (uptime < ONE_WEEK_SECOND)
754 vty_out(vty, "%dd%02dh%02dm", tm->tm_yday,
755 tm->tm_hour, tm->tm_min);
756 else
757 vty_out(vty, "%02dw%dd%02dh", tm->tm_yday / 7,
758 tm->tm_yday - ((tm->tm_yday / 7) * 7),
759 tm->tm_hour);
760 vty_out(vty, " ago\n");
761
762 for (ALL_NEXTHOPS(re->nexthop, nexthop)) {
763 char addrstr[32];
764
765 vty_out(vty, " %c%s",
766 CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)
767 ? CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_DUPLICATE)
768 ? ' ' : '*'
769 : ' ',
770 nexthop->rparent ? " " : "");
771
772 switch (nexthop->type) {
773 case NEXTHOP_TYPE_IPV4:
774 case NEXTHOP_TYPE_IPV4_IFINDEX:
775 vty_out(vty, " %s",
776 inet_ntoa(nexthop->gate.ipv4));
777 if (nexthop->ifindex)
778 vty_out(vty, ", via %s",
779 ifindex2ifname(
780 nexthop->ifindex,
781 nexthop->vrf_id));
782 break;
783 case NEXTHOP_TYPE_IPV6:
784 case NEXTHOP_TYPE_IPV6_IFINDEX:
785 vty_out(vty, " %s",
786 inet_ntop(AF_INET6, &nexthop->gate.ipv6,
787 buf, sizeof buf));
788 if (nexthop->ifindex)
789 vty_out(vty, ", via %s",
790 ifindex2ifname(
791 nexthop->ifindex,
792 nexthop->vrf_id));
793 break;
794 case NEXTHOP_TYPE_IFINDEX:
795 vty_out(vty, " directly connected, %s",
796 ifindex2ifname(nexthop->ifindex,
797 nexthop->vrf_id));
798 break;
799 case NEXTHOP_TYPE_BLACKHOLE:
800 vty_out(vty, " unreachable");
801 switch (nexthop->bh_type) {
802 case BLACKHOLE_REJECT:
803 vty_out(vty, " (ICMP unreachable)");
804 break;
805 case BLACKHOLE_ADMINPROHIB:
806 vty_out(vty,
807 " (ICMP admin-prohibited)");
808 break;
809 case BLACKHOLE_NULL:
810 vty_out(vty, " (blackhole)");
811 break;
812 case BLACKHOLE_UNSPEC:
813 break;
814 }
815 break;
816 default:
817 break;
818 }
819
820 if (re->vrf_id != nexthop->vrf_id) {
821 struct vrf *vrf =
822 vrf_lookup_by_id(nexthop->vrf_id);
823
824 vty_out(vty, "(vrf %s)", vrf->name);
825 }
826
827 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_DUPLICATE))
828 vty_out(vty, " (duplicate nexthop removed)");
829
830 if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
831 vty_out(vty, " inactive");
832
833 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK))
834 vty_out(vty, " onlink");
835
836 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
837 vty_out(vty, " (recursive)");
838
839 switch (nexthop->type) {
840 case NEXTHOP_TYPE_IPV4:
841 case NEXTHOP_TYPE_IPV4_IFINDEX:
842 if (nexthop->src.ipv4.s_addr) {
843 if (inet_ntop(AF_INET,
844 &nexthop->src.ipv4,
845 addrstr, sizeof addrstr))
846 vty_out(vty, ", src %s",
847 addrstr);
848 }
849 break;
850 case NEXTHOP_TYPE_IPV6:
851 case NEXTHOP_TYPE_IPV6_IFINDEX:
852 if (!IPV6_ADDR_SAME(&nexthop->src.ipv6,
853 &in6addr_any)) {
854 if (inet_ntop(AF_INET6,
855 &nexthop->src.ipv6,
856 addrstr, sizeof addrstr))
857 vty_out(vty, ", src %s",
858 addrstr);
859 }
860 break;
861 default:
862 break;
863 }
864
865 if (re->nexthop_mtu)
866 vty_out(vty, ", mtu %u", re->nexthop_mtu);
867
868 /* Label information */
869 if (nexthop->nh_label
870 && nexthop->nh_label->num_labels) {
871 vty_out(vty, ", label %s",
872 mpls_label2str(
873 nexthop->nh_label->num_labels,
874 nexthop->nh_label->label, buf,
875 sizeof buf, 1));
876 }
877
878 vty_out(vty, "\n");
879 }
880 vty_out(vty, "\n");
881 }
882 }
883
884 static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
885 struct route_entry *re, json_object *json)
886 {
887 struct nexthop *nexthop;
888 int len = 0;
889 char buf[SRCDEST2STR_BUFFER];
890 json_object *json_nexthops = NULL;
891 json_object *json_nexthop = NULL;
892 json_object *json_route = NULL;
893 json_object *json_labels = NULL;
894 time_t uptime;
895 struct tm *tm;
896
897 uptime = time(NULL);
898 uptime -= re->uptime;
899 tm = gmtime(&uptime);
900
901 if (json) {
902 json_route = json_object_new_object();
903 json_nexthops = json_object_new_array();
904
905 json_object_string_add(json_route, "prefix",
906 srcdest_rnode2str(rn, buf, sizeof buf));
907 json_object_string_add(json_route, "protocol",
908 zebra_route_string(re->type));
909
910 if (re->instance)
911 json_object_int_add(json_route, "instance",
912 re->instance);
913
914 if (re->vrf_id)
915 json_object_int_add(json_route, "vrfId", re->vrf_id);
916
917 if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED))
918 json_object_boolean_true_add(json_route, "selected");
919
920 if (re->type != ZEBRA_ROUTE_CONNECT) {
921 json_object_int_add(json_route, "distance",
922 re->distance);
923 json_object_int_add(json_route, "metric", re->metric);
924 }
925
926 if (uptime < ONE_DAY_SECOND)
927 sprintf(buf, "%02d:%02d:%02d", tm->tm_hour,
928 tm->tm_min, tm->tm_sec);
929 else if (uptime < ONE_WEEK_SECOND)
930 sprintf(buf, "%dd%02dh%02dm", tm->tm_yday,
931 tm->tm_hour, tm->tm_min);
932 else
933 sprintf(buf, "%02dw%dd%02dh", tm->tm_yday / 7,
934 tm->tm_yday - ((tm->tm_yday / 7) * 7),
935 tm->tm_hour);
936
937 json_object_string_add(json_route, "uptime", buf);
938
939 for (ALL_NEXTHOPS(re->nexthop, nexthop)) {
940 json_nexthop = json_object_new_object();
941
942 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_DUPLICATE))
943 json_object_boolean_true_add(json_nexthop,
944 "duplicate");
945
946 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB))
947 json_object_boolean_true_add(json_nexthop,
948 "fib");
949
950 switch (nexthop->type) {
951 case NEXTHOP_TYPE_IPV4:
952 case NEXTHOP_TYPE_IPV4_IFINDEX:
953 json_object_string_add(
954 json_nexthop, "ip",
955 inet_ntoa(nexthop->gate.ipv4));
956 json_object_string_add(json_nexthop, "afi",
957 "ipv4");
958
959 if (nexthop->ifindex) {
960 json_object_int_add(json_nexthop,
961 "interfaceIndex",
962 nexthop->ifindex);
963 json_object_string_add(
964 json_nexthop, "interfaceName",
965 ifindex2ifname(
966 nexthop->ifindex,
967 nexthop->vrf_id));
968 }
969 break;
970 case NEXTHOP_TYPE_IPV6:
971 case NEXTHOP_TYPE_IPV6_IFINDEX:
972 json_object_string_add(
973 json_nexthop, "ip",
974 inet_ntop(AF_INET6, &nexthop->gate.ipv6,
975 buf, sizeof buf));
976 json_object_string_add(json_nexthop, "afi",
977 "ipv6");
978
979 if (nexthop->ifindex) {
980 json_object_int_add(json_nexthop,
981 "interfaceIndex",
982 nexthop->ifindex);
983 json_object_string_add(
984 json_nexthop, "interfaceName",
985 ifindex2ifname(
986 nexthop->ifindex,
987 nexthop->vrf_id));
988 }
989 break;
990
991 case NEXTHOP_TYPE_IFINDEX:
992 json_object_boolean_true_add(
993 json_nexthop, "directlyConnected");
994 json_object_int_add(json_nexthop,
995 "interfaceIndex",
996 nexthop->ifindex);
997 json_object_string_add(
998 json_nexthop, "interfaceName",
999 ifindex2ifname(nexthop->ifindex,
1000 nexthop->vrf_id));
1001 break;
1002 case NEXTHOP_TYPE_BLACKHOLE:
1003 json_object_boolean_true_add(json_nexthop,
1004 "unreachable");
1005 switch (nexthop->bh_type) {
1006 case BLACKHOLE_REJECT:
1007 json_object_boolean_true_add(
1008 json_nexthop, "reject");
1009 break;
1010 case BLACKHOLE_ADMINPROHIB:
1011 json_object_boolean_true_add(
1012 json_nexthop,
1013 "admin-prohibited");
1014 break;
1015 case BLACKHOLE_NULL:
1016 json_object_boolean_true_add(
1017 json_nexthop, "blackhole");
1018 break;
1019 case BLACKHOLE_UNSPEC:
1020 break;
1021 }
1022 break;
1023 default:
1024 break;
1025 }
1026
1027 if (nexthop->vrf_id != re->vrf_id) {
1028 struct vrf *vrf =
1029 vrf_lookup_by_id(nexthop->vrf_id);
1030
1031 json_object_string_add(json_nexthop,
1032 "vrf",
1033 vrf->name);
1034 }
1035 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_DUPLICATE))
1036 json_object_boolean_true_add(json_nexthop,
1037 "duplicate");
1038
1039 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
1040 json_object_boolean_true_add(json_nexthop,
1041 "active");
1042
1043 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK))
1044 json_object_boolean_true_add(json_nexthop,
1045 "onLink");
1046
1047 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
1048 json_object_boolean_true_add(json_nexthop,
1049 "recursive");
1050
1051 switch (nexthop->type) {
1052 case NEXTHOP_TYPE_IPV4:
1053 case NEXTHOP_TYPE_IPV4_IFINDEX:
1054 if (nexthop->src.ipv4.s_addr) {
1055 if (inet_ntop(AF_INET,
1056 &nexthop->src.ipv4, buf,
1057 sizeof buf))
1058 json_object_string_add(
1059 json_nexthop, "source",
1060 buf);
1061 }
1062 break;
1063 case NEXTHOP_TYPE_IPV6:
1064 case NEXTHOP_TYPE_IPV6_IFINDEX:
1065 if (!IPV6_ADDR_SAME(&nexthop->src.ipv6,
1066 &in6addr_any)) {
1067 if (inet_ntop(AF_INET6,
1068 &nexthop->src.ipv6, buf,
1069 sizeof buf))
1070 json_object_string_add(
1071 json_nexthop, "source",
1072 buf);
1073 }
1074 break;
1075 default:
1076 break;
1077 }
1078
1079 if (nexthop->nh_label
1080 && nexthop->nh_label->num_labels) {
1081 json_labels = json_object_new_array();
1082
1083 for (int label_index = 0;
1084 label_index
1085 < nexthop->nh_label->num_labels;
1086 label_index++)
1087 json_object_array_add(
1088 json_labels,
1089 json_object_new_int(
1090 nexthop->nh_label->label
1091 [label_index]));
1092
1093 json_object_object_add(json_nexthop, "labels",
1094 json_labels);
1095 }
1096
1097 json_object_array_add(json_nexthops, json_nexthop);
1098 }
1099
1100 json_object_object_add(json_route, "nexthops", json_nexthops);
1101 json_object_array_add(json, json_route);
1102 return;
1103 }
1104
1105 /* Nexthop information. */
1106 for (ALL_NEXTHOPS(re->nexthop, nexthop)) {
1107 if (nexthop == re->nexthop) {
1108 /* Prefix information. */
1109 len = vty_out(vty, "%c", zebra_route_char(re->type));
1110 if (re->instance)
1111 len += vty_out(vty, "[%d]", re->instance);
1112 len += vty_out(
1113 vty, "%c%c %s",
1114 CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED)
1115 ? '>'
1116 : ' ',
1117 CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)
1118 ? '*'
1119 : ' ',
1120 srcdest_rnode2str(rn, buf, sizeof buf));
1121
1122 /* Distance and metric display. */
1123 if (re->type != ZEBRA_ROUTE_CONNECT)
1124 len += vty_out(vty, " [%u/%u]", re->distance,
1125 re->metric);
1126 } else {
1127 vty_out(vty, " %c%*c",
1128 CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)
1129 ? CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_DUPLICATE)
1130 ? ' ' : '*'
1131 : ' ',
1132 len - 3 + (2 * nexthop_level(nexthop)), ' ');
1133 }
1134
1135 switch (nexthop->type) {
1136 case NEXTHOP_TYPE_IPV4:
1137 case NEXTHOP_TYPE_IPV4_IFINDEX:
1138 vty_out(vty, " via %s", inet_ntoa(nexthop->gate.ipv4));
1139 if (nexthop->ifindex)
1140 vty_out(vty, ", %s",
1141 ifindex2ifname(nexthop->ifindex,
1142 nexthop->vrf_id));
1143 break;
1144 case NEXTHOP_TYPE_IPV6:
1145 case NEXTHOP_TYPE_IPV6_IFINDEX:
1146 vty_out(vty, " via %s",
1147 inet_ntop(AF_INET6, &nexthop->gate.ipv6, buf,
1148 sizeof buf));
1149 if (nexthop->ifindex)
1150 vty_out(vty, ", %s",
1151 ifindex2ifname(nexthop->ifindex,
1152 nexthop->vrf_id));
1153 break;
1154
1155 case NEXTHOP_TYPE_IFINDEX:
1156 vty_out(vty, " is directly connected, %s",
1157 ifindex2ifname(nexthop->ifindex,
1158 nexthop->vrf_id));
1159 break;
1160 case NEXTHOP_TYPE_BLACKHOLE:
1161 vty_out(vty, " unreachable");
1162 switch (nexthop->bh_type) {
1163 case BLACKHOLE_REJECT:
1164 vty_out(vty, " (ICMP unreachable)");
1165 break;
1166 case BLACKHOLE_ADMINPROHIB:
1167 vty_out(vty, " (ICMP admin-prohibited)");
1168 break;
1169 case BLACKHOLE_NULL:
1170 vty_out(vty, " (blackhole)");
1171 break;
1172 case BLACKHOLE_UNSPEC:
1173 break;
1174 }
1175 break;
1176 default:
1177 break;
1178 }
1179
1180 if (nexthop->vrf_id != re->vrf_id) {
1181 struct vrf *vrf = vrf_lookup_by_id(nexthop->vrf_id);
1182
1183 vty_out(vty, "(vrf %s)", vrf->name);
1184 }
1185
1186 if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
1187 vty_out(vty, " inactive");
1188
1189 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK))
1190 vty_out(vty, " onlink");
1191
1192 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
1193 vty_out(vty, " (recursive)");
1194
1195 switch (nexthop->type) {
1196 case NEXTHOP_TYPE_IPV4:
1197 case NEXTHOP_TYPE_IPV4_IFINDEX:
1198 if (nexthop->src.ipv4.s_addr) {
1199 if (inet_ntop(AF_INET, &nexthop->src.ipv4, buf,
1200 sizeof buf))
1201 vty_out(vty, ", src %s", buf);
1202 }
1203 break;
1204 case NEXTHOP_TYPE_IPV6:
1205 case NEXTHOP_TYPE_IPV6_IFINDEX:
1206 if (!IPV6_ADDR_SAME(&nexthop->src.ipv6, &in6addr_any)) {
1207 if (inet_ntop(AF_INET6, &nexthop->src.ipv6, buf,
1208 sizeof buf))
1209 vty_out(vty, ", src %s", buf);
1210 }
1211 break;
1212 default:
1213 break;
1214 }
1215
1216 /* Label information */
1217 if (nexthop->nh_label && nexthop->nh_label->num_labels) {
1218 vty_out(vty, ", label %s",
1219 mpls_label2str(nexthop->nh_label->num_labels,
1220 nexthop->nh_label->label, buf,
1221 sizeof buf, 1));
1222 }
1223
1224 if (uptime < ONE_DAY_SECOND)
1225 vty_out(vty, ", %02d:%02d:%02d", tm->tm_hour,
1226 tm->tm_min, tm->tm_sec);
1227 else if (uptime < ONE_WEEK_SECOND)
1228 vty_out(vty, ", %dd%02dh%02dm", tm->tm_yday,
1229 tm->tm_hour, tm->tm_min);
1230 else
1231 vty_out(vty, ", %02dw%dd%02dh", tm->tm_yday / 7,
1232 tm->tm_yday - ((tm->tm_yday / 7) * 7),
1233 tm->tm_hour);
1234 vty_out(vty, "\n");
1235 }
1236 }
1237
1238 static void do_show_route_helper(struct vty *vty, struct zebra_vrf *zvrf,
1239 struct route_table *table, afi_t afi,
1240 bool use_fib, route_tag_t tag,
1241 const struct prefix *longer_prefix_p,
1242 bool supernets_only, int type,
1243 u_short ospf_instance_id, u_char use_json)
1244 {
1245 struct route_node *rn;
1246 struct route_entry *re;
1247 int first = 1;
1248 rib_dest_t *dest;
1249 json_object *json = NULL;
1250 json_object *json_prefix = NULL;
1251 uint32_t addr;
1252 char buf[BUFSIZ];
1253
1254 if (use_json)
1255 json = json_object_new_object();
1256
1257 /* Show all routes. */
1258 for (rn = route_top(table); rn; rn = route_next(rn)) {
1259 dest = rib_dest_from_rnode(rn);
1260
1261 RNODE_FOREACH_RE (rn, re) {
1262 if (use_fib
1263 && re != dest->selected_fib)
1264 continue;
1265
1266 if (tag && re->tag != tag)
1267 continue;
1268
1269 if (longer_prefix_p
1270 && !prefix_match(longer_prefix_p, &rn->p))
1271 continue;
1272
1273 /* This can only be true when the afi is IPv4 */
1274 if (supernets_only) {
1275 addr = ntohl(rn->p.u.prefix4.s_addr);
1276
1277 if (IN_CLASSC(addr) && rn->p.prefixlen >= 24)
1278 continue;
1279
1280 if (IN_CLASSB(addr) && rn->p.prefixlen >= 16)
1281 continue;
1282
1283 if (IN_CLASSA(addr) && rn->p.prefixlen >= 8)
1284 continue;
1285 }
1286
1287 if (type && re->type != type)
1288 continue;
1289
1290 if (ospf_instance_id
1291 && (re->type != ZEBRA_ROUTE_OSPF
1292 || re->instance != ospf_instance_id))
1293 continue;
1294
1295 if (use_json) {
1296 if (!json_prefix)
1297 json_prefix = json_object_new_array();
1298 } else {
1299 if (first) {
1300 if (afi == AFI_IP)
1301 vty_out(vty,
1302 SHOW_ROUTE_V4_HEADER);
1303 else
1304 vty_out(vty,
1305 SHOW_ROUTE_V6_HEADER);
1306
1307 if (zvrf_id(zvrf) != VRF_DEFAULT)
1308 vty_out(vty, "\nVRF %s:\n",
1309 zvrf_name(zvrf));
1310
1311 first = 0;
1312 }
1313 }
1314
1315 vty_show_ip_route(vty, rn, re, json_prefix);
1316 }
1317
1318 if (json_prefix) {
1319 prefix2str(&rn->p, buf, sizeof buf);
1320 json_object_object_add(json, buf, json_prefix);
1321 json_prefix = NULL;
1322 }
1323 }
1324
1325 if (use_json) {
1326 vty_out(vty, "%s\n", json_object_to_json_string_ext(
1327 json, JSON_C_TO_STRING_PRETTY));
1328 json_object_free(json);
1329 }
1330 }
1331
1332 static int do_show_ip_route(struct vty *vty, const char *vrf_name, afi_t afi,
1333 safi_t safi, bool use_fib, u_char use_json,
1334 route_tag_t tag,
1335 const struct prefix *longer_prefix_p,
1336 bool supernets_only, int type,
1337 u_short ospf_instance_id)
1338 {
1339 struct route_table *table;
1340 struct zebra_vrf *zvrf = NULL;
1341
1342 if (!(zvrf = zebra_vrf_lookup_by_name(vrf_name))) {
1343 if (use_json)
1344 vty_out(vty, "{}\n");
1345 else
1346 vty_out(vty, "vrf %s not defined\n", vrf_name);
1347 return CMD_SUCCESS;
1348 }
1349
1350 if (zvrf_id(zvrf) == VRF_UNKNOWN) {
1351 if (use_json)
1352 vty_out(vty, "{}\n");
1353 else
1354 vty_out(vty, "vrf %s inactive\n", vrf_name);
1355 return CMD_SUCCESS;
1356 }
1357
1358 table = zebra_vrf_table(afi, safi, zvrf_id(zvrf));
1359 if (!table) {
1360 if (use_json)
1361 vty_out(vty, "{}\n");
1362 return CMD_SUCCESS;
1363 }
1364
1365 do_show_route_helper(vty, zvrf, table, afi, use_fib, tag,
1366 longer_prefix_p, supernets_only, type,
1367 ospf_instance_id, use_json);
1368
1369 return CMD_SUCCESS;
1370 }
1371
1372 DEFPY (show_route_table,
1373 show_route_table_cmd,
1374 "show <ip$ipv4|ipv6$ipv6> route table (1-4294967295)$table [json$json]",
1375 SHOW_STR
1376 IP_STR
1377 IP6_STR
1378 "IP routing table\n"
1379 "Table to display\n"
1380 "The table number to display, if available\n"
1381 JSON_STR)
1382 {
1383 afi_t afi = ipv4 ? AFI_IP : AFI_IP6;
1384 struct zebra_vrf *zvrf = zebra_vrf_lookup_by_id(VRF_DEFAULT);
1385 struct route_table *t;
1386
1387 t = zebra_ns_find_table(zvrf->zns, table, afi);
1388 if (t)
1389 do_show_route_helper(vty, zvrf, t, afi, false, 0, false, false,
1390 0, 0, !!json);
1391
1392 return CMD_SUCCESS;
1393 }
1394
1395 DEFUN (show_ip_nht,
1396 show_ip_nht_cmd,
1397 "show ip nht [vrf NAME]",
1398 SHOW_STR
1399 IP_STR
1400 "IP nexthop tracking table\n"
1401 VRF_CMD_HELP_STR)
1402 {
1403 int idx_vrf = 4;
1404 vrf_id_t vrf_id = VRF_DEFAULT;
1405
1406 if (argc == 5)
1407 VRF_GET_ID(vrf_id, argv[idx_vrf]->arg);
1408
1409 zebra_print_rnh_table(vrf_id, AF_INET, vty, RNH_NEXTHOP_TYPE);
1410 return CMD_SUCCESS;
1411 }
1412
1413
1414 DEFUN (show_ip_nht_vrf_all,
1415 show_ip_nht_vrf_all_cmd,
1416 "show ip nht vrf all",
1417 SHOW_STR
1418 IP_STR
1419 "IP nexthop tracking table\n"
1420 VRF_ALL_CMD_HELP_STR)
1421 {
1422 struct vrf *vrf;
1423 struct zebra_vrf *zvrf;
1424
1425 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name)
1426 if ((zvrf = vrf->info) != NULL) {
1427 vty_out(vty, "\nVRF %s:\n", zvrf_name(zvrf));
1428 zebra_print_rnh_table(zvrf_id(zvrf), AF_INET, vty,
1429 RNH_NEXTHOP_TYPE);
1430 }
1431
1432 return CMD_SUCCESS;
1433 }
1434
1435 DEFUN (show_ipv6_nht,
1436 show_ipv6_nht_cmd,
1437 "show ipv6 nht [vrf NAME]",
1438 SHOW_STR
1439 IPV6_STR
1440 "IPv6 nexthop tracking table\n"
1441 VRF_CMD_HELP_STR)
1442 {
1443 int idx_vrf = 4;
1444 vrf_id_t vrf_id = VRF_DEFAULT;
1445
1446 if (argc == 5)
1447 VRF_GET_ID(vrf_id, argv[idx_vrf]->arg);
1448
1449 zebra_print_rnh_table(vrf_id, AF_INET6, vty, RNH_NEXTHOP_TYPE);
1450 return CMD_SUCCESS;
1451 }
1452
1453
1454 DEFUN (show_ipv6_nht_vrf_all,
1455 show_ipv6_nht_vrf_all_cmd,
1456 "show ipv6 nht vrf all",
1457 SHOW_STR
1458 IP_STR
1459 "IPv6 nexthop tracking table\n"
1460 VRF_ALL_CMD_HELP_STR)
1461 {
1462 struct vrf *vrf;
1463 struct zebra_vrf *zvrf;
1464
1465 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name)
1466 if ((zvrf = vrf->info) != NULL) {
1467 vty_out(vty, "\nVRF %s:\n", zvrf_name(zvrf));
1468 zebra_print_rnh_table(zvrf_id(zvrf), AF_INET6, vty,
1469 RNH_NEXTHOP_TYPE);
1470 }
1471
1472 return CMD_SUCCESS;
1473 }
1474
1475 DEFUN (ip_nht_default_route,
1476 ip_nht_default_route_cmd,
1477 "ip nht resolve-via-default",
1478 IP_STR
1479 "Filter Next Hop tracking route resolution\n"
1480 "Resolve via default route\n")
1481 {
1482 if (zebra_rnh_ip_default_route)
1483 return CMD_SUCCESS;
1484
1485 zebra_rnh_ip_default_route = 1;
1486 zebra_evaluate_rnh(VRF_DEFAULT, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL);
1487 return CMD_SUCCESS;
1488 }
1489
1490 DEFUN (no_ip_nht_default_route,
1491 no_ip_nht_default_route_cmd,
1492 "no ip nht resolve-via-default",
1493 NO_STR
1494 IP_STR
1495 "Filter Next Hop tracking route resolution\n"
1496 "Resolve via default route\n")
1497 {
1498 if (!zebra_rnh_ip_default_route)
1499 return CMD_SUCCESS;
1500
1501 zebra_rnh_ip_default_route = 0;
1502 zebra_evaluate_rnh(VRF_DEFAULT, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL);
1503 return CMD_SUCCESS;
1504 }
1505
1506 DEFUN (ipv6_nht_default_route,
1507 ipv6_nht_default_route_cmd,
1508 "ipv6 nht resolve-via-default",
1509 IP6_STR
1510 "Filter Next Hop tracking route resolution\n"
1511 "Resolve via default route\n")
1512 {
1513 if (zebra_rnh_ipv6_default_route)
1514 return CMD_SUCCESS;
1515
1516 zebra_rnh_ipv6_default_route = 1;
1517 zebra_evaluate_rnh(VRF_DEFAULT, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL);
1518 return CMD_SUCCESS;
1519 }
1520
1521 DEFUN (no_ipv6_nht_default_route,
1522 no_ipv6_nht_default_route_cmd,
1523 "no ipv6 nht resolve-via-default",
1524 NO_STR
1525 IP6_STR
1526 "Filter Next Hop tracking route resolution\n"
1527 "Resolve via default route\n")
1528 {
1529 if (!zebra_rnh_ipv6_default_route)
1530 return CMD_SUCCESS;
1531
1532 zebra_rnh_ipv6_default_route = 0;
1533 zebra_evaluate_rnh(VRF_DEFAULT, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL);
1534 return CMD_SUCCESS;
1535 }
1536
1537 DEFPY (show_route,
1538 show_route_cmd,
1539 "show\
1540 <\
1541 ip$ipv4 <fib$fib|route> [vrf <NAME$vrf_name|all$vrf_all>]\
1542 [{\
1543 tag (1-4294967295)\
1544 |A.B.C.D/M$prefix longer-prefixes\
1545 |supernets-only$supernets_only\
1546 }]\
1547 [<\
1548 " FRR_IP_REDIST_STR_ZEBRA "$type_str\
1549 |ospf$type_str (1-65535)$ospf_instance_id\
1550 >]\
1551 |ipv6$ipv6 <fib$fib|route> [vrf <NAME$vrf_name|all$vrf_all>]\
1552 [{\
1553 tag (1-4294967295)\
1554 |X:X::X:X/M$prefix longer-prefixes\
1555 }]\
1556 [" FRR_IP6_REDIST_STR_ZEBRA "$type_str]\
1557 >\
1558 [json$json]",
1559 SHOW_STR
1560 IP_STR
1561 "IP forwarding table\n"
1562 "IP routing table\n"
1563 VRF_FULL_CMD_HELP_STR
1564 "Show only routes with tag\n"
1565 "Tag value\n"
1566 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
1567 "Show route matching the specified Network/Mask pair only\n"
1568 "Show supernet entries only\n"
1569 FRR_IP_REDIST_HELP_STR_ZEBRA
1570 "Open Shortest Path First (OSPFv2)\n"
1571 "Instance ID\n"
1572 IPV6_STR
1573 "IP forwarding table\n"
1574 "IP routing table\n"
1575 VRF_FULL_CMD_HELP_STR
1576 "Show only routes with tag\n"
1577 "Tag value\n"
1578 "IPv6 prefix\n"
1579 "Show route matching the specified Network/Mask pair only\n"
1580 FRR_IP6_REDIST_HELP_STR_ZEBRA
1581 JSON_STR)
1582 {
1583 afi_t afi = ipv4 ? AFI_IP : AFI_IP6;
1584 struct vrf *vrf;
1585 int type = 0;
1586
1587 if (type_str) {
1588 type = proto_redistnum(afi, type_str);
1589 if (type < 0) {
1590 vty_out(vty, "Unknown route type\n");
1591 return CMD_WARNING;
1592 }
1593 }
1594
1595 if (vrf_all) {
1596 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
1597 struct zebra_vrf *zvrf;
1598 struct route_table *table;
1599
1600 if ((zvrf = vrf->info) == NULL
1601 || (table = zvrf->table[afi][SAFI_UNICAST]) == NULL)
1602 continue;
1603
1604 do_show_ip_route(
1605 vty, zvrf_name(zvrf), afi, SAFI_UNICAST, !!fib,
1606 !!json, tag, prefix_str ? prefix : NULL,
1607 !!supernets_only, type, ospf_instance_id);
1608 }
1609 } else {
1610 vrf_id_t vrf_id = VRF_DEFAULT;
1611
1612 if (vrf_name)
1613 VRF_GET_ID(vrf_id, vrf_name);
1614 vrf = vrf_lookup_by_id(vrf_id);
1615 do_show_ip_route(vty, vrf->name, afi, SAFI_UNICAST, !!fib,
1616 !!json, tag, prefix_str ? prefix : NULL,
1617 !!supernets_only, type, ospf_instance_id);
1618 }
1619
1620 return CMD_SUCCESS;
1621 }
1622
1623 DEFPY (show_route_detail,
1624 show_route_detail_cmd,
1625 "show\
1626 <\
1627 ip$ipv4 route [vrf <NAME$vrf_name|all$vrf_all>]\
1628 <\
1629 A.B.C.D$address\
1630 |A.B.C.D/M$prefix\
1631 >\
1632 |ipv6$ipv6 route [vrf <NAME$vrf_name|all$vrf_all>]\
1633 <\
1634 X:X::X:X$address\
1635 |X:X::X:X/M$prefix\
1636 >\
1637 >",
1638 SHOW_STR
1639 IP_STR
1640 "IP routing table\n"
1641 VRF_FULL_CMD_HELP_STR
1642 "Network in the IP routing table to display\n"
1643 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
1644 IP6_STR
1645 "IP routing table\n"
1646 VRF_FULL_CMD_HELP_STR
1647 "IPv6 Address\n"
1648 "IPv6 prefix\n")
1649 {
1650 afi_t afi = ipv4 ? AFI_IP : AFI_IP6;
1651 struct route_table *table;
1652 struct prefix p;
1653 struct route_node *rn;
1654
1655 if (address_str)
1656 prefix_str = address_str;
1657 if (str2prefix(prefix_str, &p) < 0) {
1658 vty_out(vty, "%% Malformed address\n");
1659 return CMD_WARNING;
1660 }
1661
1662 if (vrf_all) {
1663 struct vrf *vrf;
1664 struct zebra_vrf *zvrf;
1665
1666 RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) {
1667 if ((zvrf = vrf->info) == NULL
1668 || (table = zvrf->table[afi][SAFI_UNICAST]) == NULL)
1669 continue;
1670
1671 rn = route_node_match(table, &p);
1672 if (!rn)
1673 continue;
1674 if (!address_str && rn->p.prefixlen != p.prefixlen) {
1675 route_unlock_node(rn);
1676 continue;
1677 }
1678
1679 vty_show_ip_route_detail(vty, rn, 0);
1680
1681 route_unlock_node(rn);
1682 }
1683 } else {
1684 vrf_id_t vrf_id = VRF_DEFAULT;
1685
1686 if (vrf_name)
1687 VRF_GET_ID(vrf_id, vrf_name);
1688
1689 table = zebra_vrf_table(afi, SAFI_UNICAST, vrf_id);
1690 if (!table)
1691 return CMD_SUCCESS;
1692
1693 rn = route_node_match(table, &p);
1694 if (!rn) {
1695 vty_out(vty, "%% Network not in table\n");
1696 return CMD_WARNING;
1697 }
1698 if (!address_str && rn->p.prefixlen != p.prefixlen) {
1699 vty_out(vty, "%% Network not in table\n");
1700 route_unlock_node(rn);
1701 return CMD_WARNING;
1702 }
1703
1704 vty_show_ip_route_detail(vty, rn, 0);
1705
1706 route_unlock_node(rn);
1707 }
1708
1709 return CMD_SUCCESS;
1710 }
1711
1712 DEFPY (show_route_summary,
1713 show_route_summary_cmd,
1714 "show\
1715 <\
1716 ip$ipv4 route [vrf <NAME$vrf_name|all$vrf_all>]\
1717 summary [prefix$prefix]\
1718 |ipv6$ipv6 route [vrf <NAME$vrf_name|all$vrf_all>]\
1719 summary [prefix$prefix]\
1720 >",
1721 SHOW_STR
1722 IP_STR
1723 "IP routing table\n"
1724 VRF_FULL_CMD_HELP_STR
1725 "Summary of all routes\n"
1726 "Prefix routes\n"
1727 IP6_STR
1728 "IP routing table\n"
1729 VRF_FULL_CMD_HELP_STR
1730 "Summary of all routes\n"
1731 "Prefix routes\n")
1732 {
1733 afi_t afi = ipv4 ? AFI_IP : AFI_IP6;
1734 struct route_table *table;
1735
1736 if (vrf_all) {
1737 struct vrf *vrf;
1738 struct zebra_vrf *zvrf;
1739
1740 RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) {
1741 if ((zvrf = vrf->info) == NULL
1742 || (table = zvrf->table[afi][SAFI_UNICAST]) == NULL)
1743 continue;
1744
1745 if (prefix)
1746 vty_show_ip_route_summary_prefix(vty, table);
1747 else
1748 vty_show_ip_route_summary(vty, table);
1749 }
1750 } else {
1751 vrf_id_t vrf_id = VRF_DEFAULT;
1752
1753 if (vrf_name)
1754 VRF_GET_ID(vrf_id, vrf_name);
1755
1756 table = zebra_vrf_table(afi, SAFI_UNICAST, vrf_id);
1757 if (!table)
1758 return CMD_SUCCESS;
1759
1760 if (prefix)
1761 vty_show_ip_route_summary_prefix(vty, table);
1762 else
1763 vty_show_ip_route_summary(vty, table);
1764 }
1765
1766 return CMD_SUCCESS;
1767 }
1768
1769 static void vty_show_ip_route_summary(struct vty *vty,
1770 struct route_table *table)
1771 {
1772 struct route_node *rn;
1773 struct route_entry *re;
1774 #define ZEBRA_ROUTE_IBGP ZEBRA_ROUTE_MAX
1775 #define ZEBRA_ROUTE_TOTAL (ZEBRA_ROUTE_IBGP + 1)
1776 u_int32_t rib_cnt[ZEBRA_ROUTE_TOTAL + 1];
1777 u_int32_t fib_cnt[ZEBRA_ROUTE_TOTAL + 1];
1778 u_int32_t i;
1779 u_int32_t is_ibgp;
1780
1781 memset(&rib_cnt, 0, sizeof(rib_cnt));
1782 memset(&fib_cnt, 0, sizeof(fib_cnt));
1783 for (rn = route_top(table); rn; rn = srcdest_route_next(rn))
1784 RNODE_FOREACH_RE (rn, re) {
1785 is_ibgp = (re->type == ZEBRA_ROUTE_BGP
1786 && CHECK_FLAG(re->flags, ZEBRA_FLAG_IBGP));
1787
1788 rib_cnt[ZEBRA_ROUTE_TOTAL]++;
1789 if (is_ibgp)
1790 rib_cnt[ZEBRA_ROUTE_IBGP]++;
1791 else
1792 rib_cnt[re->type]++;
1793
1794 if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED)) {
1795 fib_cnt[ZEBRA_ROUTE_TOTAL]++;
1796
1797 if (is_ibgp)
1798 fib_cnt[ZEBRA_ROUTE_IBGP]++;
1799 else
1800 fib_cnt[re->type]++;
1801 }
1802 }
1803
1804 vty_out(vty, "%-20s %-20s %s (vrf %s)\n", "Route Source", "Routes",
1805 "FIB", zvrf_name(((rib_table_info_t *)table->info)->zvrf));
1806
1807 for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
1808 if ((rib_cnt[i] > 0) || (i == ZEBRA_ROUTE_BGP
1809 && rib_cnt[ZEBRA_ROUTE_IBGP] > 0)) {
1810 if (i == ZEBRA_ROUTE_BGP) {
1811 vty_out(vty, "%-20s %-20d %-20d \n", "ebgp",
1812 rib_cnt[ZEBRA_ROUTE_BGP],
1813 fib_cnt[ZEBRA_ROUTE_BGP]);
1814 vty_out(vty, "%-20s %-20d %-20d \n", "ibgp",
1815 rib_cnt[ZEBRA_ROUTE_IBGP],
1816 fib_cnt[ZEBRA_ROUTE_IBGP]);
1817 } else
1818 vty_out(vty, "%-20s %-20d %-20d \n",
1819 zebra_route_string(i), rib_cnt[i],
1820 fib_cnt[i]);
1821 }
1822 }
1823
1824 vty_out(vty, "------\n");
1825 vty_out(vty, "%-20s %-20d %-20d \n", "Totals",
1826 rib_cnt[ZEBRA_ROUTE_TOTAL], fib_cnt[ZEBRA_ROUTE_TOTAL]);
1827 vty_out(vty, "\n");
1828 }
1829
1830 /*
1831 * Implementation of the ip route summary prefix command.
1832 *
1833 * This command prints the primary prefixes that have been installed by various
1834 * protocols on the box.
1835 *
1836 */
1837 static void vty_show_ip_route_summary_prefix(struct vty *vty,
1838 struct route_table *table)
1839 {
1840 struct route_node *rn;
1841 struct route_entry *re;
1842 struct nexthop *nexthop;
1843 #define ZEBRA_ROUTE_IBGP ZEBRA_ROUTE_MAX
1844 #define ZEBRA_ROUTE_TOTAL (ZEBRA_ROUTE_IBGP + 1)
1845 u_int32_t rib_cnt[ZEBRA_ROUTE_TOTAL + 1];
1846 u_int32_t fib_cnt[ZEBRA_ROUTE_TOTAL + 1];
1847 u_int32_t i;
1848 int cnt;
1849
1850 memset(&rib_cnt, 0, sizeof(rib_cnt));
1851 memset(&fib_cnt, 0, sizeof(fib_cnt));
1852 for (rn = route_top(table); rn; rn = srcdest_route_next(rn))
1853 RNODE_FOREACH_RE (rn, re) {
1854
1855 /*
1856 * In case of ECMP, count only once.
1857 */
1858 cnt = 0;
1859 for (nexthop = re->nexthop; (!cnt && nexthop);
1860 nexthop = nexthop->next) {
1861 cnt++;
1862 rib_cnt[ZEBRA_ROUTE_TOTAL]++;
1863 rib_cnt[re->type]++;
1864 if (CHECK_FLAG(nexthop->flags,
1865 NEXTHOP_FLAG_FIB)) {
1866 fib_cnt[ZEBRA_ROUTE_TOTAL]++;
1867 fib_cnt[re->type]++;
1868 }
1869 if (re->type == ZEBRA_ROUTE_BGP
1870 && CHECK_FLAG(re->flags, ZEBRA_FLAG_IBGP)) {
1871 rib_cnt[ZEBRA_ROUTE_IBGP]++;
1872 if (CHECK_FLAG(nexthop->flags,
1873 NEXTHOP_FLAG_FIB))
1874 fib_cnt[ZEBRA_ROUTE_IBGP]++;
1875 }
1876 }
1877 }
1878
1879 vty_out(vty, "%-20s %-20s %s (vrf %s)\n", "Route Source",
1880 "Prefix Routes", "FIB",
1881 zvrf_name(((rib_table_info_t *)table->info)->zvrf));
1882
1883 for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
1884 if (rib_cnt[i] > 0) {
1885 if (i == ZEBRA_ROUTE_BGP) {
1886 vty_out(vty, "%-20s %-20d %-20d \n", "ebgp",
1887 rib_cnt[ZEBRA_ROUTE_BGP]
1888 - rib_cnt[ZEBRA_ROUTE_IBGP],
1889 fib_cnt[ZEBRA_ROUTE_BGP]
1890 - fib_cnt[ZEBRA_ROUTE_IBGP]);
1891 vty_out(vty, "%-20s %-20d %-20d \n", "ibgp",
1892 rib_cnt[ZEBRA_ROUTE_IBGP],
1893 fib_cnt[ZEBRA_ROUTE_IBGP]);
1894 } else
1895 vty_out(vty, "%-20s %-20d %-20d \n",
1896 zebra_route_string(i), rib_cnt[i],
1897 fib_cnt[i]);
1898 }
1899 }
1900
1901 vty_out(vty, "------\n");
1902 vty_out(vty, "%-20s %-20d %-20d \n", "Totals",
1903 rib_cnt[ZEBRA_ROUTE_TOTAL], fib_cnt[ZEBRA_ROUTE_TOTAL]);
1904 vty_out(vty, "\n");
1905 }
1906
1907 /* Write static route configuration. */
1908 int static_config(struct vty *vty, struct zebra_vrf *zvrf,
1909 afi_t afi, safi_t safi, const char *cmd)
1910 {
1911 char spacing[100];
1912 struct route_node *rn;
1913 struct static_route *si;
1914 struct route_table *stable;
1915 char buf[SRCDEST2STR_BUFFER];
1916 int write = 0;
1917
1918 if ((stable = zvrf->stable[afi][safi]) == NULL)
1919 return write;
1920
1921 sprintf(spacing, "%s%s",
1922 (zvrf->vrf->vrf_id == VRF_DEFAULT) ? "" : " ",
1923 cmd);
1924
1925 for (rn = route_top(stable); rn; rn = srcdest_route_next(rn))
1926 for (si = rn->info; si; si = si->next) {
1927 vty_out(vty, "%s %s", spacing,
1928 srcdest_rnode2str(rn, buf, sizeof buf));
1929
1930 switch (si->type) {
1931 case STATIC_IPV4_GATEWAY:
1932 vty_out(vty, " %s",
1933 inet_ntoa(si->addr.ipv4));
1934 break;
1935 case STATIC_IPV6_GATEWAY:
1936 vty_out(vty, " %s",
1937 inet_ntop(AF_INET6,
1938 &si->addr.ipv6, buf,
1939 sizeof buf));
1940 break;
1941 case STATIC_IFNAME:
1942 vty_out(vty, " %s", si->ifname);
1943 break;
1944 case STATIC_BLACKHOLE:
1945 switch (si->bh_type) {
1946 case STATIC_BLACKHOLE_DROP:
1947 vty_out(vty, " blackhole");
1948 break;
1949 case STATIC_BLACKHOLE_NULL:
1950 vty_out(vty, " Null0");
1951 break;
1952 case STATIC_BLACKHOLE_REJECT:
1953 vty_out(vty, " reject");
1954 break;
1955 }
1956 break;
1957 case STATIC_IPV4_GATEWAY_IFNAME:
1958 vty_out(vty, " %s %s",
1959 inet_ntop(AF_INET,
1960 &si->addr.ipv4, buf,
1961 sizeof buf),
1962 si->ifname);
1963 break;
1964 case STATIC_IPV6_GATEWAY_IFNAME:
1965 vty_out(vty, " %s %s",
1966 inet_ntop(AF_INET6,
1967 &si->addr.ipv6, buf,
1968 sizeof buf),
1969 si->ifname);
1970 break;
1971 }
1972
1973 if (si->tag)
1974 vty_out(vty, " tag %" ROUTE_TAG_PRI,
1975 si->tag);
1976
1977 if (si->distance
1978 != ZEBRA_STATIC_DISTANCE_DEFAULT)
1979 vty_out(vty, " %d", si->distance);
1980
1981 if (si->nh_vrf_id != si->vrf_id) {
1982 struct vrf *vrf;
1983
1984 vrf = vrf_lookup_by_id(si->nh_vrf_id);
1985 vty_out(vty, " nexthop-vrf %s",
1986 (vrf) ? vrf->name : "Unknown");
1987 }
1988
1989 /* Label information */
1990 if (si->snh_label.num_labels)
1991 vty_out(vty, " label %s",
1992 mpls_label2str(si->snh_label.num_labels,
1993 si->snh_label.label,
1994 buf, sizeof buf, 0));
1995
1996 vty_out(vty, "\n");
1997
1998 write = 1;
1999 }
2000 return write;
2001 }
2002
2003 DEFPY(ipv6_route_blackhole,
2004 ipv6_route_blackhole_cmd,
2005 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
2006 <Null0|reject|blackhole>$flag \
2007 [{ \
2008 tag (1-4294967295) \
2009 |(1-255)$distance \
2010 |vrf NAME \
2011 |label WORD \
2012 }]",
2013 NO_STR
2014 IPV6_STR
2015 "Establish static routes\n"
2016 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
2017 "IPv6 source-dest route\n"
2018 "IPv6 source prefix\n"
2019 "Null interface\n"
2020 "Emit an ICMP unreachable when matched\n"
2021 "Silently discard pkts when matched\n"
2022 "Set tag for this route\n"
2023 "Tag value\n"
2024 "Distance value for this prefix\n"
2025 VRF_CMD_HELP_STR
2026 MPLS_LABEL_HELPSTR)
2027 {
2028 return zebra_static_route(vty, AFI_IP6, SAFI_UNICAST, no, prefix_str,
2029 NULL, from_str, NULL, NULL, flag,
2030 tag_str, distance_str, vrf, label);
2031 }
2032
2033 DEFPY(ipv6_route_blackhole_vrf,
2034 ipv6_route_blackhole_vrf_cmd,
2035 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
2036 <Null0|reject|blackhole>$flag \
2037 [{ \
2038 tag (1-4294967295) \
2039 |(1-255)$distance \
2040 |label WORD \
2041 }]",
2042 NO_STR
2043 IPV6_STR
2044 "Establish static routes\n"
2045 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
2046 "IPv6 source-dest route\n"
2047 "IPv6 source prefix\n"
2048 "Null interface\n"
2049 "Emit an ICMP unreachable when matched\n"
2050 "Silently discard pkts when matched\n"
2051 "Set tag for this route\n"
2052 "Tag value\n"
2053 "Distance value for this prefix\n"
2054 MPLS_LABEL_HELPSTR)
2055 {
2056 VTY_DECLVAR_CONTEXT(vrf, vrf);
2057 struct zebra_vrf *zvrf = vrf->info;
2058
2059 /*
2060 * Coverity is complaining that prefix could
2061 * be dereferenced, but we know that prefix will
2062 * valid. Add an assert to make it happy
2063 */
2064 assert(prefix);
2065 return zebra_static_route_leak(vty, zvrf, zvrf,
2066 AFI_IP6, SAFI_UNICAST, no, prefix_str,
2067 NULL, from_str, NULL, NULL, flag,
2068 tag_str, distance_str, label);
2069 }
2070
2071 DEFPY(ipv6_route_address_interface,
2072 ipv6_route_address_interface_cmd,
2073 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
2074 X:X::X:X$gate \
2075 INTERFACE$ifname \
2076 [{ \
2077 tag (1-4294967295) \
2078 |(1-255)$distance \
2079 |vrf NAME \
2080 |label WORD \
2081 |nexthop-vrf NAME \
2082 }]",
2083 NO_STR
2084 IPV6_STR
2085 "Establish static routes\n"
2086 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
2087 "IPv6 source-dest route\n"
2088 "IPv6 source prefix\n"
2089 "IPv6 gateway address\n"
2090 "IPv6 gateway interface name\n"
2091 "Set tag for this route\n"
2092 "Tag value\n"
2093 "Distance value for this prefix\n"
2094 VRF_CMD_HELP_STR
2095 MPLS_LABEL_HELPSTR
2096 VRF_CMD_HELP_STR)
2097 {
2098 struct zebra_vrf *zvrf;
2099 struct zebra_vrf *nh_zvrf;
2100
2101 zvrf = zebra_vrf_lookup_by_name(vrf);
2102 if (!zvrf) {
2103 vty_out(vty, "%% vrf %s is not defined\n",
2104 vrf);
2105 return CMD_WARNING_CONFIG_FAILED;
2106 }
2107
2108 if (nexthop_vrf)
2109 nh_zvrf = zebra_vrf_lookup_by_name(nexthop_vrf);
2110 else
2111 nh_zvrf = zvrf;
2112
2113 if (!nh_zvrf) {
2114 vty_out(vty, "%% nexthop vrf %s is not defined\n",
2115 nexthop_vrf);
2116 return CMD_WARNING_CONFIG_FAILED;
2117 }
2118
2119 return zebra_static_route_leak(vty, zvrf, nh_zvrf,
2120 AFI_IP6, SAFI_UNICAST, no, prefix_str,
2121 NULL, from_str, gate_str, ifname, NULL,
2122 tag_str, distance_str, label);
2123 }
2124
2125 DEFPY(ipv6_route_address_interface_vrf,
2126 ipv6_route_address_interface_vrf_cmd,
2127 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
2128 X:X::X:X$gate \
2129 INTERFACE$ifname \
2130 [{ \
2131 tag (1-4294967295) \
2132 |(1-255)$distance \
2133 |label WORD \
2134 |nexthop-vrf NAME \
2135 }]",
2136 NO_STR
2137 IPV6_STR
2138 "Establish static routes\n"
2139 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
2140 "IPv6 source-dest route\n"
2141 "IPv6 source prefix\n"
2142 "IPv6 gateway address\n"
2143 "IPv6 gateway interface name\n"
2144 "Set tag for this route\n"
2145 "Tag value\n"
2146 "Distance value for this prefix\n"
2147 MPLS_LABEL_HELPSTR
2148 VRF_CMD_HELP_STR)
2149 {
2150 VTY_DECLVAR_CONTEXT(vrf, vrf);
2151 struct zebra_vrf *zvrf = vrf->info;
2152 struct zebra_vrf *nh_zvrf;
2153
2154 if (nexthop_vrf)
2155 nh_zvrf = zebra_vrf_lookup_by_name(nexthop_vrf);
2156 else
2157 nh_zvrf = zvrf;
2158
2159 if (!nh_zvrf) {
2160 vty_out(vty, "%% nexthop vrf %s is not defined\n",
2161 nexthop_vrf);
2162 return CMD_WARNING_CONFIG_FAILED;
2163 }
2164
2165 return zebra_static_route_leak(vty, zvrf, nh_zvrf,
2166 AFI_IP6, SAFI_UNICAST, no, prefix_str,
2167 NULL, from_str, gate_str, ifname, NULL,
2168 tag_str, distance_str, label);
2169 }
2170
2171 DEFPY(ipv6_route,
2172 ipv6_route_cmd,
2173 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
2174 <X:X::X:X$gate|INTERFACE$ifname> \
2175 [{ \
2176 tag (1-4294967295) \
2177 |(1-255)$distance \
2178 |vrf NAME \
2179 |label WORD \
2180 |nexthop-vrf NAME \
2181 }]",
2182 NO_STR
2183 IPV6_STR
2184 "Establish static routes\n"
2185 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
2186 "IPv6 source-dest route\n"
2187 "IPv6 source prefix\n"
2188 "IPv6 gateway address\n"
2189 "IPv6 gateway interface name\n"
2190 "Set tag for this route\n"
2191 "Tag value\n"
2192 "Distance value for this prefix\n"
2193 VRF_CMD_HELP_STR
2194 MPLS_LABEL_HELPSTR
2195 VRF_CMD_HELP_STR)
2196 {
2197 struct zebra_vrf *zvrf;
2198 struct zebra_vrf *nh_zvrf;
2199
2200 zvrf = zebra_vrf_lookup_by_name(vrf);
2201 if (!zvrf) {
2202 vty_out(vty, "%% vrf %s is not defined\n",
2203 vrf);
2204 return CMD_WARNING_CONFIG_FAILED;
2205 }
2206
2207 if (nexthop_vrf)
2208 nh_zvrf = zebra_vrf_lookup_by_name(nexthop_vrf);
2209 else
2210 nh_zvrf = zvrf;
2211
2212 if (!nh_zvrf) {
2213 vty_out(vty, "%% nexthop vrf %s is not defined\n",
2214 nexthop_vrf);
2215 return CMD_WARNING_CONFIG_FAILED;
2216 }
2217
2218 return zebra_static_route_leak(vty, zvrf, nh_zvrf,
2219 AFI_IP6, SAFI_UNICAST, no, prefix_str,
2220 NULL, from_str, gate_str, ifname, NULL,
2221 tag_str, distance_str, label);
2222 }
2223
2224 DEFPY(ipv6_route_vrf,
2225 ipv6_route_vrf_cmd,
2226 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M] \
2227 <X:X::X:X$gate|INTERFACE$ifname> \
2228 [{ \
2229 tag (1-4294967295) \
2230 |(1-255)$distance \
2231 |label WORD \
2232 |nexthop-vrf NAME \
2233 }]",
2234 NO_STR
2235 IPV6_STR
2236 "Establish static routes\n"
2237 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
2238 "IPv6 source-dest route\n"
2239 "IPv6 source prefix\n"
2240 "IPv6 gateway address\n"
2241 "IPv6 gateway interface name\n"
2242 "Set tag for this route\n"
2243 "Tag value\n"
2244 "Distance value for this prefix\n"
2245 MPLS_LABEL_HELPSTR
2246 VRF_CMD_HELP_STR)
2247 {
2248 VTY_DECLVAR_CONTEXT(vrf, vrf);
2249 struct zebra_vrf *zvrf = vrf->info;
2250 struct zebra_vrf *nh_zvrf;
2251
2252 if (nexthop_vrf)
2253 nh_zvrf = zebra_vrf_lookup_by_name(nexthop_vrf);
2254 else
2255 nh_zvrf = zvrf;
2256
2257 if (!nh_zvrf) {
2258 vty_out(vty, "%% nexthop vrf %s is not defined\n",
2259 nexthop_vrf);
2260 return CMD_WARNING_CONFIG_FAILED;
2261 }
2262
2263 return zebra_static_route_leak(vty, zvrf, nh_zvrf,
2264 AFI_IP6, SAFI_UNICAST, no, prefix_str,
2265 NULL, from_str, gate_str, ifname, NULL,
2266 tag_str, distance_str, label);
2267 }
2268
2269 /*
2270 * Show IPv6 mroute command.Used to dump
2271 * the Multicast routing table.
2272 */
2273 DEFUN (show_ipv6_mroute,
2274 show_ipv6_mroute_cmd,
2275 "show ipv6 mroute [vrf NAME]",
2276 SHOW_STR
2277 IP_STR
2278 "IPv6 Multicast routing table\n"
2279 VRF_CMD_HELP_STR)
2280 {
2281 struct route_table *table;
2282 struct route_node *rn;
2283 struct route_entry *re;
2284 int first = 1;
2285 vrf_id_t vrf_id = VRF_DEFAULT;
2286
2287 if (argc == 5)
2288 VRF_GET_ID(vrf_id, argv[4]->arg);
2289
2290 table = zebra_vrf_table(AFI_IP6, SAFI_MULTICAST, vrf_id);
2291 if (!table)
2292 return CMD_SUCCESS;
2293
2294 /* Show all IPv6 route. */
2295 for (rn = route_top(table); rn; rn = srcdest_route_next(rn))
2296 RNODE_FOREACH_RE (rn, re) {
2297 if (first) {
2298 vty_out(vty, SHOW_ROUTE_V6_HEADER);
2299 first = 0;
2300 }
2301 vty_show_ip_route(vty, rn, re, NULL);
2302 }
2303 return CMD_SUCCESS;
2304 }
2305
2306 DEFUN (show_ipv6_mroute_vrf_all,
2307 show_ipv6_mroute_vrf_all_cmd,
2308 "show ipv6 mroute vrf all",
2309 SHOW_STR
2310 IP_STR
2311 "IPv6 Multicast routing table\n"
2312 VRF_ALL_CMD_HELP_STR)
2313 {
2314 struct route_table *table;
2315 struct route_node *rn;
2316 struct route_entry *re;
2317 struct vrf *vrf;
2318 struct zebra_vrf *zvrf;
2319 int first = 1;
2320
2321 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
2322 if ((zvrf = vrf->info) == NULL
2323 || (table = zvrf->table[AFI_IP6][SAFI_MULTICAST]) == NULL)
2324 continue;
2325
2326 /* Show all IPv6 route. */
2327 for (rn = route_top(table); rn; rn = srcdest_route_next(rn))
2328 RNODE_FOREACH_RE (rn, re) {
2329 if (first) {
2330 vty_out(vty, SHOW_ROUTE_V6_HEADER);
2331 first = 0;
2332 }
2333 vty_show_ip_route(vty, rn, re, NULL);
2334 }
2335 }
2336 return CMD_SUCCESS;
2337 }
2338
2339 DEFUN (allow_external_route_update,
2340 allow_external_route_update_cmd,
2341 "allow-external-route-update",
2342 "Allow FRR routes to be overwritten by external processes\n")
2343 {
2344 allow_delete = 1;
2345
2346 return CMD_SUCCESS;
2347 }
2348
2349 DEFUN (no_allow_external_route_update,
2350 no_allow_external_route_update_cmd,
2351 "no allow-external-route-update",
2352 NO_STR
2353 "Allow FRR routes to be overwritten by external processes\n")
2354 {
2355 allow_delete = 0;
2356
2357 return CMD_SUCCESS;
2358 }
2359
2360 /* show vrf */
2361 DEFUN (show_vrf,
2362 show_vrf_cmd,
2363 "show vrf",
2364 SHOW_STR
2365 "VRF\n")
2366 {
2367 struct vrf *vrf;
2368 struct zebra_vrf *zvrf;
2369
2370 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
2371 if (!(zvrf = vrf->info))
2372 continue;
2373 if (zvrf_id(zvrf) == VRF_DEFAULT)
2374 continue;
2375
2376 vty_out(vty, "vrf %s ", zvrf_name(zvrf));
2377 if (zvrf_id(zvrf) == VRF_UNKNOWN
2378 || !zvrf_is_active(zvrf))
2379 vty_out(vty, "inactive");
2380 else if (zvrf_ns_name(zvrf))
2381 vty_out(vty, "id %u netns %s",
2382 zvrf_id(zvrf), zvrf_ns_name(zvrf));
2383 else
2384 vty_out(vty, "id %u table %u", zvrf_id(zvrf),
2385 zvrf->table_id);
2386 if (vrf_is_user_cfged(vrf))
2387 vty_out(vty, " (configured)");
2388 vty_out(vty, "\n");
2389 }
2390
2391 return CMD_SUCCESS;
2392 }
2393
2394 DEFUN (default_vrf_vni_mapping,
2395 default_vrf_vni_mapping_cmd,
2396 "vni " CMD_VNI_RANGE "[prefix-routes-only]",
2397 "VNI corresponding to the DEFAULT VRF\n"
2398 "VNI-ID\n"
2399 "Prefix routes only \n")
2400 {
2401 int ret = 0;
2402 char err[ERR_STR_SZ];
2403 struct zebra_vrf *zvrf = NULL;
2404 vni_t vni = strtoul(argv[1]->arg, NULL, 10);
2405 int filter = 0;
2406
2407 zvrf = vrf_info_lookup(VRF_DEFAULT);
2408 if (!zvrf)
2409 return CMD_WARNING;
2410
2411 if (argc == 3)
2412 filter = 1;
2413
2414 ret = zebra_vxlan_process_vrf_vni_cmd(zvrf, vni, err, ERR_STR_SZ,
2415 filter, 1);
2416 if (ret != 0) {
2417 vty_out(vty, "%s\n", err);
2418 return CMD_WARNING;
2419 }
2420
2421 return CMD_SUCCESS;
2422 }
2423
2424 DEFUN (no_default_vrf_vni_mapping,
2425 no_default_vrf_vni_mapping_cmd,
2426 "no vni " CMD_VNI_RANGE,
2427 NO_STR
2428 "VNI corresponding to DEFAULT VRF\n"
2429 "VNI-ID")
2430 {
2431 int ret = 0;
2432 char err[ERR_STR_SZ];
2433 vni_t vni = strtoul(argv[2]->arg, NULL, 10);
2434 struct zebra_vrf *zvrf = NULL;
2435
2436 zvrf = vrf_info_lookup(VRF_DEFAULT);
2437 if (!zvrf)
2438 return CMD_WARNING;
2439
2440 ret = zebra_vxlan_process_vrf_vni_cmd(zvrf, vni, err, ERR_STR_SZ, 0, 0);
2441 if (ret != 0) {
2442 vty_out(vty, "%s\n", err);
2443 return CMD_WARNING;
2444 }
2445
2446 return CMD_SUCCESS;
2447 }
2448
2449 DEFUN (vrf_vni_mapping,
2450 vrf_vni_mapping_cmd,
2451 "vni " CMD_VNI_RANGE "[prefix-routes-only]",
2452 "VNI corresponding to tenant VRF\n"
2453 "VNI-ID\n"
2454 "prefix-routes-only\n")
2455 {
2456 int ret = 0;
2457 int filter = 0;
2458
2459 ZEBRA_DECLVAR_CONTEXT(vrf, zvrf);
2460 vni_t vni = strtoul(argv[1]->arg, NULL, 10);
2461 char err[ERR_STR_SZ];
2462
2463 assert(vrf);
2464 assert(zvrf);
2465
2466 if (argc == 3)
2467 filter = 1;
2468
2469 /* Mark as having FRR configuration */
2470 vrf_set_user_cfged(vrf);
2471 ret = zebra_vxlan_process_vrf_vni_cmd(zvrf, vni, err, ERR_STR_SZ,
2472 filter, 1);
2473 if (ret != 0) {
2474 vty_out(vty, "%s\n", err);
2475 return CMD_WARNING;
2476 }
2477
2478 return CMD_SUCCESS;
2479 }
2480
2481 DEFUN (no_vrf_vni_mapping,
2482 no_vrf_vni_mapping_cmd,
2483 "no vni " CMD_VNI_RANGE,
2484 NO_STR
2485 "VNI corresponding to tenant VRF\n"
2486 "VNI-ID")
2487 {
2488 int ret = 0;
2489 char err[ERR_STR_SZ];
2490 vni_t vni = strtoul(argv[2]->arg, NULL, 10);
2491
2492 ZEBRA_DECLVAR_CONTEXT(vrf, zvrf);
2493
2494 assert(vrf);
2495 assert(zvrf);
2496
2497 ret = zebra_vxlan_process_vrf_vni_cmd(zvrf, vni, err, ERR_STR_SZ, 0, 0);
2498 if (ret != 0) {
2499 vty_out(vty, "%s\n", err);
2500 return CMD_WARNING;
2501 }
2502
2503 /* If no other FRR config for this VRF, mark accordingly. */
2504 if (!zebra_vrf_has_config(zvrf))
2505 vrf_reset_user_cfged(vrf);
2506
2507 return CMD_SUCCESS;
2508 }
2509
2510 /* show vrf */
2511 DEFUN (show_vrf_vni,
2512 show_vrf_vni_cmd,
2513 "show vrf vni [json]",
2514 SHOW_STR
2515 "VRF\n"
2516 "VNI\n"
2517 JSON_STR)
2518 {
2519 struct vrf *vrf;
2520 struct zebra_vrf *zvrf;
2521 json_object *json = NULL;
2522 json_object *json_vrfs = NULL;
2523 u_char uj = use_json(argc, argv);
2524
2525 if (uj) {
2526 json = json_object_new_object();
2527 json_vrfs = json_object_new_array();
2528 }
2529
2530 if (!uj)
2531 vty_out(vty, "%-37s %-10s %-20s %-20s %-5s %-18s\n",
2532 "VRF", "VNI", "VxLAN IF", "L3-SVI", "State", "Rmac");
2533
2534 RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) {
2535 zvrf = vrf->info;
2536 if (!zvrf)
2537 continue;
2538
2539 zebra_vxlan_print_vrf_vni(vty, zvrf, json_vrfs);
2540 }
2541
2542 if (uj) {
2543 json_object_object_add(json, "vrfs", json_vrfs);
2544 vty_out(vty, "%s\n", json_object_to_json_string_ext(
2545 json, JSON_C_TO_STRING_PRETTY));
2546 json_object_free(json);
2547 }
2548
2549 return CMD_SUCCESS;
2550 }
2551
2552 DEFUN (show_evpn_global,
2553 show_evpn_global_cmd,
2554 "show evpn [json]",
2555 SHOW_STR
2556 "EVPN\n"
2557 JSON_STR)
2558 {
2559 u_char uj = use_json(argc, argv);
2560
2561 zebra_vxlan_print_evpn(vty, uj);
2562 return CMD_SUCCESS;
2563 }
2564
2565 DEFUN (show_evpn_vni,
2566 show_evpn_vni_cmd,
2567 "show evpn vni [json]",
2568 SHOW_STR
2569 "EVPN\n"
2570 "VxLAN information\n"
2571 JSON_STR)
2572 {
2573 struct zebra_vrf *zvrf;
2574 u_char uj = use_json(argc, argv);
2575
2576 zvrf = vrf_info_lookup(VRF_DEFAULT);
2577 zebra_vxlan_print_vnis(vty, zvrf, uj);
2578 return CMD_SUCCESS;
2579 }
2580
2581 DEFUN (show_evpn_vni_vni,
2582 show_evpn_vni_vni_cmd,
2583 "show evpn vni " CMD_VNI_RANGE "[json]",
2584 SHOW_STR
2585 "EVPN\n"
2586 "VxLAN Network Identifier\n"
2587 "VNI number\n"
2588 JSON_STR)
2589 {
2590 struct zebra_vrf *zvrf;
2591 vni_t vni;
2592 u_char uj = use_json(argc, argv);
2593
2594 vni = strtoul(argv[3]->arg, NULL, 10);
2595 zvrf = vrf_info_lookup(VRF_DEFAULT);
2596 zebra_vxlan_print_vni(vty, zvrf, vni, uj);
2597 return CMD_SUCCESS;
2598 }
2599
2600 DEFUN (show_evpn_rmac_vni_mac,
2601 show_evpn_rmac_vni_mac_cmd,
2602 "show evpn rmac vni " CMD_VNI_RANGE " mac WORD [json]",
2603 SHOW_STR
2604 "EVPN\n"
2605 "RMAC\n"
2606 "L3 VNI\n"
2607 "VNI number\n"
2608 "MAC\n"
2609 "mac-address (e.g. 0a:0a:0a:0a:0a:0a)\n"
2610 JSON_STR)
2611 {
2612 vni_t l3vni = 0;
2613 struct ethaddr mac;
2614 u_char uj = use_json(argc, argv);
2615
2616 l3vni = strtoul(argv[4]->arg, NULL, 10);
2617 if (!prefix_str2mac(argv[6]->arg, &mac)) {
2618 vty_out(vty, "%% Malformed MAC address\n");
2619 return CMD_WARNING;
2620 }
2621 zebra_vxlan_print_specific_rmac_l3vni(vty, l3vni, &mac, uj);
2622 return CMD_SUCCESS;
2623 }
2624
2625 DEFUN (show_evpn_rmac_vni,
2626 show_evpn_rmac_vni_cmd,
2627 "show evpn rmac vni " CMD_VNI_RANGE "[json]",
2628 SHOW_STR
2629 "EVPN\n"
2630 "RMAC\n"
2631 "L3 VNI\n"
2632 "VNI number\n"
2633 JSON_STR)
2634 {
2635 vni_t l3vni = 0;
2636 u_char uj = use_json(argc, argv);
2637
2638 l3vni = strtoul(argv[4]->arg, NULL, 10);
2639 zebra_vxlan_print_rmacs_l3vni(vty, l3vni, uj);
2640
2641 return CMD_SUCCESS;
2642 }
2643
2644 DEFUN (show_evpn_rmac_vni_all,
2645 show_evpn_rmac_vni_all_cmd,
2646 "show evpn rmac vni all [json]",
2647 SHOW_STR
2648 "EVPN\n"
2649 "RMAC addresses\n"
2650 "L3 VNI\n"
2651 "All VNIs\n"
2652 JSON_STR)
2653 {
2654 u_char uj = use_json(argc, argv);
2655
2656 zebra_vxlan_print_rmacs_all_l3vni(vty, uj);
2657
2658 return CMD_SUCCESS;
2659 }
2660
2661 DEFUN (show_evpn_nh_vni_ip,
2662 show_evpn_nh_vni_ip_cmd,
2663 "show evpn next-hops vni " CMD_VNI_RANGE " ip WORD [json]",
2664 SHOW_STR
2665 "EVPN\n"
2666 "Remote Vteps\n"
2667 "L3 VNI\n"
2668 "VNI number\n"
2669 "Ip address\n"
2670 "Host address (ipv4 or ipv6)\n"
2671 JSON_STR)
2672 {
2673 vni_t l3vni;
2674 struct ipaddr ip;
2675 u_char uj = use_json(argc, argv);
2676
2677 l3vni = strtoul(argv[4]->arg, NULL, 10);
2678 if (str2ipaddr(argv[6]->arg, &ip) != 0) {
2679 if (!uj)
2680 vty_out(vty, "%% Malformed Neighbor address\n");
2681 return CMD_WARNING;
2682 }
2683 zebra_vxlan_print_specific_nh_l3vni(vty, l3vni, &ip, uj);
2684
2685 return CMD_SUCCESS;
2686 }
2687
2688 DEFUN (show_evpn_nh_vni,
2689 show_evpn_nh_vni_cmd,
2690 "show evpn next-hops vni " CMD_VNI_RANGE "[json]",
2691 SHOW_STR
2692 "EVPN\n"
2693 "Remote Vteps\n"
2694 "L3 VNI\n"
2695 "VNI number\n"
2696 JSON_STR)
2697 {
2698 vni_t l3vni;
2699 u_char uj = use_json(argc, argv);
2700
2701 l3vni = strtoul(argv[4]->arg, NULL, 10);
2702 zebra_vxlan_print_nh_l3vni(vty, l3vni, uj);
2703
2704 return CMD_SUCCESS;
2705 }
2706
2707 DEFUN (show_evpn_nh_vni_all,
2708 show_evpn_nh_vni_all_cmd,
2709 "show evpn next-hops vni all [json]",
2710 SHOW_STR
2711 "EVPN\n"
2712 "Remote VTEPs\n"
2713 "L3 VNI\n"
2714 "All VNIs\n"
2715 JSON_STR)
2716 {
2717 u_char uj = use_json(argc, argv);
2718
2719 zebra_vxlan_print_nh_all_l3vni(vty, uj);
2720
2721 return CMD_SUCCESS;
2722 }
2723
2724 DEFUN (show_evpn_mac_vni,
2725 show_evpn_mac_vni_cmd,
2726 "show evpn mac vni " CMD_VNI_RANGE "[json]",
2727 SHOW_STR
2728 "EVPN\n"
2729 "MAC addresses\n"
2730 "VxLAN Network Identifier\n"
2731 "VNI number\n"
2732 JSON_STR)
2733 {
2734 struct zebra_vrf *zvrf;
2735 vni_t vni;
2736 u_char uj = use_json(argc, argv);
2737
2738 vni = strtoul(argv[4]->arg, NULL, 10);
2739 zvrf = vrf_info_lookup(VRF_DEFAULT);
2740 zebra_vxlan_print_macs_vni(vty, zvrf, vni, uj);
2741 return CMD_SUCCESS;
2742 }
2743
2744 DEFUN (show_evpn_mac_vni_all,
2745 show_evpn_mac_vni_all_cmd,
2746 "show evpn mac vni all [json]",
2747 SHOW_STR
2748 "EVPN\n"
2749 "MAC addresses\n"
2750 "VxLAN Network Identifier\n"
2751 "All VNIs\n"
2752 JSON_STR)
2753 {
2754 struct zebra_vrf *zvrf;
2755 u_char uj = use_json(argc, argv);
2756
2757 zvrf = vrf_info_lookup(VRF_DEFAULT);
2758 zebra_vxlan_print_macs_all_vni(vty, zvrf, uj);
2759 return CMD_SUCCESS;
2760 }
2761
2762 DEFUN (show_evpn_mac_vni_all_vtep,
2763 show_evpn_mac_vni_all_vtep_cmd,
2764 "show evpn mac vni all vtep A.B.C.D [json]",
2765 SHOW_STR
2766 "EVPN\n"
2767 "MAC addresses\n"
2768 "VxLAN Network Identifier\n"
2769 "All VNIs\n"
2770 "Remote VTEP\n"
2771 "Remote VTEP IP address\n"
2772 JSON_STR)
2773 {
2774 struct zebra_vrf *zvrf;
2775 struct in_addr vtep_ip;
2776 u_char uj = use_json(argc, argv);
2777
2778 if (!inet_aton(argv[6]->arg, &vtep_ip)) {
2779 if (!uj)
2780 vty_out(vty, "%% Malformed VTEP IP address\n");
2781 return CMD_WARNING;
2782 }
2783 zvrf = vrf_info_lookup(VRF_DEFAULT);
2784 zebra_vxlan_print_macs_all_vni_vtep(vty, zvrf, vtep_ip, uj);
2785
2786 return CMD_SUCCESS;
2787 }
2788
2789
2790 DEFUN (show_evpn_mac_vni_mac,
2791 show_evpn_mac_vni_mac_cmd,
2792 "show evpn mac vni " CMD_VNI_RANGE " mac WORD",
2793 SHOW_STR
2794 "EVPN\n"
2795 "MAC addresses\n"
2796 "VxLAN Network Identifier\n"
2797 "VNI number\n"
2798 "MAC\n"
2799 "MAC address (e.g., 00:e0:ec:20:12:62)\n")
2800 {
2801 struct zebra_vrf *zvrf;
2802 vni_t vni;
2803 struct ethaddr mac;
2804
2805 vni = strtoul(argv[4]->arg, NULL, 10);
2806 if (!prefix_str2mac(argv[6]->arg, &mac)) {
2807 vty_out(vty, "%% Malformed MAC address");
2808 return CMD_WARNING;
2809 }
2810 zvrf = vrf_info_lookup(VRF_DEFAULT);
2811 zebra_vxlan_print_specific_mac_vni(vty, zvrf, vni, &mac);
2812 return CMD_SUCCESS;
2813 }
2814
2815 DEFUN (show_evpn_mac_vni_vtep,
2816 show_evpn_mac_vni_vtep_cmd,
2817 "show evpn mac vni " CMD_VNI_RANGE " vtep A.B.C.D" "[json]",
2818 SHOW_STR
2819 "EVPN\n"
2820 "MAC addresses\n"
2821 "VxLAN Network Identifier\n"
2822 "VNI number\n"
2823 "Remote VTEP\n"
2824 "Remote VTEP IP address\n"
2825 JSON_STR)
2826 {
2827 struct zebra_vrf *zvrf;
2828 vni_t vni;
2829 struct in_addr vtep_ip;
2830 u_char uj = use_json(argc, argv);
2831
2832 vni = strtoul(argv[4]->arg, NULL, 10);
2833 if (!inet_aton(argv[6]->arg, &vtep_ip)) {
2834 if (!uj)
2835 vty_out(vty, "%% Malformed VTEP IP address\n");
2836 return CMD_WARNING;
2837 }
2838
2839 zvrf = vrf_info_lookup(VRF_DEFAULT);
2840 zebra_vxlan_print_macs_vni_vtep(vty, zvrf, vni, vtep_ip, uj);
2841 return CMD_SUCCESS;
2842 }
2843
2844 DEFUN (show_evpn_neigh_vni,
2845 show_evpn_neigh_vni_cmd,
2846 "show evpn arp-cache vni " CMD_VNI_RANGE "[json]",
2847 SHOW_STR
2848 "EVPN\n"
2849 "ARP and ND cache\n"
2850 "VxLAN Network Identifier\n"
2851 "VNI number\n"
2852 JSON_STR)
2853 {
2854 struct zebra_vrf *zvrf;
2855 vni_t vni;
2856 u_char uj = use_json(argc, argv);
2857
2858 vni = strtoul(argv[4]->arg, NULL, 10);
2859 zvrf = vrf_info_lookup(VRF_DEFAULT);
2860 zebra_vxlan_print_neigh_vni(vty, zvrf, vni, uj);
2861 return CMD_SUCCESS;
2862 }
2863
2864 DEFUN (show_evpn_neigh_vni_all,
2865 show_evpn_neigh_vni_all_cmd,
2866 "show evpn arp-cache vni all [json]",
2867 SHOW_STR
2868 "EVPN\n"
2869 "ARP and ND cache\n"
2870 "VxLAN Network Identifier\n"
2871 "All VNIs\n"
2872 JSON_STR)
2873 {
2874 struct zebra_vrf *zvrf;
2875 u_char uj = use_json(argc, argv);
2876
2877 zvrf = vrf_info_lookup(VRF_DEFAULT);
2878 zebra_vxlan_print_neigh_all_vni(vty, zvrf, uj);
2879 return CMD_SUCCESS;
2880 }
2881
2882 DEFUN (show_evpn_neigh_vni_neigh,
2883 show_evpn_neigh_vni_neigh_cmd,
2884 "show evpn arp-cache vni " CMD_VNI_RANGE " ip WORD [json]",
2885 SHOW_STR
2886 "EVPN\n"
2887 "ARP and ND cache\n"
2888 "VxLAN Network Identifier\n"
2889 "VNI number\n"
2890 "Neighbor\n"
2891 "Neighbor address (IPv4 or IPv6 address)\n"
2892 JSON_STR)
2893 {
2894 struct zebra_vrf *zvrf;
2895 vni_t vni;
2896 struct ipaddr ip;
2897 u_char uj = use_json(argc, argv);
2898
2899 vni = strtoul(argv[4]->arg, NULL, 10);
2900 if (str2ipaddr(argv[6]->arg, &ip) != 0) {
2901 if (!uj)
2902 vty_out(vty, "%% Malformed Neighbor address\n");
2903 return CMD_WARNING;
2904 }
2905 zvrf = vrf_info_lookup(VRF_DEFAULT);
2906 zebra_vxlan_print_specific_neigh_vni(vty, zvrf, vni, &ip, uj);
2907 return CMD_SUCCESS;
2908 }
2909
2910 DEFUN (show_evpn_neigh_vni_vtep,
2911 show_evpn_neigh_vni_vtep_cmd,
2912 "show evpn arp-cache vni " CMD_VNI_RANGE " vtep A.B.C.D [json]",
2913 SHOW_STR
2914 "EVPN\n"
2915 "ARP and ND cache\n"
2916 "VxLAN Network Identifier\n"
2917 "VNI number\n"
2918 "Remote VTEP\n"
2919 "Remote VTEP IP address\n"
2920 JSON_STR)
2921 {
2922 struct zebra_vrf *zvrf;
2923 vni_t vni;
2924 struct in_addr vtep_ip;
2925 u_char uj = use_json(argc, argv);
2926
2927 vni = strtoul(argv[4]->arg, NULL, 10);
2928 if (!inet_aton(argv[6]->arg, &vtep_ip)) {
2929 if (!uj)
2930 vty_out(vty, "%% Malformed VTEP IP address\n");
2931 return CMD_WARNING;
2932 }
2933
2934 zvrf = vrf_info_lookup(VRF_DEFAULT);
2935 zebra_vxlan_print_neigh_vni_vtep(vty, zvrf, vni, vtep_ip, uj);
2936 return CMD_SUCCESS;
2937 }
2938
2939 /* Static ip route configuration write function. */
2940 static int zebra_ip_config(struct vty *vty)
2941 {
2942 int write = 0;
2943
2944 write += zebra_import_table_config(vty);
2945
2946 return write;
2947 }
2948
2949 DEFUN (ip_zebra_import_table_distance,
2950 ip_zebra_import_table_distance_cmd,
2951 "ip import-table (1-252) [distance (1-255)] [route-map WORD]",
2952 IP_STR
2953 "import routes from non-main kernel table\n"
2954 "kernel routing table id\n"
2955 "Distance for imported routes\n"
2956 "Default distance value\n"
2957 "route-map for filtering\n"
2958 "route-map name\n")
2959 {
2960 u_int32_t table_id = 0;
2961
2962 table_id = strtoul(argv[2]->arg, NULL, 10);
2963 int distance = ZEBRA_TABLE_DISTANCE_DEFAULT;
2964 char *rmap =
2965 strmatch(argv[argc - 2]->text, "route-map")
2966 ? XSTRDUP(MTYPE_ROUTE_MAP_NAME, argv[argc - 1]->arg)
2967 : NULL;
2968 int ret;
2969
2970 if (argc == 7 || (argc == 5 && !rmap))
2971 distance = strtoul(argv[4]->arg, NULL, 10);
2972
2973 if (!is_zebra_valid_kernel_table(table_id)) {
2974 vty_out(vty,
2975 "Invalid routing table ID, %d. Must be in range 1-252\n",
2976 table_id);
2977 if (rmap)
2978 XFREE(MTYPE_ROUTE_MAP_NAME, rmap);
2979 return CMD_WARNING;
2980 }
2981
2982 if (is_zebra_main_routing_table(table_id)) {
2983 vty_out(vty,
2984 "Invalid routing table ID, %d. Must be non-default table\n",
2985 table_id);
2986 if (rmap)
2987 XFREE(MTYPE_ROUTE_MAP_NAME, rmap);
2988 return CMD_WARNING;
2989 }
2990
2991 ret = zebra_import_table(AFI_IP, table_id, distance, rmap, 1);
2992 if (rmap)
2993 XFREE(MTYPE_ROUTE_MAP_NAME, rmap);
2994
2995 return ret;
2996 }
2997
2998 DEFUN_HIDDEN (zebra_packet_process,
2999 zebra_packet_process_cmd,
3000 "zebra zapi-packets (1-10000)",
3001 ZEBRA_STR
3002 "Zapi Protocol\n"
3003 "Number of packets to process before relinquishing thread\n")
3004 {
3005 uint32_t packets = strtoul(argv[2]->arg, NULL, 10);
3006
3007 zebrad.packets_to_process = packets;
3008
3009 return CMD_SUCCESS;
3010 }
3011
3012 DEFUN_HIDDEN (no_zebra_packet_process,
3013 no_zebra_packet_process_cmd,
3014 "no zebra zapi-packets [(1-10000)]",
3015 NO_STR
3016 ZEBRA_STR
3017 "Zapi Protocol\n"
3018 "Number of packets to process before relinquishing thread\n")
3019 {
3020 zebrad.packets_to_process = ZEBRA_ZAPI_PACKETS_TO_PROCESS;
3021
3022 return CMD_SUCCESS;
3023 }
3024
3025 DEFUN_HIDDEN (zebra_workqueue_timer,
3026 zebra_workqueue_timer_cmd,
3027 "zebra work-queue (0-10000)",
3028 ZEBRA_STR
3029 "Work Queue\n"
3030 "Time in milliseconds\n")
3031 {
3032 uint32_t timer = strtoul(argv[2]->arg, NULL, 10);
3033 zebrad.ribq->spec.hold = timer;
3034
3035 return CMD_SUCCESS;
3036 }
3037
3038 DEFUN_HIDDEN (no_zebra_workqueue_timer,
3039 no_zebra_workqueue_timer_cmd,
3040 "no zebra work-queue [(0-10000)]",
3041 NO_STR
3042 ZEBRA_STR
3043 "Work Queue\n"
3044 "Time in milliseconds\n")
3045 {
3046 zebrad.ribq->spec.hold = ZEBRA_RIB_PROCESS_HOLD_TIME;
3047
3048 return CMD_SUCCESS;
3049 }
3050
3051 DEFUN (no_ip_zebra_import_table,
3052 no_ip_zebra_import_table_cmd,
3053 "no ip import-table (1-252) [distance (1-255)] [route-map NAME]",
3054 NO_STR
3055 IP_STR
3056 "import routes from non-main kernel table\n"
3057 "kernel routing table id\n"
3058 "Distance for imported routes\n"
3059 "Default distance value\n"
3060 "route-map for filtering\n"
3061 "route-map name\n")
3062 {
3063 u_int32_t table_id = 0;
3064 table_id = strtoul(argv[3]->arg, NULL, 10);
3065
3066 if (!is_zebra_valid_kernel_table(table_id)) {
3067 vty_out(vty,
3068 "Invalid routing table ID. Must be in range 1-252\n");
3069 return CMD_WARNING;
3070 }
3071
3072 if (is_zebra_main_routing_table(table_id)) {
3073 vty_out(vty,
3074 "Invalid routing table ID, %d. Must be non-default table\n",
3075 table_id);
3076 return CMD_WARNING;
3077 }
3078
3079 if (!is_zebra_import_table_enabled(AFI_IP, table_id))
3080 return CMD_SUCCESS;
3081
3082 return (zebra_import_table(AFI_IP, table_id, 0, NULL, 0));
3083 }
3084
3085 static int config_write_protocol(struct vty *vty)
3086 {
3087 if (allow_delete)
3088 vty_out(vty, "allow-external-route-update\n");
3089
3090 if (zebra_rnh_ip_default_route)
3091 vty_out(vty, "ip nht resolve-via-default\n");
3092
3093 if (zebra_rnh_ipv6_default_route)
3094 vty_out(vty, "ipv6 nht resolve-via-default\n");
3095
3096 if (zebrad.ribq->spec.hold != ZEBRA_RIB_PROCESS_HOLD_TIME)
3097 vty_out(vty, "zebra work-queue %u\n", zebrad.ribq->spec.hold);
3098
3099 if (zebrad.packets_to_process != ZEBRA_ZAPI_PACKETS_TO_PROCESS)
3100 vty_out(vty,
3101 "zebra zapi-packets %u\n", zebrad.packets_to_process);
3102
3103 enum multicast_mode ipv4_multicast_mode = multicast_mode_ipv4_get();
3104
3105 if (ipv4_multicast_mode != MCAST_NO_CONFIG)
3106 vty_out(vty, "ip multicast rpf-lookup-mode %s\n",
3107 ipv4_multicast_mode == MCAST_URIB_ONLY
3108 ? "urib-only"
3109 : ipv4_multicast_mode == MCAST_MRIB_ONLY
3110 ? "mrib-only"
3111 : ipv4_multicast_mode
3112 == MCAST_MIX_MRIB_FIRST
3113 ? "mrib-then-urib"
3114 : ipv4_multicast_mode
3115 == MCAST_MIX_DISTANCE
3116 ? "lower-distance"
3117 : "longer-prefix");
3118
3119 zebra_routemap_config_write_protocol(vty);
3120
3121 return 1;
3122 }
3123
3124 #ifdef HAVE_NETLINK
3125 /* Display default rtm_table for all clients. */
3126 DEFUN (show_table,
3127 show_table_cmd,
3128 "show table",
3129 SHOW_STR
3130 "default routing table to use for all clients\n")
3131 {
3132 vty_out(vty, "table %d\n", zebrad.rtm_table_default);
3133 return CMD_SUCCESS;
3134 }
3135
3136 DEFUN (config_table,
3137 config_table_cmd,
3138 "table TABLENO",
3139 "Configure target kernel routing table\n"
3140 "TABLE integer\n")
3141 {
3142 zebrad.rtm_table_default = strtol(argv[1]->arg, (char **)0, 10);
3143 return CMD_SUCCESS;
3144 }
3145
3146 DEFUN (no_config_table,
3147 no_config_table_cmd,
3148 "no table [TABLENO]",
3149 NO_STR
3150 "Configure target kernel routing table\n"
3151 "TABLE integer\n")
3152 {
3153 zebrad.rtm_table_default = 0;
3154 return CMD_SUCCESS;
3155 }
3156 #endif
3157
3158 DEFUN (show_zebra,
3159 show_zebra_cmd,
3160 "show zebra",
3161 SHOW_STR
3162 ZEBRA_STR)
3163 {
3164 struct vrf *vrf;
3165
3166 vty_out(vty,
3167 " Route Route Neighbor LSP LSP\n");
3168 vty_out(vty,
3169 "VRF Installs Removals Updates Installs Removals\n");
3170
3171 RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) {
3172 struct zebra_vrf *zvrf = vrf->info;
3173
3174 vty_out(vty, "%-25s %10" PRIu64 " %10" PRIu64 " %10" PRIu64
3175 " %10" PRIu64 " %10" PRIu64 "\n",
3176 vrf->name, zvrf->installs, zvrf->removals,
3177 zvrf->neigh_updates, zvrf->lsp_installs,
3178 zvrf->lsp_removals);
3179 }
3180
3181 return CMD_SUCCESS;
3182 }
3183
3184 DEFUN (ip_forwarding,
3185 ip_forwarding_cmd,
3186 "ip forwarding",
3187 IP_STR
3188 "Turn on IP forwarding\n")
3189 {
3190 int ret;
3191
3192 ret = ipforward();
3193 if (ret == 0)
3194 ret = ipforward_on();
3195
3196 if (ret == 0) {
3197 vty_out(vty, "Can't turn on IP forwarding\n");
3198 return CMD_WARNING_CONFIG_FAILED;
3199 }
3200
3201 return CMD_SUCCESS;
3202 }
3203
3204 DEFUN (no_ip_forwarding,
3205 no_ip_forwarding_cmd,
3206 "no ip forwarding",
3207 NO_STR
3208 IP_STR
3209 "Turn off IP forwarding\n")
3210 {
3211 int ret;
3212
3213 ret = ipforward();
3214 if (ret != 0)
3215 ret = ipforward_off();
3216
3217 if (ret != 0) {
3218 vty_out(vty, "Can't turn off IP forwarding\n");
3219 return CMD_WARNING_CONFIG_FAILED;
3220 }
3221
3222 return CMD_SUCCESS;
3223 }
3224
3225 /* Only display ip forwarding is enabled or not. */
3226 DEFUN (show_ip_forwarding,
3227 show_ip_forwarding_cmd,
3228 "show ip forwarding",
3229 SHOW_STR
3230 IP_STR
3231 "IP forwarding status\n")
3232 {
3233 int ret;
3234
3235 ret = ipforward();
3236
3237 if (ret == 0)
3238 vty_out(vty, "IP forwarding is off\n");
3239 else
3240 vty_out(vty, "IP forwarding is on\n");
3241 return CMD_SUCCESS;
3242 }
3243
3244 /* Only display ipv6 forwarding is enabled or not. */
3245 DEFUN (show_ipv6_forwarding,
3246 show_ipv6_forwarding_cmd,
3247 "show ipv6 forwarding",
3248 SHOW_STR
3249 "IPv6 information\n"
3250 "Forwarding status\n")
3251 {
3252 int ret;
3253
3254 ret = ipforward_ipv6();
3255
3256 switch (ret) {
3257 case -1:
3258 vty_out(vty, "ipv6 forwarding is unknown\n");
3259 break;
3260 case 0:
3261 vty_out(vty, "ipv6 forwarding is %s\n", "off");
3262 break;
3263 case 1:
3264 vty_out(vty, "ipv6 forwarding is %s\n", "on");
3265 break;
3266 default:
3267 vty_out(vty, "ipv6 forwarding is %s\n", "off");
3268 break;
3269 }
3270 return CMD_SUCCESS;
3271 }
3272
3273 DEFUN (ipv6_forwarding,
3274 ipv6_forwarding_cmd,
3275 "ipv6 forwarding",
3276 IPV6_STR
3277 "Turn on IPv6 forwarding\n")
3278 {
3279 int ret;
3280
3281 ret = ipforward_ipv6();
3282 if (ret == 0)
3283 ret = ipforward_ipv6_on();
3284
3285 if (ret == 0) {
3286 vty_out(vty, "Can't turn on IPv6 forwarding\n");
3287 return CMD_WARNING_CONFIG_FAILED;
3288 }
3289
3290 return CMD_SUCCESS;
3291 }
3292
3293 DEFUN (no_ipv6_forwarding,
3294 no_ipv6_forwarding_cmd,
3295 "no ipv6 forwarding",
3296 NO_STR
3297 IPV6_STR
3298 "Turn off IPv6 forwarding\n")
3299 {
3300 int ret;
3301
3302 ret = ipforward_ipv6();
3303 if (ret != 0)
3304 ret = ipforward_ipv6_off();
3305
3306 if (ret != 0) {
3307 vty_out(vty, "Can't turn off IPv6 forwarding\n");
3308 return CMD_WARNING_CONFIG_FAILED;
3309 }
3310
3311 return CMD_SUCCESS;
3312 }
3313
3314 /* Table configuration write function. */
3315 static int config_write_table(struct vty *vty)
3316 {
3317 if (zebrad.rtm_table_default)
3318 vty_out(vty, "table %d\n", zebrad.rtm_table_default);
3319 return 0;
3320 }
3321
3322 /* IPForwarding configuration write function. */
3323 static int config_write_forwarding(struct vty *vty)
3324 {
3325 /* FIXME: Find better place for that. */
3326 router_id_write(vty);
3327
3328 if (!ipforward())
3329 vty_out(vty, "no ip forwarding\n");
3330 if (!ipforward_ipv6())
3331 vty_out(vty, "no ipv6 forwarding\n");
3332 vty_out(vty, "!\n");
3333 return 0;
3334 }
3335
3336 /* IP node for static routes. */
3337 static struct cmd_node ip_node = {IP_NODE, "", 1};
3338 static struct cmd_node protocol_node = {PROTOCOL_NODE, "", 1};
3339 /* table node for routing tables. */
3340 static struct cmd_node table_node = {TABLE_NODE,
3341 "", /* This node has no interface. */
3342 1};
3343 static struct cmd_node forwarding_node = {FORWARDING_NODE,
3344 "", /* This node has no interface. */
3345 1};
3346
3347 /* Route VTY. */
3348 void zebra_vty_init(void)
3349 {
3350 /* Install configuration write function. */
3351 install_node(&table_node, config_write_table);
3352 install_node(&forwarding_node, config_write_forwarding);
3353
3354 install_element(VIEW_NODE, &show_ip_forwarding_cmd);
3355 install_element(CONFIG_NODE, &ip_forwarding_cmd);
3356 install_element(CONFIG_NODE, &no_ip_forwarding_cmd);
3357 install_element(ENABLE_NODE, &show_zebra_cmd);
3358
3359 #ifdef HAVE_NETLINK
3360 install_element(VIEW_NODE, &show_table_cmd);
3361 install_element(CONFIG_NODE, &config_table_cmd);
3362 install_element(CONFIG_NODE, &no_config_table_cmd);
3363 #endif /* HAVE_NETLINK */
3364
3365 install_element(VIEW_NODE, &show_ipv6_forwarding_cmd);
3366 install_element(CONFIG_NODE, &ipv6_forwarding_cmd);
3367 install_element(CONFIG_NODE, &no_ipv6_forwarding_cmd);
3368
3369 /* Route-map */
3370 zebra_route_map_init();
3371
3372 install_node(&ip_node, zebra_ip_config);
3373 install_node(&protocol_node, config_write_protocol);
3374
3375 install_element(CONFIG_NODE, &allow_external_route_update_cmd);
3376 install_element(CONFIG_NODE, &no_allow_external_route_update_cmd);
3377 install_element(CONFIG_NODE, &ip_mroute_dist_cmd);
3378 install_element(CONFIG_NODE, &ip_multicast_mode_cmd);
3379 install_element(CONFIG_NODE, &no_ip_multicast_mode_cmd);
3380 install_element(CONFIG_NODE, &ip_route_blackhole_cmd);
3381 install_element(VRF_NODE, &ip_route_blackhole_vrf_cmd);
3382 install_element(CONFIG_NODE, &ip_route_address_interface_cmd);
3383 install_element(VRF_NODE, &ip_route_address_interface_vrf_cmd);
3384 install_element(CONFIG_NODE, &ip_route_cmd);
3385 install_element(VRF_NODE, &ip_route_vrf_cmd);
3386 install_element(CONFIG_NODE, &ip_zebra_import_table_distance_cmd);
3387 install_element(CONFIG_NODE, &no_ip_zebra_import_table_cmd);
3388 install_element(CONFIG_NODE, &zebra_workqueue_timer_cmd);
3389 install_element(CONFIG_NODE, &no_zebra_workqueue_timer_cmd);
3390 install_element(CONFIG_NODE, &zebra_packet_process_cmd);
3391 install_element(CONFIG_NODE, &no_zebra_packet_process_cmd);
3392
3393 install_element(VIEW_NODE, &show_vrf_cmd);
3394 install_element(VIEW_NODE, &show_vrf_vni_cmd);
3395 install_element(VIEW_NODE, &show_route_cmd);
3396 install_element(VIEW_NODE, &show_route_table_cmd);
3397 install_element(VIEW_NODE, &show_route_detail_cmd);
3398 install_element(VIEW_NODE, &show_route_summary_cmd);
3399 install_element(VIEW_NODE, &show_ip_nht_cmd);
3400 install_element(VIEW_NODE, &show_ip_nht_vrf_all_cmd);
3401 install_element(VIEW_NODE, &show_ipv6_nht_cmd);
3402 install_element(VIEW_NODE, &show_ipv6_nht_vrf_all_cmd);
3403
3404 install_element(VIEW_NODE, &show_ip_rpf_cmd);
3405 install_element(VIEW_NODE, &show_ip_rpf_addr_cmd);
3406
3407 install_element(CONFIG_NODE, &ipv6_route_blackhole_cmd);
3408 install_element(VRF_NODE, &ipv6_route_blackhole_vrf_cmd);
3409 install_element(CONFIG_NODE, &ipv6_route_address_interface_cmd);
3410 install_element(VRF_NODE, &ipv6_route_address_interface_vrf_cmd);
3411 install_element(CONFIG_NODE, &ipv6_route_cmd);
3412 install_element(VRF_NODE, &ipv6_route_vrf_cmd);
3413 install_element(CONFIG_NODE, &ip_nht_default_route_cmd);
3414 install_element(CONFIG_NODE, &no_ip_nht_default_route_cmd);
3415 install_element(CONFIG_NODE, &ipv6_nht_default_route_cmd);
3416 install_element(CONFIG_NODE, &no_ipv6_nht_default_route_cmd);
3417 install_element(VIEW_NODE, &show_ipv6_mroute_cmd);
3418
3419 /* Commands for VRF */
3420 install_element(VIEW_NODE, &show_ipv6_mroute_vrf_all_cmd);
3421
3422 install_element(VIEW_NODE, &show_evpn_global_cmd);
3423 install_element(VIEW_NODE, &show_evpn_vni_cmd);
3424 install_element(VIEW_NODE, &show_evpn_vni_vni_cmd);
3425 install_element(VIEW_NODE, &show_evpn_rmac_vni_mac_cmd);
3426 install_element(VIEW_NODE, &show_evpn_rmac_vni_cmd);
3427 install_element(VIEW_NODE, &show_evpn_rmac_vni_all_cmd);
3428 install_element(VIEW_NODE, &show_evpn_nh_vni_ip_cmd);
3429 install_element(VIEW_NODE, &show_evpn_nh_vni_cmd);
3430 install_element(VIEW_NODE, &show_evpn_nh_vni_all_cmd);
3431 install_element(VIEW_NODE, &show_evpn_mac_vni_cmd);
3432 install_element(VIEW_NODE, &show_evpn_mac_vni_all_cmd);
3433 install_element(VIEW_NODE, &show_evpn_mac_vni_all_vtep_cmd);
3434 install_element(VIEW_NODE, &show_evpn_mac_vni_mac_cmd);
3435 install_element(VIEW_NODE, &show_evpn_mac_vni_vtep_cmd);
3436 install_element(VIEW_NODE, &show_evpn_neigh_vni_cmd);
3437 install_element(VIEW_NODE, &show_evpn_neigh_vni_all_cmd);
3438 install_element(VIEW_NODE, &show_evpn_neigh_vni_neigh_cmd);
3439 install_element(VIEW_NODE, &show_evpn_neigh_vni_vtep_cmd);
3440
3441 install_element(CONFIG_NODE, &default_vrf_vni_mapping_cmd);
3442 install_element(CONFIG_NODE, &no_default_vrf_vni_mapping_cmd);
3443 install_element(VRF_NODE, &vrf_vni_mapping_cmd);
3444 install_element(VRF_NODE, &no_vrf_vni_mapping_cmd);
3445
3446 }