Commit fe22f741 authored by Ido Schimmel's avatar Ido Schimmel Committed by Jakub Kicinski

mlxsw: spectrum_flower: Add ability to match on port ranges

Add the ability to match on port ranges by utilizing the previously
added port range registers and the port range key element. Up to two
port range registers can be used for each filter, one for source port
and another for destination port.
Signed-off-by: default avatarIdo Schimmel <idosch@nvidia.com>
Reviewed-by: default avatarPetr Machata <petrm@nvidia.com>
Signed-off-by: default avatarPetr Machata <petrm@nvidia.com>
Link: https://lore.kernel.org/r/df4385a9592917e9a22ebff339e0463e4a8dfa82.1689092769.git.petrm@nvidia.comSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 898979c7
......@@ -867,9 +867,13 @@ struct mlxsw_sp_acl_rule_info {
egress_bind_blocker:1,
counter_valid:1,
policer_index_valid:1,
ipv6_valid:1;
ipv6_valid:1,
src_port_range_reg_valid:1,
dst_port_range_reg_valid:1;
unsigned int counter_index;
u16 policer_index;
u8 src_port_range_reg_index;
u8 dst_port_range_reg_index;
struct {
u32 prev_val;
enum mlxsw_sp_acl_mangle_field prev_field;
......
......@@ -344,6 +344,12 @@ void mlxsw_sp_acl_rulei_destroy(struct mlxsw_sp *mlxsw_sp,
{
if (rulei->action_created)
mlxsw_afa_block_destroy(rulei->act_block);
if (rulei->src_port_range_reg_valid)
mlxsw_sp_port_range_reg_put(mlxsw_sp,
rulei->src_port_range_reg_index);
if (rulei->dst_port_range_reg_valid)
mlxsw_sp_port_range_reg_put(mlxsw_sp,
rulei->dst_port_range_reg_index);
kfree(rulei);
}
......
......@@ -418,6 +418,68 @@ static int mlxsw_sp_flower_parse_ports(struct mlxsw_sp *mlxsw_sp,
return 0;
}
static int
mlxsw_sp_flower_parse_ports_range(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_acl_rule_info *rulei,
struct flow_cls_offload *f, u8 ip_proto)
{
const struct flow_rule *rule = flow_cls_offload_flow_rule(f);
struct flow_match_ports_range match;
u32 key_mask_value = 0;
if (!flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_PORTS_RANGE))
return 0;
if (ip_proto != IPPROTO_TCP && ip_proto != IPPROTO_UDP) {
NL_SET_ERR_MSG_MOD(f->common.extack, "Only UDP and TCP keys are supported");
return -EINVAL;
}
flow_rule_match_ports_range(rule, &match);
if (match.mask->tp_min.src) {
struct mlxsw_sp_port_range range = {
.min = ntohs(match.key->tp_min.src),
.max = ntohs(match.key->tp_max.src),
.source = true,
};
u8 prr_index;
int err;
err = mlxsw_sp_port_range_reg_get(mlxsw_sp, &range,
f->common.extack, &prr_index);
if (err)
return err;
rulei->src_port_range_reg_index = prr_index;
rulei->src_port_range_reg_valid = true;
key_mask_value |= BIT(prr_index);
}
if (match.mask->tp_min.dst) {
struct mlxsw_sp_port_range range = {
.min = ntohs(match.key->tp_min.dst),
.max = ntohs(match.key->tp_max.dst),
};
u8 prr_index;
int err;
err = mlxsw_sp_port_range_reg_get(mlxsw_sp, &range,
f->common.extack, &prr_index);
if (err)
return err;
rulei->dst_port_range_reg_index = prr_index;
rulei->dst_port_range_reg_valid = true;
key_mask_value |= BIT(prr_index);
}
mlxsw_sp_acl_rulei_keymask_u32(rulei, MLXSW_AFK_ELEMENT_L4_PORT_RANGE,
key_mask_value, key_mask_value);
return 0;
}
static int mlxsw_sp_flower_parse_tcp(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_acl_rule_info *rulei,
struct flow_cls_offload *f,
......@@ -503,6 +565,7 @@ static int mlxsw_sp_flower_parse(struct mlxsw_sp *mlxsw_sp,
BIT(FLOW_DISSECTOR_KEY_IPV4_ADDRS) |
BIT(FLOW_DISSECTOR_KEY_IPV6_ADDRS) |
BIT(FLOW_DISSECTOR_KEY_PORTS) |
BIT(FLOW_DISSECTOR_KEY_PORTS_RANGE) |
BIT(FLOW_DISSECTOR_KEY_TCP) |
BIT(FLOW_DISSECTOR_KEY_IP) |
BIT(FLOW_DISSECTOR_KEY_VLAN))) {
......@@ -604,6 +667,11 @@ static int mlxsw_sp_flower_parse(struct mlxsw_sp *mlxsw_sp,
err = mlxsw_sp_flower_parse_ports(mlxsw_sp, rulei, f, ip_proto);
if (err)
return err;
err = mlxsw_sp_flower_parse_ports_range(mlxsw_sp, rulei, f, ip_proto);
if (err)
return err;
err = mlxsw_sp_flower_parse_tcp(mlxsw_sp, rulei, f, ip_proto);
if (err)
return err;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment