From b6a47953973f7c94239c394b649100e91bdb2152 Mon Sep 17 00:00:00 2001 From: Neale Ranns Date: Wed, 21 Nov 2018 05:44:35 -0800 Subject: GBP: l3-out subnets Change-Id: Id4a20066fc5be716c61a497dfcb4d00dc1dbb28d Signed-off-by: Neale Ranns --- extras/vom/vom/CMakeLists.txt | 3 + extras/vom/vom/gbp_ext_itf.cpp | 193 ++++++++++++++++++++++++++++++++++++ extras/vom/vom/gbp_ext_itf.hpp | 186 ++++++++++++++++++++++++++++++++++ extras/vom/vom/gbp_ext_itf_cmds.cpp | 135 +++++++++++++++++++++++++ extras/vom/vom/gbp_ext_itf_cmds.hpp | 134 +++++++++++++++++++++++++ extras/vom/vom/gbp_subnet.cpp | 21 ++++ extras/vom/vom/gbp_subnet.hpp | 14 ++- 7 files changed, 685 insertions(+), 1 deletion(-) create mode 100644 extras/vom/vom/gbp_ext_itf.cpp create mode 100644 extras/vom/vom/gbp_ext_itf.hpp create mode 100644 extras/vom/vom/gbp_ext_itf_cmds.cpp create mode 100644 extras/vom/vom/gbp_ext_itf_cmds.hpp (limited to 'extras/vom') diff --git a/extras/vom/vom/CMakeLists.txt b/extras/vom/vom/CMakeLists.txt index 7413df8d834..f68a7409362 100644 --- a/extras/vom/vom/CMakeLists.txt +++ b/extras/vom/vom/CMakeLists.txt @@ -76,6 +76,8 @@ if(GBP_FILE) gbp_endpoint.cpp gbp_endpoint_group_cmds.cpp gbp_endpoint_group.cpp + gbp_ext_itf.cpp + gbp_ext_itf_cmds.cpp gbp_recirc_cmds.cpp gbp_recirc.cpp gbp_route_domain_cmds.cpp @@ -196,6 +198,7 @@ if(GBP_FILE) gbp_bridge_domain.hpp gbp_endpoint.hpp gbp_endpoint_group.hpp + gbp_ext_itf.hpp gbp_recirc.hpp gbp_route_domain.hpp gbp_rule.hpp diff --git a/extras/vom/vom/gbp_ext_itf.cpp b/extras/vom/vom/gbp_ext_itf.cpp new file mode 100644 index 00000000000..4b7302ddaaa --- /dev/null +++ b/extras/vom/vom/gbp_ext_itf.cpp @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2018 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/gbp_ext_itf.hpp" +#include "vom/gbp_ext_itf_cmds.hpp" +#include "vom/singular_db_funcs.hpp" + +namespace VOM { + +singular_db gbp_ext_itf::m_db; + +gbp_ext_itf::event_handler gbp_ext_itf::m_evh; + +gbp_ext_itf::gbp_ext_itf(const interface& itf, + const gbp_bridge_domain& gbd, + const gbp_route_domain& grd) + : m_hw(false) + , m_itf(itf.singular()) + , m_bd(gbd.singular()) + , m_rd(grd.singular()) +{ +} + +gbp_ext_itf::gbp_ext_itf(const gbp_ext_itf& gbpe) + : m_hw(gbpe.m_hw) + , m_itf(gbpe.m_itf) + , m_bd(gbpe.m_bd) + , m_rd(gbpe.m_rd) +{ +} + +gbp_ext_itf::~gbp_ext_itf() +{ + sweep(); + m_db.release(key(), this); +} + +const gbp_ext_itf::key_t +gbp_ext_itf::key() const +{ + return (m_itf->key()); +} + +const handle_t& +gbp_ext_itf::handle() const +{ + return m_itf->handle(); +} + +bool +gbp_ext_itf::operator==(const gbp_ext_itf& gei) const +{ + return ((key() == gei.key()) && (m_itf == gei.m_itf) && (m_rd == gei.m_rd) && + (m_bd == gei.m_bd)); +} + +void +gbp_ext_itf::sweep() +{ + if (m_hw) { + HW::enqueue(new gbp_ext_itf_cmds::delete_cmd(m_hw, m_itf->handle())); + } + HW::write(); +} + +void +gbp_ext_itf::replay() +{ + if (m_hw) { + HW::enqueue(new gbp_ext_itf_cmds::create_cmd(m_hw, m_itf->handle(), + m_bd->id(), m_rd->id())); + } +} + +std::string +gbp_ext_itf::to_string() const +{ + std::ostringstream s; + s << "gbp-ext_itf:[" << m_itf->to_string() << ", " << m_bd->to_string() + << ", " << m_rd->to_string() << "]"; + + return (s.str()); +} + +void +gbp_ext_itf::update(const gbp_ext_itf& r) +{ + if (rc_t::OK != m_hw.rc()) { + HW::enqueue(new gbp_ext_itf_cmds::create_cmd(m_hw, m_itf->handle(), + m_bd->id(), m_rd->id())); + } +} + +std::shared_ptr +gbp_ext_itf::find_or_add(const gbp_ext_itf& temp) +{ + return (m_db.find_or_add(temp.key(), temp)); +} + +std::shared_ptr +gbp_ext_itf::find(const key_t& k) +{ + return (m_db.find(k)); +} + +std::shared_ptr +gbp_ext_itf::singular() const +{ + return find_or_add(*this); +} + +void +gbp_ext_itf::dump(std::ostream& os) +{ + db_dump(m_db, os); +} + +gbp_ext_itf::event_handler::event_handler() +{ + OM::register_listener(this); + inspect::register_handler({ "gbp-ext-itf" }, "GBP External-Itfs", this); +} + +void +gbp_ext_itf::event_handler::handle_replay() +{ + m_db.replay(); +} + +void +gbp_ext_itf::event_handler::handle_populate(const client_db::key_t& key) +{ + std::shared_ptr cmd = + std::make_shared(); + + HW::enqueue(cmd); + HW::write(); + + for (auto& record : *cmd) { + auto& payload = record.get_payload(); + + std::shared_ptr itf = + interface::find(payload.ext_itf.sw_if_index); + std::shared_ptr gbd = + gbp_bridge_domain::find(payload.ext_itf.bd_id); + std::shared_ptr grd = + gbp_route_domain::find(payload.ext_itf.rd_id); + + VOM_LOG(log_level_t::DEBUG) << "data: [" << payload.ext_itf.sw_if_index + << ", " << payload.ext_itf.bd_id << ", " + << payload.ext_itf.rd_id << "]"; + + if (itf && gbd && grd) { + gbp_ext_itf ext_itf(*itf, *gbd, *grd); + OM::commit(key, ext_itf); + + VOM_LOG(log_level_t::DEBUG) << "read: " << ext_itf.to_string(); + } + } +} + +dependency_t +gbp_ext_itf::event_handler::order() const +{ + return (dependency_t::BINDING); +} + +void +gbp_ext_itf::event_handler::show(std::ostream& os) +{ + db_dump(m_db, os); +} +} // namespace VOM + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "mozilla") + * End: + */ diff --git a/extras/vom/vom/gbp_ext_itf.hpp b/extras/vom/vom/gbp_ext_itf.hpp new file mode 100644 index 00000000000..20d9b6eff9b --- /dev/null +++ b/extras/vom/vom/gbp_ext_itf.hpp @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2018 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. + */ + +#ifndef __VOM_GBP_EXT_ITF_H__ +#define __VOM_GBP_EXT_ITF_H__ + +#include "vom/gbp_bridge_domain.hpp" +#include "vom/gbp_route_domain.hpp" +#include "vom/interface.hpp" +#include "vom/singular_db.hpp" + +namespace VOM { +/** + * A enternal interface for GBP + */ +class gbp_ext_itf : public object_base +{ +public: + /** + * The key for a GBP ext_itf interface + */ + typedef interface::key_t key_t; + + /** + * Construct a GBP ext_itf + */ + gbp_ext_itf(const interface& itf, + const gbp_bridge_domain& gbd, + const gbp_route_domain& grd); + + /** + * Copy Construct + */ + gbp_ext_itf(const gbp_ext_itf& r); + + /** + * Destructor + */ + ~gbp_ext_itf(); + + /** + * Return the object's key + */ + const key_t key() const; + + /** + * comparison operator + */ + bool operator==(const gbp_ext_itf& bdae) const; + + /** + * Return the matching 'singular instance' + */ + std::shared_ptr singular() const; + + /** + * Find the instnace of the ext_itf interface in the OM + */ + static std::shared_ptr find(const key_t& k); + + /** + * Dump all bridge_domain-doamin into the stream provided + */ + static void dump(std::ostream& os); + + /** + * replay the object to create it in hardware + */ + void replay(void); + + /** + * Convert to string for debugging + */ + std::string to_string() const; + + /** + * return the ext_itfulation interface's handle + */ + const handle_t& handle() const; + +private: + /** + * Class definition for listeners to OM events + */ + class event_handler : public OM::listener, public inspect::command_handler + { + public: + event_handler(); + virtual ~event_handler() = default; + + /** + * Handle a populate event + */ + void handle_populate(const client_db::key_t& key); + + /** + * Handle a replay event + */ + void handle_replay(); + + /** + * Show the object in the Singular DB + */ + void show(std::ostream& os); + + /** + * Get the sortable Id of the listener + */ + dependency_t order() const; + }; + + /** + * event_handler to register with OM + */ + static event_handler m_evh; + + /** + * Commit the acculmulated changes into VPP. i.e. to a 'HW" write. + */ + void update(const gbp_ext_itf& obj); + + /** + * Find or add the instnace of the bridge_domain domain in the OM + */ + static std::shared_ptr find_or_add(const gbp_ext_itf& temp); + + /* + * It's the VPPHW class that updates the objects in HW + */ + friend class OM; + + /** + * It's the singular_db class that calls replay() + */ + friend class singular_db; + + /** + * Sweep/reap the object if still stale + */ + void sweep(void); + + /** + * HW configuration for the result of creating the ext_itf + */ + HW::item m_hw; + + /** + * The interface the ext_itf is attached to. + */ + std::shared_ptr m_itf; + + /** + * The BD & RD the ext_itf is in + */ + std::shared_ptr m_bd; + std::shared_ptr m_rd; + + /** + * A map of all bridge_domains + */ + static singular_db m_db; +}; + +}; // namespace VOM + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "mozilla") + * End: + */ + +#endif diff --git a/extras/vom/vom/gbp_ext_itf_cmds.cpp b/extras/vom/vom/gbp_ext_itf_cmds.cpp new file mode 100644 index 00000000000..b2090ea0fa5 --- /dev/null +++ b/extras/vom/vom/gbp_ext_itf_cmds.cpp @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2018 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/gbp_ext_itf_cmds.hpp" + +namespace VOM { +namespace gbp_ext_itf_cmds { + +create_cmd::create_cmd(HW::item& item, + const handle_t& itf, + uint32_t bd_id, + uint32_t rd_id) + : rpc_cmd(item) + , m_itf(itf) + , m_bd_id(bd_id) + , m_rd_id(rd_id) +{ +} + +bool +create_cmd::operator==(const create_cmd& other) const +{ + return ((m_itf == other.m_itf) && (m_bd_id == other.m_bd_id) && + (m_rd_id == other.m_rd_id)); +} + +rc_t +create_cmd::issue(connection& con) +{ + msg_t req(con.ctx(), std::ref(*this)); + + auto& payload = req.get_request().get_payload(); + payload.is_add = 1; + payload.ext_itf.sw_if_index = m_itf.value(); + payload.ext_itf.bd_id = m_bd_id; + payload.ext_itf.rd_id = m_rd_id; + + VAPI_CALL(req.execute()); + + return (wait()); +} + +std::string +create_cmd::to_string() const +{ + std::ostringstream s; + s << "gbp-ext_itf-create: " << m_hw_item.to_string() << " itf:" << m_itf + << " bd-id:" << m_bd_id << " rd-id:" << m_rd_id; + + return (s.str()); +} + +delete_cmd::delete_cmd(HW::item& item, const handle_t& itf) + : rpc_cmd(item) + , m_itf(itf) +{ +} + +bool +delete_cmd::operator==(const delete_cmd& other) const +{ + return (m_itf == other.m_itf); +} + +rc_t +delete_cmd::issue(connection& con) +{ + msg_t req(con.ctx(), std::ref(*this)); + + auto& payload = req.get_request().get_payload(); + payload.is_add = 0; + payload.ext_itf.sw_if_index = m_itf.value(); + payload.ext_itf.bd_id = ~0; + payload.ext_itf.rd_id = ~0; + + VAPI_CALL(req.execute()); + + return (wait()); +} + +std::string +delete_cmd::to_string() const +{ + std::ostringstream s; + s << "gbp-ext-itf-delete: " << m_hw_item.to_string() << " itf:" << m_itf; + + return (s.str()); +} + +bool +dump_cmd::operator==(const dump_cmd& other) const +{ + return (true); +} + +rc_t +dump_cmd::issue(connection& con) +{ + m_dump.reset(new msg_t(con.ctx(), std::ref(*this))); + + VAPI_CALL(m_dump->execute()); + + wait(); + + return rc_t::OK; +} + +std::string +dump_cmd::to_string() const +{ + return ("gbp-ext-itf-dump"); +} + +}; // namespace gbp_ext_itf_cmds +}; // namespace VOM + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "mozilla") + * End: + */ diff --git a/extras/vom/vom/gbp_ext_itf_cmds.hpp b/extras/vom/vom/gbp_ext_itf_cmds.hpp new file mode 100644 index 00000000000..51052b9a360 --- /dev/null +++ b/extras/vom/vom/gbp_ext_itf_cmds.hpp @@ -0,0 +1,134 @@ +/* + * 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. + */ + +#ifndef __VOM_GBP_EXT_ITF_CMDS_H__ +#define __VOM_GBP_EXT_ITF_CMDS_H__ + +#include "vom/dump_cmd.hpp" +#include "vom/gbp_ext_itf.hpp" + +#include + +namespace VOM { +namespace gbp_ext_itf_cmds { + +/** +* A command class that creates or updates the GBP ext_itf +*/ +class create_cmd : public rpc_cmd, vapi::Gbp_ext_itf_add_del> +{ +public: + /** + * Constructor + */ + create_cmd(HW::item& item, + const handle_t& itf, + uint32_t bd_id, + uint32_t rd_id); + + /** + * Issue the command to VPP/HW + */ + rc_t issue(connection& con); + + /** + * convert to string format for debug purposes + */ + std::string to_string() const; + + /** + * Comparison operator - only used for UT + */ + bool operator==(const create_cmd& i) const; + +private: + const handle_t m_itf; + const uint32_t m_bd_id; + const uint32_t m_rd_id; +}; + +/** + * A cmd class that deletes a GBP ext_itf + */ +class delete_cmd : public rpc_cmd, vapi::Gbp_ext_itf_add_del> +{ +public: + /** + * Constructor + */ + delete_cmd(HW::item& item, const handle_t& itf); + + /** + * Issue the command to VPP/HW + */ + rc_t issue(connection& con); + + /** + * convert to string format for debug purposes + */ + std::string to_string() const; + + /** + * Comparison operator - only used for UT + */ + bool operator==(const delete_cmd& i) const; + +private: + const handle_t m_itf; +}; + +/** + * A cmd class that Dumps all the GBP ext_itfs + */ +class dump_cmd : public VOM::dump_cmd +{ +public: + /** + * Constructor + */ + dump_cmd() = default; + + /** + * Issue the command to VPP/HW + */ + rc_t issue(connection& con); + /** + * convert to string format for debug purposes + */ + std::string to_string() const; + + /** + * Comparison operator - only used for UT + */ + bool operator==(const dump_cmd& i) const; + +private: + /** + * HW reutrn code + */ + HW::item item; +}; +}; // namespace gbp_ext_itf_cmds +}; // namespace VOM + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "mozilla") + * End: + */ + +#endif diff --git a/extras/vom/vom/gbp_subnet.cpp b/extras/vom/vom/gbp_subnet.cpp index 2221c616dbb..8404dcd2e65 100644 --- a/extras/vom/vom/gbp_subnet.cpp +++ b/extras/vom/vom/gbp_subnet.cpp @@ -62,6 +62,18 @@ gbp_subnet::gbp_subnet(const gbp_route_domain& rd, { } +gbp_subnet::gbp_subnet(const gbp_route_domain& rd, + const route::prefix_t& prefix, + const gbp_endpoint_group& epg) + : m_hw(false) + , m_rd(rd.singular()) + , m_prefix(prefix) + , m_type(type_t::L3_OUT) + , m_recirc(nullptr) + , m_epg(epg.singular()) +{ +} + gbp_subnet::gbp_subnet(const gbp_subnet& o) : m_hw(o.m_hw) , m_rd(o.m_rd) @@ -215,6 +227,15 @@ gbp_subnet::event_handler::handle_populate(const client_db::key_t& key) VOM_LOG(log_level_t::DEBUG) << "read: " << gs.to_string(); break; } + case GBP_API_SUBNET_L3_OUT: { + std::shared_ptr epg = + gbp_endpoint_group::find(payload.subnet.epg_id); + + gbp_subnet gs(*rd, pfx, *epg); + OM::commit(key, gs); + VOM_LOG(log_level_t::DEBUG) << "read: " << gs.to_string(); + break; + } case GBP_API_SUBNET_STITCHED_EXTERNAL: { std::shared_ptr itf = interface::find(payload.subnet.sw_if_index); diff --git a/extras/vom/vom/gbp_subnet.hpp b/extras/vom/vom/gbp_subnet.hpp index e08f1a25e11..f18aa01431e 100644 --- a/extras/vom/vom/gbp_subnet.hpp +++ b/extras/vom/vom/gbp_subnet.hpp @@ -53,6 +53,11 @@ public: */ const static type_t TRANSPORT; + /** + * A transport subnet, sent via the RD's UU-fwd interface + */ + const static type_t L3_OUT; + private: type_t(int v, const std::string s); }; @@ -65,13 +70,20 @@ public: const type_t& type); /** - * Construct an external GBP subnet + * Construct an stitched external GBP subnet */ gbp_subnet(const gbp_route_domain& rd, const route::prefix_t& prefix, const gbp_recirc& recirc, const gbp_endpoint_group& epg); + /** + * Construct an l3-out GBP subnet + */ + gbp_subnet(const gbp_route_domain& rd, + const route::prefix_t& prefix, + const gbp_endpoint_group& epg); + /** * Copy Construct */ -- cgit 1.2.3-korg