aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/macvtap.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/macvtap.c')
-rw-r--r--drivers/net/macvtap.c46
1 files changed, 35 insertions, 11 deletions
diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c
index abba3cc81f1..a8a94e2f6dd 100644
--- a/drivers/net/macvtap.c
+++ b/drivers/net/macvtap.c
@@ -37,6 +37,8 @@
37struct macvtap_queue { 37struct macvtap_queue {
38 struct sock sk; 38 struct sock sk;
39 struct socket sock; 39 struct socket sock;
40 struct socket_wq wq;
41 int vnet_hdr_sz;
40 struct macvlan_dev *vlan; 42 struct macvlan_dev *vlan;
41 struct file *file; 43 struct file *file;
42 unsigned int flags; 44 unsigned int flags;
@@ -181,7 +183,7 @@ static int macvtap_forward(struct net_device *dev, struct sk_buff *skb)
181 return -ENOLINK; 183 return -ENOLINK;
182 184
183 skb_queue_tail(&q->sk.sk_receive_queue, skb); 185 skb_queue_tail(&q->sk.sk_receive_queue, skb);
184 wake_up_interruptible_poll(q->sk.sk_sleep, POLLIN | POLLRDNORM | POLLRDBAND); 186 wake_up_interruptible_poll(sk_sleep(&q->sk), POLLIN | POLLRDNORM | POLLRDBAND);
185 return 0; 187 return 0;
186} 188}
187 189
@@ -242,12 +244,15 @@ static struct rtnl_link_ops macvtap_link_ops __read_mostly = {
242 244
243static void macvtap_sock_write_space(struct sock *sk) 245static void macvtap_sock_write_space(struct sock *sk)
244{ 246{
247 wait_queue_head_t *wqueue;
248
245 if (!sock_writeable(sk) || 249 if (!sock_writeable(sk) ||
246 !test_and_clear_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags)) 250 !test_and_clear_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags))
247 return; 251 return;
248 252
249 if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) 253 wqueue = sk_sleep(sk);
250 wake_up_interruptible_poll(sk->sk_sleep, POLLOUT | POLLWRNORM | POLLWRBAND); 254 if (wqueue && waitqueue_active(wqueue))
255 wake_up_interruptible_poll(wqueue, POLLOUT | POLLWRNORM | POLLWRBAND);
251} 256}
252 257
253static int macvtap_open(struct inode *inode, struct file *file) 258static int macvtap_open(struct inode *inode, struct file *file)
@@ -272,7 +277,8 @@ static int macvtap_open(struct inode *inode, struct file *file)
272 if (!q) 277 if (!q)
273 goto out; 278 goto out;
274 279
275 init_waitqueue_head(&q->sock.wait); 280 q->sock.wq = &q->wq;
281 init_waitqueue_head(&q->wq.wait);
276 q->sock.type = SOCK_RAW; 282 q->sock.type = SOCK_RAW;
277 q->sock.state = SS_CONNECTED; 283 q->sock.state = SS_CONNECTED;
278 q->sock.file = file; 284 q->sock.file = file;
@@ -280,6 +286,7 @@ static int macvtap_open(struct inode *inode, struct file *file)
280 sock_init_data(&q->sock, &q->sk); 286 sock_init_data(&q->sock, &q->sk);
281 q->sk.sk_write_space = macvtap_sock_write_space; 287 q->sk.sk_write_space = macvtap_sock_write_space;
282 q->flags = IFF_VNET_HDR | IFF_NO_PI | IFF_TAP; 288 q->flags = IFF_VNET_HDR | IFF_NO_PI | IFF_TAP;
289 q->vnet_hdr_sz = sizeof(struct virtio_net_hdr);
283 290
284 err = macvtap_set_queue(dev, file, q); 291 err = macvtap_set_queue(dev, file, q);
285 if (err) 292 if (err)
@@ -308,7 +315,7 @@ static unsigned int macvtap_poll(struct file *file, poll_table * wait)
308 goto out; 315 goto out;
309 316
310 mask = 0; 317 mask = 0;
311 poll_wait(file, &q->sock.wait, wait); 318 poll_wait(file, &q->wq.wait, wait);
312 319
313 if (!skb_queue_empty(&q->sk.sk_receive_queue)) 320 if (!skb_queue_empty(&q->sk.sk_receive_queue))
314 mask |= POLLIN | POLLRDNORM; 321 mask |= POLLIN | POLLRDNORM;
@@ -440,14 +447,14 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q,
440 int vnet_hdr_len = 0; 447 int vnet_hdr_len = 0;
441 448
442 if (q->flags & IFF_VNET_HDR) { 449 if (q->flags & IFF_VNET_HDR) {
443 vnet_hdr_len = sizeof(vnet_hdr); 450 vnet_hdr_len = q->vnet_hdr_sz;
444 451
445 err = -EINVAL; 452 err = -EINVAL;
446 if ((len -= vnet_hdr_len) < 0) 453 if ((len -= vnet_hdr_len) < 0)
447 goto err; 454 goto err;
448 455
449 err = memcpy_fromiovecend((void *)&vnet_hdr, iv, 0, 456 err = memcpy_fromiovecend((void *)&vnet_hdr, iv, 0,
450 vnet_hdr_len); 457 sizeof(vnet_hdr));
451 if (err < 0) 458 if (err < 0)
452 goto err; 459 goto err;
453 if ((vnet_hdr.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) && 460 if ((vnet_hdr.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) &&
@@ -529,7 +536,7 @@ static ssize_t macvtap_put_user(struct macvtap_queue *q,
529 536
530 if (q->flags & IFF_VNET_HDR) { 537 if (q->flags & IFF_VNET_HDR) {
531 struct virtio_net_hdr vnet_hdr; 538 struct virtio_net_hdr vnet_hdr;
532 vnet_hdr_len = sizeof (vnet_hdr); 539 vnet_hdr_len = q->vnet_hdr_sz;
533 if ((len -= vnet_hdr_len) < 0) 540 if ((len -= vnet_hdr_len) < 0)
534 return -EINVAL; 541 return -EINVAL;
535 542
@@ -537,7 +544,7 @@ static ssize_t macvtap_put_user(struct macvtap_queue *q,
537 if (ret) 544 if (ret)
538 return ret; 545 return ret;
539 546
540 if (memcpy_toiovecend(iv, (void *)&vnet_hdr, 0, vnet_hdr_len)) 547 if (memcpy_toiovecend(iv, (void *)&vnet_hdr, 0, sizeof(vnet_hdr)))
541 return -EFAULT; 548 return -EFAULT;
542 } 549 }
543 550
@@ -562,7 +569,7 @@ static ssize_t macvtap_do_read(struct macvtap_queue *q, struct kiocb *iocb,
562 struct sk_buff *skb; 569 struct sk_buff *skb;
563 ssize_t ret = 0; 570 ssize_t ret = 0;
564 571
565 add_wait_queue(q->sk.sk_sleep, &wait); 572 add_wait_queue(sk_sleep(&q->sk), &wait);
566 while (len) { 573 while (len) {
567 current->state = TASK_INTERRUPTIBLE; 574 current->state = TASK_INTERRUPTIBLE;
568 575
@@ -587,7 +594,7 @@ static ssize_t macvtap_do_read(struct macvtap_queue *q, struct kiocb *iocb,
587 } 594 }
588 595
589 current->state = TASK_RUNNING; 596 current->state = TASK_RUNNING;
590 remove_wait_queue(q->sk.sk_sleep, &wait); 597 remove_wait_queue(sk_sleep(&q->sk), &wait);
591 return ret; 598 return ret;
592} 599}
593 600
@@ -622,6 +629,8 @@ static long macvtap_ioctl(struct file *file, unsigned int cmd,
622 struct ifreq __user *ifr = argp; 629 struct ifreq __user *ifr = argp;
623 unsigned int __user *up = argp; 630 unsigned int __user *up = argp;
624 unsigned int u; 631 unsigned int u;
632 int __user *sp = argp;
633 int s;
625 int ret; 634 int ret;
626 635
627 switch (cmd) { 636 switch (cmd) {
@@ -667,6 +676,21 @@ static long macvtap_ioctl(struct file *file, unsigned int cmd,
667 q->sk.sk_sndbuf = u; 676 q->sk.sk_sndbuf = u;
668 return 0; 677 return 0;
669 678
679 case TUNGETVNETHDRSZ:
680 s = q->vnet_hdr_sz;
681 if (put_user(s, sp))
682 return -EFAULT;
683 return 0;
684
685 case TUNSETVNETHDRSZ:
686 if (get_user(s, sp))
687 return -EFAULT;
688 if (s < (int)sizeof(struct virtio_net_hdr))
689 return -EINVAL;
690
691 q->vnet_hdr_sz = s;
692 return 0;
693
670 case TUNSETOFFLOAD: 694 case TUNSETOFFLOAD:
671 /* let the user check for future flags */ 695 /* let the user check for future flags */
672 if (arg & ~(TUN_F_CSUM | TUN_F_TSO4 | TUN_F_TSO6 | 696 if (arg & ~(TUN_F_CSUM | TUN_F_TSO4 | TUN_F_TSO6 |