From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-pl1-f196.google.com (mail-pl1-f196.google.com [209.85.214.196]) by dpdk.org (Postfix) with ESMTP id 4029B5F2D for ; Thu, 6 Dec 2018 22:44:22 +0100 (CET) Received: by mail-pl1-f196.google.com with SMTP id g9so782201plo.3 for ; Thu, 06 Dec 2018 13:44:22 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=networkplumber-org.20150623.gappssmtp.com; s=20150623; h=date:from:to:cc:subject:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=yeT+pxtxULp/ZRSlSAufN0pouJeGp2iAwSJo4d3g8z0=; b=XDpcw6JokA5PorpMEY+0JonX4vXtl1IgYse21mGTytJIaZtCHvH+7vxnGI+3DmpNk1 olDghL+sM7dVVbYYV3V1o+m6Si1fhtybXP9DZlQDdltY4k4ZUEB02aSi8tegtQbe8YCO O/XulI/Wpx7gwtrdsJkDe73rMO+IUfstasdcveariFHNpFa7+eme7iK+Q6c9v8TovYNK XdUfKHlpZk0Dm7L2Ie0SC7ObKA3tE0Q0bEQjSfGqO9/U21z/Nnyq5C6ymJM4FWWh7ILh mnasdLz+5JyYUMSm8Lgfwx/fqRXkBLW2V0dx937dcS8W03zJ3yXmts1t8xy1vgC5RXqU gLDg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=yeT+pxtxULp/ZRSlSAufN0pouJeGp2iAwSJo4d3g8z0=; b=Ucs9aFuEm/ckWgqphvlPi9bNHJXhp/x3PrZxHeGbdEXpyBsxr9g0EbEjmJ+yVfnDEo T0q+QArot7Eidr4xryQgAXxY+n6nCMoMLsyHqcRV7UF7KVBuLiPKuFEKslpqmAxbbSlf f2mhN01QaYbOFIqcadDAcTIcE+0q3fho95jDGnwHD8NMxmx2nRXJGYZVb1QcGMrRjFPV PEjsWAyc/ns86pYDI070Eix6I0GeDkpR8tKYyeP6yzDt0U5bs2c2j6CQI2hAZe5UkhYA Qg8pmCHSTYwXq7jwfhbQWhy7AchTEFjCaRJ+Z7STQ5RMtDKi/cuKx4NvNAqmNJU2/fRc Eg0A== X-Gm-Message-State: AA+aEWZtCY1iICCCG+0dZv2nmcb9Hx5y7vo/I7a88VhYmHo1moECb9pV FhZ3R7nFR8ldxBPFvM94o+FpNA== X-Google-Smtp-Source: AFSGD/W3XAJTGmlDGcSWM6uEKWxLSh/URp7jO/skmdTU/xfNSxngO70lxE0sczxKlfHEYMlOZU273g== X-Received: by 2002:a17:902:1126:: with SMTP id d35mr27951276pla.1.1544132661075; Thu, 06 Dec 2018 13:44:21 -0800 (PST) Received: from xeon-e3 (204-195-22-127.wavecable.com. [204.195.22.127]) by smtp.gmail.com with ESMTPSA id z13sm1491327pgf.84.2018.12.06.13.44.20 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Thu, 06 Dec 2018 13:44:20 -0800 (PST) Date: Thu, 6 Dec 2018 13:44:18 -0800 From: Stephen Hemminger To: Asaf Penso Cc: Adrien Mazarguil , "dev@dpdk.org" , Shahaf Shuler , Ori Kam , Thomas Monjalon Message-ID: <20181206134418.475b8d06@xeon-e3> In-Reply-To: <1543418758-23748-1-git-send-email-asafp@mellanox.com> References: <1543418758-23748-1-git-send-email-asafp@mellanox.com> MIME-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit Subject: Re: [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: , X-List-Received-Date: Thu, 06 Dec 2018 21:44:22 -0000 On Wed, 28 Nov 2018 15:26:06 +0000 Asaf Penso wrote: > 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 Since this is a debug function, it would make more sense for it to take a 'FILE *' for output like the other debug functions do. That would make it consistent with rte_pktmbuf_dump rte_event_dev_dump, rte_mempool_dump, etc. Why not name it rte_flow_dump?