diff options
Diffstat (limited to 'scripts/automation/trex_control_plane/stl/examples')
16 files changed, 1767 insertions, 0 deletions
diff --git a/scripts/automation/trex_control_plane/stl/examples/hlt_udp_simple.py b/scripts/automation/trex_control_plane/stl/examples/hlt_udp_simple.py new file mode 100644 index 00000000..1f754f0a --- /dev/null +++ b/scripts/automation/trex_control_plane/stl/examples/hlt_udp_simple.py @@ -0,0 +1,114 @@ +#!/usr/bin/python + +""" +Sample HLTAPI application (for loopback) +Connect to TRex +Send UDP packet in specific length +Each direction has its own IP range +""" + +import sys +import argparse +import stl_path +from trex_stl_lib.api import * +from trex_stl_lib.trex_stl_hltapi import * + + +if __name__ == "__main__": + parser = argparse.ArgumentParser(usage=""" + Connect to TRex and send bidirectional continuous traffic + + examples: + + hlt_udp_simple.py --server <hostname/ip> + + hlt_udp_simple.py -s 300 -d 30 -rate_pps 5000000 --src <MAC> --dst <MAC> + + then run the simulator on the output + ./stl-sim -f example.yaml -o a.pcap ==> a.pcap include the packet + + """, + description="Example for TRex HLTAPI", + epilog=" based on hhaim's stl_run_udp_simple example"); + + parser.add_argument("--server", + dest="server", + help='Remote trex address', + default="127.0.0.1", + type = str) + + parser.add_argument("-s", "--frame-size", + dest="frame_size", + help='L2 frame size in bytes without FCS', + default=60, + type = int,) + + parser.add_argument('-d','--duration', + dest='duration', + help='duration in second ', + default=10, + type = int,) + + parser.add_argument('--rate-pps', + dest='rate_pps', + help='speed in pps', + default="100") + + parser.add_argument('--src', + dest='src_mac', + help='src MAC', + default='00:50:56:b9:de:75') + + parser.add_argument('--dst', + dest='dst_mac', + help='dst MAC', + default='00:50:56:b9:34:f3') + + args = parser.parse_args(); + + hltapi = CTRexHltApi() + print('Connecting to TRex') + res = hltapi.connect(device = args.server, port_list = [0, 1], reset = True, break_locks = True) + check_res(res) + ports = list(res['port_handle'].values()) + if len(ports) < 2: + error('Should have at least 2 ports for this test') + print('Connected, acquired ports: %s' % ports) + + print('Creating traffic') + + res = hltapi.traffic_config(mode = 'create', bidirectional = True, + port_handle = ports[0], port_handle2 = ports[1], + frame_size = args.frame_size, + mac_src = args.src_mac, mac_dst = args.dst_mac, + mac_src2 = args.dst_mac, mac_dst2 = args.src_mac, + l3_protocol = 'ipv4', + ip_src_addr = '10.0.0.1', ip_src_mode = 'increment', ip_src_count = 254, + ip_dst_addr = '8.0.0.1', ip_dst_mode = 'increment', ip_dst_count = 254, + l4_protocol = 'udp', + udp_dst_port = 12, udp_src_port = 1025, + rate_pps = args.rate_pps, + ) + check_res(res) + + print('Starting traffic') + res = hltapi.traffic_control(action = 'run', port_handle = ports[:2]) + check_res(res) + wait_with_progress(args.duration) + + print('Stopping traffic') + res = hltapi.traffic_control(action = 'stop', port_handle = ports[:2]) + check_res(res) + + res = hltapi.traffic_stats(mode = 'aggregate', port_handle = ports[:2]) + check_res(res) + print_brief_stats(res) + + print('Removing all streams from port 0') + res = hltapi.traffic_config(mode = 'remove', port_handle = ports[0], stream_id = 'all') + check_res(res) + + res = hltapi.cleanup_session(port_handle = 'all') + check_res(res) + + print('Done') diff --git a/scripts/automation/trex_control_plane/stl/examples/rpc_proxy_server.py b/scripts/automation/trex_control_plane/stl/examples/rpc_proxy_server.py new file mode 100755 index 00000000..ad2697d8 --- /dev/null +++ b/scripts/automation/trex_control_plane/stl/examples/rpc_proxy_server.py @@ -0,0 +1,167 @@ +#!/usr/bin/python + +import argparse +import traceback +import logging +import sys +import os +import json +import socket +from functools import partial +logging.basicConfig(level = logging.FATAL) # keep quiet + +import stl_path +from trex_stl_lib.api import * +from trex_stl_lib.trex_stl_hltapi import CTRexHltApi, HLT_OK, HLT_ERR + +# ext libs +ext_libs = os.path.join(os.pardir, os.pardir, os.pardir, os.pardir, 'external_libs') # usual package path +if not os.path.exists(ext_libs): + ext_libs = os.path.join(os.pardir, os.pardir, 'external_libs') # client package path +sys.path.append(os.path.join(ext_libs, 'jsonrpclib-pelix-0.2.5')) +from jsonrpclib.SimpleJSONRPCServer import SimpleJSONRPCServer +import yaml + +# TODO: refactor this to class + +native_client = None +hltapi_client = None + +def OK(res = True): + return[True, res] + +def ERR(res = 'Unknown error'): + return [False, res] + +def deunicode_json(data): + return yaml.safe_load(json.dumps(data)) + + +### Server functions ### + +def add(a, b): # for sanity checks + try: + return OK(a + b) + except: + return ERR(traceback.format_exc()) + +def check_connectivity(): + return OK() + +def native_proxy_init(force = False, *args, **kwargs): + global native_client + if native_client and not force: + return ERR('Native Client is already initiated') + try: + native_client = STLClient(*args, **kwargs) + return OK('Native Client initiated') + except: + return ERR(traceback.format_exc()) + +def native_proxy_del(): + global native_client + native_client = None + return OK() + +def hltapi_proxy_init(force = False, *args, **kwargs): + global hltapi_client + if hltapi_client and not force: + return HLT_ERR('HLTAPI Client is already initiated') + try: + hltapi_client = CTRexHltApi(*args, **kwargs) + return HLT_OK() + except: + return HLT_ERR(traceback.format_exc()) + +def hltapi_proxy_del(): + global hltapi_client + hltapi_client = None + return HLT_OK() + +# any method not listed above can be called with passing its name here +def native_method(func_name, *args, **kwargs): + try: + func = getattr(native_client, func_name) + return OK(func(*deunicode_json(args), **deunicode_json(kwargs))) + except: + return ERR(traceback.format_exc()) + +# any HLTAPI method can be called with passing its name here +def hltapi_method(func_name, *args, **kwargs): + try: + func = getattr(hltapi_client, func_name) + return func(*deunicode_json(args), **deunicode_json(kwargs)) + except: + return HLT_ERR(traceback.format_exc()) + +### /Server functions ### + + +def run_server(port = 8095): + native_methods = [ + 'acquire', + 'connect', + 'disconnect', + 'get_stats', + 'get_warnings', + 'push_remote', + 'reset', + 'wait_on_traffic', + ] + hltapi_methods = [ + 'connect', + 'cleanup_session', + 'interface_config', + 'traffic_config', + 'traffic_control', + 'traffic_stats', + ] + + try: + register_socket('trex_stl_rpc_proxy') + server = SimpleJSONRPCServer(('0.0.0.0', port)) + server.register_function(add) + server.register_function(check_connectivity) + server.register_function(native_proxy_init) + server.register_function(native_proxy_del) + server.register_function(hltapi_proxy_init) + server.register_function(hltapi_proxy_del) + server.register_function(native_method) + server.register_function(hltapi_method) + + for method in native_methods: + server.register_function(partial(native_method, method), method) + for method in hltapi_methods: + if method in native_methods: # collision in names + method_hlt_name = 'hlt_%s' % method + else: + method_hlt_name = method + server.register_function(partial(hltapi_method, method), method_hlt_name) + server.register_function(server.funcs.keys, 'get_methods') # should be last + print('Started Stateless RPC proxy at port %s' % port) + server.serve_forever() + except KeyboardInterrupt: + print('Done') + +# provides unique way to determine running process +def register_socket(tag): + global foo_socket # Without this our lock gets garbage collected + foo_socket = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM) + try: + foo_socket.bind('\0%s' % tag) + print('Got the socket lock for tag %s.' % tag) + except socket.error: + print('Error: process with tag %s is already running.' % tag) + sys.exit(-1) + +### Main ### + + + +if __name__ == '__main__': + parser = argparse.ArgumentParser(description = 'Runs TRex Stateless RPC proxy for usage with any language client.') + parser.add_argument('-p', '--port', type=int, default = 8095, dest='port', action = 'store', + help = 'Select port on which the stl rpc proxy will run.\nDefault is 8095.') + kwargs = vars(parser.parse_args()) + run_server(**kwargs) + diff --git a/scripts/automation/trex_control_plane/stl/examples/stl_bi_dir_flows.py b/scripts/automation/trex_control_plane/stl/examples/stl_bi_dir_flows.py new file mode 100644 index 00000000..9977fa3e --- /dev/null +++ b/scripts/automation/trex_control_plane/stl/examples/stl_bi_dir_flows.py @@ -0,0 +1,118 @@ +import stl_path +from trex_stl_lib.api import * + +import time +import json + +# simple packet creation +def create_pkt (size, direction): + + ip_range = {'src': {'start': "10.0.0.1", 'end': "10.0.0.254"}, + 'dst': {'start': "8.0.0.1", 'end': "8.0.0.254"}} + + if (direction == 0): + src = ip_range['src'] + dst = ip_range['dst'] + else: + src = ip_range['dst'] + dst = ip_range['src'] + + vm = [ + # src + STLVmFlowVar(name="src",min_value=src['start'],max_value=src['end'],size=4,op="inc"), + STLVmWrFlowVar(fv_name="src",pkt_offset= "IP.src"), + + # dst + STLVmFlowVar(name="dst",min_value=dst['start'],max_value=dst['end'],size=4,op="inc"), + STLVmWrFlowVar(fv_name="dst",pkt_offset= "IP.dst"), + + # checksum + STLVmFixIpv4(offset = "IP") + ] + + + base = Ether()/IP()/UDP() + pad = max(0, size-len(base)) * 'x' + + return STLPktBuilder(pkt = base/pad, + vm = vm) + + +def simple_burst (port_a, port_b, pkt_size, rate): + + + # create client + c = STLClient() + passed = True + + try: + # turn this on for some information + #c.set_verbose("high") + + # create two streams + s1 = STLStream(packet = create_pkt(pkt_size, 0), + mode = STLTXCont(pps = 100)) + + # second stream with a phase of 1ms (inter stream gap) + s2 = STLStream(packet = create_pkt(pkt_size, 1), + isg = 1000, + mode = STLTXCont(pps = 100)) + + + # connect to server + c.connect() + + # prepare our ports + c.reset(ports = [port_a, port_b]) + + # add both streams to ports + c.add_streams(s1, ports = [port_a]) + c.add_streams(s2, ports = [port_b]) + + # clear the stats before injecting + c.clear_stats() + + # here we multiply the traffic lineaer to whatever given in rate + print("Running {:} on ports {:}, {:} for 10 seconds...".format(rate, port_a, port_b)) + c.start(ports = [port_a, port_b], mult = rate, duration = 10) + + # block until done + c.wait_on_traffic(ports = [port_a, port_b]) + + # read the stats after the test + stats = c.get_stats() + + print(json.dumps(stats[port_a], indent = 4, separators=(',', ': '), sort_keys = True)) + print(json.dumps(stats[port_b], indent = 4, separators=(',', ': '), sort_keys = True)) + + lost_a = stats[port_a]["opackets"] - stats[port_b]["ipackets"] + lost_b = stats[port_b]["opackets"] - stats[port_a]["ipackets"] + + print("\npackets lost from {0} --> {1}: {2} pkts".format(port_a, port_b, lost_a)) + print("packets lost from {0} --> {1}: {2} pkts".format(port_b, port_a, lost_b)) + + if c.get_warnings(): + print("\n\n*** test had warnings ****\n\n") + for w in c.get_warnings(): + print(w) + + if (lost_a == 0) and (lost_b == 0) and not c.get_warnings(): + passed = True + else: + passed = False + + except STLError as e: + passed = False + print(e) + + finally: + c.disconnect() + + if passed: + print("\nTest has passed :-)\n") + else: + print("\nTest has failed :-(\n") + +# run the tests +simple_burst(0, 3, 64, "10gbps") + diff --git a/scripts/automation/trex_control_plane/stl/examples/stl_flow_latency_stats.py b/scripts/automation/trex_control_plane/stl/examples/stl_flow_latency_stats.py new file mode 100644 index 00000000..d8a99479 --- /dev/null +++ b/scripts/automation/trex_control_plane/stl/examples/stl_flow_latency_stats.py @@ -0,0 +1,144 @@ +# Example showing how to define stream for latency measurement, and how to parse the latency information + +import stl_path +from trex_stl_lib.api import * + +import time +import pprint + +def rx_example (tx_port, rx_port, burst_size, pps): + + print("\nGoing to inject {0} packets on port {1} - checking RX stats on port {2}\n".format(burst_size, tx_port, rx_port)) + + # create client + c = STLClient() + passed = True + + try: + pkt = STLPktBuilder(pkt = Ether()/IP(src="16.0.0.1",dst="48.0.0.1")/UDP(dport=12,sport=1025)/'at_least_16_bytes_payload_needed') + total_pkts = burst_size + s1 = STLStream(name = 'rx', + packet = pkt, + flow_stats = STLFlowLatencyStats(pg_id = 5), + mode = STLTXSingleBurst(total_pkts = total_pkts, + pps = pps)) + + # connect to server + c.connect() + + # prepare our ports + c.reset(ports = [tx_port, rx_port]) + + # add both streams to ports + c.add_streams([s1], ports = [tx_port]) + + print("\nInjecting {0} packets on port {1}\n".format(total_pkts, tx_port)) + + rc = rx_iteration(c, tx_port, rx_port, total_pkts, pkt.get_pkt_len()) + if not rc: + passed = False + + except STLError as e: + passed = False + print(e) + + finally: + c.disconnect() + + if passed: + print("\nTest passed :-)\n") + else: + print("\nTest failed :-(\n") + +# RX one iteration +def rx_iteration (c, tx_port, rx_port, total_pkts, pkt_len): + + c.clear_stats() + + c.start(ports = [tx_port]) + c.wait_on_traffic(ports = [tx_port]) + + stats = c.get_stats() + flow_stats = stats['flow_stats'].get(5) + global_lat_stats = stats['latency'] + lat_stats = global_lat_stats.get(5) + if not flow_stats: + print("no flow stats available") + return False + if not lat_stats: + print("no latency stats available") + return False + + tx_pkts = flow_stats['tx_pkts'].get(tx_port, 0) + tx_bytes = flow_stats['tx_bytes'].get(tx_port, 0) + rx_pkts = flow_stats['rx_pkts'].get(rx_port, 0) + drops = lat_stats['err_cntrs']['dropped'] + ooo = lat_stats['err_cntrs']['out_of_order'] + dup = lat_stats['err_cntrs']['dup'] + sth = lat_stats['err_cntrs']['seq_too_high'] + stl = lat_stats['err_cntrs']['seq_too_low'] + old_flow = global_lat_stats['global']['old_flow'] + bad_hdr = global_lat_stats['global']['bad_hdr'] + lat = lat_stats['latency'] + jitter = lat['jitter'] + avg = lat['average'] + tot_max = lat['total_max'] + tot_min = lat['total_min'] + last_max = lat['last_max'] + hist = lat ['histogram'] + + if c.get_warnings(): + print("\n\n*** test had warnings ****\n\n") + for w in c.get_warnings(): + print(w) + return False + + print('Error counters: dropped:{0}, ooo:{1} dup:{2} seq too high:{3} seq too low:{4}'.format(drops, ooo, dup, sth, stl)) + if old_flow: + print ('Packets arriving too late after flow stopped: {0}'.format(old_flow)) + if bad_hdr: + print ('Latency packets with corrupted info: {0}'.format(bad_hdr)) + print('Latency info:') + print(" Maximum latency(usec): {0}".format(tot_max)) + print(" Minimum latency(usec): {0}".format(tot_min)) + print(" Maximum latency in last sampling period (usec): {0}".format(last_max)) + print(" Average latency(usec): {0}".format(avg)) + print(" Jitter(usec): {0}".format(jitter)) + print(" Latency distribution histogram:") + l = hist.keys() + l.sort() + for sample in l: + range_start = sample + if range_start == 0: + range_end = 10 + else: + range_end = range_start + pow(10, (len(str(range_start))-1)) + val = hist[sample] + print (" Packets with latency between {0} and {1}:{2} ".format(range_start, range_end, val)) + + if tx_pkts != total_pkts: + print("TX pkts mismatch - got: {0}, expected: {1}".format(tx_pkts, total_pkts)) + pprint.pprint(flow_stats) + return False + else: + print("TX pkts match - {0}".format(tx_pkts)) + + if tx_bytes != (total_pkts * (pkt_len + 4)): # +4 for ethernet CRC + print("TX bytes mismatch - got: {0}, expected: {1}".format(tx_bytes, (total_pkts * pkt_len))) + pprint.pprint(flow_stats) + return False + else: + print("TX bytes match - {0}".format(tx_bytes)) + + if rx_pkts != total_pkts: + print("RX pkts mismatch - got: {0}, expected: {1}".format(rx_pkts, total_pkts)) + pprint.pprint(flow_stats) + return False + else: + print("RX pkts match - {0}".format(rx_pkts)) + + return True + +# run the tests +rx_example(tx_port = 0, rx_port = 1, burst_size = 1000, pps = 1000) + diff --git a/scripts/automation/trex_control_plane/stl/examples/stl_flow_stats.py b/scripts/automation/trex_control_plane/stl/examples/stl_flow_stats.py new file mode 100644 index 00000000..3c630ece --- /dev/null +++ b/scripts/automation/trex_control_plane/stl/examples/stl_flow_stats.py @@ -0,0 +1,110 @@ +# Example showing how to define stream for getting per flow statistics, and how to parse the received statistics + +import stl_path +from trex_stl_lib.api import * + +import time +import pprint + +def rx_example (tx_port, rx_port, burst_size, bw): + + print("\nGoing to inject {0} packets on port {1} - checking RX stats on port {2}\n".format(burst_size, tx_port, rx_port)) + + # create client + c = STLClient() + passed = True + + try: + pkt = STLPktBuilder(pkt = Ether()/IP(src="16.0.0.1",dst="48.0.0.1")/UDP(dport=12,sport=1025)/IP()/'a_payload_example') + total_pkts = burst_size + s1 = STLStream(name = 'rx', + packet = pkt, + flow_stats = STLFlowStats(pg_id = 5), + mode = STLTXSingleBurst(total_pkts = total_pkts, + percentage = bw)) + + # connect to server + c.connect() + + # prepare our ports + c.reset(ports = [tx_port, rx_port]) + + # add stream to port + c.add_streams([s1], ports = [tx_port]) + + print("\ngoing to inject {0} packets on port {1}\n".format(total_pkts, tx_port)) + + rc = rx_iteration(c, tx_port, rx_port, total_pkts, s1.get_pkt_len()) + if not rc: + passed = False + + except STLError as e: + passed = False + print(e) + + finally: + c.disconnect() + + if passed: + print("\nTest passed :-)\n") + else: + print("\nTest failed :-(\n") + +# RX one iteration +def rx_iteration (c, tx_port, rx_port, total_pkts, pkt_len): + ret = True + + c.clear_stats() + + c.start(ports = [tx_port]) + c.wait_on_traffic(ports = [tx_port]) + + global_flow_stats = c.get_stats()['flow_stats'] + flow_stats = global_flow_stats.get(5) + if not flow_stats: + print("no flow stats available") + return False + + tx_pkts = flow_stats['tx_pkts'].get(tx_port, 0) + tx_bytes = flow_stats['tx_bytes'].get(tx_port, 0) + rx_pkts = flow_stats['rx_pkts'].get(rx_port, 0) + + if c.get_warnings(): + print("\n\n*** test had warnings ****\n\n") + for w in c.get_warnings(): + print(w) + return False + + if tx_pkts != total_pkts: + print("TX pkts mismatch - got: {0}, expected: {1}".format(tx_pkts, total_pkts)) + pprint.pprint(flow_stats) + ret = False + else: + print("TX pkts match - {0}".format(tx_pkts)) + + if tx_bytes != (total_pkts * pkt_len): + print("TX bytes mismatch - got: {0}, expected: {1}".format(tx_bytes, (total_pkts * pkt_len))) + pprint.pprint(flow_stats) + ret = False + else: + print("TX bytes match - {0}".format(tx_bytes)) + + if rx_pkts != total_pkts: + print("RX pkts mismatch - got: {0}, expected: {1}".format(rx_pkts, total_pkts)) + pprint.pprint(flow_stats) + ret = False + else: + print("RX pkts match - {0}".format(rx_pkts)) + + + for field in ['rx_err', 'tx_err']: + for port in global_flow_stats['global'][field].keys(): + if global_flow_stats['global'][field][port] != 0: + print ("\n{0} on port {1}: {2} - You should consider increasing rx_delay_ms value in wait_on_traffic" + .format(field, port, global_flow_stats['global'][field][port])) + + return ret + +# run the tests +rx_example(tx_port = 0, rx_port = 1, burst_size = 500, bw = 50) + diff --git a/scripts/automation/trex_control_plane/stl/examples/stl_imix.py b/scripts/automation/trex_control_plane/stl/examples/stl_imix.py new file mode 100644 index 00000000..875186ba --- /dev/null +++ b/scripts/automation/trex_control_plane/stl/examples/stl_imix.py @@ -0,0 +1,126 @@ +import stl_path +from trex_stl_lib.api import * + +import time +import json +from pprint import pprint +import argparse +import sys + +# IMIX test +# it maps the ports to sides +# then it load a predefind profile 'IMIX' +# and attach it to both sides and inject +# at a certain rate for some time +# finally it checks that all packets arrived +def imix_test (server, mult): + + + # create client + c = STLClient(server = server) + + passed = True + + + try: + + # connect to server + c.connect() + + # take all the ports + c.reset() + + + # map ports - identify the routes + table = stl_map_ports(c) + + dir_0 = [x[0] for x in table['bi']] + dir_1 = [x[1] for x in table['bi']] + + print("Mapped ports to sides {0} <--> {1}".format(dir_0, dir_1)) + + # load IMIX profile + profile_file = os.path.join(stl_path.STL_PROFILES_PATH, 'imix.py') + profile = STLProfile.load_py(profile_file) + streams = profile.get_streams() + + # add both streams to ports + c.add_streams(streams, ports = dir_0) + c.add_streams(streams, ports = dir_1) + + # clear the stats before injecting + c.clear_stats() + + # choose rate and start traffic for 10 seconds + duration = 10 + print("Injecting {0} <--> {1} on total rate of '{2}' for {3} seconds".format(dir_0, dir_1, mult, duration)) + + c.start(ports = (dir_0 + dir_1), mult = mult, duration = duration, total = True) + + # block until done + c.wait_on_traffic(ports = (dir_0 + dir_1)) + + # read the stats after the test + stats = c.get_stats() + + # use this for debug info on all the stats + #pprint(stats) + + # sum dir 0 + dir_0_opackets = sum([stats[i]["opackets"] for i in dir_0]) + dir_0_ipackets = sum([stats[i]["ipackets"] for i in dir_0]) + + # sum dir 1 + dir_1_opackets = sum([stats[i]["opackets"] for i in dir_1]) + dir_1_ipackets = sum([stats[i]["ipackets"] for i in dir_1]) + + + lost_0 = dir_0_opackets - dir_1_ipackets + lost_1 = dir_1_opackets - dir_0_ipackets + + print("\nPackets injected from {0}: {1:,}".format(dir_0, dir_0_opackets)) + print("Packets injected from {0}: {1:,}".format(dir_1, dir_1_opackets)) + + print("\npackets lost from {0} --> {1}: {2:,} pkts".format(dir_0, dir_0, lost_0)) + print("packets lost from {0} --> {1}: {2:,} pkts".format(dir_1, dir_1, lost_1)) + + if c.get_warnings(): + print("\n\n*** test had warnings ****\n\n") + for w in c.get_warnings(): + print(w) + + if (lost_0 <= 0) and (lost_1 <= 0) and not c.get_warnings(): # less or equal because we might have incoming arps etc. + passed = True + else: + passed = False + + + except STLError as e: + passed = False + print(e) + sys.exit(1) + + finally: + c.disconnect() + + if passed: + print("\nTest has passed :-)\n") + else: + print("\nTest has failed :-(\n") + +parser = argparse.ArgumentParser(description="Example for TRex Stateless, sending IMIX traffic") +parser.add_argument('-s', '--server', + dest='server', + help='Remote trex address', + default='127.0.0.1', + type = str) +parser.add_argument('-m', '--mult', + dest='mult', + help='Multiplier of traffic, see Stateless help for more info', + default='30%', + type = str) +args = parser.parse_args() + +# run the tests +imix_test(args.server, args.mult) + diff --git a/scripts/automation/trex_control_plane/stl/examples/stl_imix_bidir.py b/scripts/automation/trex_control_plane/stl/examples/stl_imix_bidir.py new file mode 100644 index 00000000..956b910a --- /dev/null +++ b/scripts/automation/trex_control_plane/stl/examples/stl_imix_bidir.py @@ -0,0 +1,113 @@ +import stl_path +from trex_stl_lib.api import * + +import imp +import time +import json +from pprint import pprint +import argparse + +# IMIX test +# it maps the ports to sides +# then it load a predefind profile 'IMIX' +# and attach it to both sides and inject +# at a certain rate for some time +# finally it checks that all packets arrived +def imix_test (server): + + + # create client + c = STLClient(server = server) + passed = True + + + try: + + # connect to server + c.connect() + + # take all the ports + c.reset() + + dir_0 = [0] + dir_1 = [1] + + print "Mapped ports to sides {0} <--> {1}".format(dir_0, dir_1) + + # load IMIX profile + profile_file = os.path.join(stl_path.STL_PROFILES_PATH, 'imix.py') + profile1 = STLProfile.load_py(profile_file, direction=0) + profile2 = STLProfile.load_py(profile_file, direction=1) + stream1 = profile1.get_streams() + stream2 = profile2.get_streams() + + # add both streams to ports + c.add_streams(stream1, ports = dir_0) + c.add_streams(stream2, ports = dir_1) + + # clear the stats before injecting + c.clear_stats() + + # choose rate and start traffic for 10 seconds on 5 mpps + duration = 30 + mult = "30%" + print "Injecting {0} <--> {1} on total rate of '{2}' for {3} seconds".format(dir_0, dir_1, mult, duration) + + c.start(ports = (dir_0 + dir_1), mult = mult, duration = duration, total = True) + + # block until done + c.wait_on_traffic(ports = (dir_0 + dir_1)) + + # read the stats after the test + stats = c.get_stats() + + # use this for debug info on all the stats + pprint(stats) + + # sum dir 0 + dir_0_opackets = sum([stats[i]["opackets"] for i in dir_0]) + dir_0_ipackets = sum([stats[i]["ipackets"] for i in dir_0]) + + # sum dir 1 + dir_1_opackets = sum([stats[i]["opackets"] for i in dir_1]) + dir_1_ipackets = sum([stats[i]["ipackets"] for i in dir_1]) + + + lost_0 = dir_0_opackets - dir_1_ipackets + lost_1 = dir_1_opackets - dir_0_ipackets + + print "\nPackets injected from {0}: {1:,}".format(dir_0, dir_0_opackets) + print "Packets injected from {0}: {1:,}".format(dir_1, dir_1_opackets) + + print "\npackets lost from {0} --> {1}: {2:,} pkts".format(dir_0, dir_1, lost_0) + print "packets lost from {0} --> {1}: {2:,} pkts".format(dir_1, dir_0, lost_1) + + if (lost_0 <= 0) and (lost_1 <= 0): # less or equal because we might have incoming arps etc. + passed = True + else: + passed = False + + + except STLError as e: + passed = False + print e + + finally: + c.disconnect() + + if passed: + print "\nTest has passed :-)\n" + else: + print "\nTest has failed :-(\n" + +parser = argparse.ArgumentParser(description="Example for TRex Stateless, sending IMIX traffic") +parser.add_argument('-s', '--server', + dest='server', + help='Remote trex address', + default='127.0.0.1', + type = str) +args = parser.parse_args() + +# run the tests +imix_test(args.server) + diff --git a/scripts/automation/trex_control_plane/stl/examples/stl_path.py b/scripts/automation/trex_control_plane/stl/examples/stl_path.py new file mode 100644 index 00000000..f190aab1 --- /dev/null +++ b/scripts/automation/trex_control_plane/stl/examples/stl_path.py @@ -0,0 +1,7 @@ +import sys, os + +# FIXME to the right path for trex_stl_lib +sys.path.insert(0, "../") + +STL_PROFILES_PATH = os.path.join(os.pardir, os.pardir, os.pardir, os.pardir, 'stl') + diff --git a/scripts/automation/trex_control_plane/stl/examples/stl_pcap.py b/scripts/automation/trex_control_plane/stl/examples/stl_pcap.py new file mode 100644 index 00000000..98af6134 --- /dev/null +++ b/scripts/automation/trex_control_plane/stl/examples/stl_pcap.py @@ -0,0 +1,117 @@ +import stl_path +from trex_stl_lib.api import * +import argparse +import sys + + +def packet_hook_generator (remove_fcs, vlan_id): + + def packet_hook (packet): + packet = Ether(packet) + + if vlan_id >= 0 and vlan_id <= 4096: + packet_l3 = packet.payload + packet = Ether() / Dot1Q(vlan = vlan_id) / packet_l3 + + if remove_fcs and packet.lastlayer().name == 'Padding': + packet.lastlayer().underlayer.remove_payload() + + return str(packet) + + return packet_hook + + +def inject_pcap (pcap_file, server, port, loop_count, ipg_usec, use_vm, remove_fcs, vlan_id): + + # create client + c = STLClient(server = server) + + if remove_fcs or vlan_id: + packet_hook = packet_hook_generator(remove_fcs, vlan_id) + else: + packet_hook = None + + try: + + vm = STLIPRange(dst = {'start': '10.0.0.1', 'end': '10.0.0.254', 'step' : 1}) if use_vm else None + + c.connect() + c.reset(ports = [port]) + + c.clear_stats() + c.push_pcap(pcap_file, + ipg_usec = ipg_usec, + count = loop_count, + vm = vm, + packet_hook = packet_hook) + + c.wait_on_traffic() + + + stats = c.get_stats() + opackets = stats[port]['opackets'] + print("{0} packets were Tx on port {1}\n".format(opackets, port)) + + except STLError as e: + print(e) + sys.exit(1) + + finally: + c.disconnect() + + +def setParserOptions(): + parser = argparse.ArgumentParser(prog="stl_pcap.py") + + parser.add_argument("-f", "--file", help = "pcap file to inject", + dest = "pcap", + required = True, + type = str) + + parser.add_argument("-s", "--server", help = "TRex server address", + dest = "server", + default = 'localhost', + type = str) + + parser.add_argument("-p", "--port", help = "port to inject on", + dest = "port", + required = True, + type = int) + + parser.add_argument("-n", "--number", help = "How many times to inject pcap [default is 1, 0 means forever]", + dest = "loop_count", + default = 1, + type = int) + + parser.add_argument("-i", help = "IPG in usec", + dest = "ipg", + default = 10.0, + type = float) + + parser.add_argument("-x", help = "Iterate over IP dest", + dest = "use_vm", + default = False, + action = "store_true") + + parser.add_argument("-r", "--remove-fcs", help = "Remove FCS if exists. Limited by Scapy capabilities.", + dest = "remove", + default = False, + action = "store_true") + + parser.add_argument("-v", "--vlan", help = "Add VLAN header with this ID. Limited by Scapy capabilities.", + dest = "vlan", + default = -1, + type = int) + + return parser + +def main (): + parser = setParserOptions() + options = parser.parse_args() + + inject_pcap(options.pcap, options.server, options.port, options.loop_count, options.ipg, options.use_vm, options.remove, options.vlan) + +# inject pcap +if __name__ == '__main__': + main() + diff --git a/scripts/automation/trex_control_plane/stl/examples/stl_pcap_remote.py b/scripts/automation/trex_control_plane/stl/examples/stl_pcap_remote.py new file mode 100644 index 00000000..c47eee31 --- /dev/null +++ b/scripts/automation/trex_control_plane/stl/examples/stl_pcap_remote.py @@ -0,0 +1,123 @@ +import stl_path +from trex_stl_lib.api import * +import argparse +import sys + + +def inject_pcap (c, pcap_file, port, loop_count, ipg_usec, duration): + + pcap_file = os.path.abspath(pcap_file) + + c.reset(ports = [port]) + c.push_remote(pcap_file, ports = [port], ipg_usec = ipg_usec, speedup = 1.0, count = loop_count, duration = duration) + # assume 100 seconds is enough - but can be more + c.wait_on_traffic(ports = [port], timeout = 100) + + stats = c.get_stats() + opackets = stats[port]['opackets'] + + return opackets + #print("{0} packets were Tx on port {1}\n".format(opackets, port)) + + + +def setParserOptions(): + parser = argparse.ArgumentParser(prog="stl_pcap.py") + + parser.add_argument("-f", "--file", help = "pcap file to inject", + dest = "pcap", + required = True, + type = str) + + parser.add_argument("-s", "--server", help = "TRex server address", + dest = "server", + default = 'localhost', + type = str) + + parser.add_argument("-p", "--port", help = "port to inject on", + dest = "port", + required = True, + type = int) + + parser.add_argument("-n", "--number", help = "How many times to inject pcap [default is 1, 0 means forever]", + dest = "loop_count", + default = 1, + type = int) + + parser.add_argument("-i", help = "IPG in usec", + dest = "ipg", + default = None, + type = float) + + parser.add_argument("-d", help = "duration in seconds", + dest = "duration", + default = -1, + type = float) + + return parser + +def sizeof_fmt(num, suffix='B'): + for unit in ['','Ki','Mi','Gi','Ti','Pi','Ei','Zi']: + if abs(num) < 1024.0: + return "%3.1f%s%s" % (num, unit, suffix) + num /= 1024.0 + return "%.1f%s%s" % (num, 'Yi', suffix) + + +def read_txt_file (filename): + + with open(filename) as f: + lines = f.readlines() + + caps = [] + for raw in lines: + raw = raw.rstrip() + if raw[0] == '#': + continue + ext=os.path.splitext(raw)[1] + if ext not in ['.cap', '.pcap', '.erf']: + # skip unknown format + continue + + caps.append(raw) + + return caps + + +def start (args): + + parser = setParserOptions() + options = parser.parse_args(args) + + ext = os.path.splitext(options.pcap)[1] + if ext == '.txt': + caps = read_txt_file(options.pcap) + elif ext in ['.cap', '.pcap']: + caps = [options.pcap] + else: + print("unknown file extension for file {0}".format(options.pcap)) + return + + c = STLClient(server = options.server) + try: + c.connect() + for i, cap in enumerate(caps, start = 1): + before = time.time() + print ("{:} CAP {:} @ {:} - ".format(i, cap, sizeof_fmt(os.path.getsize(cap)))), + injected = inject_pcap(c, cap, options.port, options.loop_count, options.ipg, options.duration) + print("took {:.2f} seconds for {:} packets").format(time.time() - before, injected) + + except STLError as e: + print(e) + return + + finally: + c.disconnect() + +def main (): + start(sys.argv[1:]) + +# inject pcap +if __name__ == '__main__': + main() + diff --git a/scripts/automation/trex_control_plane/stl/examples/stl_profile.py b/scripts/automation/trex_control_plane/stl/examples/stl_profile.py new file mode 100644 index 00000000..16d5238e --- /dev/null +++ b/scripts/automation/trex_control_plane/stl/examples/stl_profile.py @@ -0,0 +1,58 @@ +import stl_path +from trex_stl_lib.api import * + +import time + +def simple (): + + # create client + #verbose_level = LoggerApi.VERBOSE_HIGH + c = STLClient(verbose_level = LoggerApi.VERBOSE_REGULAR) + passed = True + + try: + # connect to server + c.connect() + + my_ports=[0,1] + + # prepare our ports + c.reset(ports = my_ports) + profile_file = os.path.join(stl_path.STL_PROFILES_PATH, 'hlt', 'udp_1pkt_simple.py') + + try: + profile = STLProfile.load(profile_file) + except STLError as e: + print(format_text("\nError while loading profile '{0}'\n".format(opts.file[0]), 'bold')) + print(e.brief() + "\n") + return + + print(profile.dump_to_yaml()) + + c.remove_all_streams(my_ports) + + + c.add_streams(profile.get_streams(), ports = my_ports) + + c.start(ports = [0, 1], mult = "5mpps", duration = 10) + + # block until done + c.wait_on_traffic(ports = [0, 1]) + + + except STLError as e: + passed = False + print(e) + + finally: + c.disconnect() + + if passed: + print("\nTest has passed :-)\n") + else: + print("\nTest has failed :-(\n") + + +# run the tests +simple() + diff --git a/scripts/automation/trex_control_plane/stl/examples/stl_run_udp_simple.py b/scripts/automation/trex_control_plane/stl/examples/stl_run_udp_simple.py new file mode 100644 index 00000000..d06414e4 --- /dev/null +++ b/scripts/automation/trex_control_plane/stl/examples/stl_run_udp_simple.py @@ -0,0 +1,218 @@ +#!/usr/bin/python +import sys, getopt +import argparse; +""" +Sample API application, +Connect to TRex +Send UDP packet in specific length +Each direction has its own IP range +Compare Rx-pkts to TX-pkts assuming ports are loopback + +""" + +import stl_path +from trex_stl_lib.api import * + +H_VER = "trex-x v0.1 " + +class t_global(object): + args=None; + + +import time +import json +import string + +def generate_payload(length): + word = '' + alphabet_size = len(string.letters) + for i in range(length): + word += string.letters[(i % alphabet_size)] + return word + +# simple packet creation +def create_pkt (frame_size = 9000, direction=0): + + ip_range = {'src': {'start': "10.0.0.1", 'end': "10.0.0.254"}, + 'dst': {'start': "8.0.0.1", 'end': "8.0.0.254"}} + + if (direction == 0): + src = ip_range['src'] + dst = ip_range['dst'] + else: + src = ip_range['dst'] + dst = ip_range['src'] + + vm = [ + # src + STLVmFlowVar(name="src",min_value=src['start'],max_value=src['end'],size=4,op="inc"), + STLVmWrFlowVar(fv_name="src",pkt_offset= "IP.src"), + + # dst + STLVmFlowVar(name="dst",min_value=dst['start'],max_value=dst['end'],size=4,op="inc"), + STLVmWrFlowVar(fv_name="dst",pkt_offset= "IP.dst"), + + # checksum + STLVmFixIpv4(offset = "IP") + ] + + pkt_base = Ether(src="00:00:00:00:00:01",dst="00:00:00:00:00:02")/IP()/UDP(dport=12,sport=1025) + pyld_size = frame_size - len(pkt_base); + pkt_pyld = generate_payload(pyld_size) + + return STLPktBuilder(pkt = pkt_base/pkt_pyld, + vm = vm) + + +def simple_burst (duration = 10, frame_size = 9000, speed = '1gbps'): + + if (frame_size < 60): + frame_size = 60 + + pkt_dir_0 = create_pkt (frame_size, 0) + + pkt_dir_1 = create_pkt (frame_size, 1) + + # create client + c = STLClient(server = t_global.args.ip) + + passed = True + + try: + # turn this on for some information + #c.set_verbose("high") + + # create two streams + s1 = STLStream(packet = pkt_dir_0, + mode = STLTXCont(pps = 100)) + + # second stream with a phase of 1ms (inter stream gap) + s2 = STLStream(packet = pkt_dir_1, + isg = 1000, + mode = STLTXCont(pps = 100)) + + if t_global.args.debug: + STLStream.dump_to_yaml ("example.yaml", [s1,s2]) # export to YAML so you can run it on simulator ./stl-sim -f example.yaml -o o.pcap + + # connect to server + c.connect() + + # prepare our ports (my machine has 0 <--> 1 with static route) + c.reset(ports = [0, 1]) + + # add both streams to ports + c.add_streams(s1, ports = [0]) + c.add_streams(s2, ports = [1]) + + # clear the stats before injecting + c.clear_stats() + + # choose rate and start traffic for 10 seconds on 5 mpps + print("Running {0} on ports 0, 1 for 10 seconds, UDP {1}...".format(speed,frame_size+4)) + c.start(ports = [0, 1], mult = speed, duration = duration) + + # block until done + c.wait_on_traffic(ports = [0, 1]) + + # read the stats after the test + stats = c.get_stats() + + #print stats + print(json.dumps(stats[0], indent = 4, separators=(',', ': '), sort_keys = True)) + print(json.dumps(stats[1], indent = 4, separators=(',', ': '), sort_keys = True)) + + lost_a = stats[0]["opackets"] - stats[1]["ipackets"] + lost_b = stats[1]["opackets"] - stats[0]["ipackets"] + + print("\npackets lost from 0 --> 1: {0} pkts".format(lost_a)) + print("packets lost from 1 --> 0: {0} pkts".format(lost_b)) + + if (lost_a == 0) and (lost_b == 0): + passed = True + else: + passed = False + + except STLError as e: + passed = False + print(e) + + finally: + c.disconnect() + + if passed: + print("\nPASSED\n") + else: + print("\nFAILED\n") + +def process_options (): + parser = argparse.ArgumentParser(usage=""" + connect to TRex and send burst of packets + + examples + + stl_run_udp_simple.py -s 9001 + + stl_run_udp_simple.py -s 9000 -d 2 + + stl_run_udp_simple.py -s 3000 -d 3 -m 10mbps + + stl_run_udp_simple.py -s 3000 -d 3 -m 10mbps --debug + + then run the simulator on the output + ./stl-sim -f example.yaml -o a.pcap ==> a.pcap include the packet + + """, + description="example for TRex api", + epilog=" written by hhaim"); + + parser.add_argument("-s", "--frame-size", + dest="frame_size", + help='L2 frame size in bytes without FCS', + default=60, + type = int, + ) + + parser.add_argument("--ip", + dest="ip", + help='remote trex ip default local', + default="127.0.0.1", + type = str + ) + + + parser.add_argument('-d','--duration', + dest='duration', + help='duration in second ', + default=10, + type = int, + ) + + + parser.add_argument('-m','--multiplier', + dest='mul', + help='speed in gbps/pps for example 1gbps, 1mbps, 1mpps ', + default="1mbps" + ) + + parser.add_argument('--debug', + action='store_true', + help='see debug into ') + + parser.add_argument('--version', action='version', + version=H_VER ) + + t_global.args = parser.parse_args(); + print(t_global.args) + + + +def main(): + process_options () + simple_burst(duration = t_global.args.duration, + frame_size = t_global.args.frame_size, + speed = t_global.args.mul + ) + +if __name__ == "__main__": + main() + diff --git a/scripts/automation/trex_control_plane/stl/examples/stl_simple_burst.py b/scripts/automation/trex_control_plane/stl/examples/stl_simple_burst.py new file mode 100644 index 00000000..4bd9fd4c --- /dev/null +++ b/scripts/automation/trex_control_plane/stl/examples/stl_simple_burst.py @@ -0,0 +1,71 @@ +import stl_path +from trex_stl_lib.api import * + +import time + +def simple_burst (port_a, port_b, pkt_size, burst_size, rate): + + # create client + c = STLClient() + passed = True + + try: + pkt_base = Ether()/IP(src="16.0.0.1",dst="48.0.0.1")/UDP(dport=12,sport=1025)/IP() + pad = max(0, pkt_size - len(pkt_base)) * 'x' + pkt = STLPktBuilder(pkt = pkt_base / pad) + + # create two bursts and link them + s1 = STLStream(name = 'A', + packet = pkt, + mode = STLTXSingleBurst(total_pkts = burst_size), + next = 'B') + + s2 = STLStream(name = 'B', + self_start = False, + packet = pkt, + mode = STLTXSingleBurst(total_pkts = burst_size)) + + # connect to server + c.connect() + + # prepare our ports + c.reset(ports = [port_a, port_b]) + + # add both streams to ports + stream_ids = c.add_streams([s1, s2], ports = [port_a, port_b]) + + # run 5 times + for i in range(1, 6): + c.clear_stats() + c.start(ports = [port_a, port_b], mult = rate) + c.wait_on_traffic(ports = [port_a, port_b]) + + stats = c.get_stats() + ipackets = stats['total']['ipackets'] + + print("Test iteration {0} - Packets Received: {1} ".format(i, ipackets)) + # two streams X 2 ports + if (ipackets != (burst_size * 2 * 2)): + passed = False + + except STLError as e: + passed = False + print(e) + + finally: + c.disconnect() + + if c.get_warnings(): + print("\n\n*** test had warnings ****\n\n") + for w in c.get_warnings(): + print(w) + + if passed and not c.get_warnings(): + print("\nTest has passed :-)\n") + else: + print("\nTest has failed :-(\n") + + +# run the tests +simple_burst(0, 3, 256, 50000, "80%") + diff --git a/scripts/automation/trex_control_plane/stl/examples/stl_simple_console_like.py b/scripts/automation/trex_control_plane/stl/examples/stl_simple_console_like.py new file mode 100644 index 00000000..1d4ef250 --- /dev/null +++ b/scripts/automation/trex_control_plane/stl/examples/stl_simple_console_like.py @@ -0,0 +1,60 @@ +import stl_path +from trex_stl_lib.api import * + +import time + +def simple (): + + # create client + #verbose_level = LoggerApi.VERBOSE_HIGH + c = STLClient(verbose_level = LoggerApi.VERBOSE_REGULAR) + passed = True + + try: + # connect to server + c.connect() + + my_ports=[0,1] + + # prepare our ports + c.reset(ports = my_ports) + + print((" is connected {0}".format(c.is_connected()))) + + print((" number of ports {0}".format(c.get_port_count()))) + print((" acquired_ports {0}".format(c.get_acquired_ports()))) + # port stats + print(c.get_stats(my_ports)) + # port info + print(c.get_port_info(my_ports)) + + c.ping() + profile_file = os.path.join(stl_path.STL_PROFILES_PATH, 'udp_1pkt_simple.py') + + print("start") + c.start_line (" -f %s -m 10mpps --port 0 1 " % profile_file) + time.sleep(2); + c.pause_line("--port 0 1"); + time.sleep(2); + c.resume_line("--port 0 1"); + time.sleep(2); + c.update_line("--port 0 1 -m 5mpps"); + time.sleep(2); + c.stop_line("--port 0 1"); + + except STLError as e: + passed = False + print(e) + + finally: + c.disconnect() + + if passed: + print("\nTest has passed :-)\n") + else: + print("\nTest has failed :-(\n") + + +# run the tests +simple() + diff --git a/scripts/automation/trex_control_plane/stl/examples/stl_simple_pin_core.py b/scripts/automation/trex_control_plane/stl/examples/stl_simple_pin_core.py new file mode 100644 index 00000000..6e3d5f7f --- /dev/null +++ b/scripts/automation/trex_control_plane/stl/examples/stl_simple_pin_core.py @@ -0,0 +1,72 @@ +import stl_path +from trex_stl_lib.api import * + +import time + +def simple_burst (port_a, port_b, pkt_size, burst_size, rate): + + # create client + c = STLClient() + passed = True + + try: + pkt_base = Ether()/IP(src="16.0.0.1",dst="48.0.0.1")/UDP(dport=12,sport=1025)/IP() + pad = max(0, pkt_size - len(pkt_base)) * 'x' + pkt = STLPktBuilder(pkt = pkt_base / pad) + + # create two bursts and link them + s1 = STLStream(name = 'A', + packet = pkt, + mode = STLTXSingleBurst(total_pkts = burst_size), + next = 'B') + + s2 = STLStream(name = 'B', + self_start = False, + packet = pkt, + mode = STLTXSingleBurst(total_pkts = burst_size)) + + # connect to server + c.connect() + + # prepare our ports + c.reset(ports = [port_a, port_b]) + + # add both streams to ports + stream_ids = c.add_streams([s1, s2], ports = [port_a, port_b]) + + # run 5 times + for i in range(1, 6): + c.clear_stats() + ## + c.start(ports = [port_a, port_b], mult = rate, core_mask=STLClient.CORE_MASK_PIN) # better performance + c.wait_on_traffic(ports = [port_a, port_b]) + + stats = c.get_stats() + ipackets = stats['total']['ipackets'] + + print("Test iteration {0} - Packets Received: {1} ".format(i, ipackets)) + # two streams X 2 ports + if (ipackets != (burst_size * 2 * 2)): + passed = False + + except STLError as e: + passed = False + print(e) + + finally: + c.disconnect() + + if c.get_warnings(): + print("\n\n*** test had warnings ****\n\n") + for w in c.get_warnings(): + print(w) + + if passed and not c.get_warnings(): + print("\nTest has passed :-)\n") + else: + print("\nTest has failed :-(\n") + + +# run the tests +simple_burst(0, 3, 256, 50000, "80%") + diff --git a/scripts/automation/trex_control_plane/stl/examples/using_rpc_proxy.py b/scripts/automation/trex_control_plane/stl/examples/using_rpc_proxy.py new file mode 100755 index 00000000..d2fcdff3 --- /dev/null +++ b/scripts/automation/trex_control_plane/stl/examples/using_rpc_proxy.py @@ -0,0 +1,149 @@ +#!/router/bin/python + +import argparse +import sys +import os +from time import sleep +from pprint import pprint + +# ext libs +ext_libs = os.path.join(os.pardir, os.pardir, os.pardir, os.pardir, 'external_libs') +sys.path.append(os.path.join(ext_libs, 'jsonrpclib-pelix-0.2.5')) +import jsonrpclib + +def fail(msg): + print(msg) + sys.exit(1) + +def verify(res): + if not res[0]: + fail(res[1]) + return res + +def verify_hlt(res): + if res['status'] == 0: + fail(res['log']) + return res + +### Main ### + +if __name__ == '__main__': + parser = argparse.ArgumentParser(description = 'Use of Stateless through rpc_proxy. (Can be implemented in any language)') + parser.add_argument('-s', '--server', type=str, default = 'localhost', dest='server', action = 'store', + help = 'Address of rpc proxy.') + parser.add_argument('-p', '--port', type=int, default = 8095, dest='port', action = 'store', + help = 'Port of rpc proxy.\nDefault is 8095.') + parser.add_argument('--master_port', type=int, default = 8091, dest='master_port', action = 'store', + help = 'Port of Master daemon.\nDefault is 8091.') + args = parser.parse_args() + + server = jsonrpclib.Server('http://%s:%s' % (args.server, args.port)) + master = jsonrpclib.Server('http://%s:%s' % (args.server, args.master_port)) + +# Connecting + + try: + print('Connecting to STL RPC proxy server') + server.check_connectivity() + print('Connected') + except Exception as e: + print('Could not connect to STL RPC proxy server: %s\nTrying to start it from Master daemon.' % e) + try: + master.check_connectivity() + master.start_stl_rpc_proxy() + print('Started') + except Exception as e: + print('Could not start it from Master daemon. Error: %s' % e) + sys.exit(-1) + + +# Native API + + print('Initializing Native Client') + verify(server.native_proxy_init(server = args.server, force = True)) + + print('Connecting to TRex server') + verify(server.connect()) + + print('Resetting all ports') + verify(server.reset()) + + print('Getting ports info') + res = verify(server.native_method(func_name = 'get_port_info')) + print('Ports info is: %s' % res[1]) + ports = [port['index'] for port in res[1]] + + print('Sending pcap to ports %s' % ports) + verify(server.push_remote(pcap_filename = 'stl/sample.pcap')) + sleep(3) + + print('Getting stats') + res = verify(server.get_stats()) + pprint(res[1]) + + print('Resetting all ports') + verify(server.reset()) + + imix_path_1 = '../../../../stl/imix.py' + imix_path_2 = '../../stl/imix.py' + if os.path.exists(imix_path_1): + imix_path = imix_path_1 + elif os.path.exists(imix_path_2): + imix_path = imix_path_2 + else: + print('Could not find path of imix profile, skipping') + imix_path = None + + if imix_path: + print('Adding profile %s' % imix_path) + verify(server.native_method(func_name = 'add_profile', filename = imix_path)) + + print('Start traffic for 5 sec') + verify(server.native_method('start')) + sleep(5) + + print('Getting stats') + res = verify(server.get_stats()) + pprint(res[1]) + + print('Resetting all ports') + verify(server.reset()) + + print('Deleting Native Client instance') + verify(server.native_proxy_del()) + +# HLTAPI + + print('Initializing HLTAPI Client') + verify_hlt(server.hltapi_proxy_init(force = True)) + print('HLTAPI Client initiated') + + print('HLTAPI connect') + verify_hlt(server.hlt_connect(device = args.server, port_list = ports, reset = True, break_locks = True)) + + print('Creating traffic') + verify_hlt(server.traffic_config( + mode = 'create', bidirectional = True, + port_handle = ports[0], port_handle2 = ports[1], + frame_size = 100, + l3_protocol = 'ipv4', + ip_src_addr = '10.0.0.1', ip_src_mode = 'increment', ip_src_count = 254, + ip_dst_addr = '8.0.0.1', ip_dst_mode = 'increment', ip_dst_count = 254, + l4_protocol = 'udp', + udp_dst_port = 12, udp_src_port = 1025, + rate_percent = 10, ignore_macs = True, + )) + + print('Starting traffic for 5 sec') + verify_hlt(server.traffic_control(action = 'run', port_handle = ports[:2])) + + sleep(5) + print('Stopping traffic') + verify_hlt(server.traffic_control(action = 'stop', port_handle = ports[:2])) + + print('Getting stats') + res = verify_hlt(server.traffic_stats(mode = 'aggregate', port_handle = ports[:2])) + pprint(res) + + print('Deleting HLTAPI Client instance') + verify_hlt(server.hltapi_proxy_del()) |