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