Skip to content

Commit

Permalink
net/mlx5e: CT: Make mlx5_ct_fs_smfs_ct_validate_flow_rule reusable
Browse files Browse the repository at this point in the history
This function checks whether a flow_rule has the right flow dissector
keys and masks used for a connection tracking flow offload. It is
currently used locally by the tc_ct smfs module, but is about to be used
from another place, so this commit moves it to a better place, renames
it to mlx5e_tc_ct_is_valid_flow_rule and drops the unused fs argument.

Signed-off-by: Cosmin Ratiu <cratiu@nvidia.com>
Reviewed-by: Jianbo Liu <jianbol@nvidia.com>
Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
Link: https://patch.msgid.link/20250114130646.1937192-4-tariqt@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
  • Loading branch information
Cosmin Ratiu authored and Jakub Kicinski committed Jan 16, 2025
1 parent 34eea5b commit 554f977
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 74 deletions.
75 changes: 1 addition & 74 deletions drivers/net/ethernet/mellanox/mlx5/core/en/tc/ct_fs_smfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
#define INIT_ERR_PREFIX "ct_fs_smfs init failed"
#define ct_dbg(fmt, args...)\
netdev_dbg(fs->netdev, "ct_fs_smfs debug: " fmt "\n", ##args)
#define MLX5_CT_TCP_FLAGS_MASK cpu_to_be16(be32_to_cpu(TCP_FLAG_RST | TCP_FLAG_FIN) >> 16)

struct mlx5_ct_fs_smfs_matcher {
struct mlx5dr_matcher *dr_matcher;
Expand Down Expand Up @@ -220,78 +219,6 @@ mlx5_ct_fs_smfs_destroy(struct mlx5_ct_fs *fs)
mlx5_smfs_action_destroy(fs_smfs->fwd_action);
}

static inline bool
mlx5_tc_ct_valid_used_dissector_keys(const u64 used_keys)
{
#define DISS_BIT(name) BIT_ULL(FLOW_DISSECTOR_KEY_ ## name)
const u64 basic_keys = DISS_BIT(BASIC) | DISS_BIT(CONTROL) |
DISS_BIT(META);
const u64 ipv4_tcp = basic_keys | DISS_BIT(IPV4_ADDRS) |
DISS_BIT(PORTS) | DISS_BIT(TCP);
const u64 ipv6_tcp = basic_keys | DISS_BIT(IPV6_ADDRS) |
DISS_BIT(PORTS) | DISS_BIT(TCP);
const u64 ipv4_udp = basic_keys | DISS_BIT(IPV4_ADDRS) |
DISS_BIT(PORTS);
const u64 ipv6_udp = basic_keys | DISS_BIT(IPV6_ADDRS) |
DISS_BIT(PORTS);
const u64 ipv4_gre = basic_keys | DISS_BIT(IPV4_ADDRS);
const u64 ipv6_gre = basic_keys | DISS_BIT(IPV6_ADDRS);

return (used_keys == ipv4_tcp || used_keys == ipv4_udp || used_keys == ipv6_tcp ||
used_keys == ipv6_udp || used_keys == ipv4_gre || used_keys == ipv6_gre);
}

static bool
mlx5_ct_fs_smfs_ct_validate_flow_rule(struct mlx5_ct_fs *fs, struct flow_rule *flow_rule)
{
struct flow_match_ipv4_addrs ipv4_addrs;
struct flow_match_ipv6_addrs ipv6_addrs;
struct flow_match_control control;
struct flow_match_basic basic;
struct flow_match_ports ports;
struct flow_match_tcp tcp;

if (!mlx5_tc_ct_valid_used_dissector_keys(flow_rule->match.dissector->used_keys)) {
ct_dbg("rule uses unexpected dissectors (0x%016llx)",
flow_rule->match.dissector->used_keys);
return false;
}

flow_rule_match_basic(flow_rule, &basic);
flow_rule_match_control(flow_rule, &control);
flow_rule_match_ipv4_addrs(flow_rule, &ipv4_addrs);
flow_rule_match_ipv6_addrs(flow_rule, &ipv6_addrs);
if (basic.key->ip_proto != IPPROTO_GRE)
flow_rule_match_ports(flow_rule, &ports);
if (basic.key->ip_proto == IPPROTO_TCP)
flow_rule_match_tcp(flow_rule, &tcp);

if (basic.mask->n_proto != htons(0xFFFF) ||
(basic.key->n_proto != htons(ETH_P_IP) && basic.key->n_proto != htons(ETH_P_IPV6)) ||
basic.mask->ip_proto != 0xFF ||
(basic.key->ip_proto != IPPROTO_UDP && basic.key->ip_proto != IPPROTO_TCP &&
basic.key->ip_proto != IPPROTO_GRE)) {
ct_dbg("rule uses unexpected basic match (n_proto 0x%04x/0x%04x, ip_proto 0x%02x/0x%02x)",
ntohs(basic.key->n_proto), ntohs(basic.mask->n_proto),
basic.key->ip_proto, basic.mask->ip_proto);
return false;
}

if (basic.key->ip_proto != IPPROTO_GRE &&
(ports.mask->src != htons(0xFFFF) || ports.mask->dst != htons(0xFFFF))) {
ct_dbg("rule uses ports match (src 0x%04x, dst 0x%04x)",
ports.mask->src, ports.mask->dst);
return false;
}

if (basic.key->ip_proto == IPPROTO_TCP && tcp.mask->flags != MLX5_CT_TCP_FLAGS_MASK) {
ct_dbg("rule uses unexpected tcp match (flags 0x%02x)", tcp.mask->flags);
return false;
}

return true;
}

static struct mlx5_ct_fs_rule *
mlx5_ct_fs_smfs_ct_rule_add(struct mlx5_ct_fs *fs, struct mlx5_flow_spec *spec,
struct mlx5_flow_attr *attr, struct flow_rule *flow_rule)
Expand All @@ -304,7 +231,7 @@ mlx5_ct_fs_smfs_ct_rule_add(struct mlx5_ct_fs *fs, struct mlx5_flow_spec *spec,
int num_actions = 0, err;
bool nat, tcp, ipv4, gre;

if (!mlx5_ct_fs_smfs_ct_validate_flow_rule(fs, flow_rule))
if (!mlx5e_tc_ct_is_valid_flow_rule(fs->netdev, flow_rule))
return ERR_PTR(-EOPNOTSUPP);

smfs_rule = kzalloc(sizeof(*smfs_rule), GFP_KERNEL);
Expand Down
71 changes: 71 additions & 0 deletions drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c
Original file line number Diff line number Diff line change
Expand Up @@ -2430,3 +2430,74 @@ mlx5e_tc_ct_restore_flow(struct mlx5_tc_ct_priv *ct_priv,
atomic_inc(&ct_priv->debugfs.stats.rx_dropped);
return false;
}

static bool mlx5e_tc_ct_valid_used_dissector_keys(const u64 used_keys)
{
#define DISS_BIT(name) BIT_ULL(FLOW_DISSECTOR_KEY_ ## name)
const u64 basic_keys = DISS_BIT(BASIC) | DISS_BIT(CONTROL) |
DISS_BIT(META);
const u64 ipv4_tcp = basic_keys | DISS_BIT(IPV4_ADDRS) |
DISS_BIT(PORTS) | DISS_BIT(TCP);
const u64 ipv6_tcp = basic_keys | DISS_BIT(IPV6_ADDRS) |
DISS_BIT(PORTS) | DISS_BIT(TCP);
const u64 ipv4_udp = basic_keys | DISS_BIT(IPV4_ADDRS) |
DISS_BIT(PORTS);
const u64 ipv6_udp = basic_keys | DISS_BIT(IPV6_ADDRS) |
DISS_BIT(PORTS);
const u64 ipv4_gre = basic_keys | DISS_BIT(IPV4_ADDRS);
const u64 ipv6_gre = basic_keys | DISS_BIT(IPV6_ADDRS);

return (used_keys == ipv4_tcp || used_keys == ipv4_udp || used_keys == ipv6_tcp ||
used_keys == ipv6_udp || used_keys == ipv4_gre || used_keys == ipv6_gre);
}

bool mlx5e_tc_ct_is_valid_flow_rule(const struct net_device *dev, struct flow_rule *flow_rule)
{
struct flow_match_ipv4_addrs ipv4_addrs;
struct flow_match_ipv6_addrs ipv6_addrs;
struct flow_match_control control;
struct flow_match_basic basic;
struct flow_match_ports ports;
struct flow_match_tcp tcp;

if (!mlx5e_tc_ct_valid_used_dissector_keys(flow_rule->match.dissector->used_keys)) {
netdev_dbg(dev, "ct_debug: rule uses unexpected dissectors (0x%016llx)",
flow_rule->match.dissector->used_keys);
return false;
}

flow_rule_match_basic(flow_rule, &basic);
flow_rule_match_control(flow_rule, &control);
flow_rule_match_ipv4_addrs(flow_rule, &ipv4_addrs);
flow_rule_match_ipv6_addrs(flow_rule, &ipv6_addrs);
if (basic.key->ip_proto != IPPROTO_GRE)
flow_rule_match_ports(flow_rule, &ports);
if (basic.key->ip_proto == IPPROTO_TCP)
flow_rule_match_tcp(flow_rule, &tcp);

if (basic.mask->n_proto != htons(0xFFFF) ||
(basic.key->n_proto != htons(ETH_P_IP) && basic.key->n_proto != htons(ETH_P_IPV6)) ||
basic.mask->ip_proto != 0xFF ||
(basic.key->ip_proto != IPPROTO_UDP && basic.key->ip_proto != IPPROTO_TCP &&
basic.key->ip_proto != IPPROTO_GRE)) {
netdev_dbg(dev, "ct_debug: rule uses unexpected basic match (n_proto 0x%04x/0x%04x, ip_proto 0x%02x/0x%02x)",
ntohs(basic.key->n_proto), ntohs(basic.mask->n_proto),
basic.key->ip_proto, basic.mask->ip_proto);
return false;
}

if (basic.key->ip_proto != IPPROTO_GRE &&
(ports.mask->src != htons(0xFFFF) || ports.mask->dst != htons(0xFFFF))) {
netdev_dbg(dev, "ct_debug: rule uses ports match (src 0x%04x, dst 0x%04x)",
ports.mask->src, ports.mask->dst);
return false;
}

if (basic.key->ip_proto == IPPROTO_TCP && tcp.mask->flags != MLX5_CT_TCP_FLAGS_MASK) {
netdev_dbg(dev, "ct_debug: rule uses unexpected tcp match (flags 0x%02x)",
tcp.mask->flags);
return false;
}

return true;
}
10 changes: 10 additions & 0 deletions drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.h
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,9 @@ bool
mlx5e_tc_ct_restore_flow(struct mlx5_tc_ct_priv *ct_priv,
struct sk_buff *skb, u8 zone_restore_id);

#define MLX5_CT_TCP_FLAGS_MASK cpu_to_be16(be32_to_cpu(TCP_FLAG_RST | TCP_FLAG_FIN) >> 16)
bool mlx5e_tc_ct_is_valid_flow_rule(const struct net_device *dev, struct flow_rule *flow_rule);

#else /* CONFIG_MLX5_TC_CT */

static inline struct mlx5_tc_ct_priv *
Expand Down Expand Up @@ -202,5 +205,12 @@ mlx5e_tc_ct_restore_flow(struct mlx5_tc_ct_priv *ct_priv,
return false;
}

static inline bool
mlx5e_tc_ct_is_valid_flow_rule(const struct net_device *dev,
struct flow_rule *flow_rule)
{
return false;
}

#endif /* !IS_ENABLED(CONFIG_MLX5_TC_CT) */
#endif /* __MLX5_EN_TC_CT_H__ */

0 comments on commit 554f977

Please sign in to comment.