Eelco Chaudron wrote: > Newer versions of Python require a different iterator function. This > change will make the iterator classes work with all Python versions. > > Adds a fix for python3 as it does not support the long() type. > The fix guaranties the script still works on Python 2.7. > > The uKey walker is rather slow on python3, so added a spinner to > indicate we are still busy processing entries. > > Fix functions using the iterkeys() function on dictionaries. > > Signed-off-by: Eelco Chaudron <[email protected]>
It's good to me. Tested-by: solomon <[email protected]> > --- > > v3: Fixing iterkeys, and adding a spinner > v2: Adding fix for python3 compatibility as it does not support long() > > utilities/gdb/ovs_gdb.py | 123 ++++++++++++++++++++++++++++++++------- > 1 file changed, 103 insertions(+), 20 deletions(-) > > diff --git a/utilities/gdb/ovs_gdb.py b/utilities/gdb/ovs_gdb.py > index cb9778c69..e8fb44c19 100644 > --- a/utilities/gdb/ovs_gdb.py > +++ b/utilities/gdb/ovs_gdb.py > @@ -55,7 +55,11 @@ > # ... > # ... > # > +from __future__ import print_function > + > import gdb > +import six > +import sys > import uuid > > > @@ -65,6 +69,13 @@ import uuid > N_UMAPS = 512 > > > +# > +# For Python2-3 compatibility define long as int > +# > +if six.PY3: > + long = int > + > + > # > # The container_of code below is a copied from the Linux kernel project file, > # scripts/gdb/linux/utils.py. It has the following copyright header: > @@ -150,6 +161,37 @@ def eth_addr_to_string(eth_addr): > long(eth_addr['ea'][5])) > > > +# > +# Simple class to print a spinner on the console > +# > +class ProgressIndicator(object): > + def __init__(self, message=None): > + self.spinner = "/-\|" > + self.spinner_index = 0 > + self.message = message > + > + if self.message is not None: > + print(self.message, end='') > + > + def update(self): > + print("{}\b".format(self.spinner[self.spinner_index]), end='') > + sys.stdout.flush() > + self.spinner_index += 1 > + if self.spinner_index >= len(self.spinner): > + self.spinner_index = 0 > + > + def pause(self): > + print("\r\033[K", end='') > + > + def resume(self): > + if self.message is not None: > + print(self.message, end='') > + self.update() > + > + def done(self): > + self.pause() > + > + > # > # Class that will provide an iterator over an OVS cmap. > # > @@ -192,7 +234,7 @@ class ForEachCMAP(object): > > raise StopIteration > > - def next(self): > + def __next__(self): > ipml = self.cmap['impl']['p'] > if ipml['n'] == 0: > raise StopIteration > @@ -206,6 +248,9 @@ class ForEachCMAP(object): > gdb.lookup_type(self.typeobj).pointer(), > self.member) > > + def next(self): > + return self.__next__() > + > > # > # Class that will provide an iterator over an OVS hmap. > @@ -229,7 +274,7 @@ class ForEachHMAP(object): > > raise StopIteration > > - def next(self): > + def __next__(self): > # > # In the real implementation the n values is never checked, > # however when debugging we do, as we might try to access > @@ -253,6 +298,9 @@ class ForEachHMAP(object): > gdb.lookup_type(self.typeobj).pointer(), > self.member) > > + def next(self): > + return self.__next__() > + > > # > # Class that will provide an iterator over an Netlink attributes > @@ -268,7 +316,7 @@ class ForEachNL(): > def round_up(self, val, round_to): > return int(val) + (round_to - int(val)) % round_to > > - def next(self): > + 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: > @@ -286,6 +334,9 @@ class ForEachNL(): > > return attr > > + def next(self): > + return self.__next__() > + > > # > # Class that will provide an iterator over an OVS shash. > @@ -298,14 +349,17 @@ class ForEachSHASH(ForEachHMAP): > super(ForEachSHASH, self).__init__(shash['map'], > "struct shash_node", "node") > > - def next(self): > - node = super(ForEachSHASH, self).next() > + def __next__(self): > + node = super(ForEachSHASH, self).__next__() > > if self.data_typeobj is None: > return node > > return > node['data'].cast(gdb.lookup_type(self.data_typeobj).pointer()) > > + def next(self): > + return self.__next__() > + > > # > # Class that will provide an iterator over an OVS simap. > @@ -315,10 +369,13 @@ class ForEachSIMAP(ForEachHMAP): > super(ForEachSIMAP, self).__init__(shash['map'], > "struct simap_node", "node") > > - def next(self): > - node = super(ForEachSIMAP, self).next() > + def __next__(self): > + node = super(ForEachSIMAP, self).__next__() > return node['name'], node['data'] > > + def next(self): > + return self.__next__() > + > > # > # Class that will provide an iterator over an OVS smap. > @@ -328,10 +385,13 @@ class ForEachSMAP(ForEachHMAP): > super(ForEachSMAP, self).__init__(shash['map'], > "struct smap_node", "node") > > - def next(self): > - node = super(ForEachSMAP, self).next() > + def __next__(self): > + node = super(ForEachSMAP, self).__next__() > return node['key'], node['value'] > > + def next(self): > + return self.__next__() > + > > # > # Class that will provide an iterator over an OVS list. > @@ -346,7 +406,7 @@ class ForEachLIST(): > def __iter__(self): > return self > > - def next(self): > + def __next__(self): > if self.list.address == self.node['next']: > raise StopIteration > > @@ -359,6 +419,9 @@ class ForEachLIST(): > gdb.lookup_type(self.typeobj).pointer(), > self.member) > > + def next(self): > + return self.__next__() > + > > # > # Implements the GDB "ovs_dump_bridges" command > @@ -499,7 +562,7 @@ class CmdDumpDpNetdevPollThreads(gdb.Command): > @staticmethod > def display_single_poll_thread(pmd_thread, indent=0): > indent = " " * indent > - print("{}(struct dp_netdev_pmd_thread *) {}: core_id = {:s}, " > + print("{}(struct dp_netdev_pmd_thread *) {}: core_id = {}, " > "numa_id {}".format(indent, > pmd_thread, pmd_thread['core_id'], > pmd_thread['numa_id'])) > @@ -597,7 +660,7 @@ class CmdDumpNetdev(gdb.Command): > @staticmethod > def display_single_netdev(netdev, indent=0): > indent = " " * indent > - print("{}(struct netdev *) {}: name = {:15}, auto_classified = {:5}, > " > + print("{}(struct netdev *) {}: name = {:15}, auto_classified = {}, " > "netdev_class = {}". > format(indent, netdev, netdev['name'].string(), > netdev['auto_classified'], netdev['netdev_class'])) > @@ -733,10 +796,11 @@ class CmdDumpOvsList(gdb.Command): > if typeobj is None or member is None: > print("(struct ovs_list *) {}".format(node)) > else: > - print("({} *) {} =".format( > + print("({} *) {} {}".format( > typeobj, > container_of(node, > - gdb.lookup_type(typeobj).pointer(), > member))) > + gdb.lookup_type(typeobj).pointer(), member), > + "=" if dump else "")) > if dump: > print(" {}\n".format(container_of( > node, > @@ -774,7 +838,7 @@ class CmdDumpSimap(gdb.Command): > if len(name.string()) > max_name_len: > max_name_len = len(name.string()) > > - for name in sorted(values.iterkeys()): > + for name in sorted(six.iterkeys(values)): > print("{}: {} / 0x{:x}".format(name.ljust(max_name_len), > values[name], values[name])) > > @@ -809,7 +873,7 @@ class CmdDumpSmap(gdb.Command): > if len(key.string()) > max_key_len: > max_key_len = len(key.string()) > > - for key in sorted(values.iterkeys()): > + for key in sorted(six.iterkeys(values)): > print("{}: {}".format(key.ljust(max_key_len), > values[key])) > > @@ -826,6 +890,7 @@ class CmdDumpUdpifKeys(gdb.Command): > <udpif_name> and <udpif_address> are omitted the > available udpif structures are displayed. > short : Only dump ukey structure addresses, no content > details > + no_count : Do not count the number of ukeys, as it might be slow > """ > > def __init__(self): > @@ -834,14 +899,22 @@ class CmdDumpUdpifKeys(gdb.Command): > > def count_all_ukeys(self, udpif): > count = 0 > + spinner = ProgressIndicator("Counting all ukeys: ") > + > for j in range(0, N_UMAPS): > + spinner.update() > count += udpif['ukeys'][j]['cmap']['impl']['p']['n'] > + > + spinner.done() > return count > > def dump_all_ukeys(self, udpif, indent=0, short=False): > indent = " " * indent > + spinner = ProgressIndicator("Walking ukeys: ") > for j in range(0, N_UMAPS): > + spinner.update() > if udpif['ukeys'][j]['cmap']['impl']['p']['n'] != 0: > + spinner.pause() > print("{}(struct umap *) {}:". > format(indent, udpif['ukeys'][j].address)) > for ukey in ForEachCMAP(udpif['ukeys'][j]['cmap'], > @@ -890,10 +963,14 @@ class CmdDumpUdpifKeys(gdb.Command): > # nlattr['nla_type'].cast( > # gdb.lookup_type('enum ovs_key_attr'))) > # print("{}key attributes = {}".format(indent_b, key)) > + spinner.resume() > + spinner.done() > > def invoke(self, arg, from_tty): > arg_list = gdb.string_to_argv(arg) > all_udpifs = get_global_variable('all_udpifs') > + no_count = "no_count" in arg_list > + > if all_udpifs is None: > return > > @@ -901,12 +978,15 @@ class CmdDumpUdpifKeys(gdb.Command): > for udpif in ForEachLIST(all_udpifs, "struct udpif", "list_node"): > udpifs[udpif['dpif']['full_name'].string()] = udpif > > - if len(arg_list) == 0: > + if len(arg_list) == 0 or ( > + len(arg_list) == 1 and arg_list[0] == "no_count"): > print("(struct udpif *) {}: name = {}, total keys = {}". > format(udpif, udpif['dpif']['full_name'].string(), > - self.count_all_ukeys(udpif))) > + self.count_all_ukeys(udpif) if not no_count > + else "<not counted!>")) > > - if len(arg_list) == 0: > + if len(arg_list) == 0 or ( > + len(arg_list) == 1 and arg_list[0] == "no_count"): > return > > if arg_list[0] in udpifs: > @@ -1074,7 +1154,7 @@ class CmdShowFDB(gdb.Command): > max_name_len = len(node['up']['name'].string()) > > if len(arg_list) == 0: > - for name in sorted(all_name.iterkeys()): > + for name in sorted(six.iterkeys(all_name)): > print("{}: (struct mac_learning *) {}". > format(name.ljust(max_name_len), > all_name[name]['ml'])) > @@ -1140,10 +1220,13 @@ class CmdShowUpcall(gdb.Command): > > count = 0 > j = i > + spinner = ProgressIndicator("Counting all ukeys: ") > while j < N_UMAPS: > + spinner.update() > count += udpif['ukeys'][j]['cmap']['impl']['p']['n'] > j += int(udpif['n_revalidators']) > > + spinner.done() > print("{} {}: (keys {}){}". > format(indent, revalidator['id'], count, dbg_str)) > > -- Thanks Solomon _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
