fib: fib api updates
Enhance the route add/del APIs to take a set of paths rather than just one.
Most unicast routing protocols calcualte all the available paths in one
run of the algorithm so updating all the paths at once is beneficial for the client.
two knobs control the behaviour:
is_multipath - if set the the set of paths passed will be added to those
that already exist, otherwise the set will replace them.
is_add - add or remove the set
is_add=0, is_multipath=1 and an empty set, results in deleting the route.
It is also considerably faster to add multiple paths at once, than one at a time:
vat# ip_add_del_route 1.1.1.1/32 count 100000 multipath via 10.10.10.11
100000 routes in .572240 secs, 174751.80 routes/sec
vat# ip_add_del_route 1.1.1.1/32 count 100000 multipath via 10.10.10.12
100000 routes in .528383 secs, 189256.54 routes/sec
vat# ip_add_del_route 1.1.1.1/32 count 100000 multipath via 10.10.10.13
100000 routes in .757131 secs, 132077.52 routes/sec
vat# ip_add_del_route 1.1.1.1/32 count 100000 multipath via 10.10.10.14
100000 routes in .878317 secs, 113854.12 routes/sec
vat# ip_route_add_del 1.1.1.1/32 count 100000 multipath via 10.10.10.11 via 10.10.10.12 via 10.10.10.13 via 10.10.10.14
100000 routes in .900212 secs, 111084.93 routes/sec
Change-Id: I416b93f7684745099c1adb0b33edac58c9339c1a
Signed-off-by: Neale Ranns <neale.ranns@cisco.com>
Signed-off-by: Ole Troan <ot@cisco.com>
Signed-off-by: Paul Vinciguerra <pvinci@vinciconsulting.com>
This commit is contained in:
@@ -45,6 +45,11 @@ from_api(vapi_enum_ip_neighbor_flags f)
|
||||
return out;
|
||||
}
|
||||
|
||||
invalid_decode::invalid_decode(const std::string reason)
|
||||
: reason(reason)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
to_api(const boost::asio::ip::address_v4& a, vapi_type_ip4_address& v)
|
||||
{
|
||||
@@ -82,6 +87,16 @@ to_api(const ip_address_t& a,
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
to_api(const ip_address_t& a, vapi_union_address_union& u)
|
||||
{
|
||||
if (a.is_v4()) {
|
||||
memcpy(u.ip4, a.to_v4().to_bytes().data(), 4);
|
||||
} else {
|
||||
memcpy(u.ip6, a.to_v6().to_bytes().data(), 16);
|
||||
}
|
||||
}
|
||||
|
||||
boost::asio::ip::address_v6
|
||||
from_api(const vapi_type_ip6_address& v)
|
||||
{
|
||||
@@ -122,6 +137,26 @@ from_api(const vapi_type_address& v)
|
||||
return addr;
|
||||
}
|
||||
|
||||
ip_address_t
|
||||
from_api(const vapi_union_address_union& u, vapi_enum_fib_path_nh_proto proto)
|
||||
{
|
||||
boost::asio::ip::address addr;
|
||||
|
||||
if (FIB_API_PATH_NH_PROTO_IP6 == proto) {
|
||||
std::array<uint8_t, 16> a;
|
||||
std::copy(u.ip6, u.ip6 + 16, std::begin(a));
|
||||
boost::asio::ip::address_v6 v6(a);
|
||||
addr = v6;
|
||||
} else if (FIB_API_PATH_NH_PROTO_IP4 == proto) {
|
||||
std::array<uint8_t, 4> a;
|
||||
std::copy(u.ip6, u.ip6 + 4, std::begin(a));
|
||||
boost::asio::ip::address_v4 v4(a);
|
||||
addr = v4;
|
||||
}
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
ip_address_t
|
||||
from_api(const vapi_union_address_union& u, vapi_enum_address_family af)
|
||||
{
|
||||
@@ -187,7 +222,42 @@ to_api(const route::mprefix_t& p)
|
||||
v.af = af;
|
||||
return v;
|
||||
}
|
||||
};
|
||||
|
||||
vapi_enum_fib_path_nh_proto
|
||||
to_api(const nh_proto_t& p)
|
||||
{
|
||||
if (p == nh_proto_t::IPV4) {
|
||||
return FIB_API_PATH_NH_PROTO_IP4;
|
||||
} else if (p == nh_proto_t::IPV6) {
|
||||
return FIB_API_PATH_NH_PROTO_IP6;
|
||||
} else if (p == nh_proto_t::ETHERNET) {
|
||||
return FIB_API_PATH_NH_PROTO_ETHERNET;
|
||||
} else if (p == nh_proto_t::MPLS) {
|
||||
return FIB_API_PATH_NH_PROTO_MPLS;
|
||||
}
|
||||
|
||||
return FIB_API_PATH_NH_PROTO_IP4;
|
||||
}
|
||||
const nh_proto_t&
|
||||
from_api(vapi_enum_fib_path_nh_proto p)
|
||||
{
|
||||
switch (p) {
|
||||
case FIB_API_PATH_NH_PROTO_IP4:
|
||||
return nh_proto_t::IPV4;
|
||||
case FIB_API_PATH_NH_PROTO_IP6:
|
||||
return nh_proto_t::IPV6;
|
||||
case FIB_API_PATH_NH_PROTO_ETHERNET:
|
||||
return nh_proto_t::ETHERNET;
|
||||
case FIB_API_PATH_NH_PROTO_MPLS:
|
||||
return nh_proto_t::MPLS;
|
||||
case FIB_API_PATH_NH_PROTO_BIER:
|
||||
break;
|
||||
}
|
||||
|
||||
return nh_proto_t::IPV4;
|
||||
}
|
||||
|
||||
}; // VOM
|
||||
|
||||
/*
|
||||
* fd.io coding-style-patch-verification: ON
|
||||
|
||||
@@ -22,6 +22,12 @@
|
||||
|
||||
namespace VOM {
|
||||
|
||||
struct invalid_decode
|
||||
{
|
||||
invalid_decode(const std::string reason);
|
||||
const std::string reason;
|
||||
};
|
||||
|
||||
typedef boost::asio::ip::address ip_address_t;
|
||||
|
||||
vapi_enum_ip_neighbor_flags to_api(const neighbour::flags_t& f);
|
||||
@@ -33,12 +39,15 @@ void to_api(const boost::asio::ip::address_v6& a, vapi_type_ip6_address& v);
|
||||
void to_api(const boost::asio::ip::address& a,
|
||||
vapi_union_address_union& u,
|
||||
vapi_enum_address_family& af);
|
||||
void to_api(const boost::asio::ip::address& a, vapi_union_address_union& u);
|
||||
|
||||
boost::asio::ip::address_v4 from_api(const vapi_type_ip4_address& v);
|
||||
boost::asio::ip::address_v6 from_api(const vapi_type_ip6_address& v);
|
||||
ip_address_t from_api(const vapi_type_address& v);
|
||||
ip_address_t from_api(const vapi_union_address_union& u,
|
||||
vapi_enum_address_family af);
|
||||
ip_address_t from_api(const vapi_union_address_union& u,
|
||||
vapi_enum_fib_path_nh_proto proto);
|
||||
|
||||
void to_api(const mac_address_t& a, vapi_type_mac_address& m);
|
||||
|
||||
@@ -49,7 +58,11 @@ route::mprefix_t from_api(const vapi_type_mprefix&);
|
||||
|
||||
vapi_type_prefix to_api(const route::prefix_t&);
|
||||
vapi_type_mprefix to_api(const route::mprefix_t&);
|
||||
};
|
||||
|
||||
vapi_enum_fib_path_nh_proto to_api(const nh_proto_t&);
|
||||
const nh_proto_t& from_api(vapi_enum_fib_path_nh_proto);
|
||||
|
||||
}; // VOM
|
||||
|
||||
/*
|
||||
* fd.io coding-style-patch-verification: ON
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
*/
|
||||
|
||||
#include "vom/interface.hpp"
|
||||
#include "vom/api_types.hpp"
|
||||
#include "vom/bond_group_binding.hpp"
|
||||
#include "vom/bond_group_binding_cmds.hpp"
|
||||
#include "vom/bond_interface_cmds.hpp"
|
||||
@@ -666,8 +667,7 @@ interface::event_handler::handle_populate(const client_db::key_t& key)
|
||||
|
||||
for (auto& l3_record : *dcmd) {
|
||||
auto& payload = l3_record.get_payload();
|
||||
const route::prefix_t pfx(payload.is_ipv6, payload.ip,
|
||||
payload.prefix_length);
|
||||
const route::prefix_t pfx = from_api(payload.prefix);
|
||||
|
||||
VOM_LOG(log_level_t::DEBUG) << "dump: " << pfx.to_string();
|
||||
|
||||
|
||||
@@ -45,18 +45,17 @@ update_cmd::operator==(const update_cmd& other) const
|
||||
rc_t
|
||||
update_cmd::issue(connection& con)
|
||||
{
|
||||
msg_t req(con.ctx(), std::ref(*this));
|
||||
msg_t req(con.ctx(), 1, std::ref(*this));
|
||||
|
||||
auto& payload = req.get_request().get_payload();
|
||||
|
||||
payload.table_id = m_id;
|
||||
payload.is_add = 1;
|
||||
|
||||
m_mprefix.to_vpp(&payload.is_ipv6, payload.src_address, payload.grp_address,
|
||||
&payload.grp_address_length);
|
||||
payload.route.table_id = m_id;
|
||||
payload.route.prefix = to_api(m_mprefix);
|
||||
|
||||
to_vpp(m_path, payload);
|
||||
payload.itf_flags = m_flags.value();
|
||||
to_api(m_path, payload.route.paths[0].path);
|
||||
payload.route.paths[0].itf_flags = to_api(m_flags);
|
||||
|
||||
VAPI_CALL(req.execute());
|
||||
|
||||
@@ -96,17 +95,16 @@ delete_cmd::operator==(const delete_cmd& other) const
|
||||
rc_t
|
||||
delete_cmd::issue(connection& con)
|
||||
{
|
||||
msg_t req(con.ctx(), std::ref(*this));
|
||||
msg_t req(con.ctx(), 1, std::ref(*this));
|
||||
|
||||
auto& payload = req.get_request().get_payload();
|
||||
payload.table_id = m_id;
|
||||
payload.is_add = 0;
|
||||
payload.is_add = 1;
|
||||
|
||||
m_mprefix.to_vpp(&payload.is_ipv6, payload.grp_address, payload.src_address,
|
||||
&payload.grp_address_length);
|
||||
payload.route.table_id = m_id;
|
||||
payload.route.prefix = to_api(m_mprefix);
|
||||
|
||||
to_vpp(m_path, payload);
|
||||
payload.itf_flags = m_flags.value();
|
||||
to_api(m_path, payload.route.paths[0].path);
|
||||
payload.route.paths[0].itf_flags = to_api(m_flags);
|
||||
|
||||
VAPI_CALL(req.execute());
|
||||
|
||||
@@ -126,21 +124,28 @@ delete_cmd::to_string() const
|
||||
return (s.str());
|
||||
}
|
||||
|
||||
dump_v4_cmd::dump_v4_cmd()
|
||||
dump_cmd::dump_cmd(route::table_id_t id, const l3_proto_t& proto)
|
||||
: m_id(id)
|
||||
, m_proto(proto)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
dump_v4_cmd::operator==(const dump_v4_cmd& other) const
|
||||
dump_cmd::operator==(const dump_cmd& other) const
|
||||
{
|
||||
return (true);
|
||||
}
|
||||
|
||||
rc_t
|
||||
dump_v4_cmd::issue(connection& con)
|
||||
dump_cmd::issue(connection& con)
|
||||
{
|
||||
m_dump.reset(new msg_t(con.ctx(), std::ref(*this)));
|
||||
|
||||
auto& payload = m_dump->get_request().get_payload();
|
||||
|
||||
payload.table.table_id = m_id;
|
||||
payload.table.is_ip6 = m_proto.is_ipv6();
|
||||
|
||||
VAPI_CALL(m_dump->execute());
|
||||
|
||||
wait();
|
||||
@@ -149,38 +154,14 @@ dump_v4_cmd::issue(connection& con)
|
||||
}
|
||||
|
||||
std::string
|
||||
dump_v4_cmd::to_string() const
|
||||
dump_cmd::to_string() const
|
||||
{
|
||||
return ("ip-mroute-v4-dump");
|
||||
std::ostringstream s;
|
||||
s << "ip-mroute-dump: id:" << m_id << " proto:" << m_proto.to_string();
|
||||
|
||||
return (s.str());
|
||||
}
|
||||
|
||||
dump_v6_cmd::dump_v6_cmd()
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
dump_v6_cmd::operator==(const dump_v6_cmd& other) const
|
||||
{
|
||||
return (true);
|
||||
}
|
||||
|
||||
rc_t
|
||||
dump_v6_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_v6_cmd::to_string() const
|
||||
{
|
||||
return ("ip-mroute-v6-dump");
|
||||
}
|
||||
} // namespace ip_mroute_cmds
|
||||
} // namespace mroute
|
||||
} // namespace vom
|
||||
|
||||
@@ -103,14 +103,13 @@ private:
|
||||
/**
|
||||
* A cmd class that Dumps ipv4 fib
|
||||
*/
|
||||
class dump_v4_cmd : public VOM::dump_cmd<vapi::Ip_mfib_dump>
|
||||
class dump_cmd : public VOM::dump_cmd<vapi::Ip_mroute_dump>
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
dump_v4_cmd();
|
||||
dump_v4_cmd(const dump_cmd& d);
|
||||
dump_cmd(route::table_id_t id, const l3_proto_t& proto);
|
||||
|
||||
/**
|
||||
* Issue the command to VPP/HW
|
||||
@@ -124,46 +123,15 @@ public:
|
||||
/**
|
||||
* Comparison operator - only used for UT
|
||||
*/
|
||||
bool operator==(const dump_v4_cmd& i) const;
|
||||
|
||||
private:
|
||||
/**
|
||||
* HW reutrn code
|
||||
*/
|
||||
HW::item<bool> item;
|
||||
};
|
||||
|
||||
/**
|
||||
* A cmd class that Dumps ipv6 fib
|
||||
*/
|
||||
class dump_v6_cmd : public VOM::dump_cmd<vapi::Ip6_mfib_dump>
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
dump_v6_cmd();
|
||||
dump_v6_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_v6_cmd& i) const;
|
||||
bool operator==(const dump_cmd& i) const;
|
||||
|
||||
private:
|
||||
/**
|
||||
* HW reutrn code
|
||||
*/
|
||||
HW::item<bool> item;
|
||||
route::table_id_t m_id;
|
||||
const l3_proto_t& m_proto;
|
||||
};
|
||||
|
||||
}; // namespace ip_mroute_cmds
|
||||
|
||||
@@ -181,7 +181,7 @@ private:
|
||||
/**
|
||||
* HW configuration for the result of creating the bridge_domain
|
||||
*/
|
||||
HW::item<bool> m_hw;
|
||||
HW::item<handle_t> m_hw;
|
||||
|
||||
/**
|
||||
* The bridge_domain domain the bridge_domain is in.
|
||||
|
||||
@@ -18,12 +18,12 @@
|
||||
|
||||
namespace VOM {
|
||||
namespace neighbour_cmds {
|
||||
create_cmd::create_cmd(HW::item<bool>& item,
|
||||
create_cmd::create_cmd(HW::item<handle_t>& item,
|
||||
handle_t itf,
|
||||
const mac_address_t& mac,
|
||||
const boost::asio::ip::address& ip_addr,
|
||||
const neighbour::flags_t& flags)
|
||||
: rpc_cmd(item)
|
||||
: srpc_cmd(item)
|
||||
, m_itf(itf)
|
||||
, m_mac(mac)
|
||||
, m_ip_addr(ip_addr)
|
||||
@@ -67,12 +67,12 @@ create_cmd::to_string() const
|
||||
return (s.str());
|
||||
}
|
||||
|
||||
delete_cmd::delete_cmd(HW::item<bool>& item,
|
||||
delete_cmd::delete_cmd(HW::item<handle_t>& item,
|
||||
handle_t itf,
|
||||
const mac_address_t& mac,
|
||||
const boost::asio::ip::address& ip_addr,
|
||||
const neighbour::flags_t& flags)
|
||||
: rpc_cmd(item)
|
||||
: srpc_cmd(item)
|
||||
, m_itf(itf)
|
||||
, m_mac(mac)
|
||||
, m_ip_addr(ip_addr)
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#define __VOM_NEIGHBOUR_CMDS_H__
|
||||
|
||||
#include "vom/dump_cmd.hpp"
|
||||
#include "vom/srpc_cmd.hpp"
|
||||
#include "neighbour.hpp"
|
||||
|
||||
#include <vapi/ip.api.vapi.hpp>
|
||||
@@ -27,14 +28,13 @@ namespace neighbour_cmds {
|
||||
/**
|
||||
* A command class that creates or updates the bridge domain ARP Entry
|
||||
*/
|
||||
class create_cmd : public rpc_cmd<HW::item<bool>,
|
||||
vapi::Ip_neighbor_add_del>
|
||||
class create_cmd : public srpc_cmd<vapi::Ip_neighbor_add_del>
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
create_cmd(HW::item<bool>& item,
|
||||
create_cmd(HW::item<handle_t>& item,
|
||||
handle_t itf,
|
||||
const mac_address_t& mac,
|
||||
const boost::asio::ip::address& ip_addr,
|
||||
@@ -65,14 +65,13 @@ private:
|
||||
/**
|
||||
* A cmd class that deletes a bridge domain ARP entry
|
||||
*/
|
||||
class delete_cmd : public rpc_cmd<HW::item<bool>,
|
||||
vapi::Ip_neighbor_add_del>
|
||||
class delete_cmd : public srpc_cmd<vapi::Ip_neighbor_add_del>
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
delete_cmd(HW::item<bool>& item,
|
||||
delete_cmd(HW::item<handle_t>& item,
|
||||
handle_t itf,
|
||||
const mac_address_t& mac,
|
||||
const boost::asio::ip::address& ip_addr,
|
||||
|
||||
+11
-10
@@ -32,13 +32,13 @@ l3_proto_t::l3_proto_t(int v, const std::string& s)
|
||||
}
|
||||
|
||||
bool
|
||||
l3_proto_t::is_ipv6()
|
||||
l3_proto_t::is_ipv6() const
|
||||
{
|
||||
return (*this == IPV6);
|
||||
}
|
||||
|
||||
bool
|
||||
l3_proto_t::is_ipv4()
|
||||
l3_proto_t::is_ipv4() const
|
||||
{
|
||||
return (*this == IPV4);
|
||||
}
|
||||
@@ -492,15 +492,16 @@ route::mprefix_t::mask_width() const
|
||||
return (m_len);
|
||||
}
|
||||
|
||||
void
|
||||
route::mprefix_t::to_vpp(uint8_t* is_ip6,
|
||||
uint8_t* saddr,
|
||||
uint8_t* gaddr,
|
||||
uint16_t* len) const
|
||||
l3_proto_t
|
||||
route::mprefix_t::l3_proto() const
|
||||
{
|
||||
*len = m_len;
|
||||
to_bytes(m_saddr, is_ip6, saddr);
|
||||
to_bytes(m_gaddr, is_ip6, gaddr);
|
||||
if (m_gaddr.is_v6()) {
|
||||
return (l3_proto_t::IPV6);
|
||||
} else {
|
||||
return (l3_proto_t::IPV4);
|
||||
}
|
||||
|
||||
return (l3_proto_t::IPV4);
|
||||
}
|
||||
|
||||
route::mprefix_t&
|
||||
|
||||
@@ -56,8 +56,8 @@ public:
|
||||
const static l3_proto_t IPV6;
|
||||
const static l3_proto_t MPLS;
|
||||
|
||||
bool is_ipv4();
|
||||
bool is_ipv6();
|
||||
bool is_ipv4() const;
|
||||
bool is_ipv6() const;
|
||||
|
||||
static const l3_proto_t& from_address(const boost::asio::ip::address& addr);
|
||||
|
||||
@@ -233,8 +233,8 @@ public:
|
||||
mprefix_t(const boost::asio::ip::address& gaddr, uint8_t len);
|
||||
|
||||
/**
|
||||
*Constructor for (S,G)
|
||||
*/
|
||||
*Constructor for (S,G)
|
||||
*/
|
||||
mprefix_t(const boost::asio::ip::address& saddr,
|
||||
const boost::asio::ip::address& gaddr,
|
||||
uint16_t len);
|
||||
@@ -300,11 +300,6 @@ public:
|
||||
*/
|
||||
l3_proto_t l3_proto() const;
|
||||
|
||||
void to_vpp(uint8_t* is_ip6,
|
||||
uint8_t* saddr,
|
||||
uint8_t* gaddr,
|
||||
uint16_t* len) const;
|
||||
|
||||
private:
|
||||
/**
|
||||
* The address
|
||||
|
||||
+119
-164
File diff suppressed because it is too large
Load Diff
@@ -218,8 +218,6 @@ public:
|
||||
*/
|
||||
const static itf_flags_t FORWARD;
|
||||
|
||||
static const itf_flags_t& from_vpp(uint32_t val);
|
||||
|
||||
private:
|
||||
/**
|
||||
* Private constructor taking the value and the string name
|
||||
@@ -398,7 +396,7 @@ private:
|
||||
/**
|
||||
* HW configuration for the result of creating the route
|
||||
*/
|
||||
HW::item<bool> m_hw;
|
||||
HW::item<handle_t> m_hw;
|
||||
|
||||
/**
|
||||
* The route domain the route is in.
|
||||
|
||||
@@ -13,111 +13,121 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <vom/api_types.hpp>
|
||||
#include <vom/route.hpp>
|
||||
#include <vom/route_api_types.hpp>
|
||||
|
||||
namespace VOM {
|
||||
|
||||
void
|
||||
to_vpp(const route::path& p, vapi_payload_ip_add_del_route& payload)
|
||||
const route::itf_flags_t&
|
||||
from_api(vapi_enum_mfib_itf_flags val)
|
||||
{
|
||||
payload.is_drop = 0;
|
||||
payload.is_unreach = 0;
|
||||
payload.is_prohibit = 0;
|
||||
payload.is_local = 0;
|
||||
payload.is_classify = 0;
|
||||
payload.is_resolve_host = 0;
|
||||
payload.is_resolve_attached = 0;
|
||||
if (route::itf_flags_t::ACCEPT == val)
|
||||
return route::itf_flags_t::ACCEPT;
|
||||
else
|
||||
return route::itf_flags_t::FORWARD;
|
||||
}
|
||||
|
||||
if (route::path::flags_t::DVR & p.flags()) {
|
||||
payload.is_dvr = 1;
|
||||
}
|
||||
vapi_enum_mfib_itf_flags
|
||||
to_api(const route::itf_flags_t& in)
|
||||
{
|
||||
vapi_enum_mfib_itf_flags out = MFIB_API_ITF_FLAG_NONE;
|
||||
|
||||
if (route::path::special_t::STANDARD == p.type()) {
|
||||
uint8_t path_v6;
|
||||
to_bytes(p.nh(), &path_v6, payload.next_hop_address);
|
||||
payload.next_hop_sw_if_index = 0xffffffff;
|
||||
if (route::itf_flags_t::ACCEPT & in)
|
||||
out = static_cast<vapi_enum_mfib_itf_flags>(out | MFIB_API_ITF_FLAG_ACCEPT);
|
||||
if (route::itf_flags_t::FORWARD & in)
|
||||
out =
|
||||
static_cast<vapi_enum_mfib_itf_flags>(out | MFIB_API_ITF_FLAG_FORWARD);
|
||||
|
||||
if (p.rd()) {
|
||||
payload.next_hop_table_id = p.rd()->table_id();
|
||||
}
|
||||
if (p.itf()) {
|
||||
payload.next_hop_sw_if_index = p.itf()->handle().value();
|
||||
}
|
||||
} else if (route::path::special_t::DROP == p.type()) {
|
||||
payload.is_drop = 1;
|
||||
} else if (route::path::special_t::UNREACH == p.type()) {
|
||||
payload.is_unreach = 1;
|
||||
} else if (route::path::special_t::PROHIBIT == p.type()) {
|
||||
payload.is_prohibit = 1;
|
||||
} else if (route::path::special_t::LOCAL == p.type()) {
|
||||
payload.is_local = 1;
|
||||
}
|
||||
payload.next_hop_weight = p.weight();
|
||||
payload.next_hop_preference = p.preference();
|
||||
payload.next_hop_via_label = 0x100000;
|
||||
payload.classify_table_index = 0;
|
||||
return (out);
|
||||
}
|
||||
|
||||
void
|
||||
to_vpp(const route::path& p, vapi_payload_ip_mroute_add_del& payload)
|
||||
to_api(const route::path& p, vapi_type_fib_path& payload)
|
||||
{
|
||||
payload.next_hop_afi = p.nh_proto();
|
||||
payload.flags = FIB_API_PATH_FLAG_NONE;
|
||||
payload.proto = to_api(p.nh_proto());
|
||||
payload.sw_if_index = ~0;
|
||||
|
||||
if (route::path::special_t::STANDARD == p.type()) {
|
||||
uint8_t path_v6;
|
||||
to_bytes(p.nh(), &path_v6, payload.nh_address);
|
||||
if (route::path::flags_t::DVR & p.flags()) {
|
||||
payload.type = FIB_API_PATH_TYPE_DVR;
|
||||
} else if (route::path::special_t::STANDARD == p.type()) {
|
||||
to_api(p.nh(), payload.nh.address);
|
||||
|
||||
if (p.itf()) {
|
||||
payload.next_hop_sw_if_index = p.itf()->handle().value();
|
||||
if (p.rd()) {
|
||||
payload.table_id = p.rd()->table_id();
|
||||
}
|
||||
|
||||
payload.next_hop_afi = p.nh_proto();
|
||||
if (p.itf()) {
|
||||
payload.sw_if_index = p.itf()->handle().value();
|
||||
}
|
||||
} else if (route::path::special_t::DROP == p.type()) {
|
||||
payload.type = FIB_API_PATH_TYPE_DROP;
|
||||
} else if (route::path::special_t::UNREACH == p.type()) {
|
||||
payload.type = FIB_API_PATH_TYPE_ICMP_UNREACH;
|
||||
} else if (route::path::special_t::PROHIBIT == p.type()) {
|
||||
payload.type = FIB_API_PATH_TYPE_ICMP_PROHIBIT;
|
||||
} else if (route::path::special_t::LOCAL == p.type()) {
|
||||
payload.is_local = 1;
|
||||
payload.type = FIB_API_PATH_TYPE_LOCAL;
|
||||
}
|
||||
|
||||
payload.weight = p.weight();
|
||||
payload.preference = p.preference();
|
||||
payload.n_labels = 0;
|
||||
}
|
||||
|
||||
route::path
|
||||
from_vpp(const vapi_type_fib_path& p, const nh_proto_t& nhp)
|
||||
from_api(const vapi_type_fib_path& p)
|
||||
{
|
||||
if (p.is_local) {
|
||||
return route::path(route::path::special_t::LOCAL);
|
||||
} else if (p.is_drop) {
|
||||
return route::path(route::path::special_t::DROP);
|
||||
} else if (p.is_unreach) {
|
||||
return route::path(route::path::special_t::UNREACH);
|
||||
} else if (p.is_prohibit) {
|
||||
return route::path(route::path::special_t::PROHIBIT);
|
||||
} else {
|
||||
boost::asio::ip::address address =
|
||||
from_bytes(nh_proto_t::IPV6 == nhp, p.next_hop);
|
||||
std::shared_ptr<interface> itf = interface::find(p.sw_if_index);
|
||||
if (itf) {
|
||||
if (p.is_dvr) {
|
||||
return route::path(*itf, nhp, route::path::flags_t::DVR, p.weight,
|
||||
p.preference);
|
||||
switch (p.type) {
|
||||
case FIB_API_PATH_TYPE_DVR: {
|
||||
std::shared_ptr<interface> itf = interface::find(p.sw_if_index);
|
||||
if (!itf)
|
||||
throw invalid_decode("fib-path deocde no interface:" +
|
||||
std::to_string(p.sw_if_index));
|
||||
|
||||
return (route::path(*itf, from_api(p.proto), route::path::flags_t::DVR,
|
||||
p.weight, p.preference));
|
||||
}
|
||||
case FIB_API_PATH_TYPE_NORMAL: {
|
||||
boost::asio::ip::address address = from_api(p.nh.address, p.proto);
|
||||
std::shared_ptr<interface> itf = interface::find(p.sw_if_index);
|
||||
if (itf) {
|
||||
return (route::path(address, *itf, p.weight, p.preference));
|
||||
} else {
|
||||
return route::path(address, *itf, p.weight, p.preference);
|
||||
}
|
||||
} else {
|
||||
std::shared_ptr<route_domain> rd = route_domain::find(p.table_id);
|
||||
if (rd) {
|
||||
return route::path(*rd, address, p.weight, p.preference);
|
||||
std::shared_ptr<route_domain> rd = route_domain::find(p.table_id);
|
||||
|
||||
if (!rd)
|
||||
throw invalid_decode("fib-path deocde no route-domain:" +
|
||||
std::to_string(p.table_id));
|
||||
|
||||
return (route::path(*rd, address, p.weight, p.preference));
|
||||
}
|
||||
}
|
||||
case FIB_API_PATH_TYPE_LOCAL:
|
||||
return (route::path(route::path::special_t::LOCAL));
|
||||
case FIB_API_PATH_TYPE_DROP:
|
||||
return (route::path(route::path::special_t::DROP));
|
||||
case FIB_API_PATH_TYPE_ICMP_UNREACH:
|
||||
return (route::path(route::path::special_t::PROHIBIT));
|
||||
case FIB_API_PATH_TYPE_ICMP_PROHIBIT:
|
||||
return (route::path(route::path::special_t::UNREACH));
|
||||
|
||||
case FIB_API_PATH_TYPE_UDP_ENCAP:
|
||||
case FIB_API_PATH_TYPE_BIER_IMP:
|
||||
case FIB_API_PATH_TYPE_SOURCE_LOOKUP:
|
||||
case FIB_API_PATH_TYPE_INTERFACE_RX:
|
||||
case FIB_API_PATH_TYPE_CLASSIFY:
|
||||
// not done yet
|
||||
break;
|
||||
}
|
||||
|
||||
VOM_LOG(log_level_t::ERROR) << "cannot decode: ";
|
||||
|
||||
return route::path(route::path::special_t::DROP);
|
||||
}
|
||||
return (route::path(route::path::special_t::DROP));
|
||||
};
|
||||
|
||||
/*
|
||||
* fd.io coding-style-patch-verification: ON
|
||||
*
|
||||
* Local Variables:
|
||||
* eval: (c-set-style "mozilla")
|
||||
* End:
|
||||
*/
|
||||
}; // namespace VOM
|
||||
/*
|
||||
* fd.io coding-style-patch-verification: ON
|
||||
*
|
||||
* Local Variables:
|
||||
* eval: (c-set-style "mozilla")
|
||||
* End:
|
||||
*/
|
||||
|
||||
@@ -19,10 +19,12 @@
|
||||
|
||||
namespace VOM {
|
||||
|
||||
void to_vpp(const route::path& p, vapi_payload_ip_mroute_add_del& payload);
|
||||
void to_vpp(const route::path& p, vapi_payload_ip_add_del_route& payload);
|
||||
vapi_enum_mfib_itf_flags to_api(const route::itf_flags_t& flags);
|
||||
const route::itf_flags_t& from_api(vapi_enum_mfib_itf_flags flags);
|
||||
|
||||
route::path from_vpp(const vapi_type_fib_path& p, const nh_proto_t& nh);
|
||||
void to_api(const route::path& p, vapi_type_fib_path& o);
|
||||
|
||||
route::path from_api(const vapi_type_fib_path& p);
|
||||
|
||||
}; // namespace VOM
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include <vom/api_types.hpp>
|
||||
#include <vom/route_api_types.hpp>
|
||||
#include <vom/route_cmds.hpp>
|
||||
|
||||
@@ -22,14 +23,14 @@ namespace VOM {
|
||||
namespace route {
|
||||
namespace ip_route_cmds {
|
||||
|
||||
update_cmd::update_cmd(HW::item<bool>& item,
|
||||
update_cmd::update_cmd(HW::item<handle_t>& item,
|
||||
table_id_t id,
|
||||
const prefix_t& prefix,
|
||||
const path& path)
|
||||
: rpc_cmd(item)
|
||||
const path_list_t& pl)
|
||||
: srpc_cmd(item)
|
||||
, m_id(id)
|
||||
, m_prefix(prefix)
|
||||
, m_path(path)
|
||||
, m_pl(pl)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -37,23 +38,26 @@ bool
|
||||
update_cmd::operator==(const update_cmd& other) const
|
||||
{
|
||||
return ((m_prefix == other.m_prefix) && (m_id == other.m_id) &&
|
||||
(m_path == other.m_path));
|
||||
(m_pl == other.m_pl));
|
||||
}
|
||||
|
||||
rc_t
|
||||
update_cmd::issue(connection& con)
|
||||
{
|
||||
msg_t req(con.ctx(), 0, std::ref(*this));
|
||||
msg_t req(con.ctx(), m_pl.size(), std::ref(*this));
|
||||
|
||||
auto& payload = req.get_request().get_payload();
|
||||
|
||||
payload.table_id = m_id;
|
||||
payload.route.table_id = m_id;
|
||||
payload.is_add = 1;
|
||||
payload.is_multipath = 1;
|
||||
|
||||
m_prefix.to_vpp(&payload.is_ipv6, payload.dst_address,
|
||||
&payload.dst_address_length);
|
||||
to_vpp(m_path, payload);
|
||||
payload.route.table_id = m_id;
|
||||
payload.route.prefix = to_api(m_prefix);
|
||||
|
||||
uint32_t ii = 0;
|
||||
for (auto& p : m_pl)
|
||||
to_api(p, payload.route.paths[ii++]);
|
||||
|
||||
VAPI_CALL(req.execute());
|
||||
|
||||
@@ -65,27 +69,26 @@ update_cmd::to_string() const
|
||||
{
|
||||
std::ostringstream s;
|
||||
s << "ip-route-create: " << m_hw_item.to_string() << " table-id:" << m_id
|
||||
<< " prefix:" << m_prefix.to_string() << " paths:" << m_path.to_string();
|
||||
<< " prefix:" << m_prefix.to_string() << " paths:";
|
||||
for (auto p : m_pl)
|
||||
s << p.to_string() << " ";
|
||||
|
||||
return (s.str());
|
||||
}
|
||||
|
||||
delete_cmd::delete_cmd(HW::item<bool>& item,
|
||||
delete_cmd::delete_cmd(HW::item<handle_t>& item,
|
||||
table_id_t id,
|
||||
const prefix_t& prefix,
|
||||
const path& path)
|
||||
const prefix_t& prefix)
|
||||
: rpc_cmd(item)
|
||||
, m_id(id)
|
||||
, m_prefix(prefix)
|
||||
, m_path(path)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
delete_cmd::operator==(const delete_cmd& other) const
|
||||
{
|
||||
return ((m_prefix == other.m_prefix) && (m_id == other.m_id) &&
|
||||
(m_path == other.m_path));
|
||||
return ((m_prefix == other.m_prefix) && (m_id == other.m_id));
|
||||
}
|
||||
|
||||
rc_t
|
||||
@@ -94,12 +97,12 @@ delete_cmd::issue(connection& con)
|
||||
msg_t req(con.ctx(), 0, std::ref(*this));
|
||||
|
||||
auto& payload = req.get_request().get_payload();
|
||||
payload.table_id = m_id;
|
||||
payload.route.table_id = m_id;
|
||||
payload.is_add = 0;
|
||||
payload.is_multipath = 0;
|
||||
|
||||
m_prefix.to_vpp(&payload.is_ipv6, payload.dst_address,
|
||||
&payload.dst_address_length);
|
||||
to_vpp(m_path, payload);
|
||||
payload.route.table_id = m_id;
|
||||
payload.route.prefix = to_api(m_prefix);
|
||||
|
||||
VAPI_CALL(req.execute());
|
||||
|
||||
@@ -114,26 +117,33 @@ delete_cmd::to_string() const
|
||||
{
|
||||
std::ostringstream s;
|
||||
s << "ip-route-delete: " << m_hw_item.to_string() << " id:" << m_id
|
||||
<< " prefix:" << m_prefix.to_string() << " paths:" << m_path.to_string();
|
||||
<< " prefix:" << m_prefix.to_string();
|
||||
|
||||
return (s.str());
|
||||
}
|
||||
|
||||
dump_v4_cmd::dump_v4_cmd()
|
||||
dump_cmd::dump_cmd(route::table_id_t id, const l3_proto_t& proto)
|
||||
: m_id(id)
|
||||
, m_proto(proto)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
dump_v4_cmd::operator==(const dump_v4_cmd& other) const
|
||||
dump_cmd::operator==(const dump_cmd& other) const
|
||||
{
|
||||
return (true);
|
||||
}
|
||||
|
||||
rc_t
|
||||
dump_v4_cmd::issue(connection& con)
|
||||
dump_cmd::issue(connection& con)
|
||||
{
|
||||
m_dump.reset(new msg_t(con.ctx(), std::ref(*this)));
|
||||
|
||||
auto& payload = m_dump->get_request().get_payload();
|
||||
|
||||
payload.table.table_id = m_id;
|
||||
payload.table.is_ip6 = m_proto.is_ipv6();
|
||||
|
||||
VAPI_CALL(m_dump->execute());
|
||||
|
||||
wait();
|
||||
@@ -142,45 +152,19 @@ dump_v4_cmd::issue(connection& con)
|
||||
}
|
||||
|
||||
std::string
|
||||
dump_v4_cmd::to_string() const
|
||||
dump_cmd::to_string() const
|
||||
{
|
||||
return ("ip-route-v4-dump");
|
||||
}
|
||||
|
||||
dump_v6_cmd::dump_v6_cmd()
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
dump_v6_cmd::operator==(const dump_v6_cmd& other) const
|
||||
{
|
||||
return (true);
|
||||
}
|
||||
|
||||
rc_t
|
||||
dump_v6_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_v6_cmd::to_string() const
|
||||
{
|
||||
return ("ip-route-v6-dump");
|
||||
}
|
||||
} // namespace ip_route_cmds
|
||||
} // namespace route
|
||||
} // namespace vom
|
||||
/*
|
||||
* fd.io coding-style-patch-verification: ON
|
||||
*
|
||||
* Local Variables:
|
||||
* eval: (c-set-style "mozilla")
|
||||
* End:
|
||||
*/
|
||||
|
||||
/*
|
||||
* fd.io coding-style-patch-verification: ON
|
||||
*
|
||||
* Local Variables:
|
||||
* eval: (c-set-style "mozilla")
|
||||
* End:
|
||||
*/
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
#include "vom/dump_cmd.hpp"
|
||||
#include "vom/route.hpp"
|
||||
#include "vom/rpc_cmd.hpp"
|
||||
#include "vom/srpc_cmd.hpp"
|
||||
|
||||
#include <vapi/ip.api.vapi.hpp>
|
||||
|
||||
@@ -29,16 +29,16 @@ namespace ip_route_cmds {
|
||||
/**
|
||||
* A command class that creates or updates the route
|
||||
*/
|
||||
class update_cmd : public rpc_cmd<HW::item<bool>, vapi::Ip_add_del_route>
|
||||
class update_cmd : public srpc_cmd<vapi::Ip_route_add_del>
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
update_cmd(HW::item<bool>& item,
|
||||
update_cmd(HW::item<handle_t>& item,
|
||||
table_id_t id,
|
||||
const prefix_t& prefix,
|
||||
const path& path);
|
||||
const path_list_t& pl);
|
||||
|
||||
/**
|
||||
* Issue the command to VPP/HW
|
||||
@@ -58,22 +58,19 @@ public:
|
||||
private:
|
||||
route::table_id_t m_id;
|
||||
prefix_t m_prefix;
|
||||
const path m_path;
|
||||
const path_list_t& m_pl;
|
||||
};
|
||||
|
||||
/**
|
||||
* A cmd class that deletes a route
|
||||
*/
|
||||
class delete_cmd : public rpc_cmd<HW::item<bool>, vapi::Ip_add_del_route>
|
||||
class delete_cmd : public rpc_cmd<HW::item<handle_t>, vapi::Ip_route_add_del>
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
delete_cmd(HW::item<bool>& item,
|
||||
table_id_t id,
|
||||
const prefix_t& prefix,
|
||||
const path& path);
|
||||
delete_cmd(HW::item<handle_t>& item, table_id_t id, const prefix_t& prefix);
|
||||
|
||||
/**
|
||||
* Issue the command to VPP/HW
|
||||
@@ -93,20 +90,19 @@ public:
|
||||
private:
|
||||
route::table_id_t m_id;
|
||||
prefix_t m_prefix;
|
||||
const path m_path;
|
||||
};
|
||||
|
||||
/**
|
||||
* A cmd class that Dumps ipv4 fib
|
||||
* A cmd class that Dumps ip fib routes
|
||||
*/
|
||||
class dump_v4_cmd : public VOM::dump_cmd<vapi::Ip_fib_dump>
|
||||
class dump_cmd : public VOM::dump_cmd<vapi::Ip_route_dump>
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
dump_v4_cmd();
|
||||
dump_v4_cmd(const dump_cmd& d);
|
||||
dump_cmd(route::table_id_t id, const l3_proto_t& proto);
|
||||
dump_cmd(const dump_cmd& d);
|
||||
|
||||
/**
|
||||
* Issue the command to VPP/HW
|
||||
@@ -120,46 +116,15 @@ public:
|
||||
/**
|
||||
* Comparison operator - only used for UT
|
||||
*/
|
||||
bool operator==(const dump_v4_cmd& i) const;
|
||||
|
||||
private:
|
||||
/**
|
||||
* HW reutrn code
|
||||
*/
|
||||
HW::item<bool> item;
|
||||
};
|
||||
|
||||
/**
|
||||
* A cmd class that Dumps ipv6 fib
|
||||
*/
|
||||
class dump_v6_cmd : public VOM::dump_cmd<vapi::Ip6_fib_dump>
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
dump_v6_cmd();
|
||||
dump_v6_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_v6_cmd& i) const;
|
||||
bool operator==(const dump_cmd& i) const;
|
||||
|
||||
private:
|
||||
/**
|
||||
* HW reutrn code
|
||||
*/
|
||||
HW::item<bool> item;
|
||||
route::table_id_t m_id;
|
||||
const l3_proto_t& m_proto;
|
||||
};
|
||||
|
||||
}; // namespace ip_route_cmds
|
||||
|
||||
@@ -62,6 +62,18 @@ route_domain::key() const
|
||||
return (table_id());
|
||||
}
|
||||
|
||||
route_domain::const_iterator_t
|
||||
route_domain::cbegin()
|
||||
{
|
||||
return m_db.begin();
|
||||
}
|
||||
|
||||
route_domain::const_iterator_t
|
||||
route_domain::cend()
|
||||
{
|
||||
return m_db.end();
|
||||
}
|
||||
|
||||
void
|
||||
route_domain::sweep()
|
||||
{
|
||||
@@ -159,6 +171,26 @@ route_domain::dump(std::ostream& os)
|
||||
void
|
||||
route_domain::event_handler::handle_populate(const client_db::key_t& key)
|
||||
{
|
||||
std::shared_ptr<route_domain_cmds::dump_cmd> cmd =
|
||||
std::make_shared<route_domain_cmds::dump_cmd>();
|
||||
|
||||
HW::enqueue(cmd);
|
||||
HW::write();
|
||||
|
||||
for (auto& record : *cmd) {
|
||||
auto& payload = record.get_payload();
|
||||
|
||||
route_domain rd(payload.table.table_id);
|
||||
|
||||
VOM_LOG(log_level_t::DEBUG) << "ip-table-dump: " << rd.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, rd);
|
||||
}
|
||||
}
|
||||
|
||||
route_domain::event_handler::event_handler()
|
||||
|
||||
@@ -36,6 +36,15 @@ public:
|
||||
*/
|
||||
typedef route::table_id_t key_t;
|
||||
|
||||
/**
|
||||
* The iterator type
|
||||
*/
|
||||
typedef singular_db<const key_t, route_domain>::const_iterator
|
||||
const_iterator_t;
|
||||
|
||||
static const_iterator_t cbegin();
|
||||
static const_iterator_t cend();
|
||||
|
||||
/**
|
||||
* Construct a new object matching the desried state
|
||||
*/
|
||||
|
||||
@@ -39,9 +39,9 @@ create_cmd::issue(connection& con)
|
||||
msg_t req(con.ctx(), std::ref(*this));
|
||||
|
||||
auto& payload = req.get_request().get_payload();
|
||||
payload.table_id = m_id;
|
||||
payload.table.table_id = m_id;
|
||||
payload.table.is_ip6 = m_proto.is_ipv6();
|
||||
payload.is_add = 1;
|
||||
payload.is_ipv6 = m_proto.is_ipv6();
|
||||
|
||||
VAPI_CALL(req.execute());
|
||||
|
||||
@@ -79,9 +79,9 @@ delete_cmd::issue(connection& con)
|
||||
msg_t req(con.ctx(), std::ref(*this));
|
||||
|
||||
auto& payload = req.get_request().get_payload();
|
||||
payload.table_id = m_id;
|
||||
payload.table.table_id = m_id;
|
||||
payload.table.is_ip6 = m_proto.is_ipv6();
|
||||
payload.is_add = 0;
|
||||
payload.is_ipv6 = m_proto.is_ipv6();
|
||||
|
||||
VAPI_CALL(req.execute());
|
||||
|
||||
@@ -100,6 +100,35 @@ delete_cmd::to_string() const
|
||||
|
||||
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 ("ip-table-dump");
|
||||
}
|
||||
|
||||
} // namespace route_domain_cmds
|
||||
} // namespace VOM
|
||||
/*
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#ifndef __VOM_ROUTE_DOMAIN_CMDS_H__
|
||||
#define __VOM_ROUTE_DOMAIN_CMDS_H__
|
||||
|
||||
#include "vom/dump_cmd.hpp"
|
||||
#include "vom/route_domain.hpp"
|
||||
#include "vom/rpc_cmd.hpp"
|
||||
|
||||
@@ -100,6 +101,39 @@ private:
|
||||
l3_proto_t m_proto;
|
||||
};
|
||||
|
||||
/**
|
||||
* A cmd class that Dumps IP fib tables
|
||||
*/
|
||||
class dump_cmd : public VOM::dump_cmd<vapi::Ip_table_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;
|
||||
};
|
||||
|
||||
}; // namespace route_domain_cmds
|
||||
}; // namespace VOM
|
||||
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* 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_SRPC_CMD_H__
|
||||
#define __VOM_SRPC_CMD_H__
|
||||
|
||||
#include "vom/hw.hpp"
|
||||
#include "vom/rpc_cmd.hpp"
|
||||
|
||||
namespace VOM {
|
||||
template <typename MSG>
|
||||
class srpc_cmd : public rpc_cmd<HW::item<handle_t>, MSG>
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* convenient typedef
|
||||
*/
|
||||
typedef MSG msg_t;
|
||||
|
||||
/**
|
||||
* Constructor taking the HW item that will be updated by the command
|
||||
*/
|
||||
srpc_cmd(HW::item<handle_t>& item)
|
||||
: rpc_cmd<HW::item<handle_t>, MSG>(item)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Desructor
|
||||
*/
|
||||
virtual ~srpc_cmd() {}
|
||||
|
||||
virtual vapi_error_e operator()(MSG& reply)
|
||||
{
|
||||
int stats_index = reply.get_response().get_payload().stats_index;
|
||||
int retval = reply.get_response().get_payload().retval;
|
||||
|
||||
VOM_LOG(log_level_t::DEBUG) << this->to_string() << " " << retval;
|
||||
|
||||
rc_t rc = rc_t::from_vpp_retval(retval);
|
||||
handle_t handle = handle_t::INVALID;
|
||||
|
||||
if (rc_t::OK == rc) {
|
||||
handle = stats_index;
|
||||
}
|
||||
|
||||
this->fulfill(HW::item<handle_t>(handle, rc));
|
||||
|
||||
return (VAPI_OK);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
/*
|
||||
* fd.io coding-style-patch-verification: ON
|
||||
*
|
||||
* Local Variables:
|
||||
* eval: (c-set-style "mozilla")
|
||||
* End:
|
||||
*/
|
||||
|
||||
#endif
|
||||
@@ -20,6 +20,7 @@
|
||||
*/
|
||||
|
||||
option version = "1.0.0";
|
||||
import "vnet/ip/ip_types.api";
|
||||
import "vnet/fib/fib_types.api";
|
||||
|
||||
/** \brief Get the plugin version
|
||||
|
||||
@@ -101,7 +101,7 @@ vl_api_abf_policy_add_del_t_handler (vl_api_abf_policy_add_del_t * mp)
|
||||
for (pi = 0; pi < mp->policy.n_paths; pi++)
|
||||
{
|
||||
path = &paths[pi];
|
||||
rv = fib_path_api_parse (&mp->policy.paths[pi], path);
|
||||
rv = fib_api_path_decode (&mp->policy.paths[pi], path);
|
||||
|
||||
if (0 != rv)
|
||||
{
|
||||
@@ -158,9 +158,12 @@ typedef struct abf_dump_walk_ctx_t_
|
||||
static int
|
||||
abf_policy_send_details (u32 api, void *args)
|
||||
{
|
||||
fib_route_path_encode_t *api_rpaths = NULL, *api_rpath;
|
||||
fib_path_encode_ctx_t walk_ctx = {
|
||||
.rpaths = NULL,
|
||||
};
|
||||
vl_api_abf_policy_details_t *mp;
|
||||
abf_dump_walk_ctx_t *ctx;
|
||||
fib_route_path_t *rpath;
|
||||
vl_api_fib_path_t *fp;
|
||||
size_t msg_size;
|
||||
abf_policy_t *ap;
|
||||
@@ -181,17 +184,19 @@ abf_policy_send_details (u32 api, void *args)
|
||||
mp->policy.acl_index = htonl (ap->ap_acl);
|
||||
mp->policy.policy_id = htonl (ap->ap_id);
|
||||
|
||||
fib_path_list_walk_w_ext (ap->ap_pl, NULL, fib_path_encode, &api_rpaths);
|
||||
fib_path_list_walk_w_ext (ap->ap_pl, NULL, fib_path_encode, &walk_ctx);
|
||||
|
||||
fp = mp->policy.paths;
|
||||
vec_foreach (api_rpath, api_rpaths)
|
||||
vec_foreach (rpath, walk_ctx.rpaths)
|
||||
{
|
||||
fib_api_path_encode (api_rpath, fp);
|
||||
fib_api_path_encode (rpath, fp);
|
||||
fp++;
|
||||
}
|
||||
|
||||
vl_api_send_msg (ctx->rp, (u8 *) mp);
|
||||
|
||||
vec_free (walk_ctx.rpaths);
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
|
||||
@@ -17,3 +17,4 @@
|
||||
|
||||
abf_error (NONE, "no match")
|
||||
abf_error (MATCHED, "matched")
|
||||
abf_error (MISSED, "missed")
|
||||
|
||||
@@ -505,12 +505,12 @@ abf_input_inline (vlib_main_t * vm,
|
||||
vlib_node_runtime_t * node,
|
||||
vlib_frame_t * frame, fib_protocol_t fproto)
|
||||
{
|
||||
u32 n_left_from, *from, *to_next, next_index, matches;
|
||||
u32 n_left_from, *from, *to_next, next_index, matches, misses;
|
||||
|
||||
from = vlib_frame_vector_args (frame);
|
||||
n_left_from = frame->n_vectors;
|
||||
next_index = node->cached_next_index;
|
||||
matches = 0;
|
||||
matches = misses = 0;
|
||||
|
||||
while (n_left_from > 0)
|
||||
{
|
||||
@@ -530,6 +530,7 @@ abf_input_inline (vlib_main_t * vm,
|
||||
u32 match_acl_pos = ~0;
|
||||
u32 match_rule_index = ~0;
|
||||
u32 trace_bitmap = 0;
|
||||
u32 lc_index;
|
||||
u8 action;
|
||||
|
||||
bi0 = from[0];
|
||||
@@ -549,7 +550,7 @@ abf_input_inline (vlib_main_t * vm,
|
||||
/*
|
||||
* check if any of the policies attached to this interface matches.
|
||||
*/
|
||||
u32 lc_index = abf_alctx_per_itf[fproto][sw_if_index0];
|
||||
lc_index = abf_alctx_per_itf[fproto][sw_if_index0];
|
||||
|
||||
/*
|
||||
A non-inline version looks like this:
|
||||
@@ -589,6 +590,7 @@ abf_input_inline (vlib_main_t * vm,
|
||||
* move on down the feature arc
|
||||
*/
|
||||
vnet_feature_next (&next0, b0);
|
||||
misses++;
|
||||
}
|
||||
|
||||
if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
|
||||
@@ -614,6 +616,11 @@ abf_input_inline (vlib_main_t * vm,
|
||||
abf_ip4_node.index :
|
||||
abf_ip6_node.index),
|
||||
ABF_ERROR_MATCHED, matches);
|
||||
vlib_node_increment_counter (vm,
|
||||
(fproto = FIB_PROTOCOL_IP6 ?
|
||||
abf_ip4_node.index :
|
||||
abf_ip6_node.index),
|
||||
ABF_ERROR_MISSED, misses);
|
||||
|
||||
return frame->n_vectors;
|
||||
}
|
||||
|
||||
@@ -520,8 +520,9 @@ int vnet_gtpu_add_del_tunnel
|
||||
.frp_addr = zero_addr,
|
||||
.frp_sw_if_index = 0xffffffff,
|
||||
.frp_fib_index = ~0,
|
||||
.frp_weight = 0,
|
||||
.frp_weight = 1,
|
||||
.frp_flags = FIB_ROUTE_PATH_LOCAL,
|
||||
.frp_mitf_flags = MFIB_ITF_FLAG_FORWARD,
|
||||
};
|
||||
const mfib_prefix_t mpfx = {
|
||||
.fp_proto = fp,
|
||||
@@ -535,17 +536,14 @@ int vnet_gtpu_add_del_tunnel
|
||||
* - the accepting interface is that from the API
|
||||
*/
|
||||
mfib_table_entry_path_update (t->encap_fib_index,
|
||||
&mpfx,
|
||||
MFIB_SOURCE_GTPU,
|
||||
&path, MFIB_ITF_FLAG_FORWARD);
|
||||
&mpfx, MFIB_SOURCE_GTPU, &path);
|
||||
|
||||
path.frp_sw_if_index = a->mcast_sw_if_index;
|
||||
path.frp_flags = FIB_ROUTE_PATH_FLAG_NONE;
|
||||
path.frp_mitf_flags = MFIB_ITF_FLAG_ACCEPT;
|
||||
mfei = mfib_table_entry_path_update (t->encap_fib_index,
|
||||
&mpfx,
|
||||
MFIB_SOURCE_GTPU,
|
||||
&path,
|
||||
MFIB_ITF_FLAG_ACCEPT);
|
||||
MFIB_SOURCE_GTPU, &path);
|
||||
|
||||
/*
|
||||
* Create the mcast adjacency to send traffic to the group
|
||||
|
||||
+17
-20
@@ -346,15 +346,6 @@ igmp_enable_disable (u32 sw_if_index, u8 enable, igmp_mode_t mode)
|
||||
format_vnet_sw_if_index_name, vnet_get_main (), sw_if_index);
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
fib_route_path_t for_us_path =
|
||||
{
|
||||
.frp_proto = fib_proto_to_dpo (FIB_PROTOCOL_IP4),
|
||||
.frp_addr = zero_addr,
|
||||
.frp_sw_if_index = 0xffffffff,
|
||||
.frp_fib_index = 0,
|
||||
.frp_weight = 1,
|
||||
.frp_flags = FIB_ROUTE_PATH_LOCAL,
|
||||
};
|
||||
fib_route_path_t via_itf_path =
|
||||
{
|
||||
.frp_proto = fib_proto_to_dpo (FIB_PROTOCOL_IP4),
|
||||
@@ -362,7 +353,18 @@ igmp_enable_disable (u32 sw_if_index, u8 enable, igmp_mode_t mode)
|
||||
.frp_sw_if_index = sw_if_index,
|
||||
.frp_fib_index = 0,
|
||||
.frp_weight = 1,
|
||||
.frp_mitf_flags = MFIB_ITF_FLAG_ACCEPT,
|
||||
};
|
||||
fib_route_path_t for_us_path = {
|
||||
.frp_proto = fib_proto_to_dpo (FIB_PROTOCOL_IP4),
|
||||
.frp_addr = zero_addr,
|
||||
.frp_sw_if_index = 0xffffffff,
|
||||
.frp_fib_index = 1,
|
||||
.frp_weight = 0,
|
||||
.frp_flags = FIB_ROUTE_PATH_LOCAL,
|
||||
.frp_mitf_flags = MFIB_ITF_FLAG_FORWARD,
|
||||
};
|
||||
|
||||
/* *INDENT-ON* */
|
||||
/* find configuration, if it doesn't exist, create new */
|
||||
config = igmp_config_lookup (sw_if_index);
|
||||
@@ -405,24 +407,19 @@ igmp_enable_disable (u32 sw_if_index, u8 enable, igmp_mode_t mode)
|
||||
if (1 == im->n_configs_per_mfib_index[mfib_index])
|
||||
{
|
||||
/* first config in this FIB */
|
||||
mfib_table_lock (mfib_index, FIB_PROTOCOL_IP4, MFIB_SOURCE_IGMP);
|
||||
mfib_table_entry_path_update (mfib_index,
|
||||
&mpfx_general_query,
|
||||
MFIB_SOURCE_IGMP,
|
||||
&for_us_path,
|
||||
MFIB_ITF_FLAG_FORWARD);
|
||||
MFIB_SOURCE_IGMP, &for_us_path);
|
||||
mfib_table_entry_path_update (mfib_index,
|
||||
&mpfx_report,
|
||||
MFIB_SOURCE_IGMP,
|
||||
&for_us_path,
|
||||
MFIB_ITF_FLAG_FORWARD);
|
||||
MFIB_SOURCE_IGMP, &for_us_path);
|
||||
}
|
||||
mfib_table_entry_path_update (mfib_index,
|
||||
&mpfx_general_query,
|
||||
MFIB_SOURCE_IGMP,
|
||||
&via_itf_path, MFIB_ITF_FLAG_ACCEPT);
|
||||
MFIB_SOURCE_IGMP, &via_itf_path);
|
||||
mfib_table_entry_path_update (mfib_index, &mpfx_report,
|
||||
MFIB_SOURCE_IGMP, &via_itf_path,
|
||||
MFIB_ITF_FLAG_ACCEPT);
|
||||
MFIB_SOURCE_IGMP, &via_itf_path);
|
||||
}
|
||||
}
|
||||
else if (config && !enable)
|
||||
@@ -438,6 +435,7 @@ igmp_enable_disable (u32 sw_if_index, u8 enable, igmp_mode_t mode)
|
||||
mfib_table_entry_path_remove (mfib_index,
|
||||
&mpfx_report,
|
||||
MFIB_SOURCE_IGMP, &for_us_path);
|
||||
mfib_table_unlock (mfib_index, FIB_PROTOCOL_IP4, MFIB_SOURCE_IGMP);
|
||||
}
|
||||
|
||||
mfib_table_entry_path_remove (mfib_index,
|
||||
@@ -482,7 +480,6 @@ igmp_init (vlib_main_t * vm)
|
||||
igmp_main_t *im = &igmp_main;
|
||||
|
||||
im->igmp_api_client_by_client_index = hash_create (0, sizeof (u32));
|
||||
|
||||
im->logger = vlib_log_register_class ("igmp", 0);
|
||||
|
||||
IGMP_DBG ("initialized");
|
||||
|
||||
@@ -49,13 +49,13 @@ igmp_proxy_device_mfib_path_add_del (igmp_group_t * group, u8 add)
|
||||
.frp_sw_if_index = config->sw_if_index,
|
||||
.frp_fib_index = 0,
|
||||
.frp_weight = 1,
|
||||
.frp_mitf_flags = MFIB_ITF_FLAG_FORWARD,
|
||||
};
|
||||
/* *INDENT-ON* */
|
||||
|
||||
if (add)
|
||||
mfib_table_entry_path_update (mfib_index, &mpfx_group_addr,
|
||||
MFIB_SOURCE_IGMP, &via_itf_path,
|
||||
MFIB_ITF_FLAG_FORWARD);
|
||||
MFIB_SOURCE_IGMP, &via_itf_path);
|
||||
else
|
||||
mfib_table_entry_path_remove (mfib_index, &mpfx_group_addr,
|
||||
MFIB_SOURCE_IGMP, &via_itf_path);
|
||||
|
||||
@@ -108,7 +108,7 @@ vl_api_l3xc_update_t_handler (vl_api_l3xc_update_t * mp)
|
||||
for (pi = 0; pi < mp->l3xc.n_paths; pi++)
|
||||
{
|
||||
path = &paths[pi];
|
||||
rv = fib_path_api_parse (&mp->l3xc.paths[pi], path);
|
||||
rv = fib_api_path_decode (&mp->l3xc.paths[pi], path);
|
||||
|
||||
if (0 != rv)
|
||||
{
|
||||
@@ -155,9 +155,12 @@ typedef struct l3xc_dump_walk_ctx_t_
|
||||
static int
|
||||
l3xc_send_details (u32 l3xci, void *args)
|
||||
{
|
||||
fib_route_path_encode_t *api_rpaths = NULL, *api_rpath;
|
||||
fib_path_encode_ctx_t path_ctx = {
|
||||
.rpaths = NULL,
|
||||
};
|
||||
vl_api_l3xc_details_t *mp;
|
||||
l3xc_dump_walk_ctx_t *ctx;
|
||||
fib_route_path_t *rpath;
|
||||
vl_api_fib_path_t *fp;
|
||||
size_t msg_size;
|
||||
l3xc_t *l3xc;
|
||||
@@ -177,13 +180,12 @@ l3xc_send_details (u32 l3xci, void *args)
|
||||
mp->l3xc.n_paths = n_paths;
|
||||
mp->l3xc.sw_if_index = htonl (l3xc->l3xc_sw_if_index);
|
||||
|
||||
fib_path_list_walk_w_ext (l3xc->l3xc_pl, NULL, fib_path_encode,
|
||||
&api_rpaths);
|
||||
fib_path_list_walk_w_ext (l3xc->l3xc_pl, NULL, fib_path_encode, &path_ctx);
|
||||
|
||||
fp = mp->l3xc.paths;
|
||||
vec_foreach (api_rpath, api_rpaths)
|
||||
vec_foreach (rpath, path_ctx.rpaths)
|
||||
{
|
||||
fib_api_path_encode (api_rpath, fp);
|
||||
fib_api_path_encode (rpath, fp);
|
||||
fp++;
|
||||
}
|
||||
|
||||
|
||||
@@ -770,12 +770,12 @@ bier_test_mpls_imp (void)
|
||||
.frp_bier_imp = bii,
|
||||
.frp_weight = 0,
|
||||
.frp_flags = FIB_ROUTE_PATH_BIER_IMP,
|
||||
.frp_mitf_flags = MFIB_ITF_FLAG_FORWARD,
|
||||
};
|
||||
mfib_table_entry_path_update(0, // default table
|
||||
&pfx_1_1_1_1_c_239_1_1_1 ,
|
||||
MFIB_SOURCE_API,
|
||||
&path_via_bier_imp_1,
|
||||
MFIB_ITF_FLAG_FORWARD);
|
||||
&path_via_bier_imp_1);
|
||||
mfib_table_entry_delete(0,
|
||||
&pfx_1_1_1_1_c_239_1_1_1 ,
|
||||
MFIB_SOURCE_API);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user