diff options
author | Eelco Chaudron <echaudro@redhat.com> | 2018-07-02 14:00:10 +0200 |
---|---|---|
committer | Ben Pfaff <blp@ovn.org> | 2018-07-06 14:18:21 -0700 |
commit | b23d42a68d756c3ac85b15140909ce0b04c7b242 (patch) | |
tree | 4dd256180a4b4220bbbd53273a16918205a03948 /utilities | |
parent | b3ed0e1e058cba8eadebaf7fab10d0a6e1219175 (diff) | |
download | openvswitch-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.py | 227 |
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() |