Skip to content

Instantly share code, notes, and snippets.

@odivlad
Last active December 29, 2023 07:08
Show Gist options
  • Save odivlad/62b4d0d302fd87e2db845fc445c1b917 to your computer and use it in GitHub Desktop.
Save odivlad/62b4d0d302fd87e2db845fc445c1b917 to your computer and use it in GitHub Desktop.
OpenVSwitch datapath monitoring
#!/usr/bin/env python
#
# Author: Vladislav Odintsov <odivlad@gmail.com>
#
# This script creates machine-readable output for OVS metrics
#
# Metrics values by columns:
# 1: dpflows - dapath flows count in ovs-dpctl show output
# 2: dphit - hits in cache (datapath)
# 3: dpmiss - missed searches in cache (datapath)
# 4: dploss - failed requests (datapath)
# 5: ofports - datapath ports count
# 6: mskhit - datapath mask hits
# 7: mskmiss - datapath mask missed requests
# 8: mskhitpkt - datapath mask hits/pkt
# 9: usflows - userspace flows count
import re
import subprocess
ovs_dpctl_show = ['ovs-dpctl', 'show']
ovs_ofctl_dump_aggregate = ['ovs-ofctl', 'dump-aggregate', 'c2nvp']
re_port = re.compile('\A(\w+) \d+: [\w-]+( \(.*\))?\Z')
def get_data(cmd):
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
try:
stdout, _ = p.communicate()
except subprocess.CalledProcessError as e:
raise Exception("Failed to run {0}".format(cmd))
try:
return stdout.replace('\t', '').split('\n')
except:
raise Exception("Failed to parse stdout of {0}.".format(cmd))
def process_dp(data):
res = {}
# process datapath >>>
dp = data[1].split(' ')
res['dphit'] = dp[1].split(':')[1]
res['dpmiss'] = dp[2].split(':')[1]
res['dploss'] = dp[3].split(':')[1]
# <<< process datapath
# process flows >>>
res['dpflows'] = data[2].split(': ')[1]
# <<< process flows
# process masks >>>
masks = data[3].split(' ')
res['mskhit'] = masks[1].split(':')[1]
res['mskmiss'] = masks[2].split(':')[1]
res['mskhtpkt'] = masks[3].split(':')[1]
# <<< process masks
# calculate openflow ports count >>>
ofports = 0
for i in range(0, len(data)):
m = re.match(re_port, data[i])
ofports = ofports + 1 if m and m.group(1) == 'port' else ofports
res['ofports'] = ofports
# <<< calculate openflow ports count
return res
def process_of(data):
res = {}
# process userspace flows >>>
us = data[0].split(' ')[5]
res['usflows'] = us.split('=')[1]
# <<< process userspace flows
return res
def print_result(res):
a = ''
for k, v in res.iteritems():
a += "{k}: {v}\n".format(k=k, v=v)
print(a)
def main():
dp_data = get_data(ovs_dpctl_show)
of_data = get_data(ovs_ofctl_dump_aggregate)
result = process_dp(dp_data)
result.update(process_of(of_data))
print_result(result)
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment