]> git.proxmox.com Git - mirror_frr.git/blame - ripngd/ripng_cli.c
Merge pull request #9920 from donaldsharp/zebra_seg6local_race
[mirror_frr.git] / ripngd / ripng_cli.c
CommitLineData
e9ce224b
RW
1/*
2 * Copyright (C) 1998 Kunihiro Ishiguro
3 * Copyright (C) 2018 NetDEF, Inc.
4 * Renato Westphal
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the Free
8 * Software Foundation; either version 2 of the License, or (at your option)
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#include <zebra.h>
22
23#include "if.h"
24#include "vrf.h"
25#include "log.h"
26#include "prefix.h"
27#include "command.h"
28#include "northbound_cli.h"
29#include "libfrr.h"
30
31#include "ripngd/ripngd.h"
ca473936 32#include "ripngd/ripng_nb.h"
e9ce224b
RW
33#ifndef VTYSH_EXTRACT_PL
34#include "ripngd/ripng_cli_clippy.c"
35#endif
36
9a12e9e5
RW
37/*
38 * XPath: /frr-ripngd:ripngd/instance
39 */
ca77b518 40DEFPY_YANG_NOSH (router_ripng,
9a12e9e5 41 router_ripng_cmd,
dde7b15b 42 "router ripng [vrf NAME]",
9a12e9e5 43 "Enable a routing process\n"
dde7b15b
RW
44 "Make RIPng instance command\n"
45 VRF_CMD_HELP_STR)
9a12e9e5 46{
dde7b15b 47 char xpath[XPATH_MAXLEN];
9a12e9e5
RW
48 int ret;
49
dde7b15b
RW
50 /* Build RIPng instance XPath. */
51 if (!vrf)
52 vrf = VRF_DEFAULT_NAME;
53 snprintf(xpath, sizeof(xpath), "/frr-ripngd:ripngd/instance[vrf='%s']",
54 vrf);
55
56 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
9a12e9e5
RW
57
58 ret = nb_cli_apply_changes(vty, NULL);
59 if (ret == CMD_SUCCESS)
dde7b15b 60 VTY_PUSH_XPATH(RIPNG_NODE, xpath);
9a12e9e5
RW
61
62 return ret;
63}
64
ca77b518 65DEFPY_YANG (no_router_ripng,
9a12e9e5 66 no_router_ripng_cmd,
dde7b15b 67 "no router ripng [vrf NAME]",
9a12e9e5
RW
68 NO_STR
69 "Enable a routing process\n"
dde7b15b
RW
70 "Make RIPng instance command\n"
71 VRF_CMD_HELP_STR)
9a12e9e5 72{
dde7b15b
RW
73 char xpath[XPATH_MAXLEN];
74
75 /* Build RIPng instance XPath. */
76 if (!vrf)
77 vrf = VRF_DEFAULT_NAME;
78 snprintf(xpath, sizeof(xpath), "/frr-ripngd:ripngd/instance[vrf='%s']",
79 vrf);
80
8f88441d 81 nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
9a12e9e5 82
fd396924 83 return nb_cli_apply_changes_clear_pending(vty, NULL);
9a12e9e5
RW
84}
85
25605051
IR
86void cli_show_router_ripng(struct vty *vty, const struct lyd_node *dnode,
87 bool show_defaults)
9a12e9e5 88{
dde7b15b
RW
89 const char *vrf_name;
90
91 vrf_name = yang_dnode_get_string(dnode, "./vrf");
92
9a12e9e5 93 vty_out(vty, "!\n");
dde7b15b
RW
94 vty_out(vty, "router ripng");
95 if (!strmatch(vrf_name, VRF_DEFAULT_NAME))
96 vty_out(vty, " vrf %s", vrf_name);
97 vty_out(vty, "\n");
9a12e9e5
RW
98}
99
1e42a07c
RW
100/*
101 * XPath: /frr-ripngd:ripngd/instance/allow-ecmp
102 */
ca77b518 103DEFPY_YANG (ripng_allow_ecmp,
1e42a07c
RW
104 ripng_allow_ecmp_cmd,
105 "[no] allow-ecmp",
106 NO_STR
107 "Allow Equal Cost MultiPath\n")
108{
109 nb_cli_enqueue_change(vty, "./allow-ecmp", NB_OP_MODIFY,
110 no ? "false" : "true");
111
112 return nb_cli_apply_changes(vty, NULL);
113}
114
25605051 115void cli_show_ripng_allow_ecmp(struct vty *vty, const struct lyd_node *dnode,
1e42a07c
RW
116 bool show_defaults)
117{
118 if (!yang_dnode_get_bool(dnode, NULL))
119 vty_out(vty, " no");
120
121 vty_out(vty, " allow-ecmp\n");
122}
123
54b56562
RW
124/*
125 * XPath: /frr-ripngd:ripngd/instance/default-information-originate
126 */
ca77b518 127DEFPY_YANG (ripng_default_information_originate,
54b56562
RW
128 ripng_default_information_originate_cmd,
129 "[no] default-information originate",
130 NO_STR
131 "Default route information\n"
132 "Distribute default route\n")
133{
134 nb_cli_enqueue_change(vty, "./default-information-originate",
135 NB_OP_MODIFY, no ? "false" : "true");
136
137 return nb_cli_apply_changes(vty, NULL);
138}
139
140void cli_show_ripng_default_information_originate(struct vty *vty,
25605051 141 const struct lyd_node *dnode,
54b56562
RW
142 bool show_defaults)
143{
144 if (!yang_dnode_get_bool(dnode, NULL))
145 vty_out(vty, " no");
146
147 vty_out(vty, " default-information originate\n");
148}
149
ad8778c0
RW
150/*
151 * XPath: /frr-ripngd:ripngd/instance/default-metric
152 */
ca77b518 153DEFPY_YANG (ripng_default_metric,
ad8778c0
RW
154 ripng_default_metric_cmd,
155 "default-metric (1-16)",
156 "Set a metric of redistribute routes\n"
157 "Default metric\n")
158{
159 nb_cli_enqueue_change(vty, "./default-metric", NB_OP_MODIFY,
160 default_metric_str);
161
162 return nb_cli_apply_changes(vty, NULL);
163}
164
ca77b518 165DEFPY_YANG (no_ripng_default_metric,
ad8778c0
RW
166 no_ripng_default_metric_cmd,
167 "no default-metric [(1-16)]",
168 NO_STR
169 "Set a metric of redistribute routes\n"
170 "Default metric\n")
171{
172 nb_cli_enqueue_change(vty, "./default-metric", NB_OP_MODIFY, NULL);
173
174 return nb_cli_apply_changes(vty, NULL);
175}
176
25605051
IR
177void cli_show_ripng_default_metric(struct vty *vty,
178 const struct lyd_node *dnode,
ad8778c0
RW
179 bool show_defaults)
180{
181 vty_out(vty, " default-metric %s\n",
182 yang_dnode_get_string(dnode, NULL));
183}
184
cc48702b
RW
185/*
186 * XPath: /frr-ripngd:ripngd/instance/network
187 */
ca77b518 188DEFPY_YANG (ripng_network_prefix,
cc48702b
RW
189 ripng_network_prefix_cmd,
190 "[no] network X:X::X:X/M",
191 NO_STR
192 "RIPng enable on specified interface or network.\n"
193 "IPv6 network\n")
194{
195 nb_cli_enqueue_change(vty, "./network",
95ce849b 196 no ? NB_OP_DESTROY : NB_OP_CREATE, network_str);
cc48702b
RW
197
198 return nb_cli_apply_changes(vty, NULL);
199}
200
25605051
IR
201void cli_show_ripng_network_prefix(struct vty *vty,
202 const struct lyd_node *dnode,
cc48702b
RW
203 bool show_defaults)
204{
205 vty_out(vty, " network %s\n", yang_dnode_get_string(dnode, NULL));
206}
207
208/*
209 * XPath: /frr-ripngd:ripngd/instance/interface
210 */
ca77b518 211DEFPY_YANG (ripng_network_if,
cc48702b
RW
212 ripng_network_if_cmd,
213 "[no] network WORD",
214 NO_STR
215 "RIPng enable on specified interface or network.\n"
216 "Interface name\n")
217{
218 nb_cli_enqueue_change(vty, "./interface",
95ce849b 219 no ? NB_OP_DESTROY : NB_OP_CREATE, network);
cc48702b
RW
220
221 return nb_cli_apply_changes(vty, NULL);
222}
223
25605051
IR
224void cli_show_ripng_network_interface(struct vty *vty,
225 const struct lyd_node *dnode,
cc48702b
RW
226 bool show_defaults)
227{
228 vty_out(vty, " network %s\n", yang_dnode_get_string(dnode, NULL));
229}
230
b09956ca
RW
231/*
232 * XPath: /frr-ripngd:ripngd/instance/offset-list
233 */
ca77b518 234DEFPY_YANG (ripng_offset_list,
b09956ca
RW
235 ripng_offset_list_cmd,
236 "[no] offset-list WORD$acl <in|out>$direction (0-16)$metric [IFNAME]",
237 NO_STR
238 "Modify RIPng metric\n"
239 "Access-list name\n"
240 "For incoming updates\n"
241 "For outgoing updates\n"
242 "Metric value\n"
243 "Interface to match\n")
244{
245 if (!no) {
246 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
247 nb_cli_enqueue_change(vty, "./access-list", NB_OP_MODIFY, acl);
248 nb_cli_enqueue_change(vty, "./metric", NB_OP_MODIFY,
249 metric_str);
250 } else
95ce849b 251 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
b09956ca
RW
252
253 return nb_cli_apply_changes(
254 vty, "./offset-list[interface='%s'][direction='%s']",
255 ifname ? ifname : "*", direction);
256}
257
25605051 258void cli_show_ripng_offset_list(struct vty *vty, const struct lyd_node *dnode,
b09956ca
RW
259 bool show_defaults)
260{
261 const char *interface;
262
263 interface = yang_dnode_get_string(dnode, "./interface");
264
265 vty_out(vty, " offset-list %s %s %s",
266 yang_dnode_get_string(dnode, "./access-list"),
267 yang_dnode_get_string(dnode, "./direction"),
268 yang_dnode_get_string(dnode, "./metric"));
269 if (!strmatch(interface, "*"))
270 vty_out(vty, " %s", interface);
271 vty_out(vty, "\n");
272}
273
22e8c7ae
RW
274/*
275 * XPath: /frr-ripngd:ripngd/instance/passive-interface
276 */
ca77b518 277DEFPY_YANG (ripng_passive_interface,
22e8c7ae
RW
278 ripng_passive_interface_cmd,
279 "[no] passive-interface IFNAME",
280 NO_STR
281 "Suppress routing updates on an interface\n"
282 "Interface name\n")
283{
284 nb_cli_enqueue_change(vty, "./passive-interface",
95ce849b 285 no ? NB_OP_DESTROY : NB_OP_CREATE, ifname);
22e8c7ae
RW
286
287 return nb_cli_apply_changes(vty, NULL);
288}
289
25605051
IR
290void cli_show_ripng_passive_interface(struct vty *vty,
291 const struct lyd_node *dnode,
22e8c7ae
RW
292 bool show_defaults)
293{
294 vty_out(vty, " passive-interface %s\n",
295 yang_dnode_get_string(dnode, NULL));
296}
297
db2038c7
RW
298/*
299 * XPath: /frr-ripngd:ripngd/instance/redistribute
300 */
ca77b518 301DEFPY_YANG (ripng_redistribute,
db2038c7
RW
302 ripng_redistribute_cmd,
303 "[no] redistribute " FRR_REDIST_STR_RIPNGD "$protocol [{metric (0-16)|route-map WORD}]",
304 NO_STR
305 REDIST_STR
306 FRR_REDIST_HELP_STR_RIPNGD
307 "Metric\n"
308 "Metric value\n"
309 "Route map reference\n"
310 "Pointer to route-map entries\n")
311{
312 if (!no) {
313 nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
314 nb_cli_enqueue_change(vty, "./route-map",
95ce849b 315 route_map ? NB_OP_MODIFY : NB_OP_DESTROY,
db2038c7
RW
316 route_map);
317 nb_cli_enqueue_change(vty, "./metric",
95ce849b 318 metric_str ? NB_OP_MODIFY : NB_OP_DESTROY,
db2038c7
RW
319 metric_str);
320 } else
95ce849b 321 nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
db2038c7
RW
322
323 return nb_cli_apply_changes(vty, "./redistribute[protocol='%s']",
324 protocol);
325}
326
25605051 327void cli_show_ripng_redistribute(struct vty *vty, const struct lyd_node *dnode,
db2038c7
RW
328 bool show_defaults)
329{
330 vty_out(vty, " redistribute %s",
331 yang_dnode_get_string(dnode, "./protocol"));
332 if (yang_dnode_exists(dnode, "./metric"))
333 vty_out(vty, " metric %s",
334 yang_dnode_get_string(dnode, "./metric"));
335 if (yang_dnode_exists(dnode, "./route-map"))
336 vty_out(vty, " route-map %s",
337 yang_dnode_get_string(dnode, "./route-map"));
338 vty_out(vty, "\n");
339}
340
521d1b12
RW
341/*
342 * XPath: /frr-ripngd:ripngd/instance/static-route
343 */
ca77b518 344DEFPY_YANG (ripng_route,
521d1b12
RW
345 ripng_route_cmd,
346 "[no] route X:X::X:X/M",
347 NO_STR
348 "Static route setup\n"
349 "Set static RIPng route announcement\n")
350{
351 nb_cli_enqueue_change(vty, "./static-route",
95ce849b 352 no ? NB_OP_DESTROY : NB_OP_CREATE, route_str);
521d1b12
RW
353
354 return nb_cli_apply_changes(vty, NULL);
355}
356
25605051 357void cli_show_ripng_route(struct vty *vty, const struct lyd_node *dnode,
521d1b12
RW
358 bool show_defaults)
359{
360 vty_out(vty, " route %s\n", yang_dnode_get_string(dnode, NULL));
361}
362
6fc29385
RW
363/*
364 * XPath: /frr-ripngd:ripngd/instance/aggregate-addres
365 */
ca77b518 366DEFPY_YANG (ripng_aggregate_address,
6fc29385
RW
367 ripng_aggregate_address_cmd,
368 "[no] aggregate-address X:X::X:X/M",
369 NO_STR
370 "Set aggregate RIPng route announcement\n"
371 "Aggregate network\n")
372{
373 nb_cli_enqueue_change(vty, "./aggregate-address",
95ce849b 374 no ? NB_OP_DESTROY : NB_OP_CREATE,
6fc29385
RW
375 aggregate_address_str);
376
377 return nb_cli_apply_changes(vty, NULL);
378}
379
25605051
IR
380void cli_show_ripng_aggregate_address(struct vty *vty,
381 const struct lyd_node *dnode,
6fc29385
RW
382 bool show_defaults)
383{
384 vty_out(vty, " aggregate-address %s\n",
385 yang_dnode_get_string(dnode, NULL));
386}
387
f8981ec5
RW
388/*
389 * XPath: /frr-ripngd:ripngd/instance/timers
390 */
ca77b518 391DEFPY_YANG (ripng_timers,
f8981ec5
RW
392 ripng_timers_cmd,
393 "timers basic (1-65535)$update (1-65535)$timeout (1-65535)$garbage",
394 "RIPng timers setup\n"
395 "Basic timer\n"
396 "Routing table update timer value in second. Default is 30.\n"
397 "Routing information timeout timer. Default is 180.\n"
398 "Garbage collection timer. Default is 120.\n")
399{
400 nb_cli_enqueue_change(vty, "./update-interval", NB_OP_MODIFY,
401 update_str);
402 nb_cli_enqueue_change(vty, "./holddown-interval", NB_OP_MODIFY,
403 timeout_str);
404 nb_cli_enqueue_change(vty, "./flush-interval", NB_OP_MODIFY,
405 garbage_str);
406
407 return nb_cli_apply_changes(vty, "./timers");
408}
409
ca77b518 410DEFPY_YANG (no_ripng_timers,
f8981ec5
RW
411 no_ripng_timers_cmd,
412 "no timers basic [(1-65535) (1-65535) (1-65535)]",
413 NO_STR
414 "RIPng timers setup\n"
415 "Basic timer\n"
416 "Routing table update timer value in second. Default is 30.\n"
417 "Routing information timeout timer. Default is 180.\n"
418 "Garbage collection timer. Default is 120.\n")
419{
420 nb_cli_enqueue_change(vty, "./update-interval", NB_OP_MODIFY, NULL);
421 nb_cli_enqueue_change(vty, "./holddown-interval", NB_OP_MODIFY, NULL);
422 nb_cli_enqueue_change(vty, "./flush-interval", NB_OP_MODIFY, NULL);
423
424 return nb_cli_apply_changes(vty, "./timers");
425}
426
25605051 427void cli_show_ripng_timers(struct vty *vty, const struct lyd_node *dnode,
f8981ec5
RW
428 bool show_defaults)
429{
430 vty_out(vty, " timers basic %s %s %s\n",
431 yang_dnode_get_string(dnode, "./update-interval"),
432 yang_dnode_get_string(dnode, "./holddown-interval"),
433 yang_dnode_get_string(dnode, "./flush-interval"));
434}
435
d406db4c
RW
436/*
437 * XPath: /frr-interface:lib/interface/frr-ripngd:ripng/split-horizon
438 */
ca77b518 439DEFPY_YANG (ipv6_ripng_split_horizon,
d406db4c
RW
440 ipv6_ripng_split_horizon_cmd,
441 "[no] ipv6 ripng split-horizon [poisoned-reverse$poisoned_reverse]",
442 NO_STR
443 IPV6_STR
444 "Routing Information Protocol\n"
445 "Perform split horizon\n"
446 "With poisoned-reverse\n")
447{
448 const char *value;
449
450 if (no)
451 value = "disabled";
452 else if (poisoned_reverse)
453 value = "poison-reverse";
454 else
455 value = "simple";
456
457 nb_cli_enqueue_change(vty, "./split-horizon", NB_OP_MODIFY, value);
458
459 return nb_cli_apply_changes(vty, "./frr-ripngd:ripng");
460}
461
25605051
IR
462void cli_show_ipv6_ripng_split_horizon(struct vty *vty,
463 const struct lyd_node *dnode,
d406db4c
RW
464 bool show_defaults)
465{
466 int value;
467
468 value = yang_dnode_get_enum(dnode, NULL);
469 switch (value) {
470 case RIPNG_NO_SPLIT_HORIZON:
471 vty_out(vty, " no ipv6 ripng split-horizon\n");
472 break;
473 case RIPNG_SPLIT_HORIZON:
474 vty_out(vty, " ipv6 ripng split-horizon\n");
475 break;
476 case RIPNG_SPLIT_HORIZON_POISONED_REVERSE:
477 vty_out(vty, " ipv6 ripng split-horizon poisoned-reverse\n");
478 break;
479 }
480}
481
49e06d25
RW
482/*
483 * XPath: /frr-ripngd:clear-ripng-route
484 */
ca77b518 485DEFPY_YANG (clear_ipv6_rip,
49e06d25 486 clear_ipv6_rip_cmd,
c5b2b5f6 487 "clear ipv6 ripng [vrf WORD]",
49e06d25
RW
488 CLEAR_STR
489 IPV6_STR
c5b2b5f6
RW
490 "Clear IPv6 RIP database\n"
491 VRF_CMD_HELP_STR)
49e06d25 492{
c5b2b5f6 493 struct list *input;
0783b36d 494 int ret;
c5b2b5f6
RW
495
496 input = list_new();
497 if (vrf) {
498 struct yang_data *yang_vrf;
499
500 yang_vrf = yang_data_new(
501 "/frr-ripngd:clear-ripng-route/input/vrf", vrf);
502 listnode_add(input, yang_vrf);
503 }
504
f63f5f19 505 ret = nb_cli_rpc(vty, "/frr-ripngd:clear-ripng-route", input, NULL);
0783b36d
DS
506
507 list_delete(&input);
508
509 return ret;
49e06d25
RW
510}
511
458133db
DS
512DEFUN (ripng_ipv6_distribute_list,
513 ripng_ipv6_distribute_list_cmd,
514 "ipv6 distribute-list [prefix] WORD <in|out> [WORD]",
515 "IPv6\n"
516 "Filter networks in routing updates\n"
517 "Specify a prefix\n"
518 "Access-list name\n"
519 "Filter incoming routing updates\n"
520 "Filter outgoing routing updates\n"
521 "Interface name\n")
522{
523 const char *ifname = NULL;
524 int prefix = (argv[2]->type == WORD_TKN) ? 1 : 0;
525
526 if (argv[argc - 1]->type == VARIABLE_TKN)
527 ifname = argv[argc - 1]->arg;
528
529 return distribute_list_parser(prefix, false, argv[3 + prefix]->text,
530 argv[2 + prefix]->arg, ifname);
531}
532
533DEFUN (ripng_no_ipv6_distribute_list,
534 ripng_no_ipv6_distribute_list_cmd,
535 "no ipv6 distribute-list [prefix] WORD <in|out> [WORD]",
536 NO_STR
537 "IPv6\n"
538 "Filter networks in routing updates\n"
539 "Specify a prefix\n"
540 "Access-list name\n"
541 "Filter incoming routing updates\n"
542 "Filter outgoing routing updates\n"
543 "Interface name\n")
544{
545 const char *ifname = NULL;
546 int prefix = (argv[3]->type == WORD_TKN) ? 1 : 0;
547
548 if (argv[argc - 1]->type == VARIABLE_TKN)
549 ifname = argv[argc - 1]->arg;
550
551 return distribute_list_no_parser(vty, prefix, false,
552 argv[4 + prefix]->text,
553 argv[3 + prefix]->arg, ifname);
554}
555
e9ce224b
RW
556void ripng_cli_init(void)
557{
9a12e9e5
RW
558 install_element(CONFIG_NODE, &router_ripng_cmd);
559 install_element(CONFIG_NODE, &no_router_ripng_cmd);
1e42a07c 560
458133db
DS
561 install_element(RIPNG_NODE, &ripng_ipv6_distribute_list_cmd);
562 install_element(RIPNG_NODE, &ripng_no_ipv6_distribute_list_cmd);
563
1e42a07c 564 install_element(RIPNG_NODE, &ripng_allow_ecmp_cmd);
54b56562 565 install_element(RIPNG_NODE, &ripng_default_information_originate_cmd);
ad8778c0
RW
566 install_element(RIPNG_NODE, &ripng_default_metric_cmd);
567 install_element(RIPNG_NODE, &no_ripng_default_metric_cmd);
cc48702b
RW
568 install_element(RIPNG_NODE, &ripng_network_prefix_cmd);
569 install_element(RIPNG_NODE, &ripng_network_if_cmd);
b09956ca 570 install_element(RIPNG_NODE, &ripng_offset_list_cmd);
22e8c7ae 571 install_element(RIPNG_NODE, &ripng_passive_interface_cmd);
db2038c7 572 install_element(RIPNG_NODE, &ripng_redistribute_cmd);
521d1b12 573 install_element(RIPNG_NODE, &ripng_route_cmd);
6fc29385 574 install_element(RIPNG_NODE, &ripng_aggregate_address_cmd);
f8981ec5
RW
575 install_element(RIPNG_NODE, &ripng_timers_cmd);
576 install_element(RIPNG_NODE, &no_ripng_timers_cmd);
d406db4c
RW
577
578 install_element(INTERFACE_NODE, &ipv6_ripng_split_horizon_cmd);
49e06d25
RW
579
580 install_element(ENABLE_NODE, &clear_ipv6_rip_cmd);
e9ce224b 581}