aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason Wang <jasowang@redhat.com>2018-01-16 03:31:02 -0500
committerDavid S. Miller <davem@davemloft.net>2018-01-17 15:32:10 -0500
commitaff3d70a07fffc0abb53663e4a4acb059d2f36af (patch)
tree6274d9253d5cd93105e5759e616212876ceb2ec9
parentcd5681d7d8903bf43a571aaf96cf6d2e2e00118c (diff)
tun: allow to attach ebpf socket filter
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 by allowing either qemu or libvirt to attach eBPF filter to tun. Signed-off-by: Jason Wang <jasowang@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/tun.c38
-rw-r--r--include/uapi/linux/if_tun.h1
2 files changed, 35 insertions, 4 deletions
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 76197ede22a9..170a3e89b5af 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -239,6 +239,12 @@ struct tun_struct {
239 struct tun_pcpu_stats __percpu *pcpu_stats; 239 struct tun_pcpu_stats __percpu *pcpu_stats;
240 struct bpf_prog __rcu *xdp_prog; 240 struct bpf_prog __rcu *xdp_prog;
241 struct tun_prog __rcu *steering_prog; 241 struct tun_prog __rcu *steering_prog;
242 struct tun_prog __rcu *filter_prog;
243};
244
245struct veth {
246 __be16 h_vlan_proto;
247 __be16 h_vlan_TCI;
242}; 248};
243 249
244bool tun_is_xdp_buff(void *ptr) 250bool tun_is_xdp_buff(void *ptr)
@@ -1036,12 +1042,25 @@ static void tun_automq_xmit(struct tun_struct *tun, struct sk_buff *skb)
1036#endif 1042#endif
1037} 1043}
1038 1044
1045static unsigned int run_ebpf_filter(struct tun_struct *tun,
1046 struct sk_buff *skb,
1047 int len)
1048{
1049 struct tun_prog *prog = rcu_dereference(tun->filter_prog);
1050
1051 if (prog)
1052 len = bpf_prog_run_clear_cb(prog->prog, skb);
1053
1054 return len;
1055}
1056
1039/* Net device start xmit */ 1057/* Net device start xmit */
1040static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev) 1058static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev)
1041{ 1059{
1042 struct tun_struct *tun = netdev_priv(dev); 1060 struct tun_struct *tun = netdev_priv(dev);
1043 int txq = skb->queue_mapping; 1061 int txq = skb->queue_mapping;
1044 struct tun_file *tfile; 1062 struct tun_file *tfile;
1063 int len = skb->len;
1045 1064
1046 rcu_read_lock(); 1065 rcu_read_lock();
1047 tfile = rcu_dereference(tun->tfiles[txq]); 1066 tfile = rcu_dereference(tun->tfiles[txq]);
@@ -1067,6 +1086,15 @@ static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev)
1067 sk_filter(tfile->socket.sk, skb)) 1086 sk_filter(tfile->socket.sk, skb))
1068 goto drop; 1087 goto drop;
1069 1088
1089 len = run_ebpf_filter(tun, skb, len);
1090
1091 /* Trim extra bytes since we may insert vlan proto & TCI
1092 * in tun_put_user().
1093 */
1094 len -= skb_vlan_tag_present(skb) ? sizeof(struct veth) : 0;
1095 if (len <= 0 || pskb_trim(skb, len))
1096 goto drop;
1097
1070 if (unlikely(skb_orphan_frags_rx(skb, GFP_ATOMIC))) 1098 if (unlikely(skb_orphan_frags_rx(skb, GFP_ATOMIC)))
1071 goto drop; 1099 goto drop;
1072 1100
@@ -2054,10 +2082,7 @@ static ssize_t tun_put_user(struct tun_struct *tun,
2054 2082
2055 if (vlan_hlen) { 2083 if (vlan_hlen) {
2056 int ret; 2084 int ret;
2057 struct { 2085 struct veth veth;
2058 __be16 h_vlan_proto;
2059 __be16 h_vlan_TCI;
2060 } veth;
2061 2086
2062 veth.h_vlan_proto = skb->vlan_proto; 2087 veth.h_vlan_proto = skb->vlan_proto;
2063 veth.h_vlan_TCI = htons(skb_vlan_tag_get(skb)); 2088 veth.h_vlan_TCI = htons(skb_vlan_tag_get(skb));
@@ -2225,6 +2250,7 @@ static void tun_free_netdev(struct net_device *dev)
2225 tun_flow_uninit(tun); 2250 tun_flow_uninit(tun);
2226 security_tun_dev_free_security(tun->security); 2251 security_tun_dev_free_security(tun->security);
2227 __tun_set_ebpf(tun, &tun->steering_prog, NULL); 2252 __tun_set_ebpf(tun, &tun->steering_prog, NULL);
2253 __tun_set_ebpf(tun, &tun->filter_prog, NULL);
2228} 2254}
2229 2255
2230static void tun_setup(struct net_device *dev) 2256static void tun_setup(struct net_device *dev)
@@ -3019,6 +3045,10 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
3019 ret = tun_set_ebpf(tun, &tun->steering_prog, argp); 3045 ret = tun_set_ebpf(tun, &tun->steering_prog, argp);
3020 break; 3046 break;
3021 3047
3048 case TUNSETFILTEREBPF:
3049 ret = tun_set_ebpf(tun, &tun->filter_prog, argp);
3050 break;
3051
3022 default: 3052 default:
3023 ret = -EINVAL; 3053 ret = -EINVAL;
3024 break; 3054 break;
diff --git a/include/uapi/linux/if_tun.h b/include/uapi/linux/if_tun.h
index fb38c1797131..ee432cd3018c 100644
--- a/include/uapi/linux/if_tun.h
+++ b/include/uapi/linux/if_tun.h
@@ -58,6 +58,7 @@
58#define TUNSETVNETBE _IOW('T', 222, int) 58#define TUNSETVNETBE _IOW('T', 222, int)
59#define TUNGETVNETBE _IOR('T', 223, int) 59#define TUNGETVNETBE _IOR('T', 223, int)
60#define TUNSETSTEERINGEBPF _IOR('T', 224, int) 60#define TUNSETSTEERINGEBPF _IOR('T', 224, int)
61#define TUNSETFILTEREBPF _IOR('T', 225, int)
61 62
62/* TUNSETIFF ifr flags */ 63/* TUNSETIFF ifr flags */
63#define IFF_TUN 0x0001 64#define IFF_TUN 0x0001