]>
Commit | Line | Data |
---|---|---|
12471842 PL |
1 | /* |
2 | * This file is part of PowerDNS or dnsdist. | |
3 | * Copyright -- PowerDNS.COM B.V. and its contributors | |
4 | * | |
5 | * This program is free software; you can redistribute it and/or modify | |
6 | * it under the terms of version 2 of the GNU General Public License as | |
7 | * published by the Free Software Foundation. | |
8 | * | |
9 | * In addition, for the avoidance of any doubt, permission is granted to | |
10 | * link this program with OpenSSL and to (re)distribute the binaries | |
11 | * produced as the result of such linking. | |
12 | * | |
13 | * This program is distributed in the hope that it will be useful, | |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | * GNU General Public License for more details. | |
17 | * | |
18 | * You should have received a copy of the GNU General Public License | |
19 | * along with this program; if not, write to the Free Software | |
20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
21 | */ | |
886e2cf2 RG |
22 | #pragma once |
23 | ||
24 | #include <atomic> | |
25 | #include <unordered_map> | |
26 | #include "lock.hh" | |
27 | ||
1ea747c0 RG |
28 | struct DNSQuestion; |
29 | ||
886e2cf2 RG |
30 | class DNSDistPacketCache : boost::noncopyable |
31 | { | |
32 | public: | |
78e3ac9e | 33 | DNSDistPacketCache(size_t maxEntries, uint32_t maxTTL=86400, uint32_t minTTL=0, uint32_t tempFailureTTL=60, uint32_t maxNegativeTTL=3600, uint32_t staleTTL=60, bool dontAge=false, uint32_t shards=1, bool deferrableInsertLock=true, bool parseECS=false); |
886e2cf2 RG |
34 | ~DNSDistPacketCache(); |
35 | ||
78e3ac9e RG |
36 | void insert(uint32_t key, const boost::optional<Netmask>& subnet, uint16_t queryFlags, const DNSName& qname, uint16_t qtype, uint16_t qclass, const char* response, uint16_t responseLen, bool tcp, uint8_t rcode, boost::optional<uint32_t> tempFailureTTL); |
37 | bool get(const DNSQuestion& dq, uint16_t consumed, uint16_t queryId, char* response, uint16_t* responseLen, uint32_t* keyOut, boost::optional<Netmask>& subnetOut, uint32_t allowExpired=0, bool skipAging=false); | |
4275aaba RG |
38 | void purgeExpired(size_t upTo=0); |
39 | void expunge(size_t upTo=0); | |
490dc586 | 40 | void expungeByName(const DNSName& name, uint16_t qtype=QType::ANY, bool suffixMatch=false); |
886e2cf2 RG |
41 | bool isFull(); |
42 | string toString(); | |
2b3eefc3 | 43 | uint64_t getSize(); |
9e9be156 RG |
44 | uint64_t getHits() const { return d_hits; } |
45 | uint64_t getMisses() const { return d_misses; } | |
46 | uint64_t getDeferredLookups() const { return d_deferredLookups; } | |
47 | uint64_t getDeferredInserts() const { return d_deferredInserts; } | |
48 | uint64_t getLookupCollisions() const { return d_lookupCollisions; } | |
49 | uint64_t getInsertCollisions() const { return d_insertCollisions; } | |
50 | uint64_t getMaxEntries() const { return d_maxEntries; } | |
cc8cefe1 | 51 | uint64_t getTTLTooShorts() const { return d_ttlTooShorts; } |
9e9be156 | 52 | uint64_t getEntriesCount(); |
f037144c | 53 | uint64_t dump(int fd); |
886e2cf2 | 54 | |
47698274 | 55 | static uint32_t getMinTTL(const char* packet, uint16_t length, bool* seenNoDataSOA); |
78e3ac9e | 56 | static uint32_t getKey(const std::string& qname, uint16_t consumed, const unsigned char* packet, uint16_t packetLen, bool tcp); |
886e2cf2 RG |
57 | |
58 | private: | |
59 | ||
60 | struct CacheValue | |
61 | { | |
62 | time_t getTTD() const { return validity; } | |
63 | std::string value; | |
64 | DNSName qname; | |
78e3ac9e | 65 | boost::optional<Netmask> subnet; |
886e2cf2 RG |
66 | uint16_t qtype{0}; |
67 | uint16_t qclass{0}; | |
8dcdbdb1 | 68 | uint16_t queryFlags{0}; |
886e2cf2 RG |
69 | time_t added{0}; |
70 | time_t validity{0}; | |
71 | uint16_t len{0}; | |
a176d205 | 72 | bool tcp{false}; |
886e2cf2 RG |
73 | }; |
74 | ||
2b3eefc3 RG |
75 | class CacheShard |
76 | { | |
77 | public: | |
78 | CacheShard(): d_entriesCount(0) | |
79 | { | |
80 | pthread_rwlock_init(&d_lock, 0); | |
81 | } | |
82 | CacheShard(const CacheShard& old): d_entriesCount(0) | |
83 | { | |
84 | pthread_rwlock_init(&d_lock, 0); | |
85 | } | |
86 | ||
87 | void setSize(size_t maxSize) | |
88 | { | |
89 | d_map.reserve(maxSize); | |
90 | } | |
91 | ||
92 | std::unordered_map<uint32_t,CacheValue> d_map; | |
93 | pthread_rwlock_t d_lock; | |
94 | std::atomic<uint64_t> d_entriesCount; | |
95 | }; | |
96 | ||
78e3ac9e RG |
97 | static bool getClientSubnet(const char* packet, unsigned int consumed, uint16_t len, boost::optional<Netmask>& subnet); |
98 | bool cachedValueMatches(const CacheValue& cachedValue, uint16_t queryFlags, const DNSName& qname, uint16_t qtype, uint16_t qclass, bool tcp, const boost::optional<Netmask>& subnet) const; | |
2b3eefc3 | 99 | uint32_t getShardIndex(uint32_t key) const; |
78e3ac9e | 100 | void insertLocked(CacheShard& shard, uint32_t key, CacheValue& newValue); |
2b3eefc3 RG |
101 | |
102 | std::vector<CacheShard> d_shards; | |
886e2cf2 | 103 | |
886e2cf2 RG |
104 | std::atomic<uint64_t> d_deferredLookups{0}; |
105 | std::atomic<uint64_t> d_deferredInserts{0}; | |
106 | std::atomic<uint64_t> d_hits{0}; | |
107 | std::atomic<uint64_t> d_misses{0}; | |
108 | std::atomic<uint64_t> d_insertCollisions{0}; | |
109 | std::atomic<uint64_t> d_lookupCollisions{0}; | |
cc8cefe1 | 110 | std::atomic<uint64_t> d_ttlTooShorts{0}; |
2b3eefc3 | 111 | |
886e2cf2 | 112 | size_t d_maxEntries; |
2b3eefc3 RG |
113 | uint32_t d_expungeIndex{0}; |
114 | uint32_t d_shardCount; | |
886e2cf2 | 115 | uint32_t d_maxTTL; |
2714396e | 116 | uint32_t d_tempFailureTTL; |
47698274 | 117 | uint32_t d_maxNegativeTTL; |
886e2cf2 | 118 | uint32_t d_minTTL; |
1ea747c0 | 119 | uint32_t d_staleTTL; |
2b67180c | 120 | bool d_dontAge; |
2b3eefc3 | 121 | bool d_deferrableInsertLock; |
78e3ac9e | 122 | bool d_parseECS; |
886e2cf2 | 123 | }; |