summaryrefslogtreecommitdiffstats
path: root/extras
diff options
context:
space:
mode:
Diffstat (limited to 'extras')
-rw-r--r--extras/vom/vom/CMakeLists.txt2
-rw-r--r--extras/vom/vom/api_types.cpp54
-rw-r--r--extras/vom/vom/api_types.hpp7
-rw-r--r--extras/vom/vom/mroute_cmds.cpp193
-rw-r--r--extras/vom/vom/mroute_cmds.hpp181
-rw-r--r--extras/vom/vom/prefix.cpp131
-rw-r--r--extras/vom/vom/prefix.hpp118
-rw-r--r--extras/vom/vom/route.cpp345
-rw-r--r--extras/vom/vom/route.hpp194
-rw-r--r--extras/vom/vom/route_api_types.cpp119
-rw-r--r--extras/vom/vom/route_api_types.hpp35
-rw-r--r--extras/vom/vom/route_cmds.cpp44
12 files changed, 1306 insertions, 117 deletions
diff --git a/extras/vom/vom/CMakeLists.txt b/extras/vom/vom/CMakeLists.txt
index bd8986a4864..475672a001a 100644
--- a/extras/vom/vom/CMakeLists.txt
+++ b/extras/vom/vom/CMakeLists.txt
@@ -158,6 +158,7 @@ list(APPEND VOM_SOURCES
neighbour.cpp
neighbour_cmds.cpp
object_base.cpp
+ mroute_cmds.cpp
om.cpp
pipe.cpp
pipe_cmds.cpp
@@ -165,6 +166,7 @@ list(APPEND VOM_SOURCES
ra_config.cpp
ra_prefix.cpp
route.cpp
+ route_api_types.cpp
route_cmds.cpp
route_domain.cpp
route_domain_cmds.cpp
diff --git a/extras/vom/vom/api_types.cpp b/extras/vom/vom/api_types.cpp
index 53cd047332a..4a81a41daa9 100644
--- a/extras/vom/vom/api_types.cpp
+++ b/extras/vom/vom/api_types.cpp
@@ -28,6 +28,21 @@ to_api(const ip_address_t& a, vapi_type_address& v)
memcpy(v.un.ip6, a.to_v6().to_bytes().data(), 16);
}
}
+
+void
+to_api(const ip_address_t& a,
+ vapi_union_address_union& u,
+ vapi_enum_address_family& af)
+{
+ if (a.is_v4()) {
+ af = ADDRESS_IP4;
+ memcpy(u.ip4, a.to_v4().to_bytes().data(), 4);
+ } else {
+ af = ADDRESS_IP6;
+ memcpy(u.ip6, a.to_v6().to_bytes().data(), 16);
+ }
+}
+
void
to_api(const boost::asio::ip::address& a, vapi_type_ip4_address& v)
{
@@ -54,6 +69,26 @@ from_api(const vapi_type_address& v)
return addr;
}
+ip_address_t
+from_api(const vapi_union_address_union& u, vapi_enum_address_family af)
+{
+ boost::asio::ip::address addr;
+
+ if (ADDRESS_IP6 == af) {
+ 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 {
+ 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;
+}
+
void
to_api(const mac_address_t& a, vapi_type_mac_address& v)
{
@@ -80,6 +115,25 @@ to_api(const route::prefix_t& p)
v.address_length = p.mask_width();
return v;
}
+
+route::mprefix_t
+from_api(const vapi_type_mprefix& v)
+{
+ return route::mprefix_t(from_api(v.src_address, v.af),
+ from_api(v.grp_address, v.af), v.grp_address_length);
+}
+
+vapi_type_mprefix
+to_api(const route::mprefix_t& p)
+{
+ vapi_enum_address_family af;
+ vapi_type_mprefix v;
+ to_api(p.grp_address(), v.grp_address, af);
+ to_api(p.src_address(), v.src_address, af);
+ v.grp_address_length = p.mask_width();
+ v.af = af;
+ return v;
+}
};
/*
diff --git a/extras/vom/vom/api_types.hpp b/extras/vom/vom/api_types.hpp
index 784ace2c293..5856c22d339 100644
--- a/extras/vom/vom/api_types.hpp
+++ b/extras/vom/vom/api_types.hpp
@@ -25,17 +25,24 @@ typedef boost::asio::ip::address ip_address_t;
void to_api(const ip_address_t& a, vapi_type_address& v);
void to_api(const boost::asio::ip::address& a, vapi_type_ip4_address& v);
+void to_api(const boost::asio::ip::address& a,
+ vapi_union_address_union& u,
+ vapi_enum_address_family& af);
ip_address_t from_api(const vapi_type_address& v);
ip_address_t from_api(const vapi_type_ip4_address& v);
+ip_address_t from_api(const vapi_union_address_union& u,
+ vapi_enum_address_family af);
void to_api(const mac_address_t& a, vapi_type_mac_address& m);
mac_address_t from_api(const vapi_type_mac_address& v);
route::prefix_t from_api(const vapi_type_prefix&);
+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&);
};
/*
diff --git a/extras/vom/vom/mroute_cmds.cpp b/extras/vom/vom/mroute_cmds.cpp
new file mode 100644
index 00000000000..e4df00a6ddd
--- /dev/null
+++ b/extras/vom/vom/mroute_cmds.cpp
@@ -0,0 +1,193 @@
+/*
+ * 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 <sstream>
+
+#include "vom/api_types.hpp"
+#include "vom/mroute_cmds.hpp"
+#include "vom/route_api_types.hpp"
+
+namespace VOM {
+namespace route {
+namespace ip_mroute_cmds {
+
+update_cmd::update_cmd(HW::item<bool>& item,
+ table_id_t id,
+ const mprefix_t& mprefix,
+ const path& path,
+ const itf_flags_t& flags)
+ : rpc_cmd(item)
+ , m_id(id)
+ , m_mprefix(mprefix)
+ , m_path(path)
+ , m_flags(flags)
+{
+}
+
+bool
+update_cmd::operator==(const update_cmd& other) const
+{
+ return ((m_mprefix == other.m_mprefix) && (m_id == other.m_id));
+}
+
+rc_t
+update_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.is_add = 1;
+
+ m_mprefix.to_vpp(&payload.is_ipv6, payload.grp_address, payload.src_address,
+ &payload.grp_address_length);
+
+ to_vpp(m_path, payload);
+ payload.itf_flags = m_flags.value();
+
+ VAPI_CALL(req.execute());
+
+ return (wait());
+}
+
+std::string
+update_cmd::to_string() const
+{
+ std::ostringstream s;
+ s << "ip-mroute-create: " << m_hw_item.to_string() << " table-id:" << m_id
+ << " mprefix:" << m_mprefix.to_string() << " path:" << m_path.to_string()
+ << " flags:" << m_flags;
+
+ return (s.str());
+}
+
+delete_cmd::delete_cmd(HW::item<bool>& item,
+ table_id_t id,
+ const mprefix_t& mprefix,
+ const path& path,
+ const itf_flags_t& flags)
+ : rpc_cmd(item)
+ , m_id(id)
+ , m_mprefix(mprefix)
+ , m_path(path)
+ , m_flags(flags)
+{
+}
+
+bool
+delete_cmd::operator==(const delete_cmd& other) const
+{
+ return ((m_mprefix == other.m_mprefix) && (m_id == other.m_id));
+}
+
+rc_t
+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.is_add = 0;
+
+ m_mprefix.to_vpp(&payload.is_ipv6, payload.grp_address, payload.src_address,
+ &payload.grp_address_length);
+
+ to_vpp(m_path, payload);
+ payload.itf_flags = m_flags.value();
+
+ VAPI_CALL(req.execute());
+
+ wait();
+ m_hw_item.set(rc_t::NOOP);
+
+ return rc_t::OK;
+}
+
+std::string
+delete_cmd::to_string() const
+{
+ std::ostringstream s;
+ s << "ip-mroute-delete: " << m_hw_item.to_string() << " id:" << m_id
+ << " mprefix:" << m_mprefix.to_string();
+
+ return (s.str());
+}
+
+dump_v4_cmd::dump_v4_cmd()
+{
+}
+
+bool
+dump_v4_cmd::operator==(const dump_v4_cmd& other) const
+{
+ return (true);
+}
+
+rc_t
+dump_v4_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_v4_cmd::to_string() const
+{
+ return ("ip-mroute-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-mroute-v6-dump");
+}
+} // namespace ip_mroute_cmds
+} // namespace mroute
+} // namespace vom
+ /*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "mozilla")
+ * End:
+ */
diff --git a/extras/vom/vom/mroute_cmds.hpp b/extras/vom/vom/mroute_cmds.hpp
new file mode 100644
index 00000000000..b8f18f6b45b
--- /dev/null
+++ b/extras/vom/vom/mroute_cmds.hpp
@@ -0,0 +1,181 @@
+/*
+ * 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_MROUTE_CMDS_H__
+#define __VOM_MROUTE_CMDS_H__
+
+#include "vom/dump_cmd.hpp"
+#include "vom/route.hpp"
+#include "vom/rpc_cmd.hpp"
+
+#include <vapi/ip.api.vapi.hpp>
+
+namespace VOM {
+namespace route {
+namespace ip_mroute_cmds {
+
+/**
+ * A command class that creates or updates the route
+ */
+class update_cmd : public rpc_cmd<HW::item<bool>, vapi::Ip_mroute_add_del>
+{
+public:
+ /**
+ * Constructor
+ */
+ update_cmd(HW::item<bool>& item,
+ table_id_t id,
+ const mprefix_t& mprefix,
+ const path& path,
+ const itf_flags_t& flags);
+
+ /**
+ * 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 update_cmd& i) const;
+
+private:
+ route::table_id_t m_id;
+ mprefix_t m_mprefix;
+ const path m_path;
+ const itf_flags_t& m_flags;
+};
+
+/**
+ * A cmd class that deletes a route
+ */
+class delete_cmd : public rpc_cmd<HW::item<bool>, vapi::Ip_mroute_add_del>
+{
+public:
+ /**
+ * Constructor
+ */
+ delete_cmd(HW::item<bool>& item,
+ table_id_t id,
+ const mprefix_t& mprefix,
+ const path& path,
+ const itf_flags_t& flags);
+
+ /**
+ * 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:
+ route::table_id_t m_id;
+ mprefix_t m_mprefix;
+ const path m_path;
+ const itf_flags_t& m_flags;
+};
+
+/**
+ * A cmd class that Dumps ipv4 fib
+ */
+class dump_v4_cmd : public VOM::dump_cmd<vapi::Ip_mfib_dump>
+{
+public:
+ /**
+ * Constructor
+ */
+ dump_v4_cmd();
+ dump_v4_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_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;
+
+private:
+ /**
+ * HW reutrn code
+ */
+ HW::item<bool> item;
+};
+
+}; // namespace ip_mroute_cmds
+}; // namespace route
+}; // namespace VOM
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "mozilla")
+ * End:
+ */
+
+#endif
diff --git a/extras/vom/vom/prefix.cpp b/extras/vom/vom/prefix.cpp
index abd589eef9f..fdad67998d1 100644
--- a/extras/vom/vom/prefix.cpp
+++ b/extras/vom/vom/prefix.cpp
@@ -190,7 +190,7 @@ route::prefix_t::to_string() const
}
boost::asio::ip::address
-from_bytes(uint8_t is_ip6, uint8_t* bytes)
+from_bytes(uint8_t is_ip6, const uint8_t* bytes)
{
boost::asio::ip::address addr;
@@ -420,6 +420,135 @@ route::prefix_t::high() const
return (pfx);
}
+/**
+ * The all Zeros prefix
+ */
+const route::mprefix_t route::mprefix_t::ZERO;
+const route::mprefix_t route::mprefix_t::ZEROv6;
+
+route::mprefix_t::mprefix_t(const boost::asio::ip::address& gaddr, uint8_t len)
+ : m_gaddr(gaddr)
+ , m_saddr()
+ , m_len(len)
+{
+}
+
+route::mprefix_t::mprefix_t(const boost::asio::ip::address& gaddr)
+ : m_gaddr(gaddr)
+ , m_saddr()
+ , m_len(VOM::mask_width(gaddr))
+{
+}
+
+route::mprefix_t::mprefix_t(const boost::asio::ip::address& saddr,
+ const boost::asio::ip::address& gaddr)
+ : m_gaddr(gaddr)
+ , m_saddr(saddr)
+ , m_len(2 * VOM::mask_width(gaddr))
+{
+}
+
+route::mprefix_t::mprefix_t(const boost::asio::ip::address& saddr,
+ const boost::asio::ip::address& gaddr,
+ uint16_t len)
+ : m_gaddr(gaddr)
+ , m_saddr(saddr)
+ , m_len(len)
+{
+}
+
+route::mprefix_t::mprefix_t(const mprefix_t& o)
+ : m_gaddr(o.m_gaddr)
+ , m_saddr(o.m_saddr)
+ , m_len(o.m_len)
+{
+}
+route::mprefix_t::mprefix_t()
+ : m_gaddr()
+ , m_saddr()
+ , m_len(0)
+{
+}
+
+route::mprefix_t::~mprefix_t()
+{
+}
+
+const boost::asio::ip::address&
+route::mprefix_t::grp_address() const
+{
+ return (m_gaddr);
+}
+
+const boost::asio::ip::address&
+route::mprefix_t::src_address() const
+{
+ return (m_saddr);
+}
+
+uint8_t
+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
+{
+ *len = m_len;
+ to_bytes(m_saddr, is_ip6, saddr);
+ to_bytes(m_gaddr, is_ip6, gaddr);
+}
+
+route::mprefix_t&
+route::mprefix_t::operator=(const route::mprefix_t& o)
+{
+ m_gaddr = o.m_gaddr;
+ m_saddr = o.m_saddr;
+ m_len = o.m_len;
+
+ return (*this);
+}
+
+bool
+route::mprefix_t::operator<(const route::mprefix_t& o) const
+{
+ if (m_len == o.m_len) {
+ if (m_saddr == o.m_saddr)
+ return (m_gaddr < o.m_gaddr);
+ else
+ return (m_saddr < o.m_saddr);
+ } else {
+ return (m_len < o.m_len);
+ }
+}
+
+bool
+route::mprefix_t::operator==(const route::mprefix_t& o) const
+{
+ return (m_len == o.m_len && m_gaddr == o.m_gaddr && m_saddr == o.m_saddr);
+}
+
+bool
+route::mprefix_t::operator!=(const route::mprefix_t& o) const
+{
+ return (!(*this == o));
+}
+
+std::string
+route::mprefix_t::to_string() const
+{
+ std::ostringstream s;
+
+ s << "(" << m_saddr.to_string() << "," << m_gaddr.to_string() << "/"
+ << std::to_string(m_len) << ")";
+
+ return (s.str());
+}
+
}; // namespace VOM
/*
diff --git a/extras/vom/vom/prefix.hpp b/extras/vom/vom/prefix.hpp
index 836554123f5..1b6a06874d3 100644
--- a/extras/vom/vom/prefix.hpp
+++ b/extras/vom/vom/prefix.hpp
@@ -171,8 +171,8 @@ public:
const static prefix_t ZEROv6;
/**
- * Convert the prefix into VPP API parameters
- */
+ * Convert the prefix into VPP API parameters
+ */
void to_vpp(uint8_t* is_ip6, uint8_t* addr, uint8_t* len) const;
/**
@@ -206,8 +206,120 @@ private:
*/
uint8_t m_len;
};
+
+/**
+* A prefix defintion. Address + length
+*/
+class mprefix_t
+{
+public:
+ /**
+ * Default Constructor - creates ::/0
+ */
+ mprefix_t();
+ /**
+ * Constructor for (S,G)
+ */
+ mprefix_t(const boost::asio::ip::address& saddr,
+ const boost::asio::ip::address& gaddr);
+ /*
+ * Constructor for (*,G)
+ */
+ mprefix_t(const boost::asio::ip::address& gaddr);
+
+ /*
+ * Constructor for (*,G/n)
+ */
+ mprefix_t(const boost::asio::ip::address& gaddr, uint8_t len);
+
+ /**
+*Constructor for (S,G)
+*/
+ mprefix_t(const boost::asio::ip::address& saddr,
+ const boost::asio::ip::address& gaddr,
+ uint16_t len);
+
+ /**
+ * Copy Constructor
+ */
+ mprefix_t(const mprefix_t&);
+
+ /**
+ * Destructor
+ */
+ ~mprefix_t();
+
+ /**
+ * Get the address
+ */
+ const boost::asio::ip::address& grp_address() const;
+ const boost::asio::ip::address& src_address() const;
+
+ /**
+ * Get the network mask width
+ */
+ uint8_t mask_width() const;
+
+ /**
+ * Assignement
+ */
+ mprefix_t& operator=(const mprefix_t&);
+
+ /**
+ * Less than operator
+ */
+ bool operator<(const mprefix_t& o) const;
+
+ /**
+ * equals operator
+ */
+ bool operator==(const mprefix_t& o) const;
+
+ /**
+ * not equal opartor
+ */
+ bool operator!=(const mprefix_t& o) const;
+
+ /**
+ * convert to string format for debug purposes
+ */
+ std::string to_string() const;
+
+ /**
+ * The all Zeros prefix
+ */
+ const static mprefix_t ZERO;
+
+ /**
+ * The all Zeros v6 prefix
+ */
+ const static mprefix_t ZEROv6;
+
+ /**
+ * Get the L3 protocol
+ */
+ 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
+ */
+ boost::asio::ip::address m_gaddr;
+ boost::asio::ip::address m_saddr;
+
+ /**
+ * The prefix length
+ */
+ uint8_t m_len;
};
+}; // namespace route
+
boost::asio::ip::address_v4 operator|(const boost::asio::ip::address_v4& addr1,
const boost::asio::ip::address_v4& addr2);
@@ -254,7 +366,7 @@ uint32_t mask_width(const boost::asio::ip::address& addr);
/**
* Convert a VPP byte stinrg into a boost addresss
*/
-boost::asio::ip::address from_bytes(uint8_t is_ip6, uint8_t* array);
+boost::asio::ip::address from_bytes(uint8_t is_ip6, const uint8_t* array);
};
/*
diff --git a/extras/vom/vom/route.cpp b/extras/vom/vom/route.cpp
index ec56c44a0d7..c713de9ee99 100644
--- a/extras/vom/vom/route.cpp
+++ b/extras/vom/vom/route.cpp
@@ -14,19 +14,24 @@
*/
#include "vom/route.hpp"
+#include "vom/api_types.hpp"
+#include "vom/mroute_cmds.hpp"
+#include "vom/route_api_types.hpp"
#include "vom/route_cmds.hpp"
#include "vom/singular_db_funcs.hpp"
namespace VOM {
namespace route {
ip_route::event_handler ip_route::m_evh;
+ip_mroute::event_handler ip_mroute::m_evh;
singular_db<ip_route::key_t, ip_route> ip_route::m_db;
+singular_db<ip_mroute::key_t, ip_mroute> ip_mroute::m_db;
const path::special_t path::special_t::STANDARD(0, "standard");
-const path::special_t path::special_t::LOCAL(0, "local");
-const path::special_t path::special_t::DROP(0, "standard");
-const path::special_t path::special_t::UNREACH(0, "unreachable");
-const path::special_t path::special_t::PROHIBIT(0, "prohibit");
+const path::special_t path::special_t::LOCAL(1, "local");
+const path::special_t path::special_t::DROP(2, "standard");
+const path::special_t path::special_t::UNREACH(3, "unreachable");
+const path::special_t path::special_t::PROHIBIT(4, "prohibit");
path::special_t::special_t(int v, const std::string& s)
: enum_base<path::special_t>(v, s)
@@ -41,6 +46,23 @@ path::flags_t::flags_t(int v, const std::string& s)
{
}
+const itf_flags_t itf_flags_t::NONE(0, "none");
+const itf_flags_t itf_flags_t::ACCEPT((1 << 2), "accept");
+const itf_flags_t itf_flags_t::FORWARD((1 << 3), "forward");
+
+itf_flags_t::itf_flags_t(int v, const std::string& s)
+ : enum_base<itf_flags_t>(v, s)
+{
+}
+const itf_flags_t&
+itf_flags_t::from_vpp(uint32_t val)
+{
+ if (itf_flags_t::ACCEPT == (int)val)
+ return itf_flags_t::ACCEPT;
+ else
+ return itf_flags_t::FORWARD;
+}
+
path::path(special_t special)
: m_type(special)
, m_nh_proto(nh_proto_t::IPV4)
@@ -124,16 +146,24 @@ path::operator<(const path& p) const
return false;
if (!m_rd && p.m_rd)
return true;
- if (m_rd->table_id() < p.m_rd->table_id())
- return true;
+ if (m_rd && p.m_rd) {
+ if (m_rd->table_id() < p.m_rd->table_id())
+ return true;
+ else if (m_rd->table_id() > p.m_rd->table_id())
+ return false;
+ }
if (m_nh < p.m_nh)
return true;
if (m_interface && !p.m_interface)
return false;
if (!m_interface && p.m_interface)
return true;
- if (m_interface->handle() < p.m_interface->handle())
- return true;
+ if (m_interface && p.m_interface) {
+ if (m_interface->handle() < p.m_interface->handle())
+ return true;
+ if (p.m_interface->handle() < m_interface->handle())
+ return false;
+ }
return (false);
}
@@ -410,36 +440,7 @@ ip_route::event_handler::handle_populate(const client_db::key_t& key)
ip_route ip_r(rd_temp, pfx);
for (unsigned int i = 0; i < payload.count; i++) {
- vapi_type_fib_path p = payload.path[i];
- if (p.is_local) {
- path path_v4(path::special_t::LOCAL);
- ip_r.add(path_v4);
- } else if (p.is_drop) {
- path path_v4(path::special_t::DROP);
- ip_r.add(path_v4);
- } else if (p.is_unreach) {
- path path_v4(path::special_t::UNREACH);
- ip_r.add(path_v4);
- } else if (p.is_prohibit) {
- path path_v4(path::special_t::PROHIBIT);
- ip_r.add(path_v4);
- } else {
- boost::asio::ip::address address = from_bytes(0, p.next_hop);
- std::shared_ptr<interface> itf = interface::find(p.sw_if_index);
- if (itf) {
- if (p.is_dvr) {
- path path_v4(*itf, nh_proto_t::IPV4, route::path::flags_t::DVR,
- p.weight, p.preference);
- ip_r.add(path_v4);
- } else {
- path path_v4(address, *itf, p.weight, p.preference);
- ip_r.add(path_v4);
- }
- } else {
- path path_v4(rd_temp, address, p.weight, p.preference);
- ip_r.add(path_v4);
- }
- }
+ ip_r.add(from_vpp(payload.path[i], nh_proto_t::IPV4));
}
VOM_LOG(log_level_t::DEBUG) << "ip-route-dump: " << ip_r.to_string();
@@ -463,36 +464,7 @@ ip_route::event_handler::handle_populate(const client_db::key_t& key)
ip_route ip_r(rd_temp, pfx);
for (unsigned int i = 0; i < payload.count; i++) {
- vapi_type_fib_path p = payload.path[i];
- if (p.is_local) {
- path path_v6(path::special_t::LOCAL);
- ip_r.add(path_v6);
- } else if (p.is_drop) {
- path path_v6(path::special_t::DROP);
- ip_r.add(path_v6);
- } else if (p.is_unreach) {
- path path_v6(path::special_t::UNREACH);
- ip_r.add(path_v6);
- } else if (p.is_prohibit) {
- path path_v6(path::special_t::PROHIBIT);
- ip_r.add(path_v6);
- } else {
- std::shared_ptr<interface> itf = interface::find(p.sw_if_index);
- boost::asio::ip::address address = from_bytes(1, p.next_hop);
- if (itf) {
- if (p.is_dvr) {
- path path_v6(*itf, nh_proto_t::IPV6, route::path::flags_t::DVR,
- p.weight, p.preference);
- ip_r.add(path_v6);
- } else {
- path path_v6(address, *itf, p.weight, p.preference);
- ip_r.add(path_v6);
- }
- } else {
- path path_v6(rd_temp, address, p.weight, p.preference);
- ip_r.add(path_v6);
- }
- }
+ ip_r.add(from_vpp(payload.path[i], nh_proto_t::IPV6));
}
VOM_LOG(log_level_t::DEBUG) << "ip-route-dump: " << ip_r.to_string();
@@ -517,6 +489,219 @@ ip_route::event_handler::show(std::ostream& os)
db_dump(m_db, os);
}
+ip_mroute::ip_mroute(const mprefix_t& mprefix)
+ : m_hw(false)
+ , m_rd(route_domain::get_default())
+ , m_mprefix(mprefix)
+ , m_paths()
+{
+}
+
+ip_mroute::ip_mroute(const ip_mroute& r)
+ : m_hw(r.m_hw)
+ , m_rd(r.m_rd)
+ , m_mprefix(r.m_mprefix)
+ , m_paths(r.m_paths)
+{
+}
+
+ip_mroute::ip_mroute(const route_domain& rd, const mprefix_t& mprefix)
+ : m_hw(false)
+ , m_rd(rd.singular())
+ , m_mprefix(mprefix)
+ , m_paths()
+{
+}
+
+void
+ip_mroute::add(const path& path, const itf_flags_t& flag)
+{
+ m_paths.insert(std::make_pair(path, flag));
+}
+
+ip_mroute::~ip_mroute()
+{
+ sweep();
+ m_db.release(key(), this);
+}
+
+const ip_mroute::key_t
+ip_mroute::key() const
+{
+ return (std::make_pair(m_rd->table_id(), m_mprefix));
+}
+
+bool
+ip_mroute::operator==(const ip_mroute& i) const
+{
+ return ((key() == i.key()) && (m_paths == i.m_paths));
+}
+
+void
+ip_mroute::sweep()
+{
+ if (m_hw) {
+ for (auto& p : m_paths)
+ HW::enqueue(new ip_mroute_cmds::delete_cmd(m_hw, m_rd->table_id(),
+ m_mprefix, p.first, p.second));
+ }
+ HW::write();
+}
+
+void
+ip_mroute::replay()
+{
+ if (m_hw) {
+ for (auto& p : m_paths)
+ HW::enqueue(new ip_mroute_cmds::update_cmd(m_hw, m_rd->table_id(),
+ m_mprefix, p.first, p.second));
+ }
+}
+std::string
+ip_mroute::to_string() const
+{
+ std::ostringstream s;
+ s << "route:[" << m_rd->to_string() << ", " << m_mprefix.to_string() << " ["
+ << m_paths << "]"
+ << "]";
+
+ return (s.str());
+}
+
+void
+ip_mroute::update(const ip_mroute& r)
+{
+ if (rc_t::OK != m_hw.rc()) {
+ for (auto& p : m_paths)
+ HW::enqueue(new ip_mroute_cmds::update_cmd(m_hw, m_rd->table_id(),
+ m_mprefix, p.first, p.second));
+ }
+}
+
+std::shared_ptr<ip_mroute>
+ip_mroute::find_or_add(const ip_mroute& temp)
+{
+ return (m_db.find_or_add(temp.key(), temp));
+}
+
+std::shared_ptr<ip_mroute>
+ip_mroute::find(const key_t& k)
+{
+ return (m_db.find(k));
+}
+
+std::shared_ptr<ip_mroute>
+ip_mroute::singular() const
+{
+ return find_or_add(*this);
+}
+
+void
+ip_mroute::dump(std::ostream& os)
+{
+ db_dump(m_db, os);
+}
+
+ip_mroute::event_handler::event_handler()
+{
+ OM::register_listener(this);
+ inspect::register_handler({ "ip-route" }, "ip route configurations", this);
+}
+
+void
+ip_mroute::event_handler::handle_replay()
+{
+ m_db.replay();
+}
+
+void
+ip_mroute::event_handler::handle_populate(const client_db::key_t& key)
+{
+ std::shared_ptr<ip_mroute_cmds::dump_v4_cmd> cmd_v4 =
+ std::make_shared<ip_mroute_cmds::dump_v4_cmd>();
+ std::shared_ptr<ip_mroute_cmds::dump_v6_cmd> cmd_v6 =
+ std::make_shared<ip_mroute_cmds::dump_v6_cmd>();
+
+ HW::enqueue(cmd_v4);
+ HW::enqueue(cmd_v6);
+ HW::write();
+
+ VOM_LOG(log_level_t::INFO) << "ip-mroute-dump: ";
+
+ for (auto& record : *cmd_v4) {
+ auto& payload = record.get_payload();
+
+ ip_address_t gaddr = from_bytes(0, payload.grp_address);
+ ip_address_t saddr = from_bytes(0, payload.src_address);
+ mprefix_t pfx(saddr, gaddr, payload.address_length);
+
+ /**
+ * populating the route domain here
+ */
+ route_domain rd_temp(payload.table_id);
+ std::shared_ptr<route_domain> rd = route_domain::find(payload.table_id);
+ if (!rd) {
+ OM::commit(key, rd_temp);
+ }
+ ip_mroute ip_r(rd_temp, pfx);
+
+ for (unsigned int i = 0; i < payload.count; i++) {
+ vapi_type_mfib_path& p = payload.path[i];
+ ip_r.add(from_vpp(p.path, nh_proto_t::IPV4),
+ itf_flags_t::from_vpp(p.itf_flags));
+ }
+ VOM_LOG(log_level_t::INFO) << "ip-mroute-dump: " << ip_r.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, ip_r);
+ }
+
+ for (auto& record : *cmd_v6) {
+ auto& payload = record.get_payload();
+
+ ip_address_t gaddr = from_bytes(1, payload.grp_address);
+ ip_address_t saddr = from_bytes(1, payload.src_address);
+ mprefix_t pfx(saddr, gaddr, payload.address_length);
+
+ route_domain rd_temp(payload.table_id);
+ std::shared_ptr<route_domain> rd = route_domain::find(payload.table_id);
+ if (!rd) {
+ OM::commit(key, rd_temp);
+ }
+ ip_mroute ip_r(rd_temp, pfx);
+
+ for (unsigned int i = 0; i < payload.count; i++) {
+ vapi_type_mfib_path& p = payload.path[i];
+ ip_r.add(from_vpp(p.path, nh_proto_t::IPV6),
+ itf_flags_t::from_vpp(p.itf_flags));
+ }
+ VOM_LOG(log_level_t::INFO) << "ip-mroute-dump: " << ip_r.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, ip_r);
+ }
+}
+
+dependency_t
+ip_mroute::event_handler::order() const
+{
+ return (dependency_t::TABLE);
+}
+
+void
+ip_mroute::event_handler::show(std::ostream& os)
+{
+ db_dump(m_db, os);
+}
+
std::ostream&
operator<<(std::ostream& os, const ip_route::key_t& key)
{
@@ -526,6 +711,14 @@ operator<<(std::ostream& os, const ip_route::key_t& key)
}
std::ostream&
+operator<<(std::ostream& os, const ip_mroute::key_t& key)
+{
+ os << "[" << key.first << ", " << key.second.to_string() << "]";
+
+ return (os);
+}
+
+std::ostream&
operator<<(std::ostream& os, const path_list_t& key)
{
os << "[";
@@ -536,8 +729,22 @@ operator<<(std::ostream& os, const path_list_t& key)
return (os);
}
+
+std::ostream&
+operator<<(std::ostream& os, const mpath_list_t& key)
+{
+ os << "[";
+ for (auto k : key) {
+ os << "[" << k.first.to_string() << ", " << k.second.to_string() << "]";
+ }
+ os << "]";
+
+ return (os);
}
-}
+
+}; // namespace route
+}; // namespace VOM
+
/*
* fd.io coding-style-patch-verification: ON
*
diff --git a/extras/vom/vom/route.hpp b/extras/vom/vom/route.hpp
index 65797b7c2f9..a09f704f60c 100644
--- a/extras/vom/vom/route.hpp
+++ b/extras/vom/vom/route.hpp
@@ -204,15 +204,44 @@ private:
uint8_t m_preference;
};
+class itf_flags_t : public enum_base<itf_flags_t>
+{
+public:
+ const static itf_flags_t NONE;
+ /**
+ * Path is accepting multicast traffic
+ */
+ const static itf_flags_t ACCEPT;
+
+ /**
+ * A local/for-us/recieve
+ */
+ 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
+ */
+ itf_flags_t(int v, const std::string& s);
+};
+
/**
* A path-list is a set of paths
*/
typedef std::set<path> path_list_t;
/**
+ * A mpath-list is a set of paths and interface flags
+ */
+typedef std::set<std::pair<path, itf_flags_t>> mpath_list_t;
+
+/**
* ostream output for iterator
*/
std::ostream& operator<<(std::ostream& os, const path_list_t& path_list);
+std::ostream& operator<<(std::ostream& os, const mpath_list_t& path_list);
/**
* A IP route
@@ -392,10 +421,171 @@ private:
static singular_db<key_t, ip_route> m_db;
};
-std::ostream& operator<<(std::ostream& os, const ip_route::key_t& key);
-};
+/**
+ * A IP multicast route
+ */
+class ip_mroute : public object_base
+{
+public:
+ /**
+ * The key for a route
+ */
+ typedef std::pair<route::table_id_t, mprefix_t> key_t;
+
+ /**
+ * Construct a route in the default table
+ */
+ ip_mroute(const mprefix_t& mprefix);
+
+ /**
+ * Copy Construct
+ */
+ ip_mroute(const ip_mroute& r);
+
+ /**
+ * Construct a route in the given route domain
+ */
+ ip_mroute(const route_domain& rd, const mprefix_t& mprefix);
+
+ /**
+ * Destructor
+ */
+ ~ip_mroute();
+
+ /**
+ * Get the route's key
+ */
+ const key_t key() const;
+
+ /**
+ * Comparison operator
+ */
+ bool operator==(const ip_mroute& i) const;
+
+ /**
+ * Return the matching 'singular instance'
+ */
+ std::shared_ptr<ip_mroute> singular() const;
+
+ /**
+ * Find the instnace of the route domain in the OM
+ */
+ static std::shared_ptr<ip_mroute> find(const ip_mroute& temp);
+
+ /**
+ * Dump all route-doamin into the stream provided
+ */
+ static void dump(std::ostream& os);
+
+ /**
+ * replay the object to create it in hardware
+ */
+ void replay(void);
+
+ /**
+ * Convert to string for debugging
+ */
+ std::string to_string() const;
+
+ /**
+ * Return the matching 'singular instance'
+ */
+ static std::shared_ptr<ip_mroute> find(const key_t& k);
+
+ void add(const path& path, const itf_flags_t& flag);
+
+private:
+ /**
+ * Class definition for listeners to OM events
+ */
+ class event_handler : public OM::listener, public inspect::command_handler
+ {
+ public:
+ event_handler();
+ virtual ~event_handler() = default;
+
+ /**
+ * Handle a populate event
+ */
+ void handle_populate(const client_db::key_t& key);
+
+ /**
+ * Handle a replay event
+ */
+ void handle_replay();
+
+ /**
+ * Show the object in the Singular DB
+ */
+ void show(std::ostream& os);
+
+ /**
+ * Get the sortable Id of the listener
+ */
+ dependency_t order() const;
+ };
+
+ /**
+ * event_handler to register with OM
+ */
+ static event_handler m_evh;
+
+ /**
+ * Find or add the instnace of the route domain in the OM
+ */
+ static std::shared_ptr<ip_mroute> find_or_add(const ip_mroute& temp);
+
+ /*
+ * It's the OM class that updates the objects in HW
+ */
+ friend class VOM::OM;
+
+ /**
+ * It's the singular_db class that calls replay()
+ */
+ friend class singular_db<key_t, ip_mroute>;
+
+ /**
+ * Commit the acculmulated changes into VPP. i.e. to a 'HW" write.
+ */
+ void update(const ip_mroute& obj);
+
+ /**
+ * Sweep/reap the object if still stale
+ */
+ void sweep(void);
+
+ /**
+ * HW configuration for the result of creating the route
+ */
+ HW::item<bool> m_hw;
+
+ /**
+ * The route domain the route is in.
+ */
+ std::shared_ptr<route_domain> m_rd;
+
+ /**
+ * The mprefix to match
+ */
+ mprefix_t m_mprefix;
+
+ /**
+ * The set of paths
+ */
+ mpath_list_t m_paths;
+
+ /**
+ * A map of all routes
+ */
+ static singular_db<key_t, ip_mroute> m_db;
};
+std::ostream& operator<<(std::ostream& os, const ip_route::key_t& key);
+std::ostream& operator<<(std::ostream& os, const ip_mroute::key_t& key);
+}; // namespace route
+}; // namesapce VPP
+
/*
* fd.io coding-style-patch-verification: ON
*
diff --git a/extras/vom/vom/route_api_types.cpp b/extras/vom/vom/route_api_types.cpp
new file mode 100644
index 00000000000..85fca05b35a
--- /dev/null
+++ b/extras/vom/vom/route_api_types.cpp
@@ -0,0 +1,119 @@
+/*
+ * 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/route.hpp>
+#include <vom/route_api_types.hpp>
+
+namespace VOM {
+
+void
+to_vpp(const route::path& p, vapi_payload_ip_add_del_route& payload)
+{
+ payload.is_drop = 0;
+ payload.is_unreach = 0;
+ payload.is_prohibit = 0;
+ payload.is_local = 0;
+ payload.is_classify = 0;
+ payload.is_multipath = 0;
+ payload.is_resolve_host = 0;
+ payload.is_resolve_attached = 0;
+
+ if (route::path::flags_t::DVR & p.flags()) {
+ payload.is_dvr = 1;
+ }
+
+ if (route::path::special_t::STANDARD == p.type()) {
+ uint8_t path_v6;
+ to_bytes(p.nh(), &path_v6, payload.next_hop_address);
+
+ 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 = 0;
+ payload.classify_table_index = 0;
+}
+
+void
+to_vpp(const route::path& p, vapi_payload_ip_mroute_add_del& payload)
+{
+ if (route::path::special_t::STANDARD == p.type()) {
+ uint8_t path_v6;
+ to_bytes(p.nh(), &path_v6, payload.nh_address);
+
+ if (p.itf()) {
+ payload.next_hop_sw_if_index = p.itf()->handle().value();
+ }
+
+ payload.next_hop_afi = p.nh_proto();
+ }
+}
+
+route::path
+from_vpp(const vapi_type_fib_path& p, const nh_proto_t& nhp)
+{
+ 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);
+ } 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);
+ }
+ }
+ }
+
+ VOM_LOG(log_level_t::ERROR) << "cannot decode: ";
+
+ return route::path(route::path::special_t::DROP);
+}
+};
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "mozilla")
+ * End:
+ */
diff --git a/extras/vom/vom/route_api_types.hpp b/extras/vom/vom/route_api_types.hpp
new file mode 100644
index 00000000000..09015485cdb
--- /dev/null
+++ b/extras/vom/vom/route_api_types.hpp
@@ -0,0 +1,35 @@
+/*
+ * 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/route.hpp>
+
+#include <vapi/ip.api.vapi.hpp>
+
+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);
+
+route::path from_vpp(const vapi_type_fib_path& p, const nh_proto_t& nh);
+
+}; // namespace VOM
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "mozilla")
+ * End:
+ */
diff --git a/extras/vom/vom/route_cmds.cpp b/extras/vom/vom/route_cmds.cpp
index 240592f909f..26d6593df78 100644
--- a/extras/vom/vom/route_cmds.cpp
+++ b/extras/vom/vom/route_cmds.cpp
@@ -15,53 +15,13 @@
#include <sstream>
-#include "vom/route_cmds.hpp"
+#include <vom/route_api_types.hpp>
+#include <vom/route_cmds.hpp>
namespace VOM {
namespace route {
namespace ip_route_cmds {
-static void
-to_vpp(const route::path& p, vapi_payload_ip_add_del_route& payload)
-{
- payload.is_drop = 0;
- payload.is_unreach = 0;
- payload.is_prohibit = 0;
- payload.is_local = 0;
- payload.is_classify = 0;
- payload.is_multipath = 0;
- payload.is_resolve_host = 0;
- payload.is_resolve_attached = 0;
-
- if (route::path::flags_t::DVR & p.flags()) {
- payload.is_dvr = 1;
- }
-
- if (route::path::special_t::STANDARD == p.type()) {
- uint8_t path_v6;
- to_bytes(p.nh(), &path_v6, payload.next_hop_address);
-
- 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 = 0;
- payload.classify_table_index = 0;
-}
-
update_cmd::update_cmd(HW::item<bool>& item,
table_id_t id,
const prefix_t& prefix,