Discover the OIDs representing the counter-values of all active traffic-classes
Ciscos „SNMP Object Navigator“ (http://mibs.cloudapps.cisco.com/ITDIT/MIBS/servlet/index) is our friend to get the base-OID when you know the name of the MIB:
- Object-NAME <=> Object-ID (OID)
- „cbQosCMStatsEntry“ <=> „1.3.6.1.4.1.9.9.166.1.15.1.1“
Each object is a set of all counters from „show policy-map interface“-command, the Object Navigator documents the ID of these counters, too.
I’m focusing on
- counter#13 = cbQosCMDropPkt
- counts every dropped packet
- for production usage later on
- counter#2 = cbQosCMPrePolicyPkt
- counts each single packet in a traffic class
- for demonstration purposes
There will be one object of each type:
- per traffic-class in the bound policy-map,
- per policy, if bound to multiple interfaces.
Prepare a Linux-VM with Python/SNMP-Support
https://allones.de/2017/11/17/linux-quick-and-clean-lab-vm-deployment/
https://allones.de/2017/11/20/snmp-in-pythonlinux/
Prepare some QoS-Configuration on an IOS-Router
I’ll reuse this setup:
Refresher: RMON @ Cisco IOS
Generate some Traffic (TOS 184 = DSCP 46 = Expedited Forwarding (EF)
IOS-RTR#ping 192.168.2.1 tos 184 Type escape sequence to abort. Sending 5, 100-byte ICMP Echos to 192.168.2.1, timeout is 2 seconds: .!!!! Success rate is 80 percent (4/5), round-trip min/avg/max = 1/1/3 ms
The first „ping“ was replaced by an ARP-Packet, but we can expect 4 packets in the Priority-Queue.
Quick check: QoS-Counters
- 4 Packets „RTP“
- 0 Packets „CTRL“
- 473 Packets „class-default“
IOS-RTR# show policy-map interface GigabitEthernet1 Service-policy output: PM_OUT queue stats for all priority classes: Queueing queue limit 512 packets (queue depth/total drops/no-buffer drops) 0/0/0 (pkts output/bytes output) 4/456 Class-map: CM_VOIP_RTP (match-all) 4 packets, 456 bytes 5 minute offered rate 0000 bps, drop rate 0000 bps Match: dscp ef (46) Priority: 10% (100000 kbps), burst bytes 2500000, b/w exceed drops: 0 Class-map: CM_VOIP_CTRL (match-all) 0 packets, 0 bytes 5 minute offered rate 0000 bps, drop rate 0000 bps Match: dscp af31 (26) Queueing queue limit 64 packets (queue depth/total drops/no-buffer drops) 0/0/0 (pkts output/bytes output) 0/0 bandwidth 1% (10000 kbps) Class-map: class-default (match-any) 473 packets, 57201 bytes 5 minute offered rate 1000 bps, drop rate 0000 bps Match: any Queueing queue limit 64 packets (queue depth/total drops/no-buffer drops/flowdrops) 0/0/0/0 (pkts output/bytes output) 473/57201 Fair-queue: per-flow queue limit 16 packets
SNMP-Poll the MIB from the python-CLI on the SNMP-Linux-VM
Which OID? Concatenate:
- MIB-Position „1.3.6.1.4.1.9.9.166.1.15.1.1“ (cbQosCMStatsEntry)
- counter#2 (cbQosCMPrePolicyPkt)
to
- „1.3.6.1.4.1.9.9.166.1.15.1.1.2“
user@snmp-server:~$ python Type "help", "copyright", "credits" or "license" for more information. >>> >>> from easysnmp import Session >>> >>> session = Session(hostname='192.168.2.72', community='READ', version=2) >>> >>> cbqos = session.walk('1.3.6.1.4.1.9.9.166.1.15.1.1.2') >>> print cbqos [<SNMPVariable value='4' (oid='enterprises.9.9.166.1.15.1.1.2.18.65536', oid_index='', snmp_type='COUNTER')>, <SNMPVariable value='0' (oid='enterprises.9.9.166.1.15.1.1.2.18.131072', oid_index='', snmp_type='COUNTER')>, <SNMPVariable value='473' (oid='enterprises.9.9.166.1.15.1.1.2.18.196608', oid_index='', snmp_type='COUNTER')>] >>>
=> got three Packet-Counters: 1x Value „4“, 1x value „0“, 1x value „473“
The ID ‚enterprises.9.9.166.1.15.1.1.2.18.65536‘ identifies the one counter-object associated with the Packet-Counter of outbound RTP-Traffic-Class:
>>> print session.get('enterprises.9.9.166.1.15.1.1.2.18.65536') <SNMPVariable value='4' (oid='enterprises.9.9.166.1.15.1.1.2.18.65536', oid_index='', snmp_type='COUNTER')>
Now add some complexity – add the same Policy-Map to another router-interface
IOS-RTR#conf t Enter configuration commands, one per line. End with CNTL/Z. IOS-RTR(config)#int gig 2 IOS-RTR(config-if)#service-policy output PM_OUT IOS-RTR(config-if)#end
There should be 3 additional Packet-Counters.
Go to the python-shell:
>>> cbqos = session.walk('1.3.6.1.4.1.9.9.166.1.15.1.1.2') >>> print cbqos [<SNMPVariable value='4' (oid='enterprises.9.9.166.1.15.1.1.2.18.65536', oid_index='', snmp_type='COUNTER')>, <SNMPVariable value='0' (oid='enterprises.9.9.166.1.15.1.1.2.18.131072', oid_index='', snmp_type='COUNTER')>, <SNMPVariable value='529' (oid='enterprises.9.9.166.1.15.1.1.2.18.196608', oid_index='', snmp_type='COUNTER')>, <SNMPVariable value='0' (oid='enterprises.9.9.166.1.15.1.1.2.34.65536', oid_index='', snmp_type='COUNTER')>, <SNMPVariable value='0' (oid='enterprises.9.9.166.1.15.1.1.2.34.131072', oid_index='', snmp_type='COUNTER')>, <SNMPVariable value='0' (oid='enterprises.9.9.166.1.15.1.1.2.34.196608', oid_index='', snmp_type='COUNTER')>]
Perfect!
Loop over all Packet-Counter-Objects found in the SNMP-Walk
>>> for i in cbqos: ... print i ... <SNMPVariable value='4' (oid='enterprises.9.9.166.1.15.1.1.2.18.65536', oid_index='', snmp_type='COUNTER')> <SNMPVariable value='0' (oid='enterprises.9.9.166.1.15.1.1.2.18.131072', oid_index='', snmp_type='COUNTER')> <SNMPVariable value='601' (oid='enterprises.9.9.166.1.15.1.1.2.18.196608', oid_index='', snmp_type='COUNTER')> <SNMPVariable value='0' (oid='enterprises.9.9.166.1.15.1.1.2.34.65536', oid_index='', snmp_type='COUNTER')> <SNMPVariable value='0' (oid='enterprises.9.9.166.1.15.1.1.2.34.131072', oid_index='', snmp_type='COUNTER')> <SNMPVariable value='0' (oid='enterprises.9.9.166.1.15.1.1.2.34.196608', oid_index='', snmp_type='COUNTER')>
but again, don’t poll these values in 1s interval to provide real-time graphing ;-)!
So we just need the OIDs of all „DROP“-Counters and define RMON-Alarms linked to RMON-Events. (todo)
…and, would be interesting, to find out the Interfaces, the direction and the class-Names of the discovered QoS-Classes. (todo)