| .. | .. |
|---|
| 8 | 8 | #include <linux/string.h> |
|---|
| 9 | 9 | #include <linux/rhashtable.h> |
|---|
| 10 | 10 | #include <linux/netdevice.h> |
|---|
| 11 | +#include <linux/mutex.h> |
|---|
| 11 | 12 | #include <net/net_namespace.h> |
|---|
| 12 | 13 | #include <net/tc_act/tc_vlan.h> |
|---|
| 13 | 14 | |
|---|
| .. | .. |
|---|
| 25 | 26 | struct mlxsw_sp_fid *dummy_fid; |
|---|
| 26 | 27 | struct rhashtable ruleset_ht; |
|---|
| 27 | 28 | struct list_head rules; |
|---|
| 29 | + struct mutex rules_lock; /* Protects rules list */ |
|---|
| 28 | 30 | struct { |
|---|
| 29 | 31 | struct delayed_work dw; |
|---|
| 30 | 32 | unsigned long interval; /* ms */ |
|---|
| .. | .. |
|---|
| 38 | 40 | return acl->afk; |
|---|
| 39 | 41 | } |
|---|
| 40 | 42 | |
|---|
| 41 | | -struct mlxsw_sp_acl_block_binding { |
|---|
| 42 | | - struct list_head list; |
|---|
| 43 | | - struct net_device *dev; |
|---|
| 44 | | - struct mlxsw_sp_port *mlxsw_sp_port; |
|---|
| 45 | | - bool ingress; |
|---|
| 46 | | -}; |
|---|
| 47 | | - |
|---|
| 48 | | -struct mlxsw_sp_acl_block { |
|---|
| 49 | | - struct list_head binding_list; |
|---|
| 50 | | - struct mlxsw_sp_acl_ruleset *ruleset_zero; |
|---|
| 51 | | - struct mlxsw_sp *mlxsw_sp; |
|---|
| 52 | | - unsigned int rule_count; |
|---|
| 53 | | - unsigned int disable_count; |
|---|
| 54 | | -}; |
|---|
| 55 | | - |
|---|
| 56 | 43 | struct mlxsw_sp_acl_ruleset_ht_key { |
|---|
| 57 | | - struct mlxsw_sp_acl_block *block; |
|---|
| 44 | + struct mlxsw_sp_flow_block *block; |
|---|
| 58 | 45 | u32 chain_index; |
|---|
| 59 | 46 | const struct mlxsw_sp_acl_profile_ops *ops; |
|---|
| 60 | 47 | }; |
|---|
| .. | .. |
|---|
| 64 | 51 | struct mlxsw_sp_acl_ruleset_ht_key ht_key; |
|---|
| 65 | 52 | struct rhashtable rule_ht; |
|---|
| 66 | 53 | unsigned int ref_count; |
|---|
| 67 | | - unsigned long priv[0]; |
|---|
| 54 | + unsigned int min_prio; |
|---|
| 55 | + unsigned int max_prio; |
|---|
| 56 | + unsigned long priv[]; |
|---|
| 68 | 57 | /* priv has to be always the last item */ |
|---|
| 69 | 58 | }; |
|---|
| 70 | 59 | |
|---|
| .. | .. |
|---|
| 77 | 66 | u64 last_used; |
|---|
| 78 | 67 | u64 last_packets; |
|---|
| 79 | 68 | u64 last_bytes; |
|---|
| 80 | | - unsigned long priv[0]; |
|---|
| 69 | + u64 last_drops; |
|---|
| 70 | + unsigned long priv[]; |
|---|
| 81 | 71 | /* priv has to be always the last item */ |
|---|
| 82 | 72 | }; |
|---|
| 83 | 73 | |
|---|
| .. | .. |
|---|
| 100 | 90 | return mlxsw_sp->acl->dummy_fid; |
|---|
| 101 | 91 | } |
|---|
| 102 | 92 | |
|---|
| 103 | | -struct mlxsw_sp *mlxsw_sp_acl_block_mlxsw_sp(struct mlxsw_sp_acl_block *block) |
|---|
| 104 | | -{ |
|---|
| 105 | | - return block->mlxsw_sp; |
|---|
| 106 | | -} |
|---|
| 107 | | - |
|---|
| 108 | | -unsigned int mlxsw_sp_acl_block_rule_count(struct mlxsw_sp_acl_block *block) |
|---|
| 109 | | -{ |
|---|
| 110 | | - return block ? block->rule_count : 0; |
|---|
| 111 | | -} |
|---|
| 112 | | - |
|---|
| 113 | | -void mlxsw_sp_acl_block_disable_inc(struct mlxsw_sp_acl_block *block) |
|---|
| 114 | | -{ |
|---|
| 115 | | - if (block) |
|---|
| 116 | | - block->disable_count++; |
|---|
| 117 | | -} |
|---|
| 118 | | - |
|---|
| 119 | | -void mlxsw_sp_acl_block_disable_dec(struct mlxsw_sp_acl_block *block) |
|---|
| 120 | | -{ |
|---|
| 121 | | - if (block) |
|---|
| 122 | | - block->disable_count--; |
|---|
| 123 | | -} |
|---|
| 124 | | - |
|---|
| 125 | | -bool mlxsw_sp_acl_block_disabled(struct mlxsw_sp_acl_block *block) |
|---|
| 126 | | -{ |
|---|
| 127 | | - return block->disable_count; |
|---|
| 128 | | -} |
|---|
| 129 | | - |
|---|
| 130 | | -bool mlxsw_sp_acl_block_is_egress_bound(struct mlxsw_sp_acl_block *block) |
|---|
| 131 | | -{ |
|---|
| 132 | | - struct mlxsw_sp_acl_block_binding *binding; |
|---|
| 133 | | - |
|---|
| 134 | | - list_for_each_entry(binding, &block->binding_list, list) { |
|---|
| 135 | | - if (!binding->ingress) |
|---|
| 136 | | - return true; |
|---|
| 137 | | - } |
|---|
| 138 | | - return false; |
|---|
| 139 | | -} |
|---|
| 140 | | - |
|---|
| 141 | 93 | static bool |
|---|
| 142 | 94 | mlxsw_sp_acl_ruleset_is_singular(const struct mlxsw_sp_acl_ruleset *ruleset) |
|---|
| 143 | 95 | { |
|---|
| .. | .. |
|---|
| 145 | 97 | return ruleset->ref_count == 2; |
|---|
| 146 | 98 | } |
|---|
| 147 | 99 | |
|---|
| 148 | | -static int |
|---|
| 149 | | -mlxsw_sp_acl_ruleset_bind(struct mlxsw_sp *mlxsw_sp, |
|---|
| 150 | | - struct mlxsw_sp_acl_block *block, |
|---|
| 151 | | - struct mlxsw_sp_acl_block_binding *binding) |
|---|
| 100 | +int mlxsw_sp_acl_ruleset_bind(struct mlxsw_sp *mlxsw_sp, |
|---|
| 101 | + struct mlxsw_sp_flow_block *block, |
|---|
| 102 | + struct mlxsw_sp_flow_block_binding *binding) |
|---|
| 152 | 103 | { |
|---|
| 153 | 104 | struct mlxsw_sp_acl_ruleset *ruleset = block->ruleset_zero; |
|---|
| 154 | 105 | const struct mlxsw_sp_acl_profile_ops *ops = ruleset->ht_key.ops; |
|---|
| .. | .. |
|---|
| 157 | 108 | binding->mlxsw_sp_port, binding->ingress); |
|---|
| 158 | 109 | } |
|---|
| 159 | 110 | |
|---|
| 160 | | -static void |
|---|
| 161 | | -mlxsw_sp_acl_ruleset_unbind(struct mlxsw_sp *mlxsw_sp, |
|---|
| 162 | | - struct mlxsw_sp_acl_block *block, |
|---|
| 163 | | - struct mlxsw_sp_acl_block_binding *binding) |
|---|
| 111 | +void mlxsw_sp_acl_ruleset_unbind(struct mlxsw_sp *mlxsw_sp, |
|---|
| 112 | + struct mlxsw_sp_flow_block *block, |
|---|
| 113 | + struct mlxsw_sp_flow_block_binding *binding) |
|---|
| 164 | 114 | { |
|---|
| 165 | 115 | struct mlxsw_sp_acl_ruleset *ruleset = block->ruleset_zero; |
|---|
| 166 | 116 | const struct mlxsw_sp_acl_profile_ops *ops = ruleset->ht_key.ops; |
|---|
| .. | .. |
|---|
| 169 | 119 | binding->mlxsw_sp_port, binding->ingress); |
|---|
| 170 | 120 | } |
|---|
| 171 | 121 | |
|---|
| 172 | | -static bool mlxsw_sp_acl_ruleset_block_bound(struct mlxsw_sp_acl_block *block) |
|---|
| 173 | | -{ |
|---|
| 174 | | - return block->ruleset_zero; |
|---|
| 175 | | -} |
|---|
| 176 | | - |
|---|
| 177 | 122 | static int |
|---|
| 178 | 123 | mlxsw_sp_acl_ruleset_block_bind(struct mlxsw_sp *mlxsw_sp, |
|---|
| 179 | 124 | struct mlxsw_sp_acl_ruleset *ruleset, |
|---|
| 180 | | - struct mlxsw_sp_acl_block *block) |
|---|
| 125 | + struct mlxsw_sp_flow_block *block) |
|---|
| 181 | 126 | { |
|---|
| 182 | | - struct mlxsw_sp_acl_block_binding *binding; |
|---|
| 127 | + struct mlxsw_sp_flow_block_binding *binding; |
|---|
| 183 | 128 | int err; |
|---|
| 184 | 129 | |
|---|
| 185 | 130 | block->ruleset_zero = ruleset; |
|---|
| .. | .. |
|---|
| 202 | 147 | static void |
|---|
| 203 | 148 | mlxsw_sp_acl_ruleset_block_unbind(struct mlxsw_sp *mlxsw_sp, |
|---|
| 204 | 149 | struct mlxsw_sp_acl_ruleset *ruleset, |
|---|
| 205 | | - struct mlxsw_sp_acl_block *block) |
|---|
| 150 | + struct mlxsw_sp_flow_block *block) |
|---|
| 206 | 151 | { |
|---|
| 207 | | - struct mlxsw_sp_acl_block_binding *binding; |
|---|
| 152 | + struct mlxsw_sp_flow_block_binding *binding; |
|---|
| 208 | 153 | |
|---|
| 209 | 154 | list_for_each_entry(binding, &block->binding_list, list) |
|---|
| 210 | 155 | mlxsw_sp_acl_ruleset_unbind(mlxsw_sp, block, binding); |
|---|
| 211 | 156 | block->ruleset_zero = NULL; |
|---|
| 212 | 157 | } |
|---|
| 213 | 158 | |
|---|
| 214 | | -struct mlxsw_sp_acl_block *mlxsw_sp_acl_block_create(struct mlxsw_sp *mlxsw_sp, |
|---|
| 215 | | - struct net *net) |
|---|
| 216 | | -{ |
|---|
| 217 | | - struct mlxsw_sp_acl_block *block; |
|---|
| 218 | | - |
|---|
| 219 | | - block = kzalloc(sizeof(*block), GFP_KERNEL); |
|---|
| 220 | | - if (!block) |
|---|
| 221 | | - return NULL; |
|---|
| 222 | | - INIT_LIST_HEAD(&block->binding_list); |
|---|
| 223 | | - block->mlxsw_sp = mlxsw_sp; |
|---|
| 224 | | - return block; |
|---|
| 225 | | -} |
|---|
| 226 | | - |
|---|
| 227 | | -void mlxsw_sp_acl_block_destroy(struct mlxsw_sp_acl_block *block) |
|---|
| 228 | | -{ |
|---|
| 229 | | - WARN_ON(!list_empty(&block->binding_list)); |
|---|
| 230 | | - kfree(block); |
|---|
| 231 | | -} |
|---|
| 232 | | - |
|---|
| 233 | | -static struct mlxsw_sp_acl_block_binding * |
|---|
| 234 | | -mlxsw_sp_acl_block_lookup(struct mlxsw_sp_acl_block *block, |
|---|
| 235 | | - struct mlxsw_sp_port *mlxsw_sp_port, bool ingress) |
|---|
| 236 | | -{ |
|---|
| 237 | | - struct mlxsw_sp_acl_block_binding *binding; |
|---|
| 238 | | - |
|---|
| 239 | | - list_for_each_entry(binding, &block->binding_list, list) |
|---|
| 240 | | - if (binding->mlxsw_sp_port == mlxsw_sp_port && |
|---|
| 241 | | - binding->ingress == ingress) |
|---|
| 242 | | - return binding; |
|---|
| 243 | | - return NULL; |
|---|
| 244 | | -} |
|---|
| 245 | | - |
|---|
| 246 | | -int mlxsw_sp_acl_block_bind(struct mlxsw_sp *mlxsw_sp, |
|---|
| 247 | | - struct mlxsw_sp_acl_block *block, |
|---|
| 248 | | - struct mlxsw_sp_port *mlxsw_sp_port, |
|---|
| 249 | | - bool ingress) |
|---|
| 250 | | -{ |
|---|
| 251 | | - struct mlxsw_sp_acl_block_binding *binding; |
|---|
| 252 | | - int err; |
|---|
| 253 | | - |
|---|
| 254 | | - if (WARN_ON(mlxsw_sp_acl_block_lookup(block, mlxsw_sp_port, ingress))) |
|---|
| 255 | | - return -EEXIST; |
|---|
| 256 | | - |
|---|
| 257 | | - binding = kzalloc(sizeof(*binding), GFP_KERNEL); |
|---|
| 258 | | - if (!binding) |
|---|
| 259 | | - return -ENOMEM; |
|---|
| 260 | | - binding->mlxsw_sp_port = mlxsw_sp_port; |
|---|
| 261 | | - binding->ingress = ingress; |
|---|
| 262 | | - |
|---|
| 263 | | - if (mlxsw_sp_acl_ruleset_block_bound(block)) { |
|---|
| 264 | | - err = mlxsw_sp_acl_ruleset_bind(mlxsw_sp, block, binding); |
|---|
| 265 | | - if (err) |
|---|
| 266 | | - goto err_ruleset_bind; |
|---|
| 267 | | - } |
|---|
| 268 | | - |
|---|
| 269 | | - list_add(&binding->list, &block->binding_list); |
|---|
| 270 | | - return 0; |
|---|
| 271 | | - |
|---|
| 272 | | -err_ruleset_bind: |
|---|
| 273 | | - kfree(binding); |
|---|
| 274 | | - return err; |
|---|
| 275 | | -} |
|---|
| 276 | | - |
|---|
| 277 | | -int mlxsw_sp_acl_block_unbind(struct mlxsw_sp *mlxsw_sp, |
|---|
| 278 | | - struct mlxsw_sp_acl_block *block, |
|---|
| 279 | | - struct mlxsw_sp_port *mlxsw_sp_port, |
|---|
| 280 | | - bool ingress) |
|---|
| 281 | | -{ |
|---|
| 282 | | - struct mlxsw_sp_acl_block_binding *binding; |
|---|
| 283 | | - |
|---|
| 284 | | - binding = mlxsw_sp_acl_block_lookup(block, mlxsw_sp_port, ingress); |
|---|
| 285 | | - if (!binding) |
|---|
| 286 | | - return -ENOENT; |
|---|
| 287 | | - |
|---|
| 288 | | - list_del(&binding->list); |
|---|
| 289 | | - |
|---|
| 290 | | - if (mlxsw_sp_acl_ruleset_block_bound(block)) |
|---|
| 291 | | - mlxsw_sp_acl_ruleset_unbind(mlxsw_sp, block, binding); |
|---|
| 292 | | - |
|---|
| 293 | | - kfree(binding); |
|---|
| 294 | | - return 0; |
|---|
| 295 | | -} |
|---|
| 296 | | - |
|---|
| 297 | 159 | static struct mlxsw_sp_acl_ruleset * |
|---|
| 298 | 160 | mlxsw_sp_acl_ruleset_create(struct mlxsw_sp *mlxsw_sp, |
|---|
| 299 | | - struct mlxsw_sp_acl_block *block, u32 chain_index, |
|---|
| 161 | + struct mlxsw_sp_flow_block *block, u32 chain_index, |
|---|
| 300 | 162 | const struct mlxsw_sp_acl_profile_ops *ops, |
|---|
| 301 | 163 | struct mlxsw_afk_element_usage *tmplt_elusage) |
|---|
| 302 | 164 | { |
|---|
| .. | .. |
|---|
| 319 | 181 | goto err_rhashtable_init; |
|---|
| 320 | 182 | |
|---|
| 321 | 183 | err = ops->ruleset_add(mlxsw_sp, &acl->tcam, ruleset->priv, |
|---|
| 322 | | - tmplt_elusage); |
|---|
| 184 | + tmplt_elusage, &ruleset->min_prio, |
|---|
| 185 | + &ruleset->max_prio); |
|---|
| 323 | 186 | if (err) |
|---|
| 324 | 187 | goto err_ops_ruleset_add; |
|---|
| 325 | 188 | |
|---|
| .. | .. |
|---|
| 367 | 230 | |
|---|
| 368 | 231 | static struct mlxsw_sp_acl_ruleset * |
|---|
| 369 | 232 | __mlxsw_sp_acl_ruleset_lookup(struct mlxsw_sp_acl *acl, |
|---|
| 370 | | - struct mlxsw_sp_acl_block *block, u32 chain_index, |
|---|
| 233 | + struct mlxsw_sp_flow_block *block, u32 chain_index, |
|---|
| 371 | 234 | const struct mlxsw_sp_acl_profile_ops *ops) |
|---|
| 372 | 235 | { |
|---|
| 373 | 236 | struct mlxsw_sp_acl_ruleset_ht_key ht_key; |
|---|
| .. | .. |
|---|
| 382 | 245 | |
|---|
| 383 | 246 | struct mlxsw_sp_acl_ruleset * |
|---|
| 384 | 247 | mlxsw_sp_acl_ruleset_lookup(struct mlxsw_sp *mlxsw_sp, |
|---|
| 385 | | - struct mlxsw_sp_acl_block *block, u32 chain_index, |
|---|
| 248 | + struct mlxsw_sp_flow_block *block, u32 chain_index, |
|---|
| 386 | 249 | enum mlxsw_sp_acl_profile profile) |
|---|
| 387 | 250 | { |
|---|
| 388 | 251 | const struct mlxsw_sp_acl_profile_ops *ops; |
|---|
| .. | .. |
|---|
| 400 | 263 | |
|---|
| 401 | 264 | struct mlxsw_sp_acl_ruleset * |
|---|
| 402 | 265 | mlxsw_sp_acl_ruleset_get(struct mlxsw_sp *mlxsw_sp, |
|---|
| 403 | | - struct mlxsw_sp_acl_block *block, u32 chain_index, |
|---|
| 266 | + struct mlxsw_sp_flow_block *block, u32 chain_index, |
|---|
| 404 | 267 | enum mlxsw_sp_acl_profile profile, |
|---|
| 405 | 268 | struct mlxsw_afk_element_usage *tmplt_elusage) |
|---|
| 406 | 269 | { |
|---|
| .. | .. |
|---|
| 434 | 297 | return ops->ruleset_group_id(ruleset->priv); |
|---|
| 435 | 298 | } |
|---|
| 436 | 299 | |
|---|
| 300 | +void mlxsw_sp_acl_ruleset_prio_get(struct mlxsw_sp_acl_ruleset *ruleset, |
|---|
| 301 | + unsigned int *p_min_prio, |
|---|
| 302 | + unsigned int *p_max_prio) |
|---|
| 303 | +{ |
|---|
| 304 | + *p_min_prio = ruleset->min_prio; |
|---|
| 305 | + *p_max_prio = ruleset->max_prio; |
|---|
| 306 | +} |
|---|
| 307 | + |
|---|
| 437 | 308 | struct mlxsw_sp_acl_rule_info * |
|---|
| 438 | | -mlxsw_sp_acl_rulei_create(struct mlxsw_sp_acl *acl) |
|---|
| 309 | +mlxsw_sp_acl_rulei_create(struct mlxsw_sp_acl *acl, |
|---|
| 310 | + struct mlxsw_afa_block *afa_block) |
|---|
| 439 | 311 | { |
|---|
| 440 | 312 | struct mlxsw_sp_acl_rule_info *rulei; |
|---|
| 441 | 313 | int err; |
|---|
| .. | .. |
|---|
| 444 | 316 | if (!rulei) |
|---|
| 445 | 317 | return ERR_PTR(-ENOMEM); |
|---|
| 446 | 318 | |
|---|
| 319 | + if (afa_block) { |
|---|
| 320 | + rulei->act_block = afa_block; |
|---|
| 321 | + return rulei; |
|---|
| 322 | + } |
|---|
| 323 | + |
|---|
| 447 | 324 | rulei->act_block = mlxsw_afa_block_create(acl->mlxsw_sp->afa); |
|---|
| 448 | 325 | if (IS_ERR(rulei->act_block)) { |
|---|
| 449 | 326 | err = PTR_ERR(rulei->act_block); |
|---|
| 450 | 327 | goto err_afa_block_create; |
|---|
| 451 | 328 | } |
|---|
| 329 | + rulei->action_created = 1; |
|---|
| 452 | 330 | return rulei; |
|---|
| 453 | 331 | |
|---|
| 454 | 332 | err_afa_block_create: |
|---|
| .. | .. |
|---|
| 458 | 336 | |
|---|
| 459 | 337 | void mlxsw_sp_acl_rulei_destroy(struct mlxsw_sp_acl_rule_info *rulei) |
|---|
| 460 | 338 | { |
|---|
| 461 | | - mlxsw_afa_block_destroy(rulei->act_block); |
|---|
| 339 | + if (rulei->action_created) |
|---|
| 340 | + mlxsw_afa_block_destroy(rulei->act_block); |
|---|
| 462 | 341 | kfree(rulei); |
|---|
| 463 | 342 | } |
|---|
| 464 | 343 | |
|---|
| .. | .. |
|---|
| 470 | 349 | void mlxsw_sp_acl_rulei_priority(struct mlxsw_sp_acl_rule_info *rulei, |
|---|
| 471 | 350 | unsigned int priority) |
|---|
| 472 | 351 | { |
|---|
| 473 | | - rulei->priority = priority >> 16; |
|---|
| 352 | + rulei->priority = priority; |
|---|
| 474 | 353 | } |
|---|
| 475 | 354 | |
|---|
| 476 | 355 | void mlxsw_sp_acl_rulei_keymask_u32(struct mlxsw_sp_acl_rule_info *rulei, |
|---|
| .. | .. |
|---|
| 506 | 385 | return mlxsw_afa_block_terminate(rulei->act_block); |
|---|
| 507 | 386 | } |
|---|
| 508 | 387 | |
|---|
| 509 | | -int mlxsw_sp_acl_rulei_act_drop(struct mlxsw_sp_acl_rule_info *rulei) |
|---|
| 388 | +int mlxsw_sp_acl_rulei_act_drop(struct mlxsw_sp_acl_rule_info *rulei, |
|---|
| 389 | + bool ingress, |
|---|
| 390 | + const struct flow_action_cookie *fa_cookie, |
|---|
| 391 | + struct netlink_ext_ack *extack) |
|---|
| 510 | 392 | { |
|---|
| 511 | | - return mlxsw_afa_block_append_drop(rulei->act_block); |
|---|
| 393 | + return mlxsw_afa_block_append_drop(rulei->act_block, ingress, |
|---|
| 394 | + fa_cookie, extack); |
|---|
| 512 | 395 | } |
|---|
| 513 | 396 | |
|---|
| 514 | 397 | int mlxsw_sp_acl_rulei_act_trap(struct mlxsw_sp_acl_rule_info *rulei) |
|---|
| .. | .. |
|---|
| 551 | 434 | |
|---|
| 552 | 435 | int mlxsw_sp_acl_rulei_act_mirror(struct mlxsw_sp *mlxsw_sp, |
|---|
| 553 | 436 | struct mlxsw_sp_acl_rule_info *rulei, |
|---|
| 554 | | - struct mlxsw_sp_acl_block *block, |
|---|
| 437 | + struct mlxsw_sp_flow_block *block, |
|---|
| 555 | 438 | struct net_device *out_dev, |
|---|
| 556 | 439 | struct netlink_ext_ack *extack) |
|---|
| 557 | 440 | { |
|---|
| 558 | | - struct mlxsw_sp_acl_block_binding *binding; |
|---|
| 441 | + struct mlxsw_sp_flow_block_binding *binding; |
|---|
| 559 | 442 | struct mlxsw_sp_port *in_port; |
|---|
| 560 | 443 | |
|---|
| 561 | 444 | if (!list_is_singular(&block->binding_list)) { |
|---|
| .. | .. |
|---|
| 563 | 446 | return -EOPNOTSUPP; |
|---|
| 564 | 447 | } |
|---|
| 565 | 448 | binding = list_first_entry(&block->binding_list, |
|---|
| 566 | | - struct mlxsw_sp_acl_block_binding, list); |
|---|
| 449 | + struct mlxsw_sp_flow_block_binding, list); |
|---|
| 567 | 450 | in_port = binding->mlxsw_sp_port; |
|---|
| 568 | 451 | |
|---|
| 569 | 452 | return mlxsw_afa_block_append_mirror(rulei->act_block, |
|---|
| .. | .. |
|---|
| 580 | 463 | { |
|---|
| 581 | 464 | u8 ethertype; |
|---|
| 582 | 465 | |
|---|
| 583 | | - if (action == TCA_VLAN_ACT_MODIFY) { |
|---|
| 466 | + if (action == FLOW_ACTION_VLAN_MANGLE) { |
|---|
| 584 | 467 | switch (proto) { |
|---|
| 585 | 468 | case ETH_P_8021Q: |
|---|
| 586 | 469 | ethertype = 0; |
|---|
| .. | .. |
|---|
| 605 | 488 | } |
|---|
| 606 | 489 | } |
|---|
| 607 | 490 | |
|---|
| 491 | +int mlxsw_sp_acl_rulei_act_priority(struct mlxsw_sp *mlxsw_sp, |
|---|
| 492 | + struct mlxsw_sp_acl_rule_info *rulei, |
|---|
| 493 | + u32 prio, struct netlink_ext_ack *extack) |
|---|
| 494 | +{ |
|---|
| 495 | + /* Even though both Linux and Spectrum switches support 16 priorities, |
|---|
| 496 | + * spectrum_qdisc only processes the first eight priomap elements, and |
|---|
| 497 | + * the DCB and PFC features are tied to 8 priorities as well. Therefore |
|---|
| 498 | + * bounce attempts to prioritize packets to higher priorities. |
|---|
| 499 | + */ |
|---|
| 500 | + if (prio >= IEEE_8021QAZ_MAX_TCS) { |
|---|
| 501 | + NL_SET_ERR_MSG_MOD(extack, "Only priorities 0..7 are supported"); |
|---|
| 502 | + return -EINVAL; |
|---|
| 503 | + } |
|---|
| 504 | + return mlxsw_afa_block_append_qos_switch_prio(rulei->act_block, prio, |
|---|
| 505 | + extack); |
|---|
| 506 | +} |
|---|
| 507 | + |
|---|
| 508 | +enum mlxsw_sp_acl_mangle_field { |
|---|
| 509 | + MLXSW_SP_ACL_MANGLE_FIELD_IP_DSFIELD, |
|---|
| 510 | + MLXSW_SP_ACL_MANGLE_FIELD_IP_DSCP, |
|---|
| 511 | + MLXSW_SP_ACL_MANGLE_FIELD_IP_ECN, |
|---|
| 512 | + MLXSW_SP_ACL_MANGLE_FIELD_IP_SPORT, |
|---|
| 513 | + MLXSW_SP_ACL_MANGLE_FIELD_IP_DPORT, |
|---|
| 514 | +}; |
|---|
| 515 | + |
|---|
| 516 | +struct mlxsw_sp_acl_mangle_action { |
|---|
| 517 | + enum flow_action_mangle_base htype; |
|---|
| 518 | + /* Offset is u32-aligned. */ |
|---|
| 519 | + u32 offset; |
|---|
| 520 | + /* Mask bits are unset for the modified field. */ |
|---|
| 521 | + u32 mask; |
|---|
| 522 | + /* Shift required to extract the set value. */ |
|---|
| 523 | + u32 shift; |
|---|
| 524 | + enum mlxsw_sp_acl_mangle_field field; |
|---|
| 525 | +}; |
|---|
| 526 | + |
|---|
| 527 | +#define MLXSW_SP_ACL_MANGLE_ACTION(_htype, _offset, _mask, _shift, _field) \ |
|---|
| 528 | + { \ |
|---|
| 529 | + .htype = _htype, \ |
|---|
| 530 | + .offset = _offset, \ |
|---|
| 531 | + .mask = _mask, \ |
|---|
| 532 | + .shift = _shift, \ |
|---|
| 533 | + .field = MLXSW_SP_ACL_MANGLE_FIELD_##_field, \ |
|---|
| 534 | + } |
|---|
| 535 | + |
|---|
| 536 | +#define MLXSW_SP_ACL_MANGLE_ACTION_IP4(_offset, _mask, _shift, _field) \ |
|---|
| 537 | + MLXSW_SP_ACL_MANGLE_ACTION(FLOW_ACT_MANGLE_HDR_TYPE_IP4, \ |
|---|
| 538 | + _offset, _mask, _shift, _field) |
|---|
| 539 | + |
|---|
| 540 | +#define MLXSW_SP_ACL_MANGLE_ACTION_IP6(_offset, _mask, _shift, _field) \ |
|---|
| 541 | + MLXSW_SP_ACL_MANGLE_ACTION(FLOW_ACT_MANGLE_HDR_TYPE_IP6, \ |
|---|
| 542 | + _offset, _mask, _shift, _field) |
|---|
| 543 | + |
|---|
| 544 | +#define MLXSW_SP_ACL_MANGLE_ACTION_TCP(_offset, _mask, _shift, _field) \ |
|---|
| 545 | + MLXSW_SP_ACL_MANGLE_ACTION(FLOW_ACT_MANGLE_HDR_TYPE_TCP, _offset, _mask, _shift, _field) |
|---|
| 546 | + |
|---|
| 547 | +#define MLXSW_SP_ACL_MANGLE_ACTION_UDP(_offset, _mask, _shift, _field) \ |
|---|
| 548 | + MLXSW_SP_ACL_MANGLE_ACTION(FLOW_ACT_MANGLE_HDR_TYPE_UDP, _offset, _mask, _shift, _field) |
|---|
| 549 | + |
|---|
| 550 | +static struct mlxsw_sp_acl_mangle_action mlxsw_sp_acl_mangle_actions[] = { |
|---|
| 551 | + MLXSW_SP_ACL_MANGLE_ACTION_IP4(0, 0xff00ffff, 16, IP_DSFIELD), |
|---|
| 552 | + MLXSW_SP_ACL_MANGLE_ACTION_IP4(0, 0xff03ffff, 18, IP_DSCP), |
|---|
| 553 | + MLXSW_SP_ACL_MANGLE_ACTION_IP4(0, 0xfffcffff, 16, IP_ECN), |
|---|
| 554 | + |
|---|
| 555 | + MLXSW_SP_ACL_MANGLE_ACTION_IP6(0, 0xf00fffff, 20, IP_DSFIELD), |
|---|
| 556 | + MLXSW_SP_ACL_MANGLE_ACTION_IP6(0, 0xf03fffff, 22, IP_DSCP), |
|---|
| 557 | + MLXSW_SP_ACL_MANGLE_ACTION_IP6(0, 0xffcfffff, 20, IP_ECN), |
|---|
| 558 | + |
|---|
| 559 | + MLXSW_SP_ACL_MANGLE_ACTION_TCP(0, 0x0000ffff, 16, IP_SPORT), |
|---|
| 560 | + MLXSW_SP_ACL_MANGLE_ACTION_TCP(0, 0xffff0000, 0, IP_DPORT), |
|---|
| 561 | + |
|---|
| 562 | + MLXSW_SP_ACL_MANGLE_ACTION_UDP(0, 0x0000ffff, 16, IP_SPORT), |
|---|
| 563 | + MLXSW_SP_ACL_MANGLE_ACTION_UDP(0, 0xffff0000, 0, IP_DPORT), |
|---|
| 564 | +}; |
|---|
| 565 | + |
|---|
| 566 | +static int |
|---|
| 567 | +mlxsw_sp_acl_rulei_act_mangle_field(struct mlxsw_sp *mlxsw_sp, |
|---|
| 568 | + struct mlxsw_sp_acl_rule_info *rulei, |
|---|
| 569 | + struct mlxsw_sp_acl_mangle_action *mact, |
|---|
| 570 | + u32 val, struct netlink_ext_ack *extack) |
|---|
| 571 | +{ |
|---|
| 572 | + switch (mact->field) { |
|---|
| 573 | + case MLXSW_SP_ACL_MANGLE_FIELD_IP_DSFIELD: |
|---|
| 574 | + return mlxsw_afa_block_append_qos_dsfield(rulei->act_block, |
|---|
| 575 | + val, extack); |
|---|
| 576 | + case MLXSW_SP_ACL_MANGLE_FIELD_IP_DSCP: |
|---|
| 577 | + return mlxsw_afa_block_append_qos_dscp(rulei->act_block, |
|---|
| 578 | + val, extack); |
|---|
| 579 | + case MLXSW_SP_ACL_MANGLE_FIELD_IP_ECN: |
|---|
| 580 | + return mlxsw_afa_block_append_qos_ecn(rulei->act_block, |
|---|
| 581 | + val, extack); |
|---|
| 582 | + default: |
|---|
| 583 | + return -EOPNOTSUPP; |
|---|
| 584 | + } |
|---|
| 585 | +} |
|---|
| 586 | + |
|---|
| 587 | +static int mlxsw_sp1_acl_rulei_act_mangle_field(struct mlxsw_sp *mlxsw_sp, |
|---|
| 588 | + struct mlxsw_sp_acl_rule_info *rulei, |
|---|
| 589 | + struct mlxsw_sp_acl_mangle_action *mact, |
|---|
| 590 | + u32 val, struct netlink_ext_ack *extack) |
|---|
| 591 | +{ |
|---|
| 592 | + int err; |
|---|
| 593 | + |
|---|
| 594 | + err = mlxsw_sp_acl_rulei_act_mangle_field(mlxsw_sp, rulei, mact, val, extack); |
|---|
| 595 | + if (err != -EOPNOTSUPP) |
|---|
| 596 | + return err; |
|---|
| 597 | + |
|---|
| 598 | + NL_SET_ERR_MSG_MOD(extack, "Unsupported mangle field"); |
|---|
| 599 | + return err; |
|---|
| 600 | +} |
|---|
| 601 | + |
|---|
| 602 | +static int mlxsw_sp2_acl_rulei_act_mangle_field(struct mlxsw_sp *mlxsw_sp, |
|---|
| 603 | + struct mlxsw_sp_acl_rule_info *rulei, |
|---|
| 604 | + struct mlxsw_sp_acl_mangle_action *mact, |
|---|
| 605 | + u32 val, struct netlink_ext_ack *extack) |
|---|
| 606 | +{ |
|---|
| 607 | + int err; |
|---|
| 608 | + |
|---|
| 609 | + err = mlxsw_sp_acl_rulei_act_mangle_field(mlxsw_sp, rulei, mact, val, extack); |
|---|
| 610 | + if (err != -EOPNOTSUPP) |
|---|
| 611 | + return err; |
|---|
| 612 | + |
|---|
| 613 | + switch (mact->field) { |
|---|
| 614 | + case MLXSW_SP_ACL_MANGLE_FIELD_IP_SPORT: |
|---|
| 615 | + return mlxsw_afa_block_append_l4port(rulei->act_block, false, val, extack); |
|---|
| 616 | + case MLXSW_SP_ACL_MANGLE_FIELD_IP_DPORT: |
|---|
| 617 | + return mlxsw_afa_block_append_l4port(rulei->act_block, true, val, extack); |
|---|
| 618 | + default: |
|---|
| 619 | + break; |
|---|
| 620 | + } |
|---|
| 621 | + |
|---|
| 622 | + NL_SET_ERR_MSG_MOD(extack, "Unsupported mangle field"); |
|---|
| 623 | + return err; |
|---|
| 624 | +} |
|---|
| 625 | + |
|---|
| 626 | +int mlxsw_sp_acl_rulei_act_mangle(struct mlxsw_sp *mlxsw_sp, |
|---|
| 627 | + struct mlxsw_sp_acl_rule_info *rulei, |
|---|
| 628 | + enum flow_action_mangle_base htype, |
|---|
| 629 | + u32 offset, u32 mask, u32 val, |
|---|
| 630 | + struct netlink_ext_ack *extack) |
|---|
| 631 | +{ |
|---|
| 632 | + const struct mlxsw_sp_acl_rulei_ops *acl_rulei_ops = mlxsw_sp->acl_rulei_ops; |
|---|
| 633 | + struct mlxsw_sp_acl_mangle_action *mact; |
|---|
| 634 | + size_t i; |
|---|
| 635 | + |
|---|
| 636 | + for (i = 0; i < ARRAY_SIZE(mlxsw_sp_acl_mangle_actions); ++i) { |
|---|
| 637 | + mact = &mlxsw_sp_acl_mangle_actions[i]; |
|---|
| 638 | + if (mact->htype == htype && |
|---|
| 639 | + mact->offset == offset && |
|---|
| 640 | + mact->mask == mask) { |
|---|
| 641 | + val >>= mact->shift; |
|---|
| 642 | + return acl_rulei_ops->act_mangle_field(mlxsw_sp, |
|---|
| 643 | + rulei, mact, |
|---|
| 644 | + val, extack); |
|---|
| 645 | + } |
|---|
| 646 | + } |
|---|
| 647 | + |
|---|
| 648 | + NL_SET_ERR_MSG_MOD(extack, "Unknown mangle field"); |
|---|
| 649 | + return -EINVAL; |
|---|
| 650 | +} |
|---|
| 651 | + |
|---|
| 652 | +int mlxsw_sp_acl_rulei_act_police(struct mlxsw_sp *mlxsw_sp, |
|---|
| 653 | + struct mlxsw_sp_acl_rule_info *rulei, |
|---|
| 654 | + u32 index, u64 rate_bytes_ps, |
|---|
| 655 | + u32 burst, struct netlink_ext_ack *extack) |
|---|
| 656 | +{ |
|---|
| 657 | + int err; |
|---|
| 658 | + |
|---|
| 659 | + err = mlxsw_afa_block_append_police(rulei->act_block, index, |
|---|
| 660 | + rate_bytes_ps, burst, |
|---|
| 661 | + &rulei->policer_index, extack); |
|---|
| 662 | + if (err) |
|---|
| 663 | + return err; |
|---|
| 664 | + |
|---|
| 665 | + rulei->policer_index_valid = true; |
|---|
| 666 | + |
|---|
| 667 | + return 0; |
|---|
| 668 | +} |
|---|
| 669 | + |
|---|
| 608 | 670 | int mlxsw_sp_acl_rulei_act_count(struct mlxsw_sp *mlxsw_sp, |
|---|
| 609 | 671 | struct mlxsw_sp_acl_rule_info *rulei, |
|---|
| 610 | 672 | struct netlink_ext_ack *extack) |
|---|
| 611 | 673 | { |
|---|
| 612 | | - return mlxsw_afa_block_append_counter(rulei->act_block, |
|---|
| 613 | | - &rulei->counter_index, extack); |
|---|
| 674 | + int err; |
|---|
| 675 | + |
|---|
| 676 | + err = mlxsw_afa_block_append_counter(rulei->act_block, |
|---|
| 677 | + &rulei->counter_index, extack); |
|---|
| 678 | + if (err) |
|---|
| 679 | + return err; |
|---|
| 680 | + rulei->counter_valid = true; |
|---|
| 681 | + return 0; |
|---|
| 614 | 682 | } |
|---|
| 615 | 683 | |
|---|
| 616 | 684 | int mlxsw_sp_acl_rulei_act_fid_set(struct mlxsw_sp *mlxsw_sp, |
|---|
| .. | .. |
|---|
| 624 | 692 | mlxsw_sp_acl_rule_create(struct mlxsw_sp *mlxsw_sp, |
|---|
| 625 | 693 | struct mlxsw_sp_acl_ruleset *ruleset, |
|---|
| 626 | 694 | unsigned long cookie, |
|---|
| 695 | + struct mlxsw_afa_block *afa_block, |
|---|
| 627 | 696 | struct netlink_ext_ack *extack) |
|---|
| 628 | 697 | { |
|---|
| 629 | 698 | const struct mlxsw_sp_acl_profile_ops *ops = ruleset->ht_key.ops; |
|---|
| .. | .. |
|---|
| 631 | 700 | int err; |
|---|
| 632 | 701 | |
|---|
| 633 | 702 | mlxsw_sp_acl_ruleset_ref_inc(ruleset); |
|---|
| 634 | | - rule = kzalloc(sizeof(*rule) + ops->rule_priv_size(mlxsw_sp), |
|---|
| 703 | + rule = kzalloc(sizeof(*rule) + ops->rule_priv_size, |
|---|
| 635 | 704 | GFP_KERNEL); |
|---|
| 636 | 705 | if (!rule) { |
|---|
| 637 | 706 | err = -ENOMEM; |
|---|
| .. | .. |
|---|
| 640 | 709 | rule->cookie = cookie; |
|---|
| 641 | 710 | rule->ruleset = ruleset; |
|---|
| 642 | 711 | |
|---|
| 643 | | - rule->rulei = mlxsw_sp_acl_rulei_create(mlxsw_sp->acl); |
|---|
| 712 | + rule->rulei = mlxsw_sp_acl_rulei_create(mlxsw_sp->acl, afa_block); |
|---|
| 644 | 713 | if (IS_ERR(rule->rulei)) { |
|---|
| 645 | 714 | err = PTR_ERR(rule->rulei); |
|---|
| 646 | 715 | goto err_rulei_create; |
|---|
| .. | .. |
|---|
| 670 | 739 | { |
|---|
| 671 | 740 | struct mlxsw_sp_acl_ruleset *ruleset = rule->ruleset; |
|---|
| 672 | 741 | const struct mlxsw_sp_acl_profile_ops *ops = ruleset->ht_key.ops; |
|---|
| 742 | + struct mlxsw_sp_flow_block *block = ruleset->ht_key.block; |
|---|
| 673 | 743 | int err; |
|---|
| 674 | 744 | |
|---|
| 675 | 745 | err = ops->rule_add(mlxsw_sp, ruleset->priv, rule->priv, rule->rulei); |
|---|
| .. | .. |
|---|
| 687 | 757 | * one, to be directly bound to device. The rest of the |
|---|
| 688 | 758 | * rulesets are bound by "Goto action set". |
|---|
| 689 | 759 | */ |
|---|
| 690 | | - err = mlxsw_sp_acl_ruleset_block_bind(mlxsw_sp, ruleset, |
|---|
| 691 | | - ruleset->ht_key.block); |
|---|
| 760 | + err = mlxsw_sp_acl_ruleset_block_bind(mlxsw_sp, ruleset, block); |
|---|
| 692 | 761 | if (err) |
|---|
| 693 | 762 | goto err_ruleset_block_bind; |
|---|
| 694 | 763 | } |
|---|
| 695 | 764 | |
|---|
| 765 | + mutex_lock(&mlxsw_sp->acl->rules_lock); |
|---|
| 696 | 766 | list_add_tail(&rule->list, &mlxsw_sp->acl->rules); |
|---|
| 697 | | - ruleset->ht_key.block->rule_count++; |
|---|
| 767 | + mutex_unlock(&mlxsw_sp->acl->rules_lock); |
|---|
| 768 | + block->rule_count++; |
|---|
| 769 | + block->ingress_blocker_rule_count += rule->rulei->ingress_bind_blocker; |
|---|
| 770 | + block->egress_blocker_rule_count += rule->rulei->egress_bind_blocker; |
|---|
| 698 | 771 | return 0; |
|---|
| 699 | 772 | |
|---|
| 700 | 773 | err_ruleset_block_bind: |
|---|
| .. | .. |
|---|
| 710 | 783 | { |
|---|
| 711 | 784 | struct mlxsw_sp_acl_ruleset *ruleset = rule->ruleset; |
|---|
| 712 | 785 | const struct mlxsw_sp_acl_profile_ops *ops = ruleset->ht_key.ops; |
|---|
| 786 | + struct mlxsw_sp_flow_block *block = ruleset->ht_key.block; |
|---|
| 713 | 787 | |
|---|
| 714 | | - ruleset->ht_key.block->rule_count--; |
|---|
| 788 | + block->egress_blocker_rule_count -= rule->rulei->egress_bind_blocker; |
|---|
| 789 | + block->ingress_blocker_rule_count -= rule->rulei->ingress_bind_blocker; |
|---|
| 790 | + block->rule_count--; |
|---|
| 791 | + mutex_lock(&mlxsw_sp->acl->rules_lock); |
|---|
| 715 | 792 | list_del(&rule->list); |
|---|
| 793 | + mutex_unlock(&mlxsw_sp->acl->rules_lock); |
|---|
| 716 | 794 | if (!ruleset->ht_key.chain_index && |
|---|
| 717 | 795 | mlxsw_sp_acl_ruleset_is_singular(ruleset)) |
|---|
| 718 | | - mlxsw_sp_acl_ruleset_block_unbind(mlxsw_sp, ruleset, |
|---|
| 719 | | - ruleset->ht_key.block); |
|---|
| 796 | + mlxsw_sp_acl_ruleset_block_unbind(mlxsw_sp, ruleset, block); |
|---|
| 720 | 797 | rhashtable_remove_fast(&ruleset->rule_ht, &rule->ht_node, |
|---|
| 721 | 798 | mlxsw_sp_acl_rule_ht_params); |
|---|
| 722 | 799 | ops->rule_del(mlxsw_sp, rule->priv); |
|---|
| 800 | +} |
|---|
| 801 | + |
|---|
| 802 | +int mlxsw_sp_acl_rule_action_replace(struct mlxsw_sp *mlxsw_sp, |
|---|
| 803 | + struct mlxsw_sp_acl_rule *rule, |
|---|
| 804 | + struct mlxsw_afa_block *afa_block) |
|---|
| 805 | +{ |
|---|
| 806 | + struct mlxsw_sp_acl_ruleset *ruleset = rule->ruleset; |
|---|
| 807 | + const struct mlxsw_sp_acl_profile_ops *ops = ruleset->ht_key.ops; |
|---|
| 808 | + struct mlxsw_sp_acl_rule_info *rulei; |
|---|
| 809 | + |
|---|
| 810 | + rulei = mlxsw_sp_acl_rule_rulei(rule); |
|---|
| 811 | + rulei->act_block = afa_block; |
|---|
| 812 | + |
|---|
| 813 | + return ops->rule_action_replace(mlxsw_sp, rule->priv, rule->rulei); |
|---|
| 723 | 814 | } |
|---|
| 724 | 815 | |
|---|
| 725 | 816 | struct mlxsw_sp_acl_rule * |
|---|
| .. | .. |
|---|
| 758 | 849 | struct mlxsw_sp_acl_rule *rule; |
|---|
| 759 | 850 | int err; |
|---|
| 760 | 851 | |
|---|
| 761 | | - /* Protect internal structures from changes */ |
|---|
| 762 | | - rtnl_lock(); |
|---|
| 852 | + mutex_lock(&acl->rules_lock); |
|---|
| 763 | 853 | list_for_each_entry(rule, &acl->rules, list) { |
|---|
| 764 | 854 | err = mlxsw_sp_acl_rule_activity_update(acl->mlxsw_sp, |
|---|
| 765 | 855 | rule); |
|---|
| 766 | 856 | if (err) |
|---|
| 767 | 857 | goto err_rule_update; |
|---|
| 768 | 858 | } |
|---|
| 769 | | - rtnl_unlock(); |
|---|
| 859 | + mutex_unlock(&acl->rules_lock); |
|---|
| 770 | 860 | return 0; |
|---|
| 771 | 861 | |
|---|
| 772 | 862 | err_rule_update: |
|---|
| 773 | | - rtnl_unlock(); |
|---|
| 863 | + mutex_unlock(&acl->rules_lock); |
|---|
| 774 | 864 | return err; |
|---|
| 775 | 865 | } |
|---|
| 776 | 866 | |
|---|
| .. | .. |
|---|
| 782 | 872 | msecs_to_jiffies(interval)); |
|---|
| 783 | 873 | } |
|---|
| 784 | 874 | |
|---|
| 785 | | -static void mlxsw_sp_acl_rul_activity_update_work(struct work_struct *work) |
|---|
| 875 | +static void mlxsw_sp_acl_rule_activity_update_work(struct work_struct *work) |
|---|
| 786 | 876 | { |
|---|
| 787 | 877 | struct mlxsw_sp_acl *acl = container_of(work, struct mlxsw_sp_acl, |
|---|
| 788 | 878 | rule_activity_update.dw.work); |
|---|
| .. | .. |
|---|
| 797 | 887 | |
|---|
| 798 | 888 | int mlxsw_sp_acl_rule_get_stats(struct mlxsw_sp *mlxsw_sp, |
|---|
| 799 | 889 | struct mlxsw_sp_acl_rule *rule, |
|---|
| 800 | | - u64 *packets, u64 *bytes, u64 *last_use) |
|---|
| 890 | + u64 *packets, u64 *bytes, u64 *drops, |
|---|
| 891 | + u64 *last_use, |
|---|
| 892 | + enum flow_action_hw_stats *used_hw_stats) |
|---|
| 801 | 893 | |
|---|
| 802 | 894 | { |
|---|
| 895 | + enum mlxsw_sp_policer_type type = MLXSW_SP_POLICER_TYPE_SINGLE_RATE; |
|---|
| 803 | 896 | struct mlxsw_sp_acl_rule_info *rulei; |
|---|
| 804 | | - u64 current_packets; |
|---|
| 805 | | - u64 current_bytes; |
|---|
| 897 | + u64 current_packets = 0; |
|---|
| 898 | + u64 current_bytes = 0; |
|---|
| 899 | + u64 current_drops = 0; |
|---|
| 806 | 900 | int err; |
|---|
| 807 | 901 | |
|---|
| 808 | 902 | rulei = mlxsw_sp_acl_rule_rulei(rule); |
|---|
| 809 | | - err = mlxsw_sp_flow_counter_get(mlxsw_sp, rulei->counter_index, |
|---|
| 810 | | - ¤t_packets, ¤t_bytes); |
|---|
| 811 | | - if (err) |
|---|
| 812 | | - return err; |
|---|
| 813 | | - |
|---|
| 903 | + if (rulei->counter_valid) { |
|---|
| 904 | + err = mlxsw_sp_flow_counter_get(mlxsw_sp, rulei->counter_index, |
|---|
| 905 | + ¤t_packets, |
|---|
| 906 | + ¤t_bytes); |
|---|
| 907 | + if (err) |
|---|
| 908 | + return err; |
|---|
| 909 | + *used_hw_stats = FLOW_ACTION_HW_STATS_IMMEDIATE; |
|---|
| 910 | + } |
|---|
| 911 | + if (rulei->policer_index_valid) { |
|---|
| 912 | + err = mlxsw_sp_policer_drops_counter_get(mlxsw_sp, type, |
|---|
| 913 | + rulei->policer_index, |
|---|
| 914 | + ¤t_drops); |
|---|
| 915 | + if (err) |
|---|
| 916 | + return err; |
|---|
| 917 | + } |
|---|
| 814 | 918 | *packets = current_packets - rule->last_packets; |
|---|
| 815 | 919 | *bytes = current_bytes - rule->last_bytes; |
|---|
| 920 | + *drops = current_drops - rule->last_drops; |
|---|
| 816 | 921 | *last_use = rule->last_used; |
|---|
| 817 | 922 | |
|---|
| 818 | 923 | rule->last_bytes = current_bytes; |
|---|
| 819 | 924 | rule->last_packets = current_packets; |
|---|
| 925 | + rule->last_drops = current_drops; |
|---|
| 820 | 926 | |
|---|
| 821 | 927 | return 0; |
|---|
| 822 | 928 | } |
|---|
| .. | .. |
|---|
| 855 | 961 | acl->dummy_fid = fid; |
|---|
| 856 | 962 | |
|---|
| 857 | 963 | INIT_LIST_HEAD(&acl->rules); |
|---|
| 964 | + mutex_init(&acl->rules_lock); |
|---|
| 858 | 965 | err = mlxsw_sp_acl_tcam_init(mlxsw_sp, &acl->tcam); |
|---|
| 859 | 966 | if (err) |
|---|
| 860 | 967 | goto err_acl_ops_init; |
|---|
| 861 | 968 | |
|---|
| 862 | 969 | /* Create the delayed work for the rule activity_update */ |
|---|
| 863 | 970 | INIT_DELAYED_WORK(&acl->rule_activity_update.dw, |
|---|
| 864 | | - mlxsw_sp_acl_rul_activity_update_work); |
|---|
| 971 | + mlxsw_sp_acl_rule_activity_update_work); |
|---|
| 865 | 972 | acl->rule_activity_update.interval = MLXSW_SP_ACL_RULE_ACTIVITY_UPDATE_PERIOD_MS; |
|---|
| 866 | 973 | mlxsw_core_schedule_dw(&acl->rule_activity_update.dw, 0); |
|---|
| 867 | 974 | return 0; |
|---|
| 868 | 975 | |
|---|
| 869 | 976 | err_acl_ops_init: |
|---|
| 977 | + mutex_destroy(&acl->rules_lock); |
|---|
| 870 | 978 | mlxsw_sp_fid_put(fid); |
|---|
| 871 | 979 | err_fid_get: |
|---|
| 872 | 980 | rhashtable_destroy(&acl->ruleset_ht); |
|---|
| .. | .. |
|---|
| 883 | 991 | |
|---|
| 884 | 992 | cancel_delayed_work_sync(&mlxsw_sp->acl->rule_activity_update.dw); |
|---|
| 885 | 993 | mlxsw_sp_acl_tcam_fini(mlxsw_sp, &acl->tcam); |
|---|
| 994 | + mutex_destroy(&acl->rules_lock); |
|---|
| 886 | 995 | WARN_ON(!list_empty(&acl->rules)); |
|---|
| 887 | 996 | mlxsw_sp_fid_put(acl->dummy_fid); |
|---|
| 888 | 997 | rhashtable_destroy(&acl->ruleset_ht); |
|---|
| 889 | 998 | mlxsw_afk_destroy(acl->afk); |
|---|
| 890 | 999 | kfree(acl); |
|---|
| 891 | 1000 | } |
|---|
| 1001 | + |
|---|
| 1002 | +u32 mlxsw_sp_acl_region_rehash_intrvl_get(struct mlxsw_sp *mlxsw_sp) |
|---|
| 1003 | +{ |
|---|
| 1004 | + struct mlxsw_sp_acl *acl = mlxsw_sp->acl; |
|---|
| 1005 | + |
|---|
| 1006 | + return mlxsw_sp_acl_tcam_vregion_rehash_intrvl_get(mlxsw_sp, |
|---|
| 1007 | + &acl->tcam); |
|---|
| 1008 | +} |
|---|
| 1009 | + |
|---|
| 1010 | +int mlxsw_sp_acl_region_rehash_intrvl_set(struct mlxsw_sp *mlxsw_sp, u32 val) |
|---|
| 1011 | +{ |
|---|
| 1012 | + struct mlxsw_sp_acl *acl = mlxsw_sp->acl; |
|---|
| 1013 | + |
|---|
| 1014 | + return mlxsw_sp_acl_tcam_vregion_rehash_intrvl_set(mlxsw_sp, |
|---|
| 1015 | + &acl->tcam, val); |
|---|
| 1016 | +} |
|---|
| 1017 | + |
|---|
| 1018 | +struct mlxsw_sp_acl_rulei_ops mlxsw_sp1_acl_rulei_ops = { |
|---|
| 1019 | + .act_mangle_field = mlxsw_sp1_acl_rulei_act_mangle_field, |
|---|
| 1020 | +}; |
|---|
| 1021 | + |
|---|
| 1022 | +struct mlxsw_sp_acl_rulei_ops mlxsw_sp2_acl_rulei_ops = { |
|---|
| 1023 | + .act_mangle_field = mlxsw_sp2_acl_rulei_act_mangle_field, |
|---|
| 1024 | +}; |
|---|