DVR: run L3 output features
[vpp.git] / src / vpp-api / vom / route.cpp
index e239f8c..78ea8ce 100644 (file)
  */
 
 #include "vom/route.hpp"
+#include "vom/route_cmds.hpp"
 #include "vom/singular_db.hpp"
 
-#include <vapi/ip.api.vapi.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");
@@ -33,9 +33,18 @@ path::special_t::special_t(int v, const std::string& s)
 {
 }
 
+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)
@@ -50,6 +59,7 @@ path::path(const boost::asio::ip::address& nh,
            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())
@@ -64,6 +74,7 @@ path::path(const route_domain& rd,
            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)
@@ -74,10 +85,12 @@ path::path(const route_domain& rd,
 
 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())
@@ -89,6 +102,7 @@ path::path(const interface& interface,
 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)
@@ -100,57 +114,52 @@ path::path(const path& p)
 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
@@ -160,7 +169,7 @@ path::to_string() const
 
   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();
   }
@@ -173,6 +182,62 @@ path::to_string() const
   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())
@@ -197,12 +262,35 @@ ip_route::ip_route(const route_domain& rd, const prefix_t& prefix)
 {
 }
 
+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
@@ -221,7 +309,8 @@ 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();
 }
@@ -230,7 +319,8 @@ void
 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
@@ -251,15 +341,21 @@ ip_route::update(const ip_route& r)
 * 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>
@@ -289,8 +385,10 @@ ip_route::event_handler::handle_replay()
 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);
@@ -302,8 +400,8 @@ ip_route::event_handler::handle_populate(const client_db::key_t& key)
     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);
     if (!rd) {
@@ -335,10 +433,10 @@ ip_route::event_handler::handle_populate(const client_db::key_t& key)
     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);
   }
 
@@ -377,10 +475,10 @@ ip_route::event_handler::handle_populate(const client_db::key_t& key)
     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);
   }
 }