diff options
author | Eelco Chaudron <echaudro@redhat.com> | 2018-06-20 11:04:03 +0200 |
---|---|---|
committer | Ben Pfaff <blp@ovn.org> | 2018-06-20 10:20:06 -0700 |
commit | ef557e2c55444782cc800196ff6cbf253c57faa3 (patch) | |
tree | 3653b4e8472b62bbdc2d2b575e24191431aac2c4 /utilities/gdb/ovs_gdb.py | |
parent | e02b6f8106929de0c2cc673052c9ea9aa5c221b9 (diff) | |
download | openvswitch-ef557e2c55444782cc800196ff6cbf253c57faa3.tar.gz |
utilities: Add the ovs_show_fdb command to gdb
This adds the ovs_show_fdb command:
Usage: ovs_show_fdb {<bridge_name> {dbg} {hash}}
<bridge_name> : Optional bridge name, if not supplied FDB summary
information is displayed for all bridges.
dbg : Will show structure address information
hash : Will display the forwarding table using the hash
table, rather than the rlu list.
Some examples:
(gdb) ovs_show_fdb
br0 : (struct mac_learning *) 0x139c160
table.n : 0
secret : 0x6c42c707
idle_time : 300
max_entries : 2048
ref_count : 2
need_revalidate : false
ports_by_ptr.n : 0
ports_by_usage.n: 0
br1 : (struct mac_learning *) 0x139b0b0
table.n : 0
secret : 0xcf8efaf8
idle_time : 300
max_entries : 2048
ref_count : 2
need_revalidate : false
ports_by_ptr.n : 0
ports_by_usage.n: 0
ovs_pvp_br0: (struct mac_learning *) 0x137b470
table.n : 4
secret : 0x623e75ad
idle_time : 300
max_entries : 2048
ref_count : 2
need_revalidate : false
ports_by_ptr.n : 4
ports_by_usage.n: 4
(gdb) ovs_show_fdb ovs_pvp_br0
table.n : 4
secret : 0x623e75ad
idle_time : 300
max_entries : 2048
ref_count : 2
need_revalidate : false
ports_by_ptr.n : 4
ports_by_usage.n: 4
FDB "lrus" table:
port VLAN MAC Age out @
----------------- ---- ----------------- ---------
02[vnet2] 0 52:54:00:b6:de:1e 81501
01[vnet0] 0 52:54:00:0b:60:6e 81501
03[vnet4] 0 52:54:00:89:32:4c 81501
0LOCAL[ovs_pvp_br 0 5e:26:7b:41:28:46 81501
Total MAC entries: 4
Current time is between 81198 and 81203 seconds.
Signed-off-by: Eelco Chaudron <echaudro@redhat.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Diffstat (limited to 'utilities/gdb/ovs_gdb.py')
-rw-r--r-- | utilities/gdb/ovs_gdb.py | 191 |
1 files changed, 188 insertions, 3 deletions
diff --git a/utilities/gdb/ovs_gdb.py b/utilities/gdb/ovs_gdb.py index 538383c72..65f9216d9 100644 --- a/utilities/gdb/ovs_gdb.py +++ b/utilities/gdb/ovs_gdb.py @@ -20,7 +20,7 @@ # # Notes: # It implements the following GDB commands: -# - ovs_dump_bridge [ports|wanted] +# - ovs_dump_bridge {ports|wanted} # - ovs_dump_bridge_ports <struct bridge *> # - ovs_dump_dp_netdev [ports] # - ovs_dump_dp_netdev_poll_threads <struct dp_netdev *> @@ -30,6 +30,7 @@ # - ovs_dump_netdev_provider # - ovs_dump_ovs_list <struct ovs_list *> {[<structure>] [<member>] {dump}]} # - ovs_dump_simap <struct simap *> +# - ovs_show_fdb {[<bridge_name>] {dbg} {hash}} # # Example: # $ gdb $(which ovs-vswitchd) $(pidof ovs-vswitchd) @@ -117,6 +118,28 @@ def get_global_variable(name): return gdb.parse_and_eval(name) +def get_time_msec(): + # There is no variable that stores the current time each iteration, + # to get a decent time time_now() value. For now we take the global + # "coverage_run_time" value, which is the current time + max 5 seconds + # (COVERAGE_RUN_INTERVAL) + return long(get_global_variable("coverage_run_time")), -5000 + + +def get_time_now(): + # See get_time_msec() above + return long(get_global_variable("coverage_run_time"))/1000, -5 + + +def eth_addr_to_string(eth_addr): + return "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}".format( + long(eth_addr['ea'][0]), + long(eth_addr['ea'][1]), + long(eth_addr['ea'][2]), + long(eth_addr['ea'][3]), + long(eth_addr['ea'][4]), + long(eth_addr['ea'][5])) + # # Class that will provide an iterator over an OVS cmap. # @@ -286,7 +309,7 @@ class ForEachLIST(): # class CmdDumpBridge(gdb.Command): """Dump all configured bridges. - Usage: ovs_dump_bridge [ports|wanted] + Usage: ovs_dump_bridge {ports|wanted} """ def __init__(self): super(CmdDumpBridge, self).__init__("ovs_dump_bridge", @@ -299,7 +322,7 @@ class CmdDumpBridge(gdb.Command): if len(arg_list) > 1 or \ (len(arg_list) == 1 and arg_list[0] != "ports" and arg_list[0] != "wanted"): - print("usage: ovs_dump_bridge [ports|wanted]") + print("usage: ovs_dump_bridge {ports|wanted}") return elif len(arg_list) == 1: if arg_list[0] == "ports": @@ -701,6 +724,167 @@ class CmdDumpSimap(gdb.Command): # +# Implements the GDB "ovs_show_fdb" command +# +class CmdShowFDB(gdb.Command): + """Show FDB information + Usage: ovs_show_fdb {<bridge_name> {dbg} {hash}} + + <bridge_name> : Optional bridge name, if not supplied FDB summary + information is displayed for all bridges. + dbg : Will show structure address information + hash : Will display the forwarding table using the hash + table, rather than the rlu list. + """ + + def __init__(self): + super(CmdShowFDB, self).__init__("ovs_show_fdb", + gdb.COMMAND_DATA) + + @staticmethod + def __get_port_name_num(mac_entry): + if mac_entry['mlport'] is not None: + port = mac_entry['mlport']['port'].cast( + gdb.lookup_type('struct ofbundle').pointer()) + + port_name = port['name'].string() + port_no = long(container_of( + port['ports']['next'], + gdb.lookup_type('struct ofport_dpif').pointer(), + 'bundle_node')['up']['ofp_port']) + + if port_no == 0xfff7: + port_no = "UNSET" + elif port_no == 0xfff8: + port_no = "IN_PORT" + elif port_no == 0xfff9: + port_no = "TABLE" + elif port_no == 0xfffa: + port_no = "NORMAL" + elif port_no == 0xfffb: + port_no = "FLOOD" + elif port_no == 0xfffc: + port_no = "ALL" + elif port_no == 0xfffd: + port_no = "CONTROLLER" + elif port_no == 0xfffe: + port_no = "LOCAL" + elif port_no == 0xffff: + port_no = "NONE" + else: + port_no = str(port_no) + else: + port_name = "-" + port_no = "?" + + return port_name, port_no + + @staticmethod + def display_ml_summary(ml, indent=0, dbg=False): + indent = " " * indent + if ml is None: + return + + if dbg: + print("[(struct mac_learning *) {}]".format(ml)) + + print("{}table.n : {}".format(indent, ml['table']['n'])) + print("{}secret : 0x{:x}".format(indent, long(ml['secret']))) + print("{}idle_time : {}".format(indent, ml['idle_time'])) + print("{}max_entries : {}".format(indent, ml['max_entries'])) + print("{}ref_count : {}".format(indent, ml['ref_cnt']['count'])) + print("{}need_revalidate : {}".format(indent, ml['need_revalidate'])) + print("{}ports_by_ptr.n : {}".format(indent, ml['ports_by_ptr']['n'])) + print("{}ports_by_usage.n: {}".format(indent, + ml['ports_by_usage']['n'])) + + @staticmethod + def display_mac_entry(mac_entry, indent=0, dbg=False): + port_name, port_no = CmdShowFDB.__get_port_name_num(mac_entry) + + line = "{}{:16.16} {:-4} {} {:-9}".format( + indent, + "{}[{}]".format(port_no, port_name), + long(mac_entry['vlan']), + eth_addr_to_string(mac_entry['mac']), + long(mac_entry['expires'])) + + if dbg: + line += " [(struct mac_entry *) {}]".format(mac_entry) + + print(line) + + @staticmethod + def display_ml_entries(ml, indent=0, hash=False, dbg=False): + indent = " " * indent + if ml is None: + return + + print("\n{}FDB \"{}\" table:".format(indent, + "lrus" if not hash else "hash")) + print("{}port VLAN MAC Age out @". + format(indent)) + print("{}----------------- ---- ----------------- ---------". + format(indent)) + + mac_entries = 0 + + if hash: + for mac_entry in ForEachHMAP(ml['table'], + "struct mac_entry", + "hmap_node"): + CmdShowFDB.display_mac_entry(mac_entry, len(indent), dbg) + mac_entries += 1 + else: + for mac_entry in ForEachLIST(ml['lrus'], + "struct mac_entry", + "lru_node"): + CmdShowFDB.display_mac_entry(mac_entry, len(indent), dbg) + mac_entries += 1 + + print("\nTotal MAC entries: {}".format(mac_entries)) + time_now = list(get_time_now()) + time_now[1] = time_now[0] + time_now[1] + print("\n{}Current time is between {} and {} seconds.\n". + format(indent, min(time_now[0], time_now[1]), + max(time_now[0], time_now[1]))) + + def invoke(self, arg, from_tty): + arg_list = gdb.string_to_argv(arg) + + all_ofproto_dpifs_by_name = get_global_variable( + 'all_ofproto_dpifs_by_name') + if all_ofproto_dpifs_by_name is None: + return + + all_name = dict() + max_name_len = 0 + for node in ForEachHMAP(all_ofproto_dpifs_by_name, + "struct ofproto_dpif", + "all_ofproto_dpifs_by_name_node"): + + all_name[node['up']['name'].string()] = node + if len(node['up']['name'].string()) > max_name_len: + max_name_len = len(node['up']['name'].string()) + + if len(arg_list) == 0: + for name in sorted(all_name.iterkeys()): + print("{}: (struct mac_learning *) {}". + format(name.ljust(max_name_len), + all_name[name]['ml'])) + + self.display_ml_summary(all_name[name]['ml'], 4) + else: + if not arg_list[0] in all_name: + print("ERROR: Given bridge name is not known!") + return + + ml = all_name[arg_list[0]]['ml'] + self.display_ml_summary(ml, 0, "dbg" in arg_list[1:]) + self.display_ml_entries(ml, 0, "hash" in arg_list[1:], + "dbg" in arg_list[1:]) + +# # Initialize all GDB commands # CmdDumpBridge() @@ -713,3 +897,4 @@ CmdDumpNetdev() CmdDumpNetdevProvider() CmdDumpOvsList() CmdDumpSimap() +CmdShowFDB() |