What to do with timeouts. We keep around at most 65536 outstanding answers.
*/
+
/*
mental_clock=0;
for(;;) {
return ret;
}
-bool g_pleaseQuit;
-void pleaseQuitHandler(int)
-{
- g_pleaseQuit=true;
-}
+
+
class DNSIDManager : public boost::noncopyable
{
{
for(unsigned int i=0; i < 65536; ++i)
d_available.push_back(i);
+
}
uint16_t peakID()
} s_idmanager;
-void setSocketBuffer(int fd, int optname, uint32_t size)
-{
- uint32_t psize=0;
- socklen_t len=sizeof(psize);
-
- if(!getsockopt(fd, SOL_SOCKET, optname, (char*)&psize, &len) && psize > size) {
- cerr<<"Not decreasing socket buffer size from "<<psize<<" to "<<size<<endl;
- return;
- }
-
- if (setsockopt(fd, SOL_SOCKET, optname, (char*)&size, sizeof(size)) < 0 )
- cerr<<"Warning: unable to raise socket buffer size to "<<size<<": "<<strerror(errno)<<endl;
-}
-
-static void setSocketReceiveBuffer(int fd, uint32_t size)
-{
- setSocketBuffer(fd, SO_RCVBUF, size);
-}
-
-static void setSocketSendBuffer(int fd, uint32_t size)
-{
- setSocketBuffer(fd, SO_SNDBUF, size);
-}
-
-
struct AssignedIDTag{};
struct QuestionTag{};
> qids_t;
qids_t qids;
+
+
bool g_throttled;
unsigned int s_questions, s_origanswers, s_weanswers, s_wetimedout, s_perfect, s_mostly, s_origtimedout;
unsigned int s_weunmatched, s_origunmatched;
unsigned int s_wednserrors, s_origdnserrors, s_duplicates;
+
double DiffTime(const struct timeval& first, const struct timeval& second)
{
int seconds=second.tv_sec - first.tv_sec;
return ok;
}
-vector<uint32_t> flightTimes;
-void accountFlightTime(qids_t::const_iterator iter)
-{
- if(flightTimes.empty())
- flightTimes.resize(2050);
-
- struct timeval now;
- gettimeofday(&now, 0);
- unsigned int mdiff = 1000*DiffTime(iter->d_resentTime, now);
- if(mdiff > flightTimes.size()-2)
- mdiff= flightTimes.size()-1;
-
- flightTimes[mdiff]++;
-}
-
-uint64_t countLessThan(unsigned int msec)
-{
- uint64_t ret=0;
- for(unsigned int i = 0 ; i < msec && i < flightTimes.size() ; ++i) {
- ret += flightTimes[i];
- }
- return ret;
-}
-
-void emitFlightTimes()
+void measureResultAndClean(const QuestionIdentifier& qi)
{
- uint64_t totals = countLessThan(flightTimes.size());
- unsigned int limits[]={1, 2, 3, 4, 5, 10, 20, 30, 40, 50, 100, 200, 500, 1000, flightTimes.size()};
- uint64_t sofar=0;
- cout.setf(std::ios::fixed);
- cout.precision(2);
- for(unsigned int i =0 ; i < sizeof(limits)/sizeof(limits[0]); ++i) {
- if(limits[i]!=flightTimes.size())
- cout<<"Within "<<limits[i]<<" msec: ";
- else
- cout<<"Beyond "<<limits[i]-2<<" msec: ";
- uint64_t here = countLessThan(limits[i]);
- cout<<100.0*here/totals<<"% ("<<100.0*(here-sofar)/totals<<"%)"<<endl;
- sofar=here;
-
- }
-}
-
-void measureResultAndClean(qids_t::const_iterator iter)
-{
- const QuestionData& qd=*iter;
- accountFlightTime(iter);
+ QuestionData qd=*qids.find(qi);
set<DNSRecord> canonicOrig, canonicNew;
compactAnswerSet(qd.d_origAnswers, canonicOrig);
compactAnswerSet(qd.d_newAnswers, canonicNew);
if(!g_quiet) {
- cout<<qd.d_qi<<", orig rcode: "<<qd.d_origRcode<<", ours: "<<qd.d_newRcode;
+ cout<<qi<<", orig rcode: "<<qd.d_origRcode<<", ours: "<<qd.d_newRcode;
cout<<", "<<canonicOrig.size()<< " vs " << canonicNew.size()<<", perfect: ";
}
cout<<"\t* orig better *"<<endl;
s_origbetter++;
if(!g_quiet)
- if(s_origbetterset.insert(make_pair(qd.d_qi.d_qname, qd.d_qi.d_qtype)).second) {
- cout<<"orig better: " << qd.d_qi.d_qname<<" "<< qd.d_qi.d_qtype<<endl;
+ if(s_origbetterset.insert(make_pair(qi.d_qname, qi.d_qtype)).second) {
+ cout<<"orig better: " << qi.d_qname<<" "<< qi.d_qtype<<endl;
}
}
}
}
- int releaseID=qd.d_assignedID;
- qids.erase(iter); // qd invalid now
- s_idmanager.releaseID(releaseID);
+
+ qids.erase(qi);
+ s_idmanager.releaseID(qd.d_assignedID);
}
s_weunmatched++;
continue;
}
-
- QuestionData qd=*found; // we have to make a copy because we reinsert below
+ QuestionIdentifier qi=found->d_qi;
+ QuestionData qd=*found;
+
qd.d_newAnswers=mdp.d_answers;
qd.d_newRcode=mdp.d_header.rcode;
idindex.replace(found, qd);
if(qd.d_origRcode!=-1) {
- qids_t::const_iterator iter= qids.project<0>(found);
- measureResultAndClean(iter);
+ // cout<<"Removing entry "<<i->first<<", is done [in socket]"<<endl;
+ measureResultAndClean(qi);
}
}
catch(MOADNSException &e)
s_wednserrors++;
}
}
+
}
catch(std::exception& e)
{
- cerr<<"Receiver function died: "<<e.what()<<endl;
+ cerr<<"Receiver thread died: "<<e.what()<<endl;
exit(1);
}
catch(...)
{
- cerr<<"Receiver function died with unknown exception"<<endl;
+ cerr<<"Receiver thread died with unknown exception"<<endl;
exit(1);
}
}
}
+
void printStats(uint64_t origWaitingFor=0, uint64_t weWaitingFor=0)
{
+
format headerfmt ("%|9t|Questions - Pend. - Drop = Answers = (On time + Late) = (Err + Ok)\n");
format datafmt("%s%|9t|%d %|21t|%d %|29t|%d %|36t|%d %|47t|%d %|57t|%d %|66t|%d %|72t|%d\n");
+
cerr<<headerfmt;
cerr<<(datafmt % "Orig" % s_questions % origWaitingFor % s_orignever % s_origanswers % 0 % s_origtimedout % 0 % 0);
cerr<<(datafmt % "Refer." % s_questions % weWaitingFor % s_wenever % s_weanswers % 0 % s_wetimedout % 0 % 0);
*/
printStats(origWaitingFor, weWaitingFor);
+
pruneQids();
+
}
QuestionData qd;
try {
- // yes, we send out ALWAYS. Even if we don't do anything with it later,
- if(!dh->qr) { // this is to stress out the reference server with all the pain
- qd.d_assignedID = s_idmanager.getID();
+ if(!dh->qr) {
+ qd.d_assignedID = s_idmanager.peakID();
uint16_t tmp=dh->id;
dh->id=htons(qd.d_assignedID);
- s_socket->sendTo((const char*)pr.d_payload, pr.d_len, remote);
+ s_socket->sendTo(string(pr.d_payload, pr.d_payload + pr.d_len), remote);
sent=true;
dh->id=tmp;
}
MOADNSParser mdp((const char*)pr.d_payload, pr.d_len);
QuestionIdentifier qi=QuestionIdentifier::create(pr.getSource(), pr.getDest(), mdp);
-
+
if(!mdp.d_header.qr) {
s_questions++;
if(qids.count(qi)) {
if(!g_quiet)
- cout<<"Saw an exact duplicate question in PCAP "<<qi<< endl;
+ cout<<"Saw an exact duplicate question, "<<qi<< endl;
s_duplicates++;
- s_idmanager.releaseID(qd.d_assignedID); // release = puts at back of pool
return sent;
}
- // new question - ID assigned above already
+ // new question!
qd.d_qi=qi;
gettimeofday(&qd.d_resentTime,0);
+ qd.d_assignedID = s_idmanager.getID();
qids.insert(qd);
}
else {
s_origanswers++;
- qids_t::const_iterator iter=qids.find(qi);
- if(iter != qids.end()) {
- QuestionData qd=*iter;
+
+ if(qids.count(qi)) {
+ qids_t::const_iterator i=qids.find(qi);
+ QuestionData qd=*i;
+
+ // cout<<"Matched answer "<<qi<<endl;
qd.d_origAnswers=mdp.d_answers;
qd.d_origRcode=mdp.d_header.rcode;
s_norecursionavailable++;
qd.d_norecursionavailable=true;
}
- qids.replace(iter, qd);
+ qids.replace(i, qd);
if(qd.d_newRcode!=-1) {
- measureResultAndClean(iter);
+ // cout<<"Removing entry "<<qi<<", is done [in main loop]"<<endl;
+
+ measureResultAndClean(qi);
}
return sent;
}
catch(MOADNSException &e)
{
- s_idmanager.releaseID(qd.d_assignedID); // not added to qids for cleanup
s_origdnserrors++;
}
catch(std::out_of_range &e)
{
- s_idmanager.releaseID(qd.d_assignedID); // not added to qids for cleanup
s_origdnserrors++;
-
}
-
return sent;
}
g_quiet = g_vm["quiet"].as<bool>();
- signal(SIGINT, pleaseQuitHandler);
float speedup=g_vm["speedup"].as<float>();
g_timeoutMsec=g_vm["timeout-msec"].as<uint32_t>();
s_socket= new Socket(InterNetwork, Datagram);
s_socket->setNonBlocking();
- setSocketReceiveBuffer(s_socket->getHandle(), 2000000);
- setSocketSendBuffer(s_socket->getHandle(), 2000000);
-
+
ComboAddress remote(g_vm["target-ip"].as<string>(),
g_vm["target-port"].as<uint16_t>());
unsigned int count=0;
for(;;) {
- if(g_pleaseQuit) {
- cerr<<"Interrupted from terminal"<<endl;
- break;
- }
if(!((once++)%100))
houseKeeping();
sleep(1);
receiveFromReference();
printStats();
- emitFlightTimes();
}
catch(std::exception& e)
{