From 18561adfde80d6665e24262d70d18f916e2662e5 Mon Sep 17 00:00:00 2001 From: YohanPipereau Date: Mon, 15 Jul 2019 15:37:46 +0200 Subject: vom: migration from scvpp to vom Change-Id: I79609f0bee9b8307da0d9bf704babe8ba06dba4d Signed-off-by: YohanPipereau Co-authored-by: Pavel Kotucek Co-authored-by: Andrej Kozemcak --- src/plugins/openconfig/openconfig_interfaces.cpp | 309 +++++++++++++++++++++++ 1 file changed, 309 insertions(+) create mode 100644 src/plugins/openconfig/openconfig_interfaces.cpp (limited to 'src/plugins/openconfig/openconfig_interfaces.cpp') diff --git a/src/plugins/openconfig/openconfig_interfaces.cpp b/src/plugins/openconfig/openconfig_interfaces.cpp new file mode 100644 index 0000000..40de71c --- /dev/null +++ b/src/plugins/openconfig/openconfig_interfaces.cpp @@ -0,0 +1,309 @@ +/* + * 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 +#include + +#include +#include + +#include + +#include + +using VOM::interface; +using VOM::OM; +using VOM::HW; +using VOM::rc_t; + +using type_t = VOM::interface::type_t; +using admin_state_t = VOM::interface::admin_state_t; + +class interface_builder { + public: + interface_builder() {} + + shared_ptr build() { + if (m_name.empty() || m_type.empty()) + return nullptr; + return make_shared(m_name, type_t::from_string(m_type), + admin_state_t::from_int(m_state)); + } + + /* Getters */ + string name() { + return m_name; + } + + /* Setters */ + interface_builder& set_name(string n) { + m_name = n; + return *this; + } + + interface_builder& set_type(string t) { + if (t == "iana-if-type:ethernetCsmacd") + m_type = "ETHERNET"; + return *this; + } + + interface_builder& set_state(bool enable) { + m_state = enable; + return *this; + } + + std::string to_string() { + std::ostringstream os; + os << m_name << "," << m_type << "," << m_state; + return os.str(); + } + + private: + string m_name; + string m_type; + bool m_state; +}; + + +// XPATH: /openconfig-interfaces:interfaces/interface[name='%s']/config/ +static int +oc_interfaces_config_cb(sr_session_ctx_t *ds, const char *xpath, + sr_notif_event_t event, void *private_ctx) +{ + UNUSED(private_ctx); + interface_builder builder; + shared_ptr intf; + string intf_name; + sr_change_iter_t *it = nullptr; + sr_xpath_ctx_t state; + sr_val_t *ol = nullptr; + sr_val_t *ne = nullptr; + sr_change_oper_t oper; + bool create, remove, modify; + int rc; + + SRP_LOG_INF("In %s", __FUNCTION__); + + ARG_CHECK2(SR_ERR_INVAL_ARG, ds, xpath); + + if (event != SR_EV_VERIFY) + return SR_ERR_OK; + + if (sr_get_changes_iter(ds, (char *)xpath, &it) != SR_ERR_OK) { + sr_free_change_iter(it); + return SR_ERR_OK; + } + + foreach_change (ds, it, oper, ol, ne) { + + intf_name = sr_xpath_key_value(ne->xpath, "interface", "name", &state); + if (intf_name.empty()) { + sr_set_error(ds, "XPATH interface name NOT found", ne->xpath); + return SR_ERR_INVAL_ARG; + } + sr_xpath_recover(&state); + + switch (oper) { + case SR_OP_CREATED: + if (sr_xpath_node_name_eq(ne->xpath, "name")) { + builder.set_name(ne->data.string_val); + create = true; + } else if(sr_xpath_node_name_eq(ne->xpath, "type")) { + builder.set_type(ne->data.string_val); + } else if(sr_xpath_node_name_eq(ne->xpath, "enabled")) { + builder.set_state(ne->data.bool_val); + } + break; + + case SR_OP_MODIFIED: + if (sr_xpath_node_name_eq(ne->xpath, "enabled")) { + string n = sr_xpath_key_value(ne->xpath, "interface", + "name", &state); + intf = interface::find(n); + if (!intf) { + rc = SR_ERR_OPERATION_FAILED; + goto nothing_todo; + } + intf->set(admin_state_t::from_int(ne->data.bool_val)); + modify = true; + } + break; + + case SR_OP_DELETED: + if (sr_xpath_node_name_eq(ol->xpath, "name")) { + builder.set_name(ol->data.string_val); + remove = true; + } + break; + + default: + rc = SR_ERR_UNSUPPORTED; + goto nothing_todo; + } + + sr_xpath_recover(&state); + + sr_free_val(ol); + sr_free_val(ne); + } + + if (create) { + SRP_LOG_INF("creating interface '%s'", builder.name().c_str()); + intf = builder.build(); + if (nullptr == intf) { + SRP_LOG_ERR_MSG("Interface does not exist"); + rc = SR_ERR_INVAL_ARG; + goto nothing_todo; + } + } + + if (create || modify) { + if ( OM::write(intf->key(), *intf) != rc_t::OK ) { + SRP_LOG_ERR("Fail writing changes to VPP for: %s", + builder.to_string().c_str()); + rc = SR_ERR_OPERATION_FAILED; + goto nothing_todo; + } + } else if (remove) { + SRP_LOG_INF("deleting interface '%s'", builder.name().c_str()); + OM::remove(builder.name()); + } + + sr_free_change_iter(it); + return SR_ERR_OK; + +nothing_todo: + sr_free_val(ol); + sr_free_val(ne); + sr_free_change_iter(it); + return rc; +} + +//XPATH : /openconfig-interfaces:interfaces/interface/state +static int +oc_interfaces_state_cb(const char *xpath, sr_val_t **values, size_t *values_cnt, + uint64_t request_id, const char *original_xpath, + void *private_ctx) +{ + UNUSED(request_id); UNUSED(original_xpath); UNUSED(private_ctx); + vapi_payload_sw_interface_details reply; + shared_ptr dump; + string intf_name; + sr_val_t *vals = nullptr; + sr_xpath_ctx_t state; + char xpath_root[XPATH_SIZE]; + int vc = 7; + int cnt = 0; + int rc; + + SRP_LOG_INF("In %s", __FUNCTION__); + + ARG_CHECK3(SR_ERR_INVAL_ARG, xpath, values, values_cnt); + + intf_name = sr_xpath_key_value((char*) xpath, "interface", "name", &state); + if (intf_name.empty()) { + SRP_LOG_ERR_MSG("XPATH interface name not found"); + return SR_ERR_INVAL_ARG; + } + sr_xpath_recover(&state); + + snprintf(xpath_root, XPATH_SIZE, + "/openconfig-interfaces:interfaces/interface[name='%s']/state", + intf_name.c_str()); + + rc = sr_new_values(vc, &vals); + if (SR_ERR_OK != rc) + return rc; + + dump = make_shared(intf_name); //dump only specific intf + HW::enqueue(dump); + HW::write(); + + reply = dump->begin()->get_payload(); + + sr_val_build_xpath(&vals[cnt], "%s/name", xpath_root); + sr_val_set_str_data(&vals[cnt], SR_STRING_T, (char *)reply.interface_name); + cnt++; + + //TODO revisit types after V3PO has been implemented + sr_val_build_xpath(&vals[cnt], "%s/type", xpath_root); + sr_val_set_str_data(&vals[cnt], SR_IDENTITYREF_T, "ianaift:ethernetCsmacd"); + cnt++; + + sr_val_build_xpath(&vals[cnt], "%s/mtu", xpath_root); + vals[cnt].type = SR_UINT16_T; + vals[cnt].data.uint16_val = reply.link_mtu; + cnt++; + + sr_val_build_xpath(&vals[cnt], "%s/enabled", xpath_root); + vals[cnt].type = SR_BOOL_T; + vals[cnt].data.bool_val = reply.admin_up_down; + cnt++; + + sr_val_build_xpath(&vals[cnt], "%s/ifindex", xpath_root); + vals[cnt].type = SR_UINT32_T; + vals[cnt].data.uint32_val = reply.sw_if_index; + cnt++; + + sr_val_build_xpath(&vals[cnt], "%s/admin-status", xpath_root); + sr_val_set_str_data(&vals[cnt], SR_ENUM_T, + reply.admin_up_down ? "UP" : "DOWN"); + cnt++; + + sr_val_build_xpath(&vals[cnt], "%s/oper-status", xpath_root); + sr_val_set_str_data(&vals[cnt], SR_ENUM_T, + reply.link_up_down ? "UP" : "DOWN"); + cnt++; + + *values = vals; + *values_cnt = cnt; + + return SR_ERR_OK; +} + +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", + oc_interfaces_config_cb, nullptr, 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", + oc_interfaces_state_cb, nullptr, 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); -- cgit 1.2.3-korg