neighbour_cmds.cpp \
object_base.cpp \
om.cpp \
+ pipe.cpp \
+ pipe_cmds.cpp \
prefix.cpp \
ra_config.cpp \
ra_prefix.cpp \
neighbour.hpp \
object_base.hpp \
om.hpp \
+ pipe.hpp \
prefix.hpp \
ra_config.hpp \
ra_prefix.hpp \
VAPI_CALL(req.execute());
- m_hw_item.set(wait());
-
- return rc_t::OK;
+ return (wait());
}
template <>
VAPI_CALL(req.execute());
- m_hw_item.set(wait());
-
- return rc_t::OK;
+ return (wait());
}
template <>
VAPI_CALL(req.execute());
- m_hw_item.set(wait());
-
- return rc_t::OK;
+ return (wait());
}
template <>
VAPI_CALL(req.execute());
- m_hw_item.set(wait());
-
- return rc_t::OK;
+ return (wait());
}
template <>
* A command class that binds the ACL to the interface
*/
template <typename BIND>
-class bind_cmd : public rpc_cmd<HW::item<bool>, rc_t, BIND>
+class bind_cmd : public rpc_cmd<HW::item<bool>, BIND>
{
public:
/**
const direction_t& direction,
const handle_t& itf,
const handle_t& acl)
- : rpc_cmd<HW::item<bool>, rc_t, BIND>(item)
+ : rpc_cmd<HW::item<bool>, BIND>(item)
, m_direction(direction)
, m_itf(itf)
, m_acl(acl)
* A command class that binds the ACL to the interface
*/
template <typename BIND>
-class unbind_cmd : public rpc_cmd<HW::item<bool>, rc_t, BIND>
+class unbind_cmd : public rpc_cmd<HW::item<bool>, BIND>
{
public:
/**
const direction_t& direction,
const handle_t& itf,
const handle_t& acl)
- : rpc_cmd<HW::item<bool>, rc_t, BIND>(item)
+ : rpc_cmd<HW::item<bool>, BIND>(item)
, m_direction(direction)
, m_itf(itf)
, m_acl(acl)
VAPI_CALL(req.execute());
- m_hw_item.set(wait());
-
- return rc_t::OK;
+ return (wait());
}
std::string
/**
* A command class that binds the ethertype list to the interface
*/
-class bind_cmd : public rpc_cmd<HW::item<bool>,
- rc_t,
- vapi::Acl_interface_set_etype_whitelist>
+class bind_cmd
+ : public rpc_cmd<HW::item<bool>, vapi::Acl_interface_set_etype_whitelist>
{
public:
/**
/**
* A command class that unbinds the ethertype list to the interface
*/
-class unbind_cmd : public rpc_cmd<HW::item<bool>,
- rc_t,
- vapi::Acl_interface_set_etype_whitelist>
+class unbind_cmd
+ : public rpc_cmd<HW::item<bool>, vapi::Acl_interface_set_etype_whitelist>
{
public:
/**
VAPI_CALL(req.execute());
- m_hw_item = wait();
+ wait();
+
if (m_hw_item.rc() == rc_t::OK)
insert_acl();
VAPI_CALL(req.execute());
- m_hw_item = wait();
+ wait();
+
if (m_hw_item.rc() == rc_t::OK)
insert_acl();
* A command class that Create the list
*/
template <typename RULE, typename UPDATE>
-class update_cmd
- : public rpc_cmd<HW::item<handle_t>, HW::item<handle_t>, UPDATE>
+class update_cmd : public rpc_cmd<HW::item<handle_t>, UPDATE>
{
public:
typedef typename list<RULE>::rules_t cmd_rules_t;
update_cmd(HW::item<handle_t>& item,
const cmd_key_t& key,
const cmd_rules_t& rules)
- : rpc_cmd<HW::item<handle_t>, HW::item<handle_t>, UPDATE>(item)
+ : rpc_cmd<HW::item<handle_t>, UPDATE>(item)
, m_key(key)
, m_rules(rules)
{
void succeeded()
{
- rpc_cmd<HW::item<handle_t>, HW::item<handle_t>, UPDATE>::succeeded();
+ rpc_cmd<HW::item<handle_t>, UPDATE>::succeeded();
list<RULE>::add(m_key, this->item());
}
* A cmd class that Deletes an ACL
*/
template <typename RULE, typename DELETE>
-class delete_cmd : public rpc_cmd<HW::item<handle_t>, rc_t, DELETE>
+class delete_cmd : public rpc_cmd<HW::item<handle_t>, DELETE>
{
public:
/**
* Constructor
*/
delete_cmd(HW::item<handle_t>& item)
- : rpc_cmd<HW::item<handle_t>, rc_t, DELETE>(item)
+ : rpc_cmd<HW::item<handle_t>, DELETE>(item)
{
}
VAPI_CALL(req.execute());
- m_hw_item.set(wait());
-
- return rc_t::OK;
+ return (wait());
}
std::string
* A command class that binds the LLDP config to the interface
*/
class bind_cmd
- : public rpc_cmd<HW::item<bool>, rc_t, vapi::Proxy_arp_intfc_enable_disable>
+ : public rpc_cmd<HW::item<bool>, vapi::Proxy_arp_intfc_enable_disable>
{
public:
/**
* A cmd class that Unbinds ArpProxy Config from an interface
*/
class unbind_cmd
- : public rpc_cmd<HW::item<bool>, rc_t, vapi::Proxy_arp_intfc_enable_disable>
+ : public rpc_cmd<HW::item<bool>, vapi::Proxy_arp_intfc_enable_disable>
{
public:
/**
VAPI_CALL(req.execute());
- m_hw_item.set(wait());
+ wait();
return (rc_t::OK);
}
/**
* A command class that adds the ARP Proxy config
*/
-class config_cmd : public rpc_cmd<HW::item<bool>, rc_t, vapi::Proxy_arp_add_del>
+class config_cmd : public rpc_cmd<HW::item<bool>, vapi::Proxy_arp_add_del>
{
public:
/**
/**
* A cmd class that Unconfigs ArpProxy Config from an interface
*/
-class unconfig_cmd
- : public rpc_cmd<HW::item<bool>, rc_t, vapi::Proxy_arp_add_del>
+class unconfig_cmd : public rpc_cmd<HW::item<bool>, vapi::Proxy_arp_add_del>
{
public:
/**
* We want enslaved interfaces bind to bond after interface
* but before anything else.
*/
- return (dependency_t::BOND_BINDING);
+ return (dependency_t::VIRTUAL_INTERFACE);
}
void
VAPI_CALL(req.execute());
- m_hw_item.set(wait());
-
- return rc_t::OK;
+ return (wait());
}
std::string
/**
* A command class that binds the slave interface to the bond interface
*/
-class bind_cmd : public rpc_cmd<HW::item<bool>, rc_t, vapi::Bond_enslave>
+class bind_cmd : public rpc_cmd<HW::item<bool>, vapi::Bond_enslave>
{
public:
/**
/**
* A cmd class that detach slave from a bond interface
*/
-class unbind_cmd : public rpc_cmd<HW::item<bool>, rc_t, vapi::Bond_detach_slave>
+class unbind_cmd : public rpc_cmd<HW::item<bool>, vapi::Bond_detach_slave>
{
public:
/**
VAPI_CALL(req.execute());
- m_hw_item = wait();
+ wait();
+
if (m_hw_item.rc() == rc_t::OK) {
insert_interface();
}
VAPI_CALL(req.execute());
- m_hw_item.set(wait());
-
- return rc_t::OK;
+ return (wait());
}
std::string
/**
* A command class that creates or updates the bridge domain ARP Entry
*/
-class create_cmd : public rpc_cmd<HW::item<bool>, rc_t, vapi::Bd_ip_mac_add_del>
+class create_cmd : public rpc_cmd<HW::item<bool>, vapi::Bd_ip_mac_add_del>
{
public:
/**
/**
* A cmd class that deletes a bridge domain ARP entry
*/
-class delete_cmd : public rpc_cmd<HW::item<bool>, rc_t, vapi::Bd_ip_mac_add_del>
+class delete_cmd : public rpc_cmd<HW::item<bool>, vapi::Bd_ip_mac_add_del>
{
public:
/**
VAPI_CALL(req.execute());
- m_hw_item.set(wait());
-
- return (rc_t::OK);
+ return (wait());
}
std::string
* A command class that creates an Bridge-Domain
*/
class create_cmd
- : public rpc_cmd<HW::item<uint32_t>, rc_t, vapi::Bridge_domain_add_del>
+ : public rpc_cmd<HW::item<uint32_t>, vapi::Bridge_domain_add_del>
{
public:
/**
* A cmd class that Delete an Bridge-Domain
*/
class delete_cmd
- : public rpc_cmd<HW::item<uint32_t>, rc_t, vapi::Bridge_domain_add_del>
+ : public rpc_cmd<HW::item<uint32_t>, vapi::Bridge_domain_add_del>
{
public:
/**
VAPI_CALL(req.execute());
- m_hw_item.set(wait());
-
- return rc_t::OK;
+ return (wait());
}
std::string
/**
* A command class that creates or updates the bridge_domain
*/
-class create_cmd : public rpc_cmd<HW::item<bool>, rc_t, vapi::L2fib_add_del>
+class create_cmd : public rpc_cmd<HW::item<bool>, vapi::L2fib_add_del>
{
public:
/**
/**
* A cmd class that deletes a bridge_domain
*/
-class delete_cmd : public rpc_cmd<HW::item<bool>, rc_t, vapi::L2fib_add_del>
+class delete_cmd : public rpc_cmd<HW::item<bool>, vapi::L2fib_add_del>
{
public:
/**
VAPI_CALL(req.execute());
- m_hw_item.set(wait());
-
- return rc_t::OK;
+ return (wait());
}
std::string
/**
* A command class that binds the DHCP config to the interface
*/
-class bind_cmd : public rpc_cmd<HW::item<bool>, rc_t, vapi::Dhcp_client_config>
+class bind_cmd : public rpc_cmd<HW::item<bool>, vapi::Dhcp_client_config>
{
public:
/**
/**
* A cmd class that Unbinds Dhcp Config from an interface
*/
-class unbind_cmd
- : public rpc_cmd<HW::item<bool>, rc_t, vapi::Dhcp_client_config>
+class unbind_cmd : public rpc_cmd<HW::item<bool>, vapi::Dhcp_client_config>
{
public:
/**
* The client can then 'pop' these events from this command object.
*/
template <typename WANT, typename EVENT>
-class event_cmd : public rpc_cmd<HW::item<bool>, rc_t, WANT>
+class event_cmd : public rpc_cmd<HW::item<bool>, WANT>
{
public:
/**
* Default constructor
*/
event_cmd(HW::item<bool>& b)
- : rpc_cmd<HW::item<bool>, rc_t, WANT>(b)
+ : rpc_cmd<HW::item<bool>, WANT>(b)
{
}
VAPI_CALL(req.execute());
- m_hw_item.set(wait());
-
- return rc_t::OK;
+ return (wait());
}
std::string
VAPI_CALL(req.execute());
- m_hw_item.set(wait());
-
- return rc_t::OK;
+ return (wait());
}
std::string
/**
* A command class that creates or updates the GBP contract
*/
-class create_cmd
- : public rpc_cmd<HW::item<bool>, rc_t, vapi::Gbp_contract_add_del>
+class create_cmd : public rpc_cmd<HW::item<bool>, vapi::Gbp_contract_add_del>
{
public:
/**
/**
* A cmd class that deletes a GBP contract
*/
-class delete_cmd
- : public rpc_cmd<HW::item<bool>, rc_t, vapi::Gbp_contract_add_del>
+class delete_cmd : public rpc_cmd<HW::item<bool>, vapi::Gbp_contract_add_del>
{
public:
/**
VAPI_CALL(req.execute());
- m_hw_item.set(wait());
-
- return rc_t::OK;
+ return (wait());
}
std::string
VAPI_CALL(req.execute());
- m_hw_item.set(wait());
-
- return rc_t::OK;
+ return (wait());
}
std::string
/**
* A command class that creates or updates the GBP endpoint
*/
-class create_cmd
- : public rpc_cmd<HW::item<bool>, rc_t, vapi::Gbp_endpoint_add_del>
+class create_cmd : public rpc_cmd<HW::item<bool>, vapi::Gbp_endpoint_add_del>
{
public:
/**
/**
* A cmd class that deletes a GBP endpoint
*/
-class delete_cmd
- : public rpc_cmd<HW::item<bool>, rc_t, vapi::Gbp_endpoint_add_del>
+class delete_cmd : public rpc_cmd<HW::item<bool>, vapi::Gbp_endpoint_add_del>
{
public:
/**
VAPI_CALL(req.execute());
- m_hw_item.set(wait());
-
- return rc_t::OK;
+ return (wait());
}
std::string
VAPI_CALL(req.execute());
- m_hw_item.set(wait());
-
- return rc_t::OK;
+ return (wait());
}
std::string
* A command class that creates or updates the GBP endpoint_group
*/
class create_cmd
- : public rpc_cmd<HW::item<bool>, rc_t, vapi::Gbp_endpoint_group_add_del>
+ : public rpc_cmd<HW::item<bool>, vapi::Gbp_endpoint_group_add_del>
{
public:
/**
* A cmd class that deletes a GBP endpoint_group
*/
class delete_cmd
- : public rpc_cmd<HW::item<bool>, rc_t, vapi::Gbp_endpoint_group_add_del>
+ : public rpc_cmd<HW::item<bool>, vapi::Gbp_endpoint_group_add_del>
{
public:
/**
VAPI_CALL(req.execute());
- m_hw_item.set(wait());
-
- return rc_t::OK;
+ return (wait());
}
std::string
VAPI_CALL(req.execute());
- m_hw_item.set(wait());
-
- return rc_t::OK;
+ return (wait());
}
std::string
/**
* A command class that creates or updates the GBP recirc
*/
-class create_cmd
- : public rpc_cmd<HW::item<bool>, rc_t, vapi::Gbp_recirc_add_del>
+class create_cmd : public rpc_cmd<HW::item<bool>, vapi::Gbp_recirc_add_del>
{
public:
/**
/**
* A cmd class that deletes a GBP recirc
*/
-class delete_cmd
- : public rpc_cmd<HW::item<bool>, rc_t, vapi::Gbp_recirc_add_del>
+class delete_cmd : public rpc_cmd<HW::item<bool>, vapi::Gbp_recirc_add_del>
{
public:
/**
VAPI_CALL(req.execute());
- m_hw_item.set(wait());
-
- return rc_t::OK;
+ return (wait());
}
std::string
VAPI_CALL(req.execute());
- m_hw_item.set(wait());
-
- return rc_t::OK;
+ return (wait());
}
std::string
/**
* A command class that creates or updates the GBP subnet
*/
-class create_cmd
- : public rpc_cmd<HW::item<bool>, rc_t, vapi::Gbp_subnet_add_del>
+class create_cmd : public rpc_cmd<HW::item<bool>, vapi::Gbp_subnet_add_del>
{
public:
/**
/**
* A cmd class that deletes a GBP subnet
*/
-class delete_cmd
- : public rpc_cmd<HW::item<bool>, rc_t, vapi::Gbp_subnet_add_del>
+class delete_cmd : public rpc_cmd<HW::item<bool>, vapi::Gbp_subnet_add_del>
{
public:
/**
VAPI_CALL(req.execute());
- m_hw_item.set(wait());
-
- return (rc_t::OK);
+ return (wait());
}
std::string
/**
*A command poll the HW for liveness
*/
-class poll : public rpc_cmd<HW::item<bool>, rc_t, vapi::Control_ping>
+class poll : public rpc_cmd<HW::item<bool>, vapi::Control_ping>
{
public:
/**
*/
const static type_t BOND;
+ /**
+ * pipe-parent type
+ */
+ const static type_t PIPE;
+
+ /**
+ * pipe-end type
+ */
+ const static type_t PIPE_END;
+
/**
* Convert VPP's name of the interface to a type
*/
* A base class for interface Create commands
*/
template <typename MSG>
- class create_cmd : public rpc_cmd<HW::item<handle_t>, HW::item<handle_t>, MSG>
+ class create_cmd : public rpc_cmd<HW::item<handle_t>, MSG>
{
public:
create_cmd(HW::item<handle_t>& item, const std::string& name)
- : rpc_cmd<HW::item<handle_t>, HW::item<handle_t>, MSG>(item)
+ : rpc_cmd<HW::item<handle_t>, MSG>(item)
, m_name(name)
{
}
*/
void succeeded()
{
- rpc_cmd<HW::item<handle_t>, HW::item<handle_t>, MSG>::succeeded();
+ rpc_cmd<HW::item<handle_t>, MSG>::succeeded();
interface::add(m_name, this->item());
}
handle = sw_if_index;
}
- HW::item<handle_t> res(handle, rc);
-
- this->fulfill(res);
+ this->fulfill(HW::item<handle_t>(handle, rc));
return (VAPI_OK);
}
* Base class for intterface Delete commands
*/
template <typename MSG>
- class delete_cmd : public rpc_cmd<HW::item<handle_t>, HW::item<handle_t>, MSG>
+ class delete_cmd : public rpc_cmd<HW::item<handle_t>, MSG>
{
public:
delete_cmd(HW::item<handle_t>& item, const std::string& name)
- : rpc_cmd<HW::item<handle_t>, HW::item<handle_t>, MSG>(item)
+ : rpc_cmd<HW::item<handle_t>, MSG>(item)
, m_name(name)
{
}
delete_cmd(HW::item<handle_t>& item)
- : rpc_cmd<HW::item<handle_t>, HW::item<handle_t>, MSG>(item)
+ : rpc_cmd<HW::item<handle_t>, MSG>(item)
, m_name()
{
}
*/
void set(const handle_t& handle);
friend class interface_factory;
+ friend class pipe;
/**
* The SW interface handle VPP has asigned to the interface
VAPI_CALL(req.execute());
- m_hw_item = wait();
+ wait();
if (m_hw_item.rc() == rc_t::OK) {
insert_interface();
VAPI_CALL(req.execute());
- m_hw_item = wait();
+ wait();
if (m_hw_item.rc() == rc_t::OK) {
insert_interface();
VAPI_CALL(req.execute());
- m_hw_item = wait();
+ wait();
if (m_hw_item.rc() == rc_t::OK) {
insert_interface();
VAPI_CALL(req.execute());
- m_hw_item.set(wait());
-
- return rc_t::OK;
+ return (wait());
}
std::string
VAPI_CALL(req.execute());
- m_hw_item.set(wait());
-
- return (rc_t::OK);
+ return (wait());
}
std::string
VAPI_CALL(req.execute());
- m_hw_item.set(wait());
-
- return (rc_t::OK);
+ return (wait());
}
std::string
VAPI_CALL(req.execute());
- m_hw_item.set(wait());
-
- return (rc_t::OK);
+ return (wait());
}
std::string
VAPI_CALL(req.execute());
- wait();
-
- return rc_t::OK;
+ return (wait());
}
std::string
set_tag::to_string() const
* A command class to set tag on interfaces
*/
class set_tag
- : public rpc_cmd<HW::item<handle_t>, rc_t, vapi::Sw_interface_tag_add_del>
+ : public rpc_cmd<HW::item<handle_t>, vapi::Sw_interface_tag_add_del>
{
public:
/**
* A cmd class that changes the admin state
*/
class state_change_cmd : public rpc_cmd<HW::item<interface::admin_state_t>,
- rc_t,
vapi::Sw_interface_set_flags>
{
public:
/**
* A command class that binds an interface to an L3 table
*/
-class set_table_cmd : public rpc_cmd<HW::item<route::table_id_t>,
- rc_t,
- vapi::Sw_interface_set_table>
+class set_table_cmd
+ : public rpc_cmd<HW::item<route::table_id_t>, vapi::Sw_interface_set_table>
{
public:
/**
/**
* A command class that changes the MAC address on an interface
*/
-class set_mac_cmd : public rpc_cmd<HW::item<l2_address_t>,
- rc_t,
- vapi::Sw_interface_set_mac_address>
+class set_mac_cmd
+ : public rpc_cmd<HW::item<l2_address_t>, vapi::Sw_interface_set_mac_address>
{
public:
/**
*/
class collect_detail_stats_change_cmd
: public rpc_cmd<HW::item<interface::stats_type_t>,
- rc_t,
vapi::Collect_detailed_interface_stats>
{
public:
* A command class represents our desire to recieve interface stats
*/
class stats_disable_cmd
- : public rpc_cmd<HW::item<bool>,
- rc_t,
- vapi::Want_per_interface_combined_stats>
+ : public rpc_cmd<HW::item<bool>, vapi::Want_per_interface_combined_stats>
{
public:
/**
sp = interface::find(hdl);
if (sp && !tag.empty())
sp->set(tag);
+ } else if (interface::type_t::PIPE == type) {
+ /*
+ * there's not enough information in a SW interface record to
+ * construct a pipe. so skip it. They have
+ * their own dump routines
+ */
} else if ((name.find(".") != std::string::npos) && (0 != vd.sub_id)) {
/*
* Sub-interface
bond_member bm(*itf, mode, rate);
return (bm);
}
+
+std::shared_ptr<pipe>
+interface_factory::new_pipe_interface(const vapi_payload_pipe_details& payload)
+{
+ std::shared_ptr<pipe> sp;
+
+ handle_t hdl(payload.sw_if_index);
+ pipe::handle_pair_t hdl_pair(payload.pipe_sw_if_index[0],
+ payload.pipe_sw_if_index[1]);
+
+ sp = pipe(payload.instance, interface::admin_state_t::UP).singular();
+
+ sp->set(hdl);
+ sp->set_ends(hdl_pair);
+
+ return (sp);
+}
+
}; // namespace VOM
/*
#include <vapi/vapi.hpp>
+#include "vom/bond_interface.hpp"
#include "vom/bond_member.hpp"
#include "vom/interface.hpp"
+#include "vom/pipe.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/pipe.api.vapi.hpp>
#include <vapi/tap.api.vapi.hpp>
#include <vapi/tapv2.api.vapi.hpp>
#include <vapi/vhost_user.api.vapi.hpp>
static bond_member new_bond_member_interface(
const vapi_payload_sw_interface_slave_details& vd);
+
+ static std::shared_ptr<pipe> new_pipe_interface(
+ const vapi_payload_pipe_details& payload);
};
};
/**
* A functor class that binds the ra config to the interface
*/
- class config_cmd : public rpc_cmd<HW::item<bool>, rc_t, CMD>
+ class config_cmd : public rpc_cmd<HW::item<bool>, CMD>
{
public:
/**
* Constructor
*/
config_cmd(HW::item<bool>& item, const handle_t& itf, const class_t& cls)
- : rpc_cmd<HW::item<bool>, rc_t, CMD>(item)
+ : rpc_cmd<HW::item<bool>, CMD>(item)
, m_itf(itf)
, m_cls(cls)
{
/**
* A cmd class that Unbinds L3 Config from an interface
*/
- class unconfig_cmd : public rpc_cmd<HW::item<bool>, rc_t, CMD>
+ class unconfig_cmd : public rpc_cmd<HW::item<bool>, CMD>
{
public:
/**
* Constructor
*/
unconfig_cmd(HW::item<bool>& item, const handle_t& itf, const class_t& cls)
- : rpc_cmd<HW::item<bool>, rc_t, CMD>(item)
+ : rpc_cmd<HW::item<bool>, CMD>(item)
, m_itf(itf)
, m_cls(cls)
{
VAPI_CALL(req.execute());
- m_hw_item.set(wait());
-
- return rc_t::OK;
+ return (wait());
}
template <>
VAPI_CALL(req.execute());
- m_hw_item.set(wait());
-
- return rc_t::OK;
+ return (wait());
}
template <>
VAPI_CALL(req.execute());
- m_hw_item.set(wait());
-
- return rc_t::OK;
+ return (wait());
}
std::string
* A command class that configures the interface span
*/
class config_cmd
- : public rpc_cmd<HW::item<bool>, rc_t, vapi::Sw_interface_span_enable_disable>
+ : public rpc_cmd<HW::item<bool>, vapi::Sw_interface_span_enable_disable>
{
public:
/**
* A cmd class that Unconfigs interface span
*/
class unconfig_cmd
- : public rpc_cmd<HW::item<bool>, rc_t, vapi::Sw_interface_span_enable_disable>
+ : public rpc_cmd<HW::item<bool>, vapi::Sw_interface_span_enable_disable>
{
public:
/**
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::type_t interface::type_t::PIPE(11, "Pipe");
+const interface::type_t interface::type_t::PIPE_END(12, "Pipe-end");
const interface::oper_state_t interface::oper_state_t::DOWN(0, "down");
const interface::oper_state_t interface::oper_state_t::UP(1, "up");
return interface::type_t::TAPV2;
} else if (str.find("bvi") != std::string::npos) {
return interface::type_t::BVI;
+ } else if (str.find("pipe") != std::string::npos) {
+ return interface::type_t::PIPE;
}
return interface::type_t::UNKNOWN;
VAPI_CALL(req.execute());
- m_hw_item.set(wait());
-
- return rc_t::OK;
+ return (wait());
}
std::string
*A command class that configures the IP unnumbered
*/
class config_cmd
- : public rpc_cmd<HW::item<bool>, rc_t, vapi::Sw_interface_set_unnumbered>
+ : public rpc_cmd<HW::item<bool>, vapi::Sw_interface_set_unnumbered>
{
public:
/**
* A cmd class that Unconfigs L3 Config from an interface
*/
class unconfig_cmd
- : public rpc_cmd<HW::item<bool>, rc_t, vapi::Sw_interface_set_unnumbered>
+ : public rpc_cmd<HW::item<bool>, vapi::Sw_interface_set_unnumbered>
{
public:
/**
VAPI_CALL(req.execute());
- m_hw_item.set(wait());
-
- return (rc_t::OK);
+ return (wait());
}
std::string
VAPI_CALL(req.execute());
- wait();
-
- return (rc_t::OK);
+ return (wait());
}
std::string
* A functor class that binds L2 configuration to an interface
*/
class bind_cmd
- : public rpc_cmd<HW::item<bool>, rc_t, vapi::Sw_interface_set_l2_bridge>
+ : public rpc_cmd<HW::item<bool>, vapi::Sw_interface_set_l2_bridge>
{
public:
/**
* A cmd class that Unbinds L2 configuration from an interface
*/
class unbind_cmd
- : public rpc_cmd<HW::item<bool>, rc_t, vapi::Sw_interface_set_l2_bridge>
+ : public rpc_cmd<HW::item<bool>, vapi::Sw_interface_set_l2_bridge>
{
public:
/**
* A cmd class sets the VTR operation
*/
class set_vtr_op_cmd : public rpc_cmd<HW::item<l2_binding::l2_vtr_op_t>,
- rc_t,
vapi::L2_interface_vlan_tag_rewrite>
{
public:
VAPI_CALL(req.execute());
- m_hw_item.set(wait());
-
- return (rc_t::OK);
+ return (wait());
}
std::string
/**
* A functor class that enable L2 emulation to an interface
*/
-class enable_cmd : public rpc_cmd<HW::item<bool>, rc_t, vapi::L2_emulation>
+class enable_cmd : public rpc_cmd<HW::item<bool>, vapi::L2_emulation>
{
public:
/**
/**
* A cmd class that Unbinds L2 configuration from an interface
*/
-class disable_cmd : public rpc_cmd<HW::item<bool>, rc_t, vapi::L2_emulation>
+class disable_cmd : public rpc_cmd<HW::item<bool>, vapi::L2_emulation>
{
public:
/**
VAPI_CALL(req.execute());
- m_hw_item.set(wait());
+ wait();
return (rc_t::OK);
}
* A functor class that binds L2 configuration to an interface
*/
class bind_cmd
- : public rpc_cmd<HW::item<bool>, rc_t, vapi::Sw_interface_set_l2_xconnect>
+ : public rpc_cmd<HW::item<bool>, vapi::Sw_interface_set_l2_xconnect>
{
public:
/**
* A cmd class that Unbinds L2 configuration from an interface
*/
class unbind_cmd
- : public rpc_cmd<HW::item<bool>, rc_t, vapi::Sw_interface_set_l2_xconnect>
+ : public rpc_cmd<HW::item<bool>, vapi::Sw_interface_set_l2_xconnect>
{
public:
/**
VAPI_CALL(req.execute());
- m_hw_item.set(wait());
-
- return rc_t::OK;
+ return (wait());
}
std::string
* A functor class that binds the L3 config to the interface
*/
class bind_cmd
- : public rpc_cmd<HW::item<bool>, rc_t, vapi::Sw_interface_add_del_address>
+ : public rpc_cmd<HW::item<bool>, vapi::Sw_interface_add_del_address>
{
public:
/**
* A cmd class that Unbinds L3 Config from an interface
*/
class unbind_cmd
- : public rpc_cmd<HW::item<bool>, rc_t, vapi::Sw_interface_add_del_address>
+ : public rpc_cmd<HW::item<bool>, vapi::Sw_interface_add_del_address>
{
public:
/**
VAPI_CALL(req.execute());
- m_hw_item.set(wait());
-
- return rc_t::OK;
+ return (wait());
}
std::string
/**
*A command class that binds the LLDP config to the interface
*/
-class bind_cmd
- : public rpc_cmd<HW::item<bool>, rc_t, vapi::Sw_interface_set_lldp>
+class bind_cmd : public rpc_cmd<HW::item<bool>, vapi::Sw_interface_set_lldp>
{
public:
/**
/**
* A cmd class that Unbinds Lldp Config from an interface
*/
-class unbind_cmd
- : public rpc_cmd<HW::item<bool>, rc_t, vapi::Sw_interface_set_lldp>
+class unbind_cmd : public rpc_cmd<HW::item<bool>, vapi::Sw_interface_set_lldp>
{
public:
/**
VAPI_CALL(req.execute());
- m_hw_item.set(wait());
-
- return rc_t::OK;
+ return (wait());
}
std::string
/**
* A command class that binds the LLDP global to the interface
*/
-class config_cmd : public rpc_cmd<HW::item<bool>, rc_t, vapi::Lldp_config>
+class config_cmd : public rpc_cmd<HW::item<bool>, vapi::Lldp_config>
{
public:
/**
VAPI_CALL(req.execute());
- m_hw_item.set(wait());
-
- return rc_t::OK;
+ return (wait());
}
std::string
VAPI_CALL(req.execute());
- m_hw_item.set(wait());
-
- return rc_t::OK;
+ return (wait());
}
std::string
VAPI_CALL(req.execute());
- m_hw_item.set(wait());
-
- return rc_t::OK;
+ return (wait());
}
std::string
VAPI_CALL(req.execute());
- m_hw_item.set(wait());
-
- return rc_t::OK;
+ return (wait());
}
std::string
VAPI_CALL(req.execute());
- m_hw_item.set(wait());
+ wait();
return rc_t::OK;
}
VAPI_CALL(req.execute());
- m_hw_item.set(wait());
+ wait();
return rc_t::OK;
}
* A functor class that binds a NAT configuration to an input interface
*/
class bind_44_input_cmd
- : public rpc_cmd<HW::item<bool>, rc_t, vapi::Nat44_interface_add_del_feature>
+ : public rpc_cmd<HW::item<bool>, vapi::Nat44_interface_add_del_feature>
{
public:
/**
* A cmd class that unbinds a NAT configuration from an input interface
*/
class unbind_44_input_cmd
- : public rpc_cmd<HW::item<bool>, rc_t, vapi::Nat44_interface_add_del_feature>
+ : public rpc_cmd<HW::item<bool>, vapi::Nat44_interface_add_del_feature>
{
public:
/**
* A functor class that binds a NAT configuration to an output interface
*/
class bind_44_output_cmd
- : public rpc_cmd<HW::item<bool>,
- rc_t,
- vapi::Nat44_interface_add_del_output_feature>
+ : public rpc_cmd<HW::item<bool>, vapi::Nat44_interface_add_del_output_feature>
{
public:
/**
* A cmd class that unbinds a NAT configuration from an output interface
*/
class unbind_44_output_cmd
- : public rpc_cmd<HW::item<bool>,
- rc_t,
- vapi::Nat44_interface_add_del_output_feature>
+ : public rpc_cmd<HW::item<bool>, vapi::Nat44_interface_add_del_output_feature>
{
public:
/**
* A functor class that binds a NAT configuration to an input interface
*/
class bind_66_input_cmd
- : public rpc_cmd<HW::item<bool>, rc_t, vapi::Nat66_add_del_interface>
+ : public rpc_cmd<HW::item<bool>, vapi::Nat66_add_del_interface>
{
public:
/**
* A cmd class that unbinds a NAT configuration from an input interface
*/
class unbind_66_input_cmd
- : public rpc_cmd<HW::item<bool>, rc_t, vapi::Nat66_add_del_interface>
+ : public rpc_cmd<HW::item<bool>, vapi::Nat66_add_del_interface>
{
public:
/**
VAPI_CALL(req.execute());
- m_hw_item.set(wait());
-
- return rc_t::OK;
+ return (wait());
}
std::string
VAPI_CALL(req.execute());
- m_hw_item.set(wait());
-
- return rc_t::OK;
+ return (wait());
}
std::string
* A command class that creates NAT 44 static mapping
*/
class create_44_cmd
- : public rpc_cmd<HW::item<bool>, rc_t, vapi::Nat44_add_del_static_mapping>
+ : public rpc_cmd<HW::item<bool>, vapi::Nat44_add_del_static_mapping>
{
public:
/**
* A cmd class that deletes a NAT 44 static mapping
*/
class delete_44_cmd
- : public rpc_cmd<HW::item<bool>, rc_t, vapi::Nat44_add_del_static_mapping>
+ : public rpc_cmd<HW::item<bool>, vapi::Nat44_add_del_static_mapping>
{
public:
/**
* A command class that creates NAT 66 static mapping
*/
class create_66_cmd
- : public rpc_cmd<HW::item<bool>, rc_t, vapi::Nat66_add_del_static_mapping>
+ : public rpc_cmd<HW::item<bool>, vapi::Nat66_add_del_static_mapping>
{
public:
/**
* A cmd class that deletes a NAT 66 static mapping
*/
class delete_66_cmd
- : public rpc_cmd<HW::item<bool>, rc_t, vapi::Nat66_add_del_static_mapping>
+ : public rpc_cmd<HW::item<bool>, vapi::Nat66_add_del_static_mapping>
{
public:
/**
VAPI_CALL(req.execute());
- m_hw_item.set(wait());
-
- return rc_t::OK;
+ return (wait());
}
std::string
/**
* A command class that creates or updates the bridge domain ARP Entry
*/
-class create_cmd
- : public rpc_cmd<HW::item<bool>, rc_t, vapi::Ip_neighbor_add_del>
+class create_cmd : public rpc_cmd<HW::item<bool>,
+ vapi::Ip_neighbor_add_del>
{
public:
/**
/**
* A cmd class that deletes a bridge domain ARP entry
*/
-class delete_cmd
- : public rpc_cmd<HW::item<bool>, rc_t, vapi::Ip_neighbor_add_del>
+class delete_cmd : public rpc_cmd<HW::item<bool>,
+ vapi::Ip_neighbor_add_del>
{
public:
/**
--- /dev/null
+/*
+ * 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/pipe.hpp"
+#include "vom/interface_factory.hpp"
+#include "vom/pipe_cmds.hpp"
+#include "vom/singular_db_funcs.hpp"
+
+namespace VOM {
+
+typedef enum end_t_ {
+ EAST = 0,
+ WEST,
+} end_t;
+#define N_ENDS (WEST + 1)
+
+pipe::event_handler pipe::m_evh;
+
+static const std::string
+pipe_mk_name(uint32_t instance)
+{
+ return ("pipe" + std::to_string(instance));
+}
+
+/**
+ * Construct a new object matching the desried state
+ */
+pipe::pipe(uint32_t instance, admin_state_t state)
+ : interface(pipe_mk_name(instance), type_t::PIPE, state)
+ , m_instance(instance)
+{
+}
+
+pipe::~pipe()
+{
+ sweep();
+ release();
+}
+
+pipe::pipe(const pipe& o)
+ : interface(o)
+ , m_instance(o.m_instance)
+{
+}
+
+std::string
+pipe::to_string(void) const
+{
+ std::ostringstream s;
+
+ s << "[pipe: " << interface::to_string() << " instance:" << m_instance
+ << " ends:[" << m_hdl_pair.rc().to_string() << " "
+ << m_hdl_pair.data().first << ", " << m_hdl_pair.data().second << "]]";
+
+ return (s.str());
+}
+
+std::queue<cmd*>&
+pipe::mk_create_cmd(std::queue<cmd*>& q)
+{
+ q.push(new pipe_cmds::create_cmd(m_hdl, m_name, m_instance, m_hdl_pair));
+
+ return (q);
+}
+
+std::queue<cmd*>&
+pipe::mk_delete_cmd(std::queue<cmd*>& q)
+{
+ q.push(new pipe_cmds::delete_cmd(m_hdl, m_hdl_pair));
+
+ return (q);
+}
+
+std::shared_ptr<pipe>
+pipe::singular() const
+{
+ return std::dynamic_pointer_cast<pipe>(singular_i());
+}
+
+std::shared_ptr<interface>
+pipe::singular_i() const
+{
+ return m_db.find_or_add(key(), *this);
+}
+
+std::shared_ptr<pipe>
+pipe::find(const key_t& k)
+{
+ return std::dynamic_pointer_cast<pipe>(m_db.find(k));
+}
+
+std::shared_ptr<interface>
+pipe::west()
+{
+ if (!m_ends[WEST]) {
+ if (rc_t::OK == m_hdl_pair.rc()) {
+ m_ends[WEST] = pipe_end(*this, WEST).singular();
+ m_ends[WEST]->set(m_hdl_pair.data().first);
+ }
+ }
+
+ return (m_ends[WEST]);
+}
+
+std::shared_ptr<interface>
+pipe::east()
+{
+ if (!m_ends[EAST]) {
+ if (rc_t::OK == m_hdl_pair.rc()) {
+ m_ends[EAST] = pipe_end(*this, EAST).singular();
+ m_ends[EAST]->set(m_hdl_pair.data().first);
+ }
+ }
+
+ return (m_ends[EAST]);
+}
+
+pipe::pipe_end::pipe_end(const pipe& p, uint8_t id)
+ : interface(p.name() + "." + std::to_string(id),
+ interface::type_t::PIPE_END,
+ interface::admin_state_t::UP)
+ , m_pipe(p.singular())
+{
+}
+
+std::queue<cmd*>&
+pipe::pipe_end::mk_create_cmd(std::queue<cmd*>& q)
+{
+ return (q);
+}
+
+std::queue<cmd*>&
+pipe::pipe_end::mk_delete_cmd(std::queue<cmd*>& q)
+{
+ return (q);
+}
+
+void
+pipe::set_ends(const handle_pair_t& p)
+{
+ if (handle_t::INVALID != p.first && handle_t::INVALID != p.second) {
+ m_hdl_pair = { p, rc_t::OK };
+ } else {
+ m_hdl_pair = { p, rc_t::INVALID };
+ }
+}
+
+pipe::event_handler::event_handler()
+{
+ OM::register_listener(this);
+ inspect::register_handler({ "pipe" }, "pipes", this);
+}
+
+void
+pipe::event_handler::handle_replay()
+{
+ // m_db.replay();
+}
+
+void
+pipe::event_handler::handle_populate(const client_db::key_t& key)
+{
+ std::shared_ptr<pipe_cmds::dump_cmd> cmd =
+ std::make_shared<pipe_cmds::dump_cmd>();
+
+ HW::enqueue(cmd);
+ HW::write();
+
+ for (auto& record : *cmd) {
+ std::shared_ptr<pipe> sp;
+
+ sp = interface_factory::new_pipe_interface(record.get_payload());
+
+ VOM_LOG(log_level_t::DEBUG) << " pipe-dump: " << sp->to_string();
+ OM::commit(key, *sp);
+ }
+}
+
+dependency_t
+pipe::event_handler::order() const
+{
+ return (dependency_t::VIRTUAL_INTERFACE);
+}
+
+void
+pipe::event_handler::show(std::ostream& os)
+{
+ db_dump(m_db, os);
+}
+
+}; // namespace VOM
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "mozilla")
+ * End:
+ */
--- /dev/null
+/*
+ * Copyright (c) 2018 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __VOM_PIPE_H__
+#define __VOM_PIPE_H__
+
+#include "vom/interface.hpp"
+
+namespace VOM {
+/**
+ * A Pipe interface.
+ * A pipe is composed for 3 'interfaces'.
+ * 1) the 'parent' interface - this is used as the 'key' for the pipe
+ * 2) the two 'ends' of the pipe - these are used to RX/TX packets
+ * form/to. The ends are retreivable using the east()/west() functions.
+ * The east and west end are exactly equivalent, they are merely
+ * named differently for logical purposes.
+ */
+class pipe : public interface
+{
+public:
+ typedef std::pair<handle_t, handle_t> handle_pair_t;
+
+ /**
+ * Construct a new object matching the desried state
+ */
+ pipe(uint32_t instance, admin_state_t state);
+
+ /**
+ * Destructor
+ */
+ ~pipe();
+
+ /**
+ * Copy Constructor
+ */
+ pipe(const pipe& o);
+
+ /**
+ * comparison operator - for UT
+ */
+ bool operator==(const pipe& s) const;
+
+ /**
+ * Return the matching 'singular instance' of the sub-interface
+ */
+ std::shared_ptr<pipe> singular() const;
+
+ /**
+ * Find a subinterface from its key
+ */
+ static std::shared_ptr<pipe> find(const key_t& k);
+
+ /**
+ * The interface that is the east end of the pipe
+ */
+ std::shared_ptr<interface> east();
+
+ /**
+ * The interface that is the west end of the pipe.
+ * The east and west end are exactly equivalent, they are merely
+ * named differently for logical purposes.
+ */
+ std::shared_ptr<interface> west();
+
+ virtual std::string to_string(void) const;
+
+ void set_ends(const handle_pair_t& p);
+
+private:
+ /**
+ * The interface type that forms the ends of the pipe
+ */
+ class pipe_end : public interface
+ {
+ public:
+ pipe_end(const pipe& p, uint8_t id);
+
+ private:
+ virtual std::queue<cmd*>& mk_create_cmd(std::queue<cmd*>& cmds);
+ virtual std::queue<cmd*>& mk_delete_cmd(std::queue<cmd*>& cmds);
+
+ std::shared_ptr<pipe> m_pipe;
+ };
+
+ /**
+*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;
+ };
+ static event_handler m_evh;
+
+ /**
+ * Return the matching 'instance' of the pipe
+ * over-ride from the base class
+ */
+ std::shared_ptr<interface> singular_i() const;
+
+ /**
+ * Virtual functions to construct an interface create commands.
+ */
+ virtual std::queue<cmd*>& mk_create_cmd(std::queue<cmd*>& cmds);
+
+ /**
+ * Virtual functions to construct an interface delete commands.
+ */
+ virtual std::queue<cmd*>& mk_delete_cmd(std::queue<cmd*>& cmds);
+
+ /**
+ * the handles that are set during the create command
+ */
+ HW::item<handle_pair_t> m_hdl_pair;
+
+ /**
+ * The ends of the pipe
+ */
+ std::shared_ptr<interface> m_ends[2];
+
+ /**
+ * Instance number
+ */
+ uint32_t m_instance;
+};
+
+}; // namespace VOM
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "mozilla")
+ * End:
+ */
+
+#endif
--- /dev/null
+/*
+ * Copyright (c) 2018 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "vom/pipe_cmds.hpp"
+
+DEFINE_VAPI_MSG_IDS_PIPE_API_JSON;
+
+namespace VOM {
+namespace pipe_cmds {
+
+create_cmd::create_cmd(HW::item<handle_t>& item,
+ const std::string& name,
+ uint32_t instance,
+ HW::item<pipe::handle_pair_t>& ends)
+ : interface::create_cmd<vapi::Pipe_create>(item, name)
+ , m_hdl_pair(ends)
+ , m_instance(instance)
+{
+}
+
+bool
+create_cmd::operator==(const create_cmd& other) const
+{
+ return (m_name == other.m_name);
+}
+
+vapi_error_e
+create_cmd::operator()(vapi::Pipe_create& reply)
+{
+ auto& payload = reply.get_response().get_payload();
+
+ VOM_LOG(log_level_t::DEBUG) << to_string() << " " << payload.retval;
+
+ const rc_t& rc = rc_t::from_vpp_retval(payload.retval);
+
+ m_hdl_pair = { pipe::handle_pair_t(payload.pipe_sw_if_index[0],
+ payload.pipe_sw_if_index[1]),
+ rc };
+
+ fulfill(HW::item<handle_t>(payload.sw_if_index, rc));
+
+ return (VAPI_OK);
+}
+rc_t
+create_cmd::issue(connection& con)
+{
+ msg_t req(con.ctx(), std::ref(*this));
+
+ auto& payload = req.get_request().get_payload();
+
+ payload.is_specified = 1;
+ payload.user_instance = m_instance;
+
+ VAPI_CALL(req.execute());
+
+ if (rc_t::OK == wait()) {
+ insert_interface();
+ }
+
+ return rc_t::OK;
+}
+
+std::string
+create_cmd::to_string() const
+{
+ std::ostringstream s;
+
+ s << "pipe-create: " << m_name << " instance:" << m_instance;
+
+ return (s.str());
+}
+
+delete_cmd::delete_cmd(HW::item<handle_t>& item,
+ HW::item<pipe::handle_pair_t>& end_pair)
+ : interface::delete_cmd<vapi::Pipe_delete>(item)
+ , m_hdl_pair(end_pair)
+{
+}
+
+bool
+delete_cmd::operator==(const delete_cmd& other) const
+{
+ return (m_hw_item == other.m_hw_item);
+}
+
+rc_t
+delete_cmd::issue(connection& con)
+{
+ msg_t req(con.ctx(), std::ref(*this));
+
+ VAPI_CALL(req.execute());
+
+ wait();
+ m_hw_item.set(rc_t::NOOP);
+ m_hdl_pair.set(rc_t::NOOP);
+
+ remove_interface();
+
+ return (rc_t::OK);
+}
+
+std::string
+delete_cmd::to_string() const
+{
+ return ("pipe-delete");
+}
+
+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 ("pipe-dump");
+}
+
+} // namespace pipe_cmds
+} // namespace VOM
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "mozilla")
+ * End:
+ */
--- /dev/null
+/*
+ * 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_PIPE_CMDS_H__
+#define __VOM_PIPE_CMDS_H__
+
+#include "vom/dump_cmd.hpp"
+#include "vom/pipe.hpp"
+#include "vom/rpc_cmd.hpp"
+
+#include <vapi/pipe.api.vapi.hpp>
+
+namespace VOM {
+namespace pipe_cmds {
+/**
+ * A functor class that creates an interface
+ */
+class create_cmd : public interface::create_cmd<vapi::Pipe_create>
+{
+public:
+ /**
+ * Cstrunctor taking the reference to the parent
+ * and the sub-interface's VLAN
+ */
+ create_cmd(HW::item<handle_t>& item,
+ const std::string& name,
+ uint32_t instance,
+ HW::item<pipe::handle_pair_t>& ends);
+
+ /**
+ * 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;
+
+ virtual vapi_error_e operator()(vapi::Pipe_create& reply);
+
+private:
+ HW::item<pipe::handle_pair_t>& m_hdl_pair;
+ uint32_t m_instance;
+};
+
+/**
+ * A cmd class that Delete an interface
+ */
+class delete_cmd : public interface::delete_cmd<vapi::Pipe_delete>
+{
+public:
+ /**
+ * Constructor
+ */
+ delete_cmd(HW::item<handle_t>& item, HW::item<pipe::handle_pair_t>& end_pair);
+
+ /**
+ * 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:
+ HW::item<pipe::handle_pair_t>& m_hdl_pair;
+};
+
+/**
+ * A cmd class that Dumps all the Vpp interfaces
+ */
+class dump_cmd : public VOM::dump_cmd<vapi::Pipe_dump>
+{
+public:
+ /**
+ * Default Constructor
+ */
+ dump_cmd() = default;
+
+ /**
+ * Issue the command to VPP/HW
+ */
+ rc_t issue(connection& con);
+ /**
+ * convert to string format for debug purposes
+ */
+ std::string to_string() const;
+
+ /**
+ * Comparison operator - only used for UT
+ */
+ bool operator==(const dump_cmd& i) const;
+};
+
+}; // namespace pipe_cmds
+}; // namespace VOM
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "mozilla")
+ * End:
+ */
+
+#endif
VAPI_CALL(req.execute());
- m_hw_item.set(wait());
-
- return rc_t::OK;
+ return (wait());
}
std::string
/**
* A command class that creates or updates the route
*/
-class update_cmd : public rpc_cmd<HW::item<bool>, rc_t, vapi::Ip_add_del_route>
+class update_cmd : public rpc_cmd<HW::item<bool>, vapi::Ip_add_del_route>
{
public:
/**
/**
* A cmd class that deletes a route
*/
-class delete_cmd : public rpc_cmd<HW::item<bool>, rc_t, vapi::Ip_add_del_route>
+class delete_cmd : public rpc_cmd<HW::item<bool>, vapi::Ip_add_del_route>
{
public:
/**
VAPI_CALL(req.execute());
- m_hw_item.set(wait());
-
- return (rc_t::OK);
+ return (wait());
}
std::string
/**
* A command class that creates the IP table
*/
-class create_cmd : public rpc_cmd<HW::item<bool>, rc_t, vapi::Ip_table_add_del>
+class create_cmd : public rpc_cmd<HW::item<bool>, vapi::Ip_table_add_del>
{
public:
/**
/**
* A cmd class that Deletes the IP Table
*/
-class delete_cmd : public rpc_cmd<HW::item<bool>, rc_t, vapi::Ip_table_add_del>
+class delete_cmd : public rpc_cmd<HW::item<bool>, vapi::Ip_table_add_del>
{
public:
/**
* The command is templatised on the type of the HW::item to be set by
* the command, and the data returned in the promise,
*/
-template <typename HWITEM, typename DATA, typename MSG>
+template <typename HWITEM, typename MSG>
class rpc_cmd : public cmd
{
public:
/**
* Fulfill the commands promise. Called from the RX thread
*/
- void fulfill(const DATA& d)
- {
- m_promise.set_value(d);
-
- /*
- * we reset the promise after setting the value to reuse it
- * when we run the retire command from the same cmd object
- */
- // m_promise = std::promise<DATA>();
- }
+ void fulfill(const HWITEM& d) { m_promise.set_value(d); }
/**
* Wait on the commands promise. i.e. block on the completion
* of the command.
*/
- DATA wait()
+ rc_t wait()
{
std::future_status status;
- std::future<DATA> result;
+ std::future<HWITEM> result;
result = m_promise.get_future();
status = result.wait_for(std::chrono::seconds(5));
if (status != std::future_status::ready) {
- return (DATA(rc_t::TIMEOUT));
+ m_hw_item.set(rc_t::TIMEOUT);
+ } else {
+ m_hw_item = result.get();
}
- return (result.get());
+ return (m_hw_item.rc());
}
/**
*/
virtual vapi_error_e operator()(MSG& reply)
{
+ HWITEM hi = m_hw_item;
int retval = reply.get_response().get_payload().retval;
VOM_LOG(log_level_t::DEBUG) << to_string() << " " << retval;
- fulfill(rc_t::from_vpp_retval(retval));
+
+ /* set a temporary value in this callback thread */
+ hi.set(rc_t::from_vpp_retval(retval));
+ fulfill(hi);
return (VAPI_OK);
}
/**
* The promise that implements the synchronous issue
*/
- std::promise<DATA> m_promise;
+ std::promise<HWITEM> m_promise;
};
};
VAPI_CALL(req.execute());
- m_hw_item = wait();
+ wait();
if (m_hw_item.rc() == rc_t::OK) {
insert_interface();
VAPI_CALL(req.execute());
- m_hw_item = wait();
+ wait();
if (m_hw_item.rc() == rc_t::OK) {
insert_interface();
}
- return rc_t::OK;
+ return (m_hw_item.rc());
}
std::string
INTERFACE,
/**
- * bond group binding is after interfaces but before
- * anything else
+ * virtual interfaces - those that depend on some real interface
*/
- BOND_BINDING,
-
- /**
- * Tunnel or virtual interfaces next
- */
- TUNNEL,
+ VIRTUAL_INTERFACE,
/**
* Tables in which entries are added, e.g bridge/route-domains
*/
struct rc_t : public enum_base<rc_t>
{
- rc_t(const rc_t& rc) = default;
-
/**
* Destructor
*/
dependency_t
vxlan_tunnel::event_handler::order() const
{
- return (dependency_t::TUNNEL);
+ return (dependency_t::VIRTUAL_INTERFACE);
}
void
VAPI_CALL(req.execute());
- m_hw_item = wait();
+ wait();
- if (m_hw_item) {
+ if (rc_t::OK == m_hw_item.rc()) {
insert_interface();
}
/** \brief Reply for pipe create reply
@param context - returned sender context, to match reply w/ request
@param retval - return code
- @param parent_sw_if_index - software index allocated for the new pipe parent interface
- Use the parent interface for link up/down and to delete
+ @param sw_if_index - software index allocated for the new pipe parent interface
+ Use the parent interface for link up/down and to delete
@param pipe_sw_if_index - the two SW indicies that form the ends of the pipe.
*/
define pipe_create_reply
{
u32 context;
i32 retval;
- u32 parent_sw_if_index;
+ u32 sw_if_index;
u32 pipe_sw_if_index[2];
};
/** \brief Delete pipe interface
@param client_index - opaque cookie to identify the sender
@param context - sender context, to match reply w/ request
- @param parnet_sw_if_index - interface index of existing pipe interface
+ @param sw_if_index - interface index of existing pipe interface
*/
autoreply define pipe_delete
{
u32 client_index;
u32 context;
- u32 parent_sw_if_index;
+ u32 sw_if_index;
};
/** \brief Dump pipe interfaces request */
/** \brief Reply for pipe dump request
@param sw_if_index - software index of pipe interface
- @param parent_sw_if_index - software index allocated for the pipe parent interface
+ @param sw_if_index - software index allocated for the pipe parent interface
@param pipe_sw_if_index - the two SW indicies that form the ends of the pipe.
@param instance - instance allocated
*/
define pipe_details
{
u32 context;
- u32 parent_sw_if_index;
+ u32 sw_if_index;
u32 pipe_sw_if_index[2];
u32 instance;
};
/* *INDENT-OFF* */
REPLY_MACRO2(VL_API_PIPE_CREATE_REPLY,
({
- rmp->parent_sw_if_index = ntohl (parent_sw_if_index);
+ rmp->sw_if_index = ntohl (parent_sw_if_index);
rmp->pipe_sw_if_index[0] = ntohl (pipe_sw_if_index[0]);
rmp->pipe_sw_if_index[1] = ntohl (pipe_sw_if_index[1]);
}));
vl_api_pipe_delete_reply_t *rmp;
int rv;
- rv = vnet_delete_pipe_interface (ntohl (mp->parent_sw_if_index));
+ rv = vnet_delete_pipe_interface (ntohl (mp->sw_if_index));
REPLY_MACRO (VL_API_PIPE_DELETE_REPLY);
}
mp->context = ctx->context;
mp->instance = ntohl (instance);
- mp->parent_sw_if_index = ntohl (parent_sw_if_index);
+ mp->sw_if_index = ntohl (parent_sw_if_index);
mp->pipe_sw_if_index[0] = ntohl (pipe_sw_if_index[0]);
mp->pipe_sw_if_index[1] = ntohl (pipe_sw_if_index[1]);
#include "vom/nat_static_cmds.hpp"
#include "vom/nat_binding.hpp"
#include "vom/nat_binding_cmds.hpp"
+#include "vom/pipe.hpp"
+#include "vom/pipe_cmds.hpp"
using namespace boost;
using namespace VOM;
{
rc = handle_derived<interface_cmds::events_cmd>(f_exp, f_act);
}
+ else if (typeid(*f_exp) == typeid(pipe_cmds::create_cmd))
+ {
+ rc = handle_derived<pipe_cmds::create_cmd>(f_exp, f_act);
+ }
+ else if (typeid(*f_exp) == typeid(pipe_cmds::delete_cmd))
+ {
+ rc = handle_derived<pipe_cmds::delete_cmd>(f_exp, f_act);
+ }
else
{
throw ExpException(2);
}
+BOOST_AUTO_TEST_CASE(test_pipes) {
+ VppInit vi;
+ const std::string gk = "GKChesterton";
+
+ const std::string pipe_name_1 = "pipe1";
+ VOM::pipe pipe1(1, interface::admin_state_t::UP);
+ HW::item<handle_t> hw_hdl(4, rc_t::OK);
+ HW::item<pipe::handle_pair_t> hw_hdl_pair(std::make_pair(5,6), rc_t::OK);
+
+ HW::item<interface::admin_state_t> hw_as_up(interface::admin_state_t::UP,
+ rc_t::OK);
+ HW::item<interface::admin_state_t> hw_as_down(interface::admin_state_t::DOWN,
+ rc_t::OK);
+ ADD_EXPECT(pipe_cmds::create_cmd(hw_hdl, pipe_name_1, 1, hw_hdl_pair));
+ ADD_EXPECT(interface_cmds::state_change_cmd(hw_as_up, hw_hdl));
+ TRY_CHECK_RC(OM::write(gk, pipe1));
+
+ pipe1.set_ends(hw_hdl_pair.data());
+
+ // put each end of the pipe in a BD
+ bridge_domain bd1(33, bridge_domain::learning_mode_t::OFF,
+ bridge_domain::arp_term_mode_t::OFF,
+ bridge_domain::flood_mode_t::OFF,
+ bridge_domain::mac_age_mode_t::ON);
+
+ HW::item<uint32_t> hw_bd(33, rc_t::OK);
+ ADD_EXPECT(bridge_domain_cmds::create_cmd(hw_bd,
+ bridge_domain::learning_mode_t::OFF,
+ bridge_domain::arp_term_mode_t::OFF,
+ bridge_domain::flood_mode_t::OFF,
+ bridge_domain::mac_age_mode_t::ON));
+
+ TRY_CHECK_RC(OM::write(gk, bd1));
+
+ l2_binding *l2_1 = new l2_binding(*pipe1.east(), bd1);
+ HW::item<bool> hw_l2_1_bind(true, rc_t::OK);
+
+ ADD_EXPECT(l2_binding_cmds::bind_cmd(hw_l2_1_bind,
+ pipe1.east()->handle(),
+ hw_bd.data(), false));
+ TRY_CHECK_RC(OM::write(gk, *l2_1));
+
+ l2_binding *l2_2 = new l2_binding(*pipe1.west(), bd1);
+ HW::item<bool> hw_l2_2_bind(true, rc_t::OK);
+
+ ADD_EXPECT(l2_binding_cmds::bind_cmd(hw_l2_2_bind,
+ pipe1.west()->handle(),
+ hw_bd.data(), false));
+ TRY_CHECK_RC(OM::write(gk, *l2_2));
+
+ STRICT_ORDER_OFF();
+
+ delete l2_1;
+ delete l2_2;
+ ADD_EXPECT(l2_binding_cmds::unbind_cmd(hw_l2_1_bind,
+ pipe1.east()->handle(),
+ hw_bd.data(),
+ false));
+ ADD_EXPECT(l2_binding_cmds::unbind_cmd(hw_l2_1_bind,
+ pipe1.west()->handle(),
+ hw_bd.data(),
+ false));
+ ADD_EXPECT(interface_cmds::state_change_cmd(hw_as_down, hw_hdl));
+ ADD_EXPECT(pipe_cmds::delete_cmd(hw_hdl, hw_hdl_pair));
+ ADD_EXPECT(bridge_domain_cmds::delete_cmd(hw_bd));
+ TRY_CHECK(OM::remove(gk));
+}
+
BOOST_AUTO_TEST_SUITE_END()
self.result = self._test.vapi.pipe_create(
0 if self.instance == 0xffffffff else 1,
self.instance)
- self.set_sw_if_index(self.result.parent_sw_if_index)
+ self.set_sw_if_index(self.result.sw_if_index)
def remove_vpp_config(self):
self._test.vapi.pipe_delete(
- self.result.parent_sw_if_index)
+ self.result.sw_if_index)
def __str__(self):
return self.object_id()
def query_vpp_config(self):
pipes = self._test.vapi.pipe_dump()
for p in pipes:
- if p.parent_sw_if_index == self.result.parent_sw_if_index:
+ if p.sw_if_index == self.result.sw_if_index:
return True
return False
def test_pipe(self):
""" Pipes """
- pipes = []
- pipes.append(VppPipe(self))
- pipes.append(VppPipe(self, 10))
+ pipes = [VppPipe(self), VppPipe(self, 10)]
for p in pipes:
p.add_vpp_config()