Skip to content

Commit 6d19d2b

Browse files
jpirkodavem330
authored andcommitted
mlxsw: core_acl_flex_actions: Implement flow_offload action cookie offload
Track cookies coming down to driver by flow_offload. Assign a cookie_index to each unique cookie binary. Use previously defined "Trap with userdef" flex action to ask HW to pass cookie_index alongside with the dropped packets. Signed-off-by: Jiri Pirko <[email protected]> Signed-off-by: Ido Schimmel <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent ec12165 commit 6d19d2b

File tree

5 files changed

+257
-6
lines changed

5 files changed

+257
-6
lines changed

drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_actions.c

Lines changed: 242 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
#include <linux/errno.h>
88
#include <linux/rhashtable.h>
99
#include <linux/list.h>
10+
#include <linux/idr.h>
11+
#include <linux/refcount.h>
12+
#include <net/flow_offload.h>
1013

1114
#include "item.h"
1215
#include "trap.h"
@@ -63,6 +66,8 @@ struct mlxsw_afa {
6366
void *ops_priv;
6467
struct rhashtable set_ht;
6568
struct rhashtable fwd_entry_ht;
69+
struct rhashtable cookie_ht;
70+
struct idr cookie_idr;
6671
};
6772

6873
#define MLXSW_AFA_SET_LEN 0xA8
@@ -121,6 +126,55 @@ static const struct rhashtable_params mlxsw_afa_fwd_entry_ht_params = {
121126
.automatic_shrinking = true,
122127
};
123128

129+
struct mlxsw_afa_cookie {
130+
struct rhash_head ht_node;
131+
refcount_t ref_count;
132+
struct rcu_head rcu;
133+
u32 cookie_index;
134+
struct flow_action_cookie fa_cookie;
135+
};
136+
137+
static u32 mlxsw_afa_cookie_hash(const struct flow_action_cookie *fa_cookie,
138+
u32 seed)
139+
{
140+
return jhash2((u32 *) fa_cookie->cookie,
141+
fa_cookie->cookie_len / sizeof(u32), seed);
142+
}
143+
144+
static u32 mlxsw_afa_cookie_key_hashfn(const void *data, u32 len, u32 seed)
145+
{
146+
const struct flow_action_cookie *fa_cookie = data;
147+
148+
return mlxsw_afa_cookie_hash(fa_cookie, seed);
149+
}
150+
151+
static u32 mlxsw_afa_cookie_obj_hashfn(const void *data, u32 len, u32 seed)
152+
{
153+
const struct mlxsw_afa_cookie *cookie = data;
154+
155+
return mlxsw_afa_cookie_hash(&cookie->fa_cookie, seed);
156+
}
157+
158+
static int mlxsw_afa_cookie_obj_cmpfn(struct rhashtable_compare_arg *arg,
159+
const void *obj)
160+
{
161+
const struct flow_action_cookie *fa_cookie = arg->key;
162+
const struct mlxsw_afa_cookie *cookie = obj;
163+
164+
if (cookie->fa_cookie.cookie_len == fa_cookie->cookie_len)
165+
return memcmp(cookie->fa_cookie.cookie, fa_cookie->cookie,
166+
fa_cookie->cookie_len);
167+
return 1;
168+
}
169+
170+
static const struct rhashtable_params mlxsw_afa_cookie_ht_params = {
171+
.head_offset = offsetof(struct mlxsw_afa_cookie, ht_node),
172+
.hashfn = mlxsw_afa_cookie_key_hashfn,
173+
.obj_hashfn = mlxsw_afa_cookie_obj_hashfn,
174+
.obj_cmpfn = mlxsw_afa_cookie_obj_cmpfn,
175+
.automatic_shrinking = true,
176+
};
177+
124178
struct mlxsw_afa *mlxsw_afa_create(unsigned int max_acts_per_set,
125179
const struct mlxsw_afa_ops *ops,
126180
void *ops_priv)
@@ -138,11 +192,18 @@ struct mlxsw_afa *mlxsw_afa_create(unsigned int max_acts_per_set,
138192
&mlxsw_afa_fwd_entry_ht_params);
139193
if (err)
140194
goto err_fwd_entry_rhashtable_init;
195+
err = rhashtable_init(&mlxsw_afa->cookie_ht,
196+
&mlxsw_afa_cookie_ht_params);
197+
if (err)
198+
goto err_cookie_rhashtable_init;
199+
idr_init(&mlxsw_afa->cookie_idr);
141200
mlxsw_afa->max_acts_per_set = max_acts_per_set;
142201
mlxsw_afa->ops = ops;
143202
mlxsw_afa->ops_priv = ops_priv;
144203
return mlxsw_afa;
145204

205+
err_cookie_rhashtable_init:
206+
rhashtable_destroy(&mlxsw_afa->fwd_entry_ht);
146207
err_fwd_entry_rhashtable_init:
147208
rhashtable_destroy(&mlxsw_afa->set_ht);
148209
err_set_rhashtable_init:
@@ -153,6 +214,9 @@ EXPORT_SYMBOL(mlxsw_afa_create);
153214

154215
void mlxsw_afa_destroy(struct mlxsw_afa *mlxsw_afa)
155216
{
217+
WARN_ON(!idr_is_empty(&mlxsw_afa->cookie_idr));
218+
idr_destroy(&mlxsw_afa->cookie_idr);
219+
rhashtable_destroy(&mlxsw_afa->cookie_ht);
156220
rhashtable_destroy(&mlxsw_afa->fwd_entry_ht);
157221
rhashtable_destroy(&mlxsw_afa->set_ht);
158222
kfree(mlxsw_afa);
@@ -627,6 +691,135 @@ mlxsw_afa_counter_create(struct mlxsw_afa_block *block)
627691
return ERR_PTR(err);
628692
}
629693

694+
/* 20 bits is a maximum that hardware can handle in trap with userdef action
695+
* and carry along with the trapped packet.
696+
*/
697+
#define MLXSW_AFA_COOKIE_INDEX_BITS 20
698+
#define MLXSW_AFA_COOKIE_INDEX_MAX ((1 << MLXSW_AFA_COOKIE_INDEX_BITS) - 1)
699+
700+
static struct mlxsw_afa_cookie *
701+
mlxsw_afa_cookie_create(struct mlxsw_afa *mlxsw_afa,
702+
const struct flow_action_cookie *fa_cookie)
703+
{
704+
struct mlxsw_afa_cookie *cookie;
705+
u32 cookie_index;
706+
int err;
707+
708+
cookie = kzalloc(sizeof(*cookie) + fa_cookie->cookie_len, GFP_KERNEL);
709+
if (!cookie)
710+
return ERR_PTR(-ENOMEM);
711+
refcount_set(&cookie->ref_count, 1);
712+
memcpy(&cookie->fa_cookie, fa_cookie,
713+
sizeof(*fa_cookie) + fa_cookie->cookie_len);
714+
715+
err = rhashtable_insert_fast(&mlxsw_afa->cookie_ht, &cookie->ht_node,
716+
mlxsw_afa_cookie_ht_params);
717+
if (err)
718+
goto err_rhashtable_insert;
719+
720+
/* Start cookie indexes with 1. Leave the 0 index unused. Packets
721+
* that come from the HW which are not dropped by drop-with-cookie
722+
* action are going to pass cookie_index 0 to lookup.
723+
*/
724+
cookie_index = 1;
725+
err = idr_alloc_u32(&mlxsw_afa->cookie_idr, cookie, &cookie_index,
726+
MLXSW_AFA_COOKIE_INDEX_MAX, GFP_KERNEL);
727+
if (err)
728+
goto err_idr_alloc;
729+
cookie->cookie_index = cookie_index;
730+
return cookie;
731+
732+
err_idr_alloc:
733+
rhashtable_remove_fast(&mlxsw_afa->cookie_ht, &cookie->ht_node,
734+
mlxsw_afa_cookie_ht_params);
735+
err_rhashtable_insert:
736+
kfree(cookie);
737+
return ERR_PTR(err);
738+
}
739+
740+
static void mlxsw_afa_cookie_destroy(struct mlxsw_afa *mlxsw_afa,
741+
struct mlxsw_afa_cookie *cookie)
742+
{
743+
idr_remove(&mlxsw_afa->cookie_idr, cookie->cookie_index);
744+
rhashtable_remove_fast(&mlxsw_afa->cookie_ht, &cookie->ht_node,
745+
mlxsw_afa_cookie_ht_params);
746+
kfree_rcu(cookie, rcu);
747+
}
748+
749+
static struct mlxsw_afa_cookie *
750+
mlxsw_afa_cookie_get(struct mlxsw_afa *mlxsw_afa,
751+
const struct flow_action_cookie *fa_cookie)
752+
{
753+
struct mlxsw_afa_cookie *cookie;
754+
755+
cookie = rhashtable_lookup_fast(&mlxsw_afa->cookie_ht, fa_cookie,
756+
mlxsw_afa_cookie_ht_params);
757+
if (cookie) {
758+
refcount_inc(&cookie->ref_count);
759+
return cookie;
760+
}
761+
return mlxsw_afa_cookie_create(mlxsw_afa, fa_cookie);
762+
}
763+
764+
static void mlxsw_afa_cookie_put(struct mlxsw_afa *mlxsw_afa,
765+
struct mlxsw_afa_cookie *cookie)
766+
{
767+
if (!refcount_dec_and_test(&cookie->ref_count))
768+
return;
769+
mlxsw_afa_cookie_destroy(mlxsw_afa, cookie);
770+
}
771+
772+
struct mlxsw_afa_cookie_ref {
773+
struct mlxsw_afa_resource resource;
774+
struct mlxsw_afa_cookie *cookie;
775+
};
776+
777+
static void
778+
mlxsw_afa_cookie_ref_destroy(struct mlxsw_afa_block *block,
779+
struct mlxsw_afa_cookie_ref *cookie_ref)
780+
{
781+
mlxsw_afa_resource_del(&cookie_ref->resource);
782+
mlxsw_afa_cookie_put(block->afa, cookie_ref->cookie);
783+
kfree(cookie_ref);
784+
}
785+
786+
static void
787+
mlxsw_afa_cookie_ref_destructor(struct mlxsw_afa_block *block,
788+
struct mlxsw_afa_resource *resource)
789+
{
790+
struct mlxsw_afa_cookie_ref *cookie_ref;
791+
792+
cookie_ref = container_of(resource, struct mlxsw_afa_cookie_ref,
793+
resource);
794+
mlxsw_afa_cookie_ref_destroy(block, cookie_ref);
795+
}
796+
797+
static struct mlxsw_afa_cookie_ref *
798+
mlxsw_afa_cookie_ref_create(struct mlxsw_afa_block *block,
799+
const struct flow_action_cookie *fa_cookie)
800+
{
801+
struct mlxsw_afa_cookie_ref *cookie_ref;
802+
struct mlxsw_afa_cookie *cookie;
803+
int err;
804+
805+
cookie_ref = kzalloc(sizeof(*cookie_ref), GFP_KERNEL);
806+
if (!cookie_ref)
807+
return ERR_PTR(-ENOMEM);
808+
cookie = mlxsw_afa_cookie_get(block->afa, fa_cookie);
809+
if (IS_ERR(cookie)) {
810+
err = PTR_ERR(cookie);
811+
goto err_cookie_get;
812+
}
813+
cookie_ref->cookie = cookie;
814+
cookie_ref->resource.destructor = mlxsw_afa_cookie_ref_destructor;
815+
mlxsw_afa_resource_add(block, &cookie_ref->resource);
816+
return cookie_ref;
817+
818+
err_cookie_get:
819+
kfree(cookie_ref);
820+
return ERR_PTR(err);
821+
}
822+
630823
#define MLXSW_AFA_ONE_ACTION_LEN 32
631824
#define MLXSW_AFA_PAYLOAD_OFFSET 4
632825

@@ -839,7 +1032,8 @@ mlxsw_afa_trap_mirror_pack(char *payload, bool mirror_enable,
8391032
mlxsw_afa_trap_mirror_agent_set(payload, mirror_agent);
8401033
}
8411034

842-
int mlxsw_afa_block_append_drop(struct mlxsw_afa_block *block, bool ingress)
1035+
static int mlxsw_afa_block_append_drop_plain(struct mlxsw_afa_block *block,
1036+
bool ingress)
8431037
{
8441038
char *act = mlxsw_afa_block_append_action(block, MLXSW_AFA_TRAP_CODE,
8451039
MLXSW_AFA_TRAP_SIZE);
@@ -852,6 +1046,53 @@ int mlxsw_afa_block_append_drop(struct mlxsw_afa_block *block, bool ingress)
8521046
MLXSW_TRAP_ID_DISCARD_EGRESS_ACL);
8531047
return 0;
8541048
}
1049+
1050+
static int
1051+
mlxsw_afa_block_append_drop_with_cookie(struct mlxsw_afa_block *block,
1052+
bool ingress,
1053+
const struct flow_action_cookie *fa_cookie,
1054+
struct netlink_ext_ack *extack)
1055+
{
1056+
struct mlxsw_afa_cookie_ref *cookie_ref;
1057+
u32 cookie_index;
1058+
char *act;
1059+
int err;
1060+
1061+
cookie_ref = mlxsw_afa_cookie_ref_create(block, fa_cookie);
1062+
if (IS_ERR(cookie_ref)) {
1063+
NL_SET_ERR_MSG_MOD(extack, "Cannot create cookie for drop action");
1064+
return PTR_ERR(cookie_ref);
1065+
}
1066+
cookie_index = cookie_ref->cookie->cookie_index;
1067+
1068+
act = mlxsw_afa_block_append_action(block, MLXSW_AFA_TRAPWU_CODE,
1069+
MLXSW_AFA_TRAPWU_SIZE);
1070+
if (IS_ERR(act)) {
1071+
NL_SET_ERR_MSG_MOD(extack, "Cannot append drop with cookie action");
1072+
err = PTR_ERR(act);
1073+
goto err_append_action;
1074+
}
1075+
mlxsw_afa_trapwu_pack(act, MLXSW_AFA_TRAP_TRAP_ACTION_TRAP,
1076+
MLXSW_AFA_TRAP_FORWARD_ACTION_DISCARD,
1077+
ingress ? MLXSW_TRAP_ID_DISCARD_INGRESS_ACL :
1078+
MLXSW_TRAP_ID_DISCARD_EGRESS_ACL,
1079+
cookie_index);
1080+
return 0;
1081+
1082+
err_append_action:
1083+
mlxsw_afa_cookie_ref_destroy(block, cookie_ref);
1084+
return err;
1085+
}
1086+
1087+
int mlxsw_afa_block_append_drop(struct mlxsw_afa_block *block, bool ingress,
1088+
const struct flow_action_cookie *fa_cookie,
1089+
struct netlink_ext_ack *extack)
1090+
{
1091+
return fa_cookie ?
1092+
mlxsw_afa_block_append_drop_with_cookie(block, ingress,
1093+
fa_cookie, extack) :
1094+
mlxsw_afa_block_append_drop_plain(block, ingress);
1095+
}
8551096
EXPORT_SYMBOL(mlxsw_afa_block_append_drop);
8561097

8571098
int mlxsw_afa_block_append_trap(struct mlxsw_afa_block *block, u16 trap_id)

drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_actions.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
#include <linux/types.h>
88
#include <linux/netdevice.h>
9+
#include <net/flow_offload.h>
910

1011
struct mlxsw_afa;
1112
struct mlxsw_afa_block;
@@ -42,7 +43,9 @@ int mlxsw_afa_block_activity_get(struct mlxsw_afa_block *block, bool *activity);
4243
int mlxsw_afa_block_continue(struct mlxsw_afa_block *block);
4344
int mlxsw_afa_block_jump(struct mlxsw_afa_block *block, u16 group_id);
4445
int mlxsw_afa_block_terminate(struct mlxsw_afa_block *block);
45-
int mlxsw_afa_block_append_drop(struct mlxsw_afa_block *block, bool ingress);
46+
int mlxsw_afa_block_append_drop(struct mlxsw_afa_block *block, bool ingress,
47+
const struct flow_action_cookie *fa_cookie,
48+
struct netlink_ext_ack *extack);
4649
int mlxsw_afa_block_append_trap(struct mlxsw_afa_block *block, u16 trap_id);
4750
int mlxsw_afa_block_append_trap_and_forward(struct mlxsw_afa_block *block,
4851
u16 trap_id);

drivers/net/ethernet/mellanox/mlxsw/spectrum.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include <net/pkt_cls.h>
2020
#include <net/red.h>
2121
#include <net/vxlan.h>
22+
#include <net/flow_offload.h>
2223

2324
#include "port.h"
2425
#include "core.h"
@@ -726,7 +727,9 @@ int mlxsw_sp_acl_rulei_act_jump(struct mlxsw_sp_acl_rule_info *rulei,
726727
u16 group_id);
727728
int mlxsw_sp_acl_rulei_act_terminate(struct mlxsw_sp_acl_rule_info *rulei);
728729
int mlxsw_sp_acl_rulei_act_drop(struct mlxsw_sp_acl_rule_info *rulei,
729-
bool ingress);
730+
bool ingress,
731+
const struct flow_action_cookie *fa_cookie,
732+
struct netlink_ext_ack *extack);
730733
int mlxsw_sp_acl_rulei_act_trap(struct mlxsw_sp_acl_rule_info *rulei);
731734
int mlxsw_sp_acl_rulei_act_mirror(struct mlxsw_sp *mlxsw_sp,
732735
struct mlxsw_sp_acl_rule_info *rulei,

drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -536,9 +536,12 @@ int mlxsw_sp_acl_rulei_act_terminate(struct mlxsw_sp_acl_rule_info *rulei)
536536
}
537537

538538
int mlxsw_sp_acl_rulei_act_drop(struct mlxsw_sp_acl_rule_info *rulei,
539-
bool ingress)
539+
bool ingress,
540+
const struct flow_action_cookie *fa_cookie,
541+
struct netlink_ext_ack *extack)
540542
{
541-
return mlxsw_afa_block_append_drop(rulei->act_block, ingress);
543+
return mlxsw_afa_block_append_drop(rulei->act_block, ingress,
544+
fa_cookie, extack);
542545
}
543546

544547
int mlxsw_sp_acl_rulei_act_trap(struct mlxsw_sp_acl_rule_info *rulei)

drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ static int mlxsw_sp_flower_parse_actions(struct mlxsw_sp *mlxsw_sp,
4949
return -EOPNOTSUPP;
5050
}
5151
ingress = mlxsw_sp_acl_block_is_ingress_bound(block);
52-
err = mlxsw_sp_acl_rulei_act_drop(rulei, ingress);
52+
err = mlxsw_sp_acl_rulei_act_drop(rulei, ingress,
53+
act->cookie, extack);
5354
if (err) {
5455
NL_SET_ERR_MSG_MOD(extack, "Cannot append drop action");
5556
return err;

0 commit comments

Comments
 (0)