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