PPPoE Server, double QoS

Hi Guys,

I’m looking to setup double QoS on a Tik PPPoE server… Essentially, I want the following (let’s take a 4Mbps, 2:1 service example):

  • Each user connected, get’s a simple queue rate-limiting initial service to 4Mbps. Easily achieved by PPP itself.
  • Now, I want to implement contention ratios. 4Mbps at say a 2:1 ratio
/queue tree
add name="Contention Groups" parent=global queue=ethernet-default
add name="4Mbps Broadband" limit-at=8M max-limit=8M packet-mark=INET-004 parent="Contention Groups" priority=4 queue=INET-004
add name="8Mbps Broadband" limit-at=8M max-limit=8M packet-mark=INET-008 parent="Contention Groups" priority=4 queue=INET-008
add name="10Mbps Broadband" limit-at=8M max-limit=8M packet-mark=INET-010 parent="Contention Groups" priority=4 queue=INET-010

/ip firewall mangle
add action=jump chain=forward comment="Mark Outgoing Traffic (towards customer)" dst-address=x.x.x.0/23 jump-target=QOS-INET src-address=0.0.0.0/0
add action=mark-packet chain=QOS-INET comment=user1 dst-address=x.x.x.1 new-packet-mark=INET-004 passthrough=no
add action=mark-packet chain=QOS-INET comment=user2 dst-address=x.x.x.2 new-packet-mark=INET-004 passthrough=no
add action=mark-packet chain=QOS-INET comment=user3 dst-address=x.x.x.3 new-packet-mark=INET-004 passthrough=no
add action=mark-packet chain=QOS-INET comment=user4 dst-address=x.x.x.4 new-packet-mark=INET-004 passthrough=no

From the above, each user will get their 4Mbps maximum from the simple queue, and the GROUP of 4Mbps users will use PCQ to equality devide 8Mbps of transit bandwidth between the 4 users - thus, giving me my 2:1 ratio and the ratio only comes into affect when 2 or more users are maxing out their 4Mbps service. The 8Mbps limits are increased in increments of 4Mbps for each 2nd user being added to the pool - simple math, simple stuff… That’s all good and well, works absolutely perfect and precisely what I want.

What I want to do now, is to create 8 additional sub queues in each service, so that we effectively have in the queue tree:

  • Contention Groups
    • 4Mbps Broadband
      • Prio 1
      • Prio 2
      • Prio 3
      • Prio 4
      • Prio 5
      • Prio 6
      • Prio 7
      • Prio 8
    • 8Mbps Broadband
      • Prio 1
      • Prio 2
      • Prio 3
      • Prio 4
      • Prio 5
      • Prio 6
      • Prio 7
      • Prio 8
    • 10Mbps Broadband
      • Prio 1
      • Prio 2
      • Prio 3
      • Prio 4
      • Prio 5
      • Prio 6
      • Prio 7
      • Prio 8

And the idea now is to mark certain traffic types, to certain priorities. For example, let’s say ICMP = Priority 1

I’ve tried matching in pre|post-routing, and I can get the packets to match.

/ip firewall mangle
add action=add chain=prerouting protocol=icmp new-packet-mark=Prio1 passthrough=no

What I can’t get, is that the queue tree ONLY looks at packets for the specific service. For example, given the above queue tree, Prio1 will match on the 4Mbps service, even though the subscriber is actually a 8Mbps subscriber. Do I really need to match all 8 priorities on all service levels? For example:

add action=mark-packet chain=QOS-INET comment=user1 dst-address=x.x.x.1 new-packet-mark=INET-004 passthrough=yes
add action=mark-packet chain=QOS-INET comment=user1 dst-address=x.x.x.1 protocol=icmp new-packet-mark=INET-004-Prio1 passthrough=no
add action=mark-packet chain=QOS-INET comment=user2 dst-address=x.x.x.2 new-packet-mark=INET-008 passthrough=yes
add action=mark-packet chain=QOS-INET comment=user2 dst-address=x.x.x.2 protocol=icmp new-packet-mark=INET-008-Prio1 passthrough=no

There’s going to be a crap load of rules if I need to do this :frowning:

Essentially the queue-tree packet-mark matches multiple marks with “packet-mark OR packet-mark”… I’m looking to match on “packet-mark AND packet-mark” in the queue-tree, in which case this would solve my problem:

/ip firewall mangle
add action=jump chain=forward comment="Mark Outgoing Traffic (towards customer)" dst-address=x.x.x.0/23 jump-target=QOS-INET src-address=0.0.0.0/0
add action=mark-packet chain=QOS-INET comment=user1 dst-address=x.x.x.1 new-packet-mark=INET-004 passthrough=no
add action=mark-packet chain=QOS-INET comment=user2 dst-address=x.x.x.2 new-packet-mark=INET-004 passthrough=no
add action=mark-packet chain=QOS-INET comment=user3 dst-address=x.x.x.3 new-packet-mark=INET-004 passthrough=no
add action=mark-packet chain=QOS-INET comment=user4 dst-address=x.x.x.4 new-packet-mark=INET-004 passthrough=no
add action=mark-packet chain=prerouting comment="match ICMP" protocol=icmp new-packet-mark=Prio1 passthrough=no

/queue tree
add name="Contention Groups" parent=global queue=ethernet-default
add name="4Mbps Broadband" limit-at=8M max-limit=8M packet-mark=INET-004 parent="Contention Groups" priority=4 queue=INET-004
add name="4Mbps Prio 1" packet-mark="INET-004, Prio1" parent="4Mbps Broadband" priority=1 queue=INET-004

The basic idea is that certain packets will be dropped before others when the simple-queue (PPP) rates, or contention group (Queue Tree) rates are met. i.e. drop P2P packets before you drop VoIP packets out of the queues.

Thoughts, comments, suggestions? And yes, I would prefer to do this all on one router…

I agree it would be good when an AND match is possible on a queue tree.
However, it would also be possible to solve it when the “priority” field of the packet could be used as a matcher in the queue tree element.
That would seem an obvious option: you set the priority of the packet to a 0-7 value and then use that value to select between 8 subqueues.
The packet mark matcher could then be used for the higher level.

It would also be more efficient, I now use constructs like this:

/ip firewall mangle
add action=set-priority chain=postrouting comment="From dscp high 3 bits" \
    new-priority=from-dscp-high-3-bits passthrough=yes
add action=mark-packet chain=postrouting comment="Priority 0" \
    new-packet-mark=prio0 passthrough=no priority=0
add action=mark-packet chain=postrouting comment="Priority 1" \
    new-packet-mark=prio1 passthrough=no priority=1
add action=mark-packet chain=postrouting comment="Priority 2" \
    new-packet-mark=prio2 passthrough=no priority=2
add action=mark-packet chain=postrouting comment="Priority 3" \
    new-packet-mark=prio3 passthrough=no priority=3
add action=mark-packet chain=postrouting comment="Priority 4" \
    new-packet-mark=prio4 passthrough=no priority=4
add action=mark-packet chain=postrouting comment="Priority 5" \
    new-packet-mark=prio5 passthrough=no priority=5
add action=mark-packet chain=postrouting comment="Priority 6" \
    new-packet-mark=prio6 passthrough=no priority=6
add action=mark-packet chain=postrouting comment="Priority 7" \
    new-packet-mark=prio7 passthrough=no priority=7

Using those 8 different packet marks based on priority and then matching on the packet marks in the queue tree only adds overhead.
The Linux kernel can match queue elements on priority value, it is not made available in RouterOS