[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <1548748926-23822-3-git-send-email-paulb@mellanox.com>
Date: Tue, 29 Jan 2019 10:02:02 +0200
From: Paul Blakey <paulb@...lanox.com>
To: Guy Shattah <sguy@...lanox.com>,
Marcelo Leitner <mleitner@...hat.com>,
Aaron Conole <aconole@...hat.com>,
John Hurley <john.hurley@...ronome.com>,
Simon Horman <simon.horman@...ronome.com>,
Justin Pettit <jpettit@....org>,
Gregory Rose <gvrose8192@...il.com>,
Eelco Chaudron <echaudro@...hat.com>,
Flavio Leitner <fbl@...hat.com>,
Florian Westphal <fwestpha@...hat.com>,
Jiri Pirko <jiri@...nulli.us>, Rashid Khan <rkhan@...hat.com>,
Sushil Kulkarni <sukulkar@...hat.com>,
Andy Gospodarek <andrew.gospodarek@...adcom.com>,
Roi Dayan <roid@...lanox.com>,
Yossi Kuperman <yossiku@...lanox.com>,
Or Gerlitz <ogerlitz@...lanox.com>,
Rony Efraim <ronye@...lanox.com>,
"davem@...emloft.net" <davem@...emloft.net>, netdev@...r.kernel.org
Cc: Paul Blakey <paulb@...lanox.com>
Subject: [RFC PATCH net-next 2/6 v2] net/sched: cls_flower: add match on ct info
New match on ct state, mark, and label from ct_info on the skb.
This can be set via sending the packet to ct via the ct action.
Signed-off-by: Paul Blakey <paulb@...lanox.com>
---
include/uapi/linux/pkt_cls.h | 17 ++++++
net/sched/cls_flower.c | 126 +++++++++++++++++++++++++++++++++++++++++--
2 files changed, 140 insertions(+), 3 deletions(-)
diff --git a/include/uapi/linux/pkt_cls.h b/include/uapi/linux/pkt_cls.h
index 02ac251..121f1ef 100644
--- a/include/uapi/linux/pkt_cls.h
+++ b/include/uapi/linux/pkt_cls.h
@@ -497,11 +497,28 @@ enum {
TCA_FLOWER_KEY_PORT_DST_MIN, /* be16 */
TCA_FLOWER_KEY_PORT_DST_MAX, /* be16 */
+ TCA_FLOWER_KEY_CT_STATE,
+ TCA_FLOWER_KEY_CT_STATE_MASK,
+ TCA_FLOWER_KEY_CT_ZONE,
+ TCA_FLOWER_KEY_CT_ZONE_MASK,
+ TCA_FLOWER_KEY_CT_MARK,
+ TCA_FLOWER_KEY_CT_MARK_MASK,
+ TCA_FLOWER_KEY_CT_LABELS,
+ TCA_FLOWER_KEY_CT_LABELS_MASK,
+
__TCA_FLOWER_MAX,
};
#define TCA_FLOWER_MAX (__TCA_FLOWER_MAX - 1)
+
+#define TCA_FLOWER_KEY_CT_FLAGS_NEW 0x01 /* Beginning of a new connection. */
+#define TCA_FLOWER_KEY_CT_FLAGS_ESTABLISHED 0x02 /* Part of an existing connection. */
+#define TCA_FLOWER_KEY_CT_FLAGS_RELATED 0x04 /* Related to an established connection. */
+#define TCA_FLOWER_KEY_CT_FLAGS_INVALID 0x10 /* Could not track connection. */
+#define TCA_FLOWER_KEY_CT_FLAGS_TRACKED 0x20 /* Conntrack has occurred. */
+
+
enum {
TCA_FLOWER_KEY_ENC_OPTS_UNSPEC,
TCA_FLOWER_KEY_ENC_OPTS_GENEVE, /* Nested
diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c
index f6aa57f..bf74a31 100644
--- a/net/sched/cls_flower.c
+++ b/net/sched/cls_flower.c
@@ -29,6 +29,9 @@
#include <net/dst.h>
#include <net/dst_metadata.h>
+#include <net/netfilter/nf_conntrack_core.h>
+#include <net/netfilter/nf_conntrack_labels.h>
+
struct fl_flow_key {
int indev_ifindex;
struct flow_dissector_key_control control;
@@ -57,6 +60,11 @@ struct fl_flow_key {
struct flow_dissector_key_enc_opts enc_opts;
struct flow_dissector_key_ports tp_min;
struct flow_dissector_key_ports tp_max;
+
+ u8 ct_state;
+ u16 ct_zone;
+ u32 ct_mark;
+ u32 ct_labels[NF_CT_LABELS_MAX_SIZE / sizeof(u32)];
} __aligned(BITS_PER_LONG / 8); /* Ensure that we can do comparisons as longs. */
struct fl_flow_mask_range {
@@ -265,19 +273,55 @@ static struct cls_fl_filter *fl_lookup(struct fl_flow_mask *mask,
return __fl_lookup(mask, mkey);
}
+static u8 fl_ct_get_state(enum ip_conntrack_info ctinfo)
+{
+ u8 ct_state = TCA_FLOWER_KEY_CT_FLAGS_TRACKED;
+
+ switch (ctinfo) {
+ case IP_CT_ESTABLISHED:
+ case IP_CT_ESTABLISHED_REPLY:
+ ct_state |= TCA_FLOWER_KEY_CT_FLAGS_ESTABLISHED;
+ break;
+ case IP_CT_RELATED:
+ case IP_CT_RELATED_REPLY:
+ ct_state |= TCA_FLOWER_KEY_CT_FLAGS_RELATED;
+ break;
+ case IP_CT_NEW:
+ ct_state |= TCA_FLOWER_KEY_CT_FLAGS_NEW;
+ break;
+ default:
+ break;
+ }
+
+ return ct_state;
+}
+
static int fl_classify(struct sk_buff *skb, const struct tcf_proto *tp,
struct tcf_result *res)
{
struct cls_fl_head *head = rcu_dereference_bh(tp->root);
- struct cls_fl_filter *f;
- struct fl_flow_mask *mask;
- struct fl_flow_key skb_key;
+ enum ip_conntrack_info ctinfo;
struct fl_flow_key skb_mkey;
+ struct fl_flow_key skb_key;
+ struct fl_flow_mask *mask;
+ struct nf_conn_labels *cl;
+ struct cls_fl_filter *f;
+ struct nf_conn *ct;
list_for_each_entry_rcu(mask, &head->masks, list) {
fl_clear_masked_range(&skb_key, mask);
skb_key.indev_ifindex = skb->skb_iif;
+ ct = nf_ct_get(skb, &ctinfo);
+ if (ct) {
+ skb_key.ct_state = fl_ct_get_state(ctinfo);
+ skb_key.ct_zone = ct->zone.id;
+ skb_key.ct_mark = ct->mark;
+
+ cl = nf_ct_labels_find(ct);
+ if (cl)
+ memcpy(skb_key.ct_labels, cl->bits, sizeof(skb_key.ct_labels));
+ }
/* skb_flow_dissect() does not set n_proto in case an unknown
* protocol, so do it rather here.
*/
@@ -562,6 +606,14 @@ static void *fl_get(struct tcf_proto *tp, u32 handle)
[TCA_FLOWER_KEY_ENC_IP_TTL_MASK] = { .type = NLA_U8 },
[TCA_FLOWER_KEY_ENC_OPTS] = { .type = NLA_NESTED },
[TCA_FLOWER_KEY_ENC_OPTS_MASK] = { .type = NLA_NESTED },
+ [TCA_FLOWER_KEY_CT_STATE] = { .type = NLA_U8 },
+ [TCA_FLOWER_KEY_CT_STATE_MASK] = { .type = NLA_U8 },
+ [TCA_FLOWER_KEY_CT_ZONE] = { .type = NLA_U16 },
+ [TCA_FLOWER_KEY_CT_ZONE_MASK] = { .type = NLA_U16 },
+ [TCA_FLOWER_KEY_CT_MARK] = { .type = NLA_U32 },
+ [TCA_FLOWER_KEY_CT_MARK_MASK] = { .type = NLA_U32 },
+ [TCA_FLOWER_KEY_CT_LABELS] = { .type = NLA_UNSPEC, .len = 16 },
+ [TCA_FLOWER_KEY_CT_LABELS_MASK] = { .type = NLA_UNSPEC, .len = 16 },
};
static const struct nla_policy
@@ -872,6 +924,36 @@ static int fl_set_enc_opt(struct nlattr **tb, struct fl_flow_key *key,
return 0;
}
+static int fl_set_key_ct(struct nlattr **tb, struct fl_flow_key *key,
+ struct fl_flow_key *mask,
+ struct netlink_ext_ack *extack)
+{
+ size_t label_len = 0;
+
+ if (tb[TCA_FLOWER_KEY_CT_STATE]) {
+ key->ct_state = nla_get_u8(tb[TCA_FLOWER_KEY_CT_STATE]);
+ mask->ct_state = nla_get_u8(tb[TCA_FLOWER_KEY_CT_STATE_MASK]);
+ }
+
+ if (tb[TCA_FLOWER_KEY_CT_ZONE_MASK]) {
+ key->ct_zone = nla_get_u16(tb[TCA_FLOWER_KEY_CT_ZONE]);
+ mask->ct_zone = nla_get_u16(tb[TCA_FLOWER_KEY_CT_ZONE_MASK]);
+ }
+
+ if (tb[TCA_FLOWER_KEY_CT_MARK_MASK]) {
+ key->ct_mark = nla_get_u32(tb[TCA_FLOWER_KEY_CT_MARK]);
+ mask->ct_mark = nla_get_u32(tb[TCA_FLOWER_KEY_CT_MARK_MASK]);
+ }
+
+ if (tb[TCA_FLOWER_KEY_CT_LABELS_MASK]) {
+ label_len = nla_len(tb[TCA_FLOWER_KEY_CT_LABELS]);
+ memcpy(key->ct_labels, nla_data(tb[TCA_FLOWER_KEY_CT_LABELS]), label_len);
+ memcpy(mask->ct_labels, nla_data(tb[TCA_FLOWER_KEY_CT_LABELS_MASK]), label_len);
+ }
+
+ return 0;
+}
+
static int fl_set_key(struct net *net, struct nlattr **tb,
struct fl_flow_key *key, struct fl_flow_key *mask,
struct netlink_ext_ack *extack)
@@ -1082,6 +1164,10 @@ static int fl_set_key(struct net *net, struct nlattr **tb,
return ret;
}
+ ret = fl_set_key_ct(tb, key, mask, extack);
+ if (ret)
+ return ret;
+
if (tb[TCA_FLOWER_KEY_FLAGS])
ret = fl_set_key_flags(tb, &key->control.flags, &mask->control.flags);
@@ -1761,6 +1847,37 @@ static int fl_dump_key_geneve_opt(struct sk_buff *skb,
return -EMSGSIZE;
}
+static int fl_dump_key_ct(struct sk_buff *skb,
+ struct fl_flow_key *key,
+ struct fl_flow_key *mask)
+{
+ if(fl_dump_key_val(skb, &key->ct_state, TCA_FLOWER_KEY_CT_STATE,
+ &mask->ct_state, TCA_FLOWER_KEY_CT_STATE_MASK,
+ sizeof(key->ct_state)))
+ goto nla_put_failure;
+
+ if (fl_dump_key_val(skb, &key->ct_zone, TCA_FLOWER_KEY_CT_ZONE,
+ &mask->ct_zone, TCA_FLOWER_KEY_CT_ZONE_MASK,
+ sizeof(key->ct_zone)))
+ goto nla_put_failure;
+
+ if (fl_dump_key_val(skb, &key->ct_mark, TCA_FLOWER_KEY_CT_MARK,
+ &mask->ct_mark, TCA_FLOWER_KEY_CT_MARK_MASK,
+ sizeof(key->ct_mark)))
+ goto nla_put_failure;
+
+ if (fl_dump_key_val(skb, &key->ct_labels, TCA_FLOWER_KEY_CT_LABELS,
+ &mask->ct_labels, TCA_FLOWER_KEY_CT_LABELS_MASK,
+ sizeof(key->ct_labels)))
+ goto nla_put_failure;
+
+ return 0;
+
+nla_put_failure:
+ return -EMSGSIZE;
+}
+
+
static int fl_dump_key_options(struct sk_buff *skb, int enc_opt_type,
struct flow_dissector_key_enc_opts *enc_opts)
{
@@ -1994,6 +2111,9 @@ static int fl_dump_key(struct sk_buff *skb, struct net *net,
fl_dump_key_enc_opt(skb, &key->enc_opts, &mask->enc_opts))
goto nla_put_failure;
+ if (fl_dump_key_ct(skb, key, mask))
+ goto nla_put_failure;
+
if (fl_dump_key_flags(skb, key->control.flags, mask->control.flags))
goto nla_put_failure;
--
1.8.3.1
Powered by blists - more mailing lists