summaryrefslogtreecommitdiffstats
path: root/scripts/automation/trex_control_plane/unit_tests/sock.py
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/automation/trex_control_plane/unit_tests/sock.py')
-rwxr-xr-xscripts/automation/trex_control_plane/unit_tests/sock.py552
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();
+