]> git.proxmox.com Git - mirror_frr.git/blame - zebra/zebra_vty.c
zebra: Prevent installation for a nexthop vrf that is not configed yet
[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
6e94d410 151 ret = strcmp(shr1->nhvrf_name, shr2->nhvrf_name);
4060008b
DS
152 if (ret)
153 return ret;
154
155 ret = shr1->afi - shr2->afi;
156 if (ret)
157 return ret;
158
b88689f2 159 ret = shr1->safi - shr2->safi;
4060008b
DS
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
af5849b6
DS
252 XFREE(MTYPE_STATIC_ROUTE, shr->nhvrf_name);
253 XFREE(MTYPE_STATIC_ROUTE, shr->vrf_name);
254 XFREE(MTYPE_STATIC_ROUTE, shr);
ad97d1c1
DS
255 /*
256 * If a person enters the same line again
257 * we need to silently accept it
258 */
259 return CMD_SUCCESS;
4060008b
DS
260 }
261
b88689f2
QY
262 if (!negate)
263 listnode_add_sort(static_list, shr);
4060008b
DS
264
265 return CMD_SUCCESS;
266}
267
996c9314
LB
268static int zebra_static_route_leak(
269 struct vty *vty, struct zebra_vrf *zvrf, struct zebra_vrf *nh_zvrf,
270 afi_t afi, safi_t safi, const char *negate, const char *dest_str,
271 const char *mask_str, const char *src_str, const char *gate_str,
272 const char *ifname, const char *flag_str, const char *tag_str,
273 const char *distance_str, const char *label_str)
d62a17ae 274{
275 int ret;
276 u_char distance;
1d3f0eff
RW
277 struct prefix p, src;
278 struct prefix_ipv6 *src_p = NULL;
279 union g_addr gate;
280 union g_addr *gatep = NULL;
d62a17ae 281 struct in_addr mask;
9aabb2ea 282 enum static_blackhole_type bh_type = 0;
d62a17ae 283 route_tag_t tag = 0;
c6cef20b 284 u_char type;
d62a17ae 285 struct static_nh_label snh_label;
286
d62a17ae 287 ret = str2prefix(dest_str, &p);
288 if (ret <= 0) {
4060008b
DS
289 if (vty)
290 vty_out(vty, "%% Malformed address\n");
291 else
292 zlog_warn("%s: Malformed address: %s",
293 __PRETTY_FUNCTION__, dest_str);
d62a17ae 294 return CMD_WARNING_CONFIG_FAILED;
295 }
296
4060008b
DS
297 if (zvrf->vrf->vrf_id == VRF_UNKNOWN
298 || nh_zvrf->vrf->vrf_id == VRF_UNKNOWN) {
299 vrf_set_user_cfged(zvrf->vrf);
300 return zebra_static_route_holdem(
301 zvrf, nh_zvrf, afi, safi, negate, dest_str, mask_str,
302 src_str, gate_str, ifname, flag_str, tag_str,
303 distance_str, label_str);
304 }
1d3f0eff
RW
305 switch (afi) {
306 case AFI_IP:
307 /* Cisco like mask notation. */
308 if (mask_str) {
309 ret = inet_aton(mask_str, &mask);
310 if (ret == 0) {
4060008b
DS
311 if (vty)
312 vty_out(vty, "%% Malformed address\n");
313 else
314 zlog_warn("%s: Malformed address: %s",
315 __PRETTY_FUNCTION__,
316 mask_str);
1d3f0eff
RW
317 return CMD_WARNING_CONFIG_FAILED;
318 }
319 p.prefixlen = ip_masklen(mask);
320 }
321 break;
322 case AFI_IP6:
323 /* srcdest routing */
324 if (src_str) {
325 ret = str2prefix(src_str, &src);
326 if (ret <= 0 || src.family != AF_INET6) {
4060008b
DS
327 if (vty)
328 vty_out(vty,
329 "%% Malformed source address\n");
330 else
331 zlog_warn(
332 "%s: Malformed Source address: %s",
333 __PRETTY_FUNCTION__, src_str);
1d3f0eff
RW
334 return CMD_WARNING_CONFIG_FAILED;
335 }
336 src_p = (struct prefix_ipv6 *)&src;
d62a17ae 337 }
1d3f0eff
RW
338 break;
339 default:
340 break;
d62a17ae 341 }
342
343 /* Apply mask for given prefix. */
344 apply_mask(&p);
345
346 /* Administrative distance. */
347 if (distance_str)
348 distance = atoi(distance_str);
349 else
350 distance = ZEBRA_STATIC_DISTANCE_DEFAULT;
351
352 /* tag */
353 if (tag_str)
354 tag = strtoul(tag_str, NULL, 10);
355
d62a17ae 356 /* Labels */
1d3f0eff 357 memset(&snh_label, 0, sizeof(struct static_nh_label));
d62a17ae 358 if (label_str) {
359 if (!mpls_enabled) {
4060008b
DS
360 if (vty)
361 vty_out(vty,
362 "%% MPLS not turned on in kernel, ignoring command\n");
363 else
364 zlog_warn(
365 "%s: MPLS not turned on in kernel ignoring static route to %s",
366 __PRETTY_FUNCTION__, dest_str);
d62a17ae 367 return CMD_WARNING_CONFIG_FAILED;
368 }
369 int rc = mpls_str2label(label_str, &snh_label.num_labels,
370 snh_label.label);
371 if (rc < 0) {
372 switch (rc) {
373 case -1:
4060008b
DS
374 if (vty)
375 vty_out(vty, "%% Malformed label(s)\n");
376 else
377 zlog_warn(
378 "%s: Malformed labels specified for route %s",
379 __PRETTY_FUNCTION__, dest_str);
d62a17ae 380 break;
381 case -2:
4060008b
DS
382 if (vty)
383 vty_out(vty,
384 "%% Cannot use reserved label(s) (%d-%d)\n",
385 MPLS_LABEL_RESERVED_MIN,
386 MPLS_LABEL_RESERVED_MAX);
387 else
388 zlog_warn(
389 "%s: Cannot use reserved labels (%d-%d) for %s",
390 __PRETTY_FUNCTION__,
391 MPLS_LABEL_RESERVED_MIN,
392 MPLS_LABEL_RESERVED_MAX,
393 dest_str);
d62a17ae 394 break;
395 case -3:
4060008b
DS
396 if (vty)
397 vty_out(vty,
398 "%% Too many labels. Enter %d or fewer\n",
399 MPLS_MAX_LABELS);
400 else
401 zlog_warn(
402 "%s: Too many labels, Enter %d or fewer for %s",
403 __PRETTY_FUNCTION__,
404 MPLS_MAX_LABELS, dest_str);
d62a17ae 405 break;
406 }
407 return CMD_WARNING_CONFIG_FAILED;
408 }
409 }
410
57a58d77 411 /* Null0 static route. */
bb92922e 412 if (ifname != NULL) {
996c9314
LB
413 if (strncasecmp(ifname, "Null0", strlen(ifname)) == 0
414 || strncasecmp(ifname, "reject", strlen(ifname)) == 0
415 || strncasecmp(ifname, "blackhole", strlen(ifname)) == 0) {
4060008b
DS
416 if (vty)
417 vty_out(vty,
418 "%% Nexthop interface cannot be Null0, reject or blackhole\n");
419 else
420 zlog_warn(
421 "%s: Nexthop interface cannot be Null0, reject or blackhole for %s",
422 __PRETTY_FUNCTION__, dest_str);
bb92922e
DW
423 return CMD_WARNING_CONFIG_FAILED;
424 }
57a58d77
RW
425 }
426
d62a17ae 427 /* Route flags */
428 if (flag_str) {
429 switch (flag_str[0]) {
430 case 'r':
9aabb2ea 431 bh_type = STATIC_BLACKHOLE_REJECT;
d62a17ae 432 break;
433 case 'b':
9aabb2ea 434 bh_type = STATIC_BLACKHOLE_DROP;
d62a17ae 435 break;
bb92922e
DW
436 case 'N':
437 bh_type = STATIC_BLACKHOLE_NULL;
438 break;
d62a17ae 439 default:
4060008b
DS
440 if (vty)
441 vty_out(vty, "%% Malformed flag %s \n",
442 flag_str);
443 else
444 zlog_warn("%s: Malformed flag %s for %s",
445 __PRETTY_FUNCTION__, flag_str,
446 dest_str);
d62a17ae 447 return CMD_WARNING_CONFIG_FAILED;
448 }
449 }
450
c6cef20b 451 if (gate_str) {
1d3f0eff 452 if (inet_pton(afi2family(afi), gate_str, &gate) != 1) {
4060008b
DS
453 if (vty)
454 vty_out(vty,
455 "%% Malformed nexthop address %s\n",
456 gate_str);
457 else
458 zlog_warn(
459 "%s: Malformed nexthop address %s for %s",
460 __PRETTY_FUNCTION__, gate_str,
461 dest_str);
c6cef20b
RW
462 return CMD_WARNING_CONFIG_FAILED;
463 }
464 gatep = &gate;
d62a17ae 465 }
466
c6cef20b
RW
467 if (gate_str == NULL && ifname == NULL)
468 type = STATIC_BLACKHOLE;
1d3f0eff
RW
469 else if (gate_str && ifname) {
470 if (afi == AFI_IP)
23443030 471 type = STATIC_IPV4_GATEWAY_IFNAME;
1d3f0eff 472 else
23443030 473 type = STATIC_IPV6_GATEWAY_IFNAME;
1d3f0eff 474 } else if (ifname)
23443030 475 type = STATIC_IFNAME;
1d3f0eff
RW
476 else {
477 if (afi == AFI_IP)
478 type = STATIC_IPV4_GATEWAY;
479 else
480 type = STATIC_IPV6_GATEWAY;
481 }
d62a17ae 482
22bd3e94 483 if (!negate) {
c3c04063 484 static_add_route(afi, safi, type, &p, src_p, gatep, ifname,
cbb0dbf6
DS
485 bh_type, tag, distance, zvrf, nh_zvrf,
486 &snh_label);
22bd3e94 487 /* Mark as having FRR configuration */
488 vrf_set_user_cfged(zvrf->vrf);
489 } else {
c3c04063 490 static_delete_route(afi, safi, type, &p, src_p, gatep, ifname,
1d3f0eff 491 tag, distance, zvrf, &snh_label);
22bd3e94 492 /* If no other FRR config for this VRF, mark accordingly. */
493 if (!zebra_vrf_has_config(zvrf))
494 vrf_reset_user_cfged(zvrf->vrf);
495 }
d62a17ae 496
497 return CMD_SUCCESS;
718e3744 498}
499
e7f96f74
DS
500static struct zebra_vrf *zebra_vty_get_unknown_vrf(struct vty *vty,
501 const char *vrf_name)
502{
503 struct zebra_vrf *zvrf;
504 struct vrf *vrf;
505
506 zvrf = zebra_vrf_lookup_by_name(vrf_name);
507
508 if (zvrf)
509 return zvrf;
510
511 vrf = vrf_get(VRF_UNKNOWN, vrf_name);
512 if (!vrf) {
513 vty_out(vty, "%% Could not create vrf %s\n", vrf_name);
514 return NULL;
515 }
516 zvrf = vrf->info;
517 if (!zvrf) {
518 vty_out(vty, "%% Could not create vrf-info %s\n",
519 vrf_name);
520 return NULL;
521 }
522 /* Mark as having FRR configuration */
523 vrf_set_user_cfged(vrf);
524
525 return zvrf;
526}
527
2f03bc8f 528static int zebra_static_route(struct vty *vty, afi_t afi, safi_t safi,
996c9314
LB
529 const char *negate, const char *dest_str,
530 const char *mask_str, const char *src_str,
531 const char *gate_str, const char *ifname,
532 const char *flag_str, const char *tag_str,
533 const char *distance_str, const char *vrf_name,
534 const char *label_str)
2f03bc8f
DS
535{
536 struct zebra_vrf *zvrf;
537
538 /* VRF id */
22bd3e94 539 zvrf = zebra_vrf_lookup_by_name(vrf_name);
2f03bc8f 540
22bd3e94 541 /* When trying to delete, the VRF must exist. */
542 if (negate && !zvrf) {
543 vty_out(vty, "%% vrf %s is not defined\n", vrf_name);
2f03bc8f
DS
544 return CMD_WARNING_CONFIG_FAILED;
545 }
546
22bd3e94 547 /* When trying to create, create the VRF if it doesn't exist.
548 * Note: The VRF isn't active until we hear about it from the kernel.
549 */
550 if (!zvrf) {
e7f96f74
DS
551 zvrf = zebra_vty_get_unknown_vrf(vty, vrf_name);
552 if (!zvrf)
22bd3e94 553 return CMD_WARNING_CONFIG_FAILED;
22bd3e94 554 }
996c9314
LB
555 return zebra_static_route_leak(
556 vty, zvrf, zvrf, afi, safi, negate, dest_str, mask_str, src_str,
557 gate_str, ifname, flag_str, tag_str, distance_str, label_str);
2f03bc8f
DS
558}
559
4060008b
DS
560void static_config_install_delayed_routes(struct zebra_vrf *zvrf)
561{
562 struct listnode *node, *nnode;
563 struct static_hold_route *shr;
564 struct zebra_vrf *ozvrf, *nh_zvrf;
565 int installed;
566
567 for (ALL_LIST_ELEMENTS(static_list, node, nnode, shr)) {
568 ozvrf = zebra_vrf_lookup_by_name(shr->vrf_name);
569 nh_zvrf = zebra_vrf_lookup_by_name(shr->nhvrf_name);
570
571 if (ozvrf != zvrf && nh_zvrf != zvrf)
572 continue;
573
574 if (ozvrf->vrf->vrf_id == VRF_UNKNOWN
575 || nh_zvrf->vrf->vrf_id == VRF_UNKNOWN)
576 continue;
2f03bc8f 577
4060008b
DS
578 installed = zebra_static_route_leak(
579 NULL, ozvrf, nh_zvrf, shr->afi, shr->safi, NULL,
580 shr->dest_str, shr->mask_str, shr->src_str,
581 shr->gate_str, shr->ifname, shr->flag_str, shr->tag_str,
582 shr->distance_str, shr->label_str);
583
584 if (installed != CMD_SUCCESS)
585 zlog_debug(
586 "%s: Attempt to install %s as a route and it was rejected",
587 __PRETTY_FUNCTION__, shr->dest_str);
588 listnode_delete(static_list, shr);
589 static_list_delete(shr);
590 }
591}
b78a80d7 592/* Static unicast routes for multicast RPF lookup. */
00685a85 593DEFPY (ip_mroute_dist,
b8a96915 594 ip_mroute_dist_cmd,
00685a85 595 "[no] ip mroute A.B.C.D/M$prefix <A.B.C.D$gate|INTERFACE$ifname> [(1-255)$distance]",
d7fa34c1 596 NO_STR
b78a80d7
EM
597 IP_STR
598 "Configure static unicast route into MRIB for multicast RPF lookup\n"
599 "IP destination prefix (e.g. 10.0.0.0/8)\n"
600 "Nexthop address\n"
601 "Nexthop interface name\n"
602 "Distance\n")
603{
00685a85
RW
604 return zebra_static_route(vty, AFI_IP, SAFI_MULTICAST, no, prefix_str,
605 NULL, NULL, gate_str, ifname, NULL, NULL,
606 distance_str, NULL, NULL);
b62ecea5 607}
b8a96915 608
4623d897
DL
609DEFUN (ip_multicast_mode,
610 ip_multicast_mode_cmd,
6147e2c6 611 "ip multicast rpf-lookup-mode <urib-only|mrib-only|mrib-then-urib|lower-distance|longer-prefix>",
4623d897
DL
612 IP_STR
613 "Multicast options\n"
614 "RPF lookup behavior\n"
615 "Lookup in unicast RIB only\n"
616 "Lookup in multicast RIB only\n"
617 "Try multicast RIB first, fall back to unicast RIB\n"
618 "Lookup both, use entry with lower distance\n"
619 "Lookup both, use entry with longer prefix\n")
620{
d62a17ae 621 char *mode = argv[3]->text;
622
623 if (strmatch(mode, "urib-only"))
624 multicast_mode_ipv4_set(MCAST_URIB_ONLY);
625 else if (strmatch(mode, "mrib-only"))
626 multicast_mode_ipv4_set(MCAST_MRIB_ONLY);
627 else if (strmatch(mode, "mrib-then-urib"))
628 multicast_mode_ipv4_set(MCAST_MIX_MRIB_FIRST);
629 else if (strmatch(mode, "lower-distance"))
630 multicast_mode_ipv4_set(MCAST_MIX_DISTANCE);
631 else if (strmatch(mode, "longer-prefix"))
632 multicast_mode_ipv4_set(MCAST_MIX_PFXLEN);
633 else {
634 vty_out(vty, "Invalid mode specified\n");
635 return CMD_WARNING_CONFIG_FAILED;
636 }
4623d897 637
d62a17ae 638 return CMD_SUCCESS;
4623d897
DL
639}
640
641DEFUN (no_ip_multicast_mode,
642 no_ip_multicast_mode_cmd,
b62ecea5 643 "no ip multicast rpf-lookup-mode [<urib-only|mrib-only|mrib-then-urib|lower-distance|longer-prefix>]",
4623d897
DL
644 NO_STR
645 IP_STR
646 "Multicast options\n"
647 "RPF lookup behavior\n"
648 "Lookup in unicast RIB only\n"
649 "Lookup in multicast RIB only\n"
650 "Try multicast RIB first, fall back to unicast RIB\n"
651 "Lookup both, use entry with lower distance\n"
652 "Lookup both, use entry with longer prefix\n")
653{
d62a17ae 654 multicast_mode_ipv4_set(MCAST_NO_CONFIG);
655 return CMD_SUCCESS;
4623d897
DL
656}
657
4623d897 658
b78a80d7
EM
659DEFUN (show_ip_rpf,
660 show_ip_rpf_cmd,
acb25e73 661 "show ip rpf [json]",
b78a80d7
EM
662 SHOW_STR
663 IP_STR
acb25e73
DW
664 "Display RPF information for multicast source\n"
665 JSON_STR)
b78a80d7 666{
d62a17ae 667 int uj = use_json(argc, argv);
668 return do_show_ip_route(vty, VRF_DEFAULT_NAME, AFI_IP, SAFI_MULTICAST,
fba31af2 669 false, uj, 0, NULL, false, 0, 0);
b78a80d7
EM
670}
671
65dd94cf
DL
672DEFUN (show_ip_rpf_addr,
673 show_ip_rpf_addr_cmd,
674 "show ip rpf A.B.C.D",
675 SHOW_STR
676 IP_STR
677 "Display RPF information for multicast source\n"
678 "IP multicast source address (e.g. 10.0.0.0)\n")
679{
d62a17ae 680 int idx_ipv4 = 3;
681 struct in_addr addr;
682 struct route_node *rn;
683 struct route_entry *re;
684 int ret;
685
686 ret = inet_aton(argv[idx_ipv4]->arg, &addr);
687 if (ret == 0) {
688 vty_out(vty, "%% Malformed address\n");
689 return CMD_WARNING;
690 }
691
692 re = rib_match_ipv4_multicast(VRF_DEFAULT, addr, &rn);
693
694 if (re)
695 vty_show_ip_route_detail(vty, rn, 1);
696 else
697 vty_out(vty, "%% No match for RPF lookup\n");
698
699 return CMD_SUCCESS;
700}
701
030721b7 702/* Static route configuration. */
1e058f38
DW
703DEFPY(ip_route_blackhole,
704 ip_route_blackhole_cmd,
60466a63 705 "[no] ip route\
d7d75634 706 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
10c61d28 707 <reject|blackhole>$flag \
d7d75634
DW
708 [{ \
709 tag (1-4294967295) \
710 |(1-255)$distance \
711 |vrf NAME \
712 |label WORD \
00685a85 713 }]",
60466a63
QY
714 NO_STR IP_STR
715 "Establish static routes\n"
716 "IP destination prefix (e.g. 10.0.0.0/8)\n"
717 "IP destination prefix\n"
718 "IP destination prefix mask\n"
60466a63
QY
719 "Emit an ICMP unreachable when matched\n"
720 "Silently discard pkts when matched\n"
721 "Set tag for this route\n"
722 "Tag value\n"
723 "Distance value for this route\n"
724 VRF_CMD_HELP_STR
725 MPLS_LABEL_HELPSTR)
599186ad 726{
00685a85 727 return zebra_static_route(vty, AFI_IP, SAFI_UNICAST, no, prefix,
996c9314
LB
728 mask_str, NULL, NULL, NULL, flag, tag_str,
729 distance_str, vrf, label);
1e058f38
DW
730}
731
b2ffa06b
DS
732DEFPY(ip_route_blackhole_vrf,
733 ip_route_blackhole_vrf_cmd,
734 "[no] ip route\
735 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
736 <reject|blackhole>$flag \
737 [{ \
738 tag (1-4294967295) \
739 |(1-255)$distance \
740 |label WORD \
741 }]",
742 NO_STR IP_STR
743 "Establish static routes\n"
744 "IP destination prefix (e.g. 10.0.0.0/8)\n"
745 "IP destination prefix\n"
746 "IP destination prefix mask\n"
747 "Emit an ICMP unreachable when matched\n"
748 "Silently discard pkts when matched\n"
749 "Set tag for this route\n"
750 "Tag value\n"
751 "Distance value for this route\n"
752 MPLS_LABEL_HELPSTR)
753{
754 VTY_DECLVAR_CONTEXT(vrf, vrf);
755 struct zebra_vrf *zvrf = vrf->info;
756
6447dbb3
DS
757 /*
758 * Coverity is complaining that prefix could
759 * be dereferenced, but we know that prefix will
760 * valid. Add an assert to make it happy
761 */
762 assert(prefix);
996c9314
LB
763 return zebra_static_route_leak(vty, zvrf, zvrf, AFI_IP, SAFI_UNICAST,
764 no, prefix, mask_str, NULL, NULL, NULL,
765 flag, tag_str, distance_str, label);
b2ffa06b
DS
766}
767
1e058f38
DW
768DEFPY(ip_route_address_interface,
769 ip_route_address_interface_cmd,
770 "[no] ip route\
771 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
772 A.B.C.D$gate \
773 INTERFACE$ifname \
774 [{ \
775 tag (1-4294967295) \
776 |(1-255)$distance \
777 |vrf NAME \
778 |label WORD \
61408536 779 |nexthop-vrf NAME \
1e058f38
DW
780 }]",
781 NO_STR IP_STR
782 "Establish static routes\n"
783 "IP destination prefix (e.g. 10.0.0.0/8)\n"
784 "IP destination prefix\n"
785 "IP destination prefix mask\n"
786 "IP gateway address\n"
10c61d28
QY
787 "IP gateway interface name. Specify 'Null0' (case-insensitive) for a \
788 null route.\n"
1e058f38
DW
789 "Set tag for this route\n"
790 "Tag value\n"
791 "Distance value for this route\n"
792 VRF_CMD_HELP_STR
61408536
DS
793 MPLS_LABEL_HELPSTR
794 VRF_CMD_HELP_STR)
1e058f38 795{
61408536
DS
796 struct zebra_vrf *zvrf;
797 struct zebra_vrf *nh_zvrf;
798
10c61d28
QY
799 const char *flag = NULL;
800 if (ifname && !strncasecmp(ifname, "Null0", 5)) {
801 flag = "Null0";
802 ifname = NULL;
803 }
61408536 804
6a17b1a0 805 zvrf = zebra_vty_get_unknown_vrf(vty, vrf);
e65dfe7e 806 if (!zvrf) {
996c9314 807 vty_out(vty, "%% vrf %s is not defined\n", vrf);
e65dfe7e
DS
808 return CMD_WARNING_CONFIG_FAILED;
809 }
810
811 if (nexthop_vrf)
e7f96f74 812 nh_zvrf = zebra_vty_get_unknown_vrf(vty, nexthop_vrf);
e65dfe7e
DS
813 else
814 nh_zvrf = zvrf;
61408536 815
61408536 816 if (!nh_zvrf) {
996c9314 817 vty_out(vty, "%% nexthop vrf %s is not defined\n", nexthop_vrf);
61408536
DS
818 return CMD_WARNING_CONFIG_FAILED;
819 }
820
996c9314
LB
821 return zebra_static_route_leak(
822 vty, zvrf, nh_zvrf, AFI_IP, SAFI_UNICAST, no, prefix, mask_str,
823 NULL, gate_str, ifname, flag, tag_str, distance_str, label);
1e058f38
DW
824}
825
b2ffa06b
DS
826DEFPY(ip_route_address_interface_vrf,
827 ip_route_address_interface_vrf_cmd,
828 "[no] ip route\
829 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
830 A.B.C.D$gate \
831 INTERFACE$ifname \
832 [{ \
833 tag (1-4294967295) \
834 |(1-255)$distance \
835 |label WORD \
836 |nexthop-vrf NAME \
837 }]",
838 NO_STR IP_STR
839 "Establish static routes\n"
840 "IP destination prefix (e.g. 10.0.0.0/8)\n"
841 "IP destination prefix\n"
842 "IP destination prefix mask\n"
843 "IP gateway address\n"
844 "IP gateway interface name. Specify 'Null0' (case-insensitive) for a \
845 null route.\n"
846 "Set tag for this route\n"
847 "Tag value\n"
848 "Distance value for this route\n"
849 MPLS_LABEL_HELPSTR
850 VRF_CMD_HELP_STR)
851{
852 VTY_DECLVAR_CONTEXT(vrf, vrf);
853 const char *flag = NULL;
854 struct zebra_vrf *zvrf = vrf->info;
855 struct zebra_vrf *nh_zvrf;
856
857 if (ifname && !strncasecmp(ifname, "Null0", 5)) {
858 flag = "Null0";
859 ifname = NULL;
860 }
861
dfce9b25 862 if (nexthop_vrf)
e7f96f74 863 nh_zvrf = zebra_vty_get_unknown_vrf(vty, nexthop_vrf);
dfce9b25
DS
864 else
865 nh_zvrf = zvrf;
866
b2ffa06b 867 if (!nh_zvrf) {
996c9314 868 vty_out(vty, "%% nexthop vrf %s is not defined\n", nexthop_vrf);
b2ffa06b
DS
869 return CMD_WARNING_CONFIG_FAILED;
870 }
871
996c9314
LB
872 return zebra_static_route_leak(
873 vty, zvrf, nh_zvrf, AFI_IP, SAFI_UNICAST, no, prefix, mask_str,
874 NULL, gate_str, ifname, flag, tag_str, distance_str, label);
1e058f38
DW
875}
876
877DEFPY(ip_route,
878 ip_route_cmd,
879 "[no] ip route\
880 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
881 <A.B.C.D$gate|INTERFACE$ifname> \
882 [{ \
883 tag (1-4294967295) \
884 |(1-255)$distance \
885 |vrf NAME \
886 |label WORD \
61408536 887 |nexthop-vrf NAME \
1e058f38
DW
888 }]",
889 NO_STR IP_STR
890 "Establish static routes\n"
891 "IP destination prefix (e.g. 10.0.0.0/8)\n"
892 "IP destination prefix\n"
893 "IP destination prefix mask\n"
894 "IP gateway address\n"
895 "IP gateway interface name\n"
896 "Set tag for this route\n"
897 "Tag value\n"
898 "Distance value for this route\n"
899 VRF_CMD_HELP_STR
61408536
DS
900 MPLS_LABEL_HELPSTR
901 VRF_CMD_HELP_STR)
1e058f38 902{
61408536
DS
903 struct zebra_vrf *zvrf;
904 struct zebra_vrf *nh_zvrf;
10c61d28 905 const char *flag = NULL;
61408536 906
10c61d28
QY
907 if (ifname && !strncasecmp(ifname, "Null0", 5)) {
908 flag = "Null0";
909 ifname = NULL;
910 }
61408536 911
6a17b1a0 912 zvrf = zebra_vty_get_unknown_vrf(vty, vrf);
e65dfe7e 913 if (!zvrf) {
996c9314 914 vty_out(vty, "%% vrf %s is not defined\n", vrf);
e65dfe7e
DS
915 return CMD_WARNING_CONFIG_FAILED;
916 }
917
918 if (nexthop_vrf)
e7f96f74 919 nh_zvrf = zebra_vty_get_unknown_vrf(vty, nexthop_vrf);
e65dfe7e
DS
920 else
921 nh_zvrf = zvrf;
61408536 922
61408536 923 if (!nh_zvrf) {
996c9314 924 vty_out(vty, "%% nexthop vrf %s is not defined\n", nexthop_vrf);
61408536
DS
925 return CMD_WARNING_CONFIG_FAILED;
926 }
927
e65dfe7e 928
996c9314
LB
929 return zebra_static_route_leak(
930 vty, zvrf, nh_zvrf, AFI_IP, SAFI_UNICAST, no, prefix, mask_str,
931 NULL, gate_str, ifname, flag, tag_str, distance_str, label);
8f527c5e 932}
718e3744 933
b2ffa06b
DS
934DEFPY(ip_route_vrf,
935 ip_route_vrf_cmd,
936 "[no] ip route\
937 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask> \
938 <A.B.C.D$gate|INTERFACE$ifname> \
939 [{ \
940 tag (1-4294967295) \
941 |(1-255)$distance \
942 |label WORD \
943 |nexthop-vrf NAME \
944 }]",
945 NO_STR IP_STR
946 "Establish static routes\n"
947 "IP destination prefix (e.g. 10.0.0.0/8)\n"
948 "IP destination prefix\n"
949 "IP destination prefix mask\n"
950 "IP gateway address\n"
951 "IP gateway interface name\n"
952 "Set tag for this route\n"
953 "Tag value\n"
954 "Distance value for this route\n"
955 MPLS_LABEL_HELPSTR
956 VRF_CMD_HELP_STR)
957{
958 VTY_DECLVAR_CONTEXT(vrf, vrf);
959 struct zebra_vrf *zvrf = vrf->info;
960 struct zebra_vrf *nh_zvrf;
961
962 const char *flag = NULL;
963 if (ifname && !strncasecmp(ifname, "Null0", 5)) {
964 flag = "Null0";
965 ifname = NULL;
966 }
967
dfce9b25 968 if (nexthop_vrf)
e7f96f74 969 nh_zvrf = zebra_vty_get_unknown_vrf(vty, nexthop_vrf);
dfce9b25
DS
970 else
971 nh_zvrf = zvrf;
972
b2ffa06b 973 if (!nh_zvrf) {
996c9314 974 vty_out(vty, "%% nexthop vrf %s is not defined\n", nexthop_vrf);
b2ffa06b
DS
975 return CMD_WARNING_CONFIG_FAILED;
976 }
977
996c9314
LB
978 return zebra_static_route_leak(
979 vty, zvrf, nh_zvrf, AFI_IP, SAFI_UNICAST, no, prefix, mask_str,
980 NULL, gate_str, ifname, flag, tag_str, distance_str, label);
8f527c5e 981}
718e3744 982
8f527c5e 983/* New RIB. Detailed information for IPv4 route. */
d62a17ae 984static void vty_show_ip_route_detail(struct vty *vty, struct route_node *rn,
985 int mcast)
986{
987 struct route_entry *re;
988 struct nexthop *nexthop;
989 char buf[SRCDEST2STR_BUFFER];
990 struct zebra_vrf *zvrf;
991
a2addae8 992 RNODE_FOREACH_RE (rn, re) {
d62a17ae 993 const char *mcast_info = "";
994 if (mcast) {
995 rib_table_info_t *info = srcdest_rnode_table_info(rn);
996 mcast_info = (info->safi == SAFI_MULTICAST)
997 ? " using Multicast RIB"
998 : " using Unicast RIB";
999 }
1000
1001 vty_out(vty, "Routing entry for %s%s\n",
1002 srcdest_rnode2str(rn, buf, sizeof(buf)), mcast_info);
1003 vty_out(vty, " Known via \"%s", zebra_route_string(re->type));
1004 if (re->instance)
1005 vty_out(vty, "[%d]", re->instance);
1006 vty_out(vty, "\"");
1007 vty_out(vty, ", distance %u, metric %u", re->distance,
1008 re->metric);
0efb5e9b 1009 if (re->tag) {
8526b842 1010 vty_out(vty, ", tag %u", re->tag);
0efb5e9b
DS
1011#if defined(SUPPORT_REALMS)
1012 if (re->tag > 0 && re->tag <= 255)
1013 vty_out(vty, "(realm)");
1014#endif
1015 }
d62a17ae 1016 if (re->mtu)
1017 vty_out(vty, ", mtu %u", re->mtu);
1018 if (re->vrf_id != VRF_DEFAULT) {
1019 zvrf = vrf_info_lookup(re->vrf_id);
1020 vty_out(vty, ", vrf %s", zvrf_name(zvrf));
1021 }
1022 if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED))
1023 vty_out(vty, ", best");
d62a17ae 1024 vty_out(vty, "\n");
1025
14a481d9
DS
1026 time_t uptime;
1027 struct tm *tm;
1028
1029 uptime = time(NULL);
1030 uptime -= re->uptime;
1031 tm = gmtime(&uptime);
1032
1033 vty_out(vty, " Last update ");
1034
1035 if (uptime < ONE_DAY_SECOND)
996c9314
LB
1036 vty_out(vty, "%02d:%02d:%02d", tm->tm_hour, tm->tm_min,
1037 tm->tm_sec);
14a481d9 1038 else if (uptime < ONE_WEEK_SECOND)
996c9314
LB
1039 vty_out(vty, "%dd%02dh%02dm", tm->tm_yday, tm->tm_hour,
1040 tm->tm_min);
14a481d9
DS
1041 else
1042 vty_out(vty, "%02dw%dd%02dh", tm->tm_yday / 7,
1043 tm->tm_yday - ((tm->tm_yday / 7) * 7),
1044 tm->tm_hour);
1045 vty_out(vty, " ago\n");
d62a17ae 1046
7ee30f28 1047 for (ALL_NEXTHOPS(re->ng, nexthop)) {
d62a17ae 1048 char addrstr[32];
1049
1050 vty_out(vty, " %c%s",
1051 CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)
996c9314
LB
1052 ? CHECK_FLAG(nexthop->flags,
1053 NEXTHOP_FLAG_DUPLICATE)
1054 ? ' '
1055 : '*'
d62a17ae 1056 : ' ',
1057 nexthop->rparent ? " " : "");
1058
1059 switch (nexthop->type) {
1060 case NEXTHOP_TYPE_IPV4:
1061 case NEXTHOP_TYPE_IPV4_IFINDEX:
1062 vty_out(vty, " %s",
1063 inet_ntoa(nexthop->gate.ipv4));
1064 if (nexthop->ifindex)
1065 vty_out(vty, ", via %s",
4a7371e9
DS
1066 ifindex2ifname(
1067 nexthop->ifindex,
1068 nexthop->vrf_id));
d62a17ae 1069 break;
1070 case NEXTHOP_TYPE_IPV6:
1071 case NEXTHOP_TYPE_IPV6_IFINDEX:
1072 vty_out(vty, " %s",
1073 inet_ntop(AF_INET6, &nexthop->gate.ipv6,
1074 buf, sizeof buf));
1075 if (nexthop->ifindex)
1076 vty_out(vty, ", via %s",
4a7371e9
DS
1077 ifindex2ifname(
1078 nexthop->ifindex,
1079 nexthop->vrf_id));
d62a17ae 1080 break;
1081 case NEXTHOP_TYPE_IFINDEX:
1082 vty_out(vty, " directly connected, %s",
1083 ifindex2ifname(nexthop->ifindex,
4a7371e9 1084 nexthop->vrf_id));
d62a17ae 1085 break;
1086 case NEXTHOP_TYPE_BLACKHOLE:
a8309422
DL
1087 vty_out(vty, " unreachable");
1088 switch (nexthop->bh_type) {
1089 case BLACKHOLE_REJECT:
1090 vty_out(vty, " (ICMP unreachable)");
1091 break;
1092 case BLACKHOLE_ADMINPROHIB:
60466a63
QY
1093 vty_out(vty,
1094 " (ICMP admin-prohibited)");
a8309422
DL
1095 break;
1096 case BLACKHOLE_NULL:
1097 vty_out(vty, " (blackhole)");
1098 break;
1099 case BLACKHOLE_UNSPEC:
1100 break;
1101 }
d62a17ae 1102 break;
1103 default:
1104 break;
1105 }
2793a098 1106
4a7371e9 1107 if (re->vrf_id != nexthop->vrf_id) {
2793a098 1108 struct vrf *vrf =
4a7371e9 1109 vrf_lookup_by_id(nexthop->vrf_id);
2793a098
DS
1110
1111 vty_out(vty, "(vrf %s)", vrf->name);
1112 }
1113
eaf5150f
DS
1114 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_DUPLICATE))
1115 vty_out(vty, " (duplicate nexthop removed)");
1116
d62a17ae 1117 if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
1118 vty_out(vty, " inactive");
1119
1120 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK))
1121 vty_out(vty, " onlink");
1122
1123 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
1124 vty_out(vty, " (recursive)");
1125
1126 switch (nexthop->type) {
1127 case NEXTHOP_TYPE_IPV4:
1128 case NEXTHOP_TYPE_IPV4_IFINDEX:
1129 if (nexthop->src.ipv4.s_addr) {
1130 if (inet_ntop(AF_INET,
1131 &nexthop->src.ipv4,
1132 addrstr, sizeof addrstr))
1133 vty_out(vty, ", src %s",
1134 addrstr);
1135 }
1136 break;
1137 case NEXTHOP_TYPE_IPV6:
1138 case NEXTHOP_TYPE_IPV6_IFINDEX:
1139 if (!IPV6_ADDR_SAME(&nexthop->src.ipv6,
1140 &in6addr_any)) {
1141 if (inet_ntop(AF_INET6,
1142 &nexthop->src.ipv6,
1143 addrstr, sizeof addrstr))
1144 vty_out(vty, ", src %s",
1145 addrstr);
1146 }
1147 break;
1148 default:
1149 break;
1150 }
1151
1994ae60
JB
1152 if (re->nexthop_mtu)
1153 vty_out(vty, ", mtu %u", re->nexthop_mtu);
1154
d62a17ae 1155 /* Label information */
1156 if (nexthop->nh_label
1157 && nexthop->nh_label->num_labels) {
1158 vty_out(vty, ", label %s",
1159 mpls_label2str(
1160 nexthop->nh_label->num_labels,
1161 nexthop->nh_label->label, buf,
1162 sizeof buf, 1));
1163 }
1164
1165 vty_out(vty, "\n");
1166 }
1167 vty_out(vty, "\n");
1168 }
1169}
1170
1171static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
1172 struct route_entry *re, json_object *json)
1173{
1174 struct nexthop *nexthop;
1175 int len = 0;
1176 char buf[SRCDEST2STR_BUFFER];
1177 json_object *json_nexthops = NULL;
1178 json_object *json_nexthop = NULL;
1179 json_object *json_route = NULL;
1180 json_object *json_labels = NULL;
14a481d9
DS
1181 time_t uptime;
1182 struct tm *tm;
1183
1184 uptime = time(NULL);
1185 uptime -= re->uptime;
1186 tm = gmtime(&uptime);
d62a17ae 1187
1188 if (json) {
1189 json_route = json_object_new_object();
1190 json_nexthops = json_object_new_array();
1191
1192 json_object_string_add(json_route, "prefix",
1193 srcdest_rnode2str(rn, buf, sizeof buf));
1194 json_object_string_add(json_route, "protocol",
1195 zebra_route_string(re->type));
1196
1197 if (re->instance)
1198 json_object_int_add(json_route, "instance",
1199 re->instance);
1200
1201 if (re->vrf_id)
1202 json_object_int_add(json_route, "vrfId", re->vrf_id);
1203
1204 if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED))
1205 json_object_boolean_true_add(json_route, "selected");
1206
925c2f88 1207 if (re->type != ZEBRA_ROUTE_CONNECT) {
d62a17ae 1208 json_object_int_add(json_route, "distance",
1209 re->distance);
1210 json_object_int_add(json_route, "metric", re->metric);
1211 }
1212
14a481d9 1213 if (uptime < ONE_DAY_SECOND)
996c9314
LB
1214 sprintf(buf, "%02d:%02d:%02d", tm->tm_hour, tm->tm_min,
1215 tm->tm_sec);
14a481d9 1216 else if (uptime < ONE_WEEK_SECOND)
996c9314
LB
1217 sprintf(buf, "%dd%02dh%02dm", tm->tm_yday, tm->tm_hour,
1218 tm->tm_min);
14a481d9
DS
1219 else
1220 sprintf(buf, "%02dw%dd%02dh", tm->tm_yday / 7,
1221 tm->tm_yday - ((tm->tm_yday / 7) * 7),
1222 tm->tm_hour);
1223
1224 json_object_string_add(json_route, "uptime", buf);
d62a17ae 1225
7ee30f28 1226 for (ALL_NEXTHOPS(re->ng, nexthop)) {
d62a17ae 1227 json_nexthop = json_object_new_object();
1228
eaf5150f
DS
1229 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_DUPLICATE))
1230 json_object_boolean_true_add(json_nexthop,
1231 "duplicate");
1232
d62a17ae 1233 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB))
1234 json_object_boolean_true_add(json_nexthop,
1235 "fib");
1236
1237 switch (nexthop->type) {
1238 case NEXTHOP_TYPE_IPV4:
1239 case NEXTHOP_TYPE_IPV4_IFINDEX:
1240 json_object_string_add(
1241 json_nexthop, "ip",
1242 inet_ntoa(nexthop->gate.ipv4));
1243 json_object_string_add(json_nexthop, "afi",
1244 "ipv4");
1245
1246 if (nexthop->ifindex) {
1247 json_object_int_add(json_nexthop,
1248 "interfaceIndex",
1249 nexthop->ifindex);
1250 json_object_string_add(
1251 json_nexthop, "interfaceName",
4a7371e9
DS
1252 ifindex2ifname(
1253 nexthop->ifindex,
1254 nexthop->vrf_id));
d62a17ae 1255 }
1256 break;
1257 case NEXTHOP_TYPE_IPV6:
1258 case NEXTHOP_TYPE_IPV6_IFINDEX:
1259 json_object_string_add(
1260 json_nexthop, "ip",
1261 inet_ntop(AF_INET6, &nexthop->gate.ipv6,
1262 buf, sizeof buf));
1263 json_object_string_add(json_nexthop, "afi",
1264 "ipv6");
1265
1266 if (nexthop->ifindex) {
1267 json_object_int_add(json_nexthop,
1268 "interfaceIndex",
1269 nexthop->ifindex);
1270 json_object_string_add(
1271 json_nexthop, "interfaceName",
4a7371e9
DS
1272 ifindex2ifname(
1273 nexthop->ifindex,
1274 nexthop->vrf_id));
d62a17ae 1275 }
1276 break;
1277
1278 case NEXTHOP_TYPE_IFINDEX:
1279 json_object_boolean_true_add(
1280 json_nexthop, "directlyConnected");
1281 json_object_int_add(json_nexthop,
1282 "interfaceIndex",
1283 nexthop->ifindex);
1284 json_object_string_add(
1285 json_nexthop, "interfaceName",
1286 ifindex2ifname(nexthop->ifindex,
4a7371e9 1287 nexthop->vrf_id));
d62a17ae 1288 break;
1289 case NEXTHOP_TYPE_BLACKHOLE:
1290 json_object_boolean_true_add(json_nexthop,
a8309422
DL
1291 "unreachable");
1292 switch (nexthop->bh_type) {
1293 case BLACKHOLE_REJECT:
1294 json_object_boolean_true_add(
60466a63 1295 json_nexthop, "reject");
a8309422
DL
1296 break;
1297 case BLACKHOLE_ADMINPROHIB:
1298 json_object_boolean_true_add(
60466a63
QY
1299 json_nexthop,
1300 "admin-prohibited");
a8309422
DL
1301 break;
1302 case BLACKHOLE_NULL:
1303 json_object_boolean_true_add(
60466a63 1304 json_nexthop, "blackhole");
a8309422
DL
1305 break;
1306 case BLACKHOLE_UNSPEC:
1307 break;
1308 }
d62a17ae 1309 break;
1310 default:
1311 break;
1312 }
1313
4a7371e9 1314 if (nexthop->vrf_id != re->vrf_id) {
2793a098 1315 struct vrf *vrf =
4a7371e9 1316 vrf_lookup_by_id(nexthop->vrf_id);
2793a098 1317
996c9314 1318 json_object_string_add(json_nexthop, "vrf",
2793a098
DS
1319 vrf->name);
1320 }
eaf5150f
DS
1321 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_DUPLICATE))
1322 json_object_boolean_true_add(json_nexthop,
1323 "duplicate");
1324
d62a17ae 1325 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
1326 json_object_boolean_true_add(json_nexthop,
1327 "active");
1328
1329 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK))
1330 json_object_boolean_true_add(json_nexthop,
1331 "onLink");
1332
1333 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
1334 json_object_boolean_true_add(json_nexthop,
1335 "recursive");
1336
1337 switch (nexthop->type) {
1338 case NEXTHOP_TYPE_IPV4:
1339 case NEXTHOP_TYPE_IPV4_IFINDEX:
1340 if (nexthop->src.ipv4.s_addr) {
1341 if (inet_ntop(AF_INET,
1342 &nexthop->src.ipv4, buf,
1343 sizeof buf))
1344 json_object_string_add(
1345 json_nexthop, "source",
1346 buf);
1347 }
1348 break;
1349 case NEXTHOP_TYPE_IPV6:
1350 case NEXTHOP_TYPE_IPV6_IFINDEX:
1351 if (!IPV6_ADDR_SAME(&nexthop->src.ipv6,
1352 &in6addr_any)) {
1353 if (inet_ntop(AF_INET6,
1354 &nexthop->src.ipv6, buf,
1355 sizeof buf))
1356 json_object_string_add(
1357 json_nexthop, "source",
1358 buf);
1359 }
1360 break;
1361 default:
1362 break;
1363 }
1364
1365 if (nexthop->nh_label
1366 && nexthop->nh_label->num_labels) {
1367 json_labels = json_object_new_array();
1368
1369 for (int label_index = 0;
1370 label_index
1371 < nexthop->nh_label->num_labels;
1372 label_index++)
1373 json_object_array_add(
1374 json_labels,
1375 json_object_new_int(
1376 nexthop->nh_label->label
1377 [label_index]));
1378
1379 json_object_object_add(json_nexthop, "labels",
1380 json_labels);
1381 }
1382
1383 json_object_array_add(json_nexthops, json_nexthop);
1384 }
1385
1386 json_object_object_add(json_route, "nexthops", json_nexthops);
1387 json_object_array_add(json, json_route);
1388 return;
1389 }
1390
1391 /* Nexthop information. */
7ee30f28
DS
1392 for (ALL_NEXTHOPS(re->ng, nexthop)) {
1393 if (nexthop == re->ng.nexthop) {
d62a17ae 1394 /* Prefix information. */
1395 len = vty_out(vty, "%c", zebra_route_char(re->type));
1396 if (re->instance)
1397 len += vty_out(vty, "[%d]", re->instance);
1398 len += vty_out(
1399 vty, "%c%c %s",
1400 CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED)
1401 ? '>'
1402 : ' ',
1403 CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)
1404 ? '*'
1405 : ' ',
1406 srcdest_rnode2str(rn, buf, sizeof buf));
1407
1408 /* Distance and metric display. */
925c2f88 1409 if (re->type != ZEBRA_ROUTE_CONNECT)
8526b842 1410 len += vty_out(vty, " [%u/%u]", re->distance,
d62a17ae 1411 re->metric);
eaf5150f 1412 } else {
d62a17ae 1413 vty_out(vty, " %c%*c",
1414 CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)
996c9314
LB
1415 ? CHECK_FLAG(nexthop->flags,
1416 NEXTHOP_FLAG_DUPLICATE)
1417 ? ' '
1418 : '*'
d62a17ae 1419 : ' ',
1420 len - 3 + (2 * nexthop_level(nexthop)), ' ');
eaf5150f 1421 }
d62a17ae 1422
1423 switch (nexthop->type) {
1424 case NEXTHOP_TYPE_IPV4:
1425 case NEXTHOP_TYPE_IPV4_IFINDEX:
1426 vty_out(vty, " via %s", inet_ntoa(nexthop->gate.ipv4));
1427 if (nexthop->ifindex)
1428 vty_out(vty, ", %s",
1429 ifindex2ifname(nexthop->ifindex,
4a7371e9 1430 nexthop->vrf_id));
d62a17ae 1431 break;
1432 case NEXTHOP_TYPE_IPV6:
1433 case NEXTHOP_TYPE_IPV6_IFINDEX:
1434 vty_out(vty, " via %s",
1435 inet_ntop(AF_INET6, &nexthop->gate.ipv6, buf,
1436 sizeof buf));
1437 if (nexthop->ifindex)
1438 vty_out(vty, ", %s",
1439 ifindex2ifname(nexthop->ifindex,
4a7371e9 1440 nexthop->vrf_id));
d62a17ae 1441 break;
1442
1443 case NEXTHOP_TYPE_IFINDEX:
1444 vty_out(vty, " is directly connected, %s",
99b9d960 1445 ifindex2ifname(nexthop->ifindex,
4a7371e9 1446 nexthop->vrf_id));
d62a17ae 1447 break;
1448 case NEXTHOP_TYPE_BLACKHOLE:
a8309422
DL
1449 vty_out(vty, " unreachable");
1450 switch (nexthop->bh_type) {
1451 case BLACKHOLE_REJECT:
1452 vty_out(vty, " (ICMP unreachable)");
1453 break;
1454 case BLACKHOLE_ADMINPROHIB:
1455 vty_out(vty, " (ICMP admin-prohibited)");
1456 break;
1457 case BLACKHOLE_NULL:
1458 vty_out(vty, " (blackhole)");
1459 break;
1460 case BLACKHOLE_UNSPEC:
1461 break;
1462 }
d62a17ae 1463 break;
1464 default:
1465 break;
1466 }
2793a098 1467
4a7371e9
DS
1468 if (nexthop->vrf_id != re->vrf_id) {
1469 struct vrf *vrf = vrf_lookup_by_id(nexthop->vrf_id);
2793a098
DS
1470
1471 vty_out(vty, "(vrf %s)", vrf->name);
1472 }
1473
d62a17ae 1474 if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
1475 vty_out(vty, " inactive");
1476
1477 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK))
1478 vty_out(vty, " onlink");
1479
1480 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
1481 vty_out(vty, " (recursive)");
1482
1483 switch (nexthop->type) {
1484 case NEXTHOP_TYPE_IPV4:
1485 case NEXTHOP_TYPE_IPV4_IFINDEX:
1486 if (nexthop->src.ipv4.s_addr) {
1487 if (inet_ntop(AF_INET, &nexthop->src.ipv4, buf,
1488 sizeof buf))
1489 vty_out(vty, ", src %s", buf);
1490 }
1491 break;
1492 case NEXTHOP_TYPE_IPV6:
1493 case NEXTHOP_TYPE_IPV6_IFINDEX:
1494 if (!IPV6_ADDR_SAME(&nexthop->src.ipv6, &in6addr_any)) {
1495 if (inet_ntop(AF_INET6, &nexthop->src.ipv6, buf,
1496 sizeof buf))
1497 vty_out(vty, ", src %s", buf);
1498 }
1499 break;
1500 default:
1501 break;
1502 }
1503
1504 /* Label information */
1505 if (nexthop->nh_label && nexthop->nh_label->num_labels) {
1506 vty_out(vty, ", label %s",
1507 mpls_label2str(nexthop->nh_label->num_labels,
1508 nexthop->nh_label->label, buf,
1509 sizeof buf, 1));
1510 }
1511
14a481d9
DS
1512 if (uptime < ONE_DAY_SECOND)
1513 vty_out(vty, ", %02d:%02d:%02d", tm->tm_hour,
1514 tm->tm_min, tm->tm_sec);
1515 else if (uptime < ONE_WEEK_SECOND)
1516 vty_out(vty, ", %dd%02dh%02dm", tm->tm_yday,
1517 tm->tm_hour, tm->tm_min);
1518 else
1519 vty_out(vty, ", %02dw%dd%02dh", tm->tm_yday / 7,
1520 tm->tm_yday - ((tm->tm_yday / 7) * 7),
1521 tm->tm_hour);
d62a17ae 1522 vty_out(vty, "\n");
1523 }
1524}
1525
ae825b8b
DS
1526static void do_show_route_helper(struct vty *vty, struct zebra_vrf *zvrf,
1527 struct route_table *table, afi_t afi,
1528 bool use_fib, route_tag_t tag,
1529 const struct prefix *longer_prefix_p,
1530 bool supernets_only, int type,
1531 u_short ospf_instance_id, u_char use_json)
d62a17ae 1532{
d62a17ae 1533 struct route_node *rn;
1534 struct route_entry *re;
1535 int first = 1;
ae825b8b 1536 rib_dest_t *dest;
d62a17ae 1537 json_object *json = NULL;
1538 json_object *json_prefix = NULL;
ae825b8b
DS
1539 uint32_t addr;
1540 char buf[BUFSIZ];
d62a17ae 1541
1542 if (use_json)
1543 json = json_object_new_object();
1544
1545 /* Show all routes. */
1546 for (rn = route_top(table); rn; rn = route_next(rn)) {
5f7a4718
DS
1547 dest = rib_dest_from_rnode(rn);
1548
a2addae8 1549 RNODE_FOREACH_RE (rn, re) {
996c9314 1550 if (use_fib && re != dest->selected_fib)
d62a17ae 1551 continue;
1552
1553 if (tag && re->tag != tag)
1554 continue;
1555
1556 if (longer_prefix_p
1557 && !prefix_match(longer_prefix_p, &rn->p))
1558 continue;
1559
1560 /* This can only be true when the afi is IPv4 */
1561 if (supernets_only) {
1562 addr = ntohl(rn->p.u.prefix4.s_addr);
1563
1564 if (IN_CLASSC(addr) && rn->p.prefixlen >= 24)
1565 continue;
1566
1567 if (IN_CLASSB(addr) && rn->p.prefixlen >= 16)
1568 continue;
1569
1570 if (IN_CLASSA(addr) && rn->p.prefixlen >= 8)
1571 continue;
1572 }
1573
1574 if (type && re->type != type)
1575 continue;
1576
1577 if (ospf_instance_id
1578 && (re->type != ZEBRA_ROUTE_OSPF
1579 || re->instance != ospf_instance_id))
1580 continue;
1581
1582 if (use_json) {
1583 if (!json_prefix)
1584 json_prefix = json_object_new_array();
1585 } else {
1586 if (first) {
1587 if (afi == AFI_IP)
1588 vty_out(vty,
1589 SHOW_ROUTE_V4_HEADER);
1590 else
1591 vty_out(vty,
1592 SHOW_ROUTE_V6_HEADER);
1593
1594 if (zvrf_id(zvrf) != VRF_DEFAULT)
1595 vty_out(vty, "\nVRF %s:\n",
1596 zvrf_name(zvrf));
1597
1598 first = 0;
1599 }
1600 }
1601
1602 vty_show_ip_route(vty, rn, re, json_prefix);
1603 }
1604
1605 if (json_prefix) {
1606 prefix2str(&rn->p, buf, sizeof buf);
1607 json_object_object_add(json, buf, json_prefix);
1608 json_prefix = NULL;
1609 }
1610 }
1611
1612 if (use_json) {
9d303b37
DL
1613 vty_out(vty, "%s\n", json_object_to_json_string_ext(
1614 json, JSON_C_TO_STRING_PRETTY));
d62a17ae 1615 json_object_free(json);
1616 }
ae825b8b
DS
1617}
1618
1619static int do_show_ip_route(struct vty *vty, const char *vrf_name, afi_t afi,
1620 safi_t safi, bool use_fib, u_char use_json,
1621 route_tag_t tag,
1622 const struct prefix *longer_prefix_p,
1623 bool supernets_only, int type,
1624 u_short ospf_instance_id)
1625{
1626 struct route_table *table;
1627 struct zebra_vrf *zvrf = NULL;
1628
1629 if (!(zvrf = zebra_vrf_lookup_by_name(vrf_name))) {
1630 if (use_json)
1631 vty_out(vty, "{}\n");
1632 else
1633 vty_out(vty, "vrf %s not defined\n", vrf_name);
1634 return CMD_SUCCESS;
1635 }
1636
1637 if (zvrf_id(zvrf) == VRF_UNKNOWN) {
1638 if (use_json)
1639 vty_out(vty, "{}\n");
1640 else
1641 vty_out(vty, "vrf %s inactive\n", vrf_name);
1642 return CMD_SUCCESS;
1643 }
1644
1645 table = zebra_vrf_table(afi, safi, zvrf_id(zvrf));
1646 if (!table) {
1647 if (use_json)
1648 vty_out(vty, "{}\n");
1649 return CMD_SUCCESS;
1650 }
1651
1652 do_show_route_helper(vty, zvrf, table, afi, use_fib, tag,
1653 longer_prefix_p, supernets_only, type,
1654 ospf_instance_id, use_json);
1655
1656 return CMD_SUCCESS;
1657}
1658
1659DEFPY (show_route_table,
1660 show_route_table_cmd,
1661 "show <ip$ipv4|ipv6$ipv6> route table (1-4294967295)$table [json$json]",
1662 SHOW_STR
1663 IP_STR
1664 IP6_STR
1665 "IP routing table\n"
1666 "Table to display\n"
1667 "The table number to display, if available\n"
1668 JSON_STR)
1669{
1670 afi_t afi = ipv4 ? AFI_IP : AFI_IP6;
1671 struct zebra_vrf *zvrf = zebra_vrf_lookup_by_id(VRF_DEFAULT);
1672 struct route_table *t;
1673
1674 t = zebra_ns_find_table(zvrf->zns, table, afi);
1675 if (t)
1676 do_show_route_helper(vty, zvrf, t, afi, false, 0, false, false,
1677 0, 0, !!json);
d62a17ae 1678
1679 return CMD_SUCCESS;
abbda2d4 1680}
d511d7f1 1681
8f527c5e
FL
1682DEFUN (show_ip_nht,
1683 show_ip_nht_cmd,
9bf96c84 1684 "show ip nht [vrf NAME]",
8f527c5e
FL
1685 SHOW_STR
1686 IP_STR
9bf96c84
DW
1687 "IP nexthop tracking table\n"
1688 VRF_CMD_HELP_STR)
8f527c5e 1689{
d62a17ae 1690 int idx_vrf = 4;
1691 vrf_id_t vrf_id = VRF_DEFAULT;
12f6fb97 1692
d62a17ae 1693 if (argc == 5)
1694 VRF_GET_ID(vrf_id, argv[idx_vrf]->arg);
12f6fb97 1695
d62a17ae 1696 zebra_print_rnh_table(vrf_id, AF_INET, vty, RNH_NEXTHOP_TYPE);
1697 return CMD_SUCCESS;
8f527c5e
FL
1698}
1699
12f6fb97 1700
d511d7f1
DS
1701DEFUN (show_ip_nht_vrf_all,
1702 show_ip_nht_vrf_all_cmd,
5bebf568 1703 "show ip nht vrf all",
d511d7f1
DS
1704 SHOW_STR
1705 IP_STR
1706 "IP nexthop tracking table\n"
1707 VRF_ALL_CMD_HELP_STR)
1708{
d62a17ae 1709 struct vrf *vrf;
1710 struct zebra_vrf *zvrf;
d511d7f1 1711
a2addae8
RW
1712 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name)
1713 if ((zvrf = vrf->info) != NULL) {
1714 vty_out(vty, "\nVRF %s:\n", zvrf_name(zvrf));
1715 zebra_print_rnh_table(zvrf_id(zvrf), AF_INET, vty,
1716 RNH_NEXTHOP_TYPE);
1717 }
d511d7f1 1718
d62a17ae 1719 return CMD_SUCCESS;
d511d7f1
DS
1720}
1721
8f527c5e
FL
1722DEFUN (show_ipv6_nht,
1723 show_ipv6_nht_cmd,
9bf96c84 1724 "show ipv6 nht [vrf NAME]",
8f527c5e 1725 SHOW_STR
689e6694 1726 IPV6_STR
9bf96c84
DW
1727 "IPv6 nexthop tracking table\n"
1728 VRF_CMD_HELP_STR)
8f527c5e 1729{
d62a17ae 1730 int idx_vrf = 4;
1731 vrf_id_t vrf_id = VRF_DEFAULT;
12f6fb97 1732
d62a17ae 1733 if (argc == 5)
1734 VRF_GET_ID(vrf_id, argv[idx_vrf]->arg);
12f6fb97 1735
d62a17ae 1736 zebra_print_rnh_table(vrf_id, AF_INET6, vty, RNH_NEXTHOP_TYPE);
1737 return CMD_SUCCESS;
8f527c5e
FL
1738}
1739
12f6fb97 1740
d511d7f1
DS
1741DEFUN (show_ipv6_nht_vrf_all,
1742 show_ipv6_nht_vrf_all_cmd,
5bebf568 1743 "show ipv6 nht vrf all",
d511d7f1
DS
1744 SHOW_STR
1745 IP_STR
1746 "IPv6 nexthop tracking table\n"
1747 VRF_ALL_CMD_HELP_STR)
1748{
d62a17ae 1749 struct vrf *vrf;
1750 struct zebra_vrf *zvrf;
d511d7f1 1751
a2addae8
RW
1752 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name)
1753 if ((zvrf = vrf->info) != NULL) {
1754 vty_out(vty, "\nVRF %s:\n", zvrf_name(zvrf));
1755 zebra_print_rnh_table(zvrf_id(zvrf), AF_INET6, vty,
1756 RNH_NEXTHOP_TYPE);
1757 }
d511d7f1 1758
d62a17ae 1759 return CMD_SUCCESS;
d511d7f1
DS
1760}
1761
8f527c5e
FL
1762DEFUN (ip_nht_default_route,
1763 ip_nht_default_route_cmd,
1764 "ip nht resolve-via-default",
1765 IP_STR
1766 "Filter Next Hop tracking route resolution\n"
1767 "Resolve via default route\n")
1768{
d62a17ae 1769 if (zebra_rnh_ip_default_route)
1770 return CMD_SUCCESS;
8f527c5e 1771
d62a17ae 1772 zebra_rnh_ip_default_route = 1;
90ac32c2 1773 zebra_evaluate_rnh(VRF_DEFAULT, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL);
d62a17ae 1774 return CMD_SUCCESS;
8f527c5e
FL
1775}
1776
1777DEFUN (no_ip_nht_default_route,
1778 no_ip_nht_default_route_cmd,
1779 "no ip nht resolve-via-default",
1780 NO_STR
1781 IP_STR
1782 "Filter Next Hop tracking route resolution\n"
1783 "Resolve via default route\n")
1784{
d62a17ae 1785 if (!zebra_rnh_ip_default_route)
1786 return CMD_SUCCESS;
8f527c5e 1787
d62a17ae 1788 zebra_rnh_ip_default_route = 0;
90ac32c2 1789 zebra_evaluate_rnh(VRF_DEFAULT, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL);
d62a17ae 1790 return CMD_SUCCESS;
8f527c5e
FL
1791}
1792
1793DEFUN (ipv6_nht_default_route,
1794 ipv6_nht_default_route_cmd,
1795 "ipv6 nht resolve-via-default",
1796 IP6_STR
1797 "Filter Next Hop tracking route resolution\n"
1798 "Resolve via default route\n")
1799{
d62a17ae 1800 if (zebra_rnh_ipv6_default_route)
1801 return CMD_SUCCESS;
8f527c5e 1802
d62a17ae 1803 zebra_rnh_ipv6_default_route = 1;
90ac32c2 1804 zebra_evaluate_rnh(VRF_DEFAULT, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL);
d62a17ae 1805 return CMD_SUCCESS;
8f527c5e
FL
1806}
1807
1808DEFUN (no_ipv6_nht_default_route,
1809 no_ipv6_nht_default_route_cmd,
1810 "no ipv6 nht resolve-via-default",
1811 NO_STR
1812 IP6_STR
1813 "Filter Next Hop tracking route resolution\n"
1814 "Resolve via default route\n")
1815{
d62a17ae 1816 if (!zebra_rnh_ipv6_default_route)
1817 return CMD_SUCCESS;
8f527c5e 1818
d62a17ae 1819 zebra_rnh_ipv6_default_route = 0;
90ac32c2 1820 zebra_evaluate_rnh(VRF_DEFAULT, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL);
d62a17ae 1821 return CMD_SUCCESS;
8f527c5e
FL
1822}
1823
ecffa493
RW
1824DEFPY (show_route,
1825 show_route_cmd,
1826 "show\
1827 <\
1828 ip$ipv4 <fib$fib|route> [vrf <NAME$vrf_name|all$vrf_all>]\
a3e13ef3 1829 [{\
ecffa493
RW
1830 tag (1-4294967295)\
1831 |A.B.C.D/M$prefix longer-prefixes\
1832 |supernets-only$supernets_only\
a3e13ef3
RW
1833 }]\
1834 [<\
1835 " FRR_IP_REDIST_STR_ZEBRA "$type_str\
ecffa493 1836 |ospf$type_str (1-65535)$ospf_instance_id\
a3e13ef3 1837 >]\
ecffa493 1838 |ipv6$ipv6 <fib$fib|route> [vrf <NAME$vrf_name|all$vrf_all>]\
a3e13ef3 1839 [{\
ecffa493
RW
1840 tag (1-4294967295)\
1841 |X:X::X:X/M$prefix longer-prefixes\
a3e13ef3
RW
1842 }]\
1843 [" FRR_IP6_REDIST_STR_ZEBRA "$type_str]\
ecffa493
RW
1844 >\
1845 [json$json]",
8f527c5e
FL
1846 SHOW_STR
1847 IP_STR
87a88962 1848 "IP forwarding table\n"
8f527c5e 1849 "IP routing table\n"
ecffa493 1850 VRF_FULL_CMD_HELP_STR
8f527c5e 1851 "Show only routes with tag\n"
acb25e73
DW
1852 "Tag value\n"
1853 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
1854 "Show route matching the specified Network/Mask pair only\n"
1855 "Show supernet entries only\n"
1856 FRR_IP_REDIST_HELP_STR_ZEBRA
1857 "Open Shortest Path First (OSPFv2)\n"
1858 "Instance ID\n"
ecffa493
RW
1859 IPV6_STR
1860 "IP forwarding table\n"
1861 "IP routing table\n"
1862 VRF_FULL_CMD_HELP_STR
1863 "Show only routes with tag\n"
1864 "Tag value\n"
1865 "IPv6 prefix\n"
1866 "Show route matching the specified Network/Mask pair only\n"
1867 FRR_IP6_REDIST_HELP_STR_ZEBRA
acb25e73 1868 JSON_STR)
8f527c5e 1869{
ecffa493 1870 afi_t afi = ipv4 ? AFI_IP : AFI_IP6;
d62a17ae 1871 struct vrf *vrf;
d62a17ae 1872 int type = 0;
d62a17ae 1873
ecffa493
RW
1874 if (type_str) {
1875 type = proto_redistnum(afi, type_str);
d62a17ae 1876 if (type < 0) {
1877 vty_out(vty, "Unknown route type\n");
1878 return CMD_WARNING;
1879 }
1880 }
1881
1882 if (vrf_all) {
a2addae8 1883 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
ecffa493
RW
1884 struct zebra_vrf *zvrf;
1885 struct route_table *table;
1886
d62a17ae 1887 if ((zvrf = vrf->info) == NULL
ecffa493 1888 || (table = zvrf->table[afi][SAFI_UNICAST]) == NULL)
d62a17ae 1889 continue;
1890
1891 do_show_ip_route(
ecffa493
RW
1892 vty, zvrf_name(zvrf), afi, SAFI_UNICAST, !!fib,
1893 !!json, tag, prefix_str ? prefix : NULL,
1894 !!supernets_only, type, ospf_instance_id);
d62a17ae 1895 }
1896 } else {
ecffa493
RW
1897 vrf_id_t vrf_id = VRF_DEFAULT;
1898
1899 if (vrf_name)
1900 VRF_GET_ID(vrf_id, vrf_name);
d62a17ae 1901 vrf = vrf_lookup_by_id(vrf_id);
ecffa493
RW
1902 do_show_ip_route(vty, vrf->name, afi, SAFI_UNICAST, !!fib,
1903 !!json, tag, prefix_str ? prefix : NULL,
1904 !!supernets_only, type, ospf_instance_id);
d62a17ae 1905 }
ecffa493 1906
d62a17ae 1907 return CMD_SUCCESS;
8f527c5e
FL
1908}
1909
5ce91022
RW
1910DEFPY (show_route_detail,
1911 show_route_detail_cmd,
1912 "show\
1913 <\
1914 ip$ipv4 route [vrf <NAME$vrf_name|all$vrf_all>]\
1915 <\
1916 A.B.C.D$address\
1917 |A.B.C.D/M$prefix\
1918 >\
1919 |ipv6$ipv6 route [vrf <NAME$vrf_name|all$vrf_all>]\
1920 <\
1921 X:X::X:X$address\
1922 |X:X::X:X/M$prefix\
1923 >\
1924 >",
8f527c5e
FL
1925 SHOW_STR
1926 IP_STR
1927 "IP routing table\n"
5ce91022
RW
1928 VRF_FULL_CMD_HELP_STR
1929 "Network in the IP routing table to display\n"
1930 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
1931 IP6_STR
1932 "IP routing table\n"
1933 VRF_FULL_CMD_HELP_STR
1934 "IPv6 Address\n"
1935 "IPv6 prefix\n")
8f527c5e 1936{
5ce91022 1937 afi_t afi = ipv4 ? AFI_IP : AFI_IP6;
d62a17ae 1938 struct route_table *table;
5ce91022 1939 struct prefix p;
d62a17ae 1940 struct route_node *rn;
d511d7f1 1941
5ce91022
RW
1942 if (address_str)
1943 prefix_str = address_str;
1944 if (str2prefix(prefix_str, &p) < 0) {
1945 vty_out(vty, "%% Malformed address\n");
d62a17ae 1946 return CMD_WARNING;
1947 }
8f527c5e 1948
5ce91022
RW
1949 if (vrf_all) {
1950 struct vrf *vrf;
1951 struct zebra_vrf *zvrf;
8f527c5e 1952
996c9314 1953 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
5ce91022
RW
1954 if ((zvrf = vrf->info) == NULL
1955 || (table = zvrf->table[afi][SAFI_UNICAST]) == NULL)
1956 continue;
1957
1958 rn = route_node_match(table, &p);
1959 if (!rn)
1960 continue;
1961 if (!address_str && rn->p.prefixlen != p.prefixlen) {
1962 route_unlock_node(rn);
1963 continue;
1964 }
1965
1966 vty_show_ip_route_detail(vty, rn, 0);
1967
1968 route_unlock_node(rn);
1969 }
1970 } else {
1971 vrf_id_t vrf_id = VRF_DEFAULT;
1972
1973 if (vrf_name)
1974 VRF_GET_ID(vrf_id, vrf_name);
1975
1976 table = zebra_vrf_table(afi, SAFI_UNICAST, vrf_id);
1977 if (!table)
1978 return CMD_SUCCESS;
8f527c5e 1979
5ce91022
RW
1980 rn = route_node_match(table, &p);
1981 if (!rn) {
1982 vty_out(vty, "%% Network not in table\n");
1983 return CMD_WARNING;
1984 }
1985 if (!address_str && rn->p.prefixlen != p.prefixlen) {
1986 vty_out(vty, "%% Network not in table\n");
1987 route_unlock_node(rn);
1988 return CMD_WARNING;
1989 }
8f527c5e 1990
5ce91022
RW
1991 vty_show_ip_route_detail(vty, rn, 0);
1992
1993 route_unlock_node(rn);
1994 }
8f527c5e 1995
d62a17ae 1996 return CMD_SUCCESS;
8f527c5e
FL
1997}
1998
5ce91022
RW
1999DEFPY (show_route_summary,
2000 show_route_summary_cmd,
2001 "show\
2002 <\
2003 ip$ipv4 route [vrf <NAME$vrf_name|all$vrf_all>]\
2004 summary [prefix$prefix]\
2005 |ipv6$ipv6 route [vrf <NAME$vrf_name|all$vrf_all>]\
2006 summary [prefix$prefix]\
2007 >",
8f527c5e
FL
2008 SHOW_STR
2009 IP_STR
2010 "IP routing table\n"
5ce91022
RW
2011 VRF_FULL_CMD_HELP_STR
2012 "Summary of all routes\n"
2013 "Prefix routes\n"
2014 IP6_STR
2015 "IP routing table\n"
2016 VRF_FULL_CMD_HELP_STR
2017 "Summary of all routes\n"
2018 "Prefix routes\n")
8f527c5e 2019{
5ce91022 2020 afi_t afi = ipv4 ? AFI_IP : AFI_IP6;
d62a17ae 2021 struct route_table *table;
d62a17ae 2022
5ce91022
RW
2023 if (vrf_all) {
2024 struct vrf *vrf;
2025 struct zebra_vrf *zvrf;
d511d7f1 2026
996c9314 2027 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
5ce91022
RW
2028 if ((zvrf = vrf->info) == NULL
2029 || (table = zvrf->table[afi][SAFI_UNICAST]) == NULL)
2030 continue;
8f527c5e 2031
5ce91022
RW
2032 if (prefix)
2033 vty_show_ip_route_summary_prefix(vty, table);
2034 else
2035 vty_show_ip_route_summary(vty, table);
2036 }
2037 } else {
2038 vrf_id_t vrf_id = VRF_DEFAULT;
8f527c5e 2039
5ce91022
RW
2040 if (vrf_name)
2041 VRF_GET_ID(vrf_id, vrf_name);
8f527c5e 2042
5ce91022
RW
2043 table = zebra_vrf_table(afi, SAFI_UNICAST, vrf_id);
2044 if (!table)
2045 return CMD_SUCCESS;
8f527c5e 2046
5ce91022
RW
2047 if (prefix)
2048 vty_show_ip_route_summary_prefix(vty, table);
2049 else
2050 vty_show_ip_route_summary(vty, table);
2051 }
8f527c5e 2052
d62a17ae 2053 return CMD_SUCCESS;
8f527c5e
FL
2054}
2055
d62a17ae 2056static void vty_show_ip_route_summary(struct vty *vty,
2057 struct route_table *table)
8f527c5e 2058{
d62a17ae 2059 struct route_node *rn;
2060 struct route_entry *re;
8f527c5e
FL
2061#define ZEBRA_ROUTE_IBGP ZEBRA_ROUTE_MAX
2062#define ZEBRA_ROUTE_TOTAL (ZEBRA_ROUTE_IBGP + 1)
d62a17ae 2063 u_int32_t rib_cnt[ZEBRA_ROUTE_TOTAL + 1];
2064 u_int32_t fib_cnt[ZEBRA_ROUTE_TOTAL + 1];
2065 u_int32_t i;
2066 u_int32_t is_ibgp;
2067
2068 memset(&rib_cnt, 0, sizeof(rib_cnt));
2069 memset(&fib_cnt, 0, sizeof(fib_cnt));
2070 for (rn = route_top(table); rn; rn = srcdest_route_next(rn))
a2addae8 2071 RNODE_FOREACH_RE (rn, re) {
d62a17ae 2072 is_ibgp = (re->type == ZEBRA_ROUTE_BGP
2073 && CHECK_FLAG(re->flags, ZEBRA_FLAG_IBGP));
2074
2075 rib_cnt[ZEBRA_ROUTE_TOTAL]++;
2076 if (is_ibgp)
2077 rib_cnt[ZEBRA_ROUTE_IBGP]++;
2078 else
2079 rib_cnt[re->type]++;
2080
2081 if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED)) {
2082 fib_cnt[ZEBRA_ROUTE_TOTAL]++;
2083
2084 if (is_ibgp)
2085 fib_cnt[ZEBRA_ROUTE_IBGP]++;
2086 else
2087 fib_cnt[re->type]++;
2088 }
2089 }
2090
2091 vty_out(vty, "%-20s %-20s %s (vrf %s)\n", "Route Source", "Routes",
2092 "FIB", zvrf_name(((rib_table_info_t *)table->info)->zvrf));
2093
2094 for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
9d303b37
DL
2095 if ((rib_cnt[i] > 0) || (i == ZEBRA_ROUTE_BGP
2096 && rib_cnt[ZEBRA_ROUTE_IBGP] > 0)) {
d62a17ae 2097 if (i == ZEBRA_ROUTE_BGP) {
2098 vty_out(vty, "%-20s %-20d %-20d \n", "ebgp",
2099 rib_cnt[ZEBRA_ROUTE_BGP],
2100 fib_cnt[ZEBRA_ROUTE_BGP]);
2101 vty_out(vty, "%-20s %-20d %-20d \n", "ibgp",
2102 rib_cnt[ZEBRA_ROUTE_IBGP],
2103 fib_cnt[ZEBRA_ROUTE_IBGP]);
2104 } else
2105 vty_out(vty, "%-20s %-20d %-20d \n",
2106 zebra_route_string(i), rib_cnt[i],
2107 fib_cnt[i]);
2108 }
2109 }
2110
2111 vty_out(vty, "------\n");
2112 vty_out(vty, "%-20s %-20d %-20d \n", "Totals",
2113 rib_cnt[ZEBRA_ROUTE_TOTAL], fib_cnt[ZEBRA_ROUTE_TOTAL]);
2114 vty_out(vty, "\n");
8f527c5e
FL
2115}
2116
2117/*
2118 * Implementation of the ip route summary prefix command.
2119 *
2120 * This command prints the primary prefixes that have been installed by various
2121 * protocols on the box.
2122 *
2123 */
d62a17ae 2124static void vty_show_ip_route_summary_prefix(struct vty *vty,
2125 struct route_table *table)
8f527c5e 2126{
d62a17ae 2127 struct route_node *rn;
2128 struct route_entry *re;
2129 struct nexthop *nexthop;
8f527c5e
FL
2130#define ZEBRA_ROUTE_IBGP ZEBRA_ROUTE_MAX
2131#define ZEBRA_ROUTE_TOTAL (ZEBRA_ROUTE_IBGP + 1)
d62a17ae 2132 u_int32_t rib_cnt[ZEBRA_ROUTE_TOTAL + 1];
2133 u_int32_t fib_cnt[ZEBRA_ROUTE_TOTAL + 1];
2134 u_int32_t i;
2135 int cnt;
2136
2137 memset(&rib_cnt, 0, sizeof(rib_cnt));
2138 memset(&fib_cnt, 0, sizeof(fib_cnt));
2139 for (rn = route_top(table); rn; rn = srcdest_route_next(rn))
a2addae8 2140 RNODE_FOREACH_RE (rn, re) {
d62a17ae 2141
2142 /*
2143 * In case of ECMP, count only once.
2144 */
2145 cnt = 0;
7ee30f28 2146 for (nexthop = re->ng.nexthop; (!cnt && nexthop);
d62a17ae 2147 nexthop = nexthop->next) {
2148 cnt++;
2149 rib_cnt[ZEBRA_ROUTE_TOTAL]++;
2150 rib_cnt[re->type]++;
2151 if (CHECK_FLAG(nexthop->flags,
2152 NEXTHOP_FLAG_FIB)) {
2153 fib_cnt[ZEBRA_ROUTE_TOTAL]++;
2154 fib_cnt[re->type]++;
2155 }
2156 if (re->type == ZEBRA_ROUTE_BGP
2157 && CHECK_FLAG(re->flags, ZEBRA_FLAG_IBGP)) {
2158 rib_cnt[ZEBRA_ROUTE_IBGP]++;
2159 if (CHECK_FLAG(nexthop->flags,
2160 NEXTHOP_FLAG_FIB))
2161 fib_cnt[ZEBRA_ROUTE_IBGP]++;
2162 }
2163 }
2164 }
2165
2166 vty_out(vty, "%-20s %-20s %s (vrf %s)\n", "Route Source",
2167 "Prefix Routes", "FIB",
2168 zvrf_name(((rib_table_info_t *)table->info)->zvrf));
2169
2170 for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
2171 if (rib_cnt[i] > 0) {
2172 if (i == ZEBRA_ROUTE_BGP) {
2173 vty_out(vty, "%-20s %-20d %-20d \n", "ebgp",
2174 rib_cnt[ZEBRA_ROUTE_BGP]
2175 - rib_cnt[ZEBRA_ROUTE_IBGP],
2176 fib_cnt[ZEBRA_ROUTE_BGP]
2177 - fib_cnt[ZEBRA_ROUTE_IBGP]);
2178 vty_out(vty, "%-20s %-20d %-20d \n", "ibgp",
2179 rib_cnt[ZEBRA_ROUTE_IBGP],
2180 fib_cnt[ZEBRA_ROUTE_IBGP]);
2181 } else
2182 vty_out(vty, "%-20s %-20d %-20d \n",
2183 zebra_route_string(i), rib_cnt[i],
2184 fib_cnt[i]);
2185 }
2186 }
2187
2188 vty_out(vty, "------\n");
2189 vty_out(vty, "%-20s %-20d %-20d \n", "Totals",
2190 rib_cnt[ZEBRA_ROUTE_TOTAL], fib_cnt[ZEBRA_ROUTE_TOTAL]);
2191 vty_out(vty, "\n");
9343ce83
DS
2192}
2193
9de498ec 2194/* Write static route configuration. */
996c9314
LB
2195int static_config(struct vty *vty, struct zebra_vrf *zvrf, afi_t afi,
2196 safi_t safi, const char *cmd)
d62a17ae 2197{
4060008b
DS
2198 struct static_hold_route *shr;
2199 struct listnode *node;
37728041 2200 char spacing[100];
d62a17ae 2201 struct route_node *rn;
2202 struct static_route *si;
2203 struct route_table *stable;
d62a17ae 2204 char buf[SRCDEST2STR_BUFFER];
2205 int write = 0;
2206
37728041
DS
2207 if ((stable = zvrf->stable[afi][safi]) == NULL)
2208 return write;
d62a17ae 2209
996c9314 2210 sprintf(spacing, "%s%s", (zvrf->vrf->vrf_id == VRF_DEFAULT) ? "" : " ",
37728041 2211 cmd);
d62a17ae 2212
4060008b
DS
2213 /*
2214 * Static routes for vrfs not fully inited
2215 */
2216 for (ALL_LIST_ELEMENTS_RO(static_list, node, shr)) {
2217 if (shr->afi != afi || shr->safi != safi)
2218 continue;
2219
2220 if (strcmp(zvrf->vrf->name, shr->vrf_name) != 0)
2221 continue;
2222
2223 vty_out(vty, "%s ", spacing);
2224 if (shr->dest_str)
2225 vty_out(vty, "%s ", shr->dest_str);
2226 if (shr->mask_str)
2227 vty_out(vty, "%s ", shr->mask_str);
2228 if (shr->src_str)
2229 vty_out(vty, "from %s ", shr->src_str);
2230 if (shr->gate_str)
2231 vty_out(vty, "%s ", shr->gate_str);
2232 if (shr->ifname)
2233 vty_out(vty, "%s ", shr->ifname);
2234 if (shr->flag_str)
2235 vty_out(vty, "%s ", shr->flag_str);
2236 if (shr->tag_str)
be627102 2237 vty_out(vty, "tag %s ", shr->tag_str);
4060008b
DS
2238 if (shr->distance_str)
2239 vty_out(vty, "%s ", shr->distance_str);
2240 if (shr->label_str)
2241 vty_out(vty, "label %s ", shr->label_str);
2242 if (strcmp(shr->vrf_name, shr->nhvrf_name) != 0)
2243 vty_out(vty, "nexthop-vrf %s", shr->nhvrf_name);
2244 vty_out(vty, "\n");
2245 }
2246
37728041
DS
2247 for (rn = route_top(stable); rn; rn = srcdest_route_next(rn))
2248 for (si = rn->info; si; si = si->next) {
2249 vty_out(vty, "%s %s", spacing,
2250 srcdest_rnode2str(rn, buf, sizeof buf));
2251
2252 switch (si->type) {
2253 case STATIC_IPV4_GATEWAY:
996c9314 2254 vty_out(vty, " %s", inet_ntoa(si->addr.ipv4));
37728041
DS
2255 break;
2256 case STATIC_IPV6_GATEWAY:
2257 vty_out(vty, " %s",
996c9314 2258 inet_ntop(AF_INET6, &si->addr.ipv6, buf,
37728041
DS
2259 sizeof buf));
2260 break;
2261 case STATIC_IFNAME:
2262 vty_out(vty, " %s", si->ifname);
2263 break;
2264 case STATIC_BLACKHOLE:
2265 switch (si->bh_type) {
2266 case STATIC_BLACKHOLE_DROP:
2267 vty_out(vty, " blackhole");
d62a17ae 2268 break;
37728041
DS
2269 case STATIC_BLACKHOLE_NULL:
2270 vty_out(vty, " Null0");
599186ad 2271 break;
37728041
DS
2272 case STATIC_BLACKHOLE_REJECT:
2273 vty_out(vty, " reject");
d62a17ae 2274 break;
2275 }
37728041
DS
2276 break;
2277 case STATIC_IPV4_GATEWAY_IFNAME:
2278 vty_out(vty, " %s %s",
996c9314 2279 inet_ntop(AF_INET, &si->addr.ipv4, buf,
37728041
DS
2280 sizeof buf),
2281 si->ifname);
2282 break;
2283 case STATIC_IPV6_GATEWAY_IFNAME:
2284 vty_out(vty, " %s %s",
996c9314 2285 inet_ntop(AF_INET6, &si->addr.ipv6, buf,
37728041
DS
2286 sizeof buf),
2287 si->ifname);
2288 break;
2289 }
d62a17ae 2290
37728041 2291 if (si->tag)
996c9314 2292 vty_out(vty, " tag %" ROUTE_TAG_PRI, si->tag);
d62a17ae 2293
996c9314 2294 if (si->distance != ZEBRA_STATIC_DISTANCE_DEFAULT)
37728041 2295 vty_out(vty, " %d", si->distance);
d62a17ae 2296
37728041 2297 if (si->nh_vrf_id != si->vrf_id) {
90f86c0a 2298 vty_out(vty, " nexthop-vrf %s", si->nh_vrfname);
37728041 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
6a17b1a0 2412 zvrf = zebra_vty_get_unknown_vrf(vty, vrf);
2481e732 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
6a17b1a0 2506 zvrf = zebra_vty_get_unknown_vrf(vty, vrf);
2481e732 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}