From 32b9ac3653fa27e90c0a6b16c3ab141fd4237cb7 Mon Sep 17 00:00:00 2001
From: Christian Breunig <christian@breunig.cc>
Date: Thu, 27 Jul 2023 11:16:40 +0200
Subject: openvpn: T4974: move CLI node "enable-dco" -> "offload dco" to match
 other inetfaces

Keep a common CLI structure by re-using the already established offload
node from ethernet.
---
 src/conf_mode/interfaces-openvpn.py | 28 +++++++++++++++++++++-------
 1 file changed, 21 insertions(+), 7 deletions(-)

(limited to 'src')

diff --git a/src/conf_mode/interfaces-openvpn.py b/src/conf_mode/interfaces-openvpn.py
index 653474ed0..3bef9b8f6 100755
--- a/src/conf_mode/interfaces-openvpn.py
+++ b/src/conf_mode/interfaces-openvpn.py
@@ -115,6 +115,18 @@ def get_config(config=None):
     if dict_search('server.mfa.totp', tmp) == None:
         del openvpn['server']['mfa']
 
+    # OpenVPN Data-Channel-Offload (DCO) is a Kernel module. If loaded it applies to all
+    # OpenVPN interfaces. Check if DCO is used by any other interface instance.
+    tmp = conf.get_config_dict(base, key_mangling=('-', '_'), get_first_key=True)
+    for interface, interface_config in tmp.items():
+        # If one interface has DCO configured, enable it. No need to further check
+        # all other OpenVPN interfaces. We must use a dedicated key to indicate
+        # the Kernel module must be loaded or not. The per interface "offload.dco"
+        # key is required per OpenVPN interface instance.
+        if dict_search('offload.dco', interface_config) != None:
+            openvpn['module_load_dco'] = {}
+            break
+
     return openvpn
 
 def is_ec_private_key(pki, cert_name):
@@ -675,6 +687,15 @@ def apply(openvpn):
         if interface in interfaces():
             VTunIf(interface).remove()
 
+    # dynamically load/unload DCO Kernel extension if requested
+    dco_module = 'ovpn_dco_v2'
+    if 'module_load_dco' in openvpn:
+        check_kmod(dco_module)
+    else:
+        unload_kmod(dco_module)
+
+    # Now bail out early if interface is disabled or got deleted
+    if 'deleted' in openvpn or 'disable' in openvpn:
         return None
 
     # verify specified IP address is present on any interface on this system
@@ -684,13 +705,6 @@ def apply(openvpn):
         if not is_addr_assigned(openvpn['local_host']):
             cmd('sysctl -w net.ipv4.ip_nonlocal_bind=1')
 
-    # dynamically load/unload DCO Kernel extension if requested
-    dco_module = 'ovpn_dco_v2'
-    if 'enable_dco' in openvpn:
-        check_kmod(dco_module)
-    else:
-        unload_kmod(dco_module)
-
     # No matching OpenVPN process running - maybe it got killed or none
     # existed - nevertheless, spawn new OpenVPN process
     action = 'reload-or-restart'
-- 
cgit v1.2.3