Show
Ignore:
Timestamp:
10/11/09 10:33:55 (4 years ago)
Author:
ahu
Message:

move to multiple query-local-addresses (4 and 6), plus implement very simple whole packet cache

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • trunk/pdns/pdns/pdns_recursor.cc

    r1416 r1426  
    2525#endif // WIN32 
    2626 
     27#include <boost/foreach.hpp> 
    2728#include "utility.hh"  
    2829#include "dns_random.hh" 
     30#include "md5.hh" 
    2931#include <iostream> 
    3032#include <errno.h> 
     
    7274bool g_logCommonErrors; 
    7375shared_ptr<PowerDNSLua> g_pdl; 
    74 using namespace boost; 
     76#include "namespaces.hh" 
    7577 
    7678#ifdef __FreeBSD__           // see cvstrac ticket #26 
     
    7880#include <semaphore.h> 
    7981#endif 
     82map<string, string> g_packetCache; 
    8083 
    8184MemRecursorCache RC; 
     
    9295map<int, ComboAddress> g_listenSocketsAddresses; // is shared across all threads right now 
    9396struct DNSComboWriter { 
    94   DNSComboWriter(const char* data, uint16_t len, const struct timeval& now) : d_mdp(data, len), d_now(now), d_tcp(false), d_socket(-1) 
     97  DNSComboWriter(const char* data, uint16_t len, const std::string& hash, const struct timeval& now) : d_mdp(data, len), d_now(now),  
     98                                                                                                       d_hash(hash), d_tcp(false), d_socket(-1) 
    9599  {} 
    96100  MOADNSParser d_mdp; 
     
    112116  struct timeval d_now; 
    113117  ComboAddress d_remote; 
     118  string d_hash; 
    114119  bool d_tcp; 
    115120  int d_socket; 
     
    173178} 
    174179 
     180vector<ComboAddress> g_localQueryAddresses4, g_localQueryAddresses6;  
     181ComboAddress g_local4("0.0.0.0"), g_local6("::"); 
     182ComboAddress getQueryLocalAddress(int family) 
     183{ 
     184  if(family==AF_INET) { 
     185    if(g_localQueryAddresses4.empty()) 
     186      return g_local4; 
     187    return g_localQueryAddresses4[dns_random(g_localQueryAddresses4.size())]; 
     188  } 
     189  else { 
     190    if(g_localQueryAddresses6.empty()) 
     191      return g_local6; 
     192    return g_localQueryAddresses6[dns_random(g_localQueryAddresses6.size())]; 
     193  } 
     194 
     195} 
    175196 
    176197void handleUDPServerResponse(int fd, FDMultiplexer::funcparam_t&); 
     
    253274    if(ret<0)  
    254275      throw AhuException("Making a socket for resolver: "+stringerror()); 
    255      
    256     static optional<ComboAddress> sin4; 
    257     if(!sin4) { 
    258       sin4=ComboAddress(::arg()["query-local-address"]); 
    259     } 
    260     static optional<ComboAddress> sin6; 
    261     if(!sin6) { 
    262       if(!::arg()["query-local-address6"].empty()) 
    263         sin6=ComboAddress(::arg()["query-local-address6"]); 
    264     } 
     276 
    265277     
    266278    int tries=10; 
     
    269281      if(tries==1)  // fall back to kernel 'random' 
    270282        port=0; 
    271        
    272       if(family==AF_INET) { 
    273         sin4->sin4.sin_port = htons(port);  
    274          
    275         if (::bind(ret, (struct sockaddr *)&*sin4, sin4->getSocklen()) >= 0)  
    276           break; 
    277       } 
    278       else { 
    279         if(!sin6) 
    280           break; 
    281         sin6->sin6.sin6_port = htons(port);  
    282          
    283         if (::bind(ret, (struct sockaddr *)&*sin6, sin6->getSocklen()) >= 0)  
    284           break; 
    285       } 
     283 
     284      ComboAddress sin=getQueryLocalAddress(family); 
     285      if (::bind(ret, (struct sockaddr *)&sin, sin.getSocklen()) >= 0)  
     286        break; 
    286287    } 
    287288    if(!tries) 
     
    602603       } 
    603604    } 
    604  
    605605    if(res<0) { 
    606606      pw.getHeader()->rcode=RCode::ServFail; 
     
    651651    if(!dc->d_tcp) { 
    652652      sendto(dc->d_socket, (const char*)&*packet.begin(), packet.size(), 0, (struct sockaddr *)(&dc->d_remote), dc->d_remote.getSocklen()); 
     653      if(pw.getHeader()->rcode==RCode::NoError || pw.getHeader()->rcode==RCode::NXDomain ) 
     654        g_packetCache[dc->d_hash]=string((const char*)&*packet.begin(), packet.size()); 
     655      else  
     656        ; //    cerr<<"rcode:" <<(int)pw.getHeader()->rcode<<endl; 
    653657    } 
    654658    else { 
     
    796800      DNSComboWriter* dc=0; 
    797801      try { 
    798         dc=new DNSComboWriter(tconn.data, tconn.qlen, g_now); 
     802        dc=new DNSComboWriter(tconn.data, tconn.qlen, string(), g_now); 
    799803      } 
    800804      catch(MOADNSException &mde) { 
     
    901905} 
    902906 
     907 
    903908void handleNewUDPQuestion(int fd, FDMultiplexer::funcparam_t& var) 
    904909{ 
     
    931936      else { 
    932937        ++g_stats.qcounter; 
    933 #if 0 
    934         uint16_t type; 
    935         char qname[256]; 
    936         try { 
    937            questionExpand(data, len, qname, sizeof(qname), type);   
    938         } 
    939         catch(std::exception &e) 
    940         { 
    941            throw MOADNSException(e.what()); 
    942         } 
     938        uint16_t tmp = dh->id; 
     939        dh->id=0; 
    943940         
    944         // must all be same length answers right now! 
    945         if((type==QType::A || type==QType::AAAA) && dh->arcount==0 && dh->ancount==0 && dh->nscount ==0 && ntohs(dh->qdcount)==1 ) { 
    946           char *record[10]; 
    947           uint16_t rlen[10]; 
    948           uint32_t ttd[10]; 
    949           int count; 
    950           if((count=RC.getDirect(g_now.tv_sec, qname, QType(type), ttd, record, rlen))) {  
    951             if(len + count*(sizeof(dnsrecordheader) + 2 + rlen[0]) > 512) 
    952               goto slow; 
    953  
    954             random_shuffle(record, &record[count]); 
    955             dh->qr=1; 
    956             dh->ra=1; 
    957             dh->ancount=ntohs(count); 
    958             for(int n=0; n < count ; ++n) { 
    959               memcpy(data+len, "\xc0\x0c", 2); // answer label pointer 
    960               len+=2; 
    961               struct dnsrecordheader drh; 
    962               drh.d_type=htons(type); 
    963               drh.d_class=htons(1); 
    964               drh.d_ttl=htonl(ttd[n] - g_now.tv_sec); 
    965               drh.d_clen=htons(rlen[n]); 
    966               memcpy(data+len, &drh, sizeof(drh)); 
    967               len+=sizeof(drh); 
    968               memcpy(data+len, record[n], rlen[n]); 
    969               len+=rlen[n]; 
    970             } 
    971             RDTSC(tsc2);             
    972             g_stats.shunted++; 
    973             sendto(fd, data, len, 0, (struct sockaddr *)(&fromaddr), fromaddr.getSocklen()); 
    974 //          cerr<<"shunted: " << (tsc2-tsc1) / 3000.0 << endl; 
    975             return; 
    976           } 
     941        MD5Summer md5s; 
     942        md5s.feed(data, len); 
     943        string hash = md5s.get(); 
     944        //      cerr<<"hash: "<<makeHexDump(hash)<<endl; 
     945        dh->id=tmp; 
     946 
     947        if(g_packetCache.count(hash)) { 
     948          g_stats.packetCacheHits++; 
     949          SyncRes::s_queries++; 
     950          string reply=g_packetCache[hash];  
     951          ((struct dnsheader*)reply.c_str())->id=tmp; 
     952          sendto(fd, reply.c_str(), reply.length(), 0, (struct sockaddr*) &fromaddr, fromaddr.getSocklen()); 
     953          return; 
    977954        } 
    978         else { 
    979           if(type!=QType::A && type!=QType::AAAA) 
    980             g_stats.noShuntWrongType++; 
    981           else 
    982             g_stats.noShuntWrongQuestion++; 
    983         } 
    984       slow: 
    985 #endif 
    986         DNSComboWriter* dc = new DNSComboWriter(data, len, g_now); 
     955 
     956        DNSComboWriter* dc = new DNSComboWriter(data, len, hash, g_now); 
    987957        dc->setSocket(fd); 
    988958        dc->setRemote(&fromaddr); 
     
    11601130  if(g_stats.qcounter && (RC.cacheHits + RC.cacheMisses) && SyncRes::s_queries && SyncRes::s_outqueries) { 
    11611131    //L<<Logger::Warning<<"stats: "<<g_stats.qcounter<<" questions, "<<RC.size()<<" cache entries, "<<SyncRes::s_negcache.size()<<" negative entries, " 
    1162     L<<Logger::Warning<<(int)((RC.cacheHits*100.0)/(RC.cacheHits+RC.cacheMisses))<<"% cache hits"<<endl; 
     1132    L<<Logger::Warning<<"stats: " <<(int)((RC.cacheHits*100.0)/(RC.cacheHits+RC.cacheMisses))<<"% cache hits"<<endl; 
    11631133    //    L<<Logger::Warning<<"stats: throttle map: "<<SyncRes::s_throttle.size()<<", ns speeds: " 
    11641134    // <<endl; // <<SyncRes::s_nsSpeeds.size()<<endl; // ", bytes: "<<RC.bytes()<<endl; 
     
    11701140    L<<Logger::Warning<<"stats: "<<g_stats.ednsPingMatches<<" ping matches, "<<g_stats.ednsPingMismatches<<" mismatches, "<< 
    11711141      g_stats.noPingOutQueries<<" outqueries w/o ping, "<< g_stats.noEdnsOutQueries<<" w/o EDNS"<<endl; 
     1142    L<<Logger::Warning<<"stats: "<<g_stats.packetCacheHits<<" packet cache hits ("<<(int)(100.0*g_stats.packetCacheHits/SyncRes::s_queries) << "%)"<<endl; 
    11721143  } 
    11731144  else if(statsWanted)  
     
    18551826  RC.d_followRFC2181=::arg().mustDo("auth-can-lower-ttl"); 
    18561827   
    1857   if(!::arg()["query-local-address6"].empty()) { 
    1858     SyncRes::s_doIPv6=true; 
    1859     L<<Logger::Error<<"Enabling IPv6 transport for outgoing queries"<<endl; 
     1828  try { 
     1829    vector<string> addrs;   
     1830    if(!::arg()["query-local-address6"].empty()) { 
     1831      SyncRes::s_doIPv6=true; 
     1832      L<<Logger::Error<<"Enabling IPv6 transport for outgoing queries"<<endl; 
     1833       
     1834      stringtok(addrs, ::arg()["query-local-address6"], ", ;"); 
     1835      BOOST_FOREACH(const string& addr, addrs) { 
     1836        g_localQueryAddresses6.push_back(ComboAddress(addr)); 
     1837      } 
     1838    } 
     1839    addrs.clear(); 
     1840    stringtok(addrs, ::arg()["query-local-address"], ", ;"); 
     1841    BOOST_FOREACH(const string& addr, addrs) { 
     1842      g_localQueryAddresses4.push_back(ComboAddress(addr)); 
     1843    } 
     1844  } 
     1845  catch(std::exception& e) { 
     1846    L<<Logger::Error<<"Assigning local query addresses: "<<e.what(); 
     1847    exit(99); 
    18601848  } 
    18611849