183c9e13aSJakub Kicinski /* 283c9e13aSJakub Kicinski * Copyright (C) 2017 Netronome Systems, Inc. 383c9e13aSJakub Kicinski * 483c9e13aSJakub Kicinski * This software is licensed under the GNU General License Version 2, 583c9e13aSJakub Kicinski * June 1991 as shown in the file COPYING in the top-level directory of this 683c9e13aSJakub Kicinski * source tree. 783c9e13aSJakub Kicinski * 883c9e13aSJakub Kicinski * THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" 983c9e13aSJakub Kicinski * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, 1083c9e13aSJakub Kicinski * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 1183c9e13aSJakub Kicinski * FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE 1283c9e13aSJakub Kicinski * OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME 1383c9e13aSJakub Kicinski * THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 1483c9e13aSJakub Kicinski */ 1583c9e13aSJakub Kicinski 1631d3ad83SJakub Kicinski #include <linux/debugfs.h> 1783c9e13aSJakub Kicinski #include <linux/etherdevice.h> 1883c9e13aSJakub Kicinski #include <linux/kernel.h> 1983c9e13aSJakub Kicinski #include <linux/module.h> 2083c9e13aSJakub Kicinski #include <linux/netdevice.h> 2183c9e13aSJakub Kicinski #include <linux/slab.h> 2283c9e13aSJakub Kicinski #include <net/netlink.h> 2331d3ad83SJakub Kicinski #include <net/pkt_cls.h> 2483c9e13aSJakub Kicinski #include <net/rtnetlink.h> 2583c9e13aSJakub Kicinski 2683c9e13aSJakub Kicinski #include "netdevsim.h" 2783c9e13aSJakub Kicinski 28*79579220SJakub Kicinski struct nsim_vf_config { 29*79579220SJakub Kicinski int link_state; 30*79579220SJakub Kicinski u16 min_tx_rate; 31*79579220SJakub Kicinski u16 max_tx_rate; 32*79579220SJakub Kicinski u16 vlan; 33*79579220SJakub Kicinski __be16 vlan_proto; 34*79579220SJakub Kicinski u16 qos; 35*79579220SJakub Kicinski u8 vf_mac[ETH_ALEN]; 36*79579220SJakub Kicinski bool spoofchk_enabled; 37*79579220SJakub Kicinski bool trusted; 38*79579220SJakub Kicinski bool rss_query_enabled; 39*79579220SJakub Kicinski }; 40*79579220SJakub Kicinski 41*79579220SJakub Kicinski static u32 nsim_dev_id; 42*79579220SJakub Kicinski 43*79579220SJakub Kicinski static int nsim_num_vf(struct device *dev) 44*79579220SJakub Kicinski { 45*79579220SJakub Kicinski struct netdevsim *ns = to_nsim(dev); 46*79579220SJakub Kicinski 47*79579220SJakub Kicinski return ns->num_vfs; 48*79579220SJakub Kicinski } 49*79579220SJakub Kicinski 50*79579220SJakub Kicinski static struct bus_type nsim_bus = { 51*79579220SJakub Kicinski .name = DRV_NAME, 52*79579220SJakub Kicinski .dev_name = DRV_NAME, 53*79579220SJakub Kicinski .num_vf = nsim_num_vf, 54*79579220SJakub Kicinski }; 55*79579220SJakub Kicinski 56*79579220SJakub Kicinski static int nsim_vfs_enable(struct netdevsim *ns, unsigned int num_vfs) 57*79579220SJakub Kicinski { 58*79579220SJakub Kicinski ns->vfconfigs = kcalloc(num_vfs, sizeof(struct nsim_vf_config), 59*79579220SJakub Kicinski GFP_KERNEL); 60*79579220SJakub Kicinski if (!ns->vfconfigs) 61*79579220SJakub Kicinski return -ENOMEM; 62*79579220SJakub Kicinski ns->num_vfs = num_vfs; 63*79579220SJakub Kicinski 64*79579220SJakub Kicinski return 0; 65*79579220SJakub Kicinski } 66*79579220SJakub Kicinski 67*79579220SJakub Kicinski static void nsim_vfs_disable(struct netdevsim *ns) 68*79579220SJakub Kicinski { 69*79579220SJakub Kicinski kfree(ns->vfconfigs); 70*79579220SJakub Kicinski ns->vfconfigs = NULL; 71*79579220SJakub Kicinski ns->num_vfs = 0; 72*79579220SJakub Kicinski } 73*79579220SJakub Kicinski 74*79579220SJakub Kicinski static ssize_t 75*79579220SJakub Kicinski nsim_numvfs_store(struct device *dev, struct device_attribute *attr, 76*79579220SJakub Kicinski const char *buf, size_t count) 77*79579220SJakub Kicinski { 78*79579220SJakub Kicinski struct netdevsim *ns = to_nsim(dev); 79*79579220SJakub Kicinski unsigned int num_vfs; 80*79579220SJakub Kicinski int ret; 81*79579220SJakub Kicinski 82*79579220SJakub Kicinski ret = kstrtouint(buf, 0, &num_vfs); 83*79579220SJakub Kicinski if (ret) 84*79579220SJakub Kicinski return ret; 85*79579220SJakub Kicinski 86*79579220SJakub Kicinski rtnl_lock(); 87*79579220SJakub Kicinski if (ns->num_vfs == num_vfs) 88*79579220SJakub Kicinski goto exit_good; 89*79579220SJakub Kicinski if (ns->num_vfs && num_vfs) { 90*79579220SJakub Kicinski ret = -EBUSY; 91*79579220SJakub Kicinski goto exit_unlock; 92*79579220SJakub Kicinski } 93*79579220SJakub Kicinski 94*79579220SJakub Kicinski if (num_vfs) { 95*79579220SJakub Kicinski ret = nsim_vfs_enable(ns, num_vfs); 96*79579220SJakub Kicinski if (ret) 97*79579220SJakub Kicinski goto exit_unlock; 98*79579220SJakub Kicinski } else { 99*79579220SJakub Kicinski nsim_vfs_disable(ns); 100*79579220SJakub Kicinski } 101*79579220SJakub Kicinski exit_good: 102*79579220SJakub Kicinski ret = count; 103*79579220SJakub Kicinski exit_unlock: 104*79579220SJakub Kicinski rtnl_unlock(); 105*79579220SJakub Kicinski 106*79579220SJakub Kicinski return ret; 107*79579220SJakub Kicinski } 108*79579220SJakub Kicinski 109*79579220SJakub Kicinski static ssize_t 110*79579220SJakub Kicinski nsim_numvfs_show(struct device *dev, struct device_attribute *attr, char *buf) 111*79579220SJakub Kicinski { 112*79579220SJakub Kicinski struct netdevsim *ns = to_nsim(dev); 113*79579220SJakub Kicinski 114*79579220SJakub Kicinski return sprintf(buf, "%u\n", ns->num_vfs); 115*79579220SJakub Kicinski } 116*79579220SJakub Kicinski 117*79579220SJakub Kicinski static struct device_attribute nsim_numvfs_attr = 118*79579220SJakub Kicinski __ATTR(sriov_numvfs, 0664, nsim_numvfs_show, nsim_numvfs_store); 119*79579220SJakub Kicinski 120*79579220SJakub Kicinski static struct attribute *nsim_dev_attrs[] = { 121*79579220SJakub Kicinski &nsim_numvfs_attr.attr, 122*79579220SJakub Kicinski NULL, 123*79579220SJakub Kicinski }; 124*79579220SJakub Kicinski 125*79579220SJakub Kicinski static const struct attribute_group nsim_dev_attr_group = { 126*79579220SJakub Kicinski .attrs = nsim_dev_attrs, 127*79579220SJakub Kicinski }; 128*79579220SJakub Kicinski 129*79579220SJakub Kicinski static const struct attribute_group *nsim_dev_attr_groups[] = { 130*79579220SJakub Kicinski &nsim_dev_attr_group, 131*79579220SJakub Kicinski NULL, 132*79579220SJakub Kicinski }; 133*79579220SJakub Kicinski 134*79579220SJakub Kicinski static void nsim_dev_release(struct device *dev) 135*79579220SJakub Kicinski { 136*79579220SJakub Kicinski struct netdevsim *ns = to_nsim(dev); 137*79579220SJakub Kicinski 138*79579220SJakub Kicinski nsim_vfs_disable(ns); 139*79579220SJakub Kicinski free_netdev(ns->netdev); 140*79579220SJakub Kicinski } 141*79579220SJakub Kicinski 142*79579220SJakub Kicinski struct device_type nsim_dev_type = { 143*79579220SJakub Kicinski .groups = nsim_dev_attr_groups, 144*79579220SJakub Kicinski .release = nsim_dev_release, 145*79579220SJakub Kicinski }; 146*79579220SJakub Kicinski 14731d3ad83SJakub Kicinski static int nsim_init(struct net_device *dev) 14831d3ad83SJakub Kicinski { 14931d3ad83SJakub Kicinski struct netdevsim *ns = netdev_priv(dev); 15031d3ad83SJakub Kicinski int err; 15131d3ad83SJakub Kicinski 15231d3ad83SJakub Kicinski ns->netdev = dev; 15331d3ad83SJakub Kicinski ns->ddir = debugfs_create_dir(netdev_name(dev), nsim_ddir); 15431d3ad83SJakub Kicinski 15531d3ad83SJakub Kicinski err = nsim_bpf_init(ns); 15631d3ad83SJakub Kicinski if (err) 15731d3ad83SJakub Kicinski goto err_debugfs_destroy; 15831d3ad83SJakub Kicinski 159*79579220SJakub Kicinski ns->dev.id = nsim_dev_id++; 160*79579220SJakub Kicinski ns->dev.bus = &nsim_bus; 161*79579220SJakub Kicinski ns->dev.type = &nsim_dev_type; 162*79579220SJakub Kicinski err = device_register(&ns->dev); 163*79579220SJakub Kicinski if (err) 164*79579220SJakub Kicinski goto err_bpf_uninit; 165*79579220SJakub Kicinski 166*79579220SJakub Kicinski SET_NETDEV_DEV(dev, &ns->dev); 167*79579220SJakub Kicinski 16831d3ad83SJakub Kicinski return 0; 16931d3ad83SJakub Kicinski 170*79579220SJakub Kicinski err_bpf_uninit: 171*79579220SJakub Kicinski nsim_bpf_uninit(ns); 17231d3ad83SJakub Kicinski err_debugfs_destroy: 17331d3ad83SJakub Kicinski debugfs_remove_recursive(ns->ddir); 17431d3ad83SJakub Kicinski return err; 17531d3ad83SJakub Kicinski } 17631d3ad83SJakub Kicinski 17731d3ad83SJakub Kicinski static void nsim_uninit(struct net_device *dev) 17831d3ad83SJakub Kicinski { 17931d3ad83SJakub Kicinski struct netdevsim *ns = netdev_priv(dev); 18031d3ad83SJakub Kicinski 18131d3ad83SJakub Kicinski debugfs_remove_recursive(ns->ddir); 18231d3ad83SJakub Kicinski nsim_bpf_uninit(ns); 18331d3ad83SJakub Kicinski } 18431d3ad83SJakub Kicinski 185*79579220SJakub Kicinski static void nsim_free(struct net_device *dev) 186*79579220SJakub Kicinski { 187*79579220SJakub Kicinski struct netdevsim *ns = netdev_priv(dev); 188*79579220SJakub Kicinski 189*79579220SJakub Kicinski device_unregister(&ns->dev); 190*79579220SJakub Kicinski /* netdev and vf state will be freed out of device_release() */ 191*79579220SJakub Kicinski } 192*79579220SJakub Kicinski 19383c9e13aSJakub Kicinski static netdev_tx_t nsim_start_xmit(struct sk_buff *skb, struct net_device *dev) 19483c9e13aSJakub Kicinski { 19583c9e13aSJakub Kicinski struct netdevsim *ns = netdev_priv(dev); 19683c9e13aSJakub Kicinski 19783c9e13aSJakub Kicinski u64_stats_update_begin(&ns->syncp); 19883c9e13aSJakub Kicinski ns->tx_packets++; 19983c9e13aSJakub Kicinski ns->tx_bytes += skb->len; 20083c9e13aSJakub Kicinski u64_stats_update_end(&ns->syncp); 20183c9e13aSJakub Kicinski 20283c9e13aSJakub Kicinski dev_kfree_skb(skb); 20383c9e13aSJakub Kicinski 20483c9e13aSJakub Kicinski return NETDEV_TX_OK; 20583c9e13aSJakub Kicinski } 20683c9e13aSJakub Kicinski 20783c9e13aSJakub Kicinski static void nsim_set_rx_mode(struct net_device *dev) 20883c9e13aSJakub Kicinski { 20983c9e13aSJakub Kicinski } 21083c9e13aSJakub Kicinski 21131d3ad83SJakub Kicinski static int nsim_change_mtu(struct net_device *dev, int new_mtu) 21231d3ad83SJakub Kicinski { 21331d3ad83SJakub Kicinski struct netdevsim *ns = netdev_priv(dev); 21431d3ad83SJakub Kicinski 21531d3ad83SJakub Kicinski if (ns->xdp_prog_mode == XDP_ATTACHED_DRV && 21631d3ad83SJakub Kicinski new_mtu > NSIM_XDP_MAX_MTU) 21731d3ad83SJakub Kicinski return -EBUSY; 21831d3ad83SJakub Kicinski 21931d3ad83SJakub Kicinski dev->mtu = new_mtu; 22031d3ad83SJakub Kicinski 22131d3ad83SJakub Kicinski return 0; 22231d3ad83SJakub Kicinski } 22331d3ad83SJakub Kicinski 22483c9e13aSJakub Kicinski static void 22583c9e13aSJakub Kicinski nsim_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats) 22683c9e13aSJakub Kicinski { 22783c9e13aSJakub Kicinski struct netdevsim *ns = netdev_priv(dev); 22883c9e13aSJakub Kicinski unsigned int start; 22983c9e13aSJakub Kicinski 23083c9e13aSJakub Kicinski do { 23183c9e13aSJakub Kicinski start = u64_stats_fetch_begin(&ns->syncp); 23283c9e13aSJakub Kicinski stats->tx_bytes = ns->tx_bytes; 23383c9e13aSJakub Kicinski stats->tx_packets = ns->tx_packets; 23483c9e13aSJakub Kicinski } while (u64_stats_fetch_retry(&ns->syncp, start)); 23583c9e13aSJakub Kicinski } 23683c9e13aSJakub Kicinski 23731d3ad83SJakub Kicinski static int 23831d3ad83SJakub Kicinski nsim_setup_tc_block_cb(enum tc_setup_type type, void *type_data, void *cb_priv) 23931d3ad83SJakub Kicinski { 24031d3ad83SJakub Kicinski return nsim_bpf_setup_tc_block_cb(type, type_data, cb_priv); 24131d3ad83SJakub Kicinski } 24231d3ad83SJakub Kicinski 24331d3ad83SJakub Kicinski static int 24431d3ad83SJakub Kicinski nsim_setup_tc_block(struct net_device *dev, struct tc_block_offload *f) 24531d3ad83SJakub Kicinski { 24631d3ad83SJakub Kicinski struct netdevsim *ns = netdev_priv(dev); 24731d3ad83SJakub Kicinski 24831d3ad83SJakub Kicinski if (f->binder_type != TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS) 24931d3ad83SJakub Kicinski return -EOPNOTSUPP; 25031d3ad83SJakub Kicinski 25131d3ad83SJakub Kicinski switch (f->command) { 25231d3ad83SJakub Kicinski case TC_BLOCK_BIND: 25331d3ad83SJakub Kicinski return tcf_block_cb_register(f->block, nsim_setup_tc_block_cb, 25431d3ad83SJakub Kicinski ns, ns); 25531d3ad83SJakub Kicinski case TC_BLOCK_UNBIND: 25631d3ad83SJakub Kicinski tcf_block_cb_unregister(f->block, nsim_setup_tc_block_cb, ns); 25731d3ad83SJakub Kicinski return 0; 25831d3ad83SJakub Kicinski default: 25931d3ad83SJakub Kicinski return -EOPNOTSUPP; 26031d3ad83SJakub Kicinski } 26131d3ad83SJakub Kicinski } 26231d3ad83SJakub Kicinski 263*79579220SJakub Kicinski static int nsim_set_vf_mac(struct net_device *dev, int vf, u8 *mac) 264*79579220SJakub Kicinski { 265*79579220SJakub Kicinski struct netdevsim *ns = netdev_priv(dev); 266*79579220SJakub Kicinski 267*79579220SJakub Kicinski /* Only refuse multicast addresses, zero address can mean unset/any. */ 268*79579220SJakub Kicinski if (vf >= ns->num_vfs || is_multicast_ether_addr(mac)) 269*79579220SJakub Kicinski return -EINVAL; 270*79579220SJakub Kicinski memcpy(ns->vfconfigs[vf].vf_mac, mac, ETH_ALEN); 271*79579220SJakub Kicinski 272*79579220SJakub Kicinski return 0; 273*79579220SJakub Kicinski } 274*79579220SJakub Kicinski 275*79579220SJakub Kicinski static int nsim_set_vf_vlan(struct net_device *dev, int vf, 276*79579220SJakub Kicinski u16 vlan, u8 qos, __be16 vlan_proto) 277*79579220SJakub Kicinski { 278*79579220SJakub Kicinski struct netdevsim *ns = netdev_priv(dev); 279*79579220SJakub Kicinski 280*79579220SJakub Kicinski if (vf >= ns->num_vfs || vlan > 4095 || qos > 7) 281*79579220SJakub Kicinski return -EINVAL; 282*79579220SJakub Kicinski 283*79579220SJakub Kicinski ns->vfconfigs[vf].vlan = vlan; 284*79579220SJakub Kicinski ns->vfconfigs[vf].qos = qos; 285*79579220SJakub Kicinski ns->vfconfigs[vf].vlan_proto = vlan_proto; 286*79579220SJakub Kicinski 287*79579220SJakub Kicinski return 0; 288*79579220SJakub Kicinski } 289*79579220SJakub Kicinski 290*79579220SJakub Kicinski static int nsim_set_vf_rate(struct net_device *dev, int vf, int min, int max) 291*79579220SJakub Kicinski { 292*79579220SJakub Kicinski struct netdevsim *ns = netdev_priv(dev); 293*79579220SJakub Kicinski 294*79579220SJakub Kicinski if (vf >= ns->num_vfs) 295*79579220SJakub Kicinski return -EINVAL; 296*79579220SJakub Kicinski 297*79579220SJakub Kicinski ns->vfconfigs[vf].min_tx_rate = min; 298*79579220SJakub Kicinski ns->vfconfigs[vf].max_tx_rate = max; 299*79579220SJakub Kicinski 300*79579220SJakub Kicinski return 0; 301*79579220SJakub Kicinski } 302*79579220SJakub Kicinski 303*79579220SJakub Kicinski static int nsim_set_vf_spoofchk(struct net_device *dev, int vf, bool val) 304*79579220SJakub Kicinski { 305*79579220SJakub Kicinski struct netdevsim *ns = netdev_priv(dev); 306*79579220SJakub Kicinski 307*79579220SJakub Kicinski if (vf >= ns->num_vfs) 308*79579220SJakub Kicinski return -EINVAL; 309*79579220SJakub Kicinski ns->vfconfigs[vf].spoofchk_enabled = val; 310*79579220SJakub Kicinski 311*79579220SJakub Kicinski return 0; 312*79579220SJakub Kicinski } 313*79579220SJakub Kicinski 314*79579220SJakub Kicinski static int nsim_set_vf_rss_query_en(struct net_device *dev, int vf, bool val) 315*79579220SJakub Kicinski { 316*79579220SJakub Kicinski struct netdevsim *ns = netdev_priv(dev); 317*79579220SJakub Kicinski 318*79579220SJakub Kicinski if (vf >= ns->num_vfs) 319*79579220SJakub Kicinski return -EINVAL; 320*79579220SJakub Kicinski ns->vfconfigs[vf].rss_query_enabled = val; 321*79579220SJakub Kicinski 322*79579220SJakub Kicinski return 0; 323*79579220SJakub Kicinski } 324*79579220SJakub Kicinski 325*79579220SJakub Kicinski static int nsim_set_vf_trust(struct net_device *dev, int vf, bool val) 326*79579220SJakub Kicinski { 327*79579220SJakub Kicinski struct netdevsim *ns = netdev_priv(dev); 328*79579220SJakub Kicinski 329*79579220SJakub Kicinski if (vf >= ns->num_vfs) 330*79579220SJakub Kicinski return -EINVAL; 331*79579220SJakub Kicinski ns->vfconfigs[vf].trusted = val; 332*79579220SJakub Kicinski 333*79579220SJakub Kicinski return 0; 334*79579220SJakub Kicinski } 335*79579220SJakub Kicinski 336*79579220SJakub Kicinski static int 337*79579220SJakub Kicinski nsim_get_vf_config(struct net_device *dev, int vf, struct ifla_vf_info *ivi) 338*79579220SJakub Kicinski { 339*79579220SJakub Kicinski struct netdevsim *ns = netdev_priv(dev); 340*79579220SJakub Kicinski 341*79579220SJakub Kicinski if (vf >= ns->num_vfs) 342*79579220SJakub Kicinski return -EINVAL; 343*79579220SJakub Kicinski 344*79579220SJakub Kicinski ivi->vf = vf; 345*79579220SJakub Kicinski ivi->linkstate = ns->vfconfigs[vf].link_state; 346*79579220SJakub Kicinski ivi->min_tx_rate = ns->vfconfigs[vf].min_tx_rate; 347*79579220SJakub Kicinski ivi->max_tx_rate = ns->vfconfigs[vf].max_tx_rate; 348*79579220SJakub Kicinski ivi->vlan = ns->vfconfigs[vf].vlan; 349*79579220SJakub Kicinski ivi->vlan_proto = ns->vfconfigs[vf].vlan_proto; 350*79579220SJakub Kicinski ivi->qos = ns->vfconfigs[vf].qos; 351*79579220SJakub Kicinski memcpy(&ivi->mac, ns->vfconfigs[vf].vf_mac, ETH_ALEN); 352*79579220SJakub Kicinski ivi->spoofchk = ns->vfconfigs[vf].spoofchk_enabled; 353*79579220SJakub Kicinski ivi->trusted = ns->vfconfigs[vf].trusted; 354*79579220SJakub Kicinski ivi->rss_query_en = ns->vfconfigs[vf].rss_query_enabled; 355*79579220SJakub Kicinski 356*79579220SJakub Kicinski return 0; 357*79579220SJakub Kicinski } 358*79579220SJakub Kicinski 359*79579220SJakub Kicinski static int nsim_set_vf_link_state(struct net_device *dev, int vf, int state) 360*79579220SJakub Kicinski { 361*79579220SJakub Kicinski struct netdevsim *ns = netdev_priv(dev); 362*79579220SJakub Kicinski 363*79579220SJakub Kicinski if (vf >= ns->num_vfs) 364*79579220SJakub Kicinski return -EINVAL; 365*79579220SJakub Kicinski 366*79579220SJakub Kicinski switch (state) { 367*79579220SJakub Kicinski case IFLA_VF_LINK_STATE_AUTO: 368*79579220SJakub Kicinski case IFLA_VF_LINK_STATE_ENABLE: 369*79579220SJakub Kicinski case IFLA_VF_LINK_STATE_DISABLE: 370*79579220SJakub Kicinski break; 371*79579220SJakub Kicinski default: 372*79579220SJakub Kicinski return -EINVAL; 373*79579220SJakub Kicinski } 374*79579220SJakub Kicinski 375*79579220SJakub Kicinski ns->vfconfigs[vf].link_state = state; 376*79579220SJakub Kicinski 377*79579220SJakub Kicinski return 0; 378*79579220SJakub Kicinski } 379*79579220SJakub Kicinski 38031d3ad83SJakub Kicinski static int 38131d3ad83SJakub Kicinski nsim_setup_tc(struct net_device *dev, enum tc_setup_type type, void *type_data) 38231d3ad83SJakub Kicinski { 38331d3ad83SJakub Kicinski switch (type) { 38431d3ad83SJakub Kicinski case TC_SETUP_BLOCK: 38531d3ad83SJakub Kicinski return nsim_setup_tc_block(dev, type_data); 38631d3ad83SJakub Kicinski default: 38731d3ad83SJakub Kicinski return -EOPNOTSUPP; 38831d3ad83SJakub Kicinski } 38931d3ad83SJakub Kicinski } 39031d3ad83SJakub Kicinski 39131d3ad83SJakub Kicinski static int 39231d3ad83SJakub Kicinski nsim_set_features(struct net_device *dev, netdev_features_t features) 39331d3ad83SJakub Kicinski { 39431d3ad83SJakub Kicinski struct netdevsim *ns = netdev_priv(dev); 39531d3ad83SJakub Kicinski 39631d3ad83SJakub Kicinski if ((dev->features & NETIF_F_HW_TC) > (features & NETIF_F_HW_TC)) 39731d3ad83SJakub Kicinski return nsim_bpf_disable_tc(ns); 39831d3ad83SJakub Kicinski 39931d3ad83SJakub Kicinski return 0; 40031d3ad83SJakub Kicinski } 40131d3ad83SJakub Kicinski 40283c9e13aSJakub Kicinski static const struct net_device_ops nsim_netdev_ops = { 40331d3ad83SJakub Kicinski .ndo_init = nsim_init, 40431d3ad83SJakub Kicinski .ndo_uninit = nsim_uninit, 40583c9e13aSJakub Kicinski .ndo_start_xmit = nsim_start_xmit, 40683c9e13aSJakub Kicinski .ndo_set_rx_mode = nsim_set_rx_mode, 40783c9e13aSJakub Kicinski .ndo_set_mac_address = eth_mac_addr, 40883c9e13aSJakub Kicinski .ndo_validate_addr = eth_validate_addr, 40931d3ad83SJakub Kicinski .ndo_change_mtu = nsim_change_mtu, 41083c9e13aSJakub Kicinski .ndo_get_stats64 = nsim_get_stats64, 411*79579220SJakub Kicinski .ndo_set_vf_mac = nsim_set_vf_mac, 412*79579220SJakub Kicinski .ndo_set_vf_vlan = nsim_set_vf_vlan, 413*79579220SJakub Kicinski .ndo_set_vf_rate = nsim_set_vf_rate, 414*79579220SJakub Kicinski .ndo_set_vf_spoofchk = nsim_set_vf_spoofchk, 415*79579220SJakub Kicinski .ndo_set_vf_trust = nsim_set_vf_trust, 416*79579220SJakub Kicinski .ndo_get_vf_config = nsim_get_vf_config, 417*79579220SJakub Kicinski .ndo_set_vf_link_state = nsim_set_vf_link_state, 418*79579220SJakub Kicinski .ndo_set_vf_rss_query_en = nsim_set_vf_rss_query_en, 41931d3ad83SJakub Kicinski .ndo_setup_tc = nsim_setup_tc, 42031d3ad83SJakub Kicinski .ndo_set_features = nsim_set_features, 42131d3ad83SJakub Kicinski .ndo_bpf = nsim_bpf, 42283c9e13aSJakub Kicinski }; 42383c9e13aSJakub Kicinski 42483c9e13aSJakub Kicinski static void nsim_setup(struct net_device *dev) 42583c9e13aSJakub Kicinski { 42683c9e13aSJakub Kicinski ether_setup(dev); 42783c9e13aSJakub Kicinski eth_hw_addr_random(dev); 42883c9e13aSJakub Kicinski 42983c9e13aSJakub Kicinski dev->netdev_ops = &nsim_netdev_ops; 430*79579220SJakub Kicinski dev->priv_destructor = nsim_free; 43183c9e13aSJakub Kicinski 43283c9e13aSJakub Kicinski dev->tx_queue_len = 0; 43383c9e13aSJakub Kicinski dev->flags |= IFF_NOARP; 43483c9e13aSJakub Kicinski dev->flags &= ~IFF_MULTICAST; 43583c9e13aSJakub Kicinski dev->priv_flags |= IFF_LIVE_ADDR_CHANGE | 43683c9e13aSJakub Kicinski IFF_NO_QUEUE; 43783c9e13aSJakub Kicinski dev->features |= NETIF_F_HIGHDMA | 43883c9e13aSJakub Kicinski NETIF_F_SG | 43983c9e13aSJakub Kicinski NETIF_F_FRAGLIST | 44083c9e13aSJakub Kicinski NETIF_F_HW_CSUM | 44183c9e13aSJakub Kicinski NETIF_F_TSO; 44231d3ad83SJakub Kicinski dev->hw_features |= NETIF_F_HW_TC; 44383c9e13aSJakub Kicinski dev->max_mtu = ETH_MAX_MTU; 44483c9e13aSJakub Kicinski } 44583c9e13aSJakub Kicinski 44683c9e13aSJakub Kicinski static int nsim_validate(struct nlattr *tb[], struct nlattr *data[], 44783c9e13aSJakub Kicinski struct netlink_ext_ack *extack) 44883c9e13aSJakub Kicinski { 44983c9e13aSJakub Kicinski if (tb[IFLA_ADDRESS]) { 45083c9e13aSJakub Kicinski if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN) 45183c9e13aSJakub Kicinski return -EINVAL; 45283c9e13aSJakub Kicinski if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS]))) 45383c9e13aSJakub Kicinski return -EADDRNOTAVAIL; 45483c9e13aSJakub Kicinski } 45583c9e13aSJakub Kicinski return 0; 45683c9e13aSJakub Kicinski } 45783c9e13aSJakub Kicinski 45883c9e13aSJakub Kicinski static struct rtnl_link_ops nsim_link_ops __read_mostly = { 45983c9e13aSJakub Kicinski .kind = DRV_NAME, 46083c9e13aSJakub Kicinski .priv_size = sizeof(struct netdevsim), 46183c9e13aSJakub Kicinski .setup = nsim_setup, 46283c9e13aSJakub Kicinski .validate = nsim_validate, 46383c9e13aSJakub Kicinski }; 46483c9e13aSJakub Kicinski 46531d3ad83SJakub Kicinski struct dentry *nsim_ddir; 46631d3ad83SJakub Kicinski 46783c9e13aSJakub Kicinski static int __init nsim_module_init(void) 46883c9e13aSJakub Kicinski { 46931d3ad83SJakub Kicinski int err; 47031d3ad83SJakub Kicinski 47131d3ad83SJakub Kicinski nsim_ddir = debugfs_create_dir(DRV_NAME, NULL); 47231d3ad83SJakub Kicinski if (IS_ERR(nsim_ddir)) 47331d3ad83SJakub Kicinski return PTR_ERR(nsim_ddir); 47431d3ad83SJakub Kicinski 475*79579220SJakub Kicinski err = bus_register(&nsim_bus); 47631d3ad83SJakub Kicinski if (err) 47731d3ad83SJakub Kicinski goto err_debugfs_destroy; 47831d3ad83SJakub Kicinski 479*79579220SJakub Kicinski err = rtnl_link_register(&nsim_link_ops); 480*79579220SJakub Kicinski if (err) 481*79579220SJakub Kicinski goto err_unreg_bus; 482*79579220SJakub Kicinski 48331d3ad83SJakub Kicinski return 0; 48431d3ad83SJakub Kicinski 485*79579220SJakub Kicinski err_unreg_bus: 486*79579220SJakub Kicinski bus_unregister(&nsim_bus); 48731d3ad83SJakub Kicinski err_debugfs_destroy: 48831d3ad83SJakub Kicinski debugfs_remove_recursive(nsim_ddir); 48931d3ad83SJakub Kicinski return err; 49083c9e13aSJakub Kicinski } 49183c9e13aSJakub Kicinski 49283c9e13aSJakub Kicinski static void __exit nsim_module_exit(void) 49383c9e13aSJakub Kicinski { 49483c9e13aSJakub Kicinski rtnl_link_unregister(&nsim_link_ops); 495*79579220SJakub Kicinski bus_unregister(&nsim_bus); 49631d3ad83SJakub Kicinski debugfs_remove_recursive(nsim_ddir); 49783c9e13aSJakub Kicinski } 49883c9e13aSJakub Kicinski 49983c9e13aSJakub Kicinski module_init(nsim_module_init); 50083c9e13aSJakub Kicinski module_exit(nsim_module_exit); 50183c9e13aSJakub Kicinski MODULE_LICENSE("GPL"); 50283c9e13aSJakub Kicinski MODULE_ALIAS_RTNL_LINK(DRV_NAME); 503