From: Jesper Dangaard Brouer <brouer@redhat.com>
To: Daniel Borkmann <borkmann@iogearbox.net>,
Alexei Starovoitov <alexei.starovoitov@gmail.com>
Cc: brouer@redhat.com, BPF-dev-list <bpf@vger.kernel.org>,
"Toke Høiland-Jørgensen" <toke@redhat.com>,
"Matteo Croce" <mcroce@redhat.com>,
"Lorenzo Bianconi" <lorenzo.bianconi@redhat.com>,
"Ilias Apalodimas" <ilias.apalodimas@linaro.org>
Subject: Fighting BPF verifier to reach end-of-packet with XDP
Date: Fri, 1 May 2020 17:41:32 +0200 [thread overview]
Message-ID: <20200501174132.4388983e@carbon> (raw)
Hi Daniel,
One use-case for tail grow patchset, is to add a kernel timestamp at
XDP time in the extended tailroom of packet and return XDP_PASS to let
packet travel were it needs to go, and then via tcpdump we can extract
this timestamp. (E.g. this could improve on Ilias TSN measurements[2]).
I have implemented it here[3]. It works, but it is really a hassle to
convince the BPF verifier, that my program was safe. I use the
IP-headers total length to find the end-of-packet.
Is there an easier BPF way to move a data pointer to data_end?
Any suggestion on how I could extend the kernel (or verifier) to
provide easier access to the tailroom I grow?
[3] https://github.com/xdp-project/xdp-tutorial/blob/tailgrow01.public/packet04-tailgrow/xdp_prog_kern.c#L97-L115
[1] https://patchwork.ozlabs.org/project/netdev/list/?series=173782&state=%2A&archive=both
[2] https://github.com/xdp-project/xdp-project/blob/master/areas/arm64/xdp_for_tsn.org
- -
Best regards,
Jesper Dangaard Brouer
MSc.CS, Principal Kernel Engineer at Red Hat
LinkedIn: http://www.linkedin.com/in/brouer
Relevant code copy-pasted below, to make it easier to email comment:
SEC("xdp_tailgrow_parse")
int grow_parse(struct xdp_md *ctx)
{
void *data_end;
void *data;
int action = XDP_PASS;
int eth_type, ip_type;
struct hdr_cursor nh;
struct iphdr *iphdr;
struct ethhdr *eth;
__u16 ip_tot_len;
struct my_timestamp *ts;
/* Increase packet size (at tail) and reload data pointers */
__u8 offset = sizeof(*ts);
if (bpf_xdp_adjust_tail(ctx, offset))
goto out;
data_end = (void *)(long)ctx->data_end;
data = (void *)(long)ctx->data;
/* These keep track of the next header type and iterator pointer */
nh.pos = data;
eth_type = parse_ethhdr(&nh, data_end, ð);
if (eth_type < 0) {
action = XDP_ABORTED;
goto out;
}
if (eth_type == bpf_htons(ETH_P_IP)) {
ip_type = parse_iphdr(&nh, data_end, &iphdr);
} else {
action = XDP_PASS;
goto out;
}
/* Demo use-case: Add timestamp in extended tailroom to ICMP packets,
* before sending to network-stack via XDP_PASS. This can be
* captured via tcpdump, and provide earlier (XDP layer) timestamp.
*/
if (ip_type == IPPROTO_ICMP) {
/* Packet size in bytes, including IP header and data */
ip_tot_len = bpf_ntohs(iphdr->tot_len);
/*
* Tricks to get pass the verifier. Being allowed to use
* packet value iphdr->tot_len, involves bounding possible
* values to please verifier.
*/
if (ip_tot_len < 2) {
/* This check seems strange on unsigned ip_tot_len,
* but is needed, else verifier complains:
* "unbounded min value is not allowed"
*/
goto out;
}
ip_tot_len &= 0xFFF; /* Max 4095 */
/* Finding end of packet + offset, and bound access */
if ((void *)iphdr + ip_tot_len + offset > data_end) {
action = XDP_ABORTED;
goto out;
}
/* Point ts to end-of-packet, that have been offset extended */
ts = (void *)iphdr + ip_tot_len;
ts->magic = 0x5354; /* String "TS" in network-byte-order */
ts->time = bpf_ktime_get_ns();
}
out:
return xdp_stats_record_action(ctx, action);
}
next reply other threads:[~2020-05-01 15:41 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-05-01 15:41 Jesper Dangaard Brouer [this message]
2020-05-01 18:10 ` Fighting BPF verifier to reach end-of-packet with XDP David Ahern
2020-05-06 9:08 ` Jesper Dangaard Brouer
2020-05-06 9:28 ` Daniel Borkmann
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=20200501174132.4388983e@carbon \
--to=brouer@redhat.com \
--cc=alexei.starovoitov@gmail.com \
--cc=borkmann@iogearbox.net \
--cc=bpf@vger.kernel.org \
--cc=ilias.apalodimas@linaro.org \
--cc=lorenzo.bianconi@redhat.com \
--cc=mcroce@redhat.com \
--cc=toke@redhat.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.