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