diff options
author | 2016-05-08 17:32:12 +0300 | |
---|---|---|
committer | 2016-05-09 16:48:16 +0300 | |
commit | db9145d248720c633dd4da6c785e071198986326 (patch) | |
tree | 86e00a08895f65e2840b2bf8a921b9e9298f11a1 | |
parent | 75ce59e5652f9094beab854d263a850cfc81a3de (diff) |
added duration to remote push
-rw-r--r-- | scripts/automation/trex_control_plane/stl/examples/stl_pcap_remote.py | 121 | ||||
-rwxr-xr-x | scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_client.py | 112 | ||||
-rw-r--r-- | scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_port.py | 11 | ||||
-rwxr-xr-x | scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_streams.py | 5 | ||||
-rwxr-xr-x | src/bp_sim.h | 16 | ||||
-rw-r--r-- | src/main_dpdk.cpp | 21 | ||||
-rw-r--r-- | src/rpc-server/commands/trex_rpc_cmd_general.cpp | 3 | ||||
-rw-r--r-- | src/rpc-server/commands/trex_rpc_cmds.h | 2 | ||||
-rw-r--r-- | src/stateless/cp/trex_stateless_port.cpp | 10 | ||||
-rw-r--r-- | src/stateless/cp/trex_stateless_port.h | 6 | ||||
-rw-r--r-- | src/stateless/dp/trex_stateless_dp_core.cpp | 20 | ||||
-rw-r--r-- | src/stateless/dp/trex_stateless_dp_core.h | 7 | ||||
-rw-r--r-- | src/stateless/dp/trex_stream_node.h | 4 | ||||
-rw-r--r-- | src/stateless/messaging/trex_stateless_messaging.cpp | 11 | ||||
-rw-r--r-- | src/stateless/messaging/trex_stateless_messaging.h | 5 |
15 files changed, 310 insertions, 44 deletions
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..2270b51c --- /dev/null +++ b/scripts/automation/trex_control_plane/stl/examples/stl_pcap_remote.py @@ -0,0 +1,121 @@ +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'] + #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)))), + inject_pcap(c, cap, options.port, options.loop_count, options.ipg, options.duration) + print("took {:.2f} seconds").format(time.time()-before) + + 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/trex_stl_lib/trex_stl_client.py b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_client.py index 0d95131f..9f96b237 100755 --- a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_client.py +++ b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_client.py @@ -722,13 +722,13 @@ class STLClient(object): return rc - def __push_remote (self, pcap_filename, port_id_list, ipg_usec, speedup, count): + def __push_remote (self, pcap_filename, port_id_list, ipg_usec, speedup, count, duration): port_id_list = self.__ports(port_id_list) rc = RC() for port_id in port_id_list: - rc.add(self.ports[port_id].push_remote(pcap_filename, ipg_usec, speedup, count)) + rc.add(self.ports[port_id].push_remote(pcap_filename, ipg_usec, speedup, count, duration)) return rc @@ -1874,9 +1874,15 @@ class STLClient(object): @__api_check(True) - def push_remote (self, pcap_filename, ports = None, ipg_usec = None, speedup = 1.0, count = 1): + def push_remote (self, + pcap_filename, + ports = None, + ipg_usec = None, + speedup = 1.0, + count = 1, + duration = -1): """ - Push a remote reachable PCAP file + Push a remote server-reachable PCAP file the path must be fullpath accessible to the server :parameters: @@ -1895,7 +1901,8 @@ class STLClient(object): count: int How many times to transmit the cap - + duration: float + Limit runtime by duration in seconds :raises: + :exc:`STLError` @@ -1905,11 +1912,12 @@ class STLClient(object): validate_type('pcap_filename', pcap_filename, str) validate_type('ipg_usec', ipg_usec, (float, int, type(None))) - validate_type('speedup', speedup, float) + validate_type('speedup', speedup, (float, int)) validate_type('count', count, int) + validate_type('duration', duration, (float, int)) - self.logger.pre_cmd("Pushing remote pcap on port(s) {0}:".format(ports)) - rc = self.__push_remote(pcap_filename, ports, ipg_usec, speedup, count) + self.logger.pre_cmd("Pushing remote PCAP on port(s) {0}:".format(ports)) + rc = self.__push_remote(pcap_filename, ports, ipg_usec, speedup, count, duration) self.logger.post_cmd(rc) if not rc: @@ -1917,7 +1925,71 @@ class STLClient(object): @__api_check(True) - def validate (self, ports = None, mult = "1", duration = "-1", total = False): + def push_pcap (self, + pcap_filename, + ports = None, + ipg_usec = None, + speedup = 1.0, + count = 1, + duration = -1): + """ + Push a local PCAP to the server + This is equivalent to loading a PCAP file to a profile + and attaching the profile to port(s) + + file size is limited to 1MB + + :parameters: + pcap_filename : str + PCAP filename (accessible locally) + + ports : list + Ports on which to execute the command + + ipg_usec : float + Inter-packet gap in microseconds + + speedup : float + A factor to adjust IPG. effectively IPG = IPG / speedup + + count: int + How many times to transmit the cap + + duration: float + Limit runtime by duration in seconds + + :raises: + + :exc:`STLError` + + """ + ports = ports if ports is not None else self.get_acquired_ports() + ports = self._validate_port_list(ports) + + validate_type('pcap_filename', pcap_filename, str) + validate_type('ipg_usec', ipg_usec, (float, int, type(None))) + validate_type('speedup', speedup, (float, int)) + validate_type('count', count, int) + validate_type('duration', duration, (float, int)) + + # no support for > 1MB PCAP - use push remote + if os.path.getsize(pcap_filename) > (1024 * 1024): + raise STLError("PCAP size of {:,} B is too big for local push - consider using remote push".format(os.path.getsize(pcap_filename))) + + self.remove_all_streams(ports = ports) + + profile = STLProfile.load_pcap(pcap_filename, + ipg_usec, + speedup, + count) + + + id_list = self.add_streams(profile.get_streams(), ports) + + return self.start(ports = ports, duration = duration) + + + @__api_check(True) + def validate (self, ports = None, mult = "1", duration = -1, total = False): """ Validate port(s) configuration @@ -1964,6 +2036,8 @@ class STLClient(object): rc = self.__validate(ports) self.logger.post_cmd(rc) + if not rc: + raise STLError(rc) for port in ports: self.ports[port].print_profile(mult_obj, duration) @@ -2606,24 +2680,24 @@ class STLClient(object): else: self.stop(active_ports) - # pcap injection removes all previous streams from the ports + if opts.remote: self.push_remote(opts.file[0], ports = opts.ports, ipg_usec = opts.ipg_usec, speedup = opts.speedup, - count = opts.count) + count = opts.count, + duration = opts.duration) else: - self.remove_all_streams(ports = opts.ports) - - profile = STLProfile.load_pcap(opts.file[0], - opts.ipg_usec, - opts.speedup, - opts.count) + self.push_pcap(opts.file[0], + ports = opts.ports, + ipg_usec = opts.ipg_usec, + speedup = opts.speedup, + count = opts.count, + duration = opts.duration) - id_list = self.add_streams(profile.get_streams(), opts.ports) - self.start(ports = opts.ports, duration = opts.duration, force = opts.force) + return True diff --git a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_port.py b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_port.py index 43fc29e6..391b2076 100644 --- a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_port.py +++ b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_port.py @@ -476,6 +476,9 @@ class Port(object): @owned def pause (self): + if (self.state == self.STATE_PCAP_TX) : + return self.err("pause is not supported during PCAP TX") + if (self.state != self.STATE_TX) : return self.err("port is not transmitting") @@ -512,6 +515,9 @@ class Port(object): @owned def update (self, mul, force): + if (self.state == self.STATE_PCAP_TX) : + return self.err("update is not supported during PCAP TX") + if (self.state != self.STATE_TX) : return self.err("port is not transmitting") @@ -561,14 +567,15 @@ class Port(object): return self.ok() @writeable - def push_remote (self, pcap_filename, ipg_usec, speedup, count): + def push_remote (self, pcap_filename, ipg_usec, speedup, count, duration): params = {"handler": self.handler, "port_id": self.port_id, "pcap_filename": pcap_filename, "ipg_usec": ipg_usec if ipg_usec is not None else -1, "speedup": speedup, - "count": count} + "count": count, + "duration": duration} rc = self.transmit("push_remote", params) if rc.bad(): diff --git a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_streams.py b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_streams.py index 66aeaef4..92598312 100755 --- a/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_streams.py +++ b/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_streams.py @@ -959,8 +959,8 @@ class STLProfile(object): raise STLError("file '{0}' does not exists".format(pcap_file)) # make sure IPG is not less than 1 usec - if ipg_usec is not None and ipg_usec < 1: - raise STLError("ipg_usec cannot be less than 1 usec: '{0}'".format(ipg_usec)) + if ipg_usec is not None and ipg_usec < 0.001: + raise STLError("ipg_usec cannot be less than 0.001 usec: '{0}'".format(ipg_usec)) if loop_count < 0: raise STLError("'loop_count' cannot be negative") @@ -989,7 +989,6 @@ class STLProfile(object): next = i + 1 action_count = 0 - streams.append(STLStream(name = i, packet = STLPktBuilder(pkt_buffer = cap, vm = vm), mode = STLTXSingleBurst(total_pkts = 1, percentage = 100), diff --git a/src/bp_sim.h b/src/bp_sim.h index 132824b3..77101508 100755 --- a/src/bp_sim.h +++ b/src/bp_sim.h @@ -1440,7 +1440,9 @@ public: NODE_FLAGS_LATENCY =0x20, /* got NAT msg */ NODE_FLAGS_INIT_START_FROM_SERVER_SIDE = 0x40, NODE_FLAGS_ALL_FLOW_SAME_PORT_SIDE = 0x80, - NODE_FLAGS_INIT_START_FROM_SERVER_SIDE_SERVER_ADDR = 0x100 /* init packet start from server side with server addr */ + NODE_FLAGS_INIT_START_FROM_SERVER_SIDE_SERVER_ADDR = 0x100, /* init packet start from server side with server addr */ + + NODE_FLAGS_SLOW_PATH = 0x200 /* used by the nodes to differ between fast path nodes and slow path nodes */ }; @@ -1479,6 +1481,17 @@ public: return ( m_socket_id ); } + inline void set_slow_path(bool enable) { + if (enable) { + m_flags |= NODE_FLAGS_SLOW_PATH; + } else { + m_flags &= ~NODE_FLAGS_SLOW_PATH; + } + } + + inline bool get_is_slow_path() const { + return ( (m_flags & NODE_FLAGS_SLOW_PATH) ? true : false); + } void free_base(); }; @@ -1581,6 +1594,7 @@ public: return ( (m_flags &NODE_FLAGS_ALL_FLOW_SAME_PORT_SIDE)?true:false ); } + /* direction for ip addr */ inline pkt_dir_t cur_pkt_ip_addr_dir(); diff --git a/src/main_dpdk.cpp b/src/main_dpdk.cpp index 5a383bc6..c8921ba7 100644 --- a/src/main_dpdk.cpp +++ b/src/main_dpdk.cpp @@ -1774,6 +1774,7 @@ class CCoreEthIFStateless : public CCoreEthIF { public: virtual int send_node(CGenNode * node); protected: + int handle_slow_path_node(CGenNode *node); int send_pcap_node(CGenNodePCAP *pcap_node); }; @@ -2002,11 +2003,12 @@ void CCoreEthIF::update_mac_addr(CGenNode * node,uint8_t *p){ int CCoreEthIFStateless::send_node(CGenNode * no) { - /* slow path - PCAP nodes */ - if (no->m_type == CGenNode::PCAP_PKT) { - return send_pcap_node((CGenNodePCAP *)no); + /* if a node is marked as slow path - single IF to redirect it to slow path */ + if (no->get_is_slow_path()) { + return handle_slow_path_node(no); } + CGenNodeStateless * node_sl=(CGenNodeStateless *) no; /* check that we have mbuf */ rte_mbuf_t * m=node_sl->get_cache_mbuf(); @@ -2050,6 +2052,19 @@ int CCoreEthIFStateless::send_pcap_node(CGenNodePCAP *pcap_node) { return (0); } +/** + * slow path code goes here + * + */ +int CCoreEthIFStateless::handle_slow_path_node(CGenNode * no) { + + if (no->m_type == CGenNode::PCAP_PKT) { + return send_pcap_node((CGenNodePCAP *)no); + } + + return (-1); +} + int CCoreEthIF::send_node(CGenNode * node){ diff --git a/src/rpc-server/commands/trex_rpc_cmd_general.cpp b/src/rpc-server/commands/trex_rpc_cmd_general.cpp index 5fe707af..27376fe4 100644 --- a/src/rpc-server/commands/trex_rpc_cmd_general.cpp +++ b/src/rpc-server/commands/trex_rpc_cmd_general.cpp @@ -465,11 +465,12 @@ TrexRpcCmdPushRemote::_run(const Json::Value ¶ms, Json::Value &result) { double ipg_usec = parse_double(params, "ipg_usec", result); double speedup = parse_double(params, "speedup", result); uint32_t count = parse_uint32(params, "count", result); + double duration = parse_double(params, "duration", result); TrexStatelessPort *port = get_stateless_obj()->get_port_by_id(port_id); try { - port->push_remote(pcap_filename, ipg_usec, speedup, count); + port->push_remote(pcap_filename, ipg_usec, speedup, count, duration); } catch (const TrexException &ex) { generate_execute_err(result, ex.what()); } diff --git a/src/rpc-server/commands/trex_rpc_cmds.h b/src/rpc-server/commands/trex_rpc_cmds.h index 99c83545..affa65c1 100644 --- a/src/rpc-server/commands/trex_rpc_cmds.h +++ b/src/rpc-server/commands/trex_rpc_cmds.h @@ -130,7 +130,7 @@ TREX_RPC_CMD_DEFINE(TrexRpcCmdUpdateTraffic, "update_traffic", 3, true, APIClass TREX_RPC_CMD_DEFINE(TrexRpcCmdValidate, "validate", 2, false, APIClass::API_CLASS_TYPE_CORE); -TREX_RPC_CMD_DEFINE(TrexRpcCmdPushRemote, "push_remote", 5, true, APIClass::API_CLASS_TYPE_CORE); +TREX_RPC_CMD_DEFINE(TrexRpcCmdPushRemote, "push_remote", 6, true, APIClass::API_CLASS_TYPE_CORE); #endif /* __TREX_RPC_CMD_H__ */ diff --git a/src/stateless/cp/trex_stateless_port.cpp b/src/stateless/cp/trex_stateless_port.cpp index aa2d43f3..360cc7d6 100644 --- a/src/stateless/cp/trex_stateless_port.cpp +++ b/src/stateless/cp/trex_stateless_port.cpp @@ -416,7 +416,12 @@ TrexStatelessPort::update_traffic(const TrexPortMultiplier &mul, bool force) { } void -TrexStatelessPort::push_remote(const std::string &pcap_filename, double ipg_usec, double speedup, uint32_t count) { +TrexStatelessPort::push_remote(const std::string &pcap_filename, + double ipg_usec, + double speedup, + uint32_t count, + double duration) { + /* command allowed only on state stream */ verify_state(PORT_STATE_IDLE | PORT_STATE_STREAMS); @@ -449,7 +454,8 @@ TrexStatelessPort::push_remote(const std::string &pcap_filename, double ipg_usec pcap_filename, ipg_usec, speedup, - count); + count, + duration); send_message_to_dp(tx_core, push_msg); /* update subscribers */ diff --git a/src/stateless/cp/trex_stateless_port.h b/src/stateless/cp/trex_stateless_port.h index ccbfad0d..8856b429 100644 --- a/src/stateless/cp/trex_stateless_port.h +++ b/src/stateless/cp/trex_stateless_port.h @@ -216,7 +216,11 @@ public: * push a PCAP file onto the port * */ - void push_remote(const std::string &pcap_filename, double ipg_usec, double speedup, uint32_t count); + void push_remote(const std::string &pcap_filename, + double ipg_usec, + double speedup, + uint32_t count, + double duration); /** * get the port state diff --git a/src/stateless/dp/trex_stateless_dp_core.cpp b/src/stateless/dp/trex_stateless_dp_core.cpp index 6450d0f9..dff5285d 100644 --- a/src/stateless/dp/trex_stateless_dp_core.cpp +++ b/src/stateless/dp/trex_stateless_dp_core.cpp @@ -301,7 +301,7 @@ bool TrexStatelessDpPerPort::push_pcap(uint8_t port_id, assert(m_active_pcap_node == NULL); m_active_pcap_node = pcap_node; - m_state = TrexStatelessDpPerPort::ppSTATE_TRANSMITTING; + m_state = TrexStatelessDpPerPort::ppSTATE_PCAP_TX; return (true); } @@ -898,7 +898,8 @@ TrexStatelessDpCore::push_pcap(uint8_t port_id, const std::string &pcap_filename, double ipg_usec, double speedup, - uint32_t count) { + uint32_t count, + double duration) { TrexStatelessDpPerPort * lp_port = get_port_db(port_id); @@ -917,13 +918,12 @@ TrexStatelessDpCore::push_pcap(uint8_t port_id, return; } - m_state = TrexStatelessDpCore::STATE_TRANSMITTING; - #if 0 - if ( duration > 0.0 ){ + if (duration > 0.0) { add_port_duration(duration, port_id, event_id); } - #endif + + m_state = TrexStatelessDpCore::STATE_PCAP_TX; } @@ -1007,6 +1007,9 @@ bool CGenNodePCAP::create(uint8_t port_id, m_port_id = port_id; m_count = count; + /* mark this node as slow path */ + set_slow_path(true); + if (ipg_usec != -1) { /* fixed IPG */ m_ipg_sec = usec_to_sec(ipg_usec / speedup); @@ -1046,6 +1049,11 @@ bool CGenNodePCAP::create(uint8_t port_id, return true; } +/** + * cleanup for PCAP node + * + * @author imarom (08-May-16) + */ void CGenNodePCAP::destroy() { if (m_raw_packet) { diff --git a/src/stateless/dp/trex_stateless_dp_core.h b/src/stateless/dp/trex_stateless_dp_core.h index 115f8873..0941f6f3 100644 --- a/src/stateless/dp/trex_stateless_dp_core.h +++ b/src/stateless/dp/trex_stateless_dp_core.h @@ -54,7 +54,8 @@ public: enum state_e { ppSTATE_IDLE, ppSTATE_TRANSMITTING, - ppSTATE_PAUSE + ppSTATE_PAUSE, + ppSTATE_PCAP_TX, }; @@ -117,6 +118,7 @@ public: enum state_e { STATE_IDLE, STATE_TRANSMITTING, + STATE_PCAP_TX, STATE_TERMINATE }; @@ -175,7 +177,8 @@ public: const std::string &pcap_filename, double ipg_usec, double speedup, - uint32_t count); + uint32_t count, + double duration); /** diff --git a/src/stateless/dp/trex_stream_node.h b/src/stateless/dp/trex_stream_node.h index a970c1f7..bdbc5084 100644 --- a/src/stateless/dp/trex_stream_node.h +++ b/src/stateless/dp/trex_stream_node.h @@ -406,6 +406,10 @@ public: double speedup, uint32_t count); + /** + * destroy the node cleaning up any data + * + */ void destroy(); /** diff --git a/src/stateless/messaging/trex_stateless_messaging.cpp b/src/stateless/messaging/trex_stateless_messaging.cpp index c0151c76..1cbacb6f 100644 --- a/src/stateless/messaging/trex_stateless_messaging.cpp +++ b/src/stateless/messaging/trex_stateless_messaging.cpp @@ -187,7 +187,13 @@ TrexStatelessDpUpdate::clone() { ************************/ bool TrexStatelessDpPushPCAP::handle(TrexStatelessDpCore *dp_core) { - dp_core->push_pcap(m_port_id, m_event_id, m_pcap_filename, m_ipg_usec, m_speedup, m_count); + dp_core->push_pcap(m_port_id, + m_event_id, + m_pcap_filename, + m_ipg_usec, + m_speedup, + m_count, + m_duration); return true; } @@ -198,7 +204,8 @@ TrexStatelessDpPushPCAP::clone() { m_pcap_filename, m_ipg_usec, m_speedup, - m_count); + m_count, + m_duration); return new_msg; } diff --git a/src/stateless/messaging/trex_stateless_messaging.h b/src/stateless/messaging/trex_stateless_messaging.h index c3de82ee..9b1f2e31 100644 --- a/src/stateless/messaging/trex_stateless_messaging.h +++ b/src/stateless/messaging/trex_stateless_messaging.h @@ -258,12 +258,14 @@ public: const std::string &pcap_filename, double ipg_usec, double speedup, - uint32_t count) : m_pcap_filename(pcap_filename) { + uint32_t count, + double duration) : m_pcap_filename(pcap_filename) { m_port_id = port_id; m_event_id = event_id; m_ipg_usec = ipg_usec; m_speedup = speedup; m_count = count; + m_duration = duration; } virtual bool handle(TrexStatelessDpCore *dp_core); @@ -275,6 +277,7 @@ private: int m_event_id; double m_ipg_usec; double m_speedup; + double m_duration; uint32_t m_count; uint8_t m_port_id; }; |