From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.2 required=3.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_PASS,UNPARSEABLE_RELAY, UNWANTED_LANGUAGE_BODY,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4CAADC169C4 for ; Tue, 29 Jan 2019 08:02:33 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 1A62B214DA for ; Tue, 29 Jan 2019 08:02:33 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727207AbfA2ICc (ORCPT ); Tue, 29 Jan 2019 03:02:32 -0500 Received: from mail-il-dmz.mellanox.com ([193.47.165.129]:44665 "EHLO mellanox.co.il" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1726994AbfA2ICb (ORCPT ); Tue, 29 Jan 2019 03:02:31 -0500 Received: from Internal Mail-Server by MTLPINE1 (envelope-from paulb@mellanox.com) with ESMTPS (AES256-SHA encrypted); 29 Jan 2019 10:02:24 +0200 Received: from reg-r-vrt-019-180.mtr.labs.mlnx (reg-r-vrt-019-180.mtr.labs.mlnx [10.213.19.180]) by labmailer.mlnx (8.13.8/8.13.8) with ESMTP id x0T82L0q006061; Tue, 29 Jan 2019 10:02:24 +0200 From: Paul Blakey To: Guy Shattah , Marcelo Leitner , Aaron Conole , John Hurley , Simon Horman , Justin Pettit , Gregory Rose , Eelco Chaudron , Flavio Leitner , Florian Westphal , Jiri Pirko , Rashid Khan , Sushil Kulkarni , Andy Gospodarek , Roi Dayan , Yossi Kuperman , Or Gerlitz , Rony Efraim , "davem@davemloft.net" , netdev@vger.kernel.org Cc: Paul Blakey Subject: [RFC PATCH net-next 2/6 v2] net/sched: cls_flower: add match on ct info Date: Tue, 29 Jan 2019 10:02:02 +0200 Message-Id: <1548748926-23822-3-git-send-email-paulb@mellanox.com> X-Mailer: git-send-email 1.8.4.3 In-Reply-To: <1548748926-23822-2-git-send-email-paulb@mellanox.com> References: <1548748926-23822-2-git-send-email-paulb@mellanox.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org 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 --- 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 #include +#include +#include + 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