109c434b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
29a393b5dSSainath Grandhi #include <linux/etherdevice.h>
39a393b5dSSainath Grandhi #include <linux/if_macvlan.h>
49a393b5dSSainath Grandhi #include <linux/if_tap.h>
59a393b5dSSainath Grandhi #include <linux/if_vlan.h>
69a393b5dSSainath Grandhi #include <linux/interrupt.h>
79a393b5dSSainath Grandhi #include <linux/nsproxy.h>
89a393b5dSSainath Grandhi #include <linux/compat.h>
99a393b5dSSainath Grandhi #include <linux/if_tun.h>
109a393b5dSSainath Grandhi #include <linux/module.h>
119a393b5dSSainath Grandhi #include <linux/skbuff.h>
129a393b5dSSainath Grandhi #include <linux/cache.h>
13174cd4b1SIngo Molnar #include <linux/sched/signal.h>
149a393b5dSSainath Grandhi #include <linux/types.h>
159a393b5dSSainath Grandhi #include <linux/slab.h>
169a393b5dSSainath Grandhi #include <linux/wait.h>
179a393b5dSSainath Grandhi #include <linux/cdev.h>
189a393b5dSSainath Grandhi #include <linux/idr.h>
199a393b5dSSainath Grandhi #include <linux/fs.h>
209a393b5dSSainath Grandhi #include <linux/uio.h>
219a393b5dSSainath Grandhi
229a393b5dSSainath Grandhi #include <net/net_namespace.h>
239a393b5dSSainath Grandhi #include <net/rtnetlink.h>
249a393b5dSSainath Grandhi #include <net/sock.h>
259a393b5dSSainath Grandhi #include <linux/virtio_net.h>
269a393b5dSSainath Grandhi #include <linux/skb_array.h>
279a393b5dSSainath Grandhi
289a393b5dSSainath Grandhi struct macvtap_dev {
299a393b5dSSainath Grandhi struct macvlan_dev vlan;
309a393b5dSSainath Grandhi struct tap_dev tap;
319a393b5dSSainath Grandhi };
329a393b5dSSainath Grandhi
339a393b5dSSainath Grandhi /*
349a393b5dSSainath Grandhi * Variables for dealing with macvtaps device numbers.
359a393b5dSSainath Grandhi */
369a393b5dSSainath Grandhi static dev_t macvtap_major;
379a393b5dSSainath Grandhi
macvtap_net_namespace(const struct device * d)38*fa627348SGreg Kroah-Hartman static const void *macvtap_net_namespace(const struct device *d)
399a393b5dSSainath Grandhi {
40*fa627348SGreg Kroah-Hartman const struct net_device *dev = to_net_dev(d->parent);
419a393b5dSSainath Grandhi return dev_net(dev);
429a393b5dSSainath Grandhi }
439a393b5dSSainath Grandhi
449a393b5dSSainath Grandhi static struct class macvtap_class = {
459a393b5dSSainath Grandhi .name = "macvtap",
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 | \
52fb652fdfSDavid S. Miller NETIF_F_TSO6)
539a393b5dSSainath Grandhi
macvtap_count_tx_dropped(struct tap_dev * tap)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
macvtap_count_rx_dropped(struct tap_dev * tap)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
macvtap_update_features(struct tap_dev * tap,netdev_features_t features)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
macvtap_newlink(struct net * src_net,struct net_device * dev,struct nlattr * tb[],struct nlattr * data[],struct netlink_ext_ack * extack)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 */
10842ab19eeSDavid Ahern err = macvlan_common_newlink(src_net, dev, tb, data, extack);
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
macvtap_dellink(struct net_device * dev,struct list_head * head)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
macvtap_setup(struct net_device * dev)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
macvtap_link_net(const struct net_device * dev)135a0219215SSven Eckelmann static struct net *macvtap_link_net(const struct net_device *dev)
136a0219215SSven Eckelmann {
137a0219215SSven Eckelmann return dev_net(macvlan_dev_real_dev(dev));
138a0219215SSven Eckelmann }
139a0219215SSven Eckelmann
1409a393b5dSSainath Grandhi static struct rtnl_link_ops macvtap_link_ops __read_mostly = {
1419a393b5dSSainath Grandhi .kind = "macvtap",
1429a393b5dSSainath Grandhi .setup = macvtap_setup,
1439a393b5dSSainath Grandhi .newlink = macvtap_newlink,
1449a393b5dSSainath Grandhi .dellink = macvtap_dellink,
145a0219215SSven Eckelmann .get_link_net = macvtap_link_net,
1469a393b5dSSainath Grandhi .priv_size = sizeof(struct macvtap_dev),
1479a393b5dSSainath Grandhi };
1489a393b5dSSainath Grandhi
macvtap_device_event(struct notifier_block * unused,unsigned long event,void * ptr)1499a393b5dSSainath Grandhi static int macvtap_device_event(struct notifier_block *unused,
1509a393b5dSSainath Grandhi unsigned long event, void *ptr)
1519a393b5dSSainath Grandhi {
1529a393b5dSSainath Grandhi struct net_device *dev = netdev_notifier_info_to_dev(ptr);
1539a393b5dSSainath Grandhi struct macvtap_dev *vlantap;
1549a393b5dSSainath Grandhi struct device *classdev;
1559a393b5dSSainath Grandhi dev_t devt;
1569a393b5dSSainath Grandhi int err;
1579a393b5dSSainath Grandhi char tap_name[IFNAMSIZ];
1589a393b5dSSainath Grandhi
1599a393b5dSSainath Grandhi if (dev->rtnl_link_ops != &macvtap_link_ops)
1609a393b5dSSainath Grandhi return NOTIFY_DONE;
1619a393b5dSSainath Grandhi
1629a393b5dSSainath Grandhi snprintf(tap_name, IFNAMSIZ, "tap%d", dev->ifindex);
1639a393b5dSSainath Grandhi vlantap = netdev_priv(dev);
1649a393b5dSSainath Grandhi
1659a393b5dSSainath Grandhi switch (event) {
1669a393b5dSSainath Grandhi case NETDEV_REGISTER:
1679a393b5dSSainath Grandhi /* Create the device node here after the network device has
1689a393b5dSSainath Grandhi * been registered but before register_netdevice has
1699a393b5dSSainath Grandhi * finished running.
1709a393b5dSSainath Grandhi */
1719a393b5dSSainath Grandhi err = tap_get_minor(macvtap_major, &vlantap->tap);
1729a393b5dSSainath Grandhi if (err)
1739a393b5dSSainath Grandhi return notifier_from_errno(err);
1749a393b5dSSainath Grandhi
1759a393b5dSSainath Grandhi devt = MKDEV(MAJOR(macvtap_major), vlantap->tap.minor);
1769a393b5dSSainath Grandhi classdev = device_create(&macvtap_class, &dev->dev, devt,
1771c5b5b3fSJean Sacren dev, "%s", tap_name);
1789a393b5dSSainath Grandhi if (IS_ERR(classdev)) {
1799a393b5dSSainath Grandhi tap_free_minor(macvtap_major, &vlantap->tap);
1809a393b5dSSainath Grandhi return notifier_from_errno(PTR_ERR(classdev));
1819a393b5dSSainath Grandhi }
1829a393b5dSSainath Grandhi err = sysfs_create_link(&dev->dev.kobj, &classdev->kobj,
1839a393b5dSSainath Grandhi tap_name);
1849a393b5dSSainath Grandhi if (err)
1859a393b5dSSainath Grandhi return notifier_from_errno(err);
1869a393b5dSSainath Grandhi break;
1879a393b5dSSainath Grandhi case NETDEV_UNREGISTER:
1889a393b5dSSainath Grandhi /* vlan->minor == 0 if NETDEV_REGISTER above failed */
1899a393b5dSSainath Grandhi if (vlantap->tap.minor == 0)
1909a393b5dSSainath Grandhi break;
1919a393b5dSSainath Grandhi sysfs_remove_link(&dev->dev.kobj, tap_name);
1929a393b5dSSainath Grandhi devt = MKDEV(MAJOR(macvtap_major), vlantap->tap.minor);
1939a393b5dSSainath Grandhi device_destroy(&macvtap_class, devt);
1949a393b5dSSainath Grandhi tap_free_minor(macvtap_major, &vlantap->tap);
1959a393b5dSSainath Grandhi break;
1969a393b5dSSainath Grandhi case NETDEV_CHANGE_TX_QUEUE_LEN:
1979a393b5dSSainath Grandhi if (tap_queue_resize(&vlantap->tap))
1989a393b5dSSainath Grandhi return NOTIFY_BAD;
1999a393b5dSSainath Grandhi break;
2009a393b5dSSainath Grandhi }
2019a393b5dSSainath Grandhi
2029a393b5dSSainath Grandhi return NOTIFY_DONE;
2039a393b5dSSainath Grandhi }
2049a393b5dSSainath Grandhi
2059a393b5dSSainath Grandhi static struct notifier_block macvtap_notifier_block __read_mostly = {
2069a393b5dSSainath Grandhi .notifier_call = macvtap_device_event,
2079a393b5dSSainath Grandhi };
2089a393b5dSSainath Grandhi
macvtap_init(void)209d57aae2eSXiu Jianfeng static int __init macvtap_init(void)
2109a393b5dSSainath Grandhi {
2119a393b5dSSainath Grandhi int err;
2129a393b5dSSainath Grandhi
213dea6e19fSGirish Moodalbail err = tap_create_cdev(&macvtap_cdev, &macvtap_major, "macvtap",
214dea6e19fSGirish Moodalbail THIS_MODULE);
2159a393b5dSSainath Grandhi if (err)
2169a393b5dSSainath Grandhi goto out1;
2179a393b5dSSainath Grandhi
2189a393b5dSSainath Grandhi err = class_register(&macvtap_class);
2199a393b5dSSainath Grandhi if (err)
2209a393b5dSSainath Grandhi goto out2;
2219a393b5dSSainath Grandhi
2229a393b5dSSainath Grandhi err = register_netdevice_notifier(&macvtap_notifier_block);
2239a393b5dSSainath Grandhi if (err)
2249a393b5dSSainath Grandhi goto out3;
2259a393b5dSSainath Grandhi
2269a393b5dSSainath Grandhi err = macvlan_link_register(&macvtap_link_ops);
2279a393b5dSSainath Grandhi if (err)
2289a393b5dSSainath Grandhi goto out4;
2299a393b5dSSainath Grandhi
2309a393b5dSSainath Grandhi return 0;
2319a393b5dSSainath Grandhi
2329a393b5dSSainath Grandhi out4:
2339a393b5dSSainath Grandhi unregister_netdevice_notifier(&macvtap_notifier_block);
2349a393b5dSSainath Grandhi out3:
2359a393b5dSSainath Grandhi class_unregister(&macvtap_class);
2369a393b5dSSainath Grandhi out2:
2379a393b5dSSainath Grandhi tap_destroy_cdev(macvtap_major, &macvtap_cdev);
2389a393b5dSSainath Grandhi out1:
2399a393b5dSSainath Grandhi return err;
2409a393b5dSSainath Grandhi }
2419a393b5dSSainath Grandhi module_init(macvtap_init);
2429a393b5dSSainath Grandhi
macvtap_exit(void)243d57aae2eSXiu Jianfeng static void __exit macvtap_exit(void)
2449a393b5dSSainath Grandhi {
2459a393b5dSSainath Grandhi rtnl_link_unregister(&macvtap_link_ops);
2469a393b5dSSainath Grandhi unregister_netdevice_notifier(&macvtap_notifier_block);
2479a393b5dSSainath Grandhi class_unregister(&macvtap_class);
2489a393b5dSSainath Grandhi tap_destroy_cdev(macvtap_major, &macvtap_cdev);
2499a393b5dSSainath Grandhi }
2509a393b5dSSainath Grandhi module_exit(macvtap_exit);
2519a393b5dSSainath Grandhi
2529a393b5dSSainath Grandhi MODULE_ALIAS_RTNL_LINK("macvtap");
2539a393b5dSSainath Grandhi MODULE_AUTHOR("Arnd Bergmann <arnd@arndb.de>");
2549a393b5dSSainath Grandhi MODULE_LICENSE("GPL");
255