#include <linux/etherdevice.h>#include <linux/if_macvlan.h>#include <linux/if_vlan.h>#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>#include <linux/slab.h>#include <linux/init.h>#include <linux/wait.h>#include <linux/cdev.h>#include <linux/idr.h>#include <linux/fs.h> #include <net/net_namespace.h>#include <net/rtnetlink.h>#include <net/sock.h>#include <linux/virtio_net.h> /* * 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. * */struct macvtap_queue { struct sock sk; struct socket sock; struct socket_wq wq; int vnet_hdr_sz; struct macvlan_dev __rcu *vlan; struct file *file; unsigned int flags; u16 queue_index; bool enabled; struct list_head next;}; static struct proto macvtap_proto = { .name = "macvtap", .owner = THIS_MODULE, .obj_size = sizeof (struct macvtap_queue),}; /* * Variables for dealing with macvtaps device numbers. */static dev_t macvtap_major;#define MACVTAP_NUM_DEVS (1U << MINORBITS)static DEFINE_MUTEX(minor_lock);static DEFINE_IDR(minor_idr); #define GOODCOPY_LEN 128static struct class *macvtap_class;static struct cdev macvtap_cdev; static const struct proto_ops macvtap_socket_ops; #define TUN_OFFLOADS (NETIF_F_HW_CSUM | NETIF_F_TSO_ECN | NETIF_F_TSO | \ NETIF_F_TSO6 | NETIF_F_UFO)#define RX_OFFLOADS (NETIF_F_GRO | NETIF_F_LRO)#define TAP_FEATURES (NETIF_F_GSO | NETIF_F_SG) /* * RCU usage: * 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 * or rtnl is held. * * 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. * * 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. */ static int macvtap_enable_queue(struct net_device *dev, struct file *file, struct macvtap_queue *q){ struct macvlan_dev *vlan = netdev_priv(dev); int err = -EINVAL; ASSERT_RTNL(); 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: return err;} static int macvtap_set_queue(struct net_device *dev, struct file *file, struct macvtap_queue *q){ struct macvlan_dev *vlan = netdev_priv(dev); int err = -EBUSY; rtnl_lock(); if (vlan->numqueues == MAX_MACVTAP_QUEUES) goto out; err = 0; rcu_assign_pointer(q->vlan, vlan); rcu_assign_pointer(vlan->taps[vlan->numvtaps], q); sock_hold(&q->sk); q->file = file; q->queue_index = vlan->numvtaps; q->enabled = true; file->private_data = q; list_add_tail(&q->next, &vlan->queue_list); vlan->numvtaps++; vlan->numqueues++; out: rtnl_unlock(); return err;} static int macvtap_disable_queue(struct macvtap_queue *q){ struct macvlan_dev *vlan; struct macvtap_queue *nq; ASSERT_RTNL(); if (!q->enabled) return -EINVAL; vlan = rtnl_dereference(q->vlan); if (vlan) { int index = q->queue_index; BUG_ON(index >= vlan->numvtaps); nq = rtnl_dereference(vlan->taps[vlan->numvtaps - 1]); 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;} /* * 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. * * Using the spinlock makes sure that we don't get * to the queue again after destroying it. */static void macvtap_put_queue(struct macvtap_queue *q){ struct macvlan_dev *vlan; rtnl_lock(); vlan = rtnl_dereference(q->vlan); if (vlan) { if (q->enabled) BUG_ON(macvtap_disable_queue(q)); vlan->numqueues--; RCU_INIT_POINTER(q->vlan, NULL); sock_put(&q->sk); list_del_init(&q->next); } rtnl_unlock(); synchronize_rcu(); sock_put(&q->sk);} /* * 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. */static struct macvtap_queue *macvtap_get_queue(struct net_device *dev, struct sk_buff *skb){ struct macvlan_dev *vlan = netdev_priv(dev); struct macvtap_queue *tap = NULL; /* 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. */ int numvtaps = ACCESS_ONCE(vlan->numvtaps); __u32 rxq; if (!numvtaps) goto out; /* Check if we can use flow to select a queue */ rxq = skb_get_rxhash(skb); if (rxq) { tap = rcu_dereference(vlan->taps[rxq % numvtaps]); goto out; } if (likely(skb_rx_queue_recorded(skb))) { rxq = skb_get_rx_queue(skb); while (unlikely(rxq >= numvtaps)) rxq -= numvtaps; tap = rcu_dereference(vlan->taps[rxq]); goto out; } tap = rcu_dereference(vlan->taps[0]);out: return tap;} /* * The net_device is going away, give up the reference * that it holds on all queues and safely set the pointer * from the queues to NULL. */static void macvtap_del_queues(struct net_device *dev){ struct macvlan_dev *vlan = netdev_priv(dev); struct macvtap_queue *q, *tmp, *qlist[MAX_MACVTAP_QUEUES]; int i, j = 0; ASSERT_RTNL(); list_for_each_entry_safe(q, tmp, &vlan->queue_list, next) { list_del_init(&q->next); qlist[j++] = q; RCU_INIT_POINTER(q->vlan, NULL); if (q->enabled) vlan->numvtaps--; vlan->numqueues--; } for (i = 0; i < vlan->numvtaps; i++) RCU_INIT_POINTER(vlan->taps[i], NULL); BUG_ON(vlan->numvtaps); BUG_ON(vlan->numqueues); /* guarantee that any future macvtap_set_queue will fail */ vlan->numvtaps = MAX_MACVTAP_QUEUES; for (--j; j >= 0; j--) sock_put(&qlist[j]->sk);} /* * Forward happens for data that gets sent from one macvlan * endpoint to another one in bridge mode. We just take * the skb and put it into the receive queue. */static int macvtap_forward(struct net_device *dev, struct sk_buff *skb){ struct macvlan_dev *vlan = netdev_priv(dev); struct macvtap_queue *q = macvtap_get_queue(dev, skb); netdev_features_t features = TAP_FEATURES; if (!q) goto drop; if (skb_queue_len(&q->sk.sk_receive_queue) >= dev->tx_queue_len) goto drop; skb->dev = dev; /* Apply the forward feature mask so that we perform segmentation * according to users wishes. This only works if VNET_HDR is * enabled. */ if (q->flags & IFF_VNET_HDR) features |= vlan->tap_features; if (netif_needs_gso(skb, features)) { struct sk_buff *segs = __skb_gso_segment(skb, features, false); if (IS_ERR(segs)) goto drop; if (!segs) { skb_queue_tail(&q->sk.sk_receive_queue, skb); goto wake_up; } kfree_skb(skb); while (segs) { struct sk_buff *nskb = segs->next; segs->next = NULL; skb_queue_tail(&q->sk.sk_receive_queue, segs); segs = nskb; } } else { skb_queue_tail(&q->sk.sk_receive_queue, skb); } wake_up: wake_up_interruptible_poll(sk_sleep(&q->sk), POLLIN | POLLRDNORM | POLLRDBAND); return NET_RX_SUCCESS; drop: kfree_skb(skb); return NET_RX_DROP;} /* * Receive is for data from the external interface (lowerdev), * in case of macvtap, we can treat that the same way as * forward, which macvlan cannot. */static int macvtap_receive(struct sk_buff *skb){ skb_push(skb, ETH_HLEN); return macvtap_forward(skb->dev, skb);} static int macvtap_get_minor(struct macvlan_dev *vlan){ int retval = -ENOMEM; mutex_lock(&minor_lock); retval = idr_alloc(&minor_idr, vlan, 1, MACVTAP_NUM_DEVS, GFP_KERNEL); if (retval >= 0) { vlan->minor = retval; } else if (retval == -ENOSPC) { printk(KERN_ERR "too many macvtap devices\n"); retval = -EINVAL; } mutex_unlock(&minor_lock); return retval < 0 ? retval : 0;} 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;} static int macvtap_newlink(struct net *src_net, struct net_device *dev, struct nlattr *tb[], struct nlattr *data[]){ struct macvlan_dev *vlan = netdev_priv(dev); INIT_LIST_HEAD(&vlan->queue_list); /* Since macvlan supports all offloads by default, make * tap support all offloads also. */ vlan->tap_features = TUN_OFFLOADS; /* Don't put anything that may fail after macvlan_common_newlink * because we can't undo what it does. */ return macvlan_common_newlink(src_net, dev, tb, data, macvtap_receive, macvtap_forward);} static void macvtap_dellink(struct net_device *dev, struct list_head *head){ macvtap_del_queues(dev); macvlan_dellink(dev, head);} static void macvtap_setup(struct net_device *dev){ macvlan_common_setup(dev); dev->tx_queue_len = TUN_READQ_SIZE;} static struct rtnl_link_ops macvtap_link_ops __read_mostly = { .kind = "macvtap", .setup = macvtap_setup, .newlink = macvtap_newlink, .dellink = macvtap_dellink,}; static void macvtap_sock_write_space(struct sock *sk){ wait_queue_head_t *wqueue; if (!sock_writeable(sk) || !test_and_clear_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags)) return; wqueue = sk_sleep(sk); if (wqueue && waitqueue_active(wqueue)) wake_up_interruptible_poll(wqueue, POLLOUT | POLLWRNORM | POLLWRBAND);} static void macvtap_sock_destruct(struct sock *sk){ skb_queue_purge(&sk->sk_receive_queue);} static int macvtap_open(struct inode *inode, struct file *file){ struct net *net = current->nsproxy->net_ns; struct net_device *dev = dev_get_by_macvtap_minor(iminor(inode)); struct macvtap_queue *q; int err; err = -ENODEV; if (!dev) goto out; err = -ENOMEM; q = (struct macvtap_queue *)sk_alloc(net, AF_UNSPEC, GFP_KERNEL, &macvtap_proto); if (!q) goto out; RCU_INIT_POINTER(q->sock.wq, &q->wq); init_waitqueue_head(&q->wq.wait); q->sock.type = SOCK_RAW; q->sock.state = SS_CONNECTED; q->sock.file = file; q->sock.ops = &macvtap_socket_ops; sock_init_data(&q->sock, &q->sk); q->sk.sk_write_space = macvtap_sock_write_space; q->sk.sk_destruct = macvtap_sock_destruct; q->flags = IFF_VNET_HDR | IFF_NO_PI | IFF_TAP; q->vnet_hdr_sz = sizeof(struct virtio_net_hdr); /* * so far only KVM virtio_net uses macvtap, enable zero copy between * guest kernel and host kernel when lower device supports zerocopy * * The macvlan supports zerocopy iff the lower device supports zero * copy so we don't have to look at the lower device directly. */ if ((dev->features & NETIF_F_HIGHDMA) && (dev->features & NETIF_F_SG)) sock_set_flag(&q->sk, SOCK_ZEROCOPY); err = macvtap_set_queue(dev, file, q); if (err) sock_put(&q->sk); out: if (dev) dev_put(dev); return err;} static int macvtap_release(struct inode *inode, struct file *file){ struct macvtap_queue *q = file->private_data; macvtap_put_queue(q); return 0;} static unsigned int macvtap_poll(struct file *file, poll_table * wait){ struct macvtap_queue *q = file->private_data;Lines 1–500 of 1244. Load more
#include <linux/etherdevice.h> #include <linux/if_macvlan.h> #include <linux/if_vlan.h> #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> #include <linux/slab.h> #include <linux/init.h> #include <linux/wait.h> #include <linux/cdev.h> #include <linux/idr.h> #include <linux/fs.h> #include <net/net_namespace.h> #include <net/rtnetlink.h> #include <net/sock.h> #include <linux/virtio_net.h> /* * 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. * */ struct macvtap_queue { struct sock sk; struct socket sock; struct socket_wq wq; int vnet_hdr_sz; struct macvlan_dev __rcu *vlan; struct file *file; unsigned int flags; u16 queue_index; bool enabled; struct list_head next; }; static struct proto macvtap_proto = { .name = "macvtap", .owner = THIS_MODULE, .obj_size = sizeof (struct macvtap_queue), }; /* * Variables for dealing with macvtaps device numbers. */ static dev_t macvtap_major; #define MACVTAP_NUM_DEVS (1U << MINORBITS) static DEFINE_MUTEX(minor_lock); static DEFINE_IDR(minor_idr); #define GOODCOPY_LEN 128 static struct class *macvtap_class; static struct cdev macvtap_cdev; static const struct proto_ops macvtap_socket_ops; #define TUN_OFFLOADS (NETIF_F_HW_CSUM | NETIF_F_TSO_ECN | NETIF_F_TSO | \ NETIF_F_TSO6 | NETIF_F_UFO) #define RX_OFFLOADS (NETIF_F_GRO | NETIF_F_LRO) #define TAP_FEATURES (NETIF_F_GSO | NETIF_F_SG) /* * RCU usage: * 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 * or rtnl is held. * * 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. * * 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. */ static int macvtap_enable_queue(struct net_device *dev, struct file *file, struct macvtap_queue *q) { struct macvlan_dev *vlan = netdev_priv(dev); int err = -EINVAL; ASSERT_RTNL(); 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: return err; } static int macvtap_set_queue(struct net_device *dev, struct file *file, struct macvtap_queue *q) { struct macvlan_dev *vlan = netdev_priv(dev); int err = -EBUSY; rtnl_lock(); if (vlan->numqueues == MAX_MACVTAP_QUEUES) goto out; err = 0; rcu_assign_pointer(q->vlan, vlan); rcu_assign_pointer(vlan->taps[vlan->numvtaps], q); sock_hold(&q->sk); q->file = file; q->queue_index = vlan->numvtaps; q->enabled = true; file->private_data = q; list_add_tail(&q->next, &vlan->queue_list); vlan->numvtaps++; vlan->numqueues++; out: rtnl_unlock(); return err; } static int macvtap_disable_queue(struct macvtap_queue *q) { struct macvlan_dev *vlan; struct macvtap_queue *nq; ASSERT_RTNL(); if (!q->enabled) return -EINVAL; vlan = rtnl_dereference(q->vlan); if (vlan) { int index = q->queue_index; BUG_ON(index >= vlan->numvtaps); nq = rtnl_dereference(vlan->taps[vlan->numvtaps - 1]); 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; } /* * 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. * * Using the spinlock makes sure that we don't get * to the queue again after destroying it. */ static void macvtap_put_queue(struct macvtap_queue *q) { struct macvlan_dev *vlan; rtnl_lock(); vlan = rtnl_dereference(q->vlan); if (vlan) { if (q->enabled) BUG_ON(macvtap_disable_queue(q)); vlan->numqueues--; RCU_INIT_POINTER(q->vlan, NULL); sock_put(&q->sk); list_del_init(&q->next); } rtnl_unlock(); synchronize_rcu(); sock_put(&q->sk); } /* * 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. */ static struct macvtap_queue *macvtap_get_queue(struct net_device *dev, struct sk_buff *skb) { struct macvlan_dev *vlan = netdev_priv(dev); struct macvtap_queue *tap = NULL; /* 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. */ int numvtaps = ACCESS_ONCE(vlan->numvtaps); __u32 rxq; if (!numvtaps) goto out; /* Check if we can use flow to select a queue */ rxq = skb_get_rxhash(skb); if (rxq) { tap = rcu_dereference(vlan->taps[rxq % numvtaps]); goto out; } if (likely(skb_rx_queue_recorded(skb))) { rxq = skb_get_rx_queue(skb); while (unlikely(rxq >= numvtaps)) rxq -= numvtaps; tap = rcu_dereference(vlan->taps[rxq]); goto out; } tap = rcu_dereference(vlan->taps[0]); out: return tap; } /* * The net_device is going away, give up the reference * that it holds on all queues and safely set the pointer * from the queues to NULL. */ static void macvtap_del_queues(struct net_device *dev) { struct macvlan_dev *vlan = netdev_priv(dev); struct macvtap_queue *q, *tmp, *qlist[MAX_MACVTAP_QUEUES]; int i, j = 0; ASSERT_RTNL(); list_for_each_entry_safe(q, tmp, &vlan->queue_list, next) { list_del_init(&q->next); qlist[j++] = q; RCU_INIT_POINTER(q->vlan, NULL); if (q->enabled) vlan->numvtaps--; vlan->numqueues--; } for (i = 0; i < vlan->numvtaps; i++) RCU_INIT_POINTER(vlan->taps[i], NULL); BUG_ON(vlan->numvtaps); BUG_ON(vlan->numqueues); /* guarantee that any future macvtap_set_queue will fail */ vlan->numvtaps = MAX_MACVTAP_QUEUES; for (--j; j >= 0; j--) sock_put(&qlist[j]->sk); } /* * Forward happens for data that gets sent from one macvlan * endpoint to another one in bridge mode. We just take * the skb and put it into the receive queue. */ static int macvtap_forward(struct net_device *dev, struct sk_buff *skb) { struct macvlan_dev *vlan = netdev_priv(dev); struct macvtap_queue *q = macvtap_get_queue(dev, skb); netdev_features_t features = TAP_FEATURES; if (!q) goto drop; if (skb_queue_len(&q->sk.sk_receive_queue) >= dev->tx_queue_len) goto drop; skb->dev = dev; /* Apply the forward feature mask so that we perform segmentation * according to users wishes. This only works if VNET_HDR is * enabled. */ if (q->flags & IFF_VNET_HDR) features |= vlan->tap_features; if (netif_needs_gso(skb, features)) { struct sk_buff *segs = __skb_gso_segment(skb, features, false); if (IS_ERR(segs)) goto drop; if (!segs) { skb_queue_tail(&q->sk.sk_receive_queue, skb); goto wake_up; } kfree_skb(skb); while (segs) { struct sk_buff *nskb = segs->next; segs->next = NULL; skb_queue_tail(&q->sk.sk_receive_queue, segs); segs = nskb; } } else { skb_queue_tail(&q->sk.sk_receive_queue, skb); } wake_up: wake_up_interruptible_poll(sk_sleep(&q->sk), POLLIN | POLLRDNORM | POLLRDBAND); return NET_RX_SUCCESS; drop: kfree_skb(skb); return NET_RX_DROP; } /* * Receive is for data from the external interface (lowerdev), * in case of macvtap, we can treat that the same way as * forward, which macvlan cannot. */ static int macvtap_receive(struct sk_buff *skb) { skb_push(skb, ETH_HLEN); return macvtap_forward(skb->dev, skb); } static int macvtap_get_minor(struct macvlan_dev *vlan) { int retval = -ENOMEM; mutex_lock(&minor_lock); retval = idr_alloc(&minor_idr, vlan, 1, MACVTAP_NUM_DEVS, GFP_KERNEL); if (retval >= 0) { vlan->minor = retval; } else if (retval == -ENOSPC) { printk(KERN_ERR "too many macvtap devices\n"); retval = -EINVAL; } mutex_unlock(&minor_lock); return retval < 0 ? retval : 0; } 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; } static int macvtap_newlink(struct net *src_net, struct net_device *dev, struct nlattr *tb[], struct nlattr *data[]) { struct macvlan_dev *vlan = netdev_priv(dev); INIT_LIST_HEAD(&vlan->queue_list); /* Since macvlan supports all offloads by default, make * tap support all offloads also. */ vlan->tap_features = TUN_OFFLOADS; /* Don't put anything that may fail after macvlan_common_newlink * because we can't undo what it does. */ return macvlan_common_newlink(src_net, dev, tb, data, macvtap_receive, macvtap_forward); } static void macvtap_dellink(struct net_device *dev, struct list_head *head) { macvtap_del_queues(dev); macvlan_dellink(dev, head); } static void macvtap_setup(struct net_device *dev) { macvlan_common_setup(dev); dev->tx_queue_len = TUN_READQ_SIZE; } static struct rtnl_link_ops macvtap_link_ops __read_mostly = { .kind = "macvtap", .setup = macvtap_setup, .newlink = macvtap_newlink, .dellink = macvtap_dellink, }; static void macvtap_sock_write_space(struct sock *sk) { wait_queue_head_t *wqueue; if (!sock_writeable(sk) || !test_and_clear_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags)) return; wqueue = sk_sleep(sk); if (wqueue && waitqueue_active(wqueue)) wake_up_interruptible_poll(wqueue, POLLOUT | POLLWRNORM | POLLWRBAND); } static void macvtap_sock_destruct(struct sock *sk) { skb_queue_purge(&sk->sk_receive_queue); } static int macvtap_open(struct inode *inode, struct file *file) { struct net *net = current->nsproxy->net_ns; struct net_device *dev = dev_get_by_macvtap_minor(iminor(inode)); struct macvtap_queue *q; int err; err = -ENODEV; if (!dev) goto out; err = -ENOMEM; q = (struct macvtap_queue *)sk_alloc(net, AF_UNSPEC, GFP_KERNEL, &macvtap_proto); if (!q) goto out; RCU_INIT_POINTER(q->sock.wq, &q->wq); init_waitqueue_head(&q->wq.wait); q->sock.type = SOCK_RAW; q->sock.state = SS_CONNECTED; q->sock.file = file; q->sock.ops = &macvtap_socket_ops; sock_init_data(&q->sock, &q->sk); q->sk.sk_write_space = macvtap_sock_write_space; q->sk.sk_destruct = macvtap_sock_destruct; q->flags = IFF_VNET_HDR | IFF_NO_PI | IFF_TAP; q->vnet_hdr_sz = sizeof(struct virtio_net_hdr); /* * so far only KVM virtio_net uses macvtap, enable zero copy between * guest kernel and host kernel when lower device supports zerocopy * * The macvlan supports zerocopy iff the lower device supports zero * copy so we don't have to look at the lower device directly. */ if ((dev->features & NETIF_F_HIGHDMA) && (dev->features & NETIF_F_SG)) sock_set_flag(&q->sk, SOCK_ZEROCOPY); err = macvtap_set_queue(dev, file, q); if (err) sock_put(&q->sk); out: if (dev) dev_put(dev); return err; } static int macvtap_release(struct inode *inode, struct file *file) { struct macvtap_queue *q = file->private_data; macvtap_put_queue(q); return 0; } static unsigned int macvtap_poll(struct file *file, poll_table * wait) { struct macvtap_queue *q = file->private_data;