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