opnsense-bufferbloat/bufferbloat.sh
2021-03-22 20:44:16 +01:00

213 lines
8.3 KiB
Bash

#!/bin/sh
# Display bandwidth for our WAN interface, measure for 10 Seconds, then it quits:
# Relevent line: Total Send Rate -> Last 10 Seconds
# Relevant line: Total receive rate -> Last 10 Seconds
#iftop -i igb0 -n -N -b -t -p -s 10
# Get DL bw last 10 seconds
# iftop -i igb0 -n -N -b -t -p -s 10 | grep "Total receive rate" | xargs echo | cut -d " " -f5
# Get DL bw last 2 seconds
# iftop -i igb0 -n -N -b -t -p -s 10 | grep "Total receive rate" | xargs echo | cut -d " " -f4
# Get the average ping to 1.1.1.1 in ms
#ping -t 10 -q 1.1.1.1 | cut -d "/" -s -f5
# Idea: If average ping is >200ms, reduce current download bandwidth by 10%
# Repeat until ping is OK or lower limit reached
# If average Ping <50ms -> Increase Bandwidth by 10% until upper limit reached
# maximum allowed ping in ms
pingMax=200
# optimal ping in ms
pingOpt=50
# maximum possible download bandwidth in Mbit/s
downloadBWMax=80
downloadBWMaxBits=$(units -o "%0.f" -t "${downloadBWMax} megabit" "bits")
# minimum allowed Download Bandwidth
downloadBWMin=5
downloadBWMinBits=$(units -o "%0.f" -t "${downloadBWMin} megabit" "bits")
# downloadPipe as in opnsense: ipfw pipe show
downloadPipe=10000
uploadPipe=10001
# maxmimum possible upload bandwidth in Mbit/s
uploadBWMax=20
uploadBWMaxBits=$(units -o "%0.f" -t "${uploadBWMax} megabit" "bits")
# minimum allowed upload Bandwidth
uploadBWMin=2
uploadBWMinBits=$(units -o "%0.f" -t "${uploadBWMin} megabit" "bits")
# private vars
avgping=1
avgDownloadBW10sInBits=1
avgUploadBW10sInBits=1
resetDownloadBandwidth() {
# resets the Download Bandwith to the maximum value
echo "Resetting download bandwith limit to $downloadBWMax MBit/s"
ipfw pipe "$downloadPipe" config bw "${downloadBWMax}Mbit"
}
resetUploadBandwidth() {
# resets the Upload Bandwith to the maximum value
echo "Resetting upload bandwith limit to $uploadBWMax MBit/s"
ipfw pipe "$uploadPipe" config bw "${uploadBWMax}Mbit"
}
decreaseDownloadBandwidth() {
# currently used Bandwidth limit in Mbit/s
currentBW=$(ipfw pipe show | grep "${downloadPipe}:" | xargs echo | cut -d " " -f2)
currentBWInBits=$(units -o "%0.f" -t "${currentBW} megabit" "bits")
echo "The current download BW limit in bits is $currentBWInBits and in Mbit/s $currentBW "
# decrease current average Bandwidth by 10%
# newBW=$(echo "$avgDownloadBW10sInBits * 0.9" | bc)
# decrease currently set Bandwidth by 10%
newBW=$(echo "$currentBWInBits * 0.9" | bc)
newBWMbit=$(units -o "%0.f" -t "${newBW} bits" "megabit")
echo "The average BW in the last 10s was $avgDownloadBW10s new BW would be $newBWMbit Mbit/s"
if [ 1 -eq "$(echo "${newBW} < ${downloadBWMinBits}" | bc)" ]
then
echo "Setting current Download Bandwidth to the minimum allowed Bandwidth $downloadBWMin"
ipfw pipe "$downloadPipe" config bw "${downloadBWMin}Mbit"
else
echo "Decreasing current avg Download Bandwidth by 10%, setting it to $newBW Bits/s"
echo "Decreasing current avg Download Bandwidth by 10%, setting it to $newBWMbit MBit/s"
ipfw pipe "$downloadPipe" config bw "${newBWMbit}Mbit"
fi
}
decreaseUploadBandwidth() {
# currently used Bandwidth limit in Mbit/s
currentBW=$(ipfw pipe show | grep "${uploadPipe}:" | xargs echo | cut -d " " -f2)
currentBWInBits=$(units -o "%0.f" -t "${currentBW} megabit" "bits")
echo "The current upload BW limit in bits is $currentBWInBits and in Mbit/s $currentBW "
# decrease current average Bandwidth by 10%
# newBW=$(echo "$avgUploadBW10sInBits * 0.9" | bc)
# decrease currently set Bandwidth by 10%
newBW=$(echo "$currentBWInBits * 0.9" | bc)
newBWMbit=$(units -o "%0.f" -t "${newBW} bits" "megabit")
echo "The average BW in the last 10s was $avgUploadBW10sInBits new BW would be $newBWMbit Mbit/s"
if [ 1 -eq "$(echo "${newBW} < ${uploadBWMinBits}" | bc)" ]
then
echo "Setting current Upload Bandwidth to the minimum allowed Bandwidth $uploadBWMin"
ipfw pipe "$uploadPipe" config bw "${uploadBWMin}Mbit"
else
echo "Decreasing current avg Upload Bandwidth by 10%, setting it to $newBW Bits/s"
echo "Decreasing current avg Upload Bandwidth by 10%, setting it to $newBWMbit MBit/s"
ipfw pipe "$uploadPipe" config bw "${newBWMbit}Mbit"
fi
}
increaseDownloadBandwidth() {
# currently used Bandwidth limit in Mbit/s
currentBW=$(ipfw pipe show | grep "${downloadPipe}:" | xargs echo | cut -d " " -f2)
currentBWInBits=$(units -o "%0.f" -t "${currentBW} megabit" "bits")
echo "The current download BW in bits is $currentBWInBits and in Mbit/s $currentBW "
# increase current average Bandwidth by 10%
# newBW=$(echo "$avgDownloadBW10sInBits * 1.1" | bc)
# increase currently set Bandwidth by 10%
newBW=$(echo "$currentBWInBits * 1.1" | bc)
newBWMbit=$(units -o "%0.f" -t "${newBW} bits" "megabit")
echo "The average BW in the last 10s was $avgDownloadBW10s new BW would be $newBWMbit Mbit/s"
if [ 1 -eq "$(echo "${newBW} > ${downloadBWMaxBits}" | bc)" ]
then
echo "Setting current Download Bandwidth to the maximum allowed Bandwidth $downloadBWMax"
ipfw pipe "$downloadPipe" config bw "${downloadBWMax}Mbit"
else
echo "Increasing current avg Download Bandwidth by 10%, setting it to $newBW Bits/s"
echo "Increasing current avg Download Bandwidth by 10%, setting it to $newBWMbit MBit/s"
ipfw pipe "$downloadPipe" config bw "${newBWMbit}Mbit"
fi
}
increaseUploadBandwidth() {
# currently used Bandwidth limit in Mbit/s
currentBW=$(ipfw pipe show | grep "${uploadPipe}:" | xargs echo | cut -d " " -f2)
currentBWInBits=$(units -o "%0.f" -t "${currentBW} megabit" "bits")
echo "The current upload BW in bits is $currentBWInBits and in Mbit/s $currentBW "
# increase current average Bandwidth by 10%
# newBW=$(echo "$avgUploadBW10sInBits * 1.1" | bc)
# increase currently set Bandwidth by 10%
newBW=$(echo "$currentBWInBits * 1.1" | bc)
newBWMbit=$(units -o "%0.f" -t "${newBW} bits" "megabit")
if [ 1 -eq "$(echo "${newBWMbit} == ${currentBW}" | bc)" ]
then
echo "Forcing increment by 1MBit"
newBWMbit=$(echo "${newBWMbit} + 1" | bc)
fi
echo "The average upload BW in the last 10s was $avgUploadBW10sInBits new BW would be $newBWMbit Mbit/s"
if [ 1 -eq "$(echo "${newBW} > ${uploadBWMaxBits}" | bc)" ]
then
echo "Setting current Upload Bandwidth to the maximum allowed Bandwidth $uploadBWMax"
ipfw pipe "$uploadPipe" config bw "${uploadBWMax}Mbit"
else
echo "Increasing current avg Upload Bandwidth by 10%, setting it to $newBW Bits/s"
echo "Increasing current avg Upload Bandwidth by 10%, setting it to $newBWMbit MBit/s"
ipfw pipe "$uploadPipe" config bw "${newBWMbit}Mbit"
fi
}
while true
do
echo "Pinging vps02 for average latency"
avgping=$(ping -t 10 -q 51.254.48.251 | cut -d "/" -s -f5)
echo "Average ping is $avgping"
#bwLast10s=$(iftop -i igb0 -n -N -b -t -p -s 10)
#avgDownloadBW10s=$(echo "$bwLast10s" | grep "Total receive rate" | xargs echo | cut -d " " -f5)
#avgUploadBW10s=$(echo "$bwLast10s" | grep "Total send rate" | xargs echo | cut -d " " -f5)
#echo "The average Download in the last 10 seconds is $avgDownloadBW10s"
#echo "The average Upload in the last 10 seconds is $avgUploadBW10s"
#avgDownloadBW10s=$(echo "$avgDownloadBW10s"| sed "s/B/ bit/g" | sed "s/Kb/ kilobit/g" | sed "s/Mb/ megabit/g" | sed "s/Gb/ gigabit/g")
#avgUploadBW10s=$(echo "$avgUploadBW10s"| sed "s/B/ bit/g" | sed "s/Kb/ kilobit/g" | sed "s/Mb/ megabit/g" | sed "s/Gb/ gigabit/g")
#echo "The average Download in the last 10 seconds is $avgDownloadBW10s"
#echo "The average Upload in the last 10 seconds is $avgUploadBW10s"
#avgDownloadBW10sInBits=$(units -o "%0.f" -t "$avgDownloadBW10s" "bits")
#avgUploadBW10sInBits=$(units -o "%0.f" -t "$avgUploadBW10s" "bits")
#echo "The average Download in BITS in the last 10 seconds is $avgDownloadBW10sInBits"
#echo "The average Upload in BITS in the last 10 seconds is $avgUploadBW10sInBits"
# if the average ping is higher than the maximum allowed ping, decrease bandwidth
if [ 1 -eq "$(echo "${avgping} > ${pingMax}" | bc)" ]
then
echo "ping is too high ${avgping}"
decreaseDownloadBandwidth
decreaseUploadBandwidth
fi
# if the average ping is below optimal, increase bandwidth
if [ 1 -eq "$(echo "${avgping} < ${pingOpt}" | bc)" ]
then
echo "ping is optimal ${avgping}"
increaseDownloadBandwidth
increaseUploadBandwidth
fi
echo "Sleeping for a minute"
sleep 5
done