root/drivers/net/macvtap.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. macvtap_net_namespace
  2. macvtap_count_tx_dropped
  3. macvtap_count_rx_dropped
  4. macvtap_update_features
  5. macvtap_newlink
  6. macvtap_dellink
  7. macvtap_setup
  8. macvtap_device_event
  9. macvtap_init
  10. macvtap_exit

   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 
  28 struct macvtap_dev {
  29         struct macvlan_dev vlan;
  30         struct tap_dev    tap;
  31 };
  32 
  33 /*
  34  * Variables for dealing with macvtaps device numbers.
  35  */
  36 static dev_t macvtap_major;
  37 
  38 static 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 
  44 static struct class macvtap_class = {
  45         .name = "macvtap",
  46         .owner = THIS_MODULE,
  47         .ns_type = &net_ns_type_operations,
  48         .namespace = macvtap_net_namespace,
  49 };
  50 static 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 
  55 static 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 
  63 static 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 
  71 static 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 
  81 static 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 
 120 static 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 
 130 static void macvtap_setup(struct net_device *dev)
 131 {
 132         macvlan_common_setup(dev);
 133         dev->tx_queue_len = TUN_READQ_SIZE;
 134 }
 135 
 136 static struct rtnl_link_ops macvtap_link_ops __read_mostly = {
 137         .kind           = "macvtap",
 138         .setup          = macvtap_setup,
 139         .newlink        = macvtap_newlink,
 140         .dellink        = macvtap_dellink,
 141         .priv_size      = sizeof(struct macvtap_dev),
 142 };
 143 
 144 static int macvtap_device_event(struct notifier_block *unused,
 145                                 unsigned long event, void *ptr)
 146 {
 147         struct net_device *dev = netdev_notifier_info_to_dev(ptr);
 148         struct macvtap_dev *vlantap;
 149         struct device *classdev;
 150         dev_t devt;
 151         int err;
 152         char tap_name[IFNAMSIZ];
 153 
 154         if (dev->rtnl_link_ops != &macvtap_link_ops)
 155                 return NOTIFY_DONE;
 156 
 157         snprintf(tap_name, IFNAMSIZ, "tap%d", dev->ifindex);
 158         vlantap = netdev_priv(dev);
 159 
 160         switch (event) {
 161         case NETDEV_REGISTER:
 162                 /* Create the device node here after the network device has
 163                  * been registered but before register_netdevice has
 164                  * finished running.
 165                  */
 166                 err = tap_get_minor(macvtap_major, &vlantap->tap);
 167                 if (err)
 168                         return notifier_from_errno(err);
 169 
 170                 devt = MKDEV(MAJOR(macvtap_major), vlantap->tap.minor);
 171                 classdev = device_create(&macvtap_class, &dev->dev, devt,
 172                                          dev, tap_name);
 173                 if (IS_ERR(classdev)) {
 174                         tap_free_minor(macvtap_major, &vlantap->tap);
 175                         return notifier_from_errno(PTR_ERR(classdev));
 176                 }
 177                 err = sysfs_create_link(&dev->dev.kobj, &classdev->kobj,
 178                                         tap_name);
 179                 if (err)
 180                         return notifier_from_errno(err);
 181                 break;
 182         case NETDEV_UNREGISTER:
 183                 /* vlan->minor == 0 if NETDEV_REGISTER above failed */
 184                 if (vlantap->tap.minor == 0)
 185                         break;
 186                 sysfs_remove_link(&dev->dev.kobj, tap_name);
 187                 devt = MKDEV(MAJOR(macvtap_major), vlantap->tap.minor);
 188                 device_destroy(&macvtap_class, devt);
 189                 tap_free_minor(macvtap_major, &vlantap->tap);
 190                 break;
 191         case NETDEV_CHANGE_TX_QUEUE_LEN:
 192                 if (tap_queue_resize(&vlantap->tap))
 193                         return NOTIFY_BAD;
 194                 break;
 195         }
 196 
 197         return NOTIFY_DONE;
 198 }
 199 
 200 static struct notifier_block macvtap_notifier_block __read_mostly = {
 201         .notifier_call  = macvtap_device_event,
 202 };
 203 
 204 static int macvtap_init(void)
 205 {
 206         int err;
 207 
 208         err = tap_create_cdev(&macvtap_cdev, &macvtap_major, "macvtap",
 209                               THIS_MODULE);
 210         if (err)
 211                 goto out1;
 212 
 213         err = class_register(&macvtap_class);
 214         if (err)
 215                 goto out2;
 216 
 217         err = register_netdevice_notifier(&macvtap_notifier_block);
 218         if (err)
 219                 goto out3;
 220 
 221         err = macvlan_link_register(&macvtap_link_ops);
 222         if (err)
 223                 goto out4;
 224 
 225         return 0;
 226 
 227 out4:
 228         unregister_netdevice_notifier(&macvtap_notifier_block);
 229 out3:
 230         class_unregister(&macvtap_class);
 231 out2:
 232         tap_destroy_cdev(macvtap_major, &macvtap_cdev);
 233 out1:
 234         return err;
 235 }
 236 module_init(macvtap_init);
 237 
 238 static void macvtap_exit(void)
 239 {
 240         rtnl_link_unregister(&macvtap_link_ops);
 241         unregister_netdevice_notifier(&macvtap_notifier_block);
 242         class_unregister(&macvtap_class);
 243         tap_destroy_cdev(macvtap_major, &macvtap_cdev);
 244 }
 245 module_exit(macvtap_exit);
 246 
 247 MODULE_ALIAS_RTNL_LINK("macvtap");
 248 MODULE_AUTHOR("Arnd Bergmann <arnd@arndb.de>");
 249 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */