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