Add privsep support

Change-Id: Iab2cb051807cbfa52f43604c93905a8d15158d44
This commit is contained in:
Luis Tomas Bolivar 2021-09-03 16:50:21 +02:00
parent 496755d3a2
commit 05e3d1bff4
8 changed files with 278 additions and 133 deletions

View File

@ -15,10 +15,10 @@
import json
from jinja2 import Template
from oslo_concurrency import processutils
from oslo_log import log as logging
from ovn_bgp_agent import constants
import ovn_bgp_agent.privileged.vtysh
LOG = logging.getLogger(__name__)
@ -70,31 +70,9 @@ router bgp {{ bgp_as }} vrf {{ vrf_name }}
'''
def _run_vtysh_config(frr_config_file):
vtysh_command = "copy {} running-config".format(frr_config_file)
full_args = ['/usr/bin/vtysh', '--vty_socket', constants.FRR_SOCKET_PATH,
'-c', vtysh_command]
try:
return processutils.execute(*full_args, run_as_root=True)
except Exception as e:
LOG.exception("Unable to execute vtysh with %s. Exception: %s",
full_args, e)
raise
def _run_vtysh_command(command):
full_args = ['/usr/bin/vtysh', '--vty_socket', constants.FRR_SOCKET_PATH,
'-c', command]
try:
return processutils.execute(*full_args, run_as_root=True)[0]
except Exception as e:
LOG.exception("Unable to execute vtysh with %s. Exception: %s",
full_args, e)
raise
def _get_router_id(bgp_as):
output = _run_vtysh_command(command='show ip bgp summary json')
output = ovn_bgp_agent.privileged.vtysh.run_vtysh_command(
command='show ip bgp summary json')
return json.loads(output).get('ipv4Unicast', {}).get('routerId')
@ -113,7 +91,7 @@ def vrf_leak(vrf, bgp_as, bgp_router_id=None):
with open(frr_config_file, 'w') as vrf_config_file:
vrf_config_file.write(vrf_config)
_run_vtysh_config(frr_config_file)
ovn_bgp_agent.privileged.vtysh.run_vtysh_config(frr_config_file)
def vrf_reconfigure(evpn_info, action):
@ -141,4 +119,4 @@ def vrf_reconfigure(evpn_info, action):
with open(frr_config_file, 'w') as vrf_config_file:
vrf_config_file.write(vrf_config)
_run_vtysh_config(frr_config_file)
ovn_bgp_agent.privileged.vtysh.run_vtysh_config(frr_config_file)

View File

@ -14,13 +14,14 @@
import pyroute2
from oslo_concurrency import processutils
from oslo_log import log as logging
from ovs.db import idl
from ovn_bgp_agent import constants
import ovn_bgp_agent.privileged.ovs_vsctl
from ovn_bgp_agent.utils import linux_net
from ovsdbapp.backend.ovs_idl import connection
from ovsdbapp.backend.ovs_idl import idlutils
from ovsdbapp.schema.open_vswitch import impl_idl as idl_ovs
@ -29,28 +30,16 @@ from ovsdbapp.schema.open_vswitch import impl_idl as idl_ovs
LOG = logging.getLogger(__name__)
def ovs_cmd(command, args, timeout=None):
full_args = [command]
if timeout is not None:
full_args += ['--timeout=%s' % timeout]
full_args += args
try:
return processutils.execute(*full_args, run_as_root=True)
except Exception as e:
LOG.exception("Unable to execute %s %s. Exception: %s", command,
full_args, e)
raise
def get_ovs_flows_info(bridge, flows_info, cookie):
ovs_ports = ovs_cmd('ovs-vsctl',
['list-ports', bridge])[0].rstrip()
ovs_ports = ovn_bgp_agent.privileged.ovs_vsctl.ovs_cmd(
'ovs-vsctl', ['list-ports', bridge])[0].rstrip()
if not ovs_ports:
flow = ("cookie={}/-1").format(cookie)
ovs_cmd('ovs-ofctl', ['del-flows', bridge, flow])
ovn_bgp_agent.privileged.ovs_vsctl.ovs_cmd(
'ovs-ofctl', ['del-flows', bridge, flow])
return
for ovs_port in ovs_ports.split("\n"):
ovs_ofport = ovs_cmd(
ovs_ofport = ovn_bgp_agent.privileged.ovs_vsctl.ovs_cmd(
'ovs-vsctl',
['get', 'Interface', ovs_port, 'ofport'])[0].rstrip()
flows_info[bridge]['in_port'].add(ovs_ofport)
@ -65,11 +54,13 @@ def remove_extra_ovs_flows(flows_info, cookie):
flow_v6 = ("cookie={},priority=900,ipv6,in_port={},"
"actions=mod_dl_dst:{},NORMAL".format(
cookie, in_port, info['mac']))
ovs_cmd('ovs-ofctl', ['add-flow', bridge, flow])
ovs_cmd('ovs-ofctl', ['add-flow', bridge, flow_v6])
ovn_bgp_agent.privileged.ovs_vsctl.ovs_cmd(
'ovs-ofctl', ['add-flow', bridge, flow])
ovn_bgp_agent.privileged.ovs_vsctl.ovs_cmd(
'ovs-ofctl', ['add-flow', bridge, flow_v6])
cookie_id = ("cookie={}/-1").format(cookie)
current_flows = ovs_cmd(
current_flows = ovn_bgp_agent.privileged.ovs_vsctl.ovs_cmd(
'ovs-ofctl', ['dump-flows', bridge, cookie_id]
)[0].split('\n')[1:-1]
for flow in current_flows:
@ -83,21 +74,23 @@ def remove_extra_ovs_flows(flows_info, cookie):
continue
in_port = flow.split("in_port=")[1].split(" ")[0]
del_flow = ('{},in_port={}').format(cookie_id, in_port)
ovs_cmd('ovs-ofctl', ['del-flows', bridge, del_flow])
ovn_bgp_agent.privileged.ovs_vsctl.ovs_cmd(
'ovs-ofctl', ['del-flows', bridge, del_flow])
def ensure_evpn_ovs_flow(bridge, cookie, mac, port, net, strip_vlan=False):
ovs_port = None
ovs_ports = ovs_cmd('ovs-vsctl', ['list-ports', bridge])[0].rstrip()
ovs_ports = ovn_bgp_agent.privileged.ovs_vsctl.ovs_cmd(
'ovs-vsctl', ['list-ports', bridge])[0].rstrip()
for p in ovs_ports.split('\n'):
if p.startswith('patch-provnet-'):
ovs_port = p
if not ovs_port:
return
ovs_ofport = ovs_cmd(
ovs_ofport = ovn_bgp_agent.privileged.ovs_vsctl.ovs_cmd(
'ovs-vsctl', ['get', 'Interface', ovs_port, 'ofport']
)[0].rstrip()
vrf_ofport = ovs_cmd(
vrf_ofport = ovn_bgp_agent.privileged.ovs_vsctl.ovs_cmd(
'ovs-vsctl', ['get', 'Interface', port, 'ofport']
)[0].rstrip()
@ -131,43 +124,48 @@ def ensure_evpn_ovs_flow(bridge, cookie, mac, port, net, strip_vlan=False):
"actions=mod_dl_dst:{},output={}".format(
cookie, ovs_ofport, mac, net,
ndb.interfaces[bridge]['address'], vrf_ofport))
ovs_cmd('ovs-ofctl', ['add-flow', bridge, flow])
ovn_bgp_agent.privileged.ovs_vsctl.ovs_cmd(
'ovs-ofctl', ['add-flow', bridge, flow])
def remove_evpn_router_ovs_flows(bridge, cookie, mac):
cookie_id = ("cookie={}/-1").format(cookie)
ovs_port = None
ovs_ports = ovs_cmd('ovs-vsctl', ['list-ports', bridge])[0].rstrip()
ovs_ports = ovn_bgp_agent.privileged.ovs_vsctl.ovs_cmd(
'ovs-vsctl', ['list-ports', bridge])[0].rstrip()
for p in ovs_ports.split('\n'):
if p.startswith('patch-provnet-'):
ovs_port = p
if not ovs_port:
return
ovs_ofport = ovs_cmd(
ovs_ofport = ovn_bgp_agent.privileged.ovs_vsctl.ovs_cmd(
'ovs-vsctl', ['get', 'Interface', ovs_port, 'ofport']
)[0].rstrip()
flow = ("{},ip,in_port={},dl_src:{}".format(
cookie_id, ovs_ofport, mac))
ovs_cmd('ovs-ofctl', ['del-flows', bridge, flow])
ovn_bgp_agent.privileged.ovs_vsctl.ovs_cmd(
'ovs-ofctl', ['del-flows', bridge, flow])
flow_v6 = ("{},ipv6,in_port={},dl_src:{}".format(cookie_id, ovs_ofport,
mac))
ovs_cmd('ovs-ofctl', ['del-flows', bridge, flow_v6])
ovn_bgp_agent.privileged.ovs_vsctl.ovs_cmd(
'ovs-ofctl', ['del-flows', bridge, flow_v6])
def remove_evpn_network_ovs_flow(bridge, cookie, mac, net):
cookie_id = ("cookie={}/-1").format(cookie)
ovs_port = None
ovs_ports = ovs_cmd('ovs-vsctl', ['list-ports', bridge])[0].rstrip()
ovs_ports = ovn_bgp_agent.privileged.ovs_vsctl.ovs_cmd(
'ovs-vsctl', ['list-ports', bridge])[0].rstrip()
for p in ovs_ports.split('\n'):
if p.startswith('patch-provnet-'):
ovs_port = p
if not ovs_port:
return
ovs_ofport = ovs_cmd(
ovs_ofport = ovn_bgp_agent.privileged.ovs_vsctl.ovs_cmd(
'ovs-vsctl', ['get', 'Interface', ovs_port, 'ofport']
)[0].rstrip()
@ -178,20 +176,22 @@ def remove_evpn_network_ovs_flow(bridge, cookie, mac, net):
else:
flow = ("{},ip,in_port={},dl_src:{},nw_src={}".format(
cookie_id, ovs_ofport, mac, net))
ovs_cmd('ovs-ofctl', ['del-flows', bridge, flow])
ovn_bgp_agent.privileged.ovs_vsctl.ovs_cmd(
'ovs-ofctl', ['del-flows', bridge, flow])
def ensure_default_ovs_flows(ovn_bridge_mappings, cookie):
cookie_id = ("cookie={}/-1").format(cookie)
for bridge in ovn_bridge_mappings:
ovs_port = ovs_cmd('ovs-vsctl', ['list-ports', bridge])[0].rstrip()
ovs_port = ovn_bgp_agent.privileged.ovs_vsctl.ovs_cmd(
'ovs-vsctl', ['list-ports', bridge])[0].rstrip()
if not ovs_port:
continue
ovs_ofport = ovs_cmd(
ovs_ofport = ovn_bgp_agent.privileged.ovs_vsctl.ovs_cmd(
'ovs-vsctl', ['get', 'Interface', ovs_port, 'ofport']
)[0].rstrip()
flow_filter = ('{},in_port={}').format(cookie_id, ovs_ofport)
current_flows = ovs_cmd(
current_flows = ovn_bgp_agent.privileged.ovs_vsctl.ovs_cmd(
'ovs-ofctl', ['dump-flows', bridge, flow_filter]
)[0].split('\n')[1:-1]
if len(current_flows) == 1:
@ -208,12 +208,14 @@ def ensure_default_ovs_flows(ovn_bridge_mappings, cookie):
"actions=mod_dl_dst:{},NORMAL".format(
cookie, ovs_ofport,
ndb.interfaces[bridge]['address']))
ovs_cmd('ovs-ofctl', ['add-flow', bridge, flow])
ovs_cmd('ovs-ofctl', ['add-flow', bridge, flow_v6])
ovn_bgp_agent.privileged.ovs_vsctl.ovs_cmd(
'ovs-ofctl', ['add-flow', bridge, flow])
ovn_bgp_agent.privileged.ovs_vsctl.ovs_cmd(
'ovs-ofctl', ['add-flow', bridge, flow_v6])
# Remove unneeded flows
port = 'in_port={}'.format(ovs_ofport)
current_flows = ovs_cmd(
current_flows = ovn_bgp_agent.privileged.ovs_vsctl.ovs_cmd(
'ovs-ofctl', ['dump-flows', bridge, cookie_id]
)[0].split('\n')[1:-1]
for flow in current_flows:
@ -221,32 +223,37 @@ def ensure_default_ovs_flows(ovn_bridge_mappings, cookie):
continue
in_port = flow.split("in_port=")[1].split(" ")[0]
del_flow = ('{},in_port={}').format(cookie_id, in_port)
ovs_cmd('ovs-ofctl', ['del-flows', bridge, del_flow])
ovn_bgp_agent.privileged.ovs_vsctl.ovs_cmd(
'ovs-ofctl', ['del-flows', bridge, del_flow])
def add_device_to_ovs_bridge(device, bridge, vlan_tag=None):
if vlan_tag:
tag = "tag={}".format(vlan_tag)
ovs_cmd('ovs-vsctl', ['--may-exist', 'add-port', bridge, device, tag])
ovn_bgp_agent.privileged.ovs_vsctl.ovs_cmd(
'ovs-vsctl', ['--may-exist', 'add-port', bridge, device, tag])
else:
ovs_cmd('ovs-vsctl', ['--may-exist', 'add-port', bridge, device])
ovn_bgp_agent.privileged.ovs_vsctl.ovs_cmd(
'ovs-vsctl', ['--may-exist', 'add-port', bridge, device])
def del_device_from_ovs_bridge(device, bridge=None):
if bridge:
ovs_cmd('ovs-vsctl', ['--if-exists', 'del-port', bridge, device])
ovn_bgp_agent.privileged.ovs_vsctl.ovs_cmd(
'ovs-vsctl', ['--if-exists', 'del-port', bridge, device])
else:
ovs_cmd('ovs-vsctl', ['--if-exists', 'del-port', device])
ovn_bgp_agent.privileged.ovs_vsctl.ovs_cmd(
'ovs-vsctl', ['--if-exists', 'del-port', device])
def get_bridge_flows_by_cookie(bridge, cookie):
cookie_id = ("cookie={}/-1").format(cookie)
return ovs_cmd('ovs-ofctl',
['dump-flows', bridge, cookie_id])[0].split('\n')[1:-1]
return ovn_bgp_agent.privileged.ovs_vsctl.ovs_cmd(
'ovs-ofctl', ['dump-flows', bridge, cookie_id])[0].split('\n')[1:-1]
def get_device_port_at_ovs(device):
return ovs_cmd(
return ovn_bgp_agent.privileged.ovs_vsctl.ovs_cmd(
'ovs-vsctl', ['get', 'Interface', device, 'ofport'])[0].rstrip()
@ -254,7 +261,8 @@ def del_flow(flow, bridge, cookie):
cookie_id = ("cookie={}/-1").format(cookie)
f = '{},priority{}'.format(
cookie_id, flow.split(' actions')[0].split(' priority')[1])
ovs_cmd('ovs-ofctl', ['--strict', 'del-flows', bridge, f])
ovn_bgp_agent.privileged.ovs_vsctl.ovs_cmd(
'ovs-ofctl', ['--strict', 'del-flows', bridge, f])
def get_flow_info(flow):

View File

@ -0,0 +1,42 @@
# Copyright 2021 Red Hat, Inc.
#
# 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.
from oslo_privsep import capabilities
from oslo_privsep import priv_context
default = priv_context.PrivContext(
__name__,
cfg_section='privsep',
pypath=__name__ + '.default',
capabilities=[capabilities.CAP_DAC_OVERRIDE,
capabilities.CAP_DAC_READ_SEARCH,
capabilities.CAP_NET_ADMIN,
capabilities.CAP_SYS_ADMIN],
)
ovs_vsctl_cmd = priv_context.PrivContext(
__name__,
cfg_section='privsep_ovs_vsctl',
pypath=__name__ + '.ovs_vsctl_cmd',
capabilities=[capabilities.CAP_SYS_ADMIN,
capabilities.CAP_NET_ADMIN]
)
vtysh_cmd = priv_context.PrivContext(
__name__,
cfg_section='privsep_vtysh',
pypath=__name__ + '.vtysh_cmd',
capabilities=[capabilities.CAP_SYS_ADMIN,
capabilities.CAP_NET_ADMIN]
)

View File

@ -0,0 +1,88 @@
# Copyright 2021 Red Hat, Inc.
#
# 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 ipaddress
import os
from oslo_concurrency import processutils
from oslo_log import log as logging
import ovn_bgp_agent.privileged.linux_net
LOG = logging.getLogger(__name__)
@ovn_bgp_agent.privileged.default.entrypoint
def set_kernel_flag(flag, value):
command = ["sysctl", "-w", "{}={}".format(flag, value)]
try:
return processutils.execute(*command)
except Exception as e:
LOG.error("Unable to execute %s. Exception: %s", command, e)
raise
@ovn_bgp_agent.privileged.default.entrypoint
def add_ndp_proxy(ip, dev, vlan=None):
# FIXME(ltomasbo): This should use pyroute instead but I didn't find
# out how
net_ip = str(ipaddress.IPv6Network(ip, strict=False).network_address)
dev_name = dev
if vlan:
dev_name = "{}.{}".format(dev, vlan)
command = ["ip", "-6", "nei", "add", "proxy", net_ip, "dev", dev_name]
try:
return processutils.execute(*command)
except Exception as e:
LOG.error("Unable to execute %s. Exception: %s", command, e)
raise
@ovn_bgp_agent.privileged.default.entrypoint
def del_ndp_proxy(ip, dev, vlan=None):
# FIXME(ltomasbo): This should use pyroute instead but I didn't find
# out how
net_ip = str(ipaddress.IPv6Network(ip, strict=False).network_address)
dev_name = dev
if vlan:
dev_name = "{}.{}".format(dev, vlan)
command = ["ip", "-6", "nei", "del", "proxy", net_ip, "dev", dev_name]
env = dict(os.environ)
env['LC_ALL'] = 'C'
try:
return processutils.execute(*command, env_variables=env)
except Exception as e:
if "No such file or directory" in e.stderr:
# Already deleted
return
LOG.error("Unable to execute %s. Exception: %s", command, e)
raise
@ovn_bgp_agent.privileged.default.entrypoint
def add_unreachable_route(vrf_name):
# FIXME: This should use pyroute instead but I didn't find
# out how
env = dict(os.environ)
env['LC_ALL'] = 'C'
for ip_version in [-4, -6]:
command = ["ip", ip_version, "route", "add", "vrf", vrf_name,
"unreachable", "default", "metric", "4278198272"]
try:
return processutils.execute(*command, env_variables=env)
except Exception as e:
if "RTNETLINK answers: File exists" in e.stderr:
continue
LOG.error("Unable to execute %s. Exception: %s", command, e)
raise

View File

@ -0,0 +1,34 @@
# Copyright 2021 Red Hat, Inc.
#
# 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.
from oslo_concurrency import processutils
from oslo_log import log as logging
import ovn_bgp_agent.privileged.ovs_vsctl
LOG = logging.getLogger(__name__)
@ovn_bgp_agent.privileged.ovs_vsctl_cmd.entrypoint
def ovs_cmd(command, args, timeout=None):
full_args = [command]
if timeout is not None:
full_args += ['--timeout=%s' % timeout]
full_args += args
try:
return processutils.execute(*full_args)
except Exception as e:
LOG.exception("Unable to execute %s %s. Exception: %s", command,
full_args, e)
raise

View File

@ -0,0 +1,46 @@
# Copyright 2021 Red Hat, Inc.
#
# 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.
from oslo_concurrency import processutils
from oslo_log import log as logging
from ovn_bgp_agent import constants
import ovn_bgp_agent.privileged.vtysh
LOG = logging.getLogger(__name__)
@ovn_bgp_agent.privileged.vtysh_cmd.entrypoint
def run_vtysh_config(frr_config_file):
vtysh_command = "copy {} running-config".format(frr_config_file)
full_args = ['/usr/bin/vtysh', '--vty_socket', constants.FRR_SOCKET_PATH,
'-c', vtysh_command]
try:
return processutils.execute(*full_args)
except Exception as e:
LOG.exception("Unable to execute vtysh with %s. Exception: %s",
full_args, e)
raise
@ovn_bgp_agent.privileged.vtysh_cmd.entrypoint
def run_vtysh_command(command):
full_args = ['/usr/bin/vtysh', '--vty_socket', constants.FRR_SOCKET_PATH,
'-c', command]
try:
return processutils.execute(*full_args)[0]
except Exception as e:
LOG.exception("Unable to execute vtysh with %s. Exception: %s",
full_args, e)
raise

View File

@ -13,7 +13,6 @@
# limitations under the License.
import ipaddress
import os
import pyroute2
import random
import re
@ -23,11 +22,11 @@ from pyroute2.netlink.rtnl import ndmsg
from socket import AF_INET
from socket import AF_INET6
from oslo_concurrency import processutils
from oslo_log import log as logging
from ovn_bgp_agent import constants
from ovn_bgp_agent import exceptions as agent_exc
import ovn_bgp_agent.privileged.linux_net
LOG = logging.getLogger(__name__)
@ -239,9 +238,9 @@ def ensure_vlan_device_for_network(bridge, vlan_tag):
'state', constants.LINK_UP).commit()
ipv4_flag = "net.ipv4.conf.{}/{}.proxy_arp".format(bridge, vlan_tag)
_set_kernel_flag(ipv4_flag, 1)
ovn_bgp_agent.privileged.linux_net.set_kernel_flag(ipv4_flag, 1)
ipv6_flag = "net.ipv6.conf.{}/{}.proxy_ndp".format(bridge, vlan_tag)
_set_kernel_flag(ipv6_flag, 1)
ovn_bgp_agent.privileged.linux_net.set_kernel_flag(ipv6_flag, 1)
def delete_vlan_device_for_network(bridge, vlan_tag):
@ -249,15 +248,6 @@ def delete_vlan_device_for_network(bridge, vlan_tag):
delete_device(vlan_device_name)
def _set_kernel_flag(flag, value):
command = ["sysctl", "-w", "{}={}".format(flag, value)]
try:
return processutils.execute(*command, run_as_root=True)
except Exception as e:
LOG.error("Unable to execute %s. Exception: %s", command, e)
raise
def get_exposed_ips(nic):
exposed_ips = []
with pyroute2.NDB() as ndb:
@ -413,39 +403,11 @@ def delete_ip_routes(routes):
def add_ndp_proxy(ip, dev, vlan=None):
# FIXME(ltomasbo): This should use pyroute instead but I didn't find
# out how
net_ip = str(ipaddress.IPv6Network(ip, strict=False).network_address)
dev_name = dev
if vlan:
dev_name = "{}.{}".format(dev, vlan)
command = ["ip", "-6", "nei", "add", "proxy", net_ip, "dev", dev_name]
try:
return processutils.execute(*command, run_as_root=True)
except Exception as e:
LOG.error("Unable to execute %s. Exception: %s", command, e)
raise
ovn_bgp_agent.privileged.linux_net.add_ndp_proxy(ip, dev, vlan)
def del_ndp_proxy(ip, dev, vlan=None):
# FIXME(ltomasbo): This should use pyroute instead but I didn't find
# out how
net_ip = str(ipaddress.IPv6Network(ip, strict=False).network_address)
dev_name = dev
if vlan:
dev_name = "{}.{}".format(dev, vlan)
command = ["ip", "-6", "nei", "del", "proxy", net_ip, "dev", dev_name]
env = dict(os.environ)
env['LC_ALL'] = 'C'
try:
return processutils.execute(*command, run_as_root=True,
env_variables=env)
except Exception as e:
if "No such file or directory" in e.stderr:
# Already deleted
return
LOG.error("Unable to execute %s. Exception: %s", command, e)
raise
ovn_bgp_agent.privileged.linux_net.del_ndp_proxy(ip, dev, vlan)
def add_ips_to_dev(nic, ips, clear_local_route_at_table=False):
@ -582,21 +544,7 @@ def del_ip_rule(ip, table, dev=None, lladdr=None):
def add_unreachable_route(vrf_name):
# FIXME: This should use pyroute instead but I didn't find
# out how
env = dict(os.environ)
env['LC_ALL'] = 'C'
for ip_version in [-4, -6]:
command = ["ip", ip_version, "route", "add", "vrf", vrf_name,
"unreachable", "default", "metric", "4278198272"]
try:
return processutils.execute(*command, run_as_root=True,
env_variables=env)
except Exception as e:
if "RTNETLINK answers: File exists" in e.stderr:
continue
LOG.error("Unable to execute %s. Exception: %s", command, e)
raise
ovn_bgp_agent.privileged.linux_net.add_unreachable_route(vrf_name)
def add_ip_route(ovn_routing_tables_routes, ip_address, route_table, dev,

View File

@ -9,6 +9,7 @@ neutron-lib>=2.12.0 # Apache-2.0
oslo.concurrency>=3.26.0 # Apache-2.0
oslo.config>=6.1.0 # Apache-2.0
oslo.log>=3.36.0 # Apache-2.0
oslo.privsep>=2.3.0 # Apache-2.0
oslo.service>=1.40.2 # Apache-2.0
ovs>=2.8.0 # Apache-2.0
ovsdbapp>=1.4.0 # Apache-2.0