2 #include <pugixml/pugixml.hpp>
3 #include <boost/filesystem.hpp>
8 #include "services/services_types.h"
16 const std::vector<Ip4Address> &reserve_addresses,
17 const std::string &lease_filename,
18 boost::asio::io_context &io) :
19 subnet_(subnet), plen_(plen),
20 max_lease_update_count_(0), lease_update_count_(0),
21 lease_timeout_(kDhcpLeaseTimer), lease_filename_(lease_filename) {
26 GetTaskId(
"Agent::Services"),
41 const std::vector<Ip4Address> &reserve_addresses) {
44 bool subnet_change =
false;
62 std::set<DhcpLease>::iterator it =
85 DHCP_TRACE(Error,
"DHCP Lease not available for MAC " <<
99 std::set<DhcpLease>::const_iterator it =
103 UpdateLease(mac, it->ip_, it->lease_expiry_time_,
true);
114 std::vector<DhcpLease> changed_leases;
115 for (std::set<DhcpLease>::iterator it =
leases_.begin();
121 it->ip_.to_string());
125 if (current_time > it->lease_expiry_time_) {
126 it->released_ =
true;
128 changed_leases.push_back(*it);
138 }
else if (changed_leases.size()) {
146 uint64_t expiry,
bool released) {
150 std::set<DhcpLease>::iterator it =
154 it->lease_expiry_time_ = expiry;
155 it->released_ = released;
160 ip.to_string() <<
" " << expiry <<
" " <<
161 (released ?
"released" :
"valid"));
166 bool subnet_change) {
168 uint32_t num_bits = 1 << (32 -
plen_);
169 if (num_bits < (2 + addresses.size()))
177 ((num_bits > 8192) ? 8192 : num_bits);
179 for (std::vector<Ip4Address>::const_iterator it = addresses.begin();
180 it != addresses.end(); ++it) {
196 return address.to_ulong() & (0xFFFFFFFF >>
plen_);
200 for (std::vector<Ip4Address>::const_iterator it =
229 std::ofstream lease_ofstream;
231 std::ofstream::out | std::ofstream::trunc);
232 if (!lease_ofstream.good()) {
233 lease_ofstream.close();
238 for (std::set<DhcpLease>::const_iterator it =
leases_.begin();
241 it->lease_expiry_time_, it->released_);
244 lease_ofstream.flush();
245 lease_ofstream.close();
251 const uint64_t &expiry,
253 std::ofstream lease_ofstream;
255 if (!lease_ofstream.good()) {
256 lease_ofstream.close();
257 DHCP_TRACE(Error,
"Cannot open DHCP Lease file for writing : " <<
264 lease_ofstream.flush();
265 lease_ofstream.close();
269 std::ofstream lease_ofstream;
271 if (!lease_ofstream.good()) {
272 lease_ofstream.close();
273 DHCP_TRACE(Error,
"Cannot open DHCP Lease file for writing : "
278 for (std::vector<DhcpLease>::const_iterator it = leases.begin();
279 it != leases.end(); ++it) {
281 it->lease_expiry_time_, it->released_);
284 lease_ofstream.flush();
285 lease_ofstream.close();
290 const uint64_t &expiry,
bool released) {
291 lease_ofstream <<
"<lease>";
292 lease_ofstream <<
" <mac>" << mac.
ToString() <<
"</mac>";
293 lease_ofstream <<
" <ip>" << ip.to_string() <<
"</ip>";
294 lease_ofstream <<
" <expiry>" << expiry <<
"</expiry>";
295 lease_ofstream <<
" <released>" <<
296 (released ?
"true" :
"false") <<
"</released>";
297 lease_ofstream <<
" </lease>" << std::endl;
299 if (!lease_ofstream.good()) {
301 " failed : " << mac.
ToString() <<
" " << ip.to_string() <<
302 (released ?
" released" :
" valid"));
316 DHCP_TRACE(Error,
"Cannot open DHCP Lease file for reading : " <<
321 ifile.seekg(0, std::ios::end);
322 leases.reserve(ifile.tellg());
323 ifile.seekg(0, std::ios::beg);
325 leases.assign((std::istreambuf_iterator<char>(ifile)),
326 std::istreambuf_iterator<char>());
334 std::istringstream sstream(leases);
336 xml_parse_result result = xdoc.load(sstream);
338 DHCP_TRACE(Error,
"Unable to load DHCP leases. status=" <<
339 result.status <<
", offset=" << result.offset);
343 for (xml_node root = xdoc.first_child(); root; root = root.next_sibling()) {
344 if (strcmp(root.name(),
"lease") == 0) {
354 boost::system::error_code ec;
355 bool released =
false;
357 for (xml_node root = lease.first_child(); root; root = root.next_sibling()) {
358 if (strcmp(root.name(),
"mac") == 0) {
364 if (strcmp(root.name(),
"ip") == 0) {
365 ip = Ip4Address::from_string(root.child_value(), ec);
370 if (strcmp(root.name(),
"expiry") == 0) {
372 expiry = strtoull(root.child_value(), &endp, 10);
373 while (isspace(*endp)) endp++;
378 if (strcmp(root.name(),
"released") == 0) {
379 if (strcmp(root.child_value(),
"true") == 0)
384 if (mac.
IsZero() || ip.is_unspecified() || error) {
386 ip.to_string() <<
" " << expiry);
393 void ShowGwDhcpLeases::HandleRequest()
const {
394 std::vector<GwDhcpLeases> lease_list;
397 for (DhcpProto::LeaseManagerMap::const_iterator it = lease_mgr.begin();
398 it != lease_mgr.end(); ++it) {
399 GwDhcpLeases gw_leases;
400 std::vector<DhcpLeaseData> out_lease_data;
401 const std::set<DhcpLeaseDb::DhcpLease> &lease_data =
402 it->second->leases();
403 for (std::set<DhcpLeaseDb::DhcpLease>::const_iterator lit =
404 lease_data.begin(); lit != lease_data.end(); ++lit) {
407 data.mac = lit->mac_.ToString();
408 data.ip = lit->ip_.to_string();
409 data.expiry_us = (lit->lease_expiry_time_ > current_time) ?
410 (lit->lease_expiry_time_ - current_time) : 0;
411 data.released = lit->released_ ?
"yes" :
"no";
412 out_lease_data.push_back(data);
415 gw_leases.physical_interface = vmi->
parent()->
name();
416 gw_leases.vm_interface = vmi->
name();
417 gw_leases.leases = out_lease_data;
418 lease_list.push_back(gw_leases);
421 GwDhcpLeasesResponse *resp =
new GwDhcpLeasesResponse();
422 resp->set_context(context());
423 resp->set_gw_leases(lease_list);
void PersistLeaseRecords(const std::vector< DhcpLease > &leases)
static Agent * GetInstance()
const std::set< DhcpLease > & leases() const
Bitmap released_lease_bitmap_
void IndexToAddress(size_t index, Ip4Address *address) const
bool IsIp4SubnetMember(const Ip4Address &ip, const Ip4Address &prefix_ip, uint16_t plen)
#define DHCP_TRACE(obj, arg)
void ParseLeaseFile(const std::string &leases)
void Update(const Ip4Address &subnet, uint8_t plen, const std::vector< Ip4Address > &reserve_addresses)
void ParseLease(const pugi::xml_node &lease)
std::set< DhcpLease > leases_
const LeaseManagerMap & lease_manager() const
void ReserveAddresses(const std::vector< Ip4Address > &addresses, bool subnet_change)
void WriteLeaseRecord(std::ofstream &lease_ofstream, const MacAddress &mac, const Ip4Address &ip, const uint64_t &expiry, bool released)
std::string ToString() const
void set_lease_timeout(uint32_t timeout)
DhcpProto * GetDhcpProto() const
void PersistLeaseRecord(const MacAddress &mac, const Ip4Address &ip, const uint64_t &expiry, bool released)
std::string lease_filename_
static TaskScheduler * GetInstance()
bool Allocate(const MacAddress &mac, Ip4Address *address, uint64_t lease)
size_t AddressToIndex(const Ip4Address &address) const
static Timer * CreateTimer(boost::asio::io_context &service, const std::string &name, int task_id=Timer::GetTimerTaskId(), int task_instance=Timer::GetTimerInstanceId(), bool delete_on_completion=false)
void UpdateLease(const MacAddress &mac, const Ip4Address &ip, uint64_t expiry, bool released)
boost::asio::ip::address_v4 Ip4Address
uint32_t lease_update_count_
bool IsReservedAddress(const Ip4Address &address) const
std::vector< Ip4Address > reserve_addresses_
Ip4Address subnet() const
bool Start(int time, Handler handler, ErrorHandler error_handler=NULL)
bool Release(const MacAddress &mac)
void ReadLeaseFile(std::string &leases)
const std::string & name() const
static uint64_t ClockMonotonicUsec()
DhcpLeaseDb(const Ip4Address &subnet, uint8_t plen, const std::vector< Ip4Address > &reserve_addresses, const std::string &lease_filename, boost::asio::io_context &io)
static MacAddress FromString(const std::string &str, boost::system::error_code *error=NULL)
std::map< Interface *, DhcpLeaseDb * > LeaseManagerMap
const Interface * parent() const
static bool DeleteTimer(Timer *Timer)
uint32_t max_lease_update_count_