diff options
author | Michael S. Tsirkin <mst@redhat.com> | 2010-04-29 06:50:48 -0400 |
---|---|---|
committer | Michael S. Tsirkin <mst@redhat.com> | 2010-05-03 18:35:47 -0400 |
commit | 55afbd0810922afe456f9e4e3abc84d69d3f8a15 (patch) | |
tree | 73e38287a8d81b1b03fc72d0693a66aa0a18f7a5 | |
parent | d9d52b5178af586d679c1052fb161ee05ea2e83f (diff) |
macvtap: add ioctl to modify vnet header size
This adds TUNSETVNETHDRSZ/TUNGETVNETHDRSZ support
to macvtap.
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Acked-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/macvtap.c | 27 |
1 files changed, 23 insertions, 4 deletions
diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index 1c4110df343e..a8a94e2f6ddc 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c | |||
@@ -38,6 +38,7 @@ struct macvtap_queue { | |||
38 | struct sock sk; | 38 | struct sock sk; |
39 | struct socket sock; | 39 | struct socket sock; |
40 | struct socket_wq wq; | 40 | struct socket_wq wq; |
41 | int vnet_hdr_sz; | ||
41 | struct macvlan_dev *vlan; | 42 | struct macvlan_dev *vlan; |
42 | struct file *file; | 43 | struct file *file; |
43 | unsigned int flags; | 44 | unsigned int flags; |
@@ -285,6 +286,7 @@ static int macvtap_open(struct inode *inode, struct file *file) | |||
285 | sock_init_data(&q->sock, &q->sk); | 286 | sock_init_data(&q->sock, &q->sk); |
286 | q->sk.sk_write_space = macvtap_sock_write_space; | 287 | q->sk.sk_write_space = macvtap_sock_write_space; |
287 | 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); | ||
288 | 290 | ||
289 | err = macvtap_set_queue(dev, file, q); | 291 | err = macvtap_set_queue(dev, file, q); |
290 | if (err) | 292 | if (err) |
@@ -445,14 +447,14 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, | |||
445 | int vnet_hdr_len = 0; | 447 | int vnet_hdr_len = 0; |
446 | 448 | ||
447 | if (q->flags & IFF_VNET_HDR) { | 449 | if (q->flags & IFF_VNET_HDR) { |
448 | vnet_hdr_len = sizeof(vnet_hdr); | 450 | vnet_hdr_len = q->vnet_hdr_sz; |
449 | 451 | ||
450 | err = -EINVAL; | 452 | err = -EINVAL; |
451 | if ((len -= vnet_hdr_len) < 0) | 453 | if ((len -= vnet_hdr_len) < 0) |
452 | goto err; | 454 | goto err; |
453 | 455 | ||
454 | err = memcpy_fromiovecend((void *)&vnet_hdr, iv, 0, | 456 | err = memcpy_fromiovecend((void *)&vnet_hdr, iv, 0, |
455 | vnet_hdr_len); | 457 | sizeof(vnet_hdr)); |
456 | if (err < 0) | 458 | if (err < 0) |
457 | goto err; | 459 | goto err; |
458 | if ((vnet_hdr.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) && | 460 | if ((vnet_hdr.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) && |
@@ -534,7 +536,7 @@ static ssize_t macvtap_put_user(struct macvtap_queue *q, | |||
534 | 536 | ||
535 | if (q->flags & IFF_VNET_HDR) { | 537 | if (q->flags & IFF_VNET_HDR) { |
536 | struct virtio_net_hdr vnet_hdr; | 538 | struct virtio_net_hdr vnet_hdr; |
537 | vnet_hdr_len = sizeof (vnet_hdr); | 539 | vnet_hdr_len = q->vnet_hdr_sz; |
538 | if ((len -= vnet_hdr_len) < 0) | 540 | if ((len -= vnet_hdr_len) < 0) |
539 | return -EINVAL; | 541 | return -EINVAL; |
540 | 542 | ||
@@ -542,7 +544,7 @@ static ssize_t macvtap_put_user(struct macvtap_queue *q, | |||
542 | if (ret) | 544 | if (ret) |
543 | return ret; | 545 | return ret; |
544 | 546 | ||
545 | if (memcpy_toiovecend(iv, (void *)&vnet_hdr, 0, vnet_hdr_len)) | 547 | if (memcpy_toiovecend(iv, (void *)&vnet_hdr, 0, sizeof(vnet_hdr))) |
546 | return -EFAULT; | 548 | return -EFAULT; |
547 | } | 549 | } |
548 | 550 | ||
@@ -627,6 +629,8 @@ static long macvtap_ioctl(struct file *file, unsigned int cmd, | |||
627 | struct ifreq __user *ifr = argp; | 629 | struct ifreq __user *ifr = argp; |
628 | unsigned int __user *up = argp; | 630 | unsigned int __user *up = argp; |
629 | unsigned int u; | 631 | unsigned int u; |
632 | int __user *sp = argp; | ||
633 | int s; | ||
630 | int ret; | 634 | int ret; |
631 | 635 | ||
632 | switch (cmd) { | 636 | switch (cmd) { |
@@ -672,6 +676,21 @@ static long macvtap_ioctl(struct file *file, unsigned int cmd, | |||
672 | q->sk.sk_sndbuf = u; | 676 | q->sk.sk_sndbuf = u; |
673 | return 0; | 677 | return 0; |
674 | 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 | |||
675 | case TUNSETOFFLOAD: | 694 | case TUNSETOFFLOAD: |
676 | /* let the user check for future flags */ | 695 | /* let the user check for future flags */ |
677 | if (arg & ~(TUN_F_CSUM | TUN_F_TSO4 | TUN_F_TSO6 | | 696 | if (arg & ~(TUN_F_CSUM | TUN_F_TSO4 | TUN_F_TSO6 | |