From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id B5FEAA0032; Wed, 9 Feb 2022 22:39:12 +0100 (CET) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 6C7F64116A; Wed, 9 Feb 2022 22:38:52 +0100 (CET) Received: from NAM10-MW2-obe.outbound.protection.outlook.com (mail-mw2nam10on2045.outbound.protection.outlook.com [40.107.94.45]) by mails.dpdk.org (Postfix) with ESMTP id D9E8441177 for ; Wed, 9 Feb 2022 22:38:50 +0100 (CET) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=jWxF0Ni8kJs84nzsiLsAEnDt/1wLXv9ITHIWUxFZKzTuN/EPBbgy/wpKTtqH37WvuaeyHa2cetaVVS4b6NLdiXNciRfo87fTk5Im6+RB87Z8faoOFOBsos0BLTfyrdVOozdU3uUI9Hd4ZNIdX/nsSvNzDPQMy/kEPbii3cybV0GRgzKXpZqN7Zaw2faKaZWT2KLF0Xk0WmwIQXSvSBb3gsl4gyRol39V2hKpIuY5+iLKT0l1UYi9LaTKl5Hkgo1dwnlNkYwOAazMaMIDBM48s0g15Kcf/TD6ZgGM8UiD0FeZKFtqNKXIWF0lMD4jIPrMnjlDFPCi9PJIpyNf9/w80Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=lX+dE49mPw4H3osU7IQEhmpLX8bovdemmy5E5H8HZfM=; b=A4XSlOyrMUwLMZizMBPjvrjGu86PNvh5nPRk5O8SDohBRRuDriI2Se7hrPh+kot38f+m7ptbqJ3D5377Bmt+hqYRWoCtpJgojA6G1VOio9hFY8ZW9DhapwzxGxBfySRIenYwkheqa/8ftGxw7A3eYWTui0UV5+k0fQlEg7TKDw/cY0JPTJaMhEkDxU6rMD0q/PsByZjMv0hcawA3pDCXuNT4AWFZ50NZDRl9zPahUA+Q91GQSbcUYjDH3XBceYZ/0qDyzjBlS/nh4VkAuvdcdh4Qf3A5ZSqgdScd7hdBGGPwYF2Ju4ZTkylePRtipU5X3gkc4vgICMf/muFKj0iPtw== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 12.22.5.234) smtp.rcpttodomain=intel.com smtp.mailfrom=nvidia.com; dmarc=pass (p=reject sp=reject pct=100) action=none header.from=nvidia.com; dkim=none (message not signed); arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=Nvidia.com; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=lX+dE49mPw4H3osU7IQEhmpLX8bovdemmy5E5H8HZfM=; b=cx5mXrqrJJOox1vhQIWZG/u+QChH4bfPsBbH/7FZ3ASKAPiUqicmJmfJdVXI3sydfcPjElzrHj0Y/e+BtS2HeIuLq7EIjvHd0Q8AZeMBtK79dLTwwsO8PkY4vlgogEgOmvppG+XDVRexxXIBpOpD9FPF/7OrAz1n9hFmpZ2X8pD04vy5MBFDoi3q8fnmGqKDDQD+1oj9jSkmgUqi9DzOAHdTeFB+gTDP+yUO9VWXQf/C1X1f9OhL8FeVJjxfKadu8EOWhnYdLBvn1wBaFxehQPnInpI0TQnm2ZyDFGYnFyGnwQSp2RiF68Q+VsaXfyFmqkvIwOdpctmvhiaZ0hbxoQ== Received: from BY5PR12MB4132.namprd12.prod.outlook.com (2603:10b6:a03:209::22) by MW2PR12MB4684.namprd12.prod.outlook.com (2603:10b6:302:13::29) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4951.17; Wed, 9 Feb 2022 21:38:48 +0000 Received: from MWHPR1201CA0006.namprd12.prod.outlook.com (2603:10b6:301:4a::16) by BY5PR12MB4132.namprd12.prod.outlook.com (2603:10b6:a03:209::22) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4951.12; Wed, 9 Feb 2022 21:38:47 +0000 Received: from CO1NAM11FT020.eop-nam11.prod.protection.outlook.com (2603:10b6:301:4a:cafe::4e) by MWHPR1201CA0006.outlook.office365.com (2603:10b6:301:4a::16) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4975.11 via Frontend Transport; Wed, 9 Feb 2022 21:38:47 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 12.22.5.234) smtp.mailfrom=nvidia.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=nvidia.com; Received-SPF: Pass (protection.outlook.com: domain of nvidia.com designates 12.22.5.234 as permitted sender) receiver=protection.outlook.com; client-ip=12.22.5.234; helo=mail.nvidia.com; Received: from mail.nvidia.com (12.22.5.234) by CO1NAM11FT020.mail.protection.outlook.com (10.13.174.149) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) id 15.20.4975.11 via Frontend Transport; Wed, 9 Feb 2022 21:38:46 +0000 Received: from rnnvmail201.nvidia.com (10.129.68.8) by DRHQMAIL101.nvidia.com (10.27.9.10) with Microsoft SMTP Server (TLS) id 15.0.1497.18; Wed, 9 Feb 2022 21:38:46 +0000 Received: from pegasus01.mtr.labs.mlnx (10.126.231.35) by rnnvmail201.nvidia.com (10.129.68.8) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.986.9; Wed, 9 Feb 2022 13:38:43 -0800 From: Alexander Kozyrev To: CC: , , , , , , , , , Subject: [PATCH v4 05/10] app/testpmd: implement rte flow template management Date: Wed, 9 Feb 2022 23:38:04 +0200 Message-ID: <20220209213809.1208269-6-akozyrev@nvidia.com> X-Mailer: git-send-email 2.18.2 In-Reply-To: <20220209213809.1208269-1-akozyrev@nvidia.com> References: <20220206032526.816079-1-akozyrev@nvidia.com > <20220209213809.1208269-1-akozyrev@nvidia.com> MIME-Version: 1.0 Content-Type: text/plain X-Originating-IP: [10.126.231.35] X-ClientProxiedBy: rnnvmail202.nvidia.com (10.129.68.7) To rnnvmail201.nvidia.com (10.129.68.8) X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 8dda8089-f72e-4aec-8e13-08d9ec148dba X-MS-TrafficTypeDiagnostic: BY5PR12MB4132:EE_|MW2PR12MB4684:EE_ X-LD-Processed: 43083d15-7273-40c1-b7db-39efd9ccc17a,ExtAddr,ExtAddr X-Microsoft-Antispam-PRVS: X-MS-Oob-TLC-OOBClassifiers: OLM:2331; X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: PwEqkf/QWeFqjRcv345xRTZB3kUPb/5DqMdkgZaf1+6vN3681xvAcpDaUhptWSaCv95eInIDCbltMypaXhVOIyvaIwt5UfRE59WhEwc979uW4YWrqJH0zAQzkKp+t4C5b71G+r9ChuLb9J5MZy5+ZGPS8Yw7+ROKl11z9tT4oZYMNZ/DCQ/H2srnz0xgl96yqZQQ5eoB0ELqxYBoHM5ffVaOxVK+5aapbz7B58Jv9iWOTIDUYdvjWFUg41WvtOUk+ZEENPoRKvFjjceq0YxTQLH43nf5jvr/6KCOL8NVdBUzJvoJ+xfPNZep2oENmSaV69bMNpdwI0ExEdszU5oWUYJTqluaN5rmictqjxGG8I6AuukqDn4fE9Rmbb5ZKe4akB0xqRYW544v/dl6hqNlWfbGp3taOEWaCHjuaScECmr/bjRWv3KhRqajMYtCzwqwh+ovkOob7WyOVQBcBGD8n+yNOXuCfx3bcs/ncXt5lIMmAQUPy4fh+oSSrCUq6Bn+71sqk3geAcwtzOF6Wl8JG32HcVTmTmOSnnOq8ieg3eCCxlN+1AynyCVkXCIO+mNmd+nXJvjnQMOik4j1su/tCGc8aMAE0BNkT3Dv2NfpM091H6C+3e/rm4qwW6kpMoL4h8x+ceQOs2+j3AYyG7VK4mQX25ktDjP2jQnBmZSmE1NMvZg9ZRsIliMLm0E47171U7ITN6QIdMoQgKBu4WLq1w== X-Forefront-Antispam-Report: CIP:12.22.5.234; CTRY:US; LANG:en; SCL:1; SRV:; IPV:CAL; SFV:NSPM; H:mail.nvidia.com; PTR:InfoNoRecords; CAT:NONE; SFS:(13230001)(4636009)(46966006)(36840700001)(40470700004)(8676002)(316002)(8936002)(70586007)(70206006)(82310400004)(6666004)(86362001)(4326008)(356005)(508600001)(6916009)(81166007)(54906003)(40460700003)(36756003)(1076003)(16526019)(186003)(2906002)(5660300002)(426003)(336012)(47076005)(26005)(36860700001)(30864003)(7416002)(2616005)(83380400001)(36900700001); DIR:OUT; SFP:1101; X-OriginatorOrg: Nvidia.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 09 Feb 2022 21:38:46.9856 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 8dda8089-f72e-4aec-8e13-08d9ec148dba X-MS-Exchange-CrossTenant-Id: 43083d15-7273-40c1-b7db-39efd9ccc17a X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=43083d15-7273-40c1-b7db-39efd9ccc17a; Ip=[12.22.5.234]; Helo=[mail.nvidia.com] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-CrossTenant-AuthSource: CO1NAM11FT020.eop-nam11.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-Transport-CrossTenantHeadersStamped: MW2PR12MB4684 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 Add testpmd support for the rte_flow_pattern_template and rte_flow_actions_template APIs. Provide the command line interface for the template creation/destruction. Usage example: testpmd> flow pattern_template 0 create pattern_template_id 2 template eth dst is 00:16:3e:31:15:c3 / end testpmd> flow actions_template 0 create actions_template_id 4 template drop / end mask drop / end testpmd> flow actions_template 0 destroy actions_template 4 testpmd> flow pattern_template 0 destroy pattern_template 2 Signed-off-by: Alexander Kozyrev Acked-by: Ori Kam --- app/test-pmd/cmdline_flow.c | 376 +++++++++++++++++++- app/test-pmd/config.c | 203 +++++++++++ app/test-pmd/testpmd.h | 23 ++ doc/guides/testpmd_app_ug/testpmd_funcs.rst | 97 +++++ 4 files changed, 697 insertions(+), 2 deletions(-) diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c index cc3003e6eb..34bc73eea3 100644 --- a/app/test-pmd/cmdline_flow.c +++ b/app/test-pmd/cmdline_flow.c @@ -56,6 +56,8 @@ enum index { COMMON_POLICY_ID, COMMON_FLEX_HANDLE, COMMON_FLEX_TOKEN, + COMMON_PATTERN_TEMPLATE_ID, + COMMON_ACTIONS_TEMPLATE_ID, /* TOP-level command. */ ADD, @@ -74,6 +76,8 @@ enum index { /* Sub-level commands. */ INFO, CONFIGURE, + PATTERN_TEMPLATE, + ACTIONS_TEMPLATE, INDIRECT_ACTION, VALIDATE, CREATE, @@ -92,6 +96,22 @@ enum index { FLEX_ITEM_CREATE, FLEX_ITEM_DESTROY, + /* Pattern template arguments. */ + PATTERN_TEMPLATE_CREATE, + PATTERN_TEMPLATE_DESTROY, + PATTERN_TEMPLATE_CREATE_ID, + PATTERN_TEMPLATE_DESTROY_ID, + PATTERN_TEMPLATE_RELAXED_MATCHING, + PATTERN_TEMPLATE_SPEC, + + /* Actions template arguments. */ + ACTIONS_TEMPLATE_CREATE, + ACTIONS_TEMPLATE_DESTROY, + ACTIONS_TEMPLATE_CREATE_ID, + ACTIONS_TEMPLATE_DESTROY_ID, + ACTIONS_TEMPLATE_SPEC, + ACTIONS_TEMPLATE_MASK, + /* Tunnel arguments. */ TUNNEL_CREATE, TUNNEL_CREATE_TYPE, @@ -861,6 +881,10 @@ struct buffer { uint32_t nb_queue; struct rte_flow_queue_attr queue_attr; } configure; /**< Configuration arguments. */ + struct { + uint32_t *template_id; + uint32_t template_id_n; + } templ_destroy; /**< Template destroy arguments. */ struct { uint32_t *action_id; uint32_t action_id_n; @@ -869,10 +893,13 @@ struct buffer { uint32_t action_id; } ia; /* Indirect action query arguments */ struct { + uint32_t pat_templ_id; + uint32_t act_templ_id; struct rte_flow_attr attr; struct tunnel_ops tunnel_ops; struct rte_flow_item *pattern; struct rte_flow_action *actions; + struct rte_flow_action *masks; uint32_t pattern_n; uint32_t actions_n; uint8_t *data; @@ -952,6 +979,43 @@ static const enum index next_config_attr[] = { ZERO, }; +static const enum index next_pt_subcmd[] = { + PATTERN_TEMPLATE_CREATE, + PATTERN_TEMPLATE_DESTROY, + ZERO, +}; + +static const enum index next_pt_attr[] = { + PATTERN_TEMPLATE_CREATE_ID, + PATTERN_TEMPLATE_RELAXED_MATCHING, + PATTERN_TEMPLATE_SPEC, + ZERO, +}; + +static const enum index next_pt_destroy_attr[] = { + PATTERN_TEMPLATE_DESTROY_ID, + END, + ZERO, +}; + +static const enum index next_at_subcmd[] = { + ACTIONS_TEMPLATE_CREATE, + ACTIONS_TEMPLATE_DESTROY, + ZERO, +}; + +static const enum index next_at_attr[] = { + ACTIONS_TEMPLATE_CREATE_ID, + ACTIONS_TEMPLATE_SPEC, + ZERO, +}; + +static const enum index next_at_destroy_attr[] = { + ACTIONS_TEMPLATE_DESTROY_ID, + END, + ZERO, +}; + static const enum index next_ia_create_attr[] = { INDIRECT_ACTION_CREATE_ID, INDIRECT_ACTION_INGRESS, @@ -1991,6 +2055,12 @@ static int parse_isolate(struct context *, const struct token *, static int parse_configure(struct context *, const struct token *, const char *, unsigned int, void *, unsigned int); +static int parse_template(struct context *, const struct token *, + const char *, unsigned int, + void *, unsigned int); +static int parse_template_destroy(struct context *, const struct token *, + const char *, unsigned int, + void *, unsigned int); static int parse_tunnel(struct context *, const struct token *, const char *, unsigned int, void *, unsigned int); @@ -2060,6 +2130,10 @@ static int comp_set_modify_field_op(struct context *, const struct token *, unsigned int, char *, unsigned int); static int comp_set_modify_field_id(struct context *, const struct token *, unsigned int, char *, unsigned int); +static int comp_pattern_template_id(struct context *, const struct token *, + unsigned int, char *, unsigned int); +static int comp_actions_template_id(struct context *, const struct token *, + unsigned int, char *, unsigned int); /** Token definitions. */ static const struct token token_list[] = { @@ -2210,6 +2284,20 @@ static const struct token token_list[] = { .call = parse_flex_handle, .comp = comp_none, }, + [COMMON_PATTERN_TEMPLATE_ID] = { + .name = "{pattern_template_id}", + .type = "PATTERN_TEMPLATE_ID", + .help = "pattern template id", + .call = parse_int, + .comp = comp_pattern_template_id, + }, + [COMMON_ACTIONS_TEMPLATE_ID] = { + .name = "{actions_template_id}", + .type = "ACTIONS_TEMPLATE_ID", + .help = "actions template id", + .call = parse_int, + .comp = comp_actions_template_id, + }, /* Top-level command. */ [FLOW] = { .name = "flow", @@ -2218,6 +2306,8 @@ static const struct token token_list[] = { .next = NEXT(NEXT_ENTRY (INFO, CONFIGURE, + PATTERN_TEMPLATE, + ACTIONS_TEMPLATE, INDIRECT_ACTION, VALIDATE, CREATE, @@ -2292,6 +2382,112 @@ static const struct token token_list[] = { args.configure.port_attr.nb_meters)), }, /* Top-level command. */ + [PATTERN_TEMPLATE] = { + .name = "pattern_template", + .type = "{command} {port_id} [{arg} [...]]", + .help = "manage pattern templates", + .next = NEXT(next_pt_subcmd, NEXT_ENTRY(COMMON_PORT_ID)), + .args = ARGS(ARGS_ENTRY(struct buffer, port)), + .call = parse_template, + }, + /* Sub-level commands. */ + [PATTERN_TEMPLATE_CREATE] = { + .name = "create", + .help = "create pattern template", + .next = NEXT(next_pt_attr), + .call = parse_template, + }, + [PATTERN_TEMPLATE_DESTROY] = { + .name = "destroy", + .help = "destroy pattern template", + .next = NEXT(NEXT_ENTRY(PATTERN_TEMPLATE_DESTROY_ID)), + .args = ARGS(ARGS_ENTRY(struct buffer, port)), + .call = parse_template_destroy, + }, + /* Pattern template arguments. */ + [PATTERN_TEMPLATE_CREATE_ID] = { + .name = "pattern_template_id", + .help = "specify a pattern template id to create", + .next = NEXT(next_pt_attr, + NEXT_ENTRY(COMMON_PATTERN_TEMPLATE_ID)), + .args = ARGS(ARGS_ENTRY(struct buffer, args.vc.pat_templ_id)), + }, + [PATTERN_TEMPLATE_DESTROY_ID] = { + .name = "pattern_template", + .help = "specify a pattern template id to destroy", + .next = NEXT(next_pt_destroy_attr, + NEXT_ENTRY(COMMON_PATTERN_TEMPLATE_ID)), + .args = ARGS(ARGS_ENTRY_PTR(struct buffer, + args.templ_destroy.template_id)), + .call = parse_template_destroy, + }, + [PATTERN_TEMPLATE_RELAXED_MATCHING] = { + .name = "relaxed", + .help = "is matching relaxed", + .next = NEXT(next_pt_attr, + NEXT_ENTRY(COMMON_BOOLEAN)), + .args = ARGS(ARGS_ENTRY_BF(struct buffer, + args.vc.attr.reserved, 1)), + }, + [PATTERN_TEMPLATE_SPEC] = { + .name = "template", + .help = "specify item to create pattern template", + .next = NEXT(next_item), + }, + /* Top-level command. */ + [ACTIONS_TEMPLATE] = { + .name = "actions_template", + .type = "{command} {port_id} [{arg} [...]]", + .help = "manage actions templates", + .next = NEXT(next_at_subcmd, NEXT_ENTRY(COMMON_PORT_ID)), + .args = ARGS(ARGS_ENTRY(struct buffer, port)), + .call = parse_template, + }, + /* Sub-level commands. */ + [ACTIONS_TEMPLATE_CREATE] = { + .name = "create", + .help = "create actions template", + .next = NEXT(next_at_attr), + .call = parse_template, + }, + [ACTIONS_TEMPLATE_DESTROY] = { + .name = "destroy", + .help = "destroy actions template", + .next = NEXT(NEXT_ENTRY(ACTIONS_TEMPLATE_DESTROY_ID)), + .args = ARGS(ARGS_ENTRY(struct buffer, port)), + .call = parse_template_destroy, + }, + /* Actions template arguments. */ + [ACTIONS_TEMPLATE_CREATE_ID] = { + .name = "actions_template_id", + .help = "specify an actions template id to create", + .next = NEXT(NEXT_ENTRY(ACTIONS_TEMPLATE_MASK), + NEXT_ENTRY(ACTIONS_TEMPLATE_SPEC), + NEXT_ENTRY(COMMON_ACTIONS_TEMPLATE_ID)), + .args = ARGS(ARGS_ENTRY(struct buffer, args.vc.act_templ_id)), + }, + [ACTIONS_TEMPLATE_DESTROY_ID] = { + .name = "actions_template", + .help = "specify an actions template id to destroy", + .next = NEXT(next_at_destroy_attr, + NEXT_ENTRY(COMMON_ACTIONS_TEMPLATE_ID)), + .args = ARGS(ARGS_ENTRY_PTR(struct buffer, + args.templ_destroy.template_id)), + .call = parse_template_destroy, + }, + [ACTIONS_TEMPLATE_SPEC] = { + .name = "template", + .help = "specify action to create actions template", + .next = NEXT(next_action), + .call = parse_template, + }, + [ACTIONS_TEMPLATE_MASK] = { + .name = "mask", + .help = "specify action mask to create actions template", + .next = NEXT(next_action), + .call = parse_template, + }, + /* Top-level command. */ [INDIRECT_ACTION] = { .name = "indirect_action", .type = "{command} {port_id} [{arg} [...]]", @@ -2614,7 +2810,7 @@ static const struct token token_list[] = { .name = "end", .help = "end list of pattern items", .priv = PRIV_ITEM(END, 0), - .next = NEXT(NEXT_ENTRY(ACTIONS)), + .next = NEXT(NEXT_ENTRY(ACTIONS, END)), .call = parse_vc, }, [ITEM_VOID] = { @@ -5731,7 +5927,9 @@ parse_vc(struct context *ctx, const struct token *token, if (!out) return len; if (!out->command) { - if (ctx->curr != VALIDATE && ctx->curr != CREATE) + if (ctx->curr != VALIDATE && ctx->curr != CREATE && + ctx->curr != PATTERN_TEMPLATE_CREATE && + ctx->curr != ACTIONS_TEMPLATE_CREATE) return -1; if (sizeof(*out) > size) return -1; @@ -7595,6 +7793,114 @@ parse_configure(struct context *ctx, const struct token *token, return len; } +/** Parse tokens for template create command. */ +static int +parse_template(struct context *ctx, const struct token *token, + const char *str, unsigned int len, + void *buf, unsigned int size) +{ + struct buffer *out = buf; + + /* Token name must match. */ + if (parse_default(ctx, token, str, len, NULL, 0) < 0) + return -1; + /* Nothing else to do if there is no buffer. */ + if (!out) + return len; + if (!out->command) { + if (ctx->curr != PATTERN_TEMPLATE && + ctx->curr != ACTIONS_TEMPLATE) + return -1; + if (sizeof(*out) > size) + return -1; + out->command = ctx->curr; + ctx->objdata = 0; + ctx->object = out; + ctx->objmask = NULL; + out->args.vc.data = (uint8_t *)out + size; + return len; + } + switch (ctx->curr) { + case PATTERN_TEMPLATE_CREATE: + out->args.vc.pattern = + (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1), + sizeof(double)); + out->args.vc.pat_templ_id = UINT32_MAX; + out->command = ctx->curr; + ctx->objdata = 0; + ctx->object = out; + ctx->objmask = NULL; + return len; + case ACTIONS_TEMPLATE_CREATE: + out->args.vc.act_templ_id = UINT32_MAX; + out->command = ctx->curr; + ctx->objdata = 0; + ctx->object = out; + ctx->objmask = NULL; + return len; + case ACTIONS_TEMPLATE_SPEC: + out->args.vc.actions = + (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1), + sizeof(double)); + ctx->object = out->args.vc.actions; + ctx->objmask = NULL; + return len; + case ACTIONS_TEMPLATE_MASK: + out->args.vc.masks = + (void *)RTE_ALIGN_CEIL((uintptr_t) + (out->args.vc.actions + + out->args.vc.actions_n), + sizeof(double)); + ctx->object = out->args.vc.masks; + ctx->objmask = NULL; + return len; + default: + return -1; + } +} + +/** Parse tokens for template destroy command. */ +static int +parse_template_destroy(struct context *ctx, const struct token *token, + const char *str, unsigned int len, + void *buf, unsigned int size) +{ + struct buffer *out = buf; + uint32_t *template_id; + + /* Token name must match. */ + if (parse_default(ctx, token, str, len, NULL, 0) < 0) + return -1; + /* Nothing else to do if there is no buffer. */ + if (!out) + return len; + if (!out->command || + out->command == PATTERN_TEMPLATE || + out->command == ACTIONS_TEMPLATE) { + if (ctx->curr != PATTERN_TEMPLATE_DESTROY && + ctx->curr != ACTIONS_TEMPLATE_DESTROY) + return -1; + if (sizeof(*out) > size) + return -1; + out->command = ctx->curr; + ctx->objdata = 0; + ctx->object = out; + ctx->objmask = NULL; + out->args.templ_destroy.template_id = + (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1), + sizeof(double)); + return len; + } + template_id = out->args.templ_destroy.template_id + + out->args.templ_destroy.template_id_n++; + if ((uint8_t *)template_id > (uint8_t *)out + size) + return -1; + ctx->objdata = 0; + ctx->object = template_id; + ctx->objmask = NULL; + return len; +} + static int parse_flex(struct context *ctx, const struct token *token, const char *str, unsigned int len, @@ -8564,6 +8870,54 @@ comp_set_modify_field_id(struct context *ctx, const struct token *token, return -1; } +/** Complete available pattern template IDs. */ +static int +comp_pattern_template_id(struct context *ctx, const struct token *token, + unsigned int ent, char *buf, unsigned int size) +{ + unsigned int i = 0; + struct rte_port *port; + struct port_template *pt; + + (void)token; + if (port_id_is_invalid(ctx->port, DISABLED_WARN) || + ctx->port == (portid_t)RTE_PORT_ALL) + return -1; + port = &ports[ctx->port]; + for (pt = port->pattern_templ_list; pt != NULL; pt = pt->next) { + if (buf && i == ent) + return snprintf(buf, size, "%u", pt->id); + ++i; + } + if (buf) + return -1; + return i; +} + +/** Complete available actions template IDs. */ +static int +comp_actions_template_id(struct context *ctx, const struct token *token, + unsigned int ent, char *buf, unsigned int size) +{ + unsigned int i = 0; + struct rte_port *port; + struct port_template *pt; + + (void)token; + if (port_id_is_invalid(ctx->port, DISABLED_WARN) || + ctx->port == (portid_t)RTE_PORT_ALL) + return -1; + port = &ports[ctx->port]; + for (pt = port->actions_templ_list; pt != NULL; pt = pt->next) { + if (buf && i == ent) + return snprintf(buf, size, "%u", pt->id); + ++i; + } + if (buf) + return -1; + return i; +} + /** Internal context. */ static struct context cmd_flow_context; @@ -8832,6 +9186,24 @@ cmd_flow_parsed(const struct buffer *in) in->args.configure.nb_queue, &in->args.configure.queue_attr); break; + case PATTERN_TEMPLATE_CREATE: + port_flow_pattern_template_create(in->port, in->args.vc.pat_templ_id, + in->args.vc.attr.reserved, in->args.vc.pattern); + break; + case PATTERN_TEMPLATE_DESTROY: + port_flow_pattern_template_destroy(in->port, + in->args.templ_destroy.template_id_n, + in->args.templ_destroy.template_id); + break; + case ACTIONS_TEMPLATE_CREATE: + port_flow_actions_template_create(in->port, in->args.vc.act_templ_id, + in->args.vc.actions, in->args.vc.masks); + break; + case ACTIONS_TEMPLATE_DESTROY: + port_flow_actions_template_destroy(in->port, + in->args.templ_destroy.template_id_n, + in->args.templ_destroy.template_id); + break; case INDIRECT_ACTION_CREATE: port_action_handle_create( in->port, in->args.vc.attr.group, diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c index df83f8dbdd..2ef7c3e07a 100644 --- a/app/test-pmd/config.c +++ b/app/test-pmd/config.c @@ -1609,6 +1609,49 @@ action_alloc(portid_t port_id, uint32_t id, return 0; } +static int +template_alloc(uint32_t id, struct port_template **template, + struct port_template **list) +{ + struct port_template *lst = *list; + struct port_template **ppt; + struct port_template *pt = NULL; + + *template = NULL; + if (id == UINT32_MAX) { + /* taking first available ID */ + if (lst) { + if (lst->id == UINT32_MAX - 1) { + printf("Highest template ID is already" + " assigned, delete it first\n"); + return -ENOMEM; + } + id = lst->id + 1; + } else { + id = 0; + } + } + pt = calloc(1, sizeof(*pt)); + if (!pt) { + printf("Allocation of port template failed\n"); + return -ENOMEM; + } + ppt = list; + while (*ppt && (*ppt)->id > id) + ppt = &(*ppt)->next; + if (*ppt && (*ppt)->id == id) { + printf("Template #%u is already assigned," + " delete it first\n", id); + free(pt); + return -EINVAL; + } + pt->next = *ppt; + pt->id = id; + *ppt = pt; + *template = pt; + return 0; +} + /** Get info about flow management resources. */ int port_flow_get_info(portid_t port_id) @@ -2078,6 +2121,166 @@ age_action_get(const struct rte_flow_action *actions) return NULL; } +/** Create pattern template */ +int +port_flow_pattern_template_create(portid_t port_id, uint32_t id, bool relaxed, + const struct rte_flow_item *pattern) +{ + struct rte_port *port; + struct port_template *pit; + int ret; + struct rte_flow_pattern_template_attr attr = { + .relaxed_matching = relaxed }; + struct rte_flow_error error; + + if (port_id_is_invalid(port_id, ENABLED_WARN) || + port_id == (portid_t)RTE_PORT_ALL) + return -EINVAL; + port = &ports[port_id]; + ret = template_alloc(id, &pit, &port->pattern_templ_list); + if (ret) + return ret; + /* Poisoning to make sure PMDs update it in case of error. */ + memset(&error, 0x22, sizeof(error)); + pit->template.pattern_template = rte_flow_pattern_template_create(port_id, + &attr, pattern, &error); + if (!pit->template.pattern_template) { + uint32_t destroy_id = pit->id; + port_flow_pattern_template_destroy(port_id, 1, &destroy_id); + return port_flow_complain(&error); + } + printf("Pattern template #%u created\n", pit->id); + return 0; +} + +/** Destroy pattern template */ +int +port_flow_pattern_template_destroy(portid_t port_id, uint32_t n, + const uint32_t *template) +{ + struct rte_port *port; + struct port_template **tmp; + uint32_t c = 0; + int ret = 0; + + if (port_id_is_invalid(port_id, ENABLED_WARN) || + port_id == (portid_t)RTE_PORT_ALL) + return -EINVAL; + port = &ports[port_id]; + tmp = &port->pattern_templ_list; + while (*tmp) { + uint32_t i; + + for (i = 0; i != n; ++i) { + struct rte_flow_error error; + struct port_template *pit = *tmp; + + if (template[i] != pit->id) + continue; + /* + * Poisoning to make sure PMDs update it in case + * of error. + */ + memset(&error, 0x33, sizeof(error)); + + if (pit->template.pattern_template && + rte_flow_pattern_template_destroy(port_id, + pit->template.pattern_template, + &error)) { + ret = port_flow_complain(&error); + continue; + } + *tmp = pit->next; + printf("Pattern template #%u destroyed\n", pit->id); + free(pit); + break; + } + if (i == n) + tmp = &(*tmp)->next; + ++c; + } + return ret; +} + +/** Create actions template */ +int +port_flow_actions_template_create(portid_t port_id, uint32_t id, + const struct rte_flow_action *actions, + const struct rte_flow_action *masks) +{ + struct rte_port *port; + struct port_template *pat; + int ret; + struct rte_flow_error error; + + if (port_id_is_invalid(port_id, ENABLED_WARN) || + port_id == (portid_t)RTE_PORT_ALL) + return -EINVAL; + port = &ports[port_id]; + ret = template_alloc(id, &pat, &port->actions_templ_list); + if (ret) + return ret; + /* Poisoning to make sure PMDs update it in case of error. */ + memset(&error, 0x22, sizeof(error)); + pat->template.actions_template = rte_flow_actions_template_create(port_id, + NULL, actions, masks, &error); + if (!pat->template.actions_template) { + uint32_t destroy_id = pat->id; + port_flow_actions_template_destroy(port_id, 1, &destroy_id); + return port_flow_complain(&error); + } + printf("Actions template #%u created\n", pat->id); + return 0; +} + +/** Destroy actions template */ +int +port_flow_actions_template_destroy(portid_t port_id, uint32_t n, + const uint32_t *template) +{ + struct rte_port *port; + struct port_template **tmp; + uint32_t c = 0; + int ret = 0; + + if (port_id_is_invalid(port_id, ENABLED_WARN) || + port_id == (portid_t)RTE_PORT_ALL) + return -EINVAL; + port = &ports[port_id]; + tmp = &port->actions_templ_list; + while (*tmp) { + uint32_t i; + + for (i = 0; i != n; ++i) { + struct rte_flow_error error; + struct port_template *pat = *tmp; + + if (template[i] != pat->id) + continue; + /* + * Poisoning to make sure PMDs update it in case + * of error. + */ + memset(&error, 0x33, sizeof(error)); + + if (pat->template.actions_template && + rte_flow_actions_template_destroy(port_id, + pat->template.actions_template, &error)) { + ret = port_flow_complain(&error); + continue; + } + *tmp = pat->next; + printf("Actions template #%u destroyed\n", pat->id); + free(pat); + break; + } + if (i == n) + tmp = &(*tmp)->next; + ++c; + } + return ret; +} + /** Create flow rule. */ int port_flow_create(portid_t port_id, diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h index 096b6825eb..c70b1fa4e8 100644 --- a/app/test-pmd/testpmd.h +++ b/app/test-pmd/testpmd.h @@ -166,6 +166,17 @@ enum age_action_context_type { ACTION_AGE_CONTEXT_TYPE_INDIRECT_ACTION, }; +/** Descriptor for a template. */ +struct port_template { + struct port_template *next; /**< Next template in list. */ + struct port_template *tmp; /**< Temporary linking. */ + uint32_t id; /**< Template ID. */ + union { + struct rte_flow_pattern_template *pattern_template; + struct rte_flow_actions_template *actions_template; + } template; /**< PMD opaque template object */ +}; + /** Descriptor for a single flow. */ struct port_flow { struct port_flow *next; /**< Next flow in list. */ @@ -246,6 +257,8 @@ struct rte_port { queueid_t queue_nb; /**< nb. of queues for flow rules */ uint32_t queue_sz; /**< size of a queue for flow rules */ uint8_t slave_flag; /**< bonding slave port */ + struct port_template *pattern_templ_list; /**< Pattern templates. */ + struct port_template *actions_templ_list; /**< Actions templates. */ struct port_flow *flow_list; /**< Associated flows. */ struct port_indirect_action *actions_list; /**< Associated indirect actions. */ @@ -892,6 +905,16 @@ int port_flow_configure(portid_t port_id, const struct rte_flow_port_attr *port_attr, uint16_t nb_queue, const struct rte_flow_queue_attr *queue_attr); +int port_flow_pattern_template_create(portid_t port_id, uint32_t id, + bool relaxed, + const struct rte_flow_item *pattern); +int port_flow_pattern_template_destroy(portid_t port_id, uint32_t n, + const uint32_t *template); +int port_flow_actions_template_create(portid_t port_id, uint32_t id, + const struct rte_flow_action *actions, + const struct rte_flow_action *masks); +int port_flow_actions_template_destroy(portid_t port_id, uint32_t n, + const uint32_t *template); int port_flow_validate(portid_t port_id, const struct rte_flow_attr *attr, const struct rte_flow_item *pattern, diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst index cfdda5005c..acb763bdf0 100644 --- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst +++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst @@ -3344,6 +3344,24 @@ following sections. [aging_counters_number {number}] [meters_number {number}] +- Create a pattern template:: + flow pattern_template {port_id} create [pattern_template_id {id}] + [relaxed {boolean}] template {item} [/ {item} [...]] / end + +- Destroy a pattern template:: + + flow pattern_template {port_id} destroy pattern_template {id} [...] + +- Create an actions template:: + + flow actions_template {port_id} create [actions_template_id {id}] + template {action} [/ {action} [...]] / end + mask {action} [/ {action} [...]] / end + +- Destroy an actions template:: + + flow actions_template {port_id} destroy actions_template {id} [...] + - Check whether a flow rule can be created:: flow validate {port_id} @@ -3447,6 +3465,85 @@ Otherwise it will show an error message of the form:: Caught error type [...] ([...]): [...] +Creating pattern templates +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +``flow pattern_template create`` creates the specified pattern template. +It is bound to ``rte_flow_pattern_template_create()``:: + + flow pattern_template {port_id} create [pattern_template_id {id}] + [relaxed {boolean}] template {item} [/ {item} [...]] / end + +If successful, it will show:: + + Pattern template #[...] created + +Otherwise it will show an error message of the form:: + + Caught error type [...] ([...]): [...] + +This command uses the same pattern items as ``flow create``, +their format is described in `Creating flow rules`_. + +Destroying pattern templates +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +``flow pattern_template destroy`` destroys one or more pattern templates +from their template ID (as returned by ``flow pattern_template create``), +this command calls ``rte_flow_pattern_template_destroy()`` as many +times as necessary:: + + flow pattern_template {port_id} destroy pattern_template {id} [...] + +If successful, it will show:: + + Pattern template #[...] destroyed + +It does not report anything for pattern template IDs that do not exist. +The usual error message is shown when a pattern template cannot be destroyed:: + + Caught error type [...] ([...]): [...] + +Creating actions templates +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +``flow actions_template create`` creates the specified actions template. +It is bound to ``rte_flow_actions_template_create()``:: + + flow actions_template {port_id} create [actions_template_id {id}] + template {action} [/ {action} [...]] / end + mask {action} [/ {action} [...]] / end + +If successful, it will show:: + + Actions template #[...] created + +Otherwise it will show an error message of the form:: + + Caught error type [...] ([...]): [...] + +This command uses the same actions as ``flow create``, +their format is described in `Creating flow rules`_. + +Destroying actions templates +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +``flow actions_template destroy`` destroys one or more actions templates +from their template ID (as returned by ``flow actions_template create``), +this command calls ``rte_flow_actions_template_destroy()`` as many +times as necessary:: + + flow actions_template {port_id} destroy actions_template {id} [...] + +If successful, it will show:: + + Actions template #[...] destroyed + +It does not report anything for actions template IDs that do not exist. +The usual error message is shown when an actions template cannot be destroyed:: + + Caught error type [...] ([...]): [...] + Creating a tunnel stub for offload ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -- 2.18.2