diff options
| author | l0crian1 <ryan.claridge13@gmail.com> | 2025-10-29 09:22:16 -0400 |
|---|---|---|
| committer | l0crian1 <ryan.claridge13@gmail.com> | 2025-10-29 09:22:16 -0400 |
| commit | c3bc42001e478da712bd6c31befd11f56cbd4236 (patch) | |
| tree | 54605ef75d0b4e8d50d461afe21d1f2b820aed0f /src | |
| parent | 4fbb3c6c9e70d6302ebe11d8a56e221a614449aa (diff) | |
| download | vyos-1x-c3bc42001e478da712bd6c31befd11f56cbd4236.tar.gz vyos-1x-c3bc42001e478da712bd6c31befd11f56cbd4236.zip | |
wlb: T7966: Restore default route when interface disconnects/reconnects
Diffstat (limited to 'src')
| -rwxr-xr-x | src/helpers/vyos-load-balancer.py | 41 |
1 files changed, 41 insertions, 0 deletions
diff --git a/src/helpers/vyos-load-balancer.py b/src/helpers/vyos-load-balancer.py index 5df83b31e..249433f0b 100755 --- a/src/helpers/vyos-load-balancer.py +++ b/src/helpers/vyos-load-balancer.py @@ -24,6 +24,7 @@ import time from vyos.config import Config from vyos.template import render from vyos.utils.commit import commit_in_progress +from vyos.utils.dict import dict_search_args from vyos.utils.network import get_interface_address from vyos.utils.process import rc_cmd from vyos.utils.process import run @@ -125,6 +126,43 @@ def dynamic_nexthop_update(lb, ifname): return False +def restore_default_route(lb: dict, ifname: str) -> None: + """ + Restores a missing default route for a WAN interface in its policy routing table. + + When a link flap or DHCP/PPP renegotiation removes the per-interface default route, + this function checks the interface’s assigned table for an existing default entry. + If none is found, it determines the proper next-hop (from DHCP, PPP, or static config) + and reinstalls the route using: + ip route replace table <table_num> default dev <ifname> via <nexthop> + + @param lb Load-balancer state/config dictionary. + @param ifname Interface name whose default route should be verified and restored. + @returns None — exits quietly if the table number or next-hop cannot be found. + """ + table_num = dict_search_args(lb, 'health_state', ifname, 'table_number') + if not table_num: + return + + rc, out = rc_cmd(f'ip -j route show default table {table_num}') + if rc == 0: + rt_table = json.loads(out) + if len(rt_table) > 0: + return + else: + if 'dhcp_nexthop' in lb['health_state'][ifname]: + if ifname[:5] == 'pppoe': + nexthop_addr = parse_ppp_nexthop(ifname) + else: + nexthop_addr = parse_dhcp_nexthop(ifname) + else: + nexthop_addr = dict_search_args(lb, 'interface_health', ifname, 'nexthop') + + if nexthop_addr: + run(f'ip route replace table {table_num} default dev {ifname} via {nexthop_addr}') + else: + return + def nftables_update(lb): # Atomically reload nftables table from template if not os.path.exists(nftables_wlb_conf): @@ -295,6 +333,9 @@ if __name__ == '__main__': if dynamic_nexthop_update(lb, ifname): ip_change = True + restore_default_route(lb, ifname) + + if any(state['state_changed'] for ifname, state in lb['health_state'].items()): if not nftables_update(lb): break |
