Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1561149 > unrolled thread
| Started by | Sainath Grandhi <sainath.grandhi@intel.com> |
|---|---|
| First post | 2017-01-18 01:10 +0100 |
| Last post | 2017-01-20 00:40 +0100 |
| Articles | 9 — 3 participants |
Back to article view | Back to linux.kernel
[PATCHv2 0/7] Refactor macvtap to re-use tap functionality by other virtual intefaces Sainath Grandhi <sainath.grandhi@intel.com> - 2017-01-18 01:10 +0100
[PATCHv2 1/7] TAP: Refactoring macvtap.c Sainath Grandhi <sainath.grandhi@intel.com> - 2017-01-18 01:10 +0100
[PATCHv2 7/7] IPVTAP: IP-VLAN based tap driver Sainath Grandhi <sainath.grandhi@intel.com> - 2017-01-18 01:10 +0100
Re: [PATCHv2 7/7] IPVTAP: IP-VLAN based tap driver David Miller <davem@davemloft.net> - 2017-01-18 22:30 +0100
RE: [PATCHv2 7/7] IPVTAP: IP-VLAN based tap driver "Grandhi, Sainath" <sainath.grandhi@intel.com> - 2017-01-20 00:40 +0100
[PATCHv2 6/7] TAP: tap as an independent module Sainath Grandhi <sainath.grandhi@intel.com> - 2017-01-18 01:10 +0100
[PATCHv2 3/7] TAP: Tap character device creation/destroy API Sainath Grandhi <sainath.grandhi@intel.com> - 2017-01-18 01:10 +0100
Re: [PATCHv2 3/7] TAP: Tap character device creation/destroy API David Miller <davem@davemloft.net> - 2017-01-18 22:30 +0100
RE: [PATCHv2 3/7] TAP: Tap character device creation/destroy API "Grandhi, Sainath" <sainath.grandhi@intel.com> - 2017-01-20 00:40 +0100
| From | Sainath Grandhi <sainath.grandhi@intel.com> |
|---|---|
| Date | 2017-01-18 01:10 +0100 |
| Subject | [PATCHv2 0/7] Refactor macvtap to re-use tap functionality by other virtual intefaces |
| Message-ID | <t0LZ7-5nf-3@gated-at.bofh.it> |
Tap character devices can be implemented on other virtual interfaces like ipvlan, similar to macvtap. Source code for tap functionality in macvtap can be re-used for this purpose. This patch series splits macvtap source into two modules, macvtap and tap. This patch series also includes a patch for implementing tap character device driver based on the IP-VLAN network interface, called ipvtap. These patches are tested on x86 platform. Sainath Grandhi (7): TAP: Refactoring macvtap.c TAP: Renaming tap related APIs, data structures, macros TAP: Tap character device creation/destroy API TAP: Abstract type of virtual interface from tap implementation TAP: Extending tap device create/destroy APIs TAP: tap as an independent module IPVTAP: IP-VLAN based tap driver drivers/net/Kconfig | 28 + drivers/net/Makefile | 2 + drivers/net/ipvlan/Makefile | 1 + drivers/net/ipvlan/ipvlan.h | 7 + drivers/net/ipvlan/ipvlan_core.c | 5 +- drivers/net/ipvlan/ipvlan_main.c | 27 +- drivers/net/ipvlan/ipvtap.c | 238 +++++++ drivers/net/macvlan.c | 2 +- drivers/net/macvtap.c | 1226 ++---------------------------------- drivers/net/tap.c | 1262 ++++++++++++++++++++++++++++++++++++++ drivers/vhost/Kconfig | 2 +- drivers/vhost/net.c | 3 +- include/linux/if_macvlan.h | 17 +- include/linux/if_tap.h | 75 +++ 14 files changed, 1686 insertions(+), 1209 deletions(-) create mode 100644 drivers/net/ipvlan/ipvtap.c create mode 100644 drivers/net/tap.c create mode 100644 include/linux/if_tap.h -- 2.7.4
[toc] | [next] | [standalone]
| From | Sainath Grandhi <sainath.grandhi@intel.com> |
|---|---|
| Date | 2017-01-18 01:10 +0100 |
| Subject | [PATCHv2 1/7] TAP: Refactoring macvtap.c |
| Message-ID | <t0LZ8-5nf-35@gated-at.bofh.it> |
| In reply to | #1561149 |
macvtap module has code for tap/queue management and link management. This patch splits
the code into macvtap_main.c for link management and tap.c for tap/queue management.
Functionality in tap.c can be re-used for implementing tap on other virtual interfaces.
Signed-off-by: Sainath Grandhi <sainath.grandhi@intel.com>
---
drivers/net/Makefile | 2 +
drivers/net/macvtap_main.c | 218 +++++++++++++++++++++++++++++++++++++++
drivers/net/{macvtap.c => tap.c} | 204 ++----------------------------------
include/linux/if_macvtap.h | 10 ++
4 files changed, 238 insertions(+), 196 deletions(-)
create mode 100644 drivers/net/macvtap_main.c
rename drivers/net/{macvtap.c => tap.c} (84%)
create mode 100644 include/linux/if_macvtap.h
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 7336cbd..19b03a9 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -29,6 +29,8 @@ obj-$(CONFIG_GTP) += gtp.o
obj-$(CONFIG_NLMON) += nlmon.o
obj-$(CONFIG_NET_VRF) += vrf.o
+macvtap-objs := macvtap_main.o tap.o
+
#
# Networking Drivers
#
diff --git a/drivers/net/macvtap_main.c b/drivers/net/macvtap_main.c
new file mode 100644
index 0000000..96ffa60
--- /dev/null
+++ b/drivers/net/macvtap_main.c
@@ -0,0 +1,218 @@
+#include <linux/etherdevice.h>
+#include <linux/if_macvlan.h>
+#include <linux/if_macvtap.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/wait.h>
+#include <linux/cdev.h>
+#include <linux/idr.h>
+#include <linux/fs.h>
+#include <linux/uio.h>
+
+#include <net/net_namespace.h>
+#include <net/rtnetlink.h>
+#include <net/sock.h>
+#include <linux/virtio_net.h>
+#include <linux/skb_array.h>
+
+/*
+ * Variables for dealing with macvtaps device numbers.
+ */
+static dev_t macvtap_major;
+#define MACVTAP_NUM_DEVS (1U << MINORBITS)
+
+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,
+};
+static struct cdev macvtap_cdev;
+
+#define TUN_OFFLOADS (NETIF_F_HW_CSUM | NETIF_F_TSO_ECN | NETIF_F_TSO | \
+ NETIF_F_TSO6 | NETIF_F_UFO)
+
+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);
+ int err;
+
+ INIT_LIST_HEAD(&vlan->queue_list);
+
+ /* Since macvlan supports all offloads by default, make
+ * tap support all offloads also.
+ */
+ vlan->tap_features = TUN_OFFLOADS;
+
+ err = netdev_rx_handler_register(dev, macvtap_handle_frame, vlan);
+ if (err)
+ return err;
+
+ /* Don't put anything that may fail after macvlan_common_newlink
+ * because we can't undo what it does.
+ */
+ err = macvlan_common_newlink(src_net, dev, tb, data);
+ if (err) {
+ netdev_rx_handler_unregister(dev);
+ return err;
+ }
+
+ return 0;
+}
+
+static void macvtap_dellink(struct net_device *dev,
+ struct list_head *head)
+{
+ netdev_rx_handler_unregister(dev);
+ 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 int macvtap_device_event(struct notifier_block *unused,
+ unsigned long event, void *ptr)
+{
+ struct net_device *dev = netdev_notifier_info_to_dev(ptr);
+ struct macvlan_dev *vlan;
+ struct device *classdev;
+ dev_t devt;
+ int err;
+ char tap_name[IFNAMSIZ];
+
+ if (dev->rtnl_link_ops != &macvtap_link_ops)
+ return NOTIFY_DONE;
+
+ snprintf(tap_name, IFNAMSIZ, "tap%d", dev->ifindex);
+ vlan = netdev_priv(dev);
+
+ switch (event) {
+ case NETDEV_REGISTER:
+ /* Create the device node here after the network device has
+ * been registered but before register_netdevice has
+ * finished running.
+ */
+ err = macvtap_get_minor(vlan);
+ if (err)
+ return notifier_from_errno(err);
+
+ devt = MKDEV(MAJOR(macvtap_major), vlan->minor);
+ classdev = device_create(&macvtap_class, &dev->dev, devt,
+ dev, tap_name);
+ if (IS_ERR(classdev)) {
+ macvtap_free_minor(vlan);
+ return notifier_from_errno(PTR_ERR(classdev));
+ }
+ err = sysfs_create_link(&dev->dev.kobj, &classdev->kobj,
+ tap_name);
+ if (err)
+ return notifier_from_errno(err);
+ break;
+ case NETDEV_UNREGISTER:
+ /* vlan->minor == 0 if NETDEV_REGISTER above failed */
+ if (vlan->minor == 0)
+ break;
+ sysfs_remove_link(&dev->dev.kobj, tap_name);
+ devt = MKDEV(MAJOR(macvtap_major), vlan->minor);
+ device_destroy(&macvtap_class, devt);
+ macvtap_free_minor(vlan);
+ break;
+ case NETDEV_CHANGE_TX_QUEUE_LEN:
+ if (macvtap_queue_resize(vlan))
+ return NOTIFY_BAD;
+ break;
+ }
+
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block macvtap_notifier_block __read_mostly = {
+ .notifier_call = macvtap_device_event,
+};
+
+extern struct file_operations macvtap_fops;
+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;
+
+ err = class_register(&macvtap_class);
+ if (err)
+ goto out3;
+
+ err = register_netdevice_notifier(&macvtap_notifier_block);
+ if (err)
+ goto out4;
+
+ err = macvlan_link_register(&macvtap_link_ops);
+ if (err)
+ goto out5;
+
+ return 0;
+
+out5:
+ unregister_netdevice_notifier(&macvtap_notifier_block);
+out4:
+ class_unregister(&macvtap_class);
+out3:
+ cdev_del(&macvtap_cdev);
+out2:
+ unregister_chrdev_region(macvtap_major, MACVTAP_NUM_DEVS);
+out1:
+ return err;
+}
+module_init(macvtap_init);
+
+extern struct idr minor_idr;
+static void macvtap_exit(void)
+{
+ rtnl_link_unregister(&macvtap_link_ops);
+ unregister_netdevice_notifier(&macvtap_notifier_block);
+ class_unregister(&macvtap_class);
+ cdev_del(&macvtap_cdev);
+ unregister_chrdev_region(macvtap_major, MACVTAP_NUM_DEVS);
+ idr_destroy(&minor_idr);
+}
+module_exit(macvtap_exit);
+
+MODULE_ALIAS_RTNL_LINK("macvtap");
+MODULE_AUTHOR("Arnd Bergmann <arnd@arndb.de>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/macvtap.c b/drivers/net/tap.c
similarity index 84%
rename from drivers/net/macvtap.c
rename to drivers/net/tap.c
index 5c26653..8f12a39 100644
--- a/drivers/net/macvtap.c
+++ b/drivers/net/tap.c
@@ -122,33 +122,14 @@ static struct proto macvtap_proto = {
.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_IDR(minor_idr);
#define GOODCOPY_LEN 128
-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,
-};
-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 | NETIF_F_FRAGLIST)
@@ -332,7 +313,7 @@ static struct macvtap_queue *macvtap_get_queue(struct net_device *dev,
* 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)
+void macvtap_del_queues(struct net_device *dev)
{
struct macvlan_dev *vlan = netdev_priv(dev);
struct macvtap_queue *q, *tmp;
@@ -352,7 +333,7 @@ static void macvtap_del_queues(struct net_device *dev)
vlan->numvtaps = MAX_MACVTAP_QUEUES;
}
-static rx_handler_result_t macvtap_handle_frame(struct sk_buff **pskb)
+rx_handler_result_t macvtap_handle_frame(struct sk_buff **pskb)
{
struct sk_buff *skb = *pskb;
struct net_device *dev = skb->dev;
@@ -407,7 +388,7 @@ static rx_handler_result_t macvtap_handle_frame(struct sk_buff **pskb)
/* 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.
+ * check, we either support them all or none.
*/
if (skb->ip_summed == CHECKSUM_PARTIAL &&
!(features & NETIF_F_CSUM_MASK) &&
@@ -428,7 +409,7 @@ static rx_handler_result_t macvtap_handle_frame(struct sk_buff **pskb)
return RX_HANDLER_CONSUMED;
}
-static int macvtap_get_minor(struct macvlan_dev *vlan)
+int macvtap_get_minor(struct macvlan_dev *vlan)
{
int retval = -ENOMEM;
@@ -444,7 +425,7 @@ static int macvtap_get_minor(struct macvlan_dev *vlan)
return retval < 0 ? retval : 0;
}
-static void macvtap_free_minor(struct macvlan_dev *vlan)
+void macvtap_free_minor(struct macvlan_dev *vlan)
{
mutex_lock(&minor_lock);
if (vlan->minor) {
@@ -469,59 +450,6 @@ static struct net_device *dev_get_by_macvtap_minor(int minor)
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);
- int err;
-
- INIT_LIST_HEAD(&vlan->queue_list);
-
- /* Since macvlan supports all offloads by default, make
- * tap support all offloads also.
- */
- vlan->tap_features = TUN_OFFLOADS;
-
- err = netdev_rx_handler_register(dev, macvtap_handle_frame, vlan);
- if (err)
- return err;
-
- /* Don't put anything that may fail after macvlan_common_newlink
- * because we can't undo what it does.
- */
- err = macvlan_common_newlink(src_net, dev, tb, data);
- if (err) {
- netdev_rx_handler_unregister(dev);
- return err;
- }
-
- return 0;
-}
-
-static void macvtap_dellink(struct net_device *dev,
- struct list_head *head)
-{
- netdev_rx_handler_unregister(dev);
- 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;
@@ -1169,7 +1097,7 @@ static long macvtap_compat_ioctl(struct file *file, unsigned int cmd,
}
#endif
-static const struct file_operations macvtap_fops = {
+const struct file_operations macvtap_fops = {
.owner = THIS_MODULE,
.open = macvtap_open,
.release = macvtap_release,
@@ -1235,7 +1163,7 @@ struct socket *macvtap_get_socket(struct file *file)
}
EXPORT_SYMBOL_GPL(macvtap_get_socket);
-static int macvtap_queue_resize(struct macvlan_dev *vlan)
+int macvtap_queue_resize(struct macvlan_dev *vlan)
{
struct net_device *dev = vlan->dev;
struct macvtap_queue *q;
@@ -1256,119 +1184,3 @@ static int macvtap_queue_resize(struct macvlan_dev *vlan)
kfree(arrays);
return ret;
}
-
-static int macvtap_device_event(struct notifier_block *unused,
- unsigned long event, void *ptr)
-{
- struct net_device *dev = netdev_notifier_info_to_dev(ptr);
- struct macvlan_dev *vlan;
- struct device *classdev;
- dev_t devt;
- int err;
- char tap_name[IFNAMSIZ];
-
- if (dev->rtnl_link_ops != &macvtap_link_ops)
- return NOTIFY_DONE;
-
- snprintf(tap_name, IFNAMSIZ, "tap%d", dev->ifindex);
- vlan = netdev_priv(dev);
-
- switch (event) {
- case NETDEV_REGISTER:
- /* Create the device node here after the network device has
- * been registered but before register_netdevice has
- * finished running.
- */
- err = macvtap_get_minor(vlan);
- if (err)
- return notifier_from_errno(err);
-
- devt = MKDEV(MAJOR(macvtap_major), vlan->minor);
- classdev = device_create(&macvtap_class, &dev->dev, devt,
- dev, tap_name);
- if (IS_ERR(classdev)) {
- macvtap_free_minor(vlan);
- return notifier_from_errno(PTR_ERR(classdev));
- }
- err = sysfs_create_link(&dev->dev.kobj, &classdev->kobj,
- tap_name);
- if (err)
- return notifier_from_errno(err);
- break;
- case NETDEV_UNREGISTER:
- /* vlan->minor == 0 if NETDEV_REGISTER above failed */
- if (vlan->minor == 0)
- break;
- sysfs_remove_link(&dev->dev.kobj, tap_name);
- devt = MKDEV(MAJOR(macvtap_major), vlan->minor);
- device_destroy(&macvtap_class, devt);
- macvtap_free_minor(vlan);
- break;
- case NETDEV_CHANGE_TX_QUEUE_LEN:
- if (macvtap_queue_resize(vlan))
- return NOTIFY_BAD;
- break;
- }
-
- return NOTIFY_DONE;
-}
-
-static struct notifier_block macvtap_notifier_block __read_mostly = {
- .notifier_call = macvtap_device_event,
-};
-
-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;
-
- err = class_register(&macvtap_class);
- if (err)
- goto out3;
-
- err = register_netdevice_notifier(&macvtap_notifier_block);
- if (err)
- goto out4;
-
- err = macvlan_link_register(&macvtap_link_ops);
- if (err)
- goto out5;
-
- return 0;
-
-out5:
- unregister_netdevice_notifier(&macvtap_notifier_block);
-out4:
- class_unregister(&macvtap_class);
-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);
- unregister_netdevice_notifier(&macvtap_notifier_block);
- class_unregister(&macvtap_class);
- cdev_del(&macvtap_cdev);
- unregister_chrdev_region(macvtap_major, MACVTAP_NUM_DEVS);
- idr_destroy(&minor_idr);
-}
-module_exit(macvtap_exit);
-
-MODULE_ALIAS_RTNL_LINK("macvtap");
-MODULE_AUTHOR("Arnd Bergmann <arnd@arndb.de>");
-MODULE_LICENSE("GPL");
diff --git a/include/linux/if_macvtap.h b/include/linux/if_macvtap.h
new file mode 100644
index 0000000..c9bf84b
--- /dev/null
+++ b/include/linux/if_macvtap.h
@@ -0,0 +1,10 @@
+#ifndef _LINUX_IF_MACVTAP_H_
+#define _LINUX_IF_MACVTAP_H_
+
+rx_handler_result_t macvtap_handle_frame(struct sk_buff **pskb);
+void macvtap_del_queues(struct net_device *dev);
+int macvtap_get_minor(struct macvlan_dev *vlan);
+void macvtap_free_minor(struct macvlan_dev *vlan);
+int macvtap_queue_resize(struct macvlan_dev *vlan);
+
+#endif /*_LINUX_IF_MACVTAP_H_*/
--
2.7.4
[toc] | [prev] | [next] | [standalone]
| From | Sainath Grandhi <sainath.grandhi@intel.com> |
|---|---|
| Date | 2017-01-18 01:10 +0100 |
| Subject | [PATCHv2 7/7] IPVTAP: IP-VLAN based tap driver |
| Message-ID | <t0LZ8-5nf-37@gated-at.bofh.it> |
| In reply to | #1561149 |
This patch adds a tap character device driver that is based on the
IP-VLAN network interface, called ipvtap. An ipvtap device can be created
in the same way as an ipvlan device, using 'type ipvtap', and then accessed
using the tap user space interface.
Signed-off-by: Sainath Grandhi <sainath.grandhi@intel.com>
---
drivers/net/Kconfig | 13 +++
drivers/net/Makefile | 1 +
drivers/net/ipvlan/Makefile | 1 +
drivers/net/ipvlan/ipvlan.h | 7 ++
drivers/net/ipvlan/ipvlan_core.c | 5 +-
drivers/net/ipvlan/ipvlan_main.c | 27 +++--
drivers/net/ipvlan/ipvtap.c | 238 +++++++++++++++++++++++++++++++++++++++
7 files changed, 278 insertions(+), 14 deletions(-)
create mode 100644 drivers/net/ipvlan/ipvtap.c
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 1c88437..d07b5f5 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -166,6 +166,19 @@ config IPVLAN
To compile this driver as a module, choose M here: the module
will be called ipvlan.
+config IPVTAP
+ tristate "IP-VLAN based tap driver"
+ depends on IPVLAN
+ depends on INET
+ depends on TAP
+ ---help---
+ This adds a specialized tap character device driver that is based
+ on the IP-VLAN network interface, called ipvtap. An ipvtap device
+ can be added in the same way as a ipvlan device, using 'type
+ ipvtap', and then be accessed through the tap user space interface.
+
+ To compile this driver as a module, choose M here: the module
+ will be called ipvtap.
config VXLAN
tristate "Virtual eXtensible Local Area Network (VXLAN)"
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 7dd86ca..98ed4d9 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -7,6 +7,7 @@
#
obj-$(CONFIG_BONDING) += bonding/
obj-$(CONFIG_IPVLAN) += ipvlan/
+obj-$(CONFIG_IPVTAP) += ipvlan/
obj-$(CONFIG_DUMMY) += dummy.o
obj-$(CONFIG_EQUALIZER) += eql.o
obj-$(CONFIG_IFB) += ifb.o
diff --git a/drivers/net/ipvlan/Makefile b/drivers/net/ipvlan/Makefile
index df79910..8a2c64d 100644
--- a/drivers/net/ipvlan/Makefile
+++ b/drivers/net/ipvlan/Makefile
@@ -3,5 +3,6 @@
#
obj-$(CONFIG_IPVLAN) += ipvlan.o
+obj-$(CONFIG_IPVTAP) += ipvtap.o
ipvlan-objs := ipvlan_core.o ipvlan_main.o
diff --git a/drivers/net/ipvlan/ipvlan.h b/drivers/net/ipvlan/ipvlan.h
index dbfbb33..4362d88 100644
--- a/drivers/net/ipvlan/ipvlan.h
+++ b/drivers/net/ipvlan/ipvlan.h
@@ -133,4 +133,11 @@ struct sk_buff *ipvlan_l3_rcv(struct net_device *dev, struct sk_buff *skb,
u16 proto);
unsigned int ipvlan_nf_input(void *priv, struct sk_buff *skb,
const struct nf_hook_state *state);
+void ipvlan_count_rx(const struct ipvl_dev *ipvlan,
+ unsigned int len, bool success, bool mcast);
+int ipvlan_link_new(struct net *src_net, struct net_device *dev,
+ struct nlattr *tb[], struct nlattr *data[]);
+void ipvlan_link_delete(struct net_device *dev, struct list_head *head);
+void ipvlan_link_setup(struct net_device *dev);
+int ipvlan_link_register(struct rtnl_link_ops *ops);
#endif /* __IPVLAN_H */
diff --git a/drivers/net/ipvlan/ipvlan_core.c b/drivers/net/ipvlan/ipvlan_core.c
index 83ce74a..9af16ab 100644
--- a/drivers/net/ipvlan/ipvlan_core.c
+++ b/drivers/net/ipvlan/ipvlan_core.c
@@ -16,8 +16,8 @@ void ipvlan_init_secret(void)
net_get_random_once(&ipvlan_jhash_secret, sizeof(ipvlan_jhash_secret));
}
-static void ipvlan_count_rx(const struct ipvl_dev *ipvlan,
- unsigned int len, bool success, bool mcast)
+void ipvlan_count_rx(const struct ipvl_dev *ipvlan,
+ unsigned int len, bool success, bool mcast)
{
if (!ipvlan)
return;
@@ -36,6 +36,7 @@ static void ipvlan_count_rx(const struct ipvl_dev *ipvlan,
this_cpu_inc(ipvlan->pcpu_stats->rx_errs);
}
}
+EXPORT_SYMBOL_GPL(ipvlan_count_rx);
static u8 ipvlan_get_v6_hash(const void *iaddr)
{
diff --git a/drivers/net/ipvlan/ipvlan_main.c b/drivers/net/ipvlan/ipvlan_main.c
index 8b0f993..ed750e2 100644
--- a/drivers/net/ipvlan/ipvlan_main.c
+++ b/drivers/net/ipvlan/ipvlan_main.c
@@ -494,8 +494,8 @@ static int ipvlan_nl_fillinfo(struct sk_buff *skb,
return ret;
}
-static int ipvlan_link_new(struct net *src_net, struct net_device *dev,
- struct nlattr *tb[], struct nlattr *data[])
+int ipvlan_link_new(struct net *src_net, struct net_device *dev,
+ struct nlattr *tb[], struct nlattr *data[])
{
struct ipvl_dev *ipvlan = netdev_priv(dev);
struct ipvl_port *port;
@@ -567,8 +567,9 @@ static int ipvlan_link_new(struct net *src_net, struct net_device *dev,
ipvlan_port_destroy(phy_dev);
return err;
}
+EXPORT_SYMBOL_GPL(ipvlan_link_new);
-static void ipvlan_link_delete(struct net_device *dev, struct list_head *head)
+void ipvlan_link_delete(struct net_device *dev, struct list_head *head)
{
struct ipvl_dev *ipvlan = netdev_priv(dev);
struct ipvl_addr *addr, *next;
@@ -583,8 +584,9 @@ static void ipvlan_link_delete(struct net_device *dev, struct list_head *head)
unregister_netdevice_queue(dev, head);
netdev_upper_dev_unlink(ipvlan->phy_dev, dev);
}
+EXPORT_SYMBOL_GPL(ipvlan_link_delete);
-static void ipvlan_link_setup(struct net_device *dev)
+void ipvlan_link_setup(struct net_device *dev)
{
ether_setup(dev);
@@ -595,6 +597,7 @@ static void ipvlan_link_setup(struct net_device *dev)
dev->header_ops = &ipvlan_header_ops;
dev->ethtool_ops = &ipvlan_ethtool_ops;
}
+EXPORT_SYMBOL_GPL(ipvlan_link_setup);
static const struct nla_policy ipvlan_nl_policy[IFLA_IPVLAN_MAX + 1] =
{
@@ -605,22 +608,22 @@ static struct rtnl_link_ops ipvlan_link_ops = {
.kind = "ipvlan",
.priv_size = sizeof(struct ipvl_dev),
- .get_size = ipvlan_nl_getsize,
- .policy = ipvlan_nl_policy,
- .validate = ipvlan_nl_validate,
- .fill_info = ipvlan_nl_fillinfo,
- .changelink = ipvlan_nl_changelink,
- .maxtype = IFLA_IPVLAN_MAX,
-
.setup = ipvlan_link_setup,
.newlink = ipvlan_link_new,
.dellink = ipvlan_link_delete,
};
-static int ipvlan_link_register(struct rtnl_link_ops *ops)
+int ipvlan_link_register(struct rtnl_link_ops *ops)
{
+ ops->get_size = ipvlan_nl_getsize;
+ ops->policy = ipvlan_nl_policy;
+ ops->validate = ipvlan_nl_validate;
+ ops->fill_info = ipvlan_nl_fillinfo;
+ ops->changelink = ipvlan_nl_changelink;
+ ops->maxtype = IFLA_IPVLAN_MAX;
return rtnl_link_register(ops);
}
+EXPORT_SYMBOL_GPL(ipvlan_link_register);
static int ipvlan_device_event(struct notifier_block *unused,
unsigned long event, void *ptr)
diff --git a/drivers/net/ipvlan/ipvtap.c b/drivers/net/ipvlan/ipvtap.c
new file mode 100644
index 0000000..54e9893
--- /dev/null
+++ b/drivers/net/ipvlan/ipvtap.c
@@ -0,0 +1,238 @@
+#include <linux/etherdevice.h>
+#include "ipvlan.h"
+#include <linux/if_vlan.h>
+#include <linux/if_tap.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/wait.h>
+#include <linux/cdev.h>
+#include <linux/idr.h>
+#include <linux/fs.h>
+#include <linux/uio.h>
+
+#include <net/net_namespace.h>
+#include <net/rtnetlink.h>
+#include <net/sock.h>
+#include <linux/virtio_net.h>
+
+#define TUN_OFFLOADS (NETIF_F_HW_CSUM | NETIF_F_TSO_ECN | NETIF_F_TSO | \
+ NETIF_F_TSO6 | NETIF_F_UFO)
+
+static dev_t ipvtap_major;
+static struct cdev ipvtap_cdev;
+
+static const void *ipvtap_net_namespace(struct device *d)
+{
+ struct net_device *dev = to_net_dev(d->parent);
+ return dev_net(dev);
+}
+
+static struct class ipvtap_class = {
+ .name = "ipvtap",
+ .owner = THIS_MODULE,
+ .ns_type = &net_ns_type_operations,
+ .namespace = ipvtap_net_namespace,
+};
+
+struct ipvtap_dev {
+ struct ipvl_dev vlan;
+ struct tap_dev tap;
+};
+
+static void ipvtap_count_tx_dropped(struct tap_dev *tap)
+{
+ struct ipvl_dev *vlan = (struct ipvl_dev *)container_of(tap, struct ipvtap_dev, tap);
+
+ this_cpu_inc(vlan->pcpu_stats->tx_drps);
+}
+
+static void ipvtap_count_rx_dropped(struct tap_dev *tap)
+{
+ struct ipvl_dev *vlan = (struct ipvl_dev *)container_of(tap, struct ipvtap_dev, tap);
+
+ ipvlan_count_rx(vlan, 0, 0, 0);
+}
+
+static void ipvtap_update_features(struct tap_dev *tap,
+ netdev_features_t features)
+{
+ struct ipvl_dev *vlan = (struct ipvl_dev *)container_of(tap, struct ipvtap_dev, tap);
+
+ vlan->sfeatures = features;
+ netdev_update_features(vlan->dev);
+}
+
+static int ipvtap_newlink(struct net *src_net,
+ struct net_device *dev,
+ struct nlattr *tb[],
+ struct nlattr *data[])
+{
+ struct ipvtap_dev *vlantap = netdev_priv(dev);
+ int err;
+
+ INIT_LIST_HEAD(&vlantap->tap.queue_list);
+
+ /* Since macvlan supports all offloads by default, make
+ * tap support all offloads also.
+ */
+ vlantap->tap.tap_features = TUN_OFFLOADS;
+ vlantap->tap.count_tx_dropped = ipvtap_count_tx_dropped;
+ vlantap->tap.update_features = ipvtap_update_features;
+ vlantap->tap.count_rx_dropped = ipvtap_count_rx_dropped;
+
+ err = netdev_rx_handler_register(dev, tap_handle_frame, &vlantap->tap);
+ if (err)
+ return err;
+
+ /* Don't put anything that may fail after macvlan_common_newlink
+ * because we can't undo what it does.
+ */
+ err = ipvlan_link_new(src_net, dev, tb, data);
+ if (err) {
+ netdev_rx_handler_unregister(dev);
+ return err;
+ }
+
+ vlantap->tap.dev = vlantap->vlan.dev;
+
+ return err;
+}
+
+static void ipvtap_dellink(struct net_device *dev,
+ struct list_head *head)
+{
+ struct ipvtap_dev *vlan = netdev_priv(dev);
+
+ netdev_rx_handler_unregister(dev);
+ tap_del_queues(&vlan->tap);
+ ipvlan_link_delete(dev, head);
+}
+
+static void ipvtap_setup(struct net_device *dev)
+{
+ ipvlan_link_setup(dev);
+ dev->tx_queue_len = TUN_READQ_SIZE;
+ dev->priv_flags &= ~IFF_NO_QUEUE;
+}
+
+static struct rtnl_link_ops ipvtap_link_ops __read_mostly = {
+ .kind = "ipvtap",
+ .setup = ipvtap_setup,
+ .newlink = ipvtap_newlink,
+ .dellink = ipvtap_dellink,
+ .priv_size = sizeof(struct ipvtap_dev),
+};
+
+static int ipvtap_device_event(struct notifier_block *unused,
+ unsigned long event, void *ptr)
+{
+ struct net_device *dev = netdev_notifier_info_to_dev(ptr);
+ struct ipvtap_dev *vlantap;
+ struct device *classdev;
+ dev_t devt;
+ int err;
+ char tap_name[IFNAMSIZ];
+
+ if (dev->rtnl_link_ops != &ipvtap_link_ops)
+ return NOTIFY_DONE;
+
+ snprintf(tap_name, IFNAMSIZ, "tap%d", dev->ifindex);
+ vlantap = netdev_priv(dev);
+
+ switch (event) {
+ case NETDEV_REGISTER:
+ /* Create the device node here after the network device has
+ * been registered but before register_netdevice has
+ * finished running.
+ */
+ err = tap_get_minor(ipvtap_major, &vlantap->tap);
+ if (err)
+ return notifier_from_errno(err);
+
+ devt = MKDEV(MAJOR(ipvtap_major), vlantap->tap.minor);
+ classdev = device_create(&ipvtap_class, &dev->dev, devt,
+ dev, tap_name);
+ if (IS_ERR(classdev)) {
+ tap_free_minor(ipvtap_major, &vlantap->tap);
+ return notifier_from_errno(PTR_ERR(classdev));
+ }
+ err = sysfs_create_link(&dev->dev.kobj, &classdev->kobj,
+ tap_name);
+ if (err)
+ return notifier_from_errno(err);
+ break;
+ case NETDEV_UNREGISTER:
+ /* vlan->minor == 0 if NETDEV_REGISTER above failed */
+ if (vlantap->tap.minor == 0)
+ break;
+ sysfs_remove_link(&dev->dev.kobj, tap_name);
+ devt = MKDEV(MAJOR(ipvtap_major), vlantap->tap.minor);
+ device_destroy(&ipvtap_class, devt);
+ tap_free_minor(ipvtap_major, &vlantap->tap);
+ break;
+ case NETDEV_CHANGE_TX_QUEUE_LEN:
+ if (tap_queue_resize(&vlantap->tap))
+ return NOTIFY_BAD;
+ break;
+ }
+
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block ipvtap_notifier_block __read_mostly = {
+ .notifier_call = ipvtap_device_event,
+};
+
+static int ipvtap_init(void)
+{
+ int err;
+
+ err = tap_create_cdev(&ipvtap_cdev, &ipvtap_major, "ipvtap");
+
+ if (err)
+ goto out1;
+
+ err = class_register(&ipvtap_class);
+ if (err)
+ goto out2;
+
+ err = register_netdevice_notifier(&ipvtap_notifier_block);
+ if (err)
+ goto out3;
+
+ err = ipvlan_link_register(&ipvtap_link_ops);
+ if (err)
+ goto out4;
+
+ return 0;
+
+out4:
+ unregister_netdevice_notifier(&ipvtap_notifier_block);
+out3:
+ class_unregister(&ipvtap_class);
+out2:
+ cdev_del(&ipvtap_cdev);
+out1:
+ return err;
+}
+module_init(ipvtap_init);
+
+static void ipvtap_exit(void)
+{
+ rtnl_link_unregister(&ipvtap_link_ops);
+ unregister_netdevice_notifier(&ipvtap_notifier_block);
+ class_unregister(&ipvtap_class);
+ tap_destroy_cdev(ipvtap_major, &ipvtap_cdev);
+}
+module_exit(ipvtap_exit);
+MODULE_ALIAS_RTNL_LINK("ipvtap");
+MODULE_AUTHOR("Sainath Grandhi <sainath.grandhi@intel.com>");
+MODULE_LICENSE("GPL");
--
2.7.4
[toc] | [prev] | [next] | [standalone]
| From | David Miller <davem@davemloft.net> |
|---|---|
| Date | 2017-01-18 22:30 +0100 |
| Subject | Re: [PATCHv2 7/7] IPVTAP: IP-VLAN based tap driver |
| Message-ID | <t15XR-Vm-45@gated-at.bofh.it> |
| In reply to | #1561154 |
From: Sainath Grandhi <sainath.grandhi@intel.com>
Date: Tue, 17 Jan 2017 16:03:06 -0800
> +static void ipvtap_count_tx_dropped(struct tap_dev *tap)
> +{
> + struct ipvl_dev *vlan = (struct ipvl_dev *)container_of(tap, struct ipvtap_dev, tap);
...
> +static void ipvtap_count_rx_dropped(struct tap_dev *tap)
> +{
> + struct ipvl_dev *vlan = (struct ipvl_dev *)container_of(tap, struct ipvtap_dev, tap);
...
> +static void ipvtap_update_features(struct tap_dev *tap,
> + netdev_features_t features)
> +{
> + struct ipvl_dev *vlan = (struct ipvl_dev *)container_of(tap, struct ipvtap_dev, tap);
More unnecessary casts, please remove.
[toc] | [prev] | [next] | [standalone]
| From | "Grandhi, Sainath" <sainath.grandhi@intel.com> |
|---|---|
| Date | 2017-01-20 00:40 +0100 |
| Subject | RE: [PATCHv2 7/7] IPVTAP: IP-VLAN based tap driver |
| Message-ID | <t1utb-83Y-7@gated-at.bofh.it> |
| In reply to | #1562189 |
> -----Original Message-----
> From: David Miller [mailto:davem@davemloft.net]
> Sent: Wednesday, January 18, 2017 1:29 PM
> To: Grandhi, Sainath <sainath.grandhi@intel.com>
> Cc: netdev@vger.kernel.org; mahesh@bandewar.net; linux-
> kernel@vger.kernel.org
> Subject: Re: [PATCHv2 7/7] IPVTAP: IP-VLAN based tap driver
>
> From: Sainath Grandhi <sainath.grandhi@intel.com>
> Date: Tue, 17 Jan 2017 16:03:06 -0800
>
> > +static void ipvtap_count_tx_dropped(struct tap_dev *tap) {
> > + struct ipvl_dev *vlan = (struct ipvl_dev *)container_of(tap, struct
> > +ipvtap_dev, tap);
> ...
> > +static void ipvtap_count_rx_dropped(struct tap_dev *tap) {
> > + struct ipvl_dev *vlan = (struct ipvl_dev *)container_of(tap, struct
> > +ipvtap_dev, tap);
> ...
> > +static void ipvtap_update_features(struct tap_dev *tap,
> > + netdev_features_t features)
> > +{
> > + struct ipvl_dev *vlan = (struct ipvl_dev *)container_of(tap, struct
> > +ipvtap_dev, tap);
>
> More unnecessary casts, please remove.
Will take care of it in next revision. Thanks.
[toc] | [prev] | [next] | [standalone]
| From | Sainath Grandhi <sainath.grandhi@intel.com> |
|---|---|
| Date | 2017-01-18 01:10 +0100 |
| Subject | [PATCHv2 6/7] TAP: tap as an independent module |
| Message-ID | <t0LZ9-5nf-63@gated-at.bofh.it> |
| In reply to | #1561149 |
This patch makes tap a separate module for other types of virtual interfaces, for example,
ipvlan to use.
Signed-off-by: Sainath Grandhi <sainath.grandhi@intel.com>
---
drivers/net/Kconfig | 15 +++++++++++++++
drivers/net/Makefile | 3 +--
drivers/net/{macvtap_main.c => macvtap.c} | 1 -
drivers/net/tap.c | 11 +++++++++++
drivers/vhost/Kconfig | 2 +-
include/linux/if_tap.h | 4 ++--
6 files changed, 30 insertions(+), 6 deletions(-)
rename drivers/net/{macvtap_main.c => macvtap.c} (99%)
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 95c32f2..1c88437 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -135,6 +135,7 @@ config MACVTAP
tristate "MAC-VLAN based tap driver"
depends on MACVLAN
depends on INET
+ depends on TAP
help
This adds a specialized tap character device driver that is based
on the MAC-VLAN network interface, called macvtap. A macvtap device
@@ -284,6 +285,20 @@ config TUN
If you don't know what to use this for, you don't need it.
+config TAP
+ tristate "TAP module support for virtual interfaces"
+ ---help---
+ TAP module serves two purposes. This can be used as library of functions
+ for virtual interfaces to implement tap functionality.
+
+ This module also includes character device file and socket operations
+ that can be used by virtual interface implementing tap.
+
+ To compile this driver as a module, choose M here: the module
+ will be called tap.
+
+ If you don't know what to use this for, you don't need it.
+
config TUN_VNET_CROSS_LE
bool "Support for cross-endian vnet headers on little-endian kernels"
default n
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 19b03a9..7dd86ca 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -21,6 +21,7 @@ obj-$(CONFIG_PHYLIB) += phy/
obj-$(CONFIG_RIONET) += rionet.o
obj-$(CONFIG_NET_TEAM) += team/
obj-$(CONFIG_TUN) += tun.o
+obj-$(CONFIG_TAP) += tap.o
obj-$(CONFIG_VETH) += veth.o
obj-$(CONFIG_VIRTIO_NET) += virtio_net.o
obj-$(CONFIG_VXLAN) += vxlan.o
@@ -29,8 +30,6 @@ obj-$(CONFIG_GTP) += gtp.o
obj-$(CONFIG_NLMON) += nlmon.o
obj-$(CONFIG_NET_VRF) += vrf.o
-macvtap-objs := macvtap_main.o tap.o
-
#
# Networking Drivers
#
diff --git a/drivers/net/macvtap_main.c b/drivers/net/macvtap.c
similarity index 99%
rename from drivers/net/macvtap_main.c
rename to drivers/net/macvtap.c
index 3f047b4..3efed94 100644
--- a/drivers/net/macvtap_main.c
+++ b/drivers/net/macvtap.c
@@ -232,7 +232,6 @@ static int macvtap_init(void)
}
module_init(macvtap_init);
-extern struct idr minor_idr;
static void macvtap_exit(void)
{
rtnl_link_unregister(&macvtap_link_ops);
diff --git a/drivers/net/tap.c b/drivers/net/tap.c
index 7f38dbe..32066dd 100644
--- a/drivers/net/tap.c
+++ b/drivers/net/tap.c
@@ -311,6 +311,7 @@ void tap_del_queues(struct tap_dev *tap)
/* guarantee that any future tap_set_queue will fail */
tap->numvtaps = MAX_TAP_QUEUES;
}
+EXPORT_SYMBOL_GPL(tap_del_queues);
rx_handler_result_t tap_handle_frame(struct sk_buff **pskb)
{
@@ -388,6 +389,7 @@ rx_handler_result_t tap_handle_frame(struct sk_buff **pskb)
kfree_skb(skb);
return RX_HANDLER_CONSUMED;
}
+EXPORT_SYMBOL_GPL(tap_handle_frame);
static struct major_info *tap_get_major(int major)
{
@@ -422,6 +424,7 @@ int tap_get_minor(dev_t major, struct tap_dev *tap)
mutex_unlock(&tap_major->minor_lock);
return retval < 0 ? retval : 0;
}
+EXPORT_SYMBOL_GPL(tap_get_minor);
void tap_free_minor(dev_t major, struct tap_dev *tap)
{
@@ -438,6 +441,7 @@ void tap_free_minor(dev_t major, struct tap_dev *tap)
}
mutex_unlock(&tap_major->minor_lock);
}
+EXPORT_SYMBOL_GPL(tap_free_minor);
static struct tap_dev *dev_get_by_tap_file(int major, int minor)
{
@@ -1193,6 +1197,7 @@ int tap_queue_resize(struct tap_dev *tap)
kfree(arrays);
return ret;
}
+EXPORT_SYMBOL_GPL(tap_queue_resize);
static int tap_list_add(dev_t major, const char *device_name)
{
@@ -1236,6 +1241,7 @@ int tap_create_cdev(struct cdev *tap_cdev,
out1:
return err;
}
+EXPORT_SYMBOL_GPL(tap_create_cdev);
void tap_destroy_cdev(dev_t major, struct cdev *tap_cdev)
{
@@ -1249,3 +1255,8 @@ void tap_destroy_cdev(dev_t major, struct cdev *tap_cdev)
unregister_chrdev_region(major, TAP_NUM_DEVS);
idr_destroy(&tap_major->minor_idr);
}
+EXPORT_SYMBOL_GPL(tap_destroy_cdev);
+
+MODULE_AUTHOR("Arnd Bergmann <arnd@arndb.de>");
+MODULE_AUTHOR("Sainath Grandhi <sainath.grandhi@intel.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/vhost/Kconfig b/drivers/vhost/Kconfig
index 40764ec..cfdecea 100644
--- a/drivers/vhost/Kconfig
+++ b/drivers/vhost/Kconfig
@@ -1,6 +1,6 @@
config VHOST_NET
tristate "Host kernel accelerator for virtio net"
- depends on NET && EVENTFD && (TUN || !TUN) && (MACVTAP || !MACVTAP)
+ depends on NET && EVENTFD && (TUN || !TUN) && (TAP || !TAP)
select VHOST
---help---
This kernel module can be loaded in host kernel to accelerate
diff --git a/include/linux/if_tap.h b/include/linux/if_tap.h
index 362e71c..3482c3c 100644
--- a/include/linux/if_tap.h
+++ b/include/linux/if_tap.h
@@ -1,7 +1,7 @@
#ifndef _LINUX_IF_TAP_H_
#define _LINUX_IF_TAP_H_
-#if IS_ENABLED(CONFIG_MACVTAP)
+#if IS_ENABLED(CONFIG_TAP)
struct socket *tap_get_socket(struct file *);
#else
#include <linux/err.h>
@@ -12,7 +12,7 @@ static inline struct socket *tap_get_socket(struct file *f)
{
return ERR_PTR(-EINVAL);
}
-#endif /* CONFIG_MACVTAP */
+#endif /* CONFIG_TAP */
#include <net/sock.h>
#include <linux/skb_array.h>
--
2.7.4
[toc] | [prev] | [next] | [standalone]
| From | Sainath Grandhi <sainath.grandhi@intel.com> |
|---|---|
| Date | 2017-01-18 01:10 +0100 |
| Subject | [PATCHv2 3/7] TAP: Tap character device creation/destroy API |
| Message-ID | <t0LZ8-5nf-45@gated-at.bofh.it> |
| In reply to | #1561149 |
This patch provides tap device create/destroy APIs in tap.c.
Signed-off-by: Sainath Grandhi <sainath.grandhi@intel.com>
---
drivers/net/macvtap_main.c | 29 +++++++--------------
drivers/net/tap.c | 63 ++++++++++++++++++++++++++++++++++++++--------
include/linux/if_tap.h | 5 +++-
3 files changed, 65 insertions(+), 32 deletions(-)
diff --git a/drivers/net/macvtap_main.c b/drivers/net/macvtap_main.c
index 548f339..32ad560 100644
--- a/drivers/net/macvtap_main.c
+++ b/drivers/net/macvtap_main.c
@@ -28,7 +28,6 @@
* Variables for dealing with macvtaps device numbers.
*/
static dev_t macvtap_major;
-#define MACVTAP_NUM_DEVS (1U << MINORBITS)
static const void *macvtap_net_namespace(struct device *d)
{
@@ -159,43 +158,35 @@ static struct notifier_block macvtap_notifier_block __read_mostly = {
.notifier_call = macvtap_device_event,
};
-extern struct file_operations tap_fops;
static int macvtap_init(void)
{
int err;
- err = alloc_chrdev_region(&macvtap_major, 0,
- MACVTAP_NUM_DEVS, "macvtap");
- if (err)
- goto out1;
+ err = tap_create_cdev(&macvtap_cdev, &macvtap_major, "macvtap");
- cdev_init(&macvtap_cdev, &tap_fops);
- err = cdev_add(&macvtap_cdev, macvtap_major, MACVTAP_NUM_DEVS);
if (err)
- goto out2;
+ goto out1;
err = class_register(&macvtap_class);
if (err)
- goto out3;
+ goto out2;
err = register_netdevice_notifier(&macvtap_notifier_block);
if (err)
- goto out4;
+ goto out3;
err = macvlan_link_register(&macvtap_link_ops);
if (err)
- goto out5;
+ goto out4;
return 0;
-out5:
- unregister_netdevice_notifier(&macvtap_notifier_block);
out4:
- class_unregister(&macvtap_class);
+ unregister_netdevice_notifier(&macvtap_notifier_block);
out3:
- cdev_del(&macvtap_cdev);
+ class_unregister(&macvtap_class);
out2:
- unregister_chrdev_region(macvtap_major, MACVTAP_NUM_DEVS);
+ cdev_del(&macvtap_cdev);
out1:
return err;
}
@@ -207,9 +198,7 @@ static void macvtap_exit(void)
rtnl_link_unregister(&macvtap_link_ops);
unregister_netdevice_notifier(&macvtap_notifier_block);
class_unregister(&macvtap_class);
- cdev_del(&macvtap_cdev);
- unregister_chrdev_region(macvtap_major, MACVTAP_NUM_DEVS);
- idr_destroy(&minor_idr);
+ tap_destroy_cdev(macvtap_major, &macvtap_cdev);
}
module_exit(macvtap_exit);
diff --git a/drivers/net/tap.c b/drivers/net/tap.c
index d0807c2..774ef33 100644
--- a/drivers/net/tap.c
+++ b/drivers/net/tap.c
@@ -123,8 +123,12 @@ static struct proto tap_proto = {
};
#define TAP_NUM_DEVS (1U << MINORBITS)
-static DEFINE_MUTEX(minor_lock);
-DEFINE_IDR(minor_idr);
+struct major_info {
+ dev_t major;
+ struct idr minor_idr;
+ struct mutex minor_lock;
+ const char *device_name;
+} macvtap_major;
#define GOODCOPY_LEN 128
@@ -413,26 +417,26 @@ int tap_get_minor(struct macvlan_dev *vlan)
{
int retval = -ENOMEM;
- mutex_lock(&minor_lock);
- retval = idr_alloc(&minor_idr, vlan, 1, TAP_NUM_DEVS, GFP_KERNEL);
+ mutex_lock(&macvtap_major.minor_lock);
+ retval = idr_alloc(&macvtap_major.minor_idr, vlan, 1, TAP_NUM_DEVS, GFP_KERNEL);
if (retval >= 0) {
vlan->minor = retval;
} else if (retval == -ENOSPC) {
netdev_err(vlan->dev, "Too many tap devices\n");
retval = -EINVAL;
}
- mutex_unlock(&minor_lock);
+ mutex_unlock(&macvtap_major.minor_lock);
return retval < 0 ? retval : 0;
}
void tap_free_minor(struct macvlan_dev *vlan)
{
- mutex_lock(&minor_lock);
+ mutex_lock(&macvtap_major.minor_lock);
if (vlan->minor) {
- idr_remove(&minor_idr, vlan->minor);
+ idr_remove(&macvtap_major.minor_idr, vlan->minor);
vlan->minor = 0;
}
- mutex_unlock(&minor_lock);
+ mutex_unlock(&macvtap_major.minor_lock);
}
static struct net_device *dev_get_by_tap_minor(int minor)
@@ -440,13 +444,13 @@ static struct net_device *dev_get_by_tap_minor(int minor)
struct net_device *dev = NULL;
struct macvlan_dev *vlan;
- mutex_lock(&minor_lock);
- vlan = idr_find(&minor_idr, minor);
+ mutex_lock(&macvtap_major.minor_lock);
+ vlan = idr_find(&macvtap_major.minor_idr, minor);
if (vlan) {
dev = vlan->dev;
dev_hold(dev);
}
- mutex_unlock(&minor_lock);
+ mutex_unlock(&macvtap_major.minor_lock);
return dev;
}
@@ -1184,3 +1188,40 @@ int tap_queue_resize(struct macvlan_dev *vlan)
kfree(arrays);
return ret;
}
+
+int tap_create_cdev(struct cdev *tap_cdev,
+ dev_t *tap_major, const char *device_name)
+{
+ int err;
+
+ err = alloc_chrdev_region(tap_major, 0, TAP_NUM_DEVS, device_name);
+
+ if (err)
+ goto out1;
+
+ cdev_init(tap_cdev, &tap_fops);
+ err = cdev_add(tap_cdev, *tap_major, TAP_NUM_DEVS);
+ if (err)
+ goto out2;
+
+ macvtap_major.major = MAJOR(*tap_major);
+
+ idr_init(&macvtap_major.minor_idr);
+ mutex_init(&macvtap_major.minor_lock);
+
+ macvtap_major.device_name = device_name;
+
+ return err;
+
+out2:
+ unregister_chrdev_region(*tap_major, TAP_NUM_DEVS);
+out1:
+ return err;
+}
+
+void tap_destroy_cdev(dev_t major, struct cdev *tap_cdev)
+{
+ cdev_del(tap_cdev);
+ unregister_chrdev_region(major, TAP_NUM_DEVS);
+ idr_destroy(&macvtap_major.minor_idr);
+}
diff --git a/include/linux/if_tap.h b/include/linux/if_tap.h
index d887aaa..a2dfd90 100644
--- a/include/linux/if_tap.h
+++ b/include/linux/if_tap.h
@@ -10,7 +10,7 @@ struct file;
struct socket;
static inline struct socket *tap_get_socket(struct file *f)
{
- return ERR_PTR(-EINVAL);
+ return ERR_PTR(-EINVAL);
}
#endif /* CONFIG_MACVTAP */
@@ -19,5 +19,8 @@ void tap_del_queues(struct net_device *dev);
int tap_get_minor(struct macvlan_dev *vlan);
void tap_free_minor(struct macvlan_dev *vlan);
int tap_queue_resize(struct macvlan_dev *vlan);
+int tap_create_cdev(struct cdev *tap_cdev,
+ dev_t *tap_major, const char *device_name);
+void tap_destroy_cdev(dev_t major, struct cdev *tap_cdev);
#endif /*_LINUX_IF_TAP_H_*/
--
2.7.4
[toc] | [prev] | [next] | [standalone]
| From | David Miller <davem@davemloft.net> |
|---|---|
| Date | 2017-01-18 22:30 +0100 |
| Subject | Re: [PATCHv2 3/7] TAP: Tap character device creation/destroy API |
| Message-ID | <t15XR-Vm-39@gated-at.bofh.it> |
| In reply to | #1561162 |
From: Sainath Grandhi <sainath.grandhi@intel.com>
Date: Tue, 17 Jan 2017 16:03:02 -0800
> +int tap_create_cdev(struct cdev *tap_cdev,
> + dev_t *tap_major, const char *device_name)
> +{
> + int err;
> +
> + err = alloc_chrdev_region(tap_major, 0, TAP_NUM_DEVS, device_name);
> +
> + if (err)
> + goto out1;
No need to have an empty line between the alloc_chrdev_region() call
and the "if (err)" test.
> diff --git a/include/linux/if_tap.h b/include/linux/if_tap.h
> index d887aaa..a2dfd90 100644
> --- a/include/linux/if_tap.h
> +++ b/include/linux/if_tap.h
> @@ -10,7 +10,7 @@ struct file;
> struct socket;
> static inline struct socket *tap_get_socket(struct file *f)
> {
> - return ERR_PTR(-EINVAL);
> + return ERR_PTR(-EINVAL);
> }
Instead of having to fix up the indentation here, get it right in the first place
in patch #2.
[toc] | [prev] | [next] | [standalone]
| From | "Grandhi, Sainath" <sainath.grandhi@intel.com> |
|---|---|
| Date | 2017-01-20 00:40 +0100 |
| Subject | RE: [PATCHv2 3/7] TAP: Tap character device creation/destroy API |
| Message-ID | <t1utb-83Y-1@gated-at.bofh.it> |
| In reply to | #1562187 |
> -----Original Message-----
> From: David Miller [mailto:davem@davemloft.net]
> Sent: Wednesday, January 18, 2017 1:27 PM
> To: Grandhi, Sainath <sainath.grandhi@intel.com>
> Cc: netdev@vger.kernel.org; mahesh@bandewar.net; linux-
> kernel@vger.kernel.org
> Subject: Re: [PATCHv2 3/7] TAP: Tap character device creation/destroy API
>
> From: Sainath Grandhi <sainath.grandhi@intel.com>
> Date: Tue, 17 Jan 2017 16:03:02 -0800
>
> > +int tap_create_cdev(struct cdev *tap_cdev,
> > + dev_t *tap_major, const char *device_name) {
> > + int err;
> > +
> > + err = alloc_chrdev_region(tap_major, 0, TAP_NUM_DEVS,
> device_name);
> > +
> > + if (err)
> > + goto out1;
>
> No need to have an empty line between the alloc_chrdev_region() call and
> the "if (err)" test.
>
> > diff --git a/include/linux/if_tap.h b/include/linux/if_tap.h index
> > d887aaa..a2dfd90 100644
> > --- a/include/linux/if_tap.h
> > +++ b/include/linux/if_tap.h
> > @@ -10,7 +10,7 @@ struct file;
> > struct socket;
> > static inline struct socket *tap_get_socket(struct file *f) {
> > - return ERR_PTR(-EINVAL);
> > + return ERR_PTR(-EINVAL);
> > }
>
> Instead of having to fix up the indentation here, get it right in the first place in
> patch #2.
Will work on these two comments in next version.
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web