@@ -196,7 +196,7 @@ struct tun_flow_entry {
196
196
197
197
#define TUN_NUM_FLOW_ENTRIES 1024
198
198
199
- struct tun_steering_prog {
199
+ struct tun_prog {
200
200
struct rcu_head rcu ;
201
201
struct bpf_prog * prog ;
202
202
};
@@ -238,7 +238,13 @@ struct tun_struct {
238
238
u32 rx_batched ;
239
239
struct tun_pcpu_stats __percpu * pcpu_stats ;
240
240
struct bpf_prog __rcu * xdp_prog ;
241
- struct tun_steering_prog __rcu * steering_prog ;
241
+ 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 ;
242
248
};
243
249
244
250
bool tun_is_xdp_buff (void * ptr )
@@ -590,7 +596,7 @@ static u16 tun_automq_select_queue(struct tun_struct *tun, struct sk_buff *skb)
590
596
591
597
static u16 tun_ebpf_select_queue (struct tun_struct * tun , struct sk_buff * skb )
592
598
{
593
- struct tun_steering_prog * prog ;
599
+ struct tun_prog * prog ;
594
600
u16 ret = 0 ;
595
601
596
602
prog = rcu_dereference (tun -> steering_prog );
@@ -1036,12 +1042,25 @@ static void tun_automq_xmit(struct tun_struct *tun, struct sk_buff *skb)
1036
1042
#endif
1037
1043
}
1038
1044
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
+
1039
1057
/* Net device start xmit */
1040
1058
static netdev_tx_t tun_net_xmit (struct sk_buff * skb , struct net_device * dev )
1041
1059
{
1042
1060
struct tun_struct * tun = netdev_priv (dev );
1043
1061
int txq = skb -> queue_mapping ;
1044
1062
struct tun_file * tfile ;
1063
+ int len = skb -> len ;
1045
1064
1046
1065
rcu_read_lock ();
1047
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
1086
sk_filter (tfile -> socket .sk , skb ))
1068
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
1098
if (unlikely (skb_orphan_frags_rx (skb , GFP_ATOMIC )))
1071
1099
goto drop ;
1072
1100
@@ -2054,10 +2082,7 @@ static ssize_t tun_put_user(struct tun_struct *tun,
2054
2082
2055
2083
if (vlan_hlen ) {
2056
2084
int ret ;
2057
- struct {
2058
- __be16 h_vlan_proto ;
2059
- __be16 h_vlan_TCI ;
2060
- } veth ;
2085
+ struct veth veth ;
2061
2086
2062
2087
veth .h_vlan_proto = skb -> vlan_proto ;
2063
2088
veth .h_vlan_TCI = htons (skb_vlan_tag_get (skb ));
@@ -2184,19 +2209,18 @@ static ssize_t tun_chr_read_iter(struct kiocb *iocb, struct iov_iter *to)
2184
2209
return ret ;
2185
2210
}
2186
2211
2187
- static void tun_steering_prog_free (struct rcu_head * rcu )
2212
+ static void tun_prog_free (struct rcu_head * rcu )
2188
2213
{
2189
- struct tun_steering_prog * prog = container_of (rcu ,
2190
- struct tun_steering_prog , rcu );
2214
+ struct tun_prog * prog = container_of (rcu , struct tun_prog , rcu );
2191
2215
2192
2216
bpf_prog_destroy (prog -> prog );
2193
2217
kfree (prog );
2194
2218
}
2195
2219
2196
- static int __tun_set_steering_ebpf (struct tun_struct * tun ,
2197
- struct bpf_prog * prog )
2220
+ static int __tun_set_ebpf (struct tun_struct * tun , struct tun_prog * * prog_p ,
2221
+ struct bpf_prog * prog )
2198
2222
{
2199
- struct tun_steering_prog * old , * new = NULL ;
2223
+ struct tun_prog * old , * new = NULL ;
2200
2224
2201
2225
if (prog ) {
2202
2226
new = kmalloc (sizeof (* new ), GFP_KERNEL );
@@ -2206,13 +2230,13 @@ static int __tun_set_steering_ebpf(struct tun_struct *tun,
2206
2230
}
2207
2231
2208
2232
spin_lock_bh (& tun -> lock );
2209
- old = rcu_dereference_protected (tun -> steering_prog ,
2233
+ old = rcu_dereference_protected (* prog_p ,
2210
2234
lockdep_is_held (& tun -> lock ));
2211
- rcu_assign_pointer (tun -> steering_prog , new );
2235
+ rcu_assign_pointer (* prog_p , new );
2212
2236
spin_unlock_bh (& tun -> lock );
2213
2237
2214
2238
if (old )
2215
- call_rcu (& old -> rcu , tun_steering_prog_free );
2239
+ call_rcu (& old -> rcu , tun_prog_free );
2216
2240
2217
2241
return 0 ;
2218
2242
}
@@ -2225,7 +2249,8 @@ static void tun_free_netdev(struct net_device *dev)
2225
2249
free_percpu (tun -> pcpu_stats );
2226
2250
tun_flow_uninit (tun );
2227
2251
security_tun_dev_free_security (tun -> security );
2228
- __tun_set_steering_ebpf (tun , NULL );
2252
+ __tun_set_ebpf (tun , & tun -> steering_prog , NULL );
2253
+ __tun_set_ebpf (tun , & tun -> filter_prog , NULL );
2229
2254
}
2230
2255
2231
2256
static void tun_setup (struct net_device * dev )
@@ -2720,7 +2745,8 @@ static int tun_set_queue(struct file *file, struct ifreq *ifr)
2720
2745
return ret ;
2721
2746
}
2722
2747
2723
- static int tun_set_steering_ebpf (struct tun_struct * tun , void __user * data )
2748
+ static int tun_set_ebpf (struct tun_struct * tun , struct tun_prog * * prog_p ,
2749
+ void __user * data )
2724
2750
{
2725
2751
struct bpf_prog * prog ;
2726
2752
int fd ;
@@ -2736,7 +2762,7 @@ static int tun_set_steering_ebpf(struct tun_struct *tun, void __user *data)
2736
2762
return PTR_ERR (prog );
2737
2763
}
2738
2764
2739
- return __tun_set_steering_ebpf (tun , prog );
2765
+ return __tun_set_ebpf (tun , prog_p , prog );
2740
2766
}
2741
2767
2742
2768
static long __tun_chr_ioctl (struct file * file , unsigned int cmd ,
@@ -3016,7 +3042,11 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
3016
3042
break ;
3017
3043
3018
3044
case TUNSETSTEERINGEBPF :
3019
- ret = tun_set_steering_ebpf (tun , argp );
3045
+ ret = tun_set_ebpf (tun , & tun -> steering_prog , argp );
3046
+ break ;
3047
+
3048
+ case TUNSETFILTEREBPF :
3049
+ ret = tun_set_ebpf (tun , & tun -> filter_prog , argp );
3020
3050
break ;
3021
3051
3022
3052
default :
0 commit comments