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