*/
#include "vom/route.hpp"
-#include "vom/singular_db.hpp"
-
-#include <vapi/ip.api.vapi.hpp>
+#include "vom/route_cmds.hpp"
+#include "vom/singular_db_funcs.hpp"
namespace VOM {
namespace route {
+ip_route::event_handler ip_route::m_evh;
singular_db<ip_route::key_t, ip_route> ip_route::m_db;
const path::special_t path::special_t::STANDARD(0, "standard");
{
}
+const path::flags_t path::flags_t::NONE(0, "none");
+const path::flags_t path::flags_t::DVR((1 << 0), "dvr");
+
+path::flags_t::flags_t(int v, const std::string& s)
+ : enum_base<path::flags_t>(v, s)
+{
+}
+
path::path(special_t special)
: m_type(special)
, m_nh_proto(nh_proto_t::IPV4)
+ , m_flags(flags_t::NONE)
, m_nh()
, m_rd(nullptr)
, m_interface(nullptr)
uint8_t preference)
: m_type(special_t::STANDARD)
, m_nh_proto(nh_proto_t::from_address(nh))
+ , m_flags(flags_t::NONE)
, m_nh(nh)
, m_rd(nullptr)
, m_interface(interface.singular())
uint8_t preference)
: m_type(special_t::STANDARD)
, m_nh_proto(nh_proto_t::from_address(nh))
+ , m_flags(flags_t::NONE)
, m_nh(nh)
, m_rd(rd.singular())
, m_interface(nullptr)
path::path(const interface& interface,
const nh_proto_t& proto,
+ const flags_t& flags,
uint8_t weight,
uint8_t preference)
: m_type(special_t::STANDARD)
, m_nh_proto(proto)
+ , m_flags(flags)
, m_nh()
, m_rd(nullptr)
, m_interface(interface.singular())
path::path(const path& p)
: m_type(p.m_type)
, m_nh_proto(p.m_nh_proto)
+ , m_flags(p.m_flags)
, m_nh(p.m_nh)
, m_rd(p.m_rd)
, m_interface(p.m_interface)
bool
path::operator<(const path& p) const
{
+ if (m_nh_proto < p.m_nh_proto)
+ return true;
+ if (m_flags < p.m_flags)
+ return true;
if (m_type < p.m_type)
return true;
+ if (m_rd && !p.m_rd)
+ return false;
+ if (!m_rd && p.m_rd)
+ return true;
if (m_rd->table_id() < p.m_rd->table_id())
return true;
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;
return (false);
}
-void
-path::to_vpp(vapi_payload_ip_add_del_route& payload) const
-{
- 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 (nh_proto_t::ETHERNET == m_nh_proto) {
- payload.is_l2_bridged = 1;
- }
-
- if (special_t::STANDARD == m_type) {
- uint8_t path_v6;
- to_bytes(m_nh, &path_v6, payload.next_hop_address);
+path::~path()
+{
+}
- if (m_rd) {
- payload.next_hop_table_id = m_rd->table_id();
- }
- if (m_interface) {
- payload.next_hop_sw_if_index = m_interface->handle().value();
- }
- } else if (special_t::DROP == m_type) {
- payload.is_drop = 1;
- } else if (special_t::UNREACH == m_type) {
- payload.is_unreach = 1;
- } else if (special_t::PROHIBIT == m_type) {
- payload.is_prohibit = 1;
- } else if (special_t::LOCAL == m_type) {
- payload.is_local = 1;
- }
- payload.next_hop_weight = m_weight;
- payload.next_hop_preference = m_preference;
- payload.next_hop_via_label = 0;
- payload.classify_table_index = 0;
+bool
+path::operator==(const path& p) const
+{
+ bool result = true;
+ if (m_rd && !p.m_rd)
+ return false;
+ if (!m_rd && p.m_rd)
+ return false;
+ if (m_rd && p.m_rd)
+ result &= (*m_rd == *p.m_rd);
+ if (m_interface && !p.m_interface)
+ return false;
+ if (!m_interface && p.m_interface)
+ return false;
+ if (m_interface && p.m_interface)
+ result &= (*m_interface == *p.m_interface);
+ return (result && (m_type == p.m_type) && (m_nh == p.m_nh) &&
+ (m_nh_proto == p.m_nh_proto) && (m_flags == p.m_flags));
}
std::string
s << "path:["
<< "type:" << m_type.to_string() << " proto:" << m_nh_proto.to_string()
- << " neighbour:" << m_nh.to_string();
+ << " flags:" << m_flags.to_string() << " neighbour:" << m_nh.to_string();
if (m_rd) {
s << " " << m_rd->to_string();
}
return (s.str());
}
+path::special_t
+path::type() const
+{
+ return m_type;
+}
+
+nh_proto_t
+path::nh_proto() const
+{
+ return m_nh_proto;
+}
+
+path::flags_t
+path::flags() const
+{
+ return m_flags;
+}
+
+const boost::asio::ip::address&
+path::nh() const
+{
+ return m_nh;
+}
+
+std::shared_ptr<route_domain>
+path::rd() const
+{
+ return m_rd;
+}
+
+std::shared_ptr<interface>
+path::itf() const
+{
+ return m_interface;
+}
+
+uint8_t
+path::weight() const
+{
+ return m_weight;
+}
+
+uint8_t
+path::preference() const
+{
+ return m_preference;
+}
+
+ip_route::ip_route(const prefix_t& prefix, const path& p)
+ : m_hw(false)
+ , m_rd(route_domain::get_default())
+ , m_prefix(prefix)
+ , m_paths({ p })
+{
+}
+
ip_route::ip_route(const prefix_t& prefix)
: m_hw(false)
, m_rd(route_domain::get_default())
{
}
+ip_route::ip_route(const route_domain& rd,
+ const prefix_t& prefix,
+ const path& p)
+ : m_hw(false)
+ , m_rd(rd.singular())
+ , m_prefix(prefix)
+ , m_paths({ p })
+{
+}
+
ip_route::~ip_route()
{
sweep();
// not in the DB anymore.
- m_db.release(std::make_pair(m_rd->table_id(), m_prefix), this);
+ m_db.release(key(), this);
+ m_paths.clear();
+}
+
+const ip_route::key_t
+ip_route::key() const
+{
+ return (std::make_pair(m_rd->table_id(), m_prefix));
+}
+
+bool
+ip_route::operator==(const ip_route& i) const
+{
+ return ((key() == i.key()) && (m_paths == i.m_paths));
}
void
ip_route::sweep()
{
if (m_hw) {
- HW::enqueue(new delete_cmd(m_hw, m_rd->table_id(), m_prefix));
+ HW::enqueue(
+ new ip_route_cmds::delete_cmd(m_hw, m_rd->table_id(), m_prefix));
}
HW::write();
}
ip_route::replay()
{
if (m_hw) {
- HW::enqueue(new update_cmd(m_hw, m_rd->table_id(), m_prefix, m_paths));
+ HW::enqueue(
+ new ip_route_cmds::update_cmd(m_hw, m_rd->table_id(), m_prefix, m_paths));
}
}
std::string
* create the table if it is not yet created
*/
if (rc_t::OK != m_hw.rc()) {
- HW::enqueue(new update_cmd(m_hw, m_rd->table_id(), m_prefix, m_paths));
+ HW::enqueue(
+ new ip_route_cmds::update_cmd(m_hw, m_rd->table_id(), m_prefix, m_paths));
}
}
std::shared_ptr<ip_route>
ip_route::find_or_add(const ip_route& temp)
{
- return (m_db.find_or_add(std::make_pair(temp.m_rd->table_id(), temp.m_prefix),
- temp));
+ return (m_db.find_or_add(temp.key(), temp));
+}
+
+std::shared_ptr<ip_route>
+ip_route::find(const key_t& k)
+{
+ return (m_db.find(k));
}
std::shared_ptr<ip_route>
void
ip_route::dump(std::ostream& os)
{
- m_db.dump(os);
+ db_dump(m_db, os);
}
ip_route::event_handler::event_handler()
void
ip_route::event_handler::handle_populate(const client_db::key_t& key)
{
- std::shared_ptr<ip_route::dump_v4_cmd> cmd_v4(new ip_route::dump_v4_cmd());
- std::shared_ptr<ip_route::dump_v6_cmd> cmd_v6(new ip_route::dump_v6_cmd());
+ std::shared_ptr<ip_route_cmds::dump_v4_cmd> cmd_v4 =
+ std::make_shared<ip_route_cmds::dump_v4_cmd>();
+ std::shared_ptr<ip_route_cmds::dump_v6_cmd> cmd_v6 =
+ std::make_shared<ip_route_cmds::dump_v6_cmd>();
HW::enqueue(cmd_v4);
HW::enqueue(cmd_v6);
prefix_t pfx(0, payload.address, payload.address_length);
/**
-* populating the route domain here
-*/
+ * populating the route domain here
+ */
route_domain rd_temp(payload.table_id);
- std::shared_ptr<route_domain> rd = route_domain::find(rd_temp);
+ std::shared_ptr<route_domain> rd = route_domain::find(payload.table_id);
if (!rd) {
OM::commit(key, rd_temp);
}
path path_v4(path::special_t::PROHIBIT);
ip_r.add(path_v4);
} else {
- std::shared_ptr<interface> itf = interface::find(p.sw_if_index);
boost::asio::ip::address address = from_bytes(0, p.next_hop);
- path path_v4(address, *itf, p.weight, p.preference);
- ip_r.add(path_v4);
+ 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);
+ }
}
}
VOM_LOG(log_level_t::DEBUG) << "ip-route-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
-*/
+ * 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);
}
prefix_t pfx(1, payload.address, payload.address_length);
route_domain rd_temp(payload.table_id);
- std::shared_ptr<route_domain> rd = route_domain::find(rd_temp);
+ std::shared_ptr<route_domain> rd = route_domain::find(payload.table_id);
if (!rd) {
OM::commit(key, rd_temp);
}
} else {
std::shared_ptr<interface> itf = interface::find(p.sw_if_index);
boost::asio::ip::address address = from_bytes(1, p.next_hop);
- path path_v6(address, *itf, p.weight, p.preference);
- ip_r.add(path_v6);
+ 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);
+ }
}
}
VOM_LOG(log_level_t::DEBUG) << "ip-route-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
-*/
+ * 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_route::event_handler::order() const
{
- return (dependency_t::BINDING);
+ return (dependency_t::TABLE);
}
void
ip_route::event_handler::show(std::ostream& os)
{
- m_db.dump(os);
+ db_dump(m_db, os);
}
std::ostream&