From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754888AbdL2CpL (ORCPT ); Thu, 28 Dec 2017 21:45:11 -0500 Received: from mx1.redhat.com ([209.132.183.28]:39588 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754813AbdL2CpG (ORCPT ); Thu, 28 Dec 2017 21:45:06 -0500 From: Jason Wang To: netdev@vger.kernel.org, linux-kernel@vger.kernel.org Cc: mst@redhat.com, willemb@google.com, Jason Wang Subject: [PATCH net-next 2/2] tun: allow to attach ebpf socket filter Date: Fri, 29 Dec 2017 10:44:51 +0800 Message-Id: <1514515491-6041-3-git-send-email-jasowang@redhat.com> In-Reply-To: <1514515491-6041-1-git-send-email-jasowang@redhat.com> References: <1514515491-6041-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.32]); Fri, 29 Dec 2017 02:45:06 +0000 (UTC) Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org This patch allows userspace to attach eBPF filter to tun. This will allow to implement VM dataplane filtering in a more efficient way compared to cBPF filter. Signed-off-by: Jason Wang --- drivers/net/tun.c | 26 ++++++++++++++++++++++++++ include/uapi/linux/if_tun.h | 1 + 2 files changed, 27 insertions(+) diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 0853829..6e9452b 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -238,6 +238,7 @@ struct tun_struct { struct tun_pcpu_stats __percpu *pcpu_stats; struct bpf_prog __rcu *xdp_prog; struct tun_prog __rcu *steering_prog; + struct tun_prog __rcu *filter_prog; }; static int tun_napi_receive(struct napi_struct *napi, int budget) @@ -984,12 +985,25 @@ static void tun_automq_xmit(struct tun_struct *tun, struct sk_buff *skb) #endif } +static unsigned int run_ebpf_filter(struct tun_struct *tun, + struct sk_buff *skb, + int len) +{ + struct tun_prog *prog = rcu_dereference(tun->filter_prog); + + if (prog) + len = bpf_prog_run_clear_cb(prog->prog, skb); + + return len; +} + /* Net device start xmit */ static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev) { struct tun_struct *tun = netdev_priv(dev); int txq = skb->queue_mapping; struct tun_file *tfile; + int len = skb->len; rcu_read_lock(); tfile = rcu_dereference(tun->tfiles[txq]); @@ -1015,9 +1029,16 @@ static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev) sk_filter(tfile->socket.sk, skb)) goto drop; + len = run_ebpf_filter(tun, skb, len); + if (!len) + goto drop; + if (unlikely(skb_orphan_frags_rx(skb, GFP_ATOMIC))) goto drop; + if (pskb_trim(skb, len)) + goto drop; + skb_tx_timestamp(skb); /* Orphan the skb - required as we might hang on to it @@ -2068,6 +2089,7 @@ static void tun_free_netdev(struct net_device *dev) tun_flow_uninit(tun); security_tun_dev_free_security(tun->security); __tun_set_ebpf(tun, &tun->steering_prog, NULL); + __tun_set_ebpf(tun, &tun->filter_prog, NULL); } static void tun_setup(struct net_device *dev) @@ -2849,6 +2871,10 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd, ret = tun_set_ebpf(tun, &tun->steering_prog, argp); break; + case TUNSETFILTEREBPF: + ret = tun_set_ebpf(tun, &tun->filter_prog, argp); + break; + default: ret = -EINVAL; break; diff --git a/include/uapi/linux/if_tun.h b/include/uapi/linux/if_tun.h index fb38c17..ee432cd 100644 --- a/include/uapi/linux/if_tun.h +++ b/include/uapi/linux/if_tun.h @@ -58,6 +58,7 @@ #define TUNSETVNETBE _IOW('T', 222, int) #define TUNGETVNETBE _IOR('T', 223, int) #define TUNSETSTEERINGEBPF _IOR('T', 224, int) +#define TUNSETFILTEREBPF _IOR('T', 225, int) /* TUNSETIFF ifr flags */ #define IFF_TUN 0x0001 -- 2.7.4