summaryrefslogtreecommitdiff
path: root/src/conf_mode/interfaces-macsec.py
diff options
context:
space:
mode:
authorChristian Poessinger <christian@poessinger.com>2022-07-18 23:48:31 +0200
committerChristian Poessinger <christian@poessinger.com>2022-08-15 18:00:54 +0200
commit488024e698ac5479b652f072b1680cdc62396f73 (patch)
treebc1a88da62645b70f2a838ed1f6e2f122b5ce9eb /src/conf_mode/interfaces-macsec.py
parentfd5adb0136aa49a9ec59bb16ff7956b7a9f8a85c (diff)
downloadvyos-1x-488024e698ac5479b652f072b1680cdc62396f73.tar.gz
vyos-1x-488024e698ac5479b652f072b1680cdc62396f73.zip
macsec: T4537: support online ciper and source-interface re-configuration
(cherry picked from commit 82d8494d349edd7707c3811a71ca0e9c0648204e)
Diffstat (limited to 'src/conf_mode/interfaces-macsec.py')
-rwxr-xr-xsrc/conf_mode/interfaces-macsec.py89
1 files changed, 46 insertions, 43 deletions
diff --git a/src/conf_mode/interfaces-macsec.py b/src/conf_mode/interfaces-macsec.py
index e3527a366..eac92f149 100755
--- a/src/conf_mode/interfaces-macsec.py
+++ b/src/conf_mode/interfaces-macsec.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
#
-# Copyright (C) 2020 VyOS maintainers and contributors
+# Copyright (C) 2020-2022 VyOS maintainers and contributors
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or later as
@@ -21,17 +21,19 @@ from sys import exit
from vyos.config import Config
from vyos.configdict import get_interface_dict
-from vyos.ifconfig import MACsecIf
-from vyos.ifconfig import Interface
-from vyos.template import render
-from vyos.util import call
-from vyos.util import dict_search
+from vyos.configdict import is_node_changed
from vyos.configverify import verify_vrf
from vyos.configverify import verify_address
from vyos.configverify import verify_bridge_delete
from vyos.configverify import verify_mtu_ipv6
from vyos.configverify import verify_source_interface
from vyos.configverify import verify_bond_bridge_member
+from vyos.ifconfig import MACsecIf
+from vyos.ifconfig import Interface
+from vyos.template import render
+from vyos.util import call
+from vyos.util import dict_search
+from vyos.util import is_systemd_service_running
from vyos import ConfigError
from vyos import airbag
airbag.enable()
@@ -56,6 +58,13 @@ def get_config(config=None):
source_interface = conf.return_effective_value(['source-interface'])
macsec.update({'source_interface': source_interface})
+ ifname = macsec['ifname']
+ if is_node_changed(conf, base + [ifname, 'security']):
+ macsec.update({'shutdown_required': {}})
+
+ if is_node_changed(conf, base + [ifname, 'source_interface']):
+ macsec.update({'shutdown_required': {}})
+
return macsec
@@ -70,20 +79,12 @@ def verify(macsec):
verify_address(macsec)
verify_bond_bridge_member(macsec)
- if not (('security' in macsec) and
- ('cipher' in macsec['security'])):
- raise ConfigError(
- 'Cipher suite must be set for MACsec "{ifname}"'.format(**macsec))
-
- if (('security' in macsec) and
- ('encrypt' in macsec['security'])):
- tmp = macsec.get('security')
+ if dict_search('security.cipher', macsec) == None:
+ raise ConfigError('Cipher suite must be set for MACsec "{ifname}"'.format(**macsec))
- if not (('mka' in tmp) and
- ('cak' in tmp['mka']) and
- ('ckn' in tmp['mka'])):
- raise ConfigError('Missing mandatory MACsec security '
- 'keys as encryption is enabled!')
+ if dict_search('security.encrypt', macsec) != None:
+ if dict_search('security.mka.cak', macsec) == None or dict_search('security.mka.ckn', macsec) == None:
+ raise ConfigError('Missing mandatory MACsec security keys as encryption is enabled!')
cak_len = len(dict_search('security.mka.cak', macsec))
@@ -114,35 +115,37 @@ def generate(macsec):
def apply(macsec):
- # Remove macsec interface
- if 'deleted' in macsec:
- call('systemctl stop wpa_supplicant-macsec@{source_interface}'
- .format(**macsec))
+ systemd_service = 'wpa_supplicant-macsec@{source_interface}'.format(**macsec)
+
+ # Remove macsec interface on deletion or mandatory parameter change
+ if 'deleted' in macsec or 'shutdown_required' in macsec:
+ call(f'systemctl stop {systemd_service}')
if macsec['ifname'] in interfaces():
tmp = MACsecIf(macsec['ifname'])
tmp.remove()
- # delete configuration on interface removal
- if os.path.isfile(wpa_suppl_conf.format(**macsec)):
- os.unlink(wpa_suppl_conf.format(**macsec))
-
- else:
- # This is a special type of interface which needs additional parameters
- # when created using iproute2. Instead of passing a ton of arguments,
- # use a dictionary provided by the interface class which holds all the
- # options necessary.
- conf = MACsecIf.get_config()
- conf['source_interface'] = macsec['source_interface']
- conf['security_cipher'] = macsec['security']['cipher']
-
- # It is safe to "re-create" the interface always, there is a sanity
- # check that the interface will only be create if its non existent
- i = MACsecIf(macsec['ifname'], **conf)
- i.update(macsec)
-
- call('systemctl restart wpa_supplicant-macsec@{source_interface}'
- .format(**macsec))
+ if 'deleted' in macsec:
+ # delete configuration on interface removal
+ if os.path.isfile(wpa_suppl_conf.format(**macsec)):
+ os.unlink(wpa_suppl_conf.format(**macsec))
+ return None
+
+ # This is a special type of interface which needs additional parameters
+ # when created using iproute2. Instead of passing a ton of arguments,
+ # use a dictionary provided by the interface class which holds all the
+ # options necessary.
+ conf = MACsecIf.get_config()
+ conf['source_interface'] = macsec['source_interface']
+ conf['security_cipher'] = macsec['security']['cipher']
+
+ # It is safe to "re-create" the interface always, there is a sanity
+ # check that the interface will only be create if its non existent
+ i = MACsecIf(macsec['ifname'], **conf)
+ i.update(macsec)
+
+ if not is_systemd_service_running(systemd_service) or 'shutdown_required' in macsec:
+ call(f'systemctl reload-or-restart {systemd_service}')
return None