Junos QoS notes

30 12 2011

Juniper refers to QoS as Class of Service (CoS) and it is something that I’ve always had trouble quite getting my head around for some reason.  Sure – I’ve got CoS working nicely on switches and SRXes in customer networks, with packets hitting the right queues and so on, but you’re never quite sure it is exactly right.

Studying for my JNCIP-SP, I did a practice exam on the Juniper website and it seems that CoS is something I am weak in, so I am writing up some notes here for my own reference.


Packets that need different levels of treatment when passing through a Juniper device have to be classified as they enter the device, and queued for transmission before exiting the device. How packets are taken from the queues for transmission is called ‘scheduling’ – some queues are treated as higher priority than other queues so that more important packets such as voice or video get sent first.  Within that queue, other things can happen such as shaping the traffic down to a particular rate, re-marking packets, or dropping packets.  These things are done to proactively manage the queues in the device so that they don’t fill up. If they did, all packets would be dropped (tail-drop), so it is better to drop less critical packets early using Random Early Detection.

Classification of Packets

Packets can be classified in two ways:

1) By observing QoS markings on the packet (such as EXP bits, DSCP, IP ToS or 802.1P bits)

2) By observing other fields such as source/destination address, port numbers etc.

The first method is called Behaviour Aggregate classification. It implies that your whole network has been set up from end to end to classify (for example) voice packets using the DSCP bits.

The second method is called a Multi-Field Classifier, and is used when there are no markings on the packets that can be observed. The MFC might be used at the edge of the network to classify voice packets which are then marked with DSCP values.  Once marked, classification can be done through the core of the network using a BA classifier instead.

Packet Flow through Junos CoS

As a packet enters the router, the classifier assigns each packet a ‘forwarding class’ and a ‘loss priority’.  (Although I prefer to talk about a ‘loss probability’ because it makes sense to me – higher LP = higher chance of the packet being dropped).

Forwarding classes are assigned to queues.

Each queue has a scheduler applied to it.  The scheduler determines how packets are treated in the queue (i.e. dropped, re-marked, shaped) and how the packets are transmitted (i.e. which queue to serve first).

The packet is transmitted.


There is a default classifier applied to all interfaces on a Juniper router, which is based on IP Type of Service – it is called ‘ipprec-compatibility’ and you can see it below:

root@LAB_SRX2> show class-of-service classifier name ipprec-compatibility
Classifier: ipprec-compatibility, Code point type: inet-precedence, Index: 13
Code point         Forwarding class                    Loss priority
000                best-effort                         low
001                best-effort                         high
010                best-effort                         low
011                best-effort                         high
100                best-effort                         low
101                best-effort                         high
110                network-control                     low
111                network-control                     high

The code-points are 3-bit patterns in the left column, and these each map to a forwarding class and loss priority in the middle and right columns.  Out of the box, everything except network control traffic hits the best-effort class.

You don’t see any config statements associating the classifier with interfaces within Junos – that all happens under the hood.  However, when you associate a classifier with an interface yourself, the ‘ipprec-default’. You assign a classifier to an interface by typing “set class-of-service interface <name> unit <number> classifiers inet-precedence default”.

The default classifier for inet-precedence looks a bit different to the compatibility one.

Alternatively, you can make your own classifier – based on precedence or DSCP or whatever.  You can import the default one, and simply make the necessary changes you need – in the snippet below, I import the default classifier, change the expedited forwarding for packets marked with 111 and assign it to an interface:

root@LAB_SRX2# show class-of-service
classifiers {
  inet-precedence CLASS1 {
    import default;
    forwarding-class expedited-forwarding {
      loss-priority high code-points 111;
interfaces {
  ge-0/0/0 {
    unit 0 {
      classifiers {
        inet-precedence CLASS1;

You can see that the new classifier has taken effect by issuing the operational command “show class-of-service interface”:

Physical interface: ge-0/0/0, Index: 134
Queues supported: 8, Queues in use: 4
  Scheduler map: , Index: 2
  Congestion-notification: Disabled

  Logical interface: ge-0/0/0.0, Index: 78
    Object                  Name                   Type                    Index
    Classifier              CLASS1                 ip                       4804

So that’s all good. Now I’m classifying, what to do next?


As I’ve said, a scheduler governs how the queue is treated.  There are four properties of a scheduler that you can define:

1) The bandwidth assigned to the queue
2) The buffer size for storing packets in the queue
3) The priority of the queue
4) The drop profile

By default, only two schedulers are used – queue 0 for best effort traffic (allocated 95% of interface bandwidth), and queue 3 for network control stuff (getting the remaining 5% bandwidth).

So here’s a scheduler and a drop profile:

drop-profiles {
    DP1 {
        fill-level 50 drop-probability 50;
        fill-level 80 drop-probability 80;
schedulers {
    SCHED1 {
        transmit-rate percent 10;
        buffer-size percent 10;
        drop-profile-map loss-priority low protocol any drop-profile DP1;

This sets up a drop profile that randomly discards 50% of packets when the queue is 50% full, and 80% when it is 80% full. The scheduler SCHED1 is created with 10% of line rate and 10% of the interface’s buffers.  You might be wondering how I came up with those numbers.  To be honest, I just made them up.  You won’t find a right answer for creating these values anywhere – you need to set something up that looks OK and then monitor the results closely in most situations.  If you get it wrong, by default a queue can exceed the defined bandwidth if there is room in other queues.  (Quite what happens if those queues then fill up, I don’t know…)

Now that the scheduler has been created, we need to associate it to a forwarding class – this is done through a scheduler map.  Using the examples above:  “set class-of-service scheduler-map MAP1 forwarding-class expedited-forwarding scheduler SCHED1”

Finally, assign the scheduler map to the interface using “set class-of-service interface ge-0/0/0 scheduler-map MAP1”.


To see if this works there are a couple of things you can do.  Junos allows you to set the TOS bits in ping packets, so you can do that to create the right markings and then see if the packets are hitting the queues correctly.

Pinging with the right TOS value requires a calculation.  If your classifier is looking for the pattern 101 (as per the example), you have to remember that the TOS field is eight bits in length, so there are five zeros in the remainder of the field (10100000).  The two 1s occupy the 128 and 32 bit positions – add these together and you get a value of 160.  So the command from the neighbouring device to ping the one you’ve configured your CoS on is:

ping tos 160

This creates the marked packets – now go to the device where you configured your CoS, and look at the interface statistics in detail. On the second page of the output you should see packets hitting the expedited-forwarding queue:

  Queue counters:       Queued packets  Transmitted packets      Dropped packets
    0 best-effort                61155                61155                    0
    1 expedited-fo                  11                   11                    0
    2 assured-forw                   0                    0                    0
    3 network-cont               22795                22795                    0
  Queue number:         Mapped forwarding classes
    0                   best-effort
    1                   expedited-forwarding
    2                   assured-forwarding
    3                   network-control

So that’s some basic CoS configuration based on IP ToS. I’m off for a coffee.



10 responses

12 02 2012

It might be interesting to know that although you can pick your own mapping of queues and forwarding-classes as far as I know it is not possible to actually change the queue on traffic that is generated by the forwarding-plane itself. E.g. you cannot change the queue for BFD traffic on hardware that offloads BFD processing to the forwarding-plane. This traffic is always hardwired into queue 3.

A little something to keep in mind if you decide to change the queue in which you handle network-control type traffic.

21 01 2015

Actually we could change queue for routing engine generated traffic. Its documented on Juniper web. http://www.juniper.net/documentation/en_US/junos12.2/topics/concept/hw-cos-default-re-traffic-overview-cos-config-guide.html

23 08 2013
Ranjeet Badhe

I would like to know where have you defined the forwarding classes? The number of ques varies depending upon the platform. I have got Juniper 2320 where I have defined 8 queues.

3 09 2013

Hi – I can’t remember to be honest! It was a couple of years ago.
I know you can define queue numbers like this though:

PE1> show configuration chassis
fpc 0 {
pic 0 {
tunnel-services {
bandwidth 1g;
max-queues-per-interface 8;
pic 1 {
max-queues-per-interface 8;
pic 2 {
max-queues-per-interface 8;

6 05 2014

I am always confused between shaping-rate and buffer size under the scheduler config Can you please explain difference between them ?

2 08 2014
8 05 2015
31 07 2015

Very helpful post! By the way, quite what happens in a full queue situation is depicted in the following:


Your interface will have some very real queueing limitations, which you can adjust with the typical delay vs delivery reliability tradeoff, but at some point in over-congestion, the excess will get dropped. All you can do is prioritize critical traffic and try to get TCP sessions to self-regulate via the WRED shenanigans.

3 08 2015

Ah – thanks Aaron!

23 11 2015
Tony Singarayar

Thanks Mate, You noted saved lot of my time.
Tony Singarayar

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: