mirror of
https://github.com/FRRouting/frr.git
synced 2025-04-30 13:37:17 +02:00

New CLI commands added: router pim [vrf NAME] autorp discovery autorp announce RP-ADDR [GROUP | group-list PREFIX-LIST] autorp announce {scope (1-255) | interval (1-65535) | holdtime (0-65535)} autorp discovery Enables Auto RP discovery for learning dynamic RP information using the AutoRP protocol. autorp announce RP-ADDR [GROUP | group-list PREFIX-LIST] Enable announcements of a candidate RP with the given group range, or prefix list of group ranges, to an AutoRP mapping agent. autorp announce {scope (1-255) | interval (1-65535) | holdtime (0-65535)} Configure the parameters of the AutoRP announcement messages. The scope sets the packet TTL. The interval sets the time between TX of announcements. The holdtime sets the hold time in the message, the time the mapping agent should wait before invalidating the candidate RP information. debug pim autorp Enable debug logging of the AutoRP protocol show ip pim [vrf NAME] autorp [json] Show details of the AutoRP protocol. To view learned RP info, use the existing command 'show ip pim rp-info' Extend pim yang for new configuration: augment /frr-rt:routing/frr-rt:control-plane-protocols/frr-rt:control-plane-protocol/frr-pim:pim/frr-pim:address-family: +--rw rp +--rw auto-rp +--rw discovery-enabled? boolean +--rw announce-scope? uint8 +--rw announce-interval? uint16 +--rw announce-holdtime? uint16 +--rw candidate-rp-list* [rp-address] +--rw rp-address inet:ip-address +--rw (group-or-prefix-list)? +--:(group) | +--rw group? frr-route-types:ip-multicast-group-prefix +--:(prefix-list) +--rw prefix-list? plist-ref Signed-off-by: Nathan Bahr <nbahr@atcorp.com>
3966 lines
92 KiB
C
3966 lines
92 KiB
C
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
/*
|
|
* Copyright (C) 2020 VmWare
|
|
* Sarita Patra
|
|
*/
|
|
|
|
#include <zebra.h>
|
|
|
|
#include "pimd.h"
|
|
#include "pim_nb.h"
|
|
#include "lib/northbound_cli.h"
|
|
#include "lib/sockopt.h"
|
|
#include "pim_igmpv3.h"
|
|
#include "pim_neighbor.h"
|
|
#include "pim_nht.h"
|
|
#include "pim_pim.h"
|
|
#include "pim_mlag.h"
|
|
#include "pim_bfd.h"
|
|
#include "pim_msdp_socket.h"
|
|
#include "pim_static.h"
|
|
#include "pim_ssm.h"
|
|
#include "pim_ssmpingd.h"
|
|
#include "pim_vxlan.h"
|
|
#include "pim_util.h"
|
|
#include "log.h"
|
|
#include "lib_errors.h"
|
|
#include "pim_util.h"
|
|
#include "pim6_mld.h"
|
|
#include "pim_autorp.h"
|
|
#include "pim_igmp.h"
|
|
|
|
#if PIM_IPV == 6
|
|
#define pim6_msdp_err(funcname, argtype) \
|
|
int funcname(struct argtype *args) \
|
|
{ \
|
|
snprintf(args->errmsg, args->errmsg_len, \
|
|
"Trying to configure MSDP in pim6d. " \
|
|
"MSDP does not exist for IPv6."); \
|
|
return NB_ERR_VALIDATION; \
|
|
} \
|
|
MACRO_REQUIRE_SEMICOLON()
|
|
|
|
#define yang_dnode_get_pimaddr yang_dnode_get_ipv6
|
|
|
|
#else /* PIM_IPV != 6 */
|
|
#define pim6_msdp_err(funcname, argtype) \
|
|
MACRO_REQUIRE_SEMICOLON()
|
|
|
|
#define yang_dnode_get_pimaddr yang_dnode_get_ipv4
|
|
#endif /* PIM_IPV != 6 */
|
|
|
|
/*
|
|
* When PIM is disabled on interface, IGMPv3 local membership
|
|
* information is not injected into PIM interface state.
|
|
|
|
* The function pim_if_membership_refresh() fetches all IGMPv3 local
|
|
* membership information into PIM. It is intented to be called
|
|
* whenever PIM is enabled on the interface in order to collect missed
|
|
* local membership information.
|
|
*/
|
|
static void pim_if_membership_refresh(struct interface *ifp)
|
|
{
|
|
struct pim_interface *pim_ifp;
|
|
#if PIM_IPV == 4
|
|
struct listnode *grpnode;
|
|
struct gm_group *grp;
|
|
#else
|
|
struct gm_if *gm_ifp;
|
|
struct gm_sg *sg, *sg_start;
|
|
#endif
|
|
|
|
pim_ifp = ifp->info;
|
|
assert(pim_ifp);
|
|
|
|
if (!pim_ifp->pim_enable)
|
|
return;
|
|
if (!pim_ifp->gm_enable)
|
|
return;
|
|
|
|
#if PIM_IPV == 6
|
|
gm_ifp = pim_ifp->mld;
|
|
if (!gm_ifp)
|
|
return;
|
|
#endif
|
|
/*
|
|
* First clear off membership from all PIM (S,G) entries on the
|
|
* interface
|
|
*/
|
|
|
|
pim_ifchannel_membership_clear(ifp);
|
|
|
|
#if PIM_IPV == 4
|
|
/*
|
|
* Then restore PIM (S,G) membership from all IGMPv3 (S,G) entries on
|
|
* the interface
|
|
*/
|
|
|
|
/* scan igmp groups */
|
|
for (ALL_LIST_ELEMENTS_RO(pim_ifp->gm_group_list, grpnode, grp)) {
|
|
struct listnode *srcnode;
|
|
struct gm_source *src;
|
|
|
|
/* scan group sources */
|
|
for (ALL_LIST_ELEMENTS_RO(grp->group_source_list, srcnode,
|
|
src)) {
|
|
|
|
if (IGMP_SOURCE_TEST_FORWARDING(src->source_flags)) {
|
|
pim_sgaddr sg;
|
|
|
|
memset(&sg, 0, sizeof(sg));
|
|
sg.src = src->source_addr;
|
|
sg.grp = grp->group_addr;
|
|
pim_ifchannel_local_membership_add(
|
|
ifp, &sg, false /*is_vxlan*/);
|
|
}
|
|
|
|
} /* scan group sources */
|
|
} /* scan igmp groups */
|
|
#else
|
|
sg_start = gm_sgs_first(gm_ifp->sgs);
|
|
|
|
frr_each_from (gm_sgs, gm_ifp->sgs, sg, sg_start) {
|
|
if (!in6_multicast_nofwd(&sg->sgaddr.grp)) {
|
|
pim_ifchannel_local_membership_add(
|
|
ifp, &sg->sgaddr, false /*is_vxlan*/);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* Finally delete every PIM (S,G) entry lacking all state info
|
|
*/
|
|
|
|
pim_ifchannel_delete_on_noinfo(ifp);
|
|
}
|
|
|
|
static int pim_cmd_interface_add(struct interface *ifp)
|
|
{
|
|
struct pim_interface *pim_ifp = ifp->info;
|
|
|
|
if (!pim_ifp)
|
|
pim_ifp = pim_if_new(ifp, false, true, false, false);
|
|
else
|
|
pim_ifp->pim_enable = true;
|
|
|
|
pim_if_addr_add_all(ifp);
|
|
pim_upstream_nh_if_update(pim_ifp->pim, ifp);
|
|
pim_if_membership_refresh(ifp);
|
|
|
|
pim_if_create_pimreg(pim_ifp->pim);
|
|
|
|
#if PIM_IPV == 4
|
|
pim_autorp_add_ifp(ifp);
|
|
#endif
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int interface_pim_use_src_cmd_worker(struct interface *ifp,
|
|
pim_addr source_addr, char *errmsg, size_t errmsg_len)
|
|
{
|
|
int result;
|
|
int ret = NB_OK;
|
|
|
|
result = pim_update_source_set(ifp, source_addr);
|
|
|
|
switch (result) {
|
|
case PIM_SUCCESS:
|
|
break;
|
|
case PIM_IFACE_NOT_FOUND:
|
|
ret = NB_ERR;
|
|
snprintf(errmsg, errmsg_len,
|
|
"Pim not enabled on this interface %s",
|
|
ifp->name);
|
|
break;
|
|
case PIM_UPDATE_SOURCE_DUP:
|
|
ret = NB_ERR;
|
|
snprintf(errmsg, errmsg_len, "Source already set");
|
|
break;
|
|
default:
|
|
ret = NB_ERR;
|
|
snprintf(errmsg, errmsg_len, "Source set failed");
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int pim_cmd_spt_switchover(struct pim_instance *pim,
|
|
enum pim_spt_switchover spt,
|
|
const char *plist)
|
|
{
|
|
pim->spt.switchover = spt;
|
|
|
|
switch (pim->spt.switchover) {
|
|
case PIM_SPT_IMMEDIATE:
|
|
XFREE(MTYPE_PIM_PLIST_NAME, pim->spt.plist);
|
|
|
|
pim_upstream_add_lhr_star_pimreg(pim);
|
|
break;
|
|
case PIM_SPT_INFINITY:
|
|
pim_upstream_remove_lhr_star_pimreg(pim, plist);
|
|
|
|
XFREE(MTYPE_PIM_PLIST_NAME, pim->spt.plist);
|
|
|
|
if (plist)
|
|
pim->spt.plist = XSTRDUP(MTYPE_PIM_PLIST_NAME, plist);
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
static int pim_ssm_cmd_worker(struct pim_instance *pim, const char *plist,
|
|
char *errmsg, size_t errmsg_len)
|
|
{
|
|
int result = pim_ssm_range_set(pim, pim->vrf->vrf_id, plist);
|
|
int ret = NB_ERR;
|
|
|
|
if (result == PIM_SSM_ERR_NONE)
|
|
return NB_OK;
|
|
|
|
switch (result) {
|
|
case PIM_SSM_ERR_NO_VRF:
|
|
snprintf(errmsg, errmsg_len,
|
|
"VRF doesn't exist");
|
|
break;
|
|
case PIM_SSM_ERR_DUP:
|
|
snprintf(errmsg, errmsg_len,
|
|
"duplicate config");
|
|
break;
|
|
default:
|
|
snprintf(errmsg, errmsg_len,
|
|
"ssm range config failed");
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int pim_rp_cmd_worker(struct pim_instance *pim, pim_addr rp_addr,
|
|
struct prefix group, const char *plist,
|
|
char *errmsg, size_t errmsg_len)
|
|
{
|
|
int result;
|
|
|
|
result = pim_rp_new(pim, rp_addr, group, plist, RP_SRC_STATIC);
|
|
|
|
if (result == PIM_RP_NO_PATH) {
|
|
snprintfrr(errmsg, errmsg_len,
|
|
"No Path to RP address specified: %pPA", &rp_addr);
|
|
return NB_OK;
|
|
}
|
|
|
|
if (result == PIM_GROUP_OVERLAP) {
|
|
snprintf(errmsg, errmsg_len,
|
|
"Group range specified cannot exact match another");
|
|
return NB_ERR_INCONSISTENCY;
|
|
}
|
|
|
|
if (result == PIM_GROUP_PFXLIST_OVERLAP) {
|
|
snprintf(errmsg, errmsg_len,
|
|
"This group is already covered by a RP prefix-list");
|
|
return NB_ERR_INCONSISTENCY;
|
|
}
|
|
|
|
if (result == PIM_RP_PFXLIST_IN_USE) {
|
|
snprintf(errmsg, errmsg_len,
|
|
"The same prefix-list cannot be applied to multiple RPs");
|
|
return NB_ERR_INCONSISTENCY;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
static int pim_no_rp_cmd_worker(struct pim_instance *pim, pim_addr rp_addr,
|
|
struct prefix group, const char *plist,
|
|
char *errmsg, size_t errmsg_len)
|
|
{
|
|
char group_str[PREFIX2STR_BUFFER];
|
|
int result;
|
|
|
|
prefix2str(&group, group_str, sizeof(group_str));
|
|
|
|
result = pim_rp_del(pim, rp_addr, group, plist, RP_SRC_STATIC);
|
|
|
|
if (result == PIM_GROUP_BAD_ADDRESS) {
|
|
snprintf(errmsg, errmsg_len,
|
|
"Bad group address specified: %s", group_str);
|
|
return NB_ERR_INCONSISTENCY;
|
|
}
|
|
|
|
if (result == PIM_RP_BAD_ADDRESS) {
|
|
snprintfrr(errmsg, errmsg_len, "Bad RP address specified: %pPA",
|
|
&rp_addr);
|
|
return NB_ERR_INCONSISTENCY;
|
|
}
|
|
|
|
if (result == PIM_RP_NOT_FOUND) {
|
|
snprintf(errmsg, errmsg_len,
|
|
"Unable to find specified RP");
|
|
return NB_ERR_INCONSISTENCY;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
static bool is_pim_interface(const struct lyd_node *dnode)
|
|
{
|
|
char if_xpath[XPATH_MAXLEN];
|
|
const struct lyd_node *pim_enable_dnode;
|
|
const struct lyd_node *igmp_enable_dnode;
|
|
|
|
yang_dnode_get_path(dnode, if_xpath, sizeof(if_xpath));
|
|
pim_enable_dnode =
|
|
yang_dnode_getf(dnode,
|
|
"%s/frr-pim:pim/address-family[address-family='%s']/pim-enable",
|
|
if_xpath, FRR_PIM_AF_XPATH_VAL);
|
|
igmp_enable_dnode = yang_dnode_getf(dnode,
|
|
"%s/frr-gmp:gmp/address-family[address-family='%s']/enable",
|
|
if_xpath, FRR_PIM_AF_XPATH_VAL);
|
|
|
|
if (((pim_enable_dnode) &&
|
|
(yang_dnode_get_bool(pim_enable_dnode, "."))) ||
|
|
((igmp_enable_dnode) &&
|
|
(yang_dnode_get_bool(igmp_enable_dnode, "."))))
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
static int pim_cmd_gm_start(struct interface *ifp)
|
|
{
|
|
struct pim_interface *pim_ifp;
|
|
uint8_t need_startup = 0;
|
|
|
|
pim_ifp = ifp->info;
|
|
|
|
if (!pim_ifp) {
|
|
pim_ifp = pim_if_new(ifp, true, false, false, false);
|
|
need_startup = 1;
|
|
} else {
|
|
if (!pim_ifp->gm_enable) {
|
|
pim_ifp->gm_enable = true;
|
|
need_startup = 1;
|
|
}
|
|
}
|
|
pim_if_create_pimreg(pim_ifp->pim);
|
|
|
|
/* 'ip igmp' executed multiple times, with need_startup
|
|
* avoid multiple if add all and membership refresh
|
|
*/
|
|
if (need_startup) {
|
|
pim_if_addr_add_all(ifp);
|
|
pim_if_membership_refresh(ifp);
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* CLI reconfiguration affects the interface level (struct pim_interface).
|
|
* This function propagates the reconfiguration to every active socket
|
|
* for that interface.
|
|
*/
|
|
#if PIM_IPV == 4
|
|
static void igmp_sock_query_interval_reconfig(struct gm_sock *igmp)
|
|
{
|
|
struct interface *ifp;
|
|
struct pim_interface *pim_ifp;
|
|
|
|
assert(igmp);
|
|
assert(igmp->interface);
|
|
assert(igmp->interface->info);
|
|
|
|
ifp = igmp->interface;
|
|
pim_ifp = ifp->info;
|
|
|
|
if (PIM_DEBUG_GM_TRACE)
|
|
zlog_debug("%s: Querier %pPAs on %s reconfig query_interval=%d",
|
|
__func__, &igmp->ifaddr, ifp->name,
|
|
pim_ifp->gm_default_query_interval);
|
|
|
|
/*
|
|
* igmp_startup_mode_on() will reset QQI:
|
|
|
|
* igmp->querier_query_interval = pim_ifp->gm_default_query_interval;
|
|
*/
|
|
igmp_startup_mode_on(igmp);
|
|
}
|
|
|
|
static void igmp_sock_query_reschedule(struct gm_sock *igmp)
|
|
{
|
|
if (igmp->mtrace_only)
|
|
return;
|
|
|
|
if (igmp->t_igmp_query_timer) {
|
|
/* other querier present */
|
|
assert(igmp->t_igmp_query_timer);
|
|
assert(!igmp->t_other_querier_timer);
|
|
|
|
pim_igmp_general_query_off(igmp);
|
|
pim_igmp_general_query_on(igmp);
|
|
|
|
assert(igmp->t_igmp_query_timer);
|
|
assert(!igmp->t_other_querier_timer);
|
|
} else {
|
|
/* this is the querier */
|
|
|
|
assert(!igmp->t_igmp_query_timer);
|
|
assert(igmp->t_other_querier_timer);
|
|
|
|
pim_igmp_other_querier_timer_off(igmp);
|
|
pim_igmp_other_querier_timer_on(igmp);
|
|
|
|
assert(!igmp->t_igmp_query_timer);
|
|
assert(igmp->t_other_querier_timer);
|
|
}
|
|
}
|
|
#endif /* PIM_IPV == 4 */
|
|
|
|
#if PIM_IPV == 4
|
|
static void change_query_interval(struct pim_interface *pim_ifp,
|
|
int query_interval)
|
|
{
|
|
struct listnode *sock_node;
|
|
struct gm_sock *igmp;
|
|
|
|
pim_ifp->gm_default_query_interval = query_interval;
|
|
|
|
for (ALL_LIST_ELEMENTS_RO(pim_ifp->gm_socket_list, sock_node, igmp)) {
|
|
igmp_sock_query_interval_reconfig(igmp);
|
|
igmp_sock_query_reschedule(igmp);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
static void change_query_max_response_time(struct interface *ifp,
|
|
int query_max_response_time_dsec)
|
|
{
|
|
#if PIM_IPV == 4
|
|
struct listnode *sock_node;
|
|
struct gm_sock *igmp;
|
|
struct listnode *grp_node;
|
|
struct gm_group *grp;
|
|
#endif
|
|
|
|
struct pim_interface *pim_ifp = ifp->info;
|
|
|
|
if (pim_ifp->gm_query_max_response_time_dsec ==
|
|
query_max_response_time_dsec)
|
|
return;
|
|
|
|
pim_ifp->gm_query_max_response_time_dsec = query_max_response_time_dsec;
|
|
|
|
#if PIM_IPV == 6
|
|
gm_ifp_update(ifp);
|
|
#else
|
|
/*
|
|
* Below we modify socket/group/source timers in order to quickly
|
|
* reflect the change. Otherwise, those timers would args->eventually
|
|
* catch up.
|
|
*/
|
|
|
|
/* scan all sockets */
|
|
for (ALL_LIST_ELEMENTS_RO(pim_ifp->gm_socket_list, sock_node, igmp)) {
|
|
/* reschedule socket general query */
|
|
igmp_sock_query_reschedule(igmp);
|
|
}
|
|
|
|
/* scan socket groups */
|
|
for (ALL_LIST_ELEMENTS_RO(pim_ifp->gm_group_list, grp_node, grp)) {
|
|
struct listnode *src_node;
|
|
struct gm_source *src;
|
|
|
|
/* reset group timers for groups in EXCLUDE mode */
|
|
if (grp->group_filtermode_isexcl)
|
|
igmp_group_reset_gmi(grp);
|
|
|
|
/* scan group sources */
|
|
for (ALL_LIST_ELEMENTS_RO(grp->group_source_list, src_node,
|
|
src)) {
|
|
|
|
/* reset source timers for sources with running
|
|
* timers
|
|
*/
|
|
if (src->t_source_timer)
|
|
igmp_source_reset_gmi(grp, src);
|
|
}
|
|
}
|
|
#endif /* PIM_IPV == 4 */
|
|
}
|
|
|
|
int routing_control_plane_protocols_name_validate(
|
|
struct nb_cb_create_args *args)
|
|
{
|
|
const char *name;
|
|
|
|
name = yang_dnode_get_string(args->dnode, "name");
|
|
if (!strmatch(name, "pim")) {
|
|
snprintf(args->errmsg, args->errmsg_len,
|
|
"pim supports only one instance with name pimd");
|
|
return NB_ERR_VALIDATION;
|
|
}
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath: /frr-pim:pim/address-family
|
|
*/
|
|
int pim_address_family_create(struct nb_cb_create_args *args)
|
|
{
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
case NB_EV_APPLY:
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
int pim_address_family_destroy(struct nb_cb_destroy_args *args)
|
|
{
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
case NB_EV_APPLY:
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath: /frr-pim:pim/address-family/packets
|
|
*/
|
|
int pim_address_family_packets_modify(struct nb_cb_modify_args *args)
|
|
{
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
router->packet_process = yang_dnode_get_uint8(args->dnode,
|
|
NULL);
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath: /frr-pim:pim/address-family/join-prune-interval
|
|
*/
|
|
int pim_address_family_join_prune_interval_modify(
|
|
struct nb_cb_modify_args *args)
|
|
{
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
router->t_periodic = yang_dnode_get_uint16(args->dnode, NULL);
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath: /frr-pim:pim/address-family/register-suppress-time
|
|
*/
|
|
int pim_address_family_register_suppress_time_modify(
|
|
struct nb_cb_modify_args *args)
|
|
{
|
|
uint16_t value;
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
value = yang_dnode_get_uint16(args->dnode, NULL);
|
|
/*
|
|
* As soon as this is non-constant it needs to be replaced with
|
|
* a yang_dnode_get to lookup the candidate value, *not* the
|
|
* operational value. Since the code has a field assigned and
|
|
* used for this value it should have YANG/CLI to set it too,
|
|
* otherwise just use the #define!
|
|
*/
|
|
/* RFC7761: 4.11. Timer Values */
|
|
if (value <= router->register_probe_time * 2) {
|
|
snprintf(
|
|
args->errmsg, args->errmsg_len,
|
|
"Register suppress time (%u) must be more than "
|
|
"twice the register probe time (%u).",
|
|
value, router->register_probe_time);
|
|
return NB_ERR_VALIDATION;
|
|
}
|
|
break;
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
pim_update_suppress_timers(
|
|
yang_dnode_get_uint16(args->dnode, NULL));
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/ecmp
|
|
*/
|
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_ecmp_modify(
|
|
struct nb_cb_modify_args *args)
|
|
{
|
|
struct vrf *vrf;
|
|
struct pim_instance *pim;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
vrf = nb_running_get_entry(args->dnode, NULL, true);
|
|
pim = vrf->info;
|
|
pim->ecmp_enable = yang_dnode_get_bool(args->dnode, NULL);
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/ecmp-rebalance
|
|
*/
|
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_ecmp_rebalance_modify(
|
|
struct nb_cb_modify_args *args)
|
|
{
|
|
struct vrf *vrf;
|
|
struct pim_instance *pim;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
vrf = nb_running_get_entry(args->dnode, NULL, true);
|
|
pim = vrf->info;
|
|
pim->ecmp_rebalance_enable =
|
|
yang_dnode_get_bool(args->dnode, NULL);
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/keep-alive-timer
|
|
*/
|
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_keep_alive_timer_modify(
|
|
struct nb_cb_modify_args *args)
|
|
{
|
|
struct vrf *vrf;
|
|
struct pim_instance *pim;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
vrf = nb_running_get_entry(args->dnode, NULL, true);
|
|
pim = vrf->info;
|
|
pim->keep_alive_time = yang_dnode_get_uint16(args->dnode, NULL);
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/rp-keep-alive-timer
|
|
*/
|
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_keep_alive_timer_modify(
|
|
struct nb_cb_modify_args *args)
|
|
{
|
|
struct vrf *vrf;
|
|
struct pim_instance *pim;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
vrf = nb_running_get_entry(args->dnode, NULL, true);
|
|
pim = vrf->info;
|
|
pim->rp_keep_alive_time = yang_dnode_get_uint16(args->dnode,
|
|
NULL);
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family
|
|
*/
|
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_create(
|
|
struct nb_cb_create_args *args)
|
|
{
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
case NB_EV_APPLY:
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_destroy(
|
|
struct nb_cb_destroy_args *args)
|
|
{
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
case NB_EV_APPLY:
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/send-v6-secondary
|
|
*/
|
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_send_v6_secondary_modify(
|
|
struct nb_cb_modify_args *args)
|
|
{
|
|
struct vrf *vrf;
|
|
struct pim_instance *pim;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
vrf = nb_running_get_entry(args->dnode, NULL, true);
|
|
pim = vrf->info;
|
|
pim->send_v6_secondary = yang_dnode_get_bool(args->dnode, NULL);
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_send_v6_secondary_destroy(
|
|
struct nb_cb_destroy_args *args)
|
|
{
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
case NB_EV_APPLY:
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath:
|
|
* /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/spt-switchover
|
|
*/
|
|
void routing_control_plane_protocols_control_plane_protocol_pim_address_family_spt_switchover_apply_finish(
|
|
struct nb_cb_apply_finish_args *args)
|
|
{
|
|
struct vrf *vrf;
|
|
struct pim_instance *pim;
|
|
int spt_switch_action;
|
|
const char *prefix_list = NULL;
|
|
|
|
vrf = nb_running_get_entry(args->dnode, NULL, true);
|
|
pim = vrf->info;
|
|
spt_switch_action = yang_dnode_get_enum(args->dnode, "spt-action");
|
|
|
|
switch (spt_switch_action) {
|
|
case PIM_SPT_INFINITY:
|
|
if (yang_dnode_exists(args->dnode,
|
|
"./spt-infinity-prefix-list"))
|
|
prefix_list = yang_dnode_get_string(
|
|
args->dnode, "./spt-infinity-prefix-list");
|
|
|
|
pim_cmd_spt_switchover(pim, PIM_SPT_INFINITY,
|
|
prefix_list);
|
|
break;
|
|
case PIM_SPT_IMMEDIATE:
|
|
pim_cmd_spt_switchover(pim, PIM_SPT_IMMEDIATE, NULL);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/spt-switchover/spt-action
|
|
*/
|
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_spt_switchover_spt_action_modify(
|
|
struct nb_cb_modify_args *args)
|
|
{
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
case NB_EV_APPLY:
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/spt-switchover/spt-infinity-prefix-list
|
|
*/
|
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_spt_switchover_spt_infinity_prefix_list_modify(
|
|
struct nb_cb_modify_args *args)
|
|
{
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
case NB_EV_APPLY:
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_spt_switchover_spt_infinity_prefix_list_destroy(
|
|
struct nb_cb_destroy_args *args)
|
|
{
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
case NB_EV_APPLY:
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/ssm-prefix-list
|
|
*/
|
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_ssm_prefix_list_modify(
|
|
struct nb_cb_modify_args *args)
|
|
{
|
|
struct vrf *vrf;
|
|
struct pim_instance *pim;
|
|
const char *plist_name;
|
|
int result;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
vrf = nb_running_get_entry(args->dnode, NULL, true);
|
|
pim = vrf->info;
|
|
plist_name = yang_dnode_get_string(args->dnode, NULL);
|
|
result = pim_ssm_cmd_worker(pim, plist_name, args->errmsg,
|
|
args->errmsg_len);
|
|
|
|
if (result)
|
|
return NB_ERR_INCONSISTENCY;
|
|
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_ssm_prefix_list_destroy(
|
|
struct nb_cb_destroy_args *args)
|
|
{
|
|
struct vrf *vrf;
|
|
struct pim_instance *pim;
|
|
int result;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
vrf = nb_running_get_entry(args->dnode, NULL, true);
|
|
pim = vrf->info;
|
|
result = pim_ssm_cmd_worker(pim, NULL, args->errmsg,
|
|
args->errmsg_len);
|
|
|
|
if (result)
|
|
return NB_ERR_INCONSISTENCY;
|
|
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/ssm-pingd-source-ip
|
|
*/
|
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_ssm_pingd_source_ip_create(
|
|
struct nb_cb_create_args *args)
|
|
{
|
|
struct vrf *vrf;
|
|
struct pim_instance *pim;
|
|
int result;
|
|
pim_addr source_addr;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
vrf = nb_running_get_entry(args->dnode, NULL, true);
|
|
pim = vrf->info;
|
|
yang_dnode_get_pimaddr(&source_addr, args->dnode, NULL);
|
|
result = pim_ssmpingd_start(pim, source_addr);
|
|
if (result) {
|
|
snprintf(
|
|
args->errmsg, args->errmsg_len,
|
|
"%% Failure starting ssmpingd for source %pPA: %d",
|
|
&source_addr, result);
|
|
return NB_ERR_INCONSISTENCY;
|
|
}
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_ssm_pingd_source_ip_destroy(
|
|
struct nb_cb_destroy_args *args)
|
|
{
|
|
struct vrf *vrf;
|
|
struct pim_instance *pim;
|
|
int result;
|
|
pim_addr source_addr;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
vrf = nb_running_get_entry(args->dnode, NULL, true);
|
|
pim = vrf->info;
|
|
yang_dnode_get_pimaddr(&source_addr, args->dnode, NULL);
|
|
result = pim_ssmpingd_stop(pim, source_addr);
|
|
if (result) {
|
|
snprintf(
|
|
args->errmsg, args->errmsg_len,
|
|
"%% Failure stopping ssmpingd for source %pPA: %d",
|
|
&source_addr, result);
|
|
return NB_ERR_INCONSISTENCY;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath:
|
|
* /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp/hold-time
|
|
*/
|
|
int pim_msdp_hold_time_modify(struct nb_cb_modify_args *args)
|
|
{
|
|
struct pim_instance *pim;
|
|
struct vrf *vrf;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
vrf = nb_running_get_entry(args->dnode, NULL, true);
|
|
pim = vrf->info;
|
|
pim->msdp.hold_time = yang_dnode_get_uint16(args->dnode, NULL);
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath:
|
|
* /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp/keep-alive
|
|
*/
|
|
int pim_msdp_keep_alive_modify(struct nb_cb_modify_args *args)
|
|
{
|
|
struct pim_instance *pim;
|
|
struct vrf *vrf;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
vrf = nb_running_get_entry(args->dnode, NULL, true);
|
|
pim = vrf->info;
|
|
pim->msdp.keep_alive = yang_dnode_get_uint16(args->dnode, NULL);
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath:
|
|
* /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp/connection-retry
|
|
*/
|
|
int pim_msdp_connection_retry_modify(struct nb_cb_modify_args *args)
|
|
{
|
|
struct pim_instance *pim;
|
|
struct vrf *vrf;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
vrf = nb_running_get_entry(args->dnode, NULL, true);
|
|
pim = vrf->info;
|
|
pim->msdp.connection_retry =
|
|
yang_dnode_get_uint16(args->dnode, NULL);
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
pim6_msdp_err(pim_msdp_mesh_group_destroy, nb_cb_destroy_args);
|
|
pim6_msdp_err(pim_msdp_mesh_group_create, nb_cb_create_args);
|
|
pim6_msdp_err(pim_msdp_mesh_group_source_modify, nb_cb_modify_args);
|
|
pim6_msdp_err(pim_msdp_mesh_group_source_destroy, nb_cb_destroy_args);
|
|
pim6_msdp_err(pim_msdp_mesh_group_members_create, nb_cb_create_args);
|
|
pim6_msdp_err(pim_msdp_mesh_group_members_destroy, nb_cb_destroy_args);
|
|
pim6_msdp_err(routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_peer_source_ip_modify,
|
|
nb_cb_modify_args);
|
|
pim6_msdp_err(routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_peer_destroy,
|
|
nb_cb_destroy_args);
|
|
pim6_msdp_err(routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_peer_create,
|
|
nb_cb_create_args);
|
|
pim6_msdp_err(pim_msdp_peer_authentication_type_modify, nb_cb_modify_args);
|
|
pim6_msdp_err(pim_msdp_peer_authentication_key_modify, nb_cb_modify_args);
|
|
pim6_msdp_err(pim_msdp_peer_authentication_key_destroy, nb_cb_destroy_args);
|
|
|
|
#if PIM_IPV != 6
|
|
/*
|
|
* XPath:
|
|
* /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp-mesh-groups
|
|
*/
|
|
int pim_msdp_mesh_group_create(struct nb_cb_create_args *args)
|
|
{
|
|
struct pim_msdp_mg *mg;
|
|
struct vrf *vrf;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
vrf = nb_running_get_entry(args->dnode, NULL, true);
|
|
mg = pim_msdp_mg_new(vrf->info, yang_dnode_get_string(
|
|
args->dnode, "./name"));
|
|
nb_running_set_entry(args->dnode, mg);
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
int pim_msdp_mesh_group_destroy(struct nb_cb_destroy_args *args)
|
|
{
|
|
struct pim_msdp_mg *mg;
|
|
struct vrf *vrf;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
mg = nb_running_unset_entry(args->dnode);
|
|
vrf = nb_running_get_entry(args->dnode, NULL, true);
|
|
pim_msdp_mg_free(vrf->info, &mg);
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath:
|
|
* /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp-mesh-groups/source
|
|
*/
|
|
int pim_msdp_mesh_group_source_modify(struct nb_cb_modify_args *args)
|
|
{
|
|
const struct lyd_node *vrf_dnode;
|
|
struct pim_msdp_mg *mg;
|
|
struct vrf *vrf;
|
|
struct ipaddr ip;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
mg = nb_running_get_entry(args->dnode, NULL, true);
|
|
vrf_dnode =
|
|
yang_dnode_get_parent(args->dnode, "address-family");
|
|
vrf = nb_running_get_entry(vrf_dnode, "../../", true);
|
|
yang_dnode_get_ip(&ip, args->dnode, NULL);
|
|
|
|
pim_msdp_mg_src_add(vrf->info, mg, &ip.ip._v4_addr);
|
|
break;
|
|
}
|
|
return NB_OK;
|
|
}
|
|
|
|
int pim_msdp_mesh_group_source_destroy(struct nb_cb_destroy_args *args)
|
|
{
|
|
const struct lyd_node *vrf_dnode;
|
|
struct pim_msdp_mg *mg;
|
|
struct vrf *vrf;
|
|
struct in_addr addr;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
mg = nb_running_get_entry(args->dnode, NULL, true);
|
|
vrf_dnode =
|
|
yang_dnode_get_parent(args->dnode, "address-family");
|
|
vrf = nb_running_get_entry(vrf_dnode, "../../", true);
|
|
|
|
addr.s_addr = INADDR_ANY;
|
|
pim_msdp_mg_src_add(vrf->info, mg, &addr);
|
|
break;
|
|
}
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath:
|
|
* /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp-peer/authentication-type
|
|
*/
|
|
int pim_msdp_peer_authentication_type_modify(struct nb_cb_modify_args *args)
|
|
{
|
|
struct pim_msdp_peer *mp;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
/* NOTHING */
|
|
break;
|
|
case NB_EV_APPLY:
|
|
mp = nb_running_get_entry(args->dnode, NULL, true);
|
|
mp->auth_type = yang_dnode_get_enum(args->dnode, NULL);
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath:
|
|
* /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp-peer/authentication-key
|
|
*/
|
|
int pim_msdp_peer_authentication_key_modify(struct nb_cb_modify_args *args)
|
|
{
|
|
struct pim_msdp_peer *mp;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
if (strlen(yang_dnode_get_string(args->dnode, NULL)) >
|
|
TCP_MD5SIG_MAXKEYLEN) {
|
|
snprintf(args->errmsg, args->errmsg_len,
|
|
"MD5 authentication key too long");
|
|
return NB_ERR_VALIDATION;
|
|
}
|
|
break;
|
|
case NB_EV_APPLY:
|
|
mp = nb_running_get_entry(args->dnode, NULL, true);
|
|
XFREE(MTYPE_PIM_MSDP_AUTH_KEY, mp->auth_key);
|
|
mp->auth_key = XSTRDUP(MTYPE_PIM_MSDP_AUTH_KEY,
|
|
yang_dnode_get_string(args->dnode, NULL));
|
|
|
|
/* We must start listening the new authentication key now. */
|
|
if (PIM_MSDP_PEER_IS_LISTENER(mp))
|
|
pim_msdp_sock_auth_listen(mp);
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
int pim_msdp_peer_authentication_key_destroy(struct nb_cb_destroy_args *args)
|
|
{
|
|
struct pim_msdp_peer *mp;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
/* NOTHING */
|
|
break;
|
|
case NB_EV_APPLY:
|
|
mp = nb_running_get_entry(args->dnode, NULL, true);
|
|
XFREE(MTYPE_PIM_MSDP_AUTH_KEY, mp->auth_key);
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath:
|
|
* /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp-mesh-groups/members
|
|
*/
|
|
int pim_msdp_mesh_group_members_create(struct nb_cb_create_args *args)
|
|
{
|
|
const struct lyd_node *vrf_dnode;
|
|
struct pim_msdp_mg_mbr *mbr;
|
|
struct pim_msdp_mg *mg;
|
|
struct vrf *vrf;
|
|
struct ipaddr ip;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
mg = nb_running_get_entry(args->dnode, NULL, true);
|
|
vrf_dnode =
|
|
yang_dnode_get_parent(args->dnode, "address-family");
|
|
vrf = nb_running_get_entry(vrf_dnode, "../../", true);
|
|
yang_dnode_get_ip(&ip, args->dnode, "address");
|
|
|
|
mbr = pim_msdp_mg_mbr_add(vrf->info, mg, &ip.ip._v4_addr);
|
|
nb_running_set_entry(args->dnode, mbr);
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
int pim_msdp_mesh_group_members_destroy(struct nb_cb_destroy_args *args)
|
|
{
|
|
struct pim_msdp_mg_mbr *mbr;
|
|
struct pim_msdp_mg *mg;
|
|
const struct lyd_node *mg_dnode;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
mbr = nb_running_get_entry(args->dnode, NULL, true);
|
|
mg_dnode =
|
|
yang_dnode_get_parent(args->dnode, "msdp-mesh-groups");
|
|
mg = nb_running_get_entry(mg_dnode, NULL, true);
|
|
pim_msdp_mg_mbr_del(mg, mbr);
|
|
nb_running_unset_entry(args->dnode);
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp-peer
|
|
*/
|
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_peer_create(
|
|
struct nb_cb_create_args *args)
|
|
{
|
|
struct pim_msdp_peer *mp;
|
|
struct pim_instance *pim;
|
|
struct vrf *vrf;
|
|
struct ipaddr peer_ip;
|
|
struct ipaddr source_ip;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
vrf = nb_running_get_entry(args->dnode, NULL, true);
|
|
pim = vrf->info;
|
|
yang_dnode_get_ip(&peer_ip, args->dnode, "peer-ip");
|
|
yang_dnode_get_ip(&source_ip, args->dnode, "source-ip");
|
|
mp = pim_msdp_peer_add(pim, &peer_ip.ipaddr_v4,
|
|
&source_ip.ipaddr_v4, NULL);
|
|
nb_running_set_entry(args->dnode, mp);
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_peer_destroy(
|
|
struct nb_cb_destroy_args *args)
|
|
{
|
|
struct pim_msdp_peer *mp;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
mp = nb_running_unset_entry(args->dnode);
|
|
pim_msdp_peer_del(&mp);
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp-peer/source-ip
|
|
*/
|
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_peer_source_ip_modify(
|
|
struct nb_cb_modify_args *args)
|
|
{
|
|
struct pim_msdp_peer *mp;
|
|
struct ipaddr source_ip;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
mp = nb_running_get_entry(args->dnode, NULL, true);
|
|
yang_dnode_get_ip(&source_ip, args->dnode, NULL);
|
|
pim_msdp_peer_change_source(mp, &source_ip.ipaddr_v4);
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
#endif /* PIM_IPV != 6 */
|
|
|
|
/*
|
|
* XPath:
|
|
* /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp-peer/sa-filter-in
|
|
*/
|
|
int pim_msdp_peer_sa_filter_in_modify(struct nb_cb_modify_args *args)
|
|
{
|
|
struct pim_msdp_peer *mp;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
/* NOTHING */
|
|
break;
|
|
case NB_EV_APPLY:
|
|
mp = nb_running_get_entry(args->dnode, NULL, true);
|
|
XFREE(MTYPE_TMP, mp->acl_in);
|
|
mp->acl_in = XSTRDUP(MTYPE_TMP,
|
|
yang_dnode_get_string(args->dnode, NULL));
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
int pim_msdp_peer_sa_filter_in_destroy(struct nb_cb_destroy_args *args)
|
|
{
|
|
struct pim_msdp_peer *mp;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
/* NOTHING */
|
|
break;
|
|
case NB_EV_APPLY:
|
|
mp = nb_running_get_entry(args->dnode, NULL, true);
|
|
XFREE(MTYPE_TMP, mp->acl_in);
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath:
|
|
* /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp-peer/sa-filter-out
|
|
*/
|
|
int pim_msdp_peer_sa_filter_out_modify(struct nb_cb_modify_args *args)
|
|
{
|
|
struct pim_msdp_peer *mp;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
/* NOTHING */
|
|
break;
|
|
case NB_EV_APPLY:
|
|
mp = nb_running_get_entry(args->dnode, NULL, true);
|
|
XFREE(MTYPE_TMP, mp->acl_out);
|
|
mp->acl_out = XSTRDUP(MTYPE_TMP,
|
|
yang_dnode_get_string(args->dnode, NULL));
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
int pim_msdp_peer_sa_filter_out_destroy(struct nb_cb_destroy_args *args)
|
|
{
|
|
struct pim_msdp_peer *mp;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
/* NOTHING */
|
|
break;
|
|
case NB_EV_APPLY:
|
|
mp = nb_running_get_entry(args->dnode, NULL, true);
|
|
XFREE(MTYPE_TMP, mp->acl_out);
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/mlag
|
|
*/
|
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_create(
|
|
struct nb_cb_create_args *args)
|
|
{
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
case NB_EV_APPLY:
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_destroy(
|
|
struct nb_cb_destroy_args *args)
|
|
{
|
|
struct in_addr addr;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
addr.s_addr = 0;
|
|
pim_vxlan_mlag_update(true/*mlag_enable*/,
|
|
false/*peer_state*/, MLAG_ROLE_NONE,
|
|
NULL/*peerlink*/, &addr);
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath:
|
|
* /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/mlag
|
|
*/
|
|
void routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_apply_finish(
|
|
struct nb_cb_apply_finish_args *args)
|
|
{
|
|
const char *ifname;
|
|
uint32_t role;
|
|
bool peer_state;
|
|
struct interface *ifp;
|
|
struct ipaddr reg_addr;
|
|
|
|
ifname = yang_dnode_get_string(args->dnode, "peerlink-rif");
|
|
ifp = if_lookup_by_name(ifname, VRF_DEFAULT);
|
|
if (!ifp) {
|
|
snprintf(args->errmsg, args->errmsg_len,
|
|
"No such interface name %s", ifname);
|
|
return;
|
|
}
|
|
role = yang_dnode_get_enum(args->dnode, "my-role");
|
|
peer_state = yang_dnode_get_bool(args->dnode, "peer-state");
|
|
yang_dnode_get_ip(®_addr, args->dnode, "reg-address");
|
|
|
|
pim_vxlan_mlag_update(true, peer_state, role, ifp,
|
|
®_addr.ip._v4_addr);
|
|
}
|
|
|
|
|
|
/*
|
|
* XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/mlag/peerlink-rif
|
|
*/
|
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_peerlink_rif_modify(
|
|
struct nb_cb_modify_args *args)
|
|
{
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
case NB_EV_APPLY:
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_peerlink_rif_destroy(
|
|
struct nb_cb_destroy_args *args)
|
|
{
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
case NB_EV_APPLY:
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/mlag/reg-address
|
|
*/
|
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_reg_address_modify(
|
|
struct nb_cb_modify_args *args)
|
|
{
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
case NB_EV_APPLY:
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_reg_address_destroy(
|
|
struct nb_cb_destroy_args *args)
|
|
{
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
case NB_EV_APPLY:
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/mlag/my-role
|
|
*/
|
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_my_role_modify(
|
|
struct nb_cb_modify_args *args)
|
|
{
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
case NB_EV_APPLY:
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/mlag/peer-state
|
|
*/
|
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_peer_state_modify(
|
|
struct nb_cb_modify_args *args)
|
|
{
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
case NB_EV_APPLY:
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/register-accept-list
|
|
*/
|
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_register_accept_list_modify(
|
|
struct nb_cb_modify_args *args)
|
|
{
|
|
struct vrf *vrf;
|
|
struct pim_instance *pim;
|
|
const char *plist;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
vrf = nb_running_get_entry(args->dnode, NULL, true);
|
|
pim = vrf->info;
|
|
plist = yang_dnode_get_string(args->dnode, NULL);
|
|
|
|
XFREE(MTYPE_PIM_PLIST_NAME, pim->register_plist);
|
|
pim->register_plist = XSTRDUP(MTYPE_PIM_PLIST_NAME, plist);
|
|
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_register_accept_list_destroy(
|
|
struct nb_cb_destroy_args *args)
|
|
{
|
|
struct vrf *vrf;
|
|
struct pim_instance *pim;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
vrf = nb_running_get_entry(args->dnode, NULL, true);
|
|
pim = vrf->info;
|
|
|
|
XFREE(MTYPE_PIM_PLIST_NAME, pim->register_plist);
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath: /frr-interface:lib/interface/frr-pim:pim/address-family
|
|
*/
|
|
int lib_interface_pim_address_family_create(struct nb_cb_create_args *args)
|
|
{
|
|
struct interface *ifp;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_APPLY:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_PREPARE:
|
|
ifp = nb_running_get_entry(args->dnode, NULL, true);
|
|
if (ifp->info)
|
|
return NB_OK;
|
|
|
|
pim_if_new(ifp, false, false, false, false);
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
int lib_interface_pim_address_family_destroy(struct nb_cb_destroy_args *args)
|
|
{
|
|
struct interface *ifp;
|
|
struct pim_interface *pim_ifp;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
ifp = nb_running_get_entry(args->dnode, NULL, true);
|
|
pim_ifp = ifp->info;
|
|
if (!pim_ifp)
|
|
return NB_OK;
|
|
|
|
pim_pim_interface_delete(ifp);
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath: /frr-interface:lib/interface/frr-pim:pim/address-family/pim-enable
|
|
*/
|
|
int lib_interface_pim_address_family_pim_enable_modify(struct nb_cb_modify_args *args)
|
|
{
|
|
struct interface *ifp;
|
|
struct pim_interface *pim_ifp;
|
|
int mcast_if_count;
|
|
const struct lyd_node *if_dnode;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
if_dnode = yang_dnode_get_parent(args->dnode, "interface");
|
|
mcast_if_count =
|
|
yang_get_list_elements_count(if_dnode);
|
|
|
|
/* Limiting mcast interfaces to number of VIFs */
|
|
if (mcast_if_count == MAXVIFS) {
|
|
snprintf(args->errmsg, args->errmsg_len,
|
|
"Max multicast interfaces(%d) reached.",
|
|
MAXVIFS);
|
|
return NB_ERR_VALIDATION;
|
|
}
|
|
break;
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
ifp = nb_running_get_entry(args->dnode, NULL, true);
|
|
|
|
if (yang_dnode_get_bool(args->dnode, NULL)) {
|
|
if (!pim_cmd_interface_add(ifp)) {
|
|
snprintf(args->errmsg, args->errmsg_len,
|
|
"Could not enable PIM SM on interface %s",
|
|
ifp->name);
|
|
return NB_ERR_INCONSISTENCY;
|
|
}
|
|
} else {
|
|
pim_ifp = ifp->info;
|
|
if (!pim_ifp)
|
|
return NB_ERR_INCONSISTENCY;
|
|
|
|
pim_pim_interface_delete(ifp);
|
|
}
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath:
|
|
* /frr-interface:lib/interface/frr-pim:pim/address-family/pim-passive-enable
|
|
*/
|
|
int lib_interface_pim_address_family_pim_passive_enable_modify(
|
|
struct nb_cb_modify_args *args)
|
|
{
|
|
struct interface *ifp;
|
|
struct pim_interface *pim_ifp;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_ABORT:
|
|
case NB_EV_PREPARE:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
ifp = nb_running_get_entry(args->dnode, NULL, true);
|
|
pim_ifp = ifp->info;
|
|
pim_ifp->pim_passive_enable =
|
|
yang_dnode_get_bool(args->dnode, NULL);
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath: /frr-interface:lib/interface/frr-pim:pim/address-family/hello-interval
|
|
*/
|
|
int lib_interface_pim_address_family_hello_interval_modify(
|
|
struct nb_cb_modify_args *args)
|
|
{
|
|
struct interface *ifp;
|
|
struct pim_interface *pim_ifp;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_ABORT:
|
|
case NB_EV_PREPARE:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
ifp = nb_running_get_entry(args->dnode, NULL, true);
|
|
pim_ifp = ifp->info;
|
|
pim_ifp->pim_hello_period =
|
|
yang_dnode_get_uint16(args->dnode, NULL);
|
|
pim_ifp->pim_default_holdtime = -1;
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath: /frr-interface:lib/interface/frr-pim:pim/address-family/hello-holdtime
|
|
*/
|
|
int lib_interface_pim_address_family_hello_holdtime_modify(
|
|
struct nb_cb_modify_args *args)
|
|
{
|
|
struct interface *ifp;
|
|
struct pim_interface *pim_ifp;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_ABORT:
|
|
case NB_EV_PREPARE:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
ifp = nb_running_get_entry(args->dnode, NULL, true);
|
|
pim_ifp = ifp->info;
|
|
pim_ifp->pim_default_holdtime =
|
|
yang_dnode_get_uint16(args->dnode, NULL);
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
|
|
}
|
|
|
|
int lib_interface_pim_address_family_hello_holdtime_destroy(
|
|
struct nb_cb_destroy_args *args)
|
|
{
|
|
struct interface *ifp;
|
|
struct pim_interface *pim_ifp;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_ABORT:
|
|
case NB_EV_PREPARE:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
ifp = nb_running_get_entry(args->dnode, NULL, true);
|
|
pim_ifp = ifp->info;
|
|
pim_ifp->pim_default_holdtime = -1;
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
/*
|
|
* XPath: /frr-interface:lib/interface/frr-pim:pim/address-family/bfd
|
|
*/
|
|
int lib_interface_pim_address_family_bfd_create(struct nb_cb_create_args *args)
|
|
{
|
|
struct interface *ifp;
|
|
struct pim_interface *pim_ifp;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
/* NOTHING */
|
|
break;
|
|
case NB_EV_APPLY:
|
|
ifp = nb_running_get_entry(args->dnode, NULL, true);
|
|
pim_ifp = ifp->info;
|
|
pim_ifp->bfd_config.enabled = true;
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
int lib_interface_pim_address_family_bfd_destroy(
|
|
struct nb_cb_destroy_args *args)
|
|
{
|
|
struct interface *ifp;
|
|
struct pim_interface *pim_ifp;
|
|
const struct lyd_node *if_dnode;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
if_dnode = yang_dnode_get_parent(args->dnode, "interface");
|
|
if (!is_pim_interface(if_dnode)) {
|
|
snprintf(args->errmsg, args->errmsg_len,
|
|
"Pim not enabled on this interface");
|
|
return NB_ERR_VALIDATION;
|
|
}
|
|
break;
|
|
case NB_EV_ABORT:
|
|
case NB_EV_PREPARE:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
ifp = nb_running_get_entry(args->dnode, NULL, true);
|
|
pim_ifp = ifp->info;
|
|
pim_ifp->bfd_config.enabled = false;
|
|
pim_bfd_reg_dereg_all_nbr(ifp);
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath: /frr-interface:lib/interface/frr-pim:pim/address-family/bfd
|
|
*/
|
|
void lib_interface_pim_address_family_bfd_apply_finish(
|
|
struct nb_cb_apply_finish_args *args)
|
|
{
|
|
struct interface *ifp;
|
|
struct pim_interface *pim_ifp;
|
|
|
|
ifp = nb_running_get_entry(args->dnode, NULL, true);
|
|
pim_ifp = ifp->info;
|
|
|
|
if (!pim_ifp) {
|
|
zlog_debug("Pim not enabled on this interface");
|
|
return;
|
|
}
|
|
|
|
pim_ifp->bfd_config.detection_multiplier =
|
|
yang_dnode_get_uint8(args->dnode, "detect_mult");
|
|
pim_ifp->bfd_config.min_rx =
|
|
yang_dnode_get_uint16(args->dnode, "min-rx-interval");
|
|
pim_ifp->bfd_config.min_tx =
|
|
yang_dnode_get_uint16(args->dnode, "min-tx-interval");
|
|
|
|
pim_bfd_reg_dereg_all_nbr(ifp);
|
|
}
|
|
|
|
/*
|
|
* XPath: /frr-interface:lib/interface/frr-pim:pim/address-family/bfd/min-rx-interval
|
|
*/
|
|
int lib_interface_pim_address_family_bfd_min_rx_interval_modify(
|
|
struct nb_cb_modify_args *args)
|
|
{
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
case NB_EV_APPLY:
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath: /frr-interface:lib/interface/frr-pim:pim/address-family/bfd/min-tx-interval
|
|
*/
|
|
int lib_interface_pim_address_family_bfd_min_tx_interval_modify(
|
|
struct nb_cb_modify_args *args)
|
|
{
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
case NB_EV_APPLY:
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath: /frr-interface:lib/interface/frr-pim:pim/address-family/bfd/detect_mult
|
|
*/
|
|
int lib_interface_pim_address_family_bfd_detect_mult_modify(
|
|
struct nb_cb_modify_args *args)
|
|
{
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
case NB_EV_APPLY:
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath: /frr-interface:lib/interface/frr-pim:pim/address-family/bfd/profile
|
|
*/
|
|
int lib_interface_pim_address_family_bfd_profile_modify(
|
|
struct nb_cb_modify_args *args)
|
|
{
|
|
struct interface *ifp;
|
|
struct pim_interface *pim_ifp;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
/* NOTHING */
|
|
break;
|
|
case NB_EV_APPLY:
|
|
ifp = nb_running_get_entry(args->dnode, NULL, true);
|
|
pim_ifp = ifp->info;
|
|
XFREE(MTYPE_TMP, pim_ifp->bfd_config.profile);
|
|
pim_ifp->bfd_config.profile = XSTRDUP(
|
|
MTYPE_TMP, yang_dnode_get_string(args->dnode, NULL));
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
int lib_interface_pim_address_family_bfd_profile_destroy(
|
|
struct nb_cb_destroy_args *args)
|
|
{
|
|
struct interface *ifp;
|
|
struct pim_interface *pim_ifp;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
/* NOTHING */
|
|
break;
|
|
case NB_EV_APPLY:
|
|
ifp = nb_running_get_entry(args->dnode, NULL, true);
|
|
pim_ifp = ifp->info;
|
|
XFREE(MTYPE_TMP, pim_ifp->bfd_config.profile);
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath: /frr-interface:lib/interface/frr-pim:pim/address-family/bsm
|
|
*/
|
|
int lib_interface_pim_address_family_bsm_modify(struct nb_cb_modify_args *args)
|
|
{
|
|
struct interface *ifp;
|
|
struct pim_interface *pim_ifp;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
ifp = nb_running_get_entry(args->dnode, NULL, true);
|
|
pim_ifp = ifp->info;
|
|
if (!pim_ifp) {
|
|
pim_ifp = pim_if_new(ifp, false, true, false, false);
|
|
ifp->info = pim_ifp;
|
|
}
|
|
pim_ifp->bsm_enable = yang_dnode_get_bool(args->dnode, NULL);
|
|
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath: /frr-interface:lib/interface/frr-pim:pim/address-family/unicast-bsm
|
|
*/
|
|
int lib_interface_pim_address_family_unicast_bsm_modify(
|
|
struct nb_cb_modify_args *args)
|
|
{
|
|
struct interface *ifp;
|
|
struct pim_interface *pim_ifp;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
ifp = nb_running_get_entry(args->dnode, NULL, true);
|
|
pim_ifp = ifp->info;
|
|
if (!pim_ifp) {
|
|
pim_ifp = pim_if_new(ifp, false, true, false, false);
|
|
ifp->info = pim_ifp;
|
|
}
|
|
pim_ifp->ucast_bsm_accept =
|
|
yang_dnode_get_bool(args->dnode, NULL);
|
|
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath: /frr-interface:lib/interface/frr-pim:pim/address-family/active-active
|
|
*/
|
|
int lib_interface_pim_address_family_active_active_modify(
|
|
struct nb_cb_modify_args *args)
|
|
{
|
|
struct interface *ifp;
|
|
struct pim_interface *pim_ifp;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
ifp = nb_running_get_entry(args->dnode, NULL, true);
|
|
pim_ifp = ifp->info;
|
|
if (yang_dnode_get_bool(args->dnode, NULL)) {
|
|
if (PIM_DEBUG_MLAG)
|
|
zlog_debug(
|
|
"Configuring PIM active-active on Interface: %s",
|
|
ifp->name);
|
|
pim_if_configure_mlag_dualactive(pim_ifp);
|
|
} else {
|
|
if (PIM_DEBUG_MLAG)
|
|
zlog_debug(
|
|
"UnConfiguring PIM active-active on Interface: %s",
|
|
ifp->name);
|
|
pim_if_unconfigure_mlag_dualactive(pim_ifp);
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
|
|
}
|
|
|
|
/*
|
|
* XPath: /frr-interface:lib/interface/frr-pim:pim/address-family/dr-priority
|
|
*/
|
|
int lib_interface_pim_address_family_dr_priority_modify(
|
|
struct nb_cb_modify_args *args)
|
|
{
|
|
struct interface *ifp;
|
|
struct pim_interface *pim_ifp;
|
|
uint32_t old_dr_prio;
|
|
const struct lyd_node *if_dnode;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
if_dnode = yang_dnode_get_parent(args->dnode, "interface");
|
|
if (!is_pim_interface(if_dnode)) {
|
|
snprintf(args->errmsg, args->errmsg_len,
|
|
"Pim not enabled on this interface");
|
|
return NB_ERR_VALIDATION;
|
|
}
|
|
break;
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
ifp = nb_running_get_entry(args->dnode, NULL, true);
|
|
pim_ifp = ifp->info;
|
|
old_dr_prio = pim_ifp->pim_dr_priority;
|
|
pim_ifp->pim_dr_priority = yang_dnode_get_uint32(args->dnode,
|
|
NULL);
|
|
|
|
if (old_dr_prio != pim_ifp->pim_dr_priority) {
|
|
pim_if_dr_election(ifp);
|
|
pim_hello_restart_now(ifp);
|
|
}
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath: /frr-interface:lib/interface/frr-pim:pim/address-family/use-source
|
|
*/
|
|
int lib_interface_pim_address_family_use_source_modify(
|
|
struct nb_cb_modify_args *args)
|
|
{
|
|
struct interface *ifp;
|
|
pim_addr source_addr;
|
|
int result;
|
|
const struct lyd_node *if_dnode;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
if_dnode = yang_dnode_get_parent(args->dnode, "interface");
|
|
if (!is_pim_interface(if_dnode)) {
|
|
snprintf(args->errmsg, args->errmsg_len,
|
|
"Pim not enabled on this interface");
|
|
return NB_ERR_VALIDATION;
|
|
}
|
|
break;
|
|
case NB_EV_ABORT:
|
|
case NB_EV_PREPARE:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
ifp = nb_running_get_entry(args->dnode, NULL, true);
|
|
#if PIM_IPV == 4
|
|
yang_dnode_get_ipv4(&source_addr, args->dnode, NULL);
|
|
#else
|
|
yang_dnode_get_ipv6(&source_addr, args->dnode, NULL);
|
|
#endif
|
|
|
|
result = interface_pim_use_src_cmd_worker(
|
|
ifp, source_addr,
|
|
args->errmsg, args->errmsg_len);
|
|
|
|
if (result != PIM_SUCCESS)
|
|
return NB_ERR_INCONSISTENCY;
|
|
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
int lib_interface_pim_address_family_use_source_destroy(
|
|
struct nb_cb_destroy_args *args)
|
|
{
|
|
struct interface *ifp;
|
|
int result;
|
|
const struct lyd_node *if_dnode;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
if_dnode = yang_dnode_get_parent(args->dnode, "interface");
|
|
if (!is_pim_interface(if_dnode)) {
|
|
snprintf(args->errmsg, args->errmsg_len,
|
|
"Pim not enabled on this interface");
|
|
return NB_ERR_VALIDATION;
|
|
}
|
|
break;
|
|
case NB_EV_ABORT:
|
|
case NB_EV_PREPARE:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
ifp = nb_running_get_entry(args->dnode, NULL, true);
|
|
|
|
result = interface_pim_use_src_cmd_worker(ifp, PIMADDR_ANY,
|
|
args->errmsg,
|
|
args->errmsg_len);
|
|
|
|
if (result != PIM_SUCCESS)
|
|
return NB_ERR_INCONSISTENCY;
|
|
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath: /frr-interface:lib/interface/frr-pim:pim/address-family/multicast-boundary-oil
|
|
*/
|
|
int lib_interface_pim_address_family_multicast_boundary_oil_modify(
|
|
struct nb_cb_modify_args *args)
|
|
{
|
|
struct interface *ifp;
|
|
struct pim_interface *pim_ifp;
|
|
const char *plist;
|
|
const struct lyd_node *if_dnode;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
if_dnode = yang_dnode_get_parent(args->dnode, "interface");
|
|
if (!is_pim_interface(if_dnode)) {
|
|
snprintf(args->errmsg, args->errmsg_len,
|
|
"Pim not enabled on this interface");
|
|
return NB_ERR_VALIDATION;
|
|
}
|
|
break;
|
|
case NB_EV_ABORT:
|
|
case NB_EV_PREPARE:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
ifp = nb_running_get_entry(args->dnode, NULL, true);
|
|
pim_ifp = ifp->info;
|
|
plist = yang_dnode_get_string(args->dnode, NULL);
|
|
|
|
if (pim_ifp->boundary_oil_plist)
|
|
XFREE(MTYPE_PIM_INTERFACE, pim_ifp->boundary_oil_plist);
|
|
|
|
pim_ifp->boundary_oil_plist =
|
|
XSTRDUP(MTYPE_PIM_INTERFACE, plist);
|
|
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
int lib_interface_pim_address_family_multicast_boundary_oil_destroy(
|
|
struct nb_cb_destroy_args *args)
|
|
{
|
|
struct interface *ifp;
|
|
struct pim_interface *pim_ifp;
|
|
const struct lyd_node *if_dnode;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
if_dnode = yang_dnode_get_parent(args->dnode, "interface");
|
|
if (!is_pim_interface(if_dnode)) {
|
|
snprintf(args->errmsg, args->errmsg_len,
|
|
"%% Enable PIM and/or IGMP on this interface first");
|
|
return NB_ERR_VALIDATION;
|
|
}
|
|
break;
|
|
case NB_EV_ABORT:
|
|
case NB_EV_PREPARE:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
ifp = nb_running_get_entry(args->dnode, NULL, true);
|
|
pim_ifp = ifp->info;
|
|
if (pim_ifp->boundary_oil_plist)
|
|
XFREE(MTYPE_PIM_INTERFACE, pim_ifp->boundary_oil_plist);
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath: /frr-interface:lib/interface/frr-pim:pim/address-family/mroute
|
|
*/
|
|
int lib_interface_pim_address_family_mroute_create(
|
|
struct nb_cb_create_args *args)
|
|
{
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
case NB_EV_APPLY:
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
int lib_interface_pim_address_family_mroute_destroy(
|
|
struct nb_cb_destroy_args *args)
|
|
{
|
|
struct pim_instance *pim;
|
|
struct pim_interface *pim_iifp;
|
|
struct interface *iif;
|
|
struct interface *oif;
|
|
const char *oifname;
|
|
pim_addr source_addr;
|
|
pim_addr group_addr;
|
|
const struct lyd_node *if_dnode;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
if_dnode = yang_dnode_get_parent(args->dnode, "interface");
|
|
if (!is_pim_interface(if_dnode)) {
|
|
snprintf(args->errmsg, args->errmsg_len,
|
|
"%% Enable PIM and/or IGMP on this interface first");
|
|
return NB_ERR_VALIDATION;
|
|
}
|
|
break;
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
iif = nb_running_get_entry(args->dnode, NULL, true);
|
|
pim_iifp = iif->info;
|
|
pim = pim_iifp->pim;
|
|
|
|
oifname = yang_dnode_get_string(args->dnode, "oif");
|
|
oif = if_lookup_by_name(oifname, pim->vrf->vrf_id);
|
|
|
|
if (!oif) {
|
|
snprintf(args->errmsg, args->errmsg_len,
|
|
"No such interface name %s",
|
|
oifname);
|
|
return NB_ERR_INCONSISTENCY;
|
|
}
|
|
|
|
yang_dnode_get_pimaddr(&source_addr, args->dnode, "source-addr");
|
|
yang_dnode_get_pimaddr(&group_addr, args->dnode, "group-addr");
|
|
|
|
if (pim_static_del(pim, iif, oif, group_addr, source_addr)) {
|
|
snprintf(args->errmsg, args->errmsg_len,
|
|
"Failed to remove static mroute");
|
|
return NB_ERR_INCONSISTENCY;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath: /frr-interface:lib/interface/frr-pim:pim/address-family/mroute/oif
|
|
*/
|
|
int lib_interface_pim_address_family_mroute_oif_modify(
|
|
struct nb_cb_modify_args *args)
|
|
{
|
|
struct pim_instance *pim;
|
|
struct pim_interface *pim_iifp;
|
|
struct interface *iif;
|
|
struct interface *oif;
|
|
const char *oifname;
|
|
pim_addr source_addr;
|
|
pim_addr group_addr;
|
|
const struct lyd_node *if_dnode;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
if_dnode = yang_dnode_get_parent(args->dnode, "interface");
|
|
if (!is_pim_interface(if_dnode)) {
|
|
snprintf(args->errmsg, args->errmsg_len,
|
|
"%% Enable PIM and/or IGMP on this interface first");
|
|
return NB_ERR_VALIDATION;
|
|
}
|
|
|
|
#ifdef PIM_ENFORCE_LOOPFREE_MFC
|
|
iif = nb_running_get_entry(args->dnode, NULL, false);
|
|
if (!iif) {
|
|
return NB_OK;
|
|
}
|
|
|
|
pim_iifp = iif->info;
|
|
pim = pim_iifp->pim;
|
|
|
|
oifname = yang_dnode_get_string(args->dnode, NULL);
|
|
oif = if_lookup_by_name(oifname, pim->vrf->vrf_id);
|
|
|
|
if (oif && (iif->ifindex == oif->ifindex)) {
|
|
strlcpy(args->errmsg,
|
|
"% IIF same as OIF and loopfree enforcement is enabled; rejecting",
|
|
args->errmsg_len);
|
|
return NB_ERR_VALIDATION;
|
|
}
|
|
#endif
|
|
break;
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
iif = nb_running_get_entry(args->dnode, NULL, true);
|
|
pim_iifp = iif->info;
|
|
pim = pim_iifp->pim;
|
|
|
|
oifname = yang_dnode_get_string(args->dnode, NULL);
|
|
oif = if_lookup_by_name(oifname, pim->vrf->vrf_id);
|
|
if (!oif) {
|
|
snprintf(args->errmsg, args->errmsg_len,
|
|
"No such interface name %s",
|
|
oifname);
|
|
return NB_ERR_INCONSISTENCY;
|
|
}
|
|
|
|
yang_dnode_get_pimaddr(&source_addr, args->dnode, "../source-addr");
|
|
yang_dnode_get_pimaddr(&group_addr, args->dnode, "../group-addr");
|
|
|
|
if (pim_static_add(pim, iif, oif, group_addr, source_addr)) {
|
|
snprintf(args->errmsg, args->errmsg_len,
|
|
"Failed to add static mroute");
|
|
return NB_ERR_INCONSISTENCY;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
int lib_interface_pim_address_family_mroute_oif_destroy(
|
|
struct nb_cb_destroy_args *args)
|
|
{
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
case NB_EV_APPLY:
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/frr-pim-rp:rp/static-rp/rp-list
|
|
*/
|
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_static_rp_rp_list_create(
|
|
struct nb_cb_create_args *args)
|
|
{
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
case NB_EV_APPLY:
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_static_rp_rp_list_destroy(
|
|
struct nb_cb_destroy_args *args)
|
|
{
|
|
struct vrf *vrf;
|
|
struct pim_instance *pim;
|
|
struct prefix group;
|
|
pim_addr rp_addr;
|
|
const char *plist;
|
|
int result = 0;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
vrf = nb_running_get_entry(args->dnode, NULL, true);
|
|
pim = vrf->info;
|
|
yang_dnode_get_pimaddr(&rp_addr, args->dnode, "rp-address");
|
|
|
|
if (yang_dnode_get(args->dnode, "group-list")) {
|
|
yang_dnode_get_prefix(&group, args->dnode,
|
|
"./group-list");
|
|
apply_mask(&group);
|
|
result = pim_no_rp_cmd_worker(pim, rp_addr, group, NULL,
|
|
args->errmsg,
|
|
args->errmsg_len);
|
|
}
|
|
|
|
else if (yang_dnode_get(args->dnode, "prefix-list")) {
|
|
plist = yang_dnode_get_string(args->dnode,
|
|
"./prefix-list");
|
|
if (!pim_get_all_mcast_group(&group)) {
|
|
flog_err(
|
|
EC_LIB_DEVELOPMENT,
|
|
"Unable to convert 224.0.0.0/4 to prefix");
|
|
return NB_ERR_INCONSISTENCY;
|
|
}
|
|
|
|
result = pim_no_rp_cmd_worker(pim, rp_addr, group,
|
|
plist, args->errmsg,
|
|
args->errmsg_len);
|
|
}
|
|
|
|
if (result)
|
|
return NB_ERR_INCONSISTENCY;
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* 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
|
|
*/
|
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_static_rp_rp_list_group_list_create(
|
|
struct nb_cb_create_args *args)
|
|
{
|
|
struct vrf *vrf;
|
|
struct pim_instance *pim;
|
|
struct prefix group;
|
|
pim_addr rp_addr;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
vrf = nb_running_get_entry(args->dnode, NULL, true);
|
|
pim = vrf->info;
|
|
yang_dnode_get_pimaddr(&rp_addr, args->dnode, "../rp-address");
|
|
yang_dnode_get_prefix(&group, args->dnode, NULL);
|
|
apply_mask(&group);
|
|
return pim_rp_cmd_worker(pim, rp_addr, group, NULL,
|
|
args->errmsg, args->errmsg_len);
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_static_rp_rp_list_group_list_destroy(
|
|
struct nb_cb_destroy_args *args)
|
|
{
|
|
struct vrf *vrf;
|
|
struct pim_instance *pim;
|
|
struct prefix group;
|
|
pim_addr rp_addr;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
vrf = nb_running_get_entry(args->dnode, NULL, true);
|
|
pim = vrf->info;
|
|
yang_dnode_get_pimaddr(&rp_addr, args->dnode, "../rp-address");
|
|
yang_dnode_get_prefix(&group, args->dnode, NULL);
|
|
apply_mask(&group);
|
|
|
|
return pim_no_rp_cmd_worker(pim, rp_addr, group, NULL,
|
|
args->errmsg, args->errmsg_len);
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* 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
|
|
*/
|
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_static_rp_rp_list_prefix_list_modify(
|
|
struct nb_cb_modify_args *args)
|
|
{
|
|
struct vrf *vrf;
|
|
struct pim_instance *pim;
|
|
struct prefix group;
|
|
pim_addr rp_addr;
|
|
const char *plist;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
vrf = nb_running_get_entry(args->dnode, NULL, true);
|
|
pim = vrf->info;
|
|
plist = yang_dnode_get_string(args->dnode, NULL);
|
|
yang_dnode_get_pimaddr(&rp_addr, args->dnode, "../rp-address");
|
|
if (!pim_get_all_mcast_group(&group)) {
|
|
flog_err(EC_LIB_DEVELOPMENT,
|
|
"Unable to convert 224.0.0.0/4 to prefix");
|
|
return NB_ERR_INCONSISTENCY;
|
|
}
|
|
return pim_rp_cmd_worker(pim, rp_addr, group, plist,
|
|
args->errmsg, args->errmsg_len);
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_static_rp_rp_list_prefix_list_destroy(
|
|
struct nb_cb_destroy_args *args)
|
|
{
|
|
struct vrf *vrf;
|
|
struct pim_instance *pim;
|
|
struct prefix group;
|
|
pim_addr rp_addr;
|
|
const char *plist;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
vrf = nb_running_get_entry(args->dnode, NULL, true);
|
|
pim = vrf->info;
|
|
yang_dnode_get_pimaddr(&rp_addr, args->dnode, "../rp-address");
|
|
plist = yang_dnode_get_string(args->dnode, NULL);
|
|
if (!pim_get_all_mcast_group(&group)) {
|
|
flog_err(EC_LIB_DEVELOPMENT,
|
|
"Unable to convert 224.0.0.0/4 to prefix");
|
|
return NB_ERR_INCONSISTENCY;
|
|
}
|
|
return pim_no_rp_cmd_worker(pim, rp_addr, group, plist,
|
|
args->errmsg, args->errmsg_len);
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/frr-pim-rp:rp/auto-rp/discovery-enabled
|
|
*/
|
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_discovery_enabled_modify(
|
|
struct nb_cb_modify_args *args)
|
|
{
|
|
#if PIM_IPV == 4
|
|
struct vrf *vrf;
|
|
struct pim_instance *pim;
|
|
bool enabled;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
vrf = nb_running_get_entry(args->dnode, NULL, true);
|
|
pim = vrf->info;
|
|
enabled = yang_dnode_get_bool(args->dnode, NULL);
|
|
if (enabled)
|
|
pim_autorp_start_discovery(pim);
|
|
else
|
|
pim_autorp_stop_discovery(pim);
|
|
break;
|
|
}
|
|
#endif
|
|
|
|
return NB_OK;
|
|
}
|
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_discovery_enabled_destroy(
|
|
struct nb_cb_destroy_args *args)
|
|
{
|
|
#if PIM_IPV == 4
|
|
struct vrf *vrf;
|
|
struct pim_instance *pim;
|
|
bool enabled;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
vrf = nb_running_get_entry(args->dnode, NULL, true);
|
|
pim = vrf->info;
|
|
enabled = yang_dnode_get_bool(args->dnode, NULL);
|
|
/* Run AutoRP discovery by default */
|
|
if (!enabled)
|
|
pim_autorp_start_discovery(pim);
|
|
break;
|
|
}
|
|
#endif
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/frr-pim-rp:rp/auto-rp/announce-scope
|
|
*/
|
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_announce_scope_modify(
|
|
struct nb_cb_modify_args *args)
|
|
{
|
|
#if PIM_IPV == 4
|
|
struct vrf *vrf;
|
|
struct pim_instance *pim;
|
|
uint8_t scope;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
vrf = nb_running_get_entry(args->dnode, NULL, true);
|
|
pim = vrf->info;
|
|
scope = yang_dnode_get_uint8(args->dnode, NULL);
|
|
pim_autorp_announce_scope(pim, scope);
|
|
}
|
|
#endif
|
|
|
|
return NB_OK;
|
|
}
|
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_announce_scope_destroy(
|
|
struct nb_cb_destroy_args *args)
|
|
{
|
|
#if PIM_IPV == 4
|
|
struct vrf *vrf;
|
|
struct pim_instance *pim;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
vrf = nb_running_get_entry(args->dnode, NULL, true);
|
|
pim = vrf->info;
|
|
pim_autorp_announce_scope(pim, 0);
|
|
}
|
|
#endif
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/frr-pim-rp:rp/auto-rp/announce-interval
|
|
*/
|
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_announce_interval_modify(
|
|
struct nb_cb_modify_args *args)
|
|
{
|
|
#if PIM_IPV == 4
|
|
struct vrf *vrf;
|
|
struct pim_instance *pim;
|
|
uint16_t interval;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
vrf = nb_running_get_entry(args->dnode, NULL, true);
|
|
pim = vrf->info;
|
|
interval = yang_dnode_get_uint16(args->dnode, NULL);
|
|
pim_autorp_announce_interval(pim, interval);
|
|
}
|
|
#endif
|
|
|
|
return NB_OK;
|
|
}
|
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_announce_interval_destroy(
|
|
struct nb_cb_destroy_args *args)
|
|
{
|
|
#if PIM_IPV == 4
|
|
struct vrf *vrf;
|
|
struct pim_instance *pim;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
vrf = nb_running_get_entry(args->dnode, NULL, true);
|
|
pim = vrf->info;
|
|
pim_autorp_announce_interval(pim, 0);
|
|
}
|
|
#endif
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/frr-pim-rp:rp/auto-rp/announce-holdtime
|
|
*/
|
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_announce_holdtime_modify(
|
|
struct nb_cb_modify_args *args)
|
|
{
|
|
#if PIM_IPV == 4
|
|
struct vrf *vrf;
|
|
struct pim_instance *pim;
|
|
uint16_t holdtime;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
vrf = nb_running_get_entry(args->dnode, NULL, true);
|
|
pim = vrf->info;
|
|
holdtime = yang_dnode_get_uint16(args->dnode, NULL);
|
|
pim_autorp_announce_holdtime(pim, holdtime);
|
|
}
|
|
#endif
|
|
|
|
return NB_OK;
|
|
}
|
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_announce_holdtime_destroy(
|
|
struct nb_cb_destroy_args *args)
|
|
{
|
|
#if PIM_IPV == 4
|
|
struct vrf *vrf;
|
|
struct pim_instance *pim;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
vrf = nb_running_get_entry(args->dnode, NULL, true);
|
|
pim = vrf->info;
|
|
/* 0 is a valid value, so -1 indicates deleting (go back to default) */
|
|
pim_autorp_announce_holdtime(pim, -1);
|
|
}
|
|
#endif
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/frr-pim-rp:rp/auto-rp/candidate-rp-list
|
|
*/
|
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_candidate_rp_list_create(
|
|
struct nb_cb_create_args *args)
|
|
{
|
|
#if PIM_IPV == 4
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
case NB_EV_APPLY:
|
|
break;
|
|
}
|
|
#endif
|
|
|
|
return NB_OK;
|
|
}
|
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_candidate_rp_list_destroy(
|
|
struct nb_cb_destroy_args *args)
|
|
{
|
|
#if PIM_IPV == 4
|
|
struct vrf *vrf;
|
|
struct pim_instance *pim;
|
|
pim_addr rp_addr;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
vrf = nb_running_get_entry(args->dnode, NULL, true);
|
|
pim = vrf->info;
|
|
yang_dnode_get_pimaddr(&rp_addr, args->dnode, "rp-address");
|
|
if (!pim_autorp_rm_candidate_rp(pim, rp_addr))
|
|
return NB_ERR_INCONSISTENCY;
|
|
break;
|
|
}
|
|
#endif
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/frr-pim-rp:rp/auto-rp/candidate-rp-list/group
|
|
*/
|
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_candidate_rp_list_group_modify(
|
|
struct nb_cb_modify_args *args)
|
|
{
|
|
#if PIM_IPV == 4
|
|
struct vrf *vrf;
|
|
struct pim_instance *pim;
|
|
struct prefix group;
|
|
pim_addr rp_addr;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
vrf = nb_running_get_entry(args->dnode, NULL, true);
|
|
pim = vrf->info;
|
|
yang_dnode_get_pimaddr(&rp_addr, args->dnode, "../rp-address");
|
|
yang_dnode_get_prefix(&group, args->dnode, NULL);
|
|
apply_mask(&group);
|
|
pim_autorp_add_candidate_rp_group(pim, rp_addr, group);
|
|
}
|
|
#endif
|
|
|
|
return NB_OK;
|
|
}
|
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_candidate_rp_list_group_destroy(
|
|
struct nb_cb_destroy_args *args)
|
|
{
|
|
#if PIM_IPV == 4
|
|
struct vrf *vrf;
|
|
struct pim_instance *pim;
|
|
struct prefix group;
|
|
pim_addr rp_addr;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
vrf = nb_running_get_entry(args->dnode, NULL, true);
|
|
pim = vrf->info;
|
|
yang_dnode_get_pimaddr(&rp_addr, args->dnode, "../rp-address");
|
|
yang_dnode_get_prefix(&group, args->dnode, NULL);
|
|
apply_mask(&group);
|
|
if (!pim_autorp_rm_candidate_rp_group(pim, rp_addr, group))
|
|
return NB_ERR_INCONSISTENCY;
|
|
}
|
|
#endif
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/frr-pim-rp:rp/auto-rp/candidate-rp-list/prefix-list
|
|
*/
|
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_candidate_rp_list_prefix_list_modify(
|
|
struct nb_cb_modify_args *args)
|
|
{
|
|
#if PIM_IPV == 4
|
|
struct vrf *vrf;
|
|
struct pim_instance *pim;
|
|
pim_addr rp_addr;
|
|
const char *plist;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
vrf = nb_running_get_entry(args->dnode, NULL, true);
|
|
pim = vrf->info;
|
|
plist = yang_dnode_get_string(args->dnode, NULL);
|
|
yang_dnode_get_pimaddr(&rp_addr, args->dnode, "../rp-address");
|
|
pim_autorp_add_candidate_rp_plist(pim, rp_addr, plist);
|
|
}
|
|
#endif
|
|
|
|
return NB_OK;
|
|
}
|
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_auto_rp_candidate_rp_list_prefix_list_destroy(
|
|
struct nb_cb_destroy_args *args)
|
|
{
|
|
#if PIM_IPV == 4
|
|
struct vrf *vrf;
|
|
struct pim_instance *pim;
|
|
pim_addr rp_addr;
|
|
const char *plist;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
vrf = nb_running_get_entry(args->dnode, NULL, true);
|
|
pim = vrf->info;
|
|
yang_dnode_get_pimaddr(&rp_addr, args->dnode, "../rp-address");
|
|
plist = yang_dnode_get_string(args->dnode, NULL);
|
|
if (!pim_autorp_rm_candidate_rp_plist(pim, rp_addr, plist))
|
|
return NB_ERR_INCONSISTENCY;
|
|
break;
|
|
}
|
|
#endif
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
static void yang_addrsel(struct cand_addrsel *addrsel,
|
|
const struct lyd_node *node)
|
|
{
|
|
memset(addrsel->cfg_ifname, 0, sizeof(addrsel->cfg_ifname));
|
|
addrsel->cfg_addr = PIMADDR_ANY;
|
|
|
|
if (yang_dnode_exists(node, "if-any")) {
|
|
addrsel->cfg_mode = CAND_ADDR_ANY;
|
|
} else if (yang_dnode_exists(node, "address")) {
|
|
addrsel->cfg_mode = CAND_ADDR_EXPLICIT;
|
|
yang_dnode_get_pimaddr(&addrsel->cfg_addr, node, "address");
|
|
} else if (yang_dnode_exists(node, "interface")) {
|
|
addrsel->cfg_mode = CAND_ADDR_IFACE;
|
|
strlcpy(addrsel->cfg_ifname,
|
|
yang_dnode_get_string(node, "interface"),
|
|
sizeof(addrsel->cfg_ifname));
|
|
} else if (yang_dnode_exists(node, "if-loopback")) {
|
|
addrsel->cfg_mode = CAND_ADDR_LO;
|
|
}
|
|
}
|
|
|
|
static int candidate_bsr_addrsel(struct bsm_scope *scope,
|
|
const struct lyd_node *cand_bsr_node)
|
|
{
|
|
yang_addrsel(&scope->bsr_addrsel, cand_bsr_node);
|
|
pim_cand_bsr_apply(scope);
|
|
return NB_OK;
|
|
}
|
|
|
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_candidate_bsr_create(
|
|
struct nb_cb_create_args *args)
|
|
{
|
|
struct vrf *vrf;
|
|
struct pim_instance *pim;
|
|
struct bsm_scope *scope;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
vrf = nb_running_get_entry(args->dnode, NULL, true);
|
|
pim = vrf->info;
|
|
scope = &pim->global_scope;
|
|
|
|
scope->bsr_addrsel.cfg_enable = true;
|
|
scope->cand_bsr_prio = yang_dnode_get_uint8(args->dnode,
|
|
"bsr-priority");
|
|
|
|
candidate_bsr_addrsel(scope, args->dnode);
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_candidate_bsr_destroy(
|
|
struct nb_cb_destroy_args *args)
|
|
{
|
|
struct vrf *vrf;
|
|
struct pim_instance *pim;
|
|
struct bsm_scope *scope;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
vrf = nb_running_get_entry(args->dnode, NULL, true);
|
|
pim = vrf->info;
|
|
scope = &pim->global_scope;
|
|
|
|
scope->bsr_addrsel.cfg_enable = false;
|
|
|
|
pim_cand_bsr_apply(scope);
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_candidate_bsr_priority_modify(
|
|
struct nb_cb_modify_args *args)
|
|
{
|
|
struct vrf *vrf;
|
|
struct pim_instance *pim;
|
|
struct bsm_scope *scope;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
vrf = nb_running_get_entry(args->dnode, NULL, true);
|
|
pim = vrf->info;
|
|
scope = &pim->global_scope;
|
|
|
|
scope->cand_bsr_prio = yang_dnode_get_uint8(args->dnode, NULL);
|
|
|
|
/* FIXME: force prio update */
|
|
candidate_bsr_addrsel(scope, args->dnode);
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_candidate_bsr_addrsel_create(
|
|
struct nb_cb_create_args *args)
|
|
{
|
|
struct vrf *vrf;
|
|
struct pim_instance *pim;
|
|
struct bsm_scope *scope;
|
|
const struct lyd_node *cand_bsr_node;
|
|
|
|
cand_bsr_node = yang_dnode_get_parent(args->dnode, "candidate-bsr");
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
vrf = nb_running_get_entry(args->dnode, NULL, true);
|
|
pim = vrf->info;
|
|
scope = &pim->global_scope;
|
|
|
|
return candidate_bsr_addrsel(scope, cand_bsr_node);
|
|
}
|
|
return NB_OK;
|
|
}
|
|
|
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_candidate_bsr_addrsel_modify(
|
|
struct nb_cb_modify_args *args)
|
|
{
|
|
struct vrf *vrf;
|
|
struct pim_instance *pim;
|
|
struct bsm_scope *scope;
|
|
const struct lyd_node *cand_bsr_node;
|
|
|
|
cand_bsr_node = yang_dnode_get_parent(args->dnode, "candidate-bsr");
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
vrf = nb_running_get_entry(args->dnode, NULL, true);
|
|
pim = vrf->info;
|
|
scope = &pim->global_scope;
|
|
|
|
return candidate_bsr_addrsel(scope, cand_bsr_node);
|
|
}
|
|
return NB_OK;
|
|
}
|
|
|
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_candidate_bsr_addrsel_destroy(
|
|
struct nb_cb_destroy_args *args)
|
|
{
|
|
/* nothing to do here, we'll get a CREATE for something else */
|
|
return NB_OK;
|
|
}
|
|
|
|
static int candidate_rp_addrsel(struct bsm_scope *scope,
|
|
const struct lyd_node *cand_rp_node)
|
|
{
|
|
yang_addrsel(&scope->cand_rp_addrsel, cand_rp_node);
|
|
pim_cand_rp_apply(scope);
|
|
return NB_OK;
|
|
}
|
|
|
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_candidate_rp_create(
|
|
struct nb_cb_create_args *args)
|
|
{
|
|
struct vrf *vrf;
|
|
struct pim_instance *pim;
|
|
struct bsm_scope *scope;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
vrf = nb_running_get_entry(args->dnode, NULL, true);
|
|
pim = vrf->info;
|
|
scope = &pim->global_scope;
|
|
|
|
scope->cand_rp_addrsel.cfg_enable = true;
|
|
scope->cand_rp_prio = yang_dnode_get_uint8(args->dnode,
|
|
"rp-priority");
|
|
scope->cand_rp_interval =
|
|
yang_dnode_get_uint32(args->dnode,
|
|
"advertisement-interval");
|
|
|
|
candidate_rp_addrsel(scope, args->dnode);
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_candidate_rp_destroy(
|
|
struct nb_cb_destroy_args *args)
|
|
{
|
|
struct vrf *vrf;
|
|
struct pim_instance *pim;
|
|
struct bsm_scope *scope;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
vrf = nb_running_get_entry(args->dnode, NULL, true);
|
|
pim = vrf->info;
|
|
scope = &pim->global_scope;
|
|
|
|
scope->cand_rp_addrsel.cfg_enable = false;
|
|
|
|
pim_cand_rp_apply(scope);
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_candidate_rp_priority_modify(
|
|
struct nb_cb_modify_args *args)
|
|
{
|
|
struct vrf *vrf;
|
|
struct pim_instance *pim;
|
|
struct bsm_scope *scope;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
vrf = nb_running_get_entry(args->dnode, NULL, true);
|
|
pim = vrf->info;
|
|
scope = &pim->global_scope;
|
|
|
|
scope->cand_rp_prio = yang_dnode_get_uint8(args->dnode, NULL);
|
|
|
|
pim_cand_rp_trigger(scope);
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_candidate_rp_adv_interval_modify(
|
|
struct nb_cb_modify_args *args)
|
|
{
|
|
struct vrf *vrf;
|
|
struct pim_instance *pim;
|
|
struct bsm_scope *scope;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
vrf = nb_running_get_entry(args->dnode, NULL, true);
|
|
pim = vrf->info;
|
|
scope = &pim->global_scope;
|
|
|
|
scope->cand_rp_interval = yang_dnode_get_uint32(args->dnode,
|
|
NULL);
|
|
|
|
pim_cand_rp_trigger(scope);
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
#if PIM_IPV == 4
|
|
#define yang_dnode_get_pim_p yang_dnode_get_ipv4p
|
|
#else
|
|
#define yang_dnode_get_pim_p yang_dnode_get_ipv6p
|
|
#endif
|
|
|
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_candidate_rp_group_list_create(
|
|
struct nb_cb_create_args *args)
|
|
{
|
|
struct vrf *vrf;
|
|
struct pim_instance *pim;
|
|
struct bsm_scope *scope;
|
|
prefix_pim p;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
vrf = nb_running_get_entry(args->dnode, NULL, true);
|
|
pim = vrf->info;
|
|
scope = &pim->global_scope;
|
|
|
|
yang_dnode_get_pim_p(&p, args->dnode, ".");
|
|
pim_cand_rp_grp_add(scope, &p);
|
|
break;
|
|
}
|
|
return NB_OK;
|
|
}
|
|
|
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_candidate_rp_group_list_destroy(
|
|
struct nb_cb_destroy_args *args)
|
|
{
|
|
struct vrf *vrf;
|
|
struct pim_instance *pim;
|
|
struct bsm_scope *scope;
|
|
prefix_pim p;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
vrf = nb_running_get_entry(args->dnode, NULL, true);
|
|
pim = vrf->info;
|
|
scope = &pim->global_scope;
|
|
|
|
yang_dnode_get_pim_p(&p, args->dnode, ".");
|
|
pim_cand_rp_grp_del(scope, &p);
|
|
break;
|
|
}
|
|
return NB_OK;
|
|
}
|
|
|
|
static int candidate_rp_addrsel_common(enum nb_event event,
|
|
const struct lyd_node *dnode)
|
|
{
|
|
struct vrf *vrf;
|
|
struct pim_instance *pim;
|
|
struct bsm_scope *scope;
|
|
|
|
dnode = lyd_parent(dnode);
|
|
|
|
switch (event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
vrf = nb_running_get_entry(dnode, NULL, true);
|
|
pim = vrf->info;
|
|
scope = &pim->global_scope;
|
|
|
|
candidate_rp_addrsel(scope, dnode);
|
|
break;
|
|
}
|
|
return NB_OK;
|
|
}
|
|
|
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_candidate_rp_addrsel_create(
|
|
struct nb_cb_create_args *args)
|
|
{
|
|
return candidate_rp_addrsel_common(args->event, args->dnode);
|
|
}
|
|
|
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_candidate_rp_addrsel_modify(
|
|
struct nb_cb_modify_args *args)
|
|
{
|
|
return candidate_rp_addrsel_common(args->event, args->dnode);
|
|
}
|
|
|
|
int routing_control_plane_protocols_control_plane_protocol_pim_address_family_candidate_rp_addrsel_destroy(
|
|
struct nb_cb_destroy_args *args)
|
|
{
|
|
/* nothing to do here - we'll get a create or modify event too */
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath: /frr-interface:lib/interface/frr-gmp:gmp/address-family
|
|
*/
|
|
int lib_interface_gmp_address_family_create(struct nb_cb_create_args *args)
|
|
{
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
case NB_EV_APPLY:
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
int lib_interface_gmp_address_family_destroy(struct nb_cb_destroy_args *args)
|
|
{
|
|
struct interface *ifp;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
ifp = nb_running_get_entry(args->dnode, NULL, true);
|
|
pim_gm_interface_delete(ifp);
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath: /frr-interface:lib/interface/frr-gmp:gmp/address-family/enable
|
|
*/
|
|
int lib_interface_gmp_address_family_enable_modify(
|
|
struct nb_cb_modify_args *args)
|
|
{
|
|
struct interface *ifp;
|
|
bool gm_enable;
|
|
int mcast_if_count;
|
|
const char *ifp_name;
|
|
const struct lyd_node *if_dnode;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
if_dnode = yang_dnode_get_parent(args->dnode, "interface");
|
|
mcast_if_count =
|
|
yang_get_list_elements_count(if_dnode);
|
|
/* Limiting mcast interfaces to number of VIFs */
|
|
if (mcast_if_count == MAXVIFS) {
|
|
ifp_name = yang_dnode_get_string(if_dnode, "name");
|
|
snprintf(
|
|
args->errmsg, args->errmsg_len,
|
|
"Max multicast interfaces(%d) Reached. Could not enable %s on interface %s",
|
|
MAXVIFS, GM, ifp_name);
|
|
return NB_ERR_VALIDATION;
|
|
}
|
|
break;
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
ifp = nb_running_get_entry(args->dnode, NULL, true);
|
|
gm_enable = yang_dnode_get_bool(args->dnode, NULL);
|
|
|
|
if (gm_enable)
|
|
return pim_cmd_gm_start(ifp);
|
|
|
|
else
|
|
pim_gm_interface_delete(ifp);
|
|
}
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath: /frr-interface:lib/interface/frr-gmp:gmp/address-family/igmp-version
|
|
*/
|
|
int lib_interface_gmp_address_family_igmp_version_modify(
|
|
struct nb_cb_modify_args *args)
|
|
{
|
|
struct interface *ifp;
|
|
struct pim_interface *pim_ifp;
|
|
int igmp_version, old_version = 0;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
ifp = nb_running_get_entry(args->dnode, NULL, true);
|
|
pim_ifp = ifp->info;
|
|
|
|
if (!pim_ifp)
|
|
return NB_ERR_INCONSISTENCY;
|
|
|
|
igmp_version = yang_dnode_get_uint8(args->dnode, NULL);
|
|
old_version = pim_ifp->igmp_version;
|
|
pim_ifp->igmp_version = igmp_version;
|
|
|
|
/* Current and new version is different refresh existing
|
|
* membership. Going from 3 -> 2 or 2 -> 3.
|
|
*/
|
|
if (old_version != igmp_version)
|
|
pim_if_membership_refresh(ifp);
|
|
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
int lib_interface_gmp_address_family_igmp_version_destroy(
|
|
struct nb_cb_destroy_args *args)
|
|
{
|
|
struct interface *ifp;
|
|
struct pim_interface *pim_ifp;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
ifp = nb_running_get_entry(args->dnode, NULL, true);
|
|
pim_ifp = ifp->info;
|
|
pim_ifp->igmp_version = IGMP_DEFAULT_VERSION;
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath: /frr-interface:lib/interface/frr-gmp:gmp/address-family/mld-version
|
|
*/
|
|
int lib_interface_gmp_address_family_mld_version_modify(
|
|
struct nb_cb_modify_args *args)
|
|
{
|
|
struct interface *ifp;
|
|
struct pim_interface *pim_ifp;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
ifp = nb_running_get_entry(args->dnode, NULL, true);
|
|
pim_ifp = ifp->info;
|
|
if (!pim_ifp)
|
|
return NB_ERR_INCONSISTENCY;
|
|
|
|
pim_ifp->mld_version = yang_dnode_get_uint8(args->dnode, NULL);
|
|
gm_ifp_update(ifp);
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
int lib_interface_gmp_address_family_mld_version_destroy(
|
|
struct nb_cb_destroy_args *args)
|
|
{
|
|
struct interface *ifp;
|
|
struct pim_interface *pim_ifp;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
ifp = nb_running_get_entry(args->dnode, NULL, true);
|
|
pim_ifp = ifp->info;
|
|
if (!pim_ifp)
|
|
return NB_ERR_INCONSISTENCY;
|
|
|
|
pim_ifp->mld_version = 2;
|
|
gm_ifp_update(ifp);
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath: /frr-interface:lib/interface/frr-gmp:gmp/address-family/query-interval
|
|
*/
|
|
int lib_interface_gmp_address_family_query_interval_modify(
|
|
struct nb_cb_modify_args *args)
|
|
{
|
|
struct interface *ifp;
|
|
int query_interval;
|
|
|
|
#if PIM_IPV == 4
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
ifp = nb_running_get_entry(args->dnode, NULL, true);
|
|
query_interval = yang_dnode_get_uint16(args->dnode, NULL);
|
|
change_query_interval(ifp->info, query_interval);
|
|
}
|
|
#else
|
|
struct pim_interface *pim_ifp;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
ifp = nb_running_get_entry(args->dnode, NULL, true);
|
|
pim_ifp = ifp->info;
|
|
if (!pim_ifp)
|
|
return NB_ERR_INCONSISTENCY;
|
|
|
|
query_interval = yang_dnode_get_uint16(args->dnode, NULL);
|
|
pim_ifp->gm_default_query_interval = query_interval;
|
|
gm_ifp_update(ifp);
|
|
}
|
|
#endif
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath: /frr-interface:lib/interface/frr-gmp:gmp/address-family/query-max-response-time
|
|
*/
|
|
int lib_interface_gmp_address_family_query_max_response_time_modify(
|
|
struct nb_cb_modify_args *args)
|
|
{
|
|
struct interface *ifp;
|
|
int query_max_response_time_dsec;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
ifp = nb_running_get_entry(args->dnode, NULL, true);
|
|
query_max_response_time_dsec =
|
|
yang_dnode_get_uint16(args->dnode, NULL);
|
|
change_query_max_response_time(ifp,
|
|
query_max_response_time_dsec);
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath: /frr-interface:lib/interface/frr-gmp:gmp/address-family/last-member-query-interval
|
|
*/
|
|
int lib_interface_gmp_address_family_last_member_query_interval_modify(
|
|
struct nb_cb_modify_args *args)
|
|
{
|
|
struct interface *ifp;
|
|
struct pim_interface *pim_ifp;
|
|
int last_member_query_interval;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
ifp = nb_running_get_entry(args->dnode, NULL, true);
|
|
pim_ifp = ifp->info;
|
|
last_member_query_interval =
|
|
yang_dnode_get_uint16(args->dnode, NULL);
|
|
pim_ifp->gm_specific_query_max_response_time_dsec =
|
|
last_member_query_interval;
|
|
#if PIM_IPV == 6
|
|
gm_ifp_update(ifp);
|
|
#endif
|
|
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath: /frr-interface:lib/interface/frr-gmp:gmp/address-family/robustness-variable
|
|
*/
|
|
int lib_interface_gmp_address_family_robustness_variable_modify(
|
|
struct nb_cb_modify_args *args)
|
|
{
|
|
struct interface *ifp;
|
|
struct pim_interface *pim_ifp;
|
|
int last_member_query_count;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
ifp = nb_running_get_entry(args->dnode, NULL, true);
|
|
pim_ifp = ifp->info;
|
|
last_member_query_count =
|
|
yang_dnode_get_uint8(args->dnode, NULL);
|
|
pim_ifp->gm_last_member_query_count = last_member_query_count;
|
|
#if PIM_IPV == 6
|
|
gm_ifp_update(ifp);
|
|
#endif
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath: /frr-interface:lib/interface/frr-gmp:gmp/address-family/proxy
|
|
*/
|
|
int lib_interface_gmp_address_family_proxy_modify(struct nb_cb_modify_args *args)
|
|
{
|
|
struct interface *ifp;
|
|
struct pim_interface *pim_ifp;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
ifp = nb_running_get_entry(args->dnode, NULL, true);
|
|
pim_ifp = ifp->info;
|
|
if (pim_ifp)
|
|
pim_ifp->gm_proxy = yang_dnode_get_bool(args->dnode,
|
|
NULL);
|
|
|
|
if (pim_ifp->gm_proxy)
|
|
pim_if_gm_proxy_init(pim_ifp->pim, ifp);
|
|
else
|
|
pim_if_gm_proxy_finis(pim_ifp->pim, ifp);
|
|
}
|
|
return NB_OK;
|
|
}
|
|
/*
|
|
* XPath: /frr-interface:lib/interface/frr-gmp:gmp/address-family/join-group
|
|
*/
|
|
int lib_interface_gmp_address_family_join_group_create(
|
|
struct nb_cb_create_args *args)
|
|
{
|
|
struct interface *ifp;
|
|
pim_addr source_addr;
|
|
pim_addr group_addr;
|
|
int result;
|
|
const char *ifp_name;
|
|
const struct lyd_node *if_dnode;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
if_dnode = yang_dnode_get_parent(args->dnode, "interface");
|
|
if (!is_pim_interface(if_dnode)) {
|
|
ifp_name = yang_dnode_get_string(if_dnode, "name");
|
|
snprintf(args->errmsg, args->errmsg_len,
|
|
"multicast not enabled on interface %s",
|
|
ifp_name);
|
|
return NB_ERR_VALIDATION;
|
|
}
|
|
|
|
yang_dnode_get_pimaddr(&group_addr, args->dnode,
|
|
"./group-addr");
|
|
#if PIM_IPV == 4
|
|
if (pim_is_group_224_0_0_0_24(group_addr)) {
|
|
snprintf(
|
|
args->errmsg, args->errmsg_len,
|
|
"Groups within 224.0.0.0/24 are reserved and cannot be joined");
|
|
return NB_ERR_VALIDATION;
|
|
}
|
|
#else
|
|
if (ipv6_mcast_reserved(&group_addr)) {
|
|
snprintf(
|
|
args->errmsg, args->errmsg_len,
|
|
"Groups within ffx2::/16 are reserved and cannot be joined");
|
|
return NB_ERR_VALIDATION;
|
|
}
|
|
#endif
|
|
break;
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
ifp = nb_running_get_entry(args->dnode, NULL, true);
|
|
yang_dnode_get_pimaddr(&source_addr, args->dnode,
|
|
"./source-addr");
|
|
yang_dnode_get_pimaddr(&group_addr, args->dnode,
|
|
"./group-addr");
|
|
result = pim_if_gm_join_add(ifp, group_addr, source_addr,
|
|
GM_JOIN_STATIC);
|
|
if (result) {
|
|
snprintf(args->errmsg, args->errmsg_len,
|
|
"Failure joining " GM " group");
|
|
return NB_ERR_INCONSISTENCY;
|
|
}
|
|
}
|
|
return NB_OK;
|
|
}
|
|
|
|
int lib_interface_gmp_address_family_join_group_destroy(
|
|
struct nb_cb_destroy_args *args)
|
|
{
|
|
struct interface *ifp;
|
|
pim_addr source_addr;
|
|
pim_addr group_addr;
|
|
int result;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
ifp = nb_running_get_entry(args->dnode, NULL, true);
|
|
yang_dnode_get_pimaddr(&source_addr, args->dnode,
|
|
"./source-addr");
|
|
yang_dnode_get_pimaddr(&group_addr, args->dnode,
|
|
"./group-addr");
|
|
result = pim_if_gm_join_del(ifp, group_addr, source_addr,
|
|
GM_JOIN_STATIC);
|
|
|
|
if (result) {
|
|
snprintf(args->errmsg, args->errmsg_len,
|
|
"%% Failure leaving " GM
|
|
" group %pPAs %pPAs on interface %s: %d",
|
|
&source_addr, &group_addr, ifp->name, result);
|
|
|
|
return NB_ERR_INCONSISTENCY;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|
|
|
|
/*
|
|
* XPath: /frr-interface:lib/interface/frr-gmp:gmp/address-family/static-group
|
|
*/
|
|
int lib_interface_gmp_address_family_static_group_create(
|
|
struct nb_cb_create_args *args)
|
|
{
|
|
struct interface *ifp;
|
|
pim_addr source_addr;
|
|
pim_addr group_addr;
|
|
int result;
|
|
const char *ifp_name;
|
|
const struct lyd_node *if_dnode;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
if_dnode = yang_dnode_get_parent(args->dnode, "interface");
|
|
if (!is_pim_interface(if_dnode)) {
|
|
ifp_name = yang_dnode_get_string(if_dnode, "name");
|
|
snprintf(args->errmsg, args->errmsg_len,
|
|
"multicast not enabled on interface %s",
|
|
ifp_name);
|
|
return NB_ERR_VALIDATION;
|
|
}
|
|
|
|
yang_dnode_get_pimaddr(&group_addr, args->dnode, "./group-addr");
|
|
#if PIM_IPV == 4
|
|
if (pim_is_group_224_0_0_0_24(group_addr)) {
|
|
snprintf(args->errmsg, args->errmsg_len,
|
|
"Groups within 224.0.0.0/24 are reserved and cannot be joined");
|
|
return NB_ERR_VALIDATION;
|
|
}
|
|
#else
|
|
if (ipv6_mcast_reserved(&group_addr)) {
|
|
snprintf(args->errmsg, args->errmsg_len,
|
|
"Groups within ffx2::/16 are reserved and cannot be joined");
|
|
return NB_ERR_VALIDATION;
|
|
}
|
|
#endif
|
|
break;
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
ifp = nb_running_get_entry(args->dnode, NULL, true);
|
|
yang_dnode_get_pimaddr(&source_addr, args->dnode,
|
|
"./source-addr");
|
|
yang_dnode_get_pimaddr(&group_addr, args->dnode, "./group-addr");
|
|
result = pim_if_static_group_add(ifp, group_addr, source_addr);
|
|
if (result) {
|
|
snprintf(args->errmsg, args->errmsg_len,
|
|
"Failure adding static group");
|
|
return NB_ERR_INCONSISTENCY;
|
|
}
|
|
}
|
|
return NB_OK;
|
|
}
|
|
|
|
int lib_interface_gmp_address_family_static_group_destroy(
|
|
struct nb_cb_destroy_args *args)
|
|
{
|
|
struct interface *ifp;
|
|
pim_addr source_addr;
|
|
pim_addr group_addr;
|
|
int result;
|
|
|
|
switch (args->event) {
|
|
case NB_EV_VALIDATE:
|
|
case NB_EV_PREPARE:
|
|
case NB_EV_ABORT:
|
|
break;
|
|
case NB_EV_APPLY:
|
|
ifp = nb_running_get_entry(args->dnode, NULL, true);
|
|
yang_dnode_get_pimaddr(&source_addr, args->dnode,
|
|
"./source-addr");
|
|
yang_dnode_get_pimaddr(&group_addr, args->dnode, "./group-addr");
|
|
result = pim_if_static_group_del(ifp, group_addr, source_addr);
|
|
|
|
if (result) {
|
|
snprintf(args->errmsg, args->errmsg_len,
|
|
"%% Failure removing static group %pPAs %pPAs on interface %s: %d",
|
|
&source_addr, &group_addr, ifp->name, result);
|
|
|
|
return NB_ERR_INCONSISTENCY;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
return NB_OK;
|
|
}
|