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