| .. | .. |
|---|
| 13 | 13 | * THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. |
|---|
| 14 | 14 | */ |
|---|
| 15 | 15 | |
|---|
| 16 | +#include <linux/debugfs.h> |
|---|
| 16 | 17 | #include <linux/device.h> |
|---|
| 17 | 18 | #include <linux/kernel.h> |
|---|
| 18 | 19 | #include <linux/list.h> |
|---|
| 19 | 20 | #include <linux/netdevice.h> |
|---|
| 20 | 21 | #include <linux/u64_stats_sync.h> |
|---|
| 22 | +#include <net/devlink.h> |
|---|
| 23 | +#include <net/udp_tunnel.h> |
|---|
| 21 | 24 | #include <net/xdp.h> |
|---|
| 22 | 25 | |
|---|
| 23 | 26 | #define DRV_NAME "netdevsim" |
|---|
| .. | .. |
|---|
| 26 | 29 | |
|---|
| 27 | 30 | #define NSIM_EA(extack, msg) NL_SET_ERR_MSG_MOD((extack), msg) |
|---|
| 28 | 31 | |
|---|
| 29 | | -struct bpf_prog; |
|---|
| 30 | | -struct bpf_offload_dev; |
|---|
| 31 | | -struct dentry; |
|---|
| 32 | | -struct nsim_vf_config; |
|---|
| 33 | | - |
|---|
| 34 | | -struct netdevsim_shared_dev { |
|---|
| 35 | | - unsigned int refcnt; |
|---|
| 36 | | - u32 switch_id; |
|---|
| 37 | | - |
|---|
| 38 | | - struct dentry *ddir; |
|---|
| 39 | | - |
|---|
| 40 | | - struct bpf_offload_dev *bpf_dev; |
|---|
| 41 | | - |
|---|
| 42 | | - struct dentry *ddir_bpf_bound_progs; |
|---|
| 43 | | - u32 prog_id_gen; |
|---|
| 44 | | - |
|---|
| 45 | | - struct list_head bpf_bound_progs; |
|---|
| 46 | | - struct list_head bpf_bound_maps; |
|---|
| 47 | | -}; |
|---|
| 48 | | - |
|---|
| 49 | 32 | #define NSIM_IPSEC_MAX_SA_COUNT 33 |
|---|
| 50 | 33 | #define NSIM_IPSEC_VALID BIT(31) |
|---|
| 34 | +#define NSIM_UDP_TUNNEL_N_PORTS 4 |
|---|
| 51 | 35 | |
|---|
| 52 | 36 | struct nsim_sa { |
|---|
| 53 | 37 | struct xfrm_state *xs; |
|---|
| .. | .. |
|---|
| 67 | 51 | u32 ok; |
|---|
| 68 | 52 | }; |
|---|
| 69 | 53 | |
|---|
| 54 | +struct nsim_ethtool { |
|---|
| 55 | + bool rx; |
|---|
| 56 | + bool tx; |
|---|
| 57 | + bool report_stats_rx; |
|---|
| 58 | + bool report_stats_tx; |
|---|
| 59 | +}; |
|---|
| 60 | + |
|---|
| 70 | 61 | struct netdevsim { |
|---|
| 71 | 62 | struct net_device *netdev; |
|---|
| 63 | + struct nsim_dev *nsim_dev; |
|---|
| 64 | + struct nsim_dev_port *nsim_dev_port; |
|---|
| 72 | 65 | |
|---|
| 73 | 66 | u64 tx_packets; |
|---|
| 74 | 67 | u64 tx_bytes; |
|---|
| 75 | 68 | struct u64_stats_sync syncp; |
|---|
| 76 | 69 | |
|---|
| 77 | | - struct device dev; |
|---|
| 78 | | - struct netdevsim_shared_dev *sdev; |
|---|
| 79 | | - |
|---|
| 80 | | - struct dentry *ddir; |
|---|
| 81 | | - |
|---|
| 82 | | - unsigned int num_vfs; |
|---|
| 83 | | - struct nsim_vf_config *vfconfigs; |
|---|
| 70 | + struct nsim_bus_dev *nsim_bus_dev; |
|---|
| 84 | 71 | |
|---|
| 85 | 72 | struct bpf_prog *bpf_offloaded; |
|---|
| 86 | 73 | u32 bpf_offloaded_id; |
|---|
| .. | .. |
|---|
| 88 | 75 | struct xdp_attachment_info xdp; |
|---|
| 89 | 76 | struct xdp_attachment_info xdp_hw; |
|---|
| 90 | 77 | |
|---|
| 91 | | - bool bpf_bind_accept; |
|---|
| 92 | | - u32 bpf_bind_verifier_delay; |
|---|
| 93 | | - |
|---|
| 94 | 78 | bool bpf_tc_accept; |
|---|
| 95 | 79 | bool bpf_tc_non_bound_accept; |
|---|
| 96 | 80 | bool bpf_xdpdrv_accept; |
|---|
| 97 | 81 | bool bpf_xdpoffload_accept; |
|---|
| 98 | 82 | |
|---|
| 99 | 83 | bool bpf_map_accept; |
|---|
| 100 | | -#if IS_ENABLED(CONFIG_NET_DEVLINK) |
|---|
| 101 | | - struct devlink *devlink; |
|---|
| 102 | | -#endif |
|---|
| 103 | 84 | struct nsim_ipsec ipsec; |
|---|
| 85 | + struct { |
|---|
| 86 | + u32 inject_error; |
|---|
| 87 | + u32 sleep; |
|---|
| 88 | + u32 __ports[2][NSIM_UDP_TUNNEL_N_PORTS]; |
|---|
| 89 | + u32 (*ports)[NSIM_UDP_TUNNEL_N_PORTS]; |
|---|
| 90 | + struct debugfs_u32_array dfs_ports[2]; |
|---|
| 91 | + } udp_ports; |
|---|
| 92 | + |
|---|
| 93 | + struct nsim_ethtool ethtool; |
|---|
| 104 | 94 | }; |
|---|
| 105 | 95 | |
|---|
| 96 | +struct netdevsim * |
|---|
| 97 | +nsim_create(struct nsim_dev *nsim_dev, struct nsim_dev_port *nsim_dev_port); |
|---|
| 98 | +void nsim_destroy(struct netdevsim *ns); |
|---|
| 99 | + |
|---|
| 100 | +void nsim_ethtool_init(struct netdevsim *ns); |
|---|
| 101 | + |
|---|
| 102 | +void nsim_udp_tunnels_debugfs_create(struct nsim_dev *nsim_dev); |
|---|
| 103 | +int nsim_udp_tunnels_info_create(struct nsim_dev *nsim_dev, |
|---|
| 104 | + struct net_device *dev); |
|---|
| 105 | +void nsim_udp_tunnels_info_destroy(struct net_device *dev); |
|---|
| 106 | + |
|---|
| 106 | 107 | #ifdef CONFIG_BPF_SYSCALL |
|---|
| 108 | +int nsim_bpf_dev_init(struct nsim_dev *nsim_dev); |
|---|
| 109 | +void nsim_bpf_dev_exit(struct nsim_dev *nsim_dev); |
|---|
| 107 | 110 | int nsim_bpf_init(struct netdevsim *ns); |
|---|
| 108 | 111 | void nsim_bpf_uninit(struct netdevsim *ns); |
|---|
| 109 | 112 | int nsim_bpf(struct net_device *dev, struct netdev_bpf *bpf); |
|---|
| .. | .. |
|---|
| 111 | 114 | int nsim_bpf_setup_tc_block_cb(enum tc_setup_type type, |
|---|
| 112 | 115 | void *type_data, void *cb_priv); |
|---|
| 113 | 116 | #else |
|---|
| 117 | + |
|---|
| 118 | +static inline int nsim_bpf_dev_init(struct nsim_dev *nsim_dev) |
|---|
| 119 | +{ |
|---|
| 120 | + return 0; |
|---|
| 121 | +} |
|---|
| 122 | + |
|---|
| 123 | +static inline void nsim_bpf_dev_exit(struct nsim_dev *nsim_dev) |
|---|
| 124 | +{ |
|---|
| 125 | +} |
|---|
| 114 | 126 | static inline int nsim_bpf_init(struct netdevsim *ns) |
|---|
| 115 | 127 | { |
|---|
| 116 | 128 | return 0; |
|---|
| .. | .. |
|---|
| 122 | 134 | |
|---|
| 123 | 135 | static inline int nsim_bpf(struct net_device *dev, struct netdev_bpf *bpf) |
|---|
| 124 | 136 | { |
|---|
| 125 | | - return bpf->command == XDP_QUERY_PROG ? 0 : -EOPNOTSUPP; |
|---|
| 137 | + return -EOPNOTSUPP; |
|---|
| 126 | 138 | } |
|---|
| 127 | 139 | |
|---|
| 128 | 140 | static inline int nsim_bpf_disable_tc(struct netdevsim *ns) |
|---|
| .. | .. |
|---|
| 138 | 150 | } |
|---|
| 139 | 151 | #endif |
|---|
| 140 | 152 | |
|---|
| 141 | | -#if IS_ENABLED(CONFIG_NET_DEVLINK) |
|---|
| 142 | 153 | enum nsim_resource_id { |
|---|
| 143 | 154 | NSIM_RESOURCE_NONE, /* DEVLINK_RESOURCE_ID_PARENT_TOP */ |
|---|
| 144 | 155 | NSIM_RESOURCE_IPV4, |
|---|
| .. | .. |
|---|
| 149 | 160 | NSIM_RESOURCE_IPV6_FIB_RULES, |
|---|
| 150 | 161 | }; |
|---|
| 151 | 162 | |
|---|
| 152 | | -int nsim_devlink_setup(struct netdevsim *ns); |
|---|
| 153 | | -void nsim_devlink_teardown(struct netdevsim *ns); |
|---|
| 163 | +struct nsim_dev_health { |
|---|
| 164 | + struct devlink_health_reporter *empty_reporter; |
|---|
| 165 | + struct devlink_health_reporter *dummy_reporter; |
|---|
| 166 | + struct dentry *ddir; |
|---|
| 167 | + char *recovered_break_msg; |
|---|
| 168 | + u32 binary_len; |
|---|
| 169 | + bool fail_recover; |
|---|
| 170 | +}; |
|---|
| 154 | 171 | |
|---|
| 155 | | -int nsim_devlink_init(void); |
|---|
| 156 | | -void nsim_devlink_exit(void); |
|---|
| 172 | +int nsim_dev_health_init(struct nsim_dev *nsim_dev, struct devlink *devlink); |
|---|
| 173 | +void nsim_dev_health_exit(struct nsim_dev *nsim_dev); |
|---|
| 157 | 174 | |
|---|
| 158 | | -int nsim_fib_init(void); |
|---|
| 159 | | -void nsim_fib_exit(void); |
|---|
| 160 | | -u64 nsim_fib_get_val(struct net *net, enum nsim_resource_id res_id, bool max); |
|---|
| 161 | | -int nsim_fib_set_max(struct net *net, enum nsim_resource_id res_id, u64 val, |
|---|
| 162 | | - struct netlink_ext_ack *extack); |
|---|
| 163 | | -#else |
|---|
| 164 | | -static inline int nsim_devlink_setup(struct netdevsim *ns) |
|---|
| 175 | +struct nsim_dev_port { |
|---|
| 176 | + struct list_head list; |
|---|
| 177 | + struct devlink_port devlink_port; |
|---|
| 178 | + unsigned int port_index; |
|---|
| 179 | + struct dentry *ddir; |
|---|
| 180 | + struct netdevsim *ns; |
|---|
| 181 | +}; |
|---|
| 182 | + |
|---|
| 183 | +struct nsim_dev { |
|---|
| 184 | + struct nsim_bus_dev *nsim_bus_dev; |
|---|
| 185 | + struct nsim_fib_data *fib_data; |
|---|
| 186 | + struct nsim_trap_data *trap_data; |
|---|
| 187 | + struct dentry *ddir; |
|---|
| 188 | + struct dentry *ports_ddir; |
|---|
| 189 | + struct dentry *take_snapshot; |
|---|
| 190 | + struct bpf_offload_dev *bpf_dev; |
|---|
| 191 | + bool bpf_bind_accept; |
|---|
| 192 | + bool bpf_bind_verifier_accept; |
|---|
| 193 | + u32 bpf_bind_verifier_delay; |
|---|
| 194 | + struct dentry *ddir_bpf_bound_progs; |
|---|
| 195 | + u32 prog_id_gen; |
|---|
| 196 | + struct list_head bpf_bound_progs; |
|---|
| 197 | + struct list_head bpf_bound_maps; |
|---|
| 198 | + struct netdev_phys_item_id switch_id; |
|---|
| 199 | + struct list_head port_list; |
|---|
| 200 | + struct mutex port_list_lock; /* protects port list */ |
|---|
| 201 | + bool fw_update_status; |
|---|
| 202 | + u32 fw_update_overwrite_mask; |
|---|
| 203 | + u32 max_macs; |
|---|
| 204 | + bool test1; |
|---|
| 205 | + bool dont_allow_reload; |
|---|
| 206 | + bool fail_reload; |
|---|
| 207 | + struct devlink_region *dummy_region; |
|---|
| 208 | + struct nsim_dev_health health; |
|---|
| 209 | + struct flow_action_cookie *fa_cookie; |
|---|
| 210 | + spinlock_t fa_cookie_lock; /* protects fa_cookie */ |
|---|
| 211 | + bool fail_trap_group_set; |
|---|
| 212 | + bool fail_trap_policer_set; |
|---|
| 213 | + bool fail_trap_policer_counter_get; |
|---|
| 214 | + struct { |
|---|
| 215 | + struct udp_tunnel_nic_shared utn_shared; |
|---|
| 216 | + u32 __ports[2][NSIM_UDP_TUNNEL_N_PORTS]; |
|---|
| 217 | + bool sync_all; |
|---|
| 218 | + bool open_only; |
|---|
| 219 | + bool ipv4_only; |
|---|
| 220 | + bool shared; |
|---|
| 221 | + bool static_iana_vxlan; |
|---|
| 222 | + u32 sleep; |
|---|
| 223 | + } udp_ports; |
|---|
| 224 | +}; |
|---|
| 225 | + |
|---|
| 226 | +static inline struct net *nsim_dev_net(struct nsim_dev *nsim_dev) |
|---|
| 165 | 227 | { |
|---|
| 166 | | - return 0; |
|---|
| 228 | + return devlink_net(priv_to_devlink(nsim_dev)); |
|---|
| 167 | 229 | } |
|---|
| 168 | 230 | |
|---|
| 169 | | -static inline void nsim_devlink_teardown(struct netdevsim *ns) |
|---|
| 170 | | -{ |
|---|
| 171 | | -} |
|---|
| 231 | +int nsim_dev_init(void); |
|---|
| 232 | +void nsim_dev_exit(void); |
|---|
| 233 | +int nsim_dev_probe(struct nsim_bus_dev *nsim_bus_dev); |
|---|
| 234 | +void nsim_dev_remove(struct nsim_bus_dev *nsim_bus_dev); |
|---|
| 235 | +int nsim_dev_port_add(struct nsim_bus_dev *nsim_bus_dev, |
|---|
| 236 | + unsigned int port_index); |
|---|
| 237 | +int nsim_dev_port_del(struct nsim_bus_dev *nsim_bus_dev, |
|---|
| 238 | + unsigned int port_index); |
|---|
| 172 | 239 | |
|---|
| 173 | | -static inline int nsim_devlink_init(void) |
|---|
| 174 | | -{ |
|---|
| 175 | | - return 0; |
|---|
| 176 | | -} |
|---|
| 177 | | - |
|---|
| 178 | | -static inline void nsim_devlink_exit(void) |
|---|
| 179 | | -{ |
|---|
| 180 | | -} |
|---|
| 181 | | -#endif |
|---|
| 240 | +struct nsim_fib_data *nsim_fib_create(struct devlink *devlink, |
|---|
| 241 | + struct netlink_ext_ack *extack); |
|---|
| 242 | +void nsim_fib_destroy(struct devlink *devlink, struct nsim_fib_data *fib_data); |
|---|
| 243 | +u64 nsim_fib_get_val(struct nsim_fib_data *fib_data, |
|---|
| 244 | + enum nsim_resource_id res_id, bool max); |
|---|
| 182 | 245 | |
|---|
| 183 | 246 | #if IS_ENABLED(CONFIG_XFRM_OFFLOAD) |
|---|
| 184 | 247 | void nsim_ipsec_init(struct netdevsim *ns); |
|---|
| .. | .. |
|---|
| 199 | 262 | } |
|---|
| 200 | 263 | #endif |
|---|
| 201 | 264 | |
|---|
| 202 | | -static inline struct netdevsim *to_nsim(struct device *ptr) |
|---|
| 203 | | -{ |
|---|
| 204 | | - return container_of(ptr, struct netdevsim, dev); |
|---|
| 205 | | -} |
|---|
| 265 | +struct nsim_vf_config { |
|---|
| 266 | + int link_state; |
|---|
| 267 | + u16 min_tx_rate; |
|---|
| 268 | + u16 max_tx_rate; |
|---|
| 269 | + u16 vlan; |
|---|
| 270 | + __be16 vlan_proto; |
|---|
| 271 | + u16 qos; |
|---|
| 272 | + u8 vf_mac[ETH_ALEN]; |
|---|
| 273 | + bool spoofchk_enabled; |
|---|
| 274 | + bool trusted; |
|---|
| 275 | + bool rss_query_enabled; |
|---|
| 276 | +}; |
|---|
| 277 | + |
|---|
| 278 | +struct nsim_bus_dev { |
|---|
| 279 | + struct device dev; |
|---|
| 280 | + struct list_head list; |
|---|
| 281 | + unsigned int port_count; |
|---|
| 282 | + struct net *initial_net; /* Purpose of this is to carry net pointer |
|---|
| 283 | + * during the probe time only. |
|---|
| 284 | + */ |
|---|
| 285 | + unsigned int num_vfs; |
|---|
| 286 | + struct nsim_vf_config *vfconfigs; |
|---|
| 287 | + /* Lock for devlink->reload_enabled in netdevsim module */ |
|---|
| 288 | + struct mutex nsim_bus_reload_lock; |
|---|
| 289 | + bool init; |
|---|
| 290 | +}; |
|---|
| 291 | + |
|---|
| 292 | +int nsim_bus_init(void); |
|---|
| 293 | +void nsim_bus_exit(void); |
|---|