[ovs-dev] [PATCH] utilities: Add upcall related commands to the GDB script

Eelco Chaudron echaudro at redhat.com
Mon Jul 2 12:00:10 UTC 2018


This commit adds ovs_dump_udpif_keys and ovs_show_upcall commands to the GDB script.
Here are some examples of the output:

(gdb) ovs_show_upcall
netdev at ovs-netdev:
  flows         : (current 0) (avg 0) (max 0) (limit 10000)
  dump duration : 1ms
  ufid enabled  : true

  39: (keys 0)
  42: (keys 0)
  41: (keys 0)
  43: (keys 0)
  44: (keys 0)
  45: (keys 0)

system at ovs-system:
  flows         : (current 4000) (avg 4031) (max 4064) (limit 139000)
  dump duration : 4ms
  ufid enabled  : true

  99: (keys 676)
  102: (keys 665)
  101: (keys 656)
  103: (keys 648)
  104: (keys 642)
  105: (keys 713)


(gdb) ovs_dump_udpif_keys
(struct udpif *) 0x1ebb830: name = netdev at ovs-netdev, total keys = 2
(struct udpif *) 0x20c6f00: name = system at ovs-system, total keys = 0

(gdb) ovs_dump_udpif_keys 0x1ebb830
(struct umap *) 0x1ef9328:
  (struct udpif_key *) 0x7f36e0004e40: key_len = 132, mask_len = 144
                                       ufid = 3e529416-83bf-bab4-5c6e-421127a9143a
                                       hash = 0x3d96b11d, pmd_id = 1
                                       state = UKEY_OPERATIONAL
                                       n_packets = 2, n_bytes = 68
                                       used = 1397047436, tcp_flags = 0x0000
(struct umap *) 0x1efb740:
  (struct udpif_key *) 0x7f36dc004c20: key_len = 132, mask_len = 144
                                       ufid = ee98d69f-8298-04dd-844a-4d2abee9f773
                                       hash = 0x2e8077c2, pmd_id = 15
                                       state = UKEY_OPERATIONAL
                                       n_packets = 0, n_bytes = 0
                                       used = 0, tcp_flags = 0x0000

(gdb) ovs_dump_udpif_keys 0x1ebb830 short
(struct umap *) 0x1ef9328:
  (struct udpif_key *) 0x7f36e0004e40:
(struct umap *) 0x1efb740:
  (struct udpif_key *) 0x7f36dc004c20:

Signed-off-by: Eelco Chaudron <echaudro at redhat.com>
---
 utilities/gdb/ovs_gdb.py |  227 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 226 insertions(+), 1 deletion(-)

diff --git a/utilities/gdb/ovs_gdb.py b/utilities/gdb/ovs_gdb.py
index 65f9216d9..1b59ab71f 100644
--- a/utilities/gdb/ovs_gdb.py
+++ b/utilities/gdb/ovs_gdb.py
@@ -30,7 +30,9 @@
 #    - ovs_dump_netdev_provider
 #    - ovs_dump_ovs_list <struct ovs_list *> {[<structure>] [<member>] {dump}]}
 #    - ovs_dump_simap <struct simap *>
+#    - ovs_dump_udpif_keys {<udpif_name>|<udpif_address>} {short}
 #    - ovs_show_fdb {[<bridge_name>] {dbg} {hash}}
+#    - ovs_show_upcall {dbg}
 #
 #  Example:
 #    $ gdb $(which ovs-vswitchd) $(pidof ovs-vswitchd)
@@ -52,8 +54,14 @@
 #    ...
 #    ...
 #
-
 import gdb
+import uuid
+
+
+#
+# Global #define's from OVS which might need updating based on a version.
+#
+N_UMAPS = 512
 
 
 #
@@ -140,6 +148,7 @@ def eth_addr_to_string(eth_addr):
         long(eth_addr['ea'][4]),
         long(eth_addr['ea'][5]))
 
+
 #
 # Class that will provide an iterator over an OVS cmap.
 #
@@ -244,6 +253,39 @@ class ForEachHMAP(object):
                             self.member)
 
 
+#
+# Class that will provide an iterator over an Netlink attributes
+#
+class ForEachNL():
+    def __init__(self, nlattrs, nlattrs_len):
+        self.attr = nlattrs.cast(gdb.lookup_type('struct nlattr').pointer())
+        self.attr_len = long(nlattrs_len)
+
+    def __iter__(self):
+        return self
+
+    def round_up(self, val, round_to):
+        return int(val) + (round_to - int(val)) % round_to
+
+    def next(self):
+        if self.attr is None or \
+           self.attr_len < 4 or self.attr['nla_len'] < 4 or  \
+           self.attr['nla_len'] > self.attr_len:
+            #
+            # Invalid attr set, maybe we should raise an exception?
+            #
+            raise StopIteration
+
+        attr = self.attr
+        self.attr_len -= self.round_up(attr['nla_len'], 4)
+
+        self.attr = self.attr.cast(gdb.lookup_type('void').pointer()) \
+            + self.round_up(attr['nla_len'], 4)
+        self.attr = self.attr.cast(gdb.lookup_type('struct nlattr').pointer())
+
+        return attr
+
+
 #
 # Class that will provide an iterator over an OVS shash.
 #
@@ -723,6 +765,117 @@ class CmdDumpSimap(gdb.Command):
                                            values[name], values[name]))
 
 
+#
+# Implements the GDB "ovs_dump_simap" command
+#
+class CmdDumpUdpifKeys(gdb.Command):
+    """Dump all nodes of an ovs_list give
+    Usage: ovs_dump_udpif_keys {<udpif_name>|<udpif_address>} {short}
+
+      <udpif_name>    : Full name of the udpif's dpif to dump
+      <udpif_address> : Address of the udpif structure to dump. If both the
+                        <udpif_name> and <udpif_address> are omitted the
+                        available udpif structures are displayed.
+      short           : Only dump ukey structure addresses, no content details
+    """
+
+    def __init__(self):
+        super(CmdDumpUdpifKeys, self).__init__("ovs_dump_udpif_keys",
+                                               gdb.COMMAND_DATA)
+
+    def count_all_ukeys(self, udpif):
+        count = 0
+        for j in range(0, N_UMAPS):
+            count += udpif['ukeys'][j]['cmap']['impl']['p']['n']
+        return count
+
+    def dump_all_ukeys(self, udpif, indent=0, short=False):
+        indent = " " * indent
+        for j in range(0, N_UMAPS):
+            if udpif['ukeys'][j]['cmap']['impl']['p']['n'] != 0:
+                print("{}(struct umap *) {}:".
+                      format(indent, udpif['ukeys'][j].address))
+                for ukey in ForEachCMAP(udpif['ukeys'][j]['cmap'],
+                                        "struct udpif_key", "cmap_node"):
+
+                    base_str = "{}  (struct udpif_key *) {}: ". \
+                        format(indent, ukey)
+                    if short:
+                        print(base_str)
+                        continue
+
+                    print("{}key_len = {}, mask_len = {}".
+                          format(base_str, ukey['key_len'], ukey['mask_len']))
+
+                    indent_b = " " * len(base_str)
+                    if ukey['ufid_present']:
+                        print("{}ufid = {}".
+                              format(
+                                  indent_b, str(uuid.UUID(
+                                      "{:08x}{:08x}{:08x}{:08x}".
+                                      format(long(ukey['ufid']['u32'][3]),
+                                             long(ukey['ufid']['u32'][2]),
+                                             long(ukey['ufid']['u32'][1]),
+                                             long(ukey['ufid']['u32'][0]))))))
+
+                    print("{}hash = 0x{:8x}, pmd_id = {}".
+                          format(indent_b, long(ukey['hash']), ukey['pmd_id']))
+                    print("{}state = {}".format(indent_b, ukey['state']))
+                    print("{}n_packets = {}, n_bytes = {}".
+                          format(indent_b,
+                                 ukey['stats']['n_packets'],
+                                 ukey['stats']['n_bytes']))
+                    print("{}used = {}, tcp_flags = 0x{:04x}".
+                          format(indent_b,
+                                 ukey['stats']['used'],
+                                 long(ukey['stats']['tcp_flags'])))
+
+                    #
+                    # TODO: Would like to add support for dumping key, mask
+                    #       actions, and xlate_cache
+                    #
+                    # key = ""
+                    # for nlattr in ForEachNL(ukey['key'], ukey['key_len']):
+                    #     key += "{}{}".format(
+                    #         "" if len(key) == 0 else ", ",
+                    #         nlattr['nla_type'].cast(
+                    #             gdb.lookup_type('enum ovs_key_attr')))
+                    # print("{}key attributes = {}".format(indent_b, key))
+
+    def invoke(self, arg, from_tty):
+        arg_list = gdb.string_to_argv(arg)
+        all_udpifs = get_global_variable('all_udpifs')
+        if all_udpifs is None:
+            return
+
+        udpifs = dict()
+        for udpif in ForEachLIST(all_udpifs, "struct udpif", "list_node"):
+            udpifs[udpif['dpif']['full_name'].string()] = udpif
+
+            if len(arg_list) == 0:
+                print("(struct udpif *) {}: name = {}, total keys = {}".
+                      format(udpif, udpif['dpif']['full_name'].string(),
+                             self.count_all_ukeys(udpif)))
+
+        if len(arg_list) == 0:
+            return
+
+        if arg_list[0] in udpifs:
+            udpif = udpifs[arg_list[0]]
+        else:
+            try:
+                udpif = gdb.parse_and_eval(arg_list[0]).cast(
+                    gdb.lookup_type('struct udpif').pointer())
+            except Exception:
+                udpif = None
+
+        if udpif is None:
+            print("Can't find provided udpif address!")
+            return
+
+        self.dump_all_ukeys(udpif, 0, "short" in arg_list[1:])
+
+
 #
 # Implements the GDB "ovs_show_fdb" command
 #
@@ -884,6 +1037,76 @@ class CmdShowFDB(gdb.Command):
             self.display_ml_entries(ml, 0, "hash" in arg_list[1:],
                                     "dbg" in arg_list[1:])
 
+
+#
+# Implements the GDB "ovs_show_fdb" command
+#
+class CmdShowUpcall(gdb.Command):
+    """Show upcall information
+    Usage: ovs_show_upcall {dbg}
+
+      dbg  : Will show structure address information
+    """
+
+    def __init__(self):
+        super(CmdShowUpcall, self).__init__("ovs_show_upcall",
+                                            gdb.COMMAND_DATA)
+
+    @staticmethod
+    def display_udpif_upcall(udpif, indent=0, dbg=False):
+        indent = " " * indent
+
+        enable_ufid = get_global_variable('enable_ufid')
+        if enable_ufid is None:
+            return
+
+        dbg_str = ""
+        if dbg:
+            dbg_str = ", ((struct udpif *) {})".format(udpif)
+
+        print("{}{}{}:".format(
+            indent, udpif['dpif']['full_name'].string(),
+            dbg_str))
+
+        print("{}  flows         : (current {}) (avg {}) (max {}) (limit {})".
+              format(indent, udpif['n_flows'], udpif['avg_n_flows'],
+                     udpif['max_n_flows'], udpif['flow_limit']))
+        print("{}  dump duration : {}ms".
+              format(indent, udpif['dump_duration']))
+        print("{}  ufid enabled  : {}\n".
+              format(indent, enable_ufid &
+                     udpif['backer']['rt_support']['ufid']))
+
+        for i in range(0, int(udpif['n_revalidators'])):
+            revalidator = udpif['revalidators'][i]
+
+            dbg_str = ""
+            if dbg:
+                dbg_str = ", ((struct revalidator *) {})".\
+                    format(revalidator.address)
+
+            count = 0
+            j = i
+            while j < N_UMAPS:
+                count += udpif['ukeys'][j]['cmap']['impl']['p']['n']
+                j += int(udpif['n_revalidators'])
+
+            print("{}  {}: (keys {}){}".
+                  format(indent, revalidator['id'], count, dbg_str))
+
+        print("")
+
+    def invoke(self, arg, from_tty):
+        arg_list = gdb.string_to_argv(arg)
+
+        all_udpifs = get_global_variable('all_udpifs')
+        if all_udpifs is None:
+            return
+
+        for udpif in ForEachLIST(all_udpifs, "struct udpif", "list_node"):
+            self.display_udpif_upcall(udpif, 0, "dbg" in arg_list)
+
+
 #
 # Initialize all GDB commands
 #
@@ -897,4 +1120,6 @@ CmdDumpNetdev()
 CmdDumpNetdevProvider()
 CmdDumpOvsList()
 CmdDumpSimap()
+CmdDumpUdpifKeys()
 CmdShowFDB()
+CmdShowUpcall()



More information about the dev mailing list