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 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 .owner = THIS_MODULE, 479a393b5dSSainath Grandhi .ns_type = &net_ns_type_operations, 489a393b5dSSainath Grandhi .namespace = macvtap_net_namespace, 499a393b5dSSainath Grandhi }; 509a393b5dSSainath Grandhi static struct cdev macvtap_cdev; 519a393b5dSSainath Grandhi 529a393b5dSSainath Grandhi #define TUN_OFFLOADS (NETIF_F_HW_CSUM | NETIF_F_TSO_ECN | NETIF_F_TSO | \ 53fb652fdfSDavid S. Miller NETIF_F_TSO6) 549a393b5dSSainath Grandhi 559a393b5dSSainath Grandhi static void macvtap_count_tx_dropped(struct tap_dev *tap) 569a393b5dSSainath Grandhi { 579a393b5dSSainath Grandhi struct macvtap_dev *vlantap = container_of(tap, struct macvtap_dev, tap); 589a393b5dSSainath Grandhi struct macvlan_dev *vlan = &vlantap->vlan; 599a393b5dSSainath Grandhi 609a393b5dSSainath Grandhi this_cpu_inc(vlan->pcpu_stats->tx_dropped); 619a393b5dSSainath Grandhi } 629a393b5dSSainath Grandhi 639a393b5dSSainath Grandhi static void macvtap_count_rx_dropped(struct tap_dev *tap) 649a393b5dSSainath Grandhi { 659a393b5dSSainath Grandhi struct macvtap_dev *vlantap = container_of(tap, struct macvtap_dev, tap); 669a393b5dSSainath Grandhi struct macvlan_dev *vlan = &vlantap->vlan; 679a393b5dSSainath Grandhi 689a393b5dSSainath Grandhi macvlan_count_rx(vlan, 0, 0, 0); 699a393b5dSSainath Grandhi } 709a393b5dSSainath Grandhi 719a393b5dSSainath Grandhi static void macvtap_update_features(struct tap_dev *tap, 729a393b5dSSainath Grandhi netdev_features_t features) 739a393b5dSSainath Grandhi { 749a393b5dSSainath Grandhi struct macvtap_dev *vlantap = container_of(tap, struct macvtap_dev, tap); 759a393b5dSSainath Grandhi struct macvlan_dev *vlan = &vlantap->vlan; 769a393b5dSSainath Grandhi 779a393b5dSSainath Grandhi vlan->set_features = features; 789a393b5dSSainath Grandhi netdev_update_features(vlan->dev); 799a393b5dSSainath Grandhi } 809a393b5dSSainath Grandhi 817a3f4a18SMatthias Schiffer static int macvtap_newlink(struct net *src_net, struct net_device *dev, 827a3f4a18SMatthias Schiffer struct nlattr *tb[], struct nlattr *data[], 837a3f4a18SMatthias Schiffer struct netlink_ext_ack *extack) 849a393b5dSSainath Grandhi { 859a393b5dSSainath Grandhi struct macvtap_dev *vlantap = netdev_priv(dev); 869a393b5dSSainath Grandhi int err; 879a393b5dSSainath Grandhi 889a393b5dSSainath Grandhi INIT_LIST_HEAD(&vlantap->tap.queue_list); 899a393b5dSSainath Grandhi 909a393b5dSSainath Grandhi /* Since macvlan supports all offloads by default, make 919a393b5dSSainath Grandhi * tap support all offloads also. 929a393b5dSSainath Grandhi */ 939a393b5dSSainath Grandhi vlantap->tap.tap_features = TUN_OFFLOADS; 949a393b5dSSainath Grandhi 959a393b5dSSainath Grandhi /* Register callbacks for rx/tx drops accounting and updating 969a393b5dSSainath Grandhi * net_device features 979a393b5dSSainath Grandhi */ 989a393b5dSSainath Grandhi vlantap->tap.count_tx_dropped = macvtap_count_tx_dropped; 999a393b5dSSainath Grandhi vlantap->tap.count_rx_dropped = macvtap_count_rx_dropped; 1009a393b5dSSainath Grandhi vlantap->tap.update_features = macvtap_update_features; 1019a393b5dSSainath Grandhi 1029a393b5dSSainath Grandhi err = netdev_rx_handler_register(dev, tap_handle_frame, &vlantap->tap); 1039a393b5dSSainath Grandhi if (err) 1049a393b5dSSainath Grandhi return err; 1059a393b5dSSainath Grandhi 1069a393b5dSSainath Grandhi /* Don't put anything that may fail after macvlan_common_newlink 1079a393b5dSSainath Grandhi * because we can't undo what it does. 1089a393b5dSSainath Grandhi */ 10942ab19eeSDavid Ahern err = macvlan_common_newlink(src_net, dev, tb, data, extack); 1109a393b5dSSainath Grandhi if (err) { 1119a393b5dSSainath Grandhi netdev_rx_handler_unregister(dev); 1129a393b5dSSainath Grandhi return err; 1139a393b5dSSainath Grandhi } 1149a393b5dSSainath Grandhi 1159a393b5dSSainath Grandhi vlantap->tap.dev = vlantap->vlan.dev; 1169a393b5dSSainath Grandhi 1179a393b5dSSainath Grandhi return 0; 1189a393b5dSSainath Grandhi } 1199a393b5dSSainath Grandhi 1209a393b5dSSainath Grandhi static void macvtap_dellink(struct net_device *dev, 1219a393b5dSSainath Grandhi struct list_head *head) 1229a393b5dSSainath Grandhi { 1239a393b5dSSainath Grandhi struct macvtap_dev *vlantap = netdev_priv(dev); 1249a393b5dSSainath Grandhi 1259a393b5dSSainath Grandhi netdev_rx_handler_unregister(dev); 1269a393b5dSSainath Grandhi tap_del_queues(&vlantap->tap); 1279a393b5dSSainath Grandhi macvlan_dellink(dev, head); 1289a393b5dSSainath Grandhi } 1299a393b5dSSainath Grandhi 1309a393b5dSSainath Grandhi static void macvtap_setup(struct net_device *dev) 1319a393b5dSSainath Grandhi { 1329a393b5dSSainath Grandhi macvlan_common_setup(dev); 1339a393b5dSSainath Grandhi dev->tx_queue_len = TUN_READQ_SIZE; 1349a393b5dSSainath Grandhi } 1359a393b5dSSainath Grandhi 136a0219215SSven Eckelmann static struct net *macvtap_link_net(const struct net_device *dev) 137a0219215SSven Eckelmann { 138a0219215SSven Eckelmann return dev_net(macvlan_dev_real_dev(dev)); 139a0219215SSven Eckelmann } 140a0219215SSven Eckelmann 1419a393b5dSSainath Grandhi static struct rtnl_link_ops macvtap_link_ops __read_mostly = { 1429a393b5dSSainath Grandhi .kind = "macvtap", 1439a393b5dSSainath Grandhi .setup = macvtap_setup, 1449a393b5dSSainath Grandhi .newlink = macvtap_newlink, 1459a393b5dSSainath Grandhi .dellink = macvtap_dellink, 146a0219215SSven Eckelmann .get_link_net = macvtap_link_net, 1479a393b5dSSainath Grandhi .priv_size = sizeof(struct macvtap_dev), 1489a393b5dSSainath Grandhi }; 1499a393b5dSSainath Grandhi 1509a393b5dSSainath Grandhi static int macvtap_device_event(struct notifier_block *unused, 1519a393b5dSSainath Grandhi unsigned long event, void *ptr) 1529a393b5dSSainath Grandhi { 1539a393b5dSSainath Grandhi struct net_device *dev = netdev_notifier_info_to_dev(ptr); 1549a393b5dSSainath Grandhi struct macvtap_dev *vlantap; 1559a393b5dSSainath Grandhi struct device *classdev; 1569a393b5dSSainath Grandhi dev_t devt; 1579a393b5dSSainath Grandhi int err; 1589a393b5dSSainath Grandhi char tap_name[IFNAMSIZ]; 1599a393b5dSSainath Grandhi 1609a393b5dSSainath Grandhi if (dev->rtnl_link_ops != &macvtap_link_ops) 1619a393b5dSSainath Grandhi return NOTIFY_DONE; 1629a393b5dSSainath Grandhi 1639a393b5dSSainath Grandhi snprintf(tap_name, IFNAMSIZ, "tap%d", dev->ifindex); 1649a393b5dSSainath Grandhi vlantap = netdev_priv(dev); 1659a393b5dSSainath Grandhi 1669a393b5dSSainath Grandhi switch (event) { 1679a393b5dSSainath Grandhi case NETDEV_REGISTER: 1689a393b5dSSainath Grandhi /* Create the device node here after the network device has 1699a393b5dSSainath Grandhi * been registered but before register_netdevice has 1709a393b5dSSainath Grandhi * finished running. 1719a393b5dSSainath Grandhi */ 1729a393b5dSSainath Grandhi err = tap_get_minor(macvtap_major, &vlantap->tap); 1739a393b5dSSainath Grandhi if (err) 1749a393b5dSSainath Grandhi return notifier_from_errno(err); 1759a393b5dSSainath Grandhi 1769a393b5dSSainath Grandhi devt = MKDEV(MAJOR(macvtap_major), vlantap->tap.minor); 1779a393b5dSSainath Grandhi classdev = device_create(&macvtap_class, &dev->dev, devt, 1781c5b5b3fSJean Sacren dev, "%s", tap_name); 1799a393b5dSSainath Grandhi if (IS_ERR(classdev)) { 1809a393b5dSSainath Grandhi tap_free_minor(macvtap_major, &vlantap->tap); 1819a393b5dSSainath Grandhi return notifier_from_errno(PTR_ERR(classdev)); 1829a393b5dSSainath Grandhi } 1839a393b5dSSainath Grandhi err = sysfs_create_link(&dev->dev.kobj, &classdev->kobj, 1849a393b5dSSainath Grandhi tap_name); 1859a393b5dSSainath Grandhi if (err) 1869a393b5dSSainath Grandhi return notifier_from_errno(err); 1879a393b5dSSainath Grandhi break; 1889a393b5dSSainath Grandhi case NETDEV_UNREGISTER: 1899a393b5dSSainath Grandhi /* vlan->minor == 0 if NETDEV_REGISTER above failed */ 1909a393b5dSSainath Grandhi if (vlantap->tap.minor == 0) 1919a393b5dSSainath Grandhi break; 1929a393b5dSSainath Grandhi sysfs_remove_link(&dev->dev.kobj, tap_name); 1939a393b5dSSainath Grandhi devt = MKDEV(MAJOR(macvtap_major), vlantap->tap.minor); 1949a393b5dSSainath Grandhi device_destroy(&macvtap_class, devt); 1959a393b5dSSainath Grandhi tap_free_minor(macvtap_major, &vlantap->tap); 1969a393b5dSSainath Grandhi break; 1979a393b5dSSainath Grandhi case NETDEV_CHANGE_TX_QUEUE_LEN: 1989a393b5dSSainath Grandhi if (tap_queue_resize(&vlantap->tap)) 1999a393b5dSSainath Grandhi return NOTIFY_BAD; 2009a393b5dSSainath Grandhi break; 2019a393b5dSSainath Grandhi } 2029a393b5dSSainath Grandhi 2039a393b5dSSainath Grandhi return NOTIFY_DONE; 2049a393b5dSSainath Grandhi } 2059a393b5dSSainath Grandhi 2069a393b5dSSainath Grandhi static struct notifier_block macvtap_notifier_block __read_mostly = { 2079a393b5dSSainath Grandhi .notifier_call = macvtap_device_event, 2089a393b5dSSainath Grandhi }; 2099a393b5dSSainath Grandhi 210d57aae2eSXiu Jianfeng static int __init macvtap_init(void) 2119a393b5dSSainath Grandhi { 2129a393b5dSSainath Grandhi int err; 2139a393b5dSSainath Grandhi 214dea6e19fSGirish Moodalbail err = tap_create_cdev(&macvtap_cdev, &macvtap_major, "macvtap", 215dea6e19fSGirish Moodalbail THIS_MODULE); 2169a393b5dSSainath Grandhi if (err) 2179a393b5dSSainath Grandhi goto out1; 2189a393b5dSSainath Grandhi 2199a393b5dSSainath Grandhi err = class_register(&macvtap_class); 2209a393b5dSSainath Grandhi if (err) 2219a393b5dSSainath Grandhi goto out2; 2229a393b5dSSainath Grandhi 2239a393b5dSSainath Grandhi err = register_netdevice_notifier(&macvtap_notifier_block); 2249a393b5dSSainath Grandhi if (err) 2259a393b5dSSainath Grandhi goto out3; 2269a393b5dSSainath Grandhi 2279a393b5dSSainath Grandhi err = macvlan_link_register(&macvtap_link_ops); 2289a393b5dSSainath Grandhi if (err) 2299a393b5dSSainath Grandhi goto out4; 2309a393b5dSSainath Grandhi 2319a393b5dSSainath Grandhi return 0; 2329a393b5dSSainath Grandhi 2339a393b5dSSainath Grandhi out4: 2349a393b5dSSainath Grandhi unregister_netdevice_notifier(&macvtap_notifier_block); 2359a393b5dSSainath Grandhi out3: 2369a393b5dSSainath Grandhi class_unregister(&macvtap_class); 2379a393b5dSSainath Grandhi out2: 2389a393b5dSSainath Grandhi tap_destroy_cdev(macvtap_major, &macvtap_cdev); 2399a393b5dSSainath Grandhi out1: 2409a393b5dSSainath Grandhi return err; 2419a393b5dSSainath Grandhi } 2429a393b5dSSainath Grandhi module_init(macvtap_init); 2439a393b5dSSainath Grandhi 244d57aae2eSXiu Jianfeng static void __exit macvtap_exit(void) 2459a393b5dSSainath Grandhi { 2469a393b5dSSainath Grandhi rtnl_link_unregister(&macvtap_link_ops); 2479a393b5dSSainath Grandhi unregister_netdevice_notifier(&macvtap_notifier_block); 2489a393b5dSSainath Grandhi class_unregister(&macvtap_class); 2499a393b5dSSainath Grandhi tap_destroy_cdev(macvtap_major, &macvtap_cdev); 2509a393b5dSSainath Grandhi } 2519a393b5dSSainath Grandhi module_exit(macvtap_exit); 2529a393b5dSSainath Grandhi 2539a393b5dSSainath Grandhi MODULE_ALIAS_RTNL_LINK("macvtap"); 2549a393b5dSSainath Grandhi MODULE_AUTHOR("Arnd Bergmann <arnd@arndb.de>"); 2559a393b5dSSainath Grandhi MODULE_LICENSE("GPL"); 256