Bandwidth Limiter

Bandwidth limitation with gnome menu entry.

Installing script

Create script /usr/local/bin/limit_bandwidth.sh

#!/bin/bash

set -u

error() {
        (( $# == 1 )) && $ZENITY --error --title "Error" --text="$1"
        exit 1
}

typeset -r PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
typeset -r WHICH=/usr/bin/which
typeset -r ZENITY=$($WHICH zenity)
[[ -x $ZENITY ]] || error "Problem with zenity command, exiting."
typeset -r TC=$($WHICH tc)
[[ -x $TC ]] || error "Problem with tc command, exiting."
typeset -r LSMOD=$($WHICH lsmod)
[[ -x $LSMOD ]] || error "Problem with lsmod command, exiting."
typeset -r MODPROBE=$($WHICH modprobe)
[[ -x $MODPROBE ]] || error "Problem with modprobe command, exiting."

###
# functions

check_device_availability() {
        if (ls /sys/class/net/ | grep -q "eth0" && ls /sys/class/net/ | grep -q "wlan0")
        then
                local eth_dev=$(ls /sys/class/net/ | grep "eth0")
                local wlan_dev=$(ls /sys/class/net/ | grep "wlan0")
                DEVICE=$($ZENITY --list \
                                  --title "Choose network device" \
                                  --text "Please select which device to limit" \
                                  --radiolist --column "Pick" \
                                  --column "Device" \
                                      FALSE "$eth_dev" \
                                      FALSE "$wlan_dev")
        elif (ls /sys/class/net/ | grep -q "eth0")
        then
                DEVICE=$(ls /sys/class/net/ | grep "eth0")
        elif (ls /sys/class/net/ | grep -q "wlan0")
        then
                DEVICE=$(ls /sys/class/net/ | grep "wlan0")
        else
                error "No network device available."
        fi
}

check_eth() {
        local DEVICE=$1
        cat "/sys/class/net/$DEVICE/operstate" | fgrep -q "up" || \
              error "Ethernet device $DEVICE is down."
}

choose_bandwidth_type() {
        local TYPE=$($ZENITY --height=250 --list --title "Choose $DEVICE connection type" \
                      --text "Please select which bandwidth to emulate"
                      --radiolist \
                      --column "Pick" \
                      --column "Type" \
                      --column "Bandwidth"  \
                          FALSE "3G" 1000kbit \
                          FALSE "4G" 10000kbit \
                          FALSE "modem 56k" 56kbit \
                          FALSE "DSL" 2mbit)

        case $TYPE in
                "3G")
                        BANDWIDTH="1000kbit"
                        LATENCY="200ms"
                        PACKETLOSS="0%"
                        EMULATION="3G"
                ;;
                "4G")
                        BANDWIDTH="10000kbit"
                        LATENCY="100ms"
                        PACKETLOSS="0%"
                        EMULATION="4G"
                ;;
                "modem 56k")
                        BANDWIDTH="56kbit"
                        LATENCY="120ms"
                        PACKETLOSS="0%"
                        EMULATION="modem 56k"
                ;;
                "DSL")
                        BANDWIDTH="2mbit"
                        LATENCY="40ms"
                        PACKETLOSS="0%"
                        EMULATION="DSL"
                ;;
                *)
                        error "Process aborted"
                ;;
        esac
}

slow_connection() {
        local DEVICE=$1
        local BANDWIDTH=$2
        local LATENCY=$3
        local PACKETLOSS=$4
        if      $TC qdisc show dev $DEVICE | fgrep -q "qdisc htb 1: root"; then
                local VERB=change
        else
                local VERB=add
                $TC qdisc $VERB dev $DEVICE root handle 1: htb default 12
        fi
        if ! $LSMOD | fgrep -q "sch_netem"; then
                $MODPROBE sch_netem
        fi
        $TC class $VERB dev $DEVICE parent 1:1 classid 1:12 htb rate $BANDWIDTH \
             ceil $BANDWIDTH  &&
        $TC qdisc $VERB dev $DEVICE parent 1:12 netem delay $LATENCY loss $PACKETLOSS
        RETCODE=$?
}

clear_connection() {
        local DEVICE=$1
        $TC qdisc del dev $DEVICE root
        if $LSMOD | fgrep -q "sch_netem"; then
                $MODPROBE -r sch_netem
        fi
        RETCODE=$?
}

###
# main

check_device_availability

check_eth $DEVICE

choose_bandwidth_type

slow_connection $DEVICE $BANDWIDTH $LATENCY $PACKETLOSS

CLEAR=$($ZENITY --info \
                  --title "$EMULATION emulation" \
                  --text "Interface: $DEVICE\nBandwidth: $BANDWIDTH\nLatency: \
                      $LATENCY\n\nStop emulation?")

(( $? == 0 )) && clear_connection $DEVICE

$ZENITY --info --title="End" --text="Ethernet bandwidth limitation is cleared."

(( $RETCODE == 0 )) && exit 0

# EOF

Creating sudoers file

Create sudoers file /etc/sudoers/limit_bandwidth

<user>  ALL = (ALL) NOPASSWD: /usr/local/bin/limit_bandwidth.sh

Creating Gnome file

Create desktop file /home/$USER/.local/share/applications/limit_bandwidth.desktop

[Desktop Entry]
Version=1.0
Name=[NOC] Limit Network Bandwidth
GenericName=[NOC] Limit Network Bandwidth
X-GNOME-FullName=[NOC] Limit Network Bandwidth
Comment=[NOC] Limit Network Bandwidth
Exec=/usr/bin/sudo /usr/local/bin/limit_bandwidth.sh
Icon=/usr/share/icons/gnome/32x32/status/network-transmit-receive.png
Terminal=false
Type=Application
Categories=Others;