mirror of https://gitee.com/openkylin/linux.git
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 <jiri@mellanox.com> Signed-off-by: Ido Schimmel <idosch@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
ec12165195
commit
6d19d2bdc8
|
@ -7,6 +7,9 @@
|
|||
#include <linux/errno.h>
|
||||
#include <linux/rhashtable.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/idr.h>
|
||||
#include <linux/refcount.h>
|
||||
#include <net/flow_offload.h>
|
||||
|
||||
#include "item.h"
|
||||
#include "trap.h"
|
||||
|
@ -63,6 +66,8 @@ struct mlxsw_afa {
|
|||
void *ops_priv;
|
||||
struct rhashtable set_ht;
|
||||
struct rhashtable fwd_entry_ht;
|
||||
struct rhashtable cookie_ht;
|
||||
struct idr cookie_idr;
|
||||
};
|
||||
|
||||
#define MLXSW_AFA_SET_LEN 0xA8
|
||||
|
@ -121,6 +126,55 @@ static const struct rhashtable_params mlxsw_afa_fwd_entry_ht_params = {
|
|||
.automatic_shrinking = true,
|
||||
};
|
||||
|
||||
struct mlxsw_afa_cookie {
|
||||
struct rhash_head ht_node;
|
||||
refcount_t ref_count;
|
||||
struct rcu_head rcu;
|
||||
u32 cookie_index;
|
||||
struct flow_action_cookie fa_cookie;
|
||||
};
|
||||
|
||||
static u32 mlxsw_afa_cookie_hash(const struct flow_action_cookie *fa_cookie,
|
||||
u32 seed)
|
||||
{
|
||||
return jhash2((u32 *) fa_cookie->cookie,
|
||||
fa_cookie->cookie_len / sizeof(u32), seed);
|
||||
}
|
||||
|
||||
static u32 mlxsw_afa_cookie_key_hashfn(const void *data, u32 len, u32 seed)
|
||||
{
|
||||
const struct flow_action_cookie *fa_cookie = data;
|
||||
|
||||
return mlxsw_afa_cookie_hash(fa_cookie, seed);
|
||||
}
|
||||
|
||||
static u32 mlxsw_afa_cookie_obj_hashfn(const void *data, u32 len, u32 seed)
|
||||
{
|
||||
const struct mlxsw_afa_cookie *cookie = data;
|
||||
|
||||
return mlxsw_afa_cookie_hash(&cookie->fa_cookie, seed);
|
||||
}
|
||||
|
||||
static int mlxsw_afa_cookie_obj_cmpfn(struct rhashtable_compare_arg *arg,
|
||||
const void *obj)
|
||||
{
|
||||
const struct flow_action_cookie *fa_cookie = arg->key;
|
||||
const struct mlxsw_afa_cookie *cookie = obj;
|
||||
|
||||
if (cookie->fa_cookie.cookie_len == fa_cookie->cookie_len)
|
||||
return memcmp(cookie->fa_cookie.cookie, fa_cookie->cookie,
|
||||
fa_cookie->cookie_len);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const struct rhashtable_params mlxsw_afa_cookie_ht_params = {
|
||||
.head_offset = offsetof(struct mlxsw_afa_cookie, ht_node),
|
||||
.hashfn = mlxsw_afa_cookie_key_hashfn,
|
||||
.obj_hashfn = mlxsw_afa_cookie_obj_hashfn,
|
||||
.obj_cmpfn = mlxsw_afa_cookie_obj_cmpfn,
|
||||
.automatic_shrinking = true,
|
||||
};
|
||||
|
||||
struct mlxsw_afa *mlxsw_afa_create(unsigned int max_acts_per_set,
|
||||
const struct mlxsw_afa_ops *ops,
|
||||
void *ops_priv)
|
||||
|
@ -138,11 +192,18 @@ struct mlxsw_afa *mlxsw_afa_create(unsigned int max_acts_per_set,
|
|||
&mlxsw_afa_fwd_entry_ht_params);
|
||||
if (err)
|
||||
goto err_fwd_entry_rhashtable_init;
|
||||
err = rhashtable_init(&mlxsw_afa->cookie_ht,
|
||||
&mlxsw_afa_cookie_ht_params);
|
||||
if (err)
|
||||
goto err_cookie_rhashtable_init;
|
||||
idr_init(&mlxsw_afa->cookie_idr);
|
||||
mlxsw_afa->max_acts_per_set = max_acts_per_set;
|
||||
mlxsw_afa->ops = ops;
|
||||
mlxsw_afa->ops_priv = ops_priv;
|
||||
return mlxsw_afa;
|
||||
|
||||
err_cookie_rhashtable_init:
|
||||
rhashtable_destroy(&mlxsw_afa->fwd_entry_ht);
|
||||
err_fwd_entry_rhashtable_init:
|
||||
rhashtable_destroy(&mlxsw_afa->set_ht);
|
||||
err_set_rhashtable_init:
|
||||
|
@ -153,6 +214,9 @@ EXPORT_SYMBOL(mlxsw_afa_create);
|
|||
|
||||
void mlxsw_afa_destroy(struct mlxsw_afa *mlxsw_afa)
|
||||
{
|
||||
WARN_ON(!idr_is_empty(&mlxsw_afa->cookie_idr));
|
||||
idr_destroy(&mlxsw_afa->cookie_idr);
|
||||
rhashtable_destroy(&mlxsw_afa->cookie_ht);
|
||||
rhashtable_destroy(&mlxsw_afa->fwd_entry_ht);
|
||||
rhashtable_destroy(&mlxsw_afa->set_ht);
|
||||
kfree(mlxsw_afa);
|
||||
|
@ -627,6 +691,135 @@ mlxsw_afa_counter_create(struct mlxsw_afa_block *block)
|
|||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
/* 20 bits is a maximum that hardware can handle in trap with userdef action
|
||||
* and carry along with the trapped packet.
|
||||
*/
|
||||
#define MLXSW_AFA_COOKIE_INDEX_BITS 20
|
||||
#define MLXSW_AFA_COOKIE_INDEX_MAX ((1 << MLXSW_AFA_COOKIE_INDEX_BITS) - 1)
|
||||
|
||||
static struct mlxsw_afa_cookie *
|
||||
mlxsw_afa_cookie_create(struct mlxsw_afa *mlxsw_afa,
|
||||
const struct flow_action_cookie *fa_cookie)
|
||||
{
|
||||
struct mlxsw_afa_cookie *cookie;
|
||||
u32 cookie_index;
|
||||
int err;
|
||||
|
||||
cookie = kzalloc(sizeof(*cookie) + fa_cookie->cookie_len, GFP_KERNEL);
|
||||
if (!cookie)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
refcount_set(&cookie->ref_count, 1);
|
||||
memcpy(&cookie->fa_cookie, fa_cookie,
|
||||
sizeof(*fa_cookie) + fa_cookie->cookie_len);
|
||||
|
||||
err = rhashtable_insert_fast(&mlxsw_afa->cookie_ht, &cookie->ht_node,
|
||||
mlxsw_afa_cookie_ht_params);
|
||||
if (err)
|
||||
goto err_rhashtable_insert;
|
||||
|
||||
/* Start cookie indexes with 1. Leave the 0 index unused. Packets
|
||||
* that come from the HW which are not dropped by drop-with-cookie
|
||||
* action are going to pass cookie_index 0 to lookup.
|
||||
*/
|
||||
cookie_index = 1;
|
||||
err = idr_alloc_u32(&mlxsw_afa->cookie_idr, cookie, &cookie_index,
|
||||
MLXSW_AFA_COOKIE_INDEX_MAX, GFP_KERNEL);
|
||||
if (err)
|
||||
goto err_idr_alloc;
|
||||
cookie->cookie_index = cookie_index;
|
||||
return cookie;
|
||||
|
||||
err_idr_alloc:
|
||||
rhashtable_remove_fast(&mlxsw_afa->cookie_ht, &cookie->ht_node,
|
||||
mlxsw_afa_cookie_ht_params);
|
||||
err_rhashtable_insert:
|
||||
kfree(cookie);
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
static void mlxsw_afa_cookie_destroy(struct mlxsw_afa *mlxsw_afa,
|
||||
struct mlxsw_afa_cookie *cookie)
|
||||
{
|
||||
idr_remove(&mlxsw_afa->cookie_idr, cookie->cookie_index);
|
||||
rhashtable_remove_fast(&mlxsw_afa->cookie_ht, &cookie->ht_node,
|
||||
mlxsw_afa_cookie_ht_params);
|
||||
kfree_rcu(cookie, rcu);
|
||||
}
|
||||
|
||||
static struct mlxsw_afa_cookie *
|
||||
mlxsw_afa_cookie_get(struct mlxsw_afa *mlxsw_afa,
|
||||
const struct flow_action_cookie *fa_cookie)
|
||||
{
|
||||
struct mlxsw_afa_cookie *cookie;
|
||||
|
||||
cookie = rhashtable_lookup_fast(&mlxsw_afa->cookie_ht, fa_cookie,
|
||||
mlxsw_afa_cookie_ht_params);
|
||||
if (cookie) {
|
||||
refcount_inc(&cookie->ref_count);
|
||||
return cookie;
|
||||
}
|
||||
return mlxsw_afa_cookie_create(mlxsw_afa, fa_cookie);
|
||||
}
|
||||
|
||||
static void mlxsw_afa_cookie_put(struct mlxsw_afa *mlxsw_afa,
|
||||
struct mlxsw_afa_cookie *cookie)
|
||||
{
|
||||
if (!refcount_dec_and_test(&cookie->ref_count))
|
||||
return;
|
||||
mlxsw_afa_cookie_destroy(mlxsw_afa, cookie);
|
||||
}
|
||||
|
||||
struct mlxsw_afa_cookie_ref {
|
||||
struct mlxsw_afa_resource resource;
|
||||
struct mlxsw_afa_cookie *cookie;
|
||||
};
|
||||
|
||||
static void
|
||||
mlxsw_afa_cookie_ref_destroy(struct mlxsw_afa_block *block,
|
||||
struct mlxsw_afa_cookie_ref *cookie_ref)
|
||||
{
|
||||
mlxsw_afa_resource_del(&cookie_ref->resource);
|
||||
mlxsw_afa_cookie_put(block->afa, cookie_ref->cookie);
|
||||
kfree(cookie_ref);
|
||||
}
|
||||
|
||||
static void
|
||||
mlxsw_afa_cookie_ref_destructor(struct mlxsw_afa_block *block,
|
||||
struct mlxsw_afa_resource *resource)
|
||||
{
|
||||
struct mlxsw_afa_cookie_ref *cookie_ref;
|
||||
|
||||
cookie_ref = container_of(resource, struct mlxsw_afa_cookie_ref,
|
||||
resource);
|
||||
mlxsw_afa_cookie_ref_destroy(block, cookie_ref);
|
||||
}
|
||||
|
||||
static struct mlxsw_afa_cookie_ref *
|
||||
mlxsw_afa_cookie_ref_create(struct mlxsw_afa_block *block,
|
||||
const struct flow_action_cookie *fa_cookie)
|
||||
{
|
||||
struct mlxsw_afa_cookie_ref *cookie_ref;
|
||||
struct mlxsw_afa_cookie *cookie;
|
||||
int err;
|
||||
|
||||
cookie_ref = kzalloc(sizeof(*cookie_ref), GFP_KERNEL);
|
||||
if (!cookie_ref)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
cookie = mlxsw_afa_cookie_get(block->afa, fa_cookie);
|
||||
if (IS_ERR(cookie)) {
|
||||
err = PTR_ERR(cookie);
|
||||
goto err_cookie_get;
|
||||
}
|
||||
cookie_ref->cookie = cookie;
|
||||
cookie_ref->resource.destructor = mlxsw_afa_cookie_ref_destructor;
|
||||
mlxsw_afa_resource_add(block, &cookie_ref->resource);
|
||||
return cookie_ref;
|
||||
|
||||
err_cookie_get:
|
||||
kfree(cookie_ref);
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
#define MLXSW_AFA_ONE_ACTION_LEN 32
|
||||
#define MLXSW_AFA_PAYLOAD_OFFSET 4
|
||||
|
||||
|
@ -839,7 +1032,8 @@ mlxsw_afa_trap_mirror_pack(char *payload, bool mirror_enable,
|
|||
mlxsw_afa_trap_mirror_agent_set(payload, mirror_agent);
|
||||
}
|
||||
|
||||
int mlxsw_afa_block_append_drop(struct mlxsw_afa_block *block, bool ingress)
|
||||
static int mlxsw_afa_block_append_drop_plain(struct mlxsw_afa_block *block,
|
||||
bool ingress)
|
||||
{
|
||||
char *act = mlxsw_afa_block_append_action(block, MLXSW_AFA_TRAP_CODE,
|
||||
MLXSW_AFA_TRAP_SIZE);
|
||||
|
@ -852,6 +1046,53 @@ int mlxsw_afa_block_append_drop(struct mlxsw_afa_block *block, bool ingress)
|
|||
MLXSW_TRAP_ID_DISCARD_EGRESS_ACL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
mlxsw_afa_block_append_drop_with_cookie(struct mlxsw_afa_block *block,
|
||||
bool ingress,
|
||||
const struct flow_action_cookie *fa_cookie,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct mlxsw_afa_cookie_ref *cookie_ref;
|
||||
u32 cookie_index;
|
||||
char *act;
|
||||
int err;
|
||||
|
||||
cookie_ref = mlxsw_afa_cookie_ref_create(block, fa_cookie);
|
||||
if (IS_ERR(cookie_ref)) {
|
||||
NL_SET_ERR_MSG_MOD(extack, "Cannot create cookie for drop action");
|
||||
return PTR_ERR(cookie_ref);
|
||||
}
|
||||
cookie_index = cookie_ref->cookie->cookie_index;
|
||||
|
||||
act = mlxsw_afa_block_append_action(block, MLXSW_AFA_TRAPWU_CODE,
|
||||
MLXSW_AFA_TRAPWU_SIZE);
|
||||
if (IS_ERR(act)) {
|
||||
NL_SET_ERR_MSG_MOD(extack, "Cannot append drop with cookie action");
|
||||
err = PTR_ERR(act);
|
||||
goto err_append_action;
|
||||
}
|
||||
mlxsw_afa_trapwu_pack(act, MLXSW_AFA_TRAP_TRAP_ACTION_TRAP,
|
||||
MLXSW_AFA_TRAP_FORWARD_ACTION_DISCARD,
|
||||
ingress ? MLXSW_TRAP_ID_DISCARD_INGRESS_ACL :
|
||||
MLXSW_TRAP_ID_DISCARD_EGRESS_ACL,
|
||||
cookie_index);
|
||||
return 0;
|
||||
|
||||
err_append_action:
|
||||
mlxsw_afa_cookie_ref_destroy(block, cookie_ref);
|
||||
return err;
|
||||
}
|
||||
|
||||
int mlxsw_afa_block_append_drop(struct mlxsw_afa_block *block, bool ingress,
|
||||
const struct flow_action_cookie *fa_cookie,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
return fa_cookie ?
|
||||
mlxsw_afa_block_append_drop_with_cookie(block, ingress,
|
||||
fa_cookie, extack) :
|
||||
mlxsw_afa_block_append_drop_plain(block, ingress);
|
||||
}
|
||||
EXPORT_SYMBOL(mlxsw_afa_block_append_drop);
|
||||
|
||||
int mlxsw_afa_block_append_trap(struct mlxsw_afa_block *block, u16 trap_id)
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include <linux/types.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <net/flow_offload.h>
|
||||
|
||||
struct mlxsw_afa;
|
||||
struct mlxsw_afa_block;
|
||||
|
@ -42,7 +43,9 @@ int mlxsw_afa_block_activity_get(struct mlxsw_afa_block *block, bool *activity);
|
|||
int mlxsw_afa_block_continue(struct mlxsw_afa_block *block);
|
||||
int mlxsw_afa_block_jump(struct mlxsw_afa_block *block, u16 group_id);
|
||||
int mlxsw_afa_block_terminate(struct mlxsw_afa_block *block);
|
||||
int mlxsw_afa_block_append_drop(struct mlxsw_afa_block *block, bool ingress);
|
||||
int mlxsw_afa_block_append_drop(struct mlxsw_afa_block *block, bool ingress,
|
||||
const struct flow_action_cookie *fa_cookie,
|
||||
struct netlink_ext_ack *extack);
|
||||
int mlxsw_afa_block_append_trap(struct mlxsw_afa_block *block, u16 trap_id);
|
||||
int mlxsw_afa_block_append_trap_and_forward(struct mlxsw_afa_block *block,
|
||||
u16 trap_id);
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include <net/pkt_cls.h>
|
||||
#include <net/red.h>
|
||||
#include <net/vxlan.h>
|
||||
#include <net/flow_offload.h>
|
||||
|
||||
#include "port.h"
|
||||
#include "core.h"
|
||||
|
@ -726,7 +727,9 @@ int mlxsw_sp_acl_rulei_act_jump(struct mlxsw_sp_acl_rule_info *rulei,
|
|||
u16 group_id);
|
||||
int mlxsw_sp_acl_rulei_act_terminate(struct mlxsw_sp_acl_rule_info *rulei);
|
||||
int mlxsw_sp_acl_rulei_act_drop(struct mlxsw_sp_acl_rule_info *rulei,
|
||||
bool ingress);
|
||||
bool ingress,
|
||||
const struct flow_action_cookie *fa_cookie,
|
||||
struct netlink_ext_ack *extack);
|
||||
int mlxsw_sp_acl_rulei_act_trap(struct mlxsw_sp_acl_rule_info *rulei);
|
||||
int mlxsw_sp_acl_rulei_act_mirror(struct mlxsw_sp *mlxsw_sp,
|
||||
struct mlxsw_sp_acl_rule_info *rulei,
|
||||
|
|
|
@ -536,9 +536,12 @@ int mlxsw_sp_acl_rulei_act_terminate(struct mlxsw_sp_acl_rule_info *rulei)
|
|||
}
|
||||
|
||||
int mlxsw_sp_acl_rulei_act_drop(struct mlxsw_sp_acl_rule_info *rulei,
|
||||
bool ingress)
|
||||
bool ingress,
|
||||
const struct flow_action_cookie *fa_cookie,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
return mlxsw_afa_block_append_drop(rulei->act_block, ingress);
|
||||
return mlxsw_afa_block_append_drop(rulei->act_block, ingress,
|
||||
fa_cookie, extack);
|
||||
}
|
||||
|
||||
int mlxsw_sp_acl_rulei_act_trap(struct mlxsw_sp_acl_rule_info *rulei)
|
||||
|
|
|
@ -49,7 +49,8 @@ static int mlxsw_sp_flower_parse_actions(struct mlxsw_sp *mlxsw_sp,
|
|||
return -EOPNOTSUPP;
|
||||
}
|
||||
ingress = mlxsw_sp_acl_block_is_ingress_bound(block);
|
||||
err = mlxsw_sp_acl_rulei_act_drop(rulei, ingress);
|
||||
err = mlxsw_sp_acl_rulei_act_drop(rulei, ingress,
|
||||
act->cookie, extack);
|
||||
if (err) {
|
||||
NL_SET_ERR_MSG_MOD(extack, "Cannot append drop action");
|
||||
return err;
|
||||
|
|
Loading…
Reference in New Issue