File Index
Files and directories
Sign in
FILE

helper.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/helper.c C
  1// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
  2/* Copyright (c) 2020 Mellanox Technologies Inc. All rights reserved. */
  3
  4#include "mlx5_core.h"
  5#include "eswitch.h"
  6#include "helper.h"
  7
  8struct mlx5_flow_table *
  9esw_acl_table_create(struct mlx5_eswitch *esw, struct mlx5_vport *vport, int ns, int size)
 10{
 11	struct mlx5_flow_table_attr ft_attr = {};
 12	struct mlx5_core_dev *dev = esw->dev;
 13	struct mlx5_flow_namespace *root_ns;
 14	struct mlx5_flow_table *acl;
 15	int acl_supported;
 16	u16 vport_num;
 17	int err;
 18
 19	acl_supported = (ns == MLX5_FLOW_NAMESPACE_ESW_INGRESS) ?
 20			MLX5_CAP_ESW_INGRESS_ACL(dev, ft_support) :
 21			MLX5_CAP_ESW_EGRESS_ACL(dev, ft_support);
 22
 23	if (!acl_supported)
 24		return ERR_PTR(-EOPNOTSUPP);
 25
 26	vport_num = vport->vport;
 27	esw_debug(dev, "Create vport[%d] %s ACL table\n", vport_num,
 28		  ns == MLX5_FLOW_NAMESPACE_ESW_INGRESS ? "ingress" : "egress");
 29
 30	root_ns = mlx5_get_flow_vport_namespace(dev, ns, vport->index);
 31	if (!root_ns) {
 32		esw_warn(dev, "Failed to get E-Switch root namespace for vport (%d)\n",
 33			 vport_num);
 34		return ERR_PTR(-EOPNOTSUPP);
 35	}
 36
 37	ft_attr.max_fte = size;
 38	if (vport_num || mlx5_core_is_ecpf(esw->dev))
 39		ft_attr.flags = MLX5_FLOW_TABLE_OTHER_VPORT;
 40	acl = mlx5_create_vport_flow_table(root_ns, &ft_attr, vport_num);
 41	if (IS_ERR(acl)) {
 42		err = PTR_ERR(acl);
 43		esw_warn(dev, "vport[%d] create %s ACL table, err(%d)\n", vport_num,
 44			 ns == MLX5_FLOW_NAMESPACE_ESW_INGRESS ? "ingress" : "egress", err);
 45	}
 46	return acl;
 47}
 48
 49int esw_egress_acl_vlan_create(struct mlx5_eswitch *esw,
 50			       struct mlx5_vport *vport,
 51			       struct mlx5_flow_destination *fwd_dest,
 52			       u16 vlan_id, u32 flow_action)
 53{
 54	struct mlx5_flow_act flow_act = {};
 55	struct mlx5_flow_spec *spec;
 56	int err = 0;
 57
 58	if (vport->egress.allowed_vlan)
 59		return -EEXIST;
 60
 61	spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
 62	if (!spec)
 63		return -ENOMEM;
 64
 65	MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, outer_headers.cvlan_tag);
 66	MLX5_SET_TO_ONES(fte_match_param, spec->match_value, outer_headers.cvlan_tag);
 67	MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, outer_headers.first_vid);
 68	MLX5_SET(fte_match_param, spec->match_value, outer_headers.first_vid, vlan_id);
 69
 70	spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS;
 71	flow_act.action = flow_action;
 72	vport->egress.allowed_vlan =
 73		mlx5_add_flow_rules(vport->egress.acl, spec,
 74				    &flow_act, fwd_dest, 0);
 75	if (IS_ERR(vport->egress.allowed_vlan)) {
 76		err = PTR_ERR(vport->egress.allowed_vlan);
 77		esw_warn(esw->dev,
 78			 "vport[%d] configure egress vlan rule failed, err(%d)\n",
 79			 vport->vport, err);
 80		vport->egress.allowed_vlan = NULL;
 81	}
 82
 83	kvfree(spec);
 84	return err;
 85}
 86
 87void esw_acl_egress_vlan_destroy(struct mlx5_vport *vport)
 88{
 89	if (!IS_ERR_OR_NULL(vport->egress.allowed_vlan)) {
 90		mlx5_del_flow_rules(vport->egress.allowed_vlan);
 91		vport->egress.allowed_vlan = NULL;
 92	}
 93}
 94
 95int esw_acl_egress_vlan_grp_create(struct mlx5_eswitch *esw, struct mlx5_vport *vport)
 96{
 97	int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
 98	struct mlx5_flow_group *vlan_grp;
 99	void *match_criteria;
100	u32 *flow_group_in;
101	int ret = 0;
102
103	flow_group_in = kvzalloc(inlen, GFP_KERNEL);
104	if (!flow_group_in)
105		return -ENOMEM;
106
107	MLX5_SET(create_flow_group_in, flow_group_in,
108		 match_criteria_enable, MLX5_MATCH_OUTER_HEADERS);
109	match_criteria = MLX5_ADDR_OF(create_flow_group_in,
110				      flow_group_in, match_criteria);
111	MLX5_SET_TO_ONES(fte_match_param, match_criteria, outer_headers.cvlan_tag);
112	MLX5_SET_TO_ONES(fte_match_param, match_criteria, outer_headers.first_vid);
113	MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, 0);
114	MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, 0);
115
116	vlan_grp = mlx5_create_flow_group(vport->egress.acl, flow_group_in);
117	if (IS_ERR(vlan_grp)) {
118		ret = PTR_ERR(vlan_grp);
119		esw_warn(esw->dev,
120			 "Failed to create E-Switch vport[%d] egress pop vlans flow group, err(%d)\n",
121			 vport->vport, ret);
122		goto out;
123	}
124	vport->egress.vlan_grp = vlan_grp;
125
126out:
127	kvfree(flow_group_in);
128	return ret;
129}
130
131void esw_acl_egress_vlan_grp_destroy(struct mlx5_vport *vport)
132{
133	if (!IS_ERR_OR_NULL(vport->egress.vlan_grp)) {
134		mlx5_destroy_flow_group(vport->egress.vlan_grp);
135		vport->egress.vlan_grp = NULL;
136	}
137}
138
139void esw_acl_egress_table_destroy(struct mlx5_vport *vport)
140{
141	if (IS_ERR_OR_NULL(vport->egress.acl))
142		return;
143
144	mlx5_destroy_flow_table(vport->egress.acl);
145	vport->egress.acl = NULL;
146}
147
148void esw_acl_ingress_table_destroy(struct mlx5_vport *vport)
149{
150	if (!vport->ingress.acl)
151		return;
152
153	mlx5_destroy_flow_table(vport->ingress.acl);
154	vport->ingress.acl = NULL;
155}
156
157void esw_acl_ingress_allow_rule_destroy(struct mlx5_vport *vport)
158{
159	if (!vport->ingress.allow_rule)
160		return;
161
162	mlx5_del_flow_rules(vport->ingress.allow_rule);
163	vport->ingress.allow_rule = NULL;
164}
~/ Read-only file preview.