We have a 42 mbit 4G connection (17 mbit in real), but if we exceed 40 GB per month we are kicked down to 384kbps for the rest of the month. Last month we exceeded the rate after five days.

To work around this I want to put a limit on the bandwidth, limit this huge 17 mbit wire down to something smaller.

I've found various examples, but the closest I've found is wondershaper, which applies many things I'm not interested in. I don't want smart shaping.

I just want to be able to limit download and upload speeds to fixed values, for example 2mbit down and 25kbps up.

Below is what I've come up with so far, based on wondershaper. It seems to work for downlink but not sure about uplink, and it seems it sometimes exceeds the limit - makes spikes.

I have read about tc and qdiscs and filters but I'm quite new to this, never used tc in a project before. System is Slackware 12 if that matters.

Initial questions:

A) As it works I'm looking for suggestions from you out there that master tc (which I don't) - what can be made better here, specifically the upload limiting?

B) At the bottom of the script is the download limiting filter, which drops anything coming in too fast. Will this dropping waste our data amount, like it downloads 17mbit but tc drops until it reaches 2mbit and therefore wasting 15mbit?


(Usage, to limit ppp0 to 125kb/s down and 25kb/s up I run: scriptname start ppp0 125 25)

Code:
#!/bin/bash 

# changelog
# 2014-04-22 - initial version
# 2014-05-03 - cleanup

DEV=$2

if [ "$1" = "status" ]
then
	# display status then exit
	tc -s qdisc ls dev $DEV
	tc -s class ls dev $DEV
	exit
fi

if [ "$1" = "stop" ] 
then 
	# cleanup
	tc qdisc del dev $DEV root    2> /dev/null > /dev/null
	tc qdisc del dev $DEV ingress 2> /dev/null > /dev/null
	exit
fi

if [ "$1" = "start" ] 
then 
	# convert up- and downlink from kb to kbit
	DOWNLINK=$[$3*8]
	UPLINK=$[$4*8]

	# clean existing down- and uplink qdiscs, hide errors
	tc qdisc del dev $DEV root    2> /dev/null > /dev/null
	tc qdisc del dev $DEV ingress 2> /dev/null > /dev/null

	# uplink

	# install root CBQ
	tc qdisc add dev $DEV root handle 1: cbq avpkt 1000 bandwidth 10mbit 

	# main class
	tc class add dev $DEV parent 1: classid 1:1 cbq rate ${UPLINK}kbit allot 1500 prio 5 bounded isolated 

	# filter
	tc filter add dev $DEV parent 1: protocol ip prio 18 u32 match ip dst 0.0.0.0/0 flowid 1:1

	# downlink

	# add downlink qdisc
	tc qdisc add dev $DEV handle ffff: ingress

	# filter *everything* to it (0.0.0.0/0), drop everything that's coming in too fast
	tc filter add dev $DEV parent ffff: protocol ip prio 50 u32 match ip src 0.0.0.0/0 police rate ${DOWNLINK}kbit burst 10k drop flowid :1
fi