Skip to content

Commit

Permalink
Add support for kbit/s rates
Browse files Browse the repository at this point in the history
  • Loading branch information
hkbakke committed Jan 31, 2017
1 parent 905d62e commit c135e21
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 44 deletions.
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,19 @@ Run tc-gen.sh without parameters to see more details.

## Examples of common use
Shape egress to 25 mbit/s

tc-gen.sh -i eth0 -u 25
Shape egress to 5 mbit/s and ingress to 10 mbit/s using IFB-interface

tc-gen.sh -i eth0 -u 5 -d 10 -f ifb0
Shape egress to 2 mbit/s and police ingress to 20 mbit/s
tc-gen.sh -i eth0 -u 2 -d 20
Shape egress to 1500 kbit/s and police ingress to 20 mbit/s

tc-gen.sh -i eth0 -u 1500k -d 20M
Display current configuration

tc-gen.sh -i eth0
Remove configuration

tc-gen.sh -i eth0 -x

## /etc/network/interfaces examples
Expand Down
104 changes: 66 additions & 38 deletions src/tc-gen.sh
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,11 @@ tc-gen.sh -i IF_NAME [OPTIONS]
configuration on the interface is displayed.
OPTIONS
-u UP_RATE_MBITS
-d DOWN_RATE_MBITS
Valid units for rates are k (kbit/s) and M (Mbit/s). If no unit are given
with the rate Mbit/s is used.
-u UP_RATE
-d DOWN_RATE
-f IFB_IF_NAME
If ingress shaping should be used instead of policing define a valid
ifb interface. Normally ifb0 and ifb1 are available if nothing is
Expand All @@ -44,18 +47,18 @@ OPTIONS
class has a priority of 4. If this is not set all the bandwith is
given to the default class which is sufficient for most use cases.
These classes are only used for egress shaping.
If ceil is not set it will default to UP_RATE_MBITS. If prio is not
If ceil is not set it will default to UP_RATE. If prio is not
set, it will default to the same priority as the default class.
Example:
-c "107:50::,109:30:70:2"
-c "107:50::,109:1400k:7M:2"
The example above creates a leaf class which get all egress traffic
with fw mark 107, shaped to a rate of 50 mbit/s with no ceiling and
priority, which means that it may use all the available bandwith if
available in the root class and has the same priority as the default
class. The next leaf class has a fw mark of 109, a rate of 30 mbit/s,
a ceil of 70 mbit/s and a priority of 2.
class. The next leaf class has a fw mark of 109, a rate of 1400 kbit/s,
a ceil of 7 mbit/s and a priority of 2.
-x
Clear all traffic control config on interface.
-V
Expand All @@ -68,8 +71,8 @@ EXAMPLES OF COMMON USE
Shape egress to 5 mbit/s and ingress to 10 mbit/s using IFB-interface
tc-gen.sh -i eth0 -u 5 -d 10 -f ifb0
Shape egress to 2 mbit/s and police ingress to 20 mbit/s
tc-gen.sh -i eth0 -u 2 -d 20
Shape egress to 1500 kbit/s and police ingress to 20 mbit/s
tc-gen.sh -i eth0 -u 1500k -d 20M
Display current configuration
tc-gen.sh -i eth0
Expand All @@ -82,16 +85,16 @@ EXAMPLES OF COMMON USE
policing with good results.
EGRESS TRAFFIC SHAPING
UP_RATE_MBITS uses HTB and fq_codel to efficiently shape upload
UP_RATE uses HTB and fq_codel to efficiently shape upload
traffic.
INGRESS TRAFFIC SHAPING
If DOWN_RATE_MBITS and IFB_IF_NAME is set, ingress traffic shaping using
If DOWN_RATE and IFB_IF_NAME is set, ingress traffic shaping using
an IFB-interface, HTB and fq_codel, is used for incoming traffic.
INGRESS TRAFFIC POLICING
BURST_SIZE is only used for ingress policing.
Ingress policing is used if IFB_IF_NAME is not defined and DOWN_RATE_MBITS
Ingress policing is used if IFB_IF_NAME is not defined and DOWN_RATE
is set. A good starting point for the burst size is
phy_line_rate_in_bps * burst_time_seconds / 8 = burst_size_in_bytes
Expand Down Expand Up @@ -126,22 +129,22 @@ print_version () {
}

get_htb_quantum () {
# Takes input rate in mbit/s as parameter
# Takes input rate in kbit/s as parameter
local RATE=$1
local QUANTUM=8000

if [[ ${RATE} -lt 40 ]]; then
if [[ ${RATE} -lt 40000 ]]; then
QUANTUM=1514
fi

echo ${QUANTUM}
}

get_target () {
# Takes input rate in mbit/s and mtu as parameter
# Takes input rate in kbit/s and mtu as parameter
local RATE=$1
local MTU=$2
local KBYTES=$(( ${RATE} * 1000 / 8 ))
local KBYTES=$(( ${RATE} / 8 ))
local MS=$(( ${MTU} / ${KBYTES} ))
local TARGET=5

Expand All @@ -153,19 +156,19 @@ get_target () {
}

get_fq_codel_quantum () {
# Takes input rate in mbit/s as parameter
# Takes input rate in kbit/s as parameter
local RATE=$1

if [[ ${RATE} -lt 100 ]]; then
if [[ ${RATE} -lt 100000 ]]; then
echo "quantum 300"
fi
}

get_ecn () {
# Takes input rate in mbit/s as parameter
# Takes input rate in kbit/s as parameter
local RATE=$1

if [[ ${RATE} -ge 4 ]]; then
if [[ ${RATE} -ge 4000 ]]; then
echo "ecn"
else
echo "noecn"
Expand All @@ -178,26 +181,26 @@ get_mtu () {
}

get_tx_offloads () {
# Takes rate in mbit/s as parameter
# Takes rate in kbit/s as parameter
local RATE=$1

if [[ ${RATE} -lt 40 ]]; then
if [[ ${RATE} -lt 40000 ]]; then
echo "tso off gso off"
else
echo "tso on gso on"
fi
}

get_limit () {
# Takes rate in mbit/s as parameter
# Takes rate in kbit/s as parameter
local RATE=$1
local LIMIT=10000

if [[ ${RATE} -le 10 ]]; then
if [[ ${RATE} -le 10000 ]]; then
LIMIT=600
elif [[ ${RATE} -le 100 ]]; then
elif [[ ${RATE} -le 100000 ]]; then
LIMIT=800
elif [[ ${RATE} -le 1000 ]]; then
elif [[ ${RATE} -le 1000000 ]]; then
LIMIT=1200
fi

Expand Down Expand Up @@ -240,7 +243,7 @@ apply_egress_shaping () {

# Set the overall shaped rate of the interface
${TC} class add dev ${IF_NAME} parent 1: classid 1:1 htb \
rate ${UP_RATE}mbit \
rate ${UP_RATE}kbit \
quantum $(get_htb_quantum ${UP_RATE})

local DEFAULT_RATE=${UP_RATE}
Expand All @@ -252,8 +255,8 @@ apply_egress_shaping () {
for CLASS in ${CLASSES[@]}; do
local CONFIG=( $(echo "${CLASS}" | tr ':' ' ') )
local FWMARK=${CONFIG[0]}
local CLASS_RATE=${CONFIG[1]}
local CEIL_RATE=${CONFIG[2]}
local CLASS_RATE=$(convert_rate ${CONFIG[1]})
local CEIL_RATE=$(convert_rate ${CONFIG[2]})
local PRIO=${CONFIG[3]}
local CLASS_ID=${FWMARK}

Expand All @@ -278,7 +281,7 @@ apply_egress_shaping () {
fi

${TC} class add dev ${IF_NAME} parent 1:1 classid 1:${CLASS_ID} htb \
rate ${CLASS_RATE}mbit ceil ${CEIL_RATE}mbit \
rate ${CLASS_RATE}kbit ceil ${CEIL_RATE}kbit \
prio ${PRIO} quantum $(get_htb_quantum ${CLASS_RATE})

# Should the class rate or ceil be used for the calculations here??
Expand All @@ -297,8 +300,9 @@ apply_egress_shaping () {
fi

# Create class for the default priority
${TC} class add dev ${IF_NAME} parent 1:1 classid 1:99 htb rate ${DEFAULT_RATE}mbit \
ceil ${UP_RATE}mbit prio ${DEFAULT_PRIO} \
${TC} class add dev ${IF_NAME} parent 1:1 classid 1:99 htb \
rate ${DEFAULT_RATE}kbit \
ceil ${UP_RATE}kbit prio ${DEFAULT_PRIO} \
quantum $(get_htb_quantum ${UP_RATE})

# Set qdisc to fq_codel
Expand All @@ -321,11 +325,13 @@ apply_ingress_shaping () {
${TC} qdisc add dev ${IFB_IF_NAME} root handle 1: htb default 99

# Set the overall shaped rate of the interface
${TC} class add dev ${IFB_IF_NAME} parent 1: classid 1:1 htb rate ${DOWN_RATE}mbit
${TC} class add dev ${IFB_IF_NAME} parent 1: classid 1:1 htb \
rate ${DOWN_RATE}kbit

# Create class for the default priority
${TC} class add dev ${IFB_IF_NAME} parent 1:1 classid 1:99 htb rate ${DOWN_RATE}mbit \
ceil ${DOWN_RATE}mbit prio 0 \
${TC} class add dev ${IFB_IF_NAME} parent 1:1 classid 1:99 htb \
rate ${DOWN_RATE}kbit \
ceil ${DOWN_RATE}kbit prio 0 \
quantum $(get_htb_quantum ${DOWN_RATE})

# Set qdisc to fq_codel. Enabling ECN is recommended for ingress
Expand Down Expand Up @@ -362,23 +368,45 @@ apply_ingress_policing () {
# filters earlier in the chain.
${TC} filter add dev ${IF_NAME} parent ffff: protocol all prio 99 u32 \
match u32 0 0 \
police rate ${DOWN_RATE}mbit \
police rate ${DOWN_RATE}kbit \
burst ${BURST_SIZE} \
mtu ${MTU} drop flowid :1
}

convert_rate () {
# Takes command line input rate as argument.
# Converts rates to kbit/s.
local IN_RATE=$1
local RATE=0
local DEFAULT_REGEX="^([0-9]+)$"
local KBIT_REGEX="^([0-9]+)k$"
local MBIT_REGEX="^([0-9]+)M$"

if [[ ${IN_RATE} =~ ${MBIT_REGEX} ]]; then
RATE=$(( ${BASH_REMATCH[1]} * 1000 ))
elif [[ ${IN_RATE} =~ ${KBIT_REGEX} ]]; then
RATE=${BASH_REMATCH[1]}
elif [[ ${IN_RATE} =~ ${DEFAULT_REGEX} ]]; then
RATE=$(( ${BASH_REMATCH[1]} * 1000 ))
else
echo "${IN_RATE} is not a valid rate"
false
fi

echo ${RATE}
}


# All rates should be given in mbit/s
while getopts ":i:u:d:b:f:q:c:xV" OPT; do
case ${OPT} in
i)
IF_NAME="${OPTARG}"
;;
u)
UP_RATE="${OPTARG}"
UP_RATE=$(convert_rate ${OPTARG})
;;
d)
DOWN_RATE="${OPTARG}"
DOWN_RATE=$(convert_rate ${OPTARG})
;;
b)
BURST_SIZE="${OPTARG}"
Expand Down

0 comments on commit c135e21

Please sign in to comment.