* [dpdk-dev] [PATCH] ethdev: add function to print a flow
@ 2018-11-28 15:26 Asaf Penso
2018-12-06 7:23 ` Asaf Penso
2018-12-06 21:44 ` Stephen Hemminger
0 siblings, 2 replies; 6+ messages in thread
From: Asaf Penso @ 2018-11-28 15:26 UTC (permalink / raw)
To: Adrien Mazarguil; +Cc: Asaf Penso, dev, Shahaf Shuler, Ori Kam, Thomas Monjalon
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 <asafp@mellanox.com>
---
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 <rte_udp.h>
#include <rte_byteorder.h>
#include <rte_esp.h>
+#include <rte_log.h>
+
+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
--
1.7.1
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [dpdk-dev] [PATCH] ethdev: add function to print a flow
2018-11-28 15:26 [dpdk-dev] [PATCH] ethdev: add function to print a flow Asaf Penso
@ 2018-12-06 7:23 ` Asaf Penso
2018-12-06 21:44 ` Stephen Hemminger
1 sibling, 0 replies; 6+ messages in thread
From: Asaf Penso @ 2018-12-06 7:23 UTC (permalink / raw)
To: dev; +Cc: Shahaf Shuler, Ori Kam, Thomas Monjalon, Adrien Mazarguil
Hi All, would be glad to have comments on this patch.
Good day!
Regards,
Asaf Penso
> -----Original Message-----
> From: Asaf Penso
> Sent: Wednesday, November 28, 2018 5:26 PM
> To: Adrien Mazarguil <adrien.mazarguil@6wind.com>
> Cc: Asaf Penso <asafp@mellanox.com>; dev@dpdk.org; Shahaf Shuler
> <shahafs@mellanox.com>; Ori Kam <orika@mellanox.com>; Thomas
> Monjalon <thomas@monjalon.net>
> Subject: [PATCH] ethdev: add function to print a flow
>
> 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 <asafp@mellanox.com>
> ---
> 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"P
> RIx8
> +#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 <rte_udp.h>
> #include <rte_byteorder.h>
> #include <rte_esp.h>
> +#include <rte_log.h>
> +
> +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
> --
> 1.7.1
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [dpdk-dev] [PATCH] ethdev: add function to print a flow
2018-11-28 15:26 [dpdk-dev] [PATCH] ethdev: add function to print a flow Asaf Penso
2018-12-06 7:23 ` Asaf Penso
@ 2018-12-06 21:44 ` Stephen Hemminger
2018-12-11 7:24 ` Asaf Penso
1 sibling, 1 reply; 6+ messages in thread
From: Stephen Hemminger @ 2018-12-06 21:44 UTC (permalink / raw)
To: Asaf Penso; +Cc: Adrien Mazarguil, dev, Shahaf Shuler, Ori Kam, Thomas Monjalon
On Wed, 28 Nov 2018 15:26:06 +0000
Asaf Penso <asafp@mellanox.com> 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 <asafp@mellanox.com>
> ---
> 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 <rte_udp.h>
> #include <rte_byteorder.h>
> #include <rte_esp.h>
> +#include <rte_log.h>
> +
> +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?
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [dpdk-dev] [PATCH] ethdev: add function to print a flow
2018-12-06 21:44 ` Stephen Hemminger
@ 2018-12-11 7:24 ` Asaf Penso
2018-12-11 7:29 ` Ori Kam
0 siblings, 1 reply; 6+ messages in thread
From: Asaf Penso @ 2018-12-11 7:24 UTC (permalink / raw)
To: Stephen Hemminger
Cc: Adrien Mazarguil, dev, Shahaf Shuler, Ori Kam, Thomas Monjalon
Regards,
Asaf Penso
> -----Original Message-----
> From: Stephen Hemminger <stephen@networkplumber.org>
> Sent: Thursday, December 6, 2018 11:44 PM
> To: Asaf Penso <asafp@mellanox.com>
> Cc: Adrien Mazarguil <adrien.mazarguil@6wind.com>; dev@dpdk.org;
> Shahaf Shuler <shahafs@mellanox.com>; Ori Kam <orika@mellanox.com>;
> Thomas Monjalon <thomas@monjalon.net>
> Subject: Re: [dpdk-dev] [PATCH] ethdev: add function to print a flow
>
> On Wed, 28 Nov 2018 15:26:06 +0000
> Asaf Penso <asafp@mellanox.com> 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 <asafp@mellanox.com>
> > ---
> > 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"P
> RIx8
> > +#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 <rte_udp.h>
> > #include <rte_byteorder.h>
> > #include <rte_esp.h>
> > +#include <rte_log.h>
> > +
> > +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?
Thanks for pointing this out. I'll consider renaming and make it accept a file.
I'll wait for more comments first before uploading another version of the patch.
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [dpdk-dev] [PATCH] ethdev: add function to print a flow
2018-12-11 7:24 ` Asaf Penso
@ 2018-12-11 7:29 ` Ori Kam
2018-12-11 9:15 ` Asaf Penso
0 siblings, 1 reply; 6+ messages in thread
From: Ori Kam @ 2018-12-11 7:29 UTC (permalink / raw)
To: Asaf Penso, Stephen Hemminger
Cc: Adrien Mazarguil, dev, Shahaf Shuler, Thomas Monjalon
General comment for the discussion.
I think it is important that all fields of all actions and items will be printed.
This means that any modification to the rte_flow should also reflect
in this function.
Best,
Ori
> -----Original Message-----
> From: Asaf Penso
> Sent: Tuesday, December 11, 2018 9:25 AM
> To: Stephen Hemminger <stephen@networkplumber.org>
> Cc: Adrien Mazarguil <adrien.mazarguil@6wind.com>; dev@dpdk.org; Shahaf
> Shuler <shahafs@mellanox.com>; Ori Kam <orika@mellanox.com>; Thomas
> Monjalon <thomas@monjalon.net>
> Subject: RE: [dpdk-dev] [PATCH] ethdev: add function to print a flow
>
>
>
> Regards,
> Asaf Penso
>
> > -----Original Message-----
> > From: Stephen Hemminger <stephen@networkplumber.org>
> > Sent: Thursday, December 6, 2018 11:44 PM
> > To: Asaf Penso <asafp@mellanox.com>
> > Cc: Adrien Mazarguil <adrien.mazarguil@6wind.com>; dev@dpdk.org;
> > Shahaf Shuler <shahafs@mellanox.com>; Ori Kam <orika@mellanox.com>;
> > Thomas Monjalon <thomas@monjalon.net>
> > Subject: Re: [dpdk-dev] [PATCH] ethdev: add function to print a flow
> >
> > On Wed, 28 Nov 2018 15:26:06 +0000
> > Asaf Penso <asafp@mellanox.com> 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 <asafp@mellanox.com>
> > > ---
> > > 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"P
> > RIx8
> > > +#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 <rte_udp.h>
> > > #include <rte_byteorder.h>
> > > #include <rte_esp.h>
> > > +#include <rte_log.h>
> > > +
> > > +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?
>
> Thanks for pointing this out. I'll consider renaming and make it accept a file.
> I'll wait for more comments first before uploading another version of the patch.
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [dpdk-dev] [PATCH] ethdev: add function to print a flow
2018-12-11 7:29 ` Ori Kam
@ 2018-12-11 9:15 ` Asaf Penso
0 siblings, 0 replies; 6+ messages in thread
From: Asaf Penso @ 2018-12-11 9:15 UTC (permalink / raw)
To: Ori Kam, Stephen Hemminger
Cc: Adrien Mazarguil, dev, Shahaf Shuler, Thomas Monjalon
I agree, if the proposed solution is accepted I'll upload a new patch with the rest of the fields of pattern and actions.
Regards,
Asaf Penso
> -----Original Message-----
> From: Ori Kam
> Sent: Tuesday, December 11, 2018 9:30 AM
> To: Asaf Penso <asafp@mellanox.com>; Stephen Hemminger
> <stephen@networkplumber.org>
> Cc: Adrien Mazarguil <adrien.mazarguil@6wind.com>; dev@dpdk.org;
> Shahaf Shuler <shahafs@mellanox.com>; Thomas Monjalon
> <thomas@monjalon.net>
> Subject: RE: [dpdk-dev] [PATCH] ethdev: add function to print a flow
>
> General comment for the discussion.
>
> I think it is important that all fields of all actions and items will be printed.
> This means that any modification to the rte_flow should also reflect in this
> function.
>
> Best,
> Ori
>
>
>
> > -----Original Message-----
> > From: Asaf Penso
> > Sent: Tuesday, December 11, 2018 9:25 AM
> > To: Stephen Hemminger <stephen@networkplumber.org>
> > Cc: Adrien Mazarguil <adrien.mazarguil@6wind.com>; dev@dpdk.org;
> > Shahaf Shuler <shahafs@mellanox.com>; Ori Kam <orika@mellanox.com>;
> > Thomas Monjalon <thomas@monjalon.net>
> > Subject: RE: [dpdk-dev] [PATCH] ethdev: add function to print a flow
> >
> >
> >
> > Regards,
> > Asaf Penso
> >
> > > -----Original Message-----
> > > From: Stephen Hemminger <stephen@networkplumber.org>
> > > Sent: Thursday, December 6, 2018 11:44 PM
> > > To: Asaf Penso <asafp@mellanox.com>
> > > Cc: Adrien Mazarguil <adrien.mazarguil@6wind.com>; dev@dpdk.org;
> > > Shahaf Shuler <shahafs@mellanox.com>; Ori Kam
> <orika@mellanox.com>;
> > > Thomas Monjalon <thomas@monjalon.net>
> > > Subject: Re: [dpdk-dev] [PATCH] ethdev: add function to print a flow
> > >
> > > On Wed, 28 Nov 2018 15:26:06 +0000
> > > Asaf Penso <asafp@mellanox.com> 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 <asafp@mellanox.com>
> > > > ---
> > > > 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"P
> > > RIx8
> > > > +#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 <rte_udp.h>
> > > > #include <rte_byteorder.h>
> > > > #include <rte_esp.h>
> > > > +#include <rte_log.h>
> > > > +
> > > > +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?
> >
> > Thanks for pointing this out. I'll consider renaming and make it accept a file.
> > I'll wait for more comments first before uploading another version of the
> patch.
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2018-12-11 9:15 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-11-28 15:26 [dpdk-dev] [PATCH] ethdev: add function to print a flow Asaf Penso
2018-12-06 7:23 ` Asaf Penso
2018-12-06 21:44 ` Stephen Hemminger
2018-12-11 7:24 ` Asaf Penso
2018-12-11 7:29 ` Ori Kam
2018-12-11 9:15 ` Asaf Penso
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).