Discussion:
[dpdk-dev] [PATCH] ethdev: add function to print a flow
(too old to reply)
Asaf Penso
2018-11-28 15:26:06 UTC
Permalink
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 <***@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
Asaf Penso
2018-12-06 07:23:18 UTC
Permalink
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
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.
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 /
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
---
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));
}
+ *
+ * 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-
Post by Asaf Penso
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-
Post by Asaf Penso
src.addr_bytes),
+ RTE_ETH_ADDR_BYTES_ARGS(spec-
Post by Asaf Penso
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-
Post by Asaf Penso
src.addr_bytes),
+ RTE_ETH_ADDR_BYTES_ARGS(mask-
Post by Asaf Penso
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)
Post by Asaf Penso
8,
+ (spec->hdr.src_addr & 0x00FF0000)
Post by Asaf Penso
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)
Post by Asaf Penso
8,
+ (spec->hdr.dst_addr & 0x00FF0000)
Post by Asaf Penso
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)
Post by Asaf Penso
8,
+ (mask->hdr.src_addr & 0x00FF0000)
Post by Asaf Penso
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)
Post by Asaf Penso
8,
+ (mask->hdr.dst_addr & 0x00FF0000)
Post by Asaf Penso
16,
+ (mask->hdr.dst_addr & 0xFF000000)
+ >> 24);
+ }
+ break;
+ }
+ 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-
Post by Asaf Penso
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-
Post by Asaf Penso
id);
+ RTE_FLOW_LOG(INFO, " reserved=%u\n",
+ conf->reserved);
+ }
+ break;
+ }
+ RTE_FLOW_LOG(INFO, "unfamiliar action item\n");
+ }
+ }
+}
+
/* Create a flow rule on a given port. */ struct rte_flow *
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.
+ *
+ *
+ * Port identifier of Ethernet device.
+ * Flow rule attributes.
+ * Pattern specification (list terminated by the END pattern item).
+ * Associated actions (list terminated by the END action).
+ *
+ */
+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.
*
--
1.7.1
Stephen Hemminger
2018-12-06 21:44:18 UTC
Permalink
On Wed, 28 Nov 2018 15:26:06 +0000
Post by Asaf Penso
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.
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
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
---
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));
}
+ *
+ * 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;
+ }
+ 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;
+ }
+ 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.
+ *
+ *
+ * Port identifier of Ethernet device.
+ * Flow rule attributes.
+ * Pattern specification (list terminated by the END pattern item).
+ * Associated actions (list terminated by the END action).
+ *
+ */
+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.
*
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?

Loading...