aboutsummaryrefslogtreecommitdiffstats
path: root/extras
diff options
context:
space:
mode:
authorNeale Ranns <neale.ranns@cisco.com>2018-05-16 04:12:18 -0700
committerNeale Ranns <nranns@cisco.com>2018-06-07 03:11:10 -0400
commitdaff1784037376f4a5caec2f5975f9b5fc23d5a4 (patch)
tree186701f7fcd64d691de5b5d11b477a5d8b7840a2 /extras
parent0e969ac8431c80ff4bca5f6985876b1c584eefcd (diff)
DHCP Client Dump
- use types on the DHCP API so that the same data is sent in comfing messages and in dumps - add the DHCP client dump API - update VOM to refelct API changes - rename VOM class dhcp_config* dhcp_client* - the VOM dhcp_client class maintains the lease data (which it reads on a dump) for clients to read Change-Id: I2a43463937cbd80c01d45798e74b21288d8b8ead Signed-off-by: Neale Ranns <neale.ranns@cisco.com>
Diffstat (limited to 'extras')
-rw-r--r--extras/vom/vom/Makefile.am7
-rw-r--r--extras/vom/vom/dhcp_client.cpp346
-rw-r--r--extras/vom/vom/dhcp_client.hpp (renamed from extras/vom/vom/dhcp_config.hpp)186
-rw-r--r--extras/vom/vom/dhcp_client_cmds.cpp (renamed from extras/vom/vom/dhcp_config_cmds.cpp)105
-rw-r--r--extras/vom/vom/dhcp_client_cmds.hpp (renamed from extras/vom/vom/dhcp_config_cmds.hpp)50
-rw-r--r--extras/vom/vom/dhcp_config.cpp194
-rw-r--r--extras/vom/vom/l3_binding.cpp29
-rw-r--r--extras/vom/vom/l3_binding.hpp5
-rw-r--r--extras/vom/vom/neighbour_cmds.cpp6
9 files changed, 610 insertions, 318 deletions
diff --git a/extras/vom/vom/Makefile.am b/extras/vom/vom/Makefile.am
index 892f437976e..2abf3463c8f 100644
--- a/extras/vom/vom/Makefile.am
+++ b/extras/vom/vom/Makefile.am
@@ -98,8 +98,8 @@ libvom_la_SOURCES = \
client_db.cpp \
cmd.cpp \
connection.cpp \
- dhcp_config_cmds.cpp \
- dhcp_config.cpp \
+ dhcp_client_cmds.cpp \
+ dhcp_client.cpp \
hw_cmds.cpp \
hw.cpp \
inspect.cpp \
@@ -192,8 +192,7 @@ vominclude_HEADERS = \
client_db.hpp \
cmd.hpp \
connection.hpp \
- dhcp_config.hpp \
- dhcp_config_cmds.hpp \
+ dhcp_client.hpp \
dump_cmd.hpp \
enum_base.hpp \
event_cmd.hpp \
diff --git a/extras/vom/vom/dhcp_client.cpp b/extras/vom/vom/dhcp_client.cpp
new file mode 100644
index 00000000000..fcadfa69ded
--- /dev/null
+++ b/extras/vom/vom/dhcp_client.cpp
@@ -0,0 +1,346 @@
+/*
+ * 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 "vom/dhcp_client.hpp"
+#include "vom/dhcp_client_cmds.hpp"
+#include "vom/singular_db_funcs.hpp"
+
+namespace VOM {
+const dhcp_client::state_t dhcp_client::state_t::DISCOVER(0, "discover");
+const dhcp_client::state_t dhcp_client::state_t::REQUEST(1, "request");
+const dhcp_client::state_t dhcp_client::state_t::BOUND(2, "bound");
+
+dhcp_client::state_t::state_t(int v, const std::string& s)
+ : enum_base<dhcp_client::state_t>(v, s)
+{
+}
+
+const dhcp_client::state_t&
+dhcp_client::state_t::from_vpp(int n)
+{
+ if (REQUEST == n)
+ return (REQUEST);
+ if (BOUND == n)
+ return (BOUND);
+
+ return (DISCOVER);
+}
+
+singular_db<interface::key_t, dhcp_client> dhcp_client::m_db;
+std::weak_ptr<dhcp_client_cmds::events_cmd> dhcp_client::m_s_event_cmd;
+dhcp_client::dhcp_client_listener dhcp_client::m_listener;
+
+dhcp_client::event_handler dhcp_client::m_evh;
+
+dhcp_client::dhcp_client(const interface& itf,
+ const std::string& hostname,
+ bool set_broadcast_flag,
+ event_listener* ev)
+ : m_itf(itf.singular())
+ , m_hostname(hostname)
+ , m_client_id(l2_address_t::ZERO)
+ , m_set_broadcast_flag(set_broadcast_flag)
+ , m_binding(0)
+ , m_evl(ev)
+ , m_event_cmd(get_event_cmd())
+{
+}
+
+dhcp_client::dhcp_client(const interface& itf,
+ const std::string& hostname,
+ const l2_address_t& client_id,
+ bool set_broadcast_flag,
+ event_listener* ev)
+ : m_itf(itf.singular())
+ , m_hostname(hostname)
+ , m_client_id(client_id)
+ , m_set_broadcast_flag(set_broadcast_flag)
+ , m_binding(0)
+ , m_evl(ev)
+ , m_event_cmd(get_event_cmd())
+{
+}
+
+dhcp_client::dhcp_client(const dhcp_client& o)
+ : m_itf(o.m_itf)
+ , m_hostname(o.m_hostname)
+ , m_client_id(o.m_client_id)
+ , m_set_broadcast_flag(o.m_set_broadcast_flag)
+ , m_binding(0)
+ , m_evl(o.m_evl)
+ , m_event_cmd(o.m_event_cmd)
+{
+}
+
+dhcp_client::~dhcp_client()
+{
+ sweep();
+
+ // not in the DB anymore.
+ m_db.release(m_itf->key(), this);
+}
+
+bool
+dhcp_client::operator==(const dhcp_client& l) const
+{
+ return ((key() == l.key()) && (m_hostname == l.m_hostname) &&
+ (m_client_id == l.m_client_id));
+}
+
+const dhcp_client::key_t&
+dhcp_client::key() const
+{
+ return (m_itf->key());
+}
+
+void
+dhcp_client::sweep()
+{
+ if (m_binding) {
+ HW::enqueue(
+ new dhcp_client_cmds::unbind_cmd(m_binding, m_itf->handle(), m_hostname));
+ }
+ HW::write();
+}
+
+void
+dhcp_client::dump(std::ostream& os)
+{
+ db_dump(m_db, os);
+}
+
+void
+dhcp_client::replay()
+{
+ if (m_binding) {
+ HW::enqueue(new dhcp_client_cmds::bind_cmd(m_binding, m_itf->handle(),
+ m_hostname, m_client_id));
+ }
+}
+
+std::string
+dhcp_client::to_string() const
+{
+ std::ostringstream s;
+ s << "DHCP-client: " << m_itf->to_string() << " hostname:" << m_hostname
+ << " client_id:[" << m_client_id << "] " << m_binding.to_string();
+ if (m_lease)
+ s << " " << m_lease->to_string();
+ else
+ s << " no-lease";
+
+ return (s.str());
+}
+
+void
+dhcp_client::update(const dhcp_client& desired)
+{
+ /*
+ * the desired state is always that the interface should be created
+ */
+ if (!m_binding) {
+ HW::enqueue(new dhcp_client_cmds::bind_cmd(m_binding, m_itf->handle(),
+ m_hostname, m_client_id));
+ }
+
+ if (desired.m_lease)
+ m_lease = desired.m_lease;
+ if (m_evl != desired.m_evl) {
+ m_evl = desired.m_evl;
+ }
+}
+
+const std::shared_ptr<dhcp_client::lease_t>
+dhcp_client::lease() const
+{
+ return (m_lease);
+}
+
+void
+dhcp_client::lease(std::shared_ptr<dhcp_client::lease_t> lease)
+{
+ m_lease = lease;
+}
+
+std::shared_ptr<dhcp_client>
+dhcp_client::find_or_add(const dhcp_client& temp)
+{
+ return (m_db.find_or_add(temp.m_itf->key(), temp));
+}
+
+std::shared_ptr<dhcp_client>
+dhcp_client::find(const key_t& k)
+{
+ return (m_db.find(k));
+}
+
+std::shared_ptr<dhcp_client>
+dhcp_client::singular() const
+{
+ return find_or_add(*this);
+}
+
+dhcp_client::lease_t::lease_t()
+ : state(state_t::DISCOVER)
+ , mac(mac_address_t::ZERO)
+{
+}
+
+dhcp_client::lease_t::lease_t(const state_t& state,
+ std::shared_ptr<interface> itf,
+ const boost::asio::ip::address& router_address,
+ const route::prefix_t& host_prefix,
+ const std::string& hostname,
+ const mac_address_t& mac)
+ : state(state)
+ , itf(itf)
+ , router_address(router_address)
+ , host_prefix(host_prefix)
+ , hostname(hostname)
+ , mac(mac)
+{
+}
+
+std::string
+dhcp_client::lease_t::to_string() const
+{
+ std::stringstream ss;
+
+ ss << "lease:[" << itf->to_string() << " state: " << state.to_string()
+ << " host: " << host_prefix.to_string() << " router: " << router_address
+ << " mac: " << mac.to_string() << "]";
+
+ return (ss.str());
+}
+
+dhcp_client::event_listener::event_listener()
+ : m_status(rc_t::NOOP)
+{
+}
+
+HW::item<bool>&
+dhcp_client::event_listener::status()
+{
+ return (m_status);
+}
+
+dhcp_client::event_handler::event_handler()
+{
+ OM::register_listener(this);
+ inspect::register_handler({ "dhcp" }, "DHCP clients", this);
+}
+
+void
+dhcp_client::event_handler::handle_replay()
+{
+ m_db.replay();
+}
+
+void
+dhcp_client::event_handler::handle_populate(const client_db::key_t& key)
+{
+ std::shared_ptr<dhcp_client_cmds::dump_cmd> cmd =
+ std::make_shared<dhcp_client_cmds::dump_cmd>();
+
+ HW::enqueue(cmd);
+ HW::write();
+
+ for (auto& record : *cmd) {
+ auto& payload = record.get_payload();
+
+ std::shared_ptr<interface> itf =
+ interface::find(payload.client.sw_if_index);
+
+ if (!itf) {
+ VOM_LOG(log_level_t::ERROR) << "dhcp-client dump:"
+ << " itf:" << payload.client.sw_if_index;
+ continue;
+ }
+
+ const dhcp_client::state_t& s =
+ dhcp_client::state_t::from_vpp(payload.lease.state);
+ route::prefix_t pfx(payload.lease.is_ipv6, payload.lease.host_address,
+ payload.lease.mask_width);
+ std::string hostname =
+ reinterpret_cast<const char*>(payload.lease.hostname);
+ l2_address_t l2(payload.client.id + 1);
+ dhcp_client dc(*itf, hostname, l2, payload.client.set_broadcast_flag);
+ dc.lease(std::make_shared<dhcp_client::lease_t>(
+ s, itf, from_bytes(0, payload.lease.router_address), pfx, hostname,
+ mac_address_t(payload.lease.host_mac)));
+ OM::commit(key, dc);
+ }
+}
+
+dependency_t
+dhcp_client::event_handler::order() const
+{
+ return (dependency_t::BINDING);
+}
+
+void
+dhcp_client::event_handler::show(std::ostream& os)
+{
+ db_dump(m_db, os);
+}
+
+std::shared_ptr<dhcp_client_cmds::events_cmd>
+dhcp_client::get_event_cmd()
+{
+ if (m_s_event_cmd.expired()) {
+ std::shared_ptr<dhcp_client_cmds::events_cmd> c =
+ std::make_shared<dhcp_client_cmds::events_cmd>(m_listener);
+
+ m_s_event_cmd = c;
+
+ HW::enqueue(c);
+ HW::write();
+
+ return c;
+ }
+
+ return (m_s_event_cmd.lock());
+}
+
+void
+dhcp_client::handle_dhcp_event(std::shared_ptr<lease_t> lease)
+{
+ m_lease = lease;
+ if (m_evl)
+ m_evl->handle_dhcp_event(m_lease);
+}
+
+void
+dhcp_client::dhcp_client_listener::handle_dhcp_event(std::shared_ptr<lease_t> e)
+{
+ /*
+ * Find the client the event references
+ */
+ std::shared_ptr<dhcp_client> client = find(e->itf->key());
+
+ if (client) {
+ client->handle_dhcp_event(e);
+ }
+}
+
+}; // namespace VOM
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "mozilla")
+ * End:
+ */
diff --git a/extras/vom/vom/dhcp_config.hpp b/extras/vom/vom/dhcp_client.hpp
index 8ea608d809d..17c626ed0f1 100644
--- a/extras/vom/vom/dhcp_config.hpp
+++ b/extras/vom/vom/dhcp_client.hpp
@@ -13,60 +13,130 @@
* limitations under the License.
*/
-#ifndef __VOM_DHCP_CONFIG_H__
-#define __VOM_DHCP_CONFIG_H__
+#ifndef __VOM_DHCP_CLIENT_H__
+#define __VOM_DHCP_CLIENT_H__
#include "vom/hw.hpp"
#include "vom/inspect.hpp"
#include "vom/interface.hpp"
#include "vom/object_base.hpp"
#include "vom/om.hpp"
+#include "vom/prefix.hpp"
#include "vom/singular_db.hpp"
namespace VOM {
-namespace dhcp_config_cmds {
+namespace dhcp_client_cmds {
class events_cmd;
};
/**
- * A representation of DHCP client configuration on an interface
+ * A representation of DHCP client on an interface
*/
-class dhcp_config : public object_base
+class dhcp_client : public object_base
{
public:
/**
- * typedef for the DHCP config key type
+ * typedef for the DHCP client key type
*/
typedef interface::key_t key_t;
+ struct state_t : enum_base<state_t>
+ {
+ const static state_t DISCOVER;
+ const static state_t REQUEST;
+ const static state_t BOUND;
+
+ static const state_t& from_vpp(int i);
+
+ private:
+ /**
+ * Private constructor taking the value and the string name
+ */
+ state_t(int v, const std::string& s);
+ };
+
+ /**
+ * A DHCP lease data
+ */
+ struct lease_t
+ {
+ lease_t();
+ lease_t(const state_t& state,
+ std::shared_ptr<interface> itf,
+ const boost::asio::ip::address& router_address,
+ const route::prefix_t& host_prefix,
+ const std::string& hostname,
+ const mac_address_t& mac);
+
+ std::string to_string() const;
+
+ const state_t& state;
+ std::shared_ptr<interface> itf;
+ boost::asio::ip::address router_address;
+ route::prefix_t host_prefix;
+ std::string hostname;
+ mac_address_t mac;
+ };
+
+ /**
+ * A class that listens to DHCP Events
+ */
+ class event_listener
+ {
+ public:
+ /**
+ * Constructor
+ */
+ event_listener();
+
+ /**
+ * listener's virtual function invoked when a DHCP event is
+ * available to read
+ */
+ virtual void handle_dhcp_event(std::shared_ptr<lease_t> e) = 0;
+
+ /**
+ * Return the HW::item associated with this command
+ */
+ HW::item<bool>& status();
+
+ protected:
+ /**
+ * The HW::item associated with this command
+ */
+ HW::item<bool> m_status;
+ };
+
/**
* Construct a new object matching the desried state
*/
- dhcp_config(const interface& itf,
+ dhcp_client(const interface& itf,
const std::string& hostname,
- bool set_broadcast_flag = true);
+ bool set_broadcast_flag = true,
+ event_listener* ev = nullptr);
/**
* Construct a new object matching the desried state
*/
- dhcp_config(const interface& itf,
+ dhcp_client(const interface& itf,
const std::string& hostname,
const l2_address_t& client_id,
- bool set_broadcast_flag = true);
+ bool set_broadcast_flag = true,
+ event_listener* ev = nullptr);
/**
* Copy Constructor
*/
- dhcp_config(const dhcp_config& o);
+ dhcp_client(const dhcp_client& o);
/**
* Destructor
*/
- ~dhcp_config();
+ ~dhcp_client();
/**
* Comparison operator - for UT
*/
- bool operator==(const dhcp_config& d) const;
+ bool operator==(const dhcp_client& d) const;
/**
* Return the object's key
@@ -74,9 +144,9 @@ public:
const key_t& key() const;
/**
- * Return the 'singular' of the DHCP config that matches this object
+ * Return the 'singular' of the DHCP client that matches this object
*/
- std::shared_ptr<dhcp_config> singular() const;
+ std::shared_ptr<dhcp_client> singular() const;
/**
* convert to string format for debug purposes
@@ -84,43 +154,19 @@ public:
std::string to_string() const;
/**
- * Dump all DHCP configs into the stream provided
+ * Dump all DHCP clients into the stream provided
*/
static void dump(std::ostream& os);
/**
- * Find a DHCP config from its key
+ * Find a DHCP client from its key
*/
- static std::shared_ptr<dhcp_config> find(const key_t& k);
+ static std::shared_ptr<dhcp_client> find(const key_t& k);
/**
- * A class that listens to DHCP Events
- */
- class event_listener
- {
- public:
- /**
- * Constructor
- */
- event_listener();
-
- /**
- * listener's virtual function invoked when a DHCP event is
- * available to read
- */
- virtual void handle_dhcp_event(dhcp_config_cmds::events_cmd* cmd) = 0;
-
- /**
- * Return the HW::item associated with this command
- */
- HW::item<bool>& status();
-
- protected:
- /**
- * The HW::item associated with this command
- */
- HW::item<bool> m_status;
- };
+ * return the current lease data
+ */
+ const std::shared_ptr<lease_t> lease() const;
private:
/**
@@ -161,12 +207,12 @@ private:
/**
* Enquue commonds to the VPP command Q for the update
*/
- void update(const dhcp_config& obj);
+ void update(const dhcp_client& obj);
/**
- * Find or add DHCP config to the OM
+ * Find or add DHCP client to the OM
*/
- static std::shared_ptr<dhcp_config> find_or_add(const dhcp_config& temp);
+ static std::shared_ptr<dhcp_client> find_or_add(const dhcp_client& temp);
/*
* It's the OM class that calls singular()
@@ -176,7 +222,7 @@ private:
/**
* It's the singular_db class that calls replay()
*/
- friend class singular_db<key_t, dhcp_config>;
+ friend class singular_db<key_t, dhcp_client>;
/**
* Sweep/reap the object if still stale
@@ -188,20 +234,22 @@ private:
*/
void replay(void);
+ void lease(std::shared_ptr<lease_t> l);
+
/**
- * A reference counting pointer to the interface on which DHCP config
+ * A reference counting pointer to the interface on which DHCP client
* resides. By holding the reference here, we can guarantee that
* this object will outlive the interface
*/
const std::shared_ptr<interface> m_itf;
/**
- * The hostname in the DHCP configuration
+ * The hostname in the DHCP client
*/
const std::string m_hostname;
/**
- * The option-61 client_id in the DHCP configuration
+ * The option-61 client_id in the DHCP client
*/
const l2_address_t m_client_id;
@@ -213,13 +261,41 @@ private:
/**
* HW configuration for the binding. The bool representing the
* do/don't bind.
- */
+ */
HW::item<bool> m_binding;
/**
- * A map of all Dhcp configs keyed against the interface.
+ * A pointer to an event listener for client events
*/
- static singular_db<key_t, dhcp_config> m_db;
+ event_listener* m_evl;
+
+ /**
+ * Current lease state for this client
+ */
+ std::shared_ptr<lease_t> m_lease;
+
+ std::shared_ptr<dhcp_client_cmds::events_cmd> m_event_cmd;
+
+ void handle_dhcp_event(std::shared_ptr<lease_t> e);
+
+ /**
+ * A map of all Dhcp clients keyed against the interface.
+ */
+ static singular_db<key_t, dhcp_client> m_db;
+
+ static std::weak_ptr<dhcp_client_cmds::events_cmd> m_s_event_cmd;
+ static std::shared_ptr<dhcp_client_cmds::events_cmd> get_event_cmd();
+
+ class dhcp_client_listener : public event_listener
+ {
+ public:
+ /**
+ * listener's virtual function invoked when a DHCP event is
+ * available to read
+ */
+ void handle_dhcp_event(std::shared_ptr<lease_t> e);
+ };
+ static dhcp_client_listener m_listener;
};
};
diff --git a/extras/vom/vom/dhcp_config_cmds.cpp b/extras/vom/vom/dhcp_client_cmds.cpp
index 76ce58b6b92..181a15f8f96 100644
--- a/extras/vom/vom/dhcp_config_cmds.cpp
+++ b/extras/vom/vom/dhcp_client_cmds.cpp
@@ -13,12 +13,12 @@
* limitations under the License.
*/
-#include "vom/dhcp_config_cmds.hpp"
+#include "vom/dhcp_client_cmds.hpp"
DEFINE_VAPI_MSG_IDS_DHCP_API_JSON;
namespace VOM {
-namespace dhcp_config_cmds {
+namespace dhcp_client_cmds {
bind_cmd::bind_cmd(HW::item<bool>& item,
const handle_t& itf,
@@ -45,21 +45,21 @@ bind_cmd::issue(connection& con)
msg_t req(con.ctx(), std::ref(*this));
auto& payload = req.get_request().get_payload();
- payload.sw_if_index = m_itf.value();
payload.is_add = 1;
- payload.pid = getpid();
- payload.want_dhcp_event = 1;
- payload.set_broadcast_flag = m_set_broadcast_flag;
+ payload.client.sw_if_index = m_itf.value();
+ payload.client.pid = getpid();
+ payload.client.want_dhcp_event = 1;
+ payload.client.set_broadcast_flag = m_set_broadcast_flag;
- memset(payload.hostname, 0, sizeof(payload.hostname));
- memcpy(payload.hostname, m_hostname.c_str(),
- std::min(sizeof(payload.hostname), m_hostname.length()));
+ memset(payload.client.hostname, 0, sizeof(payload.client.hostname));
+ memcpy(payload.client.hostname, m_hostname.c_str(),
+ std::min(sizeof(payload.client.hostname), m_hostname.length()));
- memset(payload.client_id, 0, sizeof(payload.client_id));
- payload.client_id[0] = 1;
+ memset(payload.client.id, 0, sizeof(payload.client.id));
+ payload.client.id[0] = 1;
std::copy_n(begin(m_client_id.bytes),
- std::min(sizeof(payload.client_id), m_client_id.bytes.size()),
- payload.client_id + 1);
+ std::min(sizeof(payload.client.id), m_client_id.bytes.size()),
+ payload.client.id + 1);
VAPI_CALL(req.execute());
@@ -72,7 +72,7 @@ std::string
bind_cmd::to_string() const
{
std::ostringstream s;
- s << "Dhcp-config-bind: " << m_hw_item.to_string()
+ s << "Dhcp-client-bind: " << m_hw_item.to_string()
<< " itf:" << m_itf.to_string() << " hostname:" << m_hostname;
return (s.str());
@@ -99,13 +99,13 @@ unbind_cmd::issue(connection& con)
msg_t req(con.ctx(), std::ref(*this));
auto& payload = req.get_request().get_payload();
- payload.sw_if_index = m_itf.value();
payload.is_add = 0;
- payload.pid = getpid();
- payload.want_dhcp_event = 0;
+ payload.client.sw_if_index = m_itf.value();
+ payload.client.pid = getpid();
+ payload.client.want_dhcp_event = 0;
- memcpy(payload.hostname, m_hostname.c_str(),
- std::min(sizeof(payload.hostname), m_hostname.length()));
+ memcpy(payload.client.hostname, m_hostname.c_str(),
+ std::min(sizeof(payload.client.hostname), m_hostname.length()));
VAPI_CALL(req.execute());
@@ -119,18 +119,23 @@ std::string
unbind_cmd::to_string() const
{
std::ostringstream s;
- s << "Dhcp-config-unbind: " << m_hw_item.to_string()
+ s << "Dhcp-client-unbind: " << m_hw_item.to_string()
<< " itf:" << m_itf.to_string() << " hostname:" << m_hostname;
return (s.str());
}
-events_cmd::events_cmd(dhcp_config::event_listener& el)
+events_cmd::events_cmd(dhcp_client::event_listener& el)
: event_cmd(el.status())
, m_listener(el)
{
}
+events_cmd::~events_cmd()
+{
+ VOM_LOG(log_level_t::INFO) << "DHCP events destroyed";
+}
+
bool
events_cmd::operator==(const events_cmd& other) const
{
@@ -159,7 +164,31 @@ events_cmd::retire(connection& con)
void
events_cmd::notify()
{
- m_listener.handle_dhcp_event(this);
+ for (auto& msg : *this) {
+ auto& payload = msg.get_payload();
+
+ const dhcp_client::state_t& s =
+ dhcp_client::state_t::from_vpp(payload.lease.state);
+ route::prefix_t pfx(payload.lease.is_ipv6, payload.lease.host_address,
+ payload.lease.mask_width);
+ std::shared_ptr<interface> itf = interface::find(payload.lease.sw_if_index);
+
+ if (itf) {
+ std::shared_ptr<dhcp_client::lease_t> ev =
+ std::make_shared<dhcp_client::lease_t>(
+ s, itf, from_bytes(0, payload.lease.router_address), pfx,
+ reinterpret_cast<const char*>(payload.lease.hostname),
+ mac_address_t(payload.lease.host_mac));
+ m_listener.handle_dhcp_event(ev);
+
+ VOM_LOG(log_level_t::INFO) << "DHCP: " << ev->to_string();
+ } else {
+ VOM_LOG(log_level_t::ERROR) << "DHCP: no interface: "
+ << payload.lease.sw_if_index;
+ }
+ }
+
+ flush();
}
std::string
@@ -167,8 +196,38 @@ events_cmd::to_string() const
{
return ("dhcp-events");
}
+
+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 ("dhcp-client-dump");
+}
+
+}; // namespace dhcp_client_cmds
+}; // namespace VOM
+
/*
* fd.io coding-style-patch-verification: ON
*
diff --git a/extras/vom/vom/dhcp_config_cmds.hpp b/extras/vom/vom/dhcp_client_cmds.hpp
index 726ff992577..e7db38f4e3b 100644
--- a/extras/vom/vom/dhcp_config_cmds.hpp
+++ b/extras/vom/vom/dhcp_client_cmds.hpp
@@ -13,17 +13,18 @@
* limitations under the License.
*/
-#ifndef __VOM_DHCP_CONFIG_CMDS_H__
-#define __VOM_DHCP_CONFIG_CMDS_H__
+#ifndef __VOM_DHCP_CLIENT_CMDS_H__
+#define __VOM_DHCP_CLIENT_CMDS_H__
-#include "vom/dhcp_config.hpp"
+#include "vom/dhcp_client.hpp"
+#include "vom/dump_cmd.hpp"
#include "vom/event_cmd.hpp"
#include <vapi/dhcp.api.vapi.hpp>
#include <vapi/vpe.api.vapi.hpp>
namespace VOM {
-namespace dhcp_config_cmds {
+namespace dhcp_client_cmds {
/**
* A command class that binds the DHCP config to the interface
@@ -125,7 +126,8 @@ public:
/**
* Constructor
*/
- events_cmd(dhcp_config::event_listener& el);
+ events_cmd(dhcp_client::event_listener& el);
+ ~events_cmd();
/**
* Issue the command to VPP/HW - subscribe to DHCP events
@@ -156,11 +158,45 @@ private:
/**
* The listner of this command
*/
- dhcp_config::event_listener& m_listener;
-};
+ dhcp_client::event_listener& m_listener;
};
+
+/**
+ * A cmd class that Dumps all the DHCP clients
+ */
+class dump_cmd : public VOM::dump_cmd<vapi::Dhcp_client_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 dhcp_client_cmds
+}; // namespace VOM
+
/*
* fd.io coding-style-patch-verification: ON
*
diff --git a/extras/vom/vom/dhcp_config.cpp b/extras/vom/vom/dhcp_config.cpp
deleted file mode 100644
index 7d97fa15d6e..00000000000
--- a/extras/vom/vom/dhcp_config.cpp
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- * 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 "vom/dhcp_config.hpp"
-#include "vom/dhcp_config_cmds.hpp"
-#include "vom/singular_db_funcs.hpp"
-
-namespace VOM {
-/**
- * A DB of all DHCP configs
- */
-singular_db<interface::key_t, dhcp_config> dhcp_config::m_db;
-
-dhcp_config::event_handler dhcp_config::m_evh;
-
-dhcp_config::dhcp_config(const interface& itf,
- const std::string& hostname,
- bool set_broadcast_flag)
- : m_itf(itf.singular())
- , m_hostname(hostname)
- , m_client_id(l2_address_t::ZERO)
- , m_set_broadcast_flag(set_broadcast_flag)
- , m_binding(0)
-{
-}
-
-dhcp_config::dhcp_config(const interface& itf,
- const std::string& hostname,
- const l2_address_t& client_id,
- bool set_broadcast_flag)
- : m_itf(itf.singular())
- , m_hostname(hostname)
- , m_client_id(client_id)
- , m_set_broadcast_flag(set_broadcast_flag)
- , m_binding(0)
-{
-}
-
-dhcp_config::dhcp_config(const dhcp_config& o)
- : m_itf(o.m_itf)
- , m_hostname(o.m_hostname)
- , m_client_id(o.m_client_id)
- , m_set_broadcast_flag(o.m_set_broadcast_flag)
- , m_binding(0)
-{
-}
-
-dhcp_config::~dhcp_config()
-{
- sweep();
-
- // not in the DB anymore.
- m_db.release(m_itf->key(), this);
-}
-
-bool
-dhcp_config::operator==(const dhcp_config& l) const
-{
- return ((key() == l.key()) && (m_hostname == l.m_hostname) &&
- (m_client_id == l.m_client_id));
-}
-
-const dhcp_config::key_t&
-dhcp_config::key() const
-{
- return (m_itf->key());
-}
-
-void
-dhcp_config::sweep()
-{
- if (m_binding) {
- HW::enqueue(
- new dhcp_config_cmds::unbind_cmd(m_binding, m_itf->handle(), m_hostname));
- }
- HW::write();
-}
-
-void
-dhcp_config::dump(std::ostream& os)
-{
- db_dump(m_db, os);
-}
-
-void
-dhcp_config::replay()
-{
- if (m_binding) {
- HW::enqueue(new dhcp_config_cmds::bind_cmd(m_binding, m_itf->handle(),
- m_hostname, m_client_id));
- }
-}
-
-std::string
-dhcp_config::to_string() const
-{
- std::ostringstream s;
- s << "Dhcp-config: " << m_itf->to_string() << " hostname:" << m_hostname
- << " client_id:[" << m_client_id << "] " << m_binding.to_string();
-
- return (s.str());
-}
-
-void
-dhcp_config::update(const dhcp_config& desired)
-{
- /*
- * the desired state is always that the interface should be created
- */
- if (!m_binding) {
- HW::enqueue(new dhcp_config_cmds::bind_cmd(m_binding, m_itf->handle(),
- m_hostname, m_client_id));
- }
-}
-
-std::shared_ptr<dhcp_config>
-dhcp_config::find_or_add(const dhcp_config& temp)
-{
- return (m_db.find_or_add(temp.m_itf->key(), temp));
-}
-
-std::shared_ptr<dhcp_config>
-dhcp_config::find(const key_t& k)
-{
- return (m_db.find(k));
-}
-
-std::shared_ptr<dhcp_config>
-dhcp_config::singular() const
-{
- return find_or_add(*this);
-}
-
-dhcp_config::event_listener::event_listener()
- : m_status(rc_t::NOOP)
-{
-}
-
-HW::item<bool>&
-dhcp_config::event_listener::status()
-{
- return (m_status);
-}
-
-dhcp_config::event_handler::event_handler()
-{
- OM::register_listener(this);
- inspect::register_handler({ "dhcp" }, "DHCP configurations", this);
-}
-
-void
-dhcp_config::event_handler::handle_replay()
-{
- m_db.replay();
-}
-
-void
-dhcp_config::event_handler::handle_populate(const client_db::key_t& key)
-{
- // FIXME
-}
-
-dependency_t
-dhcp_config::event_handler::order() const
-{
- return (dependency_t::BINDING);
-}
-
-void
-dhcp_config::event_handler::show(std::ostream& os)
-{
- db_dump(m_db, os);
-}
-}
-
-/*
- * fd.io coding-style-patch-verification: ON
- *
- * Local Variables:
- * eval: (c-set-style "mozilla")
- * End:
- */
diff --git a/extras/vom/vom/l3_binding.cpp b/extras/vom/vom/l3_binding.cpp
index 13bc1ffd575..6b8d36209a7 100644
--- a/extras/vom/vom/l3_binding.cpp
+++ b/extras/vom/vom/l3_binding.cpp
@@ -158,35 +158,6 @@ operator<<(std::ostream& os, const l3_binding::key_t& key)
return (os);
}
-std::deque<std::shared_ptr<l3_binding>>
-l3_binding::find(const interface& i)
-{
- /*
- * Loop throught the entire map looking for matching interface.
- * not the most efficient algorithm, but it will do for now. The
- * number of L3 configs is low and this is only called during bootup
- */
- std::deque<std::shared_ptr<l3_binding>> l3s;
-
- auto it = m_db.begin();
-
- while (it != m_db.end()) {
- /*
- * The key in the DB is a pair of the interface's name and prefix.
- * If the keys match, save the L3-config
- */
- auto key = it->first;
-
- if (i.key() == key.first) {
- l3s.push_back(it->second.lock());
- }
-
- ++it;
- }
-
- return (l3s);
-}
-
l3_binding::event_handler::event_handler()
{
OM::register_listener(this);
diff --git a/extras/vom/vom/l3_binding.hpp b/extras/vom/vom/l3_binding.hpp
index 0177e56ea2b..a2a46263dbd 100644
--- a/extras/vom/vom/l3_binding.hpp
+++ b/extras/vom/vom/l3_binding.hpp
@@ -95,11 +95,6 @@ public:
static void dump(std::ostream& os);
/**
- * Find all bindings in the DB for the interface passed
- */
- static std::deque<std::shared_ptr<l3_binding>> find(const interface& i);
-
- /**
* Find a binding from its key
*/
static std::shared_ptr<l3_binding> find(const key_t& k);
diff --git a/extras/vom/vom/neighbour_cmds.cpp b/extras/vom/vom/neighbour_cmds.cpp
index 2f3c200d5fb..63534f3dd94 100644
--- a/extras/vom/vom/neighbour_cmds.cpp
+++ b/extras/vom/vom/neighbour_cmds.cpp
@@ -151,7 +151,11 @@ dump_cmd::issue(connection& con)
std::string
dump_cmd::to_string() const
{
- return ("neighbour-dump");
+ std::ostringstream s;
+
+ s << "neighbour-dump: " << m_itf.to_string() << " " << m_proto.to_string();
+
+ return (s.str());
}
} // namespace neighbour_cmds
} // namespace vom