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> 2105296620SJakub Kicinski #include <net/xdp.h> 2283c9e13aSJakub Kicinski 2383c9e13aSJakub Kicinski #define DRV_NAME "netdevsim" 2483c9e13aSJakub Kicinski 2531d3ad83SJakub Kicinski #define NSIM_XDP_MAX_MTU 4000 2631d3ad83SJakub Kicinski 2731d3ad83SJakub Kicinski #define NSIM_EA(extack, msg) NL_SET_ERR_MSG_MOD((extack), msg) 2831d3ad83SJakub Kicinski 297699353dSShannon Nelson #define NSIM_IPSEC_MAX_SA_COUNT 33 307699353dSShannon Nelson #define NSIM_IPSEC_VALID BIT(31) 317699353dSShannon Nelson 327699353dSShannon Nelson struct nsim_sa { 337699353dSShannon Nelson struct xfrm_state *xs; 347699353dSShannon Nelson __be32 ipaddr[4]; 357699353dSShannon Nelson u32 key[4]; 367699353dSShannon Nelson u32 salt; 377699353dSShannon Nelson bool used; 387699353dSShannon Nelson bool crypt; 397699353dSShannon Nelson bool rx; 407699353dSShannon Nelson }; 417699353dSShannon Nelson 427699353dSShannon Nelson struct nsim_ipsec { 437699353dSShannon Nelson struct nsim_sa sa[NSIM_IPSEC_MAX_SA_COUNT]; 447699353dSShannon Nelson struct dentry *pfile; 457699353dSShannon Nelson u32 count; 467699353dSShannon Nelson u32 tx; 477699353dSShannon Nelson u32 ok; 487699353dSShannon Nelson }; 497699353dSShannon Nelson 5083c9e13aSJakub Kicinski struct netdevsim { 5131d3ad83SJakub Kicinski struct net_device *netdev; 52a60f9e48SJiri Pirko struct nsim_dev *nsim_dev; 5331d3ad83SJakub Kicinski 5483c9e13aSJakub Kicinski u64 tx_packets; 5583c9e13aSJakub Kicinski u64 tx_bytes; 5683c9e13aSJakub Kicinski struct u64_stats_sync syncp; 5731d3ad83SJakub Kicinski 5840e4fe4cSJiri Pirko struct nsim_bus_dev *nsim_bus_dev; 5979579220SJakub Kicinski 6031d3ad83SJakub Kicinski struct dentry *ddir; 6131d3ad83SJakub 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 777c5db7e7SJakub Kicinski #ifdef CONFIG_BPF_SYSCALL 78*d514f41eSJiri Pirko int nsim_bpf_dev_init(struct nsim_dev *nsim_dev); 79*d514f41eSJiri Pirko void nsim_bpf_dev_exit(struct nsim_dev *nsim_dev); 8031d3ad83SJakub Kicinski int nsim_bpf_init(struct netdevsim *ns); 8131d3ad83SJakub Kicinski void nsim_bpf_uninit(struct netdevsim *ns); 8231d3ad83SJakub Kicinski int nsim_bpf(struct net_device *dev, struct netdev_bpf *bpf); 8331d3ad83SJakub Kicinski int nsim_bpf_disable_tc(struct netdevsim *ns); 8431d3ad83SJakub Kicinski int nsim_bpf_setup_tc_block_cb(enum tc_setup_type type, 8531d3ad83SJakub Kicinski void *type_data, void *cb_priv); 867c5db7e7SJakub Kicinski #else 87*d514f41eSJiri Pirko 88*d514f41eSJiri Pirko static inline int nsim_bpf_dev_init(struct nsim_dev *nsim_dev) 89*d514f41eSJiri Pirko { 90*d514f41eSJiri Pirko return 0; 91*d514f41eSJiri Pirko } 92*d514f41eSJiri Pirko 93*d514f41eSJiri Pirko static inline void nsim_bpf_dev_exit(struct nsim_dev *nsim_dev) 94*d514f41eSJiri Pirko { 95*d514f41eSJiri Pirko } 967c5db7e7SJakub Kicinski static inline int nsim_bpf_init(struct netdevsim *ns) 977c5db7e7SJakub Kicinski { 987c5db7e7SJakub Kicinski return 0; 997c5db7e7SJakub Kicinski } 1007c5db7e7SJakub Kicinski 1017c5db7e7SJakub Kicinski static inline void nsim_bpf_uninit(struct netdevsim *ns) 1027c5db7e7SJakub Kicinski { 1037c5db7e7SJakub Kicinski } 1047c5db7e7SJakub Kicinski 1057c5db7e7SJakub Kicinski static inline int nsim_bpf(struct net_device *dev, struct netdev_bpf *bpf) 1067c5db7e7SJakub Kicinski { 1077c5db7e7SJakub Kicinski return bpf->command == XDP_QUERY_PROG ? 0 : -EOPNOTSUPP; 1087c5db7e7SJakub Kicinski } 1097c5db7e7SJakub Kicinski 1107c5db7e7SJakub Kicinski static inline int nsim_bpf_disable_tc(struct netdevsim *ns) 1117c5db7e7SJakub Kicinski { 1127c5db7e7SJakub Kicinski return 0; 1137c5db7e7SJakub Kicinski } 1147c5db7e7SJakub Kicinski 1157c5db7e7SJakub Kicinski static inline int 1167c5db7e7SJakub Kicinski nsim_bpf_setup_tc_block_cb(enum tc_setup_type type, void *type_data, 1177c5db7e7SJakub Kicinski void *cb_priv) 1187c5db7e7SJakub Kicinski { 1197c5db7e7SJakub Kicinski return -EOPNOTSUPP; 1207c5db7e7SJakub Kicinski } 1217c5db7e7SJakub Kicinski #endif 12279579220SJakub Kicinski 12337923ed6SDavid Ahern enum nsim_resource_id { 12437923ed6SDavid Ahern NSIM_RESOURCE_NONE, /* DEVLINK_RESOURCE_ID_PARENT_TOP */ 12537923ed6SDavid Ahern NSIM_RESOURCE_IPV4, 12637923ed6SDavid Ahern NSIM_RESOURCE_IPV4_FIB, 12737923ed6SDavid Ahern NSIM_RESOURCE_IPV4_FIB_RULES, 12837923ed6SDavid Ahern NSIM_RESOURCE_IPV6, 12937923ed6SDavid Ahern NSIM_RESOURCE_IPV6_FIB, 13037923ed6SDavid Ahern NSIM_RESOURCE_IPV6_FIB_RULES, 13137923ed6SDavid Ahern }; 13237923ed6SDavid Ahern 133a60f9e48SJiri Pirko struct nsim_dev { 134*d514f41eSJiri Pirko struct nsim_bus_dev *nsim_bus_dev; 135a60f9e48SJiri Pirko struct nsim_fib_data *fib_data; 136*d514f41eSJiri Pirko struct dentry *ddir; 137*d514f41eSJiri Pirko struct bpf_offload_dev *bpf_dev; 138*d514f41eSJiri Pirko bool bpf_bind_accept; 139*d514f41eSJiri Pirko u32 bpf_bind_verifier_delay; 140*d514f41eSJiri Pirko struct dentry *ddir_bpf_bound_progs; 141*d514f41eSJiri Pirko u32 prog_id_gen; 142*d514f41eSJiri Pirko struct list_head bpf_bound_progs; 143*d514f41eSJiri Pirko struct list_head bpf_bound_maps; 144a60f9e48SJiri Pirko }; 145a60f9e48SJiri Pirko 146a60f9e48SJiri Pirko struct nsim_dev * 147a60f9e48SJiri Pirko nsim_dev_create_with_ns(struct nsim_bus_dev *nsim_bus_dev, 148a60f9e48SJiri Pirko struct netdevsim *ns); 149a60f9e48SJiri Pirko void nsim_dev_destroy(struct nsim_dev *nsim_dev); 150*d514f41eSJiri Pirko int nsim_dev_init(void); 151*d514f41eSJiri Pirko void nsim_dev_exit(void); 15237923ed6SDavid Ahern 1535fc49422SJiri Pirko struct nsim_fib_data *nsim_fib_create(void); 1545fc49422SJiri Pirko void nsim_fib_destroy(struct nsim_fib_data *fib_data); 1555fc49422SJiri Pirko u64 nsim_fib_get_val(struct nsim_fib_data *fib_data, 1565fc49422SJiri Pirko enum nsim_resource_id res_id, bool max); 1575fc49422SJiri Pirko int nsim_fib_set_max(struct nsim_fib_data *fib_data, 1585fc49422SJiri Pirko enum nsim_resource_id res_id, u64 val, 1597fa76d77SDavid Ahern struct netlink_ext_ack *extack); 16037923ed6SDavid Ahern 1617699353dSShannon Nelson #if IS_ENABLED(CONFIG_XFRM_OFFLOAD) 1627699353dSShannon Nelson void nsim_ipsec_init(struct netdevsim *ns); 1637699353dSShannon Nelson void nsim_ipsec_teardown(struct netdevsim *ns); 1647699353dSShannon Nelson bool nsim_ipsec_tx(struct netdevsim *ns, struct sk_buff *skb); 1657699353dSShannon Nelson #else 1667699353dSShannon Nelson static inline void nsim_ipsec_init(struct netdevsim *ns) 1677699353dSShannon Nelson { 1687699353dSShannon Nelson } 1697699353dSShannon Nelson 1707699353dSShannon Nelson static inline void nsim_ipsec_teardown(struct netdevsim *ns) 1717699353dSShannon Nelson { 1727699353dSShannon Nelson } 1737699353dSShannon Nelson 1747699353dSShannon Nelson static inline bool nsim_ipsec_tx(struct netdevsim *ns, struct sk_buff *skb) 1757699353dSShannon Nelson { 1767699353dSShannon Nelson return true; 1777699353dSShannon Nelson } 1787699353dSShannon Nelson #endif 1797699353dSShannon Nelson 18040e4fe4cSJiri Pirko struct nsim_vf_config { 18140e4fe4cSJiri Pirko int link_state; 18240e4fe4cSJiri Pirko u16 min_tx_rate; 18340e4fe4cSJiri Pirko u16 max_tx_rate; 18440e4fe4cSJiri Pirko u16 vlan; 18540e4fe4cSJiri Pirko __be16 vlan_proto; 18640e4fe4cSJiri Pirko u16 qos; 18740e4fe4cSJiri Pirko u8 vf_mac[ETH_ALEN]; 18840e4fe4cSJiri Pirko bool spoofchk_enabled; 18940e4fe4cSJiri Pirko bool trusted; 19040e4fe4cSJiri Pirko bool rss_query_enabled; 19140e4fe4cSJiri Pirko }; 192925f5afeSJiri Pirko 19340e4fe4cSJiri Pirko struct nsim_bus_dev { 19440e4fe4cSJiri Pirko struct device dev; 195f9d9db47SJiri Pirko struct list_head list; 196f9d9db47SJiri Pirko unsigned int port_count; 19740e4fe4cSJiri Pirko unsigned int num_vfs; 19840e4fe4cSJiri Pirko struct nsim_vf_config *vfconfigs; 19940e4fe4cSJiri Pirko }; 200925f5afeSJiri Pirko 201f9d9db47SJiri Pirko struct nsim_bus_dev *nsim_bus_dev_new(unsigned int id, unsigned int port_count); 20240e4fe4cSJiri Pirko void nsim_bus_dev_del(struct nsim_bus_dev *nsim_bus_dev); 203925f5afeSJiri Pirko int nsim_bus_init(void); 204925f5afeSJiri Pirko void nsim_bus_exit(void); 205