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