summaryrefslogtreecommitdiff
path: root/utilities
diff options
context:
space:
mode:
authorEelco Chaudron <echaudro@redhat.com>2018-07-02 14:00:10 +0200
committerBen Pfaff <blp@ovn.org>2018-07-06 14:18:21 -0700
commitb23d42a68d756c3ac85b15140909ce0b04c7b242 (patch)
tree4dd256180a4b4220bbbd53273a16918205a03948 /utilities
parentb3ed0e1e058cba8eadebaf7fab10d0a6e1219175 (diff)
downloadopenvswitch-b23d42a68d756c3ac85b15140909ce0b04c7b242.tar.gz
utilities: Add upcall related commands to the GDB script
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@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@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@ovs-netdev, total keys = 2 (struct udpif *) 0x20c6f00: name = system@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@redhat.com> Signed-off-by: Ben Pfaff <blp@ovn.org>
Diffstat (limited to 'utilities')
-rw-r--r--utilities/gdb/ovs_gdb.py227
1 files changed, 226 insertions, 1 deletions
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.
#
@@ -245,6 +254,39 @@ class ForEachHMAP(object):
#
+# 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.
#
class ForEachSHASH(ForEachHMAP):
@@ -724,6 +766,117 @@ class CmdDumpSimap(gdb.Command):
#
+# 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
#
class CmdShowFDB(gdb.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()