I'm using following rules in Mangle:
0 ;;; ssl chain=prerouting action=mark-connection new-connection-mark=ssl passthrough=yes protocol=tcp port=22,223,226 1 chain=prerouting action=mark-packet new-packet-mark=ssl passthrough=yes connection-mark=ssl 2 ;;; www chain=prerouting action=mark-connection new-connection-mark=www passthrough=yes protocol=tcp port=80,806,803,443,4433,4436,8080,8100-8199 3 chain=prerouting action=mark-connection new-connection-mark=www passthrough=yes protocol=udp port=53 log=no log-prefix="" 4 chain=prerouting action=mark-packet new-packet-mark=www passthrough=yes connection-mark=www log=no log-prefix="" 5 ;;; pub chain=prerouting action=mark-connection new-connection-mark=pub passthrough=yes in-interface=wlan2-public log=no log-prefix="" 6 chain=prerouting action=mark-connection new-connection-mark=pub passthrough=yes src-address=192.168.3.0/24 7 chain=prerouting action=mark-connection new-connection-mark=pub passthrough=yes dst-address=192.168.3.0/24 8 chain=prerouting action=mark-packet new-packet-mark=pub passthrough=yes connection-mark=pub log=no log-prefix="" 9 ;;; i2p chain=prerouting action=mark-connection new-connection-mark=i2p passthrough=yes protocol=tcp port=23998,29733,29736 10 chain=prerouting action=mark-connection new-connection-mark=i2p passthrough=yes protocol=udp port=23998,29733,29736 11 chain=prerouting action=mark-packet new-packet-mark=i2p-in passthrough=yes dst-address=192.168.0.0/16 connection-mark=i2p 12 chain=prerouting action=mark-packet new-packet-mark=i2p-out passthrough=yes dst-address=!192.168.0.0/16 connection-mark=i2p 13 chain=prerouting action=mark-packet new-packet-mark=nuc-out passthrough=yes src-address=192.168.2.4 dst-address=!192.168.0.0/16 packet-mark=no-mark
It's difficult to mangle i2p because it's using random, non-ephemeral ports to communicate that's why there's "catch all" equivalent (#13). I have highly asymmetric internet (60/6) and i2p is more or less symmetric so it doesn't really matter that there's no incoming catch all rule as it's limited by outgoing before reaching internet capacity.
And Queue tree:
0 name="ssl" parent=global packet-mark=ssl limit-at=10M queue=default-small priority=1 max-limit=4096M burst-limit=0 burst-threshold=0 burst-time=0s 1 name="spam" parent=global packet-mark=no-mark limit-at=512k queue=default-huge priority=4 max-limit=1024M burst-limit=0 burst-threshold=0 burst-time=0s 2 name="pub" parent=global packet-mark=pub limit-at=512k queue=pcq-download-default priority=3 max-limit=20M burst-limit=40M burst-threshold=16M burst-time=20s 3 name="low-out" parent=global packet-mark=i2p-out,nuc-out limit-at=0 queue=default-huge priority=5 max-limit=3500k burst-limit=4M burst-threshold=3M burst-time=6s 4 name="www" parent=global packet-mark=www limit-at=1024k queue=default-huge priority=2 max-limit=1024M burst-limit=0 burst-threshold=0 burst-time=0s 5 name="low-in" parent=global packet-mark=i2p-in limit-at=0 queue=default-huge priority=5 max-limit=0 burst-limit=0 burst-threshold=0 burst-time=0s
I'd like to set i2p limit to 5M because that's a bit below max upload of my internet but 4M already makes network barely usable, 3.5M is highly disturbing but at least friends don't report www timeouts. However still they say it takes up to 20 seconds to load website whereas without i2p it's less than 2 sec. It's especially important to me as I'll be applying for a job and there's my portfolio on my server so if employer would try to enter my website and he'd receive timeout it'd be terrible failure. People even stopped using my public wifi recently probably because it's barely usable.
It makes me think that maybe i screw something up in setup? www and i2p router both are running on 192.168.2.4 server.
Side note - I know this QoS may seem funny because of "spam" being everything apart from ssl,i2p,www and public but actually I'm tunneling like 90% of traffic - VNC, NFS and basically all files transfer, Xpra, X server, pulseaudio, sometimes even http through ssh and as I can't really differ ssh, all this traffic is just top priority.