diff options
Diffstat (limited to 'drivers/net/netdevsim')
-rw-r--r-- | drivers/net/netdevsim/bus.c | 29 | ||||
-rw-r--r-- | drivers/net/netdevsim/dev.c | 66 | ||||
-rw-r--r-- | drivers/net/netdevsim/ethtool.c | 21 | ||||
-rw-r--r-- | drivers/net/netdevsim/hwstats.c | 5 | ||||
-rw-r--r-- | drivers/net/netdevsim/netdev.c | 163 | ||||
-rw-r--r-- | drivers/net/netdevsim/netdevsim.h | 18 | ||||
-rw-r--r-- | drivers/net/netdevsim/udp_tunnels.c | 12 |
7 files changed, 226 insertions, 88 deletions
diff --git a/drivers/net/netdevsim/bus.c b/drivers/net/netdevsim/bus.c index 64c0cdd31bf8..70e8c38ddad6 100644 --- a/drivers/net/netdevsim/bus.c +++ b/drivers/net/netdevsim/bus.c @@ -66,17 +66,35 @@ new_port_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct nsim_bus_dev *nsim_bus_dev = to_nsim_bus_dev(dev); + u8 eth_addr[ETH_ALEN] = {}; unsigned int port_index; + bool addr_set = false; int ret; /* Prevent to use nsim_bus_dev before initialization. */ if (!smp_load_acquire(&nsim_bus_dev->init)) return -EBUSY; - ret = kstrtouint(buf, 0, &port_index); - if (ret) - return ret; - ret = nsim_drv_port_add(nsim_bus_dev, NSIM_DEV_PORT_TYPE_PF, port_index); + ret = sscanf(buf, "%u %hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &port_index, + ð_addr[0], ð_addr[1], ð_addr[2], ð_addr[3], + ð_addr[4], ð_addr[5]); + switch (ret) { + case 7: + if (!is_valid_ether_addr(eth_addr)) { + pr_err("The supplied perm_addr is not a valid MAC address\n"); + return -EINVAL; + } + addr_set = true; + fallthrough; + case 1: + break; + default: + pr_err("Format for adding new port is \"id [perm_addr]\" (uint MAC).\n"); + return -EINVAL; + } + + ret = nsim_drv_port_add(nsim_bus_dev, NSIM_DEV_PORT_TYPE_PF, port_index, + addr_set ? eth_addr : NULL); return ret ? ret : count; } @@ -366,6 +384,9 @@ static ssize_t unlink_device_store(const struct bus_type *bus, const char *buf, err = 0; RCU_INIT_POINTER(nsim->peer, NULL); RCU_INIT_POINTER(peer->peer, NULL); + synchronize_net(); + netif_tx_wake_all_queues(dev); + netif_tx_wake_all_queues(peer->netdev); out_put_netns: put_net(ns); diff --git a/drivers/net/netdevsim/dev.c b/drivers/net/netdevsim/dev.c index 3e0b61202f0c..2672d071b325 100644 --- a/drivers/net/netdevsim/dev.c +++ b/drivers/net/netdevsim/dev.c @@ -314,6 +314,8 @@ static int nsim_dev_debugfs_init(struct nsim_dev *nsim_dev) &nsim_dev->fw_update_status); debugfs_create_u32("fw_update_overwrite_mask", 0600, nsim_dev->ddir, &nsim_dev->fw_update_overwrite_mask); + debugfs_create_u32("fw_update_flash_chunk_time_ms", 0600, nsim_dev->ddir, + &nsim_dev->fw_update_flash_chunk_time_ms); debugfs_create_u32("max_macs", 0600, nsim_dev->ddir, &nsim_dev->max_macs); debugfs_create_bool("test1", 0600, nsim_dev->ddir, @@ -388,6 +390,17 @@ static const struct file_operations nsim_dev_rate_parent_fops = { .owner = THIS_MODULE, }; +static void nsim_dev_tc_bw_debugfs_init(struct dentry *ddir, u32 *tc_bw) +{ + int i; + + for (i = 0; i < DEVLINK_RATE_TCS_MAX; i++) { + char name[16]; + + snprintf(name, sizeof(name), "tc%d_bw", i); + debugfs_create_u32(name, 0400, ddir, &tc_bw[i]); + } +} static int nsim_dev_port_debugfs_init(struct nsim_dev *nsim_dev, struct nsim_dev_port *nsim_dev_port) { @@ -415,6 +428,8 @@ static int nsim_dev_port_debugfs_init(struct nsim_dev *nsim_dev, nsim_dev_port->ddir, &nsim_dev_port->parent_name, &nsim_dev_rate_parent_fops); + nsim_dev_tc_bw_debugfs_init(nsim_dev_port->ddir, + nsim_dev_port->tc_bw); } debugfs_create_symlink("dev", nsim_dev_port->ddir, dev_link_name); @@ -576,7 +591,7 @@ static void nsim_dev_dummy_region_exit(struct nsim_dev *nsim_dev) static int __nsim_dev_port_add(struct nsim_dev *nsim_dev, enum nsim_dev_port_type type, - unsigned int port_index); + unsigned int port_index, u8 perm_addr[ETH_ALEN]); static void __nsim_dev_port_del(struct nsim_dev_port *nsim_dev_port); static int nsim_esw_legacy_enable(struct nsim_dev *nsim_dev, @@ -600,7 +615,7 @@ static int nsim_esw_switchdev_enable(struct nsim_dev *nsim_dev, int i, err; for (i = 0; i < nsim_dev_get_vfs(nsim_dev); i++) { - err = __nsim_dev_port_add(nsim_dev, NSIM_DEV_PORT_TYPE_VF, i); + err = __nsim_dev_port_add(nsim_dev, NSIM_DEV_PORT_TYPE_VF, i, NULL); if (err) { NL_SET_ERR_MSG_MOD(extack, "Failed to initialize VFs' netdevsim ports"); pr_err("Failed to initialize VF id=%d. %d.\n", i, err); @@ -1002,9 +1017,9 @@ static int nsim_dev_info_get(struct devlink *devlink, DEVLINK_INFO_VERSION_TYPE_COMPONENT); } -#define NSIM_DEV_FLASH_SIZE 500000 +#define NSIM_DEV_FLASH_SIZE 50000 #define NSIM_DEV_FLASH_CHUNK_SIZE 1000 -#define NSIM_DEV_FLASH_CHUNK_TIME_MS 10 +#define NSIM_DEV_FLASH_CHUNK_TIME_MS_DEFAULT 100 static int nsim_dev_flash_update(struct devlink *devlink, struct devlink_flash_update_params *params, @@ -1028,7 +1043,7 @@ static int nsim_dev_flash_update(struct devlink *devlink, params->component, i * NSIM_DEV_FLASH_CHUNK_SIZE, NSIM_DEV_FLASH_SIZE); - msleep(NSIM_DEV_FLASH_CHUNK_TIME_MS); + msleep(nsim_dev->fw_update_flash_chunk_time_ms ?: 1); } if (nsim_dev->fw_update_status) { @@ -1172,6 +1187,19 @@ static int nsim_rate_bytes_to_units(char *name, u64 *rate, struct netlink_ext_ac return 0; } +static int nsim_leaf_tc_bw_set(struct devlink_rate *devlink_rate, + void *priv, u32 *tc_bw, + struct netlink_ext_ack *extack) +{ + struct nsim_dev_port *nsim_dev_port = priv; + int i; + + for (i = 0; i < DEVLINK_RATE_TCS_MAX; i++) + nsim_dev_port->tc_bw[i] = tc_bw[i]; + + return 0; +} + static int nsim_leaf_tx_share_set(struct devlink_rate *devlink_rate, void *priv, u64 tx_share, struct netlink_ext_ack *extack) { @@ -1210,8 +1238,21 @@ struct nsim_rate_node { char *parent_name; u16 tx_share; u16 tx_max; + u32 tc_bw[DEVLINK_RATE_TCS_MAX]; }; +static int nsim_node_tc_bw_set(struct devlink_rate *devlink_rate, void *priv, + u32 *tc_bw, struct netlink_ext_ack *extack) +{ + struct nsim_rate_node *nsim_node = priv; + int i; + + for (i = 0; i < DEVLINK_RATE_TCS_MAX; i++) + nsim_node->tc_bw[i] = tc_bw[i]; + + return 0; +} + static int nsim_node_tx_share_set(struct devlink_rate *devlink_rate, void *priv, u64 tx_share, struct netlink_ext_ack *extack) { @@ -1264,6 +1305,8 @@ static int nsim_rate_node_new(struct devlink_rate *node, void **priv, &nsim_node->parent_name, &nsim_dev_rate_parent_fops); + nsim_dev_tc_bw_debugfs_init(nsim_node->ddir, nsim_node->tc_bw); + *priv = nsim_node; return 0; } @@ -1340,8 +1383,10 @@ static const struct devlink_ops nsim_dev_devlink_ops = { .trap_policer_counter_get = nsim_dev_devlink_trap_policer_counter_get, .rate_leaf_tx_share_set = nsim_leaf_tx_share_set, .rate_leaf_tx_max_set = nsim_leaf_tx_max_set, + .rate_leaf_tc_bw_set = nsim_leaf_tc_bw_set, .rate_node_tx_share_set = nsim_node_tx_share_set, .rate_node_tx_max_set = nsim_node_tx_max_set, + .rate_node_tc_bw_set = nsim_node_tc_bw_set, .rate_node_new = nsim_rate_node_new, .rate_node_del = nsim_rate_node_del, .rate_leaf_parent_set = nsim_rate_leaf_parent_set, @@ -1353,7 +1398,7 @@ static const struct devlink_ops nsim_dev_devlink_ops = { #define NSIM_DEV_TEST1_DEFAULT true static int __nsim_dev_port_add(struct nsim_dev *nsim_dev, enum nsim_dev_port_type type, - unsigned int port_index) + unsigned int port_index, u8 perm_addr[ETH_ALEN]) { struct devlink_port_attrs attrs = {}; struct nsim_dev_port *nsim_dev_port; @@ -1390,7 +1435,7 @@ static int __nsim_dev_port_add(struct nsim_dev *nsim_dev, enum nsim_dev_port_typ if (err) goto err_dl_port_unregister; - nsim_dev_port->ns = nsim_create(nsim_dev, nsim_dev_port); + nsim_dev_port->ns = nsim_create(nsim_dev, nsim_dev_port, perm_addr); if (IS_ERR(nsim_dev_port->ns)) { err = PTR_ERR(nsim_dev_port->ns); goto err_port_debugfs_exit; @@ -1446,7 +1491,7 @@ static int nsim_dev_port_add_all(struct nsim_dev *nsim_dev, int i, err; for (i = 0; i < port_count; i++) { - err = __nsim_dev_port_add(nsim_dev, NSIM_DEV_PORT_TYPE_PF, i); + err = __nsim_dev_port_add(nsim_dev, NSIM_DEV_PORT_TYPE_PF, i, NULL); if (err) goto err_port_del_all; } @@ -1542,6 +1587,7 @@ int nsim_drv_probe(struct nsim_bus_dev *nsim_bus_dev) INIT_LIST_HEAD(&nsim_dev->port_list); nsim_dev->fw_update_status = true; nsim_dev->fw_update_overwrite_mask = 0; + nsim_dev->fw_update_flash_chunk_time_ms = NSIM_DEV_FLASH_CHUNK_TIME_MS_DEFAULT; nsim_dev->max_macs = NSIM_DEV_MAX_MACS_DEFAULT; nsim_dev->test1 = NSIM_DEV_TEST1_DEFAULT; spin_lock_init(&nsim_dev->fa_cookie_lock); @@ -1702,7 +1748,7 @@ __nsim_dev_port_lookup(struct nsim_dev *nsim_dev, enum nsim_dev_port_type type, } int nsim_drv_port_add(struct nsim_bus_dev *nsim_bus_dev, enum nsim_dev_port_type type, - unsigned int port_index) + unsigned int port_index, u8 perm_addr[ETH_ALEN]) { struct nsim_dev *nsim_dev = dev_get_drvdata(&nsim_bus_dev->dev); int err; @@ -1711,7 +1757,7 @@ int nsim_drv_port_add(struct nsim_bus_dev *nsim_bus_dev, enum nsim_dev_port_type if (__nsim_dev_port_lookup(nsim_dev, type, port_index)) err = -EEXIST; else - err = __nsim_dev_port_add(nsim_dev, type, port_index); + err = __nsim_dev_port_add(nsim_dev, type, port_index, perm_addr); devl_unlock(priv_to_devlink(nsim_dev)); return err; } diff --git a/drivers/net/netdevsim/ethtool.c b/drivers/net/netdevsim/ethtool.c index 4d191a3293c7..f631d90c428a 100644 --- a/drivers/net/netdevsim/ethtool.c +++ b/drivers/net/netdevsim/ethtool.c @@ -101,6 +101,22 @@ nsim_get_channels(struct net_device *dev, struct ethtool_channels *ch) ch->combined_count = ns->ethtool.channels; } +static void +nsim_wake_queues(struct net_device *dev) +{ + struct netdevsim *ns = netdev_priv(dev); + struct netdevsim *peer; + + synchronize_net(); + netif_tx_wake_all_queues(dev); + + rcu_read_lock(); + peer = rcu_dereference(ns->peer); + if (peer) + netif_tx_wake_all_queues(peer->netdev); + rcu_read_unlock(); +} + static int nsim_set_channels(struct net_device *dev, struct ethtool_channels *ch) { @@ -113,6 +129,11 @@ nsim_set_channels(struct net_device *dev, struct ethtool_channels *ch) return err; ns->ethtool.channels = ch->combined_count; + + /* Only wake up queues if devices are linked */ + if (rcu_access_pointer(ns->peer)) + nsim_wake_queues(dev); + return 0; } diff --git a/drivers/net/netdevsim/hwstats.c b/drivers/net/netdevsim/hwstats.c index 66b3215db3ac..1abe48e35ca3 100644 --- a/drivers/net/netdevsim/hwstats.c +++ b/drivers/net/netdevsim/hwstats.c @@ -220,7 +220,6 @@ nsim_dev_hwstats_enable_ifindex(struct nsim_dev_hwstats *hwstats, struct nsim_dev_hwstats_netdev *hwsdev; struct nsim_dev *nsim_dev; struct net_device *netdev; - bool notify = false; struct net *net; int err = 0; @@ -251,11 +250,9 @@ nsim_dev_hwstats_enable_ifindex(struct nsim_dev_hwstats *hwstats, if (netdev_offload_xstats_enabled(netdev, type)) { nsim_dev_hwsdev_enable(hwsdev, NULL); - notify = true; + rtnl_offload_xstats_notify(netdev); } - if (notify) - rtnl_offload_xstats_notify(netdev); rtnl_unlock(); return err; diff --git a/drivers/net/netdevsim/netdev.c b/drivers/net/netdevsim/netdev.c index af545d42961c..39fe28af48b9 100644 --- a/drivers/net/netdevsim/netdev.c +++ b/drivers/net/netdevsim/netdev.c @@ -37,7 +37,53 @@ MODULE_IMPORT_NS("NETDEV_INTERNAL"); #define NSIM_RING_SIZE 256 -static int nsim_napi_rx(struct nsim_rq *rq, struct sk_buff *skb) +static void nsim_start_peer_tx_queue(struct net_device *dev, struct nsim_rq *rq) +{ + struct netdevsim *ns = netdev_priv(dev); + struct net_device *peer_dev; + struct netdevsim *peer_ns; + struct netdev_queue *txq; + u16 idx; + + idx = rq->napi.index; + rcu_read_lock(); + peer_ns = rcu_dereference(ns->peer); + if (!peer_ns) + goto out; + + /* TX device */ + peer_dev = peer_ns->netdev; + if (dev->real_num_tx_queues != peer_dev->num_rx_queues) + goto out; + + txq = netdev_get_tx_queue(peer_dev, idx); + if (!netif_tx_queue_stopped(txq)) + goto out; + + netif_tx_wake_queue(txq); +out: + rcu_read_unlock(); +} + +static void nsim_stop_tx_queue(struct net_device *tx_dev, + struct net_device *rx_dev, + struct nsim_rq *rq, + u16 idx) +{ + /* If different queues size, do not stop, since it is not + * easy to find which TX queue is mapped here + */ + if (rx_dev->real_num_tx_queues != tx_dev->num_rx_queues) + return; + + /* rq is the queue on the receive side */ + netif_subqueue_try_stop(tx_dev, idx, + NSIM_RING_SIZE - skb_queue_len(&rq->skb_queue), + NSIM_RING_SIZE / 2); +} + +static int nsim_napi_rx(struct net_device *tx_dev, struct net_device *rx_dev, + struct nsim_rq *rq, struct sk_buff *skb) { if (skb_queue_len(&rq->skb_queue) > NSIM_RING_SIZE) { dev_kfree_skb_any(skb); @@ -45,13 +91,22 @@ static int nsim_napi_rx(struct nsim_rq *rq, struct sk_buff *skb) } skb_queue_tail(&rq->skb_queue, skb); + + /* Stop the peer TX queue avoiding dropping packets later */ + if (skb_queue_len(&rq->skb_queue) >= NSIM_RING_SIZE) + nsim_stop_tx_queue(tx_dev, rx_dev, rq, + skb_get_queue_mapping(skb)); + return NET_RX_SUCCESS; } -static int nsim_forward_skb(struct net_device *dev, struct sk_buff *skb, +static int nsim_forward_skb(struct net_device *tx_dev, + struct net_device *rx_dev, + struct sk_buff *skb, struct nsim_rq *rq) { - return __dev_forward_skb(dev, skb) ?: nsim_napi_rx(rq, skb); + return __dev_forward_skb(rx_dev, skb) ?: + nsim_napi_rx(tx_dev, rx_dev, rq, skb); } static netdev_tx_t nsim_start_xmit(struct sk_buff *skb, struct net_device *dev) @@ -86,26 +141,21 @@ static netdev_tx_t nsim_start_xmit(struct sk_buff *skb, struct net_device *dev) skb_linearize(skb); skb_tx_timestamp(skb); - if (unlikely(nsim_forward_skb(peer_dev, skb, rq) == NET_RX_DROP)) + if (unlikely(nsim_forward_skb(dev, peer_dev, skb, rq) == NET_RX_DROP)) goto out_drop_cnt; if (!hrtimer_active(&rq->napi_timer)) hrtimer_start(&rq->napi_timer, us_to_ktime(5), HRTIMER_MODE_REL); rcu_read_unlock(); - u64_stats_update_begin(&ns->syncp); - ns->tx_packets++; - ns->tx_bytes += len; - u64_stats_update_end(&ns->syncp); + dev_dstats_tx_add(dev, len); return NETDEV_TX_OK; out_drop_free: dev_kfree_skb(skb); out_drop_cnt: rcu_read_unlock(); - u64_stats_update_begin(&ns->syncp); - ns->tx_dropped++; - u64_stats_update_end(&ns->syncp); + dev_dstats_tx_dropped(dev); return NETDEV_TX_OK; } @@ -126,20 +176,6 @@ static int nsim_change_mtu(struct net_device *dev, int new_mtu) return 0; } -static void -nsim_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats) -{ - struct netdevsim *ns = netdev_priv(dev); - unsigned int start; - - do { - start = u64_stats_fetch_begin(&ns->syncp); - stats->tx_bytes = ns->tx_bytes; - stats->tx_packets = ns->tx_packets; - stats->tx_dropped = ns->tx_dropped; - } while (u64_stats_fetch_retry(&ns->syncp, start)); -} - static int nsim_setup_tc_block_cb(enum tc_setup_type type, void *type_data, void *cb_priv) { @@ -350,18 +386,46 @@ static int nsim_get_iflink(const struct net_device *dev) static int nsim_rcv(struct nsim_rq *rq, int budget) { + struct net_device *dev = rq->napi.dev; + struct bpf_prog *xdp_prog; + struct netdevsim *ns; struct sk_buff *skb; - int i; + unsigned int skblen; + int i, ret; + + ns = netdev_priv(dev); + xdp_prog = READ_ONCE(ns->xdp.prog); for (i = 0; i < budget; i++) { if (skb_queue_empty(&rq->skb_queue)) break; skb = skb_dequeue(&rq->skb_queue); + + if (xdp_prog) { + /* skb might be freed directly by XDP, save the len */ + skblen = skb->len; + + if (skb->ip_summed == CHECKSUM_PARTIAL) + skb_checksum_help(skb); + ret = do_xdp_generic(xdp_prog, &skb); + if (ret != XDP_PASS) { + dev_dstats_rx_add(dev, skblen); + continue; + } + } + + /* skb might be discard at netif_receive_skb, save the len */ + skblen = skb->len; skb_mark_napi_id(skb, &rq->napi); - netif_receive_skb(skb); + ret = netif_receive_skb(skb); + if (ret == NET_RX_SUCCESS) + dev_dstats_rx_add(dev, skblen); + else + dev_dstats_rx_dropped(dev); } + nsim_start_peer_tx_queue(dev, rq); return i; } @@ -371,7 +435,8 @@ static int nsim_poll(struct napi_struct *napi, int budget) int done; done = nsim_rcv(rq, budget); - napi_complete(napi); + if (done < budget) + napi_complete_done(napi, done); return done; } @@ -555,7 +620,6 @@ static const struct net_device_ops nsim_netdev_ops = { .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, .ndo_change_mtu = nsim_change_mtu, - .ndo_get_stats64 = nsim_get_stats64, .ndo_set_vf_mac = nsim_set_vf_mac, .ndo_set_vf_vlan = nsim_set_vf_vlan, .ndo_set_vf_rate = nsim_set_vf_rate, @@ -579,7 +643,6 @@ static const struct net_device_ops nsim_vf_netdev_ops = { .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, .ndo_change_mtu = nsim_change_mtu, - .ndo_get_stats64 = nsim_get_stats64, .ndo_setup_tc = nsim_setup_tc, .ndo_set_features = nsim_set_features, }; @@ -593,7 +656,7 @@ static void nsim_get_queue_stats_rx(struct net_device *dev, int idx, struct rtnl_link_stats64 rtstats = {}; if (!idx) - nsim_get_stats64(dev, &rtstats); + dev_get_stats(dev, &rtstats); stats->packets = rtstats.rx_packets - !!rtstats.rx_packets; stats->bytes = rtstats.rx_bytes; @@ -605,7 +668,7 @@ static void nsim_get_queue_stats_tx(struct net_device *dev, int idx, struct rtnl_link_stats64 rtstats = {}; if (!idx) - nsim_get_stats64(dev, &rtstats); + dev_get_stats(dev, &rtstats); stats->packets = rtstats.tx_packets - !!rtstats.tx_packets; stats->bytes = rtstats.tx_bytes; @@ -617,7 +680,7 @@ static void nsim_get_base_stats(struct net_device *dev, { struct rtnl_link_stats64 rtstats = {}; - nsim_get_stats64(dev, &rtstats); + dev_get_stats(dev, &rtstats); rx->packets = !!rtstats.rx_packets; rx->bytes = 0; @@ -644,9 +707,12 @@ static struct nsim_rq *nsim_queue_alloc(void) return rq; } -static void nsim_queue_free(struct nsim_rq *rq) +static void nsim_queue_free(struct net_device *dev, struct nsim_rq *rq) { hrtimer_cancel(&rq->napi_timer); + local_bh_disable(); + dev_dstats_rx_dropped_add(dev, rq->skb_queue.qlen); + local_bh_enable(); skb_queue_purge_reason(&rq->skb_queue, SKB_DROP_REASON_QUEUE_PURGE); kfree(rq); } @@ -693,7 +759,7 @@ nsim_queue_mem_alloc(struct net_device *dev, void *per_queue_mem, int idx) return 0; err_free: - nsim_queue_free(qmem->rq); + nsim_queue_free(dev, qmem->rq); return err; } @@ -707,7 +773,7 @@ static void nsim_queue_mem_free(struct net_device *dev, void *per_queue_mem) if (!ns->rq_reset_mode) netif_napi_del_locked(&qmem->rq->napi); page_pool_destroy(qmem->rq->page_pool); - nsim_queue_free(qmem->rq); + nsim_queue_free(dev, qmem->rq); } } @@ -851,7 +917,8 @@ nsim_pp_hold_write(struct file *file, const char __user *data, if (!ns->page) ret = -ENOMEM; } else { - page_pool_put_full_page(ns->page->pp, ns->page, false); + page_pool_put_full_page(pp_page_to_nmdesc(ns->page)->pp, + ns->page, false); ns->page = NULL; } @@ -873,10 +940,8 @@ static void nsim_setup(struct net_device *dev) ether_setup(dev); eth_hw_addr_random(dev); - dev->tx_queue_len = 0; dev->flags &= ~IFF_MULTICAST; - dev->priv_flags |= IFF_LIVE_ADDR_CHANGE | - IFF_NO_QUEUE; + dev->priv_flags |= IFF_LIVE_ADDR_CHANGE; dev->features |= NETIF_F_HIGHDMA | NETIF_F_SG | NETIF_F_FRAGLIST | @@ -889,8 +954,9 @@ static void nsim_setup(struct net_device *dev) NETIF_F_HW_CSUM | NETIF_F_LRO | NETIF_F_TSO; + dev->pcpu_stat_type = NETDEV_PCPU_STAT_DSTATS; dev->max_mtu = ETH_MAX_MTU; - dev->xdp_features = NETDEV_XDP_ACT_HW_OFFLOAD; + dev->xdp_features = NETDEV_XDP_ACT_BASIC | NETDEV_XDP_ACT_HW_OFFLOAD; } static int nsim_queue_init(struct netdevsim *ns) @@ -924,7 +990,7 @@ static void nsim_queue_uninit(struct netdevsim *ns) int i; for (i = 0; i < dev->num_rx_queues; i++) - nsim_queue_free(ns->rq[i]); + nsim_queue_free(dev, ns->rq[i]); kfree(ns->rq); ns->rq = NULL; @@ -1006,8 +1072,9 @@ static void nsim_exit_netdevsim(struct netdevsim *ns) mock_phc_destroy(ns->phc); } -struct netdevsim * -nsim_create(struct nsim_dev *nsim_dev, struct nsim_dev_port *nsim_dev_port) +struct netdevsim *nsim_create(struct nsim_dev *nsim_dev, + struct nsim_dev_port *nsim_dev_port, + u8 perm_addr[ETH_ALEN]) { struct net_device *dev; struct netdevsim *ns; @@ -1018,10 +1085,12 @@ nsim_create(struct nsim_dev *nsim_dev, struct nsim_dev_port *nsim_dev_port) if (!dev) return ERR_PTR(-ENOMEM); + if (perm_addr) + memcpy(dev->perm_addr, perm_addr, ETH_ALEN); + dev_net_set(dev, nsim_dev_net(nsim_dev)); ns = netdev_priv(dev); ns->netdev = dev; - u64_stats_init(&ns->syncp); ns->nsim_dev = nsim_dev; ns->nsim_dev_port = nsim_dev_port; ns->nsim_bus_dev = nsim_dev->nsim_bus_dev; @@ -1040,7 +1109,6 @@ nsim_create(struct nsim_dev *nsim_dev, struct nsim_dev_port *nsim_dev_port) ns->qr_dfs = debugfs_create_file("queue_reset", 0200, nsim_dev_port->ddir, ns, &nsim_qreset_fops); - return ns; err_free_netdev: @@ -1078,7 +1146,8 @@ void nsim_destroy(struct netdevsim *ns) /* Put this intentionally late to exercise the orphaning path */ if (ns->page) { - page_pool_put_full_page(ns->page->pp, ns->page, false); + page_pool_put_full_page(pp_page_to_nmdesc(ns->page)->pp, + ns->page, false); ns->page = NULL; } diff --git a/drivers/net/netdevsim/netdevsim.h b/drivers/net/netdevsim/netdevsim.h index d04401f0bdf7..bddd24c1389d 100644 --- a/drivers/net/netdevsim/netdevsim.h +++ b/drivers/net/netdevsim/netdevsim.h @@ -108,11 +108,6 @@ struct netdevsim { int rq_reset_mode; - u64 tx_packets; - u64 tx_bytes; - u64 tx_dropped; - struct u64_stats_sync syncp; - struct nsim_bus_dev *nsim_bus_dev; struct bpf_prog *bpf_offloaded; @@ -131,7 +126,6 @@ struct netdevsim { struct nsim_macsec macsec; struct { u32 inject_error; - u32 sleep; u32 __ports[2][NSIM_UDP_TUNNEL_N_PORTS]; u32 (*ports)[NSIM_UDP_TUNNEL_N_PORTS]; struct dentry *ddir; @@ -149,8 +143,9 @@ struct netdevsim { struct netdev_net_notifier nn; }; -struct netdevsim * -nsim_create(struct nsim_dev *nsim_dev, struct nsim_dev_port *nsim_dev_port); +struct netdevsim *nsim_create(struct nsim_dev *nsim_dev, + struct nsim_dev_port *nsim_dev_port, + u8 perm_addr[ETH_ALEN]); void nsim_destroy(struct netdevsim *ns); bool netdev_is_nsim(struct net_device *dev); @@ -282,6 +277,7 @@ struct nsim_dev_port { struct dentry *ddir; struct dentry *rate_parent; char *parent_name; + u32 tc_bw[DEVLINK_RATE_TCS_MAX]; struct netdevsim *ns; }; @@ -321,6 +317,7 @@ struct nsim_dev { struct list_head port_list; bool fw_update_status; u32 fw_update_overwrite_mask; + u32 fw_update_flash_chunk_time_ms; u32 max_macs; bool test1; bool dont_allow_reload; @@ -342,7 +339,6 @@ struct nsim_dev { bool ipv4_only; bool shared; bool static_iana_vxlan; - u32 sleep; } udp_ports; struct nsim_dev_psample *psample; u16 esw_mode; @@ -368,8 +364,8 @@ void nsim_dev_exit(void); int nsim_drv_probe(struct nsim_bus_dev *nsim_bus_dev); void nsim_drv_remove(struct nsim_bus_dev *nsim_bus_dev); int nsim_drv_port_add(struct nsim_bus_dev *nsim_bus_dev, - enum nsim_dev_port_type type, - unsigned int port_index); + enum nsim_dev_port_type type, unsigned int port_index, + u8 perm_addr[ETH_ALEN]); int nsim_drv_port_del(struct nsim_bus_dev *nsim_bus_dev, enum nsim_dev_port_type type, unsigned int port_index); diff --git a/drivers/net/netdevsim/udp_tunnels.c b/drivers/net/netdevsim/udp_tunnels.c index 640b4983a9a0..89fff76e51cf 100644 --- a/drivers/net/netdevsim/udp_tunnels.c +++ b/drivers/net/netdevsim/udp_tunnels.c @@ -18,9 +18,6 @@ nsim_udp_tunnel_set_port(struct net_device *dev, unsigned int table, ret = -ns->udp_ports.inject_error; ns->udp_ports.inject_error = 0; - if (ns->udp_ports.sleep) - msleep(ns->udp_ports.sleep); - if (!ret) { if (ns->udp_ports.ports[table][entry]) { WARN(1, "entry already in use\n"); @@ -47,8 +44,6 @@ nsim_udp_tunnel_unset_port(struct net_device *dev, unsigned int table, ret = -ns->udp_ports.inject_error; ns->udp_ports.inject_error = 0; - if (ns->udp_ports.sleep) - msleep(ns->udp_ports.sleep); if (!ret) { u32 val = be16_to_cpu(ti->port) << 16 | ti->type; @@ -112,12 +107,10 @@ nsim_udp_tunnels_info_reset_write(struct file *file, const char __user *data, struct net_device *dev = file->private_data; struct netdevsim *ns = netdev_priv(dev); - rtnl_lock(); if (dev->reg_state == NETREG_REGISTERED) { memset(ns->udp_ports.ports, 0, sizeof(ns->udp_ports.__ports)); udp_tunnel_nic_reset_ntf(dev); } - rtnl_unlock(); return count; } @@ -172,7 +165,6 @@ int nsim_udp_tunnels_info_create(struct nsim_dev *nsim_dev, GFP_KERNEL); if (!info) return -ENOMEM; - ns->udp_ports.sleep = nsim_dev->udp_ports.sleep; if (nsim_dev->udp_ports.sync_all) { info->set_port = NULL; @@ -181,8 +173,6 @@ int nsim_udp_tunnels_info_create(struct nsim_dev *nsim_dev, info->sync_table = NULL; } - if (ns->udp_ports.sleep) - info->flags |= UDP_TUNNEL_NIC_INFO_MAY_SLEEP; if (nsim_dev->udp_ports.open_only) info->flags |= UDP_TUNNEL_NIC_INFO_OPEN_ONLY; if (nsim_dev->udp_ports.ipv4_only) @@ -217,6 +207,4 @@ void nsim_udp_tunnels_debugfs_create(struct nsim_dev *nsim_dev) &nsim_dev->udp_ports.shared); debugfs_create_bool("udp_ports_static_iana_vxlan", 0600, nsim_dev->ddir, &nsim_dev->udp_ports.static_iana_vxlan); - debugfs_create_u32("udp_ports_sleep", 0600, nsim_dev->ddir, - &nsim_dev->udp_ports.sleep); } |