From: Martin KaFai Lau <martin.lau@linux.dev>
To: Kui-Feng Lee <thinker.li@gmail.com>
Cc: bpf@vger.kernel.org, ast@kernel.org, song@kernel.org,
kernel-team@meta.com, andrii@kernel.org, sdf@fomichev.me,
sinquersw@gmail.com, kuifeng@meta.com
Subject: Re: [PATCH bpf-next v2 1/4] selftests/bpf: Add traffic monitor functions.
Date: Wed, 24 Jul 2024 12:08:18 -0700 [thread overview]
Message-ID: <51966001-297e-4dae-a7b8-41cdef0fd35c@linux.dev> (raw)
In-Reply-To: <20240723182439.1434795-2-thinker.li@gmail.com>
On 7/23/24 11:24 AM, Kui-Feng Lee wrote:
> Add functions that capture packets and print log in the background. They
> are supposed to be used for debugging flaky network test cases. A monitored
> test case should call traffic_monitor_start() to start a thread to capture
> packets in the background for a given namespace and call
> traffic_monitor_stop() to stop capturing.
>
> IPv4 TCP packet: 127.0.0.1:48165 -> 127.0.0.1:36707, len 68, ifindex 1, SYN
> IPv4 TCP packet: 127.0.0.1:36707 -> 127.0.0.1:48165, len 60, ifindex 1, SYN, ACK
> IPv4 TCP packet: 127.0.0.1:48165 -> 127.0.0.1:36707, len 60, ifindex 1, ACK
> IPv4 TCP packet: 127.0.0.1:36707 -> 127.0.0.1:48165, len 52, ifindex 1, ACK
> IPv4 TCP packet: 127.0.0.1:48165 -> 127.0.0.1:36707, len 52, ifindex 1, FIN, ACK
> IPv4 TCP packet: 127.0.0.1:36707 -> 127.0.0.1:48165, len 52, ifindex 1, RST, ACK
> Packet file: packets-2172-86.log
> #280/87 select_reuseport/sockhash IPv4/TCP LOOPBACK test_detach_bpf:OK
>
> The above is the output of an example. It shows the packets of a connection
> and the name of the file that contains captured packets in the directory
> /tmp/tmon_pcap. The file can be loaded by tcpdump or wireshark.
>
> This feature only works if TRAFFIC_MONITOR variable has been passed to
> build BPF selftests. For example,
>
> make TRAFFIC_MONITOR=1 -C tools/testing/selftests/bpf
If bpf CI does not have libpcap, it is better to get bpf CI ready first/soon.
[ ... ]
> +/* Show the information of the transport layer in the packet */
> +static void show_transport(const u_char *packet, u16 len, u32 ifindex,
> + const char *src_addr, const char *dst_addr,
> + u16 proto, bool ipv6)
> +{
> + struct udphdr *udp;
> + struct tcphdr *tcp;
> + u16 src_port, dst_port;
> + const char *transport_str;
> +
> + if (proto == IPPROTO_UDP) {
> + udp = (struct udphdr *)packet;
> + src_port = ntohs(udp->source);
> + dst_port = ntohs(udp->dest);
> + transport_str = "UDP";
> + } else if (proto == IPPROTO_TCP) {
> + tcp = (struct tcphdr *)packet;
> + src_port = ntohs(tcp->source);
> + dst_port = ntohs(tcp->dest);
> + transport_str = "TCP"
> +;
> + } else {
It will be useful to at least print the ICMP[46] also. Some tests use ping to
test. For IPv6, printing the ICMPv6 messages will be useful for debugging, e.g.
the neigh discovery. The icmp type (and code?) should be good enough.
That should be enough to begin with. The pcap dumped file can be used for the rest.
Thanks for switching to libpcap. It is easier to handle the captured packets in
different ways.
> + printf("%s (proto %d): %s -> %s, ifindex %d\n",
> + ipv6 ? "IPv6" : "IPv4", proto, src_addr, dst_addr, ifindex);
> + return;
> + }
> +
> + if (ipv6)
> + printf("IPv6 %s packet: [%s]:%d -> [%s]:%d, len %d, ifindex %d",
It will be useful to print the ifname also such that easier for human parsing.
It should be possible by if_indextoname (cheap enough?) if libpcap doesn't have
it. It could be something for a later followup though. Mostly nit here.
> + transport_str, src_addr, src_port,
> + dst_addr, dst_port, len, ifindex);
> + else
> + printf("IPv4 %s packet: %s:%d -> %s:%d, len %d, ifindex %d",
> + transport_str, src_addr, src_port,
> + dst_addr, dst_port, len, ifindex);
> +
> + if (proto == IPPROTO_TCP) {
> + if (tcp->fin)
> + printf(", FIN");
> + if (tcp->syn)
> + printf(", SYN");
> + if (tcp->rst)
> + printf(", RST");
> + if (tcp->ack)
> + printf(", ACK");
> + }
> +
> + printf("\n");
> +}
[ ... ]
> +/* Start to monitor the network traffic in the given network namespace.
> + *
> + * netns: the name of the network namespace to monitor. If NULL, the
> + * current network namespace is monitored.
> + *
> + * This function will start a thread to capture packets going through NICs
> + * in the give network namespace.
> + */
> +struct tmonitor_ctx *traffic_monitor_start(const char *netns)
There is opportunity to make the traffic monitoring easier for tests that create
its own netns which I hope most of the networking tests fall into this bucket
now. Especially for tests that create multiple netns such that the test does not
have to start/stop for each individual netns.
May be adding an API like "struct nstoken *netns_new(const char *netns_name)".
The netns_new() will create the netns and (optionally) start the monitoring
thread also. It will need another "void netns_free(struct nstoken *nstoken)" to
stop the thread and remove the netns. The "struct tmonitor_ctx" probably makes
sense to be embedded into "struct nstoken" if we go with this new API.
This will need some changes to the tests creating netns but it probably should
be obvious change considering most test do "ip netns add..." and then
open_netns(). It can start with the flaky test at hand first like tc_redirect.
May be a little more changes for the test using "unshare(CLONE_NEWNET)" but
should not be too bad either. This can be done only when we need to turn on
libpcap to debug that test.
Also, when the test is flaky, make it easier for people not familiar with the
codes of the networking test to turn on traffic monitoring without changing the
test code. May be in a libpcap.list file (in parallel to the existing DENYLIST)?
For the tests without having its own netns, they can either move to netns (which
I think it is a good thing to do) or use the traffic_monitor_start/stop()
manually by changing the testing code,
or a better way is to ask test_progs do it for the host netns (init_netns)
automatically for all tests in the libpcap.list.
wdyt?
> +{
> + struct tmonitor_ctx *ctx = NULL;
> + struct nstoken *nstoken = NULL;
> + int pipefd[2] = {-1, -1};
> + static int tmon_seq;
> + int r;
> +
> + if (netns) {
> + nstoken = open_netns(netns);
> + if (!nstoken)
> + return NULL;
> + }
> + ctx = malloc(sizeof(*ctx));
> + if (!ctx) {
> + log_err("Failed to malloc ctx");
> + goto fail_ctx;
> + }
> + memset(ctx, 0, sizeof(*ctx));
> +
> + snprintf(ctx->pkt_fname, sizeof(ctx->pkt_fname),
> + PCAP_DIR "/packets-%d-%d.log", getpid(), tmon_seq++);
nit. I wonder if it is useful to also have the netns name in the filename?
Not sure if it is more useful to have the test_num and subtest_num instead of
pid. Probably doable from looking at test__start_subtest().
next prev parent reply other threads:[~2024-07-24 19:08 UTC|newest]
Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-07-23 18:24 [PATCH bpf-next v2 0/4] monitor network traffic for flaky test cases Kui-Feng Lee
2024-07-23 18:24 ` [PATCH bpf-next v2 1/4] selftests/bpf: Add traffic monitor functions Kui-Feng Lee
2024-07-23 22:03 ` Kui-Feng Lee
2024-07-24 15:22 ` Stanislav Fomichev
2024-07-24 15:46 ` Kui-Feng Lee
2024-07-24 19:08 ` Martin KaFai Lau [this message]
2024-07-25 1:44 ` Martin KaFai Lau
2024-07-25 22:47 ` Kui-Feng Lee
2024-07-26 0:23 ` Martin KaFai Lau
2024-07-23 18:24 ` [PATCH bpf-next v2 2/4] selftests/bpf: Monitor traffic for tc_redirect/tc_redirect_dtime Kui-Feng Lee
2024-07-24 8:36 ` Geliang Tang
2024-07-24 16:24 ` Kui-Feng Lee
2024-07-24 15:26 ` Stanislav Fomichev
2024-07-24 18:04 ` Kui-Feng Lee
2024-07-24 22:13 ` Stanislav Fomichev
2024-07-23 18:24 ` [PATCH bpf-next v2 3/4] selftests/bpf: Monitor traffic for sockmap_listen Kui-Feng Lee
2024-07-24 9:32 ` Geliang Tang
2024-07-24 16:24 ` Kui-Feng Lee
2024-07-24 18:11 ` Andrii Nakryiko
2024-07-23 18:24 ` [PATCH bpf-next v2 4/4] selftests/bpf: Monitor traffic for select_reuseport Kui-Feng Lee
2024-07-24 9:33 ` Geliang Tang
2024-07-23 22:01 ` [PATCH bpf-next v2 0/4] monitor network traffic for flaky test cases Kui-Feng Lee
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=51966001-297e-4dae-a7b8-41cdef0fd35c@linux.dev \
--to=martin.lau@linux.dev \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=kernel-team@meta.com \
--cc=kuifeng@meta.com \
--cc=sdf@fomichev.me \
--cc=sinquersw@gmail.com \
--cc=song@kernel.org \
--cc=thinker.li@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox