Friday, August 14, 2009

Cisco IOS Configs for QoS Shaping of Vonage Traffic (Part 3 of 3)

In my last post, I described how to ensure the Vonage traffic consisting of voice and call signaling gets the correct DSCP while on the internal network.  However, even though packets are marked correctly, they will not be prioritized over other traffic during congestion if we don’t configure our routers to take action on them. 

In this post, I will implement traffic shaping on the interface of the routers facing the Internet, meaning the ones directly-connected to the cable modem and ADSL modem. 

Note- There is a lesser need to prioritize traffic anywhere else inside our network because of adequate LAN bandwidth, although should a need arise in the future, our DSCP values are already set and ready to use.

Basically, because the ISP polices or shapes our upload traffic to a certain rate, in my case, cable modem upload is not usually able to go higher than 512 Kbps, and ADSL upload is limited to a maximum of 384 Kbps.

So, if we don’t implement traffic shaping to these rates on our routers, we basically let the ISP control what traffic to delay or drop when we exceed the upload speed we pay for.  This is very bad because the ISP (either on our modem or on an upstream device) will most likely drop or delay some of our voice traffic! The results are audio quality problems, among others things.

Hence, if we can perform the QoS prioritization ourselves and say, give 90 Kbps to our voice traffic, which is enough for one G.711 phone call, which is the codec Vonage uses, and 4% of the remaining bandwidth to call signaling, and the rest of the upload bandwidth to the other non-time-sensitive apps like email, HTTP and FTP, in case of congestion, we will guarantee all the voice traffic will upload promptly, and anything over the shaped rate will get randomly dropped or delayed.

There are several Cisco IOS QoS mechanisms that can help us meet the above requirements.  In this Vonage case, I chose Low Latency Queueing (LLQ), Class-Based Weighted Fair Queueing (CBWFQ), Weighted Fair Queueing (WFQ), Weighted Random Early Detection (WRED), and a traffic shaping.  These tools will act upon our previously assigned DSCP values.

Let’s use the router supporting the cable modem connection for our example.  The Cisco QoS SRND document teleworker section states the shaper should be set to a rate of 95% of the upload speed advertised by your cable ISP.  Even though this is not a teleworker environment, the hardware and ISP access media is the same so I opted to follow this guideline.  However, in my case, even though my cable ISP tells me I won’t be able to upload to more than 512 Kbps, I know they allow more because I monitor this via NetFlow and the reports show speeds up to 768 Kbps sometimes.  So, I decided to shape at 512 Kbps instead of 486 Kbps knowing I have enough headroom.  This can be easily adjusted later.

Before doing the modular QoS CLI (MQC) commands, we need to tell the router how much bandwidth he has on the outside interface, and also force the calculation of the remaining bandwidth to equal 100% after subtracting our voice priority queue (LLQ) of 90 Kbps from 512 Kbps.  Here is the explanation:

Bandwidth 512 – 90 (LLQ) = 422 Kbps

422 Kbps = 100% of the remaining bandwidth available for CBWFQ/WFQ, as long as the following commands are entered on the interface:

int fa0/1

 bandwidth 512

 max-reserved-bandwidth 100

We just do this to allow simpler calculations.  At this point, I want 4% (422 x 0.04 = 17) assigned to call signaling, and 96% (422 x 0.96 = 405) assigned to the rest.

policy-map PM_QUEUEING


    priority 90


    bandwidth remaining percent 4

 class class-default



Note- Similar calculations would be done for the ADSL router, except in the QoS SRND, the recommendation is shaping at 70% of the upload contract.  In our case, 384 Kbps x 70% = 269 Kbps.

The above commands tell the router to use a 3-class (queues) model to prioritize our 3 types of traffic.

The keyword “priority” in the first class tells the router that as long as there are packets in this first queue, it should forward them and not service the next class until this priority queue has been serviced.  We prevent ‘starvation’ of the other 2 classes by policing at 90 Kbps. This means that any traffic above 90Kbps will be dropped and the next class will be serviced.  As mentioned above, this mechanism for the first class is called LLQ.  Now, in this case, the policing at 90 Kbps is appropriate because we have only one Vonage ATA with a single phone line, so we will always have a maximum of a single call at once.  Hence, the 90 Kbps will never be exceeded.  If we add a second line, we would need to double this priority queue to 180Kbps, which would mean there will be less bandwidth available for the rest of the classes.  Or, you could configure your Vonage setup (via their web-based dashboard) to use a lower bandwidth codec such as G.729.  So, you can see that in an enterprise environment, when LLQ is used for voice packets, which is the recommended method, some way of ensuring there will only be a certain maximum of calls at once is very important.  Call Admission Control (CAC) and gatekeeper devices is one of the tools for this.  However, it’s not in the scope of this article since we are only dealing with a home network.

The next class for call signaling is configured with the “bandwidth” keyword.  This QoS tool is called CBWFQ.  We simply assign 4% of our 422 Kbps remaining to call signaling.

The last class (class-default) is always present.  We could configure it with the remaining 96%, however, instead, we don’t assign a bandwidth which tells IOS “the rest of the bandwidth”.  One thing to keep in mind when not assigning a bandwidth to the class-default, is the other classes can rob it of bandwidth. This is because of the way the CBWFQ algorithm has been coded; if classes protected with a bandwidth statement are offered more traffic than their minimum bandwidth guarantee, the algorithm tries to protect such excess traffic at the direct expense of robbing bandwidth from class-default (if class-default is configured with fair-queue), unless class-default itself has a bandwidth statement (providing itself with a minimum bandwidth guarantee). In our case, we don’t mind if the call signaling class robs class-default for more bandwidth. 

We also configure the keyword “random-detect”, which enables WRED.  During congestion, WRED will selectively drop TCP packets matching this class to ensure there is no global synchronization of TCP traffic.  Basically, because TCP packets will be re-transmitted if dropped, we can do this with almost no noticeable impact.  However, the benefit is when a TCP session notices there are dropped packets, it slows down.  So, it therefore helps our router, and allows all traffic to be forwarded more efficiently.

We also use the “fair-queue” keyword on the class-default to use WFQ instead of FIFO.  WFQ classifies packets based on flows and favors low-volume high precedence flows.

Now that we have our queues (classes) configured with the bandwidth desired, during congestion, our preferred voice traffic will be prioritized.  However, we still need to configure the shaper to ensure we don’t exceed our ISP upload speed.  The following commands describe how to do this.

policy-map PM_SHAPING

 class class-default

    shape average 512000 5120 0

  service-policy PM_QUEUEING

In this configuration, we assign the class-default a shaping rate of 512 Kbps with the most appropriate Bc (5120 b) and Tc (10 ms) for voice traffic.  An explanation on how those second and third values were determined would be too lengthy for this blog but can definitely be found on the Cisco website or any good Cisco QoS book.

The reason we assign “class-default” the shaping rate is we need the router to activate shaping whenever “any” packet exceeds our 512 Kbps contract.  Once the shaper is active, it then can queue according to our “PM_QUEUING” classes.  The shaper then decides when to dequeue the next packet, however, it relies on the PM_QUEUEING to tell it which packet to dequeue next.  That’s how our voice traffic will get prioritized over our previously configured class-default.

The last step is to assign the policy-map PM_SHAPING to our outside interface in the outbound direction.

int fa0/1

 service-policy output PM_SHAPING


To view the QoS statistics:

show policy-map int fa0/1 out

I hope these three posts on how to configure your Cisco routers for Vonage traffic were useful.  Feel free to comment!