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