xref: /openbmc/linux/drivers/net/macvtap.c (revision fb652fdfe83710da0ca13448a41b7ed027d0a984)
19a393b5dSSainath Grandhi #include <linux/etherdevice.h>
29a393b5dSSainath Grandhi #include <linux/if_macvlan.h>
39a393b5dSSainath Grandhi #include <linux/if_tap.h>
49a393b5dSSainath Grandhi #include <linux/if_vlan.h>
59a393b5dSSainath Grandhi #include <linux/interrupt.h>
69a393b5dSSainath Grandhi #include <linux/nsproxy.h>
79a393b5dSSainath Grandhi #include <linux/compat.h>
89a393b5dSSainath Grandhi #include <linux/if_tun.h>
99a393b5dSSainath Grandhi #include <linux/module.h>
109a393b5dSSainath Grandhi #include <linux/skbuff.h>
119a393b5dSSainath Grandhi #include <linux/cache.h>
12174cd4b1SIngo Molnar #include <linux/sched/signal.h>
139a393b5dSSainath Grandhi #include <linux/types.h>
149a393b5dSSainath Grandhi #include <linux/slab.h>
159a393b5dSSainath Grandhi #include <linux/wait.h>
169a393b5dSSainath Grandhi #include <linux/cdev.h>
179a393b5dSSainath Grandhi #include <linux/idr.h>
189a393b5dSSainath Grandhi #include <linux/fs.h>
199a393b5dSSainath Grandhi #include <linux/uio.h>
209a393b5dSSainath Grandhi 
219a393b5dSSainath Grandhi #include <net/net_namespace.h>
229a393b5dSSainath Grandhi #include <net/rtnetlink.h>
239a393b5dSSainath Grandhi #include <net/sock.h>
249a393b5dSSainath Grandhi #include <linux/virtio_net.h>
259a393b5dSSainath Grandhi #include <linux/skb_array.h>
269a393b5dSSainath Grandhi 
279a393b5dSSainath Grandhi struct macvtap_dev {
289a393b5dSSainath Grandhi 	struct macvlan_dev vlan;
299a393b5dSSainath Grandhi 	struct tap_dev    tap;
309a393b5dSSainath Grandhi };
319a393b5dSSainath Grandhi 
329a393b5dSSainath Grandhi /*
339a393b5dSSainath Grandhi  * Variables for dealing with macvtaps device numbers.
349a393b5dSSainath Grandhi  */
359a393b5dSSainath Grandhi static dev_t macvtap_major;
369a393b5dSSainath Grandhi 
379a393b5dSSainath Grandhi static const void *macvtap_net_namespace(struct device *d)
389a393b5dSSainath Grandhi {
399a393b5dSSainath Grandhi 	struct net_device *dev = to_net_dev(d->parent);
409a393b5dSSainath Grandhi 	return dev_net(dev);
419a393b5dSSainath Grandhi }
429a393b5dSSainath Grandhi 
439a393b5dSSainath Grandhi static struct class macvtap_class = {
449a393b5dSSainath Grandhi 	.name = "macvtap",
459a393b5dSSainath Grandhi 	.owner = THIS_MODULE,
469a393b5dSSainath Grandhi 	.ns_type = &net_ns_type_operations,
479a393b5dSSainath Grandhi 	.namespace = macvtap_net_namespace,
489a393b5dSSainath Grandhi };
499a393b5dSSainath Grandhi static struct cdev macvtap_cdev;
509a393b5dSSainath Grandhi 
519a393b5dSSainath Grandhi #define TUN_OFFLOADS (NETIF_F_HW_CSUM | NETIF_F_TSO_ECN | NETIF_F_TSO | \
52*fb652fdfSDavid S. Miller 		      NETIF_F_TSO6)
539a393b5dSSainath Grandhi 
549a393b5dSSainath Grandhi static void macvtap_count_tx_dropped(struct tap_dev *tap)
559a393b5dSSainath Grandhi {
569a393b5dSSainath Grandhi 	struct macvtap_dev *vlantap = container_of(tap, struct macvtap_dev, tap);
579a393b5dSSainath Grandhi 	struct macvlan_dev *vlan = &vlantap->vlan;
589a393b5dSSainath Grandhi 
599a393b5dSSainath Grandhi 	this_cpu_inc(vlan->pcpu_stats->tx_dropped);
609a393b5dSSainath Grandhi }
619a393b5dSSainath Grandhi 
629a393b5dSSainath Grandhi static void macvtap_count_rx_dropped(struct tap_dev *tap)
639a393b5dSSainath Grandhi {
649a393b5dSSainath Grandhi 	struct macvtap_dev *vlantap = container_of(tap, struct macvtap_dev, tap);
659a393b5dSSainath Grandhi 	struct macvlan_dev *vlan = &vlantap->vlan;
669a393b5dSSainath Grandhi 
679a393b5dSSainath Grandhi 	macvlan_count_rx(vlan, 0, 0, 0);
689a393b5dSSainath Grandhi }
699a393b5dSSainath Grandhi 
709a393b5dSSainath Grandhi static void macvtap_update_features(struct tap_dev *tap,
719a393b5dSSainath Grandhi 				    netdev_features_t features)
729a393b5dSSainath Grandhi {
739a393b5dSSainath Grandhi 	struct macvtap_dev *vlantap = container_of(tap, struct macvtap_dev, tap);
749a393b5dSSainath Grandhi 	struct macvlan_dev *vlan = &vlantap->vlan;
759a393b5dSSainath Grandhi 
769a393b5dSSainath Grandhi 	vlan->set_features = features;
779a393b5dSSainath Grandhi 	netdev_update_features(vlan->dev);
789a393b5dSSainath Grandhi }
799a393b5dSSainath Grandhi 
807a3f4a18SMatthias Schiffer static int macvtap_newlink(struct net *src_net, struct net_device *dev,
817a3f4a18SMatthias Schiffer 			   struct nlattr *tb[], struct nlattr *data[],
827a3f4a18SMatthias Schiffer 			   struct netlink_ext_ack *extack)
839a393b5dSSainath Grandhi {
849a393b5dSSainath Grandhi 	struct macvtap_dev *vlantap = netdev_priv(dev);
859a393b5dSSainath Grandhi 	int err;
869a393b5dSSainath Grandhi 
879a393b5dSSainath Grandhi 	INIT_LIST_HEAD(&vlantap->tap.queue_list);
889a393b5dSSainath Grandhi 
899a393b5dSSainath Grandhi 	/* Since macvlan supports all offloads by default, make
909a393b5dSSainath Grandhi 	 * tap support all offloads also.
919a393b5dSSainath Grandhi 	 */
929a393b5dSSainath Grandhi 	vlantap->tap.tap_features = TUN_OFFLOADS;
939a393b5dSSainath Grandhi 
949a393b5dSSainath Grandhi 	/* Register callbacks for rx/tx drops accounting and updating
959a393b5dSSainath Grandhi 	 * net_device features
969a393b5dSSainath Grandhi 	 */
979a393b5dSSainath Grandhi 	vlantap->tap.count_tx_dropped = macvtap_count_tx_dropped;
989a393b5dSSainath Grandhi 	vlantap->tap.count_rx_dropped = macvtap_count_rx_dropped;
999a393b5dSSainath Grandhi 	vlantap->tap.update_features  = macvtap_update_features;
1009a393b5dSSainath Grandhi 
1019a393b5dSSainath Grandhi 	err = netdev_rx_handler_register(dev, tap_handle_frame, &vlantap->tap);
1029a393b5dSSainath Grandhi 	if (err)
1039a393b5dSSainath Grandhi 		return err;
1049a393b5dSSainath Grandhi 
1059a393b5dSSainath Grandhi 	/* Don't put anything that may fail after macvlan_common_newlink
1069a393b5dSSainath Grandhi 	 * because we can't undo what it does.
1079a393b5dSSainath Grandhi 	 */
1089a393b5dSSainath Grandhi 	err = macvlan_common_newlink(src_net, dev, tb, data);
1099a393b5dSSainath Grandhi 	if (err) {
1109a393b5dSSainath Grandhi 		netdev_rx_handler_unregister(dev);
1119a393b5dSSainath Grandhi 		return err;
1129a393b5dSSainath Grandhi 	}
1139a393b5dSSainath Grandhi 
1149a393b5dSSainath Grandhi 	vlantap->tap.dev = vlantap->vlan.dev;
1159a393b5dSSainath Grandhi 
1169a393b5dSSainath Grandhi 	return 0;
1179a393b5dSSainath Grandhi }
1189a393b5dSSainath Grandhi 
1199a393b5dSSainath Grandhi static void macvtap_dellink(struct net_device *dev,
1209a393b5dSSainath Grandhi 			    struct list_head *head)
1219a393b5dSSainath Grandhi {
1229a393b5dSSainath Grandhi 	struct macvtap_dev *vlantap = netdev_priv(dev);
1239a393b5dSSainath Grandhi 
1249a393b5dSSainath Grandhi 	netdev_rx_handler_unregister(dev);
1259a393b5dSSainath Grandhi 	tap_del_queues(&vlantap->tap);
1269a393b5dSSainath Grandhi 	macvlan_dellink(dev, head);
1279a393b5dSSainath Grandhi }
1289a393b5dSSainath Grandhi 
1299a393b5dSSainath Grandhi static void macvtap_setup(struct net_device *dev)
1309a393b5dSSainath Grandhi {
1319a393b5dSSainath Grandhi 	macvlan_common_setup(dev);
1329a393b5dSSainath Grandhi 	dev->tx_queue_len = TUN_READQ_SIZE;
1339a393b5dSSainath Grandhi }
1349a393b5dSSainath Grandhi 
1359a393b5dSSainath Grandhi static struct rtnl_link_ops macvtap_link_ops __read_mostly = {
1369a393b5dSSainath Grandhi 	.kind		= "macvtap",
1379a393b5dSSainath Grandhi 	.setup		= macvtap_setup,
1389a393b5dSSainath Grandhi 	.newlink	= macvtap_newlink,
1399a393b5dSSainath Grandhi 	.dellink	= macvtap_dellink,
1409a393b5dSSainath Grandhi 	.priv_size      = sizeof(struct macvtap_dev),
1419a393b5dSSainath Grandhi };
1429a393b5dSSainath Grandhi 
1439a393b5dSSainath Grandhi static int macvtap_device_event(struct notifier_block *unused,
1449a393b5dSSainath Grandhi 				unsigned long event, void *ptr)
1459a393b5dSSainath Grandhi {
1469a393b5dSSainath Grandhi 	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
1479a393b5dSSainath Grandhi 	struct macvtap_dev *vlantap;
1489a393b5dSSainath Grandhi 	struct device *classdev;
1499a393b5dSSainath Grandhi 	dev_t devt;
1509a393b5dSSainath Grandhi 	int err;
1519a393b5dSSainath Grandhi 	char tap_name[IFNAMSIZ];
1529a393b5dSSainath Grandhi 
1539a393b5dSSainath Grandhi 	if (dev->rtnl_link_ops != &macvtap_link_ops)
1549a393b5dSSainath Grandhi 		return NOTIFY_DONE;
1559a393b5dSSainath Grandhi 
1569a393b5dSSainath Grandhi 	snprintf(tap_name, IFNAMSIZ, "tap%d", dev->ifindex);
1579a393b5dSSainath Grandhi 	vlantap = netdev_priv(dev);
1589a393b5dSSainath Grandhi 
1599a393b5dSSainath Grandhi 	switch (event) {
1609a393b5dSSainath Grandhi 	case NETDEV_REGISTER:
1619a393b5dSSainath Grandhi 		/* Create the device node here after the network device has
1629a393b5dSSainath Grandhi 		 * been registered but before register_netdevice has
1639a393b5dSSainath Grandhi 		 * finished running.
1649a393b5dSSainath Grandhi 		 */
1659a393b5dSSainath Grandhi 		err = tap_get_minor(macvtap_major, &vlantap->tap);
1669a393b5dSSainath Grandhi 		if (err)
1679a393b5dSSainath Grandhi 			return notifier_from_errno(err);
1689a393b5dSSainath Grandhi 
1699a393b5dSSainath Grandhi 		devt = MKDEV(MAJOR(macvtap_major), vlantap->tap.minor);
1709a393b5dSSainath Grandhi 		classdev = device_create(&macvtap_class, &dev->dev, devt,
1719a393b5dSSainath Grandhi 					 dev, tap_name);
1729a393b5dSSainath Grandhi 		if (IS_ERR(classdev)) {
1739a393b5dSSainath Grandhi 			tap_free_minor(macvtap_major, &vlantap->tap);
1749a393b5dSSainath Grandhi 			return notifier_from_errno(PTR_ERR(classdev));
1759a393b5dSSainath Grandhi 		}
1769a393b5dSSainath Grandhi 		err = sysfs_create_link(&dev->dev.kobj, &classdev->kobj,
1779a393b5dSSainath Grandhi 					tap_name);
1789a393b5dSSainath Grandhi 		if (err)
1799a393b5dSSainath Grandhi 			return notifier_from_errno(err);
1809a393b5dSSainath Grandhi 		break;
1819a393b5dSSainath Grandhi 	case NETDEV_UNREGISTER:
1829a393b5dSSainath Grandhi 		/* vlan->minor == 0 if NETDEV_REGISTER above failed */
1839a393b5dSSainath Grandhi 		if (vlantap->tap.minor == 0)
1849a393b5dSSainath Grandhi 			break;
1859a393b5dSSainath Grandhi 		sysfs_remove_link(&dev->dev.kobj, tap_name);
1869a393b5dSSainath Grandhi 		devt = MKDEV(MAJOR(macvtap_major), vlantap->tap.minor);
1879a393b5dSSainath Grandhi 		device_destroy(&macvtap_class, devt);
1889a393b5dSSainath Grandhi 		tap_free_minor(macvtap_major, &vlantap->tap);
1899a393b5dSSainath Grandhi 		break;
1909a393b5dSSainath Grandhi 	case NETDEV_CHANGE_TX_QUEUE_LEN:
1919a393b5dSSainath Grandhi 		if (tap_queue_resize(&vlantap->tap))
1929a393b5dSSainath Grandhi 			return NOTIFY_BAD;
1939a393b5dSSainath Grandhi 		break;
1949a393b5dSSainath Grandhi 	}
1959a393b5dSSainath Grandhi 
1969a393b5dSSainath Grandhi 	return NOTIFY_DONE;
1979a393b5dSSainath Grandhi }
1989a393b5dSSainath Grandhi 
1999a393b5dSSainath Grandhi static struct notifier_block macvtap_notifier_block __read_mostly = {
2009a393b5dSSainath Grandhi 	.notifier_call	= macvtap_device_event,
2019a393b5dSSainath Grandhi };
2029a393b5dSSainath Grandhi 
2039a393b5dSSainath Grandhi static int macvtap_init(void)
2049a393b5dSSainath Grandhi {
2059a393b5dSSainath Grandhi 	int err;
2069a393b5dSSainath Grandhi 
2079a393b5dSSainath Grandhi 	err = tap_create_cdev(&macvtap_cdev, &macvtap_major, "macvtap");
2089a393b5dSSainath Grandhi 
2099a393b5dSSainath Grandhi 	if (err)
2109a393b5dSSainath Grandhi 		goto out1;
2119a393b5dSSainath Grandhi 
2129a393b5dSSainath Grandhi 	err = class_register(&macvtap_class);
2139a393b5dSSainath Grandhi 	if (err)
2149a393b5dSSainath Grandhi 		goto out2;
2159a393b5dSSainath Grandhi 
2169a393b5dSSainath Grandhi 	err = register_netdevice_notifier(&macvtap_notifier_block);
2179a393b5dSSainath Grandhi 	if (err)
2189a393b5dSSainath Grandhi 		goto out3;
2199a393b5dSSainath Grandhi 
2209a393b5dSSainath Grandhi 	err = macvlan_link_register(&macvtap_link_ops);
2219a393b5dSSainath Grandhi 	if (err)
2229a393b5dSSainath Grandhi 		goto out4;
2239a393b5dSSainath Grandhi 
2249a393b5dSSainath Grandhi 	return 0;
2259a393b5dSSainath Grandhi 
2269a393b5dSSainath Grandhi out4:
2279a393b5dSSainath Grandhi 	unregister_netdevice_notifier(&macvtap_notifier_block);
2289a393b5dSSainath Grandhi out3:
2299a393b5dSSainath Grandhi 	class_unregister(&macvtap_class);
2309a393b5dSSainath Grandhi out2:
2319a393b5dSSainath Grandhi 	tap_destroy_cdev(macvtap_major, &macvtap_cdev);
2329a393b5dSSainath Grandhi out1:
2339a393b5dSSainath Grandhi 	return err;
2349a393b5dSSainath Grandhi }
2359a393b5dSSainath Grandhi module_init(macvtap_init);
2369a393b5dSSainath Grandhi 
2379a393b5dSSainath Grandhi static void macvtap_exit(void)
2389a393b5dSSainath Grandhi {
2399a393b5dSSainath Grandhi 	rtnl_link_unregister(&macvtap_link_ops);
2409a393b5dSSainath Grandhi 	unregister_netdevice_notifier(&macvtap_notifier_block);
2419a393b5dSSainath Grandhi 	class_unregister(&macvtap_class);
2429a393b5dSSainath Grandhi 	tap_destroy_cdev(macvtap_major, &macvtap_cdev);
2439a393b5dSSainath Grandhi }
2449a393b5dSSainath Grandhi module_exit(macvtap_exit);
2459a393b5dSSainath Grandhi 
2469a393b5dSSainath Grandhi MODULE_ALIAS_RTNL_LINK("macvtap");
2479a393b5dSSainath Grandhi MODULE_AUTHOR("Arnd Bergmann <arnd@arndb.de>");
2489a393b5dSSainath Grandhi MODULE_LICENSE("GPL");
249