]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/dnsdist.hh
update documentation a bit
[thirdparty/pdns.git] / pdns / dnsdist.hh
CommitLineData
df111b53 1#pragma once
2#include "ext/luawrapper/include/LuaContext.hpp"
3#include <time.h>
4#include "misc.hh"
5#include "iputils.hh"
6#include "dnsname.hh"
7#include <atomic>
8#include <boost/circular_buffer.hpp>
9#include <boost/program_options.hpp>
df111b53 10#include <mutex>
11#include <thread>
ecbe9133 12#include "sholder.hh"
638184e9 13
638184e9 14
df111b53 15struct StopWatch
16{
17#ifndef CLOCK_MONOTONIC_RAW
18#define CLOCK_MONOTONIC_RAW CLOCK_MONOTONIC
19#endif
20 struct timespec d_start{0,0};
21 void start() {
22 if(clock_gettime(CLOCK_MONOTONIC_RAW, &d_start) < 0)
23 unixDie("Getting timestamp");
24
25 }
26
27 double udiff() const {
28 struct timespec now;
29 if(clock_gettime(CLOCK_MONOTONIC_RAW, &now) < 0)
30 unixDie("Getting timestamp");
31
32 return 1000000.0*(now.tv_sec - d_start.tv_sec) + (now.tv_nsec - d_start.tv_nsec)/1000.0;
33 }
34
35 double udiffAndSet() {
36 struct timespec now;
37 if(clock_gettime(CLOCK_MONOTONIC_RAW, &now) < 0)
38 unixDie("Getting timestamp");
39
40 auto ret= 1000000.0*(now.tv_sec - d_start.tv_sec) + (now.tv_nsec - d_start.tv_nsec)/1000.0;
41 d_start = now;
42 return ret;
43 }
44
45};
46
47class QPSLimiter
48{
49public:
50 QPSLimiter()
51 {
52 }
53
54 QPSLimiter(unsigned int rate, unsigned int burst) : d_rate(rate), d_burst(burst), d_tokens(burst)
55 {
56 d_passthrough=false;
57 d_prev.start();
58 }
59
60 unsigned int getRate() const
61 {
62 return d_passthrough? 0 : d_rate;
63 }
64
65 int getPassed() const
66 {
67 return d_passed;
68 }
69 int getBlocked() const
70 {
71 return d_blocked;
72 }
73
ecbe9133 74 bool check() const // this is not quite fair
df111b53 75 {
76 if(d_passthrough)
77 return true;
78 auto delta = d_prev.udiffAndSet();
79
80 d_tokens += 1.0*d_rate * (delta/1000000.0);
81
82 if(d_tokens > d_burst)
83 d_tokens = d_burst;
84
85 bool ret=false;
86 if(d_tokens >= 1.0) { // we need this because burst=1 is weird otherwise
87 ret=true;
88 --d_tokens;
89 d_passed++;
90 }
91 else
92 d_blocked++;
93
94 return ret;
95 }
96private:
97 bool d_passthrough{true};
98 unsigned int d_rate;
99 unsigned int d_burst;
ecbe9133 100 mutable double d_tokens;
101 mutable StopWatch d_prev;
102 mutable unsigned int d_passed{0};
103 mutable unsigned int d_blocked{0};
df111b53 104};
105
106
107struct IDState
108{
549d63c9 109 IDState() : origFD(-1) { origDest.sin4.sin_family = 0;}
df111b53 110 IDState(const IDState& orig)
111 {
112 origFD = orig.origFD;
113 origID = orig.origID;
114 origRemote = orig.origRemote;
549d63c9 115 origDest = orig.origDest;
df111b53 116 age.store(orig.age.load());
117 }
118
2bf26975 119 int origFD; // set to <0 to indicate this state is empty // 4
120
121 ComboAddress origRemote; // 28
549d63c9 122 ComboAddress origDest; // 28
2bf26975 123 StopWatch sentTime; // 16
124 DNSName qname; // 80
125 std::atomic<uint16_t> age; // 4
126 uint16_t qtype; // 2
127 uint16_t origID; // 2
df111b53 128};
129
130struct Rings {
131 Rings()
132 {
133 clientRing.set_capacity(10000);
134 queryRing.set_capacity(10000);
135 respRing.set_capacity(10000);
136 }
137 boost::circular_buffer<ComboAddress> clientRing;
138 boost::circular_buffer<DNSName> queryRing;
139 struct Response
140 {
141 DNSName name;
142 uint16_t qtype;
143 uint8_t rcode;
144 unsigned int usec;
145 };
146 boost::circular_buffer<Response> respRing;
147 std::mutex respMutex;
148};
149
ecbe9133 150extern Rings g_rings; // XXX locking for this is still substandard, queryRing and clientRing need RW lock
df111b53 151
152struct DownstreamState
153{
154 DownstreamState(const ComboAddress& remote_);
155
156 int fd;
157 std::thread tid;
158 ComboAddress remote;
159 QPSLimiter qps;
160 vector<IDState> idStates;
161 std::atomic<uint64_t> idOffset{0};
162 std::atomic<uint64_t> sendErrors{0};
163 std::atomic<uint64_t> outstanding{0};
164 std::atomic<uint64_t> reuseds{0};
165 std::atomic<uint64_t> queries{0};
166 struct {
167 std::atomic<uint64_t> sendErrors{0};
168 std::atomic<uint64_t> reuseds{0};
169 std::atomic<uint64_t> queries{0};
170 } prev;
171 double queryLoad{0.0};
172 double dropRate{0.0};
173 double latencyUsec{0.0};
174 int order{1};
175 int weight{1};
176 StopWatch sw;
177 set<string> pools;
178 enum class Availability { Up, Down, Auto} availability{Availability::Auto};
179 bool upStatus{false};
180 bool isUp() const
181 {
182 if(availability == Availability::Down)
183 return false;
184 if(availability == Availability::Up)
185 return true;
186 return upStatus;
187 }
188 void setUp() { availability = Availability::Up; }
189 void setDown() { availability = Availability::Down; }
190 void setAuto() { availability = Availability::Auto; }
191};
192using servers_t =vector<std::shared_ptr<DownstreamState>>;
193typedef std::function<shared_ptr<DownstreamState>(const servers_t& servers, const ComboAddress& remote, const DNSName& qname, uint16_t qtype, dnsheader* dh)> policy_t;
194
195
196struct ServerPolicy
197{
198 string name;
199 policy_t policy;
200};
201
202void* responderThread(std::shared_ptr<DownstreamState> state);
203extern std::mutex g_luamutex;
204extern LuaContext g_lua;
ecbe9133 205extern std::string g_outputBuffer; // locking for this is ok, as locked by g_luamutex
df111b53 206
ecbe9133 207extern GlobalStateHolder<ServerPolicy> g_policy;
208extern GlobalStateHolder<servers_t> g_dstates;
209extern GlobalStateHolder<vector<pair<boost::variant<SuffixMatchNode,NetmaskGroup>, QPSLimiter> >> g_limiters;
210extern GlobalStateHolder<vector<pair<boost::variant<SuffixMatchNode,NetmaskGroup>, std::string> >> g_poolrules;
211extern GlobalStateHolder<SuffixMatchNode> g_suffixMatchNodeFilter;
638184e9 212extern GlobalStateHolder<NetmaskGroup> g_ACL;
2e72cc0e 213
ecbe9133 214extern ComboAddress g_serverControl; // not changed during runtime
215
216extern std::vector<ComboAddress> g_locals; // not changed at runtime
217extern std::string g_key; // in theory needs locking
218
219struct dnsheader;
220
221void controlThread(int fd, ComboAddress local);
2e72cc0e 222vector<std::function<void(void)>> setupLua(bool client);
ecbe9133 223
224
df111b53 225namespace po = boost::program_options;
226extern po::variables_map g_vm;
ecbe9133 227
228std::shared_ptr<DownstreamState> firstAvailable(const servers_t& servers, const ComboAddress& remote, const DNSName& qname, uint16_t qtype, dnsheader* dh);
229std::shared_ptr<DownstreamState> leastOutstanding(const servers_t& servers, const ComboAddress& remote, const DNSName& qname, uint16_t qtype, dnsheader* dh);
230std::shared_ptr<DownstreamState> wrandom(const servers_t& servers, const ComboAddress& remote, const DNSName& qname, uint16_t qtype, dnsheader* dh);
231std::shared_ptr<DownstreamState> roundrobin(const servers_t& servers, const ComboAddress& remote, const DNSName& qname, uint16_t qtype, dnsheader* dh);