Tuesday, June 7, 2016

Cisco Intro to QoS and CoS, Part 1 -- Identifying, Classifying and Marking Traffic

One problem found in any network of reasonable size is how to handle congestion. When there is more bandwidth available than clients require, there is (of course!) no problem. However, some types of network traffic -- such as streaming media -- are particularly bandwidth intensive, and often, very sensitive to variations in delay time. Consider, for example, HTTP traffic: an end user will most likely not notice the variation in transit times ("jitter") of the various packets that make up a requested download. On the other hand, a Voice over IP call is very sensitive to jitter. If the packets making up a Voice over IP call or videoconference don't arrive within a reasonably consistent timeframe, the call quality will suffer, and your end users will not be happy. Even worse, what would happen if your dynamic routing protocols cannot send updates and keepalive traffic in a timely fashion? Clearly, there needs to be a way to prioritize certain types of traffic to ensure that your clients receive sufficient bandwidth for their needs.

Consider the following network:


On the left-hand side of the network drawing, we have three Linux hosts, clients of the server on the right-hand side of the drawing. These three hosts will be in competition with each other for network resources, and because we are running OSPF (or routing protocol of your choice -- and yes, a dynamic routing protocol is overkill on a network this simple, but stay with me...) on R1 and R2, they will be competing with the network clients for bandwidth as well. Making this problem even more apparent, I have connected all of the PC's to the network via FastEthernet interfaces, but only connected R1 and R2 with a single T1 line. Due to the extreme mismatch between LAN and WAN capabilities, any one of the network clients can easily saturate the "WAN" link between R1 and R2. Don't believe me? Let's do some tests...

On the host "CentOS6," I have configured the "echo" service, and on the host "CentOS6_Clone," I have installed a network diagnostic tool called "tcpspray." With no other traffic on the network, let's use tcpspray to see how long it takes to send a flurry of data to the "CentOS6" server:

[root@centos6_clone ~]# tcpspray -e -n 1000 192.168.2.2
Received 1024000 bytes in 25.670507 seconds (30.955 kbytes/s)
Transmitted 1024000 bytes in 25.146152 seconds (39.768 kbytes/s)
[root@centos6_clone ~]#

Also on the host "CentOS6," I am running a web server, and one of the web pages hosted on the server is an image gallery that loads a 5x5 array of JPEG images (get your mind out of the gutter! They're pictures of motorcycles that inspired me while I was building my Cafe Racer project!). How would the tcpspray bandwidth be affected if one of the Knoppix clients was downloading the images to populate the web page at the same time? Let's find out...:

[root@centos6_clone ~]# tcpspray -e -n 1000 192.168.2.2
Received 1024000 bytes in 118.753065 seconds (8.421 kbytes/s)
Transmitted 1024000 bytes in 104.348504 seconds (9.583 kbytes/s)
[root@centos6_clone ~]#

Wow...it took almost five times as long to receive the replies, due to the congestion on the network! Fortunately, quality of service and/or class of service policies can allow us to prioritize certain kinds of traffic, as our network needs dictate.

Keep in mind that nothing is free, however. If we prioritize some kinds of traffic, that necessarily comes at the expense of other traffic. Therefore, you have to have a good idea what kinds of traffic cross your network, and how they should be balanced against each other...which is a good place for us to begin with our policy. Let's define the traffic that we want prioritized.

As I mentioned earlier, the parameters I used for tcpspray specified that we would use the "echo" service for our traffic. Let's include SSH as priority traffic so we can manage our routers (you are using SSH for network management, right?). As I also mentioned earlier, our network control traffic is also high priority. Too keep the discussion simple for now, we'll assume everything else is "best effort."

Now that we have a good idea how we want to prioritize our traffic, we need a way to have the router filter our priority traffic. If you think that sounds like a job for an Access Control List, you're exactly right:

ip access-list extended CORE_GOLD
 permit tcp any eq echo any
 permit tcp any any eq echo
!
ip access-list extended CUST_EF
 permit tcp any eq 22 any
 permit tcp any any eq 22
!

After identifying the priority traffic with an ACL, we then create "class maps" to map that traffic into different classes (kind of sounds like a tautology, sorry!):

class-map match-any CORE_CONTROL
 description Network control OSPF/BGP/etc
 match ip precedence 6
 match ip precedence 7
class-map match-any CUST-EF
 match access-group name CUST_EF
class-map match-any CORE_GOLD
 description Low-latency/priority queue
 match access-group name CORE_GOLD
!

We have now created three classes of priority traffic:
  1. CORE_CONTROL, for our network control traffic,
  2. CUST-EF, for high priority traffic ("expedited forwarding"), and
  3. CORE_GOLD, for low-latency traffic.

Our next step is to use these maps to define how the different classes of traffic will be handled:

policy-map CUST-IN
 class CUST-EF
  set ip dscp ef
 class class-default
  set dscp cs3
policy-map CUST-Generic
 class CORE_GOLD
  priority percent 50
 class CORE_CONTROL
  bandwidth percent 10
 class class-default
  bandwidth percent 1
!

For our "CUST-EF" traffic, we have said that we want to place a special marking, "dscp ef," on the packets that match this traffic. This gives our "CUST-EF" traffic high priority on the network. For "CORE_GOLD" traffic, we have said that we want to give that traffic 50 per cent of the available bandwidth. For "CORE_CONTROL" traffic, we have said that we want to give such traffic 10 per cent of the available bandwidth (network control traffic is typically small-volume, bursty traffic, so it is not necessary to reserve a large amount of bandwidth for this traffic -- we just need to ensure that the traffic isn't starved for bandwidth during times of congestion). Notice that we also have another de facto class of traffic in the policy maps: class-default. This is for traffic that didn't match any of our access control lists. In the "CUST-IN" policy map, we mark it with "dscp cs3" -- a low priority traffic queue, and in the "CUST-Generic" policy map, we don't reserve any bandwidth for this class.

At this point, we have established the framework for our QoS/CoS configuration, but we haven't actually implemented it yet. Just as an access-control list used to filter certain kinds of traffic has to be applied to an interface before it is useful, so does a policy map:

interface Serial1/0
service-policy output CUST-Generic
!

We also will apply the "CUST-IN" policy map to the ingress interface, VLAN 10 on R1 and Fa0/0 on R2:

R1(config)#int vlan 10
R1(config-if)#service-policy input CUST-IN
R1(config-if)#

R2(config)#int fa0/0
R2(config-if)#service-policy input CUST-IN
R2(config-if)#

Now, let's run our tcpspray test again, while the Knoppix client reloads the web page with the 25 JPEG images:

[root@centos6_clone ~]# tcpspray -e -n 1000 192.168.2.2
Received 1024000 bytes in 78.483684 seconds (12.742 kbytes/s)
Transmitted 1024000 bytes in 69.900585 seconds (14.306 kbytes/s)
[root@centos6_clone ~]#

These results are still slower than our initial baseline test, with no congestion on the network. However, it is significantly better than the test with no QoS/CoS and a congested network.

No comments:

Post a Comment