1

I am trying to limit the download (ingress) rate for a certain app within a cgroup. I was able to limit the upload (egress) rate successfully by marking app's OUTPUT packets in iptables and then set a tc filter to handle that marked packets. However, when I did the same steps for ingress it didn't work.


steps I followed to limit upload:

  1. Mark OUTPUT packets by their cgroup
$ sudo iptables -I OUTPUT -t mangle -m cgroup --path '/user.slice/.../app-firefox-...scope'\
  -j MARK --set-mark 11
  1. filter by fw mark (11) on the root qdisc
$ tc qdisc add dev $IFACE root handle 1: htb default 1 
$ tc filter add dev $IFACE parent 1: protocol ip prio 1 handle 11 fw \
  action police rate 1000kbit burst 10k drop 

This limited the upload rate for firefox to 1000kbit successfully.


steps I followed trying to limit download:

  1. Mark INPUT packets by their cgroup
$ sudo iptables -I INPUT -t mangle -m cgroup --path '/user.slice/.../app-firefox-...scope'\
  -j MARK --set-mark 22
  1. filter by fw mark (22) on the ingress qdisc
$ tc qdisc add dev $IFACE ingress handle ffff:
$ tc filter add dev $IFACE parent ffff: protocol ip prio 1 handle 22 fw \ 
  action police rate 1000kbit burst 10k drop 

I am able to block app's download successfully with iptables:

$ sudo iptables -I INPUT -t mangle -m cgroup --path '/user.slice/.../app-firefox-....scope' -j DROP

So it seems like iptables is marking cgroup's input packets but for some reason, tc can't filter them or maybe the packets are being consumed before tc filter takes effect? if so, then what is the use of marking input packets?

If there is a way to block cgroup's input packets then there must be a way to limit them, right?

2
  • 1
    The mark you set in mangle/INPUT has no effect on tc, because tc ingress happens waaaay before. Check: en.wikipedia.org/wiki/Netfilter#/media/… . It's just a comment because I don't know (at least now) how to solve this problem.
    – A.B
    Commented Apr 29, 2023 at 7:48
  • 1
    I guess tc-connmark (or also tc-ctinfo) can retrieve the connmark that you'd have to save during egress. But "interfacing" tc-connmark with tc-fw doesn't appear that simple.
    – A.B
    Commented Apr 29, 2023 at 8:14

1 Answer 1

2

As per @A.B comments:

The mark you set in mangle/INPUT has no effect on tc, because tc ingress happens waaaay before. Check: en.wikipedia.org/wiki/Netfilter#/media/
...

To save the mark for the connection, use -j CONNMARK --save-mark for cgroup's outbound packets, retrieve connmark in inbound packets with tc-connmark, and finally, redirect packets to ifb to apply policer.


  1. Mark cgroup connection packets (Bidirectional):
$ sudo iptables -A OUTPUT -t mangle -m cgroup --path '/user.slice/.../app-firefox-...scope' \
    -j MARK --set-mark 0x11
$ sudo iptables -A OUTPUT -t mangle -j CONNMARK  --save-mark
  1. Create ifb interface
$ modprobe ifb
$ ip link set ifb0 up
$ tc qdisc add dev ifb0 root htb #For policing, we don't care about the qdisc type

  1. Retrieve connmark and Redirect $IFACE ingress to ifb0
$ tc qdisc add dev $IFACE ingress handle ffff:
$ tc filter add dev $IFACE parent ffff: protocol all prio 10 u32 match u32 0 0 flowid 1:1 \
    action connmark \
    action mirred egres s redirect dev ifb0
  1. Apply policer on the marked packets in ifb0 root qdisc
$ tc filter add dev ifb0 parent 1: protocol ip prio 20 handle 0x11 fw \
    action police rate 1000kbit burst 10k drop

This will limit Firefox's download rate to 1000kbit.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .