=========================
(gdb) ovs_dump_netdev_provider
(struct netdev_registered_class *) 0x2b2c540: refcnt = {count = 3},
(struct netdev_class *) 0x9555c0 = {type = tap, is_pmd = false, ...},
(struct netdev_registered_class *) 0x2b2c5a0: refcnt = {count = 2},
(struct netdev_class *) 0xc439d8 = {type = vxlan, is_pmd = false, ...},
(struct vport_class *) 0xc439d0 = { dpif_port = vxlan_sys, ... }
(struct netdev_registered_class *) 0x2b2c960: refcnt = {count = 1},
(struct netdev_class *) 0xc442f8 = {type = ip6erspan, is_pmd = false, ...},
(struct vport_class *) 0xc442f0 = { dpif_port = ip6erspan_sys, ... }
(struct netdev_registered_class *) 0x2b2c980: refcnt = {count = 1},
(struct netdev_class *) 0xc44540 = {type = ip6gre, is_pmd = false, ...},
(struct vport_class *) 0xc44538 = { dpif_port = ip6gre_sys, ... }
(struct netdev_registered_class *) 0x2b2ebe0: refcnt = {count = 3},
(struct netdev_class *) 0x95b8c0 = {type = dpdk, is_pmd = true, ...},
ovs_dump_ovs_list:
==================
(gdb) b memory_report
Breakpoint 1 at 0x753190: file lib/memory.c, line 136.
(gdb) set want_report=1
(gdb) c
Continuing.
Breakpoint 1, memory_report (usage=usage@entry=0x7fff0683d920) at lib/memory.c:136
136 {
(gdb) p usage
$20 = (const struct simap *) 0x7fff0683d920
(gdb) p* usage
$21 = {map = {buckets = 0x2b64df0, one = 0x0, mask = 3, n = 4}}
(gdb) p *usage
(gdb) ovs_dump_simap usage
handlers : 40 / 0x28
ports : 6 / 0x6
revalidators: 16 / 0x10
rules : 10 / 0xa
Signed-off-by: Eelco Chaudron <echaudro@redhat.com>
---
utilities/gdb/ovs_gdb.py | 113 ++++++++++++++++++++++++++++++++++++++-
1 file changed, 112 insertions(+), 1 deletion(-)
@@ -27,7 +27,9 @@
# - ovs_dump_dp_netdev_ports <struct dp_netdev *>
# - ovs_dump_dp_provider
# - ovs_dump_netdev
+# - ovs_dump_netdev_provider
# - ovs_dump_ovs_list <struct ovs_list *> {[<structure>] [<member>] {dump}]}
+# - ovs_dump_simap <struct simap *>
#
# Example:
# $ gdb $(which ovs-vswitchd) $(pidof ovs-vswitchd)
@@ -239,6 +241,19 @@ class ForEachSHASH(ForEachHMAP):
return node['data'].cast(gdb.lookup_type(self.data_typeobj).pointer())
+#
+# Class that will provide an iterator over an OVS simap.
+#
+class ForEachSIMAP(ForEachHMAP):
+ def __init__(self, shash):
+ super(ForEachSIMAP, self).__init__(shash['map'],
+ "struct simap_node", "node")
+
+ def next(self):
+ node = super(ForEachSIMAP, self).next()
+ return node['name'], node['data']
+
+
#
# Class that will provide an iterator over an OVS list.
#
@@ -473,7 +488,6 @@ class CmdDumpDpProvider(gdb.Command):
gdb.COMMAND_DATA)
def invoke(self, arg, from_tty):
-
dp_providers = get_global_variable('dpif_classes')
if dp_providers is None:
return
@@ -518,6 +532,66 @@ class CmdDumpNetdev(gdb.Command):
self.display_single_netdev(netdev)
+#
+# Implements the GDB "ovs_dump_netdev_provider" command
+#
+class CmdDumpNetdevProvider(gdb.Command):
+ """Dump all registered netdev providers.
+ Usage: ovs_dump_netdev_provider
+ """
+ def __init__(self):
+ super(CmdDumpNetdevProvider, self).__init__("ovs_dump_netdev_provider",
+ gdb.COMMAND_DATA)
+
+ @staticmethod
+ def is_class_vport_class(netdev_class):
+ netdev_class = netdev_class.cast(
+ gdb.lookup_type('struct netdev_class').pointer())
+
+ vport_construct = gdb.lookup_symbol('netdev_vport_construct')[0]
+
+ if netdev_class['construct'] == vport_construct.value():
+ return True
+ return False
+
+ @staticmethod
+ def display_single_netdev_provider(reg_class, indent=0):
+ indent = " " * indent
+ print("{}(struct netdev_registered_class *) {}: refcnt = {},".
+ format(indent, reg_class, reg_class['refcnt']))
+
+ print("{} (struct netdev_class *) 0x{:x} = {{type = {}, "
+ "is_pmd = {}, ...}}, ".
+ format(indent, long(reg_class['class']),
+ reg_class['class']['type'].string(),
+ reg_class['class']['is_pmd']))
+
+ if CmdDumpNetdevProvider.is_class_vport_class(reg_class['class']):
+ vport = container_of(
+ reg_class['class'],
+ gdb.lookup_type('struct vport_class').pointer(),
+ 'netdev_class')
+
+ if vport['dpif_port'] != 0:
+ dpif_port = vport['dpif_port'].string()
+ else:
+ dpif_port = "\"\""
+
+ print("{} (struct vport_class *) 0x{:x} = "
+ "{{ dpif_port = {}, ... }}".
+ format(indent, long(vport), dpif_port))
+
+ def invoke(self, arg, from_tty):
+ netdev_classes = get_global_variable('netdev_classes')
+ if netdev_classes is None:
+ return
+
+ for reg_class in ForEachCMAP(netdev_classes,
+ "struct netdev_registered_class",
+ "cmap_node"):
+ self.display_single_netdev_provider(reg_class)
+
+
#
# Implements the GDB "ovs_dump_ovs_list" command
#
@@ -591,6 +665,41 @@ class CmdDumpOvsList(gdb.Command):
member).dereference()))
+#
+# Implements the GDB "ovs_dump_simap" command
+#
+class CmdDumpSimap(gdb.Command):
+ """Dump all nodes of an ovs_list give
+ Usage: ovs_dump_ovs_list <struct simap *>
+ """
+
+ def __init__(self):
+ super(CmdDumpSimap, self).__init__("ovs_dump_simap",
+ gdb.COMMAND_DATA)
+
+ def invoke(self, arg, from_tty):
+ arg_list = gdb.string_to_argv(arg)
+
+ if len(arg_list) != 1:
+ print("ERROR: Missing argument!\n")
+ print(self.__doc__)
+ return
+
+ simap = gdb.parse_and_eval(arg_list[0]).cast(
+ gdb.lookup_type('struct simap').pointer())
+
+ values = dict()
+ max_name_len = 0
+ for name, value in ForEachSIMAP(simap.dereference()):
+ values[name.string()] = long(value)
+ if len(name.string()) > max_name_len:
+ max_name_len = len(name.string())
+
+ for name in sorted(values.iterkeys()):
+ print("{}: {} / 0x{:x}".format(name.ljust(max_name_len),
+ values[name], values[name]))
+
+
#
# Initialize all GDB commands
#
@@ -601,4 +710,6 @@ CmdDumpDpNetdevPollThreads()
CmdDumpDpNetdevPorts()
CmdDumpDpProvider()
CmdDumpNetdev()
+CmdDumpNetdevProvider()
CmdDumpOvsList()
+CmdDumpSimap()