From a59591c4ca428e5ee333aa868f41c9f303b2ac7f Mon Sep 17 00:00:00 2001 From: ali-aqrabawi Date: Fri, 28 Jun 2024 23:10:57 +0300 Subject: [PATCH] netns, cfg_load: loading config for each netns Signed-off-by: ali-aqrabawi --- src/iproute2_sysrepo.c | 23 ++++++++++++++++++++--- src/lib/cmdgen.h | 24 ++++++++++++++++-------- src/lib/oper_data.c | 36 +++++++++++++++++++++++++++++++----- src/lib/oper_data.h | 2 +- tests/cases/test_ip_netns.sh | 6 +++--- 5 files changed, 71 insertions(+), 20 deletions(-) diff --git a/src/iproute2_sysrepo.c b/src/iproute2_sysrepo.c index 18a701e..15c2205 100644 --- a/src/iproute2_sysrepo.c +++ b/src/iproute2_sysrepo.c @@ -662,17 +662,34 @@ int ipr2_oper_get_items_cb(sr_session_ctx_t *session, uint32_t sub_id, const cha const char *xpath, const char *request_xpath, uint32_t request_id, struct lyd_node **parent, void *private_data) { - return load_module_data(session, module_name, LYS_CONFIG_R | LYS_CONFIG_W, parent); + return load_module_data(session, module_name, LYS_CONFIG_R | LYS_CONFIG_W, parent, "1"); +} + +struct load_linux_runcfg_arg { + const char *module_name; + struct lyd_node **root_node; +}; + +int load_linux_runcfg_ns_cb(char *nsname, void *arg) +{ + struct load_linux_runcfg_arg *runcfg_arg = (struct load_linux_runcfg_arg *)arg; + load_module_data(sr_session, runcfg_arg->module_name, LYS_CONFIG_W, runcfg_arg->root_node, + nsname); + return 0; } int load_linux_running_config() { - int ret = 0; + int ret; struct lyd_node *root_node = NULL; fprintf(stdout, "%s: Started loading iproute2 running configuration.\n", __func__); for (size_t i = 0; i < sizeof(ipr2_ip_modules) / sizeof(ipr2_ip_modules[0]); i++) { fprintf(stdout, "%s: Loading module: %s data.\n", __func__, ipr2_ip_modules[i].module); - load_module_data(sr_session, ipr2_ip_modules[i].module, LYS_CONFIG_W, &root_node); + // load data from default netns + load_module_data(sr_session, ipr2_ip_modules[i].module, LYS_CONFIG_W, &root_node, "1"); + // load data from all netns + struct load_linux_runcfg_arg runcfg_arg = { ipr2_ip_modules[i].module, &root_node }; + netns_foreach(load_linux_runcfg_ns_cb, &runcfg_arg); } fprintf(stdout, "%s: Storing loaded data to sysrepo running datastore.\n", __func__); diff --git a/src/lib/cmdgen.h b/src/lib/cmdgen.h index ef679f8..62c0132 100644 --- a/src/lib/cmdgen.h +++ b/src/lib/cmdgen.h @@ -25,6 +25,22 @@ struct cmd_info { */ void free_cmds_info(struct cmd_info **cmds_info); +/** + * parse the command line and convert it to argc, argv + * @param [in] command command line string "ip link add ..." + * @param [out] argc parsed argv count + * @param [out] argv parsed argv + */ +void parse_command(const char *command, int *argc, char ***argv); + +/** + * this func insert the netns name in the cmd, for example if cmd = ip link, and netns = "red" + * the cmd will become "ip -n red link", + * @param cmd + * @param netns + */ +void insert_netns(char *cmd, const char *netns); + /** * @brief generate list of commands info from the lyd_node (diff). * @@ -34,12 +50,4 @@ void free_cmds_info(struct cmd_info **cmds_info); */ struct cmd_info **lyd2cmds(const struct lyd_node *all_change_nodes); -/** - * parse the command line and convert it to argc, argv - * @param [in] command command line string "ip link add ..." - * @param [out] argc parsed argv count - * @param [out] argv parsed argv - */ -void parse_command(const char *command, int *argc, char ***argv); - #endif // IPROUTE2_SYSREPO_CMDGEN_H diff --git a/src/lib/oper_data.c b/src/lib/oper_data.c index 97426ee..fbdce3c 100644 --- a/src/lib/oper_data.c +++ b/src/lib/oper_data.c @@ -18,6 +18,8 @@ #include "oper_data.h" #include "cmdgen.h" +char *net_namespace; + /* to be merged with cmdgen */ typedef enum { // leaf extensions @@ -394,7 +396,12 @@ int get_list_keys2(const struct lysc_node_list *list, json_object *json_array_ob free(value); } else { // key value not found in json data. - if (default_val != NULL) { + if (!strcmp(child->name, "netns")) { + json_object_object_add(keys_jobj, child->name, + json_object_new_string(net_namespace)); + if (default_val) + free(default_val); + } else if (default_val != NULL) { json_object_object_add(keys_jobj, child->name, json_object_new_string(default_val)); free(default_val); @@ -601,6 +608,13 @@ void jdata_to_leaf(struct json_object *json_obj, const char *arg_name, struct lyd_node **parent_data_node, const struct lysc_node *s_node) { char *vmap_str = NULL, *fmap_str = NULL, *combine_ext_str = NULL, *static_value = NULL; + if (!strcmp(s_node->name, "netns")) { + if (LY_SUCCESS != + lyd_new_term(*parent_data_node, NULL, s_node->name, net_namespace, 0, NULL)) { + fprintf(stderr, "%s: node %s creation failed\n", __func__, s_node->name); + return; + } + } if (get_lys_extension(OPER_FLAG_MAP_EXT, s_node, &fmap_str) == EXIT_SUCCESS) { if (fmap_str == NULL) { fprintf(stderr, @@ -831,7 +845,6 @@ void single_jobj_to_list2(struct json_object *json_obj, struct lyd_node **parent { const struct lysc_node_list *list = (const struct lysc_node_list *)s_node; char *keys = NULL; - int keys_count; if (get_list_keys2(list, json_obj, &keys) == EXIT_SUCCESS) { add_missing_parents(s_node, parent_data_node); struct lyd_node *new_data_node = NULL; @@ -1022,8 +1035,7 @@ int process_node(const struct lysc_node *s_node, json_object *json_obj, uint16_t int process_schema(const struct lysc_node *s_node, uint16_t lys_flags, struct lyd_node **parent_data_node) { - char *show_cmd = NULL; - const struct lysc_node *new_cmd_child; + char *show_cmd = "NULL"; struct json_object *cmd_output = NULL; /* Create top-level lyd_node */ if (*parent_data_node == NULL) { // Top-level node @@ -1038,6 +1050,19 @@ int process_schema(const struct lysc_node *s_node, uint16_t lys_flags, __func__, s_node->name); return EXIT_FAILURE; } + if (strcmp(net_namespace, "1") != 0) { + // Calculate the new size needed for show_cmd + size_t new_size = strlen(show_cmd) + strlen(" -n ") + strlen(net_namespace) + + 1; // +1 for the null terminator + + // Reallocate memory for show_cmd + show_cmd = realloc(show_cmd, new_size); + if (show_cmd == NULL) { + perror("realloc"); + exit(EXIT_FAILURE); + } + insert_netns(show_cmd, net_namespace); + } if (apply_ipr2_cmd(show_cmd) != EXIT_SUCCESS) { fprintf(stderr, "%s: command execution failed\n", __func__); @@ -1083,12 +1108,13 @@ int process_schema(const struct lysc_node *s_node, uint16_t lys_flags, * @return Returns an integer status code (SR_ERR_OK on success or an error code on failure). */ int load_module_data(sr_session_ctx_t *session, const char *module_name, uint16_t lys_flags, - struct lyd_node **parent) + struct lyd_node **parent, char *nsname) { int ret = SR_ERR_OK; const struct ly_ctx *ly_ctx; const struct lys_module *module = NULL; struct lyd_node *data_tree = NULL; + net_namespace = nsname; ly_ctx = sr_acquire_context(sr_session_get_connection(session)); module = ly_ctx_get_module_implemented(ly_ctx, module_name); diff --git a/src/lib/oper_data.h b/src/lib/oper_data.h index 567aeac..777d801 100644 --- a/src/lib/oper_data.h +++ b/src/lib/oper_data.h @@ -21,6 +21,6 @@ extern char json_buffer[1024 * 1024]; /* holds iproute2 show commands json outpu * @return Returns an integer status code (SR_ERR_OK on success or an error code on failure). */ int load_module_data(sr_session_ctx_t *session, const char *module_name, uint16_t lys_flags, - struct lyd_node **parent); + struct lyd_node **parent, char *nsname); #endif // IPROUTE2_SYSREPO_OPER_DATA_H diff --git a/tests/cases/test_ip_netns.sh b/tests/cases/test_ip_netns.sh index 4f7b572..21e2ca6 100755 --- a/tests/cases/test_ip_netns.sh +++ b/tests/cases/test_ip_netns.sh @@ -87,11 +87,11 @@ fi sysrepocfg -S '/iproute2-ip-link:links/link[name="netns_if"]/mtu' --value 1400 # Step 2: Check if the MTU for IP netns_if is updated by iproute2-sysrepo -current_mtu=$(ip link show dev netns_if 2>/dev/null | grep -oP '(?<=mtu )\d+' | head -n 1) +current_mtu=$(ip -n vpn10 link show dev netns_if 2>/dev/null | grep -oP '(?<=mtu )\d+' | head -n 1) if [ -z "$current_mtu" ]; then echo "TEST-ERROR:netns: Failed to retrieve MTU for IP link netns_if " - if_clean_up + clean_up exit 1 fi @@ -99,7 +99,7 @@ if [ "$current_mtu" -eq 1400 ]; then echo "TEST-INFO:netns: MTU for IP link netns_if updated successfully (OK)" else echo "TEST-ERROR:netns: Failed to update MTU for IP link netns_if, current_mtu = $current_mtu (FAIL)" - if_clean_up + clean_up exit 1 fi