]> git.puffer.fish Git - matthieu/frr.git/commitdiff
lib: register dependency between control plane protocol and vrf nb nodes
authorIgor Ryzhov <iryzhov@nfware.com>
Tue, 16 Feb 2021 09:57:01 +0000 (12:57 +0300)
committerIgor Ryzhov <iryzhov@nfware.com>
Fri, 26 Feb 2021 11:42:57 +0000 (14:42 +0300)
When the control plane protocol is created, the vrf structure is
allocated, and its address is stored in the northbound node.
The vrf structure may later be deleted by the user, which will lead to
a stale pointer stored in this node.

Instead of this, allow daemons that use the vrf pointer to register the
dependency between the control plane protocol and vrf nodes. This will
guarantee that the nodes will always be created and deleted together, and
there won't be any stale pointers.

Add such registration to staticd.

Signed-off-by: Igor Ryzhov <iryzhov@nfware.com>
lib/routing_nb.h
lib/routing_nb_config.c
staticd/static_main.c

index d1b59ea29ee655ca38dd0ed5f0e4545fde480353..ffba631a10763fd197e5754f1d86b09fa69b3cc6 100644 (file)
@@ -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_ */
index b789e8494e1443e925a52fab8d8ce82ae06d9d85..17698d2b87984d358f762b80afa27e57884df1af 100644 (file)
@@ -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);
+}
index ac8f8ff02903ae4197063a388a17fef6702edded..560814771d8e239a7ca560800ab6bc408d6b35be 100644 (file)
@@ -164,6 +164,8 @@ int main(int argc, char **argv, char **envp)
        hook_register(routing_conf_event,
                      routing_control_plane_protocols_name_validate);
 
+       routing_control_plane_protocols_register_vrf_dependency();
+
        snprintf(backup_config_file, sizeof(backup_config_file),
                 "%s/zebra.conf", frr_sysconfdir);
        staticd_di.backup_config_file = backup_config_file;