Two new command line arguments are added to ovn-detrace:
- "--ovs": which will instruct ovn-detrace to connect to the local OVS
db.sock and try to decode input/output ofport values and pretty print
the corresponding OVS interfaces.
- "--ovsdb": which allows the user to point ovn-detrace to other OVS DB
remotes (useful when ovn-trace is not run on the hypervisor where
ofproto-trace was run.
Signed-off-by: Dumitru Ceara <dce...@redhat.com>
---
utilities/ovn-detrace.1.in | 11 +++++
utilities/ovn-detrace.in | 105 +++++++++++++++++++++++++++++++++------------
2 files changed, 88 insertions(+), 28 deletions(-)
diff --git a/utilities/ovn-detrace.1.in b/utilities/ovn-detrace.1.in
index 2f662d4..b899b63 100644
--- a/utilities/ovn-detrace.1.in
+++ b/utilities/ovn-detrace.1.in
@@ -33,6 +33,17 @@ Otherwise, the default is \fBunix:@RUNDIR@/ovnnb_db.sock\fR,
but this
default is unlikely to be useful outside of single-machine OVN test
environments.
.
+.IP "\fB\-\-ovs=\fR"
+Also decode flow information (like OVS ofport) from the flows by connecting
+to the OVS DB.
+.
+.IP "\fB\-\-ovsdb=\fIserver\fR"
+The OVS DB remote to contact if \fB\-\-ovs\f is present. If the
+\fBOVS_RUNDIR\fR environment variable is set, its value is used as the
+default. Otherwise, the default is \fBunix:@RUNDIR@/db.sock\fR, but this
+default is unlikely to be useful outside of single-machine OVN test
+environments.
+.
.SH "SEE ALSO"
.
.BR ovs\-appctl (8), ovn\-sbctl (8), ovn-\-nbctl (8), ovn\-trace (8)
diff --git a/utilities/ovn-detrace.in b/utilities/ovn-detrace.in
index c645658..52f6f4f 100755
--- a/utilities/ovn-detrace.in
+++ b/utilities/ovn-detrace.in
@@ -28,6 +28,7 @@ try:
from ovs import jsonrpc
from ovs.poller import Poller
from ovs.stream import Stream
+ from ovs import dirs
except Exception:
print("ERROR: Please install the correct Open vSwitch python support")
print(" libraries (@VERSION@).")
@@ -49,7 +50,8 @@ The following options are also available:
-h, --help display this help message
-V, --version display version information
--ovnsb=DATABASE use DATABASE as southbound DB
- --ovnnb=DATABASE use DATABASE as northbound DB\
+ --ovnnb=DATABASE use DATABASE as northbound DB
+ --ovsdb=DATABASE use DATABASE as OVS DB\
""" % {'argv0': argv0})
sys.exit(0)
@@ -102,15 +104,15 @@ class OVSDB(object):
def get_table(self, table_name):
return self._idl_conn.tables[table_name]
- def _find_row(self, table_name, find_fn):
+ def _find_rows(self, table_name, find_fn):
return filter(find_fn, self.get_table(table_name).rows.values())
def _find_rows_by_name(self, table_name, value):
- return self._find_row(table_name, lambda row: row.name == value)
+ return self._find_rows(table_name, lambda row: row.name == value)
def find_rows_by_partial_uuid(self, table_name, value):
- return self._find_row(table_name,
- lambda row: str(row.uuid).startswith(value))
+ return self._find_rows(table_name,
+ lambda row: str(row.uuid).startswith(value))
class CookieHandler(object):
def __init__(self, db, table):
@@ -118,9 +120,7 @@ class CookieHandler(object):
self._table = table
def get_records(self, cookie):
- # Adjust cookie to include leading zeroes if needed.
- cookie = cookie.zfill(8)
- return self._db.find_rows_by_partial_uuid(self._table, cookie)
+ return []
def print_record(self, record):
pass
@@ -128,7 +128,16 @@ class CookieHandler(object):
def print_hint(self, record, db):
pass
-class LogicalFlowHandler(CookieHandler):
+class CookieHandlerByUUUID(CookieHandler):
+ def __init__(self, db, table):
+ super(CookieHandlerByUUUID, self).__init__(db, table)
+
+ def get_records(self, cookie):
+ # Adjust cookie to include leading zeroes if needed.
+ cookie = cookie.zfill(8)
+ return self._db.find_rows_by_partial_uuid(self._table, cookie)
+
+class LogicalFlowHandler(CookieHandlerByUUUID):
def __init__(self, ovnsb_db):
super(LogicalFlowHandler, self).__init__(ovnsb_db, 'Logical_Flow')
@@ -163,7 +172,7 @@ class LogicalFlowHandler(CookieHandler):
output += ' (log)'
print_h(output)
-class PortBindingHandler(CookieHandler):
+class PortBindingHandler(CookieHandlerByUUUID):
def __init__(self, ovnsb_db):
super(PortBindingHandler, self).__init__(ovnsb_db, 'Port_Binding')
@@ -173,7 +182,7 @@ class PortBindingHandler(CookieHandler):
(pb.logical_port, pb.tunnel_key,
chassis_str(pb.chassis)))
-class MacBindingHandler(CookieHandler):
+class MacBindingHandler(CookieHandlerByUUUID):
def __init__(self, ovnsb_db):
super(MacBindingHandler, self).__init__(ovnsb_db, 'MAC_Binding')
@@ -182,7 +191,7 @@ class MacBindingHandler(CookieHandler):
print_p('MAC Binding: ip "%s", logical_port "%s", mac "%s"' %
(mb.ip, mb.logical_port, mb.mac))
-class MulticastGroupHandler(CookieHandler):
+class MulticastGroupHandler(CookieHandlerByUUUID):
def __init__(self, ovnsb_db):
super(MulticastGroupHandler, self).__init__(ovnsb_db,
'Multicast_Group')
@@ -194,31 +203,47 @@ class MulticastGroupHandler(CookieHandler):
print_p('Multicast Group: name "%s", tunnel_key %ld ports: (%s)' %
(mc.name, mc.tunnel_key, mc_ports))
-class ChassisHandler(CookieHandler):
+class ChassisHandler(CookieHandlerByUUUID):
def __init__(self, ovnsb_db):
super(ChassisHandler, self).__init__(ovnsb_db, 'Chassis')
def print_record(self, chassis):
print_p('Chassis: %s' % (chassis_str([chassis])))
-def print_sb_record_from_cookie(ovnnb_db, ovnsb_db, cookie_handlers, cookie):
+class OvsInterfaceHandler(CookieHandler):
+ def __init__(self, ovs_db):
+ super(OvsInterfaceHandler, self).__init__(ovs_db, 'Interface')
+
+ def get_records(self, ofport):
+ return self._db._find_rows(self._table,
+ lambda intf: len(intf.ofport) > 0 and
+ str(intf.ofport[0]) == ofport)
+
+ def print_record(self, intf):
+ print_p('OVS Interface: %s (%s)' %
+ (intf.name, intf.external_ids.get('iface-id')))
+
+def print_record_from_cookie(ovnnb_db, cookie_handlers, cookie):
for handler in cookie_handlers:
- for i, sb_record in enumerate(handler.get_records(cookie)):
+ for i, record in enumerate(handler.get_records(cookie)):
if i > 0:
handler.print('[Duplicate uuid cookie]')
- handler.print_record(sb_record)
- handler.print_hint(sb_record, ovnnb_db)
+ handler.print_record(record)
+ handler.print_hint(record, ovnnb_db)
def main():
try:
options, args = getopt.gnu_getopt(sys.argv[1:], 'hV',
- ['help', 'version', 'ovnsb=',
'ovnnb='])
+ ['help', 'version', 'ovs',
+ 'ovnsb=', 'ovnnb=', 'ovsdb='])
except getopt.GetoptError, geo:
sys.stderr.write("%s: %s\n" % (argv0, geo.msg))
sys.exit(1)
ovnsb_db = None
ovnnb_db = None
+ ovs_db = None
+ ovs = False
for key, value in options:
if key in ['-h', '--help']:
@@ -229,6 +254,10 @@ def main():
ovnsb_db = value
elif key in ['--ovnnb']:
ovnnb_db = value
+ elif key in ['--ovsdb']:
+ ovs_db = value
+ elif key in ['--ovs']:
+ ovs = True
else:
sys.exit(0)
@@ -238,6 +267,8 @@ def main():
sys.exit(1)
ovn_rundir = os.getenv('OVN_RUNDIR', '@OVN_RUNDIR@')
+ ovs_rundir = os.getenv('OVS_RUNDIR', dirs.RUNDIR)
+
if not ovnsb_db:
ovnsb_db = os.getenv('OVN_SB_DB')
if not ovnsb_db:
@@ -247,6 +278,8 @@ def main():
ovnnb_db = os.getenv('OVN_NB_DB')
if not ovnnb_db:
ovnnb_db = 'unix:%s/ovnnb_db.sock' % ovn_rundir
+ if ovs and not ovs_db:
+ ovs_db = 'unix:%s/db.sock' % ovs_rundir
ovsdb_ovnsb = OVSDB(ovnsb_db, 'OVN_Southbound')
ovsdb_ovnnb = OVSDB(ovnnb_db, 'OVN_Northbound')
@@ -260,25 +293,41 @@ def main():
]
regex_cookie = re.compile(r'^.*cookie 0x([0-9a-fA-F]+)')
+ regex_handlers = [
+ (regex_cookie, cookie_handlers)
+ ]
+
+ if ovs:
+ ovsdb_ovs = OVSDB(ovs_db, 'Open_vSwitch')
+ regex_inport = re.compile(r'^ *[0-9]+\. *in_port=([0-9])+')
+ regex_outport = re.compile(r'^ *output:([0-9]+)')
+ ofport_handlers = [
+ OvsInterfaceHandler(ovsdb_ovs)
+ ]
+ regex_handlers += [
+ (regex_outport, ofport_handlers),
+ (regex_inport, ofport_handlers)
+ ]
+
regex_table_id = re.compile(r'^ *[0-9]+\.')
- cookie = None
+ cookies = []
while True:
line = sys.stdin.readline()
- if cookie:
- # Print SB record info when the current flow block ends.
+ if len(cookies) > 0:
+ # Print record info when the current flow block ends.
if regex_table_id.match(line) or line.strip() == '':
- print_sb_record_from_cookie(ovsdb_ovnnb, ovsdb_ovnsb,
- cookie_handlers, cookie)
- cookie = None
+ for cookie, handlers in cookies:
+ print_record_from_cookie(ovsdb_ovnnb, handlers, cookie)
+ cookies = []
print(line.strip())
if line == '':
break
- m = regex_cookie.match(line)
- if not m:
- continue
- cookie = m.group(1)
+ for regex, handlers in regex_handlers:
+ m = regex.match(line)
+ if m:
+ cookies.append((m.group(1), handlers))
if __name__ == "__main__":