From f0114d6b95211fc1f07fc62d560dd3c04ec9a72b Mon Sep 17 00:00:00 2001 From: Remi Gacogne Date: Fri, 16 Apr 2021 15:38:55 +0200 Subject: [PATCH] dnsdist: Move the eBPF filter class to LockGuarded --- pdns/bpf-filter.cc | 108 +++++++++++++++++++------------------ pdns/bpf-filter.hh | 26 ++++----- pdns/bpf-filter.main.ebpf | 8 +-- pdns/bpf-filter.qname.ebpf | 2 +- 4 files changed, 74 insertions(+), 70 deletions(-) diff --git a/pdns/bpf-filter.cc b/pdns/bpf-filter.cc index 7f24588c46..59912dbeb1 100644 --- a/pdns/bpf-filter.cc +++ b/pdns/bpf-filter.cc @@ -139,25 +139,26 @@ struct QNameValue uint16_t qtype; }; -BPFFilter::BPFFilter(uint32_t maxV4Addresses, uint32_t maxV6Addresses, uint32_t maxQNames): d_maxV4(maxV4Addresses), d_maxV6(maxV6Addresses), d_maxQNames(maxQNames) +BPFFilter::BPFFilter(uint32_t maxV4Addresses, uint32_t maxV6Addresses, uint32_t maxQNames): d_maps(Maps()), d_maxV4(maxV4Addresses), d_maxV6(maxV6Addresses), d_maxQNames(maxQNames) { - d_v4map.fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(uint32_t), sizeof(uint64_t), (int) maxV4Addresses); - if (d_v4map.fd == -1) { + auto maps = d_maps.lock(); + maps->d_v4map.fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(uint32_t), sizeof(uint64_t), (int) maxV4Addresses); + if (maps->d_v4map.fd == -1) { throw std::runtime_error("Error creating a BPF v4 map of size " + std::to_string(maxV4Addresses) + ": " + stringerror()); } - d_v6map.fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(struct KeyV6), sizeof(uint64_t), (int) maxV6Addresses); - if (d_v6map.fd == -1) { + maps->d_v6map.fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(struct KeyV6), sizeof(uint64_t), (int) maxV6Addresses); + if (maps->d_v6map.fd == -1) { throw std::runtime_error("Error creating a BPF v6 map of size " + std::to_string(maxV6Addresses) + ": " + stringerror()); } - d_qnamemap.fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(struct QNameKey), sizeof(struct QNameValue), (int) maxQNames); - if (d_qnamemap.fd == -1) { + maps->d_qnamemap.fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(struct QNameKey), sizeof(struct QNameValue), (int) maxQNames); + if (maps->d_qnamemap.fd == -1) { throw std::runtime_error("Error creating a BPF qname map of size " + std::to_string(maxQNames) + ": " + stringerror()); } - d_filtermap.fd = bpf_create_map(BPF_MAP_TYPE_PROG_ARRAY, sizeof(uint32_t), sizeof(uint32_t), 1); - if (d_filtermap.fd == -1) { + maps->d_filtermap.fd = bpf_create_map(BPF_MAP_TYPE_PROG_ARRAY, sizeof(uint32_t), sizeof(uint32_t), 1); + if (maps->d_filtermap.fd == -1) { throw std::runtime_error("Error creating a BPF program map of size 1: " + stringerror()); } @@ -188,7 +189,7 @@ BPFFilter::BPFFilter(uint32_t maxV4Addresses, uint32_t maxV6Addresses, uint32_t } uint32_t key = 0; - int res = bpf_update_elem(d_filtermap.fd, &key, &d_qnamefilter.fd, BPF_ANY); + int res = bpf_update_elem(maps->d_filtermap.fd, &key, &d_qnamefilter.fd, BPF_ANY); if (res != 0) { throw std::runtime_error("Error updating BPF filters map: " + stringerror()); } @@ -218,19 +219,19 @@ void BPFFilter::block(const ComboAddress& addr) int res = 0; if (addr.isIPv4()) { uint32_t key = htonl(addr.sin4.sin_addr.s_addr); - if (d_v4Count >= d_maxV4) { + auto maps = d_maps.lock(); + if (maps->d_v4Count >= d_maxV4) { throw std::runtime_error("Table full when trying to block " + addr.toString()); } - std::lock_guard lock(d_mutex); - res = bpf_lookup_elem(d_v4map.fd, &key, &counter); + res = bpf_lookup_elem(maps->d_v4map.fd, &key, &counter); if (res != -1) { throw std::runtime_error("Trying to block an already blocked address: " + addr.toString()); } - res = bpf_update_elem(d_v4map.fd, &key, &counter, BPF_NOEXIST); + res = bpf_update_elem(maps->d_v4map.fd, &key, &counter, BPF_NOEXIST); if (res == 0) { - d_v4Count++; + maps->d_v4Count++; } } else if (addr.isIPv6()) { @@ -240,19 +241,19 @@ void BPFFilter::block(const ComboAddress& addr) key[idx] = addr.sin6.sin6_addr.s6_addr[idx]; } - if (d_v6Count >= d_maxV6) { + auto maps = d_maps.lock(); + if (maps->d_v6Count >= d_maxV6) { throw std::runtime_error("Table full when trying to block " + addr.toString()); } - std::lock_guard lock(d_mutex); - res = bpf_lookup_elem(d_v6map.fd, &key, &counter); + res = bpf_lookup_elem(maps->d_v6map.fd, &key, &counter); if (res != -1) { throw std::runtime_error("Trying to block an already blocked address: " + addr.toString()); } - res = bpf_update_elem(d_v6map.fd, key, &counter, BPF_NOEXIST); + res = bpf_update_elem(maps->d_v6map.fd, key, &counter, BPF_NOEXIST); if (res == 0) { - d_v6Count++; + maps->d_v6Count++; } } @@ -266,10 +267,10 @@ void BPFFilter::unblock(const ComboAddress& addr) int res = 0; if (addr.isIPv4()) { uint32_t key = htonl(addr.sin4.sin_addr.s_addr); - std::lock_guard lock(d_mutex); - res = bpf_delete_elem(d_v4map.fd, &key); + auto maps = d_maps.lock(); + res = bpf_delete_elem(maps->d_v4map.fd, &key); if (res == 0) { - d_v4Count--; + maps->d_v4Count--; } } else if (addr.isIPv6()) { @@ -279,10 +280,10 @@ void BPFFilter::unblock(const ComboAddress& addr) key[idx] = addr.sin6.sin6_addr.s6_addr[idx]; } - std::lock_guard lock(d_mutex); - res = bpf_delete_elem(d_v6map.fd, key); + auto maps = d_maps.lock(); + res = bpf_delete_elem(maps->d_v6map.fd, key); if (res == 0) { - d_v6Count--; + maps->d_v6Count--; } } @@ -307,19 +308,19 @@ void BPFFilter::block(const DNSName& qname, uint16_t qtype) memcpy(key.qname, keyStr.c_str(), keyStr.size()); { - std::lock_guard lock(d_mutex); - if (d_qNamesCount >= d_maxQNames) { + auto maps = d_maps.lock(); + if (maps->d_qNamesCount >= d_maxQNames) { throw std::runtime_error("Table full when trying to block " + qname.toLogString()); } - int res = bpf_lookup_elem(d_qnamemap.fd, &key, &value); + int res = bpf_lookup_elem(maps->d_qnamemap.fd, &key, &value); if (res != -1) { throw std::runtime_error("Trying to block an already blocked qname: " + qname.toLogString()); } - res = bpf_update_elem(d_qnamemap.fd, &key, &value, BPF_NOEXIST); + res = bpf_update_elem(maps->d_qnamemap.fd, &key, &value, BPF_NOEXIST); if (res == 0) { - d_qNamesCount++; + maps->d_qNamesCount++; } if (res != 0) { @@ -340,11 +341,10 @@ void BPFFilter::unblock(const DNSName& qname, uint16_t qtype) memcpy(key.qname, keyStr.c_str(), keyStr.size()); { - std::lock_guard lock(d_mutex); - - int res = bpf_delete_elem(d_qnamemap.fd, &key); + auto maps = d_maps.lock(); + int res = bpf_delete_elem(maps->d_qnamemap.fd, &key); if (res == 0) { - d_qNamesCount--; + maps->d_qNamesCount--; } else { throw std::runtime_error("Error removing qname address " + qname.toLogString() + ": " + stringerror()); @@ -355,7 +355,10 @@ void BPFFilter::unblock(const DNSName& qname, uint16_t qtype) std::vector > BPFFilter::getAddrStats() { std::vector > result; - result.reserve(d_v4Count + d_v6Count); + { + auto maps = d_maps.lock(); + result.reserve(maps->d_v4Count + maps->d_v6Count); + } sockaddr_in v4Addr; memset(&v4Addr, 0, sizeof(v4Addr)); @@ -374,29 +377,29 @@ std::vector > BPFFilter::getAddrStats() static_assert(sizeof(v6Addr.sin6_addr.s6_addr) == sizeof(v6Key), "POSIX mandates s6_addr to be an array of 16 uint8_t"); memset(&v6Key, 0, sizeof(v6Key)); - std::lock_guard lock(d_mutex); - int res = bpf_get_next_key(d_v4map.fd, &v4Key, &nextV4Key); + auto maps = d_maps.lock(); + int res = bpf_get_next_key(maps->d_v4map.fd, &v4Key, &nextV4Key); while (res == 0) { v4Key = nextV4Key; - if (bpf_lookup_elem(d_v4map.fd, &v4Key, &value) == 0) { + if (bpf_lookup_elem(maps->d_v4map.fd, &v4Key, &value) == 0) { v4Addr.sin_addr.s_addr = ntohl(v4Key); result.push_back(make_pair(ComboAddress(&v4Addr), value)); } - res = bpf_get_next_key(d_v4map.fd, &v4Key, &nextV4Key); + res = bpf_get_next_key(maps->d_v4map.fd, &v4Key, &nextV4Key); } - res = bpf_get_next_key(d_v6map.fd, &v6Key, &nextV6Key); + res = bpf_get_next_key(maps->d_v6map.fd, &v6Key, &nextV6Key); while (res == 0) { - if (bpf_lookup_elem(d_v6map.fd, &nextV6Key, &value) == 0) { + if (bpf_lookup_elem(maps->d_v6map.fd, &nextV6Key, &value) == 0) { memcpy(&v6Addr.sin6_addr.s6_addr, &nextV6Key, sizeof(nextV6Key)); result.push_back(make_pair(ComboAddress(&v6Addr), value)); } - res = bpf_get_next_key(d_v6map.fd, &nextV6Key, &nextV6Key); + res = bpf_get_next_key(maps->d_v6map.fd, &nextV6Key, &nextV6Key); } return result; } @@ -404,23 +407,22 @@ std::vector > BPFFilter::getAddrStats() std::vector > BPFFilter::getQNameStats() { std::vector > result; - result.reserve(d_qNamesCount); struct QNameKey key = { { 0 } }; struct QNameKey nextKey = { { 0 } }; struct QNameValue value; - std::lock_guard lock(d_mutex); - - int res = bpf_get_next_key(d_qnamemap.fd, &key, &nextKey); + auto maps = d_maps.lock(); + result.reserve(maps->d_qNamesCount); + int res = bpf_get_next_key(maps->d_qnamemap.fd, &key, &nextKey); while (res == 0) { - if (bpf_lookup_elem(d_qnamemap.fd, &nextKey, &value) == 0) { + if (bpf_lookup_elem(maps->d_qnamemap.fd, &nextKey, &value) == 0) { nextKey.qname[sizeof(nextKey.qname) - 1 ] = '\0'; result.push_back(std::make_tuple(DNSName((const char*) nextKey.qname, sizeof(nextKey.qname), 0, false), value.qtype, value.counter)); } - res = bpf_get_next_key(d_qnamemap.fd, &nextKey, &nextKey); + res = bpf_get_next_key(maps->d_qnamemap.fd, &nextKey, &nextKey); } return result; } @@ -431,8 +433,8 @@ uint64_t BPFFilter::getHits(const ComboAddress& requestor) if (requestor.isIPv4()) { uint32_t key = htonl(requestor.sin4.sin_addr.s_addr); - std::lock_guard lock(d_mutex); - int res = bpf_lookup_elem(d_v4map.fd, &key, &counter); + auto maps = d_maps.lock(); + int res = bpf_lookup_elem(maps->d_v4map.fd, &key, &counter); if (res == 0) { return counter; } @@ -444,8 +446,8 @@ uint64_t BPFFilter::getHits(const ComboAddress& requestor) key[idx] = requestor.sin6.sin6_addr.s6_addr[idx]; } - std::lock_guard lock(d_mutex); - int res = bpf_lookup_elem(d_v6map.fd, &key, &counter); + auto maps = d_maps.lock(); + int res = bpf_lookup_elem(maps->d_v6map.fd, &key, &counter); if (res == 0) { return counter; } diff --git a/pdns/bpf-filter.hh b/pdns/bpf-filter.hh index 1bd543e626..abf805e4c2 100644 --- a/pdns/bpf-filter.hh +++ b/pdns/bpf-filter.hh @@ -22,9 +22,8 @@ #pragma once #include "config.h" -#include - #include "iputils.hh" +#include "lock.hh" class BPFFilter { @@ -52,18 +51,21 @@ private: } int fd{-1}; }; - std::mutex d_mutex; + struct Maps + { + FDWrapper d_v4map; + FDWrapper d_v6map; + FDWrapper d_qnamemap; + FDWrapper d_filtermap; + uint32_t d_v4Count{0}; + uint32_t d_v6Count{0}; + uint32_t d_qNamesCount{0}; + }; + LockGuarded d_maps; + FDWrapper d_mainfilter; + FDWrapper d_qnamefilter; uint32_t d_maxV4; uint32_t d_maxV6; uint32_t d_maxQNames; - uint32_t d_v4Count{0}; - uint32_t d_v6Count{0}; - uint32_t d_qNamesCount{0}; - FDWrapper d_v4map; - FDWrapper d_v6map; - FDWrapper d_qnamemap; - FDWrapper d_filtermap; - FDWrapper d_mainfilter; - FDWrapper d_qnamefilter; #endif /* HAVE_EBPF */ }; diff --git a/pdns/bpf-filter.main.ebpf b/pdns/bpf-filter.main.ebpf index 452a7d33b4..a8ffa37ad1 100644 --- a/pdns/bpf-filter.main.ebpf +++ b/pdns/bpf-filter.main.ebpf @@ -6,7 +6,7 @@ BPF_JMP_IMM(BPF_JEQ,BPF_REG_1,ntohs(0x86dd),11), BPF_JMP_IMM(BPF_JNE,BPF_REG_1,ntohs(0x0800),109), BPF_LD_ABS(BPF_W,-2097126), BPF_STX_MEM(BPF_W,BPF_REG_10,BPF_REG_0,-256), -BPF_LD_MAP_FD(BPF_REG_1,d_v4map.fd), +BPF_LD_MAP_FD(BPF_REG_1,maps->d_v4map.fd), BPF_MOV64_REG(BPF_REG_2,BPF_REG_10), BPF_ALU64_IMM(BPF_ADD,BPF_REG_2,-256), BPF_RAW_INSN(BPF_JMP|BPF_CALL,0,0,0,BPF_FUNC_map_lookup_elem), @@ -45,7 +45,7 @@ BPF_LD_ABS(BPF_B,-2097116), BPF_STX_MEM(BPF_B,BPF_REG_10,BPF_REG_0,-242), BPF_LD_ABS(BPF_B,-2097115), BPF_STX_MEM(BPF_B,BPF_REG_10,BPF_REG_0,-241), -BPF_LD_MAP_FD(BPF_REG_1,d_v6map.fd), +BPF_LD_MAP_FD(BPF_REG_1,maps->d_v6map.fd), BPF_MOV64_REG(BPF_REG_2,BPF_REG_10), BPF_ALU64_IMM(BPF_ADD,BPF_REG_2,-256), BPF_RAW_INSN(BPF_JMP|BPF_CALL,0,0,0,BPF_FUNC_map_lookup_elem), @@ -97,7 +97,7 @@ BPF_JMP_IMM(BPF_JGT,BPF_REG_8,63,17), BPF_JMP_IMM(BPF_JNE,BPF_REG_8,0,18), BPF_LD_ABS(BPF_H,21), BPF_MOV64_REG(BPF_REG_6,BPF_REG_0), -BPF_LD_MAP_FD(BPF_REG_1,d_qnamemap.fd), +BPF_LD_MAP_FD(BPF_REG_1,maps->d_qnamemap.fd), BPF_MOV64_REG(BPF_REG_2,BPF_REG_10), BPF_ALU64_IMM(BPF_ADD,BPF_REG_2,-256), BPF_RAW_INSN(BPF_JMP|BPF_CALL,0,0,0,BPF_FUNC_map_lookup_elem), @@ -128,7 +128,7 @@ BPF_ALU64_IMM(BPF_ADD,BPF_REG_8,-1), BPF_STX_MEM(BPF_W,BPF_REG_6,BPF_REG_8,60), BPF_ALU64_IMM(BPF_AND,BPF_REG_1,255), BPF_STX_MEM(BPF_W,BPF_REG_6,BPF_REG_1,56), -BPF_LD_MAP_FD(BPF_REG_2,d_filtermap.fd), +BPF_LD_MAP_FD(BPF_REG_2,maps->d_filtermap.fd), BPF_MOV64_REG(BPF_REG_1,BPF_REG_6), BPF_MOV64_IMM(BPF_REG_3,0), BPF_RAW_INSN(BPF_JMP|BPF_CALL,0,0,0,BPF_FUNC_tail_call), diff --git a/pdns/bpf-filter.qname.ebpf b/pdns/bpf-filter.qname.ebpf index 22b4465ff2..febb7b862c 100644 --- a/pdns/bpf-filter.qname.ebpf +++ b/pdns/bpf-filter.qname.ebpf @@ -4078,7 +4078,7 @@ BPF_MOV64_IMM(BPF_REG_9,255), BPF_ALU64_REG(BPF_ADD,BPF_REG_9,BPF_REG_7), BPF_RAW_INSN(BPF_LD|BPF_IND|BPF_H,BPF_REG_0,BPF_REG_9,0,0), BPF_MOV64_REG(BPF_REG_6,BPF_REG_0), -BPF_LD_MAP_FD(BPF_REG_1,d_qnamemap.fd), +BPF_LD_MAP_FD(BPF_REG_1,maps->d_qnamemap.fd), BPF_MOV64_REG(BPF_REG_2,BPF_REG_10), BPF_ALU64_IMM(BPF_ADD,BPF_REG_2,-256), BPF_RAW_INSN(BPF_JMP|BPF_CALL,0,0,0,BPF_FUNC_map_lookup_elem), -- 2.47.2