.. | .. |
---|
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 | +}; |
---|