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