Skip to content

Commit

Permalink
net/mlx5: E-Switch, Refactor eswitch ingress acl codes
Browse files Browse the repository at this point in the history
Restructure the eswitch ingress acl codes into eswitch directory
and different files:
. Acl ingress helper functions to acl_helper.c/h
. Acl ingress functions used in offloads mode to acl_ingress_ofld.c
. Acl ingress functions used in legacy mode to acl_ingress_lgy.c

This patch does not change any functionality.

Signed-off-by: Vu Pham <vuhuong@mellanox.com>
  • Loading branch information
Vu Pham authored and Saeed Mahameed committed May 28, 2020
1 parent ea651a8 commit 07bab95
Show file tree
Hide file tree
Showing 10 changed files with 619 additions and 583 deletions.
3 changes: 2 additions & 1 deletion drivers/net/ethernet/mellanox/mlx5/core/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ mlx5_core-$(CONFIG_MLX5_TC_CT) += en/tc_ct.o
mlx5_core-$(CONFIG_MLX5_ESWITCH) += eswitch.o eswitch_offloads.o eswitch_offloads_termtbl.o \
ecpf.o rdma.o
mlx5_core-$(CONFIG_MLX5_ESWITCH) += esw/acl/helper.o \
esw/acl/egress_lgcy.o esw/acl/egress_ofld.o
esw/acl/egress_lgcy.o esw/acl/egress_ofld.o \
esw/acl/ingress_lgcy.o esw/acl/ingress_ofld.o

mlx5_core-$(CONFIG_MLX5_MPFS) += lib/mpfs.o
mlx5_core-$(CONFIG_VXLAN) += lib/vxlan.o
Expand Down
18 changes: 18 additions & 0 deletions drivers/net/ethernet/mellanox/mlx5/core/esw/acl/helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -140,3 +140,21 @@ void esw_acl_egress_table_destroy(struct mlx5_vport *vport)
mlx5_destroy_flow_table(vport->egress.acl);
vport->egress.acl = NULL;
}

void esw_acl_ingress_table_destroy(struct mlx5_vport *vport)
{
if (!vport->ingress.acl)
return;

mlx5_destroy_flow_table(vport->ingress.acl);
vport->ingress.acl = NULL;
}

void esw_acl_ingress_allow_rule_destroy(struct mlx5_vport *vport)
{
if (!vport->ingress.allow_rule)
return;

mlx5_del_flow_rules(vport->ingress.allow_rule);
vport->ingress.allow_rule = NULL;
}
4 changes: 4 additions & 0 deletions drivers/net/ethernet/mellanox/mlx5/core/esw/acl/helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,8 @@ void esw_acl_egress_vlan_destroy(struct mlx5_vport *vport);
int esw_acl_egress_vlan_grp_create(struct mlx5_eswitch *esw, struct mlx5_vport *vport);
void esw_acl_egress_vlan_grp_destroy(struct mlx5_vport *vport);

/* Ingress acl helper functions */
void esw_acl_ingress_table_destroy(struct mlx5_vport *vport);
void esw_acl_ingress_allow_rule_destroy(struct mlx5_vport *vport);

#endif /* __MLX5_ESWITCH_ACL_HELPER_H__ */
279 changes: 279 additions & 0 deletions drivers/net/ethernet/mellanox/mlx5/core/esw/acl/ingress_lgcy.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,279 @@
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
/* Copyright (c) 2020 Mellanox Technologies Inc. All rights reserved. */

#include "mlx5_core.h"
#include "eswitch.h"
#include "helper.h"
#include "lgcy.h"

static void esw_acl_ingress_lgcy_rules_destroy(struct mlx5_vport *vport)
{
if (vport->ingress.legacy.drop_rule) {
mlx5_del_flow_rules(vport->ingress.legacy.drop_rule);
vport->ingress.legacy.drop_rule = NULL;
}
esw_acl_ingress_allow_rule_destroy(vport);
}

static int esw_acl_ingress_lgcy_groups_create(struct mlx5_eswitch *esw,
struct mlx5_vport *vport)
{
int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
struct mlx5_core_dev *dev = esw->dev;
struct mlx5_flow_group *g;
void *match_criteria;
u32 *flow_group_in;
int err;

flow_group_in = kvzalloc(inlen, GFP_KERNEL);
if (!flow_group_in)
return -ENOMEM;

match_criteria = MLX5_ADDR_OF(create_flow_group_in, flow_group_in, match_criteria);

MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable,
MLX5_MATCH_OUTER_HEADERS);
MLX5_SET_TO_ONES(fte_match_param, match_criteria, outer_headers.cvlan_tag);
MLX5_SET_TO_ONES(fte_match_param, match_criteria, outer_headers.smac_47_16);
MLX5_SET_TO_ONES(fte_match_param, match_criteria, outer_headers.smac_15_0);
MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, 0);
MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, 0);

g = mlx5_create_flow_group(vport->ingress.acl, flow_group_in);
if (IS_ERR(g)) {
err = PTR_ERR(g);
esw_warn(dev, "vport[%d] ingress create untagged spoofchk flow group, err(%d)\n",
vport->vport, err);
goto spoof_err;
}
vport->ingress.legacy.allow_untagged_spoofchk_grp = g;

memset(flow_group_in, 0, inlen);
MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable,
MLX5_MATCH_OUTER_HEADERS);
MLX5_SET_TO_ONES(fte_match_param, match_criteria, outer_headers.cvlan_tag);
MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, 1);
MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, 1);

g = mlx5_create_flow_group(vport->ingress.acl, flow_group_in);
if (IS_ERR(g)) {
err = PTR_ERR(g);
esw_warn(dev, "vport[%d] ingress create untagged flow group, err(%d)\n",
vport->vport, err);
goto untagged_err;
}
vport->ingress.legacy.allow_untagged_only_grp = g;

memset(flow_group_in, 0, inlen);
MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable,
MLX5_MATCH_OUTER_HEADERS);
MLX5_SET_TO_ONES(fte_match_param, match_criteria, outer_headers.smac_47_16);
MLX5_SET_TO_ONES(fte_match_param, match_criteria, outer_headers.smac_15_0);
MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, 2);
MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, 2);

g = mlx5_create_flow_group(vport->ingress.acl, flow_group_in);
if (IS_ERR(g)) {
err = PTR_ERR(g);
esw_warn(dev, "vport[%d] ingress create spoofchk flow group, err(%d)\n",
vport->vport, err);
goto allow_spoof_err;
}
vport->ingress.legacy.allow_spoofchk_only_grp = g;

memset(flow_group_in, 0, inlen);
MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, 3);
MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, 3);

g = mlx5_create_flow_group(vport->ingress.acl, flow_group_in);
if (IS_ERR(g)) {
err = PTR_ERR(g);
esw_warn(dev, "vport[%d] ingress create drop flow group, err(%d)\n",
vport->vport, err);
goto drop_err;
}
vport->ingress.legacy.drop_grp = g;
kvfree(flow_group_in);
return 0;

drop_err:
if (!IS_ERR_OR_NULL(vport->ingress.legacy.allow_spoofchk_only_grp)) {
mlx5_destroy_flow_group(vport->ingress.legacy.allow_spoofchk_only_grp);
vport->ingress.legacy.allow_spoofchk_only_grp = NULL;
}
allow_spoof_err:
if (!IS_ERR_OR_NULL(vport->ingress.legacy.allow_untagged_only_grp)) {
mlx5_destroy_flow_group(vport->ingress.legacy.allow_untagged_only_grp);
vport->ingress.legacy.allow_untagged_only_grp = NULL;
}
untagged_err:
if (!IS_ERR_OR_NULL(vport->ingress.legacy.allow_untagged_spoofchk_grp)) {
mlx5_destroy_flow_group(vport->ingress.legacy.allow_untagged_spoofchk_grp);
vport->ingress.legacy.allow_untagged_spoofchk_grp = NULL;
}
spoof_err:
kvfree(flow_group_in);
return err;
}

static void esw_acl_ingress_lgcy_groups_destroy(struct mlx5_vport *vport)
{
if (vport->ingress.legacy.allow_spoofchk_only_grp) {
mlx5_destroy_flow_group(vport->ingress.legacy.allow_spoofchk_only_grp);
vport->ingress.legacy.allow_spoofchk_only_grp = NULL;
}
if (vport->ingress.legacy.allow_untagged_only_grp) {
mlx5_destroy_flow_group(vport->ingress.legacy.allow_untagged_only_grp);
vport->ingress.legacy.allow_untagged_only_grp = NULL;
}
if (vport->ingress.legacy.allow_untagged_spoofchk_grp) {
mlx5_destroy_flow_group(vport->ingress.legacy.allow_untagged_spoofchk_grp);
vport->ingress.legacy.allow_untagged_spoofchk_grp = NULL;
}
if (vport->ingress.legacy.drop_grp) {
mlx5_destroy_flow_group(vport->ingress.legacy.drop_grp);
vport->ingress.legacy.drop_grp = NULL;
}
}

int esw_acl_ingress_lgcy_setup(struct mlx5_eswitch *esw,
struct mlx5_vport *vport)
{
struct mlx5_flow_destination drop_ctr_dst = {};
struct mlx5_flow_destination *dst = NULL;
struct mlx5_flow_act flow_act = {};
struct mlx5_flow_spec *spec = NULL;
struct mlx5_fc *counter = NULL;
/* The ingress acl table contains 4 groups
* (2 active rules at the same time -
* 1 allow rule from one of the first 3 groups.
* 1 drop rule from the last group):
* 1)Allow untagged traffic with smac=original mac.
* 2)Allow untagged traffic.
* 3)Allow traffic with smac=original mac.
* 4)Drop all other traffic.
*/
int table_size = 4;
int dest_num = 0;
int err = 0;
u8 *smac_v;

esw_acl_ingress_lgcy_rules_destroy(vport);

if (MLX5_CAP_ESW_INGRESS_ACL(esw->dev, flow_counter)) {
counter = mlx5_fc_create(esw->dev, false);
if (IS_ERR(counter))
esw_warn(esw->dev,
"vport[%d] configure ingress drop rule counter failed\n",
vport->vport);
vport->ingress.legacy.drop_counter = counter;
}

if (!vport->info.vlan && !vport->info.qos && !vport->info.spoofchk) {
esw_acl_ingress_lgcy_cleanup(esw, vport);
return 0;
}

if (!vport->ingress.acl) {
vport->ingress.acl = esw_acl_table_create(esw, vport->vport,
MLX5_FLOW_NAMESPACE_ESW_INGRESS,
table_size);
if (IS_ERR_OR_NULL(vport->ingress.acl)) {
err = PTR_ERR(vport->ingress.acl);
vport->ingress.acl = NULL;
return err;
}

err = esw_acl_ingress_lgcy_groups_create(esw, vport);
if (err)
goto out;
}

esw_debug(esw->dev,
"vport[%d] configure ingress rules, vlan(%d) qos(%d)\n",
vport->vport, vport->info.vlan, vport->info.qos);

spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
if (!spec) {
err = -ENOMEM;
goto out;
}

if (vport->info.vlan || vport->info.qos)
MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria,
outer_headers.cvlan_tag);

if (vport->info.spoofchk) {
MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria,
outer_headers.smac_47_16);
MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria,
outer_headers.smac_15_0);
smac_v = MLX5_ADDR_OF(fte_match_param,
spec->match_value,
outer_headers.smac_47_16);
ether_addr_copy(smac_v, vport->info.mac);
}

/* Create ingress allow rule */
memset(spec, 0, sizeof(*spec));
spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS;
flow_act.action = MLX5_FLOW_CONTEXT_ACTION_ALLOW;
vport->ingress.allow_rule = mlx5_add_flow_rules(vport->ingress.acl, spec,
&flow_act, NULL, 0);
if (IS_ERR(vport->ingress.allow_rule)) {
err = PTR_ERR(vport->ingress.allow_rule);
esw_warn(esw->dev,
"vport[%d] configure ingress allow rule, err(%d)\n",
vport->vport, err);
vport->ingress.allow_rule = NULL;
goto out;
}

memset(&flow_act, 0, sizeof(flow_act));
flow_act.action = MLX5_FLOW_CONTEXT_ACTION_DROP;
/* Attach drop flow counter */
if (counter) {
flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_COUNT;
drop_ctr_dst.type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
drop_ctr_dst.counter_id = mlx5_fc_id(counter);
dst = &drop_ctr_dst;
dest_num++;
}
vport->ingress.legacy.drop_rule =
mlx5_add_flow_rules(vport->ingress.acl, NULL,
&flow_act, dst, dest_num);
if (IS_ERR(vport->ingress.legacy.drop_rule)) {
err = PTR_ERR(vport->ingress.legacy.drop_rule);
esw_warn(esw->dev,
"vport[%d] configure ingress drop rule, err(%d)\n",
vport->vport, err);
vport->ingress.legacy.drop_rule = NULL;
goto out;
}
kvfree(spec);
return 0;

out:
esw_acl_ingress_lgcy_cleanup(esw, vport);
kvfree(spec);
return err;
}

void esw_acl_ingress_lgcy_cleanup(struct mlx5_eswitch *esw,
struct mlx5_vport *vport)
{
if (IS_ERR_OR_NULL(vport->ingress.acl))
goto clean_drop_counter;

esw_debug(esw->dev, "Destroy vport[%d] E-Switch ingress ACL\n", vport->vport);

esw_acl_ingress_lgcy_rules_destroy(vport);
esw_acl_ingress_lgcy_groups_destroy(vport);
esw_acl_ingress_table_destroy(vport);

clean_drop_counter:
if (!IS_ERR_OR_NULL(vport->ingress.legacy.drop_counter)) {
mlx5_fc_destroy(esw->dev, vport->ingress.legacy.drop_counter);
vport->ingress.legacy.drop_counter = NULL;
}
}
Loading

0 comments on commit 07bab95

Please sign in to comment.