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 static void pim_if_membership_clear(struct interface
*ifp
)
34 struct pim_interface
*pim_ifp
;
39 if (PIM_IF_TEST_PIM(pim_ifp
->options
)
40 && PIM_IF_TEST_IGMP(pim_ifp
->options
)) {
44 pim_ifchannel_membership_clear(ifp
);
48 * When PIM is disabled on interface, IGMPv3 local membership
49 * information is not injected into PIM interface state.
51 * The function pim_if_membership_refresh() fetches all IGMPv3 local
52 * membership information into PIM. It is intented to be called
53 * whenever PIM is enabled on the interface in order to collect missed
54 * local membership information.
56 static void pim_if_membership_refresh(struct interface
*ifp
)
58 struct pim_interface
*pim_ifp
;
59 struct listnode
*sock_node
;
60 struct igmp_sock
*igmp
;
65 if (!PIM_IF_TEST_PIM(pim_ifp
->options
))
67 if (!PIM_IF_TEST_IGMP(pim_ifp
->options
))
71 * First clear off membership from all PIM (S,G) entries on the
75 pim_ifchannel_membership_clear(ifp
);
78 * Then restore PIM (S,G) membership from all IGMPv3 (S,G) entries on
82 /* scan igmp sockets */
83 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->igmp_socket_list
, sock_node
, igmp
)) {
84 struct listnode
*grpnode
;
85 struct igmp_group
*grp
;
87 /* scan igmp groups */
88 for (ALL_LIST_ELEMENTS_RO(igmp
->igmp_group_list
, grpnode
,
90 struct listnode
*srcnode
;
91 struct igmp_source
*src
;
93 /* scan group sources */
94 for (ALL_LIST_ELEMENTS_RO(grp
->group_source_list
,
97 if (IGMP_SOURCE_TEST_FORWARDING(
102 sizeof(struct prefix_sg
));
103 sg
.src
= src
->source_addr
;
104 sg
.grp
= grp
->group_addr
;
105 pim_ifchannel_local_membership_add(
106 ifp
, &sg
, false /*is_vxlan*/);
109 } /* scan group sources */
110 } /* scan igmp groups */
111 } /* scan igmp sockets */
114 * Finally delete every PIM (S,G) entry lacking all state info
117 pim_ifchannel_delete_on_noinfo(ifp
);
120 static int pim_cmd_interface_add(struct interface
*ifp
)
122 struct pim_interface
*pim_ifp
= ifp
->info
;
125 pim_ifp
= pim_if_new(ifp
, false, true, false, false);
127 PIM_IF_DO_PIM(pim_ifp
->options
);
129 pim_if_addr_add_all(ifp
);
130 pim_if_membership_refresh(ifp
);
132 pim_if_create_pimreg(pim_ifp
->pim
);
136 static int pim_cmd_interface_delete(struct interface
*ifp
)
138 struct pim_interface
*pim_ifp
= ifp
->info
;
143 PIM_IF_DONT_PIM(pim_ifp
->options
);
145 pim_if_membership_clear(ifp
);
148 * pim_sock_delete() removes all neighbors from
149 * pim_ifp->pim_neighbor_list.
151 pim_sock_delete(ifp
, "pim unconfigured on interface");
153 if (!PIM_IF_TEST_IGMP(pim_ifp
->options
)) {
154 pim_if_addr_del_all(ifp
);
161 static int interface_pim_use_src_cmd_worker(struct interface
*ifp
,
162 struct in_addr source_addr
,
163 char *errmsg
, size_t errmsg_len
)
168 result
= pim_update_source_set(ifp
, source_addr
);
173 case PIM_IFACE_NOT_FOUND
:
175 snprintf(errmsg
, errmsg_len
,
176 "Pim not enabled on this interface %s",
179 case PIM_UPDATE_SOURCE_DUP
:
181 snprintf(errmsg
, errmsg_len
, "Source already set");
185 snprintf(errmsg
, errmsg_len
, "Source set failed");
191 static int pim_cmd_spt_switchover(struct pim_instance
*pim
,
192 enum pim_spt_switchover spt
,
195 pim
->spt
.switchover
= spt
;
197 switch (pim
->spt
.switchover
) {
198 case PIM_SPT_IMMEDIATE
:
199 XFREE(MTYPE_PIM_PLIST_NAME
, pim
->spt
.plist
);
201 pim_upstream_add_lhr_star_pimreg(pim
);
203 case PIM_SPT_INFINITY
:
204 pim_upstream_remove_lhr_star_pimreg(pim
, plist
);
206 XFREE(MTYPE_PIM_PLIST_NAME
, pim
->spt
.plist
);
209 pim
->spt
.plist
= XSTRDUP(MTYPE_PIM_PLIST_NAME
, plist
);
216 static int pim_ssm_cmd_worker(struct pim_instance
*pim
, const char *plist
,
217 char *errmsg
, size_t errmsg_len
)
219 int result
= pim_ssm_range_set(pim
, pim
->vrf_id
, plist
);
222 if (result
== PIM_SSM_ERR_NONE
)
226 case PIM_SSM_ERR_NO_VRF
:
227 snprintf(errmsg
, errmsg_len
,
228 "VRF doesn't exist");
230 case PIM_SSM_ERR_DUP
:
231 snprintf(errmsg
, errmsg_len
,
235 snprintf(errmsg
, errmsg_len
,
236 "ssm range config failed");
242 static int ip_no_msdp_mesh_group_cmd_worker(struct pim_instance
*pim
,
244 char *errmsg
, size_t errmsg_len
)
246 enum pim_msdp_err result
;
248 result
= pim_msdp_mg_del(pim
, mg
);
251 case PIM_MSDP_ERR_NONE
:
253 case PIM_MSDP_ERR_NO_MG
:
254 snprintf(errmsg
, errmsg_len
,
255 "%% mesh-group does not exist");
258 snprintf(errmsg
, errmsg_len
,
259 "mesh-group source del failed");
262 return result
? NB_ERR
: NB_OK
;
265 static int ip_msdp_mesh_group_member_cmd_worker(struct pim_instance
*pim
,
267 struct in_addr mbr_ip
,
268 char *errmsg
, size_t errmsg_len
)
270 enum pim_msdp_err result
;
273 result
= pim_msdp_mg_mbr_add(pim
, mg
, mbr_ip
);
276 case PIM_MSDP_ERR_NONE
:
278 case PIM_MSDP_ERR_OOM
:
280 snprintf(errmsg
, errmsg_len
,
283 case PIM_MSDP_ERR_MG_MBR_EXISTS
:
285 snprintf(errmsg
, errmsg_len
,
286 "%% mesh-group member exists");
288 case PIM_MSDP_ERR_MAX_MESH_GROUPS
:
290 snprintf(errmsg
, errmsg_len
,
291 "%% Only one mesh-group allowed currently");
295 snprintf(errmsg
, errmsg_len
,
296 "%% member add failed");
302 static int ip_no_msdp_mesh_group_member_cmd_worker(struct pim_instance
*pim
,
304 struct in_addr mbr_ip
,
308 enum pim_msdp_err result
;
310 result
= pim_msdp_mg_mbr_del(pim
, mg
, mbr_ip
);
313 case PIM_MSDP_ERR_NONE
:
315 case PIM_MSDP_ERR_NO_MG
:
316 snprintf(errmsg
, errmsg_len
,
317 "%% mesh-group does not exist");
319 case PIM_MSDP_ERR_NO_MG_MBR
:
320 snprintf(errmsg
, errmsg_len
,
321 "%% mesh-group member does not exist");
324 snprintf(errmsg
, errmsg_len
,
325 "%% mesh-group member del failed");
328 return result
? NB_ERR
: NB_OK
;
331 static int ip_msdp_mesh_group_source_cmd_worker(struct pim_instance
*pim
,
333 struct in_addr src_ip
,
334 char *errmsg
, size_t errmsg_len
)
336 enum pim_msdp_err result
;
338 result
= pim_msdp_mg_src_add(pim
, mg
, src_ip
);
341 case PIM_MSDP_ERR_NONE
:
343 case PIM_MSDP_ERR_OOM
:
344 snprintf(errmsg
, errmsg_len
,
347 case PIM_MSDP_ERR_MAX_MESH_GROUPS
:
348 snprintf(errmsg
, errmsg_len
,
349 "%% Only one mesh-group allowed currently");
352 snprintf(errmsg
, errmsg_len
,
353 "%% source add failed");
356 return result
? NB_ERR
: NB_OK
;
359 static int ip_no_msdp_mesh_group_source_cmd_worker(struct pim_instance
*pim
,
364 enum pim_msdp_err result
;
366 result
= pim_msdp_mg_src_del(pim
, mg
);
369 case PIM_MSDP_ERR_NONE
:
371 case PIM_MSDP_ERR_NO_MG
:
372 snprintf(errmsg
, errmsg_len
,
373 "%% mesh-group does not exist");
376 snprintf(errmsg
, errmsg_len
,
377 "%% mesh-group source del failed");
380 return result
? NB_ERR
: NB_OK
;
383 static int ip_msdp_peer_cmd_worker(struct pim_instance
*pim
,
384 struct in_addr peer_addr
,
385 struct in_addr local_addr
,
386 char *errmsg
, size_t errmsg_len
)
388 enum pim_msdp_err result
;
391 result
= pim_msdp_peer_add(pim
, peer_addr
, local_addr
, "default",
394 case PIM_MSDP_ERR_NONE
:
396 case PIM_MSDP_ERR_OOM
:
398 snprintf(errmsg
, errmsg_len
,
401 case PIM_MSDP_ERR_PEER_EXISTS
:
403 snprintf(errmsg
, errmsg_len
,
406 case PIM_MSDP_ERR_MAX_MESH_GROUPS
:
408 snprintf(errmsg
, errmsg_len
,
409 "%% Only one mesh-group allowed currently");
413 snprintf(errmsg
, errmsg_len
,
414 "%% peer add failed");
420 static int ip_no_msdp_peer_cmd_worker(struct pim_instance
*pim
,
421 struct in_addr peer_addr
,
422 char *errmsg
, size_t errmsg_len
)
424 enum pim_msdp_err result
;
426 result
= pim_msdp_peer_del(pim
, peer_addr
);
428 case PIM_MSDP_ERR_NONE
:
430 case PIM_MSDP_ERR_NO_PEER
:
431 snprintf(errmsg
, errmsg_len
,
432 "%% Peer does not exist");
435 snprintf(errmsg
, errmsg_len
,
436 "%% peer del failed");
439 return result
? NB_ERR
: NB_OK
;
442 static int pim_rp_cmd_worker(struct pim_instance
*pim
,
443 struct in_addr rp_addr
,
444 struct prefix group
, const char *plist
,
445 char *errmsg
, size_t errmsg_len
)
447 char rp_str
[INET_ADDRSTRLEN
];
450 inet_ntop(AF_INET
, &rp_addr
, rp_str
, sizeof(rp_str
));
452 result
= pim_rp_new(pim
, rp_addr
, group
, plist
, RP_SRC_STATIC
);
454 if (result
== PIM_RP_NO_PATH
) {
455 snprintf(errmsg
, errmsg_len
,
456 "No Path to RP address specified: %s", rp_str
);
457 return NB_ERR_INCONSISTENCY
;
460 if (result
== PIM_GROUP_OVERLAP
) {
461 snprintf(errmsg
, errmsg_len
,
462 "Group range specified cannot exact match another");
463 return NB_ERR_INCONSISTENCY
;
466 if (result
== PIM_GROUP_PFXLIST_OVERLAP
) {
467 snprintf(errmsg
, errmsg_len
,
468 "This group is already covered by a RP prefix-list");
469 return NB_ERR_INCONSISTENCY
;
472 if (result
== PIM_RP_PFXLIST_IN_USE
) {
473 snprintf(errmsg
, errmsg_len
,
474 "The same prefix-list cannot be applied to multiple RPs");
475 return NB_ERR_INCONSISTENCY
;
481 static int pim_no_rp_cmd_worker(struct pim_instance
*pim
,
482 struct in_addr rp_addr
, struct prefix group
,
484 char *errmsg
, size_t errmsg_len
)
486 char rp_str
[INET_ADDRSTRLEN
];
487 char group_str
[PREFIX2STR_BUFFER
];
490 inet_ntop(AF_INET
, &rp_addr
, rp_str
, sizeof(rp_str
));
491 prefix2str(&group
, group_str
, sizeof(group_str
));
493 result
= pim_rp_del(pim
, rp_addr
, group
, plist
, RP_SRC_STATIC
);
495 if (result
== PIM_GROUP_BAD_ADDRESS
) {
496 snprintf(errmsg
, errmsg_len
,
497 "Bad group address specified: %s", group_str
);
498 return NB_ERR_INCONSISTENCY
;
501 if (result
== PIM_RP_BAD_ADDRESS
) {
502 snprintf(errmsg
, errmsg_len
,
503 "Bad RP address specified: %s", rp_str
);
504 return NB_ERR_INCONSISTENCY
;
507 if (result
== PIM_RP_NOT_FOUND
) {
508 snprintf(errmsg
, errmsg_len
,
509 "Unable to find specified RP");
510 return NB_ERR_INCONSISTENCY
;
516 static bool is_pim_interface(const struct lyd_node
*dnode
)
518 char if_xpath
[XPATH_MAXLEN
];
519 const struct lyd_node
*pim_enable_dnode
;
520 const struct lyd_node
*igmp_enable_dnode
;
522 yang_dnode_get_path(dnode
, if_xpath
, sizeof(if_xpath
));
523 pim_enable_dnode
= yang_dnode_get(dnode
, "%s/frr-pim:pim/pim-enable",
525 igmp_enable_dnode
= yang_dnode_get(dnode
,
526 "%s/frr-igmp:igmp/igmp-enable",
529 if (((pim_enable_dnode
) &&
530 (yang_dnode_get_bool(pim_enable_dnode
, "."))) ||
531 ((igmp_enable_dnode
) &&
532 (yang_dnode_get_bool(igmp_enable_dnode
, "."))))
538 static int pim_cmd_igmp_start(struct interface
*ifp
)
540 struct pim_interface
*pim_ifp
;
541 uint8_t need_startup
= 0;
546 (void)pim_if_new(ifp
, true, false, false, false);
549 if (!PIM_IF_TEST_IGMP(pim_ifp
->options
)) {
550 PIM_IF_DO_IGMP(pim_ifp
->options
);
555 /* 'ip igmp' executed multiple times, with need_startup
556 * avoid multiple if add all and membership refresh
559 pim_if_addr_add_all(ifp
);
560 pim_if_membership_refresh(ifp
);
567 * CLI reconfiguration affects the interface level (struct pim_interface).
568 * This function propagates the reconfiguration to every active socket
569 * for that interface.
571 static void igmp_sock_query_interval_reconfig(struct igmp_sock
*igmp
)
573 struct interface
*ifp
;
574 struct pim_interface
*pim_ifp
;
578 /* other querier present? */
580 if (igmp
->t_other_querier_timer
)
583 /* this is the querier */
585 zassert(igmp
->interface
);
586 zassert(igmp
->interface
->info
);
588 ifp
= igmp
->interface
;
591 if (PIM_DEBUG_IGMP_TRACE
) {
592 char ifaddr_str
[INET_ADDRSTRLEN
];
594 pim_inet4_dump("<ifaddr?>", igmp
->ifaddr
, ifaddr_str
,
596 zlog_debug("%s: Querier %s on %s reconfig query_interval=%d",
597 __func__
, ifaddr_str
, ifp
->name
,
598 pim_ifp
->igmp_default_query_interval
);
602 * igmp_startup_mode_on() will reset QQI:
604 * igmp->querier_query_interval = pim_ifp->igmp_default_query_interval;
606 igmp_startup_mode_on(igmp
);
609 static void igmp_sock_query_reschedule(struct igmp_sock
*igmp
)
611 if (igmp
->mtrace_only
)
614 if (igmp
->t_igmp_query_timer
) {
615 /* other querier present */
616 zassert(igmp
->t_igmp_query_timer
);
617 zassert(!igmp
->t_other_querier_timer
);
619 pim_igmp_general_query_off(igmp
);
620 pim_igmp_general_query_on(igmp
);
622 zassert(igmp
->t_igmp_query_timer
);
623 zassert(!igmp
->t_other_querier_timer
);
625 /* this is the querier */
627 zassert(!igmp
->t_igmp_query_timer
);
628 zassert(igmp
->t_other_querier_timer
);
630 pim_igmp_other_querier_timer_off(igmp
);
631 pim_igmp_other_querier_timer_on(igmp
);
633 zassert(!igmp
->t_igmp_query_timer
);
634 zassert(igmp
->t_other_querier_timer
);
638 static void change_query_interval(struct pim_interface
*pim_ifp
,
641 struct listnode
*sock_node
;
642 struct igmp_sock
*igmp
;
644 pim_ifp
->igmp_default_query_interval
= query_interval
;
646 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->igmp_socket_list
, sock_node
, igmp
)) {
647 igmp_sock_query_interval_reconfig(igmp
);
648 igmp_sock_query_reschedule(igmp
);
652 static void change_query_max_response_time(struct pim_interface
*pim_ifp
,
653 int query_max_response_time_dsec
)
655 struct listnode
*sock_node
;
656 struct igmp_sock
*igmp
;
658 pim_ifp
->igmp_query_max_response_time_dsec
=
659 query_max_response_time_dsec
;
662 * Below we modify socket/group/source timers in order to quickly
663 * reflect the change. Otherwise, those timers would args->eventually
667 /* scan all sockets */
668 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->igmp_socket_list
, sock_node
, igmp
)) {
669 struct listnode
*grp_node
;
670 struct igmp_group
*grp
;
672 /* reschedule socket general query */
673 igmp_sock_query_reschedule(igmp
);
675 /* scan socket groups */
676 for (ALL_LIST_ELEMENTS_RO(igmp
->igmp_group_list
, grp_node
,
678 struct listnode
*src_node
;
679 struct igmp_source
*src
;
681 /* reset group timers for groups in EXCLUDE mode */
682 if (grp
->group_filtermode_isexcl
)
683 igmp_group_reset_gmi(grp
);
685 /* scan group sources */
686 for (ALL_LIST_ELEMENTS_RO(grp
->group_source_list
,
689 /* reset source timers for sources with running
692 if (src
->t_source_timer
)
693 igmp_source_reset_gmi(igmp
, grp
, src
);
699 int routing_control_plane_protocols_name_validate(
700 struct nb_cb_create_args
*args
)
704 name
= yang_dnode_get_string(args
->dnode
, "./name");
705 if (!strmatch(name
, "pim")) {
706 snprintf(args
->errmsg
, args
->errmsg_len
,
707 "pim supports only one instance with name pimd");
708 return NB_ERR_VALIDATION
;
714 * XPath: /frr-pim:pim/packets
716 int pim_packets_modify(struct nb_cb_modify_args
*args
)
718 switch (args
->event
) {
724 router
->packet_process
= yang_dnode_get_uint8(args
->dnode
,
733 * XPath: /frr-pim:pim/join-prune-interval
735 int pim_join_prune_interval_modify(struct nb_cb_modify_args
*args
)
737 switch (args
->event
) {
743 router
->t_periodic
= yang_dnode_get_uint16(args
->dnode
, NULL
);
751 * XPath: /frr-pim:pim/register-suppress-time
753 int pim_register_suppress_time_modify(struct nb_cb_modify_args
*args
)
756 struct pim_instance
*pim
;
758 switch (args
->event
) {
764 vrf
= nb_running_get_entry(args
->dnode
, NULL
, true);
766 pim
->keep_alive_time
= yang_dnode_get_uint16(args
->dnode
, NULL
);
774 * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/ecmp
776 int routing_control_plane_protocols_control_plane_protocol_pim_ecmp_modify(
777 struct nb_cb_modify_args
*args
)
780 struct pim_instance
*pim
;
782 switch (args
->event
) {
788 vrf
= nb_running_get_entry(args
->dnode
, NULL
, true);
790 pim
->ecmp_enable
= yang_dnode_get_bool(args
->dnode
, NULL
);
797 * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/ecmp-rebalance
799 int routing_control_plane_protocols_control_plane_protocol_pim_ecmp_rebalance_modify(
800 struct nb_cb_modify_args
*args
)
803 struct pim_instance
*pim
;
805 switch (args
->event
) {
811 vrf
= nb_running_get_entry(args
->dnode
, NULL
, true);
813 pim
->ecmp_rebalance_enable
=
814 yang_dnode_get_bool(args
->dnode
, NULL
);
821 * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/keep-alive-timer
823 int routing_control_plane_protocols_control_plane_protocol_pim_keep_alive_timer_modify(
824 struct nb_cb_modify_args
*args
)
827 struct pim_instance
*pim
;
829 switch (args
->event
) {
835 vrf
= nb_running_get_entry(args
->dnode
, NULL
, true);
837 pim
->keep_alive_time
= yang_dnode_get_uint16(args
->dnode
, NULL
);
845 * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/rp-keep-alive-timer
847 int routing_control_plane_protocols_control_plane_protocol_pim_rp_keep_alive_timer_modify(
848 struct nb_cb_modify_args
*args
)
851 struct pim_instance
*pim
;
853 switch (args
->event
) {
859 vrf
= nb_running_get_entry(args
->dnode
, NULL
, true);
861 pim
->rp_keep_alive_time
= yang_dnode_get_uint16(args
->dnode
,
870 * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family
872 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_create(
873 struct nb_cb_create_args
*args
)
875 switch (args
->event
) {
886 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_destroy(
887 struct nb_cb_destroy_args
*args
)
889 switch (args
->event
) {
894 /* TODO: implement me. */
902 * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/send-v6-secondary
904 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_send_v6_secondary_modify(
905 struct nb_cb_modify_args
*args
)
908 struct pim_instance
*pim
;
910 switch (args
->event
) {
916 vrf
= nb_running_get_entry(args
->dnode
, NULL
, true);
918 pim
->send_v6_secondary
= yang_dnode_get_bool(args
->dnode
, NULL
);
925 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_send_v6_secondary_destroy(
926 struct nb_cb_destroy_args
*args
)
928 switch (args
->event
) {
941 * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/spt-switchover
943 void routing_control_plane_protocols_control_plane_protocol_pim_address_family_spt_switchover_apply_finish(
944 struct nb_cb_apply_finish_args
*args
)
947 struct pim_instance
*pim
;
948 int spt_switch_action
;
949 const char *prefix_list
= NULL
;
951 vrf
= nb_running_get_entry(args
->dnode
, NULL
, true);
953 spt_switch_action
= yang_dnode_get_enum(args
->dnode
, "./spt-action");
955 switch (spt_switch_action
) {
956 case PIM_SPT_INFINITY
:
957 if (yang_dnode_exists(args
->dnode
,
958 "./spt-infinity-prefix-list"))
959 prefix_list
= yang_dnode_get_string(
960 args
->dnode
, "./spt-infinity-prefix-list");
962 pim_cmd_spt_switchover(pim
, PIM_SPT_INFINITY
,
965 case PIM_SPT_IMMEDIATE
:
966 pim_cmd_spt_switchover(pim
, PIM_SPT_IMMEDIATE
, NULL
);
971 * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/spt-switchover/spt-action
973 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_spt_switchover_spt_action_modify(
974 struct nb_cb_modify_args
*args
)
976 switch (args
->event
) {
988 * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/spt-switchover/spt-infinity-prefix-list
990 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_spt_switchover_spt_infinity_prefix_list_modify(
991 struct nb_cb_modify_args
*args
)
993 switch (args
->event
) {
1004 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_spt_switchover_spt_infinity_prefix_list_destroy(
1005 struct nb_cb_destroy_args
*args
)
1007 switch (args
->event
) {
1008 case NB_EV_VALIDATE
:
1019 * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/ssm-prefix-list
1021 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_ssm_prefix_list_modify(
1022 struct nb_cb_modify_args
*args
)
1025 struct pim_instance
*pim
;
1026 const char *plist_name
;
1029 switch (args
->event
) {
1030 case NB_EV_VALIDATE
:
1035 vrf
= nb_running_get_entry(args
->dnode
, NULL
, true);
1037 plist_name
= yang_dnode_get_string(args
->dnode
, NULL
);
1038 result
= pim_ssm_cmd_worker(pim
, plist_name
, args
->errmsg
,
1042 return NB_ERR_INCONSISTENCY
;
1050 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_ssm_prefix_list_destroy(
1051 struct nb_cb_destroy_args
*args
)
1054 struct pim_instance
*pim
;
1057 switch (args
->event
) {
1058 case NB_EV_VALIDATE
:
1063 vrf
= nb_running_get_entry(args
->dnode
, NULL
, true);
1065 result
= pim_ssm_cmd_worker(pim
, NULL
, args
->errmsg
,
1069 return NB_ERR_INCONSISTENCY
;
1078 * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/ssm-pingd-source-ip
1080 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_ssm_pingd_source_ip_create(
1081 struct nb_cb_create_args
*args
)
1084 struct pim_instance
*pim
;
1086 struct ipaddr source_addr
;
1088 switch (args
->event
) {
1089 case NB_EV_VALIDATE
:
1094 vrf
= nb_running_get_entry(args
->dnode
, NULL
, true);
1096 yang_dnode_get_ip(&source_addr
, args
->dnode
, NULL
);
1097 result
= pim_ssmpingd_start(pim
, source_addr
.ip
._v4_addr
);
1099 char source_str
[INET_ADDRSTRLEN
];
1101 ipaddr2str(&source_addr
, source_str
,
1102 sizeof(source_str
));
1103 snprintf(args
->errmsg
, args
->errmsg_len
,
1104 "%% Failure starting ssmpingd for source %s: %d",
1105 source_str
, result
);
1106 return NB_ERR_INCONSISTENCY
;
1113 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_ssm_pingd_source_ip_destroy(
1114 struct nb_cb_destroy_args
*args
)
1117 struct pim_instance
*pim
;
1119 struct ipaddr source_addr
;
1121 switch (args
->event
) {
1122 case NB_EV_VALIDATE
:
1127 vrf
= nb_running_get_entry(args
->dnode
, NULL
, true);
1129 yang_dnode_get_ip(&source_addr
, args
->dnode
, NULL
);
1130 result
= pim_ssmpingd_stop(pim
, source_addr
.ip
._v4_addr
);
1132 char source_str
[INET_ADDRSTRLEN
];
1134 ipaddr2str(&source_addr
, source_str
,
1135 sizeof(source_str
));
1136 snprintf(args
->errmsg
, args
->errmsg_len
,
1137 "%% Failure stopping ssmpingd for source %s: %d",
1138 source_str
, result
);
1139 return NB_ERR_INCONSISTENCY
;
1149 * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp-mesh-group
1151 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_mesh_group_create(
1152 struct nb_cb_create_args
*args
)
1154 switch (args
->event
) {
1155 case NB_EV_VALIDATE
:
1165 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_mesh_group_destroy(
1166 struct nb_cb_destroy_args
*args
)
1169 struct pim_instance
*pim
;
1170 const char *mesh_group_name
;
1173 switch (args
->event
) {
1174 case NB_EV_VALIDATE
:
1179 vrf
= nb_running_get_entry(args
->dnode
, NULL
, true);
1181 mesh_group_name
= yang_dnode_get_string(args
->dnode
, ".");
1183 result
= ip_no_msdp_mesh_group_cmd_worker(pim
, mesh_group_name
,
1187 if (result
!= PIM_MSDP_ERR_NONE
)
1188 return NB_ERR_INCONSISTENCY
;
1197 * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp-mesh-group/mesh-group-name
1199 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_mesh_group_mesh_group_name_modify(
1200 struct nb_cb_modify_args
*args
)
1202 const char *mesh_group_name
;
1203 const char *mesh_group_name_old
;
1204 char xpath
[XPATH_MAXLEN
];
1206 switch (args
->event
) {
1207 case NB_EV_VALIDATE
:
1208 mesh_group_name
= yang_dnode_get_string(args
->dnode
, ".");
1209 yang_dnode_get_path(args
->dnode
, xpath
, sizeof(xpath
));
1211 if (yang_dnode_exists(running_config
->dnode
, xpath
) == false)
1214 mesh_group_name_old
= yang_dnode_get_string(
1215 running_config
->dnode
,
1217 if (strcmp(mesh_group_name
, mesh_group_name_old
)) {
1218 /* currently only one mesh-group can exist at a time */
1219 snprintf(args
->errmsg
, args
->errmsg_len
,
1220 "Only one mesh-group allowed currently");
1221 return NB_ERR_VALIDATION
;
1233 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_mesh_group_mesh_group_name_destroy(
1234 struct nb_cb_destroy_args
*args
)
1236 switch (args
->event
) {
1237 case NB_EV_VALIDATE
:
1248 * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp-mesh-group/member-ip
1250 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_mesh_group_member_ip_create(
1251 struct nb_cb_create_args
*args
)
1254 struct pim_instance
*pim
;
1255 const char *mesh_group_name
;
1256 struct ipaddr mbr_ip
;
1257 enum pim_msdp_err result
;
1259 switch (args
->event
) {
1260 case NB_EV_VALIDATE
:
1265 vrf
= nb_running_get_entry(args
->dnode
, NULL
, true);
1267 mesh_group_name
= yang_dnode_get_string(args
->dnode
,
1268 "../mesh-group-name");
1269 yang_dnode_get_ip(&mbr_ip
, args
->dnode
, NULL
);
1271 result
= ip_msdp_mesh_group_member_cmd_worker(
1272 pim
, mesh_group_name
, mbr_ip
.ip
._v4_addr
,
1273 args
->errmsg
, args
->errmsg_len
);
1275 if (result
!= PIM_MSDP_ERR_NONE
)
1276 return NB_ERR_INCONSISTENCY
;
1284 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_mesh_group_member_ip_destroy(
1285 struct nb_cb_destroy_args
*args
)
1288 struct pim_instance
*pim
;
1289 const char *mesh_group_name
;
1290 struct ipaddr mbr_ip
;
1291 enum pim_msdp_err result
;
1293 switch (args
->event
) {
1294 case NB_EV_VALIDATE
:
1299 vrf
= nb_running_get_entry(args
->dnode
, NULL
, true);
1301 mesh_group_name
= yang_dnode_get_string(args
->dnode
,
1302 "../mesh-group-name");
1303 yang_dnode_get_ip(&mbr_ip
, args
->dnode
, NULL
);
1305 result
= ip_no_msdp_mesh_group_member_cmd_worker(
1306 pim
, mesh_group_name
, mbr_ip
.ip
._v4_addr
,
1307 args
->errmsg
, args
->errmsg_len
);
1309 if (result
!= PIM_MSDP_ERR_NONE
)
1310 return NB_ERR_INCONSISTENCY
;
1319 * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp-mesh-group/source-ip
1321 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_mesh_group_source_ip_modify(
1322 struct nb_cb_modify_args
*args
)
1325 struct pim_instance
*pim
;
1326 const char *mesh_group_name
;
1327 struct ipaddr src_ip
;
1328 enum pim_msdp_err result
;
1330 switch (args
->event
) {
1331 case NB_EV_VALIDATE
:
1336 vrf
= nb_running_get_entry(args
->dnode
, NULL
, true);
1338 mesh_group_name
= yang_dnode_get_string(args
->dnode
,
1339 "../mesh-group-name");
1340 yang_dnode_get_ip(&src_ip
, args
->dnode
, NULL
);
1342 result
= ip_msdp_mesh_group_source_cmd_worker(
1343 pim
, mesh_group_name
, src_ip
.ip
._v4_addr
,
1344 args
->errmsg
, args
->errmsg_len
);
1346 if (result
!= PIM_MSDP_ERR_NONE
)
1347 return NB_ERR_INCONSISTENCY
;
1354 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_mesh_group_source_ip_destroy(
1355 struct nb_cb_destroy_args
*args
)
1358 struct pim_instance
*pim
;
1359 const char *mesh_group_name
;
1360 enum pim_msdp_err result
;
1362 switch (args
->event
) {
1363 case NB_EV_VALIDATE
:
1368 vrf
= nb_running_get_entry(args
->dnode
, NULL
, true);
1370 mesh_group_name
= yang_dnode_get_string(args
->dnode
,
1371 "../mesh-group-name");
1373 result
= ip_no_msdp_mesh_group_source_cmd_worker(
1374 pim
, mesh_group_name
, args
->errmsg
,
1377 if (result
!= PIM_MSDP_ERR_NONE
)
1378 return NB_ERR_INCONSISTENCY
;
1386 * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp-peer
1388 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_peer_create(
1389 struct nb_cb_create_args
*args
)
1391 switch (args
->event
) {
1392 case NB_EV_VALIDATE
:
1402 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_peer_destroy(
1403 struct nb_cb_destroy_args
*args
)
1406 struct pim_instance
*pim
;
1407 struct ipaddr peer_ip
;
1410 switch (args
->event
) {
1411 case NB_EV_VALIDATE
:
1416 vrf
= nb_running_get_entry(args
->dnode
, NULL
, true);
1418 yang_dnode_get_ip(&peer_ip
, args
->dnode
, "./peer-ip");
1419 result
= ip_no_msdp_peer_cmd_worker(pim
, peer_ip
.ip
._v4_addr
,
1424 return NB_ERR_INCONSISTENCY
;
1433 * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp-peer/source-ip
1435 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_peer_source_ip_modify(
1436 struct nb_cb_modify_args
*args
)
1440 struct pim_instance
*pim
;
1441 struct ipaddr peer_ip
;
1442 struct ipaddr source_ip
;
1443 const struct lyd_node
*mesh_group_name_dnode
;
1444 const char *mesh_group_name
;
1446 switch (args
->event
) {
1447 case NB_EV_VALIDATE
:
1448 mesh_group_name_dnode
=
1449 yang_dnode_get(args
->dnode
,
1450 "../../msdp-mesh-group/mesh-group-name");
1451 if (mesh_group_name_dnode
) {
1453 yang_dnode_get_string(mesh_group_name_dnode
,
1455 if (strcmp(mesh_group_name
, "default")) {
1456 /* currently only one mesh-group can exist at a
1459 snprintf(args
->errmsg
, args
->errmsg_len
,
1460 "%% Only one mesh-group allowed currently");
1461 return NB_ERR_VALIDATION
;
1469 vrf
= nb_running_get_entry(args
->dnode
, NULL
, true);
1471 yang_dnode_get_ip(&peer_ip
, args
->dnode
, "../peer-ip");
1472 yang_dnode_get_ip(&source_ip
, args
->dnode
, NULL
);
1474 result
= ip_msdp_peer_cmd_worker(pim
, peer_ip
.ip
._v4_addr
,
1475 source_ip
.ip
._v4_addr
,
1480 return NB_ERR_INCONSISTENCY
;
1488 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_peer_source_ip_destroy(
1489 struct nb_cb_destroy_args
*args
)
1491 switch (args
->event
) {
1492 case NB_EV_VALIDATE
:
1503 * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/mlag
1505 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_create(
1506 struct nb_cb_create_args
*args
)
1508 switch (args
->event
) {
1509 case NB_EV_VALIDATE
:
1519 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_destroy(
1520 struct nb_cb_destroy_args
*args
)
1522 struct in_addr addr
;
1524 switch (args
->event
) {
1525 case NB_EV_VALIDATE
:
1531 pim_vxlan_mlag_update(true/*mlag_enable*/,
1532 false/*peer_state*/, MLAG_ROLE_NONE
,
1533 NULL
/*peerlink*/, &addr
);
1541 * /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/mlag
1543 void routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_apply_finish(
1544 struct nb_cb_apply_finish_args
*args
)
1549 struct interface
*ifp
;
1550 struct ipaddr reg_addr
;
1552 ifname
= yang_dnode_get_string(args
->dnode
, "./peerlink-rif");
1553 ifp
= if_lookup_by_name(ifname
, VRF_DEFAULT
);
1555 snprintf(args
->errmsg
, args
->errmsg_len
,
1556 "No such interface name %s", ifname
);
1559 role
= yang_dnode_get_enum(args
->dnode
, "./my-role");
1560 peer_state
= yang_dnode_get_bool(args
->dnode
, "./peer-state");
1561 yang_dnode_get_ip(®_addr
, args
->dnode
, "./reg-address");
1563 pim_vxlan_mlag_update(true, peer_state
, role
, ifp
,
1564 ®_addr
.ip
._v4_addr
);
1569 * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/mlag/peerlink-rif
1571 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_peerlink_rif_modify(
1572 struct nb_cb_modify_args
*args
)
1574 switch (args
->event
) {
1575 case NB_EV_VALIDATE
:
1585 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_peerlink_rif_destroy(
1586 struct nb_cb_destroy_args
*args
)
1588 switch (args
->event
) {
1589 case NB_EV_VALIDATE
:
1600 * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/mlag/reg-address
1602 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_reg_address_modify(
1603 struct nb_cb_modify_args
*args
)
1605 switch (args
->event
) {
1606 case NB_EV_VALIDATE
:
1616 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_reg_address_destroy(
1617 struct nb_cb_destroy_args
*args
)
1619 switch (args
->event
) {
1620 case NB_EV_VALIDATE
:
1631 * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/mlag/my-role
1633 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_my_role_modify(
1634 struct nb_cb_modify_args
*args
)
1636 switch (args
->event
) {
1637 case NB_EV_VALIDATE
:
1648 * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/mlag/peer-state
1650 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_peer_state_modify(
1651 struct nb_cb_modify_args
*args
)
1653 switch (args
->event
) {
1654 case NB_EV_VALIDATE
:
1665 * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/register-accept-list
1667 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_register_accept_list_modify(
1668 struct nb_cb_modify_args
*args
)
1671 struct pim_instance
*pim
;
1674 switch (args
->event
) {
1675 case NB_EV_VALIDATE
:
1680 vrf
= nb_running_get_entry(args
->dnode
, NULL
, true);
1682 plist
= yang_dnode_get_string(args
->dnode
, NULL
);
1684 XFREE(MTYPE_PIM_PLIST_NAME
, pim
->register_plist
);
1685 pim
->register_plist
= XSTRDUP(MTYPE_PIM_PLIST_NAME
, plist
);
1693 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_register_accept_list_destroy(
1694 struct nb_cb_destroy_args
*args
)
1697 struct pim_instance
*pim
;
1699 switch (args
->event
) {
1700 case NB_EV_VALIDATE
:
1705 vrf
= nb_running_get_entry(args
->dnode
, NULL
, true);
1708 XFREE(MTYPE_PIM_PLIST_NAME
, pim
->register_plist
);
1716 * XPath: /frr-interface:lib/interface/frr-pim:pim
1718 int lib_interface_pim_create(struct nb_cb_create_args
*args
)
1720 switch (args
->event
) {
1721 case NB_EV_VALIDATE
:
1731 int lib_interface_pim_destroy(struct nb_cb_destroy_args
*args
)
1733 struct interface
*ifp
;
1734 struct pim_interface
*pim_ifp
;
1736 switch (args
->event
) {
1737 case NB_EV_VALIDATE
:
1742 ifp
= nb_running_get_entry(args
->dnode
, NULL
, true);
1743 pim_ifp
= ifp
->info
;
1747 if (!pim_cmd_interface_delete(ifp
)) {
1748 snprintf(args
->errmsg
, args
->errmsg_len
,
1749 "Unable to delete interface information %s",
1751 return NB_ERR_INCONSISTENCY
;
1759 * XPath: /frr-interface:lib/interface/frr-pim:pim/pim-enable
1761 int lib_interface_pim_pim_enable_modify(struct nb_cb_modify_args
*args
)
1763 struct interface
*ifp
;
1764 struct pim_interface
*pim_ifp
;
1766 const struct lyd_node
*if_dnode
;
1768 switch (args
->event
) {
1769 case NB_EV_VALIDATE
:
1770 if_dnode
= yang_dnode_get_parent(args
->dnode
, "interface");
1772 yang_get_list_elements_count(if_dnode
);
1774 /* Limiting mcast interfaces to number of VIFs */
1775 if (mcast_if_count
== MAXVIFS
) {
1776 snprintf(args
->errmsg
, args
->errmsg_len
,
1777 "Max multicast interfaces(%d) reached.",
1779 return NB_ERR_VALIDATION
;
1786 ifp
= nb_running_get_entry(args
->dnode
, NULL
, true);
1788 if (yang_dnode_get_bool(args
->dnode
, NULL
)) {
1789 if (!pim_cmd_interface_add(ifp
)) {
1790 snprintf(args
->errmsg
, args
->errmsg_len
,
1791 "Could not enable PIM SM on interface %s",
1793 return NB_ERR_INCONSISTENCY
;
1796 pim_ifp
= ifp
->info
;
1798 return NB_ERR_INCONSISTENCY
;
1800 if (!pim_cmd_interface_delete(ifp
)) {
1801 snprintf(args
->errmsg
, args
->errmsg_len
,
1802 "Unable to delete interface information");
1803 return NB_ERR_INCONSISTENCY
;
1813 * XPath: /frr-interface:lib/interface/frr-pim:pim/hello-interval
1815 int lib_interface_pim_hello_interval_modify(struct nb_cb_modify_args
*args
)
1817 struct interface
*ifp
;
1818 struct pim_interface
*pim_ifp
;
1820 switch (args
->event
) {
1821 case NB_EV_VALIDATE
:
1826 ifp
= nb_running_get_entry(args
->dnode
, NULL
, true);
1827 pim_ifp
= ifp
->info
;
1828 pim_ifp
->pim_hello_period
=
1829 yang_dnode_get_uint8(args
->dnode
, NULL
);
1837 * XPath: /frr-interface:lib/interface/frr-pim:pim/hello-holdtime
1839 int lib_interface_pim_hello_holdtime_modify(struct nb_cb_modify_args
*args
)
1841 struct interface
*ifp
;
1842 struct pim_interface
*pim_ifp
;
1844 switch (args
->event
) {
1845 case NB_EV_VALIDATE
:
1850 ifp
= nb_running_get_entry(args
->dnode
, NULL
, true);
1851 pim_ifp
= ifp
->info
;
1852 pim_ifp
->pim_default_holdtime
=
1853 yang_dnode_get_uint8(args
->dnode
, NULL
);
1861 int lib_interface_pim_hello_holdtime_destroy(struct nb_cb_destroy_args
*args
)
1863 struct interface
*ifp
;
1864 struct pim_interface
*pim_ifp
;
1866 switch (args
->event
) {
1867 case NB_EV_VALIDATE
:
1872 ifp
= nb_running_get_entry(args
->dnode
, NULL
, true);
1873 pim_ifp
= ifp
->info
;
1874 pim_ifp
->pim_default_holdtime
= -1;
1881 * XPath: /frr-interface:lib/interface/frr-pim:pim/bfd
1883 int lib_interface_pim_bfd_create(struct nb_cb_create_args
*args
)
1885 switch (args
->event
) {
1886 case NB_EV_VALIDATE
:
1896 int lib_interface_pim_bfd_destroy(struct nb_cb_destroy_args
*args
)
1898 struct interface
*ifp
;
1899 struct pim_interface
*pim_ifp
;
1900 const struct lyd_node
*if_dnode
;
1902 switch (args
->event
) {
1903 case NB_EV_VALIDATE
:
1904 if_dnode
= yang_dnode_get_parent(args
->dnode
, "interface");
1905 if (!is_pim_interface(if_dnode
)) {
1906 snprintf(args
->errmsg
, args
->errmsg_len
,
1907 "Pim not enabled on this interface");
1908 return NB_ERR_VALIDATION
;
1915 ifp
= nb_running_get_entry(args
->dnode
->parent
, NULL
, true);
1916 pim_ifp
= ifp
->info
;
1917 if (pim_ifp
->bfd_info
) {
1918 pim_bfd_reg_dereg_all_nbr(ifp
,
1919 ZEBRA_BFD_DEST_DEREGISTER
);
1920 bfd_info_free(&(pim_ifp
->bfd_info
));
1929 * XPath: /frr-interface:lib/interface/frr-pim:pim/bfd
1931 void lib_interface_pim_bfd_apply_finish(struct nb_cb_apply_finish_args
*args
)
1933 struct interface
*ifp
;
1934 struct pim_interface
*pim_ifp
;
1937 uint8_t detect_mult
;
1939 ifp
= nb_running_get_entry(args
->dnode
->parent
, NULL
, true);
1940 pim_ifp
= ifp
->info
;
1943 zlog_debug("Pim not enabled on this interface");
1947 min_rx
= yang_dnode_get_uint16(args
->dnode
, "./min-rx-interval");
1948 min_tx
= yang_dnode_get_uint16(args
->dnode
, "./min-tx-interval");
1949 detect_mult
= yang_dnode_get_uint8(args
->dnode
, "./detect_mult");
1951 if ((min_rx
== BFD_DEF_MIN_RX
) && (min_tx
== BFD_DEF_MIN_TX
)
1952 && (detect_mult
== BFD_DEF_DETECT_MULT
))
1953 pim_bfd_if_param_set(ifp
, min_rx
, min_tx
, detect_mult
, 1);
1955 pim_bfd_if_param_set(ifp
, min_rx
, min_tx
, detect_mult
, 0);
1957 nb_running_set_entry(args
->dnode
, pim_ifp
->bfd_info
);
1961 * XPath: /frr-interface:lib/interface/frr-pim:pim/bfd/min-rx-interval
1963 int lib_interface_pim_bfd_min_rx_interval_modify(struct nb_cb_modify_args
*args
)
1965 switch (args
->event
) {
1966 case NB_EV_VALIDATE
:
1977 * XPath: /frr-interface:lib/interface/frr-pim:pim/bfd/min-tx-interval
1979 int lib_interface_pim_bfd_min_tx_interval_modify(struct nb_cb_modify_args
*args
)
1981 switch (args
->event
) {
1982 case NB_EV_VALIDATE
:
1993 * XPath: /frr-interface:lib/interface/frr-pim:pim/bfd/detect_mult
1995 int lib_interface_pim_bfd_detect_mult_modify(struct nb_cb_modify_args
*args
)
1997 switch (args
->event
) {
1998 case NB_EV_VALIDATE
:
2009 * XPath: /frr-interface:lib/interface/frr-pim:pim/bsm
2011 int lib_interface_pim_bsm_modify(struct nb_cb_modify_args
*args
)
2013 struct interface
*ifp
;
2014 struct pim_interface
*pim_ifp
;
2016 switch (args
->event
) {
2017 case NB_EV_VALIDATE
:
2022 ifp
= nb_running_get_entry(args
->dnode
, NULL
, true);
2023 pim_ifp
= ifp
->info
;
2024 pim_ifp
->bsm_enable
= yang_dnode_get_bool(args
->dnode
, NULL
);
2033 * XPath: /frr-interface:lib/interface/frr-pim:pim/unicast-bsm
2035 int lib_interface_pim_unicast_bsm_modify(struct nb_cb_modify_args
*args
)
2037 struct interface
*ifp
;
2038 struct pim_interface
*pim_ifp
;
2040 switch (args
->event
) {
2041 case NB_EV_VALIDATE
:
2046 ifp
= nb_running_get_entry(args
->dnode
, NULL
, true);
2047 pim_ifp
= ifp
->info
;
2048 pim_ifp
->ucast_bsm_accept
=
2049 yang_dnode_get_bool(args
->dnode
, NULL
);
2058 * XPath: /frr-interface:lib/interface/frr-pim:pim/active-active
2060 int lib_interface_pim_active_active_modify(struct nb_cb_modify_args
*args
)
2062 struct interface
*ifp
;
2063 struct pim_interface
*pim_ifp
;
2065 switch (args
->event
) {
2066 case NB_EV_VALIDATE
:
2071 ifp
= nb_running_get_entry(args
->dnode
, NULL
, true);
2072 pim_ifp
= ifp
->info
;
2073 if (yang_dnode_get_bool(args
->dnode
, NULL
)) {
2076 "Configuring PIM active-active on Interface: %s",
2078 pim_if_configure_mlag_dualactive(pim_ifp
);
2082 "UnConfiguring PIM active-active on Interface: %s",
2084 pim_if_unconfigure_mlag_dualactive(pim_ifp
);
2095 * XPath: /frr-interface:lib/interface/frr-pim:pim/dr-priority
2097 int lib_interface_pim_dr_priority_modify(struct nb_cb_modify_args
*args
)
2099 struct interface
*ifp
;
2100 struct pim_interface
*pim_ifp
;
2101 uint32_t old_dr_prio
;
2102 const struct lyd_node
*if_dnode
;
2104 switch (args
->event
) {
2105 case NB_EV_VALIDATE
:
2106 if_dnode
= yang_dnode_get_parent(args
->dnode
, "interface");
2107 if (!is_pim_interface(if_dnode
)) {
2108 snprintf(args
->errmsg
, args
->errmsg_len
,
2109 "Pim not enabled on this interface");
2110 return NB_ERR_VALIDATION
;
2117 ifp
= nb_running_get_entry(args
->dnode
, NULL
, true);
2118 pim_ifp
= ifp
->info
;
2119 old_dr_prio
= pim_ifp
->pim_dr_priority
;
2120 pim_ifp
->pim_dr_priority
= yang_dnode_get_uint32(args
->dnode
,
2123 if (old_dr_prio
!= pim_ifp
->pim_dr_priority
) {
2124 pim_if_dr_election(ifp
);
2125 pim_hello_restart_now(ifp
);
2134 * XPath: /frr-interface:lib/interface/frr-pim:pim/address-family
2136 int lib_interface_pim_address_family_create(struct nb_cb_create_args
*args
)
2138 switch (args
->event
) {
2139 case NB_EV_VALIDATE
:
2149 int lib_interface_pim_address_family_destroy(struct nb_cb_destroy_args
*args
)
2151 switch (args
->event
) {
2152 case NB_EV_VALIDATE
:
2163 * XPath: /frr-interface:lib/interface/frr-pim:pim/address-family/use-source
2165 int lib_interface_pim_address_family_use_source_modify(struct nb_cb_modify_args
*args
)
2167 struct interface
*ifp
;
2168 struct ipaddr source_addr
;
2170 const struct lyd_node
*if_dnode
;
2172 switch (args
->event
) {
2173 case NB_EV_VALIDATE
:
2174 if_dnode
= yang_dnode_get_parent(args
->dnode
, "interface");
2175 if (!is_pim_interface(if_dnode
)) {
2176 snprintf(args
->errmsg
, args
->errmsg_len
,
2177 "Pim not enabled on this interface");
2178 return NB_ERR_VALIDATION
;
2185 ifp
= nb_running_get_entry(args
->dnode
, NULL
, true);
2186 yang_dnode_get_ip(&source_addr
, args
->dnode
, NULL
);
2188 result
= interface_pim_use_src_cmd_worker(
2189 ifp
, source_addr
.ip
._v4_addr
,
2190 args
->errmsg
, args
->errmsg_len
);
2192 if (result
!= PIM_SUCCESS
)
2193 return NB_ERR_INCONSISTENCY
;
2201 int lib_interface_pim_address_family_use_source_destroy(
2202 struct nb_cb_destroy_args
*args
)
2204 struct interface
*ifp
;
2205 struct in_addr source_addr
= {INADDR_ANY
};
2207 const struct lyd_node
*if_dnode
;
2209 switch (args
->event
) {
2210 case NB_EV_VALIDATE
:
2211 if_dnode
= yang_dnode_get_parent(args
->dnode
, "interface");
2212 if (!is_pim_interface(if_dnode
)) {
2213 snprintf(args
->errmsg
, args
->errmsg_len
,
2214 "Pim not enabled on this interface");
2215 return NB_ERR_VALIDATION
;
2222 ifp
= nb_running_get_entry(args
->dnode
, NULL
, true);
2224 result
= interface_pim_use_src_cmd_worker(ifp
, source_addr
,
2228 if (result
!= PIM_SUCCESS
)
2229 return NB_ERR_INCONSISTENCY
;
2238 * XPath: /frr-interface:lib/interface/frr-pim:pim/address-family/multicast-boundary-oil
2240 int lib_interface_pim_address_family_multicast_boundary_oil_modify(
2241 struct nb_cb_modify_args
*args
)
2243 struct interface
*ifp
;
2244 struct pim_interface
*pim_ifp
;
2246 const struct lyd_node
*if_dnode
;
2248 switch (args
->event
) {
2249 case NB_EV_VALIDATE
:
2250 if_dnode
= yang_dnode_get_parent(args
->dnode
, "interface");
2251 if (!is_pim_interface(if_dnode
)) {
2252 snprintf(args
->errmsg
, args
->errmsg_len
,
2253 "Pim not enabled on this interface");
2254 return NB_ERR_VALIDATION
;
2261 ifp
= nb_running_get_entry(args
->dnode
, NULL
, true);
2262 pim_ifp
= ifp
->info
;
2263 plist
= yang_dnode_get_string(args
->dnode
, NULL
);
2265 if (pim_ifp
->boundary_oil_plist
)
2266 XFREE(MTYPE_PIM_INTERFACE
, pim_ifp
->boundary_oil_plist
);
2268 pim_ifp
->boundary_oil_plist
=
2269 XSTRDUP(MTYPE_PIM_INTERFACE
, plist
);
2277 int lib_interface_pim_address_family_multicast_boundary_oil_destroy(
2278 struct nb_cb_destroy_args
*args
)
2280 struct interface
*ifp
;
2281 struct pim_interface
*pim_ifp
;
2282 const struct lyd_node
*if_dnode
;
2284 switch (args
->event
) {
2285 case NB_EV_VALIDATE
:
2286 if_dnode
= yang_dnode_get_parent(args
->dnode
, "interface");
2287 if (!is_pim_interface(if_dnode
)) {
2288 snprintf(args
->errmsg
, args
->errmsg_len
,
2289 "%% Enable PIM and/or IGMP on this interface first");
2290 return NB_ERR_VALIDATION
;
2297 ifp
= nb_running_get_entry(args
->dnode
, NULL
, true);
2298 pim_ifp
= ifp
->info
;
2299 if (pim_ifp
->boundary_oil_plist
)
2300 XFREE(MTYPE_PIM_INTERFACE
, pim_ifp
->boundary_oil_plist
);
2308 * XPath: /frr-interface:lib/interface/frr-pim:pim/address-family/mroute
2310 int lib_interface_pim_address_family_mroute_create(
2311 struct nb_cb_create_args
*args
)
2313 switch (args
->event
) {
2314 case NB_EV_VALIDATE
:
2324 int lib_interface_pim_address_family_mroute_destroy(
2325 struct nb_cb_destroy_args
*args
)
2327 struct pim_instance
*pim
;
2328 struct pim_interface
*pim_iifp
;
2329 struct interface
*iif
;
2330 struct interface
*oif
;
2331 const char *oifname
;
2332 struct ipaddr source_addr
;
2333 struct ipaddr group_addr
;
2334 const struct lyd_node
*if_dnode
;
2336 switch (args
->event
) {
2337 case NB_EV_VALIDATE
:
2338 if_dnode
= yang_dnode_get_parent(args
->dnode
, "interface");
2339 if (!is_pim_interface(if_dnode
)) {
2340 snprintf(args
->errmsg
, args
->errmsg_len
,
2341 "%% Enable PIM and/or IGMP on this interface first");
2342 return NB_ERR_VALIDATION
;
2349 iif
= nb_running_get_entry(args
->dnode
, NULL
, true);
2350 pim_iifp
= iif
->info
;
2351 pim
= pim_iifp
->pim
;
2353 oifname
= yang_dnode_get_string(args
->dnode
, "./oif");
2354 oif
= if_lookup_by_name(oifname
, pim
->vrf_id
);
2357 snprintf(args
->errmsg
, args
->errmsg_len
,
2358 "No such interface name %s",
2360 return NB_ERR_INCONSISTENCY
;
2363 yang_dnode_get_ip(&source_addr
, args
->dnode
, "./source-addr");
2364 yang_dnode_get_ip(&group_addr
, args
->dnode
, "./group-addr");
2366 if (pim_static_del(pim
, iif
, oif
, group_addr
.ip
._v4_addr
,
2367 source_addr
.ip
._v4_addr
)) {
2368 snprintf(args
->errmsg
, args
->errmsg_len
,
2369 "Failed to remove static mroute");
2370 return NB_ERR_INCONSISTENCY
;
2380 * XPath: /frr-interface:lib/interface/frr-pim:pim/address-family/mroute/oif
2382 int lib_interface_pim_address_family_mroute_oif_modify(
2383 struct nb_cb_modify_args
*args
)
2385 struct pim_instance
*pim
;
2386 struct pim_interface
*pim_iifp
;
2387 struct interface
*iif
;
2388 struct interface
*oif
;
2389 const char *oifname
;
2390 struct ipaddr source_addr
;
2391 struct ipaddr group_addr
;
2392 const struct lyd_node
*if_dnode
;
2394 switch (args
->event
) {
2395 case NB_EV_VALIDATE
:
2396 if_dnode
= yang_dnode_get_parent(args
->dnode
, "interface");
2397 if (!is_pim_interface(if_dnode
)) {
2398 snprintf(args
->errmsg
, args
->errmsg_len
,
2399 "%% Enable PIM and/or IGMP on this interface first");
2400 return NB_ERR_VALIDATION
;
2407 iif
= nb_running_get_entry(args
->dnode
, NULL
, true);
2408 pim_iifp
= iif
->info
;
2409 pim
= pim_iifp
->pim
;
2411 oifname
= yang_dnode_get_string(args
->dnode
, NULL
);
2412 oif
= if_lookup_by_name(oifname
, pim
->vrf_id
);
2415 snprintf(args
->errmsg
, args
->errmsg_len
,
2416 "No such interface name %s",
2418 return NB_ERR_INCONSISTENCY
;
2421 yang_dnode_get_ip(&source_addr
, args
->dnode
, "../source-addr");
2422 yang_dnode_get_ip(&group_addr
, args
->dnode
, "../group-addr");
2424 if (pim_static_add(pim
, iif
, oif
, group_addr
.ip
._v4_addr
,
2425 source_addr
.ip
._v4_addr
)) {
2426 snprintf(args
->errmsg
, args
->errmsg_len
,
2427 "Failed to add static mroute");
2428 return NB_ERR_INCONSISTENCY
;
2437 int lib_interface_pim_address_family_mroute_oif_destroy(
2438 struct nb_cb_destroy_args
*args
)
2440 switch (args
->event
) {
2441 case NB_EV_VALIDATE
:
2452 * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/frr-pim-rp:rp/static-rp/rp-list
2454 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_static_rp_rp_list_create(
2455 struct nb_cb_create_args
*args
)
2457 switch (args
->event
) {
2458 case NB_EV_VALIDATE
:
2468 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_static_rp_rp_list_destroy(
2469 struct nb_cb_destroy_args
*args
)
2472 struct pim_instance
*pim
;
2473 struct prefix group
;
2474 struct ipaddr rp_addr
;
2478 switch (args
->event
) {
2479 case NB_EV_VALIDATE
:
2484 vrf
= nb_running_get_entry(args
->dnode
, NULL
, true);
2486 yang_dnode_get_ip(&rp_addr
, args
->dnode
, "./rp-address");
2488 if (yang_dnode_get(args
->dnode
, "./group-list")) {
2489 yang_dnode_get_ipv4p(&group
, args
->dnode
,
2491 apply_mask_ipv4((struct prefix_ipv4
*)&group
);
2492 result
= pim_no_rp_cmd_worker(pim
, rp_addr
.ip
._v4_addr
,
2493 group
, NULL
, args
->errmsg
,
2497 else if (yang_dnode_get(args
->dnode
, "./prefix-list")) {
2498 plist
= yang_dnode_get_string(args
->dnode
,
2500 str2prefix("224.0.0.0/4", &group
);
2501 result
= pim_no_rp_cmd_worker(pim
, rp_addr
.ip
._v4_addr
,
2508 return NB_ERR_INCONSISTENCY
;
2516 * 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
2518 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_static_rp_rp_list_group_list_create(
2519 struct nb_cb_create_args
*args
)
2522 struct pim_instance
*pim
;
2523 struct prefix group
;
2524 struct ipaddr rp_addr
;
2526 switch (args
->event
) {
2527 case NB_EV_VALIDATE
:
2532 vrf
= nb_running_get_entry(args
->dnode
, NULL
, true);
2534 yang_dnode_get_ip(&rp_addr
, args
->dnode
, "../rp-address");
2535 yang_dnode_get_ipv4p(&group
, args
->dnode
, NULL
);
2536 apply_mask_ipv4((struct prefix_ipv4
*)&group
);
2538 return pim_rp_cmd_worker(pim
, rp_addr
.ip
._v4_addr
, group
,
2539 NULL
, args
->errmsg
, args
->errmsg_len
);
2545 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_static_rp_rp_list_group_list_destroy(
2546 struct nb_cb_destroy_args
*args
)
2549 struct pim_instance
*pim
;
2550 struct prefix group
;
2551 struct ipaddr rp_addr
;
2553 switch (args
->event
) {
2554 case NB_EV_VALIDATE
:
2559 vrf
= nb_running_get_entry(args
->dnode
, NULL
, true);
2561 yang_dnode_get_ip(&rp_addr
, args
->dnode
, "../rp-address");
2562 yang_dnode_get_ipv4p(&group
, args
->dnode
, NULL
);
2563 apply_mask_ipv4((struct prefix_ipv4
*)&group
);
2565 return pim_no_rp_cmd_worker(pim
, rp_addr
.ip
._v4_addr
, group
,
2574 * 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
2576 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_static_rp_rp_list_prefix_list_modify(
2577 struct nb_cb_modify_args
*args
)
2580 struct pim_instance
*pim
;
2581 struct prefix group
;
2582 struct ipaddr rp_addr
;
2585 switch (args
->event
) {
2586 case NB_EV_VALIDATE
:
2591 vrf
= nb_running_get_entry(args
->dnode
, NULL
, true);
2593 plist
= yang_dnode_get_string(args
->dnode
, NULL
);
2594 yang_dnode_get_ip(&rp_addr
, args
->dnode
, "../rp-address");
2595 str2prefix("224.0.0.0/4", &group
);
2596 return pim_rp_cmd_worker(pim
, rp_addr
.ip
._v4_addr
, group
,
2597 plist
, args
->errmsg
, args
->errmsg_len
);
2603 int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_static_rp_rp_list_prefix_list_destroy(
2604 struct nb_cb_destroy_args
*args
)
2607 struct pim_instance
*pim
;
2608 struct prefix group
;
2609 struct ipaddr rp_addr
;
2612 switch (args
->event
) {
2613 case NB_EV_VALIDATE
:
2618 vrf
= nb_running_get_entry(args
->dnode
, NULL
, true);
2620 yang_dnode_get_ip(&rp_addr
, args
->dnode
, "../rp-address");
2621 plist
= yang_dnode_get_string(args
->dnode
, NULL
);
2622 str2prefix("224.0.0.0/4", &group
);
2623 return pim_no_rp_cmd_worker(pim
, rp_addr
.ip
._v4_addr
, group
,
2624 plist
, args
->errmsg
,
2633 * XPath: /frr-interface:lib/interface/frr-igmp:igmp
2635 int lib_interface_igmp_create(struct nb_cb_create_args
*args
)
2637 switch (args
->event
) {
2638 case NB_EV_VALIDATE
:
2648 int lib_interface_igmp_destroy(struct nb_cb_destroy_args
*args
)
2650 struct interface
*ifp
;
2651 struct pim_interface
*pim_ifp
;
2653 switch (args
->event
) {
2654 case NB_EV_VALIDATE
:
2659 ifp
= nb_running_get_entry(args
->dnode
, NULL
, true);
2660 pim_ifp
= ifp
->info
;
2665 PIM_IF_DONT_IGMP(pim_ifp
->options
);
2667 pim_if_membership_clear(ifp
);
2669 pim_if_addr_del_all_igmp(ifp
);
2671 if (!PIM_IF_TEST_PIM(pim_ifp
->options
))
2679 * XPath: /frr-interface:lib/interface/frr-igmp:igmp/igmp-enable
2681 int lib_interface_igmp_igmp_enable_modify(struct nb_cb_modify_args
*args
)
2683 struct interface
*ifp
;
2685 struct pim_interface
*pim_ifp
;
2687 const char *ifp_name
;
2688 const struct lyd_node
*if_dnode
;
2690 switch (args
->event
) {
2691 case NB_EV_VALIDATE
:
2692 if_dnode
= yang_dnode_get_parent(args
->dnode
, "interface");
2693 ifp_name
= yang_dnode_get_string(if_dnode
, ".");
2695 yang_get_list_elements_count(if_dnode
);
2696 /* Limiting mcast interfaces to number of VIFs */
2697 if (mcast_if_count
== MAXVIFS
) {
2698 snprintf(args
->errmsg
, args
->errmsg_len
,
2699 "Max multicast interfaces(%d) Reached. Could not enable IGMP on interface %s",
2701 return NB_ERR_VALIDATION
;
2708 ifp
= nb_running_get_entry(args
->dnode
, NULL
, true);
2709 igmp_enable
= yang_dnode_get_bool(args
->dnode
, NULL
);
2712 return pim_cmd_igmp_start(ifp
);
2715 pim_ifp
= ifp
->info
;
2718 return NB_ERR_INCONSISTENCY
;
2720 PIM_IF_DONT_IGMP(pim_ifp
->options
);
2722 pim_if_membership_clear(ifp
);
2724 pim_if_addr_del_all_igmp(ifp
);
2726 if (!PIM_IF_TEST_PIM(pim_ifp
->options
))
2735 * XPath: /frr-interface:lib/interface/frr-igmp:igmp/version
2737 int lib_interface_igmp_version_modify(struct nb_cb_modify_args
*args
)
2739 struct interface
*ifp
;
2740 struct pim_interface
*pim_ifp
;
2741 int igmp_version
, old_version
= 0;
2743 switch (args
->event
) {
2744 case NB_EV_VALIDATE
:
2749 ifp
= nb_running_get_entry(args
->dnode
, NULL
, true);
2750 pim_ifp
= ifp
->info
;
2753 return NB_ERR_INCONSISTENCY
;
2755 igmp_version
= yang_dnode_get_uint8(args
->dnode
, NULL
);
2756 old_version
= pim_ifp
->igmp_version
;
2757 pim_ifp
->igmp_version
= igmp_version
;
2759 /* Current and new version is different refresh existing
2760 * membership. Going from 3 -> 2 or 2 -> 3.
2762 if (old_version
!= igmp_version
)
2763 pim_if_membership_refresh(ifp
);
2771 int lib_interface_igmp_version_destroy(struct nb_cb_destroy_args
*args
)
2773 struct interface
*ifp
;
2774 struct pim_interface
*pim_ifp
;
2776 switch (args
->event
) {
2777 case NB_EV_VALIDATE
:
2782 ifp
= nb_running_get_entry(args
->dnode
, NULL
, true);
2783 pim_ifp
= ifp
->info
;
2784 pim_ifp
->igmp_version
= IGMP_DEFAULT_VERSION
;
2792 * XPath: /frr-interface:lib/interface/frr-igmp:igmp/query-interval
2794 int lib_interface_igmp_query_interval_modify(struct nb_cb_modify_args
*args
)
2796 struct interface
*ifp
;
2797 struct pim_interface
*pim_ifp
;
2799 int query_interval_dsec
;
2801 switch (args
->event
) {
2802 case NB_EV_VALIDATE
:
2807 ifp
= nb_running_get_entry(args
->dnode
, NULL
, true);
2808 pim_ifp
= ifp
->info
;
2809 query_interval
= yang_dnode_get_uint16(args
->dnode
, NULL
);
2810 query_interval_dsec
= 10 * query_interval
;
2811 if (query_interval_dsec
<=
2812 pim_ifp
->igmp_query_max_response_time_dsec
) {
2813 snprintf(args
->errmsg
, args
->errmsg_len
,
2814 "Can't set general query interval %d dsec <= query max response time %d dsec.",
2815 query_interval_dsec
,
2816 pim_ifp
->igmp_query_max_response_time_dsec
);
2817 return NB_ERR_INCONSISTENCY
;
2819 change_query_interval(pim_ifp
, query_interval
);
2826 * XPath: /frr-interface:lib/interface/frr-igmp:igmp/query-max-response-time
2828 int lib_interface_igmp_query_max_response_time_modify(
2829 struct nb_cb_modify_args
*args
)
2831 struct interface
*ifp
;
2832 struct pim_interface
*pim_ifp
;
2833 int query_max_response_time_dsec
;
2834 int default_query_interval_dsec
;
2836 switch (args
->event
) {
2837 case NB_EV_VALIDATE
:
2842 ifp
= nb_running_get_entry(args
->dnode
, NULL
, true);
2843 pim_ifp
= ifp
->info
;
2844 query_max_response_time_dsec
=
2845 yang_dnode_get_uint8(args
->dnode
, NULL
);
2846 default_query_interval_dsec
=
2847 10 * pim_ifp
->igmp_default_query_interval
;
2849 if (query_max_response_time_dsec
2850 >= default_query_interval_dsec
) {
2851 snprintf(args
->errmsg
, args
->errmsg_len
,
2852 "Can't set query max response time %d sec >= general query interval %d sec",
2853 query_max_response_time_dsec
,
2854 pim_ifp
->igmp_default_query_interval
);
2855 return NB_ERR_INCONSISTENCY
;
2858 change_query_max_response_time(pim_ifp
,
2859 query_max_response_time_dsec
);
2866 * XPath: /frr-interface:lib/interface/frr-igmp:igmp/last-member-query-interval
2868 int lib_interface_igmp_last_member_query_interval_modify(
2869 struct nb_cb_modify_args
*args
)
2871 struct interface
*ifp
;
2872 struct pim_interface
*pim_ifp
;
2873 int last_member_query_interval
;
2875 switch (args
->event
) {
2876 case NB_EV_VALIDATE
:
2881 ifp
= nb_running_get_entry(args
->dnode
, NULL
, true);
2882 pim_ifp
= ifp
->info
;
2883 last_member_query_interval
= yang_dnode_get_uint8(args
->dnode
,
2885 pim_ifp
->igmp_specific_query_max_response_time_dsec
=
2886 last_member_query_interval
;
2895 * XPath: /frr-interface:lib/interface/frr-igmp:igmp/robustness-variable
2897 int lib_interface_igmp_robustness_variable_modify(
2898 struct nb_cb_modify_args
*args
)
2900 struct interface
*ifp
;
2901 struct pim_interface
*pim_ifp
;
2902 int last_member_query_count
;
2904 switch (args
->event
) {
2905 case NB_EV_VALIDATE
:
2910 ifp
= nb_running_get_entry(args
->dnode
, NULL
, true);
2911 pim_ifp
= ifp
->info
;
2912 last_member_query_count
= yang_dnode_get_uint8(args
->dnode
,
2914 pim_ifp
->igmp_last_member_query_count
= last_member_query_count
;
2923 * XPath: /frr-interface:lib/interface/frr-igmp:igmp/address-family
2925 int lib_interface_igmp_address_family_create(struct nb_cb_create_args
*args
)
2927 switch (args
->event
) {
2928 case NB_EV_VALIDATE
:
2938 int lib_interface_igmp_address_family_destroy(struct nb_cb_destroy_args
*args
)
2940 switch (args
->event
) {
2941 case NB_EV_VALIDATE
:
2952 * XPath: /frr-interface:lib/interface/frr-igmp:igmp/address-family/static-group
2954 int lib_interface_igmp_address_family_static_group_create(
2955 struct nb_cb_create_args
*args
)
2957 struct interface
*ifp
;
2958 struct ipaddr source_addr
;
2959 struct ipaddr group_addr
;
2961 const char *ifp_name
;
2962 const struct lyd_node
*if_dnode
;
2964 switch (args
->event
) {
2965 case NB_EV_VALIDATE
:
2966 if_dnode
= yang_dnode_get_parent(args
->dnode
, "interface");
2967 if (!is_pim_interface(if_dnode
)) {
2968 ifp_name
= yang_dnode_get_string(if_dnode
, ".");
2969 snprintf(args
->errmsg
, args
->errmsg_len
,
2970 "multicast not enabled on interface %s",
2972 return NB_ERR_VALIDATION
;
2979 ifp
= nb_running_get_entry(args
->dnode
, NULL
, true);
2980 yang_dnode_get_ip(&source_addr
, args
->dnode
, "./source-addr");
2981 yang_dnode_get_ip(&group_addr
, args
->dnode
, "./group-addr");
2983 result
= pim_if_igmp_join_add(ifp
, group_addr
.ip
._v4_addr
,
2984 source_addr
.ip
._v4_addr
);
2986 snprintf(args
->errmsg
, args
->errmsg_len
,
2987 "Failure joining IGMP group");
2988 return NB_ERR_INCONSISTENCY
;
2995 int lib_interface_igmp_address_family_static_group_destroy(
2996 struct nb_cb_destroy_args
*args
)
2998 struct interface
*ifp
;
2999 struct ipaddr source_addr
;
3000 struct ipaddr group_addr
;
3003 switch (args
->event
) {
3004 case NB_EV_VALIDATE
:
3009 ifp
= nb_running_get_entry(args
->dnode
, NULL
, true);
3010 yang_dnode_get_ip(&source_addr
, args
->dnode
, "./source-addr");
3011 yang_dnode_get_ip(&group_addr
, args
->dnode
, "./group-addr");
3013 result
= pim_if_igmp_join_del(ifp
, group_addr
.ip
._v4_addr
,
3014 source_addr
.ip
._v4_addr
);
3017 char src_str
[INET_ADDRSTRLEN
];
3018 char grp_str
[INET_ADDRSTRLEN
];
3020 ipaddr2str(&source_addr
, src_str
, sizeof(src_str
));
3021 ipaddr2str(&group_addr
, grp_str
, sizeof(grp_str
));
3023 snprintf(args
->errmsg
, args
->errmsg_len
,
3024 "%% Failure leaving IGMP group %s %s on interface %s: %d",
3025 src_str
, grp_str
, ifp
->name
, result
);
3027 return NB_ERR_INCONSISTENCY
;