Skip to content

Instantly share code, notes, and snippets.

@atoonk
Created April 7, 2021 22:43
Show Gist options
  • Save atoonk/98bb2ec5f4c9eb188c19da3422883de3 to your computer and use it in GitHub Desktop.
Save atoonk/98bb2ec5f4c9eb188c19da3422883de3 to your computer and use it in GitHub Desktop.
VPP DPDK interface stats
#!/usr/bin/env python3
import subprocess
import time
import signal
import sys, os
def get_stats(interface):
command=["vppctl", "show", "hardware-interfaces", interface]
cmd_output = subprocess.Popen(
command,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
universal_newlines=True,
)
stdout, stdr = cmd_output.communicate()
if cmd_output.returncode != 0:
print(f"error>>> command: {command}")
print(f"error>>> error code: {cmd_output.returncode}")
for line in stdout.splitlines():
print(f"error >>> {line}")
return False
else:
return stdout.splitlines()
def parse(stats):
found = False
results = {
"rx_frames":0,
"tx_frames":0,
"rx_bytes":0,
"tx_bytes":0,
}
for line in stats:
line = line.strip()
if line.startswith("rx bytes ok"):
values = line.split()
results['rx_bytes']=int(values[-1])
found = True
if line.startswith("tx bytes ok"):
values = line.split()
results['tx_bytes']=int(values[-1])
found = True
if line.startswith("rx frames ok"):
values = line.split()
results['rx_frames']=int(values[-1])
found = True
if line.startswith("tx frames ok"):
values = line.split()
results['tx_frames']=int(values[-1])
found = True
if not found:
print(f"No stats found for {interface}. Are you sure this interface exists?")
sys.exit(1)
return results
def pretty_number(value):
if value < 1 * 1024:
return [value,""]
if value < 1 * 1024 * 1024:
return [value/1024,"K"]
if value < 1 * 1024 * 1024 * 1024:
return [value/(1024*1024),"M"]
if value < 1 * 1024 * 1024 * 1024 * 1024:
return [value/(1024*1024*1024),"G"]
def print_stats(counters_old, counters_new,interval):
stats_to_print = {}
for counter in counters_old:
diff = counters_new[counter] - counters_old[counter]
stats_to_print[counter] = diff / interval
in_bps = f"bps_in %3.2f {pretty_number(stats_to_print['rx_bytes']*8)[1]}" % pretty_number(stats_to_print['rx_bytes']*8)[0]
out_bps = f"bps_out %3.2f {pretty_number(stats_to_print['tx_bytes']*8)[1]}" % pretty_number(stats_to_print['tx_bytes']*8)[0]
in_pps = f"pps_in %3.2f {pretty_number(stats_to_print['rx_frames'])[1]}" % pretty_number(stats_to_print['rx_frames'])[0]
out_pps = f"pps_out %3.2f {pretty_number(stats_to_print['tx_frames'])[1]}" % pretty_number(stats_to_print['tx_frames'])[0]
print(f'|{in_bps:16} |{out_bps:16} |{in_pps:16} |{out_pps:16} |')
# capture CTRL + C or other signal here
def goodbye(signal, frame):
print('CTRL-C detected. Goodbye')
sys.exit(0)
if __name__ == "__main__":
# Handel interrupt from keyboard (CTRL + C) and call goodbye()
signal.signal(signal.SIGINT, goodbye)
#First paramater is interface name, if second that will be interval
try:
interface = sys.argv[1]
except IndexError:
print(f"Usage: {sys.argv[0]} interface_name(string) [interval(int)]")
sys.exit(1)
try:
interval = int(sys.argv[2])
except IndexError:
interval = 1
counters = {}
while True:
stats = get_stats(interface)
counters_new = parse(stats)
if not counters:
# This should happen the first loop only.
# means we have no stats from the previous run, so nothing to print
pass
else:
print_stats(counters, counters_new,interval)
counters = counters_new
time.sleep(interval)
@atoonk
Copy link
Author

atoonk commented Apr 7, 2021

To be used on a VPP machine

root@test2:~# ./dpdk_ifstats.py TenGigabitEthernet2/0/1 1
|bps_in 0.00      |bps_out 0.00     |pps_in 0.00      |pps_out 0.00     |
|bps_in 952.00    |bps_out 0.00     |pps_in 1.00      |pps_out 0.00     |
|bps_in 0.00      |bps_out 0.00     |pps_in 0.00      |pps_out 0.00     |
|bps_in 952.00    |bps_out 0.00     |pps_in 1.00      |pps_out 0.00     |
|bps_in 0.00      |bps_out 0.00     |pps_in 0.00      |pps_out 0.00     |

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment