History

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.

Jason Wang committed 8 years ago

Commit aff3d701 parent cd5681d2 files · +35 −4Browse files

Unified · Split

2 files
  1. drivers/net/tun.c +34 −4
  2. include/uapi/linux/if_tun.h +1 −0
drivers/net/tun.c+34−4
@@ -239,6 +239,12 @@ struct tun_struct { · 238 unmodified lines
239239 struct tun_pcpu_stats __percpu *pcpu_stats;
240240 struct bpf_prog __rcu *xdp_prog;
241241 struct tun_prog __rcu *steering_prog;
242+ struct tun_prog __rcu *filter_prog;
243+};
244+
245+struct veth {
246+ __be16 h_vlan_proto;
247+ __be16 h_vlan_TCI;
242248 };
243249
244250 bool tun_is_xdp_buff(void *ptr)
@@ -1036,12 +1042,25 @@ static void tun_automq_xmit(struct tun_struct *tun, struct sk_buff *skb) · 791 unmodified lines
10361042 #endif
10371043 }
10381044
1045+static 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+
10391057 /* Net device start xmit */
10401058 static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev)
10411059 {
10421060 struct tun_struct *tun = netdev_priv(dev);
10431061 int txq = skb->queue_mapping;
10441062 struct tun_file *tfile;
1063+ int len = skb->len;
10451064
10461065 rcu_read_lock();
10471066 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) · 19 unmodified lines
10671086 sk_filter(tfile->socket.sk, skb))
10681087 goto drop;
10691088
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+
10701098 if (unlikely(skb_orphan_frags_rx(skb, GFP_ATOMIC)))
10711099 goto drop;
10721100
@@ -2054,10 +2082,7 @@ static ssize_t tun_put_user(struct tun_struct *tun, · 981 unmodified lines
20542082
20552083 if (vlan_hlen) {
20562084 int ret;
2057− struct {
2058− __be16 h_vlan_proto;
2059− __be16 h_vlan_TCI;
2060− } veth;
2085+ struct veth veth;
20612086
20622087 veth.h_vlan_proto = skb->vlan_proto;
20632088 veth.h_vlan_TCI = htons(skb_vlan_tag_get(skb));
@@ -2225,6 +2250,7 @@ static void tun_free_netdev(struct net_device *dev) · 161 unmodified lines
22252250 tun_flow_uninit(tun);
22262251 security_tun_dev_free_security(tun->security);
22272252 __tun_set_ebpf(tun, &tun->steering_prog, NULL);
2253+ __tun_set_ebpf(tun, &tun->filter_prog, NULL);
22282254 }
22292255
22302256 static void tun_setup(struct net_device *dev)
@@ -3019,6 +3045,10 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd, · 788 unmodified lines
30193045 ret = tun_set_ebpf(tun, &tun->steering_prog, argp);
30203046 break;
30213047
3048+ case TUNSETFILTEREBPF:
3049+ ret = tun_set_ebpf(tun, &tun->filter_prog, argp);
3050+ break;
3051+
30223052 default:
30233053 ret = -EINVAL;
30243054 break;
include/uapi/linux/if_tun.h+1−0
@@ -58,6 +58,7 @@ · 57 unmodified lines
5858 #define TUNSETVNETBE _IOW('T', 222, int)
5959 #define TUNGETVNETBE _IOR('T', 223, int)
6060 #define TUNSETSTEERINGEBPF _IOR('T', 224, int)
61+#define TUNSETFILTEREBPF _IOR('T', 225, int)
6162
6263 /* TUNSETIFF ifr flags */
6364 #define IFF_TUN 0x0001