From a9806b569eb68b02a21986b0ba7a2de800411e77 Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Mon, 2 May 2011 16:27:58 -0700 Subject: [PATCH] ovsdbmonitor: Update to work with recent ovs-dpctl output. The format of "ovs-dpctl dump-flows" has completely changed since ovsdbmonitor was written. It seems like no one has tried out ovsdbmonitor since the rewrite, because it didn't work at all. This commit fixes the parser. --- ovsdb/ovsdbmonitor/OVEFlowWindow.py | 6 ++- ovsdb/ovsdbmonitor/OVEUtil.py | 76 ++++++++++++++--------------- 2 files changed, 40 insertions(+), 42 deletions(-) diff --git a/ovsdb/ovsdbmonitor/OVEFlowWindow.py b/ovsdb/ovsdbmonitor/OVEFlowWindow.py index ebcf466e..e5a29a9f 100644 --- a/ovsdb/ovsdbmonitor/OVEFlowWindow.py +++ b/ovsdb/ovsdbmonitor/OVEFlowWindow.py @@ -1,3 +1,4 @@ +# Copyright (c) 2011 Nicira Networks. # Copyright (c) 2010 Citrix Systems, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -22,6 +23,8 @@ from OVECommonWindow import * from Ui_FlowWindow import * +import re + class OVEFlowWindow(QtGui.QMainWindow, OVECommonWindow): LOAD_KEY = 'FlowWindow/window' COMMAND_OVS_DPCTL='/usr/bin/ovs-dpctl' @@ -231,7 +234,6 @@ class OVEFlowWindow(QtGui.QMainWindow, OVECommonWindow): colour = Qt.black for colNum, data in enumerate(flow): - item = None try: item = table.takeItem(rowNum, colNum) @@ -245,7 +247,7 @@ class OVEFlowWindow(QtGui.QMainWindow, OVECommonWindow): elif colNum == srcMacColumn or colNum == destMacColumn: cols = [int(x, 16) for x in data.split(':')] item.setBackground(QtGui.QColor(255-cols[2]*cols[3] % 192, 255-cols[3]*cols[4] % 192, 255-cols[4]*cols[5] % 192)) - elif colNum == srcIPColumn or colNum == destIPColumn: + elif re.match(r'[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+', str(data)): cols = [int(x) for x in data.split('.')] item.setBackground(QtGui.QColor(255-cols[1]*cols[2] % 192, 255-cols[2]*cols[3] % 192, 255-cols[3]*cols[0] % 192)) else: diff --git a/ovsdb/ovsdbmonitor/OVEUtil.py b/ovsdb/ovsdbmonitor/OVEUtil.py index 340d9b15..774bed27 100644 --- a/ovsdb/ovsdbmonitor/OVEUtil.py +++ b/ovsdb/ovsdbmonitor/OVEUtil.py @@ -1,3 +1,4 @@ +# Copyright (c) 2011 Nicira Networks. # Copyright (c) 2010 Citrix Systems, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -15,6 +16,7 @@ from OVEStandard import * from OVEConfig import * +import re class OVEUtil: UUID_RE = re.compile(r'([a-f0-9]{8}-[a-f0-9]{2})[a-f0-9]{2}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}') @@ -87,48 +89,42 @@ class OVEUtil: @classmethod def decodeFlows(cls, srcLines): retVal = [] - flowRe = re.compile( - # To fix this regexp: - # Comment out lines, starting from the bottom, until it works, then fix the one you stopped at - '^' + - r'tunnel([^:]*):'+ # Tunnel: tunnel00000000 - r'in_port([^:]+):' + # in_port: in_port0002 - r'vlan([^:]+):' + #VLAN: vlan65535 - r'([^ ]*) ' + # PCP: pcp0 - r'mac(.{17})->' + # Source MAC: mac00:16:76:c8:1f:c9-> - r'(.{17}) ' + # Dest MAC: mac00:16:76:c8:1f:c9 - r'type([^ ]+) ' + #Type: type05ff - r'proto([^ ]+) ' + #Proto: proto0 - r'(tos[^ ]+) ' + #Tos: tos0 - r'ip(\d+\.\d+\.\d+\.\d+)->' + # Source IP: ip1.2.3.4-> - r'(\d+\.\d+\.\d+\.\d+) ' + # Dest IP: 1.2.3.4 - r'port(\d+)->' + # Source port: port0-> - r'(\d+),\s*' + # Dest port: 0 - r'packets:(\d*),\s*' + # Packets: packets:3423, - r'bytes:(\d*),\s*' + # Bytes: bytes:272024, - r'used:([^,]+),\s*' + # Used: used:0.870s, - r'actions:(\w+)\s*' + # Actions: actions:drop - '' - ) for line in srcLines.split('\n'): if line != '': - match = flowRe.match(line) - if not match: - OVELog("Could not decode flow record '"+line+"'. Abandoning") - return retVal - else: - tunnel, inport, vlan, pcp, srcmac, destmac, type, proto, tos, srcip, destip, srcport, destport, packets, bytes, used, actions = match.groups() - tunnel = int(tunnel) - inport = int(inport) - vlan = int(vlan) - type = cls.ETHERTYPE_TRANS.get(type, type) - proto = cls.ETHERPROTO_TRANS.get(proto, proto) - srcport = int(srcport) - destport = int(destport) - packets = long(packets) - bytes = long(bytes) - # Order below needs to match that in flowDecodeHeadings - retVal.append((type, proto, inport, vlan, srcmac, destmac, srcip, destip, srcport, destport, packets, bytes, used, tos, pcp, tunnel, actions)) + fields = {} + for name, val in re.findall(r'([a-zA-Z0-9_+]+)\(([^)]+)\)', line): + if '=' in val: + for setting in val.split(','): + k,v = setting.split('=') + fields['%s.%s' % (name, k)] = v + else: + fields[name] = val + for setting in re.split(', ', line)[1:]: + if ':' in setting: + k,v = setting.split(':') + fields[k] = v + + tun_id = fields.get('tun_id', '') + in_port = int(fields.get('in_port', 0)) + eth_src = fields.get('eth.src', '') + eth_dst = fields.get('eth.dst', '') + vlan_vid = int(fields.get('vlan.vid', 0)) + vlan_pcp = int(fields.get('vlan.pcp', 0)) + eth_type = fields.get('eth_type', '') + ip_src = fields.get('ipv4.src', fields.get('ipv6.src', '')) + ip_dst = fields.get('ipv4.dst', fields.get('ipv6.dst', '')) + ip_proto = fields.get('ipv4.proto', fields.get('ipv6.proto', '')) + ip_tos = fields.get('ipv4.tos', fields.get('ipv6.tos', '')) + tp_src = fields.get('tcp.src', fields.get('udp.src', fields.get('arp.sip', fields.get('icmp.type', fields.get('icmpv6.type', ''))))) + tp_dst = fields.get('tcp.dst', fields.get('udp.dst', fields.get('arp.tip', fields.get('icmp.code', fields.get('icmpv6.code', ''))))) + + packets = fields.get('packets', '') + bytes = fields.get('bytes', '') + actions = fields.get('actions', '') + used = fields.get('used', '') + + # Order below needs to match that in flowDecodeHeadings + retVal.append((eth_type, ip_proto, in_port, vlan_vid, eth_src, eth_dst, ip_src, ip_dst, tp_src, tp_dst, packets, bytes, used, ip_tos, vlan_pcp, tun_id, actions)) return retVal -- 2.30.2