Commit 0df79c2d authored by Vitaly Lipatov's avatar Vitaly Lipatov

route-update.sh: add multipath support for multiple gateways

When gateway file contains multiple IPs, generate multipath routes with nexthop per gateway (weight 1 each). Kernel distributes traffic per-flow across gateways. Single gateway: route replace IP via GW table T Multiple: route replace IP table T nexthop via GW1 weight 1 nexthop via GW2 weight 1 Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
parent 6945e6d1
...@@ -58,11 +58,14 @@ rule_pref() ...@@ -58,11 +58,14 @@ rule_pref()
} }
# Read gateway and table from a group directory # Read gateway and table from a group directory
# Sets: gw, table # Sets: gw, table, route_via
# gw - first gateway (for display and IPv4/v6 detection)
# table - routing table number
# route_via - route suffix: "via GW table T" or "table T nexthop via GW1 ... nexthop via GW2 ..."
read_group_config() read_group_config()
{ {
local dir="$1" local dir="$1"
gw="" ; table="" gw="" ; table="" ; route_via=""
if [ -f "$dir/gateway" ] ; then if [ -f "$dir/gateway" ] ; then
read -r gw < "$dir/gateway" read -r gw < "$dir/gateway"
...@@ -77,6 +80,18 @@ read_group_config() ...@@ -77,6 +80,18 @@ read_group_config()
echo "[$(basename "$dir")] No table file, skipping" >&2 echo "[$(basename "$dir")] No table file, skipping" >&2
return 1 return 1
fi fi
# Build route suffix: single vs multipath
local gw_count=$(grep -c . "$dir/gateway")
if [ "$gw_count" -le 1 ] ; then
route_via="via $gw table $table"
else
route_via="table $table"
while read -r g ; do
[ -n "$g" ] || continue
route_via="$route_via nexthop via $g weight 1"
done < "$dir/gateway"
fi
} }
# --- Manual add/del --- # --- Manual add/del ---
...@@ -105,11 +120,11 @@ if [ "$ACTION" = "add" ] || [ "$ACTION" = "del" ] ; then ...@@ -105,11 +120,11 @@ if [ "$ACTION" = "add" ] || [ "$ACTION" = "del" ] ; then
if [ "$ACTION" = "add" ] ; then if [ "$ACTION" = "add" ] ; then
if is_ipv4 "$ADD_DEL_TARGET" || is_ipv6 "$ADD_DEL_TARGET" ; then if is_ipv4 "$ADD_DEL_TARGET" || is_ipv6 "$ADD_DEL_TARGET" ; then
$ipcmd route replace "$ADD_DEL_TARGET" via "$gw" table "$table" $ipcmd route replace "$ADD_DEL_TARGET" $route_via
else else
get_ipv4_list "$ADD_DEL_TARGET" | sort -u | while read -r ip ; do get_ipv4_list "$ADD_DEL_TARGET" | sort -u | while read -r ip ; do
[ -n "$ip" ] || continue [ -n "$ip" ] || continue
$ipcmd route replace "$ip" via "$gw" table "$table" $ipcmd route replace "$ip" $route_via
done done
fi fi
else else
...@@ -221,7 +236,8 @@ process_routes() ...@@ -221,7 +236,8 @@ process_routes()
fi fi
local count=$(wc -l < "$resolved_new") local count=$(wc -l < "$resolved_new")
log "[$name]$label Loading $count routes into table $table via $gw" local gw_display=$(paste -sd, < "$gwdir/gateway")
log "[$name]$label Loading $count routes into table $table via $gw_display"
if [ -n "$SHOW" ] ; then if [ -n "$SHOW" ] ; then
echo " Would flush table $table and load $count routes" echo " Would flush table $table and load $count routes"
...@@ -233,7 +249,7 @@ process_routes() ...@@ -233,7 +249,7 @@ process_routes()
# Flush and load via batch # Flush and load via batch
$ipcmd route flush table "$table" 2>/dev/null $ipcmd route flush table "$table" 2>/dev/null
sed "s|^|route replace |; s|$| via $gw table $table|" "$resolved_new" | \ sed "s|^|route replace |; s|$| $route_via|" "$resolved_new" | \
$ipcmd -batch - 2>&1 | grep -v "^$" | head -5 $ipcmd -batch - 2>&1 | grep -v "^$" | head -5
# Ensure ip rule exists # Ensure ip rule exists
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment