First blog post (and it’s long) so let’s just get down to brass tacks…
I recently had a minor panic attack when I was looking at all the fancy stats that show ap auto-rf 802.11a “ap name” gives you on a Cisco WLC. All 3 of my controllers were showing hundreds, if not thousands, of channel changes for a vast majority of the associated APs. My first thought was that there was something in my RF environment causing Dynamic Channel Assignment (DCA) to constantly be changing the channel plan. From what I could recall though, Cisco had designed DCA to keep cascading channel changes from rippling though the entire wireless environment. The numbers were indicating otherwise though.
A small sampling of random AP’s across sites large and small was turning up a large number of high channel change counts regardless of site. I decided that I wanted to see what my channel changes looked like for each AP. We have almost 500 AP’s so running the above command on each AP wasn’t the best use of time plus I was having to go into Cisco Prime to look up each AP’s physical location. So with the problem at hand I decided it was…
…PYTHON TIME!!
I’ve been playing around with Python for over a year now – mostly writing scripts and programs to help me out with some tedious tasks at work. I had some prior scripts that leveraged both the piapi (for interacting with Cisco Prime) and netmiko (ssh access) python libraries and so I dug in and whipped up a quick program that given a .csv file of AP names, would output another .csv with the AP Name, Number of Channel Changes, and location in an easy to read format. The program does the following:
- Opens a ssh connection to the specified WLC
- Reads in the list of AP Names from the specified .csv file
- For each AP it:
- Runs the “show ap auto-rf 802.11a APNAME” command
- Grabs the channel change count as a string
- Connects to Prime and gets the location for the specified AP
- Writes the AP Name, Channel Change Count, and Location to a list
- Dumps the contents of the list to a .csv file
The ap-list.csv file just has the AP Names listed row by row in the first column – nothing else.
Disclaimer: This a very basic program with no error checking and probably some inefficient code – it does the job though 🙂
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
import netmiko import csv from piapi import PIAPI api_url = "YOUR_PI_URL" #ex. https://prime.company.com/ api_user = "PI_DEFINED_API_USER" #Make a user in Prime with API access api_pass = "API_USER_PASSWORD" api = PIAPI(api_url, api_user, api_pass, verify=False) cisco_wlc = { 'device_type': 'cisco_wlc', 'ip': 'WLC_IP', 'username': 'WLC_USERNAME', 'password': 'WLC_PASSWORD', } net_connect = netmiko.ConnectHandler(**cisco_wlc) with open("ap-list.csv", 'r') as my_file: reader = csv.reader(my_file) my_list = list(reader) #print my_list ap_dca = [] for ap in my_list: cmd = 'show ap auto-rf 802.11a ' + ap[0] output = net_connect.send_command(cmd) lines = output.splitlines() for line in lines: if "Count" in line: count=line[50:len(line)].strip() results = api.request("AccessPoints", params={"name": ap[0]}) location=results[0]['accessPointsDTO']['location'] row = [ap[0],count,location] ap_dca.append(row) #print row with open("ap-dca-count.csv", "ab") as f: writer = csv.writer(f) writer.writerows(ap_dca) |
Output looks like this:
SO…
Once I had all my data on a nice spreadsheet I started to notice that we had single AP’s out in shacks in the middle of nowhere that were reporting channel changes every time DCA ran (at the 10 minute default). There was no reasonable explanation for that so I logged in to the WLC, checked the channel for one of those AP’s and then waited for DCA to run.
DCA runs, AP shows that the channel change count incremented by one, and guess what: NO ACTUAL CHANNEL CHANGE!
I verified the same behavior on several other AP’s. No actual channel changes but reporting as if there were. I reached out to the great wi-fi experts on the wi-fipros slack channel and the consensus was that is was probably a bug. Conveniently we had a code upgrade scheduled for that evening so I went ahead with the upgrade as planned and re-ran my program the next morning.
VOILA! I was no longer receiving false channel change counts on the controller. I have ran the program a few times over the last couple of weeks just to verify that the false channel changes have not returned and so far so good.