linux/drivers/net/dummy.c
<<
>>
Prefs
   1/* dummy.c: a dummy net driver
   2
   3        The purpose of this driver is to provide a device to point a
   4        route through, but not to actually transmit packets.
   5
   6        Why?  If you have a machine whose only connection is an occasional
   7        PPP/SLIP/PLIP link, you can only connect to your own hostname
   8        when the link is up.  Otherwise you have to use localhost.
   9        This isn't very consistent.
  10
  11        One solution is to set up a dummy link using PPP/SLIP/PLIP,
  12        but this seems (to me) too much overhead for too little gain.
  13        This driver provides a small alternative. Thus you can do
  14
  15        [when not running slip]
  16                ifconfig dummy slip.addr.ess.here up
  17        [to go to slip]
  18                ifconfig dummy down
  19                dip whatever
  20
  21        This was written by looking at Donald Becker's skeleton driver
  22        and the loopback driver.  I then threw away anything that didn't
  23        apply!  Thanks to Alan Cox for the key clue on what to do with
  24        misguided packets.
  25
  26                        Nick Holloway, 27th May 1994
  27        [I tweaked this explanation a little but that's all]
  28                        Alan Cox, 30th May 1994
  29*/
  30
  31#include <linux/module.h>
  32#include <linux/kernel.h>
  33#include <linux/netdevice.h>
  34#include <linux/etherdevice.h>
  35#include <linux/init.h>
  36#include <linux/moduleparam.h>
  37#include <linux/rtnetlink.h>
  38#include <linux/net_tstamp.h>
  39#include <net/rtnetlink.h>
  40#include <linux/u64_stats_sync.h>
  41
  42#define DRV_NAME        "dummy"
  43#define DRV_VERSION     "1.0"
  44
  45#undef pr_fmt
  46#define pr_fmt(fmt) DRV_NAME ": " fmt
  47
  48static int numdummies = 1;
  49static int num_vfs;
  50
  51struct vf_data_storage {
  52        u8      vf_mac[ETH_ALEN];
  53        u16     pf_vlan; /* When set, guest VLAN config not allowed. */
  54        u16     pf_qos;
  55        __be16  vlan_proto;
  56        u16     min_tx_rate;
  57        u16     max_tx_rate;
  58        u8      spoofchk_enabled;
  59        bool    rss_query_enabled;
  60        u8      trusted;
  61        int     link_state;
  62};
  63
  64struct dummy_priv {
  65        struct vf_data_storage  *vfinfo;
  66};
  67
  68static int dummy_num_vf(struct device *dev)
  69{
  70        return num_vfs;
  71}
  72
  73static struct bus_type dummy_bus = {
  74        .name   = "dummy",
  75        .num_vf = dummy_num_vf,
  76};
  77
  78static void release_dummy_parent(struct device *dev)
  79{
  80}
  81
  82static struct device dummy_parent = {
  83        .init_name      = "dummy",
  84        .bus            = &dummy_bus,
  85        .release        = release_dummy_parent,
  86};
  87
  88/* fake multicast ability */
  89static void set_multicast_list(struct net_device *dev)
  90{
  91}
  92
  93struct pcpu_dstats {
  94        u64                     tx_packets;
  95        u64                     tx_bytes;
  96        struct u64_stats_sync   syncp;
  97};
  98
  99static void dummy_get_stats64(struct net_device *dev,
 100                              struct rtnl_link_stats64 *stats)
 101{
 102        int i;
 103
 104        for_each_possible_cpu(i) {
 105                const struct pcpu_dstats *dstats;
 106                u64 tbytes, tpackets;
 107                unsigned int start;
 108
 109                dstats = per_cpu_ptr(dev->dstats, i);
 110                do {
 111                        start = u64_stats_fetch_begin_irq(&dstats->syncp);
 112                        tbytes = dstats->tx_bytes;
 113                        tpackets = dstats->tx_packets;
 114                } while (u64_stats_fetch_retry_irq(&dstats->syncp, start));
 115                stats->tx_bytes += tbytes;
 116                stats->tx_packets += tpackets;
 117        }
 118}
 119
 120static netdev_tx_t dummy_xmit(struct sk_buff *skb, struct net_device *dev)
 121{
 122        struct pcpu_dstats *dstats = this_cpu_ptr(dev->dstats);
 123
 124        u64_stats_update_begin(&dstats->syncp);
 125        dstats->tx_packets++;
 126        dstats->tx_bytes += skb->len;
 127        u64_stats_update_end(&dstats->syncp);
 128
 129        skb_tx_timestamp(skb);
 130        dev_kfree_skb(skb);
 131        return NETDEV_TX_OK;
 132}
 133
 134static int dummy_dev_init(struct net_device *dev)
 135{
 136        struct dummy_priv *priv = netdev_priv(dev);
 137
 138        dev->dstats = netdev_alloc_pcpu_stats(struct pcpu_dstats);
 139        if (!dev->dstats)
 140                return -ENOMEM;
 141
 142        priv->vfinfo = NULL;
 143
 144        if (!num_vfs)
 145                return 0;
 146
 147        dev->dev.parent = &dummy_parent;
 148        priv->vfinfo = kcalloc(num_vfs, sizeof(struct vf_data_storage),
 149                               GFP_KERNEL);
 150        if (!priv->vfinfo) {
 151                free_percpu(dev->dstats);
 152                return -ENOMEM;
 153        }
 154
 155        return 0;
 156}
 157
 158static void dummy_dev_uninit(struct net_device *dev)
 159{
 160        free_percpu(dev->dstats);
 161}
 162
 163static int dummy_change_carrier(struct net_device *dev, bool new_carrier)
 164{
 165        if (new_carrier)
 166                netif_carrier_on(dev);
 167        else
 168                netif_carrier_off(dev);
 169        return 0;
 170}
 171
 172static int dummy_set_vf_mac(struct net_device *dev, int vf, u8 *mac)
 173{
 174        struct dummy_priv *priv = netdev_priv(dev);
 175
 176        if (!is_valid_ether_addr(mac) || (vf >= num_vfs))
 177                return -EINVAL;
 178
 179        memcpy(priv->vfinfo[vf].vf_mac, mac, ETH_ALEN);
 180
 181        return 0;
 182}
 183
 184static int dummy_set_vf_vlan(struct net_device *dev, int vf,
 185                             u16 vlan, u8 qos, __be16 vlan_proto)
 186{
 187        struct dummy_priv *priv = netdev_priv(dev);
 188
 189        if ((vf >= num_vfs) || (vlan > 4095) || (qos > 7))
 190                return -EINVAL;
 191
 192        priv->vfinfo[vf].pf_vlan = vlan;
 193        priv->vfinfo[vf].pf_qos = qos;
 194        priv->vfinfo[vf].vlan_proto = vlan_proto;
 195
 196        return 0;
 197}
 198
 199static int dummy_set_vf_rate(struct net_device *dev, int vf, int min, int max)
 200{
 201        struct dummy_priv *priv = netdev_priv(dev);
 202
 203        if (vf >= num_vfs)
 204                return -EINVAL;
 205
 206        priv->vfinfo[vf].min_tx_rate = min;
 207        priv->vfinfo[vf].max_tx_rate = max;
 208
 209        return 0;
 210}
 211
 212static int dummy_set_vf_spoofchk(struct net_device *dev, int vf, bool val)
 213{
 214        struct dummy_priv *priv = netdev_priv(dev);
 215
 216        if (vf >= num_vfs)
 217                return -EINVAL;
 218
 219        priv->vfinfo[vf].spoofchk_enabled = val;
 220
 221        return 0;
 222}
 223
 224static int dummy_set_vf_rss_query_en(struct net_device *dev, int vf, bool val)
 225{
 226        struct dummy_priv *priv = netdev_priv(dev);
 227
 228        if (vf >= num_vfs)
 229                return -EINVAL;
 230
 231        priv->vfinfo[vf].rss_query_enabled = val;
 232
 233        return 0;
 234}
 235
 236static int dummy_set_vf_trust(struct net_device *dev, int vf, bool val)
 237{
 238        struct dummy_priv *priv = netdev_priv(dev);
 239
 240        if (vf >= num_vfs)
 241                return -EINVAL;
 242
 243        priv->vfinfo[vf].trusted = val;
 244
 245        return 0;
 246}
 247
 248static int dummy_get_vf_config(struct net_device *dev,
 249                               int vf, struct ifla_vf_info *ivi)
 250{
 251        struct dummy_priv *priv = netdev_priv(dev);
 252
 253        if (vf >= num_vfs)
 254                return -EINVAL;
 255
 256        ivi->vf = vf;
 257        memcpy(&ivi->mac, priv->vfinfo[vf].vf_mac, ETH_ALEN);
 258        ivi->vlan = priv->vfinfo[vf].pf_vlan;
 259        ivi->qos = priv->vfinfo[vf].pf_qos;
 260        ivi->spoofchk = priv->vfinfo[vf].spoofchk_enabled;
 261        ivi->linkstate = priv->vfinfo[vf].link_state;
 262        ivi->min_tx_rate = priv->vfinfo[vf].min_tx_rate;
 263        ivi->max_tx_rate = priv->vfinfo[vf].max_tx_rate;
 264        ivi->rss_query_en = priv->vfinfo[vf].rss_query_enabled;
 265        ivi->trusted = priv->vfinfo[vf].trusted;
 266        ivi->vlan_proto = priv->vfinfo[vf].vlan_proto;
 267
 268        return 0;
 269}
 270
 271static int dummy_set_vf_link_state(struct net_device *dev, int vf, int state)
 272{
 273        struct dummy_priv *priv = netdev_priv(dev);
 274
 275        if (vf >= num_vfs)
 276                return -EINVAL;
 277
 278        priv->vfinfo[vf].link_state = state;
 279
 280        return 0;
 281}
 282
 283static const struct net_device_ops dummy_netdev_ops = {
 284        .ndo_init               = dummy_dev_init,
 285        .ndo_uninit             = dummy_dev_uninit,
 286        .ndo_start_xmit         = dummy_xmit,
 287        .ndo_validate_addr      = eth_validate_addr,
 288        .ndo_set_rx_mode        = set_multicast_list,
 289        .ndo_set_mac_address    = eth_mac_addr,
 290        .ndo_get_stats64        = dummy_get_stats64,
 291        .ndo_change_carrier     = dummy_change_carrier,
 292        .ndo_set_vf_mac         = dummy_set_vf_mac,
 293        .ndo_set_vf_vlan        = dummy_set_vf_vlan,
 294        .ndo_set_vf_rate        = dummy_set_vf_rate,
 295        .ndo_set_vf_spoofchk    = dummy_set_vf_spoofchk,
 296        .ndo_set_vf_trust       = dummy_set_vf_trust,
 297        .ndo_get_vf_config      = dummy_get_vf_config,
 298        .ndo_set_vf_link_state  = dummy_set_vf_link_state,
 299        .ndo_set_vf_rss_query_en = dummy_set_vf_rss_query_en,
 300};
 301
 302static void dummy_get_drvinfo(struct net_device *dev,
 303                              struct ethtool_drvinfo *info)
 304{
 305        strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
 306        strlcpy(info->version, DRV_VERSION, sizeof(info->version));
 307}
 308
 309static int dummy_get_ts_info(struct net_device *dev,
 310                              struct ethtool_ts_info *ts_info)
 311{
 312        ts_info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE |
 313                                   SOF_TIMESTAMPING_RX_SOFTWARE |
 314                                   SOF_TIMESTAMPING_SOFTWARE;
 315
 316        ts_info->phc_index = -1;
 317
 318        return 0;
 319};
 320
 321static const struct ethtool_ops dummy_ethtool_ops = {
 322        .get_drvinfo            = dummy_get_drvinfo,
 323        .get_ts_info            = dummy_get_ts_info,
 324};
 325
 326static void dummy_free_netdev(struct net_device *dev)
 327{
 328        struct dummy_priv *priv = netdev_priv(dev);
 329
 330        kfree(priv->vfinfo);
 331}
 332
 333static void dummy_setup(struct net_device *dev)
 334{
 335        ether_setup(dev);
 336
 337        /* Initialize the device structure. */
 338        dev->netdev_ops = &dummy_netdev_ops;
 339        dev->ethtool_ops = &dummy_ethtool_ops;
 340        dev->needs_free_netdev = true;
 341        dev->priv_destructor = dummy_free_netdev;
 342
 343        /* Fill in device structure with ethernet-generic values. */
 344        dev->flags |= IFF_NOARP;
 345        dev->flags &= ~IFF_MULTICAST;
 346        dev->priv_flags |= IFF_LIVE_ADDR_CHANGE | IFF_NO_QUEUE;
 347        dev->features   |= NETIF_F_SG | NETIF_F_FRAGLIST;
 348        dev->features   |= NETIF_F_ALL_TSO | NETIF_F_UFO;
 349        dev->features   |= NETIF_F_HW_CSUM | NETIF_F_HIGHDMA | NETIF_F_LLTX;
 350        dev->features   |= NETIF_F_GSO_ENCAP_ALL;
 351        dev->hw_features |= dev->features;
 352        dev->hw_enc_features |= dev->features;
 353        eth_hw_addr_random(dev);
 354
 355        dev->min_mtu = 0;
 356        dev->max_mtu = ETH_MAX_MTU;
 357}
 358
 359static int dummy_validate(struct nlattr *tb[], struct nlattr *data[],
 360                          struct netlink_ext_ack *extack)
 361{
 362        if (tb[IFLA_ADDRESS]) {
 363                if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN)
 364                        return -EINVAL;
 365                if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS])))
 366                        return -EADDRNOTAVAIL;
 367        }
 368        return 0;
 369}
 370
 371static struct rtnl_link_ops dummy_link_ops __read_mostly = {
 372        .kind           = DRV_NAME,
 373        .priv_size      = sizeof(struct dummy_priv),
 374        .setup          = dummy_setup,
 375        .validate       = dummy_validate,
 376};
 377
 378/* Number of dummy devices to be set up by this module. */
 379module_param(numdummies, int, 0);
 380MODULE_PARM_DESC(numdummies, "Number of dummy pseudo devices");
 381
 382module_param(num_vfs, int, 0);
 383MODULE_PARM_DESC(num_vfs, "Number of dummy VFs per dummy device");
 384
 385static int __init dummy_init_one(void)
 386{
 387        struct net_device *dev_dummy;
 388        int err;
 389
 390        dev_dummy = alloc_netdev(sizeof(struct dummy_priv),
 391                                 "dummy%d", NET_NAME_UNKNOWN, dummy_setup);
 392        if (!dev_dummy)
 393                return -ENOMEM;
 394
 395        dev_dummy->rtnl_link_ops = &dummy_link_ops;
 396        err = register_netdevice(dev_dummy);
 397        if (err < 0)
 398                goto err;
 399        return 0;
 400
 401err:
 402        free_netdev(dev_dummy);
 403        return err;
 404}
 405
 406static int __init dummy_init_module(void)
 407{
 408        int i, err = 0;
 409
 410        if (num_vfs) {
 411                err = bus_register(&dummy_bus);
 412                if (err < 0) {
 413                        pr_err("registering dummy bus failed\n");
 414                        return err;
 415                }
 416
 417                err = device_register(&dummy_parent);
 418                if (err < 0) {
 419                        pr_err("registering dummy parent device failed\n");
 420                        bus_unregister(&dummy_bus);
 421                        return err;
 422                }
 423        }
 424
 425        rtnl_lock();
 426        err = __rtnl_link_register(&dummy_link_ops);
 427        if (err < 0)
 428                goto out;
 429
 430        for (i = 0; i < numdummies && !err; i++) {
 431                err = dummy_init_one();
 432                cond_resched();
 433        }
 434        if (err < 0)
 435                __rtnl_link_unregister(&dummy_link_ops);
 436
 437out:
 438        rtnl_unlock();
 439
 440        if (err && num_vfs) {
 441                device_unregister(&dummy_parent);
 442                bus_unregister(&dummy_bus);
 443        }
 444
 445        return err;
 446}
 447
 448static void __exit dummy_cleanup_module(void)
 449{
 450        rtnl_link_unregister(&dummy_link_ops);
 451
 452        if (num_vfs) {
 453                device_unregister(&dummy_parent);
 454                bus_unregister(&dummy_bus);
 455        }
 456}
 457
 458module_init(dummy_init_module);
 459module_exit(dummy_cleanup_module);
 460MODULE_LICENSE("GPL");
 461MODULE_ALIAS_RTNL_LINK(DRV_NAME);
 462MODULE_VERSION(DRV_VERSION);
 463