From 78aed58edbe6eb8a71339c7add491fe9de9a0546 Mon Sep 17 00:00:00 2001 From: Jakub Libosvar Date: Thu, 13 Aug 2015 09:08:20 +0000 Subject: [PATCH] Fix establishing UDP connection Previously, in establish_connection() for UDP protocol data were sent but never read on peer socket. That lead to successful read on peer side if this connection was filtered. Having constant testing string masked this issue as we can't distinguish to which test of connectivity data belong. This patch makes unique data string per test_connectivity() and also makes establish_connection() to create an ASSURED entry in conntrack table. Finally, in last test after firewall filter was removed, connection is re-established in order to avoid troubles with terminated processes or TCP continuing sending packets which weren't successfully delivered. Closes-Bug: 1478847 Change-Id: I2920d587d8df8d96dc1c752c28f48ba495f3cf0f --- neutron/tests/common/net_helpers.py | 24 ++++++++++++------- .../functional/agent/linux/test_iptables.py | 5 ++++ 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/neutron/tests/common/net_helpers.py b/neutron/tests/common/net_helpers.py index a79c1ff20..172420c7f 100644 --- a/neutron/tests/common/net_helpers.py +++ b/neutron/tests/common/net_helpers.py @@ -252,7 +252,6 @@ class RootHelperProcess(subprocess.Popen): class NetcatTester(object): - TESTING_STRING = 'foo' TCP = n_const.PROTO_NAME_TCP UDP = n_const.PROTO_NAME_UDP @@ -325,21 +324,30 @@ class NetcatTester(object): self.client_namespace, address=self.address) if self.protocol == self.UDP: - # Create an entry in conntrack table for UDP packets - self.client_process.writeline(self.TESTING_STRING) + # Create an ASSURED entry in conntrack table for UDP packets, + # that requires 3-way communcation + # 1st transmission creates UNREPLIED + # 2nd transmission removes UNREPLIED + # 3rd transmission creates ASSURED + data = 'foo' + self.client_process.writeline(data) + self.server_process.read_stdout(READ_TIMEOUT) + self.server_process.writeline(data) + self.client_process.read_stdout(READ_TIMEOUT) + self.client_process.writeline(data) + self.server_process.read_stdout(READ_TIMEOUT) def test_connectivity(self, respawn=False): - stop_required = (respawn and self._client_process and - self._client_process.poll() is not None) - if stop_required: + testing_string = uuidutils.generate_uuid() + if respawn: self.stop_processes() - self.client_process.writeline(self.TESTING_STRING) + self.client_process.writeline(testing_string) message = self.server_process.read_stdout(READ_TIMEOUT).strip() self.server_process.writeline(message) message = self.client_process.read_stdout(READ_TIMEOUT).strip() - return message == self.TESTING_STRING + return message == testing_string def _spawn_nc_in_namespace(self, namespace, address, listen=False): cmd = ['nc', address, self.dst_port] diff --git a/neutron/tests/functional/agent/linux/test_iptables.py b/neutron/tests/functional/agent/linux/test_iptables.py index 93c03e672..2bbbedd4a 100644 --- a/neutron/tests/functional/agent/linux/test_iptables.py +++ b/neutron/tests/functional/agent/linux/test_iptables.py @@ -88,6 +88,8 @@ class IptablesManagerTestCase(functional_base.BaseSudoTestCase): self.assertTrue(netcat.test_connectivity(), 'Failed connectivity check before applying a filter ' 'with %s' % filter_params) + # REVISIT(jlibosva): Make sure we have ASSURED conntrack entry for + # given connection self.filter_add_rule( fw_manager, self.server.ip, direction, protocol, port) with testtools.ExpectedException( @@ -97,6 +99,9 @@ class IptablesManagerTestCase(functional_base.BaseSudoTestCase): netcat.test_connectivity() self.filter_remove_rule( fw_manager, self.server.ip, direction, protocol, port) + # With TCP packets will get through after firewall was removed, so we + # would get old data on socket and with UDP process died, so we need to + # respawn processes to have clean sockets self.assertTrue(netcat.test_connectivity(True), 'Failed connectivity check after removing a filter ' 'with %s' % filter_params) -- 2.45.2