#!/usr/bin/env bash # # JbTecWiz Support Centre -- generated fix script # # Fault : Bonded or teamed interfaces will not come up, or run at one link's speed # Fix : Set the hash policy, and correct the expectation # Source: https://jbtecwiz.com/support/lnx-net-bonding # # Run as : Root shell and the switch # Expect : 30 minutes # Risk : medium # Reversible : yes # # WHEN THIS IS THE RIGHT FIX # The bond is up and throughput is unchanged. # # HOW TO UNDO IT # Set xmit_hash_policy back to layer2 and reapply. # # Walks the fix one step at a time and asks before each. Steps with no # command are yours to do -- it prints those and waits. DRYRUN=1 prints # without executing; UNATTENDED=1 does not ask. # # -------------------------------------------------------------------- # NO WARRANTY - USE AT YOUR OWN RISK # # This script is provided by JbTecWiz as-is and with no warranty of any # kind, express or implied. You run it entirely at your own risk. # # JbTecWiz accepts no liability for any loss or damage arising from its # use, including but not limited to data loss, downtime, or configuration # changes that turn out to be wrong for your system. # # You are responsible for reading this script before running it, for # satisfying yourself that it suits the machine in front of you, and for # having a working backup first. Some steps cannot be undone. # -------------------------------------------------------------------- set -uo pipefail DRYRUN="${DRYRUN:-0}" UNATTENDED="${UNATTENDED:-0}" failed=0 if [ "$(id -u)" -ne 0 ]; then echo " This fix is documented as needing root. Re-run with sudo." >&2 exit 3 fi rule() { printf "\n%s\n" "$(printf '-%.0s' $(seq 1 70))"; if [ $# -gt 0 ]; then echo "$1"; fi; } prose() { echo "$1" | fold -s -w 74 | sed "s/^/ /"; } # Returns 0 when the caller should run the command, 1 when it should not. # A manual step always returns 1 -- there is nothing for the caller to run. step() { # step [command lines...] local n="$1" dotext="$2" why="$3" mode="$4"; shift 4 rule " Step $n of 5" prose "$dotext" if [ -n "$why" ]; then echo; prose "$why"; fi if [ "$mode" = "manual" ]; then echo; echo " -> Do this yourself, then press Enter to carry on." if [ "$UNATTENDED" = "0" ] && [ "$DRYRUN" = "0" ]; then read -r _; fi return 1 fi echo; printf " %s\n" "$@"; echo if [ "$DRYRUN" = "1" ]; then echo " (dry run -- not executed)"; return 1; fi if [ "$UNATTENDED" = "0" ]; then read -r -p " Run this step? [Y]es / [S]kip / [Q]uit " a case "$a" in [Qq]*) echo " Stopped at your request."; exit 0 ;; [Ss]*) echo " Skipped."; return 1 ;; esac fi return 0 } rule echo " Bonded or teamed interfaces will not come up, or run at one link'\''s speed" echo " Set the hash policy, and correct the expectation" echo echo " Risk: medium Reversible 30 minutes" echo prose 'No warranty. Use at your own risk - JbTecWiz accepts no liability. Read it before you run it, and have a backup.' rule echo if [ "$UNATTENDED" = "0" ] && [ "$DRYRUN" = "0" ]; then read -r -p " Ready? [y/N] " go case "$go" in [Yy]*) ;; *) echo " Nothing was changed."; exit 0;; esac fi step 1 'Understand the limit first: a single TCP connection always uses one physical link. A two-link bond does not make one file copy twice as fast -- it lets two copies run at full speed at the same time.' 'This is the expectation that causes most bonding complaints, and no configuration change will alter it. Aggregation distributes flows, it does not split them.' manual || true if step 2 'Check the current hash policy.' '' cmd 'cat /proc/net/bonding/bond0 | grep -i '\''hash policy'\'''; then cat /proc/net/bonding/bond0 | grep -i 'hash policy' if [ $? -ne 0 ]; then failed=$((failed+1)) echo " Step 2 failed. The rest of the fix may depend on it." >&2 fi fi if step 3 'Set layer3+4 hashing, which distributes by port as well as address and spreads multiple connections between the same two machines.' '' cmd 'sudo nmcli connection modify bond0 bond.options '\''mode=802.3ad,miimon=100,lacp_rate=fast,xmit_hash_policy=layer3+4'\''' 'sudo nmcli connection up bond0'; then sudo nmcli connection modify bond0 bond.options 'mode=802.3ad,miimon=100,lacp_rate=fast,xmit_hash_policy=layer3+4' sudo nmcli connection up bond0 if [ $? -ne 0 ]; then failed=$((failed+1)) echo " Step 3 failed. The rest of the fix may depend on it." >&2 fi fi step 4 'Set the matching hash on the switch. A mismatch is legal and simply distributes badly in one direction.' '' manual || true if step 5 'Test with several parallel streams rather than one.' '' cmd 'iperf3 -c 10.0.0.20 -P 8 -t 30'; then iperf3 -c 10.0.0.20 -P 8 -t 30 if [ $? -ne 0 ]; then failed=$((failed+1)) echo " Step 5 failed. The rest of the fix may depend on it." >&2 fi fi rule " Confirm it worked" prose 'Parallel streams together exceed a single link'\''s capacity and the per-slave counters both rise.' if [ "$DRYRUN" = "0" ]; then cat /proc/net/bonding/bond0 | grep -A3 'Slave Interface' fi rule if [ "$failed" -gt 0 ]; then echo " Finished with $failed failed step(s)." echo " Read the full write-up at https://jbtecwiz.com/support/lnx-net-bonding" else echo " Finished." fi echo prose 'To undo: Set xmit_hash_policy back to layer2 and reapply.' rule