Blame view

drivers/net/macvtap.c 31.7 KB
20d29d7a9   Arnd Bergmann   net: macvtap driver
1
2
  #include <linux/etherdevice.h>
  #include <linux/if_macvlan.h>
f09e2249c   Basil Gor   macvtap: restore ...
3
  #include <linux/if_vlan.h>
20d29d7a9   Arnd Bergmann   net: macvtap driver
4
5
6
7
8
9
10
11
12
  #include <linux/interrupt.h>
  #include <linux/nsproxy.h>
  #include <linux/compat.h>
  #include <linux/if_tun.h>
  #include <linux/module.h>
  #include <linux/skbuff.h>
  #include <linux/cache.h>
  #include <linux/sched.h>
  #include <linux/types.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
13
  #include <linux/slab.h>
20d29d7a9   Arnd Bergmann   net: macvtap driver
14
15
  #include <linux/wait.h>
  #include <linux/cdev.h>
404015308   Al Viro   security: trim se...
16
  #include <linux/idr.h>
20d29d7a9   Arnd Bergmann   net: macvtap driver
17
  #include <linux/fs.h>
6c36d2e26   Herbert Xu   macvtap: Use iove...
18
  #include <linux/uio.h>
20d29d7a9   Arnd Bergmann   net: macvtap driver
19
20
21
22
  
  #include <net/net_namespace.h>
  #include <net/rtnetlink.h>
  #include <net/sock.h>
b9fb9ee07   Arnd Bergmann   macvtap: add GSO/...
23
  #include <linux/virtio_net.h>
362899b87   Jason Wang   macvtap: switch t...
24
  #include <linux/skb_array.h>
20d29d7a9   Arnd Bergmann   net: macvtap driver
25
26
27
28
29
30
31
32
33
34
  
  /*
   * A macvtap queue is the central object of this driver, it connects
   * an open character device to a macvlan interface. There can be
   * multiple queues on one interface, which map back to queues
   * implemented in hardware on the underlying device.
   *
   * macvtap_proto is used to allocate queues through the sock allocation
   * mechanism.
   *
20d29d7a9   Arnd Bergmann   net: macvtap driver
35
36
37
38
   */
  struct macvtap_queue {
  	struct sock sk;
  	struct socket sock;
438154823   Eric Dumazet   net: sock_def_rea...
39
  	struct socket_wq wq;
55afbd081   Michael S. Tsirkin   macvtap: add ioct...
40
  	int vnet_hdr_sz;
13707f9e5   Eric Dumazet   drivers/net: remo...
41
  	struct macvlan_dev __rcu *vlan;
20d29d7a9   Arnd Bergmann   net: macvtap driver
42
  	struct file *file;
b9fb9ee07   Arnd Bergmann   macvtap: add GSO/...
43
  	unsigned int flags;
376b1aabe   Jason Wang   macvtap: eliminat...
44
  	u16 queue_index;
815f236d6   Jason Wang   macvtap: add TUNS...
45
46
  	bool enabled;
  	struct list_head next;
362899b87   Jason Wang   macvtap: switch t...
47
  	struct skb_array skb_array;
20d29d7a9   Arnd Bergmann   net: macvtap driver
48
  };
01b07fb35   Michael S. Tsirkin   macvtap: drop bro...
49
50
51
  #define MACVTAP_FEATURES (IFF_VNET_HDR | IFF_MULTI_QUEUE)
  
  #define MACVTAP_VNET_LE 0x80000000
8b8e658b1   Greg Kurz   macvtap/tun: cros...
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
  #define MACVTAP_VNET_BE 0x40000000
  
  #ifdef CONFIG_TUN_VNET_CROSS_LE
  static inline bool macvtap_legacy_is_little_endian(struct macvtap_queue *q)
  {
  	return q->flags & MACVTAP_VNET_BE ? false :
  		virtio_legacy_is_little_endian();
  }
  
  static long macvtap_get_vnet_be(struct macvtap_queue *q, int __user *sp)
  {
  	int s = !!(q->flags & MACVTAP_VNET_BE);
  
  	if (put_user(s, sp))
  		return -EFAULT;
  
  	return 0;
  }
  
  static long macvtap_set_vnet_be(struct macvtap_queue *q, int __user *sp)
  {
  	int s;
  
  	if (get_user(s, sp))
  		return -EFAULT;
  
  	if (s)
  		q->flags |= MACVTAP_VNET_BE;
  	else
  		q->flags &= ~MACVTAP_VNET_BE;
  
  	return 0;
  }
  #else
  static inline bool macvtap_legacy_is_little_endian(struct macvtap_queue *q)
  {
  	return virtio_legacy_is_little_endian();
  }
  
  static long macvtap_get_vnet_be(struct macvtap_queue *q, int __user *argp)
  {
  	return -EINVAL;
  }
  
  static long macvtap_set_vnet_be(struct macvtap_queue *q, int __user *argp)
  {
  	return -EINVAL;
  }
  #endif /* CONFIG_TUN_VNET_CROSS_LE */
6ae7feb31   Michael S. Tsirkin   macvtap: TUN_VNET...
101

5b11e15f2   Greg Kurz   macvtap: introduc...
102
103
  static inline bool macvtap_is_little_endian(struct macvtap_queue *q)
  {
7d8241095   Greg Kurz   virtio: add expli...
104
  	return q->flags & MACVTAP_VNET_LE ||
8b8e658b1   Greg Kurz   macvtap/tun: cros...
105
  		macvtap_legacy_is_little_endian(q);
5b11e15f2   Greg Kurz   macvtap: introduc...
106
  }
6ae7feb31   Michael S. Tsirkin   macvtap: TUN_VNET...
107
108
109
  
  static inline u16 macvtap16_to_cpu(struct macvtap_queue *q, __virtio16 val)
  {
5b11e15f2   Greg Kurz   macvtap: introduc...
110
  	return __virtio16_to_cpu(macvtap_is_little_endian(q), val);
6ae7feb31   Michael S. Tsirkin   macvtap: TUN_VNET...
111
112
113
114
  }
  
  static inline __virtio16 cpu_to_macvtap16(struct macvtap_queue *q, u16 val)
  {
5b11e15f2   Greg Kurz   macvtap: introduc...
115
  	return __cpu_to_virtio16(macvtap_is_little_endian(q), val);
6ae7feb31   Michael S. Tsirkin   macvtap: TUN_VNET...
116
  }
20d29d7a9   Arnd Bergmann   net: macvtap driver
117
118
119
120
121
122
123
  static struct proto macvtap_proto = {
  	.name = "macvtap",
  	.owner = THIS_MODULE,
  	.obj_size = sizeof (struct macvtap_queue),
  };
  
  /*
e09eff7fc   Eric W. Biederman   macvtap: Fix the ...
124
   * Variables for dealing with macvtaps device numbers.
20d29d7a9   Arnd Bergmann   net: macvtap driver
125
   */
1ebed71ae   David S. Miller   macvtap: Use dev_...
126
  static dev_t macvtap_major;
e09eff7fc   Eric W. Biederman   macvtap: Fix the ...
127
128
129
  #define MACVTAP_NUM_DEVS (1U << MINORBITS)
  static DEFINE_MUTEX(minor_lock);
  static DEFINE_IDR(minor_idr);
97bc3633b   Shirley Ma   macvtap: macvtapT...
130
  #define GOODCOPY_LEN 128
17af2bce8   Marc Angel   macvtap: add name...
131
132
133
134
135
136
137
138
139
140
141
142
  static const void *macvtap_net_namespace(struct device *d)
  {
  	struct net_device *dev = to_net_dev(d->parent);
  	return dev_net(dev);
  }
  
  static struct class macvtap_class = {
  	.name = "macvtap",
  	.owner = THIS_MODULE,
  	.ns_type = &net_ns_type_operations,
  	.namespace = macvtap_net_namespace,
  };
20d29d7a9   Arnd Bergmann   net: macvtap driver
143
  static struct cdev macvtap_cdev;
501c774cb   Arnd Bergmann   net/macvtap: add ...
144
  static const struct proto_ops macvtap_socket_ops;
2be5c7679   Vlad Yasevich   macvtap: Let TUNS...
145
  #define TUN_OFFLOADS (NETIF_F_HW_CSUM | NETIF_F_TSO_ECN | NETIF_F_TSO | \
e3e3c423f   Vlad Yasevich   Revert "drivers/n...
146
  		      NETIF_F_TSO6 | NETIF_F_UFO)
2be5c7679   Vlad Yasevich   macvtap: Let TUNS...
147
  #define RX_OFFLOADS (NETIF_F_GRO | NETIF_F_LRO)
f23d538bc   Jason Wang   macvtap: unbreak ...
148
  #define TAP_FEATURES (NETIF_F_GSO | NETIF_F_SG | NETIF_F_FRAGLIST)
a567dd625   Vlad Yasevich   macvtap: simplify...
149

6acf54f1c   Vlad Yasevich   macvtap: Add supp...
150
151
152
153
  static struct macvlan_dev *macvtap_get_vlan_rcu(const struct net_device *dev)
  {
  	return rcu_dereference(dev->rx_handler_data);
  }
20d29d7a9   Arnd Bergmann   net: macvtap driver
154
155
  /*
   * RCU usage:
02df55d28   Arnd Bergmann   macvtap: rework o...
156
157
   * The macvtap_queue and the macvlan_dev are loosely coupled, the
   * pointers from one to the other can only be read while rcu_read_lock
441ac0fca   Vlad Yasevich   macvtap: Convert ...
158
   * or rtnl is held.
20d29d7a9   Arnd Bergmann   net: macvtap driver
159
   *
02df55d28   Arnd Bergmann   macvtap: rework o...
160
161
162
163
   * Both the file and the macvlan_dev hold a reference on the macvtap_queue
   * through sock_hold(&q->sk). When the macvlan_dev goes away first,
   * q->vlan becomes inaccessible. When the files gets closed,
   * macvtap_get_queue() fails.
20d29d7a9   Arnd Bergmann   net: macvtap driver
164
   *
02df55d28   Arnd Bergmann   macvtap: rework o...
165
166
167
168
   * There may still be references to the struct sock inside of the
   * queue from outbound SKBs, but these never reference back to the
   * file or the dev. The data structure is freed through __sk_free
   * when both our references and any pending SKBs are gone.
20d29d7a9   Arnd Bergmann   net: macvtap driver
169
   */
20d29d7a9   Arnd Bergmann   net: macvtap driver
170

815f236d6   Jason Wang   macvtap: add TUNS...
171
  static int macvtap_enable_queue(struct net_device *dev, struct file *file,
20d29d7a9   Arnd Bergmann   net: macvtap driver
172
173
174
  				struct macvtap_queue *q)
  {
  	struct macvlan_dev *vlan = netdev_priv(dev);
815f236d6   Jason Wang   macvtap: add TUNS...
175
  	int err = -EINVAL;
441ac0fca   Vlad Yasevich   macvtap: Convert ...
176
  	ASSERT_RTNL();
815f236d6   Jason Wang   macvtap: add TUNS...
177
178
179
180
181
182
183
184
185
186
187
  
  	if (q->enabled)
  		goto out;
  
  	err = 0;
  	rcu_assign_pointer(vlan->taps[vlan->numvtaps], q);
  	q->queue_index = vlan->numvtaps;
  	q->enabled = true;
  
  	vlan->numvtaps++;
  out:
815f236d6   Jason Wang   macvtap: add TUNS...
188
189
  	return err;
  }
40b8fe45d   Vlad Yasevich   macvtap: Fix race...
190
  /* Requires RTNL */
815f236d6   Jason Wang   macvtap: add TUNS...
191
192
193
194
  static int macvtap_set_queue(struct net_device *dev, struct file *file,
  			     struct macvtap_queue *q)
  {
  	struct macvlan_dev *vlan = netdev_priv(dev);
20d29d7a9   Arnd Bergmann   net: macvtap driver
195

815f236d6   Jason Wang   macvtap: add TUNS...
196
  	if (vlan->numqueues == MAX_MACVTAP_QUEUES)
40b8fe45d   Vlad Yasevich   macvtap: Fix race...
197
  		return -EBUSY;
20d29d7a9   Arnd Bergmann   net: macvtap driver
198

02df55d28   Arnd Bergmann   macvtap: rework o...
199
  	rcu_assign_pointer(q->vlan, vlan);
376b1aabe   Jason Wang   macvtap: eliminat...
200
  	rcu_assign_pointer(vlan->taps[vlan->numvtaps], q);
02df55d28   Arnd Bergmann   macvtap: rework o...
201
  	sock_hold(&q->sk);
20d29d7a9   Arnd Bergmann   net: macvtap driver
202
203
  
  	q->file = file;
376b1aabe   Jason Wang   macvtap: eliminat...
204
  	q->queue_index = vlan->numvtaps;
815f236d6   Jason Wang   macvtap: add TUNS...
205
  	q->enabled = true;
02df55d28   Arnd Bergmann   macvtap: rework o...
206
  	file->private_data = q;
815f236d6   Jason Wang   macvtap: add TUNS...
207
  	list_add_tail(&q->next, &vlan->queue_list);
20d29d7a9   Arnd Bergmann   net: macvtap driver
208

1565c7c1c   Krishna Kumar   macvtap: Implemen...
209
  	vlan->numvtaps++;
815f236d6   Jason Wang   macvtap: add TUNS...
210
  	vlan->numqueues++;
1565c7c1c   Krishna Kumar   macvtap: Implemen...
211

40b8fe45d   Vlad Yasevich   macvtap: Fix race...
212
  	return 0;
20d29d7a9   Arnd Bergmann   net: macvtap driver
213
  }
441ac0fca   Vlad Yasevich   macvtap: Convert ...
214
  static int macvtap_disable_queue(struct macvtap_queue *q)
815f236d6   Jason Wang   macvtap: add TUNS...
215
216
217
  {
  	struct macvlan_dev *vlan;
  	struct macvtap_queue *nq;
441ac0fca   Vlad Yasevich   macvtap: Convert ...
218
  	ASSERT_RTNL();
815f236d6   Jason Wang   macvtap: add TUNS...
219
220
  	if (!q->enabled)
  		return -EINVAL;
441ac0fca   Vlad Yasevich   macvtap: Convert ...
221
  	vlan = rtnl_dereference(q->vlan);
815f236d6   Jason Wang   macvtap: add TUNS...
222
223
224
  	if (vlan) {
  		int index = q->queue_index;
  		BUG_ON(index >= vlan->numvtaps);
441ac0fca   Vlad Yasevich   macvtap: Convert ...
225
  		nq = rtnl_dereference(vlan->taps[vlan->numvtaps - 1]);
815f236d6   Jason Wang   macvtap: add TUNS...
226
227
228
229
230
231
232
233
234
235
236
  		nq->queue_index = index;
  
  		rcu_assign_pointer(vlan->taps[index], nq);
  		RCU_INIT_POINTER(vlan->taps[vlan->numvtaps - 1], NULL);
  		q->enabled = false;
  
  		vlan->numvtaps--;
  	}
  
  	return 0;
  }
20d29d7a9   Arnd Bergmann   net: macvtap driver
237
  /*
02df55d28   Arnd Bergmann   macvtap: rework o...
238
239
240
   * The file owning the queue got closed, give up both
   * the reference that the files holds as well as the
   * one from the macvlan_dev if that still exists.
20d29d7a9   Arnd Bergmann   net: macvtap driver
241
242
243
   *
   * Using the spinlock makes sure that we don't get
   * to the queue again after destroying it.
20d29d7a9   Arnd Bergmann   net: macvtap driver
244
   */
02df55d28   Arnd Bergmann   macvtap: rework o...
245
  static void macvtap_put_queue(struct macvtap_queue *q)
20d29d7a9   Arnd Bergmann   net: macvtap driver
246
  {
02df55d28   Arnd Bergmann   macvtap: rework o...
247
  	struct macvlan_dev *vlan;
20d29d7a9   Arnd Bergmann   net: macvtap driver
248

441ac0fca   Vlad Yasevich   macvtap: Convert ...
249
250
  	rtnl_lock();
  	vlan = rtnl_dereference(q->vlan);
02df55d28   Arnd Bergmann   macvtap: rework o...
251
  	if (vlan) {
815f236d6   Jason Wang   macvtap: add TUNS...
252
  		if (q->enabled)
441ac0fca   Vlad Yasevich   macvtap: Convert ...
253
  			BUG_ON(macvtap_disable_queue(q));
376b1aabe   Jason Wang   macvtap: eliminat...
254

815f236d6   Jason Wang   macvtap: add TUNS...
255
  		vlan->numqueues--;
2cfa5a047   Eric Dumazet   net: treewide use...
256
  		RCU_INIT_POINTER(q->vlan, NULL);
02df55d28   Arnd Bergmann   macvtap: rework o...
257
  		sock_put(&q->sk);
815f236d6   Jason Wang   macvtap: add TUNS...
258
  		list_del_init(&q->next);
20d29d7a9   Arnd Bergmann   net: macvtap driver
259
  	}
441ac0fca   Vlad Yasevich   macvtap: Convert ...
260
  	rtnl_unlock();
20d29d7a9   Arnd Bergmann   net: macvtap driver
261
262
263
264
265
266
  
  	synchronize_rcu();
  	sock_put(&q->sk);
  }
  
  /*
1565c7c1c   Krishna Kumar   macvtap: Implemen...
267
268
269
270
271
   * Select a queue based on the rxq of the device on which this packet
   * arrived. If the incoming device is not mq, calculate a flow hash
   * to select a queue. If all fails, find the first available queue.
   * Cache vlan->numvtaps since it can become zero during the execution
   * of this function.
20d29d7a9   Arnd Bergmann   net: macvtap driver
272
273
274
275
276
   */
  static struct macvtap_queue *macvtap_get_queue(struct net_device *dev,
  					       struct sk_buff *skb)
  {
  	struct macvlan_dev *vlan = netdev_priv(dev);
1565c7c1c   Krishna Kumar   macvtap: Implemen...
277
  	struct macvtap_queue *tap = NULL;
815f236d6   Jason Wang   macvtap: add TUNS...
278
279
280
281
282
  	/* Access to taps array is protected by rcu, but access to numvtaps
  	 * isn't. Below we use it to lookup a queue, but treat it as a hint
  	 * and validate that the result isn't NULL - in case we are
  	 * racing against queue removal.
  	 */
ed0483fa0   Jason Wang   macvtap: fix a po...
283
  	int numvtaps = ACCESS_ONCE(vlan->numvtaps);
1565c7c1c   Krishna Kumar   macvtap: Implemen...
284
285
286
287
  	__u32 rxq;
  
  	if (!numvtaps)
  		goto out;
1b16bf42d   Jason Wang   macvtap: avoid ha...
288
289
  	if (numvtaps == 1)
  		goto single;
ef0002b57   Krishna Kumar   macvtap: Fix macv...
290
  	/* Check if we can use flow to select a queue */
3958afa1b   Tom Herbert   net: Change skb_g...
291
  	rxq = skb_get_hash(skb);
ef0002b57   Krishna Kumar   macvtap: Fix macv...
292
293
  	if (rxq) {
  		tap = rcu_dereference(vlan->taps[rxq % numvtaps]);
376b1aabe   Jason Wang   macvtap: eliminat...
294
  		goto out;
ef0002b57   Krishna Kumar   macvtap: Fix macv...
295
  	}
1565c7c1c   Krishna Kumar   macvtap: Implemen...
296
297
  	if (likely(skb_rx_queue_recorded(skb))) {
  		rxq = skb_get_rx_queue(skb);
20d29d7a9   Arnd Bergmann   net: macvtap driver
298

1565c7c1c   Krishna Kumar   macvtap: Implemen...
299
300
301
302
  		while (unlikely(rxq >= numvtaps))
  			rxq -= numvtaps;
  
  		tap = rcu_dereference(vlan->taps[rxq]);
376b1aabe   Jason Wang   macvtap: eliminat...
303
  		goto out;
1565c7c1c   Krishna Kumar   macvtap: Implemen...
304
  	}
1b16bf42d   Jason Wang   macvtap: avoid ha...
305
  single:
376b1aabe   Jason Wang   macvtap: eliminat...
306
  	tap = rcu_dereference(vlan->taps[0]);
1565c7c1c   Krishna Kumar   macvtap: Implemen...
307
308
  out:
  	return tap;
20d29d7a9   Arnd Bergmann   net: macvtap driver
309
  }
02df55d28   Arnd Bergmann   macvtap: rework o...
310
311
  /*
   * The net_device is going away, give up the reference
1565c7c1c   Krishna Kumar   macvtap: Implemen...
312
313
   * that it holds on all queues and safely set the pointer
   * from the queues to NULL.
02df55d28   Arnd Bergmann   macvtap: rework o...
314
   */
20d29d7a9   Arnd Bergmann   net: macvtap driver
315
316
317
  static void macvtap_del_queues(struct net_device *dev)
  {
  	struct macvlan_dev *vlan = netdev_priv(dev);
dfe816c5e   Pankaj Gupta   macvtap: Increase...
318
  	struct macvtap_queue *q, *tmp;
02df55d28   Arnd Bergmann   macvtap: rework o...
319

441ac0fca   Vlad Yasevich   macvtap: Convert ...
320
  	ASSERT_RTNL();
815f236d6   Jason Wang   macvtap: add TUNS...
321
322
  	list_for_each_entry_safe(q, tmp, &vlan->queue_list, next) {
  		list_del_init(&q->next);
376b1aabe   Jason Wang   macvtap: eliminat...
323
  		RCU_INIT_POINTER(q->vlan, NULL);
815f236d6   Jason Wang   macvtap: add TUNS...
324
325
326
  		if (q->enabled)
  			vlan->numvtaps--;
  		vlan->numqueues--;
dfe816c5e   Pankaj Gupta   macvtap: Increase...
327
  		sock_put(&q->sk);
564517e80   Arnd Bergmann   net/macvtap: fix ...
328
  	}
815f236d6   Jason Wang   macvtap: add TUNS...
329
330
  	BUG_ON(vlan->numvtaps);
  	BUG_ON(vlan->numqueues);
99f34b38c   Eric W. Biederman   macvtap: Close a ...
331
332
  	/* guarantee that any future macvtap_set_queue will fail */
  	vlan->numvtaps = MAX_MACVTAP_QUEUES;
20d29d7a9   Arnd Bergmann   net: macvtap driver
333
  }
6acf54f1c   Vlad Yasevich   macvtap: Add supp...
334
  static rx_handler_result_t macvtap_handle_frame(struct sk_buff **pskb)
20d29d7a9   Arnd Bergmann   net: macvtap driver
335
  {
6acf54f1c   Vlad Yasevich   macvtap: Add supp...
336
337
338
339
  	struct sk_buff *skb = *pskb;
  	struct net_device *dev = skb->dev;
  	struct macvlan_dev *vlan;
  	struct macvtap_queue *q;
a567dd625   Vlad Yasevich   macvtap: simplify...
340
  	netdev_features_t features = TAP_FEATURES;
6acf54f1c   Vlad Yasevich   macvtap: Add supp...
341
342
343
344
345
  	vlan = macvtap_get_vlan_rcu(dev);
  	if (!vlan)
  		return RX_HANDLER_PASS;
  
  	q = macvtap_get_queue(dev, skb);
20d29d7a9   Arnd Bergmann   net: macvtap driver
346
  	if (!q)
6acf54f1c   Vlad Yasevich   macvtap: Add supp...
347
  		return RX_HANDLER_PASS;
8a35747a5   Herbert Xu   macvtap: Limit pa...
348

362899b87   Jason Wang   macvtap: switch t...
349
  	if (__skb_array_full(&q->skb_array))
8a35747a5   Herbert Xu   macvtap: Limit pa...
350
  		goto drop;
20d29d7a9   Arnd Bergmann   net: macvtap driver
351

6acf54f1c   Vlad Yasevich   macvtap: Add supp...
352
  	skb_push(skb, ETH_HLEN);
3e4f8b787   Vlad Yasevich   macvtap: Perform ...
353
  	/* Apply the forward feature mask so that we perform segmentation
e5733321d   Vlad Yasevich   macvtap: Ignore t...
354
355
  	 * according to users wishes.  This only works if VNET_HDR is
  	 * enabled.
3e4f8b787   Vlad Yasevich   macvtap: Perform ...
356
  	 */
e5733321d   Vlad Yasevich   macvtap: Ignore t...
357
358
  	if (q->flags & IFF_VNET_HDR)
  		features |= vlan->tap_features;
8b86a61da   Johannes Berg   net: remove unuse...
359
  	if (netif_needs_gso(skb, features)) {
3e4f8b787   Vlad Yasevich   macvtap: Perform ...
360
361
362
363
364
365
  		struct sk_buff *segs = __skb_gso_segment(skb, features, false);
  
  		if (IS_ERR(segs))
  			goto drop;
  
  		if (!segs) {
362899b87   Jason Wang   macvtap: switch t...
366
367
  			if (skb_array_produce(&q->skb_array, skb))
  				goto drop;
3e4f8b787   Vlad Yasevich   macvtap: Perform ...
368
369
  			goto wake_up;
  		}
be0bd3160   Eric Dumazet   macvtap: segmente...
370
  		consume_skb(skb);
3e4f8b787   Vlad Yasevich   macvtap: Perform ...
371
372
373
374
  		while (segs) {
  			struct sk_buff *nskb = segs->next;
  
  			segs->next = NULL;
362899b87   Jason Wang   macvtap: switch t...
375
376
377
378
379
  			if (skb_array_produce(&q->skb_array, segs)) {
  				kfree_skb(segs);
  				kfree_skb_list(nskb);
  				break;
  			}
3e4f8b787   Vlad Yasevich   macvtap: Perform ...
380
381
382
  			segs = nskb;
  		}
  	} else {
cbdb04279   Vlad Yasevich   mactap: Fix check...
383
384
385
386
387
388
  		/* If we receive a partial checksum and the tap side
  		 * doesn't support checksum offload, compute the checksum.
  		 * Note: it doesn't matter which checksum feature to
  		 *        check, we either support them all or none.
  		 */
  		if (skb->ip_summed == CHECKSUM_PARTIAL &&
a188222b6   Tom Herbert   net: Rename NETIF...
389
  		    !(features & NETIF_F_CSUM_MASK) &&
cbdb04279   Vlad Yasevich   mactap: Fix check...
390
391
  		    skb_checksum_help(skb))
  			goto drop;
362899b87   Jason Wang   macvtap: switch t...
392
393
  		if (skb_array_produce(&q->skb_array, skb))
  			goto drop;
3e4f8b787   Vlad Yasevich   macvtap: Perform ...
394
395
396
  	}
  
  wake_up:
4a4771a58   Eric Dumazet   net: use sk_sleep()
397
  	wake_up_interruptible_poll(sk_sleep(&q->sk), POLLIN | POLLRDNORM | POLLRDBAND);
6acf54f1c   Vlad Yasevich   macvtap: Add supp...
398
  	return RX_HANDLER_CONSUMED;
8a35747a5   Herbert Xu   macvtap: Limit pa...
399
400
  
  drop:
6acf54f1c   Vlad Yasevich   macvtap: Add supp...
401
402
  	/* Count errors/drops only here, thus don't care about args. */
  	macvlan_count_rx(vlan, 0, 0, 0);
8a35747a5   Herbert Xu   macvtap: Limit pa...
403
  	kfree_skb(skb);
6acf54f1c   Vlad Yasevich   macvtap: Add supp...
404
  	return RX_HANDLER_CONSUMED;
20d29d7a9   Arnd Bergmann   net: macvtap driver
405
  }
e09eff7fc   Eric W. Biederman   macvtap: Fix the ...
406
407
408
  static int macvtap_get_minor(struct macvlan_dev *vlan)
  {
  	int retval = -ENOMEM;
e09eff7fc   Eric W. Biederman   macvtap: Fix the ...
409
410
  
  	mutex_lock(&minor_lock);
ec09ebc14   Tejun Heo   macvtap: convert ...
411
412
413
414
  	retval = idr_alloc(&minor_idr, vlan, 1, MACVTAP_NUM_DEVS, GFP_KERNEL);
  	if (retval >= 0) {
  		vlan->minor = retval;
  	} else if (retval == -ENOSPC) {
e09eff7fc   Eric W. Biederman   macvtap: Fix the ...
415
416
417
  		printk(KERN_ERR "too many macvtap devices
  ");
  		retval = -EINVAL;
e09eff7fc   Eric W. Biederman   macvtap: Fix the ...
418
  	}
e09eff7fc   Eric W. Biederman   macvtap: Fix the ...
419
  	mutex_unlock(&minor_lock);
ec09ebc14   Tejun Heo   macvtap: convert ...
420
  	return retval < 0 ? retval : 0;
e09eff7fc   Eric W. Biederman   macvtap: Fix the ...
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
  }
  
  static void macvtap_free_minor(struct macvlan_dev *vlan)
  {
  	mutex_lock(&minor_lock);
  	if (vlan->minor) {
  		idr_remove(&minor_idr, vlan->minor);
  		vlan->minor = 0;
  	}
  	mutex_unlock(&minor_lock);
  }
  
  static struct net_device *dev_get_by_macvtap_minor(int minor)
  {
  	struct net_device *dev = NULL;
  	struct macvlan_dev *vlan;
  
  	mutex_lock(&minor_lock);
  	vlan = idr_find(&minor_idr, minor);
  	if (vlan) {
  		dev = vlan->dev;
  		dev_hold(dev);
  	}
  	mutex_unlock(&minor_lock);
  	return dev;
  }
20d29d7a9   Arnd Bergmann   net: macvtap driver
447
448
449
450
451
  static int macvtap_newlink(struct net *src_net,
  			   struct net_device *dev,
  			   struct nlattr *tb[],
  			   struct nlattr *data[])
  {
815f236d6   Jason Wang   macvtap: add TUNS...
452
  	struct macvlan_dev *vlan = netdev_priv(dev);
6acf54f1c   Vlad Yasevich   macvtap: Add supp...
453
  	int err;
815f236d6   Jason Wang   macvtap: add TUNS...
454
  	INIT_LIST_HEAD(&vlan->queue_list);
2be5c7679   Vlad Yasevich   macvtap: Let TUNS...
455
456
457
458
  	/* Since macvlan supports all offloads by default, make
  	 * tap support all offloads also.
  	 */
  	vlan->tap_features = TUN_OFFLOADS;
6acf54f1c   Vlad Yasevich   macvtap: Add supp...
459
460
461
  	err = netdev_rx_handler_register(dev, macvtap_handle_frame, vlan);
  	if (err)
  		return err;
9bf1907f4   Eric W. Biederman   macvtap: Rewrite ...
462
463
464
  	/* Don't put anything that may fail after macvlan_common_newlink
  	 * because we can't undo what it does.
  	 */
e824265d6   Gao Feng   driver: macvtap: ...
465
466
467
468
469
470
471
  	err = macvlan_common_newlink(src_net, dev, tb, data);
  	if (err) {
  		netdev_rx_handler_unregister(dev);
  		return err;
  	}
  
  	return 0;
20d29d7a9   Arnd Bergmann   net: macvtap driver
472
473
474
475
476
  }
  
  static void macvtap_dellink(struct net_device *dev,
  			    struct list_head *head)
  {
6acf54f1c   Vlad Yasevich   macvtap: Add supp...
477
  	netdev_rx_handler_unregister(dev);
20d29d7a9   Arnd Bergmann   net: macvtap driver
478
479
480
  	macvtap_del_queues(dev);
  	macvlan_dellink(dev, head);
  }
8a35747a5   Herbert Xu   macvtap: Limit pa...
481
482
483
484
485
  static void macvtap_setup(struct net_device *dev)
  {
  	macvlan_common_setup(dev);
  	dev->tx_queue_len = TUN_READQ_SIZE;
  }
20d29d7a9   Arnd Bergmann   net: macvtap driver
486
487
  static struct rtnl_link_ops macvtap_link_ops __read_mostly = {
  	.kind		= "macvtap",
8a35747a5   Herbert Xu   macvtap: Limit pa...
488
  	.setup		= macvtap_setup,
20d29d7a9   Arnd Bergmann   net: macvtap driver
489
490
491
492
493
494
495
  	.newlink	= macvtap_newlink,
  	.dellink	= macvtap_dellink,
  };
  
  
  static void macvtap_sock_write_space(struct sock *sk)
  {
438154823   Eric Dumazet   net: sock_def_rea...
496
  	wait_queue_head_t *wqueue;
20d29d7a9   Arnd Bergmann   net: macvtap driver
497
  	if (!sock_writeable(sk) ||
9cd3e072b   Eric Dumazet   net: rename SOCK_...
498
  	    !test_and_clear_bit(SOCKWQ_ASYNC_NOSPACE, &sk->sk_socket->flags))
20d29d7a9   Arnd Bergmann   net: macvtap driver
499
  		return;
438154823   Eric Dumazet   net: sock_def_rea...
500
501
502
  	wqueue = sk_sleep(sk);
  	if (wqueue && waitqueue_active(wqueue))
  		wake_up_interruptible_poll(wqueue, POLLOUT | POLLWRNORM | POLLWRBAND);
20d29d7a9   Arnd Bergmann   net: macvtap driver
503
  }
2259fef0b   Eric W. Biederman   macvtap: Don't le...
504
505
  static void macvtap_sock_destruct(struct sock *sk)
  {
362899b87   Jason Wang   macvtap: switch t...
506
  	struct macvtap_queue *q = container_of(sk, struct macvtap_queue, sk);
362899b87   Jason Wang   macvtap: switch t...
507

104a49339   Jason Wang   macvtap: fix use ...
508
  	skb_array_cleanup(&q->skb_array);
2259fef0b   Eric W. Biederman   macvtap: Don't le...
509
  }
20d29d7a9   Arnd Bergmann   net: macvtap driver
510
511
512
  static int macvtap_open(struct inode *inode, struct file *file)
  {
  	struct net *net = current->nsproxy->net_ns;
40b8fe45d   Vlad Yasevich   macvtap: Fix race...
513
  	struct net_device *dev;
20d29d7a9   Arnd Bergmann   net: macvtap driver
514
  	struct macvtap_queue *q;
40b8fe45d   Vlad Yasevich   macvtap: Fix race...
515
  	int err = -ENODEV;
20d29d7a9   Arnd Bergmann   net: macvtap driver
516

40b8fe45d   Vlad Yasevich   macvtap: Fix race...
517
518
  	rtnl_lock();
  	dev = dev_get_by_macvtap_minor(iminor(inode));
20d29d7a9   Arnd Bergmann   net: macvtap driver
519
  	if (!dev)
362899b87   Jason Wang   macvtap: switch t...
520
  		goto err;
20d29d7a9   Arnd Bergmann   net: macvtap driver
521

20d29d7a9   Arnd Bergmann   net: macvtap driver
522
523
  	err = -ENOMEM;
  	q = (struct macvtap_queue *)sk_alloc(net, AF_UNSPEC, GFP_KERNEL,
11aa9c28b   Eric W. Biederman   net: Pass kern fr...
524
  					     &macvtap_proto, 0);
20d29d7a9   Arnd Bergmann   net: macvtap driver
525
  	if (!q)
362899b87   Jason Wang   macvtap: switch t...
526
  		goto err;
20d29d7a9   Arnd Bergmann   net: macvtap driver
527

d9a90a310   Jason Wang   macvtap: slient s...
528
  	RCU_INIT_POINTER(q->sock.wq, &q->wq);
438154823   Eric Dumazet   net: sock_def_rea...
529
  	init_waitqueue_head(&q->wq.wait);
20d29d7a9   Arnd Bergmann   net: macvtap driver
530
531
  	q->sock.type = SOCK_RAW;
  	q->sock.state = SS_CONNECTED;
501c774cb   Arnd Bergmann   net/macvtap: add ...
532
533
  	q->sock.file = file;
  	q->sock.ops = &macvtap_socket_ops;
20d29d7a9   Arnd Bergmann   net: macvtap driver
534
  	sock_init_data(&q->sock, &q->sk);
20d29d7a9   Arnd Bergmann   net: macvtap driver
535
  	q->sk.sk_write_space = macvtap_sock_write_space;
2259fef0b   Eric W. Biederman   macvtap: Don't le...
536
  	q->sk.sk_destruct = macvtap_sock_destruct;
b9fb9ee07   Arnd Bergmann   macvtap: add GSO/...
537
  	q->flags = IFF_VNET_HDR | IFF_NO_PI | IFF_TAP;
55afbd081   Michael S. Tsirkin   macvtap: add ioct...
538
  	q->vnet_hdr_sz = sizeof(struct virtio_net_hdr);
20d29d7a9   Arnd Bergmann   net: macvtap driver
539

97bc3633b   Shirley Ma   macvtap: macvtapT...
540
541
542
  	/*
  	 * so far only KVM virtio_net uses macvtap, enable zero copy between
  	 * guest kernel and host kernel when lower device supports zerocopy
047af9cfe   Eric W. Biederman   macvtap: Fix macv...
543
544
545
  	 *
  	 * The macvlan supports zerocopy iff the lower device supports zero
  	 * copy so we don't have to look at the lower device directly.
97bc3633b   Shirley Ma   macvtap: macvtapT...
546
  	 */
047af9cfe   Eric W. Biederman   macvtap: Fix macv...
547
548
  	if ((dev->features & NETIF_F_HIGHDMA) && (dev->features & NETIF_F_SG))
  		sock_set_flag(&q->sk, SOCK_ZEROCOPY);
97bc3633b   Shirley Ma   macvtap: macvtapT...
549

362899b87   Jason Wang   macvtap: switch t...
550
551
552
  	err = -ENOMEM;
  	if (skb_array_init(&q->skb_array, dev->tx_queue_len, GFP_KERNEL))
  		goto err_array;
20d29d7a9   Arnd Bergmann   net: macvtap driver
553
554
  	err = macvtap_set_queue(dev, file, q);
  	if (err)
362899b87   Jason Wang   macvtap: switch t...
555
  		goto err_queue;
20d29d7a9   Arnd Bergmann   net: macvtap driver
556

362899b87   Jason Wang   macvtap: switch t...
557
558
559
560
561
562
563
564
565
566
  	dev_put(dev);
  
  	rtnl_unlock();
  	return err;
  
  err_queue:
  	skb_array_cleanup(&q->skb_array);
  err_array:
  	sock_put(&q->sk);
  err:
20d29d7a9   Arnd Bergmann   net: macvtap driver
567
568
  	if (dev)
  		dev_put(dev);
40b8fe45d   Vlad Yasevich   macvtap: Fix race...
569
  	rtnl_unlock();
20d29d7a9   Arnd Bergmann   net: macvtap driver
570
571
572
573
574
  	return err;
  }
  
  static int macvtap_release(struct inode *inode, struct file *file)
  {
02df55d28   Arnd Bergmann   macvtap: rework o...
575
576
  	struct macvtap_queue *q = file->private_data;
  	macvtap_put_queue(q);
20d29d7a9   Arnd Bergmann   net: macvtap driver
577
578
579
580
581
  	return 0;
  }
  
  static unsigned int macvtap_poll(struct file *file, poll_table * wait)
  {
02df55d28   Arnd Bergmann   macvtap: rework o...
582
  	struct macvtap_queue *q = file->private_data;
20d29d7a9   Arnd Bergmann   net: macvtap driver
583
584
585
586
587
588
  	unsigned int mask = POLLERR;
  
  	if (!q)
  		goto out;
  
  	mask = 0;
438154823   Eric Dumazet   net: sock_def_rea...
589
  	poll_wait(file, &q->wq.wait, wait);
20d29d7a9   Arnd Bergmann   net: macvtap driver
590

362899b87   Jason Wang   macvtap: switch t...
591
  	if (!skb_array_empty(&q->skb_array))
20d29d7a9   Arnd Bergmann   net: macvtap driver
592
593
594
  		mask |= POLLIN | POLLRDNORM;
  
  	if (sock_writeable(&q->sk) ||
9cd3e072b   Eric Dumazet   net: rename SOCK_...
595
  	    (!test_and_set_bit(SOCKWQ_ASYNC_NOSPACE, &q->sock.flags) &&
20d29d7a9   Arnd Bergmann   net: macvtap driver
596
597
598
599
  	     sock_writeable(&q->sk)))
  		mask |= POLLOUT | POLLWRNORM;
  
  out:
20d29d7a9   Arnd Bergmann   net: macvtap driver
600
601
  	return mask;
  }
b9fb9ee07   Arnd Bergmann   macvtap: add GSO/...
602
603
604
605
606
607
608
609
610
611
612
  static inline struct sk_buff *macvtap_alloc_skb(struct sock *sk, size_t prepad,
  						size_t len, size_t linear,
  						int noblock, int *err)
  {
  	struct sk_buff *skb;
  
  	/* Under a page?  Don't bother with paged skb. */
  	if (prepad + len < PAGE_SIZE || !linear)
  		linear = len;
  
  	skb = sock_alloc_send_pskb(sk, prepad + linear, len - linear, noblock,
28d642710   Eric Dumazet   net: attempt high...
613
  				   err, 0);
b9fb9ee07   Arnd Bergmann   macvtap: add GSO/...
614
615
616
617
618
619
620
621
622
623
  	if (!skb)
  		return NULL;
  
  	skb_reserve(skb, prepad);
  	skb_put(skb, linear);
  	skb->data_len = len - linear;
  	skb->len += len - linear;
  
  	return skb;
  }
2f1d8b9e8   Eric Dumazet   macvtap: make sur...
624
625
  /* Neighbour code has some assumptions on HH_DATA_MOD alignment */
  #define MACVTAP_RESERVE HH_DATA_OFF(ETH_HLEN)
20d29d7a9   Arnd Bergmann   net: macvtap driver
626
  /* Get packet from user space buffer */
97bc3633b   Shirley Ma   macvtap: macvtapT...
627
  static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m,
f5ff53b4d   Al Viro   {macvtap,tun}_get...
628
  				struct iov_iter *from, int noblock)
20d29d7a9   Arnd Bergmann   net: macvtap driver
629
  {
2f1d8b9e8   Eric Dumazet   macvtap: make sur...
630
  	int good_linear = SKB_MAX_HEAD(MACVTAP_RESERVE);
20d29d7a9   Arnd Bergmann   net: macvtap driver
631
  	struct sk_buff *skb;
02df55d28   Arnd Bergmann   macvtap: rework o...
632
  	struct macvlan_dev *vlan;
f5ff53b4d   Al Viro   {macvtap,tun}_get...
633
  	unsigned long total_len = iov_iter_count(from);
97bc3633b   Shirley Ma   macvtap: macvtapT...
634
  	unsigned long len = total_len;
20d29d7a9   Arnd Bergmann   net: macvtap driver
635
  	int err;
b9fb9ee07   Arnd Bergmann   macvtap: add GSO/...
636
637
  	struct virtio_net_hdr vnet_hdr = { 0 };
  	int vnet_hdr_len = 0;
b92946e29   Jason Wang   macvtap: zerocopy...
638
  	int copylen = 0;
c5c62f1bb   Ivan Vecera   macvtap: fix netw...
639
  	int depth;
97bc3633b   Shirley Ma   macvtap: macvtapT...
640
  	bool zerocopy = false;
61d46bf97   Jason Wang   macvtap: correctl...
641
  	size_t linear;
f5ff53b4d   Al Viro   {macvtap,tun}_get...
642
  	ssize_t n;
b9fb9ee07   Arnd Bergmann   macvtap: add GSO/...
643
644
  
  	if (q->flags & IFF_VNET_HDR) {
b90cb484c   Willem de Bruijn   macvtap: read vne...
645
  		vnet_hdr_len = READ_ONCE(q->vnet_hdr_sz);
b9fb9ee07   Arnd Bergmann   macvtap: add GSO/...
646
647
  
  		err = -EINVAL;
ce3c86928   Nicolas Kaiser   drivers/net/macvt...
648
  		if (len < vnet_hdr_len)
b9fb9ee07   Arnd Bergmann   macvtap: add GSO/...
649
  			goto err;
ce3c86928   Nicolas Kaiser   drivers/net/macvt...
650
  		len -= vnet_hdr_len;
b9fb9ee07   Arnd Bergmann   macvtap: add GSO/...
651

f5ff53b4d   Al Viro   {macvtap,tun}_get...
652
653
654
  		err = -EFAULT;
  		n = copy_from_iter(&vnet_hdr, sizeof(vnet_hdr), from);
  		if (n != sizeof(vnet_hdr))
b9fb9ee07   Arnd Bergmann   macvtap: add GSO/...
655
  			goto err;
f5ff53b4d   Al Viro   {macvtap,tun}_get...
656
  		iov_iter_advance(from, vnet_hdr_len - sizeof(vnet_hdr));
b9fb9ee07   Arnd Bergmann   macvtap: add GSO/...
657
  		if ((vnet_hdr.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) &&
6ae7feb31   Michael S. Tsirkin   macvtap: TUN_VNET...
658
659
660
661
662
663
  		     macvtap16_to_cpu(q, vnet_hdr.csum_start) +
  		     macvtap16_to_cpu(q, vnet_hdr.csum_offset) + 2 >
  			     macvtap16_to_cpu(q, vnet_hdr.hdr_len))
  			vnet_hdr.hdr_len = cpu_to_macvtap16(q,
  				 macvtap16_to_cpu(q, vnet_hdr.csum_start) +
  				 macvtap16_to_cpu(q, vnet_hdr.csum_offset) + 2);
b9fb9ee07   Arnd Bergmann   macvtap: add GSO/...
664
  		err = -EINVAL;
6ae7feb31   Michael S. Tsirkin   macvtap: TUN_VNET...
665
  		if (macvtap16_to_cpu(q, vnet_hdr.hdr_len) > len)
b9fb9ee07   Arnd Bergmann   macvtap: add GSO/...
666
667
  			goto err;
  	}
20d29d7a9   Arnd Bergmann   net: macvtap driver
668

b9fb9ee07   Arnd Bergmann   macvtap: add GSO/...
669
  	err = -EINVAL;
20d29d7a9   Arnd Bergmann   net: macvtap driver
670
  	if (unlikely(len < ETH_HLEN))
b9fb9ee07   Arnd Bergmann   macvtap: add GSO/...
671
  		goto err;
20d29d7a9   Arnd Bergmann   net: macvtap driver
672

ece793fcf   Jason Wang   macvtap: do not z...
673
  	if (m && m->msg_control && sock_flag(&q->sk, SOCK_ZEROCOPY)) {
f5ff53b4d   Al Viro   {macvtap,tun}_get...
674
  		struct iov_iter i;
6ae7feb31   Michael S. Tsirkin   macvtap: TUN_VNET...
675
676
  		copylen = vnet_hdr.hdr_len ?
  			macvtap16_to_cpu(q, vnet_hdr.hdr_len) : GOODCOPY_LEN;
16a3fa286   Jason Wang   macvtap: limit he...
677
678
  		if (copylen > good_linear)
  			copylen = good_linear;
8e2ad4113   Willem de Bruijn   macvtap: always p...
679
680
  		else if (copylen < ETH_HLEN)
  			copylen = ETH_HLEN;
61d46bf97   Jason Wang   macvtap: correctl...
681
  		linear = copylen;
f5ff53b4d   Al Viro   {macvtap,tun}_get...
682
683
684
  		i = *from;
  		iov_iter_advance(&i, copylen);
  		if (iov_iter_npages(&i, INT_MAX) <= MAX_SKB_FRAGS)
ece793fcf   Jason Wang   macvtap: do not z...
685
686
687
688
  			zerocopy = true;
  	}
  
  	if (!zerocopy) {
97bc3633b   Shirley Ma   macvtap: macvtapT...
689
  		copylen = len;
8e2ad4113   Willem de Bruijn   macvtap: always p...
690
691
  		linear = macvtap16_to_cpu(q, vnet_hdr.hdr_len);
  		if (linear > good_linear)
16a3fa286   Jason Wang   macvtap: limit he...
692
  			linear = good_linear;
8e2ad4113   Willem de Bruijn   macvtap: always p...
693
694
  		else if (linear < ETH_HLEN)
  			linear = ETH_HLEN;
61d46bf97   Jason Wang   macvtap: correctl...
695
  	}
97bc3633b   Shirley Ma   macvtap: macvtapT...
696

2f1d8b9e8   Eric Dumazet   macvtap: make sur...
697
  	skb = macvtap_alloc_skb(&q->sk, MACVTAP_RESERVE, copylen,
61d46bf97   Jason Wang   macvtap: correctl...
698
  				linear, noblock, &err);
02df55d28   Arnd Bergmann   macvtap: rework o...
699
700
  	if (!skb)
  		goto err;
20d29d7a9   Arnd Bergmann   net: macvtap driver
701

01d6657b3   Jason Wang   macvtap: zerocopy...
702
  	if (zerocopy)
f5ff53b4d   Al Viro   {macvtap,tun}_get...
703
  		err = zerocopy_sg_from_iter(skb, from);
aa196eed3   Jason Wang   macvtap: handle u...
704
  	else
f5ff53b4d   Al Viro   {macvtap,tun}_get...
705
  		err = skb_copy_datagram_from_iter(skb, 0, from, len);
ece793fcf   Jason Wang   macvtap: do not z...
706

02df55d28   Arnd Bergmann   macvtap: rework o...
707
  	if (err)
b9fb9ee07   Arnd Bergmann   macvtap: add GSO/...
708
  		goto err_kfree;
20d29d7a9   Arnd Bergmann   net: macvtap driver
709
710
  
  	skb_set_network_header(skb, ETH_HLEN);
b9fb9ee07   Arnd Bergmann   macvtap: add GSO/...
711
712
713
714
  	skb_reset_mac_header(skb);
  	skb->protocol = eth_hdr(skb)->h_proto;
  
  	if (vnet_hdr_len) {
fd88d68b3   Mike Rapoport   macvtap: use comm...
715
716
  		err = virtio_net_hdr_to_skb(skb, &vnet_hdr,
  					    macvtap_is_little_endian(q));
b9fb9ee07   Arnd Bergmann   macvtap: add GSO/...
717
718
719
  		if (err)
  			goto err_kfree;
  	}
40893fd0f   Jason Wang   net: switch to us...
720
  	skb_probe_transport_header(skb, ETH_HLEN);
9b4d669bc   Jason Wang   macvtap: set tran...
721

c5c62f1bb   Ivan Vecera   macvtap: fix netw...
722
723
724
725
726
  	/* Move network header to the right position for VLAN tagged packets */
  	if ((skb->protocol == htons(ETH_P_8021Q) ||
  	     skb->protocol == htons(ETH_P_8021AD)) &&
  	    __vlan_get_protocol(skb, skb->protocol, &depth) != 0)
  		skb_set_network_header(skb, depth);
ac4e4af1e   Vlad Yasevich   macvtap: Consiste...
727
728
  	rcu_read_lock();
  	vlan = rcu_dereference(q->vlan);
97bc3633b   Shirley Ma   macvtap: macvtapT...
729
  	/* copy skb_ubuf_info for callback when skb has no error */
01d6657b3   Jason Wang   macvtap: zerocopy...
730
  	if (zerocopy) {
97bc3633b   Shirley Ma   macvtap: macvtapT...
731
  		skb_shinfo(skb)->destructor_arg = m->msg_control;
01d6657b3   Jason Wang   macvtap: zerocopy...
732
  		skb_shinfo(skb)->tx_flags |= SKBTX_DEV_ZEROCOPY;
c9af6db4c   Pravin B Shelar   net: Fix possible...
733
  		skb_shinfo(skb)->tx_flags |= SKBTX_SHARED_FRAG;
aa196eed3   Jason Wang   macvtap: handle u...
734
735
736
  	} else if (m && m->msg_control) {
  		struct ubuf_info *uarg = m->msg_control;
  		uarg->callback(uarg, false);
01d6657b3   Jason Wang   macvtap: zerocopy...
737
  	}
aa196eed3   Jason Wang   macvtap: handle u...
738

29d791969   Eric Dumazet   macvtap: fix two ...
739
  	if (vlan) {
6acf54f1c   Vlad Yasevich   macvtap: Add supp...
740
741
  		skb->dev = vlan->dev;
  		dev_queue_xmit(skb);
29d791969   Eric Dumazet   macvtap: fix two ...
742
  	} else {
02df55d28   Arnd Bergmann   macvtap: rework o...
743
  		kfree_skb(skb);
29d791969   Eric Dumazet   macvtap: fix two ...
744
  	}
ac4e4af1e   Vlad Yasevich   macvtap: Consiste...
745
  	rcu_read_unlock();
20d29d7a9   Arnd Bergmann   net: macvtap driver
746

97bc3633b   Shirley Ma   macvtap: macvtapT...
747
  	return total_len;
02df55d28   Arnd Bergmann   macvtap: rework o...
748

b9fb9ee07   Arnd Bergmann   macvtap: add GSO/...
749
750
  err_kfree:
  	kfree_skb(skb);
02df55d28   Arnd Bergmann   macvtap: rework o...
751
  err:
ac4e4af1e   Vlad Yasevich   macvtap: Consiste...
752
753
  	rcu_read_lock();
  	vlan = rcu_dereference(q->vlan);
02df55d28   Arnd Bergmann   macvtap: rework o...
754
  	if (vlan)
cd3e22b75   Jason Wang   macvtap: fix tx_d...
755
  		this_cpu_inc(vlan->pcpu_stats->tx_dropped);
ac4e4af1e   Vlad Yasevich   macvtap: Consiste...
756
  	rcu_read_unlock();
02df55d28   Arnd Bergmann   macvtap: rework o...
757

02df55d28   Arnd Bergmann   macvtap: rework o...
758
  	return err;
20d29d7a9   Arnd Bergmann   net: macvtap driver
759
  }
f5ff53b4d   Al Viro   {macvtap,tun}_get...
760
  static ssize_t macvtap_write_iter(struct kiocb *iocb, struct iov_iter *from)
20d29d7a9   Arnd Bergmann   net: macvtap driver
761
762
  {
  	struct file *file = iocb->ki_filp;
02df55d28   Arnd Bergmann   macvtap: rework o...
763
  	struct macvtap_queue *q = file->private_data;
20d29d7a9   Arnd Bergmann   net: macvtap driver
764

f5ff53b4d   Al Viro   {macvtap,tun}_get...
765
  	return macvtap_get_user(q, NULL, from, file->f_flags & O_NONBLOCK);
20d29d7a9   Arnd Bergmann   net: macvtap driver
766
767
768
769
770
  }
  
  /* Put packet to the user space buffer */
  static ssize_t macvtap_put_user(struct macvtap_queue *q,
  				const struct sk_buff *skb,
6c36d2e26   Herbert Xu   macvtap: Use iove...
771
  				struct iov_iter *iter)
20d29d7a9   Arnd Bergmann   net: macvtap driver
772
  {
20d29d7a9   Arnd Bergmann   net: macvtap driver
773
  	int ret;
b9fb9ee07   Arnd Bergmann   macvtap: add GSO/...
774
  	int vnet_hdr_len = 0;
f09e2249c   Basil Gor   macvtap: restore ...
775
  	int vlan_offset = 0;
6c36d2e26   Herbert Xu   macvtap: Use iove...
776
  	int total;
b9fb9ee07   Arnd Bergmann   macvtap: add GSO/...
777
778
779
  
  	if (q->flags & IFF_VNET_HDR) {
  		struct virtio_net_hdr vnet_hdr;
b90cb484c   Willem de Bruijn   macvtap: read vne...
780
  		vnet_hdr_len = READ_ONCE(q->vnet_hdr_sz);
6c36d2e26   Herbert Xu   macvtap: Use iove...
781
  		if (iov_iter_count(iter) < vnet_hdr_len)
b9fb9ee07   Arnd Bergmann   macvtap: add GSO/...
782
  			return -EINVAL;
fd88d68b3   Mike Rapoport   macvtap: use comm...
783
  		ret = virtio_net_hdr_from_skb(skb, &vnet_hdr,
1e7cbb413   Jason Wang   virtio-net: resto...
784
  					      macvtap_is_little_endian(q), true);
fd88d68b3   Mike Rapoport   macvtap: use comm...
785
786
  		if (ret)
  			BUG();
b9fb9ee07   Arnd Bergmann   macvtap: add GSO/...
787

6c36d2e26   Herbert Xu   macvtap: Use iove...
788
789
  		if (copy_to_iter(&vnet_hdr, sizeof(vnet_hdr), iter) !=
  		    sizeof(vnet_hdr))
b9fb9ee07   Arnd Bergmann   macvtap: add GSO/...
790
  			return -EFAULT;
7cc76f515   Jason Wang   macvtap: advance ...
791
792
  
  		iov_iter_advance(iter, vnet_hdr_len - sizeof(vnet_hdr));
b9fb9ee07   Arnd Bergmann   macvtap: add GSO/...
793
  	}
6c36d2e26   Herbert Xu   macvtap: Use iove...
794
  	total = vnet_hdr_len;
ce232ce01   Jason Wang   macvtap: signal t...
795
  	total += skb->len;
f09e2249c   Basil Gor   macvtap: restore ...
796

df8a39def   Jiri Pirko   net: rename vlan_...
797
  	if (skb_vlan_tag_present(skb)) {
f09e2249c   Basil Gor   macvtap: restore ...
798
799
800
801
  		struct {
  			__be16 h_vlan_proto;
  			__be16 h_vlan_TCI;
  		} veth;
0fbe0d47b   Jason Wang   macvtap: do not a...
802
  		veth.h_vlan_proto = skb->vlan_proto;
df8a39def   Jiri Pirko   net: rename vlan_...
803
  		veth.h_vlan_TCI = htons(skb_vlan_tag_get(skb));
f09e2249c   Basil Gor   macvtap: restore ...
804
805
  
  		vlan_offset = offsetof(struct vlan_ethhdr, h_vlan_proto);
ce232ce01   Jason Wang   macvtap: signal t...
806
  		total += VLAN_HLEN;
f09e2249c   Basil Gor   macvtap: restore ...
807

6c36d2e26   Herbert Xu   macvtap: Use iove...
808
809
  		ret = skb_copy_datagram_iter(skb, 0, iter, vlan_offset);
  		if (ret || !iov_iter_count(iter))
f09e2249c   Basil Gor   macvtap: restore ...
810
  			goto done;
6c36d2e26   Herbert Xu   macvtap: Use iove...
811
812
  		ret = copy_to_iter(&veth, sizeof(veth), iter);
  		if (ret != sizeof(veth) || !iov_iter_count(iter))
f09e2249c   Basil Gor   macvtap: restore ...
813
814
  			goto done;
  	}
20d29d7a9   Arnd Bergmann   net: macvtap driver
815

6c36d2e26   Herbert Xu   macvtap: Use iove...
816
817
  	ret = skb_copy_datagram_iter(skb, vlan_offset, iter,
  				     skb->len - vlan_offset);
20d29d7a9   Arnd Bergmann   net: macvtap driver
818

f09e2249c   Basil Gor   macvtap: restore ...
819
  done:
ce232ce01   Jason Wang   macvtap: signal t...
820
  	return ret ? ret : total;
20d29d7a9   Arnd Bergmann   net: macvtap driver
821
  }
55ec8e25c   Zhi Yong Wu   macvtap: remove u...
822
  static ssize_t macvtap_do_read(struct macvtap_queue *q,
3af0bfe58   Al Viro   switch macvtap to...
823
  			       struct iov_iter *to,
501c774cb   Arnd Bergmann   net/macvtap: add ...
824
  			       int noblock)
20d29d7a9   Arnd Bergmann   net: macvtap driver
825
  {
ccf7e72b5   Hong zhi guo   macvtap: use prep...
826
  	DEFINE_WAIT(wait);
20d29d7a9   Arnd Bergmann   net: macvtap driver
827
  	struct sk_buff *skb;
501c774cb   Arnd Bergmann   net/macvtap: add ...
828
  	ssize_t ret = 0;
20d29d7a9   Arnd Bergmann   net: macvtap driver
829

3af0bfe58   Al Viro   switch macvtap to...
830
831
832
833
  	if (!iov_iter_count(to))
  		return 0;
  
  	while (1) {
89cee917d   Jason Wang   macvtap: do not a...
834
835
836
  		if (!noblock)
  			prepare_to_wait(sk_sleep(&q->sk), &wait,
  					TASK_INTERRUPTIBLE);
20d29d7a9   Arnd Bergmann   net: macvtap driver
837
838
  
  		/* Read frames from the queue */
362899b87   Jason Wang   macvtap: switch t...
839
  		skb = skb_array_consume(&q->skb_array);
3af0bfe58   Al Viro   switch macvtap to...
840
841
842
843
844
  		if (skb)
  			break;
  		if (noblock) {
  			ret = -EAGAIN;
  			break;
20d29d7a9   Arnd Bergmann   net: macvtap driver
845
  		}
3af0bfe58   Al Viro   switch macvtap to...
846
847
848
849
850
851
852
  		if (signal_pending(current)) {
  			ret = -ERESTARTSYS;
  			break;
  		}
  		/* Nothing to read, let's sleep */
  		schedule();
  	}
a499a2e9d   Vlad Yasevich   macvtap: Resolve ...
853
854
  	if (!noblock)
  		finish_wait(sk_sleep(&q->sk), &wait);
3af0bfe58   Al Viro   switch macvtap to...
855
856
  	if (skb) {
  		ret = macvtap_put_user(q, skb, to);
f51a5e82e   Jason Wang   tun/macvtap: use ...
857
858
859
860
  		if (unlikely(ret < 0))
  			kfree_skb(skb);
  		else
  			consume_skb(skb);
20d29d7a9   Arnd Bergmann   net: macvtap driver
861
  	}
501c774cb   Arnd Bergmann   net/macvtap: add ...
862
863
  	return ret;
  }
3af0bfe58   Al Viro   switch macvtap to...
864
  static ssize_t macvtap_read_iter(struct kiocb *iocb, struct iov_iter *to)
501c774cb   Arnd Bergmann   net/macvtap: add ...
865
866
867
  {
  	struct file *file = iocb->ki_filp;
  	struct macvtap_queue *q = file->private_data;
3af0bfe58   Al Viro   switch macvtap to...
868
  	ssize_t len = iov_iter_count(to), ret;
20d29d7a9   Arnd Bergmann   net: macvtap driver
869

3af0bfe58   Al Viro   switch macvtap to...
870
  	ret = macvtap_do_read(q, to, file->f_flags & O_NONBLOCK);
ce232ce01   Jason Wang   macvtap: signal t...
871
  	ret = min_t(ssize_t, ret, len);
e6ebc7f16   Zhi Yong Wu   macvtap: update f...
872
873
  	if (ret > 0)
  		iocb->ki_pos = ret;
20d29d7a9   Arnd Bergmann   net: macvtap driver
874
875
  	return ret;
  }
8f475a318   Jason Wang   macvtap: introduc...
876
877
878
  static struct macvlan_dev *macvtap_get_vlan(struct macvtap_queue *q)
  {
  	struct macvlan_dev *vlan;
441ac0fca   Vlad Yasevich   macvtap: Convert ...
879
880
  	ASSERT_RTNL();
  	vlan = rtnl_dereference(q->vlan);
8f475a318   Jason Wang   macvtap: introduc...
881
882
  	if (vlan)
  		dev_hold(vlan->dev);
8f475a318   Jason Wang   macvtap: introduc...
883
884
885
886
887
888
889
890
  
  	return vlan;
  }
  
  static void macvtap_put_vlan(struct macvlan_dev *vlan)
  {
  	dev_put(vlan->dev);
  }
815f236d6   Jason Wang   macvtap: add TUNS...
891
892
893
894
895
896
897
898
899
900
901
902
903
904
  static int macvtap_ioctl_set_queue(struct file *file, unsigned int flags)
  {
  	struct macvtap_queue *q = file->private_data;
  	struct macvlan_dev *vlan;
  	int ret;
  
  	vlan = macvtap_get_vlan(q);
  	if (!vlan)
  		return -EINVAL;
  
  	if (flags & IFF_ATTACH_QUEUE)
  		ret = macvtap_enable_queue(vlan->dev, file, q);
  	else if (flags & IFF_DETACH_QUEUE)
  		ret = macvtap_disable_queue(q);
f57855a54   Jason Wang   macvtap: fix unin...
905
906
  	else
  		ret = -EINVAL;
815f236d6   Jason Wang   macvtap: add TUNS...
907
908
909
910
  
  	macvtap_put_vlan(vlan);
  	return ret;
  }
2be5c7679   Vlad Yasevich   macvtap: Let TUNS...
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
  static int set_offload(struct macvtap_queue *q, unsigned long arg)
  {
  	struct macvlan_dev *vlan;
  	netdev_features_t features;
  	netdev_features_t feature_mask = 0;
  
  	vlan = rtnl_dereference(q->vlan);
  	if (!vlan)
  		return -ENOLINK;
  
  	features = vlan->dev->features;
  
  	if (arg & TUN_F_CSUM) {
  		feature_mask = NETIF_F_HW_CSUM;
  
  		if (arg & (TUN_F_TSO4 | TUN_F_TSO6)) {
  			if (arg & TUN_F_TSO_ECN)
  				feature_mask |= NETIF_F_TSO_ECN;
  			if (arg & TUN_F_TSO4)
  				feature_mask |= NETIF_F_TSO;
  			if (arg & TUN_F_TSO6)
  				feature_mask |= NETIF_F_TSO6;
  		}
e3e3c423f   Vlad Yasevich   Revert "drivers/n...
934
935
936
  
  		if (arg & TUN_F_UFO)
  			feature_mask |= NETIF_F_UFO;
2be5c7679   Vlad Yasevich   macvtap: Let TUNS...
937
938
939
940
941
942
943
944
945
946
  	}
  
  	/* tun/tap driver inverts the usage for TSO offloads, where
  	 * setting the TSO bit means that the userspace wants to
  	 * accept TSO frames and turning it off means that user space
  	 * does not support TSO.
  	 * For macvtap, we have to invert it to mean the same thing.
  	 * When user space turns off TSO, we turn off GSO/LRO so that
  	 * user-space will not receive TSO frames.
  	 */
e3e3c423f   Vlad Yasevich   Revert "drivers/n...
947
  	if (feature_mask & (NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_UFO))
2be5c7679   Vlad Yasevich   macvtap: Let TUNS...
948
949
950
951
952
953
954
  		features |= RX_OFFLOADS;
  	else
  		features &= ~RX_OFFLOADS;
  
  	/* tap_features are the same as features on tun/tap and
  	 * reflect user expectations.
  	 */
a567dd625   Vlad Yasevich   macvtap: simplify...
955
  	vlan->tap_features = feature_mask;
2be5c7679   Vlad Yasevich   macvtap: Let TUNS...
956
957
958
959
960
  	vlan->set_features = features;
  	netdev_update_features(vlan->dev);
  
  	return 0;
  }
20d29d7a9   Arnd Bergmann   net: macvtap driver
961
962
963
964
965
966
  /*
   * provide compatibility with generic tun/tap interface
   */
  static long macvtap_ioctl(struct file *file, unsigned int cmd,
  			  unsigned long arg)
  {
02df55d28   Arnd Bergmann   macvtap: rework o...
967
968
  	struct macvtap_queue *q = file->private_data;
  	struct macvlan_dev *vlan;
20d29d7a9   Arnd Bergmann   net: macvtap driver
969
970
971
  	void __user *argp = (void __user *)arg;
  	struct ifreq __user *ifr = argp;
  	unsigned int __user *up = argp;
39ec7de70   Michael S. Tsirkin   macvtap: fix unin...
972
  	unsigned short u;
55afbd081   Michael S. Tsirkin   macvtap: add ioct...
973
  	int __user *sp = argp;
7f460d30c   Justin Cormack   fix missing copy_...
974
  	struct sockaddr sa;
55afbd081   Michael S. Tsirkin   macvtap: add ioct...
975
  	int s;
02df55d28   Arnd Bergmann   macvtap: rework o...
976
  	int ret;
20d29d7a9   Arnd Bergmann   net: macvtap driver
977
978
979
980
981
982
  
  	switch (cmd) {
  	case TUNSETIFF:
  		/* ignore the name, just look at flags */
  		if (get_user(u, &ifr->ifr_flags))
  			return -EFAULT;
b9fb9ee07   Arnd Bergmann   macvtap: add GSO/...
983
984
  
  		ret = 0;
6ae7feb31   Michael S. Tsirkin   macvtap: TUN_VNET...
985
  		if ((u & ~MACVTAP_FEATURES) != (IFF_NO_PI | IFF_TAP))
b9fb9ee07   Arnd Bergmann   macvtap: add GSO/...
986
987
  			ret = -EINVAL;
  		else
39ec7de70   Michael S. Tsirkin   macvtap: fix unin...
988
  			q->flags = (q->flags & ~MACVTAP_FEATURES) | u;
b9fb9ee07   Arnd Bergmann   macvtap: add GSO/...
989
990
  
  		return ret;
20d29d7a9   Arnd Bergmann   net: macvtap driver
991
992
  
  	case TUNGETIFF:
441ac0fca   Vlad Yasevich   macvtap: Convert ...
993
  		rtnl_lock();
8f475a318   Jason Wang   macvtap: introduc...
994
  		vlan = macvtap_get_vlan(q);
441ac0fca   Vlad Yasevich   macvtap: Convert ...
995
996
  		if (!vlan) {
  			rtnl_unlock();
20d29d7a9   Arnd Bergmann   net: macvtap driver
997
  			return -ENOLINK;
441ac0fca   Vlad Yasevich   macvtap: Convert ...
998
  		}
20d29d7a9   Arnd Bergmann   net: macvtap driver
999

02df55d28   Arnd Bergmann   macvtap: rework o...
1000
  		ret = 0;
39ec7de70   Michael S. Tsirkin   macvtap: fix unin...
1001
  		u = q->flags;
13707f9e5   Eric Dumazet   drivers/net: remo...
1002
  		if (copy_to_user(&ifr->ifr_name, vlan->dev->name, IFNAMSIZ) ||
39ec7de70   Michael S. Tsirkin   macvtap: fix unin...
1003
  		    put_user(u, &ifr->ifr_flags))
02df55d28   Arnd Bergmann   macvtap: rework o...
1004
  			ret = -EFAULT;
8f475a318   Jason Wang   macvtap: introduc...
1005
  		macvtap_put_vlan(vlan);
441ac0fca   Vlad Yasevich   macvtap: Convert ...
1006
  		rtnl_unlock();
02df55d28   Arnd Bergmann   macvtap: rework o...
1007
  		return ret;
20d29d7a9   Arnd Bergmann   net: macvtap driver
1008

815f236d6   Jason Wang   macvtap: add TUNS...
1009
1010
1011
  	case TUNSETQUEUE:
  		if (get_user(u, &ifr->ifr_flags))
  			return -EFAULT;
441ac0fca   Vlad Yasevich   macvtap: Convert ...
1012
1013
1014
  		rtnl_lock();
  		ret = macvtap_ioctl_set_queue(file, u);
  		rtnl_unlock();
82a19eb8c   Jason Wang   macvtap: fix the ...
1015
  		return ret;
815f236d6   Jason Wang   macvtap: add TUNS...
1016

20d29d7a9   Arnd Bergmann   net: macvtap driver
1017
  	case TUNGETFEATURES:
6ae7feb31   Michael S. Tsirkin   macvtap: TUN_VNET...
1018
  		if (put_user(IFF_TAP | IFF_NO_PI | MACVTAP_FEATURES, up))
20d29d7a9   Arnd Bergmann   net: macvtap driver
1019
1020
1021
1022
  			return -EFAULT;
  		return 0;
  
  	case TUNSETSNDBUF:
3ea79249e   Michael S. Tsirkin   macvtap: fix TUNS...
1023
  		if (get_user(s, sp))
20d29d7a9   Arnd Bergmann   net: macvtap driver
1024
  			return -EFAULT;
3ea79249e   Michael S. Tsirkin   macvtap: fix TUNS...
1025
  		q->sk.sk_sndbuf = s;
20d29d7a9   Arnd Bergmann   net: macvtap driver
1026
  		return 0;
55afbd081   Michael S. Tsirkin   macvtap: add ioct...
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
  	case TUNGETVNETHDRSZ:
  		s = q->vnet_hdr_sz;
  		if (put_user(s, sp))
  			return -EFAULT;
  		return 0;
  
  	case TUNSETVNETHDRSZ:
  		if (get_user(s, sp))
  			return -EFAULT;
  		if (s < (int)sizeof(struct virtio_net_hdr))
  			return -EINVAL;
  
  		q->vnet_hdr_sz = s;
  		return 0;
01b07fb35   Michael S. Tsirkin   macvtap: drop bro...
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
  	case TUNGETVNETLE:
  		s = !!(q->flags & MACVTAP_VNET_LE);
  		if (put_user(s, sp))
  			return -EFAULT;
  		return 0;
  
  	case TUNSETVNETLE:
  		if (get_user(s, sp))
  			return -EFAULT;
  		if (s)
  			q->flags |= MACVTAP_VNET_LE;
  		else
  			q->flags &= ~MACVTAP_VNET_LE;
  		return 0;
8b8e658b1   Greg Kurz   macvtap/tun: cros...
1055
1056
1057
1058
1059
  	case TUNGETVNETBE:
  		return macvtap_get_vnet_be(q, sp);
  
  	case TUNSETVNETBE:
  		return macvtap_set_vnet_be(q, sp);
20d29d7a9   Arnd Bergmann   net: macvtap driver
1060
1061
1062
  	case TUNSETOFFLOAD:
  		/* let the user check for future flags */
  		if (arg & ~(TUN_F_CSUM | TUN_F_TSO4 | TUN_F_TSO6 |
e3e3c423f   Vlad Yasevich   Revert "drivers/n...
1063
  			    TUN_F_TSO_ECN | TUN_F_UFO))
20d29d7a9   Arnd Bergmann   net: macvtap driver
1064
  			return -EINVAL;
2be5c7679   Vlad Yasevich   macvtap: Let TUNS...
1065
1066
1067
1068
  		rtnl_lock();
  		ret = set_offload(q, arg);
  		rtnl_unlock();
  		return ret;
20d29d7a9   Arnd Bergmann   net: macvtap driver
1069

b50820833   Justin Cormack   macvtap add missi...
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
  	case SIOCGIFHWADDR:
  		rtnl_lock();
  		vlan = macvtap_get_vlan(q);
  		if (!vlan) {
  			rtnl_unlock();
  			return -ENOLINK;
  		}
  		ret = 0;
  		u = vlan->dev->type;
  		if (copy_to_user(&ifr->ifr_name, vlan->dev->name, IFNAMSIZ) ||
  		    copy_to_user(&ifr->ifr_hwaddr.sa_data, vlan->dev->dev_addr, ETH_ALEN) ||
  		    put_user(u, &ifr->ifr_hwaddr.sa_family))
  			ret = -EFAULT;
  		macvtap_put_vlan(vlan);
  		rtnl_unlock();
  		return ret;
  
  	case SIOCSIFHWADDR:
7f460d30c   Justin Cormack   fix missing copy_...
1088
1089
  		if (copy_from_user(&sa, &ifr->ifr_hwaddr, sizeof(sa)))
  			return -EFAULT;
b50820833   Justin Cormack   macvtap add missi...
1090
1091
1092
1093
1094
1095
  		rtnl_lock();
  		vlan = macvtap_get_vlan(q);
  		if (!vlan) {
  			rtnl_unlock();
  			return -ENOLINK;
  		}
7f460d30c   Justin Cormack   fix missing copy_...
1096
  		ret = dev_set_mac_address(vlan->dev, &sa);
b50820833   Justin Cormack   macvtap add missi...
1097
1098
1099
  		macvtap_put_vlan(vlan);
  		rtnl_unlock();
  		return ret;
20d29d7a9   Arnd Bergmann   net: macvtap driver
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
  	default:
  		return -EINVAL;
  	}
  }
  
  #ifdef CONFIG_COMPAT
  static long macvtap_compat_ioctl(struct file *file, unsigned int cmd,
  				 unsigned long arg)
  {
  	return macvtap_ioctl(file, cmd, (unsigned long)compat_ptr(arg));
  }
  #endif
  
  static const struct file_operations macvtap_fops = {
  	.owner		= THIS_MODULE,
  	.open		= macvtap_open,
  	.release	= macvtap_release,
3af0bfe58   Al Viro   switch macvtap to...
1117
  	.read_iter	= macvtap_read_iter,
f5ff53b4d   Al Viro   {macvtap,tun}_get...
1118
  	.write_iter	= macvtap_write_iter,
20d29d7a9   Arnd Bergmann   net: macvtap driver
1119
1120
1121
1122
1123
1124
1125
  	.poll		= macvtap_poll,
  	.llseek		= no_llseek,
  	.unlocked_ioctl	= macvtap_ioctl,
  #ifdef CONFIG_COMPAT
  	.compat_ioctl	= macvtap_compat_ioctl,
  #endif
  };
1b7841404   Ying Xue   net: Remove iocb ...
1126
1127
  static int macvtap_sendmsg(struct socket *sock, struct msghdr *m,
  			   size_t total_len)
501c774cb   Arnd Bergmann   net/macvtap: add ...
1128
1129
  {
  	struct macvtap_queue *q = container_of(sock, struct macvtap_queue, sock);
c0371da60   Al Viro   put iov_iter into...
1130
  	return macvtap_get_user(q, m, &m->msg_iter, m->msg_flags & MSG_DONTWAIT);
501c774cb   Arnd Bergmann   net/macvtap: add ...
1131
  }
1b7841404   Ying Xue   net: Remove iocb ...
1132
1133
  static int macvtap_recvmsg(struct socket *sock, struct msghdr *m,
  			   size_t total_len, int flags)
501c774cb   Arnd Bergmann   net/macvtap: add ...
1134
1135
1136
1137
1138
  {
  	struct macvtap_queue *q = container_of(sock, struct macvtap_queue, sock);
  	int ret;
  	if (flags & ~(MSG_DONTWAIT|MSG_TRUNC))
  		return -EINVAL;
c0371da60   Al Viro   put iov_iter into...
1139
  	ret = macvtap_do_read(q, &m->msg_iter, flags & MSG_DONTWAIT);
de2aa4760   David S. Miller   Revert "macvtap: ...
1140
1141
1142
1143
  	if (ret > total_len) {
  		m->msg_flags |= MSG_TRUNC;
  		ret = flags & MSG_TRUNC ? ret : total_len;
  	}
501c774cb   Arnd Bergmann   net/macvtap: add ...
1144
1145
  	return ret;
  }
362899b87   Jason Wang   macvtap: switch t...
1146
1147
1148
1149
1150
1151
  static int macvtap_peek_len(struct socket *sock)
  {
  	struct macvtap_queue *q = container_of(sock, struct macvtap_queue,
  					       sock);
  	return skb_array_peek_len(&q->skb_array);
  }
501c774cb   Arnd Bergmann   net/macvtap: add ...
1152
1153
1154
1155
  /* Ops structure to mimic raw sockets with tun */
  static const struct proto_ops macvtap_socket_ops = {
  	.sendmsg = macvtap_sendmsg,
  	.recvmsg = macvtap_recvmsg,
362899b87   Jason Wang   macvtap: switch t...
1156
  	.peek_len = macvtap_peek_len,
501c774cb   Arnd Bergmann   net/macvtap: add ...
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
  };
  
  /* Get an underlying socket object from tun file.  Returns error unless file is
   * attached to a device.  The returned object works like a packet socket, it
   * can be used for sock_sendmsg/sock_recvmsg.  The caller is responsible for
   * holding a reference to the file for as long as the socket is in use. */
  struct socket *macvtap_get_socket(struct file *file)
  {
  	struct macvtap_queue *q;
  	if (file->f_op != &macvtap_fops)
  		return ERR_PTR(-EINVAL);
  	q = file->private_data;
  	if (!q)
  		return ERR_PTR(-EBADFD);
  	return &q->sock;
  }
  EXPORT_SYMBOL_GPL(macvtap_get_socket);
362899b87   Jason Wang   macvtap: switch t...
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
  static int macvtap_queue_resize(struct macvlan_dev *vlan)
  {
  	struct net_device *dev = vlan->dev;
  	struct macvtap_queue *q;
  	struct skb_array **arrays;
  	int n = vlan->numqueues;
  	int ret, i = 0;
  
  	arrays = kmalloc(sizeof *arrays * n, GFP_KERNEL);
  	if (!arrays)
  		return -ENOMEM;
  
  	list_for_each_entry(q, &vlan->queue_list, next)
  		arrays[i++] = &q->skb_array;
  
  	ret = skb_array_resize_multiple(arrays, n,
  					dev->tx_queue_len, GFP_KERNEL);
  
  	kfree(arrays);
  	return ret;
  }
9bf1907f4   Eric W. Biederman   macvtap: Rewrite ...
1195
1196
1197
  static int macvtap_device_event(struct notifier_block *unused,
  				unsigned long event, void *ptr)
  {
351638e7d   Jiri Pirko   net: pass info st...
1198
  	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
e09eff7fc   Eric W. Biederman   macvtap: Fix the ...
1199
  	struct macvlan_dev *vlan;
9bf1907f4   Eric W. Biederman   macvtap: Rewrite ...
1200
1201
  	struct device *classdev;
  	dev_t devt;
e09eff7fc   Eric W. Biederman   macvtap: Fix the ...
1202
  	int err;
17af2bce8   Marc Angel   macvtap: add name...
1203
  	char tap_name[IFNAMSIZ];
9bf1907f4   Eric W. Biederman   macvtap: Rewrite ...
1204
1205
1206
  
  	if (dev->rtnl_link_ops != &macvtap_link_ops)
  		return NOTIFY_DONE;
17af2bce8   Marc Angel   macvtap: add name...
1207
  	snprintf(tap_name, IFNAMSIZ, "tap%d", dev->ifindex);
e09eff7fc   Eric W. Biederman   macvtap: Fix the ...
1208
  	vlan = netdev_priv(dev);
9bf1907f4   Eric W. Biederman   macvtap: Rewrite ...
1209
1210
1211
1212
1213
1214
1215
  
  	switch (event) {
  	case NETDEV_REGISTER:
  		/* Create the device node here after the network device has
  		 * been registered but before register_netdevice has
  		 * finished running.
  		 */
e09eff7fc   Eric W. Biederman   macvtap: Fix the ...
1216
1217
1218
1219
1220
  		err = macvtap_get_minor(vlan);
  		if (err)
  			return notifier_from_errno(err);
  
  		devt = MKDEV(MAJOR(macvtap_major), vlan->minor);
17af2bce8   Marc Angel   macvtap: add name...
1221
1222
  		classdev = device_create(&macvtap_class, &dev->dev, devt,
  					 dev, tap_name);
e09eff7fc   Eric W. Biederman   macvtap: Fix the ...
1223
1224
  		if (IS_ERR(classdev)) {
  			macvtap_free_minor(vlan);
9bf1907f4   Eric W. Biederman   macvtap: Rewrite ...
1225
  			return notifier_from_errno(PTR_ERR(classdev));
e09eff7fc   Eric W. Biederman   macvtap: Fix the ...
1226
  		}
17af2bce8   Marc Angel   macvtap: add name...
1227
1228
1229
1230
  		err = sysfs_create_link(&dev->dev.kobj, &classdev->kobj,
  					tap_name);
  		if (err)
  			return notifier_from_errno(err);
9bf1907f4   Eric W. Biederman   macvtap: Rewrite ...
1231
1232
  		break;
  	case NETDEV_UNREGISTER:
e96c37f18   Francesco Ruggeri   macvtap: check mi...
1233
1234
1235
  		/* vlan->minor == 0 if NETDEV_REGISTER above failed */
  		if (vlan->minor == 0)
  			break;
17af2bce8   Marc Angel   macvtap: add name...
1236
  		sysfs_remove_link(&dev->dev.kobj, tap_name);
e09eff7fc   Eric W. Biederman   macvtap: Fix the ...
1237
  		devt = MKDEV(MAJOR(macvtap_major), vlan->minor);
17af2bce8   Marc Angel   macvtap: add name...
1238
  		device_destroy(&macvtap_class, devt);
e09eff7fc   Eric W. Biederman   macvtap: Fix the ...
1239
  		macvtap_free_minor(vlan);
9bf1907f4   Eric W. Biederman   macvtap: Rewrite ...
1240
  		break;
362899b87   Jason Wang   macvtap: switch t...
1241
1242
1243
1244
  	case NETDEV_CHANGE_TX_QUEUE_LEN:
  		if (macvtap_queue_resize(vlan))
  			return NOTIFY_BAD;
  		break;
9bf1907f4   Eric W. Biederman   macvtap: Rewrite ...
1245
1246
1247
1248
1249
1250
1251
1252
  	}
  
  	return NOTIFY_DONE;
  }
  
  static struct notifier_block macvtap_notifier_block __read_mostly = {
  	.notifier_call	= macvtap_device_event,
  };
20d29d7a9   Arnd Bergmann   net: macvtap driver
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
  static int macvtap_init(void)
  {
  	int err;
  
  	err = alloc_chrdev_region(&macvtap_major, 0,
  				MACVTAP_NUM_DEVS, "macvtap");
  	if (err)
  		goto out1;
  
  	cdev_init(&macvtap_cdev, &macvtap_fops);
  	err = cdev_add(&macvtap_cdev, macvtap_major, MACVTAP_NUM_DEVS);
  	if (err)
  		goto out2;
17af2bce8   Marc Angel   macvtap: add name...
1266
1267
  	err = class_register(&macvtap_class);
  	if (err)
20d29d7a9   Arnd Bergmann   net: macvtap driver
1268
  		goto out3;
20d29d7a9   Arnd Bergmann   net: macvtap driver
1269

9bf1907f4   Eric W. Biederman   macvtap: Rewrite ...
1270
  	err = register_netdevice_notifier(&macvtap_notifier_block);
20d29d7a9   Arnd Bergmann   net: macvtap driver
1271
1272
  	if (err)
  		goto out4;
9bf1907f4   Eric W. Biederman   macvtap: Rewrite ...
1273
1274
1275
  	err = macvlan_link_register(&macvtap_link_ops);
  	if (err)
  		goto out5;
20d29d7a9   Arnd Bergmann   net: macvtap driver
1276
  	return 0;
9bf1907f4   Eric W. Biederman   macvtap: Rewrite ...
1277
1278
  out5:
  	unregister_netdevice_notifier(&macvtap_notifier_block);
20d29d7a9   Arnd Bergmann   net: macvtap driver
1279
  out4:
17af2bce8   Marc Angel   macvtap: add name...
1280
  	class_unregister(&macvtap_class);
20d29d7a9   Arnd Bergmann   net: macvtap driver
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
  out3:
  	cdev_del(&macvtap_cdev);
  out2:
  	unregister_chrdev_region(macvtap_major, MACVTAP_NUM_DEVS);
  out1:
  	return err;
  }
  module_init(macvtap_init);
  
  static void macvtap_exit(void)
  {
  	rtnl_link_unregister(&macvtap_link_ops);
9bf1907f4   Eric W. Biederman   macvtap: Rewrite ...
1293
  	unregister_netdevice_notifier(&macvtap_notifier_block);
17af2bce8   Marc Angel   macvtap: add name...
1294
  	class_unregister(&macvtap_class);
20d29d7a9   Arnd Bergmann   net: macvtap driver
1295
1296
  	cdev_del(&macvtap_cdev);
  	unregister_chrdev_region(macvtap_major, MACVTAP_NUM_DEVS);
d5de19878   Johannes Thumshirn   macvtap: Destroy ...
1297
  	idr_destroy(&minor_idr);
20d29d7a9   Arnd Bergmann   net: macvtap driver
1298
1299
1300
1301
1302
1303
  }
  module_exit(macvtap_exit);
  
  MODULE_ALIAS_RTNL_LINK("macvtap");
  MODULE_AUTHOR("Arnd Bergmann <arnd@arndb.de>");
  MODULE_LICENSE("GPL");