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:
Neale Ranns
2018-05-01 05:17:55 -07:00
committed by Ole Trøan
parent 39baa32186
commit 097fa66b98
133 changed files with 4883 additions and 5081 deletions
+71 -1
View File
@@ -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
+14 -1
View File
@@ -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
+2 -2
View File
@@ -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();
+26 -45
View File
@@ -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
+5 -37
View File
@@ -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
+1 -1
View File
@@ -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.
+4 -4
View File
@@ -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)
+5 -6
View File
@@ -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
View File
@@ -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&
+4 -9
View File
@@ -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
View File
File diff suppressed because it is too large Load Diff
+1 -3
View File
@@ -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.
+90 -80
View File
@@ -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:
*/
+5 -3
View File
@@ -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
+44 -60
View File
@@ -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:
*/
+14 -49
View File
@@ -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
+32
View File
@@ -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()
+9
View File
@@ -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
*/
+33 -4
View File
@@ -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
/*
+34
View File
@@ -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
+74
View File
@@ -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
+1
View File
@@ -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
+10 -5
View File
@@ -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);
}
+1
View File
@@ -17,3 +17,4 @@
abf_error (NONE, "no match")
abf_error (MATCHED, "matched")
abf_error (MISSED, "missed")
+10 -3
View File
@@ -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;
}
+5 -7
View File
@@ -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
View File
@@ -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");
+2 -2
View File
@@ -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);
+8 -6
View File
@@ -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++;
}
+2 -2
View File
@@ -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