mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-13 17:27:42 +00:00
pimd: Northbound implementation for pim commands.
interface_ip_pim_ssm interface_ip_pim_sm interface_ip_pim interface_no_ip_pim_ssm interface_no_ip_pim_sm interface_no_ip_pim Yang Model: augment /frr-interface:lib/frr-interface:interface: +--rw pim! +--rw pim-enable? boolean <false> Signed-off-by: Sarita Patra <saritap@vmware.com>
This commit is contained in:
parent
b0475d5a52
commit
50d194f8c8
144
pimd/pim_cmd.c
144
pimd/pim_cmd.c
@ -8092,36 +8092,19 @@ DEFUN_HIDDEN (interface_ip_pim_ssm,
|
||||
PIM_STR
|
||||
IFACE_PIM_STR)
|
||||
{
|
||||
VTY_DECLVAR_CONTEXT(interface, ifp);
|
||||
int ret;
|
||||
|
||||
if (!pim_cmd_interface_add(vty, ifp)) {
|
||||
vty_out(vty, "Could not enable PIM SM on interface %s\n",
|
||||
ifp->name);
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY, "true");
|
||||
|
||||
ret = nb_cli_apply_changes(vty, "./frr-pim:pim");
|
||||
|
||||
if (ret != NB_OK)
|
||||
return ret;
|
||||
|
||||
vty_out(vty,
|
||||
"WARN: Enabled PIM SM on interface; configure PIM SSM range if needed\n");
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
static int interface_ip_pim_helper(struct vty *vty)
|
||||
{
|
||||
struct pim_interface *pim_ifp;
|
||||
|
||||
VTY_DECLVAR_CONTEXT(interface, ifp);
|
||||
|
||||
if (!pim_cmd_interface_add(vty, ifp)) {
|
||||
vty_out(vty, "Could not enable PIM SM on interface %s\n",
|
||||
ifp->name);
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
pim_ifp = ifp->info;
|
||||
|
||||
pim_if_create_pimreg(pim_ifp->pim);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
return NB_OK;
|
||||
}
|
||||
|
||||
DEFUN_HIDDEN (interface_ip_pim_sm,
|
||||
@ -8131,7 +8114,9 @@ DEFUN_HIDDEN (interface_ip_pim_sm,
|
||||
PIM_STR
|
||||
IFACE_PIM_SM_STR)
|
||||
{
|
||||
return interface_ip_pim_helper(vty);
|
||||
nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY, "true");
|
||||
|
||||
return nb_cli_apply_changes(vty, "./frr-pim:pim");
|
||||
}
|
||||
|
||||
DEFUN (interface_ip_pim,
|
||||
@ -8140,43 +8125,9 @@ DEFUN (interface_ip_pim,
|
||||
IP_STR
|
||||
PIM_STR)
|
||||
{
|
||||
return interface_ip_pim_helper(vty);
|
||||
}
|
||||
nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY, "true");
|
||||
|
||||
static int pim_cmd_interface_delete(struct interface *ifp)
|
||||
{
|
||||
struct pim_interface *pim_ifp = ifp->info;
|
||||
|
||||
if (!pim_ifp)
|
||||
return 1;
|
||||
|
||||
PIM_IF_DONT_PIM(pim_ifp->options);
|
||||
|
||||
pim_if_membership_clear(ifp);
|
||||
|
||||
/*
|
||||
pim_sock_delete() removes all neighbors from
|
||||
pim_ifp->pim_neighbor_list.
|
||||
*/
|
||||
pim_sock_delete(ifp, "pim unconfigured on interface");
|
||||
|
||||
if (!PIM_IF_TEST_IGMP(pim_ifp->options)) {
|
||||
pim_if_addr_del_all(ifp);
|
||||
pim_if_delete(ifp);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int interface_no_ip_pim_helper(struct vty *vty)
|
||||
{
|
||||
VTY_DECLVAR_CONTEXT(interface, ifp);
|
||||
if (!pim_cmd_interface_delete(ifp)) {
|
||||
vty_out(vty, "Unable to delete interface information\n");
|
||||
return CMD_WARNING_CONFIG_FAILED;
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
return nb_cli_apply_changes(vty, "./frr-pim:pim");
|
||||
}
|
||||
|
||||
DEFUN_HIDDEN (interface_no_ip_pim_ssm,
|
||||
@ -8187,7 +8138,28 @@ DEFUN_HIDDEN (interface_no_ip_pim_ssm,
|
||||
PIM_STR
|
||||
IFACE_PIM_STR)
|
||||
{
|
||||
return interface_no_ip_pim_helper(vty);
|
||||
const struct lyd_node *igmp_enable_dnode;
|
||||
char igmp_if_xpath[XPATH_MAXLEN];
|
||||
|
||||
snprintf(igmp_if_xpath, sizeof(igmp_if_xpath),
|
||||
"%s/frr-igmp:igmp", VTY_CURR_XPATH);
|
||||
igmp_enable_dnode = yang_dnode_get(vty->candidate_config->dnode,
|
||||
"%s/igmp-enable", igmp_if_xpath);
|
||||
|
||||
if (!igmp_enable_dnode) {
|
||||
nb_cli_enqueue_change(vty, igmp_if_xpath, NB_OP_DESTROY, NULL);
|
||||
nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
|
||||
} else {
|
||||
if (!yang_dnode_get_bool(igmp_enable_dnode, ".")) {
|
||||
nb_cli_enqueue_change(vty, igmp_if_xpath, NB_OP_DESTROY,
|
||||
NULL);
|
||||
nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
|
||||
} else
|
||||
nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY,
|
||||
"false");
|
||||
}
|
||||
|
||||
return nb_cli_apply_changes(vty, "./frr-pim:pim");
|
||||
}
|
||||
|
||||
DEFUN_HIDDEN (interface_no_ip_pim_sm,
|
||||
@ -8198,7 +8170,28 @@ DEFUN_HIDDEN (interface_no_ip_pim_sm,
|
||||
PIM_STR
|
||||
IFACE_PIM_SM_STR)
|
||||
{
|
||||
return interface_no_ip_pim_helper(vty);
|
||||
const struct lyd_node *igmp_enable_dnode;
|
||||
char igmp_if_xpath[XPATH_MAXLEN];
|
||||
|
||||
snprintf(igmp_if_xpath, sizeof(igmp_if_xpath),
|
||||
"%s/frr-igmp:igmp", VTY_CURR_XPATH);
|
||||
igmp_enable_dnode = yang_dnode_get(vty->candidate_config->dnode,
|
||||
"%s/igmp-enable", igmp_if_xpath);
|
||||
|
||||
if (!igmp_enable_dnode) {
|
||||
nb_cli_enqueue_change(vty, igmp_if_xpath, NB_OP_DESTROY, NULL);
|
||||
nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
|
||||
} else {
|
||||
if (!yang_dnode_get_bool(igmp_enable_dnode, ".")) {
|
||||
nb_cli_enqueue_change(vty, igmp_if_xpath, NB_OP_DESTROY,
|
||||
NULL);
|
||||
nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
|
||||
} else
|
||||
nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY,
|
||||
"false");
|
||||
}
|
||||
|
||||
return nb_cli_apply_changes(vty, "./frr-pim:pim");
|
||||
}
|
||||
|
||||
DEFUN (interface_no_ip_pim,
|
||||
@ -8208,7 +8201,28 @@ DEFUN (interface_no_ip_pim,
|
||||
IP_STR
|
||||
PIM_STR)
|
||||
{
|
||||
return interface_no_ip_pim_helper(vty);
|
||||
const struct lyd_node *igmp_enable_dnode;
|
||||
char igmp_if_xpath[XPATH_MAXLEN];
|
||||
|
||||
snprintf(igmp_if_xpath, sizeof(igmp_if_xpath),
|
||||
"%s/frr-igmp:igmp", VTY_CURR_XPATH);
|
||||
igmp_enable_dnode = yang_dnode_get(vty->candidate_config->dnode,
|
||||
"%s/igmp-enable", igmp_if_xpath);
|
||||
|
||||
if (!igmp_enable_dnode) {
|
||||
nb_cli_enqueue_change(vty, igmp_if_xpath, NB_OP_DESTROY, NULL);
|
||||
nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
|
||||
} else {
|
||||
if (!yang_dnode_get_bool(igmp_enable_dnode, ".")) {
|
||||
nb_cli_enqueue_change(vty, igmp_if_xpath, NB_OP_DESTROY,
|
||||
NULL);
|
||||
nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
|
||||
} else
|
||||
nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY,
|
||||
"false");
|
||||
}
|
||||
|
||||
return nb_cli_apply_changes(vty, "./frr-pim:pim");
|
||||
}
|
||||
|
||||
/* boundaries */
|
||||
|
@ -21,9 +21,136 @@
|
||||
#include "pim_nb.h"
|
||||
#include "lib/northbound_cli.h"
|
||||
#include "pim_igmpv3.h"
|
||||
#include "pim_pim.h"
|
||||
|
||||
void pim_if_membership_clear(struct interface *ifp);
|
||||
void pim_if_membership_refresh(struct interface *ifp);
|
||||
static void pim_if_membership_clear(struct interface *ifp)
|
||||
{
|
||||
struct pim_interface *pim_ifp;
|
||||
|
||||
pim_ifp = ifp->info;
|
||||
zassert(pim_ifp);
|
||||
|
||||
if (PIM_IF_TEST_PIM(pim_ifp->options)
|
||||
&& PIM_IF_TEST_IGMP(pim_ifp->options)) {
|
||||
return;
|
||||
}
|
||||
|
||||
pim_ifchannel_membership_clear(ifp);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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;
|
||||
struct listnode *sock_node;
|
||||
struct igmp_sock *igmp;
|
||||
|
||||
pim_ifp = ifp->info;
|
||||
zassert(pim_ifp);
|
||||
|
||||
if (!PIM_IF_TEST_PIM(pim_ifp->options))
|
||||
return;
|
||||
if (!PIM_IF_TEST_IGMP(pim_ifp->options))
|
||||
return;
|
||||
|
||||
/*
|
||||
* First clear off membership from all PIM (S,G) entries on the
|
||||
* interface
|
||||
*/
|
||||
|
||||
pim_ifchannel_membership_clear(ifp);
|
||||
|
||||
/*
|
||||
* Then restore PIM (S,G) membership from all IGMPv3 (S,G) entries on
|
||||
* the interface
|
||||
*/
|
||||
|
||||
/* scan igmp sockets */
|
||||
for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) {
|
||||
struct listnode *grpnode;
|
||||
struct igmp_group *grp;
|
||||
|
||||
/* scan igmp groups */
|
||||
for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list, grpnode,
|
||||
grp)) {
|
||||
struct listnode *srcnode;
|
||||
struct igmp_source *src;
|
||||
|
||||
/* scan group sources */
|
||||
for (ALL_LIST_ELEMENTS_RO(grp->group_source_list,
|
||||
srcnode, src)) {
|
||||
|
||||
if (IGMP_SOURCE_TEST_FORWARDING(
|
||||
src->source_flags)) {
|
||||
struct prefix_sg sg;
|
||||
|
||||
memset(&sg, 0,
|
||||
sizeof(struct prefix_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 */
|
||||
} /* scan igmp sockets */
|
||||
|
||||
/*
|
||||
* 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_IF_DO_PIM(pim_ifp->options);
|
||||
|
||||
pim_if_addr_add_all(ifp);
|
||||
pim_if_membership_refresh(ifp);
|
||||
|
||||
pim_if_create_pimreg(pim_ifp->pim);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int pim_cmd_interface_delete(struct interface *ifp)
|
||||
{
|
||||
struct pim_interface *pim_ifp = ifp->info;
|
||||
|
||||
if (!pim_ifp)
|
||||
return 1;
|
||||
|
||||
PIM_IF_DONT_PIM(pim_ifp->options);
|
||||
|
||||
pim_if_membership_clear(ifp);
|
||||
|
||||
/*
|
||||
* pim_sock_delete() removes all neighbors from
|
||||
* pim_ifp->pim_neighbor_list.
|
||||
*/
|
||||
pim_sock_delete(ifp, "pim unconfigured on interface");
|
||||
|
||||
if (!PIM_IF_TEST_IGMP(pim_ifp->options)) {
|
||||
pim_if_addr_del_all(ifp);
|
||||
pim_if_delete(ifp);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static bool is_pim_interface(const struct lyd_node *dnode)
|
||||
{
|
||||
@ -866,7 +993,6 @@ int lib_interface_pim_create(struct nb_cb_create_args *args)
|
||||
case NB_EV_PREPARE:
|
||||
case NB_EV_ABORT:
|
||||
case NB_EV_APPLY:
|
||||
/* TODO: implement me. */
|
||||
break;
|
||||
}
|
||||
|
||||
@ -875,13 +1001,26 @@ int lib_interface_pim_create(struct nb_cb_create_args *args)
|
||||
|
||||
int lib_interface_pim_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:
|
||||
case NB_EV_APPLY:
|
||||
/* TODO: implement me. */
|
||||
break;
|
||||
case NB_EV_APPLY:
|
||||
ifp = nb_running_get_entry(args->dnode, NULL, true);
|
||||
pim_ifp = ifp->info;
|
||||
if (!pim_ifp)
|
||||
return NB_OK;
|
||||
|
||||
if (!pim_cmd_interface_delete(ifp)) {
|
||||
snprintf(args->errmsg, args->errmsg_len,
|
||||
"Unable to delete interface information %s",
|
||||
ifp->name);
|
||||
return NB_ERR_INCONSISTENCY;
|
||||
}
|
||||
}
|
||||
|
||||
return NB_OK;
|
||||
@ -892,12 +1031,49 @@ int lib_interface_pim_destroy(struct nb_cb_destroy_args *args)
|
||||
*/
|
||||
int lib_interface_pim_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:
|
||||
/* TODO: implement me. */
|
||||
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;
|
||||
|
||||
if (!pim_cmd_interface_delete(ifp)) {
|
||||
snprintf(args->errmsg, args->errmsg_len,
|
||||
"Unable to delete interface information");
|
||||
return NB_ERR_INCONSISTENCY;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user