2
0
mirror of https://github.com/openvswitch/ovs synced 2025-10-27 15:18:06 +00:00

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>
This commit is contained in:
Eelco Chaudron
2018-06-20 11:04:03 +02:00
committed by Ben Pfaff
parent e02b6f8106
commit ef557e2c55

View File

@@ -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()