ipvtap.c (6029B)
1// SPDX-License-Identifier: GPL-2.0-only 2#include <linux/etherdevice.h> 3#include "ipvlan.h" 4#include <linux/if_vlan.h> 5#include <linux/if_tap.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.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 27#define TUN_OFFLOADS (NETIF_F_HW_CSUM | NETIF_F_TSO_ECN | NETIF_F_TSO | \ 28 NETIF_F_TSO6) 29 30static dev_t ipvtap_major; 31static struct cdev ipvtap_cdev; 32 33static const void *ipvtap_net_namespace(struct device *d) 34{ 35 struct net_device *dev = to_net_dev(d->parent); 36 return dev_net(dev); 37} 38 39static struct class ipvtap_class = { 40 .name = "ipvtap", 41 .owner = THIS_MODULE, 42 .ns_type = &net_ns_type_operations, 43 .namespace = ipvtap_net_namespace, 44}; 45 46struct ipvtap_dev { 47 struct ipvl_dev vlan; 48 struct tap_dev tap; 49}; 50 51static void ipvtap_count_tx_dropped(struct tap_dev *tap) 52{ 53 struct ipvtap_dev *vlantap = container_of(tap, struct ipvtap_dev, tap); 54 struct ipvl_dev *vlan = &vlantap->vlan; 55 56 this_cpu_inc(vlan->pcpu_stats->tx_drps); 57} 58 59static void ipvtap_count_rx_dropped(struct tap_dev *tap) 60{ 61 struct ipvtap_dev *vlantap = container_of(tap, struct ipvtap_dev, tap); 62 struct ipvl_dev *vlan = &vlantap->vlan; 63 64 ipvlan_count_rx(vlan, 0, 0, 0); 65} 66 67static void ipvtap_update_features(struct tap_dev *tap, 68 netdev_features_t features) 69{ 70 struct ipvtap_dev *vlantap = container_of(tap, struct ipvtap_dev, tap); 71 struct ipvl_dev *vlan = &vlantap->vlan; 72 73 vlan->sfeatures = features; 74 netdev_update_features(vlan->dev); 75} 76 77static int ipvtap_newlink(struct net *src_net, struct net_device *dev, 78 struct nlattr *tb[], struct nlattr *data[], 79 struct netlink_ext_ack *extack) 80{ 81 struct ipvtap_dev *vlantap = netdev_priv(dev); 82 int err; 83 84 INIT_LIST_HEAD(&vlantap->tap.queue_list); 85 86 /* Since macvlan supports all offloads by default, make 87 * tap support all offloads also. 88 */ 89 vlantap->tap.tap_features = TUN_OFFLOADS; 90 vlantap->tap.count_tx_dropped = ipvtap_count_tx_dropped; 91 vlantap->tap.update_features = ipvtap_update_features; 92 vlantap->tap.count_rx_dropped = ipvtap_count_rx_dropped; 93 94 err = netdev_rx_handler_register(dev, tap_handle_frame, &vlantap->tap); 95 if (err) 96 return err; 97 98 /* Don't put anything that may fail after macvlan_common_newlink 99 * because we can't undo what it does. 100 */ 101 err = ipvlan_link_new(src_net, dev, tb, data, extack); 102 if (err) { 103 netdev_rx_handler_unregister(dev); 104 return err; 105 } 106 107 vlantap->tap.dev = vlantap->vlan.dev; 108 109 return err; 110} 111 112static void ipvtap_dellink(struct net_device *dev, 113 struct list_head *head) 114{ 115 struct ipvtap_dev *vlan = netdev_priv(dev); 116 117 netdev_rx_handler_unregister(dev); 118 tap_del_queues(&vlan->tap); 119 ipvlan_link_delete(dev, head); 120} 121 122static void ipvtap_setup(struct net_device *dev) 123{ 124 ipvlan_link_setup(dev); 125 dev->tx_queue_len = TUN_READQ_SIZE; 126 dev->priv_flags &= ~IFF_NO_QUEUE; 127} 128 129static struct rtnl_link_ops ipvtap_link_ops __read_mostly = { 130 .kind = "ipvtap", 131 .setup = ipvtap_setup, 132 .newlink = ipvtap_newlink, 133 .dellink = ipvtap_dellink, 134 .priv_size = sizeof(struct ipvtap_dev), 135}; 136 137static int ipvtap_device_event(struct notifier_block *unused, 138 unsigned long event, void *ptr) 139{ 140 struct net_device *dev = netdev_notifier_info_to_dev(ptr); 141 struct ipvtap_dev *vlantap; 142 struct device *classdev; 143 dev_t devt; 144 int err; 145 char tap_name[IFNAMSIZ]; 146 147 if (dev->rtnl_link_ops != &ipvtap_link_ops) 148 return NOTIFY_DONE; 149 150 snprintf(tap_name, IFNAMSIZ, "tap%d", dev->ifindex); 151 vlantap = netdev_priv(dev); 152 153 switch (event) { 154 case NETDEV_REGISTER: 155 /* Create the device node here after the network device has 156 * been registered but before register_netdevice has 157 * finished running. 158 */ 159 err = tap_get_minor(ipvtap_major, &vlantap->tap); 160 if (err) 161 return notifier_from_errno(err); 162 163 devt = MKDEV(MAJOR(ipvtap_major), vlantap->tap.minor); 164 classdev = device_create(&ipvtap_class, &dev->dev, devt, 165 dev, "%s", tap_name); 166 if (IS_ERR(classdev)) { 167 tap_free_minor(ipvtap_major, &vlantap->tap); 168 return notifier_from_errno(PTR_ERR(classdev)); 169 } 170 err = sysfs_create_link(&dev->dev.kobj, &classdev->kobj, 171 tap_name); 172 if (err) 173 return notifier_from_errno(err); 174 break; 175 case NETDEV_UNREGISTER: 176 /* vlan->minor == 0 if NETDEV_REGISTER above failed */ 177 if (vlantap->tap.minor == 0) 178 break; 179 sysfs_remove_link(&dev->dev.kobj, tap_name); 180 devt = MKDEV(MAJOR(ipvtap_major), vlantap->tap.minor); 181 device_destroy(&ipvtap_class, devt); 182 tap_free_minor(ipvtap_major, &vlantap->tap); 183 break; 184 case NETDEV_CHANGE_TX_QUEUE_LEN: 185 if (tap_queue_resize(&vlantap->tap)) 186 return NOTIFY_BAD; 187 break; 188 } 189 190 return NOTIFY_DONE; 191} 192 193static struct notifier_block ipvtap_notifier_block __read_mostly = { 194 .notifier_call = ipvtap_device_event, 195}; 196 197static int ipvtap_init(void) 198{ 199 int err; 200 201 err = tap_create_cdev(&ipvtap_cdev, &ipvtap_major, "ipvtap", 202 THIS_MODULE); 203 if (err) 204 goto out1; 205 206 err = class_register(&ipvtap_class); 207 if (err) 208 goto out2; 209 210 err = register_netdevice_notifier(&ipvtap_notifier_block); 211 if (err) 212 goto out3; 213 214 err = ipvlan_link_register(&ipvtap_link_ops); 215 if (err) 216 goto out4; 217 218 return 0; 219 220out4: 221 unregister_netdevice_notifier(&ipvtap_notifier_block); 222out3: 223 class_unregister(&ipvtap_class); 224out2: 225 tap_destroy_cdev(ipvtap_major, &ipvtap_cdev); 226out1: 227 return err; 228} 229module_init(ipvtap_init); 230 231static void ipvtap_exit(void) 232{ 233 rtnl_link_unregister(&ipvtap_link_ops); 234 unregister_netdevice_notifier(&ipvtap_notifier_block); 235 class_unregister(&ipvtap_class); 236 tap_destroy_cdev(ipvtap_major, &ipvtap_cdev); 237} 238module_exit(ipvtap_exit); 239MODULE_ALIAS_RTNL_LINK("ipvtap"); 240MODULE_AUTHOR("Sainath Grandhi <sainath.grandhi@intel.com>"); 241MODULE_LICENSE("GPL");