]> git.proxmox.com Git - mirror_frr.git/blob - zebra/zebra_vty.c
ccc7cb30c312d6f213251c047994ebcc28ca7171
[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 vty_out(vty, "inactive");
2379 else
2380 vty_out(vty, "id %u table %u", zvrf_id(zvrf),
2381 zvrf->table_id);
2382 if (vrf_is_user_cfged(vrf))
2383 vty_out(vty, " (configured)");
2384 vty_out(vty, "\n");
2385 }
2386
2387 return CMD_SUCCESS;
2388 }
2389
2390 DEFUN (default_vrf_vni_mapping,
2391 default_vrf_vni_mapping_cmd,
2392 "vni " CMD_VNI_RANGE "[prefix-routes-only]",
2393 "VNI corresponding to the DEFAULT VRF\n"
2394 "VNI-ID\n"
2395 "Prefix routes only \n")
2396 {
2397 int ret = 0;
2398 char err[ERR_STR_SZ];
2399 struct zebra_vrf *zvrf = NULL;
2400 vni_t vni = strtoul(argv[1]->arg, NULL, 10);
2401 int filter = 0;
2402
2403 zvrf = vrf_info_lookup(VRF_DEFAULT);
2404 if (!zvrf)
2405 return CMD_WARNING;
2406
2407 if (argc == 3)
2408 filter = 1;
2409
2410 ret = zebra_vxlan_process_vrf_vni_cmd(zvrf, vni, err, ERR_STR_SZ,
2411 filter, 1);
2412 if (ret != 0) {
2413 vty_out(vty, "%s\n", err);
2414 return CMD_WARNING;
2415 }
2416
2417 return CMD_SUCCESS;
2418 }
2419
2420 DEFUN (no_default_vrf_vni_mapping,
2421 no_default_vrf_vni_mapping_cmd,
2422 "no vni " CMD_VNI_RANGE,
2423 NO_STR
2424 "VNI corresponding to DEFAULT VRF\n"
2425 "VNI-ID")
2426 {
2427 int ret = 0;
2428 char err[ERR_STR_SZ];
2429 vni_t vni = strtoul(argv[2]->arg, NULL, 10);
2430 struct zebra_vrf *zvrf = NULL;
2431
2432 zvrf = vrf_info_lookup(VRF_DEFAULT);
2433 if (!zvrf)
2434 return CMD_WARNING;
2435
2436 ret = zebra_vxlan_process_vrf_vni_cmd(zvrf, vni, err, ERR_STR_SZ, 0, 0);
2437 if (ret != 0) {
2438 vty_out(vty, "%s\n", err);
2439 return CMD_WARNING;
2440 }
2441
2442 return CMD_SUCCESS;
2443 }
2444
2445 DEFUN (vrf_vni_mapping,
2446 vrf_vni_mapping_cmd,
2447 "vni " CMD_VNI_RANGE "[prefix-routes-only]",
2448 "VNI corresponding to tenant VRF\n"
2449 "VNI-ID\n"
2450 "prefix-routes-only\n")
2451 {
2452 int ret = 0;
2453 int filter = 0;
2454
2455 ZEBRA_DECLVAR_CONTEXT(vrf, zvrf);
2456 vni_t vni = strtoul(argv[1]->arg, NULL, 10);
2457 char err[ERR_STR_SZ];
2458
2459 assert(vrf);
2460 assert(zvrf);
2461
2462 if (argc == 3)
2463 filter = 1;
2464
2465 /* Mark as having FRR configuration */
2466 vrf_set_user_cfged(vrf);
2467 ret = zebra_vxlan_process_vrf_vni_cmd(zvrf, vni, err, ERR_STR_SZ,
2468 filter, 1);
2469 if (ret != 0) {
2470 vty_out(vty, "%s\n", err);
2471 return CMD_WARNING;
2472 }
2473
2474 return CMD_SUCCESS;
2475 }
2476
2477 DEFUN (no_vrf_vni_mapping,
2478 no_vrf_vni_mapping_cmd,
2479 "no vni " CMD_VNI_RANGE,
2480 NO_STR
2481 "VNI corresponding to tenant VRF\n"
2482 "VNI-ID")
2483 {
2484 int ret = 0;
2485 char err[ERR_STR_SZ];
2486 vni_t vni = strtoul(argv[2]->arg, NULL, 10);
2487
2488 ZEBRA_DECLVAR_CONTEXT(vrf, zvrf);
2489
2490 assert(vrf);
2491 assert(zvrf);
2492
2493 ret = zebra_vxlan_process_vrf_vni_cmd(zvrf, vni, err, ERR_STR_SZ, 0, 0);
2494 if (ret != 0) {
2495 vty_out(vty, "%s\n", err);
2496 return CMD_WARNING;
2497 }
2498
2499 /* If no other FRR config for this VRF, mark accordingly. */
2500 if (!zebra_vrf_has_config(zvrf))
2501 vrf_reset_user_cfged(vrf);
2502
2503 return CMD_SUCCESS;
2504 }
2505
2506 /* show vrf */
2507 DEFUN (show_vrf_vni,
2508 show_vrf_vni_cmd,
2509 "show vrf vni [json]",
2510 SHOW_STR
2511 "VRF\n"
2512 "VNI\n"
2513 JSON_STR)
2514 {
2515 struct vrf *vrf;
2516 struct zebra_vrf *zvrf;
2517 json_object *json = NULL;
2518 json_object *json_vrfs = NULL;
2519 u_char uj = use_json(argc, argv);
2520
2521 if (uj) {
2522 json = json_object_new_object();
2523 json_vrfs = json_object_new_array();
2524 }
2525
2526 if (!uj)
2527 vty_out(vty, "%-37s %-10s %-20s %-20s %-5s %-18s\n",
2528 "VRF", "VNI", "VxLAN IF", "L3-SVI", "State", "Rmac");
2529
2530 RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) {
2531 zvrf = vrf->info;
2532 if (!zvrf)
2533 continue;
2534
2535 zebra_vxlan_print_vrf_vni(vty, zvrf, json_vrfs);
2536 }
2537
2538 if (uj) {
2539 json_object_object_add(json, "vrfs", json_vrfs);
2540 vty_out(vty, "%s\n", json_object_to_json_string_ext(
2541 json, JSON_C_TO_STRING_PRETTY));
2542 json_object_free(json);
2543 }
2544
2545 return CMD_SUCCESS;
2546 }
2547
2548 DEFUN (show_evpn_global,
2549 show_evpn_global_cmd,
2550 "show evpn [json]",
2551 SHOW_STR
2552 "EVPN\n"
2553 JSON_STR)
2554 {
2555 u_char uj = use_json(argc, argv);
2556
2557 zebra_vxlan_print_evpn(vty, uj);
2558 return CMD_SUCCESS;
2559 }
2560
2561 DEFUN (show_evpn_vni,
2562 show_evpn_vni_cmd,
2563 "show evpn vni [json]",
2564 SHOW_STR
2565 "EVPN\n"
2566 "VxLAN information\n"
2567 JSON_STR)
2568 {
2569 struct zebra_vrf *zvrf;
2570 u_char uj = use_json(argc, argv);
2571
2572 zvrf = vrf_info_lookup(VRF_DEFAULT);
2573 zebra_vxlan_print_vnis(vty, zvrf, uj);
2574 return CMD_SUCCESS;
2575 }
2576
2577 DEFUN (show_evpn_vni_vni,
2578 show_evpn_vni_vni_cmd,
2579 "show evpn vni " CMD_VNI_RANGE "[json]",
2580 SHOW_STR
2581 "EVPN\n"
2582 "VxLAN Network Identifier\n"
2583 "VNI number\n"
2584 JSON_STR)
2585 {
2586 struct zebra_vrf *zvrf;
2587 vni_t vni;
2588 u_char uj = use_json(argc, argv);
2589
2590 vni = strtoul(argv[3]->arg, NULL, 10);
2591 zvrf = vrf_info_lookup(VRF_DEFAULT);
2592 zebra_vxlan_print_vni(vty, zvrf, vni, uj);
2593 return CMD_SUCCESS;
2594 }
2595
2596 DEFUN (show_evpn_rmac_vni_mac,
2597 show_evpn_rmac_vni_mac_cmd,
2598 "show evpn rmac vni " CMD_VNI_RANGE " mac WORD [json]",
2599 SHOW_STR
2600 "EVPN\n"
2601 "RMAC\n"
2602 "L3 VNI\n"
2603 "VNI number\n"
2604 "MAC\n"
2605 "mac-address (e.g. 0a:0a:0a:0a:0a:0a)\n"
2606 JSON_STR)
2607 {
2608 vni_t l3vni = 0;
2609 struct ethaddr mac;
2610 u_char uj = use_json(argc, argv);
2611
2612 l3vni = strtoul(argv[4]->arg, NULL, 10);
2613 if (!prefix_str2mac(argv[6]->arg, &mac)) {
2614 vty_out(vty, "%% Malformed MAC address\n");
2615 return CMD_WARNING;
2616 }
2617 zebra_vxlan_print_specific_rmac_l3vni(vty, l3vni, &mac, uj);
2618 return CMD_SUCCESS;
2619 }
2620
2621 DEFUN (show_evpn_rmac_vni,
2622 show_evpn_rmac_vni_cmd,
2623 "show evpn rmac vni " CMD_VNI_RANGE "[json]",
2624 SHOW_STR
2625 "EVPN\n"
2626 "RMAC\n"
2627 "L3 VNI\n"
2628 "VNI number\n"
2629 JSON_STR)
2630 {
2631 vni_t l3vni = 0;
2632 u_char uj = use_json(argc, argv);
2633
2634 l3vni = strtoul(argv[4]->arg, NULL, 10);
2635 zebra_vxlan_print_rmacs_l3vni(vty, l3vni, uj);
2636
2637 return CMD_SUCCESS;
2638 }
2639
2640 DEFUN (show_evpn_rmac_vni_all,
2641 show_evpn_rmac_vni_all_cmd,
2642 "show evpn rmac vni all [json]",
2643 SHOW_STR
2644 "EVPN\n"
2645 "RMAC addresses\n"
2646 "L3 VNI\n"
2647 "All VNIs\n"
2648 JSON_STR)
2649 {
2650 u_char uj = use_json(argc, argv);
2651
2652 zebra_vxlan_print_rmacs_all_l3vni(vty, uj);
2653
2654 return CMD_SUCCESS;
2655 }
2656
2657 DEFUN (show_evpn_nh_vni_ip,
2658 show_evpn_nh_vni_ip_cmd,
2659 "show evpn next-hops vni " CMD_VNI_RANGE " ip WORD [json]",
2660 SHOW_STR
2661 "EVPN\n"
2662 "Remote Vteps\n"
2663 "L3 VNI\n"
2664 "VNI number\n"
2665 "Ip address\n"
2666 "Host address (ipv4 or ipv6)\n"
2667 JSON_STR)
2668 {
2669 vni_t l3vni;
2670 struct ipaddr ip;
2671 u_char uj = use_json(argc, argv);
2672
2673 l3vni = strtoul(argv[4]->arg, NULL, 10);
2674 if (str2ipaddr(argv[6]->arg, &ip) != 0) {
2675 if (!uj)
2676 vty_out(vty, "%% Malformed Neighbor address\n");
2677 return CMD_WARNING;
2678 }
2679 zebra_vxlan_print_specific_nh_l3vni(vty, l3vni, &ip, uj);
2680
2681 return CMD_SUCCESS;
2682 }
2683
2684 DEFUN (show_evpn_nh_vni,
2685 show_evpn_nh_vni_cmd,
2686 "show evpn next-hops vni " CMD_VNI_RANGE "[json]",
2687 SHOW_STR
2688 "EVPN\n"
2689 "Remote Vteps\n"
2690 "L3 VNI\n"
2691 "VNI number\n"
2692 JSON_STR)
2693 {
2694 vni_t l3vni;
2695 u_char uj = use_json(argc, argv);
2696
2697 l3vni = strtoul(argv[4]->arg, NULL, 10);
2698 zebra_vxlan_print_nh_l3vni(vty, l3vni, uj);
2699
2700 return CMD_SUCCESS;
2701 }
2702
2703 DEFUN (show_evpn_nh_vni_all,
2704 show_evpn_nh_vni_all_cmd,
2705 "show evpn next-hops vni all [json]",
2706 SHOW_STR
2707 "EVPN\n"
2708 "Remote VTEPs\n"
2709 "L3 VNI\n"
2710 "All VNIs\n"
2711 JSON_STR)
2712 {
2713 u_char uj = use_json(argc, argv);
2714
2715 zebra_vxlan_print_nh_all_l3vni(vty, uj);
2716
2717 return CMD_SUCCESS;
2718 }
2719
2720 DEFUN (show_evpn_mac_vni,
2721 show_evpn_mac_vni_cmd,
2722 "show evpn mac vni " CMD_VNI_RANGE "[json]",
2723 SHOW_STR
2724 "EVPN\n"
2725 "MAC addresses\n"
2726 "VxLAN Network Identifier\n"
2727 "VNI number\n"
2728 JSON_STR)
2729 {
2730 struct zebra_vrf *zvrf;
2731 vni_t vni;
2732 u_char uj = use_json(argc, argv);
2733
2734 vni = strtoul(argv[4]->arg, NULL, 10);
2735 zvrf = vrf_info_lookup(VRF_DEFAULT);
2736 zebra_vxlan_print_macs_vni(vty, zvrf, vni, uj);
2737 return CMD_SUCCESS;
2738 }
2739
2740 DEFUN (show_evpn_mac_vni_all,
2741 show_evpn_mac_vni_all_cmd,
2742 "show evpn mac vni all [json]",
2743 SHOW_STR
2744 "EVPN\n"
2745 "MAC addresses\n"
2746 "VxLAN Network Identifier\n"
2747 "All VNIs\n"
2748 JSON_STR)
2749 {
2750 struct zebra_vrf *zvrf;
2751 u_char uj = use_json(argc, argv);
2752
2753 zvrf = vrf_info_lookup(VRF_DEFAULT);
2754 zebra_vxlan_print_macs_all_vni(vty, zvrf, uj);
2755 return CMD_SUCCESS;
2756 }
2757
2758 DEFUN (show_evpn_mac_vni_all_vtep,
2759 show_evpn_mac_vni_all_vtep_cmd,
2760 "show evpn mac vni all vtep A.B.C.D [json]",
2761 SHOW_STR
2762 "EVPN\n"
2763 "MAC addresses\n"
2764 "VxLAN Network Identifier\n"
2765 "All VNIs\n"
2766 "Remote VTEP\n"
2767 "Remote VTEP IP address\n"
2768 JSON_STR)
2769 {
2770 struct zebra_vrf *zvrf;
2771 struct in_addr vtep_ip;
2772 u_char uj = use_json(argc, argv);
2773
2774 if (!inet_aton(argv[6]->arg, &vtep_ip)) {
2775 if (!uj)
2776 vty_out(vty, "%% Malformed VTEP IP address\n");
2777 return CMD_WARNING;
2778 }
2779 zvrf = vrf_info_lookup(VRF_DEFAULT);
2780 zebra_vxlan_print_macs_all_vni_vtep(vty, zvrf, vtep_ip, uj);
2781
2782 return CMD_SUCCESS;
2783 }
2784
2785
2786 DEFUN (show_evpn_mac_vni_mac,
2787 show_evpn_mac_vni_mac_cmd,
2788 "show evpn mac vni " CMD_VNI_RANGE " mac WORD",
2789 SHOW_STR
2790 "EVPN\n"
2791 "MAC addresses\n"
2792 "VxLAN Network Identifier\n"
2793 "VNI number\n"
2794 "MAC\n"
2795 "MAC address (e.g., 00:e0:ec:20:12:62)\n")
2796 {
2797 struct zebra_vrf *zvrf;
2798 vni_t vni;
2799 struct ethaddr mac;
2800
2801 vni = strtoul(argv[4]->arg, NULL, 10);
2802 if (!prefix_str2mac(argv[6]->arg, &mac)) {
2803 vty_out(vty, "%% Malformed MAC address");
2804 return CMD_WARNING;
2805 }
2806 zvrf = vrf_info_lookup(VRF_DEFAULT);
2807 zebra_vxlan_print_specific_mac_vni(vty, zvrf, vni, &mac);
2808 return CMD_SUCCESS;
2809 }
2810
2811 DEFUN (show_evpn_mac_vni_vtep,
2812 show_evpn_mac_vni_vtep_cmd,
2813 "show evpn mac vni " CMD_VNI_RANGE " vtep A.B.C.D" "[json]",
2814 SHOW_STR
2815 "EVPN\n"
2816 "MAC addresses\n"
2817 "VxLAN Network Identifier\n"
2818 "VNI number\n"
2819 "Remote VTEP\n"
2820 "Remote VTEP IP address\n"
2821 JSON_STR)
2822 {
2823 struct zebra_vrf *zvrf;
2824 vni_t vni;
2825 struct in_addr vtep_ip;
2826 u_char uj = use_json(argc, argv);
2827
2828 vni = strtoul(argv[4]->arg, NULL, 10);
2829 if (!inet_aton(argv[6]->arg, &vtep_ip)) {
2830 if (!uj)
2831 vty_out(vty, "%% Malformed VTEP IP address\n");
2832 return CMD_WARNING;
2833 }
2834
2835 zvrf = vrf_info_lookup(VRF_DEFAULT);
2836 zebra_vxlan_print_macs_vni_vtep(vty, zvrf, vni, vtep_ip, uj);
2837 return CMD_SUCCESS;
2838 }
2839
2840 DEFUN (show_evpn_neigh_vni,
2841 show_evpn_neigh_vni_cmd,
2842 "show evpn arp-cache vni " CMD_VNI_RANGE "[json]",
2843 SHOW_STR
2844 "EVPN\n"
2845 "ARP and ND cache\n"
2846 "VxLAN Network Identifier\n"
2847 "VNI number\n"
2848 JSON_STR)
2849 {
2850 struct zebra_vrf *zvrf;
2851 vni_t vni;
2852 u_char uj = use_json(argc, argv);
2853
2854 vni = strtoul(argv[4]->arg, NULL, 10);
2855 zvrf = vrf_info_lookup(VRF_DEFAULT);
2856 zebra_vxlan_print_neigh_vni(vty, zvrf, vni, uj);
2857 return CMD_SUCCESS;
2858 }
2859
2860 DEFUN (show_evpn_neigh_vni_all,
2861 show_evpn_neigh_vni_all_cmd,
2862 "show evpn arp-cache vni all [json]",
2863 SHOW_STR
2864 "EVPN\n"
2865 "ARP and ND cache\n"
2866 "VxLAN Network Identifier\n"
2867 "All VNIs\n"
2868 JSON_STR)
2869 {
2870 struct zebra_vrf *zvrf;
2871 u_char uj = use_json(argc, argv);
2872
2873 zvrf = vrf_info_lookup(VRF_DEFAULT);
2874 zebra_vxlan_print_neigh_all_vni(vty, zvrf, uj);
2875 return CMD_SUCCESS;
2876 }
2877
2878 DEFUN (show_evpn_neigh_vni_neigh,
2879 show_evpn_neigh_vni_neigh_cmd,
2880 "show evpn arp-cache vni " CMD_VNI_RANGE " ip WORD [json]",
2881 SHOW_STR
2882 "EVPN\n"
2883 "ARP and ND cache\n"
2884 "VxLAN Network Identifier\n"
2885 "VNI number\n"
2886 "Neighbor\n"
2887 "Neighbor address (IPv4 or IPv6 address)\n"
2888 JSON_STR)
2889 {
2890 struct zebra_vrf *zvrf;
2891 vni_t vni;
2892 struct ipaddr ip;
2893 u_char uj = use_json(argc, argv);
2894
2895 vni = strtoul(argv[4]->arg, NULL, 10);
2896 if (str2ipaddr(argv[6]->arg, &ip) != 0) {
2897 if (!uj)
2898 vty_out(vty, "%% Malformed Neighbor address\n");
2899 return CMD_WARNING;
2900 }
2901 zvrf = vrf_info_lookup(VRF_DEFAULT);
2902 zebra_vxlan_print_specific_neigh_vni(vty, zvrf, vni, &ip, uj);
2903 return CMD_SUCCESS;
2904 }
2905
2906 DEFUN (show_evpn_neigh_vni_vtep,
2907 show_evpn_neigh_vni_vtep_cmd,
2908 "show evpn arp-cache vni " CMD_VNI_RANGE " vtep A.B.C.D [json]",
2909 SHOW_STR
2910 "EVPN\n"
2911 "ARP and ND cache\n"
2912 "VxLAN Network Identifier\n"
2913 "VNI number\n"
2914 "Remote VTEP\n"
2915 "Remote VTEP IP address\n"
2916 JSON_STR)
2917 {
2918 struct zebra_vrf *zvrf;
2919 vni_t vni;
2920 struct in_addr vtep_ip;
2921 u_char uj = use_json(argc, argv);
2922
2923 vni = strtoul(argv[4]->arg, NULL, 10);
2924 if (!inet_aton(argv[6]->arg, &vtep_ip)) {
2925 if (!uj)
2926 vty_out(vty, "%% Malformed VTEP IP address\n");
2927 return CMD_WARNING;
2928 }
2929
2930 zvrf = vrf_info_lookup(VRF_DEFAULT);
2931 zebra_vxlan_print_neigh_vni_vtep(vty, zvrf, vni, vtep_ip, uj);
2932 return CMD_SUCCESS;
2933 }
2934
2935 /* Static ip route configuration write function. */
2936 static int zebra_ip_config(struct vty *vty)
2937 {
2938 int write = 0;
2939
2940 write += zebra_import_table_config(vty);
2941
2942 return write;
2943 }
2944
2945 DEFUN (ip_zebra_import_table_distance,
2946 ip_zebra_import_table_distance_cmd,
2947 "ip import-table (1-252) [distance (1-255)] [route-map WORD]",
2948 IP_STR
2949 "import routes from non-main kernel table\n"
2950 "kernel routing table id\n"
2951 "Distance for imported routes\n"
2952 "Default distance value\n"
2953 "route-map for filtering\n"
2954 "route-map name\n")
2955 {
2956 u_int32_t table_id = 0;
2957
2958 table_id = strtoul(argv[2]->arg, NULL, 10);
2959 int distance = ZEBRA_TABLE_DISTANCE_DEFAULT;
2960 char *rmap =
2961 strmatch(argv[argc - 2]->text, "route-map")
2962 ? XSTRDUP(MTYPE_ROUTE_MAP_NAME, argv[argc - 1]->arg)
2963 : NULL;
2964 int ret;
2965
2966 if (argc == 7 || (argc == 5 && !rmap))
2967 distance = strtoul(argv[4]->arg, NULL, 10);
2968
2969 if (!is_zebra_valid_kernel_table(table_id)) {
2970 vty_out(vty,
2971 "Invalid routing table ID, %d. Must be in range 1-252\n",
2972 table_id);
2973 if (rmap)
2974 XFREE(MTYPE_ROUTE_MAP_NAME, rmap);
2975 return CMD_WARNING;
2976 }
2977
2978 if (is_zebra_main_routing_table(table_id)) {
2979 vty_out(vty,
2980 "Invalid routing table ID, %d. Must be non-default table\n",
2981 table_id);
2982 if (rmap)
2983 XFREE(MTYPE_ROUTE_MAP_NAME, rmap);
2984 return CMD_WARNING;
2985 }
2986
2987 ret = zebra_import_table(AFI_IP, table_id, distance, rmap, 1);
2988 if (rmap)
2989 XFREE(MTYPE_ROUTE_MAP_NAME, rmap);
2990
2991 return ret;
2992 }
2993
2994 DEFUN_HIDDEN (zebra_packet_process,
2995 zebra_packet_process_cmd,
2996 "zebra zapi-packets (1-10000)",
2997 ZEBRA_STR
2998 "Zapi Protocol\n"
2999 "Number of packets to process before relinquishing thread\n")
3000 {
3001 uint32_t packets = strtoul(argv[2]->arg, NULL, 10);
3002
3003 zebrad.packets_to_process = packets;
3004
3005 return CMD_SUCCESS;
3006 }
3007
3008 DEFUN_HIDDEN (no_zebra_packet_process,
3009 no_zebra_packet_process_cmd,
3010 "no zebra zapi-packets [(1-10000)]",
3011 NO_STR
3012 ZEBRA_STR
3013 "Zapi Protocol\n"
3014 "Number of packets to process before relinquishing thread\n")
3015 {
3016 zebrad.packets_to_process = ZEBRA_ZAPI_PACKETS_TO_PROCESS;
3017
3018 return CMD_SUCCESS;
3019 }
3020
3021 DEFUN_HIDDEN (zebra_workqueue_timer,
3022 zebra_workqueue_timer_cmd,
3023 "zebra work-queue (0-10000)",
3024 ZEBRA_STR
3025 "Work Queue\n"
3026 "Time in milliseconds\n")
3027 {
3028 uint32_t timer = strtoul(argv[2]->arg, NULL, 10);
3029 zebrad.ribq->spec.hold = timer;
3030
3031 return CMD_SUCCESS;
3032 }
3033
3034 DEFUN_HIDDEN (no_zebra_workqueue_timer,
3035 no_zebra_workqueue_timer_cmd,
3036 "no zebra work-queue [(0-10000)]",
3037 NO_STR
3038 ZEBRA_STR
3039 "Work Queue\n"
3040 "Time in milliseconds\n")
3041 {
3042 zebrad.ribq->spec.hold = ZEBRA_RIB_PROCESS_HOLD_TIME;
3043
3044 return CMD_SUCCESS;
3045 }
3046
3047 DEFUN (no_ip_zebra_import_table,
3048 no_ip_zebra_import_table_cmd,
3049 "no ip import-table (1-252) [distance (1-255)] [route-map NAME]",
3050 NO_STR
3051 IP_STR
3052 "import routes from non-main kernel table\n"
3053 "kernel routing table id\n"
3054 "Distance for imported routes\n"
3055 "Default distance value\n"
3056 "route-map for filtering\n"
3057 "route-map name\n")
3058 {
3059 u_int32_t table_id = 0;
3060 table_id = strtoul(argv[3]->arg, NULL, 10);
3061
3062 if (!is_zebra_valid_kernel_table(table_id)) {
3063 vty_out(vty,
3064 "Invalid routing table ID. Must be in range 1-252\n");
3065 return CMD_WARNING;
3066 }
3067
3068 if (is_zebra_main_routing_table(table_id)) {
3069 vty_out(vty,
3070 "Invalid routing table ID, %d. Must be non-default table\n",
3071 table_id);
3072 return CMD_WARNING;
3073 }
3074
3075 if (!is_zebra_import_table_enabled(AFI_IP, table_id))
3076 return CMD_SUCCESS;
3077
3078 return (zebra_import_table(AFI_IP, table_id, 0, NULL, 0));
3079 }
3080
3081 static int config_write_protocol(struct vty *vty)
3082 {
3083 if (allow_delete)
3084 vty_out(vty, "allow-external-route-update\n");
3085
3086 if (zebra_rnh_ip_default_route)
3087 vty_out(vty, "ip nht resolve-via-default\n");
3088
3089 if (zebra_rnh_ipv6_default_route)
3090 vty_out(vty, "ipv6 nht resolve-via-default\n");
3091
3092 if (zebrad.ribq->spec.hold != ZEBRA_RIB_PROCESS_HOLD_TIME)
3093 vty_out(vty, "zebra work-queue %u\n", zebrad.ribq->spec.hold);
3094
3095 if (zebrad.packets_to_process != ZEBRA_ZAPI_PACKETS_TO_PROCESS)
3096 vty_out(vty,
3097 "zebra zapi-packets %u\n", zebrad.packets_to_process);
3098
3099 enum multicast_mode ipv4_multicast_mode = multicast_mode_ipv4_get();
3100
3101 if (ipv4_multicast_mode != MCAST_NO_CONFIG)
3102 vty_out(vty, "ip multicast rpf-lookup-mode %s\n",
3103 ipv4_multicast_mode == MCAST_URIB_ONLY
3104 ? "urib-only"
3105 : ipv4_multicast_mode == MCAST_MRIB_ONLY
3106 ? "mrib-only"
3107 : ipv4_multicast_mode
3108 == MCAST_MIX_MRIB_FIRST
3109 ? "mrib-then-urib"
3110 : ipv4_multicast_mode
3111 == MCAST_MIX_DISTANCE
3112 ? "lower-distance"
3113 : "longer-prefix");
3114
3115 zebra_routemap_config_write_protocol(vty);
3116
3117 return 1;
3118 }
3119
3120 #ifdef HAVE_NETLINK
3121 /* Display default rtm_table for all clients. */
3122 DEFUN (show_table,
3123 show_table_cmd,
3124 "show table",
3125 SHOW_STR
3126 "default routing table to use for all clients\n")
3127 {
3128 vty_out(vty, "table %d\n", zebrad.rtm_table_default);
3129 return CMD_SUCCESS;
3130 }
3131
3132 DEFUN (config_table,
3133 config_table_cmd,
3134 "table TABLENO",
3135 "Configure target kernel routing table\n"
3136 "TABLE integer\n")
3137 {
3138 zebrad.rtm_table_default = strtol(argv[1]->arg, (char **)0, 10);
3139 return CMD_SUCCESS;
3140 }
3141
3142 DEFUN (no_config_table,
3143 no_config_table_cmd,
3144 "no table [TABLENO]",
3145 NO_STR
3146 "Configure target kernel routing table\n"
3147 "TABLE integer\n")
3148 {
3149 zebrad.rtm_table_default = 0;
3150 return CMD_SUCCESS;
3151 }
3152 #endif
3153
3154 DEFUN (show_zebra,
3155 show_zebra_cmd,
3156 "show zebra",
3157 SHOW_STR
3158 ZEBRA_STR)
3159 {
3160 struct vrf *vrf;
3161
3162 vty_out(vty,
3163 " Route Route Neighbor LSP LSP\n");
3164 vty_out(vty,
3165 "VRF Installs Removals Updates Installs Removals\n");
3166
3167 RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) {
3168 struct zebra_vrf *zvrf = vrf->info;
3169
3170 vty_out(vty, "%-25s %10" PRIu64 " %10" PRIu64 " %10" PRIu64
3171 " %10" PRIu64 " %10" PRIu64 "\n",
3172 vrf->name, zvrf->installs, zvrf->removals,
3173 zvrf->neigh_updates, zvrf->lsp_installs,
3174 zvrf->lsp_removals);
3175 }
3176
3177 return CMD_SUCCESS;
3178 }
3179
3180 DEFUN (ip_forwarding,
3181 ip_forwarding_cmd,
3182 "ip forwarding",
3183 IP_STR
3184 "Turn on IP forwarding\n")
3185 {
3186 int ret;
3187
3188 ret = ipforward();
3189 if (ret == 0)
3190 ret = ipforward_on();
3191
3192 if (ret == 0) {
3193 vty_out(vty, "Can't turn on IP forwarding\n");
3194 return CMD_WARNING_CONFIG_FAILED;
3195 }
3196
3197 return CMD_SUCCESS;
3198 }
3199
3200 DEFUN (no_ip_forwarding,
3201 no_ip_forwarding_cmd,
3202 "no ip forwarding",
3203 NO_STR
3204 IP_STR
3205 "Turn off IP forwarding\n")
3206 {
3207 int ret;
3208
3209 ret = ipforward();
3210 if (ret != 0)
3211 ret = ipforward_off();
3212
3213 if (ret != 0) {
3214 vty_out(vty, "Can't turn off IP forwarding\n");
3215 return CMD_WARNING_CONFIG_FAILED;
3216 }
3217
3218 return CMD_SUCCESS;
3219 }
3220
3221 /* Only display ip forwarding is enabled or not. */
3222 DEFUN (show_ip_forwarding,
3223 show_ip_forwarding_cmd,
3224 "show ip forwarding",
3225 SHOW_STR
3226 IP_STR
3227 "IP forwarding status\n")
3228 {
3229 int ret;
3230
3231 ret = ipforward();
3232
3233 if (ret == 0)
3234 vty_out(vty, "IP forwarding is off\n");
3235 else
3236 vty_out(vty, "IP forwarding is on\n");
3237 return CMD_SUCCESS;
3238 }
3239
3240 /* Only display ipv6 forwarding is enabled or not. */
3241 DEFUN (show_ipv6_forwarding,
3242 show_ipv6_forwarding_cmd,
3243 "show ipv6 forwarding",
3244 SHOW_STR
3245 "IPv6 information\n"
3246 "Forwarding status\n")
3247 {
3248 int ret;
3249
3250 ret = ipforward_ipv6();
3251
3252 switch (ret) {
3253 case -1:
3254 vty_out(vty, "ipv6 forwarding is unknown\n");
3255 break;
3256 case 0:
3257 vty_out(vty, "ipv6 forwarding is %s\n", "off");
3258 break;
3259 case 1:
3260 vty_out(vty, "ipv6 forwarding is %s\n", "on");
3261 break;
3262 default:
3263 vty_out(vty, "ipv6 forwarding is %s\n", "off");
3264 break;
3265 }
3266 return CMD_SUCCESS;
3267 }
3268
3269 DEFUN (ipv6_forwarding,
3270 ipv6_forwarding_cmd,
3271 "ipv6 forwarding",
3272 IPV6_STR
3273 "Turn on IPv6 forwarding\n")
3274 {
3275 int ret;
3276
3277 ret = ipforward_ipv6();
3278 if (ret == 0)
3279 ret = ipforward_ipv6_on();
3280
3281 if (ret == 0) {
3282 vty_out(vty, "Can't turn on IPv6 forwarding\n");
3283 return CMD_WARNING_CONFIG_FAILED;
3284 }
3285
3286 return CMD_SUCCESS;
3287 }
3288
3289 DEFUN (no_ipv6_forwarding,
3290 no_ipv6_forwarding_cmd,
3291 "no ipv6 forwarding",
3292 NO_STR
3293 IPV6_STR
3294 "Turn off IPv6 forwarding\n")
3295 {
3296 int ret;
3297
3298 ret = ipforward_ipv6();
3299 if (ret != 0)
3300 ret = ipforward_ipv6_off();
3301
3302 if (ret != 0) {
3303 vty_out(vty, "Can't turn off IPv6 forwarding\n");
3304 return CMD_WARNING_CONFIG_FAILED;
3305 }
3306
3307 return CMD_SUCCESS;
3308 }
3309
3310 /* Table configuration write function. */
3311 static int config_write_table(struct vty *vty)
3312 {
3313 if (zebrad.rtm_table_default)
3314 vty_out(vty, "table %d\n", zebrad.rtm_table_default);
3315 return 0;
3316 }
3317
3318 /* IPForwarding configuration write function. */
3319 static int config_write_forwarding(struct vty *vty)
3320 {
3321 /* FIXME: Find better place for that. */
3322 router_id_write(vty);
3323
3324 if (!ipforward())
3325 vty_out(vty, "no ip forwarding\n");
3326 if (!ipforward_ipv6())
3327 vty_out(vty, "no ipv6 forwarding\n");
3328 vty_out(vty, "!\n");
3329 return 0;
3330 }
3331
3332 /* IP node for static routes. */
3333 static struct cmd_node ip_node = {IP_NODE, "", 1};
3334 static struct cmd_node protocol_node = {PROTOCOL_NODE, "", 1};
3335 /* table node for routing tables. */
3336 static struct cmd_node table_node = {TABLE_NODE,
3337 "", /* This node has no interface. */
3338 1};
3339 static struct cmd_node forwarding_node = {FORWARDING_NODE,
3340 "", /* This node has no interface. */
3341 1};
3342
3343 /* Route VTY. */
3344 void zebra_vty_init(void)
3345 {
3346 /* Install configuration write function. */
3347 install_node(&table_node, config_write_table);
3348 install_node(&forwarding_node, config_write_forwarding);
3349
3350 install_element(VIEW_NODE, &show_ip_forwarding_cmd);
3351 install_element(CONFIG_NODE, &ip_forwarding_cmd);
3352 install_element(CONFIG_NODE, &no_ip_forwarding_cmd);
3353 install_element(ENABLE_NODE, &show_zebra_cmd);
3354
3355 #ifdef HAVE_NETLINK
3356 install_element(VIEW_NODE, &show_table_cmd);
3357 install_element(CONFIG_NODE, &config_table_cmd);
3358 install_element(CONFIG_NODE, &no_config_table_cmd);
3359 #endif /* HAVE_NETLINK */
3360
3361 install_element(VIEW_NODE, &show_ipv6_forwarding_cmd);
3362 install_element(CONFIG_NODE, &ipv6_forwarding_cmd);
3363 install_element(CONFIG_NODE, &no_ipv6_forwarding_cmd);
3364
3365 /* Route-map */
3366 zebra_route_map_init();
3367
3368 install_node(&ip_node, zebra_ip_config);
3369 install_node(&protocol_node, config_write_protocol);
3370
3371 install_element(CONFIG_NODE, &allow_external_route_update_cmd);
3372 install_element(CONFIG_NODE, &no_allow_external_route_update_cmd);
3373 install_element(CONFIG_NODE, &ip_mroute_dist_cmd);
3374 install_element(CONFIG_NODE, &ip_multicast_mode_cmd);
3375 install_element(CONFIG_NODE, &no_ip_multicast_mode_cmd);
3376 install_element(CONFIG_NODE, &ip_route_blackhole_cmd);
3377 install_element(VRF_NODE, &ip_route_blackhole_vrf_cmd);
3378 install_element(CONFIG_NODE, &ip_route_address_interface_cmd);
3379 install_element(VRF_NODE, &ip_route_address_interface_vrf_cmd);
3380 install_element(CONFIG_NODE, &ip_route_cmd);
3381 install_element(VRF_NODE, &ip_route_vrf_cmd);
3382 install_element(CONFIG_NODE, &ip_zebra_import_table_distance_cmd);
3383 install_element(CONFIG_NODE, &no_ip_zebra_import_table_cmd);
3384 install_element(CONFIG_NODE, &zebra_workqueue_timer_cmd);
3385 install_element(CONFIG_NODE, &no_zebra_workqueue_timer_cmd);
3386 install_element(CONFIG_NODE, &zebra_packet_process_cmd);
3387 install_element(CONFIG_NODE, &no_zebra_packet_process_cmd);
3388
3389 install_element(VIEW_NODE, &show_vrf_cmd);
3390 install_element(VIEW_NODE, &show_vrf_vni_cmd);
3391 install_element(VIEW_NODE, &show_route_cmd);
3392 install_element(VIEW_NODE, &show_route_table_cmd);
3393 install_element(VIEW_NODE, &show_route_detail_cmd);
3394 install_element(VIEW_NODE, &show_route_summary_cmd);
3395 install_element(VIEW_NODE, &show_ip_nht_cmd);
3396 install_element(VIEW_NODE, &show_ip_nht_vrf_all_cmd);
3397 install_element(VIEW_NODE, &show_ipv6_nht_cmd);
3398 install_element(VIEW_NODE, &show_ipv6_nht_vrf_all_cmd);
3399
3400 install_element(VIEW_NODE, &show_ip_rpf_cmd);
3401 install_element(VIEW_NODE, &show_ip_rpf_addr_cmd);
3402
3403 install_element(CONFIG_NODE, &ipv6_route_blackhole_cmd);
3404 install_element(VRF_NODE, &ipv6_route_blackhole_vrf_cmd);
3405 install_element(CONFIG_NODE, &ipv6_route_address_interface_cmd);
3406 install_element(VRF_NODE, &ipv6_route_address_interface_vrf_cmd);
3407 install_element(CONFIG_NODE, &ipv6_route_cmd);
3408 install_element(VRF_NODE, &ipv6_route_vrf_cmd);
3409 install_element(CONFIG_NODE, &ip_nht_default_route_cmd);
3410 install_element(CONFIG_NODE, &no_ip_nht_default_route_cmd);
3411 install_element(CONFIG_NODE, &ipv6_nht_default_route_cmd);
3412 install_element(CONFIG_NODE, &no_ipv6_nht_default_route_cmd);
3413 install_element(VIEW_NODE, &show_ipv6_mroute_cmd);
3414
3415 /* Commands for VRF */
3416 install_element(VIEW_NODE, &show_ipv6_mroute_vrf_all_cmd);
3417
3418 install_element(VIEW_NODE, &show_evpn_global_cmd);
3419 install_element(VIEW_NODE, &show_evpn_vni_cmd);
3420 install_element(VIEW_NODE, &show_evpn_vni_vni_cmd);
3421 install_element(VIEW_NODE, &show_evpn_rmac_vni_mac_cmd);
3422 install_element(VIEW_NODE, &show_evpn_rmac_vni_cmd);
3423 install_element(VIEW_NODE, &show_evpn_rmac_vni_all_cmd);
3424 install_element(VIEW_NODE, &show_evpn_nh_vni_ip_cmd);
3425 install_element(VIEW_NODE, &show_evpn_nh_vni_cmd);
3426 install_element(VIEW_NODE, &show_evpn_nh_vni_all_cmd);
3427 install_element(VIEW_NODE, &show_evpn_mac_vni_cmd);
3428 install_element(VIEW_NODE, &show_evpn_mac_vni_all_cmd);
3429 install_element(VIEW_NODE, &show_evpn_mac_vni_all_vtep_cmd);
3430 install_element(VIEW_NODE, &show_evpn_mac_vni_mac_cmd);
3431 install_element(VIEW_NODE, &show_evpn_mac_vni_vtep_cmd);
3432 install_element(VIEW_NODE, &show_evpn_neigh_vni_cmd);
3433 install_element(VIEW_NODE, &show_evpn_neigh_vni_all_cmd);
3434 install_element(VIEW_NODE, &show_evpn_neigh_vni_neigh_cmd);
3435 install_element(VIEW_NODE, &show_evpn_neigh_vni_vtep_cmd);
3436
3437 install_element(CONFIG_NODE, &default_vrf_vni_mapping_cmd);
3438 install_element(CONFIG_NODE, &no_default_vrf_vni_mapping_cmd);
3439 install_element(VRF_NODE, &vrf_vni_mapping_cmd);
3440 install_element(VRF_NODE, &no_vrf_vni_mapping_cmd);
3441
3442 }