From patchwork Wed Jun 22 01:22:23 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Satheesh Paul Antonysamy X-Patchwork-Id: 113198 X-Patchwork-Delegate: gakhil@marvell.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 78B19A00C3; Wed, 22 Jun 2022 03:22:33 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 53CE34069C; Wed, 22 Jun 2022 03:22:33 +0200 (CEST) Received: from mx0b-0016f401.pphosted.com (mx0a-0016f401.pphosted.com [67.231.148.174]) by mails.dpdk.org (Postfix) with ESMTP id BFC5840151 for ; Wed, 22 Jun 2022 03:22:31 +0200 (CEST) Received: from pps.filterd (m0045849.ppops.net [127.0.0.1]) by mx0a-0016f401.pphosted.com (8.17.1.5/8.17.1.5) with ESMTP id 25LLVFV9001710; Tue, 21 Jun 2022 18:22:30 -0700 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=marvell.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=pfpt0220; bh=IosZjX1bqtgHw77tmAFHdMuu9DHmL6M36nihRCUx/Js=; b=VVKk+8rVZ4D9YUiu6KP4LALXvFujs0q21EKijv0T7874Eu5seoYBD2l2XgNQDhEaVJ0e 25/DMDCSqhXU2eTmnPo8LZlcJF92I9zXXTamDPDy2lx71dIWnCuPbzLvH0jEJl4ttu5J +Dl6QShewPjWCna5waJoyZ4KOT8KcCqR6sSc3vpkMVICo+oVsKq9X34YYZvDcGccK6aC XLpvqJv5suqRjDNH4lfVB9A/EKNDKA+QMCBi5OALujgY3rp2yt6NEYq0DfJh+LT+rh/R xvC1ivzt7Hx27C4BZgTdD67nIQ7zCZ6sodeaJ2EEVKA6MpxKeegFbO0WNHjansj9gKtu cQ== Received: from dc5-exch02.marvell.com ([199.233.59.182]) by mx0a-0016f401.pphosted.com (PPS) with ESMTPS id 3gu47pwtpp-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT); Tue, 21 Jun 2022 18:22:30 -0700 Received: from DC5-EXCH01.marvell.com (10.69.176.38) by DC5-EXCH02.marvell.com (10.69.176.39) with Microsoft SMTP Server (TLS) id 15.0.1497.18; Tue, 21 Jun 2022 18:22:29 -0700 Received: from maili.marvell.com (10.69.176.80) by DC5-EXCH01.marvell.com (10.69.176.38) with Microsoft SMTP Server id 15.0.1497.2 via Frontend Transport; Tue, 21 Jun 2022 18:22:29 -0700 Received: from satheeshpaullabpc.. (unknown [10.28.34.33]) by maili.marvell.com (Postfix) with ESMTP id 129983F7090; Tue, 21 Jun 2022 18:22:26 -0700 (PDT) From: To: Radu Nicolau , Akhil Goyal CC: , Satheesh Paul Subject: [dpdk-dev] [PATCH v5] examples/ipsec-secgw: support more flow patterns and actions Date: Wed, 22 Jun 2022 06:52:23 +0530 Message-ID: <20220622012223.1903350-1-psatheesh@marvell.com> X-Mailer: git-send-email 2.35.3 In-Reply-To: <20220419082537.270116-1-psatheesh@marvell.com> References: <20220419082537.270116-1-psatheesh@marvell.com> MIME-Version: 1.0 X-Proofpoint-GUID: 3VD-E_4xJN7Da9pftfdgnx63ScXBTXnm X-Proofpoint-ORIG-GUID: 3VD-E_4xJN7Da9pftfdgnx63ScXBTXnm X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.883,Hydra:6.0.517,FMLib:17.11.64.514 definitions=2022-06-21_11,2022-06-21_01,2022-02-23_01 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org From: Satheesh Paul Added support to create flow rules with count, mark and security actions and mark pattern. Signed-off-by: Satheesh Paul Acked-by: Fan Zhang Acked-by: Akhil Goyal --- v5: * Rebased the patch. v4: * Added more description in documenation for flow rule options. v3: * Fixed IPv4 and IPv6 dst addr setting in flow pattern spec. v2: * Updated documentation in ipsec_secgw.rst. doc/guides/sample_app_ug/ipsec_secgw.rst | 63 +++++- examples/ipsec-secgw/flow.c | 274 +++++++++++++++++++---- examples/ipsec-secgw/flow.h | 1 + examples/ipsec-secgw/ipsec-secgw.c | 3 +- 4 files changed, 290 insertions(+), 51 deletions(-) diff --git a/doc/guides/sample_app_ug/ipsec_secgw.rst b/doc/guides/sample_app_ug/ipsec_secgw.rst index 94197a34f0..7032da8d0d 100644 --- a/doc/guides/sample_app_ug/ipsec_secgw.rst +++ b/doc/guides/sample_app_ug/ipsec_secgw.rst @@ -890,16 +890,35 @@ The flow rule syntax is shown as follows: .. code-block:: console - flow - + flow \ + where each options means: +```` + + * Set RTE_FLOW_ITEM_TYPE_MARK pattern item in the flow rule with the given + mark value. This option can be used to match an arbitrary integer value + which was set using the RTE_FLOW_ACTION_TYPE_MARK action (see ````) + in a previously matched rule. + + * Optional: Yes, this pattern is not set by default. + + * Syntax: *mark X* + +```` + + * Set RTE_FLOW_ITEM_TYPE_ETH pattern item. This matches all ethernet packets. + + * Optional: Yes, this pattern is not set by default. + + * Syntax: *eth* + ```` * IP protocol version - * Optional: No + * Optional: Yes, this pattern is not set by default. * Available options: @@ -944,6 +963,32 @@ where each options means: * Syntax: *queue X* +```` + + * Set RTE_FLOW_ACTION_TYPE_COUNT action. + + * Optional: yes, this action is not set by default. + + * Syntax: *count* + +```` + + * Set RTE_FLOW_ITEM_TYPE_ESP pattern and RTE_FLOW_ACTION_TYPE_SECURITY action. + + * Optional: yes, this pattern and action are not set by default. + + * Syntax: *security* + +```` + + * Set RTE_FLOW_ACTION_TYPE_MARK action in the flow rule with the given mark + value. This option can be used to set the given integer value(mark) to + packets and set RTE_MBUF_F_RX_FDIR and RTE_MBUF_F_RX_FDIR_ID mbuf flags. + + * Optional: yes, this action is not set by default. + + * Syntax: *set_mark X* + Example flow rules: .. code-block:: console @@ -952,6 +997,18 @@ Example flow rules: flow ipv6 dst 1111:1111:1111:1111:1111:1111:1111:5555/116 port 1 queue 0 + flow mark 123 ipv4 dst 192.168.0.0/16 port 0 queue 0 count + + flow eth ipv4 dst 192.168.0.0/16 port 0 queue 0 count + + flow ipv4 dst 192.168.0.0/16 port 0 queue 0 count + + flow ipv4 dst 192.168.0.0/16 port 0 queue 0 + + flow port 0 security set_mark 123 + + flow ipv4 dst 1.1.0.0/16 port 0 count set_mark 123 security + Neighbour rule syntax ^^^^^^^^^^^^^^^^^^^^^ diff --git a/examples/ipsec-secgw/flow.c b/examples/ipsec-secgw/flow.c index c217b9e475..aee97b2fc4 100644 --- a/examples/ipsec-secgw/flow.c +++ b/examples/ipsec-secgw/flow.c @@ -15,7 +15,9 @@ #define FLOW_RULES_MAX 128 struct flow_rule_entry { + uint8_t is_eth; uint8_t is_ipv4; + uint8_t is_ipv6; RTE_STD_C11 union { struct { @@ -27,8 +29,15 @@ struct flow_rule_entry { struct rte_flow_item_ipv6 mask; } ipv6; }; + struct rte_flow_item_mark mark_val; uint16_t port; uint16_t queue; + bool is_queue_set; + bool enable_count; + bool enable_mark; + bool set_security_action; + bool set_mark_action; + uint32_t mark_action_val; struct rte_flow *flow; } flow_rule_tbl[FLOW_RULES_MAX]; @@ -64,8 +73,9 @@ ipv4_addr_cpy(rte_be32_t *spec, rte_be32_t *mask, char *token, memcpy(mask, &rte_flow_item_ipv4_mask.hdr.src_addr, sizeof(ip)); *spec = ip.s_addr; + if (depth < 32) - *mask = *mask << (32-depth); + *mask = htonl(*mask << (32 - depth)); return 0; } @@ -124,7 +134,7 @@ parse_flow_tokens(char **tokens, uint32_t n_tokens, struct parse_status *status) { struct flow_rule_entry *rule; - uint32_t ti; + uint32_t ti = 0; if (nb_flow_rule >= FLOW_RULES_MAX) { printf("Too many flow rules\n"); @@ -134,49 +144,73 @@ parse_flow_tokens(char **tokens, uint32_t n_tokens, rule = &flow_rule_tbl[nb_flow_rule]; memset(rule, 0, sizeof(*rule)); - if (strcmp(tokens[0], "ipv4") == 0) { - rule->is_ipv4 = 1; - } else if (strcmp(tokens[0], "ipv6") == 0) { - rule->is_ipv4 = 0; - } else { - APP_CHECK(0, status, "unrecognized input \"%s\"", tokens[0]); - return; - } - - for (ti = 1; ti < n_tokens; ti++) { - if (strcmp(tokens[ti], "src") == 0) { + for (ti = 0; ti < n_tokens; ti++) { + if (strcmp(tokens[ti], "mark") == 0) { INCREMENT_TOKEN_INDEX(ti, n_tokens, status); + if (status->status < 0) + return; + APP_CHECK_TOKEN_IS_NUM(tokens, ti, status); if (status->status < 0) return; - if (rule->is_ipv4) { + rule->mark_val.id = atoi(tokens[ti]); + rule->enable_mark = true; + continue; + } + if (strcmp(tokens[ti], "eth") == 0) { + rule->is_eth = true; + continue; + } + + if (strcmp(tokens[ti], "ipv4") == 0) { + rule->is_ipv4 = true; + INCREMENT_TOKEN_INDEX(ti, n_tokens, status); + if (status->status < 0) + return; + if (strcmp(tokens[ti], "src") == 0) { + INCREMENT_TOKEN_INDEX(ti, n_tokens, status); + if (status->status < 0) + return; if (ipv4_addr_cpy(&rule->ipv4.spec.hdr.src_addr, &rule->ipv4.mask.hdr.src_addr, tokens[ti], status)) return; - } else { - if (ipv6_addr_cpy(rule->ipv6.spec.hdr.src_addr, - rule->ipv6.mask.hdr.src_addr, + } + if (strcmp(tokens[ti], "dst") == 0) { + INCREMENT_TOKEN_INDEX(ti, n_tokens, status); + if (status->status < 0) + return; + if (ipv4_addr_cpy(&rule->ipv4.spec.hdr.dst_addr, + &rule->ipv4.mask.hdr.dst_addr, tokens[ti], status)) return; } + continue; } - if (strcmp(tokens[ti], "dst") == 0) { + if (strcmp(tokens[ti], "ipv6") == 0) { + rule->is_ipv6 = true; INCREMENT_TOKEN_INDEX(ti, n_tokens, status); if (status->status < 0) return; - - if (rule->is_ipv4) { - if (ipv4_addr_cpy(&rule->ipv4.spec.hdr.dst_addr, - &rule->ipv4.mask.hdr.dst_addr, + if (strcmp(tokens[ti], "src") == 0) { + INCREMENT_TOKEN_INDEX(ti, n_tokens, status); + if (status->status < 0) + return; + if (ipv6_addr_cpy(rule->ipv6.spec.hdr.src_addr, + rule->ipv6.mask.hdr.src_addr, tokens[ti], status)) return; - } else { + } + if (strcmp(tokens[ti], "dst") == 0) { + INCREMENT_TOKEN_INDEX(ti, n_tokens, status); + if (status->status < 0) + return; if (ipv6_addr_cpy(rule->ipv6.spec.hdr.dst_addr, rule->ipv6.mask.hdr.dst_addr, tokens[ti], status)) return; } + continue; } if (strcmp(tokens[ti], "port") == 0) { @@ -188,6 +222,7 @@ parse_flow_tokens(char **tokens, uint32_t n_tokens, return; rule->port = atoi(tokens[ti]); + continue; } if (strcmp(tokens[ti], "queue") == 0) { @@ -199,50 +234,129 @@ parse_flow_tokens(char **tokens, uint32_t n_tokens, return; rule->queue = atoi(tokens[ti]); + rule->is_queue_set = true; + continue; + } + + if (strcmp(tokens[ti], "count") == 0) { + rule->enable_count = true; + continue; + } + + if (strcmp(tokens[ti], "security") == 0) { + rule->set_security_action = true; + continue; } + if (strcmp(tokens[ti], "set_mark") == 0) { + INCREMENT_TOKEN_INDEX(ti, n_tokens, status); + if (status->status < 0) + return; + APP_CHECK_TOKEN_IS_NUM(tokens, ti, status); + if (status->status < 0) + return; + + rule->set_mark_action = true; + rule->mark_action_val = atoi(tokens[ti]); + continue; + } + + sprintf(status->parse_msg, "Unrecognized input:%s\n", + tokens[ti]); + status->status = -1; + return; } + printf("\n"); nb_flow_rule++; } -#define MAX_RTE_FLOW_PATTERN (3) -#define MAX_RTE_FLOW_ACTIONS (2) +#define MAX_RTE_FLOW_PATTERN (4) +#define MAX_RTE_FLOW_ACTIONS (5) static void flow_init_single(struct flow_rule_entry *rule) { - struct rte_flow_item pattern[MAX_RTE_FLOW_PATTERN] = {}; struct rte_flow_action action[MAX_RTE_FLOW_ACTIONS] = {}; + struct rte_flow_item pattern[MAX_RTE_FLOW_PATTERN] = {}; + struct rte_flow_action_queue queue_action; + struct rte_flow_action_mark mark_action; + int ret, pattern_idx = 0, act_idx = 0; + struct rte_flow_item_mark mark_mask; struct rte_flow_attr attr = {}; struct rte_flow_error err = {}; - int ret; attr.egress = 0; attr.ingress = 1; - action[0].type = RTE_FLOW_ACTION_TYPE_QUEUE; - action[0].conf = &(struct rte_flow_action_queue) { - .index = rule->queue, - }; - action[1].type = RTE_FLOW_ACTION_TYPE_END; + if (rule->is_queue_set) { + queue_action.index = rule->queue; + action[act_idx].type = RTE_FLOW_ACTION_TYPE_QUEUE; + action[act_idx].conf = &queue_action; + act_idx++; + } - pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH; + if (rule->enable_count) { + action[act_idx].type = RTE_FLOW_ACTION_TYPE_COUNT; + act_idx++; + } + + if (rule->set_security_action) { + action[act_idx].type = RTE_FLOW_ACTION_TYPE_SECURITY; + action[act_idx].conf = NULL; + act_idx++; + } + + if (rule->set_mark_action) { + mark_action.id = rule->mark_action_val; + action[act_idx].type = RTE_FLOW_ACTION_TYPE_MARK; + action[act_idx].conf = &mark_action; + act_idx++; + } + + action[act_idx].type = RTE_FLOW_ACTION_TYPE_END; + action[act_idx].conf = NULL; + + if (rule->enable_mark) { + mark_mask.id = UINT32_MAX; + pattern[pattern_idx].type = RTE_FLOW_ITEM_TYPE_MARK; + pattern[pattern_idx].spec = &rule->mark_val; + pattern[pattern_idx].mask = &mark_mask; + pattern_idx++; + } + + if (rule->is_eth) { + pattern[pattern_idx].type = RTE_FLOW_ITEM_TYPE_ETH; + pattern_idx++; + } if (rule->is_ipv4) { - pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV4; - pattern[1].spec = &rule->ipv4.spec; - pattern[1].mask = &rule->ipv4.mask; - } else { - pattern[1].type = RTE_FLOW_ITEM_TYPE_IPV6; - pattern[1].spec = &rule->ipv6.spec; - pattern[1].mask = &rule->ipv6.mask; + pattern[pattern_idx].type = RTE_FLOW_ITEM_TYPE_IPV4; + pattern[pattern_idx].spec = &rule->ipv4.spec; + pattern[pattern_idx].mask = &rule->ipv4.mask; + pattern_idx++; + } + + if (rule->is_ipv6) { + pattern[pattern_idx].type = RTE_FLOW_ITEM_TYPE_IPV6; + pattern[pattern_idx].spec = &rule->ipv6.spec; + pattern[pattern_idx].mask = &rule->ipv6.mask; + pattern_idx++; } - pattern[2].type = RTE_FLOW_ITEM_TYPE_END; + if (rule->set_security_action) { + pattern[pattern_idx].type = RTE_FLOW_ITEM_TYPE_ESP; + pattern[pattern_idx].spec = NULL; + pattern[pattern_idx].mask = NULL; + pattern[pattern_idx].last = NULL; + pattern_idx++; + } + + pattern[pattern_idx].type = RTE_FLOW_ITEM_TYPE_END; ret = rte_flow_validate(rule->port, &attr, pattern, action, &err); if (ret < 0) { RTE_LOG(ERR, IPSEC, "Flow validation failed %s\n", err.message); + rule->flow = 0; return; } @@ -251,6 +365,56 @@ flow_init_single(struct flow_rule_entry *rule) RTE_LOG(ERR, IPSEC, "Flow creation return %s\n", err.message); } +void +flow_print_counters(void) +{ + struct rte_flow_query_count count_query; + struct rte_flow_action action; + struct flow_rule_entry *rule; + struct rte_flow_error error; + int i = 0, ret = 0; + + action.type = RTE_FLOW_ACTION_TYPE_COUNT; + + for (i = 0; i < nb_flow_rule; i++) { + rule = &flow_rule_tbl[i]; + if (!rule->flow || !rule->enable_count) + continue; + + /* Poisoning to make sure PMDs update it in case of error. */ + memset(&error, 0x55, sizeof(error)); + memset(&count_query, 0, sizeof(count_query)); + ret = rte_flow_query(rule->port, rule->flow, &action, + &count_query, &error); + if (ret) + RTE_LOG(ERR, IPSEC, + "Failed to get flow counter " + " for port %u, err msg: %s\n", + rule->port, error.message); + + printf("Flow #%3d:", i); + if (rule->is_ipv4) { + printf(" spec ipv4 "); + ipv4_hdr_print(&rule->ipv4.spec.hdr); + } + if (rule->is_ipv6) { + printf(" spec ipv6 "); + ipv6_hdr_print(&rule->ipv6.spec.hdr); + } + + if (rule->set_security_action) + printf(" Security action set,"); + + if (rule->enable_mark) + printf(" Mark Enabled"); + + printf(" Port: %d,", rule->port); + if (rule->is_queue_set) + printf(" Queue: %d", rule->queue); + printf(" Hits: %"PRIu64"\n", count_query.hits); + } +} + void flow_init(void) { @@ -264,21 +428,37 @@ flow_init(void) for (i = 0; i < nb_flow_rule; i++) { rule = &flow_rule_tbl[i]; + printf("Flow #%3d: ", i); if (rule->is_ipv4) { - printf("Flow #%3d: spec ipv4 ", i); + printf("spec ipv4 "); ipv4_hdr_print(&rule->ipv4.spec.hdr); printf("\n"); - printf(" mask ipv4 "); + printf(" mask ipv4 "); ipv4_hdr_print(&rule->ipv4.mask.hdr); - } else { - printf("Flow #%3d: spec ipv6 ", i); + } + if (rule->is_ipv6) { + printf("spec ipv6 "); ipv6_hdr_print(&rule->ipv6.spec.hdr); printf("\n"); - printf(" mask ipv6 "); + printf(" mask ipv6 "); ipv6_hdr_print(&rule->ipv6.mask.hdr); } - printf("\tPort: %d, Queue: %d", rule->port, rule->queue); + if (rule->enable_mark) + printf(", Mark enabled"); + + printf("\tPort: %d,", rule->port); + if (rule->is_queue_set) + printf(" Queue: %d,", rule->queue); + + if (rule->set_security_action) + printf(" Security action set,"); + + if (rule->set_mark_action) + printf(" Mark: %d,", rule->mark_action_val); + + if (rule->enable_count) + printf(" Counter enabled,"); if (rule->flow == NULL) printf(" [UNSUPPORTED]"); diff --git a/examples/ipsec-secgw/flow.h b/examples/ipsec-secgw/flow.h index 1b1b4774e4..9492d06346 100644 --- a/examples/ipsec-secgw/flow.h +++ b/examples/ipsec-secgw/flow.h @@ -11,5 +11,6 @@ void parse_flow_tokens(char **tokens, uint32_t n_tokens, struct parse_status *status); void flow_init(void); +void flow_print_counters(void); #endif /* _FLOW_H_ */ diff --git a/examples/ipsec-secgw/ipsec-secgw.c b/examples/ipsec-secgw/ipsec-secgw.c index 25255e053c..fb97b67465 100644 --- a/examples/ipsec-secgw/ipsec-secgw.c +++ b/examples/ipsec-secgw/ipsec-secgw.c @@ -2875,7 +2875,6 @@ ipsec_secgw_telemetry_init(void) "Optional Parameters: int "); } - int32_t main(int32_t argc, char **argv) { @@ -3131,6 +3130,8 @@ main(int32_t argc, char **argv) printf(" Done\n"); } + flow_print_counters(); + RTE_ETH_FOREACH_DEV(portid) { if ((enabled_port_mask & (1 << portid)) == 0) continue;