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