From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.8 required=3.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY, SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 359A1C4360F for ; Wed, 20 Mar 2019 14:50:23 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id F3BDE2146E for ; Wed, 20 Mar 2019 14:50:22 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="QKdMx+4a" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728296AbfCTOuV (ORCPT ); Wed, 20 Mar 2019 10:50:21 -0400 Received: from mail-qt1-f196.google.com ([209.85.160.196]:45560 "EHLO mail-qt1-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728145AbfCTOuD (ORCPT ); Wed, 20 Mar 2019 10:50:03 -0400 Received: by mail-qt1-f196.google.com with SMTP id v20so2769661qtv.12 for ; Wed, 20 Mar 2019 07:50:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=8WXcS1KrE6vua5wx+Bvx3BW9RQeN93C5u2MIzbYeVsE=; b=QKdMx+4aZlCf5ZRuSeTAzURaz++FND9uOr8mYgUD3f+7Es19W0L2eSergn0JoCYkb8 p42PAjD8bb8fgdqutmFPu6tTwNjPZ8/a0vkSNRAePBFFIyZwdmmhKqZqsG9MkLcmvb+U ucVOmO5sjsrprLcMTnw2r5Ly7XUSWjLj1yfPpE7LZJ2nPLR64wjSfny7AA3OZwFrC4Gu +F5ATAb1pSdjhm3yrPQXM+P/TsOksFgDtBBrLsVzYZ2Fvy4F/G2KSEvjrf70ANbOQYk3 juKK3v1dE6MrovVF+tZRR2b/AQWhl05Jxa7Bw5FlXoeDAEqIJ1g+ursGWtqkGFjNoCky E5Sw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=8WXcS1KrE6vua5wx+Bvx3BW9RQeN93C5u2MIzbYeVsE=; b=fgw0vdjEFSD+hm44E/JqdufPjxjIJndhhujaGSxdTwVS/erfWIfUySjTKmypnpClTo YLtIkdSGG6ZaNBE+WsgHjWU/Q6OTZlMm2CD8hPBxpoYdOYRSV3WL1ZK6dazsglqUTQyT OJc2gpZhXXsEeWFGIv799xrZL+aoO4dRYJzWsdfMPdPngd+niGsn/gfu1p8RZ5cqw/lA LAH9HE8uzLsMf0gQbe3Uhpm8OxxYa7hHeVfEh/FhKhqxd4tn6INpRilpwU3Lu2q39O3d y3kKlA3asGqj/nZazd2tfuZTQKWN38vW7vV3e2c6ZSbvaDJhhwiAxNsfg7YrCgzg4fY9 Fu3w== X-Gm-Message-State: APjAAAXjH9BnneDSItgSOT0hk0QMiaQaFUv5SHv/vYXzDbDGZUAWvZva 6n8AGV3m3ky0AbLYkd0c296EkWt5 X-Google-Smtp-Source: APXvYqyS+XOi5Do5+vHrZ0IFXl3Mc3SAsffFSE4EuEPG6Oq6drC3QOccBBYrGa2dPtkpxfusOzpOXA== X-Received: by 2002:a0c:d0f8:: with SMTP id b53mr7027629qvh.46.1553093401557; Wed, 20 Mar 2019 07:50:01 -0700 (PDT) Received: from willemb1.nyc.corp.google.com ([2620:0:1003:315:3fa1:a34c:1128:1d39]) by smtp.gmail.com with ESMTPSA id x201sm1142257qkb.92.2019.03.20.07.50.00 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 20 Mar 2019 07:50:00 -0700 (PDT) From: Willem de Bruijn To: netdev@vger.kernel.org Cc: ast@kernel.org, daniel@iogearbox.net, sdf@google.com, posk@google.com, Willem de Bruijn Subject: [PATCH bpf-next 09/13] bpf: add bpf_skb_adjust_room encap flags Date: Wed, 20 Mar 2019 10:49:40 -0400 Message-Id: <20190320144944.147862-10-willemdebruijn.kernel@gmail.com> X-Mailer: git-send-email 2.21.0.225.g810b269d1ac-goog In-Reply-To: <20190320144944.147862-1-willemdebruijn.kernel@gmail.com> References: <20190320144944.147862-1-willemdebruijn.kernel@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Willem de Bruijn When pushing tunnel headers, annotate skbs in the same way as tunnel devices. For GSO packets, the network stack requires certain fields set to segment packets with tunnel headers. gro_gse_segment depends on transport and inner mac header, for instance. Add an option to pass this information. Remove the restriction on len_diff to network header length, which is too short, e.g., for GRE protocols. Signed-off-by: Willem de Bruijn --- include/uapi/linux/bpf.h | 14 +++++++++- net/core/filter.c | 58 +++++++++++++++++++++++++++++++++++++--- 2 files changed, 67 insertions(+), 5 deletions(-) diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index 0eda8f564a381..a444534cc88d7 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -2595,7 +2595,19 @@ enum bpf_func_id { /* BPF_FUNC_skb_adjust_room flags. */ #define BPF_F_ADJ_ROOM_FIXED_GSO (1ULL << 0) -#define BPF_F_ADJ_ROOM_MASK (BPF_F_ADJ_ROOM_FIXED_GSO) + +#define BPF_F_ADJ_ROOM_ENCAP_L3_IPV4 (1ULL << 1) +#define BPF_F_ADJ_ROOM_ENCAP_L3_IPV6 (1ULL << 2) +#define BPF_F_ADJ_ROOM_ENCAP_L3_MASK (BPF_F_ADJ_ROOM_ENCAP_L3_IPV4 | \ + BPF_F_ADJ_ROOM_ENCAP_L3_IPV6) + +#define BPF_F_ADJ_ROOM_ENCAP_L4_GRE (1ULL << 3) +#define BPF_F_ADJ_ROOM_ENCAP_L4_UDP (1ULL << 4) + +#define BPF_F_ADJ_ROOM_MASK (BPF_F_ADJ_ROOM_FIXED_GSO | \ + BPF_F_ADJ_ROOM_ENCAP_L3_MASK | \ + BPF_F_ADJ_ROOM_ENCAP_L4_GRE | \ + BPF_F_ADJ_ROOM_ENCAP_L4_UDP) /* Mode for BPF_FUNC_skb_adjust_room helper. */ enum bpf_adj_room_mode { diff --git a/net/core/filter.c b/net/core/filter.c index e346e48098000..6007b0b4bc0d7 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -2966,6 +2966,9 @@ static u32 bpf_skb_net_base_len(const struct sk_buff *skb) static int bpf_skb_net_grow(struct sk_buff *skb, u32 off, u32 len_diff, u64 flags) { + bool encap = flags & BPF_F_ADJ_ROOM_ENCAP_L3_MASK; + unsigned int gso_type = SKB_GSO_DODGY; + u16 mac_len, inner_net, inner_trans; int ret; if (skb_is_gso(skb) && !skb_is_gso_tcp(skb)) { @@ -2979,10 +2982,60 @@ static int bpf_skb_net_grow(struct sk_buff *skb, u32 off, u32 len_diff, if (unlikely(ret < 0)) return ret; + if (encap) { + if (skb->protocol != htons(ETH_P_IP) && + skb->protocol != htons(ETH_P_IPV6)) + return -ENOTSUPP; + + if (flags & BPF_F_ADJ_ROOM_ENCAP_L3_IPV4 && + flags & BPF_F_ADJ_ROOM_ENCAP_L3_IPV6) + return -EINVAL; + + if (flags & BPF_F_ADJ_ROOM_ENCAP_L4_GRE && + flags & BPF_F_ADJ_ROOM_ENCAP_L4_UDP) + return -EINVAL; + + if (skb->encapsulation) + return -EALREADY; + + mac_len = skb->network_header - skb->mac_header; + inner_net = skb->network_header; + inner_trans = skb->transport_header; + } + ret = bpf_skb_net_hdr_push(skb, off, len_diff); if (unlikely(ret < 0)) return ret; + if (encap) { + /* inner mac == inner_net on l3 encap */ + skb->inner_mac_header = inner_net; + skb->inner_network_header = inner_net; + skb->inner_transport_header = inner_trans; + skb_set_inner_protocol(skb, skb->protocol); + + skb->encapsulation = 1; + skb_set_network_header(skb, mac_len); + + if (flags & BPF_F_ADJ_ROOM_ENCAP_L4_UDP) + gso_type |= SKB_GSO_UDP_TUNNEL; + else if (flags & BPF_F_ADJ_ROOM_ENCAP_L4_GRE) + gso_type |= SKB_GSO_GRE; + else if (flags & BPF_F_ADJ_ROOM_ENCAP_L3_IPV6) + gso_type |= SKB_GSO_IPXIP6; + else + gso_type |= SKB_GSO_IPXIP4; + + if (flags & BPF_F_ADJ_ROOM_ENCAP_L4_GRE || + flags & BPF_F_ADJ_ROOM_ENCAP_L4_UDP) { + int nh_len = flags & BPF_F_ADJ_ROOM_ENCAP_L3_IPV6 ? + sizeof(struct ipv6hdr) : + sizeof(struct iphdr); + + skb_set_transport_header(skb, mac_len + nh_len); + } + } + if (skb_is_gso(skb)) { struct skb_shared_info *shinfo = skb_shinfo(skb); @@ -2991,7 +3044,7 @@ static int bpf_skb_net_grow(struct sk_buff *skb, u32 off, u32 len_diff, skb_decrease_gso_size(shinfo, len_diff); /* Header must be checked, and gso_segs recomputed. */ - shinfo->gso_type |= SKB_GSO_DODGY; + shinfo->gso_type |= gso_type; shinfo->gso_segs = 0; } @@ -3042,7 +3095,6 @@ static u32 __bpf_skb_max_len(const struct sk_buff *skb) BPF_CALL_4(bpf_skb_adjust_room, struct sk_buff *, skb, s32, len_diff, u32, mode, u64, flags) { - bool trans_same = skb->transport_header == skb->network_header; u32 len_cur, len_diff_abs = abs(len_diff); u32 len_min = bpf_skb_net_base_len(skb); u32 len_max = __bpf_skb_max_len(skb); @@ -3071,8 +3123,6 @@ BPF_CALL_4(bpf_skb_adjust_room, struct sk_buff *, skb, s32, len_diff, } len_cur = skb->len - skb_network_offset(skb); - if (skb_transport_header_was_set(skb) && !trans_same) - len_cur = skb_network_header_len(skb); if ((shrink && (len_diff_abs >= len_cur || len_cur - len_diff_abs < len_min)) || (!shrink && (skb->len + len_diff_abs > len_max && -- 2.21.0.225.g810b269d1ac-goog