From patchwork Tue Apr 19 08:25:37 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: 109867 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 72E70A00BE; Tue, 19 Apr 2022 10:25:46 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 4D7224068E; Tue, 19 Apr 2022 10:25:46 +0200 (CEST) Received: from mx0b-0016f401.pphosted.com (mx0b-0016f401.pphosted.com [67.231.156.173]) by mails.dpdk.org (Postfix) with ESMTP id D87AD40687 for ; Tue, 19 Apr 2022 10:25:44 +0200 (CEST) Received: from pps.filterd (m0045851.ppops.net [127.0.0.1]) by mx0b-0016f401.pphosted.com (8.16.1.2/8.16.1.2) with ESMTP id 23INFuDZ010003; Tue, 19 Apr 2022 01:25:44 -0700 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=marvell.com; h=from : to : cc : subject : date : message-id : mime-version : content-transfer-encoding : content-type; s=pfpt0220; bh=1cpg8G5ezT4/ujYnDMYmbwYt/aAl9GtHV3TDv4FIvU8=; b=Ie0JT81W6X+YSzOHRZjhUP+XsJNZCeHTDhQLX92g45jzngWDRb180xSsibjgT5mOUf3T DNessYwFMfDMNiDtkEGsdaSKopkuBVIa3Lqfzh6CVR8MS15FP20RYlKGzc0XX2PrmR69 gf9Wn0IyDHsKjccYPkK3BhRfBE2oXV3sW1rNaU4k0pleboOQhMBdZf6buc0Xrb9WnQ33 HozmWsz3ZqQIBlLPpNKcusCkwAhy/MhlQo681BWO4CsS+/fpBZ3AvvAp2pCeWhGSBajF gARkWHeWCUO+Y13Yhl1JDKwwQQuazS0tF/lVuxPVCeDqgmUR8pseuINz/Jio223SUdB2 0w== Received: from dc5-exch01.marvell.com ([199.233.59.181]) by mx0b-0016f401.pphosted.com (PPS) with ESMTPS id 3ffwap2m33-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT); Tue, 19 Apr 2022 01:25:43 -0700 Received: from DC5-EXCH02.marvell.com (10.69.176.39) by DC5-EXCH01.marvell.com (10.69.176.38) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Tue, 19 Apr 2022 01:25:41 -0700 Received: from maili.marvell.com (10.69.176.80) by DC5-EXCH02.marvell.com (10.69.176.39) with Microsoft SMTP Server id 15.0.1497.18 via Frontend Transport; Tue, 19 Apr 2022 01:25:41 -0700 Received: from localhost.localdomain (unknown [10.28.34.33]) by maili.marvell.com (Postfix) with ESMTP id 4BD993F7045; Tue, 19 Apr 2022 01:25:40 -0700 (PDT) From: To: Radu Nicolau , Akhil Goyal CC: , Satheesh Paul Subject: [dpdk-dev] [PATCH] examples/ipsec-secgw: support more flow patterns and actions Date: Tue, 19 Apr 2022 13:55:37 +0530 Message-ID: <20220419082537.270116-1-psatheesh@marvell.com> X-Mailer: git-send-email 2.25.4 MIME-Version: 1.0 X-Proofpoint-GUID: 9CVG3R8Uy_LZG1IBO05WriUZf5K7XxMN X-Proofpoint-ORIG-GUID: 9CVG3R8Uy_LZG1IBO05WriUZf5K7XxMN X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.858,Hydra:6.0.486,FMLib:17.11.64.514 definitions=2022-04-19_02,2022-04-15_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 flows with count, mark and security actions and mark pattern. The flow configuration can be done with these pattern and actions in the below format in the configuration file. flow [mark ] [eth] [ipv4 | ipv6] | \ port queue \ [count] [security] [set_mark ] mark : Set RTE_FLOW_ITEM_TYPE_MARK pattern item with value eth: Set RTE_FLOW_ITEM_TYPE_ETH pattern item. This matches all ethernet packets. ipv4 | ipv6 |: Set RTE_FLOW_ITEM_TYPE_IPV4|RTE_FLOW_ITEM_TYPE_IPV6 pattern with given ipv4 or ipv6 address as source or destination. port : Create flow rule on port . queue : Set RTE_FLOW_ACTION_TYPE_QUEUE action with queue . count: Set RTE_FLOW_ACTION_TYPE_COUNT action. security: Set RTE_FLOW_ITEM_TYPE_ESP pattern and RTE_FLOW_ACTION_TYPE_SECURITY action. set_mark : Set RTE_FLOW_ACTION_TYPE_MARK action with as mark. Examples: 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 Signed-off-by: Satheesh Paul --- examples/ipsec-secgw/flow.c | 280 +++++++++++++++++++++++------ examples/ipsec-secgw/flow.h | 1 + examples/ipsec-secgw/ipsec-secgw.c | 3 +- 3 files changed, 233 insertions(+), 51 deletions(-) diff --git a/examples/ipsec-secgw/flow.c b/examples/ipsec-secgw/flow.c index 1a1ec7861c..23962f35e7 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.src_addr, + &rule->ipv4.mask.hdr.src_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 (ipv6_addr_cpy(rule->ipv6.spec.hdr.dst_addr, - rule->ipv6.mask.hdr.dst_addr, + } + 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.src_addr, + rule->ipv6.mask.hdr.src_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; + struct rte_flow_error err = {}; 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++; + } + + 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++; + } - pattern[0].type = RTE_FLOW_ITEM_TYPE_ETH; + 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++; + } + + 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[2].type = RTE_FLOW_ITEM_TYPE_END; + 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 42b5081840..244453e06e 100644 --- a/examples/ipsec-secgw/ipsec-secgw.c +++ b/examples/ipsec-secgw/ipsec-secgw.c @@ -3271,7 +3271,6 @@ ipsec_secgw_telemetry_init(void) "Optional Parameters: int "); } - int32_t main(int32_t argc, char **argv) { @@ -3512,6 +3511,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;