]> git.proxmox.com Git - mirror_frr.git/blame - zebra/zebra_vty.c
zebra: Fix some memory leaks on shutdown
[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"
7758e3f3 32#include "mpls.h"
4a1ab8e4 33#include "routemap.h"
05737783 34#include "srcdest_table.h"
cec2e17d 35#include "vxlan.h"
718e3744 36
a1ac18c4 37#include "zebra/zserv.h"
7c551956 38#include "zebra/zebra_vrf.h"
7758e3f3 39#include "zebra/zebra_mpls.h"
fb018d25 40#include "zebra/zebra_rnh.h"
7a4bb9c5 41#include "zebra/redistribute.h"
6baf7bb8 42#include "zebra/zebra_routemap.h"
28f6dde8 43#include "zebra/zebra_static.h"
1d666fcb 44#include "lib/json.h"
cec2e17d 45#include "zebra/zebra_vxlan.h"
00685a85 46#include "zebra/zebra_vty_clippy.c"
6baf7bb8
DS
47
48extern int allow_delete;
a1ac18c4 49
d62a17ae 50static int do_show_ip_route(struct vty *vty, const char *vrf_name, afi_t afi,
51 safi_t safi, bool use_fib, u_char use_json,
52 route_tag_t tag, struct prefix *longer_prefix_p,
53 bool supernets_only, int type,
54 u_short ospf_instance_id);
55static void vty_show_ip_route_detail(struct vty *vty, struct route_node *rn,
56 int mcast);
b78a80d7 57
18a4ded2
DW
58#define ONE_DAY_SECOND 60*60*24
59#define ONE_WEEK_SECOND 60*60*24*7
60
cec2e17d 61/* VNI range as per RFC 7432 */
62#define CMD_VNI_RANGE "(1-16777215)"
63
b78a80d7 64/* General function for static route. */
1d3f0eff 65static int zebra_static_route(struct vty *vty, afi_t afi, safi_t safi,
00685a85 66 const char *negate, const char *dest_str,
1d3f0eff
RW
67 const char *mask_str, const char *src_str,
68 const char *gate_str, const char *ifname,
69 const char *flag_str, const char *tag_str,
70 const char *distance_str, const char *vrf_id_str,
71 const char *label_str)
d62a17ae 72{
73 int ret;
74 u_char distance;
1d3f0eff
RW
75 struct prefix p, src;
76 struct prefix_ipv6 *src_p = NULL;
77 union g_addr gate;
78 union g_addr *gatep = NULL;
d62a17ae 79 struct in_addr mask;
80 u_char flag = 0;
81 route_tag_t tag = 0;
1d3f0eff 82 struct zebra_vrf *zvrf;
d62a17ae 83 unsigned int ifindex = 0;
c6cef20b 84 u_char type;
d62a17ae 85 struct static_nh_label snh_label;
86
d62a17ae 87 ret = str2prefix(dest_str, &p);
88 if (ret <= 0) {
89 vty_out(vty, "%% Malformed address\n");
90 return CMD_WARNING_CONFIG_FAILED;
91 }
92
1d3f0eff
RW
93 switch (afi) {
94 case AFI_IP:
95 /* Cisco like mask notation. */
96 if (mask_str) {
97 ret = inet_aton(mask_str, &mask);
98 if (ret == 0) {
99 vty_out(vty, "%% Malformed address\n");
100 return CMD_WARNING_CONFIG_FAILED;
101 }
102 p.prefixlen = ip_masklen(mask);
103 }
104 break;
105 case AFI_IP6:
106 /* srcdest routing */
107 if (src_str) {
108 ret = str2prefix(src_str, &src);
109 if (ret <= 0 || src.family != AF_INET6) {
110 vty_out(vty, "%% Malformed source address\n");
111 return CMD_WARNING_CONFIG_FAILED;
112 }
113 src_p = (struct prefix_ipv6 *)&src;
d62a17ae 114 }
1d3f0eff
RW
115 break;
116 default:
117 break;
d62a17ae 118 }
119
120 /* Apply mask for given prefix. */
121 apply_mask(&p);
122
123 /* Administrative distance. */
124 if (distance_str)
125 distance = atoi(distance_str);
126 else
127 distance = ZEBRA_STATIC_DISTANCE_DEFAULT;
128
129 /* tag */
130 if (tag_str)
131 tag = strtoul(tag_str, NULL, 10);
132
133 /* VRF id */
134 zvrf = zebra_vrf_lookup_by_name(vrf_id_str);
135
136 if (!zvrf) {
137 vty_out(vty, "%% vrf %s is not defined\n", vrf_id_str);
138 return CMD_WARNING_CONFIG_FAILED;
139 }
140
141 /* Labels */
1d3f0eff 142 memset(&snh_label, 0, sizeof(struct static_nh_label));
d62a17ae 143 if (label_str) {
144 if (!mpls_enabled) {
145 vty_out(vty,
146 "%% MPLS not turned on in kernel, ignoring command\n");
147 return CMD_WARNING_CONFIG_FAILED;
148 }
149 int rc = mpls_str2label(label_str, &snh_label.num_labels,
150 snh_label.label);
151 if (rc < 0) {
152 switch (rc) {
153 case -1:
154 vty_out(vty, "%% Malformed label(s)\n");
155 break;
156 case -2:
157 vty_out(vty,
158 "%% Cannot use reserved label(s) (%d-%d)\n",
159 MPLS_MIN_RESERVED_LABEL,
160 MPLS_MAX_RESERVED_LABEL);
161 break;
162 case -3:
163 vty_out(vty,
164 "%% Too many labels. Enter %d or fewer\n",
165 MPLS_MAX_LABELS);
166 break;
167 }
168 return CMD_WARNING_CONFIG_FAILED;
169 }
170 }
171
172 /* Null0 static route. */
c6cef20b
RW
173 if ((ifname != NULL)
174 && (strncasecmp(ifname, "Null0", strlen(ifname)) == 0)) {
d62a17ae 175 if (flag_str) {
176 vty_out(vty, "%% can not have flag %s with Null0\n",
177 flag_str);
178 return CMD_WARNING_CONFIG_FAILED;
179 }
c6cef20b
RW
180 SET_FLAG(flag, ZEBRA_FLAG_BLACKHOLE);
181 ifname = NULL;
d62a17ae 182 }
183
184 /* Route flags */
185 if (flag_str) {
186 switch (flag_str[0]) {
187 case 'r':
188 case 'R': /* XXX */
189 SET_FLAG(flag, ZEBRA_FLAG_REJECT);
190 break;
191 case 'b':
192 case 'B': /* XXX */
193 SET_FLAG(flag, ZEBRA_FLAG_BLACKHOLE);
194 break;
195 default:
196 vty_out(vty, "%% Malformed flag %s \n", flag_str);
197 return CMD_WARNING_CONFIG_FAILED;
198 }
199 }
200
c6cef20b 201 if (gate_str) {
1d3f0eff 202 if (inet_pton(afi2family(afi), gate_str, &gate) != 1) {
c6cef20b
RW
203 vty_out(vty, "%% Malformed nexthop address %s\n",
204 gate_str);
205 return CMD_WARNING_CONFIG_FAILED;
206 }
207 gatep = &gate;
d62a17ae 208 }
209
c6cef20b
RW
210 if (ifname) {
211 struct interface *ifp;
212 ifp = if_lookup_by_name(ifname, zvrf_id(zvrf));
d62a17ae 213 if (!ifp) {
c6cef20b
RW
214 vty_out(vty, "%% Malformed Interface name %s\n",
215 ifname);
d62a17ae 216 ifindex = IFINDEX_DELETED;
217 } else
218 ifindex = ifp->ifindex;
c6cef20b
RW
219 }
220
221 if (gate_str == NULL && ifname == NULL)
222 type = STATIC_BLACKHOLE;
1d3f0eff
RW
223 else if (gate_str && ifname) {
224 if (afi == AFI_IP)
225 type = STATIC_IPV4_GATEWAY_IFINDEX;
226 else
227 type = STATIC_IPV6_GATEWAY_IFINDEX;
228 } else if (ifname)
d62a17ae 229 type = STATIC_IFINDEX;
1d3f0eff
RW
230 else {
231 if (afi == AFI_IP)
232 type = STATIC_IPV4_GATEWAY;
233 else
234 type = STATIC_IPV6_GATEWAY;
235 }
d62a17ae 236
00685a85 237 if (!negate)
1d3f0eff
RW
238 static_add_route(afi, safi, type, &p, src_p, gatep, ifindex,
239 ifname, flag, tag, distance, zvrf, &snh_label);
d62a17ae 240 else
1d3f0eff
RW
241 static_delete_route(afi, safi, type, &p, src_p, gatep, ifindex,
242 tag, distance, zvrf, &snh_label);
d62a17ae 243
244 return CMD_SUCCESS;
718e3744 245}
246
b78a80d7 247/* Static unicast routes for multicast RPF lookup. */
00685a85 248DEFPY (ip_mroute_dist,
b8a96915 249 ip_mroute_dist_cmd,
00685a85 250 "[no] ip mroute A.B.C.D/M$prefix <A.B.C.D$gate|INTERFACE$ifname> [(1-255)$distance]",
d7fa34c1 251 NO_STR
b78a80d7
EM
252 IP_STR
253 "Configure static unicast route into MRIB for multicast RPF lookup\n"
254 "IP destination prefix (e.g. 10.0.0.0/8)\n"
255 "Nexthop address\n"
256 "Nexthop interface name\n"
257 "Distance\n")
258{
00685a85
RW
259 return zebra_static_route(vty, AFI_IP, SAFI_MULTICAST, no, prefix_str,
260 NULL, NULL, gate_str, ifname, NULL, NULL,
261 distance_str, NULL, NULL);
b62ecea5 262}
b8a96915 263
4623d897
DL
264DEFUN (ip_multicast_mode,
265 ip_multicast_mode_cmd,
6147e2c6 266 "ip multicast rpf-lookup-mode <urib-only|mrib-only|mrib-then-urib|lower-distance|longer-prefix>",
4623d897
DL
267 IP_STR
268 "Multicast options\n"
269 "RPF lookup behavior\n"
270 "Lookup in unicast RIB only\n"
271 "Lookup in multicast RIB only\n"
272 "Try multicast RIB first, fall back to unicast RIB\n"
273 "Lookup both, use entry with lower distance\n"
274 "Lookup both, use entry with longer prefix\n")
275{
d62a17ae 276 char *mode = argv[3]->text;
277
278 if (strmatch(mode, "urib-only"))
279 multicast_mode_ipv4_set(MCAST_URIB_ONLY);
280 else if (strmatch(mode, "mrib-only"))
281 multicast_mode_ipv4_set(MCAST_MRIB_ONLY);
282 else if (strmatch(mode, "mrib-then-urib"))
283 multicast_mode_ipv4_set(MCAST_MIX_MRIB_FIRST);
284 else if (strmatch(mode, "lower-distance"))
285 multicast_mode_ipv4_set(MCAST_MIX_DISTANCE);
286 else if (strmatch(mode, "longer-prefix"))
287 multicast_mode_ipv4_set(MCAST_MIX_PFXLEN);
288 else {
289 vty_out(vty, "Invalid mode specified\n");
290 return CMD_WARNING_CONFIG_FAILED;
291 }
4623d897 292
d62a17ae 293 return CMD_SUCCESS;
4623d897
DL
294}
295
296DEFUN (no_ip_multicast_mode,
297 no_ip_multicast_mode_cmd,
b62ecea5 298 "no ip multicast rpf-lookup-mode [<urib-only|mrib-only|mrib-then-urib|lower-distance|longer-prefix>]",
4623d897
DL
299 NO_STR
300 IP_STR
301 "Multicast options\n"
302 "RPF lookup behavior\n"
303 "Lookup in unicast RIB only\n"
304 "Lookup in multicast RIB only\n"
305 "Try multicast RIB first, fall back to unicast RIB\n"
306 "Lookup both, use entry with lower distance\n"
307 "Lookup both, use entry with longer prefix\n")
308{
d62a17ae 309 multicast_mode_ipv4_set(MCAST_NO_CONFIG);
310 return CMD_SUCCESS;
4623d897
DL
311}
312
4623d897 313
b78a80d7
EM
314DEFUN (show_ip_rpf,
315 show_ip_rpf_cmd,
acb25e73 316 "show ip rpf [json]",
b78a80d7
EM
317 SHOW_STR
318 IP_STR
acb25e73
DW
319 "Display RPF information for multicast source\n"
320 JSON_STR)
b78a80d7 321{
d62a17ae 322 int uj = use_json(argc, argv);
323 return do_show_ip_route(vty, VRF_DEFAULT_NAME, AFI_IP, SAFI_MULTICAST,
324 false, uj, 0, NULL, false, -1, 0);
b78a80d7
EM
325}
326
65dd94cf
DL
327DEFUN (show_ip_rpf_addr,
328 show_ip_rpf_addr_cmd,
329 "show ip rpf A.B.C.D",
330 SHOW_STR
331 IP_STR
332 "Display RPF information for multicast source\n"
333 "IP multicast source address (e.g. 10.0.0.0)\n")
334{
d62a17ae 335 int idx_ipv4 = 3;
336 struct in_addr addr;
337 struct route_node *rn;
338 struct route_entry *re;
339 int ret;
340
341 ret = inet_aton(argv[idx_ipv4]->arg, &addr);
342 if (ret == 0) {
343 vty_out(vty, "%% Malformed address\n");
344 return CMD_WARNING;
345 }
346
347 re = rib_match_ipv4_multicast(VRF_DEFAULT, addr, &rn);
348
349 if (re)
350 vty_show_ip_route_detail(vty, rn, 1);
351 else
352 vty_out(vty, "%% No match for RPF lookup\n");
353
354 return CMD_SUCCESS;
355}
356
030721b7 357/* Static route configuration. */
00685a85 358DEFPY (ip_route,
030721b7 359 ip_route_cmd,
00685a85
RW
360 "[no] ip route\
361 <A.B.C.D/M$prefix|A.B.C.D$prefix A.B.C.D$mask>\
362 <\
363 {A.B.C.D$gate|INTERFACE$ifname}\
364 |null0$ifname\
365 |<reject|blackhole>$flag\
366 >\
367 [{\
368 tag (1-4294967295)\
369 |(1-255)$distance\
370 |vrf NAME\
371 |label WORD\
372 }]",
373 NO_STR
0d9551dc
DS
374 IP_STR
375 "Establish static routes\n"
376 "IP destination prefix (e.g. 10.0.0.0/8)\n"
00685a85
RW
377 "IP destination prefix\n"
378 "IP destination prefix mask\n"
0d9551dc
DS
379 "IP gateway address\n"
380 "IP gateway interface name\n"
381 "Null interface\n"
0d9551dc
DS
382 "Emit an ICMP unreachable when matched\n"
383 "Silently discard pkts when matched\n"
384 "Set tag for this route\n"
030721b7
DS
385 "Tag value\n"
386 "Distance value for this route\n"
599186ad
RW
387 VRF_CMD_HELP_STR
388 MPLS_LABEL_HELPSTR)
389{
00685a85
RW
390 return zebra_static_route(vty, AFI_IP, SAFI_UNICAST, no, prefix,
391 mask_str, NULL, gate_str, ifname, flag,
392 tag_str, distance_str, vrf, label);
393 return 0;
8f527c5e 394}
718e3744 395
8f527c5e 396/* New RIB. Detailed information for IPv4 route. */
d62a17ae 397static void vty_show_ip_route_detail(struct vty *vty, struct route_node *rn,
398 int mcast)
399{
400 struct route_entry *re;
401 struct nexthop *nexthop;
402 char buf[SRCDEST2STR_BUFFER];
403 struct zebra_vrf *zvrf;
404
405 RNODE_FOREACH_RE(rn, re)
8f527c5e 406 {
d62a17ae 407 const char *mcast_info = "";
408 if (mcast) {
409 rib_table_info_t *info = srcdest_rnode_table_info(rn);
410 mcast_info = (info->safi == SAFI_MULTICAST)
411 ? " using Multicast RIB"
412 : " using Unicast RIB";
413 }
414
415 vty_out(vty, "Routing entry for %s%s\n",
416 srcdest_rnode2str(rn, buf, sizeof(buf)), mcast_info);
417 vty_out(vty, " Known via \"%s", zebra_route_string(re->type));
418 if (re->instance)
419 vty_out(vty, "[%d]", re->instance);
420 vty_out(vty, "\"");
421 vty_out(vty, ", distance %u, metric %u", re->distance,
422 re->metric);
423 if (re->tag)
424 vty_out(vty, ", tag %d", re->tag);
425 if (re->mtu)
426 vty_out(vty, ", mtu %u", re->mtu);
427 if (re->vrf_id != VRF_DEFAULT) {
428 zvrf = vrf_info_lookup(re->vrf_id);
429 vty_out(vty, ", vrf %s", zvrf_name(zvrf));
430 }
431 if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED))
432 vty_out(vty, ", best");
433 if (re->refcnt)
434 vty_out(vty, ", refcnt %ld", re->refcnt);
435 if (CHECK_FLAG(re->flags, ZEBRA_FLAG_BLACKHOLE))
436 vty_out(vty, ", blackhole");
437 if (CHECK_FLAG(re->flags, ZEBRA_FLAG_REJECT))
438 vty_out(vty, ", reject");
439 vty_out(vty, "\n");
440
441 if (re->type == ZEBRA_ROUTE_RIP || re->type == ZEBRA_ROUTE_OSPF
442 || re->type == ZEBRA_ROUTE_ISIS
443 || re->type == ZEBRA_ROUTE_NHRP
444 || re->type == ZEBRA_ROUTE_TABLE
445 || re->type == ZEBRA_ROUTE_BGP) {
446 time_t uptime;
447 struct tm *tm;
448
449 uptime = time(NULL);
450 uptime -= re->uptime;
451 tm = gmtime(&uptime);
452
453 vty_out(vty, " Last update ");
454
455 if (uptime < ONE_DAY_SECOND)
456 vty_out(vty, "%02d:%02d:%02d", tm->tm_hour,
457 tm->tm_min, tm->tm_sec);
458 else if (uptime < ONE_WEEK_SECOND)
459 vty_out(vty, "%dd%02dh%02dm", tm->tm_yday,
460 tm->tm_hour, tm->tm_min);
461 else
462 vty_out(vty, "%02dw%dd%02dh", tm->tm_yday / 7,
463 tm->tm_yday - ((tm->tm_yday / 7) * 7),
464 tm->tm_hour);
465 vty_out(vty, " ago\n");
466 }
467
468 for (ALL_NEXTHOPS(re->nexthop, nexthop)) {
469 char addrstr[32];
470
471 vty_out(vty, " %c%s",
472 CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)
473 ? '*'
474 : ' ',
475 nexthop->rparent ? " " : "");
476
477 switch (nexthop->type) {
478 case NEXTHOP_TYPE_IPV4:
479 case NEXTHOP_TYPE_IPV4_IFINDEX:
480 vty_out(vty, " %s",
481 inet_ntoa(nexthop->gate.ipv4));
482 if (nexthop->ifindex)
483 vty_out(vty, ", via %s",
484 ifindex2ifname(nexthop->ifindex,
485 re->vrf_id));
486 break;
487 case NEXTHOP_TYPE_IPV6:
488 case NEXTHOP_TYPE_IPV6_IFINDEX:
489 vty_out(vty, " %s",
490 inet_ntop(AF_INET6, &nexthop->gate.ipv6,
491 buf, sizeof buf));
492 if (nexthop->ifindex)
493 vty_out(vty, ", via %s",
494 ifindex2ifname(nexthop->ifindex,
495 re->vrf_id));
496 break;
497 case NEXTHOP_TYPE_IFINDEX:
498 vty_out(vty, " directly connected, %s",
499 ifindex2ifname(nexthop->ifindex,
500 re->vrf_id));
501 break;
502 case NEXTHOP_TYPE_BLACKHOLE:
503 vty_out(vty, " directly connected, Null0");
504 break;
505 default:
506 break;
507 }
508 if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
509 vty_out(vty, " inactive");
510
511 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK))
512 vty_out(vty, " onlink");
513
514 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
515 vty_out(vty, " (recursive)");
516
517 switch (nexthop->type) {
518 case NEXTHOP_TYPE_IPV4:
519 case NEXTHOP_TYPE_IPV4_IFINDEX:
520 if (nexthop->src.ipv4.s_addr) {
521 if (inet_ntop(AF_INET,
522 &nexthop->src.ipv4,
523 addrstr, sizeof addrstr))
524 vty_out(vty, ", src %s",
525 addrstr);
526 }
527 break;
528 case NEXTHOP_TYPE_IPV6:
529 case NEXTHOP_TYPE_IPV6_IFINDEX:
530 if (!IPV6_ADDR_SAME(&nexthop->src.ipv6,
531 &in6addr_any)) {
532 if (inet_ntop(AF_INET6,
533 &nexthop->src.ipv6,
534 addrstr, sizeof addrstr))
535 vty_out(vty, ", src %s",
536 addrstr);
537 }
538 break;
539 default:
540 break;
541 }
542
1994ae60
JB
543 if (re->nexthop_mtu)
544 vty_out(vty, ", mtu %u", re->nexthop_mtu);
545
d62a17ae 546 /* Label information */
547 if (nexthop->nh_label
548 && nexthop->nh_label->num_labels) {
549 vty_out(vty, ", label %s",
550 mpls_label2str(
551 nexthop->nh_label->num_labels,
552 nexthop->nh_label->label, buf,
553 sizeof buf, 1));
554 }
555
556 vty_out(vty, "\n");
557 }
558 vty_out(vty, "\n");
559 }
560}
561
562static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
563 struct route_entry *re, json_object *json)
564{
565 struct nexthop *nexthop;
566 int len = 0;
567 char buf[SRCDEST2STR_BUFFER];
568 json_object *json_nexthops = NULL;
569 json_object *json_nexthop = NULL;
570 json_object *json_route = NULL;
571 json_object *json_labels = NULL;
572
573 if (json) {
574 json_route = json_object_new_object();
575 json_nexthops = json_object_new_array();
576
577 json_object_string_add(json_route, "prefix",
578 srcdest_rnode2str(rn, buf, sizeof buf));
579 json_object_string_add(json_route, "protocol",
580 zebra_route_string(re->type));
581
582 if (re->instance)
583 json_object_int_add(json_route, "instance",
584 re->instance);
585
586 if (re->vrf_id)
587 json_object_int_add(json_route, "vrfId", re->vrf_id);
588
589 if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED))
590 json_object_boolean_true_add(json_route, "selected");
591
925c2f88 592 if (re->type != ZEBRA_ROUTE_CONNECT) {
d62a17ae 593 json_object_int_add(json_route, "distance",
594 re->distance);
595 json_object_int_add(json_route, "metric", re->metric);
596 }
597
598 if (CHECK_FLAG(re->flags, ZEBRA_FLAG_BLACKHOLE))
599 json_object_boolean_true_add(json_route, "blackhole");
600
601 if (CHECK_FLAG(re->flags, ZEBRA_FLAG_REJECT))
602 json_object_boolean_true_add(json_route, "reject");
603
604 if (re->type == ZEBRA_ROUTE_RIP || re->type == ZEBRA_ROUTE_OSPF
605 || re->type == ZEBRA_ROUTE_ISIS
606 || re->type == ZEBRA_ROUTE_NHRP
607 || re->type == ZEBRA_ROUTE_TABLE
608 || re->type == ZEBRA_ROUTE_BGP) {
609 time_t uptime;
610 struct tm *tm;
611
612 uptime = time(NULL);
613 uptime -= re->uptime;
614 tm = gmtime(&uptime);
615
616 if (uptime < ONE_DAY_SECOND)
617 sprintf(buf, "%02d:%02d:%02d", tm->tm_hour,
618 tm->tm_min, tm->tm_sec);
619 else if (uptime < ONE_WEEK_SECOND)
620 sprintf(buf, "%dd%02dh%02dm", tm->tm_yday,
621 tm->tm_hour, tm->tm_min);
622 else
623 sprintf(buf, "%02dw%dd%02dh", tm->tm_yday / 7,
624 tm->tm_yday - ((tm->tm_yday / 7) * 7),
625 tm->tm_hour);
626
627 json_object_string_add(json_route, "uptime", buf);
628 }
629
630 for (ALL_NEXTHOPS(re->nexthop, nexthop)) {
631 json_nexthop = json_object_new_object();
632
633 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB))
634 json_object_boolean_true_add(json_nexthop,
635 "fib");
636
637 switch (nexthop->type) {
638 case NEXTHOP_TYPE_IPV4:
639 case NEXTHOP_TYPE_IPV4_IFINDEX:
640 json_object_string_add(
641 json_nexthop, "ip",
642 inet_ntoa(nexthop->gate.ipv4));
643 json_object_string_add(json_nexthop, "afi",
644 "ipv4");
645
646 if (nexthop->ifindex) {
647 json_object_int_add(json_nexthop,
648 "interfaceIndex",
649 nexthop->ifindex);
650 json_object_string_add(
651 json_nexthop, "interfaceName",
652 ifindex2ifname(nexthop->ifindex,
653 re->vrf_id));
654 }
655 break;
656 case NEXTHOP_TYPE_IPV6:
657 case NEXTHOP_TYPE_IPV6_IFINDEX:
658 json_object_string_add(
659 json_nexthop, "ip",
660 inet_ntop(AF_INET6, &nexthop->gate.ipv6,
661 buf, sizeof buf));
662 json_object_string_add(json_nexthop, "afi",
663 "ipv6");
664
665 if (nexthop->ifindex) {
666 json_object_int_add(json_nexthop,
667 "interfaceIndex",
668 nexthop->ifindex);
669 json_object_string_add(
670 json_nexthop, "interfaceName",
671 ifindex2ifname(nexthop->ifindex,
672 re->vrf_id));
673 }
674 break;
675
676 case NEXTHOP_TYPE_IFINDEX:
677 json_object_boolean_true_add(
678 json_nexthop, "directlyConnected");
679 json_object_int_add(json_nexthop,
680 "interfaceIndex",
681 nexthop->ifindex);
682 json_object_string_add(
683 json_nexthop, "interfaceName",
684 ifindex2ifname(nexthop->ifindex,
685 re->vrf_id));
686 break;
687 case NEXTHOP_TYPE_BLACKHOLE:
688 json_object_boolean_true_add(json_nexthop,
689 "blackhole");
690 break;
691 default:
692 break;
693 }
694
695 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
696 json_object_boolean_true_add(json_nexthop,
697 "active");
698
699 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK))
700 json_object_boolean_true_add(json_nexthop,
701 "onLink");
702
703 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
704 json_object_boolean_true_add(json_nexthop,
705 "recursive");
706
707 switch (nexthop->type) {
708 case NEXTHOP_TYPE_IPV4:
709 case NEXTHOP_TYPE_IPV4_IFINDEX:
710 if (nexthop->src.ipv4.s_addr) {
711 if (inet_ntop(AF_INET,
712 &nexthop->src.ipv4, buf,
713 sizeof buf))
714 json_object_string_add(
715 json_nexthop, "source",
716 buf);
717 }
718 break;
719 case NEXTHOP_TYPE_IPV6:
720 case NEXTHOP_TYPE_IPV6_IFINDEX:
721 if (!IPV6_ADDR_SAME(&nexthop->src.ipv6,
722 &in6addr_any)) {
723 if (inet_ntop(AF_INET6,
724 &nexthop->src.ipv6, buf,
725 sizeof buf))
726 json_object_string_add(
727 json_nexthop, "source",
728 buf);
729 }
730 break;
731 default:
732 break;
733 }
734
735 if (nexthop->nh_label
736 && nexthop->nh_label->num_labels) {
737 json_labels = json_object_new_array();
738
739 for (int label_index = 0;
740 label_index
741 < nexthop->nh_label->num_labels;
742 label_index++)
743 json_object_array_add(
744 json_labels,
745 json_object_new_int(
746 nexthop->nh_label->label
747 [label_index]));
748
749 json_object_object_add(json_nexthop, "labels",
750 json_labels);
751 }
752
753 json_object_array_add(json_nexthops, json_nexthop);
754 }
755
756 json_object_object_add(json_route, "nexthops", json_nexthops);
757 json_object_array_add(json, json_route);
758 return;
759 }
760
761 /* Nexthop information. */
762 for (ALL_NEXTHOPS(re->nexthop, nexthop)) {
763 if (nexthop == re->nexthop) {
764 /* Prefix information. */
765 len = vty_out(vty, "%c", zebra_route_char(re->type));
766 if (re->instance)
767 len += vty_out(vty, "[%d]", re->instance);
768 len += vty_out(
769 vty, "%c%c %s",
770 CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED)
771 ? '>'
772 : ' ',
773 CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)
774 ? '*'
775 : ' ',
776 srcdest_rnode2str(rn, buf, sizeof buf));
777
778 /* Distance and metric display. */
925c2f88 779 if (re->type != ZEBRA_ROUTE_CONNECT)
d62a17ae 780 len += vty_out(vty, " [%d/%d]", re->distance,
781 re->metric);
782 } else
783 vty_out(vty, " %c%*c",
784 CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)
785 ? '*'
786 : ' ',
787 len - 3 + (2 * nexthop_level(nexthop)), ' ');
788
789 switch (nexthop->type) {
790 case NEXTHOP_TYPE_IPV4:
791 case NEXTHOP_TYPE_IPV4_IFINDEX:
792 vty_out(vty, " via %s", inet_ntoa(nexthop->gate.ipv4));
793 if (nexthop->ifindex)
794 vty_out(vty, ", %s",
795 ifindex2ifname(nexthop->ifindex,
796 re->vrf_id));
797 break;
798 case NEXTHOP_TYPE_IPV6:
799 case NEXTHOP_TYPE_IPV6_IFINDEX:
800 vty_out(vty, " via %s",
801 inet_ntop(AF_INET6, &nexthop->gate.ipv6, buf,
802 sizeof buf));
803 if (nexthop->ifindex)
804 vty_out(vty, ", %s",
805 ifindex2ifname(nexthop->ifindex,
806 re->vrf_id));
807 break;
808
809 case NEXTHOP_TYPE_IFINDEX:
810 vty_out(vty, " is directly connected, %s",
811 ifindex2ifname(nexthop->ifindex, re->vrf_id));
812 break;
813 case NEXTHOP_TYPE_BLACKHOLE:
814 vty_out(vty, " is directly connected, Null0");
815 break;
816 default:
817 break;
818 }
819 if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
820 vty_out(vty, " inactive");
821
822 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK))
823 vty_out(vty, " onlink");
824
825 if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
826 vty_out(vty, " (recursive)");
827
828 switch (nexthop->type) {
829 case NEXTHOP_TYPE_IPV4:
830 case NEXTHOP_TYPE_IPV4_IFINDEX:
831 if (nexthop->src.ipv4.s_addr) {
832 if (inet_ntop(AF_INET, &nexthop->src.ipv4, buf,
833 sizeof buf))
834 vty_out(vty, ", src %s", buf);
835 }
836 break;
837 case NEXTHOP_TYPE_IPV6:
838 case NEXTHOP_TYPE_IPV6_IFINDEX:
839 if (!IPV6_ADDR_SAME(&nexthop->src.ipv6, &in6addr_any)) {
840 if (inet_ntop(AF_INET6, &nexthop->src.ipv6, buf,
841 sizeof buf))
842 vty_out(vty, ", src %s", buf);
843 }
844 break;
845 default:
846 break;
847 }
848
849 /* Label information */
850 if (nexthop->nh_label && nexthop->nh_label->num_labels) {
851 vty_out(vty, ", label %s",
852 mpls_label2str(nexthop->nh_label->num_labels,
853 nexthop->nh_label->label, buf,
854 sizeof buf, 1));
855 }
856
857 if (CHECK_FLAG(re->flags, ZEBRA_FLAG_BLACKHOLE))
858 vty_out(vty, ", bh");
859 if (CHECK_FLAG(re->flags, ZEBRA_FLAG_REJECT))
860 vty_out(vty, ", rej");
861
862 if (re->type == ZEBRA_ROUTE_RIP || re->type == ZEBRA_ROUTE_OSPF
863 || re->type == ZEBRA_ROUTE_ISIS
864 || re->type == ZEBRA_ROUTE_NHRP
865 || re->type == ZEBRA_ROUTE_TABLE
866 || re->type == ZEBRA_ROUTE_BGP) {
867 time_t uptime;
868 struct tm *tm;
869
870 uptime = time(NULL);
871 uptime -= re->uptime;
872 tm = gmtime(&uptime);
873
874 if (uptime < ONE_DAY_SECOND)
875 vty_out(vty, ", %02d:%02d:%02d", tm->tm_hour,
876 tm->tm_min, tm->tm_sec);
877 else if (uptime < ONE_WEEK_SECOND)
878 vty_out(vty, ", %dd%02dh%02dm", tm->tm_yday,
879 tm->tm_hour, tm->tm_min);
880 else
881 vty_out(vty, ", %02dw%dd%02dh", tm->tm_yday / 7,
882 tm->tm_yday - ((tm->tm_yday / 7) * 7),
883 tm->tm_hour);
884 }
885 vty_out(vty, "\n");
886 }
887}
888
889static bool use_fib(struct cmd_token *token)
890{
891 return strncmp(token->arg, "route", strlen(token->arg));
892}
893
894static int do_show_ip_route(struct vty *vty, const char *vrf_name, afi_t afi,
895 safi_t safi, bool use_fib, u_char use_json,
896 route_tag_t tag, struct prefix *longer_prefix_p,
897 bool supernets_only, int type,
898 u_short ospf_instance_id)
899{
900 struct route_table *table;
901 struct route_node *rn;
902 struct route_entry *re;
903 int first = 1;
904 struct zebra_vrf *zvrf = NULL;
905 char buf[BUFSIZ];
906 json_object *json = NULL;
907 json_object *json_prefix = NULL;
908 u_int32_t addr;
909
910 if (!(zvrf = zebra_vrf_lookup_by_name(vrf_name))) {
911 if (use_json)
912 vty_out(vty, "{}\n");
913 else
914 vty_out(vty, "vrf %s not defined\n", vrf_name);
915 return CMD_SUCCESS;
916 }
917
918 if (zvrf_id(zvrf) == VRF_UNKNOWN) {
919 if (use_json)
920 vty_out(vty, "{}\n");
921 else
922 vty_out(vty, "vrf %s inactive\n", vrf_name);
923 return CMD_SUCCESS;
924 }
925
926 table = zebra_vrf_table(afi, safi, zvrf_id(zvrf));
927 if (!table) {
928 if (use_json)
929 vty_out(vty, "{}\n");
930 return CMD_SUCCESS;
931 }
932
933 if (use_json)
934 json = json_object_new_object();
935
936 /* Show all routes. */
937 for (rn = route_top(table); rn; rn = route_next(rn)) {
938 RNODE_FOREACH_RE(rn, re)
939 {
940 if (use_fib
941 && !CHECK_FLAG(re->status,
942 ROUTE_ENTRY_SELECTED_FIB))
943 continue;
944
945 if (tag && re->tag != tag)
946 continue;
947
948 if (longer_prefix_p
949 && !prefix_match(longer_prefix_p, &rn->p))
950 continue;
951
952 /* This can only be true when the afi is IPv4 */
953 if (supernets_only) {
954 addr = ntohl(rn->p.u.prefix4.s_addr);
955
956 if (IN_CLASSC(addr) && rn->p.prefixlen >= 24)
957 continue;
958
959 if (IN_CLASSB(addr) && rn->p.prefixlen >= 16)
960 continue;
961
962 if (IN_CLASSA(addr) && rn->p.prefixlen >= 8)
963 continue;
964 }
965
966 if (type && re->type != type)
967 continue;
968
969 if (ospf_instance_id
970 && (re->type != ZEBRA_ROUTE_OSPF
971 || re->instance != ospf_instance_id))
972 continue;
973
974 if (use_json) {
975 if (!json_prefix)
976 json_prefix = json_object_new_array();
977 } else {
978 if (first) {
979 if (afi == AFI_IP)
980 vty_out(vty,
981 SHOW_ROUTE_V4_HEADER);
982 else
983 vty_out(vty,
984 SHOW_ROUTE_V6_HEADER);
985
986 if (zvrf_id(zvrf) != VRF_DEFAULT)
987 vty_out(vty, "\nVRF %s:\n",
988 zvrf_name(zvrf));
989
990 first = 0;
991 }
992 }
993
994 vty_show_ip_route(vty, rn, re, json_prefix);
995 }
996
997 if (json_prefix) {
998 prefix2str(&rn->p, buf, sizeof buf);
999 json_object_object_add(json, buf, json_prefix);
1000 json_prefix = NULL;
1001 }
1002 }
1003
1004 if (use_json) {
9d303b37
DL
1005 vty_out(vty, "%s\n", json_object_to_json_string_ext(
1006 json, JSON_C_TO_STRING_PRETTY));
d62a17ae 1007 json_object_free(json);
1008 }
1009
1010 return CMD_SUCCESS;
abbda2d4 1011}
d511d7f1 1012
8f527c5e
FL
1013DEFUN (show_ip_nht,
1014 show_ip_nht_cmd,
9bf96c84 1015 "show ip nht [vrf NAME]",
8f527c5e
FL
1016 SHOW_STR
1017 IP_STR
9bf96c84
DW
1018 "IP nexthop tracking table\n"
1019 VRF_CMD_HELP_STR)
8f527c5e 1020{
d62a17ae 1021 int idx_vrf = 4;
1022 vrf_id_t vrf_id = VRF_DEFAULT;
12f6fb97 1023
d62a17ae 1024 if (argc == 5)
1025 VRF_GET_ID(vrf_id, argv[idx_vrf]->arg);
12f6fb97 1026
d62a17ae 1027 zebra_print_rnh_table(vrf_id, AF_INET, vty, RNH_NEXTHOP_TYPE);
1028 return CMD_SUCCESS;
8f527c5e
FL
1029}
1030
12f6fb97 1031
d511d7f1
DS
1032DEFUN (show_ip_nht_vrf_all,
1033 show_ip_nht_vrf_all_cmd,
5bebf568 1034 "show ip nht vrf all",
d511d7f1
DS
1035 SHOW_STR
1036 IP_STR
1037 "IP nexthop tracking table\n"
1038 VRF_ALL_CMD_HELP_STR)
1039{
d62a17ae 1040 struct vrf *vrf;
1041 struct zebra_vrf *zvrf;
d511d7f1 1042
d62a17ae 1043 RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name)
1044 if ((zvrf = vrf->info) != NULL) {
1045 vty_out(vty, "\nVRF %s:\n", zvrf_name(zvrf));
1046 zebra_print_rnh_table(zvrf_id(zvrf), AF_INET, vty,
1047 RNH_NEXTHOP_TYPE);
1048 }
d511d7f1 1049
d62a17ae 1050 return CMD_SUCCESS;
d511d7f1
DS
1051}
1052
8f527c5e
FL
1053DEFUN (show_ipv6_nht,
1054 show_ipv6_nht_cmd,
9bf96c84 1055 "show ipv6 nht [vrf NAME]",
8f527c5e 1056 SHOW_STR
689e6694 1057 IPV6_STR
9bf96c84
DW
1058 "IPv6 nexthop tracking table\n"
1059 VRF_CMD_HELP_STR)
8f527c5e 1060{
d62a17ae 1061 int idx_vrf = 4;
1062 vrf_id_t vrf_id = VRF_DEFAULT;
12f6fb97 1063
d62a17ae 1064 if (argc == 5)
1065 VRF_GET_ID(vrf_id, argv[idx_vrf]->arg);
12f6fb97 1066
d62a17ae 1067 zebra_print_rnh_table(vrf_id, AF_INET6, vty, RNH_NEXTHOP_TYPE);
1068 return CMD_SUCCESS;
8f527c5e
FL
1069}
1070
12f6fb97 1071
d511d7f1
DS
1072DEFUN (show_ipv6_nht_vrf_all,
1073 show_ipv6_nht_vrf_all_cmd,
5bebf568 1074 "show ipv6 nht vrf all",
d511d7f1
DS
1075 SHOW_STR
1076 IP_STR
1077 "IPv6 nexthop tracking table\n"
1078 VRF_ALL_CMD_HELP_STR)
1079{
d62a17ae 1080 struct vrf *vrf;
1081 struct zebra_vrf *zvrf;
d511d7f1 1082
d62a17ae 1083 RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name)
1084 if ((zvrf = vrf->info) != NULL) {
1085 vty_out(vty, "\nVRF %s:\n", zvrf_name(zvrf));
1086 zebra_print_rnh_table(zvrf_id(zvrf), AF_INET6, vty,
1087 RNH_NEXTHOP_TYPE);
1088 }
d511d7f1 1089
d62a17ae 1090 return CMD_SUCCESS;
d511d7f1
DS
1091}
1092
8f527c5e
FL
1093DEFUN (ip_nht_default_route,
1094 ip_nht_default_route_cmd,
1095 "ip nht resolve-via-default",
1096 IP_STR
1097 "Filter Next Hop tracking route resolution\n"
1098 "Resolve via default route\n")
1099{
d62a17ae 1100 if (zebra_rnh_ip_default_route)
1101 return CMD_SUCCESS;
8f527c5e 1102
d62a17ae 1103 zebra_rnh_ip_default_route = 1;
1104 zebra_evaluate_rnh(0, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL);
1105 return CMD_SUCCESS;
8f527c5e
FL
1106}
1107
1108DEFUN (no_ip_nht_default_route,
1109 no_ip_nht_default_route_cmd,
1110 "no ip nht resolve-via-default",
1111 NO_STR
1112 IP_STR
1113 "Filter Next Hop tracking route resolution\n"
1114 "Resolve via default route\n")
1115{
d62a17ae 1116 if (!zebra_rnh_ip_default_route)
1117 return CMD_SUCCESS;
8f527c5e 1118
d62a17ae 1119 zebra_rnh_ip_default_route = 0;
1120 zebra_evaluate_rnh(0, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL);
1121 return CMD_SUCCESS;
8f527c5e
FL
1122}
1123
1124DEFUN (ipv6_nht_default_route,
1125 ipv6_nht_default_route_cmd,
1126 "ipv6 nht resolve-via-default",
1127 IP6_STR
1128 "Filter Next Hop tracking route resolution\n"
1129 "Resolve via default route\n")
1130{
d62a17ae 1131 if (zebra_rnh_ipv6_default_route)
1132 return CMD_SUCCESS;
8f527c5e 1133
d62a17ae 1134 zebra_rnh_ipv6_default_route = 1;
1135 zebra_evaluate_rnh(0, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL);
1136 return CMD_SUCCESS;
8f527c5e
FL
1137}
1138
1139DEFUN (no_ipv6_nht_default_route,
1140 no_ipv6_nht_default_route_cmd,
1141 "no ipv6 nht resolve-via-default",
1142 NO_STR
1143 IP6_STR
1144 "Filter Next Hop tracking route resolution\n"
1145 "Resolve via default route\n")
1146{
d62a17ae 1147 if (!zebra_rnh_ipv6_default_route)
1148 return CMD_SUCCESS;
8f527c5e 1149
d62a17ae 1150 zebra_rnh_ipv6_default_route = 0;
1151 zebra_evaluate_rnh(0, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL);
1152 return CMD_SUCCESS;
8f527c5e
FL
1153}
1154
acb25e73
DW
1155DEFUN (show_ip_route,
1156 show_ip_route_cmd,
1157 "show ip <fib|route> [vrf NAME] [tag (1-4294967295)|A.B.C.D/M longer-prefixes|supernets-only|" FRR_IP_REDIST_STR_ZEBRA "|ospf (1-65535)] [json]",
8f527c5e
FL
1158 SHOW_STR
1159 IP_STR
87a88962 1160 "IP forwarding table\n"
8f527c5e 1161 "IP routing table\n"
9bf96c84 1162 VRF_CMD_HELP_STR
8f527c5e 1163 "Show only routes with tag\n"
acb25e73
DW
1164 "Tag value\n"
1165 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
1166 "Show route matching the specified Network/Mask pair only\n"
1167 "Show supernet entries only\n"
1168 FRR_IP_REDIST_HELP_STR_ZEBRA
1169 "Open Shortest Path First (OSPFv2)\n"
1170 "Instance ID\n"
1171 JSON_STR)
8f527c5e 1172{
d62a17ae 1173 bool uf = use_fib(argv[2]);
1174 struct route_table *table;
1175 int vrf_all = 0;
1176 route_tag_t tag = 0;
1177 vrf_id_t vrf_id = VRF_DEFAULT;
1178 struct vrf *vrf;
1179 struct zebra_vrf *zvrf;
1180 int uj = use_json(argc, argv);
1181 int idx = 0;
1182 struct prefix p;
1183 bool longer_prefixes = false;
1184 bool supernets_only = false;
1185 int type = 0;
1186 u_short ospf_instance_id = 0;
1187
1188 if (argv_find(argv, argc, "vrf", &idx)) {
1189 if (strmatch(argv[idx + 1]->arg, "all"))
1190 vrf_all = 1;
1191 else
1192 VRF_GET_ID(vrf_id, argv[idx + 1]->arg);
1193 }
1194
1195 if (argv_find(argv, argc, "tag", &idx))
1196 tag = strtoul(argv[idx + 1]->arg, NULL, 10);
1197
1198 else if (argv_find(argv, argc, "A.B.C.D/M", &idx)) {
1199 str2prefix(argv[idx]->arg, &p);
1200 longer_prefixes = true;
1201 }
1202
1203 else if (argv_find(argv, argc, "supernets_only", &idx))
1204 supernets_only = true;
1205
1206 else {
1207 if (argv_find(argv, argc, "kernel", &idx))
1208 type = proto_redistnum(AFI_IP, argv[idx]->text);
1209 else if (argv_find(argv, argc, "babel", &idx))
1210 type = proto_redistnum(AFI_IP, argv[idx]->text);
1211 else if (argv_find(argv, argc, "connected", &idx))
1212 type = proto_redistnum(AFI_IP, argv[idx]->text);
1213 else if (argv_find(argv, argc, "static", &idx))
1214 type = proto_redistnum(AFI_IP, argv[idx]->text);
1215 else if (argv_find(argv, argc, "rip", &idx))
1216 type = proto_redistnum(AFI_IP, argv[idx]->text);
1217 else if (argv_find(argv, argc, "ospf", &idx))
1218 type = proto_redistnum(AFI_IP, argv[idx]->text);
1219 else if (argv_find(argv, argc, "isis", &idx))
1220 type = proto_redistnum(AFI_IP, argv[idx]->text);
1221 else if (argv_find(argv, argc, "bgp", &idx))
1222 type = proto_redistnum(AFI_IP, argv[idx]->text);
1223 else if (argv_find(argv, argc, "pim", &idx))
1224 type = proto_redistnum(AFI_IP, argv[idx]->text);
1225 else if (argv_find(argv, argc, "eigrp", &idx))
1226 type = proto_redistnum(AFI_IP, argv[idx]->text);
1227 else if (argv_find(argv, argc, "nhrp", &idx))
1228 type = proto_redistnum(AFI_IP, argv[idx]->text);
1229 else if (argv_find(argv, argc, "table", &idx))
1230 type = proto_redistnum(AFI_IP, argv[idx]->text);
1231 else if (argv_find(argv, argc, "vnc", &idx))
1232 type = proto_redistnum(AFI_IP, argv[idx]->text);
1233
1234 if (argv_find(argv, argc, "(1-65535)", &idx))
1235 ospf_instance_id = strtoul(argv[idx]->arg, NULL, 10);
1236
1237 if (type < 0) {
1238 vty_out(vty, "Unknown route type\n");
1239 return CMD_WARNING;
1240 }
1241 }
1242
1243 if (vrf_all) {
1244 RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name)
1245 {
1246 if ((zvrf = vrf->info) == NULL
1247 || (table = zvrf->table[AFI_IP][SAFI_UNICAST])
1248 == NULL)
1249 continue;
1250
1251 do_show_ip_route(
1252 vty, zvrf_name(zvrf), AFI_IP, SAFI_UNICAST, uf,
1253 uj, tag, longer_prefixes ? &p : NULL,
1254 supernets_only, type, ospf_instance_id);
1255 }
1256 } else {
1257 vrf = vrf_lookup_by_id(vrf_id);
1258 do_show_ip_route(vty, vrf->name, AFI_IP, SAFI_UNICAST, uf, uj,
1259 tag, longer_prefixes ? &p : NULL,
1260 supernets_only, type, ospf_instance_id);
1261 }
1262 return CMD_SUCCESS;
8f527c5e
FL
1263}
1264
1265DEFUN (show_ip_route_addr,
1266 show_ip_route_addr_cmd,
9bf96c84 1267 "show ip route [vrf NAME] A.B.C.D",
8f527c5e
FL
1268 SHOW_STR
1269 IP_STR
1270 "IP routing table\n"
9bf96c84 1271 VRF_CMD_HELP_STR
8f527c5e
FL
1272 "Network in the IP routing table to display\n")
1273{
d62a17ae 1274 int ret;
1275 struct prefix_ipv4 p;
1276 struct route_table *table;
1277 struct route_node *rn;
1278 vrf_id_t vrf_id = VRF_DEFAULT;
1279
1280 if (strmatch(argv[3]->text, "vrf")) {
1281 VRF_GET_ID(vrf_id, argv[4]->arg);
1282 ret = str2prefix_ipv4(argv[5]->arg, &p);
1283 } else {
1284 ret = str2prefix_ipv4(argv[3]->arg, &p);
1285 }
d511d7f1 1286
d62a17ae 1287 if (ret <= 0) {
1288 vty_out(vty, "%% Malformed IPv4 address\n");
1289 return CMD_WARNING;
1290 }
8f527c5e 1291
d62a17ae 1292 table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, vrf_id);
1293 if (!table)
1294 return CMD_SUCCESS;
8f527c5e 1295
d62a17ae 1296 rn = route_node_match(table, (struct prefix *)&p);
1297 if (!rn) {
1298 vty_out(vty, "%% Network not in table\n");
1299 return CMD_WARNING;
1300 }
8f527c5e 1301
d62a17ae 1302 vty_show_ip_route_detail(vty, rn, 0);
8f527c5e 1303
d62a17ae 1304 route_unlock_node(rn);
8f527c5e 1305
d62a17ae 1306 return CMD_SUCCESS;
8f527c5e
FL
1307}
1308
8f527c5e
FL
1309DEFUN (show_ip_route_prefix,
1310 show_ip_route_prefix_cmd,
9bf96c84 1311 "show ip route [vrf NAME] A.B.C.D/M",
8f527c5e
FL
1312 SHOW_STR
1313 IP_STR
1314 "IP routing table\n"
9bf96c84 1315 VRF_CMD_HELP_STR
8f527c5e
FL
1316 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n")
1317{
d62a17ae 1318 int ret;
1319 struct prefix_ipv4 p;
1320 struct route_table *table;
1321 struct route_node *rn;
1322 vrf_id_t vrf_id = VRF_DEFAULT;
1323
1324 if (strmatch(argv[3]->text, "vrf")) {
1325 VRF_GET_ID(vrf_id, argv[4]->arg);
1326 ret = str2prefix_ipv4(argv[5]->arg, &p);
1327 } else {
1328 ret = str2prefix_ipv4(argv[3]->arg, &p);
1329 }
d511d7f1 1330
d62a17ae 1331 if (ret <= 0) {
1332 vty_out(vty, "%% Malformed IPv4 address\n");
1333 return CMD_WARNING;
1334 }
8f527c5e 1335
d62a17ae 1336 table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, vrf_id);
1337 if (!table)
1338 return CMD_SUCCESS;
8f527c5e 1339
d62a17ae 1340 rn = route_node_match(table, (struct prefix *)&p);
1341 if (!rn || rn->p.prefixlen != p.prefixlen) {
1342 vty_out(vty, "%% Network not in table\n");
1343 return CMD_WARNING;
1344 }
8f527c5e 1345
d62a17ae 1346 vty_show_ip_route_detail(vty, rn, 0);
8f527c5e 1347
d62a17ae 1348 route_unlock_node(rn);
8f527c5e 1349
d62a17ae 1350 return CMD_SUCCESS;
8f527c5e
FL
1351}
1352
8f527c5e 1353
d62a17ae 1354static void vty_show_ip_route_summary(struct vty *vty,
1355 struct route_table *table)
8f527c5e 1356{
d62a17ae 1357 struct route_node *rn;
1358 struct route_entry *re;
8f527c5e
FL
1359#define ZEBRA_ROUTE_IBGP ZEBRA_ROUTE_MAX
1360#define ZEBRA_ROUTE_TOTAL (ZEBRA_ROUTE_IBGP + 1)
d62a17ae 1361 u_int32_t rib_cnt[ZEBRA_ROUTE_TOTAL + 1];
1362 u_int32_t fib_cnt[ZEBRA_ROUTE_TOTAL + 1];
1363 u_int32_t i;
1364 u_int32_t is_ibgp;
1365
1366 memset(&rib_cnt, 0, sizeof(rib_cnt));
1367 memset(&fib_cnt, 0, sizeof(fib_cnt));
1368 for (rn = route_top(table); rn; rn = srcdest_route_next(rn))
1369 RNODE_FOREACH_RE(rn, re)
1370 {
1371 is_ibgp = (re->type == ZEBRA_ROUTE_BGP
1372 && CHECK_FLAG(re->flags, ZEBRA_FLAG_IBGP));
1373
1374 rib_cnt[ZEBRA_ROUTE_TOTAL]++;
1375 if (is_ibgp)
1376 rib_cnt[ZEBRA_ROUTE_IBGP]++;
1377 else
1378 rib_cnt[re->type]++;
1379
1380 if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED)) {
1381 fib_cnt[ZEBRA_ROUTE_TOTAL]++;
1382
1383 if (is_ibgp)
1384 fib_cnt[ZEBRA_ROUTE_IBGP]++;
1385 else
1386 fib_cnt[re->type]++;
1387 }
1388 }
1389
1390 vty_out(vty, "%-20s %-20s %s (vrf %s)\n", "Route Source", "Routes",
1391 "FIB", zvrf_name(((rib_table_info_t *)table->info)->zvrf));
1392
1393 for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
9d303b37
DL
1394 if ((rib_cnt[i] > 0) || (i == ZEBRA_ROUTE_BGP
1395 && rib_cnt[ZEBRA_ROUTE_IBGP] > 0)) {
d62a17ae 1396 if (i == ZEBRA_ROUTE_BGP) {
1397 vty_out(vty, "%-20s %-20d %-20d \n", "ebgp",
1398 rib_cnt[ZEBRA_ROUTE_BGP],
1399 fib_cnt[ZEBRA_ROUTE_BGP]);
1400 vty_out(vty, "%-20s %-20d %-20d \n", "ibgp",
1401 rib_cnt[ZEBRA_ROUTE_IBGP],
1402 fib_cnt[ZEBRA_ROUTE_IBGP]);
1403 } else
1404 vty_out(vty, "%-20s %-20d %-20d \n",
1405 zebra_route_string(i), rib_cnt[i],
1406 fib_cnt[i]);
1407 }
1408 }
1409
1410 vty_out(vty, "------\n");
1411 vty_out(vty, "%-20s %-20d %-20d \n", "Totals",
1412 rib_cnt[ZEBRA_ROUTE_TOTAL], fib_cnt[ZEBRA_ROUTE_TOTAL]);
1413 vty_out(vty, "\n");
8f527c5e
FL
1414}
1415
1416/*
1417 * Implementation of the ip route summary prefix command.
1418 *
1419 * This command prints the primary prefixes that have been installed by various
1420 * protocols on the box.
1421 *
1422 */
d62a17ae 1423static void vty_show_ip_route_summary_prefix(struct vty *vty,
1424 struct route_table *table)
8f527c5e 1425{
d62a17ae 1426 struct route_node *rn;
1427 struct route_entry *re;
1428 struct nexthop *nexthop;
8f527c5e
FL
1429#define ZEBRA_ROUTE_IBGP ZEBRA_ROUTE_MAX
1430#define ZEBRA_ROUTE_TOTAL (ZEBRA_ROUTE_IBGP + 1)
d62a17ae 1431 u_int32_t rib_cnt[ZEBRA_ROUTE_TOTAL + 1];
1432 u_int32_t fib_cnt[ZEBRA_ROUTE_TOTAL + 1];
1433 u_int32_t i;
1434 int cnt;
1435
1436 memset(&rib_cnt, 0, sizeof(rib_cnt));
1437 memset(&fib_cnt, 0, sizeof(fib_cnt));
1438 for (rn = route_top(table); rn; rn = srcdest_route_next(rn))
1439 RNODE_FOREACH_RE(rn, re)
1440 {
1441
1442 /*
1443 * In case of ECMP, count only once.
1444 */
1445 cnt = 0;
1446 for (nexthop = re->nexthop; (!cnt && nexthop);
1447 nexthop = nexthop->next) {
1448 cnt++;
1449 rib_cnt[ZEBRA_ROUTE_TOTAL]++;
1450 rib_cnt[re->type]++;
1451 if (CHECK_FLAG(nexthop->flags,
1452 NEXTHOP_FLAG_FIB)) {
1453 fib_cnt[ZEBRA_ROUTE_TOTAL]++;
1454 fib_cnt[re->type]++;
1455 }
1456 if (re->type == ZEBRA_ROUTE_BGP
1457 && CHECK_FLAG(re->flags, ZEBRA_FLAG_IBGP)) {
1458 rib_cnt[ZEBRA_ROUTE_IBGP]++;
1459 if (CHECK_FLAG(nexthop->flags,
1460 NEXTHOP_FLAG_FIB))
1461 fib_cnt[ZEBRA_ROUTE_IBGP]++;
1462 }
1463 }
1464 }
1465
1466 vty_out(vty, "%-20s %-20s %s (vrf %s)\n", "Route Source",
1467 "Prefix Routes", "FIB",
1468 zvrf_name(((rib_table_info_t *)table->info)->zvrf));
1469
1470 for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
1471 if (rib_cnt[i] > 0) {
1472 if (i == ZEBRA_ROUTE_BGP) {
1473 vty_out(vty, "%-20s %-20d %-20d \n", "ebgp",
1474 rib_cnt[ZEBRA_ROUTE_BGP]
1475 - rib_cnt[ZEBRA_ROUTE_IBGP],
1476 fib_cnt[ZEBRA_ROUTE_BGP]
1477 - fib_cnt[ZEBRA_ROUTE_IBGP]);
1478 vty_out(vty, "%-20s %-20d %-20d \n", "ibgp",
1479 rib_cnt[ZEBRA_ROUTE_IBGP],
1480 fib_cnt[ZEBRA_ROUTE_IBGP]);
1481 } else
1482 vty_out(vty, "%-20s %-20d %-20d \n",
1483 zebra_route_string(i), rib_cnt[i],
1484 fib_cnt[i]);
1485 }
1486 }
1487
1488 vty_out(vty, "------\n");
1489 vty_out(vty, "%-20s %-20d %-20d \n", "Totals",
1490 rib_cnt[ZEBRA_ROUTE_TOTAL], fib_cnt[ZEBRA_ROUTE_TOTAL]);
1491 vty_out(vty, "\n");
9343ce83
DS
1492}
1493
718e3744 1494/* Show route summary. */
1495DEFUN (show_ip_route_summary,
1496 show_ip_route_summary_cmd,
9bf96c84 1497 "show ip route [vrf NAME] summary",
718e3744 1498 SHOW_STR
1499 IP_STR
1500 "IP routing table\n"
9bf96c84 1501 VRF_CMD_HELP_STR
718e3744 1502 "Summary of all routes\n")
1503{
d62a17ae 1504 struct route_table *table;
1505 vrf_id_t vrf_id = VRF_DEFAULT;
718e3744 1506
d62a17ae 1507 if (strmatch(argv[3]->text, "vrf"))
1508 VRF_GET_ID(vrf_id, argv[4]->arg);
af41b63a 1509
d62a17ae 1510 table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, vrf_id);
1511 if (!table)
1512 return CMD_SUCCESS;
718e3744 1513
d62a17ae 1514 vty_show_ip_route_summary(vty, table);
718e3744 1515
d62a17ae 1516 return CMD_SUCCESS;
718e3744 1517}
1518
9343ce83
DS
1519/* Show route summary prefix. */
1520DEFUN (show_ip_route_summary_prefix,
1521 show_ip_route_summary_prefix_cmd,
9bf96c84 1522 "show ip route [vrf NAME] summary prefix",
9343ce83
DS
1523 SHOW_STR
1524 IP_STR
1525 "IP routing table\n"
9bf96c84 1526 VRF_CMD_HELP_STR
9343ce83
DS
1527 "Summary of all routes\n"
1528 "Prefix routes\n")
1529{
d62a17ae 1530 struct route_table *table;
1531 vrf_id_t vrf_id = VRF_DEFAULT;
9343ce83 1532
d62a17ae 1533 if (strmatch(argv[3]->text, "vrf"))
1534 VRF_GET_ID(vrf_id, argv[4]->arg);
af41b63a 1535
d62a17ae 1536 table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, vrf_id);
1537 if (!table)
1538 return CMD_SUCCESS;
9343ce83 1539
d62a17ae 1540 vty_show_ip_route_summary_prefix(vty, table);
9343ce83 1541
d62a17ae 1542 return CMD_SUCCESS;
9343ce83
DS
1543}
1544
af41b63a 1545
acb25e73
DW
1546DEFUN (show_ip_route_vrf_all_addr,
1547 show_ip_route_vrf_all_addr_cmd,
1548 "show ip route vrf all A.B.C.D",
af41b63a
FL
1549 SHOW_STR
1550 IP_STR
1551 "IP routing table\n"
acb25e73
DW
1552 VRF_ALL_CMD_HELP_STR
1553 "Network in the IP routing table to display\n")
af41b63a 1554{
d62a17ae 1555 int idx_ipv4 = 5;
1556 int ret;
1557 struct prefix_ipv4 p;
1558 struct route_table *table;
1559 struct route_node *rn;
1560 struct vrf *vrf;
1561 struct zebra_vrf *zvrf;
1562
1563 ret = str2prefix_ipv4(argv[idx_ipv4]->arg, &p);
1564 if (ret <= 0) {
1565 vty_out(vty, "%% Malformed IPv4 address\n");
1566 return CMD_WARNING;
1567 }
af41b63a 1568
d62a17ae 1569 RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name)
1570 {
1571 if ((zvrf = vrf->info) == NULL
1572 || (table = zvrf->table[AFI_IP][SAFI_UNICAST]) == NULL)
1573 continue;
af41b63a 1574
d62a17ae 1575 rn = route_node_match(table, (struct prefix *)&p);
1576 if (!rn)
1577 continue;
d511d7f1 1578
d62a17ae 1579 vty_show_ip_route_detail(vty, rn, 0);
acb25e73 1580
d62a17ae 1581 route_unlock_node(rn);
1582 }
8f527c5e 1583
d62a17ae 1584 return CMD_SUCCESS;
8f527c5e
FL
1585}
1586
d511d7f1
DS
1587DEFUN (show_ip_route_vrf_all_prefix,
1588 show_ip_route_vrf_all_prefix_cmd,
5bebf568 1589 "show ip route vrf all A.B.C.D/M",
8f527c5e
FL
1590 SHOW_STR
1591 IP_STR
1592 "IP routing table\n"
d511d7f1
DS
1593 VRF_ALL_CMD_HELP_STR
1594 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n")
8f527c5e 1595{
d62a17ae 1596 int idx_ipv4_prefixlen = 5;
1597 int ret;
1598 struct prefix_ipv4 p;
1599 struct route_table *table;
1600 struct route_node *rn;
1601 struct vrf *vrf;
1602 struct zebra_vrf *zvrf;
1603
1604 ret = str2prefix_ipv4(argv[idx_ipv4_prefixlen]->arg, &p);
1605 if (ret <= 0) {
1606 vty_out(vty, "%% Malformed IPv4 address\n");
1607 return CMD_WARNING;
1608 }
8f527c5e 1609
d62a17ae 1610 RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name)
1611 {
1612 if ((zvrf = vrf->info) == NULL
1613 || (table = zvrf->table[AFI_IP][SAFI_UNICAST]) == NULL)
1614 continue;
8f527c5e 1615
d62a17ae 1616 rn = route_node_match(table, (struct prefix *)&p);
1617 if (!rn)
1618 continue;
1619 if (rn->p.prefixlen != p.prefixlen) {
1620 route_unlock_node(rn);
1621 continue;
1622 }
8f527c5e 1623
d62a17ae 1624 vty_show_ip_route_detail(vty, rn, 0);
8f527c5e 1625
d62a17ae 1626 route_unlock_node(rn);
1627 }
8f527c5e 1628
d62a17ae 1629 return CMD_SUCCESS;
8f527c5e
FL
1630}
1631
d511d7f1
DS
1632DEFUN (show_ip_route_vrf_all_summary,
1633 show_ip_route_vrf_all_summary_cmd,
5bebf568 1634 "show ip route vrf all summary ",
8f527c5e
FL
1635 SHOW_STR
1636 IP_STR
1637 "IP routing table\n"
d511d7f1
DS
1638 VRF_ALL_CMD_HELP_STR
1639 "Summary of all routes\n")
8f527c5e 1640{
d62a17ae 1641 struct vrf *vrf;
1642 struct zebra_vrf *zvrf;
8f527c5e 1643
d62a17ae 1644 RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name)
1645 if ((zvrf = vrf->info) != NULL)
1646 vty_show_ip_route_summary(vty,
1647 zvrf->table[AFI_IP][SAFI_UNICAST]);
8f527c5e 1648
d62a17ae 1649 return CMD_SUCCESS;
8f527c5e
FL
1650}
1651
d511d7f1
DS
1652DEFUN (show_ip_route_vrf_all_summary_prefix,
1653 show_ip_route_vrf_all_summary_prefix_cmd,
5bebf568 1654 "show ip route vrf all summary prefix",
8f527c5e
FL
1655 SHOW_STR
1656 IP_STR
1657 "IP routing table\n"
d511d7f1 1658 VRF_ALL_CMD_HELP_STR
8f527c5e 1659 "Summary of all routes\n"
d511d7f1 1660 "Prefix routes\n")
8f527c5e 1661{
d62a17ae 1662 struct vrf *vrf;
1663 struct zebra_vrf *zvrf;
8f527c5e 1664
d62a17ae 1665 RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name)
1666 if ((zvrf = vrf->info) != NULL)
1667 vty_show_ip_route_summary_prefix(
1668 vty, zvrf->table[AFI_IP][SAFI_UNICAST]);
8f527c5e 1669
d62a17ae 1670 return CMD_SUCCESS;
8f527c5e
FL
1671}
1672
9de498ec 1673/* Write static route configuration. */
d62a17ae 1674static int static_config(struct vty *vty, afi_t afi, safi_t safi,
1675 const char *cmd)
1676{
1677 struct route_node *rn;
1678 struct static_route *si;
1679 struct route_table *stable;
1680 struct vrf *vrf;
1681 struct zebra_vrf *zvrf;
1682 char buf[SRCDEST2STR_BUFFER];
1683 int write = 0;
1684
1685 RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name)
1686 {
1687 if (!(zvrf = vrf->info))
1688 continue;
1689 if ((stable = zvrf->stable[afi][safi]) == NULL)
1690 continue;
1691
1692 for (rn = route_top(stable); rn; rn = srcdest_route_next(rn))
1693 for (si = rn->info; si; si = si->next) {
1694 vty_out(vty, "%s %s", cmd,
1695 srcdest_rnode2str(rn, buf, sizeof buf));
1696
1697 switch (si->type) {
1698 case STATIC_IPV4_GATEWAY:
1699 vty_out(vty, " %s",
1700 inet_ntoa(si->addr.ipv4));
1701 break;
1702 case STATIC_IPV6_GATEWAY:
1703 vty_out(vty, " %s",
1704 inet_ntop(AF_INET6,
1705 &si->addr.ipv6, buf,
1706 sizeof buf));
1707 break;
1708 case STATIC_IFINDEX:
1709 vty_out(vty, " %s", si->ifname);
1710 break;
1ac79ce8 1711 /* blackhole and Null0 mean the same thing */
d62a17ae 1712 case STATIC_BLACKHOLE:
1ac79ce8
DW
1713 if (CHECK_FLAG(si->flags, ZEBRA_FLAG_REJECT))
1714 vty_out(vty, " reject");
1715 else
1716 vty_out(vty, " Null0");
d62a17ae 1717 break;
599186ad
RW
1718 case STATIC_IPV4_GATEWAY_IFINDEX:
1719 vty_out(vty, " %s %s",
1720 inet_ntop(AF_INET,
1721 &si->addr.ipv4, buf,
1722 sizeof buf),
1723 ifindex2ifname(si->ifindex,
1724 si->vrf_id));
1725 break;
d62a17ae 1726 case STATIC_IPV6_GATEWAY_IFINDEX:
1727 vty_out(vty, " %s %s",
1728 inet_ntop(AF_INET6,
1729 &si->addr.ipv6, buf,
1730 sizeof buf),
1731 ifindex2ifname(si->ifindex,
1732 si->vrf_id));
1733 break;
1734 }
1735
1736 /* flags are incompatible with STATIC_BLACKHOLE
1737 */
1738 if (si->type != STATIC_BLACKHOLE) {
1739 if (CHECK_FLAG(si->flags,
1740 ZEBRA_FLAG_REJECT))
1741 vty_out(vty, " %s", "reject");
1742
1743 if (CHECK_FLAG(si->flags,
1744 ZEBRA_FLAG_BLACKHOLE))
1745 vty_out(vty, " %s",
1746 "blackhole");
1747 }
1748
1749 if (si->tag)
1750 vty_out(vty, " tag %" ROUTE_TAG_PRI,
1751 si->tag);
1752
1753 if (si->distance
1754 != ZEBRA_STATIC_DISTANCE_DEFAULT)
1755 vty_out(vty, " %d", si->distance);
1756
1757 if (si->vrf_id != VRF_DEFAULT)
1758 vty_out(vty, " vrf %s",
1759 zvrf_name(zvrf));
1760
1761 /* Label information */
1762 if (si->snh_label.num_labels)
1763 vty_out(vty, " label %s",
1764 mpls_label2str(
1765 si->snh_label
1766 .num_labels,
1767 si->snh_label.label,
1768 buf, sizeof buf, 0));
1769
1770 vty_out(vty, "\n");
1771
1772 write = 1;
1773 }
1774 }
1775 return write;
8f527c5e
FL
1776}
1777
00685a85 1778DEFPY (ipv6_route,
8f527c5e 1779 ipv6_route_cmd,
00685a85
RW
1780 "[no] ipv6 route X:X::X:X/M$prefix [from X:X::X:X/M]\
1781 <\
1782 {X:X::X:X$gate|INTERFACE$ifname}\
1783 |null0$ifname\
1784 |<reject|blackhole>$flag\
1785 >\
1786 [{\
1787 tag (1-4294967295)\
1788 |(1-255)$distance\
1789 |vrf NAME\
1790 |label WORD\
1791 }]",
81dfcaa2 1792 NO_STR
00685a85 1793 IPV6_STR
81dfcaa2 1794 "Establish static routes\n"
1795 "IPv6 destination prefix (e.g. 3ffe:506::/32)\n"
c423229b
CF
1796 "IPv6 source-dest route\n"
1797 "IPv6 source prefix\n"
81dfcaa2 1798 "IPv6 gateway address\n"
1799 "IPv6 gateway interface name\n"
e9e190f2 1800 "Null interface\n"
0d9551dc
DS
1801 "Emit an ICMP unreachable when matched\n"
1802 "Silently discard pkts when matched\n"
1803 "Set tag for this route\n"
1804 "Tag value\n"
8f527c5e 1805 "Distance value for this prefix\n"
d97c792e
RW
1806 VRF_CMD_HELP_STR
1807 MPLS_LABEL_HELPSTR)
0d9551dc 1808{
00685a85
RW
1809 return zebra_static_route(vty, AFI_IP6, SAFI_UNICAST, no, prefix_str,
1810 NULL, from_str, gate_str, ifname, flag,
1811 tag_str, distance_str, vrf, label);
0d9551dc
DS
1812}
1813
718e3744 1814DEFUN (show_ipv6_route,
1815 show_ipv6_route_cmd,
acb25e73 1816 "show ipv6 <fib|route> [vrf NAME] [tag (1-4294967295)|X:X::X:X/M longer-prefixes|" FRR_IP6_REDIST_STR_ZEBRA "] [json]",
718e3744 1817 SHOW_STR
1818 IP_STR
acb25e73
DW
1819 "IP forwarding table\n"
1820 "IP routing table\n"
b62ecea5 1821 VRF_CMD_HELP_STR
acb25e73
DW
1822 "Show only routes with tag\n"
1823 "Tag value\n"
1824 "IPv6 prefix\n"
1825 "Show route matching the specified Network/Mask pair only\n"
1826 FRR_IP6_REDIST_HELP_STR_ZEBRA
1827 JSON_STR)
718e3744 1828{
d62a17ae 1829 bool uf = use_fib(argv[2]);
1830 struct route_table *table;
1831 int vrf_all = 0;
1832 route_tag_t tag = 0;
1833 vrf_id_t vrf_id = VRF_DEFAULT;
1834 struct vrf *vrf;
1835 struct zebra_vrf *zvrf;
1836 int uj = use_json(argc, argv);
1837 int idx = 0;
1838 struct prefix p;
1839 bool longer_prefixes = false;
1840 bool supernets_only = false;
1841 int type = 0;
1842
1843 if (argv_find(argv, argc, "vrf", &idx)) {
1844 if (strmatch(argv[idx + 1]->arg, "all"))
1845 vrf_all = 1;
1846 else
1847 VRF_GET_ID(vrf_id, argv[idx + 1]->arg);
1848 }
1849
1850 if (argv_find(argv, argc, "tag", &idx))
1851 tag = strtoul(argv[idx + 1]->arg, NULL, 10);
1852
1853 else if (argv_find(argv, argc, "X:X::X:X/M", &idx)) {
1854 str2prefix(argv[idx]->arg, &p);
1855 longer_prefixes = true;
1856 }
1857
1858 else {
1859 if (argv_find(argv, argc, "kernel", &idx))
1860 type = proto_redistnum(AFI_IP6, argv[idx]->text);
1861 else if (argv_find(argv, argc, "babel", &idx))
1862 type = proto_redistnum(AFI_IP6, argv[idx]->text);
1863 else if (argv_find(argv, argc, "connected", &idx))
1864 type = proto_redistnum(AFI_IP6, argv[idx]->text);
1865 else if (argv_find(argv, argc, "static", &idx))
1866 type = proto_redistnum(AFI_IP6, argv[idx]->text);
1867 else if (argv_find(argv, argc, "ripng", &idx))
1868 type = proto_redistnum(AFI_IP6, argv[idx]->text);
1869 else if (argv_find(argv, argc, "ospf6", &idx))
1870 type = proto_redistnum(AFI_IP6, argv[idx]->text);
1871 else if (argv_find(argv, argc, "isis", &idx))
1872 type = proto_redistnum(AFI_IP6, argv[idx]->text);
1873 else if (argv_find(argv, argc, "bgp", &idx))
1874 type = proto_redistnum(AFI_IP6, argv[idx]->text);
1875 else if (argv_find(argv, argc, "nhrp", &idx))
1876 type = proto_redistnum(AFI_IP6, argv[idx]->text);
1877 else if (argv_find(argv, argc, "table", &idx))
1878 type = proto_redistnum(AFI_IP6, argv[idx]->text);
1879 else if (argv_find(argv, argc, "vnc", &idx))
1880 type = proto_redistnum(AFI_IP6, argv[idx]->text);
1881
1882 if (type < 0) {
1883 vty_out(vty, "Unknown route type\n");
1884 return CMD_WARNING;
1885 }
1886 }
1887
1888 if (vrf_all) {
1889 RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name)
1890 {
1891 if ((zvrf = vrf->info) == NULL
1892 || (table = zvrf->table[AFI_IP6][SAFI_UNICAST])
1893 == NULL)
1894 continue;
1895
1896 do_show_ip_route(vty, zvrf_name(zvrf), AFI_IP6,
1897 SAFI_UNICAST, uf, uj, tag,
1898 longer_prefixes ? &p : NULL,
1899 supernets_only, type, 0);
1900 }
1901 } else {
1902 vrf = vrf_lookup_by_id(vrf_id);
1903 do_show_ip_route(vty, vrf->name, AFI_IP6, SAFI_UNICAST, uf, uj,
1904 tag, longer_prefixes ? &p : NULL,
1905 supernets_only, type, 0);
1906 }
1907 return CMD_SUCCESS;
718e3744 1908}
1909
1910DEFUN (show_ipv6_route_addr,
1911 show_ipv6_route_addr_cmd,
9bf96c84 1912 "show ipv6 route [vrf NAME] X:X::X:X",
718e3744 1913 SHOW_STR
1914 IP_STR
1915 "IPv6 routing table\n"
9bf96c84 1916 VRF_CMD_HELP_STR
718e3744 1917 "IPv6 Address\n")
1918{
d62a17ae 1919 int ret;
1920 struct prefix_ipv6 p;
1921 struct route_table *table;
1922 struct route_node *rn;
1923 vrf_id_t vrf_id = VRF_DEFAULT;
1924
1925 if (strmatch(argv[3]->text, "vrf")) {
1926 VRF_GET_ID(vrf_id, argv[4]->arg);
1927 ret = str2prefix_ipv6(argv[5]->arg, &p);
1928 } else {
1929 ret = str2prefix_ipv6(argv[3]->arg, &p);
1930 }
d511d7f1 1931
d62a17ae 1932 if (ret <= 0) {
1933 vty_out(vty, "Malformed IPv6 address\n");
1934 return CMD_WARNING;
1935 }
718e3744 1936
d62a17ae 1937 table = zebra_vrf_table(AFI_IP6, SAFI_UNICAST, vrf_id);
1938 if (!table)
1939 return CMD_SUCCESS;
718e3744 1940
d62a17ae 1941 rn = route_node_match(table, (struct prefix *)&p);
1942 if (!rn) {
1943 vty_out(vty, "%% Network not in table\n");
1944 return CMD_WARNING;
1945 }
718e3744 1946
d62a17ae 1947 vty_show_ip_route_detail(vty, rn, 0);
718e3744 1948
d62a17ae 1949 route_unlock_node(rn);
718e3744 1950
d62a17ae 1951 return CMD_SUCCESS;
718e3744 1952}
1953
1954DEFUN (show_ipv6_route_prefix,
1955 show_ipv6_route_prefix_cmd,
9bf96c84 1956 "show ipv6 route [vrf NAME] X:X::X:X/M",
718e3744 1957 SHOW_STR
1958 IP_STR
1959 "IPv6 routing table\n"
9bf96c84 1960 VRF_CMD_HELP_STR
718e3744 1961 "IPv6 prefix\n")
1962{
d62a17ae 1963 int ret;
1964 struct prefix_ipv6 p;
1965 struct route_table *table;
1966 struct route_node *rn;
1967 vrf_id_t vrf_id = VRF_DEFAULT;
1968
1969 if (strmatch(argv[3]->text, "vrf")) {
1970 VRF_GET_ID(vrf_id, argv[4]->arg);
1971 ret = str2prefix_ipv6(argv[5]->arg, &p);
1972 } else
1973 ret = str2prefix_ipv6(argv[3]->arg, &p);
1974
1975 if (ret <= 0) {
1976 vty_out(vty, "Malformed IPv6 prefix\n");
1977 return CMD_WARNING;
1978 }
718e3744 1979
d62a17ae 1980 table = zebra_vrf_table(AFI_IP6, SAFI_UNICAST, vrf_id);
1981 if (!table)
1982 return CMD_SUCCESS;
718e3744 1983
d62a17ae 1984 rn = route_node_match(table, (struct prefix *)&p);
1985 if (!rn || rn->p.prefixlen != p.prefixlen) {
1986 vty_out(vty, "%% Network not in table\n");
1987 return CMD_WARNING;
1988 }
718e3744 1989
d62a17ae 1990 vty_show_ip_route_detail(vty, rn, 0);
718e3744 1991
d62a17ae 1992 route_unlock_node(rn);
718e3744 1993
d62a17ae 1994 return CMD_SUCCESS;
718e3744 1995}
1996
af41b63a 1997
61691c91
ST
1998/* Show route summary. */
1999DEFUN (show_ipv6_route_summary,
2000 show_ipv6_route_summary_cmd,
9bf96c84 2001 "show ipv6 route [vrf NAME] summary",
61691c91
ST
2002 SHOW_STR
2003 IP_STR
2004 "IPv6 routing table\n"
9bf96c84 2005 VRF_CMD_HELP_STR
61691c91
ST
2006 "Summary of all IPv6 routes\n")
2007{
d62a17ae 2008 struct route_table *table;
2009 vrf_id_t vrf_id = VRF_DEFAULT;
61691c91 2010
d62a17ae 2011 if (strmatch(argv[3]->text, "vrf"))
2012 VRF_GET_ID(vrf_id, argv[4]->arg);
61691c91 2013
d62a17ae 2014 table = zebra_vrf_table(AFI_IP6, SAFI_UNICAST, vrf_id);
2015 if (!table)
2016 return CMD_SUCCESS;
61691c91 2017
d62a17ae 2018 vty_show_ip_route_summary(vty, table);
61691c91 2019
d62a17ae 2020 return CMD_SUCCESS;
61691c91
ST
2021}
2022
af41b63a 2023
9343ce83
DS
2024/* Show ipv6 route summary prefix. */
2025DEFUN (show_ipv6_route_summary_prefix,
2026 show_ipv6_route_summary_prefix_cmd,
9bf96c84 2027 "show ipv6 route [vrf NAME] summary prefix",
9343ce83
DS
2028 SHOW_STR
2029 IP_STR
2030 "IPv6 routing table\n"
9bf96c84 2031 VRF_CMD_HELP_STR
9343ce83
DS
2032 "Summary of all IPv6 routes\n"
2033 "Prefix routes\n")
2034{
d62a17ae 2035 struct route_table *table;
2036 vrf_id_t vrf_id = VRF_DEFAULT;
9343ce83 2037
d62a17ae 2038 if (strmatch(argv[3]->text, "vrf"))
2039 VRF_GET_ID(vrf_id, argv[4]->arg);
9343ce83 2040
d62a17ae 2041 table = zebra_vrf_table(AFI_IP6, SAFI_UNICAST, vrf_id);
2042 if (!table)
2043 return CMD_SUCCESS;
9343ce83 2044
d62a17ae 2045 vty_show_ip_route_summary_prefix(vty, table);
9343ce83 2046
d62a17ae 2047 return CMD_SUCCESS;
9343ce83
DS
2048}
2049
af41b63a 2050
cddf391b
B
2051/*
2052 * Show IPv6 mroute command.Used to dump
2053 * the Multicast routing table.
2054 */
cddf391b
B
2055DEFUN (show_ipv6_mroute,
2056 show_ipv6_mroute_cmd,
9bf96c84 2057 "show ipv6 mroute [vrf NAME]",
cddf391b
B
2058 SHOW_STR
2059 IP_STR
9bf96c84
DW
2060 "IPv6 Multicast routing table\n"
2061 VRF_CMD_HELP_STR)
cddf391b 2062{
d62a17ae 2063 struct route_table *table;
2064 struct route_node *rn;
2065 struct route_entry *re;
2066 int first = 1;
2067 vrf_id_t vrf_id = VRF_DEFAULT;
2068
2069 if (argc == 5)
2070 VRF_GET_ID(vrf_id, argv[4]->arg);
2071
2072 table = zebra_vrf_table(AFI_IP6, SAFI_MULTICAST, vrf_id);
2073 if (!table)
2074 return CMD_SUCCESS;
2075
2076 /* Show all IPv6 route. */
2077 for (rn = route_top(table); rn; rn = srcdest_route_next(rn))
2078 RNODE_FOREACH_RE(rn, re)
2079 {
2080 if (first) {
2081 vty_out(vty, SHOW_ROUTE_V6_HEADER);
2082 first = 0;
2083 }
2084 vty_show_ip_route(vty, rn, re, NULL);
2085 }
2086 return CMD_SUCCESS;
cddf391b
B
2087}
2088
d511d7f1
DS
2089DEFUN (show_ipv6_route_vrf_all_addr,
2090 show_ipv6_route_vrf_all_addr_cmd,
5bebf568 2091 "show ipv6 route vrf all X:X::X:X",
af41b63a
FL
2092 SHOW_STR
2093 IP_STR
2094 "IPv6 routing table\n"
d511d7f1
DS
2095 VRF_ALL_CMD_HELP_STR
2096 "IPv6 Address\n")
af41b63a 2097{
d62a17ae 2098 int idx_ipv6 = 5;
2099 int ret;
2100 struct prefix_ipv6 p;
2101 struct route_table *table;
2102 struct route_node *rn;
2103 struct vrf *vrf;
2104 struct zebra_vrf *zvrf;
2105
2106 ret = str2prefix_ipv6(argv[idx_ipv6]->arg, &p);
2107 if (ret <= 0) {
2108 vty_out(vty, "Malformed IPv6 address\n");
2109 return CMD_WARNING;
2110 }
af41b63a 2111
d62a17ae 2112 RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name)
2113 {
2114 if ((zvrf = vrf->info) == NULL
2115 || (table = zvrf->table[AFI_IP6][SAFI_UNICAST]) == NULL)
2116 continue;
af41b63a 2117
d62a17ae 2118 rn = route_node_match(table, (struct prefix *)&p);
2119 if (!rn)
2120 continue;
af41b63a 2121
d62a17ae 2122 vty_show_ip_route_detail(vty, rn, 0);
af41b63a 2123
d62a17ae 2124 route_unlock_node(rn);
2125 }
af41b63a 2126
d62a17ae 2127 return CMD_SUCCESS;
af41b63a
FL
2128}
2129
d511d7f1
DS
2130DEFUN (show_ipv6_route_vrf_all_prefix,
2131 show_ipv6_route_vrf_all_prefix_cmd,
5bebf568 2132 "show ipv6 route vrf all X:X::X:X/M",
af41b63a
FL
2133 SHOW_STR
2134 IP_STR
2135 "IPv6 routing table\n"
d511d7f1
DS
2136 VRF_ALL_CMD_HELP_STR
2137 "IPv6 prefix\n")
af41b63a 2138{
d62a17ae 2139 int idx_ipv6_prefixlen = 5;
2140 int ret;
2141 struct prefix_ipv6 p;
2142 struct route_table *table;
2143 struct route_node *rn;
2144 struct vrf *vrf;
2145 struct zebra_vrf *zvrf;
2146
2147 ret = str2prefix_ipv6(argv[idx_ipv6_prefixlen]->arg, &p);
2148 if (ret <= 0) {
2149 vty_out(vty, "Malformed IPv6 prefix\n");
2150 return CMD_WARNING;
2151 }
af41b63a 2152
d62a17ae 2153 RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name)
2154 {
2155 if ((zvrf = vrf->info) == NULL
2156 || (table = zvrf->table[AFI_IP6][SAFI_UNICAST]) == NULL)
2157 continue;
af41b63a 2158
d62a17ae 2159 rn = route_node_match(table, (struct prefix *)&p);
2160 if (!rn)
2161 continue;
2162 if (rn->p.prefixlen != p.prefixlen) {
2163 route_unlock_node(rn);
2164 continue;
2165 }
af41b63a 2166
d62a17ae 2167 vty_show_ip_route_detail(vty, rn, 0);
af41b63a 2168
d62a17ae 2169 route_unlock_node(rn);
2170 }
af41b63a 2171
d62a17ae 2172 return CMD_SUCCESS;
af41b63a
FL
2173}
2174
d511d7f1
DS
2175DEFUN (show_ipv6_route_vrf_all_summary,
2176 show_ipv6_route_vrf_all_summary_cmd,
5bebf568 2177 "show ipv6 route vrf all summary",
af41b63a
FL
2178 SHOW_STR
2179 IP_STR
2180 "IPv6 routing table\n"
d511d7f1
DS
2181 VRF_ALL_CMD_HELP_STR
2182 "Summary of all IPv6 routes\n")
af41b63a 2183{
d62a17ae 2184 struct vrf *vrf;
2185 struct zebra_vrf *zvrf;
af41b63a 2186
d62a17ae 2187 RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name)
2188 if ((zvrf = vrf->info) != NULL)
2189 vty_show_ip_route_summary(vty,
2190 zvrf->table[AFI_IP6][SAFI_UNICAST]);
af41b63a 2191
d62a17ae 2192 return CMD_SUCCESS;
af41b63a
FL
2193}
2194
2195DEFUN (show_ipv6_mroute_vrf_all,
2196 show_ipv6_mroute_vrf_all_cmd,
5bebf568 2197 "show ipv6 mroute vrf all",
af41b63a
FL
2198 SHOW_STR
2199 IP_STR
2200 "IPv6 Multicast routing table\n"
2201 VRF_ALL_CMD_HELP_STR)
2202{
d62a17ae 2203 struct route_table *table;
2204 struct route_node *rn;
2205 struct route_entry *re;
2206 struct vrf *vrf;
2207 struct zebra_vrf *zvrf;
2208 int first = 1;
2209
2210 RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name)
2211 {
2212 if ((zvrf = vrf->info) == NULL
2213 || (table = zvrf->table[AFI_IP6][SAFI_MULTICAST]) == NULL)
2214 continue;
2215
2216 /* Show all IPv6 route. */
2217 for (rn = route_top(table); rn; rn = srcdest_route_next(rn))
2218 RNODE_FOREACH_RE(rn, re)
2219 {
2220 if (first) {
2221 vty_out(vty, SHOW_ROUTE_V6_HEADER);
2222 first = 0;
2223 }
2224 vty_show_ip_route(vty, rn, re, NULL);
2225 }
2226 }
2227 return CMD_SUCCESS;
af41b63a
FL
2228}
2229
d511d7f1
DS
2230DEFUN (show_ipv6_route_vrf_all_summary_prefix,
2231 show_ipv6_route_vrf_all_summary_prefix_cmd,
5bebf568 2232 "show ipv6 route vrf all summary prefix",
af41b63a
FL
2233 SHOW_STR
2234 IP_STR
2235 "IPv6 routing table\n"
d511d7f1 2236 VRF_ALL_CMD_HELP_STR
af41b63a 2237 "Summary of all IPv6 routes\n"
d511d7f1 2238 "Prefix routes\n")
af41b63a 2239{
d62a17ae 2240 struct vrf *vrf;
2241 struct zebra_vrf *zvrf;
af41b63a 2242
d62a17ae 2243 RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name)
2244 if ((zvrf = vrf->info) != NULL)
2245 vty_show_ip_route_summary_prefix(
2246 vty, zvrf->table[AFI_IP6][SAFI_UNICAST]);
af41b63a 2247
d62a17ae 2248 return CMD_SUCCESS;
af41b63a
FL
2249}
2250
6baf7bb8
DS
2251DEFUN (allow_external_route_update,
2252 allow_external_route_update_cmd,
2253 "allow-external-route-update",
17d990c1 2254 "Allow FRR routes to be overwritten by external processes\n")
6baf7bb8 2255{
d62a17ae 2256 allow_delete = 1;
6baf7bb8 2257
d62a17ae 2258 return CMD_SUCCESS;
6baf7bb8
DS
2259}
2260
2261DEFUN (no_allow_external_route_update,
2262 no_allow_external_route_update_cmd,
2263 "no allow-external-route-update",
17d990c1
DS
2264 NO_STR
2265 "Allow FRR routes to be overwritten by external processes\n")
6baf7bb8 2266{
d62a17ae 2267 allow_delete = 0;
6baf7bb8 2268
d62a17ae 2269 return CMD_SUCCESS;
6baf7bb8
DS
2270}
2271
12f6fb97
DS
2272/* show vrf */
2273DEFUN (show_vrf,
2274 show_vrf_cmd,
2275 "show vrf",
2276 SHOW_STR
2277 "VRF\n")
2278{
d62a17ae 2279 struct vrf *vrf;
2280 struct zebra_vrf *zvrf;
12f6fb97 2281
d62a17ae 2282 RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name)
2283 {
2284 if (!(zvrf = vrf->info))
2285 continue;
2286 if (!zvrf_id(zvrf))
2287 continue;
2288
2289 vty_out(vty, "vrf %s ", zvrf_name(zvrf));
2290 if (zvrf_id(zvrf) == VRF_UNKNOWN)
2291 vty_out(vty, "inactive");
2292 else
2293 vty_out(vty, "id %u table %u", zvrf_id(zvrf),
2294 zvrf->table_id);
2295 vty_out(vty, "\n");
2296 }
12f6fb97 2297
d62a17ae 2298 return CMD_SUCCESS;
12f6fb97
DS
2299}
2300
cec2e17d 2301DEFUN (show_evpn_vni,
2302 show_evpn_vni_cmd,
2303 "show evpn vni",
2304 SHOW_STR
2305 "EVPN\n"
2306 "VxLAN information\n")
2307{
d62a17ae 2308 struct zebra_vrf *zvrf;
cec2e17d 2309
d62a17ae 2310 zvrf = vrf_info_lookup(VRF_DEFAULT);
2311 zebra_vxlan_print_vnis(vty, zvrf);
2312 return CMD_SUCCESS;
cec2e17d 2313}
2314
2315DEFUN (show_evpn_vni_vni,
2316 show_evpn_vni_vni_cmd,
2317 "show evpn vni " CMD_VNI_RANGE,
2318 SHOW_STR
2319 "EVPN\n"
2320 "VxLAN Network Identifier\n"
2321 "VNI number\n")
2322{
d62a17ae 2323 struct zebra_vrf *zvrf;
2324 vni_t vni;
cec2e17d 2325
d62a17ae 2326 vni = strtoul(argv[3]->arg, NULL, 10);
2327 zvrf = vrf_info_lookup(VRF_DEFAULT);
2328 zebra_vxlan_print_vni(vty, zvrf, vni);
2329 return CMD_SUCCESS;
cec2e17d 2330}
2331
2332DEFUN (show_evpn_mac_vni,
2333 show_evpn_mac_vni_cmd,
2334 "show evpn mac vni " CMD_VNI_RANGE,
2335 SHOW_STR
2336 "EVPN\n"
2337 "MAC addresses\n"
2338 "VxLAN Network Identifier\n"
2339 "VNI number\n")
2340{
d62a17ae 2341 struct zebra_vrf *zvrf;
2342 vni_t vni;
cec2e17d 2343
d62a17ae 2344 vni = strtoul(argv[4]->arg, NULL, 10);
2345 zvrf = vrf_info_lookup(VRF_DEFAULT);
2346 zebra_vxlan_print_macs_vni(vty, zvrf, vni);
2347 return CMD_SUCCESS;
cec2e17d 2348}
2349
2350DEFUN (show_evpn_mac_vni_all,
2351 show_evpn_mac_vni_all_cmd,
2352 "show evpn mac vni all",
2353 SHOW_STR
2354 "EVPN\n"
2355 "MAC addresses\n"
2356 "VxLAN Network Identifier\n"
2357 "All VNIs\n")
2358{
d62a17ae 2359 struct zebra_vrf *zvrf;
cec2e17d 2360
d62a17ae 2361 zvrf = vrf_info_lookup(VRF_DEFAULT);
2362 zebra_vxlan_print_macs_all_vni(vty, zvrf);
2363 return CMD_SUCCESS;
cec2e17d 2364}
2365
2366DEFUN (show_evpn_mac_vni_all_vtep,
2367 show_evpn_mac_vni_all_vtep_cmd,
2368 "show evpn mac vni all vtep A.B.C.D",
2369 SHOW_STR
2370 "EVPN\n"
2371 "MAC addresses\n"
2372 "VxLAN Network Identifier\n"
2373 "All VNIs\n"
2374 "Remote VTEP\n"
2375 "Remote VTEP IP address\n")
2376{
d62a17ae 2377 struct zebra_vrf *zvrf;
2378 struct in_addr vtep_ip;
cec2e17d 2379
d62a17ae 2380 if (!inet_aton(argv[6]->arg, &vtep_ip)) {
2381 vty_out(vty, "%% Malformed VTEP IP address\n");
2382 return CMD_WARNING;
2383 }
2384 zvrf = vrf_info_lookup(VRF_DEFAULT);
2385 zebra_vxlan_print_macs_all_vni_vtep(vty, zvrf, vtep_ip);
cec2e17d 2386
d62a17ae 2387 return CMD_SUCCESS;
cec2e17d 2388}
2389
2390
2391DEFUN (show_evpn_mac_vni_mac,
2392 show_evpn_mac_vni_mac_cmd,
2393 "show evpn mac vni " CMD_VNI_RANGE " mac WORD",
2394 SHOW_STR
2395 "EVPN\n"
2396 "MAC addresses\n"
2397 "VxLAN Network Identifier\n"
2398 "VNI number\n"
2399 "MAC\n"
2400 "MAC address (e.g., 00:e0:ec:20:12:62)\n")
2401{
d62a17ae 2402 struct zebra_vrf *zvrf;
2403 vni_t vni;
2404 struct ethaddr mac;
cec2e17d 2405
d62a17ae 2406 vni = strtoul(argv[4]->arg, NULL, 10);
2407 if (!prefix_str2mac(argv[6]->arg, &mac)) {
2408 vty_out(vty, "%% Malformed MAC address");
2409 return CMD_WARNING;
2410 }
2411 zvrf = vrf_info_lookup(VRF_DEFAULT);
2412 zebra_vxlan_print_specific_mac_vni(vty, zvrf, vni, &mac);
2413 return CMD_SUCCESS;
cec2e17d 2414}
2415
2416DEFUN (show_evpn_mac_vni_vtep,
2417 show_evpn_mac_vni_vtep_cmd,
2418 "show evpn mac vni " CMD_VNI_RANGE " vtep A.B.C.D",
2419 SHOW_STR
2420 "EVPN\n"
2421 "MAC addresses\n"
2422 "VxLAN Network Identifier\n"
2423 "VNI number\n"
2424 "Remote VTEP\n"
2425 "Remote VTEP IP address\n")
2426{
d62a17ae 2427 struct zebra_vrf *zvrf;
2428 vni_t vni;
2429 struct in_addr vtep_ip;
cec2e17d 2430
d62a17ae 2431 vni = strtoul(argv[4]->arg, NULL, 10);
2432 if (!inet_aton(argv[6]->arg, &vtep_ip)) {
2433 vty_out(vty, "%% Malformed VTEP IP address\n");
2434 return CMD_WARNING;
2435 }
cec2e17d 2436
d62a17ae 2437 zvrf = vrf_info_lookup(VRF_DEFAULT);
2438 zebra_vxlan_print_macs_vni_vtep(vty, zvrf, vni, vtep_ip);
2439 return CMD_SUCCESS;
cec2e17d 2440}
2441
2442DEFUN (show_evpn_neigh_vni,
2443 show_evpn_neigh_vni_cmd,
2444 "show evpn arp-cache vni " CMD_VNI_RANGE,
2445 SHOW_STR
2446 "EVPN\n"
2447 "ARP and ND cache\n"
2448 "VxLAN Network Identifier\n"
2449 "VNI number\n")
2450{
d62a17ae 2451 struct zebra_vrf *zvrf;
2452 vni_t vni;
cec2e17d 2453
d62a17ae 2454 vni = strtoul(argv[4]->arg, NULL, 10);
2455 zvrf = vrf_info_lookup(VRF_DEFAULT);
2456 zebra_vxlan_print_neigh_vni(vty, zvrf, vni);
2457 return CMD_SUCCESS;
cec2e17d 2458}
2459
2460DEFUN (show_evpn_neigh_vni_all,
2461 show_evpn_neigh_vni_all_cmd,
2462 "show evpn arp-cache vni all",
2463 SHOW_STR
2464 "EVPN\n"
2465 "ARP and ND cache\n"
2466 "VxLAN Network Identifier\n"
2467 "All VNIs\n")
2468{
d62a17ae 2469 struct zebra_vrf *zvrf;
cec2e17d 2470
d62a17ae 2471 zvrf = vrf_info_lookup(VRF_DEFAULT);
2472 zebra_vxlan_print_neigh_all_vni(vty, zvrf);
2473 return CMD_SUCCESS;
cec2e17d 2474}
2475
2476DEFUN (show_evpn_neigh_vni_neigh,
2477 show_evpn_neigh_vni_neigh_cmd,
2478 "show evpn arp-cache vni " CMD_VNI_RANGE " ip WORD",
2479 SHOW_STR
2480 "EVPN\n"
2481 "ARP and ND cache\n"
2482 "VxLAN Network Identifier\n"
2483 "VNI number\n"
2484 "Neighbor\n"
2485 "Neighbor address (IPv4 or IPv6 address)\n")
2486{
d62a17ae 2487 struct zebra_vrf *zvrf;
2488 vni_t vni;
2489 struct ipaddr ip;
cec2e17d 2490
d62a17ae 2491 vni = strtoul(argv[4]->arg, NULL, 10);
2492 if (str2ipaddr(argv[6]->arg, &ip) != 0) {
2493 vty_out(vty, "%% Malformed Neighbor address\n");
2494 return CMD_WARNING;
2495 }
2496 zvrf = vrf_info_lookup(VRF_DEFAULT);
2497 zebra_vxlan_print_specific_neigh_vni(vty, zvrf, vni, &ip);
2498 return CMD_SUCCESS;
cec2e17d 2499}
2500
2501DEFUN (show_evpn_neigh_vni_vtep,
2502 show_evpn_neigh_vni_vtep_cmd,
2503 "show evpn arp-cache vni " CMD_VNI_RANGE " vtep A.B.C.D",
2504 SHOW_STR
2505 "EVPN\n"
2506 "ARP and ND cache\n"
2507 "VxLAN Network Identifier\n"
2508 "VNI number\n"
2509 "Remote VTEP\n"
2510 "Remote VTEP IP address\n")
2511{
d62a17ae 2512 struct zebra_vrf *zvrf;
2513 vni_t vni;
2514 struct in_addr vtep_ip;
cec2e17d 2515
d62a17ae 2516 vni = strtoul(argv[4]->arg, NULL, 10);
2517 if (!inet_aton(argv[6]->arg, &vtep_ip)) {
2518 vty_out(vty, "%% Malformed VTEP IP address\n");
2519 return CMD_WARNING;
2520 }
cec2e17d 2521
d62a17ae 2522 zvrf = vrf_info_lookup(VRF_DEFAULT);
2523 zebra_vxlan_print_neigh_vni_vtep(vty, zvrf, vni, vtep_ip);
2524 return CMD_SUCCESS;
cec2e17d 2525}
2526
718e3744 2527/* Static ip route configuration write function. */
d62a17ae 2528static int zebra_ip_config(struct vty *vty)
718e3744 2529{
d62a17ae 2530 int write = 0;
718e3744 2531
d62a17ae 2532 write += static_config(vty, AFI_IP, SAFI_UNICAST, "ip route");
2533 write += static_config(vty, AFI_IP, SAFI_MULTICAST, "ip mroute");
2534 write += static_config(vty, AFI_IP6, SAFI_UNICAST, "ipv6 route");
718e3744 2535
d62a17ae 2536 write += zebra_import_table_config(vty);
2537 return write;
718e3744 2538}
2539
7a4bb9c5
DS
2540DEFUN (ip_zebra_import_table_distance,
2541 ip_zebra_import_table_distance_cmd,
12dcf78e 2542 "ip import-table (1-252) [distance (1-255)] [route-map WORD]",
8902474b
DS
2543 IP_STR
2544 "import routes from non-main kernel table\n"
2545 "kernel routing table id\n"
2546 "Distance for imported routes\n"
2547 "Default distance value\n"
2548 "route-map for filtering\n"
2549 "route-map name\n")
2550{
d62a17ae 2551 u_int32_t table_id = 0;
8902474b 2552
d62a17ae 2553 table_id = strtoul(argv[2]->arg, NULL, 10);
2554 int distance = ZEBRA_TABLE_DISTANCE_DEFAULT;
2555 char *rmap =
2556 strmatch(argv[argc - 2]->text, "route-map")
2557 ? XSTRDUP(MTYPE_ROUTE_MAP_NAME, argv[argc - 1]->arg)
2558 : NULL;
2559 int ret;
d722f26e 2560
d62a17ae 2561 if (argc == 7 || (argc == 5 && !rmap))
2562 distance = strtoul(argv[4]->arg, NULL, 10);
8902474b 2563
d62a17ae 2564 if (!is_zebra_valid_kernel_table(table_id)) {
2565 vty_out(vty,
2566 "Invalid routing table ID, %d. Must be in range 1-252\n",
2567 table_id);
2568 return CMD_WARNING;
2569 }
8902474b 2570
d62a17ae 2571 if (is_zebra_main_routing_table(table_id)) {
2572 vty_out(vty,
2573 "Invalid routing table ID, %d. Must be non-default table\n",
2574 table_id);
2575 return CMD_WARNING;
2576 }
8902474b 2577
d62a17ae 2578 ret = zebra_import_table(AFI_IP, table_id, distance, rmap, 1);
2579 if (rmap)
2580 XFREE(MTYPE_ROUTE_MAP_NAME, rmap);
d722f26e 2581
d62a17ae 2582 return ret;
8902474b
DS
2583}
2584
7a4bb9c5
DS
2585DEFUN (no_ip_zebra_import_table,
2586 no_ip_zebra_import_table_cmd,
b62ecea5 2587 "no ip import-table (1-252) [distance (1-255)] [route-map NAME]",
7a4bb9c5
DS
2588 NO_STR
2589 IP_STR
2590 "import routes from non-main kernel table\n"
3a2d747c
QY
2591 "kernel routing table id\n"
2592 "Distance for imported routes\n"
2593 "Default distance value\n"
2594 "route-map for filtering\n"
2595 "route-map name\n")
7a4bb9c5 2596{
d62a17ae 2597 u_int32_t table_id = 0;
2598 table_id = strtoul(argv[3]->arg, NULL, 10);
7a4bb9c5 2599
d62a17ae 2600 if (!is_zebra_valid_kernel_table(table_id)) {
2601 vty_out(vty,
2602 "Invalid routing table ID. Must be in range 1-252\n");
2603 return CMD_WARNING;
2604 }
7a4bb9c5 2605
d62a17ae 2606 if (is_zebra_main_routing_table(table_id)) {
2607 vty_out(vty,
2608 "Invalid routing table ID, %d. Must be non-default table\n",
2609 table_id);
2610 return CMD_WARNING;
2611 }
7a4bb9c5 2612
d62a17ae 2613 if (!is_zebra_import_table_enabled(AFI_IP, table_id))
2614 return CMD_SUCCESS;
7a4bb9c5 2615
d62a17ae 2616 return (zebra_import_table(AFI_IP, table_id, 0, NULL, 0));
7a4bb9c5
DS
2617}
2618
d62a17ae 2619static int config_write_protocol(struct vty *vty)
6baf7bb8 2620{
d62a17ae 2621 if (allow_delete)
2622 vty_out(vty, "allow-external-route-update\n");
6baf7bb8 2623
d62a17ae 2624 if (zebra_rnh_ip_default_route)
2625 vty_out(vty, "ip nht resolve-via-default\n");
6baf7bb8 2626
d62a17ae 2627 if (zebra_rnh_ipv6_default_route)
2628 vty_out(vty, "ipv6 nht resolve-via-default\n");
6baf7bb8 2629
d62a17ae 2630 enum multicast_mode ipv4_multicast_mode = multicast_mode_ipv4_get();
4623d897 2631
d62a17ae 2632 if (ipv4_multicast_mode != MCAST_NO_CONFIG)
2633 vty_out(vty, "ip multicast rpf-lookup-mode %s\n",
2634 ipv4_multicast_mode == MCAST_URIB_ONLY
2635 ? "urib-only"
2636 : ipv4_multicast_mode == MCAST_MRIB_ONLY
2637 ? "mrib-only"
2638 : ipv4_multicast_mode
2639 == MCAST_MIX_MRIB_FIRST
2640 ? "mrib-then-urib"
2641 : ipv4_multicast_mode
2642 == MCAST_MIX_DISTANCE
2643 ? "lower-distance"
2644 : "longer-prefix");
4623d897 2645
d62a17ae 2646 zebra_routemap_config_write_protocol(vty);
6baf7bb8 2647
d62a17ae 2648 return 1;
6baf7bb8
DS
2649}
2650
718e3744 2651/* IP node for static routes. */
d62a17ae 2652static struct cmd_node ip_node = {IP_NODE, "", 1};
2653static struct cmd_node protocol_node = {PROTOCOL_NODE, "", 1};
718e3744 2654
2655/* Route VTY. */
d62a17ae 2656void zebra_vty_init(void)
2657{
2658 install_node(&ip_node, zebra_ip_config);
2659 install_node(&protocol_node, config_write_protocol);
2660
2661 install_element(CONFIG_NODE, &allow_external_route_update_cmd);
2662 install_element(CONFIG_NODE, &no_allow_external_route_update_cmd);
2663 install_element(CONFIG_NODE, &ip_mroute_dist_cmd);
d62a17ae 2664 install_element(CONFIG_NODE, &ip_multicast_mode_cmd);
2665 install_element(CONFIG_NODE, &no_ip_multicast_mode_cmd);
2666 install_element(CONFIG_NODE, &ip_route_cmd);
d62a17ae 2667 install_element(CONFIG_NODE, &ip_zebra_import_table_distance_cmd);
2668 install_element(CONFIG_NODE, &no_ip_zebra_import_table_cmd);
2669
2670 install_element(VIEW_NODE, &show_vrf_cmd);
2671 install_element(VIEW_NODE, &show_ip_route_cmd);
2672 install_element(VIEW_NODE, &show_ip_nht_cmd);
2673 install_element(VIEW_NODE, &show_ip_nht_vrf_all_cmd);
2674 install_element(VIEW_NODE, &show_ipv6_nht_cmd);
2675 install_element(VIEW_NODE, &show_ipv6_nht_vrf_all_cmd);
2676 install_element(VIEW_NODE, &show_ip_route_addr_cmd);
2677 install_element(VIEW_NODE, &show_ip_route_prefix_cmd);
2678 install_element(VIEW_NODE, &show_ip_route_summary_cmd);
2679 install_element(VIEW_NODE, &show_ip_route_summary_prefix_cmd);
2680
2681 install_element(VIEW_NODE, &show_ip_rpf_cmd);
2682 install_element(VIEW_NODE, &show_ip_rpf_addr_cmd);
2683
d62a17ae 2684 install_element(VIEW_NODE, &show_ip_route_vrf_all_addr_cmd);
2685 install_element(VIEW_NODE, &show_ip_route_vrf_all_prefix_cmd);
2686 install_element(VIEW_NODE, &show_ip_route_vrf_all_summary_cmd);
2687 install_element(VIEW_NODE, &show_ip_route_vrf_all_summary_prefix_cmd);
2688
2689 install_element(CONFIG_NODE, &ipv6_route_cmd);
d62a17ae 2690 install_element(CONFIG_NODE, &ip_nht_default_route_cmd);
2691 install_element(CONFIG_NODE, &no_ip_nht_default_route_cmd);
2692 install_element(CONFIG_NODE, &ipv6_nht_default_route_cmd);
2693 install_element(CONFIG_NODE, &no_ipv6_nht_default_route_cmd);
2694 install_element(VIEW_NODE, &show_ipv6_route_cmd);
2695 install_element(VIEW_NODE, &show_ipv6_route_summary_cmd);
2696 install_element(VIEW_NODE, &show_ipv6_route_summary_prefix_cmd);
2697 install_element(VIEW_NODE, &show_ipv6_route_addr_cmd);
2698 install_element(VIEW_NODE, &show_ipv6_route_prefix_cmd);
2699 install_element(VIEW_NODE, &show_ipv6_mroute_cmd);
2700
2701 /* Commands for VRF */
2702 install_element(VIEW_NODE, &show_ipv6_route_vrf_all_summary_cmd);
2703 install_element(VIEW_NODE, &show_ipv6_route_vrf_all_summary_prefix_cmd);
2704 install_element(VIEW_NODE, &show_ipv6_route_vrf_all_addr_cmd);
2705 install_element(VIEW_NODE, &show_ipv6_route_vrf_all_prefix_cmd);
2706
2707 install_element(VIEW_NODE, &show_ipv6_mroute_vrf_all_cmd);
2708
2709 install_element(VIEW_NODE, &show_evpn_vni_cmd);
2710 install_element(VIEW_NODE, &show_evpn_vni_vni_cmd);
2711 install_element(VIEW_NODE, &show_evpn_mac_vni_cmd);
2712 install_element(VIEW_NODE, &show_evpn_mac_vni_all_cmd);
2713 install_element(VIEW_NODE, &show_evpn_mac_vni_all_vtep_cmd);
2714 install_element(VIEW_NODE, &show_evpn_mac_vni_mac_cmd);
2715 install_element(VIEW_NODE, &show_evpn_mac_vni_vtep_cmd);
2716 install_element(VIEW_NODE, &show_evpn_neigh_vni_cmd);
2717 install_element(VIEW_NODE, &show_evpn_neigh_vni_all_cmd);
2718 install_element(VIEW_NODE, &show_evpn_neigh_vni_neigh_cmd);
2719 install_element(VIEW_NODE, &show_evpn_neigh_vni_vtep_cmd);
718e3744 2720}