Line data Source code
1 : /*
2 : * Copyright (C) 2020 VmWare
3 : * Sarita Patra
4 : *
5 : * This program is free software; you can redistribute it and/or modify it
6 : * under the terms of the GNU General Public License as published by the Free
7 : * Software Foundation; either version 2 of the License, or (at your option)
8 : * any later version.
9 : *
10 : * This program is distributed in the hope that it will be useful, but WITHOUT
11 : * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 : * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 : * more details.
14 : *
15 : * You should have received a copy of the GNU General Public License along
16 : * with this program; see the file COPYING; if not, write to the Free Software
17 : * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 : */
19 :
20 : #include <zebra.h>
21 :
22 : #include "pimd.h"
23 : #include "pim_nb.h"
24 : #include "lib/northbound_cli.h"
25 : #include "pim_igmpv3.h"
26 : #include "pim_neighbor.h"
27 : #include "pim_nht.h"
28 : #include "pim_pim.h"
29 : #include "pim_mlag.h"
30 : #include "pim_bfd.h"
31 : #include "pim_static.h"
32 : #include "pim_ssm.h"
33 : #include "pim_ssmpingd.h"
34 : #include "pim_vxlan.h"
35 : #include "pim_util.h"
36 : #include "log.h"
37 : #include "lib_errors.h"
38 : #include "pim_util.h"
39 : #include "pim6_mld.h"
40 :
41 : #if PIM_IPV == 6
42 : #define pim6_msdp_err(funcname, argtype) \
43 : int funcname(struct argtype *args) \
44 : { \
45 : snprintf(args->errmsg, args->errmsg_len, \
46 : "Trying to configure MSDP in pim6d. " \
47 : "MSDP does not exist for IPv6."); \
48 : return NB_ERR_VALIDATION; \
49 : } \
50 : MACRO_REQUIRE_SEMICOLON()
51 :
52 : #define yang_dnode_get_pimaddr yang_dnode_get_ipv6
53 :
54 : #else /* PIM_IPV != 6 */
55 : #define pim6_msdp_err(funcname, argtype) \
56 : MACRO_REQUIRE_SEMICOLON()
57 :
58 : #define yang_dnode_get_pimaddr yang_dnode_get_ipv4
59 : #endif /* PIM_IPV != 6 */
60 :
61 0 : static void pim_if_membership_clear(struct interface *ifp)
62 : {
63 0 : struct pim_interface *pim_ifp;
64 :
65 0 : pim_ifp = ifp->info;
66 0 : assert(pim_ifp);
67 :
68 0 : if (pim_ifp->pim_enable && pim_ifp->gm_enable) {
69 : return;
70 : }
71 :
72 0 : pim_ifchannel_membership_clear(ifp);
73 : }
74 :
75 : /*
76 : * When PIM is disabled on interface, IGMPv3 local membership
77 : * information is not injected into PIM interface state.
78 :
79 : * The function pim_if_membership_refresh() fetches all IGMPv3 local
80 : * membership information into PIM. It is intented to be called
81 : * whenever PIM is enabled on the interface in order to collect missed
82 : * local membership information.
83 : */
84 74 : static void pim_if_membership_refresh(struct interface *ifp)
85 : {
86 74 : struct pim_interface *pim_ifp;
87 74 : struct listnode *grpnode;
88 74 : struct gm_group *grp;
89 :
90 :
91 74 : pim_ifp = ifp->info;
92 74 : assert(pim_ifp);
93 :
94 74 : if (!pim_ifp->pim_enable)
95 : return;
96 65 : if (!pim_ifp->gm_enable)
97 : return;
98 :
99 : /*
100 : * First clear off membership from all PIM (S,G) entries on the
101 : * interface
102 : */
103 :
104 24 : pim_ifchannel_membership_clear(ifp);
105 :
106 : /*
107 : * Then restore PIM (S,G) membership from all IGMPv3 (S,G) entries on
108 : * the interface
109 : */
110 :
111 : /* scan igmp groups */
112 48 : for (ALL_LIST_ELEMENTS_RO(pim_ifp->gm_group_list, grpnode, grp)) {
113 0 : struct listnode *srcnode;
114 0 : struct gm_source *src;
115 :
116 : /* scan group sources */
117 0 : for (ALL_LIST_ELEMENTS_RO(grp->group_source_list, srcnode,
118 : src)) {
119 :
120 0 : if (IGMP_SOURCE_TEST_FORWARDING(src->source_flags)) {
121 0 : pim_sgaddr sg;
122 :
123 0 : memset(&sg, 0, sizeof(sg));
124 0 : sg.src = src->source_addr;
125 0 : sg.grp = grp->group_addr;
126 0 : pim_ifchannel_local_membership_add(
127 : ifp, &sg, false /*is_vxlan*/);
128 : }
129 :
130 : } /* scan group sources */
131 : } /* scan igmp groups */
132 :
133 : /*
134 : * Finally delete every PIM (S,G) entry lacking all state info
135 : */
136 :
137 24 : pim_ifchannel_delete_on_noinfo(ifp);
138 : }
139 :
140 50 : static int pim_cmd_interface_add(struct interface *ifp)
141 : {
142 50 : struct pim_interface *pim_ifp = ifp->info;
143 :
144 50 : if (!pim_ifp)
145 41 : pim_ifp = pim_if_new(ifp, false, true, false, false);
146 : else
147 9 : pim_ifp->pim_enable = true;
148 :
149 50 : pim_if_addr_add_all(ifp);
150 50 : pim_upstream_nh_if_update(pim_ifp->pim, ifp);
151 50 : pim_if_membership_refresh(ifp);
152 :
153 50 : pim_if_create_pimreg(pim_ifp->pim);
154 50 : return 1;
155 : }
156 :
157 0 : static int pim_cmd_interface_delete(struct interface *ifp)
158 : {
159 0 : struct pim_interface *pim_ifp = ifp->info;
160 :
161 0 : if (!pim_ifp)
162 : return 1;
163 :
164 0 : pim_ifp->pim_enable = false;
165 :
166 0 : pim_if_membership_clear(ifp);
167 :
168 : /*
169 : * pim_sock_delete() removes all neighbors from
170 : * pim_ifp->pim_neighbor_list.
171 : */
172 0 : pim_sock_delete(ifp, "pim unconfigured on interface");
173 :
174 0 : if (!pim_ifp->gm_enable) {
175 0 : pim_if_addr_del_all(ifp);
176 0 : pim_upstream_nh_if_update(pim_ifp->pim, ifp);
177 0 : pim_if_delete(ifp);
178 : }
179 :
180 : return 1;
181 : }
182 :
183 0 : static int interface_pim_use_src_cmd_worker(struct interface *ifp,
184 : pim_addr source_addr, char *errmsg, size_t errmsg_len)
185 : {
186 0 : int result;
187 0 : int ret = NB_OK;
188 :
189 0 : result = pim_update_source_set(ifp, source_addr);
190 :
191 0 : switch (result) {
192 : case PIM_SUCCESS:
193 : break;
194 0 : case PIM_IFACE_NOT_FOUND:
195 0 : ret = NB_ERR;
196 0 : snprintf(errmsg, errmsg_len,
197 : "Pim not enabled on this interface %s",
198 0 : ifp->name);
199 0 : break;
200 0 : case PIM_UPDATE_SOURCE_DUP:
201 0 : ret = NB_ERR;
202 0 : snprintf(errmsg, errmsg_len, "Source already set");
203 0 : break;
204 0 : default:
205 0 : ret = NB_ERR;
206 0 : snprintf(errmsg, errmsg_len, "Source set failed");
207 : }
208 :
209 0 : return ret;
210 : }
211 :
212 0 : static int pim_cmd_spt_switchover(struct pim_instance *pim,
213 : enum pim_spt_switchover spt,
214 : const char *plist)
215 : {
216 0 : pim->spt.switchover = spt;
217 :
218 0 : switch (pim->spt.switchover) {
219 0 : case PIM_SPT_IMMEDIATE:
220 0 : XFREE(MTYPE_PIM_PLIST_NAME, pim->spt.plist);
221 :
222 0 : pim_upstream_add_lhr_star_pimreg(pim);
223 0 : break;
224 0 : case PIM_SPT_INFINITY:
225 0 : pim_upstream_remove_lhr_star_pimreg(pim, plist);
226 :
227 0 : XFREE(MTYPE_PIM_PLIST_NAME, pim->spt.plist);
228 :
229 0 : if (plist)
230 0 : pim->spt.plist = XSTRDUP(MTYPE_PIM_PLIST_NAME, plist);
231 : break;
232 : }
233 :
234 0 : return NB_OK;
235 : }
236 :
237 0 : static int pim_ssm_cmd_worker(struct pim_instance *pim, const char *plist,
238 : char *errmsg, size_t errmsg_len)
239 : {
240 0 : int result = pim_ssm_range_set(pim, pim->vrf->vrf_id, plist);
241 0 : int ret = NB_ERR;
242 :
243 0 : if (result == PIM_SSM_ERR_NONE)
244 : return NB_OK;
245 :
246 0 : switch (result) {
247 0 : case PIM_SSM_ERR_NO_VRF:
248 0 : snprintf(errmsg, errmsg_len,
249 : "VRF doesn't exist");
250 0 : break;
251 0 : case PIM_SSM_ERR_DUP:
252 0 : snprintf(errmsg, errmsg_len,
253 : "duplicate config");
254 0 : break;
255 0 : default:
256 0 : snprintf(errmsg, errmsg_len,
257 : "ssm range config failed");
258 : }
259 :
260 : return ret;
261 : }
262 :
263 4 : static int pim_rp_cmd_worker(struct pim_instance *pim, pim_addr rp_addr,
264 : struct prefix group, const char *plist,
265 : char *errmsg, size_t errmsg_len)
266 : {
267 4 : int result;
268 :
269 4 : result = pim_rp_new(pim, rp_addr, group, plist, RP_SRC_STATIC);
270 :
271 4 : if (result == PIM_RP_NO_PATH) {
272 3 : snprintfrr(errmsg, errmsg_len,
273 : "No Path to RP address specified: %pPA", &rp_addr);
274 3 : return NB_ERR_INCONSISTENCY;
275 : }
276 :
277 1 : if (result == PIM_GROUP_OVERLAP) {
278 0 : snprintf(errmsg, errmsg_len,
279 : "Group range specified cannot exact match another");
280 0 : return NB_ERR_INCONSISTENCY;
281 : }
282 :
283 1 : if (result == PIM_GROUP_PFXLIST_OVERLAP) {
284 0 : snprintf(errmsg, errmsg_len,
285 : "This group is already covered by a RP prefix-list");
286 0 : return NB_ERR_INCONSISTENCY;
287 : }
288 :
289 1 : if (result == PIM_RP_PFXLIST_IN_USE) {
290 0 : snprintf(errmsg, errmsg_len,
291 : "The same prefix-list cannot be applied to multiple RPs");
292 0 : return NB_ERR_INCONSISTENCY;
293 : }
294 :
295 : return NB_OK;
296 : }
297 :
298 0 : static int pim_no_rp_cmd_worker(struct pim_instance *pim, pim_addr rp_addr,
299 : struct prefix group, const char *plist,
300 : char *errmsg, size_t errmsg_len)
301 : {
302 0 : char group_str[PREFIX2STR_BUFFER];
303 0 : int result;
304 :
305 0 : prefix2str(&group, group_str, sizeof(group_str));
306 :
307 0 : result = pim_rp_del(pim, rp_addr, group, plist, RP_SRC_STATIC);
308 :
309 0 : if (result == PIM_GROUP_BAD_ADDRESS) {
310 0 : snprintf(errmsg, errmsg_len,
311 : "Bad group address specified: %s", group_str);
312 0 : return NB_ERR_INCONSISTENCY;
313 : }
314 :
315 0 : if (result == PIM_RP_BAD_ADDRESS) {
316 0 : snprintfrr(errmsg, errmsg_len, "Bad RP address specified: %pPA",
317 : &rp_addr);
318 0 : return NB_ERR_INCONSISTENCY;
319 : }
320 :
321 0 : if (result == PIM_RP_NOT_FOUND) {
322 0 : snprintf(errmsg, errmsg_len,
323 : "Unable to find specified RP");
324 0 : return NB_ERR_INCONSISTENCY;
325 : }
326 :
327 : return NB_OK;
328 : }
329 :
330 0 : static bool is_pim_interface(const struct lyd_node *dnode)
331 : {
332 0 : char if_xpath[XPATH_MAXLEN];
333 0 : const struct lyd_node *pim_enable_dnode;
334 0 : const struct lyd_node *igmp_enable_dnode;
335 :
336 0 : yang_dnode_get_path(dnode, if_xpath, sizeof(if_xpath));
337 0 : pim_enable_dnode =
338 0 : yang_dnode_getf(dnode,
339 : "%s/frr-pim:pim/address-family[address-family='%s']/pim-enable",
340 : if_xpath, FRR_PIM_AF_XPATH_VAL);
341 0 : igmp_enable_dnode = yang_dnode_getf(dnode,
342 : "%s/frr-gmp:gmp/address-family[address-family='%s']/enable",
343 : if_xpath, FRR_PIM_AF_XPATH_VAL);
344 :
345 0 : if (((pim_enable_dnode) &&
346 0 : (yang_dnode_get_bool(pim_enable_dnode, "."))) ||
347 0 : ((igmp_enable_dnode) &&
348 0 : (yang_dnode_get_bool(igmp_enable_dnode, "."))))
349 0 : return true;
350 :
351 : return false;
352 : }
353 :
354 24 : static int pim_cmd_gm_start(struct interface *ifp)
355 : {
356 24 : struct pim_interface *pim_ifp;
357 24 : uint8_t need_startup = 0;
358 :
359 24 : pim_ifp = ifp->info;
360 :
361 24 : if (!pim_ifp) {
362 9 : pim_ifp = pim_if_new(ifp, true, false, false, false);
363 9 : need_startup = 1;
364 : } else {
365 15 : if (!pim_ifp->gm_enable) {
366 15 : pim_ifp->gm_enable = true;
367 15 : need_startup = 1;
368 : }
369 : }
370 24 : pim_if_create_pimreg(pim_ifp->pim);
371 :
372 : /* 'ip igmp' executed multiple times, with need_startup
373 : * avoid multiple if add all and membership refresh
374 : */
375 24 : if (need_startup) {
376 24 : pim_if_addr_add_all(ifp);
377 24 : pim_if_membership_refresh(ifp);
378 : }
379 :
380 24 : return NB_OK;
381 : }
382 :
383 : /*
384 : * CLI reconfiguration affects the interface level (struct pim_interface).
385 : * This function propagates the reconfiguration to every active socket
386 : * for that interface.
387 : */
388 : #if PIM_IPV == 4
389 0 : static void igmp_sock_query_interval_reconfig(struct gm_sock *igmp)
390 : {
391 0 : struct interface *ifp;
392 0 : struct pim_interface *pim_ifp;
393 :
394 0 : assert(igmp);
395 0 : assert(igmp->interface);
396 0 : assert(igmp->interface->info);
397 :
398 0 : ifp = igmp->interface;
399 0 : pim_ifp = ifp->info;
400 :
401 0 : if (PIM_DEBUG_GM_TRACE)
402 0 : zlog_debug("%s: Querier %pPAs on %s reconfig query_interval=%d",
403 : __func__, &igmp->ifaddr, ifp->name,
404 : pim_ifp->gm_default_query_interval);
405 :
406 : /*
407 : * igmp_startup_mode_on() will reset QQI:
408 :
409 : * igmp->querier_query_interval = pim_ifp->gm_default_query_interval;
410 : */
411 0 : igmp_startup_mode_on(igmp);
412 0 : }
413 :
414 0 : static void igmp_sock_query_reschedule(struct gm_sock *igmp)
415 : {
416 0 : if (igmp->mtrace_only)
417 : return;
418 :
419 0 : if (igmp->t_igmp_query_timer) {
420 : /* other querier present */
421 0 : assert(igmp->t_igmp_query_timer);
422 0 : assert(!igmp->t_other_querier_timer);
423 :
424 0 : pim_igmp_general_query_off(igmp);
425 0 : pim_igmp_general_query_on(igmp);
426 :
427 0 : assert(igmp->t_igmp_query_timer);
428 0 : assert(!igmp->t_other_querier_timer);
429 : } else {
430 : /* this is the querier */
431 :
432 0 : assert(!igmp->t_igmp_query_timer);
433 0 : assert(igmp->t_other_querier_timer);
434 :
435 0 : pim_igmp_other_querier_timer_off(igmp);
436 0 : pim_igmp_other_querier_timer_on(igmp);
437 :
438 0 : assert(!igmp->t_igmp_query_timer);
439 0 : assert(igmp->t_other_querier_timer);
440 : }
441 : }
442 : #endif /* PIM_IPV == 4 */
443 :
444 : #if PIM_IPV == 4
445 0 : static void change_query_interval(struct pim_interface *pim_ifp,
446 : int query_interval)
447 : {
448 0 : struct listnode *sock_node;
449 0 : struct gm_sock *igmp;
450 :
451 0 : pim_ifp->gm_default_query_interval = query_interval;
452 :
453 0 : for (ALL_LIST_ELEMENTS_RO(pim_ifp->gm_socket_list, sock_node, igmp)) {
454 0 : igmp_sock_query_interval_reconfig(igmp);
455 0 : igmp_sock_query_reschedule(igmp);
456 : }
457 0 : }
458 : #endif
459 :
460 8 : static void change_query_max_response_time(struct interface *ifp,
461 : int query_max_response_time_dsec)
462 : {
463 : #if PIM_IPV == 4
464 0 : struct listnode *sock_node;
465 0 : struct gm_sock *igmp;
466 0 : struct listnode *grp_node;
467 0 : struct gm_group *grp;
468 : #endif
469 :
470 8 : struct pim_interface *pim_ifp = ifp->info;
471 :
472 8 : if (pim_ifp->gm_query_max_response_time_dsec ==
473 : query_max_response_time_dsec)
474 : return;
475 :
476 8 : pim_ifp->gm_query_max_response_time_dsec = query_max_response_time_dsec;
477 :
478 : #if PIM_IPV == 6
479 8 : gm_ifp_update(ifp);
480 : #else
481 : /*
482 : * Below we modify socket/group/source timers in order to quickly
483 : * reflect the change. Otherwise, those timers would args->eventually
484 : * catch up.
485 : */
486 :
487 : /* scan all sockets */
488 0 : for (ALL_LIST_ELEMENTS_RO(pim_ifp->gm_socket_list, sock_node, igmp)) {
489 : /* reschedule socket general query */
490 0 : igmp_sock_query_reschedule(igmp);
491 : }
492 :
493 : /* scan socket groups */
494 0 : for (ALL_LIST_ELEMENTS_RO(pim_ifp->gm_group_list, grp_node, grp)) {
495 0 : struct listnode *src_node;
496 0 : struct gm_source *src;
497 :
498 : /* reset group timers for groups in EXCLUDE mode */
499 0 : if (grp->group_filtermode_isexcl)
500 0 : igmp_group_reset_gmi(grp);
501 :
502 : /* scan group sources */
503 0 : for (ALL_LIST_ELEMENTS_RO(grp->group_source_list, src_node,
504 : src)) {
505 :
506 : /* reset source timers for sources with running
507 : * timers
508 : */
509 0 : if (src->t_source_timer)
510 0 : igmp_source_reset_gmi(grp, src);
511 : }
512 : }
513 : #endif /* PIM_IPV == 4 */
514 : }
515 :
516 4 : int routing_control_plane_protocols_name_validate(
517 : struct nb_cb_create_args *args)
518 : {
519 4 : const char *name;
520 :
521 4 : name = yang_dnode_get_string(args->dnode, "./name");
522 4 : if (!strmatch(name, "pim")) {
523 0 : snprintf(args->errmsg, args->errmsg_len,
524 : "pim supports only one instance with name pimd");
525 0 : return NB_ERR_VALIDATION;
526 : }
527 : return NB_OK;
528 : }
529 :
530 : /*
531 : * XPath: /frr-pim:pim/address-family
532 : */
533 3 : int pim_address_family_create(struct nb_cb_create_args *args)
534 : {
535 3 : switch (args->event) {
536 : case NB_EV_VALIDATE:
537 : case NB_EV_PREPARE:
538 : case NB_EV_ABORT:
539 : case NB_EV_APPLY:
540 : break;
541 : }
542 :
543 3 : return NB_OK;
544 : }
545 :
546 0 : int pim_address_family_destroy(struct nb_cb_destroy_args *args)
547 : {
548 0 : switch (args->event) {
549 : case NB_EV_VALIDATE:
550 : case NB_EV_PREPARE:
551 : case NB_EV_ABORT:
552 : case NB_EV_APPLY:
553 : break;
554 : }
555 :
556 0 : return NB_OK;
557 : }
558 :
559 : /*
560 : * XPath: /frr-pim:pim/address-family/packets
561 : */
562 0 : int pim_address_family_packets_modify(struct nb_cb_modify_args *args)
563 : {
564 0 : switch (args->event) {
565 : case NB_EV_VALIDATE:
566 : case NB_EV_PREPARE:
567 : case NB_EV_ABORT:
568 : break;
569 0 : case NB_EV_APPLY:
570 0 : router->packet_process = yang_dnode_get_uint8(args->dnode,
571 : NULL);
572 0 : break;
573 : }
574 :
575 0 : return NB_OK;
576 : }
577 :
578 : /*
579 : * XPath: /frr-pim:pim/address-family/join-prune-interval
580 : */
581 3 : int pim_address_family_join_prune_interval_modify(
582 : struct nb_cb_modify_args *args)
583 : {
584 3 : switch (args->event) {
585 : case NB_EV_VALIDATE:
586 : case NB_EV_PREPARE:
587 : case NB_EV_ABORT:
588 : break;
589 1 : case NB_EV_APPLY:
590 1 : router->t_periodic = yang_dnode_get_uint16(args->dnode, NULL);
591 1 : break;
592 : }
593 :
594 3 : return NB_OK;
595 : }
596 :
597 : /*
598 : * XPath: /frr-pim:pim/address-family/register-suppress-time
599 : */
600 0 : int pim_address_family_register_suppress_time_modify(
601 : struct nb_cb_modify_args *args)
602 : {
603 0 : uint16_t value;
604 0 : switch (args->event) {
605 0 : case NB_EV_VALIDATE:
606 0 : value = yang_dnode_get_uint16(args->dnode, NULL);
607 : /*
608 : * As soon as this is non-constant it needs to be replaced with
609 : * a yang_dnode_get to lookup the candidate value, *not* the
610 : * operational value. Since the code has a field assigned and
611 : * used for this value it should have YANG/CLI to set it too,
612 : * otherwise just use the #define!
613 : */
614 : /* RFC7761: 4.11. Timer Values */
615 0 : if (value <= router->register_probe_time * 2) {
616 0 : snprintf(
617 : args->errmsg, args->errmsg_len,
618 : "Register suppress time (%u) must be more than "
619 : "twice the register probe time (%u).",
620 : value, router->register_probe_time);
621 0 : return NB_ERR_VALIDATION;
622 : }
623 : break;
624 : case NB_EV_PREPARE:
625 : case NB_EV_ABORT:
626 : break;
627 0 : case NB_EV_APPLY:
628 0 : pim_update_suppress_timers(
629 0 : yang_dnode_get_uint16(args->dnode, NULL));
630 0 : break;
631 : }
632 :
633 : return NB_OK;
634 : }
635 :
636 : /*
637 : * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/ecmp
638 : */
639 0 : int routing_control_plane_protocols_control_plane_protocol_pim_address_family_ecmp_modify(
640 : struct nb_cb_modify_args *args)
641 : {
642 0 : struct vrf *vrf;
643 0 : struct pim_instance *pim;
644 :
645 0 : switch (args->event) {
646 : case NB_EV_VALIDATE:
647 : case NB_EV_PREPARE:
648 : case NB_EV_ABORT:
649 : break;
650 0 : case NB_EV_APPLY:
651 0 : vrf = nb_running_get_entry(args->dnode, NULL, true);
652 0 : pim = vrf->info;
653 0 : pim->ecmp_enable = yang_dnode_get_bool(args->dnode, NULL);
654 : }
655 :
656 0 : return NB_OK;
657 : }
658 :
659 : /*
660 : * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/ecmp-rebalance
661 : */
662 0 : int routing_control_plane_protocols_control_plane_protocol_pim_address_family_ecmp_rebalance_modify(
663 : struct nb_cb_modify_args *args)
664 : {
665 0 : struct vrf *vrf;
666 0 : struct pim_instance *pim;
667 :
668 0 : switch (args->event) {
669 : case NB_EV_VALIDATE:
670 : case NB_EV_PREPARE:
671 : case NB_EV_ABORT:
672 : break;
673 0 : case NB_EV_APPLY:
674 0 : vrf = nb_running_get_entry(args->dnode, NULL, true);
675 0 : pim = vrf->info;
676 0 : pim->ecmp_rebalance_enable =
677 0 : yang_dnode_get_bool(args->dnode, NULL);
678 : }
679 :
680 0 : return NB_OK;
681 : }
682 :
683 : /*
684 : * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/keep-alive-timer
685 : */
686 0 : int routing_control_plane_protocols_control_plane_protocol_pim_address_family_keep_alive_timer_modify(
687 : struct nb_cb_modify_args *args)
688 : {
689 0 : struct vrf *vrf;
690 0 : struct pim_instance *pim;
691 :
692 0 : switch (args->event) {
693 : case NB_EV_VALIDATE:
694 : case NB_EV_PREPARE:
695 : case NB_EV_ABORT:
696 : break;
697 0 : case NB_EV_APPLY:
698 0 : vrf = nb_running_get_entry(args->dnode, NULL, true);
699 0 : pim = vrf->info;
700 0 : pim->keep_alive_time = yang_dnode_get_uint16(args->dnode, NULL);
701 0 : break;
702 : }
703 :
704 0 : return NB_OK;
705 : }
706 :
707 : /*
708 : * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/rp-keep-alive-timer
709 : */
710 0 : int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_keep_alive_timer_modify(
711 : struct nb_cb_modify_args *args)
712 : {
713 0 : struct vrf *vrf;
714 0 : struct pim_instance *pim;
715 :
716 0 : switch (args->event) {
717 : case NB_EV_VALIDATE:
718 : case NB_EV_PREPARE:
719 : case NB_EV_ABORT:
720 : break;
721 0 : case NB_EV_APPLY:
722 0 : vrf = nb_running_get_entry(args->dnode, NULL, true);
723 0 : pim = vrf->info;
724 0 : pim->rp_keep_alive_time = yang_dnode_get_uint16(args->dnode,
725 : NULL);
726 0 : break;
727 : }
728 :
729 0 : return NB_OK;
730 : }
731 :
732 : /*
733 : * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family
734 : */
735 12 : int routing_control_plane_protocols_control_plane_protocol_pim_address_family_create(
736 : struct nb_cb_create_args *args)
737 : {
738 12 : switch (args->event) {
739 : case NB_EV_VALIDATE:
740 : case NB_EV_PREPARE:
741 : case NB_EV_ABORT:
742 : case NB_EV_APPLY:
743 : break;
744 : }
745 :
746 12 : return NB_OK;
747 : }
748 :
749 0 : int routing_control_plane_protocols_control_plane_protocol_pim_address_family_destroy(
750 : struct nb_cb_destroy_args *args)
751 : {
752 0 : switch (args->event) {
753 : case NB_EV_VALIDATE:
754 : case NB_EV_PREPARE:
755 : case NB_EV_ABORT:
756 : case NB_EV_APPLY:
757 : break;
758 : }
759 :
760 0 : return NB_OK;
761 : }
762 :
763 : /*
764 : * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/send-v6-secondary
765 : */
766 0 : int routing_control_plane_protocols_control_plane_protocol_pim_address_family_send_v6_secondary_modify(
767 : struct nb_cb_modify_args *args)
768 : {
769 0 : struct vrf *vrf;
770 0 : struct pim_instance *pim;
771 :
772 0 : switch (args->event) {
773 : case NB_EV_VALIDATE:
774 : case NB_EV_PREPARE:
775 : case NB_EV_ABORT:
776 : break;
777 0 : case NB_EV_APPLY:
778 0 : vrf = nb_running_get_entry(args->dnode, NULL, true);
779 0 : pim = vrf->info;
780 0 : pim->send_v6_secondary = yang_dnode_get_bool(args->dnode, NULL);
781 0 : break;
782 : }
783 :
784 0 : return NB_OK;
785 : }
786 :
787 0 : int routing_control_plane_protocols_control_plane_protocol_pim_address_family_send_v6_secondary_destroy(
788 : struct nb_cb_destroy_args *args)
789 : {
790 0 : switch (args->event) {
791 : case NB_EV_VALIDATE:
792 : case NB_EV_PREPARE:
793 : case NB_EV_ABORT:
794 : case NB_EV_APPLY:
795 : break;
796 : }
797 :
798 0 : return NB_OK;
799 : }
800 :
801 : /*
802 : * XPath:
803 : * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/spt-switchover
804 : */
805 0 : void routing_control_plane_protocols_control_plane_protocol_pim_address_family_spt_switchover_apply_finish(
806 : struct nb_cb_apply_finish_args *args)
807 : {
808 0 : struct vrf *vrf;
809 0 : struct pim_instance *pim;
810 0 : int spt_switch_action;
811 0 : const char *prefix_list = NULL;
812 :
813 0 : vrf = nb_running_get_entry(args->dnode, NULL, true);
814 0 : pim = vrf->info;
815 0 : spt_switch_action = yang_dnode_get_enum(args->dnode, "./spt-action");
816 :
817 0 : switch (spt_switch_action) {
818 0 : case PIM_SPT_INFINITY:
819 0 : if (yang_dnode_exists(args->dnode,
820 : "./spt-infinity-prefix-list"))
821 0 : prefix_list = yang_dnode_get_string(
822 : args->dnode, "./spt-infinity-prefix-list");
823 :
824 0 : pim_cmd_spt_switchover(pim, PIM_SPT_INFINITY,
825 : prefix_list);
826 0 : break;
827 0 : case PIM_SPT_IMMEDIATE:
828 0 : pim_cmd_spt_switchover(pim, PIM_SPT_IMMEDIATE, NULL);
829 : }
830 0 : }
831 :
832 : /*
833 : * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/spt-switchover/spt-action
834 : */
835 0 : int routing_control_plane_protocols_control_plane_protocol_pim_address_family_spt_switchover_spt_action_modify(
836 : struct nb_cb_modify_args *args)
837 : {
838 0 : switch (args->event) {
839 : case NB_EV_VALIDATE:
840 : case NB_EV_PREPARE:
841 : case NB_EV_ABORT:
842 : case NB_EV_APPLY:
843 : break;
844 : }
845 :
846 0 : return NB_OK;
847 : }
848 :
849 : /*
850 : * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/spt-switchover/spt-infinity-prefix-list
851 : */
852 0 : int routing_control_plane_protocols_control_plane_protocol_pim_address_family_spt_switchover_spt_infinity_prefix_list_modify(
853 : struct nb_cb_modify_args *args)
854 : {
855 0 : switch (args->event) {
856 : case NB_EV_VALIDATE:
857 : case NB_EV_PREPARE:
858 : case NB_EV_ABORT:
859 : case NB_EV_APPLY:
860 : break;
861 : }
862 :
863 0 : return NB_OK;
864 : }
865 :
866 0 : int routing_control_plane_protocols_control_plane_protocol_pim_address_family_spt_switchover_spt_infinity_prefix_list_destroy(
867 : struct nb_cb_destroy_args *args)
868 : {
869 0 : switch (args->event) {
870 : case NB_EV_VALIDATE:
871 : case NB_EV_PREPARE:
872 : case NB_EV_ABORT:
873 : case NB_EV_APPLY:
874 : break;
875 : }
876 :
877 0 : return NB_OK;
878 : }
879 :
880 : /*
881 : * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/ssm-prefix-list
882 : */
883 0 : int routing_control_plane_protocols_control_plane_protocol_pim_address_family_ssm_prefix_list_modify(
884 : struct nb_cb_modify_args *args)
885 : {
886 0 : struct vrf *vrf;
887 0 : struct pim_instance *pim;
888 0 : const char *plist_name;
889 0 : int result;
890 :
891 0 : switch (args->event) {
892 : case NB_EV_VALIDATE:
893 : case NB_EV_PREPARE:
894 : case NB_EV_ABORT:
895 : break;
896 0 : case NB_EV_APPLY:
897 0 : vrf = nb_running_get_entry(args->dnode, NULL, true);
898 0 : pim = vrf->info;
899 0 : plist_name = yang_dnode_get_string(args->dnode, NULL);
900 0 : result = pim_ssm_cmd_worker(pim, plist_name, args->errmsg,
901 : args->errmsg_len);
902 :
903 0 : if (result)
904 : return NB_ERR_INCONSISTENCY;
905 :
906 : break;
907 : }
908 :
909 : return NB_OK;
910 : }
911 :
912 0 : int routing_control_plane_protocols_control_plane_protocol_pim_address_family_ssm_prefix_list_destroy(
913 : struct nb_cb_destroy_args *args)
914 : {
915 0 : struct vrf *vrf;
916 0 : struct pim_instance *pim;
917 0 : int result;
918 :
919 0 : switch (args->event) {
920 : case NB_EV_VALIDATE:
921 : case NB_EV_PREPARE:
922 : case NB_EV_ABORT:
923 : break;
924 0 : case NB_EV_APPLY:
925 0 : vrf = nb_running_get_entry(args->dnode, NULL, true);
926 0 : pim = vrf->info;
927 0 : result = pim_ssm_cmd_worker(pim, NULL, args->errmsg,
928 : args->errmsg_len);
929 :
930 0 : if (result)
931 : return NB_ERR_INCONSISTENCY;
932 :
933 : break;
934 : }
935 :
936 : return NB_OK;
937 : }
938 :
939 : /*
940 : * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/ssm-pingd-source-ip
941 : */
942 0 : int routing_control_plane_protocols_control_plane_protocol_pim_address_family_ssm_pingd_source_ip_create(
943 : struct nb_cb_create_args *args)
944 : {
945 0 : struct vrf *vrf;
946 0 : struct pim_instance *pim;
947 0 : int result;
948 0 : pim_addr source_addr;
949 :
950 0 : switch (args->event) {
951 : case NB_EV_VALIDATE:
952 : case NB_EV_PREPARE:
953 : case NB_EV_ABORT:
954 : break;
955 0 : case NB_EV_APPLY:
956 0 : vrf = nb_running_get_entry(args->dnode, NULL, true);
957 0 : pim = vrf->info;
958 0 : yang_dnode_get_pimaddr(&source_addr, args->dnode,
959 : "./source-addr");
960 0 : result = pim_ssmpingd_start(pim, source_addr);
961 0 : if (result) {
962 0 : snprintf(
963 : args->errmsg, args->errmsg_len,
964 : "%% Failure starting ssmpingd for source %pPA: %d",
965 : &source_addr, result);
966 0 : return NB_ERR_INCONSISTENCY;
967 : }
968 : }
969 :
970 : return NB_OK;
971 : }
972 :
973 0 : int routing_control_plane_protocols_control_plane_protocol_pim_address_family_ssm_pingd_source_ip_destroy(
974 : struct nb_cb_destroy_args *args)
975 : {
976 0 : struct vrf *vrf;
977 0 : struct pim_instance *pim;
978 0 : int result;
979 0 : pim_addr source_addr;
980 :
981 0 : switch (args->event) {
982 : case NB_EV_VALIDATE:
983 : case NB_EV_PREPARE:
984 : case NB_EV_ABORT:
985 : break;
986 0 : case NB_EV_APPLY:
987 0 : vrf = nb_running_get_entry(args->dnode, NULL, true);
988 0 : pim = vrf->info;
989 0 : yang_dnode_get_pimaddr(&source_addr, args->dnode,
990 : "./source-addr");
991 0 : result = pim_ssmpingd_stop(pim, source_addr);
992 0 : if (result) {
993 0 : snprintf(
994 : args->errmsg, args->errmsg_len,
995 : "%% Failure stopping ssmpingd for source %pPA: %d",
996 : &source_addr, result);
997 0 : return NB_ERR_INCONSISTENCY;
998 : }
999 :
1000 : break;
1001 : }
1002 :
1003 : return NB_OK;
1004 : }
1005 :
1006 : /*
1007 : * XPath:
1008 : * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp/hold-time
1009 : */
1010 0 : int pim_msdp_hold_time_modify(struct nb_cb_modify_args *args)
1011 : {
1012 0 : struct pim_instance *pim;
1013 0 : struct vrf *vrf;
1014 :
1015 0 : switch (args->event) {
1016 : case NB_EV_VALIDATE:
1017 : case NB_EV_PREPARE:
1018 : case NB_EV_ABORT:
1019 : break;
1020 0 : case NB_EV_APPLY:
1021 0 : vrf = nb_running_get_entry(args->dnode, NULL, true);
1022 0 : pim = vrf->info;
1023 0 : pim->msdp.hold_time = yang_dnode_get_uint16(args->dnode, NULL);
1024 0 : break;
1025 : }
1026 :
1027 0 : return NB_OK;
1028 : }
1029 :
1030 : /*
1031 : * XPath:
1032 : * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp/keep-alive
1033 : */
1034 0 : int pim_msdp_keep_alive_modify(struct nb_cb_modify_args *args)
1035 : {
1036 0 : struct pim_instance *pim;
1037 0 : struct vrf *vrf;
1038 :
1039 0 : switch (args->event) {
1040 : case NB_EV_VALIDATE:
1041 : case NB_EV_PREPARE:
1042 : case NB_EV_ABORT:
1043 : break;
1044 0 : case NB_EV_APPLY:
1045 0 : vrf = nb_running_get_entry(args->dnode, NULL, true);
1046 0 : pim = vrf->info;
1047 0 : pim->msdp.keep_alive = yang_dnode_get_uint16(args->dnode, NULL);
1048 0 : break;
1049 : }
1050 :
1051 0 : return NB_OK;
1052 : }
1053 :
1054 : /*
1055 : * XPath:
1056 : * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp/connection-retry
1057 : */
1058 0 : int pim_msdp_connection_retry_modify(struct nb_cb_modify_args *args)
1059 : {
1060 0 : struct pim_instance *pim;
1061 0 : struct vrf *vrf;
1062 :
1063 0 : switch (args->event) {
1064 : case NB_EV_VALIDATE:
1065 : case NB_EV_PREPARE:
1066 : case NB_EV_ABORT:
1067 : break;
1068 0 : case NB_EV_APPLY:
1069 0 : vrf = nb_running_get_entry(args->dnode, NULL, true);
1070 0 : pim = vrf->info;
1071 0 : pim->msdp.connection_retry =
1072 0 : yang_dnode_get_uint16(args->dnode, NULL);
1073 0 : break;
1074 : }
1075 :
1076 0 : return NB_OK;
1077 : }
1078 :
1079 0 : pim6_msdp_err(pim_msdp_mesh_group_destroy, nb_cb_destroy_args);
1080 0 : pim6_msdp_err(pim_msdp_mesh_group_create, nb_cb_create_args);
1081 0 : pim6_msdp_err(pim_msdp_mesh_group_source_modify, nb_cb_modify_args);
1082 0 : pim6_msdp_err(pim_msdp_mesh_group_source_destroy, nb_cb_destroy_args);
1083 0 : pim6_msdp_err(pim_msdp_mesh_group_members_create, nb_cb_create_args);
1084 0 : pim6_msdp_err(pim_msdp_mesh_group_members_destroy, nb_cb_destroy_args);
1085 0 : pim6_msdp_err(routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_peer_source_ip_modify,
1086 : nb_cb_modify_args);
1087 0 : pim6_msdp_err(routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_peer_destroy,
1088 : nb_cb_destroy_args);
1089 0 : pim6_msdp_err(routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_peer_create,
1090 : nb_cb_create_args);
1091 :
1092 : #if PIM_IPV != 6
1093 : /*
1094 : * XPath:
1095 : * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp-mesh-groups
1096 : */
1097 0 : int pim_msdp_mesh_group_create(struct nb_cb_create_args *args)
1098 : {
1099 0 : struct pim_msdp_mg *mg;
1100 0 : struct vrf *vrf;
1101 :
1102 0 : switch (args->event) {
1103 : case NB_EV_VALIDATE:
1104 : case NB_EV_PREPARE:
1105 : case NB_EV_ABORT:
1106 : break;
1107 0 : case NB_EV_APPLY:
1108 0 : vrf = nb_running_get_entry(args->dnode, NULL, true);
1109 0 : mg = pim_msdp_mg_new(vrf->info, yang_dnode_get_string(
1110 : args->dnode, "./name"));
1111 0 : nb_running_set_entry(args->dnode, mg);
1112 0 : break;
1113 : }
1114 :
1115 0 : return NB_OK;
1116 : }
1117 :
1118 0 : int pim_msdp_mesh_group_destroy(struct nb_cb_destroy_args *args)
1119 : {
1120 0 : struct pim_msdp_mg *mg;
1121 0 : struct vrf *vrf;
1122 :
1123 0 : switch (args->event) {
1124 : case NB_EV_VALIDATE:
1125 : case NB_EV_PREPARE:
1126 : case NB_EV_ABORT:
1127 : break;
1128 0 : case NB_EV_APPLY:
1129 0 : mg = nb_running_unset_entry(args->dnode);
1130 0 : vrf = nb_running_get_entry(args->dnode, NULL, true);
1131 0 : pim_msdp_mg_free(vrf->info, &mg);
1132 0 : break;
1133 : }
1134 :
1135 0 : return NB_OK;
1136 : }
1137 :
1138 : /*
1139 : * XPath:
1140 : * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp-mesh-groups/source
1141 : */
1142 0 : int pim_msdp_mesh_group_source_modify(struct nb_cb_modify_args *args)
1143 : {
1144 0 : const struct lyd_node *vrf_dnode;
1145 0 : struct pim_msdp_mg *mg;
1146 0 : struct vrf *vrf;
1147 0 : struct ipaddr ip;
1148 :
1149 0 : switch (args->event) {
1150 : case NB_EV_VALIDATE:
1151 : case NB_EV_PREPARE:
1152 : case NB_EV_ABORT:
1153 : break;
1154 0 : case NB_EV_APPLY:
1155 0 : mg = nb_running_get_entry(args->dnode, NULL, true);
1156 0 : vrf_dnode =
1157 0 : yang_dnode_get_parent(args->dnode, "address-family");
1158 0 : vrf = nb_running_get_entry(vrf_dnode, "../../", true);
1159 0 : yang_dnode_get_ip(&ip, args->dnode, NULL);
1160 :
1161 0 : pim_msdp_mg_src_add(vrf->info, mg, &ip.ip._v4_addr);
1162 0 : break;
1163 : }
1164 0 : return NB_OK;
1165 : }
1166 :
1167 0 : int pim_msdp_mesh_group_source_destroy(struct nb_cb_destroy_args *args)
1168 : {
1169 0 : const struct lyd_node *vrf_dnode;
1170 0 : struct pim_msdp_mg *mg;
1171 0 : struct vrf *vrf;
1172 0 : struct in_addr addr;
1173 :
1174 0 : switch (args->event) {
1175 : case NB_EV_VALIDATE:
1176 : case NB_EV_PREPARE:
1177 : case NB_EV_ABORT:
1178 : break;
1179 0 : case NB_EV_APPLY:
1180 0 : mg = nb_running_get_entry(args->dnode, NULL, true);
1181 0 : vrf_dnode =
1182 0 : yang_dnode_get_parent(args->dnode, "address-family");
1183 0 : vrf = nb_running_get_entry(vrf_dnode, "../../", true);
1184 :
1185 0 : addr.s_addr = INADDR_ANY;
1186 0 : pim_msdp_mg_src_add(vrf->info, mg, &addr);
1187 0 : break;
1188 : }
1189 0 : return NB_OK;
1190 : }
1191 :
1192 :
1193 : /*
1194 : * XPath:
1195 : * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp-mesh-groups/members
1196 : */
1197 0 : int pim_msdp_mesh_group_members_create(struct nb_cb_create_args *args)
1198 : {
1199 0 : const struct lyd_node *vrf_dnode;
1200 0 : struct pim_msdp_mg_mbr *mbr;
1201 0 : struct pim_msdp_mg *mg;
1202 0 : struct vrf *vrf;
1203 0 : struct ipaddr ip;
1204 :
1205 0 : switch (args->event) {
1206 : case NB_EV_VALIDATE:
1207 : case NB_EV_PREPARE:
1208 : case NB_EV_ABORT:
1209 : break;
1210 0 : case NB_EV_APPLY:
1211 0 : mg = nb_running_get_entry(args->dnode, NULL, true);
1212 0 : vrf_dnode =
1213 0 : yang_dnode_get_parent(args->dnode, "address-family");
1214 0 : vrf = nb_running_get_entry(vrf_dnode, "../../", true);
1215 0 : yang_dnode_get_ip(&ip, args->dnode, "address");
1216 :
1217 0 : mbr = pim_msdp_mg_mbr_add(vrf->info, mg, &ip.ip._v4_addr);
1218 0 : nb_running_set_entry(args->dnode, mbr);
1219 0 : break;
1220 : }
1221 :
1222 0 : return NB_OK;
1223 : }
1224 :
1225 0 : int pim_msdp_mesh_group_members_destroy(struct nb_cb_destroy_args *args)
1226 : {
1227 0 : struct pim_msdp_mg_mbr *mbr;
1228 0 : struct pim_msdp_mg *mg;
1229 0 : const struct lyd_node *mg_dnode;
1230 :
1231 0 : switch (args->event) {
1232 : case NB_EV_VALIDATE:
1233 : case NB_EV_PREPARE:
1234 : case NB_EV_ABORT:
1235 : break;
1236 0 : case NB_EV_APPLY:
1237 0 : mbr = nb_running_get_entry(args->dnode, NULL, true);
1238 0 : mg_dnode =
1239 0 : yang_dnode_get_parent(args->dnode, "msdp-mesh-groups");
1240 0 : mg = nb_running_get_entry(mg_dnode, NULL, true);
1241 0 : pim_msdp_mg_mbr_del(mg, mbr);
1242 0 : nb_running_unset_entry(args->dnode);
1243 0 : break;
1244 : }
1245 :
1246 0 : return NB_OK;
1247 : }
1248 :
1249 : /*
1250 : * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp-peer
1251 : */
1252 0 : int routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_peer_create(
1253 : struct nb_cb_create_args *args)
1254 : {
1255 0 : struct pim_msdp_peer *mp;
1256 0 : struct pim_instance *pim;
1257 0 : struct vrf *vrf;
1258 0 : struct ipaddr peer_ip;
1259 0 : struct ipaddr source_ip;
1260 :
1261 0 : switch (args->event) {
1262 : case NB_EV_VALIDATE:
1263 : case NB_EV_PREPARE:
1264 : case NB_EV_ABORT:
1265 : break;
1266 0 : case NB_EV_APPLY:
1267 0 : vrf = nb_running_get_entry(args->dnode, NULL, true);
1268 0 : pim = vrf->info;
1269 0 : yang_dnode_get_ip(&peer_ip, args->dnode, "./peer-ip");
1270 0 : yang_dnode_get_ip(&source_ip, args->dnode, "./source-ip");
1271 0 : mp = pim_msdp_peer_add(pim, &peer_ip.ipaddr_v4,
1272 : &source_ip.ipaddr_v4, NULL);
1273 0 : nb_running_set_entry(args->dnode, mp);
1274 0 : break;
1275 : }
1276 :
1277 0 : return NB_OK;
1278 : }
1279 :
1280 0 : int routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_peer_destroy(
1281 : struct nb_cb_destroy_args *args)
1282 : {
1283 0 : struct pim_msdp_peer *mp;
1284 :
1285 0 : switch (args->event) {
1286 : case NB_EV_VALIDATE:
1287 : case NB_EV_PREPARE:
1288 : case NB_EV_ABORT:
1289 : break;
1290 0 : case NB_EV_APPLY:
1291 0 : mp = nb_running_unset_entry(args->dnode);
1292 0 : pim_msdp_peer_del(&mp);
1293 0 : break;
1294 : }
1295 :
1296 0 : return NB_OK;
1297 : }
1298 :
1299 : /*
1300 : * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp-peer/source-ip
1301 : */
1302 0 : int routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_peer_source_ip_modify(
1303 : struct nb_cb_modify_args *args)
1304 : {
1305 0 : struct pim_msdp_peer *mp;
1306 0 : struct ipaddr source_ip;
1307 :
1308 0 : switch (args->event) {
1309 : case NB_EV_VALIDATE:
1310 : case NB_EV_PREPARE:
1311 : case NB_EV_ABORT:
1312 : break;
1313 0 : case NB_EV_APPLY:
1314 0 : mp = nb_running_get_entry(args->dnode, NULL, true);
1315 0 : yang_dnode_get_ip(&source_ip, args->dnode, NULL);
1316 0 : pim_msdp_peer_change_source(mp, &source_ip.ipaddr_v4);
1317 0 : break;
1318 : }
1319 :
1320 0 : return NB_OK;
1321 : }
1322 : #endif /* PIM_IPV != 6 */
1323 :
1324 : /*
1325 : * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/mlag
1326 : */
1327 0 : int routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_create(
1328 : struct nb_cb_create_args *args)
1329 : {
1330 0 : switch (args->event) {
1331 : case NB_EV_VALIDATE:
1332 : case NB_EV_PREPARE:
1333 : case NB_EV_ABORT:
1334 : case NB_EV_APPLY:
1335 : break;
1336 : }
1337 :
1338 0 : return NB_OK;
1339 : }
1340 :
1341 0 : int routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_destroy(
1342 : struct nb_cb_destroy_args *args)
1343 : {
1344 0 : struct in_addr addr;
1345 :
1346 0 : switch (args->event) {
1347 : case NB_EV_VALIDATE:
1348 : case NB_EV_PREPARE:
1349 : case NB_EV_ABORT:
1350 : break;
1351 0 : case NB_EV_APPLY:
1352 0 : addr.s_addr = 0;
1353 0 : pim_vxlan_mlag_update(true/*mlag_enable*/,
1354 : false/*peer_state*/, MLAG_ROLE_NONE,
1355 : NULL/*peerlink*/, &addr);
1356 : }
1357 :
1358 0 : return NB_OK;
1359 : }
1360 :
1361 : /*
1362 : * XPath:
1363 : * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/mlag
1364 : */
1365 0 : void routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_apply_finish(
1366 : struct nb_cb_apply_finish_args *args)
1367 : {
1368 0 : const char *ifname;
1369 0 : uint32_t role;
1370 0 : bool peer_state;
1371 0 : struct interface *ifp;
1372 0 : struct ipaddr reg_addr;
1373 :
1374 0 : ifname = yang_dnode_get_string(args->dnode, "./peerlink-rif");
1375 0 : ifp = if_lookup_by_name(ifname, VRF_DEFAULT);
1376 0 : if (!ifp) {
1377 0 : snprintf(args->errmsg, args->errmsg_len,
1378 : "No such interface name %s", ifname);
1379 0 : return;
1380 : }
1381 0 : role = yang_dnode_get_enum(args->dnode, "./my-role");
1382 0 : peer_state = yang_dnode_get_bool(args->dnode, "./peer-state");
1383 0 : yang_dnode_get_ip(®_addr, args->dnode, "./reg-address");
1384 :
1385 0 : pim_vxlan_mlag_update(true, peer_state, role, ifp,
1386 : ®_addr.ip._v4_addr);
1387 : }
1388 :
1389 :
1390 : /*
1391 : * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/mlag/peerlink-rif
1392 : */
1393 0 : int routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_peerlink_rif_modify(
1394 : struct nb_cb_modify_args *args)
1395 : {
1396 0 : switch (args->event) {
1397 : case NB_EV_VALIDATE:
1398 : case NB_EV_PREPARE:
1399 : case NB_EV_ABORT:
1400 : case NB_EV_APPLY:
1401 : break;
1402 : }
1403 :
1404 0 : return NB_OK;
1405 : }
1406 :
1407 0 : int routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_peerlink_rif_destroy(
1408 : struct nb_cb_destroy_args *args)
1409 : {
1410 0 : switch (args->event) {
1411 : case NB_EV_VALIDATE:
1412 : case NB_EV_PREPARE:
1413 : case NB_EV_ABORT:
1414 : case NB_EV_APPLY:
1415 : break;
1416 : }
1417 :
1418 0 : return NB_OK;
1419 : }
1420 :
1421 : /*
1422 : * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/mlag/reg-address
1423 : */
1424 0 : int routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_reg_address_modify(
1425 : struct nb_cb_modify_args *args)
1426 : {
1427 0 : switch (args->event) {
1428 : case NB_EV_VALIDATE:
1429 : case NB_EV_PREPARE:
1430 : case NB_EV_ABORT:
1431 : case NB_EV_APPLY:
1432 : break;
1433 : }
1434 :
1435 0 : return NB_OK;
1436 : }
1437 :
1438 0 : int routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_reg_address_destroy(
1439 : struct nb_cb_destroy_args *args)
1440 : {
1441 0 : switch (args->event) {
1442 : case NB_EV_VALIDATE:
1443 : case NB_EV_PREPARE:
1444 : case NB_EV_ABORT:
1445 : case NB_EV_APPLY:
1446 : break;
1447 : }
1448 :
1449 0 : return NB_OK;
1450 : }
1451 :
1452 : /*
1453 : * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/mlag/my-role
1454 : */
1455 0 : int routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_my_role_modify(
1456 : struct nb_cb_modify_args *args)
1457 : {
1458 0 : switch (args->event) {
1459 : case NB_EV_VALIDATE:
1460 : case NB_EV_PREPARE:
1461 : case NB_EV_ABORT:
1462 : case NB_EV_APPLY:
1463 : break;
1464 : }
1465 :
1466 0 : return NB_OK;
1467 : }
1468 :
1469 : /*
1470 : * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/mlag/peer-state
1471 : */
1472 0 : int routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_peer_state_modify(
1473 : struct nb_cb_modify_args *args)
1474 : {
1475 0 : switch (args->event) {
1476 : case NB_EV_VALIDATE:
1477 : case NB_EV_PREPARE:
1478 : case NB_EV_ABORT:
1479 : case NB_EV_APPLY:
1480 : break;
1481 : }
1482 :
1483 0 : return NB_OK;
1484 : }
1485 :
1486 : /*
1487 : * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/register-accept-list
1488 : */
1489 3 : int routing_control_plane_protocols_control_plane_protocol_pim_address_family_register_accept_list_modify(
1490 : struct nb_cb_modify_args *args)
1491 : {
1492 3 : struct vrf *vrf;
1493 3 : struct pim_instance *pim;
1494 3 : const char *plist;
1495 :
1496 3 : switch (args->event) {
1497 : case NB_EV_VALIDATE:
1498 : case NB_EV_PREPARE:
1499 : case NB_EV_ABORT:
1500 : break;
1501 1 : case NB_EV_APPLY:
1502 1 : vrf = nb_running_get_entry(args->dnode, NULL, true);
1503 1 : pim = vrf->info;
1504 1 : plist = yang_dnode_get_string(args->dnode, NULL);
1505 :
1506 1 : XFREE(MTYPE_PIM_PLIST_NAME, pim->register_plist);
1507 1 : pim->register_plist = XSTRDUP(MTYPE_PIM_PLIST_NAME, plist);
1508 :
1509 1 : break;
1510 : }
1511 :
1512 3 : return NB_OK;
1513 : }
1514 :
1515 0 : int routing_control_plane_protocols_control_plane_protocol_pim_address_family_register_accept_list_destroy(
1516 : struct nb_cb_destroy_args *args)
1517 : {
1518 0 : struct vrf *vrf;
1519 0 : struct pim_instance *pim;
1520 :
1521 0 : switch (args->event) {
1522 : case NB_EV_VALIDATE:
1523 : case NB_EV_PREPARE:
1524 : case NB_EV_ABORT:
1525 : break;
1526 0 : case NB_EV_APPLY:
1527 0 : vrf = nb_running_get_entry(args->dnode, NULL, true);
1528 0 : pim = vrf->info;
1529 :
1530 0 : XFREE(MTYPE_PIM_PLIST_NAME, pim->register_plist);
1531 0 : break;
1532 : }
1533 :
1534 0 : return NB_OK;
1535 : }
1536 :
1537 : /*
1538 : * XPath: /frr-interface:lib/interface/frr-pim:pim/address-family
1539 : */
1540 150 : int lib_interface_pim_address_family_create(struct nb_cb_create_args *args)
1541 : {
1542 150 : switch (args->event) {
1543 : case NB_EV_VALIDATE:
1544 : case NB_EV_PREPARE:
1545 : case NB_EV_ABORT:
1546 : case NB_EV_APPLY:
1547 : break;
1548 : }
1549 :
1550 150 : return NB_OK;
1551 : }
1552 :
1553 0 : int lib_interface_pim_address_family_destroy(struct nb_cb_destroy_args *args)
1554 : {
1555 0 : struct interface *ifp;
1556 0 : struct pim_interface *pim_ifp;
1557 :
1558 0 : switch (args->event) {
1559 : case NB_EV_VALIDATE:
1560 : case NB_EV_PREPARE:
1561 : case NB_EV_ABORT:
1562 : break;
1563 0 : case NB_EV_APPLY:
1564 0 : ifp = nb_running_get_entry(args->dnode, NULL, true);
1565 0 : pim_ifp = ifp->info;
1566 0 : if (!pim_ifp)
1567 : return NB_OK;
1568 :
1569 0 : if (!pim_cmd_interface_delete(ifp)) {
1570 0 : snprintf(args->errmsg, args->errmsg_len,
1571 : "Unable to delete interface information %s",
1572 0 : ifp->name);
1573 0 : return NB_ERR_INCONSISTENCY;
1574 : }
1575 : }
1576 :
1577 : return NB_OK;
1578 : }
1579 :
1580 : /*
1581 : * XPath: /frr-interface:lib/interface/frr-pim:pim/address-family/pim-enable
1582 : */
1583 150 : int lib_interface_pim_address_family_pim_enable_modify(struct nb_cb_modify_args *args)
1584 : {
1585 150 : struct interface *ifp;
1586 150 : struct pim_interface *pim_ifp;
1587 150 : int mcast_if_count;
1588 150 : const struct lyd_node *if_dnode;
1589 :
1590 150 : switch (args->event) {
1591 50 : case NB_EV_VALIDATE:
1592 50 : if_dnode = yang_dnode_get_parent(args->dnode, "interface");
1593 100 : mcast_if_count =
1594 50 : yang_get_list_elements_count(if_dnode);
1595 :
1596 : /* Limiting mcast interfaces to number of VIFs */
1597 50 : if (mcast_if_count == MAXVIFS) {
1598 0 : snprintf(args->errmsg, args->errmsg_len,
1599 : "Max multicast interfaces(%d) reached.",
1600 : MAXVIFS);
1601 0 : return NB_ERR_VALIDATION;
1602 : }
1603 : break;
1604 : case NB_EV_PREPARE:
1605 : case NB_EV_ABORT:
1606 : break;
1607 50 : case NB_EV_APPLY:
1608 50 : ifp = nb_running_get_entry(args->dnode, NULL, true);
1609 :
1610 50 : if (yang_dnode_get_bool(args->dnode, NULL)) {
1611 50 : if (!pim_cmd_interface_add(ifp)) {
1612 0 : snprintf(args->errmsg, args->errmsg_len,
1613 : "Could not enable PIM SM on interface %s",
1614 0 : ifp->name);
1615 0 : return NB_ERR_INCONSISTENCY;
1616 : }
1617 : } else {
1618 0 : pim_ifp = ifp->info;
1619 0 : if (!pim_ifp)
1620 : return NB_ERR_INCONSISTENCY;
1621 :
1622 0 : if (!pim_cmd_interface_delete(ifp)) {
1623 0 : snprintf(args->errmsg, args->errmsg_len,
1624 : "Unable to delete interface information");
1625 0 : return NB_ERR_INCONSISTENCY;
1626 : }
1627 : }
1628 : break;
1629 : }
1630 :
1631 : return NB_OK;
1632 : }
1633 :
1634 : /*
1635 : * XPath:
1636 : * /frr-interface:lib/interface/frr-pim:pim/address-family/pim-passive-enable
1637 : */
1638 0 : int lib_interface_pim_address_family_pim_passive_enable_modify(
1639 : struct nb_cb_modify_args *args)
1640 : {
1641 0 : struct interface *ifp;
1642 0 : struct pim_interface *pim_ifp;
1643 :
1644 0 : switch (args->event) {
1645 : case NB_EV_VALIDATE:
1646 : case NB_EV_ABORT:
1647 : case NB_EV_PREPARE:
1648 : break;
1649 0 : case NB_EV_APPLY:
1650 0 : ifp = nb_running_get_entry(args->dnode, NULL, true);
1651 0 : pim_ifp = ifp->info;
1652 0 : pim_ifp->pim_passive_enable =
1653 0 : yang_dnode_get_bool(args->dnode, NULL);
1654 0 : break;
1655 : }
1656 :
1657 0 : return NB_OK;
1658 : }
1659 :
1660 : /*
1661 : * XPath: /frr-interface:lib/interface/frr-pim:pim/address-family/hello-interval
1662 : */
1663 102 : int lib_interface_pim_address_family_hello_interval_modify(
1664 : struct nb_cb_modify_args *args)
1665 : {
1666 102 : struct interface *ifp;
1667 102 : struct pim_interface *pim_ifp;
1668 :
1669 102 : switch (args->event) {
1670 : case NB_EV_VALIDATE:
1671 : case NB_EV_ABORT:
1672 : case NB_EV_PREPARE:
1673 : break;
1674 34 : case NB_EV_APPLY:
1675 34 : ifp = nb_running_get_entry(args->dnode, NULL, true);
1676 34 : pim_ifp = ifp->info;
1677 68 : pim_ifp->pim_hello_period =
1678 34 : yang_dnode_get_uint8(args->dnode, NULL);
1679 34 : pim_ifp->pim_default_holdtime = -1;
1680 34 : break;
1681 : }
1682 :
1683 102 : return NB_OK;
1684 : }
1685 :
1686 : /*
1687 : * XPath: /frr-interface:lib/interface/frr-pim:pim/address-family/hello-holdtime
1688 : */
1689 102 : int lib_interface_pim_address_family_hello_holdtime_modify(
1690 : struct nb_cb_modify_args *args)
1691 : {
1692 102 : struct interface *ifp;
1693 102 : struct pim_interface *pim_ifp;
1694 :
1695 102 : switch (args->event) {
1696 : case NB_EV_VALIDATE:
1697 : case NB_EV_ABORT:
1698 : case NB_EV_PREPARE:
1699 : break;
1700 34 : case NB_EV_APPLY:
1701 34 : ifp = nb_running_get_entry(args->dnode, NULL, true);
1702 34 : pim_ifp = ifp->info;
1703 68 : pim_ifp->pim_default_holdtime =
1704 34 : yang_dnode_get_uint16(args->dnode, NULL);
1705 34 : break;
1706 : }
1707 :
1708 102 : return NB_OK;
1709 :
1710 : }
1711 :
1712 0 : int lib_interface_pim_address_family_hello_holdtime_destroy(
1713 : struct nb_cb_destroy_args *args)
1714 : {
1715 0 : struct interface *ifp;
1716 0 : struct pim_interface *pim_ifp;
1717 :
1718 0 : switch (args->event) {
1719 : case NB_EV_VALIDATE:
1720 : case NB_EV_ABORT:
1721 : case NB_EV_PREPARE:
1722 : break;
1723 0 : case NB_EV_APPLY:
1724 0 : ifp = nb_running_get_entry(args->dnode, NULL, true);
1725 0 : pim_ifp = ifp->info;
1726 0 : pim_ifp->pim_default_holdtime = -1;
1727 0 : break;
1728 : }
1729 :
1730 0 : return NB_OK;
1731 : }
1732 : /*
1733 : * XPath: /frr-interface:lib/interface/frr-pim:pim/address-family/bfd
1734 : */
1735 36 : int lib_interface_pim_address_family_bfd_create(struct nb_cb_create_args *args)
1736 : {
1737 36 : struct interface *ifp;
1738 36 : struct pim_interface *pim_ifp;
1739 :
1740 36 : switch (args->event) {
1741 : case NB_EV_VALIDATE:
1742 : case NB_EV_PREPARE:
1743 : case NB_EV_ABORT:
1744 : /* NOTHING */
1745 : break;
1746 12 : case NB_EV_APPLY:
1747 12 : ifp = nb_running_get_entry(args->dnode, NULL, true);
1748 12 : pim_ifp = ifp->info;
1749 12 : pim_ifp->bfd_config.enabled = true;
1750 12 : break;
1751 : }
1752 :
1753 36 : return NB_OK;
1754 : }
1755 :
1756 0 : int lib_interface_pim_address_family_bfd_destroy(
1757 : struct nb_cb_destroy_args *args)
1758 : {
1759 0 : struct interface *ifp;
1760 0 : struct pim_interface *pim_ifp;
1761 0 : const struct lyd_node *if_dnode;
1762 :
1763 0 : switch (args->event) {
1764 0 : case NB_EV_VALIDATE:
1765 0 : if_dnode = yang_dnode_get_parent(args->dnode, "interface");
1766 0 : if (!is_pim_interface(if_dnode)) {
1767 0 : snprintf(args->errmsg, args->errmsg_len,
1768 : "Pim not enabled on this interface");
1769 0 : return NB_ERR_VALIDATION;
1770 : }
1771 : break;
1772 : case NB_EV_ABORT:
1773 : case NB_EV_PREPARE:
1774 : break;
1775 0 : case NB_EV_APPLY:
1776 0 : ifp = nb_running_get_entry(args->dnode, NULL, true);
1777 0 : pim_ifp = ifp->info;
1778 0 : pim_ifp->bfd_config.enabled = false;
1779 0 : pim_bfd_reg_dereg_all_nbr(ifp);
1780 0 : break;
1781 : }
1782 :
1783 : return NB_OK;
1784 : }
1785 :
1786 : /*
1787 : * XPath: /frr-interface:lib/interface/frr-pim:pim/address-family/bfd
1788 : */
1789 12 : void lib_interface_pim_address_family_bfd_apply_finish(
1790 : struct nb_cb_apply_finish_args *args)
1791 : {
1792 12 : struct interface *ifp;
1793 12 : struct pim_interface *pim_ifp;
1794 :
1795 12 : ifp = nb_running_get_entry(args->dnode, NULL, true);
1796 12 : pim_ifp = ifp->info;
1797 :
1798 12 : if (!pim_ifp) {
1799 0 : zlog_debug("Pim not enabled on this interface");
1800 0 : return;
1801 : }
1802 :
1803 24 : pim_ifp->bfd_config.detection_multiplier =
1804 12 : yang_dnode_get_uint8(args->dnode, "./detect_mult");
1805 24 : pim_ifp->bfd_config.min_rx =
1806 12 : yang_dnode_get_uint16(args->dnode, "./min-rx-interval");
1807 24 : pim_ifp->bfd_config.min_tx =
1808 12 : yang_dnode_get_uint16(args->dnode, "./min-tx-interval");
1809 :
1810 12 : pim_bfd_reg_dereg_all_nbr(ifp);
1811 : }
1812 :
1813 : /*
1814 : * XPath: /frr-interface:lib/interface/frr-pim:pim/address-family/bfd/min-rx-interval
1815 : */
1816 0 : int lib_interface_pim_address_family_bfd_min_rx_interval_modify(
1817 : struct nb_cb_modify_args *args)
1818 : {
1819 0 : switch (args->event) {
1820 : case NB_EV_VALIDATE:
1821 : case NB_EV_PREPARE:
1822 : case NB_EV_ABORT:
1823 : case NB_EV_APPLY:
1824 : break;
1825 : }
1826 :
1827 0 : return NB_OK;
1828 : }
1829 :
1830 : /*
1831 : * XPath: /frr-interface:lib/interface/frr-pim:pim/address-family/bfd/min-tx-interval
1832 : */
1833 0 : int lib_interface_pim_address_family_bfd_min_tx_interval_modify(
1834 : struct nb_cb_modify_args *args)
1835 : {
1836 0 : switch (args->event) {
1837 : case NB_EV_VALIDATE:
1838 : case NB_EV_PREPARE:
1839 : case NB_EV_ABORT:
1840 : case NB_EV_APPLY:
1841 : break;
1842 : }
1843 :
1844 0 : return NB_OK;
1845 : }
1846 :
1847 : /*
1848 : * XPath: /frr-interface:lib/interface/frr-pim:pim/address-family/bfd/detect_mult
1849 : */
1850 0 : int lib_interface_pim_address_family_bfd_detect_mult_modify(
1851 : struct nb_cb_modify_args *args)
1852 : {
1853 0 : switch (args->event) {
1854 : case NB_EV_VALIDATE:
1855 : case NB_EV_PREPARE:
1856 : case NB_EV_ABORT:
1857 : case NB_EV_APPLY:
1858 : break;
1859 : }
1860 :
1861 0 : return NB_OK;
1862 : }
1863 :
1864 : /*
1865 : * XPath: /frr-interface:lib/interface/frr-pim:pim/address-family/bfd/profile
1866 : */
1867 6 : int lib_interface_pim_address_family_bfd_profile_modify(
1868 : struct nb_cb_modify_args *args)
1869 : {
1870 6 : struct interface *ifp;
1871 6 : struct pim_interface *pim_ifp;
1872 :
1873 6 : switch (args->event) {
1874 : case NB_EV_VALIDATE:
1875 : case NB_EV_PREPARE:
1876 : case NB_EV_ABORT:
1877 : /* NOTHING */
1878 : break;
1879 2 : case NB_EV_APPLY:
1880 2 : ifp = nb_running_get_entry(args->dnode, NULL, true);
1881 2 : pim_ifp = ifp->info;
1882 2 : XFREE(MTYPE_TMP, pim_ifp->bfd_config.profile);
1883 2 : pim_ifp->bfd_config.profile = XSTRDUP(
1884 : MTYPE_TMP, yang_dnode_get_string(args->dnode, NULL));
1885 2 : break;
1886 : }
1887 :
1888 6 : return NB_OK;
1889 : }
1890 :
1891 0 : int lib_interface_pim_address_family_bfd_profile_destroy(
1892 : struct nb_cb_destroy_args *args)
1893 : {
1894 0 : struct interface *ifp;
1895 0 : struct pim_interface *pim_ifp;
1896 :
1897 0 : switch (args->event) {
1898 : case NB_EV_VALIDATE:
1899 : case NB_EV_PREPARE:
1900 : case NB_EV_ABORT:
1901 : /* NOTHING */
1902 : break;
1903 0 : case NB_EV_APPLY:
1904 0 : ifp = nb_running_get_entry(args->dnode, NULL, true);
1905 0 : pim_ifp = ifp->info;
1906 0 : XFREE(MTYPE_TMP, pim_ifp->bfd_config.profile);
1907 0 : break;
1908 : }
1909 :
1910 0 : return NB_OK;
1911 : }
1912 :
1913 : /*
1914 : * XPath: /frr-interface:lib/interface/frr-pim:pim/address-family/bsm
1915 : */
1916 0 : int lib_interface_pim_address_family_bsm_modify(struct nb_cb_modify_args *args)
1917 : {
1918 0 : struct interface *ifp;
1919 0 : struct pim_interface *pim_ifp;
1920 :
1921 0 : switch (args->event) {
1922 : case NB_EV_VALIDATE:
1923 : case NB_EV_PREPARE:
1924 : case NB_EV_ABORT:
1925 : break;
1926 0 : case NB_EV_APPLY:
1927 0 : ifp = nb_running_get_entry(args->dnode, NULL, true);
1928 0 : pim_ifp = ifp->info;
1929 0 : pim_ifp->bsm_enable = yang_dnode_get_bool(args->dnode, NULL);
1930 :
1931 0 : break;
1932 : }
1933 :
1934 0 : return NB_OK;
1935 : }
1936 :
1937 : /*
1938 : * XPath: /frr-interface:lib/interface/frr-pim:pim/address-family/unicast-bsm
1939 : */
1940 0 : int lib_interface_pim_address_family_unicast_bsm_modify(
1941 : struct nb_cb_modify_args *args)
1942 : {
1943 0 : struct interface *ifp;
1944 0 : struct pim_interface *pim_ifp;
1945 :
1946 0 : switch (args->event) {
1947 : case NB_EV_VALIDATE:
1948 : case NB_EV_PREPARE:
1949 : case NB_EV_ABORT:
1950 : break;
1951 0 : case NB_EV_APPLY:
1952 0 : ifp = nb_running_get_entry(args->dnode, NULL, true);
1953 0 : pim_ifp = ifp->info;
1954 0 : pim_ifp->ucast_bsm_accept =
1955 0 : yang_dnode_get_bool(args->dnode, NULL);
1956 :
1957 0 : break;
1958 : }
1959 :
1960 0 : return NB_OK;
1961 : }
1962 :
1963 : /*
1964 : * XPath: /frr-interface:lib/interface/frr-pim:pim/address-family/active-active
1965 : */
1966 0 : int lib_interface_pim_address_family_active_active_modify(
1967 : struct nb_cb_modify_args *args)
1968 : {
1969 0 : struct interface *ifp;
1970 0 : struct pim_interface *pim_ifp;
1971 :
1972 0 : switch (args->event) {
1973 : case NB_EV_VALIDATE:
1974 : case NB_EV_PREPARE:
1975 : case NB_EV_ABORT:
1976 : break;
1977 0 : case NB_EV_APPLY:
1978 0 : ifp = nb_running_get_entry(args->dnode, NULL, true);
1979 0 : pim_ifp = ifp->info;
1980 0 : if (yang_dnode_get_bool(args->dnode, NULL)) {
1981 0 : if (PIM_DEBUG_MLAG)
1982 0 : zlog_debug(
1983 : "Configuring PIM active-active on Interface: %s",
1984 : ifp->name);
1985 0 : pim_if_configure_mlag_dualactive(pim_ifp);
1986 : } else {
1987 0 : if (PIM_DEBUG_MLAG)
1988 0 : zlog_debug(
1989 : "UnConfiguring PIM active-active on Interface: %s",
1990 : ifp->name);
1991 0 : pim_if_unconfigure_mlag_dualactive(pim_ifp);
1992 : }
1993 :
1994 : break;
1995 : }
1996 :
1997 0 : return NB_OK;
1998 :
1999 : }
2000 :
2001 : /*
2002 : * XPath: /frr-interface:lib/interface/frr-pim:pim/address-family/dr-priority
2003 : */
2004 0 : int lib_interface_pim_address_family_dr_priority_modify(
2005 : struct nb_cb_modify_args *args)
2006 : {
2007 0 : struct interface *ifp;
2008 0 : struct pim_interface *pim_ifp;
2009 0 : uint32_t old_dr_prio;
2010 0 : const struct lyd_node *if_dnode;
2011 :
2012 0 : switch (args->event) {
2013 0 : case NB_EV_VALIDATE:
2014 0 : if_dnode = yang_dnode_get_parent(args->dnode, "interface");
2015 0 : if (!is_pim_interface(if_dnode)) {
2016 0 : snprintf(args->errmsg, args->errmsg_len,
2017 : "Pim not enabled on this interface");
2018 0 : return NB_ERR_VALIDATION;
2019 : }
2020 : break;
2021 : case NB_EV_PREPARE:
2022 : case NB_EV_ABORT:
2023 : break;
2024 0 : case NB_EV_APPLY:
2025 0 : ifp = nb_running_get_entry(args->dnode, NULL, true);
2026 0 : pim_ifp = ifp->info;
2027 0 : old_dr_prio = pim_ifp->pim_dr_priority;
2028 0 : pim_ifp->pim_dr_priority = yang_dnode_get_uint32(args->dnode,
2029 : NULL);
2030 :
2031 0 : if (old_dr_prio != pim_ifp->pim_dr_priority) {
2032 0 : pim_if_dr_election(ifp);
2033 0 : pim_hello_restart_now(ifp);
2034 : }
2035 : break;
2036 : }
2037 :
2038 : return NB_OK;
2039 : }
2040 :
2041 : /*
2042 : * XPath: /frr-interface:lib/interface/frr-pim:pim/address-family/use-source
2043 : */
2044 0 : int lib_interface_pim_address_family_use_source_modify(
2045 : struct nb_cb_modify_args *args)
2046 : {
2047 0 : struct interface *ifp;
2048 0 : pim_addr source_addr;
2049 0 : int result;
2050 0 : const struct lyd_node *if_dnode;
2051 :
2052 0 : switch (args->event) {
2053 0 : case NB_EV_VALIDATE:
2054 0 : if_dnode = yang_dnode_get_parent(args->dnode, "interface");
2055 0 : if (!is_pim_interface(if_dnode)) {
2056 0 : snprintf(args->errmsg, args->errmsg_len,
2057 : "Pim not enabled on this interface");
2058 0 : return NB_ERR_VALIDATION;
2059 : }
2060 : break;
2061 : case NB_EV_ABORT:
2062 : case NB_EV_PREPARE:
2063 : break;
2064 0 : case NB_EV_APPLY:
2065 0 : ifp = nb_running_get_entry(args->dnode, NULL, true);
2066 : #if PIM_IPV == 4
2067 0 : yang_dnode_get_ipv4(&source_addr, args->dnode, NULL);
2068 : #else
2069 0 : yang_dnode_get_ipv6(&source_addr, args->dnode, NULL);
2070 : #endif
2071 :
2072 0 : result = interface_pim_use_src_cmd_worker(
2073 : ifp, source_addr,
2074 : args->errmsg, args->errmsg_len);
2075 :
2076 0 : if (result != PIM_SUCCESS)
2077 : return NB_ERR_INCONSISTENCY;
2078 :
2079 : break;
2080 : }
2081 :
2082 : return NB_OK;
2083 : }
2084 :
2085 0 : int lib_interface_pim_address_family_use_source_destroy(
2086 : struct nb_cb_destroy_args *args)
2087 : {
2088 0 : struct interface *ifp;
2089 0 : int result;
2090 0 : const struct lyd_node *if_dnode;
2091 :
2092 0 : switch (args->event) {
2093 0 : case NB_EV_VALIDATE:
2094 0 : if_dnode = yang_dnode_get_parent(args->dnode, "interface");
2095 0 : if (!is_pim_interface(if_dnode)) {
2096 0 : snprintf(args->errmsg, args->errmsg_len,
2097 : "Pim not enabled on this interface");
2098 0 : return NB_ERR_VALIDATION;
2099 : }
2100 0 : break;
2101 : case NB_EV_ABORT:
2102 : case NB_EV_PREPARE:
2103 : break;
2104 0 : case NB_EV_APPLY:
2105 0 : ifp = nb_running_get_entry(args->dnode, NULL, true);
2106 :
2107 0 : result = interface_pim_use_src_cmd_worker(ifp, PIMADDR_ANY,
2108 : args->errmsg,
2109 : args->errmsg_len);
2110 :
2111 0 : if (result != PIM_SUCCESS)
2112 : return NB_ERR_INCONSISTENCY;
2113 :
2114 : break;
2115 : }
2116 :
2117 : return NB_OK;
2118 : }
2119 :
2120 : /*
2121 : * XPath: /frr-interface:lib/interface/frr-pim:pim/address-family/multicast-boundary-oil
2122 : */
2123 0 : int lib_interface_pim_address_family_multicast_boundary_oil_modify(
2124 : struct nb_cb_modify_args *args)
2125 : {
2126 0 : struct interface *ifp;
2127 0 : struct pim_interface *pim_ifp;
2128 0 : const char *plist;
2129 0 : const struct lyd_node *if_dnode;
2130 :
2131 0 : switch (args->event) {
2132 0 : case NB_EV_VALIDATE:
2133 0 : if_dnode = yang_dnode_get_parent(args->dnode, "interface");
2134 0 : if (!is_pim_interface(if_dnode)) {
2135 0 : snprintf(args->errmsg, args->errmsg_len,
2136 : "Pim not enabled on this interface");
2137 0 : return NB_ERR_VALIDATION;
2138 : }
2139 : break;
2140 : case NB_EV_ABORT:
2141 : case NB_EV_PREPARE:
2142 : break;
2143 0 : case NB_EV_APPLY:
2144 0 : ifp = nb_running_get_entry(args->dnode, NULL, true);
2145 0 : pim_ifp = ifp->info;
2146 0 : plist = yang_dnode_get_string(args->dnode, NULL);
2147 :
2148 0 : if (pim_ifp->boundary_oil_plist)
2149 0 : XFREE(MTYPE_PIM_INTERFACE, pim_ifp->boundary_oil_plist);
2150 :
2151 0 : pim_ifp->boundary_oil_plist =
2152 0 : XSTRDUP(MTYPE_PIM_INTERFACE, plist);
2153 :
2154 0 : break;
2155 : }
2156 :
2157 : return NB_OK;
2158 : }
2159 :
2160 0 : int lib_interface_pim_address_family_multicast_boundary_oil_destroy(
2161 : struct nb_cb_destroy_args *args)
2162 : {
2163 0 : struct interface *ifp;
2164 0 : struct pim_interface *pim_ifp;
2165 0 : const struct lyd_node *if_dnode;
2166 :
2167 0 : switch (args->event) {
2168 0 : case NB_EV_VALIDATE:
2169 0 : if_dnode = yang_dnode_get_parent(args->dnode, "interface");
2170 0 : if (!is_pim_interface(if_dnode)) {
2171 0 : snprintf(args->errmsg, args->errmsg_len,
2172 : "%% Enable PIM and/or IGMP on this interface first");
2173 0 : return NB_ERR_VALIDATION;
2174 : }
2175 : break;
2176 : case NB_EV_ABORT:
2177 : case NB_EV_PREPARE:
2178 : break;
2179 0 : case NB_EV_APPLY:
2180 0 : ifp = nb_running_get_entry(args->dnode, NULL, true);
2181 0 : pim_ifp = ifp->info;
2182 0 : if (pim_ifp->boundary_oil_plist)
2183 0 : XFREE(MTYPE_PIM_INTERFACE, pim_ifp->boundary_oil_plist);
2184 : break;
2185 : }
2186 :
2187 : return NB_OK;
2188 : }
2189 :
2190 : /*
2191 : * XPath: /frr-interface:lib/interface/frr-pim:pim/address-family/mroute
2192 : */
2193 0 : int lib_interface_pim_address_family_mroute_create(
2194 : struct nb_cb_create_args *args)
2195 : {
2196 0 : switch (args->event) {
2197 : case NB_EV_VALIDATE:
2198 : case NB_EV_PREPARE:
2199 : case NB_EV_ABORT:
2200 : case NB_EV_APPLY:
2201 : break;
2202 : }
2203 :
2204 0 : return NB_OK;
2205 : }
2206 :
2207 0 : int lib_interface_pim_address_family_mroute_destroy(
2208 : struct nb_cb_destroy_args *args)
2209 : {
2210 0 : struct pim_instance *pim;
2211 0 : struct pim_interface *pim_iifp;
2212 0 : struct interface *iif;
2213 0 : struct interface *oif;
2214 0 : const char *oifname;
2215 0 : pim_addr source_addr;
2216 0 : pim_addr group_addr;
2217 0 : const struct lyd_node *if_dnode;
2218 :
2219 0 : switch (args->event) {
2220 0 : case NB_EV_VALIDATE:
2221 0 : if_dnode = yang_dnode_get_parent(args->dnode, "interface");
2222 0 : if (!is_pim_interface(if_dnode)) {
2223 0 : snprintf(args->errmsg, args->errmsg_len,
2224 : "%% Enable PIM and/or IGMP on this interface first");
2225 0 : return NB_ERR_VALIDATION;
2226 : }
2227 : break;
2228 : case NB_EV_PREPARE:
2229 : case NB_EV_ABORT:
2230 : break;
2231 0 : case NB_EV_APPLY:
2232 0 : iif = nb_running_get_entry(args->dnode, NULL, true);
2233 0 : pim_iifp = iif->info;
2234 0 : pim = pim_iifp->pim;
2235 :
2236 0 : oifname = yang_dnode_get_string(args->dnode, "./oif");
2237 0 : oif = if_lookup_by_name(oifname, pim->vrf->vrf_id);
2238 :
2239 0 : if (!oif) {
2240 0 : snprintf(args->errmsg, args->errmsg_len,
2241 : "No such interface name %s",
2242 : oifname);
2243 0 : return NB_ERR_INCONSISTENCY;
2244 : }
2245 :
2246 0 : yang_dnode_get_pimaddr(&source_addr, args->dnode, "./source-addr");
2247 0 : yang_dnode_get_pimaddr(&group_addr, args->dnode, "./group-addr");
2248 :
2249 0 : if (pim_static_del(pim, iif, oif, group_addr, source_addr)) {
2250 0 : snprintf(args->errmsg, args->errmsg_len,
2251 : "Failed to remove static mroute");
2252 0 : return NB_ERR_INCONSISTENCY;
2253 : }
2254 :
2255 : break;
2256 : }
2257 :
2258 : return NB_OK;
2259 : }
2260 :
2261 : /*
2262 : * XPath: /frr-interface:lib/interface/frr-pim:pim/address-family/mroute/oif
2263 : */
2264 0 : int lib_interface_pim_address_family_mroute_oif_modify(
2265 : struct nb_cb_modify_args *args)
2266 : {
2267 0 : struct pim_instance *pim;
2268 0 : struct pim_interface *pim_iifp;
2269 0 : struct interface *iif;
2270 0 : struct interface *oif;
2271 0 : const char *oifname;
2272 0 : pim_addr source_addr;
2273 0 : pim_addr group_addr;
2274 0 : const struct lyd_node *if_dnode;
2275 :
2276 0 : switch (args->event) {
2277 0 : case NB_EV_VALIDATE:
2278 0 : if_dnode = yang_dnode_get_parent(args->dnode, "interface");
2279 0 : if (!is_pim_interface(if_dnode)) {
2280 0 : snprintf(args->errmsg, args->errmsg_len,
2281 : "%% Enable PIM and/or IGMP on this interface first");
2282 0 : return NB_ERR_VALIDATION;
2283 : }
2284 :
2285 : #ifdef PIM_ENFORCE_LOOPFREE_MFC
2286 0 : iif = nb_running_get_entry(args->dnode, NULL, false);
2287 0 : if (!iif) {
2288 : return NB_OK;
2289 : }
2290 :
2291 0 : pim_iifp = iif->info;
2292 0 : pim = pim_iifp->pim;
2293 :
2294 0 : oifname = yang_dnode_get_string(args->dnode, NULL);
2295 0 : oif = if_lookup_by_name(oifname, pim->vrf->vrf_id);
2296 :
2297 0 : if (oif && (iif->ifindex == oif->ifindex)) {
2298 0 : strlcpy(args->errmsg,
2299 : "% IIF same as OIF and loopfree enforcement is enabled; rejecting",
2300 : args->errmsg_len);
2301 0 : return NB_ERR_VALIDATION;
2302 : }
2303 : #endif
2304 : break;
2305 : case NB_EV_PREPARE:
2306 : case NB_EV_ABORT:
2307 : break;
2308 0 : case NB_EV_APPLY:
2309 0 : iif = nb_running_get_entry(args->dnode, NULL, true);
2310 0 : pim_iifp = iif->info;
2311 0 : pim = pim_iifp->pim;
2312 :
2313 0 : oifname = yang_dnode_get_string(args->dnode, NULL);
2314 0 : oif = if_lookup_by_name(oifname, pim->vrf->vrf_id);
2315 0 : if (!oif) {
2316 0 : snprintf(args->errmsg, args->errmsg_len,
2317 : "No such interface name %s",
2318 : oifname);
2319 0 : return NB_ERR_INCONSISTENCY;
2320 : }
2321 :
2322 0 : yang_dnode_get_pimaddr(&source_addr, args->dnode, "../source-addr");
2323 0 : yang_dnode_get_pimaddr(&group_addr, args->dnode, "../group-addr");
2324 :
2325 0 : if (pim_static_add(pim, iif, oif, group_addr, source_addr)) {
2326 0 : snprintf(args->errmsg, args->errmsg_len,
2327 : "Failed to add static mroute");
2328 0 : return NB_ERR_INCONSISTENCY;
2329 : }
2330 :
2331 : break;
2332 : }
2333 :
2334 : return NB_OK;
2335 : }
2336 :
2337 0 : int lib_interface_pim_address_family_mroute_oif_destroy(
2338 : struct nb_cb_destroy_args *args)
2339 : {
2340 0 : switch (args->event) {
2341 : case NB_EV_VALIDATE:
2342 : case NB_EV_PREPARE:
2343 : case NB_EV_ABORT:
2344 : case NB_EV_APPLY:
2345 : break;
2346 : }
2347 :
2348 0 : return NB_OK;
2349 : }
2350 :
2351 : /*
2352 : * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/frr-pim-rp:rp/static-rp/rp-list
2353 : */
2354 12 : int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_static_rp_rp_list_create(
2355 : struct nb_cb_create_args *args)
2356 : {
2357 12 : switch (args->event) {
2358 : case NB_EV_VALIDATE:
2359 : case NB_EV_PREPARE:
2360 : case NB_EV_ABORT:
2361 : case NB_EV_APPLY:
2362 : break;
2363 : }
2364 :
2365 12 : return NB_OK;
2366 : }
2367 :
2368 0 : int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_static_rp_rp_list_destroy(
2369 : struct nb_cb_destroy_args *args)
2370 : {
2371 0 : struct vrf *vrf;
2372 0 : struct pim_instance *pim;
2373 0 : struct prefix group;
2374 0 : pim_addr rp_addr;
2375 0 : const char *plist;
2376 0 : int result = 0;
2377 :
2378 0 : switch (args->event) {
2379 : case NB_EV_VALIDATE:
2380 : case NB_EV_PREPARE:
2381 : case NB_EV_ABORT:
2382 : break;
2383 0 : case NB_EV_APPLY:
2384 0 : vrf = nb_running_get_entry(args->dnode, NULL, true);
2385 0 : pim = vrf->info;
2386 0 : yang_dnode_get_pimaddr(&rp_addr, args->dnode, "./rp-address");
2387 :
2388 0 : if (yang_dnode_get(args->dnode, "./group-list")) {
2389 0 : yang_dnode_get_prefix(&group, args->dnode,
2390 : "./group-list");
2391 0 : apply_mask(&group);
2392 0 : result = pim_no_rp_cmd_worker(pim, rp_addr, group, NULL,
2393 : args->errmsg,
2394 : args->errmsg_len);
2395 : }
2396 :
2397 0 : else if (yang_dnode_get(args->dnode, "./prefix-list")) {
2398 0 : plist = yang_dnode_get_string(args->dnode,
2399 : "./prefix-list");
2400 0 : if (!pim_get_all_mcast_group(&group)) {
2401 0 : flog_err(
2402 : EC_LIB_DEVELOPMENT,
2403 : "Unable to convert 224.0.0.0/4 to prefix");
2404 0 : return NB_ERR_INCONSISTENCY;
2405 : }
2406 :
2407 0 : result = pim_no_rp_cmd_worker(pim, rp_addr, group,
2408 : plist, args->errmsg,
2409 : args->errmsg_len);
2410 : }
2411 :
2412 0 : if (result)
2413 : return NB_ERR_INCONSISTENCY;
2414 : break;
2415 : }
2416 :
2417 : return NB_OK;
2418 : }
2419 :
2420 : /*
2421 : * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/frr-pim-rp:rp/static-rp/rp-list/group-list
2422 : */
2423 12 : int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_static_rp_rp_list_group_list_create(
2424 : struct nb_cb_create_args *args)
2425 : {
2426 12 : struct vrf *vrf;
2427 12 : struct pim_instance *pim;
2428 12 : struct prefix group;
2429 12 : pim_addr rp_addr;
2430 :
2431 12 : switch (args->event) {
2432 : case NB_EV_VALIDATE:
2433 : case NB_EV_PREPARE:
2434 : case NB_EV_ABORT:
2435 : break;
2436 4 : case NB_EV_APPLY:
2437 4 : vrf = nb_running_get_entry(args->dnode, NULL, true);
2438 4 : pim = vrf->info;
2439 4 : yang_dnode_get_pimaddr(&rp_addr, args->dnode, "../rp-address");
2440 4 : yang_dnode_get_prefix(&group, args->dnode, NULL);
2441 4 : apply_mask(&group);
2442 4 : return pim_rp_cmd_worker(pim, rp_addr, group, NULL,
2443 : args->errmsg, args->errmsg_len);
2444 : }
2445 :
2446 : return NB_OK;
2447 : }
2448 :
2449 0 : int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_static_rp_rp_list_group_list_destroy(
2450 : struct nb_cb_destroy_args *args)
2451 : {
2452 0 : struct vrf *vrf;
2453 0 : struct pim_instance *pim;
2454 0 : struct prefix group;
2455 0 : pim_addr rp_addr;
2456 :
2457 0 : switch (args->event) {
2458 : case NB_EV_VALIDATE:
2459 : case NB_EV_PREPARE:
2460 : case NB_EV_ABORT:
2461 : break;
2462 0 : case NB_EV_APPLY:
2463 0 : vrf = nb_running_get_entry(args->dnode, NULL, true);
2464 0 : pim = vrf->info;
2465 0 : yang_dnode_get_pimaddr(&rp_addr, args->dnode, "../rp-address");
2466 0 : yang_dnode_get_prefix(&group, args->dnode, NULL);
2467 0 : apply_mask(&group);
2468 :
2469 0 : return pim_no_rp_cmd_worker(pim, rp_addr, group, NULL,
2470 : args->errmsg, args->errmsg_len);
2471 : }
2472 :
2473 : return NB_OK;
2474 : }
2475 :
2476 : /*
2477 : * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/frr-pim-rp:rp/static-rp/rp-list/prefix-list
2478 : */
2479 0 : int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_static_rp_rp_list_prefix_list_modify(
2480 : struct nb_cb_modify_args *args)
2481 : {
2482 0 : struct vrf *vrf;
2483 0 : struct pim_instance *pim;
2484 0 : struct prefix group;
2485 0 : pim_addr rp_addr;
2486 0 : const char *plist;
2487 :
2488 0 : switch (args->event) {
2489 : case NB_EV_VALIDATE:
2490 : case NB_EV_PREPARE:
2491 : case NB_EV_ABORT:
2492 : break;
2493 0 : case NB_EV_APPLY:
2494 0 : vrf = nb_running_get_entry(args->dnode, NULL, true);
2495 0 : pim = vrf->info;
2496 0 : plist = yang_dnode_get_string(args->dnode, NULL);
2497 0 : yang_dnode_get_pimaddr(&rp_addr, args->dnode, "../rp-address");
2498 0 : if (!pim_get_all_mcast_group(&group)) {
2499 0 : flog_err(EC_LIB_DEVELOPMENT,
2500 : "Unable to convert 224.0.0.0/4 to prefix");
2501 0 : return NB_ERR_INCONSISTENCY;
2502 : }
2503 0 : return pim_rp_cmd_worker(pim, rp_addr, group, plist,
2504 : args->errmsg, args->errmsg_len);
2505 : }
2506 :
2507 : return NB_OK;
2508 : }
2509 :
2510 0 : int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_static_rp_rp_list_prefix_list_destroy(
2511 : struct nb_cb_destroy_args *args)
2512 : {
2513 0 : struct vrf *vrf;
2514 0 : struct pim_instance *pim;
2515 0 : struct prefix group;
2516 0 : pim_addr rp_addr;
2517 0 : const char *plist;
2518 :
2519 0 : switch (args->event) {
2520 : case NB_EV_VALIDATE:
2521 : case NB_EV_PREPARE:
2522 : case NB_EV_ABORT:
2523 : break;
2524 0 : case NB_EV_APPLY:
2525 0 : vrf = nb_running_get_entry(args->dnode, NULL, true);
2526 0 : pim = vrf->info;
2527 0 : yang_dnode_get_pimaddr(&rp_addr, args->dnode, "../rp-address");
2528 0 : plist = yang_dnode_get_string(args->dnode, NULL);
2529 0 : if (!pim_get_all_mcast_group(&group)) {
2530 0 : flog_err(EC_LIB_DEVELOPMENT,
2531 : "Unable to convert 224.0.0.0/4 to prefix");
2532 0 : return NB_ERR_INCONSISTENCY;
2533 : }
2534 0 : return pim_no_rp_cmd_worker(pim, rp_addr, group, plist,
2535 : args->errmsg, args->errmsg_len);
2536 : break;
2537 : }
2538 :
2539 : return NB_OK;
2540 : }
2541 :
2542 : /*
2543 : * XPath: /frr-interface:lib/interface/frr-gmp:gmp/address-family
2544 : */
2545 72 : int lib_interface_gmp_address_family_create(struct nb_cb_create_args *args)
2546 : {
2547 72 : switch (args->event) {
2548 : case NB_EV_VALIDATE:
2549 : case NB_EV_PREPARE:
2550 : case NB_EV_ABORT:
2551 : case NB_EV_APPLY:
2552 : break;
2553 : }
2554 :
2555 72 : return NB_OK;
2556 : }
2557 :
2558 0 : int lib_interface_gmp_address_family_destroy(struct nb_cb_destroy_args *args)
2559 : {
2560 0 : struct interface *ifp;
2561 0 : struct pim_interface *pim_ifp;
2562 :
2563 0 : switch (args->event) {
2564 : case NB_EV_VALIDATE:
2565 : case NB_EV_PREPARE:
2566 : case NB_EV_ABORT:
2567 : break;
2568 0 : case NB_EV_APPLY:
2569 0 : ifp = nb_running_get_entry(args->dnode, NULL, true);
2570 0 : pim_ifp = ifp->info;
2571 :
2572 0 : if (!pim_ifp)
2573 : return NB_OK;
2574 :
2575 0 : pim_ifp->gm_enable = false;
2576 :
2577 0 : pim_if_membership_clear(ifp);
2578 :
2579 0 : pim_if_addr_del_all_igmp(ifp);
2580 :
2581 0 : if (!pim_ifp->pim_enable)
2582 0 : pim_if_delete(ifp);
2583 : }
2584 :
2585 : return NB_OK;
2586 : }
2587 :
2588 : /*
2589 : * XPath: /frr-interface:lib/interface/frr-gmp:gmp/address-family/enable
2590 : */
2591 72 : int lib_interface_gmp_address_family_enable_modify(
2592 : struct nb_cb_modify_args *args)
2593 : {
2594 72 : struct interface *ifp;
2595 72 : bool gm_enable;
2596 72 : struct pim_interface *pim_ifp;
2597 72 : int mcast_if_count;
2598 72 : const char *ifp_name;
2599 72 : const struct lyd_node *if_dnode;
2600 :
2601 72 : switch (args->event) {
2602 24 : case NB_EV_VALIDATE:
2603 24 : if_dnode = yang_dnode_get_parent(args->dnode, "interface");
2604 48 : mcast_if_count =
2605 24 : yang_get_list_elements_count(if_dnode);
2606 : /* Limiting mcast interfaces to number of VIFs */
2607 24 : if (mcast_if_count == MAXVIFS) {
2608 0 : ifp_name = yang_dnode_get_string(if_dnode, "name");
2609 0 : snprintf(
2610 : args->errmsg, args->errmsg_len,
2611 : "Max multicast interfaces(%d) Reached. Could not enable %s on interface %s",
2612 : MAXVIFS, GM, ifp_name);
2613 0 : return NB_ERR_VALIDATION;
2614 : }
2615 : break;
2616 : case NB_EV_PREPARE:
2617 : case NB_EV_ABORT:
2618 : break;
2619 24 : case NB_EV_APPLY:
2620 24 : ifp = nb_running_get_entry(args->dnode, NULL, true);
2621 24 : gm_enable = yang_dnode_get_bool(args->dnode, NULL);
2622 :
2623 24 : if (gm_enable)
2624 24 : return pim_cmd_gm_start(ifp);
2625 :
2626 : else {
2627 0 : pim_ifp = ifp->info;
2628 :
2629 0 : if (!pim_ifp)
2630 : return NB_ERR_INCONSISTENCY;
2631 :
2632 0 : pim_ifp->gm_enable = false;
2633 :
2634 0 : pim_if_membership_clear(ifp);
2635 :
2636 : #if PIM_IPV == 4
2637 0 : pim_if_addr_del_all_igmp(ifp);
2638 : #else
2639 0 : gm_ifp_teardown(ifp);
2640 : #endif
2641 :
2642 0 : if (!pim_ifp->pim_enable)
2643 0 : pim_if_delete(ifp);
2644 : }
2645 : }
2646 : return NB_OK;
2647 : }
2648 :
2649 : /*
2650 : * XPath: /frr-interface:lib/interface/frr-gmp:gmp/address-family/igmp-version
2651 : */
2652 0 : int lib_interface_gmp_address_family_igmp_version_modify(
2653 : struct nb_cb_modify_args *args)
2654 : {
2655 0 : struct interface *ifp;
2656 0 : struct pim_interface *pim_ifp;
2657 0 : int igmp_version, old_version = 0;
2658 :
2659 0 : switch (args->event) {
2660 : case NB_EV_VALIDATE:
2661 : case NB_EV_PREPARE:
2662 : case NB_EV_ABORT:
2663 : break;
2664 0 : case NB_EV_APPLY:
2665 0 : ifp = nb_running_get_entry(args->dnode, NULL, true);
2666 0 : pim_ifp = ifp->info;
2667 :
2668 0 : if (!pim_ifp)
2669 : return NB_ERR_INCONSISTENCY;
2670 :
2671 0 : igmp_version = yang_dnode_get_uint8(args->dnode, NULL);
2672 0 : old_version = pim_ifp->igmp_version;
2673 0 : pim_ifp->igmp_version = igmp_version;
2674 :
2675 : /* Current and new version is different refresh existing
2676 : * membership. Going from 3 -> 2 or 2 -> 3.
2677 : */
2678 0 : if (old_version != igmp_version)
2679 0 : pim_if_membership_refresh(ifp);
2680 :
2681 : break;
2682 : }
2683 :
2684 : return NB_OK;
2685 : }
2686 :
2687 0 : int lib_interface_gmp_address_family_igmp_version_destroy(
2688 : struct nb_cb_destroy_args *args)
2689 : {
2690 0 : struct interface *ifp;
2691 0 : struct pim_interface *pim_ifp;
2692 :
2693 0 : switch (args->event) {
2694 : case NB_EV_VALIDATE:
2695 : case NB_EV_PREPARE:
2696 : case NB_EV_ABORT:
2697 : break;
2698 0 : case NB_EV_APPLY:
2699 0 : ifp = nb_running_get_entry(args->dnode, NULL, true);
2700 0 : pim_ifp = ifp->info;
2701 0 : pim_ifp->igmp_version = IGMP_DEFAULT_VERSION;
2702 0 : break;
2703 : }
2704 :
2705 0 : return NB_OK;
2706 : }
2707 :
2708 : /*
2709 : * XPath: /frr-interface:lib/interface/frr-gmp:gmp/address-family/mld-version
2710 : */
2711 0 : int lib_interface_gmp_address_family_mld_version_modify(
2712 : struct nb_cb_modify_args *args)
2713 : {
2714 0 : struct interface *ifp;
2715 0 : struct pim_interface *pim_ifp;
2716 :
2717 0 : switch (args->event) {
2718 : case NB_EV_VALIDATE:
2719 : case NB_EV_PREPARE:
2720 : case NB_EV_ABORT:
2721 : break;
2722 0 : case NB_EV_APPLY:
2723 0 : ifp = nb_running_get_entry(args->dnode, NULL, true);
2724 0 : pim_ifp = ifp->info;
2725 0 : if (!pim_ifp)
2726 : return NB_ERR_INCONSISTENCY;
2727 :
2728 0 : pim_ifp->mld_version = yang_dnode_get_uint8(args->dnode, NULL);
2729 0 : gm_ifp_update(ifp);
2730 0 : break;
2731 : }
2732 :
2733 : return NB_OK;
2734 : }
2735 :
2736 0 : int lib_interface_gmp_address_family_mld_version_destroy(
2737 : struct nb_cb_destroy_args *args)
2738 : {
2739 0 : struct interface *ifp;
2740 0 : struct pim_interface *pim_ifp;
2741 :
2742 0 : switch (args->event) {
2743 : case NB_EV_VALIDATE:
2744 : case NB_EV_PREPARE:
2745 : case NB_EV_ABORT:
2746 : break;
2747 0 : case NB_EV_APPLY:
2748 0 : ifp = nb_running_get_entry(args->dnode, NULL, true);
2749 0 : pim_ifp = ifp->info;
2750 0 : if (!pim_ifp)
2751 : return NB_ERR_INCONSISTENCY;
2752 :
2753 0 : pim_ifp->mld_version = 2;
2754 0 : gm_ifp_update(ifp);
2755 0 : break;
2756 : }
2757 :
2758 : return NB_OK;
2759 : }
2760 :
2761 : /*
2762 : * XPath: /frr-interface:lib/interface/frr-gmp:gmp/address-family/query-interval
2763 : */
2764 24 : int lib_interface_gmp_address_family_query_interval_modify(
2765 : struct nb_cb_modify_args *args)
2766 : {
2767 24 : struct interface *ifp;
2768 24 : int query_interval;
2769 :
2770 : #if PIM_IPV == 4
2771 0 : switch (args->event) {
2772 : case NB_EV_VALIDATE:
2773 : case NB_EV_PREPARE:
2774 : case NB_EV_ABORT:
2775 : break;
2776 0 : case NB_EV_APPLY:
2777 0 : ifp = nb_running_get_entry(args->dnode, NULL, true);
2778 0 : query_interval = yang_dnode_get_uint16(args->dnode, NULL);
2779 0 : change_query_interval(ifp->info, query_interval);
2780 : }
2781 : #else
2782 24 : struct pim_interface *pim_ifp;
2783 :
2784 24 : switch (args->event) {
2785 : case NB_EV_VALIDATE:
2786 : case NB_EV_PREPARE:
2787 : case NB_EV_ABORT:
2788 : break;
2789 8 : case NB_EV_APPLY:
2790 8 : ifp = nb_running_get_entry(args->dnode, NULL, true);
2791 8 : pim_ifp = ifp->info;
2792 8 : if (!pim_ifp)
2793 : return NB_ERR_INCONSISTENCY;
2794 :
2795 8 : query_interval = yang_dnode_get_uint16(args->dnode, NULL);
2796 8 : pim_ifp->gm_default_query_interval = query_interval;
2797 8 : gm_ifp_update(ifp);
2798 : }
2799 : #endif
2800 0 : return NB_OK;
2801 : }
2802 :
2803 : /*
2804 : * XPath: /frr-interface:lib/interface/frr-gmp:gmp/address-family/query-max-response-time
2805 : */
2806 24 : int lib_interface_gmp_address_family_query_max_response_time_modify(
2807 : struct nb_cb_modify_args *args)
2808 : {
2809 24 : struct interface *ifp;
2810 24 : int query_max_response_time_dsec;
2811 :
2812 24 : switch (args->event) {
2813 : case NB_EV_VALIDATE:
2814 : case NB_EV_PREPARE:
2815 : case NB_EV_ABORT:
2816 : break;
2817 8 : case NB_EV_APPLY:
2818 8 : ifp = nb_running_get_entry(args->dnode, NULL, true);
2819 16 : query_max_response_time_dsec =
2820 8 : yang_dnode_get_uint16(args->dnode, NULL);
2821 8 : change_query_max_response_time(ifp,
2822 : query_max_response_time_dsec);
2823 : }
2824 :
2825 24 : return NB_OK;
2826 : }
2827 :
2828 : /*
2829 : * XPath: /frr-interface:lib/interface/frr-gmp:gmp/address-family/last-member-query-interval
2830 : */
2831 0 : int lib_interface_gmp_address_family_last_member_query_interval_modify(
2832 : struct nb_cb_modify_args *args)
2833 : {
2834 0 : struct interface *ifp;
2835 0 : struct pim_interface *pim_ifp;
2836 0 : int last_member_query_interval;
2837 :
2838 0 : switch (args->event) {
2839 : case NB_EV_VALIDATE:
2840 : case NB_EV_PREPARE:
2841 : case NB_EV_ABORT:
2842 : break;
2843 0 : case NB_EV_APPLY:
2844 0 : ifp = nb_running_get_entry(args->dnode, NULL, true);
2845 0 : pim_ifp = ifp->info;
2846 0 : last_member_query_interval =
2847 0 : yang_dnode_get_uint16(args->dnode, NULL);
2848 0 : pim_ifp->gm_specific_query_max_response_time_dsec =
2849 : last_member_query_interval;
2850 : #if PIM_IPV == 6
2851 0 : gm_ifp_update(ifp);
2852 : #endif
2853 :
2854 0 : break;
2855 : }
2856 :
2857 0 : return NB_OK;
2858 : }
2859 :
2860 : /*
2861 : * XPath: /frr-interface:lib/interface/frr-gmp:gmp/address-family/robustness-variable
2862 : */
2863 0 : int lib_interface_gmp_address_family_robustness_variable_modify(
2864 : struct nb_cb_modify_args *args)
2865 : {
2866 0 : struct interface *ifp;
2867 0 : struct pim_interface *pim_ifp;
2868 0 : int last_member_query_count;
2869 :
2870 0 : switch (args->event) {
2871 : case NB_EV_VALIDATE:
2872 : case NB_EV_PREPARE:
2873 : case NB_EV_ABORT:
2874 : break;
2875 0 : case NB_EV_APPLY:
2876 0 : ifp = nb_running_get_entry(args->dnode, NULL, true);
2877 0 : pim_ifp = ifp->info;
2878 0 : last_member_query_count =
2879 0 : yang_dnode_get_uint8(args->dnode, NULL);
2880 0 : pim_ifp->gm_last_member_query_count = last_member_query_count;
2881 : #if PIM_IPV == 6
2882 0 : gm_ifp_update(ifp);
2883 : #endif
2884 0 : break;
2885 : }
2886 :
2887 0 : return NB_OK;
2888 : }
2889 :
2890 : /*
2891 : * XPath: /frr-interface:lib/interface/frr-gmp:gmp/address-family/static-group
2892 : */
2893 0 : int lib_interface_gmp_address_family_static_group_create(
2894 : struct nb_cb_create_args *args)
2895 : {
2896 : #if PIM_IPV == 4
2897 0 : struct interface *ifp;
2898 0 : struct ipaddr source_addr;
2899 0 : struct ipaddr group_addr;
2900 0 : int result;
2901 0 : const char *ifp_name;
2902 0 : const struct lyd_node *if_dnode;
2903 :
2904 0 : switch (args->event) {
2905 0 : case NB_EV_VALIDATE:
2906 0 : if_dnode = yang_dnode_get_parent(args->dnode, "interface");
2907 0 : if (!is_pim_interface(if_dnode)) {
2908 0 : ifp_name = yang_dnode_get_string(if_dnode, "name");
2909 0 : snprintf(args->errmsg, args->errmsg_len,
2910 : "multicast not enabled on interface %s",
2911 : ifp_name);
2912 0 : return NB_ERR_VALIDATION;
2913 : }
2914 :
2915 0 : yang_dnode_get_ip(&group_addr, args->dnode, "./group-addr");
2916 0 : if (pim_is_group_224_0_0_0_24(group_addr.ip._v4_addr)) {
2917 0 : snprintf(
2918 : args->errmsg, args->errmsg_len,
2919 : "Groups within 224.0.0.0/24 are reserved and cannot be joined");
2920 0 : return NB_ERR_VALIDATION;
2921 : }
2922 : break;
2923 : case NB_EV_PREPARE:
2924 : case NB_EV_ABORT:
2925 : break;
2926 0 : case NB_EV_APPLY:
2927 0 : ifp = nb_running_get_entry(args->dnode, NULL, true);
2928 0 : yang_dnode_get_ip(&source_addr, args->dnode, "./source-addr");
2929 0 : yang_dnode_get_ip(&group_addr, args->dnode, "./group-addr");
2930 :
2931 0 : result = pim_if_igmp_join_add(ifp, group_addr.ip._v4_addr,
2932 : source_addr.ip._v4_addr);
2933 0 : if (result) {
2934 0 : snprintf(args->errmsg, args->errmsg_len,
2935 : "Failure joining IGMP group");
2936 0 : return NB_ERR_INCONSISTENCY;
2937 : }
2938 : }
2939 : #else
2940 : /* TBD Depends on MLD data structure changes */
2941 : #endif /* PIM_IPV == 4 */
2942 0 : return NB_OK;
2943 : }
2944 :
2945 0 : int lib_interface_gmp_address_family_static_group_destroy(
2946 : struct nb_cb_destroy_args *args)
2947 : {
2948 0 : struct interface *ifp;
2949 0 : struct ipaddr source_addr;
2950 0 : struct ipaddr group_addr;
2951 0 : int result;
2952 :
2953 0 : switch (args->event) {
2954 : case NB_EV_VALIDATE:
2955 : case NB_EV_PREPARE:
2956 : case NB_EV_ABORT:
2957 : break;
2958 0 : case NB_EV_APPLY:
2959 0 : ifp = nb_running_get_entry(args->dnode, NULL, true);
2960 0 : yang_dnode_get_ip(&source_addr, args->dnode, "./source-addr");
2961 0 : yang_dnode_get_ip(&group_addr, args->dnode, "./group-addr");
2962 :
2963 0 : result = pim_if_igmp_join_del(ifp, group_addr.ip._v4_addr,
2964 : source_addr.ip._v4_addr);
2965 :
2966 0 : if (result) {
2967 0 : char src_str[INET_ADDRSTRLEN];
2968 0 : char grp_str[INET_ADDRSTRLEN];
2969 :
2970 0 : ipaddr2str(&source_addr, src_str, sizeof(src_str));
2971 0 : ipaddr2str(&group_addr, grp_str, sizeof(grp_str));
2972 :
2973 0 : snprintf(args->errmsg, args->errmsg_len,
2974 : "%% Failure leaving IGMP group %s %s on interface %s: %d",
2975 0 : src_str, grp_str, ifp->name, result);
2976 :
2977 0 : return NB_ERR_INCONSISTENCY;
2978 : }
2979 :
2980 : break;
2981 : }
2982 :
2983 : return NB_OK;
2984 : }
|