summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/northbound.c60
-rw-r--r--lib/northbound.h13
-rw-r--r--lib/prefix.c4
-rw-r--r--lib/prefix.h2
-rw-r--r--lib/routing_nb.h7
-rw-r--r--lib/routing_nb_config.c61
-rw-r--r--lib/vrf.c7
-rw-r--r--lib/vrf.h3
-rw-r--r--lib/vty.c6
9 files changed, 138 insertions, 25 deletions
diff --git a/lib/northbound.c b/lib/northbound.c
index ecfa2c9d11..224951b22b 100644
--- a/lib/northbound.c
+++ b/lib/northbound.c
@@ -185,6 +185,25 @@ struct nb_node *nb_node_find(const char *xpath)
return snode->priv;
}
+void nb_node_set_dependency_cbs(const char *dependency_xpath,
+ const char *dependant_xpath,
+ struct nb_dependency_callbacks *cbs)
+{
+ struct nb_node *dependency = nb_node_find(dependency_xpath);
+ struct nb_node *dependant = nb_node_find(dependant_xpath);
+
+ if (!dependency || !dependant)
+ return;
+
+ dependency->dep_cbs.get_dependant_xpath = cbs->get_dependant_xpath;
+ dependant->dep_cbs.get_dependency_xpath = cbs->get_dependency_xpath;
+}
+
+bool nb_node_has_dependency(struct nb_node *node)
+{
+ return node->dep_cbs.get_dependency_xpath != NULL;
+}
+
static int nb_node_validate_cb(const struct nb_node *nb_node,
enum nb_operation operation,
int callback_implemented, bool optional)
@@ -532,8 +551,9 @@ int nb_candidate_edit(struct nb_config *candidate,
const struct yang_data *previous,
const struct yang_data *data)
{
- struct lyd_node *dnode;
+ struct lyd_node *dnode, *dep_dnode;
char xpath_edit[XPATH_MAXLEN];
+ char dep_xpath[XPATH_MAXLEN];
/* Use special notation for leaf-lists (RFC 6020, section 9.13.5). */
if (nb_node->snode->nodetype == LYS_LEAFLIST)
@@ -549,9 +569,33 @@ int nb_candidate_edit(struct nb_config *candidate,
dnode = lyd_new_path(candidate->dnode, ly_native_ctx,
xpath_edit, (void *)data->value, 0,
LYD_PATH_OPT_UPDATE);
- if (!dnode && ly_errno) {
- flog_warn(EC_LIB_LIBYANG, "%s: lyd_new_path() failed",
- __func__);
+ if (dnode) {
+ /*
+ * create dependency
+ *
+ * dnode returned by the lyd_new_path may be from a
+ * different schema, so we need to update the nb_node
+ */
+ nb_node = dnode->schema->priv;
+ if (nb_node->dep_cbs.get_dependency_xpath) {
+ nb_node->dep_cbs.get_dependency_xpath(
+ dnode, dep_xpath);
+
+ ly_errno = 0;
+ dep_dnode = lyd_new_path(candidate->dnode,
+ ly_native_ctx,
+ dep_xpath, NULL, 0,
+ LYD_PATH_OPT_UPDATE);
+ if (!dep_dnode && ly_errno) {
+ flog_warn(EC_LIB_LIBYANG,
+ "%s: lyd_new_path(%s) failed",
+ __func__, dep_xpath);
+ return NB_ERR;
+ }
+ }
+ } else if (ly_errno) {
+ flog_warn(EC_LIB_LIBYANG, "%s: lyd_new_path(%s) failed",
+ __func__, xpath_edit);
return NB_ERR;
}
break;
@@ -563,6 +607,14 @@ int nb_candidate_edit(struct nb_config *candidate,
* whether to ignore it or not.
*/
return NB_ERR_NOT_FOUND;
+ /* destroy dependant */
+ if (nb_node->dep_cbs.get_dependant_xpath) {
+ nb_node->dep_cbs.get_dependant_xpath(dnode, dep_xpath);
+
+ dep_dnode = yang_dnode_get(candidate->dnode, dep_xpath);
+ if (dep_dnode)
+ lyd_free(dep_dnode);
+ }
lyd_free(dnode);
break;
case NB_OP_MOVE:
diff --git a/lib/northbound.h b/lib/northbound.h
index 8dd6b4c337..3e1342f985 100644
--- a/lib/northbound.h
+++ b/lib/northbound.h
@@ -509,6 +509,11 @@ struct nb_callbacks {
void (*cli_show_end)(struct vty *vty, struct lyd_node *dnode);
};
+struct nb_dependency_callbacks {
+ void (*get_dependant_xpath)(const struct lyd_node *dnode, char *xpath);
+ void (*get_dependency_xpath)(const struct lyd_node *dnode, char *xpath);
+};
+
/*
* Northbound-specific data that is allocated for each schema node of the native
* YANG modules.
@@ -523,6 +528,8 @@ struct nb_node {
/* Priority - lower priorities are processed first. */
uint32_t priority;
+ struct nb_dependency_callbacks dep_cbs;
+
/* Callbacks implemented for this node. */
struct nb_callbacks cbs;
@@ -722,6 +729,12 @@ void nb_nodes_delete(void);
*/
extern struct nb_node *nb_node_find(const char *xpath);
+extern void nb_node_set_dependency_cbs(const char *dependency_xpath,
+ const char *dependant_xpath,
+ struct nb_dependency_callbacks *cbs);
+
+bool nb_node_has_dependency(struct nb_node *node);
+
/*
* Create a new northbound configuration.
*
diff --git a/lib/prefix.c b/lib/prefix.c
index 663a87afde..c98e0c1c72 100644
--- a/lib/prefix.c
+++ b/lib/prefix.c
@@ -1160,7 +1160,7 @@ in_addr_t ipv4_broadcast_addr(in_addr_t hostaddr, int masklen)
ex.) "1.1.0.0" "255.255.0.0" => "1.1.0.0/16"
ex.) "1.0.0.0" NULL => "1.0.0.0/8" */
int netmask_str2prefix_str(const char *net_str, const char *mask_str,
- char *prefix_str)
+ char *prefix_str, size_t prefix_str_len)
{
struct in_addr network;
struct in_addr mask;
@@ -1193,7 +1193,7 @@ int netmask_str2prefix_str(const char *net_str, const char *mask_str,
return 0;
}
- sprintf(prefix_str, "%s/%d", net_str, prefixlen);
+ snprintf(prefix_str, prefix_str_len, "%s/%d", net_str, prefixlen);
return 1;
}
diff --git a/lib/prefix.h b/lib/prefix.h
index b7fdc26369..b2f3b0592f 100644
--- a/lib/prefix.h
+++ b/lib/prefix.h
@@ -491,7 +491,7 @@ extern void masklen2ip(const int, struct in_addr *);
* special treatment for /31 according to RFC3021 section 3.3 */
extern in_addr_t ipv4_broadcast_addr(in_addr_t hostaddr, int masklen);
-extern int netmask_str2prefix_str(const char *, const char *, char *);
+extern int netmask_str2prefix_str(const char *, const char *, char *, size_t);
extern struct prefix_ipv6 *prefix_ipv6_new(void);
extern void prefix_ipv6_free(struct prefix_ipv6 **p);
diff --git a/lib/routing_nb.h b/lib/routing_nb.h
index d1b59ea29e..ffba631a10 100644
--- a/lib/routing_nb.h
+++ b/lib/routing_nb.h
@@ -15,10 +15,17 @@ int routing_control_plane_protocols_control_plane_protocol_destroy(
#define FRR_ROUTING_KEY_XPATH \
"/frr-routing:routing/control-plane-protocols/" \
"control-plane-protocol[type='%s'][name='%s'][vrf='%s']"
+
+#define FRR_ROUTING_KEY_XPATH_VRF \
+ "/frr-routing:routing/control-plane-protocols/" \
+ "control-plane-protocol[vrf='%s']"
+
/*
* callbacks for routing to handle configuration events
* based on the control plane protocol
*/
DECLARE_HOOK(routing_conf_event, (struct nb_cb_create_args *args), (args))
+void routing_control_plane_protocols_register_vrf_dependency(void);
+
#endif /* _FRR_ROUTING_NB_H_ */
diff --git a/lib/routing_nb_config.c b/lib/routing_nb_config.c
index b789e8494e..17698d2b87 100644
--- a/lib/routing_nb_config.c
+++ b/lib/routing_nb_config.c
@@ -45,15 +45,21 @@ int routing_control_plane_protocols_control_plane_protocol_create(
case NB_EV_ABORT:
break;
case NB_EV_APPLY:
- vrfname = yang_dnode_get_string(args->dnode, "./vrf");
- vrf = vrf_lookup_by_name(vrfname);
- vrf = vrf ? vrf : vrf_get(VRF_UNKNOWN, vrfname);
- if (!vrf) {
- flog_warn(EC_LIB_NB_CB_CONFIG_APPLY,
- "vrf creation %s failed", vrfname);
- return NB_ERR;
+ /*
+ * If the daemon relies on the VRF pointer stored in this
+ * dnode, then it should register the dependency between this
+ * module and the VRF module using
+ * routing_control_plane_protocols_register_vrf_dependency.
+ * If such dependency is not registered, then nothing is
+ * stored in the dnode. If the dependency is registered,
+ * find the vrf and store the pointer.
+ */
+ if (nb_node_has_dependency(args->dnode->schema->priv)) {
+ vrfname = yang_dnode_get_string(args->dnode, "./vrf");
+ vrf = vrf_lookup_by_name(vrfname);
+ assert(vrf);
+ nb_running_set_entry(args->dnode, vrf);
}
- nb_running_set_entry(args->dnode, vrf);
break;
};
@@ -63,12 +69,45 @@ int routing_control_plane_protocols_control_plane_protocol_create(
int routing_control_plane_protocols_control_plane_protocol_destroy(
struct nb_cb_destroy_args *args)
{
- struct vrf *vrf __attribute__((unused));
-
if (args->event != NB_EV_APPLY)
return NB_OK;
- vrf = nb_running_unset_entry(args->dnode);
+ /*
+ * If dependency on VRF module is registered, then VRF
+ * pointer was stored and must be cleared.
+ */
+ if (nb_node_has_dependency(args->dnode->schema->priv))
+ nb_running_unset_entry(args->dnode);
return NB_OK;
}
+
+static void vrf_to_control_plane_protocol(const struct lyd_node *dnode,
+ char *xpath)
+{
+ const char *vrf;
+
+ vrf = yang_dnode_get_string(dnode, "./name");
+
+ snprintf(xpath, XPATH_MAXLEN, FRR_ROUTING_KEY_XPATH_VRF, vrf);
+}
+
+static void control_plane_protocol_to_vrf(const struct lyd_node *dnode,
+ char *xpath)
+{
+ const char *vrf;
+
+ vrf = yang_dnode_get_string(dnode, "./vrf");
+
+ snprintf(xpath, XPATH_MAXLEN, FRR_VRF_KEY_XPATH, vrf);
+}
+
+void routing_control_plane_protocols_register_vrf_dependency(void)
+{
+ struct nb_dependency_callbacks cbs;
+
+ cbs.get_dependant_xpath = vrf_to_control_plane_protocol;
+ cbs.get_dependency_xpath = control_plane_protocol_to_vrf;
+
+ nb_node_set_dependency_cbs(FRR_VRF_XPATH, FRR_ROUTING_XPATH, &cbs);
+}
diff --git a/lib/vrf.c b/lib/vrf.c
index 136938783f..0a91f4bc86 100644
--- a/lib/vrf.c
+++ b/lib/vrf.c
@@ -686,8 +686,8 @@ int vrf_handler_create(struct vty *vty, const char *vrfname,
}
if (vty) {
- snprintf(xpath_list, sizeof(xpath_list),
- "/frr-vrf:lib/vrf[name='%s']", vrfname);
+ snprintf(xpath_list, sizeof(xpath_list), FRR_VRF_KEY_XPATH,
+ vrfname);
nb_cli_enqueue_change(vty, xpath_list, NB_OP_CREATE, NULL);
ret = nb_cli_apply_changes(vty, xpath_list);
@@ -821,8 +821,7 @@ DEFUN_YANG (no_vrf,
return CMD_WARNING_CONFIG_FAILED;
}
- snprintf(xpath_list, sizeof(xpath_list), "/frr-vrf:lib/vrf[name='%s']",
- vrfname);
+ snprintf(xpath_list, sizeof(xpath_list), FRR_VRF_KEY_XPATH, vrfname);
nb_cli_enqueue_change(vty, xpath_list, NB_OP_DESTROY, NULL);
return nb_cli_apply_changes(vty, xpath_list);
diff --git a/lib/vrf.h b/lib/vrf.h
index 32e6fb4289..333d68ce96 100644
--- a/lib/vrf.h
+++ b/lib/vrf.h
@@ -52,6 +52,9 @@ enum { IFLA_VRF_UNSPEC, IFLA_VRF_TABLE, __IFLA_VRF_MAX };
#define VRF_ALL_CMD_HELP_STR "Specify the VRF\nAll VRFs\n"
#define VRF_FULL_CMD_HELP_STR "Specify the VRF\nThe VRF name\nAll VRFs\n"
+#define FRR_VRF_XPATH "/frr-vrf:lib/vrf"
+#define FRR_VRF_KEY_XPATH "/frr-vrf:lib/vrf[name='%s']"
+
/*
* Pass some OS specific data up through
* to the daemons
diff --git a/lib/vty.c b/lib/vty.c
index 65f8d78a96..df518422f0 100644
--- a/lib/vty.c
+++ b/lib/vty.c
@@ -2427,9 +2427,9 @@ bool vty_read_config(struct nb_config *config, const char *config_file,
__func__, errno);
goto tmp_free_and_out;
}
- tmp = XMALLOC(MTYPE_TMP,
- strlen(cwd) + strlen(config_file) + 2);
- sprintf(tmp, "%s/%s", cwd, config_file);
+ size_t tmp_len = strlen(cwd) + strlen(config_file) + 2;
+ tmp = XMALLOC(MTYPE_TMP, tmp_len);
+ snprintf(tmp, tmp_len, "%s/%s", cwd, config_file);
fullpath = tmp;
} else
fullpath = config_file;