Avoid usage of NDB linux_net utils
This patch continues with the work on avoiding NDB usage in favor of IPRoute Partial-Bug: #2022357 Change-Id: I1a8e1a8ca3c82d3cc5a4a10dbccd28cbe14f64c7
This commit is contained in:
parent
1e95409666
commit
14a78503de
@ -12,6 +12,9 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import socket
|
||||
|
||||
import netaddr
|
||||
from oslo_utils import uuidutils
|
||||
|
||||
from ovn_bgp_agent import exceptions as agent_exc
|
||||
@ -22,7 +25,10 @@ from ovn_bgp_agent.tests.functional.privileged import test_linux_net as \
|
||||
from ovn_bgp_agent.utils import linux_net
|
||||
|
||||
|
||||
class GetInterfaceAddressTestCase(base_functional.BaseFunctionalTestCase):
|
||||
_IP_VERSION_FAMILY_MAP = {4: socket.AF_INET, 6: socket.AF_INET6}
|
||||
|
||||
|
||||
class GetInterfaceTestCase(base_functional.BaseFunctionalTestCase):
|
||||
|
||||
def _delete_interfaces(self, dev_names):
|
||||
for dev_name in dev_names:
|
||||
@ -37,6 +43,25 @@ class GetInterfaceAddressTestCase(base_functional.BaseFunctionalTestCase):
|
||||
if device['name'] == device_name:
|
||||
return device
|
||||
|
||||
def test_get_interfaces(self):
|
||||
dev_names = list(map(lambda x: uuidutils.generate_uuid()[:15],
|
||||
range(3)))
|
||||
self.addCleanup(self._delete_interfaces, dev_names)
|
||||
for dev_name in dev_names:
|
||||
priv_linux_net.create_interface(dev_name, 'dummy')
|
||||
ret = linux_net.get_interfaces()
|
||||
for dev in dev_names:
|
||||
self.assertIn(dev, ret)
|
||||
|
||||
def test_get_interface_index(self):
|
||||
dev_name = uuidutils.generate_uuid()[:15]
|
||||
self.addCleanup(self._delete_interfaces, [dev_name])
|
||||
priv_linux_net.create_interface(dev_name, 'dummy')
|
||||
device = self._get_device(dev_name)
|
||||
|
||||
ret = linux_net.get_interface_index(dev_name)
|
||||
self.assertEqual(device['index'], ret)
|
||||
|
||||
def test_get_interface_address(self):
|
||||
dev_names = list(map(lambda x: uuidutils.generate_uuid()[:15],
|
||||
range(5)))
|
||||
@ -50,3 +75,59 @@ class GetInterfaceAddressTestCase(base_functional.BaseFunctionalTestCase):
|
||||
def test_get_interface_address_no_interface(self):
|
||||
self.assertRaises(agent_exc.NetworkInterfaceNotFound,
|
||||
linux_net.get_interface_address, 'no_interface_name')
|
||||
|
||||
def test_get_exposed_ips(self):
|
||||
ips = ['240.0.0.1', 'fd00::1']
|
||||
dev_name = uuidutils.generate_uuid()[:15]
|
||||
self.addCleanup(self._delete_interfaces, [dev_name])
|
||||
priv_linux_net.create_interface(dev_name, 'dummy')
|
||||
for ip in ips:
|
||||
priv_linux_net.add_ip_address(ip, dev_name)
|
||||
|
||||
ret = linux_net.get_exposed_ips(dev_name)
|
||||
self.assertEqual(ips, ret)
|
||||
|
||||
def test_get_nic_ip(self):
|
||||
ips = ['240.0.0.1', 'fd00::1']
|
||||
dev_name = uuidutils.generate_uuid()[:15]
|
||||
self.addCleanup(self._delete_interfaces, [dev_name])
|
||||
priv_linux_net.create_interface(dev_name, 'dummy')
|
||||
for ip in ips:
|
||||
priv_linux_net.add_ip_address(ip, dev_name)
|
||||
|
||||
ret = linux_net.get_nic_ip(dev_name)
|
||||
self.assertEqual(ips, ret)
|
||||
|
||||
|
||||
class GetRulesTestCase(base_functional.BaseFunctionalTestCase):
|
||||
|
||||
def _delete_rules(self, rules):
|
||||
for rule in rules:
|
||||
try:
|
||||
priv_linux_net.rule_delete(rule)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
def test_get_ovn_ip_rules(self):
|
||||
cidrs = ['192.168.0.0/24', '172.90.0.0/16', 'fd00::1/128']
|
||||
table = 100
|
||||
expected_rules = {}
|
||||
rules_added = []
|
||||
for cidr in cidrs:
|
||||
_ip = netaddr.IPNetwork(cidr)
|
||||
ip_version = linux_net.get_ip_version(cidr)
|
||||
rule = {'dst': str(_ip.ip),
|
||||
'dst_len': _ip.netmask.netmask_bits(),
|
||||
'table': table,
|
||||
'family': _IP_VERSION_FAMILY_MAP[ip_version]}
|
||||
dst = "{}/{}".format(str(_ip.ip), _ip.netmask.netmask_bits())
|
||||
rules_added.append(rule)
|
||||
expected_rules[dst] = {
|
||||
'table': table,
|
||||
'family': _IP_VERSION_FAMILY_MAP[ip_version]}
|
||||
self.addCleanup(self._delete_rules, rules_added)
|
||||
for rule in rules_added:
|
||||
priv_linux_net.rule_create(rule)
|
||||
|
||||
ret = linux_net.get_ovn_ip_rules([table])
|
||||
self.assertEqual(expected_rules, ret)
|
||||
|
@ -25,6 +25,14 @@ 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 None
|
||||
|
||||
|
||||
class TestLinuxNet(test_base.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
@ -57,19 +65,24 @@ class TestLinuxNet(test_base.TestCase):
|
||||
self.assertEqual(6, linux_net.get_ip_version(self.ipv6))
|
||||
|
||||
def test_get_interfaces(self):
|
||||
iface0 = mock.Mock(ifname='ethfake0')
|
||||
iface1 = mock.Mock(ifname='ethfake1')
|
||||
iface2 = mock.Mock(ifname='ethfake2')
|
||||
self.fake_ndb.interfaces = [iface0, iface1, iface2]
|
||||
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_ndb.interfaces = {'fake-nic': {'index': 7}}
|
||||
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]
|
||||
@ -105,16 +118,6 @@ class TestLinuxNet(test_base.TestCase):
|
||||
linux_net.ensure_veth('fake-veth', 'fake-veth-peer')
|
||||
mock_ensure_veth.assert_called_once_with('fake-veth', 'fake-veth-peer')
|
||||
|
||||
def test_set_master_for_device_already_set(self):
|
||||
dev = mock.MagicMock()
|
||||
dev.get.return_value = 5
|
||||
|
||||
self.fake_ndb.interfaces = {
|
||||
'fake-dev': dev, 'fake-master': {'index': 5}}
|
||||
linux_net.set_master_for_device('fake-dev', 'fake-master')
|
||||
# Both values were the same, assert set() is not called
|
||||
self.assertFalse(dev.__enter__().set.called)
|
||||
|
||||
@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')
|
||||
@ -202,13 +205,16 @@ class TestLinuxNet(test_base.TestCase):
|
||||
mock_flag.assert_called_once_with(expected_flag, 1)
|
||||
|
||||
def test_get_exposed_ips(self):
|
||||
ip0 = mock.Mock(address=self.ip, prefixlen=32)
|
||||
ip1 = mock.Mock(address=self.ipv6, prefixlen=128)
|
||||
ip2 = mock.Mock(address='10.10.1.18', prefixlen=24)
|
||||
ip3 = mock.Mock(address='2001:0DB8:0000:000b::', prefixlen=64)
|
||||
iface = mock.Mock()
|
||||
iface.ipaddr.summary.return_value = [ip0, ip1, ip2, ip3]
|
||||
self.fake_ndb.interfaces = {self.dev: iface}
|
||||
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)
|
||||
|
||||
@ -216,36 +222,28 @@ class TestLinuxNet(test_base.TestCase):
|
||||
self.assertEqual(expected_ips, ips)
|
||||
|
||||
def test_get_nic_ip(self):
|
||||
ip0 = mock.Mock(address='10.10.1.16')
|
||||
ip1 = mock.Mock(address='10.10.1.17')
|
||||
iface = mock.Mock()
|
||||
iface.ipaddr.summary.return_value = [ip0, ip1]
|
||||
self.fake_ndb.interfaces = {self.dev: iface}
|
||||
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_nic_ip_prefixlen(self):
|
||||
ip = mock.Mock(address=self.ip, prefixlen=32)
|
||||
iface = mock.Mock()
|
||||
iface.ipaddr.summary.return_value.filter.return_value = [ip]
|
||||
self.fake_ndb.interfaces = {self.dev: iface}
|
||||
|
||||
linux_net.get_nic_ip(self.dev, prefixlen_filter=32)
|
||||
iface.ipaddr.summary.return_value.filter.assert_called_once_with(
|
||||
prefixlen=32)
|
||||
|
||||
def test_get_exposed_ips_on_network(self):
|
||||
ip0 = mock.Mock(address=self.ip, prefixlen=32)
|
||||
ip1 = mock.Mock(address='10.10.1.17', prefixlen=128)
|
||||
ip2 = mock.Mock(address=self.ipv6, prefixlen=128)
|
||||
ip3 = mock.Mock(
|
||||
address='2001:db8:3333:4444:5555:6666:7777:8888', prefixlen=128)
|
||||
iface = mock.Mock()
|
||||
iface.ipaddr.summary.return_value = [ip0, ip1, ip2, ip3]
|
||||
self.fake_ndb.interfaces = {self.dev: iface}
|
||||
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)]
|
||||
@ -314,16 +312,24 @@ class TestLinuxNet(test_base.TestCase):
|
||||
self.assertEqual([route1], ret)
|
||||
|
||||
def test_get_ovn_ip_rules(self):
|
||||
rule0 = mock.Mock(table=7, dst=10, dst_len=128, family='fake')
|
||||
rule1 = mock.Mock(table=7, dst=11, dst_len=32, family='fake')
|
||||
rule2 = mock.Mock(table=9, dst=5, dst_len=24, family='fake')
|
||||
rule3 = mock.Mock(table=10, dst=6, dst_len=128, family='fake')
|
||||
self.fake_ndb.rules.dump.return_value = [rule0, rule1, rule2, rule3]
|
||||
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': 'fake'},
|
||||
'11/32': {'table': 7, 'family': 'fake'},
|
||||
'6/128': {'table': 10, 'family': 'fake'}}
|
||||
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')
|
||||
@ -338,15 +344,13 @@ class TestLinuxNet(test_base.TestCase):
|
||||
linux_net.delete_ip_rules(ip_rules)
|
||||
mock_delete_ip_rules.assert_called_once_with(ip_rules)
|
||||
|
||||
def _test_delete_bridge_ip_routes(self, mock_route_delete, is_vlan=False,
|
||||
has_gateway=False):
|
||||
@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
|
||||
vlan_dev = '%s.%s' % (self.bridge, vlan) if is_vlan else None
|
||||
self.fake_ndb.interfaces = {self.bridge: {'index': oif}}
|
||||
if is_vlan:
|
||||
self.fake_ndb.interfaces.update({vlan_dev: {'index': oif}})
|
||||
mock_get_index.return_value = oif
|
||||
|
||||
route = {'route': {'dst': self.ip,
|
||||
'dst_len': 32,
|
||||
@ -358,19 +362,28 @@ class TestLinuxNet(test_base.TestCase):
|
||||
routing_tables = {self.bridge: 20}
|
||||
routing_tables_routes = {self.bridge: [route]}
|
||||
# extra_route0 matches with the route
|
||||
extra_route0 = {'dst': self.ip, 'dst_len': 32,
|
||||
'family': AF_INET, 'oif': oif,
|
||||
'gateway': gateway, 'table': 20}
|
||||
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 = copy.deepcopy(extra_route0)
|
||||
extra_route1['dst'] = '10.10.1.17'
|
||||
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
|
||||
mock_route_delete.assert_called_once_with(extra_route1)
|
||||
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):
|
||||
@ -386,30 +399,33 @@ class TestLinuxNet(test_base.TestCase):
|
||||
|
||||
@mock.patch('ovn_bgp_agent.utils.linux_net.delete_ip_routes')
|
||||
def test_delete_routes_from_table(self, mock_delete_ip_routes):
|
||||
route0 = mock.MagicMock(scope=1, proto=11)
|
||||
route1 = mock.MagicMock(scope=2, proto=22)
|
||||
route2 = mock.MagicMock(scope=254, proto=186)
|
||||
self.fake_ndb.routes.dump().filter.return_value = [
|
||||
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]
|
||||
|
||||
self.fake_ndb.routes.__getitem__.side_effect = (
|
||||
route0, route1)
|
||||
|
||||
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 = mock.MagicMock(table=10, dst='10.10.10.10', proto=10)
|
||||
route0 = IPRouteDict({
|
||||
'proto': 10, 'table': 10,
|
||||
'attrs': [('RTA_DST', '10.10.10.10')]})
|
||||
# Route1 has proto 186, should be ignored
|
||||
route1 = mock.MagicMock(table=11, dst='11.11.11.11', proto=186)
|
||||
route2 = mock.MagicMock(table=11, dst='12.12.12.12', proto=12)
|
||||
# Route3 is not in the table list, should be ignored
|
||||
route3 = mock.MagicMock(table=99, dst='14.14.14.14', proto=14)
|
||||
# Route4 is in the list but dst is empty
|
||||
route4 = mock.MagicMock(table=22, dst='', proto=10)
|
||||
self.fake_ndb.routes.dump.return_value = [
|
||||
route0, route1, route2, route3, route4]
|
||||
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])
|
||||
|
||||
@ -424,7 +440,6 @@ class TestLinuxNet(test_base.TestCase):
|
||||
table=11, dst='11.11.11.11', proto=11, dst_len=64,
|
||||
oif='ethout', family='fake', gateway='2.2.2.2')
|
||||
routes = [route0, route1]
|
||||
self.fake_ndb.routes.__getitem__.side_effect = routes
|
||||
|
||||
linux_net.delete_ip_routes(routes)
|
||||
|
||||
@ -443,9 +458,6 @@ class TestLinuxNet(test_base.TestCase):
|
||||
@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):
|
||||
iface = mock.MagicMock(index=7)
|
||||
self.fake_ndb.interfaces = {self.dev: iface}
|
||||
|
||||
ips = [self.ip, self.ipv6]
|
||||
linux_net.add_ips_to_dev(
|
||||
self.dev, ips, clear_local_route_at_table=123)
|
||||
@ -464,9 +476,6 @@ class TestLinuxNet(test_base.TestCase):
|
||||
|
||||
@mock.patch('ovn_bgp_agent.privileged.linux_net.del_ip_from_dev')
|
||||
def test_del_ips_from_dev(self, mock_del_ip_from_dev):
|
||||
iface = mock.MagicMock()
|
||||
self.fake_ndb.interfaces = {self.dev: iface}
|
||||
|
||||
ips = [self.ip, self.ipv6]
|
||||
linux_net.del_ips_from_dev(self.dev, ips)
|
||||
|
||||
@ -508,9 +517,6 @@ class TestLinuxNet(test_base.TestCase):
|
||||
@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):
|
||||
rule = mock.MagicMock()
|
||||
self.fake_ndb.rules.__getitem__.return_value = rule
|
||||
|
||||
linux_net.del_ip_rule(self.ip, 7, dev=self.dev, lladdr=self.mac)
|
||||
|
||||
expected_args = {'dst': self.ip, 'table': 7, 'dst_len': 32}
|
||||
@ -520,9 +526,6 @@ class TestLinuxNet(test_base.TestCase):
|
||||
@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):
|
||||
rule = mock.MagicMock()
|
||||
self.fake_ndb.rules.__getitem__.return_value = rule
|
||||
|
||||
linux_net.del_ip_rule(self.ipv6, 7, dev=self.dev, lladdr=self.mac)
|
||||
|
||||
expected_args = {'dst': self.ipv6, 'table': 7,
|
||||
@ -533,9 +536,6 @@ class TestLinuxNet(test_base.TestCase):
|
||||
@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):
|
||||
rule = mock.MagicMock()
|
||||
self.fake_ndb.rules.__getitem__.return_value = rule
|
||||
|
||||
self.assertRaises(agent_exc.InvalidPortIP,
|
||||
linux_net.del_ip_rule, '10.10.1.6/30/128', 7)
|
||||
|
||||
@ -565,7 +565,6 @@ class TestLinuxNet(test_base.TestCase):
|
||||
'table': 7},
|
||||
'vlan': None}]}
|
||||
self.assertEqual(expected_routes, routes)
|
||||
self.assertFalse(self.fake_ndb.routes.create.called)
|
||||
mock_route_create.assert_not_called()
|
||||
|
||||
@mock.patch('ovn_bgp_agent.privileged.linux_net.route_create')
|
||||
@ -614,14 +613,15 @@ class TestLinuxNet(test_base.TestCase):
|
||||
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_ensure_vlan_device,
|
||||
mock_get_index):
|
||||
routes = {}
|
||||
oif = '5'
|
||||
self.fake_ndb.interfaces.__getitem__.side_effect = (
|
||||
KeyError('No index'), {'index': oif})
|
||||
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,
|
||||
@ -651,8 +651,8 @@ class TestLinuxNet(test_base.TestCase):
|
||||
mock_route_create.assert_not_called()
|
||||
|
||||
@mock.patch('ovn_bgp_agent.privileged.linux_net.route_create')
|
||||
def test_add_ip_route_keyerror(self, mock_route_create):
|
||||
self.fake_ndb.routes.__getitem__.side_effect = KeyError('Nite Expo')
|
||||
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 = {
|
||||
|
@ -43,9 +43,9 @@ def get_ip_version(ip):
|
||||
stop=tenacity.stop_after_delay(8),
|
||||
reraise=True)
|
||||
def get_interfaces(filter_out=[]):
|
||||
with pyroute2.NDB() as ndb:
|
||||
return [iface.ifname for iface in ndb.interfaces
|
||||
if iface.ifname not in filter_out]
|
||||
with pyroute2.IPRoute() as ipr:
|
||||
return [iface.get_attr('IFLA_IFNAME') for iface in ipr.get_links()
|
||||
if iface.get_attr('IFLA_IFNAME') not in filter_out]
|
||||
|
||||
|
||||
@tenacity.retry(
|
||||
@ -55,8 +55,11 @@ def get_interfaces(filter_out=[]):
|
||||
stop=tenacity.stop_after_delay(8),
|
||||
reraise=True)
|
||||
def get_interface_index(nic):
|
||||
with pyroute2.NDB() as ndb:
|
||||
return ndb.interfaces[nic]['index']
|
||||
try:
|
||||
with pyroute2.IPRoute() as ipr:
|
||||
return ipr.link_lookup(ifname=nic)[0]
|
||||
except IndexError:
|
||||
raise agent_exc.NetworkInterfaceNotFound(device=nic)
|
||||
|
||||
|
||||
@tenacity.retry(
|
||||
@ -69,8 +72,7 @@ def get_interface_address(nic):
|
||||
try:
|
||||
with pyroute2.IPRoute() as ipr:
|
||||
idx = ipr.link_lookup(ifname=nic)[0]
|
||||
mac = ipr.get_links(idx)[0].get_attr('IFLA_ADDRESS')
|
||||
return mac
|
||||
return ipr.get_links(idx)[0].get_attr('IFLA_ADDRESS')
|
||||
except IndexError:
|
||||
raise agent_exc.NetworkInterfaceNotFound(device=nic)
|
||||
|
||||
@ -186,24 +188,23 @@ def ensure_routing_table_for_bridge(ovn_routing_tables, bridge, vrf_table):
|
||||
def _ensure_routing_table_routes(ovn_routing_tables, bridge):
|
||||
# add default route on that table if it does not exist
|
||||
extra_routes = []
|
||||
bridge_idx = get_interface_index(bridge)
|
||||
|
||||
with pyroute2.NDB() as ndb:
|
||||
with pyroute2.IPRoute() as ip:
|
||||
table_route_dsts = set(
|
||||
[
|
||||
(r.dst, r.dst_len)
|
||||
for r in ndb.routes.summary().filter(
|
||||
table=ovn_routing_tables[bridge]
|
||||
)
|
||||
(r.get_attr('RTA_DST'), r['dst_len'])
|
||||
for r in ip.get_routes(table=ovn_routing_tables[bridge])
|
||||
]
|
||||
)
|
||||
|
||||
if not table_route_dsts:
|
||||
r1 = {'dst': 'default', 'oif': ndb.interfaces[bridge]['index'],
|
||||
r1 = {'dst': 'default', 'oif': bridge_idx,
|
||||
'table': ovn_routing_tables[bridge], 'scope': 253,
|
||||
'proto': 3}
|
||||
ovn_bgp_agent.privileged.linux_net.route_create(r1)
|
||||
|
||||
r2 = {'dst': 'default', 'oif': ndb.interfaces[bridge]['index'],
|
||||
r2 = {'dst': 'default', 'oif': bridge_idx,
|
||||
'table': ovn_routing_tables[bridge], 'family': AF_INET6,
|
||||
'proto': 3}
|
||||
ovn_bgp_agent.privileged.linux_net.route_create(r2)
|
||||
@ -213,54 +214,52 @@ def _ensure_routing_table_routes(ovn_routing_tables, bridge):
|
||||
for (dst, dst_len) in table_route_dsts:
|
||||
if not dst: # default route
|
||||
try:
|
||||
route = ndb.routes[
|
||||
{'table': ovn_routing_tables[bridge],
|
||||
'dst': '',
|
||||
'family': AF_INET}]
|
||||
if (bridge ==
|
||||
ndb.interfaces[{'index': route['oif']}][
|
||||
'ifname']):
|
||||
route = [
|
||||
r for r in ip.get_routes(
|
||||
table=ovn_routing_tables[bridge],
|
||||
family=AF_INET)
|
||||
if not r.get_attr('RTA_DST')][0]
|
||||
if bridge_idx == route.get_attr('RTA_OIF'):
|
||||
route_missing = False
|
||||
else:
|
||||
extra_routes.append(route)
|
||||
except KeyError:
|
||||
except IndexError:
|
||||
pass # no ipv4 default rule
|
||||
try:
|
||||
route_6 = ndb.routes[
|
||||
{'table': ovn_routing_tables[bridge],
|
||||
'dst': '',
|
||||
'family': AF_INET6}]
|
||||
if (bridge ==
|
||||
ndb.interfaces[{'index': route_6['oif']}][
|
||||
'ifname']):
|
||||
route_6 = [
|
||||
r for r in ip.get_routes(
|
||||
table=ovn_routing_tables[bridge],
|
||||
family=AF_INET6)
|
||||
if not r.get_attr('RTA_DST')][0]
|
||||
if bridge_idx == route_6.get_attr('RTA_OIF'):
|
||||
route6_missing = False
|
||||
else:
|
||||
extra_routes.append(route_6)
|
||||
except KeyError:
|
||||
except IndexError:
|
||||
pass # no ipv6 default rule
|
||||
else:
|
||||
if get_ip_version(dst) == constants.IP_VERSION_6:
|
||||
extra_routes.append(
|
||||
ndb.routes[{'table': ovn_routing_tables[bridge],
|
||||
'dst': dst,
|
||||
'dst_len': dst_len,
|
||||
'family': AF_INET6}]
|
||||
)
|
||||
ip.get_routes(
|
||||
table=ovn_routing_tables[bridge],
|
||||
dst=dst,
|
||||
dst_len=dst_len,
|
||||
family=AF_INET6)[0])
|
||||
else:
|
||||
extra_routes.append(
|
||||
ndb.routes[{'table': ovn_routing_tables[bridge],
|
||||
'dst': dst,
|
||||
'dst_len': dst_len,
|
||||
'family': AF_INET}]
|
||||
)
|
||||
ip.get_routes(
|
||||
table=ovn_routing_tables[bridge],
|
||||
dst=dst,
|
||||
dst_len=dst_len,
|
||||
family=AF_INET)[0])
|
||||
|
||||
if route_missing:
|
||||
r = {'dst': 'default', 'oif': ndb.interfaces[bridge]['index'],
|
||||
r = {'dst': 'default', 'oif': bridge_idx,
|
||||
'table': ovn_routing_tables[bridge], 'scope': 253,
|
||||
'proto': 3}
|
||||
ovn_bgp_agent.privileged.linux_net.route_create(r)
|
||||
if route6_missing:
|
||||
r = {'dst': 'default', 'oif': ndb.interfaces[bridge]['index'],
|
||||
r = {'dst': 'default', 'oif': bridge_idx,
|
||||
'table': ovn_routing_tables[bridge], 'family': AF_INET6,
|
||||
'proto': 3}
|
||||
ovn_bgp_agent.privileged.linux_net.route_create(r)
|
||||
@ -275,14 +274,12 @@ def _ensure_routing_table_routes(ovn_routing_tables, bridge):
|
||||
reraise=True)
|
||||
def get_extra_routing_table_for_bridge(ovn_routing_tables, bridge):
|
||||
extra_routes = []
|
||||
|
||||
with pyroute2.NDB() as ndb:
|
||||
bridge_idx = get_interface_index(bridge)
|
||||
with pyroute2.IPRoute() as ip:
|
||||
table_route_dsts = set(
|
||||
[
|
||||
(r.dst, r.dst_len)
|
||||
for r in ndb.routes.summary().filter(
|
||||
table=ovn_routing_tables[bridge]
|
||||
)
|
||||
(r.get_attr('RTA_DST'), r['dst_len'])
|
||||
for r in ip.get_routes(table=ovn_routing_tables[bridge])
|
||||
]
|
||||
)
|
||||
|
||||
@ -292,40 +289,40 @@ def get_extra_routing_table_for_bridge(ovn_routing_tables, bridge):
|
||||
for (dst, dst_len) in table_route_dsts:
|
||||
if not dst: # default route
|
||||
try:
|
||||
route = ndb.routes[
|
||||
{'table': ovn_routing_tables[bridge],
|
||||
'dst': '',
|
||||
'family': AF_INET}]
|
||||
if (bridge != ndb.interfaces[{'index': route['oif']}][
|
||||
'ifname']):
|
||||
route = [
|
||||
r for r in ip.get_routes(
|
||||
table=ovn_routing_tables[bridge],
|
||||
family=AF_INET)
|
||||
if not r.get_attr('RTA_DST')][0]
|
||||
if bridge_idx != route.get_attr('RTA_OIF'):
|
||||
extra_routes.append(route)
|
||||
except KeyError:
|
||||
pass # no ipv4 default rule
|
||||
except IndexError:
|
||||
pass # no IPv4 default rule
|
||||
try:
|
||||
route_6 = ndb.routes[
|
||||
{'table': ovn_routing_tables[bridge],
|
||||
'dst': '',
|
||||
'family': AF_INET6}]
|
||||
if (bridge != ndb.interfaces[{'index': route_6['oif']}][
|
||||
'ifname']):
|
||||
route_6 = [
|
||||
r for r in ip.get_routes(
|
||||
table=ovn_routing_tables[bridge],
|
||||
family=AF_INET6)
|
||||
if not r.get_attr('RTA_DST')][0]
|
||||
if bridge_idx != route_6.get_attr('RTA_OIF'):
|
||||
extra_routes.append(route_6)
|
||||
except KeyError:
|
||||
pass # no ipv6 default rule
|
||||
except IndexError:
|
||||
pass # no IPv6 default rule
|
||||
else:
|
||||
if get_ip_version(dst) == constants.IP_VERSION_6:
|
||||
extra_routes.append(
|
||||
ndb.routes[{'table': ovn_routing_tables[bridge],
|
||||
'dst': dst,
|
||||
'dst_len': dst_len,
|
||||
'family': AF_INET6}]
|
||||
)
|
||||
ip.get_routes(
|
||||
table=ovn_routing_tables[bridge],
|
||||
dst=dst,
|
||||
dst_len=dst_len,
|
||||
family=AF_INET6)[0])
|
||||
else:
|
||||
extra_routes.append(
|
||||
ndb.routes[{'table': ovn_routing_tables[bridge],
|
||||
'dst': dst,
|
||||
'dst_len': dst_len,
|
||||
'family': AF_INET}]
|
||||
)
|
||||
ip.get_routes(
|
||||
table=ovn_routing_tables[bridge],
|
||||
dst=dst,
|
||||
dst_len=dst_len,
|
||||
family=AF_INET)[0])
|
||||
return extra_routes
|
||||
|
||||
|
||||
@ -359,12 +356,17 @@ def enable_proxy_arp(device):
|
||||
stop=tenacity.stop_after_delay(8),
|
||||
reraise=True)
|
||||
def get_exposed_ips(nic):
|
||||
exposed_ips = []
|
||||
with pyroute2.NDB() as ndb:
|
||||
exposed_ips = [ip.address
|
||||
for ip in ndb.interfaces[nic].ipaddr.summary()
|
||||
if ip.prefixlen == 32 or ip.prefixlen == 128]
|
||||
return exposed_ips
|
||||
nic_idx = get_interface_index(nic)
|
||||
try:
|
||||
with pyroute2.IPRoute() as ipr:
|
||||
return [ip.get_attr('IFA_ADDRESS')
|
||||
for ip in ipr.get_addr(index=nic_idx)
|
||||
if ip['prefixlen'] in (32, 128)]
|
||||
except pyroute2.netlink.exceptions.NetlinkError:
|
||||
# Nic does not exist
|
||||
LOG.debug("NIC %s does not yet exist, so it does not have exposed IPs",
|
||||
nic)
|
||||
return []
|
||||
|
||||
|
||||
@tenacity.retry(
|
||||
@ -374,38 +376,24 @@ def get_exposed_ips(nic):
|
||||
stop=tenacity.stop_after_delay(8),
|
||||
reraise=True)
|
||||
def get_nic_ip(nic, prefixlen_filter=None):
|
||||
exposed_ips = []
|
||||
with pyroute2.NDB() as ndb:
|
||||
nic_idx = get_interface_index(nic)
|
||||
with pyroute2.IPRoute() as ipr:
|
||||
if prefixlen_filter:
|
||||
exposed_ips = [ip.address
|
||||
for ip in ndb.interfaces[nic].ipaddr.summary(
|
||||
).filter(prefixlen=prefixlen_filter)]
|
||||
return [
|
||||
ip.get_attr('IFA_ADDRESS')
|
||||
for ip in ipr.get_addr(index=nic_idx,
|
||||
prefixlen=prefixlen_filter)
|
||||
]
|
||||
else:
|
||||
exposed_ips = [ip.address
|
||||
for ip in ndb.interfaces[nic].ipaddr.summary()]
|
||||
|
||||
return exposed_ips
|
||||
return [
|
||||
ip.get_attr('IFA_ADDRESS')
|
||||
for ip in ipr.get_addr(index=nic_idx)
|
||||
]
|
||||
|
||||
|
||||
@tenacity.retry(
|
||||
retry=tenacity.retry_if_exception_type(
|
||||
netlink_exceptions.NetlinkDumpInterrupted),
|
||||
wait=tenacity.wait_exponential(multiplier=0.02, max=1),
|
||||
stop=tenacity.stop_after_delay(8),
|
||||
reraise=True)
|
||||
def get_exposed_ips_on_network(nic, network):
|
||||
exposed_ips = []
|
||||
with pyroute2.NDB() as ndb:
|
||||
try:
|
||||
exposed_ips = [ip.address
|
||||
for ip in ndb.interfaces[nic].ipaddr.summary()
|
||||
if ((ip.prefixlen == 32 or ip.prefixlen == 128) and
|
||||
ipaddress.ip_address(ip.address) in network)]
|
||||
except KeyError:
|
||||
# Nic does not exists
|
||||
LOG.debug("Nic %s does not yet exists, so it does not have "
|
||||
"exposed IPs", nic)
|
||||
return exposed_ips
|
||||
exposed_ips = get_exposed_ips(nic)
|
||||
return [ip for ip in exposed_ips if ipaddress.ip_address(ip) in network]
|
||||
|
||||
|
||||
@tenacity.retry(
|
||||
@ -434,14 +422,17 @@ def get_exposed_routes_on_network(table_ids, network):
|
||||
wait=tenacity.wait_exponential(multiplier=0.02, max=1),
|
||||
stop=tenacity.stop_after_delay(8),
|
||||
reraise=True)
|
||||
def get_ovn_ip_rules(routing_table):
|
||||
# get the rules pointing to ovn bridges
|
||||
def get_ovn_ip_rules(routing_tables):
|
||||
ovn_ip_rules = {}
|
||||
with pyroute2.NDB() as ndb:
|
||||
rules_info = [(rule.table,
|
||||
"{}/{}".format(rule.dst, rule.dst_len),
|
||||
rule.family) for rule in ndb.rules.dump()
|
||||
if rule.table in routing_table]
|
||||
with pyroute2.IPRoute() as ipr:
|
||||
rules_info = [
|
||||
(rule.get_attr('FRA_TABLE'),
|
||||
"{}/{}".format(rule.get_attr('FRA_DST'), rule['dst_len']),
|
||||
rule['family'])
|
||||
for rule in (
|
||||
ipr.get_rules(family=AF_INET) + ipr.get_rules(family=AF_INET6))
|
||||
if rule.get_attr('FRA_TABLE') in routing_tables
|
||||
]
|
||||
for table, dst, family in rules_info:
|
||||
ovn_ip_rules[dst] = {'table': table, 'family': family}
|
||||
return ovn_ip_rules
|
||||
@ -457,39 +448,40 @@ def delete_ip_rules(ip_rules):
|
||||
|
||||
def delete_bridge_ip_routes(routing_tables, routing_tables_routes,
|
||||
extra_routes):
|
||||
with pyroute2.NDB() as ndb:
|
||||
for device, routes_info in routing_tables_routes.items():
|
||||
if not extra_routes.get(device):
|
||||
continue
|
||||
for route_info in routes_info:
|
||||
oif = ndb.interfaces[device]['index']
|
||||
if route_info['vlan']:
|
||||
vlan_device_name = '{}.{}'.format(device,
|
||||
route_info['vlan'])
|
||||
oif = ndb.interfaces[vlan_device_name]['index']
|
||||
if 'gateway' in route_info['route'].keys(): # subnet route
|
||||
possible_matchings = [
|
||||
r for r in extra_routes[device]
|
||||
if (r['dst'] == route_info['route']['dst'] and
|
||||
r['dst_len'] == route_info['route']['dst_len'] and
|
||||
r['gateway'] == route_info['route']['gateway'])]
|
||||
else: # cr-lrp
|
||||
possible_matchings = [
|
||||
r for r in extra_routes[device]
|
||||
if (r['dst'] == route_info['route']['dst'] and
|
||||
r['dst_len'] == route_info['route']['dst_len'] and
|
||||
r['oif'] == oif)]
|
||||
for r in possible_matchings:
|
||||
extra_routes[device].remove(r)
|
||||
for device, routes_info in routing_tables_routes.items():
|
||||
if not extra_routes.get(device):
|
||||
continue
|
||||
for route_info in routes_info:
|
||||
oif = get_interface_index(device)
|
||||
if route_info['vlan']:
|
||||
vlan_device_name = '{}.{}'.format(device,
|
||||
route_info['vlan'])
|
||||
oif = get_interface_index(vlan_device_name)
|
||||
if 'gateway' in route_info['route'].keys(): # subnet route
|
||||
possible_matchings = [
|
||||
r for r in extra_routes[device]
|
||||
if (r.get_attr('RTA_DST') == route_info['route']['dst'] and
|
||||
r['dst_len'] == route_info['route']['dst_len'] and
|
||||
r.get_attr('RTA_GATEWAY') == route_info['route'][
|
||||
'gateway'])]
|
||||
else: # cr-lrp
|
||||
possible_matchings = [
|
||||
r for r in extra_routes[device]
|
||||
if (r.get_attr('RTA_DST') == route_info['route']['dst'] and
|
||||
r['dst_len'] == route_info['route']['dst_len'] and
|
||||
r.get_attr('RTA_OIF') == oif)]
|
||||
for r in possible_matchings:
|
||||
extra_routes[device].remove(r)
|
||||
|
||||
for bridge, routes in extra_routes.items():
|
||||
for route in routes:
|
||||
r_info = {'dst': route['dst'],
|
||||
r_info = {'dst': route.get_attr('RTA_DST'),
|
||||
'dst_len': route['dst_len'],
|
||||
'family': route['family'],
|
||||
'oif': route['oif'],
|
||||
'gateway': route['gateway'],
|
||||
'oif': route.get_attr('RTA_OIF'),
|
||||
'table': routing_tables[bridge]}
|
||||
if route.get_attr('RTA_GATEWAY'):
|
||||
r_info['gateway'] = route.get_attr('RTA_GATEWAY')
|
||||
ovn_bgp_agent.privileged.linux_net.route_delete(r_info)
|
||||
|
||||
|
||||
@ -505,10 +497,11 @@ def delete_routes_from_table(table):
|
||||
stop=tenacity.stop_after_delay(8),
|
||||
reraise=True)
|
||||
def _get_table_routes(table):
|
||||
with pyroute2.NDB() as ndb:
|
||||
# FIXME: problem in pyroute2 removing routes with local (254) scope
|
||||
return [r for r in ndb.routes.dump().filter(table=table)
|
||||
if r.scope != 254 and r.proto != 186]
|
||||
with pyroute2.IPRoute() as ipr:
|
||||
return [
|
||||
r for r in ipr.get_routes(table=table)
|
||||
if r['scope'] != 254 and r['proto'] != 186
|
||||
]
|
||||
|
||||
|
||||
@tenacity.retry(
|
||||
@ -518,10 +511,15 @@ def _get_table_routes(table):
|
||||
stop=tenacity.stop_after_delay(8),
|
||||
reraise=True)
|
||||
def get_routes_on_tables(table_ids):
|
||||
with pyroute2.NDB() as ndb:
|
||||
# NOTE: skip bgp routes (proto 186)
|
||||
return [r for r in ndb.routes.dump()
|
||||
if r.table in table_ids and r.dst != '' and r.proto != 186]
|
||||
routes = []
|
||||
with pyroute2.IPRoute() as ipr:
|
||||
for table_id in table_ids:
|
||||
table_routes = [
|
||||
r for r in ipr.get_routes(table=table_id)
|
||||
if r.get_attr('RTA_DST') and r['proto'] != 186
|
||||
]
|
||||
routes.extend(table_routes)
|
||||
return routes
|
||||
|
||||
|
||||
def delete_ip_routes(routes):
|
||||
@ -549,22 +547,19 @@ def add_ips_to_dev(nic, ips, clear_local_route_at_table=False):
|
||||
try:
|
||||
ovn_bgp_agent.privileged.linux_net.add_ip_to_dev(ip, nic)
|
||||
except agent_exc.IpAddressAlreadyExists:
|
||||
# NDB raises KeyError: 'object exists'
|
||||
# if the ip is already added
|
||||
already_added_ips.append(ip)
|
||||
|
||||
if clear_local_route_at_table:
|
||||
for ip in ips:
|
||||
if ip in already_added_ips:
|
||||
continue
|
||||
with pyroute2.NDB() as ndb:
|
||||
oif = ndb.interfaces[nic]['index']
|
||||
route = {'table': clear_local_route_at_table,
|
||||
'proto': 2,
|
||||
'scope': 254,
|
||||
'dst': ip,
|
||||
'oif': oif}
|
||||
ovn_bgp_agent.privileged.linux_net.route_delete(route)
|
||||
oif = get_interface_index(nic)
|
||||
route = {'table': clear_local_route_at_table,
|
||||
'proto': 2,
|
||||
'scope': 254,
|
||||
'dst': ip,
|
||||
'oif': oif}
|
||||
ovn_bgp_agent.privileged.linux_net.route_delete(route)
|
||||
|
||||
|
||||
def del_ips_from_dev(nic, ips):
|
||||
@ -601,8 +596,6 @@ def add_ip_nei(ip, lladdr, dev):
|
||||
param lladdr: link layer address of the neighbor to associate to that IP
|
||||
param dev: the interface to which the neighbor is attached
|
||||
"""
|
||||
# FIXME: There is no support for creating neighbours in NDB
|
||||
# So we are using iproute here
|
||||
ovn_bgp_agent.privileged.linux_net.add_ip_nei(ip, lladdr, dev)
|
||||
|
||||
|
||||
@ -635,8 +628,6 @@ def del_ip_nei(ip, lladdr, dev):
|
||||
param lladdr: link layer address of the neighbor to disassociate
|
||||
param dev: the interface to which the neighbor is attached
|
||||
"""
|
||||
# FIXME: There is no support for deleting neighbours in NDB
|
||||
# So we are using iproute here
|
||||
ovn_bgp_agent.privileged.linux_net.del_ip_nei(ip, lladdr, dev)
|
||||
|
||||
|
||||
@ -644,6 +635,12 @@ def add_unreachable_route(vrf_name):
|
||||
ovn_bgp_agent.privileged.linux_net.add_unreachable_route(vrf_name)
|
||||
|
||||
|
||||
@tenacity.retry(
|
||||
retry=tenacity.retry_if_exception_type(
|
||||
netlink_exceptions.NetlinkDumpInterrupted),
|
||||
wait=tenacity.wait_exponential(multiplier=0.02, max=1),
|
||||
stop=tenacity.stop_after_delay(8),
|
||||
reraise=True)
|
||||
def add_ip_route(ovn_routing_tables_routes, ip_address, route_table, dev,
|
||||
vlan=None, mask=None, via=None):
|
||||
net_ip = ip_address
|
||||
@ -661,20 +658,19 @@ def add_ip_route(ovn_routing_tables_routes, ip_address, route_table, dev,
|
||||
net_ip = '{}'.format(ipaddress.IPv4Network(
|
||||
ip, strict=False).network_address)
|
||||
|
||||
with pyroute2.NDB() as ndb:
|
||||
if vlan:
|
||||
oif_name = '{}.{}'.format(dev, vlan)
|
||||
try:
|
||||
oif = ndb.interfaces[oif_name]['index']
|
||||
except KeyError:
|
||||
# Most provider network was recently created an
|
||||
# there has not been a sync since then, therefore
|
||||
# the vlan device has not yet been created
|
||||
# Trying to create the device and retrying
|
||||
ensure_vlan_device_for_network(dev, vlan)
|
||||
oif = ndb.interfaces[oif_name]['index']
|
||||
else:
|
||||
oif = ndb.interfaces[dev]['index']
|
||||
if vlan:
|
||||
oif_name = '{}.{}'.format(dev, vlan)
|
||||
try:
|
||||
oif = get_interface_index(oif_name)
|
||||
except agent_exc.NetworkInterfaceNotFound:
|
||||
# Most provider network was recently created an
|
||||
# there has not been a sync since then, therefore
|
||||
# the vlan device has not yet been created
|
||||
# Trying to create the device and retrying
|
||||
ensure_vlan_device_for_network(dev, vlan)
|
||||
oif = get_interface_index(oif_name)
|
||||
else:
|
||||
oif = get_interface_index(dev)
|
||||
|
||||
route = {'dst': net_ip, 'dst_len': int(mask), 'oif': oif,
|
||||
'table': int(route_table), 'proto': 3}
|
||||
@ -687,14 +683,13 @@ def add_ip_route(ovn_routing_tables_routes, ip_address, route_table, dev,
|
||||
route['family'] = AF_INET6
|
||||
del route['scope']
|
||||
|
||||
with pyroute2.NDB() as ndb:
|
||||
try:
|
||||
with ndb.routes[route]:
|
||||
LOG.debug("Route already existing: %s", route)
|
||||
except KeyError:
|
||||
with pyroute2.IPRoute() as ipr:
|
||||
if not ipr.route('show', **route):
|
||||
LOG.debug("Creating route at table %s: %s", route_table, route)
|
||||
ovn_bgp_agent.privileged.linux_net.route_create(route)
|
||||
LOG.debug("Route created at table %s: %s", route_table, route)
|
||||
else:
|
||||
LOG.debug("Route already existing: %s", route)
|
||||
route_info = {'vlan': vlan, 'route': route}
|
||||
ovn_routing_tables_routes.setdefault(dev, []).append(route_info)
|
||||
|
||||
@ -716,18 +711,17 @@ def del_ip_route(ovn_routing_tables_routes, ip_address, route_table, dev,
|
||||
net_ip = '{}'.format(ipaddress.IPv4Network(
|
||||
ip, strict=False).network_address)
|
||||
|
||||
with pyroute2.NDB() as ndb:
|
||||
try:
|
||||
if vlan:
|
||||
oif_name = '{}.{}'.format(dev, vlan)
|
||||
oif = ndb.interfaces[oif_name]['index']
|
||||
else:
|
||||
oif = ndb.interfaces[dev]['index']
|
||||
except KeyError:
|
||||
LOG.debug("Device %s does not exists, so the associated "
|
||||
"routes should have been automatically deleted.", dev)
|
||||
ovn_routing_tables_routes.pop(dev, None)
|
||||
return
|
||||
try:
|
||||
if vlan:
|
||||
oif_name = '{}.{}'.format(dev, vlan)
|
||||
oif = get_interface_index(oif_name)
|
||||
else:
|
||||
oif = get_interface_index(dev)
|
||||
except agent_exc.NetworkInterfaceNotFound:
|
||||
LOG.debug("Device %s does not exists, so the associated "
|
||||
"routes should have been automatically deleted.", dev)
|
||||
ovn_routing_tables_routes.pop(dev, None)
|
||||
return
|
||||
|
||||
route = {'dst': net_ip, 'dst_len': int(mask), 'oif': oif,
|
||||
'table': int(route_table), 'proto': 3}
|
||||
|
Loading…
x
Reference in New Issue
Block a user