pimd: Northbound implementation for ssm prefix-list, ssmpingd command

ip_pim_ssm_prefix_list
no_ip_pim_ssm_prefix_list
no_ip_pim_ssm_prefix_list_name
no_ip_ssmpingd
ip_ssmpingd

Yang Model:
  augment /frr-routing:routing/frr-routing:control-plane-protocols/frr-routing:control-plane-protocol:
    +--rw pim
       +--rw address-family* [address-family]
          +--rw address-family          identityref
          +--rw ssm-prefix-list?        plist-ref
          +--rw ssm-pingd-source-ip*    ietf-inet-types:ip-address

Signed-off-by: Sarita Patra <saritap@vmware.com>
This commit is contained in:
Sarita Patra 2020-10-23 06:58:51 -07:00
parent db9cca95be
commit f206085e19
2 changed files with 238 additions and 69 deletions

View File

@ -7409,30 +7409,6 @@ DEFUN (no_ip_pim_rp_prefix_list,
return pim_no_rp_cmd_worker(pim, vty, argv[4]->arg, NULL, argv[6]->arg);
}
static int pim_ssm_cmd_worker(struct pim_instance *pim, struct vty *vty,
const char *plist)
{
int result = pim_ssm_range_set(pim, pim->vrf_id, plist);
int ret = CMD_WARNING_CONFIG_FAILED;
if (result == PIM_SSM_ERR_NONE)
return CMD_SUCCESS;
switch (result) {
case PIM_SSM_ERR_NO_VRF:
vty_out(vty, "%% VRF doesn't exist\n");
break;
case PIM_SSM_ERR_DUP:
vty_out(vty, "%% duplicate config\n");
ret = CMD_WARNING;
break;
default:
vty_out(vty, "%% ssm range config failed\n");
}
return ret;
}
DEFUN (ip_pim_ssm_prefix_list,
ip_pim_ssm_prefix_list_cmd,
"ip pim ssm prefix-list WORD",
@ -7442,8 +7418,31 @@ DEFUN (ip_pim_ssm_prefix_list,
"group range prefix-list filter\n"
"Name of a prefix-list\n")
{
PIM_DECLVAR_CONTEXT(vrf, pim);
return pim_ssm_cmd_worker(pim, vty, argv[4]->arg);
const struct lyd_node *vrf_dnode;
const char *vrfname;
char ssm_plist_xpath[XPATH_MAXLEN];
if (vty->xpath_index) {
vrf_dnode =
yang_dnode_get(vty->candidate_config->dnode,
VTY_CURR_XPATH);
if (!vrf_dnode) {
vty_out(vty,
"%% Failed to get vrf dnode in candidate db\n");
return CMD_WARNING_CONFIG_FAILED;
}
vrfname = yang_dnode_get_string(vrf_dnode, "./name");
} else
vrfname = VRF_DEFAULT_NAME;
snprintf(ssm_plist_xpath, sizeof(ssm_plist_xpath),
FRR_PIM_AF_XPATH,
"frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4");
strlcat(ssm_plist_xpath, "/ssm-prefix-list", sizeof(ssm_plist_xpath));
nb_cli_enqueue_change(vty, ssm_plist_xpath, NB_OP_MODIFY, argv[4]->arg);
return nb_cli_apply_changes(vty, NULL);
}
DEFUN (no_ip_pim_ssm_prefix_list,
@ -7455,8 +7454,31 @@ DEFUN (no_ip_pim_ssm_prefix_list,
"Source Specific Multicast\n"
"group range prefix-list filter\n")
{
PIM_DECLVAR_CONTEXT(vrf, pim);
return pim_ssm_cmd_worker(pim, vty, NULL);
const struct lyd_node *vrf_dnode;
const char *vrfname;
char ssm_plist_xpath[XPATH_MAXLEN];
if (vty->xpath_index) {
vrf_dnode =
yang_dnode_get(vty->candidate_config->dnode,
VTY_CURR_XPATH);
if (!vrf_dnode) {
vty_out(vty,
"%% Failed to get vrf dnode in candidate db\n");
return CMD_WARNING_CONFIG_FAILED;
}
vrfname = yang_dnode_get_string(vrf_dnode, "./name");
} else
vrfname = VRF_DEFAULT_NAME;
snprintf(ssm_plist_xpath, sizeof(ssm_plist_xpath),
FRR_PIM_AF_XPATH,
"frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4");
strlcat(ssm_plist_xpath, "/ssm-prefix-list", sizeof(ssm_plist_xpath));
nb_cli_enqueue_change(vty, ssm_plist_xpath, NB_OP_DESTROY, NULL);
return nb_cli_apply_changes(vty, NULL);
}
DEFUN (no_ip_pim_ssm_prefix_list_name,
@ -7469,11 +7491,50 @@ DEFUN (no_ip_pim_ssm_prefix_list_name,
"group range prefix-list filter\n"
"Name of a prefix-list\n")
{
PIM_DECLVAR_CONTEXT(vrf, pim);
struct pim_ssm *ssm = pim->ssm_info;
const struct lyd_node *vrf_dnode;
const char *vrfname;
const struct lyd_node *ssm_plist_dnode;
char ssm_plist_xpath[XPATH_MAXLEN];
const char *ssm_plist_name;
if (ssm->plist_name && !strcmp(ssm->plist_name, argv[5]->arg))
return pim_ssm_cmd_worker(pim, vty, NULL);
if (vty->xpath_index) {
vrf_dnode =
yang_dnode_get(vty->candidate_config->dnode,
VTY_CURR_XPATH);
if (!vrf_dnode) {
vty_out(vty,
"%% Failed to get vrf dnode in candidate db\n");
return CMD_WARNING_CONFIG_FAILED;
}
vrfname = yang_dnode_get_string(vrf_dnode, "./name");
} else
vrfname = VRF_DEFAULT_NAME;
snprintf(ssm_plist_xpath, sizeof(ssm_plist_xpath),
FRR_PIM_AF_XPATH,
"frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4");
strlcat(ssm_plist_xpath, "/ssm-prefix-list", sizeof(ssm_plist_xpath));
ssm_plist_dnode = yang_dnode_get(vty->candidate_config->dnode,
ssm_plist_xpath);
if (!ssm_plist_dnode) {
vty_out(vty,
"%% pim ssm prefix-list %s doesn't exist\n",
argv[5]->arg);
return CMD_WARNING_CONFIG_FAILED;
}
ssm_plist_name = yang_dnode_get_string(ssm_plist_dnode, ".");
if (ssm_plist_name && !strcmp(ssm_plist_name, argv[5]->arg)) {
nb_cli_enqueue_change(vty, ssm_plist_xpath, NB_OP_DESTROY,
NULL);
return nb_cli_apply_changes(vty, NULL);
}
vty_out(vty, "%% pim ssm prefix-list %s doesn't exist\n", argv[5]->arg);
@ -7602,27 +7663,35 @@ DEFUN (ip_ssmpingd,
CONF_SSMPINGD_STR
"Source address\n")
{
PIM_DECLVAR_CONTEXT(vrf, pim);
int idx_ipv4 = 2;
int result;
struct in_addr source_addr;
const char *source_str = (argc == 3) ? argv[idx_ipv4]->arg : "0.0.0.0";
const struct lyd_node *vrf_dnode;
const char *vrfname;
char ssmpingd_ip_xpath[XPATH_MAXLEN];
result = inet_pton(AF_INET, source_str, &source_addr);
if (result <= 0) {
vty_out(vty, "%% Bad source address %s: errno=%d: %s\n",
source_str, errno, safe_strerror(errno));
return CMD_WARNING_CONFIG_FAILED;
}
if (vty->xpath_index) {
vrf_dnode =
yang_dnode_get(vty->candidate_config->dnode,
VTY_CURR_XPATH);
if (!vrf_dnode) {
vty_out(vty,
"%% Failed to get vrf dnode in candidate db\n");
return CMD_WARNING_CONFIG_FAILED;
}
vrfname = yang_dnode_get_string(vrf_dnode, "./name");
} else
vrfname = VRF_DEFAULT_NAME;
result = pim_ssmpingd_start(pim, source_addr);
if (result) {
vty_out(vty, "%% Failure starting ssmpingd for source %s: %d\n",
source_str, result);
return CMD_WARNING_CONFIG_FAILED;
}
snprintf(ssmpingd_ip_xpath, sizeof(ssmpingd_ip_xpath),
FRR_PIM_AF_XPATH,
"frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4");
strlcat(ssmpingd_ip_xpath, "/ssm-pingd-source-ip",
sizeof(ssmpingd_ip_xpath));
return CMD_SUCCESS;
nb_cli_enqueue_change(vty, ssmpingd_ip_xpath, NB_OP_CREATE,
source_str);
return nb_cli_apply_changes(vty, NULL);
}
DEFUN (no_ip_ssmpingd,
@ -7633,27 +7702,35 @@ DEFUN (no_ip_ssmpingd,
CONF_SSMPINGD_STR
"Source address\n")
{
PIM_DECLVAR_CONTEXT(vrf, pim);
const struct lyd_node *vrf_dnode;
const char *vrfname;
int idx_ipv4 = 3;
int result;
struct in_addr source_addr;
const char *source_str = (argc == 4) ? argv[idx_ipv4]->arg : "0.0.0.0";
char ssmpingd_ip_xpath[XPATH_MAXLEN];
result = inet_pton(AF_INET, source_str, &source_addr);
if (result <= 0) {
vty_out(vty, "%% Bad source address %s: errno=%d: %s\n",
source_str, errno, safe_strerror(errno));
return CMD_WARNING_CONFIG_FAILED;
}
if (vty->xpath_index) {
vrf_dnode =
yang_dnode_get(vty->candidate_config->dnode,
VTY_CURR_XPATH);
if (!vrf_dnode) {
vty_out(vty,
"%% Failed to get vrf dnode in candidate db\n");
return CMD_WARNING_CONFIG_FAILED;
}
vrfname = yang_dnode_get_string(vrf_dnode, "./name");
} else
vrfname = VRF_DEFAULT_NAME;
result = pim_ssmpingd_stop(pim, source_addr);
if (result) {
vty_out(vty, "%% Failure stopping ssmpingd for source %s: %d\n",
source_str, result);
return CMD_WARNING_CONFIG_FAILED;
}
snprintf(ssmpingd_ip_xpath, sizeof(ssmpingd_ip_xpath),
FRR_PIM_AF_XPATH,
"frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4");
strlcat(ssmpingd_ip_xpath, "/ssm-pingd-source-ip",
sizeof(ssmpingd_ip_xpath));
return CMD_SUCCESS;
nb_cli_enqueue_change(vty, ssmpingd_ip_xpath, NB_OP_DESTROY,
source_str);
return nb_cli_apply_changes(vty, NULL);
}
DEFUN (ip_pim_ecmp,

View File

@ -25,6 +25,8 @@
#include "pim_mlag.h"
#include "pim_bfd.h"
#include "pim_static.h"
#include "pim_ssm.h"
#include "pim_ssmpingd.h"
static void pim_if_membership_clear(struct interface *ifp)
{
@ -210,6 +212,32 @@ static int pim_cmd_spt_switchover(struct pim_instance *pim,
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_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 bool is_pim_interface(const struct lyd_node *dnode)
{
char if_xpath[XPATH_MAXLEN];
@ -706,12 +734,26 @@ int routing_control_plane_protocols_control_plane_protocol_pim_address_family_sp
*/
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:
/* TODO: implement me. */
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;
}
@ -720,12 +762,24 @@ int routing_control_plane_protocols_control_plane_protocol_pim_address_family_ss
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:
/* TODO: implement me. */
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;
}
@ -737,13 +791,31 @@ int routing_control_plane_protocols_control_plane_protocol_pim_address_family_ss
*/
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;
struct ipaddr source_addr;
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:
vrf = nb_running_get_entry(args->dnode, NULL, true);
pim = vrf->info;
yang_dnode_get_ip(&source_addr, args->dnode, NULL);
result = pim_ssmpingd_start(pim, source_addr.ip._v4_addr);
if (result) {
char source_str[INET_ADDRSTRLEN];
ipaddr2str(&source_addr, source_str,
sizeof(source_str));
snprintf(args->errmsg, args->errmsg_len,
"%% Failure starting ssmpingd for source %s: %d",
source_str, result);
return NB_ERR_INCONSISTENCY;
}
}
return NB_OK;
@ -751,12 +823,32 @@ int routing_control_plane_protocols_control_plane_protocol_pim_address_family_ss
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;
struct ipaddr source_addr;
switch (args->event) {
case NB_EV_VALIDATE:
case NB_EV_PREPARE:
case NB_EV_ABORT:
break;
case NB_EV_APPLY:
/* TODO: implement me. */
vrf = nb_running_get_entry(args->dnode, NULL, true);
pim = vrf->info;
yang_dnode_get_ip(&source_addr, args->dnode, NULL);
result = pim_ssmpingd_stop(pim, source_addr.ip._v4_addr);
if (result) {
char source_str[INET_ADDRSTRLEN];
ipaddr2str(&source_addr, source_str,
sizeof(source_str));
snprintf(args->errmsg, args->errmsg_len,
"%% Failure stopping ssmpingd for source %s: %d",
source_str, result);
return NB_ERR_INCONSISTENCY;
}
break;
}