]>
Commit | Line | Data |
---|---|---|
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" | |
32 | #include "ripngd/ripng_cli.h" | |
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 | */ | |
40 | DEFPY_NOSH (router_ripng, | |
41 | router_ripng_cmd, | |
42 | "router ripng", | |
43 | "Enable a routing process\n" | |
44 | "Make RIPng instance command\n") | |
45 | { | |
46 | int ret; | |
47 | ||
48 | nb_cli_enqueue_change(vty, "/frr-ripngd:ripngd/instance", NB_OP_CREATE, | |
49 | NULL); | |
50 | ||
51 | ret = nb_cli_apply_changes(vty, NULL); | |
52 | if (ret == CMD_SUCCESS) | |
53 | VTY_PUSH_XPATH(RIPNG_NODE, "/frr-ripngd:ripngd/instance"); | |
54 | ||
55 | return ret; | |
56 | } | |
57 | ||
58 | DEFPY (no_router_ripng, | |
59 | no_router_ripng_cmd, | |
60 | "no router ripng", | |
61 | NO_STR | |
62 | "Enable a routing process\n" | |
63 | "Make RIPng instance command\n") | |
64 | { | |
95ce849b | 65 | nb_cli_enqueue_change(vty, "/frr-ripngd:ripngd/instance", NB_OP_DESTROY, |
9a12e9e5 RW |
66 | NULL); |
67 | ||
68 | return nb_cli_apply_changes(vty, NULL); | |
69 | } | |
70 | ||
71 | void cli_show_router_ripng(struct vty *vty, struct lyd_node *dnode, | |
72 | bool show_defaults) | |
73 | { | |
74 | vty_out(vty, "!\n"); | |
75 | vty_out(vty, "router ripng\n"); | |
76 | } | |
77 | ||
1e42a07c RW |
78 | /* |
79 | * XPath: /frr-ripngd:ripngd/instance/allow-ecmp | |
80 | */ | |
81 | DEFPY (ripng_allow_ecmp, | |
82 | ripng_allow_ecmp_cmd, | |
83 | "[no] allow-ecmp", | |
84 | NO_STR | |
85 | "Allow Equal Cost MultiPath\n") | |
86 | { | |
87 | nb_cli_enqueue_change(vty, "./allow-ecmp", NB_OP_MODIFY, | |
88 | no ? "false" : "true"); | |
89 | ||
90 | return nb_cli_apply_changes(vty, NULL); | |
91 | } | |
92 | ||
93 | void cli_show_ripng_allow_ecmp(struct vty *vty, struct lyd_node *dnode, | |
94 | bool show_defaults) | |
95 | { | |
96 | if (!yang_dnode_get_bool(dnode, NULL)) | |
97 | vty_out(vty, " no"); | |
98 | ||
99 | vty_out(vty, " allow-ecmp\n"); | |
100 | } | |
101 | ||
54b56562 RW |
102 | /* |
103 | * XPath: /frr-ripngd:ripngd/instance/default-information-originate | |
104 | */ | |
105 | DEFPY (ripng_default_information_originate, | |
106 | ripng_default_information_originate_cmd, | |
107 | "[no] default-information originate", | |
108 | NO_STR | |
109 | "Default route information\n" | |
110 | "Distribute default route\n") | |
111 | { | |
112 | nb_cli_enqueue_change(vty, "./default-information-originate", | |
113 | NB_OP_MODIFY, no ? "false" : "true"); | |
114 | ||
115 | return nb_cli_apply_changes(vty, NULL); | |
116 | } | |
117 | ||
118 | void cli_show_ripng_default_information_originate(struct vty *vty, | |
119 | struct lyd_node *dnode, | |
120 | bool show_defaults) | |
121 | { | |
122 | if (!yang_dnode_get_bool(dnode, NULL)) | |
123 | vty_out(vty, " no"); | |
124 | ||
125 | vty_out(vty, " default-information originate\n"); | |
126 | } | |
127 | ||
ad8778c0 RW |
128 | /* |
129 | * XPath: /frr-ripngd:ripngd/instance/default-metric | |
130 | */ | |
131 | DEFPY (ripng_default_metric, | |
132 | ripng_default_metric_cmd, | |
133 | "default-metric (1-16)", | |
134 | "Set a metric of redistribute routes\n" | |
135 | "Default metric\n") | |
136 | { | |
137 | nb_cli_enqueue_change(vty, "./default-metric", NB_OP_MODIFY, | |
138 | default_metric_str); | |
139 | ||
140 | return nb_cli_apply_changes(vty, NULL); | |
141 | } | |
142 | ||
143 | DEFPY (no_ripng_default_metric, | |
144 | no_ripng_default_metric_cmd, | |
145 | "no default-metric [(1-16)]", | |
146 | NO_STR | |
147 | "Set a metric of redistribute routes\n" | |
148 | "Default metric\n") | |
149 | { | |
150 | nb_cli_enqueue_change(vty, "./default-metric", NB_OP_MODIFY, NULL); | |
151 | ||
152 | return nb_cli_apply_changes(vty, NULL); | |
153 | } | |
154 | ||
155 | void cli_show_ripng_default_metric(struct vty *vty, struct lyd_node *dnode, | |
156 | bool show_defaults) | |
157 | { | |
158 | vty_out(vty, " default-metric %s\n", | |
159 | yang_dnode_get_string(dnode, NULL)); | |
160 | } | |
161 | ||
cc48702b RW |
162 | /* |
163 | * XPath: /frr-ripngd:ripngd/instance/network | |
164 | */ | |
165 | DEFPY (ripng_network_prefix, | |
166 | ripng_network_prefix_cmd, | |
167 | "[no] network X:X::X:X/M", | |
168 | NO_STR | |
169 | "RIPng enable on specified interface or network.\n" | |
170 | "IPv6 network\n") | |
171 | { | |
172 | nb_cli_enqueue_change(vty, "./network", | |
95ce849b | 173 | no ? NB_OP_DESTROY : NB_OP_CREATE, network_str); |
cc48702b RW |
174 | |
175 | return nb_cli_apply_changes(vty, NULL); | |
176 | } | |
177 | ||
178 | void cli_show_ripng_network_prefix(struct vty *vty, struct lyd_node *dnode, | |
179 | bool show_defaults) | |
180 | { | |
181 | vty_out(vty, " network %s\n", yang_dnode_get_string(dnode, NULL)); | |
182 | } | |
183 | ||
184 | /* | |
185 | * XPath: /frr-ripngd:ripngd/instance/interface | |
186 | */ | |
187 | DEFPY (ripng_network_if, | |
188 | ripng_network_if_cmd, | |
189 | "[no] network WORD", | |
190 | NO_STR | |
191 | "RIPng enable on specified interface or network.\n" | |
192 | "Interface name\n") | |
193 | { | |
194 | nb_cli_enqueue_change(vty, "./interface", | |
95ce849b | 195 | no ? NB_OP_DESTROY : NB_OP_CREATE, network); |
cc48702b RW |
196 | |
197 | return nb_cli_apply_changes(vty, NULL); | |
198 | } | |
199 | ||
200 | void cli_show_ripng_network_interface(struct vty *vty, struct lyd_node *dnode, | |
201 | bool show_defaults) | |
202 | { | |
203 | vty_out(vty, " network %s\n", yang_dnode_get_string(dnode, NULL)); | |
204 | } | |
205 | ||
b09956ca RW |
206 | /* |
207 | * XPath: /frr-ripngd:ripngd/instance/offset-list | |
208 | */ | |
209 | DEFPY (ripng_offset_list, | |
210 | ripng_offset_list_cmd, | |
211 | "[no] offset-list WORD$acl <in|out>$direction (0-16)$metric [IFNAME]", | |
212 | NO_STR | |
213 | "Modify RIPng metric\n" | |
214 | "Access-list name\n" | |
215 | "For incoming updates\n" | |
216 | "For outgoing updates\n" | |
217 | "Metric value\n" | |
218 | "Interface to match\n") | |
219 | { | |
220 | if (!no) { | |
221 | nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL); | |
222 | nb_cli_enqueue_change(vty, "./access-list", NB_OP_MODIFY, acl); | |
223 | nb_cli_enqueue_change(vty, "./metric", NB_OP_MODIFY, | |
224 | metric_str); | |
225 | } else | |
95ce849b | 226 | nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL); |
b09956ca RW |
227 | |
228 | return nb_cli_apply_changes( | |
229 | vty, "./offset-list[interface='%s'][direction='%s']", | |
230 | ifname ? ifname : "*", direction); | |
231 | } | |
232 | ||
233 | void cli_show_ripng_offset_list(struct vty *vty, struct lyd_node *dnode, | |
234 | bool show_defaults) | |
235 | { | |
236 | const char *interface; | |
237 | ||
238 | interface = yang_dnode_get_string(dnode, "./interface"); | |
239 | ||
240 | vty_out(vty, " offset-list %s %s %s", | |
241 | yang_dnode_get_string(dnode, "./access-list"), | |
242 | yang_dnode_get_string(dnode, "./direction"), | |
243 | yang_dnode_get_string(dnode, "./metric")); | |
244 | if (!strmatch(interface, "*")) | |
245 | vty_out(vty, " %s", interface); | |
246 | vty_out(vty, "\n"); | |
247 | } | |
248 | ||
22e8c7ae RW |
249 | /* |
250 | * XPath: /frr-ripngd:ripngd/instance/passive-interface | |
251 | */ | |
252 | DEFPY (ripng_passive_interface, | |
253 | ripng_passive_interface_cmd, | |
254 | "[no] passive-interface IFNAME", | |
255 | NO_STR | |
256 | "Suppress routing updates on an interface\n" | |
257 | "Interface name\n") | |
258 | { | |
259 | nb_cli_enqueue_change(vty, "./passive-interface", | |
95ce849b | 260 | no ? NB_OP_DESTROY : NB_OP_CREATE, ifname); |
22e8c7ae RW |
261 | |
262 | return nb_cli_apply_changes(vty, NULL); | |
263 | } | |
264 | ||
265 | void cli_show_ripng_passive_interface(struct vty *vty, struct lyd_node *dnode, | |
266 | bool show_defaults) | |
267 | { | |
268 | vty_out(vty, " passive-interface %s\n", | |
269 | yang_dnode_get_string(dnode, NULL)); | |
270 | } | |
271 | ||
db2038c7 RW |
272 | /* |
273 | * XPath: /frr-ripngd:ripngd/instance/redistribute | |
274 | */ | |
275 | DEFPY (ripng_redistribute, | |
276 | ripng_redistribute_cmd, | |
277 | "[no] redistribute " FRR_REDIST_STR_RIPNGD "$protocol [{metric (0-16)|route-map WORD}]", | |
278 | NO_STR | |
279 | REDIST_STR | |
280 | FRR_REDIST_HELP_STR_RIPNGD | |
281 | "Metric\n" | |
282 | "Metric value\n" | |
283 | "Route map reference\n" | |
284 | "Pointer to route-map entries\n") | |
285 | { | |
286 | if (!no) { | |
287 | nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL); | |
288 | nb_cli_enqueue_change(vty, "./route-map", | |
95ce849b | 289 | route_map ? NB_OP_MODIFY : NB_OP_DESTROY, |
db2038c7 RW |
290 | route_map); |
291 | nb_cli_enqueue_change(vty, "./metric", | |
95ce849b | 292 | metric_str ? NB_OP_MODIFY : NB_OP_DESTROY, |
db2038c7 RW |
293 | metric_str); |
294 | } else | |
95ce849b | 295 | nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL); |
db2038c7 RW |
296 | |
297 | return nb_cli_apply_changes(vty, "./redistribute[protocol='%s']", | |
298 | protocol); | |
299 | } | |
300 | ||
301 | void cli_show_ripng_redistribute(struct vty *vty, struct lyd_node *dnode, | |
302 | bool show_defaults) | |
303 | { | |
304 | vty_out(vty, " redistribute %s", | |
305 | yang_dnode_get_string(dnode, "./protocol")); | |
306 | if (yang_dnode_exists(dnode, "./metric")) | |
307 | vty_out(vty, " metric %s", | |
308 | yang_dnode_get_string(dnode, "./metric")); | |
309 | if (yang_dnode_exists(dnode, "./route-map")) | |
310 | vty_out(vty, " route-map %s", | |
311 | yang_dnode_get_string(dnode, "./route-map")); | |
312 | vty_out(vty, "\n"); | |
313 | } | |
314 | ||
521d1b12 RW |
315 | /* |
316 | * XPath: /frr-ripngd:ripngd/instance/static-route | |
317 | */ | |
318 | DEFPY (ripng_route, | |
319 | ripng_route_cmd, | |
320 | "[no] route X:X::X:X/M", | |
321 | NO_STR | |
322 | "Static route setup\n" | |
323 | "Set static RIPng route announcement\n") | |
324 | { | |
325 | nb_cli_enqueue_change(vty, "./static-route", | |
95ce849b | 326 | no ? NB_OP_DESTROY : NB_OP_CREATE, route_str); |
521d1b12 RW |
327 | |
328 | return nb_cli_apply_changes(vty, NULL); | |
329 | } | |
330 | ||
331 | void cli_show_ripng_route(struct vty *vty, struct lyd_node *dnode, | |
332 | bool show_defaults) | |
333 | { | |
334 | vty_out(vty, " route %s\n", yang_dnode_get_string(dnode, NULL)); | |
335 | } | |
336 | ||
6fc29385 RW |
337 | /* |
338 | * XPath: /frr-ripngd:ripngd/instance/aggregate-addres | |
339 | */ | |
340 | DEFPY (ripng_aggregate_address, | |
341 | ripng_aggregate_address_cmd, | |
342 | "[no] aggregate-address X:X::X:X/M", | |
343 | NO_STR | |
344 | "Set aggregate RIPng route announcement\n" | |
345 | "Aggregate network\n") | |
346 | { | |
347 | nb_cli_enqueue_change(vty, "./aggregate-address", | |
95ce849b | 348 | no ? NB_OP_DESTROY : NB_OP_CREATE, |
6fc29385 RW |
349 | aggregate_address_str); |
350 | ||
351 | return nb_cli_apply_changes(vty, NULL); | |
352 | } | |
353 | ||
354 | void cli_show_ripng_aggregate_address(struct vty *vty, struct lyd_node *dnode, | |
355 | bool show_defaults) | |
356 | { | |
357 | vty_out(vty, " aggregate-address %s\n", | |
358 | yang_dnode_get_string(dnode, NULL)); | |
359 | } | |
360 | ||
f8981ec5 RW |
361 | /* |
362 | * XPath: /frr-ripngd:ripngd/instance/timers | |
363 | */ | |
364 | DEFPY (ripng_timers, | |
365 | ripng_timers_cmd, | |
366 | "timers basic (1-65535)$update (1-65535)$timeout (1-65535)$garbage", | |
367 | "RIPng timers setup\n" | |
368 | "Basic timer\n" | |
369 | "Routing table update timer value in second. Default is 30.\n" | |
370 | "Routing information timeout timer. Default is 180.\n" | |
371 | "Garbage collection timer. Default is 120.\n") | |
372 | { | |
373 | nb_cli_enqueue_change(vty, "./update-interval", NB_OP_MODIFY, | |
374 | update_str); | |
375 | nb_cli_enqueue_change(vty, "./holddown-interval", NB_OP_MODIFY, | |
376 | timeout_str); | |
377 | nb_cli_enqueue_change(vty, "./flush-interval", NB_OP_MODIFY, | |
378 | garbage_str); | |
379 | ||
380 | return nb_cli_apply_changes(vty, "./timers"); | |
381 | } | |
382 | ||
383 | DEFPY (no_ripng_timers, | |
384 | no_ripng_timers_cmd, | |
385 | "no timers basic [(1-65535) (1-65535) (1-65535)]", | |
386 | NO_STR | |
387 | "RIPng timers setup\n" | |
388 | "Basic timer\n" | |
389 | "Routing table update timer value in second. Default is 30.\n" | |
390 | "Routing information timeout timer. Default is 180.\n" | |
391 | "Garbage collection timer. Default is 120.\n") | |
392 | { | |
393 | nb_cli_enqueue_change(vty, "./update-interval", NB_OP_MODIFY, NULL); | |
394 | nb_cli_enqueue_change(vty, "./holddown-interval", NB_OP_MODIFY, NULL); | |
395 | nb_cli_enqueue_change(vty, "./flush-interval", NB_OP_MODIFY, NULL); | |
396 | ||
397 | return nb_cli_apply_changes(vty, "./timers"); | |
398 | } | |
399 | ||
400 | void cli_show_ripng_timers(struct vty *vty, struct lyd_node *dnode, | |
401 | bool show_defaults) | |
402 | { | |
403 | vty_out(vty, " timers basic %s %s %s\n", | |
404 | yang_dnode_get_string(dnode, "./update-interval"), | |
405 | yang_dnode_get_string(dnode, "./holddown-interval"), | |
406 | yang_dnode_get_string(dnode, "./flush-interval")); | |
407 | } | |
408 | ||
d406db4c RW |
409 | /* |
410 | * XPath: /frr-interface:lib/interface/frr-ripngd:ripng/split-horizon | |
411 | */ | |
412 | DEFPY (ipv6_ripng_split_horizon, | |
413 | ipv6_ripng_split_horizon_cmd, | |
414 | "[no] ipv6 ripng split-horizon [poisoned-reverse$poisoned_reverse]", | |
415 | NO_STR | |
416 | IPV6_STR | |
417 | "Routing Information Protocol\n" | |
418 | "Perform split horizon\n" | |
419 | "With poisoned-reverse\n") | |
420 | { | |
421 | const char *value; | |
422 | ||
423 | if (no) | |
424 | value = "disabled"; | |
425 | else if (poisoned_reverse) | |
426 | value = "poison-reverse"; | |
427 | else | |
428 | value = "simple"; | |
429 | ||
430 | nb_cli_enqueue_change(vty, "./split-horizon", NB_OP_MODIFY, value); | |
431 | ||
432 | return nb_cli_apply_changes(vty, "./frr-ripngd:ripng"); | |
433 | } | |
434 | ||
435 | void cli_show_ipv6_ripng_split_horizon(struct vty *vty, struct lyd_node *dnode, | |
436 | bool show_defaults) | |
437 | { | |
438 | int value; | |
439 | ||
440 | value = yang_dnode_get_enum(dnode, NULL); | |
441 | switch (value) { | |
442 | case RIPNG_NO_SPLIT_HORIZON: | |
443 | vty_out(vty, " no ipv6 ripng split-horizon\n"); | |
444 | break; | |
445 | case RIPNG_SPLIT_HORIZON: | |
446 | vty_out(vty, " ipv6 ripng split-horizon\n"); | |
447 | break; | |
448 | case RIPNG_SPLIT_HORIZON_POISONED_REVERSE: | |
449 | vty_out(vty, " ipv6 ripng split-horizon poisoned-reverse\n"); | |
450 | break; | |
451 | } | |
452 | } | |
453 | ||
49e06d25 RW |
454 | /* |
455 | * XPath: /frr-ripngd:clear-ripng-route | |
456 | */ | |
457 | DEFPY (clear_ipv6_rip, | |
458 | clear_ipv6_rip_cmd, | |
459 | "clear ipv6 ripng", | |
460 | CLEAR_STR | |
461 | IPV6_STR | |
462 | "Clear IPv6 RIP database\n") | |
463 | { | |
464 | return nb_cli_rpc("/frr-ripngd:clear-ripng-route", NULL, NULL); | |
465 | } | |
466 | ||
e9ce224b RW |
467 | void ripng_cli_init(void) |
468 | { | |
9a12e9e5 RW |
469 | install_element(CONFIG_NODE, &router_ripng_cmd); |
470 | install_element(CONFIG_NODE, &no_router_ripng_cmd); | |
1e42a07c RW |
471 | |
472 | install_element(RIPNG_NODE, &ripng_allow_ecmp_cmd); | |
54b56562 | 473 | install_element(RIPNG_NODE, &ripng_default_information_originate_cmd); |
ad8778c0 RW |
474 | install_element(RIPNG_NODE, &ripng_default_metric_cmd); |
475 | install_element(RIPNG_NODE, &no_ripng_default_metric_cmd); | |
cc48702b RW |
476 | install_element(RIPNG_NODE, &ripng_network_prefix_cmd); |
477 | install_element(RIPNG_NODE, &ripng_network_if_cmd); | |
b09956ca | 478 | install_element(RIPNG_NODE, &ripng_offset_list_cmd); |
22e8c7ae | 479 | install_element(RIPNG_NODE, &ripng_passive_interface_cmd); |
db2038c7 | 480 | install_element(RIPNG_NODE, &ripng_redistribute_cmd); |
521d1b12 | 481 | install_element(RIPNG_NODE, &ripng_route_cmd); |
6fc29385 | 482 | install_element(RIPNG_NODE, &ripng_aggregate_address_cmd); |
f8981ec5 RW |
483 | install_element(RIPNG_NODE, &ripng_timers_cmd); |
484 | install_element(RIPNG_NODE, &no_ripng_timers_cmd); | |
d406db4c RW |
485 | |
486 | install_element(INTERFACE_NODE, &ipv6_ripng_split_horizon_cmd); | |
49e06d25 RW |
487 | |
488 | install_element(ENABLE_NODE, &clear_ipv6_rip_cmd); | |
e9ce224b | 489 | } |