Repository: napalm-automation/napalm

Issue:
Cisco IOS Interface Counter TenGig and beyond not parsed correctly
### show interface summary not parsed correctly for 10G Interfaces

### Setup

### napalm version
(Paste verbatim output from `pip freeze | grep napalm` between quotes below)

```
napalm            2.5.0
****
```

### Network Operating Sytem 
```
Cisco IOS XE Software, Version 16.05.01b
```


I was playing arround with napalm to gather some interface data specifically on ios xe  router with 10G interfaces.

I noticed that I had a couple of interfaces with drops, but using the function 
get_interface_counters through nornir delivers a tx_discards: -1 

```
  'TenGigabitEthernet0/0/2': { 'rx_broadcast_packets': 0,
                               'rx_discards': -1,
                               'rx_errors': 0,
                               'rx_multicast_packets': 0,
                               'rx_octets': 1533128411516,
                               'rx_unicast_packets': 1780831170,
                               'tx_broadcast_packets': -1,
                               'tx_discards': -1,
                               'tx_errors': 0,
                               'tx_multicast_packets': -1,
                               'tx_octets': 1006199251542,
                               'tx_unicast_packets': 1631763809},

```

I could not image how -1 could be the correct output. 

Interfaces with Gigabitspeed were parsed correctly. 

IOS.py Line 2105

Digging through the source code I found , that napalm using "show interface summary" to get the IQD value, but it is searching for TenGigabitEthernet0/0/2 not for Te0/0/2 like in the output. 


###show interface summary example 
```
   Interface                   IHQ       IQD       OHQ       OQD      RXBS      RXPS      TXBS      TXPS      TRTL    
 -----------------------------------------------------------------------------------------------------------------    
 * Te0/0/0                       0         0         0         0 633161000    222861 1567988000    276185         0   
 * Te0/0/1                       0         0         0         0 514257000    153657 2048510000    343953         0   
 * Te0/0/2                       0         0         0         45454 514257000    153657 2048510000    343953         0    
 * GigabitEthernet0/0            0         0         0         1         0         1         0         0         0    
   GigabitEthernet0/1            0         0         0         2         0         1         0         0         0    
   GigabitEthernet0/2            0         0         0         0         0         1         0         0         0    
```                                                                                                                

From my point of view FortyGigabitEthernet , TwentyFiveGigabitEthernet ,HundredGigabitEthernet
are also not parsed correctly. 

I have already created a workaround, but not sure if this fits the code qualtity of this project. 

###Prototype
```
 for line in text.splitlines():
	 short_if_names = {'HundredGigabitEthernet':'Hu','TwentyFiveGigabitEthernet':'Tf','FortyGigabitEthernet':'Fo','TenGigabitEthernet':'Te'}
     match = re.search(r'(HundredGigabitEthernet|TwentyFiveGigabitEthernet|FortyGigabitEthernet|TenGigabitEthernet)(\d\/\d\/\d)',
             interface)

     if match:

        interface_short = '{}{}'.format(short_if_names.get(\
        match.groups()[0]), match.groups()[1])
        if interface_short in line:
             # Line is tabular output with columns
             # Interface  IHQ  IQD  OHQ  OQD  RXBS  RXPS  TXBS  TXPS  TRTL
             # where columns (excluding interface) are integers
             regex = (
                 r"\b"
                 + interface_short
                 + r"\b\s+(\d+)\s+(?P<IQD>\d+)\s+(\d+)"
                 + r"\s+(?P<OQD>\d+)\s+(\d+)\s+(\d+)"
                 + r"\s+(\d+)\s+(\d+)\s+(\d+)"
             )
             match = re.search(regex, line)
             if match:
				counters[interface]["rx_discards"] = int(match.group("IQD"))
				counters[interface]["tx_discards"] = int(match.group("OQD"))
     else:

         
         if interface in line:
             # Line is tabular output with columns
             # Interface  IHQ  IQD  OHQ  OQD  RXBS  RXPS  TXBS  TXPS  TRTL
             # where columns (excluding interface) are integers
             regex = (
                 r"\b"
                 + interface
                 + r"\b\s+(\d+)\s+(?P<IQD>\d+)\s+(\d+)"
                 + r"\s+(?P<OQD>\d+)\s+(\d+)\s+(\d+)"
                 + r"\s+(\d+)\s+(\d+)\s+(\d+)"
             )
             match = re.search(regex, line)
             if match:
				counters[interface]["rx_discards"] = int(match.group("IQD"))
				counters[interface]["tx_discards"] = int(match.group("OQD"))
```



Discussion:
We could probably just make use of the NAPALM canonical map (see https://github.com/napalm-automation/napalm/blob/develop/napalm/base/canonical_map.py) to convert from the short name to the full name (when looping through the output of `show interface summary`), e.g., map Te0/0/0 out to TenGigabitEthernet0/0/0, then match that into the output.
I'm open to create a PR , but can you give me a ref. where this map is already applied or used?

Resolving patch:
diff --git a/napalm/ios/ios.py b/napalm/ios/ios.py
--- a/napalm/ios/ios.py
+++ b/napalm/ios/ios.py
@@ -39,6 +39,8 @@
     canonical_interface_name,
     transform_lldp_capab,
     textfsm_extractor,
+    split_interface,
+    abbreviated_interface_name,
 )
 from napalm.base.netmiko_helpers import netmiko_args
 
@@ -2103,6 +2105,14 @@ def get_interfaces_counters(self):
                     match = re.search(r"(\d+) output errors", line)
                     counters[interface]["tx_errors"] = int(match.group(1))
                     counters[interface]["tx_discards"] = -1
+
+            interface_type, interface_number = split_interface(interface)
+            if interface_type in [
+                "HundredGigabitEthernet",
+                "FortyGigabitEthernet",
+                "TenGigabitEthernet",
+            ]:
+                interface = abbreviated_interface_name(interface)
             for line in sh_int_sum_cmd_out.splitlines():
                 if interface in line:
                     # Line is tabular output with columns
@@ -2117,6 +2127,7 @@ def get_interfaces_counters(self):
                     )
                     match = re.search(regex, line)
                     if match:
+                        interface = canonical_interface_name(interface)
                         counters[interface]["rx_discards"] = int(match.group("IQD"))
                         counters[interface]["tx_discards"] = int(match.group("OQD"))
 


Test patch:
diff --git a/test/ios/mocked_data/test_get_interfaces_counters/short_if_names/expected_result.json b/test/ios/mocked_data/test_get_interfaces_counters/short_if_names/expected_result.json
new file mode 100644
--- /dev/null
+++ b/test/ios/mocked_data/test_get_interfaces_counters/short_if_names/expected_result.json
@@ -0,0 +1,58 @@
+{
+	"TenGigabitEthernet0/0/0": {
+		"rx_unicast_packets": 0,
+		"rx_octets": 1748592,
+		"rx_broadcast_packets": 0,
+		"rx_multicast_packets": 0,
+		"rx_errors": 0,
+		"rx_discards": 0,
+		"tx_unicast_packets": 9297,
+		"tx_octets": 1355261,
+		"tx_broadcast_packets": -1,
+		"tx_multicast_packets": -1,
+		"tx_errors": 0,
+		"tx_discards": 0
+	},
+	"TenGigabitEthernet0/0/1": {
+		"rx_unicast_packets": 0,
+		"rx_octets": 1748592,
+		"rx_broadcast_packets": 0,
+		"rx_multicast_packets": 0,
+		"rx_errors": 0,
+		"rx_discards": 1,
+		"tx_unicast_packets": 9297,
+		"tx_octets": 1355261,
+		"tx_broadcast_packets": -1,
+		"tx_multicast_packets": -1,
+		"tx_errors": 0,
+		"tx_discards": 0
+	},
+	"FortyGigabitEthernet0/0/2": {
+		"rx_unicast_packets": 0,
+		"rx_octets": 1748592,
+		"rx_broadcast_packets": 0,
+		"rx_multicast_packets": 0,
+		"rx_errors": 0,
+		"rx_discards": 2,
+		"tx_unicast_packets": 9297,
+		"tx_octets": 1355261,
+		"tx_broadcast_packets": -1,
+		"tx_multicast_packets": -1,
+		"tx_errors": 0,
+		"tx_discards": 0
+	},
+	"HundredGigabitEthernet0/0/3": {
+		"rx_unicast_packets": 0,
+		"rx_octets": 1748592,
+		"rx_broadcast_packets": 0,
+		"rx_multicast_packets": 0,
+		"rx_errors": 0,
+		"rx_discards": 3,
+		"tx_unicast_packets": 9297,
+		"tx_octets": 1355261,
+		"tx_broadcast_packets": -1,
+		"tx_multicast_packets": -1,
+		"tx_errors": 0,
+		"tx_discards": 0
+	}
+}
diff --git a/test/ios/mocked_data/test_get_interfaces_counters/short_if_names/show_interface_summary.txt b/test/ios/mocked_data/test_get_interfaces_counters/short_if_names/show_interface_summary.txt
new file mode 100644
--- /dev/null
+++ b/test/ios/mocked_data/test_get_interfaces_counters/short_if_names/show_interface_summary.txt
@@ -0,0 +1,14 @@
+
+ *: interface is up
+ IHQ: pkts in input hold queue     IQD: pkts dropped from input queue
+ OHQ: pkts in output hold queue    OQD: pkts dropped from output queue
+ RXBS: rx rate (bits/sec)          RXPS: rx rate (pkts/sec)
+ TXBS: tx rate (bits/sec)          TXPS: tx rate (pkts/sec)
+ TRTL: throttle count
+
+  Interface                   IHQ       IQD       OHQ       OQD      RXBS      RXPS      TXBS      TXPS      TRTL
+-----------------------------------------------------------------------------------------------------------------
+* Te0/0/0                      0         0         0         0         0         0         0         0         0
+  Te0/0/1                      0         1         0         0         0         0         0         0         0
+  Fo0/0/2                      0         2         0         0         0         0         0         0         0
+  Hu0/0/3                      0         3         0         0         0         0         0         0         0
diff --git a/test/ios/mocked_data/test_get_interfaces_counters/short_if_names/show_interfaces.txt b/test/ios/mocked_data/test_get_interfaces_counters/short_if_names/show_interfaces.txt
new file mode 100644
--- /dev/null
+++ b/test/ios/mocked_data/test_get_interfaces_counters/short_if_names/show_interfaces.txt
@@ -0,0 +1,112 @@
+TenGigabitEthernet0/0/0 is up, line protocol is up
+  Hardware is EPA-10X10GE, address is 0000.1111.2222 (bia 0000.1111.2222)
+  Description: Link
+  MTU 1500 bytes, BW 10000000 Kbit/sec, DLY 10 usec,
+     reliability 255/255, txload 1/255, rxload 1/255
+  Encapsulation 802.1Q Virtual LAN, Vlan ID  1., loopback not set
+  Keepalive not supported
+  Full Duplex, 10000Mbps, link type is force-up, media type is SFP-SR
+  output flow-control is on, input flow-control is on
+  ARP type: ARPA, ARP Timeout 04:00:00
+  Last input 00:00:00, output 00:00:30, output hang never
+  Last clearing of "show interface" counters 1w5d
+  Input queue: 0/375/0/0 (size/max/drops/flushes); Total output drops: 0
+  Queueing strategy: fifo
+  Output queue: 0/40 (size/max)
+  30 second input rate 1 bits/sec, 0 packets/sec
+  30 second output rate 1 bits/sec, 0 packets/sec
+     0 packets input, 1748592 bytes, 0 no buffer
+     Received 0 broadcasts (0 IP multicasts)
+     0 runts, 0 giants, 0 throttles
+     0 input errors, 0 CRC, 0 frame, 0 overrun, 0 ignored
+     0 watchdog, 0 multicast, 0 pause input
+     9297 packets output, 1355261 bytes, 0 underruns
+     0 output errors, 0 collisions, 0 interface resets
+     0 unknown protocol drops
+     0 babbles, 0 late collision, 0 deferred
+     0 lost carrier, 0 no carrier, 0 pause output
+     0 output buffer failures, 0 output buffers swapped out
+TenGigabitEthernet0/0/1 is up, line protocol is up
+  Hardware is EPA-10X10GE, address is 0000.1111.2222 (bia 0000.1111.2222)
+  Description: Link
+  MTU 1500 bytes, BW 10000000 Kbit/sec, DLY 10 usec,
+     reliability 255/255, txload 1/255, rxload 1/255
+  Encapsulation 802.1Q Virtual LAN, Vlan ID  1., loopback not set
+  Keepalive not supported
+  Full Duplex, 10000Mbps, link type is force-up, media type is SFP-SR
+  output flow-control is on, input flow-control is on
+  ARP type: ARPA, ARP Timeout 04:00:00
+  Last input 00:00:00, output 00:00:30, output hang never
+  Last clearing of "show interface" counters 1w5d
+  Input queue: 0/375/0/0 (size/max/drops/flushes); Total output drops: 1
+  Queueing strategy: fifo
+  Output queue: 0/40 (size/max)
+  30 second input rate 1 bits/sec, 0 packets/sec
+  30 second output rate 1 bits/sec, 0 packets/sec
+     0 packets input, 1748592 bytes, 0 no buffer
+     Received 0 broadcasts (0 IP multicasts)
+     0 runts, 0 giants, 0 throttles
+     0 input errors, 0 CRC, 0 frame, 0 overrun, 0 ignored
+     0 watchdog, 0 multicast, 0 pause input
+     9297 packets output, 1355261 bytes, 0 underruns
+     0 output errors, 0 collisions, 0 interface resets
+     0 unknown protocol drops
+     0 babbles, 0 late collision, 0 deferred
+     0 lost carrier, 0 no carrier, 0 pause output
+     0 output buffer failures, 0 output buffers swapped out
+FortyGigabitEthernet0/0/2 is up, line protocol is up
+  Hardware is EPA-10X40GE, address is 0000.1111.2222 (bia 0000.1111.2222)
+  Description: Link
+  MTU 1500 bytes, BW 40000000 Kbit/sec, DLY 10 usec,
+     reliability 255/255, txload 1/255, rxload 1/255
+  Encapsulation 802.1Q Virtual LAN, Vlan ID  1., loopback not set
+  Keepalive not supported
+  Full Duplex, 40000Mbps, link type is force-up, media type is SFP-SR
+  output flow-control is on, input flow-control is on
+  ARP type: ARPA, ARP Timeout 04:00:00
+  Last input 00:00:00, output 00:00:30, output hang never
+  Last clearing of "show interface" counters 1w5d
+  Input queue: 0/375/0/0 (size/max/drops/flushes); Total output drops: 2
+  Queueing strategy: fifo
+  Output queue: 0/40 (size/max)
+  30 second input rate 1 bits/sec, 0 packets/sec
+  30 second output rate 1 bits/sec, 0 packets/sec
+     0 packets input, 1748592 bytes, 0 no buffer
+     Received 0 broadcasts (0 IP multicasts)
+     0 runts, 0 giants, 0 throttles
+     0 input errors, 0 CRC, 0 frame, 0 overrun, 0 ignored
+     0 watchdog, 0 multicast, 0 pause input
+     9297 packets output, 1355261 bytes, 0 underruns
+     0 output errors, 0 collisions, 0 interface resets
+     0 unknown protocol drops
+     0 babbles, 0 late collision, 0 deferred
+     0 lost carrier, 0 no carrier, 0 pause output
+     0 output buffer failures, 0 output buffers swapped out
+HundredGigabitEthernet0/0/3 is up, line protocol is up
+  Hardware is EPA-1X100GE, address is 0000.1111.2222 (bia 0000.1111.2222)
+  Description: Link
+  MTU 1500 bytes, BW 100000000 Kbit/sec, DLY 10 usec,
+     reliability 255/255, txload 1/255, rxload 1/255
+  Encapsulation 802.1Q Virtual LAN, Vlan ID  1., loopback not set
+  Keepalive not supported
+  Full Duplex, 100000Mbps, link type is force-up, media type is SFP-SR
+  output flow-control is on, input flow-control is on
+  ARP type: ARPA, ARP Timeout 04:00:00
+  Last input 00:00:00, output 00:00:30, output hang never
+  Last clearing of "show interface" counters 1w5d
+  Input queue: 0/375/0/0 (size/max/drops/flushes); Total output drops: 3
+  Queueing strategy: fifo
+  Output queue: 0/40 (size/max)
+  30 second input rate 1 bits/sec, 0 packets/sec
+  30 second output rate 1 bits/sec, 0 packets/sec
+     0 packets input, 1748592 bytes, 0 no buffer
+     Received 0 broadcasts (0 IP multicasts)
+     0 runts, 0 giants, 0 throttles
+     0 input errors, 0 CRC, 0 frame, 0 overrun, 0 ignored
+     0 watchdog, 0 multicast, 0 pause input
+     9297 packets output, 1355261 bytes, 0 underruns
+     0 output errors, 0 collisions, 0 interface resets
+     0 unknown protocol drops
+     0 babbles, 0 late collision, 0 deferred
+     0 lost carrier, 0 no carrier, 0 pause output
+     0 output buffer failures, 0 output buffers swapped out