Here is how the CBWFQ (Class-Based Weighted Fair Queueing) allocation mechanism is described on Cisco website : If excess bandwidth is available, the excess bandwidth is divided amongst the traffic classes in proportion to their configured bandwidths. If not all of the bandwidth is allocated, the remaining bandwidth is proportionally allocated among the classes, based on their configured bandwidth.”

How Is Unused Bandwidth Allocated?

In this example, policy-map “TOP” guarantees 20 percent of the bandwidth to class aaa and 40 percent of the bandwidth to class bbb.

policy-map TOP
class C1
bandwidth percent 20
class C2
bandwidth percent 40

If we apply this policy to a 100 Mbps link, it means that 20 Mbps is the minimum guaranteed to class aaa, and 40 Mbps is minimum guaranteed to class bbb. Importantly, 40 Mbps is leftover for class-default.

Should both classes C1 and C2 require bandwidth simultaneously, they proportionally share the unused bandwith 40 Mbps based on the configured rates.

The sharing ratio, in this case, is set at 20:40 or 1:2 so they share it in proportion to the configured rates, reflecting the respective allocations to class aaa and class bbb.

Now, let’s explore the scenarios where we explicitly specify the class-default and those where we don’t

Test environment :

We can conduct the tests using EVE-NG and iperf as follow :

From the client, we initiate two flows as follows:

└─# iperf -c 5.5.5.2 -u -P 1 -i 1 -p 5000 -f k -b 1.0M -t 0

└─# iperf -c 5.5.5.2 -u -P 1 -i 1 -p 5001 -f k -b 1.0M -t 0

On the server, we simultaneously listen to both UDP ports:

└─# iperf -s -u -P 0 -i 1 -p 5001 -f k

└─# iperf -s -u -P 0 -i 1 -p 5000 -f k

We use a Cisco CSR1K router, and we match the port UDP 5000 to class CM1 (so 5001 will go to class-default) :

class-map match-all CM1
match access-group name ACL1

ip access-list extended ACL1
permit udp any any eq 5000

Without Explicitly Allocating Bandwidth on class-default:

We configure the CSR Cisco router as follow :

policy-map TEST
class CM1
bandwidth percent 20
class class-default

policy-map SHAPE
class class-default
shape average 1000000
service-policy TEST

interface GigabitEthernet5
service-policy output SHAPE

In the Cisco output, implicitly, the class-default has been allocated 80%.

Router#show policy-map interface gigabitEthernet 5
GigabitEthernet5

Service-policy output: SHAPE
Class-map: class-default (match-any)  
  441009 packets, 666677500 bytes
  5 minute offered rate 2157000 bps, drop rate 1162000 bps
  Match: any 
  Queueing
  queue limit 64 packets
  (queue depth/total drops/no-buffer drops) 0/228229/0
  (pkts output/bytes output) 213515/322756330
  shape (average) cir 1000000, bc 4000, be 4000
  target shape rate 1000000

  Service-policy : TEST

    Class-map: CM1 (match-all)  
      212393 packets, 321138216 bytes
      5 minute offered rate 1078000 bps, drop rate 878000 bps
      Match: access-group name ACL1
      Queueing
      queue limit 64 packets
      (queue depth/total drops/no-buffer drops) 64/166765/0
      (pkts output/bytes output) 46862/70855344
      bandwidth 20% (200 kbps)

    Class-map: class-default (match-any)  
      226849 packets, 342867580 bytes
      5 minute offered rate 1079000 bps, drop rate 285000 bps
      Match: any 
      Queueing
      queue limit 64 packets
      (queue depth/total drops/no-buffer drops) 63/61464/0
      (pkts output/bytes output) 166653/251900986
      bandwidth 80% (800 kbps)

Now, let’s launch the trafic from the iPerf and see what we’ve got :

As observed, the default class did not receive the entire 80% of the remaining share. Instead, the excess share was proportionally divided. In our case, with only the CM1 class having a 20% minimum guaranteed, it received 20 + (20 * 80%) = 36%

without explicitly assigning bandwidth to the default class, it operates on a best-effort basis. All classes will contend for the remaining bandwidth after claiming their designated shares.

With Explicitly Allocating Bandwidth on Default-Class:

Now, let’s explicitly define the allocation for the class-default :

policy-map TEST
class CM1
bandwidth percent 20
class class-default
bandwidth percent 80

When bandwidth is explicitly allocated to the default class (80% in this example), it ensures that default traffic will receive its designated share, even when CM1 attempts to utilize the entire link.

In summary

In situations where non-default classes saturate the bandwidth, it becomes crucial to explicitly allocate bandwidth for the default-class. This explicit assignment ensures that unclassified or traffic not specified by other classes receives a dedicated share.

Failure to assign a specific bandwidth percentage to the default-class under such saturation scenarios may lead to potential capacity starvation for critical business applications or essential traffic falling within the default class (if there is), particularly when not explicitly identified and classified.

Leveraging ChatGPT3’s assistance, I’ve crafted a tool for pasting the class-map configuration and monitoring the dynamic distribution behavior 🙂

Feel free to make use of it (https://lastopinion.io/public/QoS_CBWFQ_proportion.html)

You can download the Lab here

Hope this helps !

Mehdi SFAR (CCDE 2021:3, CCIE #51583)