Luis Tomas Bolivar 546a8bef21 Ensure proxy arp and ndp is configure for flat provider networks
If there are flat and vlan provider networks configured on the
same ovs provider bridge, the arp/ndp proxy were not being
configured for the bridge, therefore breaking the connectivity
to the VMs on the flat network. This patch ensures it is always
configured

Closes-Bug: #2045401
Change-Id: I9e4cbe6861b6f83c90d664424a4eb905fe49e4a7
2023-12-01 10:41:19 +01:00

773 lines
33 KiB
Python

# Copyright 2022 Red Hat, Inc.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import copy
import ipaddress
from socket import AF_INET
from socket import AF_INET6
from unittest import mock
from ovn_bgp_agent import exceptions as agent_exc
from ovn_bgp_agent.tests import base as test_base
from ovn_bgp_agent.utils import linux_net
class IPRouteDict(dict):
def get_attr(self, attr_name):
for attr in self['attrs']:
if attr[0] == attr_name:
return attr[1]
return
class TestLinuxNet(test_base.TestCase):
def setUp(self):
super(TestLinuxNet, self).setUp()
# Mock pyroute2.NDB context manager object
self.mock_ndb = mock.patch.object(linux_net.pyroute2, 'NDB').start()
self.fake_ndb = self.mock_ndb().__enter__()
# Mock pyroute2.IPRoute context manager object
self.mock_ipr = mock.patch.object(linux_net.pyroute2,
'IPRoute').start()
self.fake_ipr = self.mock_ipr().__enter__()
# Helper variables used accross many tests
self.ip = '10.10.1.16'
self.ipv6 = '2002::1234:abcd:ffff:c0a8:101'
self.dev = 'ethfake'
self.mac = 'aa:bb:cc:dd:ee:ff'
self.bridge = 'br-fake'
self.table_id = 100
self.network = ipaddress.IPv4Network("10.10.1.0/24")
self.network_v6 = ipaddress.IPv6Network("2002:0:0:1234:0:0:0:0/64")
def test_get_ip_version_v4(self):
self.assertEqual(4, linux_net.get_ip_version('%s/32' % self.ip))
self.assertEqual(4, linux_net.get_ip_version(self.ip))
def test_get_ip_version_v6(self):
self.assertEqual(6, linux_net.get_ip_version('%s/64' % self.ipv6))
self.assertEqual(6, linux_net.get_ip_version(self.ipv6))
def test_get_interfaces(self):
iface0 = IPRouteDict({'attrs': [('IFLA_IFNAME', 'ethfake0')]})
iface1 = IPRouteDict({'attrs': [('IFLA_IFNAME', 'ethfake1')]})
iface2 = IPRouteDict({'attrs': [('IFLA_IFNAME', 'ethfake2')]})
self.fake_ipr.get_links.return_value = [iface0, iface1, iface2]
ret = linux_net.get_interfaces(filter_out='ethfake1')
self.assertEqual(['ethfake0', 'ethfake2'], ret)
def test_get_interface_index(self):
self.fake_ipr.link_lookup.return_value = [7]
ret = linux_net.get_interface_index('fake-nic')
self.assertEqual(7, ret)
def test_get_interface_index_error(self):
self.fake_ipr.link_lookup.return_value = ''
self.assertRaises(agent_exc.NetworkInterfaceNotFound,
linux_net.get_interface_index, 'fake-nic')
def test_get_interface_address(self):
device_idx = 7
self.fake_ipr.link_lookup.return_value = [device_idx]
fake_link = mock.MagicMock()
fake_link.get_attr.return_value = self.mac
self.fake_ipr.get_links.return_value = [fake_link]
ret = linux_net.get_interface_address('fake-nic')
self.assertEqual(self.mac, ret)
def test_get_interface_address_index_error(self):
self.fake_ipr.link_lookup.return_value = ''
self.assertRaises(agent_exc.NetworkInterfaceNotFound,
linux_net.get_interface_address, 'fake-nic')
def test_get_nic_info(self):
device_idx = 7
nic_addr = IPRouteDict({'prefixlen': 32,
'attrs': [('IFA_ADDRESS', self.ip)]})
self.fake_ipr.link_lookup.return_value = [device_idx]
self.fake_ipr.get_addr.return_value = [nic_addr]
fake_link = mock.MagicMock()
fake_link.get_attr.return_value = self.mac
self.fake_ipr.get_links.return_value = [fake_link]
ret = linux_net.get_nic_info('fake-nic')
self.assertEqual(('{}/32'.format(self.ip), self.mac), ret)
def test_get_nic_info_index_error(self):
self.fake_ipr.link_lookup.return_value = ''
self.assertRaises(agent_exc.NetworkInterfaceNotFound,
linux_net.get_nic_info, 'fake-nic')
@mock.patch('ovn_bgp_agent.privileged.linux_net.ensure_vrf')
def test_ensure_vrf(self, mock_ensure_vrf):
linux_net.ensure_vrf('fake-vrf', 10)
mock_ensure_vrf.assert_called_once_with('fake-vrf', 10)
@mock.patch('ovn_bgp_agent.privileged.linux_net.ensure_bridge')
def test_ensure_bridge(self, mock_ensure_bridge):
linux_net.ensure_bridge('fake-bridge')
mock_ensure_bridge.assert_called_once_with('fake-bridge')
@mock.patch('ovn_bgp_agent.privileged.linux_net.ensure_vxlan')
def test_ensure_vxlan(self, mock_ensure_vxlan):
linux_net.ensure_vxlan('fake-vxlan', 11, self.ip, 7)
mock_ensure_vxlan.assert_called_once_with('fake-vxlan', 11, self.ip, 7)
@mock.patch('ovn_bgp_agent.privileged.linux_net.ensure_veth')
def test_ensure_veth(self, mock_ensure_veth):
linux_net.ensure_veth('fake-veth', 'fake-veth-peer')
mock_ensure_veth.assert_called_once_with('fake-veth', 'fake-veth-peer')
@mock.patch('ovn_bgp_agent.privileged.linux_net.ensure_dummy_device')
def test_ensure_dummy_device(self, mock_ensure_dummy_device):
linux_net.ensure_dummy_device('fake-dev')
mock_ensure_dummy_device.assert_called_once_with('fake-dev')
@mock.patch.object(linux_net, 'ensure_dummy_device')
@mock.patch.object(linux_net, 'set_master_for_device')
def test_ensure_ovn_device(self, mock_master, mock_dummy):
linux_net.ensure_ovn_device('ifname', 'fake-vrf')
mock_dummy.assert_called_once_with('ifname')
mock_master.assert_called_once_with('ifname', 'fake-vrf')
@mock.patch('ovn_bgp_agent.privileged.linux_net.delete_device')
def test_delete_device(self, mock_delete_device):
linux_net.delete_device('fake-dev')
mock_delete_device.assert_called_once_with('fake-dev')
@mock.patch.object(linux_net, 'enable_proxy_arp')
@mock.patch.object(linux_net, 'enable_proxy_ndp')
@mock.patch('ovn_bgp_agent.privileged.linux_net.add_ip_to_dev')
def test_ensure_arp_ndp_enabled_for_bridge(self, mock_add_ip_to_dev,
mock_ndp, mock_arp):
linux_net.ensure_arp_ndp_enabled_for_bridge('fake-bridge', 511)
# NOTE(ltomasbo): hardoced starting ipv4 is 192.168.0.0, and ipv6 is
# fd53:d91e:400:7f17::0
ipv4 = '169.254.1.255' # base + 511 offset
ipv6 = 'fd53:d91e:400:7f17::1ff' # base + 5122 offset (to hex)
calls = [mock.call(ipv4, 'fake-bridge'),
mock.call(ipv6, 'fake-bridge')]
mock_add_ip_to_dev.assert_has_calls(calls)
mock_ndp.assert_called_once_with('fake-bridge')
mock_arp.assert_called_once_with('fake-bridge')
@mock.patch.object(linux_net, 'enable_proxy_arp')
@mock.patch.object(linux_net, 'enable_proxy_ndp')
@mock.patch('ovn_bgp_agent.privileged.linux_net.add_ip_to_dev')
def test_ensure_arp_ndp_enabled_for_bridge_vlan(self, mock_add_ip_to_dev,
mock_ndp, mock_arp):
linux_net.ensure_arp_ndp_enabled_for_bridge('fake-bridge', 511, 11)
# NOTE(ltomasbo): hardoced starting ipv4 is 192.168.0.0, and ipv6 is
# fd53:d91e:400:7f17::0
ipv4 = '169.254.1.255' # base + 511 offset
ipv6 = 'fd53:d91e:400:7f17::1ff' # base + 5122 offset (to hex)
calls = [mock.call(ipv4, 'fake-bridge'),
mock.call(ipv6, 'fake-bridge')]
mock_add_ip_to_dev.assert_has_calls(calls)
mock_ndp.assert_called_once_with('fake-bridge')
mock_arp.assert_called_once_with('fake-bridge')
def test_ensure_routing_table_for_bridge(self):
# TODO(lucasagomes): This method is massive and complex, perhaps
# break it into helper methods for both readibility and maintenance
# of it.
pass
@mock.patch.object(linux_net, 'enable_proxy_arp')
@mock.patch.object(linux_net, 'enable_proxy_ndp')
@mock.patch(
'ovn_bgp_agent.privileged.linux_net.ensure_vlan_device_for_network')
def test_ensure_vlan_device_for_network(
self, mock_ensure_vlan_device_for_network, mock_ndp, mock_arp):
linux_net.ensure_vlan_device_for_network('fake-br', 10)
expected_dev = 'fake-br/10'
mock_ensure_vlan_device_for_network.assert_called_once_with(
'fake-br', 10)
mock_ndp.assert_called_once_with(expected_dev)
mock_arp.assert_called_once_with(expected_dev)
@mock.patch.object(linux_net, 'delete_device')
def test_delete_vlan_device_for_network(self, mock_del):
linux_net.delete_vlan_device_for_network('fake-br', 10)
vlan_name = 'fake-br.10'
mock_del.assert_called_once_with(vlan_name)
@mock.patch('ovn_bgp_agent.privileged.linux_net.set_kernel_flag')
def test_enable_proxy_ndp(self, mock_flag):
linux_net.enable_proxy_ndp(self.dev)
expected_flag = 'net.ipv6.conf.%s.proxy_ndp' % self.dev
mock_flag.assert_called_once_with(expected_flag, 1)
@mock.patch('ovn_bgp_agent.privileged.linux_net.set_kernel_flag')
def test_enable_proxy_arp(self, mock_flag):
linux_net.enable_proxy_arp(self.dev)
expected_flag = 'net.ipv4.conf.%s.proxy_arp' % self.dev
mock_flag.assert_called_once_with(expected_flag, 1)
def test_get_exposed_ips(self):
ip0 = IPRouteDict({'prefixlen': 32,
'attrs': [('IFA_ADDRESS', self.ip)]})
ip1 = IPRouteDict({'prefixlen': 128,
'attrs': [('IFA_ADDRESS', self.ipv6)]})
ip2 = IPRouteDict({'prefixlen': 24,
'attrs': [('IFA_ADDRESS', '10.10.1.18')]})
ip3 = IPRouteDict(
{'prefixlen': 64,
'attrs': [('IFA_ADDRESS', '2001:0DB8:0000:000b::')]})
self.fake_ipr.get_addr.return_value = [ip0, ip1, ip2, ip3]
ips = linux_net.get_exposed_ips(self.dev)
expected_ips = [self.ip, self.ipv6]
self.assertEqual(expected_ips, ips)
def test_get_nic_ip(self):
ip0 = IPRouteDict({'attrs': [('IFA_ADDRESS', '10.10.1.16')]})
ip1 = IPRouteDict({'attrs': [('IFA_ADDRESS', '10.10.1.17')]})
self.fake_ipr.get_addr.return_value = [ip0, ip1]
ips = linux_net.get_nic_ip(self.dev)
expected_ips = ['10.10.1.16', '10.10.1.17']
self.assertEqual(expected_ips, ips)
def test_get_exposed_ips_on_network(self):
ip0 = IPRouteDict({'prefixlen': 32,
'attrs': [('IFA_ADDRESS', self.ip)]})
ip1 = IPRouteDict({'prefixlen': 128,
'attrs': [('IFA_ADDRESS', '10.10.1.17')]})
ip2 = IPRouteDict({'prefixlen': 128,
'attrs': [('IFA_ADDRESS', self.ipv6)]})
ip3 = IPRouteDict({
'prefixlen': 128,
'attrs': [('IFA_ADDRESS', '2001:db8:3333:4444:5555:6666:7777:8888')
]})
self.fake_ipr.get_addr.return_value = [ip0, ip1, ip2, ip3]
network_ips = [ipaddress.ip_address(self.ip),
ipaddress.ip_address(self.ipv6)]
ret = linux_net.get_exposed_ips_on_network(self.dev, network_ips)
self.assertEqual([self.ip, self.ipv6], ret)
def test_get_exposed_routes_on_network_v4(self):
route0 = mock.MagicMock(
dst=mock.Mock(),
table=self.table_id,
scope=1,
proto=11,
gateway=self.ip,
)
route1 = mock.MagicMock(
dst=mock.Mock(),
table=self.table_id,
scope=1,
proto=11,
gateway=self.ipv6,
)
route2 = mock.MagicMock(
dst=mock.Mock(),
table=self.table_id,
scope=1,
proto=11,
gateway=None,
)
self.fake_ndb.routes.dump.return_value = [route0, route1, route2]
ret = linux_net.get_exposed_routes_on_network(
[self.table_id], self.network
)
self.assertEqual([route0], ret)
def test_get_exposed_routes_on_network_v6(self):
route0 = mock.MagicMock(
dst=mock.Mock(),
table=self.table_id,
scope=1,
proto=11,
gateway=self.ip,
)
route1 = mock.MagicMock(
dst=mock.Mock(),
table=self.table_id,
scope=1,
proto=11,
gateway=self.ipv6,
)
route2 = mock.MagicMock(
dst=mock.Mock(),
table=self.table_id,
scope=1,
proto=11,
gateway=None,
)
self.fake_ndb.routes.dump.return_value = [route0, route1, route2]
ret = linux_net.get_exposed_routes_on_network(
[self.table_id], self.network_v6
)
self.assertEqual([route1], ret)
def test_get_ovn_ip_rules(self):
rule0 = IPRouteDict({'dst_len': 128, 'family': 10,
'attrs': [('FRA_TABLE', 7),
('FRA_DST', 10)]})
rule1 = IPRouteDict({'dst_len': 32, 'family': 2,
'attrs': [('FRA_TABLE', 7),
('FRA_DST', 11)]})
rule2 = IPRouteDict({'dst_len': 24, 'family': 2,
'attrs': [('FRA_TABLE', 9),
('FRA_DST', 5)]})
rule3 = IPRouteDict({'dst_len': 128, 'family': 10,
'attrs': [('FRA_TABLE', 10),
('FRA_DST', 6)]})
self.fake_ipr.get_rules.side_effect = [[rule1, rule2], [rule0, rule3]]
ret = linux_net.get_ovn_ip_rules([7, 10])
expected_ret = {'10/128': {'table': 7, 'family': 10},
'11/32': {'table': 7, 'family': 2},
'6/128': {'table': 10, 'family': 10}}
self.assertEqual(expected_ret, ret)
@mock.patch('ovn_bgp_agent.privileged.linux_net.delete_exposed_ips')
def test_delete_exposed_ips(self, mock_delete_exposed_ips):
linux_net.delete_exposed_ips([self.ip], self.dev)
mock_delete_exposed_ips.assert_called_once_with([self.ip], self.dev)
@mock.patch('ovn_bgp_agent.privileged.linux_net.delete_ip_rules')
def test_delete_ip_rules(self, mock_delete_ip_rules):
ip_rules = {'10/128': {'table': 7, 'family': 'fake'},
'6/128': {'table': 10, 'family': 'fake'}}
linux_net.delete_ip_rules(ip_rules)
mock_delete_ip_rules.assert_called_once_with(ip_rules)
@mock.patch.object(linux_net, 'get_interface_index')
def _test_delete_bridge_ip_routes(self, mock_route_delete, mock_get_index,
is_vlan=False, has_gateway=False):
gateway = '1.1.1.1'
oif = 11
vlan = 30 if is_vlan else None
mock_get_index.return_value = oif
route = {'route': {'dst': self.ip,
'dst_len': 32,
'table': 20},
'vlan': vlan}
if has_gateway:
route['route']['gateway'] = gateway
routing_tables = {self.bridge: 20}
routing_tables_routes = {self.bridge: [route]}
# extra_route0 matches with the route
extra_route0 = IPRouteDict({
'dst_len': 32, 'family': AF_INET, 'table': 20,
'attrs': [('RTA_DST', self.ip),
('RTA_OIF', oif),
('RTA_GATEWAY', gateway)]})
# extra_route1 does not match with route and should be removed
extra_route1 = IPRouteDict({
'dst_len': 32, 'family': AF_INET, 'table': 20,
'attrs': [('RTA_DST', '10.10.1.17'),
('RTA_OIF', oif),
('RTA_GATEWAY', gateway)]})
extra_routes = {self.bridge: [extra_route0, extra_route1]}
linux_net.delete_bridge_ip_routes(
routing_tables, routing_tables_routes, extra_routes)
# Assert extra_route1 has been removed
expected_route = {'dst': '10.10.1.17', 'dst_len': 32,
'family': AF_INET, 'oif': oif,
'gateway': gateway, 'table': 20}
mock_route_delete.assert_called_once_with(expected_route)
@mock.patch('ovn_bgp_agent.privileged.linux_net.route_delete')
def test_delete_bridge_ip_routes(self, mock_route_delete):
self._test_delete_bridge_ip_routes(mock_route_delete)
@mock.patch('ovn_bgp_agent.privileged.linux_net.route_delete')
def test_delete_bridge_ip_routes_vlan(self, mock_route_delete):
self._test_delete_bridge_ip_routes(mock_route_delete, is_vlan=True)
@mock.patch('ovn_bgp_agent.privileged.linux_net.route_delete')
def test_delete_bridge_ip_routes_gateway(self, mock_route_delete):
self._test_delete_bridge_ip_routes(mock_route_delete, has_gateway=True)
@mock.patch('ovn_bgp_agent.utils.linux_net.delete_ip_routes')
def test_delete_routes_from_table(self, mock_delete_ip_routes):
route0 = {'scope': 1, 'proto': 11}
route1 = {'scope': 2, 'proto': 22}
route2 = {'scope': 254, 'proto': 186}
self.fake_ipr.get_routes.return_value = [
route0, route1, route2]
linux_net.delete_routes_from_table('fake-table')
mock_delete_ip_routes.assert_called_once_with([route0, route1])
def test_get_routes_on_tables(self):
route0 = IPRouteDict({
'proto': 10, 'table': 10,
'attrs': [('RTA_DST', '10.10.10.10')]})
# Route1 has proto 186, should be ignored
route1 = IPRouteDict({
'proto': 186, 'table': 11,
'attrs': [('RTA_DST', '11.11.11.11')]})
route2 = IPRouteDict({
'proto': 12, 'table': 11,
'attrs': [('RTA_DST', '12.12.12.12')]})
# Route3 is in the list but dst is empty
route3 = IPRouteDict({
'proto': 10, 'table': 22,
'attrs': [('RTA_DST', '')]})
self.fake_ipr.get_routes.side_effect = [
[route0], [route1, route2], [route3]]
ret = linux_net.get_routes_on_tables([10, 11, 22])
self.assertEqual([route0, route2], ret)
@mock.patch('ovn_bgp_agent.privileged.linux_net.route_delete')
def test_delete_ip_routes(self, mock_route_delete):
route0 = mock.MagicMock(
table=10, dst='10.10.10.10', proto=10, dst_len=128,
oif='ethout', family='fake', gateway='1.1.1.1')
route1 = mock.MagicMock(
table=11, dst='11.11.11.11', proto=11, dst_len=64,
oif='ethout', family='fake', gateway='2.2.2.2')
routes = [route0, route1]
linux_net.delete_ip_routes(routes)
mock_route_delete.has_calls([mock.call(route0), mock.call(route1)])
@mock.patch('ovn_bgp_agent.privileged.linux_net.add_ndp_proxy')
def test_add_ndp_proxy(self, mock_ndp_proxy):
linux_net.add_ndp_proxy(self.ip, self.dev, vlan=10)
mock_ndp_proxy.assert_called_once_with(self.ip, self.dev, 10)
@mock.patch('ovn_bgp_agent.privileged.linux_net.del_ndp_proxy')
def test_del_ndp_proxy(self, mock_ndp_proxy):
linux_net.del_ndp_proxy(self.ip, self.dev, vlan=10)
mock_ndp_proxy.assert_called_once_with(self.ip, self.dev, 10)
@mock.patch('ovn_bgp_agent.privileged.linux_net.route_delete')
@mock.patch('ovn_bgp_agent.privileged.linux_net.add_ip_to_dev')
def test_add_ips_to_dev(self, mock_add_ip_to_dev, mock_route_delete):
ips = [self.ip, self.ipv6]
linux_net.add_ips_to_dev(
self.dev, ips, clear_local_route_at_table=123)
# Assert called for each ip
calls = [mock.call(self.ip, self.dev),
mock.call(self.ipv6, self.dev)]
mock_add_ip_to_dev.has_calls(calls)
r1 = {'table': 123, 'proto': 2, 'scope': 254, 'dst': self.ip, 'oif': 7}
r2 = {'table': 123, 'proto': 2, 'scope': 254, 'dst': self.ipv6,
'oif': 7}
calls = [mock.call(r1),
mock.call(r2)]
mock_route_delete.has_calls(calls)
@mock.patch('ovn_bgp_agent.privileged.linux_net.del_ip_from_dev')
def test_del_ips_from_dev(self, mock_del_ip_from_dev):
ips = [self.ip, self.ipv6]
linux_net.del_ips_from_dev(self.dev, ips)
calls = [mock.call(self.ip, self.dev),
mock.call(self.ipv6, self.dev)]
mock_del_ip_from_dev.has_calls(calls)
@mock.patch.object(linux_net, 'add_ip_nei')
@mock.patch('ovn_bgp_agent.privileged.linux_net.rule_create')
def test_add_ip_rule(self, mock_rule_create, mock_add_ip_nei):
linux_net.add_ip_rule(
self.ip, 7, dev=self.dev, lladdr=self.mac)
expected_args = {'dst': self.ip, 'table': 7, 'dst_len': 32}
mock_rule_create.assert_called_once_with(expected_args)
mock_add_ip_nei.assert_called_once_with(self.ip, self.mac, self.dev)
@mock.patch.object(linux_net, 'add_ip_nei')
@mock.patch('ovn_bgp_agent.privileged.linux_net.rule_create')
def test_add_ip_rule_ipv6(self, mock_rule_create, mock_add_ip_nei):
linux_net.add_ip_rule(self.ipv6, 7, dev=self.dev, lladdr=self.mac)
expected_args = {'dst': self.ipv6,
'table': 7, 'dst_len': 128, 'family': AF_INET6}
mock_rule_create.assert_called_once_with(expected_args)
mock_add_ip_nei.assert_called_once_with(self.ipv6, self.mac, self.dev)
@mock.patch('ovn_bgp_agent.privileged.linux_net.rule_create')
def test_add_ip_rule_invalid_ip(self, mock_rule_create):
self.assertRaises(agent_exc.InvalidPortIP,
linux_net.add_ip_rule, '10.10.1.6/30/128', 7)
mock_rule_create.assert_not_called()
@mock.patch('ovn_bgp_agent.privileged.linux_net.add_ip_nei')
def test_add_ip_nei(self, mock_add_ip_nei):
linux_net.add_ip_nei(self.ip, self.mac, self.dev)
mock_add_ip_nei.assert_called_once_with(self.ip, self.mac, self.dev)
@mock.patch.object(linux_net, 'del_ip_nei')
@mock.patch('ovn_bgp_agent.privileged.linux_net.rule_delete')
def test_del_ip_rule(self, mock_rule_delete, mock_del_ip_nei):
linux_net.del_ip_rule(self.ip, 7, dev=self.dev, lladdr=self.mac)
expected_args = {'dst': self.ip, 'table': 7, 'dst_len': 32}
mock_rule_delete.assert_called_once_with(expected_args)
mock_del_ip_nei.assert_called_once_with(self.ip, self.mac, self.dev)
@mock.patch.object(linux_net, 'del_ip_nei')
@mock.patch('ovn_bgp_agent.privileged.linux_net.rule_delete')
def test_del_ip_rule_ipv6(self, mock_rule_delete, mock_del_ip_nei):
linux_net.del_ip_rule(self.ipv6, 7, dev=self.dev, lladdr=self.mac)
expected_args = {'dst': self.ipv6, 'table': 7,
'dst_len': 128, 'family': AF_INET6}
mock_rule_delete.assert_called_once_with(expected_args)
mock_del_ip_nei.assert_called_once_with(self.ipv6, self.mac, self.dev)
@mock.patch.object(linux_net, 'del_ip_nei')
@mock.patch('ovn_bgp_agent.privileged.linux_net.rule_delete')
def test_del_ip_rule_invalid_ip(self, mock_rule_delete, mock_del_ip_nei):
self.assertRaises(agent_exc.InvalidPortIP,
linux_net.del_ip_rule, '10.10.1.6/30/128', 7)
mock_rule_delete.assert_not_called()
mock_del_ip_nei.assert_not_called()
@mock.patch('ovn_bgp_agent.privileged.linux_net.del_ip_nei')
def test_del_ip_nei(self, mock_del_ip_nei):
linux_net.del_ip_nei(self.ip, self.mac, self.dev)
mock_del_ip_nei.assert_called_once_with(self.ip, self.mac, self.dev)
@mock.patch('ovn_bgp_agent.privileged.linux_net.add_unreachable_route')
def test_add_unreachable_route(self, mock_add_route):
linux_net.add_unreachable_route('fake-vrf')
mock_add_route.assert_called_once_with('fake-vrf')
@mock.patch('ovn_bgp_agent.privileged.linux_net.route_create')
def test_add_ip_route(self, mock_route_create):
routes = {}
linux_net.add_ip_route(routes, self.ip, 7, self.dev)
expected_routes = {
self.dev: [{'route': {'dst': self.ip,
'dst_len': 32,
'oif': mock.ANY,
'proto': 3,
'scope': 253,
'table': 7},
'vlan': None}]}
self.assertEqual(expected_routes, routes)
mock_route_create.assert_not_called()
@mock.patch('ovn_bgp_agent.privileged.linux_net.route_create')
def test_add_ip_route_ipv6(self, mock_route_create):
routes = {}
linux_net.add_ip_route(routes, self.ipv6, 7, self.dev)
expected_routes = {
self.dev: [{'route': {'dst': self.ipv6,
'dst_len': 128,
'family': AF_INET6,
'oif': mock.ANY,
'proto': 3,
'table': 7},
'vlan': None}]}
self.assertEqual(expected_routes, routes)
mock_route_create.assert_not_called()
@mock.patch('ovn_bgp_agent.privileged.linux_net.route_create')
def test_add_ip_route_via(self, mock_route_create):
routes = {}
linux_net.add_ip_route(routes, self.ip, 7, self.dev, via='1.1.1.1')
expected_routes = {
self.dev: [{'route': {'dst': self.ip,
'dst_len': 32,
'gateway': '1.1.1.1',
'oif': mock.ANY,
'proto': 3,
'scope': 0,
'table': 7},
'vlan': None}]}
self.assertEqual(expected_routes, routes)
mock_route_create.assert_not_called()
@mock.patch('ovn_bgp_agent.privileged.linux_net.route_create')
def test_add_ip_route_vlan(self, mock_route_create):
routes = {}
linux_net.add_ip_route(routes, self.ip, 7, self.dev, vlan=10)
expected_routes = {
self.dev: [{'route': {'dst': self.ip,
'dst_len': 32,
'oif': mock.ANY,
'proto': 3,
'scope': 253,
'table': 7},
'vlan': 10}]}
self.assertEqual(expected_routes, routes)
mock_route_create.assert_not_called()
@mock.patch.object(linux_net, 'get_interface_index')
@mock.patch.object(linux_net, 'ensure_vlan_device_for_network')
@mock.patch('ovn_bgp_agent.privileged.linux_net.route_create')
def test_add_ip_route_vlan_keyerror(self, mock_route_create,
mock_ensure_vlan_device,
mock_get_index):
routes = {}
oif = '5'
mock_get_index.side_effect = [agent_exc.NetworkInterfaceNotFound, oif]
linux_net.add_ip_route(routes, self.ip, 7, self.dev, vlan=10)
expected_routes = {
self.dev: [{'route': {'dst': self.ip,
'dst_len': 32,
'oif': oif,
'proto': 3,
'scope': 253,
'table': 7},
'vlan': 10}]}
self.assertEqual(expected_routes, routes)
mock_ensure_vlan_device.assert_called_once_with(self.dev, 10)
mock_route_create.assert_not_called()
@mock.patch('ovn_bgp_agent.privileged.linux_net.route_create')
def test_add_ip_route_mask(self, mock_route_create):
routes = {}
linux_net.add_ip_route(routes, self.ip, 7, self.dev, mask=30)
expected_routes = {
self.dev: [{'route': {'dst': self.ip,
'dst_len': 30,
'oif': mock.ANY,
'proto': 3,
'scope': 253,
'table': 7},
'vlan': None}]}
self.assertEqual(expected_routes, routes)
mock_route_create.assert_not_called()
@mock.patch('ovn_bgp_agent.privileged.linux_net.route_create')
def test_add_ip_route_no_route(self, mock_route_create):
self.fake_ipr.route.return_value = ()
routes = {}
linux_net.add_ip_route(routes, self.ip, 7, self.dev)
expected_routes = {
self.dev: [{'route': {'dst': self.ip,
'dst_len': 32,
'oif': mock.ANY,
'proto': 3,
'scope': 253,
'table': 7},
'vlan': None}]}
self.assertEqual(expected_routes, routes)
mock_route_create.assert_called_once_with(
expected_routes[self.dev][0]['route'])
@mock.patch('ovn_bgp_agent.privileged.linux_net.route_delete')
def test_del_ip_route(self, mock_route_delete):
routes = {
self.dev: [{'route': {'dst': self.ip,
'dst_len': 32,
'oif': mock.ANY,
'proto': 3,
'scope': 253,
'table': 7},
'vlan': None}]}
route = copy.deepcopy(routes[self.dev][0]['route'])
linux_net.del_ip_route(routes, self.ip, 7, self.dev)
self.assertEqual({self.dev: []}, routes)
mock_route_delete.assert_called_once_with(route)
@mock.patch('ovn_bgp_agent.privileged.linux_net.route_delete')
def test_del_ip_route_ipv6(self, mock_route_delete):
routes = {
self.dev: [{'route': {'dst': self.ipv6,
'dst_len': 128,
'family': AF_INET6,
'oif': mock.ANY,
'proto': 3,
'table': 7},
'vlan': None}]}
route = copy.deepcopy(routes[self.dev][0]['route'])
linux_net.del_ip_route(routes, self.ipv6, 7, self.dev)
self.assertEqual({self.dev: []}, routes)
mock_route_delete.assert_called_once_with(route)
@mock.patch('ovn_bgp_agent.privileged.linux_net.route_delete')
def test_del_ip_route_via(self, mock_route_delete):
routes = {
self.dev: [{'route': {'dst': self.ip,
'dst_len': 32,
'oif': mock.ANY,
'gateway': '1.1.1.1',
'proto': 3,
'scope': 0,
'table': 7},
'vlan': None}]}
route = copy.deepcopy(routes[self.dev][0]['route'])
linux_net.del_ip_route(routes, self.ip, 7, self.dev, via='1.1.1.1')
self.assertEqual({self.dev: []}, routes)
mock_route_delete.assert_called_once_with(route)
@mock.patch('ovn_bgp_agent.privileged.linux_net.route_delete')
def test_del_ip_route_vlan(self, mock_route_delete):
routes = {
self.dev: [{'route': {'dst': self.ip,
'dst_len': 32,
'oif': mock.ANY,
'proto': 3,
'scope': 253,
'table': 7},
'vlan': 10}]}
route = copy.deepcopy(routes[self.dev][0]['route'])
linux_net.del_ip_route(routes, self.ip, 7, self.dev, vlan=10)
self.assertEqual({self.dev: []}, routes)
mock_route_delete.assert_called_once_with(route)
@mock.patch('ovn_bgp_agent.privileged.linux_net.route_delete')
def test_del_ip_route_mask(self, mock_route_delete):
routes = {
self.dev: [{'route': {'dst': self.ip,
'dst_len': 30,
'oif': mock.ANY,
'proto': 3,
'scope': 253,
'table': 7},
'vlan': None}]}
route = copy.deepcopy(routes[self.dev][0]['route'])
linux_net.del_ip_route(routes, self.ip, 7, self.dev, mask=30)
self.assertEqual({self.dev: []}, routes)
mock_route_delete.assert_called_once_with(route)