pool.second.last_change = e;
}
-bool OSDMap::is_blocklisted(const entity_addr_t& orig) const
+OSDMap::range_bits::range_bits() : ipv6(false) {
+ memset(&bits, 0, sizeof(bits));
+}
+
+OSDMap::range_bits::range_bits(const entity_addr_t& addr) : ipv6(false) {
+ memset(&bits, 0, sizeof(bits));
+ parse(addr);
+}
+
+void OSDMap::range_bits::get_ipv6_bytes(unsigned const char *addr,
+ uint64_t *upper, uint64_t *lower)
+{
+ *upper = ((uint64_t)(ntohl(*(uint32_t*)(addr)))) << 32 |
+ ((uint64_t)(ntohl(*(uint32_t*)(&addr[4]))));
+ *lower = ((uint64_t)(ntohl(*(uint32_t*)(&addr[8])))) << 32 |
+ ((uint64_t)(ntohl(*(uint32_t*)(&addr[12]))));
+}
+
+void OSDMap::range_bits::parse(const entity_addr_t& addr) {
+ // parse it into meaningful data
+ if (addr.is_ipv6()) {
+ get_ipv6_bytes(addr.in6_addr().sin6_addr.s6_addr,
+ &bits.ipv6.upper_64_bits, &bits.ipv6.lower_64_bits);
+ int32_t lower_shift = std::min(128-
+ static_cast<int32_t>(addr.get_nonce()), 64);
+ int32_t upper_shift = std::max(64- //(128-b.first.get_nonce())-64
+ static_cast<int32_t>(addr.get_nonce()), 0);
+
+ auto get_mask = [](int32_t shift) -> uint64_t {
+ if (shift >= 0 && shift < 64) {
+ return UINT64_MAX << shift;
+ }
+ return 0;
+ };
+
+ bits.ipv6.lower_mask = get_mask(lower_shift);
+ bits.ipv6.upper_mask = get_mask(upper_shift);
+ ipv6 = true;
+ } else if (addr.is_ipv4()) {
+ bits.ipv4.ip_32_bits = ntohl(addr.in4_addr().sin_addr.s_addr);
+ bits.ipv4.mask = UINT32_MAX << (32-addr.get_nonce());
+ } else {
+ // uh...
+ }
+}
+
+bool OSDMap::range_bits::matches(const entity_addr_t& addr) const {
+ if (addr.is_ipv4() && !ipv6) {
+ return ((ntohl(addr.in4_addr().sin_addr.s_addr) & bits.ipv4.mask) ==
+ (bits.ipv4.ip_32_bits & bits.ipv4.mask));
+ } else if (addr.is_ipv6() && ipv6) {
+ uint64_t upper_64, lower_64;
+ get_ipv6_bytes(addr.in6_addr().sin6_addr.s6_addr, &upper_64, &lower_64);
+ return (((upper_64 & bits.ipv6.upper_mask) ==
+ (bits.ipv6.upper_64_bits & bits.ipv6.upper_mask)) &&
+ ((lower_64 & bits.ipv6.lower_mask) ==
+ (bits.ipv6.lower_64_bits & bits.ipv6.lower_mask)));
+ }
+ return false;
+}
+
+bool OSDMap::is_blocklisted(const entity_addr_t& orig, CephContext *cct) const
{
- if (blocklist.empty()) {
+ if (cct) ldout(cct, 25) << "is_blocklisted: " << orig << dendl;
+ if (blocklist.empty() && range_blocklist.empty()) {
+ if (cct) ldout(cct, 30) << "not blocklisted: " << orig << dendl;
return false;
}
// this specific instance?
if (blocklist.count(a)) {
+ if (cct) ldout(cct, 20) << "blocklist contains " << a << dendl;
return true;
}
a.set_port(0);
a.set_nonce(0);
if (blocklist.count(a)) {
+ if (cct) ldout(cct, 20) << "blocklist contains " << a << dendl;
return true;
}
}
+ // is it in a blocklisted range?
+ for (const auto& i : calculated_ranges) {
+ bool blocked = i.second.matches(a);
+ if (blocked) {
+ if (cct) ldout(cct, 20) << "range_blocklist contains " << a << dendl;
+ return true;
+ }
+ }
+
+ if (cct) ldout(cct, 25) << "not blocklisted: " << orig << dendl;
return false;
}
-bool OSDMap::is_blocklisted(const entity_addrvec_t& av) const
+bool OSDMap::is_blocklisted(const entity_addrvec_t& av, CephContext *cct) const
{
- if (blocklist.empty())
+ if (blocklist.empty() && range_blocklist.empty())
return false;
for (auto& a : av.v) {
- if (is_blocklisted(a)) {
+ if (is_blocklisted(a, cct)) {
return true;
}
}
for (const auto &addr : inc.old_blocklist)
blocklist.erase(addr);
- if (!inc.new_range_blocklist.empty()) {
- range_blocklist.insert(inc.new_range_blocklist.begin(),
- inc.new_range_blocklist.end());
+ for (const auto& addr_p : inc.new_range_blocklist) {
+ range_blocklist.insert(addr_p);
+ calculated_ranges.emplace(addr_p.first, addr_p.first);
new_blocklist_entries = true;
}
- for (const auto &addr : inc.old_range_blocklist)
+ for (const auto &addr : inc.old_range_blocklist) {
+ calculated_ranges.erase(addr);
range_blocklist.erase(addr);
+ }
for (auto& i : inc.new_crush_node_flags) {
if (i.second) {
}
if (struct_v >= 11) {
decode(range_blocklist, bl);
+ calculated_ranges.clear();
+ for (const auto& i : range_blocklist) {
+ calculated_ranges.emplace(i.first, i.first);
+ }
}
DECODE_FINISH(bl); // osd-only data
}
std::shared_ptr< mempool::osdmap::vector<uuid_d> > osd_uuid;
mempool::osdmap::vector<osd_xinfo_t> osd_xinfo;
+ class range_bits {
+ struct ip6 {
+ uint64_t upper_64_bits, lower_64_bits;
+ uint64_t upper_mask, lower_mask;
+ };
+ struct ip4 {
+ uint32_t ip_32_bits;
+ uint32_t mask;
+ };
+ union {
+ ip6 ipv6;
+ ip4 ipv4;
+ } bits;
+ bool ipv6;
+ static void get_ipv6_bytes(unsigned const char *addr,
+ uint64_t *upper, uint64_t *lower);
+ public:
+ range_bits();
+ range_bits(const entity_addr_t& addr);
+ void parse(const entity_addr_t& addr);
+ bool matches(const entity_addr_t& addr) const;
+ };
mempool::osdmap::unordered_map<entity_addr_t,utime_t> blocklist;
mempool::osdmap::map<entity_addr_t,utime_t> range_blocklist;
+ mempool::osdmap::map<entity_addr_t,range_bits> calculated_ranges;
/// queue of snaps to remove
mempool::osdmap::map<int64_t, snap_interval_set_t> removed_snaps_queue;
const utime_t& get_created() const { return created; }
const utime_t& get_modified() const { return modified; }
- bool is_blocklisted(const entity_addr_t& a) const;
- bool is_blocklisted(const entity_addrvec_t& a) const;
+ bool is_blocklisted(const entity_addr_t& a, CephContext *cct=nullptr) const;
+ bool is_blocklisted(const entity_addrvec_t& a, CephContext *cct=nullptr) const;
void get_blocklist(std::list<std::pair<entity_addr_t,utime_t > > *bl,
std::list<std::pair<entity_addr_t,utime_t> > *rl) const;
void get_blocklist(std::set<entity_addr_t> *bl,