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