aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/macvtap.c
diff options
context:
space:
mode:
authorMichael S. Tsirkin <mst@redhat.com>2010-04-29 06:50:48 -0400
committerMichael S. Tsirkin <mst@redhat.com>2010-05-03 18:35:47 -0400
commit55afbd0810922afe456f9e4e3abc84d69d3f8a15 (patch)
tree73e38287a8d81b1b03fc72d0693a66aa0a18f7a5 /drivers/net/macvtap.c
parentd9d52b5178af586d679c1052fb161ee05ea2e83f (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>
Diffstat (limited to 'drivers/net/macvtap.c')
-rw-r--r--drivers/net/macvtap.c27
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 |