diff options
Diffstat (limited to 'src/vpp-api/vom/vxlan_tunnel.cpp')
-rw-r--r-- | src/vpp-api/vom/vxlan_tunnel.cpp | 272 |
1 files changed, 272 insertions, 0 deletions
diff --git a/src/vpp-api/vom/vxlan_tunnel.cpp b/src/vpp-api/vom/vxlan_tunnel.cpp new file mode 100644 index 00000000000..7079021ee6e --- /dev/null +++ b/src/vpp-api/vom/vxlan_tunnel.cpp @@ -0,0 +1,272 @@ +/* + * Copyright (c) 2017 Cisco 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 "vom/vxlan_tunnel.hpp" +#include "vom/logger.hpp" + +namespace VOM { +const std::string VXLAN_TUNNEL_NAME = "vxlan-tunnel-itf"; + +vxlan_tunnel::event_handler vxlan_tunnel::m_evh; + +/** + * A DB of all vxlan_tunnels + * this does not register as a listener for replay events, since the tunnels + * are also in the base-class interface DB and so will be poked from there. + */ +singular_db<vxlan_tunnel::endpoint_t, vxlan_tunnel> vxlan_tunnel::m_db; + +vxlan_tunnel::endpoint_t::endpoint_t(const boost::asio::ip::address& src, + const boost::asio::ip::address& dst, + uint32_t vni) + : src(src) + , dst(dst) + , vni(vni) +{ +} + +vxlan_tunnel::endpoint_t::endpoint_t() + : src() + , dst() + , vni(0) +{ +} + +bool +vxlan_tunnel::endpoint_t::operator==(const endpoint_t& other) const +{ + return ((src == other.src) && (dst == other.dst) && (vni == other.vni)); +} + +bool +vxlan_tunnel::endpoint_t::operator<(const vxlan_tunnel::endpoint_t& o) const +{ + if (src < o.src) + return true; + if (dst < o.dst) + return true; + if (vni < o.vni) + return true; + + return false; +} + +std::string +vxlan_tunnel::endpoint_t::to_string() const +{ + std::ostringstream s; + + s << "ep:[" + << "src:" << src.to_string() << " dst:" << dst.to_string() << " vni:" << vni + << "]"; + + return (s.str()); +} + +std::ostream& +operator<<(std::ostream& os, const vxlan_tunnel::endpoint_t& ep) +{ + os << ep.to_string(); + + return (os); +} + +std::string +vxlan_tunnel::mk_name(const boost::asio::ip::address& src, + const boost::asio::ip::address& dst, + uint32_t vni) +{ + std::ostringstream s; + + s << VXLAN_TUNNEL_NAME << "-" << src << "-" << dst << ":" << vni; + + return (s.str()); +} + +vxlan_tunnel::vxlan_tunnel(const boost::asio::ip::address& src, + const boost::asio::ip::address& dst, + uint32_t vni) + : interface(mk_name(src, dst, vni), + interface::type_t::VXLAN, + interface::admin_state_t::UP) + , m_tep(src, dst, vni) +{ +} + +vxlan_tunnel::vxlan_tunnel(const handle_t& hdl, + const boost::asio::ip::address& src, + const boost::asio::ip::address& dst, + uint32_t vni) + : interface(hdl, + l2_address_t::ZERO, + mk_name(src, dst, vni), + interface::type_t::VXLAN, + interface::admin_state_t::UP) + , m_tep(src, dst, vni) +{ +} + +vxlan_tunnel::vxlan_tunnel(const vxlan_tunnel& o) + : interface(o) + , m_tep(o.m_tep) +{ +} + +const handle_t& +vxlan_tunnel::handle() const +{ + return (m_hdl.data()); +} + +void +vxlan_tunnel::sweep() +{ + if (m_hdl) { + HW::enqueue(new delete_cmd(m_hdl, m_tep)); + } + HW::write(); +} + +void +vxlan_tunnel::replay() +{ + if (m_hdl) { + HW::enqueue(new create_cmd(m_hdl, name(), m_tep)); + } +} + +vxlan_tunnel::~vxlan_tunnel() +{ + sweep(); + + /* + * release from both DBs + */ + release(); + m_db.release(m_tep, this); +} + +std::string +vxlan_tunnel::to_string() const +{ + std::ostringstream s; + s << "vxlan-tunnel: " << m_hdl.to_string() << " " << m_tep.to_string(); + + return (s.str()); +} + +void +vxlan_tunnel::update(const vxlan_tunnel& desired) +{ + /* + * the desired state is always that the interface should be created + */ + if (!m_hdl) { + HW::enqueue(new create_cmd(m_hdl, name(), m_tep)); + } +} + +std::shared_ptr<vxlan_tunnel> +vxlan_tunnel::find_or_add(const vxlan_tunnel& temp) +{ + /* + * a VXLAN tunnel needs to be in both the interface-find-by-name + * and the vxlan_tunnel-find-by-endpoint singular databases + */ + std::shared_ptr<vxlan_tunnel> sp; + + sp = m_db.find_or_add(temp.m_tep, temp); + + interface::m_db.add(temp.name(), sp); + + return (sp); +} + +std::shared_ptr<vxlan_tunnel> +vxlan_tunnel::singular() const +{ + return (find_or_add(*this)); +} + +std::shared_ptr<interface> +vxlan_tunnel::singular_i() const +{ + return find_or_add(*this); +} + +void +vxlan_tunnel::dump(std::ostream& os) +{ + m_db.dump(os); +} + +void +vxlan_tunnel::event_handler::handle_populate(const client_db::key_t& key) +{ + /* + * dump VPP current states + */ + std::shared_ptr<vxlan_tunnel::dump_cmd> cmd(new vxlan_tunnel::dump_cmd()); + + HW::enqueue(cmd); + HW::write(); + + for (auto& record : *cmd) { + auto& payload = record.get_payload(); + handle_t hdl(payload.sw_if_index); + boost::asio::ip::address src = + from_bytes(payload.is_ipv6, payload.src_address); + boost::asio::ip::address dst = + from_bytes(payload.is_ipv6, payload.dst_address); + + vxlan_tunnel vt(hdl, src, dst, payload.vni); + + VOM_LOG(log_level_t::DEBUG) << "dump: " << vt.to_string(); + + OM::commit(key, vt); + } +} + +vxlan_tunnel::event_handler::event_handler() +{ + OM::register_listener(this); + inspect::register_handler({ "vxlan" }, "VXLAN Tunnels", this); +} + +void +vxlan_tunnel::event_handler::handle_replay() +{ + // replay is handled from the interface DB +} + +dependency_t +vxlan_tunnel::event_handler::order() const +{ + return (dependency_t::TUNNEL); +} + +void +vxlan_tunnel::event_handler::show(std::ostream& os) +{ + m_db.dump(os); +} +} +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "mozilla") + * End: + */ |