summaryrefslogtreecommitdiff
path: root/utilities/gdb/ovs_gdb.py
diff options
context:
space:
mode:
authorEelco Chaudron <echaudro@redhat.com>2018-06-20 11:04:03 +0200
committerBen Pfaff <blp@ovn.org>2018-06-20 10:20:06 -0700
commitef557e2c55444782cc800196ff6cbf253c57faa3 (patch)
tree3653b4e8472b62bbdc2d2b575e24191431aac2c4 /utilities/gdb/ovs_gdb.py
parente02b6f8106929de0c2cc673052c9ea9aa5c221b9 (diff)
downloadopenvswitch-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.py191
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()