3#include <xmlrpc-c/girerr.hpp>
11#include "log_admindb_arpwatch_exporter.h"
15constexpr uint32_t SUBNET_ID_TO_VLAN_MODULUS{10000};
19 return "ip2mac-" + ip.toText();
24 return "mac2ip-" + mac.toText(
false);
30 const uint16_t vlan = subnet_id % SUBNET_ID_TO_VLAN_MODULUS;
31 return "ip2macWithVLAN-" + std::to_string(vlan) +
'-' + ip.toText();
39 if (worker_keep_running) {
46 LOG_DEBUG(logger, 1, EXPORTER_REDIS_WORKER_START);
47 worker_keep_running =
true;
48 worker = std::make_unique<std::thread>([
this]() { run_worker(); });
53 LOG_DEBUG(logger, 1, EXPORTER_REDIS_WORKER_STOP);
54 worker_keep_running =
false;
55 worker_notify_cv.notify_all();
56 if (worker->joinable()) {
63 const std::chrono::seconds valid_lft)
65 LOG_DEBUG(logger, 10, EXPORTER_WRITE_REDIS)
66 .arg(mac.toText(
false).c_str())
67 .arg(ip4.toText().c_str());
68 std::unique_lock<std::mutex> lck{lease_queue_mtx};
69 lease_queue.emplace(mac, ip4, subnet_id, valid_lft);
71 worker_notify_cv.notify_all();
76 LOG_DEBUG(logger, 20, EXPORTER_FLUSH_LEASE_QUEUE);
78 std::unique_lock<std::mutex> lck{lease_queue_mtx};
79 while (not lease_queue.empty()) {
81 worker_notify_cv.notify_all();
87void Exporter::run_worker()
89 while (worker_keep_running) {
90 std::unique_lock<std::mutex> cv_lk{lease_queue_mtx};
91 worker_notify_cv.wait(
92 cv_lk, [
this]() {
return not lease_queue.empty() || not worker_keep_running; });
99 LOG_WARN(logger, HIREDIS_ERROR).arg(e.
what());
106 while (not lease_queue.empty()) {
107 assert(cv_lk.owns_lock());
109 const auto& lease = lease_queue.front();
113 worker_send_lease_to_redis(lease);
114 worker_send_lease_to_arpwatch(lease);
117 LOG_WARN(logger, HIREDIS_ERROR).arg(ex.
what());
121 catch (girerr::error& ex) {
122 LOG_WARN(logger, EXPORTER_RPC_ERROR).arg(ex.what());
124 catch (std::exception& ex) {
125 LOG_WARN(logger, EXPORTER_PUSH_ERROR).arg(ex.what());
134void Exporter::worker_send_lease_to_redis(
const lease4_t& lease)
136 const auto& [mac, ip, subnet_id, valid_lft] = lease;
137 std::string ip2mac_key = get_ip2mac_key(ip);
138 std::string mac2ip_key = get_mac2ip_key(mac);
139 std::string ip2macWithVLAN_key = get_ip2macWithVLAN_key(ip, subnet_id);
140 std::string mac_value = mac.toText(
false);
141 std::string ip4_value = ip.toText();
144 static_cast<std::uint32_t
>(
static_cast<double>(valid_lft.count()) *
REDIS_EXPIRE_FACT);
146 LOG_DEBUG(logger, 10, EXPORTER_SEND_REDIS)
147 .arg(ip2mac_key.c_str())
148 .arg(mac_value.c_str())
150 redis_adapter.
set(ip2mac_key, mac_value, expire);
152 LOG_DEBUG(logger, 10, EXPORTER_SEND_REDIS)
153 .arg(mac2ip_key.c_str())
154 .arg(ip4_value.c_str())
156 redis_adapter.
sadd(mac2ip_key, ip4_value, expire);
158 if (subnet_id != 0) {
159 LOG_DEBUG(logger, 10, EXPORTER_SEND_REDIS)
160 .arg(ip2macWithVLAN_key)
163 redis_adapter.
set(ip2macWithVLAN_key, mac_value, expire);
167void Exporter::worker_send_lease_to_arpwatch(
const lease4_t& lease)
169 const auto& [mac, ip4, subnet_id, valid_lft] = lease;
170 const auto vlan_id = subnet_id % SUBNET_ID_TO_VLAN_MODULUS;
virtual void push_seen_entry(const isc::dhcp::SubnetID &subnet_id, const isc::dhcp::HWAddr &mac, const isc::asiolink::IOAddress &ip4)
RPC method callers.
virtual sadd_reply_t sadd(const std::string &key, const std::string &value, const timeout_t expire=0)
virtual void connect()
Connect to the Redis server.
virtual set_reply_t set(const std::string &key, const std::string &value, const timeout_t expire=0)
virtual bool is_connected() const noexcept
A problem has occured whilst interacting with Redis.
const char * what() const noexcept
static constexpr double REDIS_EXPIRE_FACT
isc::dhcp::HWAddr mac_addr_t
static constexpr std::chrono::seconds REDIS_RECONNECT_WAIT
static constexpr std::chrono::milliseconds LEASE_QUEUE_FLUSH_WAIT
isc::dhcp::SubnetID subnet_id_t
void push_lease(const mac_addr_t &mac, const ip4_addr_t &ip4, subnet_id_t subnet_id=0, std::chrono::seconds valid_lft=DEFAULT_VALID_LFT)
isc::asiolink::IOAddress ip4_addr_t