Centos-kernel-stream-9/drivers/net/netdevsim/netdev.c

853 lines
19 KiB
C
Raw Normal View History

/*
* Copyright (C) 2017 Netronome Systems, Inc.
*
* This software is licensed under the GNU General License Version 2,
* June 1991 as shown in the file COPYING in the top-level directory of this
* source tree.
*
* THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS"
* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE
* OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME
* THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
*/
#include <linux/debugfs.h>
#include <linux/etherdevice.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/slab.h>
#include <net/netdev_queues.h>
#include <net/page_pool/helpers.h>
#include <net/netlink.h>
#include <net/pkt_cls.h>
#include <net/rtnetlink.h>
#include <net/udp_tunnel.h>
#include "netdevsim.h"
#define NSIM_RING_SIZE 256
static int nsim_napi_rx(struct nsim_rq *rq, struct sk_buff *skb)
{
if (skb_queue_len(&rq->skb_queue) > NSIM_RING_SIZE) {
dev_kfree_skb_any(skb);
return NET_RX_DROP;
}
skb_queue_tail(&rq->skb_queue, skb);
return NET_RX_SUCCESS;
}
static int nsim_forward_skb(struct net_device *dev, struct sk_buff *skb,
struct nsim_rq *rq)
{
return __dev_forward_skb(dev, skb) ?: nsim_napi_rx(rq, skb);
}
static netdev_tx_t nsim_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct netdevsim *ns = netdev_priv(dev);
struct net_device *peer_dev;
netdevsim: forward skbs from one connected port to another JIRA: https://issues.redhat.com/browse/RHEL-38987 Upstream commit(s): commit 9eb95228a74163e26d338913a5d61e571ea45307 Author: David Wei <dw@davidwei.uk> Date: Wed Feb 28 15:22:50 2024 -0800 netdevsim: forward skbs from one connected port to another Forward skbs sent from one netdevsim port to its connected netdevsim port using dev_forward_skb, in a spirit similar to veth. Add a tx_dropped variable to struct netdevsim, tracking the number of skbs that could not be forwarded using dev_forward_skb(). The xmit() function accessing the peer ptr is protected by an RCU read critical section. The rcu_read_lock() is functionally redundant as since v5.0 all softirqs are implicitly RCU read critical sections; but it is useful for human readers. If another CPU is concurrently in nsim_destroy(), then it will first set the peer ptr to NULL. This does not affect any existing readers that dereferenced a non-NULL peer. Then, in unregister_netdevice(), there is a synchronize_rcu() before the netdev is actually unregistered and freed. This ensures that any readers i.e. xmit() that got a non-NULL peer will complete before the netdev is freed. Any readers after the RCU_INIT_POINTER() but before synchronize_rcu() will dereference NULL, making it safe. The codepath to nsim_destroy() and nsim_create() takes both the newly added nsim_dev_list_lock and rtnl_lock. This makes it safe with concurrent calls to linking two netdevsims together. Signed-off-by: David Wei <dw@davidwei.uk> Reviewed-by: Maciek Machnikowski <maciek@machnikowski.net> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Petr Oros <poros@redhat.com>
2024-05-28 11:28:32 +00:00
unsigned int len = skb->len;
struct netdevsim *peer_ns;
struct nsim_rq *rq;
int rxq;
netdevsim: forward skbs from one connected port to another JIRA: https://issues.redhat.com/browse/RHEL-38987 Upstream commit(s): commit 9eb95228a74163e26d338913a5d61e571ea45307 Author: David Wei <dw@davidwei.uk> Date: Wed Feb 28 15:22:50 2024 -0800 netdevsim: forward skbs from one connected port to another Forward skbs sent from one netdevsim port to its connected netdevsim port using dev_forward_skb, in a spirit similar to veth. Add a tx_dropped variable to struct netdevsim, tracking the number of skbs that could not be forwarded using dev_forward_skb(). The xmit() function accessing the peer ptr is protected by an RCU read critical section. The rcu_read_lock() is functionally redundant as since v5.0 all softirqs are implicitly RCU read critical sections; but it is useful for human readers. If another CPU is concurrently in nsim_destroy(), then it will first set the peer ptr to NULL. This does not affect any existing readers that dereferenced a non-NULL peer. Then, in unregister_netdevice(), there is a synchronize_rcu() before the netdev is actually unregistered and freed. This ensures that any readers i.e. xmit() that got a non-NULL peer will complete before the netdev is freed. Any readers after the RCU_INIT_POINTER() but before synchronize_rcu() will dereference NULL, making it safe. The codepath to nsim_destroy() and nsim_create() takes both the newly added nsim_dev_list_lock and rtnl_lock. This makes it safe with concurrent calls to linking two netdevsims together. Signed-off-by: David Wei <dw@davidwei.uk> Reviewed-by: Maciek Machnikowski <maciek@machnikowski.net> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Petr Oros <poros@redhat.com>
2024-05-28 11:28:32 +00:00
rcu_read_lock();
if (!nsim_ipsec_tx(ns, skb))
netdevsim: forward skbs from one connected port to another JIRA: https://issues.redhat.com/browse/RHEL-38987 Upstream commit(s): commit 9eb95228a74163e26d338913a5d61e571ea45307 Author: David Wei <dw@davidwei.uk> Date: Wed Feb 28 15:22:50 2024 -0800 netdevsim: forward skbs from one connected port to another Forward skbs sent from one netdevsim port to its connected netdevsim port using dev_forward_skb, in a spirit similar to veth. Add a tx_dropped variable to struct netdevsim, tracking the number of skbs that could not be forwarded using dev_forward_skb(). The xmit() function accessing the peer ptr is protected by an RCU read critical section. The rcu_read_lock() is functionally redundant as since v5.0 all softirqs are implicitly RCU read critical sections; but it is useful for human readers. If another CPU is concurrently in nsim_destroy(), then it will first set the peer ptr to NULL. This does not affect any existing readers that dereferenced a non-NULL peer. Then, in unregister_netdevice(), there is a synchronize_rcu() before the netdev is actually unregistered and freed. This ensures that any readers i.e. xmit() that got a non-NULL peer will complete before the netdev is freed. Any readers after the RCU_INIT_POINTER() but before synchronize_rcu() will dereference NULL, making it safe. The codepath to nsim_destroy() and nsim_create() takes both the newly added nsim_dev_list_lock and rtnl_lock. This makes it safe with concurrent calls to linking two netdevsims together. Signed-off-by: David Wei <dw@davidwei.uk> Reviewed-by: Maciek Machnikowski <maciek@machnikowski.net> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Petr Oros <poros@redhat.com>
2024-05-28 11:28:32 +00:00
goto out_drop_free;
netdevsim: forward skbs from one connected port to another JIRA: https://issues.redhat.com/browse/RHEL-38987 Upstream commit(s): commit 9eb95228a74163e26d338913a5d61e571ea45307 Author: David Wei <dw@davidwei.uk> Date: Wed Feb 28 15:22:50 2024 -0800 netdevsim: forward skbs from one connected port to another Forward skbs sent from one netdevsim port to its connected netdevsim port using dev_forward_skb, in a spirit similar to veth. Add a tx_dropped variable to struct netdevsim, tracking the number of skbs that could not be forwarded using dev_forward_skb(). The xmit() function accessing the peer ptr is protected by an RCU read critical section. The rcu_read_lock() is functionally redundant as since v5.0 all softirqs are implicitly RCU read critical sections; but it is useful for human readers. If another CPU is concurrently in nsim_destroy(), then it will first set the peer ptr to NULL. This does not affect any existing readers that dereferenced a non-NULL peer. Then, in unregister_netdevice(), there is a synchronize_rcu() before the netdev is actually unregistered and freed. This ensures that any readers i.e. xmit() that got a non-NULL peer will complete before the netdev is freed. Any readers after the RCU_INIT_POINTER() but before synchronize_rcu() will dereference NULL, making it safe. The codepath to nsim_destroy() and nsim_create() takes both the newly added nsim_dev_list_lock and rtnl_lock. This makes it safe with concurrent calls to linking two netdevsims together. Signed-off-by: David Wei <dw@davidwei.uk> Reviewed-by: Maciek Machnikowski <maciek@machnikowski.net> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Petr Oros <poros@redhat.com>
2024-05-28 11:28:32 +00:00
peer_ns = rcu_dereference(ns->peer);
if (!peer_ns)
goto out_drop_free;
peer_dev = peer_ns->netdev;
rxq = skb_get_queue_mapping(skb);
if (rxq >= peer_dev->num_rx_queues)
rxq = rxq % peer_dev->num_rx_queues;
rq = &peer_ns->rq[rxq];
netdevsim: forward skbs from one connected port to another JIRA: https://issues.redhat.com/browse/RHEL-38987 Upstream commit(s): commit 9eb95228a74163e26d338913a5d61e571ea45307 Author: David Wei <dw@davidwei.uk> Date: Wed Feb 28 15:22:50 2024 -0800 netdevsim: forward skbs from one connected port to another Forward skbs sent from one netdevsim port to its connected netdevsim port using dev_forward_skb, in a spirit similar to veth. Add a tx_dropped variable to struct netdevsim, tracking the number of skbs that could not be forwarded using dev_forward_skb(). The xmit() function accessing the peer ptr is protected by an RCU read critical section. The rcu_read_lock() is functionally redundant as since v5.0 all softirqs are implicitly RCU read critical sections; but it is useful for human readers. If another CPU is concurrently in nsim_destroy(), then it will first set the peer ptr to NULL. This does not affect any existing readers that dereferenced a non-NULL peer. Then, in unregister_netdevice(), there is a synchronize_rcu() before the netdev is actually unregistered and freed. This ensures that any readers i.e. xmit() that got a non-NULL peer will complete before the netdev is freed. Any readers after the RCU_INIT_POINTER() but before synchronize_rcu() will dereference NULL, making it safe. The codepath to nsim_destroy() and nsim_create() takes both the newly added nsim_dev_list_lock and rtnl_lock. This makes it safe with concurrent calls to linking two netdevsims together. Signed-off-by: David Wei <dw@davidwei.uk> Reviewed-by: Maciek Machnikowski <maciek@machnikowski.net> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Petr Oros <poros@redhat.com>
2024-05-28 11:28:32 +00:00
skb_tx_timestamp(skb);
if (unlikely(nsim_forward_skb(peer_dev, skb, rq) == NET_RX_DROP))
netdevsim: forward skbs from one connected port to another JIRA: https://issues.redhat.com/browse/RHEL-38987 Upstream commit(s): commit 9eb95228a74163e26d338913a5d61e571ea45307 Author: David Wei <dw@davidwei.uk> Date: Wed Feb 28 15:22:50 2024 -0800 netdevsim: forward skbs from one connected port to another Forward skbs sent from one netdevsim port to its connected netdevsim port using dev_forward_skb, in a spirit similar to veth. Add a tx_dropped variable to struct netdevsim, tracking the number of skbs that could not be forwarded using dev_forward_skb(). The xmit() function accessing the peer ptr is protected by an RCU read critical section. The rcu_read_lock() is functionally redundant as since v5.0 all softirqs are implicitly RCU read critical sections; but it is useful for human readers. If another CPU is concurrently in nsim_destroy(), then it will first set the peer ptr to NULL. This does not affect any existing readers that dereferenced a non-NULL peer. Then, in unregister_netdevice(), there is a synchronize_rcu() before the netdev is actually unregistered and freed. This ensures that any readers i.e. xmit() that got a non-NULL peer will complete before the netdev is freed. Any readers after the RCU_INIT_POINTER() but before synchronize_rcu() will dereference NULL, making it safe. The codepath to nsim_destroy() and nsim_create() takes both the newly added nsim_dev_list_lock and rtnl_lock. This makes it safe with concurrent calls to linking two netdevsims together. Signed-off-by: David Wei <dw@davidwei.uk> Reviewed-by: Maciek Machnikowski <maciek@machnikowski.net> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Petr Oros <poros@redhat.com>
2024-05-28 11:28:32 +00:00
goto out_drop_cnt;
napi_schedule(&rq->napi);
netdevsim: forward skbs from one connected port to another JIRA: https://issues.redhat.com/browse/RHEL-38987 Upstream commit(s): commit 9eb95228a74163e26d338913a5d61e571ea45307 Author: David Wei <dw@davidwei.uk> Date: Wed Feb 28 15:22:50 2024 -0800 netdevsim: forward skbs from one connected port to another Forward skbs sent from one netdevsim port to its connected netdevsim port using dev_forward_skb, in a spirit similar to veth. Add a tx_dropped variable to struct netdevsim, tracking the number of skbs that could not be forwarded using dev_forward_skb(). The xmit() function accessing the peer ptr is protected by an RCU read critical section. The rcu_read_lock() is functionally redundant as since v5.0 all softirqs are implicitly RCU read critical sections; but it is useful for human readers. If another CPU is concurrently in nsim_destroy(), then it will first set the peer ptr to NULL. This does not affect any existing readers that dereferenced a non-NULL peer. Then, in unregister_netdevice(), there is a synchronize_rcu() before the netdev is actually unregistered and freed. This ensures that any readers i.e. xmit() that got a non-NULL peer will complete before the netdev is freed. Any readers after the RCU_INIT_POINTER() but before synchronize_rcu() will dereference NULL, making it safe. The codepath to nsim_destroy() and nsim_create() takes both the newly added nsim_dev_list_lock and rtnl_lock. This makes it safe with concurrent calls to linking two netdevsims together. Signed-off-by: David Wei <dw@davidwei.uk> Reviewed-by: Maciek Machnikowski <maciek@machnikowski.net> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Petr Oros <poros@redhat.com>
2024-05-28 11:28:32 +00:00
rcu_read_unlock();
u64_stats_update_begin(&ns->syncp);
ns->tx_packets++;
netdevsim: forward skbs from one connected port to another JIRA: https://issues.redhat.com/browse/RHEL-38987 Upstream commit(s): commit 9eb95228a74163e26d338913a5d61e571ea45307 Author: David Wei <dw@davidwei.uk> Date: Wed Feb 28 15:22:50 2024 -0800 netdevsim: forward skbs from one connected port to another Forward skbs sent from one netdevsim port to its connected netdevsim port using dev_forward_skb, in a spirit similar to veth. Add a tx_dropped variable to struct netdevsim, tracking the number of skbs that could not be forwarded using dev_forward_skb(). The xmit() function accessing the peer ptr is protected by an RCU read critical section. The rcu_read_lock() is functionally redundant as since v5.0 all softirqs are implicitly RCU read critical sections; but it is useful for human readers. If another CPU is concurrently in nsim_destroy(), then it will first set the peer ptr to NULL. This does not affect any existing readers that dereferenced a non-NULL peer. Then, in unregister_netdevice(), there is a synchronize_rcu() before the netdev is actually unregistered and freed. This ensures that any readers i.e. xmit() that got a non-NULL peer will complete before the netdev is freed. Any readers after the RCU_INIT_POINTER() but before synchronize_rcu() will dereference NULL, making it safe. The codepath to nsim_destroy() and nsim_create() takes both the newly added nsim_dev_list_lock and rtnl_lock. This makes it safe with concurrent calls to linking two netdevsims together. Signed-off-by: David Wei <dw@davidwei.uk> Reviewed-by: Maciek Machnikowski <maciek@machnikowski.net> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Petr Oros <poros@redhat.com>
2024-05-28 11:28:32 +00:00
ns->tx_bytes += len;
u64_stats_update_end(&ns->syncp);
netdevsim: forward skbs from one connected port to another JIRA: https://issues.redhat.com/browse/RHEL-38987 Upstream commit(s): commit 9eb95228a74163e26d338913a5d61e571ea45307 Author: David Wei <dw@davidwei.uk> Date: Wed Feb 28 15:22:50 2024 -0800 netdevsim: forward skbs from one connected port to another Forward skbs sent from one netdevsim port to its connected netdevsim port using dev_forward_skb, in a spirit similar to veth. Add a tx_dropped variable to struct netdevsim, tracking the number of skbs that could not be forwarded using dev_forward_skb(). The xmit() function accessing the peer ptr is protected by an RCU read critical section. The rcu_read_lock() is functionally redundant as since v5.0 all softirqs are implicitly RCU read critical sections; but it is useful for human readers. If another CPU is concurrently in nsim_destroy(), then it will first set the peer ptr to NULL. This does not affect any existing readers that dereferenced a non-NULL peer. Then, in unregister_netdevice(), there is a synchronize_rcu() before the netdev is actually unregistered and freed. This ensures that any readers i.e. xmit() that got a non-NULL peer will complete before the netdev is freed. Any readers after the RCU_INIT_POINTER() but before synchronize_rcu() will dereference NULL, making it safe. The codepath to nsim_destroy() and nsim_create() takes both the newly added nsim_dev_list_lock and rtnl_lock. This makes it safe with concurrent calls to linking two netdevsims together. Signed-off-by: David Wei <dw@davidwei.uk> Reviewed-by: Maciek Machnikowski <maciek@machnikowski.net> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Petr Oros <poros@redhat.com>
2024-05-28 11:28:32 +00:00
return NETDEV_TX_OK;
netdevsim: forward skbs from one connected port to another JIRA: https://issues.redhat.com/browse/RHEL-38987 Upstream commit(s): commit 9eb95228a74163e26d338913a5d61e571ea45307 Author: David Wei <dw@davidwei.uk> Date: Wed Feb 28 15:22:50 2024 -0800 netdevsim: forward skbs from one connected port to another Forward skbs sent from one netdevsim port to its connected netdevsim port using dev_forward_skb, in a spirit similar to veth. Add a tx_dropped variable to struct netdevsim, tracking the number of skbs that could not be forwarded using dev_forward_skb(). The xmit() function accessing the peer ptr is protected by an RCU read critical section. The rcu_read_lock() is functionally redundant as since v5.0 all softirqs are implicitly RCU read critical sections; but it is useful for human readers. If another CPU is concurrently in nsim_destroy(), then it will first set the peer ptr to NULL. This does not affect any existing readers that dereferenced a non-NULL peer. Then, in unregister_netdevice(), there is a synchronize_rcu() before the netdev is actually unregistered and freed. This ensures that any readers i.e. xmit() that got a non-NULL peer will complete before the netdev is freed. Any readers after the RCU_INIT_POINTER() but before synchronize_rcu() will dereference NULL, making it safe. The codepath to nsim_destroy() and nsim_create() takes both the newly added nsim_dev_list_lock and rtnl_lock. This makes it safe with concurrent calls to linking two netdevsims together. Signed-off-by: David Wei <dw@davidwei.uk> Reviewed-by: Maciek Machnikowski <maciek@machnikowski.net> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Petr Oros <poros@redhat.com>
2024-05-28 11:28:32 +00:00
out_drop_free:
dev_kfree_skb(skb);
netdevsim: forward skbs from one connected port to another JIRA: https://issues.redhat.com/browse/RHEL-38987 Upstream commit(s): commit 9eb95228a74163e26d338913a5d61e571ea45307 Author: David Wei <dw@davidwei.uk> Date: Wed Feb 28 15:22:50 2024 -0800 netdevsim: forward skbs from one connected port to another Forward skbs sent from one netdevsim port to its connected netdevsim port using dev_forward_skb, in a spirit similar to veth. Add a tx_dropped variable to struct netdevsim, tracking the number of skbs that could not be forwarded using dev_forward_skb(). The xmit() function accessing the peer ptr is protected by an RCU read critical section. The rcu_read_lock() is functionally redundant as since v5.0 all softirqs are implicitly RCU read critical sections; but it is useful for human readers. If another CPU is concurrently in nsim_destroy(), then it will first set the peer ptr to NULL. This does not affect any existing readers that dereferenced a non-NULL peer. Then, in unregister_netdevice(), there is a synchronize_rcu() before the netdev is actually unregistered and freed. This ensures that any readers i.e. xmit() that got a non-NULL peer will complete before the netdev is freed. Any readers after the RCU_INIT_POINTER() but before synchronize_rcu() will dereference NULL, making it safe. The codepath to nsim_destroy() and nsim_create() takes both the newly added nsim_dev_list_lock and rtnl_lock. This makes it safe with concurrent calls to linking two netdevsims together. Signed-off-by: David Wei <dw@davidwei.uk> Reviewed-by: Maciek Machnikowski <maciek@machnikowski.net> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Petr Oros <poros@redhat.com>
2024-05-28 11:28:32 +00:00
out_drop_cnt:
rcu_read_unlock();
u64_stats_update_begin(&ns->syncp);
ns->tx_dropped++;
u64_stats_update_end(&ns->syncp);
return NETDEV_TX_OK;
}
static void nsim_set_rx_mode(struct net_device *dev)
{
}
static int nsim_change_mtu(struct net_device *dev, int new_mtu)
{
struct netdevsim *ns = netdev_priv(dev);
if (ns->xdp.prog && new_mtu > NSIM_XDP_MAX_MTU)
return -EBUSY;
WRITE_ONCE(dev->mtu, 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;
netdevsim: forward skbs from one connected port to another JIRA: https://issues.redhat.com/browse/RHEL-38987 Upstream commit(s): commit 9eb95228a74163e26d338913a5d61e571ea45307 Author: David Wei <dw@davidwei.uk> Date: Wed Feb 28 15:22:50 2024 -0800 netdevsim: forward skbs from one connected port to another Forward skbs sent from one netdevsim port to its connected netdevsim port using dev_forward_skb, in a spirit similar to veth. Add a tx_dropped variable to struct netdevsim, tracking the number of skbs that could not be forwarded using dev_forward_skb(). The xmit() function accessing the peer ptr is protected by an RCU read critical section. The rcu_read_lock() is functionally redundant as since v5.0 all softirqs are implicitly RCU read critical sections; but it is useful for human readers. If another CPU is concurrently in nsim_destroy(), then it will first set the peer ptr to NULL. This does not affect any existing readers that dereferenced a non-NULL peer. Then, in unregister_netdevice(), there is a synchronize_rcu() before the netdev is actually unregistered and freed. This ensures that any readers i.e. xmit() that got a non-NULL peer will complete before the netdev is freed. Any readers after the RCU_INIT_POINTER() but before synchronize_rcu() will dereference NULL, making it safe. The codepath to nsim_destroy() and nsim_create() takes both the newly added nsim_dev_list_lock and rtnl_lock. This makes it safe with concurrent calls to linking two netdevsims together. Signed-off-by: David Wei <dw@davidwei.uk> Reviewed-by: Maciek Machnikowski <maciek@machnikowski.net> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Petr Oros <poros@redhat.com>
2024-05-28 11:28:32 +00:00
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)
{
return nsim_bpf_setup_tc_block_cb(type, type_data, cb_priv);
}
static int nsim_set_vf_mac(struct net_device *dev, int vf, u8 *mac)
{
struct netdevsim *ns = netdev_priv(dev);
struct nsim_dev *nsim_dev = ns->nsim_dev;
/* Only refuse multicast addresses, zero address can mean unset/any. */
if (vf >= nsim_dev_get_vfs(nsim_dev) || is_multicast_ether_addr(mac))
return -EINVAL;
memcpy(nsim_dev->vfconfigs[vf].vf_mac, mac, ETH_ALEN);
return 0;
}
static int nsim_set_vf_vlan(struct net_device *dev, int vf,
u16 vlan, u8 qos, __be16 vlan_proto)
{
struct netdevsim *ns = netdev_priv(dev);
struct nsim_dev *nsim_dev = ns->nsim_dev;
if (vf >= nsim_dev_get_vfs(nsim_dev) || vlan > 4095 || qos > 7)
return -EINVAL;
nsim_dev->vfconfigs[vf].vlan = vlan;
nsim_dev->vfconfigs[vf].qos = qos;
nsim_dev->vfconfigs[vf].vlan_proto = vlan_proto;
return 0;
}
static int nsim_set_vf_rate(struct net_device *dev, int vf, int min, int max)
{
struct netdevsim *ns = netdev_priv(dev);
struct nsim_dev *nsim_dev = ns->nsim_dev;
if (nsim_esw_mode_is_switchdev(ns->nsim_dev)) {
pr_err("Not supported in switchdev mode. Please use devlink API.\n");
return -EOPNOTSUPP;
}
if (vf >= nsim_dev_get_vfs(nsim_dev))
return -EINVAL;
nsim_dev->vfconfigs[vf].min_tx_rate = min;
nsim_dev->vfconfigs[vf].max_tx_rate = max;
return 0;
}
static int nsim_set_vf_spoofchk(struct net_device *dev, int vf, bool val)
{
struct netdevsim *ns = netdev_priv(dev);
struct nsim_dev *nsim_dev = ns->nsim_dev;
if (vf >= nsim_dev_get_vfs(nsim_dev))
return -EINVAL;
nsim_dev->vfconfigs[vf].spoofchk_enabled = val;
return 0;
}
static int nsim_set_vf_rss_query_en(struct net_device *dev, int vf, bool val)
{
struct netdevsim *ns = netdev_priv(dev);
struct nsim_dev *nsim_dev = ns->nsim_dev;
if (vf >= nsim_dev_get_vfs(nsim_dev))
return -EINVAL;
nsim_dev->vfconfigs[vf].rss_query_enabled = val;
return 0;
}
static int nsim_set_vf_trust(struct net_device *dev, int vf, bool val)
{
struct netdevsim *ns = netdev_priv(dev);
struct nsim_dev *nsim_dev = ns->nsim_dev;
if (vf >= nsim_dev_get_vfs(nsim_dev))
return -EINVAL;
nsim_dev->vfconfigs[vf].trusted = val;
return 0;
}
static int
nsim_get_vf_config(struct net_device *dev, int vf, struct ifla_vf_info *ivi)
{
struct netdevsim *ns = netdev_priv(dev);
struct nsim_dev *nsim_dev = ns->nsim_dev;
if (vf >= nsim_dev_get_vfs(nsim_dev))
return -EINVAL;
ivi->vf = vf;
ivi->linkstate = nsim_dev->vfconfigs[vf].link_state;
ivi->min_tx_rate = nsim_dev->vfconfigs[vf].min_tx_rate;
ivi->max_tx_rate = nsim_dev->vfconfigs[vf].max_tx_rate;
ivi->vlan = nsim_dev->vfconfigs[vf].vlan;
ivi->vlan_proto = nsim_dev->vfconfigs[vf].vlan_proto;
ivi->qos = nsim_dev->vfconfigs[vf].qos;
memcpy(&ivi->mac, nsim_dev->vfconfigs[vf].vf_mac, ETH_ALEN);
ivi->spoofchk = nsim_dev->vfconfigs[vf].spoofchk_enabled;
ivi->trusted = nsim_dev->vfconfigs[vf].trusted;
ivi->rss_query_en = nsim_dev->vfconfigs[vf].rss_query_enabled;
return 0;
}
static int nsim_set_vf_link_state(struct net_device *dev, int vf, int state)
{
struct netdevsim *ns = netdev_priv(dev);
struct nsim_dev *nsim_dev = ns->nsim_dev;
if (vf >= nsim_dev_get_vfs(nsim_dev))
return -EINVAL;
switch (state) {
case IFLA_VF_LINK_STATE_AUTO:
case IFLA_VF_LINK_STATE_ENABLE:
case IFLA_VF_LINK_STATE_DISABLE:
break;
default:
return -EINVAL;
}
nsim_dev->vfconfigs[vf].link_state = state;
return 0;
}
static void nsim_taprio_stats(struct tc_taprio_qopt_stats *stats)
{
stats->window_drops = 0;
stats->tx_overruns = 0;
}
static int nsim_setup_tc_taprio(struct net_device *dev,
struct tc_taprio_qopt_offload *offload)
{
int err = 0;
switch (offload->cmd) {
case TAPRIO_CMD_REPLACE:
case TAPRIO_CMD_DESTROY:
break;
case TAPRIO_CMD_STATS:
nsim_taprio_stats(&offload->stats);
break;
default:
err = -EOPNOTSUPP;
}
return err;
}
static LIST_HEAD(nsim_block_cb_list);
static int
nsim_setup_tc(struct net_device *dev, enum tc_setup_type type, void *type_data)
{
struct netdevsim *ns = netdev_priv(dev);
switch (type) {
case TC_SETUP_QDISC_TAPRIO:
return nsim_setup_tc_taprio(dev, type_data);
case TC_SETUP_BLOCK:
return flow_block_cb_setup_simple(type_data,
&nsim_block_cb_list,
nsim_setup_tc_block_cb,
ns, ns, true);
default:
return -EOPNOTSUPP;
}
}
static int
nsim_set_features(struct net_device *dev, netdev_features_t features)
{
struct netdevsim *ns = netdev_priv(dev);
if ((dev->features & NETIF_F_HW_TC) > (features & NETIF_F_HW_TC))
return nsim_bpf_disable_tc(ns);
return 0;
}
static int nsim_get_iflink(const struct net_device *dev)
{
struct netdevsim *nsim, *peer;
int iflink;
nsim = netdev_priv(dev);
rcu_read_lock();
peer = rcu_dereference(nsim->peer);
iflink = peer ? READ_ONCE(peer->netdev->ifindex) :
READ_ONCE(dev->ifindex);
rcu_read_unlock();
return iflink;
}
static int nsim_rcv(struct nsim_rq *rq, int budget)
{
struct sk_buff *skb;
int i;
for (i = 0; i < budget; i++) {
if (skb_queue_empty(&rq->skb_queue))
break;
skb = skb_dequeue(&rq->skb_queue);
netif_receive_skb(skb);
}
return i;
}
static int nsim_poll(struct napi_struct *napi, int budget)
{
struct nsim_rq *rq = container_of(napi, struct nsim_rq, napi);
int done;
done = nsim_rcv(rq, budget);
napi_complete(napi);
return done;
}
static int nsim_create_page_pool(struct nsim_rq *rq)
{
struct page_pool_params p = {
.order = 0,
.pool_size = NSIM_RING_SIZE,
.nid = NUMA_NO_NODE,
.dev = &rq->napi.dev->dev,
.napi = &rq->napi,
.dma_dir = DMA_BIDIRECTIONAL,
.netdev = rq->napi.dev,
};
rq->page_pool = page_pool_create(&p);
if (IS_ERR(rq->page_pool)) {
int err = PTR_ERR(rq->page_pool);
rq->page_pool = NULL;
return err;
}
return 0;
}
static int nsim_init_napi(struct netdevsim *ns)
{
struct net_device *dev = ns->netdev;
struct nsim_rq *rq;
int err, i;
for (i = 0; i < dev->num_rx_queues; i++) {
rq = &ns->rq[i];
netif_napi_add(dev, &rq->napi, nsim_poll);
}
for (i = 0; i < dev->num_rx_queues; i++) {
rq = &ns->rq[i];
err = nsim_create_page_pool(rq);
if (err)
goto err_pp_destroy;
}
return 0;
err_pp_destroy:
while (i--) {
page_pool_destroy(ns->rq[i].page_pool);
ns->rq[i].page_pool = NULL;
}
for (i = 0; i < dev->num_rx_queues; i++)
__netif_napi_del(&ns->rq[i].napi);
return err;
}
static void nsim_enable_napi(struct netdevsim *ns)
{
struct net_device *dev = ns->netdev;
int i;
for (i = 0; i < dev->num_rx_queues; i++) {
struct nsim_rq *rq = &ns->rq[i];
netif_queue_set_napi(dev, i, NETDEV_QUEUE_TYPE_RX, &rq->napi);
napi_enable(&rq->napi);
}
}
static int nsim_open(struct net_device *dev)
{
struct netdevsim *ns = netdev_priv(dev);
int err;
err = nsim_init_napi(ns);
if (err)
return err;
nsim_enable_napi(ns);
return 0;
}
static void nsim_del_napi(struct netdevsim *ns)
{
struct net_device *dev = ns->netdev;
int i;
for (i = 0; i < dev->num_rx_queues; i++) {
struct nsim_rq *rq = &ns->rq[i];
napi_disable(&rq->napi);
__netif_napi_del(&rq->napi);
}
synchronize_net();
for (i = 0; i < dev->num_rx_queues; i++) {
page_pool_destroy(ns->rq[i].page_pool);
ns->rq[i].page_pool = NULL;
}
}
static int nsim_stop(struct net_device *dev)
{
struct netdevsim *ns = netdev_priv(dev);
struct netdevsim *peer;
netif_carrier_off(dev);
peer = rtnl_dereference(ns->peer);
if (peer)
netif_carrier_off(peer->netdev);
nsim_del_napi(ns);
return 0;
}
static const struct net_device_ops nsim_netdev_ops = {
.ndo_start_xmit = nsim_start_xmit,
.ndo_set_rx_mode = nsim_set_rx_mode,
.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,
.ndo_set_vf_spoofchk = nsim_set_vf_spoofchk,
.ndo_set_vf_trust = nsim_set_vf_trust,
.ndo_get_vf_config = nsim_get_vf_config,
.ndo_set_vf_link_state = nsim_set_vf_link_state,
.ndo_set_vf_rss_query_en = nsim_set_vf_rss_query_en,
.ndo_setup_tc = nsim_setup_tc,
.ndo_set_features = nsim_set_features,
.ndo_get_iflink = nsim_get_iflink,
.ndo_bpf = nsim_bpf,
.ndo_open = nsim_open,
.ndo_stop = nsim_stop,
};
static const struct net_device_ops nsim_vf_netdev_ops = {
.ndo_start_xmit = nsim_start_xmit,
.ndo_set_rx_mode = nsim_set_rx_mode,
.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,
};
/* We don't have true per-queue stats, yet, so do some random fakery here.
* Only report stuff for queue 0.
*/
static void nsim_get_queue_stats_rx(struct net_device *dev, int idx,
struct netdev_queue_stats_rx *stats)
{
struct rtnl_link_stats64 rtstats = {};
if (!idx)
nsim_get_stats64(dev, &rtstats);
stats->packets = rtstats.rx_packets - !!rtstats.rx_packets;
stats->bytes = rtstats.rx_bytes;
}
static void nsim_get_queue_stats_tx(struct net_device *dev, int idx,
struct netdev_queue_stats_tx *stats)
{
struct rtnl_link_stats64 rtstats = {};
if (!idx)
nsim_get_stats64(dev, &rtstats);
stats->packets = rtstats.tx_packets - !!rtstats.tx_packets;
stats->bytes = rtstats.tx_bytes;
}
static void nsim_get_base_stats(struct net_device *dev,
struct netdev_queue_stats_rx *rx,
struct netdev_queue_stats_tx *tx)
{
struct rtnl_link_stats64 rtstats = {};
nsim_get_stats64(dev, &rtstats);
rx->packets = !!rtstats.rx_packets;
rx->bytes = 0;
tx->packets = !!rtstats.tx_packets;
tx->bytes = 0;
}
static const struct netdev_stat_ops nsim_stat_ops = {
.get_queue_stats_tx = nsim_get_queue_stats_tx,
.get_queue_stats_rx = nsim_get_queue_stats_rx,
.get_base_stats = nsim_get_base_stats,
};
static ssize_t
nsim_pp_hold_read(struct file *file, char __user *data,
size_t count, loff_t *ppos)
{
struct netdevsim *ns = file->private_data;
char buf[3] = "n\n";
if (ns->page)
buf[0] = 'y';
return simple_read_from_buffer(data, count, ppos, buf, 2);
}
static ssize_t
nsim_pp_hold_write(struct file *file, const char __user *data,
size_t count, loff_t *ppos)
{
struct netdevsim *ns = file->private_data;
ssize_t ret;
bool val;
ret = kstrtobool_from_user(data, count, &val);
if (ret)
return ret;
rtnl_lock();
ret = count;
if (val == !!ns->page)
goto exit;
if (!netif_running(ns->netdev) && val) {
ret = -ENETDOWN;
} else if (val) {
ns->page = page_pool_dev_alloc_pages(ns->rq[0].page_pool);
if (!ns->page)
ret = -ENOMEM;
} else {
page_pool_put_full_page(ns->page->pp, ns->page, false);
ns->page = NULL;
}
rtnl_unlock();
exit:
return count;
}
static const struct file_operations nsim_pp_hold_fops = {
.open = simple_open,
.read = nsim_pp_hold_read,
.write = nsim_pp_hold_write,
.llseek = generic_file_llseek,
.owner = THIS_MODULE,
};
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->features |= NETIF_F_HIGHDMA |
NETIF_F_SG |
NETIF_F_FRAGLIST |
NETIF_F_HW_CSUM |
NETIF_F_TSO;
dev->hw_features |= NETIF_F_HW_TC;
dev->max_mtu = ETH_MAX_MTU;
drivers: net: turn on XDP features Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2178930 Conflicts: - drivers/net/ethernet/engleder/tsnep_main.c: We don't have this driver - drivers/net/ethernet/fungible/funeth/funeth_main.c: We don't have this driver - drivers/net/ethernet/aquantia/atlantic/aq_nic.c: left out because it does not have XDP support - drivers/net/ethernet/mediatek/mtk_eth_soc.c: left out because mtk_eth_soc does not have XDP support - drivers/net/ethernet/freescale/dpaa/dpaa_eth.c: left out because driver is not enabled - drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c: left out because driver is not enabled - drivers/net/ethernet/freescale/enetc/enetc_pf.c: left out because driver is not enabled - drivers/net/ethernet/marvell/mvneta.c: left out because driver is not enabled - drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c: left out because driver is not enabled - drivers/net/ethernet/socionext/netsec.c: left out because driver is not enabled - drivers/net/ethernet/ti/cpsw.c: left out because driver is not enabled - drivers/net/ethernet/ti/cpsw_new.c: left out because driver is not enabled - drivers/net/ethernet/netronome/nfp/nfp_net_common.c: Context difference due to missing 67d2656b48f1 ("nfp: support RX VLAN ctag/stag strip") and 7de8b691615f ("nfp: enable TSO by default for nfp netdev") - drivers/net/ethernet/intel/ice/ice_main.c: Merge conflict upstream between 5b246e533d01 ("ice: split probe into smaller functions") and this commit. Resolved the same way as upstream in de4287336794 (pull-request: bpf-next 2023-02-11): only add the XDP features to the existing ice_cfg_netdev() function. - drivers/net/ethernet/intel/i40e/i40e_main.c: Code difference because the driver does not have support for frags/multi-buff. The last parameter of xdp_features_set_redirect_target indicates if frags are supported for Tx, we change the code to set it to false. Omitted-fix: 1dc55923296d ("net: mvneta: do not set xdp_features for hw buffer devices") mvneta is not enabled and hunks in this commit are skipped Omitted-fix: 481e96fc1307 ("mvpp2: take care of xdp_features when reconfiguring queues") mvpp2 is not enabled and hunks in this commit are skipped Omitted-fix: e4ac7cc6e5a4 ("net: fec: turn on XDP features") fec does not have XDP support commit 66c0e13ad236c74ea88c7c1518f3cef7f372e3da Author: Marek Majtyka <alardam@gmail.com> Date: Wed Feb 1 11:24:18 2023 +0100 drivers: net: turn on XDP features A summary of the flags being set for various drivers is given below. Note that XDP_F_REDIRECT_TARGET and XDP_F_FRAG_TARGET are features that can be turned off and on at runtime. This means that these flags may be set and unset under RTNL lock protection by the driver. Hence, READ_ONCE must be used by code loading the flag value. Also, these flags are not used for synchronization against the availability of XDP resources on a device. It is merely a hint, and hence the read may race with the actual teardown of XDP resources on the device. This may change in the future, e.g. operations taking a reference on the XDP resources of the driver, and in turn inhibiting turning off this flag. However, for now, it can only be used as a hint to check whether device supports becoming a redirection target. Turn 'hw-offload' feature flag on for: - netronome (nfp) - netdevsim. Turn 'native' and 'zerocopy' features flags on for: - intel (i40e, ice, ixgbe, igc) - mellanox (mlx5). - stmmac - netronome (nfp) Turn 'native' features flags on for: - amazon (ena) - broadcom (bnxt) - freescale (dpaa, dpaa2, enetc) - funeth - intel (igb) - marvell (mvneta, mvpp2, octeontx2) - mellanox (mlx4) - mtk_eth_soc - qlogic (qede) - sfc - socionext (netsec) - ti (cpsw) - tap - tsnep - veth - xen - virtio_net. Turn 'basic' (tx, pass, aborted and drop) features flags on for: - netronome (nfp) - cavium (thunder) - hyperv. Turn 'redirect_target' feature flag on for: - amanzon (ena) - broadcom (bnxt) - freescale (dpaa, dpaa2) - intel (i40e, ice, igb, ixgbe) - ti (cpsw) - marvell (mvneta, mvpp2) - sfc - socionext (netsec) - qlogic (qede) - mellanox (mlx5) - tap - veth - virtio_net - xen Reviewed-by: Gerhard Engleder <gerhard@engleder-embedded.com> Reviewed-by: Simon Horman <simon.horman@corigine.com> Acked-by: Stanislav Fomichev <sdf@google.com> Acked-by: Jakub Kicinski <kuba@kernel.org> Co-developed-by: Kumar Kartikeya Dwivedi <memxor@gmail.com> Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com> Co-developed-by: Lorenzo Bianconi <lorenzo@kernel.org> Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org> Signed-off-by: Marek Majtyka <alardam@gmail.com> Link: https://lore.kernel.org/r/3eca9fafb308462f7edb1f58e451d59209aa07eb.1675245258.git.lorenzo@kernel.org Signed-off-by: Alexei Starovoitov <ast@kernel.org> Signed-off-by: Felix Maurer <fmaurer@redhat.com>
2023-05-10 09:50:53 +00:00
dev->xdp_features = NETDEV_XDP_ACT_HW_OFFLOAD;
}
static int nsim_queue_init(struct netdevsim *ns)
{
struct net_device *dev = ns->netdev;
int i;
ns->rq = kvcalloc(dev->num_rx_queues, sizeof(*ns->rq),
GFP_KERNEL_ACCOUNT | __GFP_RETRY_MAYFAIL);
if (!ns->rq)
return -ENOMEM;
for (i = 0; i < dev->num_rx_queues; i++)
skb_queue_head_init(&ns->rq[i].skb_queue);
return 0;
}
static void nsim_queue_free(struct netdevsim *ns)
{
struct net_device *dev = ns->netdev;
int i;
for (i = 0; i < dev->num_rx_queues; i++)
skb_queue_purge_reason(&ns->rq[i].skb_queue,
SKB_DROP_REASON_QUEUE_PURGE);
kvfree(ns->rq);
ns->rq = NULL;
}
static int nsim_init_netdevsim(struct netdevsim *ns)
{
struct mock_phc *phc;
int err;
phc = mock_phc_create(&ns->nsim_bus_dev->dev);
if (IS_ERR(phc))
return PTR_ERR(phc);
ns->phc = phc;
ns->netdev->netdev_ops = &nsim_netdev_ops;
ns->netdev->stat_ops = &nsim_stat_ops;
err = nsim_udp_tunnels_info_create(ns->nsim_dev, ns->netdev);
if (err)
goto err_phc_destroy;
rtnl_lock();
err = nsim_queue_init(ns);
if (err)
goto err_utn_destroy;
err = nsim_bpf_init(ns);
if (err)
goto err_rq_destroy;
nsim_macsec_init(ns);
nsim_ipsec_init(ns);
err = register_netdevice(ns->netdev);
if (err)
goto err_ipsec_teardown;
rtnl_unlock();
return 0;
err_ipsec_teardown:
nsim_ipsec_teardown(ns);
nsim_macsec_teardown(ns);
nsim_bpf_uninit(ns);
err_rq_destroy:
nsim_queue_free(ns);
err_utn_destroy:
rtnl_unlock();
nsim_udp_tunnels_info_destroy(ns->netdev);
err_phc_destroy:
mock_phc_destroy(ns->phc);
return err;
}
static int nsim_init_netdevsim_vf(struct netdevsim *ns)
{
int err;
ns->netdev->netdev_ops = &nsim_vf_netdev_ops;
rtnl_lock();
err = register_netdevice(ns->netdev);
rtnl_unlock();
return err;
}
static void nsim_exit_netdevsim(struct netdevsim *ns)
{
nsim_udp_tunnels_info_destroy(ns->netdev);
mock_phc_destroy(ns->phc);
}
struct netdevsim *
nsim_create(struct nsim_dev *nsim_dev, struct nsim_dev_port *nsim_dev_port)
{
struct net_device *dev;
struct netdevsim *ns;
int err;
dev = alloc_netdev_mq(sizeof(*ns), "eth%d", NET_NAME_UNKNOWN, nsim_setup,
nsim_dev->nsim_bus_dev->num_queues);
if (!dev)
return ERR_PTR(-ENOMEM);
dev_net_set(dev, nsim_dev_net(nsim_dev));
ns = netdev_priv(dev);
ns->netdev = dev;
netdevsim: init u64 stats for 32bit hardware Init the u64 stats in order to avoid the lockdep prints on the 32bit hardware like INFO: trying to register non-static key. the code is fine but needs lockdep annotation. turning off the locking correctness validator. CPU: 0 PID: 4695 Comm: syz-executor.0 Not tainted 5.11.0-rc5-syzkaller #0 Hardware name: ARM-Versatile Express Backtrace: [<826fc5b8>] (dump_backtrace) from [<826fc82c>] (show_stack+0x18/0x1c arch/arm/kernel/traps.c:252) [<826fc814>] (show_stack) from [<8270d1f8>] (__dump_stack lib/dump_stack.c:79 [inline]) [<826fc814>] (show_stack) from [<8270d1f8>] (dump_stack+0xa8/0xc8 lib/dump_stack.c:120) [<8270d150>] (dump_stack) from [<802bf9c0>] (assign_lock_key kernel/locking/lockdep.c:935 [inline]) [<8270d150>] (dump_stack) from [<802bf9c0>] (register_lock_class+0xabc/0xb68 kernel/locking/lockdep.c:1247) [<802bef04>] (register_lock_class) from [<802baa2c>] (__lock_acquire+0x84/0x32d4 kernel/locking/lockdep.c:4711) [<802ba9a8>] (__lock_acquire) from [<802be840>] (lock_acquire.part.0+0xf0/0x554 kernel/locking/lockdep.c:5442) [<802be750>] (lock_acquire.part.0) from [<802bed10>] (lock_acquire+0x6c/0x74 kernel/locking/lockdep.c:5415) [<802beca4>] (lock_acquire) from [<81560548>] (seqcount_lockdep_reader_access include/linux/seqlock.h:103 [inline]) [<802beca4>] (lock_acquire) from [<81560548>] (__u64_stats_fetch_begin include/linux/u64_stats_sync.h:164 [inline]) [<802beca4>] (lock_acquire) from [<81560548>] (u64_stats_fetch_begin include/linux/u64_stats_sync.h:175 [inline]) [<802beca4>] (lock_acquire) from [<81560548>] (nsim_get_stats64+0xdc/0xf0 drivers/net/netdevsim/netdev.c:70) [<8156046c>] (nsim_get_stats64) from [<81e2efa0>] (dev_get_stats+0x44/0xd0 net/core/dev.c:10405) [<81e2ef5c>] (dev_get_stats) from [<81e53204>] (rtnl_fill_stats+0x38/0x120 net/core/rtnetlink.c:1211) [<81e531cc>] (rtnl_fill_stats) from [<81e59d58>] (rtnl_fill_ifinfo+0x6d4/0x148c net/core/rtnetlink.c:1783) [<81e59684>] (rtnl_fill_ifinfo) from [<81e5ceb4>] (rtmsg_ifinfo_build_skb+0x9c/0x108 net/core/rtnetlink.c:3798) [<81e5ce18>] (rtmsg_ifinfo_build_skb) from [<81e5d0ac>] (rtmsg_ifinfo_event net/core/rtnetlink.c:3830 [inline]) [<81e5ce18>] (rtmsg_ifinfo_build_skb) from [<81e5d0ac>] (rtmsg_ifinfo_event net/core/rtnetlink.c:3821 [inline]) [<81e5ce18>] (rtmsg_ifinfo_build_skb) from [<81e5d0ac>] (rtmsg_ifinfo+0x44/0x70 net/core/rtnetlink.c:3839) [<81e5d068>] (rtmsg_ifinfo) from [<81e45c2c>] (register_netdevice+0x664/0x68c net/core/dev.c:10103) [<81e455c8>] (register_netdevice) from [<815608bc>] (nsim_create+0xf8/0x124 drivers/net/netdevsim/netdev.c:317) [<815607c4>] (nsim_create) from [<81561184>] (__nsim_dev_port_add+0x108/0x188 drivers/net/netdevsim/dev.c:941) [<8156107c>] (__nsim_dev_port_add) from [<815620d8>] (nsim_dev_port_add_all drivers/net/netdevsim/dev.c:990 [inline]) [<8156107c>] (__nsim_dev_port_add) from [<815620d8>] (nsim_dev_probe+0x5cc/0x750 drivers/net/netdevsim/dev.c:1119) [<81561b0c>] (nsim_dev_probe) from [<815661dc>] (nsim_bus_probe+0x10/0x14 drivers/net/netdevsim/bus.c:287) [<815661cc>] (nsim_bus_probe) from [<811724c0>] (really_probe+0x100/0x50c drivers/base/dd.c:554) [<811723c0>] (really_probe) from [<811729c4>] (driver_probe_device+0xf8/0x1c8 drivers/base/dd.c:740) [<811728cc>] (driver_probe_device) from [<81172fe4>] (__device_attach_driver+0x8c/0xf0 drivers/base/dd.c:846) [<81172f58>] (__device_attach_driver) from [<8116fee0>] (bus_for_each_drv+0x88/0xd8 drivers/base/bus.c:431) [<8116fe58>] (bus_for_each_drv) from [<81172c6c>] (__device_attach+0xdc/0x1d0 drivers/base/dd.c:914) [<81172b90>] (__device_attach) from [<8117305c>] (device_initial_probe+0x14/0x18 drivers/base/dd.c:961) [<81173048>] (device_initial_probe) from [<81171358>] (bus_probe_device+0x90/0x98 drivers/base/bus.c:491) [<811712c8>] (bus_probe_device) from [<8116e77c>] (device_add+0x320/0x824 drivers/base/core.c:3109) [<8116e45c>] (device_add) from [<8116ec9c>] (device_register+0x1c/0x20 drivers/base/core.c:3182) [<8116ec80>] (device_register) from [<81566710>] (nsim_bus_dev_new drivers/net/netdevsim/bus.c:336 [inline]) [<8116ec80>] (device_register) from [<81566710>] (new_device_store+0x178/0x208 drivers/net/netdevsim/bus.c:215) [<81566598>] (new_device_store) from [<8116fcb4>] (bus_attr_store+0x2c/0x38 drivers/base/bus.c:122) [<8116fc88>] (bus_attr_store) from [<805b4b8c>] (sysfs_kf_write+0x48/0x54 fs/sysfs/file.c:139) [<805b4b44>] (sysfs_kf_write) from [<805b3c90>] (kernfs_fop_write_iter+0x128/0x1ec fs/kernfs/file.c:296) [<805b3b68>] (kernfs_fop_write_iter) from [<804d22fc>] (call_write_iter include/linux/fs.h:1901 [inline]) [<805b3b68>] (kernfs_fop_write_iter) from [<804d22fc>] (new_sync_write fs/read_write.c:518 [inline]) [<805b3b68>] (kernfs_fop_write_iter) from [<804d22fc>] (vfs_write+0x3dc/0x57c fs/read_write.c:605) [<804d1f20>] (vfs_write) from [<804d2604>] (ksys_write+0x68/0xec fs/read_write.c:658) [<804d259c>] (ksys_write) from [<804d2698>] (__do_sys_write fs/read_write.c:670 [inline]) [<804d259c>] (ksys_write) from [<804d2698>] (sys_write+0x10/0x14 fs/read_write.c:667) [<804d2688>] (sys_write) from [<80200060>] (ret_fast_syscall+0x0/0x2c arch/arm/mm/proc-v7.S:64) Fixes: 83c9e13aa39a ("netdevsim: add software driver for testing offloads") Reported-by: syzbot+e74a6857f2d0efe3ad81@syzkaller.appspotmail.com Tested-by: Dmitry Vyukov <dvyukov@google.com> Signed-off-by: Hillf Danton <hdanton@sina.com> Signed-off-by: Jakub Kicinski <kuba@kernel.org> Signed-off-by: David S. Miller <davem@davemloft.net>
2021-03-04 18:30:09 +00:00
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;
SET_NETDEV_DEV(dev, &ns->nsim_bus_dev->dev);
net: make drivers to use SET_NETDEV_DEVLINK_PORT to set devlink_port Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2172273 Conflicts: - drivers/net/ethernet/mellanox/mlxsw/core.c: adjusted context conflicts due to missing 3471ac9b22c18a ("mlxsw: Remove unused IB stuff") - drivers/net/ethernet/mellanox/mlxsw/spectrum.c: adjusted context conflicts due to missing a159e986ad26d3 ("mlxsw: spectrum: Clear PTP configuration after unregistering the netdevice") - drivers/net/ethernet/marvell/prestera/prestera_main.c: adjusted context conflict due to missing 52323ef75414d6 ("net: marvell: prestera: add phylink support") - drivers/net/ethernet/mscc/ocelot_vsc7514.c: adjusted context conflict due to missing e6e12df625f23e net: mscc: ocelot: convert to phylink - drivers/net/ethernet/ti/am65-cpsw-nuss.c: skipped chunk due to missing 0680e20af5fbf4 ("net: ethernet: ti: am65-cpsw: Fix devlink port register sequence") - drivers/net/ethernet/fungible/funeth/funeth_main.c: unmerged path because file missing in RHEL Upstream commit(s): commit ac73d4bf2cdaf2cb8a43df8ee4a5c066d2c5d7b4 Author: Jiri Pirko <jiri@nvidia.com> Date: Wed Nov 2 17:02:04 2022 +0100 net: make drivers to use SET_NETDEV_DEVLINK_PORT to set devlink_port Benefit from the previously implemented tracking of netdev events in devlink code and instead of calling devlink_port_type_eth_set() and devlink_port_type_clear() to set devlink port type and link to related netdev, use SET_NETDEV_DEVLINK_PORT() macro to assign devlink_port pointer to netdevice which is about to be registered. Signed-off-by: Jiri Pirko <jiri@nvidia.com> Signed-off-by: Jakub Kicinski <kuba@kernel.org> Signed-off-by: Petr Oros <poros@redhat.com>
2023-03-28 09:19:41 +00:00
SET_NETDEV_DEVLINK_PORT(dev, &nsim_dev_port->devlink_port);
nsim_ethtool_init(ns);
if (nsim_dev_port_is_pf(nsim_dev_port))
err = nsim_init_netdevsim(ns);
else
err = nsim_init_netdevsim_vf(ns);
if (err)
goto err_free_netdev;
ns->pp_dfs = debugfs_create_file("pp_hold", 0600, nsim_dev_port->ddir,
ns, &nsim_pp_hold_fops);
return ns;
err_free_netdev:
free_netdev(dev);
return ERR_PTR(err);
}
void nsim_destroy(struct netdevsim *ns)
{
struct net_device *dev = ns->netdev;
struct netdevsim *peer;
debugfs_remove(ns->pp_dfs);
rtnl_lock();
peer = rtnl_dereference(ns->peer);
if (peer)
RCU_INIT_POINTER(peer->peer, NULL);
RCU_INIT_POINTER(ns->peer, NULL);
unregister_netdevice(dev);
if (nsim_dev_port_is_pf(ns->nsim_dev_port)) {
nsim_macsec_teardown(ns);
nsim_ipsec_teardown(ns);
nsim_bpf_uninit(ns);
nsim_queue_free(ns);
}
rtnl_unlock();
if (nsim_dev_port_is_pf(ns->nsim_dev_port))
nsim_exit_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);
ns->page = NULL;
}
free_netdev(dev);
}
bool netdev_is_nsim(struct net_device *dev)
{
return dev->netdev_ops == &nsim_netdev_ops;
}
static int nsim_validate(struct nlattr *tb[], struct nlattr *data[],
struct netlink_ext_ack *extack)
{
NL_SET_ERR_MSG_MOD(extack,
"Please use: echo \"[ID] [PORT_COUNT] [NUM_QUEUES]\" > /sys/bus/netdevsim/new_device");
return -EOPNOTSUPP;
}
static struct rtnl_link_ops nsim_link_ops __read_mostly = {
.kind = DRV_NAME,
.validate = nsim_validate,
};
static int __init nsim_module_init(void)
{
int err;
err = nsim_dev_init();
if (err)
return err;
err = nsim_bus_init();
if (err)
goto err_dev_exit;
err = rtnl_link_register(&nsim_link_ops);
if (err)
goto err_bus_exit;
return 0;
err_bus_exit:
nsim_bus_exit();
err_dev_exit:
nsim_dev_exit();
return err;
}
static void __exit nsim_module_exit(void)
{
rtnl_link_unregister(&nsim_link_ops);
nsim_bus_exit();
nsim_dev_exit();
}
module_init(nsim_module_init);
module_exit(nsim_module_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Simulated networking device for testing");
MODULE_ALIAS_RTNL_LINK(DRV_NAME);