From ce1a0daa15be4c3b7a3df64ea57ad231664e700f Mon Sep 17 00:00:00 2001 From: jackiechen1985 Date: Sun, 19 May 2019 12:35:28 +0800 Subject: Introduce a new registration mechanism to sweetcomb. Sweetcomb plugins register for various [initialization] events by placing structures and __attribute__((constructor)) functions into the library. When sysrepo plugin is initializing, the framework walks constructor-generated singly-linked structure lists, calls the indicated functions. Change-Id: I0cb078391f2662e4f6dd08c1a383173f203adf2a Signed-off-by: jackiechen1985 --- src/plugins/CMakeLists.txt | 5 +- src/plugins/ietf/ietf_interface.c | 101 +++++++++--------- src/plugins/ietf/ietf_nat.c | 57 ++++++---- src/plugins/openconfig/openconfig_interfaces.c | 105 +++++++++--------- src/plugins/openconfig/openconfig_local_routing.c | 124 +++++++++++----------- src/plugins/sc_init.c | 48 +++++++++ src/plugins/sc_init.h | 113 ++++++++++++++++++++ src/plugins/sc_model.c | 82 -------------- src/plugins/sc_model.h | 85 --------------- src/plugins/sc_plugins.c | 28 +++-- src/plugins/sc_plugins.h | 17 +++ 11 files changed, 401 insertions(+), 364 deletions(-) create mode 100644 src/plugins/sc_init.c create mode 100644 src/plugins/sc_init.h delete mode 100644 src/plugins/sc_model.c delete mode 100644 src/plugins/sc_model.h diff --git a/src/plugins/CMakeLists.txt b/src/plugins/CMakeLists.txt index a07ae60..ce09682 100644 --- a/src/plugins/CMakeLists.txt +++ b/src/plugins/CMakeLists.txt @@ -53,10 +53,13 @@ set(CMAKE_C_FLAGS_DEBUG "-Wall -Wextra -std=gnu99 -g -O0 ${RIGOROUS_C_FLAGS}") #NDEBUG to skip assert checks set(CMAKE_C_FLAGS_RELEASE "-Wall -Wextra -std=gnu99 -DNDEBUG -O2 ${RIGOROUS_C_FLAGS}") +# add plugin include directories +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) + # plugins sources set(PLUGINS_SOURCES + sc_init.c sc_plugins.c - sc_model.c ietf/ietf_interface.c ietf/ietf_nat.c openconfig/openconfig_interfaces.c diff --git a/src/plugins/ietf/ietf_interface.c b/src/plugins/ietf/ietf_interface.c index 0f8c37e..4d13d13 100644 --- a/src/plugins/ietf/ietf_interface.c +++ b/src/plugins/ietf/ietf_interface.c @@ -16,8 +16,7 @@ #include #include -#include "../sc_model.h" -#include "../sys_util.h" +#include #include #include @@ -339,51 +338,55 @@ nothing_todo: return rc; } -const xpath_t ietf_interfaces_xpaths[IETF_INTERFACES_SIZE] = { - { - .xpath = "/ietf-interfaces:interfaces/interface", - .method = XPATH, - .datastore = SR_DS_RUNNING, - .cb.scb = ietf_interface_change_cb, - .private_ctx = NULL, - .priority = 0, - .opts = SR_SUBSCR_CTX_REUSE | SR_SUBSCR_EV_ENABLED - }, - { - .xpath = "/ietf-interfaces:interfaces/interface/enabled", - .method = XPATH, - .datastore = SR_DS_RUNNING, - .cb.scb = ietf_interface_enable_disable_cb, - .private_ctx = NULL, - .priority = 100, - .opts = SR_SUBSCR_CTX_REUSE | SR_SUBSCR_EV_ENABLED - }, - { - .xpath = "/ietf-interfaces:interfaces/interface/ietf-ip:ipv4/address", - .method = XPATH, - .datastore = SR_DS_RUNNING, - .cb.scb = ietf_interface_ipv46_address_change_cb, - .private_ctx = NULL, - .priority = 99, - .opts = SR_SUBSCR_CTX_REUSE | SR_SUBSCR_EV_ENABLED - }, - { - .xpath = "/ietf-interfaces:interfaces/interface/ietf-ip:ipv6/address", - .method = XPATH, - .datastore = SR_DS_RUNNING, - .cb.scb = ietf_interface_ipv46_address_change_cb, - .private_ctx = NULL, - .priority = 98, - .opts = SR_SUBSCR_CTX_REUSE | SR_SUBSCR_EV_ENABLED - }, - { - .xpath = "/ietf-interfaces:interfaces-state", - .method = GETITEM, - .datastore = SR_DS_RUNNING, - .cb.gcb = ietf_interface_state_cb, - .private_ctx = NULL, - .priority = 98, - //.opts = SR_SUBSCR_DEFAULT, - .opts = SR_SUBSCR_CTX_REUSE + +int +ietf_interface_init(sc_plugin_main_t *pm) +{ + int rc = SR_ERR_OK; + SRP_LOG_DBG_MSG("Initializing ietf-interface plugin."); + + rc = sr_subtree_change_subscribe(pm->session, "/ietf-interfaces:interfaces/interface", + ietf_interface_change_cb, NULL, 0, SR_SUBSCR_CTX_REUSE | SR_SUBSCR_EV_ENABLED, &pm->subscription); + if (SR_ERR_OK != rc) { + goto error; + } + + rc = sr_subtree_change_subscribe(pm->session, "/ietf-interfaces:interfaces/interface/enabled", + ietf_interface_enable_disable_cb, NULL, 100, SR_SUBSCR_CTX_REUSE | SR_SUBSCR_EV_ENABLED, &pm->subscription); + if (SR_ERR_OK != rc) { + goto error; + } + + rc = sr_subtree_change_subscribe(pm->session, "/ietf-interfaces:interfaces/interface/ietf-ip:ipv4/address", + ietf_interface_ipv46_address_change_cb, NULL, 99, SR_SUBSCR_CTX_REUSE | SR_SUBSCR_EV_ENABLED, &pm->subscription); + if (SR_ERR_OK != rc) { + goto error; + } + + rc = sr_subtree_change_subscribe(pm->session, "/ietf-interfaces:interfaces/interface/ietf-ip:ipv6/address", + ietf_interface_ipv46_address_change_cb, NULL, 98, SR_SUBSCR_CTX_REUSE | SR_SUBSCR_EV_ENABLED, &pm->subscription); + if (SR_ERR_OK != rc) { + goto error; + } + + rc = sr_dp_get_items_subscribe(pm->session, "/ietf-interfaces:interfaces-state", + ietf_interface_state_cb, NULL, SR_SUBSCR_CTX_REUSE, &pm->subscription); + if (SR_ERR_OK != rc) { + goto error; } -}; + + SRP_LOG_DBG_MSG("ietf-interface plugin initialized successfully."); + return SR_ERR_OK; + +error: + SRP_LOG_ERR("Error by initialization of ietf-interface plugin. Error : %d", rc); + return rc; +} + +void +ietf_interface_exit(__attribute__((unused)) sc_plugin_main_t *pm) +{ +} + +SC_INIT_FUNCTION(ietf_interface_init); +SC_EXIT_FUNCTION(ietf_interface_exit); diff --git a/src/plugins/ietf/ietf_nat.c b/src/plugins/ietf/ietf_nat.c index 3b82f28..287fa02 100644 --- a/src/plugins/ietf/ietf_nat.c +++ b/src/plugins/ietf/ietf_nat.c @@ -18,7 +18,7 @@ #include #include -#include "../sc_model.h" +#include #include #include @@ -29,8 +29,6 @@ #include #include -#include "../sys_util.h" - /** * @brief Wrapper struct for VAPI address range payload. */ @@ -490,23 +488,36 @@ error: return rc; } -const xpath_t ietf_nat_xpaths[IETF_NAT_SIZE] = { - { - .xpath = "/ietf-nat:nat/instances/instance/policy/external-ip-address-pool", - .method = XPATH, - .datastore = SR_DS_RUNNING, - .cb.scb = instances_instance_policy_external_ip_address_pool_cb, - .private_ctx = NULL, - .priority = 0, - .opts = SR_SUBSCR_CTX_REUSE - }, - { - .xpath = "/ietf-nat:nat/instances/instance/mapping-table/mapping-entry", - .method = XPATH, - .datastore = SR_DS_RUNNING, - .cb.scb = instances_instance_mapping_table_mapping_entry_cb, - .private_ctx = NULL, - .priority = 0, - .opts = SR_SUBSCR_CTX_REUSE - }, -}; +int +ietf_nat_init(sc_plugin_main_t *pm) +{ + int rc = SR_ERR_OK; + SRP_LOG_DBG_MSG("Initializing ietf-nat plugin."); + + rc = sr_subtree_change_subscribe(pm->session, "/ietf-nat:nat/instances/instance/policy/external-ip-address-pool", + instances_instance_policy_external_ip_address_pool_cb, NULL, 0, SR_SUBSCR_CTX_REUSE, &pm->subscription); + if (rc != SR_ERR_OK) { + goto error; + } + + rc = sr_subtree_change_subscribe(pm->session, "/ietf-nat:nat/instances/instance/mapping-table/mapping-entry", + instances_instance_mapping_table_mapping_entry_cb, NULL, 0, SR_SUBSCR_CTX_REUSE, &pm->subscription); + if (rc != SR_ERR_OK) { + goto error; + } + + SRP_LOG_DBG_MSG("ietf-nat plugin initialized successfully."); + return SR_ERR_OK; + +error: + SRP_LOG_ERR("Error by initialization of ietf-nat plugin. Error : %d", rc); + return rc; +} + +void +ietf_nat_exit(__attribute__((unused)) sc_plugin_main_t *pm) +{ +} + +SC_INIT_FUNCTION(ietf_nat_init); +SC_EXIT_FUNCTION(ietf_nat_exit); diff --git a/src/plugins/openconfig/openconfig_interfaces.c b/src/plugins/openconfig/openconfig_interfaces.c index 7242c2b..67b9a3c 100644 --- a/src/plugins/openconfig/openconfig_interfaces.c +++ b/src/plugins/openconfig/openconfig_interfaces.c @@ -21,8 +21,7 @@ #include #include -#include "../sc_model.h" -#include "../sys_util.h" +#include // XPATH: /openconfig-interfaces:interfaces/interface[name='%s']/config/ static int openconfig_interfaces_interfaces_interface_config_cb( @@ -590,52 +589,58 @@ static int openconfig_interfaces_interfaces_interface_subinterfaces_subinterface return SR_ERR_OK; } -const xpath_t oc_interfaces_xpaths[OC_INTERFACES_SIZE] = { - { - .xpath = "/openconfig-interfaces:interfaces/interface/config", - .method = XPATH, - .datastore = SR_DS_RUNNING, - .cb.scb = openconfig_interfaces_interfaces_interface_config_cb, - .private_ctx = NULL, - .priority = 98, - //.opts = SR_SUBSCR_DEFAULT - .opts = SR_SUBSCR_CTX_REUSE - }, - { - .xpath = "/openconfig-interfaces:interfaces/interface/state", - .method = GETITEM, - .datastore = SR_DS_RUNNING, - .cb.gcb = openconfig_interfaces_interfaces_interface_state_cb, - .private_ctx = NULL, - .priority = 98, - .opts = SR_SUBSCR_CTX_REUSE - }, - { - .xpath = "/openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/state", - .method = GETITEM, - .datastore = SR_DS_RUNNING, - .cb.gcb = openconfig_interfaces_interfaces_interface_subinterfaces_subinterface_state_cb, - .private_ctx = NULL, - .priority = 99, - .opts = SR_SUBSCR_CTX_REUSE - }, - { - .xpath = "/openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/openconfig-if-ip:ipv4/openconfig-if-ip:addresses/openconfig-if-ip:address/openconfig-if-ip:config", - .method = XPATH, - .datastore = SR_DS_RUNNING, - .cb.scb = openconfig_interfaces_interfaces_interface_subinterfaces_subinterface_oc_ip_ipv4_oc_ip_addresses_oc_ip_address_oc_ip_config_cb, - .private_ctx = NULL, - .priority = 100, - //.opts = SR_SUBSCR_DEFAULT - .opts = SR_SUBSCR_CTX_REUSE - }, - { - .xpath = "/openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/openconfig-if-ip:ipv4/openconfig-if-ip:addresses/openconfig-if-ip:address/openconfig-if-ip:state", - .method = GETITEM, - .datastore = SR_DS_RUNNING, - .cb.gcb = openconfig_interfaces_interfaces_interface_subinterfaces_subinterface_oc_ip_ipv4_oc_ip_addresses_oc_ip_address_oc_ip_state_cb, - .private_ctx = NULL, - .priority = 100, - .opts = SR_SUBSCR_CTX_REUSE +int +openconfig_interface_init(sc_plugin_main_t *pm) +{ + int rc = SR_ERR_OK; + SRP_LOG_DBG_MSG("Initializing openconfig-interfaces plugin."); + + rc = sr_subtree_change_subscribe(pm->session, "/openconfig-interfaces:interfaces/interface/config", + openconfig_interfaces_interfaces_interface_config_cb, NULL, 98, SR_SUBSCR_CTX_REUSE, &pm->subscription); + if (SR_ERR_OK != rc) { + goto error; + } + + rc = sr_dp_get_items_subscribe(pm->session, "/openconfig-interfaces:interfaces/interface/state", + openconfig_interfaces_interfaces_interface_state_cb, NULL, SR_SUBSCR_CTX_REUSE, &pm->subscription); + if (SR_ERR_OK != rc) { + goto error; + } + + rc = sr_dp_get_items_subscribe(pm->session, "/openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/state", + openconfig_interfaces_interfaces_interface_subinterfaces_subinterface_state_cb, NULL, SR_SUBSCR_CTX_REUSE, &pm->subscription); + if (SR_ERR_OK != rc) { + goto error; + } + + rc = sr_subtree_change_subscribe(pm->session, + "/openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/openconfig-if-ip:ipv4/openconfig-if-ip:addresses/openconfig-if-ip:address/openconfig-if-ip:config", + openconfig_interfaces_interfaces_interface_subinterfaces_subinterface_oc_ip_ipv4_oc_ip_addresses_oc_ip_address_oc_ip_config_cb, + NULL, 100, SR_SUBSCR_CTX_REUSE, &pm->subscription); + if (SR_ERR_OK != rc) { + goto error; + } + + rc = sr_dp_get_items_subscribe(pm->session, + "/openconfig-interfaces:interfaces/interface/subinterfaces/subinterface/openconfig-if-ip:ipv4/openconfig-if-ip:addresses/openconfig-if-ip:address/openconfig-if-ip:state", + openconfig_interfaces_interfaces_interface_subinterfaces_subinterface_oc_ip_ipv4_oc_ip_addresses_oc_ip_address_oc_ip_state_cb, + NULL, SR_SUBSCR_CTX_REUSE, &pm->subscription); + if (SR_ERR_OK != rc) { + goto error; } -}; + + SRP_LOG_DBG_MSG("openconfig-interfaces plugin initialized successfully."); + return SR_ERR_OK; + +error: + SRP_LOG_ERR("Error by initialization of openconfig-interfaces plugin. Error : %d", rc); + return rc; +} + +void +openconfig_interface_exit(__attribute__((unused)) sc_plugin_main_t *pm) +{ +} + +SC_INIT_FUNCTION(openconfig_interface_init); +SC_EXIT_FUNCTION(openconfig_interface_exit); diff --git a/src/plugins/openconfig/openconfig_local_routing.c b/src/plugins/openconfig/openconfig_local_routing.c index 6a3b5bd..2d16da0 100644 --- a/src/plugins/openconfig/openconfig_local_routing.c +++ b/src/plugins/openconfig/openconfig_local_routing.c @@ -21,8 +21,7 @@ #include #include -#include "../sc_model.h" -#include "../sys_util.h" +#include #define HOP_INDEX_SIZE 10 //number of digit in max 32 bit integer @@ -400,7 +399,7 @@ oc_next_hop_state_cb(const char *xpath, sr_val_t **values, size_t *values_cnt, if (strtoul(index, NULL, 0) != reply->path[0].next_hop_id) { SRP_LOG_ERR("next hop index is %d for prefix %s", reply->path[0].next_hop_id, prefix); - SRP_LOG_ERR("before %s, stroul is %d", index, strtoul(index, NULL, 0)); + SRP_LOG_ERR("before %s, stroul is %lu", index, strtoul(index, NULL, 0)); return SR_ERR_INVAL_ARG; } @@ -468,7 +467,7 @@ oc_next_hop_interface_state_cb(const char *xpath, sr_val_t **values, if (strtoul(index, NULL, 0) != reply->path[0].next_hop_id) { SRP_LOG_ERR("next hop index is %d for prefix %s", reply->path[0].next_hop_id, prefix); - SRP_LOG_ERR("before %s, stroul is %d", index, strtoul(index, NULL, 0)); + SRP_LOG_ERR("before %s, stroul is %lu", index, strtoul(index, NULL, 0)); return SR_ERR_INVAL_ARG; } @@ -489,62 +488,61 @@ oc_next_hop_interface_state_cb(const char *xpath, sr_val_t **values, return SR_ERR_OK; } -const xpath_t oc_local_routing_xpaths[OC_LROUTING_SIZE] = { - { - .xpath = "/openconfig-local-routing:local-routes/static-routes/static/config", - .method = XPATH, - .datastore = SR_DS_RUNNING, - .cb.scb = oc_prefix_config_cb, - .private_ctx = NULL, - .priority = 0, - //.opts = SR_SUBSCR_DEFAULT - .opts = SR_SUBSCR_CTX_REUSE - }, - { - .xpath = "/openconfig-local-routing:local-routes/static-routes/static/next-hops/next-hop/config", - .method = XPATH, - .datastore = SR_DS_RUNNING, - .cb.scb = oc_next_hop_config_cb, - .private_ctx = NULL, - .priority = 0, - //.opts = SR_SUBSCR_DEFAULT - .opts = SR_SUBSCR_CTX_REUSE - }, - { - .xpath = "/openconfig-local-routing:local-routes/static-routes/static/next-hops/next-hop/interface-ref/config", - .method = XPATH, - .datastore = SR_DS_RUNNING, - .cb.scb = oc_next_hop_interface_config_cb, - .private_ctx = NULL, - .priority = 0, - //.opts = SR_SUBSCR_DEFAULT - .opts = SR_SUBSCR_CTX_REUSE - }, - { - .xpath = "/openconfig-local-routing:local-routes/static-routes/static/state", - .method = GETITEM, - .datastore = SR_DS_RUNNING, - .cb.gcb = oc_prefix_state_cb, - .private_ctx = NULL, - .priority = 0, - .opts = SR_SUBSCR_CTX_REUSE - }, - { - .xpath = "/openconfig-local-routing:local-routes/static-routes/static/next-hops/next-hop/state", - .method = GETITEM, - .datastore = SR_DS_RUNNING, - .cb.gcb = oc_next_hop_state_cb, - .private_ctx = NULL, - .priority = 0, - .opts = SR_SUBSCR_CTX_REUSE - }, - { - .xpath = "/openconfig-local-routing:local-routes/static-routes/static/next-hops/next-hop/interface-ref/state", - .method = GETITEM, - .datastore = SR_DS_RUNNING, - .cb.gcb = oc_next_hop_interface_state_cb, - .private_ctx = NULL, - .priority = 0, - .opts = SR_SUBSCR_CTX_REUSE - }, -}; +int +openconfig_local_routing_init(sc_plugin_main_t *pm) +{ + int rc = SR_ERR_OK; + SRP_LOG_DBG_MSG("Initializing openconfig-local-routing plugin."); + + rc = sr_subtree_change_subscribe(pm->session, "/openconfig-local-routing:local-routes/static-routes/static/config", + oc_prefix_config_cb, NULL, 0, SR_SUBSCR_CTX_REUSE, &pm->subscription); + if (SR_ERR_OK != rc) { + goto error; + } + + rc = sr_subtree_change_subscribe(pm->session, "/openconfig-local-routing:local-routes/static-routes/static/next-hops/next-hop/config", + oc_next_hop_config_cb, NULL, 0, SR_SUBSCR_CTX_REUSE, &pm->subscription); + if (SR_ERR_OK != rc) { + goto error; + } + + rc = sr_subtree_change_subscribe(pm->session, "/openconfig-local-routing:local-routes/static-routes/static/next-hops/next-hop/interface-ref/config", + oc_next_hop_interface_config_cb, NULL, 0, SR_SUBSCR_CTX_REUSE, &pm->subscription); + if (SR_ERR_OK != rc) { + goto error; + } + + rc = sr_dp_get_items_subscribe(pm->session, "/openconfig-local-routing:local-routes/static-routes/static/state", + oc_prefix_state_cb, NULL, SR_SUBSCR_CTX_REUSE, &pm->subscription); + if (SR_ERR_OK != rc) { + goto error; + } + + rc = sr_dp_get_items_subscribe(pm->session, "/openconfig-local-routing:local-routes/static-routes/static/next-hops/next-hop/state", + oc_next_hop_state_cb, NULL, SR_SUBSCR_CTX_REUSE, &pm->subscription); + if (SR_ERR_OK != rc) { + goto error; + } + + rc = sr_dp_get_items_subscribe(pm->session, "/openconfig-local-routing:local-routes/static-routes/static/next-hops/next-hop/interface-ref/state", + oc_next_hop_interface_state_cb, NULL, SR_SUBSCR_CTX_REUSE, &pm->subscription); + if (SR_ERR_OK != rc) { + goto error; + } + + SRP_LOG_DBG_MSG("openconfig-local-routing plugin initialized successfully."); + return SR_ERR_OK; + +error: + SRP_LOG_ERR("Error by initialization of openconfig-local-routing plugin. Error : %d", rc); + return rc; +} + +void +openconfig_local_routing_exit(__attribute__((unused)) sc_plugin_main_t *pm) +{ +} + +SC_INIT_FUNCTION(openconfig_local_routing_init); +SC_EXIT_FUNCTION(openconfig_local_routing_exit); + diff --git a/src/plugins/sc_init.c b/src/plugins/sc_init.c new file mode 100644 index 0000000..baae3f6 --- /dev/null +++ b/src/plugins/sc_init.c @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2019 Tieto and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "sc_plugins.h" + +int +sc_call_all_init_function(sc_plugin_main_t *pm) +{ + int ret = SR_ERR_OK; + _sc_init_function_list_elt_t *p = pm->init_function_registrations; + while (p != NULL) { + if (!p->is_called) { + p->is_called = true; + ret = p->func(pm); + if (ret != SR_ERR_OK) { + return ret; + } + } + p = p->next; + } + return ret; +} + +void +sc_call_all_exit_function(sc_plugin_main_t *pm) +{ + _sc_exit_function_list_elt_t *p = pm->exit_function_registrations; + while (p != NULL) { + if (!p->is_called) { + p->is_called = true; + p->func(pm); + } + p = p->next; + } +} + diff --git a/src/plugins/sc_init.h b/src/plugins/sc_init.h new file mode 100644 index 0000000..b7ba1ef --- /dev/null +++ b/src/plugins/sc_init.h @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2019 Tieto and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __SC_INIT_H__ +#define __SC_INIT_H__ + +#include + +struct sc_plugin_main_t; + +/* Init/exit functions: called at start/end of sr plugin init/cleaup. */ +typedef int (sc_init_function_t) (struct sc_plugin_main_t *pm); +typedef void (sc_exit_function_t) (struct sc_plugin_main_t *pm); + +/* Declaration of init/exit Linked List structures */ +#define foreach_sc_declare_function_list \ +_(init) \ +_(exit) + +#define _(tag) \ +typedef struct _sc_##tag##_function_list_elt { \ + struct _sc_##tag##_function_list_elt *next; \ + sc_##tag##_function_t *func; \ + bool is_called; \ +} _sc_##tag##_function_list_elt_t; +foreach_sc_declare_function_list +#undef _ + +/* Declaration of add/rm function that need to be add/remote link list */ +#define SC_DECLARE_FUNCTION(f, tag) \ +static void __sc_add_##tag##_function_##f() __attribute__((__constructor__)); \ +static void __sc_add_##tag##_function_##f() \ +{ \ + sc_plugin_main_t *pm = sc_get_plugin_main(); \ + static _sc_##tag##_function_list_elt_t _sc_##tag##_function; \ + _sc_##tag##_function.next = pm->tag##_function_registrations; \ + _sc_##tag##_function.func = &f; \ + _sc_##tag##_function.is_called = false; \ + pm->tag##_function_registrations = &_sc_##tag##_function; \ +} \ +static void __sc_rm_##tag##_function_##f() __attribute__((__destructor__)); \ +static void __sc_rm_##tag##_function_##f() \ +{ \ + sc_plugin_main_t *pm = sc_get_plugin_main(); \ + _sc_##tag##_function_list_elt_t *p; \ + if (pm->tag##_function_registrations->func == &f) { \ + pm->tag##_function_registrations = pm->tag##_function_registrations->next; \ + return; \ + } \ + p = pm->tag##_function_registrations; \ + while (p->next != NULL) { \ + if (p->next->func == &f) { \ + p->next = p->next->next; \ + return; \ + } \ + p = p->next; \ + } \ +} + +/* Macros to be called from yang model implementation. + Register init and exit functions for YANG model implementation in Linked List. */ +#define SC_INIT_FUNCTION(f) SC_DECLARE_FUNCTION(f, init) +#define SC_EXIT_FUNCTION(f) SC_DECLARE_FUNCTION(f, exit) + +/* Call given init/exit function: used for init/exit function dependencies. */ +#define sc_call_init_function(f, pm) \ +({ \ + int _ret = SR_ERR_OK; \ + _sc_init_function_list_elt_t *p = pm->init_function_registrations; \ + while (p != NULL) { \ + if (p->func == f && !p->is_called) { \ + p->is_called = true; \ + _ret = p->func(pm); \ + break; \ + } \ + p = p->next; \ + } \ + _ret; \ +}) + +#define sc_call_exit_function(f, pm) \ +({ \ + _sc_exit_function_list_elt_t *p = pm->exit_function_registrations; \ + while (p != NULL) { \ + if (p->func == f && !p->is_called) { \ + p->is_called = true; \ + p->func(pm); \ + break; \ + } \ + p = p->next; \ + } \ +}) + +/* Run through all registered init/exit functions of models. */ +int +sc_call_all_init_function(struct sc_plugin_main_t *pm); + +void +sc_call_all_exit_function(struct sc_plugin_main_t *pm); + +#endif //__SC_INIT_H__ diff --git a/src/plugins/sc_model.c b/src/plugins/sc_model.c deleted file mode 100644 index d9bf92b..0000000 --- a/src/plugins/sc_model.c +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (c) 2018 PANTHEON.tech. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "sc_model.h" - -#include - -static int -subscribe(sr_session_ctx_t *ds, sr_subscription_ctx_t **sub, - const xpath_t *xpath) -{ - int rc; - - switch (xpath->method) { - case MODULE: - rc = sr_module_change_subscribe(ds, xpath->xpath, xpath->cb.mcb, - xpath->private_ctx, xpath->priority, - xpath->opts, sub); - break; - - case XPATH: - rc = sr_subtree_change_subscribe(ds, xpath->xpath, xpath->cb.scb, - xpath->private_ctx, - xpath->priority, xpath->opts, sub); - break; - - case GETITEM: - rc = sr_dp_get_items_subscribe(ds, xpath->xpath, xpath->cb.gcb, - xpath->private_ctx, xpath->opts, - sub); - break; - - case RPC: - rc = sr_rpc_subscribe(ds, xpath->xpath, xpath->cb.rcb, - xpath->private_ctx, xpath->opts, sub); - break; - - default: - SRP_LOG_ERR("Unknown method %d", xpath->method); - return SR_ERR_NOT_FOUND; - } - - if (SR_ERR_OK != rc) { - SRP_LOG_ERR("Error subscribing to %s", xpath->xpath); - return rc; - } - - SRP_LOG_INF("Subscribed to xpath: %s", xpath->xpath); - - return SR_ERR_OK; -} - -int -model_register(plugin_main_t* plugin_main, const xpath_t *xpaths, size_t size) -{ - int rc = 0; - uint32_t i = 0; - - ARG_CHECK(-1, plugin_main); - - for (i = 0; i < size; i++) { - rc = subscribe(plugin_main->session, &plugin_main->subscription, - &xpaths[i]); - if (SR_ERR_OK != rc) - SRP_LOG_ERR("Subscription failed for xpath: %s", xpaths[i].xpath); - } - - return 0; -} diff --git a/src/plugins/sc_model.h b/src/plugins/sc_model.h deleted file mode 100644 index a9392f9..0000000 --- a/src/plugins/sc_model.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (c) 2018 PANTHEON.tech. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __SC_MODEL_H__ -#define __SC_MODEL_H__ - -/* - * IETF or Openconfig YANG models registering/unregistering - * - * Every model supports a certain number of operations which require a - * subscription to sysrepo : xpath_t - */ - -#include -#include -#include -#include - -#include //for ARG_CHECK only - -typedef enum { - MODULE, - XPATH, - GETITEM, - RPC, -} method_e; - -#define ARRAY_SIZE(X) (sizeof(X) / sizeof(X[0])) - -typedef struct _xpath_t { - char *xpath; - method_e method; - sr_datastore_t datastore; - union { - sr_module_change_cb mcb; - sr_subtree_change_cb scb; - sr_dp_get_items_cb gcb; - sr_rpc_cb rcb; - } cb; - void *private_ctx; - uint32_t priority; - sr_subscr_options_t opts; -} xpath_t; - -/* - * Stateful informations. Keep sesssions informations about a user - */ - -typedef struct { - sr_session_ctx_t *session; - sr_subscription_ctx_t *subscription; -} plugin_main_t; - - -int -model_register(plugin_main_t *plugin_main, const xpath_t *xpaths, size_t size); - -/* Declare registration */ - -#define OC_INTERFACES_SIZE 5 -extern const xpath_t oc_interfaces_xpaths[OC_INTERFACES_SIZE]; - -#define OC_LROUTING_SIZE 6 -extern const xpath_t oc_local_routing_xpaths[OC_LROUTING_SIZE]; - -#define IETF_NAT_SIZE 2 -extern const xpath_t ietf_nat_xpaths[IETF_NAT_SIZE]; - -#define IETF_INTERFACES_SIZE 5 -extern const xpath_t ietf_interfaces_xpaths[IETF_INTERFACES_SIZE]; - -#endif /* __SC_MODEL_H__ */ diff --git a/src/plugins/sc_plugins.c b/src/plugins/sc_plugins.c index df191bf..e0de0f6 100644 --- a/src/plugins/sc_plugins.c +++ b/src/plugins/sc_plugins.c @@ -13,12 +13,18 @@ * limitations under the License. */ -#include "sc_model.h" #include "sc_plugins.h" + #include +sc_plugin_main_t sc_plugin_main; static int vpp_pid_start; +sc_plugin_main_t *sc_get_plugin_main() +{ + return &sc_plugin_main; +} + /* get vpp pid in system */ int get_vpp_pid() { @@ -63,26 +69,24 @@ int get_vpp_pid() int sr_plugin_init_cb(sr_session_ctx_t *session, void **private_ctx) { - plugin_main_t plugin_main; int rc; + sc_plugin_main.session = session; + rc = sc_connect_vpp(); if (0 != rc) { SRP_LOG_ERR("vpp connect error , with return %d.", rc); return SR_ERR_INTERNAL; } - plugin_main.session = session; - plugin_main.subscription = NULL; - - /* Use the same sr_subscription_ctx for all models */ - model_register(&plugin_main, ietf_interfaces_xpaths, IETF_INTERFACES_SIZE); - model_register(&plugin_main, ietf_nat_xpaths, IETF_NAT_SIZE); - model_register(&plugin_main, oc_interfaces_xpaths, OC_INTERFACES_SIZE); - model_register(&plugin_main, oc_local_routing_xpaths, OC_LROUTING_SIZE); + rc = sc_call_all_init_function(&sc_plugin_main); + if (rc != SR_ERR_OK) { + SRP_LOG_ERR("Call all init function error: %d", rc); + return rc; + } /* set subscription as our private context */ - *private_ctx = plugin_main.subscription; + *private_ctx = sc_plugin_main.subscription; /* get the vpp pid sweetcomb connected, we assumed that only one vpp is run in system */ vpp_pid_start = get_vpp_pid(); return SR_ERR_OK; @@ -90,6 +94,8 @@ int sr_plugin_init_cb(sr_session_ctx_t *session, void **private_ctx) void sr_plugin_cleanup_cb(sr_session_ctx_t *session, void *private_ctx) { + sc_call_all_exit_function(&sc_plugin_main); + /* subscription was set as our private context */ if (private_ctx != NULL) sr_unsubscribe(session, private_ctx); diff --git a/src/plugins/sc_plugins.h b/src/plugins/sc_plugins.h index 4a784fb..681be6b 100644 --- a/src/plugins/sc_plugins.h +++ b/src/plugins/sc_plugins.h @@ -20,6 +20,23 @@ #include #include +#include "sc_init.h" +#include "sys_util.h" + +typedef struct sc_plugin_main_t { + /* Session context acquired with ::sr_session_start call. */ + sr_session_ctx_t *session; + + /* Subscription context that is supposed to be released by ::sr_unsubscribe */ + sr_subscription_ctx_t *subscription; + + /* List of init/exit functions to call, setup by constructors */ + _sc_init_function_list_elt_t *init_function_registrations; + _sc_exit_function_list_elt_t *exit_function_registrations; +} sc_plugin_main_t; + +sc_plugin_main_t *sc_get_plugin_main(); + //functions that sysrepo-plugin need int sr_plugin_init_cb(sr_session_ctx_t *session, void **private_ctx); void sr_plugin_cleanup_cb(sr_session_ctx_t *session, void *private_ctx); -- cgit 1.2.3-korg