summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/command.h4
-rw-r--r--lib/lib_vty.c54
-rw-r--r--lib/vty.c1
-rw-r--r--lib/yang.c6
-rw-r--r--lib/yang.h5
-rw-r--r--ospf6d/ospf6_snmp.c6
-rw-r--r--pimd/pim_cmd.c2994
-rw-r--r--pimd/pim_main.c9
-rw-r--r--pimd/pim_nb.c417
-rw-r--r--pimd/pim_nb.h203
-rw-r--r--pimd/pim_nb_config.c3034
-rw-r--r--pimd/pim_rp.c33
-rw-r--r--pimd/pim_rp.h2
-rw-r--r--pimd/subdir.am12
-rw-r--r--sharpd/sharp_main.c12
-rw-r--r--vtysh/vtysh_config.c4
-rw-r--r--yang/frr-igmp.yang7
-rw-r--r--yang/frr-pim.yang107
18 files changed, 5376 insertions, 1534 deletions
diff --git a/lib/command.h b/lib/command.h
index bb007b086..e529239f6 100644
--- a/lib/command.h
+++ b/lib/command.h
@@ -530,7 +530,9 @@ extern int cmd_execute_command(vector, struct vty *,
const struct cmd_element **, int);
extern int cmd_execute_command_strict(vector, struct vty *,
const struct cmd_element **);
-extern void cmd_init(int);
+extern void cmd_init(int terminal);
+extern void cmd_init_config_callbacks(void (*start_config)(void),
+ void (*end_config)(void));
extern void cmd_terminate(void);
extern void cmd_exit(struct vty *vty);
extern int cmd_list_cmds(struct vty *vty, int do_permute);
diff --git a/lib/lib_vty.c b/lib/lib_vty.c
index 9c927ca4a..8207aa20e 100644
--- a/lib/lib_vty.c
+++ b/lib/lib_vty.c
@@ -212,6 +212,57 @@ DEFUN (frr_version,
return CMD_SUCCESS;
}
+static struct call_back {
+ time_t readin_time;
+
+ void (*start_config)(void);
+ void (*end_config)(void);
+} callback;
+
+
+DEFUN_HIDDEN (start_config,
+ start_config_cmd,
+ "start_configuration",
+ "The Beginning of Configuration\n")
+{
+ callback.readin_time = monotime(NULL);
+
+ if (callback.start_config)
+ (*callback.start_config)();
+
+ return CMD_SUCCESS;
+}
+
+DEFUN_HIDDEN (end_config,
+ end_config_cmd,
+ "end_configuration",
+ "The End of Configuration\n")
+{
+ time_t readin_time;
+ char readin_time_str[MONOTIME_STRLEN];
+
+ readin_time = monotime(NULL);
+ readin_time -= callback.readin_time;
+
+ frrtime_to_interval(readin_time, readin_time_str,
+ sizeof(readin_time_str));
+
+ zlog_info("Configuration Read in Took: %s", readin_time_str);
+
+ if (callback.end_config)
+ (*callback.end_config)();
+
+ return CMD_SUCCESS;
+}
+
+void cmd_init_config_callbacks(void (*start_config)(void),
+ void (*end_config)(void))
+{
+ callback.start_config = start_config;
+ callback.end_config = end_config;
+}
+
+
static void defaults_autocomplete(vector comps, struct cmd_token *token)
{
const char **p;
@@ -234,6 +285,9 @@ void lib_cmd_init(void)
install_element(VIEW_NODE, &show_memory_cmd);
install_element(VIEW_NODE, &show_modules_cmd);
+
+ install_element(CONFIG_NODE, &start_config_cmd);
+ install_element(CONFIG_NODE, &end_config_cmd);
}
/* Stats querying from users */
diff --git a/lib/vty.c b/lib/vty.c
index 1eb417163..21b3d47b0 100644
--- a/lib/vty.c
+++ b/lib/vty.c
@@ -1811,6 +1811,7 @@ static int vty_accept(struct thread *thread)
set_cloexec(vty_sock);
if (!sockunion2hostprefix(&su, &p)) {
+ close(vty_sock);
zlog_info("Vty unable to convert prefix from sockunion %s",
sockunion2str(&su, buf, SU_ADDRSTRLEN));
return -1;
diff --git a/lib/yang.c b/lib/yang.c
index c59cb642f..22fe938e4 100644
--- a/lib/yang.c
+++ b/lib/yang.c
@@ -772,8 +772,7 @@ const struct lyd_node *yang_dnode_get_parent(const struct lyd_node *dnode,
return NULL;
}
-/* API to check if the given node is last node in the list */
-static bool yang_is_last_list_dnode(const struct lyd_node *dnode)
+bool yang_is_last_list_dnode(const struct lyd_node *dnode)
{
return (((dnode->next == NULL)
|| (dnode->next
@@ -785,8 +784,7 @@ static bool yang_is_last_list_dnode(const struct lyd_node *dnode)
!= 0)));
}
-/* API to check if the given node is last node in the data tree level */
-static bool yang_is_last_level_dnode(const struct lyd_node *dnode)
+bool yang_is_last_level_dnode(const struct lyd_node *dnode)
{
const struct lyd_node *parent;
const struct lys_node_list *snode;
diff --git a/lib/yang.h b/lib/yang.h
index 0cd6a4a6f..b8bf07ee7 100644
--- a/lib/yang.h
+++ b/lib/yang.h
@@ -587,6 +587,11 @@ extern uint32_t yang_get_list_elements_count(const struct lyd_node *node);
/* To get the immediate child of a dnode */
const struct lyd_node *yang_dnode_get_child(const struct lyd_node *dnode);
+/* API to check if the given node is last node in the list */
+bool yang_is_last_list_dnode(const struct lyd_node *dnode);
+
+/* API to check if the given node is last node in the data tree level */
+bool yang_is_last_level_dnode(const struct lyd_node *dnode);
#ifdef __cplusplus
}
diff --git a/ospf6d/ospf6_snmp.c b/ospf6d/ospf6_snmp.c
index 1836dc206..51a3bff2a 100644
--- a/ospf6d/ospf6_snmp.c
+++ b/ospf6d/ospf6_snmp.c
@@ -963,8 +963,6 @@ static uint8_t *ospfv3WwLsdbEntry(struct variable *v, oid *name, size_t *length,
else if (v->magic & OSPFv3WWLINKTABLE) {
/* We build a sorted list of interfaces */
ifslist = list_new();
- if (!ifslist)
- return NULL;
ifslist->cmp = (int (*)(void *, void *))if_icmp_func;
FOR_ALL_INTERFACES (vrf, iif)
listnode_add_sort(ifslist, iif);
@@ -993,6 +991,7 @@ static uint8_t *ospfv3WwLsdbEntry(struct variable *v, oid *name, size_t *length,
}
list_delete_all_node(ifslist);
+ list_delete(&ifslist);
}
}
@@ -1100,8 +1099,6 @@ static uint8_t *ospfv3IfEntry(struct variable *v, oid *name, size_t *length,
} else {
/* We build a sorted list of interfaces */
ifslist = list_new();
- if (!ifslist)
- return NULL;
ifslist->cmp = (int (*)(void *, void *))if_icmp_func;
FOR_ALL_INTERFACES (vrf, iif)
listnode_add_sort(ifslist, iif);
@@ -1121,6 +1118,7 @@ static uint8_t *ospfv3IfEntry(struct variable *v, oid *name, size_t *length,
}
list_delete_all_node(ifslist);
+ list_delete(&ifslist);
}
if (!oi)
diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c
index adf6faef5..81a778fd5 100644
--- a/pimd/pim_cmd.c
+++ b/pimd/pim_cmd.c
@@ -64,6 +64,9 @@
#include "pim_mlag.h"
#include "bfd.h"
#include "pim_bsm.h"
+#include "lib/northbound_cli.h"
+#include "pim_errors.h"
+#include "pim_nb.h"
#ifndef VTYSH_EXTRACT_PL
#include "pimd/pim_cmd_clippy.c"
@@ -101,94 +104,6 @@ static struct vrf *pim_cmd_lookup_vrf(struct vty *vty, struct cmd_token *argv[],
return vrf;
}
-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 void pim_show_assert_helper(struct vty *vty,
struct pim_interface *pim_ifp,
struct pim_ifchannel *ch, time_t now)
@@ -6797,83 +6712,6 @@ DEFUN (show_ip_ssmpingd,
return CMD_SUCCESS;
}
-static int pim_rp_cmd_worker(struct pim_instance *pim, struct vty *vty,
- const char *rp, const char *group,
- const char *plist)
-{
- int result;
-
- result = pim_rp_new_config(pim, rp, group, plist);
-
- if (result == PIM_GROUP_BAD_ADDR_MASK_COMBO) {
- vty_out(vty, "%% Inconsistent address and mask: %s\n",
- group ? group : "No Group Address");
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- if (result == PIM_GROUP_BAD_ADDRESS) {
- vty_out(vty, "%% Bad group address specified: %s\n",
- group ? group : "No Group Address");
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- if (result == PIM_RP_BAD_ADDRESS) {
- vty_out(vty, "%% Bad RP address specified: %s\n", rp);
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- if (result == PIM_RP_NO_PATH) {
- vty_out(vty, "%% No Path to RP address specified: %s\n", rp);
- return CMD_WARNING;
- }
-
- if (result == PIM_GROUP_OVERLAP) {
- vty_out(vty,
- "%% Group range specified cannot exact match another\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- if (result == PIM_GROUP_PFXLIST_OVERLAP) {
- vty_out(vty,
- "%% This group is already covered by a RP prefix-list\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- if (result == PIM_RP_PFXLIST_IN_USE) {
- vty_out(vty,
- "%% The same prefix-list cannot be applied to multiple RPs\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- return CMD_SUCCESS;
-}
-
-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 CMD_SUCCESS;
-}
-
DEFUN (ip_pim_spt_switchover_infinity,
ip_pim_spt_switchover_infinity_cmd,
"ip pim spt-switchover infinity-and-beyond",
@@ -6882,8 +6720,45 @@ DEFUN (ip_pim_spt_switchover_infinity,
"SPT-Switchover\n"
"Never switch to SPT Tree\n")
{
- PIM_DECLVAR_CONTEXT(vrf, pim);
- return pim_cmd_spt_switchover(pim, PIM_SPT_INFINITY, NULL);
+ const struct lyd_node *vrf_dnode;
+ const char *vrfname;
+ char spt_plist_xpath[XPATH_MAXLEN];
+ char spt_action_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(spt_plist_xpath, sizeof(spt_plist_xpath),
+ FRR_PIM_AF_XPATH, "frr-pim:pimd", "pim", vrfname,
+ "frr-routing:ipv4");
+ strlcat(spt_plist_xpath, "/spt-switchover/spt-infinity-prefix-list",
+ sizeof(spt_plist_xpath));
+
+ snprintf(spt_action_xpath, sizeof(spt_action_xpath),
+ FRR_PIM_AF_XPATH, "frr-pim:pimd", "pim", vrfname,
+ "frr-routing:ipv4");
+ strlcat(spt_action_xpath, "/spt-switchover/spt-action",
+ sizeof(spt_action_xpath));
+
+ if (yang_dnode_exists(vty->candidate_config->dnode, spt_plist_xpath))
+ nb_cli_enqueue_change(vty, spt_plist_xpath, NB_OP_DESTROY,
+ NULL);
+ nb_cli_enqueue_change(vty, spt_action_xpath, NB_OP_MODIFY,
+ "PIM_SPT_INFINITY");
+
+ return nb_cli_apply_changes(vty, NULL);
}
DEFUN (ip_pim_spt_switchover_infinity_plist,
@@ -6896,8 +6771,44 @@ DEFUN (ip_pim_spt_switchover_infinity_plist,
"Prefix-List to control which groups to switch\n"
"Prefix-List name\n")
{
- PIM_DECLVAR_CONTEXT(vrf, pim);
- return pim_cmd_spt_switchover(pim, PIM_SPT_INFINITY, argv[5]->arg);
+ const struct lyd_node *vrf_dnode;
+ const char *vrfname;
+ char spt_plist_xpath[XPATH_MAXLEN];
+ char spt_action_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(spt_plist_xpath, sizeof(spt_plist_xpath),
+ FRR_PIM_AF_XPATH, "frr-pim:pimd", "pim", vrfname,
+ "frr-routing:ipv4");
+ strlcat(spt_plist_xpath, "/spt-switchover/spt-infinity-prefix-list",
+ sizeof(spt_plist_xpath));
+
+ snprintf(spt_action_xpath, sizeof(spt_action_xpath),
+ FRR_PIM_AF_XPATH, "frr-pim:pimd", "pim", vrfname,
+ "frr-routing:ipv4");
+ strlcat(spt_action_xpath, "/spt-switchover/spt-action",
+ sizeof(spt_action_xpath));
+
+ nb_cli_enqueue_change(vty, spt_action_xpath, NB_OP_MODIFY,
+ "PIM_SPT_INFINITY");
+ nb_cli_enqueue_change(vty, spt_plist_xpath, NB_OP_MODIFY,
+ argv[5]->arg);
+
+ return nb_cli_apply_changes(vty, NULL);
}
DEFUN (no_ip_pim_spt_switchover_infinity,
@@ -6909,8 +6820,43 @@ DEFUN (no_ip_pim_spt_switchover_infinity,
"SPT_Switchover\n"
"Never switch to SPT Tree\n")
{
- PIM_DECLVAR_CONTEXT(vrf, pim);
- return pim_cmd_spt_switchover(pim, PIM_SPT_IMMEDIATE, NULL);
+ const struct lyd_node *vrf_dnode;
+ const char *vrfname;
+ char spt_plist_xpath[XPATH_MAXLEN];
+ char spt_action_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(spt_plist_xpath, sizeof(spt_plist_xpath),
+ FRR_PIM_AF_XPATH, "frr-pim:pimd", "pim", vrfname,
+ "frr-routing:ipv4");
+ strlcat(spt_plist_xpath, "/spt-switchover/spt-infinity-prefix-list",
+ sizeof(spt_plist_xpath));
+
+ snprintf(spt_action_xpath, sizeof(spt_action_xpath),
+ FRR_PIM_AF_XPATH, "frr-pim:pimd", "pim", vrfname,
+ "frr-routing:ipv4");
+ strlcat(spt_action_xpath, "/spt-switchover/spt-action",
+ sizeof(spt_action_xpath));
+
+ nb_cli_enqueue_change(vty, spt_plist_xpath, NB_OP_DESTROY, NULL);
+ nb_cli_enqueue_change(vty, spt_action_xpath, NB_OP_MODIFY,
+ "PIM_SPT_IMMEDIATE");
+
+ return nb_cli_apply_changes(vty, NULL);
}
DEFUN (no_ip_pim_spt_switchover_infinity_plist,
@@ -6924,8 +6870,43 @@ DEFUN (no_ip_pim_spt_switchover_infinity_plist,
"Prefix-List to control which groups to switch\n"
"Prefix-List name\n")
{
- PIM_DECLVAR_CONTEXT(vrf, pim);
- return pim_cmd_spt_switchover(pim, PIM_SPT_IMMEDIATE, NULL);
+ const struct lyd_node *vrf_dnode;
+ const char *vrfname;
+ char spt_plist_xpath[XPATH_MAXLEN];
+ char spt_action_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(spt_plist_xpath, sizeof(spt_plist_xpath),
+ FRR_PIM_AF_XPATH, "frr-pim:pimd", "pim", vrfname,
+ "frr-routing:ipv4");
+ strlcat(spt_plist_xpath, "/spt-switchover/spt-infinity-prefix-list",
+ sizeof(spt_plist_xpath));
+
+ snprintf(spt_action_xpath, sizeof(spt_action_xpath),
+ FRR_PIM_AF_XPATH, "frr-pim:pimd", "pim", vrfname,
+ "frr-routing:ipv4");
+ strlcat(spt_action_xpath, "/spt-switchover/spt-action",
+ sizeof(spt_action_xpath));
+
+ nb_cli_enqueue_change(vty, spt_plist_xpath, NB_OP_DESTROY, NULL);
+ nb_cli_enqueue_change(vty, spt_action_xpath, NB_OP_MODIFY,
+ "PIM_SPT_IMMEDIATE");
+
+ return nb_cli_apply_changes(vty, NULL);
}
DEFPY (pim_register_accept_list,
@@ -6937,15 +6918,37 @@ DEFPY (pim_register_accept_list,
"Only accept registers from a specific source prefix list\n"
"Prefix-List name\n")
{
- PIM_DECLVAR_CONTEXT(vrf, pim);
+ const struct lyd_node *vrf_dnode;
+ const char *vrfname;
+ char reg_alist_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(reg_alist_xpath, sizeof(reg_alist_xpath),
+ FRR_PIM_AF_XPATH, "frr-pim:pimd", "pim", vrfname,
+ "frr-routing:ipv4");
+ strlcat(reg_alist_xpath, "/register-accept-list",
+ sizeof(reg_alist_xpath));
if (no)
- XFREE(MTYPE_PIM_PLIST_NAME, pim->register_plist);
- else {
- XFREE(MTYPE_PIM_PLIST_NAME, pim->register_plist);
- pim->register_plist = XSTRDUP(MTYPE_PIM_PLIST_NAME, word);
- }
- return CMD_SUCCESS;
+ nb_cli_enqueue_change(vty, reg_alist_xpath,
+ NB_OP_DESTROY, NULL);
+ else
+ nb_cli_enqueue_change(vty, reg_alist_xpath,
+ NB_OP_MODIFY, word);
+
+ return nb_cli_apply_changes(vty, NULL);
}
DEFUN (ip_pim_joinprune_time,
@@ -6956,9 +6959,10 @@ DEFUN (ip_pim_joinprune_time,
"Join Prune Send Interval\n"
"Seconds\n")
{
- PIM_DECLVAR_CONTEXT(vrf, pim);
- router->t_periodic = atoi(argv[3]->arg);
- return CMD_SUCCESS;
+ nb_cli_enqueue_change(vty, "/frr-pim:pim/join-prune-interval",
+ NB_OP_MODIFY, argv[3]->arg);
+
+ return nb_cli_apply_changes(vty, NULL);
}
DEFUN (no_ip_pim_joinprune_time,
@@ -6970,9 +6974,15 @@ DEFUN (no_ip_pim_joinprune_time,
"Join Prune Send Interval\n"
"Seconds\n")
{
- PIM_DECLVAR_CONTEXT(vrf, pim);
- router->t_periodic = PIM_DEFAULT_T_PERIODIC;
- return CMD_SUCCESS;
+ char jp_default_timer[5];
+
+ snprintf(jp_default_timer, sizeof(jp_default_timer), "%d",
+ PIM_DEFAULT_T_PERIODIC);
+
+ nb_cli_enqueue_change(vty, "/frr-pim:pim/join-prune-interval",
+ NB_OP_MODIFY, jp_default_timer);
+
+ return nb_cli_apply_changes(vty, NULL);
}
DEFUN (ip_pim_register_suppress,
@@ -6983,9 +6993,10 @@ DEFUN (ip_pim_register_suppress,
"Register Suppress Timer\n"
"Seconds\n")
{
- PIM_DECLVAR_CONTEXT(vrf, pim);
- router->register_suppress_time = atoi(argv[3]->arg);
- return CMD_SUCCESS;
+ nb_cli_enqueue_change(vty, "/frr-pim:pim/register-suppress-time",
+ NB_OP_MODIFY, argv[3]->arg);
+
+ return nb_cli_apply_changes(vty, NULL);
}
DEFUN (no_ip_pim_register_suppress,
@@ -6997,9 +7008,15 @@ DEFUN (no_ip_pim_register_suppress,
"Register Suppress Timer\n"
"Seconds\n")
{
- PIM_DECLVAR_CONTEXT(vrf, pim);
- router->register_suppress_time = PIM_REGISTER_SUPPRESSION_TIME_DEFAULT;
- return CMD_SUCCESS;
+ char rs_default_timer[5];
+
+ snprintf(rs_default_timer, sizeof(rs_default_timer), "%d",
+ PIM_REGISTER_SUPPRESSION_TIME_DEFAULT);
+
+ nb_cli_enqueue_change(vty, "/frr-pim:pim/register-suppress-time",
+ NB_OP_MODIFY, rs_default_timer);
+
+ return nb_cli_apply_changes(vty, NULL);
}
DEFUN (ip_pim_rp_keep_alive,
@@ -7011,9 +7028,32 @@ DEFUN (ip_pim_rp_keep_alive,
"Keep alive Timer\n"
"Seconds\n")
{
- PIM_DECLVAR_CONTEXT(vrf, pim);
- pim->rp_keep_alive_time = atoi(argv[4]->arg);
- return CMD_SUCCESS;
+ const struct lyd_node *vrf_dnode;
+ const char *vrfname;
+ char rp_ka_timer_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(rp_ka_timer_xpath, sizeof(rp_ka_timer_xpath),
+ FRR_PIM_XPATH, "frr-pim:pimd", "pim", vrfname);
+ strlcat(rp_ka_timer_xpath, "/rp-keep-alive-timer",
+ sizeof(rp_ka_timer_xpath));
+
+ nb_cli_enqueue_change(vty, rp_ka_timer_xpath, NB_OP_MODIFY,
+ argv[4]->arg);
+
+ return nb_cli_apply_changes(vty, NULL);
}
DEFUN (no_ip_pim_rp_keep_alive,
@@ -7026,9 +7066,36 @@ DEFUN (no_ip_pim_rp_keep_alive,
"Keep alive Timer\n"
"Seconds\n")
{
- PIM_DECLVAR_CONTEXT(vrf, pim);
- pim->rp_keep_alive_time = PIM_KEEPALIVE_PERIOD;
- return CMD_SUCCESS;
+ const struct lyd_node *vrf_dnode;
+ const char *vrfname;
+ char rp_ka_timer[5];
+ char rp_ka_timer_xpath[XPATH_MAXLEN];
+
+ snprintf(rp_ka_timer, sizeof(rp_ka_timer), "%d", PIM_KEEPALIVE_PERIOD);
+
+ 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(rp_ka_timer_xpath, sizeof(rp_ka_timer_xpath),
+ FRR_PIM_XPATH, "frr-pim:pimd", "pim", vrfname);
+ strlcat(rp_ka_timer_xpath, "/rp-keep-alive-timer",
+ sizeof(rp_ka_timer_xpath));
+
+ nb_cli_enqueue_change(vty, rp_ka_timer_xpath, NB_OP_MODIFY,
+ rp_ka_timer);
+
+ return nb_cli_apply_changes(vty, NULL);
}
DEFUN (ip_pim_keep_alive,
@@ -7039,9 +7106,31 @@ DEFUN (ip_pim_keep_alive,
"Keep alive Timer\n"
"Seconds\n")
{
- PIM_DECLVAR_CONTEXT(vrf, pim);
- pim->keep_alive_time = atoi(argv[3]->arg);
- return CMD_SUCCESS;
+ const struct lyd_node *vrf_dnode;
+ const char *vrfname;
+ char ka_timer_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(ka_timer_xpath, sizeof(ka_timer_xpath), FRR_PIM_XPATH,
+ "frr-pim:pimd", "pim", vrfname);
+ strlcat(ka_timer_xpath, "/keep-alive-timer", sizeof(ka_timer_xpath));
+
+ nb_cli_enqueue_change(vty, ka_timer_xpath, NB_OP_MODIFY,
+ argv[3]->arg);
+
+ return nb_cli_apply_changes(vty, NULL);
}
DEFUN (no_ip_pim_keep_alive,
@@ -7053,9 +7142,34 @@ DEFUN (no_ip_pim_keep_alive,
"Keep alive Timer\n"
"Seconds\n")
{
- PIM_DECLVAR_CONTEXT(vrf, pim);
- pim->keep_alive_time = PIM_KEEPALIVE_PERIOD;
- return CMD_SUCCESS;
+ const struct lyd_node *vrf_dnode;
+ const char *vrfname;
+ char ka_timer[5];
+ char ka_timer_xpath[XPATH_MAXLEN];
+
+ snprintf(ka_timer, sizeof(ka_timer), "%d", PIM_KEEPALIVE_PERIOD);
+
+ 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(ka_timer_xpath, sizeof(ka_timer_xpath), FRR_PIM_XPATH,
+ "frr-pim:pimd", "pim", vrfname);
+ strlcat(ka_timer_xpath, "/keep-alive-timer", sizeof(ka_timer_xpath));
+
+ nb_cli_enqueue_change(vty, ka_timer_xpath, NB_OP_MODIFY,
+ ka_timer);
+
+ return nb_cli_apply_changes(vty, NULL);
}
DEFUN (ip_pim_packets,
@@ -7066,9 +7180,10 @@ DEFUN (ip_pim_packets,
"packets to process at one time per fd\n"
"Number of packets\n")
{
- PIM_DECLVAR_CONTEXT(vrf, pim);
- router->packet_process = atoi(argv[3]->arg);
- return CMD_SUCCESS;
+ nb_cli_enqueue_change(vty, "/frr-pim:pim/packets", NB_OP_MODIFY,
+ argv[3]->arg);
+
+ return nb_cli_apply_changes(vty, NULL);
}
DEFUN (no_ip_pim_packets,
@@ -7080,9 +7195,15 @@ DEFUN (no_ip_pim_packets,
"packets to process at one time per fd\n"
"Number of packets\n")
{
- PIM_DECLVAR_CONTEXT(vrf, pim);
- router->packet_process = PIM_DEFAULT_PACKET_PROCESS;
- return CMD_SUCCESS;
+ char default_packet[3];
+
+ snprintf(default_packet, sizeof(default_packet), "%d",
+ PIM_DEFAULT_PACKET_PROCESS);
+
+ nb_cli_enqueue_change(vty, "/frr-pim:pim/packets", NB_OP_MODIFY,
+ default_packet);
+
+ return nb_cli_apply_changes(vty, NULL);
}
DEFPY (igmp_group_watermark,
@@ -7121,10 +7242,33 @@ DEFUN (ip_pim_v6_secondary,
"pim multicast routing\n"
"Send v6 secondary addresses\n")
{
- PIM_DECLVAR_CONTEXT(vrf, pim);
- pim->send_v6_secondary = 1;
+ const struct lyd_node *vrf_dnode;
+ const char *vrfname;
+ char send_v6_secondary_xpath[XPATH_MAXLEN];
- return CMD_SUCCESS;
+ 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(send_v6_secondary_xpath, sizeof(send_v6_secondary_xpath),
+ FRR_PIM_AF_XPATH,
+ "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4");
+ strlcat(send_v6_secondary_xpath, "/send-v6-secondary",
+ sizeof(send_v6_secondary_xpath));
+
+ nb_cli_enqueue_change(vty, send_v6_secondary_xpath, NB_OP_MODIFY,
+ "true");
+
+ return nb_cli_apply_changes(vty, NULL);
}
DEFUN (no_ip_pim_v6_secondary,
@@ -7135,10 +7279,33 @@ DEFUN (no_ip_pim_v6_secondary,
"pim multicast routing\n"
"Send v6 secondary addresses\n")
{
- PIM_DECLVAR_CONTEXT(vrf, pim);
- pim->send_v6_secondary = 0;
+ const struct lyd_node *vrf_dnode;
+ const char *vrfname;
+ char send_v6_secondary_xpath[XPATH_MAXLEN];
- return CMD_SUCCESS;
+ 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(send_v6_secondary_xpath, sizeof(send_v6_secondary_xpath),
+ FRR_PIM_AF_XPATH,
+ "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4");
+ strlcat(send_v6_secondary_xpath, "/send-v6-secondary",
+ sizeof(send_v6_secondary_xpath));
+
+ nb_cli_enqueue_change(vty, send_v6_secondary_xpath, NB_OP_MODIFY,
+ "false");
+
+ return nb_cli_apply_changes(vty, NULL);
}
DEFUN (ip_pim_rp,
@@ -7150,15 +7317,66 @@ DEFUN (ip_pim_rp,
"ip address of RP\n"
"Group Address range to cover\n")
{
- PIM_DECLVAR_CONTEXT(vrf, pim);
- int idx_ipv4 = 3;
+ const struct lyd_node *vrf_dnode;
+ const char *vrfname;
+ int idx_rp = 3, idx_group = 4;
+ char rp_group_xpath[XPATH_MAXLEN];
+ int result = 0;
+ struct prefix group;
+ struct in_addr rp_addr;
+ const char *group_str =
+ (argc == 5) ? argv[idx_group]->arg : "224.0.0.0/4";
- if (argc == (idx_ipv4 + 1))
- return pim_rp_cmd_worker(pim, vty, argv[idx_ipv4]->arg, NULL,
- NULL);
- else
- return pim_rp_cmd_worker(pim, vty, argv[idx_ipv4]->arg,
- argv[idx_ipv4 + 1]->arg, NULL);
+ result = str2prefix(group_str, &group);
+ if (result) {
+ struct prefix temp;
+
+ prefix_copy(&temp, &group);
+ apply_mask(&temp);
+ if (!prefix_same(&group, &temp)) {
+ vty_out(vty, "%% Inconsistent address and mask: %s\n",
+ group_str);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ }
+
+ if (!result) {
+ vty_out(vty, "%% Bad group address specified: %s\n",
+ group_str);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ result = inet_pton(AF_INET, argv[idx_rp]->arg, &rp_addr);
+ if (result <= 0) {
+ vty_out(vty, "%% Bad RP address specified: %s\n",
+ argv[idx_rp]->arg);
+ 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;
+
+ snprintf(rp_group_xpath, sizeof(rp_group_xpath),
+ FRR_PIM_STATIC_RP_XPATH,
+ "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4",
+ argv[idx_rp]->arg);
+ strlcat(rp_group_xpath, "/group-list", sizeof(rp_group_xpath));
+
+ nb_cli_enqueue_change(vty, rp_group_xpath, NB_OP_CREATE, group_str);
+
+ return nb_cli_apply_changes(vty, NULL);
}
DEFUN (ip_pim_rp_prefix_list,
@@ -7171,33 +7389,36 @@ DEFUN (ip_pim_rp_prefix_list,
"group prefix-list filter\n"
"Name of a prefix-list\n")
{
- PIM_DECLVAR_CONTEXT(vrf, pim);
- return pim_rp_cmd_worker(pim, vty, argv[3]->arg, NULL, argv[5]->arg);
-}
+ int idx_rp = 3, idx_plist = 5;
+ const struct lyd_node *vrf_dnode;
+ const char *vrfname;
+ char rp_plist_xpath[XPATH_MAXLEN];
-static int pim_no_rp_cmd_worker(struct pim_instance *pim, struct vty *vty,
- const char *rp, const char *group,
- const char *plist)
-{
- int result = pim_rp_del_config(pim, rp, group, plist);
+ if (vty->xpath_index) {
+ vrf_dnode =
+ yang_dnode_get(vty->candidate_config->dnode,
+ VTY_CURR_XPATH);
- if (result == PIM_GROUP_BAD_ADDRESS) {
- vty_out(vty, "%% Bad group address specified: %s\n",
- group ? group : "No Group Address");
- return CMD_WARNING_CONFIG_FAILED;
- }
+ if (!vrf_dnode) {
+ vty_out(vty,
+ "%% Failed to get vrf dnode in candidate db\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
- if (result == PIM_RP_BAD_ADDRESS) {
- vty_out(vty, "%% Bad RP address specified: %s\n", rp);
- return CMD_WARNING_CONFIG_FAILED;
- }
+ vrfname = yang_dnode_get_string(vrf_dnode, "./name");
+ } else
+ vrfname = VRF_DEFAULT_NAME;
- if (result == PIM_RP_NOT_FOUND) {
- vty_out(vty, "%% Unable to find specified RP\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
+ snprintf(rp_plist_xpath, sizeof(rp_plist_xpath),
+ FRR_PIM_STATIC_RP_XPATH,
+ "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4",
+ argv[idx_rp]->arg);
+ strlcat(rp_plist_xpath, "/prefix-list", sizeof(rp_plist_xpath));
- return CMD_SUCCESS;
+ nb_cli_enqueue_change(vty, rp_plist_xpath, NB_OP_MODIFY,
+ argv[idx_plist]->arg);
+
+ return nb_cli_apply_changes(vty, NULL);
}
DEFUN (no_ip_pim_rp,
@@ -7210,15 +7431,55 @@ DEFUN (no_ip_pim_rp,
"ip address of RP\n"
"Group Address range to cover\n")
{
- PIM_DECLVAR_CONTEXT(vrf, pim);
- int idx_ipv4 = 4, idx_group = 0;
+ int idx_rp = 4, idx_group = 5;
+ const char *group_str =
+ (argc == 6) ? argv[idx_group]->arg : "224.0.0.0/4";
+ char group_xpath[XPATH_MAXLEN];
+ char temp_xpath[XPATH_MAXLEN];
+ char rp_xpath[XPATH_MAXLEN];
+ const struct lyd_node *vrf_dnode;
+ const char *vrfname;
+ const struct lyd_node *group_dnode;
+
+ 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;
- if (argv_find(argv, argc, "A.B.C.D/M", &idx_group))
- return pim_no_rp_cmd_worker(pim, vty, argv[idx_ipv4]->arg,
- argv[idx_group]->arg, NULL);
+ snprintf(rp_xpath, sizeof(rp_xpath), FRR_PIM_STATIC_RP_XPATH,
+ "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4",
+ argv[idx_rp]->arg);
+
+ snprintf(group_xpath, sizeof(group_xpath), FRR_PIM_STATIC_RP_XPATH,
+ "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4",
+ argv[idx_rp]->arg);
+ snprintf(temp_xpath, sizeof(temp_xpath), "/group-list[.='%s']",
+ group_str);
+ strlcat(group_xpath, temp_xpath, sizeof(group_xpath));
+
+ if (!yang_dnode_exists(vty->candidate_config->dnode, group_xpath)) {
+ vty_out(vty, "%% Unable to find specified RP\n");
+ return NB_OK;
+ }
+
+ group_dnode = yang_dnode_get(vty->candidate_config->dnode, group_xpath);
+
+ if (yang_is_last_list_dnode(group_dnode))
+ nb_cli_enqueue_change(vty, rp_xpath, NB_OP_DESTROY, NULL);
else
- return pim_no_rp_cmd_worker(pim, vty, argv[idx_ipv4]->arg, NULL,
- NULL);
+ nb_cli_enqueue_change(vty, group_xpath, NB_OP_DESTROY, NULL);
+
+ return nb_cli_apply_changes(vty, NULL);
}
DEFUN (no_ip_pim_rp_prefix_list,
@@ -7232,32 +7493,52 @@ DEFUN (no_ip_pim_rp_prefix_list,
"group prefix-list filter\n"
"Name of a prefix-list\n")
{
- PIM_DECLVAR_CONTEXT(vrf, pim);
- return pim_no_rp_cmd_worker(pim, vty, argv[4]->arg, NULL, argv[6]->arg);
-}
+ int idx_rp = 4;
+ int idx_plist = 6;
+ char rp_xpath[XPATH_MAXLEN];
+ char plist_xpath[XPATH_MAXLEN];
+ const struct lyd_node *vrf_dnode;
+ const char *vrfname;
+ const struct lyd_node *plist_dnode;
+ const char *plist;
+
+ 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;
-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;
+ snprintf(rp_xpath, sizeof(rp_xpath), FRR_PIM_STATIC_RP_XPATH,
+ "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4",
+ argv[idx_rp]->arg);
- if (result == PIM_SSM_ERR_NONE)
- return CMD_SUCCESS;
+ snprintf(plist_xpath, sizeof(plist_xpath), FRR_PIM_STATIC_RP_XPATH,
+ "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4",
+ argv[idx_rp]->arg);
+ strlcat(plist_xpath, "/prefix-list", sizeof(plist_xpath));
- 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");
+ plist_dnode = yang_dnode_get(vty->candidate_config->dnode, plist_xpath);
+ if (!plist_dnode) {
+ vty_out(vty, "%% Unable to find specified RP\n");
+ return NB_OK;
+ }
+
+ plist = yang_dnode_get_string(plist_dnode, plist_xpath);
+ if (strcmp(argv[idx_plist]->arg, plist)) {
+ vty_out(vty, "%% Unable to find specified RP\n");
+ return NB_OK;
}
- return ret;
+ nb_cli_enqueue_change(vty, rp_xpath, NB_OP_DESTROY, NULL);
+
+ return nb_cli_apply_changes(vty, NULL);
}
DEFUN (ip_pim_ssm_prefix_list,
@@ -7269,8 +7550,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,
@@ -7282,8 +7586,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,
@@ -7296,11 +7623,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 (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;
+ }
- if (ssm->plist_name && !strcmp(ssm->plist_name, argv[5]->arg))
- return pim_ssm_cmd_worker(pim, vty, NULL);
+ 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);
@@ -7429,27 +7795,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];
+
+ 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 = 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;
- }
+ 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));
- 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;
- }
+ nb_cli_enqueue_change(vty, ssmpingd_ip_xpath, NB_OP_CREATE,
+ source_str);
- return CMD_SUCCESS;
+ return nb_cli_apply_changes(vty, NULL);
}
DEFUN (no_ip_ssmpingd,
@@ -7460,27 +7834,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,
@@ -7490,10 +7872,29 @@ DEFUN (ip_pim_ecmp,
"pim multicast routing\n"
"Enable PIM ECMP \n")
{
- PIM_DECLVAR_CONTEXT(vrf, pim);
- pim->ecmp_enable = true;
+ const struct lyd_node *vrf_dnode;
+ const char *vrfname;
+ char ecmp_xpath[XPATH_MAXLEN];
- return CMD_SUCCESS;
+ 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(ecmp_xpath, sizeof(ecmp_xpath), FRR_PIM_XPATH,
+ "frr-pim:pimd", "pim", vrfname);
+ strlcat(ecmp_xpath, "/ecmp", sizeof(ecmp_xpath));
+
+ nb_cli_enqueue_change(vty, ecmp_xpath, NB_OP_MODIFY, "true");
+ return nb_cli_apply_changes(vty, NULL);
}
DEFUN (no_ip_pim_ecmp,
@@ -7504,10 +7905,30 @@ DEFUN (no_ip_pim_ecmp,
"pim multicast routing\n"
"Disable PIM ECMP \n")
{
- PIM_DECLVAR_CONTEXT(vrf, pim);
- pim->ecmp_enable = false;
+ const struct lyd_node *vrf_dnode;
+ const char *vrfname;
+ char ecmp_xpath[XPATH_MAXLEN];
- return CMD_SUCCESS;
+ 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(ecmp_xpath, sizeof(ecmp_xpath), FRR_PIM_XPATH,
+ "frr-pim:pimd", "pim", vrfname);
+ strlcat(ecmp_xpath, "/ecmp", sizeof(ecmp_xpath));
+
+ nb_cli_enqueue_change(vty, ecmp_xpath, NB_OP_MODIFY, "false");
+
+ return nb_cli_apply_changes(vty, NULL);
}
DEFUN (ip_pim_ecmp_rebalance,
@@ -7518,11 +7939,37 @@ DEFUN (ip_pim_ecmp_rebalance,
"Enable PIM ECMP \n"
"Enable PIM ECMP Rebalance\n")
{
- PIM_DECLVAR_CONTEXT(vrf, pim);
- pim->ecmp_enable = true;
- pim->ecmp_rebalance_enable = true;
+ const struct lyd_node *vrf_dnode;
+ const char *vrfname;
+ char ecmp_xpath[XPATH_MAXLEN];
+ char ecmp_rebalance_xpath[XPATH_MAXLEN];
- return CMD_SUCCESS;
+ 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(ecmp_xpath, sizeof(ecmp_xpath), FRR_PIM_XPATH,
+ "frr-pim:pimd", "pim", vrfname);
+ strlcat(ecmp_xpath, "/ecmp", sizeof(ecmp_xpath));
+ snprintf(ecmp_rebalance_xpath, sizeof(ecmp_rebalance_xpath),
+ FRR_PIM_XPATH,
+ "frr-pim:pimd", "pim", vrfname);
+ strlcat(ecmp_rebalance_xpath, "/ecmp-rebalance",
+ sizeof(ecmp_rebalance_xpath));
+
+ nb_cli_enqueue_change(vty, ecmp_xpath, NB_OP_MODIFY, "true");
+ nb_cli_enqueue_change(vty, ecmp_rebalance_xpath, NB_OP_MODIFY, "true");
+
+ return nb_cli_apply_changes(vty, NULL);
}
DEFUN (no_ip_pim_ecmp_rebalance,
@@ -7534,46 +7981,32 @@ DEFUN (no_ip_pim_ecmp_rebalance,
"Disable PIM ECMP \n"
"Disable PIM ECMP Rebalance\n")
{
- PIM_DECLVAR_CONTEXT(vrf, pim);
- pim->ecmp_rebalance_enable = false;
-
- return CMD_SUCCESS;
-}
+ const struct lyd_node *vrf_dnode;
+ const char *vrfname;
+ char ecmp_rebalance_xpath[XPATH_MAXLEN];
-static int pim_cmd_igmp_start(struct vty *vty, struct interface *ifp)
-{
- struct pim_interface *pim_ifp;
- struct pim_instance *pim;
- uint8_t need_startup = 0;
-
- pim_ifp = ifp->info;
-
- if (!pim_ifp) {
- pim = pim_get_pim_instance(ifp->vrf_id);
- /* Limit mcast interfaces to number of vifs available */
- if (pim->mcast_if_count == MAXVIFS) {
+ if (vty->xpath_index) {
+ vrf_dnode =
+ yang_dnode_get(vty->candidate_config->dnode,
+ VTY_CURR_XPATH);
+ if (!vrf_dnode) {
vty_out(vty,
- "Max multicast interfaces(%d) Reached. Could not enable IGMP on interface %s\n",
- MAXVIFS, ifp->name);
+ "%% Failed to get vrf dnode in candidate db\n");
return CMD_WARNING_CONFIG_FAILED;
}
- (void)pim_if_new(ifp, true, false, false, false);
- need_startup = 1;
- } else {
- if (!PIM_IF_TEST_IGMP(pim_ifp->options)) {
- PIM_IF_DO_IGMP(pim_ifp->options);
- need_startup = 1;
- }
- }
+ vrfname = yang_dnode_get_string(vrf_dnode, "./name");
+ } else
+ vrfname = VRF_DEFAULT_NAME;
- /* '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);
- }
+ snprintf(ecmp_rebalance_xpath, sizeof(ecmp_rebalance_xpath),
+ FRR_PIM_XPATH,
+ "frr-pim:pimd", "pim", vrfname);
+ strlcat(ecmp_rebalance_xpath, "/ecmp-rebalance",
+ sizeof(ecmp_rebalance_xpath));
- return CMD_SUCCESS;
+ nb_cli_enqueue_change(vty, ecmp_rebalance_xpath, NB_OP_MODIFY, "false");
+
+ return nb_cli_apply_changes(vty, NULL);
}
DEFUN (interface_ip_igmp,
@@ -7582,9 +8015,9 @@ DEFUN (interface_ip_igmp,
IP_STR
IFACE_IGMP_STR)
{
- VTY_DECLVAR_CONTEXT(interface, ifp);
+ nb_cli_enqueue_change(vty, "./igmp-enable", NB_OP_MODIFY, "true");
- return pim_cmd_igmp_start(vty, ifp);
+ return nb_cli_apply_changes(vty, "./frr-igmp:igmp");
}
DEFUN (interface_no_ip_igmp,
@@ -7594,23 +8027,28 @@ DEFUN (interface_no_ip_igmp,
IP_STR
IFACE_IGMP_STR)
{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct pim_interface *pim_ifp = ifp->info;
-
- if (!pim_ifp)
- return CMD_SUCCESS;
-
- PIM_IF_DONT_IGMP(pim_ifp->options);
+ const struct lyd_node *pim_enable_dnode;
+ char pim_if_xpath[XPATH_MAXLEN];
- pim_if_membership_clear(ifp);
+ snprintf(pim_if_xpath, sizeof(pim_if_xpath),
+ "%s/frr-pim:pim", VTY_CURR_XPATH);
- pim_if_addr_del_all_igmp(ifp);
-
- if (!PIM_IF_TEST_PIM(pim_ifp->options)) {
- pim_if_delete(ifp);
+ pim_enable_dnode = yang_dnode_get(vty->candidate_config->dnode,
+ "%s/pim-enable", pim_if_xpath);
+ if (!pim_enable_dnode) {
+ nb_cli_enqueue_change(vty, pim_if_xpath, NB_OP_DESTROY, NULL);
+ nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
+ } else {
+ if (!yang_dnode_get_bool(pim_enable_dnode, ".")) {
+ nb_cli_enqueue_change(vty, pim_if_xpath, NB_OP_DESTROY,
+ NULL);
+ nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
+ } else
+ nb_cli_enqueue_change(vty, "./igmp-enable",
+ NB_OP_MODIFY, "false");
}
- return CMD_SUCCESS;
+ return nb_cli_apply_changes(vty, "./frr-igmp:igmp");
}
DEFUN (interface_ip_igmp_join,
@@ -7622,46 +8060,28 @@ DEFUN (interface_ip_igmp_join,
"Multicast group address\n"
"Source address\n")
{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- int idx_ipv4 = 3;
- int idx_ipv4_2 = 4;
- const char *group_str;
+ int idx_group = 3;
+ int idx_source = 4;
const char *source_str;
- struct in_addr group_addr;
- struct in_addr source_addr;
- int result;
+ char xpath[XPATH_MAXLEN];
- /* Group address */
- group_str = argv[idx_ipv4]->arg;
- result = inet_pton(AF_INET, group_str, &group_addr);
- if (result <= 0) {
- vty_out(vty, "Bad group address %s: errno=%d: %s\n", group_str,
- errno, safe_strerror(errno));
- return CMD_WARNING_CONFIG_FAILED;
- }
+ if (argc == 5) {
+ source_str = argv[idx_source]->arg;
- /* Source address */
- if (argc == (idx_ipv4_2 + 1)) {
- source_str = argv[idx_ipv4_2]->arg;
- 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;
- }
- /* Reject 0.0.0.0. Reserved for any source. */
- if (source_addr.s_addr == INADDR_ANY) {
- vty_out(vty, "Bad source address %s\n", source_str);
+ if (strcmp(source_str, "0.0.0.0") == 0) {
+ vty_out(vty, "Bad source address %s\n",
+ argv[idx_source]->arg);
return CMD_WARNING_CONFIG_FAILED;
}
- } else {
- source_addr.s_addr = INADDR_ANY;
- }
+ } else
+ source_str = "0.0.0.0";
- CMD_FERR_RETURN(pim_if_igmp_join_add(ifp, group_addr, source_addr),
- "Failure joining IGMP group: $ERR");
+ snprintf(xpath, sizeof(xpath), FRR_IGMP_JOIN_XPATH,
+ "frr-routing:ipv4", argv[idx_group]->arg, source_str);
- return CMD_SUCCESS;
+ nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
+
+ return nb_cli_apply_changes(vty, NULL);
}
DEFUN (interface_no_ip_igmp_join,
@@ -7674,190 +8094,30 @@ DEFUN (interface_no_ip_igmp_join,
"Multicast group address\n"
"Source address\n")
{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- int idx_ipv4 = 4;
- int idx_ipv4_2 = 5;
- const char *group_str;
+ int idx_group = 4;
+ int idx_source = 5;
const char *source_str;
- struct in_addr group_addr;
- struct in_addr source_addr;
- int result;
+ char xpath[XPATH_MAXLEN];
- /* Group address */
- group_str = argv[idx_ipv4]->arg;
- result = inet_pton(AF_INET, group_str, &group_addr);
- if (result <= 0) {
- vty_out(vty, "Bad group address %s: errno=%d: %s\n", group_str,
- errno, safe_strerror(errno));
- return CMD_WARNING_CONFIG_FAILED;
- }
+ if (argc == 6) {
+ source_str = argv[idx_source]->arg;
- /* Source address */
- if (argc == (idx_ipv4_2 + 1)) {
- source_str = argv[idx_ipv4_2]->arg;
- 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;
- }
- /* Reject 0.0.0.0. Reserved for any source. */
- if (source_addr.s_addr == INADDR_ANY) {
- vty_out(vty, "Bad source address %s\n", source_str);
+ if (strcmp(source_str, "0.0.0.0") == 0) {
+ vty_out(vty, "Bad source address %s\n",
+ argv[idx_source]->arg);
return CMD_WARNING_CONFIG_FAILED;
}
- } else {
- source_str = "*";
- source_addr.s_addr = INADDR_ANY;
- }
-
- result = pim_if_igmp_join_del(ifp, group_addr, source_addr);
- if (result) {
- vty_out(vty,
- "%% Failure leaving IGMP group %s source %s on interface %s: %d\n",
- group_str, source_str, ifp->name, result);
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- return CMD_SUCCESS;
-}
-
-/*
- CLI reconfiguration affects the interface level (struct pim_interface).
- This function propagates the reconfiguration to every active socket
- for that interface.
- */
-static void igmp_sock_query_interval_reconfig(struct igmp_sock *igmp)
-{
- struct interface *ifp;
- struct pim_interface *pim_ifp;
-
- zassert(igmp);
-
- /* other querier present? */
-
- if (igmp->t_other_querier_timer)
- return;
-
- /* this is the querier */
-
- zassert(igmp->interface);
- zassert(igmp->interface->info);
-
- ifp = igmp->interface;
- pim_ifp = ifp->info;
-
- if (PIM_DEBUG_IGMP_TRACE) {
- char ifaddr_str[INET_ADDRSTRLEN];
- pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str,
- sizeof(ifaddr_str));
- zlog_debug("%s: Querier %s on %s reconfig query_interval=%d",
- __func__, ifaddr_str, ifp->name,
- pim_ifp->igmp_default_query_interval);
- }
-
- /*
- igmp_startup_mode_on() will reset QQI:
-
- igmp->querier_query_interval = pim_ifp->igmp_default_query_interval;
- */
- igmp_startup_mode_on(igmp);
-}
-
-static void igmp_sock_query_reschedule(struct igmp_sock *igmp)
-{
- if (igmp->mtrace_only)
- return;
-
- if (igmp->t_igmp_query_timer) {
- /* other querier present */
- zassert(igmp->t_igmp_query_timer);
- zassert(!igmp->t_other_querier_timer);
-
- pim_igmp_general_query_off(igmp);
- pim_igmp_general_query_on(igmp);
-
- zassert(igmp->t_igmp_query_timer);
- zassert(!igmp->t_other_querier_timer);
- } else {
- /* this is the querier */
-
- zassert(!igmp->t_igmp_query_timer);
- zassert(igmp->t_other_querier_timer);
-
- pim_igmp_other_querier_timer_off(igmp);
- pim_igmp_other_querier_timer_on(igmp);
-
- zassert(!igmp->t_igmp_query_timer);
- zassert(igmp->t_other_querier_timer);
- }
-}
-
-static void change_query_interval(struct pim_interface *pim_ifp,
- int query_interval)
-{
- struct listnode *sock_node;
- struct igmp_sock *igmp;
-
- pim_ifp->igmp_default_query_interval = query_interval;
-
- for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) {
- igmp_sock_query_interval_reconfig(igmp);
- igmp_sock_query_reschedule(igmp);
- }
-}
-
-static void change_query_max_response_time(struct pim_interface *pim_ifp,
- int query_max_response_time_dsec)
-{
- struct listnode *sock_node;
- struct igmp_sock *igmp;
-
- pim_ifp->igmp_query_max_response_time_dsec =
- query_max_response_time_dsec;
-
- /*
- Below we modify socket/group/source timers in order to quickly
- reflect the change. Otherwise, those timers would eventually catch
- up.
- */
-
- /* scan all sockets */
- for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) {
- struct listnode *grp_node;
- struct igmp_group *grp;
-
- /* reschedule socket general query */
- igmp_sock_query_reschedule(igmp);
-
- /* scan socket groups */
- for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list, grp_node,
- grp)) {
- struct listnode *src_node;
- struct igmp_source *src;
+ } else
+ source_str = "0.0.0.0";
- /* reset group timers for groups in EXCLUDE mode */
- if (grp->group_filtermode_isexcl) {
- igmp_group_reset_gmi(grp);
- }
+ snprintf(xpath, sizeof(xpath), FRR_IGMP_JOIN_XPATH,
+ "frr-routing:ipv4", argv[idx_group]->arg, source_str);
- /* scan group sources */
- for (ALL_LIST_ELEMENTS_RO(grp->group_source_list,
- src_node, src)) {
+ nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
- /* reset source timers for sources with running
- * timers */
- if (src->t_source_timer) {
- igmp_source_reset_gmi(igmp, grp, src);
- }
- }
- }
- }
+ return nb_cli_apply_changes(vty, NULL);
}
-#define IGMP_QUERY_INTERVAL_MIN (1)
-#define IGMP_QUERY_INTERVAL_MAX (1800)
-
DEFUN (interface_ip_igmp_query_interval,
interface_ip_igmp_query_interval_cmd,
"ip igmp query-interval (1-1800)",
@@ -7866,50 +8126,24 @@ DEFUN (interface_ip_igmp_query_interval,
IFACE_IGMP_QUERY_INTERVAL_STR
"Query interval in seconds\n")
{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct pim_interface *pim_ifp = ifp->info;
- int query_interval;
- int query_interval_dsec;
- int ret;
-
- if (!pim_ifp) {
- ret = pim_cmd_igmp_start(vty, ifp);
- if (ret != CMD_SUCCESS)
- return ret;
- pim_ifp = ifp->info;
- }
-
- query_interval = atoi(argv[3]->arg);
- query_interval_dsec = 10 * query_interval;
+ const struct lyd_node *pim_enable_dnode;
- /*
- It seems we don't need to check bounds since command.c does it
- already, but we verify them anyway for extra safety.
- */
- if (query_interval < IGMP_QUERY_INTERVAL_MIN) {
- vty_out(vty,
- "General query interval %d lower than minimum %d\n",
- query_interval, IGMP_QUERY_INTERVAL_MIN);
- return CMD_WARNING_CONFIG_FAILED;
- }
- if (query_interval > IGMP_QUERY_INTERVAL_MAX) {
- vty_out(vty,
- "General query interval %d higher than maximum %d\n",
- query_interval, IGMP_QUERY_INTERVAL_MAX);
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- if (query_interval_dsec <= pim_ifp->igmp_query_max_response_time_dsec) {
- vty_out(vty,
- "Can't set general query interval %d dsec <= query max response time %d dsec.\n",
- query_interval_dsec,
- pim_ifp->igmp_query_max_response_time_dsec);
- return CMD_WARNING_CONFIG_FAILED;
+ pim_enable_dnode = yang_dnode_get(vty->candidate_config->dnode,
+ "%s/frr-pim:pim/pim-enable",
+ VTY_CURR_XPATH);
+ if (!pim_enable_dnode) {
+ nb_cli_enqueue_change(vty, "./igmp-enable", NB_OP_MODIFY,
+ "true");
+ } else {
+ if (!yang_dnode_get_bool(pim_enable_dnode, "."))
+ nb_cli_enqueue_change(vty, "./igmp-enable",
+ NB_OP_MODIFY, "true");
}
- change_query_interval(pim_ifp, query_interval);
+ nb_cli_enqueue_change(vty, "./query-interval", NB_OP_MODIFY,
+ argv[3]->arg);
- return CMD_SUCCESS;
+ return nb_cli_apply_changes(vty, "./frr-igmp:igmp");
}
DEFUN (interface_no_ip_igmp_query_interval,
@@ -7920,27 +8154,15 @@ DEFUN (interface_no_ip_igmp_query_interval,
IFACE_IGMP_STR
IFACE_IGMP_QUERY_INTERVAL_STR)
{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct pim_interface *pim_ifp = ifp->info;
- int default_query_interval_dsec;
-
- if (!pim_ifp)
- return CMD_SUCCESS;
+ char default_query_interval[5];
- default_query_interval_dsec = IGMP_GENERAL_QUERY_INTERVAL * 10;
+ snprintf(default_query_interval, sizeof(default_query_interval), "%d",
+ IGMP_GENERAL_QUERY_INTERVAL);
- if (default_query_interval_dsec
- <= pim_ifp->igmp_query_max_response_time_dsec) {
- vty_out(vty,
- "Can't set default general query interval %d dsec <= query max response time %d dsec.\n",
- default_query_interval_dsec,
- pim_ifp->igmp_query_max_response_time_dsec);
- return CMD_WARNING_CONFIG_FAILED;
- }
+ nb_cli_enqueue_change(vty, "./query-interval", NB_OP_MODIFY,
+ default_query_interval);
- change_query_interval(pim_ifp, IGMP_GENERAL_QUERY_INTERVAL);
-
- return CMD_SUCCESS;
+ return nb_cli_apply_changes(vty, "./frr-igmp:igmp");
}
DEFUN (interface_ip_igmp_version,
@@ -7951,36 +8173,11 @@ DEFUN (interface_ip_igmp_version,
"IGMP version\n"
"IGMP version number\n")
{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct pim_interface *pim_ifp = ifp->info;
- int igmp_version, old_version = 0;
- int ret;
-
- if (!pim_ifp) {
- ret = pim_cmd_igmp_start(vty, ifp);
- if (ret != CMD_SUCCESS)
- return ret;
- pim_ifp = ifp->info;
- }
+ nb_cli_enqueue_change(vty, "./igmp-enable", NB_OP_MODIFY,
+ "true");
+ nb_cli_enqueue_change(vty, "./version", NB_OP_MODIFY, argv[3]->arg);
- igmp_version = atoi(argv[3]->arg);
- old_version = pim_ifp->igmp_version;
- pim_ifp->igmp_version = igmp_version;
-
- // Check if IGMP is Enabled otherwise, enable on interface
- if (!PIM_IF_TEST_IGMP(pim_ifp->options)) {
- PIM_IF_DO_IGMP(pim_ifp->options);
- pim_if_addr_add_all(ifp);
- pim_if_membership_refresh(ifp);
- old_version = igmp_version;
- // avoid refreshing membership again.
- }
- /* 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);
-
- return CMD_SUCCESS;
+ return nb_cli_apply_changes(vty, "./frr-igmp:igmp");
}
DEFUN (interface_no_ip_igmp_version,
@@ -7992,20 +8189,11 @@ DEFUN (interface_no_ip_igmp_version,
"IGMP version\n"
"IGMP version number\n")
{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct pim_interface *pim_ifp = ifp->info;
-
- if (!pim_ifp)
- return CMD_SUCCESS;
+ nb_cli_enqueue_change(vty, "./version", NB_OP_DESTROY, NULL);
- pim_ifp->igmp_version = IGMP_DEFAULT_VERSION;
-
- return CMD_SUCCESS;
+ return nb_cli_apply_changes(vty, "./frr-igmp:igmp");
}
-#define IGMP_QUERY_MAX_RESPONSE_TIME_MIN_DSEC (10)
-#define IGMP_QUERY_MAX_RESPONSE_TIME_MAX_DSEC (250)
-
DEFUN (interface_ip_igmp_query_max_response_time,
interface_ip_igmp_query_max_response_time_cmd,
"ip igmp query-max-response-time (10-250)",
@@ -8014,32 +8202,25 @@ DEFUN (interface_ip_igmp_query_max_response_time,
IFACE_IGMP_QUERY_MAX_RESPONSE_TIME_STR
"Query response value in deci-seconds\n")
{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct pim_interface *pim_ifp = ifp->info;
- int query_max_response_time;
- int ret;
+ const struct lyd_node *pim_enable_dnode;
- if (!pim_ifp) {
- ret = pim_cmd_igmp_start(vty, ifp);
- if (ret != CMD_SUCCESS)
- return ret;
- pim_ifp = ifp->info;
- }
+ pim_enable_dnode = yang_dnode_get(vty->candidate_config->dnode,
+ "%s/frr-pim:pim/pim-enable",
+ VTY_CURR_XPATH);
- query_max_response_time = atoi(argv[3]->arg);
-
- if (query_max_response_time
- >= pim_ifp->igmp_default_query_interval * 10) {
- vty_out(vty,
- "Can't set query max response time %d sec >= general query interval %d sec\n",
- query_max_response_time,
- pim_ifp->igmp_default_query_interval);
- return CMD_WARNING_CONFIG_FAILED;
+ if (!pim_enable_dnode) {
+ nb_cli_enqueue_change(vty, "./igmp-enable", NB_OP_MODIFY,
+ "true");
+ } else {
+ if (!yang_dnode_get_bool(pim_enable_dnode, "."))
+ nb_cli_enqueue_change(vty, "./igmp-enable",
+ NB_OP_MODIFY, "true");
}
- change_query_max_response_time(pim_ifp, query_max_response_time);
+ nb_cli_enqueue_change(vty, "./query-max-response-time", NB_OP_MODIFY,
+ argv[3]->arg);
- return CMD_SUCCESS;
+ return nb_cli_apply_changes(vty, "./frr-igmp:igmp");
}
DEFUN (interface_no_ip_igmp_query_max_response_time,
@@ -8051,21 +8232,17 @@ DEFUN (interface_no_ip_igmp_query_max_response_time,
IFACE_IGMP_QUERY_MAX_RESPONSE_TIME_STR
"Time for response in deci-seconds\n")
{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct pim_interface *pim_ifp = ifp->info;
-
- if (!pim_ifp)
- return CMD_SUCCESS;
+ char default_query_max_response_time[4];
- change_query_max_response_time(pim_ifp,
- IGMP_QUERY_MAX_RESPONSE_TIME_DSEC);
+ snprintf(default_query_max_response_time,
+ sizeof(default_query_max_response_time),
+ "%d", IGMP_QUERY_MAX_RESPONSE_TIME_DSEC);
- return CMD_SUCCESS;
+ nb_cli_enqueue_change(vty, "./query-max-response-time", NB_OP_MODIFY,
+ default_query_max_response_time);
+ return nb_cli_apply_changes(vty, "./frr-igmp:igmp");
}
-#define IGMP_QUERY_MAX_RESPONSE_TIME_MIN_DSEC (10)
-#define IGMP_QUERY_MAX_RESPONSE_TIME_MAX_DSEC (250)
-
DEFUN_HIDDEN (interface_ip_igmp_query_max_response_time_dsec,
interface_ip_igmp_query_max_response_time_dsec_cmd,
"ip igmp query-max-response-time-dsec (10-250)",
@@ -8074,34 +8251,24 @@ DEFUN_HIDDEN (interface_ip_igmp_query_max_response_time_dsec,
IFACE_IGMP_QUERY_MAX_RESPONSE_TIME_DSEC_STR
"Query response value in deciseconds\n")
{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct pim_interface *pim_ifp = ifp->info;
- int query_max_response_time_dsec;
- int default_query_interval_dsec;
- int ret;
-
- if (!pim_ifp) {
- ret = pim_cmd_igmp_start(vty, ifp);
- if (ret != CMD_SUCCESS)
- return ret;
- pim_ifp = ifp->info;
- }
+ const struct lyd_node *pim_enable_dnode;
- query_max_response_time_dsec = atoi(argv[4]->arg);
-
- default_query_interval_dsec = 10 * pim_ifp->igmp_default_query_interval;
-
- if (query_max_response_time_dsec >= default_query_interval_dsec) {
- vty_out(vty,
- "Can't set query max response time %d dsec >= general query interval %d dsec\n",
- query_max_response_time_dsec,
- default_query_interval_dsec);
- return CMD_WARNING_CONFIG_FAILED;
+ pim_enable_dnode = yang_dnode_get(vty->candidate_config->dnode,
+ "%s/frr-pim:pim/pim-enable",
+ VTY_CURR_XPATH);
+ if (!pim_enable_dnode) {
+ nb_cli_enqueue_change(vty, "./igmp-enable", NB_OP_MODIFY,
+ "true");
+ } else {
+ if (!yang_dnode_get_bool(pim_enable_dnode, "."))
+ nb_cli_enqueue_change(vty, "./igmp-enable",
+ NB_OP_MODIFY, "true");
}
- change_query_max_response_time(pim_ifp, query_max_response_time_dsec);
+ nb_cli_enqueue_change(vty, "./query-max-response-time", NB_OP_MODIFY,
+ argv[3]->arg);
- return CMD_SUCCESS;
+ return nb_cli_apply_changes(vty, "./frr-igmp:igmp");
}
DEFUN_HIDDEN (interface_no_ip_igmp_query_max_response_time_dsec,
@@ -8112,21 +8279,18 @@ DEFUN_HIDDEN (interface_no_ip_igmp_query_max_response_time_dsec,
IFACE_IGMP_STR
IFACE_IGMP_QUERY_MAX_RESPONSE_TIME_DSEC_STR)
{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct pim_interface *pim_ifp = ifp->info;
+ char default_query_max_response_time[4];
- if (!pim_ifp)
- return CMD_SUCCESS;
+ snprintf(default_query_max_response_time,
+ sizeof(default_query_max_response_time),
+ "%d", IGMP_QUERY_MAX_RESPONSE_TIME_DSEC);
- change_query_max_response_time(pim_ifp,
- IGMP_QUERY_MAX_RESPONSE_TIME_DSEC);
+ nb_cli_enqueue_change(vty, "./query-max-response-time", NB_OP_MODIFY,
+ default_query_max_response_time);
- return CMD_SUCCESS;
+ return nb_cli_apply_changes(vty, "./frr-igmp:igmp");
}
-#define IGMP_LAST_MEMBER_QUERY_COUNT_MIN (1)
-#define IGMP_LAST_MEMBER_QUERY_COUNT_MAX (7)
-
DEFUN (interface_ip_igmp_last_member_query_count,
interface_ip_igmp_last_member_query_count_cmd,
"ip igmp last-member-query-count (1-7)",
@@ -8135,23 +8299,24 @@ DEFUN (interface_ip_igmp_last_member_query_count,
IFACE_IGMP_LAST_MEMBER_QUERY_COUNT_STR
"Last member query count\n")
{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct pim_interface *pim_ifp = ifp->info;
- int last_member_query_count;
- int ret;
+ const struct lyd_node *pim_enable_dnode;
- if (!pim_ifp) {
- ret = pim_cmd_igmp_start(vty, ifp);
- if (ret != CMD_SUCCESS)
- return ret;
- pim_ifp = ifp->info;
+ pim_enable_dnode = yang_dnode_get(vty->candidate_config->dnode,
+ "%s/frr-pim:pim/pim-enable",
+ VTY_CURR_XPATH);
+ if (!pim_enable_dnode) {
+ nb_cli_enqueue_change(vty, "./igmp-enable", NB_OP_MODIFY,
+ "true");
+ } else {
+ if (!yang_dnode_get_bool(pim_enable_dnode, "."))
+ nb_cli_enqueue_change(vty, "./igmp-enable",
+ NB_OP_MODIFY, "true");
}
- last_member_query_count = atoi(argv[3]->arg);
-
- pim_ifp->igmp_last_member_query_count = last_member_query_count;
+ nb_cli_enqueue_change(vty, "./robustness-variable", NB_OP_MODIFY,
+ argv[3]->arg);
- return CMD_SUCCESS;
+ return nb_cli_apply_changes(vty, "./frr-igmp:igmp");
}
DEFUN (interface_no_ip_igmp_last_member_query_count,
@@ -8162,21 +8327,17 @@ DEFUN (interface_no_ip_igmp_last_member_query_count,
IFACE_IGMP_STR
IFACE_IGMP_LAST_MEMBER_QUERY_COUNT_STR)
{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct pim_interface *pim_ifp = ifp->info;
+ char default_robustness[2];
- if (!pim_ifp)
- return CMD_SUCCESS;
+ snprintf(default_robustness, sizeof(default_robustness), "%d",
+ IGMP_DEFAULT_ROBUSTNESS_VARIABLE);
- pim_ifp->igmp_last_member_query_count =
- IGMP_DEFAULT_ROBUSTNESS_VARIABLE;
+ nb_cli_enqueue_change(vty, "./robustness-variable", NB_OP_MODIFY,
+ default_robustness);
- return CMD_SUCCESS;
+ return nb_cli_apply_changes(vty, "./frr-igmp:igmp");
}
-#define IGMP_LAST_MEMBER_QUERY_INTERVAL_MIN (1)
-#define IGMP_LAST_MEMBER_QUERY_INTERVAL_MAX (255)
-
DEFUN (interface_ip_igmp_last_member_query_interval,
interface_ip_igmp_last_member_query_interval_cmd,
"ip igmp last-member-query-interval (1-255)",
@@ -8185,23 +8346,24 @@ DEFUN (interface_ip_igmp_last_member_query_interval,
IFACE_IGMP_LAST_MEMBER_QUERY_INTERVAL_STR
"Last member query interval in deciseconds\n")
{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct pim_interface *pim_ifp = ifp->info;
- int last_member_query_interval;
- int ret;
+ const struct lyd_node *pim_enable_dnode;
- if (!pim_ifp) {
- ret = pim_cmd_igmp_start(vty, ifp);
- if (ret != CMD_SUCCESS)
- return ret;
- pim_ifp = ifp->info;
+ pim_enable_dnode = yang_dnode_get(vty->candidate_config->dnode,
+ "%s/frr-pim:pim/pim-enable",
+ VTY_CURR_XPATH);
+ if (!pim_enable_dnode) {
+ nb_cli_enqueue_change(vty, "./igmp-enable", NB_OP_MODIFY,
+ "true");
+ } else {
+ if (!yang_dnode_get_bool(pim_enable_dnode, "."))
+ nb_cli_enqueue_change(vty, "./igmp-enable",
+ NB_OP_MODIFY, "true");
}
- last_member_query_interval = atoi(argv[3]->arg);
- pim_ifp->igmp_specific_query_max_response_time_dsec
- = last_member_query_interval;
+ nb_cli_enqueue_change(vty, "./last-member-query-interval", NB_OP_MODIFY,
+ argv[3]->arg);
- return CMD_SUCCESS;
+ return nb_cli_apply_changes(vty, "./frr-igmp:igmp");
}
DEFUN (interface_no_ip_igmp_last_member_query_interval,
@@ -8212,16 +8374,16 @@ DEFUN (interface_no_ip_igmp_last_member_query_interval,
IFACE_IGMP_STR
IFACE_IGMP_LAST_MEMBER_QUERY_INTERVAL_STR)
{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct pim_interface *pim_ifp = ifp->info;
+ char default_last_member_query_count[4];
- if (!pim_ifp)
- return CMD_SUCCESS;
+ snprintf(default_last_member_query_count,
+ sizeof(default_last_member_query_count),
+ "%d", IGMP_SPECIFIC_QUERY_MAX_RESPONSE_TIME_DSEC);
- pim_ifp->igmp_specific_query_max_response_time_dsec =
- IGMP_SPECIFIC_QUERY_MAX_RESPONSE_TIME_DSEC;
+ nb_cli_enqueue_change(vty, "./last-member-query-interval", NB_OP_MODIFY,
+ default_last_member_query_count);
- return CMD_SUCCESS;
+ return nb_cli_apply_changes(vty, "./frr-igmp:igmp");
}
DEFUN (interface_ip_pim_drprio,
@@ -8232,26 +8394,12 @@ DEFUN (interface_ip_pim_drprio,
"Set the Designated Router Election Priority\n"
"Value of the new DR Priority\n")
{
- VTY_DECLVAR_CONTEXT(interface, ifp);
int idx_number = 3;
- struct pim_interface *pim_ifp = ifp->info;
- uint32_t old_dr_prio;
-
- if (!pim_ifp) {
- vty_out(vty, "Please enable PIM on interface, first\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- old_dr_prio = pim_ifp->pim_dr_priority;
-
- pim_ifp->pim_dr_priority = strtol(argv[idx_number]->arg, NULL, 10);
- if (old_dr_prio != pim_ifp->pim_dr_priority) {
- pim_if_dr_election(ifp);
- pim_hello_restart_now(ifp);
- }
+ nb_cli_enqueue_change(vty, "./dr-priority", NB_OP_MODIFY,
+ argv[idx_number]->arg);
- return CMD_SUCCESS;
+ return nb_cli_apply_changes(vty, "./frr-pim:pim");
}
DEFUN (interface_no_ip_pim_drprio,
@@ -8263,21 +8411,15 @@ DEFUN (interface_no_ip_pim_drprio,
"Revert the Designated Router Priority to default\n"
"Old Value of the Priority\n")
{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct pim_interface *pim_ifp = ifp->info;
+ char default_priority[10];
- if (!pim_ifp) {
- vty_out(vty, "Pim not enabled on this interface\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
+ snprintf(default_priority, sizeof(default_priority), "%d",
+ PIM_DEFAULT_DR_PRIORITY);
- if (pim_ifp->pim_dr_priority != PIM_DEFAULT_DR_PRIORITY) {
- pim_ifp->pim_dr_priority = PIM_DEFAULT_DR_PRIORITY;
- pim_if_dr_election(ifp);
- pim_hello_restart_now(ifp);
- }
+ nb_cli_enqueue_change(vty, "./dr-priority", NB_OP_MODIFY,
+ default_priority);
- return CMD_SUCCESS;
+ return nb_cli_apply_changes(vty, "./frr-pim:pim");
}
DEFPY_HIDDEN (interface_ip_igmp_query_generate,
@@ -8306,30 +8448,6 @@ DEFPY_HIDDEN (interface_ip_igmp_query_generate,
return CMD_SUCCESS;
}
-static int pim_cmd_interface_add(struct vty *vty, struct interface *ifp)
-{
- struct pim_interface *pim_ifp = ifp->info;
- struct pim_instance *pim;
-
- if (!pim_ifp) {
- pim = pim_get_pim_instance(ifp->vrf_id);
- /* Limiting mcast interfaces to number of VIFs */
- if (pim->mcast_if_count == MAXVIFS) {
- vty_out(vty, "Max multicast interfaces(%d) reached.",
- MAXVIFS);
- return 0;
- }
- 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;
-}
-
DEFPY_HIDDEN (pim_test_sg_keepalive,
pim_test_sg_keepalive_cmd,
"test pim [vrf NAME$name] keepalive-reset A.B.C.D$source A.B.C.D$group",
@@ -8388,28 +8506,18 @@ DEFPY (interface_ip_pim_activeactive,
PIM_STR
"Mark interface as Active-Active for MLAG operations, Hidden because not finished yet\n")
{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct pim_interface *pim_ifp;
+ if (no)
+ nb_cli_enqueue_change(vty, "./active-active", NB_OP_MODIFY,
+ "false");
+ else {
+ nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY,
+ "true");
- if (!no && !pim_cmd_interface_add(vty, ifp)) {
- vty_out(vty,
- "Could not enable PIM SM active-active on interface %s\n",
- ifp->name);
- return CMD_WARNING_CONFIG_FAILED;
+ nb_cli_enqueue_change(vty, "./active-active", NB_OP_MODIFY,
+ "true");
}
-
- if (PIM_DEBUG_MLAG)
- zlog_debug("%sConfiguring PIM active-active on Interface: %s",
- no ? "Un-" : " ", ifp->name);
-
- pim_ifp = ifp->info;
- if (no)
- pim_if_unconfigure_mlag_dualactive(pim_ifp);
- else
- pim_if_configure_mlag_dualactive(pim_ifp);
-
- return CMD_SUCCESS;
+ return nb_cli_apply_changes(vty, "./frr-pim:pim");
}
DEFUN_HIDDEN (interface_ip_pim_ssm,
@@ -8419,36 +8527,19 @@ DEFUN_HIDDEN (interface_ip_pim_ssm,
PIM_STR
IFACE_PIM_STR)
{
- 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;
- }
-
- 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;
+ int ret;
- VTY_DECLVAR_CONTEXT(interface, ifp);
+ nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY, "true");
- 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;
- }
+ ret = nb_cli_apply_changes(vty, "./frr-pim:pim");
- pim_ifp = ifp->info;
+ if (ret != NB_OK)
+ return ret;
- pim_if_create_pimreg(pim_ifp->pim);
+ vty_out(vty,
+ "WARN: Enabled PIM SM on interface; configure PIM SSM range if needed\n");
- return CMD_SUCCESS;
+ return NB_OK;
}
DEFUN_HIDDEN (interface_ip_pim_sm,
@@ -8458,7 +8549,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,
@@ -8467,43 +8560,9 @@ DEFUN (interface_ip_pim,
IP_STR
PIM_STR)
{
- return interface_ip_pim_helper(vty);
-}
-
-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);
+ nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY, "true");
- /*
- 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,
@@ -8514,7 +8573,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,
@@ -8525,7 +8605,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,
@@ -8535,7 +8636,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 */
@@ -8548,22 +8670,13 @@ DEFUN(interface_ip_pim_boundary_oil,
"Filter OIL by group using prefix list\n"
"Prefix list to filter OIL with\n")
{
- VTY_DECLVAR_CONTEXT(interface, iif);
- struct pim_interface *pim_ifp;
- int idx = 0;
-
- argv_find(argv, argc, "WORD", &idx);
-
- PIM_GET_PIM_INTERFACE(pim_ifp, iif);
-
- if (pim_ifp->boundary_oil_plist)
- XFREE(MTYPE_PIM_INTERFACE, pim_ifp->boundary_oil_plist);
+ nb_cli_enqueue_change(vty, "./multicast-boundary-oil", NB_OP_MODIFY,
+ argv[4]->arg);
- pim_ifp->boundary_oil_plist =
- XSTRDUP(MTYPE_PIM_INTERFACE, argv[idx]->arg);
+ return nb_cli_apply_changes(vty,
+ "./frr-pim:pim/address-family[address-family='%s']",
+ "frr-routing:ipv4");
- /* Interface will be pruned from OIL on next Join */
- return CMD_SUCCESS;
}
DEFUN(interface_no_ip_pim_boundary_oil,
@@ -8576,18 +8689,12 @@ DEFUN(interface_no_ip_pim_boundary_oil,
"Filter OIL by group using prefix list\n"
"Prefix list to filter OIL with\n")
{
- VTY_DECLVAR_CONTEXT(interface, iif);
- struct pim_interface *pim_ifp;
- int idx = 0;
-
- argv_find(argv, argc, "WORD", &idx);
+ nb_cli_enqueue_change(vty, "./multicast-boundary-oil", NB_OP_DESTROY,
+ NULL);
- PIM_GET_PIM_INTERFACE(pim_ifp, iif);
-
- if (pim_ifp->boundary_oil_plist)
- XFREE(MTYPE_PIM_INTERFACE, pim_ifp->boundary_oil_plist);
-
- return CMD_SUCCESS;
+ return nb_cli_apply_changes(vty,
+ "./frr-pim:pim/address-family[address-family='%s']",
+ "frr-routing:ipv4");
}
DEFUN (interface_ip_mroute,
@@ -8599,56 +8706,21 @@ DEFUN (interface_ip_mroute,
"Group address\n"
"Source address\n")
{
- VTY_DECLVAR_CONTEXT(interface, iif);
- struct pim_interface *pim_ifp;
- struct pim_instance *pim;
int idx_interface = 2;
int idx_ipv4 = 3;
- struct interface *oif;
- const char *oifname;
- const char *grp_str;
- struct in_addr grp_addr;
- const char *src_str;
- struct in_addr src_addr;
- int result;
-
- PIM_GET_PIM_INTERFACE(pim_ifp, iif);
- pim = pim_ifp->pim;
-
- oifname = argv[idx_interface]->arg;
- oif = if_lookup_by_name(oifname, pim->vrf_id);
- if (!oif) {
- vty_out(vty, "No such interface name %s\n", oifname);
- return CMD_WARNING;
- }
+ const char *source_str;
- grp_str = argv[idx_ipv4]->arg;
- result = inet_pton(AF_INET, grp_str, &grp_addr);
- if (result <= 0) {
- vty_out(vty, "Bad group address %s: errno=%d: %s\n", grp_str,
- errno, safe_strerror(errno));
- return CMD_WARNING;
- }
+ if (argc == (idx_ipv4 + 1))
+ source_str = "0.0.0.0";
+ else
+ source_str = argv[idx_ipv4 + 1]->arg;
- if (argc == (idx_ipv4 + 1)) {
- src_addr.s_addr = INADDR_ANY;
- }
- else {
- src_str = argv[idx_ipv4 + 1]->arg;
- result = inet_pton(AF_INET, src_str, &src_addr);
- if (result <= 0) {
- vty_out(vty, "Bad source address %s: errno=%d: %s\n", src_str,
- errno, safe_strerror(errno));
- return CMD_WARNING;
- }
- }
-
- if (pim_static_add(pim, iif, oif, grp_addr, src_addr)) {
- vty_out(vty, "Failed to add static mroute\n");
- return CMD_WARNING;
- }
+ nb_cli_enqueue_change(vty, "./oif", NB_OP_MODIFY,
+ argv[idx_interface]->arg);
- return CMD_SUCCESS;
+ return nb_cli_apply_changes(vty,
+ "./frr-pim:pim/address-family[address-family='%s']/mroute[source-addr='%s'][group-addr='%s']",
+ "frr-routing:ipv4", source_str, argv[idx_ipv4]->arg);
}
DEFUN (interface_no_ip_mroute,
@@ -8661,56 +8733,19 @@ DEFUN (interface_no_ip_mroute,
"Group Address\n"
"Source Address\n")
{
- VTY_DECLVAR_CONTEXT(interface, iif);
- struct pim_interface *pim_ifp;
- struct pim_instance *pim;
- int idx_interface = 3;
int idx_ipv4 = 4;
- struct interface *oif;
- const char *oifname;
- const char *grp_str;
- struct in_addr grp_addr;
- const char *src_str;
- struct in_addr src_addr;
- int result;
-
- PIM_GET_PIM_INTERFACE(pim_ifp, iif);
- pim = pim_ifp->pim;
-
- oifname = argv[idx_interface]->arg;
- oif = if_lookup_by_name(oifname, pim->vrf_id);
- if (!oif) {
- vty_out(vty, "No such interface name %s\n", oifname);
- return CMD_WARNING;
- }
+ const char *source_str;
- grp_str = argv[idx_ipv4]->arg;
- result = inet_pton(AF_INET, grp_str, &grp_addr);
- if (result <= 0) {
- vty_out(vty, "Bad group address %s: errno=%d: %s\n", grp_str,
- errno, safe_strerror(errno));
- return CMD_WARNING;
- }
+ if (argc == (idx_ipv4 + 1))
+ source_str = "0.0.0.0";
+ else
+ source_str = argv[idx_ipv4 + 1]->arg;
- if (argc == (idx_ipv4 + 1)) {
- src_addr.s_addr = INADDR_ANY;
- }
- else {
- src_str = argv[idx_ipv4 + 1]->arg;
- result = inet_pton(AF_INET, src_str, &src_addr);
- if (result <= 0) {
- vty_out(vty, "Bad source address %s: errno=%d: %s\n", src_str,
- errno, safe_strerror(errno));
- return CMD_WARNING;
- }
- }
-
- if (pim_static_del(pim, iif, oif, grp_addr, src_addr)) {
- vty_out(vty, "Failed to remove static mroute\n");
- return CMD_WARNING;
- }
+ nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
- return CMD_SUCCESS;
+ return nb_cli_apply_changes(vty,
+ "./frr-pim:pim/address-family[address-family='%s']/mroute[source-addr='%s'][group-addr='%s']",
+ "frr-routing:ipv4", source_str, argv[idx_ipv4]->arg);
}
DEFUN (interface_ip_pim_hello,
@@ -8722,28 +8757,30 @@ DEFUN (interface_ip_pim_hello,
IFACE_PIM_HELLO_TIME_STR
IFACE_PIM_HELLO_HOLD_STR)
{
- VTY_DECLVAR_CONTEXT(interface, ifp);
int idx_time = 3;
int idx_hold = 4;
- struct pim_interface *pim_ifp = ifp->info;
-
- if (!pim_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;
- }
+ const struct lyd_node *igmp_enable_dnode;
+
+ igmp_enable_dnode = yang_dnode_get(vty->candidate_config->dnode,
+ "%s/frr-igmp:igmp/igmp-enable",
+ VTY_CURR_XPATH);
+ if (!igmp_enable_dnode) {
+ nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY,
+ "true");
+ } else {
+ if (!yang_dnode_get_bool(igmp_enable_dnode, "."))
+ nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY,
+ "true");
}
- pim_ifp = ifp->info;
- pim_ifp->pim_hello_period = strtol(argv[idx_time]->arg, NULL, 10);
+ nb_cli_enqueue_change(vty, "./hello-interval", NB_OP_MODIFY,
+ argv[idx_time]->arg);
if (argc == idx_hold + 1)
- pim_ifp->pim_default_holdtime =
- strtol(argv[idx_hold]->arg, NULL, 10);
+ nb_cli_enqueue_change(vty, "./hello-holdtime", NB_OP_MODIFY,
+ argv[idx_hold]->arg);
- return CMD_SUCCESS;
+ return nb_cli_apply_changes(vty, "./frr-pim:pim");
}
DEFUN (interface_no_ip_pim_hello,
@@ -8756,18 +8793,16 @@ DEFUN (interface_no_ip_pim_hello,
IFACE_PIM_HELLO_TIME_STR
IFACE_PIM_HELLO_HOLD_STR)
{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct pim_interface *pim_ifp = ifp->info;
+ char hello_default_timer[3];
- if (!pim_ifp) {
- vty_out(vty, "Pim not enabled on this interface\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
+ snprintf(hello_default_timer, sizeof(hello_default_timer), "%d",
+ PIM_DEFAULT_HELLO_PERIOD);
- pim_ifp->pim_hello_period = PIM_DEFAULT_HELLO_PERIOD;
- pim_ifp->pim_default_holdtime = -1;
+ nb_cli_enqueue_change(vty, "./hello-interval", NB_OP_MODIFY,
+ hello_default_timer);
+ nb_cli_enqueue_change(vty, "./hello-holdtime", NB_OP_DESTROY, NULL);
- return CMD_SUCCESS;
+ return nb_cli_apply_changes(vty, "./frr-pim:pim");
}
DEFUN (debug_igmp,
@@ -9404,40 +9439,6 @@ DEFUN_NOSH (show_debugging_pim,
return CMD_SUCCESS;
}
-static int interface_pim_use_src_cmd_worker(struct vty *vty, const char *source)
-{
- int result;
- struct in_addr source_addr;
- int ret = CMD_SUCCESS;
- VTY_DECLVAR_CONTEXT(interface, ifp);
-
- result = inet_pton(AF_INET, source, &source_addr);
- if (result <= 0) {
- vty_out(vty, "%% Bad source address %s: errno=%d: %s\n", source,
- errno, safe_strerror(errno));
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- result = pim_update_source_set(ifp, source_addr);
- switch (result) {
- case PIM_SUCCESS:
- break;
- case PIM_IFACE_NOT_FOUND:
- ret = CMD_WARNING_CONFIG_FAILED;
- vty_out(vty, "Pim not enabled on this interface\n");
- break;
- case PIM_UPDATE_SOURCE_DUP:
- ret = CMD_WARNING;
- vty_out(vty, "%% Source already set to %s\n", source);
- break;
- default:
- ret = CMD_WARNING_CONFIG_FAILED;
- vty_out(vty, "%% Source set failed\n");
- }
-
- return ret;
-}
-
DEFUN (interface_pim_use_source,
interface_pim_use_source_cmd,
"ip pim use-source A.B.C.D",
@@ -9446,7 +9447,11 @@ DEFUN (interface_pim_use_source,
"Configure primary IP address\n"
"source ip address\n")
{
- return interface_pim_use_src_cmd_worker(vty, argv[3]->arg);
+ nb_cli_enqueue_change(vty, "./use-source", NB_OP_MODIFY, argv[3]->arg);
+
+ return nb_cli_apply_changes(vty,
+ "./frr-pim:pim/address-family[address-family='%s']",
+ "frr-routing:ipv4");
}
DEFUN (interface_no_pim_use_source,
@@ -9458,7 +9463,11 @@ DEFUN (interface_no_pim_use_source,
"Delete source IP address\n"
"source ip address\n")
{
- return interface_pim_use_src_cmd_worker(vty, "0.0.0.0");
+ nb_cli_enqueue_change(vty, "./use-source", NB_OP_MODIFY, "0.0.0.0");
+
+ return nb_cli_apply_changes(vty,
+ "./frr-pim:pim/address-family[address-family='%s']",
+ "frr-routing:ipv4");
}
DEFUN (ip_pim_bfd,
@@ -9468,27 +9477,50 @@ DEFUN (ip_pim_bfd,
PIM_STR
"Enables BFD support\n")
{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct pim_interface *pim_ifp = ifp->info;
struct bfd_info *bfd_info = NULL;
-
- if (!pim_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;
- }
+ char default_rx_interval[5];
+ char default_tx_interval[5];
+ char default_detect_mult[3];
+ const struct lyd_node *igmp_enable_dnode;
+ char bfd_xpath[XPATH_MAXLEN];
+
+ igmp_enable_dnode = yang_dnode_get(vty->candidate_config->dnode,
+ "%s/frr-igmp:igmp/igmp-enable",
+ VTY_CURR_XPATH);
+ if (!igmp_enable_dnode)
+ nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY,
+ "true");
+ else {
+ if (!yang_dnode_get_bool(igmp_enable_dnode, "."))
+ nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY,
+ "true");
}
- pim_ifp = ifp->info;
- bfd_info = pim_ifp->bfd_info;
+ snprintf(default_rx_interval, sizeof(default_rx_interval), "%d",
+ BFD_DEF_MIN_RX);
+ snprintf(default_tx_interval, sizeof(default_tx_interval), "%d",
+ BFD_DEF_MIN_TX);
+ snprintf(default_detect_mult, sizeof(default_detect_mult), "%d",
+ BFD_DEF_DETECT_MULT);
- if (!bfd_info || !CHECK_FLAG(bfd_info->flags, BFD_FLAG_PARAM_CFG))
- pim_bfd_if_param_set(ifp, BFD_DEF_MIN_RX, BFD_DEF_MIN_TX,
- BFD_DEF_DETECT_MULT, 1);
+ snprintf(bfd_xpath, sizeof(bfd_xpath), "%s/frr-pim:pim/bfd",
+ VTY_CURR_XPATH);
+ bfd_info = nb_running_get_entry(NULL, bfd_xpath, false);
- return CMD_SUCCESS;
+ if (!bfd_info ||
+ !CHECK_FLAG(bfd_info->flags, BFD_FLAG_PARAM_CFG)) {
+ nb_cli_enqueue_change(vty, "./bfd/min-rx-interval",
+ NB_OP_MODIFY, default_rx_interval);
+ nb_cli_enqueue_change(vty, "./bfd/min-tx-interval",
+ NB_OP_MODIFY, default_tx_interval);
+ nb_cli_enqueue_change(vty, "./bfd/detect_mult",
+ NB_OP_MODIFY,
+ default_detect_mult);
+
+ return nb_cli_apply_changes(vty, "./frr-pim:pim");
+ }
+
+ return NB_OK;
}
DEFUN (no_ip_pim_bfd,
@@ -9499,20 +9531,9 @@ DEFUN (no_ip_pim_bfd,
PIM_STR
"Disables BFD support\n")
{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct pim_interface *pim_ifp = ifp->info;
-
- if (!pim_ifp) {
- vty_out(vty, "Pim not enabled on this interface\n");
- return CMD_WARNING;
- }
+ nb_cli_enqueue_change(vty, "./bfd", NB_OP_DESTROY, NULL);
- if (pim_ifp->bfd_info) {
- pim_bfd_reg_dereg_all_nbr(ifp, ZEBRA_BFD_DEST_DEREGISTER);
- bfd_info_free(&(pim_ifp->bfd_info));
- }
-
- return CMD_SUCCESS;
+ return nb_cli_apply_changes(vty, "./frr-pim:pim");
}
DEFUN (ip_pim_bsm,
@@ -9522,22 +9543,23 @@ DEFUN (ip_pim_bsm,
PIM_STR
"Enables BSM support on the interface\n")
{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct pim_interface *pim_ifp = ifp->info;
+ const struct lyd_node *igmp_enable_dnode;
- if (!pim_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;
- }
+ igmp_enable_dnode = yang_dnode_get(vty->candidate_config->dnode,
+ "%s/frr-igmp:igmp/igmp-enable",
+ VTY_CURR_XPATH);
+ if (!igmp_enable_dnode)
+ nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY,
+ "true");
+ else {
+ if (!yang_dnode_get_bool(igmp_enable_dnode, "."))
+ nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY,
+ "true");
}
- pim_ifp = ifp->info;
- pim_ifp->bsm_enable = true;
+ nb_cli_enqueue_change(vty, "./bsm", NB_OP_MODIFY, "true");
- return CMD_SUCCESS;
+ return nb_cli_apply_changes(vty, "./frr-pim:pim");
}
DEFUN (no_ip_pim_bsm,
@@ -9548,17 +9570,9 @@ DEFUN (no_ip_pim_bsm,
PIM_STR
"Disables BSM support\n")
{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct pim_interface *pim_ifp = ifp->info;
+ nb_cli_enqueue_change(vty, "./bsm", NB_OP_MODIFY, "false");
- if (!pim_ifp) {
- vty_out(vty, "Pim not enabled on this interface\n");
- return CMD_WARNING;
- }
-
- pim_ifp->bsm_enable = false;
-
- return CMD_SUCCESS;
+ return nb_cli_apply_changes(vty, "./frr-pim:pim");
}
DEFUN (ip_pim_ucast_bsm,
@@ -9568,22 +9582,23 @@ DEFUN (ip_pim_ucast_bsm,
PIM_STR
"Accept/Send unicast BSM on the interface\n")
{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct pim_interface *pim_ifp = ifp->info;
+ const struct lyd_node *igmp_enable_dnode;
- if (!pim_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;
- }
+ igmp_enable_dnode = yang_dnode_get(vty->candidate_config->dnode,
+ "%s/frr-igmp:igmp/igmp-enable",
+ VTY_CURR_XPATH);
+ if (!igmp_enable_dnode)
+ nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY,
+ "true");
+ else {
+ if (!yang_dnode_get_bool(igmp_enable_dnode, "."))
+ nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY,
+ "true");
}
- pim_ifp = ifp->info;
- pim_ifp->ucast_bsm_accept = true;
+ nb_cli_enqueue_change(vty, "./unicast-bsm", NB_OP_MODIFY, "true");
- return CMD_SUCCESS;
+ return nb_cli_apply_changes(vty, "./frr-pim:pim");
}
DEFUN (no_ip_pim_ucast_bsm,
@@ -9594,17 +9609,9 @@ DEFUN (no_ip_pim_ucast_bsm,
PIM_STR
"Block send/receive unicast BSM on this interface\n")
{
- VTY_DECLVAR_CONTEXT(interface, ifp);
- struct pim_interface *pim_ifp = ifp->info;
-
- if (!pim_ifp) {
- vty_out(vty, "Pim not enabled on this interface\n");
- return CMD_WARNING;
- }
-
- pim_ifp->ucast_bsm_accept = false;
+ nb_cli_enqueue_change(vty, "./unicast-bsm", NB_OP_MODIFY, "false");
- return CMD_SUCCESS;
+ return nb_cli_apply_changes(vty, "./frr-pim:pim");
}
#if HAVE_BFDD > 0
@@ -9631,7 +9638,6 @@ DEFUN(
"Desired min transmit interval\n")
#endif /* HAVE_BFDD */
{
- VTY_DECLVAR_CONTEXT(interface, ifp);
int idx_number = 3;
int idx_number_2 = 4;
int idx_number_3 = 5;
@@ -9639,26 +9645,35 @@ DEFUN(
uint32_t tx_val;
uint8_t dm_val;
int ret;
- struct pim_interface *pim_ifp = ifp->info;
+ const struct lyd_node *igmp_enable_dnode;
- if (!pim_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;
- }
- }
-
- if ((ret = bfd_validate_param(
- vty, argv[idx_number]->arg, argv[idx_number_2]->arg,
- argv[idx_number_3]->arg, &dm_val, &rx_val, &tx_val))
- != CMD_SUCCESS)
+ if ((ret = bfd_validate_param(vty, argv[idx_number]->arg,
+ argv[idx_number_2]->arg,
+ argv[idx_number_3]->arg, &dm_val, &rx_val,
+ &tx_val))
+ != CMD_SUCCESS)
return ret;
- pim_bfd_if_param_set(ifp, rx_val, tx_val, dm_val, 0);
+ igmp_enable_dnode = yang_dnode_get(vty->candidate_config->dnode,
+ "%s/frr-igmp:igmp/igmp-enable",
+ VTY_CURR_XPATH);
+ if (!igmp_enable_dnode)
+ nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY,
+ "true");
+ else {
+ if (!yang_dnode_get_bool(igmp_enable_dnode, "."))
+ nb_cli_enqueue_change(vty, "./pim-enable", NB_OP_MODIFY,
+ "true");
+ }
- return CMD_SUCCESS;
+ nb_cli_enqueue_change(vty, "./bfd/min-rx-interval", NB_OP_MODIFY,
+ argv[idx_number_2]->arg);
+ nb_cli_enqueue_change(vty, "./bfd/min-tx-interval", NB_OP_MODIFY,
+ argv[idx_number_3]->arg);
+ nb_cli_enqueue_change(vty, "./bfd/detect_mult", NB_OP_MODIFY,
+ argv[idx_number]->arg);
+
+ return nb_cli_apply_changes(vty, "./frr-pim:pim");
}
#if HAVE_BFDD == 0
@@ -9670,53 +9685,6 @@ ALIAS(no_ip_pim_bfd, no_ip_pim_bfd_param_cmd,
"Desired min transmit interval\n")
#endif /* !HAVE_BFDD */
-static int ip_msdp_peer_cmd_worker(struct pim_instance *pim, struct vty *vty,
- const char *peer, const char *local)
-{
- enum pim_msdp_err result;
- struct in_addr peer_addr;
- struct in_addr local_addr;
- int ret = CMD_SUCCESS;
-
- result = inet_pton(AF_INET, peer, &peer_addr);
- if (result <= 0) {
- vty_out(vty, "%% Bad peer address %s: errno=%d: %s\n", peer,
- errno, safe_strerror(errno));
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- result = inet_pton(AF_INET, local, &local_addr);
- if (result <= 0) {
- vty_out(vty, "%% Bad source address %s: errno=%d: %s\n", local,
- errno, safe_strerror(errno));
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- result = pim_msdp_peer_add(pim, peer_addr, local_addr, "default",
- NULL /* mp_p */);
- switch (result) {
- case PIM_MSDP_ERR_NONE:
- break;
- case PIM_MSDP_ERR_OOM:
- ret = CMD_WARNING_CONFIG_FAILED;
- vty_out(vty, "%% Out of memory\n");
- break;
- case PIM_MSDP_ERR_PEER_EXISTS:
- ret = CMD_WARNING;
- vty_out(vty, "%% Peer exists\n");
- break;
- case PIM_MSDP_ERR_MAX_MESH_GROUPS:
- ret = CMD_WARNING_CONFIG_FAILED;
- vty_out(vty, "%% Only one mesh-group allowed currently\n");
- break;
- default:
- ret = CMD_WARNING_CONFIG_FAILED;
- vty_out(vty, "%% peer add failed\n");
- }
-
- return ret;
-}
-
DEFUN (ip_msdp_peer,
ip_msdp_peer_cmd,
"ip msdp peer A.B.C.D source A.B.C.D",
@@ -9727,35 +9695,37 @@ DEFUN (ip_msdp_peer,
"Source address for TCP connection\n"
"local ip address\n")
{
- PIM_DECLVAR_CONTEXT(vrf, pim);
- return ip_msdp_peer_cmd_worker(pim, vty, argv[3]->arg, argv[5]->arg);
-}
+ const struct lyd_node *vrf_dnode;
+ const char *vrfname;
+ char temp_xpath[XPATH_MAXLEN];
+ char msdp_peer_source_xpath[XPATH_MAXLEN];
-static int ip_no_msdp_peer_cmd_worker(struct pim_instance *pim, struct vty *vty,
- const char *peer)
-{
- enum pim_msdp_err result;
- struct in_addr peer_addr;
+ 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 = inet_pton(AF_INET, peer, &peer_addr);
- if (result <= 0) {
- vty_out(vty, "%% Bad peer address %s: errno=%d: %s\n", peer,
- errno, safe_strerror(errno));
- return CMD_WARNING_CONFIG_FAILED;
- }
+ snprintf(msdp_peer_source_xpath, sizeof(msdp_peer_source_xpath),
+ FRR_PIM_AF_XPATH,
+ "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4");
+ snprintf(temp_xpath, sizeof(temp_xpath),
+ "/msdp-peer[peer-ip='%s']/source-ip",
+ argv[3]->arg);
+ strlcat(msdp_peer_source_xpath, temp_xpath,
+ sizeof(msdp_peer_source_xpath));
- result = pim_msdp_peer_del(pim, peer_addr);
- switch (result) {
- case PIM_MSDP_ERR_NONE:
- break;
- case PIM_MSDP_ERR_NO_PEER:
- vty_out(vty, "%% Peer does not exist\n");
- break;
- default:
- vty_out(vty, "%% peer del failed\n");
- }
+ nb_cli_enqueue_change(vty, msdp_peer_source_xpath, NB_OP_MODIFY,
+ argv[5]->arg);
- return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS;
+ return nb_cli_apply_changes(vty, NULL);
}
DEFUN (no_ip_msdp_peer,
@@ -9767,47 +9737,36 @@ DEFUN (no_ip_msdp_peer,
"Delete MSDP peer\n"
"peer ip address\n")
{
- PIM_DECLVAR_CONTEXT(vrf, pim);
- return ip_no_msdp_peer_cmd_worker(pim, vty, argv[4]->arg);
-}
+ const struct lyd_node *vrf_dnode;
+ const char *vrfname;
+ char msdp_peer_xpath[XPATH_MAXLEN];
+ char temp_xpath[XPATH_MAXLEN];
-static int ip_msdp_mesh_group_member_cmd_worker(struct pim_instance *pim,
- struct vty *vty, const char *mg,
- const char *mbr)
-{
- enum pim_msdp_err result;
- struct in_addr mbr_ip;
- int ret = CMD_SUCCESS;
+ 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 = inet_pton(AF_INET, mbr, &mbr_ip);
- if (result <= 0) {
- vty_out(vty, "%% Bad member address %s: errno=%d: %s\n", mbr,
- errno, safe_strerror(errno));
- return CMD_WARNING_CONFIG_FAILED;
- }
+ snprintf(msdp_peer_xpath, sizeof(msdp_peer_xpath),
+ FRR_PIM_AF_XPATH,
+ "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4");
+ snprintf(temp_xpath, sizeof(temp_xpath),
+ "/msdp-peer[peer-ip='%s']",
+ argv[4]->arg);
- result = pim_msdp_mg_mbr_add(pim, mg, mbr_ip);
- switch (result) {
- case PIM_MSDP_ERR_NONE:
- break;
- case PIM_MSDP_ERR_OOM:
- ret = CMD_WARNING_CONFIG_FAILED;
- vty_out(vty, "%% Out of memory\n");
- break;
- case PIM_MSDP_ERR_MG_MBR_EXISTS:
- ret = CMD_WARNING;
- vty_out(vty, "%% mesh-group member exists\n");
- break;
- case PIM_MSDP_ERR_MAX_MESH_GROUPS:
- ret = CMD_WARNING_CONFIG_FAILED;
- vty_out(vty, "%% Only one mesh-group allowed currently\n");
- break;
- default:
- ret = CMD_WARNING_CONFIG_FAILED;
- vty_out(vty, "%% member add failed\n");
- }
+ strlcat(msdp_peer_xpath, temp_xpath, sizeof(msdp_peer_xpath));
- return ret;
+ nb_cli_enqueue_change(vty, msdp_peer_xpath, NB_OP_DESTROY, NULL);
+
+ return nb_cli_apply_changes(vty, NULL);
}
DEFUN (ip_msdp_mesh_group_member,
@@ -9820,42 +9779,44 @@ DEFUN (ip_msdp_mesh_group_member,
"mesh group member\n"
"peer ip address\n")
{
- PIM_DECLVAR_CONTEXT(vrf, pim);
- return ip_msdp_mesh_group_member_cmd_worker(pim, vty, argv[3]->arg,
- argv[5]->arg);
-}
+ const struct lyd_node *vrf_dnode;
+ const char *vrfname;
+ char msdp_mesh_group_name_xpath[XPATH_MAXLEN];
+ char msdp_mesh_group_member_xpath[XPATH_MAXLEN];
-static int ip_no_msdp_mesh_group_member_cmd_worker(struct pim_instance *pim,
- struct vty *vty,
- const char *mg,
- const char *mbr)
-{
- enum pim_msdp_err result;
- struct in_addr mbr_ip;
+ 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 = inet_pton(AF_INET, mbr, &mbr_ip);
- if (result <= 0) {
- vty_out(vty, "%% Bad member address %s: errno=%d: %s\n", mbr,
- errno, safe_strerror(errno));
- return CMD_WARNING_CONFIG_FAILED;
- }
+ snprintf(msdp_mesh_group_name_xpath, sizeof(msdp_mesh_group_name_xpath),
+ FRR_PIM_AF_XPATH,
+ "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4");
+ strlcat(msdp_mesh_group_name_xpath, "/msdp-mesh-group/mesh-group-name",
+ sizeof(msdp_mesh_group_name_xpath));
+ snprintf(msdp_mesh_group_member_xpath,
+ sizeof(msdp_mesh_group_member_xpath),
+ FRR_PIM_AF_XPATH,
+ "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4");
+ strlcat(msdp_mesh_group_member_xpath, "/msdp-mesh-group/member-ip",
+ sizeof(msdp_mesh_group_member_xpath));
- result = pim_msdp_mg_mbr_del(pim, mg, mbr_ip);
- switch (result) {
- case PIM_MSDP_ERR_NONE:
- break;
- case PIM_MSDP_ERR_NO_MG:
- vty_out(vty, "%% mesh-group does not exist\n");
- break;
- case PIM_MSDP_ERR_NO_MG_MBR:
- vty_out(vty, "%% mesh-group member does not exist\n");
- break;
- default:
- vty_out(vty, "%% mesh-group member del failed\n");
- }
+ nb_cli_enqueue_change(vty, msdp_mesh_group_name_xpath, NB_OP_MODIFY,
+ argv[3]->arg);
+ nb_cli_enqueue_change(vty, msdp_mesh_group_member_xpath, NB_OP_CREATE,
+ argv[5]->arg);
- return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS;
+ return nb_cli_apply_changes(vty, NULL);
}
+
DEFUN (no_ip_msdp_mesh_group_member,
no_ip_msdp_mesh_group_member_cmd,
"no ip msdp mesh-group WORD member A.B.C.D",
@@ -9867,42 +9828,89 @@ DEFUN (no_ip_msdp_mesh_group_member,
"mesh group member\n"
"peer ip address\n")
{
- PIM_DECLVAR_CONTEXT(vrf, pim);
- return ip_no_msdp_mesh_group_member_cmd_worker(pim, vty, argv[4]->arg,
- argv[6]->arg);
-}
-
-static int ip_msdp_mesh_group_source_cmd_worker(struct pim_instance *pim,
- struct vty *vty, const char *mg,
- const char *src)
-{
- enum pim_msdp_err result;
- struct in_addr src_ip;
-
- result = inet_pton(AF_INET, src, &src_ip);
- if (result <= 0) {
- vty_out(vty, "%% Bad source address %s: errno=%d: %s\n", src,
- errno, safe_strerror(errno));
- return CMD_WARNING_CONFIG_FAILED;
+ const struct lyd_node *vrf_dnode;
+ const char *vrfname;
+ char temp_xpath[XPATH_MAXLEN];
+ char mesh_group_xpath[XPATH_MAXLEN];
+ char group_member_xpath[XPATH_MAXLEN];
+ char source_xpath[XPATH_MAXLEN];
+ char mesh_group_name_xpath[XPATH_MAXLEN];
+ const char *mesh_group_name;
+ const struct lyd_node *member_dnode;
+
+ 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(mesh_group_xpath, sizeof(mesh_group_xpath),
+ FRR_PIM_AF_XPATH,
+ "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4");
+ strlcat(mesh_group_xpath, "/msdp-mesh-group", sizeof(mesh_group_xpath));
+
+ snprintf(group_member_xpath, sizeof(group_member_xpath),
+ FRR_PIM_AF_XPATH,
+ "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4");
+ snprintf(temp_xpath, sizeof(temp_xpath),
+ "/msdp-mesh-group/member-ip[.='%s']", argv[6]->arg);
+ strlcat(group_member_xpath, temp_xpath, sizeof(group_member_xpath));
+
+ snprintf(source_xpath, sizeof(source_xpath),
+ FRR_PIM_AF_XPATH,
+ "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4");
+ snprintf(temp_xpath, sizeof(temp_xpath),
+ "/msdp-mesh-group/source-ip");
+ strlcat(source_xpath, temp_xpath, sizeof(source_xpath));
+
+ snprintf(mesh_group_name_xpath, sizeof(mesh_group_name_xpath),
+ FRR_PIM_AF_XPATH,
+ "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4");
+ strlcat(mesh_group_name_xpath, "/msdp-mesh-group/mesh-group-name",
+ sizeof(mesh_group_name_xpath));
+
+ if (yang_dnode_exists(running_config->dnode, mesh_group_name_xpath)
+ == true) {
+ mesh_group_name = yang_dnode_get_string(running_config->dnode,
+ mesh_group_name_xpath);
+ if (strcmp(mesh_group_name, argv[4]->arg)) {
+ vty_out(vty, "%% mesh-group does not exist\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
}
- result = pim_msdp_mg_src_add(pim, mg, src_ip);
- switch (result) {
- case PIM_MSDP_ERR_NONE:
- break;
- case PIM_MSDP_ERR_OOM:
- vty_out(vty, "%% Out of memory\n");
- break;
- case PIM_MSDP_ERR_MAX_MESH_GROUPS:
- vty_out(vty, "%% Only one mesh-group allowed currently\n");
- break;
- default:
- vty_out(vty, "%% source add failed\n");
+ if (yang_dnode_exists(vty->candidate_config->dnode,
+ group_member_xpath)) {
+ if (!yang_dnode_exists(vty->candidate_config->dnode,
+ source_xpath)) {
+ member_dnode = yang_dnode_get(
+ vty->candidate_config->dnode,
+ group_member_xpath);
+ if (yang_is_last_list_dnode(member_dnode)) {
+ nb_cli_enqueue_change(vty, mesh_group_xpath,
+ NB_OP_DESTROY, NULL);
+ return nb_cli_apply_changes(vty, NULL);
+ }
+ nb_cli_enqueue_change(vty, group_member_xpath,
+ NB_OP_DESTROY, NULL);
+ return nb_cli_apply_changes(vty, NULL);
+ }
+ nb_cli_enqueue_change(vty, group_member_xpath,
+ NB_OP_DESTROY, NULL);
+ return nb_cli_apply_changes(vty, NULL);
}
- return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS;
-}
+ vty_out(vty, "%% mesh-group member does not exist\n");
+ return CMD_SUCCESS;
+}
DEFUN (ip_msdp_mesh_group_source,
ip_msdp_mesh_group_source_cmd,
@@ -9914,48 +9922,42 @@ DEFUN (ip_msdp_mesh_group_source,
"mesh group local address\n"
"source ip address for the TCP connection\n")
{
- PIM_DECLVAR_CONTEXT(vrf, pim);
- return ip_msdp_mesh_group_source_cmd_worker(pim, vty, argv[3]->arg,
- argv[5]->arg);
-}
-
-static int ip_no_msdp_mesh_group_source_cmd_worker(struct pim_instance *pim,
- struct vty *vty,
- const char *mg)
-{
- enum pim_msdp_err result;
+ const struct lyd_node *vrf_dnode;
+ const char *vrfname;
+ char msdp_mesh_source_ip_xpath[XPATH_MAXLEN];
+ char msdp_mesh_group_name_xpath[XPATH_MAXLEN];
- result = pim_msdp_mg_src_del(pim, mg);
- switch (result) {
- case PIM_MSDP_ERR_NONE:
- break;
- case PIM_MSDP_ERR_NO_MG:
- vty_out(vty, "%% mesh-group does not exist\n");
- break;
- default:
- vty_out(vty, "%% mesh-group source del failed\n");
- }
+ 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;
- return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS;
-}
+ snprintf(msdp_mesh_group_name_xpath, sizeof(msdp_mesh_group_name_xpath),
+ FRR_PIM_AF_XPATH,
+ "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4");
+ strlcat(msdp_mesh_group_name_xpath, "/msdp-mesh-group/mesh-group-name",
+ sizeof(msdp_mesh_group_name_xpath));
-static int ip_no_msdp_mesh_group_cmd_worker(struct pim_instance *pim,
- struct vty *vty, const char *mg)
-{
- enum pim_msdp_err result;
+ snprintf(msdp_mesh_source_ip_xpath, sizeof(msdp_mesh_source_ip_xpath),
+ FRR_PIM_AF_XPATH,
+ "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4");
+ strlcat(msdp_mesh_source_ip_xpath, "/msdp-mesh-group/source-ip",
+ sizeof(msdp_mesh_source_ip_xpath));
- result = pim_msdp_mg_del(pim, mg);
- switch (result) {
- case PIM_MSDP_ERR_NONE:
- break;
- case PIM_MSDP_ERR_NO_MG:
- vty_out(vty, "%% mesh-group does not exist\n");
- break;
- default:
- vty_out(vty, "%% mesh-group source del failed\n");
- }
+ nb_cli_enqueue_change(vty, msdp_mesh_group_name_xpath, NB_OP_MODIFY,
+ argv[3]->arg);
+ nb_cli_enqueue_change(vty, msdp_mesh_source_ip_xpath, NB_OP_MODIFY,
+ argv[5]->arg);
- return result ? CMD_WARNING_CONFIG_FAILED : CMD_SUCCESS;
+ return nb_cli_apply_changes(vty, NULL);
}
DEFUN (no_ip_msdp_mesh_group_source,
@@ -9969,9 +9971,69 @@ DEFUN (no_ip_msdp_mesh_group_source,
"mesh group source\n"
"mesh group local address\n")
{
- PIM_DECLVAR_CONTEXT(vrf, pim);
+ const struct lyd_node *vrf_dnode;
+ const char *vrfname;
+ char msdp_mesh_xpath[XPATH_MAXLEN];
+ char source_xpath[XPATH_MAXLEN];
+ char group_member_xpath[XPATH_MAXLEN];
+ char mesh_group_name_xpath[XPATH_MAXLEN];
+ const char *mesh_group_name;
+
+ 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(msdp_mesh_xpath, sizeof(msdp_mesh_xpath),
+ FRR_PIM_AF_XPATH,
+ "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4");
+ strlcat(msdp_mesh_xpath, "/msdp-mesh-group", sizeof(msdp_mesh_xpath));
+
+ snprintf(source_xpath, sizeof(source_xpath),
+ FRR_PIM_AF_XPATH,
+ "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4");
+ strlcat(source_xpath, "/msdp-mesh-group/source-ip",
+ sizeof(source_xpath));
+
+ snprintf(group_member_xpath,
+ sizeof(group_member_xpath),
+ FRR_PIM_AF_XPATH,
+ "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4");
+ strlcat(group_member_xpath, "/msdp-mesh-group/member-ip",
+ sizeof(group_member_xpath));
+
+ snprintf(mesh_group_name_xpath, sizeof(mesh_group_name_xpath),
+ FRR_PIM_AF_XPATH,
+ "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4");
+ strlcat(mesh_group_name_xpath, "/msdp-mesh-group/mesh-group-name",
+ sizeof(mesh_group_name_xpath));
+
+ if (yang_dnode_exists(running_config->dnode, mesh_group_name_xpath)
+ == true) {
+ mesh_group_name = yang_dnode_get_string(running_config->dnode,
+ mesh_group_name_xpath);
+ if (strcmp(mesh_group_name, argv[4]->arg)) {
+ vty_out(vty, "%% mesh-group does not exist\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ }
- return ip_no_msdp_mesh_group_source_cmd_worker(pim, vty, argv[4]->arg);
+ if (!yang_dnode_exists(vty->candidate_config->dnode,
+ group_member_xpath)) {
+ nb_cli_enqueue_change(vty, msdp_mesh_xpath, NB_OP_DESTROY,
+ NULL);
+ return nb_cli_apply_changes(vty, NULL);
+ }
+ nb_cli_enqueue_change(vty, source_xpath, NB_OP_DESTROY, NULL);
+ return nb_cli_apply_changes(vty, NULL);
}
DEFUN (no_ip_msdp_mesh_group,
@@ -9983,12 +10045,50 @@ DEFUN (no_ip_msdp_mesh_group,
"Delete MSDP mesh-group\n"
"mesh group name")
{
- PIM_DECLVAR_CONTEXT(vrf, pim);
+ const struct lyd_node *vrf_dnode;
+ const char *vrfname;
+ const char *mesh_group_name;
+ char xpath[XPATH_MAXLEN];
+ char msdp_mesh_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;
+
+ if (argc == 5) {
+ snprintf(xpath, sizeof(xpath), FRR_PIM_AF_XPATH, "frr-pim:pimd",
+ "pim", vrfname, "frr-routing:ipv4");
+ strlcat(xpath, "/msdp-mesh-group/mesh-group-name",
+ sizeof(xpath));
+
+ if (yang_dnode_exists(running_config->dnode, xpath) == true) {
+ mesh_group_name =
+ yang_dnode_get_string(running_config->dnode,
+ xpath);
+
+ if (strcmp(mesh_group_name, argv[4]->arg)) {
+ vty_out(vty, "%% mesh-group does not exist\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ }
+ }
- if (argc == 5)
- return ip_no_msdp_mesh_group_cmd_worker(pim, vty, argv[4]->arg);
- else
- return ip_no_msdp_mesh_group_cmd_worker(pim, vty, NULL);
+ snprintf(msdp_mesh_xpath, sizeof(msdp_mesh_xpath),
+ FRR_PIM_AF_XPATH,
+ "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4");
+ strlcat(msdp_mesh_xpath, "/msdp-mesh-group", sizeof(msdp_mesh_xpath));
+
+ nb_cli_enqueue_change(vty, msdp_mesh_xpath, NB_OP_DESTROY, NULL);
+ return nb_cli_apply_changes(vty, NULL);
}
static void print_empty_json_obj(struct vty *vty)
@@ -11008,14 +11108,16 @@ DEFUN_HIDDEN (no_ip_pim_mlag,
PIM_STR
"MLAG\n")
{
- struct in_addr addr;
+ char mlag_xpath[XPATH_MAXLEN];
- addr.s_addr = 0;
- pim_vxlan_mlag_update(true/*mlag_enable*/,
- false/*peer_state*/, MLAG_ROLE_NONE,
- NULL/*peerlink*/, &addr);
+ snprintf(mlag_xpath, sizeof(mlag_xpath), FRR_PIM_AF_XPATH,
+ "frr-pim:pimd", "pim", "default", "frr-routing:ipv4");
+ strlcat(mlag_xpath, "/mlag", sizeof(mlag_xpath));
- return CMD_SUCCESS;
+ nb_cli_enqueue_change(vty, mlag_xpath, NB_OP_DESTROY, NULL);
+
+
+ return nb_cli_apply_changes(vty, NULL);
}
DEFUN_HIDDEN (ip_pim_mlag,
@@ -11034,53 +11136,73 @@ DEFUN_HIDDEN (ip_pim_mlag,
"configure PIP\n"
"unique ip address\n")
{
- struct interface *ifp;
- const char *peerlink;
- uint32_t role;
int idx;
- bool peer_state;
- int result;
- struct in_addr reg_addr;
+ char mlag_peerlink_rif_xpath[XPATH_MAXLEN];
+ char mlag_my_role_xpath[XPATH_MAXLEN];
+ char mlag_peer_state_xpath[XPATH_MAXLEN];
+ char mlag_reg_address_xpath[XPATH_MAXLEN];
+
+ snprintf(mlag_peerlink_rif_xpath, sizeof(mlag_peerlink_rif_xpath),
+ FRR_PIM_AF_XPATH,
+ "frr-pim:pimd", "pim", "default", "frr-routing:ipv4");
+ strlcat(mlag_peerlink_rif_xpath, "/mlag/peerlink-rif",
+ sizeof(mlag_peerlink_rif_xpath));
idx = 3;
- peerlink = argv[idx]->arg;
- ifp = if_lookup_by_name(peerlink, VRF_DEFAULT);
- if (!ifp) {
- vty_out(vty, "No such interface name %s\n", peerlink);
- return CMD_WARNING;
- }
+ nb_cli_enqueue_change(vty, mlag_peerlink_rif_xpath, NB_OP_MODIFY,
+ argv[idx]->arg);
+
+ snprintf(mlag_my_role_xpath, sizeof(mlag_my_role_xpath),
+ FRR_PIM_AF_XPATH,
+ "frr-pim:pimd", "pim", "default", "frr-routing:ipv4");
+ strlcat(mlag_my_role_xpath, "/mlag/my-role",
+ sizeof(mlag_my_role_xpath));
idx += 2;
if (!strcmp(argv[idx]->arg, "primary")) {
- role = MLAG_ROLE_PRIMARY;
+ nb_cli_enqueue_change(vty, mlag_my_role_xpath, NB_OP_MODIFY,
+ "MLAG_ROLE_PRIMARY");
+
} else if (!strcmp(argv[idx]->arg, "secondary")) {
- role = MLAG_ROLE_SECONDARY;
+ nb_cli_enqueue_change(vty, mlag_my_role_xpath, NB_OP_MODIFY,
+ "MLAG_ROLE_SECONDARY");
+
} else {
vty_out(vty, "unknown MLAG role %s\n", argv[idx]->arg);
return CMD_WARNING;
}
+ snprintf(mlag_peer_state_xpath, sizeof(mlag_peer_state_xpath),
+ FRR_PIM_AF_XPATH,
+ "frr-pim:pimd", "pim", "default", "frr-routing:ipv4");
+ strlcat(mlag_peer_state_xpath, "/mlag/peer-state",
+ sizeof(mlag_peer_state_xpath));
+
idx += 2;
if (!strcmp(argv[idx]->arg, "up")) {
- peer_state = true;
+ nb_cli_enqueue_change(vty, mlag_peer_state_xpath, NB_OP_MODIFY,
+ "true");
+
} else if (strcmp(argv[idx]->arg, "down")) {
- peer_state = false;
+ nb_cli_enqueue_change(vty, mlag_peer_state_xpath, NB_OP_MODIFY,
+ "false");
+
} else {
vty_out(vty, "unknown MLAG state %s\n", argv[idx]->arg);
return CMD_WARNING;
}
+ snprintf(mlag_reg_address_xpath, sizeof(mlag_reg_address_xpath),
+ FRR_PIM_AF_XPATH,
+ "frr-pim:pimd", "pim", "default", "frr-routing:ipv4");
+ strlcat(mlag_reg_address_xpath, "/mlag/reg-address",
+ sizeof(mlag_reg_address_xpath));
+
idx += 2;
- result = inet_pton(AF_INET, argv[idx]->arg, &reg_addr);
- if (result <= 0) {
- vty_out(vty, "%% Bad reg address %s: errno=%d: %s\n",
- argv[idx]->arg,
- errno, safe_strerror(errno));
- return CMD_WARNING_CONFIG_FAILED;
- }
- pim_vxlan_mlag_update(true, peer_state, role, ifp, &reg_addr);
+ nb_cli_enqueue_change(vty, mlag_reg_address_xpath, NB_OP_MODIFY,
+ argv[idx]->arg);
- return CMD_SUCCESS;
+ return nb_cli_apply_changes(vty, NULL);
}
void pim_cmd_init(void)
diff --git a/pimd/pim_main.c b/pimd/pim_main.c
index 132d913f6..b7ca90ad9 100644
--- a/pimd/pim_main.c
+++ b/pimd/pim_main.c
@@ -38,6 +38,7 @@
#include "vrf.h"
#include "libfrr.h"
#include "routemap.h"
+#include "routing_nb.h"
#include "pimd.h"
#include "pim_instance.h"
@@ -49,6 +50,7 @@
#include "pim_bfd.h"
#include "pim_mlag.h"
#include "pim_errors.h"
+#include "pim_nb.h"
extern struct host host;
@@ -77,6 +79,10 @@ static const struct frr_yang_module_info *const pimd_yang_modules[] = {
&frr_interface_info,
&frr_route_map_info,
&frr_vrf_info,
+ &frr_routing_info,
+ &frr_pim_info,
+ &frr_pim_rp_info,
+ &frr_igmp_info,
};
FRR_DAEMON_INFO(pimd, PIM, .vty_port = PIMD_VTY_PORT,
@@ -137,6 +143,9 @@ int main(int argc, char **argv, char **envp)
pim_bfd_init();
pim_mlag_init();
+ hook_register(routing_conf_event,
+ routing_control_plane_protocols_name_validate);
+
frr_config_fork();
#ifdef PIM_DEBUG_BYDEFAULT
diff --git a/pimd/pim_nb.c b/pimd/pim_nb.c
new file mode 100644
index 000000000..8ca0e0780
--- /dev/null
+++ b/pimd/pim_nb.c
@@ -0,0 +1,417 @@
+/*
+ * Copyright (C) 2020 VmWare
+ * Sarita Patra
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <zebra.h>
+
+#include "northbound.h"
+#include "libfrr.h"
+#include "vrf.h"
+#include "pimd/pim_nb.h"
+
+/* clang-format off */
+const struct frr_yang_module_info frr_pim_info = {
+ .name = "frr-pim",
+ .nodes = {
+ {
+ .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/ecmp",
+ .cbs = {
+ .modify = routing_control_plane_protocols_control_plane_protocol_pim_ecmp_modify,
+ }
+ },
+ {
+ .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/ecmp-rebalance",
+ .cbs = {
+ .modify = routing_control_plane_protocols_control_plane_protocol_pim_ecmp_rebalance_modify,
+ }
+ },
+ {
+ .xpath = "/frr-pim:pim/join-prune-interval",
+ .cbs = {
+ .modify = pim_join_prune_interval_modify,
+ }
+ },
+ {
+ .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/keep-alive-timer",
+ .cbs = {
+ .modify = routing_control_plane_protocols_control_plane_protocol_pim_keep_alive_timer_modify,
+ }
+ },
+ {
+ .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/rp-keep-alive-timer",
+ .cbs = {
+ .modify = routing_control_plane_protocols_control_plane_protocol_pim_rp_keep_alive_timer_modify,
+ }
+ },
+ {
+ .xpath = "/frr-pim:pim/packets",
+ .cbs = {
+ .modify = pim_packets_modify,
+ }
+ },
+ {
+ .xpath = "/frr-pim:pim/register-suppress-time",
+ .cbs = {
+ .modify = pim_register_suppress_time_modify,
+ }
+ },
+ {
+ .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family",
+ .cbs = {
+ .create = routing_control_plane_protocols_control_plane_protocol_pim_address_family_create,
+ .destroy = routing_control_plane_protocols_control_plane_protocol_pim_address_family_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/send-v6-secondary",
+ .cbs = {
+ .modify = routing_control_plane_protocols_control_plane_protocol_pim_address_family_send_v6_secondary_modify,
+ .destroy = routing_control_plane_protocols_control_plane_protocol_pim_address_family_send_v6_secondary_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/spt-switchover",
+ .cbs = {
+ .apply_finish = routing_control_plane_protocols_control_plane_protocol_pim_address_family_spt_switchover_apply_finish,
+ }
+ },
+ {
+ .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/spt-switchover/spt-action",
+ .cbs = {
+ .modify = routing_control_plane_protocols_control_plane_protocol_pim_address_family_spt_switchover_spt_action_modify,
+ }
+ },
+ {
+ .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/spt-switchover/spt-infinity-prefix-list",
+ .cbs = {
+ .modify = routing_control_plane_protocols_control_plane_protocol_pim_address_family_spt_switchover_spt_infinity_prefix_list_modify,
+ .destroy = routing_control_plane_protocols_control_plane_protocol_pim_address_family_spt_switchover_spt_infinity_prefix_list_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/ssm-prefix-list",
+ .cbs = {
+ .modify = routing_control_plane_protocols_control_plane_protocol_pim_address_family_ssm_prefix_list_modify,
+ .destroy = routing_control_plane_protocols_control_plane_protocol_pim_address_family_ssm_prefix_list_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/ssm-pingd-source-ip",
+ .cbs = {
+ .create = routing_control_plane_protocols_control_plane_protocol_pim_address_family_ssm_pingd_source_ip_create,
+ .destroy = routing_control_plane_protocols_control_plane_protocol_pim_address_family_ssm_pingd_source_ip_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp-mesh-group",
+ .cbs = {
+ .create = routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_mesh_group_create,
+ .destroy = routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_mesh_group_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp-mesh-group/mesh-group-name",
+ .cbs = {
+ .modify = routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_mesh_group_mesh_group_name_modify,
+ .destroy = routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_mesh_group_mesh_group_name_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp-mesh-group/member-ip",
+ .cbs = {
+ .create = routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_mesh_group_member_ip_create,
+ .destroy = routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_mesh_group_member_ip_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp-mesh-group/source-ip",
+ .cbs = {
+ .modify = routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_mesh_group_source_ip_modify,
+ .destroy = routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_mesh_group_source_ip_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp-peer",
+ .cbs = {
+ .create = routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_peer_create,
+ .destroy = routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_peer_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp-peer/source-ip",
+ .cbs = {
+ .modify = routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_peer_source_ip_modify,
+ .destroy = routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_peer_source_ip_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/mlag",
+ .cbs = {
+ .create = routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_create,
+ .destroy = routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_destroy,
+ .apply_finish = routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_apply_finish,
+ }
+ },
+ {
+ .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/mlag/peerlink-rif",
+ .cbs = {
+ .modify = routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_peerlink_rif_modify,
+ .destroy = routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_peerlink_rif_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/mlag/reg-address",
+ .cbs = {
+ .modify = routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_reg_address_modify,
+ .destroy = routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_reg_address_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/mlag/my-role",
+ .cbs = {
+ .modify = routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_my_role_modify,
+ }
+ },
+ {
+ .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/mlag/peer-state",
+ .cbs = {
+ .modify = routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_peer_state_modify,
+ }
+ },
+ {
+ .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/register-accept-list",
+ .cbs = {
+ .modify = routing_control_plane_protocols_control_plane_protocol_pim_address_family_register_accept_list_modify,
+ .destroy = routing_control_plane_protocols_control_plane_protocol_pim_address_family_register_accept_list_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-pim:pim",
+ .cbs = {
+ .create = lib_interface_pim_create,
+ .destroy = lib_interface_pim_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-pim:pim/pim-enable",
+ .cbs = {
+ .modify = lib_interface_pim_pim_enable_modify,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-pim:pim/dr-priority",
+ .cbs = {
+ .modify = lib_interface_pim_dr_priority_modify,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-pim:pim/hello-interval",
+ .cbs = {
+ .modify = lib_interface_pim_hello_interval_modify,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-pim:pim/hello-holdtime",
+ .cbs = {
+ .modify = lib_interface_pim_hello_holdtime_modify,
+ .destroy = lib_interface_pim_hello_holdtime_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-pim:pim/bfd",
+ .cbs = {
+ .create = lib_interface_pim_bfd_create,
+ .destroy = lib_interface_pim_bfd_destroy,
+ .apply_finish = lib_interface_pim_bfd_apply_finish,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-pim:pim/bfd/min-rx-interval",
+ .cbs = {
+ .modify = lib_interface_pim_bfd_min_rx_interval_modify,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-pim:pim/bfd/min-tx-interval",
+ .cbs = {
+ .modify = lib_interface_pim_bfd_min_tx_interval_modify,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-pim:pim/bfd/detect_mult",
+ .cbs = {
+ .modify = lib_interface_pim_bfd_detect_mult_modify,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-pim:pim/bsm",
+ .cbs = {
+ .modify = lib_interface_pim_bsm_modify,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-pim:pim/unicast-bsm",
+ .cbs = {
+ .modify = lib_interface_pim_unicast_bsm_modify,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-pim:pim/active-active",
+ .cbs = {
+ .modify = lib_interface_pim_active_active_modify,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-pim:pim/address-family",
+ .cbs = {
+ .create = lib_interface_pim_address_family_create,
+ .destroy = lib_interface_pim_address_family_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-pim:pim/address-family/use-source",
+ .cbs = {
+ .modify = lib_interface_pim_address_family_use_source_modify,
+ .destroy = lib_interface_pim_address_family_use_source_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-pim:pim/address-family/multicast-boundary-oil",
+ .cbs = {
+ .modify = lib_interface_pim_address_family_multicast_boundary_oil_modify,
+ .destroy = lib_interface_pim_address_family_multicast_boundary_oil_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-pim:pim/address-family/mroute",
+ .cbs = {
+ .create = lib_interface_pim_address_family_mroute_create,
+ .destroy = lib_interface_pim_address_family_mroute_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-pim:pim/address-family/mroute/oif",
+ .cbs = {
+ .modify = lib_interface_pim_address_family_mroute_oif_modify,
+ .destroy = lib_interface_pim_address_family_mroute_oif_destroy,
+ }
+ },
+ {
+ .xpath = NULL,
+ },
+ }
+};
+
+/* clang-format off */
+const struct frr_yang_module_info frr_pim_rp_info = {
+ .name = "frr-pim-rp",
+ .nodes = {
+ {
+ .xpath = "/frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/frr-pim-rp:rp/static-rp/rp-list",
+ .cbs = {
+ .create = routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_static_rp_rp_list_create,
+ .destroy = routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_static_rp_rp_list_destroy,
+ }
+ },
+ {
+ .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",
+ .cbs = {
+ .create = routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_static_rp_rp_list_group_list_create,
+ .destroy = routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_static_rp_rp_list_group_list_destroy,
+ }
+ },
+ {
+ .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",
+ .cbs = {
+ .modify = routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_static_rp_rp_list_prefix_list_modify,
+ .destroy = routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_static_rp_rp_list_prefix_list_destroy,
+ }
+ },
+ {
+ .xpath = NULL,
+ },
+ }
+};
+
+/* clang-format off */
+const struct frr_yang_module_info frr_igmp_info = {
+ .name = "frr-igmp",
+ .nodes = {
+ {
+ .xpath = "/frr-interface:lib/interface/frr-igmp:igmp",
+ .cbs = {
+ .create = lib_interface_igmp_create,
+ .destroy = lib_interface_igmp_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-igmp:igmp/igmp-enable",
+ .cbs = {
+ .modify = lib_interface_igmp_igmp_enable_modify,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-igmp:igmp/version",
+ .cbs = {
+ .modify = lib_interface_igmp_version_modify,
+ .destroy = lib_interface_igmp_version_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-igmp:igmp/query-interval",
+ .cbs = {
+ .modify = lib_interface_igmp_query_interval_modify,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-igmp:igmp/query-max-response-time",
+ .cbs = {
+ .modify = lib_interface_igmp_query_max_response_time_modify,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-igmp:igmp/last-member-query-interval",
+ .cbs = {
+ .modify = lib_interface_igmp_last_member_query_interval_modify,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-igmp:igmp/robustness-variable",
+ .cbs = {
+ .modify = lib_interface_igmp_robustness_variable_modify,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-igmp:igmp/address-family",
+ .cbs = {
+ .create = lib_interface_igmp_address_family_create,
+ .destroy = lib_interface_igmp_address_family_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-interface:lib/interface/frr-igmp:igmp/address-family/static-group",
+ .cbs = {
+ .create = lib_interface_igmp_address_family_static_group_create,
+ .destroy = lib_interface_igmp_address_family_static_group_destroy,
+ }
+ },
+ {
+ .xpath = NULL,
+ },
+ }
+};
diff --git a/pimd/pim_nb.h b/pimd/pim_nb.h
new file mode 100644
index 000000000..78eb68010
--- /dev/null
+++ b/pimd/pim_nb.h
@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) 2020 VmWare
+ * Sarita Patra
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef _FRR_PIM_NB_H_
+#define _FRR_PIM_NB_H_
+
+extern const struct frr_yang_module_info frr_pim_info;
+extern const struct frr_yang_module_info frr_pim_rp_info;
+extern const struct frr_yang_module_info frr_igmp_info;
+
+/* frr-pim prototypes*/
+int routing_control_plane_protocols_control_plane_protocol_pim_ecmp_modify(
+ struct nb_cb_modify_args *args);
+int routing_control_plane_protocols_control_plane_protocol_pim_ecmp_rebalance_modify(
+ struct nb_cb_modify_args *args);
+int pim_join_prune_interval_modify(struct nb_cb_modify_args *args);
+int routing_control_plane_protocols_control_plane_protocol_pim_keep_alive_timer_modify(
+ struct nb_cb_modify_args *args);
+int routing_control_plane_protocols_control_plane_protocol_pim_rp_keep_alive_timer_modify(
+ struct nb_cb_modify_args *args);
+int pim_packets_modify(struct nb_cb_modify_args *args);
+int pim_register_suppress_time_modify(struct nb_cb_modify_args *args);
+int routing_control_plane_protocols_control_plane_protocol_pim_address_family_create(
+ struct nb_cb_create_args *args);
+int routing_control_plane_protocols_control_plane_protocol_pim_address_family_destroy(
+ struct nb_cb_destroy_args *args);
+int routing_control_plane_protocols_control_plane_protocol_pim_address_family_send_v6_secondary_modify(
+ struct nb_cb_modify_args *args);
+int routing_control_plane_protocols_control_plane_protocol_pim_address_family_send_v6_secondary_destroy(
+ struct nb_cb_destroy_args *args);
+void routing_control_plane_protocols_control_plane_protocol_pim_address_family_spt_switchover_apply_finish(
+ struct nb_cb_apply_finish_args *args);
+int routing_control_plane_protocols_control_plane_protocol_pim_address_family_spt_switchover_spt_action_modify(
+ struct nb_cb_modify_args *args);
+int routing_control_plane_protocols_control_plane_protocol_pim_address_family_spt_switchover_spt_infinity_prefix_list_modify(
+ struct nb_cb_modify_args *args);
+int routing_control_plane_protocols_control_plane_protocol_pim_address_family_spt_switchover_spt_infinity_prefix_list_destroy(
+ struct nb_cb_destroy_args *args);
+int routing_control_plane_protocols_control_plane_protocol_pim_address_family_ssm_prefix_list_modify(
+ struct nb_cb_modify_args *args);
+int routing_control_plane_protocols_control_plane_protocol_pim_address_family_ssm_prefix_list_destroy(
+ struct nb_cb_destroy_args *args);
+int routing_control_plane_protocols_control_plane_protocol_pim_address_family_ssm_pingd_source_ip_create(
+ struct nb_cb_create_args *args);
+int routing_control_plane_protocols_control_plane_protocol_pim_address_family_ssm_pingd_source_ip_destroy(
+ struct nb_cb_destroy_args *args);
+int routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_mesh_group_create(
+ struct nb_cb_create_args *args);
+int routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_mesh_group_destroy(
+ struct nb_cb_destroy_args *args);
+int routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_mesh_group_mesh_group_name_modify(
+ struct nb_cb_modify_args *args);
+int routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_mesh_group_mesh_group_name_destroy(
+ struct nb_cb_destroy_args *args);
+int routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_mesh_group_member_ip_create(
+ struct nb_cb_create_args *args);
+int routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_mesh_group_member_ip_destroy(
+ struct nb_cb_destroy_args *args);
+int routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_mesh_group_source_ip_modify(
+ struct nb_cb_modify_args *args);
+int routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_mesh_group_source_ip_destroy(
+ struct nb_cb_destroy_args *args);
+int routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_peer_create(
+ struct nb_cb_create_args *args);
+int routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_peer_destroy(
+ struct nb_cb_destroy_args *args);
+int routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_peer_source_ip_modify(
+ struct nb_cb_modify_args *args);
+int routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_peer_source_ip_destroy(
+ struct nb_cb_destroy_args *args);
+int routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_create(
+ struct nb_cb_create_args *args);
+int routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_destroy(
+ struct nb_cb_destroy_args *args);
+void routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_apply_finish(
+ struct nb_cb_apply_finish_args *args);
+int routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_peerlink_rif_modify(
+ struct nb_cb_modify_args *args);
+int routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_peerlink_rif_destroy(
+ struct nb_cb_destroy_args *args);
+int routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_reg_address_modify(
+ struct nb_cb_modify_args *args);
+int routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_reg_address_destroy(
+ struct nb_cb_destroy_args *args);
+int routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_my_role_modify(
+ struct nb_cb_modify_args *args);
+int routing_control_plane_protocols_control_plane_protocol_pim_address_family_mlag_peer_state_modify(
+ struct nb_cb_modify_args *args);
+int routing_control_plane_protocols_control_plane_protocol_pim_address_family_register_accept_list_modify(
+ struct nb_cb_modify_args *args);
+int routing_control_plane_protocols_control_plane_protocol_pim_address_family_register_accept_list_destroy(
+ struct nb_cb_destroy_args *args);
+int lib_interface_pim_dr_priority_modify(
+ struct nb_cb_modify_args *args);
+int lib_interface_pim_create(struct nb_cb_create_args *args);
+int lib_interface_pim_destroy(struct nb_cb_destroy_args *args);
+int lib_interface_pim_pim_enable_modify(struct nb_cb_modify_args *args);
+int lib_interface_pim_hello_interval_modify(struct nb_cb_modify_args *args);
+int lib_interface_pim_hello_holdtime_modify(struct nb_cb_modify_args *args);
+int lib_interface_pim_hello_holdtime_destroy(struct nb_cb_destroy_args *args);
+int lib_interface_pim_bfd_create(struct nb_cb_create_args *args);
+int lib_interface_pim_bfd_destroy(struct nb_cb_destroy_args *args);
+void lib_interface_pim_bfd_apply_finish(struct nb_cb_apply_finish_args *args);
+int lib_interface_pim_bfd_min_rx_interval_modify(struct nb_cb_modify_args *args);
+int lib_interface_pim_bfd_min_tx_interval_modify(
+ struct nb_cb_modify_args *args);
+int lib_interface_pim_bfd_detect_mult_modify(struct nb_cb_modify_args *args);
+int lib_interface_pim_bsm_modify(struct nb_cb_modify_args *args);
+int lib_interface_pim_unicast_bsm_modify(struct nb_cb_modify_args *args);
+int lib_interface_pim_active_active_modify(struct nb_cb_modify_args *args);
+int lib_interface_pim_address_family_create(struct nb_cb_create_args *args);
+int lib_interface_pim_address_family_destroy(struct nb_cb_destroy_args *args);
+int lib_interface_pim_address_family_use_source_modify(
+ struct nb_cb_modify_args *args);
+int lib_interface_pim_address_family_use_source_destroy(
+ struct nb_cb_destroy_args *args);
+int lib_interface_pim_address_family_multicast_boundary_oil_modify(
+ struct nb_cb_modify_args *args);
+int lib_interface_pim_address_family_multicast_boundary_oil_destroy(
+ struct nb_cb_destroy_args *args);
+int lib_interface_pim_address_family_mroute_create(
+ struct nb_cb_create_args *args);
+int lib_interface_pim_address_family_mroute_destroy(
+ struct nb_cb_destroy_args *args);
+int lib_interface_pim_address_family_mroute_oif_modify(
+ struct nb_cb_modify_args *args);
+int lib_interface_pim_address_family_mroute_oif_destroy(
+ struct nb_cb_destroy_args *args);
+
+/* frr-pim-rp prototypes*/
+int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_static_rp_rp_list_create(
+ struct nb_cb_create_args *args);
+int routing_control_plane_protocols_control_plane_protocol_pim_address_family_rp_static_rp_rp_list_destroy(
+ struct nb_cb_destroy_args *args);
+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);
+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);
+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);
+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);
+
+/* frr-igmp prototypes*/
+int lib_interface_igmp_create(struct nb_cb_create_args *args);
+int lib_interface_igmp_destroy(struct nb_cb_destroy_args *args);
+int lib_interface_igmp_igmp_enable_modify(struct nb_cb_modify_args *args);
+int lib_interface_igmp_version_modify(struct nb_cb_modify_args *args);
+int lib_interface_igmp_version_destroy(struct nb_cb_destroy_args *args);
+int lib_interface_igmp_query_interval_modify(struct nb_cb_modify_args *args);
+int lib_interface_igmp_query_max_response_time_modify(
+ struct nb_cb_modify_args *args);
+int lib_interface_igmp_last_member_query_interval_modify(
+ struct nb_cb_modify_args *args);
+int lib_interface_igmp_robustness_variable_modify(
+ struct nb_cb_modify_args *args);
+int lib_interface_igmp_address_family_create(struct nb_cb_create_args *args);
+int lib_interface_igmp_address_family_destroy(struct nb_cb_destroy_args *args);
+int lib_interface_igmp_address_family_static_group_create(
+ struct nb_cb_create_args *args);
+int lib_interface_igmp_address_family_static_group_destroy(
+ struct nb_cb_destroy_args *args);
+
+/*
+ * Callback registered with routing_nb lib to validate only
+ * one instance of staticd is allowed
+ */
+int routing_control_plane_protocols_name_validate(
+ struct nb_cb_create_args *args);
+
+#define FRR_PIM_XPATH \
+ "/frr-routing:routing/control-plane-protocols/" \
+ "control-plane-protocol[type='%s'][name='%s'][vrf='%s']/" \
+ "frr-pim:pim"
+#define FRR_PIM_AF_XPATH \
+ "/frr-routing:routing/control-plane-protocols/" \
+ "control-plane-protocol[type='%s'][name='%s'][vrf='%s']/" \
+ "frr-pim:pim/address-family[address-family='%s']"
+#define FRR_PIM_STATIC_RP_XPATH \
+ "/frr-routing:routing/control-plane-protocols/" \
+ "control-plane-protocol[type='%s'][name='%s'][vrf='%s']/" \
+ "frr-pim:pim/address-family[address-family='%s']/" \
+ "frr-pim-rp:rp/static-rp/rp-list[rp-address='%s']"
+#define FRR_IGMP_JOIN_XPATH \
+ "./frr-igmp:igmp/address-family[address-family='%s']/" \
+ "static-group[group-addr='%s'][source-addr='%s']"
+#endif /* _FRR_PIM_NB_H_ */
diff --git a/pimd/pim_nb_config.c b/pimd/pim_nb_config.c
new file mode 100644
index 000000000..9f7e5286f
--- /dev/null
+++ b/pimd/pim_nb_config.c
@@ -0,0 +1,3034 @@
+/*
+ * Copyright (C) 2020 VmWare
+ * Sarita Patra
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "pimd.h"
+#include "pim_nb.h"
+#include "lib/northbound_cli.h"
+#include "pim_igmpv3.h"
+#include "pim_pim.h"
+#include "pim_mlag.h"
+#include "pim_bfd.h"
+#include "pim_static.h"
+#include "pim_ssm.h"
+#include "pim_ssmpingd.h"
+#include "pim_vxlan.h"
+
+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 int interface_pim_use_src_cmd_worker(struct interface *ifp,
+ struct in_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_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 ip_no_msdp_mesh_group_cmd_worker(struct pim_instance *pim,
+ const char *mg,
+ char *errmsg, size_t errmsg_len)
+{
+ enum pim_msdp_err result;
+
+ result = pim_msdp_mg_del(pim, mg);
+
+ switch (result) {
+ case PIM_MSDP_ERR_NONE:
+ break;
+ case PIM_MSDP_ERR_NO_MG:
+ snprintf(errmsg, errmsg_len,
+ "%% mesh-group does not exist");
+ break;
+ default:
+ snprintf(errmsg, errmsg_len,
+ "mesh-group source del failed");
+ }
+
+ return result ? NB_ERR : NB_OK;
+}
+
+static int ip_msdp_mesh_group_member_cmd_worker(struct pim_instance *pim,
+ const char *mg,
+ struct in_addr mbr_ip,
+ char *errmsg, size_t errmsg_len)
+{
+ enum pim_msdp_err result;
+ int ret = NB_OK;
+
+ result = pim_msdp_mg_mbr_add(pim, mg, mbr_ip);
+
+ switch (result) {
+ case PIM_MSDP_ERR_NONE:
+ break;
+ case PIM_MSDP_ERR_OOM:
+ ret = NB_ERR;
+ snprintf(errmsg, errmsg_len,
+ "%% Out of memory");
+ break;
+ case PIM_MSDP_ERR_MG_MBR_EXISTS:
+ ret = NB_ERR;
+ snprintf(errmsg, errmsg_len,
+ "%% mesh-group member exists");
+ break;
+ case PIM_MSDP_ERR_MAX_MESH_GROUPS:
+ ret = NB_ERR;
+ snprintf(errmsg, errmsg_len,
+ "%% Only one mesh-group allowed currently");
+ break;
+ default:
+ ret = NB_ERR;
+ snprintf(errmsg, errmsg_len,
+ "%% member add failed");
+ }
+
+ return ret;
+}
+
+static int ip_no_msdp_mesh_group_member_cmd_worker(struct pim_instance *pim,
+ const char *mg,
+ struct in_addr mbr_ip,
+ char *errmsg,
+ size_t errmsg_len)
+{
+ enum pim_msdp_err result;
+
+ result = pim_msdp_mg_mbr_del(pim, mg, mbr_ip);
+
+ switch (result) {
+ case PIM_MSDP_ERR_NONE:
+ break;
+ case PIM_MSDP_ERR_NO_MG:
+ snprintf(errmsg, errmsg_len,
+ "%% mesh-group does not exist");
+ break;
+ case PIM_MSDP_ERR_NO_MG_MBR:
+ snprintf(errmsg, errmsg_len,
+ "%% mesh-group member does not exist");
+ break;
+ default:
+ snprintf(errmsg, errmsg_len,
+ "%% mesh-group member del failed");
+ }
+
+ return result ? NB_ERR : NB_OK;
+}
+
+static int ip_msdp_mesh_group_source_cmd_worker(struct pim_instance *pim,
+ const char *mg,
+ struct in_addr src_ip,
+ char *errmsg, size_t errmsg_len)
+{
+ enum pim_msdp_err result;
+
+ result = pim_msdp_mg_src_add(pim, mg, src_ip);
+
+ switch (result) {
+ case PIM_MSDP_ERR_NONE:
+ break;
+ case PIM_MSDP_ERR_OOM:
+ snprintf(errmsg, errmsg_len,
+ "%% Out of memory");
+ break;
+ case PIM_MSDP_ERR_MAX_MESH_GROUPS:
+ snprintf(errmsg, errmsg_len,
+ "%% Only one mesh-group allowed currently");
+ break;
+ default:
+ snprintf(errmsg, errmsg_len,
+ "%% source add failed");
+ }
+
+ return result ? NB_ERR : NB_OK;
+}
+
+static int ip_no_msdp_mesh_group_source_cmd_worker(struct pim_instance *pim,
+ const char *mg,
+ char *errmsg,
+ size_t errmsg_len)
+{
+ enum pim_msdp_err result;
+
+ result = pim_msdp_mg_src_del(pim, mg);
+
+ switch (result) {
+ case PIM_MSDP_ERR_NONE:
+ break;
+ case PIM_MSDP_ERR_NO_MG:
+ snprintf(errmsg, errmsg_len,
+ "%% mesh-group does not exist");
+ break;
+ default:
+ snprintf(errmsg, errmsg_len,
+ "%% mesh-group source del failed");
+ }
+
+ return result ? NB_ERR : NB_OK;
+}
+
+static int ip_msdp_peer_cmd_worker(struct pim_instance *pim,
+ struct in_addr peer_addr,
+ struct in_addr local_addr,
+ char *errmsg, size_t errmsg_len)
+{
+ enum pim_msdp_err result;
+ int ret = NB_OK;
+
+ result = pim_msdp_peer_add(pim, peer_addr, local_addr, "default",
+ NULL /* mp_p */);
+ switch (result) {
+ case PIM_MSDP_ERR_NONE:
+ break;
+ case PIM_MSDP_ERR_OOM:
+ ret = NB_ERR;
+ snprintf(errmsg, errmsg_len,
+ "%% Out of memory");
+ break;
+ case PIM_MSDP_ERR_PEER_EXISTS:
+ ret = NB_ERR;
+ snprintf(errmsg, errmsg_len,
+ "%% Peer exists");
+ break;
+ case PIM_MSDP_ERR_MAX_MESH_GROUPS:
+ ret = NB_ERR;
+ snprintf(errmsg, errmsg_len,
+ "%% Only one mesh-group allowed currently");
+ break;
+ default:
+ ret = NB_ERR;
+ snprintf(errmsg, errmsg_len,
+ "%% peer add failed");
+ }
+
+ return ret;
+}
+
+static int ip_no_msdp_peer_cmd_worker(struct pim_instance *pim,
+ struct in_addr peer_addr,
+ char *errmsg, size_t errmsg_len)
+{
+ enum pim_msdp_err result;
+
+ result = pim_msdp_peer_del(pim, peer_addr);
+ switch (result) {
+ case PIM_MSDP_ERR_NONE:
+ break;
+ case PIM_MSDP_ERR_NO_PEER:
+ snprintf(errmsg, errmsg_len,
+ "%% Peer does not exist");
+ break;
+ default:
+ snprintf(errmsg, errmsg_len,
+ "%% peer del failed");
+ }
+
+ return result ? NB_ERR : NB_OK;
+}
+
+static int pim_rp_cmd_worker(struct pim_instance *pim,
+ struct in_addr rp_addr,
+ struct prefix group, const char *plist,
+ char *errmsg, size_t errmsg_len)
+{
+ char rp_str[INET_ADDRSTRLEN];
+ int result;
+
+ inet_ntop(AF_INET, &rp_addr, rp_str, sizeof(rp_str));
+
+ result = pim_rp_new(pim, rp_addr, group, plist, RP_SRC_STATIC);
+
+ if (result == PIM_RP_NO_PATH) {
+ snprintf(errmsg, errmsg_len,
+ "No Path to RP address specified: %s", rp_str);
+ return NB_ERR_INCONSISTENCY;
+ }
+
+ 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,
+ struct in_addr rp_addr, struct prefix group,
+ const char *plist,
+ char *errmsg, size_t errmsg_len)
+{
+ char rp_str[INET_ADDRSTRLEN];
+ char group_str[PREFIX2STR_BUFFER];
+ int result;
+
+ inet_ntop(AF_INET, &rp_addr, rp_str, sizeof(rp_str));
+ 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) {
+ snprintf(errmsg, errmsg_len,
+ "Bad RP address specified: %s", rp_str);
+ 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_get(dnode, "%s/frr-pim:pim/pim-enable",
+ if_xpath);
+ igmp_enable_dnode = yang_dnode_get(dnode,
+ "%s/frr-igmp:igmp/igmp-enable",
+ if_xpath);
+
+ 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_igmp_start(struct interface *ifp)
+{
+ struct pim_interface *pim_ifp;
+ uint8_t need_startup = 0;
+
+ pim_ifp = ifp->info;
+
+ if (!pim_ifp) {
+ (void)pim_if_new(ifp, true, false, false, false);
+ need_startup = 1;
+ } else {
+ if (!PIM_IF_TEST_IGMP(pim_ifp->options)) {
+ PIM_IF_DO_IGMP(pim_ifp->options);
+ need_startup = 1;
+ }
+ }
+
+ /* '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.
+ */
+static void igmp_sock_query_interval_reconfig(struct igmp_sock *igmp)
+{
+ struct interface *ifp;
+ struct pim_interface *pim_ifp;
+
+ zassert(igmp);
+
+ /* other querier present? */
+
+ if (igmp->t_other_querier_timer)
+ return;
+
+ /* this is the querier */
+
+ zassert(igmp->interface);
+ zassert(igmp->interface->info);
+
+ ifp = igmp->interface;
+ pim_ifp = ifp->info;
+
+ if (PIM_DEBUG_IGMP_TRACE) {
+ char ifaddr_str[INET_ADDRSTRLEN];
+
+ pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str,
+ sizeof(ifaddr_str));
+ zlog_debug("%s: Querier %s on %s reconfig query_interval=%d",
+ __func__, ifaddr_str, ifp->name,
+ pim_ifp->igmp_default_query_interval);
+ }
+
+ /*
+ * igmp_startup_mode_on() will reset QQI:
+
+ * igmp->querier_query_interval = pim_ifp->igmp_default_query_interval;
+ */
+ igmp_startup_mode_on(igmp);
+}
+
+static void igmp_sock_query_reschedule(struct igmp_sock *igmp)
+{
+ if (igmp->mtrace_only)
+ return;
+
+ if (igmp->t_igmp_query_timer) {
+ /* other querier present */
+ zassert(igmp->t_igmp_query_timer);
+ zassert(!igmp->t_other_querier_timer);
+
+ pim_igmp_general_query_off(igmp);
+ pim_igmp_general_query_on(igmp);
+
+ zassert(igmp->t_igmp_query_timer);
+ zassert(!igmp->t_other_querier_timer);
+ } else {
+ /* this is the querier */
+
+ zassert(!igmp->t_igmp_query_timer);
+ zassert(igmp->t_other_querier_timer);
+
+ pim_igmp_other_querier_timer_off(igmp);
+ pim_igmp_other_querier_timer_on(igmp);
+
+ zassert(!igmp->t_igmp_query_timer);
+ zassert(igmp->t_other_querier_timer);
+ }
+}
+
+static void change_query_interval(struct pim_interface *pim_ifp,
+ int query_interval)
+{
+ struct listnode *sock_node;
+ struct igmp_sock *igmp;
+
+ pim_ifp->igmp_default_query_interval = query_interval;
+
+ for (ALL_LIST_ELEMENTS_RO(pim_ifp->igmp_socket_list, sock_node, igmp)) {
+ igmp_sock_query_interval_reconfig(igmp);
+ igmp_sock_query_reschedule(igmp);
+ }
+}
+
+static void change_query_max_response_time(struct pim_interface *pim_ifp,
+ int query_max_response_time_dsec)
+{
+ struct listnode *sock_node;
+ struct igmp_sock *igmp;
+
+ pim_ifp->igmp_query_max_response_time_dsec =
+ query_max_response_time_dsec;
+
+ /*
+ * 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->igmp_socket_list, sock_node, igmp)) {
+ struct listnode *grp_node;
+ struct igmp_group *grp;
+
+ /* reschedule socket general query */
+ igmp_sock_query_reschedule(igmp);
+
+ /* scan socket groups */
+ for (ALL_LIST_ELEMENTS_RO(igmp->igmp_group_list, grp_node,
+ grp)) {
+ struct listnode *src_node;
+ struct igmp_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(igmp, grp, src);
+ }
+ }
+ }
+}
+
+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/packets
+ */
+int pim_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/join-prune-interval
+ */
+int pim_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/register-suppress-time
+ */
+int pim_register_suppress_time_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/ecmp
+ */
+int routing_control_plane_protocols_control_plane_protocol_pim_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/ecmp-rebalance
+ */
+int routing_control_plane_protocols_control_plane_protocol_pim_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/keep-alive-timer
+ */
+int routing_control_plane_protocols_control_plane_protocol_pim_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/rp-keep-alive-timer
+ */
+int routing_control_plane_protocols_control_plane_protocol_pim_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:
+ /* TODO: implement me. */
+ 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;
+ struct ipaddr 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_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;
+}
+
+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:
+ 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;
+ }
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp-mesh-group
+ */
+int routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_mesh_group_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_msdp_mesh_group_destroy(
+ struct nb_cb_destroy_args *args)
+{
+ struct vrf *vrf;
+ struct pim_instance *pim;
+ const char *mesh_group_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;
+ mesh_group_name = yang_dnode_get_string(args->dnode, ".");
+
+ result = ip_no_msdp_mesh_group_cmd_worker(pim, mesh_group_name,
+ args->errmsg,
+ args->errmsg_len);
+
+ if (result != PIM_MSDP_ERR_NONE)
+ return NB_ERR_INCONSISTENCY;
+
+ break;
+ }
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp-mesh-group/mesh-group-name
+ */
+int routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_mesh_group_mesh_group_name_modify(
+ struct nb_cb_modify_args *args)
+{
+ const char *mesh_group_name;
+ const char *mesh_group_name_old;
+ char xpath[XPATH_MAXLEN];
+
+ switch (args->event) {
+ case NB_EV_VALIDATE:
+ mesh_group_name = yang_dnode_get_string(args->dnode, ".");
+ yang_dnode_get_path(args->dnode, xpath, sizeof(xpath));
+
+ if (yang_dnode_exists(running_config->dnode, xpath) == false)
+ break;
+
+ mesh_group_name_old = yang_dnode_get_string(
+ running_config->dnode,
+ xpath);
+ if (strcmp(mesh_group_name, mesh_group_name_old)) {
+ /* currently only one mesh-group can exist at a time */
+ snprintf(args->errmsg, args->errmsg_len,
+ "Only one mesh-group allowed currently");
+ return NB_ERR_VALIDATION;
+ }
+ break;
+ 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_msdp_mesh_group_mesh_group_name_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/msdp-mesh-group/member-ip
+ */
+int routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_mesh_group_member_ip_create(
+ struct nb_cb_create_args *args)
+{
+ struct vrf *vrf;
+ struct pim_instance *pim;
+ const char *mesh_group_name;
+ struct ipaddr mbr_ip;
+ enum pim_msdp_err 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;
+ mesh_group_name = yang_dnode_get_string(args->dnode,
+ "../mesh-group-name");
+ yang_dnode_get_ip(&mbr_ip, args->dnode, NULL);
+
+ result = ip_msdp_mesh_group_member_cmd_worker(
+ pim, mesh_group_name, mbr_ip.ip._v4_addr,
+ args->errmsg, args->errmsg_len);
+
+ if (result != PIM_MSDP_ERR_NONE)
+ return NB_ERR_INCONSISTENCY;
+
+ break;
+ }
+
+ return NB_OK;
+}
+
+int routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_mesh_group_member_ip_destroy(
+ struct nb_cb_destroy_args *args)
+{
+ struct vrf *vrf;
+ struct pim_instance *pim;
+ const char *mesh_group_name;
+ struct ipaddr mbr_ip;
+ enum pim_msdp_err 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;
+ mesh_group_name = yang_dnode_get_string(args->dnode,
+ "../mesh-group-name");
+ yang_dnode_get_ip(&mbr_ip, args->dnode, NULL);
+
+ result = ip_no_msdp_mesh_group_member_cmd_worker(
+ pim, mesh_group_name, mbr_ip.ip._v4_addr,
+ args->errmsg, args->errmsg_len);
+
+ if (result != PIM_MSDP_ERR_NONE)
+ return NB_ERR_INCONSISTENCY;
+
+ break;
+ }
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-routing:routing/control-plane-protocols/control-plane-protocol/frr-pim:pim/address-family/msdp-mesh-group/source-ip
+ */
+int routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_mesh_group_source_ip_modify(
+ struct nb_cb_modify_args *args)
+{
+ struct vrf *vrf;
+ struct pim_instance *pim;
+ const char *mesh_group_name;
+ struct ipaddr src_ip;
+ enum pim_msdp_err 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;
+ mesh_group_name = yang_dnode_get_string(args->dnode,
+ "../mesh-group-name");
+ yang_dnode_get_ip(&src_ip, args->dnode, NULL);
+
+ result = ip_msdp_mesh_group_source_cmd_worker(
+ pim, mesh_group_name, src_ip.ip._v4_addr,
+ args->errmsg, args->errmsg_len);
+
+ if (result != PIM_MSDP_ERR_NONE)
+ return NB_ERR_INCONSISTENCY;
+
+ break;
+ }
+ return NB_OK;
+}
+
+int routing_control_plane_protocols_control_plane_protocol_pim_address_family_msdp_mesh_group_source_ip_destroy(
+ struct nb_cb_destroy_args *args)
+{
+ struct vrf *vrf;
+ struct pim_instance *pim;
+ const char *mesh_group_name;
+ enum pim_msdp_err 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;
+ mesh_group_name = yang_dnode_get_string(args->dnode,
+ "../mesh-group-name");
+
+ result = ip_no_msdp_mesh_group_source_cmd_worker(
+ pim, mesh_group_name, args->errmsg,
+ args->errmsg_len);
+
+ if (result != PIM_MSDP_ERR_NONE)
+ return NB_ERR_INCONSISTENCY;
+
+ 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)
+{
+ 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_msdp_peer_destroy(
+ struct nb_cb_destroy_args *args)
+{
+ int result;
+ struct pim_instance *pim;
+ struct ipaddr peer_ip;
+ 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;
+ yang_dnode_get_ip(&peer_ip, args->dnode, "./peer-ip");
+ result = ip_no_msdp_peer_cmd_worker(pim, peer_ip.ip._v4_addr,
+ 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/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)
+{
+ int result;
+ struct vrf *vrf;
+ struct pim_instance *pim;
+ struct ipaddr peer_ip;
+ struct ipaddr source_ip;
+ const struct lyd_node *mesh_group_name_dnode;
+ const char *mesh_group_name;
+
+ switch (args->event) {
+ case NB_EV_VALIDATE:
+ mesh_group_name_dnode =
+ yang_dnode_get(args->dnode,
+ "../../msdp-mesh-group/mesh-group-name");
+ if (mesh_group_name_dnode) {
+ mesh_group_name =
+ yang_dnode_get_string(mesh_group_name_dnode,
+ ".");
+ if (strcmp(mesh_group_name, "default")) {
+ /* currently only one mesh-group can exist at a
+ * time
+ */
+ snprintf(args->errmsg, args->errmsg_len,
+ "%% Only one mesh-group allowed currently");
+ return NB_ERR_VALIDATION;
+ }
+ }
+ break;
+ 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, NULL);
+
+ result = ip_msdp_peer_cmd_worker(pim, peer_ip.ip._v4_addr,
+ source_ip.ip._v4_addr,
+ 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_msdp_peer_source_ip_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
+ */
+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(&reg_addr, args->dnode, "./reg-address");
+
+ pim_vxlan_mlag_update(true, peer_state, role, ifp,
+ &reg_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
+ */
+int lib_interface_pim_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_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;
+
+ 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;
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-pim:pim/pim-enable
+ */
+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:
+ 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;
+ }
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-pim:pim/hello-interval
+ */
+int lib_interface_pim_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_uint8(args->dnode, NULL);
+ break;
+ }
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-pim:pim/hello-holdtime
+ */
+int lib_interface_pim_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_uint8(args->dnode, NULL);
+ break;
+ }
+
+ return NB_OK;
+
+}
+
+int lib_interface_pim_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/bfd
+ */
+int lib_interface_pim_bfd_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_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->parent, NULL, true);
+ pim_ifp = ifp->info;
+ if (pim_ifp->bfd_info) {
+ pim_bfd_reg_dereg_all_nbr(ifp,
+ ZEBRA_BFD_DEST_DEREGISTER);
+ bfd_info_free(&(pim_ifp->bfd_info));
+ }
+ break;
+ }
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-pim:pim/bfd
+ */
+void lib_interface_pim_bfd_apply_finish(struct nb_cb_apply_finish_args *args)
+{
+ struct interface *ifp;
+ struct pim_interface *pim_ifp;
+ uint32_t min_rx;
+ uint32_t min_tx;
+ uint8_t detect_mult;
+
+ ifp = nb_running_get_entry(args->dnode->parent, NULL, true);
+ pim_ifp = ifp->info;
+
+ if (!pim_ifp) {
+ zlog_debug("Pim not enabled on this interface");
+ return;
+ }
+
+ min_rx = yang_dnode_get_uint16(args->dnode, "./min-rx-interval");
+ min_tx = yang_dnode_get_uint16(args->dnode, "./min-tx-interval");
+ detect_mult = yang_dnode_get_uint8(args->dnode, "./detect_mult");
+
+ if ((min_rx == BFD_DEF_MIN_RX) && (min_tx == BFD_DEF_MIN_TX)
+ && (detect_mult == BFD_DEF_DETECT_MULT))
+ pim_bfd_if_param_set(ifp, min_rx, min_tx, detect_mult, 1);
+ else
+ pim_bfd_if_param_set(ifp, min_rx, min_tx, detect_mult, 0);
+
+ nb_running_set_entry(args->dnode, pim_ifp->bfd_info);
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-pim:pim/bfd/min-rx-interval
+ */
+int lib_interface_pim_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/bfd/min-tx-interval
+ */
+int lib_interface_pim_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/bfd/detect_mult
+ */
+int lib_interface_pim_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/bsm
+ */
+int lib_interface_pim_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;
+ pim_ifp->bsm_enable = yang_dnode_get_bool(args->dnode, NULL);
+
+ break;
+ }
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-pim:pim/unicast-bsm
+ */
+int lib_interface_pim_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;
+ pim_ifp->ucast_bsm_accept =
+ yang_dnode_get_bool(args->dnode, NULL);
+
+ break;
+ }
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-pim:pim/active-active
+ */
+int lib_interface_pim_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/dr-priority
+ */
+int lib_interface_pim_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
+ */
+int lib_interface_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 lib_interface_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-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;
+ struct ipaddr 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);
+ yang_dnode_get_ip(&source_addr, args->dnode, NULL);
+
+ result = interface_pim_use_src_cmd_worker(
+ ifp, source_addr.ip._v4_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;
+ struct in_addr source_addr = {INADDR_ANY};
+ 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, source_addr,
+ 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;
+ struct ipaddr source_addr;
+ struct ipaddr 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_id);
+
+ if (!oif) {
+ snprintf(args->errmsg, args->errmsg_len,
+ "No such interface name %s",
+ oifname);
+ return NB_ERR_INCONSISTENCY;
+ }
+
+ yang_dnode_get_ip(&source_addr, args->dnode, "./source-addr");
+ yang_dnode_get_ip(&group_addr, args->dnode, "./group-addr");
+
+ if (pim_static_del(pim, iif, oif, group_addr.ip._v4_addr,
+ source_addr.ip._v4_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;
+ struct ipaddr source_addr;
+ struct ipaddr 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, NULL);
+ oif = if_lookup_by_name(oifname, pim->vrf_id);
+
+ if (!oif) {
+ snprintf(args->errmsg, args->errmsg_len,
+ "No such interface name %s",
+ oifname);
+ return NB_ERR_INCONSISTENCY;
+ }
+
+ yang_dnode_get_ip(&source_addr, args->dnode, "../source-addr");
+ yang_dnode_get_ip(&group_addr, args->dnode, "../group-addr");
+
+ if (pim_static_add(pim, iif, oif, group_addr.ip._v4_addr,
+ source_addr.ip._v4_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;
+ struct ipaddr 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_ip(&rp_addr, args->dnode, "./rp-address");
+
+ if (yang_dnode_get(args->dnode, "./group-list")) {
+ yang_dnode_get_ipv4p(&group, args->dnode,
+ "./group-list");
+ apply_mask_ipv4((struct prefix_ipv4 *)&group);
+ result = pim_no_rp_cmd_worker(pim, rp_addr.ip._v4_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");
+ str2prefix("224.0.0.0/4", &group);
+ result = pim_no_rp_cmd_worker(pim, rp_addr.ip._v4_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;
+ struct ipaddr 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_ip(&rp_addr, args->dnode, "../rp-address");
+ yang_dnode_get_ipv4p(&group, args->dnode, NULL);
+ apply_mask_ipv4((struct prefix_ipv4 *)&group);
+
+ return pim_rp_cmd_worker(pim, rp_addr.ip._v4_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;
+ struct ipaddr 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_ip(&rp_addr, args->dnode, "../rp-address");
+ yang_dnode_get_ipv4p(&group, args->dnode, NULL);
+ apply_mask_ipv4((struct prefix_ipv4 *)&group);
+
+ return pim_no_rp_cmd_worker(pim, rp_addr.ip._v4_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;
+ struct ipaddr 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_ip(&rp_addr, args->dnode, "../rp-address");
+ str2prefix("224.0.0.0/4", &group);
+ return pim_rp_cmd_worker(pim, rp_addr.ip._v4_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;
+ struct ipaddr 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_ip(&rp_addr, args->dnode, "../rp-address");
+ plist = yang_dnode_get_string(args->dnode, NULL);
+ str2prefix("224.0.0.0/4", &group);
+ return pim_no_rp_cmd_worker(pim, rp_addr.ip._v4_addr, group,
+ plist, args->errmsg,
+ args->errmsg_len);
+ break;
+ }
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-igmp:igmp
+ */
+int lib_interface_igmp_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_igmp_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_IF_DONT_IGMP(pim_ifp->options);
+
+ pim_if_membership_clear(ifp);
+
+ pim_if_addr_del_all_igmp(ifp);
+
+ if (!PIM_IF_TEST_PIM(pim_ifp->options))
+ pim_if_delete(ifp);
+ }
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-igmp:igmp/igmp-enable
+ */
+int lib_interface_igmp_igmp_enable_modify(struct nb_cb_modify_args *args)
+{
+ struct interface *ifp;
+ bool igmp_enable;
+ struct pim_interface *pim_ifp;
+ 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");
+ ifp_name = yang_dnode_get_string(if_dnode, ".");
+ 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. Could not enable IGMP on interface %s",
+ MAXVIFS, 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);
+ igmp_enable = yang_dnode_get_bool(args->dnode, NULL);
+
+ if (igmp_enable)
+ return pim_cmd_igmp_start(ifp);
+
+ else {
+ pim_ifp = ifp->info;
+
+ if (!pim_ifp)
+ return NB_ERR_INCONSISTENCY;
+
+ PIM_IF_DONT_IGMP(pim_ifp->options);
+
+ pim_if_membership_clear(ifp);
+
+ pim_if_addr_del_all_igmp(ifp);
+
+ if (!PIM_IF_TEST_PIM(pim_ifp->options))
+ pim_if_delete(ifp);
+ }
+ }
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-igmp:igmp/version
+ */
+int lib_interface_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_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-igmp:igmp/query-interval
+ */
+int lib_interface_igmp_query_interval_modify(struct nb_cb_modify_args *args)
+{
+ struct interface *ifp;
+ struct pim_interface *pim_ifp;
+ int query_interval;
+ int query_interval_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);
+ pim_ifp = ifp->info;
+ query_interval = yang_dnode_get_uint16(args->dnode, NULL);
+ query_interval_dsec = 10 * query_interval;
+ if (query_interval_dsec <=
+ pim_ifp->igmp_query_max_response_time_dsec) {
+ snprintf(args->errmsg, args->errmsg_len,
+ "Can't set general query interval %d dsec <= query max response time %d dsec.",
+ query_interval_dsec,
+ pim_ifp->igmp_query_max_response_time_dsec);
+ return NB_ERR_INCONSISTENCY;
+ }
+ change_query_interval(pim_ifp, query_interval);
+ }
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-igmp:igmp/query-max-response-time
+ */
+int lib_interface_igmp_query_max_response_time_modify(
+ struct nb_cb_modify_args *args)
+{
+ struct interface *ifp;
+ struct pim_interface *pim_ifp;
+ int query_max_response_time_dsec;
+ int default_query_interval_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);
+ pim_ifp = ifp->info;
+ query_max_response_time_dsec =
+ yang_dnode_get_uint8(args->dnode, NULL);
+ default_query_interval_dsec =
+ 10 * pim_ifp->igmp_default_query_interval;
+
+ if (query_max_response_time_dsec
+ >= default_query_interval_dsec) {
+ snprintf(args->errmsg, args->errmsg_len,
+ "Can't set query max response time %d sec >= general query interval %d sec",
+ query_max_response_time_dsec,
+ pim_ifp->igmp_default_query_interval);
+ return NB_ERR_INCONSISTENCY;
+ }
+
+ change_query_max_response_time(pim_ifp,
+ query_max_response_time_dsec);
+ }
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-igmp:igmp/last-member-query-interval
+ */
+int lib_interface_igmp_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_uint8(args->dnode,
+ NULL);
+ pim_ifp->igmp_specific_query_max_response_time_dsec =
+ last_member_query_interval;
+
+ break;
+ }
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-igmp:igmp/robustness-variable
+ */
+int lib_interface_igmp_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->igmp_last_member_query_count = last_member_query_count;
+
+ break;
+ }
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-interface:lib/interface/frr-igmp:igmp/address-family
+ */
+int lib_interface_igmp_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_igmp_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-interface:lib/interface/frr-igmp:igmp/address-family/static-group
+ */
+int lib_interface_igmp_address_family_static_group_create(
+ struct nb_cb_create_args *args)
+{
+ struct interface *ifp;
+ struct ipaddr source_addr;
+ struct ipaddr 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, ".");
+ snprintf(args->errmsg, args->errmsg_len,
+ "multicast not enabled on interface %s",
+ 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);
+ yang_dnode_get_ip(&source_addr, args->dnode, "./source-addr");
+ yang_dnode_get_ip(&group_addr, args->dnode, "./group-addr");
+
+ result = pim_if_igmp_join_add(ifp, group_addr.ip._v4_addr,
+ source_addr.ip._v4_addr);
+ if (result) {
+ snprintf(args->errmsg, args->errmsg_len,
+ "Failure joining IGMP group");
+ return NB_ERR_INCONSISTENCY;
+ }
+ }
+
+ return NB_OK;
+}
+
+int lib_interface_igmp_address_family_static_group_destroy(
+ struct nb_cb_destroy_args *args)
+{
+ struct interface *ifp;
+ struct ipaddr source_addr;
+ struct ipaddr 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_ip(&source_addr, args->dnode, "./source-addr");
+ yang_dnode_get_ip(&group_addr, args->dnode, "./group-addr");
+
+ result = pim_if_igmp_join_del(ifp, group_addr.ip._v4_addr,
+ source_addr.ip._v4_addr);
+
+ if (result) {
+ char src_str[INET_ADDRSTRLEN];
+ char grp_str[INET_ADDRSTRLEN];
+
+ ipaddr2str(&source_addr, src_str, sizeof(src_str));
+ ipaddr2str(&group_addr, grp_str, sizeof(grp_str));
+
+ snprintf(args->errmsg, args->errmsg_len,
+ "%% Failure leaving IGMP group %s %s on interface %s: %d",
+ src_str, grp_str, ifp->name, result);
+
+ return NB_ERR_INCONSISTENCY;
+ }
+
+ break;
+ }
+
+ return NB_OK;
+}
diff --git a/pimd/pim_rp.c b/pimd/pim_rp.c
index 7246482f0..727daa42c 100644
--- a/pimd/pim_rp.c
+++ b/pimd/pim_rp.c
@@ -394,39 +394,6 @@ void pim_upstream_update(struct pim_instance *pim, struct pim_upstream *up)
pim_zebra_update_all_interfaces(pim);
}
-int pim_rp_new_config(struct pim_instance *pim, const char *rp,
- const char *group_range, const char *plist)
-{
- int result = 0;
- struct prefix group;
- struct in_addr rp_addr;
-
- if (group_range == NULL)
- result = str2prefix("224.0.0.0/4", &group);
- else {
- result = str2prefix(group_range, &group);
- if (result) {
- struct prefix temp;
-
- prefix_copy(&temp, &group);
- apply_mask(&temp);
- if (!prefix_same(&group, &temp))
- return PIM_GROUP_BAD_ADDR_MASK_COMBO;
- }
- }
-
- if (!result)
- return PIM_GROUP_BAD_ADDRESS;
-
- result = inet_pton(AF_INET, rp, &rp_addr);
-
- if (result <= 0)
- return PIM_RP_BAD_ADDRESS;
-
- result = pim_rp_new(pim, rp_addr, group, plist, RP_SRC_STATIC);
- return result;
-}
-
int pim_rp_new(struct pim_instance *pim, struct in_addr rp_addr,
struct prefix group, const char *plist,
enum rp_source rp_src_flag)
diff --git a/pimd/pim_rp.h b/pimd/pim_rp.h
index 6dc26c07a..8a12cb076 100644
--- a/pimd/pim_rp.h
+++ b/pimd/pim_rp.h
@@ -46,8 +46,6 @@ void pim_rp_free(struct pim_instance *pim);
void pim_rp_list_hash_clean(void *data);
-int pim_rp_new_config(struct pim_instance *pim, const char *rp,
- const char *group, const char *plist);
int pim_rp_new(struct pim_instance *pim, struct in_addr rp_addr,
struct prefix group, const char *plist,
enum rp_source rp_src_flag);
diff --git a/pimd/subdir.am b/pimd/subdir.am
index 8952d15aa..ad5463caf 100644
--- a/pimd/subdir.am
+++ b/pimd/subdir.am
@@ -41,6 +41,8 @@ pimd_libpim_a_SOURCES = \
pimd/pim_msdp_packet.c \
pimd/pim_msdp_socket.c \
pimd/pim_msg.c \
+ pimd/pim_nb.c \
+ pimd/pim_nb_config.c \
pimd/pim_neighbor.c \
pimd/pim_nht.c \
pimd/pim_oil.c \
@@ -66,6 +68,9 @@ pimd_libpim_a_SOURCES = \
pimd/pim_vxlan.c \
pimd/pim_zpthread.c \
pimd/pimd.c \
+ yang/frr-pim.yang.c \
+ yang/frr-pim-rp.yang.c \
+ yang/frr-igmp.yang.c \
# end
noinst_HEADERS += \
@@ -96,6 +101,7 @@ noinst_HEADERS += \
pimd/pim_msdp_packet.h \
pimd/pim_msdp_socket.h \
pimd/pim_msg.h \
+ pimd/pim_nb.h \
pimd/pim_neighbor.h \
pimd/pim_nht.h \
pimd/pim_oil.h \
@@ -145,3 +151,9 @@ pimd_mtracebis_SOURCES = pimd/mtracebis.c \
pimd/mtracebis_netlink.c \
pimd/mtracebis_routeget.c \
# end
+
+nodist_pimd_pimd_SOURCES = \
+ yang/frr-pim.yang.c \
+ yang/frr-pim-rp.yang.c \
+ yang/frr-igmp.yang.c \
+ # end
diff --git a/sharpd/sharp_main.c b/sharpd/sharp_main.c
index 4cd92c7f3..fe7f9851f 100644
--- a/sharpd/sharp_main.c
+++ b/sharpd/sharp_main.c
@@ -139,6 +139,16 @@ static void sharp_global_init(void)
sg.nhs = list_new();
}
+static void sharp_start_configuration(void)
+{
+ zlog_debug("Configuration has started to be read");
+}
+
+static void sharp_end_configuration(void)
+{
+ zlog_debug("Configuration has finished being read");
+}
+
int main(int argc, char **argv, char **envp)
{
frr_preinit(&sharpd_di, argc, argv);
@@ -163,6 +173,8 @@ int main(int argc, char **argv, char **envp)
master = frr_init();
+ cmd_init_config_callbacks(sharp_start_configuration,
+ sharp_end_configuration);
sharp_global_init();
sharp_nhgroup_init();
diff --git a/vtysh/vtysh_config.c b/vtysh/vtysh_config.c
index 4b6c648d2..7dcf01988 100644
--- a/vtysh/vtysh_config.c
+++ b/vtysh/vtysh_config.c
@@ -526,9 +526,13 @@ static int vtysh_read_file(FILE *confp)
vtysh_execute_no_pager("enable");
vtysh_execute_no_pager("configure terminal");
+ vtysh_execute_no_pager("start_configuration");
+
/* Execute configuration file. */
ret = vtysh_config_from_file(vty, confp);
+ vtysh_execute_no_pager("end_configuration");
+
vtysh_execute_no_pager("end");
vtysh_execute_no_pager("disable");
diff --git a/yang/frr-igmp.yang b/yang/frr-igmp.yang
index b63d0f97e..e2971dc5c 100644
--- a/yang/frr-igmp.yang
+++ b/yang/frr-igmp.yang
@@ -71,14 +71,13 @@ module frr-igmp {
type boolean;
default "false";
description
- "Enable IGMP protocol on the interface.";
+ "Enable IGMP flag on the interface.";
}
leaf version {
type uint8 {
range "2..3";
}
- default "3";
description
"IGMP version.";
}
@@ -156,8 +155,8 @@ module frr-igmp {
*/
augment "/frr-interface:lib/frr-interface:interface" {
container igmp {
- description
- "IGMP interface parameters.";
+ presence
+ "Configure IGMP on an interface.";
uses interface-config-attributes;
list address-family {
key "address-family";
diff --git a/yang/frr-pim.yang b/yang/frr-pim.yang
index 2135d22f6..f959ff8be 100644
--- a/yang/frr-pim.yang
+++ b/yang/frr-pim.yang
@@ -82,26 +82,19 @@ module frr-pim {
"A grouping defining pim global attributes.";
leaf ecmp {
- type empty;
+ type boolean;
+ default "false";
description
"Enable PIM ECMP.";
}
leaf ecmp-rebalance {
- type empty;
+ type boolean;
+ default "false";
description
"Enable PIM ECMP Rebalance.";
}
- leaf join-prune-interval {
- type uint16 {
- range "60..600";
- }
- default "60";
- description
- "Join Prune Send Interval in seconds.";
- }
-
leaf keep-alive-timer {
type uint16 {
range "31..60000";
@@ -119,26 +112,7 @@ module frr-pim {
description
"RP keep alive Timer in seconds.";
}
-
- leaf packets {
- type uint8 {
- range "1..100";
- }
- default "3";
- description
- "Number of packets to process at one time per fd.";
- }
-
- leaf register-suppress-time {
- type uint16 {
- range "5..60000";
- }
- default "60";
- description
- "Register Suppress Timer.";
- }
}
-
grouping per-af-global-pim-config-attributes {
description
"A grouping defining per address family pim global attributes";
@@ -148,7 +122,8 @@ module frr-pim {
description
"Only applicable to IPv4 address family.";
}
- type empty;
+ type boolean;
+ default "true";
description
"Send v6 secondary addresses.";
}
@@ -241,7 +216,7 @@ module frr-pim {
}
container mlag {
- description
+ presence
"Multi-chassis link aggregation.";
leaf peerlink-rif {
@@ -300,22 +275,14 @@ module frr-pim {
"A grouping defining pim interface attributes.";
leaf pim-enable {
- type empty;
+ type boolean;
+ default "false";
description
"Enable PIM flag on the interface.";
}
- leaf dr-priority {
- type uint32 {
- range "1..4294967295";
- }
- default 1;
- description
- "DR (Designated Router) priority";
- }
-
leaf hello-interval {
- type uint16 {
+ type uint8 {
range "1..180";
}
default "30";
@@ -324,7 +291,7 @@ module frr-pim {
}
leaf hello-holdtime {
- type uint16 {
+ type uint8 {
range "1..180";
}
description
@@ -364,22 +331,34 @@ module frr-pim {
}
leaf bsm {
- type empty;
+ type boolean;
+ default "false";
description
"Enables BSM support on the interface.";
}
leaf unicast-bsm {
- type empty;
+ type boolean;
+ default "false";
description
"Accept/Send unicast BSM on the interface.";
}
leaf active-active {
- type empty;
+ type boolean;
+ default "false";
description
"Mark interface as Active-Active for MLAG operations.";
}
+
+ leaf dr-priority {
+ type uint32 {
+ range "1..4294967295";
+ }
+ default 1;
+ description
+ "DR (Designated Router) priority";
+ }
} // interface-pim-config-attributes
grouping per-af-interface-pim-config-attributes {
@@ -455,8 +434,8 @@ module frr-pim {
*/
augment "/frr-interface:lib/frr-interface:interface" {
container pim {
- description
- "PIM interface parameters.";
+ presence
+ "Configure PIM on an interface.";
uses interface-pim-config-attributes;
list address-family {
key "address-family";
@@ -467,5 +446,33 @@ module frr-pim {
}
}
}
-}
+ container pim {
+ description
+ "PIM router parameters.";
+ leaf packets {
+ type uint8 {
+ range "1..100";
+ }
+ default "3";
+ description
+ "Number of packets to process at one time per fd.";
+ }
+ leaf join-prune-interval {
+ type uint16 {
+ range "60..600";
+ }
+ default "60";
+ description
+ "Join Prune Send Interval in seconds.";
+ }
+ leaf register-suppress-time {
+ type uint16 {
+ range "5..60000";
+ }
+ default "60";
+ description
+ "Register Suppress Timer.";
+ }
+ }
+}