From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753274AbdIDDgS (ORCPT ); Sun, 3 Sep 2017 23:36:18 -0400 Received: from mx1.redhat.com ([209.132.183.28]:49128 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753198AbdIDDgR (ORCPT ); Sun, 3 Sep 2017 23:36:17 -0400 DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com D5D3383F3D Authentication-Results: ext-mx03.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx03.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=jasowang@redhat.com From: Jason Wang To: netdev@vger.kernel.org, linux-kernel@vger.kernel.org Cc: mst@redhat.com, Jason Wang , Jakub Kicinski Subject: [PATCH net-next 1/2] tun: reserve extra headroom only when XDP is set Date: Mon, 4 Sep 2017 11:36:08 +0800 Message-Id: <1504496169-31190-1-git-send-email-jasowang@redhat.com> X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.27]); Mon, 04 Sep 2017 03:36:17 +0000 (UTC) Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org We reserve headroom unconditionally which could cause unnecessary stress on socket memory accounting because of increased trusesize. Fix this by only reserve extra headroom when XDP is set. Cc: Jakub Kicinski Signed-off-by: Jason Wang --- drivers/net/tun.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 06e8f0b..80ac18f 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -108,7 +108,7 @@ do { \ #endif #define TUN_HEADROOM 256 -#define TUN_RX_PAD (NET_IP_ALIGN + NET_SKB_PAD + TUN_HEADROOM) +#define TUN_RX_PAD (NET_IP_ALIGN + NET_SKB_PAD) /* TUN device flags */ @@ -1272,25 +1272,35 @@ static struct sk_buff *tun_build_skb(struct tun_struct *tun, struct page_frag *alloc_frag = ¤t->task_frag; struct sk_buff *skb; struct bpf_prog *xdp_prog; - int buflen = SKB_DATA_ALIGN(len + TUN_RX_PAD) + - SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); + int buflen = SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); unsigned int delta = 0; char *buf; size_t copied; bool xdp_xmit = false; - int err; + int err, pad = TUN_RX_PAD; + + rcu_read_lock(); + xdp_prog = rcu_dereference(tun->xdp_prog); + if (xdp_prog) + pad += TUN_HEADROOM; + buflen += SKB_DATA_ALIGN(len + pad); + rcu_read_unlock(); if (unlikely(!skb_page_frag_refill(buflen, alloc_frag, GFP_KERNEL))) return ERR_PTR(-ENOMEM); buf = (char *)page_address(alloc_frag->page) + alloc_frag->offset; copied = copy_page_from_iter(alloc_frag->page, - alloc_frag->offset + TUN_RX_PAD, + alloc_frag->offset + pad, len, from); if (copied != len) return ERR_PTR(-EFAULT); - if (hdr->gso_type) + /* There's a small window that XDP may be set after the check + * of xdp_prog above, this should be rare and for simplicity + * we do XDP on skb in case the headroom is not enough. + */ + if (hdr->gso_type || !xdp_prog) *generic_xdp = 1; else *generic_xdp = 0; @@ -1303,7 +1313,7 @@ static struct sk_buff *tun_build_skb(struct tun_struct *tun, u32 act; xdp.data_hard_start = buf; - xdp.data = buf + TUN_RX_PAD; + xdp.data = buf + pad; xdp.data_end = xdp.data + len; orig_data = xdp.data; act = bpf_prog_run_xdp(xdp_prog, &xdp); @@ -1339,7 +1349,7 @@ static struct sk_buff *tun_build_skb(struct tun_struct *tun, return ERR_PTR(-ENOMEM); } - skb_reserve(skb, TUN_RX_PAD - delta); + skb_reserve(skb, pad - delta); skb_put(skb, len + delta); get_page(alloc_frag->page); alloc_frag->offset += buflen; -- 2.7.4