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