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 1679579220SJakub Kicinski #include <linux/device.h> 1783c9e13aSJakub Kicinski #include <linux/kernel.h> 1831d3ad83SJakub Kicinski #include <linux/list.h> 1983c9e13aSJakub Kicinski #include <linux/netdevice.h> 2083c9e13aSJakub Kicinski #include <linux/u64_stats_sync.h> 218320d145SJiri Pirko #include <net/devlink.h> 2205296620SJakub Kicinski #include <net/xdp.h> 2383c9e13aSJakub Kicinski 2483c9e13aSJakub Kicinski #define DRV_NAME "netdevsim" 2583c9e13aSJakub Kicinski 2631d3ad83SJakub Kicinski #define NSIM_XDP_MAX_MTU 4000 2731d3ad83SJakub Kicinski 2831d3ad83SJakub Kicinski #define NSIM_EA(extack, msg) NL_SET_ERR_MSG_MOD((extack), msg) 2931d3ad83SJakub Kicinski 307699353dSShannon Nelson #define NSIM_IPSEC_MAX_SA_COUNT 33 317699353dSShannon Nelson #define NSIM_IPSEC_VALID BIT(31) 327699353dSShannon Nelson 337699353dSShannon Nelson struct nsim_sa { 347699353dSShannon Nelson struct xfrm_state *xs; 357699353dSShannon Nelson __be32 ipaddr[4]; 367699353dSShannon Nelson u32 key[4]; 377699353dSShannon Nelson u32 salt; 387699353dSShannon Nelson bool used; 397699353dSShannon Nelson bool crypt; 407699353dSShannon Nelson bool rx; 417699353dSShannon Nelson }; 427699353dSShannon Nelson 437699353dSShannon Nelson struct nsim_ipsec { 447699353dSShannon Nelson struct nsim_sa sa[NSIM_IPSEC_MAX_SA_COUNT]; 457699353dSShannon Nelson struct dentry *pfile; 467699353dSShannon Nelson u32 count; 477699353dSShannon Nelson u32 tx; 487699353dSShannon Nelson u32 ok; 497699353dSShannon Nelson }; 507699353dSShannon Nelson 5183c9e13aSJakub Kicinski struct netdevsim { 5231d3ad83SJakub Kicinski struct net_device *netdev; 53a60f9e48SJiri Pirko struct nsim_dev *nsim_dev; 54e05b2d14SJiri Pirko struct nsim_dev_port *nsim_dev_port; 5531d3ad83SJakub Kicinski 5683c9e13aSJakub Kicinski u64 tx_packets; 5783c9e13aSJakub Kicinski u64 tx_bytes; 5883c9e13aSJakub Kicinski struct u64_stats_sync syncp; 5931d3ad83SJakub Kicinski 6040e4fe4cSJiri Pirko struct nsim_bus_dev *nsim_bus_dev; 6179579220SJakub Kicinski 6231d3ad83SJakub Kicinski struct bpf_prog *bpf_offloaded; 6331d3ad83SJakub Kicinski u32 bpf_offloaded_id; 6431d3ad83SJakub Kicinski 6505296620SJakub Kicinski struct xdp_attachment_info xdp; 66799e173dSJakub Kicinski struct xdp_attachment_info xdp_hw; 6731d3ad83SJakub Kicinski 6831d3ad83SJakub Kicinski bool bpf_tc_accept; 6931d3ad83SJakub Kicinski bool bpf_tc_non_bound_accept; 7031d3ad83SJakub Kicinski bool bpf_xdpdrv_accept; 7131d3ad83SJakub Kicinski bool bpf_xdpoffload_accept; 72395cacb5SJakub Kicinski 73395cacb5SJakub Kicinski bool bpf_map_accept; 747699353dSShannon Nelson struct nsim_ipsec ipsec; 7583c9e13aSJakub Kicinski }; 7631d3ad83SJakub Kicinski 77e05b2d14SJiri Pirko struct netdevsim * 78e05b2d14SJiri Pirko nsim_create(struct nsim_dev *nsim_dev, struct nsim_dev_port *nsim_dev_port); 79e05b2d14SJiri Pirko void nsim_destroy(struct netdevsim *ns); 80e05b2d14SJiri Pirko 817c5db7e7SJakub Kicinski #ifdef CONFIG_BPF_SYSCALL 82d514f41eSJiri Pirko int nsim_bpf_dev_init(struct nsim_dev *nsim_dev); 83d514f41eSJiri Pirko void nsim_bpf_dev_exit(struct nsim_dev *nsim_dev); 8431d3ad83SJakub Kicinski int nsim_bpf_init(struct netdevsim *ns); 8531d3ad83SJakub Kicinski void nsim_bpf_uninit(struct netdevsim *ns); 8631d3ad83SJakub Kicinski int nsim_bpf(struct net_device *dev, struct netdev_bpf *bpf); 8731d3ad83SJakub Kicinski int nsim_bpf_disable_tc(struct netdevsim *ns); 8831d3ad83SJakub Kicinski int nsim_bpf_setup_tc_block_cb(enum tc_setup_type type, 8931d3ad83SJakub Kicinski void *type_data, void *cb_priv); 907c5db7e7SJakub Kicinski #else 91d514f41eSJiri Pirko 92d514f41eSJiri Pirko static inline int nsim_bpf_dev_init(struct nsim_dev *nsim_dev) 93d514f41eSJiri Pirko { 94d514f41eSJiri Pirko return 0; 95d514f41eSJiri Pirko } 96d514f41eSJiri Pirko 97d514f41eSJiri Pirko static inline void nsim_bpf_dev_exit(struct nsim_dev *nsim_dev) 98d514f41eSJiri Pirko { 99d514f41eSJiri Pirko } 1007c5db7e7SJakub Kicinski static inline int nsim_bpf_init(struct netdevsim *ns) 1017c5db7e7SJakub Kicinski { 1027c5db7e7SJakub Kicinski return 0; 1037c5db7e7SJakub Kicinski } 1047c5db7e7SJakub Kicinski 1057c5db7e7SJakub Kicinski static inline void nsim_bpf_uninit(struct netdevsim *ns) 1067c5db7e7SJakub Kicinski { 1077c5db7e7SJakub Kicinski } 1087c5db7e7SJakub Kicinski 1097c5db7e7SJakub Kicinski static inline int nsim_bpf(struct net_device *dev, struct netdev_bpf *bpf) 1107c5db7e7SJakub Kicinski { 1117c5db7e7SJakub Kicinski return bpf->command == XDP_QUERY_PROG ? 0 : -EOPNOTSUPP; 1127c5db7e7SJakub Kicinski } 1137c5db7e7SJakub Kicinski 1147c5db7e7SJakub Kicinski static inline int nsim_bpf_disable_tc(struct netdevsim *ns) 1157c5db7e7SJakub Kicinski { 1167c5db7e7SJakub Kicinski return 0; 1177c5db7e7SJakub Kicinski } 1187c5db7e7SJakub Kicinski 1197c5db7e7SJakub Kicinski static inline int 1207c5db7e7SJakub Kicinski nsim_bpf_setup_tc_block_cb(enum tc_setup_type type, void *type_data, 1217c5db7e7SJakub Kicinski void *cb_priv) 1227c5db7e7SJakub Kicinski { 1237c5db7e7SJakub Kicinski return -EOPNOTSUPP; 1247c5db7e7SJakub Kicinski } 1257c5db7e7SJakub Kicinski #endif 12679579220SJakub Kicinski 12737923ed6SDavid Ahern enum nsim_resource_id { 12837923ed6SDavid Ahern NSIM_RESOURCE_NONE, /* DEVLINK_RESOURCE_ID_PARENT_TOP */ 12937923ed6SDavid Ahern NSIM_RESOURCE_IPV4, 13037923ed6SDavid Ahern NSIM_RESOURCE_IPV4_FIB, 13137923ed6SDavid Ahern NSIM_RESOURCE_IPV4_FIB_RULES, 13237923ed6SDavid Ahern NSIM_RESOURCE_IPV6, 13337923ed6SDavid Ahern NSIM_RESOURCE_IPV6_FIB, 13437923ed6SDavid Ahern NSIM_RESOURCE_IPV6_FIB_RULES, 13537923ed6SDavid Ahern }; 13637923ed6SDavid Ahern 13782c93a87SJiri Pirko struct nsim_dev_health { 13882c93a87SJiri Pirko struct devlink_health_reporter *empty_reporter; 13982c93a87SJiri Pirko struct devlink_health_reporter *dummy_reporter; 14082c93a87SJiri Pirko struct dentry *ddir; 14182c93a87SJiri Pirko char *recovered_break_msg; 14282c93a87SJiri Pirko u32 binary_len; 14382c93a87SJiri Pirko bool fail_recover; 14482c93a87SJiri Pirko }; 14582c93a87SJiri Pirko 14682c93a87SJiri Pirko int nsim_dev_health_init(struct nsim_dev *nsim_dev, struct devlink *devlink); 14782c93a87SJiri Pirko void nsim_dev_health_exit(struct nsim_dev *nsim_dev); 14882c93a87SJiri Pirko 1498320d145SJiri Pirko struct nsim_dev_port { 1508320d145SJiri Pirko struct list_head list; 1518320d145SJiri Pirko struct devlink_port devlink_port; 1528320d145SJiri Pirko unsigned int port_index; 1538320d145SJiri Pirko struct dentry *ddir; 154e05b2d14SJiri Pirko struct netdevsim *ns; 1558320d145SJiri Pirko }; 1568320d145SJiri Pirko 157a60f9e48SJiri Pirko struct nsim_dev { 158d514f41eSJiri Pirko struct nsim_bus_dev *nsim_bus_dev; 159a60f9e48SJiri Pirko struct nsim_fib_data *fib_data; 160da58f90fSIdo Schimmel struct nsim_trap_data *trap_data; 161d514f41eSJiri Pirko struct dentry *ddir; 162ab1d0cc0SJiri Pirko struct dentry *ports_ddir; 1638526ad96STaehee Yoo struct dentry *take_snapshot; 164d514f41eSJiri Pirko struct bpf_offload_dev *bpf_dev; 165d514f41eSJiri Pirko bool bpf_bind_accept; 166d514f41eSJiri Pirko u32 bpf_bind_verifier_delay; 167d514f41eSJiri Pirko struct dentry *ddir_bpf_bound_progs; 168d514f41eSJiri Pirko u32 prog_id_gen; 169d514f41eSJiri Pirko struct list_head bpf_bound_progs; 170d514f41eSJiri Pirko struct list_head bpf_bound_maps; 171514cf64cSJiri Pirko struct netdev_phys_item_id switch_id; 1728320d145SJiri Pirko struct list_head port_list; 173794b2c05SJiri Pirko struct mutex port_list_lock; /* protects port list */ 174fa4dfc4aSJiri Pirko bool fw_update_status; 175150e8f8aSJiri Pirko u32 max_macs; 176150e8f8aSJiri Pirko bool test1; 177155ddfc5SJiri Pirko bool dont_allow_reload; 178155ddfc5SJiri Pirko bool fail_reload; 1794418f862SJiri Pirko struct devlink_region *dummy_region; 18082c93a87SJiri Pirko struct nsim_dev_health health; 181*d3cbb907SJiri Pirko struct flow_action_cookie *fa_cookie; 182*d3cbb907SJiri Pirko spinlock_t fa_cookie_lock; /* protects fa_cookie */ 183a60f9e48SJiri Pirko }; 184a60f9e48SJiri Pirko 18590d29913SJiri Pirko static inline struct net *nsim_dev_net(struct nsim_dev *nsim_dev) 18690d29913SJiri Pirko { 18790d29913SJiri Pirko return devlink_net(priv_to_devlink(nsim_dev)); 18890d29913SJiri Pirko } 18990d29913SJiri Pirko 190d514f41eSJiri Pirko int nsim_dev_init(void); 191d514f41eSJiri Pirko void nsim_dev_exit(void); 1928320d145SJiri Pirko int nsim_dev_probe(struct nsim_bus_dev *nsim_bus_dev); 1938320d145SJiri Pirko void nsim_dev_remove(struct nsim_bus_dev *nsim_bus_dev); 194794b2c05SJiri Pirko int nsim_dev_port_add(struct nsim_bus_dev *nsim_bus_dev, 195794b2c05SJiri Pirko unsigned int port_index); 196794b2c05SJiri Pirko int nsim_dev_port_del(struct nsim_bus_dev *nsim_bus_dev, 197794b2c05SJiri Pirko unsigned int port_index); 19837923ed6SDavid Ahern 19975ba029fSJiri Pirko struct nsim_fib_data *nsim_fib_create(struct devlink *devlink, 20075ba029fSJiri Pirko struct netlink_ext_ack *extack); 20175ba029fSJiri Pirko void nsim_fib_destroy(struct devlink *devlink, struct nsim_fib_data *fib_data); 202a5facc4cSJiri Pirko u64 nsim_fib_get_val(struct nsim_fib_data *fib_data, 203a5facc4cSJiri Pirko enum nsim_resource_id res_id, bool max); 20437923ed6SDavid Ahern 2057699353dSShannon Nelson #if IS_ENABLED(CONFIG_XFRM_OFFLOAD) 2067699353dSShannon Nelson void nsim_ipsec_init(struct netdevsim *ns); 2077699353dSShannon Nelson void nsim_ipsec_teardown(struct netdevsim *ns); 2087699353dSShannon Nelson bool nsim_ipsec_tx(struct netdevsim *ns, struct sk_buff *skb); 2097699353dSShannon Nelson #else 2107699353dSShannon Nelson static inline void nsim_ipsec_init(struct netdevsim *ns) 2117699353dSShannon Nelson { 2127699353dSShannon Nelson } 2137699353dSShannon Nelson 2147699353dSShannon Nelson static inline void nsim_ipsec_teardown(struct netdevsim *ns) 2157699353dSShannon Nelson { 2167699353dSShannon Nelson } 2177699353dSShannon Nelson 2187699353dSShannon Nelson static inline bool nsim_ipsec_tx(struct netdevsim *ns, struct sk_buff *skb) 2197699353dSShannon Nelson { 2207699353dSShannon Nelson return true; 2217699353dSShannon Nelson } 2227699353dSShannon Nelson #endif 2237699353dSShannon Nelson 22440e4fe4cSJiri Pirko struct nsim_vf_config { 22540e4fe4cSJiri Pirko int link_state; 22640e4fe4cSJiri Pirko u16 min_tx_rate; 22740e4fe4cSJiri Pirko u16 max_tx_rate; 22840e4fe4cSJiri Pirko u16 vlan; 22940e4fe4cSJiri Pirko __be16 vlan_proto; 23040e4fe4cSJiri Pirko u16 qos; 23140e4fe4cSJiri Pirko u8 vf_mac[ETH_ALEN]; 23240e4fe4cSJiri Pirko bool spoofchk_enabled; 23340e4fe4cSJiri Pirko bool trusted; 23440e4fe4cSJiri Pirko bool rss_query_enabled; 23540e4fe4cSJiri Pirko }; 236925f5afeSJiri Pirko 23740e4fe4cSJiri Pirko struct nsim_bus_dev { 23840e4fe4cSJiri Pirko struct device dev; 239f9d9db47SJiri Pirko struct list_head list; 240f9d9db47SJiri Pirko unsigned int port_count; 2417b60027bSJiri Pirko struct net *initial_net; /* Purpose of this is to carry net pointer 2427b60027bSJiri Pirko * during the probe time only. 2437b60027bSJiri Pirko */ 24440e4fe4cSJiri Pirko unsigned int num_vfs; 24540e4fe4cSJiri Pirko struct nsim_vf_config *vfconfigs; 2466ab63366STaehee Yoo /* Lock for devlink->reload_enabled in netdevsim module */ 2476ab63366STaehee Yoo struct mutex nsim_bus_reload_lock; 248f5cd2160STaehee Yoo bool init; 24940e4fe4cSJiri Pirko }; 250925f5afeSJiri Pirko 251925f5afeSJiri Pirko int nsim_bus_init(void); 252925f5afeSJiri Pirko void nsim_bus_exit(void); 253