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
This commit is contained in:
Jakub Libosvar 2015-08-13 09:08:20 +00:00
parent cd4d889374
commit 78aed58edb
2 changed files with 21 additions and 8 deletions

View File

@ -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]

View File

@ -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)