Line data Source code
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 "table.h"
28 : #include "command.h"
29 : #include "routemap.h"
30 : #include "agg_table.h"
31 : #include "northbound.h"
32 : #include "libfrr.h"
33 :
34 : #include "ripngd/ripngd.h"
35 : #include "ripngd/ripng_nb.h"
36 : #include "ripngd/ripng_debug.h"
37 : #include "ripngd/ripng_route.h"
38 :
39 : /*
40 : * XPath: /frr-ripngd:ripngd/instance
41 : */
42 3 : int ripngd_instance_create(struct nb_cb_create_args *args)
43 : {
44 3 : struct ripng *ripng;
45 3 : struct vrf *vrf;
46 3 : const char *vrf_name;
47 3 : int socket;
48 :
49 3 : vrf_name = yang_dnode_get_string(args->dnode, "./vrf");
50 3 : vrf = vrf_lookup_by_name(vrf_name);
51 :
52 : /*
53 : * Try to create a RIPng socket only if the VRF is enabled, otherwise
54 : * create a disabled RIPng instance and wait for the VRF to be enabled.
55 : */
56 3 : switch (args->event) {
57 : case NB_EV_VALIDATE:
58 : break;
59 1 : case NB_EV_PREPARE:
60 1 : if (!vrf || !vrf_is_enabled(vrf))
61 : break;
62 :
63 1 : socket = ripng_make_socket(vrf);
64 1 : if (socket < 0)
65 : return NB_ERR_RESOURCE;
66 1 : args->resource->fd = socket;
67 1 : break;
68 0 : case NB_EV_ABORT:
69 0 : if (!vrf || !vrf_is_enabled(vrf))
70 : break;
71 :
72 0 : socket = args->resource->fd;
73 0 : close(socket);
74 0 : break;
75 1 : case NB_EV_APPLY:
76 1 : if (vrf && vrf_is_enabled(vrf))
77 1 : socket = args->resource->fd;
78 : else
79 : socket = -1;
80 :
81 1 : ripng = ripng_create(vrf_name, vrf, socket);
82 1 : nb_running_set_entry(args->dnode, ripng);
83 1 : break;
84 : }
85 :
86 : return NB_OK;
87 : }
88 :
89 0 : int ripngd_instance_destroy(struct nb_cb_destroy_args *args)
90 : {
91 0 : struct ripng *ripng;
92 :
93 0 : if (args->event != NB_EV_APPLY)
94 : return NB_OK;
95 :
96 0 : ripng = nb_running_unset_entry(args->dnode);
97 0 : ripng_clean(ripng);
98 :
99 0 : return NB_OK;
100 : }
101 :
102 0 : const void *ripngd_instance_get_next(struct nb_cb_get_next_args *args)
103 : {
104 0 : struct ripng *ripng = (struct ripng *)args->list_entry;
105 :
106 0 : if (args->list_entry == NULL)
107 0 : ripng = RB_MIN(ripng_instance_head, &ripng_instances);
108 : else
109 0 : ripng = RB_NEXT(ripng_instance_head, ripng);
110 :
111 0 : return ripng;
112 : }
113 :
114 0 : int ripngd_instance_get_keys(struct nb_cb_get_keys_args *args)
115 : {
116 0 : const struct ripng *ripng = args->list_entry;
117 :
118 0 : args->keys->num = 1;
119 0 : strlcpy(args->keys->key[0], ripng->vrf_name,
120 : sizeof(args->keys->key[0]));
121 :
122 0 : return NB_OK;
123 : }
124 :
125 0 : const void *ripngd_instance_lookup_entry(struct nb_cb_lookup_entry_args *args)
126 : {
127 0 : const char *vrf_name = args->keys->key[0];
128 :
129 0 : return ripng_lookup_by_vrf_name(vrf_name);
130 : }
131 :
132 : /*
133 : * XPath: /frr-ripngd:ripngd/instance/allow-ecmp
134 : */
135 0 : int ripngd_instance_allow_ecmp_modify(struct nb_cb_modify_args *args)
136 : {
137 0 : struct ripng *ripng;
138 :
139 0 : if (args->event != NB_EV_APPLY)
140 : return NB_OK;
141 :
142 0 : ripng = nb_running_get_entry(args->dnode, NULL, true);
143 0 : ripng->ecmp = yang_dnode_get_bool(args->dnode, NULL);
144 0 : if (!ripng->ecmp)
145 0 : ripng_ecmp_disable(ripng);
146 :
147 : return NB_OK;
148 : }
149 :
150 : /*
151 : * XPath: /frr-ripngd:ripngd/instance/default-information-originate
152 : */
153 0 : int ripngd_instance_default_information_originate_modify(
154 : struct nb_cb_modify_args *args)
155 : {
156 0 : struct ripng *ripng;
157 0 : bool default_information;
158 0 : struct prefix_ipv6 p;
159 :
160 0 : if (args->event != NB_EV_APPLY)
161 : return NB_OK;
162 :
163 0 : ripng = nb_running_get_entry(args->dnode, NULL, true);
164 0 : default_information = yang_dnode_get_bool(args->dnode, NULL);
165 :
166 0 : (void)str2prefix_ipv6("::/0", &p);
167 0 : if (default_information) {
168 0 : ripng_redistribute_add(ripng, ZEBRA_ROUTE_RIPNG,
169 : RIPNG_ROUTE_DEFAULT, &p, 0, NULL, 0);
170 : } else {
171 0 : ripng_redistribute_delete(ripng, ZEBRA_ROUTE_RIPNG,
172 : RIPNG_ROUTE_DEFAULT, &p, 0);
173 : }
174 :
175 : return NB_OK;
176 : }
177 :
178 : /*
179 : * XPath: /frr-ripngd:ripngd/instance/default-metric
180 : */
181 0 : int ripngd_instance_default_metric_modify(struct nb_cb_modify_args *args)
182 : {
183 0 : struct ripng *ripng;
184 :
185 0 : if (args->event != NB_EV_APPLY)
186 : return NB_OK;
187 :
188 0 : ripng = nb_running_get_entry(args->dnode, NULL, true);
189 0 : ripng->default_metric = yang_dnode_get_uint8(args->dnode, NULL);
190 :
191 0 : return NB_OK;
192 : }
193 :
194 : /*
195 : * XPath: /frr-ripngd:ripngd/instance/network
196 : */
197 3 : int ripngd_instance_network_create(struct nb_cb_create_args *args)
198 : {
199 3 : struct ripng *ripng;
200 3 : struct prefix p;
201 :
202 3 : if (args->event != NB_EV_APPLY)
203 : return NB_OK;
204 :
205 1 : ripng = nb_running_get_entry(args->dnode, NULL, true);
206 1 : yang_dnode_get_ipv6p(&p, args->dnode, NULL);
207 1 : apply_mask_ipv6((struct prefix_ipv6 *)&p);
208 :
209 1 : return ripng_enable_network_add(ripng, &p);
210 : }
211 :
212 0 : int ripngd_instance_network_destroy(struct nb_cb_destroy_args *args)
213 : {
214 0 : struct ripng *ripng;
215 0 : struct prefix p;
216 :
217 0 : if (args->event != NB_EV_APPLY)
218 : return NB_OK;
219 :
220 0 : ripng = nb_running_get_entry(args->dnode, NULL, true);
221 0 : yang_dnode_get_ipv6p(&p, args->dnode, NULL);
222 0 : apply_mask_ipv6((struct prefix_ipv6 *)&p);
223 :
224 0 : return ripng_enable_network_delete(ripng, &p);
225 : }
226 :
227 : /*
228 : * XPath: /frr-ripngd:ripngd/instance/interface
229 : */
230 0 : int ripngd_instance_interface_create(struct nb_cb_create_args *args)
231 : {
232 0 : struct ripng *ripng;
233 0 : const char *ifname;
234 :
235 0 : if (args->event != NB_EV_APPLY)
236 : return NB_OK;
237 :
238 0 : ripng = nb_running_get_entry(args->dnode, NULL, true);
239 0 : ifname = yang_dnode_get_string(args->dnode, NULL);
240 :
241 0 : return ripng_enable_if_add(ripng, ifname);
242 : }
243 :
244 0 : int ripngd_instance_interface_destroy(struct nb_cb_destroy_args *args)
245 : {
246 0 : struct ripng *ripng;
247 0 : const char *ifname;
248 :
249 0 : if (args->event != NB_EV_APPLY)
250 : return NB_OK;
251 :
252 0 : ripng = nb_running_get_entry(args->dnode, NULL, true);
253 0 : ifname = yang_dnode_get_string(args->dnode, NULL);
254 :
255 0 : return ripng_enable_if_delete(ripng, ifname);
256 : }
257 :
258 : /*
259 : * XPath: /frr-ripngd:ripngd/instance/offset-list
260 : */
261 0 : int ripngd_instance_offset_list_create(struct nb_cb_create_args *args)
262 : {
263 0 : struct ripng *ripng;
264 0 : const char *ifname;
265 0 : struct ripng_offset_list *offset;
266 :
267 0 : if (args->event != NB_EV_APPLY)
268 : return NB_OK;
269 :
270 0 : ripng = nb_running_get_entry(args->dnode, NULL, true);
271 0 : ifname = yang_dnode_get_string(args->dnode, "./interface");
272 :
273 0 : offset = ripng_offset_list_new(ripng, ifname);
274 0 : nb_running_set_entry(args->dnode, offset);
275 :
276 0 : return NB_OK;
277 : }
278 :
279 0 : int ripngd_instance_offset_list_destroy(struct nb_cb_destroy_args *args)
280 : {
281 0 : int direct;
282 0 : struct ripng_offset_list *offset;
283 :
284 0 : if (args->event != NB_EV_APPLY)
285 : return NB_OK;
286 :
287 0 : direct = yang_dnode_get_enum(args->dnode, "./direction");
288 :
289 0 : offset = nb_running_unset_entry(args->dnode);
290 0 : if (offset->direct[direct].alist_name) {
291 0 : free(offset->direct[direct].alist_name);
292 0 : offset->direct[direct].alist_name = NULL;
293 : }
294 0 : if (offset->direct[RIPNG_OFFSET_LIST_IN].alist_name == NULL
295 0 : && offset->direct[RIPNG_OFFSET_LIST_OUT].alist_name == NULL)
296 0 : ripng_offset_list_del(offset);
297 :
298 : return NB_OK;
299 : }
300 :
301 : /*
302 : * XPath: /frr-ripngd:ripngd/instance/offset-list/access-list
303 : */
304 0 : int ripngd_instance_offset_list_access_list_modify(
305 : struct nb_cb_modify_args *args)
306 : {
307 0 : int direct;
308 0 : struct ripng_offset_list *offset;
309 0 : const char *alist_name;
310 :
311 0 : if (args->event != NB_EV_APPLY)
312 : return NB_OK;
313 :
314 0 : direct = yang_dnode_get_enum(args->dnode, "../direction");
315 0 : alist_name = yang_dnode_get_string(args->dnode, NULL);
316 :
317 0 : offset = nb_running_get_entry(args->dnode, NULL, true);
318 0 : if (offset->direct[direct].alist_name)
319 0 : free(offset->direct[direct].alist_name);
320 0 : offset->direct[direct].alist_name = strdup(alist_name);
321 :
322 0 : return NB_OK;
323 : }
324 :
325 : /*
326 : * XPath: /frr-ripngd:ripngd/instance/offset-list/metric
327 : */
328 0 : int ripngd_instance_offset_list_metric_modify(struct nb_cb_modify_args *args)
329 : {
330 0 : int direct;
331 0 : uint8_t metric;
332 0 : struct ripng_offset_list *offset;
333 :
334 0 : if (args->event != NB_EV_APPLY)
335 : return NB_OK;
336 :
337 0 : direct = yang_dnode_get_enum(args->dnode, "../direction");
338 0 : metric = yang_dnode_get_uint8(args->dnode, NULL);
339 :
340 0 : offset = nb_running_get_entry(args->dnode, NULL, true);
341 0 : offset->direct[direct].metric = metric;
342 :
343 0 : return NB_OK;
344 : }
345 :
346 : /*
347 : * XPath: /frr-ripngd:ripngd/instance/passive-interface
348 : */
349 0 : int ripngd_instance_passive_interface_create(struct nb_cb_create_args *args)
350 : {
351 0 : struct ripng *ripng;
352 0 : const char *ifname;
353 :
354 0 : if (args->event != NB_EV_APPLY)
355 : return NB_OK;
356 :
357 0 : ripng = nb_running_get_entry(args->dnode, NULL, true);
358 0 : ifname = yang_dnode_get_string(args->dnode, NULL);
359 :
360 0 : return ripng_passive_interface_set(ripng, ifname);
361 : }
362 :
363 0 : int ripngd_instance_passive_interface_destroy(struct nb_cb_destroy_args *args)
364 : {
365 0 : struct ripng *ripng;
366 0 : const char *ifname;
367 :
368 0 : if (args->event != NB_EV_APPLY)
369 : return NB_OK;
370 :
371 0 : ripng = nb_running_get_entry(args->dnode, NULL, true);
372 0 : ifname = yang_dnode_get_string(args->dnode, NULL);
373 :
374 0 : return ripng_passive_interface_unset(ripng, ifname);
375 : }
376 :
377 : /*
378 : * XPath: /frr-ripngd:ripngd/instance/redistribute
379 : */
380 0 : int ripngd_instance_redistribute_create(struct nb_cb_create_args *args)
381 : {
382 0 : struct ripng *ripng;
383 0 : int type;
384 :
385 0 : if (args->event != NB_EV_APPLY)
386 : return NB_OK;
387 :
388 0 : ripng = nb_running_get_entry(args->dnode, NULL, true);
389 0 : type = yang_dnode_get_enum(args->dnode, "./protocol");
390 :
391 0 : ripng->redist[type].enabled = true;
392 :
393 0 : return NB_OK;
394 : }
395 :
396 0 : int ripngd_instance_redistribute_destroy(struct nb_cb_destroy_args *args)
397 : {
398 0 : struct ripng *ripng;
399 0 : int type;
400 :
401 0 : if (args->event != NB_EV_APPLY)
402 : return NB_OK;
403 :
404 0 : ripng = nb_running_get_entry(args->dnode, NULL, true);
405 0 : type = yang_dnode_get_enum(args->dnode, "./protocol");
406 :
407 0 : ripng->redist[type].enabled = false;
408 0 : if (ripng->redist[type].route_map.name) {
409 0 : free(ripng->redist[type].route_map.name);
410 0 : ripng->redist[type].route_map.name = NULL;
411 0 : ripng->redist[type].route_map.map = NULL;
412 : }
413 0 : ripng->redist[type].metric_config = false;
414 0 : ripng->redist[type].metric = 0;
415 :
416 0 : if (ripng->enabled)
417 0 : ripng_redistribute_conf_delete(ripng, type);
418 :
419 : return NB_OK;
420 : }
421 :
422 0 : void ripngd_instance_redistribute_apply_finish(
423 : struct nb_cb_apply_finish_args *args)
424 : {
425 0 : struct ripng *ripng;
426 0 : int type;
427 :
428 0 : ripng = nb_running_get_entry(args->dnode, NULL, true);
429 0 : type = yang_dnode_get_enum(args->dnode, "./protocol");
430 :
431 0 : if (ripng->enabled)
432 0 : ripng_redistribute_conf_update(ripng, type);
433 0 : }
434 :
435 : /*
436 : * XPath: /frr-ripngd:ripngd/instance/redistribute/route-map
437 : */
438 0 : int ripngd_instance_redistribute_route_map_modify(
439 : struct nb_cb_modify_args *args)
440 : {
441 0 : struct ripng *ripng;
442 0 : int type;
443 0 : const char *rmap_name;
444 :
445 0 : if (args->event != NB_EV_APPLY)
446 : return NB_OK;
447 :
448 0 : ripng = nb_running_get_entry(args->dnode, NULL, true);
449 0 : type = yang_dnode_get_enum(args->dnode, "../protocol");
450 0 : rmap_name = yang_dnode_get_string(args->dnode, NULL);
451 :
452 0 : if (ripng->redist[type].route_map.name)
453 0 : free(ripng->redist[type].route_map.name);
454 0 : ripng->redist[type].route_map.name = strdup(rmap_name);
455 0 : ripng->redist[type].route_map.map = route_map_lookup_by_name(rmap_name);
456 :
457 0 : return NB_OK;
458 : }
459 :
460 0 : int ripngd_instance_redistribute_route_map_destroy(
461 : struct nb_cb_destroy_args *args)
462 : {
463 0 : struct ripng *ripng;
464 0 : int type;
465 :
466 0 : if (args->event != NB_EV_APPLY)
467 : return NB_OK;
468 :
469 0 : ripng = nb_running_get_entry(args->dnode, NULL, true);
470 0 : type = yang_dnode_get_enum(args->dnode, "../protocol");
471 :
472 0 : free(ripng->redist[type].route_map.name);
473 0 : ripng->redist[type].route_map.name = NULL;
474 0 : ripng->redist[type].route_map.map = NULL;
475 :
476 0 : return NB_OK;
477 : }
478 :
479 : /*
480 : * XPath: /frr-ripngd:ripngd/instance/redistribute/metric
481 : */
482 0 : int ripngd_instance_redistribute_metric_modify(struct nb_cb_modify_args *args)
483 : {
484 0 : struct ripng *ripng;
485 0 : int type;
486 0 : uint8_t metric;
487 :
488 0 : if (args->event != NB_EV_APPLY)
489 : return NB_OK;
490 :
491 0 : ripng = nb_running_get_entry(args->dnode, NULL, true);
492 0 : type = yang_dnode_get_enum(args->dnode, "../protocol");
493 0 : metric = yang_dnode_get_uint8(args->dnode, NULL);
494 :
495 0 : ripng->redist[type].metric_config = true;
496 0 : ripng->redist[type].metric = metric;
497 :
498 0 : return NB_OK;
499 : }
500 :
501 0 : int ripngd_instance_redistribute_metric_destroy(struct nb_cb_destroy_args *args)
502 : {
503 0 : struct ripng *ripng;
504 0 : int type;
505 :
506 0 : if (args->event != NB_EV_APPLY)
507 : return NB_OK;
508 :
509 0 : ripng = nb_running_get_entry(args->dnode, NULL, true);
510 0 : type = yang_dnode_get_enum(args->dnode, "../protocol");
511 :
512 0 : ripng->redist[type].metric_config = false;
513 0 : ripng->redist[type].metric = 0;
514 :
515 0 : return NB_OK;
516 : }
517 :
518 : /*
519 : * XPath: /frr-ripngd:ripngd/instance/static-route
520 : */
521 0 : int ripngd_instance_static_route_create(struct nb_cb_create_args *args)
522 : {
523 0 : struct ripng *ripng;
524 0 : struct prefix_ipv6 p;
525 :
526 0 : if (args->event != NB_EV_APPLY)
527 : return NB_OK;
528 :
529 0 : ripng = nb_running_get_entry(args->dnode, NULL, true);
530 0 : yang_dnode_get_ipv6p(&p, args->dnode, NULL);
531 0 : apply_mask_ipv6(&p);
532 :
533 0 : ripng_redistribute_add(ripng, ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_STATIC, &p,
534 : 0, NULL, 0);
535 :
536 0 : return NB_OK;
537 : }
538 :
539 0 : int ripngd_instance_static_route_destroy(struct nb_cb_destroy_args *args)
540 : {
541 0 : struct ripng *ripng;
542 0 : struct prefix_ipv6 p;
543 :
544 0 : if (args->event != NB_EV_APPLY)
545 : return NB_OK;
546 :
547 0 : ripng = nb_running_get_entry(args->dnode, NULL, true);
548 0 : yang_dnode_get_ipv6p(&p, args->dnode, NULL);
549 0 : apply_mask_ipv6(&p);
550 :
551 0 : ripng_redistribute_delete(ripng, ZEBRA_ROUTE_RIPNG, RIPNG_ROUTE_STATIC,
552 : &p, 0);
553 :
554 0 : return NB_OK;
555 : }
556 :
557 : /*
558 : * XPath: /frr-ripngd:ripngd/instance/aggregate-address
559 : */
560 0 : int ripngd_instance_aggregate_address_create(struct nb_cb_create_args *args)
561 : {
562 0 : struct ripng *ripng;
563 0 : struct prefix_ipv6 p;
564 :
565 0 : if (args->event != NB_EV_APPLY)
566 : return NB_OK;
567 :
568 0 : ripng = nb_running_get_entry(args->dnode, NULL, true);
569 0 : yang_dnode_get_ipv6p(&p, args->dnode, NULL);
570 0 : apply_mask_ipv6(&p);
571 :
572 0 : ripng_aggregate_add(ripng, (struct prefix *)&p);
573 :
574 0 : return NB_OK;
575 : }
576 :
577 0 : int ripngd_instance_aggregate_address_destroy(struct nb_cb_destroy_args *args)
578 : {
579 0 : struct ripng *ripng;
580 0 : struct prefix_ipv6 p;
581 :
582 0 : if (args->event != NB_EV_APPLY)
583 : return NB_OK;
584 :
585 0 : ripng = nb_running_get_entry(args->dnode, NULL, true);
586 0 : yang_dnode_get_ipv6p(&p, args->dnode, NULL);
587 0 : apply_mask_ipv6(&p);
588 :
589 0 : ripng_aggregate_delete(ripng, (struct prefix *)&p);
590 :
591 0 : return NB_OK;
592 : }
593 :
594 : /*
595 : * XPath: /frr-ripngd:ripngd/instance/timers
596 : */
597 0 : void ripngd_instance_timers_apply_finish(struct nb_cb_apply_finish_args *args)
598 : {
599 0 : struct ripng *ripng;
600 :
601 0 : ripng = nb_running_get_entry(args->dnode, NULL, true);
602 :
603 : /* Reset update timer thread. */
604 0 : ripng_event(ripng, RIPNG_UPDATE_EVENT, 0);
605 0 : }
606 :
607 : /*
608 : * XPath: /frr-ripngd:ripngd/instance/timers/flush-interval
609 : */
610 0 : int ripngd_instance_timers_flush_interval_modify(struct nb_cb_modify_args *args)
611 : {
612 0 : struct ripng *ripng;
613 :
614 0 : if (args->event != NB_EV_APPLY)
615 : return NB_OK;
616 :
617 0 : ripng = nb_running_get_entry(args->dnode, NULL, true);
618 0 : ripng->garbage_time = yang_dnode_get_uint16(args->dnode, NULL);
619 :
620 0 : return NB_OK;
621 : }
622 :
623 : /*
624 : * XPath: /frr-ripngd:ripngd/instance/timers/holddown-interval
625 : */
626 0 : int ripngd_instance_timers_holddown_interval_modify(
627 : struct nb_cb_modify_args *args)
628 : {
629 0 : struct ripng *ripng;
630 :
631 0 : if (args->event != NB_EV_APPLY)
632 : return NB_OK;
633 :
634 0 : ripng = nb_running_get_entry(args->dnode, NULL, true);
635 0 : ripng->timeout_time = yang_dnode_get_uint16(args->dnode, NULL);
636 :
637 0 : return NB_OK;
638 : }
639 :
640 : /*
641 : * XPath: /frr-ripngd:ripngd/instance/timers/update-interval
642 : */
643 0 : int ripngd_instance_timers_update_interval_modify(
644 : struct nb_cb_modify_args *args)
645 : {
646 0 : struct ripng *ripng;
647 :
648 0 : if (args->event != NB_EV_APPLY)
649 : return NB_OK;
650 :
651 0 : ripng = nb_running_get_entry(args->dnode, NULL, true);
652 0 : ripng->update_time = yang_dnode_get_uint16(args->dnode, NULL);
653 :
654 0 : return NB_OK;
655 : }
656 :
657 : /*
658 : * XPath: /frr-interface:lib/interface/frr-ripngd:ripng/split-horizon
659 : */
660 0 : int lib_interface_ripng_split_horizon_modify(struct nb_cb_modify_args *args)
661 : {
662 0 : struct interface *ifp;
663 0 : struct ripng_interface *ri;
664 :
665 0 : if (args->event != NB_EV_APPLY)
666 : return NB_OK;
667 :
668 0 : ifp = nb_running_get_entry(args->dnode, NULL, true);
669 0 : ri = ifp->info;
670 0 : ri->split_horizon = yang_dnode_get_enum(args->dnode, NULL);
671 :
672 0 : return NB_OK;
673 : }
|