summaryrefslogtreecommitdiff
path: root/src/conf_mode/vpp.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/conf_mode/vpp.py')
-rwxr-xr-xsrc/conf_mode/vpp.py71
1 files changed, 51 insertions, 20 deletions
diff --git a/src/conf_mode/vpp.py b/src/conf_mode/vpp.py
index d541e52ba..25fe159f8 100755
--- a/src/conf_mode/vpp.py
+++ b/src/conf_mode/vpp.py
@@ -16,9 +16,11 @@
from pathlib import Path
+from re import search as re_search, MULTILINE as re_M
from vyos.config import Config
from vyos.configdict import dict_merge
+from vyos.configdict import node_changed
from vyos.ifconfig import Section
from vyos.ifconfig import EthernetIf
from vyos.ifconfig import interface
@@ -30,6 +32,7 @@ from vyos.xml import defaults
from vyos import ConfigError
from vyos import airbag
from vyos.vpp import VPPControl
+from vyos.vpp import HostControl
airbag.enable()
@@ -38,14 +41,25 @@ service_conf = Path(f'/run/vpp/{service_name}.conf')
systemd_override = '/run/systemd/system/vpp.service.d/10-override.conf'
-def _get_pci_address_by_interface(iface):
+def _get_pci_address_by_interface(iface) -> str:
from vyos.util import rc_cmd
rc, out = rc_cmd(f'ethtool -i {iface}')
- if rc == 0:
- output_lines = out.split('\n')
- for line in output_lines:
- if 'bus-info' in line:
- return line.split(None, 1)[1].strip()
+ # if ethtool command was successful
+ if rc == 0 and out:
+ regex_filter = r'^bus-info: (?P<address>\w+:\w+:\w+\.\w+)$'
+ re_obj = re_search(regex_filter, out, re_M)
+ # if bus-info with PCI address found
+ if re_obj:
+ address = re_obj.groupdict().get('address', '')
+ return address
+ # use VPP - maybe interface already attached to it
+ vpp_control = VPPControl()
+ pci_addr = vpp_control.get_pci_addr(iface)
+ if pci_addr:
+ return pci_addr
+ # return empty string if address was not found
+ return ''
+
def get_config(config=None):
@@ -56,8 +70,20 @@ def get_config(config=None):
base = ['vpp']
base_ethernet = ['interfaces', 'ethernet']
+
+ # find interfaces removed from VPP
+ removed_ifaces = []
+ tmp = node_changed(conf, base + ['interface'])
+ if tmp:
+ for removed_iface in tmp:
+ pci_address: str = _get_pci_address_by_interface(removed_iface)
+ removed_ifaces.append({
+ 'iface_name': removed_iface,
+ 'iface_pci_addr': pci_address
+ })
+
if not conf.exists(base):
- return None
+ return {'removed_ifaces': removed_ifaces}
config = conf.get_config_dict(base,
get_first_key=True,
@@ -84,12 +110,15 @@ def get_config(config=None):
config['other_interfaces'] = conf.get_config_dict(base_ethernet, key_mangling=('-', '_'),
get_first_key=True, no_tag_node_value_mangle=True)
+ if removed_ifaces:
+ config['removed_ifaces'] = removed_ifaces
+
return config
def verify(config):
# bail out early - looks like removal from running config
- if not config:
+ if not config or (len(config) == 1 and 'removed_ifaces' in config):
return None
if 'interface' not in config:
@@ -101,7 +130,7 @@ def verify(config):
def generate(config):
- if not config:
+ if not config or (len(config) == 1 and 'removed_ifaces' in config):
# Remove old config and return
service_conf.unlink(missing_ok=True)
return None
@@ -113,22 +142,24 @@ def generate(config):
def apply(config):
- if not config:
- print(f'systemctl stop {service_name}.service')
+ if not config or (len(config) == 1 and 'removed_ifaces' in config):
call(f'systemctl stop {service_name}.service')
- return
else:
- print(f'systemctl restart {service_name}.service')
+ call('systemctl daemon-reload')
call(f'systemctl restart {service_name}.service')
- call('systemctl daemon-reload')
+ for iface in config.get('removed_ifaces', []):
+ HostControl().pci_rescan(iface['iface_pci_addr'])
- call('sudo sysctl -w vm.nr_hugepages=4096')
- vpp_control = VPPControl()
- for iface, _ in config['interface'].items():
- # Create lcp
- if iface not in Section.interfaces():
- vpp_control.lcp_pair_add(iface, iface)
+ if 'interface' in config:
+ # connect to VPP
+ # must be performed multiple attempts because API is not available
+ # immediately after the service restart
+ vpp_control = VPPControl(attempts=20, interval=500)
+ for iface, _ in config['interface'].items():
+ # Create lcp
+ if iface not in Section.interfaces():
+ vpp_control.lcp_pair_add(iface, iface)
# update interface config
#e = EthernetIf(iface)