]> git.proxmox.com Git - mirror_frr.git/blob - pimd/pim_nb_config.c
Merge pull request #10883 from donaldsharp/bgp_evpn_stream_read
[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 pim_addr 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_pimaddr(&source_addr, args->dnode,
944 "./source-addr");
945 result = pim_ssmpingd_start(pim, source_addr);
946 if (result) {
947 snprintf(
948 args->errmsg, args->errmsg_len,
949 "%% Failure starting ssmpingd for source %pPA: %d",
950 &source_addr, result);
951 return NB_ERR_INCONSISTENCY;
952 }
953 }
954
955 return NB_OK;
956 }
957
958 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_ssm_pingd_source_ip_destroy(
959 struct nb_cb_destroy_args *args)
960 {
961 struct vrf *vrf;
962 struct pim_instance *pim;
963 int result;
964 pim_addr source_addr;
965
966 switch (args->event) {
967 case NB_EV_VALIDATE:
968 case NB_EV_PREPARE:
969 case NB_EV_ABORT:
970 break;
971 case NB_EV_APPLY:
972 vrf = nb_running_get_entry(args->dnode, NULL, true);
973 pim = vrf->info;
974 yang_dnode_get_pimaddr(&source_addr, args->dnode,
975 "./source-addr");
976 result = pim_ssmpingd_stop(pim, source_addr);
977 if (result) {
978 snprintf(
979 args->errmsg, args->errmsg_len,
980 "%% Failure stopping ssmpingd for source %pPA: %d",
981 &source_addr, result);
982 return NB_ERR_INCONSISTENCY;
983 }
984
985 break;
986 }
987
988 return NB_OK;
989 }
990
991 /*
992 * XPath:
993 * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp/hold-time
994 */
995 int pim_msdp_hold_time_modify(struct nb_cb_modify_args *args)
996 {
997 struct pim_instance *pim;
998 struct vrf *vrf;
999
1000 switch (args->event) {
1001 case NB_EV_VALIDATE:
1002 case NB_EV_PREPARE:
1003 case NB_EV_ABORT:
1004 break;
1005 case NB_EV_APPLY:
1006 vrf = nb_running_get_entry(args->dnode, NULL, true);
1007 pim = vrf->info;
1008 pim->msdp.hold_time = yang_dnode_get_uint16(args->dnode, NULL);
1009 break;
1010 }
1011
1012 return NB_OK;
1013 }
1014
1015 /*
1016 * XPath:
1017 * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp/keep-alive
1018 */
1019 int pim_msdp_keep_alive_modify(struct nb_cb_modify_args *args)
1020 {
1021 struct pim_instance *pim;
1022 struct vrf *vrf;
1023
1024 switch (args->event) {
1025 case NB_EV_VALIDATE:
1026 case NB_EV_PREPARE:
1027 case NB_EV_ABORT:
1028 break;
1029 case NB_EV_APPLY:
1030 vrf = nb_running_get_entry(args->dnode, NULL, true);
1031 pim = vrf->info;
1032 pim->msdp.keep_alive = yang_dnode_get_uint16(args->dnode, NULL);
1033 break;
1034 }
1035
1036 return NB_OK;
1037 }
1038
1039 /*
1040 * XPath:
1041 * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp/connection-retry
1042 */
1043 int pim_msdp_connection_retry_modify(struct nb_cb_modify_args *args)
1044 {
1045 struct pim_instance *pim;
1046 struct vrf *vrf;
1047
1048 switch (args->event) {
1049 case NB_EV_VALIDATE:
1050 case NB_EV_PREPARE:
1051 case NB_EV_ABORT:
1052 break;
1053 case NB_EV_APPLY:
1054 vrf = nb_running_get_entry(args->dnode, NULL, true);
1055 pim = vrf->info;
1056 pim->msdp.connection_retry =
1057 yang_dnode_get_uint16(args->dnode, NULL);
1058 break;
1059 }
1060
1061 return NB_OK;
1062 }
1063
1064 pim6_msdp_err(pim_msdp_mesh_group_destroy, nb_cb_destroy_args);
1065 pim6_msdp_err(pim_msdp_mesh_group_create, nb_cb_create_args);
1066 pim6_msdp_err(pim_msdp_mesh_group_source_modify, nb_cb_modify_args);
1067 pim6_msdp_err(pim_msdp_mesh_group_source_destroy, nb_cb_destroy_args);
1068 pim6_msdp_err(pim_msdp_mesh_group_members_create, nb_cb_create_args);
1069 pim6_msdp_err(pim_msdp_mesh_group_members_destroy, nb_cb_destroy_args);
1070 pim6_msdp_err(routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_peer_source_ip_modify,
1071 nb_cb_modify_args);
1072 pim6_msdp_err(routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_peer_destroy,
1073 nb_cb_destroy_args);
1074 pim6_msdp_err(routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_peer_create,
1075 nb_cb_create_args);
1076
1077 #if PIM_IPV != 6
1078 /*
1079 * XPath:
1080 * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp-mesh-groups
1081 */
1082 int pim_msdp_mesh_group_create(struct nb_cb_create_args *args)
1083 {
1084 struct pim_msdp_mg *mg;
1085 struct vrf *vrf;
1086
1087 switch (args->event) {
1088 case NB_EV_VALIDATE:
1089 case NB_EV_PREPARE:
1090 case NB_EV_ABORT:
1091 break;
1092 case NB_EV_APPLY:
1093 vrf = nb_running_get_entry(args->dnode, NULL, true);
1094 mg = pim_msdp_mg_new(vrf->info, yang_dnode_get_string(
1095 args->dnode, "./name"));
1096 nb_running_set_entry(args->dnode, mg);
1097 break;
1098 }
1099
1100 return NB_OK;
1101 }
1102
1103 int pim_msdp_mesh_group_destroy(struct nb_cb_destroy_args *args)
1104 {
1105 struct pim_msdp_mg *mg;
1106 struct vrf *vrf;
1107
1108 switch (args->event) {
1109 case NB_EV_VALIDATE:
1110 case NB_EV_PREPARE:
1111 case NB_EV_ABORT:
1112 break;
1113 case NB_EV_APPLY:
1114 mg = nb_running_unset_entry(args->dnode);
1115 vrf = nb_running_get_entry(args->dnode, NULL, true);
1116 pim_msdp_mg_free(vrf->info, &mg);
1117 break;
1118 }
1119
1120 return NB_OK;
1121 }
1122
1123 /*
1124 * XPath:
1125 * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp-mesh-groups/source
1126 */
1127 int pim_msdp_mesh_group_source_modify(struct nb_cb_modify_args *args)
1128 {
1129 const struct lyd_node *vrf_dnode;
1130 struct pim_msdp_mg *mg;
1131 struct vrf *vrf;
1132 struct ipaddr ip;
1133
1134 switch (args->event) {
1135 case NB_EV_VALIDATE:
1136 case NB_EV_PREPARE:
1137 case NB_EV_ABORT:
1138 break;
1139 case NB_EV_APPLY:
1140 mg = nb_running_get_entry(args->dnode, NULL, true);
1141 vrf_dnode =
1142 yang_dnode_get_parent(args->dnode, "address-family");
1143 vrf = nb_running_get_entry(vrf_dnode, "../../", true);
1144 yang_dnode_get_ip(&ip, args->dnode, NULL);
1145
1146 pim_msdp_mg_src_add(vrf->info, mg, &ip.ip._v4_addr);
1147 break;
1148 }
1149 return NB_OK;
1150 }
1151
1152 int pim_msdp_mesh_group_source_destroy(struct nb_cb_destroy_args *args)
1153 {
1154 const struct lyd_node *vrf_dnode;
1155 struct pim_msdp_mg *mg;
1156 struct vrf *vrf;
1157 struct in_addr addr;
1158
1159 switch (args->event) {
1160 case NB_EV_VALIDATE:
1161 case NB_EV_PREPARE:
1162 case NB_EV_ABORT:
1163 break;
1164 case NB_EV_APPLY:
1165 mg = nb_running_get_entry(args->dnode, NULL, true);
1166 vrf_dnode =
1167 yang_dnode_get_parent(args->dnode, "address-family");
1168 vrf = nb_running_get_entry(vrf_dnode, "../../", true);
1169
1170 addr.s_addr = INADDR_ANY;
1171 pim_msdp_mg_src_add(vrf->info, mg, &addr);
1172 break;
1173 }
1174 return NB_OK;
1175 }
1176
1177
1178 /*
1179 * XPath:
1180 * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp-mesh-groups/members
1181 */
1182 int pim_msdp_mesh_group_members_create(struct nb_cb_create_args *args)
1183 {
1184 const struct lyd_node *vrf_dnode;
1185 struct pim_msdp_mg_mbr *mbr;
1186 struct pim_msdp_mg *mg;
1187 struct vrf *vrf;
1188 struct ipaddr ip;
1189
1190 switch (args->event) {
1191 case NB_EV_VALIDATE:
1192 case NB_EV_PREPARE:
1193 case NB_EV_ABORT:
1194 break;
1195 case NB_EV_APPLY:
1196 mg = nb_running_get_entry(args->dnode, NULL, true);
1197 vrf_dnode =
1198 yang_dnode_get_parent(args->dnode, "address-family");
1199 vrf = nb_running_get_entry(vrf_dnode, "../../", true);
1200 yang_dnode_get_ip(&ip, args->dnode, "address");
1201
1202 mbr = pim_msdp_mg_mbr_add(vrf->info, mg, &ip.ip._v4_addr);
1203 nb_running_set_entry(args->dnode, mbr);
1204 break;
1205 }
1206
1207 return NB_OK;
1208 }
1209
1210 int pim_msdp_mesh_group_members_destroy(struct nb_cb_destroy_args *args)
1211 {
1212 struct pim_msdp_mg_mbr *mbr;
1213 struct pim_msdp_mg *mg;
1214 const struct lyd_node *mg_dnode;
1215
1216 switch (args->event) {
1217 case NB_EV_VALIDATE:
1218 case NB_EV_PREPARE:
1219 case NB_EV_ABORT:
1220 break;
1221 case NB_EV_APPLY:
1222 mbr = nb_running_get_entry(args->dnode, NULL, true);
1223 mg_dnode =
1224 yang_dnode_get_parent(args->dnode, "msdp-mesh-groups");
1225 mg = nb_running_get_entry(mg_dnode, NULL, true);
1226 pim_msdp_mg_mbr_del(mg, mbr);
1227 nb_running_unset_entry(args->dnode);
1228 break;
1229 }
1230
1231 return NB_OK;
1232 }
1233
1234 /*
1235 * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp-peer
1236 */
1237 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_peer_create(
1238 struct nb_cb_create_args *args)
1239 {
1240 struct pim_msdp_peer *mp;
1241 struct pim_instance *pim;
1242 struct vrf *vrf;
1243 struct ipaddr peer_ip;
1244 struct ipaddr source_ip;
1245
1246 switch (args->event) {
1247 case NB_EV_VALIDATE:
1248 case NB_EV_PREPARE:
1249 case NB_EV_ABORT:
1250 break;
1251 case NB_EV_APPLY:
1252 vrf = nb_running_get_entry(args->dnode, NULL, true);
1253 pim = vrf->info;
1254 yang_dnode_get_ip(&peer_ip, args->dnode, "./peer-ip");
1255 yang_dnode_get_ip(&source_ip, args->dnode, "./source-ip");
1256 mp = pim_msdp_peer_add(pim, &peer_ip.ipaddr_v4,
1257 &source_ip.ipaddr_v4, NULL);
1258 nb_running_set_entry(args->dnode, mp);
1259 break;
1260 }
1261
1262 return NB_OK;
1263 }
1264
1265 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_peer_destroy(
1266 struct nb_cb_destroy_args *args)
1267 {
1268 struct pim_msdp_peer *mp;
1269
1270 switch (args->event) {
1271 case NB_EV_VALIDATE:
1272 case NB_EV_PREPARE:
1273 case NB_EV_ABORT:
1274 break;
1275 case NB_EV_APPLY:
1276 mp = nb_running_unset_entry(args->dnode);
1277 pim_msdp_peer_del(&mp);
1278 break;
1279 }
1280
1281 return NB_OK;
1282 }
1283
1284 /*
1285 * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp-peer/source-ip
1286 */
1287 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_peer_source_ip_modify(
1288 struct nb_cb_modify_args *args)
1289 {
1290 struct pim_msdp_peer *mp;
1291 struct ipaddr source_ip;
1292
1293 switch (args->event) {
1294 case NB_EV_VALIDATE:
1295 case NB_EV_PREPARE:
1296 case NB_EV_ABORT:
1297 break;
1298 case NB_EV_APPLY:
1299 mp = nb_running_get_entry(args->dnode, NULL, true);
1300 yang_dnode_get_ip(&source_ip, args->dnode, NULL);
1301 pim_msdp_peer_change_source(mp, &source_ip.ipaddr_v4);
1302 break;
1303 }
1304
1305 return NB_OK;
1306 }
1307 #endif /* PIM_IPV != 6 */
1308
1309 /*
1310 * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/mlag
1311 */
1312 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_create(
1313 struct nb_cb_create_args *args)
1314 {
1315 switch (args->event) {
1316 case NB_EV_VALIDATE:
1317 case NB_EV_PREPARE:
1318 case NB_EV_ABORT:
1319 case NB_EV_APPLY:
1320 break;
1321 }
1322
1323 return NB_OK;
1324 }
1325
1326 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_destroy(
1327 struct nb_cb_destroy_args *args)
1328 {
1329 struct in_addr addr;
1330
1331 switch (args->event) {
1332 case NB_EV_VALIDATE:
1333 case NB_EV_PREPARE:
1334 case NB_EV_ABORT:
1335 break;
1336 case NB_EV_APPLY:
1337 addr.s_addr = 0;
1338 pim_vxlan_mlag_update(true/*mlag_enable*/,
1339 false/*peer_state*/, MLAG_ROLE_NONE,
1340 NULL/*peerlink*/, &addr);
1341 }
1342
1343 return NB_OK;
1344 }
1345
1346 /*
1347 * XPath:
1348 * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/mlag
1349 */
1350 void routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_apply_finish(
1351 struct nb_cb_apply_finish_args *args)
1352 {
1353 const char *ifname;
1354 uint32_t role;
1355 bool peer_state;
1356 struct interface *ifp;
1357 struct ipaddr reg_addr;
1358
1359 ifname = yang_dnode_get_string(args->dnode, "./peerlink-rif");
1360 ifp = if_lookup_by_name(ifname, VRF_DEFAULT);
1361 if (!ifp) {
1362 snprintf(args->errmsg, args->errmsg_len,
1363 "No such interface name %s", ifname);
1364 return;
1365 }
1366 role = yang_dnode_get_enum(args->dnode, "./my-role");
1367 peer_state = yang_dnode_get_bool(args->dnode, "./peer-state");
1368 yang_dnode_get_ip(&reg_addr, args->dnode, "./reg-address");
1369
1370 pim_vxlan_mlag_update(true, peer_state, role, ifp,
1371 &reg_addr.ip._v4_addr);
1372 }
1373
1374
1375 /*
1376 * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/mlag/peerlink-rif
1377 */
1378 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_peerlink_rif_modify(
1379 struct nb_cb_modify_args *args)
1380 {
1381 switch (args->event) {
1382 case NB_EV_VALIDATE:
1383 case NB_EV_PREPARE:
1384 case NB_EV_ABORT:
1385 case NB_EV_APPLY:
1386 break;
1387 }
1388
1389 return NB_OK;
1390 }
1391
1392 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_peerlink_rif_destroy(
1393 struct nb_cb_destroy_args *args)
1394 {
1395 switch (args->event) {
1396 case NB_EV_VALIDATE:
1397 case NB_EV_PREPARE:
1398 case NB_EV_ABORT:
1399 case NB_EV_APPLY:
1400 break;
1401 }
1402
1403 return NB_OK;
1404 }
1405
1406 /*
1407 * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/mlag/reg-address
1408 */
1409 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_reg_address_modify(
1410 struct nb_cb_modify_args *args)
1411 {
1412 switch (args->event) {
1413 case NB_EV_VALIDATE:
1414 case NB_EV_PREPARE:
1415 case NB_EV_ABORT:
1416 case NB_EV_APPLY:
1417 break;
1418 }
1419
1420 return NB_OK;
1421 }
1422
1423 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_reg_address_destroy(
1424 struct nb_cb_destroy_args *args)
1425 {
1426 switch (args->event) {
1427 case NB_EV_VALIDATE:
1428 case NB_EV_PREPARE:
1429 case NB_EV_ABORT:
1430 case NB_EV_APPLY:
1431 break;
1432 }
1433
1434 return NB_OK;
1435 }
1436
1437 /*
1438 * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/mlag/my-role
1439 */
1440 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_my_role_modify(
1441 struct nb_cb_modify_args *args)
1442 {
1443 switch (args->event) {
1444 case NB_EV_VALIDATE:
1445 case NB_EV_PREPARE:
1446 case NB_EV_ABORT:
1447 case NB_EV_APPLY:
1448 break;
1449 }
1450
1451 return NB_OK;
1452 }
1453
1454 /*
1455 * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/mlag/peer-state
1456 */
1457 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_peer_state_modify(
1458 struct nb_cb_modify_args *args)
1459 {
1460 switch (args->event) {
1461 case NB_EV_VALIDATE:
1462 case NB_EV_PREPARE:
1463 case NB_EV_ABORT:
1464 case NB_EV_APPLY:
1465 break;
1466 }
1467
1468 return NB_OK;
1469 }
1470
1471 /*
1472 * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/register-accept-list
1473 */
1474 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_register_accept_list_modify(
1475 struct nb_cb_modify_args *args)
1476 {
1477 struct vrf *vrf;
1478 struct pim_instance *pim;
1479 const char *plist;
1480
1481 switch (args->event) {
1482 case NB_EV_VALIDATE:
1483 case NB_EV_PREPARE:
1484 case NB_EV_ABORT:
1485 break;
1486 case NB_EV_APPLY:
1487 vrf = nb_running_get_entry(args->dnode, NULL, true);
1488 pim = vrf->info;
1489 plist = yang_dnode_get_string(args->dnode, NULL);
1490
1491 XFREE(MTYPE_PIM_PLIST_NAME, pim->register_plist);
1492 pim->register_plist = XSTRDUP(MTYPE_PIM_PLIST_NAME, plist);
1493
1494 break;
1495 }
1496
1497 return NB_OK;
1498 }
1499
1500 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_register_accept_list_destroy(
1501 struct nb_cb_destroy_args *args)
1502 {
1503 struct vrf *vrf;
1504 struct pim_instance *pim;
1505
1506 switch (args->event) {
1507 case NB_EV_VALIDATE:
1508 case NB_EV_PREPARE:
1509 case NB_EV_ABORT:
1510 break;
1511 case NB_EV_APPLY:
1512 vrf = nb_running_get_entry(args->dnode, NULL, true);
1513 pim = vrf->info;
1514
1515 XFREE(MTYPE_PIM_PLIST_NAME, pim->register_plist);
1516 break;
1517 }
1518
1519 return NB_OK;
1520 }
1521
1522 /*
1523 * XPath: /frr-interface:lib/interface/frr-pim:pim/address-family
1524 */
1525 int lib_interface_pim_address_family_create(struct nb_cb_create_args *args)
1526 {
1527 switch (args->event) {
1528 case NB_EV_VALIDATE:
1529 case NB_EV_PREPARE:
1530 case NB_EV_ABORT:
1531 case NB_EV_APPLY:
1532 break;
1533 }
1534
1535 return NB_OK;
1536 }
1537
1538 int lib_interface_pim_address_family_destroy(struct nb_cb_destroy_args *args)
1539 {
1540 struct interface *ifp;
1541 struct pim_interface *pim_ifp;
1542
1543 switch (args->event) {
1544 case NB_EV_VALIDATE:
1545 case NB_EV_PREPARE:
1546 case NB_EV_ABORT:
1547 break;
1548 case NB_EV_APPLY:
1549 ifp = nb_running_get_entry(args->dnode, NULL, true);
1550 pim_ifp = ifp->info;
1551 if (!pim_ifp)
1552 return NB_OK;
1553
1554 if (!pim_cmd_interface_delete(ifp)) {
1555 snprintf(args->errmsg, args->errmsg_len,
1556 "Unable to delete interface information %s",
1557 ifp->name);
1558 return NB_ERR_INCONSISTENCY;
1559 }
1560 }
1561
1562 return NB_OK;
1563 }
1564
1565 /*
1566 * XPath: /frr-interface:lib/interface/frr-pim:pim/address-family/pim-enable
1567 */
1568 int lib_interface_pim_address_family_pim_enable_modify(struct nb_cb_modify_args *args)
1569 {
1570 struct interface *ifp;
1571 struct pim_interface *pim_ifp;
1572 int mcast_if_count;
1573 const struct lyd_node *if_dnode;
1574
1575 switch (args->event) {
1576 case NB_EV_VALIDATE:
1577 if_dnode = yang_dnode_get_parent(args->dnode, "interface");
1578 mcast_if_count =
1579 yang_get_list_elements_count(if_dnode);
1580
1581 /* Limiting mcast interfaces to number of VIFs */
1582 if (mcast_if_count == MAXVIFS) {
1583 snprintf(args->errmsg, args->errmsg_len,
1584 "Max multicast interfaces(%d) reached.",
1585 MAXVIFS);
1586 return NB_ERR_VALIDATION;
1587 }
1588 break;
1589 case NB_EV_PREPARE:
1590 case NB_EV_ABORT:
1591 break;
1592 case NB_EV_APPLY:
1593 ifp = nb_running_get_entry(args->dnode, NULL, true);
1594
1595 if (yang_dnode_get_bool(args->dnode, NULL)) {
1596 if (!pim_cmd_interface_add(ifp)) {
1597 snprintf(args->errmsg, args->errmsg_len,
1598 "Could not enable PIM SM on interface %s",
1599 ifp->name);
1600 return NB_ERR_INCONSISTENCY;
1601 }
1602 } else {
1603 pim_ifp = ifp->info;
1604 if (!pim_ifp)
1605 return NB_ERR_INCONSISTENCY;
1606
1607 if (!pim_cmd_interface_delete(ifp)) {
1608 snprintf(args->errmsg, args->errmsg_len,
1609 "Unable to delete interface information");
1610 return NB_ERR_INCONSISTENCY;
1611 }
1612 }
1613 break;
1614 }
1615
1616 return NB_OK;
1617 }
1618
1619 /*
1620 * XPath: /frr-interface:lib/interface/frr-pim:pim/address-family/hello-interval
1621 */
1622 int lib_interface_pim_address_family_hello_interval_modify(
1623 struct nb_cb_modify_args *args)
1624 {
1625 struct interface *ifp;
1626 struct pim_interface *pim_ifp;
1627
1628 switch (args->event) {
1629 case NB_EV_VALIDATE:
1630 case NB_EV_ABORT:
1631 case NB_EV_PREPARE:
1632 break;
1633 case NB_EV_APPLY:
1634 ifp = nb_running_get_entry(args->dnode, NULL, true);
1635 pim_ifp = ifp->info;
1636 pim_ifp->pim_hello_period =
1637 yang_dnode_get_uint8(args->dnode, NULL);
1638 pim_ifp->pim_default_holdtime = -1;
1639 break;
1640 }
1641
1642 return NB_OK;
1643 }
1644
1645 /*
1646 * XPath: /frr-interface:lib/interface/frr-pim:pim/address-family/hello-holdtime
1647 */
1648 int lib_interface_pim_address_family_hello_holdtime_modify(
1649 struct nb_cb_modify_args *args)
1650 {
1651 struct interface *ifp;
1652 struct pim_interface *pim_ifp;
1653
1654 switch (args->event) {
1655 case NB_EV_VALIDATE:
1656 case NB_EV_ABORT:
1657 case NB_EV_PREPARE:
1658 break;
1659 case NB_EV_APPLY:
1660 ifp = nb_running_get_entry(args->dnode, NULL, true);
1661 pim_ifp = ifp->info;
1662 pim_ifp->pim_default_holdtime =
1663 yang_dnode_get_uint16(args->dnode, NULL);
1664 break;
1665 }
1666
1667 return NB_OK;
1668
1669 }
1670
1671 int lib_interface_pim_address_family_hello_holdtime_destroy(
1672 struct nb_cb_destroy_args *args)
1673 {
1674 struct interface *ifp;
1675 struct pim_interface *pim_ifp;
1676
1677 switch (args->event) {
1678 case NB_EV_VALIDATE:
1679 case NB_EV_ABORT:
1680 case NB_EV_PREPARE:
1681 break;
1682 case NB_EV_APPLY:
1683 ifp = nb_running_get_entry(args->dnode, NULL, true);
1684 pim_ifp = ifp->info;
1685 pim_ifp->pim_default_holdtime = -1;
1686 break;
1687 }
1688
1689 return NB_OK;
1690 }
1691 /*
1692 * XPath: /frr-interface:lib/interface/frr-pim:pim/address-family/bfd
1693 */
1694 int lib_interface_pim_address_family_bfd_create(struct nb_cb_create_args *args)
1695 {
1696 struct interface *ifp;
1697 struct pim_interface *pim_ifp;
1698
1699 switch (args->event) {
1700 case NB_EV_VALIDATE:
1701 case NB_EV_PREPARE:
1702 case NB_EV_ABORT:
1703 /* NOTHING */
1704 break;
1705 case NB_EV_APPLY:
1706 ifp = nb_running_get_entry(args->dnode, NULL, true);
1707 pim_ifp = ifp->info;
1708 pim_ifp->bfd_config.enabled = true;
1709 break;
1710 }
1711
1712 return NB_OK;
1713 }
1714
1715 int lib_interface_pim_address_family_bfd_destroy(
1716 struct nb_cb_destroy_args *args)
1717 {
1718 struct interface *ifp;
1719 struct pim_interface *pim_ifp;
1720 const struct lyd_node *if_dnode;
1721
1722 switch (args->event) {
1723 case NB_EV_VALIDATE:
1724 if_dnode = yang_dnode_get_parent(args->dnode, "interface");
1725 if (!is_pim_interface(if_dnode)) {
1726 snprintf(args->errmsg, args->errmsg_len,
1727 "Pim not enabled on this interface");
1728 return NB_ERR_VALIDATION;
1729 }
1730 break;
1731 case NB_EV_ABORT:
1732 case NB_EV_PREPARE:
1733 break;
1734 case NB_EV_APPLY:
1735 ifp = nb_running_get_entry(args->dnode, NULL, true);
1736 pim_ifp = ifp->info;
1737 pim_ifp->bfd_config.enabled = false;
1738 pim_bfd_reg_dereg_all_nbr(ifp);
1739 break;
1740 }
1741
1742 return NB_OK;
1743 }
1744
1745 /*
1746 * XPath: /frr-interface:lib/interface/frr-pim:pim/address-family/bfd
1747 */
1748 void lib_interface_pim_address_family_bfd_apply_finish(
1749 struct nb_cb_apply_finish_args *args)
1750 {
1751 struct interface *ifp;
1752 struct pim_interface *pim_ifp;
1753
1754 ifp = nb_running_get_entry(args->dnode, NULL, true);
1755 pim_ifp = ifp->info;
1756
1757 if (!pim_ifp) {
1758 zlog_debug("Pim not enabled on this interface");
1759 return;
1760 }
1761
1762 pim_ifp->bfd_config.detection_multiplier =
1763 yang_dnode_get_uint8(args->dnode, "./detect_mult");
1764 pim_ifp->bfd_config.min_rx =
1765 yang_dnode_get_uint16(args->dnode, "./min-rx-interval");
1766 pim_ifp->bfd_config.min_tx =
1767 yang_dnode_get_uint16(args->dnode, "./min-tx-interval");
1768
1769 pim_bfd_reg_dereg_all_nbr(ifp);
1770 }
1771
1772 /*
1773 * XPath: /frr-interface:lib/interface/frr-pim:pim/address-family/bfd/min-rx-interval
1774 */
1775 int lib_interface_pim_address_family_bfd_min_rx_interval_modify(
1776 struct nb_cb_modify_args *args)
1777 {
1778 switch (args->event) {
1779 case NB_EV_VALIDATE:
1780 case NB_EV_PREPARE:
1781 case NB_EV_ABORT:
1782 case NB_EV_APPLY:
1783 break;
1784 }
1785
1786 return NB_OK;
1787 }
1788
1789 /*
1790 * XPath: /frr-interface:lib/interface/frr-pim:pim/address-family/bfd/min-tx-interval
1791 */
1792 int lib_interface_pim_address_family_bfd_min_tx_interval_modify(
1793 struct nb_cb_modify_args *args)
1794 {
1795 switch (args->event) {
1796 case NB_EV_VALIDATE:
1797 case NB_EV_PREPARE:
1798 case NB_EV_ABORT:
1799 case NB_EV_APPLY:
1800 break;
1801 }
1802
1803 return NB_OK;
1804 }
1805
1806 /*
1807 * XPath: /frr-interface:lib/interface/frr-pim:pim/address-family/bfd/detect_mult
1808 */
1809 int lib_interface_pim_address_family_bfd_detect_mult_modify(
1810 struct nb_cb_modify_args *args)
1811 {
1812 switch (args->event) {
1813 case NB_EV_VALIDATE:
1814 case NB_EV_PREPARE:
1815 case NB_EV_ABORT:
1816 case NB_EV_APPLY:
1817 break;
1818 }
1819
1820 return NB_OK;
1821 }
1822
1823 /*
1824 * XPath: /frr-interface:lib/interface/frr-pim:pim/address-family/bfd/profile
1825 */
1826 int lib_interface_pim_address_family_bfd_profile_modify(
1827 struct nb_cb_modify_args *args)
1828 {
1829 struct interface *ifp;
1830 struct pim_interface *pim_ifp;
1831
1832 switch (args->event) {
1833 case NB_EV_VALIDATE:
1834 case NB_EV_PREPARE:
1835 case NB_EV_ABORT:
1836 /* NOTHING */
1837 break;
1838 case NB_EV_APPLY:
1839 ifp = nb_running_get_entry(args->dnode, NULL, true);
1840 pim_ifp = ifp->info;
1841 XFREE(MTYPE_TMP, pim_ifp->bfd_config.profile);
1842 pim_ifp->bfd_config.profile = XSTRDUP(
1843 MTYPE_TMP, yang_dnode_get_string(args->dnode, NULL));
1844 break;
1845 }
1846
1847 return NB_OK;
1848 }
1849
1850 int lib_interface_pim_address_family_bfd_profile_destroy(
1851 struct nb_cb_destroy_args *args)
1852 {
1853 struct interface *ifp;
1854 struct pim_interface *pim_ifp;
1855
1856 switch (args->event) {
1857 case NB_EV_VALIDATE:
1858 case NB_EV_PREPARE:
1859 case NB_EV_ABORT:
1860 /* NOTHING */
1861 break;
1862 case NB_EV_APPLY:
1863 ifp = nb_running_get_entry(args->dnode, NULL, true);
1864 pim_ifp = ifp->info;
1865 XFREE(MTYPE_TMP, pim_ifp->bfd_config.profile);
1866 break;
1867 }
1868
1869 return NB_OK;
1870 }
1871
1872 /*
1873 * XPath: /frr-interface:lib/interface/frr-pim:pim/address-family/bsm
1874 */
1875 int lib_interface_pim_address_family_bsm_modify(struct nb_cb_modify_args *args)
1876 {
1877 struct interface *ifp;
1878 struct pim_interface *pim_ifp;
1879
1880 switch (args->event) {
1881 case NB_EV_VALIDATE:
1882 case NB_EV_PREPARE:
1883 case NB_EV_ABORT:
1884 break;
1885 case NB_EV_APPLY:
1886 ifp = nb_running_get_entry(args->dnode, NULL, true);
1887 pim_ifp = ifp->info;
1888 pim_ifp->bsm_enable = yang_dnode_get_bool(args->dnode, NULL);
1889
1890 break;
1891 }
1892
1893 return NB_OK;
1894 }
1895
1896 /*
1897 * XPath: /frr-interface:lib/interface/frr-pim:pim/address-family/unicast-bsm
1898 */
1899 int lib_interface_pim_address_family_unicast_bsm_modify(
1900 struct nb_cb_modify_args *args)
1901 {
1902 struct interface *ifp;
1903 struct pim_interface *pim_ifp;
1904
1905 switch (args->event) {
1906 case NB_EV_VALIDATE:
1907 case NB_EV_PREPARE:
1908 case NB_EV_ABORT:
1909 break;
1910 case NB_EV_APPLY:
1911 ifp = nb_running_get_entry(args->dnode, NULL, true);
1912 pim_ifp = ifp->info;
1913 pim_ifp->ucast_bsm_accept =
1914 yang_dnode_get_bool(args->dnode, NULL);
1915
1916 break;
1917 }
1918
1919 return NB_OK;
1920 }
1921
1922 /*
1923 * XPath: /frr-interface:lib/interface/frr-pim:pim/address-family/active-active
1924 */
1925 int lib_interface_pim_address_family_active_active_modify(
1926 struct nb_cb_modify_args *args)
1927 {
1928 struct interface *ifp;
1929 struct pim_interface *pim_ifp;
1930
1931 switch (args->event) {
1932 case NB_EV_VALIDATE:
1933 case NB_EV_PREPARE:
1934 case NB_EV_ABORT:
1935 break;
1936 case NB_EV_APPLY:
1937 ifp = nb_running_get_entry(args->dnode, NULL, true);
1938 pim_ifp = ifp->info;
1939 if (yang_dnode_get_bool(args->dnode, NULL)) {
1940 if (PIM_DEBUG_MLAG)
1941 zlog_debug(
1942 "Configuring PIM active-active on Interface: %s",
1943 ifp->name);
1944 pim_if_configure_mlag_dualactive(pim_ifp);
1945 } else {
1946 if (PIM_DEBUG_MLAG)
1947 zlog_debug(
1948 "UnConfiguring PIM active-active on Interface: %s",
1949 ifp->name);
1950 pim_if_unconfigure_mlag_dualactive(pim_ifp);
1951 }
1952
1953 break;
1954 }
1955
1956 return NB_OK;
1957
1958 }
1959
1960 /*
1961 * XPath: /frr-interface:lib/interface/frr-pim:pim/address-family/dr-priority
1962 */
1963 int lib_interface_pim_address_family_dr_priority_modify(
1964 struct nb_cb_modify_args *args)
1965 {
1966 struct interface *ifp;
1967 struct pim_interface *pim_ifp;
1968 uint32_t old_dr_prio;
1969 const struct lyd_node *if_dnode;
1970
1971 switch (args->event) {
1972 case NB_EV_VALIDATE:
1973 if_dnode = yang_dnode_get_parent(args->dnode, "interface");
1974 if (!is_pim_interface(if_dnode)) {
1975 snprintf(args->errmsg, args->errmsg_len,
1976 "Pim not enabled on this interface");
1977 return NB_ERR_VALIDATION;
1978 }
1979 break;
1980 case NB_EV_PREPARE:
1981 case NB_EV_ABORT:
1982 break;
1983 case NB_EV_APPLY:
1984 ifp = nb_running_get_entry(args->dnode, NULL, true);
1985 pim_ifp = ifp->info;
1986 old_dr_prio = pim_ifp->pim_dr_priority;
1987 pim_ifp->pim_dr_priority = yang_dnode_get_uint32(args->dnode,
1988 NULL);
1989
1990 if (old_dr_prio != pim_ifp->pim_dr_priority) {
1991 pim_if_dr_election(ifp);
1992 pim_hello_restart_now(ifp);
1993 }
1994 break;
1995 }
1996
1997 return NB_OK;
1998 }
1999
2000 /*
2001 * XPath: /frr-interface:lib/interface/frr-pim:pim/address-family/use-source
2002 */
2003 int lib_interface_pim_address_family_use_source_modify(
2004 struct nb_cb_modify_args *args)
2005 {
2006 struct interface *ifp;
2007 pim_addr source_addr;
2008 int result;
2009 const struct lyd_node *if_dnode;
2010
2011 switch (args->event) {
2012 case NB_EV_VALIDATE:
2013 if_dnode = yang_dnode_get_parent(args->dnode, "interface");
2014 if (!is_pim_interface(if_dnode)) {
2015 snprintf(args->errmsg, args->errmsg_len,
2016 "Pim not enabled on this interface");
2017 return NB_ERR_VALIDATION;
2018 }
2019 break;
2020 case NB_EV_ABORT:
2021 case NB_EV_PREPARE:
2022 break;
2023 case NB_EV_APPLY:
2024 ifp = nb_running_get_entry(args->dnode, NULL, true);
2025 #if PIM_IPV == 4
2026 yang_dnode_get_ipv4(&source_addr, args->dnode, NULL);
2027 #else
2028 yang_dnode_get_ipv6(&source_addr, args->dnode, NULL);
2029 #endif
2030
2031 result = interface_pim_use_src_cmd_worker(
2032 ifp, source_addr,
2033 args->errmsg, args->errmsg_len);
2034
2035 if (result != PIM_SUCCESS)
2036 return NB_ERR_INCONSISTENCY;
2037
2038 break;
2039 }
2040
2041 return NB_OK;
2042 }
2043
2044 int lib_interface_pim_address_family_use_source_destroy(
2045 struct nb_cb_destroy_args *args)
2046 {
2047 struct interface *ifp;
2048 int result;
2049 const struct lyd_node *if_dnode;
2050
2051 switch (args->event) {
2052 case NB_EV_VALIDATE:
2053 if_dnode = yang_dnode_get_parent(args->dnode, "interface");
2054 if (!is_pim_interface(if_dnode)) {
2055 snprintf(args->errmsg, args->errmsg_len,
2056 "Pim not enabled on this interface");
2057 return NB_ERR_VALIDATION;
2058 }
2059 break;
2060 case NB_EV_ABORT:
2061 case NB_EV_PREPARE:
2062 break;
2063 case NB_EV_APPLY:
2064 ifp = nb_running_get_entry(args->dnode, NULL, true);
2065
2066 result = interface_pim_use_src_cmd_worker(ifp, PIMADDR_ANY,
2067 args->errmsg,
2068 args->errmsg_len);
2069
2070 if (result != PIM_SUCCESS)
2071 return NB_ERR_INCONSISTENCY;
2072
2073 break;
2074 }
2075
2076 return NB_OK;
2077 }
2078
2079 /*
2080 * XPath: /frr-interface:lib/interface/frr-pim:pim/address-family/multicast-boundary-oil
2081 */
2082 int lib_interface_pim_address_family_multicast_boundary_oil_modify(
2083 struct nb_cb_modify_args *args)
2084 {
2085 struct interface *ifp;
2086 struct pim_interface *pim_ifp;
2087 const char *plist;
2088 const struct lyd_node *if_dnode;
2089
2090 switch (args->event) {
2091 case NB_EV_VALIDATE:
2092 if_dnode = yang_dnode_get_parent(args->dnode, "interface");
2093 if (!is_pim_interface(if_dnode)) {
2094 snprintf(args->errmsg, args->errmsg_len,
2095 "Pim not enabled on this interface");
2096 return NB_ERR_VALIDATION;
2097 }
2098 break;
2099 case NB_EV_ABORT:
2100 case NB_EV_PREPARE:
2101 break;
2102 case NB_EV_APPLY:
2103 ifp = nb_running_get_entry(args->dnode, NULL, true);
2104 pim_ifp = ifp->info;
2105 plist = yang_dnode_get_string(args->dnode, NULL);
2106
2107 if (pim_ifp->boundary_oil_plist)
2108 XFREE(MTYPE_PIM_INTERFACE, pim_ifp->boundary_oil_plist);
2109
2110 pim_ifp->boundary_oil_plist =
2111 XSTRDUP(MTYPE_PIM_INTERFACE, plist);
2112
2113 break;
2114 }
2115
2116 return NB_OK;
2117 }
2118
2119 int lib_interface_pim_address_family_multicast_boundary_oil_destroy(
2120 struct nb_cb_destroy_args *args)
2121 {
2122 struct interface *ifp;
2123 struct pim_interface *pim_ifp;
2124 const struct lyd_node *if_dnode;
2125
2126 switch (args->event) {
2127 case NB_EV_VALIDATE:
2128 if_dnode = yang_dnode_get_parent(args->dnode, "interface");
2129 if (!is_pim_interface(if_dnode)) {
2130 snprintf(args->errmsg, args->errmsg_len,
2131 "%% Enable PIM and/or IGMP on this interface first");
2132 return NB_ERR_VALIDATION;
2133 }
2134 break;
2135 case NB_EV_ABORT:
2136 case NB_EV_PREPARE:
2137 break;
2138 case NB_EV_APPLY:
2139 ifp = nb_running_get_entry(args->dnode, NULL, true);
2140 pim_ifp = ifp->info;
2141 if (pim_ifp->boundary_oil_plist)
2142 XFREE(MTYPE_PIM_INTERFACE, pim_ifp->boundary_oil_plist);
2143 break;
2144 }
2145
2146 return NB_OK;
2147 }
2148
2149 /*
2150 * XPath: /frr-interface:lib/interface/frr-pim:pim/address-family/mroute
2151 */
2152 int lib_interface_pim_address_family_mroute_create(
2153 struct nb_cb_create_args *args)
2154 {
2155 switch (args->event) {
2156 case NB_EV_VALIDATE:
2157 case NB_EV_PREPARE:
2158 case NB_EV_ABORT:
2159 case NB_EV_APPLY:
2160 break;
2161 }
2162
2163 return NB_OK;
2164 }
2165
2166 int lib_interface_pim_address_family_mroute_destroy(
2167 struct nb_cb_destroy_args *args)
2168 {
2169 struct pim_instance *pim;
2170 struct pim_interface *pim_iifp;
2171 struct interface *iif;
2172 struct interface *oif;
2173 const char *oifname;
2174 pim_addr source_addr;
2175 pim_addr group_addr;
2176 const struct lyd_node *if_dnode;
2177
2178 switch (args->event) {
2179 case NB_EV_VALIDATE:
2180 if_dnode = yang_dnode_get_parent(args->dnode, "interface");
2181 if (!is_pim_interface(if_dnode)) {
2182 snprintf(args->errmsg, args->errmsg_len,
2183 "%% Enable PIM and/or IGMP on this interface first");
2184 return NB_ERR_VALIDATION;
2185 }
2186 break;
2187 case NB_EV_PREPARE:
2188 case NB_EV_ABORT:
2189 break;
2190 case NB_EV_APPLY:
2191 iif = nb_running_get_entry(args->dnode, NULL, true);
2192 pim_iifp = iif->info;
2193 pim = pim_iifp->pim;
2194
2195 oifname = yang_dnode_get_string(args->dnode, "./oif");
2196 oif = if_lookup_by_name(oifname, pim->vrf->vrf_id);
2197
2198 if (!oif) {
2199 snprintf(args->errmsg, args->errmsg_len,
2200 "No such interface name %s",
2201 oifname);
2202 return NB_ERR_INCONSISTENCY;
2203 }
2204
2205 yang_dnode_get_pimaddr(&source_addr, args->dnode, "./source-addr");
2206 yang_dnode_get_pimaddr(&group_addr, args->dnode, "./group-addr");
2207
2208 if (pim_static_del(pim, iif, oif, group_addr, source_addr)) {
2209 snprintf(args->errmsg, args->errmsg_len,
2210 "Failed to remove static mroute");
2211 return NB_ERR_INCONSISTENCY;
2212 }
2213
2214 break;
2215 }
2216
2217 return NB_OK;
2218 }
2219
2220 /*
2221 * XPath: /frr-interface:lib/interface/frr-pim:pim/address-family/mroute/oif
2222 */
2223 int lib_interface_pim_address_family_mroute_oif_modify(
2224 struct nb_cb_modify_args *args)
2225 {
2226 struct pim_instance *pim;
2227 struct pim_interface *pim_iifp;
2228 struct interface *iif;
2229 struct interface *oif;
2230 const char *oifname;
2231 pim_addr source_addr;
2232 pim_addr group_addr;
2233 const struct lyd_node *if_dnode;
2234
2235 switch (args->event) {
2236 case NB_EV_VALIDATE:
2237 if_dnode = yang_dnode_get_parent(args->dnode, "interface");
2238 if (!is_pim_interface(if_dnode)) {
2239 snprintf(args->errmsg, args->errmsg_len,
2240 "%% Enable PIM and/or IGMP on this interface first");
2241 return NB_ERR_VALIDATION;
2242 }
2243
2244 #ifdef PIM_ENFORCE_LOOPFREE_MFC
2245 iif = nb_running_get_entry(args->dnode, NULL, false);
2246 if (!iif) {
2247 return NB_OK;
2248 }
2249
2250 pim_iifp = iif->info;
2251 pim = pim_iifp->pim;
2252
2253 oifname = yang_dnode_get_string(args->dnode, NULL);
2254 oif = if_lookup_by_name(oifname, pim->vrf->vrf_id);
2255
2256 if (oif && (iif->ifindex == oif->ifindex)) {
2257 strlcpy(args->errmsg,
2258 "% IIF same as OIF and loopfree enforcement is enabled; rejecting",
2259 args->errmsg_len);
2260 return NB_ERR_VALIDATION;
2261 }
2262 #endif
2263 break;
2264 case NB_EV_PREPARE:
2265 case NB_EV_ABORT:
2266 break;
2267 case NB_EV_APPLY:
2268 iif = nb_running_get_entry(args->dnode, NULL, true);
2269 pim_iifp = iif->info;
2270 pim = pim_iifp->pim;
2271
2272 oifname = yang_dnode_get_string(args->dnode, NULL);
2273 oif = if_lookup_by_name(oifname, pim->vrf->vrf_id);
2274 if (!oif) {
2275 snprintf(args->errmsg, args->errmsg_len,
2276 "No such interface name %s",
2277 oifname);
2278 return NB_ERR_INCONSISTENCY;
2279 }
2280
2281 yang_dnode_get_pimaddr(&source_addr, args->dnode, "../source-addr");
2282 yang_dnode_get_pimaddr(&group_addr, args->dnode, "../group-addr");
2283
2284 if (pim_static_add(pim, iif, oif, group_addr, source_addr)) {
2285 snprintf(args->errmsg, args->errmsg_len,
2286 "Failed to add static mroute");
2287 return NB_ERR_INCONSISTENCY;
2288 }
2289
2290 break;
2291 }
2292
2293 return NB_OK;
2294 }
2295
2296 int lib_interface_pim_address_family_mroute_oif_destroy(
2297 struct nb_cb_destroy_args *args)
2298 {
2299 switch (args->event) {
2300 case NB_EV_VALIDATE:
2301 case NB_EV_PREPARE:
2302 case NB_EV_ABORT:
2303 case NB_EV_APPLY:
2304 break;
2305 }
2306
2307 return NB_OK;
2308 }
2309
2310 /*
2311 * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/frr-pim-rp:rp/static-rp/rp-list
2312 */
2313 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_static_rp_rp_list_create(
2314 struct nb_cb_create_args *args)
2315 {
2316 switch (args->event) {
2317 case NB_EV_VALIDATE:
2318 case NB_EV_PREPARE:
2319 case NB_EV_ABORT:
2320 case NB_EV_APPLY:
2321 break;
2322 }
2323
2324 return NB_OK;
2325 }
2326
2327 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_static_rp_rp_list_destroy(
2328 struct nb_cb_destroy_args *args)
2329 {
2330 struct vrf *vrf;
2331 struct pim_instance *pim;
2332 struct prefix group;
2333 pim_addr rp_addr;
2334 const char *plist;
2335 int result = 0;
2336
2337 switch (args->event) {
2338 case NB_EV_VALIDATE:
2339 case NB_EV_PREPARE:
2340 case NB_EV_ABORT:
2341 break;
2342 case NB_EV_APPLY:
2343 vrf = nb_running_get_entry(args->dnode, NULL, true);
2344 pim = vrf->info;
2345 yang_dnode_get_pimaddr(&rp_addr, args->dnode, "./rp-address");
2346
2347 if (yang_dnode_get(args->dnode, "./group-list")) {
2348 yang_dnode_get_prefix(&group, args->dnode,
2349 "./group-list");
2350 apply_mask(&group);
2351 result = pim_no_rp_cmd_worker(pim, rp_addr, group, NULL,
2352 args->errmsg,
2353 args->errmsg_len);
2354 }
2355
2356 else if (yang_dnode_get(args->dnode, "./prefix-list")) {
2357 plist = yang_dnode_get_string(args->dnode,
2358 "./prefix-list");
2359 if (!pim_get_all_mcast_group(&group)) {
2360 flog_err(
2361 EC_LIB_DEVELOPMENT,
2362 "Unable to convert 224.0.0.0/4 to prefix");
2363 return NB_ERR_INCONSISTENCY;
2364 }
2365
2366 result = pim_no_rp_cmd_worker(pim, rp_addr, group,
2367 plist, args->errmsg,
2368 args->errmsg_len);
2369 }
2370
2371 if (result)
2372 return NB_ERR_INCONSISTENCY;
2373 break;
2374 }
2375
2376 return NB_OK;
2377 }
2378
2379 /*
2380 * 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
2381 */
2382 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_static_rp_rp_list_group_list_create(
2383 struct nb_cb_create_args *args)
2384 {
2385 struct vrf *vrf;
2386 struct pim_instance *pim;
2387 struct prefix group;
2388 pim_addr rp_addr;
2389
2390 switch (args->event) {
2391 case NB_EV_VALIDATE:
2392 case NB_EV_PREPARE:
2393 case NB_EV_ABORT:
2394 break;
2395 case NB_EV_APPLY:
2396 vrf = nb_running_get_entry(args->dnode, NULL, true);
2397 pim = vrf->info;
2398 yang_dnode_get_pimaddr(&rp_addr, args->dnode, "../rp-address");
2399 yang_dnode_get_prefix(&group, args->dnode, NULL);
2400 apply_mask(&group);
2401 return pim_rp_cmd_worker(pim, rp_addr, group, NULL,
2402 args->errmsg, args->errmsg_len);
2403 }
2404
2405 return NB_OK;
2406 }
2407
2408 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_static_rp_rp_list_group_list_destroy(
2409 struct nb_cb_destroy_args *args)
2410 {
2411 struct vrf *vrf;
2412 struct pim_instance *pim;
2413 struct prefix group;
2414 pim_addr rp_addr;
2415
2416 switch (args->event) {
2417 case NB_EV_VALIDATE:
2418 case NB_EV_PREPARE:
2419 case NB_EV_ABORT:
2420 break;
2421 case NB_EV_APPLY:
2422 vrf = nb_running_get_entry(args->dnode, NULL, true);
2423 pim = vrf->info;
2424 yang_dnode_get_pimaddr(&rp_addr, args->dnode, "../rp-address");
2425 yang_dnode_get_prefix(&group, args->dnode, NULL);
2426 apply_mask(&group);
2427
2428 return pim_no_rp_cmd_worker(pim, rp_addr, group, NULL,
2429 args->errmsg, args->errmsg_len);
2430 }
2431
2432 return NB_OK;
2433 }
2434
2435 /*
2436 * 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
2437 */
2438 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_static_rp_rp_list_prefix_list_modify(
2439 struct nb_cb_modify_args *args)
2440 {
2441 struct vrf *vrf;
2442 struct pim_instance *pim;
2443 struct prefix group;
2444 pim_addr rp_addr;
2445 const char *plist;
2446
2447 switch (args->event) {
2448 case NB_EV_VALIDATE:
2449 case NB_EV_PREPARE:
2450 case NB_EV_ABORT:
2451 break;
2452 case NB_EV_APPLY:
2453 vrf = nb_running_get_entry(args->dnode, NULL, true);
2454 pim = vrf->info;
2455 plist = yang_dnode_get_string(args->dnode, NULL);
2456 yang_dnode_get_pimaddr(&rp_addr, args->dnode, "../rp-address");
2457 if (!pim_get_all_mcast_group(&group)) {
2458 flog_err(EC_LIB_DEVELOPMENT,
2459 "Unable to convert 224.0.0.0/4 to prefix");
2460 return NB_ERR_INCONSISTENCY;
2461 }
2462 return pim_rp_cmd_worker(pim, rp_addr, group, plist,
2463 args->errmsg, args->errmsg_len);
2464 }
2465
2466 return NB_OK;
2467 }
2468
2469 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_static_rp_rp_list_prefix_list_destroy(
2470 struct nb_cb_destroy_args *args)
2471 {
2472 struct vrf *vrf;
2473 struct pim_instance *pim;
2474 struct prefix group;
2475 pim_addr rp_addr;
2476 const char *plist;
2477
2478 switch (args->event) {
2479 case NB_EV_VALIDATE:
2480 case NB_EV_PREPARE:
2481 case NB_EV_ABORT:
2482 break;
2483 case NB_EV_APPLY:
2484 vrf = nb_running_get_entry(args->dnode, NULL, true);
2485 pim = vrf->info;
2486 yang_dnode_get_pimaddr(&rp_addr, args->dnode, "../rp-address");
2487 plist = yang_dnode_get_string(args->dnode, NULL);
2488 if (!pim_get_all_mcast_group(&group)) {
2489 flog_err(EC_LIB_DEVELOPMENT,
2490 "Unable to convert 224.0.0.0/4 to prefix");
2491 return NB_ERR_INCONSISTENCY;
2492 }
2493 return pim_no_rp_cmd_worker(pim, rp_addr, group, plist,
2494 args->errmsg, args->errmsg_len);
2495 break;
2496 }
2497
2498 return NB_OK;
2499 }
2500
2501 /*
2502 * XPath: /frr-interface:lib/interface/frr-gmp:gmp/address-family
2503 */
2504 int lib_interface_gmp_address_family_create(struct nb_cb_create_args *args)
2505 {
2506 switch (args->event) {
2507 case NB_EV_VALIDATE:
2508 case NB_EV_PREPARE:
2509 case NB_EV_ABORT:
2510 case NB_EV_APPLY:
2511 break;
2512 }
2513
2514 return NB_OK;
2515 }
2516
2517 int lib_interface_gmp_address_family_destroy(struct nb_cb_destroy_args *args)
2518 {
2519 struct interface *ifp;
2520 struct pim_interface *pim_ifp;
2521
2522 switch (args->event) {
2523 case NB_EV_VALIDATE:
2524 case NB_EV_PREPARE:
2525 case NB_EV_ABORT:
2526 break;
2527 case NB_EV_APPLY:
2528 ifp = nb_running_get_entry(args->dnode, NULL, true);
2529 pim_ifp = ifp->info;
2530
2531 if (!pim_ifp)
2532 return NB_OK;
2533
2534 PIM_IF_DONT_IGMP(pim_ifp->options);
2535
2536 pim_if_membership_clear(ifp);
2537
2538 pim_if_addr_del_all_igmp(ifp);
2539
2540 if (!PIM_IF_TEST_PIM(pim_ifp->options))
2541 pim_if_delete(ifp);
2542 }
2543
2544 return NB_OK;
2545 }
2546
2547 /*
2548 * XPath: /frr-interface:lib/interface/frr-gmp:gmp/address-family/enable
2549 */
2550 int lib_interface_gmp_address_family_enable_modify(
2551 struct nb_cb_modify_args *args)
2552 {
2553 struct interface *ifp;
2554 bool igmp_enable;
2555 struct pim_interface *pim_ifp;
2556 int mcast_if_count;
2557 const char *ifp_name;
2558 const struct lyd_node *if_dnode;
2559
2560 switch (args->event) {
2561 case NB_EV_VALIDATE:
2562 if_dnode = yang_dnode_get_parent(args->dnode, "interface");
2563 mcast_if_count =
2564 yang_get_list_elements_count(if_dnode);
2565 /* Limiting mcast interfaces to number of VIFs */
2566 if (mcast_if_count == MAXVIFS) {
2567 ifp_name = yang_dnode_get_string(if_dnode, "name");
2568 snprintf(args->errmsg, args->errmsg_len,
2569 "Max multicast interfaces(%d) Reached. Could not enable IGMP on interface %s",
2570 MAXVIFS, ifp_name);
2571 return NB_ERR_VALIDATION;
2572 }
2573 break;
2574 case NB_EV_PREPARE:
2575 case NB_EV_ABORT:
2576 break;
2577 case NB_EV_APPLY:
2578 ifp = nb_running_get_entry(args->dnode, NULL, true);
2579 igmp_enable = yang_dnode_get_bool(args->dnode, NULL);
2580
2581 if (igmp_enable)
2582 return pim_cmd_igmp_start(ifp);
2583
2584 else {
2585 pim_ifp = ifp->info;
2586
2587 if (!pim_ifp)
2588 return NB_ERR_INCONSISTENCY;
2589
2590 PIM_IF_DONT_IGMP(pim_ifp->options);
2591
2592 pim_if_membership_clear(ifp);
2593
2594 pim_if_addr_del_all_igmp(ifp);
2595
2596 if (!PIM_IF_TEST_PIM(pim_ifp->options))
2597 pim_if_delete(ifp);
2598 }
2599 }
2600
2601 return NB_OK;
2602 }
2603
2604 /*
2605 * XPath: /frr-interface:lib/interface/frr-gmp:gmp/address-family/igmp-version
2606 */
2607 int lib_interface_gmp_address_family_igmp_version_modify(
2608 struct nb_cb_modify_args *args)
2609 {
2610 struct interface *ifp;
2611 struct pim_interface *pim_ifp;
2612 int igmp_version, old_version = 0;
2613
2614 switch (args->event) {
2615 case NB_EV_VALIDATE:
2616 case NB_EV_PREPARE:
2617 case NB_EV_ABORT:
2618 break;
2619 case NB_EV_APPLY:
2620 ifp = nb_running_get_entry(args->dnode, NULL, true);
2621 pim_ifp = ifp->info;
2622
2623 if (!pim_ifp)
2624 return NB_ERR_INCONSISTENCY;
2625
2626 igmp_version = yang_dnode_get_uint8(args->dnode, NULL);
2627 old_version = pim_ifp->igmp_version;
2628 pim_ifp->igmp_version = igmp_version;
2629
2630 /* Current and new version is different refresh existing
2631 * membership. Going from 3 -> 2 or 2 -> 3.
2632 */
2633 if (old_version != igmp_version)
2634 pim_if_membership_refresh(ifp);
2635
2636 break;
2637 }
2638
2639 return NB_OK;
2640 }
2641
2642 int lib_interface_gmp_address_family_igmp_version_destroy(
2643 struct nb_cb_destroy_args *args)
2644 {
2645 struct interface *ifp;
2646 struct pim_interface *pim_ifp;
2647
2648 switch (args->event) {
2649 case NB_EV_VALIDATE:
2650 case NB_EV_PREPARE:
2651 case NB_EV_ABORT:
2652 break;
2653 case NB_EV_APPLY:
2654 ifp = nb_running_get_entry(args->dnode, NULL, true);
2655 pim_ifp = ifp->info;
2656 pim_ifp->igmp_version = IGMP_DEFAULT_VERSION;
2657 break;
2658 }
2659
2660 return NB_OK;
2661 }
2662
2663 /*
2664 * XPath: /frr-interface:lib/interface/frr-gmp:gmp/address-family/mld-version
2665 */
2666 int lib_interface_gmp_address_family_mld_version_modify(
2667 struct nb_cb_modify_args *args)
2668 {
2669 switch (args->event) {
2670 case NB_EV_VALIDATE:
2671 case NB_EV_PREPARE:
2672 case NB_EV_ABORT:
2673 case NB_EV_APPLY:
2674 break;
2675 }
2676
2677 return NB_OK;
2678 }
2679
2680 int lib_interface_gmp_address_family_mld_version_destroy(
2681 struct nb_cb_destroy_args *args)
2682 {
2683 switch (args->event) {
2684 case NB_EV_VALIDATE:
2685 case NB_EV_PREPARE:
2686 case NB_EV_ABORT:
2687 case NB_EV_APPLY:
2688 break;
2689 }
2690
2691 return NB_OK;
2692 }
2693
2694 /*
2695 * XPath: /frr-interface:lib/interface/frr-gmp:gmp/address-family/query-interval
2696 */
2697 int lib_interface_gmp_address_family_query_interval_modify(
2698 struct nb_cb_modify_args *args)
2699 {
2700 struct interface *ifp;
2701 int query_interval;
2702
2703 switch (args->event) {
2704 case NB_EV_VALIDATE:
2705 case NB_EV_PREPARE:
2706 case NB_EV_ABORT:
2707 break;
2708 case NB_EV_APPLY:
2709 ifp = nb_running_get_entry(args->dnode, NULL, true);
2710 query_interval = yang_dnode_get_uint16(args->dnode, NULL);
2711 change_query_interval(ifp->info, query_interval);
2712 }
2713
2714 return NB_OK;
2715 }
2716
2717 /*
2718 * XPath: /frr-interface:lib/interface/frr-gmp:gmp/address-family/query-max-response-time
2719 */
2720 int lib_interface_gmp_address_family_query_max_response_time_modify(
2721 struct nb_cb_modify_args *args)
2722 {
2723 struct interface *ifp;
2724 int query_max_response_time_dsec;
2725
2726 switch (args->event) {
2727 case NB_EV_VALIDATE:
2728 case NB_EV_PREPARE:
2729 case NB_EV_ABORT:
2730 break;
2731 case NB_EV_APPLY:
2732 ifp = nb_running_get_entry(args->dnode, NULL, true);
2733 query_max_response_time_dsec =
2734 yang_dnode_get_uint16(args->dnode, NULL);
2735 change_query_max_response_time(ifp->info,
2736 query_max_response_time_dsec);
2737 }
2738
2739 return NB_OK;
2740 }
2741
2742 /*
2743 * XPath: /frr-interface:lib/interface/frr-gmp:gmp/address-family/last-member-query-interval
2744 */
2745 int lib_interface_gmp_address_family_last_member_query_interval_modify(
2746 struct nb_cb_modify_args *args)
2747 {
2748 struct interface *ifp;
2749 struct pim_interface *pim_ifp;
2750 int last_member_query_interval;
2751
2752 switch (args->event) {
2753 case NB_EV_VALIDATE:
2754 case NB_EV_PREPARE:
2755 case NB_EV_ABORT:
2756 break;
2757 case NB_EV_APPLY:
2758 ifp = nb_running_get_entry(args->dnode, NULL, true);
2759 pim_ifp = ifp->info;
2760 last_member_query_interval =
2761 yang_dnode_get_uint16(args->dnode, NULL);
2762 pim_ifp->gm_specific_query_max_response_time_dsec =
2763 last_member_query_interval;
2764
2765 break;
2766 }
2767
2768 return NB_OK;
2769 }
2770
2771 /*
2772 * XPath: /frr-interface:lib/interface/frr-gmp:gmp/address-family/robustness-variable
2773 */
2774 int lib_interface_gmp_address_family_robustness_variable_modify(
2775 struct nb_cb_modify_args *args)
2776 {
2777 struct interface *ifp;
2778 struct pim_interface *pim_ifp;
2779 int last_member_query_count;
2780
2781 switch (args->event) {
2782 case NB_EV_VALIDATE:
2783 case NB_EV_PREPARE:
2784 case NB_EV_ABORT:
2785 break;
2786 case NB_EV_APPLY:
2787 ifp = nb_running_get_entry(args->dnode, NULL, true);
2788 pim_ifp = ifp->info;
2789 last_member_query_count =
2790 yang_dnode_get_uint8(args->dnode, NULL);
2791 pim_ifp->gm_last_member_query_count = last_member_query_count;
2792
2793 break;
2794 }
2795
2796 return NB_OK;
2797 }
2798
2799 /*
2800 * XPath: /frr-interface:lib/interface/frr-gmp:gmp/address-family/static-group
2801 */
2802 int lib_interface_gmp_address_family_static_group_create(
2803 struct nb_cb_create_args *args)
2804 {
2805 struct interface *ifp;
2806 struct ipaddr source_addr;
2807 struct ipaddr group_addr;
2808 int result;
2809 const char *ifp_name;
2810 const struct lyd_node *if_dnode;
2811
2812 switch (args->event) {
2813 case NB_EV_VALIDATE:
2814 if_dnode = yang_dnode_get_parent(args->dnode, "interface");
2815 if (!is_pim_interface(if_dnode)) {
2816 ifp_name = yang_dnode_get_string(if_dnode, "name");
2817 snprintf(args->errmsg, args->errmsg_len,
2818 "multicast not enabled on interface %s",
2819 ifp_name);
2820 return NB_ERR_VALIDATION;
2821 }
2822
2823 yang_dnode_get_ip(&group_addr, args->dnode, "./group-addr");
2824 if (pim_is_group_224_0_0_0_24(group_addr.ip._v4_addr)) {
2825 snprintf(
2826 args->errmsg, args->errmsg_len,
2827 "Groups within 224.0.0.0/24 are reserved and cannot be joined");
2828 return NB_ERR_VALIDATION;
2829 }
2830 break;
2831 case NB_EV_PREPARE:
2832 case NB_EV_ABORT:
2833 break;
2834 case NB_EV_APPLY:
2835 ifp = nb_running_get_entry(args->dnode, NULL, true);
2836 yang_dnode_get_ip(&source_addr, args->dnode, "./source-addr");
2837 yang_dnode_get_ip(&group_addr, args->dnode, "./group-addr");
2838
2839 result = pim_if_igmp_join_add(ifp, group_addr.ip._v4_addr,
2840 source_addr.ip._v4_addr);
2841 if (result) {
2842 snprintf(args->errmsg, args->errmsg_len,
2843 "Failure joining IGMP group");
2844 return NB_ERR_INCONSISTENCY;
2845 }
2846 }
2847
2848 return NB_OK;
2849 }
2850
2851 int lib_interface_gmp_address_family_static_group_destroy(
2852 struct nb_cb_destroy_args *args)
2853 {
2854 struct interface *ifp;
2855 struct ipaddr source_addr;
2856 struct ipaddr group_addr;
2857 int result;
2858
2859 switch (args->event) {
2860 case NB_EV_VALIDATE:
2861 case NB_EV_PREPARE:
2862 case NB_EV_ABORT:
2863 break;
2864 case NB_EV_APPLY:
2865 ifp = nb_running_get_entry(args->dnode, NULL, true);
2866 yang_dnode_get_ip(&source_addr, args->dnode, "./source-addr");
2867 yang_dnode_get_ip(&group_addr, args->dnode, "./group-addr");
2868
2869 result = pim_if_igmp_join_del(ifp, group_addr.ip._v4_addr,
2870 source_addr.ip._v4_addr);
2871
2872 if (result) {
2873 char src_str[INET_ADDRSTRLEN];
2874 char grp_str[INET_ADDRSTRLEN];
2875
2876 ipaddr2str(&source_addr, src_str, sizeof(src_str));
2877 ipaddr2str(&group_addr, grp_str, sizeof(grp_str));
2878
2879 snprintf(args->errmsg, args->errmsg_len,
2880 "%% Failure leaving IGMP group %s %s on interface %s: %d",
2881 src_str, grp_str, ifp->name, result);
2882
2883 return NB_ERR_INCONSISTENCY;
2884 }
2885
2886 break;
2887 }
2888
2889 return NB_OK;
2890 }