def test_create_update_subnet_hostroute(self):
        host_routes = [{'destination': '135.207.0.0/16', 'nexthop': '1.2.3.4'}]
        network, lswitch = self._test_create_network_revision()
        self.nb_api.update.reset_mock()
        self.nb_api.get.side_effect = nb_api_get_func(lswitch)
        with self.subnet(network={'network': network},
                         host_routes=host_routes,
                         set_context=True) as subnet:
            self.nb_api.update.assert_called_once()
            lswitch = self.nb_api.update.call_args_list[0][0][0]
            self.assertIsInstance(lswitch, l2.LogicalSwitch)
            self.nb_api.get.side_effect = nb_api_get_func(lswitch)
            self.nb_api.update.reset_mock()
            df_subnet = lswitch.find_subnet(subnet['subnet']['id'])
            self.assertEqual(
                [host_route.HostRoute(**hr) for hr in host_routes],
                df_subnet.host_routes)

            data = {'subnet': {'host_routes': None}}
            req = self.new_update_request('subnets', data,
                                          subnet['subnet']['id'])
            req.get_response(self.api)
            self.nb_api.update.assert_called_once()
            lswitch = self.nb_api.update.call_args_list[0][0][0]
            df_subnet = lswitch.find_subnet(subnet['subnet']['id'])
            self.assertEqual([], df_subnet.host_routes)
    def test_create_update_subnet_hostroute(self):
        host_routes = [{'destination': '135.207.0.0/16', 'nexthop': '1.2.3.4'}]
        network, lswitch = self._test_create_network_revision()
        self.nb_api.create.reset_mock()
        self.nb_api.update.reset_mock()
        self.nb_api.get.side_effect = nb_api_get_func(lswitch)
        with self.subnet(network={'network': network},
                         host_routes=host_routes,
                         set_context=True) as n_subnet:
            # Create Subnet, create DHCP port
            self.assertEqual(2, self.nb_api.create.call_count)
            self.nb_api.update.assert_called_once()
            lswitch = self.nb_api.update.call_args_list[0][0][0]
            self.assertIsInstance(lswitch, l2.LogicalSwitch)
            dhcp_lport = self.nb_api.create.call_args_list[0][0][0]
            self.assertIsInstance(dhcp_lport, l2.LogicalPort)
            subnet = self.nb_api.create.call_args_list[1][0][0]
            self.assertIsInstance(subnet, l2.Subnet)
            self.nb_api.get.side_effect = nb_api_get_func(subnet)
            self.nb_api.update.reset_mock()
            self.assertEqual(
                [host_route.HostRoute(**hr) for hr in host_routes],
                subnet.host_routes)

            data = {'subnet': {'host_routes': None}}
            req = self.new_update_request('subnets', data,
                                          n_subnet['subnet']['id'])
            req.get_response(self.api)
            # Update subnet, update lswitch's version
            self.assertEqual(2, self.nb_api.update.call_count)
            subnet = self.nb_api.update.call_args_list[0][0][0]
            self.assertIsInstance(subnet, l2.Subnet)
            self.assertEqual([], subnet.host_routes)
Exemple #3
0
    def _get_host_routes_list_bin(self, subnet, lport):
        host_routes = copy.copy(subnet.host_routes)
        if self.conf.df_add_link_local_route:
            # Add route for metadata request.
            host_routes.append(host_route.HostRoute(
                destination='%s/32' % const.METADATA_SERVICE_IP,
                nexthop=lport.ip))

        routes_bin = b''
        opt = lport.dhcp_params.opts.get(dhcp.DHCP_CLASSLESS_ROUTE_OPT)
        if opt:
            dest_cidr, _c, via = opt.partition(',')
            host_routes.append(
                host_route.HostRoute(destination=dest_cidr,
                                     nexthop=via))

        # We must add the default route here. if a host supports classless
        # route options, it must ignore the router option
        gateway = self._get_port_gateway_address(subnet, lport)
        if gateway is not None:
            host_routes.append(
                host_route.HostRoute(
                    destination='0.0.0.0/0',
                    nexthop=gateway,
                ),
            )

        for route in host_routes:
            dest = route.destination.network
            mask = route.destination.prefixlen
            routes_bin += struct.pack('B', mask)
            """
            for compact encoding
            Width of subnet mask      Number of significant octets
                            0               0
                         1- 8               1
                         9-16               2
                        17-24               3
                        25-32               4
            """
            addr_bin = addrconv.ipv4.text_to_bin(dest)
            dest_len = int(math.ceil(mask / 8.0))
            routes_bin += addr_bin[:dest_len]
            routes_bin += addrconv.ipv4.text_to_bin(route.nexthop)

        return routes_bin
Exemple #4
0
    def test_add_del_lport_after_router_route(self):
        # add route
        routes = [host_route.HostRoute(destination="10.100.0.0/16",
                                       nexthop="10.0.0.6"),
                  host_route.HostRoute(destination="10.101.0.0/16",
                                       nexthop="10.0.0.6")]
        # Use another object here to differentiate the one in cache
        router_with_route = copy.deepcopy(self.router)
        router_with_route.routes = routes
        router_with_route.version += 1
        self.controller.update(router_with_route)
        # No lport no flow for route
        self.assertFalse(self.app.mod_flow.called)

        self.controller.update(test_app_base.fake_local_port1)
        # 2 routes, 2 mod_flow and 1 mod_flow for add lport proactive route
        self.assertEqual(3, self.app.mod_flow.call_count)

        self.app.mod_flow.reset_mock()
        self.controller.delete(test_app_base.fake_local_port1)
        # 2 routes, 2 mod_flow and 1 mod_flow for del lport proactive route
        self.assertEqual(3, self.app.mod_flow.call_count)
Exemple #5
0
    def _get_host_routes_list_bin(self, subnet, lport):
        host_routes = copy.copy(subnet.host_routes)
        if self.conf.df_add_link_local_route:
            # Add route for metadata request.
            host_routes.append(
                host_route.HostRoute(destination='%s/32' %
                                     const.METADATA_SERVICE_IP,
                                     nexthop=lport.ip))

        routes_bin = b''

        dhcp_opts = lport.extra_dhcp_options
        for opt in dhcp_opts:
            if opt.tag == DHCP_CLASSLESS_ROUTE_OPT:
                dest_cidr, _c, via = opt.value.partition(',')
                host_routes.append(
                    host_route.HostRoute(destination=dest_cidr, nexthop=via))

        for route in host_routes:
            dest = route.destination.network
            mask = route.destination.prefixlen
            routes_bin += struct.pack('B', mask)
            """
            for compact encoding
            Width of subnet mask      Number of significant octets
                            0               0
                         1- 8               1
                         9-16               2
                        17-24               3
                        25-32               4
            """
            addr_bin = addrconv.ipv4.text_to_bin(dest)
            dest_len = int(math.ceil(mask / 8.0))
            routes_bin += addr_bin[:dest_len]
            routes_bin += addrconv.ipv4.text_to_bin(route.nexthop)

        return routes_bin
Exemple #6
0
    def _reprocess_to_add_route(self, lport):
        """Add extra routes for lport.

        @param lport: The lport related to extra routes.
        """
        LOG.debug("Reprocess to add extra routes that use lport %s "
                  "as nexthop", lport)
        lswitch_id = lport.lswitch.id
        port_ip = lport.ip
        router, router_if = self._get_router_by_lswitch_and_port_ip(
            lswitch_id, port_ip)
        if not router:
            LOG.debug("No router for lport %s, skip adding extra route",
                      lport)
            return

        router_id = router.id
        cached_routes = self.route_cache.get(router_id)
        if not cached_routes or not cached_routes.get(ROUTE_TO_ADD):
            LOG.debug("No extra routes need to be processed for logical "
                      "router %s", router)
            return

        # Make a copy here, or else _change_route_cache_status will delete
        # elements in routes inside the iteration.
        routes = copy.deepcopy(cached_routes.get(ROUTE_TO_ADD))
        for route in routes:
            if str(port_ip) != route[1]:
                continue
            route = host_route.HostRoute(destination=route[0],
                                         nexthop=route[1])
            self._add_extra_route_to_router(router.unique_key,
                                            router_if.mac,
                                            lport.unique_key,
                                            lport.mac,
                                            route)
            self._change_route_cache_status(router_id,
                                            from_part=ROUTE_TO_ADD,
                                            to_part=ROUTE_ADDED,
                                            route=route)
    def test_add_remove_bgp_network(self):
        bgp_speaker = objects.BGPSpeakerTestObj(self.neutron, self.nb_api)
        self.addCleanup(bgp_speaker.close)
        bgp_speaker.create()
        address_scope = objects.AddressScopeTestObj(self.neutron, self.nb_api)
        self.addCleanup(address_scope.close)
        as_id = address_scope.create()
        private_subnetpool = objects.SubnetPoolTestObj(self.neutron,
                                                       self.nb_api)
        self.addCleanup(private_subnetpool.close)
        private_sp_id = private_subnetpool.create(
            subnetpool={
                'name': "private_sp",
                'default_prefixlen': 24,
                'prefixes': ["20.0.0.0/8"],
                'address_scope_id': as_id
            })
        public_subnetpool = objects.SubnetPoolTestObj(self.neutron,
                                                      self.nb_api)
        self.addCleanup(public_subnetpool.close)
        public_sp_id = public_subnetpool.create(
            subnetpool={
                'name': "public_sp",
                'default_prefixlen': 24,
                'prefixes': ["172.24.4.0/24"],
                'address_scope_id': as_id
            })
        public_network = objects.NetworkTestObj(self.neutron, self.nb_api)
        self.addCleanup(public_network.close)
        public_network_id = public_network.create(network={
            'name': 'public',
            'router:external': True
        })
        public_subnet = objects.SubnetTestObj(self.neutron, self.nb_api,
                                              public_network_id)
        self.addCleanup(public_subnet.close)
        public_subnet.create(
            subnet={
                'ip_version': 4,
                'network_id': public_network_id,
                'subnetpool_id': public_sp_id
            })
        private_network = objects.NetworkTestObj(self.neutron, self.nb_api)
        self.addCleanup(private_network.close)
        private_network_id = private_network.create(network={'name': "public"})
        private_subnet = objects.SubnetTestObj(self.neutron, self.nb_api,
                                               private_network_id)
        self.addCleanup(private_subnet.close)
        private_sn_id = private_subnet.create(
            subnet={
                'ip_version': 4,
                'network_id': private_network_id,
                'subnetpool_id': private_sp_id
            })
        bgp_speaker.add_network(public_network_id)
        router = objects.RouterTestObj(self.neutron, self.nb_api)
        self.addCleanup(router.close)
        router_id = router.create()
        self.neutron.add_interface_router(router_id,
                                          body={'subnet_id': private_sn_id})
        self.neutron.add_gateway_router(router_id,
                                        body={'network_id': public_network_id})
        # Finnally, verify the route has been set in nb db.
        nb_bgp_speaker = bgp_speaker.get_nb_bgp_speaker()
        self.assertEqual(1, len(nb_bgp_speaker.prefix_routes))

        vm = objects.VMTestObj(self, self.neutron)
        self.addCleanup(vm.close)
        vm_id = vm.create(network=private_network)
        vm_port = self.neutron.list_ports(device_id=vm_id).get('ports')[0]
        vm_port_id = vm_port.get('id')
        fip = objects.FloatingipTestObj(self.neutron, self.nb_api)
        self.addCleanup(fip.close)
        fip.create({
            'floating_network_id': public_network_id,
            'port_id': vm_port_id
        })
        fip_addr = fip.get_floatingip().floating_ip_address
        nb_bgp_speaker = bgp_speaker.get_nb_bgp_speaker()
        self.assertEqual(1, len(nb_bgp_speaker.host_routes))
        self.assertIn(
            host_route.HostRoute(destination=netaddr.IPNetwork(fip_addr),
                                 nexthop='172.24.4.100'),
            nb_bgp_speaker.host_routes)

        fip.update({'port_id': None})
        nb_bgp_speaker = bgp_speaker.get_nb_bgp_speaker()
        self.assertFalse(nb_bgp_speaker.host_routes)

        bgp_speaker.remove_network(public_network_id)
        nb_bgp_speaker = bgp_speaker.get_nb_bgp_speaker()
        self.assertFalse(nb_bgp_speaker.prefix_routes)