[ovs-dev] [PATCH ovn] ovn-detrace: Decode OVS Interfaces from ofproto/trace dumps.

Dumitru Ceara dceara at redhat.com
Thu Nov 21 18:32:43 UTC 2019


On Thu, Nov 21, 2019 at 7:22 PM Mark Michelson <mmichels at redhat.com> wrote:
>
> I pushed this to master.

Thanks!

>
> On 11/15/19 8:39 PM, Mark Michelson wrote:
> > Acked-by: Mark Michelson <mmichels at redhat.com>
> >
> > On 11/15/19 2:24 PM, Dumitru Ceara wrote:
> >> 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 <dceara at 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__":
> >>
> >
>



More information about the dev mailing list