vom: Add TAPv2 support

Change-Id: I1fff014dd7d8a66ed3cb063e8c996de4f7e745c2
Signed-off-by: Mohsin Kazmi <sykazmi@cisco.com>
This commit is contained in:
Mohsin Kazmi
2018-07-04 15:17:01 +02:00
committed by Neale Ranns
parent 858151ff84
commit 9aca7b5ee9
11 changed files with 383 additions and 176 deletions

View File

@ -23,6 +23,7 @@
#include "vom/logger.hpp"
#include "vom/prefix.hpp"
#include "vom/singular_db_funcs.hpp"
#include "vom/tap_interface_cmds.hpp"
namespace VOM {
/**
@ -286,8 +287,7 @@ interface::mk_create_cmd(std::queue<cmd*>& q)
q.push(new interface_cmds::af_packet_create_cmd(m_hdl, m_name));
if (!m_tag.empty())
q.push(new interface_cmds::set_tag(m_hdl, m_tag));
} else if (type_t::TAP == m_type) {
q.push(new interface_cmds::tap_create_cmd(m_hdl, m_name));
} else if (type_t::TAP == m_type || type_t::TAPV2 == m_type) {
if (!m_tag.empty())
q.push(new interface_cmds::set_tag(m_hdl, m_tag));
} else if (type_t::VHOST == m_type) {
@ -306,8 +306,6 @@ interface::mk_delete_cmd(std::queue<cmd*>& q)
q.push(new interface_cmds::loopback_delete_cmd(m_hdl));
} else if (type_t::AFPACKET == m_type) {
q.push(new interface_cmds::af_packet_delete_cmd(m_hdl, m_name));
} else if (type_t::TAP == m_type) {
q.push(new interface_cmds::tap_delete_cmd(m_hdl));
} else if (type_t::VHOST == m_type) {
q.push(new interface_cmds::vhost_delete_cmd(m_hdl, m_name));
}
@ -491,7 +489,7 @@ void
interface::event_handler::handle_populate(const client_db::key_t& key)
{
/*
* dump VPP current states
* dump VPP vhost-user interfaces
*/
std::shared_ptr<interface_cmds::vhost_dump_cmd> vcmd =
std::make_shared<interface_cmds::vhost_dump_cmd>();
@ -507,6 +505,9 @@ interface::event_handler::handle_populate(const client_db::key_t& key)
OM::commit(key, *vitf);
}
/*
* dump VPP af-packet interfaces
*/
std::shared_ptr<interface_cmds::af_packet_dump_cmd> afcmd =
std::make_shared<interface_cmds::af_packet_dump_cmd>();
@ -521,6 +522,53 @@ interface::event_handler::handle_populate(const client_db::key_t& key)
OM::commit(key, *afitf);
}
/*
* dump VPP tap interfaces
*/
std::shared_ptr<tap_interface_cmds::tap_dump_cmd> tapcmd =
std::make_shared<tap_interface_cmds::tap_dump_cmd>();
HW::enqueue(tapcmd);
HW::write();
for (auto& tap_record : *tapcmd) {
std::shared_ptr<tap_interface> tapitf =
interface_factory::new_tap_interface(tap_record.get_payload());
VOM_LOG(log_level_t::DEBUG) << "tap-dump: " << tapitf->to_string();
/*
* Write each of the discovered interfaces into the OM,
* but disable the HW Command q whilst we do, so that no
* commands are sent to VPP
*/
OM::commit(key, *tapitf);
}
/*
* dump VPP tapv2 interfaces
*/
std::shared_ptr<tap_interface_cmds::tapv2_dump_cmd> tapv2cmd =
std::make_shared<tap_interface_cmds::tapv2_dump_cmd>();
HW::enqueue(tapv2cmd);
HW::write();
for (auto& tapv2_record : *tapv2cmd) {
std::shared_ptr<tap_interface> tapv2itf =
interface_factory::new_tap_v2_interface(tapv2_record.get_payload());
VOM_LOG(log_level_t::DEBUG) << "tapv2-dump: " << tapv2itf->to_string();
/*
* Write each of the discovered interfaces into the OM,
* but disable the HW Command q whilst we do, so that no
* commands are sent to VPP
*/
OM::commit(key, *tapv2itf);
}
/*
* dump VPP interfaces
*/
std::shared_ptr<interface_cmds::dump_cmd> cmd =
std::make_shared<interface_cmds::dump_cmd>();
@ -567,6 +615,9 @@ interface::event_handler::handle_populate(const client_db::key_t& key)
}
}
/*
* dump VPP bond interfaces
*/
std::shared_ptr<bond_interface_cmds::dump_cmd> bcmd =
std::make_shared<bond_interface_cmds::dump_cmd>();

View File

@ -99,6 +99,11 @@ public:
*/
const static type_t TAP;
/**
* TAPv2 interface type
*/
const static type_t TAPV2;
/**
* vhost-user interface type
*/

View File

@ -19,7 +19,6 @@
DEFINE_VAPI_MSG_IDS_VPE_API_JSON;
DEFINE_VAPI_MSG_IDS_INTERFACE_API_JSON;
DEFINE_VAPI_MSG_IDS_AF_PACKET_API_JSON;
DEFINE_VAPI_MSG_IDS_TAP_API_JSON;
DEFINE_VAPI_MSG_IDS_VHOST_USER_API_JSON;
DEFINE_VAPI_MSG_IDS_STATS_API_JSON;
@ -92,44 +91,6 @@ af_packet_create_cmd::to_string() const
return (s.str());
}
tap_create_cmd::tap_create_cmd(HW::item<handle_t>& item,
const std::string& name)
: create_cmd(item, name)
{
}
rc_t
tap_create_cmd::issue(connection& con)
{
msg_t req(con.ctx(), std::ref(*this));
auto& payload = req.get_request().get_payload();
memset(payload.tap_name, 0, sizeof(payload.tap_name));
memcpy(payload.tap_name, m_name.c_str(),
std::min(m_name.length(), sizeof(payload.tap_name)));
payload.use_random_mac = 1;
VAPI_CALL(req.execute());
m_hw_item = wait();
if (m_hw_item.rc() == rc_t::OK) {
insert_interface();
}
return rc_t::OK;
}
std::string
tap_create_cmd::to_string() const
{
std::ostringstream s;
s << "tap-intf-create: " << m_hw_item.to_string() << " name:" << m_name;
return (s.str());
}
vhost_create_cmd::vhost_create_cmd(HW::item<handle_t>& item,
const std::string& name,
const std::string& tag)
@ -242,28 +203,6 @@ af_packet_delete_cmd::to_string() const
return (s.str());
}
tap_delete_cmd::tap_delete_cmd(HW::item<handle_t>& item)
: delete_cmd(item)
{
}
rc_t
tap_delete_cmd::issue(connection& con)
{
// finally... call VPP
remove_interface();
return rc_t::OK;
}
std::string
tap_delete_cmd::to_string() const
{
std::ostringstream s;
s << "tap-itf-delete: " << m_hw_item.to_string();
return (s.str());
}
vhost_delete_cmd::vhost_delete_cmd(HW::item<handle_t>& item,
const std::string& name)
: delete_cmd(item, name)
@ -470,13 +409,13 @@ rc_t
events_cmd::issue(connection& con)
{
/*
* First set the call back to handle the interface events
*/
* First set the call back to handle the interface events
*/
m_reg.reset(new reg_t(con.ctx(), std::ref(*(static_cast<event_cmd*>(this)))));
/*
* then send the request to enable them
*/
* then send the request to enable them
*/
msg_t req(con.ctx(), std::ref(*(static_cast<rpc_cmd*>(this))));
auto& payload = req.get_request().get_payload();
@ -494,8 +433,8 @@ void
events_cmd::retire(connection& con)
{
/*
* disable interface events.
*/
* disable interface events.
*/
msg_t req(con.ctx(), std::ref(*(static_cast<rpc_cmd*>(this))));
auto& payload = req.get_request().get_payload();

View File

@ -86,30 +86,6 @@ public:
std::string to_string() const;
};
/**
* A command class to create TAP interfaces in VPP
*/
class tap_create_cmd : public interface::create_cmd<vapi::Tap_connect>
{
public:
/**
* Constructor taking the HW::item to update
* and the name of the interface to create
*/
tap_create_cmd(HW::item<handle_t>& item, const std::string& name);
~tap_create_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;
};
/**
* A functor class that creates an interface
*/
@ -178,27 +154,6 @@ public:
std::string to_string() const;
};
/**
* A command class to delete TAP interfaces in VPP
*/
class tap_delete_cmd : public interface::delete_cmd<vapi::Tap_delete>
{
public:
/**
* Constructor taking the HW::item to update
*/
tap_delete_cmd(HW::item<handle_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;
};
/**
* A functor class that deletes a Vhost interface
*/

View File

@ -72,11 +72,11 @@ interface_factory::new_interface(const vapi_payload_sw_interface_details& vd)
/*
* pull out the other special cases
*/
if (interface::type_t::TAP == type) {
if (interface::type_t::TAP == type || interface::type_t::TAPV2 == type) {
/*
* TAP interface
* TAP interfaces
*/
sp = tap_interface(name, state, route::prefix_t()).singular();
sp = interface::find(hdl);
if (sp && !tag.empty())
sp->set(tag);
} else if ((name.find(".") != std::string::npos) && (0 != vd.sub_id)) {
@ -153,6 +153,48 @@ interface_factory::new_af_packet_interface(
return (sp);
}
std::shared_ptr<tap_interface>
interface_factory::new_tap_interface(
const vapi_payload_sw_interface_tap_details& vd)
{
std::shared_ptr<tap_interface> sp;
std::string name = reinterpret_cast<const char*>(vd.dev_name);
handle_t hdl(vd.sw_if_index);
sp = tap_interface(name, interface::type_t::TAP, interface::admin_state_t::UP,
route::prefix_t::ZERO)
.singular();
sp->set(hdl);
return (sp);
}
std::shared_ptr<tap_interface>
interface_factory::new_tap_v2_interface(
const vapi_payload_sw_interface_tap_v2_details& vd)
{
std::shared_ptr<tap_interface> sp;
handle_t hdl(vd.sw_if_index);
std::string name = reinterpret_cast<const char*>(vd.host_if_name);
route::prefix_t pfx(route::prefix_t::ZERO);
boost::asio::ip::address addr;
if (vd.host_ip4_prefix_len)
pfx =
route::prefix_t(0, (uint8_t*)vd.host_ip4_addr, vd.host_ip4_prefix_len);
else if (vd.host_ip6_prefix_len)
pfx =
route::prefix_t(1, (uint8_t*)vd.host_ip6_addr, vd.host_ip6_prefix_len);
l2_address_t l2_address(vd.host_mac_addr, 6);
sp = tap_interface(name, interface::type_t::TAPV2,
interface::admin_state_t::UP, pfx, l2_address)
.singular();
sp->set(hdl);
return (sp);
}
std::shared_ptr<bond_interface>
interface_factory::new_bond_interface(
const vapi_payload_sw_interface_bond_details& vd)

View File

@ -20,10 +20,13 @@
#include "vom/bond_member.hpp"
#include "vom/interface.hpp"
#include "vom/tap_interface.hpp"
#include <vapi/af_packet.api.vapi.hpp>
#include <vapi/bond.api.vapi.hpp>
#include <vapi/interface.api.vapi.hpp>
#include <vapi/tap.api.vapi.hpp>
#include <vapi/tapv2.api.vapi.hpp>
#include <vapi/vhost_user.api.vapi.hpp>
namespace VOM {
@ -43,6 +46,12 @@ public:
static std::shared_ptr<interface> new_af_packet_interface(
const vapi_payload_af_packet_details& vd);
static std::shared_ptr<tap_interface> new_tap_interface(
const vapi_payload_sw_interface_tap_details& vd);
static std::shared_ptr<tap_interface> new_tap_v2_interface(
const vapi_payload_sw_interface_tap_v2_details& vd);
static std::shared_ptr<bond_interface> new_bond_interface(
const vapi_payload_sw_interface_bond_details& vd);

View File

@ -26,8 +26,9 @@ const interface::type_t interface::type_t::AFPACKET(4, "AFPACKET");
const interface::type_t interface::type_t::LOOPBACK(5, "LOOPBACK");
const interface::type_t interface::type_t::LOCAL(6, "LOCAL");
const interface::type_t interface::type_t::TAP(7, "TAP");
const interface::type_t interface::type_t::VHOST(8, "VHOST");
const interface::type_t interface::type_t::BOND(9, "Bond");
const interface::type_t interface::type_t::TAPV2(8, "TAPV2");
const interface::type_t interface::type_t::VHOST(9, "VHOST");
const interface::type_t interface::type_t::BOND(10, "Bond");
const interface::oper_state_t interface::oper_state_t::DOWN(0, "down");
const interface::oper_state_t interface::oper_state_t::UP(1, "up");
@ -58,8 +59,11 @@ interface::type_t::from_string(const std::string& str)
return interface::type_t::AFPACKET;
} else if (str.find("local") != std::string::npos) {
return interface::type_t::LOCAL;
} else if (str.find("tap") != std::string::npos) {
} else if ((str.find("tapcli") != std::string::npos) ||
(str.find("tuntap") != std::string::npos)) {
return interface::type_t::TAP;
} else if (str.find("tap") != std::string::npos) {
return interface::type_t::TAPV2;
} else if (str.find("bvi") != std::string::npos) {
return interface::type_t::BVI;
}

View File

@ -25,19 +25,21 @@ tap_interface::event_handler tap_interface::m_evh;
* Construct a new object matching the desried state
*/
tap_interface::tap_interface(const std::string& name,
type_t type,
admin_state_t state,
route::prefix_t prefix)
: interface(name, type_t::TAP, state)
: interface(name, type, state)
, m_prefix(prefix)
, m_l2_address(l2_address_t::ZERO)
{
}
tap_interface::tap_interface(const std::string& name,
type_t type,
admin_state_t state,
route::prefix_t prefix,
const l2_address_t& l2_address)
: interface(name, type_t::TAP, state)
: interface(name, type, state)
, m_prefix(prefix)
, m_l2_address(l2_address)
{
@ -59,8 +61,12 @@ tap_interface::tap_interface(const tap_interface& o)
std::queue<cmd*>&
tap_interface::mk_create_cmd(std::queue<cmd*>& q)
{
q.push(
new tap_interface_cmds::create_cmd(m_hdl, name(), m_prefix, m_l2_address));
if (type_t::TAPV2 == type())
q.push(new tap_interface_cmds::tapv2_create_cmd(m_hdl, name(), m_prefix,
m_l2_address));
else
q.push(new tap_interface_cmds::tap_create_cmd(m_hdl, name(), m_prefix,
m_l2_address));
return (q);
}
@ -68,7 +74,10 @@ tap_interface::mk_create_cmd(std::queue<cmd*>& q)
std::queue<cmd*>&
tap_interface::mk_delete_cmd(std::queue<cmd*>& q)
{
q.push(new tap_interface_cmds::delete_cmd(m_hdl));
if (type_t::TAPV2 == type())
q.push(new tap_interface_cmds::tapv2_delete_cmd(m_hdl));
else
q.push(new tap_interface_cmds::tap_delete_cmd(m_hdl));
return (q);
}
@ -88,32 +97,7 @@ tap_interface::singular_i() const
void
tap_interface::event_handler::handle_populate(const client_db::key_t& key)
{
/*
* dump VPP current states
*/
std::shared_ptr<tap_interface_cmds::dump_cmd> cmd =
std::make_shared<tap_interface_cmds::dump_cmd>();
HW::enqueue(cmd);
HW::write();
for (auto& record : *cmd) {
auto& payload = record.get_payload();
std::string name = reinterpret_cast<const char*>(payload.dev_name);
tap_interface itf(name, interface::admin_state_t::UP,
route::prefix_t::ZERO);
VOM_LOG(log_level_t::DEBUG) << "tap-dump: " << itf.to_string();
/*
* Write each of the discovered interfaces into the OM,
* but disable the HW Command q whilst we do, so that no
* commands are sent to VPP
*/
OM::commit(key, itf);
}
// It will be polulate by interface handler
}
tap_interface::event_handler::event_handler()

View File

@ -26,10 +26,12 @@ class tap_interface : public interface
{
public:
tap_interface(const std::string& name,
type_t type,
admin_state_t state,
route::prefix_t prefix);
tap_interface(const std::string& name,
type_t type,
admin_state_t state,
route::prefix_t prefix,
const l2_address_t& l2_address);
@ -75,10 +77,13 @@ private:
static event_handler m_evh;
/**
* Ip Prefix
* host Ip Prefix
*/
route::prefix_t m_prefix;
/**
* host mac address
*/
l2_address_t m_l2_address;
/**

View File

@ -16,13 +16,17 @@
#include "vom/tap_interface_cmds.hpp"
#include <vapi/tap.api.vapi.hpp>
#include <vapi/tapv2.api.vapi.hpp>
DEFINE_VAPI_MSG_IDS_TAP_API_JSON;
DEFINE_VAPI_MSG_IDS_TAPV2_API_JSON;
namespace VOM {
namespace tap_interface_cmds {
create_cmd::create_cmd(HW::item<handle_t>& item,
const std::string& name,
route::prefix_t& prefix,
const l2_address_t& l2_address)
tap_create_cmd::tap_create_cmd(HW::item<handle_t>& item,
const std::string& name,
route::prefix_t& prefix,
const l2_address_t& l2_address)
: interface::create_cmd<vapi::Tap_connect>(item, name)
, m_prefix(prefix)
, m_l2_address(l2_address)
@ -30,7 +34,7 @@ create_cmd::create_cmd(HW::item<handle_t>& item,
}
rc_t
create_cmd::issue(connection& con)
tap_create_cmd::issue(connection& con)
{
msg_t req(con.ctx(), std::ref(*this));
@ -58,12 +62,15 @@ create_cmd::issue(connection& con)
VAPI_CALL(req.execute());
m_hw_item = wait();
if (m_hw_item.rc() == rc_t::OK) {
insert_interface();
}
return rc_t::OK;
}
std::string
create_cmd::to_string() const
tap_create_cmd::to_string() const
{
std::ostringstream s;
s << "tap-intf-create: " << m_hw_item.to_string()
@ -72,20 +79,30 @@ create_cmd::to_string() const
return (s.str());
}
delete_cmd::delete_cmd(HW::item<handle_t>& item)
tap_delete_cmd::tap_delete_cmd(HW::item<handle_t>& item)
: interface::delete_cmd<vapi::Tap_delete>(item)
{
}
rc_t
delete_cmd::issue(connection& con)
tap_delete_cmd::issue(connection& con)
{
// finally... call VPP
msg_t req(con.ctx(), std::ref(*this));
auto& payload = req.get_request().get_payload();
payload.sw_if_index = m_hw_item.data().value();
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
tap_delete_cmd::to_string() const
{
std::ostringstream s;
s << "tap-itf-delete: " << m_hw_item.to_string();
@ -93,18 +110,18 @@ delete_cmd::to_string() const
return (s.str());
}
dump_cmd::dump_cmd()
tap_dump_cmd::tap_dump_cmd()
{
}
bool
dump_cmd::operator==(const dump_cmd& other) const
tap_dump_cmd::operator==(const tap_dump_cmd& other) const
{
return (true);
}
rc_t
dump_cmd::issue(connection& con)
tap_dump_cmd::issue(connection& con)
{
m_dump.reset(new msg_t(con.ctx(), std::ref(*this)));
@ -116,10 +133,136 @@ dump_cmd::issue(connection& con)
}
std::string
dump_cmd::to_string() const
tap_dump_cmd::to_string() const
{
return ("tap-itf-dump");
}
/*
* TAPV2
*/
tapv2_create_cmd::tapv2_create_cmd(HW::item<handle_t>& item,
const std::string& name,
route::prefix_t& prefix,
const l2_address_t& l2_address)
: interface::create_cmd<vapi::Tap_create_v2>(item, name)
, m_prefix(prefix)
, m_l2_address(l2_address)
{
}
rc_t
tapv2_create_cmd::issue(connection& con)
{
msg_t req(con.ctx(), std::ref(*this));
auto& payload = req.get_request().get_payload();
memset(payload.host_if_name, 0, sizeof(payload.host_if_name));
memcpy(payload.host_if_name, m_name.c_str(),
std::min(m_name.length(), sizeof(payload.host_if_name)));
payload.host_if_name_set = 1;
if (m_prefix != route::prefix_t::ZERO) {
if (m_prefix.address().is_v6()) {
m_prefix.to_vpp(&payload.host_ip6_addr_set, payload.host_ip6_addr,
&payload.host_ip6_prefix_len);
} else {
m_prefix.to_vpp(&payload.host_ip4_addr_set, payload.host_ip4_addr,
&payload.host_ip4_prefix_len);
payload.host_ip4_addr_set = 1;
}
}
if (m_l2_address != l2_address_t::ZERO) {
m_l2_address.to_bytes(payload.host_mac_addr, 6);
payload.host_mac_addr_set = 1;
}
payload.id = 0xffffffff;
payload.use_random_mac = 1;
payload.tx_ring_sz = 1024;
payload.rx_ring_sz = 1024;
VAPI_CALL(req.execute());
m_hw_item = wait();
if (m_hw_item.rc() == rc_t::OK) {
insert_interface();
}
return rc_t::OK;
}
std::string
tapv2_create_cmd::to_string() const
{
std::ostringstream s;
s << "tapv2-intf-create: " << m_hw_item.to_string()
<< " ip-prefix:" << m_prefix.to_string();
return (s.str());
}
tapv2_delete_cmd::tapv2_delete_cmd(HW::item<handle_t>& item)
: interface::delete_cmd<vapi::Tap_delete_v2>(item)
{
}
rc_t
tapv2_delete_cmd::issue(connection& con)
{
msg_t req(con.ctx(), std::ref(*this));
auto& payload = req.get_request().get_payload();
payload.sw_if_index = m_hw_item.data().value();
VAPI_CALL(req.execute());
wait();
m_hw_item.set(rc_t::NOOP);
remove_interface();
return rc_t::OK;
}
std::string
tapv2_delete_cmd::to_string() const
{
std::ostringstream s;
s << "tapv2-itf-delete: " << m_hw_item.to_string();
return (s.str());
}
tapv2_dump_cmd::tapv2_dump_cmd()
{
}
bool
tapv2_dump_cmd::operator==(const tapv2_dump_cmd& other) const
{
return (true);
}
rc_t
tapv2_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
tapv2_dump_cmd::to_string() const
{
return ("tapv2-itf-dump");
}
} // namespace tap_interface_cmds
} // namespace VOM

View File

@ -23,6 +23,7 @@
#include <vapi/interface.api.vapi.hpp>
#include <vapi/tap.api.vapi.hpp>
#include <vapi/tapv2.api.vapi.hpp>
namespace VOM {
namespace tap_interface_cmds {
@ -30,10 +31,10 @@ namespace tap_interface_cmds {
/**
* A functor class that creates an interface
*/
class create_cmd : public interface::create_cmd<vapi::Tap_connect>
class tap_create_cmd : public interface::create_cmd<vapi::Tap_connect>
{
public:
create_cmd(HW::item<handle_t>& item,
tap_create_cmd(HW::item<handle_t>& item,
const std::string& name,
route::prefix_t& prefix,
const l2_address_t& l2_address);
@ -55,10 +56,10 @@ private:
/**
* A functor class that deletes a Tap interface
*/
class delete_cmd : public interface::delete_cmd<vapi::Tap_delete>
class tap_delete_cmd : public interface::delete_cmd<vapi::Tap_delete>
{
public:
delete_cmd(HW::item<handle_t>& item);
tap_delete_cmd(HW::item<handle_t>& item);
/**
* Issue the command to VPP/HW
@ -73,13 +74,13 @@ public:
/**
* A cmd class that Dumps all the Vpp Interfaces
*/
class dump_cmd : public VOM::dump_cmd<vapi::Sw_interface_tap_dump>
class tap_dump_cmd : public VOM::dump_cmd<vapi::Sw_interface_tap_dump>
{
public:
/**
* Default Constructor
*/
dump_cmd();
tap_dump_cmd();
/**
* Issue the command to VPP/HW
@ -93,7 +94,76 @@ public:
/**
* Comparison operator - only used for UT
*/
bool operator==(const dump_cmd& i) const;
bool operator==(const tap_dump_cmd& i) const;
};
/**
* A functor class that creates an interface
*/
class tapv2_create_cmd : public interface::create_cmd<vapi::Tap_create_v2>
{
public:
tapv2_create_cmd(HW::item<handle_t>& item,
const std::string& name,
route::prefix_t& prefix,
const l2_address_t& l2_address);
/**
* Issue the command to VPP/HW
*/
rc_t issue(connection& con);
/**
* convert to string format for debug purposes
*/
std::string to_string() const;
private:
route::prefix_t& m_prefix;
const l2_address_t& m_l2_address;
};
/**
* A functor class that deletes a Tap interface
*/
class tapv2_delete_cmd : public interface::delete_cmd<vapi::Tap_delete_v2>
{
public:
tapv2_delete_cmd(HW::item<handle_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;
};
/**
* A cmd class that Dumps all the Vpp Interfaces
*/
class tapv2_dump_cmd : public VOM::dump_cmd<vapi::Sw_interface_tap_v2_dump>
{
public:
/**
* Default Constructor
*/
tapv2_dump_cmd();
/**
* 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 tapv2_dump_cmd& i) const;
};
}; // namespace tap_interface_cmds