OSDN Git Service

bpf: BPF-helper for MTU checking add length input
authorJesper Dangaard Brouer <brouer@redhat.com>
Mon, 8 Mar 2021 14:59:18 +0000 (15:59 +0100)
committerDaniel Borkmann <daniel@iogearbox.net>
Mon, 8 Mar 2021 21:44:33 +0000 (22:44 +0100)
The FIB lookup example[1] show how the IP-header field tot_len
(iph->tot_len) is used as input to perform the MTU check.

This patch extend the BPF-helper bpf_check_mtu() with the same ability
to provide the length as user parameter input, via mtu_len parameter.

This still needs to be done before the bpf_check_mtu() helper API
becomes frozen.

  [1] samples/bpf/xdp_fwd_kern.c

Fixes: 34b2021cc616 ("bpf: Add BPF-helper for MTU checking")
Signed-off-by: Jesper Dangaard Brouer <brouer@redhat.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: John Fastabend <john.fastabend@gmail.com>
Link: https://lore.kernel.org/bpf/161521555850.3515614.6533850861569774444.stgit@firesoul
include/uapi/linux/bpf.h
net/core/filter.c

index 79c8933..4ba4ef0 100644 (file)
@@ -3850,7 +3850,7 @@ union bpf_attr {
  *
  * long bpf_check_mtu(void *ctx, u32 ifindex, u32 *mtu_len, s32 len_diff, u64 flags)
  *     Description
- *             Check ctx packet size against exceeding MTU of net device (based
+ *             Check packet size against exceeding MTU of net device (based
  *             on *ifindex*).  This helper will likely be used in combination
  *             with helpers that adjust/change the packet size.
  *
@@ -3867,6 +3867,14 @@ union bpf_attr {
  *             against the current net device.  This is practical if this isn't
  *             used prior to redirect.
  *
+ *             On input *mtu_len* must be a valid pointer, else verifier will
+ *             reject BPF program.  If the value *mtu_len* is initialized to
+ *             zero then the ctx packet size is use.  When value *mtu_len* is
+ *             provided as input this specify the L3 length that the MTU check
+ *             is done against. Remember XDP and TC length operate at L2, but
+ *             this value is L3 as this correlate to MTU and IP-header tot_len
+ *             values which are L3 (similar behavior as bpf_fib_lookup).
+ *
  *             The Linux kernel route table can configure MTUs on a more
  *             specific per route level, which is not provided by this helper.
  *             For route level MTU checks use the **bpf_fib_lookup**\ ()
@@ -3891,11 +3899,9 @@ union bpf_attr {
  *
  *             On return *mtu_len* pointer contains the MTU value of the net
  *             device.  Remember the net device configured MTU is the L3 size,
- *             which is returned here and XDP and TX length operate at L2.
+ *             which is returned here and XDP and TC length operate at L2.
  *             Helper take this into account for you, but remember when using
- *             MTU value in your BPF-code.  On input *mtu_len* must be a valid
- *             pointer and be initialized (to zero), else verifier will reject
- *             BPF program.
+ *             MTU value in your BPF-code.
  *
  *     Return
  *             * 0 on success, and populate MTU value in *mtu_len* pointer.
index adfdad2..9323d34 100644 (file)
@@ -5658,7 +5658,7 @@ BPF_CALL_5(bpf_skb_check_mtu, struct sk_buff *, skb,
        if (unlikely(flags & ~(BPF_MTU_CHK_SEGS)))
                return -EINVAL;
 
-       if (unlikely(flags & BPF_MTU_CHK_SEGS && len_diff))
+       if (unlikely(flags & BPF_MTU_CHK_SEGS && (len_diff || *mtu_len)))
                return -EINVAL;
 
        dev = __dev_via_ifindex(dev, ifindex);
@@ -5668,7 +5668,11 @@ BPF_CALL_5(bpf_skb_check_mtu, struct sk_buff *, skb,
        mtu = READ_ONCE(dev->mtu);
 
        dev_len = mtu + dev->hard_header_len;
-       skb_len = skb->len + len_diff; /* minus result pass check */
+
+       /* If set use *mtu_len as input, L3 as iph->tot_len (like fib_lookup) */
+       skb_len = *mtu_len ? *mtu_len + dev->hard_header_len : skb->len;
+
+       skb_len += len_diff; /* minus result pass check */
        if (skb_len <= dev_len) {
                ret = BPF_MTU_CHK_RET_SUCCESS;
                goto out;
@@ -5713,6 +5717,10 @@ BPF_CALL_5(bpf_xdp_check_mtu, struct xdp_buff *, xdp,
        /* Add L2-header as dev MTU is L3 size */
        dev_len = mtu + dev->hard_header_len;
 
+       /* Use *mtu_len as input, L3 as iph->tot_len (like fib_lookup) */
+       if (*mtu_len)
+               xdp_len = *mtu_len + dev->hard_header_len;
+
        xdp_len += len_diff; /* minus result pass check */
        if (xdp_len > dev_len)
                ret = BPF_MTU_CHK_RET_FRAG_NEEDED;