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