From patchwork Mon Jan 13 18:05:30 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sowmini Varadhan X-Patchwork-Id: 64575 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id B2EA0A04F1; Mon, 13 Jan 2020 19:05:59 +0100 (CET) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 3BDC51D17A; Mon, 13 Jan 2020 19:05:45 +0100 (CET) Received: from mail-qk1-f193.google.com (mail-qk1-f193.google.com [209.85.222.193]) by dpdk.org (Postfix) with ESMTP id AB1A31D14A for ; Mon, 13 Jan 2020 19:05:40 +0100 (CET) Received: by mail-qk1-f193.google.com with SMTP id x129so9336809qke.8 for ; Mon, 13 Jan 2020 10:05:40 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:subject:date:message-id:in-reply-to:references:in-reply-to :references; bh=oMkNLd4B4GkgFyfNiHTYuTlMAIjwW/47ozBO2IbJl/Y=; b=o2vnICIaWy/8GS1kSuHe9S+2y/MrzNz8yNM7ROlYUyfzmQQ8czLbWoCE+s0Y36RBdz XYKRnJ/XfTTZmMbrYq/BVwY19WDdVdRLLXdj/Gbsw3O2OIqS5gN/xYQRJ+9n/HQCNPdp xTOzfld7i8nbOgMtLZuRVQ3ILmzMrmz6OHeNSgm85KplWS6vG3J1zvpaNHPZGKC55BYW EWZL0EdM9pREywFPom8ELqmV7NeLznx00NdOAtR3YgAdIk2kmVzSvHCTo/s2NRNPm7WK 9F4L6Z1J3X/MFY/y+iGwLQQiWiSpGWPYSOosafihAG3sCPFqtE9lxp9ZJ4H3gToyVXZk hPiA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:in-reply-to:references; bh=oMkNLd4B4GkgFyfNiHTYuTlMAIjwW/47ozBO2IbJl/Y=; b=E9eYWG3SOLsC0zwn5wUhSQyG9GXUZ5+WS+K5abkr2Xj5NwFog6R5rpyopm6UQfnIPR 3q2zSrtP7xHOoWoEGfGaqIKOMpKBTfGOoSOaGV9xPenBCEo5q0TTSUMEUCNwkubDCRW8 cnO5MHsgWOMYF8ROZQvDbcdp63oQsKmSGECE2FXP4JigG+mnYRmnrVVXQ0KaheIUDk6c lt/AUHZ2oY6gWeRbTU/FSDudG1aSZlqAXsbVQApG4yu3isW7TIhGIb3Bo70NQHN5ITWG 3JS4y+SbcwVy1Q3UN5u9Saqk0SdloFQiQkRuDutDWjK0+/qxN/Bh2HeKUzXhw7/ZcWCh jsjw== X-Gm-Message-State: APjAAAWanB/yxYxiz4U47lxm9vNQzaUQ8lWuWZP++ykS9d+BJbFN4PSO WMpC1j7bwMuXz1diwwEW4o0= X-Google-Smtp-Source: APXvYqwCNc1g09nlGBu5d26J1ilqbuAAS68AGX398/dnHMp1s4Hbw8fFyYQDbJhi3BOW0/fT8CjNiw== X-Received: by 2002:ae9:efc5:: with SMTP id d188mr17368920qkg.178.1578938739970; Mon, 13 Jan 2020 10:05:39 -0800 (PST) Received: from sovaradhvm.ojp4suxva1celnnpiyhedynfde.bx.internal.cloudapp.net ([104.211.12.148]) by smtp.gmail.com with ESMTPSA id a36sm6272483qtk.29.2020.01.13.10.05.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 13 Jan 2020 10:05:39 -0800 (PST) From: Sowmini Varadhan To: sowmini05@gmail.com, dev@dpdk.org Date: Mon, 13 Jan 2020 18:05:30 +0000 Message-Id: X-Mailer: git-send-email 2.17.1 In-Reply-To: References: In-Reply-To: References: Subject: [dpdk-dev] [PATCH RFC V2 2/2] Allow the flow_classify example to add an ACL table for tcp. X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" The struct rte_flow_classifier can have upto RTE_FLOW_CLASSIFY_TABLE_MAX (32) classifier tables, but the existing flow_classify examples only adds a single table for the L4 5-tuple. When dealing with tcp flows, we frequently want to add add ACLs and filters to filter based on the state of the TCP connection, e.g., by looking at the tcp flags field. So we enhance flow_classify to add an additional acl table for tcp 5-typles. If the input-file-parser detects a filter for a tcp flow with a non-wildcard argument for tcp_flags, the IP4_TCP_5TUPLE table is used by flow_classify. Signed-off-by: Sowmini Varadhan --- V2 updates: checkpatch fixes examples/flow_classify/flow_classify.c | 44 +++++++--- lib/librte_flow_classify/rte_flow_classify.c | 87 +++++++++++++++++++ lib/librte_flow_classify/rte_flow_classify.h | 19 ++++ .../rte_flow_classify_parse.c | 8 +- 4 files changed, 144 insertions(+), 14 deletions(-) diff --git a/examples/flow_classify/flow_classify.c b/examples/flow_classify/flow_classify.c index e8a41741f..a0d138eb5 100644 --- a/examples/flow_classify/flow_classify.c +++ b/examples/flow_classify/flow_classify.c @@ -708,11 +708,6 @@ add_classify_rule(struct rte_eth_ntuple_filter *ntuple_filter, return ret; } - /* XXX but this only adds table_type of - * RTE_FLOW_CLASSIFY_TABLE_ACL_IP4_5TUPLE - * i.e., it only ever does allocate_acl_ipv4_5tuple_rule() - * so the tcp_flags is ignored! - */ rule = rte_flow_classify_table_entry_add( cls_app->cls, &attr, pattern_ipv4_5tuple, actions, &key_found, &error); @@ -839,7 +834,8 @@ main(int argc, char *argv[]) int ret; int socket_id; struct rte_table_acl_params table_acl_params; - struct rte_flow_classify_table_params cls_table_params; + struct rte_table_acl_params table_acl_tcp_params; + struct rte_flow_classify_table_params cls_table_params[2]; struct flow_classifier *cls_app; struct rte_flow_classifier_params cls_params; uint32_t size; @@ -902,20 +898,42 @@ main(int argc, char *argv[]) memcpy(table_acl_params.field_format, ipv4_defs, sizeof(ipv4_defs)); /* initialise table create params */ - cls_table_params.ops = &rte_table_acl_ops; - cls_table_params.arg_create = &table_acl_params; - cls_table_params.type = RTE_FLOW_CLASSIFY_TABLE_ACL_IP4_5TUPLE; + cls_table_params[0].ops = &rte_table_acl_ops; + cls_table_params[0].arg_create = &table_acl_params; + cls_table_params[0].type = RTE_FLOW_CLASSIFY_TABLE_ACL_IP4_5TUPLE; + + /* initialise ACL table params */ + table_acl_tcp_params.name = "table_acl_ipv4_tcp_5tuple"; + table_acl_tcp_params.n_rules = FLOW_CLASSIFY_MAX_RULE_NUM; + table_acl_tcp_params.n_rule_fields = RTE_DIM(ipv4_defs); + memcpy(table_acl_tcp_params.field_format, ipv4_defs, sizeof(ipv4_defs)); + + /* initialise table create params */ + cls_table_params[1].ops = &rte_table_acl_ops; + cls_table_params[1].arg_create = &table_acl_tcp_params; + cls_table_params[1].type = RTE_FLOW_CLASSIFY_TABLE_ACL_IP4_TCP_5TUPLE; - ret = rte_flow_classify_table_create(cls_app->cls, &cls_table_params); + ret = rte_flow_classify_table_create(cls_app->cls, + &cls_table_params[0]); if (ret) { rte_flow_classifier_free(cls_app->cls); rte_free(cls_app); - rte_exit(EXIT_FAILURE, "Failed to create classifier table\n"); + rte_exit(EXIT_FAILURE, + "Failed to create classifier table\n"); } + ret = rte_flow_classify_table_create(cls_app->cls, + &cls_table_params[1]); + if (ret) { + rte_flow_classifier_free(cls_app->cls); + rte_free(cls_app); + rte_exit(EXIT_FAILURE, + "Failed to create classifier table\n"); + } + /* read file of IPv4 5 tuple rules and initialize parameters - * for rte_flow_classify_validate and rte_flow_classify_table_entry_add - * API's. + * for rte_flow_classify_validate and + * rte_flow_classify_table_entry_add API's. */ if (add_rules(parm_config.rule_ipv4_name, cls_app)) { rte_flow_classifier_free(cls_app->cls); diff --git a/lib/librte_flow_classify/rte_flow_classify.c b/lib/librte_flow_classify/rte_flow_classify.c index 5ff585803..cda1a6129 100644 --- a/lib/librte_flow_classify/rte_flow_classify.c +++ b/lib/librte_flow_classify/rte_flow_classify.c @@ -62,6 +62,7 @@ enum { DST_FIELD_IPV4, SRCP_FIELD_IPV4, DSTP_FIELD_IPV4, + TCP_FLAGS_FIELD, NUM_FIELDS_IPV4 }; @@ -74,6 +75,7 @@ struct classify_rules { enum rte_flow_classify_rule_type type; union { struct rte_flow_classify_ipv4_5tuple ipv4_5tuple; + struct rte_flow_classify_ipv4_tcp_5tuple ipv4_tcp_5tuple; } u; }; @@ -482,6 +484,84 @@ allocate_acl_ipv4_5tuple_rule(struct rte_flow_classifier *cls) return rule; } +static struct rte_flow_classify_rule * +allocate_acl_ipv4_tcp_5tuple_rule(struct rte_flow_classifier *cls) +{ + struct rte_flow_classify_rule *rule; + int log_level; + + rule = malloc(sizeof(struct rte_flow_classify_rule)); + if (!rule) + return rule; + + memset(rule, 0, sizeof(struct rte_flow_classify_rule)); + rule->id = unique_id++; + rule->rules.type = RTE_FLOW_CLASSIFY_RULE_TYPE_IPV4_TCP_5TUPLE; + + /* key add values */ + rule->u.key.key_add.priority = cls->ntuple_filter.priority; + rule->u.key.key_add.field_value[PROTO_FIELD_IPV4].mask_range.u8 = + cls->ntuple_filter.proto_mask; + rule->u.key.key_add.field_value[PROTO_FIELD_IPV4].value.u8 = + cls->ntuple_filter.proto; + rule->rules.u.ipv4_tcp_5tuple.proto = cls->ntuple_filter.proto; + rule->rules.u.ipv4_tcp_5tuple.proto_mask = + cls->ntuple_filter.proto_mask; + + rule->u.key.key_add.field_value[SRC_FIELD_IPV4].mask_range.u32 = + cls->ntuple_filter.src_ip_mask; + rule->u.key.key_add.field_value[SRC_FIELD_IPV4].value.u32 = + cls->ntuple_filter.src_ip; + rule->rules.u.ipv4_tcp_5tuple.src_ip_mask = + cls->ntuple_filter.src_ip_mask; + rule->rules.u.ipv4_tcp_5tuple.src_ip = cls->ntuple_filter.src_ip; + + rule->u.key.key_add.field_value[DST_FIELD_IPV4].mask_range.u32 = + cls->ntuple_filter.dst_ip_mask; + rule->u.key.key_add.field_value[DST_FIELD_IPV4].value.u32 = + cls->ntuple_filter.dst_ip; + rule->rules.u.ipv4_tcp_5tuple.dst_ip_mask = + cls->ntuple_filter.dst_ip_mask; + rule->rules.u.ipv4_tcp_5tuple.dst_ip = cls->ntuple_filter.dst_ip; + + rule->u.key.key_add.field_value[SRCP_FIELD_IPV4].mask_range.u16 = + cls->ntuple_filter.src_port_mask; + rule->u.key.key_add.field_value[SRCP_FIELD_IPV4].value.u16 = + cls->ntuple_filter.src_port; + rule->rules.u.ipv4_tcp_5tuple.src_port_mask = + cls->ntuple_filter.src_port_mask; + rule->rules.u.ipv4_tcp_5tuple.src_port = cls->ntuple_filter.src_port; + + rule->u.key.key_add.field_value[DSTP_FIELD_IPV4].mask_range.u16 = + cls->ntuple_filter.dst_port_mask; + rule->u.key.key_add.field_value[DSTP_FIELD_IPV4].value.u16 = + cls->ntuple_filter.dst_port; + rule->rules.u.ipv4_tcp_5tuple.dst_port_mask = + cls->ntuple_filter.dst_port_mask; + rule->rules.u.ipv4_tcp_5tuple.dst_port = cls->ntuple_filter.dst_port; + + rule->u.key.key_add.field_value[TCP_FLAGS_FIELD].mask_range.u32 = + rte_be_to_cpu_32(0xff); + rule->u.key.key_add.field_value[TCP_FLAGS_FIELD].value.u32 = + rte_be_to_cpu_32(cls->ntuple_filter.tcp_flags); + rule->rules.u.ipv4_tcp_5tuple.tcp_flags = cls->ntuple_filter.tcp_flags; + + log_level = rte_log_get_level(librte_flow_classify_logtype); + + if (log_level == RTE_LOG_DEBUG) + print_acl_ipv4_key_add(&rule->u.key.key_add); + + /* key delete values */ + memcpy(&rule->u.key.key_del.field_value[PROTO_FIELD_IPV4], + &rule->u.key.key_add.field_value[PROTO_FIELD_IPV4], + NUM_FIELDS_IPV4 * sizeof(struct rte_acl_field)); + + if (log_level == RTE_LOG_DEBUG) + print_acl_ipv4_key_delete(&rule->u.key.key_del); + + return rule; +} + struct rte_flow_classify_rule * rte_flow_classify_table_entry_add(struct rte_flow_classifier *cls, const struct rte_flow_attr *attr, @@ -519,6 +599,13 @@ rte_flow_classify_table_entry_add(struct rte_flow_classifier *cls, rule->tbl_type = table_type; cls->table_mask |= table_type; break; + case RTE_FLOW_CLASSIFY_TABLE_ACL_IP4_TCP_5TUPLE: + rule = allocate_acl_ipv4_tcp_5tuple_rule(cls); + if (!rule) + return NULL; + rule->tbl_type = table_type; + cls->table_mask |= table_type; + break; default: return NULL; } diff --git a/lib/librte_flow_classify/rte_flow_classify.h b/lib/librte_flow_classify/rte_flow_classify.h index 74d1ecaf5..921277f90 100644 --- a/lib/librte_flow_classify/rte_flow_classify.h +++ b/lib/librte_flow_classify/rte_flow_classify.h @@ -78,6 +78,8 @@ enum rte_flow_classify_rule_type { RTE_FLOW_CLASSIFY_RULE_TYPE_NONE, /** IPv4 5tuple type */ RTE_FLOW_CLASSIFY_RULE_TYPE_IPV4_5TUPLE, + /** IPv4 TCP 5tuple type */ + RTE_FLOW_CLASSIFY_RULE_TYPE_IPV4_TCP_5TUPLE, }; /** Flow classify table type */ @@ -90,6 +92,8 @@ enum rte_flow_classify_table_type { RTE_FLOW_CLASSIFY_TABLE_ACL_VLAN_IP4_5TUPLE = 1 << 2, /** ACL QinQ IP4 5TUPLE */ RTE_FLOW_CLASSIFY_TABLE_ACL_QINQ_IP4_5TUPLE = 1 << 3, + /** ACL IP4 5TUPLE with tcp_flags */ + RTE_FLOW_CLASSIFY_TABLE_ACL_IP4_TCP_5TUPLE = 1 << 4, }; @@ -129,6 +133,21 @@ struct rte_flow_classify_ipv4_5tuple { uint8_t proto_mask; /**< Mask of L4 protocol. */ }; +/** IPv4 5-tuple data with tcp flags*/ +struct rte_flow_classify_ipv4_tcp_5tuple { + uint32_t dst_ip; /**< Destination IP address in big endian. */ + uint32_t dst_ip_mask; /**< Mask of destination IP address. */ + uint32_t src_ip; /**< Source IP address in big endian. */ + uint32_t src_ip_mask; /**< Mask of destination IP address. */ + uint16_t dst_port; /**< Destination port in big endian. */ + uint16_t dst_port_mask; /**< Mask of destination port. */ + uint16_t src_port; /**< Source Port in big endian. */ + uint16_t src_port_mask; /**< Mask of source port. */ + uint8_t proto; /**< L4 protocol. */ + uint8_t proto_mask; /**< Mask of L4 protocol. */ + uint8_t tcp_flags; /**< Tcp only */ +}; + /** * Flow stats * diff --git a/lib/librte_flow_classify/rte_flow_classify_parse.c b/lib/librte_flow_classify/rte_flow_classify_parse.c index 465330291..fe4ee05b6 100644 --- a/lib/librte_flow_classify/rte_flow_classify_parse.c +++ b/lib/librte_flow_classify/rte_flow_classify_parse.c @@ -216,6 +216,7 @@ classify_parse_ntuple_filter(const struct rte_flow_attr *attr, const struct rte_flow_action_count *count; const struct rte_flow_action_mark *mark_spec; uint32_t index; + bool have_tcp = false; /* parse pattern */ index = 0; @@ -375,6 +376,8 @@ classify_parse_ntuple_filter(const struct rte_flow_attr *attr, filter->dst_port = tcp_spec->hdr.dst_port; filter->src_port = tcp_spec->hdr.src_port; filter->tcp_flags = tcp_spec->hdr.tcp_flags; + if (filter->tcp_flags != 0) + have_tcp = true; } else if (item->type == RTE_FLOW_ITEM_TYPE_UDP) { udp_mask = item->mask; @@ -434,7 +437,10 @@ classify_parse_ntuple_filter(const struct rte_flow_attr *attr, return -EINVAL; } - table_type = RTE_FLOW_CLASSIFY_TABLE_ACL_IP4_5TUPLE; + if (have_tcp) + table_type = RTE_FLOW_CLASSIFY_TABLE_ACL_IP4_TCP_5TUPLE; + else + table_type = RTE_FLOW_CLASSIFY_TABLE_ACL_IP4_5TUPLE; /* parse attr */ /* must be input direction */