def sendloop(ns, busy_loop=False): geotimes = options.delta*slottimes set_affinity('sendloop') time_time = time.time # faster: http://wiki.python.org/moin/PythonSpeed/PerformanceTips time_sleep = time.sleep if ns.cnum: pnum = ns.cnum else: pnum = options.pnum INFO('expected run time', '~%.2f s (mean inter-probe time %.2e s)' % (geotimes[-1], options.delta/options.rate)) if geotimes[-1]/60/60>4: WARN('WARNING', 'stationarity may not hold!') # notify receiver that we are ready to send and block until # receiver process says it is ready ns.SND_READY=True while not ns.RCV_READY: time.sleep(0.1) DEBUG('READY', __name__) payload_rest = '8'*PKT_ARRAY_APPEND try: t_start = time_time() geotimes += t_start pkt = ''.join([pkts[0],payload_rest]) if busy_loop==True: for i in xrange(1,pnum): sendpacket(pkt) pkt = ''.join([pkts[i],payload_rest]) # append payload while (time_time() < geotimes[i]): pass else: for i in xrange(1,pnum): sendpacket(pkt) pkt = ''.join([pkts[i],payload_rest]) # append payload time_sleep(np.max((geotimes[i]-time_time(),0.0))) # reduce the load at the expence of accuracy sendpacket(pkt) # send the last prepared packet except KeyboardInterrupt: pass t_total = time_time() - t_start print '\a', #s.close() # close socket DEBUG("sender runtime:\t %.8f s" % (t_total))
def rcvloop(data_pipe, ns, geotimes=None): """receive ICMP packets from pcap, extract sequence number and timestamp and forward to parser over pipe q""" if ns.cnum: pnum = ns.cnum else: pnum = options.pnum hphelper.set_affinity("rcvloop") ttl = None struct_unpack = struct.unpack def pcap_cb(time, pkt): (icmp_type,) = struct_unpack("!B", pkt[34 : 34 + 1]) (seq, slot) = struct_unpack("!LL", pkt[50:58]) # ICMP (offset 34) + 16:50+4+4 if icmp_type == 8: # ICMP echo request s_times[seq] = time # store send time elif icmp_type == 0: # ICMP echo reply snd_time = s_times[seq] # use captured send time to calculate RTT data_pipe.send((seq, slot, time - snd_time)) # send to parser process # (ttl,) = struct_unpack('!B',pkt[22:22+1]) # 14 Ethernet 14 + 8 IP DEBUG("starting receiver ", __name__) # init empty numpy arrays to store snd/rcv times s_times = -1.0 * np.ones(pnum) try: po = pcap.pcap(options.eth, snaplen=80, immediate=False, timeout_ms=3000) # timeout_ms works with dispatch only po.setfilter("(icmp[icmptype] == icmp-echoreply or icmp[icmptype] == icmp-echo) and ip host " + options.IPDST) po_dispatch = po.dispatch except OSError as e: print e exit(-1) raise SystemExit(-1) # notify sender that we are ready to capture ns.RCV_READY = True # block until sender says it is ready while not ns.SND_READY: time.sleep(0.1) DEBUG("READY", __name__) try: while po_dispatch(0, pcap_cb): pass except KeyboardInterrupt: pass # timeout_ms was reached, notify parser that we are done data_pipe.send("RCV_DONE") DEBUG("DONE", __name__)
def dumpwriter(pipe, ns, ST=None): hphelper.set_affinity("parser") DEBUG("starting", __name__) stats = hphelper.stats_stats() # start progress bar thread hphelper.bar_init(options, stats) if not options.start_time: options.start_time = time.time() if not options.savefile: # default save name is destination + YYMMDD + HHMM options.savefile = options.DST + time.strftime("_%Y%m%d_%H%M", time.localtime(options.start_time)) options.savefile += options.tag options.savefile += ".dump" print "saving RTTs to " + options.savefile + " ..." try: fs = open(options.savefile, mode="w") fs.write("% " + "options:" + " " + str(options) + "\n") # save options except KeyboardInterrupt: print "canceled writing file." # block until sender + receiver say they are ready while not all([ns.RCV_READY, ns.SND_READY]): time.sleep(0.1) stats.run_start = time.time() try: while 1: (seq, slot, rtt) = pipe.recv() if seq == -2: break stats.update(seq, rtt=rtt, current_slot=slot) fs.write("%d %d %.9f\n" % (seq, slot, rtt)) except (ValueError, KeyboardInterrupt) as e: print fs.close() DEBUG("done", __name__) stats.run_end = time.time() stats.pprint()
def dumploop(pipe, ns, geotimes=None): if not dump: print "ERROR: dump file not loaded!" return if ns.cnum: pnum = ns.cnum else: pnum = options.pnum hphelper.set_affinity("rcvloop") # notify sender that we are ready to capture ns.RCV_READY = True # block until sender says it is ready while not ns.SND_READY: time.sleep(0.1) DEBUG("READY", __name__) try: for s in dump.rcv_order[:pnum]: if s == -1: continue seq = s slot = dump.slottimes[seq] rtt = dump.rtts[seq] pipe.send((seq, slot, rtt)) # send to parser process except IndexError: print s print seq except KeyboardInterrupt: print s print "canceled reading file." # notify parser that we are done pipe.send("RCV_DONE") # q.close() DEBUG("done ", __name__)
def xcparser(pipe, ns, slottimes): if not options.start_time: options.start_time = time.time() if not options.savefile: # default save name is destination + YYMMDD + HHMM options.savefile = options.DST + time.strftime("_%Y%m%d_%H%M", time.localtime(options.start_time)) options.savefile += options.tag options.savefile += '_xc' timetime = time.time # faster: http://wiki.python.org/moin/PythonSpeed/PerformanceTips hphelper.set_affinity('parser') rcv_buf = deque() # TODO rcv_buf = xcfast.fixed_buf(options.pnum) xc = XcovEstimator(rcv_buf, slottimes) xc.daemon = True xc.name='parseloop' # start xcplotter Thread xcplotter_thread = threading.Thread(target=xcplotter, args=(xc,)) xcplotter_thread.daemon = True #block until sender + receiver say they are ready while not all([ns.RCV_READY,ns.SND_READY]): time.sleep(0.1) DEBUG('starting parser: '+__name__) xc.stats.run_start = timetime() xcplotter_thread.start() xc.start() data = None try: while 1: # faster than while True data = pipe.recv() # get (seq, slot, rtt) from capture process (seq, slot, rtt) = data rcv_buf.append((seq, slot, rtt)) except (KeyboardInterrupt): rcv_buf.append((-2,-2,-2)) print '\n\nparse loop interrupted...' except (ValueError) as e: rcv_buf.append((-2,-2,-2)) print '\a', # all packets received try: xc.join() xcplotter_thread.join() except KeyboardInterrupt: pass # display statistics xc.stats.run_end = timetime() xc.stats.rx_slots = xc.xc.slot_count xc.stats.pprint() (d,y0) = xc.fit() print print "\tH=%.2f (slope %.4f y0=%.4f)" % ((d+2)/2, d, y0 ) print fname = options.savefile + '.dat' print "saving covariance to " + fname + " ..." try: fs = open(fname, mode='w') fs.write('% ' + options.IPDST + ' ' + str(options)) for j in xc.xc.xcov[1:]: fs.write("%e\n" % (j)) fs.close() except KeyboardInterrupt: print 'canceled saving.'
def statsparser(pipe, ns, slottimes=None): hphelper.set_affinity('parser') DEBUG('starting parser ', __name__) #block until sender + receiver say they are ready while not all([ns.RCV_READY,ns.SND_READY]): time.sleep(0.1) stats = hphelper.stats_stats() # init empty array to store RTTs for histogram rtts = -1.0*ones(options.pnum) # start progress bar thread hphelper.bar_init(options, stats, ns.cnum) run_start = time.time() while 1: try: data = pipe.recv() if data == 'RCV_DONE': break (seq, currslot, rtt) = data if currslot == -1: rtt = -1 stats.snd_err += 1 continue stats.update(seq, rtt, currslot) if rtt<stats.min_rtt: stats.min_rtt = rtt rtts[seq] = rtt except (KeyboardInterrupt) as e: print 'parser canceled' except (ValueError) as e: print e print 'done writing' except (IndexError) as e: print e, seq pass ### TODO last sequence number causes error # omit invalid rtts rtts = rtts[rtts!=-1] if not any(rtts): ns.FATAL_ERROR = True ERROR("could not calculate average delay") # store mean RTT for use in other modules ns.mean_rtt = mean(rtts) stats.append_stats(median=('RTT median','%.6f' % median(rtts)), std=('RTT std. dev.','%.6f' % std(rtts)), #min=('min RTT','%.6f' % min(rtts)), max=('RTT maximum','%.6f' % max(rtts)), ) stats.pprint() if options.hist: plot_hist(rtts) return