The below is taken from internal documents with a few things removed.
You can further optimize that by using the address-list option on the Hotspot User Profile - users are automatically added to that address-list on login and are removed again on logout. There's also a corresponding RADIUS attribute. That would allow you to mark packets not only on interface but also based on address-list so you could run different policies (and rate limits) on the same interface.
Rate Limiting (Users and Networks)
Note: This is a very simplified view of QoS on RouterOS, a full description can be found at
http://wiki.mikrotik.com/wiki/Queue,
http://wiki.mikrotik.com/wiki/Packet_Flow in detail describes how packets flow through the router.
Hotspot users are usually rate limited via dynamically created simple queues. When a user logs in, a simple queue with the user's IP address as a target is created. Upload and download limits are taken from the user profile applied during login. There is no built in way to define a bandwidth pool to be shared between users, each rate limit is user specific. This works fine for per user products such as [retracted] and no further configuration is required.
When a network as a whole should be rate limited, [retracted], manual QoS must be configured. In addition to rate limiting a pool of network connections as a whole this can also be extended to create a rate limit not to be exceeded by a pool of connections with each connection specifically rate limited by a smaller queue. This is achieved via queue trees. Queue trees are hierarchical and at the bottom of the tree inherit from global-in and global-out, or from specific interfaces. Packets are then shifted further down the tree to a specific bucket by merit of packet marks. Queue trees attached directly to global-in and global-out get hit before simple queues are evaluated, so if a packet is eligible for rate limiting via a simple queue and a global-in/out inherited queue tree the queue tree rate limit will take. This enables us to combine Hotspots and their redirects and user authentication with global rate limits.
First, packets must be marked. In this example, a packet mark of 'hotspot1-up' is applied to all packets coming into the router through the hotspot1 interface. A packet mark of 'hotspot1-down' is applied to all packets leaving the router through the hotspot1 interface.
/ip firewall mangle
add chain=prerouting action=mark-packet in-interface=hotspot1 new-packet-mark=hotspot1-up passthrough=yes
add chain=postrouting action=mark-packet out-interface=hotspot1 new-packet-mark=hotspot1-down passthrough=yes
Flags: X - disabled, I - invalid, D - dynamic
0 chain=prerouting action=mark-packet
new-packet-mark=hotspot1-up passthrough=yes
in-interface=hotspot1
1 chain=postrouting action=mark-packet
new-packet-mark=hotspot1-down passthrough=yes
out-interface=hotspot1
Then two queues - one for upload and one for download - are created based on the packet marks. In this example a total of 5mbps downstream and 2mbps upstream are configured.
/queue tree
add name=hotspot1-down parent=global-out packet-mark=hotspot1-down max-limit=5000000 queue=default
add name=hotspot1-up parent=global-in packet-mark=hotspot1-up max-limit=2000000 queue=default
Flags: X - disabled, I - invalid
0 name="hotspot1-down" parent=global-out
packet-mark=hotspot1-down limit-at=0 queue=default
priority=8 max-limit=5M burst-limit=0
burst-threshold=0 burst-time=0s
1 name="hotspot1-up" parent=global-in
packet-mark=hotspot1-up limit-at=0 queue=default
priority=8 max-limit=2M burst-limit=0
burst-threshold=0 burst-time=0s
If the 5mbps/2mbps global rate limit is to be applied together with each user not exceeding 512kbps down and 256kbps down, PCQ can be used to dynamically create queues based on the source and destination addresses. For upstream traffic the source address is used as an identifier as it corresponds to the not yet NAT'd client IP address. For downstream traffic the destination address is used as an identifier as it corresponds to the client IP address after client NAT to the router public IP has been reversed (refer to above linked packet flow diagram for details).
First, PCQ queue types are created:
/queue type
add name=hotspot1-down-per-user kind=pcq pcq-rate=512000 pcq-classifier=dst-address
add name=hotspot1-up-per-user kind=pcq pcq-rate=256000 pcq-classifier=src-address
0 name="default" kind=pfifo pfifo-limit=50
1 name="ethernet-default" kind=pfifo pfifo-limit=50
2 name="wireless-default" kind=sfq sfq-perturb=5
sfq-allot=1514
3 name="synchronous-default" kind=red red-limit=60
red-min-threshold=10 red-max-threshold=50 red-burst=20
red-avg-packet=1000
4 name="hotspot-default" kind=sfq sfq-perturb=5
sfq-allot=1514
5 name="hotspot1-up-per-user" kind=pcq pcq-rate=256000
pcq-limit=50 pcq-classifier=src-address
pcq-total-limit=2000
6 name="hotspot1-down-per-user" kind=pcq pcq-rate=512000
pcq-limit=50 pcq-classifier=dst-address
pcq-total-limit=2000
7 name="default-small" kind=pfifo pfifo-limit=10
Then the PCQ queue types are applied to the queue trees - now a dynamic queue will be created for each user, but all those dynamic queues combined may not exceeded the queue tree limit of 5mbps/2mbps:
/queue tree
set [find name=hotspot1-down] queue=hotspot1-down-per-user
set [find name=hotspot1-up] queue=hotspot1-up-per-user
Flags: X - disabled, I - invalid
0 name="hotspot1-down" parent=global-out
packet-mark=hotspot1-down limit-at=0
queue=hotspot1-down-per-user priority=8 max-limit=5M
burst-limit=0 burst-threshold=0 burst-time=0s
1 name="hotspot1-up" parent=global-in
packet-mark=hotspot1-up limit-at=0
queue=hotspot1-up-per-user priority=8
max-limit=3m burst-limit=0 burst-threshold=0
burst-time=0s