Limit bandwith per IP/MAC with OpenWrt (Luci)?

If you are experimenting on a single AP in a single location for an indefinite time... Bravo, great spirit there and I wish you success. I think many many fellow mates here have the knowledge to assist you!

If you are looking for scaleability (multiple APs, different locations), offer a paid hotspot or do not hear any complaints from users; I suggest you start thinking about freeradius or leave all the work to cloudbased hotspot operators for a fee. Should anything happen, you can always blame it on the paid party. : )

Not sure what you are running, but if it is not to be had in a repository it would appear to be pretty straight forward from looking at the commit. Check the makefile for dependencies and ensure those are installed on your device. Other than that there are just /etc/init.d/script and /etc/config/conf files. Not a clue if there are any version requirements on those dependencies though.

Thanx for your suggestion regarding freeradius; usually I already use freeradius together with coova-chilli and intercepting squid. But in certain scenarios, this is an overkill to (also) implement traffic limits per IP.
Last not least: Cloud based hotspot operators lack some enhanced features. Off-the-Shelf-Software usually lacks top-notch features.

Have squid tag YouTube packets with DSCP CS1, WMM may do the rest. Would be interesting to see. Also if APs are separate from router you can put layer cake on the LAN side Ethernet interface of the router.

I can do traffic limits (also) using delay pools, or using coova/radius. But for special scenario I just need the limits, in simplest setup. So iptables probably will be the method of choice: KISS.
As YT is only one example for a bandwidth hog.

But I will keep your proposal regarding DSCP CS1 in mind. Good idea ...

You can use DSCP CS1 from iptables. Dnsmasq can fill an ipset based on DNS lookups, then you tag packets from or to those ipsets

Im running OpenWrt 18.06.2 r7676-cddd7b4c77 / LuCI openwrt-18.06 branch (git-19.020.41695-6f6641d) on my raspberry, how can I update it with the commit with traffcishaper?
Have no clue on how to do it. Thanks

DNSMASQ and ipset is an alternative, but again, there are other hogs besides YT. Which would be required to be identified, first. Using delaypools or coova/radius are a general solution, without additional packages to install, as required anyway.
Similar to iptables+hashlimits :slight_smile:

Use Hashlimit to set a conntrack mark on any stream that goes over N Mbps with CS1. Will find all those bursty hogs in one, then tag all of them with CS1

If you have the controller (coova-chilli) running separately on a decent machine and leaving the wireless APs to just doing what they do best, I can't see where the overkill is. Maybe you can shed some light so I can also improve my network better. :stuck_out_tongue_winking_eye:

It would be great if you can share typically the balllpart numbers APs per location involved, the average online users per hourly basis and average gateway bandwidth. I really do hope to do something if coovachilli or the operators cannot handle it one day.

From the makefile:

  24    DEPENDS:=+tc +kmod-sched-core +kmod-sched-connmark +kmod-ifb +iptables +kmod-sched-cake +iptables-mod-conntrack-extra

so using opkg list-installed check you have each of those(you will already have some), install any that might be missing. When you have all the requisite dependencies copy and paste into new file /etc/config/trafficshaper, and copy and paste into new file /etc/init.d/trafficshaper, then:

/etc/init.d/trafficshaper enable
/etc/init.d/trafficshaper start

but again, this was pushed to master and I am not sure if there is any version requirements on the above dependencies.

with the obvious proviso to make that config relevant to your use-case.

@reinerotto

I think cake with per-ip fairness would work well, but here's another approach written on my phone untested but should be debuggable :sunglasses: @hisham2630 might be interested too.

Assumes eth0 is the interface to a LAN full of APs etc and your only goal is share the bandwidth fairly among dst IPs

In fact you really want hfsc shaping on top of this... But you can see examples elsewhere.


tc qdisc replace dev eth0 handle 1 root drr 

for i in {1..11} do
  tc class add dev eth0 parent 1: classid 1:$(print %x $i) drr
  tc qdisc add dev eth0 parent 1:$(print %x $i) handle "a$(print %x $i)":1 fq_codel 
done

tc filter add dev eth0 parent 1: flow hash key dst perturb 3 divisor 11
1 Like

Here's some slightly debugged code that actually runs and installs the appropriate qdiscs, as example.

It sets up an HFSC qdisc with a single link-share class with an upper limit speed to set the egress speed to a given value (ie. like the download speed of your WAN). Then it puts a drr qdisc underneath that one HFSC class, and it puts 11 subclasses in the DRR qdisc. Then it sets up fq_codel underneath each drr class.

It creates two filters attached to the DRR that causes it to select a DRR class on the basis of the dst address (one filter for ip and one for ipv6).

What this does is it assigns all traffic for a given IP to a consistent DRR class, and then that class shares equally across all the flows in use by that IP.

Of course, with only 11 classes it may assign more than one IP to a given class, so it perturbs the hash function every 3 seconds to spread this around. I choose 11 because it's a prime number. It's really not a major problem to have hash collisions as long as you're perturbing.

#!/bin/bash -x


tc qdisc replace dev eth0 handle 1 root hfsc default 1

tc class change dev eth0 parent 1: classid 1:1 hfsc ls m2 10000kbit ul m2 10000kbit

tc qdisc add dev eth0 parent 1:1 handle 2: drr 

for i in {0..10}; do
  tc class add dev eth0 parent 2: classid 2:$(printf %x $i) drr
  tc qdisc add dev eth0 parent 2:$(printf %x $i) handle "a"$(printf %x $i):1 fq_codel 
done

tc filter add dev eth0 parent 2: handle 1 protocol ip prio 1 flow hash keys dst perturb 3 divisor 11
tc filter add dev eth0 parent 2: handle 2 protocol ipv6 prio 2 flow hash keys dst perturb 3 divisor 11

To clarify: For a scenario, which does NOT need squid caching or coovas CP functionality, only using squid or coova for bandwidth limiting I consider it "overkill".
For such a scenario I need a simple, possibly not exact, bandwidth limitation per client IP.

Thank you very much for your efforts. However, because until now I have no experience regarding these special tools for bandwidth management, I am hesitating to dig into these tools for the required rather simple functionality right now. I will give iptables hashlimit a try, first. As it looks most simple to use to me, and sufficiently precise, as an exact limit is not required. In case, this method is not good enough, I will have to learn the "Black Magic" of tc etc. and come back to your research.
Again, your help is greatly appreciated.

Could you try to use cake's per-IP-fairness mode as well. This should be easy/quick to test and will give valuable feed-back from the field for cake's developers. I have a hunch that per-IP-fairness and air-time fairness should pretty much lead to a good-enough solution that requires no maintenance :wink:

Will try.
Actually, I force "airtime fairness for dummies" simply by allowing only lower WiFi speeds.
KISS :slight_smile:

I am not sure this is going to work well. Really try the airtime fairness approach, as that aims at sharing the contended resource.Wifi by default aims at sharing bandwidth, which means slow stations drag down everybody and get a disproportionate share of transmit opportunities. That means one user with a 802.11b device is able slow everybody down...

Thanks I will try this, I will let you know

one user with a 802.11b device is able slow everybody down...<
Yes.
But I exclude 11b, and only allow lower 11g-speeds. So the Wifi channel not to be saturated by YT-HD-viewers.
I do not dispute better solutions to be available, but this one works for years already.
Manchmal sind auch althergebrachte Methoden gut.