From 70eef8dd6ef160d3782984742fbc7958a35c03c7 Mon Sep 17 00:00:00 2001 From: Rodolfo Alonso Hernandez Date: Fri, 20 Jul 2018 16:40:29 +0100 Subject: Improve NetworkServiceTestCase._get_ip_flow_range() function Improve the method to calculate the CIDR IP address range (first one, last one). IPv4Network or IPv6Network hosts() is an iterator throught the list of valid IPs. If the network is too big, the generation of a list [1] can be very expensive. [1]https://github.com/opnfv/yardstick/blob/master/yardstick/benchmark/scenarios/networking/vnf_generic.py#L90 JIRA: YARDSTICK-1339 Change-Id: I9352b2e7ff4925c246df8b40ecf43e8dc96c42d2 Signed-off-by: Rodolfo Alonso Hernandez --- .../benchmark/scenarios/networking/vnf_generic.py | 49 ++++++++++--------- .../scenarios/networking/test_vnf_generic.py | 56 ++++++++++++++-------- 2 files changed, 59 insertions(+), 46 deletions(-) diff --git a/yardstick/benchmark/scenarios/networking/vnf_generic.py b/yardstick/benchmark/scenarios/networking/vnf_generic.py index 7a11d3e76..a7557733b 100644 --- a/yardstick/benchmark/scenarios/networking/vnf_generic.py +++ b/yardstick/benchmark/scenarios/networking/vnf_generic.py @@ -64,37 +64,36 @@ class NetworkServiceTestCase(scenario_base.Scenario): self._mq_ids = [] def _get_ip_flow_range(self, ip_start_range): + """Retrieve a CIDR first and last viable IPs - # IP range is specified as 'x.x.x.x-y.y.y.y' + :param ip_start_range: could be the IP range itself or a dictionary + with the host name and the port. + :return: (str) IP range (min, max) with this format "x.x.x.x-y.y.y.y" + """ if isinstance(ip_start_range, six.string_types): return ip_start_range - node_name, range_or_interface = next(iter(ip_start_range.items()), (None, '0.0.0.0')) + node_name, range_or_interface = next(iter(ip_start_range.items()), + (None, '0.0.0.0')) if node_name is None: - # we are manually specifying the range - ip_addr_range = range_or_interface + return range_or_interface + + node = self.context_cfg['nodes'].get(node_name, {}) + interface = node.get('interfaces', {}).get(range_or_interface) + if interface: + ip = interface['local_ip'] + mask = interface['netmask'] else: - node = self.context_cfg["nodes"].get(node_name, {}) - try: - # the ip_range is the interface name - interface = node.get("interfaces", {})[range_or_interface] - except KeyError: - ip = "0.0.0.0" - mask = "255.255.255.0" - else: - ip = interface["local_ip"] - # we can't default these values, they must both exist to be valid - mask = interface["netmask"] - - ipaddr = ipaddress.ip_network(six.text_type('{}/{}'.format(ip, mask)), strict=False) - hosts = list(ipaddr.hosts()) - if len(hosts) > 2: - # skip the first host in case of gateway - ip_addr_range = "{}-{}".format(hosts[1], hosts[-1]) - else: - LOG.warning("Only single IP in range %s", ipaddr) - # fall back to single IP range - ip_addr_range = ip + ip = '0.0.0.0' + mask = '255.255.255.0' + + ipaddr = ipaddress.ip_network( + six.text_type('{}/{}'.format(ip, mask)), strict=False) + if ipaddr.prefixlen + 2 < ipaddr.max_prefixlen: + ip_addr_range = '{}-{}'.format(ipaddr[2], ipaddr[-2]) + else: + LOG.warning('Only single IP in range %s', ipaddr) + ip_addr_range = ip return ip_addr_range def _get_traffic_flow(self): diff --git a/yardstick/tests/unit/benchmark/scenarios/networking/test_vnf_generic.py b/yardstick/tests/unit/benchmark/scenarios/networking/test_vnf_generic.py index cdb91f66d..49578b383 100644 --- a/yardstick/tests/unit/benchmark/scenarios/networking/test_vnf_generic.py +++ b/yardstick/tests/unit/benchmark/scenarios/networking/test_vnf_generic.py @@ -358,35 +358,49 @@ class TestNetworkServiceTestCase(unittest.TestCase): self.assertIsNotNone(self.topology) def test__get_ip_flow_range_string(self): - self.scenario_cfg["traffic_options"]["flow"] = \ - self._get_file_abspath("ipv4_1flow_Packets_vpe.yaml") result = '152.16.100.2-152.16.100.254' self.assertEqual(result, self.s._get_ip_flow_range( '152.16.100.2-152.16.100.254')) - def test__get_ip_flow_range(self): - self.scenario_cfg["traffic_options"]["flow"] = \ - self._get_file_abspath("ipv4_1flow_Packets_vpe.yaml") - result = '152.16.100.2-152.16.100.254' - self.assertEqual(result, self.s._get_ip_flow_range({"tg__1": 'xe0'})) + def test__get_ip_flow_range_no_nodes(self): + self.assertEqual('0.0.0.0', self.s._get_ip_flow_range({})) - @mock.patch('yardstick.benchmark.scenarios.networking.vnf_generic.ipaddress') - def test__get_ip_flow_range_no_node_data(self, mock_ipaddress): - scenario_cfg = deepcopy(self.scenario_cfg) - scenario_cfg["traffic_options"]["flow"] = \ - self._get_file_abspath("ipv4_1flow_Packets_vpe.yaml") + def test__get_ip_flow_range_no_node_data(self): + node_data = {'tg__0': 'xe0'} + self.s.context_cfg['nodes']['tg__0'] = {} + result = self.s._get_ip_flow_range(node_data) + self.assertEqual('0.0.0.2-0.0.0.254', result) - mock_ipaddress.ip_network.return_value = ipaddr = mock.Mock() - ipaddr.hosts.return_value = [] + def test__et_ip_flow_range_ipv4(self): + node_data = {'tg__0': 'xe0'} + self.s.context_cfg['nodes']['tg__0'] = { + 'interfaces': { + 'xe0': {'local_ip': '192.168.1.15', + 'netmask': '255.255.255.128'} + } + } + result = self.s._get_ip_flow_range(node_data) + self.assertEqual('192.168.1.2-192.168.1.126', result) - expected = '0.0.0.0' - result = self.s._get_ip_flow_range({"tg__2": 'xe0'}) - self.assertEqual(result, expected) + def test__get_ip_flow_range_ipv4_mask_30(self): + node_data = {'tg__0': 'xe0'} + self.s.context_cfg['nodes']['tg__0'] = { + 'interfaces': { + 'xe0': {'local_ip': '192.168.1.15', 'netmask': 30} + } + } + result = self.s._get_ip_flow_range(node_data) + self.assertEqual('192.168.1.15', result) - def test__get_ip_flow_range_no_nodes(self): - expected = '0.0.0.0' - result = self.s._get_ip_flow_range({}) - self.assertEqual(result, expected) + def test__get_ip_flow_range_ipv6(self): + node_data = {'tg__0': 'xe0'} + self.s.context_cfg['nodes']['tg__0'] = { + 'interfaces': { + 'xe0': {'local_ip': '2001::11', 'netmask': 64} + } + } + result = self.s._get_ip_flow_range(node_data) + self.assertEqual('2001::2-2001::ffff:ffff:ffff:fffe', result) def test___get_traffic_flow(self): self.scenario_cfg["traffic_options"]["flow"] = \ -- cgit 1.2.3-korg