2 * Copyright (C) 2020 VmWare
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)
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
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
22 #include "lib/northbound_cli.h"
23 #include "pim_igmpv3.h"
27 #include "pim_static.h"
29 #include "pim_ssmpingd.h"
30 #include "pim_vxlan.h"
32 #include "lib_errors.h"
34 static void pim_if_membership_clear(struct interface
*ifp
)
36 struct pim_interface
*pim_ifp
;
41 if (PIM_IF_TEST_PIM(pim_ifp
->options
)
42 && PIM_IF_TEST_IGMP(pim_ifp
->options
)) {
46 pim_ifchannel_membership_clear(ifp
);
50 * When PIM is disabled on interface, IGMPv3 local membership
51 * information is not injected into PIM interface state.
53 * The function pim_if_membership_refresh() fetches all IGMPv3 local
54 * membership information into PIM. It is intented to be called
55 * whenever PIM is enabled on the interface in order to collect missed
56 * local membership information.
58 static void pim_if_membership_refresh(struct interface
*ifp
)
60 struct pim_interface
*pim_ifp
;
61 struct listnode
*sock_node
;
62 struct igmp_sock
*igmp
;
67 if (!PIM_IF_TEST_PIM(pim_ifp
->options
))
69 if (!PIM_IF_TEST_IGMP(pim_ifp
->options
))
73 * First clear off membership from all PIM (S,G) entries on the
77 pim_ifchannel_membership_clear(ifp
);
80 * Then restore PIM (S,G) membership from all IGMPv3 (S,G) entries on
84 /* scan igmp sockets */
85 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->igmp_socket_list
, sock_node
, igmp
)) {
86 struct listnode
*grpnode
;
87 struct igmp_group
*grp
;
89 /* scan igmp groups */
90 for (ALL_LIST_ELEMENTS_RO(igmp
->igmp_group_list
, grpnode
,
92 struct listnode
*srcnode
;
93 struct igmp_source
*src
;
95 /* scan group sources */
96 for (ALL_LIST_ELEMENTS_RO(grp
->group_source_list
,
99 if (IGMP_SOURCE_TEST_FORWARDING(
100 src
->source_flags
)) {
104 sizeof(struct prefix_sg
));
105 sg
.src
= src
->source_addr
;
106 sg
.grp
= grp
->group_addr
;
107 pim_ifchannel_local_membership_add(
108 ifp
, &sg
, false /*is_vxlan*/);
111 } /* scan group sources */
112 } /* scan igmp groups */
113 } /* scan igmp sockets */
116 * Finally delete every PIM (S,G) entry lacking all state info
119 pim_ifchannel_delete_on_noinfo(ifp
);
122 static int pim_cmd_interface_add(struct interface
*ifp
)
124 struct pim_interface
*pim_ifp
= ifp
->info
;
127 pim_ifp
= pim_if_new(ifp
, false, true, false, false);
129 PIM_IF_DO_PIM(pim_ifp
->options
);
131 pim_if_addr_add_all(ifp
);
132 pim_if_membership_refresh(ifp
);
134 pim_if_create_pimreg(pim_ifp
->pim
);
138 static int pim_cmd_interface_delete(struct interface
*ifp
)
140 struct pim_interface
*pim_ifp
= ifp
->info
;
145 PIM_IF_DONT_PIM(pim_ifp
->options
);
147 pim_if_membership_clear(ifp
);
150 * pim_sock_delete() removes all neighbors from
151 * pim_ifp->pim_neighbor_list.
153 pim_sock_delete(ifp
, "pim unconfigured on interface");
155 if (!PIM_IF_TEST_IGMP(pim_ifp
->options
)) {
156 pim_if_addr_del_all(ifp
);
163 static int interface_pim_use_src_cmd_worker(struct interface
*ifp
,
164 struct in_addr source_addr
,
165 char *errmsg
, size_t errmsg_len
)
170 result
= pim_update_source_set(ifp
, source_addr
);
175 case PIM_IFACE_NOT_FOUND
:
177 snprintf(errmsg
, errmsg_len
,
178 "Pim not enabled on this interface %s",
181 case PIM_UPDATE_SOURCE_DUP
:
183 snprintf(errmsg
, errmsg_len
, "Source already set");
187 snprintf(errmsg
, errmsg_len
, "Source set failed");
193 static int pim_cmd_spt_switchover(struct pim_instance
*pim
,
194 enum pim_spt_switchover spt
,
197 pim
->spt
.switchover
= spt
;
199 switch (pim
->spt
.switchover
) {
200 case PIM_SPT_IMMEDIATE
:
201 XFREE(MTYPE_PIM_PLIST_NAME
, pim
->spt
.plist
);
203 pim_upstream_add_lhr_star_pimreg(pim
);
205 case PIM_SPT_INFINITY
:
206 pim_upstream_remove_lhr_star_pimreg(pim
, plist
);
208 XFREE(MTYPE_PIM_PLIST_NAME
, pim
->spt
.plist
);
211 pim
->spt
.plist
= XSTRDUP(MTYPE_PIM_PLIST_NAME
, plist
);
218 static int pim_ssm_cmd_worker(struct pim_instance
*pim
, const char *plist
,
219 char *errmsg
, size_t errmsg_len
)
221 int result
= pim_ssm_range_set(pim
, pim
->vrf_id
, plist
);
224 if (result
== PIM_SSM_ERR_NONE
)
228 case PIM_SSM_ERR_NO_VRF
:
229 snprintf(errmsg
, errmsg_len
,
230 "VRF doesn't exist");
232 case PIM_SSM_ERR_DUP
:
233 snprintf(errmsg
, errmsg_len
,
237 snprintf(errmsg
, errmsg_len
,
238 "ssm range config failed");
244 static int ip_no_msdp_mesh_group_cmd_worker(struct pim_instance
*pim
,
246 char *errmsg
, size_t errmsg_len
)
248 enum pim_msdp_err result
;
250 result
= pim_msdp_mg_del(pim
, mg
);
253 case PIM_MSDP_ERR_NONE
:
255 case PIM_MSDP_ERR_NO_MG
:
256 snprintf(errmsg
, errmsg_len
,
257 "%% mesh-group does not exist");
260 snprintf(errmsg
, errmsg_len
,
261 "mesh-group source del failed");
264 return result
? NB_ERR
: NB_OK
;
267 static int ip_msdp_mesh_group_member_cmd_worker(struct pim_instance
*pim
,
269 struct in_addr mbr_ip
,
270 char *errmsg
, size_t errmsg_len
)
272 enum pim_msdp_err result
;
275 result
= pim_msdp_mg_mbr_add(pim
, mg
, mbr_ip
);
278 case PIM_MSDP_ERR_NONE
:
280 case PIM_MSDP_ERR_OOM
:
282 snprintf(errmsg
, errmsg_len
,
285 case PIM_MSDP_ERR_MG_MBR_EXISTS
:
287 snprintf(errmsg
, errmsg_len
,
288 "%% mesh-group member exists");
290 case PIM_MSDP_ERR_MAX_MESH_GROUPS
:
292 snprintf(errmsg
, errmsg_len
,
293 "%% Only one mesh-group allowed currently");
297 snprintf(errmsg
, errmsg_len
,
298 "%% member add failed");
304 static int ip_no_msdp_mesh_group_member_cmd_worker(struct pim_instance
*pim
,
306 struct in_addr mbr_ip
,
310 enum pim_msdp_err result
;
312 result
= pim_msdp_mg_mbr_del(pim
, mg
, mbr_ip
);
315 case PIM_MSDP_ERR_NONE
:
317 case PIM_MSDP_ERR_NO_MG
:
318 snprintf(errmsg
, errmsg_len
,
319 "%% mesh-group does not exist");
321 case PIM_MSDP_ERR_NO_MG_MBR
:
322 snprintf(errmsg
, errmsg_len
,
323 "%% mesh-group member does not exist");
326 snprintf(errmsg
, errmsg_len
,
327 "%% mesh-group member del failed");
330 return result
? NB_ERR
: NB_OK
;
333 static int ip_msdp_mesh_group_source_cmd_worker(struct pim_instance
*pim
,
335 struct in_addr src_ip
,
336 char *errmsg
, size_t errmsg_len
)
338 enum pim_msdp_err result
;
340 result
= pim_msdp_mg_src_add(pim
, mg
, src_ip
);
343 case PIM_MSDP_ERR_NONE
:
345 case PIM_MSDP_ERR_OOM
:
346 snprintf(errmsg
, errmsg_len
,
349 case PIM_MSDP_ERR_MAX_MESH_GROUPS
:
350 snprintf(errmsg
, errmsg_len
,
351 "%% Only one mesh-group allowed currently");
354 snprintf(errmsg
, errmsg_len
,
355 "%% source add failed");
358 return result
? NB_ERR
: NB_OK
;
361 static int ip_no_msdp_mesh_group_source_cmd_worker(struct pim_instance
*pim
,
366 enum pim_msdp_err result
;
368 result
= pim_msdp_mg_src_del(pim
, mg
);
371 case PIM_MSDP_ERR_NONE
:
373 case PIM_MSDP_ERR_NO_MG
:
374 snprintf(errmsg
, errmsg_len
,
375 "%% mesh-group does not exist");
378 snprintf(errmsg
, errmsg_len
,
379 "%% mesh-group source del failed");
382 return result
? NB_ERR
: NB_OK
;
385 static int ip_msdp_peer_cmd_worker(struct pim_instance
*pim
,
386 struct in_addr peer_addr
,
387 struct in_addr local_addr
,
388 char *errmsg
, size_t errmsg_len
)
390 enum pim_msdp_err result
;
393 result
= pim_msdp_peer_add(pim
, peer_addr
, local_addr
, "default",
396 case PIM_MSDP_ERR_NONE
:
398 case PIM_MSDP_ERR_OOM
:
400 snprintf(errmsg
, errmsg_len
,
403 case PIM_MSDP_ERR_PEER_EXISTS
:
405 snprintf(errmsg
, errmsg_len
,
408 case PIM_MSDP_ERR_MAX_MESH_GROUPS
:
410 snprintf(errmsg
, errmsg_len
,
411 "%% Only one mesh-group allowed currently");
415 snprintf(errmsg
, errmsg_len
,
416 "%% peer add failed");
422 static int ip_no_msdp_peer_cmd_worker(struct pim_instance
*pim
,
423 struct in_addr peer_addr
,
424 char *errmsg
, size_t errmsg_len
)
426 enum pim_msdp_err result
;
428 result
= pim_msdp_peer_del(pim
, peer_addr
);
430 case PIM_MSDP_ERR_NONE
:
432 case PIM_MSDP_ERR_NO_PEER
:
433 snprintf(errmsg
, errmsg_len
,
434 "%% Peer does not exist");
437 snprintf(errmsg
, errmsg_len
,
438 "%% peer del failed");
441 return result
? NB_ERR
: NB_OK
;
444 static int pim_rp_cmd_worker(struct pim_instance
*pim
,
445 struct in_addr rp_addr
,
446 struct prefix group
, const char *plist
,
447 char *errmsg
, size_t errmsg_len
)
449 char rp_str
[INET_ADDRSTRLEN
];
452 inet_ntop(AF_INET
, &rp_addr
, rp_str
, sizeof(rp_str
));
454 result
= pim_rp_new(pim
, rp_addr
, group
, plist
, RP_SRC_STATIC
);
456 if (result
== PIM_RP_NO_PATH
) {
457 snprintf(errmsg
, errmsg_len
,
458 "No Path to RP address specified: %s", rp_str
);
459 return NB_ERR_INCONSISTENCY
;
462 if (result
== PIM_GROUP_OVERLAP
) {
463 snprintf(errmsg
, errmsg_len
,
464 "Group range specified cannot exact match another");
465 return NB_ERR_INCONSISTENCY
;
468 if (result
== PIM_GROUP_PFXLIST_OVERLAP
) {
469 snprintf(errmsg
, errmsg_len
,
470 "This group is already covered by a RP prefix-list");
471 return NB_ERR_INCONSISTENCY
;
474 if (result
== PIM_RP_PFXLIST_IN_USE
) {
475 snprintf(errmsg
, errmsg_len
,
476 "The same prefix-list cannot be applied to multiple RPs");
477 return NB_ERR_INCONSISTENCY
;
483 static int pim_no_rp_cmd_worker(struct pim_instance
*pim
,
484 struct in_addr rp_addr
, struct prefix group
,
486 char *errmsg
, size_t errmsg_len
)
488 char rp_str
[INET_ADDRSTRLEN
];
489 char group_str
[PREFIX2STR_BUFFER
];
492 inet_ntop(AF_INET
, &rp_addr
, rp_str
, sizeof(rp_str
));
493 prefix2str(&group
, group_str
, sizeof(group_str
));
495 result
= pim_rp_del(pim
, rp_addr
, group
, plist
, RP_SRC_STATIC
);
497 if (result
== PIM_GROUP_BAD_ADDRESS
) {
498 snprintf(errmsg
, errmsg_len
,
499 "Bad group address specified: %s", group_str
);
500 return NB_ERR_INCONSISTENCY
;
503 if (result
== PIM_RP_BAD_ADDRESS
) {
504 snprintf(errmsg
, errmsg_len
,
505 "Bad RP address specified: %s", rp_str
);
506 return NB_ERR_INCONSISTENCY
;
509 if (result
== PIM_RP_NOT_FOUND
) {
510 snprintf(errmsg
, errmsg_len
,
511 "Unable to find specified RP");
512 return NB_ERR_INCONSISTENCY
;
518 static bool is_pim_interface(const struct lyd_node
*dnode
)
520 char if_xpath
[XPATH_MAXLEN
];
521 const struct lyd_node
*pim_enable_dnode
;
522 const struct lyd_node
*igmp_enable_dnode
;
524 yang_dnode_get_path(dnode
, if_xpath
, sizeof(if_xpath
));
525 pim_enable_dnode
= yang_dnode_get(dnode
, "%s/frr-pim:pim/pim-enable",
527 igmp_enable_dnode
= yang_dnode_get(dnode
,
528 "%s/frr-igmp:igmp/igmp-enable",
531 if (((pim_enable_dnode
) &&
532 (yang_dnode_get_bool(pim_enable_dnode
, "."))) ||
533 ((igmp_enable_dnode
) &&
534 (yang_dnode_get_bool(igmp_enable_dnode
, "."))))
540 static int pim_cmd_igmp_start(struct interface
*ifp
)
542 struct pim_interface
*pim_ifp
;
543 uint8_t need_startup
= 0;
548 (void)pim_if_new(ifp
, true, false, false, false);
551 if (!PIM_IF_TEST_IGMP(pim_ifp
->options
)) {
552 PIM_IF_DO_IGMP(pim_ifp
->options
);
557 /* 'ip igmp' executed multiple times, with need_startup
558 * avoid multiple if add all and membership refresh
561 pim_if_addr_add_all(ifp
);
562 pim_if_membership_refresh(ifp
);
569 * CLI reconfiguration affects the interface level (struct pim_interface).
570 * This function propagates the reconfiguration to every active socket
571 * for that interface.
573 static void igmp_sock_query_interval_reconfig(struct igmp_sock
*igmp
)
575 struct interface
*ifp
;
576 struct pim_interface
*pim_ifp
;
580 /* other querier present? */
582 if (igmp
->t_other_querier_timer
)
585 /* this is the querier */
587 zassert(igmp
->interface
);
588 zassert(igmp
->interface
->info
);
590 ifp
= igmp
->interface
;
593 if (PIM_DEBUG_IGMP_TRACE
) {
594 char ifaddr_str
[INET_ADDRSTRLEN
];
596 pim_inet4_dump("<ifaddr?>", igmp
->ifaddr
, ifaddr_str
,
598 zlog_debug("%s: Querier %s on %s reconfig query_interval=%d",
599 __func__
, ifaddr_str
, ifp
->name
,
600 pim_ifp
->igmp_default_query_interval
);
604 * igmp_startup_mode_on() will reset QQI:
606 * igmp->querier_query_interval = pim_ifp->igmp_default_query_interval;
608 igmp_startup_mode_on(igmp
);
611 static void igmp_sock_query_reschedule(struct igmp_sock
*igmp
)
613 if (igmp
->mtrace_only
)
616 if (igmp
->t_igmp_query_timer
) {
617 /* other querier present */
618 zassert(igmp
->t_igmp_query_timer
);
619 zassert(!igmp
->t_other_querier_timer
);
621 pim_igmp_general_query_off(igmp
);
622 pim_igmp_general_query_on(igmp
);
624 zassert(igmp
->t_igmp_query_timer
);
625 zassert(!igmp
->t_other_querier_timer
);
627 /* this is the querier */
629 zassert(!igmp
->t_igmp_query_timer
);
630 zassert(igmp
->t_other_querier_timer
);
632 pim_igmp_other_querier_timer_off(igmp
);
633 pim_igmp_other_querier_timer_on(igmp
);
635 zassert(!igmp
->t_igmp_query_timer
);
636 zassert(igmp
->t_other_querier_timer
);
640 static void change_query_interval(struct pim_interface
*pim_ifp
,
643 struct listnode
*sock_node
;
644 struct igmp_sock
*igmp
;
646 pim_ifp
->igmp_default_query_interval
= query_interval
;
648 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->igmp_socket_list
, sock_node
, igmp
)) {
649 igmp_sock_query_interval_reconfig(igmp
);
650 igmp_sock_query_reschedule(igmp
);
654 static void change_query_max_response_time(struct pim_interface
*pim_ifp
,
655 int query_max_response_time_dsec
)
657 struct listnode
*sock_node
;
658 struct igmp_sock
*igmp
;
660 pim_ifp
->igmp_query_max_response_time_dsec
=
661 query_max_response_time_dsec
;
664 * Below we modify socket/group/source timers in order to quickly
665 * reflect the change. Otherwise, those timers would args->eventually
669 /* scan all sockets */
670 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->igmp_socket_list
, sock_node
, igmp
)) {
671 struct listnode
*grp_node
;
672 struct igmp_group
*grp
;
674 /* reschedule socket general query */
675 igmp_sock_query_reschedule(igmp
);
677 /* scan socket groups */
678 for (ALL_LIST_ELEMENTS_RO(igmp
->igmp_group_list
, grp_node
,
680 struct listnode
*src_node
;
681 struct igmp_source
*src
;
683 /* reset group timers for groups in EXCLUDE mode */
684 if (grp
->group_filtermode_isexcl
)
685 igmp_group_reset_gmi(grp
);
687 /* scan group sources */
688 for (ALL_LIST_ELEMENTS_RO(grp
->group_source_list
,
691 /* reset source timers for sources with running
694 if (src
->t_source_timer
)
695 igmp_source_reset_gmi(igmp
, grp
, src
);
701 int routing_control_plane_protocols_name_validate(
702 struct nb_cb_create_args
*args
)
706 name
= yang_dnode_get_string(args
->dnode
, "./name");
707 if (!strmatch(name
, "pim")) {
708 snprintf(args
->errmsg
, args
->errmsg_len
,
709 "pim supports only one instance with name pimd");
710 return NB_ERR_VALIDATION
;
716 * XPath: /frr-pim:pim/packets
718 int pim_packets_modify(struct nb_cb_modify_args
*args
)
720 switch (args
->event
) {
726 router
->packet_process
= yang_dnode_get_uint8(args
->dnode
,
735 * XPath: /frr-pim:pim/join-prune-interval
737 int pim_join_prune_interval_modify(struct nb_cb_modify_args
*args
)
739 switch (args
->event
) {
745 router
->t_periodic
= yang_dnode_get_uint16(args
->dnode
, NULL
);
753 * XPath: /frr-pim:pim/register-suppress-time
755 int pim_register_suppress_time_modify(struct nb_cb_modify_args
*args
)
758 struct pim_instance
*pim
;
760 switch (args
->event
) {
766 vrf
= nb_running_get_entry(args
->dnode
, NULL
, true);
768 pim
->keep_alive_time
= yang_dnode_get_uint16(args
->dnode
, NULL
);
776 * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/ecmp
778 int routing_control_plane_protocols_control_plane_protocol_pim_ecmp_modify(
779 struct nb_cb_modify_args
*args
)
782 struct pim_instance
*pim
;
784 switch (args
->event
) {
790 vrf
= nb_running_get_entry(args
->dnode
, NULL
, true);
792 pim
->ecmp_enable
= yang_dnode_get_bool(args
->dnode
, NULL
);
799 * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/ecmp-rebalance
801 int routing_control_plane_protocols_control_plane_protocol_pim_ecmp_rebalance_modify(
802 struct nb_cb_modify_args
*args
)
805 struct pim_instance
*pim
;
807 switch (args
->event
) {
813 vrf
= nb_running_get_entry(args
->dnode
, NULL
, true);
815 pim
->ecmp_rebalance_enable
=
816 yang_dnode_get_bool(args
->dnode
, NULL
);
823 * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/keep-alive-timer
825 int routing_control_plane_protocols_control_plane_protocol_pim_keep_alive_timer_modify(
826 struct nb_cb_modify_args
*args
)
829 struct pim_instance
*pim
;
831 switch (args
->event
) {
837 vrf
= nb_running_get_entry(args
->dnode
, NULL
, true);
839 pim
->keep_alive_time
= yang_dnode_get_uint16(args
->dnode
, NULL
);
847 * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/rp-keep-alive-timer
849 int routing_control_plane_protocols_control_plane_protocol_pim_rp_keep_alive_timer_modify(
850 struct nb_cb_modify_args
*args
)
853 struct pim_instance
*pim
;
855 switch (args
->event
) {
861 vrf
= nb_running_get_entry(args
->dnode
, NULL
, true);
863 pim
->rp_keep_alive_time
= yang_dnode_get_uint16(args
->dnode
,
872 * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family
874 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_create(
875 struct nb_cb_create_args
*args
)
877 switch (args
->event
) {
888 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_destroy(
889 struct nb_cb_destroy_args
*args
)
891 switch (args
->event
) {
896 /* TODO: implement me. */
904 * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/send-v6-secondary
906 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_send_v6_secondary_modify(
907 struct nb_cb_modify_args
*args
)
910 struct pim_instance
*pim
;
912 switch (args
->event
) {
918 vrf
= nb_running_get_entry(args
->dnode
, NULL
, true);
920 pim
->send_v6_secondary
= yang_dnode_get_bool(args
->dnode
, NULL
);
927 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_send_v6_secondary_destroy(
928 struct nb_cb_destroy_args
*args
)
930 switch (args
->event
) {
943 * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/spt-switchover
945 void routing_control_plane_protocols_control_plane_protocol_pim_address_family_spt_switchover_apply_finish(
946 struct nb_cb_apply_finish_args
*args
)
949 struct pim_instance
*pim
;
950 int spt_switch_action
;
951 const char *prefix_list
= NULL
;
953 vrf
= nb_running_get_entry(args
->dnode
, NULL
, true);
955 spt_switch_action
= yang_dnode_get_enum(args
->dnode
, "./spt-action");
957 switch (spt_switch_action
) {
958 case PIM_SPT_INFINITY
:
959 if (yang_dnode_exists(args
->dnode
,
960 "./spt-infinity-prefix-list"))
961 prefix_list
= yang_dnode_get_string(
962 args
->dnode
, "./spt-infinity-prefix-list");
964 pim_cmd_spt_switchover(pim
, PIM_SPT_INFINITY
,
967 case PIM_SPT_IMMEDIATE
:
968 pim_cmd_spt_switchover(pim
, PIM_SPT_IMMEDIATE
, NULL
);
973 * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/spt-switchover/spt-action
975 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_spt_switchover_spt_action_modify(
976 struct nb_cb_modify_args
*args
)
978 switch (args
->event
) {
990 * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/spt-switchover/spt-infinity-prefix-list
992 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_spt_switchover_spt_infinity_prefix_list_modify(
993 struct nb_cb_modify_args
*args
)
995 switch (args
->event
) {
1006 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_spt_switchover_spt_infinity_prefix_list_destroy(
1007 struct nb_cb_destroy_args
*args
)
1009 switch (args
->event
) {
1010 case NB_EV_VALIDATE
:
1021 * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/ssm-prefix-list
1023 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_ssm_prefix_list_modify(
1024 struct nb_cb_modify_args
*args
)
1027 struct pim_instance
*pim
;
1028 const char *plist_name
;
1031 switch (args
->event
) {
1032 case NB_EV_VALIDATE
:
1037 vrf
= nb_running_get_entry(args
->dnode
, NULL
, true);
1039 plist_name
= yang_dnode_get_string(args
->dnode
, NULL
);
1040 result
= pim_ssm_cmd_worker(pim
, plist_name
, args
->errmsg
,
1044 return NB_ERR_INCONSISTENCY
;
1052 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_ssm_prefix_list_destroy(
1053 struct nb_cb_destroy_args
*args
)
1056 struct pim_instance
*pim
;
1059 switch (args
->event
) {
1060 case NB_EV_VALIDATE
:
1065 vrf
= nb_running_get_entry(args
->dnode
, NULL
, true);
1067 result
= pim_ssm_cmd_worker(pim
, NULL
, args
->errmsg
,
1071 return NB_ERR_INCONSISTENCY
;
1080 * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/ssm-pingd-source-ip
1082 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_ssm_pingd_source_ip_create(
1083 struct nb_cb_create_args
*args
)
1086 struct pim_instance
*pim
;
1088 struct ipaddr source_addr
;
1090 switch (args
->event
) {
1091 case NB_EV_VALIDATE
:
1096 vrf
= nb_running_get_entry(args
->dnode
, NULL
, true);
1098 yang_dnode_get_ip(&source_addr
, args
->dnode
, NULL
);
1099 result
= pim_ssmpingd_start(pim
, source_addr
.ip
._v4_addr
);
1101 char source_str
[INET_ADDRSTRLEN
];
1103 ipaddr2str(&source_addr
, source_str
,
1104 sizeof(source_str
));
1105 snprintf(args
->errmsg
, args
->errmsg_len
,
1106 "%% Failure starting ssmpingd for source %s: %d",
1107 source_str
, result
);
1108 return NB_ERR_INCONSISTENCY
;
1115 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_ssm_pingd_source_ip_destroy(
1116 struct nb_cb_destroy_args
*args
)
1119 struct pim_instance
*pim
;
1121 struct ipaddr source_addr
;
1123 switch (args
->event
) {
1124 case NB_EV_VALIDATE
:
1129 vrf
= nb_running_get_entry(args
->dnode
, NULL
, true);
1131 yang_dnode_get_ip(&source_addr
, args
->dnode
, NULL
);
1132 result
= pim_ssmpingd_stop(pim
, source_addr
.ip
._v4_addr
);
1134 char source_str
[INET_ADDRSTRLEN
];
1136 ipaddr2str(&source_addr
, source_str
,
1137 sizeof(source_str
));
1138 snprintf(args
->errmsg
, args
->errmsg_len
,
1139 "%% Failure stopping ssmpingd for source %s: %d",
1140 source_str
, result
);
1141 return NB_ERR_INCONSISTENCY
;
1151 * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp-mesh-group
1153 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_mesh_group_create(
1154 struct nb_cb_create_args
*args
)
1156 switch (args
->event
) {
1157 case NB_EV_VALIDATE
:
1167 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_mesh_group_destroy(
1168 struct nb_cb_destroy_args
*args
)
1171 struct pim_instance
*pim
;
1172 const char *mesh_group_name
;
1175 switch (args
->event
) {
1176 case NB_EV_VALIDATE
:
1181 vrf
= nb_running_get_entry(args
->dnode
, NULL
, true);
1183 mesh_group_name
= yang_dnode_get_string(args
->dnode
, ".");
1185 result
= ip_no_msdp_mesh_group_cmd_worker(pim
, mesh_group_name
,
1189 if (result
!= PIM_MSDP_ERR_NONE
)
1190 return NB_ERR_INCONSISTENCY
;
1199 * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp-mesh-group/mesh-group-name
1201 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_mesh_group_mesh_group_name_modify(
1202 struct nb_cb_modify_args
*args
)
1204 const char *mesh_group_name
;
1205 const char *mesh_group_name_old
;
1206 char xpath
[XPATH_MAXLEN
];
1208 switch (args
->event
) {
1209 case NB_EV_VALIDATE
:
1210 mesh_group_name
= yang_dnode_get_string(args
->dnode
, ".");
1211 yang_dnode_get_path(args
->dnode
, xpath
, sizeof(xpath
));
1213 if (yang_dnode_exists(running_config
->dnode
, xpath
) == false)
1216 mesh_group_name_old
= yang_dnode_get_string(
1217 running_config
->dnode
,
1219 if (strcmp(mesh_group_name
, mesh_group_name_old
)) {
1220 /* currently only one mesh-group can exist at a time */
1221 snprintf(args
->errmsg
, args
->errmsg_len
,
1222 "Only one mesh-group allowed currently");
1223 return NB_ERR_VALIDATION
;
1235 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_mesh_group_mesh_group_name_destroy(
1236 struct nb_cb_destroy_args
*args
)
1238 switch (args
->event
) {
1239 case NB_EV_VALIDATE
:
1250 * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp-mesh-group/member-ip
1252 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_mesh_group_member_ip_create(
1253 struct nb_cb_create_args
*args
)
1256 struct pim_instance
*pim
;
1257 const char *mesh_group_name
;
1258 struct ipaddr mbr_ip
;
1259 enum pim_msdp_err result
;
1261 switch (args
->event
) {
1262 case NB_EV_VALIDATE
:
1267 vrf
= nb_running_get_entry(args
->dnode
, NULL
, true);
1269 mesh_group_name
= yang_dnode_get_string(args
->dnode
,
1270 "../mesh-group-name");
1271 yang_dnode_get_ip(&mbr_ip
, args
->dnode
, NULL
);
1273 result
= ip_msdp_mesh_group_member_cmd_worker(
1274 pim
, mesh_group_name
, mbr_ip
.ip
._v4_addr
,
1275 args
->errmsg
, args
->errmsg_len
);
1277 if (result
!= PIM_MSDP_ERR_NONE
)
1278 return NB_ERR_INCONSISTENCY
;
1286 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_mesh_group_member_ip_destroy(
1287 struct nb_cb_destroy_args
*args
)
1290 struct pim_instance
*pim
;
1291 const char *mesh_group_name
;
1292 struct ipaddr mbr_ip
;
1293 enum pim_msdp_err result
;
1295 switch (args
->event
) {
1296 case NB_EV_VALIDATE
:
1301 vrf
= nb_running_get_entry(args
->dnode
, NULL
, true);
1303 mesh_group_name
= yang_dnode_get_string(args
->dnode
,
1304 "../mesh-group-name");
1305 yang_dnode_get_ip(&mbr_ip
, args
->dnode
, NULL
);
1307 result
= ip_no_msdp_mesh_group_member_cmd_worker(
1308 pim
, mesh_group_name
, mbr_ip
.ip
._v4_addr
,
1309 args
->errmsg
, args
->errmsg_len
);
1311 if (result
!= PIM_MSDP_ERR_NONE
)
1312 return NB_ERR_INCONSISTENCY
;
1321 * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp-mesh-group/source-ip
1323 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_mesh_group_source_ip_modify(
1324 struct nb_cb_modify_args
*args
)
1327 struct pim_instance
*pim
;
1328 const char *mesh_group_name
;
1329 struct ipaddr src_ip
;
1330 enum pim_msdp_err result
;
1332 switch (args
->event
) {
1333 case NB_EV_VALIDATE
:
1338 vrf
= nb_running_get_entry(args
->dnode
, NULL
, true);
1340 mesh_group_name
= yang_dnode_get_string(args
->dnode
,
1341 "../mesh-group-name");
1342 yang_dnode_get_ip(&src_ip
, args
->dnode
, NULL
);
1344 result
= ip_msdp_mesh_group_source_cmd_worker(
1345 pim
, mesh_group_name
, src_ip
.ip
._v4_addr
,
1346 args
->errmsg
, args
->errmsg_len
);
1348 if (result
!= PIM_MSDP_ERR_NONE
)
1349 return NB_ERR_INCONSISTENCY
;
1356 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_mesh_group_source_ip_destroy(
1357 struct nb_cb_destroy_args
*args
)
1360 struct pim_instance
*pim
;
1361 const char *mesh_group_name
;
1362 enum pim_msdp_err result
;
1364 switch (args
->event
) {
1365 case NB_EV_VALIDATE
:
1370 vrf
= nb_running_get_entry(args
->dnode
, NULL
, true);
1372 mesh_group_name
= yang_dnode_get_string(args
->dnode
,
1373 "../mesh-group-name");
1375 result
= ip_no_msdp_mesh_group_source_cmd_worker(
1376 pim
, mesh_group_name
, args
->errmsg
,
1379 if (result
!= PIM_MSDP_ERR_NONE
)
1380 return NB_ERR_INCONSISTENCY
;
1388 * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp-peer
1390 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_peer_create(
1391 struct nb_cb_create_args
*args
)
1393 switch (args
->event
) {
1394 case NB_EV_VALIDATE
:
1404 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_peer_destroy(
1405 struct nb_cb_destroy_args
*args
)
1408 struct pim_instance
*pim
;
1409 struct ipaddr peer_ip
;
1412 switch (args
->event
) {
1413 case NB_EV_VALIDATE
:
1418 vrf
= nb_running_get_entry(args
->dnode
, NULL
, true);
1420 yang_dnode_get_ip(&peer_ip
, args
->dnode
, "./peer-ip");
1421 result
= ip_no_msdp_peer_cmd_worker(pim
, peer_ip
.ip
._v4_addr
,
1426 return NB_ERR_INCONSISTENCY
;
1435 * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp-peer/source-ip
1437 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_peer_source_ip_modify(
1438 struct nb_cb_modify_args
*args
)
1442 struct pim_instance
*pim
;
1443 struct ipaddr peer_ip
;
1444 struct ipaddr source_ip
;
1445 const struct lyd_node
*mesh_group_name_dnode
;
1446 const char *mesh_group_name
;
1448 switch (args
->event
) {
1449 case NB_EV_VALIDATE
:
1450 mesh_group_name_dnode
=
1451 yang_dnode_get(args
->dnode
,
1452 "../../msdp-mesh-group/mesh-group-name");
1453 if (mesh_group_name_dnode
) {
1455 yang_dnode_get_string(mesh_group_name_dnode
,
1457 if (strcmp(mesh_group_name
, "default")) {
1458 /* currently only one mesh-group can exist at a
1461 snprintf(args
->errmsg
, args
->errmsg_len
,
1462 "%% Only one mesh-group allowed currently");
1463 return NB_ERR_VALIDATION
;
1471 vrf
= nb_running_get_entry(args
->dnode
, NULL
, true);
1473 yang_dnode_get_ip(&peer_ip
, args
->dnode
, "../peer-ip");
1474 yang_dnode_get_ip(&source_ip
, args
->dnode
, NULL
);
1476 result
= ip_msdp_peer_cmd_worker(pim
, peer_ip
.ip
._v4_addr
,
1477 source_ip
.ip
._v4_addr
,
1482 return NB_ERR_INCONSISTENCY
;
1490 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_peer_source_ip_destroy(
1491 struct nb_cb_destroy_args
*args
)
1493 switch (args
->event
) {
1494 case NB_EV_VALIDATE
:
1505 * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/mlag
1507 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_create(
1508 struct nb_cb_create_args
*args
)
1510 switch (args
->event
) {
1511 case NB_EV_VALIDATE
:
1521 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_destroy(
1522 struct nb_cb_destroy_args
*args
)
1524 struct in_addr addr
;
1526 switch (args
->event
) {
1527 case NB_EV_VALIDATE
:
1533 pim_vxlan_mlag_update(true/*mlag_enable*/,
1534 false/*peer_state*/, MLAG_ROLE_NONE
,
1535 NULL
/*peerlink*/, &addr
);
1543 * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/mlag
1545 void routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_apply_finish(
1546 struct nb_cb_apply_finish_args
*args
)
1551 struct interface
*ifp
;
1552 struct ipaddr reg_addr
;
1554 ifname
= yang_dnode_get_string(args
->dnode
, "./peerlink-rif");
1555 ifp
= if_lookup_by_name(ifname
, VRF_DEFAULT
);
1557 snprintf(args
->errmsg
, args
->errmsg_len
,
1558 "No such interface name %s", ifname
);
1561 role
= yang_dnode_get_enum(args
->dnode
, "./my-role");
1562 peer_state
= yang_dnode_get_bool(args
->dnode
, "./peer-state");
1563 yang_dnode_get_ip(®_addr
, args
->dnode
, "./reg-address");
1565 pim_vxlan_mlag_update(true, peer_state
, role
, ifp
,
1566 ®_addr
.ip
._v4_addr
);
1571 * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/mlag/peerlink-rif
1573 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_peerlink_rif_modify(
1574 struct nb_cb_modify_args
*args
)
1576 switch (args
->event
) {
1577 case NB_EV_VALIDATE
:
1587 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_peerlink_rif_destroy(
1588 struct nb_cb_destroy_args
*args
)
1590 switch (args
->event
) {
1591 case NB_EV_VALIDATE
:
1602 * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/mlag/reg-address
1604 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_reg_address_modify(
1605 struct nb_cb_modify_args
*args
)
1607 switch (args
->event
) {
1608 case NB_EV_VALIDATE
:
1618 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_reg_address_destroy(
1619 struct nb_cb_destroy_args
*args
)
1621 switch (args
->event
) {
1622 case NB_EV_VALIDATE
:
1633 * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/mlag/my-role
1635 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_my_role_modify(
1636 struct nb_cb_modify_args
*args
)
1638 switch (args
->event
) {
1639 case NB_EV_VALIDATE
:
1650 * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/mlag/peer-state
1652 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_peer_state_modify(
1653 struct nb_cb_modify_args
*args
)
1655 switch (args
->event
) {
1656 case NB_EV_VALIDATE
:
1667 * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/register-accept-list
1669 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_register_accept_list_modify(
1670 struct nb_cb_modify_args
*args
)
1673 struct pim_instance
*pim
;
1676 switch (args
->event
) {
1677 case NB_EV_VALIDATE
:
1682 vrf
= nb_running_get_entry(args
->dnode
, NULL
, true);
1684 plist
= yang_dnode_get_string(args
->dnode
, NULL
);
1686 XFREE(MTYPE_PIM_PLIST_NAME
, pim
->register_plist
);
1687 pim
->register_plist
= XSTRDUP(MTYPE_PIM_PLIST_NAME
, plist
);
1695 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_register_accept_list_destroy(
1696 struct nb_cb_destroy_args
*args
)
1699 struct pim_instance
*pim
;
1701 switch (args
->event
) {
1702 case NB_EV_VALIDATE
:
1707 vrf
= nb_running_get_entry(args
->dnode
, NULL
, true);
1710 XFREE(MTYPE_PIM_PLIST_NAME
, pim
->register_plist
);
1718 * XPath: /frr-interface:lib/interface/frr-pim:pim
1720 int lib_interface_pim_create(struct nb_cb_create_args
*args
)
1722 switch (args
->event
) {
1723 case NB_EV_VALIDATE
:
1733 int lib_interface_pim_destroy(struct nb_cb_destroy_args
*args
)
1735 struct interface
*ifp
;
1736 struct pim_interface
*pim_ifp
;
1738 switch (args
->event
) {
1739 case NB_EV_VALIDATE
:
1744 ifp
= nb_running_get_entry(args
->dnode
, NULL
, true);
1745 pim_ifp
= ifp
->info
;
1749 if (!pim_cmd_interface_delete(ifp
)) {
1750 snprintf(args
->errmsg
, args
->errmsg_len
,
1751 "Unable to delete interface information %s",
1753 return NB_ERR_INCONSISTENCY
;
1761 * XPath: /frr-interface:lib/interface/frr-pim:pim/pim-enable
1763 int lib_interface_pim_pim_enable_modify(struct nb_cb_modify_args
*args
)
1765 struct interface
*ifp
;
1766 struct pim_interface
*pim_ifp
;
1768 const struct lyd_node
*if_dnode
;
1770 switch (args
->event
) {
1771 case NB_EV_VALIDATE
:
1772 if_dnode
= yang_dnode_get_parent(args
->dnode
, "interface");
1774 yang_get_list_elements_count(if_dnode
);
1776 /* Limiting mcast interfaces to number of VIFs */
1777 if (mcast_if_count
== MAXVIFS
) {
1778 snprintf(args
->errmsg
, args
->errmsg_len
,
1779 "Max multicast interfaces(%d) reached.",
1781 return NB_ERR_VALIDATION
;
1788 ifp
= nb_running_get_entry(args
->dnode
, NULL
, true);
1790 if (yang_dnode_get_bool(args
->dnode
, NULL
)) {
1791 if (!pim_cmd_interface_add(ifp
)) {
1792 snprintf(args
->errmsg
, args
->errmsg_len
,
1793 "Could not enable PIM SM on interface %s",
1795 return NB_ERR_INCONSISTENCY
;
1798 pim_ifp
= ifp
->info
;
1800 return NB_ERR_INCONSISTENCY
;
1802 if (!pim_cmd_interface_delete(ifp
)) {
1803 snprintf(args
->errmsg
, args
->errmsg_len
,
1804 "Unable to delete interface information");
1805 return NB_ERR_INCONSISTENCY
;
1815 * XPath: /frr-interface:lib/interface/frr-pim:pim/hello-interval
1817 int lib_interface_pim_hello_interval_modify(struct nb_cb_modify_args
*args
)
1819 struct interface
*ifp
;
1820 struct pim_interface
*pim_ifp
;
1822 switch (args
->event
) {
1823 case NB_EV_VALIDATE
:
1828 ifp
= nb_running_get_entry(args
->dnode
, NULL
, true);
1829 pim_ifp
= ifp
->info
;
1830 pim_ifp
->pim_hello_period
=
1831 yang_dnode_get_uint8(args
->dnode
, NULL
);
1839 * XPath: /frr-interface:lib/interface/frr-pim:pim/hello-holdtime
1841 int lib_interface_pim_hello_holdtime_modify(struct nb_cb_modify_args
*args
)
1843 struct interface
*ifp
;
1844 struct pim_interface
*pim_ifp
;
1846 switch (args
->event
) {
1847 case NB_EV_VALIDATE
:
1852 ifp
= nb_running_get_entry(args
->dnode
, NULL
, true);
1853 pim_ifp
= ifp
->info
;
1854 pim_ifp
->pim_default_holdtime
=
1855 yang_dnode_get_uint8(args
->dnode
, NULL
);
1863 int lib_interface_pim_hello_holdtime_destroy(struct nb_cb_destroy_args
*args
)
1865 struct interface
*ifp
;
1866 struct pim_interface
*pim_ifp
;
1868 switch (args
->event
) {
1869 case NB_EV_VALIDATE
:
1874 ifp
= nb_running_get_entry(args
->dnode
, NULL
, true);
1875 pim_ifp
= ifp
->info
;
1876 pim_ifp
->pim_default_holdtime
= -1;
1883 * XPath: /frr-interface:lib/interface/frr-pim:pim/bfd
1885 int lib_interface_pim_bfd_create(struct nb_cb_create_args
*args
)
1887 switch (args
->event
) {
1888 case NB_EV_VALIDATE
:
1898 int lib_interface_pim_bfd_destroy(struct nb_cb_destroy_args
*args
)
1900 struct interface
*ifp
;
1901 struct pim_interface
*pim_ifp
;
1902 const struct lyd_node
*if_dnode
;
1904 switch (args
->event
) {
1905 case NB_EV_VALIDATE
:
1906 if_dnode
= yang_dnode_get_parent(args
->dnode
, "interface");
1907 if (!is_pim_interface(if_dnode
)) {
1908 snprintf(args
->errmsg
, args
->errmsg_len
,
1909 "Pim not enabled on this interface");
1910 return NB_ERR_VALIDATION
;
1917 ifp
= nb_running_get_entry(args
->dnode
->parent
, NULL
, true);
1918 pim_ifp
= ifp
->info
;
1919 if (pim_ifp
->bfd_info
) {
1920 pim_bfd_reg_dereg_all_nbr(ifp
,
1921 ZEBRA_BFD_DEST_DEREGISTER
);
1922 bfd_info_free(&(pim_ifp
->bfd_info
));
1931 * XPath: /frr-interface:lib/interface/frr-pim:pim/bfd
1933 void lib_interface_pim_bfd_apply_finish(struct nb_cb_apply_finish_args
*args
)
1935 struct interface
*ifp
;
1936 struct pim_interface
*pim_ifp
;
1939 uint8_t detect_mult
;
1941 ifp
= nb_running_get_entry(args
->dnode
->parent
, NULL
, true);
1942 pim_ifp
= ifp
->info
;
1945 zlog_debug("Pim not enabled on this interface");
1949 min_rx
= yang_dnode_get_uint16(args
->dnode
, "./min-rx-interval");
1950 min_tx
= yang_dnode_get_uint16(args
->dnode
, "./min-tx-interval");
1951 detect_mult
= yang_dnode_get_uint8(args
->dnode
, "./detect_mult");
1953 if ((min_rx
== BFD_DEF_MIN_RX
) && (min_tx
== BFD_DEF_MIN_TX
)
1954 && (detect_mult
== BFD_DEF_DETECT_MULT
))
1955 pim_bfd_if_param_set(ifp
, min_rx
, min_tx
, detect_mult
, 1);
1957 pim_bfd_if_param_set(ifp
, min_rx
, min_tx
, detect_mult
, 0);
1959 nb_running_set_entry(args
->dnode
, pim_ifp
->bfd_info
);
1963 * XPath: /frr-interface:lib/interface/frr-pim:pim/bfd/min-rx-interval
1965 int lib_interface_pim_bfd_min_rx_interval_modify(struct nb_cb_modify_args
*args
)
1967 switch (args
->event
) {
1968 case NB_EV_VALIDATE
:
1979 * XPath: /frr-interface:lib/interface/frr-pim:pim/bfd/min-tx-interval
1981 int lib_interface_pim_bfd_min_tx_interval_modify(struct nb_cb_modify_args
*args
)
1983 switch (args
->event
) {
1984 case NB_EV_VALIDATE
:
1995 * XPath: /frr-interface:lib/interface/frr-pim:pim/bfd/detect_mult
1997 int lib_interface_pim_bfd_detect_mult_modify(struct nb_cb_modify_args
*args
)
1999 switch (args
->event
) {
2000 case NB_EV_VALIDATE
:
2011 * XPath: /frr-interface:lib/interface/frr-pim:pim/bsm
2013 int lib_interface_pim_bsm_modify(struct nb_cb_modify_args
*args
)
2015 struct interface
*ifp
;
2016 struct pim_interface
*pim_ifp
;
2018 switch (args
->event
) {
2019 case NB_EV_VALIDATE
:
2024 ifp
= nb_running_get_entry(args
->dnode
, NULL
, true);
2025 pim_ifp
= ifp
->info
;
2026 pim_ifp
->bsm_enable
= yang_dnode_get_bool(args
->dnode
, NULL
);
2035 * XPath: /frr-interface:lib/interface/frr-pim:pim/unicast-bsm
2037 int lib_interface_pim_unicast_bsm_modify(struct nb_cb_modify_args
*args
)
2039 struct interface
*ifp
;
2040 struct pim_interface
*pim_ifp
;
2042 switch (args
->event
) {
2043 case NB_EV_VALIDATE
:
2048 ifp
= nb_running_get_entry(args
->dnode
, NULL
, true);
2049 pim_ifp
= ifp
->info
;
2050 pim_ifp
->ucast_bsm_accept
=
2051 yang_dnode_get_bool(args
->dnode
, NULL
);
2060 * XPath: /frr-interface:lib/interface/frr-pim:pim/active-active
2062 int lib_interface_pim_active_active_modify(struct nb_cb_modify_args
*args
)
2064 struct interface
*ifp
;
2065 struct pim_interface
*pim_ifp
;
2067 switch (args
->event
) {
2068 case NB_EV_VALIDATE
:
2073 ifp
= nb_running_get_entry(args
->dnode
, NULL
, true);
2074 pim_ifp
= ifp
->info
;
2075 if (yang_dnode_get_bool(args
->dnode
, NULL
)) {
2078 "Configuring PIM active-active on Interface: %s",
2080 pim_if_configure_mlag_dualactive(pim_ifp
);
2084 "UnConfiguring PIM active-active on Interface: %s",
2086 pim_if_unconfigure_mlag_dualactive(pim_ifp
);
2097 * XPath: /frr-interface:lib/interface/frr-pim:pim/dr-priority
2099 int lib_interface_pim_dr_priority_modify(struct nb_cb_modify_args
*args
)
2101 struct interface
*ifp
;
2102 struct pim_interface
*pim_ifp
;
2103 uint32_t old_dr_prio
;
2104 const struct lyd_node
*if_dnode
;
2106 switch (args
->event
) {
2107 case NB_EV_VALIDATE
:
2108 if_dnode
= yang_dnode_get_parent(args
->dnode
, "interface");
2109 if (!is_pim_interface(if_dnode
)) {
2110 snprintf(args
->errmsg
, args
->errmsg_len
,
2111 "Pim not enabled on this interface");
2112 return NB_ERR_VALIDATION
;
2119 ifp
= nb_running_get_entry(args
->dnode
, NULL
, true);
2120 pim_ifp
= ifp
->info
;
2121 old_dr_prio
= pim_ifp
->pim_dr_priority
;
2122 pim_ifp
->pim_dr_priority
= yang_dnode_get_uint32(args
->dnode
,
2125 if (old_dr_prio
!= pim_ifp
->pim_dr_priority
) {
2126 pim_if_dr_election(ifp
);
2127 pim_hello_restart_now(ifp
);
2136 * XPath: /frr-interface:lib/interface/frr-pim:pim/address-family
2138 int lib_interface_pim_address_family_create(struct nb_cb_create_args
*args
)
2140 switch (args
->event
) {
2141 case NB_EV_VALIDATE
:
2151 int lib_interface_pim_address_family_destroy(struct nb_cb_destroy_args
*args
)
2153 switch (args
->event
) {
2154 case NB_EV_VALIDATE
:
2165 * XPath: /frr-interface:lib/interface/frr-pim:pim/address-family/use-source
2167 int lib_interface_pim_address_family_use_source_modify(struct nb_cb_modify_args
*args
)
2169 struct interface
*ifp
;
2170 struct ipaddr source_addr
;
2172 const struct lyd_node
*if_dnode
;
2174 switch (args
->event
) {
2175 case NB_EV_VALIDATE
:
2176 if_dnode
= yang_dnode_get_parent(args
->dnode
, "interface");
2177 if (!is_pim_interface(if_dnode
)) {
2178 snprintf(args
->errmsg
, args
->errmsg_len
,
2179 "Pim not enabled on this interface");
2180 return NB_ERR_VALIDATION
;
2187 ifp
= nb_running_get_entry(args
->dnode
, NULL
, true);
2188 yang_dnode_get_ip(&source_addr
, args
->dnode
, NULL
);
2190 result
= interface_pim_use_src_cmd_worker(
2191 ifp
, source_addr
.ip
._v4_addr
,
2192 args
->errmsg
, args
->errmsg_len
);
2194 if (result
!= PIM_SUCCESS
)
2195 return NB_ERR_INCONSISTENCY
;
2203 int lib_interface_pim_address_family_use_source_destroy(
2204 struct nb_cb_destroy_args
*args
)
2206 struct interface
*ifp
;
2207 struct in_addr source_addr
= {INADDR_ANY
};
2209 const struct lyd_node
*if_dnode
;
2211 switch (args
->event
) {
2212 case NB_EV_VALIDATE
:
2213 if_dnode
= yang_dnode_get_parent(args
->dnode
, "interface");
2214 if (!is_pim_interface(if_dnode
)) {
2215 snprintf(args
->errmsg
, args
->errmsg_len
,
2216 "Pim not enabled on this interface");
2217 return NB_ERR_VALIDATION
;
2224 ifp
= nb_running_get_entry(args
->dnode
, NULL
, true);
2226 result
= interface_pim_use_src_cmd_worker(ifp
, source_addr
,
2230 if (result
!= PIM_SUCCESS
)
2231 return NB_ERR_INCONSISTENCY
;
2240 * XPath: /frr-interface:lib/interface/frr-pim:pim/address-family/multicast-boundary-oil
2242 int lib_interface_pim_address_family_multicast_boundary_oil_modify(
2243 struct nb_cb_modify_args
*args
)
2245 struct interface
*ifp
;
2246 struct pim_interface
*pim_ifp
;
2248 const struct lyd_node
*if_dnode
;
2250 switch (args
->event
) {
2251 case NB_EV_VALIDATE
:
2252 if_dnode
= yang_dnode_get_parent(args
->dnode
, "interface");
2253 if (!is_pim_interface(if_dnode
)) {
2254 snprintf(args
->errmsg
, args
->errmsg_len
,
2255 "Pim not enabled on this interface");
2256 return NB_ERR_VALIDATION
;
2263 ifp
= nb_running_get_entry(args
->dnode
, NULL
, true);
2264 pim_ifp
= ifp
->info
;
2265 plist
= yang_dnode_get_string(args
->dnode
, NULL
);
2267 if (pim_ifp
->boundary_oil_plist
)
2268 XFREE(MTYPE_PIM_INTERFACE
, pim_ifp
->boundary_oil_plist
);
2270 pim_ifp
->boundary_oil_plist
=
2271 XSTRDUP(MTYPE_PIM_INTERFACE
, plist
);
2279 int lib_interface_pim_address_family_multicast_boundary_oil_destroy(
2280 struct nb_cb_destroy_args
*args
)
2282 struct interface
*ifp
;
2283 struct pim_interface
*pim_ifp
;
2284 const struct lyd_node
*if_dnode
;
2286 switch (args
->event
) {
2287 case NB_EV_VALIDATE
:
2288 if_dnode
= yang_dnode_get_parent(args
->dnode
, "interface");
2289 if (!is_pim_interface(if_dnode
)) {
2290 snprintf(args
->errmsg
, args
->errmsg_len
,
2291 "%% Enable PIM and/or IGMP on this interface first");
2292 return NB_ERR_VALIDATION
;
2299 ifp
= nb_running_get_entry(args
->dnode
, NULL
, true);
2300 pim_ifp
= ifp
->info
;
2301 if (pim_ifp
->boundary_oil_plist
)
2302 XFREE(MTYPE_PIM_INTERFACE
, pim_ifp
->boundary_oil_plist
);
2310 * XPath: /frr-interface:lib/interface/frr-pim:pim/address-family/mroute
2312 int lib_interface_pim_address_family_mroute_create(
2313 struct nb_cb_create_args
*args
)
2315 switch (args
->event
) {
2316 case NB_EV_VALIDATE
:
2326 int lib_interface_pim_address_family_mroute_destroy(
2327 struct nb_cb_destroy_args
*args
)
2329 struct pim_instance
*pim
;
2330 struct pim_interface
*pim_iifp
;
2331 struct interface
*iif
;
2332 struct interface
*oif
;
2333 const char *oifname
;
2334 struct ipaddr source_addr
;
2335 struct ipaddr group_addr
;
2336 const struct lyd_node
*if_dnode
;
2338 switch (args
->event
) {
2339 case NB_EV_VALIDATE
:
2340 if_dnode
= yang_dnode_get_parent(args
->dnode
, "interface");
2341 if (!is_pim_interface(if_dnode
)) {
2342 snprintf(args
->errmsg
, args
->errmsg_len
,
2343 "%% Enable PIM and/or IGMP on this interface first");
2344 return NB_ERR_VALIDATION
;
2351 iif
= nb_running_get_entry(args
->dnode
, NULL
, true);
2352 pim_iifp
= iif
->info
;
2353 pim
= pim_iifp
->pim
;
2355 oifname
= yang_dnode_get_string(args
->dnode
, "./oif");
2356 oif
= if_lookup_by_name(oifname
, pim
->vrf_id
);
2359 snprintf(args
->errmsg
, args
->errmsg_len
,
2360 "No such interface name %s",
2362 return NB_ERR_INCONSISTENCY
;
2365 yang_dnode_get_ip(&source_addr
, args
->dnode
, "./source-addr");
2366 yang_dnode_get_ip(&group_addr
, args
->dnode
, "./group-addr");
2368 if (pim_static_del(pim
, iif
, oif
, group_addr
.ip
._v4_addr
,
2369 source_addr
.ip
._v4_addr
)) {
2370 snprintf(args
->errmsg
, args
->errmsg_len
,
2371 "Failed to remove static mroute");
2372 return NB_ERR_INCONSISTENCY
;
2382 * XPath: /frr-interface:lib/interface/frr-pim:pim/address-family/mroute/oif
2384 int lib_interface_pim_address_family_mroute_oif_modify(
2385 struct nb_cb_modify_args
*args
)
2387 struct pim_instance
*pim
;
2388 struct pim_interface
*pim_iifp
;
2389 struct interface
*iif
;
2390 struct interface
*oif
;
2391 const char *oifname
;
2392 struct ipaddr source_addr
;
2393 struct ipaddr group_addr
;
2394 const struct lyd_node
*if_dnode
;
2396 switch (args
->event
) {
2397 case NB_EV_VALIDATE
:
2398 if_dnode
= yang_dnode_get_parent(args
->dnode
, "interface");
2399 if (!is_pim_interface(if_dnode
)) {
2400 snprintf(args
->errmsg
, args
->errmsg_len
,
2401 "%% Enable PIM and/or IGMP on this interface first");
2402 return NB_ERR_VALIDATION
;
2409 iif
= nb_running_get_entry(args
->dnode
, NULL
, true);
2410 pim_iifp
= iif
->info
;
2411 pim
= pim_iifp
->pim
;
2413 oifname
= yang_dnode_get_string(args
->dnode
, NULL
);
2414 oif
= if_lookup_by_name(oifname
, pim
->vrf_id
);
2417 snprintf(args
->errmsg
, args
->errmsg_len
,
2418 "No such interface name %s",
2420 return NB_ERR_INCONSISTENCY
;
2423 yang_dnode_get_ip(&source_addr
, args
->dnode
, "../source-addr");
2424 yang_dnode_get_ip(&group_addr
, args
->dnode
, "../group-addr");
2426 if (pim_static_add(pim
, iif
, oif
, group_addr
.ip
._v4_addr
,
2427 source_addr
.ip
._v4_addr
)) {
2428 snprintf(args
->errmsg
, args
->errmsg_len
,
2429 "Failed to add static mroute");
2430 return NB_ERR_INCONSISTENCY
;
2439 int lib_interface_pim_address_family_mroute_oif_destroy(
2440 struct nb_cb_destroy_args
*args
)
2442 switch (args
->event
) {
2443 case NB_EV_VALIDATE
:
2454 * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/frr-pim-rp:rp/static-rp/rp-list
2456 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_static_rp_rp_list_create(
2457 struct nb_cb_create_args
*args
)
2459 switch (args
->event
) {
2460 case NB_EV_VALIDATE
:
2470 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_static_rp_rp_list_destroy(
2471 struct nb_cb_destroy_args
*args
)
2474 struct pim_instance
*pim
;
2475 struct prefix group
;
2476 struct ipaddr rp_addr
;
2480 switch (args
->event
) {
2481 case NB_EV_VALIDATE
:
2486 vrf
= nb_running_get_entry(args
->dnode
, NULL
, true);
2488 yang_dnode_get_ip(&rp_addr
, args
->dnode
, "./rp-address");
2490 if (yang_dnode_get(args
->dnode
, "./group-list")) {
2491 yang_dnode_get_ipv4p(&group
, args
->dnode
,
2493 apply_mask_ipv4((struct prefix_ipv4
*)&group
);
2494 result
= pim_no_rp_cmd_worker(pim
, rp_addr
.ip
._v4_addr
,
2495 group
, NULL
, args
->errmsg
,
2499 else if (yang_dnode_get(args
->dnode
, "./prefix-list")) {
2500 plist
= yang_dnode_get_string(args
->dnode
,
2502 if (!str2prefix("224.0.0.0/4", &group
)) {
2505 "Unable to convert 224.0.0.0/4 to prefix");
2506 return NB_ERR_INCONSISTENCY
;
2509 result
= pim_no_rp_cmd_worker(pim
, rp_addr
.ip
._v4_addr
,
2516 return NB_ERR_INCONSISTENCY
;
2524 * 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
2526 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_static_rp_rp_list_group_list_create(
2527 struct nb_cb_create_args
*args
)
2530 struct pim_instance
*pim
;
2531 struct prefix group
;
2532 struct ipaddr rp_addr
;
2534 switch (args
->event
) {
2535 case NB_EV_VALIDATE
:
2540 vrf
= nb_running_get_entry(args
->dnode
, NULL
, true);
2542 yang_dnode_get_ip(&rp_addr
, args
->dnode
, "../rp-address");
2543 yang_dnode_get_ipv4p(&group
, args
->dnode
, NULL
);
2544 apply_mask_ipv4((struct prefix_ipv4
*)&group
);
2546 return pim_rp_cmd_worker(pim
, rp_addr
.ip
._v4_addr
, group
,
2547 NULL
, args
->errmsg
, args
->errmsg_len
);
2553 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_static_rp_rp_list_group_list_destroy(
2554 struct nb_cb_destroy_args
*args
)
2557 struct pim_instance
*pim
;
2558 struct prefix group
;
2559 struct ipaddr rp_addr
;
2561 switch (args
->event
) {
2562 case NB_EV_VALIDATE
:
2567 vrf
= nb_running_get_entry(args
->dnode
, NULL
, true);
2569 yang_dnode_get_ip(&rp_addr
, args
->dnode
, "../rp-address");
2570 yang_dnode_get_ipv4p(&group
, args
->dnode
, NULL
);
2571 apply_mask_ipv4((struct prefix_ipv4
*)&group
);
2573 return pim_no_rp_cmd_worker(pim
, rp_addr
.ip
._v4_addr
, group
,
2582 * 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
2584 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_static_rp_rp_list_prefix_list_modify(
2585 struct nb_cb_modify_args
*args
)
2588 struct pim_instance
*pim
;
2589 struct prefix group
;
2590 struct ipaddr rp_addr
;
2593 switch (args
->event
) {
2594 case NB_EV_VALIDATE
:
2599 vrf
= nb_running_get_entry(args
->dnode
, NULL
, true);
2601 plist
= yang_dnode_get_string(args
->dnode
, NULL
);
2602 yang_dnode_get_ip(&rp_addr
, args
->dnode
, "../rp-address");
2603 if (!str2prefix("224.0.0.0/4", &group
)) {
2604 flog_err(EC_LIB_DEVELOPMENT
,
2605 "Unable to convert 224.0.0.0/4 to prefix");
2606 return NB_ERR_INCONSISTENCY
;
2608 return pim_rp_cmd_worker(pim
, rp_addr
.ip
._v4_addr
, group
,
2609 plist
, args
->errmsg
, args
->errmsg_len
);
2615 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_static_rp_rp_list_prefix_list_destroy(
2616 struct nb_cb_destroy_args
*args
)
2619 struct pim_instance
*pim
;
2620 struct prefix group
;
2621 struct ipaddr rp_addr
;
2624 switch (args
->event
) {
2625 case NB_EV_VALIDATE
:
2630 vrf
= nb_running_get_entry(args
->dnode
, NULL
, true);
2632 yang_dnode_get_ip(&rp_addr
, args
->dnode
, "../rp-address");
2633 plist
= yang_dnode_get_string(args
->dnode
, NULL
);
2634 if (!str2prefix("224.0.0.0/4", &group
)) {
2635 flog_err(EC_LIB_DEVELOPMENT
,
2636 "Unable to convert 224.0.0.0/4 to prefix");
2637 return NB_ERR_INCONSISTENCY
;
2639 return pim_no_rp_cmd_worker(pim
, rp_addr
.ip
._v4_addr
, group
,
2640 plist
, args
->errmsg
,
2649 * XPath: /frr-interface:lib/interface/frr-igmp:igmp
2651 int lib_interface_igmp_create(struct nb_cb_create_args
*args
)
2653 switch (args
->event
) {
2654 case NB_EV_VALIDATE
:
2664 int lib_interface_igmp_destroy(struct nb_cb_destroy_args
*args
)
2666 struct interface
*ifp
;
2667 struct pim_interface
*pim_ifp
;
2669 switch (args
->event
) {
2670 case NB_EV_VALIDATE
:
2675 ifp
= nb_running_get_entry(args
->dnode
, NULL
, true);
2676 pim_ifp
= ifp
->info
;
2681 PIM_IF_DONT_IGMP(pim_ifp
->options
);
2683 pim_if_membership_clear(ifp
);
2685 pim_if_addr_del_all_igmp(ifp
);
2687 if (!PIM_IF_TEST_PIM(pim_ifp
->options
))
2695 * XPath: /frr-interface:lib/interface/frr-igmp:igmp/igmp-enable
2697 int lib_interface_igmp_igmp_enable_modify(struct nb_cb_modify_args
*args
)
2699 struct interface
*ifp
;
2701 struct pim_interface
*pim_ifp
;
2703 const char *ifp_name
;
2704 const struct lyd_node
*if_dnode
;
2706 switch (args
->event
) {
2707 case NB_EV_VALIDATE
:
2708 if_dnode
= yang_dnode_get_parent(args
->dnode
, "interface");
2709 ifp_name
= yang_dnode_get_string(if_dnode
, ".");
2711 yang_get_list_elements_count(if_dnode
);
2712 /* Limiting mcast interfaces to number of VIFs */
2713 if (mcast_if_count
== MAXVIFS
) {
2714 snprintf(args
->errmsg
, args
->errmsg_len
,
2715 "Max multicast interfaces(%d) Reached. Could not enable IGMP on interface %s",
2717 return NB_ERR_VALIDATION
;
2724 ifp
= nb_running_get_entry(args
->dnode
, NULL
, true);
2725 igmp_enable
= yang_dnode_get_bool(args
->dnode
, NULL
);
2728 return pim_cmd_igmp_start(ifp
);
2731 pim_ifp
= ifp
->info
;
2734 return NB_ERR_INCONSISTENCY
;
2736 PIM_IF_DONT_IGMP(pim_ifp
->options
);
2738 pim_if_membership_clear(ifp
);
2740 pim_if_addr_del_all_igmp(ifp
);
2742 if (!PIM_IF_TEST_PIM(pim_ifp
->options
))
2751 * XPath: /frr-interface:lib/interface/frr-igmp:igmp/version
2753 int lib_interface_igmp_version_modify(struct nb_cb_modify_args
*args
)
2755 struct interface
*ifp
;
2756 struct pim_interface
*pim_ifp
;
2757 int igmp_version
, old_version
= 0;
2759 switch (args
->event
) {
2760 case NB_EV_VALIDATE
:
2765 ifp
= nb_running_get_entry(args
->dnode
, NULL
, true);
2766 pim_ifp
= ifp
->info
;
2769 return NB_ERR_INCONSISTENCY
;
2771 igmp_version
= yang_dnode_get_uint8(args
->dnode
, NULL
);
2772 old_version
= pim_ifp
->igmp_version
;
2773 pim_ifp
->igmp_version
= igmp_version
;
2775 /* Current and new version is different refresh existing
2776 * membership. Going from 3 -> 2 or 2 -> 3.
2778 if (old_version
!= igmp_version
)
2779 pim_if_membership_refresh(ifp
);
2787 int lib_interface_igmp_version_destroy(struct nb_cb_destroy_args
*args
)
2789 struct interface
*ifp
;
2790 struct pim_interface
*pim_ifp
;
2792 switch (args
->event
) {
2793 case NB_EV_VALIDATE
:
2798 ifp
= nb_running_get_entry(args
->dnode
, NULL
, true);
2799 pim_ifp
= ifp
->info
;
2800 pim_ifp
->igmp_version
= IGMP_DEFAULT_VERSION
;
2808 * XPath: /frr-interface:lib/interface/frr-igmp:igmp/query-interval
2810 int lib_interface_igmp_query_interval_modify(struct nb_cb_modify_args
*args
)
2812 struct interface
*ifp
;
2813 struct pim_interface
*pim_ifp
;
2815 int query_interval_dsec
;
2817 switch (args
->event
) {
2818 case NB_EV_VALIDATE
:
2823 ifp
= nb_running_get_entry(args
->dnode
, NULL
, true);
2824 pim_ifp
= ifp
->info
;
2825 query_interval
= yang_dnode_get_uint16(args
->dnode
, NULL
);
2826 query_interval_dsec
= 10 * query_interval
;
2827 if (query_interval_dsec
<=
2828 pim_ifp
->igmp_query_max_response_time_dsec
) {
2829 snprintf(args
->errmsg
, args
->errmsg_len
,
2830 "Can't set general query interval %d dsec <= query max response time %d dsec.",
2831 query_interval_dsec
,
2832 pim_ifp
->igmp_query_max_response_time_dsec
);
2833 return NB_ERR_INCONSISTENCY
;
2835 change_query_interval(pim_ifp
, query_interval
);
2842 * XPath: /frr-interface:lib/interface/frr-igmp:igmp/query-max-response-time
2844 int lib_interface_igmp_query_max_response_time_modify(
2845 struct nb_cb_modify_args
*args
)
2847 struct interface
*ifp
;
2848 struct pim_interface
*pim_ifp
;
2849 int query_max_response_time_dsec
;
2850 int default_query_interval_dsec
;
2852 switch (args
->event
) {
2853 case NB_EV_VALIDATE
:
2858 ifp
= nb_running_get_entry(args
->dnode
, NULL
, true);
2859 pim_ifp
= ifp
->info
;
2860 query_max_response_time_dsec
=
2861 yang_dnode_get_uint8(args
->dnode
, NULL
);
2862 default_query_interval_dsec
=
2863 10 * pim_ifp
->igmp_default_query_interval
;
2865 if (query_max_response_time_dsec
2866 >= default_query_interval_dsec
) {
2867 snprintf(args
->errmsg
, args
->errmsg_len
,
2868 "Can't set query max response time %d sec >= general query interval %d sec",
2869 query_max_response_time_dsec
,
2870 pim_ifp
->igmp_default_query_interval
);
2871 return NB_ERR_INCONSISTENCY
;
2874 change_query_max_response_time(pim_ifp
,
2875 query_max_response_time_dsec
);
2882 * XPath: /frr-interface:lib/interface/frr-igmp:igmp/last-member-query-interval
2884 int lib_interface_igmp_last_member_query_interval_modify(
2885 struct nb_cb_modify_args
*args
)
2887 struct interface
*ifp
;
2888 struct pim_interface
*pim_ifp
;
2889 int last_member_query_interval
;
2891 switch (args
->event
) {
2892 case NB_EV_VALIDATE
:
2897 ifp
= nb_running_get_entry(args
->dnode
, NULL
, true);
2898 pim_ifp
= ifp
->info
;
2899 last_member_query_interval
= yang_dnode_get_uint8(args
->dnode
,
2901 pim_ifp
->igmp_specific_query_max_response_time_dsec
=
2902 last_member_query_interval
;
2911 * XPath: /frr-interface:lib/interface/frr-igmp:igmp/robustness-variable
2913 int lib_interface_igmp_robustness_variable_modify(
2914 struct nb_cb_modify_args
*args
)
2916 struct interface
*ifp
;
2917 struct pim_interface
*pim_ifp
;
2918 int last_member_query_count
;
2920 switch (args
->event
) {
2921 case NB_EV_VALIDATE
:
2926 ifp
= nb_running_get_entry(args
->dnode
, NULL
, true);
2927 pim_ifp
= ifp
->info
;
2928 last_member_query_count
= yang_dnode_get_uint8(args
->dnode
,
2930 pim_ifp
->igmp_last_member_query_count
= last_member_query_count
;
2939 * XPath: /frr-interface:lib/interface/frr-igmp:igmp/address-family
2941 int lib_interface_igmp_address_family_create(struct nb_cb_create_args
*args
)
2943 switch (args
->event
) {
2944 case NB_EV_VALIDATE
:
2954 int lib_interface_igmp_address_family_destroy(struct nb_cb_destroy_args
*args
)
2956 switch (args
->event
) {
2957 case NB_EV_VALIDATE
:
2968 * XPath: /frr-interface:lib/interface/frr-igmp:igmp/address-family/static-group
2970 int lib_interface_igmp_address_family_static_group_create(
2971 struct nb_cb_create_args
*args
)
2973 struct interface
*ifp
;
2974 struct ipaddr source_addr
;
2975 struct ipaddr group_addr
;
2977 const char *ifp_name
;
2978 const struct lyd_node
*if_dnode
;
2980 switch (args
->event
) {
2981 case NB_EV_VALIDATE
:
2982 if_dnode
= yang_dnode_get_parent(args
->dnode
, "interface");
2983 if (!is_pim_interface(if_dnode
)) {
2984 ifp_name
= yang_dnode_get_string(if_dnode
, ".");
2985 snprintf(args
->errmsg
, args
->errmsg_len
,
2986 "multicast not enabled on interface %s",
2988 return NB_ERR_VALIDATION
;
2995 ifp
= nb_running_get_entry(args
->dnode
, NULL
, true);
2996 yang_dnode_get_ip(&source_addr
, args
->dnode
, "./source-addr");
2997 yang_dnode_get_ip(&group_addr
, args
->dnode
, "./group-addr");
2999 result
= pim_if_igmp_join_add(ifp
, group_addr
.ip
._v4_addr
,
3000 source_addr
.ip
._v4_addr
);
3002 snprintf(args
->errmsg
, args
->errmsg_len
,
3003 "Failure joining IGMP group");
3004 return NB_ERR_INCONSISTENCY
;
3011 int lib_interface_igmp_address_family_static_group_destroy(
3012 struct nb_cb_destroy_args
*args
)
3014 struct interface
*ifp
;
3015 struct ipaddr source_addr
;
3016 struct ipaddr group_addr
;
3019 switch (args
->event
) {
3020 case NB_EV_VALIDATE
:
3025 ifp
= nb_running_get_entry(args
->dnode
, NULL
, true);
3026 yang_dnode_get_ip(&source_addr
, args
->dnode
, "./source-addr");
3027 yang_dnode_get_ip(&group_addr
, args
->dnode
, "./group-addr");
3029 result
= pim_if_igmp_join_del(ifp
, group_addr
.ip
._v4_addr
,
3030 source_addr
.ip
._v4_addr
);
3033 char src_str
[INET_ADDRSTRLEN
];
3034 char grp_str
[INET_ADDRSTRLEN
];
3036 ipaddr2str(&source_addr
, src_str
, sizeof(src_str
));
3037 ipaddr2str(&group_addr
, grp_str
, sizeof(grp_str
));
3039 snprintf(args
->errmsg
, args
->errmsg_len
,
3040 "%% Failure leaving IGMP group %s %s on interface %s: %d",
3041 src_str
, grp_str
, ifp
->name
, result
);
3043 return NB_ERR_INCONSISTENCY
;