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