From: Ole Troan Date: Wed, 3 Mar 2021 09:40:05 +0000 (+0100) Subject: tests: use socket transport instead of shared memory X-Git-Tag: v21.10-rc0~380 X-Git-Url: https://gerrit.fd.io/r/gitweb?p=vpp.git;a=commitdiff_plain;h=4376ab2a926b36c1131588069a8a9cdd2520073d tests: use socket transport instead of shared memory Type: improvement Signed-off-by: Ole Troan Change-Id: I9e65c94a5a05047a5104e9361ea36eac77b40442 Signed-off-by: Ole Troan --- diff --git a/src/plugins/linux-cp/lcp.api b/src/plugins/linux-cp/lcp.api index 49fdeddf886..5bde88082df 100644 --- a/src/plugins/linux-cp/lcp.api +++ b/src/plugins/linux-cp/lcp.api @@ -85,13 +85,13 @@ autoreply autoendian define lcp_itf_pair_add_del @param context - sender context, to match reply w/ request @param sw_if_index - interface to use as filter (~0 == "all") */ -autoendian define lcp_itf_pair_get +define lcp_itf_pair_get { u32 client_index; u32 context; u32 cursor; }; -autoendian define lcp_itf_pair_get_reply +define lcp_itf_pair_get_reply { u32 context; i32 retval; diff --git a/src/plugins/map/test/test_map.py b/src/plugins/map/test/test_map.py index 93ea3f06976..746f0aff2de 100644 --- a/src/plugins/map/test/test_map.py +++ b/src/plugins/map/test/test_map.py @@ -114,15 +114,16 @@ class TestMAP(VppTestCase): def test_api_map_domains_get(self): # Create a bunch of domains - domains = self.create_domains('130.67.0.0/24', '2001::/32', + no_domains = 4096 # This must be large enough to ensure VPP suspends + domains = self.create_domains('130.67.0.0/20', '2001::/32', '2001::1/128') - self.assertEqual(len(domains), 256) + self.assertEqual(len(domains), no_domains) d = [] cursor = 0 # Invalid cursor - rv, details = self.vapi.map_domains_get(cursor=1234) + rv, details = self.vapi.map_domains_get(cursor=no_domains+10) self.assertEqual(rv.retval, -7) # Delete a domain in the middle of walk @@ -136,7 +137,7 @@ class TestMAP(VppTestCase): self.assertEqual(rv.retval, -165) d = list(self.vapi.vpp.details_iter(self.vapi.map_domains_get)) - self.assertEqual(len(d), 255) + self.assertEqual(len(d), no_domains - 1) # Clean up for i in domains: diff --git a/src/vlib/test/test_cli.py b/src/vlib/test/test_cli.py index a1ffbac81d8..5005bf4c43a 100644 --- a/src/vlib/test/test_cli.py +++ b/src/vlib/test/test_cli.py @@ -5,7 +5,7 @@ import datetime import time import unittest -from vpp_papi import vpp_transport_shmem +from vpp_papi import VPPIOError from framework import VppTestCase, VppTestRunner @@ -39,9 +39,8 @@ class TestCLI(VppTestCase): self.assertEqual(rv.retval, 0) def test_long_cli_delay(self): - """ Test that VppApiClient raises VppTransportShmemIOError if timeout.""" # noqa - with self.assertRaises( - vpp_transport_shmem.VppTransportShmemIOError) as ctx: + """ Test that VppApiClient raises VppIOError if timeout.""" # noqa + with self.assertRaises(VPPIOError) as ctx: rv = self.vapi.papi.cli_inband(cmd='wait 10') def test_long_cli_delay_override(self): diff --git a/src/vnet/bfd/bfd.api b/src/vnet/bfd/bfd.api index 9fdd5b728d4..f53cc7630fd 100644 --- a/src/vnet/bfd/bfd.api +++ b/src/vnet/bfd/bfd.api @@ -206,6 +206,11 @@ autoreply define bfd_udp_session_set_flags vl_api_if_status_flags_t flags; }; +service { + rpc want_bfd_events returns want_bfd_events_reply + events bfd_udp_session_event; +}; + /** \brief Register for BFD events @param client_index - opaque cookie to identify the sender @param context - sender context, to match reply w/ request @@ -220,6 +225,22 @@ autoreply define want_bfd_events u32 pid; }; +define bfd_udp_session_event +{ + u32 client_index; + u32 pid; + vl_api_interface_index_t sw_if_index; + vl_api_address_t local_addr; + vl_api_address_t peer_addr; + vl_api_bfd_state_t state; + bool is_authenticated; + u8 bfd_key_id; + u32 conf_key_id; + u32 required_min_rx; + u32 desired_min_tx; + u8 detect_mult; +}; + /** \brief BFD UDP - add/replace key to configuration @param client_index - opaque cookie to identify the sender @param context - sender context, to match reply w/ request diff --git a/src/vnet/bfd/bfd_api.c b/src/vnet/bfd/bfd_api.c index ba7783fd54f..4760df2ac1b 100644 --- a/src/vnet/bfd/bfd_api.c +++ b/src/vnet/bfd/bfd_api.c @@ -174,6 +174,48 @@ send_bfd_udp_session_details (vl_api_registration_t * reg, u32 context, vl_api_send_msg (reg, (u8 *) mp); } +void +send_bfd_udp_session_event (vl_api_registration_t *reg, u32 pid, + bfd_session_t *bs) +{ + if (bs->transport != BFD_TRANSPORT_UDP4 && + bs->transport != BFD_TRANSPORT_UDP6) + { + return; + } + + vl_api_bfd_udp_session_event_t *mp = vl_msg_api_alloc (sizeof (*mp)); + clib_memset (mp, 0, sizeof (*mp)); + mp->_vl_msg_id = ntohs (VL_API_BFD_UDP_SESSION_EVENT); + mp->pid = pid; + mp->state = clib_host_to_net_u32 (bs->local_state); + bfd_udp_session_t *bus = &bs->udp; + bfd_udp_key_t *key = &bus->key; + mp->sw_if_index = clib_host_to_net_u32 (key->sw_if_index); + if ((!bs->auth.is_delayed && bs->auth.curr_key) || + (bs->auth.is_delayed && bs->auth.next_key)) + { + mp->is_authenticated = true; + } + if (bs->auth.is_delayed && bs->auth.next_key) + { + mp->bfd_key_id = bs->auth.next_bfd_key_id; + mp->conf_key_id = clib_host_to_net_u32 (bs->auth.next_key->conf_key_id); + } + else if (!bs->auth.is_delayed && bs->auth.curr_key) + { + mp->bfd_key_id = bs->auth.curr_bfd_key_id; + mp->conf_key_id = clib_host_to_net_u32 (bs->auth.curr_key->conf_key_id); + } + ip_address_encode (&key->local_addr, IP46_TYPE_ANY, &mp->local_addr); + ip_address_encode (&key->peer_addr, IP46_TYPE_ANY, &mp->peer_addr); + + mp->required_min_rx = clib_host_to_net_u32 (bs->config_required_min_rx_usec); + mp->desired_min_tx = clib_host_to_net_u32 (bs->config_desired_min_tx_usec); + mp->detect_mult = bs->local_detect_mult; + vl_api_send_msg (reg, (u8 *) mp); +} + void bfd_event (bfd_main_t * bm, bfd_session_t * bs) { @@ -190,7 +232,7 @@ bfd_event (bfd_main_t * bm, bfd_session_t * bs) case BFD_TRANSPORT_UDP4: /* fallthrough */ case BFD_TRANSPORT_UDP6: - send_bfd_udp_session_details (vl_reg, 0, bs); + send_bfd_udp_session_event (vl_reg, 0, bs); } } } diff --git a/src/vnet/bfd/test/test_bfd.py b/src/vnet/bfd/test/test_bfd.py index 3e6453ccbc9..01b468c8e27 100644 --- a/src/vnet/bfd/test/test_bfd.py +++ b/src/vnet/bfd/test/test_bfd.py @@ -549,7 +549,7 @@ def bfd_session_up(test): test.test_session.inc_seq_num() test.test_session.send_packet() test.logger.info("BFD: Waiting for event") - e = test.vapi.wait_for_event(1, "bfd_udp_session_details") + e = test.vapi.wait_for_event(1, "bfd_udp_session_event") verify_event(test, e, expected_state=BFDState.up) test.logger.info("BFD: Session is Up") test.test_session.update(state=BFDState.up) @@ -569,7 +569,7 @@ def bfd_session_down(test): test.test_session.inc_seq_num() test.test_session.send_packet() test.logger.info("BFD: Waiting for event") - e = test.vapi.wait_for_event(1, "bfd_udp_session_details") + e = test.vapi.wait_for_event(1, "bfd_udp_session_event") verify_event(test, e, expected_state=BFDState.down) test.logger.info("BFD: Session is Down") test.assert_equal(test.vpp_session.state, BFDState.down, BFDState) @@ -750,12 +750,12 @@ class BFD4TestCase(VppTestCase): self.test_session.update(your_discriminator=p[BFD].my_discriminator, state=BFDState.up) self.logger.info("BFD: Waiting for event") - e = self.vapi.wait_for_event(1, "bfd_udp_session_details") + e = self.vapi.wait_for_event(1, "bfd_udp_session_event") verify_event(self, e, expected_state=BFDState.init) self.logger.info("BFD: Sending Up") self.test_session.send_packet() self.logger.info("BFD: Waiting for event") - e = self.vapi.wait_for_event(1, "bfd_udp_session_details") + e = self.vapi.wait_for_event(1, "bfd_udp_session_event") verify_event(self, e, expected_state=BFDState.up) self.logger.info("BFD: Session is Up") self.test_session.update(state=BFDState.up) @@ -820,7 +820,7 @@ class BFD4TestCase(VppTestCase): detection_time = self.test_session.detect_mult *\ self.vpp_session.required_min_rx / USEC_IN_SEC self.sleep(detection_time, "waiting for BFD session time-out") - e = self.vapi.wait_for_event(1, "bfd_udp_session_details") + e = self.vapi.wait_for_event(1, "bfd_udp_session_event") verify_event(self, e, expected_state=BFDState.down) def test_peer_discr_reset_sess_down(self): @@ -917,7 +917,7 @@ class BFD4TestCase(VppTestCase): self.vpp_session.required_min_rx) / USEC_IN_SEC self.test_session.send_packet(final) time_mark = time.time() - e = self.vapi.wait_for_event(2 * timeout, "bfd_udp_session_details") + e = self.vapi.wait_for_event(2 * timeout, "bfd_udp_session_event") verify_event(self, e, expected_state=BFDState.down) time_to_event = time.time() - time_mark self.assert_in_range(time_to_event, .9 * timeout, @@ -957,7 +957,7 @@ class BFD4TestCase(VppTestCase): self.vpp_session.required_min_rx / USEC_IN_SEC before = time.time() e = self.vapi.wait_for_event( - 2 * detection_time, "bfd_udp_session_details") + 2 * detection_time, "bfd_udp_session_event") after = time.time() self.assert_in_range(after - before, 0.9 * detection_time, @@ -1404,7 +1404,7 @@ class BFD4TestCase(VppTestCase): bfd_session_up(self) self.vpp_session.admin_down() self.pg0.enable_capture() - e = self.vapi.wait_for_event(1, "bfd_udp_session_details") + e = self.vapi.wait_for_event(1, "bfd_udp_session_event") verify_event(self, e, expected_state=BFDState.admin_down) for dummy in range(2): p = wait_for_bfd_packet(self) @@ -1417,7 +1417,7 @@ class BFD4TestCase(VppTestCase): self.assert_equal(p[BFD].state, BFDState.admin_down, BFDState) self.vpp_session.admin_up() self.test_session.update(state=BFDState.down) - e = self.vapi.wait_for_event(1, "bfd_udp_session_details") + e = self.vapi.wait_for_event(1, "bfd_udp_session_event") verify_event(self, e, expected_state=BFDState.down) p = wait_for_bfd_packet( self, pcap_time_min=time.time() - self.vpp_clock_offset) @@ -1426,14 +1426,14 @@ class BFD4TestCase(VppTestCase): p = wait_for_bfd_packet( self, pcap_time_min=time.time() - self.vpp_clock_offset) self.assert_equal(p[BFD].state, BFDState.init, BFDState) - e = self.vapi.wait_for_event(1, "bfd_udp_session_details") + e = self.vapi.wait_for_event(1, "bfd_udp_session_event") verify_event(self, e, expected_state=BFDState.init) self.test_session.update(state=BFDState.up) self.test_session.send_packet() p = wait_for_bfd_packet( self, pcap_time_min=time.time() - self.vpp_clock_offset) self.assert_equal(p[BFD].state, BFDState.up, BFDState) - e = self.vapi.wait_for_event(1, "bfd_udp_session_details") + e = self.vapi.wait_for_event(1, "bfd_udp_session_event") verify_event(self, e, expected_state=BFDState.up) def test_config_change_remote_demand(self): @@ -1483,7 +1483,7 @@ class BFD4TestCase(VppTestCase): vpp_session.add_vpp_config() vpp_session.admin_up() intf.remove_vpp_config() - e = self.vapi.wait_for_event(1, "bfd_udp_session_details") + e = self.vapi.wait_for_event(1, "bfd_udp_session_event") self.assert_equal(e.sw_if_index, sw_if_index, "sw_if_index") self.assertFalse(vpp_session.query_vpp_config()) @@ -1562,12 +1562,12 @@ class BFD6TestCase(VppTestCase): self.test_session.update(your_discriminator=p[BFD].my_discriminator, state=BFDState.up) self.logger.info("BFD: Waiting for event") - e = self.vapi.wait_for_event(1, "bfd_udp_session_details") + e = self.vapi.wait_for_event(1, "bfd_udp_session_event") verify_event(self, e, expected_state=BFDState.init) self.logger.info("BFD: Sending Up") self.test_session.send_packet() self.logger.info("BFD: Waiting for event") - e = self.vapi.wait_for_event(1, "bfd_udp_session_details") + e = self.vapi.wait_for_event(1, "bfd_udp_session_event") verify_event(self, e, expected_state=BFDState.up) self.logger.info("BFD: Session is Up") self.test_session.update(state=BFDState.up) @@ -1698,7 +1698,7 @@ class BFD6TestCase(VppTestCase): vpp_session.add_vpp_config() vpp_session.admin_up() intf.remove_vpp_config() - e = self.vapi.wait_for_event(1, "bfd_udp_session_details") + e = self.vapi.wait_for_event(1, "bfd_udp_session_event") self.assert_equal(e.sw_if_index, sw_if_index, "sw_if_index") self.assertFalse(vpp_session.query_vpp_config()) diff --git a/src/vpp-api/python/vpp_papi/vpp_papi.py b/src/vpp-api/python/vpp_papi/vpp_papi.py index 86bf7cbee30..851c214cad4 100644 --- a/src/vpp-api/python/vpp_papi/vpp_papi.py +++ b/src/vpp-api/python/vpp_papi/vpp_papi.py @@ -917,13 +917,8 @@ class VPPApiClient: while True: kwargs['cursor'] = cursor rv, details = f(**kwargs) - # - # Convert to yield from details when we only support python 3 - # for d in details: yield d if rv.retval == 0 or rv.retval != -165: break cursor = rv.cursor - -# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 diff --git a/src/vpp-api/python/vpp_papi/vpp_transport_socket.py b/src/vpp-api/python/vpp_papi/vpp_transport_socket.py index 4af2d934ae8..b0861057e72 100644 --- a/src/vpp-api/python/vpp_papi/vpp_transport_socket.py +++ b/src/vpp-api/python/vpp_papi/vpp_transport_socket.py @@ -90,8 +90,8 @@ class VppTransport: try: self.socket.connect(self.server_address) except socket.error as msg: - logging.error("{} on socket {}".format(msg, self.server_address)) - raise + # logging.error("{} on socket {}".format(msg, self.server_address)) + raise msg self.connected = True diff --git a/test/Makefile b/test/Makefile index 514cb27fc14..084fc849897 100644 --- a/test/Makefile +++ b/test/Makefile @@ -401,8 +401,6 @@ help: @echo "" @echo " SKIP_AARCH64=1 - skip tests that are failing on the ARM platorm in FD.io CI" @echo "" - @echo " SOCKET=1 - Communicate with VPP over Unix domain socket instead of SHM" - @echo "" @echo " RND_SEED=seed - Seed RND with given seed" @echo "" @echo "Creating test documentation" diff --git a/test/framework.py b/test/framework.py index 4ccbc454b5b..4e0949bcf45 100644 --- a/test/framework.py +++ b/test/framework.py @@ -33,7 +33,7 @@ from vpp_bvi_interface import VppBviInterface from vpp_papi_provider import VppPapiProvider import vpp_papi from vpp_papi.vpp_stats import VPPStats -from vpp_papi.vpp_transport_shmem import VppTransportShmemIOError +from vpp_papi.vpp_transport_socket import VppTransportSocketIOError from log import RED, GREEN, YELLOW, double_line_delim, single_line_delim, \ get_logger, colorize from vpp_object import VppObjectRegistry @@ -564,10 +564,10 @@ class VppTestCase(unittest.TestCase): cls.logger.addHandler(cls.file_handler) cls.logger.debug("--- setUpClass() for %s called ---" % cls.__name__) - cls.shm_prefix = os.path.basename(cls.tempdir) + cls.shm_prefix = os.path.basename(cls.tempdir) # Only used for VAPI os.chdir(cls.tempdir) - cls.logger.info("Temporary dir is %s, shm prefix is %s", - cls.tempdir, cls.shm_prefix) + cls.logger.info("Temporary dir is %s, api socket is %s", + cls.tempdir, cls.api_sock) cls.logger.debug("Random seed is %s" % seed) cls.setUpConstants() cls.reset_packet_infos() @@ -593,7 +593,7 @@ class VppTestCase(unittest.TestCase): cls.pump_thread.start() if cls.debug_gdb or cls.debug_gdbserver: cls.vapi_response_timeout = 0 - cls.vapi = VppPapiProvider(cls.shm_prefix, cls.shm_prefix, cls, + cls.vapi = VppPapiProvider(cls.__name__, cls, cls.vapi_response_timeout) if cls.step: hook = hookmodule.StepHook(cls) @@ -611,7 +611,7 @@ class VppTestCase(unittest.TestCase): raise try: cls.vapi.connect() - except vpp_papi.VPPIOError as e: + except (vpp_papi.VPPIOError, Exception) as e: cls.logger.debug("Exception connecting to vapi: %s" % e) cls.vapi.disconnect() @@ -619,15 +619,15 @@ class VppTestCase(unittest.TestCase): print(colorize("You're running VPP inside gdbserver but " "VPP-API connection failed, did you forget " "to 'continue' VPP from within gdb?", RED)) - raise + raise e except vpp_papi.VPPRuntimeError as e: cls.logger.debug("%s" % e) cls.quit() - raise + raise e except Exception as e: cls.logger.debug("Exception connecting to VPP: %s" % e) cls.quit() - raise + raise e @classmethod def _debug_quit(cls): @@ -679,7 +679,11 @@ class VppTestCase(unittest.TestCase): cls.logger.debug("Sending TERM to vpp") cls.vpp.terminate() cls.logger.debug("Waiting for vpp to die") - cls.vpp.communicate() + try: + outs, errs = cls.vpp.communicate(timeout=5) + except subprocess.TimeoutExpired: + cls.vpp.kill() + outs, errs = cls.vpp.communicate() cls.logger.debug("Deleting class vpp attribute on %s", cls.__name__) cls.vpp.stdout.close() @@ -758,8 +762,8 @@ class VppTestCase(unittest.TestCase): os.rename(tmp_api_trace, vpp_api_trace_log) self.logger.info(self.vapi.ppcli("api trace custom-dump %s" % vpp_api_trace_log)) - except VppTransportShmemIOError: - self.logger.debug("VppTransportShmemIOError: Vpp dead. " + except VppTransportSocketIOError: + self.logger.debug("VppTransportSocketIOError: Vpp dead. " "Cannot log show commands.") self.vpp_dead = True else: diff --git a/test/test_ipsec_tun_if_esp.py b/test/test_ipsec_tun_if_esp.py index 158e911e0c7..b72d464c663 100644 --- a/test/test_ipsec_tun_if_esp.py +++ b/test/test_ipsec_tun_if_esp.py @@ -509,7 +509,7 @@ class TestIpsec6TunIfEspHandoff(TemplateIpsec6TunIfEsp, stats0 = policer.get_stats(worker=0) stats1 = policer.get_stats(worker=1) - if pol_bind is 1: + if pol_bind == 1: # First pass: Worker 1, should have done all the policing self.assertEqual(stats, stats1) @@ -581,7 +581,7 @@ class TestIpsec4TunIfEspHandoff(TemplateIpsec4TunIfEsp, stats0 = policer.get_stats(worker=0) stats1 = policer.get_stats(worker=1) - if pol_bind is 1: + if pol_bind == 1: # First pass: Worker 1, should have done all the policing self.assertEqual(stats, stats1) diff --git a/test/vpp_papi_provider.py b/test/vpp_papi_provider.py index 81e25ecc621..da693c73e2a 100644 --- a/test/vpp_papi_provider.py +++ b/test/vpp_papi_provider.py @@ -8,13 +8,12 @@ import os import time from collections import deque - +import queue from six import moves, iteritems from vpp_papi import VPPApiClient, mac_pton from hook import Hook from vpp_ip_route import MPLS_IETF_MAX_LABEL, MPLS_LABEL_INVALID - # # Dictionary keyed on message name to override default values for # named parameters @@ -131,10 +130,9 @@ class VppPapiProvider(object): _zero, _negative = range(2) - def __init__(self, name, shm_prefix, test_class, read_timeout): + def __init__(self, name, test_class, read_timeout): self.hook = Hook(test_class) self.name = name - self.shm_prefix = shm_prefix self.test_class = test_class self._expect_api_retval = self._zero self._expect_stack = [] @@ -143,18 +141,11 @@ class VppPapiProvider(object): # calling the constructor. VPPApiClient.apidir = os.getenv('VPP_INSTALL_PATH') - use_socket = False - try: - if os.environ['SOCKET'] == '1': - use_socket = True - except KeyError: - pass - self.vpp = VPPApiClient(logger=test_class.logger, read_timeout=read_timeout, - use_socket=use_socket, + use_socket=True, server_address=test_class.api_sock) - self._events = deque() + self._events = queue.Queue() def __enter__(self): return self @@ -193,9 +184,14 @@ class VppPapiProvider(object): def collect_events(self): """ Collect all events from the internal queue and clear the queue. """ - e = self._events - self._events = deque() - return e + result = [] + while True: + try: + e = self._events.get(block=False) + result.append(e) + except queue.Empty: + return result + return result def wait_for_event(self, timeout, name=None): """ Wait for and return next event. """ @@ -205,28 +201,21 @@ class VppPapiProvider(object): else: self.test_class.logger.debug("Expecting event within %ss", timeout) - if self._events: - self.test_class.logger.debug("Not waiting, event already queued") - limit = time.time() + timeout - while time.time() < limit: - if self._events: - e = self._events.popleft() - if name and type(e).__name__ != name: - raise Exception( - "Unexpected event received: %s, expected: %s" % - (type(e).__name__, name)) - self.test_class.logger.debug("Returning event %s:%s" % - (name, e)) - return e - self.test_class.sleep(0) # yield - raise Exception("Event did not occur within timeout") + try: + e = self._events.get(timeout=timeout) + except queue.Empty: + raise Exception("Event did not occur within timeout") + msgname = type(e).__name__ + if name and msgname != name: + raise Exception("Unexpected event received: %s, expected: %s" + % msgname) + self.test_class.logger.debug("Returning event %s:%s" % (name, e)) + return e def __call__(self, name, event): """ Enqueue event in the internal event queue. """ - # FIXME use the name instead of relying on type(e).__name__ ? - # FIXME #2 if this throws, it is eaten silently, Ole? self.test_class.logger.debug("New event: %s: %s" % (name, event)) - self._events.append(event) + self._events.put(event) def factory(self, name, apifn): def f(*a, **ka): @@ -262,7 +251,14 @@ class VppPapiProvider(object): def connect(self): """Connect the API to VPP""" - self.vpp.connect(self.name, self.shm_prefix) + # This might be called before VPP is prepared to listen to the socket + retries = 0 + while not os.path.exists(self.test_class.api_sock): + time.sleep(0.5) + retries += 1 + if retries > 120: + break + self.vpp.connect(self.name[:63]) self.papi = self.vpp.api self.vpp.register_event_callback(self)