]> git.proxmox.com Git - mirror_frr.git/blob - eigrpd/eigrp_vty.c
tools: improve explanation of 'wrap' options
[mirror_frr.git] / eigrpd / eigrp_vty.c
1 /*
2 * EIGRP VTY Interface.
3 * Copyright (C) 2013-2016
4 * Authors:
5 * Donnie Savage
6 * Jan Janovic
7 * Matej Perina
8 * Peter Orsag
9 * Peter Paluch
10 * Frantisek Gazo
11 * Tomas Hvorkovy
12 * Martin Kontsek
13 * Lukas Koribsky
14 *
15 * This file is part of GNU Zebra.
16 *
17 * GNU Zebra is free software; you can redistribute it and/or modify it
18 * under the terms of the GNU General Public License as published by the
19 * Free Software Foundation; either version 2, or (at your option) any
20 * later version.
21 *
22 * GNU Zebra is distributed in the hope that it will be useful, but
23 * WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
25 * General Public License for more details.
26 *
27 * You should have received a copy of the GNU General Public License along
28 * with this program; see the file COPYING; if not, write to the Free Software
29 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
30 */
31
32 #include <zebra.h>
33
34 #include "memory.h"
35 #include "thread.h"
36 #include "prefix.h"
37 #include "table.h"
38 #include "vty.h"
39 #include "command.h"
40 #include "plist.h"
41 #include "log.h"
42 #include "zclient.h"
43 #include "keychain.h"
44 #include "linklist.h"
45 #include "distribute.h"
46
47 #include "eigrpd/eigrp_structs.h"
48 #include "eigrpd/eigrpd.h"
49 #include "eigrpd/eigrp_interface.h"
50 #include "eigrpd/eigrp_neighbor.h"
51 #include "eigrpd/eigrp_packet.h"
52 #include "eigrpd/eigrp_zebra.h"
53 #include "eigrpd/eigrp_vty.h"
54 #include "eigrpd/eigrp_network.h"
55 #include "eigrpd/eigrp_dump.h"
56 #include "eigrpd/eigrp_const.h"
57
58 #ifndef VTYSH_EXTRACT_PL
59 #include "eigrpd/eigrp_vty_clippy.c"
60 #endif
61
62 static void eigrp_vty_display_prefix_entry(struct vty *vty, struct eigrp *eigrp,
63 struct eigrp_prefix_descriptor *pe,
64 bool all)
65 {
66 bool first = true;
67 struct eigrp_route_descriptor *te;
68 struct listnode *node;
69
70 for (ALL_LIST_ELEMENTS_RO(pe->entries, node, te)) {
71 if (all
72 || (((te->flags & EIGRP_ROUTE_DESCRIPTOR_SUCCESSOR_FLAG)
73 == EIGRP_ROUTE_DESCRIPTOR_SUCCESSOR_FLAG)
74 || ((te->flags & EIGRP_ROUTE_DESCRIPTOR_FSUCCESSOR_FLAG)
75 == EIGRP_ROUTE_DESCRIPTOR_FSUCCESSOR_FLAG))) {
76 show_ip_eigrp_route_descriptor(vty, eigrp, te, &first);
77 first = false;
78 }
79 }
80 }
81
82 static struct eigrp *eigrp_vty_get_eigrp(struct vty *vty, const char *vrf_name)
83 {
84 struct vrf *vrf;
85
86 if (vrf_name)
87 vrf = vrf_lookup_by_name(vrf_name);
88 else
89 vrf = vrf_lookup_by_id(VRF_DEFAULT);
90
91 if (!vrf) {
92 vty_out(vty, "VRF %s specified does not exist",
93 vrf_name ? vrf_name : VRF_DEFAULT_NAME);
94 return NULL;
95 }
96
97 return eigrp_lookup(vrf->vrf_id);
98 }
99
100 static void eigrp_topology_helper(struct vty *vty, struct eigrp *eigrp,
101 const char *all)
102 {
103 struct eigrp_prefix_descriptor *tn;
104 struct route_node *rn;
105
106 show_ip_eigrp_topology_header(vty, eigrp);
107
108 for (rn = route_top(eigrp->topology_table); rn; rn = route_next(rn)) {
109 if (!rn->info)
110 continue;
111
112 tn = rn->info;
113 eigrp_vty_display_prefix_entry(vty, eigrp, tn,
114 all ? true : false);
115 }
116 }
117
118 DEFPY (show_ip_eigrp_topology_all,
119 show_ip_eigrp_topology_all_cmd,
120 "show ip eigrp [vrf NAME] topology [all-links$all]",
121 SHOW_STR
122 IP_STR
123 "IP-EIGRP show commands\n"
124 VRF_CMD_HELP_STR
125 "IP-EIGRP topology\n"
126 "Show all links in topology table\n")
127 {
128 struct eigrp *eigrp;
129
130 if (vrf && strncmp(vrf, "all", sizeof("all")) == 0) {
131 struct vrf *v;
132
133 RB_FOREACH (v, vrf_name_head, &vrfs_by_name) {
134 eigrp = eigrp_lookup(v->vrf_id);
135 if (!eigrp)
136 continue;
137
138 vty_out(vty, "VRF %s:\n", v->name);
139
140 eigrp_topology_helper(vty, eigrp, all);
141 }
142 } else {
143 eigrp = eigrp_vty_get_eigrp(vty, vrf);
144 if (eigrp == NULL) {
145 vty_out(vty, " EIGRP Routing Process not enabled\n");
146 return CMD_SUCCESS;
147 }
148
149 eigrp_topology_helper(vty, eigrp, all);
150 }
151
152 return CMD_SUCCESS;
153 }
154
155 DEFPY (show_ip_eigrp_topology,
156 show_ip_eigrp_topology_cmd,
157 "show ip eigrp [vrf NAME] topology <A.B.C.D$address|A.B.C.D/M$prefix>",
158 SHOW_STR
159 IP_STR
160 "IP-EIGRP show commands\n"
161 VRF_CMD_HELP_STR
162 "IP-EIGRP topology\n"
163 "For a specific address\n"
164 "For a specific prefix\n")
165 {
166 struct eigrp *eigrp;
167 struct eigrp_prefix_descriptor *tn;
168 struct route_node *rn;
169 struct prefix cmp;
170
171 if (vrf && strncmp(vrf, "all", sizeof("all")) == 0) {
172 vty_out(vty, "Specifying vrf `all` for a particular address/prefix makes no sense\n");
173 return CMD_SUCCESS;
174 }
175
176 eigrp = eigrp_vty_get_eigrp(vty, vrf);
177 if (eigrp == NULL) {
178 vty_out(vty, " EIGRP Routing Process not enabled\n");
179 return CMD_SUCCESS;
180 }
181
182 show_ip_eigrp_topology_header(vty, eigrp);
183
184 if (address_str)
185 prefix_str = address_str;
186
187 if (str2prefix(prefix_str, &cmp) < 0) {
188 vty_out(vty, "%% Malformed address\n");
189 return CMD_WARNING;
190 }
191
192 rn = route_node_match(eigrp->topology_table, &cmp);
193 if (!rn) {
194 vty_out(vty, "%% Network not in table\n");
195 return CMD_WARNING;
196 }
197
198 if (!rn->info) {
199 vty_out(vty, "%% Network not in table\n");
200 route_unlock_node(rn);
201 return CMD_WARNING;
202 }
203
204 tn = rn->info;
205 eigrp_vty_display_prefix_entry(vty, eigrp, tn, argc == 5);
206
207 route_unlock_node(rn);
208 return CMD_SUCCESS;
209 }
210
211 static void eigrp_interface_helper(struct vty *vty, struct eigrp *eigrp,
212 const char *ifname, const char *detail)
213 {
214 struct eigrp_interface *ei;
215 struct listnode *node;
216
217 if (!ifname)
218 show_ip_eigrp_interface_header(vty, eigrp);
219
220 for (ALL_LIST_ELEMENTS_RO(eigrp->eiflist, node, ei)) {
221 if (!ifname || strcmp(ei->ifp->name, ifname) == 0) {
222 show_ip_eigrp_interface_sub(vty, eigrp, ei);
223 if (detail)
224 show_ip_eigrp_interface_detail(vty, eigrp, ei);
225 }
226 }
227 }
228
229 DEFPY (show_ip_eigrp_interfaces,
230 show_ip_eigrp_interfaces_cmd,
231 "show ip eigrp [vrf NAME] interfaces [IFNAME] [detail]$detail",
232 SHOW_STR
233 IP_STR
234 "IP-EIGRP show commands\n"
235 VRF_CMD_HELP_STR
236 "IP-EIGRP interfaces\n"
237 "Interface name to look at\n"
238 "Detailed information\n")
239 {
240 struct eigrp *eigrp;
241
242 if (vrf && strncmp(vrf, "all", sizeof("all")) == 0) {
243 struct vrf *vrf;
244
245 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
246 eigrp = eigrp_lookup(vrf->vrf_id);
247 if (!eigrp)
248 continue;
249
250 vty_out(vty, "VRF %s:\n", vrf->name);
251
252 eigrp_interface_helper(vty, eigrp, ifname, detail);
253 }
254 } else {
255 eigrp = eigrp_vty_get_eigrp(vty, vrf);
256 if (eigrp == NULL) {
257 vty_out(vty, "EIGRP Routing Process not enabled\n");
258 return CMD_SUCCESS;
259 }
260
261 eigrp_interface_helper(vty, eigrp, ifname, detail);
262 }
263
264
265 return CMD_SUCCESS;
266 }
267
268 static void eigrp_neighbors_helper(struct vty *vty, struct eigrp *eigrp,
269 const char *ifname, const char *detail)
270 {
271 struct eigrp_interface *ei;
272 struct listnode *node, *node2, *nnode2;
273 struct eigrp_neighbor *nbr;
274
275 show_ip_eigrp_neighbor_header(vty, eigrp);
276
277 for (ALL_LIST_ELEMENTS_RO(eigrp->eiflist, node, ei)) {
278 if (!ifname || strcmp(ei->ifp->name, ifname) == 0) {
279 for (ALL_LIST_ELEMENTS(ei->nbrs, node2, nnode2, nbr)) {
280 if (detail || (nbr->state == EIGRP_NEIGHBOR_UP))
281 show_ip_eigrp_neighbor_sub(vty, nbr,
282 !!detail);
283 }
284 }
285 }
286 }
287
288 DEFPY (show_ip_eigrp_neighbors,
289 show_ip_eigrp_neighbors_cmd,
290 "show ip eigrp [vrf NAME] neighbors [IFNAME] [detail]$detail",
291 SHOW_STR
292 IP_STR
293 "IP-EIGRP show commands\n"
294 VRF_CMD_HELP_STR
295 "IP-EIGRP neighbors\n"
296 "Interface to show on\n"
297 "Detailed Information\n")
298 {
299 struct eigrp *eigrp;
300
301 if (vrf && strncmp(vrf, "all", sizeof("all")) == 0) {
302 struct vrf *vrf;
303
304 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
305 eigrp = eigrp_lookup(vrf->vrf_id);
306 if (!eigrp)
307 continue;
308
309 vty_out(vty, "VRF %s:\n", vrf->name);
310
311 eigrp_neighbors_helper(vty, eigrp, ifname, detail);
312 }
313 } else {
314 eigrp = eigrp_vty_get_eigrp(vty, vrf);
315 if (eigrp == NULL) {
316 vty_out(vty, " EIGRP Routing Process not enabled\n");
317 return CMD_SUCCESS;
318 }
319
320 eigrp_neighbors_helper(vty, eigrp, ifname, detail);
321 }
322
323 return CMD_SUCCESS;
324 }
325
326 /*
327 * Execute hard restart for all neighbors
328 */
329 DEFPY (clear_ip_eigrp_neighbors,
330 clear_ip_eigrp_neighbors_cmd,
331 "clear ip eigrp [vrf NAME] neighbors",
332 CLEAR_STR
333 IP_STR
334 "Clear IP-EIGRP\n"
335 VRF_CMD_HELP_STR
336 "Clear IP-EIGRP neighbors\n")
337 {
338 struct eigrp *eigrp;
339 struct eigrp_interface *ei;
340 struct listnode *node, *node2, *nnode2;
341 struct eigrp_neighbor *nbr;
342
343 /* Check if eigrp process is enabled */
344 eigrp = eigrp_vty_get_eigrp(vty, vrf);
345 if (eigrp == NULL) {
346 vty_out(vty, " EIGRP Routing Process not enabled\n");
347 return CMD_SUCCESS;
348 }
349
350 /* iterate over all eigrp interfaces */
351 for (ALL_LIST_ELEMENTS_RO(eigrp->eiflist, node, ei)) {
352 /* send Goodbye Hello */
353 eigrp_hello_send(ei, EIGRP_HELLO_GRACEFUL_SHUTDOWN, NULL);
354
355 /* iterate over all neighbors on eigrp interface */
356 for (ALL_LIST_ELEMENTS(ei->nbrs, node2, nnode2, nbr)) {
357 if (nbr->state != EIGRP_NEIGHBOR_DOWN) {
358 zlog_debug(
359 "Neighbor %pI4 (%s) is down: manually cleared",
360 &nbr->src,
361 ifindex2ifname(nbr->ei->ifp->ifindex,
362 eigrp->vrf_id));
363 vty_time_print(vty, 0);
364 vty_out(vty,
365 "Neighbor %pI4 (%s) is down: manually cleared\n",
366 &nbr->src,
367 ifindex2ifname(nbr->ei->ifp->ifindex,
368 eigrp->vrf_id));
369
370 /* set neighbor to DOWN */
371 nbr->state = EIGRP_NEIGHBOR_DOWN;
372 /* delete neighbor */
373 eigrp_nbr_delete(nbr);
374 }
375 }
376 }
377
378 return CMD_SUCCESS;
379 }
380
381 /*
382 * Execute hard restart for all neighbors on interface
383 */
384 DEFPY (clear_ip_eigrp_neighbors_int,
385 clear_ip_eigrp_neighbors_int_cmd,
386 "clear ip eigrp [vrf NAME] neighbors IFNAME",
387 CLEAR_STR
388 IP_STR
389 "Clear IP-EIGRP\n"
390 VRF_CMD_HELP_STR
391 "Clear IP-EIGRP neighbors\n"
392 "Interface's name\n")
393 {
394 struct eigrp *eigrp;
395 struct eigrp_interface *ei;
396 struct listnode *node2, *nnode2;
397 struct eigrp_neighbor *nbr;
398
399 /* Check if eigrp process is enabled */
400 eigrp = eigrp_vty_get_eigrp(vty, vrf);
401 if (eigrp == NULL) {
402 vty_out(vty, " EIGRP Routing Process not enabled\n");
403 return CMD_SUCCESS;
404 }
405
406 /* lookup interface by specified name */
407 ei = eigrp_if_lookup_by_name(eigrp, ifname);
408 if (ei == NULL) {
409 vty_out(vty, " Interface (%s) doesn't exist\n", ifname);
410 return CMD_WARNING;
411 }
412
413 /* send Goodbye Hello */
414 eigrp_hello_send(ei, EIGRP_HELLO_GRACEFUL_SHUTDOWN, NULL);
415
416 /* iterate over all neighbors on eigrp interface */
417 for (ALL_LIST_ELEMENTS(ei->nbrs, node2, nnode2, nbr)) {
418 if (nbr->state != EIGRP_NEIGHBOR_DOWN) {
419 zlog_debug(
420 "Neighbor %pI4 (%s) is down: manually cleared",
421 &nbr->src,
422 ifindex2ifname(nbr->ei->ifp->ifindex,
423 eigrp->vrf_id));
424 vty_time_print(vty, 0);
425 vty_out(vty,
426 "Neighbor %pI4 (%s) is down: manually cleared\n",
427 &nbr->src,
428 ifindex2ifname(nbr->ei->ifp->ifindex,
429 eigrp->vrf_id));
430
431 /* set neighbor to DOWN */
432 nbr->state = EIGRP_NEIGHBOR_DOWN;
433 /* delete neighbor */
434 eigrp_nbr_delete(nbr);
435 }
436 }
437
438 return CMD_SUCCESS;
439 }
440
441 /*
442 * Execute hard restart for neighbor specified by IP
443 */
444 DEFPY (clear_ip_eigrp_neighbors_IP,
445 clear_ip_eigrp_neighbors_IP_cmd,
446 "clear ip eigrp [vrf NAME] neighbors A.B.C.D$nbr_addr",
447 CLEAR_STR
448 IP_STR
449 "Clear IP-EIGRP\n"
450 VRF_CMD_HELP_STR
451 "Clear IP-EIGRP neighbors\n"
452 "IP-EIGRP neighbor address\n")
453 {
454 struct eigrp *eigrp;
455 struct eigrp_neighbor *nbr;
456
457 /* Check if eigrp process is enabled */
458 eigrp = eigrp_vty_get_eigrp(vty, vrf);
459 if (eigrp == NULL) {
460 vty_out(vty, " EIGRP Routing Process not enabled\n");
461 return CMD_SUCCESS;
462 }
463
464 /* lookup neighbor in whole process */
465 nbr = eigrp_nbr_lookup_by_addr_process(eigrp, nbr_addr);
466
467 /* if neighbor doesn't exists, notify user and exit */
468 if (nbr == NULL) {
469 vty_out(vty, "Neighbor with entered address doesn't exists.\n");
470 return CMD_WARNING;
471 }
472
473 /* execute hard reset on neighbor */
474 eigrp_nbr_hard_restart(nbr, vty);
475
476 return CMD_SUCCESS;
477 }
478
479 /*
480 * Execute graceful restart for all neighbors
481 */
482 DEFPY (clear_ip_eigrp_neighbors_soft,
483 clear_ip_eigrp_neighbors_soft_cmd,
484 "clear ip eigrp [vrf NAME] neighbors soft",
485 CLEAR_STR
486 IP_STR
487 "Clear IP-EIGRP\n"
488 VRF_CMD_HELP_STR
489 "Clear IP-EIGRP neighbors\n"
490 "Resync with peers without adjacency reset\n")
491 {
492 struct eigrp *eigrp;
493
494 /* Check if eigrp process is enabled */
495 eigrp = eigrp_vty_get_eigrp(vty, vrf);
496 if (eigrp == NULL) {
497 vty_out(vty, " EIGRP Routing Process not enabled\n");
498 return CMD_SUCCESS;
499 }
500
501 /* execute graceful restart on all neighbors */
502 eigrp_update_send_process_GR(eigrp, EIGRP_GR_MANUAL, vty);
503
504 return CMD_SUCCESS;
505 }
506
507 /*
508 * Execute graceful restart for all neighbors on interface
509 */
510 DEFPY (clear_ip_eigrp_neighbors_int_soft,
511 clear_ip_eigrp_neighbors_int_soft_cmd,
512 "clear ip eigrp [vrf NAME] neighbors IFNAME soft",
513 CLEAR_STR
514 IP_STR
515 "Clear IP-EIGRP\n"
516 VRF_CMD_HELP_STR
517 "Clear IP-EIGRP neighbors\n"
518 "Interface's name\n"
519 "Resync with peer without adjacency reset\n")
520 {
521 struct eigrp *eigrp;
522 struct eigrp_interface *ei;
523
524 /* Check if eigrp process is enabled */
525 eigrp = eigrp_vty_get_eigrp(vty, vrf);
526 if (eigrp == NULL) {
527 vty_out(vty, " EIGRP Routing Process not enabled\n");
528 return CMD_SUCCESS;
529 }
530
531 /* lookup interface by specified name */
532 ei = eigrp_if_lookup_by_name(eigrp, ifname);
533 if (ei == NULL) {
534 vty_out(vty, " Interface (%s) doesn't exist\n", argv[4]->arg);
535 return CMD_WARNING;
536 }
537
538 /* execute graceful restart for all neighbors on interface */
539 eigrp_update_send_interface_GR(ei, EIGRP_GR_MANUAL, vty);
540 return CMD_SUCCESS;
541 }
542
543 /*
544 * Execute graceful restart for neighbor specified by IP
545 */
546 DEFPY (clear_ip_eigrp_neighbors_IP_soft,
547 clear_ip_eigrp_neighbors_IP_soft_cmd,
548 "clear ip eigrp [vrf NAME] neighbors A.B.C.D$nbr_addr soft",
549 CLEAR_STR
550 IP_STR
551 "Clear IP-EIGRP\n"
552 VRF_CMD_HELP_STR
553 "Clear IP-EIGRP neighbors\n"
554 "IP-EIGRP neighbor address\n"
555 "Resync with peer without adjacency reset\n")
556 {
557 struct eigrp *eigrp;
558 struct eigrp_neighbor *nbr;
559
560
561 /* Check if eigrp process is enabled */
562 eigrp = eigrp_vty_get_eigrp(vty, vrf);
563 if (eigrp == NULL) {
564 vty_out(vty, " EIGRP Routing Process not enabled\n");
565 return CMD_SUCCESS;
566 }
567
568 /* lookup neighbor in whole process */
569 nbr = eigrp_nbr_lookup_by_addr_process(eigrp, nbr_addr);
570
571 /* if neighbor doesn't exists, notify user and exit */
572 if (nbr == NULL) {
573 vty_out(vty, "Neighbor with entered address doesn't exists.\n");
574 return CMD_WARNING;
575 }
576
577 /* execute graceful restart on neighbor */
578 eigrp_update_send_GR(nbr, EIGRP_GR_MANUAL, vty);
579
580 return CMD_SUCCESS;
581 }
582
583 void eigrp_vty_show_init(void)
584 {
585 install_element(VIEW_NODE, &show_ip_eigrp_interfaces_cmd);
586
587 install_element(VIEW_NODE, &show_ip_eigrp_neighbors_cmd);
588
589 install_element(VIEW_NODE, &show_ip_eigrp_topology_cmd);
590 install_element(VIEW_NODE, &show_ip_eigrp_topology_all_cmd);
591 }
592
593 /* Install EIGRP related vty commands. */
594 void eigrp_vty_init(void)
595 {
596 /* commands for manual hard restart */
597 install_element(ENABLE_NODE, &clear_ip_eigrp_neighbors_cmd);
598 install_element(ENABLE_NODE, &clear_ip_eigrp_neighbors_int_cmd);
599 install_element(ENABLE_NODE, &clear_ip_eigrp_neighbors_IP_cmd);
600 /* commands for manual graceful restart */
601 install_element(ENABLE_NODE, &clear_ip_eigrp_neighbors_soft_cmd);
602 install_element(ENABLE_NODE, &clear_ip_eigrp_neighbors_int_soft_cmd);
603 install_element(ENABLE_NODE, &clear_ip_eigrp_neighbors_IP_soft_cmd);
604 }