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