[ovs-dev] [PATCH] Utilities: Add the ovs_show_fdb command to gdb
Eelco Chaudron
echaudro at redhat.com
Wed Jun 20 09:04:03 UTC 2018
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 at redhat.com>
---
utilities/gdb/ovs_gdb.py | 191 ++++++++++++++++++++++++++++++++++++++-
1 file 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":
@@ -700,6 +723,167 @@ class CmdDumpSimap(gdb.Command):
values[name], values[name]))
+#
+# 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
#
@@ -713,3 +897,4 @@ CmdDumpNetdev()
CmdDumpNetdevProvider()
CmdDumpOvsList()
CmdDumpSimap()
+CmdShowFDB()
--
2.17.1
More information about the dev
mailing list