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