1 /*- 2 * Copyright (c) 2013-2017, Mellanox Technologies, Ltd. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS `AS IS' AND 14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23 * SUCH DAMAGE. 24 */ 25 26 #ifndef _MLX5_FS_CORE_ 27 #define _MLX5_FS_CORE_ 28 29 #include <asm/atomic.h> 30 #include <linux/completion.h> 31 #include <linux/mutex.h> 32 #include <dev/mlx5/fs.h> 33 34 enum fs_type { 35 FS_TYPE_NAMESPACE, 36 FS_TYPE_PRIO, 37 FS_TYPE_FLOW_TABLE, 38 FS_TYPE_FLOW_GROUP, 39 FS_TYPE_FLOW_ENTRY, 40 FS_TYPE_FLOW_DEST 41 }; 42 43 enum fs_ft_type { 44 FS_FT_NIC_RX = 0x0, 45 FS_FT_ESW_EGRESS_ACL = 0x2, 46 FS_FT_ESW_INGRESS_ACL = 0x3, 47 FS_FT_FDB = 0X4, 48 FS_FT_SNIFFER_RX = 0x5, 49 FS_FT_SNIFFER_TX = 0x6 50 }; 51 52 enum fs_fte_status { 53 FS_FTE_STATUS_EXISTING = 1UL << 0, 54 }; 55 56 /* Should always be the first variable in the struct */ 57 struct fs_base { 58 struct list_head list; 59 struct fs_base *parent; 60 enum fs_type type; 61 struct kref refcount; 62 /* lock the node for writing and traversing */ 63 struct mutex lock; 64 struct completion complete; 65 atomic_t users_refcount; 66 const char *name; 67 }; 68 69 struct mlx5_flow_rule { 70 struct fs_base base; 71 struct mlx5_flow_destination dest_attr; 72 struct list_head clients_data; 73 /*protect clients lits*/ 74 struct mutex clients_lock; 75 }; 76 77 struct fs_fte { 78 struct fs_base base; 79 u32 val[MLX5_ST_SZ_DW(fte_match_param)]; 80 uint32_t dests_size; 81 struct list_head dests; 82 uint32_t index; /* index in ft */ 83 struct mlx5_flow_act flow_act; 84 u32 sw_action; /* enum mlx5_rule_fwd_action */ 85 enum fs_fte_status status; 86 }; 87 88 struct fs_star_rule { 89 struct mlx5_flow_group *fg; 90 struct fs_fte *fte; 91 }; 92 93 struct mlx5_flow_table { 94 struct fs_base base; 95 /* sorted list by start_index */ 96 struct list_head fgs; 97 struct { 98 bool active; 99 unsigned int max_types; 100 unsigned int group_size; 101 unsigned int num_types; 102 } autogroup; 103 unsigned int max_fte; 104 unsigned int level; 105 uint32_t id; 106 u16 vport; 107 enum fs_ft_type type; 108 struct fs_star_rule star_rule; 109 unsigned int shared_refcount; 110 }; 111 112 enum fs_prio_flags { 113 MLX5_CORE_FS_PRIO_SHARED = 1 114 }; 115 116 struct fs_prio { 117 struct fs_base base; 118 struct list_head objs; /* each object is a namespace or ft */ 119 unsigned int max_ft; 120 unsigned int num_ft; 121 unsigned int max_ns; 122 unsigned int prio; 123 /*When create shared flow table, this lock should be taken*/ 124 struct mutex shared_lock; 125 u8 flags; 126 }; 127 128 struct mlx5_flow_namespace { 129 /* parent == NULL => root ns */ 130 struct fs_base base; 131 /* sorted by priority number */ 132 struct list_head prios; /* list of fs_prios */ 133 struct list_head list_notifiers; 134 struct rw_semaphore notifiers_rw_sem; 135 struct rw_semaphore dests_rw_sem; 136 }; 137 138 struct mlx5_flow_root_namespace { 139 struct mlx5_flow_namespace ns; 140 struct mlx5_flow_table *ft_level_0; 141 enum fs_ft_type table_type; 142 struct mlx5_core_dev *dev; 143 struct mlx5_flow_table *root_ft; 144 /* When chaining flow-tables, this lock should be taken */ 145 struct mutex fs_chain_lock; 146 }; 147 148 struct mlx5_flow_group { 149 struct fs_base base; 150 struct list_head ftes; 151 struct mlx5_core_fs_mask mask; 152 uint32_t start_index; 153 uint32_t max_ftes; 154 uint32_t num_ftes; 155 uint32_t id; 156 }; 157 158 struct mlx5_flow_handler { 159 struct list_head list; 160 rule_event_fn add_dst_cb; 161 rule_event_fn del_dst_cb; 162 void *client_context; 163 struct mlx5_flow_namespace *ns; 164 }; 165 166 struct fs_client_priv_data { 167 struct mlx5_flow_handler *fs_handler; 168 struct list_head list; 169 void *client_dst_data; 170 }; 171 172 struct mlx5_modify_hdr { 173 enum mlx5_flow_namespace_type ns_type; 174 u32 id; 175 }; 176 177 struct mlx5_pkt_reformat { 178 enum mlx5_flow_namespace_type ns_type; 179 int reformat_type; /* from mlx5_ifc */ 180 u32 id; 181 }; 182 183 void _fs_remove_node(struct kref *kref); 184 #define fs_get_obj(v, _base) {v = container_of((_base), typeof(*v), base); } 185 #define fs_get_parent(v, child) {v = (child)->base.parent ? \ 186 container_of((child)->base.parent, \ 187 typeof(*v), base) : NULL; } 188 189 #define fs_list_for_each_entry(pos, cond, root) \ 190 list_for_each_entry(pos, root, base.list) \ 191 if (!(cond)) {} else 192 193 #define fs_list_for_each_entry_continue(pos, cond, root) \ 194 list_for_each_entry_continue(pos, root, base.list) \ 195 if (!(cond)) {} else 196 197 #define fs_list_for_each_entry_reverse(pos, cond, root) \ 198 list_for_each_entry_reverse(pos, root, base.list) \ 199 if (!(cond)) {} else 200 201 #define fs_list_for_each_entry_continue_reverse(pos, cond, root) \ 202 list_for_each_entry_continue_reverse(pos, root, base.list) \ 203 if (!(cond)) {} else 204 205 #define fs_for_each_ft(pos, prio) \ 206 fs_list_for_each_entry(pos, (pos)->base.type == FS_TYPE_FLOW_TABLE, \ 207 &(prio)->objs) 208 209 #define fs_for_each_ft_reverse(pos, prio) \ 210 fs_list_for_each_entry_reverse(pos, \ 211 (pos)->base.type == FS_TYPE_FLOW_TABLE, \ 212 &(prio)->objs) 213 214 #define fs_for_each_ns(pos, prio) \ 215 fs_list_for_each_entry(pos, \ 216 (pos)->base.type == FS_TYPE_NAMESPACE, \ 217 &(prio)->objs) 218 219 #define fs_for_each_ns_or_ft_reverse(pos, prio) \ 220 list_for_each_entry_reverse(pos, &(prio)->objs, list) \ 221 if (!((pos)->type == FS_TYPE_NAMESPACE || \ 222 (pos)->type == FS_TYPE_FLOW_TABLE)) {} else 223 224 #define fs_for_each_ns_or_ft(pos, prio) \ 225 list_for_each_entry(pos, &(prio)->objs, list) \ 226 if (!((pos)->type == FS_TYPE_NAMESPACE || \ 227 (pos)->type == FS_TYPE_FLOW_TABLE)) {} else 228 229 #define fs_for_each_ns_or_ft_continue_reverse(pos, prio) \ 230 list_for_each_entry_continue_reverse(pos, &(prio)->objs, list) \ 231 if (!((pos)->type == FS_TYPE_NAMESPACE || \ 232 (pos)->type == FS_TYPE_FLOW_TABLE)) {} else 233 234 #define fs_for_each_ns_or_ft_continue(pos, prio) \ 235 list_for_each_entry_continue(pos, &(prio)->objs, list) \ 236 if (!((pos)->type == FS_TYPE_NAMESPACE || \ 237 (pos)->type == FS_TYPE_FLOW_TABLE)) {} else 238 239 #define fs_for_each_prio(pos, ns) \ 240 fs_list_for_each_entry(pos, (pos)->base.type == FS_TYPE_PRIO, \ 241 &(ns)->prios) 242 243 #define fs_for_each_prio_reverse(pos, ns) \ 244 fs_list_for_each_entry_reverse(pos, (pos)->base.type == FS_TYPE_PRIO, \ 245 &(ns)->prios) 246 247 #define fs_for_each_prio_continue(pos, ns) \ 248 fs_list_for_each_entry_continue(pos, (pos)->base.type == FS_TYPE_PRIO, \ 249 &(ns)->prios) 250 251 #define fs_for_each_prio_continue_reverse(pos, ns) \ 252 fs_list_for_each_entry_continue_reverse(pos, \ 253 (pos)->base.type == FS_TYPE_PRIO, \ 254 &(ns)->prios) 255 256 #define fs_for_each_fg(pos, ft) \ 257 fs_list_for_each_entry(pos, (pos)->base.type == FS_TYPE_FLOW_GROUP, \ 258 &(ft)->fgs) 259 260 #define fs_for_each_fte(pos, fg) \ 261 fs_list_for_each_entry(pos, (pos)->base.type == FS_TYPE_FLOW_ENTRY, \ 262 &(fg)->ftes) 263 #define fs_for_each_dst(pos, fte) \ 264 fs_list_for_each_entry(pos, (pos)->base.type == FS_TYPE_FLOW_DEST, \ 265 &(fte)->dests) 266 267 int mlx5_cmd_fs_create_ft(struct mlx5_core_dev *dev, 268 u16 vport, enum fs_ft_type type, unsigned int level, 269 unsigned int log_size, const char *name, unsigned int *table_id); 270 271 int mlx5_cmd_fs_destroy_ft(struct mlx5_core_dev *dev, 272 u16 vport, 273 enum fs_ft_type type, unsigned int table_id); 274 275 int mlx5_cmd_fs_create_fg(struct mlx5_core_dev *dev, 276 u32 *in, 277 u16 vport, 278 enum fs_ft_type type, unsigned int table_id, 279 unsigned int *group_id); 280 281 int mlx5_cmd_fs_destroy_fg(struct mlx5_core_dev *dev, 282 u16 vport, 283 enum fs_ft_type type, unsigned int table_id, 284 unsigned int group_id); 285 286 287 int mlx5_cmd_fs_set_fte(struct mlx5_core_dev *dev, 288 u16 vport, 289 enum fs_fte_status *fte_status, 290 u32 *match_val, 291 enum fs_ft_type type, unsigned int table_id, 292 unsigned int index, unsigned int group_id, 293 struct mlx5_flow_act *flow_act, 294 u32 sw_action, int dest_size, 295 struct list_head *dests); /* mlx5_flow_desination */ 296 297 int mlx5_cmd_fs_delete_fte(struct mlx5_core_dev *dev, 298 u16 vport, 299 enum fs_fte_status *fte_status, 300 enum fs_ft_type type, unsigned int table_id, 301 unsigned int index); 302 303 int mlx5_cmd_update_root_ft(struct mlx5_core_dev *dev, 304 enum fs_ft_type type, 305 unsigned int id); 306 307 int mlx5_init_fs(struct mlx5_core_dev *dev); 308 void mlx5_cleanup_fs(struct mlx5_core_dev *dev); 309 void mlx5_fc_update_sampling_interval(struct mlx5_core_dev *dev, 310 unsigned long interval); 311 312 int mlx5_cmd_modify_header_alloc(struct mlx5_core_dev *dev, 313 enum mlx5_flow_namespace_type namespace, 314 u8 num_actions, 315 void *modify_actions, 316 struct mlx5_modify_hdr *modify_hdr); 317 void mlx5_cmd_modify_header_dealloc(struct mlx5_core_dev *dev, 318 struct mlx5_modify_hdr *modify_hdr); 319 int mlx5_cmd_packet_reformat_alloc(struct mlx5_core_dev *dev, 320 struct mlx5_pkt_reformat_params *params, 321 enum mlx5_flow_namespace_type namespace, 322 struct mlx5_pkt_reformat *pkt_reformat); 323 void mlx5_cmd_packet_reformat_dealloc(struct mlx5_core_dev *dev, 324 struct mlx5_pkt_reformat *pkt_reformat); 325 #endif 326