]> git.proxmox.com Git - mirror_frr.git/blob - eigrpd/eigrp_vty.c
Merge pull request #7137 from kssoman/ospf
[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,
63 struct eigrp *eigrp,
64 struct eigrp_prefix_entry *pe,
65 bool all)
66 {
67 bool first = true;
68 struct eigrp_nexthop_entry *te;
69 struct listnode *node;
70
71 for (ALL_LIST_ELEMENTS_RO(pe->entries, node, te)) {
72 if (all
73 || (((te->flags
74 & EIGRP_NEXTHOP_ENTRY_SUCCESSOR_FLAG)
75 == EIGRP_NEXTHOP_ENTRY_SUCCESSOR_FLAG)
76 || ((te->flags
77 & EIGRP_NEXTHOP_ENTRY_FSUCCESSOR_FLAG)
78 == EIGRP_NEXTHOP_ENTRY_FSUCCESSOR_FLAG))) {
79 show_ip_eigrp_nexthop_entry(vty, eigrp, te,
80 &first);
81 first = false;
82 }
83 }
84 }
85
86 static struct eigrp *eigrp_vty_get_eigrp(struct vty *vty, const char *vrf_name)
87 {
88 struct vrf *vrf;
89
90 if (vrf_name)
91 vrf = vrf_lookup_by_name(vrf_name);
92 else
93 vrf = vrf_lookup_by_id(VRF_DEFAULT);
94
95 if (!vrf) {
96 vty_out(vty, "VRF %s specified does not exist",
97 vrf_name ? vrf_name : VRF_DEFAULT_NAME);
98 return NULL;
99 }
100
101 return eigrp_lookup(vrf->vrf_id);
102 }
103
104 static void eigrp_topology_helper(struct vty *vty, struct eigrp *eigrp,
105 const char *all)
106 {
107 struct eigrp_prefix_entry *tn;
108 struct route_node *rn;
109
110 show_ip_eigrp_topology_header(vty, eigrp);
111
112 for (rn = route_top(eigrp->topology_table); rn; rn = route_next(rn)) {
113 if (!rn->info)
114 continue;
115
116 tn = rn->info;
117 eigrp_vty_display_prefix_entry(vty, eigrp, tn,
118 all ? true : false);
119 }
120 }
121
122 DEFPY (show_ip_eigrp_topology_all,
123 show_ip_eigrp_topology_all_cmd,
124 "show ip eigrp [vrf NAME] topology [all-links$all]",
125 SHOW_STR
126 IP_STR
127 "IP-EIGRP show commands\n"
128 VRF_CMD_HELP_STR
129 "IP-EIGRP topology\n"
130 "Show all links in topology table\n")
131 {
132 struct eigrp *eigrp;
133
134 if (vrf && strncmp(vrf, "all", sizeof("all")) == 0) {
135 struct vrf *v;
136
137 RB_FOREACH (v, vrf_name_head, &vrfs_by_name) {
138 eigrp = eigrp_lookup(v->vrf_id);
139 if (!eigrp)
140 continue;
141
142 vty_out(vty, "VRF %s:\n", v->name);
143
144 eigrp_topology_helper(vty, eigrp, all);
145 }
146 } else {
147 eigrp = eigrp_vty_get_eigrp(vty, vrf);
148 if (eigrp == NULL) {
149 vty_out(vty, " EIGRP Routing Process not enabled\n");
150 return CMD_SUCCESS;
151 }
152
153 eigrp_topology_helper(vty, eigrp, all);
154 }
155
156 return CMD_SUCCESS;
157 }
158
159 DEFPY (show_ip_eigrp_topology,
160 show_ip_eigrp_topology_cmd,
161 "show ip eigrp [vrf NAME] topology <A.B.C.D$address|A.B.C.D/M$prefix>",
162 SHOW_STR
163 IP_STR
164 "IP-EIGRP show commands\n"
165 VRF_CMD_HELP_STR
166 "IP-EIGRP topology\n"
167 "For a specific address\n"
168 "For a specific prefix\n")
169 {
170 struct eigrp *eigrp;
171 struct eigrp_prefix_entry *tn;
172 struct route_node *rn;
173 struct prefix cmp;
174
175 if (vrf && strncmp(vrf, "all", sizeof("all")) == 0) {
176 vty_out(vty, "Specifying vrf `all` for a particular address/prefix makes no sense\n");
177 return CMD_SUCCESS;
178 }
179
180 eigrp = eigrp_vty_get_eigrp(vty, vrf);
181 if (eigrp == NULL) {
182 vty_out(vty, " EIGRP Routing Process not enabled\n");
183 return CMD_SUCCESS;
184 }
185
186 show_ip_eigrp_topology_header(vty, eigrp);
187
188 if (address_str)
189 prefix_str = address_str;
190
191 if (str2prefix(prefix_str, &cmp) < 0) {
192 vty_out(vty, "%% Malformed address\n");
193 return CMD_WARNING;
194 }
195
196 rn = route_node_match(eigrp->topology_table, &cmp);
197 if (!rn) {
198 vty_out(vty, "%% Network not in table\n");
199 return CMD_WARNING;
200 }
201
202 if (!rn->info) {
203 vty_out(vty, "%% Network not in table\n");
204 route_unlock_node(rn);
205 return CMD_WARNING;
206 }
207
208 tn = rn->info;
209 eigrp_vty_display_prefix_entry(vty, eigrp, tn, argc == 5);
210
211 route_unlock_node(rn);
212 return CMD_SUCCESS;
213 }
214
215 static void eigrp_interface_helper(struct vty *vty, struct eigrp *eigrp,
216 const char *ifname, const char *detail)
217 {
218 struct eigrp_interface *ei;
219 struct listnode *node;
220
221 if (!ifname)
222 show_ip_eigrp_interface_header(vty, eigrp);
223
224 for (ALL_LIST_ELEMENTS_RO(eigrp->eiflist, node, ei)) {
225 if (!ifname || strcmp(ei->ifp->name, ifname) == 0) {
226 show_ip_eigrp_interface_sub(vty, eigrp, ei);
227 if (detail)
228 show_ip_eigrp_interface_detail(vty, eigrp, ei);
229 }
230 }
231 }
232
233 DEFPY (show_ip_eigrp_interfaces,
234 show_ip_eigrp_interfaces_cmd,
235 "show ip eigrp [vrf NAME] interfaces [IFNAME] [detail]$detail",
236 SHOW_STR
237 IP_STR
238 "IP-EIGRP show commands\n"
239 VRF_CMD_HELP_STR
240 "IP-EIGRP interfaces\n"
241 "Interface name to look at\n"
242 "Detailed information\n")
243 {
244 struct eigrp *eigrp;
245
246 if (vrf && strncmp(vrf, "all", sizeof("all")) == 0) {
247 struct vrf *vrf;
248
249 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
250 eigrp = eigrp_lookup(vrf->vrf_id);
251 if (!eigrp)
252 continue;
253
254 vty_out(vty, "VRF %s:\n", vrf->name);
255
256 eigrp_interface_helper(vty, eigrp, ifname, detail);
257 }
258 } else {
259 eigrp = eigrp_vty_get_eigrp(vty, vrf);
260 if (eigrp == NULL) {
261 vty_out(vty, "EIGRP Routing Process not enabled\n");
262 return CMD_SUCCESS;
263 }
264
265 eigrp_interface_helper(vty, eigrp, ifname, detail);
266 }
267
268
269 return CMD_SUCCESS;
270 }
271
272 static void eigrp_neighbors_helper(struct vty *vty, struct eigrp *eigrp,
273 const char *ifname, const char *detail)
274 {
275 struct eigrp_interface *ei;
276 struct listnode *node, *node2, *nnode2;
277 struct eigrp_neighbor *nbr;
278
279 show_ip_eigrp_neighbor_header(vty, eigrp);
280
281 for (ALL_LIST_ELEMENTS_RO(eigrp->eiflist, node, ei)) {
282 if (!ifname || strcmp(ei->ifp->name, ifname) == 0) {
283 for (ALL_LIST_ELEMENTS(ei->nbrs, node2, nnode2, nbr)) {
284 if (detail || (nbr->state == EIGRP_NEIGHBOR_UP))
285 show_ip_eigrp_neighbor_sub(vty, nbr,
286 !!detail);
287 }
288 }
289 }
290 }
291
292 DEFPY (show_ip_eigrp_neighbors,
293 show_ip_eigrp_neighbors_cmd,
294 "show ip eigrp [vrf NAME] neighbors [IFNAME] [detail]$detail",
295 SHOW_STR
296 IP_STR
297 "IP-EIGRP show commands\n"
298 VRF_CMD_HELP_STR
299 "IP-EIGRP neighbors\n"
300 "Interface to show on\n"
301 "Detailed Information\n")
302 {
303 struct eigrp *eigrp;
304
305 if (vrf && strncmp(vrf, "all", sizeof("all")) == 0) {
306 struct vrf *vrf;
307
308 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
309 eigrp = eigrp_lookup(vrf->vrf_id);
310 if (!eigrp)
311 continue;
312
313 vty_out(vty, "VRF %s:\n", vrf->name);
314
315 eigrp_neighbors_helper(vty, eigrp, ifname, detail);
316 }
317 } else {
318 eigrp = eigrp_vty_get_eigrp(vty, vrf);
319 if (eigrp == NULL) {
320 vty_out(vty, " EIGRP Routing Process not enabled\n");
321 return CMD_SUCCESS;
322 }
323
324 eigrp_neighbors_helper(vty, eigrp, ifname, detail);
325 }
326
327 return CMD_SUCCESS;
328 }
329
330 /*
331 * Execute hard restart for all neighbors
332 */
333 DEFPY (clear_ip_eigrp_neighbors,
334 clear_ip_eigrp_neighbors_cmd,
335 "clear ip eigrp [vrf NAME] neighbors",
336 CLEAR_STR
337 IP_STR
338 "Clear IP-EIGRP\n"
339 VRF_CMD_HELP_STR
340 "Clear IP-EIGRP neighbors\n")
341 {
342 struct eigrp *eigrp;
343 struct eigrp_interface *ei;
344 struct listnode *node, *node2, *nnode2;
345 struct eigrp_neighbor *nbr;
346
347 /* Check if eigrp process is enabled */
348 eigrp = eigrp_vty_get_eigrp(vty, vrf);
349 if (eigrp == NULL) {
350 vty_out(vty, " EIGRP Routing Process not enabled\n");
351 return CMD_SUCCESS;
352 }
353
354 /* iterate over all eigrp interfaces */
355 for (ALL_LIST_ELEMENTS_RO(eigrp->eiflist, node, ei)) {
356 /* send Goodbye Hello */
357 eigrp_hello_send(ei, EIGRP_HELLO_GRACEFUL_SHUTDOWN, NULL);
358
359 /* iterate over all neighbors on eigrp interface */
360 for (ALL_LIST_ELEMENTS(ei->nbrs, node2, nnode2, nbr)) {
361 if (nbr->state != EIGRP_NEIGHBOR_DOWN) {
362 zlog_debug(
363 "Neighbor %pI4 (%s) is down: manually cleared",
364 &nbr->src,
365 ifindex2ifname(nbr->ei->ifp->ifindex,
366 eigrp->vrf_id));
367 vty_time_print(vty, 0);
368 vty_out(vty,
369 "Neighbor %pI4 (%s) is down: manually cleared\n",
370 &nbr->src,
371 ifindex2ifname(nbr->ei->ifp->ifindex,
372 eigrp->vrf_id));
373
374 /* set neighbor to DOWN */
375 nbr->state = EIGRP_NEIGHBOR_DOWN;
376 /* delete neighbor */
377 eigrp_nbr_delete(nbr);
378 }
379 }
380 }
381
382 return CMD_SUCCESS;
383 }
384
385 /*
386 * Execute hard restart for all neighbors on interface
387 */
388 DEFPY (clear_ip_eigrp_neighbors_int,
389 clear_ip_eigrp_neighbors_int_cmd,
390 "clear ip eigrp [vrf NAME] neighbors IFNAME",
391 CLEAR_STR
392 IP_STR
393 "Clear IP-EIGRP\n"
394 VRF_CMD_HELP_STR
395 "Clear IP-EIGRP neighbors\n"
396 "Interface's name\n")
397 {
398 struct eigrp *eigrp;
399 struct eigrp_interface *ei;
400 struct listnode *node2, *nnode2;
401 struct eigrp_neighbor *nbr;
402
403 /* Check if eigrp process is enabled */
404 eigrp = eigrp_vty_get_eigrp(vty, vrf);
405 if (eigrp == NULL) {
406 vty_out(vty, " EIGRP Routing Process not enabled\n");
407 return CMD_SUCCESS;
408 }
409
410 /* lookup interface by specified name */
411 ei = eigrp_if_lookup_by_name(eigrp, ifname);
412 if (ei == NULL) {
413 vty_out(vty, " Interface (%s) doesn't exist\n", ifname);
414 return CMD_WARNING;
415 }
416
417 /* send Goodbye Hello */
418 eigrp_hello_send(ei, EIGRP_HELLO_GRACEFUL_SHUTDOWN, NULL);
419
420 /* iterate over all neighbors on eigrp interface */
421 for (ALL_LIST_ELEMENTS(ei->nbrs, node2, nnode2, nbr)) {
422 if (nbr->state != EIGRP_NEIGHBOR_DOWN) {
423 zlog_debug(
424 "Neighbor %pI4 (%s) is down: manually cleared",
425 &nbr->src,
426 ifindex2ifname(nbr->ei->ifp->ifindex,
427 eigrp->vrf_id));
428 vty_time_print(vty, 0);
429 vty_out(vty,
430 "Neighbor %pI4 (%s) is down: manually cleared\n",
431 &nbr->src,
432 ifindex2ifname(nbr->ei->ifp->ifindex,
433 eigrp->vrf_id));
434
435 /* set neighbor to DOWN */
436 nbr->state = EIGRP_NEIGHBOR_DOWN;
437 /* delete neighbor */
438 eigrp_nbr_delete(nbr);
439 }
440 }
441
442 return CMD_SUCCESS;
443 }
444
445 /*
446 * Execute hard restart for neighbor specified by IP
447 */
448 DEFPY (clear_ip_eigrp_neighbors_IP,
449 clear_ip_eigrp_neighbors_IP_cmd,
450 "clear ip eigrp [vrf NAME] neighbors A.B.C.D$nbr_addr",
451 CLEAR_STR
452 IP_STR
453 "Clear IP-EIGRP\n"
454 VRF_CMD_HELP_STR
455 "Clear IP-EIGRP neighbors\n"
456 "IP-EIGRP neighbor address\n")
457 {
458 struct eigrp *eigrp;
459 struct eigrp_neighbor *nbr;
460
461 /* Check if eigrp process is enabled */
462 eigrp = eigrp_vty_get_eigrp(vty, vrf);
463 if (eigrp == NULL) {
464 vty_out(vty, " EIGRP Routing Process not enabled\n");
465 return CMD_SUCCESS;
466 }
467
468 /* lookup neighbor in whole process */
469 nbr = eigrp_nbr_lookup_by_addr_process(eigrp, nbr_addr);
470
471 /* if neighbor doesn't exists, notify user and exit */
472 if (nbr == NULL) {
473 vty_out(vty, "Neighbor with entered address doesn't exists.\n");
474 return CMD_WARNING;
475 }
476
477 /* execute hard reset on neighbor */
478 eigrp_nbr_hard_restart(nbr, vty);
479
480 return CMD_SUCCESS;
481 }
482
483 /*
484 * Execute graceful restart for all neighbors
485 */
486 DEFPY (clear_ip_eigrp_neighbors_soft,
487 clear_ip_eigrp_neighbors_soft_cmd,
488 "clear ip eigrp [vrf NAME] neighbors soft",
489 CLEAR_STR
490 IP_STR
491 "Clear IP-EIGRP\n"
492 VRF_CMD_HELP_STR
493 "Clear IP-EIGRP neighbors\n"
494 "Resync with peers without adjacency reset\n")
495 {
496 struct eigrp *eigrp;
497
498 /* Check if eigrp process is enabled */
499 eigrp = eigrp_vty_get_eigrp(vty, vrf);
500 if (eigrp == NULL) {
501 vty_out(vty, " EIGRP Routing Process not enabled\n");
502 return CMD_SUCCESS;
503 }
504
505 /* execute graceful restart on all neighbors */
506 eigrp_update_send_process_GR(eigrp, EIGRP_GR_MANUAL, vty);
507
508 return CMD_SUCCESS;
509 }
510
511 /*
512 * Execute graceful restart for all neighbors on interface
513 */
514 DEFPY (clear_ip_eigrp_neighbors_int_soft,
515 clear_ip_eigrp_neighbors_int_soft_cmd,
516 "clear ip eigrp [vrf NAME] neighbors IFNAME soft",
517 CLEAR_STR
518 IP_STR
519 "Clear IP-EIGRP\n"
520 VRF_CMD_HELP_STR
521 "Clear IP-EIGRP neighbors\n"
522 "Interface's name\n"
523 "Resync with peer without adjacency reset\n")
524 {
525 struct eigrp *eigrp;
526 struct eigrp_interface *ei;
527
528 /* Check if eigrp process is enabled */
529 eigrp = eigrp_vty_get_eigrp(vty, vrf);
530 if (eigrp == NULL) {
531 vty_out(vty, " EIGRP Routing Process not enabled\n");
532 return CMD_SUCCESS;
533 }
534
535 /* lookup interface by specified name */
536 ei = eigrp_if_lookup_by_name(eigrp, ifname);
537 if (ei == NULL) {
538 vty_out(vty, " Interface (%s) doesn't exist\n", argv[4]->arg);
539 return CMD_WARNING;
540 }
541
542 /* execute graceful restart for all neighbors on interface */
543 eigrp_update_send_interface_GR(ei, EIGRP_GR_MANUAL, vty);
544 return CMD_SUCCESS;
545 }
546
547 /*
548 * Execute graceful restart for neighbor specified by IP
549 */
550 DEFPY (clear_ip_eigrp_neighbors_IP_soft,
551 clear_ip_eigrp_neighbors_IP_soft_cmd,
552 "clear ip eigrp [vrf NAME] neighbors A.B.C.D$nbr_addr soft",
553 CLEAR_STR
554 IP_STR
555 "Clear IP-EIGRP\n"
556 VRF_CMD_HELP_STR
557 "Clear IP-EIGRP neighbors\n"
558 "IP-EIGRP neighbor address\n"
559 "Resync with peer without adjacency reset\n")
560 {
561 struct eigrp *eigrp;
562 struct eigrp_neighbor *nbr;
563
564
565 /* Check if eigrp process is enabled */
566 eigrp = eigrp_vty_get_eigrp(vty, vrf);
567 if (eigrp == NULL) {
568 vty_out(vty, " EIGRP Routing Process not enabled\n");
569 return CMD_SUCCESS;
570 }
571
572 /* lookup neighbor in whole process */
573 nbr = eigrp_nbr_lookup_by_addr_process(eigrp, nbr_addr);
574
575 /* if neighbor doesn't exists, notify user and exit */
576 if (nbr == NULL) {
577 vty_out(vty, "Neighbor with entered address doesn't exists.\n");
578 return CMD_WARNING;
579 }
580
581 /* execute graceful restart on neighbor */
582 eigrp_update_send_GR(nbr, EIGRP_GR_MANUAL, vty);
583
584 return CMD_SUCCESS;
585 }
586
587 void eigrp_vty_show_init(void)
588 {
589 install_element(VIEW_NODE, &show_ip_eigrp_interfaces_cmd);
590
591 install_element(VIEW_NODE, &show_ip_eigrp_neighbors_cmd);
592
593 install_element(VIEW_NODE, &show_ip_eigrp_topology_cmd);
594 install_element(VIEW_NODE, &show_ip_eigrp_topology_all_cmd);
595 }
596
597 /* Install EIGRP related vty commands. */
598 void eigrp_vty_init(void)
599 {
600 /* commands for manual hard restart */
601 install_element(ENABLE_NODE, &clear_ip_eigrp_neighbors_cmd);
602 install_element(ENABLE_NODE, &clear_ip_eigrp_neighbors_int_cmd);
603 install_element(ENABLE_NODE, &clear_ip_eigrp_neighbors_IP_cmd);
604 /* commands for manual graceful restart */
605 install_element(ENABLE_NODE, &clear_ip_eigrp_neighbors_soft_cmd);
606 install_element(ENABLE_NODE, &clear_ip_eigrp_neighbors_int_soft_cmd);
607 install_element(ENABLE_NODE, &clear_ip_eigrp_neighbors_IP_soft_cmd);
608 }