Skip to content

Commit

Permalink
Merge branch 'net-dissection-and-matching-on-tos-and-ttl'
Browse files Browse the repository at this point in the history
Or Gerlitz says:

====================
net: add support for dissection and matching on ip tos and ttl

The 1st two patches enable matching/classifying on ip tos and ttl by
the flow dissector and flower. The other two patches offload matching
on tcp flags and ip tos in mlx5.

The mlx5 patches touch single file/function and not interfere with
other inflight mlx5 submissions.

V2:  repost as asked by Dave.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Jun 4, 2017
2 parents f4d0166 + fd7da28 commit e8317a4
Show file tree
Hide file tree
Showing 5 changed files with 138 additions and 3 deletions.
46 changes: 45 additions & 1 deletion drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
Original file line number Diff line number Diff line change
Expand Up @@ -581,7 +581,9 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
BIT(FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS) |
BIT(FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS) |
BIT(FLOW_DISSECTOR_KEY_ENC_PORTS) |
BIT(FLOW_DISSECTOR_KEY_ENC_CONTROL))) {
BIT(FLOW_DISSECTOR_KEY_ENC_CONTROL) |
BIT(FLOW_DISSECTOR_KEY_TCP) |
BIT(FLOW_DISSECTOR_KEY_IP))) {
netdev_warn(priv->netdev, "Unsupported key used: 0x%x\n",
f->dissector->used_keys);
return -EOPNOTSUPP;
Expand Down Expand Up @@ -808,6 +810,48 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
*min_inline = MLX5_INLINE_MODE_TCP_UDP;
}

if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_IP)) {
struct flow_dissector_key_ip *key =
skb_flow_dissector_target(f->dissector,
FLOW_DISSECTOR_KEY_IP,
f->key);
struct flow_dissector_key_ip *mask =
skb_flow_dissector_target(f->dissector,
FLOW_DISSECTOR_KEY_IP,
f->mask);

MLX5_SET(fte_match_set_lyr_2_4, headers_c, ip_ecn, mask->tos & 0x3);
MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_ecn, key->tos & 0x3);

MLX5_SET(fte_match_set_lyr_2_4, headers_c, ip_dscp, mask->tos >> 2);
MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_dscp, key->tos >> 2);

if (mask->tos)
*min_inline = MLX5_INLINE_MODE_IP;

if (mask->ttl) /* currently not supported */
return -EOPNOTSUPP;
}

if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_TCP)) {
struct flow_dissector_key_tcp *key =
skb_flow_dissector_target(f->dissector,
FLOW_DISSECTOR_KEY_TCP,
f->key);
struct flow_dissector_key_tcp *mask =
skb_flow_dissector_target(f->dissector,
FLOW_DISSECTOR_KEY_TCP,
f->mask);

MLX5_SET(fte_match_set_lyr_2_4, headers_c, tcp_flags,
ntohs(mask->flags));
MLX5_SET(fte_match_set_lyr_2_4, headers_v, tcp_flags,
ntohs(key->flags));

if (mask->flags)
*min_inline = MLX5_INLINE_MODE_TCP_UDP;
}

return 0;
}

Expand Down
11 changes: 11 additions & 0 deletions include/net/flow_dissector.h
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,16 @@ struct flow_dissector_key_tcp {
__be16 flags;
};

/**
* struct flow_dissector_key_ip:
* @tos: tos
* @ttl: ttl
*/
struct flow_dissector_key_ip {
__u8 tos;
__u8 ttl;
};

enum flow_dissector_key_id {
FLOW_DISSECTOR_KEY_CONTROL, /* struct flow_dissector_key_control */
FLOW_DISSECTOR_KEY_BASIC, /* struct flow_dissector_key_basic */
Expand All @@ -186,6 +196,7 @@ enum flow_dissector_key_id {
FLOW_DISSECTOR_KEY_ENC_PORTS, /* struct flow_dissector_key_ports */
FLOW_DISSECTOR_KEY_MPLS, /* struct flow_dissector_key_mpls */
FLOW_DISSECTOR_KEY_TCP, /* struct flow_dissector_key_tcp */
FLOW_DISSECTOR_KEY_IP, /* struct flow_dissector_key_ip */

FLOW_DISSECTOR_KEY_MAX,
};
Expand Down
5 changes: 5 additions & 0 deletions include/uapi/linux/pkt_cls.h
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,11 @@ enum {
TCA_FLOWER_KEY_TCP_FLAGS, /* be16 */
TCA_FLOWER_KEY_TCP_FLAGS_MASK, /* be16 */

TCA_FLOWER_KEY_IP_TOS, /* u8 */
TCA_FLOWER_KEY_IP_TOS_MASK, /* u8 */
TCA_FLOWER_KEY_IP_TTL, /* u8 */
TCA_FLOWER_KEY_IP_TTL_MASK, /* u8 */

__TCA_FLOWER_MAX,
};

Expand Down
40 changes: 40 additions & 0 deletions net/core/flow_dissector.c
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,40 @@ __skb_flow_dissect_tcp(const struct sk_buff *skb,
key_tcp->flags = (*(__be16 *) &tcp_flag_word(th) & htons(0x0FFF));
}

static void
__skb_flow_dissect_ipv4(const struct sk_buff *skb,
struct flow_dissector *flow_dissector,
void *target_container, void *data, const struct iphdr *iph)
{
struct flow_dissector_key_ip *key_ip;

if (!dissector_uses_key(flow_dissector, FLOW_DISSECTOR_KEY_IP))
return;

key_ip = skb_flow_dissector_target(flow_dissector,
FLOW_DISSECTOR_KEY_IP,
target_container);
key_ip->tos = iph->tos;
key_ip->ttl = iph->ttl;
}

static void
__skb_flow_dissect_ipv6(const struct sk_buff *skb,
struct flow_dissector *flow_dissector,
void *target_container, void *data, const struct ipv6hdr *iph)
{
struct flow_dissector_key_ip *key_ip;

if (!dissector_uses_key(flow_dissector, FLOW_DISSECTOR_KEY_IP))
return;

key_ip = skb_flow_dissector_target(flow_dissector,
FLOW_DISSECTOR_KEY_IP,
target_container);
key_ip->tos = ipv6_get_dsfield(iph);
key_ip->ttl = iph->hop_limit;
}

/**
* __skb_flow_dissect - extract the flow_keys struct and return it
* @skb: sk_buff to extract the flow from, can be NULL if the rest are specified
Expand Down Expand Up @@ -469,6 +503,9 @@ bool __skb_flow_dissect(const struct sk_buff *skb,
}
}

__skb_flow_dissect_ipv4(skb, flow_dissector,
target_container, data, iph);

if (flags & FLOW_DISSECTOR_F_STOP_AT_L3)
goto out_good;

Expand Down Expand Up @@ -514,6 +551,9 @@ bool __skb_flow_dissect(const struct sk_buff *skb,
goto out_good;
}

__skb_flow_dissect_ipv6(skb, flow_dissector,
target_container, data, iph);

if (flags & FLOW_DISSECTOR_F_STOP_AT_L3)
goto out_good;

Expand Down
39 changes: 37 additions & 2 deletions net/sched/cls_flower.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ struct fl_flow_key {
struct flow_dissector_key_ports enc_tp;
struct flow_dissector_key_mpls mpls;
struct flow_dissector_key_tcp tcp;
struct flow_dissector_key_ip ip;
} __aligned(BITS_PER_LONG / 8); /* Ensure that we can do comparisons as longs. */

struct fl_flow_mask_range {
Expand Down Expand Up @@ -427,6 +428,10 @@ static const struct nla_policy fl_policy[TCA_FLOWER_MAX + 1] = {
[TCA_FLOWER_KEY_MPLS_LABEL] = { .type = NLA_U32 },
[TCA_FLOWER_KEY_TCP_FLAGS] = { .type = NLA_U16 },
[TCA_FLOWER_KEY_TCP_FLAGS_MASK] = { .type = NLA_U16 },
[TCA_FLOWER_KEY_IP_TOS] = { .type = NLA_U8 },
[TCA_FLOWER_KEY_IP_TOS_MASK] = { .type = NLA_U8 },
[TCA_FLOWER_KEY_IP_TTL] = { .type = NLA_U8 },
[TCA_FLOWER_KEY_IP_TTL_MASK] = { .type = NLA_U8 },
};

static void fl_set_key_val(struct nlattr **tb,
Expand Down Expand Up @@ -528,6 +533,19 @@ static int fl_set_key_flags(struct nlattr **tb,
return 0;
}

static void fl_set_key_ip(struct nlattr **tb,
struct flow_dissector_key_ip *key,
struct flow_dissector_key_ip *mask)
{
fl_set_key_val(tb, &key->tos, TCA_FLOWER_KEY_IP_TOS,
&mask->tos, TCA_FLOWER_KEY_IP_TOS_MASK,
sizeof(key->tos));

fl_set_key_val(tb, &key->ttl, TCA_FLOWER_KEY_IP_TTL,
&mask->ttl, TCA_FLOWER_KEY_IP_TTL_MASK,
sizeof(key->ttl));
}

static int fl_set_key(struct net *net, struct nlattr **tb,
struct fl_flow_key *key, struct fl_flow_key *mask)
{
Expand Down Expand Up @@ -570,6 +588,7 @@ static int fl_set_key(struct net *net, struct nlattr **tb,
fl_set_key_val(tb, &key->basic.ip_proto, TCA_FLOWER_KEY_IP_PROTO,
&mask->basic.ip_proto, TCA_FLOWER_UNSPEC,
sizeof(key->basic.ip_proto));
fl_set_key_ip(tb, &key->ip, &mask->ip);
}

if (tb[TCA_FLOWER_KEY_IPV4_SRC] || tb[TCA_FLOWER_KEY_IPV4_DST]) {
Expand Down Expand Up @@ -772,6 +791,8 @@ static void fl_init_dissector(struct cls_fl_head *head,
FLOW_DISSECTOR_KEY_IPV6_ADDRS, ipv6);
FL_KEY_SET_IF_MASKED(&mask->key, keys, cnt,
FLOW_DISSECTOR_KEY_PORTS, tp);
FL_KEY_SET_IF_MASKED(&mask->key, keys, cnt,
FLOW_DISSECTOR_KEY_IP, ip);
FL_KEY_SET_IF_MASKED(&mask->key, keys, cnt,
FLOW_DISSECTOR_KEY_TCP, tcp);
FL_KEY_SET_IF_MASKED(&mask->key, keys, cnt,
Expand Down Expand Up @@ -1082,6 +1103,19 @@ static int fl_dump_key_mpls(struct sk_buff *skb,
return 0;
}

static int fl_dump_key_ip(struct sk_buff *skb,
struct flow_dissector_key_ip *key,
struct flow_dissector_key_ip *mask)
{
if (fl_dump_key_val(skb, &key->tos, TCA_FLOWER_KEY_IP_TOS, &mask->tos,
TCA_FLOWER_KEY_IP_TOS_MASK, sizeof(key->tos)) ||
fl_dump_key_val(skb, &key->ttl, TCA_FLOWER_KEY_IP_TTL, &mask->ttl,
TCA_FLOWER_KEY_IP_TTL_MASK, sizeof(key->ttl)))
return -1;

return 0;
}

static int fl_dump_key_vlan(struct sk_buff *skb,
struct flow_dissector_key_vlan *vlan_key,
struct flow_dissector_key_vlan *vlan_mask)
Expand Down Expand Up @@ -1195,9 +1229,10 @@ static int fl_dump(struct net *net, struct tcf_proto *tp, unsigned long fh,

if ((key->basic.n_proto == htons(ETH_P_IP) ||
key->basic.n_proto == htons(ETH_P_IPV6)) &&
fl_dump_key_val(skb, &key->basic.ip_proto, TCA_FLOWER_KEY_IP_PROTO,
(fl_dump_key_val(skb, &key->basic.ip_proto, TCA_FLOWER_KEY_IP_PROTO,
&mask->basic.ip_proto, TCA_FLOWER_UNSPEC,
sizeof(key->basic.ip_proto)))
sizeof(key->basic.ip_proto)) ||
fl_dump_key_ip(skb, &key->ip, &mask->ip)))
goto nla_put_failure;

if (key->control.addr_type == FLOW_DISSECTOR_KEY_IPV4_ADDRS &&
Expand Down

0 comments on commit e8317a4

Please sign in to comment.