On 19 Nov 2021, at 15:35, 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 Guess you removed the > before the commands from the previous commit, guess another mail client issue. However should not matter, it’s just a commit message. Rest looks good to me (one small nit below, maybe can be fixed on commit) Acked-by: Eelco Chaudron <echau...@redhat.com> > (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 <m...@redhat.com> > --- > utilities/gdb/ovs_gdb.py | 114 ++++++++++++++++++++++++++++++++++++++- > 1 file changed, 112 insertions(+), 2 deletions(-) > > diff --git a/utilities/gdb/ovs_gdb.py b/utilities/gdb/ovs_gdb.py > index 0b2ecb81b..9da83920b 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} > @@ -56,8 +57,15 @@ > # ... > # > import gdb > +import struct > import sys > import uuid > +try: > + from scapy.layers.l2 import Ether > + from scapy.utils import tcpdump > +except ModuleNotFoundError: > + Ether = None > + tcpdump = None > > > # > @@ -138,7 +146,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 +164,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 +1314,107 @@ 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. If nothing > + is passed in as a tcpdump option, the default is "-n". > + > + (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): > + if Ether is None: > + print("ERROR: This command requires scapy to be installed.") > + > + 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]") > + return > + > + symb_name = arg_list[0] > + tcpdump_args = arg_list[1:] > + > + if not tcpdump_args: > + # Add a sane default > + tcpdump_args = ["-n"] > + > + 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: > {}".format(str(val.type))) Guess you format to fix the general ERROR format, i.e.: print(“ERROR: Unsupported argument type: {}".format(str(val.type))) > + return > + > + tcpdump(pkt_list, args=tcpdump_args) > + > + 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_']) > + > + 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 +1428,7 @@ CmdDumpNetdev() > CmdDumpNetdevProvider() > CmdDumpOfpacts() > CmdDumpOvsList() > +CmdDumpPackets() > CmdDumpSimap() > CmdDumpSmap() > CmdDumpUdpifKeys() > -- > 2.27.0 _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev