[U-Boot] [PATCH] net: introduce packet capture support
Ramon Fried
rfried.dev at gmail.com
Fri Jun 21 14:02:20 UTC 2019
On Fri, Jun 21, 2019 at 2:40 PM Alex Marginean <alexm.osslist at gmail.com> wrote:
>
> Hi Ramon,
>
> On 6/14/2019 9:18 AM, Ramon Fried wrote:
> > Add support for capturing ethernet packets and storing
> > them in memory in PCAP(2.4) format, later to be analyzed by
> > any PCAP viewer software (IE. Wireshark)
> >
> > This feature greatly assist debugging network issues such
> > as detecting dropped packets, packet corruption etc.
> >
> > Signed-off-by: Ramon Fried <rfried.dev at gmail.com>
> > ---
> >
> > include/net.h | 29 ++++++++++++++++++
> > net/Kconfig | 22 ++++++++++++++
> > net/Makefile | 1 +
> > net/net.c | 11 +++++++
> > net/pcap.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++
> > 5 files changed, 146 insertions(+)
> > create mode 100644 net/pcap.c
>
> Reviewed-by: Alex Marginean <alexm.osslist at gmail.com>
> Tested-by: Alex Marginean <alexm.osslist at gmail.com>
>
> There's one typo in filling the packet time which makes it come out
> wrong, see below.
>
> This is a really nice feature, I suggest you consider adding a pcap
> command to:
> - set start address, making NET_PCAP_ADDR optional,
> - start/stop capture,
> - restart the capture from the beginning of the buffer,
> - maybe print the current state - buffer address, pcap size, on/off
> state.
>
> I used tftpput to copy the pcap out, fatwrite should also work.
>
> >
> > diff --git a/include/net.h b/include/net.h
> > index 44b32385c4..d1dc864896 100644
> > --- a/include/net.h
> > +++ b/include/net.h
> > @@ -630,6 +630,31 @@ bool arp_is_waiting(void); /* Waiting for ARP reply? */
> > void net_set_icmp_handler(rxhand_icmp_f *f); /* Set ICMP RX handler */
> > void net_set_timeout_handler(ulong, thand_f *);/* Set timeout handler */
> >
> > +/* PCAP extension */
> > +
> > +/**
> > + * pcap_init() - Initialize PCAP memory buffer
> > + *
> > + * @return 0 on success, -ERROR on error
> > + */
> > +int pcap_init(void);
> > +
> > +/**
> > + * pcap_post() - Post a packet to PCAP file
> > + *
> > + * @packet: packet to post
> > + * @len: packet length in bytes
> > + * @return 0 on success, -ERROR on error
> > + */
> > +int pcap_post(const void *packet, size_t len);
> > +
> > +/**
> > + * pcap_size() - get size of PCAP file
> > + *
> > + * @return size of PCAP file in bytes
> > + */
> > +unsigned int pcap_size(void);
> > +
> > /* Network loop state */
> > enum net_loop_state {
> > NETLOOP_CONTINUE,
> > @@ -658,6 +683,10 @@ static inline void net_send_packet(uchar *pkt, int len)
> > {
> > /* Currently no way to return errors from eth_send() */
> > (void) eth_send(pkt, len);
> > +
> > +#if defined(CONFIG_NET_PCAP)
> > + pcap_post(pkt, len);
> > +#endif
> > }
> >
> > /*
> > diff --git a/net/Kconfig b/net/Kconfig
> > index f2363e5256..8b8ab88e57 100644
> > --- a/net/Kconfig
> > +++ b/net/Kconfig
> > @@ -8,6 +8,28 @@ menuconfig NET
> >
> > if NET
> >
> > +config NET_PCAP
> > + bool "PCAP network capture"
> > + help
> > + Selecting this will capture all Ethernet packets and store
> > + them in a PCAP formated file later to be analyzed by PCAP
> > + reader application (IE. WireShark).
> > +
> > +config NET_PCAP_ADDR
> > + hex "Address of PCAP file in memory"
> > + depends on NET_PCAP
> > + help
> > + Sets the address of the PCAP file in physical memory.
> > +
> > +config NET_PCAP_SIZE
> > + hex "Size of PCAP file"
> > + depends on NET_PCAP
> > + default 0x100000
> > + help
> > + Sets the maximum size of PCAP file in bytes.
> > + When it fills up completely, it will stop capturing
> > + packets silently.
> > +
> > config NET_RANDOM_ETHADDR
> > bool "Random ethaddr if unset"
> > help
> > diff --git a/net/Makefile b/net/Makefile
> > index ce36362168..85103fee93 100644
> > --- a/net/Makefile
> > +++ b/net/Makefile
> > @@ -18,6 +18,7 @@ endif
> > obj-$(CONFIG_NET) += eth_common.o
> > obj-$(CONFIG_CMD_LINK_LOCAL) += link_local.o
> > obj-$(CONFIG_NET) += net.o
> > +obj-$(CONFIG_NET_PCAP) += pcap.o
> > obj-$(CONFIG_CMD_NFS) += nfs.o
> > obj-$(CONFIG_CMD_PING) += ping.o
> > obj-$(CONFIG_CMD_RARP) += rarp.o
> > diff --git a/net/net.c b/net/net.c
> > index 58b0417cbe..d0bdf8fe20 100644
> > --- a/net/net.c
> > +++ b/net/net.c
> > @@ -387,6 +387,10 @@ void net_init(void)
> >
> > /* Only need to setup buffer pointers once. */
> > first_call = 0;
> > +
> > +#if defined(CONFIG_NET_PCAP)
> > + pcap_init();
> > +#endif
> > }
> >
> > net_init_loop();
> > @@ -671,6 +675,10 @@ done:
> > net_set_icmp_handler(NULL);
> > #endif
> > net_set_state(prev_net_state);
> > +
> > +#if defined(CONFIG_NET_PCAP)
> > + printf("PCAP len: 0x%x\n", pcap_size());
> > +#endif
> > return ret;
> > }
> >
> > @@ -1083,6 +1091,9 @@ void net_process_received_packet(uchar *in_packet, int len)
> >
> > debug_cond(DEBUG_NET_PKT, "packet received\n");
> >
> > +#if defined(CONFIG_NET_PCAP)
> > + pcap_post(in_packet, len);
> > +#endif
> > net_rx_packet = in_packet;
> > net_rx_packet_len = len;
> > et = (struct ethernet_hdr *)in_packet;
> > diff --git a/net/pcap.c b/net/pcap.c
> > new file mode 100644
> > index 0000000000..dadfa7563b
> > --- /dev/null
> > +++ b/net/pcap.c
> > @@ -0,0 +1,83 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * Copyright 2019 Ramon Fried <rfried.dev at gmail.com>
> > + */
> > +
> > +#include <common.h>
> > +#include <net.h>
> > +#include <time.h>
> > +#include <asm/io.h>
> > +
> > +#define LINKTYPE_ETHERNET 1
> > +
> > +static void *buf;
> > +static unsigned int pos;
> > +
> > +struct pcap_header {
> > + u32 magic;
> > + u16 version_major;
> > + u16 version_minor;
> > + s32 thiszone;
> > + u32 sigfigs;
> > + u32 snaplen;
> > + u32 network;
> > +};
> > +
> > +struct pcap_packet_header {
> > + u32 ts_sec;
> > + u32 ts_usec;
> > + u32 incl_len;
> > + u32 orig_len;
> > +};
> > +
> > +static struct pcap_header file_header = {
> > + .magic = 0xa1b2c3d4,
> > + .version_major = 2,
> > + .version_minor = 4,
> > + .snaplen = 65535,
> > + .network = LINKTYPE_ETHERNET,
> > +};
> > +
> > +int pcap_init(void)
> > +{
> > + buf = map_physmem(CONFIG_NET_PCAP_ADDR, CONFIG_NET_PCAP_SIZE, 0);
> > + if (!buf) {
> > + printf("Failed mapping PCAP memory\n");
> > + return -ENOMEM;
> > + }
> > +
> > + printf("PCAP capture initialized: addr: 0x%lx max length: 0x%x\n",
> > + (unsigned long)buf, CONFIG_NET_PCAP_SIZE);
> > +
> > + memcpy(buf, &file_header, sizeof(file_header));
> > + pos += sizeof(file_header);
> > + return 0;
> > +}
> > +
> > +int pcap_post(const void *packet, size_t len)
> > +{
> > + struct pcap_packet_header header;
> > + u64 cur_time = timer_get_us();
> > +
> > + if (!buf)
> > + return -ENODEV;
> > + if ((pos + len + sizeof(header)) >= CONFIG_NET_PCAP_SIZE)
> > + return -ENOMEM;
> > +
> > + header.ts_sec = cur_time / 1000000;
> > + header.ts_sec = cur_time % 1000000;
>
> This should be header.ts_usec.
Right !
Thanks,
Ramon
>
> Thank you!
> Alex
>
> > + header.incl_len = len;
> > + header.orig_len = len;
> > +
> > + memcpy(buf + pos, &header, sizeof(header));
> > + pos += sizeof(header);
> > + memcpy(buf + pos, packet, len);
> > + pos += len;
> > +
> > + return 0;
> > +}
> > +
> > +unsigned int pcap_size(void)
> > +{
> > + return pos;
> > +}
> >
>
More information about the U-Boot
mailing list