Thursday, December 7, 2017

A (somewhat obsessive) deep-dive into methods of finding unused ports on Cisco switches, using only native IOS commands

tldr: scroll to bottom

It all started so innocently. I just wanted an unused port on a Cisco switch that was fully patched-in. I knew for sure most ports hadn't seen traffic in (potentially) years, but it was very possible some are still in use (but not currently online).

I found that the last output value in show interface output is what I'm after.

(Why not Last input? Turns out, that value is not incremented on L2 interfaces, or when CEF is enabled!) source1 source2

Let's get started:

sh int | i (line protocol|output never)

Interfaces directly preceding a Last input... line have never seen traffic since last counter reset. E.g.:

FastEthernet0/24 is down, line protocol is down (notconnect) Last input never, output never, output hang never 

If that command does not return at least one Last input... line, try this:

sh int | i (line protocol|Last input)

This may be hard to visually parse, however. It includes all interfaces, regardless of status, and their last input time.

Can we make our lives any easier?

sh int | i (line protocol|output [0-9]+[ywd])

This shows all interfaces, regardless of status, but then only lines with last output greater than 1 day.

This is because the output format follows 00:00:00 (HH:MM:SS) for timestamps less than 1 day. It follows y/w/d format thereafter (e.g., 34w4d)

Example output:

FastEthernet0/15 is administratively down, line protocol is down (disabled) Last input never, output 47w1d, output hang never FastEthernet0/16 is up, line protocol is up (connected) FastEthernet0/17 is down, line protocol is down (notconnect) Last input never, output 34w6d, output hang never FastEthernet0/18 is down, line protocol is down (notconnect) Last input never, output 8w6d, output hang never FastEthernet0/19 is down, line protocol is down (notconnect) Last input never, output 6w4d, output hang never FastEthernet0/20 is down, line protocol is down (notconnect) Last input never, output 6w4d, output hang never FastEthernet0/21 is down, line protocol is down (notconnect) Last input never, output 34w6d, output hang never FastEthernet0/22 is up, line protocol is up (connected) FastEthernet0/23 is down, line protocol is down (notconnect) Last input never, output 34w6d, output hang never FastEthernet0/24 is down, line protocol is down (notconnect) FastEthernet0/25 is up, line protocol is up (connected) FastEthernet0/26 is up, line protocol is up (connected) FastEthernet0/27 is up, line protocol is up (connected) 

This indeed makes it easier to see which interfaces might be unused.

Can we combine both into a one-liner?

sh int | i (line protocol|output never|output [0-9]+[ywd])

Example output:

FastEthernet0/28 is administratively down, line protocol is down (disabled) Last input never, output never, output hang never FastEthernet0/29 is up, line protocol is up (connected) FastEthernet0/30 is down, line protocol is down (notconnect) FastEthernet0/31 is down, line protocol is down (notconnect) Last input never, output 34w6d, output hang never FastEthernet0/32 is up, line protocol is up (connected) FastEthernet0/33 is down, line protocol is down (notconnect) Last input never, output 28w5d, output hang never FastEthernet0/34 is down, line protocol is down (notconnect) Last input never, output 34w6d, output hang never FastEthernet0/35 is down, line protocol is down (notconnect) FastEthernet0/36 is down, line protocol is down (notconnect) FastEthernet0/37 is down, line protocol is down (notconnect) FastEthernet0/38 is down, line protocol is down (notconnect) FastEthernet0/39 is down, line protocol is down (notconnect) 

Sure, this works! I still like running them separately, because never-used interfaces will be easier to spot.

We can take this a step further and only find interfaces that have been inactive for longer than one day:

  • sh int | i (line protocol|output [0-9]+[y]) — At least 1 year
  • sh int | i (line protocol|output [0-9]+[yw]) — At least 1 week
  • sh int | i (line protocol|output [0-9]+[y]|output [4-9]+[0-9]*[w]) — At least 4 weeks (~1 month)
  • sh int | i (line protocol|output [0-9]+[y]|output (1[2-9]|[2-9][0-9])[w]) - At least 12 weeks (~3 months)
  • sh int | i (line protocol|output [0-9]+[y]|output (2[6-9]|[3-9][0-9])[w]) — At least 26 weeks (~6 months)

Further down the rabbit hole:

sh int | i (down|output hang)

This is easy to remember, and reasonably semantic.

I like it less than above, because it will include results from connected interfaces, which may produce confusing results. E.g.:

FastEthernet0/24 is down, line protocol is down (notconnect) Last input never, output 20:39:49, output hang never Last input 8w5d, output 00:00:01, output hang never Last input never, output 00:00:01, output hang never Last input never, output 00:00:01, output hang never Last input never, output never, output hang never Last input never, output 00:00:01, output hang never 

Fa0/24's last output line is only the one directly below it. Subsequent lines belong to ports that are not down, and must be ignored.

Another approach:

sh int | i (down|output never)

Example output:

(output omitted) FastEthernet0/20 is down, line protocol is down (notconnect) FastEthernet0/21 is down, line protocol is down (notconnect) FastEthernet0/23 is down, line protocol is down (notconnect) FastEthernet0/24 is down, line protocol is down (notconnect) FastEthernet0/28 is administratively down, line protocol is down (disabled) Last input never, output never, output hang never FastEthernet0/30 is down, line protocol is down (notconnect) FastEthernet0/31 is down, line protocol is down (notconnect) FastEthernet0/33 is down, line protocol is down (notconnect) FastEthernet0/34 is down, line protocol is down (notconnect) (output omitted) 

It's pretty easy to see Fa0/28 is a candidate!

Warning: this approach assumes that connected interfaces will never match output never

Depending on your environment, this may not be a safe assumption! Although it seems unlikely, it's possible a connected interface has output never. If this happens, you can't rely on the above output, because it's possible adjacent lines do not belong to the same interface.

Let's look at the converse to really illustrate the risk:

sh int | i (connected|output never)

Example output:

FastEthernet0/27 is up, line protocol is up (connected) Last input never, output never, output hang never 

Huh? Fa0/27 is connected, but has NEVER sent a frame? Very unlikely (unless I just reset counters for that int, which I didn't)

Switch# sh int f0/27 FastEthernet0/27 is up, line protocol is up (connected) (omitted output) Last input never, output 00:00:00, output hang never (omitted output) 

Yeah, that's what I thought. So what happened?

The Last input never, output never, output hang never line came after FastEthernet0/27, but actually belonged to a different connected interface.

Bottom line: Only one expression in parentheses can be conditional. If both are conditional, you run the (admittedly small) risk of getting unreliable output. In sh int | i (connected|output never), the term connected will not necessarily return results for every interface, and the same is true for output never. We cannot guarantee adjacent output lines belong to the same interface.

As long as at least one expression is unconditional (i.e., returns results for every interface), we get 100% reliable results.

Put another way: Native IOS offers no 100% reliable way to show only interfaces which are both down, and have not seen traffic recently.

Pulling it all together

When I need an available port on a switch:

  1. sh int | i (down|output never) — Interfaces directly preceding any Last input... lines are almost certainly* ports that are not in use. If you receive no Last input... line in the output, all ports have been used at some point, since the last counter reset.
  2. sh int | i (down|output [0-9]+[y]|output (1[2-9]|[2-9][0-9])[w]) — Interfaces directly preceding any Last input... lines have not seen use for at least 12 weeks. In my case, that's good enough.
  3. If both of the above produce no Last intput... lines, consider stepping down the threshold, or consider the possibility that all ports are actually in use.

* This assumes a negligible likelihood of a port being connected, yet having output never

Now I'm curious if there's a way to wrap all this into the napalm-ios module :}



No comments:

Post a Comment