From ea7b51655f5504404cc7c416547608c24fbd45ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C5=82awek=20Kap=C5=82o=C5=84ski?= Date: Wed, 26 Oct 2016 11:46:46 +0200 Subject: [PATCH] Add fullstack test for check DSCP marks outbounds New fullstack test is added to check if packets which should be sent from port with DSCP mark set are really sent to another port with this DSCP mark. This test uses IPv4 only. Change-Id: I4b26c3c644eb6f2f7813658c99d16fbc3cc61e06 Closes-Bug: #1625570 --- neutron/tests/common/agents/l2_extensions.py | 39 ++++++++++++++++ neutron/tests/fullstack/test_qos.py | 48 ++++++++++++++++++++ 2 files changed, 87 insertions(+) diff --git a/neutron/tests/common/agents/l2_extensions.py b/neutron/tests/common/agents/l2_extensions.py index 85188e619f8..158daaa8971 100644 --- a/neutron/tests/common/agents/l2_extensions.py +++ b/neutron/tests/common/agents/l2_extensions.py @@ -13,9 +13,19 @@ # License for the specific language governing permissions and limitations # under the License. +import re + +from neutron.agent.linux import async_process from neutron.common import utils as common_utils +IPv4_ADDR_REGEX = r"(\d{1,3}\.){3}\d{1,3}" + + +class TcpdumpException(Exception): + pass + + def extract_mod_nw_tos_action(flows): tos_mark = None if flows: @@ -52,3 +62,32 @@ def wait_until_dscp_marking_rule_applied(bridge, port_vif, rule): return dscp_mark == expected common_utils.wait_until_true(_dscp_marking_rule_applied) + + +def wait_for_dscp_marked_packet(sender_vm, receiver_vm, dscp_mark): + cmd = ["tcpdump", "-i", receiver_vm.port.name, "-nlt"] + if dscp_mark: + cmd += ["(ip[1] & 0xfc == %s)" % (dscp_mark << 2)] + tcpdump_async = async_process.AsyncProcess(cmd, run_as_root=True, + namespace=receiver_vm.namespace) + tcpdump_async.start() + sender_vm.block_until_ping(receiver_vm.ip) + try: + tcpdump_async.stop() + except async_process.AsyncProcessException: + # If it was already stopped than we don't care about it + pass + + pattern = (r"IP (?P%(ip_addr_regex)s) > " + "(?P%(ip_addr_regex)s): ICMP .*$" % { + 'ip_addr_regex': IPv4_ADDR_REGEX}) + for line in tcpdump_async.iter_stdout(): + m = re.match(pattern, line) + if m and (m.group("src_ip") == sender_vm.ip and + m.group("dst_ip") == receiver_vm.ip): + return + raise TcpdumpException( + "No packets marked with DSCP = %(dscp_mark)s received from %(src)s " + "to %(dst)s" % {'dscp_mark': dscp_mark, + 'src': sender_vm.ip, + 'dst': receiver_vm.ip}) diff --git a/neutron/tests/fullstack/test_qos.py b/neutron/tests/fullstack/test_qos.py index 422ece386b0..58dd4286746 100644 --- a/neutron/tests/fullstack/test_qos.py +++ b/neutron/tests/fullstack/test_qos.py @@ -176,6 +176,29 @@ class TestDscpMarkingQoSOvs(BaseQoSRuleTestCase, base.BaseFullStackTestCase): scenarios = fullstack_utils.get_ovs_interface_scenarios() l2_agent_type = constants.AGENT_TYPE_OVS + def setUp(self): + host_desc = [ + environment.HostDescription( + l3_agent=False, + of_interface=self.of_interface, + ovsdb_interface=self.ovsdb_interface, + l2_agent_type=self.l2_agent_type + ) for _ in range(2)] + env_desc = environment.EnvironmentDescription( + qos=True) + env = environment.Environment(env_desc, host_desc) + super(BaseQoSRuleTestCase, self).setUp(env) + + self.tenant_id = uuidutils.generate_uuid() + self.network = self.safe_client.create_network(self.tenant_id, + 'network-test') + self.subnet = self.safe_client.create_subnet( + self.tenant_id, self.network['id'], + cidr='10.0.0.0/24', + gateway_ip='10.0.0.1', + name='subnet-test', + enable_dhcp=False) + def _wait_for_dscp_marking_rule_applied(self, vm, dscp_mark): l2_extensions.wait_until_dscp_marking_rule_applied( vm.bridge, vm.port.name, dscp_mark) @@ -223,6 +246,31 @@ class TestDscpMarkingQoSOvs(BaseQoSRuleTestCase, base.BaseFullStackTestCase): body={'port': {'qos_policy_id': None}}) self._wait_for_dscp_marking_rule_removed(vm) + def test_dscp_marking_packets(self): + # Create port (vm) which will be used to received and test packets + receiver_port = self.safe_client.create_port( + self.tenant_id, self.network['id'], + self.environment.hosts[1].hostname) + + receiver = self.useFixture( + machine.FakeFullstackMachine( + self.environment.hosts[1], + self.network['id'], + self.tenant_id, + self.safe_client, + neutron_port=receiver_port)) + + # Create port with qos policy attached + sender, qos_policy = self._prepare_vm_with_qos_policy( + [functools.partial(self._add_dscp_rule, DSCP_MARK)]) + + sender.block_until_boot() + receiver.block_until_boot() + + self._wait_for_dscp_marking_rule_applied(sender, DSCP_MARK) + l2_extensions.wait_for_dscp_marked_packet( + sender, receiver, DSCP_MARK) + class TestQoSWithL2Population(base.BaseFullStackTestCase):