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