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>
This commit is contained in:
@ -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 \
|
||||
|
346
extras/vom/vom/dhcp_client.cpp
Normal file
346
extras/vom/vom/dhcp_client.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@ -13,89 +13,73 @@
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Construct a new object matching the desried state
|
||||
*/
|
||||
dhcp_config(const interface& itf,
|
||||
const std::string& hostname,
|
||||
bool set_broadcast_flag = true);
|
||||
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);
|
||||
};
|
||||
|
||||
/**
|
||||
* Construct a new object matching the desried state
|
||||
* A DHCP lease data
|
||||
*/
|
||||
dhcp_config(const interface& itf,
|
||||
const std::string& hostname,
|
||||
const l2_address_t& client_id,
|
||||
bool set_broadcast_flag = true);
|
||||
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;
|
||||
};
|
||||
|
||||
/**
|
||||
* Copy Constructor
|
||||
* A class that listens to DHCP Events
|
||||
*/
|
||||
dhcp_config(const dhcp_config& o);
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~dhcp_config();
|
||||
|
||||
/**
|
||||
* Comparison operator - for UT
|
||||
*/
|
||||
bool operator==(const dhcp_config& d) const;
|
||||
|
||||
/**
|
||||
* Return the object's key
|
||||
*/
|
||||
const key_t& key() const;
|
||||
|
||||
/**
|
||||
* Return the 'singular' of the DHCP config that matches this object
|
||||
*/
|
||||
std::shared_ptr<dhcp_config> singular() const;
|
||||
|
||||
/**
|
||||
* convert to string format for debug purposes
|
||||
*/
|
||||
std::string to_string() const;
|
||||
|
||||
/**
|
||||
* Dump all DHCP configs into the stream provided
|
||||
*/
|
||||
static void dump(std::ostream& os);
|
||||
|
||||
/**
|
||||
* Find a DHCP config from its key
|
||||
*/
|
||||
static std::shared_ptr<dhcp_config> find(const key_t& k);
|
||||
|
||||
/**
|
||||
* A class that listens to DHCP Events
|
||||
*/
|
||||
class event_listener
|
||||
{
|
||||
public:
|
||||
@ -108,7 +92,7 @@ public:
|
||||
* 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;
|
||||
virtual void handle_dhcp_event(std::shared_ptr<lease_t> e) = 0;
|
||||
|
||||
/**
|
||||
* Return the HW::item associated with this command
|
||||
@ -122,6 +106,68 @@ public:
|
||||
HW::item<bool> m_status;
|
||||
};
|
||||
|
||||
/**
|
||||
* Construct a new object matching the desried state
|
||||
*/
|
||||
dhcp_client(const interface& itf,
|
||||
const std::string& hostname,
|
||||
bool set_broadcast_flag = true,
|
||||
event_listener* ev = nullptr);
|
||||
|
||||
/**
|
||||
* Construct a new object matching the desried state
|
||||
*/
|
||||
dhcp_client(const interface& itf,
|
||||
const std::string& hostname,
|
||||
const l2_address_t& client_id,
|
||||
bool set_broadcast_flag = true,
|
||||
event_listener* ev = nullptr);
|
||||
|
||||
/**
|
||||
* Copy Constructor
|
||||
*/
|
||||
dhcp_client(const dhcp_client& o);
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~dhcp_client();
|
||||
|
||||
/**
|
||||
* Comparison operator - for UT
|
||||
*/
|
||||
bool operator==(const dhcp_client& d) const;
|
||||
|
||||
/**
|
||||
* Return the object's key
|
||||
*/
|
||||
const key_t& key() const;
|
||||
|
||||
/**
|
||||
* Return the 'singular' of the DHCP client that matches this object
|
||||
*/
|
||||
std::shared_ptr<dhcp_client> singular() const;
|
||||
|
||||
/**
|
||||
* convert to string format for debug purposes
|
||||
*/
|
||||
std::string to_string() const;
|
||||
|
||||
/**
|
||||
* Dump all DHCP clients into the stream provided
|
||||
*/
|
||||
static void dump(std::ostream& os);
|
||||
|
||||
/**
|
||||
* Find a DHCP client from its key
|
||||
*/
|
||||
static std::shared_ptr<dhcp_client> find(const key_t& k);
|
||||
|
||||
/**
|
||||
* return the current lease data
|
||||
*/
|
||||
const std::shared_ptr<lease_t> lease() const;
|
||||
|
||||
private:
|
||||
/**
|
||||
* Class definition for listeners to OM events
|
||||
@ -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;
|
||||
};
|
||||
};
|
||||
|
@ -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
|
||||
*
|
@ -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
|
||||
*
|
@ -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:
|
||||
*/
|
@ -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);
|
||||
|
@ -94,11 +94,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
|
||||
*/
|
||||
|
@ -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
|
||||
|
@ -2669,10 +2669,11 @@ vl_api_dhcp_compl_event_t_handler (vl_api_dhcp_compl_event_t * mp)
|
||||
{
|
||||
errmsg ("DHCP compl event: pid %d %s hostname %s host_addr %U "
|
||||
"router_addr %U host_mac %U",
|
||||
ntohl (mp->pid), mp->is_ipv6 ? "ipv6" : "ipv4", mp->hostname,
|
||||
format_ip4_address, &mp->host_address,
|
||||
format_ip4_address, &mp->router_address,
|
||||
format_ethernet_address, mp->host_mac);
|
||||
ntohl (mp->pid), mp->lease.is_ipv6 ? "ipv6" : "ipv4",
|
||||
mp->lease.hostname,
|
||||
format_ip4_address, &mp->lease.host_address,
|
||||
format_ip4_address, &mp->lease.router_address,
|
||||
format_ethernet_address, mp->lease.host_mac);
|
||||
}
|
||||
|
||||
static void vl_api_dhcp_compl_event_t_handler_json
|
||||
@ -10125,12 +10126,12 @@ api_dhcp_client_config (vat_main_t * vam)
|
||||
/* Construct the API message */
|
||||
M (DHCP_CLIENT_CONFIG, mp);
|
||||
|
||||
mp->sw_if_index = htonl (sw_if_index);
|
||||
clib_memcpy (mp->hostname, hostname, vec_len (hostname));
|
||||
vec_free (hostname);
|
||||
mp->is_add = is_add;
|
||||
mp->want_dhcp_event = disable_event ? 0 : 1;
|
||||
mp->pid = htonl (getpid ());
|
||||
mp->client.sw_if_index = htonl (sw_if_index);
|
||||
clib_memcpy (mp->client.hostname, hostname, vec_len (hostname));
|
||||
vec_free (hostname);
|
||||
mp->client.want_dhcp_event = disable_event ? 0 : 1;
|
||||
mp->client.pid = htonl (getpid ());
|
||||
|
||||
/* send it... */
|
||||
S (mp);
|
||||
|
@ -100,7 +100,6 @@ static void
|
||||
dhcp_client_addr_callback (dhcp_client_t * c)
|
||||
{
|
||||
dhcp_client_main_t *dcm = &dhcp_client_main;
|
||||
void (*fp) (u32, u32, u8 *, u8, u8, u8 *, u8 *, u8 *) = c->event_callback;
|
||||
|
||||
/* disable the feature */
|
||||
vnet_feature_enable_disable ("ip4-unicast",
|
||||
@ -147,12 +146,8 @@ dhcp_client_addr_callback (dhcp_client_t * c)
|
||||
/*
|
||||
* Call the user's event callback to report DHCP information
|
||||
*/
|
||||
if (fp)
|
||||
(*fp) (c->client_index, /* clinet index */
|
||||
c->pid, c->hostname, c->subnet_mask_width, 0, /* is_ipv6 */
|
||||
(u8 *) & c->leased_address, /* host IP address */
|
||||
(u8 *) & c->router_address, /* router IP address */
|
||||
(u8 *) (c->l2_rewrite + 6)); /* host MAC address */
|
||||
if (c->event_callback)
|
||||
c->event_callback (c->client_index, c);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -977,13 +972,14 @@ dhcp_client_add_del (dhcp_client_add_del_args_t * a)
|
||||
}
|
||||
|
||||
int
|
||||
dhcp_client_config (vlib_main_t * vm,
|
||||
dhcp_client_config (u32 is_add,
|
||||
u32 client_index,
|
||||
vlib_main_t * vm,
|
||||
u32 sw_if_index,
|
||||
u8 * hostname,
|
||||
u8 * client_id,
|
||||
u32 is_add,
|
||||
u32 client_index,
|
||||
void *event_callback, u8 set_broadcast_flag, u32 pid)
|
||||
dhcp_event_cb_t event_callback,
|
||||
u8 set_broadcast_flag, u32 pid)
|
||||
{
|
||||
dhcp_client_add_del_args_t _a, *a = &_a;
|
||||
int rv;
|
||||
@ -1061,6 +1057,22 @@ dhcp_client_config (vlib_main_t * vm,
|
||||
return rv;
|
||||
}
|
||||
|
||||
void
|
||||
dhcp_client_walk (dhcp_client_walk_cb_t cb, void *ctx)
|
||||
{
|
||||
dhcp_client_main_t *dcm = &dhcp_client_main;
|
||||
dhcp_client_t *c;
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
pool_foreach (c, dcm->clients,
|
||||
({
|
||||
if (!cb(c, ctx))
|
||||
break;
|
||||
}));
|
||||
/* *INDENT-ON* */
|
||||
|
||||
}
|
||||
|
||||
static clib_error_t *
|
||||
dhcp_client_set_command_fn (vlib_main_t * vm,
|
||||
unformat_input_t * input,
|
||||
|
@ -34,7 +34,15 @@ typedef enum
|
||||
#undef _
|
||||
} dhcp_client_state_t;
|
||||
|
||||
typedef struct
|
||||
struct dhcp_client_t_;
|
||||
|
||||
/**
|
||||
* Callback function for DHCP complete events
|
||||
*/
|
||||
typedef void (*dhcp_event_cb_t) (u32 client_index,
|
||||
const struct dhcp_client_t_ * client);
|
||||
|
||||
typedef struct dhcp_client_t_
|
||||
{
|
||||
dhcp_client_state_t state;
|
||||
|
||||
@ -78,7 +86,7 @@ typedef struct
|
||||
u8 client_hardware_address[6];
|
||||
u8 client_detect_feature_enabled;
|
||||
|
||||
void *event_callback;
|
||||
dhcp_event_cb_t event_callback;
|
||||
} dhcp_client_t;
|
||||
|
||||
typedef struct
|
||||
@ -109,7 +117,7 @@ typedef struct
|
||||
/* Information used for event callback */
|
||||
u32 client_index;
|
||||
u32 pid;
|
||||
void *event_callback;
|
||||
dhcp_event_cb_t event_callback;
|
||||
} dhcp_client_add_del_args_t;
|
||||
|
||||
extern dhcp_client_main_t dhcp_client_main;
|
||||
@ -121,13 +129,36 @@ int dhcp_client_for_us (u32 bi0,
|
||||
ip4_header_t * ip0,
|
||||
udp_header_t * u0, dhcp_header_t * dh0);
|
||||
|
||||
int dhcp_client_config (vlib_main_t * vm,
|
||||
u32 sw_if_index,
|
||||
u8 * hostname,
|
||||
u8 * client_id,
|
||||
u32 is_add,
|
||||
u32 client_index,
|
||||
void *event_callback, u8 set_broadcast_flag, u32 pid);
|
||||
/**
|
||||
* Add/Delete DHCP clients
|
||||
*/
|
||||
extern int dhcp_client_config (u32 is_add,
|
||||
u32 client_index,
|
||||
vlib_main_t * vm,
|
||||
u32 sw_if_index,
|
||||
u8 * hostname,
|
||||
u8 * client_id,
|
||||
dhcp_event_cb_t event_callback,
|
||||
u8 set_broadcast_flag, u32 pid);
|
||||
|
||||
/**
|
||||
* callback function for clients walking the DHCP client configurations
|
||||
*
|
||||
* @param client The client being visitsed
|
||||
* @param data The data passed during the call to 'walk'
|
||||
* @return !0 to continue walking 0 to stop.
|
||||
*/
|
||||
typedef int (*dhcp_client_walk_cb_t) (const dhcp_client_t * client,
|
||||
void *data);
|
||||
|
||||
/**
|
||||
* Walk (visit each) DHCP client configuration
|
||||
*
|
||||
* @param cb The callback function invoked as each client is visited
|
||||
* @param ctx Context data passed back to the client in the invocation of
|
||||
* the callback.
|
||||
*/
|
||||
extern void dhcp_client_walk (dhcp_client_walk_cb_t cb, void *ctx);
|
||||
|
||||
#endif /* included_dhcp_client_h */
|
||||
|
||||
|
@ -13,7 +13,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
option version = "1.0.1";
|
||||
option version = "2.0.0";
|
||||
|
||||
/** \brief DHCP Proxy config add / del request
|
||||
@param client_index - opaque cookie to identify the sender
|
||||
@ -62,45 +62,53 @@ autoreply define dhcp_proxy_set_vss
|
||||
u8 is_add;
|
||||
};
|
||||
|
||||
/** \brief DHCP Client config add / del request
|
||||
@param client_index - opaque cookie to identify the sender
|
||||
@param context - sender context, to match reply w/ request
|
||||
/** \brief DHCP Client config data
|
||||
@param sw_if_index - index of the interface for DHCP client
|
||||
@param hostname - hostname
|
||||
@param client_id - Client ID - option 61
|
||||
@param is_add - add the config if non-zero, else delete
|
||||
@param id - Client ID - option 61
|
||||
@param want_dhcp_event - DHCP event sent to the sender
|
||||
via dhcp_compl_event API message if non-zero
|
||||
@param set_broadcast_flag - in the DHCP Discover to control
|
||||
how the resulting OFFER is addressed.
|
||||
@param pid - sender's pid
|
||||
*/
|
||||
autoreply define dhcp_client_config
|
||||
typeonly define dhcp_client
|
||||
{
|
||||
u32 client_index;
|
||||
u32 context;
|
||||
u32 sw_if_index;
|
||||
u8 hostname[64];
|
||||
u8 client_id[64];
|
||||
u8 is_add;
|
||||
u8 id[64];
|
||||
u8 want_dhcp_event;
|
||||
u8 set_broadcast_flag;
|
||||
u32 pid;
|
||||
};
|
||||
|
||||
/** \brief Tell client about a DHCP completion event
|
||||
/** \brief DHCP Client config add / del request
|
||||
@param client_index - opaque cookie to identify the sender
|
||||
@param pid - client pid registered to receive notification
|
||||
@param context - sender context, to match reply w/ request
|
||||
@param is_add - add the config if non-zero, else delete
|
||||
@param client - client configuration data
|
||||
*/
|
||||
autoreply define dhcp_client_config
|
||||
{
|
||||
u32 client_index;
|
||||
u32 context;
|
||||
u8 is_add;
|
||||
vl_api_dhcp_client_t client;
|
||||
};
|
||||
|
||||
/** \brief Data learned by the client during the DHCP process
|
||||
@param sw_if_index - the interface on which the client is configured
|
||||
@param state - the state of the lease (see dhcp_client_state_t)
|
||||
@param is_ipv6 - if non-zero the address is ipv6, else ipv4
|
||||
@param mask_width - The length of the subnet mask assigned
|
||||
@param host_address - Host IP address
|
||||
@param router_address - Router IP address
|
||||
@param host_mac - Host MAC address
|
||||
*/
|
||||
define dhcp_compl_event
|
||||
typeonly define dhcp_lease
|
||||
{
|
||||
u32 client_index;
|
||||
u32 pid;
|
||||
u32 sw_if_index;
|
||||
u8 state;
|
||||
u8 hostname[64];
|
||||
u8 is_ipv6;
|
||||
u8 mask_width;
|
||||
@ -109,10 +117,41 @@ define dhcp_compl_event
|
||||
u8 host_mac[6];
|
||||
};
|
||||
|
||||
/** \brief Tell client about a DHCP completion event
|
||||
@param client_index - opaque cookie to identify the sender
|
||||
@param pid - client pid registered to receive notification
|
||||
@param lease - Data learned during the DHCP process;
|
||||
*/
|
||||
define dhcp_compl_event
|
||||
{
|
||||
u32 client_index;
|
||||
u32 pid;
|
||||
vl_api_dhcp_lease_t lease;
|
||||
};
|
||||
|
||||
service {
|
||||
rpc dhcp_client_config returns dhcp_client_config_reply events dhcp_compl_event;
|
||||
};
|
||||
|
||||
/** \brief Dump the DHCP client configurations
|
||||
*/
|
||||
define dhcp_client_dump
|
||||
{
|
||||
u32 client_index;
|
||||
u32 context;
|
||||
};
|
||||
|
||||
/** \brief DHCP Client details returned from dump
|
||||
* @param client - The configured client
|
||||
* @param lease - The learned lease data
|
||||
*/
|
||||
define dhcp_client_details
|
||||
{
|
||||
u32 context;
|
||||
vl_api_dhcp_client_t client;
|
||||
vl_api_dhcp_lease_t lease;
|
||||
};
|
||||
|
||||
/** \brief Dump DHCP proxy table
|
||||
@param client_index - opaque cookie to identify the sender
|
||||
@param True for IPv6 proxy table
|
||||
|
@ -48,7 +48,8 @@
|
||||
_(DHCP_PROXY_CONFIG,dhcp_proxy_config) \
|
||||
_(DHCP_PROXY_DUMP,dhcp_proxy_dump) \
|
||||
_(DHCP_PROXY_SET_VSS,dhcp_proxy_set_vss) \
|
||||
_(DHCP_CLIENT_CONFIG, dhcp_client_config)
|
||||
_(DHCP_CLIENT_CONFIG, dhcp_client_config) \
|
||||
_(DHCP_CLIENT_DUMP, dhcp_client_dump)
|
||||
|
||||
|
||||
static void
|
||||
@ -203,14 +204,56 @@ dhcp_send_details (fib_protocol_t proto,
|
||||
vl_api_send_msg (reg, (u8 *) mp);
|
||||
}
|
||||
|
||||
void
|
||||
dhcp_compl_event_callback (u32 client_index, u32 pid, u8 * hostname,
|
||||
u8 mask_width, u8 is_ipv6, u8 * host_address,
|
||||
u8 * router_address, u8 * host_mac)
|
||||
static void
|
||||
dhcp_client_lease_encode (vl_api_dhcp_lease_t * lease,
|
||||
const dhcp_client_t * client)
|
||||
{
|
||||
size_t len;
|
||||
|
||||
lease->is_ipv6 = 0; // only support IPv6 clients
|
||||
lease->sw_if_index = ntohl (client->sw_if_index);
|
||||
lease->state = client->state;
|
||||
len = clib_min (sizeof (lease->hostname) - 1, vec_len (client->hostname));
|
||||
clib_memcpy (&lease->hostname, client->hostname, len);
|
||||
lease->hostname[len] = 0;
|
||||
|
||||
lease->mask_width = client->subnet_mask_width;
|
||||
clib_memcpy (&lease->host_address[0], (u8 *) & client->leased_address, 4);
|
||||
clib_memcpy (&lease->router_address[0], (u8 *) & client->router_address, 4);
|
||||
|
||||
if (NULL != client->l2_rewrite)
|
||||
clib_memcpy (&lease->host_mac[0], client->l2_rewrite + 6, 6);
|
||||
}
|
||||
|
||||
static void
|
||||
dhcp_client_data_encode (vl_api_dhcp_client_t * vclient,
|
||||
const dhcp_client_t * client)
|
||||
{
|
||||
size_t len;
|
||||
|
||||
vclient->sw_if_index = ntohl (client->sw_if_index);
|
||||
len = clib_min (sizeof (vclient->hostname) - 1, vec_len (client->hostname));
|
||||
clib_memcpy (&vclient->hostname, client->hostname, len);
|
||||
vclient->hostname[len] = 0;
|
||||
|
||||
len = clib_min (sizeof (vclient->id) - 1,
|
||||
vec_len (client->client_identifier));
|
||||
clib_memcpy (&vclient->id, client->client_identifier, len);
|
||||
vclient->id[len] = 0;
|
||||
|
||||
if (NULL != client->event_callback)
|
||||
vclient->want_dhcp_event = 1;
|
||||
else
|
||||
vclient->want_dhcp_event = 0;
|
||||
vclient->set_broadcast_flag = client->set_broadcast_flag;
|
||||
vclient->pid = client->pid;
|
||||
}
|
||||
|
||||
static void
|
||||
dhcp_compl_event_callback (u32 client_index, const dhcp_client_t * client)
|
||||
{
|
||||
vl_api_registration_t *reg;
|
||||
vl_api_dhcp_compl_event_t *mp;
|
||||
u32 len;
|
||||
|
||||
reg = vl_api_client_index_to_registration (client_index);
|
||||
if (!reg)
|
||||
@ -218,17 +261,8 @@ dhcp_compl_event_callback (u32 client_index, u32 pid, u8 * hostname,
|
||||
|
||||
mp = vl_msg_api_alloc (sizeof (*mp));
|
||||
mp->client_index = client_index;
|
||||
mp->pid = pid;
|
||||
mp->is_ipv6 = is_ipv6;
|
||||
len = (vec_len (hostname) < 63) ? vec_len (hostname) : 63;
|
||||
clib_memcpy (&mp->hostname, hostname, len);
|
||||
mp->hostname[len] = 0;
|
||||
mp->mask_width = mask_width;
|
||||
clib_memcpy (&mp->host_address[0], host_address, 16);
|
||||
clib_memcpy (&mp->router_address[0], router_address, 16);
|
||||
|
||||
if (NULL != host_mac)
|
||||
clib_memcpy (&mp->host_mac[0], host_mac, 6);
|
||||
mp->pid = client->pid;
|
||||
dhcp_client_lease_encode (&mp->lease, client);
|
||||
|
||||
mp->_vl_msg_id = ntohs (VL_API_DHCP_COMPL_EVENT);
|
||||
|
||||
@ -240,21 +274,76 @@ static void vl_api_dhcp_client_config_t_handler
|
||||
{
|
||||
vlib_main_t *vm = vlib_get_main ();
|
||||
vl_api_dhcp_client_config_reply_t *rmp;
|
||||
u32 sw_if_index;
|
||||
int rv = 0;
|
||||
|
||||
VALIDATE_SW_IF_INDEX (mp);
|
||||
sw_if_index = ntohl (mp->client.sw_if_index);
|
||||
if (!vnet_sw_if_index_is_api_valid (sw_if_index))
|
||||
{
|
||||
rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
|
||||
goto bad_sw_if_index;
|
||||
}
|
||||
|
||||
rv = dhcp_client_config (vm, ntohl (mp->sw_if_index),
|
||||
mp->hostname, mp->client_id,
|
||||
mp->is_add, mp->client_index,
|
||||
mp->want_dhcp_event ? dhcp_compl_event_callback :
|
||||
NULL, mp->set_broadcast_flag, mp->pid);
|
||||
rv = dhcp_client_config (mp->is_add,
|
||||
mp->client_index,
|
||||
vm,
|
||||
sw_if_index,
|
||||
mp->client.hostname,
|
||||
mp->client.id,
|
||||
(mp->client.want_dhcp_event ?
|
||||
dhcp_compl_event_callback :
|
||||
NULL),
|
||||
mp->client.set_broadcast_flag, mp->client.pid);
|
||||
|
||||
BAD_SW_IF_INDEX_LABEL;
|
||||
|
||||
REPLY_MACRO (VL_API_DHCP_CLIENT_CONFIG_REPLY);
|
||||
}
|
||||
|
||||
typedef struct dhcp_client_send_walk_ctx_t_
|
||||
{
|
||||
vl_api_registration_t *reg;
|
||||
u32 context;
|
||||
} dhcp_client_send_walk_ctx_t;
|
||||
|
||||
static int
|
||||
send_dhcp_client_entry (const dhcp_client_t * client, void *arg)
|
||||
{
|
||||
dhcp_client_send_walk_ctx_t *ctx;
|
||||
vl_api_dhcp_client_details_t *mp;
|
||||
|
||||
ctx = arg;
|
||||
|
||||
mp = vl_msg_api_alloc (sizeof (*mp));
|
||||
memset (mp, 0, sizeof (*mp));
|
||||
|
||||
mp->_vl_msg_id = ntohs (VL_API_DHCP_CLIENT_DETAILS);
|
||||
mp->context = ctx->context;
|
||||
|
||||
dhcp_client_data_encode (&mp->client, client);
|
||||
dhcp_client_lease_encode (&mp->lease, client);
|
||||
|
||||
vl_api_send_msg (ctx->reg, (u8 *) mp);
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
static void
|
||||
vl_api_dhcp_client_dump_t_handler (vl_api_dhcp_client_dump_t * mp)
|
||||
{
|
||||
vl_api_registration_t *reg;
|
||||
|
||||
reg = vl_api_client_index_to_registration (mp->client_index);
|
||||
if (!reg)
|
||||
return;
|
||||
|
||||
dhcp_client_send_walk_ctx_t ctx = {
|
||||
.reg = reg,
|
||||
.context = mp->context,
|
||||
};
|
||||
dhcp_client_walk (send_dhcp_client_entry, &ctx);
|
||||
}
|
||||
|
||||
/*
|
||||
* dhcp_api_hookup
|
||||
* Add vpe's API message handlers to the table.
|
||||
|
@ -1011,13 +1011,13 @@ static void *vl_api_dhcp_client_config_t_print
|
||||
|
||||
s = format (0, "SCRIPT: dhcp_client_config ");
|
||||
|
||||
s = format (s, "sw_if_index %d ", ntohl (mp->sw_if_index));
|
||||
s = format (s, "sw_if_index %d ", ntohl (mp->client.sw_if_index));
|
||||
|
||||
s = format (s, "hostname %s ", mp->hostname);
|
||||
s = format (s, "hostname %s ", mp->client.hostname);
|
||||
|
||||
s = format (s, "want_dhcp_event %d ", mp->want_dhcp_event);
|
||||
s = format (s, "want_dhcp_event %d ", mp->client.want_dhcp_event);
|
||||
|
||||
s = format (s, "pid %d ", ntohl (mp->pid));
|
||||
s = format (s, "pid %d ", ntohl (mp->client.pid));
|
||||
|
||||
if (mp->is_add == 0)
|
||||
s = format (s, "del ");
|
||||
|
@ -1422,6 +1422,29 @@ class TestDHCP(VppTestCase):
|
||||
mactobinary(self.pg3.remote_mac),
|
||||
self.pg3.remote_ip4,
|
||||
is_add=0)
|
||||
|
||||
#
|
||||
# read the DHCP client details from a dump
|
||||
#
|
||||
clients = self.vapi.dhcp_client_dump()
|
||||
|
||||
self.assertEqual(clients[0].client.sw_if_index,
|
||||
self.pg3.sw_if_index)
|
||||
self.assertEqual(clients[0].lease.sw_if_index,
|
||||
self.pg3.sw_if_index)
|
||||
self.assertEqual(clients[0].client.hostname.rstrip('\0'),
|
||||
hostname)
|
||||
self.assertEqual(clients[0].lease.hostname.rstrip('\0'),
|
||||
hostname)
|
||||
self.assertEqual(clients[0].lease.is_ipv6, 0)
|
||||
# 0 = DISCOVER, 1 = REQUEST, 2 = BOUND
|
||||
self.assertEqual(clients[0].lease.state, 2)
|
||||
self.assertEqual(clients[0].lease.mask_width, 24)
|
||||
self.assertEqual(clients[0].lease.router_address.rstrip('\0'),
|
||||
self.pg3.remote_ip4n)
|
||||
self.assertEqual(clients[0].lease.host_address.rstrip('\0'),
|
||||
self.pg3.local_ip4n)
|
||||
|
||||
#
|
||||
# remove the DHCP config
|
||||
#
|
||||
|
@ -2298,6 +2298,9 @@ class VppPapiProvider(object):
|
||||
'is_ipv6': is_ip6,
|
||||
})
|
||||
|
||||
def dhcp_client_dump(self):
|
||||
return self.api(self.papi.dhcp_client_dump, {})
|
||||
|
||||
def dhcp_client(self,
|
||||
sw_if_index,
|
||||
hostname,
|
||||
@ -2308,13 +2311,14 @@ class VppPapiProvider(object):
|
||||
return self.api(
|
||||
self.papi.dhcp_client_config,
|
||||
{
|
||||
'sw_if_index': sw_if_index,
|
||||
'hostname': hostname,
|
||||
'client_id': client_id,
|
||||
'is_add': is_add,
|
||||
'want_dhcp_event': want_dhcp_events,
|
||||
'set_broadcast_flag': set_broadcast_flag,
|
||||
'pid': os.getpid(),
|
||||
'client': {
|
||||
'sw_if_index': sw_if_index,
|
||||
'hostname': hostname,
|
||||
'id': client_id,
|
||||
'want_dhcp_event': want_dhcp_events,
|
||||
'set_broadcast_flag': set_broadcast_flag,
|
||||
'pid': os.getpid()}
|
||||
})
|
||||
|
||||
def ip_mroute_add_del(self,
|
||||
|
Reference in New Issue
Block a user