Skip to content

Commit

Permalink
interfaces-plugin: switch startup DS loading to running DS loading
Browse files Browse the repository at this point in the history
  • Loading branch information
zinccyy committed Dec 13, 2022
1 parent 8fc31b0 commit 7b92de7
Show file tree
Hide file tree
Showing 7 changed files with 244 additions and 11 deletions.
4 changes: 4 additions & 0 deletions src/interfaces/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ set(
src/plugin/startup/load.c
src/plugin/startup/store.c

# running
src/plugin/running/load.c
src/plugin/running/store.c

# subscription
src/plugin/subscription/change.c
src/plugin/subscription/operational.c
Expand Down
24 changes: 14 additions & 10 deletions src/interfaces/src/plugin.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,16 @@
#include "netlink/socket.h"
#include "plugin/common.h"
#include "plugin/context.h"

// startup
#include "plugin/data/interfaces/interface_state.h"

// startup DS
#include "plugin/startup/load.h"
#include "plugin/startup/store.h"

// running DS
#include "plugin/running/load.h"
#include "plugin/running/store.h"

// subscription
#include "plugin/subscription/change.h"
#include "plugin/subscription/operational.h"
Expand Down Expand Up @@ -284,21 +288,21 @@ int sr_plugin_init_cb(sr_session_ctx_t* running_session, void** private_data)

ctx->startup_ctx.startup_session = startup_session;

SRPC_SAFE_CALL_ERR(error, srpc_check_empty_datastore(startup_session, INTERFACES_INTERFACES_INTERFACE_YANG_PATH, &empty_startup), error_out);
SRPC_SAFE_CALL_ERR(error, srpc_check_empty_datastore(running_session, INTERFACES_INTERFACES_INTERFACE_YANG_PATH, &empty_startup), error_out);

if (empty_startup) {
SRPLG_LOG_INF(PLUGIN_NAME, "Startup datastore is empty");
SRPLG_LOG_INF(PLUGIN_NAME, "Running datastore is empty");
SRPLG_LOG_INF(PLUGIN_NAME, "Loading initial system data");

// load initial data on the system
SRPC_SAFE_CALL_ERR(error, interfaces_startup_load(ctx, running_session), error_out);
// load initial running DS data on the system
SRPC_SAFE_CALL_ERR(error, interfaces_running_load(ctx, running_session), error_out);
} else {
// make sure the data from startup DS is stored in the interfaces
SRPLG_LOG_INF(PLUGIN_NAME, "Startup datastore contains data");
SRPLG_LOG_INF(PLUGIN_NAME, "Storing startup datastore data in the system");
SRPLG_LOG_INF(PLUGIN_NAME, "Running datastore contains data");
SRPLG_LOG_INF(PLUGIN_NAME, "Checking running datastore against system data");

// check and store startup data on the system
SRPC_SAFE_CALL_ERR(error, interfaces_startup_store(ctx, startup_session), error_out);
// check and store running DS data on the system
SRPC_SAFE_CALL_ERR(error, interfaces_running_store(ctx, running_session), error_out);
}

// subscribe every module change
Expand Down
4 changes: 3 additions & 1 deletion src/interfaces/src/plugin/data/interfaces/interface.c
Original file line number Diff line number Diff line change
Expand Up @@ -611,7 +611,7 @@ int interfaces_interface_type_nl2ly(const char* nl_type, const char** ly_type)

if (nl_type == NULL) {
// fix for now - investigate more - lo interface has type == NULL
*ly_type = "iana-if-type:softwareLoopback";
*ly_type = "iana-if-type:other";
return 0;
}

Expand All @@ -623,6 +623,8 @@ int interfaces_interface_type_nl2ly(const char* nl_type, const char** ly_type)
*ly_type = "iana-if-type:l2vlan";
} else if (strcmp(nl_type, "dummy") == 0) {
*ly_type = "iana-if-type:other";
} else if (strcmp(nl_type, "bridge") == 0) {
*ly_type = "iana-if-type:bridge";
} else {
error = -2;
}
Expand Down
104 changes: 104 additions & 0 deletions src/interfaces/src/plugin/running/load.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
#include "load.h"
#include "libyang/printer_data.h"
#include "plugin/common.h"
#include "plugin/data/interfaces/interface.h"
#include "plugin/ly_tree.h"

#include "plugin/api/interfaces/load.h"
#include "plugin/types.h"
#include "src/uthash.h"
#include "src/utlist.h"
#include "srpc/common.h"

#include <libyang/libyang.h>
#include <srpc.h>
#include <sysrepo.h>

static int interfaces_running_load_interface(void* priv, sr_session_ctx_t* session, const struct ly_ctx* ly_ctx, struct lyd_node* parent_node);

int interfaces_running_load(interfaces_ctx_t* ctx, sr_session_ctx_t* session)
{
int error = 0;

const struct ly_ctx* ly_ctx = NULL;
struct lyd_node* root_node = NULL;
sr_conn_ctx_t* conn_ctx = NULL;

srpc_startup_load_t load_values[] = {
{
"/ietf-interfaces:interfaces/interface",
interfaces_running_load_interface,
},
};

SRPC_SAFE_CALL_PTR(conn_ctx, sr_session_get_connection(session), error_out);
SRPC_SAFE_CALL_PTR(ly_ctx, sr_acquire_context(conn_ctx), error_out);

SRPC_SAFE_CALL_ERR(error, interfaces_ly_tree_create_interfaces(ly_ctx, &root_node), error_out);

for (size_t i = 0; i < ARRAY_SIZE(load_values); i++) {
const srpc_startup_load_t* load = &load_values[i];

error = load->cb((void*)ctx, session, ly_ctx, root_node);
if (error) {
SRPLG_LOG_ERR(PLUGIN_NAME, "Node creation callback failed for value %s", load->name);
goto error_out;
}
}

/* enable or disable storing into startup, use for testing */
#define INTERFACES_PLUGIN_LOAD_STARTUP
/* disable for now */
// #undef INTERFACES_PLUGIN_LOAD_STARTUP
#ifdef INTERFACES_PLUGIN_LOAD_STARTUP
error = sr_edit_batch(session, root_node, "merge");
if (error != SR_ERR_OK) {
SRPLG_LOG_ERR(PLUGIN_NAME, "sr_edit_batch() error (%d): %s", error, sr_strerror(error));
goto error_out;
}

error = sr_apply_changes(session, 0);
if (error != 0) {
SRPLG_LOG_ERR(PLUGIN_NAME, "sr_apply_changes() error (%d): %s", error, sr_strerror(error));
goto error_out;
}
#endif

goto out;

error_out:
error = -1;

out:
if (root_node) {
lyd_free_tree(root_node);
}
sr_release_context(conn_ctx);

return error;
}

static int interfaces_running_load_interface(void* priv, sr_session_ctx_t* session, const struct ly_ctx* ly_ctx, struct lyd_node* parent_node)
{
int error = 0;
interfaces_ctx_t* ctx = (interfaces_ctx_t*)priv;
interfaces_interface_hash_element_t* interface_hash = NULL;

// load interfaces data
SRPC_SAFE_CALL_ERR(error, interfaces_load_interface(ctx, &interface_hash), error_out);

// convert to libyang
SRPC_SAFE_CALL_ERR(error, interfaces_interface_hash_to_ly(ly_ctx, interface_hash, &parent_node), error_out);

// print created tree
// lyd_print_file(stdout, parent_node, LYD_XML, 0);

goto out;

error_out:
error = -1;
out:
interfaces_interface_hash_free(&interface_hash);

return error;
}
8 changes: 8 additions & 0 deletions src/interfaces/src/plugin/running/load.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#ifndef INTERFACES_PLUGIN_RUNNING_LOAD_H
#define INTERFACES_PLUGIN_RUNNING_LOAD_H

#include "plugin/context.h"

int interfaces_running_load(interfaces_ctx_t* ctx, sr_session_ctx_t* session);

#endif // INTERFACES_PLUGIN_RUNNING_LOAD_H
103 changes: 103 additions & 0 deletions src/interfaces/src/plugin/running/store.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
#include "store.h"
#include "plugin/common.h"

#include "plugin/api/interfaces/check.h"
#include "plugin/api/interfaces/store.h"
#include "plugin/data/interfaces/interface.h"
#include "srpc/ly_tree.h"

#include <libyang/libyang.h>
#include <srpc.h>
#include <sysrepo.h>

static int interfaces_running_store_interface(void* priv, const struct lyd_node* parent_container);

int interfaces_running_store(interfaces_ctx_t* ctx, sr_session_ctx_t* session)
{
int error = 0;
sr_data_t* subtree = NULL;

SRPC_SAFE_CALL_ERR(error, sr_get_subtree(session, INTERFACES_INTERFACES_CONTAINER_YANG_PATH, 0, &subtree), error_out);

srpc_startup_store_t store_values[] = {
{
"/ietf-interfaces:interfaces/interface[name='%s']",
interfaces_running_store_interface,
},
};

for (size_t i = 0; i < ARRAY_SIZE(store_values); i++) {
const srpc_startup_store_t* store = &store_values[i];

error = store->cb(ctx, subtree->tree);
if (error != 0) {
SRPLG_LOG_ERR(PLUGIN_NAME, "Startup store callback failed for value %s", store->name);
goto error_out;
}
}

goto out;

error_out:
error = -1;

out:
if (subtree) {
sr_release_data(subtree);
}

return error;
}

static int interfaces_running_store_interface(void* priv, const struct lyd_node* parent_container)
{
int error = 0;
interfaces_ctx_t* ctx = (interfaces_ctx_t*)priv;
srpc_check_status_t check_status = srpc_check_status_none;
interfaces_interface_hash_element_t* if_hash = NULL;
struct lyd_node* interface_node = NULL;

interface_node = srpc_ly_tree_get_child_list(parent_container, "interface");
if (interface_node == NULL) {
SRPLG_LOG_ERR(PLUGIN_NAME, "srpc_ly_tree_get_child_leaf returned NULL for 'interfaces'");
goto error_out;
}

// map libyang data to the interface hash
SRPC_SAFE_CALL_ERR(error, interfaces_interface_hash_from_ly(&if_hash, interface_node), error_out);

// check startup data
SRPLG_LOG_INF(PLUGIN_NAME, "Checking interface list data");
check_status = interfaces_check_interface(ctx, if_hash);

switch (check_status) {
case srpc_check_status_none:
SRPLG_LOG_ERR(PLUGIN_NAME, "Error loading current interface list");
goto error_out;
case srpc_check_status_error:
SRPLG_LOG_ERR(PLUGIN_NAME, "Error loading current interface list");
goto error_out;
case srpc_check_status_non_existant:
SRPLG_LOG_INF(PLUGIN_NAME, "Storing interface list");
SRPC_SAFE_CALL_ERR(error, interfaces_store_interface(ctx, if_hash), error_out);
break;
case srpc_check_status_equal:
SRPLG_LOG_ERR(PLUGIN_NAME, "Startup interface list is already applied on the system");
break;
case srpc_check_status_partial:
SRPLG_LOG_ERR(PLUGIN_NAME, "Error loading current interface list");
goto error_out;
}

goto out;

error_out:
error = -1;

out:
if (if_hash) {
interfaces_interface_hash_free(&if_hash);
}

return error;
}
8 changes: 8 additions & 0 deletions src/interfaces/src/plugin/running/store.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#ifndef INTERFACES_PLUGIN_RUNNING_STORE_H
#define INTERFACES_PLUGIN_RUNNING_STORE_H

#include "plugin/context.h"

int interfaces_running_store(interfaces_ctx_t* ctx, sr_session_ctx_t* session);

#endif // INTERFACES_PLUGIN_RUNNING_STORE_H

0 comments on commit 7b92de7

Please sign in to comment.