linux/drivers/net/macvtap.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2#include <linux/etherdevice.h>
   3#include <linux/if_macvlan.h>
   4#include <linux/if_tap.h>
   5#include <linux/if_vlan.h>
   6#include <linux/interrupt.h>
   7#include <linux/nsproxy.h>
   8#include <linux/compat.h>
   9#include <linux/if_tun.h>
  10#include <linux/module.h>
  11#include <linux/skbuff.h>
  12#include <linux/cache.h>
  13#include <linux/sched/signal.h>
  14#include <linux/types.h>
  15#include <linux/slab.h>
  16#include <linux/wait.h>
  17#include <linux/cdev.h>
  18#include <linux/idr.h>
  19#include <linux/fs.h>
  20#include <linux/uio.h>
  21
  22#include <net/net_namespace.h>
  23#include <net/rtnetlink.h>
  24#include <net/sock.h>
  25#include <linux/virtio_net.h>
  26#include <linux/skb_array.h>
  27
  28struct macvtap_dev {
  29        struct macvlan_dev vlan;
  30        struct tap_dev    tap;
  31};
  32
  33/*
  34 * Variables for dealing with macvtaps device numbers.
  35 */
  36static dev_t macvtap_major;
  37
  38static const void *macvtap_net_namespace(struct device *d)
  39{
  40        struct net_device *dev = to_net_dev(d->parent);
  41        return dev_net(dev);
  42}
  43
  44static struct class macvtap_class = {
  45        .name = "macvtap",
  46        .owner = THIS_MODULE,
  47        .ns_type = &net_ns_type_operations,
  48        .namespace = macvtap_net_namespace,
  49};
  50static struct cdev macvtap_cdev;
  51
  52#define TUN_OFFLOADS (NETIF_F_HW_CSUM | NETIF_F_TSO_ECN | NETIF_F_TSO | \
  53                      NETIF_F_TSO6)
  54
  55static void macvtap_count_tx_dropped(struct tap_dev *tap)
  56{
  57        struct macvtap_dev *vlantap = container_of(tap, struct macvtap_dev, tap);
  58        struct macvlan_dev *vlan = &vlantap->vlan;
  59
  60        this_cpu_inc(vlan->pcpu_stats->tx_dropped);
  61}
  62
  63static void macvtap_count_rx_dropped(struct tap_dev *tap)
  64{
  65        struct macvtap_dev *vlantap = container_of(tap, struct macvtap_dev, tap);
  66        struct macvlan_dev *vlan = &vlantap->vlan;
  67
  68        macvlan_count_rx(vlan, 0, 0, 0);
  69}
  70
  71static void macvtap_update_features(struct tap_dev *tap,
  72                                    netdev_features_t features)
  73{
  74        struct macvtap_dev *vlantap = container_of(tap, struct macvtap_dev, tap);
  75        struct macvlan_dev *vlan = &vlantap->vlan;
  76
  77        vlan->set_features = features;
  78        netdev_update_features(vlan->dev);
  79}
  80
  81static int macvtap_newlink(struct net *src_net, struct net_device *dev,
  82                           struct nlattr *tb[], struct nlattr *data[],
  83                           struct netlink_ext_ack *extack)
  84{
  85        struct macvtap_dev *vlantap = netdev_priv(dev);
  86        int err;
  87
  88        INIT_LIST_HEAD(&vlantap->tap.queue_list);
  89
  90        /* Since macvlan supports all offloads by default, make
  91         * tap support all offloads also.
  92         */
  93        vlantap->tap.tap_features = TUN_OFFLOADS;
  94
  95        /* Register callbacks for rx/tx drops accounting and updating
  96         * net_device features
  97         */
  98        vlantap->tap.count_tx_dropped = macvtap_count_tx_dropped;
  99        vlantap->tap.count_rx_dropped = macvtap_count_rx_dropped;
 100        vlantap->tap.update_features  = macvtap_update_features;
 101
 102        err = netdev_rx_handler_register(dev, tap_handle_frame, &vlantap->tap);
 103        if (err)
 104                return err;
 105
 106        /* Don't put anything that may fail after macvlan_common_newlink
 107         * because we can't undo what it does.
 108         */
 109        err = macvlan_common_newlink(src_net, dev, tb, data, extack);
 110        if (err) {
 111                netdev_rx_handler_unregister(dev);
 112                return err;
 113        }
 114
 115        vlantap->tap.dev = vlantap->vlan.dev;
 116
 117        return 0;
 118}
 119
 120static void macvtap_dellink(struct net_device *dev,
 121                            struct list_head *head)
 122{
 123        struct macvtap_dev *vlantap = netdev_priv(dev);
 124
 125        netdev_rx_handler_unregister(dev);
 126        tap_del_queues(&vlantap->tap);
 127        macvlan_dellink(dev, head);
 128}
 129
 130static void macvtap_setup(struct net_device *dev)
 131{
 132        macvlan_common_setup(dev);
 133        dev->tx_queue_len = TUN_READQ_SIZE;
 134}
 135
 136static struct net *macvtap_link_net(const struct net_device *dev)
 137{
 138        return dev_net(macvlan_dev_real_dev(dev));
 139}
 140
 141static struct rtnl_link_ops macvtap_link_ops __read_mostly = {
 142        .kind           = "macvtap",
 143        .setup          = macvtap_setup,
 144        .newlink        = macvtap_newlink,
 145        .dellink        = macvtap_dellink,
 146        .get_link_net   = macvtap_link_net,
 147        .priv_size      = sizeof(struct macvtap_dev),
 148};
 149
 150static int macvtap_device_event(struct notifier_block *unused,
 151                                unsigned long event, void *ptr)
 152{
 153        struct net_device *dev = netdev_notifier_info_to_dev(ptr);
 154        struct macvtap_dev *vlantap;
 155        struct device *classdev;
 156        dev_t devt;
 157        int err;
 158        char tap_name[IFNAMSIZ];
 159
 160        if (dev->rtnl_link_ops != &macvtap_link_ops)
 161                return NOTIFY_DONE;
 162
 163        snprintf(tap_name, IFNAMSIZ, "tap%d", dev->ifindex);
 164        vlantap = netdev_priv(dev);
 165
 166        switch (event) {
 167        case NETDEV_REGISTER:
 168                /* Create the device node here after the network device has
 169                 * been registered but before register_netdevice has
 170                 * finished running.
 171                 */
 172                err = tap_get_minor(macvtap_major, &vlantap->tap);
 173                if (err)
 174                        return notifier_from_errno(err);
 175
 176                devt = MKDEV(MAJOR(macvtap_major), vlantap->tap.minor);
 177                classdev = device_create(&macvtap_class, &dev->dev, devt,
 178                                         dev, "%s", tap_name);
 179                if (IS_ERR(classdev)) {
 180                        tap_free_minor(macvtap_major, &vlantap->tap);
 181                        return notifier_from_errno(PTR_ERR(classdev));
 182                }
 183                err = sysfs_create_link(&dev->dev.kobj, &classdev->kobj,
 184                                        tap_name);
 185                if (err)
 186                        return notifier_from_errno(err);
 187                break;
 188        case NETDEV_UNREGISTER:
 189                /* vlan->minor == 0 if NETDEV_REGISTER above failed */
 190                if (vlantap->tap.minor == 0)
 191                        break;
 192                sysfs_remove_link(&dev->dev.kobj, tap_name);
 193                devt = MKDEV(MAJOR(macvtap_major), vlantap->tap.minor);
 194                device_destroy(&macvtap_class, devt);
 195                tap_free_minor(macvtap_major, &vlantap->tap);
 196                break;
 197        case NETDEV_CHANGE_TX_QUEUE_LEN:
 198                if (tap_queue_resize(&vlantap->tap))
 199                        return NOTIFY_BAD;
 200                break;
 201        }
 202
 203        return NOTIFY_DONE;
 204}
 205
 206static struct notifier_block macvtap_notifier_block __read_mostly = {
 207        .notifier_call  = macvtap_device_event,
 208};
 209
 210static int macvtap_init(void)
 211{
 212        int err;
 213
 214        err = tap_create_cdev(&macvtap_cdev, &macvtap_major, "macvtap",
 215                              THIS_MODULE);
 216        if (err)
 217                goto out1;
 218
 219        err = class_register(&macvtap_class);
 220        if (err)
 221                goto out2;
 222
 223        err = register_netdevice_notifier(&macvtap_notifier_block);
 224        if (err)
 225                goto out3;
 226
 227        err = macvlan_link_register(&macvtap_link_ops);
 228        if (err)
 229                goto out4;
 230
 231        return 0;
 232
 233out4:
 234        unregister_netdevice_notifier(&macvtap_notifier_block);
 235out3:
 236        class_unregister(&macvtap_class);
 237out2:
 238        tap_destroy_cdev(macvtap_major, &macvtap_cdev);
 239out1:
 240        return err;
 241}
 242module_init(macvtap_init);
 243
 244static void macvtap_exit(void)
 245{
 246        rtnl_link_unregister(&macvtap_link_ops);
 247        unregister_netdevice_notifier(&macvtap_notifier_block);
 248        class_unregister(&macvtap_class);
 249        tap_destroy_cdev(macvtap_major, &macvtap_cdev);
 250}
 251module_exit(macvtap_exit);
 252
 253MODULE_ALIAS_RTNL_LINK("macvtap");
 254MODULE_AUTHOR("Arnd Bergmann <arnd@arndb.de>");
 255MODULE_LICENSE("GPL");
 256