]> git.proxmox.com Git - mirror_frr.git/blob - eigrpd/eigrp_vty.c
Merge pull request #7089 from pguibert6WIND/netns-refactor
[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 %s (%s) is down: manually cleared",
364 inet_ntoa(nbr->src),
365 ifindex2ifname(nbr->ei->ifp->ifindex,
366 eigrp->vrf_id));
367 vty_time_print(vty, 0);
368 vty_out(vty,
369 "Neighbor %s (%s) is down: manually cleared\n",
370 inet_ntoa(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("Neighbor %s (%s) is down: manually cleared",
424 inet_ntoa(nbr->src),
425 ifindex2ifname(nbr->ei->ifp->ifindex,
426 eigrp->vrf_id));
427 vty_time_print(vty, 0);
428 vty_out(vty,
429 "Neighbor %s (%s) is down: manually cleared\n",
430 inet_ntoa(nbr->src),
431 ifindex2ifname(nbr->ei->ifp->ifindex,
432 eigrp->vrf_id));
433
434 /* set neighbor to DOWN */
435 nbr->state = EIGRP_NEIGHBOR_DOWN;
436 /* delete neighbor */
437 eigrp_nbr_delete(nbr);
438 }
439 }
440
441 return CMD_SUCCESS;
442 }
443
444 /*
445 * Execute hard restart for neighbor specified by IP
446 */
447 DEFPY (clear_ip_eigrp_neighbors_IP,
448 clear_ip_eigrp_neighbors_IP_cmd,
449 "clear ip eigrp [vrf NAME] neighbors A.B.C.D$nbr_addr",
450 CLEAR_STR
451 IP_STR
452 "Clear IP-EIGRP\n"
453 VRF_CMD_HELP_STR
454 "Clear IP-EIGRP neighbors\n"
455 "IP-EIGRP neighbor address\n")
456 {
457 struct eigrp *eigrp;
458 struct eigrp_neighbor *nbr;
459
460 /* Check if eigrp process is enabled */
461 eigrp = eigrp_vty_get_eigrp(vty, vrf);
462 if (eigrp == NULL) {
463 vty_out(vty, " EIGRP Routing Process not enabled\n");
464 return CMD_SUCCESS;
465 }
466
467 /* lookup neighbor in whole process */
468 nbr = eigrp_nbr_lookup_by_addr_process(eigrp, nbr_addr);
469
470 /* if neighbor doesn't exists, notify user and exit */
471 if (nbr == NULL) {
472 vty_out(vty, "Neighbor with entered address doesn't exists.\n");
473 return CMD_WARNING;
474 }
475
476 /* execute hard reset on neighbor */
477 eigrp_nbr_hard_restart(nbr, vty);
478
479 return CMD_SUCCESS;
480 }
481
482 /*
483 * Execute graceful restart for all neighbors
484 */
485 DEFPY (clear_ip_eigrp_neighbors_soft,
486 clear_ip_eigrp_neighbors_soft_cmd,
487 "clear ip eigrp [vrf NAME] neighbors soft",
488 CLEAR_STR
489 IP_STR
490 "Clear IP-EIGRP\n"
491 VRF_CMD_HELP_STR
492 "Clear IP-EIGRP neighbors\n"
493 "Resync with peers without adjacency reset\n")
494 {
495 struct eigrp *eigrp;
496
497 /* Check if eigrp process is enabled */
498 eigrp = eigrp_vty_get_eigrp(vty, vrf);
499 if (eigrp == NULL) {
500 vty_out(vty, " EIGRP Routing Process not enabled\n");
501 return CMD_SUCCESS;
502 }
503
504 /* execute graceful restart on all neighbors */
505 eigrp_update_send_process_GR(eigrp, EIGRP_GR_MANUAL, vty);
506
507 return CMD_SUCCESS;
508 }
509
510 /*
511 * Execute graceful restart for all neighbors on interface
512 */
513 DEFPY (clear_ip_eigrp_neighbors_int_soft,
514 clear_ip_eigrp_neighbors_int_soft_cmd,
515 "clear ip eigrp [vrf NAME] neighbors IFNAME soft",
516 CLEAR_STR
517 IP_STR
518 "Clear IP-EIGRP\n"
519 VRF_CMD_HELP_STR
520 "Clear IP-EIGRP neighbors\n"
521 "Interface's name\n"
522 "Resync with peer without adjacency reset\n")
523 {
524 struct eigrp *eigrp;
525 struct eigrp_interface *ei;
526
527 /* Check if eigrp process is enabled */
528 eigrp = eigrp_vty_get_eigrp(vty, vrf);
529 if (eigrp == NULL) {
530 vty_out(vty, " EIGRP Routing Process not enabled\n");
531 return CMD_SUCCESS;
532 }
533
534 /* lookup interface by specified name */
535 ei = eigrp_if_lookup_by_name(eigrp, ifname);
536 if (ei == NULL) {
537 vty_out(vty, " Interface (%s) doesn't exist\n", argv[4]->arg);
538 return CMD_WARNING;
539 }
540
541 /* execute graceful restart for all neighbors on interface */
542 eigrp_update_send_interface_GR(ei, EIGRP_GR_MANUAL, vty);
543 return CMD_SUCCESS;
544 }
545
546 /*
547 * Execute graceful restart for neighbor specified by IP
548 */
549 DEFPY (clear_ip_eigrp_neighbors_IP_soft,
550 clear_ip_eigrp_neighbors_IP_soft_cmd,
551 "clear ip eigrp [vrf NAME] neighbors A.B.C.D$nbr_addr soft",
552 CLEAR_STR
553 IP_STR
554 "Clear IP-EIGRP\n"
555 VRF_CMD_HELP_STR
556 "Clear IP-EIGRP neighbors\n"
557 "IP-EIGRP neighbor address\n"
558 "Resync with peer without adjacency reset\n")
559 {
560 struct eigrp *eigrp;
561 struct eigrp_neighbor *nbr;
562
563
564 /* Check if eigrp process is enabled */
565 eigrp = eigrp_vty_get_eigrp(vty, vrf);
566 if (eigrp == NULL) {
567 vty_out(vty, " EIGRP Routing Process not enabled\n");
568 return CMD_SUCCESS;
569 }
570
571 /* lookup neighbor in whole process */
572 nbr = eigrp_nbr_lookup_by_addr_process(eigrp, nbr_addr);
573
574 /* if neighbor doesn't exists, notify user and exit */
575 if (nbr == NULL) {
576 vty_out(vty, "Neighbor with entered address doesn't exists.\n");
577 return CMD_WARNING;
578 }
579
580 /* execute graceful restart on neighbor */
581 eigrp_update_send_GR(nbr, EIGRP_GR_MANUAL, vty);
582
583 return CMD_SUCCESS;
584 }
585
586 void eigrp_vty_show_init(void)
587 {
588 install_element(VIEW_NODE, &show_ip_eigrp_interfaces_cmd);
589
590 install_element(VIEW_NODE, &show_ip_eigrp_neighbors_cmd);
591
592 install_element(VIEW_NODE, &show_ip_eigrp_topology_cmd);
593 install_element(VIEW_NODE, &show_ip_eigrp_topology_all_cmd);
594 }
595
596 /* Install EIGRP related vty commands. */
597 void eigrp_vty_init(void)
598 {
599 /* commands for manual hard restart */
600 install_element(ENABLE_NODE, &clear_ip_eigrp_neighbors_cmd);
601 install_element(ENABLE_NODE, &clear_ip_eigrp_neighbors_int_cmd);
602 install_element(ENABLE_NODE, &clear_ip_eigrp_neighbors_IP_cmd);
603 /* commands for manual graceful restart */
604 install_element(ENABLE_NODE, &clear_ip_eigrp_neighbors_soft_cmd);
605 install_element(ENABLE_NODE, &clear_ip_eigrp_neighbors_int_soft_cmd);
606 install_element(ENABLE_NODE, &clear_ip_eigrp_neighbors_IP_soft_cmd);
607 }