GBP Endpoint Learning
Learning GBP endpoints over vxlan-gbp tunnels Change-Id: I1db9fda5a16802d9ad8b4efd4e475614f3b21502 Signed-off-by: Neale Ranns <neale.ranns@cisco.com>
This commit is contained in:

committed by
Damjan Marion

parent
c3df1e9a0a
commit
93cc3ee3b3
@ -68,16 +68,22 @@ endif()
|
||||
|
||||
if(GBP_FILE)
|
||||
list(APPEND VOM_SOURCES
|
||||
gbp_recirc_cmds.cpp
|
||||
gbp_recirc.cpp
|
||||
gbp_subnet_cmds.cpp
|
||||
gbp_subnet.cpp
|
||||
gbp_contract_cmds.cpp
|
||||
gbp_contract.cpp
|
||||
gbp_bridge_domain_cmds.cpp
|
||||
gbp_bridge_domain.cpp
|
||||
gbp_endpoint_cmds.cpp
|
||||
gbp_endpoint.cpp
|
||||
gbp_endpoint_group_cmds.cpp
|
||||
gbp_endpoint_group.cpp
|
||||
gbp_contract_cmds.cpp
|
||||
gbp_contract.cpp
|
||||
gbp_recirc_cmds.cpp
|
||||
gbp_recirc.cpp
|
||||
gbp_route_domain_cmds.cpp
|
||||
gbp_route_domain.cpp
|
||||
gbp_subnet_cmds.cpp
|
||||
gbp_subnet.cpp
|
||||
gbp_vxlan.cpp
|
||||
gbp_vxlan_cmds.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
|
232
extras/vom/vom/gbp_bridge_domain.cpp
Normal file
232
extras/vom/vom/gbp_bridge_domain.cpp
Normal file
@ -0,0 +1,232 @@
|
||||
/*
|
||||
* 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/gbp_bridge_domain.hpp"
|
||||
#include "vom/gbp_bridge_domain_cmds.hpp"
|
||||
#include "vom/interface.hpp"
|
||||
#include "vom/l2_binding.hpp"
|
||||
#include "vom/singular_db_funcs.hpp"
|
||||
|
||||
namespace VOM {
|
||||
|
||||
/**
|
||||
* A DB of al the interfaces, key on the name
|
||||
*/
|
||||
singular_db<uint32_t, gbp_bridge_domain> gbp_bridge_domain::m_db;
|
||||
|
||||
gbp_bridge_domain::event_handler gbp_bridge_domain::m_evh;
|
||||
|
||||
/**
|
||||
* Construct a new object matching the desried state
|
||||
*/
|
||||
gbp_bridge_domain::gbp_bridge_domain(const bridge_domain& bd)
|
||||
: m_id(bd.id())
|
||||
, m_bd(bd.singular())
|
||||
{
|
||||
}
|
||||
|
||||
gbp_bridge_domain::gbp_bridge_domain(const bridge_domain& bd,
|
||||
const interface& bvi,
|
||||
const interface& uu_fwd)
|
||||
: m_id(bd.id())
|
||||
, m_bd(bd.singular())
|
||||
, m_bvi(bvi.singular())
|
||||
, m_uu_fwd(uu_fwd.singular())
|
||||
{
|
||||
}
|
||||
|
||||
gbp_bridge_domain::gbp_bridge_domain(const gbp_bridge_domain& bd)
|
||||
: m_id(bd.id())
|
||||
, m_bd(bd.m_bd)
|
||||
{
|
||||
}
|
||||
|
||||
const gbp_bridge_domain::key_t
|
||||
gbp_bridge_domain::key() const
|
||||
{
|
||||
return (m_bd->key());
|
||||
}
|
||||
|
||||
uint32_t
|
||||
gbp_bridge_domain::id() const
|
||||
{
|
||||
return (m_bd->id());
|
||||
}
|
||||
|
||||
bool
|
||||
gbp_bridge_domain::operator==(const gbp_bridge_domain& b) const
|
||||
{
|
||||
bool equal = true;
|
||||
|
||||
if (m_bvi && b.m_bvi)
|
||||
equal &= (m_bvi->key() == b.m_bvi->key());
|
||||
else if (!m_bvi && !b.m_bvi)
|
||||
;
|
||||
else
|
||||
equal = false;
|
||||
|
||||
if (m_uu_fwd && b.m_uu_fwd)
|
||||
equal &= (m_uu_fwd->key() == b.m_uu_fwd->key());
|
||||
else if (!m_uu_fwd && !b.m_uu_fwd)
|
||||
;
|
||||
else
|
||||
equal = false;
|
||||
|
||||
return ((m_bd->key() == b.m_bd->key()) && equal);
|
||||
}
|
||||
|
||||
void
|
||||
gbp_bridge_domain::sweep()
|
||||
{
|
||||
if (rc_t::OK == m_id.rc()) {
|
||||
HW::enqueue(new gbp_bridge_domain_cmds::delete_cmd(m_id));
|
||||
}
|
||||
HW::write();
|
||||
}
|
||||
|
||||
void
|
||||
gbp_bridge_domain::replay()
|
||||
{
|
||||
if (rc_t::OK == m_id.rc()) {
|
||||
if (m_bvi && m_uu_fwd)
|
||||
HW::enqueue(new gbp_bridge_domain_cmds::create_cmd(m_id, m_bvi->handle(),
|
||||
m_uu_fwd->handle()));
|
||||
else
|
||||
HW::enqueue(new gbp_bridge_domain_cmds::create_cmd(
|
||||
m_id, handle_t::INVALID, handle_t::INVALID));
|
||||
}
|
||||
}
|
||||
|
||||
gbp_bridge_domain::~gbp_bridge_domain()
|
||||
{
|
||||
sweep();
|
||||
|
||||
// not in the DB anymore.
|
||||
m_db.release(m_id.data(), this);
|
||||
}
|
||||
|
||||
std::string
|
||||
gbp_bridge_domain::to_string() const
|
||||
{
|
||||
std::ostringstream s;
|
||||
s << "gbp-bridge-domain:[" << m_bd->to_string() << "]";
|
||||
|
||||
return (s.str());
|
||||
}
|
||||
|
||||
std::shared_ptr<gbp_bridge_domain>
|
||||
gbp_bridge_domain::find(const key_t& key)
|
||||
{
|
||||
return (m_db.find(key));
|
||||
}
|
||||
|
||||
void
|
||||
gbp_bridge_domain::update(const gbp_bridge_domain& desired)
|
||||
{
|
||||
/*
|
||||
* the desired state is always that the interface should be created
|
||||
*/
|
||||
if (rc_t::OK != m_id.rc()) {
|
||||
if (m_bvi && m_uu_fwd)
|
||||
HW::enqueue(new gbp_bridge_domain_cmds::create_cmd(m_id, m_bvi->handle(),
|
||||
m_uu_fwd->handle()));
|
||||
else
|
||||
HW::enqueue(new gbp_bridge_domain_cmds::create_cmd(
|
||||
m_id, handle_t::INVALID, handle_t::INVALID));
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<gbp_bridge_domain>
|
||||
gbp_bridge_domain::find_or_add(const gbp_bridge_domain& temp)
|
||||
{
|
||||
return (m_db.find_or_add(temp.m_id.data(), temp));
|
||||
}
|
||||
|
||||
std::shared_ptr<gbp_bridge_domain>
|
||||
gbp_bridge_domain::singular() const
|
||||
{
|
||||
return find_or_add(*this);
|
||||
}
|
||||
|
||||
void
|
||||
gbp_bridge_domain::dump(std::ostream& os)
|
||||
{
|
||||
db_dump(m_db, os);
|
||||
}
|
||||
|
||||
void
|
||||
gbp_bridge_domain::event_handler::handle_populate(const client_db::key_t& key)
|
||||
{
|
||||
/*
|
||||
* dump VPP Bridge domains
|
||||
*/
|
||||
std::shared_ptr<gbp_bridge_domain_cmds::dump_cmd> cmd =
|
||||
std::make_shared<gbp_bridge_domain_cmds::dump_cmd>();
|
||||
|
||||
HW::enqueue(cmd);
|
||||
HW::write();
|
||||
|
||||
for (auto& record : *cmd) {
|
||||
auto& payload = record.get_payload();
|
||||
|
||||
std::shared_ptr<interface> uu_fwd =
|
||||
interface::find(payload.bd.uu_fwd_sw_if_index);
|
||||
std::shared_ptr<interface> bvi =
|
||||
interface::find(payload.bd.bvi_sw_if_index);
|
||||
|
||||
if (uu_fwd && bvi) {
|
||||
gbp_bridge_domain bd(payload.bd.bd_id, *bvi, *uu_fwd);
|
||||
OM::commit(key, bd);
|
||||
VOM_LOG(log_level_t::DEBUG) << "dump: " << bd.to_string();
|
||||
} else {
|
||||
gbp_bridge_domain bd(payload.bd.bd_id);
|
||||
OM::commit(key, bd);
|
||||
VOM_LOG(log_level_t::DEBUG) << "dump: " << bd.to_string();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gbp_bridge_domain::event_handler::event_handler()
|
||||
{
|
||||
OM::register_listener(this);
|
||||
inspect::register_handler({ "gbd", "gbridge" }, "GBP Bridge Domains", this);
|
||||
}
|
||||
|
||||
void
|
||||
gbp_bridge_domain::event_handler::handle_replay()
|
||||
{
|
||||
m_db.replay();
|
||||
}
|
||||
|
||||
dependency_t
|
||||
gbp_bridge_domain::event_handler::order() const
|
||||
{
|
||||
return (dependency_t::TABLE);
|
||||
}
|
||||
|
||||
void
|
||||
gbp_bridge_domain::event_handler::show(std::ostream& os)
|
||||
{
|
||||
db_dump(m_db, os);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* fd.io coding-style-patch-verification: ON
|
||||
*
|
||||
* Local Variables:
|
||||
* eval: (c-set-style "mozilla")
|
||||
* End:
|
||||
*/
|
183
extras/vom/vom/gbp_bridge_domain.hpp
Normal file
183
extras/vom/vom/gbp_bridge_domain.hpp
Normal file
@ -0,0 +1,183 @@
|
||||
/*
|
||||
* 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_BRIDGE_DOMAIN_H__
|
||||
#define __VOM_GBP_BRIDGE_DOMAIN_H__
|
||||
|
||||
#include "vom/bridge_domain.hpp"
|
||||
#include "vom/interface.hpp"
|
||||
#include "vom/singular_db.hpp"
|
||||
#include "vom/types.hpp"
|
||||
|
||||
namespace VOM {
|
||||
|
||||
/**
|
||||
* A entry in the ARP termination table of a Bridge Domain
|
||||
*/
|
||||
class gbp_bridge_domain : public object_base
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* The key for a bridge_domain is the pari of EPG-IDs
|
||||
*/
|
||||
typedef bridge_domain::key_t key_t;
|
||||
|
||||
/**
|
||||
* Construct a GBP bridge_domain
|
||||
*/
|
||||
gbp_bridge_domain(const bridge_domain& bd);
|
||||
|
||||
gbp_bridge_domain(const bridge_domain& bd,
|
||||
const interface& bvi,
|
||||
const interface& uu_fwd);
|
||||
|
||||
/**
|
||||
* Copy Construct
|
||||
*/
|
||||
gbp_bridge_domain(const gbp_bridge_domain& r);
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~gbp_bridge_domain();
|
||||
|
||||
/**
|
||||
* Return the object's key
|
||||
*/
|
||||
const key_t key() const;
|
||||
|
||||
/**
|
||||
* Return the bridge domain's VPP ID
|
||||
*/
|
||||
uint32_t id() const;
|
||||
|
||||
/**
|
||||
* comparison operator
|
||||
*/
|
||||
bool operator==(const gbp_bridge_domain& bdae) const;
|
||||
|
||||
/**
|
||||
* Return the matching 'singular instance'
|
||||
*/
|
||||
std::shared_ptr<gbp_bridge_domain> singular() const;
|
||||
|
||||
/**
|
||||
* Find the instnace of the bridge_domain domain in the OM
|
||||
*/
|
||||
static std::shared_ptr<gbp_bridge_domain> 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;
|
||||
|
||||
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_bridge_domain& obj);
|
||||
|
||||
/**
|
||||
* Find or add the instance of the bridge_domain domain in the OM
|
||||
*/
|
||||
static std::shared_ptr<gbp_bridge_domain> find_or_add(
|
||||
const gbp_bridge_domain& 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<key_t, gbp_bridge_domain>;
|
||||
|
||||
/**
|
||||
* Sweep/reap the object if still stale
|
||||
*/
|
||||
void sweep(void);
|
||||
|
||||
/**
|
||||
* HW configuration for the result of creating the endpoint
|
||||
*/
|
||||
HW::item<uint32_t> m_id;
|
||||
|
||||
std::shared_ptr<bridge_domain> m_bd;
|
||||
std::shared_ptr<interface> m_bvi;
|
||||
std::shared_ptr<interface> m_uu_fwd;
|
||||
|
||||
/**
|
||||
* A map of all bridge_domains
|
||||
*/
|
||||
static singular_db<key_t, gbp_bridge_domain> m_db;
|
||||
};
|
||||
|
||||
}; // namespace
|
||||
|
||||
/*
|
||||
* fd.io coding-style-patch-verification: ON
|
||||
*
|
||||
* Local Variables:
|
||||
* eval: (c-set-style "mozilla")
|
||||
* End:
|
||||
*/
|
||||
|
||||
#endif
|
133
extras/vom/vom/gbp_bridge_domain_cmds.cpp
Normal file
133
extras/vom/vom/gbp_bridge_domain_cmds.cpp
Normal file
@ -0,0 +1,133 @@
|
||||
/*
|
||||
* 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/gbp_bridge_domain_cmds.hpp"
|
||||
|
||||
namespace VOM {
|
||||
namespace gbp_bridge_domain_cmds {
|
||||
|
||||
create_cmd::create_cmd(HW::item<uint32_t>& item,
|
||||
const handle_t bvi,
|
||||
const handle_t uu_fwd)
|
||||
: rpc_cmd(item)
|
||||
, m_bvi(bvi)
|
||||
, m_uu_fwd(uu_fwd)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
create_cmd::operator==(const create_cmd& other) const
|
||||
{
|
||||
return ((m_hw_item.data() == other.m_hw_item.data()) &&
|
||||
(m_bvi == other.m_bvi) && (m_uu_fwd == other.m_uu_fwd));
|
||||
}
|
||||
|
||||
rc_t
|
||||
create_cmd::issue(connection& con)
|
||||
{
|
||||
msg_t req(con.ctx(), std::ref(*this));
|
||||
|
||||
auto& payload = req.get_request().get_payload();
|
||||
|
||||
payload.bd.bd_id = m_hw_item.data();
|
||||
payload.bd.bvi_sw_if_index = m_bvi.value();
|
||||
payload.bd.uu_fwd_sw_if_index = m_uu_fwd.value();
|
||||
|
||||
VAPI_CALL(req.execute());
|
||||
|
||||
return (wait());
|
||||
}
|
||||
|
||||
std::string
|
||||
create_cmd::to_string() const
|
||||
{
|
||||
std::ostringstream s;
|
||||
s << "gbp-bridge-domain: " << m_hw_item.to_string()
|
||||
<< " bvi:" << m_bvi.to_string() << " uu-fwd:" << m_uu_fwd.to_string();
|
||||
|
||||
return (s.str());
|
||||
}
|
||||
|
||||
delete_cmd::delete_cmd(HW::item<uint32_t>& item)
|
||||
: rpc_cmd(item)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
delete_cmd::operator==(const delete_cmd& other) const
|
||||
{
|
||||
return (m_hw_item.data() == other.m_hw_item.data());
|
||||
}
|
||||
|
||||
rc_t
|
||||
delete_cmd::issue(connection& con)
|
||||
{
|
||||
msg_t req(con.ctx(), std::ref(*this));
|
||||
|
||||
auto& payload = req.get_request().get_payload();
|
||||
|
||||
payload.bd_id = m_hw_item.data();
|
||||
|
||||
VAPI_CALL(req.execute());
|
||||
|
||||
wait();
|
||||
m_hw_item.set(rc_t::NOOP);
|
||||
|
||||
return rc_t::OK;
|
||||
}
|
||||
|
||||
std::string
|
||||
delete_cmd::to_string() const
|
||||
{
|
||||
std::ostringstream s;
|
||||
s << "gbp-bridge-domain: " << m_hw_item.to_string();
|
||||
|
||||
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-bridge-domain-dump");
|
||||
}
|
||||
|
||||
}; // namespace gbp_bridge_domain_cmds
|
||||
}; // namespace VOM
|
||||
|
||||
/*
|
||||
* fd.io coding-style-patch-verification: ON
|
||||
*
|
||||
* Local Variables:
|
||||
* eval: (c-set-style "mozilla")
|
||||
* End:
|
||||
*/
|
131
extras/vom/vom/gbp_bridge_domain_cmds.hpp
Normal file
131
extras/vom/vom/gbp_bridge_domain_cmds.hpp
Normal file
@ -0,0 +1,131 @@
|
||||
/*
|
||||
* 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_BRIDGE_DOMAIN_CMDS_H__
|
||||
#define __VOM_GBP_BRIDGE_DOMAIN_CMDS_H__
|
||||
|
||||
#include "vom/dump_cmd.hpp"
|
||||
#include "vom/gbp_bridge_domain.hpp"
|
||||
#include "vom/rpc_cmd.hpp"
|
||||
|
||||
#include <vapi/gbp.api.vapi.hpp>
|
||||
|
||||
namespace VOM {
|
||||
namespace gbp_bridge_domain_cmds {
|
||||
/**
|
||||
* A command class that creates an Bridge-Domain
|
||||
*/
|
||||
class create_cmd
|
||||
: public rpc_cmd<HW::item<uint32_t>, vapi::Gbp_bridge_domain_add>
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
create_cmd(HW::item<uint32_t>& item,
|
||||
const handle_t bvi,
|
||||
const handle_t uu_fwd);
|
||||
|
||||
/**
|
||||
* 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_bvi;
|
||||
const handle_t m_uu_fwd;
|
||||
};
|
||||
|
||||
/**
|
||||
* A cmd class that Delete an Bridge-Domain
|
||||
*/
|
||||
class delete_cmd
|
||||
: public rpc_cmd<HW::item<uint32_t>, vapi::Gbp_bridge_domain_del>
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
delete_cmd(HW::item<uint32_t>& item);
|
||||
|
||||
/**
|
||||
* 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;
|
||||
};
|
||||
|
||||
/**
|
||||
* A cmd class that Dumps all the bridge domains
|
||||
*/
|
||||
class dump_cmd : public VOM::dump_cmd<vapi::Gbp_bridge_domain_dump>
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
dump_cmd() = default;
|
||||
dump_cmd(const dump_cmd& d) = 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<bool> item;
|
||||
};
|
||||
|
||||
}; // gbp_bridge_domain_cmds
|
||||
}; // VOM
|
||||
|
||||
/*
|
||||
* fd.io coding-style-patch-verification: ON
|
||||
*
|
||||
* Local Variables:
|
||||
* eval: (c-set-style "mozilla")
|
||||
* End:
|
||||
*/
|
||||
|
||||
#endif
|
@ -91,7 +91,7 @@ private:
|
||||
};
|
||||
|
||||
/**
|
||||
* A cmd class that Dumps all the GBP endpoints
|
||||
* A cmd class that Dumps all the GBP contracts
|
||||
*/
|
||||
class dump_cmd : public VOM::dump_cmd<vapi::Gbp_contract_dump>
|
||||
{
|
||||
|
@ -26,8 +26,8 @@ gbp_endpoint_group::event_handler gbp_endpoint_group::m_evh;
|
||||
|
||||
gbp_endpoint_group::gbp_endpoint_group(epg_id_t epg_id,
|
||||
const interface& itf,
|
||||
const route_domain& rd,
|
||||
const bridge_domain& bd)
|
||||
const gbp_route_domain& rd,
|
||||
const gbp_bridge_domain& bd)
|
||||
: m_hw(false)
|
||||
, m_epg_id(epg_id)
|
||||
, m_itf(itf.singular())
|
||||
@ -64,10 +64,10 @@ gbp_endpoint_group::id() const
|
||||
}
|
||||
|
||||
bool
|
||||
gbp_endpoint_group::operator==(const gbp_endpoint_group& gbpe) const
|
||||
gbp_endpoint_group::operator==(const gbp_endpoint_group& gg) const
|
||||
{
|
||||
return (key() == gbpe.key() && (m_itf == gbpe.m_itf) && (m_rd == gbpe.m_rd) &&
|
||||
(m_bd == gbpe.m_bd));
|
||||
return (key() == gg.key() && (m_itf == gg.m_itf) && (m_rd == gg.m_rd) &&
|
||||
(m_bd == gg.m_bd));
|
||||
}
|
||||
|
||||
void
|
||||
@ -84,7 +84,7 @@ gbp_endpoint_group::replay()
|
||||
{
|
||||
if (m_hw) {
|
||||
HW::enqueue(new gbp_endpoint_group_cmds::create_cmd(
|
||||
m_hw, m_epg_id, m_bd->id(), m_rd->table_id(), m_itf->handle()));
|
||||
m_hw, m_epg_id, m_bd->id(), m_rd->id(), m_itf->handle()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -104,7 +104,7 @@ gbp_endpoint_group::update(const gbp_endpoint_group& r)
|
||||
{
|
||||
if (rc_t::OK != m_hw.rc()) {
|
||||
HW::enqueue(new gbp_endpoint_group_cmds::create_cmd(
|
||||
m_hw, m_epg_id, m_bd->id(), m_rd->table_id(), m_itf->handle()));
|
||||
m_hw, m_epg_id, m_bd->id(), m_rd->id(), m_itf->handle()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -159,12 +159,13 @@ gbp_endpoint_group::event_handler::handle_populate(const client_db::key_t& key)
|
||||
|
||||
std::shared_ptr<interface> itf =
|
||||
interface::find(payload.epg.uplink_sw_if_index);
|
||||
std::shared_ptr<route_domain> rd =
|
||||
route_domain::find(payload.epg.ip4_table_id);
|
||||
std::shared_ptr<bridge_domain> bd = bridge_domain::find(payload.epg.bd_id);
|
||||
std::shared_ptr<gbp_route_domain> rd =
|
||||
gbp_route_domain::find(payload.epg.rd_id);
|
||||
std::shared_ptr<gbp_bridge_domain> bd =
|
||||
gbp_bridge_domain::find(payload.epg.bd_id);
|
||||
|
||||
VOM_LOG(log_level_t::DEBUG) << "data: [" << payload.epg.uplink_sw_if_index
|
||||
<< ", " << payload.epg.ip4_table_id << ", "
|
||||
<< ", " << payload.epg.rd_id << ", "
|
||||
<< payload.epg.bd_id << "]";
|
||||
|
||||
if (itf && bd && rd) {
|
||||
|
@ -20,8 +20,8 @@
|
||||
#include "vom/singular_db.hpp"
|
||||
#include "vom/types.hpp"
|
||||
|
||||
#include "vom/bridge_domain.hpp"
|
||||
#include "vom/route_domain.hpp"
|
||||
#include "vom/gbp_bridge_domain.hpp"
|
||||
#include "vom/gbp_route_domain.hpp"
|
||||
|
||||
namespace VOM {
|
||||
|
||||
@ -46,8 +46,11 @@ public:
|
||||
*/
|
||||
gbp_endpoint_group(epg_id_t epg_id,
|
||||
const interface& itf,
|
||||
const route_domain& rd,
|
||||
const bridge_domain& bd);
|
||||
const gbp_route_domain& rd,
|
||||
const gbp_bridge_domain& bd);
|
||||
gbp_endpoint_group(epg_id_t epg_id,
|
||||
const gbp_route_domain& rd,
|
||||
const gbp_bridge_domain& bd);
|
||||
|
||||
/**
|
||||
* Copy Construct
|
||||
@ -179,12 +182,12 @@ private:
|
||||
/**
|
||||
* The route-domain the EPG uses
|
||||
*/
|
||||
std::shared_ptr<route_domain> m_rd;
|
||||
std::shared_ptr<gbp_route_domain> m_rd;
|
||||
|
||||
/**
|
||||
* The bridge-domain the EPG uses
|
||||
*/
|
||||
std::shared_ptr<bridge_domain> m_bd;
|
||||
std::shared_ptr<gbp_bridge_domain> m_bd;
|
||||
|
||||
/**
|
||||
* A map of all bridge_domains
|
||||
|
@ -44,12 +44,10 @@ 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.epg.uplink_sw_if_index = m_itf.value();
|
||||
payload.epg.epg_id = m_epg_id;
|
||||
payload.epg.bd_id = m_bd_id;
|
||||
payload.epg.ip4_table_id = m_rd_id;
|
||||
payload.epg.ip6_table_id = m_rd_id;
|
||||
payload.epg.rd_id = m_rd_id;
|
||||
|
||||
VAPI_CALL(req.execute());
|
||||
|
||||
@ -85,8 +83,7 @@ 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.epg.epg_id = m_epg_id;
|
||||
payload.epg_id = m_epg_id;
|
||||
|
||||
VAPI_CALL(req.execute());
|
||||
|
||||
|
@ -27,8 +27,7 @@ namespace gbp_endpoint_group_cmds {
|
||||
/**
|
||||
* A command class that creates or updates the GBP endpoint_group
|
||||
*/
|
||||
class create_cmd
|
||||
: public rpc_cmd<HW::item<bool>, vapi::Gbp_endpoint_group_add_del>
|
||||
class create_cmd : public rpc_cmd<HW::item<bool>, vapi::Gbp_endpoint_group_add>
|
||||
{
|
||||
public:
|
||||
/**
|
||||
@ -65,8 +64,7 @@ private:
|
||||
/**
|
||||
* A cmd class that deletes a GBP endpoint_group
|
||||
*/
|
||||
class delete_cmd
|
||||
: public rpc_cmd<HW::item<bool>, vapi::Gbp_endpoint_group_add_del>
|
||||
class delete_cmd : public rpc_cmd<HW::item<bool>, vapi::Gbp_endpoint_group_del>
|
||||
{
|
||||
public:
|
||||
/**
|
||||
|
232
extras/vom/vom/gbp_route_domain.cpp
Normal file
232
extras/vom/vom/gbp_route_domain.cpp
Normal file
@ -0,0 +1,232 @@
|
||||
/*
|
||||
* 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/gbp_route_domain.hpp"
|
||||
#include "vom/gbp_route_domain_cmds.hpp"
|
||||
#include "vom/interface.hpp"
|
||||
#include "vom/l2_binding.hpp"
|
||||
#include "vom/singular_db_funcs.hpp"
|
||||
|
||||
namespace VOM {
|
||||
|
||||
/**
|
||||
* A DB of al the interfaces, key on the name
|
||||
*/
|
||||
singular_db<uint32_t, gbp_route_domain> gbp_route_domain::m_db;
|
||||
|
||||
gbp_route_domain::event_handler gbp_route_domain::m_evh;
|
||||
|
||||
/**
|
||||
* Construct a new object matching the desried state
|
||||
*/
|
||||
gbp_route_domain::gbp_route_domain(const gbp_route_domain& rd)
|
||||
: m_id(rd.id())
|
||||
, m_rd(rd.m_rd)
|
||||
{
|
||||
}
|
||||
|
||||
gbp_route_domain::gbp_route_domain(const route_domain& rd,
|
||||
const interface& ip4_uu_fwd,
|
||||
const interface& ip6_uu_fwd)
|
||||
: m_id(rd.table_id())
|
||||
, m_rd(rd.singular())
|
||||
, m_ip4_uu_fwd(ip4_uu_fwd.singular())
|
||||
, m_ip6_uu_fwd(ip6_uu_fwd.singular())
|
||||
{
|
||||
}
|
||||
|
||||
gbp_route_domain::gbp_route_domain(const route_domain& rd)
|
||||
: m_id(rd.table_id())
|
||||
, m_rd(rd.singular())
|
||||
{
|
||||
}
|
||||
|
||||
const gbp_route_domain::key_t
|
||||
gbp_route_domain::key() const
|
||||
{
|
||||
return (m_rd->key());
|
||||
}
|
||||
|
||||
uint32_t
|
||||
gbp_route_domain::id() const
|
||||
{
|
||||
return (m_rd->table_id());
|
||||
}
|
||||
|
||||
bool
|
||||
gbp_route_domain::operator==(const gbp_route_domain& b) const
|
||||
{
|
||||
bool equal = true;
|
||||
|
||||
if (m_ip4_uu_fwd && b.m_ip4_uu_fwd)
|
||||
equal &= (m_ip4_uu_fwd->key() == b.m_ip4_uu_fwd->key());
|
||||
else if (!m_ip4_uu_fwd && !b.m_ip4_uu_fwd)
|
||||
;
|
||||
else
|
||||
equal = false;
|
||||
|
||||
if (m_ip6_uu_fwd && b.m_ip6_uu_fwd)
|
||||
equal &= (m_ip6_uu_fwd->key() == b.m_ip6_uu_fwd->key());
|
||||
else if (!m_ip6_uu_fwd && !b.m_ip6_uu_fwd)
|
||||
;
|
||||
else
|
||||
equal = false;
|
||||
|
||||
return ((m_rd->key() == b.m_rd->key()) && equal);
|
||||
}
|
||||
|
||||
void
|
||||
gbp_route_domain::sweep()
|
||||
{
|
||||
if (rc_t::OK == m_id.rc()) {
|
||||
HW::enqueue(new gbp_route_domain_cmds::delete_cmd(m_id));
|
||||
}
|
||||
HW::write();
|
||||
}
|
||||
|
||||
void
|
||||
gbp_route_domain::replay()
|
||||
{
|
||||
if (rc_t::OK == m_id.rc()) {
|
||||
if (m_ip4_uu_fwd && m_ip6_uu_fwd)
|
||||
HW::enqueue(new gbp_route_domain_cmds::create_cmd(
|
||||
m_id, m_ip4_uu_fwd->handle(), m_ip6_uu_fwd->handle()));
|
||||
else
|
||||
HW::enqueue(new gbp_route_domain_cmds::create_cmd(m_id, handle_t::INVALID,
|
||||
handle_t::INVALID));
|
||||
}
|
||||
}
|
||||
|
||||
gbp_route_domain::~gbp_route_domain()
|
||||
{
|
||||
sweep();
|
||||
|
||||
// not in the DB anymore.
|
||||
m_db.release(m_id.data(), this);
|
||||
}
|
||||
|
||||
std::string
|
||||
gbp_route_domain::to_string() const
|
||||
{
|
||||
std::ostringstream s;
|
||||
s << "gbp-route-domain:[" << m_rd->to_string() << "]";
|
||||
|
||||
return (s.str());
|
||||
}
|
||||
|
||||
std::shared_ptr<gbp_route_domain>
|
||||
gbp_route_domain::find(const key_t& key)
|
||||
{
|
||||
return (m_db.find(key));
|
||||
}
|
||||
|
||||
void
|
||||
gbp_route_domain::update(const gbp_route_domain& desired)
|
||||
{
|
||||
/*
|
||||
* the desired state is always that the interface should be created
|
||||
*/
|
||||
if (rc_t::OK != m_id.rc()) {
|
||||
if (m_ip4_uu_fwd && m_ip6_uu_fwd)
|
||||
HW::enqueue(new gbp_route_domain_cmds::create_cmd(
|
||||
m_id, m_ip4_uu_fwd->handle(), m_ip6_uu_fwd->handle()));
|
||||
else
|
||||
HW::enqueue(new gbp_route_domain_cmds::create_cmd(m_id, handle_t::INVALID,
|
||||
handle_t::INVALID));
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<gbp_route_domain>
|
||||
gbp_route_domain::find_or_add(const gbp_route_domain& temp)
|
||||
{
|
||||
return (m_db.find_or_add(temp.m_id.data(), temp));
|
||||
}
|
||||
|
||||
std::shared_ptr<gbp_route_domain>
|
||||
gbp_route_domain::singular() const
|
||||
{
|
||||
return find_or_add(*this);
|
||||
}
|
||||
|
||||
void
|
||||
gbp_route_domain::dump(std::ostream& os)
|
||||
{
|
||||
db_dump(m_db, os);
|
||||
}
|
||||
|
||||
void
|
||||
gbp_route_domain::event_handler::handle_populate(const client_db::key_t& key)
|
||||
{
|
||||
/*
|
||||
* dump VPP Route domains
|
||||
*/
|
||||
std::shared_ptr<gbp_route_domain_cmds::dump_cmd> cmd =
|
||||
std::make_shared<gbp_route_domain_cmds::dump_cmd>();
|
||||
|
||||
HW::enqueue(cmd);
|
||||
HW::write();
|
||||
|
||||
for (auto& record : *cmd) {
|
||||
auto& payload = record.get_payload();
|
||||
|
||||
std::shared_ptr<interface> ip6_uu_fwd =
|
||||
interface::find(payload.rd.ip6_uu_sw_if_index);
|
||||
std::shared_ptr<interface> ip4_uu_fwd =
|
||||
interface::find(payload.rd.ip4_uu_sw_if_index);
|
||||
|
||||
if (ip6_uu_fwd && ip4_uu_fwd) {
|
||||
gbp_route_domain rd(payload.rd.rd_id, *ip4_uu_fwd, *ip6_uu_fwd);
|
||||
OM::commit(key, rd);
|
||||
VOM_LOG(log_level_t::DEBUG) << "dump: " << rd.to_string();
|
||||
} else {
|
||||
gbp_route_domain rd(payload.rd.rd_id);
|
||||
OM::commit(key, rd);
|
||||
VOM_LOG(log_level_t::DEBUG) << "dump: " << rd.to_string();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gbp_route_domain::event_handler::event_handler()
|
||||
{
|
||||
OM::register_listener(this);
|
||||
inspect::register_handler({ "grd", "groute" }, "GBP Route Domains", this);
|
||||
}
|
||||
|
||||
void
|
||||
gbp_route_domain::event_handler::handle_replay()
|
||||
{
|
||||
m_db.replay();
|
||||
}
|
||||
|
||||
dependency_t
|
||||
gbp_route_domain::event_handler::order() const
|
||||
{
|
||||
return (dependency_t::TABLE);
|
||||
}
|
||||
|
||||
void
|
||||
gbp_route_domain::event_handler::show(std::ostream& os)
|
||||
{
|
||||
db_dump(m_db, os);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* fd.io coding-style-patch-verification: ON
|
||||
*
|
||||
* Local Variables:
|
||||
* eval: (c-set-style "mozilla")
|
||||
* End:
|
||||
*/
|
183
extras/vom/vom/gbp_route_domain.hpp
Normal file
183
extras/vom/vom/gbp_route_domain.hpp
Normal file
@ -0,0 +1,183 @@
|
||||
/*
|
||||
* 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_ROUTE_DOMAIN_H__
|
||||
#define __VOM_GBP_ROUTE_DOMAIN_H__
|
||||
|
||||
#include "vom/interface.hpp"
|
||||
#include "vom/route_domain.hpp"
|
||||
#include "vom/singular_db.hpp"
|
||||
#include "vom/types.hpp"
|
||||
|
||||
namespace VOM {
|
||||
|
||||
/**
|
||||
* A entry in the ARP termination table of a Route Domain
|
||||
*/
|
||||
class gbp_route_domain : public object_base
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* The key for a route_domain is the pari of EPG-IDs
|
||||
*/
|
||||
typedef route_domain::key_t key_t;
|
||||
|
||||
/**
|
||||
* Construct a GBP route_domain
|
||||
*/
|
||||
gbp_route_domain(const route_domain& rd);
|
||||
|
||||
gbp_route_domain(const route_domain& rd,
|
||||
const interface& ip4_uu_fwd,
|
||||
const interface& ip6_uu_fwd);
|
||||
|
||||
/**
|
||||
* Copy Construct
|
||||
*/
|
||||
gbp_route_domain(const gbp_route_domain& r);
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~gbp_route_domain();
|
||||
|
||||
/**
|
||||
* Return the object's key
|
||||
*/
|
||||
const key_t key() const;
|
||||
|
||||
/**
|
||||
* Return the route domain's VPP ID
|
||||
*/
|
||||
uint32_t id() const;
|
||||
|
||||
/**
|
||||
* comparison operator
|
||||
*/
|
||||
bool operator==(const gbp_route_domain& rdae) const;
|
||||
|
||||
/**
|
||||
* Return the matching 'singular instance'
|
||||
*/
|
||||
std::shared_ptr<gbp_route_domain> singular() const;
|
||||
|
||||
/**
|
||||
* Find the instnace of the route_domain domain in the OM
|
||||
*/
|
||||
static std::shared_ptr<gbp_route_domain> find(const key_t& k);
|
||||
|
||||
/**
|
||||
* Dump all route_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;
|
||||
|
||||
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_route_domain& obj);
|
||||
|
||||
/**
|
||||
* Find or add the instance of the route_domain domain in the OM
|
||||
*/
|
||||
static std::shared_ptr<gbp_route_domain> find_or_add(
|
||||
const gbp_route_domain& 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<key_t, gbp_route_domain>;
|
||||
|
||||
/**
|
||||
* Sweep/reap the object if still stale
|
||||
*/
|
||||
void sweep(void);
|
||||
|
||||
/**
|
||||
* HW configuration for the result of creating the endpoint
|
||||
*/
|
||||
HW::item<uint32_t> m_id;
|
||||
|
||||
std::shared_ptr<route_domain> m_rd;
|
||||
std::shared_ptr<interface> m_ip4_uu_fwd;
|
||||
std::shared_ptr<interface> m_ip6_uu_fwd;
|
||||
|
||||
/**
|
||||
* A map of all route_domains
|
||||
*/
|
||||
static singular_db<key_t, gbp_route_domain> m_db;
|
||||
};
|
||||
|
||||
}; // namespace
|
||||
|
||||
/*
|
||||
* fd.io coding-style-patch-verification: ON
|
||||
*
|
||||
* Local Variables:
|
||||
* eval: (c-set-style "mozilla")
|
||||
* End:
|
||||
*/
|
||||
|
||||
#endif
|
135
extras/vom/vom/gbp_route_domain_cmds.cpp
Normal file
135
extras/vom/vom/gbp_route_domain_cmds.cpp
Normal file
@ -0,0 +1,135 @@
|
||||
/*
|
||||
* 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/gbp_route_domain_cmds.hpp"
|
||||
|
||||
namespace VOM {
|
||||
namespace gbp_route_domain_cmds {
|
||||
|
||||
create_cmd::create_cmd(HW::item<uint32_t>& item,
|
||||
const handle_t ip4_uu_fwd,
|
||||
const handle_t ip6_uu_fwd)
|
||||
: rpc_cmd(item)
|
||||
, m_ip4_uu_fwd(ip4_uu_fwd)
|
||||
, m_ip6_uu_fwd(ip6_uu_fwd)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
create_cmd::operator==(const create_cmd& other) const
|
||||
{
|
||||
return ((m_hw_item.data() == other.m_hw_item.data()) &&
|
||||
(m_ip4_uu_fwd == other.m_ip4_uu_fwd) &&
|
||||
(m_ip6_uu_fwd == other.m_ip6_uu_fwd));
|
||||
}
|
||||
|
||||
rc_t
|
||||
create_cmd::issue(connection& con)
|
||||
{
|
||||
msg_t req(con.ctx(), std::ref(*this));
|
||||
|
||||
auto& payload = req.get_request().get_payload();
|
||||
|
||||
payload.rd.rd_id = m_hw_item.data();
|
||||
payload.rd.ip4_uu_sw_if_index = m_ip4_uu_fwd.value();
|
||||
payload.rd.ip6_uu_sw_if_index = m_ip6_uu_fwd.value();
|
||||
|
||||
VAPI_CALL(req.execute());
|
||||
|
||||
return (wait());
|
||||
}
|
||||
|
||||
std::string
|
||||
create_cmd::to_string() const
|
||||
{
|
||||
std::ostringstream s;
|
||||
s << "gbp-route-domain: " << m_hw_item.to_string()
|
||||
<< " ip4-uu-fwd:" << m_ip4_uu_fwd.to_string()
|
||||
<< " ip6-uu-fwd:" << m_ip6_uu_fwd.to_string();
|
||||
|
||||
return (s.str());
|
||||
}
|
||||
|
||||
delete_cmd::delete_cmd(HW::item<uint32_t>& item)
|
||||
: rpc_cmd(item)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
delete_cmd::operator==(const delete_cmd& other) const
|
||||
{
|
||||
return (m_hw_item.data() == other.m_hw_item.data());
|
||||
}
|
||||
|
||||
rc_t
|
||||
delete_cmd::issue(connection& con)
|
||||
{
|
||||
msg_t req(con.ctx(), std::ref(*this));
|
||||
|
||||
auto& payload = req.get_request().get_payload();
|
||||
|
||||
payload.rd_id = m_hw_item.data();
|
||||
|
||||
VAPI_CALL(req.execute());
|
||||
|
||||
wait();
|
||||
m_hw_item.set(rc_t::NOOP);
|
||||
|
||||
return rc_t::OK;
|
||||
}
|
||||
|
||||
std::string
|
||||
delete_cmd::to_string() const
|
||||
{
|
||||
std::ostringstream s;
|
||||
s << "gbp-route-domain: " << m_hw_item.to_string();
|
||||
|
||||
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-route-domain-dump");
|
||||
}
|
||||
|
||||
}; // namespace gbp_route_domain_cmds
|
||||
}; // namespace VOM
|
||||
|
||||
/*
|
||||
* fd.io coding-style-patch-verification: ON
|
||||
*
|
||||
* Local Variables:
|
||||
* eval: (c-set-style "mozilla")
|
||||
* End:
|
||||
*/
|
131
extras/vom/vom/gbp_route_domain_cmds.hpp
Normal file
131
extras/vom/vom/gbp_route_domain_cmds.hpp
Normal file
@ -0,0 +1,131 @@
|
||||
/*
|
||||
* 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_ROUTE_DOMAIN_CMDS_H__
|
||||
#define __VOM_GBP_ROUTE_DOMAIN_CMDS_H__
|
||||
|
||||
#include "vom/dump_cmd.hpp"
|
||||
#include "vom/gbp_route_domain.hpp"
|
||||
#include "vom/rpc_cmd.hpp"
|
||||
|
||||
#include <vapi/gbp.api.vapi.hpp>
|
||||
|
||||
namespace VOM {
|
||||
namespace gbp_route_domain_cmds {
|
||||
/**
|
||||
* A command class that creates an Route-Domain
|
||||
*/
|
||||
class create_cmd
|
||||
: public rpc_cmd<HW::item<uint32_t>, vapi::Gbp_route_domain_add>
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
create_cmd(HW::item<uint32_t>& item,
|
||||
const handle_t ip4_uu_fwd,
|
||||
const handle_t ip6_uu_fwd);
|
||||
|
||||
/**
|
||||
* 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_ip4_uu_fwd;
|
||||
const handle_t m_ip6_uu_fwd;
|
||||
};
|
||||
|
||||
/**
|
||||
* A cmd class that Delete an Route-Domain
|
||||
*/
|
||||
class delete_cmd
|
||||
: public rpc_cmd<HW::item<uint32_t>, vapi::Gbp_route_domain_del>
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
delete_cmd(HW::item<uint32_t>& item);
|
||||
|
||||
/**
|
||||
* 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;
|
||||
};
|
||||
|
||||
/**
|
||||
* A cmd class that Dumps all the route domains
|
||||
*/
|
||||
class dump_cmd : public VOM::dump_cmd<vapi::Gbp_route_domain_dump>
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
dump_cmd() = default;
|
||||
dump_cmd(const dump_cmd& d) = 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<bool> item;
|
||||
};
|
||||
|
||||
}; // gbp_route_domain_cmds
|
||||
}; // VOM
|
||||
|
||||
/*
|
||||
* fd.io coding-style-patch-verification: ON
|
||||
*
|
||||
* Local Variables:
|
||||
* eval: (c-set-style "mozilla")
|
||||
* End:
|
||||
*/
|
||||
|
||||
#endif
|
@ -25,31 +25,38 @@ gbp_subnet::type_t::type_t(int v, const std::string s)
|
||||
{
|
||||
}
|
||||
|
||||
const gbp_subnet::type_t gbp_subnet::type_t::INTERNAL(0, "internal");
|
||||
const gbp_subnet::type_t gbp_subnet::type_t::EXTERNAL(1, "external");
|
||||
const gbp_subnet::type_t gbp_subnet::type_t::STITCHED_INTERNAL(
|
||||
0,
|
||||
"stitched-internal");
|
||||
const gbp_subnet::type_t gbp_subnet::type_t::STITCHED_EXTERNAL(
|
||||
1,
|
||||
"stitched-external");
|
||||
const gbp_subnet::type_t gbp_subnet::type_t::TRANSPORT(1, "transport");
|
||||
|
||||
singular_db<gbp_subnet::key_t, gbp_subnet> gbp_subnet::m_db;
|
||||
|
||||
gbp_subnet::event_handler gbp_subnet::m_evh;
|
||||
|
||||
gbp_subnet::gbp_subnet(const route_domain& rd, const route::prefix_t& prefix)
|
||||
gbp_subnet::gbp_subnet(const gbp_route_domain& rd,
|
||||
const route::prefix_t& prefix,
|
||||
const type_t& type)
|
||||
: m_hw(false)
|
||||
, m_rd(rd.singular())
|
||||
, m_prefix(prefix)
|
||||
, m_type(type_t::INTERNAL)
|
||||
, m_type(type)
|
||||
, m_recirc(nullptr)
|
||||
, m_epg(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
gbp_subnet::gbp_subnet(const route_domain& rd,
|
||||
gbp_subnet::gbp_subnet(const gbp_route_domain& rd,
|
||||
const route::prefix_t& prefix,
|
||||
const gbp_recirc& recirc,
|
||||
const gbp_endpoint_group& epg)
|
||||
: m_hw(false)
|
||||
, m_rd(rd.singular())
|
||||
, m_prefix(prefix)
|
||||
, m_type(type_t::EXTERNAL)
|
||||
, m_type(type_t::STITCHED_EXTERNAL)
|
||||
, m_recirc(recirc.singular())
|
||||
, m_epg(epg.singular())
|
||||
{
|
||||
@ -88,8 +95,7 @@ void
|
||||
gbp_subnet::sweep()
|
||||
{
|
||||
if (m_hw) {
|
||||
HW::enqueue(
|
||||
new gbp_subnet_cmds::delete_cmd(m_hw, m_rd->table_id(), m_prefix));
|
||||
HW::enqueue(new gbp_subnet_cmds::delete_cmd(m_hw, m_rd->id(), m_prefix));
|
||||
}
|
||||
HW::write();
|
||||
}
|
||||
@ -99,7 +105,7 @@ gbp_subnet::replay()
|
||||
{
|
||||
if (m_hw) {
|
||||
HW::enqueue(new gbp_subnet_cmds::create_cmd(
|
||||
m_hw, m_rd->table_id(), m_prefix, (m_type == type_t::INTERNAL),
|
||||
m_hw, m_rd->id(), m_prefix, m_type,
|
||||
(m_recirc ? m_recirc->handle() : handle_t::INVALID),
|
||||
(m_epg ? m_epg->id() : ~0)));
|
||||
}
|
||||
@ -126,7 +132,7 @@ gbp_subnet::update(const gbp_subnet& r)
|
||||
{
|
||||
if (rc_t::OK != m_hw.rc()) {
|
||||
HW::enqueue(new gbp_subnet_cmds::create_cmd(
|
||||
m_hw, m_rd->table_id(), m_prefix, (m_type == type_t::INTERNAL),
|
||||
m_hw, m_rd->id(), m_prefix, m_type,
|
||||
(m_recirc ? m_recirc->handle() : handle_t::INVALID),
|
||||
(m_epg ? m_epg->id() : ~0)));
|
||||
} else {
|
||||
@ -136,7 +142,7 @@ gbp_subnet::update(const gbp_subnet& r)
|
||||
m_type = r.m_type;
|
||||
|
||||
HW::enqueue(new gbp_subnet_cmds::create_cmd(
|
||||
m_hw, m_rd->table_id(), m_prefix, (m_type == type_t::INTERNAL),
|
||||
m_hw, m_rd->id(), m_prefix, m_type,
|
||||
(m_recirc ? m_recirc->handle() : handle_t::INVALID),
|
||||
(m_epg ? m_epg->id() : ~0)));
|
||||
}
|
||||
@ -192,15 +198,24 @@ gbp_subnet::event_handler::handle_populate(const client_db::key_t& key)
|
||||
auto& payload = record.get_payload();
|
||||
|
||||
route::prefix_t pfx = from_api(payload.subnet.prefix);
|
||||
std::shared_ptr<route_domain> rd =
|
||||
route_domain::find(payload.subnet.table_id);
|
||||
std::shared_ptr<gbp_route_domain> rd =
|
||||
gbp_route_domain::find(payload.subnet.rd_id);
|
||||
|
||||
if (rd) {
|
||||
if (payload.subnet.is_internal) {
|
||||
gbp_subnet gs(*rd, pfx);
|
||||
switch (payload.subnet.type) {
|
||||
case GBP_API_SUBNET_TRANSPORT: {
|
||||
gbp_subnet gs(*rd, pfx, type_t::TRANSPORT);
|
||||
OM::commit(key, gs);
|
||||
VOM_LOG(log_level_t::DEBUG) << "read: " << gs.to_string();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
case GBP_API_SUBNET_STITCHED_INTERNAL: {
|
||||
gbp_subnet gs(*rd, pfx, type_t::STITCHED_INTERNAL);
|
||||
OM::commit(key, gs);
|
||||
VOM_LOG(log_level_t::DEBUG) << "read: " << gs.to_string();
|
||||
break;
|
||||
}
|
||||
case GBP_API_SUBNET_STITCHED_EXTERNAL: {
|
||||
std::shared_ptr<interface> itf =
|
||||
interface::find(payload.subnet.sw_if_index);
|
||||
std::shared_ptr<gbp_endpoint_group> epg =
|
||||
@ -218,6 +233,7 @@ gbp_subnet::event_handler::handle_populate(const client_db::key_t& key)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependency_t
|
||||
@ -231,6 +247,15 @@ gbp_subnet::event_handler::show(std::ostream& os)
|
||||
{
|
||||
db_dump(m_db, os);
|
||||
}
|
||||
|
||||
std::ostream&
|
||||
operator<<(std::ostream& os, const gbp_subnet::key_t& key)
|
||||
{
|
||||
os << "[" << key.first << ", " << key.second << "]";
|
||||
|
||||
return os;
|
||||
}
|
||||
|
||||
} // namespace VOM
|
||||
|
||||
/*
|
||||
|
@ -16,9 +16,11 @@
|
||||
#ifndef __VOM_GBP_SUBNET_H__
|
||||
#define __VOM_GBP_SUBNET_H__
|
||||
|
||||
#include <ostream>
|
||||
|
||||
#include "vom/gbp_endpoint_group.hpp"
|
||||
#include "vom/gbp_recirc.hpp"
|
||||
#include "vom/route.hpp"
|
||||
#include "vom/gbp_route_domain.hpp"
|
||||
#include "vom/singular_db.hpp"
|
||||
|
||||
namespace VOM {
|
||||
@ -31,17 +33,41 @@ public:
|
||||
/**
|
||||
* The key for a GBP subnet; table and prefix
|
||||
*/
|
||||
typedef std::pair<route_domain::key_t, route::prefix_t> key_t;
|
||||
typedef std::pair<gbp_route_domain::key_t, route::prefix_t> key_t;
|
||||
|
||||
struct type_t : public enum_base<type_t>
|
||||
{
|
||||
/**
|
||||
* Internal subnet is reachable through the source EPG's
|
||||
* uplink interface.
|
||||
*/
|
||||
const static type_t STITCHED_INTERNAL;
|
||||
|
||||
/**
|
||||
* External subnet requires NAT translation before egress.
|
||||
*/
|
||||
const static type_t STITCHED_EXTERNAL;
|
||||
|
||||
/**
|
||||
* A transport subnet, sent via the RD's UU-fwd interface
|
||||
*/
|
||||
const static type_t TRANSPORT;
|
||||
|
||||
private:
|
||||
type_t(int v, const std::string s);
|
||||
};
|
||||
|
||||
/**
|
||||
* Construct an internal GBP subnet
|
||||
*/
|
||||
gbp_subnet(const route_domain& rd, const route::prefix_t& prefix);
|
||||
gbp_subnet(const gbp_route_domain& rd,
|
||||
const route::prefix_t& prefix,
|
||||
const type_t& type);
|
||||
|
||||
/**
|
||||
* Construct an external GBP subnet
|
||||
*/
|
||||
gbp_subnet(const route_domain& rd,
|
||||
gbp_subnet(const gbp_route_domain& rd,
|
||||
const route::prefix_t& prefix,
|
||||
const gbp_recirc& recirc,
|
||||
const gbp_endpoint_group& epg);
|
||||
@ -92,23 +118,6 @@ public:
|
||||
std::string to_string() const;
|
||||
|
||||
private:
|
||||
struct type_t : public enum_base<type_t>
|
||||
{
|
||||
/**
|
||||
* Internal subnet is reachable through the source EPG's
|
||||
* uplink interface.
|
||||
*/
|
||||
const static type_t INTERNAL;
|
||||
|
||||
/**
|
||||
* External subnet requires NAT translation before egress.
|
||||
*/
|
||||
const static type_t EXTERNAL;
|
||||
|
||||
private:
|
||||
type_t(int v, const std::string s);
|
||||
};
|
||||
|
||||
/**
|
||||
* Class definition for listeners to OM events
|
||||
*/
|
||||
@ -177,7 +186,7 @@ private:
|
||||
/**
|
||||
* the route domain the prefix is in
|
||||
*/
|
||||
const std::shared_ptr<route_domain> m_rd;
|
||||
const std::shared_ptr<gbp_route_domain> m_rd;
|
||||
|
||||
/**
|
||||
* prefix to match
|
||||
@ -205,6 +214,8 @@ private:
|
||||
static singular_db<key_t, gbp_subnet> m_db;
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const gbp_subnet::key_t& key);
|
||||
|
||||
}; // namespace
|
||||
|
||||
/*
|
||||
|
@ -22,13 +22,13 @@ namespace gbp_subnet_cmds {
|
||||
create_cmd::create_cmd(HW::item<bool>& item,
|
||||
route::table_id_t rd,
|
||||
const route::prefix_t& prefix,
|
||||
bool internal,
|
||||
const gbp_subnet::type_t& type,
|
||||
const handle_t& itf,
|
||||
epg_id_t epg_id)
|
||||
: rpc_cmd(item)
|
||||
, m_rd(rd)
|
||||
, m_prefix(prefix)
|
||||
, m_internal(internal)
|
||||
, m_type(type)
|
||||
, m_itf(itf)
|
||||
, m_epg_id(epg_id)
|
||||
{
|
||||
@ -38,8 +38,21 @@ bool
|
||||
create_cmd::operator==(const create_cmd& other) const
|
||||
{
|
||||
return ((m_itf == other.m_itf) && (m_rd == other.m_rd) &&
|
||||
(m_prefix == other.m_prefix) && (m_itf == other.m_itf) &&
|
||||
(m_epg_id == other.m_epg_id));
|
||||
(m_prefix == other.m_prefix) && (m_type == other.m_type) &&
|
||||
(m_itf == other.m_itf) && (m_epg_id == other.m_epg_id));
|
||||
}
|
||||
|
||||
static vapi_enum_gbp_subnet_type
|
||||
gbp_subnet_type_to_api(const gbp_subnet::type_t& type)
|
||||
{
|
||||
if (gbp_subnet::type_t::STITCHED_INTERNAL == type)
|
||||
return (GBP_API_SUBNET_STITCHED_INTERNAL);
|
||||
if (gbp_subnet::type_t::STITCHED_EXTERNAL == type)
|
||||
return (GBP_API_SUBNET_STITCHED_EXTERNAL);
|
||||
if (gbp_subnet::type_t::TRANSPORT == type)
|
||||
return (GBP_API_SUBNET_TRANSPORT);
|
||||
|
||||
return (GBP_API_SUBNET_STITCHED_INTERNAL);
|
||||
}
|
||||
|
||||
rc_t
|
||||
@ -49,8 +62,8 @@ create_cmd::issue(connection& con)
|
||||
|
||||
auto& payload = req.get_request().get_payload();
|
||||
payload.is_add = 1;
|
||||
payload.subnet.is_internal = m_internal;
|
||||
payload.subnet.table_id = m_rd;
|
||||
payload.subnet.type = gbp_subnet_type_to_api(m_type);
|
||||
payload.subnet.rd_id = m_rd;
|
||||
payload.subnet.sw_if_index = m_itf.value();
|
||||
payload.subnet.epg_id = m_epg_id;
|
||||
payload.subnet.prefix = to_api(m_prefix);
|
||||
@ -64,9 +77,9 @@ std::string
|
||||
create_cmd::to_string() const
|
||||
{
|
||||
std::ostringstream s;
|
||||
s << "gbp-subnet-create: " << m_hw_item.to_string()
|
||||
<< "internal:" << m_internal << ", " << m_rd << ":" << m_prefix.to_string()
|
||||
<< " itf:" << m_itf << " epg-id:" << m_epg_id;
|
||||
s << "gbp-subnet-create: " << m_hw_item.to_string() << "type:" << m_type
|
||||
<< ", " << m_rd << ":" << m_prefix.to_string() << " itf:" << m_itf
|
||||
<< " epg-id:" << m_epg_id;
|
||||
|
||||
return (s.str());
|
||||
}
|
||||
@ -93,13 +106,9 @@ delete_cmd::issue(connection& con)
|
||||
|
||||
auto& payload = req.get_request().get_payload();
|
||||
payload.is_add = 0;
|
||||
payload.subnet.table_id = m_rd;
|
||||
payload.subnet.rd_id = m_rd;
|
||||
payload.subnet.prefix = to_api(m_prefix);
|
||||
|
||||
payload.subnet.is_internal = 0;
|
||||
payload.subnet.sw_if_index = ~0;
|
||||
payload.subnet.epg_id = ~0;
|
||||
|
||||
VAPI_CALL(req.execute());
|
||||
|
||||
return (wait());
|
||||
|
@ -36,7 +36,7 @@ public:
|
||||
create_cmd(HW::item<bool>& item,
|
||||
route::table_id_t rd,
|
||||
const route::prefix_t& prefix,
|
||||
bool internal,
|
||||
const gbp_subnet::type_t& type,
|
||||
const handle_t& itf,
|
||||
epg_id_t epg_id);
|
||||
|
||||
@ -58,7 +58,7 @@ public:
|
||||
private:
|
||||
const route::table_id_t m_rd;
|
||||
const route::prefix_t m_prefix;
|
||||
const bool m_internal;
|
||||
const gbp_subnet::type_t& m_type;
|
||||
const handle_t m_itf;
|
||||
const epg_id_t m_epg_id;
|
||||
};
|
||||
|
231
extras/vom/vom/gbp_vxlan.cpp
Normal file
231
extras/vom/vom/gbp_vxlan.cpp
Normal file
@ -0,0 +1,231 @@
|
||||
/*
|
||||
* 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/gbp_vxlan.hpp"
|
||||
#include "vom/gbp_vxlan_cmds.hpp"
|
||||
#include "vom/interface.hpp"
|
||||
#include "vom/singular_db_funcs.hpp"
|
||||
|
||||
namespace VOM {
|
||||
|
||||
const std::string GBP_VXLAN_NAME = "gbp-vxlan";
|
||||
|
||||
/**
|
||||
* A DB of al the interfaces, key on the name
|
||||
*/
|
||||
singular_db<gbp_vxlan::key_t, gbp_vxlan> gbp_vxlan::m_db;
|
||||
|
||||
gbp_vxlan::event_handler gbp_vxlan::m_evh;
|
||||
|
||||
gbp_vxlan::gbp_vxlan(uint32_t vni, const gbp_route_domain& grd)
|
||||
: interface(mk_name(vni),
|
||||
interface::type_t::UNKNOWN,
|
||||
interface::admin_state_t::UP)
|
||||
, m_vni(vni)
|
||||
, m_gbd()
|
||||
, m_grd(grd.singular())
|
||||
{
|
||||
}
|
||||
gbp_vxlan::gbp_vxlan(uint32_t vni, const gbp_bridge_domain& gbd)
|
||||
: interface(mk_name(vni),
|
||||
interface::type_t::UNKNOWN,
|
||||
interface::admin_state_t::UP)
|
||||
, m_vni(vni)
|
||||
, m_gbd(gbd.singular())
|
||||
, m_grd()
|
||||
{
|
||||
}
|
||||
|
||||
gbp_vxlan::gbp_vxlan(const gbp_vxlan& vt)
|
||||
: interface(vt)
|
||||
, m_vni(vt.m_vni)
|
||||
, m_gbd(vt.m_gbd)
|
||||
, m_grd(vt.m_grd)
|
||||
{
|
||||
}
|
||||
|
||||
std::string
|
||||
gbp_vxlan::mk_name(uint32_t vni)
|
||||
{
|
||||
std::ostringstream s;
|
||||
|
||||
s << GBP_VXLAN_NAME << "-" << vni;
|
||||
|
||||
return (s.str());
|
||||
}
|
||||
|
||||
const gbp_vxlan::key_t
|
||||
gbp_vxlan::key() const
|
||||
{
|
||||
return (m_vni);
|
||||
}
|
||||
|
||||
bool
|
||||
gbp_vxlan::operator==(const gbp_vxlan& vt) const
|
||||
{
|
||||
return (m_vni == vt.m_vni);
|
||||
}
|
||||
|
||||
void
|
||||
gbp_vxlan::sweep()
|
||||
{
|
||||
if (rc_t::OK == m_hdl) {
|
||||
HW::enqueue(new gbp_vxlan_cmds::delete_cmd(m_hdl, m_vni));
|
||||
}
|
||||
HW::write();
|
||||
}
|
||||
|
||||
void
|
||||
gbp_vxlan::replay()
|
||||
{
|
||||
if (rc_t::OK == m_hdl) {
|
||||
if (m_grd)
|
||||
HW::enqueue(new gbp_vxlan_cmds::create_cmd(m_hdl, name(), m_vni, false,
|
||||
m_grd->id()));
|
||||
else if (m_gbd)
|
||||
HW::enqueue(new gbp_vxlan_cmds::create_cmd(m_hdl, name(), m_vni, true,
|
||||
m_gbd->id()));
|
||||
}
|
||||
}
|
||||
|
||||
gbp_vxlan::~gbp_vxlan()
|
||||
{
|
||||
sweep();
|
||||
m_db.release(key(), this);
|
||||
}
|
||||
|
||||
std::string
|
||||
gbp_vxlan::to_string() const
|
||||
{
|
||||
std::ostringstream s;
|
||||
s << "gbp-vxlan:[" << m_vni << "]";
|
||||
|
||||
return (s.str());
|
||||
}
|
||||
|
||||
std::shared_ptr<gbp_vxlan>
|
||||
gbp_vxlan::find(const key_t key)
|
||||
{
|
||||
return (m_db.find(key));
|
||||
}
|
||||
|
||||
void
|
||||
gbp_vxlan::update(const gbp_vxlan& desired)
|
||||
{
|
||||
/*
|
||||
* the desired state is always that the interface should be created
|
||||
*/
|
||||
if (rc_t::OK != m_hdl) {
|
||||
if (m_grd)
|
||||
HW::enqueue(new gbp_vxlan_cmds::create_cmd(m_hdl, name(), m_vni, false,
|
||||
m_grd->id()));
|
||||
else if (m_gbd)
|
||||
HW::enqueue(new gbp_vxlan_cmds::create_cmd(m_hdl, name(), m_vni, true,
|
||||
m_gbd->id()));
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<gbp_vxlan>
|
||||
gbp_vxlan::find_or_add(const gbp_vxlan& temp)
|
||||
{
|
||||
return (m_db.find_or_add(temp.key(), temp));
|
||||
}
|
||||
|
||||
std::shared_ptr<gbp_vxlan>
|
||||
gbp_vxlan::singular() const
|
||||
{
|
||||
return find_or_add(*this);
|
||||
}
|
||||
|
||||
std::shared_ptr<interface>
|
||||
gbp_vxlan::singular_i() const
|
||||
{
|
||||
return find_or_add(*this);
|
||||
}
|
||||
|
||||
void
|
||||
gbp_vxlan::dump(std::ostream& os)
|
||||
{
|
||||
db_dump(m_db, os);
|
||||
}
|
||||
|
||||
void
|
||||
gbp_vxlan::event_handler::handle_populate(const client_db::key_t& key)
|
||||
{
|
||||
/*
|
||||
* dump VPP Bridge domains
|
||||
*/
|
||||
std::shared_ptr<gbp_vxlan_cmds::dump_cmd> cmd =
|
||||
std::make_shared<gbp_vxlan_cmds::dump_cmd>();
|
||||
|
||||
HW::enqueue(cmd);
|
||||
HW::write();
|
||||
|
||||
for (auto& record : *cmd) {
|
||||
auto& payload = record.get_payload();
|
||||
|
||||
if (GBP_VXLAN_TUNNEL_MODE_L3 == payload.tunnel.mode) {
|
||||
auto rd = gbp_route_domain::find(payload.tunnel.bd_rd_id);
|
||||
|
||||
if (rd) {
|
||||
gbp_vxlan vt(payload.tunnel.vni, *rd);
|
||||
OM::commit(key, vt);
|
||||
VOM_LOG(log_level_t::DEBUG) << "dump: " << vt.to_string();
|
||||
}
|
||||
} else {
|
||||
auto bd = gbp_bridge_domain::find(payload.tunnel.bd_rd_id);
|
||||
|
||||
if (bd) {
|
||||
gbp_vxlan vt(payload.tunnel.vni, *bd);
|
||||
OM::commit(key, vt);
|
||||
VOM_LOG(log_level_t::DEBUG) << "dump: " << vt.to_string();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gbp_vxlan::event_handler::event_handler()
|
||||
{
|
||||
OM::register_listener(this);
|
||||
inspect::register_handler({ "gvt", "gbp-vxlan-tunnel" }, "GBP VXLAN Tunnels",
|
||||
this);
|
||||
}
|
||||
|
||||
void
|
||||
gbp_vxlan::event_handler::handle_replay()
|
||||
{
|
||||
m_db.replay();
|
||||
}
|
||||
|
||||
dependency_t
|
||||
gbp_vxlan::event_handler::order() const
|
||||
{
|
||||
return (dependency_t::BINDING);
|
||||
}
|
||||
|
||||
void
|
||||
gbp_vxlan::event_handler::show(std::ostream& os)
|
||||
{
|
||||
db_dump(m_db, os);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* fd.io coding-style-patch-verification: ON
|
||||
*
|
||||
* Local Variables:
|
||||
* eval: (c-set-style "mozilla")
|
||||
* End:
|
||||
*/
|
186
extras/vom/vom/gbp_vxlan.hpp
Normal file
186
extras/vom/vom/gbp_vxlan.hpp
Normal file
@ -0,0 +1,186 @@
|
||||
/*
|
||||
* 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_VXLAN_H__
|
||||
#define __VOM_GBP_VXLAN_H__
|
||||
|
||||
#include "vom/gbp_bridge_domain.hpp"
|
||||
#include "vom/gbp_route_domain.hpp"
|
||||
#include "vom/hw.hpp"
|
||||
#include "vom/inspect.hpp"
|
||||
#include "vom/interface.hpp"
|
||||
#include "vom/singular_db.hpp"
|
||||
|
||||
namespace VOM {
|
||||
/**
|
||||
* A representation of a GBP_VXLAN Tunnel in VPP
|
||||
*/
|
||||
class gbp_vxlan : public interface
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* The VNI is the key
|
||||
*/
|
||||
typedef uint32_t key_t;
|
||||
|
||||
/**
|
||||
* Construct a new object matching the desried state
|
||||
*/
|
||||
gbp_vxlan(uint32_t vni, const gbp_bridge_domain& gbd);
|
||||
gbp_vxlan(uint32_t vni, const gbp_route_domain& grd);
|
||||
|
||||
/*
|
||||
* Destructor
|
||||
*/
|
||||
~gbp_vxlan();
|
||||
|
||||
/**
|
||||
* Copy constructor
|
||||
*/
|
||||
gbp_vxlan(const gbp_vxlan& o);
|
||||
|
||||
bool operator==(const gbp_vxlan& vt) const;
|
||||
|
||||
/**
|
||||
* Return the matching 'singular instance'
|
||||
*/
|
||||
std::shared_ptr<gbp_vxlan> singular() const;
|
||||
|
||||
/**
|
||||
* Return the object's key
|
||||
*/
|
||||
const key_t key() const;
|
||||
|
||||
/**
|
||||
* Debug rpint function
|
||||
*/
|
||||
virtual std::string to_string() const;
|
||||
|
||||
/**
|
||||
* Return VPP's handle to this object
|
||||
*/
|
||||
const handle_t& handle() const;
|
||||
|
||||
/**
|
||||
* Dump all L3Configs into the stream provided
|
||||
*/
|
||||
static void dump(std::ostream& os);
|
||||
|
||||
/**
|
||||
* Find the GBP_VXLAN tunnel in the OM
|
||||
*/
|
||||
static std::shared_ptr<gbp_vxlan> find(const key_t k);
|
||||
|
||||
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 handle 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_vxlan& obj);
|
||||
|
||||
/**
|
||||
* Return the matching 'instance' of the sub-interface
|
||||
* over-ride from the base class
|
||||
*/
|
||||
std::shared_ptr<interface> singular_i() const;
|
||||
|
||||
/**
|
||||
* Find the GBP_VXLAN tunnel in the OM
|
||||
*/
|
||||
static std::shared_ptr<gbp_vxlan> find_or_add(const gbp_vxlan& 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<key_t, gbp_vxlan>;
|
||||
|
||||
/**
|
||||
* Sweep/reap the object if still stale
|
||||
*/
|
||||
void sweep(void);
|
||||
|
||||
/**
|
||||
* replay the object to create it in hardware
|
||||
*/
|
||||
void replay(void);
|
||||
|
||||
/**
|
||||
* Tunnel VNI/key
|
||||
*/
|
||||
uint32_t m_vni;
|
||||
std::shared_ptr<gbp_bridge_domain> m_gbd;
|
||||
std::shared_ptr<gbp_route_domain> m_grd;
|
||||
|
||||
/**
|
||||
* A map of all VLAN tunnela against thier key
|
||||
*/
|
||||
static singular_db<key_t, gbp_vxlan> m_db;
|
||||
|
||||
/**
|
||||
* Construct a unique name for the tunnel
|
||||
*/
|
||||
static std::string mk_name(uint32_t vni);
|
||||
};
|
||||
|
||||
}; // namespace VOM
|
||||
|
||||
/*
|
||||
* fd.io coding-style-patch-verification: ON
|
||||
*
|
||||
* Local Variables:
|
||||
* eval: (c-set-style "mozilla")
|
||||
* End:
|
||||
*/
|
||||
|
||||
#endif
|
137
extras/vom/vom/gbp_vxlan_cmds.cpp
Normal file
137
extras/vom/vom/gbp_vxlan_cmds.cpp
Normal file
@ -0,0 +1,137 @@
|
||||
/*
|
||||
* 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/gbp_vxlan_cmds.hpp"
|
||||
|
||||
#include <vapi/tap.api.vapi.hpp>
|
||||
|
||||
namespace VOM {
|
||||
namespace gbp_vxlan_cmds {
|
||||
create_cmd::create_cmd(HW::item<handle_t>& item,
|
||||
const std::string& name,
|
||||
uint32_t vni,
|
||||
bool is_l2,
|
||||
uint32_t bd_rd)
|
||||
: interface::create_cmd<vapi::Gbp_vxlan_tunnel_add>(item, name)
|
||||
, m_vni(vni)
|
||||
, m_is_l2(is_l2)
|
||||
, m_bd_rd(bd_rd)
|
||||
{
|
||||
}
|
||||
|
||||
rc_t
|
||||
create_cmd::issue(connection& con)
|
||||
{
|
||||
msg_t req(con.ctx(), std::ref(*this));
|
||||
|
||||
auto& payload = req.get_request().get_payload();
|
||||
|
||||
payload.tunnel.vni = m_vni;
|
||||
payload.tunnel.bd_rd_id = m_bd_rd;
|
||||
if (m_is_l2)
|
||||
payload.tunnel.mode = GBP_VXLAN_TUNNEL_MODE_L2;
|
||||
else
|
||||
payload.tunnel.mode = GBP_VXLAN_TUNNEL_MODE_L3;
|
||||
|
||||
VAPI_CALL(req.execute());
|
||||
|
||||
wait();
|
||||
if (m_hw_item.rc() == rc_t::OK) {
|
||||
insert_interface();
|
||||
}
|
||||
|
||||
return (m_hw_item.rc());
|
||||
}
|
||||
|
||||
std::string
|
||||
create_cmd::to_string() const
|
||||
{
|
||||
std::ostringstream s;
|
||||
s << "gbp-vxlan-create: " << m_hw_item.to_string() << " vni:" << m_vni
|
||||
<< " bd/rd:" << m_bd_rd;
|
||||
|
||||
return (s.str());
|
||||
}
|
||||
|
||||
delete_cmd::delete_cmd(HW::item<handle_t>& item, uint32_t vni)
|
||||
: interface::delete_cmd<vapi::Gbp_vxlan_tunnel_del>(item)
|
||||
, m_vni(vni)
|
||||
{
|
||||
}
|
||||
|
||||
rc_t
|
||||
delete_cmd::issue(connection& con)
|
||||
{
|
||||
msg_t req(con.ctx(), std::ref(*this));
|
||||
|
||||
auto& payload = req.get_request().get_payload();
|
||||
payload.vni = m_vni;
|
||||
|
||||
VAPI_CALL(req.execute());
|
||||
|
||||
wait();
|
||||
m_hw_item.set(rc_t::NOOP);
|
||||
|
||||
remove_interface();
|
||||
return rc_t::OK;
|
||||
}
|
||||
|
||||
std::string
|
||||
delete_cmd::to_string() const
|
||||
{
|
||||
std::ostringstream s;
|
||||
s << "gbp-vxlan-delete: " << m_hw_item.to_string() << " vni:" << m_vni;
|
||||
|
||||
return (s.str());
|
||||
}
|
||||
|
||||
dump_cmd::dump_cmd()
|
||||
{
|
||||
}
|
||||
|
||||
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-vxlan-dump");
|
||||
}
|
||||
|
||||
} // namespace gbp_vxlan_cmds
|
||||
} // namespace VOM
|
||||
|
||||
/*
|
||||
* fd.io coding-style-patch-verification: ON
|
||||
*
|
||||
* Local Variables:
|
||||
* eval: (c-set-style "mozilla")
|
||||
* End:
|
||||
*/
|
135
extras/vom/vom/gbp_vxlan_cmds.hpp
Normal file
135
extras/vom/vom/gbp_vxlan_cmds.hpp
Normal file
@ -0,0 +1,135 @@
|
||||
/*
|
||||
* 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_VXLAN_CMDS_H__
|
||||
#define __VOM_GBP_VXLAN_CMDS_H__
|
||||
|
||||
#include "vom/dump_cmd.hpp"
|
||||
#include "vom/gbp_vxlan.hpp"
|
||||
#include "vom/interface.hpp"
|
||||
|
||||
#include <vapi/gbp.api.vapi.hpp>
|
||||
|
||||
namespace VOM {
|
||||
namespace gbp_vxlan_cmds {
|
||||
/**
|
||||
* A command class that creates an Bridge-Domain
|
||||
*/
|
||||
class create_cmd : public interface::create_cmd<vapi::Gbp_vxlan_tunnel_add>
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
create_cmd(HW::item<handle_t>& item,
|
||||
const std::string& name,
|
||||
uint32_t vni,
|
||||
bool is_l2,
|
||||
uint32_t bd_rd);
|
||||
|
||||
/**
|
||||
* 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:
|
||||
uint32_t m_vni;
|
||||
bool m_is_l2;
|
||||
uint32_t m_bd_rd;
|
||||
};
|
||||
|
||||
/**
|
||||
* A cmd class that Delete an Bridge-Domain
|
||||
*/
|
||||
class delete_cmd : public interface::delete_cmd<vapi::Gbp_vxlan_tunnel_del>
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
delete_cmd(HW::item<handle_t>& item, uint32_t vni);
|
||||
|
||||
/**
|
||||
* 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:
|
||||
uint32_t m_vni;
|
||||
};
|
||||
|
||||
/**
|
||||
* A cmd class that Dumps all the bridge domains
|
||||
*/
|
||||
class dump_cmd : public VOM::dump_cmd<vapi::Gbp_vxlan_tunnel_dump>
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
dump_cmd();
|
||||
dump_cmd(const dump_cmd& d);
|
||||
|
||||
/**
|
||||
* 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<bool> item;
|
||||
};
|
||||
|
||||
}; // gbp_vxlan_cmds
|
||||
}; // VOM
|
||||
|
||||
/*
|
||||
* fd.io coding-style-patch-verification: ON
|
||||
*
|
||||
* Local Variables:
|
||||
* eval: (c-set-style "mozilla")
|
||||
* End:
|
||||
*/
|
||||
|
||||
#endif
|
186
extras/vom/vom/gbp_vxlan_tunnel.cpp
Normal file
186
extras/vom/vom/gbp_vxlan_tunnel.cpp
Normal file
@ -0,0 +1,186 @@
|
||||
/*
|
||||
* 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/gbp_vxlan_tunnel.hpp"
|
||||
#include "vom/gbp_vxlan_tunnel_cmds.hpp"
|
||||
#include "vom/interface.hpp"
|
||||
#include "vom/singular_db_funcs.hpp"
|
||||
|
||||
namespace VOM {
|
||||
|
||||
/**
|
||||
* A DB of al the interfaces, key on the name
|
||||
*/
|
||||
singular_db<uint32_t, gbp_vxlan_tunnel> gbp_vxlan_tunnel::m_db;
|
||||
|
||||
gbp_vxlan_tunnel::event_handler gbp_vxlan_tunnel::m_evh;
|
||||
|
||||
/**
|
||||
* Construct a new object matching the desried state
|
||||
*/
|
||||
gbp_vxlan_tunnel::gbp_vxlan_tunnel(const vxlan_tunnel& vt)
|
||||
: interface(vt)
|
||||
, m_vni(vt.m_vni)
|
||||
{
|
||||
}
|
||||
|
||||
gbp_vxlan_tunnel::gbp_vxlan_tunnel(uint32_t vni)
|
||||
: interface(mk_name(vni),
|
||||
interface::type_t::UNKNOWN,
|
||||
interface::admin_state_t::UP)
|
||||
, m_vni(vt.m_vni)
|
||||
{
|
||||
}
|
||||
|
||||
const gbp_vxlan_tunnel::key_t
|
||||
gbp_vxlan_tunnel::key() const
|
||||
{
|
||||
return (m_vni);
|
||||
}
|
||||
|
||||
bool
|
||||
gbp_vxlan_tunnel::operator==(const gbp_vxlan_tunnel& vt) const
|
||||
{
|
||||
return (m_vni == vt.m_vni);
|
||||
}
|
||||
|
||||
void
|
||||
gbp_vxlan_tunnel::sweep()
|
||||
{
|
||||
if (rc_t::OK == m_id.rc()) {
|
||||
HW::enqueue(new gbp_vxlan_tunnel_cmds::delete_cmd(m_vni));
|
||||
}
|
||||
HW::write();
|
||||
}
|
||||
|
||||
void
|
||||
gbp_vxlan_tunnel::replay()
|
||||
{
|
||||
if (rc_t::OK == m_hdl) {
|
||||
HW::enqueue(new gbp_vxlan_tunnel_cmds::create_cmd(m_vni));
|
||||
}
|
||||
}
|
||||
|
||||
gbp_vxlan_tunnel::~gbp_vxlan_tunnel()
|
||||
{
|
||||
sweep();
|
||||
m_db.release(m_id.data(), this);
|
||||
}
|
||||
|
||||
std::string
|
||||
gbp_vxlan_tunnel::to_string() const
|
||||
{
|
||||
std::ostringstream s;
|
||||
s << "gbp-vxlan:[" << m_vni << "]";
|
||||
|
||||
return (s.str());
|
||||
}
|
||||
|
||||
std::shared_ptr<gbp_vxlan_tunnel>
|
||||
gbp_vxlan_tunnel::find(const key_t& key)
|
||||
{
|
||||
return (m_db.find(key));
|
||||
}
|
||||
|
||||
void
|
||||
gbp_vxlan_tunnel::update(const gbp_vxlan_tunnel& desired)
|
||||
{
|
||||
/*
|
||||
* the desired state is always that the interface should be created
|
||||
*/
|
||||
if (rc_t::OK != m_hdl) {
|
||||
HW::enqueue(new gbp_vxlan_tunnel_cmds::create_cmd(m_vni));
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<gbp_vxlan_tunnel>
|
||||
gbp_vxlan_tunnel::find_or_add(const gbp_vxlan_tunnel& temp)
|
||||
{
|
||||
return (m_db.find_or_add(temp.m_id.data(), temp));
|
||||
}
|
||||
|
||||
std::shared_ptr<gbp_vxlan_tunnel>
|
||||
gbp_vxlan_tunnel::singular() const
|
||||
{
|
||||
return find_or_add(*this);
|
||||
}
|
||||
|
||||
void
|
||||
gbp_vxlan_tunnel::dump(std::ostream& os)
|
||||
{
|
||||
db_dump(m_db, os);
|
||||
}
|
||||
|
||||
void
|
||||
gbp_vxlan_tunnel::event_handler::handle_populate(const client_db::key_t& key)
|
||||
{
|
||||
/*
|
||||
* dump VPP Bridge domains
|
||||
*/
|
||||
std::shared_ptr<gbp_vxlan_tunnel_cmds::dump_cmd> cmd =
|
||||
std::make_shared<gbp_vxlan_tunnel_cmds::dump_cmd>();
|
||||
|
||||
HW::enqueue(cmd);
|
||||
HW::write();
|
||||
|
||||
for (auto& record : *cmd) {
|
||||
auto& payload = record.get_payload();
|
||||
|
||||
gbp_vxlan_tunnel vt(payload.tunnel.vni, );
|
||||
OM::commit(key, vt);
|
||||
VOM_LOG(log_level_t::DEBUG) << "dump: " << vt.to_string();
|
||||
}
|
||||
else
|
||||
{
|
||||
gbp_vxlan_tunnel vt(payload.vt.vt_id);
|
||||
OM::commit(key, vt);
|
||||
VOM_LOG(log_level_t::DEBUG) << "dump: " << vt.to_string();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gbp_vxlan_tunnel::event_handler::event_handler()
|
||||
{
|
||||
OM::register_listener(this);
|
||||
inspect::register_handler({ "gvt", "gbp-vxlan-tunnel" }, "GBP VXLAN Tunnels",
|
||||
this);
|
||||
}
|
||||
|
||||
void
|
||||
gbp_vxlan_tunnel::event_handler::handle_replay()
|
||||
{
|
||||
m_db.replay();
|
||||
}
|
||||
|
||||
dependency_t
|
||||
gbp_vxlan_tunnel::event_handler::order() const
|
||||
{
|
||||
return (dependency_t::INTERFACE);
|
||||
}
|
||||
|
||||
void
|
||||
gbp_vxlan_tunnel::event_handler::show(std::ostream& os)
|
||||
{
|
||||
db_dump(m_db, os);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* fd.io coding-style-patch-verification: ON
|
||||
*
|
||||
* Local Variables:
|
||||
* eval: (c-set-style "mozilla")
|
||||
* End:
|
||||
*/
|
@ -38,6 +38,10 @@ interface_factory::new_interface(const vapi_payload_sw_interface_details& vd)
|
||||
l2_address_t l2_address(vd.l2_address, vd.l2_address_length);
|
||||
std::string tag = "";
|
||||
|
||||
if (interface::type_t::UNKNOWN == type) {
|
||||
return sp;
|
||||
}
|
||||
|
||||
sp = interface::find(hdl);
|
||||
if (sp) {
|
||||
sp->set(state);
|
||||
|
@ -13,17 +13,23 @@
|
||||
|
||||
add_vpp_plugin(gbp
|
||||
SOURCES
|
||||
gbp_subnet.c
|
||||
gbp_api.c
|
||||
gbp_bridge_domain.c
|
||||
gbp_classify.c
|
||||
gbp_contract.c
|
||||
gbp_endpoint.c
|
||||
gbp_endpoint_group.c
|
||||
gbp_classify.c
|
||||
gbp_recirc.c
|
||||
gbp_policy.c
|
||||
gbp_policy_dpo.c
|
||||
gbp_fwd.c
|
||||
gbp_fwd_dpo.c
|
||||
gbp_api.c
|
||||
gbp_itf.c
|
||||
gbp_learn.c
|
||||
gbp_policy.c
|
||||
gbp_policy_dpo.c
|
||||
gbp_recirc.c
|
||||
gbp_route_domain.c
|
||||
gbp_scanner.c
|
||||
gbp_subnet.c
|
||||
gbp_vxlan.c
|
||||
|
||||
API_FILES
|
||||
gbp.api
|
||||
|
@ -19,16 +19,96 @@ option version = "2.0.0";
|
||||
import "vnet/ip/ip_types.api";
|
||||
import "vnet/ethernet/ethernet_types.api";
|
||||
|
||||
typedef gbp_bridge_domain
|
||||
{
|
||||
u32 bd_id;
|
||||
u32 bvi_sw_if_index;
|
||||
u32 uu_fwd_sw_if_index;
|
||||
};
|
||||
|
||||
autoreply define gbp_bridge_domain_add
|
||||
{
|
||||
u32 client_index;
|
||||
u32 context;
|
||||
vl_api_gbp_bridge_domain_t bd;
|
||||
};
|
||||
autoreply define gbp_bridge_domain_del
|
||||
{
|
||||
u32 client_index;
|
||||
u32 context;
|
||||
u32 bd_id;
|
||||
};
|
||||
autoreply define gbp_bridge_domain_dump
|
||||
{
|
||||
u32 client_index;
|
||||
u32 context;
|
||||
};
|
||||
define gbp_bridge_domain_details
|
||||
{
|
||||
u32 context;
|
||||
vl_api_gbp_bridge_domain_t bd;
|
||||
};
|
||||
|
||||
typedef gbp_route_domain
|
||||
{
|
||||
u32 rd_id;
|
||||
u32 ip4_table_id;
|
||||
u32 ip6_table_id;
|
||||
u32 ip4_uu_sw_if_index;
|
||||
u32 ip6_uu_sw_if_index;
|
||||
};
|
||||
|
||||
autoreply define gbp_route_domain_add
|
||||
{
|
||||
u32 client_index;
|
||||
u32 context;
|
||||
vl_api_gbp_route_domain_t rd;
|
||||
};
|
||||
autoreply define gbp_route_domain_del
|
||||
{
|
||||
u32 client_index;
|
||||
u32 context;
|
||||
u32 rd_id;
|
||||
};
|
||||
autoreply define gbp_route_domain_dump
|
||||
{
|
||||
u32 client_index;
|
||||
u32 context;
|
||||
};
|
||||
define gbp_route_domain_details
|
||||
{
|
||||
u32 context;
|
||||
vl_api_gbp_route_domain_t rd;
|
||||
};
|
||||
|
||||
/** \brief Endpoint
|
||||
@param client_index - opaque cookie to identify the sender
|
||||
@param context - sender context, to match reply w/ request
|
||||
*/
|
||||
|
||||
enum gbp_endpoint_flags
|
||||
{
|
||||
NONE = 0,
|
||||
BOUNCE = 0x1,
|
||||
REMOTE = 0x2,
|
||||
LEARNT = 0x4,
|
||||
/* hey Ole WTF */
|
||||
REMOTE_LEARNT = 0x6,
|
||||
};
|
||||
|
||||
typedef gbp_endpoint_tun
|
||||
{
|
||||
vl_api_address_t src;
|
||||
vl_api_address_t dst;
|
||||
};
|
||||
|
||||
typedef gbp_endpoint
|
||||
{
|
||||
u32 sw_if_index;
|
||||
u16 epg_id;
|
||||
vl_api_gbp_endpoint_flags_t flags;
|
||||
vl_api_mac_address_t mac;
|
||||
vl_api_gbp_endpoint_tun_t tun;
|
||||
u8 n_ips;
|
||||
vl_api_address_t ips[n_ips];
|
||||
};
|
||||
@ -63,6 +143,8 @@ define gbp_endpoint_dump
|
||||
define gbp_endpoint_details
|
||||
{
|
||||
u32 context;
|
||||
f64 age;
|
||||
u32 handle;
|
||||
vl_api_gbp_endpoint_t endpoint;
|
||||
};
|
||||
|
||||
@ -70,18 +152,22 @@ typeonly define gbp_endpoint_group
|
||||
{
|
||||
u16 epg_id;
|
||||
u32 bd_id;
|
||||
u32 ip4_table_id;
|
||||
u32 ip6_table_id;
|
||||
u32 rd_id;
|
||||
u32 uplink_sw_if_index;
|
||||
};
|
||||
|
||||
autoreply define gbp_endpoint_group_add_del
|
||||
autoreply define gbp_endpoint_group_add
|
||||
{
|
||||
u32 client_index;
|
||||
u32 context;
|
||||
u8 is_add;
|
||||
vl_api_gbp_endpoint_group_t epg;
|
||||
};
|
||||
autoreply define gbp_endpoint_group_del
|
||||
{
|
||||
u32 client_index;
|
||||
u32 context;
|
||||
u16 epg_id;
|
||||
};
|
||||
|
||||
define gbp_endpoint_group_dump
|
||||
{
|
||||
@ -122,12 +208,19 @@ define gbp_recirc_details
|
||||
vl_api_gbp_recirc_t recirc;
|
||||
};
|
||||
|
||||
enum gbp_subnet_type
|
||||
{
|
||||
GBP_API_SUBNET_TRANSPORT,
|
||||
GBP_API_SUBNET_STITCHED_INTERNAL,
|
||||
GBP_API_SUBNET_STITCHED_EXTERNAL,
|
||||
};
|
||||
|
||||
typeonly define gbp_subnet
|
||||
{
|
||||
u32 table_id;
|
||||
u32 rd_id;
|
||||
u32 sw_if_index;
|
||||
u16 epg_id;
|
||||
u8 is_internal;
|
||||
vl_api_gbp_subnet_type_t type;
|
||||
vl_api_prefix_t prefix;
|
||||
};
|
||||
|
||||
@ -178,6 +271,70 @@ define gbp_contract_details
|
||||
vl_api_gbp_contract_t contract;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Set the time throeshold after which an endpoint is
|
||||
considered inative and is aged/reaped by the scanner
|
||||
* @param threshold In seconds
|
||||
*/
|
||||
autoreply define gbp_endpoint_learn_set_inactive_threshold
|
||||
{
|
||||
u32 client_index;
|
||||
u32 context;
|
||||
u32 threshold;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Configure a 'base' tunnel from which learned tunnels
|
||||
* are permitted to derive
|
||||
* A base tunnel consists only of the VNI, any src,dst IP
|
||||
* pair is thus allowed.
|
||||
*/
|
||||
enum gbp_vxlan_tunnel_mode
|
||||
{
|
||||
GBP_VXLAN_TUNNEL_MODE_L2,
|
||||
GBP_VXLAN_TUNNEL_MODE_L3,
|
||||
};
|
||||
|
||||
typedef gbp_vxlan_tunnel
|
||||
{
|
||||
u32 vni;
|
||||
vl_api_gbp_vxlan_tunnel_mode_t mode;
|
||||
u32 bd_rd_id;
|
||||
};
|
||||
|
||||
define gbp_vxlan_tunnel_add
|
||||
{
|
||||
u32 client_index;
|
||||
u32 context;
|
||||
vl_api_gbp_vxlan_tunnel_t tunnel;
|
||||
};
|
||||
|
||||
define gbp_vxlan_tunnel_add_reply
|
||||
{
|
||||
u32 context;
|
||||
i32 retval;
|
||||
u32 sw_if_index;
|
||||
};
|
||||
|
||||
autoreply define gbp_vxlan_tunnel_del
|
||||
{
|
||||
u32 client_index;
|
||||
u32 context;
|
||||
u32 vni;
|
||||
};
|
||||
|
||||
define gbp_vxlan_tunnel_dump
|
||||
{
|
||||
u32 client_index;
|
||||
u32 context;
|
||||
};
|
||||
|
||||
define gbp_vxlan_tunnel_details
|
||||
{
|
||||
u32 context;
|
||||
vl_api_gbp_vxlan_tunnel_t tunnel;
|
||||
};
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* eval: (c-set-style "gnu")
|
||||
|
File diff suppressed because it is too large
Load Diff
368
src/plugins/gbp/gbp_bridge_domain.c
Normal file
368
src/plugins/gbp/gbp_bridge_domain.c
Normal file
File diff suppressed because it is too large
Load Diff
80
src/plugins/gbp/gbp_bridge_domain.h
Normal file
80
src/plugins/gbp/gbp_bridge_domain.h
Normal file
@ -0,0 +1,80 @@
|
||||
/*
|
||||
* 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 __GBP_BRIDGE_DOMAIN_H__
|
||||
#define __GBP_BRIDGE_DOMAIN_H__
|
||||
|
||||
#include <plugins/gbp/gbp_types.h>
|
||||
|
||||
#include <vnet/fib/fib_types.h>
|
||||
|
||||
/**
|
||||
* A bridge Domain Representation.
|
||||
* This is a standard bridge-domain plus all the attributes it must
|
||||
* have to supprt the GBP model.
|
||||
*/
|
||||
typedef struct gpb_bridge_domain_t_
|
||||
{
|
||||
/**
|
||||
* Bridge-domain ID
|
||||
*/
|
||||
u32 gb_bd_id;
|
||||
u32 gb_bd_index;
|
||||
|
||||
/**
|
||||
* The BD's BVI interface (obligatory)
|
||||
*/
|
||||
u32 gb_bvi_sw_if_index;
|
||||
|
||||
/**
|
||||
* The BD's MAC spine-proxy interface (optional)
|
||||
*/
|
||||
u32 gb_uu_fwd_sw_if_index;
|
||||
|
||||
/**
|
||||
* The BD's VNI interface on which packets from unkown endpoints
|
||||
* arrive
|
||||
*/
|
||||
u32 gb_vni_sw_if_index;
|
||||
|
||||
/**
|
||||
* locks/references to the BD so it does not get deleted (from the API)
|
||||
* whilst it is still being used
|
||||
*/
|
||||
u32 gb_locks;
|
||||
} gbp_bridge_domain_t;
|
||||
|
||||
extern int gbp_bridge_domain_add_and_lock (u32 bd_id,
|
||||
u32 bvi_sw_if_index,
|
||||
u32 uu_fwd_sw_if_index);
|
||||
extern void gbp_bridge_domain_unlock (index_t gbi);
|
||||
extern index_t gbp_bridge_domain_find_and_lock (u32 bd_id);
|
||||
extern int gbp_bridge_domain_delete (u32 bd_id);
|
||||
extern gbp_bridge_domain_t *gbp_bridge_domain_get (index_t i);
|
||||
|
||||
typedef int (*gbp_bridge_domain_cb_t) (gbp_bridge_domain_t * gb, void *ctx);
|
||||
extern void gbp_bridge_domain_walk (gbp_bridge_domain_cb_t bgpe, void *ctx);
|
||||
|
||||
extern u8 *format_gbp_bridge_domain (u8 * s, va_list * args);
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* fd.io coding-style-patch-verification: ON
|
||||
*
|
||||
* Local Variables:
|
||||
* eval: (c-set-style "gnu")
|
||||
* End:
|
||||
*/
|
@ -18,6 +18,8 @@
|
||||
#include <plugins/gbp/gbp.h>
|
||||
#include <vnet/l2/l2_input.h>
|
||||
#include <vnet/l2/feat_bitmap.h>
|
||||
#include <vnet/fib/fib_table.h>
|
||||
#include <vnet/vxlan-gbp/vxlan_gbp_packet.h>
|
||||
|
||||
typedef enum gbp_src_classify_type_t_
|
||||
{
|
||||
@ -56,7 +58,7 @@ always_inline uword
|
||||
gbp_classify_inline (vlib_main_t * vm,
|
||||
vlib_node_runtime_t * node,
|
||||
vlib_frame_t * frame,
|
||||
gbp_src_classify_type_t type, u8 is_l3)
|
||||
gbp_src_classify_type_t type, dpo_proto_t dproto)
|
||||
{
|
||||
gbp_src_classify_main_t *gscm = &gbp_src_classify_main;
|
||||
u32 n_left_from, *from, *to_next;
|
||||
@ -75,7 +77,7 @@ gbp_classify_inline (vlib_main_t * vm,
|
||||
while (n_left_from > 0 && n_left_to_next > 0)
|
||||
{
|
||||
u32 next0, bi0, src_epg, sw_if_index0;
|
||||
const gbp_endpoint_t *gep0;
|
||||
const gbp_endpoint_t *ge0;
|
||||
vlib_buffer_t *b0;
|
||||
|
||||
bi0 = from[0];
|
||||
@ -88,6 +90,7 @@ gbp_classify_inline (vlib_main_t * vm,
|
||||
b0 = vlib_get_buffer (vm, bi0);
|
||||
|
||||
sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
|
||||
vnet_buffer2 (b0)->gbp.flags = VXLAN_GBP_GPFLAGS_NONE;
|
||||
|
||||
if (GBP_SRC_CLASSIFY_NULL == type)
|
||||
{
|
||||
@ -98,10 +101,46 @@ gbp_classify_inline (vlib_main_t * vm,
|
||||
}
|
||||
else
|
||||
{
|
||||
gep0 = gbp_endpoint_get_itf (sw_if_index0);
|
||||
src_epg = gep0->ge_epg_id;
|
||||
if (is_l3)
|
||||
if (DPO_PROTO_ETHERNET == dproto)
|
||||
{
|
||||
const ethernet_header_t *h0;
|
||||
|
||||
h0 = vlib_buffer_get_current (b0);
|
||||
next0 =
|
||||
vnet_l2_feature_next (b0, gscm->l2_input_feat_next[type],
|
||||
L2INPUT_FEAT_GBP_SRC_CLASSIFY);
|
||||
ge0 = gbp_endpoint_find_mac (h0->src_address,
|
||||
vnet_buffer (b0)->l2.bd_index);
|
||||
}
|
||||
else if (DPO_PROTO_IP4 == dproto)
|
||||
{
|
||||
const ip4_header_t *h0;
|
||||
|
||||
h0 = vlib_buffer_get_current (b0);
|
||||
|
||||
ge0 = gbp_endpoint_find_ip4
|
||||
(&h0->src_address,
|
||||
fib_table_get_index_for_sw_if_index (FIB_PROTOCOL_IP4,
|
||||
sw_if_index0));
|
||||
|
||||
|
||||
/*
|
||||
* Go straight to looukp, do not pass go, do not collect $200
|
||||
*/
|
||||
next0 = 0;
|
||||
}
|
||||
else if (DPO_PROTO_IP6 == dproto)
|
||||
{
|
||||
const ip6_header_t *h0;
|
||||
|
||||
h0 = vlib_buffer_get_current (b0);
|
||||
|
||||
ge0 = gbp_endpoint_find_ip6
|
||||
(&h0->src_address,
|
||||
fib_table_get_index_for_sw_if_index (FIB_PROTOCOL_IP6,
|
||||
sw_if_index0));
|
||||
|
||||
|
||||
/*
|
||||
* Go straight to lookup, do not pass go, do not collect $200
|
||||
*/
|
||||
@ -109,10 +148,15 @@ gbp_classify_inline (vlib_main_t * vm,
|
||||
}
|
||||
else
|
||||
{
|
||||
next0 =
|
||||
vnet_l2_feature_next (b0, gscm->l2_input_feat_next[type],
|
||||
L2INPUT_FEAT_GBP_SRC_CLASSIFY);
|
||||
ge0 = NULL;
|
||||
next0 = 0;
|
||||
ASSERT (0);
|
||||
}
|
||||
|
||||
if (PREDICT_TRUE (NULL != ge0))
|
||||
src_epg = ge0->ge_epg_id;
|
||||
else
|
||||
src_epg = EPG_INVALID;
|
||||
}
|
||||
|
||||
vnet_buffer2 (b0)->gbp.src_epg = src_epg;
|
||||
@ -139,28 +183,32 @@ static uword
|
||||
gbp_src_classify (vlib_main_t * vm,
|
||||
vlib_node_runtime_t * node, vlib_frame_t * frame)
|
||||
{
|
||||
return (gbp_classify_inline (vm, node, frame, GBP_SRC_CLASSIFY_PORT, 0));
|
||||
return (gbp_classify_inline (vm, node, frame,
|
||||
GBP_SRC_CLASSIFY_PORT, DPO_PROTO_ETHERNET));
|
||||
}
|
||||
|
||||
static uword
|
||||
gbp_null_classify (vlib_main_t * vm,
|
||||
vlib_node_runtime_t * node, vlib_frame_t * frame)
|
||||
{
|
||||
return (gbp_classify_inline (vm, node, frame, GBP_SRC_CLASSIFY_NULL, 0));
|
||||
return (gbp_classify_inline (vm, node, frame,
|
||||
GBP_SRC_CLASSIFY_NULL, DPO_PROTO_ETHERNET));
|
||||
}
|
||||
|
||||
static uword
|
||||
gbp_ip4_src_classify (vlib_main_t * vm,
|
||||
vlib_node_runtime_t * node, vlib_frame_t * frame)
|
||||
{
|
||||
return (gbp_classify_inline (vm, node, frame, 0, 1));
|
||||
return (gbp_classify_inline (vm, node, frame,
|
||||
GBP_SRC_CLASSIFY_PORT, DPO_PROTO_IP4));
|
||||
}
|
||||
|
||||
static uword
|
||||
gbp_ip6_src_classify (vlib_main_t * vm,
|
||||
vlib_node_runtime_t * node, vlib_frame_t * frame)
|
||||
{
|
||||
return (gbp_classify_inline (vm, node, frame, 0, 1));
|
||||
return (gbp_classify_inline (vm, node, frame,
|
||||
GBP_SRC_CLASSIFY_PORT, DPO_PROTO_IP6));
|
||||
}
|
||||
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user