From patchwork Wed Nov 28 15:26:06 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Asaf Penso X-Patchwork-Id: 48391 X-Patchwork-Delegate: ferruh.yigit@amd.com Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id D86501B3FD; Wed, 28 Nov 2018 16:26:10 +0100 (CET) Received: from EUR03-AM5-obe.outbound.protection.outlook.com (mail-eopbgr30047.outbound.protection.outlook.com [40.107.3.47]) by dpdk.org (Postfix) with ESMTP id 409531B3FD for ; Wed, 28 Nov 2018 16:26:09 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=Mellanox.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=NpKIua95myWAqWYOKfMt6l9b60A8yMIhlV/qepzZCvU=; b=sISffGy4p9C559Tl80bwqtWeb7EucM1AO7q6rQyVLnk4ISain0YWvXC9t4Qd+spML9MsGxBIpY/5PgCQSD8wzowvh/Ohm1wcc3dL4j+pHWrSucEMQYyzufaVpOON/K+2QI8Fx7Xc4UQKYshkbqiTx7IZyanGu6I6QWRrUz31M0A= Received: from DB7PR05MB4187.eurprd05.prod.outlook.com (52.134.107.156) by DB7PR05MB5370.eurprd05.prod.outlook.com (20.178.42.84) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.1361.19; Wed, 28 Nov 2018 15:26:06 +0000 Received: from DB7PR05MB4187.eurprd05.prod.outlook.com ([fe80::986a:870a:d964:7788]) by DB7PR05MB4187.eurprd05.prod.outlook.com ([fe80::986a:870a:d964:7788%3]) with mapi id 15.20.1361.019; Wed, 28 Nov 2018 15:26:06 +0000 From: Asaf Penso To: Adrien Mazarguil CC: Asaf Penso , "dev@dpdk.org" , Shahaf Shuler , Ori Kam , Thomas Monjalon Thread-Topic: [PATCH] ethdev: add function to print a flow Thread-Index: AQHUhy6uk2CN7DZIq0ujCLWKDIF8yQ== Date: Wed, 28 Nov 2018 15:26:06 +0000 Message-ID: <1543418758-23748-1-git-send-email-asafp@mellanox.com> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-clientproxiedby: LO2P265CA0188.GBRP265.PROD.OUTLOOK.COM (2603:10a6:600:a::32) To DB7PR05MB4187.eurprd05.prod.outlook.com (2603:10a6:5:18::28) authentication-results: spf=none (sender IP is ) smtp.mailfrom=asafp@mellanox.com; x-ms-exchange-messagesentrepresentingtype: 1 x-originating-ip: [37.142.13.130] x-ms-publictraffictype: Email x-microsoft-exchange-diagnostics: 1; DB7PR05MB5370; 6:7g8uGeT02aXpIZmmiP0jvaOMeN+I0wGgAAKCpLWwC4v0O8bzdpLLyKPGuKLS1iaeQVZ4m1Xq8Exr9qH5zb6EzcgCIXA6e7IphSnmbm3slwqCqtZ35TmeSbszv8NQjGlYXl/9Ys0fETf0ACdoR+E2eN/7lXkNQZNEJ7JD4AM4uLtNVAKvCokPixUBDdJycp/cQHEDBuy/rJo9MzM3QMkKc/6RwuSFkSv32P0ijJs4AyZ+PyS1fnMl85GIAT93HuL/iJPYDtFuk7JqyzTCZ6xEyPw/CJropie/pcX0sFHscrw1iQWjrD7XmZ0R1F79TOU6rh4im5GmUtlCELRE2EPoJgPr8Daa9vor/kXoKq0try1/YtKaXhqXMvbaN+UpfpipyDg8nUvQePwXnXcISldwEHrDRflD5oTOWbKm5YXC8xcTAgwiRzWxyJzZbPWgIFvnlYT7KZBBBRLHO2Rpk9nb9A==; 5:bFZzZMgg77Cbt+/qRMDckgcgXGRzQkOThoLKJ0K17X4/Upv/oP3CaQScCnHHZTgT3XFuqPdgGxE0eTHw/+4+8Gz3lLMIGSgDviKfFHY9T36qBO2oMnrg5okUUNRfKYCw+oVnSR+eTljs9ngNW3e0yYEWlsL3In6dfZmrD604Z8E=; 7:R7+wsKVIoVX2IfGa4mcNnUczNTQBhl37C7uqP3oIs5W6VycdGU8CVqr7DmwjJetZNNnGtKs7y5eFDmjvfokIzYydgpKSXBcit5L5qny+DiQzlsYK0+ADHOjvxM/2lGr/BZiEhE3j58/UmF0L3nsO6g== x-ms-office365-filtering-correlation-id: 2d17cb6a-6e3c-4336-507f-08d65545d0bd x-ms-office365-filtering-ht: Tenant x-microsoft-antispam: BCL:0; PCL:0; RULEID:(2390098)(7020095)(4652040)(8989299)(5600074)(711020)(4618075)(4534185)(4627221)(201703031133081)(201702281549075)(8990200)(2017052603328)(7153060)(7193020); SRVR:DB7PR05MB5370; x-ms-traffictypediagnostic: DB7PR05MB5370: x-ld-processed: a652971c-7d2e-4d9b-a6a4-d149256f461b,ExtAddr x-microsoft-antispam-prvs: x-ms-exchange-senderadcheck: 1 x-exchange-antispam-report-cfa-test: BCL:0; PCL:0; RULEID:(8211001083)(6040522)(2401047)(5005006)(8121501046)(93006095)(93001095)(3002001)(10201501046)(3231443)(999002)(944501410)(52105112)(6055026)(148016)(149066)(150057)(6041310)(20161123562045)(20161123558120)(20161123560045)(201703131423095)(201702281528075)(20161123555045)(201703061421075)(201703061406153)(20161123564045)(201708071742011)(7699051)(76991095); SRVR:DB7PR05MB5370; BCL:0; PCL:0; RULEID:; SRVR:DB7PR05MB5370; x-forefront-prvs: 0870212862 x-forefront-antispam-report: SFV:NSPM; SFS:(10009020)(396003)(136003)(376002)(366004)(39860400002)(346002)(199004)(189003)(102836004)(3846002)(86362001)(68736007)(476003)(2616005)(486006)(106356001)(575784001)(8676002)(6116002)(186003)(66066001)(6506007)(6916009)(25786009)(6436002)(386003)(81166006)(81156014)(52116002)(8936002)(14454004)(2906002)(26005)(99286004)(6486002)(36756003)(316002)(54906003)(71190400001)(4744004)(14444005)(7736002)(478600001)(6512007)(256004)(53936002)(71200400001)(97736004)(305945005)(105586002)(5660300001)(4326008); DIR:OUT; SFP:1101; SCL:1; SRVR:DB7PR05MB5370; H:DB7PR05MB4187.eurprd05.prod.outlook.com; FPR:; SPF:None; LANG:en; PTR:InfoNoRecords; A:1; MX:1; received-spf: None (protection.outlook.com: mellanox.com does not designate permitted sender hosts) x-microsoft-antispam-message-info: HOQrekERZ3+bHqek0lgTLF+DC170IiA55RBAJPYe0r4fhIgCkrCeiqGrtQtovN77sdlcmFk2JiOekvEm4DHClVJGwsghTtl0tbXjsmn1IK+wPZuseWEtn/PjX2leRtKzMWPcZD60vj7X+YIHHNWiHFh0Z0BmqDYTKgWaXjwtVRM9xIv7Th4n/nK/vGI7T31kuUqmn12ZqxHiqjilHgaCTKKbTyn7S8K6qm/BLAOdTBDzojq16SpOFBC7clpBxOGGk85AL5KLORuAVAGXAUIjH8mvbyUQEy1wll1bqrEvtIhudr7vxtuzfHydYFTfnhzL97i8MOC4ufBksnWbplMYjbIe5B7EyK1hk0XaoRS3GKY= spamdiagnosticoutput: 1:99 spamdiagnosticmetadata: NSPM MIME-Version: 1.0 X-OriginatorOrg: Mellanox.com X-MS-Exchange-CrossTenant-Network-Message-Id: 2d17cb6a-6e3c-4336-507f-08d65545d0bd X-MS-Exchange-CrossTenant-originalarrivaltime: 28 Nov 2018 15:26:06.8144 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: a652971c-7d2e-4d9b-a6a4-d149256f461b X-MS-Exchange-Transport-CrossTenantHeadersStamped: DB7PR05MB5370 Subject: [dpdk-dev] [PATCH] ethdev: add function to print a flow 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" Flow contains the following information: port id, attributes, patterns and actions. The function rte_flow_print prints all above information. It can be used for debugging purposes to validate the behavior of different dpdk applications. Example: running testpmd with the following flow create: flow create 1 transfer ingress pattern eth src is 52:54:00:15:b1:b1 dst is 24:8A:07:8D:AE:C6 / end actions of_push_vlan ethertype 0x8100 / of_set_vlan_vid vlan_vid 0x888 / of_set_vlan_pcp vlan_pcp 7 / port_id id 0 / end Will result in this output: Print flow info port_id =1 group =0 priority =0 ingress =1 egress =0 transfer =1 group =0 reserved =0 pattern type =9 name=RTE_FLOW_ITEM_TYPE_ETH spec type=0x0, src=52:54:00:15:b1:b1, dst=24:8a:07:8d:ae:c6 mask type=0x0, src=ff:ff:ff:ff:ff:ff, dst=ff:ff:ff:ff:ff:ff actions type =23 name=RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN ethertype=0x81 actions type =24 name=RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID vlan_vid=0x8808 actions type =25 name=RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP vlan_pcp=7 actions type =13 name=RTE_FLOW_ACTION_TYPE_PORT_ID id=0 reserved=0 Signed-off-by: Asaf Penso --- lib/librte_ethdev/rte_ethdev_version.map | 1 + lib/librte_ethdev/rte_flow.c | 226 ++++++++++++++++++++++++++++++ lib/librte_ethdev/rte_flow.h | 31 ++++ 3 files changed, 258 insertions(+), 0 deletions(-) diff --git a/lib/librte_ethdev/rte_ethdev_version.map b/lib/librte_ethdev/rte_ethdev_version.map index 92ac3de..7676983 100644 --- a/lib/librte_ethdev/rte_ethdev_version.map +++ b/lib/librte_ethdev/rte_ethdev_version.map @@ -249,6 +249,7 @@ EXPERIMENTAL { rte_eth_switch_domain_free; rte_flow_conv; rte_flow_expand_rss; + rte_flow_print; rte_mtr_capabilities_get; rte_mtr_create; rte_mtr_destroy; diff --git a/lib/librte_ethdev/rte_flow.c b/lib/librte_ethdev/rte_flow.c index 3277be1..742d892 100644 --- a/lib/librte_ethdev/rte_flow.c +++ b/lib/librte_ethdev/rte_flow.c @@ -16,6 +16,8 @@ #include "rte_flow_driver.h" #include "rte_flow.h" +int rte_flow_logtype; + /** * Flow elements description tables. */ @@ -202,6 +204,222 @@ struct rte_flow_desc_data { NULL, rte_strerror(ENOSYS)); } +/* Example: + * + * struct eth_addr mac; + * [...] + * printf("The Ethernet address is "RTE_ETH_ADDR_FMT"\n", + * RTE_ETH_ADDR_ARGS(mac)); + * + */ +#define RTE_ETH_ADDR_FMT \ + "%02"PRIx8":%02"PRIx8":%02"PRIx8":%02"PRIx8":%02"PRIx8":%02"PRIx8 +#define RTE_ETH_ADDR_ARGS(addr) RTE_ETH_ADDR_BYTES_ARGS((addr).ea) +#define RTE_ETH_ADDR_BYTES_ARGS(bytes) \ + (bytes)[0], (bytes)[1], (bytes)[2], (bytes)[3], (bytes)[4], (bytes)[5] + +/* Print the flow fields. */ +void __rte_experimental +rte_flow_print(uint16_t port_id, + const struct rte_flow_attr *attr, + const struct rte_flow_item pattern[], + const struct rte_flow_action actions[]) +{ + RTE_FLOW_LOG(INFO, "Print flow info\n"); + RTE_FLOW_LOG(INFO, "port_id =%u\n", port_id); + RTE_FLOW_LOG(INFO, "group =%u\n", attr->group); + RTE_FLOW_LOG(INFO, "priority =%u\n", attr->priority); + RTE_FLOW_LOG(INFO, "ingress =%u\n", attr->ingress); + RTE_FLOW_LOG(INFO, "egress =%u\n", attr->egress); + RTE_FLOW_LOG(INFO, "transfer =%u\n", attr->transfer); + RTE_FLOW_LOG(INFO, "group =%u\n", attr->group); + RTE_FLOW_LOG(INFO, "reserved =%u\n", attr->reserved); + + for (; pattern->type != RTE_FLOW_ITEM_TYPE_END; pattern++) { + RTE_FLOW_LOG(INFO, "pattern type =%u\n", pattern->type); + switch (pattern->type) { + case RTE_FLOW_ITEM_TYPE_ETH: { + RTE_FLOW_LOG(INFO, " name=RTE_FLOW_ITEM_TYPE_ETH\n"); + if (pattern->spec) { + const struct rte_flow_item_eth *spec = + pattern->spec; + RTE_FLOW_LOG(INFO, " spec type=0x%x, " + "src="RTE_ETH_ADDR_FMT", dst="RTE_ETH_ADDR_FMT + "\n", + spec->type, + RTE_ETH_ADDR_BYTES_ARGS(spec->src.addr_bytes), + RTE_ETH_ADDR_BYTES_ARGS(spec->dst.addr_bytes)); + } + + if (pattern->mask) { + const struct rte_flow_item_eth *mask = + pattern->mask; + RTE_FLOW_LOG(INFO, " mask type=0x%x, " + "src="RTE_ETH_ADDR_FMT", dst="RTE_ETH_ADDR_FMT + "\n", + mask->type, + RTE_ETH_ADDR_BYTES_ARGS(mask->src.addr_bytes), + RTE_ETH_ADDR_BYTES_ARGS(mask->dst.addr_bytes)); + } + break; + } + case RTE_FLOW_ITEM_TYPE_VLAN: { + RTE_FLOW_LOG(INFO, " name=RTE_FLOW_ITEM_TYPE_VLAN\n"); + if (pattern->spec) { + const struct rte_flow_item_vlan *spec = + pattern->spec; + RTE_FLOW_LOG(INFO, " spec tci=0x%x\n", + spec->tci); + RTE_FLOW_LOG(INFO, " spec inner_type=%u\n", + spec->inner_type); + } + if (pattern->mask) { + const struct rte_flow_item_vlan *mask = + pattern->mask; + RTE_FLOW_LOG(INFO, " mask tci=0x%x\n", + mask->tci); + RTE_FLOW_LOG(INFO, " mask inner_type=%u\n", + mask->inner_type); + } + break; + } + case RTE_FLOW_ITEM_TYPE_IPV4: { + RTE_FLOW_LOG(INFO, " name=RTE_FLOW_ITEM_TYPE_IPV4\n"); + if (pattern->spec) { + const struct rte_flow_item_ipv4 *spec = + pattern->spec; + RTE_FLOW_LOG(INFO, " spec version_ihl=%u\n", + spec->hdr.version_ihl); + RTE_FLOW_LOG(INFO, " spec type_of_service=%u\n", + spec->hdr.type_of_service); + RTE_FLOW_LOG(INFO, " spec total_length=%u\n", + spec->hdr.total_length); + RTE_FLOW_LOG(INFO, " spec packet_id=%u\n", + spec->hdr.packet_id); + RTE_FLOW_LOG(INFO, " spec fragment_offset=%u\n", + spec->hdr.fragment_offset); + RTE_FLOW_LOG(INFO, " spec time_to_live=%u\n", + spec->hdr.time_to_live); + RTE_FLOW_LOG(INFO, " spec next_proto_id=%u\n", + spec->hdr.next_proto_id); + RTE_FLOW_LOG(INFO, " spec hdr_checksum=0x%x\n", + spec->hdr.hdr_checksum); + RTE_FLOW_LOG(INFO, + " spec src_addr=%d.%d.%d.%d\n", + (spec->hdr.src_addr & 0x000000FF), + (spec->hdr.src_addr & 0x0000FF00) >> 8, + (spec->hdr.src_addr & 0x00FF0000) >> 16, + (spec->hdr.src_addr & 0xFF000000) + >> 24); + RTE_FLOW_LOG(INFO, + " spec dst_addr=%d.%d.%d.%d\n", + (spec->hdr.dst_addr & 0x000000FF), + (spec->hdr.dst_addr & 0x0000FF00) >> 8, + (spec->hdr.dst_addr & 0x00FF0000) >> 16, + (spec->hdr.dst_addr & 0xFF000000) + >> 24); + } + + if (pattern->mask) { + const struct rte_flow_item_ipv4 *mask = + pattern->mask; + RTE_FLOW_LOG(INFO, " mask version_ihl=%u\n", + mask->hdr.version_ihl); + RTE_FLOW_LOG(INFO, " mask type_of_service=%u\n", + mask->hdr.type_of_service); + RTE_FLOW_LOG(INFO, " mask total_length=%u\n", + mask->hdr.total_length); + RTE_FLOW_LOG(INFO, " mask packet_id=%u\n", + mask->hdr.packet_id); + RTE_FLOW_LOG(INFO, " mask fragment_offset=%u\n", + mask->hdr.fragment_offset); + RTE_FLOW_LOG(INFO, " mask time_to_live=%u\n", + mask->hdr.time_to_live); + RTE_FLOW_LOG(INFO, " mask next_proto_id=%u\n", + mask->hdr.next_proto_id); + RTE_FLOW_LOG(INFO, " mask hdr_checksum=0x%x\n", + mask->hdr.hdr_checksum); + RTE_FLOW_LOG(INFO, + " mask src_addr=%d.%d.%d.%d\n", + (mask->hdr.src_addr & 0x000000FF), + (mask->hdr.src_addr & 0x0000FF00) >> 8, + (mask->hdr.src_addr & 0x00FF0000) >> 16, + (mask->hdr.src_addr & 0xFF000000) + >> 24); + RTE_FLOW_LOG(INFO, + " mask dst_addr=%d.%d.%d.%d\n", + (mask->hdr.dst_addr & 0x000000FF), + (mask->hdr.dst_addr & 0x0000FF00) >> 8, + (mask->hdr.dst_addr & 0x00FF0000) >> 16, + (mask->hdr.dst_addr & 0xFF000000) + >> 24); + } + break; + } + default: + RTE_FLOW_LOG(INFO, "unfamiliar pattern item\n"); + } + } + + for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) { + RTE_FLOW_LOG(INFO, "actions type =%u\n", actions->type); + switch (actions->type) { + case RTE_FLOW_ACTION_TYPE_OF_POP_VLAN: { + RTE_FLOW_LOG(INFO, + " name=RTE_FLOW_ACTION_TYPE_OF_POP_VLAN\n"); + break; + } + case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN: { + RTE_FLOW_LOG(INFO, + " name=RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN\n"); + if (actions->conf) { + const struct rte_flow_action_of_push_vlan + *conf = actions->conf; + RTE_FLOW_LOG(INFO, " ethertype=0x%x\n", + conf->ethertype); + } + break; + } + case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID: { + RTE_FLOW_LOG(INFO, + " name=RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID\n"); + if (actions->conf) { + const struct rte_flow_action_of_set_vlan_vid + *conf = actions->conf; + RTE_FLOW_LOG(INFO, " vlan_vid=0x%x\n", + conf->vlan_vid); + } + break; + } + case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP: { + RTE_FLOW_LOG(INFO, + " name=RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP\n"); + if (actions->conf) { + const struct rte_flow_action_of_set_vlan_pcp + *conf = actions->conf; + RTE_FLOW_LOG(INFO, " vlan_pcp=%u\n", + conf->vlan_pcp); + } + break; + } + case RTE_FLOW_ACTION_TYPE_PORT_ID: { + RTE_FLOW_LOG(INFO, + " name=RTE_FLOW_ACTION_TYPE_PORT_ID\n"); + if (actions->conf) { + const struct rte_flow_action_port_id + *conf = actions->conf; + RTE_FLOW_LOG(INFO, " id=%u\n", conf->id); + RTE_FLOW_LOG(INFO, " reserved=%u\n", + conf->reserved); + } + break; + } + default: + RTE_FLOW_LOG(INFO, "unfamiliar action item\n"); + } + } +} + /* Create a flow rule on a given port. */ struct rte_flow * rte_flow_create(uint16_t port_id, @@ -1001,3 +1219,11 @@ enum rte_flow_conv_item_spec_type { }; return lsize; } + +RTE_INIT(flow_init_log) +{ + rte_flow_logtype = rte_log_register("lib.flow"); + if (rte_flow_logtype >= 0) + rte_log_set_level(rte_flow_logtype, RTE_LOG_INFO); +} + diff --git a/lib/librte_ethdev/rte_flow.h b/lib/librte_ethdev/rte_flow.h index c0fe879..0a7e70b 100644 --- a/lib/librte_ethdev/rte_flow.h +++ b/lib/librte_ethdev/rte_flow.h @@ -28,6 +28,12 @@ #include #include #include +#include + +extern int rte_flow_logtype; + +#define RTE_FLOW_LOG(level, ...) \ + rte_log(RTE_LOG_ ## level, rte_flow_logtype, "" __VA_ARGS__) #ifdef __cplusplus extern "C" { @@ -2414,6 +2420,31 @@ enum rte_flow_conv_op { struct rte_flow_error *error); /** + * Print the flow fields. + * + * The flow contains the port id, different attributes, the pattern's + * items and the action's items, which are all being printed. + * + * @b EXPERIMENTAL: this API may change without prior notice + * + * @param port_id + * Port identifier of Ethernet device. + * @param[in] attr + * Flow rule attributes. + * @param[in] pattern + * Pattern specification (list terminated by the END pattern item). + * @param[in] actions + * Associated actions (list terminated by the END action). + * + * @note not all enum values of patterns and actions are printed. + */ +void __rte_experimental +rte_flow_print(uint16_t port_id, + const struct rte_flow_attr *attr, + const struct rte_flow_item pattern[], + const struct rte_flow_action actions[]); + +/** * Create a flow rule on a given port. * * @param port_id