Monday, May 27, 2013

Implementing QoS on a GRE tunnel

Every night at a client location, we receive disconnects and an inability to run our capture configuration. Apparently they run a massive file backup which cannot be turned off. We decided to implement QoS (Quality of Service) on the tunnel in an attempt to not be disconnected. This was a one time deal so I doubt anyone will have to do this exact implementation again but hopefully this will unconfuse you when it comes to how QoS works.

QoS is basically traffic shaping; I'm not going to go in depth into it because I know less than I probably should considering I'm writing a wiki about it...We're giving priority to certain traffic when the packets are queued outbound.

It works somewhat differently with tunnels because we need to have the packet headers inspected BEFORE encapsulation. To do this we have to declare qos pre-classify; what this does is it creates a copy of the packet and caches it, encapsulates the packet, then when it comes to apply the QoS settings, it refers to the copy rather than the outbound packet itself.


Atlas

The first thing we have to do is define a class-map. Class maps identify traffic flows using a wide array of filtering criteria which are individually defined by match statements within the class map. Multiple match statements can be defined under a single class map.

When multiple match statements are used, the class map can be specified as follows:
match-all - a logical AND operand, meaning that all match statements must be true at the same time for the class map condition to be true
match-any - a logical OR operand, meaning that any of the match statements can be true for the class map condition to be true

You can define the follow criteria to match:
  access-group         Access group
  any                  Any packets
  class-map            Class map
  cos                  IEEE 802.1Q/ISL class of service/user priority values
  destination-address  Destination address
  discard-class        Discard behavior identifier
  dscp                 Match DSCP in IP(v4) and IPv6 packets
  flow                 Flow based QoS parameters
  fr-de                Match on Frame-relay DE bit
  fr-dlci              Match on fr-dlci
  input-interface      Select an input interface to match
  ip                   IP specific values
  mpls                 Multi Protocol Label Switching specific values
  not                  Negate this match result
  packet               Layer 3 Packet length
  precedence           Match Precedence in IP(v4) and IPv6 packets
  protocol             Protocol
  qos-group            Qos-group
  source-address       Source address
  vlan                 VLANs to match
For this specific scenario, we're concerned about SNMP and Telnet traffic:
class-map match-any CM-MANAGE
 match protocol snmp
 match protocol telnet
The next map you'll have to define is the first of two policy-maps. A policy map defines a named object that represents a set of policies to be applied to a set of traffic classes. There's two types of classes you can use, one such as our MANAGE class we defined earlier, and class-default which is the system default class matching otherwise unclassified packets. For our child policy map, we need to use a user-defined class.

Once in place, we can enforce a number of things:
  bandwidth        Bandwidth
  compression      Activate Compression
  drop             Drop all packets
  exit             Exit from class action configuration mode
  fair-queue       Enable Flow-based Fair Queuing in this Class
  log              Log IPv4 and ARP packets
  netflow-sampler  NetFlow action
  no               Negate or set default values of a command
  police           Police
  priority         Strict Scheduling Priority for this Class
  queue-limit      Queue Max Threshold for Tail Drop
  random-detect    Enable Random Early Detection as drop policy
  service-policy   Configure QoS Service Policy
  set              Set QoS values
  shape            Traffic Shaping
Our implementation is farily simple, so we're just giving our SNMP and Telnet traffic a priority. When defining priority, you can specify Kbps or percentage of total bandwidth. For us, we're just giving our traffic a 50Kb window.
policy-map PM-QOS-CHILD
 class MANAGE
  priority 50
For our next map, our parent map, we need to use the class-default class. As noted before, this matches unclassified packets. Within this class, we can refer to our CHILD policy map and implement traffic shaping. We could have implemented policing; policing also puts a limit on the maximum amount of available bandwidth, however, it simply drops off any packets that go over the set limit. Whereas shaping (which we're using here) will queue the traffic, cramming as many packets as possible within the limit given.



Because QoS on tunnels can only be applied ingress, we shape for the maximum upload rate provided by the ISP; in this case it's 500000bps (488Kbps). We also have to declare our child policy we defined earlier. The reason being is you cannot apply LLQ to the default class.

Low Latency Queuing (LLQ) allows delay-sensitive data to be given preferential treatment over other traffic by letting the data to be dequeued and sent first. 
policy-map PM-QOS-PARENT
 class class-default
  shape average 500000
  service-policy PM-QOS-CHILD
Now that we've drawn up our maps, we can apply them to our tunnel interface. Remember that we have to enable pre-classification to the interface otherwise our packets will be filtered after encapsulation.
int tun0
 service-policy output PM-QOS-PARENT
 qos pre-classify

Show

To verify that our QoS setup is working, we can use the show policy-map int tun0 command (replace tun0 with whatever interface you're applying it to).

You'll have to let some appropriate traffic through before this will accumulate any data; for our purpose, I simply spammed the inside with SNMP packets.

The main things we want to look for is any dropped packets, as you can see below there are none at the moment. We also want to make sure that our class-map is matching traffic; if you look under the user-defined class-map you will see a packet count. If this any anywhere higher than zero, it means your traffic is being matched and your QoS should be working.

Tunnel0 

  Service-policy output: PM-QOS-PARENT

    Class-map: class-default (match-any)
      2566 packets, 1453477 bytes
      5 minute offered rate 11000 bps, drop rate 0 bps
      Match: any 
      Queueing
      queue limit 64 packets
      (queue depth/total drops/no-buffer drops) 0/0/0
      (pkts output/bytes output) 0/0
      shape (average) cir 500000, bc 131250, be 131250
      target shape rate 500000

      Service-policy : PM-QOS-CHILD

        queue stats for all priority classes:
          
          queue limit 64 packets
          (queue depth/total drops/no-buffer drops) 0/0/0
          (pkts output/bytes output) 0/0

        Class-map: CM-MANAGE (match-any)
          157 packets, 110875 bytes
          5 minute offered rate 11000 bps, drop rate 0 bps
          Match: protocol snmp
            66 packets, 100848 bytes
            5 minute rate 11000 bps
          Match: protocol telnet
            91 packets, 10027 bytes
            5 minute rate 0 bps
          Priority: 50 kbps, burst bytes 1500, b/w exceed drops: 0
          

        Class-map: class-default (match-any)
          2409 packets, 1342602 bytes
          5 minute offered rate 0 bps, drop rate 0 bps
          Match: any 
          
          queue limit 64 packets
          (queue depth/total drops/no-buffer drops) 0/0/0
          (pkts output/bytes output) 0/0

1 comment: