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