diff options
author | Hanoh Haim <hhaim@cisco.com> | 2015-06-24 14:03:29 +0300 |
---|---|---|
committer | Hanoh Haim <hhaim@cisco.com> | 2015-06-24 14:03:29 +0300 |
commit | 8b52a31ed2c299b759f330c4f976b9c70f5765f4 (patch) | |
tree | 9d6da5438b5b56b1d2d57e6c13494b4e65d000e7 /scripts/automation/trex_control_plane/unit_tests/sock.py |
first version
Diffstat (limited to 'scripts/automation/trex_control_plane/unit_tests/sock.py')
-rwxr-xr-x | scripts/automation/trex_control_plane/unit_tests/sock.py | 552 |
1 files changed, 552 insertions, 0 deletions
diff --git a/scripts/automation/trex_control_plane/unit_tests/sock.py b/scripts/automation/trex_control_plane/unit_tests/sock.py new file mode 100755 index 00000000..29248e3e --- /dev/null +++ b/scripts/automation/trex_control_plane/unit_tests/sock.py @@ -0,0 +1,552 @@ +import os +import dpkt +import struct +import socket +import sys +import argparse; + + +H_SCRIPT_VER = "0.1" + +class sock_driver(object): + args=None; + + +def nl (buf): + return ( struct.unpack('>I', buf)[0]); + +def dump_tuple (t): + for obj in t: + print hex(obj),",", + +class CFlowRec: + def __init__ (self): + self.is_init_dir=False; + self.bytes=0; + self.data=None; + + def __str__ (self): + if self.is_init_dir : + s=" client " + else: + s=" server " + s+= " %d " %(self.bytes) + return (s); + + + +class CPcapFileReader: + def __init__ (self,file_name): + self.file_name=file_name; + self.tuple=None; + self.swap=False; + self.info=[]; + + def dump_info (self): + for obj in self.info: + print obj + #print "'",obj.data,"'" + + def is_client_side (self,swap): + if self.swap ==swap: + return (True); + else: + return (False); + + def add_server(self,server,data): + r=CFlowRec(); + r.is_init_dir =False; + r.bytes = server + r.data=data + self.info.append(r); + + def add_client(self,client,data): + r=CFlowRec(); + r.is_init_dir =True; + r.bytes = client + r.data=data + self.info.append(r); + + def check_tcp_flow (self): + f = open(self.file_name) + pcap = dpkt.pcap.Reader(f) + for ts, buf in pcap: + eth = dpkt.ethernet.Ethernet(buf) + ip = eth.data + tcp = ip.data + if ip.p != 6 : + raise Exception("not a TCP flow .."); + if tcp.flags != dpkt.tcp.TH_SYN : + raise Exception("first packet should be with SYN"); + break; + f.close(); + + def check_one_flow (self): + cnt=1 + client=0; + server=0; + client_data='' + server_data='' + is_c=False # the direction + is_s=False + f = open(self.file_name) + pcap = dpkt.pcap.Reader(f) + for ts, buf in pcap: + eth = dpkt.ethernet.Ethernet(buf) + ip = eth.data + tcp = ip.data + pld = tcp.data; + + pkt_swap=False + if nl(ip.src) > nl(ip.dst): + pkt_swap=True + tuple= (nl(ip.dst),nl(ip.src), tcp.dport ,tcp.sport,ip.p ); + else: + tuple= (nl(ip.src),nl(ip.dst) ,tcp.sport,tcp.dport,ip.p ); + + if self.tuple == None: + self.swap=pkt_swap + self.tuple=tuple + else: + if self.tuple != tuple: + raise Exception("More than one flow - can't process this flow"); + + + print " %5d," % (cnt), + if self.is_client_side (pkt_swap): + print "client", + if len(pld) >0 : + if is_c==False: + is_c=True + if is_s: + self.add_server(server,server_data); + server=0; + server_data='' + is_s=False; + + client+=len(pld); + client_data=client_data+pld; + else: + if len(pld) >0 : + if is_s==False: + is_s=True + if is_c: + self.add_client(client,client_data); + client=0; + client_data='' + is_c=False; + + server+=len(pld) + server_data=server_data+pld; + + print "server", + print " %5d" % (len(pld)), + dump_tuple (tuple) + print + + cnt=cnt+1 + + if is_c: + self.add_client(client,client_data); + if is_s: + self.add_server(server,server_data); + + f.close(); + + +class CClientServerCommon(object): + + def __init__ (self): + pass; + + def send_info (self,data): + print "server send %d bytes" % (len(data)) + self.connection.sendall(data) + + def rcv_info (self,msg_size): + print "server wait for %d bytes" % (msg_size) + + bytes_recd = 0 + while bytes_recd < msg_size: + chunk = self.connection.recv(min(msg_size - bytes_recd, 2048)) + if chunk == '': + raise RuntimeError("socket connection broken") + bytes_recd = bytes_recd + len(chunk) + + + def process (self,is_server): + pcapinfo=self.pcapr.info + for obj in pcapinfo: + if is_server: + if obj.is_init_dir: + self.rcv_info (obj.bytes); + else: + self.send_info (obj.data); + else: + if obj.is_init_dir: + self.send_info (obj.data); + else: + self.rcv_info (obj.bytes); + + self.connection.close(); + self.connection = None + + +class CServer(CClientServerCommon) : + def __init__ (self,pcapr,port): + super(CServer, self).__init__() + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + + server_address = ('', port) + print 'starting up on %s port %s' % server_address + sock.bind(server_address) + sock.listen(1) + + self.pcapr=pcapr; # save the info + + while True: + # Wait for a connection + print 'waiting for a connection' + connection, client_address = sock.accept() + + try: + print 'connection from', client_address + self.connection = connection; + + self.process(True); + finally: + if self.connection : + self.connection.close() + self.connection = None + + +class CClient(CClientServerCommon): + def __init__ (self,pcapr,ip,port): + super(CClient, self).__init__() + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + #sock.setsockopt(socket.SOL_SOCKET,socket.TCP_MAXSEG,300) + server_address = (ip, port) + print 'connecting to %s port %s' % server_address + + sock.connect(server_address) + self.connection=sock; + self.pcapr=pcapr; # save the info + + try: + + self.process(False); + finally: + if self.connection : + self.connection.close() + self.connection = None + + +def test_file_load (): + pcapr= CPcapFileReader("delay_10_http_browsing_0.pcap") + pcapr.check_tcp_flow () + pcapr.check_one_flow () + pcapr.dump_info(); + + +def process_options (): + parser = argparse.ArgumentParser(usage=""" + sock [-s|-c] -f file_name + + """, + description="offline process a pcap file", + epilog=" written by hhaim"); + + parser.add_argument("-f", dest="file_name", + help=""" the file name to process """, + required=True) + + parser.add_argument('-c', action='store_true', + help='client side') + + parser.add_argument('-s', action='store_true', + help='server side ') + + parser.add_argument('--fix-time', action='store_true', + help='fix_time ') + + parser.add_argument('--port', type=int, default=1000, + help='server_port ') + + parser.add_argument('--ip', default='127.0.0.1', + help='socket ip ') + + parser.add_argument('--debug', action='store_true', + help='debug mode') + + parser.add_argument('--version', action='version', + version=H_SCRIPT_VER ) + + + + sock_driver.args = parser.parse_args(); + + if sock_driver.args.fix_time : + return ; + if (sock_driver.args.c ^ sock_driver.args.s) ==0: + raise Exception ("you must set either client or server mode"); + +def load_pcap_file (): + pcapr= CPcapFileReader(sock_driver.args.file_name) + pcapr.check_tcp_flow () + pcapr.check_one_flow () + pcapr.dump_info(); + return pcapr + +def run_client_side (): + pcapr=load_pcap_file () + socket_client = CClient(pcapr,sock_driver.args.ip,sock_driver.args.port); + + +def run_server_side (): + pcapr=load_pcap_file () + socket_server = CServer(pcapr,sock_driver.args.port); + + +class CPktWithTime: + def __init__ (self,pkt,ts): + self.pkt=pkt; + self.ts=ts + def __cmp__ (self,other): + return cmp(self.ts,other.ts); + + def __repr__ (self): + s=" %x:%d" %(self.pkt,self.ts) + return s; + + +class CPcapFixTime: + def __init__ (self,in_file_name, + out_file_name): + self.in_file_name = in_file_name; + self.out_file_name = out_file_name; + self.tuple=None; + self.swap=False; + self.rtt =0; + self.rtt_syn_ack_ack =0; # ack on the syn ack + self.pkts=[] + + def calc_rtt (self): + f = open(self.in_file_name) + pcap = dpkt.pcap.Reader(f) + cnt=0; + first_time_set=False; + first_time=0; + last_syn_time=0; + rtt=0; + rtt_syn_ack_ack=0; + + for ts, buf in pcap: + eth = dpkt.ethernet.Ethernet(buf) + ip = eth.data + tcp = ip.data + + if first_time_set ==False: + first_time=ts; + first_time_set=True; + else: + rtt=ts-first_time; + + if ip.p != 6 : + raise Exception("not a TCP flow .."); + + if cnt==0 or cnt==1: + if (tcp.flags & dpkt.tcp.TH_SYN) != dpkt.tcp.TH_SYN : + raise Exception("first packet should be with SYN"); + + if cnt==1: + last_syn_time=ts; + + if cnt==2: + rtt_syn_ack_ack=ts-last_syn_time; + + if cnt > 1 : + break; + cnt = cnt +1; + + f.close(); + self.rtt_syn_ack_ack = rtt_syn_ack_ack; + return (rtt); + + def is_client_side (self,swap): + if self.swap ==swap: + return (True); + else: + return (False); + + def calc_timing (self): + self.rtt=self.calc_rtt (); + + def fix_timing (self): + + rtt=self.calc_rtt (); + print "RTT is %f msec" % (rtt*1000) + + if (rtt/2)*1000<5: + raise Exception ("RTT is less than 5msec, you should replay it"); + + time_to_center=rtt/4; + + f = open(self.in_file_name) + fo = open(self.out_file_name,"wb") + pcap = dpkt.pcap.Reader(f) + pcap_out = dpkt.pcap.Writer(fo) + + for ts, buf in pcap: + eth = dpkt.ethernet.Ethernet(buf) + ip = eth.data + tcp = ip.data + pld = tcp.data; + + pkt_swap=False + if nl(ip.src) > nl(ip.dst): + pkt_swap=True + tuple= (nl(ip.dst),nl(ip.src), tcp.dport ,tcp.sport,ip.p ); + else: + tuple= (nl(ip.src),nl(ip.dst) ,tcp.sport,tcp.dport,ip.p ); + + if self.tuple == None: + self.swap=pkt_swap + self.tuple=tuple + else: + if self.tuple != tuple: + raise Exception("More than one flow - can't process this flow"); + + if self.is_client_side (pkt_swap): + self.pkts.append(CPktWithTime( buf,ts+time_to_center)); + else: + self.pkts.append(CPktWithTime( buf,ts-time_to_center)); + + self.pkts.sort(); + for pkt in self.pkts: + pcap_out.writepkt(pkt.pkt, pkt.ts) + + f.close() + fo.close(); + + + +def main (): + process_options () + + if sock_driver.args.fix_time: + pcap = CPcapFixTime(sock_driver.args.file_name ,sock_driver.args.file_name+".fix.pcap") + pcap.fix_timing () + + if sock_driver.args.c: + run_client_side (); + + if sock_driver.args.s: + run_server_side (); + + +files_to_convert=[ +'citrix_0', +'exchange_0', +'http_browsing_0', +'http_get_0', +'http_post_0', +'https_0', +'mail_pop_0', +'mail_pop_1', +'mail_pop_2', +'oracle_0', +'rtsp_0', +'smtp_0', +'smtp_1', +'smtp_2' +]; + + +#files_to_convert=[ +#'http_browsing_0', +#]; + +def test_pcap_file (): + for file in files_to_convert: + fn='tun_'+file+'.pcap'; + fno='_tun_'+file+'_fixed.pcap'; + print "convert ",fn + pcap = CPcapFixTime(fn,fno) + pcap.fix_timing () + + + + +class CPcapFileState: + def __init__ (self,file_name): + self.file_name = file_name + self.is_one_tcp_flow = False; + self.is_rtt_valid = False; + self.rtt=0; + self.rtt_ack=0; + + def calc_stats (self): + file = CPcapFileReader(self.file_name); + try: + file.check_tcp_flow() + file.check_one_flow () + self.is_one_tcp_flow = True; + except Exception : + self.is_one_tcp_flow = False; + + print self.is_one_tcp_flow + if self.is_one_tcp_flow : + pcap= CPcapFixTime(self.file_name,""); + try: + pcap.calc_timing () + print "rtt : %d %d \n" % (pcap.rtt*1000,pcap.rtt_syn_ack_ack*1000); + if (pcap.rtt*1000) > 10 and (pcap.rtt_syn_ack_ack*1000) >0.0 and (pcap.rtt_syn_ack_ack*1000) <2.0 : + self.is_rtt_valid = True + self.rtt = pcap.rtt*1000; + self.rtt_ack =pcap.rtt_syn_ack_ack*1000; + except Exception : + pass; + + +def test_pcap_file (file_name): + p= CPcapFileState(file_name) + p.calc_stats(); + if p.is_rtt_valid: + return True + else: + return False + +def iterate_tree_files (dirwalk,path_to): + fl=open("res.csv","w+"); + cnt=0; + cnt_valid=0 + for root, _, files in os.walk(dirwalk): + for f in files: + fullpath = os.path.join(root, f) + p= CPcapFileState(fullpath) + p.calc_stats(); + + valid=test_pcap_file (fullpath) + s='%s,%d,%d,%d \n' %(fullpath,p.is_rtt_valid,p.rtt,p.rtt_ack) + cnt = cnt +1 ; + if p.is_rtt_valid: + cnt_valid = cnt_valid +1; + diro=path_to+"/"+root; + fo = os.path.join(diro, f) + os.system("mkdir -p "+ diro); + pcap = CPcapFixTime(fullpath,fo) + pcap.fix_timing () + + print s + fl.write(s); + print " %d %% %d valids \n" % (100*cnt_valid/cnt,cnt); + fl.close(); + +path_code="/scratch/tftp/pFidelity/pcap_repository" + +iterate_tree_files (path_code,"output") +#test_pcap_file () +#test_pcap_file () +#main(); + |