diff --git a/src/etc/inc/plugins.inc.d/dpinger.inc b/src/etc/inc/plugins.inc.d/dpinger.inc index 858360898..cc296da6e 100644 --- a/src/etc/inc/plugins.inc.d/dpinger.inc +++ b/src/etc/inc/plugins.inc.d/dpinger.inc @@ -311,6 +311,9 @@ function dpinger_status() 'monitor' => !empty($gwitem['monitor']) ? $gwitem['monitor'] : '~', 'gateway' => $gwitem['gateway'] ?? '', 'monitor_killstates' => $gwitem['monitor_killstates'] ?? '0', + 'monitor_killstates_priority' => $gwitem['monitor_killstates_priority'] ?? '0', + 'priority' => $gwitem['priority'] ?? '255', + 'ipprotocol' => $gwitem['ipprotocol'], 'name' => $gwname, 'stddev' => '~', 'delay' => '~', diff --git a/src/etc/rc.syshook.d/monitor/20-recover b/src/etc/rc.syshook.d/monitor/20-recover index 87b960206..4a48f2500 100755 --- a/src/etc/rc.syshook.d/monitor/20-recover +++ b/src/etc/rc.syshook.d/monitor/20-recover @@ -35,6 +35,8 @@ require_once 'interfaces.inc'; $gwnames = []; $affected_gateways = !empty($argv[1]) ? explode(',', $argv[1]) : []; +$metered_found_prios = ['inet' => 256, 'inet6' => 256]; +$metered_gws = ['inet' => [], 'inet6' => []]; foreach (return_gateways_status() as $status) { if ($status['status'] == 'down') { /* try to recover monitors stuck in down state ignoring "force_down" */ @@ -42,6 +44,23 @@ foreach (return_gateways_status() as $status) { if (!empty($status['monitor_killstates']) && in_array($status['name'], $affected_gateways)) { configdp_run('filter kill gateway_states', [$status['gateway']], true); } + } elseif ($status['status'] != 'force_down') { + /* collect "metered" gateways which should be killed depending priority */ + if (!empty($status['monitor_killstates_priority'])) { + $metered_gws[$status['ipprotocol']][] = $status; + } elseif (in_array($status['name'], $affected_gateways)) { + /* only trigger on "up" events to calculate highest prio */ + $metered_found_prios[$status['ipprotocol']] = min($status['priority'], $metered_found_prios[$status['ipprotocol']]); + } + } +} + +foreach ($metered_found_prios as $ipproto => $metered_found_prio) { + /* kill states for "metered" gateways */ + foreach ($metered_gws[$ipproto] as $status) { + if ($status['priority'] > $metered_found_prio) { + configdp_run('filter kill gateway_states', [$status['gateway']], true); + } } } diff --git a/src/opnsense/mvc/app/controllers/OPNsense/Routing/forms/dialogEditGateway.xml b/src/opnsense/mvc/app/controllers/OPNsense/Routing/forms/dialogEditGateway.xml index e0e9ac622..1d7088b72 100644 --- a/src/opnsense/mvc/app/controllers/OPNsense/Routing/forms/dialogEditGateway.xml +++ b/src/opnsense/mvc/app/controllers/OPNsense/Routing/forms/dialogEditGateway.xml @@ -63,6 +63,13 @@ When a monitor down event is triggered, kill all states to this gateway. + + gateway_item.monitor_killstates_priority + + checkbox + + When a monitor up event is triggered for a gateway with a higher priority (lower value) than this, kill all states to this gateway. Most common use for this switch are metered connections like LTE. + gateway_item.monitor diff --git a/src/opnsense/mvc/app/models/OPNsense/Routing/Gateways.xml b/src/opnsense/mvc/app/models/OPNsense/Routing/Gateways.xml index 21a0b845d..67903e5c7 100644 --- a/src/opnsense/mvc/app/models/OPNsense/Routing/Gateways.xml +++ b/src/opnsense/mvc/app/models/OPNsense/Routing/Gateways.xml @@ -56,6 +56,7 @@ +