[ovs-dev] [PATCH v2] utilities: Add another GDB macro for ovs-vswitchd
Eelco Chaudron
echaudro at redhat.com
Fri Nov 12 10:27:47 UTC 2021
Some small remaining comments, rest looks good!
On 5 Nov 2021, at 18:26, Mike Pattrick wrote:
> This commit adds a basic packet metadata macro to the already existing
> macros in ovs_gdb.py, ovs_dump_packets will print out information about
> one or more packets. It feeds packets into tcpdump, and the user can
> pass in tcpdump options to modify how packets are parsed or even write
> out packets to a pcap file.
>
> Example usage:
> (gdb) break fast_path_processing
> (gdb) commands
>> ovs_dump_packets packets_
>> continue
>> end
> (gdb) continue
>
> Thread 1 "ovs-vswitchd" hit Breakpoint 2, fast_path_processing ...
> 12:01:05.962485 ARP, Ethernet (len 6), IPv4 (len 4), Request who-has 10.1.1.1 tell 10.1.1.2, length 28
> Thread 1 "ovs-vswitchd" hit Breakpoint 1, fast_path_processing ...
> 12:01:05.981214 ARP, Ethernet (len 6), IPv4 (len 4), Reply 10.1.1.1 is-at a6:0f:c3:f0:5f:bd (oui Unknown), length 28
>
> Signed-off-by: Mike Pattrick <mkp at redhat.com>
> ---
> utilities/gdb/ovs_gdb.py | 102 ++++++++++++++++++++++++++++++++++++++-
> 1 file changed, 100 insertions(+), 2 deletions(-)
>
> diff --git a/utilities/gdb/ovs_gdb.py b/utilities/gdb/ovs_gdb.py
> index 0b2ecb81b..ee9160607 100644
> --- a/utilities/gdb/ovs_gdb.py
> +++ b/utilities/gdb/ovs_gdb.py
> @@ -29,6 +29,7 @@
> # - ovs_dump_netdev
> # - ovs_dump_netdev_provider
> # - ovs_dump_ovs_list <struct ovs_list *> {[<structure>] [<member>] {dump}]}
> +# - ovs_dump_packets <struct dp_packet_batch|struct dp_packet> [tcpdump options]
> # - ovs_dump_simap <struct simap *>
> # - ovs_dump_smap <struct smap *>
> # - ovs_dump_udpif_keys {<udpif_name>|<udpif_address>} {short}
> @@ -58,6 +59,9 @@
> import gdb
> import sys
> import uuid
> +import struct
Please keep imports in alphabetical order.
> +from scapy.layers.l2 import Ether
> +from scapy.utils import tcpdump
Not everybody might have/need scapy support. Maybe we can change it to something like:
try:
from scapy.layers.l2 import Ether
from scapy.utils import tcpdump
except ModuleNotFoundError:
print("WARNING: Can't find the Scapy Python module!")
print(" This is required for the ovs_dump_packets command.")
>
> #
> @@ -138,7 +142,7 @@ def get_time_msec():
>
> def get_time_now():
> # See get_time_msec() above
> - return int(get_global_variable("coverage_run_time"))/1000, -5
> + return int(get_global_variable("coverage_run_time")) / 1000, -5
>
>
> def eth_addr_to_string(eth_addr):
> @@ -156,7 +160,7 @@ def eth_addr_to_string(eth_addr):
> #
> class ProgressIndicator(object):
> def __init__(self, message=None):
> - self.spinner = "/-\|"
> + self.spinner = "/-\\|"
> self.spinner_index = 0
> self.message = message
>
> @@ -1306,6 +1310,99 @@ class CmdDumpOfpacts(gdb.Command):
> print("(struct ofpact *) {}: {}".format(node, node.dereference()))
>
>
> +#
> +# Implements the GDB "ovs_dump_packets" command
> +#
> +class CmdDumpPackets(gdb.Command):
> + """Dump metadata about dp_packets
> + Usage: ovs_dump_packets <struct dp_packet_batch|struct dp_packet> [tcpdump options]
> +
> + This command can take either a dp_packet_batch struct and print out metadata
> + about all packets in this batch, or a single dp_packet struct and print out
> + metadata about a single packet.
> +
> + Everything after the struct reference is passed into tcpdump.
> +
> + (gdb) ovs_dump_packets packets_
> + 12:01:05.981214 ARP, Ethernet (len 6), IPv4 (len 4), Reply 10.1.1.1 is-at a6:0f:c3:f0:5f:bd (oui Unknown), length 28
> + """
> + def __init__(self):
> + super().__init__("ovs_dump_packets", gdb.COMMAND_DATA)
> +
> + def invoke(self, arg, from_tty):
> + arg_list = gdb.string_to_argv(arg)
> + if len(arg_list) == 0:
> + print("Usage: ovs_dump_packets <struct dp_packet_batch|"
> + "struct dp_packet> [tcpdump options]")
Indent is not correct here.
> + return
> +
> + symb_name = arg_list[0]
> + tcpdump_args = arg_list[1:]
> +
> + val = gdb.parse_and_eval(symb_name)
> + while val.type.code == gdb.TYPE_CODE_PTR:
> + val = val.dereference()
> +
> + pkt_list = []
> + if str(val.type).startswith("struct dp_packet_batch"):
> + for idx in range(val['count']):
> + pkt_struct = val['packets'][idx].dereference()
> + pkt = self.extract_pkt(pkt_struct)
> + if pkt is None:
> + continue
> + pkt_list.append(pkt)
> + elif str(val.type) == "struct dp_packet":
> + pkt = self.extract_pkt(val)
> + if pkt is None:
> + return
> + pkt_list.append(pkt)
> + else:
> + print("Error, unsupported argument type:", str(val.type))
All errors are in the format print(“ERROR: unsupported argument type: {}”.format(str(val.type))
> + return
> +
> + tcpdump(pkt_list, args=tcpdump_args)
Wondering if we should supply the “-n” option if no options are given to speed up the actual display. But I’ll leave it up to you.
> +
> + def extract_pkt(self, pkt):
> + pkt_fields = pkt.type.keys()
> + if pkt['packet_type'] != 0:
> + return
> + if pkt['l3_ofs'] == 0xFFFF:
> + return
> +
> + if "mbuf" in pkt_fields:
> + if pkt['mbuf']['data_off'] == 0xFFFF:
> + return
> + eth_ptr = pkt['mbuf']['buf_addr']
> + eth_off = int(pkt['mbuf']['data_off'])
> + eth_len = int(pkt['mbuf']['pkt_len'])
> + else:
> + if pkt['data_ofs'] == 0xFFFF:
> + return
> + eth_ptr = pkt['base_']
> + eth_off = int(pkt['data_ofs'])
> + eth_len = int(pkt['size_'])
> +
Thanks for doing the above, so it will also work with core dumps!
> + if eth_ptr == 0 or eth_len < 1:
> + return
> +
> + # Extract packet
> + pkt_ptr = eth_ptr.cast(
> + gdb.lookup_type('uint8_t').pointer()
> + )
> + pkt_ptr += eth_off
> +
> + pkt_data = []
> + for idx in range(eth_len):
> + pkt_data.append(int(pkt_ptr[idx]))
> +
> + pkt_data = struct.pack("{}B".format(eth_len), *pkt_data)
> +
> + packet = Ether(pkt_data)
> + packet.len = int(eth_len)
> +
> + return packet
> +
> +
> #
> # Initialize all GDB commands
> #
> @@ -1319,6 +1416,7 @@ CmdDumpNetdev()
> CmdDumpNetdevProvider()
> CmdDumpOfpacts()
> CmdDumpOvsList()
> +CmdDumpPackets()
> CmdDumpSimap()
> CmdDumpSmap()
> CmdDumpUdpifKeys()
> --
> 2.30.2
>
>
> _______________________________________________
> dev mailing list
> dev at openvswitch.org
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
More information about the dev
mailing list