```
counter=0
servers=getServers()
-function luaroundrobin(remote, qname, qtype)
+function luaroundrobin(remote, qname, qtype, dh)
counter=counter+1
return servers[1+(counter % #servers)]
end
Incidentally, this is similar to setting: `setServerPolicy(roundrobin)`
which uses the C++ based roundrobin policy.
+To implement a split horizon, try:
+
+```
+authServer=newServer2{address="2001:888:2000:1d::2", order=12}
+-- order=12 is the current hack to make sure this server does
+-- generally get used, will be replaced by dedicated pools later
+
+function splitSetup(remote, qname, qtype, dh)
+ if(dh:getRD() == false)
+ then
+ return authServer
+ else
+ return firstAvailable(remote, qname, qtype, dh)
+ end
+end
+```
+
+This will forward queries that don't want recursion to a specific
+server, and will apply the default load balancing policy to all
+other queries.
+
Running it for real
-------------------
First run on the command line, and generate a key:
/* Known sins:
We replace g_ACL w/o locking, might crash
+ g_policy too probably
No centralized statistics
We neglect to do recvfromto() on 0.0.0.0
Receiver is currently singlethreaded (not that bad actually)
std::mutex g_luamutex;
LuaContext g_lua;
-std::function<shared_ptr<DownstreamState>(const ComboAddress& remote, const DNSName& qname, uint16_t qtype)> g_policy;
+std::function<shared_ptr<DownstreamState>(const ComboAddress& remote, const DNSName& qname, uint16_t qtype, dnsheader* dh)> g_policy;
-shared_ptr<DownstreamState> getLuaDownstream(const ComboAddress& remote, const DNSName& qname, uint16_t qtype)
-{
- //auto pickServer=g_lua.readVariable<LuaContext::LuaFunctionCaller<std::shared_ptr<DownstreamState> (void)> >("pickServer");
-
- std::lock_guard<std::mutex> lock(g_luamutex);
-
- auto pickServer=g_lua.readVariable<std::function<std::shared_ptr<DownstreamState>(ComboAddress, DNSName, uint16_t)> >("pickServer");
- return pickServer(remote, DNSName(qname), qtype);
-}
-
-shared_ptr<DownstreamState> firstAvailable(const ComboAddress& remote, const DNSName& qname, uint16_t qtype)
+shared_ptr<DownstreamState> firstAvailable(const ComboAddress& remote, const DNSName& qname, uint16_t qtype, dnsheader* dh)
{
for(auto& d : g_dstates) {
if(d->isUp() && d->qps.check())
}
else {
std::lock_guard<std::mutex> lock(g_luamutex);
- ss = g_policy(remote, qname, qtype).get();
+ ss = g_policy(remote, qname, qtype, dh).get();
}
ss->queries++;
Let's start naively.
*/
-int getTCPDownstream(DownstreamState** ds, const ComboAddress& remote, const DNSName& qname, uint16_t qtype)
+int getTCPDownstream(DownstreamState** ds, const ComboAddress& remote, const DNSName& qname, uint16_t qtype, dnsheader* dh)
{
- *ds = g_policy(remote, qname, qtype).get();
+ {
+ std::lock_guard<std::mutex> lock(g_luamutex);
+ *ds = g_policy(remote, qname, qtype, dh).get();
+ }
vinfolog("TCP connecting to downstream %s", (*ds)->remote.toStringWithPort());
int sock = SSocket((*ds)->remote.sin4.sin_family, SOCK_STREAM, 0);
ci=*citmp;
delete citmp;
- if(dsock == -1) {
-
- dsock = getTCPDownstream(&ds, ci.remote, DNSName(), 0);
- }
- else {
- vinfolog("Reusing existing TCP connection to %s", ds->remote.toStringWithPort());
- }
uint16_t qlen, rlen;
try {
ds->outstanding++;
char query[qlen];
readn2(ci.fd, query, qlen);
+ uint16_t qtype;
+ DNSName qname(query, qlen, 12, false, &qtype);
+ struct dnsheader* dh =(dnsheader*)query;
+ if(dsock == -1) {
+ dsock = getTCPDownstream(&ds, ci.remote, qname, qtype, dh);
+ }
+ else {
+ vinfolog("Reusing existing TCP connection to %s", ds->remote.toStringWithPort());
+ }
+
// FIXME: drop AXFR queries here, they confuse us
retry:;
if(!putMsgLen(dsock, qlen)) {
vinfolog("Downstream connection to %s died on us, getting a new one!", ds->remote.toStringWithPort());
close(dsock);
- dsock=getTCPDownstream(&ds, ci.remote, DNSName(), 0);
+ dsock=getTCPDownstream(&ds, ci.remote, qname, qtype, dh);
goto retry;
}
if(!getMsgLen(dsock, &rlen)) {
vinfolog("Downstream connection to %s died on us phase 2, getting a new one!", ds->remote.toStringWithPort());
close(dsock);
- dsock=getTCPDownstream(&ds, ci.remote, DNSName(), 0);
+ dsock=getTCPDownstream(&ds, ci.remote, qname, qtype, dh);
goto retry;
}
} );
- g_lua.writeFunction("setServerPolicy", [](std::function<shared_ptr<DownstreamState>(const ComboAddress&, const DNSName&, uint16_t)> func) {
+ g_lua.writeFunction("setServerPolicy", [](std::function<shared_ptr<DownstreamState>(const ComboAddress&, const DNSName&, uint16_t, dnsheader*)> func) {
g_policy = func;
});
dh.rd=v;
});
+ g_lua.registerFunction<bool(dnsheader::*)()>("getRD", [](dnsheader& dh) {
+ return (bool)dh.rd;
+ });
+
+
g_lua.registerFunction<void(dnsheader::*)(bool)>("setTC", [](dnsheader& dh, bool v) {
dh.tc=v;
});