Last active
December 29, 2023 07:08
-
-
Save odivlad/62b4d0d302fd87e2db845fc445c1b917 to your computer and use it in GitHub Desktop.
OpenVSwitch datapath monitoring
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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