From 7ba9fae5540f3490cea8258cc7830138b58d2740 Mon Sep 17 00:00:00 2001 From: Klement Sekera Date: Wed, 31 Mar 2021 13:36:38 +0200 Subject: [PATCH] tests: support injecting multiple worker pcaps on one PG This change allows one to inject multiple streams for different workers on the same PG interface at the same time. Type: improvement Change-Id: I29d80369aabada261eda466e5a5d8d3518bb8bc8 Signed-off-by: Klement Sekera --- test/framework.py | 15 +++++++++--- test/vpp_pg_interface.py | 63 +++++++++++++++++++++--------------------------- 2 files changed, 39 insertions(+), 39 deletions(-) diff --git a/test/framework.py b/test/framework.py index f3c74ceec3e..5e39854ac42 100644 --- a/test/framework.py +++ b/test/framework.py @@ -581,6 +581,7 @@ class VppTestCase(unittest.TestCase): cls.setUpConstants() cls.reset_packet_infos() cls._captures = [] + cls._old_captures = [] cls.verbose = 0 cls.vpp_dead = False cls.registry = VppObjectRegistry() @@ -814,10 +815,10 @@ class VppTestCase(unittest.TestCase): i.enable_capture() @classmethod - def register_capture(cls, cap_name): + def register_capture(cls, intf, worker): """ Register a capture in the testclass """ # add to the list of captures with current timestamp - cls._captures.append((time.time(), cap_name)) + cls._captures.append((intf, worker)) @classmethod def get_vpp_time(cls): @@ -841,6 +842,10 @@ class VppTestCase(unittest.TestCase): @classmethod def pg_start(cls, trace=True): """ Enable the PG, wait till it is done, then clean up """ + for (intf, worker) in cls._old_captures: + intf.rename_previous_capture_file(intf.get_in_path(worker), + intf.in_history_counter) + cls._old_captures = [] if trace: cls.vapi.cli("clear trace") cls.vapi.cli("trace add pg-input 1000") @@ -855,8 +860,10 @@ class VppTestCase(unittest.TestCase): if time.time() > deadline: cls.logger.error("Timeout waiting for pg to stop") break - for stamp, cap_name in cls._captures: - cls.vapi.cli('packet-generator delete %s' % cap_name) + for intf, worker in cls._captures: + cls.vapi.cli('packet-generator delete %s' % + intf.get_cap_name(worker)) + cls._old_captures = cls._captures cls._captures = [] @classmethod diff --git a/test/vpp_pg_interface.py b/test/vpp_pg_interface.py index c4b2e0a96db..c8debff0301 100755 --- a/test/vpp_pg_interface.py +++ b/test/vpp_pg_interface.py @@ -69,29 +69,33 @@ class VppPGInterface(VppInterface): """pcap file path - captured packets""" return self._out_path - @property - def in_path(self): + def get_in_path(self, worker): """ pcap file path - injected packets""" - return self._in_path + if worker is not None: + return "%s/pg%u_wrk%u_in.pcap" % (self.test.tempdir, self.pg_index, + worker) + return "%s/pg%u_in.pcap" % (self.test.tempdir, self.pg_index) @property def capture_cli(self): """CLI string to start capture on this interface""" return self._capture_cli - @property - def cap_name(self): - """capture name for this interface""" + def get_cap_name(self, worker=None): + """return capture name for this interface and given worker""" + if worker is not None: + return self._cap_name + "-worker%d" % worker return self._cap_name - @property - def input_cli(self): - """CLI string to load the injected packets""" - if self._nb_replays is not None: - return "%s limit %d" % (self._input_cli, self._nb_replays) - if self._worker is not None: - return "%s worker %d" % (self._input_cli, self._worker) - return self._input_cli + def get_input_cli(self, nb_replays=None, worker=None): + """return CLI string to load the injected packets""" + input_cli = "packet-generator new pcap %s source pg%u name %s" % ( + self.get_in_path(worker), self.pg_index, self.get_cap_name(worker)) + if nb_replays is not None: + return "%s limit %d" % (input_cli, nb_replays) + if worker is not None: + return "%s worker %d" % (input_cli, worker) + return input_cli @property def in_history_counter(self): @@ -109,7 +113,7 @@ class VppPGInterface(VppInterface): def __init__(self, test, pg_index, gso, gso_size): """ Create VPP packet-generator interface """ - super(VppPGInterface, self).__init__(test) + super().__init__(test) r = test.vapi.pg_create_interface(pg_index, gso, gso_size) self.set_sw_if_index(r.sw_if_index) @@ -123,19 +127,14 @@ class VppPGInterface(VppInterface): self._coalesce_enabled = 0 self._out_file = "pg%u_out.pcap" % self.pg_index self._out_path = self.test.tempdir + "/" + self._out_file - self._in_file = "pg%u_in.pcap" % self.pg_index - self._in_path = self.test.tempdir + "/" + self._in_file self._capture_cli = "packet-generator capture pg%u pcap %s" % ( self.pg_index, self.out_path) self._cap_name = "pcap%u-sw_if_index-%s" % ( self.pg_index, self.sw_if_index) - self._input_cli = \ - "packet-generator new pcap %s source pg%u name %s" % ( - self.in_path, self.pg_index, self.cap_name) - self._nb_replays = None - def _rename_previous_capture_file(self, path, counter, file): + def rename_previous_capture_file(self, path, counter): # if a file from a previous capture exists, rename it. + filename = os.path.basename(path) try: if os.path.isfile(path): name = "%s/history.[timestamp:%f].[%s-counter:%04d].%s" % \ @@ -143,13 +142,13 @@ class VppPGInterface(VppInterface): time.time(), self.name, counter, - file) + filename) self.test.logger.debug("Renaming %s->%s" % (path, name)) os.rename(path, name) except OSError: self.test.logger.debug("OSError: Could not rename %s %s" % - (path, file)) + (path, filename)) def enable_capture(self): """ Enable capture on this packet-generator interface @@ -158,9 +157,8 @@ class VppPGInterface(VppInterface): """ # disable the capture to flush the capture self.disable_capture() - self._rename_previous_capture_file(self.out_path, - self.out_history_counter, - self._out_file) + self.rename_previous_capture_file(self.out_path, + self.out_history_counter) # FIXME this should be an API, but no such exists atm self.test.vapi.cli(self.capture_cli) self._pcap_reader = None @@ -187,15 +185,10 @@ class VppPGInterface(VppInterface): :param pkts: iterable packets """ - self._worker = worker - self._nb_replays = nb_replays - self._rename_previous_capture_file(self.in_path, - self.in_history_counter, - self._in_file) - wrpcap(self.in_path, pkts) - self.test.register_capture(self.cap_name) + wrpcap(self.get_in_path(worker), pkts) + self.test.register_capture(self, worker) # FIXME this should be an API, but no such exists atm - self.test.vapi.cli(self.input_cli) + self.test.vapi.cli(self.get_input_cli(nb_replays, worker)) def generate_debug_aid(self, kind): """ Create a hardlink to the out file with a counter and a file -- 2.16.6