From a2a634fc8b5bac450ea37f29dde521b7d9e740c8 Mon Sep 17 00:00:00 2001 From: Dan Klein Date: Thu, 22 Oct 2015 13:44:25 +0300 Subject: minor updates --- scripts/automation/trex_control_plane/client/trex_hltapi.py | 6 ++++++ 1 file changed, 6 insertions(+) mode change 100644 => 100755 scripts/automation/trex_control_plane/client/trex_hltapi.py (limited to 'scripts/automation/trex_control_plane/client/trex_hltapi.py') diff --git a/scripts/automation/trex_control_plane/client/trex_hltapi.py b/scripts/automation/trex_control_plane/client/trex_hltapi.py old mode 100644 new mode 100755 index 46c283f8..b180eb5b --- a/scripts/automation/trex_control_plane/client/trex_hltapi.py +++ b/scripts/automation/trex_control_plane/client/trex_hltapi.py @@ -2,6 +2,7 @@ import trex_root_path from client_utils.packet_builder import CTRexPktBuilder +from trex_stateless_client import CTRexStatelessClient print "done!" @@ -10,6 +11,11 @@ class CTRexHltApi(object): def __init__(self): pass + def connect_status(self): + pass + + + def config_traffic(self): pass -- cgit From ebb0b48faca96bad7bfe8da0bf80df7c7c80350d Mon Sep 17 00:00:00 2001 From: Dan Klein Date: Sun, 25 Oct 2015 11:33:48 +0200 Subject: HLTAPI progress... --- .../trex_control_plane/client/trex_hltapi.py | 30 ++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) (limited to 'scripts/automation/trex_control_plane/client/trex_hltapi.py') diff --git a/scripts/automation/trex_control_plane/client/trex_hltapi.py b/scripts/automation/trex_control_plane/client/trex_hltapi.py index b180eb5b..7453d8ec 100755 --- a/scripts/automation/trex_control_plane/client/trex_hltapi.py +++ b/scripts/automation/trex_control_plane/client/trex_hltapi.py @@ -11,14 +11,40 @@ class CTRexHltApi(object): def __init__(self): pass - def connect_status(self): + def connect(self, device, port_list, username, reset=False, break_locks=False): pass + def interface_config(self, port_handle, mode="config"): + pass + + def get_status(self): + pass + + def get_port_handler(self): + pass + + def traffic_config(self, mode, port_handle, + mac_src, mac_dst, + l3_protocol, ip_src_addr, ip_dst_addr, l3_length, + transmit_mode, rate_pps): + pass + def traffic_control(self, action, port_handle): + pass - def config_traffic(self): + def traffic_stats(self, port_handle, mode): pass + def get_aggregate_port_stats(self, port_handle): + return self.traffic_stats(port_handle, mode="aggregate") + + def get_stream_stats(self, port_handle): + return self.traffic_stats(port_handle, mode="stream") + + + + + if __name__ == "__main__": pass -- cgit From a39e4416cd78fc3b147695465c4de1c896b3face Mon Sep 17 00:00:00 2001 From: Dan Klein Date: Tue, 27 Oct 2015 10:00:18 +0200 Subject: more hltapi progress connect working --- .../trex_control_plane/client/trex_hltapi.py | 72 ++++++++++++++++++++-- 1 file changed, 68 insertions(+), 4 deletions(-) (limited to 'scripts/automation/trex_control_plane/client/trex_hltapi.py') diff --git a/scripts/automation/trex_control_plane/client/trex_hltapi.py b/scripts/automation/trex_control_plane/client/trex_hltapi.py index 7453d8ec..6194d376 100755 --- a/scripts/automation/trex_control_plane/client/trex_hltapi.py +++ b/scripts/automation/trex_control_plane/client/trex_hltapi.py @@ -4,14 +4,54 @@ import trex_root_path from client_utils.packet_builder import CTRexPktBuilder from trex_stateless_client import CTRexStatelessClient -print "done!" class CTRexHltApi(object): def __init__(self): + self.trex_client = None + self.connected = False + + pass + + # ----- session functions ----- # + + def connect(self, device, port_list, username, port=5050, reset=False, break_locks=False): + ret_dict = {"status": 0} + self.trex_client = CTRexStatelessClient(username, device, port) + res_ok, msg = self.trex_client.connect() + if not res_ok: + self.trex_client = None + ret_dict.update({"log": msg}) + return ret_dict + # arrived here, connection successfully created with server + # next, try acquiring ports of TRex + port_list = self.parse_port_list(port_list) + response = self.trex_client.acquire(port_list, force=break_locks) + res_ok, log = CTRexHltApi.process_response(port_list, response) + if not res_ok: + self.trex_client.disconnect() + self.trex_client = None + ret_dict.update({"log": log}) + # TODO: should revert taken ports?! + return ret_dict + # arrived here, all desired ports were successfully acquired + print log + if reset: + # remove all port traffic configuration from TRex + response = self.trex_client.remove_all_streams(port_list) + res_ok, log = CTRexHltApi.process_response(port_list, response) + if not res_ok: + self.trex_client.disconnect() + self.trex_client = None + ret_dict.update({"log": log}) + return ret_dict + print log + ret_dict.update({"status": 1}) + self.trex_client.disconnect() + pass - def connect(self, device, port_list, username, reset=False, break_locks=False): + def cleanup_session(self, port_list, maintain_lock=False): pass def interface_config(self, port_handle, mode="config"): @@ -41,8 +81,32 @@ class CTRexHltApi(object): def get_stream_stats(self, port_handle): return self.traffic_stats(port_handle, mode="stream") - - + # ----- internal functions ----- # + @staticmethod + def process_response(port_list, response): + if isinstance(port_list, list): + res_ok, response = response + log = CTRexHltApi.join_batch_response(response) + else: + res_ok = response.success + log = str(response) + return res_ok, log + + @staticmethod + def parse_port_list(port_list): + if isinstance(port_list, str): + return [int(port) + for port in port_list.split()] + elif isinstance(port_list, list): + return [int(port) + for port in port_list] + else: + return port_list + + @staticmethod + def join_batch_response(responses): + return "\n".join([str(response) + for response in responses]) if __name__ == "__main__": -- cgit From 3bebf60874ec07d157944088ee3cfd5909eccc0f Mon Sep 17 00:00:00 2001 From: Dan Klein Date: Tue, 27 Oct 2015 16:02:29 +0200 Subject: More HLTAPI --- .../trex_control_plane/client/trex_hltapi.py | 67 +++++++++++++++++----- 1 file changed, 54 insertions(+), 13 deletions(-) (limited to 'scripts/automation/trex_control_plane/client/trex_hltapi.py') diff --git a/scripts/automation/trex_control_plane/client/trex_hltapi.py b/scripts/automation/trex_control_plane/client/trex_hltapi.py index 6194d376..b237071f 100755 --- a/scripts/automation/trex_control_plane/client/trex_hltapi.py +++ b/scripts/automation/trex_control_plane/client/trex_hltapi.py @@ -3,6 +3,7 @@ import trex_root_path from client_utils.packet_builder import CTRexPktBuilder from trex_stateless_client import CTRexStatelessClient +import dpkt class CTRexHltApi(object): @@ -46,28 +47,68 @@ class CTRexHltApi(object): ret_dict.update({"log": log}) return ret_dict print log - ret_dict.update({"status": 1}) - self.trex_client.disconnect() + port_handle = {device: {port: port # since only supporting single TRex at the moment, 1:1 map + for port in port_list} + } - pass + ret_dict.update({"status": 1, + "log": None, + "port_handle": port_handle, + "offline": 0}) # ports are online + return ret_dict def cleanup_session(self, port_list, maintain_lock=False): - pass + ret_dict = {"status": 0} + if not maintain_lock: + # release taken ports + if port_list == "all": + port_list = self.trex_client.get_acquired_ports() + else: + port_list = self.parse_port_list(port_list) + response = self.trex_client.release(port_list) + res_ok, log = CTRexHltApi.process_response(port_list, response) + print log + if not res_ok: + ret_dict.update({"log": log}) + return ret_dict + ret_dict.update({"status": 1, + "log": None}) + self.trex_client.disconnect() + self.trex_client = None + return ret_dict def interface_config(self, port_handle, mode="config"): - pass - - def get_status(self): - pass - - def get_port_handler(self): - pass + allowed_modes = ["config", "modify", "destroy"] + if mode not in allowed_modes: + raise ValueError("mode must be one of the following values: {modes}".format(modes=allowed_modes)) + # pass this function for now... + return {"status": 1, "log": None} + # ----- traffic functions ----- # def traffic_config(self, mode, port_handle, - mac_src, mac_dst, + l2_encap, mac_src, mac_dst, l3_protocol, ip_src_addr, ip_dst_addr, l3_length, transmit_mode, rate_pps): - pass + allowed_modes = ["create", "modify", "remove", "enable", "disable", "reset"] + if mode not in allowed_modes: + raise ValueError("mode must be one of the following values: {modes}".format(modes=allowed_modes)) + if mode == "create": + # create a new stream with desired attributes + pkt_bld = CTRexPktBuilder() + if l2_encap == "ethernet_ii": + pkt_bld.add_pkt_layer("l2", dpkt.ethernet.Ethernet()) + # set Ethernet layer attributes + pkt_bld.set_eth_layer_addr("l2", "src", mac_src) + pkt_bld.set_eth_layer_addr("l2", "dst", mac_dst) + else: + raise NotImplementedError("l2_encap does not support the desired encapsulation '{0}'".format(l2_encap)) + # set l3 attrubutes + if l3_protocol == "ipv4": + + + pass + else: + raise NotImplementedError("mode '{0}' is not supported yet on TRex".format(mode)) def traffic_control(self, action, port_handle): pass -- cgit From fe6e03366eae72376f1201ed68744cb1206773de Mon Sep 17 00:00:00 2001 From: Dan Klein Date: Wed, 28 Oct 2015 07:36:08 +0200 Subject: more HLTAPI 2 --- .../trex_control_plane/client/trex_hltapi.py | 64 ++++++++++++++++------ 1 file changed, 48 insertions(+), 16 deletions(-) (limited to 'scripts/automation/trex_control_plane/client/trex_hltapi.py') diff --git a/scripts/automation/trex_control_plane/client/trex_hltapi.py b/scripts/automation/trex_control_plane/client/trex_hltapi.py index b237071f..cc7005e8 100755 --- a/scripts/automation/trex_control_plane/client/trex_hltapi.py +++ b/scripts/automation/trex_control_plane/client/trex_hltapi.py @@ -78,9 +78,9 @@ class CTRexHltApi(object): return ret_dict def interface_config(self, port_handle, mode="config"): - allowed_modes = ["config", "modify", "destroy"] - if mode not in allowed_modes: - raise ValueError("mode must be one of the following values: {modes}".format(modes=allowed_modes)) + ALLOWED_MODES = ["config", "modify", "destroy"] + if mode not in ALLOWED_MODES: + raise ValueError("mode must be one of the following values: {modes}".format(modes=ALLOWED_MODES)) # pass this function for now... return {"status": 1, "log": None} @@ -89,21 +89,15 @@ class CTRexHltApi(object): l2_encap, mac_src, mac_dst, l3_protocol, ip_src_addr, ip_dst_addr, l3_length, transmit_mode, rate_pps): - allowed_modes = ["create", "modify", "remove", "enable", "disable", "reset"] - if mode not in allowed_modes: - raise ValueError("mode must be one of the following values: {modes}".format(modes=allowed_modes)) + ALLOWED_MODES = ["create", "modify", "remove", "enable", "disable", "reset"] + if mode not in ALLOWED_MODES: + raise ValueError("mode must be one of the following values: {modes}".format(modes=ALLOWED_MODES)) if mode == "create": # create a new stream with desired attributes - pkt_bld = CTRexPktBuilder() - if l2_encap == "ethernet_ii": - pkt_bld.add_pkt_layer("l2", dpkt.ethernet.Ethernet()) - # set Ethernet layer attributes - pkt_bld.set_eth_layer_addr("l2", "src", mac_src) - pkt_bld.set_eth_layer_addr("l2", "dst", mac_dst) - else: - raise NotImplementedError("l2_encap does not support the desired encapsulation '{0}'".format(l2_encap)) - # set l3 attrubutes - if l3_protocol == "ipv4": + stream = CTRexHltApi.generate_stream(l2_encap, mac_src, mac_dst, + l3_protocol, ip_src_addr, ip_dst_addr, l3_length, + transmit_mode, rate_pps) + pass @@ -149,6 +143,44 @@ class CTRexHltApi(object): return "\n".join([str(response) for response in responses]) + @staticmethod + def generate_stream(l2_encap, mac_src, mac_dst, + l3_protocol, ip_src_addr, ip_dst_addr, l3_length, + transmit_mode, rate_pps): + ALLOWED_L3_PROTOCOL = {"ipv4": dpkt.ethernet.ETH_TYPE_IP, + "ipv6": dpkt.ethernet.ETH_TYPE_IP6, + "arp": dpkt.ethernet.ETH_TYPE_ARP} + ALLOWED_L4_PROTOCOL = {"tcp": dpkt.ip.IP_PROTO_TCP, + "udp": dpkt.ip.IP_PROTO_UDP, + "icmp": dpkt.ip.IP_PROTO_ICMP, + "icmpv6": dpkt.ip.IP_PROTO_ICMP6, + "igmp": dpkt.ip.IP_PROTO_IGMP, + "rtp": dpkt.ip.IP_PROTO_IRTP, + "isis": dpkt.ip.IP_PROTO_ISIS, + "ospf": dpkt.ip.IP_PROTO_OSPF} + + pkt_bld = CTRexPktBuilder() + if l2_encap == "ethernet_ii": + pkt_bld.add_pkt_layer("l2", dpkt.ethernet.Ethernet()) + # set Ethernet layer attributes + pkt_bld.set_eth_layer_addr("l2", "src", mac_src) + pkt_bld.set_eth_layer_addr("l2", "dst", mac_dst) + else: + raise NotImplementedError("l2_encap does not support the desired encapsulation '{0}'".format(l2_encap)) + # set l3 on l2 + if l3_protocol not in ALLOWED_L3_PROTOCOL: + raise ValueError("l3_protocol must be one of the following: {0}".format(ALLOWED_L3_PROTOCOL)) + pkt_bld.set_layer_attr("l2", "type", ALLOWED_L3_PROTOCOL[l3_protocol]) + + # set l3 attributes + if l3_protocol == "ipv4": + pkt_bld.add_pkt_layer("l3", dpkt.ip.IP()) + pkt_bld.set_ip_layer_addr("l3", "src", ip_src_addr) + pkt_bld.set_ip_layer_addr("l3", "dst", ip_dst_addr) + else: + raise NotImplementedError("l3_protocol '{0}' is not supported by TRex yet.".format(l3_protocol)) + + if __name__ == "__main__": pass -- cgit From 0c2b3c83f9cc0c25277c39660dce132aad55c3d7 Mon Sep 17 00:00:00 2001 From: Dan Klein Date: Wed, 28 Oct 2015 07:28:37 +0200 Subject: updated more HLTAPI functionality and fixed found bugs. Working: Start/stop traffic, traffic config (semi), connect, clean Missing: stats Next: boost console --- .../trex_control_plane/client/trex_hltapi.py | 158 ++++++++++++++++++--- 1 file changed, 139 insertions(+), 19 deletions(-) (limited to 'scripts/automation/trex_control_plane/client/trex_hltapi.py') diff --git a/scripts/automation/trex_control_plane/client/trex_hltapi.py b/scripts/automation/trex_control_plane/client/trex_hltapi.py index cc7005e8..92768ca4 100755 --- a/scripts/automation/trex_control_plane/client/trex_hltapi.py +++ b/scripts/automation/trex_control_plane/client/trex_hltapi.py @@ -3,6 +3,8 @@ import trex_root_path from client_utils.packet_builder import CTRexPktBuilder from trex_stateless_client import CTRexStatelessClient +from common.trex_streams import * +from client_utils.general_utils import id_count_gen import dpkt @@ -11,8 +13,8 @@ class CTRexHltApi(object): def __init__(self): self.trex_client = None self.connected = False - - pass + # self._stream_db = CStreamList() + self._port_data = {} # ----- session functions ----- # @@ -50,11 +52,12 @@ class CTRexHltApi(object): port_handle = {device: {port: port # since only supporting single TRex at the moment, 1:1 map for port in port_list} } - ret_dict.update({"status": 1, "log": None, "port_handle": port_handle, "offline": 0}) # ports are online + self.connected = True + self._port_data_init(port_list) return ret_dict def cleanup_session(self, port_list, maintain_lock=False): @@ -75,6 +78,7 @@ class CTRexHltApi(object): "log": None}) self.trex_client.disconnect() self.trex_client = None + self.connected = False return ret_dict def interface_config(self, port_handle, mode="config"): @@ -86,37 +90,150 @@ class CTRexHltApi(object): # ----- traffic functions ----- # def traffic_config(self, mode, port_handle, - l2_encap, mac_src, mac_dst, - l3_protocol, ip_src_addr, ip_dst_addr, l3_length, - transmit_mode, rate_pps): + l2_encap="ethernet_ii", mac_src="00:00:01:00:00:01", mac_dst="00:00:00:00:00:00", + l3_protocol="ipv4", ip_src_addr="0.0.0.0", ip_dst_addr="192.0.0.1", l3_length=110, + transmit_mode="continuous", rate_pps=100, + **kwargs): ALLOWED_MODES = ["create", "modify", "remove", "enable", "disable", "reset"] if mode not in ALLOWED_MODES: raise ValueError("mode must be one of the following values: {modes}".format(modes=ALLOWED_MODES)) if mode == "create": - # create a new stream with desired attributes - stream = CTRexHltApi.generate_stream(l2_encap, mac_src, mac_dst, - l3_protocol, ip_src_addr, ip_dst_addr, l3_length, - transmit_mode, rate_pps) - - - - pass + # create a new stream with desired attributes, starting by creating packet + try: + packet = CTRexHltApi.generate_stream(l2_encap, mac_src, mac_dst, + l3_protocol, ip_src_addr, ip_dst_addr, l3_length) + # set transmission attributes + tx_mode = CTxMode(transmit_mode, rate_pps, **kwargs) + # set rx_stats + rx_stats = CRxStats() # defaults with disabled + # join the generated data into stream + stream_obj = CStream() + stream_obj_params = {"enabled": True, + "self_start": True, + "next_stream_id": -1, + "isg": 0.0, + "mode": tx_mode, + "rx_stats": rx_stats, + "packet": packet} # vm is excluded from this list since CTRexPktBuilder obj is passed + stream_obj.load_data(**stream_obj_params) + except Exception as e: + # some exception happened during the stream creation + return {"status": 0, "log": str(e)} + # try adding the stream, until free stream_id is found + port_data = self._port_data.get(port_handle) + id_candidate = None + # TODO: change this to better implementation + while True: + id_candidate = port_data["stream_id_gen"].next() + response = self.trex_client.add_stream(stream_id=id_candidate, + stream_obj=stream_obj, + port_id=port_handle) + res_ok, log = CTRexHltApi.process_response(port_handle, response) + if res_ok: + # found non-taken stream_id on server + # save it for modifying needs + port_data["streams"].update({id_candidate: stream_obj}) + break + else: + # proceed to another iteration to use another id + continue + return {"status": 1, + "stream_id": id_candidate, + "log": None} else: raise NotImplementedError("mode '{0}' is not supported yet on TRex".format(mode)) def traffic_control(self, action, port_handle): - pass + ALLOWED_ACTIONS = ["clear_stats", "run", "stop", "sync_run"] + if action not in ALLOWED_ACTIONS: + raise ValueError("action must be one of the following values: {actions}".format(actions=ALLOWED_ACTIONS)) + # ret_dict = {"status": 0, "stopped": 1} + port_list = self.parse_port_list(port_handle) + if action == "run": + response = self.trex_client.start_traffic(port_id=port_list) + res_ok, log = CTRexHltApi.process_response(port_list, response) + if res_ok: + return {"status": 1, + "stopped": 0, + "log": None} + elif action == "stop": + response = self.trex_client.stop_traffic(port_id=port_list) + res_ok, log = CTRexHltApi.process_response(port_list, response) + if res_ok: + return {"status": 1, + "stopped": 1, + "log": None} + else: + raise NotImplementedError("action '{0}' is not supported yet on TRex".format(action)) + + # if we arrived here, this means that operation FAILED! + return {"status": 0, + "log": log} + def traffic_stats(self, port_handle, mode): - pass + ALLOWED_MODES = ["aggregate", "streams", "all"] + if mode not in ALLOWED_MODES: + raise ValueError("mode must be one of the following values: {modes}".format(modes=ALLOWED_MODES)) + # pass this function for now... + if mode == "aggregate": + # create a new stream with desired attributes, starting by creating packet + try: + packet = CTRexHltApi.generate_stream(l2_encap, mac_src, mac_dst, + l3_protocol, ip_src_addr, ip_dst_addr, l3_length) + # set transmission attributes + tx_mode = CTxMode(transmit_mode, rate_pps, **kwargs) + # set rx_stats + rx_stats = CRxStats() # defaults with disabled + # join the generated data into stream + stream_obj = CStream() + stream_obj_params = {"enabled": True, + "self_start": True, + "next_stream_id": -1, + "isg": 0.0, + "mode": tx_mode, + "rx_stats": rx_stats, + "packet": packet} # vm is excluded from this list since CTRexPktBuilder obj is passed + stream_obj.load_data(**stream_obj_params) + except Exception as e: + # some exception happened during the stream creation + return {"status": 0, "log": str(e)} + # try adding the stream, until free stream_id is found + port_data = self._port_data.get(port_handle) + id_candidate = None + # TODO: change this to better implementation + while True: + id_candidate = port_data["stream_id_gen"].next() + response = self.trex_client.add_stream(stream_id=id_candidate, + stream_obj=stream_obj, + port_id=port_handle) + res_ok, log = CTRexHltApi.process_response(port_handle, response) + if res_ok: + # found non-taken stream_id on server + # save it for modifying needs + port_data["streams"].update({id_candidate: stream_obj}) + break + else: + # proceed to another iteration to use another id + continue + return {"status": 1, + "stream_id": id_candidate, + "log": None} + else: + raise NotImplementedError("mode '{0}' is not supported yet on TRex".format(mode)) def get_aggregate_port_stats(self, port_handle): return self.traffic_stats(port_handle, mode="aggregate") def get_stream_stats(self, port_handle): - return self.traffic_stats(port_handle, mode="stream") + return self.traffic_stats(port_handle, mode="streams") # ----- internal functions ----- # + def _port_data_init(self, port_list): + for port in port_list: + self._port_data[port] = {"stream_id_gen": id_count_gen(), + "streams": {}} + @staticmethod def process_response(port_list, response): if isinstance(port_list, list): @@ -145,8 +262,7 @@ class CTRexHltApi(object): @staticmethod def generate_stream(l2_encap, mac_src, mac_dst, - l3_protocol, ip_src_addr, ip_dst_addr, l3_length, - transmit_mode, rate_pps): + l3_protocol, ip_src_addr, ip_dst_addr, l3_length): ALLOWED_L3_PROTOCOL = {"ipv4": dpkt.ethernet.ETH_TYPE_IP, "ipv6": dpkt.ethernet.ETH_TYPE_IP6, "arp": dpkt.ethernet.ETH_TYPE_ARP} @@ -177,9 +293,13 @@ class CTRexHltApi(object): pkt_bld.add_pkt_layer("l3", dpkt.ip.IP()) pkt_bld.set_ip_layer_addr("l3", "src", ip_src_addr) pkt_bld.set_ip_layer_addr("l3", "dst", ip_dst_addr) + pkt_bld.set_layer_attr("l3", "len", l3_length) else: raise NotImplementedError("l3_protocol '{0}' is not supported by TRex yet.".format(l3_protocol)) + pkt_bld.dump_pkt_to_pcap("stream_test.pcap") + return pkt_bld + if __name__ == "__main__": -- cgit