00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 #if !defined (_P_DNSProcessor_h_)
00025 #define _P_DNSProcessor_h_
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 #include "I_EventSystem.h"
00035 
00036 #define MAX_NAMED                           32
00037 #define DEFAULT_DNS_RETRIES                 5
00038 #define MAX_DNS_RETRIES                     9
00039 #define DEFAULT_DNS_TIMEOUT                 30
00040 #define MAX_DNS_IN_FLIGHT                   2048
00041 #define DEFAULT_FAILOVER_NUMBER             (DEFAULT_DNS_RETRIES + 1)
00042 #define DEFAULT_FAILOVER_PERIOD             (DEFAULT_DNS_TIMEOUT + 30)
00043 
00044 
00045 #define DEFAULT_FAILOVER_TRY_PERIOD         (DEFAULT_DNS_TIMEOUT + 1)
00046 #define DEFAULT_DNS_SEARCH           1
00047 #define FAILOVER_SOON_RETRY          5
00048 #define NO_NAMESERVER_SELECTED       -1
00049 
00050 
00051 
00052 
00053 extern int dns_timeout;
00054 extern int dns_retries;
00055 extern int dns_search;
00056 extern int dns_failover_number;
00057 extern int dns_failover_period;
00058 extern int dns_failover_try_period;
00059 extern int dns_max_dns_in_flight;
00060 extern unsigned int dns_sequence_number;
00061 
00062 
00063 
00064 
00065 
00066 #define DNS_PERIOD                          HRTIME_MSECONDS(-100)
00067 #define DNS_DELAY_PERIOD                    HRTIME_MSECONDS(10)
00068 #define DNS_SEQUENCE_NUMBER_RESTART_OFFSET  4000
00069 #define DNS_PRIMARY_RETRY_PERIOD            HRTIME_SECONDS(5)
00070 #define DNS_PRIMARY_REOPEN_PERIOD           HRTIME_SECONDS(60)
00071 #define BAD_DNS_RESULT                      ((HostEnt*)(uintptr_t)-1)
00072 #define DEFAULT_NUM_TRY_SERVER              8
00073 
00074 
00075 #ifndef HFIXEDSZ
00076 #define HFIXEDSZ 12
00077 #endif
00078 #ifndef QFIXEDSZ
00079 #define QFIXEDSZ 4
00080 #endif
00081 
00082 
00083 
00084 
00085 #define DNS_EVENT_LOOKUP             DNS_EVENT_EVENTS_START
00086 
00087 extern int dns_fd;
00088 
00089 void *dns_udp_receiver(void *arg);
00090 
00091 
00092 
00093 enum DNS_Stats
00094 {
00095   dns_total_lookups_stat,
00096   dns_response_time_stat,
00097   dns_success_time_stat,
00098   dns_lookup_success_stat,
00099   dns_lookup_fail_stat,
00100   dns_fail_time_stat,
00101   dns_retries_stat,
00102   dns_max_retries_exceeded_stat,
00103   dns_sequence_number_stat,
00104   dns_in_flight_stat,
00105   DNS_Stat_Count
00106 };
00107 
00108 struct HostEnt;
00109 struct DNSHandler;
00110 
00111 struct RecRawStatBlock;
00112 extern RecRawStatBlock *dns_rsb;
00113 
00114 
00115 
00116 #define DNS_DEBUG_COUNT_DYN_STAT(_x, _y)                            \
00117   RecIncrRawStatCount(dns_rsb, mutex->thread_holding, (int)_x, _y)
00118 
00119 #define DNS_INCREMENT_DYN_STAT(_x)                              \
00120   RecIncrRawStatSum(dns_rsb, mutex->thread_holding, (int)_x, 1)
00121 
00122 #define DNS_DECREMENT_DYN_STAT(_x)                                \
00123   RecIncrRawStatSum(dns_rsb, mutex->thread_holding, (int)_x, -1)
00124 
00125 #define DNS_SUM_DYN_STAT(_x, _r)                                  \
00126   RecIncrRawStatSum(dns_rsb, mutex->thread_holding, (int)_x, _r)
00127 
00128 #define DNS_READ_DYN_STAT(_x, _count, _sum) do {    \
00129     RecGetRawStatSum(dns_rsb, (int)_x, &_sum);      \
00130     RecGetRawStatCount(dns_rsb, (int)_x, &_count);  \
00131   } while (0)
00132 
00133 #define DNS_SET_DYN_COUNT(_x, _count)           \
00134   RecSetRawStatCount(dns_rsb, _x, _count);
00135 
00136 #define DNS_INCREMENT_THREAD_DYN_STAT(_s, _t)   \
00137   RecIncrRawStatSum(dns_rsb, _t, (int) _s, 1);
00138 
00139 #define DNS_DECREMENT_THREAD_DYN_STAT(_s, _t)   \
00140   RecIncrRawStatSum(dns_rsb, _t, (int) _s, -1);
00141 
00142 
00143 
00144 
00145 
00146 
00147 
00148 struct DNSEntry: public Continuation
00149 {
00150   int id[MAX_DNS_RETRIES];
00151   int qtype; 
00152   HostResStyle host_res_style; 
00153   int retries;
00154   int which_ns;
00155   ink_hrtime submit_time;
00156   ink_hrtime send_time;
00157   char qname[MAXDNAME];
00158   int qname_len;
00159   int orig_qname_len;
00160   char **domains;
00161   EThread *submit_thread;
00162   Action action;
00163   Event *timeout;
00164   Ptr<HostEnt> result_ent;
00165   DNSHandler *dnsH;
00166   bool written_flag;
00167   bool once_written_flag;
00168   bool last;
00169   LINK(DNSEntry, dup_link);
00170   Que(DNSEntry, dup_link) dups;
00171 
00172   int mainEvent(int event, Event *e);
00173   int delayEvent(int event, Event *e);
00174   int post(DNSHandler *h, HostEnt *ent);
00175   int postEvent(int event, Event *e);
00176   void init(const char *x, int len, int qtype_arg, Continuation *acont, DNSProcessor::Options const& opt);
00177 
00178    DNSEntry()
00179      : Continuation(NULL),
00180        qtype(0),
00181        host_res_style(HOST_RES_NONE),
00182        retries(DEFAULT_DNS_RETRIES),
00183        which_ns(NO_NAMESERVER_SELECTED), submit_time(0), send_time(0), qname_len(0),
00184        orig_qname_len(0), domains(0), timeout(0), result_ent(0), dnsH(0), written_flag(false),
00185        once_written_flag(false), last(false)
00186   {
00187     for (int i = 0; i < MAX_DNS_RETRIES; i++)
00188       id[i] = -1;
00189     memset(qname, 0, MAXDNAME);
00190   }
00191 };
00192 
00193 
00194 typedef int (DNSEntry::*DNSEntryHandler) (int, void *);
00195 
00196 struct DNSEntry;
00197 
00198 
00199 
00200 
00201 
00202 
00203 struct DNSHandler: public Continuation
00204 {
00205 
00206   IpEndpoint ip;
00207   IpEndpoint local_ipv6; 
00208   IpEndpoint local_ipv4; 
00209   int ifd[MAX_NAMED];
00210   int n_con;
00211   DNSConnection con[MAX_NAMED];
00212   int options;
00213   Queue<DNSEntry> entries;
00214   Queue<DNSConnection> triggered;
00215   int in_flight;
00216   int name_server;
00217   int in_write_dns;
00218   HostEnt *hostent_cache;
00219 
00220   int ns_down[MAX_NAMED];
00221   int failover_number[MAX_NAMED];
00222   int failover_soon_number[MAX_NAMED];
00223   ink_hrtime crossed_failover_number[MAX_NAMED];
00224   ink_hrtime last_primary_retry;
00225   ink_hrtime last_primary_reopen;
00226 
00227   ink_res_state m_res;
00228   int txn_lookup_timeout;
00229 
00230   InkRand generator;
00231   
00232   uint64_t qid_in_flight[(USHRT_MAX+1)/64];
00233 
00234   void received_one(int i)
00235   {
00236     failover_number[i] = failover_soon_number[i] = crossed_failover_number[i] = 0;
00237   }
00238 
00239   void sent_one()
00240   {
00241     ++failover_number[name_server];
00242     Debug("dns", "sent_one: failover_number for resolver %d is %d", name_server, failover_number[name_server]);
00243     if (failover_number[name_server] >= dns_failover_number && !crossed_failover_number[name_server])
00244       crossed_failover_number[name_server] = ink_get_hrtime();
00245   }
00246 
00247   bool failover_now(int i)
00248   {
00249     if (is_debug_tag_set("dns")) {
00250       Debug("dns", "failover_now: Considering immediate failover, target time is %" PRId64 "",
00251             (ink_hrtime)HRTIME_SECONDS(dns_failover_period));
00252       Debug("dns", "\tdelta time is %" PRId64 "", (ink_get_hrtime() - crossed_failover_number[i]));
00253     }
00254     return (crossed_failover_number[i] &&
00255             ((ink_get_hrtime() - crossed_failover_number[i]) > HRTIME_SECONDS(dns_failover_period)));
00256   }
00257 
00258   bool failover_soon(int i) {
00259     return (crossed_failover_number[i] &&
00260             ((ink_get_hrtime() - crossed_failover_number[i]) >
00261              (HRTIME_SECONDS(dns_failover_try_period + failover_soon_number[i] * FAILOVER_SOON_RETRY))));
00262   }
00263 
00264   void recv_dns(int event, Event *e);
00265   int startEvent(int event, Event *e);
00266   int startEvent_sdns(int event, Event *e);
00267   int mainEvent(int event, Event *e);
00268 
00269   void open_con(sockaddr const* addr, bool failed = false, int icon = 0);
00270   void failover();
00271   void rr_failure(int ndx);
00272   void recover();
00273   void retry_named(int ndx, ink_hrtime t, bool reopen = true);
00274   void try_primary_named(bool reopen = true);
00275   void switch_named(int ndx);
00276   uint16_t get_query_id();
00277 
00278   void release_query_id(uint16_t qid) {
00279     qid_in_flight[qid >> 6] &= (uint64_t)~(0x1ULL << (qid & 0x3F));
00280   };
00281 
00282   void set_query_id_in_use(uint16_t qid) {
00283     qid_in_flight[qid >> 6] |= (uint64_t)(0x1ULL << (qid & 0x3F));
00284   };
00285 
00286   bool query_id_in_use(uint16_t qid) {
00287     return (qid_in_flight[(uint16_t)(qid) >> 6] & (uint64_t)(0x1ULL << ((uint16_t)(qid) & 0x3F))) != 0;
00288   };
00289 
00290   DNSHandler();
00291 
00292 private:
00293   
00294   void validate_ip();
00295 };
00296 
00297 
00298 
00299 
00300 
00301 
00302 struct DNSServer
00303 {
00304   IpEndpoint x_server_ip[MAXNS];
00305   char x_dns_ip_line[MAXDNAME * 2];
00306 
00307   char x_def_domain[MAXDNAME];
00308   char x_domain_srch_list[MAXDNAME];
00309 
00310   DNSHandler *x_dnsH;
00311 
00312   DNSServer()
00313   : x_dnsH(NULL)
00314   {
00315     memset(x_server_ip, 0, sizeof(x_server_ip));
00316 
00317     memset(x_def_domain, 0, MAXDNAME);
00318     memset(x_domain_srch_list, 0, MAXDNAME);
00319     memset(x_dns_ip_line, 0, MAXDNAME * 2);
00320   }
00321 };
00322 
00323 
00324 TS_INLINE DNSHandler::DNSHandler()
00325  : Continuation(NULL), n_con(0), options(0), in_flight(0), name_server(0), in_write_dns(0),
00326   hostent_cache(0), last_primary_retry(0), last_primary_reopen(0),
00327   m_res(0), txn_lookup_timeout(0), generator((uint32_t)((uintptr_t)time(NULL) ^ (uintptr_t)this))
00328 {
00329   ats_ip_invalidate(&ip);
00330   for (int i = 0; i < MAX_NAMED; i++) {
00331     ifd[i] = -1;
00332     failover_number[i] = 0;
00333     failover_soon_number[i] = 0;
00334     crossed_failover_number[i] = 0;
00335     ns_down[i] = 1;
00336     con[i].handler = this;
00337   }
00338   memset(&qid_in_flight, 0, sizeof(qid_in_flight));  
00339   SET_HANDLER(&DNSHandler::startEvent);
00340   Debug("net_epoll", "inline DNSHandler::DNSHandler()");
00341 }
00342 
00343 #define DOT_SEPARATED(_x)                                   \
00344   ((unsigned char*)&(_x))[0], ((unsigned char*)&(_x))[1],   \
00345     ((unsigned char*)&(_x))[2], ((unsigned char*)&(_x))[3]
00346 
00347 #endif