DPDK patches and discussions
 help / color / mirror / Atom feed
* [dpdk-dev] [PATCH 0/4] rte_flow extension for vSwitch acceleration
@ 2018-03-28 23:29 Qi Zhang
  2018-03-28 23:29 ` [dpdk-dev] [PATCH 1/4] ether: add flow action to redirect packet in a switch domain Qi Zhang
                   ` (7 more replies)
  0 siblings, 8 replies; 61+ messages in thread
From: Qi Zhang @ 2018-03-28 23:29 UTC (permalink / raw)
  To: adrien.mazarguil
  Cc: dev, declan.doherty, sugesh.chandran, michael.j.glynn, yu.y.liu,
	konstantin.ananyev, bruce.richardson, Qi Zhang

This patch extend rte_flow API.
The purpose is to provide necessary programming interface for virtual
switch software (such as OVS) to take advantage of incoming device's
vSwitch acceleration capability when using DPDK as data plane.

Below is summary of changes:

1. Support to specify flow's destination as an ethdev interface.

Add action RTE_FLOW_ACTION_TYPE_ETHDEV_PORT, use port_id as the identification
of the destitation. A typical use case is, with a smart NIC used for vSwitch
acceleration, flow is defined to redirect packet between switch port that is
managed by a Port Representor.

2. Enhanced flow statistics query.
Enhanced action RTE_FLOW_ACTION_COUNT by adding last hit timestamp tracking which is
the requirement from OVS.

3. Add protocol headers which will be supported by incoming device.

New protocal headers include IPV4 ARP, IPV6 ICMP , IPV6 extent header.

4. Add packet modification actions which will be supported by incoming device.

Add new actions that be used to modify packet content with generic semantic:

RTE_FLOW_ACTION_TYPE_FIELD_UPDATE: update specific field of packet
RTE_FLWO_ACTION_TYPE_FIELD_INCREMENT: increament specific field of packet
RTE_FLWO_ACTION_TYPE_FIELD_DECREMENT: decreament specific field of packet
RTE_FLWO_ACTION_TYPE_FIELD_COPY: copy data from one field to another in packet.

All action use struct rte_flow_item parameter to match the pattern that going
to be modified, if no pattern match, the action just be skipped.
These action are non-terminating action. they will not impact the fate of the
packets, since pattern match is expected to be performed before packet be modified.

Note:
- The driver to demonstrate the new APIs is still in development, 
  but we hope it could be accepted early to make OVS integration smoothly.
- Testpmd command line support does not be included and will be submitted
  seperately in future.

Qi Zhang (4):
  ether: add flow action to redirect packet in a switch domain
  ether: add flow last hit query support
  ether: add more protocol support in flow API
  ether: add packet modification aciton in flow API

 doc/guides/prog_guide/rte_flow.rst | 111 ++++++++++++++++
 lib/librte_ether/rte_flow.h        | 258 ++++++++++++++++++++++++++++++++++++-
 2 files changed, 368 insertions(+), 1 deletion(-)

-- 
2.7.4

^ permalink raw reply	[flat|nested] 61+ messages in thread

* [dpdk-dev] [PATCH 1/4] ether: add flow action to redirect packet in a switch domain
  2018-03-28 23:29 [dpdk-dev] [PATCH 0/4] rte_flow extension for vSwitch acceleration Qi Zhang
@ 2018-03-28 23:29 ` Qi Zhang
  2018-03-29 10:48   ` Pattan, Reshma
  2018-03-29 11:20   ` Pattan, Reshma
  2018-03-28 23:29 ` [dpdk-dev] [PATCH 2/4] ether: add flow last hit query support Qi Zhang
                   ` (6 subsequent siblings)
  7 siblings, 2 replies; 61+ messages in thread
From: Qi Zhang @ 2018-03-28 23:29 UTC (permalink / raw)
  To: adrien.mazarguil
  Cc: dev, declan.doherty, sugesh.chandran, michael.j.glynn, yu.y.liu,
	konstantin.ananyev, bruce.richardson, Qi Zhang

Add action RTE_FLOW_ACTION_TYPE_SWITCH_PORT, it can be used to redirect
a packet to a network interface that connect to the same switch domain,
rte_ethdev's port_id is used as an identification of the destination.
A typical use case is: with a smart NIC for vSwitch acceleration, flow
is defined to forward packets between the switch port that is managed by
Port Representor.

Signed-off-by: Qi Zhang <qi.z.zhang@intel.com>
---
 doc/guides/prog_guide/rte_flow.rst | 22 ++++++++++++++++++++++
 lib/librte_ether/rte_flow.h        | 19 ++++++++++++++++++-
 2 files changed, 40 insertions(+), 1 deletion(-)

diff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst
index 961943d..aa5c818 100644
--- a/doc/guides/prog_guide/rte_flow.rst
+++ b/doc/guides/prog_guide/rte_flow.rst
@@ -1486,6 +1486,28 @@ fields in the pattern items.
    | 1     | END      |
    +-------+----------+
 
+Action: ``PORT``
+^^^^^^^^^^^^^^^^
+
+Redirect packets to an interface that connect to the same switch domain.
+
+The desitnation should be managed by a rte_ethdev instance, port_id is
+the identification of the destination. A typical use case is to define
+a flow that redirect packet to a interface that mananged by a Port
+Representor.
+
+- Terminating by default.
+
+.. _table_rte_flow_action_port:
+
+.. table:: PORT
+
+   +--------------+-----------------------------------+
+   | Field        | Value                             |
+   +==============+===================================+
+   | ``port_id``  | identification of the destination |
+   +--------------+-----------------------------------+
+
 Negative types
 ~~~~~~~~~~~~~~
 
diff --git a/lib/librte_ether/rte_flow.h b/lib/librte_ether/rte_flow.h
index 13e4202..9649519 100644
--- a/lib/librte_ether/rte_flow.h
+++ b/lib/librte_ether/rte_flow.h
@@ -1010,7 +1010,14 @@ enum rte_flow_action_type {
 	 *
 	 * See struct rte_flow_action_security.
 	 */
-	RTE_FLOW_ACTION_TYPE_SECURITY
+	RTE_FLOW_ACTION_TYPE_SECURITY,
+
+	/**
+	 * Redirect packets to a network interface in the same switch domain.
+	 *
+	 * See struct rte_flow_action_port.
+	 */
+	RTE_FLOW_ACTION_TYPE_PORT,
 };
 
 /**
@@ -1148,6 +1155,16 @@ struct rte_flow_action_security {
 	void *security_session; /**< Pointer to security session structure. */
 };
 
+/** RTE_FLOW_ACTION_TYPE_PORT
+ *
+ * Redirect packets to a network interface in the same switch domain.
+ *
+ * Terminateing by default.
+ */
+struct rte_flow_action_port {
+	uint16_t port_id; /**< identification of the forward destination. */
+};
+
 /**
  * Definition of a single action.
  *
-- 
2.7.4

^ permalink raw reply	[flat|nested] 61+ messages in thread

* [dpdk-dev] [PATCH 2/4] ether: add flow last hit query support
  2018-03-28 23:29 [dpdk-dev] [PATCH 0/4] rte_flow extension for vSwitch acceleration Qi Zhang
  2018-03-28 23:29 ` [dpdk-dev] [PATCH 1/4] ether: add flow action to redirect packet in a switch domain Qi Zhang
@ 2018-03-28 23:29 ` Qi Zhang
  2018-03-28 23:29 ` [dpdk-dev] [PATCH 3/4] ether: add more protocol support in flow API Qi Zhang
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 61+ messages in thread
From: Qi Zhang @ 2018-03-28 23:29 UTC (permalink / raw)
  To: adrien.mazarguil
  Cc: dev, declan.doherty, sugesh.chandran, michael.j.glynn, yu.y.liu,
	konstantin.ananyev, bruce.richardson, Qi Zhang

Enhanced the action RTE_FLOW_TYPE_ACTION_COUNT, number of
milliseconds since last hit can be queried.

Signed-off-by: Qi Zhang <qi.z.zhang@intel.com>
---
 lib/librte_ether/rte_flow.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/lib/librte_ether/rte_flow.h b/lib/librte_ether/rte_flow.h
index 9649519..1288379 100644
--- a/lib/librte_ether/rte_flow.h
+++ b/lib/librte_ether/rte_flow.h
@@ -1054,9 +1054,11 @@ struct rte_flow_query_count {
 	uint32_t reset:1; /**< Reset counters after query [in]. */
 	uint32_t hits_set:1; /**< hits field is set [out]. */
 	uint32_t bytes_set:1; /**< bytes field is set [out]. */
+	uint32_t last_hit_set:1; /**< last_hit field is set [out]. */
 	uint32_t reserved:29; /**< Reserved, must be zero [in, out]. */
 	uint64_t hits; /**< Number of hits for this rule [out]. */
 	uint64_t bytes; /**< Number of bytes through this rule [out]. */
+	uint64_t last_hit; /**< Number of milliseconds since last hit [out]. */
 };
 
 /**
-- 
2.7.4

^ permalink raw reply	[flat|nested] 61+ messages in thread

* [dpdk-dev] [PATCH 3/4] ether: add more protocol support in flow API
  2018-03-28 23:29 [dpdk-dev] [PATCH 0/4] rte_flow extension for vSwitch acceleration Qi Zhang
  2018-03-28 23:29 ` [dpdk-dev] [PATCH 1/4] ether: add flow action to redirect packet in a switch domain Qi Zhang
  2018-03-28 23:29 ` [dpdk-dev] [PATCH 2/4] ether: add flow last hit query support Qi Zhang
@ 2018-03-28 23:29 ` Qi Zhang
  2018-03-29 14:32   ` Pattan, Reshma
  2018-03-28 23:29 ` [dpdk-dev] [PATCH 4/4] ether: add packet modification aciton " Qi Zhang
                   ` (4 subsequent siblings)
  7 siblings, 1 reply; 61+ messages in thread
From: Qi Zhang @ 2018-03-28 23:29 UTC (permalink / raw)
  To: adrien.mazarguil
  Cc: dev, declan.doherty, sugesh.chandran, michael.j.glynn, yu.y.liu,
	konstantin.ananyev, bruce.richardson, Qi Zhang

Add new protocol header match support as below

RTE_FLOW_ITEM_TYPE_ARP
	- match IPv4 ARP header
RTE_FLOW_ITEM_TYPE_EXT_HDR_ANY
	- match any IPv6 extension header
RTE_FLOW_ITEM_TYPE_ICMPV6
	- match IPv6 ICMP header
RTE_FLOW_ITEM_TYPE_ICMPV6_TGT_ADDR
	- match IPv6 ICMP Target address
RTE_FLOW_ITEM_TYPE_ICMPV6_SSL
	- match IPv6 ICMP Source Link-layer address
RTE_FLOW_ITEM_TYPE_ICMPV6_TTL
	- match IPv6 ICMP Target Link-layer address

Signed-off-by: Qi Zhang <qi.z.zhang@intel.com>
---
 lib/librte_ether/rte_flow.h | 158 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 158 insertions(+)

diff --git a/lib/librte_ether/rte_flow.h b/lib/librte_ether/rte_flow.h
index 1288379..f38b7be 100644
--- a/lib/librte_ether/rte_flow.h
+++ b/lib/librte_ether/rte_flow.h
@@ -323,6 +323,49 @@ enum rte_flow_item_type {
 	 * See struct rte_flow_item_geneve.
 	 */
 	RTE_FLOW_ITEM_TYPE_GENEVE,
+
+	/**
+	 * Matches ARP IPv4 header.
+	 *
+	 * See struct rte_flow_item_arp.
+	 */
+	TE_FLOW_ITEM_TYPE_ARP,
+
+	/**
+	 * Matches any IPv6 Extension header.
+	 *
+	 * See struct rte_flow_item_ipv6_ext_any.
+	 */
+	TE_FLOW_ITEM_TYPE_IPV6_EXT_HDR_ANY,
+
+	/**
+	 * Matches ICMPv6 header.
+	 *
+	 * See struct rte_flow_item_icmpv6
+	 */
+	TE_FLOW_ITEM_TYPE_ICMPV6,
+
+	/**
+	 * Match ICMPv6 target address.
+	 *
+	 * See struct rte_flow_item_icmpv6_tgt_addr.
+	 */
+	TE_FLOW_ITEM_TYPE_ICMPV6_TGT_ADDR,
+
+	/**
+	 * Match ICMPv6 Source Link-Layer Address.
+	 *
+	 * See struct rte_flow_item_icmpv6_sll.
+	 */
+	TE_FLOW_ITEM_TYPE_ICMPV6_SLL,
+
+	/**
+	 * Match ICMPv6 Source Link-Layer Address.
+	 *
+	 * See struct rte_flow_item_icmpv6_tll.
+	 */
+	RTE_FLOW_ITEM_TYPE_ICMPV6_TLL,
+
 };
 
 /**
@@ -815,6 +858,121 @@ static const struct rte_flow_item_geneve rte_flow_item_geneve_mask = {
 #endif
 
 /**
+ * RTE_FLOW_ITEM_TYPE_ARP
+ *
+ * Matches IPv4 ARP packet header
+ */
+struct rte_flow_item_arp {
+	struct arp_hdr hdr;
+};
+
+/** Default mask for RTE_FLOW_ITEM_TYPE_ARP. */
+#ifndef __cplusplus
+static const struct rte_flow_item_arp rte_flow_item_arp_mask = {
+	.hdr = {
+		.arp_data = {
+			.arp_sha = {
+			.addr_bytes = "\xff\xff\xff\xff\xff\xff",
+		},
+		.arp_sip = RTE_BE32(0xffffffff),
+		.arp_tha = {
+			.addr_bytes = "\xff\xff\xff\xff\xff\xff",
+		},
+			.arp_tip = RTE_BE32(0xffffffff),
+		},
+	},
+};
+#endif
+
+/**
+ * RTE_FLOW_ITEM_TYPE_IPV6_EXT_HDR_ANY
+ *
+ * Matches any IPv6 extension header.
+ */
+struct rte_flow_item_ipv6_ext_hdr_any {
+	uint8_t next_hdr;
+};
+
+/** Default mask for RTE_FLOW_ITEM_TYPE_IPV6_EXT_HDR_ANY. */
+#ifndef __cplusplus
+static const
+struct rte_flow_item_ipv6_ext_hdr_any rte_flow_item_ipv6_ext_any_mask = {
+	.next_hdr = 0xff,
+};
+#endif
+
+/**
+ * RTE_FLOW_ITEM_TYPE_ICMPV6
+ *
+ * Matches ICMPv6 header.
+ */
+struct rte_flow_item_icmpv6 {
+	uint8_t type;
+	uint8_t code;
+	uint16_t checksum;
+};
+
+/** Default mask for RTE_FLOW_ITEM_TYPE_ICMPV6 */
+#ifndef __cplusplus
+static const struct rte_flow_item_icmpv6 rte_flow_item_icmpv6_mask = {
+	.type = 0xff,
+	.code = 0xff,
+	.checksum = RTE_BE16(0xffff),
+};
+#endif
+
+/**
+ * RTE_FLOW_ITEM_TYPE_ICMPV6_TGT_ADDR
+ *
+ * Matches ICMPv6's Target Address.
+ */
+struct rte_flow_item_icmpv6_tgt_addr {
+	uint8_t addr[16];
+};
+
+/** Default mask for RTE_FLOW_ITEM_TYPE_ICMPV6_TGT_ADDR */
+#ifndef __cplusplus
+static const
+struct rte_flow_item_icmpv6_tgt_addr rte_flow_item_icmpv6_tgt_addr_mask = {
+	.addr = "\xff\xff\xff\xff",
+};
+#endif
+
+/**
+ * RTE_FLOW_ITEM_TYPE_ICPMV6_SLL.
+ *
+ * Matches ICMPv6 Source Link-Layer address.
+ */
+struct rte_flow_item_icmpv6_sll {
+	struct ether_addr addr;
+};
+/** Default mask for RTE_FLOW_ITEM_TYPE_ICMPV6_SLL */
+#ifndef __cplusplus
+static const struct rte_flow_item_icmpv6_sll rte_flow_item_icmpv6_sll_mask = {
+	.addr = {
+		.addr_bytes = "\xff\xff\xff\xff\xff\xff",
+	}
+};
+#endif
+
+/**
+ * RTE_FLOW_ITEM_TYPE_ICMPV6_TLL.
+ *
+ * Matches ICMPv6 Target Link-Layer address.
+ */
+struct rte_flow_item_icmpv6_tll {
+	struct ether_addr addr;
+};
+/** Default mask for RTE_FLOW_ITEM_TYPE_ICMPV6_TLL */
+#ifndef __cplusplus
+static const struct rte_flow_item_icmpv6_tll rte_flow_item_icmpv6_tll_mask = {
+	.addr = {
+		.addr_bytes = "\xff\xff\xff\xff\xff\xff",
+	}
+};
+#endif
+
+/**
  * Matching pattern item definition.
  *
  * A pattern is formed by stacking items starting from the lowest protocol
-- 
2.7.4

^ permalink raw reply	[flat|nested] 61+ messages in thread

* [dpdk-dev] [PATCH 4/4] ether: add packet modification aciton in flow API
  2018-03-28 23:29 [dpdk-dev] [PATCH 0/4] rte_flow extension for vSwitch acceleration Qi Zhang
                   ` (2 preceding siblings ...)
  2018-03-28 23:29 ` [dpdk-dev] [PATCH 3/4] ether: add more protocol support in flow API Qi Zhang
@ 2018-03-28 23:29 ` Qi Zhang
  2018-03-29 15:23   ` Pattan, Reshma
  2018-04-01 21:19 ` [dpdk-dev] [PATCH v2 0/4] rte_flow extension for vSwitch acceleration Qi Zhang
                   ` (3 subsequent siblings)
  7 siblings, 1 reply; 61+ messages in thread
From: Qi Zhang @ 2018-03-28 23:29 UTC (permalink / raw)
  To: adrien.mazarguil
  Cc: dev, declan.doherty, sugesh.chandran, michael.j.glynn, yu.y.liu,
	konstantin.ananyev, bruce.richardson, Qi Zhang

Add new actions that be used to modify packet content with
generic semantic:

RTE_FLOW_ACTION_TYPE_FIELD_UPDATE:
	- update specific field of packet
RTE_FLWO_ACTION_TYPE_FIELD_INCREMENT:
	- increament specific field of packet
RTE_FLWO_ACTION_TYPE_FIELD_DECREMENT:
	- decreament specific field of packet
RTE_FLWO_ACTION_TYPE_FIELD_COPY:
	- copy data from one field to another in packet.

All action use struct rte_flow_item parameter to match the pattern
that going to be modified, if no pattern match, the action just be
skipped. These action are non-terminating action. they will not
impact the fate of the packets.

Signed-off-by: Qi Zhang <qi.z.zhang@intel.com>
---
 doc/guides/prog_guide/rte_flow.rst | 89 ++++++++++++++++++++++++++++++++++++++
 lib/librte_ether/rte_flow.h        | 79 +++++++++++++++++++++++++++++++++
 2 files changed, 168 insertions(+)

diff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst
index aa5c818..006886b 100644
--- a/doc/guides/prog_guide/rte_flow.rst
+++ b/doc/guides/prog_guide/rte_flow.rst
@@ -1508,6 +1508,95 @@ Representor.
    | ``port_id``  | identification of the destination |
    +--------------+-----------------------------------+
 
+Action: ``FILED_UPDATE``
+^^^^^^^^^^^^^^^^^^^^^^^
+
+Update specific field of the packet.
+
+- Non-terminating by default.
+
+.. _table_rte_flow_action_field_update:
+
+.. table:: FIELD_UPDATE
+
+   +-----------+---------------------------------------------------------+
+   | Field     | Value                                                   |
+   +===========+=========================================================+
+   | ``item``  | item->type: specify the pattern to modify               |
+   |           | item->spec: specify the new value to update             |
+   |           | item->mask: specify which part of the pattern to update |
+   |           | item->last: ignored                                     |
+   +-----------+---------------------------------------------------------+
+   | ``layer`` | 0 means outermost matched pattern,                      |
+   |           | 1 means next-to-outermost and so on ...                 |
+   +-----------+---------------------------------------------------------+
+
+Action: ``FILED_INCREMENT``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Increment 1 on specific field of the packet.
+
+- Non-terminating by default.
+
+.. _table_rte_flow_action_field_increment:
+
+.. table:: FIELD_INCREMENT
+
+   +-----------+---------------------------------------------------------+
+   | Field     | Value                                                   |
+   +===========+=========================================================+
+   | ``item``  | item->type: specify the pattern to modify               |
+   |           | item->spec: ignored                                     |
+   |           | item->mask: specify which part of the pattern to update |
+   |           | item->last: ignored                                     |
+   +-----------+---------------------------------------------------------+
+   | ``layer`` | 0 means outermost matched pattern,                      |
+   |           | 1 means next-to-outermost and so on ...                 |
+   +-----------+---------------------------------------------------------+
+
+Action: ``FIELD_DECREMENT``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Decrement 1 on specific field of the packet.
+
+Paramenter is same is FIELD_INCREMENT.
+
+-Non-terminating by default.
+
+ACTION: ``FIELD_COPY``
+^^^^^^^^^^^^^^^^^^^^^^
+
+Copy data of one field to another of the packet.
+
+-Non-terminating by default.
+
+.. _table_rte_flow_action_field_increment:
+
+.. table:: FIELD_COPY
+
+   +-----------------+-----------------------------------------------------------------+
+   | Field           | Value                                                           |
+   +=================+=================================================================+
+   | ``src_item``    | src_item->type: match the pattern that data will be copy from   |
+   |                 | src_item->spec: ignored                                         |
+   |                 | src_item->mask: specify which part of the pattern to copy       |
+   |                 | src_item->last: ignored                                         |
+   +-----------------+-----------------------------------------------------------------+
+   | ``src_layer``   | layer of src_item                                               |
+   |                 | 0 means outermost matched pattern,                              |
+   |                 | 1 means next-to-outermost and so on ...                         |
+   +-----------------+-----------------------------------------------------------------+
+   | ``dst_item``    | dst_item->type: match the pattern that data will be copy to     |
+   |                 | dst_item->spec: ignored                                         |
+   |                 | dst_item->mask: specify which part of the pattern to be update  |
+   |                 |                 it must match src_item->mask.                   |
+   |                 | dst_item->last: ignored                                         |
+   +-----------------+-----------------------------------------------------------------+
+   | ``dst_layer``   | layer of dst_item                                               |
+   |                 | 0 means outermost matched pattern,                              |
+   |                 | 1 means next-to-outermost and so on ...                         |
+   +-----------------+-----------------------------------------------------------------+
+
 Negative types
 ~~~~~~~~~~~~~~
 
diff --git a/lib/librte_ether/rte_flow.h b/lib/librte_ether/rte_flow.h
index f38b7be..15976fe 100644
--- a/lib/librte_ether/rte_flow.h
+++ b/lib/librte_ether/rte_flow.h
@@ -1176,6 +1176,34 @@ enum rte_flow_action_type {
 	 * See struct rte_flow_action_port.
 	 */
 	RTE_FLOW_ACTION_TYPE_PORT,
+
+	/**
+	 * Update specific field of the packet.
+	 *
+	 * See struct rte_flow_item_type_field_update.
+	 */
+	RTE_FLOW_ACTION_TYPE_FILED_UPDATE,
+
+	/**
+	 * Increment specific field of the packet.
+	 *
+	 * See struct rte_flow_item_type_field_increment.
+	 */
+	RTE_FLOW_ACTION_TYPE_FIELD_INCREMENT,
+
+	/**
+	 * Decrement specific field of the packet.
+	 *
+	 * See struct rte_flow_item_type_field_decrement.
+	 */
+	RTE_FLOW_ACTION_TYPE_FIELD_DECREMENT,
+
+	/**
+	 * Copy data of one field to another of the packet.
+	 *
+	 * See struct rte_flow_item_type_field_copy.
+	 */
+	RTE_FLOW_ACTION_TYPE_FIELD_COPY,
 };
 
 /**
@@ -1325,6 +1353,57 @@ struct rte_flow_action_port {
 	uint16_t port_id; /**< identification of the forward destination. */
 };
 
+/** RTE_FLOW_ACTION_TYPE_FIELD_UPDATE
+ *
+ * Update specific field of the packet.
+ *
+ * Typical usage: update mac/ip address.
+ */
+struct rte_flow_action_field_update {
+	const struct rte_flow_item *item; /**< specify the data to modify. */
+	uint8_t layer;
+	/**< 0 means outermost matched pattern, 1 means next-to-outermost... */
+};
+
+/** RTE_FLOW_ACTION_TYPE_FIELD_INCREMENT
+ *
+ * Increment 1 on specific field of the packet.
+ *
+ * Typical usage: increase TTL
+ */
+struct rte_flow_action_field_increment {
+	const struct rte_flow_item *item; /**< specify the data to modify. */
+	uint8_t layer;
+	/**< 0 means outermost matched pattern, 1 means next-to-outermost... */
+};
+
+/** RTE_FLOW_ACTION_TYPE_FIELD_DECREMENT
+ *
+ * Decrement 1 on specific field of the packet.
+ *
+ * Typical usage: Decrease TTL
+ */
+struct rte_flow_action_field_decrement {
+	const struct rte_flow_item *item; /**< Specify the data to modify. */
+	uint8_t layer;
+	/**< 0 means outermost matched pattern, 1 means next-to-outermost... */
+};
+
+/** RTE_FLOW_ACTION_TYPE_FIELD_COPY
+ *
+ * Copy data from one field to another of the packet.
+ *
+ * Typical usage: TTL copy-in / copy-out
+ */
+struct rte_flow_action_field_copy {
+	const struct rte_flow_item *src_item; /**< Specify the data copy from */
+	uint8_t src_layer;
+	/**< 0 means outermost matched pattern, 1 means next-to-outermost... */
+	const struct rte_flow_item *dst_item; /**< Specify the data copy to */
+	uint8_t dst_layer;
+	/**< 0 means outermost matched pattern, 1 means next-to-outermost... */
+};
+
 /**
  * Definition of a single action.
  *
-- 
2.7.4

^ permalink raw reply	[flat|nested] 61+ messages in thread

* Re: [dpdk-dev] [PATCH 1/4] ether: add flow action to redirect packet in a switch domain
  2018-03-28 23:29 ` [dpdk-dev] [PATCH 1/4] ether: add flow action to redirect packet in a switch domain Qi Zhang
@ 2018-03-29 10:48   ` Pattan, Reshma
  2018-03-29 11:20   ` Pattan, Reshma
  1 sibling, 0 replies; 61+ messages in thread
From: Pattan, Reshma @ 2018-03-29 10:48 UTC (permalink / raw)
  To: Zhang, Qi Z, adrien.mazarguil
  Cc: dev, Doherty, Declan, Chandran, Sugesh, Glynn, Michael J, Liu,
	Yu Y, Ananyev, Konstantin, Richardson, Bruce, Zhang, Qi Z

Hi 

> Add action RTE_FLOW_ACTION_TYPE_SWITCH_PORT, it can be used to
> redirect a packet to a network interface that connect to the same switch
> domain, rte_ethdev's port_id is used as an identification of the destination.
> A typical use case is: with a smart NIC for vSwitch acceleration, flow is defined
> to forward packets between the switch port that is managed by Port
> Representor.
> 

The macro name in commit message not matching with name in code.

> Signed-off-by: Qi Zhang <qi.z.zhang@intel.com>
> ---
>  doc/guides/prog_guide/rte_flow.rst | 22 ++++++++++++++++++++++
>  lib/librte_ether/rte_flow.h        | 19 ++++++++++++++++++-
>  2 files changed, 40 insertions(+), 1 deletion(-)
> 

I guess doc patch should be separated out and some typos in doc.

>  /**
> @@ -1148,6 +1155,16 @@ struct rte_flow_action_security {
>  	void *security_session; /**< Pointer to security session structure. */
> };
> 
> +/** RTE_FLOW_ACTION_TYPE_PORT
> + *
> + * Redirect packets to a network interface in the same switch domain.
> + *
> + * Terminateing by default.

Typo..

^ permalink raw reply	[flat|nested] 61+ messages in thread

* Re: [dpdk-dev] [PATCH 1/4] ether: add flow action to redirect packet in a switch domain
  2018-03-28 23:29 ` [dpdk-dev] [PATCH 1/4] ether: add flow action to redirect packet in a switch domain Qi Zhang
  2018-03-29 10:48   ` Pattan, Reshma
@ 2018-03-29 11:20   ` Pattan, Reshma
  1 sibling, 0 replies; 61+ messages in thread
From: Pattan, Reshma @ 2018-03-29 11:20 UTC (permalink / raw)
  To: Zhang, Qi Z, adrien.mazarguil
  Cc: dev, Doherty, Declan, Chandran, Sugesh, Glynn, Michael J, Liu,
	Yu Y, Ananyev, Konstantin, Richardson, Bruce, Zhang, Qi Z


Also patch heading  is missing "port"  " ether: add flow action to redirect packet in a switch domain".

^ permalink raw reply	[flat|nested] 61+ messages in thread

* Re: [dpdk-dev] [PATCH 3/4] ether: add more protocol support in flow API
  2018-03-28 23:29 ` [dpdk-dev] [PATCH 3/4] ether: add more protocol support in flow API Qi Zhang
@ 2018-03-29 14:32   ` Pattan, Reshma
  0 siblings, 0 replies; 61+ messages in thread
From: Pattan, Reshma @ 2018-03-29 14:32 UTC (permalink / raw)
  To: Zhang, Qi Z, adrien.mazarguil
  Cc: dev, Doherty, Declan, Chandran, Sugesh, Glynn, Michael J, Liu,
	Yu Y, Ananyev, Konstantin, Richardson, Bruce, Zhang, Qi Z

Hi,

> +
> +	/**
> +	 * Matches ARP IPv4 header.
> +	 *
> +	 * See struct rte_flow_item_arp.
> +	 */
> +	TE_FLOW_ITEM_TYPE_ARP,
> +

R is missing in name RTE_, similary in other places.

+	/**
+	 * Match ICMPv6 Source Link-Layer Address.
+	 *
+	 * See struct rte_flow_item_icmpv6_tll.
+	 */
+	RTE_FLOW_ITEM_TYPE_ICMPV6_TLL,

Description in comments not correct w.r.t enum name.
No need of ',' at the end.

> +
> +/** Default mask for RTE_FLOW_ITEM_TYPE_ARP. */ #ifndef __cplusplus
> +static const struct rte_flow_item_arp rte_flow_item_arp_mask = {
> +	.hdr = {
> +		.arp_data = {
> +			.arp_sha = {
> +			.addr_bytes = "\xff\xff\xff\xff\xff\xff",
> +		},
> +		.arp_sip = RTE_BE32(0xffffffff),
> +		.arp_tha = {
> +			.addr_bytes = "\xff\xff\xff\xff\xff\xff",
> +		},
> +			.arp_tip = RTE_BE32(0xffffffff),
> +		},
> +	},
> +};
> +#endif
> +

Indentation issue in above code.

> +/**
> + * RTE_FLOW_ITEM_TYPE_IPV6_EXT_HDR_ANY
> + *
> + * Matches any IPv6 extension header.
> + */
> +struct rte_flow_item_ipv6_ext_hdr_any {
> +	uint8_t next_hdr;
> +};
> +
> +/** Default mask for RTE_FLOW_ITEM_TYPE_IPV6_EXT_HDR_ANY. */
> #ifndef
> +__cplusplus static const struct rte_flow_item_ipv6_ext_hdr_any
> +rte_flow_item_ipv6_ext_any_mask = {
> +	.next_hdr = 0xff,
> +};
> +#endif

General comment, Is that ok to move all structure declarations together and 
all default mask settings inside one ifndef _cpluscplus?

> +
> +/** Default mask for RTE_FLOW_ITEM_TYPE_ICMPV6_TGT_ADDR */ #ifndef
> +__cplusplus static const struct rte_flow_item_icmpv6_tgt_addr
> +rte_flow_item_icmpv6_tgt_addr_mask = {
> +	.addr = "\xff\xff\xff\xff",

You should assign all 16bytes wilth xff? You are assigning only first 4.

Thanks,
Reshma

^ permalink raw reply	[flat|nested] 61+ messages in thread

* Re: [dpdk-dev] [PATCH 4/4] ether: add packet modification aciton in flow API
  2018-03-28 23:29 ` [dpdk-dev] [PATCH 4/4] ether: add packet modification aciton " Qi Zhang
@ 2018-03-29 15:23   ` Pattan, Reshma
  2018-04-02  3:35     ` Zhang, Qi Z
  0 siblings, 1 reply; 61+ messages in thread
From: Pattan, Reshma @ 2018-03-29 15:23 UTC (permalink / raw)
  To: Zhang, Qi Z, adrien.mazarguil
  Cc: dev, Doherty, Declan, Chandran, Sugesh, Glynn, Michael J, Liu,
	Yu Y, Ananyev, Konstantin, Richardson, Bruce, Zhang, Qi Z

Hi,

> Subject: [dpdk-dev] [PATCH 4/4] ether: add packet modification aciton in flow

Typo in the commit message header "action"

> +/** RTE_FLOW_ACTION_TYPE_FIELD_INCREMENT
> + *
> + * Increment 1 on specific field of the packet.
> + *
> + * Typical usage: increase TTL
> + */
> +struct rte_flow_action_field_increment {
> +	const struct rte_flow_item *item; /**< specify the data to modify. */
> +	uint8_t layer;
> +	/**< 0 means outermost matched pattern, 1 means next-to-
> outermost...
> +*/ };
> +
> +/** RTE_FLOW_ACTION_TYPE_FIELD_DECREMENT
> + *
> + * Decrement 1 on specific field of the packet.
> + *
> + * Typical usage: Decrease TTL
> + */
> +struct rte_flow_action_field_decrement {
> +	const struct rte_flow_item *item; /**< Specify the data to modify. */
> +	uint8_t layer;
> +	/**< 0 means outermost matched pattern, 1 means next-to-
> outermost...
> +*/ };
> +

Can you have only one  struct to represent both increment/decrements operations instead of two structs? As I see both use same data types . 

Thanks,
Reshma

^ permalink raw reply	[flat|nested] 61+ messages in thread

* [dpdk-dev] [PATCH v2 0/4] rte_flow extension for vSwitch acceleration
  2018-03-28 23:29 [dpdk-dev] [PATCH 0/4] rte_flow extension for vSwitch acceleration Qi Zhang
                   ` (3 preceding siblings ...)
  2018-03-28 23:29 ` [dpdk-dev] [PATCH 4/4] ether: add packet modification aciton " Qi Zhang
@ 2018-04-01 21:19 ` Qi Zhang
  2018-04-01 21:19   ` [dpdk-dev] [PATCH v2 1/4] ether: add flow action to redirect packet to a port Qi Zhang
                     ` (4 more replies)
  2018-04-16  5:16 ` [dpdk-dev] [PATCH v3 " Qi Zhang
                   ` (2 subsequent siblings)
  7 siblings, 5 replies; 61+ messages in thread
From: Qi Zhang @ 2018-04-01 21:19 UTC (permalink / raw)
  To: adrien.mazarguil
  Cc: dev, declan.doherty, sugesh.chandran, michael.j.glynn, yu.y.liu,
	konstantin.ananyev, bruce.richardson, Qi Zhang

v2: 
- fix couple typoes in code, doc and commit log

This patch extend rte_flow API.
The purpose is to provide necessary programming interface for virtual
switch software (such as OVS) to take advantage of incoming device's
vSwitch acceleration capability when using DPDK as data plane.

Below is summary of changes:

1. Support to specify flow's destination as an ethdev interface.

Add action RTE_FLOW_ACTION_TYPE_PORT, use port_id as the identification
of the destitation. A typical use case is, with a smart NIC used for vSwitch
acceleration, flow is defined to redirect packet between switch port that is
managed by a Port Representor.

2. Enhanced flow statistics query.
Enhanced action RTE_FLOW_ACTION_COUNT by adding last hit timestamp tracking which is
the requirement from OVS.

3. Add protocol headers which will be supported by incoming device.

New protocal headers include IPV4 ARP, IPV6 ICMP , IPV6 extent header.

4. Add packet modification actions which will be supported by incoming device.

Add new actions that be used to modify packet content with generic semantic:

RTE_FLOW_ACTION_TYPE_FIELD_UPDATE: update specific field of packet
RTE_FLWO_ACTION_TYPE_FIELD_INCREMENT: increament specific field of packet
RTE_FLWO_ACTION_TYPE_FIELD_DECREMENT: decreament specific field of packet
RTE_FLWO_ACTION_TYPE_FIELD_COPY: copy data from one field to another in packet.

All action use struct rte_flow_item parameter to match the pattern that going
to be modified, if no pattern match, the action just be skipped.
These action are non-terminating action. they will not impact the fate of the
packets, since pattern match is expected to be performed before packet be modified. 

Note:
- The driver to demonstrate the new APIs is still in development,
  but we hope it could be accepted early to make OVS integration smoothly.
- Testpmd command line support does not be included and will be submitted
  seperately in future.

Qi Zhang (4):
  ether: add flow action to redirect packet to a port
  ether: add flow last hit query support
  ether: add more protocol support in flow API
  ether: add packet modification aciton in flow API

 doc/guides/prog_guide/rte_flow.rst | 111 +++++++++++++++++
 lib/librte_ether/rte_flow.h        | 238 ++++++++++++++++++++++++++++++++++++-
 2 files changed, 348 insertions(+), 1 deletion(-)

-- 
2.7.4

^ permalink raw reply	[flat|nested] 61+ messages in thread

* [dpdk-dev] [PATCH v2 1/4] ether: add flow action to redirect packet to a port
  2018-04-01 21:19 ` [dpdk-dev] [PATCH v2 0/4] rte_flow extension for vSwitch acceleration Qi Zhang
@ 2018-04-01 21:19   ` Qi Zhang
  2018-04-11 16:30     ` Adrien Mazarguil
  2018-04-01 21:19   ` [dpdk-dev] [PATCH v2 2/4] ether: add flow last hit query support Qi Zhang
                     ` (3 subsequent siblings)
  4 siblings, 1 reply; 61+ messages in thread
From: Qi Zhang @ 2018-04-01 21:19 UTC (permalink / raw)
  To: adrien.mazarguil
  Cc: dev, declan.doherty, sugesh.chandran, michael.j.glynn, yu.y.liu,
	konstantin.ananyev, bruce.richardson, Qi Zhang

Add action RTE_FLOW_ACTION_TYPE_PORT, it can be used to redirect
a packet to a network interface that connect to the same switch
domain, rte_ethdev's port_id is used as an identification of the
destination. A typical use case is: with a smart NIC for vSwitch
acceleration, flow is defined to forward packets between the switch
port that is managed by Port Representor.

Signed-off-by: Qi Zhang <qi.z.zhang@intel.com>
---
 doc/guides/prog_guide/rte_flow.rst | 22 ++++++++++++++++++++++
 lib/librte_ether/rte_flow.h        | 19 ++++++++++++++++++-
 2 files changed, 40 insertions(+), 1 deletion(-)

diff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst
index 961943d..aa5c818 100644
--- a/doc/guides/prog_guide/rte_flow.rst
+++ b/doc/guides/prog_guide/rte_flow.rst
@@ -1486,6 +1486,28 @@ fields in the pattern items.
    | 1     | END      |
    +-------+----------+
 
+Action: ``PORT``
+^^^^^^^^^^^^^^^^
+
+Redirect packets to an interface that connect to the same switch domain.
+
+The desitnation should be managed by a rte_ethdev instance, port_id is
+the identification of the destination. A typical use case is to define
+a flow that redirect packet to a interface that mananged by a Port
+Representor.
+
+- Terminating by default.
+
+.. _table_rte_flow_action_port:
+
+.. table:: PORT
+
+   +--------------+-----------------------------------+
+   | Field        | Value                             |
+   +==============+===================================+
+   | ``port_id``  | identification of the destination |
+   +--------------+-----------------------------------+
+
 Negative types
 ~~~~~~~~~~~~~~
 
diff --git a/lib/librte_ether/rte_flow.h b/lib/librte_ether/rte_flow.h
index 13e4202..1080086 100644
--- a/lib/librte_ether/rte_flow.h
+++ b/lib/librte_ether/rte_flow.h
@@ -1010,7 +1010,14 @@ enum rte_flow_action_type {
 	 *
 	 * See struct rte_flow_action_security.
 	 */
-	RTE_FLOW_ACTION_TYPE_SECURITY
+	RTE_FLOW_ACTION_TYPE_SECURITY,
+
+	/**
+	 * Redirect packets to a network interface in the same switch domain.
+	 *
+	 * See struct rte_flow_action_port.
+	 */
+	RTE_FLOW_ACTION_TYPE_PORT,
 };
 
 /**
@@ -1148,6 +1155,16 @@ struct rte_flow_action_security {
 	void *security_session; /**< Pointer to security session structure. */
 };
 
+/** RTE_FLOW_ACTION_TYPE_PORT
+ *
+ * Redirect packets to a network interface in the same switch domain.
+ *
+ * Terminating by default.
+ */
+struct rte_flow_action_port {
+	uint16_t port_id; /**< identification of the forward destination. */
+};
+
 /**
  * Definition of a single action.
  *
-- 
2.7.4

^ permalink raw reply	[flat|nested] 61+ messages in thread

* [dpdk-dev] [PATCH v2 2/4] ether: add flow last hit query support
  2018-04-01 21:19 ` [dpdk-dev] [PATCH v2 0/4] rte_flow extension for vSwitch acceleration Qi Zhang
  2018-04-01 21:19   ` [dpdk-dev] [PATCH v2 1/4] ether: add flow action to redirect packet to a port Qi Zhang
@ 2018-04-01 21:19   ` Qi Zhang
  2018-04-11 16:31     ` Adrien Mazarguil
  2018-04-01 21:19   ` [dpdk-dev] [PATCH v2 3/4] ether: add more protocol support in flow API Qi Zhang
                     ` (2 subsequent siblings)
  4 siblings, 1 reply; 61+ messages in thread
From: Qi Zhang @ 2018-04-01 21:19 UTC (permalink / raw)
  To: adrien.mazarguil
  Cc: dev, declan.doherty, sugesh.chandran, michael.j.glynn, yu.y.liu,
	konstantin.ananyev, bruce.richardson, Qi Zhang

Enhanced the action RTE_FLOW_TYPE_ACTION_COUNT, number of
milliseconds since last hit can be queried.

Signed-off-by: Qi Zhang <qi.z.zhang@intel.com>
---
 lib/librte_ether/rte_flow.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/lib/librte_ether/rte_flow.h b/lib/librte_ether/rte_flow.h
index 1080086..8f75db0 100644
--- a/lib/librte_ether/rte_flow.h
+++ b/lib/librte_ether/rte_flow.h
@@ -1054,9 +1054,11 @@ struct rte_flow_query_count {
 	uint32_t reset:1; /**< Reset counters after query [in]. */
 	uint32_t hits_set:1; /**< hits field is set [out]. */
 	uint32_t bytes_set:1; /**< bytes field is set [out]. */
+	uint32_t last_hit_set:1; /**< last_hit field is set [out]. */
 	uint32_t reserved:29; /**< Reserved, must be zero [in, out]. */
 	uint64_t hits; /**< Number of hits for this rule [out]. */
 	uint64_t bytes; /**< Number of bytes through this rule [out]. */
+	uint64_t last_hit; /**< Number of milliseconds since last hit [out]. */
 };
 
 /**
-- 
2.7.4

^ permalink raw reply	[flat|nested] 61+ messages in thread

* [dpdk-dev] [PATCH v2 3/4] ether: add more protocol support in flow API
  2018-04-01 21:19 ` [dpdk-dev] [PATCH v2 0/4] rte_flow extension for vSwitch acceleration Qi Zhang
  2018-04-01 21:19   ` [dpdk-dev] [PATCH v2 1/4] ether: add flow action to redirect packet to a port Qi Zhang
  2018-04-01 21:19   ` [dpdk-dev] [PATCH v2 2/4] ether: add flow last hit query support Qi Zhang
@ 2018-04-01 21:19   ` Qi Zhang
  2018-04-11 16:32     ` Adrien Mazarguil
  2018-04-01 21:19   ` [dpdk-dev] [PATCH v2 4/4] ether: add packet modification aciton " Qi Zhang
  2018-04-10 14:12   ` [dpdk-dev] [PATCH v2 0/4] rte_flow extension for vSwitch acceleration Thomas Monjalon
  4 siblings, 1 reply; 61+ messages in thread
From: Qi Zhang @ 2018-04-01 21:19 UTC (permalink / raw)
  To: adrien.mazarguil
  Cc: dev, declan.doherty, sugesh.chandran, michael.j.glynn, yu.y.liu,
	konstantin.ananyev, bruce.richardson, Qi Zhang

Add new protocol header match support as below

RTE_FLOW_ITEM_TYPE_ARP
	- match IPv4 ARP header
RTE_FLOW_ITEM_TYPE_EXT_HDR_ANY
	- match any IPv6 extension header
RTE_FLOW_ITEM_TYPE_ICMPV6
	- match IPv6 ICMP header
RTE_FLOW_ITEM_TYPE_ICMPV6_TGT_ADDR
	- match IPv6 ICMP Target address
RTE_FLOW_ITEM_TYPE_ICMPV6_SSL
	- match IPv6 ICMP Source Link-layer address
RTE_FLOW_ITEM_TYPE_ICMPV6_TTL
	- match IPv6 ICMP Target Link-layer address

Signed-off-by: Qi Zhang <qi.z.zhang@intel.com>
---
 lib/librte_ether/rte_flow.h | 160 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 160 insertions(+)

diff --git a/lib/librte_ether/rte_flow.h b/lib/librte_ether/rte_flow.h
index 8f75db0..a8ec780 100644
--- a/lib/librte_ether/rte_flow.h
+++ b/lib/librte_ether/rte_flow.h
@@ -323,6 +323,49 @@ enum rte_flow_item_type {
 	 * See struct rte_flow_item_geneve.
 	 */
 	RTE_FLOW_ITEM_TYPE_GENEVE,
+
+	/**
+	 * Matches ARP IPv4 header.
+	 *
+	 * See struct rte_flow_item_arp.
+	 */
+	RTE_FLOW_ITEM_TYPE_ARP,
+
+	/**
+	 * Matches any IPv6 Extension header.
+	 *
+	 * See struct rte_flow_item_ipv6_ext_any.
+	 */
+	RTE_FLOW_ITEM_TYPE_IPV6_EXT_HDR_ANY,
+
+	/**
+	 * Matches ICMPv6 header.
+	 *
+	 * See struct rte_flow_item_icmpv6
+	 */
+	RTE_FLOW_ITEM_TYPE_ICMPV6,
+
+	/**
+	 * Match ICMPv6 target address.
+	 *
+	 * See struct rte_flow_item_icmpv6_tgt_addr.
+	 */
+	RTE_FLOW_ITEM_TYPE_ICMPV6_TGT_ADDR,
+
+	/**
+	 * Match ICMPv6 Source Link-Layer Address.
+	 *
+	 * See struct rte_flow_item_icmpv6_sll.
+	 */
+	RTE_FLOW_ITEM_TYPE_ICMPV6_SLL,
+
+	/**
+	 * Match ICMPv6 Target Link-Layer Address.
+	 *
+	 * See struct rte_flow_item_icmpv6_tll.
+	 */
+	RTE_FLOW_ITEM_TYPE_ICMPV6_TLL,
+
 };
 
 /**
@@ -815,6 +858,123 @@ static const struct rte_flow_item_geneve rte_flow_item_geneve_mask = {
 #endif
 
 /**
+ * RTE_FLOW_ITEM_TYPE_ARP
+ *
+ * Matches IPv4 ARP packet header
+ */
+struct rte_flow_item_arp {
+	struct arp_hdr hdr;
+};
+
+/** Default mask for RTE_FLOW_ITEM_TYPE_ARP. */
+#ifndef __cplusplus
+static const struct rte_flow_item_arp rte_flow_item_arp_mask = {
+	.hdr = {
+		.arp_data = {
+			.arp_sha = {
+				.addr_bytes = "\xff\xff\xff\xff\xff\xff",
+			},
+			.arp_sip = RTE_BE32(0xffffffff),
+			.arp_tha = {
+				.addr_bytes = "\xff\xff\xff\xff\xff\xff",
+			},
+			.arp_tip = RTE_BE32(0xffffffff),
+		},
+	},
+};
+#endif
+
+/**
+ * RTE_FLOW_ITEM_TYPE_IPV6_EXT_HDR_ANY
+ *
+ * Matches any IPv6 extension header.
+ */
+struct rte_flow_item_ipv6_ext_hdr_any {
+	uint8_t next_hdr;
+};
+
+/** Default mask for RTE_FLOW_ITEM_TYPE_IPV6_EXT_HDR_ANY. */
+#ifndef __cplusplus
+static const
+struct rte_flow_item_ipv6_ext_hdr_any rte_flow_item_ipv6_ext_any_mask = {
+	.next_hdr = 0xff,
+};
+#endif
+
+/**
+ * RTE_FLOW_ITEM_TYPE_ICMPV6
+ *
+ * Matches ICMPv6 header.
+ */
+struct rte_flow_item_icmpv6 {
+	uint8_t type;
+	uint8_t code;
+	uint16_t checksum;
+};
+
+/** Default mask for RTE_FLOW_ITEM_TYPE_ICMPV6 */
+#ifndef __cplusplus
+static const struct rte_flow_item_icmpv6 rte_flow_item_icmpv6_mask = {
+	.type = 0xff,
+	.code = 0xff,
+	.checksum = RTE_BE16(0xffff),
+};
+#endif
+
+/**
+ * RTE_FLOW_ITEM_TYPE_ICMPV6_TGT_ADDR
+ *
+ * Matches ICMPv6's Target Address.
+ */
+struct rte_flow_item_icmpv6_tgt_addr {
+	uint8_t addr[16];
+};
+
+/** Default mask for RTE_FLOW_ITEM_TYPE_ICMPV6_TGT_ADDR */
+#ifndef __cplusplus
+static const
+struct rte_flow_item_icmpv6_tgt_addr rte_flow_item_icmpv6_tgt_addr_mask = {
+	.addr =
+		"\xff\xff\xff\xff\xff\xff\xff\xff"
+		"\xff\xff\xff\xff\xff\xff\xff\xff",
+};
+#endif
+
+/**
+ * RTE_FLOW_ITEM_TYPE_ICPMV6_SLL.
+ *
+ * Matches ICMPv6 Source Link-Layer address.
+ */
+struct rte_flow_item_icmpv6_sll {
+	struct ether_addr addr;
+};
+/** Default mask for RTE_FLOW_ITEM_TYPE_ICMPV6_SLL */
+#ifndef __cplusplus
+static const struct rte_flow_item_icmpv6_sll rte_flow_item_icmpv6_sll_mask = {
+	.addr = {
+		.addr_bytes = "\xff\xff\xff\xff\xff\xff",
+	}
+};
+#endif
+
+/**
+ * RTE_FLOW_ITEM_TYPE_ICMPV6_TLL.
+ *
+ * Matches ICMPv6 Target Link-Layer address.
+ */
+struct rte_flow_item_icmpv6_tll {
+	struct ether_addr addr;
+};
+/** Default mask for RTE_FLOW_ITEM_TYPE_ICMPV6_TLL */
+#ifndef __cplusplus
+static const struct rte_flow_item_icmpv6_tll rte_flow_item_icmpv6_tll_mask = {
+	.addr = {
+		.addr_bytes = "\xff\xff\xff\xff\xff\xff",
+	}
+};
+#endif
+
+/**
  * Matching pattern item definition.
  *
  * A pattern is formed by stacking items starting from the lowest protocol
-- 
2.7.4

^ permalink raw reply	[flat|nested] 61+ messages in thread

* [dpdk-dev] [PATCH v2 4/4] ether: add packet modification aciton in flow API
  2018-04-01 21:19 ` [dpdk-dev] [PATCH v2 0/4] rte_flow extension for vSwitch acceleration Qi Zhang
                     ` (2 preceding siblings ...)
  2018-04-01 21:19   ` [dpdk-dev] [PATCH v2 3/4] ether: add more protocol support in flow API Qi Zhang
@ 2018-04-01 21:19   ` Qi Zhang
  2018-04-12  7:03     ` Adrien Mazarguil
  2018-04-10 14:12   ` [dpdk-dev] [PATCH v2 0/4] rte_flow extension for vSwitch acceleration Thomas Monjalon
  4 siblings, 1 reply; 61+ messages in thread
From: Qi Zhang @ 2018-04-01 21:19 UTC (permalink / raw)
  To: adrien.mazarguil
  Cc: dev, declan.doherty, sugesh.chandran, michael.j.glynn, yu.y.liu,
	konstantin.ananyev, bruce.richardson, Qi Zhang

Add new actions that be used to modify packet content with
generic semantic:

RTE_FLOW_ACTION_TYPE_FIELD_UPDATE:
	- update specific field of packet
RTE_FLWO_ACTION_TYPE_FIELD_INCREMENT:
	- increament specific field of packet
RTE_FLWO_ACTION_TYPE_FIELD_DECREMENT:
	- decreament specific field of packet
RTE_FLWO_ACTION_TYPE_FIELD_COPY:
	- copy data from one field to another in packet.

All action use struct rte_flow_item parameter to match the pattern
that going to be modified, if no pattern match, the action just be
skipped. These action are non-terminating action. they will not
impact the fate of the packets.

Signed-off-by: Qi Zhang <qi.z.zhang@intel.com>
---
 doc/guides/prog_guide/rte_flow.rst | 89 ++++++++++++++++++++++++++++++++++++++
 lib/librte_ether/rte_flow.h        | 57 ++++++++++++++++++++++++
 2 files changed, 146 insertions(+)

diff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst
index aa5c818..6628964 100644
--- a/doc/guides/prog_guide/rte_flow.rst
+++ b/doc/guides/prog_guide/rte_flow.rst
@@ -1508,6 +1508,95 @@ Representor.
    | ``port_id``  | identification of the destination |
    +--------------+-----------------------------------+
 
+Action: ``FILED_UPDATE``
+^^^^^^^^^^^^^^^^^^^^^^^
+
+Update specific field of the packet.
+
+- Non-terminating by default.
+
+.. _table_rte_flow_action_field_update:
+
+.. table:: FIELD_UPDATE
+
+   +-----------+---------------------------------------------------------+
+   | Field     | Value                                                   |
+   +===========+=========================================================+
+   | ``item``  | item->type: specify the pattern to modify               |
+   |           | item->spec: specify the new value to update             |
+   |           | item->mask: specify which part of the pattern to update |
+   |           | item->last: ignored                                     |
+   +-----------+---------------------------------------------------------+
+   | ``layer`` | 0 means outermost matched pattern,                      |
+   |           | 1 means next-to-outermost and so on ...                 |
+   +-----------+---------------------------------------------------------+
+
+Action: ``FILED_INCREMENT``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Increment 1 on specific field of the packet.
+
+- Non-terminating by default.
+
+.. _table_rte_flow_action_field_update:
+
+.. table:: FIELD_INCREMENT
+
+   +-----------+---------------------------------------------------------+
+   | Field     | Value                                                   |
+   +===========+=========================================================+
+   | ``item``  | item->type: specify the pattern to modify               |
+   |           | item->spec: ignored                                     |
+   |           | item->mask: specify which part of the pattern to update |
+   |           | item->last: ignored                                     |
+   +-----------+---------------------------------------------------------+
+   | ``layer`` | 0 means outermost matched pattern,                      |
+   |           | 1 means next-to-outermost and so on ...                 |
+   +-----------+---------------------------------------------------------+
+
+Action: ``FIELD_DECREMENT``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Decrement 1 on specific field of the packet.
+
+Paramenter is same is FIELD_INCREMENT.
+
+-Non-terminating by default.
+
+ACTION: ``FIELD_COPY``
+^^^^^^^^^^^^^^^^^^^^^^
+
+Copy data of one field to another of the packet.
+
+-Non-terminating by default.
+
+.. _table_rte_flow_action_field_copy:
+
+.. table:: FIELD_COPY
+
+   +-----------------+-----------------------------------------------------------------+
+   | Field           | Value                                                           |
+   +=================+=================================================================+
+   | ``src_item``    | src_item->type: match the pattern that data will be copy from   |
+   |                 | src_item->spec: ignored                                         |
+   |                 | src_item->mask: specify which part of the pattern to copy       |
+   |                 | src_item->last: ignored                                         |
+   +-----------------+-----------------------------------------------------------------+
+   | ``src_layer``   | layer of src_item                                               |
+   |                 | 0 means outermost matched pattern,                              |
+   |                 | 1 means next-to-outermost and so on ...                         |
+   +-----------------+-----------------------------------------------------------------+
+   | ``dst_item``    | dst_item->type: match the pattern that data will be copy to     |
+   |                 | dst_item->spec: ignored                                         |
+   |                 | dst_item->mask: specify which part of the pattern to be update  |
+   |                 |                 it must match src_item->mask.                   |
+   |                 | dst_item->last: ignored                                         |
+   +-----------------+-----------------------------------------------------------------+
+   | ``dst_layer``   | layer of dst_item                                               |
+   |                 | 0 means outermost matched pattern,                              |
+   |                 | 1 means next-to-outermost and so on ...                         |
+   +-----------------+-----------------------------------------------------------------+
+
 Negative types
 ~~~~~~~~~~~~~~
 
diff --git a/lib/librte_ether/rte_flow.h b/lib/librte_ether/rte_flow.h
index a8ec780..d81ac4c 100644
--- a/lib/librte_ether/rte_flow.h
+++ b/lib/librte_ether/rte_flow.h
@@ -1178,6 +1178,34 @@ enum rte_flow_action_type {
 	 * See struct rte_flow_action_port.
 	 */
 	RTE_FLOW_ACTION_TYPE_PORT,
+
+	/**
+	 * Update specific field of the packet.
+	 *
+	 * See struct rte_flow_item_field_update.
+	 */
+	RTE_FLOW_ACTION_TYPE_FILED_UPDATE,
+
+	/**
+	 * Increment specific field of the packet.
+	 *
+	 * See struct rte_flow_item_field_update.
+	 */
+	RTE_FLOW_ACTION_TYPE_FIELD_INCREMENT,
+
+	/**
+	 * Decrement specific field of the packet.
+	 *
+	 * See struct rte_flow_item_field_update.
+	 */
+	RTE_FLOW_ACTION_TYPE_FIELD_DECREMENT,
+
+	/**
+	 * Copy data of one field to another of the packet.
+	 *
+	 * See struct rte_flow_item_type_field_copy.
+	 */
+	RTE_FLOW_ACTION_TYPE_FIELD_COPY,
 };
 
 /**
@@ -1327,6 +1355,35 @@ struct rte_flow_action_port {
 	uint16_t port_id; /**< identification of the forward destination. */
 };
 
+/** RTE_FLOW_ACTION_TYPE_FIELD_UPDATE
+ *  RTE_FLOW_ACTION_TYPE_FIELD_INCREMENT
+ *  RTE_FLOW_ACTION_TYPE_FIELD_DECREMENT
+ *
+ * Update specific field of the packet.
+ *
+ * Typical usage: update mac/ip address.
+ */
+struct rte_flow_action_field_update {
+	const struct rte_flow_item *item; /**< specify the data to modify. */
+	uint8_t layer;
+	/**< 0 means outermost matched pattern, 1 means next-to-outermost... */
+};
+
+/** RTE_FLOW_ACTION_TYPE_FIELD_COPY
+ *
+ * Copy data from one field to another of the packet.
+ *
+ * Typical usage: TTL copy-in / copy-out
+ */
+struct rte_flow_action_field_copy {
+	const struct rte_flow_item *src_item; /**< Specify the data copy from */
+	uint8_t src_layer;
+	/**< 0 means outermost matched pattern, 1 means next-to-outermost... */
+	const struct rte_flow_item *dst_item; /**< Specify the data copy to */
+	uint8_t dst_layer;
+	/**< 0 means outermost matched pattern, 1 means next-to-outermost... */
+};
+
 /**
  * Definition of a single action.
  *
-- 
2.7.4

^ permalink raw reply	[flat|nested] 61+ messages in thread

* Re: [dpdk-dev] [PATCH 4/4] ether: add packet modification aciton in flow API
  2018-03-29 15:23   ` Pattan, Reshma
@ 2018-04-02  3:35     ` Zhang, Qi Z
  0 siblings, 0 replies; 61+ messages in thread
From: Zhang, Qi Z @ 2018-04-02  3:35 UTC (permalink / raw)
  To: Pattan, Reshma, adrien.mazarguil
  Cc: dev, Doherty, Declan, Chandran, Sugesh, Glynn, Michael J, Liu,
	Yu Y, Ananyev, Konstantin, Richardson, Bruce

Hi Reshma:

	Thanks for your review and I accepted most of your comments except:
	1. doc and code will still be merged in one patch to follow the usual way when we add a new API.
	2. code re-org for "ifndef _cpluscplus", is not the scope of the patch, it could be done separately.
	For others I will fix in v2.

Thanks.
Qi

> -----Original Message-----
> From: Pattan, Reshma
> Sent: Thursday, March 29, 2018 11:23 PM
> To: Zhang, Qi Z <qi.z.zhang@intel.com>; adrien.mazarguil@6wind.com
> Cc: dev@dpdk.org; Doherty, Declan <declan.doherty@intel.com>; Chandran,
> Sugesh <sugesh.chandran@intel.com>; Glynn, Michael J
> <michael.j.glynn@intel.com>; Liu, Yu Y <yu.y.liu@intel.com>; Ananyev,
> Konstantin <konstantin.ananyev@intel.com>; Richardson, Bruce
> <bruce.richardson@intel.com>; Zhang, Qi Z <qi.z.zhang@intel.com>
> Subject: RE: [dpdk-dev] [PATCH 4/4] ether: add packet modification aciton in
> flow API
> 
> Hi,
> 
> > Subject: [dpdk-dev] [PATCH 4/4] ether: add packet modification aciton in
> flow
> 
> Typo in the commit message header "action"
> 
> > +/** RTE_FLOW_ACTION_TYPE_FIELD_INCREMENT
> > + *
> > + * Increment 1 on specific field of the packet.
> > + *
> > + * Typical usage: increase TTL
> > + */
> > +struct rte_flow_action_field_increment {
> > +	const struct rte_flow_item *item; /**< specify the data to modify. */
> > +	uint8_t layer;
> > +	/**< 0 means outermost matched pattern, 1 means next-to-
> > outermost...
> > +*/ };
> > +
> > +/** RTE_FLOW_ACTION_TYPE_FIELD_DECREMENT
> > + *
> > + * Decrement 1 on specific field of the packet.
> > + *
> > + * Typical usage: Decrease TTL
> > + */
> > +struct rte_flow_action_field_decrement {
> > +	const struct rte_flow_item *item; /**< Specify the data to modify. */
> > +	uint8_t layer;
> > +	/**< 0 means outermost matched pattern, 1 means next-to-
> > outermost...
> > +*/ };
> > +
> 
> Can you have only one  struct to represent both increment/decrements
> operations instead of two structs? As I see both use same data types .
> 
> Thanks,
> Reshma

^ permalink raw reply	[flat|nested] 61+ messages in thread

* Re: [dpdk-dev] [PATCH v2 0/4] rte_flow extension for vSwitch acceleration
  2018-04-01 21:19 ` [dpdk-dev] [PATCH v2 0/4] rte_flow extension for vSwitch acceleration Qi Zhang
                     ` (3 preceding siblings ...)
  2018-04-01 21:19   ` [dpdk-dev] [PATCH v2 4/4] ether: add packet modification aciton " Qi Zhang
@ 2018-04-10 14:12   ` Thomas Monjalon
  4 siblings, 0 replies; 61+ messages in thread
From: Thomas Monjalon @ 2018-04-10 14:12 UTC (permalink / raw)
  To: adrien.mazarguil
  Cc: dev, Qi Zhang, declan.doherty, sugesh.chandran, michael.j.glynn,
	yu.y.liu, konstantin.ananyev, bruce.richardson

Adrien,

How this series integrate with yours?

Please, we need your review here.


01/04/2018 23:19, Qi Zhang:
> v2: 
> - fix couple typoes in code, doc and commit log
> 
> This patch extend rte_flow API.
> The purpose is to provide necessary programming interface for virtual
> switch software (such as OVS) to take advantage of incoming device's
> vSwitch acceleration capability when using DPDK as data plane.
> 
> Below is summary of changes:
> 
> 1. Support to specify flow's destination as an ethdev interface.
> 
> Add action RTE_FLOW_ACTION_TYPE_PORT, use port_id as the identification
> of the destitation. A typical use case is, with a smart NIC used for vSwitch
> acceleration, flow is defined to redirect packet between switch port that is
> managed by a Port Representor.
> 
> 2. Enhanced flow statistics query.
> Enhanced action RTE_FLOW_ACTION_COUNT by adding last hit timestamp tracking which is
> the requirement from OVS.
> 
> 3. Add protocol headers which will be supported by incoming device.
> 
> New protocal headers include IPV4 ARP, IPV6 ICMP , IPV6 extent header.
> 
> 4. Add packet modification actions which will be supported by incoming device.
> 
> Add new actions that be used to modify packet content with generic semantic:
> 
> RTE_FLOW_ACTION_TYPE_FIELD_UPDATE: update specific field of packet
> RTE_FLWO_ACTION_TYPE_FIELD_INCREMENT: increament specific field of packet
> RTE_FLWO_ACTION_TYPE_FIELD_DECREMENT: decreament specific field of packet
> RTE_FLWO_ACTION_TYPE_FIELD_COPY: copy data from one field to another in packet.
> 
> All action use struct rte_flow_item parameter to match the pattern that going
> to be modified, if no pattern match, the action just be skipped.
> These action are non-terminating action. they will not impact the fate of the
> packets, since pattern match is expected to be performed before packet be modified. 
> 
> Note:
> - The driver to demonstrate the new APIs is still in development,
>   but we hope it could be accepted early to make OVS integration smoothly.
> - Testpmd command line support does not be included and will be submitted
>   seperately in future.
> 
> Qi Zhang (4):
>   ether: add flow action to redirect packet to a port
>   ether: add flow last hit query support
>   ether: add more protocol support in flow API
>   ether: add packet modification aciton in flow API
> 
>  doc/guides/prog_guide/rte_flow.rst | 111 +++++++++++++++++
>  lib/librte_ether/rte_flow.h        | 238 ++++++++++++++++++++++++++++++++++++-
>  2 files changed, 348 insertions(+), 1 deletion(-)
> 
> 

^ permalink raw reply	[flat|nested] 61+ messages in thread

* Re: [dpdk-dev] [PATCH v2 1/4] ether: add flow action to redirect packet to a port
  2018-04-01 21:19   ` [dpdk-dev] [PATCH v2 1/4] ether: add flow action to redirect packet to a port Qi Zhang
@ 2018-04-11 16:30     ` Adrien Mazarguil
  0 siblings, 0 replies; 61+ messages in thread
From: Adrien Mazarguil @ 2018-04-11 16:30 UTC (permalink / raw)
  To: Qi Zhang
  Cc: dev, declan.doherty, sugesh.chandran, michael.j.glynn, yu.y.liu,
	konstantin.ananyev, bruce.richardson

On Sun, Apr 01, 2018 at 05:19:19PM -0400, Qi Zhang wrote:
> Add action RTE_FLOW_ACTION_TYPE_PORT, it can be used to redirect
> a packet to a network interface that connect to the same switch
> domain, rte_ethdev's port_id is used as an identification of the
> destination. A typical use case is: with a smart NIC for vSwitch
> acceleration, flow is defined to forward packets between the switch
> port that is managed by Port Representor.
> 
> Signed-off-by: Qi Zhang <qi.z.zhang@intel.com>

Just to let every one know that as discussed [1], this patch is superseded
by "ethdev: add port ID item and action to flow API" [2].

It is therefore not a candidate for inclusion and does not need to be
reviewed.

[1] http://dpdk.org/ml/archives/dev/2018-April/095525.html
[2] http://dpdk.org/ml/archives/dev/2018-April/096538.html

-- 
Adrien Mazarguil
6WIND

^ permalink raw reply	[flat|nested] 61+ messages in thread

* Re: [dpdk-dev] [PATCH v2 2/4] ether: add flow last hit query support
  2018-04-01 21:19   ` [dpdk-dev] [PATCH v2 2/4] ether: add flow last hit query support Qi Zhang
@ 2018-04-11 16:31     ` Adrien Mazarguil
  0 siblings, 0 replies; 61+ messages in thread
From: Adrien Mazarguil @ 2018-04-11 16:31 UTC (permalink / raw)
  To: Qi Zhang
  Cc: dev, declan.doherty, sugesh.chandran, michael.j.glynn, yu.y.liu,
	konstantin.ananyev, bruce.richardson

On Sun, Apr 01, 2018 at 05:19:20PM -0400, Qi Zhang wrote:
> Enhanced the action RTE_FLOW_TYPE_ACTION_COUNT, number of
> milliseconds since last hit can be queried.
> 
> Signed-off-by: Qi Zhang <qi.z.zhang@intel.com>

Please confirm whether existing devices have the ability to report time
elapsed since last hit, or if PMDs are supposed to take care of that
entirely on their own in software?

If the latter, I suggest to drop this patch and let applications check
counters regularly on their own. Unlike applications, PMDs do not easily
have access to a reliable time source.

Otherwise, the patch looks acceptable but I can't tell if milliseconds are
the right unit for such information. Same issue as mbuf timestamps [1]
basically. As a 64-bit field, a precision down to the nanosecond is a
possibility so perhaps like mbufs, the reference and precision should be
undefined in the API in order to be processed by a PMD callback?

More comments below.

[1] commit 918ae9dc775e ("mbuf: add a timestamp field")

> ---
>  lib/librte_ether/rte_flow.h | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/lib/librte_ether/rte_flow.h b/lib/librte_ether/rte_flow.h
> index 1080086..8f75db0 100644
> --- a/lib/librte_ether/rte_flow.h
> +++ b/lib/librte_ether/rte_flow.h
> @@ -1054,9 +1054,11 @@ struct rte_flow_query_count {
>  	uint32_t reset:1; /**< Reset counters after query [in]. */
>  	uint32_t hits_set:1; /**< hits field is set [out]. */
>  	uint32_t bytes_set:1; /**< bytes field is set [out]. */
> +	uint32_t last_hit_set:1; /**< last_hit field is set [out]. */
>  	uint32_t reserved:29; /**< Reserved, must be zero [in, out]. */

You need to decrement reserved bits.

>  	uint64_t hits; /**< Number of hits for this rule [out]. */
>  	uint64_t bytes; /**< Number of bytes through this rule [out]. */
> +	uint64_t last_hit; /**< Number of milliseconds since last hit [out]. */
>  };

Doing so impacts ABI compatibility. While normally frowned upon for
rte_flow, it's OK for 18.05 because we already destroyed it. You still need
to mention what functions are impacted by this change as in "ethdev: add
encap level to RSS flow API action" [2] and update the .map files where
necessary.

In this case at least rte_flow_query() is impacted.

Please update doc/guides/prog_guide/rte_flow.rst as well (look for "COUNT
query").

[2] http://dpdk.org/ml/archives/dev/2018-April/096531.html

-- 
Adrien Mazarguil
6WIND

^ permalink raw reply	[flat|nested] 61+ messages in thread

* Re: [dpdk-dev] [PATCH v2 3/4] ether: add more protocol support in flow API
  2018-04-01 21:19   ` [dpdk-dev] [PATCH v2 3/4] ether: add more protocol support in flow API Qi Zhang
@ 2018-04-11 16:32     ` Adrien Mazarguil
  2018-04-12  5:12       ` Zhang, Qi Z
  0 siblings, 1 reply; 61+ messages in thread
From: Adrien Mazarguil @ 2018-04-11 16:32 UTC (permalink / raw)
  To: Qi Zhang
  Cc: dev, declan.doherty, sugesh.chandran, michael.j.glynn, yu.y.liu,
	konstantin.ananyev, bruce.richardson

On Sun, Apr 01, 2018 at 05:19:21PM -0400, Qi Zhang wrote:
> Add new protocol header match support as below
> 
> RTE_FLOW_ITEM_TYPE_ARP
> 	- match IPv4 ARP header
> RTE_FLOW_ITEM_TYPE_EXT_HDR_ANY
> 	- match any IPv6 extension header

While properly defined in the patch, "IPV6" is missing here.

> RTE_FLOW_ITEM_TYPE_ICMPV6
> 	- match IPv6 ICMP header
> RTE_FLOW_ITEM_TYPE_ICMPV6_TGT_ADDR
> 	- match IPv6 ICMP Target address
> RTE_FLOW_ITEM_TYPE_ICMPV6_SSL
> 	- match IPv6 ICMP Source Link-layer address
> RTE_FLOW_ITEM_TYPE_ICMPV6_TTL
> 	- match IPv6 ICMP Target Link-layer address
> 
> Signed-off-by: Qi Zhang <qi.z.zhang@intel.com>

First, since they are added at the end of enum rte_flow_item_type, no ABI
breakage notice is necessary.

However testpmd implementation [1][2] and documentation update [3][4] are
mandatory for all new pattern items and actions.

More comments below regarding these definitions.

[1] flow_item[] in app/test-pmd/config.c
[2] using ITEM_ICMP as an example in app/test-pmd/cmdline_flow.c
[3] "Pattern items" section in doc/guides/testpmd_app_ug/testpmd_funcs.rst
[4] using "Item: ``ICMP``" section as an example in
    doc/guides/prog_guide/rte_flow.rst

> ---
>  lib/librte_ether/rte_flow.h | 160 ++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 160 insertions(+)
> 
> diff --git a/lib/librte_ether/rte_flow.h b/lib/librte_ether/rte_flow.h
> index 8f75db0..a8ec780 100644
> --- a/lib/librte_ether/rte_flow.h
> +++ b/lib/librte_ether/rte_flow.h
> @@ -323,6 +323,49 @@ enum rte_flow_item_type {
>  	 * See struct rte_flow_item_geneve.
>  	 */
>  	RTE_FLOW_ITEM_TYPE_GENEVE,
> +
> +	/**
> +	 * Matches ARP IPv4 header.

=> Matches an IPv4 ARP header.

> +	 *
> +	 * See struct rte_flow_item_arp.
> +	 */
> +	RTE_FLOW_ITEM_TYPE_ARP,

While you're right to make "IPv4" clear since ARP is also used for other
protocols DPDK doesn't support (and likely never will), the ARP header has
both a fixed and a variably-sized part.

Ideally an ARP pattern item should match the fixed part only and a separate
ARP_IPV4 match its payload, somewhat like you did for ICMPv6/NDP below.

Problem is that in DPDK, struct arp_hdr includes struct arp_ipv4, so one
suggestion would be to rename this pattern item ARP_IPV4 directly:

=> RTE_FLOW_ITEM_TYPE_ARP_IPV4

> +
> +	/**
> +	 * Matches any IPv6 Extension header.

=> Matches an IPv6 extension header.

> +	 *
> +	 * See struct rte_flow_item_ipv6_ext_any.
> +	 */
> +	RTE_FLOW_ITEM_TYPE_IPV6_EXT_HDR_ANY,

I'm not sure this definition is necessary, more below about that.

Also I don't see a benefit in having "ANY" part of the name, if you want to
keep it, I suggest the simpler:

=> RTE_FLOW_ITEM_TYPE_IPV6_EXT

> +
> +	/**
> +	 * Matches ICMPv6 header.

=> Matches an ICMPv6 header.

> +	 *
> +	 * See struct rte_flow_item_icmpv6

Missing "."

> +	 */
> +	RTE_FLOW_ITEM_TYPE_ICMPV6,
> +

Before entering NDP territory below, I understand those should be stacked on
top of RTE_FLOW_ITEM_TYPE_ICMPV6. It's fine but for clarity they should be
named after the NDP types they represent, not inner data fields.

Also I think we should consider NDP as a protocol sitting on top of
ICMPv6. We could therefore drop "ICMP" from these definitions.

Since "ND" is a common shorthand for this protocol and "6" another when
doing something related to IPv6, I suggest to use "ND6" to name he related
pattern items.

These are the reasons behind my next suggestions:

> +	/**
> +	 * Match ICMPv6 target address.
> +	 *
> +	 * See struct rte_flow_item_icmpv6_tgt_addr.
> +	 */
> +	RTE_FLOW_ITEM_TYPE_ICMPV6_TGT_ADDR,

=> Matches an IPv6 network discovery router solicitation.
=> See struct rte_flow_item_nd6_rs.
=> RTE_FLOW_ITEM_TYPE_ND6_RS,

You should add another item for neighbor advertisement messages using the
same template:

=> Match an IPv6 network discovery neighbor advertisement.
=> See struct rte_flow_item_nd6_na.
=> RTE_FLOW_ITEM_TYPE_ND6_NA,

The following are possible options for these headers, if specified they must
be found afterward. Also since IPv6 may run on top of protocols other than
Ethernet, you need to clarify these link-layer addresses use the Ethernet
format:

> +
> +	/**
> +	 * Match ICMPv6 Source Link-Layer Address.
> +	 *
> +	 * See struct rte_flow_item_icmpv6_sll.
> +	 */
> +	RTE_FLOW_ITEM_TYPE_ICMPV6_SLL,

=> Matches an IPv6 network discovery source Ethernet link-layer address option.
=> See struct rte_flow_item_nd6_opt_sla_eth.
=> RTE_FLOW_ITEM_TYPE_ND6_OPT_SLA_ETH,

> +
> +	/**
> +	 * Match ICMPv6 Target Link-Layer Address.
> +	 *
> +	 * See struct rte_flow_item_icmpv6_tll.
> +	 */
> +	RTE_FLOW_ITEM_TYPE_ICMPV6_TLL,

=> Matches an IPv6 network discovery target Ethernet link-layer address option.
=> See struct rte_flow_item_nd6_opt_tla_eth.
=> RTE_FLOW_ITEM_TYPE_ND6_OPT_TLA_ETH,

> +

Unnecessary empty line.

>  };
>  
>  /**
> @@ -815,6 +858,123 @@ static const struct rte_flow_item_geneve rte_flow_item_geneve_mask = {
>  #endif
>  
>  /**
> + * RTE_FLOW_ITEM_TYPE_ARP
> + *
> + * Matches IPv4 ARP packet header

As above:

=> Matches an IPv4 ARP header.
=> RTE_FLOW_ITEM_TYPE_ARP_IPV4

> + */
> +struct rte_flow_item_arp {
> +	struct arp_hdr hdr;
> +};

Needs #include <rte_arp.h> and a Doxygen comment next to hdr for
consistency, see ICMP and other definitions.

> +
> +/** Default mask for RTE_FLOW_ITEM_TYPE_ARP. */
> +#ifndef __cplusplus
> +static const struct rte_flow_item_arp rte_flow_item_arp_mask = {
> +	.hdr = {
> +		.arp_data = {
> +			.arp_sha = {
> +				.addr_bytes = "\xff\xff\xff\xff\xff\xff",
> +			},
> +			.arp_sip = RTE_BE32(0xffffffff),
> +			.arp_tha = {
> +				.addr_bytes = "\xff\xff\xff\xff\xff\xff",
> +			},
> +			.arp_tip = RTE_BE32(0xffffffff),
> +		},
> +	},
> +};
> +#endif
> +
> +/**
> + * RTE_FLOW_ITEM_TYPE_IPV6_EXT_HDR_ANY
> + *
> + * Matches any IPv6 extension header.
> + */
> +struct rte_flow_item_ipv6_ext_hdr_any {
> +	uint8_t next_hdr;
> +};

So what's the point? next_hdr is already part of either struct ipv6_hdr
("proto") and individual extension headers. Moreover it's implicit if an
extension header is provided in a pattern.

How about removing it?

> +
> +/** Default mask for RTE_FLOW_ITEM_TYPE_IPV6_EXT_HDR_ANY. */
> +#ifndef __cplusplus
> +static const
> +struct rte_flow_item_ipv6_ext_hdr_any rte_flow_item_ipv6_ext_any_mask = {
> +	.next_hdr = 0xff,
> +};
> +#endif

Ditto.

> +
> +/**
> + * RTE_FLOW_ITEM_TYPE_ICMPV6
> + *
> + * Matches ICMPv6 header.

=> Matches an ICMPv6 header.

> + */
> +struct rte_flow_item_icmpv6 {
> +	uint8_t type;
> +	uint8_t code;
> +	uint16_t checksum;

The last 32-bit "reserved" data field is missing.

> +};

Too bad there is no struct icmp6_hdr definition in rte_icmp.h. You could add
it. In any case Doxygen comments are missing, please add them (see other
structure definitions for examples).

> +
> +/** Default mask for RTE_FLOW_ITEM_TYPE_ICMPV6 */

Missing "."

> +#ifndef __cplusplus
> +static const struct rte_flow_item_icmpv6 rte_flow_item_icmpv6_mask = {
> +	.type = 0xff,
> +	.code = 0xff,
> +	.checksum = RTE_BE16(0xffff),
> +};
> +#endif

You must remove checksum matching from the default mask. That's the last
thing an application might want to match exactly :)

> +
> +/**
> + * RTE_FLOW_ITEM_TYPE_ICMPV6_TGT_ADDR
> + *
> + * Matches ICMPv6's Target Address.
> + */
> +struct rte_flow_item_icmpv6_tgt_addr {
> +	uint8_t addr[16];
> +};

You need to expand this as two items, see prior comments regarding
RTE_FLOW_ITEM_TYPE_ND6_RS, RTE_FLOW_ITEM_TYPE_ND6_NA and their respective
structs rte_flow_item_nd6_rs and rte_flow_item_nd6_na.

Also Doxygen documentation is missing for the addr field and you need to
describe that these are only valid when used after
RTE_FLOW_ITEM_TYPE_ICMPV6.

> +
> +/** Default mask for RTE_FLOW_ITEM_TYPE_ICMPV6_TGT_ADDR */

Missing "."

> +#ifndef __cplusplus
> +static const
> +struct rte_flow_item_icmpv6_tgt_addr rte_flow_item_icmpv6_tgt_addr_mask = {
> +	.addr =
> +		"\xff\xff\xff\xff\xff\xff\xff\xff"
> +		"\xff\xff\xff\xff\xff\xff\xff\xff",
> +};
> +#endif
> +
> +/**
> + * RTE_FLOW_ITEM_TYPE_ICPMV6_SLL.
> + *
> + * Matches ICMPv6 Source Link-Layer address.
> + */
> +struct rte_flow_item_icmpv6_sll {
> +	struct ether_addr addr;
> +};

See prior comments regarding RTE_FLOW_ITEM_TYPE_ND6_OPT_SLA_ETH and struct
rte_flow_item_type_nd6_opt_sla_eth.

Also Doxygen documentation is missing for the addr field and you need to
describe that it is only valid when found after either
RTE_FLOW_ITEM_TYPE_ND6_RS or RTE_FLOW_ITEM_TYPE_ND6_NA.

Also missing empty line here.

> +/** Default mask for RTE_FLOW_ITEM_TYPE_ICMPV6_SLL */

Missing "."

> +#ifndef __cplusplus
> +static const struct rte_flow_item_icmpv6_sll rte_flow_item_icmpv6_sll_mask = {
> +	.addr = {
> +		.addr_bytes = "\xff\xff\xff\xff\xff\xff",
> +	}
> +};
> +#endif
> +
> +/**
> + * RTE_FLOW_ITEM_TYPE_ICMPV6_TLL.
> + *
> + * Matches ICMPv6 Target Link-Layer address.
> + */
> +struct rte_flow_item_icmpv6_tll {
> +	struct ether_addr addr;
> +};

See prior comments regarding RTE_FLOW_ITEM_TYPE_ND6_OPT_TLA_ETH and struct
rte_flow_item_type_nd6_opt_tla_eth.

Also Doxygen documentation is missing for the addr field and you need to
describe that it is only valid when found after either
RTE_FLOW_ITEM_TYPE_ND6_RS or RTE_FLOW_ITEM_TYPE_ND6_NA.

Also missing empty line here.

> +/** Default mask for RTE_FLOW_ITEM_TYPE_ICMPV6_TLL */

Missing "."

> +#ifndef __cplusplus
> +static const struct rte_flow_item_icmpv6_tll rte_flow_item_icmpv6_tll_mask = {
> +	.addr = {
> +		.addr_bytes = "\xff\xff\xff\xff\xff\xff",
> +	}
> +};
> +#endif
> +
> +/**
>   * Matching pattern item definition.
>   *
>   * A pattern is formed by stacking items starting from the lowest protocol
> -- 
> 2.7.4
> 

-- 
Adrien Mazarguil
6WIND

^ permalink raw reply	[flat|nested] 61+ messages in thread

* Re: [dpdk-dev] [PATCH v2 3/4] ether: add more protocol support in flow API
  2018-04-11 16:32     ` Adrien Mazarguil
@ 2018-04-12  5:12       ` Zhang, Qi Z
  2018-04-12  9:19         ` Adrien Mazarguil
  0 siblings, 1 reply; 61+ messages in thread
From: Zhang, Qi Z @ 2018-04-12  5:12 UTC (permalink / raw)
  To: Adrien Mazarguil
  Cc: dev, Doherty, Declan, Chandran, Sugesh, Glynn, Michael J, Liu,
	Yu Y, Ananyev, Konstantin, Richardson, Bruce

Hi Adrien:

	Thank you so much for your careful review and helpful suggestions!
	I agree with most of your comments, except couple question about RTE_FLOW_ITEM_TYPE_TGT_ADDR and RTE_FLOW_ITEM_IPV6_EXT_HDR
	Please see my comment inline.

Thanks!
Qi

> -----Original Message-----
> From: Adrien Mazarguil [mailto:adrien.mazarguil@6wind.com]
> Sent: Thursday, April 12, 2018 12:32 AM
> To: Zhang, Qi Z <qi.z.zhang@intel.com>
> Cc: dev@dpdk.org; Doherty, Declan <declan.doherty@intel.com>; Chandran,
> Sugesh <sugesh.chandran@intel.com>; Glynn, Michael J
> <michael.j.glynn@intel.com>; Liu, Yu Y <yu.y.liu@intel.com>; Ananyev,
> Konstantin <konstantin.ananyev@intel.com>; Richardson, Bruce
> <bruce.richardson@intel.com>
> Subject: Re: [PATCH v2 3/4] ether: add more protocol support in flow API
> 
> On Sun, Apr 01, 2018 at 05:19:21PM -0400, Qi Zhang wrote:
> > Add new protocol header match support as below
> >
> > RTE_FLOW_ITEM_TYPE_ARP
> > 	- match IPv4 ARP header
> > RTE_FLOW_ITEM_TYPE_EXT_HDR_ANY
> > 	- match any IPv6 extension header
> 
> While properly defined in the patch, "IPV6" is missing here.
> 
> > RTE_FLOW_ITEM_TYPE_ICMPV6
> > 	- match IPv6 ICMP header
> > RTE_FLOW_ITEM_TYPE_ICMPV6_TGT_ADDR
> > 	- match IPv6 ICMP Target address
> > RTE_FLOW_ITEM_TYPE_ICMPV6_SSL
> > 	- match IPv6 ICMP Source Link-layer address
> > RTE_FLOW_ITEM_TYPE_ICMPV6_TTL
> > 	- match IPv6 ICMP Target Link-layer address
> >
> > Signed-off-by: Qi Zhang <qi.z.zhang@intel.com>
> 
> First, since they are added at the end of enum rte_flow_item_type, no ABI
> breakage notice is necessary.
> 
> However testpmd implementation [1][2] and documentation update [3][4] are
> mandatory for all new pattern items and actions.

OK, will add this into v2.

> 
> More comments below regarding these definitions.
> 
> [1] flow_item[] in app/test-pmd/config.c [2] using ITEM_ICMP as an example
> in app/test-pmd/cmdline_flow.c [3] "Pattern items" section in
> doc/guides/testpmd_app_ug/testpmd_funcs.rst
> [4] using "Item: ``ICMP``" section as an example in
>     doc/guides/prog_guide/rte_flow.rst
> 
> > ---
> >  lib/librte_ether/rte_flow.h | 160
> > ++++++++++++++++++++++++++++++++++++++++++++
> >  1 file changed, 160 insertions(+)
> >
> > diff --git a/lib/librte_ether/rte_flow.h b/lib/librte_ether/rte_flow.h
> > index 8f75db0..a8ec780 100644
> > --- a/lib/librte_ether/rte_flow.h
> > +++ b/lib/librte_ether/rte_flow.h
> > @@ -323,6 +323,49 @@ enum rte_flow_item_type {
> >  	 * See struct rte_flow_item_geneve.
> >  	 */
> >  	RTE_FLOW_ITEM_TYPE_GENEVE,
> > +
> > +	/**
> > +	 * Matches ARP IPv4 header.
> 
> => Matches an IPv4 ARP header.
> 
> > +	 *
> > +	 * See struct rte_flow_item_arp.
> > +	 */
> > +	RTE_FLOW_ITEM_TYPE_ARP,
> 
> While you're right to make "IPv4" clear since ARP is also used for other
> protocols DPDK doesn't support (and likely never will), the ARP header has
> both a fixed and a variably-sized part.
> 
> Ideally an ARP pattern item should match the fixed part only and a separate
> ARP_IPV4 match its payload, somewhat like you did for ICMPv6/NDP below.
> 
> Problem is that in DPDK, struct arp_hdr includes struct arp_ipv4, so one
> suggestion would be to rename this pattern item ARP_IPV4 directly:
> 
> => RTE_FLOW_ITEM_TYPE_ARP_IPV4
> 
> > +
> > +	/**
> > +	 * Matches any IPv6 Extension header.
> 
> => Matches an IPv6 extension header.
> 
> > +	 *
> > +	 * See struct rte_flow_item_ipv6_ext_any.
> > +	 */
> > +	RTE_FLOW_ITEM_TYPE_IPV6_EXT_HDR_ANY,
> 
> I'm not sure this definition is necessary, more below about that.
> 
> Also I don't see a benefit in having "ANY" part of the name, if you want to keep
> it, I suggest the simpler:
> 
> => RTE_FLOW_ITEM_TYPE_IPV6_EXT
> 
> > +
> > +	/**
> > +	 * Matches ICMPv6 header.
> 
> => Matches an ICMPv6 header.
> 
> > +	 *
> > +	 * See struct rte_flow_item_icmpv6
> 
> Missing "."
> 
> > +	 */
> > +	RTE_FLOW_ITEM_TYPE_ICMPV6,
> > +
> 
> Before entering NDP territory below, I understand those should be stacked on
> top of RTE_FLOW_ITEM_TYPE_ICMPV6. It's fine but for clarity they should be
> named after the NDP types they represent, not inner data fields.
> 
> Also I think we should consider NDP as a protocol sitting on top of ICMPv6. We
> could therefore drop "ICMP" from these definitions.
> 
> Since "ND" is a common shorthand for this protocol and "6" another when
> doing something related to IPv6, I suggest to use "ND6" to name he related
> pattern items.

I agree.

> 
> These are the reasons behind my next suggestions:
> 
> > +	/**
> > +	 * Match ICMPv6 target address.
> > +	 *
> > +	 * See struct rte_flow_item_icmpv6_tgt_addr.
> > +	 */
> > +	RTE_FLOW_ITEM_TYPE_ICMPV6_TGT_ADDR,
> 
> => Matches an IPv6 network discovery router solicitation.
> => See struct rte_flow_item_nd6_rs.
> => RTE_FLOW_ITEM_TYPE_ND6_RS,
> 
> You should add another item for neighbor advertisement messages using the
> same template:
> 
> => Match an IPv6 network discovery neighbor advertisement.
> => See struct rte_flow_item_nd6_na.
> => RTE_FLOW_ITEM_TYPE_ND6_NA,

The purpose of RTE_FLOW_ITEM_TYPE_ICMPV6_TGT_ADDR is to match a "target address"
according to IPv6 ND spec https://tools.ietf.org/html/rfc4861#page-22, when type = 135/136

so do you mean we should have RTE_FLOW_ITEM_TYPE_ND6_NS (Neighbor Solicitation)
 and RTE_FLOW_ITEM_TYPE_ND6_NA (Neighbor Advertisement) here,
and with the same template (an IPV6 addr) for rte_flow_item_icmpv6_tgt_addr?

> 
> The following are possible options for these headers, if specified they must be
> found afterward. Also since IPv6 may run on top of protocols other than
> Ethernet, you need to clarify these link-layer addresses use the Ethernet
> format:
> 
> > +
> > +	/**
> > +	 * Match ICMPv6 Source Link-Layer Address.
> > +	 *
> > +	 * See struct rte_flow_item_icmpv6_sll.
> > +	 */
> > +	RTE_FLOW_ITEM_TYPE_ICMPV6_SLL,
> 
> => Matches an IPv6 network discovery source Ethernet link-layer address
> option.
> => See struct rte_flow_item_nd6_opt_sla_eth.
> => RTE_FLOW_ITEM_TYPE_ND6_OPT_SLA_ETH,
> 
> > +
> > +	/**
> > +	 * Match ICMPv6 Target Link-Layer Address.
> > +	 *
> > +	 * See struct rte_flow_item_icmpv6_tll.
> > +	 */
> > +	RTE_FLOW_ITEM_TYPE_ICMPV6_TLL,
> 
> => Matches an IPv6 network discovery target Ethernet link-layer address
> option.
> => See struct rte_flow_item_nd6_opt_tla_eth.
> => RTE_FLOW_ITEM_TYPE_ND6_OPT_TLA_ETH,
> 

Agree to rename.

> > +
> 
> Unnecessary empty line.
> 
> >  };
> >
> >  /**
> > @@ -815,6 +858,123 @@ static const struct rte_flow_item_geneve
> > rte_flow_item_geneve_mask = {  #endif
> >
> >  /**
> > + * RTE_FLOW_ITEM_TYPE_ARP
> > + *
> > + * Matches IPv4 ARP packet header
> 
> As above:
> 
> => Matches an IPv4 ARP header.
> => RTE_FLOW_ITEM_TYPE_ARP_IPV4
> 
> > + */
> > +struct rte_flow_item_arp {
> > +	struct arp_hdr hdr;
> > +};
> 
> Needs #include <rte_arp.h> and a Doxygen comment next to hdr for
> consistency, see ICMP and other definitions.
> 
> > +
> > +/** Default mask for RTE_FLOW_ITEM_TYPE_ARP. */ #ifndef __cplusplus
> > +static const struct rte_flow_item_arp rte_flow_item_arp_mask = {
> > +	.hdr = {
> > +		.arp_data = {
> > +			.arp_sha = {
> > +				.addr_bytes = "\xff\xff\xff\xff\xff\xff",
> > +			},
> > +			.arp_sip = RTE_BE32(0xffffffff),
> > +			.arp_tha = {
> > +				.addr_bytes = "\xff\xff\xff\xff\xff\xff",
> > +			},
> > +			.arp_tip = RTE_BE32(0xffffffff),
> > +		},
> > +	},
> > +};
> > +#endif
> > +
> > +/**
> > + * RTE_FLOW_ITEM_TYPE_IPV6_EXT_HDR_ANY
> > + *
> > + * Matches any IPv6 extension header.
> > + */
> > +struct rte_flow_item_ipv6_ext_hdr_any {
> > +	uint8_t next_hdr;
> > +};
> 
> So what's the point? next_hdr is already part of either struct ipv6_hdr
> ("proto") and individual extension headers. Moreover it's implicit if an
> extension header is provided in a pattern.
> 
> How about removing it?

We need this to match a packet that have extend header
For example:
IPV6(proto = 43, <Routing EH >) / EXT_HDR (next_head = 60 <Destination EH>) / EXT_HDR (next_head = 44, <Fragment EH)/ EXT_HDR (next_head = 6 <tcp>) / TCP ...

I use "ANY" to match any extend header regardless their content.
There is no conflict if we can add multiple RTE_FLOW_ITEM_EXT_HDR_XXX in futures

> 
> > +
> > +/** Default mask for RTE_FLOW_ITEM_TYPE_IPV6_EXT_HDR_ANY. */
> #ifndef
> > +__cplusplus static const struct rte_flow_item_ipv6_ext_hdr_any
> > +rte_flow_item_ipv6_ext_any_mask = {
> > +	.next_hdr = 0xff,
> > +};
> > +#endif
> 
> Ditto.
> 
> > +
> > +/**
> > + * RTE_FLOW_ITEM_TYPE_ICMPV6
> > + *
> > + * Matches ICMPv6 header.
> 
> => Matches an ICMPv6 header.
> 
> > + */
> > +struct rte_flow_item_icmpv6 {
> > +	uint8_t type;
> > +	uint8_t code;
> > +	uint16_t checksum;
> 
> The last 32-bit "reserved" data field is missing.
> 
> > +};
> 
> Too bad there is no struct icmp6_hdr definition in rte_icmp.h. You could add it.
> In any case Doxygen comments are missing, please add them (see other
> structure definitions for examples).
> 
> > +
> > +/** Default mask for RTE_FLOW_ITEM_TYPE_ICMPV6 */
> 
> Missing "."
> 
> > +#ifndef __cplusplus
> > +static const struct rte_flow_item_icmpv6 rte_flow_item_icmpv6_mask = {
> > +	.type = 0xff,
> > +	.code = 0xff,
> > +	.checksum = RTE_BE16(0xffff),
> > +};
> > +#endif
> 
> You must remove checksum matching from the default mask. That's the last
> thing an application might want to match exactly :)
> 
> > +
> > +/**
> > + * RTE_FLOW_ITEM_TYPE_ICMPV6_TGT_ADDR
> > + *
> > + * Matches ICMPv6's Target Address.
> > + */
> > +struct rte_flow_item_icmpv6_tgt_addr {
> > +	uint8_t addr[16];
> > +};
> 
> You need to expand this as two items, see prior comments regarding
> RTE_FLOW_ITEM_TYPE_ND6_RS, RTE_FLOW_ITEM_TYPE_ND6_NA and their
> respective structs rte_flow_item_nd6_rs and rte_flow_item_nd6_na.
> 
> Also Doxygen documentation is missing for the addr field and you need to
> describe that these are only valid when used after
> RTE_FLOW_ITEM_TYPE_ICMPV6.
> 
> > +
> > +/** Default mask for RTE_FLOW_ITEM_TYPE_ICMPV6_TGT_ADDR */
> 
> Missing "."
> 
> > +#ifndef __cplusplus
> > +static const
> > +struct rte_flow_item_icmpv6_tgt_addr
> rte_flow_item_icmpv6_tgt_addr_mask = {
> > +	.addr =
> > +		"\xff\xff\xff\xff\xff\xff\xff\xff"
> > +		"\xff\xff\xff\xff\xff\xff\xff\xff",
> > +};
> > +#endif
> > +
> > +/**
> > + * RTE_FLOW_ITEM_TYPE_ICPMV6_SLL.
> > + *
> > + * Matches ICMPv6 Source Link-Layer address.
> > + */
> > +struct rte_flow_item_icmpv6_sll {
> > +	struct ether_addr addr;
> > +};
> 
> See prior comments regarding RTE_FLOW_ITEM_TYPE_ND6_OPT_SLA_ETH and
> struct rte_flow_item_type_nd6_opt_sla_eth.
> 
> Also Doxygen documentation is missing for the addr field and you need to
> describe that it is only valid when found after either
> RTE_FLOW_ITEM_TYPE_ND6_RS or RTE_FLOW_ITEM_TYPE_ND6_NA.
> 
> Also missing empty line here.
> 
> > +/** Default mask for RTE_FLOW_ITEM_TYPE_ICMPV6_SLL */
> 
> Missing "."
> 
> > +#ifndef __cplusplus
> > +static const struct rte_flow_item_icmpv6_sll
> rte_flow_item_icmpv6_sll_mask = {
> > +	.addr = {
> > +		.addr_bytes = "\xff\xff\xff\xff\xff\xff",
> > +	}
> > +};
> > +#endif
> > +
> > +/**
> > + * RTE_FLOW_ITEM_TYPE_ICMPV6_TLL.
> > + *
> > + * Matches ICMPv6 Target Link-Layer address.
> > + */
> > +struct rte_flow_item_icmpv6_tll {
> > +	struct ether_addr addr;
> > +};
> 
> See prior comments regarding RTE_FLOW_ITEM_TYPE_ND6_OPT_TLA_ETH
> and struct rte_flow_item_type_nd6_opt_tla_eth.
> 
> Also Doxygen documentation is missing for the addr field and you need to
> describe that it is only valid when found after either
> RTE_FLOW_ITEM_TYPE_ND6_RS or RTE_FLOW_ITEM_TYPE_ND6_NA.
> 
> Also missing empty line here.
> 
> > +/** Default mask for RTE_FLOW_ITEM_TYPE_ICMPV6_TLL */
> 
> Missing "."
> 
> > +#ifndef __cplusplus
> > +static const struct rte_flow_item_icmpv6_tll
> rte_flow_item_icmpv6_tll_mask = {
> > +	.addr = {
> > +		.addr_bytes = "\xff\xff\xff\xff\xff\xff",
> > +	}
> > +};
> > +#endif
> > +
> > +/**
> >   * Matching pattern item definition.
> >   *
> >   * A pattern is formed by stacking items starting from the lowest
> > protocol
> > --
> > 2.7.4
> >
> 
> --
> Adrien Mazarguil
> 6WIND

^ permalink raw reply	[flat|nested] 61+ messages in thread

* Re: [dpdk-dev] [PATCH v2 4/4] ether: add packet modification aciton in flow API
  2018-04-01 21:19   ` [dpdk-dev] [PATCH v2 4/4] ether: add packet modification aciton " Qi Zhang
@ 2018-04-12  7:03     ` Adrien Mazarguil
  2018-04-12  8:50       ` Zhang, Qi Z
  0 siblings, 1 reply; 61+ messages in thread
From: Adrien Mazarguil @ 2018-04-12  7:03 UTC (permalink / raw)
  To: Qi Zhang
  Cc: dev, declan.doherty, sugesh.chandran, michael.j.glynn, yu.y.liu,
	konstantin.ananyev, bruce.richardson

On Sun, Apr 01, 2018 at 05:19:22PM -0400, Qi Zhang wrote:
> Add new actions that be used to modify packet content with
> generic semantic:
> 
> RTE_FLOW_ACTION_TYPE_FIELD_UPDATE:
> 	- update specific field of packet
> RTE_FLWO_ACTION_TYPE_FIELD_INCREMENT:
> 	- increament specific field of packet
> RTE_FLWO_ACTION_TYPE_FIELD_DECREMENT:
> 	- decreament specific field of packet
> RTE_FLWO_ACTION_TYPE_FIELD_COPY:
> 	- copy data from one field to another in packet.
> 
> All action use struct rte_flow_item parameter to match the pattern
> that going to be modified, if no pattern match, the action just be
> skipped.

That's not good. It must result in undefined behavior, more about that
below.

> These action are non-terminating action. they will not
> impact the fate of the packets.
> 
> Signed-off-by: Qi Zhang <qi.z.zhang@intel.com>

Noticed a few typos above and in subject line ("aciton", "FLWO",
"increament", "decreament").

Note that I'm usually against using rte_flow_item structures and associated
enum values inside action lists because it could be seen as inconsistent
from an API standpoint. On the other hand, reusing existing types is a good
thing so let's go with that for now.

Please see inline comments.

> ---
>  doc/guides/prog_guide/rte_flow.rst | 89 ++++++++++++++++++++++++++++++++++++++
>  lib/librte_ether/rte_flow.h        | 57 ++++++++++++++++++++++++
>  2 files changed, 146 insertions(+)
> 
> diff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst
> index aa5c818..6628964 100644
> --- a/doc/guides/prog_guide/rte_flow.rst
> +++ b/doc/guides/prog_guide/rte_flow.rst
> @@ -1508,6 +1508,95 @@ Representor.
>     | ``port_id``  | identification of the destination |
>     +--------------+-----------------------------------+
>  
> +Action: ``FILED_UPDATE``
> +^^^^^^^^^^^^^^^^^^^^^^^

FILED => FIELD

Underline is also shorter than title and might cause documentation warnings.

> +
> +Update specific field of the packet.
> +
> +- Non-terminating by default.

These statements are not needed since "ethdev: alter behavior of flow API
actions" [1].

[1] http://dpdk.org/ml/archives/dev/2018-April/096527.html

> +
> +.. _table_rte_flow_action_field_update:
> +
> +.. table:: FIELD_UPDATE
> +
> +   +-----------+---------------------------------------------------------+
> +   | Field     | Value                                                   |
> +   +===========+=========================================================+
> +   | ``item``  | item->type: specify the pattern to modify               |
> +   |           | item->spec: specify the new value to update             |
> +   |           | item->mask: specify which part of the pattern to update |
> +   |           | item->last: ignored                                     |

This table needs to be divided a bit more with one cell per field for better
clarity. See other pattern item definitions such as "Item: ``RAW``" for an
example.

> +   +-----------+---------------------------------------------------------+
> +   | ``layer`` | 0 means outermost matched pattern,                      |
> +   |           | 1 means next-to-outermost and so on ...                 |
> +   +-----------+---------------------------------------------------------+

What does "layer" refer to by the way? The layer described on the pattern
side of the flow rule, the actual protocol layer matched inside traffic, or
is "item" actually an END-terminated list of items (as suggested by
"pattern" in above documentation)?

I suspect the intent is for layer to have the same definition as RSS
encapulation level ("ethdev: add encap level to RSS flow API action" [2]),
and item points to a single item, correct?

In that case, it's misleading, please rename it "level". Also keep in mind
you can't make an action rely on anything found on the pattern side of a
flow rule.

What happens when this action is attempted on non-matching traffic must be
documented here as well. Refer to discussion re "ethdev: Add tunnel
encap/decap actions" [3]. To be on the safe side, it must be documented as
resulting in undefined behavior.

Based the same thread, I also suggest here to define "last" as reserved and
therefore an error if set to anything other than NULL, however it might
prove useful, see below.

[2] http://dpdk.org/ml/archives/dev/2018-April/096531.html
[3] http://dpdk.org/ml/archives/dev/2018-April/096418.html

> +
> +Action: ``FILED_INCREMENT``
> +^^^^^^^^^^^^^^^^^^^^^^^^^^^

FILED => FIELD

> +
> +Increment 1 on specific field of the packet.

All right, but what for? FIELD_UPDATE overwrites a specific value at some
specific place after matching something rather specific.

In my opinion to get predictable results with FIELD_INCREMENT, applications
also need to have a pretty good idea of what's about to be incremented.
That's because you can't put conditionals in flow rules (yet). So if you
need to match an exact IPv4 address in order to increment it, why wouldn't
you just provide its replacement directly?

I'm not saying there are no use cases for this, but you know, a couple of
real world example scenarios can't hurt. This should answer what an
application could possibly want to unconditionally increment in
ingress/egress traffic and for what purpose.

> +
> +- Non-terminating by default.

Same comment as in FIELD_UPDATE.

> +
> +.. _table_rte_flow_action_field_update:
> +
> +.. table:: FIELD_INCREMENT
> +
> +   +-----------+---------------------------------------------------------+
> +   | Field     | Value                                                   |
> +   +===========+=========================================================+
> +   | ``item``  | item->type: specify the pattern to modify               |
> +   |           | item->spec: ignored                                     |
> +   |           | item->mask: specify which part of the pattern to update |
> +   |           | item->last: ignored                                     |
> +   +-----------+---------------------------------------------------------+
> +   | ``layer`` | 0 means outermost matched pattern,                      |
> +   |           | 1 means next-to-outermost and so on ...                 |
> +   +-----------+---------------------------------------------------------+

Ditto.

With another comment regarding "last". When specified it could be used to
provide a stride, i.e. the amount to increment instead of 1 (increment =
last - spec).

> +
> +Action: ``FIELD_DECREMENT``
> +^^^^^^^^^^^^^^^^^^^^^^^^^^^
> +
> +Decrement 1 on specific field of the packet.

Same comment as in FIELD_INCREMENT.

> +
> +Paramenter is same is FIELD_INCREMENT.

Paramenter => Parameter

> +
> +-Non-terminating by default.

Same comment as in FIELD_UPDATE.

A table is missing in this section and must be included. Keep in mind
section titles are used as anchors in the documentation and readers may
reach this point without going through the previous sections.

> +
> +ACTION: ``FIELD_COPY``
> +^^^^^^^^^^^^^^^^^^^^^^
> +
> +Copy data of one field to another of the packet.
> +
> +-Non-terminating by default.

Same comment as in FIELD_UPDATE.

> +
> +.. _table_rte_flow_action_field_copy:
> +
> +.. table:: FIELD_COPY
> +
> +   +-----------------+-----------------------------------------------------------------+
> +   | Field           | Value                                                           |
> +   +=================+=================================================================+
> +   | ``src_item``    | src_item->type: match the pattern that data will be copy from   |
> +   |                 | src_item->spec: ignored                                         |
> +   |                 | src_item->mask: specify which part of the pattern to copy       |
> +   |                 | src_item->last: ignored                                         |
> +   +-----------------+-----------------------------------------------------------------+
> +   | ``src_layer``   | layer of src_item                                               |
> +   |                 | 0 means outermost matched pattern,                              |
> +   |                 | 1 means next-to-outermost and so on ...                         |
> +   +-----------------+-----------------------------------------------------------------+
> +   | ``dst_item``    | dst_item->type: match the pattern that data will be copy to     |
> +   |                 | dst_item->spec: ignored                                         |
> +   |                 | dst_item->mask: specify which part of the pattern to be update  |
> +   |                 |                 it must match src_item->mask.                   |
> +   |                 | dst_item->last: ignored                                         |
> +   +-----------------+-----------------------------------------------------------------+
> +   | ``dst_layer``   | layer of dst_item                                               |
> +   |                 | 0 means outermost matched pattern,                              |
> +   |                 | 1 means next-to-outermost and so on ...                         |
> +   +-----------------+-----------------------------------------------------------------+

Same comments as in FIELD_UPDATE regarding table format, "last", etc.

A couple of real world use cases would be a nice addition here as well.

> +
>  Negative types
>  ~~~~~~~~~~~~~~
>  
> diff --git a/lib/librte_ether/rte_flow.h b/lib/librte_ether/rte_flow.h
> index a8ec780..d81ac4c 100644
> --- a/lib/librte_ether/rte_flow.h
> +++ b/lib/librte_ether/rte_flow.h
> @@ -1178,6 +1178,34 @@ enum rte_flow_action_type {
>  	 * See struct rte_flow_action_port.
>  	 */
>  	RTE_FLOW_ACTION_TYPE_PORT,
> +
> +	/**
> +	 * Update specific field of the packet.

Update => Updates (to keep the style)

> +	 *
> +	 * See struct rte_flow_item_field_update.
> +	 */
> +	RTE_FLOW_ACTION_TYPE_FILED_UPDATE,

FILED => FIELD

> +
> +	/**
> +	 * Increment specific field of the packet.

Increment => Increments

> +	 *
> +	 * See struct rte_flow_item_field_update.
> +	 */
> +	RTE_FLOW_ACTION_TYPE_FIELD_INCREMENT,
> +
> +	/**
> +	 * Decrement specific field of the packet.

Decrement => Decrements

> +	 *
> +	 * See struct rte_flow_item_field_update.
> +	 */
> +	RTE_FLOW_ACTION_TYPE_FIELD_DECREMENT,
> +
> +	/**
> +	 * Copy data of one field to another of the packet.

Copy => Copies

> +	 *
> +	 * See struct rte_flow_item_type_field_copy.
> +	 */
> +	RTE_FLOW_ACTION_TYPE_FIELD_COPY,
>  };
>  
>  /**
> @@ -1327,6 +1355,35 @@ struct rte_flow_action_port {
>  	uint16_t port_id; /**< identification of the forward destination. */
>  };
>  
> +/** RTE_FLOW_ACTION_TYPE_FIELD_UPDATE

Here "/**" should be on its own line like the rest of the file. You can
safely ignore checkpatch nonsense (if any).

> + *  RTE_FLOW_ACTION_TYPE_FIELD_INCREMENT
> + *  RTE_FLOW_ACTION_TYPE_FIELD_DECREMENT

One shared structure for everything? How about a single UPDATE action to
cover everything instead?

- mask && last is NULL or last - spec is 0 => update
- mask && last - spec is positive => increment by that amount
- mask && last - spec is negative => decrement by that amount

This would be easier to document, would result in a smaller patch,
implicitly gives meaning to "last" and provides the ability to
simultaneously increment, decrement and update several fields at once.

> + *
> + * Update specific field of the packet.
> + *
> + * Typical usage: update mac/ip address.

Documentation is a bit weak and needs improvement. In any case, except for
tables and examples, whatever is written in this comment should be word for
word the same as what is written in rte_flow.rst.

> + */
> +struct rte_flow_action_field_update {
> +	const struct rte_flow_item *item; /**< specify the data to modify. */

Since there is a single item that contains its own pointers to
spec/last/mask, "item" shouldn't be a pointer. It's unnecessary and
misleading.

Documentation needs improvement.

> +	uint8_t layer;
> +	/**< 0 means outermost matched pattern, 1 means next-to-outermost... */

uint8_t layer => uint32_t level (we're not constrained by space)

Ditto re documentation. See RSS encap level patch [2] for ideas.

> +};
> +
> +/** RTE_FLOW_ACTION_TYPE_FIELD_COPY

Ditto for "/**".

> + *
> + * Copy data from one field to another of the packet.
> + *
> + * Typical usage: TTL copy-in / copy-out

This typical usage doesn't look that obvious to me. Copy TTL from what part
of the packet to where? What happens to the overwritten TTL value? Why
should they be synchronized?

> + */
> +struct rte_flow_action_field_copy {
> +	const struct rte_flow_item *src_item; /**< Specify the data copy from */
> +	uint8_t src_layer;
> +	/**< 0 means outermost matched pattern, 1 means next-to-outermost... */
> +	const struct rte_flow_item *dst_item; /**< Specify the data copy to */
> +	uint8_t dst_layer;
> +	/**< 0 means outermost matched pattern, 1 means next-to-outermost... */
> +};

Same comments as for struct rte_flow_action_field_update.

> +
>  /**
>   * Definition of a single action.
>   *
> -- 
> 2.7.4
> 

-- 
Adrien Mazarguil
6WIND

^ permalink raw reply	[flat|nested] 61+ messages in thread

* Re: [dpdk-dev] [PATCH v2 4/4] ether: add packet modification aciton in flow API
  2018-04-12  7:03     ` Adrien Mazarguil
@ 2018-04-12  8:50       ` Zhang, Qi Z
  2018-04-12 10:22         ` Adrien Mazarguil
  0 siblings, 1 reply; 61+ messages in thread
From: Zhang, Qi Z @ 2018-04-12  8:50 UTC (permalink / raw)
  To: Adrien Mazarguil
  Cc: dev, Doherty, Declan, Chandran, Sugesh, Glynn, Michael J, Liu,
	Yu Y, Ananyev, Konstantin, Richardson, Bruce

Hi Adrien

> -----Original Message-----
> From: Adrien Mazarguil [mailto:adrien.mazarguil@6wind.com]
> Sent: Thursday, April 12, 2018 3:04 PM
> To: Zhang, Qi Z <qi.z.zhang@intel.com>
> Cc: dev@dpdk.org; Doherty, Declan <declan.doherty@intel.com>; Chandran,
> Sugesh <sugesh.chandran@intel.com>; Glynn, Michael J
> <michael.j.glynn@intel.com>; Liu, Yu Y <yu.y.liu@intel.com>; Ananyev,
> Konstantin <konstantin.ananyev@intel.com>; Richardson, Bruce
> <bruce.richardson@intel.com>
> Subject: Re: [PATCH v2 4/4] ether: add packet modification aciton in flow API
> 
> On Sun, Apr 01, 2018 at 05:19:22PM -0400, Qi Zhang wrote:
> > Add new actions that be used to modify packet content with generic
> > semantic:
> >
> > RTE_FLOW_ACTION_TYPE_FIELD_UPDATE:
> > 	- update specific field of packet
> > RTE_FLWO_ACTION_TYPE_FIELD_INCREMENT:
> > 	- increament specific field of packet
> > RTE_FLWO_ACTION_TYPE_FIELD_DECREMENT:
> > 	- decreament specific field of packet
> > RTE_FLWO_ACTION_TYPE_FIELD_COPY:
> > 	- copy data from one field to another in packet.
> >
> > All action use struct rte_flow_item parameter to match the pattern
> > that going to be modified, if no pattern match, the action just be
> > skipped.
> 
> That's not good. It must result in undefined behavior, more about that below.

I may not get your point, see my below comment.

> 
> > These action are non-terminating action. they will not impact the fate
> > of the packets.
> >
> > Signed-off-by: Qi Zhang <qi.z.zhang@intel.com>
> 
> Noticed a few typos above and in subject line ("aciton", "FLWO", "increament",
> "decreament").
> 
> Note that I'm usually against using rte_flow_item structures and associated
> enum values inside action lists because it could be seen as inconsistent from
> an API standpoint. On the other hand, reusing existing types is a good thing so
> let's go with that for now.
> 
> Please see inline comments.
> 
> > ---
> >  doc/guides/prog_guide/rte_flow.rst | 89
> ++++++++++++++++++++++++++++++++++++++
> >  lib/librte_ether/rte_flow.h        | 57 ++++++++++++++++++++++++
> >  2 files changed, 146 insertions(+)
> >
> > diff --git a/doc/guides/prog_guide/rte_flow.rst
> > b/doc/guides/prog_guide/rte_flow.rst
> > index aa5c818..6628964 100644
> > --- a/doc/guides/prog_guide/rte_flow.rst
> > +++ b/doc/guides/prog_guide/rte_flow.rst
> > @@ -1508,6 +1508,95 @@ Representor.
> >     | ``port_id``  | identification of the destination |
> >     +--------------+-----------------------------------+
> >
> > +Action: ``FILED_UPDATE``
> > +^^^^^^^^^^^^^^^^^^^^^^^
> 
> FILED => FIELD
> 
> Underline is also shorter than title and might cause documentation warnings.
> 
> > +
> > +Update specific field of the packet.
> > +
> > +- Non-terminating by default.
> 
> These statements are not needed since "ethdev: alter behavior of flow API
> actions" [1].
> 
> [1] http://dpdk.org/ml/archives/dev/2018-April/096527.html
> 
> > +
> > +.. _table_rte_flow_action_field_update:
> > +
> > +.. table:: FIELD_UPDATE
> > +
> > +   +-----------+---------------------------------------------------------+
> > +   | Field     | Value
> |
> > +
> +===========+====================================================
> =====+
> > +   | ``item``  | item->type: specify the pattern to modify
> |
> > +   |           | item->spec: specify the new value to update
> |
> > +   |           | item->mask: specify which part of the pattern to update
> |
> > +   |           | item->last: ignored
> |
> 
> This table needs to be divided a bit more with one cell per field for better
> clarity. See other pattern item definitions such as "Item: ``RAW``" for an
> example.
> 
> > +   +-----------+---------------------------------------------------------+
> > +   | ``layer`` | 0 means outermost matched pattern,
> |
> > +   |           | 1 means next-to-outermost and so on ...
> |
> > +
> > + +-----------+-------------------------------------------------------
> > + --+
> 
> What does "layer" refer to by the way? The layer described on the pattern side
> of the flow rule, the actual protocol layer matched inside traffic, or is "item"
> actually an END-terminated list of items (as suggested by "pattern" in above
> documentation)?
> 
> I suspect the intent is for layer to have the same definition as RSS encapulation
> level ("ethdev: add encap level to RSS flow API action" [2]), and item points to
> a single item, correct?

Yes
> 
> In that case, it's misleading, please rename it "level". Also keep in mind you
> can't make an action rely on anything found on the pattern side of a flow rule.
> 
OK, "Level" looks better.
Also I may not get your point here. please correct me, 
My understanding is, all the modification action of a flow is independent of patterns of the same flow, 
For example when define a flow with pattern = eth/ipv4 and with a TCP modification action.
all ipv4 packets will hit that flow, and go to the same destination, but only TCP packet will be modified
otherwise, the action is just skipped,

> What happens when this action is attempted on non-matching traffic must be
> documented here as well. Refer to discussion re "ethdev: Add tunnel
> encap/decap actions" [3]. To be on the safe side, it must be documented as
> resulting in undefined behavior.

so what is "undefined behavior" you means?
The rule is:
If a packet matched pattern in action, it will be modified, otherwise the action just take no effect
is this idea acceptable?

> 
> Based the same thread, I also suggest here to define "last" as reserved and
> therefore an error if set to anything other than NULL, however it might prove
> useful, see below.
> 
> [2] http://dpdk.org/ml/archives/dev/2018-April/096531.html
> [3] http://dpdk.org/ml/archives/dev/2018-April/096418.html
> 
> > +
> > +Action: ``FILED_INCREMENT``
> > +^^^^^^^^^^^^^^^^^^^^^^^^^^^
> 
> FILED => FIELD
> 
> > +
> > +Increment 1 on specific field of the packet.
> 
> All right, but what for? FIELD_UPDATE overwrites a specific value at some
> specific place after matching something rather specific.
> 
> In my opinion to get predictable results with FIELD_INCREMENT, applications
> also need to have a pretty good idea of what's about to be incremented.
> That's because you can't put conditionals in flow rules (yet). So if you need to
> match an exact IPv4 address in order to increment it, why wouldn't you just
> provide its replacement directly?

The typical usage is for TTL or similar count that are not be matched in flow pattern. 

> 
> I'm not saying there are no use cases for this, but you know, a couple of real
> world example scenarios can't hurt. This should answer what an application
> could possibly want to unconditionally increment in ingress/egress traffic and
> for what purpose.

> 
> > +
> > +- Non-terminating by default.
> 
> Same comment as in FIELD_UPDATE.
> 
> > +
> > +.. _table_rte_flow_action_field_update:
> > +
> > +.. table:: FIELD_INCREMENT
> > +
> > +   +-----------+---------------------------------------------------------+
> > +   | Field     | Value
> |
> > +
> +===========+====================================================
> =====+
> > +   | ``item``  | item->type: specify the pattern to modify
> |
> > +   |           | item->spec: ignored
> |
> > +   |           | item->mask: specify which part of the pattern to update
> |
> > +   |           | item->last: ignored
> |
> > +   +-----------+---------------------------------------------------------+
> > +   | ``layer`` | 0 means outermost matched pattern,
> |
> > +   |           | 1 means next-to-outermost and so on ...
> |
> > +
> > + +-----------+-------------------------------------------------------
> > + --+
> 
> Ditto.
> 
> With another comment regarding "last". When specified it could be used to
> provide a stride, i.e. the amount to increment instead of 1 (increment = last -
> spec).

But the initial value is not predicable like TTL.

> 
> > +
> > +Action: ``FIELD_DECREMENT``
> > +^^^^^^^^^^^^^^^^^^^^^^^^^^^
> > +
> > +Decrement 1 on specific field of the packet.
> 
> Same comment as in FIELD_INCREMENT.
> 
> > +
> > +Paramenter is same is FIELD_INCREMENT.
> 
> Paramenter => Parameter
> 
> > +
> > +-Non-terminating by default.
> 
> Same comment as in FIELD_UPDATE.
> 
> A table is missing in this section and must be included. Keep in mind section
> titles are used as anchors in the documentation and readers may reach this
> point without going through the previous sections.
> 

OK, will add.

> > +
> > +ACTION: ``FIELD_COPY``
> > +^^^^^^^^^^^^^^^^^^^^^^
> > +
> > +Copy data of one field to another of the packet.
> > +
> > +-Non-terminating by default.
> 
> Same comment as in FIELD_UPDATE.
> 
> > +
> > +.. _table_rte_flow_action_field_copy:
> > +
> > +.. table:: FIELD_COPY
> > +
> > +   +-----------------+-----------------------------------------------------------------+
> > +   | Field           | Value
> |
> > +
> +=================+==============================================
> ===================+
> > +   | ``src_item``    | src_item->type: match the pattern that data will be
> copy from   |
> > +   |                 | src_item->spec: ignored
> |
> > +   |                 | src_item->mask: specify which part of the
> pattern to copy       |
> > +   |                 | src_item->last: ignored
> |
> > +   +-----------------+-----------------------------------------------------------------+
> > +   | ``src_layer``   | layer of src_item
> |
> > +   |                 | 0 means outermost matched pattern,
> |
> > +   |                 | 1 means next-to-outermost and so on ...
> |
> > +   +-----------------+-----------------------------------------------------------------+
> > +   | ``dst_item``    | dst_item->type: match the pattern that data will be
> copy to     |
> > +   |                 | dst_item->spec: ignored
> |
> > +   |                 | dst_item->mask: specify which part of the
> pattern to be update  |
> > +   |                 |                 it must match
> src_item->mask.                   |
> > +   |                 | dst_item->last: ignored
> |
> > +   +-----------------+-----------------------------------------------------------------+
> > +   | ``dst_layer``   | layer of dst_item
> |
> > +   |                 | 0 means outermost matched pattern,
> |
> > +   |                 | 1 means next-to-outermost and so on ...
> |
> > +
> > + +-----------------+-------------------------------------------------
> > + ----------------+
> 
> Same comments as in FIELD_UPDATE regarding table format, "last", etc.
> 
> A couple of real world use cases would be a nice addition here as well.
> 

For TTL copy-in/copy-out :)
Sorry, I should add typical usage in document also

> > +
> >  Negative types
> >  ~~~~~~~~~~~~~~
> >
> > diff --git a/lib/librte_ether/rte_flow.h b/lib/librte_ether/rte_flow.h
> > index a8ec780..d81ac4c 100644
> > --- a/lib/librte_ether/rte_flow.h
> > +++ b/lib/librte_ether/rte_flow.h
> > @@ -1178,6 +1178,34 @@ enum rte_flow_action_type {
> >  	 * See struct rte_flow_action_port.
> >  	 */
> >  	RTE_FLOW_ACTION_TYPE_PORT,
> > +
> > +	/**
> > +	 * Update specific field of the packet.
> 
> Update => Updates (to keep the style)
> 
> > +	 *
> > +	 * See struct rte_flow_item_field_update.
> > +	 */
> > +	RTE_FLOW_ACTION_TYPE_FILED_UPDATE,
> 
> FILED => FIELD
> 
> > +
> > +	/**
> > +	 * Increment specific field of the packet.
> 
> Increment => Increments
> 
> > +	 *
> > +	 * See struct rte_flow_item_field_update.
> > +	 */
> > +	RTE_FLOW_ACTION_TYPE_FIELD_INCREMENT,
> > +
> > +	/**
> > +	 * Decrement specific field of the packet.
> 
> Decrement => Decrements
> 
> > +	 *
> > +	 * See struct rte_flow_item_field_update.
> > +	 */
> > +	RTE_FLOW_ACTION_TYPE_FIELD_DECREMENT,
> > +
> > +	/**
> > +	 * Copy data of one field to another of the packet.
> 
> Copy => Copies
> 
> > +	 *
> > +	 * See struct rte_flow_item_type_field_copy.
> > +	 */
> > +	RTE_FLOW_ACTION_TYPE_FIELD_COPY,
> >  };
> >
> >  /**
> > @@ -1327,6 +1355,35 @@ struct rte_flow_action_port {
> >  	uint16_t port_id; /**< identification of the forward destination. */
> > };
> >
> > +/** RTE_FLOW_ACTION_TYPE_FIELD_UPDATE
> 
> Here "/**" should be on its own line like the rest of the file. You can safely
> ignore checkpatch nonsense (if any).
> 
> > + *  RTE_FLOW_ACTION_TYPE_FIELD_INCREMENT
> > + *  RTE_FLOW_ACTION_TYPE_FIELD_DECREMENT
> 
> One shared structure for everything? How about a single UPDATE action to
> cover everything instead?
> 
> - mask && last is NULL or last - spec is 0 => update
> - mask && last - spec is positive => increment by that amount
> - mask && last - spec is negative => decrement by that amount

So, only care about delta?, last=4 spec=3 is the same thing as last=34 spec=33?
It looks a little bit confuse to me. 

> 
> This would be easier to document, would result in a smaller patch, implicitly
> gives meaning to "last" and provides the ability to simultaneously increment,
> decrement and update several fields at once.
> 
> > + *
> > + * Update specific field of the packet.
> > + *
> > + * Typical usage: update mac/ip address.
> 
> Documentation is a bit weak and needs improvement. In any case, except for
> tables and examples, whatever is written in this comment should be word for
> word the same as what is written in rte_flow.rst.
> 
> > + */
> > +struct rte_flow_action_field_update {
> > +	const struct rte_flow_item *item; /**< specify the data to modify.
> > +*/
> 
> Since there is a single item that contains its own pointers to spec/last/mask,
> "item" shouldn't be a pointer. It's unnecessary and misleading.

OK, will change to structure.
> 
> Documentation needs improvement.
> 
> > +	uint8_t layer;
> > +	/**< 0 means outermost matched pattern, 1 means next-to-outermost...
> > +*/
> 
> uint8_t layer => uint32_t level (we're not constrained by space)
> 
> Ditto re documentation. See RSS encap level patch [2] for ideas.

Thanks for heads up, will check that.

> 
> > +};
> > +
> > +/** RTE_FLOW_ACTION_TYPE_FIELD_COPY
> 
> Ditto for "/**".
> 
> > + *
> > + * Copy data from one field to another of the packet.
> > + *
> > + * Typical usage: TTL copy-in / copy-out
> 
> This typical usage doesn't look that obvious to me. Copy TTL from what part of
> the packet to where? What happens to the overwritten TTL value? Why should
> they be synchronized?

I think this is standard flow action from OpenFlow, and it is supported by our hardware
This is the generic way we implemented, let me know if you have other better idea.

Thanks
Qi

> 
> > + */
> > +struct rte_flow_action_field_copy {
> > +	const struct rte_flow_item *src_item; /**< Specify the data copy from */
> > +	uint8_t src_layer;
> > +	/**< 0 means outermost matched pattern, 1 means next-to-outermost...
> */
> > +	const struct rte_flow_item *dst_item; /**< Specify the data copy to */
> > +	uint8_t dst_layer;
> > +	/**< 0 means outermost matched pattern, 1 means next-to-outermost...
> > +*/ };
> 
> Same comments as for struct rte_flow_action_field_update.
> 
> > +
> >  /**
> >   * Definition of a single action.
> >   *
> > --
> > 2.7.4
> >
> 
> --
> Adrien Mazarguil
> 6WIND

^ permalink raw reply	[flat|nested] 61+ messages in thread

* Re: [dpdk-dev] [PATCH v2 3/4] ether: add more protocol support in flow API
  2018-04-12  5:12       ` Zhang, Qi Z
@ 2018-04-12  9:19         ` Adrien Mazarguil
  2018-04-12 10:00           ` Zhang, Qi Z
  0 siblings, 1 reply; 61+ messages in thread
From: Adrien Mazarguil @ 2018-04-12  9:19 UTC (permalink / raw)
  To: Zhang, Qi Z
  Cc: dev, Doherty, Declan, Chandran, Sugesh, Glynn, Michael J, Liu,
	Yu Y, Ananyev, Konstantin, Richardson, Bruce

On Thu, Apr 12, 2018 at 05:12:08AM +0000, Zhang, Qi Z wrote:
> Hi Adrien:
> 
> 	Thank you so much for your careful review and helpful suggestions!
> 	I agree with most of your comments, except couple question about RTE_FLOW_ITEM_TYPE_TGT_ADDR and RTE_FLOW_ITEM_IPV6_EXT_HDR
> 	Please see my comment inline.
> 
> Thanks!
> Qi

Thanks, replying inline also.

> > -----Original Message-----
> > From: Adrien Mazarguil [mailto:adrien.mazarguil@6wind.com]
> > Sent: Thursday, April 12, 2018 12:32 AM
> > To: Zhang, Qi Z <qi.z.zhang@intel.com>
> > Cc: dev@dpdk.org; Doherty, Declan <declan.doherty@intel.com>; Chandran,
> > Sugesh <sugesh.chandran@intel.com>; Glynn, Michael J
> > <michael.j.glynn@intel.com>; Liu, Yu Y <yu.y.liu@intel.com>; Ananyev,
> > Konstantin <konstantin.ananyev@intel.com>; Richardson, Bruce
> > <bruce.richardson@intel.com>
> > Subject: Re: [PATCH v2 3/4] ether: add more protocol support in flow API
> > 
> > On Sun, Apr 01, 2018 at 05:19:21PM -0400, Qi Zhang wrote:
> > > Add new protocol header match support as below
> > >
> > > RTE_FLOW_ITEM_TYPE_ARP
> > > 	- match IPv4 ARP header
> > > RTE_FLOW_ITEM_TYPE_EXT_HDR_ANY
> > > 	- match any IPv6 extension header
> > 
> > While properly defined in the patch, "IPV6" is missing here.
> > 
> > > RTE_FLOW_ITEM_TYPE_ICMPV6
> > > 	- match IPv6 ICMP header
> > > RTE_FLOW_ITEM_TYPE_ICMPV6_TGT_ADDR
> > > 	- match IPv6 ICMP Target address
> > > RTE_FLOW_ITEM_TYPE_ICMPV6_SSL
> > > 	- match IPv6 ICMP Source Link-layer address
> > > RTE_FLOW_ITEM_TYPE_ICMPV6_TTL
> > > 	- match IPv6 ICMP Target Link-layer address
> > >
> > > Signed-off-by: Qi Zhang <qi.z.zhang@intel.com>
> > 
> > First, since they are added at the end of enum rte_flow_item_type, no ABI
> > breakage notice is necessary.
> > 
> > However testpmd implementation [1][2] and documentation update [3][4] are
> > mandatory for all new pattern items and actions.
> 
> OK, will add this into v2.
> 
> > 
> > More comments below regarding these definitions.
> > 
> > [1] flow_item[] in app/test-pmd/config.c [2] using ITEM_ICMP as an example
> > in app/test-pmd/cmdline_flow.c [3] "Pattern items" section in
> > doc/guides/testpmd_app_ug/testpmd_funcs.rst
> > [4] using "Item: ``ICMP``" section as an example in
> >     doc/guides/prog_guide/rte_flow.rst
> > 
> > > ---
> > >  lib/librte_ether/rte_flow.h | 160
> > > ++++++++++++++++++++++++++++++++++++++++++++
> > >  1 file changed, 160 insertions(+)
> > >
> > > diff --git a/lib/librte_ether/rte_flow.h b/lib/librte_ether/rte_flow.h
> > > index 8f75db0..a8ec780 100644
> > > --- a/lib/librte_ether/rte_flow.h
> > > +++ b/lib/librte_ether/rte_flow.h
> > > @@ -323,6 +323,49 @@ enum rte_flow_item_type {
> > >  	 * See struct rte_flow_item_geneve.
> > >  	 */
> > >  	RTE_FLOW_ITEM_TYPE_GENEVE,
> > > +
> > > +	/**
> > > +	 * Matches ARP IPv4 header.
> > 
> > => Matches an IPv4 ARP header.
> > 
> > > +	 *
> > > +	 * See struct rte_flow_item_arp.
> > > +	 */
> > > +	RTE_FLOW_ITEM_TYPE_ARP,
> > 
> > While you're right to make "IPv4" clear since ARP is also used for other
> > protocols DPDK doesn't support (and likely never will), the ARP header has
> > both a fixed and a variably-sized part.
> > 
> > Ideally an ARP pattern item should match the fixed part only and a separate
> > ARP_IPV4 match its payload, somewhat like you did for ICMPv6/NDP below.
> > 
> > Problem is that in DPDK, struct arp_hdr includes struct arp_ipv4, so one
> > suggestion would be to rename this pattern item ARP_IPV4 directly:
> > 
> > => RTE_FLOW_ITEM_TYPE_ARP_IPV4
> > 
> > > +
> > > +	/**
> > > +	 * Matches any IPv6 Extension header.
> > 
> > => Matches an IPv6 extension header.
> > 
> > > +	 *
> > > +	 * See struct rte_flow_item_ipv6_ext_any.
> > > +	 */
> > > +	RTE_FLOW_ITEM_TYPE_IPV6_EXT_HDR_ANY,
> > 
> > I'm not sure this definition is necessary, more below about that.
> > 
> > Also I don't see a benefit in having "ANY" part of the name, if you want to keep
> > it, I suggest the simpler:
> > 
> > => RTE_FLOW_ITEM_TYPE_IPV6_EXT
> > 
> > > +
> > > +	/**
> > > +	 * Matches ICMPv6 header.
> > 
> > => Matches an ICMPv6 header.
> > 
> > > +	 *
> > > +	 * See struct rte_flow_item_icmpv6
> > 
> > Missing "."
> > 
> > > +	 */
> > > +	RTE_FLOW_ITEM_TYPE_ICMPV6,
> > > +
> > 
> > Before entering NDP territory below, I understand those should be stacked on
> > top of RTE_FLOW_ITEM_TYPE_ICMPV6. It's fine but for clarity they should be
> > named after the NDP types they represent, not inner data fields.
> > 
> > Also I think we should consider NDP as a protocol sitting on top of ICMPv6. We
> > could therefore drop "ICMP" from these definitions.
> > 
> > Since "ND" is a common shorthand for this protocol and "6" another when
> > doing something related to IPv6, I suggest to use "ND6" to name he related
> > pattern items.
> 
> I agree.
> 
> > 
> > These are the reasons behind my next suggestions:
> > 
> > > +	/**
> > > +	 * Match ICMPv6 target address.
> > > +	 *
> > > +	 * See struct rte_flow_item_icmpv6_tgt_addr.
> > > +	 */
> > > +	RTE_FLOW_ITEM_TYPE_ICMPV6_TGT_ADDR,
> > 
> > => Matches an IPv6 network discovery router solicitation.
> > => See struct rte_flow_item_nd6_rs.
> > => RTE_FLOW_ITEM_TYPE_ND6_RS,

By the way, I wrote "router solicitation" (RS) here but it should have been
"neighbor solicitation" (NS) obviously.

> > 
> > You should add another item for neighbor advertisement messages using the
> > same template:
> > 
> > => Match an IPv6 network discovery neighbor advertisement.
> > => See struct rte_flow_item_nd6_na.
> > => RTE_FLOW_ITEM_TYPE_ND6_NA,
> 
> The purpose of RTE_FLOW_ITEM_TYPE_ICMPV6_TGT_ADDR is to match a "target address"
> according to IPv6 ND spec https://tools.ietf.org/html/rfc4861#page-22, when type = 135/136
> 
> so do you mean we should have RTE_FLOW_ITEM_TYPE_ND6_NS (Neighbor Solicitation)
>  and RTE_FLOW_ITEM_TYPE_ND6_NA (Neighbor Advertisement) here,
> and with the same template (an IPV6 addr) for rte_flow_item_icmpv6_tgt_addr?

The rationale is that while they share a similar format, they are in fact
different messages that applications could want to match more conveniently
than providing ICMP type/code values. It would be done for consistency given
the same RFC also defines router solicitation/advertisement messages.

However a problem remains since these messages are part of the ICMP format
whose "reserved" field sometimes contains message flags, particularly with
RA. These structures would lack that data.

Honestly your approach makes sense, but it shouldn't be possible to mix
target addresses with RA/RS and it should be convenient to match these
messages without specifically matching their contents.

So another suggestion would be to define new types at the ICMPv6 level to
use directly on top of ETH for each possible message and define separate
structures for options.

First let's drop one character here and in all other definitions in this
patch:

 ICMPV6 => ICMP6 

Then the new items would respectively be:

 RTE_FLOW_ITEM_TYPE_ICMP6
 RTE_FLOW_ITEM_TYPE_ICMP6_ND_NA
 RTE_FLOW_ITEM_TYPE_ICMP6_ND_NS
 RTE_FLOW_ITEM_TYPE_ICMP6_ND_OPT_SLA
 RTE_FLOW_ITEM_TYPE_ICMP6_ND_OPT_TLA

All the related structure definitions would include the ICMPv6 header part
defined according to the RFC and except for RTE_FLOW_ITEM_TYPE_ICMP6, a
default mask that excludes type/code since they are implicit:

 struct rte_flow_item_icmp6_nd_na {
      uint8_t type; /**< ICMPv6 type, normally 136. */
      uint8_t code; /**< ICMPv6 code, normally 0. */
      rte_be16_t checksum; /**< ICMPv6 checksum. */
      /**
       * Router flag (1b), solicited flag (1b), override flag (1b),
       * reserved (29b).
       */
      rte_be32_t rso_reserved;
      uint8_t target[16]; /**< Target address. */
 };

 static const struct rte_flow_item_icmp6_nd_na rte_flow_item_icmp6_nd_na_mask = {
     .target =
          "\xff\xff\xff\xff\xff\xff\xff\xff"
          "\xff\xff\xff\xff\xff\xff\xff\xff",
 };

Also notice how uint(16|32)_t were modified as rte_be(16|32)_t while there.

What's your opinion?

> 
> > 
> > The following are possible options for these headers, if specified they must be
> > found afterward. Also since IPv6 may run on top of protocols other than
> > Ethernet, you need to clarify these link-layer addresses use the Ethernet
> > format:
> > 
> > > +
> > > +	/**
> > > +	 * Match ICMPv6 Source Link-Layer Address.
> > > +	 *
> > > +	 * See struct rte_flow_item_icmpv6_sll.
> > > +	 */
> > > +	RTE_FLOW_ITEM_TYPE_ICMPV6_SLL,
> > 
> > => Matches an IPv6 network discovery source Ethernet link-layer address
> > option.
> > => See struct rte_flow_item_nd6_opt_sla_eth.
> > => RTE_FLOW_ITEM_TYPE_ND6_OPT_SLA_ETH,
> > 
> > > +
> > > +	/**
> > > +	 * Match ICMPv6 Target Link-Layer Address.
> > > +	 *
> > > +	 * See struct rte_flow_item_icmpv6_tll.
> > > +	 */
> > > +	RTE_FLOW_ITEM_TYPE_ICMPV6_TLL,
> > 
> > => Matches an IPv6 network discovery target Ethernet link-layer address
> > option.
> > => See struct rte_flow_item_nd6_opt_tla_eth.
> > => RTE_FLOW_ITEM_TYPE_ND6_OPT_TLA_ETH,
> > 
> 
> Agree to rename.
> 
> > > +
> > 
> > Unnecessary empty line.
> > 
> > >  };
> > >
> > >  /**
> > > @@ -815,6 +858,123 @@ static const struct rte_flow_item_geneve
> > > rte_flow_item_geneve_mask = {  #endif
> > >
> > >  /**
> > > + * RTE_FLOW_ITEM_TYPE_ARP
> > > + *
> > > + * Matches IPv4 ARP packet header
> > 
> > As above:
> > 
> > => Matches an IPv4 ARP header.
> > => RTE_FLOW_ITEM_TYPE_ARP_IPV4
> > 
> > > + */
> > > +struct rte_flow_item_arp {
> > > +	struct arp_hdr hdr;
> > > +};
> > 
> > Needs #include <rte_arp.h> and a Doxygen comment next to hdr for
> > consistency, see ICMP and other definitions.
> > 
> > > +
> > > +/** Default mask for RTE_FLOW_ITEM_TYPE_ARP. */ #ifndef __cplusplus
> > > +static const struct rte_flow_item_arp rte_flow_item_arp_mask = {
> > > +	.hdr = {
> > > +		.arp_data = {
> > > +			.arp_sha = {
> > > +				.addr_bytes = "\xff\xff\xff\xff\xff\xff",
> > > +			},
> > > +			.arp_sip = RTE_BE32(0xffffffff),
> > > +			.arp_tha = {
> > > +				.addr_bytes = "\xff\xff\xff\xff\xff\xff",
> > > +			},
> > > +			.arp_tip = RTE_BE32(0xffffffff),
> > > +		},
> > > +	},
> > > +};
> > > +#endif
> > > +
> > > +/**
> > > + * RTE_FLOW_ITEM_TYPE_IPV6_EXT_HDR_ANY
> > > + *
> > > + * Matches any IPv6 extension header.
> > > + */
> > > +struct rte_flow_item_ipv6_ext_hdr_any {
> > > +	uint8_t next_hdr;
> > > +};
> > 
> > So what's the point? next_hdr is already part of either struct ipv6_hdr
> > ("proto") and individual extension headers. Moreover it's implicit if an
> > extension header is provided in a pattern.
> > 
> > How about removing it?
> 
> We need this to match a packet that have extend header
> For example:
> IPV6(proto = 43, <Routing EH >) / EXT_HDR (next_head = 60 <Destination EH>) / EXT_HDR (next_head = 44, <Fragment EH)/ EXT_HDR (next_head = 6 <tcp>) / TCP ...
> 
> I use "ANY" to match any extend header regardless their content.
> There is no conflict if we can add multiple RTE_FLOW_ITEM_EXT_HDR_XXX in futures

I see, makes sense. How about doing like ICMPv6 above? Generic item uses
the base name and can only match the generic part specifically (next_hdr),
while specific items don't match the generic part but whatever additions
their dedicated structures define, i.e.:

 RTE_FLOW_ITEM_TYPE_IPV6_EXT
 RTE_FLOW_ITEM_TYPE_IPV6_EXT_HBH
 RTE_FLOW_ITEM_TYPE_IPV6_EXT_DEST
 RTE_FLOW_ITEM_TYPE_IPV6_EXT_RTHDR
 RTE_FLOW_ITEM_TYPE_IPV6_EXT_FRAG
 ...

No need to define them all if you only need EXT, this is just to describe
the idea (it's also OK if you want to define them while you're at it).

> 
> > 
> > > +
> > > +/** Default mask for RTE_FLOW_ITEM_TYPE_IPV6_EXT_HDR_ANY. */
> > #ifndef
> > > +__cplusplus static const struct rte_flow_item_ipv6_ext_hdr_any
> > > +rte_flow_item_ipv6_ext_any_mask = {
> > > +	.next_hdr = 0xff,
> > > +};
> > > +#endif
> > 
> > Ditto.
> > 
> > > +
> > > +/**
> > > + * RTE_FLOW_ITEM_TYPE_ICMPV6
> > > + *
> > > + * Matches ICMPv6 header.
> > 
> > => Matches an ICMPv6 header.
> > 
> > > + */
> > > +struct rte_flow_item_icmpv6 {
> > > +	uint8_t type;
> > > +	uint8_t code;
> > > +	uint16_t checksum;
> > 
> > The last 32-bit "reserved" data field is missing.
> > 
> > > +};
> > 
> > Too bad there is no struct icmp6_hdr definition in rte_icmp.h. You could add it.
> > In any case Doxygen comments are missing, please add them (see other
> > structure definitions for examples).

No need to rely on an external definition due to the above suggestions by
the way.

> > 
> > > +
> > > +/** Default mask for RTE_FLOW_ITEM_TYPE_ICMPV6 */
> > 
> > Missing "."
> > 
> > > +#ifndef __cplusplus
> > > +static const struct rte_flow_item_icmpv6 rte_flow_item_icmpv6_mask = {
> > > +	.type = 0xff,
> > > +	.code = 0xff,
> > > +	.checksum = RTE_BE16(0xffff),
> > > +};
> > > +#endif
> > 
> > You must remove checksum matching from the default mask. That's the last
> > thing an application might want to match exactly :)
> > 
> > > +
> > > +/**
> > > + * RTE_FLOW_ITEM_TYPE_ICMPV6_TGT_ADDR
> > > + *
> > > + * Matches ICMPv6's Target Address.
> > > + */
> > > +struct rte_flow_item_icmpv6_tgt_addr {
> > > +	uint8_t addr[16];
> > > +};
> > 
> > You need to expand this as two items, see prior comments regarding
> > RTE_FLOW_ITEM_TYPE_ND6_RS, RTE_FLOW_ITEM_TYPE_ND6_NA and their
> > respective structs rte_flow_item_nd6_rs and rte_flow_item_nd6_na.
> > 
> > Also Doxygen documentation is missing for the addr field and you need to
> > describe that these are only valid when used after
> > RTE_FLOW_ITEM_TYPE_ICMPV6.
> > 
> > > +
> > > +/** Default mask for RTE_FLOW_ITEM_TYPE_ICMPV6_TGT_ADDR */
> > 
> > Missing "."
> > 
> > > +#ifndef __cplusplus
> > > +static const
> > > +struct rte_flow_item_icmpv6_tgt_addr
> > rte_flow_item_icmpv6_tgt_addr_mask = {
> > > +	.addr =
> > > +		"\xff\xff\xff\xff\xff\xff\xff\xff"
> > > +		"\xff\xff\xff\xff\xff\xff\xff\xff",
> > > +};
> > > +#endif
> > > +
> > > +/**
> > > + * RTE_FLOW_ITEM_TYPE_ICPMV6_SLL.
> > > + *
> > > + * Matches ICMPv6 Source Link-Layer address.
> > > + */
> > > +struct rte_flow_item_icmpv6_sll {
> > > +	struct ether_addr addr;
> > > +};
> > 
> > See prior comments regarding RTE_FLOW_ITEM_TYPE_ND6_OPT_SLA_ETH and
> > struct rte_flow_item_type_nd6_opt_sla_eth.
> > 
> > Also Doxygen documentation is missing for the addr field and you need to
> > describe that it is only valid when found after either
> > RTE_FLOW_ITEM_TYPE_ND6_RS or RTE_FLOW_ITEM_TYPE_ND6_NA.
> > 
> > Also missing empty line here.
> > 
> > > +/** Default mask for RTE_FLOW_ITEM_TYPE_ICMPV6_SLL */
> > 
> > Missing "."
> > 
> > > +#ifndef __cplusplus
> > > +static const struct rte_flow_item_icmpv6_sll
> > rte_flow_item_icmpv6_sll_mask = {
> > > +	.addr = {
> > > +		.addr_bytes = "\xff\xff\xff\xff\xff\xff",
> > > +	}
> > > +};
> > > +#endif
> > > +
> > > +/**
> > > + * RTE_FLOW_ITEM_TYPE_ICMPV6_TLL.
> > > + *
> > > + * Matches ICMPv6 Target Link-Layer address.
> > > + */
> > > +struct rte_flow_item_icmpv6_tll {
> > > +	struct ether_addr addr;
> > > +};
> > 
> > See prior comments regarding RTE_FLOW_ITEM_TYPE_ND6_OPT_TLA_ETH
> > and struct rte_flow_item_type_nd6_opt_tla_eth.
> > 
> > Also Doxygen documentation is missing for the addr field and you need to
> > describe that it is only valid when found after either
> > RTE_FLOW_ITEM_TYPE_ND6_RS or RTE_FLOW_ITEM_TYPE_ND6_NA.
> > 
> > Also missing empty line here.
> > 
> > > +/** Default mask for RTE_FLOW_ITEM_TYPE_ICMPV6_TLL */
> > 
> > Missing "."
> > 
> > > +#ifndef __cplusplus
> > > +static const struct rte_flow_item_icmpv6_tll
> > rte_flow_item_icmpv6_tll_mask = {
> > > +	.addr = {
> > > +		.addr_bytes = "\xff\xff\xff\xff\xff\xff",
> > > +	}
> > > +};
> > > +#endif
> > > +
> > > +/**
> > >   * Matching pattern item definition.
> > >   *
> > >   * A pattern is formed by stacking items starting from the lowest
> > > protocol
> > > --
> > > 2.7.4
> > >

-- 
Adrien Mazarguil
6WIND

^ permalink raw reply	[flat|nested] 61+ messages in thread

* Re: [dpdk-dev] [PATCH v2 3/4] ether: add more protocol support in flow API
  2018-04-12  9:19         ` Adrien Mazarguil
@ 2018-04-12 10:00           ` Zhang, Qi Z
  0 siblings, 0 replies; 61+ messages in thread
From: Zhang, Qi Z @ 2018-04-12 10:00 UTC (permalink / raw)
  To: Adrien Mazarguil
  Cc: dev, Doherty, Declan, Chandran, Sugesh, Glynn, Michael J, Liu,
	Yu Y, Ananyev, Konstantin, Richardson, Bruce



> -----Original Message-----
> From: Adrien Mazarguil [mailto:adrien.mazarguil@6wind.com]
> Sent: Thursday, April 12, 2018 5:20 PM
> To: Zhang, Qi Z <qi.z.zhang@intel.com>
> Cc: dev@dpdk.org; Doherty, Declan <declan.doherty@intel.com>; Chandran,
> Sugesh <sugesh.chandran@intel.com>; Glynn, Michael J
> <michael.j.glynn@intel.com>; Liu, Yu Y <yu.y.liu@intel.com>; Ananyev,
> Konstantin <konstantin.ananyev@intel.com>; Richardson, Bruce
> <bruce.richardson@intel.com>
> Subject: Re: [PATCH v2 3/4] ether: add more protocol support in flow API
> 
> On Thu, Apr 12, 2018 at 05:12:08AM +0000, Zhang, Qi Z wrote:
> > Hi Adrien:
> >
> > 	Thank you so much for your careful review and helpful suggestions!
> > 	I agree with most of your comments, except couple question about
> RTE_FLOW_ITEM_TYPE_TGT_ADDR and RTE_FLOW_ITEM_IPV6_EXT_HDR
> > 	Please see my comment inline.
> >
> > Thanks!
> > Qi
> 
> Thanks, replying inline also.
> 
> > > -----Original Message-----
> > > From: Adrien Mazarguil [mailto:adrien.mazarguil@6wind.com]
> > > Sent: Thursday, April 12, 2018 12:32 AM
> > > To: Zhang, Qi Z <qi.z.zhang@intel.com>
> > > Cc: dev@dpdk.org; Doherty, Declan <declan.doherty@intel.com>;
> > > Chandran, Sugesh <sugesh.chandran@intel.com>; Glynn, Michael J
> > > <michael.j.glynn@intel.com>; Liu, Yu Y <yu.y.liu@intel.com>;
> > > Ananyev, Konstantin <konstantin.ananyev@intel.com>; Richardson,
> > > Bruce <bruce.richardson@intel.com>
> > > Subject: Re: [PATCH v2 3/4] ether: add more protocol support in flow
> > > API
> > >
> > > On Sun, Apr 01, 2018 at 05:19:21PM -0400, Qi Zhang wrote:
> > > > Add new protocol header match support as below
> > > >
> > > > RTE_FLOW_ITEM_TYPE_ARP
> > > > 	- match IPv4 ARP header
> > > > RTE_FLOW_ITEM_TYPE_EXT_HDR_ANY
> > > > 	- match any IPv6 extension header
> > >
> > > While properly defined in the patch, "IPV6" is missing here.
> > >
> > > > RTE_FLOW_ITEM_TYPE_ICMPV6
> > > > 	- match IPv6 ICMP header
> > > > RTE_FLOW_ITEM_TYPE_ICMPV6_TGT_ADDR
> > > > 	- match IPv6 ICMP Target address
> > > > RTE_FLOW_ITEM_TYPE_ICMPV6_SSL
> > > > 	- match IPv6 ICMP Source Link-layer address
> > > > RTE_FLOW_ITEM_TYPE_ICMPV6_TTL
> > > > 	- match IPv6 ICMP Target Link-layer address
> > > >
> > > > Signed-off-by: Qi Zhang <qi.z.zhang@intel.com>
> > >
> > > First, since they are added at the end of enum rte_flow_item_type,
> > > no ABI breakage notice is necessary.
> > >
> > > However testpmd implementation [1][2] and documentation update
> > > [3][4] are mandatory for all new pattern items and actions.
> >
> > OK, will add this into v2.
> >
> > >
> > > More comments below regarding these definitions.
> > >
> > > [1] flow_item[] in app/test-pmd/config.c [2] using ITEM_ICMP as an
> > > example in app/test-pmd/cmdline_flow.c [3] "Pattern items" section
> > > in doc/guides/testpmd_app_ug/testpmd_funcs.rst
> > > [4] using "Item: ``ICMP``" section as an example in
> > >     doc/guides/prog_guide/rte_flow.rst
> > >
> > > > ---
> > > >  lib/librte_ether/rte_flow.h | 160
> > > > ++++++++++++++++++++++++++++++++++++++++++++
> > > >  1 file changed, 160 insertions(+)
> > > >
> > > > diff --git a/lib/librte_ether/rte_flow.h
> > > > b/lib/librte_ether/rte_flow.h index 8f75db0..a8ec780 100644
> > > > --- a/lib/librte_ether/rte_flow.h
> > > > +++ b/lib/librte_ether/rte_flow.h
> > > > @@ -323,6 +323,49 @@ enum rte_flow_item_type {
> > > >  	 * See struct rte_flow_item_geneve.
> > > >  	 */
> > > >  	RTE_FLOW_ITEM_TYPE_GENEVE,
> > > > +
> > > > +	/**
> > > > +	 * Matches ARP IPv4 header.
> > >
> > > => Matches an IPv4 ARP header.
> > >
> > > > +	 *
> > > > +	 * See struct rte_flow_item_arp.
> > > > +	 */
> > > > +	RTE_FLOW_ITEM_TYPE_ARP,
> > >
> > > While you're right to make "IPv4" clear since ARP is also used for
> > > other protocols DPDK doesn't support (and likely never will), the
> > > ARP header has both a fixed and a variably-sized part.
> > >
> > > Ideally an ARP pattern item should match the fixed part only and a
> > > separate
> > > ARP_IPV4 match its payload, somewhat like you did for ICMPv6/NDP
> below.
> > >
> > > Problem is that in DPDK, struct arp_hdr includes struct arp_ipv4, so
> > > one suggestion would be to rename this pattern item ARP_IPV4 directly:
> > >
> > > => RTE_FLOW_ITEM_TYPE_ARP_IPV4
> > >
> > > > +
> > > > +	/**
> > > > +	 * Matches any IPv6 Extension header.
> > >
> > > => Matches an IPv6 extension header.
> > >
> > > > +	 *
> > > > +	 * See struct rte_flow_item_ipv6_ext_any.
> > > > +	 */
> > > > +	RTE_FLOW_ITEM_TYPE_IPV6_EXT_HDR_ANY,
> > >
> > > I'm not sure this definition is necessary, more below about that.
> > >
> > > Also I don't see a benefit in having "ANY" part of the name, if you
> > > want to keep it, I suggest the simpler:
> > >
> > > => RTE_FLOW_ITEM_TYPE_IPV6_EXT
> > >
> > > > +
> > > > +	/**
> > > > +	 * Matches ICMPv6 header.
> > >
> > > => Matches an ICMPv6 header.
> > >
> > > > +	 *
> > > > +	 * See struct rte_flow_item_icmpv6
> > >
> > > Missing "."
> > >
> > > > +	 */
> > > > +	RTE_FLOW_ITEM_TYPE_ICMPV6,
> > > > +
> > >
> > > Before entering NDP territory below, I understand those should be
> > > stacked on top of RTE_FLOW_ITEM_TYPE_ICMPV6. It's fine but for
> > > clarity they should be named after the NDP types they represent, not inner
> data fields.
> > >
> > > Also I think we should consider NDP as a protocol sitting on top of
> > > ICMPv6. We could therefore drop "ICMP" from these definitions.
> > >
> > > Since "ND" is a common shorthand for this protocol and "6" another
> > > when doing something related to IPv6, I suggest to use "ND6" to name
> > > he related pattern items.
> >
> > I agree.
> >
> > >
> > > These are the reasons behind my next suggestions:
> > >
> > > > +	/**
> > > > +	 * Match ICMPv6 target address.
> > > > +	 *
> > > > +	 * See struct rte_flow_item_icmpv6_tgt_addr.
> > > > +	 */
> > > > +	RTE_FLOW_ITEM_TYPE_ICMPV6_TGT_ADDR,
> > >
> > > => Matches an IPv6 network discovery router solicitation.
> > > => See struct rte_flow_item_nd6_rs.
> > > => RTE_FLOW_ITEM_TYPE_ND6_RS,
> 
> By the way, I wrote "router solicitation" (RS) here but it should have been
> "neighbor solicitation" (NS) obviously.
> 
> > >
> > > You should add another item for neighbor advertisement messages
> > > using the same template:
> > >
> > > => Match an IPv6 network discovery neighbor advertisement.
> > > => See struct rte_flow_item_nd6_na.
> > > => RTE_FLOW_ITEM_TYPE_ND6_NA,
> >
> > The purpose of RTE_FLOW_ITEM_TYPE_ICMPV6_TGT_ADDR is to match a
> "target address"
> > according to IPv6 ND spec https://tools.ietf.org/html/rfc4861#page-22,
> > when type = 135/136
> >
> > so do you mean we should have RTE_FLOW_ITEM_TYPE_ND6_NS (Neighbor
> > Solicitation)  and RTE_FLOW_ITEM_TYPE_ND6_NA (Neighbor
> Advertisement)
> > here, and with the same template (an IPV6 addr) for
> rte_flow_item_icmpv6_tgt_addr?
> 
> The rationale is that while they share a similar format, they are in fact different
> messages that applications could want to match more conveniently than
> providing ICMP type/code values. It would be done for consistency given the
> same RFC also defines router solicitation/advertisement messages.
> 
> However a problem remains since these messages are part of the ICMP format
> whose "reserved" field sometimes contains message flags, particularly with RA.
> These structures would lack that data.
> 
> Honestly your approach makes sense, but it shouldn't be possible to mix target
> addresses with RA/RS and it should be convenient to match these messages
> without specifically matching their contents.
> 
> So another suggestion would be to define new types at the ICMPv6 level to use
> directly on top of ETH for each possible message and define separate
> structures for options.
> 
> First let's drop one character here and in all other definitions in this
> patch:
> 
>  ICMPV6 => ICMP6
> 
> Then the new items would respectively be:
> 
>  RTE_FLOW_ITEM_TYPE_ICMP6
>  RTE_FLOW_ITEM_TYPE_ICMP6_ND_NA
>  RTE_FLOW_ITEM_TYPE_ICMP6_ND_NS
>  RTE_FLOW_ITEM_TYPE_ICMP6_ND_OPT_SLA
>  RTE_FLOW_ITEM_TYPE_ICMP6_ND_OPT_TLA
> 
> All the related structure definitions would include the ICMPv6 header part
> defined according to the RFC and except for RTE_FLOW_ITEM_TYPE_ICMP6, a
> default mask that excludes type/code since they are implicit:
> 
>  struct rte_flow_item_icmp6_nd_na {
>       uint8_t type; /**< ICMPv6 type, normally 136. */
>       uint8_t code; /**< ICMPv6 code, normally 0. */
>       rte_be16_t checksum; /**< ICMPv6 checksum. */
>       /**
>        * Router flag (1b), solicited flag (1b), override flag (1b),
>        * reserved (29b).
>        */
>       rte_be32_t rso_reserved;
>       uint8_t target[16]; /**< Target address. */  };
> 
>  static const struct rte_flow_item_icmp6_nd_na
> rte_flow_item_icmp6_nd_na_mask = {
>      .target =
>           "\xff\xff\xff\xff\xff\xff\xff\xff"
>           "\xff\xff\xff\xff\xff\xff\xff\xff",
>  };
> 
> Also notice how uint(16|32)_t were modified as rte_be(16|32)_t while there.
> 
> What's your opinion?

OK, I will take this method, it looks good, thanks 

> 
> >
> > >
> > > The following are possible options for these headers, if specified
> > > they must be found afterward. Also since IPv6 may run on top of
> > > protocols other than Ethernet, you need to clarify these link-layer
> > > addresses use the Ethernet
> > > format:
> > >
> > > > +
> > > > +	/**
> > > > +	 * Match ICMPv6 Source Link-Layer Address.
> > > > +	 *
> > > > +	 * See struct rte_flow_item_icmpv6_sll.
> > > > +	 */
> > > > +	RTE_FLOW_ITEM_TYPE_ICMPV6_SLL,
> > >
> > > => Matches an IPv6 network discovery source Ethernet link-layer
> > > address option.
> > > => See struct rte_flow_item_nd6_opt_sla_eth.
> > > => RTE_FLOW_ITEM_TYPE_ND6_OPT_SLA_ETH,
> > >
> > > > +
> > > > +	/**
> > > > +	 * Match ICMPv6 Target Link-Layer Address.
> > > > +	 *
> > > > +	 * See struct rte_flow_item_icmpv6_tll.
> > > > +	 */
> > > > +	RTE_FLOW_ITEM_TYPE_ICMPV6_TLL,
> > >
> > > => Matches an IPv6 network discovery target Ethernet link-layer
> > > address option.
> > > => See struct rte_flow_item_nd6_opt_tla_eth.
> > > => RTE_FLOW_ITEM_TYPE_ND6_OPT_TLA_ETH,
> > >
> >
> > Agree to rename.
> >
> > > > +
> > >
> > > Unnecessary empty line.
> > >
> > > >  };
> > > >
> > > >  /**
> > > > @@ -815,6 +858,123 @@ static const struct rte_flow_item_geneve
> > > > rte_flow_item_geneve_mask = {  #endif
> > > >
> > > >  /**
> > > > + * RTE_FLOW_ITEM_TYPE_ARP
> > > > + *
> > > > + * Matches IPv4 ARP packet header
> > >
> > > As above:
> > >
> > > => Matches an IPv4 ARP header.
> > > => RTE_FLOW_ITEM_TYPE_ARP_IPV4
> > >
> > > > + */
> > > > +struct rte_flow_item_arp {
> > > > +	struct arp_hdr hdr;
> > > > +};
> > >
> > > Needs #include <rte_arp.h> and a Doxygen comment next to hdr for
> > > consistency, see ICMP and other definitions.
> > >
> > > > +
> > > > +/** Default mask for RTE_FLOW_ITEM_TYPE_ARP. */ #ifndef
> > > > +__cplusplus static const struct rte_flow_item_arp
> rte_flow_item_arp_mask = {
> > > > +	.hdr = {
> > > > +		.arp_data = {
> > > > +			.arp_sha = {
> > > > +				.addr_bytes = "\xff\xff\xff\xff\xff\xff",
> > > > +			},
> > > > +			.arp_sip = RTE_BE32(0xffffffff),
> > > > +			.arp_tha = {
> > > > +				.addr_bytes = "\xff\xff\xff\xff\xff\xff",
> > > > +			},
> > > > +			.arp_tip = RTE_BE32(0xffffffff),
> > > > +		},
> > > > +	},
> > > > +};
> > > > +#endif
> > > > +
> > > > +/**
> > > > + * RTE_FLOW_ITEM_TYPE_IPV6_EXT_HDR_ANY
> > > > + *
> > > > + * Matches any IPv6 extension header.
> > > > + */
> > > > +struct rte_flow_item_ipv6_ext_hdr_any {
> > > > +	uint8_t next_hdr;
> > > > +};
> > >
> > > So what's the point? next_hdr is already part of either struct
> > > ipv6_hdr
> > > ("proto") and individual extension headers. Moreover it's implicit
> > > if an extension header is provided in a pattern.
> > >
> > > How about removing it?
> >
> > We need this to match a packet that have extend header For example:
> > IPV6(proto = 43, <Routing EH >) / EXT_HDR (next_head = 60 <Destination EH>)
> / EXT_HDR (next_head = 44, <Fragment EH)/ EXT_HDR (next_head = 6 <tcp>) /
> TCP ...
> >
> > I use "ANY" to match any extend header regardless their content.
> > There is no conflict if we can add multiple RTE_FLOW_ITEM_EXT_HDR_XXX
> > in futures
> 
> I see, makes sense. How about doing like ICMPv6 above? Generic item uses the
> base name and can only match the generic part specifically (next_hdr), while
> specific items don't match the generic part but whatever additions their
> dedicated structures define, i.e.:
> 
>  RTE_FLOW_ITEM_TYPE_IPV6_EXT
>  RTE_FLOW_ITEM_TYPE_IPV6_EXT_HBH
>  RTE_FLOW_ITEM_TYPE_IPV6_EXT_DEST
>  RTE_FLOW_ITEM_TYPE_IPV6_EXT_RTHDR
>  RTE_FLOW_ITEM_TYPE_IPV6_EXT_FRAG
>  ...

Yes, agree.

> 
> No need to define them all if you only need EXT, this is just to describe the idea
> (it's also OK if you want to define them while you're at it).
> 
> >
> > >
> > > > +
> > > > +/** Default mask for RTE_FLOW_ITEM_TYPE_IPV6_EXT_HDR_ANY. */
> > > #ifndef
> > > > +__cplusplus static const struct rte_flow_item_ipv6_ext_hdr_any
> > > > +rte_flow_item_ipv6_ext_any_mask = {
> > > > +	.next_hdr = 0xff,
> > > > +};
> > > > +#endif
> > >
> > > Ditto.
> > >
> > > > +
> > > > +/**
> > > > + * RTE_FLOW_ITEM_TYPE_ICMPV6
> > > > + *
> > > > + * Matches ICMPv6 header.
> > >
> > > => Matches an ICMPv6 header.
> > >
> > > > + */
> > > > +struct rte_flow_item_icmpv6 {
> > > > +	uint8_t type;
> > > > +	uint8_t code;
> > > > +	uint16_t checksum;
> > >
> > > The last 32-bit "reserved" data field is missing.
> > >
> > > > +};
> > >
> > > Too bad there is no struct icmp6_hdr definition in rte_icmp.h. You could
> add it.
> > > In any case Doxygen comments are missing, please add them (see other
> > > structure definitions for examples).
> 
> No need to rely on an external definition due to the above suggestions by the
> way.
> 
> > >
> > > > +
> > > > +/** Default mask for RTE_FLOW_ITEM_TYPE_ICMPV6 */
> > >
> > > Missing "."
> > >
> > > > +#ifndef __cplusplus
> > > > +static const struct rte_flow_item_icmpv6 rte_flow_item_icmpv6_mask =
> {
> > > > +	.type = 0xff,
> > > > +	.code = 0xff,
> > > > +	.checksum = RTE_BE16(0xffff),
> > > > +};
> > > > +#endif
> > >
> > > You must remove checksum matching from the default mask. That's the
> > > last thing an application might want to match exactly :)
> > >
> > > > +
> > > > +/**
> > > > + * RTE_FLOW_ITEM_TYPE_ICMPV6_TGT_ADDR
> > > > + *
> > > > + * Matches ICMPv6's Target Address.
> > > > + */
> > > > +struct rte_flow_item_icmpv6_tgt_addr {
> > > > +	uint8_t addr[16];
> > > > +};
> > >
> > > You need to expand this as two items, see prior comments regarding
> > > RTE_FLOW_ITEM_TYPE_ND6_RS, RTE_FLOW_ITEM_TYPE_ND6_NA and
> their
> > > respective structs rte_flow_item_nd6_rs and rte_flow_item_nd6_na.
> > >
> > > Also Doxygen documentation is missing for the addr field and you
> > > need to describe that these are only valid when used after
> > > RTE_FLOW_ITEM_TYPE_ICMPV6.
> > >
> > > > +
> > > > +/** Default mask for RTE_FLOW_ITEM_TYPE_ICMPV6_TGT_ADDR */
> > >
> > > Missing "."
> > >
> > > > +#ifndef __cplusplus
> > > > +static const
> > > > +struct rte_flow_item_icmpv6_tgt_addr
> > > rte_flow_item_icmpv6_tgt_addr_mask = {
> > > > +	.addr =
> > > > +		"\xff\xff\xff\xff\xff\xff\xff\xff"
> > > > +		"\xff\xff\xff\xff\xff\xff\xff\xff",
> > > > +};
> > > > +#endif
> > > > +
> > > > +/**
> > > > + * RTE_FLOW_ITEM_TYPE_ICPMV6_SLL.
> > > > + *
> > > > + * Matches ICMPv6 Source Link-Layer address.
> > > > + */
> > > > +struct rte_flow_item_icmpv6_sll {
> > > > +	struct ether_addr addr;
> > > > +};
> > >
> > > See prior comments regarding RTE_FLOW_ITEM_TYPE_ND6_OPT_SLA_ETH
> and
> > > struct rte_flow_item_type_nd6_opt_sla_eth.
> > >
> > > Also Doxygen documentation is missing for the addr field and you
> > > need to describe that it is only valid when found after either
> > > RTE_FLOW_ITEM_TYPE_ND6_RS or RTE_FLOW_ITEM_TYPE_ND6_NA.
> > >
> > > Also missing empty line here.
> > >
> > > > +/** Default mask for RTE_FLOW_ITEM_TYPE_ICMPV6_SLL */
> > >
> > > Missing "."
> > >
> > > > +#ifndef __cplusplus
> > > > +static const struct rte_flow_item_icmpv6_sll
> > > rte_flow_item_icmpv6_sll_mask = {
> > > > +	.addr = {
> > > > +		.addr_bytes = "\xff\xff\xff\xff\xff\xff",
> > > > +	}
> > > > +};
> > > > +#endif
> > > > +
> > > > +/**
> > > > + * RTE_FLOW_ITEM_TYPE_ICMPV6_TLL.
> > > > + *
> > > > + * Matches ICMPv6 Target Link-Layer address.
> > > > + */
> > > > +struct rte_flow_item_icmpv6_tll {
> > > > +	struct ether_addr addr;
> > > > +};
> > >
> > > See prior comments regarding RTE_FLOW_ITEM_TYPE_ND6_OPT_TLA_ETH
> > > and struct rte_flow_item_type_nd6_opt_tla_eth.
> > >
> > > Also Doxygen documentation is missing for the addr field and you
> > > need to describe that it is only valid when found after either
> > > RTE_FLOW_ITEM_TYPE_ND6_RS or RTE_FLOW_ITEM_TYPE_ND6_NA.
> > >
> > > Also missing empty line here.
> > >
> > > > +/** Default mask for RTE_FLOW_ITEM_TYPE_ICMPV6_TLL */
> > >
> > > Missing "."
> > >
> > > > +#ifndef __cplusplus
> > > > +static const struct rte_flow_item_icmpv6_tll
> > > rte_flow_item_icmpv6_tll_mask = {
> > > > +	.addr = {
> > > > +		.addr_bytes = "\xff\xff\xff\xff\xff\xff",
> > > > +	}
> > > > +};
> > > > +#endif
> > > > +
> > > > +/**
> > > >   * Matching pattern item definition.
> > > >   *
> > > >   * A pattern is formed by stacking items starting from the lowest
> > > > protocol
> > > > --
> > > > 2.7.4
> > > >
> 
> --
> Adrien Mazarguil
> 6WIND

^ permalink raw reply	[flat|nested] 61+ messages in thread

* Re: [dpdk-dev] [PATCH v2 4/4] ether: add packet modification aciton in flow API
  2018-04-12  8:50       ` Zhang, Qi Z
@ 2018-04-12 10:22         ` Adrien Mazarguil
  2018-04-13 13:47           ` Zhang, Qi Z
  0 siblings, 1 reply; 61+ messages in thread
From: Adrien Mazarguil @ 2018-04-12 10:22 UTC (permalink / raw)
  To: Zhang, Qi Z
  Cc: dev, Doherty, Declan, Chandran, Sugesh, Glynn, Michael J, Liu,
	Yu Y, Ananyev, Konstantin, Richardson, Bruce

On Thu, Apr 12, 2018 at 08:50:14AM +0000, Zhang, Qi Z wrote:
> Hi Adrien
> 
> > -----Original Message-----
> > From: Adrien Mazarguil [mailto:adrien.mazarguil@6wind.com]
> > Sent: Thursday, April 12, 2018 3:04 PM
> > To: Zhang, Qi Z <qi.z.zhang@intel.com>
> > Cc: dev@dpdk.org; Doherty, Declan <declan.doherty@intel.com>; Chandran,
> > Sugesh <sugesh.chandran@intel.com>; Glynn, Michael J
> > <michael.j.glynn@intel.com>; Liu, Yu Y <yu.y.liu@intel.com>; Ananyev,
> > Konstantin <konstantin.ananyev@intel.com>; Richardson, Bruce
> > <bruce.richardson@intel.com>
> > Subject: Re: [PATCH v2 4/4] ether: add packet modification aciton in flow API
> > 
> > On Sun, Apr 01, 2018 at 05:19:22PM -0400, Qi Zhang wrote:
> > > Add new actions that be used to modify packet content with generic
> > > semantic:
> > >
> > > RTE_FLOW_ACTION_TYPE_FIELD_UPDATE:
> > > 	- update specific field of packet
> > > RTE_FLWO_ACTION_TYPE_FIELD_INCREMENT:
> > > 	- increament specific field of packet
> > > RTE_FLWO_ACTION_TYPE_FIELD_DECREMENT:
> > > 	- decreament specific field of packet
> > > RTE_FLWO_ACTION_TYPE_FIELD_COPY:
> > > 	- copy data from one field to another in packet.
> > >
> > > All action use struct rte_flow_item parameter to match the pattern
> > > that going to be modified, if no pattern match, the action just be
> > > skipped.
> > 
> > That's not good. It must result in undefined behavior, more about that below.
> 
> I may not get your point, see my below comment.
> 
> > 
> > > These action are non-terminating action. they will not impact the fate
> > > of the packets.
> > >
> > > Signed-off-by: Qi Zhang <qi.z.zhang@intel.com>
> > 
> > Noticed a few typos above and in subject line ("aciton", "FLWO", "increament",
> > "decreament").
> > 
> > Note that I'm usually against using rte_flow_item structures and associated
> > enum values inside action lists because it could be seen as inconsistent from
> > an API standpoint. On the other hand, reusing existing types is a good thing so
> > let's go with that for now.
> > 
> > Please see inline comments.
> > 
> > > ---
> > >  doc/guides/prog_guide/rte_flow.rst | 89
> > ++++++++++++++++++++++++++++++++++++++
> > >  lib/librte_ether/rte_flow.h        | 57 ++++++++++++++++++++++++
> > >  2 files changed, 146 insertions(+)
> > >
> > > diff --git a/doc/guides/prog_guide/rte_flow.rst
> > > b/doc/guides/prog_guide/rte_flow.rst
> > > index aa5c818..6628964 100644
> > > --- a/doc/guides/prog_guide/rte_flow.rst
> > > +++ b/doc/guides/prog_guide/rte_flow.rst
> > > @@ -1508,6 +1508,95 @@ Representor.
> > >     | ``port_id``  | identification of the destination |
> > >     +--------------+-----------------------------------+
> > >
> > > +Action: ``FILED_UPDATE``
> > > +^^^^^^^^^^^^^^^^^^^^^^^
> > 
> > FILED => FIELD
> > 
> > Underline is also shorter than title and might cause documentation warnings.
> > 
> > > +
> > > +Update specific field of the packet.
> > > +
> > > +- Non-terminating by default.
> > 
> > These statements are not needed since "ethdev: alter behavior of flow API
> > actions" [1].
> > 
> > [1] http://dpdk.org/ml/archives/dev/2018-April/096527.html
> > 
> > > +
> > > +.. _table_rte_flow_action_field_update:
> > > +
> > > +.. table:: FIELD_UPDATE
> > > +
> > > +   +-----------+---------------------------------------------------------+
> > > +   | Field     | Value
> > |
> > > +
> > +===========+====================================================
> > =====+
> > > +   | ``item``  | item->type: specify the pattern to modify
> > |
> > > +   |           | item->spec: specify the new value to update
> > |
> > > +   |           | item->mask: specify which part of the pattern to update
> > |
> > > +   |           | item->last: ignored
> > |
> > 
> > This table needs to be divided a bit more with one cell per field for better
> > clarity. See other pattern item definitions such as "Item: ``RAW``" for an
> > example.
> > 
> > > +   +-----------+---------------------------------------------------------+
> > > +   | ``layer`` | 0 means outermost matched pattern,
> > |
> > > +   |           | 1 means next-to-outermost and so on ...
> > |
> > > +
> > > + +-----------+-------------------------------------------------------
> > > + --+
> > 
> > What does "layer" refer to by the way? The layer described on the pattern side
> > of the flow rule, the actual protocol layer matched inside traffic, or is "item"
> > actually an END-terminated list of items (as suggested by "pattern" in above
> > documentation)?
> > 
> > I suspect the intent is for layer to have the same definition as RSS encapulation
> > level ("ethdev: add encap level to RSS flow API action" [2]), and item points to
> > a single item, correct?
> 
> Yes
> > 
> > In that case, it's misleading, please rename it "level". Also keep in mind you
> > can't make an action rely on anything found on the pattern side of a flow rule.
> > 
> OK, "Level" looks better.
> Also I may not get your point here. please correct me, 
> My understanding is, all the modification action of a flow is independent of patterns of the same flow, 
> For example when define a flow with pattern = eth/ipv4 and with a TCP modification action.
> all ipv4 packets will hit that flow, and go to the same destination, but only TCP packet will be modified
> otherwise, the action is just skipped,
> 
> > What happens when this action is attempted on non-matching traffic must be
> > documented here as well. Refer to discussion re "ethdev: Add tunnel
> > encap/decap actions" [3]. To be on the safe side, it must be documented as
> > resulting in undefined behavior.
> 
> so what is "undefined behavior" you means?
> The rule is:
> If a packet matched pattern in action, it will be modified, otherwise the action just take no effect
> is this idea acceptable?

Not really, what happens will depend on the underlying device. It's better
to document it as undefined because you can't predict the result. Some
devices will cause packets to be lost, others will let them through
unchanged, others will crash the system after formatting the hard drive, no
one knows.

It's an application's responsibility to properly match traffic or otherwise
make sure only matching traffic goes through before performing any actions
on it, otherwise they'll encounter such undefined behavior.

> > Based the same thread, I also suggest here to define "last" as reserved and
> > therefore an error if set to anything other than NULL, however it might prove
> > useful, see below.
> > 
> > [2] http://dpdk.org/ml/archives/dev/2018-April/096531.html
> > [3] http://dpdk.org/ml/archives/dev/2018-April/096418.html
> > 
> > > +
> > > +Action: ``FILED_INCREMENT``
> > > +^^^^^^^^^^^^^^^^^^^^^^^^^^^
> > 
> > FILED => FIELD
> > 
> > > +
> > > +Increment 1 on specific field of the packet.
> > 
> > All right, but what for? FIELD_UPDATE overwrites a specific value at some
> > specific place after matching something rather specific.
> > 
> > In my opinion to get predictable results with FIELD_INCREMENT, applications
> > also need to have a pretty good idea of what's about to be incremented.
> > That's because you can't put conditionals in flow rules (yet). So if you need to
> > match an exact IPv4 address in order to increment it, why wouldn't you just
> > provide its replacement directly?
> 
> The typical usage is for TTL or similar count that are not be matched in flow pattern. 

Incrementing TTL? Let's assume it's automatically decremented. What happens
when its value is already 0 in the packet?

> > I'm not saying there are no use cases for this, but you know, a couple of real
> > world example scenarios can't hurt. This should answer what an application
> > could possibly want to unconditionally increment in ingress/egress traffic and
> > for what purpose.
> 
> > 
> > > +
> > > +- Non-terminating by default.
> > 
> > Same comment as in FIELD_UPDATE.
> > 
> > > +
> > > +.. _table_rte_flow_action_field_update:
> > > +
> > > +.. table:: FIELD_INCREMENT
> > > +
> > > +   +-----------+---------------------------------------------------------+
> > > +   | Field     | Value
> > |
> > > +
> > +===========+====================================================
> > =====+
> > > +   | ``item``  | item->type: specify the pattern to modify
> > |
> > > +   |           | item->spec: ignored
> > |
> > > +   |           | item->mask: specify which part of the pattern to update
> > |
> > > +   |           | item->last: ignored
> > |
> > > +   +-----------+---------------------------------------------------------+
> > > +   | ``layer`` | 0 means outermost matched pattern,
> > |
> > > +   |           | 1 means next-to-outermost and so on ...
> > |
> > > +
> > > + +-----------+-------------------------------------------------------
> > > + --+
> > 
> > Ditto.
> > 
> > With another comment regarding "last". When specified it could be used to
> > provide a stride, i.e. the amount to increment instead of 1 (increment = last -
> > spec).
> 
> But the initial value is not predicable like TTL.

Not sure I understand this comment. The action part of a flow rule blindly
affects traffic as described in the action, it doesn't even look at the
original value. The pattern part is supposed to select traffic on which
actions must be performed.

Decrementing TTL is a possibility but I don't see TTL as something
predictable on the pattern side. Are we both talking about Time-to-Live?

> 
> > 
> > > +
> > > +Action: ``FIELD_DECREMENT``
> > > +^^^^^^^^^^^^^^^^^^^^^^^^^^^
> > > +
> > > +Decrement 1 on specific field of the packet.
> > 
> > Same comment as in FIELD_INCREMENT.
> > 
> > > +
> > > +Paramenter is same is FIELD_INCREMENT.
> > 
> > Paramenter => Parameter
> > 
> > > +
> > > +-Non-terminating by default.
> > 
> > Same comment as in FIELD_UPDATE.
> > 
> > A table is missing in this section and must be included. Keep in mind section
> > titles are used as anchors in the documentation and readers may reach this
> > point without going through the previous sections.
> > 
> 
> OK, will add.
> 
> > > +
> > > +ACTION: ``FIELD_COPY``
> > > +^^^^^^^^^^^^^^^^^^^^^^
> > > +
> > > +Copy data of one field to another of the packet.
> > > +
> > > +-Non-terminating by default.
> > 
> > Same comment as in FIELD_UPDATE.
> > 
> > > +
> > > +.. _table_rte_flow_action_field_copy:
> > > +
> > > +.. table:: FIELD_COPY
> > > +
> > > +   +-----------------+-----------------------------------------------------------------+
> > > +   | Field           | Value
> > |
> > > +
> > +=================+==============================================
> > ===================+
> > > +   | ``src_item``    | src_item->type: match the pattern that data will be
> > copy from   |
> > > +   |                 | src_item->spec: ignored
> > |
> > > +   |                 | src_item->mask: specify which part of the
> > pattern to copy       |
> > > +   |                 | src_item->last: ignored
> > |
> > > +   +-----------------+-----------------------------------------------------------------+
> > > +   | ``src_layer``   | layer of src_item
> > |
> > > +   |                 | 0 means outermost matched pattern,
> > |
> > > +   |                 | 1 means next-to-outermost and so on ...
> > |
> > > +   +-----------------+-----------------------------------------------------------------+
> > > +   | ``dst_item``    | dst_item->type: match the pattern that data will be
> > copy to     |
> > > +   |                 | dst_item->spec: ignored
> > |
> > > +   |                 | dst_item->mask: specify which part of the
> > pattern to be update  |
> > > +   |                 |                 it must match
> > src_item->mask.                   |
> > > +   |                 | dst_item->last: ignored
> > |
> > > +   +-----------------+-----------------------------------------------------------------+
> > > +   | ``dst_layer``   | layer of dst_item
> > |
> > > +   |                 | 0 means outermost matched pattern,
> > |
> > > +   |                 | 1 means next-to-outermost and so on ...
> > |
> > > +
> > > + +-----------------+-------------------------------------------------
> > > + ----------------+
> > 
> > Same comments as in FIELD_UPDATE regarding table format, "last", etc.
> > 
> > A couple of real world use cases would be a nice addition here as well.
> > 
> 
> For TTL copy-in/copy-out :)
> Sorry, I should add typical usage in document also

Then please elaborate.

> 
> > > +
> > >  Negative types
> > >  ~~~~~~~~~~~~~~
> > >
> > > diff --git a/lib/librte_ether/rte_flow.h b/lib/librte_ether/rte_flow.h
> > > index a8ec780..d81ac4c 100644
> > > --- a/lib/librte_ether/rte_flow.h
> > > +++ b/lib/librte_ether/rte_flow.h
> > > @@ -1178,6 +1178,34 @@ enum rte_flow_action_type {
> > >  	 * See struct rte_flow_action_port.
> > >  	 */
> > >  	RTE_FLOW_ACTION_TYPE_PORT,
> > > +
> > > +	/**
> > > +	 * Update specific field of the packet.
> > 
> > Update => Updates (to keep the style)
> > 
> > > +	 *
> > > +	 * See struct rte_flow_item_field_update.
> > > +	 */
> > > +	RTE_FLOW_ACTION_TYPE_FILED_UPDATE,
> > 
> > FILED => FIELD
> > 
> > > +
> > > +	/**
> > > +	 * Increment specific field of the packet.
> > 
> > Increment => Increments
> > 
> > > +	 *
> > > +	 * See struct rte_flow_item_field_update.
> > > +	 */
> > > +	RTE_FLOW_ACTION_TYPE_FIELD_INCREMENT,
> > > +
> > > +	/**
> > > +	 * Decrement specific field of the packet.
> > 
> > Decrement => Decrements
> > 
> > > +	 *
> > > +	 * See struct rte_flow_item_field_update.
> > > +	 */
> > > +	RTE_FLOW_ACTION_TYPE_FIELD_DECREMENT,
> > > +
> > > +	/**
> > > +	 * Copy data of one field to another of the packet.
> > 
> > Copy => Copies
> > 
> > > +	 *
> > > +	 * See struct rte_flow_item_type_field_copy.
> > > +	 */
> > > +	RTE_FLOW_ACTION_TYPE_FIELD_COPY,
> > >  };
> > >
> > >  /**
> > > @@ -1327,6 +1355,35 @@ struct rte_flow_action_port {
> > >  	uint16_t port_id; /**< identification of the forward destination. */
> > > };
> > >
> > > +/** RTE_FLOW_ACTION_TYPE_FIELD_UPDATE
> > 
> > Here "/**" should be on its own line like the rest of the file. You can safely
> > ignore checkpatch nonsense (if any).
> > 
> > > + *  RTE_FLOW_ACTION_TYPE_FIELD_INCREMENT
> > > + *  RTE_FLOW_ACTION_TYPE_FIELD_DECREMENT
> > 
> > One shared structure for everything? How about a single UPDATE action to
> > cover everything instead?
> > 
> > - mask && last is NULL or last - spec is 0 => update
> > - mask && last - spec is positive => increment by that amount
> > - mask && last - spec is negative => decrement by that amount
> 
> So, only care about delta?, last=4 spec=3 is the same thing as last=34 spec=33?
> It looks a little bit confuse to me. 

Anything's fine as long as it's properly documented and convincing enough :)

This approach allows decrementing by a large amount using unsigned values
or whatever types spec/last fields use according to a mask. One can
decrement or increment something as small as a single bit and as large as an
IPv6 address:

 spec = 0x8000, last = 0 => decrement by 0x8000

 spec = 0, last = 0x8000 => increment by 0x8000

 spec = 0x8000, last = 0x8000 => set to 0x8000

All the above *only* for masked fields and when last is non-NULL. Think of
the possibilities!

> 
> > 
> > This would be easier to document, would result in a smaller patch, implicitly
> > gives meaning to "last" and provides the ability to simultaneously increment,
> > decrement and update several fields at once.
> > 
> > > + *
> > > + * Update specific field of the packet.
> > > + *
> > > + * Typical usage: update mac/ip address.
> > 
> > Documentation is a bit weak and needs improvement. In any case, except for
> > tables and examples, whatever is written in this comment should be word for
> > word the same as what is written in rte_flow.rst.
> > 
> > > + */
> > > +struct rte_flow_action_field_update {
> > > +	const struct rte_flow_item *item; /**< specify the data to modify.
> > > +*/
> > 
> > Since there is a single item that contains its own pointers to spec/last/mask,
> > "item" shouldn't be a pointer. It's unnecessary and misleading.
> 
> OK, will change to structure.
> > 
> > Documentation needs improvement.
> > 
> > > +	uint8_t layer;
> > > +	/**< 0 means outermost matched pattern, 1 means next-to-outermost...
> > > +*/
> > 
> > uint8_t layer => uint32_t level (we're not constrained by space)
> > 
> > Ditto re documentation. See RSS encap level patch [2] for ideas.
> 
> Thanks for heads up, will check that.
> 
> > 
> > > +};
> > > +
> > > +/** RTE_FLOW_ACTION_TYPE_FIELD_COPY
> > 
> > Ditto for "/**".
> > 
> > > + *
> > > + * Copy data from one field to another of the packet.
> > > + *
> > > + * Typical usage: TTL copy-in / copy-out
> > 
> > This typical usage doesn't look that obvious to me. Copy TTL from what part of
> > the packet to where? What happens to the overwritten TTL value? Why should
> > they be synchronized?
> 
> I think this is standard flow action from OpenFlow, and it is supported by our hardware
> This is the generic way we implemented, let me know if you have other better idea.

OK, after looking it up [4], I see OpenFlow defines specific "Change-TTL"
actions that only work with specific protocols (IPv4 TTL, IPv6 hops, MPLS
TTL). The above makes so much sense now.

This document describes that packets with invalid TTLs are rejected,
particularly on the decrement side. If this is what HW supports, I think it
would be wiser to define specific TTL-manipulating actions as well.

As defined, increment/decrement actions are rather dumb and cannot care
about what's being incremented/decremented. Since they can be used with any
header field, they don't have special provisions when the original or
resulting value is 0.

I think a dedicated set of OpenFlow actions is needed if OF is considered a
HW capability. They would be easy to document by pointing to their original
specification. Based on [1] this should result in:

 RTE_FLOW_ACTION_TYPE_OF_COPY_TTL_INWARDS
 RTE_FLOW_ACTION_TYPE_OF_POP
 RTE_FLOW_ACTION_TYPE_OF_PUSH_MPLS
 RTE_FLOW_ACTION_TYPE_OF_PUSH_PBB
 RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN
 RTE_FLOW_ACTION_TYPE_OF_COPY_TTL_OUTWARDS
 RTE_FLOW_ACTION_TYPE_OF_DECREMENT_TTL
 ...

Many of them wouldn't even need a configuration structure.

[4] https://www.opennetworking.org/images/stories/downloads/sdn-resources/onf-specifications/openflow/openflow-spec-v1.3.0.pdf

> 
> Thanks
> Qi
> 
> > 
> > > + */
> > > +struct rte_flow_action_field_copy {
> > > +	const struct rte_flow_item *src_item; /**< Specify the data copy from */
> > > +	uint8_t src_layer;
> > > +	/**< 0 means outermost matched pattern, 1 means next-to-outermost...
> > */
> > > +	const struct rte_flow_item *dst_item; /**< Specify the data copy to */
> > > +	uint8_t dst_layer;
> > > +	/**< 0 means outermost matched pattern, 1 means next-to-outermost...
> > > +*/ };
> > 
> > Same comments as for struct rte_flow_action_field_update.
> > 
> > > +
> > >  /**
> > >   * Definition of a single action.
> > >   *
> > > --
> > > 2.7.4
> > >
> > 
> > --
> > Adrien Mazarguil
> > 6WIND

-- 
Adrien Mazarguil
6WIND

^ permalink raw reply	[flat|nested] 61+ messages in thread

* Re: [dpdk-dev] [PATCH v2 4/4] ether: add packet modification aciton in flow API
  2018-04-12 10:22         ` Adrien Mazarguil
@ 2018-04-13 13:47           ` Zhang, Qi Z
  2018-04-16 13:30             ` Adrien Mazarguil
  0 siblings, 1 reply; 61+ messages in thread
From: Zhang, Qi Z @ 2018-04-13 13:47 UTC (permalink / raw)
  To: Adrien Mazarguil
  Cc: dev, Doherty, Declan, Chandran, Sugesh, Glynn, Michael J, Liu,
	Yu Y, Ananyev, Konstantin, Richardson, Bruce



> -----Original Message-----
> From: Adrien Mazarguil [mailto:adrien.mazarguil@6wind.com]
> Sent: Thursday, April 12, 2018 6:23 PM
> To: Zhang, Qi Z <qi.z.zhang@intel.com>
> Cc: dev@dpdk.org; Doherty, Declan <declan.doherty@intel.com>; Chandran,
> Sugesh <sugesh.chandran@intel.com>; Glynn, Michael J
> <michael.j.glynn@intel.com>; Liu, Yu Y <yu.y.liu@intel.com>; Ananyev,
> Konstantin <konstantin.ananyev@intel.com>; Richardson, Bruce
> <bruce.richardson@intel.com>
> Subject: Re: [PATCH v2 4/4] ether: add packet modification aciton in flow API
> 
> On Thu, Apr 12, 2018 at 08:50:14AM +0000, Zhang, Qi Z wrote:
> > Hi Adrien
> >
> > > -----Original Message-----
> > > From: Adrien Mazarguil [mailto:adrien.mazarguil@6wind.com]
> > > Sent: Thursday, April 12, 2018 3:04 PM
> > > To: Zhang, Qi Z <qi.z.zhang@intel.com>
> > > Cc: dev@dpdk.org; Doherty, Declan <declan.doherty@intel.com>;
> > > Chandran, Sugesh <sugesh.chandran@intel.com>; Glynn, Michael J
> > > <michael.j.glynn@intel.com>; Liu, Yu Y <yu.y.liu@intel.com>;
> > > Ananyev, Konstantin <konstantin.ananyev@intel.com>; Richardson,
> > > Bruce <bruce.richardson@intel.com>
> > > Subject: Re: [PATCH v2 4/4] ether: add packet modification aciton in
> > > flow API
> > >
> > > On Sun, Apr 01, 2018 at 05:19:22PM -0400, Qi Zhang wrote:
> > > > Add new actions that be used to modify packet content with generic
> > > > semantic:
> > > >
> > > > RTE_FLOW_ACTION_TYPE_FIELD_UPDATE:
> > > > 	- update specific field of packet
> > > > RTE_FLWO_ACTION_TYPE_FIELD_INCREMENT:
> > > > 	- increament specific field of packet
> > > > RTE_FLWO_ACTION_TYPE_FIELD_DECREMENT:
> > > > 	- decreament specific field of packet
> > > > RTE_FLWO_ACTION_TYPE_FIELD_COPY:
> > > > 	- copy data from one field to another in packet.
> > > >
> > > > All action use struct rte_flow_item parameter to match the pattern
> > > > that going to be modified, if no pattern match, the action just be
> > > > skipped.
> > >
> > > That's not good. It must result in undefined behavior, more about that
> below.
> >
> > I may not get your point, see my below comment.
> >
> > >
> > > > These action are non-terminating action. they will not impact the
> > > > fate of the packets.
> > > >
> > > > Signed-off-by: Qi Zhang <qi.z.zhang@intel.com>
> > >
> > > Noticed a few typos above and in subject line ("aciton", "FLWO",
> > > "increament", "decreament").
> > >
> > > Note that I'm usually against using rte_flow_item structures and
> > > associated enum values inside action lists because it could be seen
> > > as inconsistent from an API standpoint. On the other hand, reusing
> > > existing types is a good thing so let's go with that for now.
> > >
> > > Please see inline comments.
> > >
> > > > ---
> > > >  doc/guides/prog_guide/rte_flow.rst | 89
> > > ++++++++++++++++++++++++++++++++++++++
> > > >  lib/librte_ether/rte_flow.h        | 57
> ++++++++++++++++++++++++
> > > >  2 files changed, 146 insertions(+)
> > > >
> > > > diff --git a/doc/guides/prog_guide/rte_flow.rst
> > > > b/doc/guides/prog_guide/rte_flow.rst
> > > > index aa5c818..6628964 100644
> > > > --- a/doc/guides/prog_guide/rte_flow.rst
> > > > +++ b/doc/guides/prog_guide/rte_flow.rst
> > > > @@ -1508,6 +1508,95 @@ Representor.
> > > >     | ``port_id``  | identification of the destination |
> > > >     +--------------+-----------------------------------+
> > > >
> > > > +Action: ``FILED_UPDATE``
> > > > +^^^^^^^^^^^^^^^^^^^^^^^
> > >
> > > FILED => FIELD
> > >
> > > Underline is also shorter than title and might cause documentation
> warnings.
> > >
> > > > +
> > > > +Update specific field of the packet.
> > > > +
> > > > +- Non-terminating by default.
> > >
> > > These statements are not needed since "ethdev: alter behavior of
> > > flow API actions" [1].
> > >
> > > [1] http://dpdk.org/ml/archives/dev/2018-April/096527.html
> > >
> > > > +
> > > > +.. _table_rte_flow_action_field_update:
> > > > +
> > > > +.. table:: FIELD_UPDATE
> > > > +
> > > > +   +-----------+---------------------------------------------------------+
> > > > +   | Field     | Value
> > > |
> > > > +
> > >
> +===========+==================================================
> ==
> > > =====+
> > > > +   | ``item``  | item->type: specify the pattern to modify
> > > |
> > > > +   |           | item->spec: specify the new value to update
> > > |
> > > > +   |           | item->mask: specify which part of the pattern to
> update
> > > |
> > > > +   |           | item->last: ignored
> > > |
> > >
> > > This table needs to be divided a bit more with one cell per field
> > > for better clarity. See other pattern item definitions such as
> > > "Item: ``RAW``" for an example.
> > >
> > > > +   +-----------+---------------------------------------------------------+
> > > > +   | ``layer`` | 0 means outermost matched pattern,
> > > |
> > > > +   |           | 1 means next-to-outermost and so on ...
> > > |
> > > > +
> > > > + +-----------+---------------------------------------------------
> > > > + +-----------+----
> > > > + --+
> > >
> > > What does "layer" refer to by the way? The layer described on the
> > > pattern side of the flow rule, the actual protocol layer matched inside
> traffic, or is "item"
> > > actually an END-terminated list of items (as suggested by "pattern"
> > > in above documentation)?
> > >
> > > I suspect the intent is for layer to have the same definition as RSS
> > > encapulation level ("ethdev: add encap level to RSS flow API action"
> > > [2]), and item points to a single item, correct?
> >
> > Yes
> > >
> > > In that case, it's misleading, please rename it "level". Also keep
> > > in mind you can't make an action rely on anything found on the pattern
> side of a flow rule.
> > >
> > OK, "Level" looks better.
> > Also I may not get your point here. please correct me, My
> > understanding is, all the modification action of a flow is independent
> > of patterns of the same flow, For example when define a flow with pattern
> = eth/ipv4 and with a TCP modification action.
> > all ipv4 packets will hit that flow, and go to the same destination,
> > but only TCP packet will be modified otherwise, the action is just
> > skipped,
> >
> > > What happens when this action is attempted on non-matching traffic
> > > must be documented here as well. Refer to discussion re "ethdev: Add
> > > tunnel encap/decap actions" [3]. To be on the safe side, it must be
> > > documented as resulting in undefined behavior.
> >
> > so what is "undefined behavior" you means?
> > The rule is:
> > If a packet matched pattern in action, it will be modified, otherwise
> > the action just take no effect is this idea acceptable?
> 
> Not really, what happens will depend on the underlying device. It's better to
> document it as undefined because you can't predict the result. Some devices
> will cause packets to be lost, others will let them through unchanged, others
> will crash the system after formatting the hard drive, no one knows.

OK, basically I think "undefined behavior" is not friendly to application, we should avoid.
But you are right, we need to consider device with different behavior for " modification on non-matched pattern"
I'm thinking why driver can't avoid non-matched pattern modification if the device does not support?
For example, driver can reject a flow ETH/IPV4 with TCP action, but may accept ETH/IPV4/TCP with TCP action base on 
its capability.

> 
> It's an application's responsibility to properly match traffic or otherwise make
> sure only matching traffic goes through before performing any actions on it,
> otherwise they'll encounter such undefined behavior.
> 
> > > Based the same thread, I also suggest here to define "last" as
> > > reserved and therefore an error if set to anything other than NULL,
> > > however it might prove useful, see below.
> > >
> > > [2] http://dpdk.org/ml/archives/dev/2018-April/096531.html
> > > [3] http://dpdk.org/ml/archives/dev/2018-April/096418.html
> > >
> > > > +
> > > > +Action: ``FILED_INCREMENT``
> > > > +^^^^^^^^^^^^^^^^^^^^^^^^^^^
> > >
> > > FILED => FIELD
> > >
> > > > +
> > > > +Increment 1 on specific field of the packet.
> > >
> > > All right, but what for? FIELD_UPDATE overwrites a specific value at
> > > some specific place after matching something rather specific.
> > >
> > > In my opinion to get predictable results with FIELD_INCREMENT,
> > > applications also need to have a pretty good idea of what's about to be
> incremented.
> > > That's because you can't put conditionals in flow rules (yet). So if
> > > you need to match an exact IPv4 address in order to increment it,
> > > why wouldn't you just provide its replacement directly?
> >
> > The typical usage is for TTL or similar count that are not be matched in flow
> pattern.
> 
> Incrementing TTL? Let's assume it's automatically decremented. What
> happens when its value is already 0 in the packet?
> 
> > > I'm not saying there are no use cases for this, but you know, a
> > > couple of real world example scenarios can't hurt. This should
> > > answer what an application could possibly want to unconditionally
> > > increment in ingress/egress traffic and for what purpose.
> >
> > >
> > > > +
> > > > +- Non-terminating by default.
> > >
> > > Same comment as in FIELD_UPDATE.
> > >
> > > > +
> > > > +.. _table_rte_flow_action_field_update:
> > > > +
> > > > +.. table:: FIELD_INCREMENT
> > > > +
> > > > +   +-----------+---------------------------------------------------------+
> > > > +   | Field     | Value
> > > |
> > > > +
> > >
> +===========+==================================================
> ==
> > > =====+
> > > > +   | ``item``  | item->type: specify the pattern to modify
> > > |
> > > > +   |           | item->spec: ignored
> > > |
> > > > +   |           | item->mask: specify which part of the pattern to
> update
> > > |
> > > > +   |           | item->last: ignored
> > > |
> > > > +   +-----------+---------------------------------------------------------+
> > > > +   | ``layer`` | 0 means outermost matched pattern,
> > > |
> > > > +   |           | 1 means next-to-outermost and so on ...
> > > |
> > > > +
> > > > + +-----------+---------------------------------------------------
> > > > + +-----------+----
> > > > + --+
> > >
> > > Ditto.
> > >
> > > With another comment regarding "last". When specified it could be
> > > used to provide a stride, i.e. the amount to increment instead of 1
> > > (increment = last - spec).
> >
> > But the initial value is not predicable like TTL.
> 
> Not sure I understand this comment. The action part of a flow rule blindly
> affects traffic as described in the action, it doesn't even look at the original
> value. The pattern part is supposed to select traffic on which actions must be
> performed.
> 
> Decrementing TTL is a possibility but I don't see TTL as something predictable
> on the pattern side. Are we both talking about Time-to-Live?
> 
> >
> > >
> > > > +
> > > > +Action: ``FIELD_DECREMENT``
> > > > +^^^^^^^^^^^^^^^^^^^^^^^^^^^
> > > > +
> > > > +Decrement 1 on specific field of the packet.
> > >
> > > Same comment as in FIELD_INCREMENT.
> > >
> > > > +
> > > > +Paramenter is same is FIELD_INCREMENT.
> > >
> > > Paramenter => Parameter
> > >
> > > > +
> > > > +-Non-terminating by default.
> > >
> > > Same comment as in FIELD_UPDATE.
> > >
> > > A table is missing in this section and must be included. Keep in
> > > mind section titles are used as anchors in the documentation and
> > > readers may reach this point without going through the previous sections.
> > >
> >
> > OK, will add.
> >
> > > > +
> > > > +ACTION: ``FIELD_COPY``
> > > > +^^^^^^^^^^^^^^^^^^^^^^
> > > > +
> > > > +Copy data of one field to another of the packet.
> > > > +
> > > > +-Non-terminating by default.
> > >
> > > Same comment as in FIELD_UPDATE.
> > >
> > > > +
> > > > +.. _table_rte_flow_action_field_copy:
> > > > +
> > > > +.. table:: FIELD_COPY
> > > > +
> > > > +   +-----------------+-----------------------------------------------------------------+
> > > > +   | Field           | Value
> > > |
> > > > +
> > >
> +=================+============================================
> ==
> > > ===================+
> > > > +   | ``src_item``    | src_item->type: match the pattern that data
> will be
> > > copy from   |
> > > > +   |                 | src_item->spec: ignored
> > > |
> > > > +   |                 | src_item->mask: specify which part of the
> > > pattern to copy       |
> > > > +   |                 | src_item->last: ignored
> > > |
> > > > +   +-----------------+-----------------------------------------------------------------+
> > > > +   | ``src_layer``   | layer of src_item
> > > |
> > > > +   |                 | 0 means outermost matched pattern,
> > > |
> > > > +   |                 | 1 means next-to-outermost and so on ...
> > > |
> > > > +   +-----------------+-----------------------------------------------------------------+
> > > > +   | ``dst_item``    | dst_item->type: match the pattern that data
> will be
> > > copy to     |
> > > > +   |                 | dst_item->spec: ignored
> > > |
> > > > +   |                 | dst_item->mask: specify which part of the
> > > pattern to be update  |
> > > > +   |                 |                 it must match
> > > src_item->mask.                   |
> > > > +   |                 | dst_item->last: ignored
> > > |
> > > > +   +-----------------+-----------------------------------------------------------------+
> > > > +   | ``dst_layer``   | layer of dst_item
> > > |
> > > > +   |                 | 0 means outermost matched pattern,
> > > |
> > > > +   |                 | 1 means next-to-outermost and so on ...
> > > |
> > > > +
> > > > + +-----------------+---------------------------------------------
> > > > + +-----------------+----
> > > > + ----------------+
> > >
> > > Same comments as in FIELD_UPDATE regarding table format, "last", etc.
> > >
> > > A couple of real world use cases would be a nice addition here as well.
> > >
> >
> > For TTL copy-in/copy-out :)
> > Sorry, I should add typical usage in document also
> 
> Then please elaborate.
> 
> >
> > > > +
> > > >  Negative types
> > > >  ~~~~~~~~~~~~~~
> > > >
> > > > diff --git a/lib/librte_ether/rte_flow.h
> > > > b/lib/librte_ether/rte_flow.h index a8ec780..d81ac4c 100644
> > > > --- a/lib/librte_ether/rte_flow.h
> > > > +++ b/lib/librte_ether/rte_flow.h
> > > > @@ -1178,6 +1178,34 @@ enum rte_flow_action_type {
> > > >  	 * See struct rte_flow_action_port.
> > > >  	 */
> > > >  	RTE_FLOW_ACTION_TYPE_PORT,
> > > > +
> > > > +	/**
> > > > +	 * Update specific field of the packet.
> > >
> > > Update => Updates (to keep the style)
> > >
> > > > +	 *
> > > > +	 * See struct rte_flow_item_field_update.
> > > > +	 */
> > > > +	RTE_FLOW_ACTION_TYPE_FILED_UPDATE,
> > >
> > > FILED => FIELD
> > >
> > > > +
> > > > +	/**
> > > > +	 * Increment specific field of the packet.
> > >
> > > Increment => Increments
> > >
> > > > +	 *
> > > > +	 * See struct rte_flow_item_field_update.
> > > > +	 */
> > > > +	RTE_FLOW_ACTION_TYPE_FIELD_INCREMENT,
> > > > +
> > > > +	/**
> > > > +	 * Decrement specific field of the packet.
> > >
> > > Decrement => Decrements
> > >
> > > > +	 *
> > > > +	 * See struct rte_flow_item_field_update.
> > > > +	 */
> > > > +	RTE_FLOW_ACTION_TYPE_FIELD_DECREMENT,
> > > > +
> > > > +	/**
> > > > +	 * Copy data of one field to another of the packet.
> > >
> > > Copy => Copies
> > >
> > > > +	 *
> > > > +	 * See struct rte_flow_item_type_field_copy.
> > > > +	 */
> > > > +	RTE_FLOW_ACTION_TYPE_FIELD_COPY,
> > > >  };
> > > >
> > > >  /**
> > > > @@ -1327,6 +1355,35 @@ struct rte_flow_action_port {
> > > >  	uint16_t port_id; /**< identification of the forward
> > > > destination. */ };
> > > >
> > > > +/** RTE_FLOW_ACTION_TYPE_FIELD_UPDATE
> > >
> > > Here "/**" should be on its own line like the rest of the file. You
> > > can safely ignore checkpatch nonsense (if any).
> > >
> > > > + *  RTE_FLOW_ACTION_TYPE_FIELD_INCREMENT
> > > > + *  RTE_FLOW_ACTION_TYPE_FIELD_DECREMENT
> > >
> > > One shared structure for everything? How about a single UPDATE
> > > action to cover everything instead?
> > >
> > > - mask && last is NULL or last - spec is 0 => update
> > > - mask && last - spec is positive => increment by that amount
> > > - mask && last - spec is negative => decrement by that amount
> >
> > So, only care about delta?, last=4 spec=3 is the same thing as last=34
> spec=33?
> > It looks a little bit confuse to me.
> 
> Anything's fine as long as it's properly documented and convincing enough :)
> 
> This approach allows decrementing by a large amount using unsigned values
> or whatever types spec/last fields use according to a mask. One can
> decrement or increment something as small as a single bit and as large as an
> IPv6 address:
> 
>  spec = 0x8000, last = 0 => decrement by 0x8000
> 
>  spec = 0, last = 0x8000 => increment by 0x8000
> 
>  spec = 0x8000, last = 0x8000 => set to 0x8000
> 
> All the above *only* for masked fields and when last is non-NULL. Think of
> the possibilities!
> 
> >
> > >
> > > This would be easier to document, would result in a smaller patch,
> > > implicitly gives meaning to "last" and provides the ability to
> > > simultaneously increment, decrement and update several fields at once.
> > >
> > > > + *
> > > > + * Update specific field of the packet.
> > > > + *
> > > > + * Typical usage: update mac/ip address.
> > >
> > > Documentation is a bit weak and needs improvement. In any case,
> > > except for tables and examples, whatever is written in this comment
> > > should be word for word the same as what is written in rte_flow.rst.
> > >
> > > > + */
> > > > +struct rte_flow_action_field_update {
> > > > +	const struct rte_flow_item *item; /**< specify the data to modify.
> > > > +*/
> > >
> > > Since there is a single item that contains its own pointers to
> > > spec/last/mask, "item" shouldn't be a pointer. It's unnecessary and
> misleading.
> >
> > OK, will change to structure.
> > >
> > > Documentation needs improvement.
> > >
> > > > +	uint8_t layer;
> > > > +	/**< 0 means outermost matched pattern, 1 means
> next-to-outermost...
> > > > +*/
> > >
> > > uint8_t layer => uint32_t level (we're not constrained by space)
> > >
> > > Ditto re documentation. See RSS encap level patch [2] for ideas.
> >
> > Thanks for heads up, will check that.
> >
> > >
> > > > +};
> > > > +
> > > > +/** RTE_FLOW_ACTION_TYPE_FIELD_COPY
> > >
> > > Ditto for "/**".
> > >
> > > > + *
> > > > + * Copy data from one field to another of the packet.
> > > > + *
> > > > + * Typical usage: TTL copy-in / copy-out
> > >
> > > This typical usage doesn't look that obvious to me. Copy TTL from
> > > what part of the packet to where? What happens to the overwritten
> > > TTL value? Why should they be synchronized?
> >
> > I think this is standard flow action from OpenFlow, and it is
> > supported by our hardware This is the generic way we implemented, let me
> know if you have other better idea.
> 
> OK, after looking it up [4], I see OpenFlow defines specific "Change-TTL"
> actions that only work with specific protocols (IPv4 TTL, IPv6 hops, MPLS TTL).
> The above makes so much sense now.
> 
> This document describes that packets with invalid TTLs are rejected,
> particularly on the decrement side. If this is what HW supports, I think it
> would be wiser to define specific TTL-manipulating actions as well.
> 
> As defined, increment/decrement actions are rather dumb and cannot care
> about what's being incremented/decremented. Since they can be used with
> any header field, they don't have special provisions when the original or
> resulting value is 0.
> 
> I think a dedicated set of OpenFlow actions is needed if OF is considered a
> HW capability. They would be easy to document by pointing to their original
> specification. Based on [1] this should result in:
> 
>  RTE_FLOW_ACTION_TYPE_OF_COPY_TTL_INWARDS
>  RTE_FLOW_ACTION_TYPE_OF_POP
>  RTE_FLOW_ACTION_TYPE_OF_PUSH_MPLS
>  RTE_FLOW_ACTION_TYPE_OF_PUSH_PBB
>  RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN
>  RTE_FLOW_ACTION_TYPE_OF_COPY_TTL_OUTWARDS
>  RTE_FLOW_ACTION_TYPE_OF_DECREMENT_TTL
>  ...
> 

Yes, actually this is another option during design :)
Since you suggested, I'd like to change to this style.

Thanks
Qi





> Many of them wouldn't even need a configuration structure.
> 
> [4]
> https://www.opennetworking.org/images/stories/downloads/sdn-resources/
> onf-specifications/openflow/openflow-spec-v1.3.0.pdf
> 
> >
> > Thanks
> > Qi
> >
> > >
> > > > + */
> > > > +struct rte_flow_action_field_copy {
> > > > +	const struct rte_flow_item *src_item; /**< Specify the data copy
> from */
> > > > +	uint8_t src_layer;
> > > > +	/**< 0 means outermost matched pattern, 1 means
> next-to-outermost...
> > > */
> > > > +	const struct rte_flow_item *dst_item; /**< Specify the data copy to
> */
> > > > +	uint8_t dst_layer;
> > > > +	/**< 0 means outermost matched pattern, 1 means
> next-to-outermost...
> > > > +*/ };
> > >
> > > Same comments as for struct rte_flow_action_field_update.
> > >
> > > > +
> > > >  /**
> > > >   * Definition of a single action.
> > > >   *
> > > > --
> > > > 2.7.4
> > > >
> > >
> > > --
> > > Adrien Mazarguil
> > > 6WIND
> 
> --
> Adrien Mazarguil
> 6WIND

^ permalink raw reply	[flat|nested] 61+ messages in thread

* [dpdk-dev] [PATCH v3 0/4] rte_flow extension for vSwitch acceleration
  2018-03-28 23:29 [dpdk-dev] [PATCH 0/4] rte_flow extension for vSwitch acceleration Qi Zhang
                   ` (4 preceding siblings ...)
  2018-04-01 21:19 ` [dpdk-dev] [PATCH v2 0/4] rte_flow extension for vSwitch acceleration Qi Zhang
@ 2018-04-16  5:16 ` Qi Zhang
  2018-04-16  5:16   ` [dpdk-dev] [PATCH v3 1/4] ethdev: add more protocol support in flow API Qi Zhang
                     ` (3 more replies)
  2018-04-16  6:10 ` [dpdk-dev] [PATCH v3 0/4] rte_flow extension for vSwitch acceleration Qi Zhang
  2018-04-23  6:36 ` [dpdk-dev] [PATCH v4 0/3] rte_flow extension for vSwitch acceleration Qi Zhang
  7 siblings, 4 replies; 61+ messages in thread
From: Qi Zhang @ 2018-04-16  5:16 UTC (permalink / raw)
  To: adrien.mazarguil
  Cc: dev, declan.doherty, sugesh.chandran, michael.j.glynn, yu.y.liu,
	konstantin.ananyev, bruce.richardson, Qi Zhang

v3:
- remove patch for port action and enhanced statistic query.
- reworked IPv6 ND related pattern base on Adrien's suggestion.
- remove generic increament/decrement/copy action
- rework packet modification action(RTE_FLOW_ACTION_TYPE_FIELD_SET).
- Add OpenFlow friendly TTL change actions.
- Add OpenFlow friendly VLAN/MPLS push/pop actions

v2: 
- fix couple typoes in code, doc and commit log

This patch extend rte_flow API.
The purpose is to provide necessary programming interface for virtual
switch software (such as OVS) to take advantage of incoming device's
vSwitch acceleration capability when using DPDK as data plane.

Note:
- The driver to demonstrate the new APIs is still in development,
  but we hope it could be accepted early to make OVS integration
  smoothly.

Qi Zhang (4):
  ethdev: add more protocol support in flow API
  ethdev: add packet field set aciton in flow API
  ethdev: add TTL change actions in flow API
  ethdev: add VLAN and MPLS pop push action in flow API

 app/test-pmd/cmdline_flow.c                 | 320 +++++++++++++++++++++
 app/test-pmd/config.c                       |   8 +
 doc/guides/prog_guide/rte_flow.rst          | 251 +++++++++++++++++
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  53 ++++
 lib/librte_ether/rte_flow.h                 | 421 +++++++++++++++++++++++++++-
 5 files changed, 1052 insertions(+), 1 deletion(-)

-- 
2.13.6

^ permalink raw reply	[flat|nested] 61+ messages in thread

* [dpdk-dev] [PATCH v3 1/4] ethdev: add more protocol support in flow API
  2018-04-16  5:16 ` [dpdk-dev] [PATCH v3 " Qi Zhang
@ 2018-04-16  5:16   ` Qi Zhang
  2018-04-16  5:16   ` [dpdk-dev] [PATCH v3 2/4] ethdev: add packet field set aciton " Qi Zhang
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 61+ messages in thread
From: Qi Zhang @ 2018-04-16  5:16 UTC (permalink / raw)
  To: adrien.mazarguil
  Cc: dev, declan.doherty, sugesh.chandran, michael.j.glynn, yu.y.liu,
	konstantin.ananyev, bruce.richardson, Qi Zhang

Add new protocol header match support as below

RTE_FLOW_ITEM_TYPE_ARP_IPV4
	- matches an IPv4 ARP header
RTE_FLOW_ITEM_TYPE_IPV6_EXT
	- matches an IPv6 extension header with any type.
RTE_FLOW_ITEM_TYPE_ICMP6
	- matches an ICMPv6 header followed by any message body.
RTE_FLOW_ITEM_TYPE_ICMP6_ND_NS
	- matches an ICMPv6 header followed by network discovery
	  neighbor solicitation.
RTE_FLOW_ITEM_TYPE_ICMP6_ND_NA
	- matches an ICMPv6 header followed by network discovery
	  neighbor advertisement.
RTE_FLOW_ITEM_TYPE_ICMP6_ND_OPT_ETH_SLA
	- matches an ICMPv6 header followed by network discovery
	  neighbor solicitation contains source Ethernet link-layer
	  address option.
RTE_FLOW_ITEM_TYPE_ICMP6_ND_OPT_ETH_TLA
	- matches an ICMPv6 header followed by network discovery
	  neighbor advertisement contains target Ethernet link-layer
	  address option.

Suggested-by: Adrien Mazarguil <adrien.mazarguil@6wind.com>
Signed-off-by: Qi Zhang <qi.z.zhang@intel.com>
---
 app/test-pmd/cmdline_flow.c                 | 174 +++++++++++++++++++++
 app/test-pmd/config.c                       |   8 +
 doc/guides/prog_guide/rte_flow.rst          |  72 +++++++++
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  27 ++++
 lib/librte_ether/rte_flow.h                 | 231 ++++++++++++++++++++++++++++
 5 files changed, 512 insertions(+)

diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c
index 59f3b3b57..a5e21c1fe 100644
--- a/app/test-pmd/cmdline_flow.c
+++ b/app/test-pmd/cmdline_flow.c
@@ -150,6 +150,21 @@ enum index {
 	ITEM_GENEVE,
 	ITEM_GENEVE_VNI,
 	ITEM_GENEVE_PROTO,
+	ITEM_IPV6_EXT,
+	ITEM_IPV6_EXT_NEXT_HDR,
+	ITEM_ICMP6,
+	ITEM_ICMP6_TYPE,
+	ITEM_ICMP6_CODE,
+	ITEM_ICMP6_ND_NS,
+	ITEM_ICMP6_ND_NS_TGT_ADDR,
+	ITEM_ICMP6_ND_NA,
+	ITEM_ICMP6_ND_NA_TGT_ADDR,
+	ITEM_ICMP6_ND_OPT_SLA_ETH,
+	ITEM_ICMP6_ND_OPT_SLA_ETH_TGT_ADDR,
+	ITEM_ICMP6_ND_OPT_SLA_ETH_SLL_ADDR,
+	ITEM_ICMP6_ND_OPT_TLA_ETH,
+	ITEM_ICMP6_ND_OPT_TLA_ETH_TGT_ADDR,
+	ITEM_ICMP6_ND_OPT_TLA_ETH_TLL_ADDR,
 
 	/* Validate/create actions. */
 	ACTIONS,
@@ -436,6 +451,12 @@ static const enum index next_item[] = {
 	ITEM_GTPC,
 	ITEM_GTPU,
 	ITEM_GENEVE,
+	ITEM_IPV6_EXT,
+	ITEM_ICMP6,
+	ITEM_ICMP6_ND_NS,
+	ITEM_ICMP6_ND_NA,
+	ITEM_ICMP6_ND_OPT_SLA_ETH,
+	ITEM_ICMP6_ND_OPT_TLA_ETH,
 	ZERO,
 };
 
@@ -586,6 +607,39 @@ static const enum index item_geneve[] = {
 	ZERO,
 };
 
+static const enum index item_ipv6_ext[] = {
+	ITEM_IPV6_EXT_NEXT_HDR,
+	ZERO,
+};
+
+static const enum index item_icmp6[] = {
+	ITEM_ICMP6_TYPE,
+	ITEM_ICMP6_CODE,
+	ZERO,
+};
+
+static const enum index item_icmp6_nd_ns[] = {
+	ITEM_ICMP6_ND_NS_TGT_ADDR,
+	ZERO,
+};
+
+static const enum index item_icmp6_nd_na[] = {
+	ITEM_ICMP6_ND_NA_TGT_ADDR,
+	ZERO,
+};
+
+static const enum index item_icmp6_nd_opt_sla_eth[] = {
+	ITEM_ICMP6_ND_OPT_SLA_ETH_TGT_ADDR,
+	ITEM_ICMP6_ND_OPT_SLA_ETH_SLL_ADDR,
+	ZERO,
+};
+
+static const enum index item_icmp6_nd_opt_tla_eth[] = {
+	ITEM_ICMP6_ND_OPT_TLA_ETH_TGT_ADDR,
+	ITEM_ICMP6_ND_OPT_TLA_ETH_TLL_ADDR,
+	ZERO,
+};
+
 static const enum index next_action[] = {
 	ACTION_END,
 	ACTION_VOID,
@@ -1473,6 +1527,126 @@ static const struct token token_list[] = {
 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve,
 					     protocol)),
 	},
+	[ITEM_IPV6_EXT] = {
+		.name = "ext",
+		.help = "match IPv6 extend header",
+		.priv = PRIV_ITEM(IPV6_EXT,
+				  sizeof(struct rte_flow_item_ipv6_ext)),
+		.next = NEXT(item_ipv6_ext),
+		.call = parse_vc,
+	},
+	[ITEM_IPV6_EXT_NEXT_HDR] = {
+		.name = "next",
+		.help = "next header in IPv6 extend header",
+		.next = NEXT(item_ipv6_ext, NEXT_ENTRY(UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_ext,
+					     next_hdr)),
+	},
+	[ITEM_ICMP6] = {
+		.name = "icmp6",
+		.help = "match ICMPv6 header",
+		.priv = PRIV_ITEM(ICMP, sizeof(struct rte_flow_item_icmp6)),
+		.next = NEXT(item_icmp6),
+		.call = parse_vc,
+	},
+	[ITEM_ICMP6_TYPE] = {
+		.name = "type",
+		.help = "ICMPv6 packet type",
+		.next = NEXT(item_icmp6, NEXT_ENTRY(UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6,
+					     type)),
+	},
+	[ITEM_ICMP6_CODE] = {
+		.name = "code",
+		.help = "ICMPv6 packet code",
+		.next = NEXT(item_icmp6, NEXT_ENTRY(UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6,
+					     code)),
+	},
+	[ITEM_ICMP6_ND_NS] = {
+		.name = "ns",
+		.help = "match neighbor solicitation over ICMPv6 ",
+		.priv = PRIV_ITEM(ICMP6_ND_NS,
+				  sizeof(struct rte_flow_item_icmp6_nd_ns)),
+		.next = NEXT(item_icmp6_nd_ns),
+		.call = parse_vc,
+	},
+	[ITEM_ICMP6_ND_NS_TGT_ADDR] = {
+		.name = "tgt_addr",
+		.help = "target address of neighbor solicitation",
+		.next = NEXT(item_icmp6_nd_ns, NEXT_ENTRY(UNSIGNED),
+			     item_param),
+		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_ns,
+					     target_addr)),
+	},
+	[ITEM_ICMP6_ND_NA] = {
+		.name = "na",
+		.help = "match neighbor advertisement over ICMPv6 ",
+		.priv = PRIV_ITEM(ICMP6_ND_NA,
+				  sizeof(struct rte_flow_item_icmp6_nd_na)),
+		.next = NEXT(item_icmp6_nd_na),
+		.call = parse_vc,
+	},
+	[ITEM_ICMP6_ND_NA_TGT_ADDR] = {
+		.name = "tgt_addr",
+		.help = "target address of neighbor advertisement",
+		.next = NEXT(item_icmp6_nd_na, NEXT_ENTRY(UNSIGNED),
+			     item_param),
+		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_na,
+					     target_addr)),
+	},
+	[ITEM_ICMP6_ND_OPT_SLA_ETH] = {
+		.name = "sla",
+		.help = "match source link-layer address over neighbor solicitation",
+		.priv = PRIV_ITEM(ICMP6_ND_OPT_SLA_ETH,
+			  sizeof(struct rte_flow_item_icmp6_nd_opt_sla_eth)),
+		.next = NEXT(item_icmp6_nd_opt_sla_eth),
+		.call = parse_vc,
+	},
+	[ITEM_ICMP6_ND_OPT_SLA_ETH_TGT_ADDR] = {
+		.name = "tgt_addr",
+		.help = "target address of neighbor solicitation",
+		.next = NEXT(item_icmp6_nd_opt_sla_eth, NEXT_ENTRY(UNSIGNED),
+			     item_param),
+		.args = ARGS(ARGS_ENTRY_HTON(
+			     struct rte_flow_item_icmp6_nd_opt_sla_eth,
+			     target_addr)),
+	},
+	[ITEM_ICMP6_ND_OPT_SLA_ETH_SLL_ADDR] = {
+		.name = "sll_addr",
+		.help = "source link-layer address over neighbor solicitation",
+		.next = NEXT(item_icmp6_nd_opt_sla_eth, NEXT_ENTRY(UNSIGNED),
+			     item_param),
+		.args = ARGS(ARGS_ENTRY_HTON(
+			     struct rte_flow_item_icmp6_nd_opt_sla_eth,
+			     sll_addr)),
+	},
+	[ITEM_ICMP6_ND_OPT_TLA_ETH] = {
+		.name = "tla",
+		.help = "match target link-layer address over neighbor advertisement",
+		.priv = PRIV_ITEM(ICMP6_ND_OPT_TLA_ETH,
+			  sizeof(struct rte_flow_item_icmp6_nd_opt_tla_eth)),
+		.next = NEXT(item_icmp6_nd_opt_tla_eth),
+		.call = parse_vc,
+	},
+	[ITEM_ICMP6_ND_OPT_TLA_ETH_TGT_ADDR] = {
+		.name = "tgt_addr",
+		.help = "target address of neighbor advertisement",
+		.next = NEXT(item_icmp6_nd_opt_tla_eth, NEXT_ENTRY(UNSIGNED),
+			     item_param),
+		.args = ARGS(ARGS_ENTRY_HTON(
+			     struct rte_flow_item_icmp6_nd_opt_tla_eth,
+			     target_addr)),
+	},
+	[ITEM_ICMP6_ND_OPT_TLA_ETH_TLL_ADDR] = {
+		.name = "tll_addr",
+		.help = "target link-layer address over neighbor advertisement",
+		.next = NEXT(item_icmp6_nd_opt_tla_eth, NEXT_ENTRY(UNSIGNED),
+			     item_param),
+		.args = ARGS(ARGS_ENTRY_HTON(
+			     struct rte_flow_item_icmp6_nd_opt_tla_eth,
+			     tll_addr)),
+	},
 
 	/* Validate/create actions. */
 	[ACTIONS] = {
diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
index 4bb255c62..4cd56bf26 100644
--- a/app/test-pmd/config.c
+++ b/app/test-pmd/config.c
@@ -980,6 +980,14 @@ static const struct {
 	MK_FLOW_ITEM(GTPC, sizeof(struct rte_flow_item_gtp)),
 	MK_FLOW_ITEM(GTPU, sizeof(struct rte_flow_item_gtp)),
 	MK_FLOW_ITEM(GENEVE, sizeof(struct rte_flow_item_geneve)),
+	MK_FLOW_ITEM(IPV6_EXT, sizeof(struct rte_flow_item_ipv6_ext)),
+	MK_FLOW_ITEM(ICMP6, sizeof(struct rte_flow_item_icmp6)),
+	MK_FLOW_ITEM(ICMP6_ND_NS, sizeof(struct rte_flow_item_icmp6_nd_ns)),
+	MK_FLOW_ITEM(ICMP6_ND_NA, sizeof(struct rte_flow_item_icmp6_nd_na)),
+	MK_FLOW_ITEM(ICMP6_ND_OPT_SLA_ETH,
+		     sizeof(struct rte_flow_item_icmp6_nd_opt_sla_eth)),
+	MK_FLOW_ITEM(ICMP6_ND_OPT_TLA_ETH,
+		     sizeof(struct rte_flow_item_icmp6_nd_opt_tla_eth)),
 };
 
 /** Compute storage space needed by item specification. */
diff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst
index 961943dda..9c9ddcbd2 100644
--- a/doc/guides/prog_guide/rte_flow.rst
+++ b/doc/guides/prog_guide/rte_flow.rst
@@ -992,6 +992,78 @@ Matches a GENEVE header.
 - ``rsvd1``: reserved, normally 0x00.
 - Default ``mask`` matches VNI only.
 
+Item: ``IPV6_EXT``
+^^^^^^^^^^^^^^^^^^
+
+Matches an IPv6 Extension header with any type.
+
+- ``next_hdr``: protocol of next header.
+- Default ``mask`` matches protocal of next header.
+
+Item: ``ICMP6``
+^^^^^^^^^^^^^^^
+
+Matches an ICMPv6 header followed by any message body.
+
+- ``type``: ICMPv6 type.
+- ``code``: ICMPv6 code.
+- ``checksume``: ICMPv6 checksume.
+- Default ``mask`` matches type and code only.
+
+Item: ``ICMP6_ND_NS``
+^^^^^^^^^^^^^^^^^^^^^
+
+Matches an ICMPv6 header followed by network discvoery neighbor solicitation,
+
+- ``type``: ICMPv6 type, normally 135.
+- ``code``: ICMPv6 code, normally 0.
+- ``checksume``: ICMPv6 checksume.
+- ``reserved``: reserved, normally 0x00.
+- ``tgt_addr``: target address of neighbor solicitation.
+- Default ``mask`` matches target address only.
+
+Item: ``ICMP6_ND_NA``
+^^^^^^^^^^^^^^^^^^^^^
+
+Matches an ICMPv6 header followed by network discvoery neighbor advertisement,
+
+- ``type``: ICMPv6 type, normally 136.
+- ``code``: ICMPv6 code, normally 0.
+- ``checksume``: ICMPv6 checksume.
+- ``rso_reserved``: route flag (1b), solicited flag (1b), override flag (1b),
+  reserved (29b).
+- ``tgt_addr``: target address of neighbor advertisement.
+- Default ``mask`` matches target address only.
+
+Item: ``ICMP6_ND_OPT_SLA_ETH``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Matches an ICMPv6 header followed by network discvoery neighbor solicitation
+that contains source Ethernet link-layer address option.
+
+- ``type``: ICMPv6 type, normally 135.
+- ``code``: ICMPv6 code, normally 0.
+- ``checksume``: ICMPv6 checksume.
+- ``reserved``: reserved, normally 0x00.
+- ``tgt_addr``: target address of neighbor solicitation.
+- ``sll_ADDR``: source Ethernet link-layer address.
+- Default ``mask`` matches target address and source link-layer address only.
+
+Item: ``ICMP6_ND_OPT_TLA_ETH``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Matches an ICMPv6 header followed by network discvoery neighbor advertisement.
+that contains target Ethernet link-layer address option.
+
+- ``type``: ICMPv6 type, normally 136.
+- ``code``: ICMPv6 code, normally 0.
+- ``checksume``: ICMPv6 checksume.
+- ``rso_reserved``: route flag (1b), solicited flag (1b), override flag (1b),
+  reserved (29b).
+- ``tgt_addr``: target address of neighbor advertisement.
+- ``tll_ADDR``: target Ethernet link-layer address.
+- Default ``mask`` matches target address and target link-layer address only.
+
 Actions
 ~~~~~~~
 
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index a766ac795..48688600e 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -3305,6 +3305,33 @@ This section lists supported pattern items and their attributes, if any.
   - ``vni {unsigned}``: virtual network identifier.
   - ``protocol {unsigned}``: protocol type.
 
+- ``ext``: match IPv6 extend header.
+
+  - ``next {unsigned}``: protocol (next header).
+
+- ``icmp6``: match ICMPv6 header.
+
+  - ``type {unsgined}``: ICMPv6 packet type.
+  - ``code {unsigned}``: ICMPv6 packet code.
+
+- ``ns``: match neighbor solicitation over ICMPv6.
+
+  - ``tgt_addr {ipv6 address}``: target address of neighbor solicitation.
+
+- ``na``: match neighbor advertisement over ICMPv6.
+
+  - ``tgt_addr {ipv6 address}``: target address of neighbor advertisement.
+
+- ``sla``: match source link-layer address over neighbor solicitation.
+
+  - ``tgt_addr {ipv6 address}``: target address of neighbor solicitation.
+  - ``sll_addr {MAC-48}``: source link-layer address over neightbor solicitation.
+
+- ``tla``: match target link-layer address over neighbor advertisement.
+
+  - ``tgt_addr {ipv6 address}``: target address of neighbor advertisement.
+  - ``tll_addr {MAC-48}``: target link-layer address over neightbor advertisement.
+
 Actions list
 ^^^^^^^^^^^^
 
diff --git a/lib/librte_ether/rte_flow.h b/lib/librte_ether/rte_flow.h
index 56c733451..2efbfb3c4 100644
--- a/lib/librte_ether/rte_flow.h
+++ b/lib/librte_ether/rte_flow.h
@@ -323,6 +323,61 @@ enum rte_flow_item_type {
 	 * See struct rte_flow_item_geneve.
 	 */
 	RTE_FLOW_ITEM_TYPE_GENEVE,
+
+	/**
+	 * Matches an IPv4 ARP header.
+	 *
+	 * See struct rte_flow_item_arp.
+	 */
+	RTE_FLOW_ITEM_TYPE_ARP_IPV4,
+
+	/**
+	 * Matches an IPv6 Extension header with any type.
+	 *
+	 * See struct rte_flow_item_ipv6_ext.
+	 */
+	RTE_FLOW_ITEM_TYPE_IPV6_EXT,
+
+	/**
+	 * Matches an ICMPv6 header followed by any message body.
+	 *
+	 * See struct rte_flow_item_icmp6.
+	 */
+	RTE_FLOW_ITEM_TYPE_ICMP6,
+
+	/**
+	 * Matches an ICMPv6 header followed by network discovery
+	 * neighbor solicitation.
+	 *
+	 * See struct rte_flow_item_icmp6_nd_ns.
+	 */
+	RTE_FLOW_ITEM_TYPE_ICMP6_ND_NS,
+
+	/**
+	 * Matches an ICMPv6 header followed by network discovery
+	 * neighbor advertisement.
+	 *
+	 * See struct rte_flow_item_icmp6_nd_na.
+	 */
+	RTE_FLOW_ITEM_TYPE_ICMP6_ND_NA,
+
+	/**
+	 * Matches an ICMPv6 header followed by network discovery neighbor
+	 * solicitation that contains source Ethernet link-layer address
+	 * option.
+	 *
+	 * See struct rte_flow_item_icmp6_nd_opt_sla_eth.
+	 */
+	RTE_FLOW_ITEM_TYPE_ICMP6_ND_OPT_SLA_ETH,
+
+	/**
+	 * Matches an ICMPv6 header followed by network discovery neighbor
+	 * advertisement that contains target Ethernet link-layer address
+	 * option.
+	 *
+	 * See struct rte_flow_item_icmp6_nd_opt_tla_eth.
+	 */
+	RTE_FLOW_ITEM_TYPE_ICMP6_ND_OPT_TLA_ETH,
 };
 
 /**
@@ -815,6 +870,182 @@ static const struct rte_flow_item_geneve rte_flow_item_geneve_mask = {
 #endif
 
 /**
+ * RTE_FLOW_ITEM_TYPE_ARP_IPV4
+ *
+ * Matches an IPv4 ARP header.
+ */
+struct rte_flow_item_arp {
+	struct arp_hdr hdr; /**< ARP header. */
+};
+
+/** Default mask for RTE_FLOW_ITEM_TYPE_ARP_IPV4. */
+#ifndef __cplusplus
+static const struct rte_flow_item_arp rte_flow_item_arp_mask = {
+	.hdr = {
+		.arp_data = {
+			.arp_sha = {
+				.addr_bytes = "\xff\xff\xff\xff\xff\xff",
+			},
+			.arp_sip = RTE_BE32(0xffffffff),
+			.arp_tha = {
+				.addr_bytes = "\xff\xff\xff\xff\xff\xff",
+			},
+			.arp_tip = RTE_BE32(0xffffffff),
+		},
+	},
+};
+#endif
+
+/**
+ * RTE_FLOW_ITEM_TYPE_IPV6_EXT
+ *
+ * Matches an IPv6 extension header with any type.
+ */
+struct rte_flow_item_ipv6_ext {
+	uint8_t next_hdr; /**< protocol of next  header */
+};
+
+/** Default mask for RTE_FLOW_ITEM_TYPE_IPV6_EXT. */
+#ifndef __cplusplus
+static const
+struct rte_flow_item_ipv6_ext rte_flow_item_ipv6_ext_mask = {
+	.next_hdr = 0xff,
+};
+#endif
+
+/**
+ * RTE_FLOW_ITEM_TYPE_ICMP6
+ *
+ * Matches an ICMPv6 header followed by any message body.
+ */
+struct rte_flow_item_icmp6 {
+	uint8_t type; /**< ICMPv6 type. */
+	uint8_t code; /**< ICMPv6 code. */
+	uint16_t checksum; /**< ICMPv6 checksum. */
+};
+
+/** Default mask for RTE_FLOW_ITEM_TYPE_ICMP6. */
+#ifndef __cplusplus
+static const struct rte_flow_item_icmp6 rte_flow_item_icmp6_mask = {
+	.type = 0xff,
+	.code = 0xff,
+};
+#endif
+
+/**
+ * RTE_FLOW_ITEM_TYPE_ICMP6_ND_NS
+ *
+ * Matches an ICMP6 header followed by network discovery
+ * neighbor solicitation.
+ */
+struct rte_flow_item_icmp6_nd_ns {
+	uint8_t type; /**< ICMPv6 type, normally 135. */
+	uint8_t code; /**< ICMPv6 code, normally 0. */
+	rte_be16_t checksum; /**< ICMPv6 checksum. */
+	rte_be32_t reserved;
+	uint8_t target_addr[16]; /**< Target address. */
+};
+
+/** Default mask for RTE_FLOW_ITEM_TYPE_ICMP6_ND_NS */
+#ifndef __cplusplus
+static const
+struct rte_flow_item_icmp6_nd_ns rte_flow_item_icmp6_nd_ns_mask = {
+	.target_addr =
+		"\xff\xff\xff\xff\xff\xff\xff\xff"
+		"\xff\xff\xff\xff\xff\xff\xff\xff",
+};
+#endif
+
+/**
+ * RTE_FLOW_ITEM_TYPE_ICMP6_ND_NA
+ *
+ * Matches an ICMPv6 header followed by network discovery
+ * neighbor advertisement.
+ */
+struct rte_flow_item_icmp6_nd_na {
+	uint8_t type; /**< ICMPv6 type, normally 136. */
+	uint8_t code; /**< ICMPv6 code, normally 0. */
+	rte_be16_t checksum; /**< ICMPv6 checksum. */
+	/**
+	 * Route flag (1b), solicited flag (1b), override flag (1b),
+	 * reserved (29b).
+	 */
+	rte_be32_t rso_reserved;
+	uint8_t target_addr[16]; /**< Target address. */
+};
+
+/** Default mask for RTE_FLOW_ITEM_TYPE_ICMP6_ND_NA. */
+#ifndef __cplusplus
+static const
+struct rte_flow_item_icmp6_nd_na rte_flow_item_icmp6_nd_na_mask = {
+	.target_addr =
+		"\xff\xff\xff\xff\xff\xff\xff\xff"
+		"\xff\xff\xff\xff\xff\xff\xff\xff",
+};
+#endif
+
+/**
+ * RTE_FLOW_ITEM_TYPE_ICMP6_ND_OPT_SLA_ETH
+ *
+ * Matches an ICMPv6 header followed by network discovery neighbor
+ * solicitation that contains source Ethernet link-layer address option.
+ */
+struct rte_flow_item_icmp6_nd_opt_sla_eth {
+	uint8_t type; /**< ICMPv6 type, normally 135. */
+	uint8_t code; /**< ICMPv6 code, normally 0. */
+	rte_be16_t checksum; /**< ICMPv6 checksum. */
+	rte_be32_t reserved;
+	uint8_t target_addr[16]; /**< Target address. */
+	struct ether_addr sll_addr; /**< Source Ethernet link-layer address. */
+};
+
+/** Default mask for RTE_FLOW_ITEM_TYPE_ICMP6_ND_OPT_SLA_ETH. */
+#ifndef __cplusplus
+static const struct rte_flow_item_icmp6_nd_opt_sla_eth
+	rte_flow_item_icmp6_nd_opt_sla_eth_mask = {
+	.target_addr =
+		"\xff\xff\xff\xff\xff\xff\xff\xff"
+		"\xff\xff\xff\xff\xff\xff\xff\xff",
+	.sll_addr = {
+		.addr_bytes = "\xff\xff\xff\xff\xff\xff",
+	}
+};
+#endif
+
+/**
+ * RTE_FLOW_ITEM_TYPE_ICMP6_ND_OPT_TLA_ETH
+ *
+ * Matches an ICMPv6 header followed by network discovery neighbor
+ * advertisement that contains target Ethernet link-layer address option.
+ */
+struct rte_flow_item_icmp6_nd_opt_tla_eth {
+	uint8_t type; /**< ICMPv6 type, normally 136. */
+	uint8_t code; /**< ICMPv6 code, normally 0. */
+	rte_be16_t checksum; /**< ICMPv6 checksum. */
+	/**
+	 * Route flag (1b), solicited flag (1b), override flag (1b),
+	 * reserved (29b).
+	 */
+	rte_be32_t rso_reserved;
+	uint8_t target_addr[16]; /**< Target address. */
+	struct ether_addr tll_addr; /**< Target Ethernet link-layer address. */
+
+};
+
+/** Default mask for RTE_FLOW_ITEM_TYPE_ICMP6_ND_OPT_TLA_ETH. */
+#ifndef __cplusplus
+static const struct rte_flow_item_icmp6_nd_opt_tla_eth
+	rte_flow_item_icmp6_nd_opt_tla_eth_mask = {
+	.target_addr =
+		"\xff\xff\xff\xff\xff\xff\xff\xff"
+		"\xff\xff\xff\xff\xff\xff\xff\xff",
+	.tll_addr = {
+		.addr_bytes = "\xff\xff\xff\xff\xff\xff",
+	}
+};
+#endif
+
+/**
  * Matching pattern item definition.
  *
  * A pattern is formed by stacking items starting from the lowest protocol
-- 
2.13.6

^ permalink raw reply	[flat|nested] 61+ messages in thread

* [dpdk-dev] [PATCH v3 2/4] ethdev: add packet field set aciton in flow API
  2018-04-16  5:16 ` [dpdk-dev] [PATCH v3 " Qi Zhang
  2018-04-16  5:16   ` [dpdk-dev] [PATCH v3 1/4] ethdev: add more protocol support in flow API Qi Zhang
@ 2018-04-16  5:16   ` Qi Zhang
  2018-04-16  5:16   ` [dpdk-dev] [PATCH v3 3/4] ethdev: add TTL change actions " Qi Zhang
  2018-04-16  5:16   ` [dpdk-dev] [PATCH v3 4/4] ethdev: add VLAN and MPLS pop push action " Qi Zhang
  3 siblings, 0 replies; 61+ messages in thread
From: Qi Zhang @ 2018-04-16  5:16 UTC (permalink / raw)
  To: adrien.mazarguil
  Cc: dev, declan.doherty, sugesh.chandran, michael.j.glynn, yu.y.liu,
	konstantin.ananyev, bruce.richardson, Qi Zhang

Add new action RTE_FLOW_ACTION_TYPE_FIELD_SET, it is used to
modify fields of specific protocol layer of the packet, for
packet that does not include the specific protocal layer, the
action is skipped.

Signed-off-by: Qi Zhang <qi.z.zhang@intel.com>
---
 doc/guides/prog_guide/rte_flow.rst | 30 +++++++++++++++++++++++++++
 lib/librte_ether/rte_flow.h        | 42 +++++++++++++++++++++++++++++++++++++-
 2 files changed, 71 insertions(+), 1 deletion(-)

diff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst
index 9c9ddcbd2..ea0e40a52 100644
--- a/doc/guides/prog_guide/rte_flow.rst
+++ b/doc/guides/prog_guide/rte_flow.rst
@@ -1558,6 +1558,36 @@ fields in the pattern items.
    | 1     | END      |
    +-------+----------+
 
+Action: ``FILED_SET``
+^^^^^^^^^^^^^^^^^^^^^
+
+Modify the value of fields in a protocol layer, only applies to packets that
+contain respective protocol layer.
+
+.. _table_rte_flow_action_field_set:
+
+.. table:: FIELD_SET
+
+   +---------------+-------------------------------------------------------------------+
+   | Field         | Value                                                             |
+   +===============+===================================================================+
+   | ``type``      | Specify the type of a protocol layer. (see RTE_FLOW_ITEM_TYPE_*)  |
+   +---------------+-------------------------------------------------------------------+
+   | ``dir_level`` | Specify the level of matched protocol layer.                      |
+   |               | direction (1b)                                                    |
+   |               | 0: match start from outermost.                                    |
+   |               | 1: match start from innermost.                                    |
+   |               | level: (31b)                                                      |
+   |               | 0: outermost or innermost protocol layer that matched @type       |
+   |               | 1: next to outmost or innermost protocol layer that matched @type |
+   |               | 2: and so on ...                                                  |
+   +---------------+-------------------------------------------------------------------+
+   |  ``new_val``  | Pointer to specific data structure according to protocol type,    |
+   |               | the content is the new value to updtae.                           |
+   +---------------+-------------------------------------------------------------------+
+   |  ``mask``     | Bit-mask applied to new_val                                       |
+   +---------------+-------------------------------------------------------------------+
+
 Negative types
 ~~~~~~~~~~~~~~
 
diff --git a/lib/librte_ether/rte_flow.h b/lib/librte_ether/rte_flow.h
index 2efbfb3c4..80cf75ff0 100644
--- a/lib/librte_ether/rte_flow.h
+++ b/lib/librte_ether/rte_flow.h
@@ -1241,7 +1241,15 @@ enum rte_flow_action_type {
 	 *
 	 * See struct rte_flow_action_security.
 	 */
-	RTE_FLOW_ACTION_TYPE_SECURITY
+	RTE_FLOW_ACTION_TYPE_SECURITY,
+
+	/**
+	 * Modify the value of fields in a protocol layer, only applies to
+	 * packets that contain respective protocol layer.
+	 *
+	 * See struct rte_flow_action_field_set.
+	 */
+	RTE_FLOW_ACTION_TYPE_FIELD_SET,
 };
 
 /**
@@ -1380,6 +1388,38 @@ struct rte_flow_action_security {
 };
 
 /**
+ * RTE_FLOW_ACTION_TYPE_FIELD_SET
+ *
+ * Modify the value of fields in a protocol layer, only applies to
+ * packets that contain respective protocol layer.
+ */
+struct rte_flow_action_field_set {
+	/**
+	 * Specify the type of a protocol layer.
+	 */
+	enum rte_flow_item_type type;
+	/**
+	 * Specify the level of matched protocol layer.
+	 *
+	 * direction (1b)
+	 * 0: match start from outermost.
+	 * 1: match start from innermost.
+	 *
+	 * level (31b)
+	 * 0: outermost|innermost protocol layer that matched @type.
+	 * 1: next to outermost|innermost protocol layer that matched @type.
+	 * 2: and so on ...
+	 */
+	uint32_t dir_level;
+	/**
+	 * Pointer to specific data structure according to protocol type,
+	 * the content is the new value to update.
+	 */
+	const void *new_val;
+	const void *mask; /**< Bit-mask applied to new_val. */
+};
+
+/**
  * Definition of a single action.
  *
  * A list of actions is terminated by a END action.
-- 
2.13.6

^ permalink raw reply	[flat|nested] 61+ messages in thread

* [dpdk-dev] [PATCH v3 3/4] ethdev: add TTL change actions in flow API
  2018-04-16  5:16 ` [dpdk-dev] [PATCH v3 " Qi Zhang
  2018-04-16  5:16   ` [dpdk-dev] [PATCH v3 1/4] ethdev: add more protocol support in flow API Qi Zhang
  2018-04-16  5:16   ` [dpdk-dev] [PATCH v3 2/4] ethdev: add packet field set aciton " Qi Zhang
@ 2018-04-16  5:16   ` Qi Zhang
  2018-04-16  5:48     ` Shahaf Shuler
  2018-04-16  5:16   ` [dpdk-dev] [PATCH v3 4/4] ethdev: add VLAN and MPLS pop push action " Qi Zhang
  3 siblings, 1 reply; 61+ messages in thread
From: Qi Zhang @ 2018-04-16  5:16 UTC (permalink / raw)
  To: adrien.mazarguil
  Cc: dev, declan.doherty, sugesh.chandran, michael.j.glynn, yu.y.liu,
	konstantin.ananyev, bruce.richardson, Qi Zhang

Add couple OpenFlow frienldy TTL change actions.

RTE_FLOW_ACTION_MLPS_TTL_DEC - decrement MPLS TTL.
RTE_FLOW_ACTION_IP_TTL_DEC - decrement IP TTL.
RTE_FLOW_ACTION_TTL_COPY_OUT - copy TTL outwards.
RTE_FLOW_ACTION_TTL_COPY_IN - copy TTL inwards.

Signed-off-by: Qi Zhang <qi.z.zhang@intel.com>
---
 app/test-pmd/cmdline_flow.c                 | 64 +++++++++++++++++++++++
 doc/guides/prog_guide/rte_flow.rst          | 80 +++++++++++++++++++++++++++++
 doc/guides/testpmd_app_ug/testpmd_funcs.rst | 12 +++++
 lib/librte_ether/rte_flow.h                 | 77 +++++++++++++++++++++++++++
 4 files changed, 233 insertions(+)

diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c
index a5e21c1fe..fa35ecc6d 100644
--- a/app/test-pmd/cmdline_flow.c
+++ b/app/test-pmd/cmdline_flow.c
@@ -190,6 +190,12 @@ enum index {
 	ACTION_VF_ID,
 	ACTION_METER,
 	ACTION_METER_ID,
+	ACTION_MPLS_TTL_DEC,
+	ACTION_MPLS_TTL_DEC_LVL,
+	ACTION_IP_TTL_DEC,
+	ACTION_IP_TTL_DEC_LVL,
+	ACTION_TTL_COPY_OUT,
+	ACTION_TTL_COPY_IN,
 };
 
 /** Size of pattern[] field in struct rte_flow_item_raw. */
@@ -654,6 +660,10 @@ static const enum index next_action[] = {
 	ACTION_PF,
 	ACTION_VF,
 	ACTION_METER,
+	ACTION_MPLS_TTL_DEC,
+	ACTION_IP_TTL_DEC,
+	ACTION_TTL_COPY_OUT,
+	ACTION_TTL_COPY_IN,
 	ZERO,
 };
 
@@ -694,6 +704,16 @@ static const enum index action_meter[] = {
 	ZERO,
 };
 
+static const enum index action_mpls_ttl_dec[] = {
+	ACTION_MPLS_TTL_DEC_LVL,
+	ZERO,
+};
+
+static const enum index action_ip_ttl_dec[] = {
+	ACTION_IP_TTL_DEC_LVL,
+	ZERO,
+};
+
 static int parse_init(struct context *, const struct token *,
 		      const char *, unsigned int,
 		      void *, unsigned int);
@@ -1807,6 +1827,50 @@ static const struct token token_list[] = {
 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter, mtr_id)),
 		.call = parse_vc_conf,
 	},
+	[ACTION_MPLS_TTL_DEC] = {
+		.name = "mpls_ttl_dec",
+		.help = "decrement MPLS TTL",
+		.priv = PRIV_ACTION(MPLS_TTL_DEC,
+				sizeof(struct rte_flow_action_mpls_ttl_dec)),
+		.next = NEXT(action_mpls_ttl_dec),
+		.call = parse_vc,
+	},
+	[ACTION_MPLS_TTL_DEC_LVL] = {
+		.name = "level",
+		.help = "level of MPLS header",
+		.next = NEXT(action_mpls_ttl_dec, NEXT_ENTRY(UNSIGNED)),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_queue, index)),
+		.call = parse_vc,
+	},
+	[ACTION_IP_TTL_DEC] = {
+		.name = "ip_ttl_dec",
+		.help = "decrement IPv4 TTL or IPv6 Hop Limit",
+		.priv = PRIV_ACTION(MPLS_TTL_DEC,
+				sizeof(struct rte_flow_action_ip_ttl_dec)),
+		.next = NEXT(action_ip_ttl_dec),
+		.call = parse_vc,
+	},
+	[ACTION_IP_TTL_DEC_LVL] = {
+		.name = "level",
+		.help = "level of IPv4 or IPv6 header",
+		.next = NEXT(action_ip_ttl_dec, NEXT_ENTRY(UNSIGNED)),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_queue, index)),
+		.call = parse_vc,
+	},
+	[ACTION_TTL_COPY_OUT] = {
+		.name = "ttl_copy_out",
+		.help = "copy TTL  outwards",
+		.priv = PRIV_ACTION(DROP, 0),
+		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
+		.call = parse_vc,
+	},
+	[ACTION_TTL_COPY_IN] = {
+		.name = "ttl_copy_in",
+		.help = "copy TTL  inwards",
+		.priv = PRIV_ACTION(DROP, 0),
+		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
+		.call = parse_vc,
+	},
 };
 
 /** Remove and return last entry from argument stack. */
diff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst
index ea0e40a52..e81f0e375 100644
--- a/doc/guides/prog_guide/rte_flow.rst
+++ b/doc/guides/prog_guide/rte_flow.rst
@@ -1588,6 +1588,86 @@ contain respective protocol layer.
    |  ``mask``     | Bit-mask applied to new_val                                       |
    +---------------+-------------------------------------------------------------------+
 
+Action: ``MPLS_TTL_DEC``
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+Decrement MPLS TTL, only applies to packets that contain specific MPLS
+headers.
+
+.. _table_rte_flow_action_mpls_ttl_dec:
+
+.. table:: MPLS_TTL_DEC
+
+   +---------------+---------------------------------------------+
+   | Field         | Value                                       |
+   +===============+=============================================+
+   | ``dir_level`` | Specify the level of MPLS header.           |
+   |               | direction (1b)                              |
+   |               | 0: match start from outermost.              |
+   |               | 1: match start from innermost.              |
+   |               | level: (31b)                                |
+   |               | 0: outermost or innermost MPLS header       |
+   |               | 1: next to outmost or innermost MPLS header |
+   |               | 2: and so on ...                            |
+   +---------------+---------------------------------------------+
+
+Action: ``IP_TTL_DEC``
+^^^^^^^^^^^^^^^^^^^^^^
+
+Decrement IPv4 TTL or IPv6 hop limit field and update the IP checksum,
+only applies to packets that contain specific MPLS headers.
+
+.. _table_rte_flow_action_ip_ttl_dec:
+
+.. table:: IP_TTL_DEC
+
+   +---------------+----------------------------------------------------------+
+   | Field         | Value                                                    |
+   +===============+==========================================================+
+   | ``dir_level`` | Specify the level of IPv4 or IPv6 header.                |
+   |               | direction (1b)                                           |
+   |               | 0: match start from outermost.                           |
+   |               | 1: match start from innermost.                           |
+   |               | level: (31b)                                             |
+   |               | 0: outermost or innermost Ipv4 or IPv6 header            |
+   |               | 1: next to outmost or innermost MPLS IPv4 or IPv6 header |
+   |               | 2: and so on ...                                         |
+   +---------------+----------------------------------------------------------+
+
+Action: ``TTL_COPY_OUT``
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+Copy the TTL from next-to-outermost to outermost header with TTL, copy can
+be IP to IP, MPLS to MPLS or IP to MPLS, only applies packets that contain
+required MPLS or IP headers.
+
+.. _table_rte_flow_action_ttl_copy_out:
+
+.. table:: TTL_COPY_OUT
+
+   +---------------+
+   | Field         |
+   +===============+
+   | no properties |
+   +---------------+
+
+Action: ``TTL_COPY_IN``
+^^^^^^^^^^^^^^^^^^^^^^^
+
+Copy the TTL from outermost to next-to-outermost header with TTL, copy can
+be IP to IP, MPLS to MPLS or MPLS to IP, only applies packets that contain
+required MPLS or IP headers.
+
+.. _table_rte_flow_action_ttl_copy_in:
+
+.. table:: TTL_COPY_IN
+
+   +---------------+
+   | Field         |
+   +===============+
+   | no properties |
+   +---------------+
+
 Negative types
 ~~~~~~~~~~~~~~
 
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index 48688600e..4dd86f10e 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -3442,6 +3442,18 @@ This section lists supported actions and their attributes, if any.
   - ``original {boolean}``: use original VF ID if possible.
   - ``id {unsigned}``: VF ID to redirect packets to.
 
+- ``mpls_ttl_dec``: decrement MPLS TTL.
+
+  - ``level``: level of MPLS header.
+
+- ``ip_ttl_dec``: decrement IPv4 TTL or IPv6 Hot Limit.
+
+  - ``level``: level of IPv4 or IPv6 header.
+
+- ``ttl_copy_out``: copy TTL outwards.
+
+- ``ttl_copy_in``: copy TTL inwards.
+
 Destroying flow rules
 ~~~~~~~~~~~~~~~~~~~~~
 
diff --git a/lib/librte_ether/rte_flow.h b/lib/librte_ether/rte_flow.h
index 80cf75ff0..96a236945 100644
--- a/lib/librte_ether/rte_flow.h
+++ b/lib/librte_ether/rte_flow.h
@@ -1250,6 +1250,37 @@ enum rte_flow_action_type {
 	 * See struct rte_flow_action_field_set.
 	 */
 	RTE_FLOW_ACTION_TYPE_FIELD_SET,
+
+	/**
+	 * Decrement MPLS TTL, only applies to packets that contain specific
+	 * MPLS header.
+	 *
+	 * See struct rte_flow_action_mpls_ttl_dec.
+	 */
+	RTE_FLOW_ACTION_TYPE_MPLS_TTL_DEC,
+
+	/**
+	 * Decrement IPv4 TTL or IPv6 Hop limit field and update the IP
+	 * checksum, only applies to packets that contain specific IPv4
+	 * or IPv6 header.
+	 *
+	 * See struct rte_flow_action_ip_ttl_dec.
+	 */
+	RTE_FLOW_ACTION_TYPE_IP_TTL_DEC,
+
+	/**
+	 * Copy the TTL from next-to-outermost to outermost header with TTL,
+	 * copy can be IP to IP, MPLS to MPLS or IP to MPLS, only applies
+	 * packets that contain required protocol headers.
+	 */
+	RTE_FLOW_ACTION_TYPE_TTL_COPY_OUT,
+
+	/**
+	 * Copy the TTL from outermost to next-to-outermost header with TTL,
+	 * copy can be IP to IP, MPLS to MPLS or MPLS to IP, only applies
+	 * packets that contain required protocol headers.
+	 */
+	RTE_FLOW_ACTION_TYPE_TTL_COPY_IN,
 };
 
 /**
@@ -1420,6 +1451,52 @@ struct rte_flow_action_field_set {
 };
 
 /**
+ * RTE_FLOW_ACTION_TYPE_MPLS_TTL_DEC
+ *
+ * Decrement MPLS TTL, only applies to packets that contain specific
+ * MPLS header.
+ */
+struct rte_flow_action_mpls_ttl_dec {
+	/**
+	 * Specify the level of MPLS header.
+	 *
+	 * direction (1b)
+	 * 0: match start from outermost.
+	 * 1: match start from innermost.
+	 *
+	 * level (31b)
+	 * 0: outermost|innermost MPLS header.
+	 * 1: next to outermost|innermost MPLS header.
+	 * 2: and so on ...
+	 */
+	uint32_t dir_level;
+
+};
+
+/**
+ * RTE_FLOW_ACTION_TYPE_IP_TTL_DEC
+ *
+ * Decrement IPv4 TTL or IPv6 hop limit field and update the IP
+ * checksum, only applies to packets that contain specific IPv4
+ * or IPv6 header.
+ */
+struct rte_flow_action_ip_ttl_dec {
+	/**
+	 * Specify the level of IPv4 or IPv6 header.
+	 *
+	 * direction (1b)
+	 * 0: match start from outermost.
+	 * 1: match start from innermost.
+	 *
+	 * level (31b)
+	 * 0: outermost|innermost IPv4 or IPv6 header.
+	 * 1: next to outermost|innermost IPv4 or IPv6 header.
+	 * 2: and so on ...
+	 */
+	uint32_t dir_level;
+};
+
+/**
  * Definition of a single action.
  *
  * A list of actions is terminated by a END action.
-- 
2.13.6

^ permalink raw reply	[flat|nested] 61+ messages in thread

* [dpdk-dev] [PATCH v3 4/4] ethdev: add VLAN and MPLS pop push action in flow API
  2018-04-16  5:16 ` [dpdk-dev] [PATCH v3 " Qi Zhang
                     ` (2 preceding siblings ...)
  2018-04-16  5:16   ` [dpdk-dev] [PATCH v3 3/4] ethdev: add TTL change actions " Qi Zhang
@ 2018-04-16  5:16   ` Qi Zhang
  3 siblings, 0 replies; 61+ messages in thread
From: Qi Zhang @ 2018-04-16  5:16 UTC (permalink / raw)
  To: adrien.mazarguil
  Cc: dev, declan.doherty, sugesh.chandran, michael.j.glynn, yu.y.liu,
	konstantin.ananyev, bruce.richardson, Qi Zhang

Add couple Openflow frienldy VLAN/MPLS push/pop actions.

RTE_FLOW_ACTION_VLAN_POP - pop a VLAN header.
RTE_FLOW_ACTION_VLAN_PUSH - push a VLAN header.
RTE_FLOW_ACTION_MPLS_POP - pop a MPLS header.
RTE_FLOW_ACTION_MPLS_PUSH - push a MPLS header.

Signed-off-by: Qi Zhang <qi.z.zhang@intel.com>
---
 app/test-pmd/cmdline_flow.c                 | 82 +++++++++++++++++++++++++++++
 doc/guides/prog_guide/rte_flow.rst          | 69 ++++++++++++++++++++++++
 doc/guides/testpmd_app_ug/testpmd_funcs.rst | 14 +++++
 lib/librte_ether/rte_flow.h                 | 71 +++++++++++++++++++++++++
 4 files changed, 236 insertions(+)

diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c
index fa35ecc6d..48a3ccdfc 100644
--- a/app/test-pmd/cmdline_flow.c
+++ b/app/test-pmd/cmdline_flow.c
@@ -196,6 +196,13 @@ enum index {
 	ACTION_IP_TTL_DEC_LVL,
 	ACTION_TTL_COPY_OUT,
 	ACTION_TTL_COPY_IN,
+	ACTION_VLAN_POP,
+	ACTION_VLAN_PUSH,
+	ACTION_VLAN_PUSH_TYPE,
+	ACTION_MPLS_POP,
+	ACTION_MPLS_POP_TYPE,
+	ACTION_MPLS_PUSH,
+	ACTION_MPLS_PUSH_TYPE,
 };
 
 /** Size of pattern[] field in struct rte_flow_item_raw. */
@@ -664,6 +671,10 @@ static const enum index next_action[] = {
 	ACTION_IP_TTL_DEC,
 	ACTION_TTL_COPY_OUT,
 	ACTION_TTL_COPY_IN,
+	ACTION_VLAN_POP,
+	ACTION_VLAN_PUSH,
+	ACTION_MPLS_POP,
+	ACTION_MPLS_PUSH,
 	ZERO,
 };
 
@@ -714,6 +725,21 @@ static const enum index action_ip_ttl_dec[] = {
 	ZERO,
 };
 
+static const enum index action_vlan_push[] = {
+	ACTION_VLAN_PUSH_TYPE,
+	ZERO,
+};
+
+static const enum index action_mpls_pop[] = {
+	ACTION_MPLS_POP_TYPE,
+	ZERO,
+};
+
+static const enum index action_mpls_push[] = {
+	ACTION_MPLS_PUSH_TYPE,
+	ZERO,
+};
+
 static int parse_init(struct context *, const struct token *,
 		      const char *, unsigned int,
 		      void *, unsigned int);
@@ -1871,6 +1897,62 @@ static const struct token token_list[] = {
 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
 		.call = parse_vc,
 	},
+
+	[ACTION_VLAN_POP] = {
+		.name = "vlan_pop",
+		.help = "pop the outermost VLAN header.",
+		.priv = PRIV_ACTION(DROP, 0),
+		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
+		.call = parse_vc,
+	},
+	[ACTION_VLAN_PUSH] = {
+		.name = "vlan_push",
+		.help = "push new VLAN header onto the packet",
+		.priv = PRIV_ACTION(VLAN_PUSH,
+				sizeof(struct rte_flow_action_vlan_push)),
+		.next = NEXT(action_vlan_push),
+		.call = parse_vc,
+	},
+	[ACTION_VLAN_PUSH_TYPE] = {
+		.name = "type",
+		.help = "Ethertype of VLAN header",
+		.next = NEXT(action_vlan_push, NEXT_ENTRY(UNSIGNED)),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_vlan_push,
+					ether_type)),
+		.call = parse_vc,
+	},
+	[ACTION_MPLS_POP] = {
+		.name = "mpls_pop",
+		.help = "pop the outermost MPLS header",
+		.priv = PRIV_ACTION(MPLS_POP,
+				sizeof(struct rte_flow_action_mpls_pop)),
+		.next = NEXT(action_mpls_pop),
+		.call = parse_vc,
+	},
+	[ACTION_MPLS_POP_TYPE] = {
+		.name = "type",
+		.help = "Ethertype of MPLS header",
+		.next = NEXT(action_mpls_pop, NEXT_ENTRY(UNSIGNED)),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_mpls_pop,
+					ether_type)),
+		.call = parse_vc,
+	},
+	[ACTION_MPLS_PUSH] = {
+		.name = "mpls_push",
+		.help = "push new MPLS header onto the packet",
+		.priv = PRIV_ACTION(MPLS_PUSH,
+				sizeof(struct rte_flow_action_mpls_push)),
+		.next = NEXT(action_mpls_push),
+		.call = parse_vc,
+	},
+	[ACTION_MPLS_PUSH_TYPE] = {
+		.name = "type",
+		.help = "Ethertype of MPLS header",
+		.next = NEXT(action_mpls_push, NEXT_ENTRY(UNSIGNED)),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_mpls_push,
+					ether_type)),
+		.call = parse_vc,
+	},
 };
 
 /** Remove and return last entry from argument stack. */
diff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst
index e81f0e375..bc143c1e9 100644
--- a/doc/guides/prog_guide/rte_flow.rst
+++ b/doc/guides/prog_guide/rte_flow.rst
@@ -1668,6 +1668,75 @@ required MPLS or IP headers.
    | no properties |
    +---------------+
 
+Action: ``ACTION_VLAN_POP``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Pop the outer-most VLAN header from the packet.
+
+.. _table_rte_flow_action_vlan_pop:
+
+.. table:: VLAN_POP
+
+   +---------------+
+   | Field         |
+   +===============+
+   | no properties |
+   +---------------+
+
+Action: ``ACTION_VLAN_PUSH``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Push a new VLAN header onto the packet, Ethertype 0x8100 or 0x88a8 should
+be used. The value of VLAN ID and VLAN priority for the new header is copied
+from an exist VLAN header in the packet, they will be set to 0 if no such
+VLAN header exist.
+
+.. _table_rte_flow_action_vlan_push:
+
+.. table:: VLAN_PUSH
+
+   +----------------+------------------------+
+   | Field          | Value                  |
+   +================+========================+
+   | ``ether_type`` | Ethertype for VLAN tag |
+   +----------------+------------------------+
+
+Action: ``ACTION_MPLS_POP``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Pop the outer-most MPLS header from the packet, Ethertype is required for
+the resulting packet if it is not the last MPLS header be popped, Ethertype
+must be 0x8847 or 0x8848.
+
+.. _table_rte_flow_action_mpls_pop:
+
+.. table:: MPLS_POP
+
+   +----------------+---------------------------+
+   | Field          | Value                     |
+   +================+===========================+
+   | ``ether_type`` | Ethertype for MPLS header |
+   +----------------+---------------------------+
+
+Action: ``ACTION_MPLS_PUSH``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Push a new MPLS header onto the packet, Ethertype 0x8847 or 0x8848 should
+be used. The value of MPLS label and traffic class is copied from exist
+outermost MPLS header, and TTL is copied from exist outermost MPLS or IP
+header, they will be set to 0 if exist packet does not contain required
+header.
+
+.. _table_rte_flow_action_mpls_push:
+
+.. table:: MPLS_PUSH
+
+   +----------------+---------------------------+
+   | Field          | Value                     |
+   +================+===========================+
+   | ``ether_type`` | Ethertype for MPLS header |
+   +----------------+---------------------------+
+
 Negative types
 ~~~~~~~~~~~~~~
 
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index 4dd86f10e..76b348439 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -3454,6 +3454,20 @@ This section lists supported actions and their attributes, if any.
 
 - ``ttl_copy_in``: copy TTL inwards.
 
+- ``vlan_pop``: pop the outermost VLAN header.
+
+- ``vlan_push``: push new VLAN header onto the packet.
+
+  - ``type``: Ethertype of the VLAN header.
+
+- ``mpls_pop``: pop the outermost MPLS header.
+
+  - ``type``: Ethertype of the MPLS header.
+
+- ``mpls_push``: push new MPLS header onto the packet.
+
+  - ``type``: Ethertype of the MPLS header.
+
 Destroying flow rules
 ~~~~~~~~~~~~~~~~~~~~~
 
diff --git a/lib/librte_ether/rte_flow.h b/lib/librte_ether/rte_flow.h
index 96a236945..3f7f9dcea 100644
--- a/lib/librte_ether/rte_flow.h
+++ b/lib/librte_ether/rte_flow.h
@@ -1281,6 +1281,41 @@ enum rte_flow_action_type {
 	 * packets that contain required protocol headers.
 	 */
 	RTE_FLOW_ACTION_TYPE_TTL_COPY_IN,
+
+	/**
+	 * Pop the outer-most VLAN header from the packet.
+	 */
+	RTE_FLOW_ACTION_TYPE_VLAN_POP,
+
+	/**
+	 * Push a new VLAN header onto the packet, Ethertype 0x8100 or 0x88a8
+	 * should be used. The value of VLAN ID and VLAN priority for the new
+	 * header is copied from an exist VLAN header in the packet, they will
+	 * be set to 0 if no such VLAN header exist.
+	 *
+	 * See struct rte_flow_action_vlan_push.
+	 */
+	RTE_FLOW_ACTION_TYPE_VLAN_PUSH,
+
+	/**
+	 * Pop the outer-most MPLS header from the packet, Ethertype is
+	 * required for the resulting packet if it is not the last MPLS
+	 * header be popped, Ethertype must be 0x8847 or 0x8848.
+	 *
+	 * See struct rte_flow_action_mpls_pop.
+	 */
+	RTE_FLOW_ACTION_TYPE_MPLS_POP,
+
+	/**
+	 * Push a new MPLS header onto the packet, Ethertype 0x8847 or 0x8848
+	 * should be used. The value of MPLS label and traffic class is copied
+	 * from exist outermost MPLS header, and TTL is copied from exist
+	 * outermost MPLS or IP header, they will be set to 0 if exist packet
+	 * does not contain required header.
+	 *
+	 * See struct rte_flow_action_mpls_push.
+	 */
+	RTE_FLOW_ACTION_TYPE_MPLS_PUSH,
 };
 
 /**
@@ -1497,6 +1532,42 @@ struct rte_flow_action_ip_ttl_dec {
 };
 
 /**
+ * RTE_FLOW_ACTION_TYPE_VLAN_PUSH,
+ *
+ * Push a new VLAN header onto the packet, Ethertype 0x8100 or 0x88a8
+ * should be used. The value of VLAN ID and VLAN priority for the new
+ * header is copied from an exist outermost VLAN header in the packet,
+ * they will be set to 0 if no such VLAN header exist.
+ */
+struct rte_flow_action_vlan_push {
+	rte_be16_t ether_type; /**< Ethertype for vlan tag. */
+};
+
+/**
+ * RTE_FLOW_ACTION_TYPE_MPLS_POP,
+ *
+ * Pop the outer-most MPLS header from the packet, Ethertype is
+ * required for the resulting packet if it is not the last MPLS
+ * header be popped, Ethertype must be 0x8847 or 0x8848.
+ */
+struct rte_flow_action_mpls_pop {
+	rte_be16_t ether_type; /**< Ethertype for MPLS header */
+};
+
+/**
+ * RTE_FLOW_ACTION_TYPE_MPLS_PUSH,
+ *
+ * Push a new MPLS header onto the packet, Ethertype 0x8847 or 0x8848
+ * should be used. The value of MPLS label and traffic class are copied
+ * from exist outermost MPLS header, and TTL is copied from exist outermost
+ * MPLS or IP header, they will be set to 0, if exist packet does not
+ * contain required header.
+ */
+struct rte_flow_action_mpls_push {
+	rte_be16_t ether_type; /**< Ethertype for MPLS header */
+};
+
+/**
  * Definition of a single action.
  *
  * A list of actions is terminated by a END action.
-- 
2.13.6

^ permalink raw reply	[flat|nested] 61+ messages in thread

* Re: [dpdk-dev] [PATCH v3 3/4] ethdev: add TTL change actions in flow API
  2018-04-16  5:16   ` [dpdk-dev] [PATCH v3 3/4] ethdev: add TTL change actions " Qi Zhang
@ 2018-04-16  5:48     ` Shahaf Shuler
  2018-04-16  8:12       ` Adrien Mazarguil
  0 siblings, 1 reply; 61+ messages in thread
From: Shahaf Shuler @ 2018-04-16  5:48 UTC (permalink / raw)
  To: Qi Zhang, Adrien Mazarguil
  Cc: dev, declan.doherty, sugesh.chandran, michael.j.glynn, yu.y.liu,
	konstantin.ananyev, bruce.richardson, Thomas Monjalon

Hi Qi,

Am wondering if we can make the below more generic and not tailored for specific use cases. 

Monday, April 16, 2018 8:17 AM, Qi Zhang:
> Subject: [dpdk-dev] [PATCH v3 3/4] ethdev: add TTL change actions in flow
> API
> 
> Add couple OpenFlow frienldy TTL change actions.
> 
> RTE_FLOW_ACTION_MLPS_TTL_DEC - decrement MPLS TTL.
> RTE_FLOW_ACTION_IP_TTL_DEC - decrement IP TTL.
> RTE_FLOW_ACTION_TTL_COPY_OUT - copy TTL outwards.
> RTE_FLOW_ACTION_TTL_COPY_IN - copy TTL inwards.
> 
> Signed-off-by: Qi Zhang <qi.z.zhang@intel.com>
> ---
>  app/test-pmd/cmdline_flow.c                 | 64 +++++++++++++++++++++++
>  doc/guides/prog_guide/rte_flow.rst          | 80
> +++++++++++++++++++++++++++++
>  doc/guides/testpmd_app_ug/testpmd_funcs.rst | 12 +++++
>  lib/librte_ether/rte_flow.h                 | 77 +++++++++++++++++++++++++++
>  4 files changed, 233 insertions(+)

[...]

> 
>  /** Remove and return last entry from argument stack. */ diff --git
> a/doc/guides/prog_guide/rte_flow.rst
> b/doc/guides/prog_guide/rte_flow.rst
> index ea0e40a52..e81f0e375 100644
> --- a/doc/guides/prog_guide/rte_flow.rst
> +++ b/doc/guides/prog_guide/rte_flow.rst
> @@ -1588,6 +1588,86 @@ contain respective protocol layer.
>     |  ``mask``     | Bit-mask applied to new_val                                       |
>     +---------------+-------------------------------------------------------------------+
> 
> +Action: ``MPLS_TTL_DEC``
> +^^^^^^^^^^^^^^^^^^^^^^^^
> +
> +Decrement MPLS TTL, only applies to packets that contain specific MPLS
> +headers.
> +
> +.. _table_rte_flow_action_mpls_ttl_dec:
> +
> +.. table:: MPLS_TTL_DEC
> +
> +   +---------------+---------------------------------------------+
> +   | Field         | Value                                       |
> +
> +===============+=========================================
> ====+
> +   | ``dir_level`` | Specify the level of MPLS header.           |
> +   |               | direction (1b)                              |
> +   |               | 0: match start from outermost.              |
> +   |               | 1: match start from innermost.              |
> +   |               | level: (31b)                                |
> +   |               | 0: outermost or innermost MPLS header       |
> +   |               | 1: next to outmost or innermost MPLS header |
> +   |               | 2: and so on ...                            |
> +   +---------------+---------------------------------------------+

Why not exposing it is as generic operation: increment/decrement for any type of header.
The action struct will receive the flow item type to modify, list of increment/decrement values for each of its fields (+x/-y) along with corresponding mask?

It is true the main use case is TTL decrement for vRouters, however It will save the duplication of the TTL_DEC action below and maybe we will not need to modify the API for future similar actions.


> +
> +Action: ``IP_TTL_DEC``
> +^^^^^^^^^^^^^^^^^^^^^^
> +
> +Decrement IPv4 TTL or IPv6 hop limit field and update the IP checksum,
> +only applies to packets that contain specific MPLS headers.
> +
> +.. _table_rte_flow_action_ip_ttl_dec:
> +
> +.. table:: IP_TTL_DEC
> +
> +   +---------------+----------------------------------------------------------+
> +   | Field         | Value                                                    |
> +
> +===============+=========================================
> =================+
> +   | ``dir_level`` | Specify the level of IPv4 or IPv6 header.                |
> +   |               | direction (1b)                                           |
> +   |               | 0: match start from outermost.                           |
> +   |               | 1: match start from innermost.                           |
> +   |               | level: (31b)                                             |
> +   |               | 0: outermost or innermost Ipv4 or IPv6 header            |
> +   |               | 1: next to outmost or innermost MPLS IPv4 or IPv6 header |
> +   |               | 2: and so on ...                                         |
> +
> + +---------------+-----------------------------------------------------
> + -----+
> +
> +Action: ``TTL_COPY_OUT``
> +^^^^^^^^^^^^^^^^^^^^^^^^
> +
> +Copy the TTL from next-to-outermost to outermost header with TTL, copy
> +can be IP to IP, MPLS to MPLS or IP to MPLS, only applies packets that
> +contain required MPLS or IP headers.
> +
> +.. _table_rte_flow_action_ttl_copy_out:
> +
> +.. table:: TTL_COPY_OUT
> +
> +   +---------------+
> +   | Field         |
> +   +===============+
> +   | no properties |
> +   +---------------+

Why only the TTL ? and why only from outermost to next-to-outer-most? 

We can have an action to copy field from flow item to another flow item. 
We will need flow item for src + mask for the field to copy, flow item for dst + mask for the field to set

> +
> +Action: ``TTL_COPY_IN``
> +^^^^^^^^^^^^^^^^^^^^^^^
> +
> +Copy the TTL from outermost to next-to-outermost header with TTL, copy
> +can be IP to IP, MPLS to MPLS or MPLS to IP, only applies packets that
> +contain required MPLS or IP headers.
> +
> +.. _table_rte_flow_action_ttl_copy_in:
> +
> +.. table:: TTL_COPY_IN
> +
> +   +---------------+
> +   | Field         |
> +   +===============+
> +   | no properties |
> +   +---------------+
> +
>  Negative types
>  ~~~~~~~~~~~~~~
> 
> diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
> b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
> index 48688600e..4dd86f10e 100644
> --- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
> +++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
> @@ -3442,6 +3442,18 @@ This section lists supported actions and their
> attributes, if any.
>    - ``original {boolean}``: use original VF ID if possible.
>    - ``id {unsigned}``: VF ID to redirect packets to.
> 
> +- ``mpls_ttl_dec``: decrement MPLS TTL.
> +
> +  - ``level``: level of MPLS header.
> +
> +- ``ip_ttl_dec``: decrement IPv4 TTL or IPv6 Hot Limit.
> +
> +  - ``level``: level of IPv4 or IPv6 header.
> +
> +- ``ttl_copy_out``: copy TTL outwards.
> +
> +- ``ttl_copy_in``: copy TTL inwards.
> +
>  Destroying flow rules
>  ~~~~~~~~~~~~~~~~~~~~~
> 
> diff --git a/lib/librte_ether/rte_flow.h b/lib/librte_ether/rte_flow.h index
> 80cf75ff0..96a236945 100644
> --- a/lib/librte_ether/rte_flow.h
> +++ b/lib/librte_ether/rte_flow.h
> @@ -1250,6 +1250,37 @@ enum rte_flow_action_type {
>  	 * See struct rte_flow_action_field_set.
>  	 */
>  	RTE_FLOW_ACTION_TYPE_FIELD_SET,
> +
> +	/**
> +	 * Decrement MPLS TTL, only applies to packets that contain specific
> +	 * MPLS header.
> +	 *
> +	 * See struct rte_flow_action_mpls_ttl_dec.
> +	 */
> +	RTE_FLOW_ACTION_TYPE_MPLS_TTL_DEC,
> +
> +	/**
> +	 * Decrement IPv4 TTL or IPv6 Hop limit field and update the IP
> +	 * checksum, only applies to packets that contain specific IPv4
> +	 * or IPv6 header.
> +	 *
> +	 * See struct rte_flow_action_ip_ttl_dec.
> +	 */
> +	RTE_FLOW_ACTION_TYPE_IP_TTL_DEC,
> +
> +	/**
> +	 * Copy the TTL from next-to-outermost to outermost header with
> TTL,
> +	 * copy can be IP to IP, MPLS to MPLS or IP to MPLS, only applies
> +	 * packets that contain required protocol headers.
> +	 */
> +	RTE_FLOW_ACTION_TYPE_TTL_COPY_OUT,
> +
> +	/**
> +	 * Copy the TTL from outermost to next-to-outermost header with
> TTL,
> +	 * copy can be IP to IP, MPLS to MPLS or MPLS to IP, only applies
> +	 * packets that contain required protocol headers.
> +	 */
> +	RTE_FLOW_ACTION_TYPE_TTL_COPY_IN,
>  };
> 
>  /**
> @@ -1420,6 +1451,52 @@ struct rte_flow_action_field_set {  };
> 
>  /**
> + * RTE_FLOW_ACTION_TYPE_MPLS_TTL_DEC
> + *
> + * Decrement MPLS TTL, only applies to packets that contain specific
> + * MPLS header.
> + */
> +struct rte_flow_action_mpls_ttl_dec {
> +	/**
> +	 * Specify the level of MPLS header.
> +	 *
> +	 * direction (1b)
> +	 * 0: match start from outermost.
> +	 * 1: match start from innermost.
> +	 *
> +	 * level (31b)
> +	 * 0: outermost|innermost MPLS header.
> +	 * 1: next to outermost|innermost MPLS header.
> +	 * 2: and so on ...
> +	 */
> +	uint32_t dir_level;
> +
> +};
> +
> +/**
> + * RTE_FLOW_ACTION_TYPE_IP_TTL_DEC
> + *
> + * Decrement IPv4 TTL or IPv6 hop limit field and update the IP
> + * checksum, only applies to packets that contain specific IPv4
> + * or IPv6 header.
> + */
> +struct rte_flow_action_ip_ttl_dec {
> +	/**
> +	 * Specify the level of IPv4 or IPv6 header.
> +	 *
> +	 * direction (1b)
> +	 * 0: match start from outermost.
> +	 * 1: match start from innermost.
> +	 *
> +	 * level (31b)
> +	 * 0: outermost|innermost IPv4 or IPv6 header.
> +	 * 1: next to outermost|innermost IPv4 or IPv6 header.
> +	 * 2: and so on ...
> +	 */
> +	uint32_t dir_level;
> +};
> +
> +/**
>   * Definition of a single action.
>   *
>   * A list of actions is terminated by a END action.
> --
> 2.13.6

^ permalink raw reply	[flat|nested] 61+ messages in thread

* [dpdk-dev] [PATCH v3 0/4] rte_flow extension for vSwitch acceleration
  2018-03-28 23:29 [dpdk-dev] [PATCH 0/4] rte_flow extension for vSwitch acceleration Qi Zhang
                   ` (5 preceding siblings ...)
  2018-04-16  5:16 ` [dpdk-dev] [PATCH v3 " Qi Zhang
@ 2018-04-16  6:10 ` Qi Zhang
  2018-04-16  6:10   ` [dpdk-dev] [PATCH v3 1/4] ethdev: add more protocol support in flow API Qi Zhang
                     ` (3 more replies)
  2018-04-23  6:36 ` [dpdk-dev] [PATCH v4 0/3] rte_flow extension for vSwitch acceleration Qi Zhang
  7 siblings, 4 replies; 61+ messages in thread
From: Qi Zhang @ 2018-04-16  6:10 UTC (permalink / raw)
  To: adrien.mazarguil
  Cc: dev, declan.doherty, sugesh.chandran, michael.j.glynn, yu.y.liu,
	konstantin.ananyev, bruce.richardson, Qi Zhang

v3:
- remove patch for port action and enhanced statistic query.
- reworked IPv6 ND related pattern base on Adrien's suggestion.
- remove generic increament/decrement/copy action
- rework packet modification action(RTE_FLOW_ACTION_TYPE_FIELD_SET).
- Add OpenFlow friendly TTL change actions.
- Add OpenFlow friendly VLAN/MPLS push/pop actions

v2:
- fix couple typoes in code, doc and commit log

This patch extend rte_flow API.
The purpose is to provide necessary programming interface for virtual
switch software (such as OVS) to take advantage of incoming device's
vSwitch acceleration capability when using DPDK as data plane.

Note:
- The driver to demonstrate the new APIs is still in development,
  but we hope it could be accepted early to make OVS integration
  smoothly. 

Qi Zhang (4):
  ethdev: add more protocol support in flow API
  ethdev: add packet field set aciton in flow API
  ethdev: add TTL change actions in flow API
  ethdev: add VLAN and MPLS pop push action in flow API

 app/test-pmd/cmdline_flow.c                 | 370 ++++++++++++++++++++++++
 app/test-pmd/config.c                       |   9 +
 doc/guides/prog_guide/rte_flow.rst          | 267 +++++++++++++++++
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  60 ++++
 lib/librte_ether/rte_flow.h                 | 425 +++++++++++++++++++++++++++-
 5 files changed, 1130 insertions(+), 1 deletion(-)

-- 
2.13.6

^ permalink raw reply	[flat|nested] 61+ messages in thread

* [dpdk-dev] [PATCH v3 1/4] ethdev: add more protocol support in flow API
  2018-04-16  6:10 ` [dpdk-dev] [PATCH v3 0/4] rte_flow extension for vSwitch acceleration Qi Zhang
@ 2018-04-16  6:10   ` Qi Zhang
  2018-04-19 14:48     ` Adrien Mazarguil
  2018-04-16  6:10   ` [dpdk-dev] [PATCH v3 2/4] ethdev: add packet field set aciton " Qi Zhang
                     ` (2 subsequent siblings)
  3 siblings, 1 reply; 61+ messages in thread
From: Qi Zhang @ 2018-04-16  6:10 UTC (permalink / raw)
  To: adrien.mazarguil
  Cc: dev, declan.doherty, sugesh.chandran, michael.j.glynn, yu.y.liu,
	konstantin.ananyev, bruce.richardson, Qi Zhang

Add new protocol header match support as below

RTE_FLOW_ITEM_TYPE_ARP_IPV4
	- matches an IPv4 ARP header
RTE_FLOW_ITEM_TYPE_IPV6_EXT
	- matches an IPv6 extension header with any type.
RTE_FLOW_ITEM_TYPE_ICMP6
	- matches an ICMPv6 header followed by any message body.
RTE_FLOW_ITEM_TYPE_ICMP6_ND_NS
	- matches an ICMPv6 header followed by network discovery
	  neighbor solicitation.
RTE_FLOW_ITEM_TYPE_ICMP6_ND_NA
	- matches an ICMPv6 header followed by network discovery
	  neighbor advertisement.
RTE_FLOW_ITEM_TYPE_ICMP6_ND_OPT_ETH_SLA
	- matches an ICMPv6 header followed by network discovery
	  neighbor solicitation contains source Ethernet link-layer
	  address option.
RTE_FLOW_ITEM_TYPE_ICMP6_ND_OPT_ETH_TLA
	- matches an ICMPv6 header followed by network discovery
	  neighbor advertisement contains target Ethernet link-layer
	  address option.

Suggested-by: Adrien Mazarguil <adrien.mazarguil@6wind.com>
Signed-off-by: Qi Zhang <qi.z.zhang@intel.com>
---
 app/test-pmd/cmdline_flow.c                 | 224 ++++++++++++++++++++++++++
 app/test-pmd/config.c                       |   9 ++
 doc/guides/prog_guide/rte_flow.rst          |  88 +++++++++++
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  34 ++++
 lib/librte_ether/rte_flow.h                 | 235 ++++++++++++++++++++++++++++
 5 files changed, 590 insertions(+)

diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c
index 59f3b3b57..7950b1b8d 100644
--- a/app/test-pmd/cmdline_flow.c
+++ b/app/test-pmd/cmdline_flow.c
@@ -150,6 +150,26 @@ enum index {
 	ITEM_GENEVE,
 	ITEM_GENEVE_VNI,
 	ITEM_GENEVE_PROTO,
+	ITEM_ARP_IPV4,
+	ITEM_ARP_IPV4_SHA,
+	ITEM_ARP_IPV4_SIP,
+	ITEM_ARP_IPV4_THA,
+	ITEM_ARP_IPV4_TIP,
+	ITEM_IPV6_EXT,
+	ITEM_IPV6_EXT_NEXT_HDR,
+	ITEM_ICMP6,
+	ITEM_ICMP6_TYPE,
+	ITEM_ICMP6_CODE,
+	ITEM_ICMP6_ND_NS,
+	ITEM_ICMP6_ND_NS_TGT_ADDR,
+	ITEM_ICMP6_ND_NA,
+	ITEM_ICMP6_ND_NA_TGT_ADDR,
+	ITEM_ICMP6_ND_OPT_SLA_ETH,
+	ITEM_ICMP6_ND_OPT_SLA_ETH_TGT_ADDR,
+	ITEM_ICMP6_ND_OPT_SLA_ETH_SLL_ADDR,
+	ITEM_ICMP6_ND_OPT_TLA_ETH,
+	ITEM_ICMP6_ND_OPT_TLA_ETH_TGT_ADDR,
+	ITEM_ICMP6_ND_OPT_TLA_ETH_TLL_ADDR,
 
 	/* Validate/create actions. */
 	ACTIONS,
@@ -436,6 +456,13 @@ static const enum index next_item[] = {
 	ITEM_GTPC,
 	ITEM_GTPU,
 	ITEM_GENEVE,
+	ITEM_ARP_IPV4,
+	ITEM_IPV6_EXT,
+	ITEM_ICMP6,
+	ITEM_ICMP6_ND_NS,
+	ITEM_ICMP6_ND_NA,
+	ITEM_ICMP6_ND_OPT_SLA_ETH,
+	ITEM_ICMP6_ND_OPT_TLA_ETH,
 	ZERO,
 };
 
@@ -586,6 +613,47 @@ static const enum index item_geneve[] = {
 	ZERO,
 };
 
+static const enum index item_arp_ipv4[] = {
+	ITEM_ARP_IPV4_SHA,
+	ITEM_ARP_IPV4_SIP,
+	ITEM_ARP_IPV4_THA,
+	ITEM_ARP_IPV4_TIP,
+	ZERO,
+};
+
+static const enum index item_ipv6_ext[] = {
+	ITEM_IPV6_EXT_NEXT_HDR,
+	ZERO,
+};
+
+static const enum index item_icmp6[] = {
+	ITEM_ICMP6_TYPE,
+	ITEM_ICMP6_CODE,
+	ZERO,
+};
+
+static const enum index item_icmp6_nd_ns[] = {
+	ITEM_ICMP6_ND_NS_TGT_ADDR,
+	ZERO,
+};
+
+static const enum index item_icmp6_nd_na[] = {
+	ITEM_ICMP6_ND_NA_TGT_ADDR,
+	ZERO,
+};
+
+static const enum index item_icmp6_nd_opt_sla_eth[] = {
+	ITEM_ICMP6_ND_OPT_SLA_ETH_TGT_ADDR,
+	ITEM_ICMP6_ND_OPT_SLA_ETH_SLL_ADDR,
+	ZERO,
+};
+
+static const enum index item_icmp6_nd_opt_tla_eth[] = {
+	ITEM_ICMP6_ND_OPT_TLA_ETH_TGT_ADDR,
+	ITEM_ICMP6_ND_OPT_TLA_ETH_TLL_ADDR,
+	ZERO,
+};
+
 static const enum index next_action[] = {
 	ACTION_END,
 	ACTION_VOID,
@@ -1473,6 +1541,162 @@ static const struct token token_list[] = {
 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve,
 					     protocol)),
 	},
+	[ITEM_ARP_IPV4] = {
+		.name = "arp",
+		.help = "match IPv4 ARP header",
+		.priv = PRIV_ITEM(ARP_IPV4,
+				  sizeof(struct rte_flow_item_arp_ipv4)),
+		.next = NEXT(item_arp_ipv4),
+		.call = parse_vc,
+	},
+	[ITEM_ARP_IPV4_SHA] = {
+		.name = "sha",
+		.help = "sender hardware address",
+		.next = NEXT(item_arp_ipv4, NEXT_ENTRY(UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_ipv4,
+					     arp_sha.addr_bytes)),
+	},
+	[ITEM_ARP_IPV4_SIP] = {
+		.name = "sip",
+		.help = "sender IP address",
+		.next = NEXT(item_arp_ipv4, NEXT_ENTRY(UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_ipv4,
+					     arp_sip)),
+	},
+	[ITEM_ARP_IPV4_THA] = {
+		.name = "tha",
+		.help = "target hardware address",
+		.next = NEXT(item_arp_ipv4, NEXT_ENTRY(UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_ipv4,
+					     arp_tha.addr_bytes)),
+	},
+	[ITEM_ARP_IPV4_TIP] = {
+		.name = "tip",
+		.help = "target IP address",
+		.next = NEXT(item_arp_ipv4, NEXT_ENTRY(UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_ipv4,
+					     arp_tip)),
+	},
+	[ITEM_IPV6_EXT] = {
+		.name = "ext",
+		.help = "match IPv6 extend header",
+		.priv = PRIV_ITEM(IPV6_EXT,
+				  sizeof(struct rte_flow_item_ipv6_ext)),
+		.next = NEXT(item_ipv6_ext),
+		.call = parse_vc,
+	},
+	[ITEM_IPV6_EXT_NEXT_HDR] = {
+		.name = "next",
+		.help = "next header in IPv6 extend header",
+		.next = NEXT(item_ipv6_ext, NEXT_ENTRY(UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_ext,
+					     next_hdr)),
+	},
+	[ITEM_ICMP6] = {
+		.name = "icmp6",
+		.help = "match ICMPv6 header",
+		.priv = PRIV_ITEM(ICMP, sizeof(struct rte_flow_item_icmp6)),
+		.next = NEXT(item_icmp6),
+		.call = parse_vc,
+	},
+	[ITEM_ICMP6_TYPE] = {
+		.name = "type",
+		.help = "ICMPv6 packet type",
+		.next = NEXT(item_icmp6, NEXT_ENTRY(UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6,
+					     type)),
+	},
+	[ITEM_ICMP6_CODE] = {
+		.name = "code",
+		.help = "ICMPv6 packet code",
+		.next = NEXT(item_icmp6, NEXT_ENTRY(UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6,
+					     code)),
+	},
+	[ITEM_ICMP6_ND_NS] = {
+		.name = "ns",
+		.help = "match neighbor solicitation over ICMPv6 ",
+		.priv = PRIV_ITEM(ICMP6_ND_NS,
+				  sizeof(struct rte_flow_item_icmp6_nd_ns)),
+		.next = NEXT(item_icmp6_nd_ns),
+		.call = parse_vc,
+	},
+	[ITEM_ICMP6_ND_NS_TGT_ADDR] = {
+		.name = "tgt_addr",
+		.help = "target address of neighbor solicitation",
+		.next = NEXT(item_icmp6_nd_ns, NEXT_ENTRY(UNSIGNED),
+			     item_param),
+		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_ns,
+					     target_addr)),
+	},
+	[ITEM_ICMP6_ND_NA] = {
+		.name = "na",
+		.help = "match neighbor advertisement over ICMPv6 ",
+		.priv = PRIV_ITEM(ICMP6_ND_NA,
+				  sizeof(struct rte_flow_item_icmp6_nd_na)),
+		.next = NEXT(item_icmp6_nd_na),
+		.call = parse_vc,
+	},
+	[ITEM_ICMP6_ND_NA_TGT_ADDR] = {
+		.name = "tgt_addr",
+		.help = "target address of neighbor advertisement",
+		.next = NEXT(item_icmp6_nd_na, NEXT_ENTRY(UNSIGNED),
+			     item_param),
+		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_na,
+					     target_addr)),
+	},
+	[ITEM_ICMP6_ND_OPT_SLA_ETH] = {
+		.name = "sla",
+		.help = "match source link-layer address over neighbor solicitation",
+		.priv = PRIV_ITEM(ICMP6_ND_OPT_SLA_ETH,
+			  sizeof(struct rte_flow_item_icmp6_nd_opt_sla_eth)),
+		.next = NEXT(item_icmp6_nd_opt_sla_eth),
+		.call = parse_vc,
+	},
+	[ITEM_ICMP6_ND_OPT_SLA_ETH_TGT_ADDR] = {
+		.name = "tgt_addr",
+		.help = "target address of neighbor solicitation",
+		.next = NEXT(item_icmp6_nd_opt_sla_eth, NEXT_ENTRY(UNSIGNED),
+			     item_param),
+		.args = ARGS(ARGS_ENTRY_HTON(
+			     struct rte_flow_item_icmp6_nd_opt_sla_eth,
+			     target_addr)),
+	},
+	[ITEM_ICMP6_ND_OPT_SLA_ETH_SLL_ADDR] = {
+		.name = "sll_addr",
+		.help = "source link-layer address over neighbor solicitation",
+		.next = NEXT(item_icmp6_nd_opt_sla_eth, NEXT_ENTRY(UNSIGNED),
+			     item_param),
+		.args = ARGS(ARGS_ENTRY_HTON(
+			     struct rte_flow_item_icmp6_nd_opt_sla_eth,
+			     sll_addr)),
+	},
+	[ITEM_ICMP6_ND_OPT_TLA_ETH] = {
+		.name = "tla",
+		.help = "match target link-layer address over neighbor advertisement",
+		.priv = PRIV_ITEM(ICMP6_ND_OPT_TLA_ETH,
+			  sizeof(struct rte_flow_item_icmp6_nd_opt_tla_eth)),
+		.next = NEXT(item_icmp6_nd_opt_tla_eth),
+		.call = parse_vc,
+	},
+	[ITEM_ICMP6_ND_OPT_TLA_ETH_TGT_ADDR] = {
+		.name = "tgt_addr",
+		.help = "target address of neighbor advertisement",
+		.next = NEXT(item_icmp6_nd_opt_tla_eth, NEXT_ENTRY(UNSIGNED),
+			     item_param),
+		.args = ARGS(ARGS_ENTRY_HTON(
+			     struct rte_flow_item_icmp6_nd_opt_tla_eth,
+			     target_addr)),
+	},
+	[ITEM_ICMP6_ND_OPT_TLA_ETH_TLL_ADDR] = {
+		.name = "tll_addr",
+		.help = "target link-layer address over neighbor advertisement",
+		.next = NEXT(item_icmp6_nd_opt_tla_eth, NEXT_ENTRY(UNSIGNED),
+			     item_param),
+		.args = ARGS(ARGS_ENTRY_HTON(
+			     struct rte_flow_item_icmp6_nd_opt_tla_eth,
+			     tll_addr)),
+	},
 
 	/* Validate/create actions. */
 	[ACTIONS] = {
diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
index 4bb255c62..4a1af5c57 100644
--- a/app/test-pmd/config.c
+++ b/app/test-pmd/config.c
@@ -980,6 +980,15 @@ static const struct {
 	MK_FLOW_ITEM(GTPC, sizeof(struct rte_flow_item_gtp)),
 	MK_FLOW_ITEM(GTPU, sizeof(struct rte_flow_item_gtp)),
 	MK_FLOW_ITEM(GENEVE, sizeof(struct rte_flow_item_geneve)),
+	MK_FLOW_ITEM(ARP_IPV4, sizeof(struct rte_flow_item_arp_ipv4)),
+	MK_FLOW_ITEM(IPV6_EXT, sizeof(struct rte_flow_item_ipv6_ext)),
+	MK_FLOW_ITEM(ICMP6, sizeof(struct rte_flow_item_icmp6)),
+	MK_FLOW_ITEM(ICMP6_ND_NS, sizeof(struct rte_flow_item_icmp6_nd_ns)),
+	MK_FLOW_ITEM(ICMP6_ND_NA, sizeof(struct rte_flow_item_icmp6_nd_na)),
+	MK_FLOW_ITEM(ICMP6_ND_OPT_SLA_ETH,
+		     sizeof(struct rte_flow_item_icmp6_nd_opt_sla_eth)),
+	MK_FLOW_ITEM(ICMP6_ND_OPT_TLA_ETH,
+		     sizeof(struct rte_flow_item_icmp6_nd_opt_tla_eth)),
 };
 
 /** Compute storage space needed by item specification. */
diff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst
index 961943dda..99468bf60 100644
--- a/doc/guides/prog_guide/rte_flow.rst
+++ b/doc/guides/prog_guide/rte_flow.rst
@@ -992,6 +992,94 @@ Matches a GENEVE header.
 - ``rsvd1``: reserved, normally 0x00.
 - Default ``mask`` matches VNI only.
 
+Item: ``ARP_IPV4``
+^^^^^^^^^^^^^^^^^^
+
+Matches an IPv4 ARP header.
+
+- ``arp_hdr``: format of hardware address.
+- ``arp_pro``: format of protocol address.
+- ``arp_hln``: length of hardware address.
+- ``arp_pln``: length of protocol address.
+- ``arp_op``: ARP opcode.
+- ``sha``: sender hardware address.
+- ``sip``: sender IP address.
+- ``tha``: target hardware address.
+- ``tip``: target IP address.
+- Default ``mask`` only matches sha, sip, tha, tip.
+
+Item: ``IPV6_EXT``
+^^^^^^^^^^^^^^^^^^
+
+Matches an IPv6 Extension header with any type.
+
+- ``next_hdr``: protocol of next header.
+- Default ``mask`` matches protocal of next header.
+
+Item: ``ICMP6``
+^^^^^^^^^^^^^^^
+
+Matches an ICMPv6 header followed by any message body.
+
+- ``type``: ICMPv6 type.
+- ``code``: ICMPv6 code.
+- ``checksume``: ICMPv6 checksume.
+- Default ``mask`` matches type and code only.
+
+Item: ``ICMP6_ND_NS``
+^^^^^^^^^^^^^^^^^^^^^
+
+Matches an ICMPv6 header followed by network discvoery neighbor solicitation,
+
+- ``type``: ICMPv6 type, normally 135.
+- ``code``: ICMPv6 code, normally 0.
+- ``checksume``: ICMPv6 checksume.
+- ``reserved``: reserved, normally 0x00.
+- ``tgt_addr``: target address of neighbor solicitation.
+- Default ``mask`` matches target address only.
+
+Item: ``ICMP6_ND_NA``
+^^^^^^^^^^^^^^^^^^^^^
+
+Matches an ICMPv6 header followed by network discvoery neighbor advertisement,
+
+- ``type``: ICMPv6 type, normally 136.
+- ``code``: ICMPv6 code, normally 0.
+- ``checksume``: ICMPv6 checksume.
+- ``rso_reserved``: route flag (1b), solicited flag (1b), override flag (1b),
+  reserved (29b).
+- ``tgt_addr``: target address of neighbor advertisement.
+- Default ``mask`` matches target address only.
+
+Item: ``ICMP6_ND_OPT_SLA_ETH``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Matches an ICMPv6 header followed by network discvoery neighbor solicitation
+that contains source Ethernet link-layer address option.
+
+- ``type``: ICMPv6 type, normally 135.
+- ``code``: ICMPv6 code, normally 0.
+- ``checksume``: ICMPv6 checksume.
+- ``reserved``: reserved, normally 0x00.
+- ``tgt_addr``: target address of neighbor solicitation.
+- ``sll_ADDR``: source Ethernet link-layer address.
+- Default ``mask`` matches target address and source link-layer address only.
+
+Item: ``ICMP6_ND_OPT_TLA_ETH``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Matches an ICMPv6 header followed by network discvoery neighbor advertisement.
+that contains target Ethernet link-layer address option.
+
+- ``type``: ICMPv6 type, normally 136.
+- ``code``: ICMPv6 code, normally 0.
+- ``checksume``: ICMPv6 checksume.
+- ``rso_reserved``: route flag (1b), solicited flag (1b), override flag (1b),
+  reserved (29b).
+- ``tgt_addr``: target address of neighbor advertisement.
+- ``tll_ADDR``: target Ethernet link-layer address.
+- Default ``mask`` matches target address and target link-layer address only.
+
 Actions
 ~~~~~~~
 
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index a766ac795..12d78f10b 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -3305,6 +3305,40 @@ This section lists supported pattern items and their attributes, if any.
   - ``vni {unsigned}``: virtual network identifier.
   - ``protocol {unsigned}``: protocol type.
 
+- ``arp``: match IPv4 arp header.
+
+  - ``sha``: sender hardware address.
+  - ``sip``: sender IP address.
+  - ``tha``: target hardware address.
+  - ``tip``: target IP address.
+
+- ``ext``: match IPv6 extend header.
+
+  - ``next {unsigned}``: protocol (next header).
+
+- ``icmp6``: match ICMPv6 header.
+
+  - ``type {unsgined}``: ICMPv6 packet type.
+  - ``code {unsigned}``: ICMPv6 packet code.
+
+- ``ns``: match neighbor solicitation over ICMPv6.
+
+  - ``tgt_addr {ipv6 address}``: target address of neighbor solicitation.
+
+- ``na``: match neighbor advertisement over ICMPv6.
+
+  - ``tgt_addr {ipv6 address}``: target address of neighbor advertisement.
+
+- ``sla``: match source link-layer address over neighbor solicitation.
+
+  - ``tgt_addr {ipv6 address}``: target address of neighbor solicitation.
+  - ``sll_addr {MAC-48}``: source link-layer address over neightbor solicitation.
+
+- ``tla``: match target link-layer address over neighbor advertisement.
+
+  - ``tgt_addr {ipv6 address}``: target address of neighbor advertisement.
+  - ``tll_addr {MAC-48}``: target link-layer address over neightbor advertisement.
+
 Actions list
 ^^^^^^^^^^^^
 
diff --git a/lib/librte_ether/rte_flow.h b/lib/librte_ether/rte_flow.h
index 56c733451..f84bbfda5 100644
--- a/lib/librte_ether/rte_flow.h
+++ b/lib/librte_ether/rte_flow.h
@@ -323,6 +323,61 @@ enum rte_flow_item_type {
 	 * See struct rte_flow_item_geneve.
 	 */
 	RTE_FLOW_ITEM_TYPE_GENEVE,
+
+	/**
+	 * Matches an IPv4 ARP header.
+	 *
+	 * See struct rte_flow_item_arp_ipv4.
+	 */
+	RTE_FLOW_ITEM_TYPE_ARP_IPV4,
+
+	/**
+	 * Matches an IPv6 Extension header with any type.
+	 *
+	 * See struct rte_flow_item_ipv6_ext.
+	 */
+	RTE_FLOW_ITEM_TYPE_IPV6_EXT,
+
+	/**
+	 * Matches an ICMPv6 header followed by any message body.
+	 *
+	 * See struct rte_flow_item_icmp6.
+	 */
+	RTE_FLOW_ITEM_TYPE_ICMP6,
+
+	/**
+	 * Matches an ICMPv6 header followed by network discovery
+	 * neighbor solicitation.
+	 *
+	 * See struct rte_flow_item_icmp6_nd_ns.
+	 */
+	RTE_FLOW_ITEM_TYPE_ICMP6_ND_NS,
+
+	/**
+	 * Matches an ICMPv6 header followed by network discovery
+	 * neighbor advertisement.
+	 *
+	 * See struct rte_flow_item_icmp6_nd_na.
+	 */
+	RTE_FLOW_ITEM_TYPE_ICMP6_ND_NA,
+
+	/**
+	 * Matches an ICMPv6 header followed by network discovery neighbor
+	 * solicitation that contains source Ethernet link-layer address
+	 * option.
+	 *
+	 * See struct rte_flow_item_icmp6_nd_opt_sla_eth.
+	 */
+	RTE_FLOW_ITEM_TYPE_ICMP6_ND_OPT_SLA_ETH,
+
+	/**
+	 * Matches an ICMPv6 header followed by network discovery neighbor
+	 * advertisement that contains target Ethernet link-layer address
+	 * option.
+	 *
+	 * See struct rte_flow_item_icmp6_nd_opt_tla_eth.
+	 */
+	RTE_FLOW_ITEM_TYPE_ICMP6_ND_OPT_TLA_ETH,
 };
 
 /**
@@ -815,6 +870,186 @@ static const struct rte_flow_item_geneve rte_flow_item_geneve_mask = {
 #endif
 
 /**
+ * RTE_FLOW_ITEM_TYPE_ARP_IPV4
+ *
+ * Matches an IPv4 ARP header.
+ */
+struct rte_flow_item_arp_ipv4 {
+	rte_be16_t arp_hrd; /**< format of hardware address. */
+	rte_be16_t arp_pro; /**< format of protocol address. */
+	uint8_t arp_hln; /**< length of hardware address. */
+	uint8_t arp_pln; /**< length of protocol address. */
+	rte_be16_t arp_op; /**< ARP opcode */
+	struct ether_addr arp_sha; /**< sender hardware address. */
+	rte_be32_t arp_sip; /**< sender IP address. */
+	struct ether_addr arp_tha; /**< target hardware address. */
+	rte_be32_t arp_tip; /**< target IP address. */
+};
+
+/** Default mask for RTE_FLOW_ITEM_TYPE_ARP_IPV4. */
+#ifndef __cplusplus
+static const struct rte_flow_item_arp_ipv4 rte_flow_item_arp_ipv4_mask = {
+	.arp_sha = {
+		.addr_bytes = "\xff\xff\xff\xff\xff\xff",
+	},
+	.arp_sip = RTE_BE32(0xffffffff),
+	.arp_tha = {
+		.addr_bytes = "\xff\xff\xff\xff\xff\xff",
+	},
+	.arp_tip = RTE_BE32(0xffffffff),
+};
+#endif
+
+/**
+ * RTE_FLOW_ITEM_TYPE_IPV6_EXT
+ *
+ * Matches an IPv6 extension header with any type.
+ */
+struct rte_flow_item_ipv6_ext {
+	uint8_t next_hdr; /**< protocol of next  header */
+};
+
+/** Default mask for RTE_FLOW_ITEM_TYPE_IPV6_EXT. */
+#ifndef __cplusplus
+static const
+struct rte_flow_item_ipv6_ext rte_flow_item_ipv6_ext_mask = {
+	.next_hdr = 0xff,
+};
+#endif
+
+/**
+ * RTE_FLOW_ITEM_TYPE_ICMP6
+ *
+ * Matches an ICMPv6 header followed by any message body.
+ */
+struct rte_flow_item_icmp6 {
+	uint8_t type; /**< ICMPv6 type. */
+	uint8_t code; /**< ICMPv6 code. */
+	uint16_t checksum; /**< ICMPv6 checksum. */
+};
+
+/** Default mask for RTE_FLOW_ITEM_TYPE_ICMP6. */
+#ifndef __cplusplus
+static const struct rte_flow_item_icmp6 rte_flow_item_icmp6_mask = {
+	.type = 0xff,
+	.code = 0xff,
+};
+#endif
+
+/**
+ * RTE_FLOW_ITEM_TYPE_ICMP6_ND_NS
+ *
+ * Matches an ICMP6 header followed by network discovery
+ * neighbor solicitation.
+ */
+struct rte_flow_item_icmp6_nd_ns {
+	uint8_t type; /**< ICMPv6 type, normally 135. */
+	uint8_t code; /**< ICMPv6 code, normally 0. */
+	rte_be16_t checksum; /**< ICMPv6 checksum. */
+	rte_be32_t reserved;
+	uint8_t target_addr[16]; /**< Target address. */
+};
+
+/** Default mask for RTE_FLOW_ITEM_TYPE_ICMP6_ND_NS */
+#ifndef __cplusplus
+static const
+struct rte_flow_item_icmp6_nd_ns rte_flow_item_icmp6_nd_ns_mask = {
+	.target_addr =
+		"\xff\xff\xff\xff\xff\xff\xff\xff"
+		"\xff\xff\xff\xff\xff\xff\xff\xff",
+};
+#endif
+
+/**
+ * RTE_FLOW_ITEM_TYPE_ICMP6_ND_NA
+ *
+ * Matches an ICMPv6 header followed by network discovery
+ * neighbor advertisement.
+ */
+struct rte_flow_item_icmp6_nd_na {
+	uint8_t type; /**< ICMPv6 type, normally 136. */
+	uint8_t code; /**< ICMPv6 code, normally 0. */
+	rte_be16_t checksum; /**< ICMPv6 checksum. */
+	/**
+	 * Route flag (1b), solicited flag (1b), override flag (1b),
+	 * reserved (29b).
+	 */
+	rte_be32_t rso_reserved;
+	uint8_t target_addr[16]; /**< Target address. */
+};
+
+/** Default mask for RTE_FLOW_ITEM_TYPE_ICMP6_ND_NA. */
+#ifndef __cplusplus
+static const
+struct rte_flow_item_icmp6_nd_na rte_flow_item_icmp6_nd_na_mask = {
+	.target_addr =
+		"\xff\xff\xff\xff\xff\xff\xff\xff"
+		"\xff\xff\xff\xff\xff\xff\xff\xff",
+};
+#endif
+
+/**
+ * RTE_FLOW_ITEM_TYPE_ICMP6_ND_OPT_SLA_ETH
+ *
+ * Matches an ICMPv6 header followed by network discovery neighbor
+ * solicitation that contains source Ethernet link-layer address option.
+ */
+struct rte_flow_item_icmp6_nd_opt_sla_eth {
+	uint8_t type; /**< ICMPv6 type, normally 135. */
+	uint8_t code; /**< ICMPv6 code, normally 0. */
+	rte_be16_t checksum; /**< ICMPv6 checksum. */
+	rte_be32_t reserved;
+	uint8_t target_addr[16]; /**< Target address. */
+	struct ether_addr sll_addr; /**< Source Ethernet link-layer address. */
+};
+
+/** Default mask for RTE_FLOW_ITEM_TYPE_ICMP6_ND_OPT_SLA_ETH. */
+#ifndef __cplusplus
+static const struct rte_flow_item_icmp6_nd_opt_sla_eth
+	rte_flow_item_icmp6_nd_opt_sla_eth_mask = {
+	.target_addr =
+		"\xff\xff\xff\xff\xff\xff\xff\xff"
+		"\xff\xff\xff\xff\xff\xff\xff\xff",
+	.sll_addr = {
+		.addr_bytes = "\xff\xff\xff\xff\xff\xff",
+	}
+};
+#endif
+
+/**
+ * RTE_FLOW_ITEM_TYPE_ICMP6_ND_OPT_TLA_ETH
+ *
+ * Matches an ICMPv6 header followed by network discovery neighbor
+ * advertisement that contains target Ethernet link-layer address option.
+ */
+struct rte_flow_item_icmp6_nd_opt_tla_eth {
+	uint8_t type; /**< ICMPv6 type, normally 136. */
+	uint8_t code; /**< ICMPv6 code, normally 0. */
+	rte_be16_t checksum; /**< ICMPv6 checksum. */
+	/**
+	 * Route flag (1b), solicited flag (1b), override flag (1b),
+	 * reserved (29b).
+	 */
+	rte_be32_t rso_reserved;
+	uint8_t target_addr[16]; /**< Target address. */
+	struct ether_addr tll_addr; /**< Target Ethernet link-layer address. */
+
+};
+
+/** Default mask for RTE_FLOW_ITEM_TYPE_ICMP6_ND_OPT_TLA_ETH. */
+#ifndef __cplusplus
+static const struct rte_flow_item_icmp6_nd_opt_tla_eth
+	rte_flow_item_icmp6_nd_opt_tla_eth_mask = {
+	.target_addr =
+		"\xff\xff\xff\xff\xff\xff\xff\xff"
+		"\xff\xff\xff\xff\xff\xff\xff\xff",
+	.tll_addr = {
+		.addr_bytes = "\xff\xff\xff\xff\xff\xff",
+	}
+};
+#endif
+
+/**
  * Matching pattern item definition.
  *
  * A pattern is formed by stacking items starting from the lowest protocol
-- 
2.13.6

^ permalink raw reply	[flat|nested] 61+ messages in thread

* [dpdk-dev] [PATCH v3 2/4] ethdev: add packet field set aciton in flow API
  2018-04-16  6:10 ` [dpdk-dev] [PATCH v3 0/4] rte_flow extension for vSwitch acceleration Qi Zhang
  2018-04-16  6:10   ` [dpdk-dev] [PATCH v3 1/4] ethdev: add more protocol support in flow API Qi Zhang
@ 2018-04-16  6:10   ` Qi Zhang
  2018-04-19 14:48     ` Adrien Mazarguil
  2018-04-16  6:10   ` [dpdk-dev] [PATCH v3 3/4] ethdev: add TTL change actions " Qi Zhang
  2018-04-16  6:10   ` [dpdk-dev] [PATCH v3 4/4] ethdev: add VLAN and MPLS pop push action " Qi Zhang
  3 siblings, 1 reply; 61+ messages in thread
From: Qi Zhang @ 2018-04-16  6:10 UTC (permalink / raw)
  To: adrien.mazarguil
  Cc: dev, declan.doherty, sugesh.chandran, michael.j.glynn, yu.y.liu,
	konstantin.ananyev, bruce.richardson, Qi Zhang

Add new action RTE_FLOW_ACTION_TYPE_FIELD_SET, it is used to
modify fields of specific protocol layer of the packet, the
action only apply on packets that contain the requireds protocol
layer.

Signed-off-by: Qi Zhang <qi.z.zhang@intel.com>
---
 doc/guides/prog_guide/rte_flow.rst | 30 +++++++++++++++++++++++++++
 lib/librte_ether/rte_flow.h        | 42 +++++++++++++++++++++++++++++++++++++-
 2 files changed, 71 insertions(+), 1 deletion(-)

diff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst
index 99468bf60..68deb9812 100644
--- a/doc/guides/prog_guide/rte_flow.rst
+++ b/doc/guides/prog_guide/rte_flow.rst
@@ -1574,6 +1574,36 @@ fields in the pattern items.
    | 1     | END      |
    +-------+----------+
 
+Action: ``FILED_SET``
+^^^^^^^^^^^^^^^^^^^^^
+
+Modify the value of fields in a protocol layer, only applies to packets that
+contain respective protocol layer.
+
+.. _table_rte_flow_action_field_set:
+
+.. table:: FIELD_SET
+
+   +---------------+-------------------------------------------------------------------+
+   | Field         | Value                                                             |
+   +===============+===================================================================+
+   | ``type``      | Specify the type of a protocol layer. (see RTE_FLOW_ITEM_TYPE_*)  |
+   +---------------+-------------------------------------------------------------------+
+   | ``dir_level`` | Specify the level of matched protocol layer.                      |
+   |               | direction (1b)                                                    |
+   |               | 0: match start from outermost.                                    |
+   |               | 1: match start from innermost.                                    |
+   |               | level: (31b)                                                      |
+   |               | 0: outermost or innermost protocol layer that matched @type       |
+   |               | 1: next to outmost or innermost protocol layer that matched @type |
+   |               | 2: and so on ...                                                  |
+   +---------------+-------------------------------------------------------------------+
+   |  ``new_val``  | Pointer to specific data structure according to protocol type,    |
+   |               | the content is the new value to updtae.                           |
+   +---------------+-------------------------------------------------------------------+
+   |  ``mask``     | Bit-mask applied to new_val                                       |
+   +---------------+-------------------------------------------------------------------+
+
 Negative types
 ~~~~~~~~~~~~~~
 
diff --git a/lib/librte_ether/rte_flow.h b/lib/librte_ether/rte_flow.h
index f84bbfda5..2dc95b6b8 100644
--- a/lib/librte_ether/rte_flow.h
+++ b/lib/librte_ether/rte_flow.h
@@ -1245,7 +1245,15 @@ enum rte_flow_action_type {
 	 *
 	 * See struct rte_flow_action_security.
 	 */
-	RTE_FLOW_ACTION_TYPE_SECURITY
+	RTE_FLOW_ACTION_TYPE_SECURITY,
+
+	/**
+	 * Modify the value of fields in a protocol layer, only applies to
+	 * packets that contain respective protocol layer.
+	 *
+	 * See struct rte_flow_action_field_set.
+	 */
+	RTE_FLOW_ACTION_TYPE_FIELD_SET,
 };
 
 /**
@@ -1384,6 +1392,38 @@ struct rte_flow_action_security {
 };
 
 /**
+ * RTE_FLOW_ACTION_TYPE_FIELD_SET
+ *
+ * Modify the value of fields in a protocol layer, only applies to
+ * packets that contain respective protocol layer.
+ */
+struct rte_flow_action_field_set {
+	/**
+	 * Specify the type of a protocol layer.
+	 */
+	enum rte_flow_item_type type;
+	/**
+	 * Specify the level of matched protocol layer.
+	 *
+	 * direction (1b)
+	 * 0: match start from outermost.
+	 * 1: match start from innermost.
+	 *
+	 * level (31b)
+	 * 0: outermost|innermost protocol layer that matched @type.
+	 * 1: next to outermost|innermost protocol layer that matched @type.
+	 * 2: and so on ...
+	 */
+	uint32_t dir_level;
+	/**
+	 * Pointer to specific data structure according to protocol type,
+	 * the content is the new value to update.
+	 */
+	const void *new_val;
+	const void *mask; /**< Bit-mask applied to new_val. */
+};
+
+/**
  * Definition of a single action.
  *
  * A list of actions is terminated by a END action.
-- 
2.13.6

^ permalink raw reply	[flat|nested] 61+ messages in thread

* [dpdk-dev] [PATCH v3 3/4] ethdev: add TTL change actions in flow API
  2018-04-16  6:10 ` [dpdk-dev] [PATCH v3 0/4] rte_flow extension for vSwitch acceleration Qi Zhang
  2018-04-16  6:10   ` [dpdk-dev] [PATCH v3 1/4] ethdev: add more protocol support in flow API Qi Zhang
  2018-04-16  6:10   ` [dpdk-dev] [PATCH v3 2/4] ethdev: add packet field set aciton " Qi Zhang
@ 2018-04-16  6:10   ` Qi Zhang
  2018-04-19 14:48     ` Adrien Mazarguil
  2018-04-16  6:10   ` [dpdk-dev] [PATCH v3 4/4] ethdev: add VLAN and MPLS pop push action " Qi Zhang
  3 siblings, 1 reply; 61+ messages in thread
From: Qi Zhang @ 2018-04-16  6:10 UTC (permalink / raw)
  To: adrien.mazarguil
  Cc: dev, declan.doherty, sugesh.chandran, michael.j.glynn, yu.y.liu,
	konstantin.ananyev, bruce.richardson, Qi Zhang

Add couple OpenFlow frienldy TTL change actions.

RTE_FLOW_ACTION_MLPS_TTL_DEC - decrement MPLS TTL.
RTE_FLOW_ACTION_IP_TTL_DEC - decrement IP TTL.
RTE_FLOW_ACTION_TTL_COPY_OUT - copy TTL outwards.
RTE_FLOW_ACTION_TTL_COPY_IN - copy TTL inwards.

Signed-off-by: Qi Zhang <qi.z.zhang@intel.com>
---
 app/test-pmd/cmdline_flow.c                 | 64 +++++++++++++++++++++++
 doc/guides/prog_guide/rte_flow.rst          | 80 +++++++++++++++++++++++++++++
 doc/guides/testpmd_app_ug/testpmd_funcs.rst | 12 +++++
 lib/librte_ether/rte_flow.h                 | 77 +++++++++++++++++++++++++++
 4 files changed, 233 insertions(+)

diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c
index 7950b1b8d..417cbecc9 100644
--- a/app/test-pmd/cmdline_flow.c
+++ b/app/test-pmd/cmdline_flow.c
@@ -195,6 +195,12 @@ enum index {
 	ACTION_VF_ID,
 	ACTION_METER,
 	ACTION_METER_ID,
+	ACTION_MPLS_TTL_DEC,
+	ACTION_MPLS_TTL_DEC_LVL,
+	ACTION_IP_TTL_DEC,
+	ACTION_IP_TTL_DEC_LVL,
+	ACTION_TTL_COPY_OUT,
+	ACTION_TTL_COPY_IN,
 };
 
 /** Size of pattern[] field in struct rte_flow_item_raw. */
@@ -668,6 +674,10 @@ static const enum index next_action[] = {
 	ACTION_PF,
 	ACTION_VF,
 	ACTION_METER,
+	ACTION_MPLS_TTL_DEC,
+	ACTION_IP_TTL_DEC,
+	ACTION_TTL_COPY_OUT,
+	ACTION_TTL_COPY_IN,
 	ZERO,
 };
 
@@ -708,6 +718,16 @@ static const enum index action_meter[] = {
 	ZERO,
 };
 
+static const enum index action_mpls_ttl_dec[] = {
+	ACTION_MPLS_TTL_DEC_LVL,
+	ZERO,
+};
+
+static const enum index action_ip_ttl_dec[] = {
+	ACTION_IP_TTL_DEC_LVL,
+	ZERO,
+};
+
 static int parse_init(struct context *, const struct token *,
 		      const char *, unsigned int,
 		      void *, unsigned int);
@@ -1857,6 +1877,50 @@ static const struct token token_list[] = {
 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter, mtr_id)),
 		.call = parse_vc_conf,
 	},
+	[ACTION_MPLS_TTL_DEC] = {
+		.name = "mpls_ttl_dec",
+		.help = "decrement MPLS TTL",
+		.priv = PRIV_ACTION(MPLS_TTL_DEC,
+				sizeof(struct rte_flow_action_mpls_ttl_dec)),
+		.next = NEXT(action_mpls_ttl_dec),
+		.call = parse_vc,
+	},
+	[ACTION_MPLS_TTL_DEC_LVL] = {
+		.name = "level",
+		.help = "level of MPLS header",
+		.next = NEXT(action_mpls_ttl_dec, NEXT_ENTRY(UNSIGNED)),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_queue, index)),
+		.call = parse_vc,
+	},
+	[ACTION_IP_TTL_DEC] = {
+		.name = "ip_ttl_dec",
+		.help = "decrement IPv4 TTL or IPv6 Hop Limit",
+		.priv = PRIV_ACTION(MPLS_TTL_DEC,
+				sizeof(struct rte_flow_action_ip_ttl_dec)),
+		.next = NEXT(action_ip_ttl_dec),
+		.call = parse_vc,
+	},
+	[ACTION_IP_TTL_DEC_LVL] = {
+		.name = "level",
+		.help = "level of IPv4 or IPv6 header",
+		.next = NEXT(action_ip_ttl_dec, NEXT_ENTRY(UNSIGNED)),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_queue, index)),
+		.call = parse_vc,
+	},
+	[ACTION_TTL_COPY_OUT] = {
+		.name = "ttl_copy_out",
+		.help = "copy TTL outwards",
+		.priv = PRIV_ACTION(DROP, 0),
+		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
+		.call = parse_vc,
+	},
+	[ACTION_TTL_COPY_IN] = {
+		.name = "ttl_copy_in",
+		.help = "copy TTL inwards",
+		.priv = PRIV_ACTION(DROP, 0),
+		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
+		.call = parse_vc,
+	},
 };
 
 /** Remove and return last entry from argument stack. */
diff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst
index 68deb9812..65f2d4a16 100644
--- a/doc/guides/prog_guide/rte_flow.rst
+++ b/doc/guides/prog_guide/rte_flow.rst
@@ -1604,6 +1604,86 @@ contain respective protocol layer.
    |  ``mask``     | Bit-mask applied to new_val                                       |
    +---------------+-------------------------------------------------------------------+
 
+Action: ``MPLS_TTL_DEC``
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+Decrement MPLS TTL, only applies to packets that contain specific MPLS
+headers.
+
+.. _table_rte_flow_action_mpls_ttl_dec:
+
+.. table:: MPLS_TTL_DEC
+
+   +---------------+---------------------------------------------+
+   | Field         | Value                                       |
+   +===============+=============================================+
+   | ``dir_level`` | Specify the level of MPLS header.           |
+   |               | direction (1b)                              |
+   |               | 0: match start from outermost.              |
+   |               | 1: match start from innermost.              |
+   |               | level: (31b)                                |
+   |               | 0: outermost or innermost MPLS header       |
+   |               | 1: next to outmost or innermost MPLS header |
+   |               | 2: and so on ...                            |
+   +---------------+---------------------------------------------+
+
+Action: ``IP_TTL_DEC``
+^^^^^^^^^^^^^^^^^^^^^^
+
+Decrement IPv4 TTL or IPv6 hop limit field and update the IP checksum,
+only applies to packets that contain specific MPLS headers.
+
+.. _table_rte_flow_action_ip_ttl_dec:
+
+.. table:: IP_TTL_DEC
+
+   +---------------+----------------------------------------------------------+
+   | Field         | Value                                                    |
+   +===============+==========================================================+
+   | ``dir_level`` | Specify the level of IPv4 or IPv6 header.                |
+   |               | direction (1b)                                           |
+   |               | 0: match start from outermost.                           |
+   |               | 1: match start from innermost.                           |
+   |               | level: (31b)                                             |
+   |               | 0: outermost or innermost Ipv4 or IPv6 header            |
+   |               | 1: next to outmost or innermost MPLS IPv4 or IPv6 header |
+   |               | 2: and so on ...                                         |
+   +---------------+----------------------------------------------------------+
+
+Action: ``TTL_COPY_OUT``
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+Copy the TTL from next-to-outermost to outermost header with TTL, copy can
+be IP to IP, MPLS to MPLS or IP to MPLS, only applies packets that contain
+required MPLS or IP headers.
+
+.. _table_rte_flow_action_ttl_copy_out:
+
+.. table:: TTL_COPY_OUT
+
+   +---------------+
+   | Field         |
+   +===============+
+   | no properties |
+   +---------------+
+
+Action: ``TTL_COPY_IN``
+^^^^^^^^^^^^^^^^^^^^^^^
+
+Copy the TTL from outermost to next-to-outermost header with TTL, copy can
+be IP to IP, MPLS to MPLS or MPLS to IP, only applies packets that contain
+required MPLS or IP headers.
+
+.. _table_rte_flow_action_ttl_copy_in:
+
+.. table:: TTL_COPY_IN
+
+   +---------------+
+   | Field         |
+   +===============+
+   | no properties |
+   +---------------+
+
 Negative types
 ~~~~~~~~~~~~~~
 
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index 12d78f10b..d2fe6637b 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -3449,6 +3449,18 @@ This section lists supported actions and their attributes, if any.
   - ``original {boolean}``: use original VF ID if possible.
   - ``id {unsigned}``: VF ID to redirect packets to.
 
+- ``mpls_ttl_dec``: decrement MPLS TTL.
+
+  - ``level``: level of MPLS header.
+
+- ``ip_ttl_dec``: decrement IPv4 TTL or IPv6 Hot Limit.
+
+  - ``level``: level of IPv4 or IPv6 header.
+
+- ``ttl_copy_out``: copy TTL outwards.
+
+- ``ttl_copy_in``: copy TTL inwards.
+
 Destroying flow rules
 ~~~~~~~~~~~~~~~~~~~~~
 
diff --git a/lib/librte_ether/rte_flow.h b/lib/librte_ether/rte_flow.h
index 2dc95b6b8..ab181cd83 100644
--- a/lib/librte_ether/rte_flow.h
+++ b/lib/librte_ether/rte_flow.h
@@ -1254,6 +1254,37 @@ enum rte_flow_action_type {
 	 * See struct rte_flow_action_field_set.
 	 */
 	RTE_FLOW_ACTION_TYPE_FIELD_SET,
+
+	/**
+	 * Decrement MPLS TTL, only applies to packets that contain specific
+	 * MPLS header.
+	 *
+	 * See struct rte_flow_action_mpls_ttl_dec.
+	 */
+	RTE_FLOW_ACTION_TYPE_MPLS_TTL_DEC,
+
+	/**
+	 * Decrement IPv4 TTL or IPv6 Hop limit field and update the IP
+	 * checksum, only applies to packets that contain specific IPv4
+	 * or IPv6 header.
+	 *
+	 * See struct rte_flow_action_ip_ttl_dec.
+	 */
+	RTE_FLOW_ACTION_TYPE_IP_TTL_DEC,
+
+	/**
+	 * Copy the TTL from next-to-outermost to outermost header with TTL,
+	 * copy can be IP to IP, MPLS to MPLS or IP to MPLS, only applies
+	 * packets that contain required protocol headers.
+	 */
+	RTE_FLOW_ACTION_TYPE_TTL_COPY_OUT,
+
+	/**
+	 * Copy the TTL from outermost to next-to-outermost header with TTL,
+	 * copy can be IP to IP, MPLS to MPLS or MPLS to IP, only applies
+	 * packets that contain required protocol headers.
+	 */
+	RTE_FLOW_ACTION_TYPE_TTL_COPY_IN,
 };
 
 /**
@@ -1424,6 +1455,52 @@ struct rte_flow_action_field_set {
 };
 
 /**
+ * RTE_FLOW_ACTION_TYPE_MPLS_TTL_DEC
+ *
+ * Decrement MPLS TTL, only applies to packets that contain specific
+ * MPLS header.
+ */
+struct rte_flow_action_mpls_ttl_dec {
+	/**
+	 * Specify the level of MPLS header.
+	 *
+	 * direction (1b)
+	 * 0: match start from outermost.
+	 * 1: match start from innermost.
+	 *
+	 * level (31b)
+	 * 0: outermost|innermost MPLS header.
+	 * 1: next to outermost|innermost MPLS header.
+	 * 2: and so on ...
+	 */
+	uint32_t dir_level;
+
+};
+
+/**
+ * RTE_FLOW_ACTION_TYPE_IP_TTL_DEC
+ *
+ * Decrement IPv4 TTL or IPv6 hop limit field and update the IP
+ * checksum, only applies to packets that contain specific IPv4
+ * or IPv6 header.
+ */
+struct rte_flow_action_ip_ttl_dec {
+	/**
+	 * Specify the level of IPv4 or IPv6 header.
+	 *
+	 * direction (1b)
+	 * 0: match start from outermost.
+	 * 1: match start from innermost.
+	 *
+	 * level (31b)
+	 * 0: outermost|innermost IPv4 or IPv6 header.
+	 * 1: next to outermost|innermost IPv4 or IPv6 header.
+	 * 2: and so on ...
+	 */
+	uint32_t dir_level;
+};
+
+/**
  * Definition of a single action.
  *
  * A list of actions is terminated by a END action.
-- 
2.13.6

^ permalink raw reply	[flat|nested] 61+ messages in thread

* [dpdk-dev] [PATCH v3 4/4] ethdev: add VLAN and MPLS pop push action in flow API
  2018-04-16  6:10 ` [dpdk-dev] [PATCH v3 0/4] rte_flow extension for vSwitch acceleration Qi Zhang
                     ` (2 preceding siblings ...)
  2018-04-16  6:10   ` [dpdk-dev] [PATCH v3 3/4] ethdev: add TTL change actions " Qi Zhang
@ 2018-04-16  6:10   ` Qi Zhang
  2018-04-17  7:34     ` Shahaf Shuler
  2018-04-19 14:49     ` Adrien Mazarguil
  3 siblings, 2 replies; 61+ messages in thread
From: Qi Zhang @ 2018-04-16  6:10 UTC (permalink / raw)
  To: adrien.mazarguil
  Cc: dev, declan.doherty, sugesh.chandran, michael.j.glynn, yu.y.liu,
	konstantin.ananyev, bruce.richardson, Qi Zhang

Add couple Openflow frienldy VLAN/MPLS push/pop actions.

RTE_FLOW_ACTION_VLAN_POP - pop a VLAN header.
RTE_FLOW_ACTION_VLAN_PUSH - push a VLAN header.
RTE_FLOW_ACTION_MPLS_POP - pop a MPLS header.
RTE_FLOW_ACTION_MPLS_PUSH - push a MPLS header.

Signed-off-by: Qi Zhang <qi.z.zhang@intel.com>
---
 app/test-pmd/cmdline_flow.c                 | 82 +++++++++++++++++++++++++++++
 doc/guides/prog_guide/rte_flow.rst          | 69 ++++++++++++++++++++++++
 doc/guides/testpmd_app_ug/testpmd_funcs.rst | 14 +++++
 lib/librte_ether/rte_flow.h                 | 71 +++++++++++++++++++++++++
 4 files changed, 236 insertions(+)

diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c
index 417cbecc9..736d79bef 100644
--- a/app/test-pmd/cmdline_flow.c
+++ b/app/test-pmd/cmdline_flow.c
@@ -201,6 +201,13 @@ enum index {
 	ACTION_IP_TTL_DEC_LVL,
 	ACTION_TTL_COPY_OUT,
 	ACTION_TTL_COPY_IN,
+	ACTION_VLAN_POP,
+	ACTION_VLAN_PUSH,
+	ACTION_VLAN_PUSH_TYPE,
+	ACTION_MPLS_POP,
+	ACTION_MPLS_POP_TYPE,
+	ACTION_MPLS_PUSH,
+	ACTION_MPLS_PUSH_TYPE,
 };
 
 /** Size of pattern[] field in struct rte_flow_item_raw. */
@@ -678,6 +685,10 @@ static const enum index next_action[] = {
 	ACTION_IP_TTL_DEC,
 	ACTION_TTL_COPY_OUT,
 	ACTION_TTL_COPY_IN,
+	ACTION_VLAN_POP,
+	ACTION_VLAN_PUSH,
+	ACTION_MPLS_POP,
+	ACTION_MPLS_PUSH,
 	ZERO,
 };
 
@@ -728,6 +739,21 @@ static const enum index action_ip_ttl_dec[] = {
 	ZERO,
 };
 
+static const enum index action_vlan_push[] = {
+	ACTION_VLAN_PUSH_TYPE,
+	ZERO,
+};
+
+static const enum index action_mpls_pop[] = {
+	ACTION_MPLS_POP_TYPE,
+	ZERO,
+};
+
+static const enum index action_mpls_push[] = {
+	ACTION_MPLS_PUSH_TYPE,
+	ZERO,
+};
+
 static int parse_init(struct context *, const struct token *,
 		      const char *, unsigned int,
 		      void *, unsigned int);
@@ -1921,6 +1947,62 @@ static const struct token token_list[] = {
 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
 		.call = parse_vc,
 	},
+
+	[ACTION_VLAN_POP] = {
+		.name = "vlan_pop",
+		.help = "pop the outermost VLAN header.",
+		.priv = PRIV_ACTION(DROP, 0),
+		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
+		.call = parse_vc,
+	},
+	[ACTION_VLAN_PUSH] = {
+		.name = "vlan_push",
+		.help = "push new VLAN header onto the packet",
+		.priv = PRIV_ACTION(VLAN_PUSH,
+				sizeof(struct rte_flow_action_vlan_push)),
+		.next = NEXT(action_vlan_push),
+		.call = parse_vc,
+	},
+	[ACTION_VLAN_PUSH_TYPE] = {
+		.name = "type",
+		.help = "Ethertype of VLAN header",
+		.next = NEXT(action_vlan_push, NEXT_ENTRY(UNSIGNED)),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_vlan_push,
+					ether_type)),
+		.call = parse_vc,
+	},
+	[ACTION_MPLS_POP] = {
+		.name = "mpls_pop",
+		.help = "pop the outermost MPLS header",
+		.priv = PRIV_ACTION(MPLS_POP,
+				sizeof(struct rte_flow_action_mpls_pop)),
+		.next = NEXT(action_mpls_pop),
+		.call = parse_vc,
+	},
+	[ACTION_MPLS_POP_TYPE] = {
+		.name = "type",
+		.help = "Ethertype of MPLS header",
+		.next = NEXT(action_mpls_pop, NEXT_ENTRY(UNSIGNED)),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_mpls_pop,
+					ether_type)),
+		.call = parse_vc,
+	},
+	[ACTION_MPLS_PUSH] = {
+		.name = "mpls_push",
+		.help = "push new MPLS header onto the packet",
+		.priv = PRIV_ACTION(MPLS_PUSH,
+				sizeof(struct rte_flow_action_mpls_push)),
+		.next = NEXT(action_mpls_push),
+		.call = parse_vc,
+	},
+	[ACTION_MPLS_PUSH_TYPE] = {
+		.name = "type",
+		.help = "Ethertype of MPLS header",
+		.next = NEXT(action_mpls_push, NEXT_ENTRY(UNSIGNED)),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_mpls_push,
+					ether_type)),
+		.call = parse_vc,
+	},
 };
 
 /** Remove and return last entry from argument stack. */
diff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst
index 65f2d4a16..a009f1aac 100644
--- a/doc/guides/prog_guide/rte_flow.rst
+++ b/doc/guides/prog_guide/rte_flow.rst
@@ -1684,6 +1684,75 @@ required MPLS or IP headers.
    | no properties |
    +---------------+
 
+Action: ``ACTION_VLAN_POP``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Pop the outer-most VLAN header from the packet.
+
+.. _table_rte_flow_action_vlan_pop:
+
+.. table:: VLAN_POP
+
+   +---------------+
+   | Field         |
+   +===============+
+   | no properties |
+   +---------------+
+
+Action: ``ACTION_VLAN_PUSH``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Push a new VLAN header onto the packet, Ethertype 0x8100 or 0x88a8 should
+be used. The value of VLAN ID and VLAN priority for the new header is copied
+from an exist VLAN header in the packet, they will be set to 0 if no such
+VLAN header exist.
+
+.. _table_rte_flow_action_vlan_push:
+
+.. table:: VLAN_PUSH
+
+   +----------------+------------------------+
+   | Field          | Value                  |
+   +================+========================+
+   | ``ether_type`` | Ethertype for VLAN tag |
+   +----------------+------------------------+
+
+Action: ``ACTION_MPLS_POP``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Pop the outer-most MPLS header from the packet, Ethertype is required for
+the resulting packet if it is not the last MPLS header be popped, Ethertype
+must be 0x8847 or 0x8848.
+
+.. _table_rte_flow_action_mpls_pop:
+
+.. table:: MPLS_POP
+
+   +----------------+---------------------------+
+   | Field          | Value                     |
+   +================+===========================+
+   | ``ether_type`` | Ethertype for MPLS header |
+   +----------------+---------------------------+
+
+Action: ``ACTION_MPLS_PUSH``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Push a new MPLS header onto the packet, Ethertype 0x8847 or 0x8848 should
+be used. The value of MPLS label and traffic class is copied from exist
+outermost MPLS header, and TTL is copied from exist outermost MPLS or IP
+header, they will be set to 0 if exist packet does not contain required
+header.
+
+.. _table_rte_flow_action_mpls_push:
+
+.. table:: MPLS_PUSH
+
+   +----------------+---------------------------+
+   | Field          | Value                     |
+   +================+===========================+
+   | ``ether_type`` | Ethertype for MPLS header |
+   +----------------+---------------------------+
+
 Negative types
 ~~~~~~~~~~~~~~
 
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index d2fe6637b..c06f2f0b0 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -3461,6 +3461,20 @@ This section lists supported actions and their attributes, if any.
 
 - ``ttl_copy_in``: copy TTL inwards.
 
+- ``vlan_pop``: pop the outermost VLAN header.
+
+- ``vlan_push``: push new VLAN header onto the packet.
+
+  - ``type``: Ethertype of the VLAN header.
+
+- ``mpls_pop``: pop the outermost MPLS header.
+
+  - ``type``: Ethertype of the MPLS header.
+
+- ``mpls_push``: push new MPLS header onto the packet.
+
+  - ``type``: Ethertype of the MPLS header.
+
 Destroying flow rules
 ~~~~~~~~~~~~~~~~~~~~~
 
diff --git a/lib/librte_ether/rte_flow.h b/lib/librte_ether/rte_flow.h
index ab181cd83..c5b30363e 100644
--- a/lib/librte_ether/rte_flow.h
+++ b/lib/librte_ether/rte_flow.h
@@ -1285,6 +1285,41 @@ enum rte_flow_action_type {
 	 * packets that contain required protocol headers.
 	 */
 	RTE_FLOW_ACTION_TYPE_TTL_COPY_IN,
+
+	/**
+	 * Pop the outer-most VLAN header from the packet.
+	 */
+	RTE_FLOW_ACTION_TYPE_VLAN_POP,
+
+	/**
+	 * Push a new VLAN header onto the packet, Ethertype 0x8100 or 0x88a8
+	 * should be used. The value of VLAN ID and VLAN priority for the new
+	 * header is copied from an exist VLAN header in the packet, they will
+	 * be set to 0 if no such VLAN header exist.
+	 *
+	 * See struct rte_flow_action_vlan_push.
+	 */
+	RTE_FLOW_ACTION_TYPE_VLAN_PUSH,
+
+	/**
+	 * Pop the outer-most MPLS header from the packet, Ethertype is
+	 * required for the resulting packet if it is not the last MPLS
+	 * header be popped, Ethertype must be 0x8847 or 0x8848.
+	 *
+	 * See struct rte_flow_action_mpls_pop.
+	 */
+	RTE_FLOW_ACTION_TYPE_MPLS_POP,
+
+	/**
+	 * Push a new MPLS header onto the packet, Ethertype 0x8847 or 0x8848
+	 * should be used. The value of MPLS label and traffic class is copied
+	 * from exist outermost MPLS header, and TTL is copied from exist
+	 * outermost MPLS or IP header, they will be set to 0 if exist packet
+	 * does not contain required header.
+	 *
+	 * See struct rte_flow_action_mpls_push.
+	 */
+	RTE_FLOW_ACTION_TYPE_MPLS_PUSH,
 };
 
 /**
@@ -1501,6 +1536,42 @@ struct rte_flow_action_ip_ttl_dec {
 };
 
 /**
+ * RTE_FLOW_ACTION_TYPE_VLAN_PUSH,
+ *
+ * Push a new VLAN header onto the packet, Ethertype 0x8100 or 0x88a8
+ * should be used. The value of VLAN ID and VLAN priority for the new
+ * header is copied from an exist outermost VLAN header in the packet,
+ * they will be set to 0 if no such VLAN header exist.
+ */
+struct rte_flow_action_vlan_push {
+	rte_be16_t ether_type; /**< Ethertype for vlan tag. */
+};
+
+/**
+ * RTE_FLOW_ACTION_TYPE_MPLS_POP,
+ *
+ * Pop the outer-most MPLS header from the packet, Ethertype is
+ * required for the resulting packet if it is not the last MPLS
+ * header be popped, Ethertype must be 0x8847 or 0x8848.
+ */
+struct rte_flow_action_mpls_pop {
+	rte_be16_t ether_type; /**< Ethertype for MPLS header */
+};
+
+/**
+ * RTE_FLOW_ACTION_TYPE_MPLS_PUSH,
+ *
+ * Push a new MPLS header onto the packet, Ethertype 0x8847 or 0x8848
+ * should be used. The value of MPLS label and traffic class are copied
+ * from exist outermost MPLS header, and TTL is copied from exist outermost
+ * MPLS or IP header, they will be set to 0, if exist packet does not
+ * contain required header.
+ */
+struct rte_flow_action_mpls_push {
+	rte_be16_t ether_type; /**< Ethertype for MPLS header */
+};
+
+/**
  * Definition of a single action.
  *
  * A list of actions is terminated by a END action.
-- 
2.13.6

^ permalink raw reply	[flat|nested] 61+ messages in thread

* Re: [dpdk-dev] [PATCH v3 3/4] ethdev: add TTL change actions in flow API
  2018-04-16  5:48     ` Shahaf Shuler
@ 2018-04-16  8:12       ` Adrien Mazarguil
  2018-04-16  8:56         ` Shahaf Shuler
  0 siblings, 1 reply; 61+ messages in thread
From: Adrien Mazarguil @ 2018-04-16  8:12 UTC (permalink / raw)
  To: Shahaf Shuler
  Cc: Qi Zhang, dev, declan.doherty, sugesh.chandran, michael.j.glynn,
	yu.y.liu, konstantin.ananyev, bruce.richardson, Thomas Monjalon

Hi Shahaf,

On Mon, Apr 16, 2018 at 05:48:19AM +0000, Shahaf Shuler wrote:
> Hi Qi,
> 
> Am wondering if we can make the below more generic and not tailored for specific use cases. 

Regarding this, please see my previous answer [1] where I asked Qi to make
his changes more focused on the use case at hand when it became clear all
this work was targeting OpenFlow.

The OF specification [2] defines the behavior associated with each action,
for instance when a TTL is 0 or decrementing it would yield 0, the packet
must be dropped. Translating this to a generic decrement action for any
packet field is not so easy and not convenient.

Therefore my opinion is that if OF actions as defined by this specification
are supported as hardware capabilities, it makes sense to define dedicated
rte_flow actions for each of them (although "OF" should be part of their
name for clarity).

I'll comment the patch proper in a separate message.

[1] http://dpdk.org/ml/archives/dev/2018-April/096857.html
[2] https://www.opennetworking.org/images/stories/downloads/sdn-resources/onf-specifications/openflow/openflow-spec-v1.3.0.pdf

-- 
Adrien Mazarguil
6WIND

^ permalink raw reply	[flat|nested] 61+ messages in thread

* Re: [dpdk-dev] [PATCH v3 3/4] ethdev: add TTL change actions in flow API
  2018-04-16  8:12       ` Adrien Mazarguil
@ 2018-04-16  8:56         ` Shahaf Shuler
  2018-04-16  9:59           ` Adrien Mazarguil
  0 siblings, 1 reply; 61+ messages in thread
From: Shahaf Shuler @ 2018-04-16  8:56 UTC (permalink / raw)
  To: Adrien Mazarguil
  Cc: Qi Zhang, dev, declan.doherty, sugesh.chandran, michael.j.glynn,
	yu.y.liu, konstantin.ananyev, bruce.richardson, Thomas Monjalon

Monday, April 16, 2018 11:12 AM, Adrien Mazarguil:
> Subject: Re: [dpdk-dev] [PATCH v3 3/4] ethdev: add TTL change actions in
> flow API
> 
> Hi Shahaf,
> 
> On Mon, Apr 16, 2018 at 05:48:19AM +0000, Shahaf Shuler wrote:
> > Hi Qi,
> >
> > Am wondering if we can make the below more generic and not tailored for
> specific use cases.
> 
> Regarding this, please see my previous answer [1] where I asked Qi to make
> his changes more focused on the use case at hand when it became clear all
> this work was targeting OpenFlow.

OK,
I missed that. Sorry for jumping in late.

> 
> The OF specification [2] defines the behavior associated with each action, for
> instance when a TTL is 0 or decrementing it would yield 0, the packet must be
> dropped. Translating this to a generic decrement action for any packet field is
> not so easy and not convenient.

I am not sure I understand why. It is to set -1 in the TTL field of the generic action. 
We can define the corner cases more carefully as part of the actions. For example - no wrap around. 
I did not understood the drop if TTL is 0 is part of the action (it is not described the action description[1]).
Is this the case? 

I think it is wrong approach to introduce a "combo" actions (both decrements and drops if value) in rte_flow. 
I would model such  operation by a set of (pseudo code)
1. ACTION_FIELD_DEC_INC , ACTION_GO_TO_GROUP
2. (in next group) matching on the TTL , ACTION_DROP 

> 
> Therefore my opinion is that if OF actions as defined by this specification are
> supported as hardware capabilities, it makes sense to define dedicated
> rte_flow actions for each of them (although "OF" should be part of their
> name for clarity).

I still think we may need in the future to support copy/increment/decrement of fields not specifically related to OF. 
It is better to have APIs which will not change or have double meaning. 


[1]
[1]
+Action: ``IP_TTL_DEC``
+^^^^^^^^^^^^^^^^^^^^^^
+
+Decrement IPv4 TTL or IPv6 hop limit field and update the IP checksum, 
+only applies to packets that contain specific MPLS headers.
+
+.. _table_rte_flow_action_ip_ttl_dec:
+
+.. table:: IP_TTL_DEC


> 
> I'll comment the patch proper in a separate message.
> 
> [1]
> https://emea01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fdpd
> k.org%2Fml%2Farchives%2Fdev%2F2018-
> April%2F096857.html&data=02%7C01%7Cshahafs%40mellanox.com%7C6d2b
> 747ae47841bc55e508d5a371d2f4%7Ca652971c7d2e4d9ba6a4d149256f461b%7
> C0%7C0%7C636594631626247567&sdata=3oTbKT6QwS1WiAIrkF885dEU76ep4
> xreuHoHiwDA2Ec%3D&reserved=0
> [2]
> https://emea01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fw
> ww.opennetworking.org%2Fimages%2Fstories%2Fdownloads%2Fsdn-
> resources%2Fonf-specifications%2Fopenflow%2Fopenflow-spec-
> v1.3.0.pdf&data=02%7C01%7Cshahafs%40mellanox.com%7C6d2b747ae4784
> 1bc55e508d5a371d2f4%7Ca652971c7d2e4d9ba6a4d149256f461b%7C0%7C1%
> 7C636594631626247567&sdata=e6uelVwIu1poE2uIvEJELuIzela8H%2B8HclQE5
> EdKEaM%3D&reserved=0
> 
> --
> Adrien Mazarguil
> 6WIND

^ permalink raw reply	[flat|nested] 61+ messages in thread

* Re: [dpdk-dev] [PATCH v3 3/4] ethdev: add TTL change actions in flow API
  2018-04-16  8:56         ` Shahaf Shuler
@ 2018-04-16  9:59           ` Adrien Mazarguil
  0 siblings, 0 replies; 61+ messages in thread
From: Adrien Mazarguil @ 2018-04-16  9:59 UTC (permalink / raw)
  To: Shahaf Shuler
  Cc: Qi Zhang, dev, declan.doherty, sugesh.chandran, michael.j.glynn,
	yu.y.liu, konstantin.ananyev, bruce.richardson, Thomas Monjalon

On Mon, Apr 16, 2018 at 08:56:37AM +0000, Shahaf Shuler wrote:
> Monday, April 16, 2018 11:12 AM, Adrien Mazarguil:
> > Subject: Re: [dpdk-dev] [PATCH v3 3/4] ethdev: add TTL change actions in
> > flow API
> > 
> > Hi Shahaf,
> > 
> > On Mon, Apr 16, 2018 at 05:48:19AM +0000, Shahaf Shuler wrote:
> > > Hi Qi,
> > >
> > > Am wondering if we can make the below more generic and not tailored for
> > specific use cases.
> > 
> > Regarding this, please see my previous answer [1] where I asked Qi to make
> > his changes more focused on the use case at hand when it became clear all
> > this work was targeting OpenFlow.
> 
> OK,
> I missed that. Sorry for jumping in late.
> 
> > 
> > The OF specification [2] defines the behavior associated with each action, for
> > instance when a TTL is 0 or decrementing it would yield 0, the packet must be
> > dropped. Translating this to a generic decrement action for any packet field is
> > not so easy and not convenient.
> 
> I am not sure I understand why. It is to set -1 in the TTL field of the generic action. 
> We can define the corner cases more carefully as part of the actions. For example - no wrap around. 
> I did not understood the drop if TTL is 0 is part of the action (it is not described the action description[1]).
> Is this the case? 

I still need to comment the original patch :)

Basically I would like to make all these actions point to the OpenFlow
action documentation describing them with a disclaimer such as "These are
OpenFlow actions, here's a summary of what they do, see linked OF
documentation for details".

> I think it is wrong approach to introduce a "combo" actions (both decrements and drops if value) in rte_flow. 
> I would model such  operation by a set of (pseudo code)
> 1. ACTION_FIELD_DEC_INC , ACTION_GO_TO_GROUP
> 2. (in next group) matching on the TTL , ACTION_DROP 

If a device really implements something that does "check TTL on protocol $FOO,
decrement it, re-check TTL, update checksum, drop packet if any of the
previous steps failed", then by all means I think a dedicated action is
justified. It's also easier to document as "does what OpenFlow specifies"
and much more convenient to applications.

Another set of actions can be added for devices (or PMDs) with partial
support (e.g. to expose a "dumb" decrement capability as in the original
series).

The real question is are there devices that fully implement OF actions as
described by the linked spec? Can any missing bits be handled by PMDs
without a noticeable performance impact?

> > Therefore my opinion is that if OF actions as defined by this specification are
> > supported as hardware capabilities, it makes sense to define dedicated
> > rte_flow actions for each of them (although "OF" should be part of their
> > name for clarity).
> 
> I still think we may need in the future to support copy/increment/decrement of fields not specifically related to OF. 
> It is better to have APIs which will not change or have double meaning. 

We could add them later on a needed basis. Correct me if I'm wrong, but
right now OF is the only use case everyone has in mind. Application
developers will always favor a set of explicit OF actions over more
convoluted means of achieving the expected behavior.

> [1]
> +Action: ``IP_TTL_DEC``
> +^^^^^^^^^^^^^^^^^^^^^^
> +
> +Decrement IPv4 TTL or IPv6 hop limit field and update the IP checksum, 
> +only applies to packets that contain specific MPLS headers.
> +
> +.. _table_rte_flow_action_ip_ttl_dec:
> +
> +.. table:: IP_TTL_DEC
> 
> 
> > 
> > I'll comment the patch proper in a separate message.
> > 
> > [1]
> > https://emea01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fdpd
> > k.org%2Fml%2Farchives%2Fdev%2F2018-
> > April%2F096857.html&data=02%7C01%7Cshahafs%40mellanox.com%7C6d2b
> > 747ae47841bc55e508d5a371d2f4%7Ca652971c7d2e4d9ba6a4d149256f461b%7
> > C0%7C0%7C636594631626247567&sdata=3oTbKT6QwS1WiAIrkF885dEU76ep4
> > xreuHoHiwDA2Ec%3D&reserved=0
> > [2]
> > https://emea01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fw
> > ww.opennetworking.org%2Fimages%2Fstories%2Fdownloads%2Fsdn-
> > resources%2Fonf-specifications%2Fopenflow%2Fopenflow-spec-
> > v1.3.0.pdf&data=02%7C01%7Cshahafs%40mellanox.com%7C6d2b747ae4784
> > 1bc55e508d5a371d2f4%7Ca652971c7d2e4d9ba6a4d149256f461b%7C0%7C1%
> > 7C636594631626247567&sdata=e6uelVwIu1poE2uIvEJELuIzela8H%2B8HclQE5
> > EdKEaM%3D&reserved=0
> > 
> > --
> > Adrien Mazarguil
> > 6WIND

-- 
Adrien Mazarguil
6WIND

^ permalink raw reply	[flat|nested] 61+ messages in thread

* Re: [dpdk-dev] [PATCH v2 4/4] ether: add packet modification aciton in flow API
  2018-04-13 13:47           ` Zhang, Qi Z
@ 2018-04-16 13:30             ` Adrien Mazarguil
  2018-04-16 15:03               ` Zhang, Qi Z
  0 siblings, 1 reply; 61+ messages in thread
From: Adrien Mazarguil @ 2018-04-16 13:30 UTC (permalink / raw)
  To: Zhang, Qi Z
  Cc: dev, Doherty, Declan, Chandran, Sugesh, Glynn, Michael J, Liu,
	Yu Y, Ananyev, Konstantin, Richardson, Bruce

On Fri, Apr 13, 2018 at 01:47:15PM +0000, Zhang, Qi Z wrote:
> > -----Original Message-----
> > From: Adrien Mazarguil [mailto:adrien.mazarguil@6wind.com]
> > Sent: Thursday, April 12, 2018 6:23 PM
> > To: Zhang, Qi Z <qi.z.zhang@intel.com>
> > Cc: dev@dpdk.org; Doherty, Declan <declan.doherty@intel.com>; Chandran,
> > Sugesh <sugesh.chandran@intel.com>; Glynn, Michael J
> > <michael.j.glynn@intel.com>; Liu, Yu Y <yu.y.liu@intel.com>; Ananyev,
> > Konstantin <konstantin.ananyev@intel.com>; Richardson, Bruce
> > <bruce.richardson@intel.com>
> > Subject: Re: [PATCH v2 4/4] ether: add packet modification aciton in flow API
> > 
> > On Thu, Apr 12, 2018 at 08:50:14AM +0000, Zhang, Qi Z wrote:
> > > Hi Adrien
> > >
> > > > -----Original Message-----
> > > > From: Adrien Mazarguil [mailto:adrien.mazarguil@6wind.com]
> > > > Sent: Thursday, April 12, 2018 3:04 PM
> > > > To: Zhang, Qi Z <qi.z.zhang@intel.com>
> > > > Cc: dev@dpdk.org; Doherty, Declan <declan.doherty@intel.com>;
> > > > Chandran, Sugesh <sugesh.chandran@intel.com>; Glynn, Michael J
> > > > <michael.j.glynn@intel.com>; Liu, Yu Y <yu.y.liu@intel.com>;
> > > > Ananyev, Konstantin <konstantin.ananyev@intel.com>; Richardson,
> > > > Bruce <bruce.richardson@intel.com>
> > > > Subject: Re: [PATCH v2 4/4] ether: add packet modification aciton in
> > > > flow API
> > > >
> > > > On Sun, Apr 01, 2018 at 05:19:22PM -0400, Qi Zhang wrote:
> > > > > Add new actions that be used to modify packet content with generic
> > > > > semantic:
> > > > >
> > > > > RTE_FLOW_ACTION_TYPE_FIELD_UPDATE:
> > > > > 	- update specific field of packet
> > > > > RTE_FLWO_ACTION_TYPE_FIELD_INCREMENT:
> > > > > 	- increament specific field of packet
> > > > > RTE_FLWO_ACTION_TYPE_FIELD_DECREMENT:
> > > > > 	- decreament specific field of packet
> > > > > RTE_FLWO_ACTION_TYPE_FIELD_COPY:
> > > > > 	- copy data from one field to another in packet.
> > > > >
> > > > > All action use struct rte_flow_item parameter to match the pattern
> > > > > that going to be modified, if no pattern match, the action just be
> > > > > skipped.
<snip>
> > > > What happens when this action is attempted on non-matching traffic
> > > > must be documented here as well. Refer to discussion re "ethdev: Add
> > > > tunnel encap/decap actions" [3]. To be on the safe side, it must be
> > > > documented as resulting in undefined behavior.
> > >
> > > so what is "undefined behavior" you means?
> > > The rule is:
> > > If a packet matched pattern in action, it will be modified, otherwise
> > > the action just take no effect is this idea acceptable?
> > 
> > Not really, what happens will depend on the underlying device. It's better to
> > document it as undefined because you can't predict the result. Some devices
> > will cause packets to be lost, others will let them through unchanged, others
> > will crash the system after formatting the hard drive, no one knows.
> 
> OK, basically I think "undefined behavior" is not friendly to application, we should avoid.
> But you are right, we need to consider device with different behavior for " modification on non-matched pattern"
> I'm thinking why driver can't avoid non-matched pattern modification if the device does not support?
> For example, driver can reject a flow ETH/IPV4 with TCP action, but may accept ETH/IPV4/TCP with TCP action base on 
> its capability.

Drivers are free to accept an action or not depending on what is guaranteed
to be matched on the pattern side. It's fine as long as the resulting flow
rule works exactly as documented. Consistency is much more important to
applications than offloads proper.

Depending on device capabilities and the importance given to offload
specific use cases by vendors, PMD support may range from a basic 1:1
translation attempt between rte_flow and device format, to an all out
processing effort resulting in multiple device flow rules and whatnot to
satisfy the request by any means necessary (see mlx5 RSS support on empty
patterns in case you're curious).

Whichever approach you choose (basic or complex), my recommendation is
simply to make sure the PMD reports an error whenever a flow rule is
ambiguous and could result in unexpected behavior if applied as is to the
device.

The error message should also be helpful. A message such as "unable to apply
flow rule" is pretty useless, while "this action is not supported when X
pattern item is not present" actually gives useful information.

"Undefined behavior" is for application writers. It means that if a PMD
happens to accept the rule in question, what happens isn't covered by
documentation. Ideally a PMD shouldn't accept it in the first place
though.

-- 
Adrien Mazarguil
6WIND

^ permalink raw reply	[flat|nested] 61+ messages in thread

* Re: [dpdk-dev] [PATCH v2 4/4] ether: add packet modification aciton in flow API
  2018-04-16 13:30             ` Adrien Mazarguil
@ 2018-04-16 15:03               ` Zhang, Qi Z
  2018-04-17  9:55                 ` Adrien Mazarguil
  0 siblings, 1 reply; 61+ messages in thread
From: Zhang, Qi Z @ 2018-04-16 15:03 UTC (permalink / raw)
  To: Adrien Mazarguil
  Cc: dev, Doherty, Declan, Chandran, Sugesh, Glynn, Michael J, Liu,
	Yu Y, Ananyev, Konstantin, Richardson, Bruce



> -----Original Message-----
> From: Adrien Mazarguil [mailto:adrien.mazarguil@6wind.com]
> Sent: Monday, April 16, 2018 9:31 PM
> To: Zhang, Qi Z <qi.z.zhang@intel.com>
> Cc: dev@dpdk.org; Doherty, Declan <declan.doherty@intel.com>; Chandran,
> Sugesh <sugesh.chandran@intel.com>; Glynn, Michael J
> <michael.j.glynn@intel.com>; Liu, Yu Y <yu.y.liu@intel.com>; Ananyev,
> Konstantin <konstantin.ananyev@intel.com>; Richardson, Bruce
> <bruce.richardson@intel.com>
> Subject: Re: [PATCH v2 4/4] ether: add packet modification aciton in flow API
> 
> On Fri, Apr 13, 2018 at 01:47:15PM +0000, Zhang, Qi Z wrote:
> > > -----Original Message-----
> > > From: Adrien Mazarguil [mailto:adrien.mazarguil@6wind.com]
> > > Sent: Thursday, April 12, 2018 6:23 PM
> > > To: Zhang, Qi Z <qi.z.zhang@intel.com>
> > > Cc: dev@dpdk.org; Doherty, Declan <declan.doherty@intel.com>;
> > > Chandran, Sugesh <sugesh.chandran@intel.com>; Glynn, Michael J
> > > <michael.j.glynn@intel.com>; Liu, Yu Y <yu.y.liu@intel.com>;
> > > Ananyev, Konstantin <konstantin.ananyev@intel.com>; Richardson,
> > > Bruce <bruce.richardson@intel.com>
> > > Subject: Re: [PATCH v2 4/4] ether: add packet modification aciton in
> > > flow API
> > >
> > > On Thu, Apr 12, 2018 at 08:50:14AM +0000, Zhang, Qi Z wrote:
> > > > Hi Adrien
> > > >
> > > > > -----Original Message-----
> > > > > From: Adrien Mazarguil [mailto:adrien.mazarguil@6wind.com]
> > > > > Sent: Thursday, April 12, 2018 3:04 PM
> > > > > To: Zhang, Qi Z <qi.z.zhang@intel.com>
> > > > > Cc: dev@dpdk.org; Doherty, Declan <declan.doherty@intel.com>;
> > > > > Chandran, Sugesh <sugesh.chandran@intel.com>; Glynn, Michael J
> > > > > <michael.j.glynn@intel.com>; Liu, Yu Y <yu.y.liu@intel.com>;
> > > > > Ananyev, Konstantin <konstantin.ananyev@intel.com>; Richardson,
> > > > > Bruce <bruce.richardson@intel.com>
> > > > > Subject: Re: [PATCH v2 4/4] ether: add packet modification
> > > > > aciton in flow API
> > > > >
> > > > > On Sun, Apr 01, 2018 at 05:19:22PM -0400, Qi Zhang wrote:
> > > > > > Add new actions that be used to modify packet content with
> > > > > > generic
> > > > > > semantic:
> > > > > >
> > > > > > RTE_FLOW_ACTION_TYPE_FIELD_UPDATE:
> > > > > > 	- update specific field of packet
> > > > > > RTE_FLWO_ACTION_TYPE_FIELD_INCREMENT:
> > > > > > 	- increament specific field of packet
> > > > > > RTE_FLWO_ACTION_TYPE_FIELD_DECREMENT:
> > > > > > 	- decreament specific field of packet
> > > > > > RTE_FLWO_ACTION_TYPE_FIELD_COPY:
> > > > > > 	- copy data from one field to another in packet.
> > > > > >
> > > > > > All action use struct rte_flow_item parameter to match the
> > > > > > pattern that going to be modified, if no pattern match, the
> > > > > > action just be skipped.
> <snip>
> > > > > What happens when this action is attempted on non-matching
> > > > > traffic must be documented here as well. Refer to discussion re
> > > > > "ethdev: Add tunnel encap/decap actions" [3]. To be on the safe
> > > > > side, it must be documented as resulting in undefined behavior.
> > > >
> > > > so what is "undefined behavior" you means?
> > > > The rule is:
> > > > If a packet matched pattern in action, it will be modified,
> > > > otherwise the action just take no effect is this idea acceptable?
> > >
> > > Not really, what happens will depend on the underlying device. It's
> > > better to document it as undefined because you can't predict the
> > > result. Some devices will cause packets to be lost, others will let
> > > them through unchanged, others will crash the system after formatting
> the hard drive, no one knows.
> >
> > OK, basically I think "undefined behavior" is not friendly to application, we
> should avoid.
> > But you are right, we need to consider device with different behavior for "
> modification on non-matched pattern"
> > I'm thinking why driver can't avoid non-matched pattern modification if the
> device does not support?
> > For example, driver can reject a flow ETH/IPV4 with TCP action, but
> > may accept ETH/IPV4/TCP with TCP action base on its capability.
> 
> Drivers are free to accept an action or not depending on what is guaranteed
> to be matched on the pattern side. It's fine as long as the resulting flow rule
> works exactly as documented. Consistency is much more important to
> applications than offloads proper.
> 
> Depending on device capabilities and the importance given to offload specific
> use cases by vendors, PMD support may range from a basic 1:1 translation
> attempt between rte_flow and device format, to an all out processing effort
> resulting in multiple device flow rules and whatnot to satisfy the request by
> any means necessary (see mlx5 RSS support on empty patterns in case you're
> curious).
> 
> Whichever approach you choose (basic or complex), my recommendation is
> simply to make sure the PMD reports an error whenever a flow rule is
> ambiguous and could result in unexpected behavior if applied as is to the
> device.
> 
> The error message should also be helpful. A message such as "unable to
> apply flow rule" is pretty useless, while "this action is not supported when X
> pattern item is not present" actually gives useful information.

> 
> "Undefined behavior" is for application writers. It means that if a PMD
> happens to accept the rule in question, what happens isn't covered by
> documentation. Ideally a PMD shouldn't accept it in the first place though.

OK, I'm trying to understand why "Undefined behavior" is necessary for this action.
For example, we have a device that can offload TCP layer modification, for packet that contain TCP, packet be modified, for no-tcp packet, the packet will be dropped
Also the device does not support TCP filter, so we are not able to create a flow to filter TCP packet only. 
Then without "Undefined behavior", the driver has to reject any flow with TCP packet modification action, since it can't guarantee no-tcp packet not be impacted, 
while with " Undefined behavior", a flow with tcp action is actually is a "rule in question" and it can "happens to" be accepted by the driver?
  
Regards
Qi

> 
> --
> Adrien Mazarguil
> 6WIND

^ permalink raw reply	[flat|nested] 61+ messages in thread

* Re: [dpdk-dev] [PATCH v3 4/4] ethdev: add VLAN and MPLS pop push action in flow API
  2018-04-16  6:10   ` [dpdk-dev] [PATCH v3 4/4] ethdev: add VLAN and MPLS pop push action " Qi Zhang
@ 2018-04-17  7:34     ` Shahaf Shuler
  2018-04-19 14:49     ` Adrien Mazarguil
  1 sibling, 0 replies; 61+ messages in thread
From: Shahaf Shuler @ 2018-04-17  7:34 UTC (permalink / raw)
  To: Qi Zhang, Adrien Mazarguil
  Cc: dev, declan.doherty, sugesh.chandran, michael.j.glynn, yu.y.liu,
	konstantin.ananyev, bruce.richardson

Monday, April 16, 2018 9:11 AM, Qi Zhang:
> Subject: [dpdk-dev] [PATCH v3 4/4] ethdev: add VLAN and MPLS pop push
> action in flow API
> 
> Add couple Openflow frienldy VLAN/MPLS push/pop actions.
> 
> RTE_FLOW_ACTION_VLAN_POP - pop a VLAN header.
> RTE_FLOW_ACTION_VLAN_PUSH - push a VLAN header.
> RTE_FLOW_ACTION_MPLS_POP - pop a MPLS header.
> RTE_FLOW_ACTION_MPLS_PUSH - push a MPLS header.
> 
> Signed-off-by: Qi Zhang <qi.z.zhang@intel.com>
> ---


>  /**
> @@ -1501,6 +1536,42 @@ struct rte_flow_action_ip_ttl_dec {  };
> 
>  /**
> + * RTE_FLOW_ACTION_TYPE_VLAN_PUSH,
> + *
> + * Push a new VLAN header onto the packet, Ethertype 0x8100 or 0x88a8
> + * should be used. The value of VLAN ID and VLAN priority for the new
> + * header is copied from an exist outermost VLAN header in the packet,
> + * they will be set to 0 if no such VLAN header exist.
> + */
> +struct rte_flow_action_vlan_push {
> +	rte_be16_t ether_type; /**< Ethertype for vlan tag. */ };
> +

I may have missed this also in the previous discussions.
But why limit the VLAN ID and prio to 0 if not exists? 
Why not to enable the application to define the full VLAN header it wants to push? The default, if application hasn't specified any, can be what you suggest. 

> +/**
> + * RTE_FLOW_ACTION_TYPE_MPLS_POP,
> + *
> + * Pop the outer-most MPLS header from the packet, Ethertype is
> + * required for the resulting packet if it is not the last MPLS
> + * header be popped, Ethertype must be 0x8847 or 0x8848.
> + */
> +struct rte_flow_action_mpls_pop {
> +	rte_be16_t ether_type; /**< Ethertype for MPLS header */ };
> +
> +/**
> + * RTE_FLOW_ACTION_TYPE_MPLS_PUSH,
> + *
> + * Push a new MPLS header onto the packet, Ethertype 0x8847 or 0x8848
> + * should be used. The value of MPLS label and traffic class are copied
> + * from exist outermost MPLS header, and TTL is copied from exist
> +outermost

I guess those are derived from OF spec. 

> + * MPLS or IP header, they will be set to 0, if exist packet does not
> + * contain required header.
> + */
> +struct rte_flow_action_mpls_push {
> +	rte_be16_t ether_type; /**< Ethertype for MPLS header */ };
> +

Same question as above - why not let the user to specify its MPLS header and have what you suggest as default behavior?

> +/**
>   * Definition of a single action.
>   *
>   * A list of actions is terminated by a END action.
> --
> 2.13.6

^ permalink raw reply	[flat|nested] 61+ messages in thread

* Re: [dpdk-dev] [PATCH v2 4/4] ether: add packet modification aciton in flow API
  2018-04-16 15:03               ` Zhang, Qi Z
@ 2018-04-17  9:55                 ` Adrien Mazarguil
  2018-04-17 10:32                   ` Zhang, Qi Z
  0 siblings, 1 reply; 61+ messages in thread
From: Adrien Mazarguil @ 2018-04-17  9:55 UTC (permalink / raw)
  To: Zhang, Qi Z
  Cc: dev, Doherty, Declan, Chandran, Sugesh, Glynn, Michael J, Liu,
	Yu Y, Ananyev, Konstantin, Richardson, Bruce

On Mon, Apr 16, 2018 at 03:03:39PM +0000, Zhang, Qi Z wrote:
> > -----Original Message-----
> > From: Adrien Mazarguil [mailto:adrien.mazarguil@6wind.com]
> > Sent: Monday, April 16, 2018 9:31 PM
> > To: Zhang, Qi Z <qi.z.zhang@intel.com>
> > Cc: dev@dpdk.org; Doherty, Declan <declan.doherty@intel.com>; Chandran,
> > Sugesh <sugesh.chandran@intel.com>; Glynn, Michael J
> > <michael.j.glynn@intel.com>; Liu, Yu Y <yu.y.liu@intel.com>; Ananyev,
> > Konstantin <konstantin.ananyev@intel.com>; Richardson, Bruce
> > <bruce.richardson@intel.com>
> > Subject: Re: [PATCH v2 4/4] ether: add packet modification aciton in flow API
> > 
> > On Fri, Apr 13, 2018 at 01:47:15PM +0000, Zhang, Qi Z wrote:
> > > > -----Original Message-----
> > > > From: Adrien Mazarguil [mailto:adrien.mazarguil@6wind.com]
> > > > Sent: Thursday, April 12, 2018 6:23 PM
> > > > To: Zhang, Qi Z <qi.z.zhang@intel.com>
> > > > Cc: dev@dpdk.org; Doherty, Declan <declan.doherty@intel.com>;
> > > > Chandran, Sugesh <sugesh.chandran@intel.com>; Glynn, Michael J
> > > > <michael.j.glynn@intel.com>; Liu, Yu Y <yu.y.liu@intel.com>;
> > > > Ananyev, Konstantin <konstantin.ananyev@intel.com>; Richardson,
> > > > Bruce <bruce.richardson@intel.com>
> > > > Subject: Re: [PATCH v2 4/4] ether: add packet modification aciton in
> > > > flow API
> > > >
> > > > On Thu, Apr 12, 2018 at 08:50:14AM +0000, Zhang, Qi Z wrote:
> > > > > Hi Adrien
> > > > >
> > > > > > -----Original Message-----
> > > > > > From: Adrien Mazarguil [mailto:adrien.mazarguil@6wind.com]
> > > > > > Sent: Thursday, April 12, 2018 3:04 PM
> > > > > > To: Zhang, Qi Z <qi.z.zhang@intel.com>
> > > > > > Cc: dev@dpdk.org; Doherty, Declan <declan.doherty@intel.com>;
> > > > > > Chandran, Sugesh <sugesh.chandran@intel.com>; Glynn, Michael J
> > > > > > <michael.j.glynn@intel.com>; Liu, Yu Y <yu.y.liu@intel.com>;
> > > > > > Ananyev, Konstantin <konstantin.ananyev@intel.com>; Richardson,
> > > > > > Bruce <bruce.richardson@intel.com>
> > > > > > Subject: Re: [PATCH v2 4/4] ether: add packet modification
> > > > > > aciton in flow API
> > > > > >
> > > > > > On Sun, Apr 01, 2018 at 05:19:22PM -0400, Qi Zhang wrote:
> > > > > > > Add new actions that be used to modify packet content with
> > > > > > > generic
> > > > > > > semantic:
> > > > > > >
> > > > > > > RTE_FLOW_ACTION_TYPE_FIELD_UPDATE:
> > > > > > > 	- update specific field of packet
> > > > > > > RTE_FLWO_ACTION_TYPE_FIELD_INCREMENT:
> > > > > > > 	- increament specific field of packet
> > > > > > > RTE_FLWO_ACTION_TYPE_FIELD_DECREMENT:
> > > > > > > 	- decreament specific field of packet
> > > > > > > RTE_FLWO_ACTION_TYPE_FIELD_COPY:
> > > > > > > 	- copy data from one field to another in packet.
> > > > > > >
> > > > > > > All action use struct rte_flow_item parameter to match the
> > > > > > > pattern that going to be modified, if no pattern match, the
> > > > > > > action just be skipped.
> > <snip>
> > > > > > What happens when this action is attempted on non-matching
> > > > > > traffic must be documented here as well. Refer to discussion re
> > > > > > "ethdev: Add tunnel encap/decap actions" [3]. To be on the safe
> > > > > > side, it must be documented as resulting in undefined behavior.
> > > > >
> > > > > so what is "undefined behavior" you means?
> > > > > The rule is:
> > > > > If a packet matched pattern in action, it will be modified,
> > > > > otherwise the action just take no effect is this idea acceptable?
> > > >
> > > > Not really, what happens will depend on the underlying device. It's
> > > > better to document it as undefined because you can't predict the
> > > > result. Some devices will cause packets to be lost, others will let
> > > > them through unchanged, others will crash the system after formatting
> > the hard drive, no one knows.
> > >
> > > OK, basically I think "undefined behavior" is not friendly to application, we
> > should avoid.
> > > But you are right, we need to consider device with different behavior for "
> > modification on non-matched pattern"
> > > I'm thinking why driver can't avoid non-matched pattern modification if the
> > device does not support?
> > > For example, driver can reject a flow ETH/IPV4 with TCP action, but
> > > may accept ETH/IPV4/TCP with TCP action base on its capability.
> > 
> > Drivers are free to accept an action or not depending on what is guaranteed
> > to be matched on the pattern side. It's fine as long as the resulting flow rule
> > works exactly as documented. Consistency is much more important to
> > applications than offloads proper.
> > 
> > Depending on device capabilities and the importance given to offload specific
> > use cases by vendors, PMD support may range from a basic 1:1 translation
> > attempt between rte_flow and device format, to an all out processing effort
> > resulting in multiple device flow rules and whatnot to satisfy the request by
> > any means necessary (see mlx5 RSS support on empty patterns in case you're
> > curious).
> > 
> > Whichever approach you choose (basic or complex), my recommendation is
> > simply to make sure the PMD reports an error whenever a flow rule is
> > ambiguous and could result in unexpected behavior if applied as is to the
> > device.
> > 
> > The error message should also be helpful. A message such as "unable to
> > apply flow rule" is pretty useless, while "this action is not supported when X
> > pattern item is not present" actually gives useful information.
> 
> > 
> > "Undefined behavior" is for application writers. It means that if a PMD
> > happens to accept the rule in question, what happens isn't covered by
> > documentation. Ideally a PMD shouldn't accept it in the first place though.
> 
> OK, I'm trying to understand why "Undefined behavior" is necessary for this action.
> For example, we have a device that can offload TCP layer modification, for packet that contain TCP, packet be modified, for no-tcp packet, the packet will be dropped

Well, this is how rte_flow is defined at a higher level than just the TCP
action we're talking about: all actions of a flow rule must happen on
matched traffic regardless, as guaranteed by the API. Actions do not perform
a second round of traffic matching, they mindlessly affect it according to
their documentation.

With that in mind, what should be the end result of a TCP-specific action on
a packet without a TCP header?

In your case, the device happens to let traffic through. On mine, traffic is
dropped. On another, a deadlock occurs in the device. This is why I think
"undefined behavior" is appropriate here.

> Also the device does not support TCP filter, so we are not able to create a flow to filter TCP packet only. 

OK, now I'm starting to understand your concern.

> Then without "Undefined behavior", the driver has to reject any flow with TCP packet modification action, since it can't guarantee no-tcp packet not be impacted, 
> while with " Undefined behavior", a flow with tcp action is actually is a "rule in question" and it can "happens to" be accepted by the driver?

I guess expecting applications to rely on PMD-specific (undefined) behavior
is out of the question? :)

The simplest solution to this problem is obviously to document it on an
action basis like you suggested. However doing so puts such actions at odds
with the rest of the API and is not recommended.

So far we took TCP as an example here, but before going further, is there an
actual scenario in this series where the device is unable to match the
protocol an action will affect?

For instance, I assume your device supports IPv4/IPv6 matching before
requesting a TTL-decrementing action. If so, can we stay on "undefined
behavior" for when an application doesn't match IPv4/IPv6 first?

-- 
Adrien Mazarguil
6WIND

^ permalink raw reply	[flat|nested] 61+ messages in thread

* Re: [dpdk-dev] [PATCH v2 4/4] ether: add packet modification aciton in flow API
  2018-04-17  9:55                 ` Adrien Mazarguil
@ 2018-04-17 10:32                   ` Zhang, Qi Z
  0 siblings, 0 replies; 61+ messages in thread
From: Zhang, Qi Z @ 2018-04-17 10:32 UTC (permalink / raw)
  To: Adrien Mazarguil
  Cc: dev, Doherty, Declan, Chandran, Sugesh, Glynn, Michael J, Liu,
	Yu Y, Ananyev, Konstantin, Richardson, Bruce



> -----Original Message-----
> From: Adrien Mazarguil [mailto:adrien.mazarguil@6wind.com]
> Sent: Tuesday, April 17, 2018 5:55 PM
> To: Zhang, Qi Z <qi.z.zhang@intel.com>
> Cc: dev@dpdk.org; Doherty, Declan <declan.doherty@intel.com>; Chandran,
> Sugesh <sugesh.chandran@intel.com>; Glynn, Michael J
> <michael.j.glynn@intel.com>; Liu, Yu Y <yu.y.liu@intel.com>; Ananyev,
> Konstantin <konstantin.ananyev@intel.com>; Richardson, Bruce
> <bruce.richardson@intel.com>
> Subject: Re: [PATCH v2 4/4] ether: add packet modification aciton in flow API
> 
> On Mon, Apr 16, 2018 at 03:03:39PM +0000, Zhang, Qi Z wrote:
> > > -----Original Message-----
> > > From: Adrien Mazarguil [mailto:adrien.mazarguil@6wind.com]
> > > Sent: Monday, April 16, 2018 9:31 PM
> > > To: Zhang, Qi Z <qi.z.zhang@intel.com>
> > > Cc: dev@dpdk.org; Doherty, Declan <declan.doherty@intel.com>;
> > > Chandran, Sugesh <sugesh.chandran@intel.com>; Glynn, Michael J
> > > <michael.j.glynn@intel.com>; Liu, Yu Y <yu.y.liu@intel.com>;
> > > Ananyev, Konstantin <konstantin.ananyev@intel.com>; Richardson,
> > > Bruce <bruce.richardson@intel.com>
> > > Subject: Re: [PATCH v2 4/4] ether: add packet modification aciton in
> > > flow API
> > >
> > > On Fri, Apr 13, 2018 at 01:47:15PM +0000, Zhang, Qi Z wrote:
> > > > > -----Original Message-----
> > > > > From: Adrien Mazarguil [mailto:adrien.mazarguil@6wind.com]
> > > > > Sent: Thursday, April 12, 2018 6:23 PM
> > > > > To: Zhang, Qi Z <qi.z.zhang@intel.com>
> > > > > Cc: dev@dpdk.org; Doherty, Declan <declan.doherty@intel.com>;
> > > > > Chandran, Sugesh <sugesh.chandran@intel.com>; Glynn, Michael J
> > > > > <michael.j.glynn@intel.com>; Liu, Yu Y <yu.y.liu@intel.com>;
> > > > > Ananyev, Konstantin <konstantin.ananyev@intel.com>; Richardson,
> > > > > Bruce <bruce.richardson@intel.com>
> > > > > Subject: Re: [PATCH v2 4/4] ether: add packet modification
> > > > > aciton in flow API
> > > > >
> > > > > On Thu, Apr 12, 2018 at 08:50:14AM +0000, Zhang, Qi Z wrote:
> > > > > > Hi Adrien
> > > > > >
> > > > > > > -----Original Message-----
> > > > > > > From: Adrien Mazarguil [mailto:adrien.mazarguil@6wind.com]
> > > > > > > Sent: Thursday, April 12, 2018 3:04 PM
> > > > > > > To: Zhang, Qi Z <qi.z.zhang@intel.com>
> > > > > > > Cc: dev@dpdk.org; Doherty, Declan
> > > > > > > <declan.doherty@intel.com>; Chandran, Sugesh
> > > > > > > <sugesh.chandran@intel.com>; Glynn, Michael J
> > > > > > > <michael.j.glynn@intel.com>; Liu, Yu Y <yu.y.liu@intel.com>;
> > > > > > > Ananyev, Konstantin <konstantin.ananyev@intel.com>;
> > > > > > > Richardson, Bruce <bruce.richardson@intel.com>
> > > > > > > Subject: Re: [PATCH v2 4/4] ether: add packet modification
> > > > > > > aciton in flow API
> > > > > > >
> > > > > > > On Sun, Apr 01, 2018 at 05:19:22PM -0400, Qi Zhang wrote:
> > > > > > > > Add new actions that be used to modify packet content with
> > > > > > > > generic
> > > > > > > > semantic:
> > > > > > > >
> > > > > > > > RTE_FLOW_ACTION_TYPE_FIELD_UPDATE:
> > > > > > > > 	- update specific field of packet
> > > > > > > > RTE_FLWO_ACTION_TYPE_FIELD_INCREMENT:
> > > > > > > > 	- increament specific field of packet
> > > > > > > > RTE_FLWO_ACTION_TYPE_FIELD_DECREMENT:
> > > > > > > > 	- decreament specific field of packet
> > > > > > > > RTE_FLWO_ACTION_TYPE_FIELD_COPY:
> > > > > > > > 	- copy data from one field to another in packet.
> > > > > > > >
> > > > > > > > All action use struct rte_flow_item parameter to match the
> > > > > > > > pattern that going to be modified, if no pattern match,
> > > > > > > > the action just be skipped.
> > > <snip>
> > > > > > > What happens when this action is attempted on non-matching
> > > > > > > traffic must be documented here as well. Refer to discussion
> > > > > > > re
> > > > > > > "ethdev: Add tunnel encap/decap actions" [3]. To be on the
> > > > > > > safe side, it must be documented as resulting in undefined
> behavior.
> > > > > >
> > > > > > so what is "undefined behavior" you means?
> > > > > > The rule is:
> > > > > > If a packet matched pattern in action, it will be modified,
> > > > > > otherwise the action just take no effect is this idea acceptable?
> > > > >
> > > > > Not really, what happens will depend on the underlying device.
> > > > > It's better to document it as undefined because you can't
> > > > > predict the result. Some devices will cause packets to be lost,
> > > > > others will let them through unchanged, others will crash the
> > > > > system after formatting
> > > the hard drive, no one knows.
> > > >
> > > > OK, basically I think "undefined behavior" is not friendly to
> > > > application, we
> > > should avoid.
> > > > But you are right, we need to consider device with different behavior
> for "
> > > modification on non-matched pattern"
> > > > I'm thinking why driver can't avoid non-matched pattern
> > > > modification if the
> > > device does not support?
> > > > For example, driver can reject a flow ETH/IPV4 with TCP action,
> > > > but may accept ETH/IPV4/TCP with TCP action base on its capability.
> > >
> > > Drivers are free to accept an action or not depending on what is
> > > guaranteed to be matched on the pattern side. It's fine as long as
> > > the resulting flow rule works exactly as documented. Consistency is
> > > much more important to applications than offloads proper.
> > >
> > > Depending on device capabilities and the importance given to offload
> > > specific use cases by vendors, PMD support may range from a basic
> > > 1:1 translation attempt between rte_flow and device format, to an
> > > all out processing effort resulting in multiple device flow rules
> > > and whatnot to satisfy the request by any means necessary (see mlx5
> > > RSS support on empty patterns in case you're curious).
> > >
> > > Whichever approach you choose (basic or complex), my recommendation
> > > is simply to make sure the PMD reports an error whenever a flow rule
> > > is ambiguous and could result in unexpected behavior if applied as
> > > is to the device.
> > >
> > > The error message should also be helpful. A message such as "unable
> > > to apply flow rule" is pretty useless, while "this action is not
> > > supported when X pattern item is not present" actually gives useful
> information.
> >
> > >
> > > "Undefined behavior" is for application writers. It means that if a
> > > PMD happens to accept the rule in question, what happens isn't
> > > covered by documentation. Ideally a PMD shouldn't accept it in the first
> place though.
> >
> > OK, I'm trying to understand why "Undefined behavior" is necessary for this
> action.
> > For example, we have a device that can offload TCP layer modification,
> > for packet that contain TCP, packet be modified, for no-tcp packet,
> > the packet will be dropped
> 
> Well, this is how rte_flow is defined at a higher level than just the TCP action
> we're talking about: all actions of a flow rule must happen on matched traffic
> regardless, as guaranteed by the API. Actions do not perform a second round
> of traffic matching, they mindlessly affect it according to their
> documentation.
> 
> With that in mind, what should be the end result of a TCP-specific action on a
> packet without a TCP header?
> 
> In your case, the device happens to let traffic through. On mine, traffic is
> dropped. On another, a deadlock occurs in the device. This is why I think
> "undefined behavior" is appropriate here.

OK, I'm fine to add "undefined behavior" into document.
But besides this, would you help to review my v3 patches

Thanks
Qi

> 
> > Also the device does not support TCP filter, so we are not able to create a
> flow to filter TCP packet only.
> 
> OK, now I'm starting to understand your concern.
> 
> > Then without "Undefined behavior", the driver has to reject any flow
> > with TCP packet modification action, since it can't guarantee no-tcp packet
> not be impacted, while with " Undefined behavior", a flow with tcp action is
> actually is a "rule in question" and it can "happens to" be accepted by the
> driver?
> 
> I guess expecting applications to rely on PMD-specific (undefined) behavior is
> out of the question? :)
> 
> The simplest solution to this problem is obviously to document it on an
> action basis like you suggested. However doing so puts such actions at odds
> with the rest of the API and is not recommended.
> 
> So far we took TCP as an example here, but before going further, is there an
> actual scenario in this series where the device is unable to match the
> protocol an action will affect?
> 
> For instance, I assume your device supports IPv4/IPv6 matching before
> requesting a TTL-decrementing action. If so, can we stay on "undefined
> behavior" for when an application doesn't match IPv4/IPv6 first?
> 
> --
> Adrien Mazarguil
> 6WIND

^ permalink raw reply	[flat|nested] 61+ messages in thread

* Re: [dpdk-dev] [PATCH v3 1/4] ethdev: add more protocol support in flow API
  2018-04-16  6:10   ` [dpdk-dev] [PATCH v3 1/4] ethdev: add more protocol support in flow API Qi Zhang
@ 2018-04-19 14:48     ` Adrien Mazarguil
  0 siblings, 0 replies; 61+ messages in thread
From: Adrien Mazarguil @ 2018-04-19 14:48 UTC (permalink / raw)
  To: Qi Zhang
  Cc: dev, declan.doherty, sugesh.chandran, michael.j.glynn, yu.y.liu,
	konstantin.ananyev, bruce.richardson

On Mon, Apr 16, 2018 at 02:10:39PM +0800, Qi Zhang wrote:
> Add new protocol header match support as below
> 
> RTE_FLOW_ITEM_TYPE_ARP_IPV4
> 	- matches an IPv4 ARP header
> RTE_FLOW_ITEM_TYPE_IPV6_EXT
> 	- matches an IPv6 extension header with any type.
> RTE_FLOW_ITEM_TYPE_ICMP6
> 	- matches an ICMPv6 header followed by any message body.
> RTE_FLOW_ITEM_TYPE_ICMP6_ND_NS
> 	- matches an ICMPv6 header followed by network discovery
> 	  neighbor solicitation.
> RTE_FLOW_ITEM_TYPE_ICMP6_ND_NA
> 	- matches an ICMPv6 header followed by network discovery
> 	  neighbor advertisement.
> RTE_FLOW_ITEM_TYPE_ICMP6_ND_OPT_ETH_SLA
> 	- matches an ICMPv6 header followed by network discovery
> 	  neighbor solicitation contains source Ethernet link-layer
> 	  address option.
> RTE_FLOW_ITEM_TYPE_ICMP6_ND_OPT_ETH_TLA
> 	- matches an ICMPv6 header followed by network discovery
> 	  neighbor advertisement contains target Ethernet link-layer
> 	  address option.
> 
> Suggested-by: Adrien Mazarguil <adrien.mazarguil@6wind.com>
> Signed-off-by: Qi Zhang <qi.z.zhang@intel.com>

Beside a bunch of nits and typos, I think this patch is fine, please see
below.

> ---
>  app/test-pmd/cmdline_flow.c                 | 224 ++++++++++++++++++++++++++
>  app/test-pmd/config.c                       |   9 ++
>  doc/guides/prog_guide/rte_flow.rst          |  88 +++++++++++
>  doc/guides/testpmd_app_ug/testpmd_funcs.rst |  34 ++++
>  lib/librte_ether/rte_flow.h                 | 235 ++++++++++++++++++++++++++++
>  5 files changed, 590 insertions(+)
> 
> diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c
> index 59f3b3b57..7950b1b8d 100644
> --- a/app/test-pmd/cmdline_flow.c
> +++ b/app/test-pmd/cmdline_flow.c
> @@ -150,6 +150,26 @@ enum index {
>  	ITEM_GENEVE,
>  	ITEM_GENEVE_VNI,
>  	ITEM_GENEVE_PROTO,
> +	ITEM_ARP_IPV4,
> +	ITEM_ARP_IPV4_SHA,
> +	ITEM_ARP_IPV4_SIP,
> +	ITEM_ARP_IPV4_THA,
> +	ITEM_ARP_IPV4_TIP,
> +	ITEM_IPV6_EXT,
> +	ITEM_IPV6_EXT_NEXT_HDR,
> +	ITEM_ICMP6,
> +	ITEM_ICMP6_TYPE,
> +	ITEM_ICMP6_CODE,
> +	ITEM_ICMP6_ND_NS,
> +	ITEM_ICMP6_ND_NS_TGT_ADDR,
> +	ITEM_ICMP6_ND_NA,
> +	ITEM_ICMP6_ND_NA_TGT_ADDR,
> +	ITEM_ICMP6_ND_OPT_SLA_ETH,
> +	ITEM_ICMP6_ND_OPT_SLA_ETH_TGT_ADDR,
> +	ITEM_ICMP6_ND_OPT_SLA_ETH_SLL_ADDR,
> +	ITEM_ICMP6_ND_OPT_TLA_ETH,
> +	ITEM_ICMP6_ND_OPT_TLA_ETH_TGT_ADDR,
> +	ITEM_ICMP6_ND_OPT_TLA_ETH_TLL_ADDR,
>  
>  	/* Validate/create actions. */
>  	ACTIONS,
> @@ -436,6 +456,13 @@ static const enum index next_item[] = {
>  	ITEM_GTPC,
>  	ITEM_GTPU,
>  	ITEM_GENEVE,
> +	ITEM_ARP_IPV4,
> +	ITEM_IPV6_EXT,
> +	ITEM_ICMP6,
> +	ITEM_ICMP6_ND_NS,
> +	ITEM_ICMP6_ND_NA,
> +	ITEM_ICMP6_ND_OPT_SLA_ETH,
> +	ITEM_ICMP6_ND_OPT_TLA_ETH,
>  	ZERO,
>  };
>  
> @@ -586,6 +613,47 @@ static const enum index item_geneve[] = {
>  	ZERO,
>  };
>  
> +static const enum index item_arp_ipv4[] = {
> +	ITEM_ARP_IPV4_SHA,
> +	ITEM_ARP_IPV4_SIP,
> +	ITEM_ARP_IPV4_THA,
> +	ITEM_ARP_IPV4_TIP,
> +	ZERO,
> +};
> +
> +static const enum index item_ipv6_ext[] = {
> +	ITEM_IPV6_EXT_NEXT_HDR,
> +	ZERO,
> +};
> +
> +static const enum index item_icmp6[] = {
> +	ITEM_ICMP6_TYPE,
> +	ITEM_ICMP6_CODE,
> +	ZERO,
> +};
> +
> +static const enum index item_icmp6_nd_ns[] = {
> +	ITEM_ICMP6_ND_NS_TGT_ADDR,
> +	ZERO,
> +};
> +
> +static const enum index item_icmp6_nd_na[] = {
> +	ITEM_ICMP6_ND_NA_TGT_ADDR,
> +	ZERO,
> +};
> +
> +static const enum index item_icmp6_nd_opt_sla_eth[] = {
> +	ITEM_ICMP6_ND_OPT_SLA_ETH_TGT_ADDR,
> +	ITEM_ICMP6_ND_OPT_SLA_ETH_SLL_ADDR,
> +	ZERO,
> +};
> +
> +static const enum index item_icmp6_nd_opt_tla_eth[] = {
> +	ITEM_ICMP6_ND_OPT_TLA_ETH_TGT_ADDR,
> +	ITEM_ICMP6_ND_OPT_TLA_ETH_TLL_ADDR,
> +	ZERO,
> +};
> +
>  static const enum index next_action[] = {
>  	ACTION_END,
>  	ACTION_VOID,
> @@ -1473,6 +1541,162 @@ static const struct token token_list[] = {
>  		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve,
>  					     protocol)),
>  	},
> +	[ITEM_ARP_IPV4] = {
> +		.name = "arp",
> +		.help = "match IPv4 ARP header",
> +		.priv = PRIV_ITEM(ARP_IPV4,
> +				  sizeof(struct rte_flow_item_arp_ipv4)),
> +		.next = NEXT(item_arp_ipv4),
> +		.call = parse_vc,
> +	},
> +	[ITEM_ARP_IPV4_SHA] = {
> +		.name = "sha",
> +		.help = "sender hardware address",
> +		.next = NEXT(item_arp_ipv4, NEXT_ENTRY(UNSIGNED), item_param),
> +		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_ipv4,
> +					     arp_sha.addr_bytes)),
> +	},
> +	[ITEM_ARP_IPV4_SIP] = {
> +		.name = "sip",
> +		.help = "sender IP address",
> +		.next = NEXT(item_arp_ipv4, NEXT_ENTRY(UNSIGNED), item_param),
> +		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_ipv4,
> +					     arp_sip)),
> +	},
> +	[ITEM_ARP_IPV4_THA] = {
> +		.name = "tha",
> +		.help = "target hardware address",
> +		.next = NEXT(item_arp_ipv4, NEXT_ENTRY(UNSIGNED), item_param),
> +		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_ipv4,
> +					     arp_tha.addr_bytes)),
> +	},
> +	[ITEM_ARP_IPV4_TIP] = {
> +		.name = "tip",
> +		.help = "target IP address",
> +		.next = NEXT(item_arp_ipv4, NEXT_ENTRY(UNSIGNED), item_param),
> +		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_ipv4,
> +					     arp_tip)),
> +	},
> +	[ITEM_IPV6_EXT] = {
> +		.name = "ext",
> +		.help = "match IPv6 extend header",

extend => extended

> +		.priv = PRIV_ITEM(IPV6_EXT,
> +				  sizeof(struct rte_flow_item_ipv6_ext)),
> +		.next = NEXT(item_ipv6_ext),
> +		.call = parse_vc,
> +	},
> +	[ITEM_IPV6_EXT_NEXT_HDR] = {
> +		.name = "next",
> +		.help = "next header in IPv6 extend header",
> +		.next = NEXT(item_ipv6_ext, NEXT_ENTRY(UNSIGNED), item_param),
> +		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_ext,
> +					     next_hdr)),
> +	},
> +	[ITEM_ICMP6] = {
> +		.name = "icmp6",
> +		.help = "match ICMPv6 header",
> +		.priv = PRIV_ITEM(ICMP, sizeof(struct rte_flow_item_icmp6)),
> +		.next = NEXT(item_icmp6),
> +		.call = parse_vc,
> +	},
> +	[ITEM_ICMP6_TYPE] = {
> +		.name = "type",
> +		.help = "ICMPv6 packet type",
> +		.next = NEXT(item_icmp6, NEXT_ENTRY(UNSIGNED), item_param),
> +		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6,
> +					     type)),
> +	},
> +	[ITEM_ICMP6_CODE] = {
> +		.name = "code",
> +		.help = "ICMPv6 packet code",
> +		.next = NEXT(item_icmp6, NEXT_ENTRY(UNSIGNED), item_param),
> +		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6,
> +					     code)),
> +	},
> +	[ITEM_ICMP6_ND_NS] = {
> +		.name = "ns",
> +		.help = "match neighbor solicitation over ICMPv6 ",

Extra space after "ICMPv6".

> +		.priv = PRIV_ITEM(ICMP6_ND_NS,
> +				  sizeof(struct rte_flow_item_icmp6_nd_ns)),
> +		.next = NEXT(item_icmp6_nd_ns),
> +		.call = parse_vc,
> +	},
> +	[ITEM_ICMP6_ND_NS_TGT_ADDR] = {
> +		.name = "tgt_addr",
> +		.help = "target address of neighbor solicitation",
> +		.next = NEXT(item_icmp6_nd_ns, NEXT_ENTRY(UNSIGNED),
> +			     item_param),
> +		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_ns,
> +					     target_addr)),
> +	},
> +	[ITEM_ICMP6_ND_NA] = {
> +		.name = "na",
> +		.help = "match neighbor advertisement over ICMPv6 ",
> +		.priv = PRIV_ITEM(ICMP6_ND_NA,
> +				  sizeof(struct rte_flow_item_icmp6_nd_na)),
> +		.next = NEXT(item_icmp6_nd_na),
> +		.call = parse_vc,
> +	},
> +	[ITEM_ICMP6_ND_NA_TGT_ADDR] = {
> +		.name = "tgt_addr",
> +		.help = "target address of neighbor advertisement",
> +		.next = NEXT(item_icmp6_nd_na, NEXT_ENTRY(UNSIGNED),
> +			     item_param),
> +		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_na,
> +					     target_addr)),
> +	},
> +	[ITEM_ICMP6_ND_OPT_SLA_ETH] = {
> +		.name = "sla",
> +		.help = "match source link-layer address over neighbor solicitation",
> +		.priv = PRIV_ITEM(ICMP6_ND_OPT_SLA_ETH,
> +			  sizeof(struct rte_flow_item_icmp6_nd_opt_sla_eth)),
> +		.next = NEXT(item_icmp6_nd_opt_sla_eth),
> +		.call = parse_vc,
> +	},
> +	[ITEM_ICMP6_ND_OPT_SLA_ETH_TGT_ADDR] = {
> +		.name = "tgt_addr",
> +		.help = "target address of neighbor solicitation",
> +		.next = NEXT(item_icmp6_nd_opt_sla_eth, NEXT_ENTRY(UNSIGNED),
> +			     item_param),
> +		.args = ARGS(ARGS_ENTRY_HTON(
> +			     struct rte_flow_item_icmp6_nd_opt_sla_eth,
> +			     target_addr)),
> +	},
> +	[ITEM_ICMP6_ND_OPT_SLA_ETH_SLL_ADDR] = {
> +		.name = "sll_addr",
> +		.help = "source link-layer address over neighbor solicitation",
> +		.next = NEXT(item_icmp6_nd_opt_sla_eth, NEXT_ENTRY(UNSIGNED),
> +			     item_param),
> +		.args = ARGS(ARGS_ENTRY_HTON(
> +			     struct rte_flow_item_icmp6_nd_opt_sla_eth,
> +			     sll_addr)),
> +	},
> +	[ITEM_ICMP6_ND_OPT_TLA_ETH] = {
> +		.name = "tla",
> +		.help = "match target link-layer address over neighbor advertisement",
> +		.priv = PRIV_ITEM(ICMP6_ND_OPT_TLA_ETH,
> +			  sizeof(struct rte_flow_item_icmp6_nd_opt_tla_eth)),
> +		.next = NEXT(item_icmp6_nd_opt_tla_eth),
> +		.call = parse_vc,
> +	},
> +	[ITEM_ICMP6_ND_OPT_TLA_ETH_TGT_ADDR] = {
> +		.name = "tgt_addr",
> +		.help = "target address of neighbor advertisement",
> +		.next = NEXT(item_icmp6_nd_opt_tla_eth, NEXT_ENTRY(UNSIGNED),
> +			     item_param),
> +		.args = ARGS(ARGS_ENTRY_HTON(
> +			     struct rte_flow_item_icmp6_nd_opt_tla_eth,
> +			     target_addr)),
> +	},
> +	[ITEM_ICMP6_ND_OPT_TLA_ETH_TLL_ADDR] = {
> +		.name = "tll_addr",
> +		.help = "target link-layer address over neighbor advertisement",
> +		.next = NEXT(item_icmp6_nd_opt_tla_eth, NEXT_ENTRY(UNSIGNED),
> +			     item_param),
> +		.args = ARGS(ARGS_ENTRY_HTON(
> +			     struct rte_flow_item_icmp6_nd_opt_tla_eth,
> +			     tll_addr)),
> +	},
>  
>  	/* Validate/create actions. */
>  	[ACTIONS] = {
> diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
> index 4bb255c62..4a1af5c57 100644
> --- a/app/test-pmd/config.c
> +++ b/app/test-pmd/config.c
> @@ -980,6 +980,15 @@ static const struct {
>  	MK_FLOW_ITEM(GTPC, sizeof(struct rte_flow_item_gtp)),
>  	MK_FLOW_ITEM(GTPU, sizeof(struct rte_flow_item_gtp)),
>  	MK_FLOW_ITEM(GENEVE, sizeof(struct rte_flow_item_geneve)),
> +	MK_FLOW_ITEM(ARP_IPV4, sizeof(struct rte_flow_item_arp_ipv4)),
> +	MK_FLOW_ITEM(IPV6_EXT, sizeof(struct rte_flow_item_ipv6_ext)),
> +	MK_FLOW_ITEM(ICMP6, sizeof(struct rte_flow_item_icmp6)),
> +	MK_FLOW_ITEM(ICMP6_ND_NS, sizeof(struct rte_flow_item_icmp6_nd_ns)),
> +	MK_FLOW_ITEM(ICMP6_ND_NA, sizeof(struct rte_flow_item_icmp6_nd_na)),
> +	MK_FLOW_ITEM(ICMP6_ND_OPT_SLA_ETH,
> +		     sizeof(struct rte_flow_item_icmp6_nd_opt_sla_eth)),
> +	MK_FLOW_ITEM(ICMP6_ND_OPT_TLA_ETH,
> +		     sizeof(struct rte_flow_item_icmp6_nd_opt_tla_eth)),
>  };
>  
>  /** Compute storage space needed by item specification. */
> diff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst
> index 961943dda..99468bf60 100644
> --- a/doc/guides/prog_guide/rte_flow.rst
> +++ b/doc/guides/prog_guide/rte_flow.rst
> @@ -992,6 +992,94 @@ Matches a GENEVE header.
>  - ``rsvd1``: reserved, normally 0x00.
>  - Default ``mask`` matches VNI only.
>  
> +Item: ``ARP_IPV4``
> +^^^^^^^^^^^^^^^^^^
> +
> +Matches an IPv4 ARP header.
> +
> +- ``arp_hdr``: format of hardware address.
> +- ``arp_pro``: format of protocol address.
> +- ``arp_hln``: length of hardware address.
> +- ``arp_pln``: length of protocol address.
> +- ``arp_op``: ARP opcode.
> +- ``sha``: sender hardware address.
> +- ``sip``: sender IP address.
> +- ``tha``: target hardware address.
> +- ``tip``: target IP address.
> +- Default ``mask`` only matches sha, sip, tha, tip.
> +
> +Item: ``IPV6_EXT``
> +^^^^^^^^^^^^^^^^^^
> +
> +Matches an IPv6 Extension header with any type.
> +
> +- ``next_hdr``: protocol of next header.
> +- Default ``mask`` matches protocal of next header.

protocal => protocol

> +
> +Item: ``ICMP6``
> +^^^^^^^^^^^^^^^
> +
> +Matches an ICMPv6 header followed by any message body.
> +
> +- ``type``: ICMPv6 type.
> +- ``code``: ICMPv6 code.
> +- ``checksume``: ICMPv6 checksume.

checksume => checksum

> +- Default ``mask`` matches type and code only.
> +
> +Item: ``ICMP6_ND_NS``
> +^^^^^^^^^^^^^^^^^^^^^
> +
> +Matches an ICMPv6 header followed by network discvoery neighbor solicitation,

discvoery => discovery

> +
> +- ``type``: ICMPv6 type, normally 135.
> +- ``code``: ICMPv6 code, normally 0.
> +- ``checksume``: ICMPv6 checksume.

checksume => checksum

> +- ``reserved``: reserved, normally 0x00.
> +- ``tgt_addr``: target address of neighbor solicitation.
> +- Default ``mask`` matches target address only.
> +
> +Item: ``ICMP6_ND_NA``
> +^^^^^^^^^^^^^^^^^^^^^
> +
> +Matches an ICMPv6 header followed by network discvoery neighbor advertisement,

discvoery => discovery

> +
> +- ``type``: ICMPv6 type, normally 136.
> +- ``code``: ICMPv6 code, normally 0.
> +- ``checksume``: ICMPv6 checksume.

checksume => checksum

> +- ``rso_reserved``: route flag (1b), solicited flag (1b), override flag (1b),
> +  reserved (29b).
> +- ``tgt_addr``: target address of neighbor advertisement.
> +- Default ``mask`` matches target address only.
> +
> +Item: ``ICMP6_ND_OPT_SLA_ETH``
> +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> +
> +Matches an ICMPv6 header followed by network discvoery neighbor solicitation

discvoery => discovery

> +that contains source Ethernet link-layer address option.
> +
> +- ``type``: ICMPv6 type, normally 135.
> +- ``code``: ICMPv6 code, normally 0.
> +- ``checksume``: ICMPv6 checksume.

checksume => checksum

> +- ``reserved``: reserved, normally 0x00.
> +- ``tgt_addr``: target address of neighbor solicitation.
> +- ``sll_ADDR``: source Ethernet link-layer address.
> +- Default ``mask`` matches target address and source link-layer address only.
> +
> +Item: ``ICMP6_ND_OPT_TLA_ETH``
> +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> +
> +Matches an ICMPv6 header followed by network discvoery neighbor advertisement.

discvoery => discovery

> +that contains target Ethernet link-layer address option.
> +
> +- ``type``: ICMPv6 type, normally 136.
> +- ``code``: ICMPv6 code, normally 0.
> +- ``checksume``: ICMPv6 checksume.

checksume => checksum

> +- ``rso_reserved``: route flag (1b), solicited flag (1b), override flag (1b),
> +  reserved (29b).
> +- ``tgt_addr``: target address of neighbor advertisement.
> +- ``tll_ADDR``: target Ethernet link-layer address.
> +- Default ``mask`` matches target address and target link-layer address only.
> +
>  Actions
>  ~~~~~~~
>  
> diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
> index a766ac795..12d78f10b 100644
> --- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
> +++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
> @@ -3305,6 +3305,40 @@ This section lists supported pattern items and their attributes, if any.
>    - ``vni {unsigned}``: virtual network identifier.
>    - ``protocol {unsigned}``: protocol type.
>  
> +- ``arp``: match IPv4 arp header.
> +
> +  - ``sha``: sender hardware address.
> +  - ``sip``: sender IP address.
> +  - ``tha``: target hardware address.
> +  - ``tip``: target IP address.
> +
> +- ``ext``: match IPv6 extend header.
> +
> +  - ``next {unsigned}``: protocol (next header).
> +
> +- ``icmp6``: match ICMPv6 header.
> +
> +  - ``type {unsgined}``: ICMPv6 packet type.

unsgined => unsigned

> +  - ``code {unsigned}``: ICMPv6 packet code.
> +
> +- ``ns``: match neighbor solicitation over ICMPv6.
> +
> +  - ``tgt_addr {ipv6 address}``: target address of neighbor solicitation.
> +
> +- ``na``: match neighbor advertisement over ICMPv6.
> +
> +  - ``tgt_addr {ipv6 address}``: target address of neighbor advertisement.
> +
> +- ``sla``: match source link-layer address over neighbor solicitation.
> +
> +  - ``tgt_addr {ipv6 address}``: target address of neighbor solicitation.
> +  - ``sll_addr {MAC-48}``: source link-layer address over neightbor solicitation.

neightbor => neighbor

> +
> +- ``tla``: match target link-layer address over neighbor advertisement.
> +
> +  - ``tgt_addr {ipv6 address}``: target address of neighbor advertisement.
> +  - ``tll_addr {MAC-48}``: target link-layer address over neightbor advertisement.

neightbor => neighbor


> +
>  Actions list
>  ^^^^^^^^^^^^
>  
> diff --git a/lib/librte_ether/rte_flow.h b/lib/librte_ether/rte_flow.h
> index 56c733451..f84bbfda5 100644
> --- a/lib/librte_ether/rte_flow.h
> +++ b/lib/librte_ether/rte_flow.h
> @@ -323,6 +323,61 @@ enum rte_flow_item_type {
>  	 * See struct rte_flow_item_geneve.
>  	 */
>  	RTE_FLOW_ITEM_TYPE_GENEVE,
> +
> +	/**
> +	 * Matches an IPv4 ARP header.
> +	 *
> +	 * See struct rte_flow_item_arp_ipv4.
> +	 */
> +	RTE_FLOW_ITEM_TYPE_ARP_IPV4,
> +
> +	/**
> +	 * Matches an IPv6 Extension header with any type.
> +	 *
> +	 * See struct rte_flow_item_ipv6_ext.
> +	 */
> +	RTE_FLOW_ITEM_TYPE_IPV6_EXT,
> +
> +	/**
> +	 * Matches an ICMPv6 header followed by any message body.
> +	 *
> +	 * See struct rte_flow_item_icmp6.
> +	 */
> +	RTE_FLOW_ITEM_TYPE_ICMP6,
> +
> +	/**
> +	 * Matches an ICMPv6 header followed by network discovery
> +	 * neighbor solicitation.
> +	 *
> +	 * See struct rte_flow_item_icmp6_nd_ns.
> +	 */
> +	RTE_FLOW_ITEM_TYPE_ICMP6_ND_NS,
> +
> +	/**
> +	 * Matches an ICMPv6 header followed by network discovery
> +	 * neighbor advertisement.
> +	 *
> +	 * See struct rte_flow_item_icmp6_nd_na.
> +	 */
> +	RTE_FLOW_ITEM_TYPE_ICMP6_ND_NA,
> +
> +	/**
> +	 * Matches an ICMPv6 header followed by network discovery neighbor
> +	 * solicitation that contains source Ethernet link-layer address
> +	 * option.
> +	 *
> +	 * See struct rte_flow_item_icmp6_nd_opt_sla_eth.
> +	 */
> +	RTE_FLOW_ITEM_TYPE_ICMP6_ND_OPT_SLA_ETH,
> +
> +	/**
> +	 * Matches an ICMPv6 header followed by network discovery neighbor
> +	 * advertisement that contains target Ethernet link-layer address
> +	 * option.
> +	 *
> +	 * See struct rte_flow_item_icmp6_nd_opt_tla_eth.
> +	 */
> +	RTE_FLOW_ITEM_TYPE_ICMP6_ND_OPT_TLA_ETH,
>  };
>  
>  /**
> @@ -815,6 +870,186 @@ static const struct rte_flow_item_geneve rte_flow_item_geneve_mask = {
>  #endif
>  
>  /**
> + * RTE_FLOW_ITEM_TYPE_ARP_IPV4
> + *
> + * Matches an IPv4 ARP header.
> + */
> +struct rte_flow_item_arp_ipv4 {
> +	rte_be16_t arp_hrd; /**< format of hardware address. */
> +	rte_be16_t arp_pro; /**< format of protocol address. */
> +	uint8_t arp_hln; /**< length of hardware address. */
> +	uint8_t arp_pln; /**< length of protocol address. */
> +	rte_be16_t arp_op; /**< ARP opcode */
> +	struct ether_addr arp_sha; /**< sender hardware address. */
> +	rte_be32_t arp_sip; /**< sender IP address. */
> +	struct ether_addr arp_tha; /**< target hardware address. */
> +	rte_be32_t arp_tip; /**< target IP address. */
> +};

Missing caps on the first word on each comment (keep the style of the file).

> +
> +/** Default mask for RTE_FLOW_ITEM_TYPE_ARP_IPV4. */
> +#ifndef __cplusplus
> +static const struct rte_flow_item_arp_ipv4 rte_flow_item_arp_ipv4_mask = {
> +	.arp_sha = {
> +		.addr_bytes = "\xff\xff\xff\xff\xff\xff",
> +	},
> +	.arp_sip = RTE_BE32(0xffffffff),
> +	.arp_tha = {
> +		.addr_bytes = "\xff\xff\xff\xff\xff\xff",
> +	},
> +	.arp_tip = RTE_BE32(0xffffffff),
> +};
> +#endif
> +
> +/**
> + * RTE_FLOW_ITEM_TYPE_IPV6_EXT
> + *
> + * Matches an IPv6 extension header with any type.
> + */
> +struct rte_flow_item_ipv6_ext {
> +	uint8_t next_hdr; /**< protocol of next  header */
> +};

Ditto.

> +
> +/** Default mask for RTE_FLOW_ITEM_TYPE_IPV6_EXT. */
> +#ifndef __cplusplus
> +static const
> +struct rte_flow_item_ipv6_ext rte_flow_item_ipv6_ext_mask = {
> +	.next_hdr = 0xff,
> +};
> +#endif
> +
> +/**
> + * RTE_FLOW_ITEM_TYPE_ICMP6
> + *
> + * Matches an ICMPv6 header followed by any message body.
> + */
> +struct rte_flow_item_icmp6 {
> +	uint8_t type; /**< ICMPv6 type. */
> +	uint8_t code; /**< ICMPv6 code. */
> +	uint16_t checksum; /**< ICMPv6 checksum. */
> +};
> +
> +/** Default mask for RTE_FLOW_ITEM_TYPE_ICMP6. */
> +#ifndef __cplusplus
> +static const struct rte_flow_item_icmp6 rte_flow_item_icmp6_mask = {
> +	.type = 0xff,
> +	.code = 0xff,
> +};
> +#endif
> +
> +/**
> + * RTE_FLOW_ITEM_TYPE_ICMP6_ND_NS
> + *
> + * Matches an ICMP6 header followed by network discovery
> + * neighbor solicitation.
> + */
> +struct rte_flow_item_icmp6_nd_ns {
> +	uint8_t type; /**< ICMPv6 type, normally 135. */
> +	uint8_t code; /**< ICMPv6 code, normally 0. */
> +	rte_be16_t checksum; /**< ICMPv6 checksum. */
> +	rte_be32_t reserved;
> +	uint8_t target_addr[16]; /**< Target address. */
> +};
> +
> +/** Default mask for RTE_FLOW_ITEM_TYPE_ICMP6_ND_NS */

Missing "."

> +#ifndef __cplusplus
> +static const
> +struct rte_flow_item_icmp6_nd_ns rte_flow_item_icmp6_nd_ns_mask = {
> +	.target_addr =
> +		"\xff\xff\xff\xff\xff\xff\xff\xff"
> +		"\xff\xff\xff\xff\xff\xff\xff\xff",
> +};
> +#endif
> +
> +/**
> + * RTE_FLOW_ITEM_TYPE_ICMP6_ND_NA
> + *
> + * Matches an ICMPv6 header followed by network discovery
> + * neighbor advertisement.
> + */
> +struct rte_flow_item_icmp6_nd_na {
> +	uint8_t type; /**< ICMPv6 type, normally 136. */
> +	uint8_t code; /**< ICMPv6 code, normally 0. */
> +	rte_be16_t checksum; /**< ICMPv6 checksum. */
> +	/**
> +	 * Route flag (1b), solicited flag (1b), override flag (1b),
> +	 * reserved (29b).
> +	 */
> +	rte_be32_t rso_reserved;
> +	uint8_t target_addr[16]; /**< Target address. */
> +};
> +
> +/** Default mask for RTE_FLOW_ITEM_TYPE_ICMP6_ND_NA. */
> +#ifndef __cplusplus
> +static const
> +struct rte_flow_item_icmp6_nd_na rte_flow_item_icmp6_nd_na_mask = {
> +	.target_addr =
> +		"\xff\xff\xff\xff\xff\xff\xff\xff"
> +		"\xff\xff\xff\xff\xff\xff\xff\xff",
> +};
> +#endif
> +
> +/**
> + * RTE_FLOW_ITEM_TYPE_ICMP6_ND_OPT_SLA_ETH
> + *
> + * Matches an ICMPv6 header followed by network discovery neighbor
> + * solicitation that contains source Ethernet link-layer address option.
> + */
> +struct rte_flow_item_icmp6_nd_opt_sla_eth {
> +	uint8_t type; /**< ICMPv6 type, normally 135. */
> +	uint8_t code; /**< ICMPv6 code, normally 0. */
> +	rte_be16_t checksum; /**< ICMPv6 checksum. */
> +	rte_be32_t reserved;
> +	uint8_t target_addr[16]; /**< Target address. */
> +	struct ether_addr sll_addr; /**< Source Ethernet link-layer address. */
> +};
> +
> +/** Default mask for RTE_FLOW_ITEM_TYPE_ICMP6_ND_OPT_SLA_ETH. */
> +#ifndef __cplusplus
> +static const struct rte_flow_item_icmp6_nd_opt_sla_eth
> +	rte_flow_item_icmp6_nd_opt_sla_eth_mask = {
> +	.target_addr =
> +		"\xff\xff\xff\xff\xff\xff\xff\xff"
> +		"\xff\xff\xff\xff\xff\xff\xff\xff",
> +	.sll_addr = {
> +		.addr_bytes = "\xff\xff\xff\xff\xff\xff",
> +	}
> +};
> +#endif
> +
> +/**
> + * RTE_FLOW_ITEM_TYPE_ICMP6_ND_OPT_TLA_ETH
> + *
> + * Matches an ICMPv6 header followed by network discovery neighbor
> + * advertisement that contains target Ethernet link-layer address option.
> + */
> +struct rte_flow_item_icmp6_nd_opt_tla_eth {
> +	uint8_t type; /**< ICMPv6 type, normally 136. */
> +	uint8_t code; /**< ICMPv6 code, normally 0. */
> +	rte_be16_t checksum; /**< ICMPv6 checksum. */
> +	/**
> +	 * Route flag (1b), solicited flag (1b), override flag (1b),
> +	 * reserved (29b).
> +	 */
> +	rte_be32_t rso_reserved;
> +	uint8_t target_addr[16]; /**< Target address. */
> +	struct ether_addr tll_addr; /**< Target Ethernet link-layer address. */
> +
> +};
> +
> +/** Default mask for RTE_FLOW_ITEM_TYPE_ICMP6_ND_OPT_TLA_ETH. */
> +#ifndef __cplusplus
> +static const struct rte_flow_item_icmp6_nd_opt_tla_eth
> +	rte_flow_item_icmp6_nd_opt_tla_eth_mask = {
> +	.target_addr =
> +		"\xff\xff\xff\xff\xff\xff\xff\xff"
> +		"\xff\xff\xff\xff\xff\xff\xff\xff",
> +	.tll_addr = {
> +		.addr_bytes = "\xff\xff\xff\xff\xff\xff",
> +	}
> +};
> +#endif
> +
> +/**
>   * Matching pattern item definition.
>   *
>   * A pattern is formed by stacking items starting from the lowest protocol
> -- 
> 2.13.6
> 

-- 
Adrien Mazarguil
6WIND

^ permalink raw reply	[flat|nested] 61+ messages in thread

* Re: [dpdk-dev] [PATCH v3 2/4] ethdev: add packet field set aciton in flow API
  2018-04-16  6:10   ` [dpdk-dev] [PATCH v3 2/4] ethdev: add packet field set aciton " Qi Zhang
@ 2018-04-19 14:48     ` Adrien Mazarguil
  2018-04-20  2:24       ` Zhang, Qi Z
  0 siblings, 1 reply; 61+ messages in thread
From: Adrien Mazarguil @ 2018-04-19 14:48 UTC (permalink / raw)
  To: Qi Zhang
  Cc: dev, declan.doherty, sugesh.chandran, michael.j.glynn, yu.y.liu,
	konstantin.ananyev, bruce.richardson

Typo in commit title: aciton => action

On Mon, Apr 16, 2018 at 02:10:40PM +0800, Qi Zhang wrote:
> Add new action RTE_FLOW_ACTION_TYPE_FIELD_SET, it is used to
> modify fields of specific protocol layer of the packet, the
> action only apply on packets that contain the requireds protocol
> layer.

requireds => required

> 
> Signed-off-by: Qi Zhang <qi.z.zhang@intel.com>

(more below)

> ---
>  doc/guides/prog_guide/rte_flow.rst | 30 +++++++++++++++++++++++++++
>  lib/librte_ether/rte_flow.h        | 42 +++++++++++++++++++++++++++++++++++++-
>  2 files changed, 71 insertions(+), 1 deletion(-)
> 
> diff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst
> index 99468bf60..68deb9812 100644
> --- a/doc/guides/prog_guide/rte_flow.rst
> +++ b/doc/guides/prog_guide/rte_flow.rst
> @@ -1574,6 +1574,36 @@ fields in the pattern items.
>     | 1     | END      |
>     +-------+----------+
>  
> +Action: ``FILED_SET``
> +^^^^^^^^^^^^^^^^^^^^^

FILED_SET => FIELD_SET

> +
> +Modify the value of fields in a protocol layer, only applies to packets that
> +contain respective protocol layer.
> +
> +.. _table_rte_flow_action_field_set:
> +
> +.. table:: FIELD_SET
> +
> +   +---------------+-------------------------------------------------------------------+
> +   | Field         | Value                                                             |
> +   +===============+===================================================================+
> +   | ``type``      | Specify the type of a protocol layer. (see RTE_FLOW_ITEM_TYPE_*)  |
> +   +---------------+-------------------------------------------------------------------+
> +   | ``dir_level`` | Specify the level of matched protocol layer.                      |
> +   |               | direction (1b)                                                    |
> +   |               | 0: match start from outermost.                                    |
> +   |               | 1: match start from innermost.                                    |

Please remove the direction part. What devices can match is always outermost
up to the point where they can't recognize an inner header. "innermost" is
almost guaranteed to never have the desired effect.

> +   |               | level: (31b)                                                      |
> +   |               | 0: outermost or innermost protocol layer that matched @type       |
> +   |               | 1: next to outmost or innermost protocol layer that matched @type |
> +   |               | 2: and so on ...                                                  |

Then you can remove any reference to dir_level from here.

> +   +---------------+-------------------------------------------------------------------+
> +   |  ``new_val``  | Pointer to specific data structure according to protocol type,    |
> +   |               | the content is the new value to updtae.                           |

updtae => update

> +   +---------------+-------------------------------------------------------------------+
> +   |  ``mask``     | Bit-mask applied to new_val                                       |
> +   +---------------+-------------------------------------------------------------------+
> +
>  Negative types
>  ~~~~~~~~~~~~~~
>  
> diff --git a/lib/librte_ether/rte_flow.h b/lib/librte_ether/rte_flow.h
> index f84bbfda5..2dc95b6b8 100644
> --- a/lib/librte_ether/rte_flow.h
> +++ b/lib/librte_ether/rte_flow.h
> @@ -1245,7 +1245,15 @@ enum rte_flow_action_type {
>  	 *
>  	 * See struct rte_flow_action_security.
>  	 */
> -	RTE_FLOW_ACTION_TYPE_SECURITY
> +	RTE_FLOW_ACTION_TYPE_SECURITY,
> +
> +	/**
> +	 * Modify the value of fields in a protocol layer, only applies to
> +	 * packets that contain respective protocol layer.
> +	 *
> +	 * See struct rte_flow_action_field_set.
> +	 */
> +	RTE_FLOW_ACTION_TYPE_FIELD_SET,
>  };
>  
>  /**
> @@ -1384,6 +1392,38 @@ struct rte_flow_action_security {
>  };
>  
>  /**
> + * RTE_FLOW_ACTION_TYPE_FIELD_SET
> + *
> + * Modify the value of fields in a protocol layer, only applies to
> + * packets that contain respective protocol layer.
> + */
> +struct rte_flow_action_field_set {
> +	/**
> +	 * Specify the type of a protocol layer.
> +	 */
> +	enum rte_flow_item_type type;
> +	/**
> +	 * Specify the level of matched protocol layer.
> +	 *
> +	 * direction (1b)
> +	 * 0: match start from outermost.
> +	 * 1: match start from innermost.
> +	 *
> +	 * level (31b)
> +	 * 0: outermost|innermost protocol layer that matched @type.
> +	 * 1: next to outermost|innermost protocol layer that matched @type.
> +	 * 2: and so on ...
> +	 */
> +	uint32_t dir_level;

See above regarding this field.

> +	/**
> +	 * Pointer to specific data structure according to protocol type,
> +	 * the content is the new value to update.
> +	 */
> +	const void *new_val;
> +	const void *mask; /**< Bit-mask applied to new_val. */
> +};
> +
> +/**
>   * Definition of a single action.
>   *
>   * A list of actions is terminated by a END action.
> -- 
> 2.13.6
> 

Testpmd implementation and documentation update are also missing, however
I'm still not convinced by the definition of this new action, it seems too
generic to be useful (e.g. compare this with a dedicated "update destination
IPv4 address" action for instance).

What existing HW capabilities do you intend to expose through this, what
kind of fields can be updated at this point?

If it's still unclear, I suggest to remove this patch from the series or at
the very least mark it as experimental. You can even provide a forward
declaration without the contents of struct rte_flow_action_field_set to
prevent applications from using it before it's finalized.

-- 
Adrien Mazarguil
6WIND

^ permalink raw reply	[flat|nested] 61+ messages in thread

* Re: [dpdk-dev] [PATCH v3 3/4] ethdev: add TTL change actions in flow API
  2018-04-16  6:10   ` [dpdk-dev] [PATCH v3 3/4] ethdev: add TTL change actions " Qi Zhang
@ 2018-04-19 14:48     ` Adrien Mazarguil
  0 siblings, 0 replies; 61+ messages in thread
From: Adrien Mazarguil @ 2018-04-19 14:48 UTC (permalink / raw)
  To: Qi Zhang
  Cc: dev, declan.doherty, sugesh.chandran, michael.j.glynn, yu.y.liu,
	konstantin.ananyev, bruce.richardson

On Mon, Apr 16, 2018 at 02:10:41PM +0800, Qi Zhang wrote:
> Add couple OpenFlow frienldy TTL change actions.

frienldy => friendly

> 
> RTE_FLOW_ACTION_MLPS_TTL_DEC - decrement MPLS TTL.
> RTE_FLOW_ACTION_IP_TTL_DEC - decrement IP TTL.
> RTE_FLOW_ACTION_TTL_COPY_OUT - copy TTL outwards.
> RTE_FLOW_ACTION_TTL_COPY_IN - copy TTL inwards.
> 
> Signed-off-by: Qi Zhang <qi.z.zhang@intel.com>

These are OpenFlow actions whose behavior is defined by the OpenFlow
specification. They must have "OF" part of their name to make this clear,
as in "RTE_FLOW_ACTION_OF_MPLS_TTL_DEC".

More below.

> ---
>  app/test-pmd/cmdline_flow.c                 | 64 +++++++++++++++++++++++
>  doc/guides/prog_guide/rte_flow.rst          | 80 +++++++++++++++++++++++++++++
>  doc/guides/testpmd_app_ug/testpmd_funcs.rst | 12 +++++
>  lib/librte_ether/rte_flow.h                 | 77 +++++++++++++++++++++++++++
>  4 files changed, 233 insertions(+)
> 
> diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c
> index 7950b1b8d..417cbecc9 100644
> --- a/app/test-pmd/cmdline_flow.c
> +++ b/app/test-pmd/cmdline_flow.c
> @@ -195,6 +195,12 @@ enum index {
>  	ACTION_VF_ID,
>  	ACTION_METER,
>  	ACTION_METER_ID,
> +	ACTION_MPLS_TTL_DEC,
> +	ACTION_MPLS_TTL_DEC_LVL,
> +	ACTION_IP_TTL_DEC,
> +	ACTION_IP_TTL_DEC_LVL,
> +	ACTION_TTL_COPY_OUT,
> +	ACTION_TTL_COPY_IN,
>  };
>  
>  /** Size of pattern[] field in struct rte_flow_item_raw. */
> @@ -668,6 +674,10 @@ static const enum index next_action[] = {
>  	ACTION_PF,
>  	ACTION_VF,
>  	ACTION_METER,
> +	ACTION_MPLS_TTL_DEC,
> +	ACTION_IP_TTL_DEC,
> +	ACTION_TTL_COPY_OUT,
> +	ACTION_TTL_COPY_IN,
>  	ZERO,
>  };
>  
> @@ -708,6 +718,16 @@ static const enum index action_meter[] = {
>  	ZERO,
>  };
>  
> +static const enum index action_mpls_ttl_dec[] = {
> +	ACTION_MPLS_TTL_DEC_LVL,
> +	ZERO,
> +};
> +
> +static const enum index action_ip_ttl_dec[] = {
> +	ACTION_IP_TTL_DEC_LVL,
> +	ZERO,
> +};
> +

The OpenFlow specification doesn't mention any parameter for these
actions. Unless I'm mistaken, it doesn't have a concept of "level", please
remove them.

>  static int parse_init(struct context *, const struct token *,
>  		      const char *, unsigned int,
>  		      void *, unsigned int);
> @@ -1857,6 +1877,50 @@ static const struct token token_list[] = {
>  		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter, mtr_id)),
>  		.call = parse_vc_conf,
>  	},
> +	[ACTION_MPLS_TTL_DEC] = {
> +		.name = "mpls_ttl_dec",

mpls_ttl_dec => of_mpls_ttl_dec

> +		.help = "decrement MPLS TTL",
> +		.priv = PRIV_ACTION(MPLS_TTL_DEC,
> +				sizeof(struct rte_flow_action_mpls_ttl_dec)),
> +		.next = NEXT(action_mpls_ttl_dec),
> +		.call = parse_vc,
> +	},
> +	[ACTION_MPLS_TTL_DEC_LVL] = {
> +		.name = "level",
> +		.help = "level of MPLS header",
> +		.next = NEXT(action_mpls_ttl_dec, NEXT_ENTRY(UNSIGNED)),
> +		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_queue, index)),
> +		.call = parse_vc,
> +	},
> +	[ACTION_IP_TTL_DEC] = {
> +		.name = "ip_ttl_dec",

ip_ttl_dec => of_ip_ttl_dec

> +		.help = "decrement IPv4 TTL or IPv6 Hop Limit",
> +		.priv = PRIV_ACTION(MPLS_TTL_DEC,
> +				sizeof(struct rte_flow_action_ip_ttl_dec)),
> +		.next = NEXT(action_ip_ttl_dec),
> +		.call = parse_vc,
> +	},
> +	[ACTION_IP_TTL_DEC_LVL] = {
> +		.name = "level",
> +		.help = "level of IPv4 or IPv6 header",
> +		.next = NEXT(action_ip_ttl_dec, NEXT_ENTRY(UNSIGNED)),
> +		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_queue, index)),
> +		.call = parse_vc,
> +	},
> +	[ACTION_TTL_COPY_OUT] = {
> +		.name = "ttl_copy_out",

ttl_copy_out => of_ttl_copy_out

> +		.help = "copy TTL outwards",
> +		.priv = PRIV_ACTION(DROP, 0),

Should be "PRIV_ACTION(ACTION_TTL_COPY_OUT, 0)".

> +		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
> +		.call = parse_vc,
> +	},
> +	[ACTION_TTL_COPY_IN] = {
> +		.name = "ttl_copy_in",

ttl_copy_in => of_ttl_copy_in

> +		.help = "copy TTL inwards",
> +		.priv = PRIV_ACTION(DROP, 0),

Should be "PRIV_ACTION(ACTION_TTL_COPY_IN, 0)".

> +		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
> +		.call = parse_vc,
> +	},
>  };
>  
>  /** Remove and return last entry from argument stack. */
> diff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst
> index 68deb9812..65f2d4a16 100644
> --- a/doc/guides/prog_guide/rte_flow.rst
> +++ b/doc/guides/prog_guide/rte_flow.rst
> @@ -1604,6 +1604,86 @@ contain respective protocol layer.
>     |  ``mask``     | Bit-mask applied to new_val                                       |
>     +---------------+-------------------------------------------------------------------+
>  
> +Action: ``MPLS_TTL_DEC``
> +^^^^^^^^^^^^^^^^^^^^^^^^
> +
> +Decrement MPLS TTL, only applies to packets that contain specific MPLS
> +headers.
> +
> +.. _table_rte_flow_action_mpls_ttl_dec:
> +
> +.. table:: MPLS_TTL_DEC
> +
> +   +---------------+---------------------------------------------+
> +   | Field         | Value                                       |
> +   +===============+=============================================+
> +   | ``dir_level`` | Specify the level of MPLS header.           |
> +   |               | direction (1b)                              |
> +   |               | 0: match start from outermost.              |
> +   |               | 1: match start from innermost.              |
> +   |               | level: (31b)                                |
> +   |               | 0: outermost or innermost MPLS header       |
> +   |               | 1: next to outmost or innermost MPLS header |
> +   |               | 2: and so on ...                            |
> +   +---------------+---------------------------------------------+

No need to document dir and level for the above reasons.

You must describe how it's an OpenFlow action and provide a link to the
relevant OF specification.

> +
> +Action: ``IP_TTL_DEC``
> +^^^^^^^^^^^^^^^^^^^^^^
> +
> +Decrement IPv4 TTL or IPv6 hop limit field and update the IP checksum,
> +only applies to packets that contain specific MPLS headers.
> +
> +.. _table_rte_flow_action_ip_ttl_dec:
> +
> +.. table:: IP_TTL_DEC
> +
> +   +---------------+----------------------------------------------------------+
> +   | Field         | Value                                                    |
> +   +===============+==========================================================+
> +   | ``dir_level`` | Specify the level of IPv4 or IPv6 header.                |
> +   |               | direction (1b)                                           |
> +   |               | 0: match start from outermost.                           |
> +   |               | 1: match start from innermost.                           |
> +   |               | level: (31b)                                             |
> +   |               | 0: outermost or innermost Ipv4 or IPv6 header            |
> +   |               | 1: next to outmost or innermost MPLS IPv4 or IPv6 header |
> +   |               | 2: and so on ...                                         |
> +   +---------------+----------------------------------------------------------+

Ditto.

> +
> +Action: ``TTL_COPY_OUT``
> +^^^^^^^^^^^^^^^^^^^^^^^^
> +
> +Copy the TTL from next-to-outermost to outermost header with TTL, copy can
> +be IP to IP, MPLS to MPLS or IP to MPLS, only applies packets that contain
> +required MPLS or IP headers.
> +
> +.. _table_rte_flow_action_ttl_copy_out:
> +
> +.. table:: TTL_COPY_OUT
> +
> +   +---------------+
> +   | Field         |
> +   +===============+
> +   | no properties |
> +   +---------------+

Same comment as above re linking to OpenFlow.

> +
> +Action: ``TTL_COPY_IN``
> +^^^^^^^^^^^^^^^^^^^^^^^
> +
> +Copy the TTL from outermost to next-to-outermost header with TTL, copy can
> +be IP to IP, MPLS to MPLS or MPLS to IP, only applies packets that contain
> +required MPLS or IP headers.
> +
> +.. _table_rte_flow_action_ttl_copy_in:
> +
> +.. table:: TTL_COPY_IN
> +
> +   +---------------+
> +   | Field         |
> +   +===============+
> +   | no properties |
> +   +---------------+

Ditto.

> +
>  Negative types
>  ~~~~~~~~~~~~~~
>  
> diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
> index 12d78f10b..d2fe6637b 100644
> --- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
> +++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
> @@ -3449,6 +3449,18 @@ This section lists supported actions and their attributes, if any.
>    - ``original {boolean}``: use original VF ID if possible.
>    - ``id {unsigned}``: VF ID to redirect packets to.
>  
> +- ``mpls_ttl_dec``: decrement MPLS TTL.
> +
> +  - ``level``: level of MPLS header.
> +
> +- ``ip_ttl_dec``: decrement IPv4 TTL or IPv6 Hot Limit.
> +
> +  - ``level``: level of IPv4 or IPv6 header.
> +
> +- ``ttl_copy_out``: copy TTL outwards.
> +
> +- ``ttl_copy_in``: copy TTL inwards.

"level" must be removed from here also.

> +
>  Destroying flow rules
>  ~~~~~~~~~~~~~~~~~~~~~
>  
> diff --git a/lib/librte_ether/rte_flow.h b/lib/librte_ether/rte_flow.h
> index 2dc95b6b8..ab181cd83 100644
> --- a/lib/librte_ether/rte_flow.h
> +++ b/lib/librte_ether/rte_flow.h
> @@ -1254,6 +1254,37 @@ enum rte_flow_action_type {
>  	 * See struct rte_flow_action_field_set.
>  	 */
>  	RTE_FLOW_ACTION_TYPE_FIELD_SET,
> +
> +	/**
> +	 * Decrement MPLS TTL, only applies to packets that contain specific
> +	 * MPLS header.
> +	 *
> +	 * See struct rte_flow_action_mpls_ttl_dec.
> +	 */
> +	RTE_FLOW_ACTION_TYPE_MPLS_TTL_DEC,
> +
> +	/**
> +	 * Decrement IPv4 TTL or IPv6 Hop limit field and update the IP
> +	 * checksum, only applies to packets that contain specific IPv4
> +	 * or IPv6 header.
> +	 *
> +	 * See struct rte_flow_action_ip_ttl_dec.
> +	 */
> +	RTE_FLOW_ACTION_TYPE_IP_TTL_DEC,
> +
> +	/**
> +	 * Copy the TTL from next-to-outermost to outermost header with TTL,
> +	 * copy can be IP to IP, MPLS to MPLS or IP to MPLS, only applies
> +	 * packets that contain required protocol headers.

As for other actions, please add:

 No associated configuration structure.

> +	 */
> +	RTE_FLOW_ACTION_TYPE_TTL_COPY_OUT,
> +
> +	/**
> +	 * Copy the TTL from outermost to next-to-outermost header with TTL,
> +	 * copy can be IP to IP, MPLS to MPLS or MPLS to IP, only applies
> +	 * packets that contain required protocol headers.

Ditto.

> +	 */
> +	RTE_FLOW_ACTION_TYPE_TTL_COPY_IN,
>  };
>  
>  /**
> @@ -1424,6 +1455,52 @@ struct rte_flow_action_field_set {
>  };
>  
>  /**
> + * RTE_FLOW_ACTION_TYPE_MPLS_TTL_DEC
> + *
> + * Decrement MPLS TTL, only applies to packets that contain specific
> + * MPLS header.
> + */
> +struct rte_flow_action_mpls_ttl_dec {
> +	/**
> +	 * Specify the level of MPLS header.
> +	 *
> +	 * direction (1b)
> +	 * 0: match start from outermost.
> +	 * 1: match start from innermost.
> +	 *
> +	 * level (31b)
> +	 * 0: outermost|innermost MPLS header.
> +	 * 1: next to outermost|innermost MPLS header.
> +	 * 2: and so on ...
> +	 */
> +	uint32_t dir_level;
> +
> +};

As described above, this structure must be removed.

> +
> +/**
> + * RTE_FLOW_ACTION_TYPE_IP_TTL_DEC
> + *
> + * Decrement IPv4 TTL or IPv6 hop limit field and update the IP
> + * checksum, only applies to packets that contain specific IPv4
> + * or IPv6 header.
> + */
> +struct rte_flow_action_ip_ttl_dec {
> +	/**
> +	 * Specify the level of IPv4 or IPv6 header.
> +	 *
> +	 * direction (1b)
> +	 * 0: match start from outermost.
> +	 * 1: match start from innermost.
> +	 *
> +	 * level (31b)
> +	 * 0: outermost|innermost IPv4 or IPv6 header.
> +	 * 1: next to outermost|innermost IPv4 or IPv6 header.
> +	 * 2: and so on ...
> +	 */
> +	uint32_t dir_level;
> +};

Ditto.

> +
> +/**
>   * Definition of a single action.
>   *
>   * A list of actions is terminated by a END action.
> -- 
> 2.13.6
> 

-- 
Adrien Mazarguil
6WIND

^ permalink raw reply	[flat|nested] 61+ messages in thread

* Re: [dpdk-dev] [PATCH v3 4/4] ethdev: add VLAN and MPLS pop push action in flow API
  2018-04-16  6:10   ` [dpdk-dev] [PATCH v3 4/4] ethdev: add VLAN and MPLS pop push action " Qi Zhang
  2018-04-17  7:34     ` Shahaf Shuler
@ 2018-04-19 14:49     ` Adrien Mazarguil
  1 sibling, 0 replies; 61+ messages in thread
From: Adrien Mazarguil @ 2018-04-19 14:49 UTC (permalink / raw)
  To: Qi Zhang
  Cc: dev, declan.doherty, sugesh.chandran, michael.j.glynn, yu.y.liu,
	konstantin.ananyev, bruce.richardson

On Mon, Apr 16, 2018 at 02:10:42PM +0800, Qi Zhang wrote:
> Add couple Openflow frienldy VLAN/MPLS push/pop actions.

Openflow => OpenFlow
frienldy => friendly

> 
> RTE_FLOW_ACTION_VLAN_POP - pop a VLAN header.
> RTE_FLOW_ACTION_VLAN_PUSH - push a VLAN header.
> RTE_FLOW_ACTION_MPLS_POP - pop a MPLS header.
> RTE_FLOW_ACTION_MPLS_PUSH - push a MPLS header.
> 
> Signed-off-by: Qi Zhang <qi.z.zhang@intel.com>

Same fundamental comment as for the previous patch ("ethdev: add TTL change
actions in flow API"), "OF" must be part of the name of these new actions,
e.g.:

 RTE_FLOW_ACTION_OF_VLAN_POP

More below.

> ---
>  app/test-pmd/cmdline_flow.c                 | 82 +++++++++++++++++++++++++++++
>  doc/guides/prog_guide/rte_flow.rst          | 69 ++++++++++++++++++++++++
>  doc/guides/testpmd_app_ug/testpmd_funcs.rst | 14 +++++
>  lib/librte_ether/rte_flow.h                 | 71 +++++++++++++++++++++++++
>  4 files changed, 236 insertions(+)
> 
> diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c
> index 417cbecc9..736d79bef 100644
> --- a/app/test-pmd/cmdline_flow.c
> +++ b/app/test-pmd/cmdline_flow.c
> @@ -201,6 +201,13 @@ enum index {
>  	ACTION_IP_TTL_DEC_LVL,
>  	ACTION_TTL_COPY_OUT,
>  	ACTION_TTL_COPY_IN,
> +	ACTION_VLAN_POP,
> +	ACTION_VLAN_PUSH,
> +	ACTION_VLAN_PUSH_TYPE,
> +	ACTION_MPLS_POP,
> +	ACTION_MPLS_POP_TYPE,
> +	ACTION_MPLS_PUSH,
> +	ACTION_MPLS_PUSH_TYPE,
>  };
>  
>  /** Size of pattern[] field in struct rte_flow_item_raw. */
> @@ -678,6 +685,10 @@ static const enum index next_action[] = {
>  	ACTION_IP_TTL_DEC,
>  	ACTION_TTL_COPY_OUT,
>  	ACTION_TTL_COPY_IN,
> +	ACTION_VLAN_POP,
> +	ACTION_VLAN_PUSH,
> +	ACTION_MPLS_POP,
> +	ACTION_MPLS_PUSH,
>  	ZERO,
>  };
>  
> @@ -728,6 +739,21 @@ static const enum index action_ip_ttl_dec[] = {
>  	ZERO,
>  };
>  
> +static const enum index action_vlan_push[] = {
> +	ACTION_VLAN_PUSH_TYPE,
> +	ZERO,
> +};
> +
> +static const enum index action_mpls_pop[] = {
> +	ACTION_MPLS_POP_TYPE,
> +	ZERO,
> +};
> +
> +static const enum index action_mpls_push[] = {
> +	ACTION_MPLS_PUSH_TYPE,
> +	ZERO,
> +};
> +
>  static int parse_init(struct context *, const struct token *,
>  		      const char *, unsigned int,
>  		      void *, unsigned int);
> @@ -1921,6 +1947,62 @@ static const struct token token_list[] = {
>  		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
>  		.call = parse_vc,
>  	},
> +
> +	[ACTION_VLAN_POP] = {
> +		.name = "vlan_pop",

vlan_pop => of_vlan_pop

> +		.help = "pop the outermost VLAN header.",

These help strings shouldn't be terminated with a "." for consistency.

> +		.priv = PRIV_ACTION(DROP, 0),

DROP => OF_VLAN_POP

> +		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
> +		.call = parse_vc,
> +	},
> +	[ACTION_VLAN_PUSH] = {
> +		.name = "vlan_push",

vlan_push => of_vlan_push

> +		.help = "push new VLAN header onto the packet",
> +		.priv = PRIV_ACTION(VLAN_PUSH,
> +				sizeof(struct rte_flow_action_vlan_push)),
> +		.next = NEXT(action_vlan_push),
> +		.call = parse_vc,
> +	},
> +	[ACTION_VLAN_PUSH_TYPE] = {
> +		.name = "type",
> +		.help = "Ethertype of VLAN header",
> +		.next = NEXT(action_vlan_push, NEXT_ENTRY(UNSIGNED)),

Ethertype => EtherType (here and everywhere else, this is the official name
for that field)

> +		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_vlan_push,
> +					ether_type)),
> +		.call = parse_vc,
> +	},
> +	[ACTION_MPLS_POP] = {
> +		.name = "mpls_pop",

mpls_pop => of_mpls_pop

> +		.help = "pop the outermost MPLS header",
> +		.priv = PRIV_ACTION(MPLS_POP,
> +				sizeof(struct rte_flow_action_mpls_pop)),
> +		.next = NEXT(action_mpls_pop),
> +		.call = parse_vc,
> +	},
> +	[ACTION_MPLS_POP_TYPE] = {
> +		.name = "type",
> +		.help = "Ethertype of MPLS header",
> +		.next = NEXT(action_mpls_pop, NEXT_ENTRY(UNSIGNED)),
> +		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_mpls_pop,
> +					ether_type)),
> +		.call = parse_vc,
> +	},
> +	[ACTION_MPLS_PUSH] = {
> +		.name = "mpls_push",

mpls_push => of_mpls_push

> +		.help = "push new MPLS header onto the packet",
> +		.priv = PRIV_ACTION(MPLS_PUSH,
> +				sizeof(struct rte_flow_action_mpls_push)),
> +		.next = NEXT(action_mpls_push),
> +		.call = parse_vc,
> +	},
> +	[ACTION_MPLS_PUSH_TYPE] = {
> +		.name = "type",
> +		.help = "Ethertype of MPLS header",
> +		.next = NEXT(action_mpls_push, NEXT_ENTRY(UNSIGNED)),
> +		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_mpls_push,
> +					ether_type)),
> +		.call = parse_vc,
> +	},
>  };
>  
>  /** Remove and return last entry from argument stack. */
> diff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst
> index 65f2d4a16..a009f1aac 100644
> --- a/doc/guides/prog_guide/rte_flow.rst
> +++ b/doc/guides/prog_guide/rte_flow.rst
> @@ -1684,6 +1684,75 @@ required MPLS or IP headers.
>     | no properties |
>     +---------------+
>  
> +Action: ``ACTION_VLAN_POP``
> +^^^^^^^^^^^^^^^^^^^^^^^^^^^
> +
> +Pop the outer-most VLAN header from the packet.
> +
> +.. _table_rte_flow_action_vlan_pop:
> +
> +.. table:: VLAN_POP
> +
> +   +---------------+
> +   | Field         |
> +   +===============+
> +   | no properties |
> +   +---------------+

Missing reference to OF specification etc.

> +
> +Action: ``ACTION_VLAN_PUSH``
> +^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> +
> +Push a new VLAN header onto the packet, Ethertype 0x8100 or 0x88a8 should
> +be used. The value of VLAN ID and VLAN priority for the new header is copied
> +from an exist VLAN header in the packet, they will be set to 0 if no such
> +VLAN header exist.
> +
> +.. _table_rte_flow_action_vlan_push:
> +
> +.. table:: VLAN_PUSH
> +
> +   +----------------+------------------------+
> +   | Field          | Value                  |
> +   +================+========================+
> +   | ``ether_type`` | Ethertype for VLAN tag |
> +   +----------------+------------------------+

Beside the missing reference to OF specification, I think this patch should
also provide a "VLAN action change" action, otherwise what's the point of
pushing a VLAN header without the ability to pick a VID?
(see ofp_action_vlan_vid).

> +
> +Action: ``ACTION_MPLS_POP``
> +^^^^^^^^^^^^^^^^^^^^^^^^^^^
> +
> +Pop the outer-most MPLS header from the packet, Ethertype is required for
> +the resulting packet if it is not the last MPLS header be popped, Ethertype
> +must be 0x8847 or 0x8848.
> +
> +.. _table_rte_flow_action_mpls_pop:
> +
> +.. table:: MPLS_POP
> +
> +   +----------------+---------------------------+
> +   | Field          | Value                     |
> +   +================+===========================+
> +   | ``ether_type`` | Ethertype for MPLS header |
> +   +----------------+---------------------------+

Name this field "ethertype" (without "_") like its OF counterpart.

> +
> +Action: ``ACTION_MPLS_PUSH``
> +^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> +
> +Push a new MPLS header onto the packet, Ethertype 0x8847 or 0x8848 should
> +be used. The value of MPLS label and traffic class is copied from exist
> +outermost MPLS header, and TTL is copied from exist outermost MPLS or IP
> +header, they will be set to 0 if exist packet does not contain required
> +header.
> +
> +.. _table_rte_flow_action_mpls_push:
> +
> +.. table:: MPLS_PUSH
> +
> +   +----------------+---------------------------+
> +   | Field          | Value                     |
> +   +================+===========================+
> +   | ``ether_type`` | Ethertype for MPLS header |
> +   +----------------+---------------------------+

Ditto.

> +
>  Negative types
>  ~~~~~~~~~~~~~~
>  
> diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
> index d2fe6637b..c06f2f0b0 100644
> --- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
> +++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
> @@ -3461,6 +3461,20 @@ This section lists supported actions and their attributes, if any.
>  
>  - ``ttl_copy_in``: copy TTL inwards.
>  
> +- ``vlan_pop``: pop the outermost VLAN header.
> +
> +- ``vlan_push``: push new VLAN header onto the packet.
> +
> +  - ``type``: Ethertype of the VLAN header.
> +
> +- ``mpls_pop``: pop the outermost MPLS header.
> +
> +  - ``type``: Ethertype of the MPLS header.
> +
> +- ``mpls_push``: push new MPLS header onto the packet.
> +
> +  - ``type``: Ethertype of the MPLS header.
> +
>  Destroying flow rules
>  ~~~~~~~~~~~~~~~~~~~~~
>  
> diff --git a/lib/librte_ether/rte_flow.h b/lib/librte_ether/rte_flow.h
> index ab181cd83..c5b30363e 100644
> --- a/lib/librte_ether/rte_flow.h
> +++ b/lib/librte_ether/rte_flow.h
> @@ -1285,6 +1285,41 @@ enum rte_flow_action_type {
>  	 * packets that contain required protocol headers.
>  	 */
>  	RTE_FLOW_ACTION_TYPE_TTL_COPY_IN,
> +
> +	/**
> +	 * Pop the outer-most VLAN header from the packet.

As for other actions without one, please add:

 No associated configuration structure.

> +	 */
> +	RTE_FLOW_ACTION_TYPE_VLAN_POP,
> +
> +	/**
> +	 * Push a new VLAN header onto the packet, Ethertype 0x8100 or 0x88a8
> +	 * should be used. The value of VLAN ID and VLAN priority for the new
> +	 * header is copied from an exist VLAN header in the packet, they will
> +	 * be set to 0 if no such VLAN header exist.
> +	 *
> +	 * See struct rte_flow_action_vlan_push.
> +	 */
> +	RTE_FLOW_ACTION_TYPE_VLAN_PUSH,
> +
> +	/**
> +	 * Pop the outer-most MPLS header from the packet, Ethertype is
> +	 * required for the resulting packet if it is not the last MPLS
> +	 * header be popped, Ethertype must be 0x8847 or 0x8848.
> +	 *
> +	 * See struct rte_flow_action_mpls_pop.
> +	 */
> +	RTE_FLOW_ACTION_TYPE_MPLS_POP,
> +
> +	/**
> +	 * Push a new MPLS header onto the packet, Ethertype 0x8847 or 0x8848
> +	 * should be used. The value of MPLS label and traffic class is copied
> +	 * from exist outermost MPLS header, and TTL is copied from exist
> +	 * outermost MPLS or IP header, they will be set to 0 if exist packet
> +	 * does not contain required header.
> +	 *
> +	 * See struct rte_flow_action_mpls_push.
> +	 */
> +	RTE_FLOW_ACTION_TYPE_MPLS_PUSH,
>  };
>  
>  /**
> @@ -1501,6 +1536,42 @@ struct rte_flow_action_ip_ttl_dec {
>  };
>  
>  /**
> + * RTE_FLOW_ACTION_TYPE_VLAN_PUSH,
> + *
> + * Push a new VLAN header onto the packet, Ethertype 0x8100 or 0x88a8
> + * should be used. The value of VLAN ID and VLAN priority for the new
> + * header is copied from an exist outermost VLAN header in the packet,
> + * they will be set to 0 if no such VLAN header exist.
> + */
> +struct rte_flow_action_vlan_push {
> +	rte_be16_t ether_type; /**< Ethertype for vlan tag. */
> +};
> +
> +/**
> + * RTE_FLOW_ACTION_TYPE_MPLS_POP,
> + *
> + * Pop the outer-most MPLS header from the packet, Ethertype is
> + * required for the resulting packet if it is not the last MPLS
> + * header be popped, Ethertype must be 0x8847 or 0x8848.
> + */
> +struct rte_flow_action_mpls_pop {
> +	rte_be16_t ether_type; /**< Ethertype for MPLS header */
> +};
> +
> +/**
> + * RTE_FLOW_ACTION_TYPE_MPLS_PUSH,
> + *
> + * Push a new MPLS header onto the packet, Ethertype 0x8847 or 0x8848
> + * should be used. The value of MPLS label and traffic class are copied
> + * from exist outermost MPLS header, and TTL is copied from exist outermost
> + * MPLS or IP header, they will be set to 0, if exist packet does not
> + * contain required header.
> + */
> +struct rte_flow_action_mpls_push {
> +	rte_be16_t ether_type; /**< Ethertype for MPLS header */
> +};
> +
> +/**
>   * Definition of a single action.
>   *
>   * A list of actions is terminated by a END action.
> -- 
> 2.13.6
> 

-- 
Adrien Mazarguil
6WIND

^ permalink raw reply	[flat|nested] 61+ messages in thread

* Re: [dpdk-dev] [PATCH v3 2/4] ethdev: add packet field set aciton in flow API
  2018-04-19 14:48     ` Adrien Mazarguil
@ 2018-04-20  2:24       ` Zhang, Qi Z
  2018-04-20  8:54         ` Adrien Mazarguil
  0 siblings, 1 reply; 61+ messages in thread
From: Zhang, Qi Z @ 2018-04-20  2:24 UTC (permalink / raw)
  To: Adrien Mazarguil
  Cc: dev, Doherty, Declan, Chandran, Sugesh, Glynn, Michael J, Liu,
	Yu Y, Ananyev, Konstantin, Richardson, Bruce

Hi Adrien:

> -----Original Message-----
> From: Adrien Mazarguil [mailto:adrien.mazarguil@6wind.com]
> Sent: Thursday, April 19, 2018 10:49 PM
> To: Zhang, Qi Z <qi.z.zhang@intel.com>
> Cc: dev@dpdk.org; Doherty, Declan <declan.doherty@intel.com>; Chandran,
> Sugesh <sugesh.chandran@intel.com>; Glynn, Michael J
> <michael.j.glynn@intel.com>; Liu, Yu Y <yu.y.liu@intel.com>; Ananyev,
> Konstantin <konstantin.ananyev@intel.com>; Richardson, Bruce
> <bruce.richardson@intel.com>
> Subject: Re: [PATCH v3 2/4] ethdev: add packet field set aciton in flow API
> 
> Typo in commit title: aciton => action
> 
> On Mon, Apr 16, 2018 at 02:10:40PM +0800, Qi Zhang wrote:
> > Add new action RTE_FLOW_ACTION_TYPE_FIELD_SET, it is used to modify
> > fields of specific protocol layer of the packet, the action only apply
> > on packets that contain the requireds protocol layer.
> 
> requireds => required
> 
> >
> > Signed-off-by: Qi Zhang <qi.z.zhang@intel.com>
> 
> (more below)
> 
> > ---
> >  doc/guides/prog_guide/rte_flow.rst | 30
> +++++++++++++++++++++++++++
> >  lib/librte_ether/rte_flow.h        | 42
> +++++++++++++++++++++++++++++++++++++-
> >  2 files changed, 71 insertions(+), 1 deletion(-)
> >
> > diff --git a/doc/guides/prog_guide/rte_flow.rst
> > b/doc/guides/prog_guide/rte_flow.rst
> > index 99468bf60..68deb9812 100644
> > --- a/doc/guides/prog_guide/rte_flow.rst
> > +++ b/doc/guides/prog_guide/rte_flow.rst
> > @@ -1574,6 +1574,36 @@ fields in the pattern items.
> >     | 1     | END      |
> >     +-------+----------+
> >
> > +Action: ``FILED_SET``
> > +^^^^^^^^^^^^^^^^^^^^^
> 
> FILED_SET => FIELD_SET
> 
> > +
> > +Modify the value of fields in a protocol layer, only applies to
> > +packets that contain respective protocol layer.
> > +
> > +.. _table_rte_flow_action_field_set:
> > +
> > +.. table:: FIELD_SET
> > +
> > +   +---------------+-------------------------------------------------------------------+
> > +   | Field         | Value
> |
> > +
> +===============+==============================================
> =====================+
> > +   | ``type``      | Specify the type of a protocol layer. (see
> RTE_FLOW_ITEM_TYPE_*)  |
> > +   +---------------+-------------------------------------------------------------------+
> > +   | ``dir_level`` | Specify the level of matched protocol layer.
> |
> > +   |               | direction (1b)
> |
> > +   |               | 0: match start from outermost.
> |
> > +   |               | 1: match start from innermost.
> |
> 
> Please remove the direction part. What devices can match is always
> outermost up to the point where they can't recognize an inner header.
> "innermost" is almost guaranteed to never have the desired effect.
> 
> > +   |               | level: (31b)
> |
> > +   |               | 0: outermost or innermost protocol layer that
> matched @type       |
> > +   |               | 1: next to outmost or innermost protocol layer
> that matched @type |
> > +   |               | 2: and so on ...
> |
> 
> Then you can remove any reference to dir_level from here.
> 
> > +   +---------------+-------------------------------------------------------------------+
> > +   |  ``new_val``  | Pointer to specific data structure according to
> protocol type,    |
> > +   |               | the content is the new value to updtae.
> |
> 
> updtae => update
> 
> > +   +---------------+-------------------------------------------------------------------+
> > +   |  ``mask``     | Bit-mask applied to new_val
> |
> > +
> > + +---------------+---------------------------------------------------
> > + ----------------+
> > +
> >  Negative types
> >  ~~~~~~~~~~~~~~
> >
> > diff --git a/lib/librte_ether/rte_flow.h b/lib/librte_ether/rte_flow.h
> > index f84bbfda5..2dc95b6b8 100644
> > --- a/lib/librte_ether/rte_flow.h
> > +++ b/lib/librte_ether/rte_flow.h
> > @@ -1245,7 +1245,15 @@ enum rte_flow_action_type {
> >  	 *
> >  	 * See struct rte_flow_action_security.
> >  	 */
> > -	RTE_FLOW_ACTION_TYPE_SECURITY
> > +	RTE_FLOW_ACTION_TYPE_SECURITY,
> > +
> > +	/**
> > +	 * Modify the value of fields in a protocol layer, only applies to
> > +	 * packets that contain respective protocol layer.
> > +	 *
> > +	 * See struct rte_flow_action_field_set.
> > +	 */
> > +	RTE_FLOW_ACTION_TYPE_FIELD_SET,
> >  };
> >
> >  /**
> > @@ -1384,6 +1392,38 @@ struct rte_flow_action_security {  };
> >
> >  /**
> > + * RTE_FLOW_ACTION_TYPE_FIELD_SET
> > + *
> > + * Modify the value of fields in a protocol layer, only applies to
> > + * packets that contain respective protocol layer.
> > + */
> > +struct rte_flow_action_field_set {
> > +	/**
> > +	 * Specify the type of a protocol layer.
> > +	 */
> > +	enum rte_flow_item_type type;
> > +	/**
> > +	 * Specify the level of matched protocol layer.
> > +	 *
> > +	 * direction (1b)
> > +	 * 0: match start from outermost.
> > +	 * 1: match start from innermost.
> > +	 *
> > +	 * level (31b)
> > +	 * 0: outermost|innermost protocol layer that matched @type.
> > +	 * 1: next to outermost|innermost protocol layer that matched @type.
> > +	 * 2: and so on ...
> > +	 */
> > +	uint32_t dir_level;
> 
> See above regarding this field.
> 
> > +	/**
> > +	 * Pointer to specific data structure according to protocol type,
> > +	 * the content is the new value to update.
> > +	 */
> > +	const void *new_val;
> > +	const void *mask; /**< Bit-mask applied to new_val. */ };
> > +
> > +/**
> >   * Definition of a single action.
> >   *
> >   * A list of actions is terminated by a END action.
> > --
> > 2.13.6
> >
> 
> Testpmd implementation and documentation update are also missing,
> however
> I'm still not convinced by the definition of this new action, it seems too
> generic to be useful (e.g. compare this with a dedicated "update destination
> IPv4 address" action for instance).
> 
> What existing HW capabilities do you intend to expose through this, what
> kind of fields can be updated at this point?

For our device, there will be more than 20 actions if we create an action for each field like "RTE_FLOW_ACTION_TYPE_IPV4_ADDR_SET",
More detail, that will cover fields in IPV4/IPV6/Ether/ICMP/ND/ARP, so I think a generic field set action would be better.

For testpmd support, Seems there is no reference to enable an action with void parameters, so it may take me time to figure out a solution,
I'm not sure I can capture this on the 18.05, so is that possible we just deferred testpmd support for this action? since I saw action like rte_flow_action_security also don't have
testpmd support yet.

Thanks
Qi

> 
> If it's still unclear, I suggest to remove this patch from the series or at
> the very least mark it as experimental. You can even provide a forward
> declaration without the contents of struct rte_flow_action_field_set to
> prevent applications from using it before it's finalized.
> 
> --
> Adrien Mazarguil
> 6WIND

^ permalink raw reply	[flat|nested] 61+ messages in thread

* Re: [dpdk-dev] [PATCH v3 2/4] ethdev: add packet field set aciton in flow API
  2018-04-20  2:24       ` Zhang, Qi Z
@ 2018-04-20  8:54         ` Adrien Mazarguil
  0 siblings, 0 replies; 61+ messages in thread
From: Adrien Mazarguil @ 2018-04-20  8:54 UTC (permalink / raw)
  To: Zhang, Qi Z
  Cc: dev, Doherty, Declan, Chandran, Sugesh, Glynn, Michael J, Liu,
	Yu Y, Ananyev, Konstantin, Richardson, Bruce

On Fri, Apr 20, 2018 at 02:24:20AM +0000, Zhang, Qi Z wrote:
> Hi Adrien:
> 
> > -----Original Message-----
> > From: Adrien Mazarguil [mailto:adrien.mazarguil@6wind.com]
> > Sent: Thursday, April 19, 2018 10:49 PM
> > To: Zhang, Qi Z <qi.z.zhang@intel.com>
> > Cc: dev@dpdk.org; Doherty, Declan <declan.doherty@intel.com>; Chandran,
> > Sugesh <sugesh.chandran@intel.com>; Glynn, Michael J
> > <michael.j.glynn@intel.com>; Liu, Yu Y <yu.y.liu@intel.com>; Ananyev,
> > Konstantin <konstantin.ananyev@intel.com>; Richardson, Bruce
> > <bruce.richardson@intel.com>
> > Subject: Re: [PATCH v3 2/4] ethdev: add packet field set aciton in flow API
> > 
> > Typo in commit title: aciton => action
> > 
> > On Mon, Apr 16, 2018 at 02:10:40PM +0800, Qi Zhang wrote:
> > > Add new action RTE_FLOW_ACTION_TYPE_FIELD_SET, it is used to modify
> > > fields of specific protocol layer of the packet, the action only apply
> > > on packets that contain the requireds protocol layer.
> > 
> > requireds => required
> > 
> > >
> > > Signed-off-by: Qi Zhang <qi.z.zhang@intel.com>
> > 
> > (more below)
> > 
> > > ---
> > >  doc/guides/prog_guide/rte_flow.rst | 30
> > +++++++++++++++++++++++++++
> > >  lib/librte_ether/rte_flow.h        | 42
> > +++++++++++++++++++++++++++++++++++++-
> > >  2 files changed, 71 insertions(+), 1 deletion(-)
> > >
> > > diff --git a/doc/guides/prog_guide/rte_flow.rst
> > > b/doc/guides/prog_guide/rte_flow.rst
> > > index 99468bf60..68deb9812 100644
> > > --- a/doc/guides/prog_guide/rte_flow.rst
> > > +++ b/doc/guides/prog_guide/rte_flow.rst
> > > @@ -1574,6 +1574,36 @@ fields in the pattern items.
> > >     | 1     | END      |
> > >     +-------+----------+
> > >
> > > +Action: ``FILED_SET``
> > > +^^^^^^^^^^^^^^^^^^^^^
> > 
> > FILED_SET => FIELD_SET
> > 
> > > +
> > > +Modify the value of fields in a protocol layer, only applies to
> > > +packets that contain respective protocol layer.
> > > +
> > > +.. _table_rte_flow_action_field_set:
> > > +
> > > +.. table:: FIELD_SET
> > > +
> > > +   +---------------+-------------------------------------------------------------------+
> > > +   | Field         | Value
> > |
> > > +
> > +===============+==============================================
> > =====================+
> > > +   | ``type``      | Specify the type of a protocol layer. (see
> > RTE_FLOW_ITEM_TYPE_*)  |
> > > +   +---------------+-------------------------------------------------------------------+
> > > +   | ``dir_level`` | Specify the level of matched protocol layer.
> > |
> > > +   |               | direction (1b)
> > |
> > > +   |               | 0: match start from outermost.
> > |
> > > +   |               | 1: match start from innermost.
> > |
> > 
> > Please remove the direction part. What devices can match is always
> > outermost up to the point where they can't recognize an inner header.
> > "innermost" is almost guaranteed to never have the desired effect.
> > 
> > > +   |               | level: (31b)
> > |
> > > +   |               | 0: outermost or innermost protocol layer that
> > matched @type       |
> > > +   |               | 1: next to outmost or innermost protocol layer
> > that matched @type |
> > > +   |               | 2: and so on ...
> > |
> > 
> > Then you can remove any reference to dir_level from here.
> > 
> > > +   +---------------+-------------------------------------------------------------------+
> > > +   |  ``new_val``  | Pointer to specific data structure according to
> > protocol type,    |
> > > +   |               | the content is the new value to updtae.
> > |
> > 
> > updtae => update
> > 
> > > +   +---------------+-------------------------------------------------------------------+
> > > +   |  ``mask``     | Bit-mask applied to new_val
> > |
> > > +
> > > + +---------------+---------------------------------------------------
> > > + ----------------+
> > > +
> > >  Negative types
> > >  ~~~~~~~~~~~~~~
> > >
> > > diff --git a/lib/librte_ether/rte_flow.h b/lib/librte_ether/rte_flow.h
> > > index f84bbfda5..2dc95b6b8 100644
> > > --- a/lib/librte_ether/rte_flow.h
> > > +++ b/lib/librte_ether/rte_flow.h
> > > @@ -1245,7 +1245,15 @@ enum rte_flow_action_type {
> > >  	 *
> > >  	 * See struct rte_flow_action_security.
> > >  	 */
> > > -	RTE_FLOW_ACTION_TYPE_SECURITY
> > > +	RTE_FLOW_ACTION_TYPE_SECURITY,
> > > +
> > > +	/**
> > > +	 * Modify the value of fields in a protocol layer, only applies to
> > > +	 * packets that contain respective protocol layer.
> > > +	 *
> > > +	 * See struct rte_flow_action_field_set.
> > > +	 */
> > > +	RTE_FLOW_ACTION_TYPE_FIELD_SET,
> > >  };
> > >
> > >  /**
> > > @@ -1384,6 +1392,38 @@ struct rte_flow_action_security {  };
> > >
> > >  /**
> > > + * RTE_FLOW_ACTION_TYPE_FIELD_SET
> > > + *
> > > + * Modify the value of fields in a protocol layer, only applies to
> > > + * packets that contain respective protocol layer.
> > > + */
> > > +struct rte_flow_action_field_set {
> > > +	/**
> > > +	 * Specify the type of a protocol layer.
> > > +	 */
> > > +	enum rte_flow_item_type type;
> > > +	/**
> > > +	 * Specify the level of matched protocol layer.
> > > +	 *
> > > +	 * direction (1b)
> > > +	 * 0: match start from outermost.
> > > +	 * 1: match start from innermost.
> > > +	 *
> > > +	 * level (31b)
> > > +	 * 0: outermost|innermost protocol layer that matched @type.
> > > +	 * 1: next to outermost|innermost protocol layer that matched @type.
> > > +	 * 2: and so on ...
> > > +	 */
> > > +	uint32_t dir_level;
> > 
> > See above regarding this field.
> > 
> > > +	/**
> > > +	 * Pointer to specific data structure according to protocol type,
> > > +	 * the content is the new value to update.
> > > +	 */
> > > +	const void *new_val;
> > > +	const void *mask; /**< Bit-mask applied to new_val. */ };
> > > +
> > > +/**
> > >   * Definition of a single action.
> > >   *
> > >   * A list of actions is terminated by a END action.
> > > --
> > > 2.13.6
> > >
> > 
> > Testpmd implementation and documentation update are also missing,
> > however
> > I'm still not convinced by the definition of this new action, it seems too
> > generic to be useful (e.g. compare this with a dedicated "update destination
> > IPv4 address" action for instance).
> > 
> > What existing HW capabilities do you intend to expose through this, what
> > kind of fields can be updated at this point?
> 
> For our device, there will be more than 20 actions if we create an action for each field like "RTE_FLOW_ACTION_TYPE_IPV4_ADDR_SET",
> More detail, that will cover fields in IPV4/IPV6/Ether/ICMP/ND/ARP, so I think a generic field set action would be better.

I see. You know, I think adding 20+ focused actions would be fine actually,
easier to document, report as HW capabilities and to use by applications
(e.g. see issue you raise about adding testpmd support below).

In all the protocols you mention, is the device able to really update *all*
fields or only the "usual" set? IPv4 src/dst probably, now what about ToS,
packet ID, fragment offset and so on? Same for other protocols, should we
care about protocol fields that applications rarely set (if at all),
especially if no device can update them?

> For testpmd support, Seems there is no reference to enable an action with void parameters, so it may take me time to figure out a solution,

Dedicated actions on the other hand should be way easier to add :)

> I'm not sure I can capture this on the 18.05, so is that possible we just deferred testpmd support for this action? since I saw action like rte_flow_action_security also don't have
> testpmd support yet.

I know, there are several problematic actions without testpmd
support. However those are often associated with experimental APIs and may
be modified without prior notice.

Keep in mind there is no need to rush. Adding rte_flow actions doesn't hurt
ABI and can be done for any DPDK release, even part of the same series as
the first PMD implementation which must be validated somehow (no one ever
submits code that can't be tested, right?), this is why testpmd support is
mandatory.

> > If it's still unclear, I suggest to remove this patch from the series or at
> > the very least mark it as experimental. You can even provide a forward
> > declaration without the contents of struct rte_flow_action_field_set to
> > prevent applications from using it before it's finalized.

-- 
Adrien Mazarguil
6WIND

^ permalink raw reply	[flat|nested] 61+ messages in thread

* [dpdk-dev] [PATCH v4 0/3] rte_flow extension for vSwitch acceleration
  2018-03-28 23:29 [dpdk-dev] [PATCH 0/4] rte_flow extension for vSwitch acceleration Qi Zhang
                   ` (6 preceding siblings ...)
  2018-04-16  6:10 ` [dpdk-dev] [PATCH v3 0/4] rte_flow extension for vSwitch acceleration Qi Zhang
@ 2018-04-23  6:36 ` Qi Zhang
  2018-04-23  6:36   ` [dpdk-dev] [PATCH v4 1/3] ethdev: add more protocol support in flow API Qi Zhang
                     ` (3 more replies)
  7 siblings, 4 replies; 61+ messages in thread
From: Qi Zhang @ 2018-04-23  6:36 UTC (permalink / raw)
  To: adrien.mazarguil
  Cc: dev, declan.doherty, sugesh.chandran, michael.j.glynn, yu.y.liu,
	konstantin.ananyev, bruce.richardson, Qi Zhang

From: Qi Zhang <Qi.z.zhang@intel.com>

v4:
- Change to OpenFlow complied TTL actions
- Change to OpenFlow complied VLAN/MPLS actions. 
- typos fix.
- Remove generic field_set action since, couple opens not closed (should we move
  to dedicate filed modification actions?)

v3:
- remove patch for port action and enhanced statistic query.
- reworked IPv6 ND related pattern base on Adrien's suggestion.
- remove generic increament/decrement/copy action
- rework packet modification action(RTE_FLOW_ACTION_TYPE_FIELD_SET).
- Add OpenFlow friendly TTL change actions.
- Add OpenFlow friendly VLAN/MPLS push/pop actions

v2:
- fix couple typoes in code, doc and commit log

This patch extend rte_flow API.
The purpose is to provide necessary programming interface for virtual
switch software (such as OVS) to take advantage of incoming device's
vSwitch acceleration capability when using DPDK as data plane.

Note:
- The driver to demonstrate the new APIs is still in development,
  but we hope it could be accepted early to make OVS integration
  smoothly. 

Qi Zhang (3):
  ethdev: add more protocol support in flow API
  ethdev: add TTL change actions in flow API
  ethdev: add VLAN and MPLS actions in flow API

 app/test-pmd/cmdline_flow.c                 | 444 ++++++++++++++++++++++++++++
 app/test-pmd/config.c                       |   9 +
 doc/guides/prog_guide/rte_flow.rst          | 291 ++++++++++++++++++
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  72 +++++
 lib/librte_ether/rte_flow.h                 | 432 ++++++++++++++++++++++++++-
 5 files changed, 1247 insertions(+), 1 deletion(-)

-- 
2.13.6

^ permalink raw reply	[flat|nested] 61+ messages in thread

* [dpdk-dev] [PATCH v4 1/3] ethdev: add more protocol support in flow API
  2018-04-23  6:36 ` [dpdk-dev] [PATCH v4 0/3] rte_flow extension for vSwitch acceleration Qi Zhang
@ 2018-04-23  6:36   ` Qi Zhang
  2018-04-23  6:36   ` [dpdk-dev] [PATCH v4 2/3] ethdev: add TTL change actions " Qi Zhang
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 61+ messages in thread
From: Qi Zhang @ 2018-04-23  6:36 UTC (permalink / raw)
  To: adrien.mazarguil
  Cc: dev, declan.doherty, sugesh.chandran, michael.j.glynn, yu.y.liu,
	konstantin.ananyev, bruce.richardson, Qi Zhang

Add new protocol header match support as below

RTE_FLOW_ITEM_TYPE_ARP_IPV4
	- matches an IPv4 ARP header
RTE_FLOW_ITEM_TYPE_IPV6_EXT
	- matches an IPv6 extension header with any type.
RTE_FLOW_ITEM_TYPE_ICMP6
	- matches an ICMPv6 header followed by any message body.
RTE_FLOW_ITEM_TYPE_ICMP6_ND_NS
	- matches an ICMPv6 header followed by network discovery
	  neighbor solicitation.
RTE_FLOW_ITEM_TYPE_ICMP6_ND_NA
	- matches an ICMPv6 header followed by network discovery
	  neighbor advertisement.
RTE_FLOW_ITEM_TYPE_ICMP6_ND_OPT_ETH_SLA
	- matches an ICMPv6 header followed by network discovery
	  neighbor solicitation contains source Ethernet link-layer
	  address option.
RTE_FLOW_ITEM_TYPE_ICMP6_ND_OPT_ETH_TLA
	- matches an ICMPv6 header followed by network discovery
	  neighbor advertisement contains target Ethernet link-layer
	  address option.

Suggested-by: Adrien Mazarguil <adrien.mazarguil@6wind.com>
Signed-off-by: Qi Zhang <qi.z.zhang@intel.com>
---
 app/test-pmd/cmdline_flow.c                 | 224 ++++++++++++++++++++++++++
 app/test-pmd/config.c                       |   9 ++
 doc/guides/prog_guide/rte_flow.rst          |  88 +++++++++++
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  34 ++++
 lib/librte_ether/rte_flow.h                 | 235 ++++++++++++++++++++++++++++
 5 files changed, 590 insertions(+)

diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c
index 59f3b3b57..a9e4f56ba 100644
--- a/app/test-pmd/cmdline_flow.c
+++ b/app/test-pmd/cmdline_flow.c
@@ -150,6 +150,26 @@ enum index {
 	ITEM_GENEVE,
 	ITEM_GENEVE_VNI,
 	ITEM_GENEVE_PROTO,
+	ITEM_ARP_IPV4,
+	ITEM_ARP_IPV4_SHA,
+	ITEM_ARP_IPV4_SIP,
+	ITEM_ARP_IPV4_THA,
+	ITEM_ARP_IPV4_TIP,
+	ITEM_IPV6_EXT,
+	ITEM_IPV6_EXT_NEXT_HDR,
+	ITEM_ICMP6,
+	ITEM_ICMP6_TYPE,
+	ITEM_ICMP6_CODE,
+	ITEM_ICMP6_ND_NS,
+	ITEM_ICMP6_ND_NS_TGT_ADDR,
+	ITEM_ICMP6_ND_NA,
+	ITEM_ICMP6_ND_NA_TGT_ADDR,
+	ITEM_ICMP6_ND_OPT_SLA_ETH,
+	ITEM_ICMP6_ND_OPT_SLA_ETH_TGT_ADDR,
+	ITEM_ICMP6_ND_OPT_SLA_ETH_SLL_ADDR,
+	ITEM_ICMP6_ND_OPT_TLA_ETH,
+	ITEM_ICMP6_ND_OPT_TLA_ETH_TGT_ADDR,
+	ITEM_ICMP6_ND_OPT_TLA_ETH_TLL_ADDR,
 
 	/* Validate/create actions. */
 	ACTIONS,
@@ -436,6 +456,13 @@ static const enum index next_item[] = {
 	ITEM_GTPC,
 	ITEM_GTPU,
 	ITEM_GENEVE,
+	ITEM_ARP_IPV4,
+	ITEM_IPV6_EXT,
+	ITEM_ICMP6,
+	ITEM_ICMP6_ND_NS,
+	ITEM_ICMP6_ND_NA,
+	ITEM_ICMP6_ND_OPT_SLA_ETH,
+	ITEM_ICMP6_ND_OPT_TLA_ETH,
 	ZERO,
 };
 
@@ -586,6 +613,47 @@ static const enum index item_geneve[] = {
 	ZERO,
 };
 
+static const enum index item_arp_ipv4[] = {
+	ITEM_ARP_IPV4_SHA,
+	ITEM_ARP_IPV4_SIP,
+	ITEM_ARP_IPV4_THA,
+	ITEM_ARP_IPV4_TIP,
+	ZERO,
+};
+
+static const enum index item_ipv6_ext[] = {
+	ITEM_IPV6_EXT_NEXT_HDR,
+	ZERO,
+};
+
+static const enum index item_icmp6[] = {
+	ITEM_ICMP6_TYPE,
+	ITEM_ICMP6_CODE,
+	ZERO,
+};
+
+static const enum index item_icmp6_nd_ns[] = {
+	ITEM_ICMP6_ND_NS_TGT_ADDR,
+	ZERO,
+};
+
+static const enum index item_icmp6_nd_na[] = {
+	ITEM_ICMP6_ND_NA_TGT_ADDR,
+	ZERO,
+};
+
+static const enum index item_icmp6_nd_opt_sla_eth[] = {
+	ITEM_ICMP6_ND_OPT_SLA_ETH_TGT_ADDR,
+	ITEM_ICMP6_ND_OPT_SLA_ETH_SLL_ADDR,
+	ZERO,
+};
+
+static const enum index item_icmp6_nd_opt_tla_eth[] = {
+	ITEM_ICMP6_ND_OPT_TLA_ETH_TGT_ADDR,
+	ITEM_ICMP6_ND_OPT_TLA_ETH_TLL_ADDR,
+	ZERO,
+};
+
 static const enum index next_action[] = {
 	ACTION_END,
 	ACTION_VOID,
@@ -1473,6 +1541,162 @@ static const struct token token_list[] = {
 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve,
 					     protocol)),
 	},
+	[ITEM_ARP_IPV4] = {
+		.name = "arp",
+		.help = "match IPv4 ARP header",
+		.priv = PRIV_ITEM(ARP_IPV4,
+				  sizeof(struct rte_flow_item_arp_ipv4)),
+		.next = NEXT(item_arp_ipv4),
+		.call = parse_vc,
+	},
+	[ITEM_ARP_IPV4_SHA] = {
+		.name = "sha",
+		.help = "sender hardware address",
+		.next = NEXT(item_arp_ipv4, NEXT_ENTRY(UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_ipv4,
+					     arp_sha.addr_bytes)),
+	},
+	[ITEM_ARP_IPV4_SIP] = {
+		.name = "sip",
+		.help = "sender IP address",
+		.next = NEXT(item_arp_ipv4, NEXT_ENTRY(UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_ipv4,
+					     arp_sip)),
+	},
+	[ITEM_ARP_IPV4_THA] = {
+		.name = "tha",
+		.help = "target hardware address",
+		.next = NEXT(item_arp_ipv4, NEXT_ENTRY(UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_ipv4,
+					     arp_tha.addr_bytes)),
+	},
+	[ITEM_ARP_IPV4_TIP] = {
+		.name = "tip",
+		.help = "target IP address",
+		.next = NEXT(item_arp_ipv4, NEXT_ENTRY(UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_ipv4,
+					     arp_tip)),
+	},
+	[ITEM_IPV6_EXT] = {
+		.name = "ext",
+		.help = "match IPv6 extended header",
+		.priv = PRIV_ITEM(IPV6_EXT,
+				  sizeof(struct rte_flow_item_ipv6_ext)),
+		.next = NEXT(item_ipv6_ext),
+		.call = parse_vc,
+	},
+	[ITEM_IPV6_EXT_NEXT_HDR] = {
+		.name = "next",
+		.help = "next header in IPv6 extend header",
+		.next = NEXT(item_ipv6_ext, NEXT_ENTRY(UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_ext,
+					     next_hdr)),
+	},
+	[ITEM_ICMP6] = {
+		.name = "icmp6",
+		.help = "match ICMPv6 header",
+		.priv = PRIV_ITEM(ICMP, sizeof(struct rte_flow_item_icmp6)),
+		.next = NEXT(item_icmp6),
+		.call = parse_vc,
+	},
+	[ITEM_ICMP6_TYPE] = {
+		.name = "type",
+		.help = "ICMPv6 packet type",
+		.next = NEXT(item_icmp6, NEXT_ENTRY(UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6,
+					     type)),
+	},
+	[ITEM_ICMP6_CODE] = {
+		.name = "code",
+		.help = "ICMPv6 packet code",
+		.next = NEXT(item_icmp6, NEXT_ENTRY(UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6,
+					     code)),
+	},
+	[ITEM_ICMP6_ND_NS] = {
+		.name = "ns",
+		.help = "match neighbor solicitation over ICMPv6",
+		.priv = PRIV_ITEM(ICMP6_ND_NS,
+				  sizeof(struct rte_flow_item_icmp6_nd_ns)),
+		.next = NEXT(item_icmp6_nd_ns),
+		.call = parse_vc,
+	},
+	[ITEM_ICMP6_ND_NS_TGT_ADDR] = {
+		.name = "tgt_addr",
+		.help = "target address of neighbor solicitation",
+		.next = NEXT(item_icmp6_nd_ns, NEXT_ENTRY(UNSIGNED),
+			     item_param),
+		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_ns,
+					     target_addr)),
+	},
+	[ITEM_ICMP6_ND_NA] = {
+		.name = "na",
+		.help = "match neighbor advertisement over ICMPv6 ",
+		.priv = PRIV_ITEM(ICMP6_ND_NA,
+				  sizeof(struct rte_flow_item_icmp6_nd_na)),
+		.next = NEXT(item_icmp6_nd_na),
+		.call = parse_vc,
+	},
+	[ITEM_ICMP6_ND_NA_TGT_ADDR] = {
+		.name = "tgt_addr",
+		.help = "target address of neighbor advertisement",
+		.next = NEXT(item_icmp6_nd_na, NEXT_ENTRY(UNSIGNED),
+			     item_param),
+		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_na,
+					     target_addr)),
+	},
+	[ITEM_ICMP6_ND_OPT_SLA_ETH] = {
+		.name = "sla",
+		.help = "match source link-layer address over neighbor solicitation",
+		.priv = PRIV_ITEM(ICMP6_ND_OPT_SLA_ETH,
+			  sizeof(struct rte_flow_item_icmp6_nd_opt_sla_eth)),
+		.next = NEXT(item_icmp6_nd_opt_sla_eth),
+		.call = parse_vc,
+	},
+	[ITEM_ICMP6_ND_OPT_SLA_ETH_TGT_ADDR] = {
+		.name = "tgt_addr",
+		.help = "target address of neighbor solicitation",
+		.next = NEXT(item_icmp6_nd_opt_sla_eth, NEXT_ENTRY(UNSIGNED),
+			     item_param),
+		.args = ARGS(ARGS_ENTRY_HTON(
+			     struct rte_flow_item_icmp6_nd_opt_sla_eth,
+			     target_addr)),
+	},
+	[ITEM_ICMP6_ND_OPT_SLA_ETH_SLL_ADDR] = {
+		.name = "sll_addr",
+		.help = "source link-layer address over neighbor solicitation",
+		.next = NEXT(item_icmp6_nd_opt_sla_eth, NEXT_ENTRY(UNSIGNED),
+			     item_param),
+		.args = ARGS(ARGS_ENTRY_HTON(
+			     struct rte_flow_item_icmp6_nd_opt_sla_eth,
+			     sll_addr)),
+	},
+	[ITEM_ICMP6_ND_OPT_TLA_ETH] = {
+		.name = "tla",
+		.help = "match target link-layer address over neighbor advertisement",
+		.priv = PRIV_ITEM(ICMP6_ND_OPT_TLA_ETH,
+			  sizeof(struct rte_flow_item_icmp6_nd_opt_tla_eth)),
+		.next = NEXT(item_icmp6_nd_opt_tla_eth),
+		.call = parse_vc,
+	},
+	[ITEM_ICMP6_ND_OPT_TLA_ETH_TGT_ADDR] = {
+		.name = "tgt_addr",
+		.help = "target address of neighbor advertisement",
+		.next = NEXT(item_icmp6_nd_opt_tla_eth, NEXT_ENTRY(UNSIGNED),
+			     item_param),
+		.args = ARGS(ARGS_ENTRY_HTON(
+			     struct rte_flow_item_icmp6_nd_opt_tla_eth,
+			     target_addr)),
+	},
+	[ITEM_ICMP6_ND_OPT_TLA_ETH_TLL_ADDR] = {
+		.name = "tll_addr",
+		.help = "target link-layer address over neighbor advertisement",
+		.next = NEXT(item_icmp6_nd_opt_tla_eth, NEXT_ENTRY(UNSIGNED),
+			     item_param),
+		.args = ARGS(ARGS_ENTRY_HTON(
+			     struct rte_flow_item_icmp6_nd_opt_tla_eth,
+			     tll_addr)),
+	},
 
 	/* Validate/create actions. */
 	[ACTIONS] = {
diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
index ca14bb25d..27823d6d1 100644
--- a/app/test-pmd/config.c
+++ b/app/test-pmd/config.c
@@ -996,6 +996,15 @@ static const struct {
 	MK_FLOW_ITEM(GTPC, sizeof(struct rte_flow_item_gtp)),
 	MK_FLOW_ITEM(GTPU, sizeof(struct rte_flow_item_gtp)),
 	MK_FLOW_ITEM(GENEVE, sizeof(struct rte_flow_item_geneve)),
+	MK_FLOW_ITEM(ARP_IPV4, sizeof(struct rte_flow_item_arp_ipv4)),
+	MK_FLOW_ITEM(IPV6_EXT, sizeof(struct rte_flow_item_ipv6_ext)),
+	MK_FLOW_ITEM(ICMP6, sizeof(struct rte_flow_item_icmp6)),
+	MK_FLOW_ITEM(ICMP6_ND_NS, sizeof(struct rte_flow_item_icmp6_nd_ns)),
+	MK_FLOW_ITEM(ICMP6_ND_NA, sizeof(struct rte_flow_item_icmp6_nd_na)),
+	MK_FLOW_ITEM(ICMP6_ND_OPT_SLA_ETH,
+		     sizeof(struct rte_flow_item_icmp6_nd_opt_sla_eth)),
+	MK_FLOW_ITEM(ICMP6_ND_OPT_TLA_ETH,
+		     sizeof(struct rte_flow_item_icmp6_nd_opt_tla_eth)),
 };
 
 /** Compute storage space needed by item specification. */
diff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst
index 961943dda..cfa790417 100644
--- a/doc/guides/prog_guide/rte_flow.rst
+++ b/doc/guides/prog_guide/rte_flow.rst
@@ -992,6 +992,94 @@ Matches a GENEVE header.
 - ``rsvd1``: reserved, normally 0x00.
 - Default ``mask`` matches VNI only.
 
+Item: ``ARP_IPV4``
+^^^^^^^^^^^^^^^^^^
+
+Matches an IPv4 ARP header.
+
+- ``arp_hdr``: format of hardware address.
+- ``arp_pro``: format of protocol address.
+- ``arp_hln``: length of hardware address.
+- ``arp_pln``: length of protocol address.
+- ``arp_op``: ARP opcode.
+- ``sha``: sender hardware address.
+- ``sip``: sender IP address.
+- ``tha``: target hardware address.
+- ``tip``: target IP address.
+- Default ``mask`` only matches sha, sip, tha, tip.
+
+Item: ``IPV6_EXT``
+^^^^^^^^^^^^^^^^^^
+
+Matches an IPv6 Extension header with any type.
+
+- ``next_hdr``: protocol of next header.
+- Default ``mask`` matches protocol of next header.
+
+Item: ``ICMP6``
+^^^^^^^^^^^^^^^
+
+Matches an ICMPv6 header followed by any message body.
+
+- ``type``: ICMPv6 type.
+- ``code``: ICMPv6 code.
+- ``checksum``: ICMPv6 checksum.
+- Default ``mask`` matches type and code only.
+
+Item: ``ICMP6_ND_NS``
+^^^^^^^^^^^^^^^^^^^^^
+
+Matches an ICMPv6 header followed by network discovery neighbor solicitation,
+
+- ``type``: ICMPv6 type, normally 135.
+- ``code``: ICMPv6 code, normally 0.
+- ``checksum``: ICMPv6 checksum.
+- ``reserved``: reserved, normally 0x00.
+- ``tgt_addr``: target address of neighbor solicitation.
+- Default ``mask`` matches target address only.
+
+Item: ``ICMP6_ND_NA``
+^^^^^^^^^^^^^^^^^^^^^
+
+Matches an ICMPv6 header followed by network discovery neighbor advertisement,
+
+- ``type``: ICMPv6 type, normally 136.
+- ``code``: ICMPv6 code, normally 0.
+- ``checksum``: ICMPv6 checksum.
+- ``rso_reserved``: route flag (1b), solicited flag (1b), override flag (1b),
+  reserved (29b).
+- ``tgt_addr``: target address of neighbor advertisement.
+- Default ``mask`` matches target address only.
+
+Item: ``ICMP6_ND_OPT_SLA_ETH``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Matches an ICMPv6 header followed by network discovery neighbor solicitation
+that contains source Ethernet link-layer address option.
+
+- ``type``: ICMPv6 type, normally 135.
+- ``code``: ICMPv6 code, normally 0.
+- ``checksum``: ICMPv6 checksum.
+- ``reserved``: reserved, normally 0x00.
+- ``tgt_addr``: target address of neighbor solicitation.
+- ``sll_ADDR``: source Ethernet link-layer address.
+- Default ``mask`` matches target address and source link-layer address only.
+
+Item: ``ICMP6_ND_OPT_TLA_ETH``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Matches an ICMPv6 header followed by network discovery neighbor advertisement.
+that contains target Ethernet link-layer address option.
+
+- ``type``: ICMPv6 type, normally 136.
+- ``code``: ICMPv6 code, normally 0.
+- ``checksum``: ICMPv6 checksum.
+- ``rso_reserved``: route flag (1b), solicited flag (1b), override flag (1b),
+  reserved (29b).
+- ``tgt_addr``: target address of neighbor advertisement.
+- ``tll_ADDR``: target Ethernet link-layer address.
+- Default ``mask`` matches target address and target link-layer address only.
+
 Actions
 ~~~~~~~
 
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index a766ac795..d2d084bb2 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -3305,6 +3305,40 @@ This section lists supported pattern items and their attributes, if any.
   - ``vni {unsigned}``: virtual network identifier.
   - ``protocol {unsigned}``: protocol type.
 
+- ``arp``: match IPv4 arp header.
+
+  - ``sha``: sender hardware address.
+  - ``sip``: sender IP address.
+  - ``tha``: target hardware address.
+  - ``tip``: target IP address.
+
+- ``ext``: match IPv6 extend header.
+
+  - ``next {unsigned}``: protocol (next header).
+
+- ``icmp6``: match ICMPv6 header.
+
+  - ``type {unsigned}``: ICMPv6 packet type.
+  - ``code {unsigned}``: ICMPv6 packet code.
+
+- ``ns``: match neighbor solicitation over ICMPv6.
+
+  - ``tgt_addr {ipv6 address}``: target address of neighbor solicitation.
+
+- ``na``: match neighbor advertisement over ICMPv6.
+
+  - ``tgt_addr {ipv6 address}``: target address of neighbor advertisement.
+
+- ``sla``: match source link-layer address over neighbor solicitation.
+
+  - ``tgt_addr {ipv6 address}``: target address of neighbor solicitation.
+  - ``sll_addr {MAC-48}``: source link-layer address over neighbor solicitation.
+
+- ``tla``: match target link-layer address over neighbor advertisement.
+
+  - ``tgt_addr {ipv6 address}``: target address of neighbor advertisement.
+  - ``tll_addr {MAC-48}``: target link-layer address over neighbor advertisement.
+
 Actions list
 ^^^^^^^^^^^^
 
diff --git a/lib/librte_ether/rte_flow.h b/lib/librte_ether/rte_flow.h
index 56c733451..25581513d 100644
--- a/lib/librte_ether/rte_flow.h
+++ b/lib/librte_ether/rte_flow.h
@@ -323,6 +323,61 @@ enum rte_flow_item_type {
 	 * See struct rte_flow_item_geneve.
 	 */
 	RTE_FLOW_ITEM_TYPE_GENEVE,
+
+	/**
+	 * Matches an IPv4 ARP header.
+	 *
+	 * See struct rte_flow_item_arp_ipv4.
+	 */
+	RTE_FLOW_ITEM_TYPE_ARP_IPV4,
+
+	/**
+	 * Matches an IPv6 Extension header with any type.
+	 *
+	 * See struct rte_flow_item_ipv6_ext.
+	 */
+	RTE_FLOW_ITEM_TYPE_IPV6_EXT,
+
+	/**
+	 * Matches an ICMPv6 header followed by any message body.
+	 *
+	 * See struct rte_flow_item_icmp6.
+	 */
+	RTE_FLOW_ITEM_TYPE_ICMP6,
+
+	/**
+	 * Matches an ICMPv6 header followed by network discovery
+	 * neighbor solicitation.
+	 *
+	 * See struct rte_flow_item_icmp6_nd_ns.
+	 */
+	RTE_FLOW_ITEM_TYPE_ICMP6_ND_NS,
+
+	/**
+	 * Matches an ICMPv6 header followed by network discovery
+	 * neighbor advertisement.
+	 *
+	 * See struct rte_flow_item_icmp6_nd_na.
+	 */
+	RTE_FLOW_ITEM_TYPE_ICMP6_ND_NA,
+
+	/**
+	 * Matches an ICMPv6 header followed by network discovery neighbor
+	 * solicitation that contains source Ethernet link-layer address
+	 * option.
+	 *
+	 * See struct rte_flow_item_icmp6_nd_opt_sla_eth.
+	 */
+	RTE_FLOW_ITEM_TYPE_ICMP6_ND_OPT_SLA_ETH,
+
+	/**
+	 * Matches an ICMPv6 header followed by network discovery neighbor
+	 * advertisement that contains target Ethernet link-layer address
+	 * option.
+	 *
+	 * See struct rte_flow_item_icmp6_nd_opt_tla_eth.
+	 */
+	RTE_FLOW_ITEM_TYPE_ICMP6_ND_OPT_TLA_ETH,
 };
 
 /**
@@ -815,6 +870,186 @@ static const struct rte_flow_item_geneve rte_flow_item_geneve_mask = {
 #endif
 
 /**
+ * RTE_FLOW_ITEM_TYPE_ARP_IPV4
+ *
+ * Matches an IPv4 ARP header.
+ */
+struct rte_flow_item_arp_ipv4 {
+	rte_be16_t arp_hrd; /**< Format of hardware address. */
+	rte_be16_t arp_pro; /**< Format of protocol address. */
+	uint8_t arp_hln; /**< Length of hardware address. */
+	uint8_t arp_pln; /**< Length of protocol address. */
+	rte_be16_t arp_op; /**< ARP opcode */
+	struct ether_addr arp_sha; /**< Sender hardware address. */
+	rte_be32_t arp_sip; /**< Sender IP address. */
+	struct ether_addr arp_tha; /**< Target hardware address. */
+	rte_be32_t arp_tip; /**< Target IP address. */
+};
+
+/** Default mask for RTE_FLOW_ITEM_TYPE_ARP_IPV4. */
+#ifndef __cplusplus
+static const struct rte_flow_item_arp_ipv4 rte_flow_item_arp_ipv4_mask = {
+	.arp_sha = {
+		.addr_bytes = "\xff\xff\xff\xff\xff\xff",
+	},
+	.arp_sip = RTE_BE32(0xffffffff),
+	.arp_tha = {
+		.addr_bytes = "\xff\xff\xff\xff\xff\xff",
+	},
+	.arp_tip = RTE_BE32(0xffffffff),
+};
+#endif
+
+/**
+ * RTE_FLOW_ITEM_TYPE_IPV6_EXT
+ *
+ * Matches an IPv6 extension header with any type.
+ */
+struct rte_flow_item_ipv6_ext {
+	uint8_t next_hdr; /**< Protocol of next  header */
+};
+
+/** Default mask for RTE_FLOW_ITEM_TYPE_IPV6_EXT. */
+#ifndef __cplusplus
+static const
+struct rte_flow_item_ipv6_ext rte_flow_item_ipv6_ext_mask = {
+	.next_hdr = 0xff,
+};
+#endif
+
+/**
+ * RTE_FLOW_ITEM_TYPE_ICMP6
+ *
+ * Matches an ICMPv6 header followed by any message body.
+ */
+struct rte_flow_item_icmp6 {
+	uint8_t type; /**< ICMPv6 type. */
+	uint8_t code; /**< ICMPv6 code. */
+	uint16_t checksum; /**< ICMPv6 checksum. */
+};
+
+/** Default mask for RTE_FLOW_ITEM_TYPE_ICMP6. */
+#ifndef __cplusplus
+static const struct rte_flow_item_icmp6 rte_flow_item_icmp6_mask = {
+	.type = 0xff,
+	.code = 0xff,
+};
+#endif
+
+/**
+ * RTE_FLOW_ITEM_TYPE_ICMP6_ND_NS
+ *
+ * Matches an ICMP6 header followed by network discovery
+ * neighbor solicitation.
+ */
+struct rte_flow_item_icmp6_nd_ns {
+	uint8_t type; /**< ICMPv6 type, normally 135. */
+	uint8_t code; /**< ICMPv6 code, normally 0. */
+	rte_be16_t checksum; /**< ICMPv6 checksum. */
+	rte_be32_t reserved;
+	uint8_t target_addr[16]; /**< Target address. */
+};
+
+/** Default mask for RTE_FLOW_ITEM_TYPE_ICMP6_ND_NS. */
+#ifndef __cplusplus
+static const
+struct rte_flow_item_icmp6_nd_ns rte_flow_item_icmp6_nd_ns_mask = {
+	.target_addr =
+		"\xff\xff\xff\xff\xff\xff\xff\xff"
+		"\xff\xff\xff\xff\xff\xff\xff\xff",
+};
+#endif
+
+/**
+ * RTE_FLOW_ITEM_TYPE_ICMP6_ND_NA
+ *
+ * Matches an ICMPv6 header followed by network discovery
+ * neighbor advertisement.
+ */
+struct rte_flow_item_icmp6_nd_na {
+	uint8_t type; /**< ICMPv6 type, normally 136. */
+	uint8_t code; /**< ICMPv6 code, normally 0. */
+	rte_be16_t checksum; /**< ICMPv6 checksum. */
+	/**
+	 * Route flag (1b), solicited flag (1b), override flag (1b),
+	 * reserved (29b).
+	 */
+	rte_be32_t rso_reserved;
+	uint8_t target_addr[16]; /**< Target address. */
+};
+
+/** Default mask for RTE_FLOW_ITEM_TYPE_ICMP6_ND_NA. */
+#ifndef __cplusplus
+static const
+struct rte_flow_item_icmp6_nd_na rte_flow_item_icmp6_nd_na_mask = {
+	.target_addr =
+		"\xff\xff\xff\xff\xff\xff\xff\xff"
+		"\xff\xff\xff\xff\xff\xff\xff\xff",
+};
+#endif
+
+/**
+ * RTE_FLOW_ITEM_TYPE_ICMP6_ND_OPT_SLA_ETH
+ *
+ * Matches an ICMPv6 header followed by network discovery neighbor
+ * solicitation that contains source Ethernet link-layer address option.
+ */
+struct rte_flow_item_icmp6_nd_opt_sla_eth {
+	uint8_t type; /**< ICMPv6 type, normally 135. */
+	uint8_t code; /**< ICMPv6 code, normally 0. */
+	rte_be16_t checksum; /**< ICMPv6 checksum. */
+	rte_be32_t reserved;
+	uint8_t target_addr[16]; /**< Target address. */
+	struct ether_addr sll_addr; /**< Source Ethernet link-layer address. */
+};
+
+/** Default mask for RTE_FLOW_ITEM_TYPE_ICMP6_ND_OPT_SLA_ETH. */
+#ifndef __cplusplus
+static const struct rte_flow_item_icmp6_nd_opt_sla_eth
+	rte_flow_item_icmp6_nd_opt_sla_eth_mask = {
+	.target_addr =
+		"\xff\xff\xff\xff\xff\xff\xff\xff"
+		"\xff\xff\xff\xff\xff\xff\xff\xff",
+	.sll_addr = {
+		.addr_bytes = "\xff\xff\xff\xff\xff\xff",
+	}
+};
+#endif
+
+/**
+ * RTE_FLOW_ITEM_TYPE_ICMP6_ND_OPT_TLA_ETH
+ *
+ * Matches an ICMPv6 header followed by network discovery neighbor
+ * advertisement that contains target Ethernet link-layer address option.
+ */
+struct rte_flow_item_icmp6_nd_opt_tla_eth {
+	uint8_t type; /**< ICMPv6 type, normally 136. */
+	uint8_t code; /**< ICMPv6 code, normally 0. */
+	rte_be16_t checksum; /**< ICMPv6 checksum. */
+	/**
+	 * Route flag (1b), solicited flag (1b), override flag (1b),
+	 * reserved (29b).
+	 */
+	rte_be32_t rso_reserved;
+	uint8_t target_addr[16]; /**< Target address. */
+	struct ether_addr tll_addr; /**< Target Ethernet link-layer address. */
+
+};
+
+/** Default mask for RTE_FLOW_ITEM_TYPE_ICMP6_ND_OPT_TLA_ETH. */
+#ifndef __cplusplus
+static const struct rte_flow_item_icmp6_nd_opt_tla_eth
+	rte_flow_item_icmp6_nd_opt_tla_eth_mask = {
+	.target_addr =
+		"\xff\xff\xff\xff\xff\xff\xff\xff"
+		"\xff\xff\xff\xff\xff\xff\xff\xff",
+	.tll_addr = {
+		.addr_bytes = "\xff\xff\xff\xff\xff\xff",
+	}
+};
+#endif
+
+/**
  * Matching pattern item definition.
  *
  * A pattern is formed by stacking items starting from the lowest protocol
-- 
2.13.6

^ permalink raw reply	[flat|nested] 61+ messages in thread

* [dpdk-dev] [PATCH v4 2/3] ethdev: add TTL change actions in flow API
  2018-04-23  6:36 ` [dpdk-dev] [PATCH v4 0/3] rte_flow extension for vSwitch acceleration Qi Zhang
  2018-04-23  6:36   ` [dpdk-dev] [PATCH v4 1/3] ethdev: add more protocol support in flow API Qi Zhang
@ 2018-04-23  6:36   ` Qi Zhang
  2018-04-23  6:36   ` [dpdk-dev] [PATCH v4 3/3] ethdev: add VLAN and MPLS " Qi Zhang
  2018-04-24 15:58   ` [dpdk-dev] [PATCH v5 0/3] rte_flow extension for vSwitch acceleration Adrien Mazarguil
  3 siblings, 0 replies; 61+ messages in thread
From: Qi Zhang @ 2018-04-23  6:36 UTC (permalink / raw)
  To: adrien.mazarguil
  Cc: dev, declan.doherty, sugesh.chandran, michael.j.glynn, yu.y.liu,
	konstantin.ananyev, bruce.richardson, Qi Zhang

Add OpenFlow complied TTL change actions.

RTE_FLOW_ACTIOn_OF_MPLS_TTL_SET - set MPLS TTL.
RTE_FLOW_ACTION_OF_MLPS_TTL_DEC - decrement MPLS TTL.
RTE_FLOW_ACTIOn_OF_IP_TTL_SET - set IP TTL.
RTE_FLOW_ACTION_OF_IP_TTL_DEC - decrement IP TTL.
RTE_FLOW_ACTION_OF_TTL_COPY_OUT - copy TTL outwards.
RTE_FLOW_ACTION_OF_TTL_COPY_IN - copy TTL inwards.

Suggested-by: Adrien Mazarguil <adrien.mazarguil@6wind.com>
Signed-off-by: Qi Zhang <qi.z.zhang@intel.com>
---
 app/test-pmd/cmdline_flow.c                 |  86 ++++++++++++++++++++++++
 doc/guides/prog_guide/rte_flow.rst          | 100 ++++++++++++++++++++++++++++
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  16 +++++
 lib/librte_ether/rte_flow.h                 |  78 +++++++++++++++++++++-
 4 files changed, 279 insertions(+), 1 deletion(-)

diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c
index a9e4f56ba..18a7b4734 100644
--- a/app/test-pmd/cmdline_flow.c
+++ b/app/test-pmd/cmdline_flow.c
@@ -195,6 +195,14 @@ enum index {
 	ACTION_VF_ID,
 	ACTION_METER,
 	ACTION_METER_ID,
+	ACTION_OF_MPLS_TTL_SET,
+	ACTION_OF_MPLS_TTL_SET_TTL,
+	ACTION_OF_MPLS_TTL_DEC,
+	ACTION_OF_IP_TTL_SET,
+	ACTION_OF_IP_TTL_SET_TTL,
+	ACTION_OF_IP_TTL_DEC,
+	ACTION_OF_TTL_COPY_OUT,
+	ACTION_OF_TTL_COPY_IN,
 };
 
 /** Size of pattern[] field in struct rte_flow_item_raw. */
@@ -668,6 +676,12 @@ static const enum index next_action[] = {
 	ACTION_PF,
 	ACTION_VF,
 	ACTION_METER,
+	ACTION_OF_MPLS_TTL_SET,
+	ACTION_OF_MPLS_TTL_DEC,
+	ACTION_OF_IP_TTL_SET,
+	ACTION_OF_IP_TTL_DEC,
+	ACTION_OF_TTL_COPY_OUT,
+	ACTION_OF_TTL_COPY_IN,
 	ZERO,
 };
 
@@ -708,6 +722,18 @@ static const enum index action_meter[] = {
 	ZERO,
 };
 
+static const enum index action_of_mpls_ttl_set[] = {
+	ACTION_OF_MPLS_TTL_SET_TTL,
+	ACTION_NEXT,
+	ZERO,
+};
+
+static const enum index action_of_ip_ttl_set[] = {
+	ACTION_OF_IP_TTL_SET_TTL,
+	ACTION_NEXT,
+	ZERO,
+};
+
 static int parse_init(struct context *, const struct token *,
 		      const char *, unsigned int,
 		      void *, unsigned int);
@@ -1857,6 +1883,66 @@ static const struct token token_list[] = {
 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter, mtr_id)),
 		.call = parse_vc_conf,
 	},
+	[ACTION_OF_MPLS_TTL_SET] = {
+		.name = "of_mpls_ttl_set",
+		.help = "set MPLS TTL",
+		.priv = PRIV_ACTION(OF_MPLS_TTL_SET,
+			sizeof(struct rte_flow_action_of_mpls_ttl_set)),
+		.next = NEXT(action_of_mpls_ttl_set),
+		.call = parse_vc,
+	},
+	[ACTION_OF_MPLS_TTL_SET_TTL] = {
+		.name = "ttl",
+		.help = "new TTL to set",
+		.next = NEXT(action_of_mpls_ttl_set, NEXT_ENTRY(UNSIGNED)),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_of_mpls_ttl_set,
+					ttl)),
+		.call = parse_vc_conf,
+	},
+	[ACTION_OF_MPLS_TTL_DEC] = {
+		.name = "of_mpls_ttl_dec",
+		.help = "decrement MPLS TTL",
+		.priv = PRIV_ACTION(OF_MPLS_TTL_DEC, 0),
+		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
+		.call = parse_vc,
+	},
+	[ACTION_OF_IP_TTL_SET] = {
+		.name = "of_ip_ttl_set",
+		.help = "set IP TTL",
+		.priv = PRIV_ACTION(OF_IP_TTL_SET,
+			sizeof(struct rte_flow_action_of_ip_ttl_set)),
+		.next = NEXT(action_of_ip_ttl_set),
+		.call = parse_vc,
+	},
+	[ACTION_OF_IP_TTL_SET_TTL] = {
+		.name = "ttl",
+		.help = "new TTL to set",
+		.next = NEXT(action_of_ip_ttl_set, NEXT_ENTRY(UNSIGNED)),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_of_ip_ttl_set,
+					ttl)),
+		.call = parse_vc_conf,
+	},
+	[ACTION_OF_IP_TTL_DEC] = {
+		.name = "of_ip_ttl_dec",
+		.help = "decrement IPv4 TTL or IPv6 Hop Limit",
+		.priv = PRIV_ACTION(OF_IP_TTL_DEC, 0),
+		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
+		.call = parse_vc,
+	},
+	[ACTION_OF_TTL_COPY_OUT] = {
+		.name = "of_ttl_copy_out",
+		.help = "copy TTL outwards",
+		.priv = PRIV_ACTION(OF_TTL_COPY_OUT, 0),
+		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
+		.call = parse_vc,
+	},
+	[ACTION_OF_TTL_COPY_IN] = {
+		.name = "of_ttl_copy_in",
+		.help = "copy TTL inwards",
+		.priv = PRIV_ACTION(OF_TTL_COPY_IN, 0),
+		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
+		.call = parse_vc,
+	},
 };
 
 /** Remove and return last entry from argument stack. */
diff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst
index cfa790417..7b07fe791 100644
--- a/doc/guides/prog_guide/rte_flow.rst
+++ b/doc/guides/prog_guide/rte_flow.rst
@@ -1574,6 +1574,106 @@ fields in the pattern items.
    | 1     | END      |
    +-------+----------+
 
+Action: ``OF_MPLS_TTL_SET``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Replace MPLS TTL, only applies to packets that contain MPLS
+headers. Comply with OpenFlow action "OFPAT_SET_MPLS_TTL".
+
+.. _table_rte_flow_action_of_mpls_ttl_set:
+
+.. table:: OF_MPLS_TTL_SET
+
+   +---------+---------------------+
+   | Field   | Value               |
+   +=========+=====================+
+   | ``ttl`` | new MPLS TTL to set |
+   +---------+---------------------+
+
+Action: ``OF_MPLS_TTL_DEC``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Decrement MPLS TTL, only applies to packets that contain MPLS
+headers, Comply with OpenFlow action "OFPAT_DEC_MPLS_TTL".
+
+.. _table_rte_flow_action_of_mpls_ttl_dec:
+
+.. table:: OF_MPLS_TTL_DEC
+
+   +---------------+
+   | Field         |
+   +===============+
+   | no properties |
+   +---------------+
+
+Action: ``OF_IP_TTL_SET``
+^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Replace IPv4 TTL or IPv6 Hop Limit field and update the IP checksum,
+only applies to packets that contain MPLS headers. Comply with OpenFlow
+action "OFPAT_DEC_NW_TTL".
+
+.. _table_rte_flow_action_of_ip_ttl_set:
+
+.. table:: OF_IP_TTL_SET
+
+   +---------+---------------------------------------+
+   | Field   | Value                                 |
+   +=========+=======================================+
+   | ``ttl`` | new IPv4 TTL or IPv6 Hot Limit to set |
+   +---------+---------------------------------------+
+
+Action: ``OF_IP_TTL_DEC``
+^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Decrement IPv4 TTL or IPv6 Hop Limit field and update the IP checksum,
+only applies to packets that contain MPLS headers. Comply with OpenFlow
+action "OFPAT_DEC_NW_TTL".
+
+.. _table_rte_flow_action_of_ip_ttl_dec:
+
+.. table:: OF_IP_TTL_DEC
+
+   +---------------+
+   | Field         |
+   +===============+
+   | no properties |
+   +---------------+
+
+Action: ``OF_TTL_COPY_OUT``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Copy the TTL from next-to-outermost to outermost header with TTL, copy can
+be IP to IP, MPLS to MPLS or IP to MPLS, only applies packets that contain
+required MPLS or IP headers. Comply with OpenFlow action "OFPAT_COPY_TTL_OUT".
+
+.. _table_rte_flow_action_of_ttl_copy_out:
+
+.. table:: OF_TTL_COPY_OUT
+
+   +---------------+
+   | Field         |
+   +===============+
+   | no properties |
+   +---------------+
+
+Action: ``OF_TTL_COPY_IN``
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Copy the TTL from outermost to next-to-outermost header with TTL, copy can
+be IP to IP, MPLS to MPLS or MPLS to IP, only applies packets that contain
+required MPLS or IP headers. Comply with OpenFlow action "OFPAT_COPY_TTL_IN".
+
+.. _table_rte_flow_action_of_ttl_copy_in:
+
+.. table:: OF_TTL_COPY_IN
+
+   +---------------+
+   | Field         |
+   +===============+
+   | no properties |
+   +---------------+
+
 Negative types
 ~~~~~~~~~~~~~~
 
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index d2d084bb2..c1bc53741 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -3449,6 +3449,22 @@ This section lists supported actions and their attributes, if any.
   - ``original {boolean}``: use original VF ID if possible.
   - ``id {unsigned}``: VF ID to redirect packets to.
 
+- ``of_mpls_ttl_set``: set MPLS TTL (note: OpenFlow comply).
+
+  - ``ttl``: new TTL to set.
+
+- ``of_mpls_ttl_dec``: decrement MPLS TTL (note: OpenFlow comply).
+
+- ``of_ip_ttl_set``: set IPv4 TTL or IPv6 Hot Limit (note: OpenFlow comply).
+
+  - ``ttl``: new TTL to set.
+
+- ``of_ip_ttl_dec``: decrement IPv4 TTL or IPv6 Hot Limit (note: OpenFlow comply).
+
+- ``of_ttl_copy_out``: copy TTL outwards (note: OpenFlow comply).
+
+- ``of_ttl_copy_in``: copy TTL inwards (note: OpenFlow comply).
+
 Destroying flow rules
 ~~~~~~~~~~~~~~~~~~~~~
 
diff --git a/lib/librte_ether/rte_flow.h b/lib/librte_ether/rte_flow.h
index 25581513d..72819abd2 100644
--- a/lib/librte_ether/rte_flow.h
+++ b/lib/librte_ether/rte_flow.h
@@ -1245,7 +1245,62 @@ enum rte_flow_action_type {
 	 *
 	 * See struct rte_flow_action_security.
 	 */
-	RTE_FLOW_ACTION_TYPE_SECURITY
+	RTE_FLOW_ACTION_TYPE_SECURITY,
+
+	/**
+	 * Replace MPLS TTL, only applies to packets that contain
+	 * MPLS header. Comply with OpenFlow action "OFPAT_SET_MPLS_TTL".
+	 *
+	 * See struct rte_flow_action_of_mpls_ttl_set.
+	 */
+	RTE_FLOW_ACTION_TYPE_OF_MPLS_TTL_SET,
+
+
+	/**
+	 * Decrement MPLS TTL, only applies to packets that contain
+	 * MPLS header. Comply with OpenFlow action "OFPAT_DEC_MPLS_TTL".
+	 *
+	 * No associated configuration structure.
+	 */
+	RTE_FLOW_ACTION_TYPE_OF_MPLS_TTL_DEC,
+
+	/**
+	 * Replace IPv4 TTL or IPv6 Hop Limit field and update the IP
+	 * checksum, only applies to packets that contain IPv4 or IPv6
+	 * header. Comply with OpenFlow action "OFPAT_SET_NW_TTL".
+	 *
+	 * See struct rte_flow_action_of_ip_ttl_set.
+	 */
+	RTE_FLOW_ACTION_TYPE_OF_IP_TTL_SET,
+
+	/**
+	 * Decrement IPv4 TTL or IPv6 Hop Limit field and update the IP
+	 * checksum, only applies to packets that contain IPv4 or IPv6
+	 * header. Comply with OpenFlow action "OFPAT_DEC_NW_TTL".
+	 *
+	 * No associated configuration structure.
+	 */
+	RTE_FLOW_ACTION_TYPE_OF_IP_TTL_DEC,
+
+	/**
+	 * Copy the TTL from next-to-outermost to outermost header with TTL,
+	 * copy can be IP to IP, MPLS to MPLS or IP to MPLS, only applies
+	 * packets that contain required protocol headers. Comply with OpenFlow
+	 * action "OFPAT_COPY_TTL_OUT".
+	 *
+	 * No associated configuration structure.
+	 */
+	RTE_FLOW_ACTION_TYPE_OF_TTL_COPY_OUT,
+
+	/**
+	 * Copy the TTL from outermost to next-to-outermost header with TTL,
+	 * copy can be IP to IP, MPLS to MPLS or MPLS to IP, only applies
+	 * packets that contain required protocol headers. Comply with OpenFlow
+	 * action "OFPAT_COPY_TTL_IN".
+	 *
+	 * No associated configuration structure.
+	 */
+	RTE_FLOW_ACTION_TYPE_OF_TTL_COPY_IN,
 };
 
 /**
@@ -1384,6 +1439,27 @@ struct rte_flow_action_security {
 };
 
 /**
+ * RTE_FLOW_ACTION_TYPE_OF_MPLS_TTL_SET
+ *
+ * Replace MPLS TTL, only applies to packets that contain MPLS header.
+ * Comply with OpenFlow action "OFPAT_SET_MPLS_TTL".
+ */
+struct rte_flow_action_of_mpls_ttl_set {
+	uint8_t ttl; /**< New TTL to set */
+};
+
+/**
+ * RTE_FLOW_ACTION_TYPE_OF_IP_TTL_SET
+ *
+ * Replace IPv4 TTL or IPv6 Hop Limit field and update the IP
+ * checksum, only applies to packets that contain IPv4 or IPv6
+ * header. Comply with OpenFlow action "OFPAT_SET_NW_TTL".
+ */
+struct rte_flow_action_of_ip_ttl_set {
+	uint8_t ttl; /**< New TTL or Hop Limit to set */
+};
+
+/**
  * Definition of a single action.
  *
  * A list of actions is terminated by a END action.
-- 
2.13.6

^ permalink raw reply	[flat|nested] 61+ messages in thread

* [dpdk-dev] [PATCH v4 3/3] ethdev: add VLAN and MPLS actions in flow API
  2018-04-23  6:36 ` [dpdk-dev] [PATCH v4 0/3] rte_flow extension for vSwitch acceleration Qi Zhang
  2018-04-23  6:36   ` [dpdk-dev] [PATCH v4 1/3] ethdev: add more protocol support in flow API Qi Zhang
  2018-04-23  6:36   ` [dpdk-dev] [PATCH v4 2/3] ethdev: add TTL change actions " Qi Zhang
@ 2018-04-23  6:36   ` Qi Zhang
  2018-04-24 15:58   ` [dpdk-dev] [PATCH v5 0/3] rte_flow extension for vSwitch acceleration Adrien Mazarguil
  3 siblings, 0 replies; 61+ messages in thread
From: Qi Zhang @ 2018-04-23  6:36 UTC (permalink / raw)
  To: adrien.mazarguil
  Cc: dev, declan.doherty, sugesh.chandran, michael.j.glynn, yu.y.liu,
	konstantin.ananyev, bruce.richardson, Qi Zhang

Add Openflow complied VLAN and MPLS actions.

RTE_FLOW_ACTION_OF_VLAN_POP - pop a VLAN header.
RTE_FLOW_ACTION_OF_VLAN_PUSH - push a VLAN header.
RTE_FLOW_ACTION_OF_VLAN_VID_SET - set VLAN id.
RTE_FLOW_ACTION_OF_VLAN_PCP_SET - set VLAN priority.
RTE_FLOW_ACTION_OF_MPLS_POP - pop a MPLS header.
RTE_FLOW_ACTION_OF_MPLS_PUSH - push a MPLS header.

Suggested-by: Adrien Mazarguil <adrien.mazarguil@6wind.com>
Signed-off-by: Qi Zhang <qi.z.zhang@intel.com>
---
 app/test-pmd/cmdline_flow.c                 | 134 ++++++++++++++++++++++++++++
 doc/guides/prog_guide/rte_flow.rst          | 103 +++++++++++++++++++++
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  22 +++++
 lib/librte_ether/rte_flow.h                 | 119 ++++++++++++++++++++++++
 4 files changed, 378 insertions(+)

diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c
index 18a7b4734..8730c80e5 100644
--- a/app/test-pmd/cmdline_flow.c
+++ b/app/test-pmd/cmdline_flow.c
@@ -203,6 +203,17 @@ enum index {
 	ACTION_OF_IP_TTL_DEC,
 	ACTION_OF_TTL_COPY_OUT,
 	ACTION_OF_TTL_COPY_IN,
+	ACTION_OF_VLAN_POP,
+	ACTION_OF_VLAN_PUSH,
+	ACTION_OF_VLAN_PUSH_TYPE,
+	ACTION_OF_VLAN_VID_SET,
+	ACTION_OF_VLAN_VID_SET_VID,
+	ACTION_OF_VLAN_PCP_SET,
+	ACTION_OF_VLAN_PCP_SET_PCP,
+	ACTION_OF_MPLS_POP,
+	ACTION_OF_MPLS_POP_TYPE,
+	ACTION_OF_MPLS_PUSH,
+	ACTION_OF_MPLS_PUSH_TYPE,
 };
 
 /** Size of pattern[] field in struct rte_flow_item_raw. */
@@ -682,6 +693,12 @@ static const enum index next_action[] = {
 	ACTION_OF_IP_TTL_DEC,
 	ACTION_OF_TTL_COPY_OUT,
 	ACTION_OF_TTL_COPY_IN,
+	ACTION_OF_VLAN_POP,
+	ACTION_OF_VLAN_PUSH,
+	ACTION_OF_VLAN_VID_SET,
+	ACTION_OF_VLAN_PCP_SET,
+	ACTION_OF_MPLS_POP,
+	ACTION_OF_MPLS_PUSH,
 	ZERO,
 };
 
@@ -734,6 +751,36 @@ static const enum index action_of_ip_ttl_set[] = {
 	ZERO,
 };
 
+static const enum index action_of_vlan_push[] = {
+	ACTION_OF_VLAN_PUSH_TYPE,
+	ACTION_NEXT,
+	ZERO,
+};
+
+static const enum index action_of_vlan_vid_set[] = {
+	ACTION_OF_VLAN_VID_SET_VID,
+	ACTION_NEXT,
+	ZERO,
+};
+
+static const enum index action_of_vlan_pcp_set[] = {
+	ACTION_OF_VLAN_PCP_SET_PCP,
+	ACTION_NEXT,
+	ZERO,
+};
+
+static const enum index action_of_mpls_pop[] = {
+	ACTION_OF_MPLS_POP_TYPE,
+	ACTION_NEXT,
+	ZERO,
+};
+
+static const enum index action_of_mpls_push[] = {
+	ACTION_OF_MPLS_PUSH_TYPE,
+	ACTION_NEXT,
+	ZERO,
+};
+
 static int parse_init(struct context *, const struct token *,
 		      const char *, unsigned int,
 		      void *, unsigned int);
@@ -1943,6 +1990,93 @@ static const struct token token_list[] = {
 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
 		.call = parse_vc,
 	},
+	[ACTION_OF_VLAN_POP] = {
+		.name = "of_vlan_pop",
+		.help = "pop the outermost VLAN header.",
+		.priv = PRIV_ACTION(OF_VLAN_POP, 0),
+		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
+		.call = parse_vc,
+	},
+	[ACTION_OF_VLAN_PUSH] = {
+		.name = "of_vlan_push",
+		.help = "push new VLAN header onto the packet",
+		.priv = PRIV_ACTION(OF_VLAN_PUSH,
+				sizeof(struct rte_flow_action_of_vlan_push)),
+		.next = NEXT(action_of_vlan_push),
+		.call = parse_vc,
+	},
+	[ACTION_OF_VLAN_PUSH_TYPE] = {
+		.name = "type",
+		.help = "EtherType of VLAN header",
+		.next = NEXT(action_of_vlan_push, NEXT_ENTRY(UNSIGNED)),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_of_vlan_push,
+					ether_type)),
+		.call = parse_vc,
+	},
+	[ACTION_OF_VLAN_VID_SET] = {
+		.name = "of_vlan_vid_set",
+		.help = "set VLAN id of an exist or new pushed VLAN header",
+		.priv = PRIV_ACTION(OF_VLAN_VID_SET,
+				sizeof(struct rte_flow_action_of_vlan_vid_set)),
+		.next = NEXT(action_of_vlan_vid_set),
+		.call = parse_vc,
+	},
+	[ACTION_OF_VLAN_VID_SET_VID] = {
+		.name = "vid",
+		.help = "VLAN id",
+		.next = NEXT(action_of_vlan_vid_set, NEXT_ENTRY(UNSIGNED)),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_of_vlan_vid_set,
+					vid)),
+		.call = parse_vc,
+	},
+	[ACTION_OF_VLAN_PCP_SET] = {
+		.name = "of_vlan_pcp_set",
+		.help = "set priority of an exist or new pushed VLAN header",
+		.priv = PRIV_ACTION(OF_VLAN_PCP_SET,
+				sizeof(struct rte_flow_action_of_vlan_pcp_set)),
+		.next = NEXT(action_of_vlan_pcp_set),
+		.call = parse_vc,
+	},
+	[ACTION_OF_VLAN_PCP_SET_PCP] = {
+		.name = "pcp",
+		.help = "VLAN priority",
+		.next = NEXT(action_of_vlan_pcp_set, NEXT_ENTRY(UNSIGNED)),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_of_vlan_pcp_set,
+					pcp)),
+		.call = parse_vc,
+	},
+	[ACTION_OF_MPLS_POP] = {
+		.name = "of_mpls_pop",
+		.help = "pop the outermost MPLS header",
+		.priv = PRIV_ACTION(OF_MPLS_POP,
+				sizeof(struct rte_flow_action_of_mpls_pop)),
+		.next = NEXT(action_of_mpls_pop),
+		.call = parse_vc,
+	},
+	[ACTION_OF_MPLS_POP_TYPE] = {
+		.name = "type",
+		.help = "EtherType of MPLS header",
+		.next = NEXT(action_of_mpls_pop, NEXT_ENTRY(UNSIGNED)),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_of_mpls_pop,
+					ether_type)),
+		.call = parse_vc,
+	},
+	[ACTION_OF_MPLS_PUSH] = {
+		.name = "mpls_push",
+		.help = "push new MPLS header onto the packet",
+		.priv = PRIV_ACTION(OF_MPLS_PUSH,
+				sizeof(struct rte_flow_action_of_mpls_push)),
+		.next = NEXT(action_of_mpls_push),
+		.call = parse_vc,
+	},
+	[ACTION_OF_MPLS_PUSH_TYPE] = {
+		.name = "type",
+		.help = "EtherType of MPLS header",
+		.next = NEXT(action_of_mpls_push, NEXT_ENTRY(UNSIGNED)),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_of_mpls_push,
+					ether_type)),
+		.call = parse_vc,
+	},
 };
 
 /** Remove and return last entry from argument stack. */
diff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst
index 7b07fe791..f8387d4e8 100644
--- a/doc/guides/prog_guide/rte_flow.rst
+++ b/doc/guides/prog_guide/rte_flow.rst
@@ -1674,6 +1674,109 @@ required MPLS or IP headers. Comply with OpenFlow action "OFPAT_COPY_TTL_IN".
    | no properties |
    +---------------+
 
+Action: ``OF_VLAN_POP``
+^^^^^^^^^^^^^^^^^^^^^^^
+
+Pop the outer-most VLAN header from the packet. Comply with OpenFlow action
+"OFPAT_POP_VLAN".
+
+.. _table_rte_flow_action_of_vlan_pop:
+
+.. table:: OF_VLAN_POP
+
+   +---------------+
+   | Field         |
+   +===============+
+   | no properties |
+   +---------------+
+
+Action: ``OF_VLAN_PUSH``
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+Push a new VLAN header onto the packet, EtherType 0x8100 or 0x88a8 should
+be used. The value of VLAN ID and VLAN priority for the new header is copied
+from an exist VLAN header in the packet, they will be set to 0 if no such
+VLAN header exist. Comply with OpenFlow action "OFPAT_PUSH_VLAN".
+
+.. _table_rte_flow_action_of_vlan_push:
+
+.. table:: OF_VLAN_PUSH
+
+   +----------------+------------------------+
+   | Field          | Value                  |
+   +================+========================+
+   | ``ether_type`` | EtherType for VLAN tag |
+   +----------------+------------------------+
+
+Action: ``OF_VLAN_VID_SET``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Set VLAN id of an exist VLAN header or a new pushed VLAN header
+(when follow action RTE_FLOW_ACTION_TYPE_OF_VLAN_PUSH). Comply with
+OpenFlow action "OFPAT_SET_VLAN_VID".
+
+.. _table_rte_flow_action_of_vlan_vid_set:
+
+.. table:: OF_VLAN_VID_SET
+
+   +---------+----------------+
+   | Field   | Value          |
+   +=========+================+
+   | ``vid`` | VLAN id to set |
+   +---------+----------------+
+
+Action: ``OF_VLAN_PCP_SET``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Set 3-bit priority of an exist VLAN header or a new pushed VLAN header
+(when follow action RTE_FLOW_ACTION_TYPE_OF_VLAN_PUSH). Comply with
+OpenFlow action "OFPAT_SET_VLAN_PCP".
+
+.. _table_rte_flow_action_of_vlan_pcp_set:
+
+.. table:: OF_VLAN_PCP_SET
+
+   +---------+-----------------+
+   | Field   | Value           |
+   +=========+=================+
+   | ``pcp`` | priority to set |
+   +---------+-----------------+
+
+Action: ``OF_MPLS_POP``
+^^^^^^^^^^^^^^^^^^^^^^^
+
+Pop the outer-most MPLS header from the packet, EtherType is required for
+the resulting packet if it is not the last MPLS header be popped, EtherType
+must be 0x8847 or 0x8848. Comply with OpenFlow action "OFPAT_POP_MPLS".
+
+.. _table_rte_flow_action_of_mpls_pop:
+
+.. table:: OF_MPLS_POP
+
+   +----------------+---------------------------+
+   | Field          | Value                     |
+   +================+===========================+
+   | ``ether_type`` | EtherType for MPLS header |
+   +----------------+---------------------------+
+
+Action: ``OF_MPLS_PUSH``
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+Push a new MPLS header onto the packet, EtherType 0x8847 or 0x8848 should
+be used. The value of MPLS label and traffic class is copied from exist
+outermost MPLS header, and TTL is copied from exist outermost MPLS or IP
+header, they will be set to 0 if exist packet does not contain required
+header. Comply with OpenFlow action "OFPAT_PUSH_MPLS".
+
+.. _table_rte_flow_action_of_mpls_push:
+
+.. table:: OF_MPLS_PUSH
+
+   +----------------+---------------------------+
+   | Field          | Value                     |
+   +================+===========================+
+   | ``ether_type`` | EtherType for MPLS header |
+   +----------------+---------------------------+
+
 Negative types
 ~~~~~~~~~~~~~~
 
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index c1bc53741..df04bc59f 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -3465,6 +3465,28 @@ This section lists supported actions and their attributes, if any.
 
 - ``of_ttl_copy_in``: copy TTL inwards (note: OpenFlow comply).
 
+- ``of_vlan_pop``: pop the outermost VLAN header (note: OpenFlow comply).
+
+- ``of_vlan_push``: push new VLAN header onto the packet (note: OpenFlow comply).
+
+  - ``type``: Ethertype of the VLAN header.
+
+- ``of_vlan_vid_set``: set VLAN id of a VLAN header (note: OpenFlow comply).
+
+  - ``vid``: VLAN id to set.
+
+- ``of_vlan_pcp_set``: set priority of a VLAN header (note: OpenFlow comply).
+
+  - ``pcp``: priority to set.
+
+- ``of_mpls_pop``: pop the outermost MPLS header (note: OpenFlow comply).
+
+  - ``type``: Ethertype of the MPLS header.
+
+- ``of_mpls_push``: push new MPLS header onto the packet (note: OpenFlow comply).
+
+  - ``type``: Ethertype of the MPLS header.
+
 Destroying flow rules
 ~~~~~~~~~~~~~~~~~~~~~
 
diff --git a/lib/librte_ether/rte_flow.h b/lib/librte_ether/rte_flow.h
index 72819abd2..b13913816 100644
--- a/lib/librte_ether/rte_flow.h
+++ b/lib/librte_ether/rte_flow.h
@@ -1301,6 +1301,65 @@ enum rte_flow_action_type {
 	 * No associated configuration structure.
 	 */
 	RTE_FLOW_ACTION_TYPE_OF_TTL_COPY_IN,
+
+	/**
+	 * Pop the outer-most VLAN header from the packet. Comply with OpenFlow
+	 * action "OFPAT_POP_VLAN".
+	 *
+	 * No associated configuration structure.
+	 */
+	RTE_FLOW_ACTION_TYPE_OF_VLAN_POP,
+
+	/**
+	 * Push a new VLAN header onto the packet, EtherType 0x8100 or 0x88a8
+	 * should be used. The value of VLAN ID and VLAN priority for the new
+	 * header is copied from an exist VLAN header in the packet, they will
+	 * be set to 0 if no such VLAN header exist. Comply with OpenFlow action
+	 * "OFPAT_PUSH_VLAN".
+	 *
+	 * See struct rte_flow_action_of_vlan_push.
+	 */
+	RTE_FLOW_ACTION_TYPE_OF_VLAN_PUSH,
+
+	/**
+	 * Set VLAN id of an exist VLAN header or a new pushed VLAN header
+	 * (when follow action RTE_FLOW_ACTION_TYPE_OF_VLAN_PUSH). Comply with
+	 * OpenFlow action "OFPAT_SET_VLAN_VID".
+	 *
+	 * See struct rte_flow_action_of_vlan_vid_set.
+	 */
+	RTE_FLOW_ACTION_TYPE_OF_VLAN_VID_SET,
+
+	/**
+	 * Set 3-bit priority of an exist VLAN header or a new pushed VLAN
+	 * header (when follow action RTE_FLOW_ACTION_TYPE_OF_VLAN_PUSH).
+	 * Comply with OpenFlow action "OFPAT_SET_VLAN_PCP".
+	 *
+	 * See struct rte_flow_action_of_vlan_pcp_set.
+	 */
+	RTE_FLOW_ACTION_TYPE_OF_VLAN_PCP_SET,
+
+	/**
+	 * Pop the outer-most MPLS header from the packet, EtherType is required
+	 * for the resulting packet if it is not the last MPLS header be popped,
+	 * EtherType must be 0x8847 or 0x8848. Comply with OpenFlow action
+	 * "OFPAT_POP_MPLS".
+	 *
+	 * See struct rte_flow_action_of_mpls_pop.
+	 */
+	RTE_FLOW_ACTION_TYPE_OF_MPLS_POP,
+
+	/**
+	 * Push a new MPLS header onto the packet, EtherType 0x8847 or 0x8848
+	 * should be used. The value of MPLS label and traffic class is copied
+	 * from exist outermost MPLS header, and TTL is copied from exist
+	 * outermost MPLS or IP header, they will be set to 0 if exist packet
+	 * does not contain required header. Comply with OpenFlow action
+	 * "OFPAT_PUSH_MPLS".
+	 *
+	 * See struct rte_flow_action_of_mpls_push.
+	 */
+	RTE_FLOW_ACTION_TYPE_OF_MPLS_PUSH,
 };
 
 /**
@@ -1460,6 +1519,66 @@ struct rte_flow_action_of_ip_ttl_set {
 };
 
 /**
+ * RTE_FLOW_ACTION_TYPE_OF_VLAN_PUSH
+ *
+ * Push a new VLAN header onto the packet, EtherType 0x8100 or 0x88a8
+ * should be used. The value of VLAN ID and VLAN priority for the new
+ * header is copied from an exist outermost VLAN header in the packet,
+ * they will be set to 0 if no such VLAN header exist. Comply with
+ * OpenFlow action "OFPAT_PUSH_VLAN".
+ */
+struct rte_flow_action_of_vlan_push {
+	rte_be16_t ether_type; /**< EtherType for vlan tag. */
+};
+
+/**
+ * RTE_FLOW_ACTION_TYPE_OF_VLAN_VID_SET
+ *
+ * Set VLAN id of an exist VLAN header or a new pushed VLAN header
+ * (when follow action RTE_FLOW_ACTION_TYPE_OF_VLAN_PUSH). Comply with
+ * OpenFlow action "OFPAT_SET_VLAN_VID".
+ */
+struct rte_flow_action_of_vlan_vid_set {
+	rte_be16_t vid; /**< VLAN id to set. */
+};
+
+/**
+ * RTE_FLOW_ACTION_TYPE_OF_VLAN_PCP_SET
+ *
+ * Set 3-bit priority of an exist VLAN header or a new pushed VLAN header
+ * (when follow action RTE_FLOW_ACTION_TYPE_OF_VLAN_PUSH). Comply with
+ * OpenFlow action "OFPAT_SET_VLAN_PCP".
+ */
+struct rte_flow_action_of_vlan_pcp_set {
+	uint8_t pcp; /**< Vlan priority to set. */
+};
+
+/**
+ * RTE_FLOW_ACTION_TYPE_OF_MPLS_POP,
+ *
+ * Pop the outer-most MPLS header from the packet, EtherType is
+ * required for the resulting packet if it is not the last MPLS
+ * header be popped, EtherType must be 0x8847 or 0x8848. Comply
+ * with OpenFlow action "OFPAT_POP_MPLS".
+ */
+struct rte_flow_action_of_mpls_pop {
+	rte_be16_t ether_type; /**< EtherType for MPLS header */
+};
+
+/**
+ * RTE_FLOW_ACTION_TYPE_OF_MPLS_PUSH,
+ *
+ * Push a new MPLS header onto the packet, EtherType 0x8847 or 0x8848
+ * should be used. The value of MPLS label and traffic class are copied
+ * from exist outermost MPLS header, and TTL is copied from exist outermost
+ * MPLS or IP header, they will be set to 0, if exist packet does not
+ * contain required header. Comply with OpenFlow action "OFPAT_PUSH_MPLS".
+ */
+struct rte_flow_action_of_mpls_push {
+	rte_be16_t ether_type; /**< EtherType for MPLS header */
+};
+
+/**
  * Definition of a single action.
  *
  * A list of actions is terminated by a END action.
-- 
2.13.6

^ permalink raw reply	[flat|nested] 61+ messages in thread

* [dpdk-dev] [PATCH v5 0/3] rte_flow extension for vSwitch acceleration
  2018-04-23  6:36 ` [dpdk-dev] [PATCH v4 0/3] rte_flow extension for vSwitch acceleration Qi Zhang
                     ` (2 preceding siblings ...)
  2018-04-23  6:36   ` [dpdk-dev] [PATCH v4 3/3] ethdev: add VLAN and MPLS " Qi Zhang
@ 2018-04-24 15:58   ` Adrien Mazarguil
  2018-04-24 15:58     ` [dpdk-dev] [PATCH v5 1/3] ethdev: add neighbor discovery support to flow API Adrien Mazarguil
                       ` (3 more replies)
  3 siblings, 4 replies; 61+ messages in thread
From: Adrien Mazarguil @ 2018-04-24 15:58 UTC (permalink / raw)
  To: Ferruh Yigit, Qi Zhang
  Cc: dev, declan.doherty, sugesh.chandran, michael.j.glynn, yu.y.liu,
	konstantin.ananyev, bruce.richardson

v5 (Adrien):

While the previous version (v4) looked fine, I noticed several issues and
inconsistencies while testing it. I decided to take over Qi Zhang's series
to hasten things for RC1.

Please have a look at individual patches, where I summarized the changes for
each of them.

v4:
- Change to OpenFlow complied TTL actions
- Change to OpenFlow complied VLAN/MPLS actions. 
- typos fix.
- Remove generic field_set action since, couple opens not closed (should we move
  to dedicate filed modification actions?)

v3:
- remove patch for port action and enhanced statistic query.
- reworked IPv6 ND related pattern base on Adrien's suggestion.
- remove generic increament/decrement/copy action
- rework packet modification action(RTE_FLOW_ACTION_TYPE_FIELD_SET).
- Add OpenFlow friendly TTL change actions.
- Add OpenFlow friendly VLAN/MPLS push/pop actions

v2:
- fix couple typoes in code, doc and commit log

This patch extend rte_flow API.
The purpose is to provide necessary programming interface for virtual
switch software (such as OVS) to take advantage of incoming device's
vSwitch acceleration capability when using DPDK as data plane.

Note:
- The driver to demonstrate the new APIs is still in development,
  but we hope it could be accepted early to make OVS integration
  smoothly. 

Qi Zhang (3):
  ethdev: add neighbor discovery support to flow API
  ethdev: add TTL change actions to flow API
  ethdev: add VLAN and MPLS actions to flow API

 app/test-pmd/cmdline_flow.c                 | 472 +++++++++++++++++++++++
 app/test-pmd/config.c                       |  29 ++
 doc/guides/prog_guide/rte_flow.rst          | 309 ++++++++++++++-
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  76 ++++
 lib/librte_ether/rte_flow.c                 |  29 ++
 lib/librte_ether/rte_flow.h                 | 424 +++++++++++++++++++-
 6 files changed, 1336 insertions(+), 3 deletions(-)

-- 
2.11.0

^ permalink raw reply	[flat|nested] 61+ messages in thread

* [dpdk-dev] [PATCH v5 1/3] ethdev: add neighbor discovery support to flow API
  2018-04-24 15:58   ` [dpdk-dev] [PATCH v5 0/3] rte_flow extension for vSwitch acceleration Adrien Mazarguil
@ 2018-04-24 15:58     ` Adrien Mazarguil
  2018-04-24 15:59     ` [dpdk-dev] [PATCH v5 2/3] ethdev: add TTL change actions " Adrien Mazarguil
                       ` (2 subsequent siblings)
  3 siblings, 0 replies; 61+ messages in thread
From: Adrien Mazarguil @ 2018-04-24 15:58 UTC (permalink / raw)
  To: Ferruh Yigit, Qi Zhang
  Cc: dev, declan.doherty, sugesh.chandran, michael.j.glynn, yu.y.liu,
	konstantin.ananyev, bruce.richardson

From: Qi Zhang <qi.z.zhang@intel.com>

- RTE_FLOW_ITEM_TYPE_ARP_ETH_IPV4: matches an ARP header for Ethernet/IPv4.

- RTE_FLOW_ITEM_TYPE_IPV6_EXT: matches the presence of any IPv6 extension
  header.

- RTE_FLOW_ITEM_TYPE_ICMP6: matches any ICMPv6 header.

- RTE_FLOW_ITEM_TYPE_ICMP6_ND_NS: matches an ICMPv6 neighbor discovery
  solicitation.

- RTE_FLOW_ITEM_TYPE_ICMP6_ND_NA: matches an ICMPv6 neighbor discovery
  advertisement.

- RTE_FLOW_ITEM_TYPE_ICMP6_ND_OPT: matches the presence of any ICMPv6
  neighbor discovery option.

- RTE_FLOW_ITEM_TYPE_ICMP6_ND_OPT_ETH_SLA: matches an ICMPv6 neighbor
  discovery source Ethernet link-layer address option.

- RTE_FLOW_ITEM_TYPE_ICMP6_ND_OPT_ETH_TLA: matches an ICMPv6 neighbor
  discovery target Ethernet link-layer address option.

Signed-off-by: Qi Zhang <qi.z.zhang@intel.com>
Signed-off-by: Adrien Mazarguil <adrien.mazarguil@6wind.com>

--

v5 changes:

- Clarified ITEM_ARP_IPV4 as ITEM_ARP_ETH_IPV4.
- Expanded abbreviated macros (e.g. ITEM_ICMP6_ND_NS_TGT_ADDR =>
  ITEM_ICMP6_ND_NS_TARGET_ADDR) to match the name of the underlying
  structure field.
- Fixed testpmd flow command issues (lack of ITEM_NEXT, use of UNSIGNED
  instead of IPV4_ADDR/IPV6_ADDR/MAC_ADDR).
- Clarified/fixed flow command help strings and matching documentation.
- Added ITEM_ICMP6_ND_OPT for generic ND options.
- Modified ITEM_ICMP6_ND_OPT_SLA_ETH and ITEM_ICMP6_ND_OPT_TLA_ETH to not
  include an ICMPv6 header but instead work like ITEM_ICMP6_ND_OPT as
  separate items to stack on top of ICMPv6 ND on a needed basis.
- Updated documentation accordingly.
- Added these new pattern items to rte_flow_copy().
- Updated commit log to reflect patch contents.
---
 app/test-pmd/cmdline_flow.c                 | 241 +++++++++++++++++++++
 app/test-pmd/config.c                       |  10 +
 doc/guides/prog_guide/rte_flow.rst          | 114 +++++++++-
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  38 ++++
 lib/librte_ether/rte_flow.c                 |  10 +
 lib/librte_ether/rte_flow.h                 | 254 ++++++++++++++++++++++-
 6 files changed, 665 insertions(+), 2 deletions(-)

diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c
index 32fe6645a..2bb2be101 100644
--- a/app/test-pmd/cmdline_flow.c
+++ b/app/test-pmd/cmdline_flow.c
@@ -154,6 +154,26 @@ enum index {
 	ITEM_GENEVE,
 	ITEM_GENEVE_VNI,
 	ITEM_GENEVE_PROTO,
+	ITEM_ARP_ETH_IPV4,
+	ITEM_ARP_ETH_IPV4_SHA,
+	ITEM_ARP_ETH_IPV4_SPA,
+	ITEM_ARP_ETH_IPV4_THA,
+	ITEM_ARP_ETH_IPV4_TPA,
+	ITEM_IPV6_EXT,
+	ITEM_IPV6_EXT_NEXT_HDR,
+	ITEM_ICMP6,
+	ITEM_ICMP6_TYPE,
+	ITEM_ICMP6_CODE,
+	ITEM_ICMP6_ND_NS,
+	ITEM_ICMP6_ND_NS_TARGET_ADDR,
+	ITEM_ICMP6_ND_NA,
+	ITEM_ICMP6_ND_NA_TARGET_ADDR,
+	ITEM_ICMP6_ND_OPT,
+	ITEM_ICMP6_ND_OPT_TYPE,
+	ITEM_ICMP6_ND_OPT_SLA_ETH,
+	ITEM_ICMP6_ND_OPT_SLA_ETH_SLA,
+	ITEM_ICMP6_ND_OPT_TLA_ETH,
+	ITEM_ICMP6_ND_OPT_TLA_ETH_TLA,
 
 	/* Validate/create actions. */
 	ACTIONS,
@@ -470,6 +490,14 @@ static const enum index next_item[] = {
 	ITEM_GTPC,
 	ITEM_GTPU,
 	ITEM_GENEVE,
+	ITEM_ARP_ETH_IPV4,
+	ITEM_IPV6_EXT,
+	ITEM_ICMP6,
+	ITEM_ICMP6_ND_NS,
+	ITEM_ICMP6_ND_NA,
+	ITEM_ICMP6_ND_OPT,
+	ITEM_ICMP6_ND_OPT_SLA_ETH,
+	ITEM_ICMP6_ND_OPT_TLA_ETH,
 	ZERO,
 };
 
@@ -626,6 +654,58 @@ static const enum index item_geneve[] = {
 	ZERO,
 };
 
+static const enum index item_arp_eth_ipv4[] = {
+	ITEM_ARP_ETH_IPV4_SHA,
+	ITEM_ARP_ETH_IPV4_SPA,
+	ITEM_ARP_ETH_IPV4_THA,
+	ITEM_ARP_ETH_IPV4_TPA,
+	ITEM_NEXT,
+	ZERO,
+};
+
+static const enum index item_ipv6_ext[] = {
+	ITEM_IPV6_EXT_NEXT_HDR,
+	ITEM_NEXT,
+	ZERO,
+};
+
+static const enum index item_icmp6[] = {
+	ITEM_ICMP6_TYPE,
+	ITEM_ICMP6_CODE,
+	ITEM_NEXT,
+	ZERO,
+};
+
+static const enum index item_icmp6_nd_ns[] = {
+	ITEM_ICMP6_ND_NS_TARGET_ADDR,
+	ITEM_NEXT,
+	ZERO,
+};
+
+static const enum index item_icmp6_nd_na[] = {
+	ITEM_ICMP6_ND_NA_TARGET_ADDR,
+	ITEM_NEXT,
+	ZERO,
+};
+
+static const enum index item_icmp6_nd_opt[] = {
+	ITEM_ICMP6_ND_OPT_TYPE,
+	ITEM_NEXT,
+	ZERO,
+};
+
+static const enum index item_icmp6_nd_opt_sla_eth[] = {
+	ITEM_ICMP6_ND_OPT_SLA_ETH_SLA,
+	ITEM_NEXT,
+	ZERO,
+};
+
+static const enum index item_icmp6_nd_opt_tla_eth[] = {
+	ITEM_ICMP6_ND_OPT_TLA_ETH_TLA,
+	ITEM_NEXT,
+	ZERO,
+};
+
 static const enum index next_action[] = {
 	ACTION_END,
 	ACTION_VOID,
@@ -1560,6 +1640,167 @@ static const struct token token_list[] = {
 		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_geneve,
 					     protocol)),
 	},
+	[ITEM_ARP_ETH_IPV4] = {
+		.name = "arp_eth_ipv4",
+		.help = "match ARP header for Ethernet/IPv4",
+		.priv = PRIV_ITEM(ARP_ETH_IPV4,
+				  sizeof(struct rte_flow_item_arp_eth_ipv4)),
+		.next = NEXT(item_arp_eth_ipv4),
+		.call = parse_vc,
+	},
+	[ITEM_ARP_ETH_IPV4_SHA] = {
+		.name = "sha",
+		.help = "sender hardware address",
+		.next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(MAC_ADDR),
+			     item_param),
+		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
+					     sha)),
+	},
+	[ITEM_ARP_ETH_IPV4_SPA] = {
+		.name = "spa",
+		.help = "sender IPv4 address",
+		.next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(IPV4_ADDR),
+			     item_param),
+		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
+					     spa)),
+	},
+	[ITEM_ARP_ETH_IPV4_THA] = {
+		.name = "tha",
+		.help = "target hardware address",
+		.next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(MAC_ADDR),
+			     item_param),
+		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
+					     tha)),
+	},
+	[ITEM_ARP_ETH_IPV4_TPA] = {
+		.name = "tpa",
+		.help = "target IPv4 address",
+		.next = NEXT(item_arp_eth_ipv4, NEXT_ENTRY(IPV4_ADDR),
+			     item_param),
+		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_arp_eth_ipv4,
+					     tpa)),
+	},
+	[ITEM_IPV6_EXT] = {
+		.name = "ipv6_ext",
+		.help = "match presence of any IPv6 extension header",
+		.priv = PRIV_ITEM(IPV6_EXT,
+				  sizeof(struct rte_flow_item_ipv6_ext)),
+		.next = NEXT(item_ipv6_ext),
+		.call = parse_vc,
+	},
+	[ITEM_IPV6_EXT_NEXT_HDR] = {
+		.name = "next_hdr",
+		.help = "next header",
+		.next = NEXT(item_ipv6_ext, NEXT_ENTRY(UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_ipv6_ext,
+					     next_hdr)),
+	},
+	[ITEM_ICMP6] = {
+		.name = "icmp6",
+		.help = "match any ICMPv6 header",
+		.priv = PRIV_ITEM(ICMP6, sizeof(struct rte_flow_item_icmp6)),
+		.next = NEXT(item_icmp6),
+		.call = parse_vc,
+	},
+	[ITEM_ICMP6_TYPE] = {
+		.name = "type",
+		.help = "ICMPv6 type",
+		.next = NEXT(item_icmp6, NEXT_ENTRY(UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6,
+					     type)),
+	},
+	[ITEM_ICMP6_CODE] = {
+		.name = "code",
+		.help = "ICMPv6 code",
+		.next = NEXT(item_icmp6, NEXT_ENTRY(UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6,
+					     code)),
+	},
+	[ITEM_ICMP6_ND_NS] = {
+		.name = "icmp6_nd_ns",
+		.help = "match ICMPv6 neighbor discovery solicitation",
+		.priv = PRIV_ITEM(ICMP6_ND_NS,
+				  sizeof(struct rte_flow_item_icmp6_nd_ns)),
+		.next = NEXT(item_icmp6_nd_ns),
+		.call = parse_vc,
+	},
+	[ITEM_ICMP6_ND_NS_TARGET_ADDR] = {
+		.name = "target_addr",
+		.help = "target address",
+		.next = NEXT(item_icmp6_nd_ns, NEXT_ENTRY(IPV6_ADDR),
+			     item_param),
+		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_ns,
+					     target_addr)),
+	},
+	[ITEM_ICMP6_ND_NA] = {
+		.name = "icmp6_nd_na",
+		.help = "match ICMPv6 neighbor discovery advertisement",
+		.priv = PRIV_ITEM(ICMP6_ND_NA,
+				  sizeof(struct rte_flow_item_icmp6_nd_na)),
+		.next = NEXT(item_icmp6_nd_na),
+		.call = parse_vc,
+	},
+	[ITEM_ICMP6_ND_NA_TARGET_ADDR] = {
+		.name = "target_addr",
+		.help = "target address",
+		.next = NEXT(item_icmp6_nd_na, NEXT_ENTRY(IPV6_ADDR),
+			     item_param),
+		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_na,
+					     target_addr)),
+	},
+	[ITEM_ICMP6_ND_OPT] = {
+		.name = "icmp6_nd_opt",
+		.help = "match presence of any ICMPv6 neighbor discovery"
+			" option",
+		.priv = PRIV_ITEM(ICMP6_ND_OPT,
+				  sizeof(struct rte_flow_item_icmp6_nd_opt)),
+		.next = NEXT(item_icmp6_nd_opt),
+		.call = parse_vc,
+	},
+	[ITEM_ICMP6_ND_OPT_TYPE] = {
+		.name = "type",
+		.help = "ND option type",
+		.next = NEXT(item_icmp6_nd_opt, NEXT_ENTRY(UNSIGNED),
+			     item_param),
+		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_icmp6_nd_opt,
+					     type)),
+	},
+	[ITEM_ICMP6_ND_OPT_SLA_ETH] = {
+		.name = "icmp6_nd_opt_sla_eth",
+		.help = "match ICMPv6 neighbor discovery source Ethernet"
+			" link-layer address option",
+		.priv = PRIV_ITEM
+			(ICMP6_ND_OPT_SLA_ETH,
+			 sizeof(struct rte_flow_item_icmp6_nd_opt_sla_eth)),
+		.next = NEXT(item_icmp6_nd_opt_sla_eth),
+		.call = parse_vc,
+	},
+	[ITEM_ICMP6_ND_OPT_SLA_ETH_SLA] = {
+		.name = "sla",
+		.help = "source Ethernet LLA",
+		.next = NEXT(item_icmp6_nd_opt_sla_eth, NEXT_ENTRY(MAC_ADDR),
+			     item_param),
+		.args = ARGS(ARGS_ENTRY_HTON
+			     (struct rte_flow_item_icmp6_nd_opt_sla_eth, sla)),
+	},
+	[ITEM_ICMP6_ND_OPT_TLA_ETH] = {
+		.name = "icmp6_nd_opt_tla_eth",
+		.help = "match ICMPv6 neighbor discovery target Ethernet"
+			" link-layer address option",
+		.priv = PRIV_ITEM
+			(ICMP6_ND_OPT_TLA_ETH,
+			 sizeof(struct rte_flow_item_icmp6_nd_opt_tla_eth)),
+		.next = NEXT(item_icmp6_nd_opt_tla_eth),
+		.call = parse_vc,
+	},
+	[ITEM_ICMP6_ND_OPT_TLA_ETH_TLA] = {
+		.name = "tla",
+		.help = "target Ethernet LLA",
+		.next = NEXT(item_icmp6_nd_opt_tla_eth, NEXT_ENTRY(MAC_ADDR),
+			     item_param),
+		.args = ARGS(ARGS_ENTRY_HTON
+			     (struct rte_flow_item_icmp6_nd_opt_tla_eth, tla)),
+	},
 
 	/* Validate/create actions. */
 	[ACTIONS] = {
diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
index 104e85ba2..c06b76c31 100644
--- a/app/test-pmd/config.c
+++ b/app/test-pmd/config.c
@@ -1014,6 +1014,16 @@ static const struct {
 	MK_FLOW_ITEM(GTPC, sizeof(struct rte_flow_item_gtp)),
 	MK_FLOW_ITEM(GTPU, sizeof(struct rte_flow_item_gtp)),
 	MK_FLOW_ITEM(GENEVE, sizeof(struct rte_flow_item_geneve)),
+	MK_FLOW_ITEM(ARP_ETH_IPV4, sizeof(struct rte_flow_item_arp_eth_ipv4)),
+	MK_FLOW_ITEM(IPV6_EXT, sizeof(struct rte_flow_item_ipv6_ext)),
+	MK_FLOW_ITEM(ICMP6, sizeof(struct rte_flow_item_icmp6)),
+	MK_FLOW_ITEM(ICMP6_ND_NS, sizeof(struct rte_flow_item_icmp6_nd_ns)),
+	MK_FLOW_ITEM(ICMP6_ND_NA, sizeof(struct rte_flow_item_icmp6_nd_na)),
+	MK_FLOW_ITEM(ICMP6_ND_OPT, sizeof(struct rte_flow_item_icmp6_nd_opt)),
+	MK_FLOW_ITEM(ICMP6_ND_OPT_SLA_ETH,
+		     sizeof(struct rte_flow_item_icmp6_nd_opt_sla_eth)),
+	MK_FLOW_ITEM(ICMP6_ND_OPT_TLA_ETH,
+		     sizeof(struct rte_flow_item_icmp6_nd_opt_tla_eth)),
 };
 
 /** Pattern item specification types. */
diff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst
index 2fb8e9c3f..644076cb9 100644
--- a/doc/guides/prog_guide/rte_flow.rst
+++ b/doc/guides/prog_guide/rte_flow.rst
@@ -874,7 +874,8 @@ Item: ``IPV6``
 
 Matches an IPv6 header.
 
-Note: IPv6 options are handled by dedicated pattern items.
+Note: IPv6 options are handled by dedicated pattern items, see `Item:
+IPV6_EXT`_.
 
 - ``hdr``: IPv6 header definition (``rte_ip.h``).
 - Default ``mask`` matches source and destination addresses only.
@@ -1054,6 +1055,117 @@ Matches a GENEVE header.
 - ``rsvd1``: reserved, normally 0x00.
 - Default ``mask`` matches VNI only.
 
+Item: ``ARP_ETH_IPV4``
+^^^^^^^^^^^^^^^^^^^^^^
+
+Matches an ARP header for Ethernet/IPv4.
+
+- ``hdr``: hardware type, normally 1.
+- ``pro``: protocol type, normally 0x0800.
+- ``hln``: hardware address length, normally 6.
+- ``pln``: protocol address length, normally 4.
+- ``op``: opcode (1 for request, 2 for reply).
+- ``sha``: sender hardware address.
+- ``spa``: sender IPv4 address.
+- ``tha``: target hardware address.
+- ``tpa``: target IPv4 address.
+- Default ``mask`` matches SHA, SPA, THA and TPA.
+
+Item: ``IPV6_EXT``
+^^^^^^^^^^^^^^^^^^
+
+Matches the presence of any IPv6 extension header.
+
+- ``next_hdr``: next header.
+- Default ``mask`` matches ``next_hdr``.
+
+Normally preceded by any of:
+
+- `Item: IPV6`_
+- `Item: IPV6_EXT`_
+
+Item: ``ICMP6``
+^^^^^^^^^^^^^^^
+
+Matches any ICMPv6 header.
+
+- ``type``: ICMPv6 type.
+- ``code``: ICMPv6 code.
+- ``checksum``: ICMPv6 checksum.
+- Default ``mask`` matches ``type`` and ``code``.
+
+Item: ``ICMP6_ND_NS``
+^^^^^^^^^^^^^^^^^^^^^
+
+Matches an ICMPv6 neighbor discovery solicitation.
+
+- ``type``: ICMPv6 type, normally 135.
+- ``code``: ICMPv6 code, normally 0.
+- ``checksum``: ICMPv6 checksum.
+- ``reserved``: reserved, normally 0.
+- ``target_addr``: target address.
+- Default ``mask`` matches target address only.
+
+Item: ``ICMP6_ND_NA``
+^^^^^^^^^^^^^^^^^^^^^
+
+Matches an ICMPv6 neighbor discovery advertisement.
+
+- ``type``: ICMPv6 type, normally 136.
+- ``code``: ICMPv6 code, normally 0.
+- ``checksum``: ICMPv6 checksum.
+- ``rso_reserved``: route flag (1b), solicited flag (1b), override flag
+  (1b), reserved (29b).
+- ``target_addr``: target address.
+- Default ``mask`` matches target address only.
+
+Item: ``ICMP6_ND_OPT``
+^^^^^^^^^^^^^^^^^^^^^^
+
+Matches the presence of any ICMPv6 neighbor discovery option.
+
+- ``type``: ND option type.
+- ``length``: ND option length.
+- Default ``mask`` matches type only.
+
+Normally preceded by any of:
+
+- `Item: ICMP6_ND_NA`_
+- `Item: ICMP6_ND_NS`_
+- `Item: ICMP6_ND_OPT`_
+
+Item: ``ICMP6_ND_OPT_SLA_ETH``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Matches an ICMPv6 neighbor discovery source Ethernet link-layer address
+option.
+
+- ``type``: ND option type, normally 1.
+- ``length``: ND option length, normally 1.
+- ``sla``: source Ethernet LLA.
+- Default ``mask`` matches source link-layer address only.
+
+Normally preceded by any of:
+
+- `Item: ICMP6_ND_NA`_
+- `Item: ICMP6_ND_OPT`_
+
+Item: ``ICMP6_ND_OPT_TLA_ETH``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Matches an ICMPv6 neighbor discovery target Ethernet link-layer address
+option.
+
+- ``type``: ND option type, normally 2.
+- ``length``: ND option length, normally 1.
+- ``tla``: target Ethernet LLA.
+- Default ``mask`` matches target link-layer address only.
+
+Normally preceded by any of:
+
+- `Item: ICMP6_ND_NS`_
+- `Item: ICMP6_ND_OPT`_
+
 Actions
 ~~~~~~~
 
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index 829e38428..8e7cae00b 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -3312,6 +3312,44 @@ This section lists supported pattern items and their attributes, if any.
   - ``vni {unsigned}``: virtual network identifier.
   - ``protocol {unsigned}``: protocol type.
 
+- ``arp_eth_ipv4``: match ARP header for Ethernet/IPv4.
+
+  - ``sha {MAC-48}``: sender hardware address.
+  - ``spa {ipv4 address}``: sender IPv4 address.
+  - ``tha {MAC-48}``: target hardware address.
+  - ``tpa {ipv4 address}``: target IPv4 address.
+
+- ``ipv6_ext``: match presence of any IPv6 extension header.
+
+  - ``next_hdr {unsigned}``: next header.
+
+- ``icmp6``: match any ICMPv6 header.
+
+  - ``type {unsigned}``: ICMPv6 type.
+  - ``code {unsigned}``: ICMPv6 code.
+
+- ``icmp6_nd_ns``: match ICMPv6 neighbor discovery solicitation.
+
+  - ``target_addr {ipv6 address}``: target address.
+
+- ``icmp6_nd_na``: match ICMPv6 neighbor discovery advertisement.
+
+  - ``target_addr {ipv6 address}``: target address.
+
+- ``icmp6_nd_opt``: match presence of any ICMPv6 neighbor discovery option.
+
+  - ``type {unsigned}``: ND option type.
+
+- ``icmp6_nd_opt_sla_eth``: match ICMPv6 neighbor discovery source Ethernet
+  link-layer address option.
+
+  - ``sla {MAC-48}``: source Ethernet LLA.
+
+- ``icmp6_nd_opt_sla_eth``: match ICMPv6 neighbor discovery target Ethernet
+  link-layer address option.
+
+  - ``tla {MAC-48}``: target Ethernet LLA.
+
 Actions list
 ^^^^^^^^^^^^
 
diff --git a/lib/librte_ether/rte_flow.c b/lib/librte_ether/rte_flow.c
index cecab59f6..39fa93baa 100644
--- a/lib/librte_ether/rte_flow.c
+++ b/lib/librte_ether/rte_flow.c
@@ -55,6 +55,16 @@ static const struct rte_flow_desc_data rte_flow_desc_item[] = {
 	MK_FLOW_ITEM(E_TAG, sizeof(struct rte_flow_item_e_tag)),
 	MK_FLOW_ITEM(NVGRE, sizeof(struct rte_flow_item_nvgre)),
 	MK_FLOW_ITEM(GENEVE, sizeof(struct rte_flow_item_geneve)),
+	MK_FLOW_ITEM(ARP_ETH_IPV4, sizeof(struct rte_flow_item_arp_eth_ipv4)),
+	MK_FLOW_ITEM(IPV6_EXT, sizeof(struct rte_flow_item_ipv6_ext)),
+	MK_FLOW_ITEM(ICMP6, sizeof(struct rte_flow_item_icmp6)),
+	MK_FLOW_ITEM(ICMP6_ND_NS, sizeof(struct rte_flow_item_icmp6_nd_ns)),
+	MK_FLOW_ITEM(ICMP6_ND_NA, sizeof(struct rte_flow_item_icmp6_nd_na)),
+	MK_FLOW_ITEM(ICMP6_ND_OPT, sizeof(struct rte_flow_item_icmp6_nd_opt)),
+	MK_FLOW_ITEM(ICMP6_ND_OPT_SLA_ETH,
+		     sizeof(struct rte_flow_item_icmp6_nd_opt_sla_eth)),
+	MK_FLOW_ITEM(ICMP6_ND_OPT_TLA_ETH,
+		     sizeof(struct rte_flow_item_icmp6_nd_opt_tla_eth)),
 };
 
 /** Generate flow_action[] entry. */
diff --git a/lib/librte_ether/rte_flow.h b/lib/librte_ether/rte_flow.h
index 09a21e531..e9b361dda 100644
--- a/lib/librte_ether/rte_flow.h
+++ b/lib/librte_ether/rte_flow.h
@@ -339,6 +339,64 @@ enum rte_flow_item_type {
 	 * See struct rte_flow_item_geneve.
 	 */
 	RTE_FLOW_ITEM_TYPE_GENEVE,
+
+	/**
+	 * Matches an ARP header for Ethernet/IPv4.
+	 *
+	 * See struct rte_flow_item_arp_eth_ipv4.
+	 */
+	RTE_FLOW_ITEM_TYPE_ARP_ETH_IPV4,
+
+	/**
+	 * Matches the presence of any IPv6 extension header.
+	 *
+	 * See struct rte_flow_item_ipv6_ext.
+	 */
+	RTE_FLOW_ITEM_TYPE_IPV6_EXT,
+
+	/**
+	 * Matches any ICMPv6 header.
+	 *
+	 * See struct rte_flow_item_icmp6.
+	 */
+	RTE_FLOW_ITEM_TYPE_ICMP6,
+
+	/**
+	 * Matches an ICMPv6 neighbor discovery solicitation.
+	 *
+	 * See struct rte_flow_item_icmp6_nd_ns.
+	 */
+	RTE_FLOW_ITEM_TYPE_ICMP6_ND_NS,
+
+	/**
+	 * Matches an ICMPv6 neighbor discovery advertisement.
+	 *
+	 * See struct rte_flow_item_icmp6_nd_na.
+	 */
+	RTE_FLOW_ITEM_TYPE_ICMP6_ND_NA,
+
+	/**
+	 * Matches the presence of any ICMPv6 neighbor discovery option.
+	 *
+	 * See struct rte_flow_item_icmp6_nd_opt.
+	 */
+	RTE_FLOW_ITEM_TYPE_ICMP6_ND_OPT,
+
+	/**
+	 * Matches an ICMPv6 neighbor discovery source Ethernet link-layer
+	 * address option.
+	 *
+	 * See struct rte_flow_item_icmp6_nd_opt_sla_eth.
+	 */
+	RTE_FLOW_ITEM_TYPE_ICMP6_ND_OPT_SLA_ETH,
+
+	/**
+	 * Matches an ICMPv6 neighbor discovery target Ethernet link-layer
+	 * address option.
+	 *
+	 * See struct rte_flow_item_icmp6_nd_opt_tla_eth.
+	 */
+	RTE_FLOW_ITEM_TYPE_ICMP6_ND_OPT_TLA_ETH,
 };
 
 /**
@@ -564,7 +622,8 @@ static const struct rte_flow_item_ipv4 rte_flow_item_ipv4_mask = {
  *
  * Matches an IPv6 header.
  *
- * Note: IPv6 options are handled by dedicated pattern items.
+ * Note: IPv6 options are handled by dedicated pattern items, see
+ * RTE_FLOW_ITEM_TYPE_IPV6_EXT.
  */
 struct rte_flow_item_ipv6 {
 	struct ipv6_hdr hdr; /**< IPv6 header definition. */
@@ -868,6 +927,199 @@ static const struct rte_flow_item_geneve rte_flow_item_geneve_mask = {
 #endif
 
 /**
+ * RTE_FLOW_ITEM_TYPE_ARP_ETH_IPV4
+ *
+ * Matches an ARP header for Ethernet/IPv4.
+ */
+struct rte_flow_item_arp_eth_ipv4 {
+	rte_be16_t hrd; /**< Hardware type, normally 1. */
+	rte_be16_t pro; /**< Protocol type, normally 0x0800. */
+	uint8_t hln; /**< Hardware address length, normally 6. */
+	uint8_t pln; /**< Protocol address length, normally 4. */
+	rte_be16_t op; /**< Opcode (1 for request, 2 for reply). */
+	struct ether_addr sha; /**< Sender hardware address. */
+	rte_be32_t spa; /**< Sender IPv4 address. */
+	struct ether_addr tha; /**< Target hardware address. */
+	rte_be32_t tpa; /**< Target IPv4 address. */
+};
+
+/** Default mask for RTE_FLOW_ITEM_TYPE_ARP_ETH_IPV4. */
+#ifndef __cplusplus
+static const struct rte_flow_item_arp_eth_ipv4
+rte_flow_item_arp_eth_ipv4_mask = {
+	.sha.addr_bytes = "\xff\xff\xff\xff\xff\xff",
+	.spa = RTE_BE32(0xffffffff),
+	.tha.addr_bytes = "\xff\xff\xff\xff\xff\xff",
+	.tpa = RTE_BE32(0xffffffff),
+};
+#endif
+
+/**
+ * RTE_FLOW_ITEM_TYPE_IPV6_EXT
+ *
+ * Matches the presence of any IPv6 extension header.
+ *
+ * Normally preceded by any of:
+ *
+ * - RTE_FLOW_ITEM_TYPE_IPV6
+ * - RTE_FLOW_ITEM_TYPE_IPV6_EXT
+ */
+struct rte_flow_item_ipv6_ext {
+	uint8_t next_hdr; /**< Next header. */
+};
+
+/** Default mask for RTE_FLOW_ITEM_TYPE_IPV6_EXT. */
+#ifndef __cplusplus
+static const
+struct rte_flow_item_ipv6_ext rte_flow_item_ipv6_ext_mask = {
+	.next_hdr = 0xff,
+};
+#endif
+
+/**
+ * RTE_FLOW_ITEM_TYPE_ICMP6
+ *
+ * Matches any ICMPv6 header.
+ */
+struct rte_flow_item_icmp6 {
+	uint8_t type; /**< ICMPv6 type. */
+	uint8_t code; /**< ICMPv6 code. */
+	uint16_t checksum; /**< ICMPv6 checksum. */
+};
+
+/** Default mask for RTE_FLOW_ITEM_TYPE_ICMP6. */
+#ifndef __cplusplus
+static const struct rte_flow_item_icmp6 rte_flow_item_icmp6_mask = {
+	.type = 0xff,
+	.code = 0xff,
+};
+#endif
+
+/**
+ * RTE_FLOW_ITEM_TYPE_ICMP6_ND_NS
+ *
+ * Matches an ICMPv6 neighbor discovery solicitation.
+ */
+struct rte_flow_item_icmp6_nd_ns {
+	uint8_t type; /**< ICMPv6 type, normally 135. */
+	uint8_t code; /**< ICMPv6 code, normally 0. */
+	rte_be16_t checksum; /**< ICMPv6 checksum. */
+	rte_be32_t reserved; /**< Reserved, normally 0. */
+	uint8_t target_addr[16]; /**< Target address. */
+};
+
+/** Default mask for RTE_FLOW_ITEM_TYPE_ICMP6_ND_NS. */
+#ifndef __cplusplus
+static const
+struct rte_flow_item_icmp6_nd_ns rte_flow_item_icmp6_nd_ns_mask = {
+	.target_addr =
+		"\xff\xff\xff\xff\xff\xff\xff\xff"
+		"\xff\xff\xff\xff\xff\xff\xff\xff",
+};
+#endif
+
+/**
+ * RTE_FLOW_ITEM_TYPE_ICMP6_ND_NA
+ *
+ * Matches an ICMPv6 neighbor discovery advertisement.
+ */
+struct rte_flow_item_icmp6_nd_na {
+	uint8_t type; /**< ICMPv6 type, normally 136. */
+	uint8_t code; /**< ICMPv6 code, normally 0. */
+	rte_be16_t checksum; /**< ICMPv6 checksum. */
+	/**
+	 * Route flag (1b), solicited flag (1b), override flag (1b),
+	 * reserved (29b).
+	 */
+	rte_be32_t rso_reserved;
+	uint8_t target_addr[16]; /**< Target address. */
+};
+
+/** Default mask for RTE_FLOW_ITEM_TYPE_ICMP6_ND_NA. */
+#ifndef __cplusplus
+static const
+struct rte_flow_item_icmp6_nd_na rte_flow_item_icmp6_nd_na_mask = {
+	.target_addr =
+		"\xff\xff\xff\xff\xff\xff\xff\xff"
+		"\xff\xff\xff\xff\xff\xff\xff\xff",
+};
+#endif
+
+/**
+ * RTE_FLOW_ITEM_TYPE_ICMP6_ND_OPT
+ *
+ * Matches the presence of any ICMPv6 neighbor discovery option.
+ *
+ * Normally preceded by any of:
+ *
+ * - RTE_FLOW_ITEM_TYPE_ICMP6_ND_NA
+ * - RTE_FLOW_ITEM_TYPE_ICMP6_ND_NS
+ * - RTE_FLOW_ITEM_TYPE_ICMP6_ND_OPT
+ */
+struct rte_flow_item_icmp6_nd_opt {
+	uint8_t type; /**< ND option type. */
+	uint8_t length; /**< ND option length. */
+};
+
+/** Default mask for RTE_FLOW_ITEM_TYPE_ICMP6_ND_OPT. */
+#ifndef __cplusplus
+static const struct rte_flow_item_icmp6_nd_opt
+rte_flow_item_icmp6_nd_opt_mask = {
+	.type = 0xff,
+};
+#endif
+
+/**
+ * RTE_FLOW_ITEM_TYPE_ICMP6_ND_OPT_SLA_ETH
+ *
+ * Matches an ICMPv6 neighbor discovery source Ethernet link-layer address
+ * option.
+ *
+ * Normally preceded by any of:
+ *
+ * - RTE_FLOW_ITEM_TYPE_ICMP6_ND_NA
+ * - RTE_FLOW_ITEM_TYPE_ICMP6_ND_OPT
+ */
+struct rte_flow_item_icmp6_nd_opt_sla_eth {
+	uint8_t type; /**< ND option type, normally 1. */
+	uint8_t length; /**< ND option length, normally 1. */
+	struct ether_addr sla; /**< Source Ethernet LLA. */
+};
+
+/** Default mask for RTE_FLOW_ITEM_TYPE_ICMP6_ND_OPT_SLA_ETH. */
+#ifndef __cplusplus
+static const struct rte_flow_item_icmp6_nd_opt_sla_eth
+rte_flow_item_icmp6_nd_opt_sla_eth_mask = {
+	.sla.addr_bytes = "\xff\xff\xff\xff\xff\xff",
+};
+#endif
+
+/**
+ * RTE_FLOW_ITEM_TYPE_ICMP6_ND_OPT_TLA_ETH
+ *
+ * Matches an ICMPv6 neighbor discovery target Ethernet link-layer address
+ * option.
+ *
+ * Normally preceded by any of:
+ *
+ * - RTE_FLOW_ITEM_TYPE_ICMP6_ND_NS
+ * - RTE_FLOW_ITEM_TYPE_ICMP6_ND_OPT
+ */
+struct rte_flow_item_icmp6_nd_opt_tla_eth {
+	uint8_t type; /**< ND option type, normally 2. */
+	uint8_t length; /**< ND option length, normally 1. */
+	struct ether_addr tla; /**< Target Ethernet LLA. */
+};
+
+/** Default mask for RTE_FLOW_ITEM_TYPE_ICMP6_ND_OPT_TLA_ETH. */
+#ifndef __cplusplus
+static const struct rte_flow_item_icmp6_nd_opt_tla_eth
+rte_flow_item_icmp6_nd_opt_tla_eth_mask = {
+	.tla.addr_bytes = "\xff\xff\xff\xff\xff\xff",
+};
+#endif
+
+/**
  * Matching pattern item definition.
  *
  * A pattern is formed by stacking items starting from the lowest protocol
-- 
2.11.0

^ permalink raw reply	[flat|nested] 61+ messages in thread

* [dpdk-dev] [PATCH v5 2/3] ethdev: add TTL change actions to flow API
  2018-04-24 15:58   ` [dpdk-dev] [PATCH v5 0/3] rte_flow extension for vSwitch acceleration Adrien Mazarguil
  2018-04-24 15:58     ` [dpdk-dev] [PATCH v5 1/3] ethdev: add neighbor discovery support to flow API Adrien Mazarguil
@ 2018-04-24 15:59     ` Adrien Mazarguil
  2018-04-24 15:59     ` [dpdk-dev] [PATCH v5 3/3] ethdev: add VLAN and MPLS " Adrien Mazarguil
  2018-04-25 13:54     ` [dpdk-dev] [PATCH v5 0/3] rte_flow extension for vSwitch acceleration Zhang, Qi Z
  3 siblings, 0 replies; 61+ messages in thread
From: Adrien Mazarguil @ 2018-04-24 15:59 UTC (permalink / raw)
  To: Ferruh Yigit, Qi Zhang
  Cc: dev, declan.doherty, sugesh.chandran, michael.j.glynn, yu.y.liu,
	konstantin.ananyev, bruce.richardson

From: Qi Zhang <qi.z.zhang@intel.com>

Add support for the following OpenFlow-defined actions:

- RTE_FLOW_ACTION_OF_SET_MPLS_TTL: MPLS TTL.

- RTE_FLOW_ACTION_OF_DEC_MPLS_TTL: decrement MPLS TTL.

- RTE_FLOW_ACTION_OF_SET_NW_TTL: IP TTL.

- RTE_FLOW_ACTION_OF_DEC_NW_TTL: decrement IP TTL.

- RTE_FLOW_ACTION_OF_COPY_TTL_OUT: copy TTL "outwards".

- RTE_FLOW_ACTION_OF_COPY_TTL_IN: copy TTL "inwards".

Signed-off-by: Qi Zhang <qi.z.zhang@intel.com>
Signed-off-by: Adrien Mazarguil <adrien.mazarguil@6wind.com>

--

v5 changes:

- Modified action names (e.g. ACTION_OF_MPLS_TTL_SET =>
  ACTION_OF_SET_MPLS_TTL) to match their OpenFlow counterparts (e.g.
  OFPAT_SET_MPLS_TTL).
- Simplified documentation of all these actions to point to the OpenFlow
  Switch Specification instead of providing a (possibly) inaccurate
  summary.
- Updated testpmd flow command accordingly.
- Expanded field names in structure definitions and in the testpmd flow
  command to match OpenFlow's.
- Added related item copy code to testpmd and rte_flow_copy().
- Updated commit log to reflect patch contents.
---
 app/test-pmd/cmdline_flow.c                 | 88 +++++++++++++++++++++
 app/test-pmd/config.c                       |  8 ++
 doc/guides/prog_guide/rte_flow.rst          | 99 ++++++++++++++++++++++++
 doc/guides/testpmd_app_ug/testpmd_funcs.rst | 16 ++++
 lib/librte_ether/rte_flow.c                 |  8 ++
 lib/librte_ether/rte_flow.h                 | 72 ++++++++++++++++-
 6 files changed, 290 insertions(+), 1 deletion(-)

diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c
index 2bb2be101..07ca3ac4d 100644
--- a/app/test-pmd/cmdline_flow.c
+++ b/app/test-pmd/cmdline_flow.c
@@ -212,6 +212,14 @@ enum index {
 	ACTION_PORT_ID_ID,
 	ACTION_METER,
 	ACTION_METER_ID,
+	ACTION_OF_SET_MPLS_TTL,
+	ACTION_OF_SET_MPLS_TTL_MPLS_TTL,
+	ACTION_OF_DEC_MPLS_TTL,
+	ACTION_OF_SET_NW_TTL,
+	ACTION_OF_SET_NW_TTL_NW_TTL,
+	ACTION_OF_DEC_NW_TTL,
+	ACTION_OF_COPY_TTL_OUT,
+	ACTION_OF_COPY_TTL_IN,
 };
 
 /** Maximum size for pattern in struct rte_flow_item_raw. */
@@ -721,6 +729,12 @@ static const enum index next_action[] = {
 	ACTION_PHY_PORT,
 	ACTION_PORT_ID,
 	ACTION_METER,
+	ACTION_OF_SET_MPLS_TTL,
+	ACTION_OF_DEC_MPLS_TTL,
+	ACTION_OF_SET_NW_TTL,
+	ACTION_OF_DEC_NW_TTL,
+	ACTION_OF_COPY_TTL_OUT,
+	ACTION_OF_COPY_TTL_IN,
 	ZERO,
 };
 
@@ -774,6 +788,18 @@ static const enum index action_meter[] = {
 	ZERO,
 };
 
+static const enum index action_of_set_mpls_ttl[] = {
+	ACTION_OF_SET_MPLS_TTL_MPLS_TTL,
+	ACTION_NEXT,
+	ZERO,
+};
+
+static const enum index action_of_set_nw_ttl[] = {
+	ACTION_OF_SET_NW_TTL_NW_TTL,
+	ACTION_NEXT,
+	ZERO,
+};
+
 static int parse_init(struct context *, const struct token *,
 		      const char *, unsigned int,
 		      void *, unsigned int);
@@ -2062,6 +2088,68 @@ static const struct token token_list[] = {
 		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_meter, mtr_id)),
 		.call = parse_vc_conf,
 	},
+	[ACTION_OF_SET_MPLS_TTL] = {
+		.name = "of_set_mpls_ttl",
+		.help = "OpenFlow's OFPAT_SET_MPLS_TTL",
+		.priv = PRIV_ACTION
+			(OF_SET_MPLS_TTL,
+			 sizeof(struct rte_flow_action_of_set_mpls_ttl)),
+		.next = NEXT(action_of_set_mpls_ttl),
+		.call = parse_vc,
+	},
+	[ACTION_OF_SET_MPLS_TTL_MPLS_TTL] = {
+		.name = "mpls_ttl",
+		.help = "MPLS TTL",
+		.next = NEXT(action_of_set_mpls_ttl, NEXT_ENTRY(UNSIGNED)),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_of_set_mpls_ttl,
+					mpls_ttl)),
+		.call = parse_vc_conf,
+	},
+	[ACTION_OF_DEC_MPLS_TTL] = {
+		.name = "of_dec_mpls_ttl",
+		.help = "OpenFlow's OFPAT_DEC_MPLS_TTL",
+		.priv = PRIV_ACTION(OF_DEC_MPLS_TTL, 0),
+		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
+		.call = parse_vc,
+	},
+	[ACTION_OF_SET_NW_TTL] = {
+		.name = "of_set_nw_ttl",
+		.help = "OpenFlow's OFPAT_SET_NW_TTL",
+		.priv = PRIV_ACTION
+			(OF_SET_NW_TTL,
+			 sizeof(struct rte_flow_action_of_set_nw_ttl)),
+		.next = NEXT(action_of_set_nw_ttl),
+		.call = parse_vc,
+	},
+	[ACTION_OF_SET_NW_TTL_NW_TTL] = {
+		.name = "nw_ttl",
+		.help = "IP TTL",
+		.next = NEXT(action_of_set_nw_ttl, NEXT_ENTRY(UNSIGNED)),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_action_of_set_nw_ttl,
+					nw_ttl)),
+		.call = parse_vc_conf,
+	},
+	[ACTION_OF_DEC_NW_TTL] = {
+		.name = "of_dec_nw_ttl",
+		.help = "OpenFlow's OFPAT_DEC_NW_TTL",
+		.priv = PRIV_ACTION(OF_DEC_NW_TTL, 0),
+		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
+		.call = parse_vc,
+	},
+	[ACTION_OF_COPY_TTL_OUT] = {
+		.name = "of_copy_ttl_out",
+		.help = "OpenFlow's OFPAT_COPY_TTL_OUT",
+		.priv = PRIV_ACTION(OF_COPY_TTL_OUT, 0),
+		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
+		.call = parse_vc,
+	},
+	[ACTION_OF_COPY_TTL_IN] = {
+		.name = "of_copy_ttl_in",
+		.help = "OpenFlow's OFPAT_COPY_TTL_IN",
+		.priv = PRIV_ACTION(OF_COPY_TTL_IN, 0),
+		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
+		.call = parse_vc,
+	},
 };
 
 /** Remove and return last entry from argument stack. */
diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
index c06b76c31..f1b8f5f75 100644
--- a/app/test-pmd/config.c
+++ b/app/test-pmd/config.c
@@ -1105,6 +1105,14 @@ static const struct {
 	MK_FLOW_ACTION(PHY_PORT, sizeof(struct rte_flow_action_phy_port)),
 	MK_FLOW_ACTION(PORT_ID, sizeof(struct rte_flow_action_port_id)),
 	MK_FLOW_ACTION(METER, sizeof(struct rte_flow_action_meter)),
+	MK_FLOW_ACTION(OF_SET_MPLS_TTL,
+		       sizeof(struct rte_flow_action_of_set_mpls_ttl)),
+	MK_FLOW_ACTION(OF_DEC_MPLS_TTL, 0),
+	MK_FLOW_ACTION(OF_SET_NW_TTL,
+		       sizeof(struct rte_flow_action_of_set_nw_ttl)),
+	MK_FLOW_ACTION(OF_DEC_NW_TTL, 0),
+	MK_FLOW_ACTION(OF_COPY_TTL_OUT, 0),
+	MK_FLOW_ACTION(OF_COPY_TTL_IN, 0),
 };
 
 /** Compute storage space needed by action configuration and copy it. */
diff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst
index 644076cb9..be946cb8c 100644
--- a/doc/guides/prog_guide/rte_flow.rst
+++ b/doc/guides/prog_guide/rte_flow.rst
@@ -1704,6 +1704,103 @@ fields in the pattern items.
    | 1     | END      |
    +-------+----------+
 
+Action: ``OF_SET_MPLS_TTL``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Implements ``OFPAT_SET_MPLS_TTL`` ("MPLS TTL") as defined by the `OpenFlow
+Switch Specification`_.
+
+.. _table_rte_flow_action_of_set_mpls_ttl:
+
+.. table:: OF_SET_MPLS_TTL
+
+   +--------------+----------+
+   | Field        | Value    |
+   +==============+==========+
+   | ``mpls_ttl`` | MPLS TTL |
+   +--------------+----------+
+
+Action: ``OF_DEC_MPLS_TTL``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Implements ``OFPAT_DEC_MPLS_TTL`` ("decrement MPLS TTL") as defined by the
+`OpenFlow Switch Specification`_.
+
+.. _table_rte_flow_action_of_dec_mpls_ttl:
+
+.. table:: OF_DEC_MPLS_TTL
+
+   +---------------+
+   | Field         |
+   +===============+
+   | no properties |
+   +---------------+
+
+Action: ``OF_SET_NW_TTL``
+^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Implements ``OFPAT_SET_NW_TTL`` ("IP TTL") as defined by the `OpenFlow
+Switch Specification`_.
+
+.. _table_rte_flow_action_of_set_nw_ttl:
+
+.. table:: OF_SET_NW_TTL
+
+   +------------+--------+
+   | Field      | Value  |
+   +============+========+
+   | ``nw_ttl`` | IP TTL |
+   +------------+--------+
+
+Action: ``OF_DEC_NW_TTL``
+^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Implements ``OFPAT_DEC_NW_TTL`` ("decrement IP TTL") as defined by the
+`OpenFlow Switch Specification`_.
+
+.. _table_rte_flow_action_of_dec_nw_ttl:
+
+.. table:: OF_DEC_NW_TTL
+
+   +---------------+
+   | Field         |
+   +===============+
+   | no properties |
+   +---------------+
+
+Action: ``OF_COPY_TTL_OUT``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Implements ``OFPAT_COPY_TTL_OUT`` ("copy TTL "outwards" -- from
+next-to-outermost to outermost") as defined by the `OpenFlow Switch
+Specification`_.
+
+.. _table_rte_flow_action_of_copy_ttl_out:
+
+.. table:: OF_COPY_TTL_OUT
+
+   +---------------+
+   | Field         |
+   +===============+
+   | no properties |
+   +---------------+
+
+Action: ``OF_COPY_TTL_IN``
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Implements ``OFPAT_COPY_TTL_IN`` ("copy TTL "inwards" -- from outermost to
+next-to-outermost") as defined by the `OpenFlow Switch Specification`_.
+
+.. _table_rte_flow_action_of_copy_ttl_in:
+
+.. table:: OF_COPY_TTL_IN
+
+   +---------------+
+   | Field         |
+   +===============+
+   | no properties |
+   +---------------+
+
 Negative types
 ~~~~~~~~~~~~~~
 
@@ -2284,3 +2381,5 @@ Future evolutions
 
 - Optional software fallback when PMDs are unable to handle requested flow
   rules so applications do not have to implement their own.
+
+.. _OpenFlow Switch Specification: https://www.opennetworking.org/software-defined-standards/specifications/
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index 8e7cae00b..c223a8a9f 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -3477,6 +3477,22 @@ This section lists supported actions and their attributes, if any.
   - ``original {boolean}``: use original DPDK port ID if possible.
   - ``id {unsigned}``: DPDK port ID.
 
+- ``of_set_mpls_ttl``: OpenFlow's ``OFPAT_SET_MPLS_TTL``.
+
+  - ``mpls_ttl``: MPLS TTL.
+
+- ``of_dec_mpls_ttl``: OpenFlow's ``OFPAT_DEC_MPLS_TTL``.
+
+- ``of_set_nw_ttl``: OpenFlow's ``OFPAT_SET_NW_TTL``.
+
+  - ``nw_ttl``: IP TTL.
+
+- ``of_dec_nw_ttl``: OpenFlow's ``OFPAT_DEC_NW_TTL``.
+
+- ``of_copy_ttl_out``: OpenFlow's ``OFPAT_COPY_TTL_OUT``.
+
+- ``of_copy_ttl_in``: OpenFlow's ``OFPAT_COPY_TTL_IN``.
+
 Destroying flow rules
 ~~~~~~~~~~~~~~~~~~~~~
 
diff --git a/lib/librte_ether/rte_flow.c b/lib/librte_ether/rte_flow.c
index 39fa93baa..e66cfb4c8 100644
--- a/lib/librte_ether/rte_flow.c
+++ b/lib/librte_ether/rte_flow.c
@@ -89,6 +89,14 @@ static const struct rte_flow_desc_data rte_flow_desc_action[] = {
 	MK_FLOW_ACTION(VF, sizeof(struct rte_flow_action_vf)),
 	MK_FLOW_ACTION(PHY_PORT, sizeof(struct rte_flow_action_phy_port)),
 	MK_FLOW_ACTION(PORT_ID, sizeof(struct rte_flow_action_port_id)),
+	MK_FLOW_ACTION(OF_SET_MPLS_TTL,
+		       sizeof(struct rte_flow_action_of_set_mpls_ttl)),
+	MK_FLOW_ACTION(OF_DEC_MPLS_TTL, 0),
+	MK_FLOW_ACTION(OF_SET_NW_TTL,
+		       sizeof(struct rte_flow_action_of_set_nw_ttl)),
+	MK_FLOW_ACTION(OF_DEC_NW_TTL, 0),
+	MK_FLOW_ACTION(OF_COPY_TTL_OUT, 0),
+	MK_FLOW_ACTION(OF_COPY_TTL_IN, 0),
 };
 
 static int
diff --git a/lib/librte_ether/rte_flow.h b/lib/librte_ether/rte_flow.h
index e9b361dda..e8b7ce84f 100644
--- a/lib/librte_ether/rte_flow.h
+++ b/lib/librte_ether/rte_flow.h
@@ -1305,7 +1305,57 @@ enum rte_flow_action_type {
 	 *
 	 * See struct rte_flow_action_security.
 	 */
-	RTE_FLOW_ACTION_TYPE_SECURITY
+	RTE_FLOW_ACTION_TYPE_SECURITY,
+
+	/**
+	 * Implements OFPAT_SET_MPLS_TTL ("MPLS TTL") as defined by the
+	 * OpenFlow Switch Specification.
+	 *
+	 * See struct rte_flow_action_of_set_mpls_ttl.
+	 */
+	RTE_FLOW_ACTION_TYPE_OF_SET_MPLS_TTL,
+
+	/**
+	 * Implements OFPAT_DEC_MPLS_TTL ("decrement MPLS TTL") as defined
+	 * by the OpenFlow Switch Specification.
+	 *
+	 * No associated configuration structure.
+	 */
+	RTE_FLOW_ACTION_TYPE_OF_DEC_MPLS_TTL,
+
+	/**
+	 * Implements OFPAT_SET_NW_TTL ("IP TTL") as defined by the OpenFlow
+	 * Switch Specification.
+	 *
+	 * See struct rte_flow_action_of_set_nw_ttl.
+	 */
+	RTE_FLOW_ACTION_TYPE_OF_SET_NW_TTL,
+
+	/**
+	 * Implements OFPAT_DEC_NW_TTL ("decrement IP TTL") as defined by
+	 * the OpenFlow Switch Specification.
+	 *
+	 * No associated configuration structure.
+	 */
+	RTE_FLOW_ACTION_TYPE_OF_DEC_NW_TTL,
+
+	/**
+	 * Implements OFPAT_COPY_TTL_OUT ("copy TTL "outwards" -- from
+	 * next-to-outermost to outermost") as defined by the OpenFlow
+	 * Switch Specification.
+	 *
+	 * No associated configuration structure.
+	 */
+	RTE_FLOW_ACTION_TYPE_OF_COPY_TTL_OUT,
+
+	/**
+	 * Implements OFPAT_COPY_TTL_IN ("copy TTL "inwards" -- from
+	 * outermost to next-to-outermost") as defined by the OpenFlow
+	 * Switch Specification.
+	 *
+	 * No associated configuration structure.
+	 */
+	RTE_FLOW_ACTION_TYPE_OF_COPY_TTL_IN,
 };
 
 /**
@@ -1483,6 +1533,26 @@ struct rte_flow_action_security {
 };
 
 /**
+ * RTE_FLOW_ACTION_TYPE_OF_SET_MPLS_TTL
+ *
+ * Implements OFPAT_SET_MPLS_TTL ("MPLS TTL") as defined by the OpenFlow
+ * Switch Specification.
+ */
+struct rte_flow_action_of_set_mpls_ttl {
+	uint8_t mpls_ttl; /**< MPLS TTL. */
+};
+
+/**
+ * RTE_FLOW_ACTION_TYPE_OF_SET_NW_TTL
+ *
+ * Implements OFPAT_SET_NW_TTL ("IP TTL") as defined by the OpenFlow Switch
+ * Specification.
+ */
+struct rte_flow_action_of_set_nw_ttl {
+	uint8_t nw_ttl; /**< IP TTL. */
+};
+
+/**
  * Definition of a single action.
  *
  * A list of actions is terminated by a END action.
-- 
2.11.0

^ permalink raw reply	[flat|nested] 61+ messages in thread

* [dpdk-dev] [PATCH v5 3/3] ethdev: add VLAN and MPLS actions to flow API
  2018-04-24 15:58   ` [dpdk-dev] [PATCH v5 0/3] rte_flow extension for vSwitch acceleration Adrien Mazarguil
  2018-04-24 15:58     ` [dpdk-dev] [PATCH v5 1/3] ethdev: add neighbor discovery support to flow API Adrien Mazarguil
  2018-04-24 15:59     ` [dpdk-dev] [PATCH v5 2/3] ethdev: add TTL change actions " Adrien Mazarguil
@ 2018-04-24 15:59     ` Adrien Mazarguil
  2018-04-25 13:54     ` [dpdk-dev] [PATCH v5 0/3] rte_flow extension for vSwitch acceleration Zhang, Qi Z
  3 siblings, 0 replies; 61+ messages in thread
From: Adrien Mazarguil @ 2018-04-24 15:59 UTC (permalink / raw)
  To: Ferruh Yigit, Qi Zhang
  Cc: dev, declan.doherty, sugesh.chandran, michael.j.glynn, yu.y.liu,
	konstantin.ananyev, bruce.richardson

From: Qi Zhang <qi.z.zhang@intel.com>

Add support for the following OpenFlow-defined actions:

- RTE_FLOW_ACTION_OF_POP_VLAN: pop the outer VLAN tag.

- RTE_FLOW_ACTION_OF_PUSH_VLAN: push a new VLAN tag.

- RTE_FLOW_ACTION_OF_SET_VLAN_VID: set the 802.1q VLAN id.

- RTE_FLOW_ACTION_OF_SET_VLAN_PCP: set the 802.1q priority.

- RTE_FLOW_ACTION_OF_POP_MPLS: pop the outer MPLS tag.

- RTE_FLOW_ACTION_OF_PUSH_MPLS: push a new MPLS tag.

Signed-off-by: Qi Zhang <qi.z.zhang@intel.com>
Signed-off-by: Adrien Mazarguil <adrien.mazarguil@6wind.com>

--

v5 changes:

- Modified action names (e.g. RTE_FLOW_ACTION_OF_VLAN_POP =>
  RTE_FLOW_ACTION_OF_POP_VLAN) to match their OpenFlow counterparts (e.g.
  OFPAT_POP_VLAN).
- Simplified documentation of all these actions to point to the OpenFlow
  Switch Specification instead of providing a (possibly) inaccurate
  summary.
- Updated testpmd flow command accordingly.
- Fixed issues with testpmd flow command (lack of HTON, use of parse_vc
  instead of parse_vc_conf).
- Expanded field names in structure definitions and in the testpmd flow
  command to match OpenFlow's.
- Added related item copy code to testpmd and rte_flow_copy().
- Updated commit log to reflect patch contents.
---
 app/test-pmd/cmdline_flow.c                 | 143 +++++++++++++++++++++++
 app/test-pmd/config.c                       |  11 ++
 doc/guides/prog_guide/rte_flow.rst          |  96 +++++++++++++++
 doc/guides/testpmd_app_ug/testpmd_funcs.rst |  22 ++++
 lib/librte_ether/rte_flow.c                 |  11 ++
 lib/librte_ether/rte_flow.h                 |  98 ++++++++++++++++
 6 files changed, 381 insertions(+)

diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c
index 07ca3ac4d..6a93462f5 100644
--- a/app/test-pmd/cmdline_flow.c
+++ b/app/test-pmd/cmdline_flow.c
@@ -220,6 +220,17 @@ enum index {
 	ACTION_OF_DEC_NW_TTL,
 	ACTION_OF_COPY_TTL_OUT,
 	ACTION_OF_COPY_TTL_IN,
+	ACTION_OF_POP_VLAN,
+	ACTION_OF_PUSH_VLAN,
+	ACTION_OF_PUSH_VLAN_ETHERTYPE,
+	ACTION_OF_SET_VLAN_VID,
+	ACTION_OF_SET_VLAN_VID_VLAN_VID,
+	ACTION_OF_SET_VLAN_PCP,
+	ACTION_OF_SET_VLAN_PCP_VLAN_PCP,
+	ACTION_OF_POP_MPLS,
+	ACTION_OF_POP_MPLS_ETHERTYPE,
+	ACTION_OF_PUSH_MPLS,
+	ACTION_OF_PUSH_MPLS_ETHERTYPE,
 };
 
 /** Maximum size for pattern in struct rte_flow_item_raw. */
@@ -735,6 +746,12 @@ static const enum index next_action[] = {
 	ACTION_OF_DEC_NW_TTL,
 	ACTION_OF_COPY_TTL_OUT,
 	ACTION_OF_COPY_TTL_IN,
+	ACTION_OF_POP_VLAN,
+	ACTION_OF_PUSH_VLAN,
+	ACTION_OF_SET_VLAN_VID,
+	ACTION_OF_SET_VLAN_PCP,
+	ACTION_OF_POP_MPLS,
+	ACTION_OF_PUSH_MPLS,
 	ZERO,
 };
 
@@ -800,6 +817,36 @@ static const enum index action_of_set_nw_ttl[] = {
 	ZERO,
 };
 
+static const enum index action_of_push_vlan[] = {
+	ACTION_OF_PUSH_VLAN_ETHERTYPE,
+	ACTION_NEXT,
+	ZERO,
+};
+
+static const enum index action_of_set_vlan_vid[] = {
+	ACTION_OF_SET_VLAN_VID_VLAN_VID,
+	ACTION_NEXT,
+	ZERO,
+};
+
+static const enum index action_of_set_vlan_pcp[] = {
+	ACTION_OF_SET_VLAN_PCP_VLAN_PCP,
+	ACTION_NEXT,
+	ZERO,
+};
+
+static const enum index action_of_pop_mpls[] = {
+	ACTION_OF_POP_MPLS_ETHERTYPE,
+	ACTION_NEXT,
+	ZERO,
+};
+
+static const enum index action_of_push_mpls[] = {
+	ACTION_OF_PUSH_MPLS_ETHERTYPE,
+	ACTION_NEXT,
+	ZERO,
+};
+
 static int parse_init(struct context *, const struct token *,
 		      const char *, unsigned int,
 		      void *, unsigned int);
@@ -2150,6 +2197,102 @@ static const struct token token_list[] = {
 		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
 		.call = parse_vc,
 	},
+	[ACTION_OF_POP_VLAN] = {
+		.name = "of_pop_vlan",
+		.help = "OpenFlow's OFPAT_POP_VLAN",
+		.priv = PRIV_ACTION(OF_POP_VLAN, 0),
+		.next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
+		.call = parse_vc,
+	},
+	[ACTION_OF_PUSH_VLAN] = {
+		.name = "of_push_vlan",
+		.help = "OpenFlow's OFPAT_PUSH_VLAN",
+		.priv = PRIV_ACTION
+			(OF_PUSH_VLAN,
+			 sizeof(struct rte_flow_action_of_push_vlan)),
+		.next = NEXT(action_of_push_vlan),
+		.call = parse_vc,
+	},
+	[ACTION_OF_PUSH_VLAN_ETHERTYPE] = {
+		.name = "ethertype",
+		.help = "EtherType",
+		.next = NEXT(action_of_push_vlan, NEXT_ENTRY(UNSIGNED)),
+		.args = ARGS(ARGS_ENTRY_HTON
+			     (struct rte_flow_action_of_push_vlan,
+			      ethertype)),
+		.call = parse_vc_conf,
+	},
+	[ACTION_OF_SET_VLAN_VID] = {
+		.name = "of_set_vlan_vid",
+		.help = "OpenFlow's OFPAT_SET_VLAN_VID",
+		.priv = PRIV_ACTION
+			(OF_SET_VLAN_VID,
+			 sizeof(struct rte_flow_action_of_set_vlan_vid)),
+		.next = NEXT(action_of_set_vlan_vid),
+		.call = parse_vc,
+	},
+	[ACTION_OF_SET_VLAN_VID_VLAN_VID] = {
+		.name = "vlan_vid",
+		.help = "VLAN id",
+		.next = NEXT(action_of_set_vlan_vid, NEXT_ENTRY(UNSIGNED)),
+		.args = ARGS(ARGS_ENTRY_HTON
+			     (struct rte_flow_action_of_set_vlan_vid,
+			      vlan_vid)),
+		.call = parse_vc_conf,
+	},
+	[ACTION_OF_SET_VLAN_PCP] = {
+		.name = "of_set_vlan_pcp",
+		.help = "OpenFlow's OFPAT_SET_VLAN_PCP",
+		.priv = PRIV_ACTION
+			(OF_SET_VLAN_PCP,
+			 sizeof(struct rte_flow_action_of_set_vlan_pcp)),
+		.next = NEXT(action_of_set_vlan_pcp),
+		.call = parse_vc,
+	},
+	[ACTION_OF_SET_VLAN_PCP_VLAN_PCP] = {
+		.name = "vlan_pcp",
+		.help = "VLAN priority",
+		.next = NEXT(action_of_set_vlan_pcp, NEXT_ENTRY(UNSIGNED)),
+		.args = ARGS(ARGS_ENTRY_HTON
+			     (struct rte_flow_action_of_set_vlan_pcp,
+			      vlan_pcp)),
+		.call = parse_vc_conf,
+	},
+	[ACTION_OF_POP_MPLS] = {
+		.name = "of_pop_mpls",
+		.help = "OpenFlow's OFPAT_POP_MPLS",
+		.priv = PRIV_ACTION(OF_POP_MPLS,
+				    sizeof(struct rte_flow_action_of_pop_mpls)),
+		.next = NEXT(action_of_pop_mpls),
+		.call = parse_vc,
+	},
+	[ACTION_OF_POP_MPLS_ETHERTYPE] = {
+		.name = "ethertype",
+		.help = "EtherType",
+		.next = NEXT(action_of_pop_mpls, NEXT_ENTRY(UNSIGNED)),
+		.args = ARGS(ARGS_ENTRY_HTON
+			     (struct rte_flow_action_of_pop_mpls,
+			      ethertype)),
+		.call = parse_vc_conf,
+	},
+	[ACTION_OF_PUSH_MPLS] = {
+		.name = "of_push_mpls",
+		.help = "OpenFlow's OFPAT_PUSH_MPLS",
+		.priv = PRIV_ACTION
+			(OF_PUSH_MPLS,
+			 sizeof(struct rte_flow_action_of_push_mpls)),
+		.next = NEXT(action_of_push_mpls),
+		.call = parse_vc,
+	},
+	[ACTION_OF_PUSH_MPLS_ETHERTYPE] = {
+		.name = "ethertype",
+		.help = "EtherType",
+		.next = NEXT(action_of_push_mpls, NEXT_ENTRY(UNSIGNED)),
+		.args = ARGS(ARGS_ENTRY_HTON
+			     (struct rte_flow_action_of_push_mpls,
+			      ethertype)),
+		.call = parse_vc_conf,
+	},
 };
 
 /** Remove and return last entry from argument stack. */
diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
index f1b8f5f75..1147458ab 100644
--- a/app/test-pmd/config.c
+++ b/app/test-pmd/config.c
@@ -1113,6 +1113,17 @@ static const struct {
 	MK_FLOW_ACTION(OF_DEC_NW_TTL, 0),
 	MK_FLOW_ACTION(OF_COPY_TTL_OUT, 0),
 	MK_FLOW_ACTION(OF_COPY_TTL_IN, 0),
+	MK_FLOW_ACTION(OF_POP_VLAN, 0),
+	MK_FLOW_ACTION(OF_PUSH_VLAN,
+		       sizeof(struct rte_flow_action_of_push_vlan)),
+	MK_FLOW_ACTION(OF_SET_VLAN_VID,
+		       sizeof(struct rte_flow_action_of_set_vlan_vid)),
+	MK_FLOW_ACTION(OF_SET_VLAN_PCP,
+		       sizeof(struct rte_flow_action_of_set_vlan_pcp)),
+	MK_FLOW_ACTION(OF_POP_MPLS,
+		       sizeof(struct rte_flow_action_of_pop_mpls)),
+	MK_FLOW_ACTION(OF_PUSH_MPLS,
+		       sizeof(struct rte_flow_action_of_push_mpls)),
 };
 
 /** Compute storage space needed by action configuration and copy it. */
diff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst
index be946cb8c..7e43aaaf6 100644
--- a/doc/guides/prog_guide/rte_flow.rst
+++ b/doc/guides/prog_guide/rte_flow.rst
@@ -1801,6 +1801,102 @@ next-to-outermost") as defined by the `OpenFlow Switch Specification`_.
    | no properties |
    +---------------+
 
+Action: ``OF_POP_VLAN``
+^^^^^^^^^^^^^^^^^^^^^^^
+
+Implements ``OFPAT_POP_VLAN`` ("pop the outer VLAN tag") as defined
+by the `OpenFlow Switch Specification`_.
+
+.. _table_rte_flow_action_of_pop_vlan:
+
+.. table:: OF_POP_VLAN
+
+   +---------------+
+   | Field         |
+   +===============+
+   | no properties |
+   +---------------+
+
+Action: ``OF_PUSH_VLAN``
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+Implements ``OFPAT_PUSH_VLAN`` ("push a new VLAN tag") as defined by the
+`OpenFlow Switch Specification`_.
+
+.. _table_rte_flow_action_of_push_vlan:
+
+.. table:: OF_PUSH_VLAN
+
+   +---------------+-----------+
+   | Field         | Value     |
+   +===============+===========+
+   | ``ethertype`` | EtherType |
+   +---------------+-----------+
+
+Action: ``OF_SET_VLAN_VID``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Implements ``OFPAT_SET_VLAN_VID`` ("set the 802.1q VLAN id") as defined by
+the `OpenFlow Switch Specification`_.
+
+.. _table_rte_flow_action_of_set_vlan_vid:
+
+.. table:: OF_SET_VLAN_VID
+
+   +--------------+---------+
+   | Field        | Value   |
+   +==============+=========+
+   | ``vlan_vid`` | VLAN id |
+   +--------------+---------+
+
+Action: ``OF_SET_VLAN_PCP``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Implements ``OFPAT_SET_LAN_PCP`` ("set the 802.1q priority") as defined by
+the `OpenFlow Switch Specification`_.
+
+.. _table_rte_flow_action_of_set_vlan_pcp:
+
+.. table:: OF_SET_VLAN_PCP
+
+   +--------------+---------------+
+   | Field        | Value         |
+   +==============+===============+
+   | ``vlan_pcp`` | VLAN priority |
+   +--------------+---------------+
+
+Action: ``OF_POP_MPLS``
+^^^^^^^^^^^^^^^^^^^^^^^
+
+Implements ``OFPAT_POP_MPLS`` ("pop the outer MPLS tag") as defined by the
+`OpenFlow Switch Specification`_.
+
+.. _table_rte_flow_action_of_pop_mpls:
+
+.. table:: OF_POP_MPLS
+
+   +---------------+-----------+
+   | Field         | Value     |
+   +===============+===========+
+   | ``ethertype`` | EtherType |
+   +---------------+-----------+
+
+Action: ``OF_PUSH_MPLS``
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+Implements ``OFPAT_PUSH_MPLS`` ("push a new MPLS tag") as defined by the
+`OpenFlow Switch Specification`_.
+
+.. _table_rte_flow_action_of_push_mpls:
+
+.. table:: OF_PUSH_MPLS
+
+   +---------------+-----------+
+   | Field         | Value     |
+   +===============+===========+
+   | ``ethertype`` | EtherType |
+   +---------------+-----------+
+
 Negative types
 ~~~~~~~~~~~~~~
 
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index c223a8a9f..381f781a5 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -3493,6 +3493,28 @@ This section lists supported actions and their attributes, if any.
 
 - ``of_copy_ttl_in``: OpenFlow's ``OFPAT_COPY_TTL_IN``.
 
+- ``of_pop_vlan``: OpenFlow's ``OFPAT_POP_VLAN``.
+
+- ``of_push_vlan``: OpenFlow's ``OFPAT_PUSH_VLAN``.
+
+  - ``ethertype``: Ethertype.
+
+- ``of_set_vlan_vid``: OpenFlow's ``OFPAT_SET_VLAN_VID``.
+
+  - ``vlan_vid``: VLAN id.
+
+- ``of_set_vlan_pcp``: OpenFlow's ``OFPAT_SET_VLAN_PCP``.
+
+  - ``vlan_pcp``: VLAN priority.
+
+- ``of_pop_mpls``: OpenFlow's ``OFPAT_POP_MPLS``.
+
+  - ``ethertype``: Ethertype.
+
+- ``of_push_mpls``: OpenFlow's ``OFPAT_PUSH_MPLS``.
+
+  - ``ethertype``: Ethertype.
+
 Destroying flow rules
 ~~~~~~~~~~~~~~~~~~~~~
 
diff --git a/lib/librte_ether/rte_flow.c b/lib/librte_ether/rte_flow.c
index e66cfb4c8..c1d88941a 100644
--- a/lib/librte_ether/rte_flow.c
+++ b/lib/librte_ether/rte_flow.c
@@ -97,6 +97,17 @@ static const struct rte_flow_desc_data rte_flow_desc_action[] = {
 	MK_FLOW_ACTION(OF_DEC_NW_TTL, 0),
 	MK_FLOW_ACTION(OF_COPY_TTL_OUT, 0),
 	MK_FLOW_ACTION(OF_COPY_TTL_IN, 0),
+	MK_FLOW_ACTION(OF_POP_VLAN, 0),
+	MK_FLOW_ACTION(OF_PUSH_VLAN,
+		       sizeof(struct rte_flow_action_of_push_vlan)),
+	MK_FLOW_ACTION(OF_SET_VLAN_VID,
+		       sizeof(struct rte_flow_action_of_set_vlan_vid)),
+	MK_FLOW_ACTION(OF_SET_VLAN_PCP,
+		       sizeof(struct rte_flow_action_of_set_vlan_pcp)),
+	MK_FLOW_ACTION(OF_POP_MPLS,
+		       sizeof(struct rte_flow_action_of_pop_mpls)),
+	MK_FLOW_ACTION(OF_PUSH_MPLS,
+		       sizeof(struct rte_flow_action_of_push_mpls)),
 };
 
 static int
diff --git a/lib/librte_ether/rte_flow.h b/lib/librte_ether/rte_flow.h
index e8b7ce84f..de34de80b 100644
--- a/lib/librte_ether/rte_flow.h
+++ b/lib/librte_ether/rte_flow.h
@@ -1356,6 +1356,54 @@ enum rte_flow_action_type {
 	 * No associated configuration structure.
 	 */
 	RTE_FLOW_ACTION_TYPE_OF_COPY_TTL_IN,
+
+	/**
+	 * Implements OFPAT_POP_VLAN ("pop the outer VLAN tag") as defined
+	 * by the OpenFlow Switch Specification.
+	 *
+	 * No associated configuration structure.
+	 */
+	RTE_FLOW_ACTION_TYPE_OF_POP_VLAN,
+
+	/**
+	 * Implements OFPAT_PUSH_VLAN ("push a new VLAN tag") as defined by
+	 * the OpenFlow Switch Specification.
+	 *
+	 * See struct rte_flow_action_of_push_vlan.
+	 */
+	RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN,
+
+	/**
+	 * Implements OFPAT_SET_VLAN_VID ("set the 802.1q VLAN id") as
+	 * defined by the OpenFlow Switch Specification.
+	 *
+	 * See struct rte_flow_action_of_set_vlan_vid.
+	 */
+	RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID,
+
+	/**
+	 * Implements OFPAT_SET_LAN_PCP ("set the 802.1q priority") as
+	 * defined by the OpenFlow Switch Specification.
+	 *
+	 * See struct rte_flow_action_of_set_vlan_pcp.
+	 */
+	RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP,
+
+	/**
+	 * Implements OFPAT_POP_MPLS ("pop the outer MPLS tag") as defined
+	 * by the OpenFlow Switch Specification.
+	 *
+	 * See struct rte_flow_action_of_pop_mpls.
+	 */
+	RTE_FLOW_ACTION_TYPE_OF_POP_MPLS,
+
+	/**
+	 * Implements OFPAT_PUSH_MPLS ("push a new MPLS tag") as defined by
+	 * the OpenFlow Switch Specification.
+	 *
+	 * See struct rte_flow_action_of_push_mpls.
+	 */
+	RTE_FLOW_ACTION_TYPE_OF_PUSH_MPLS,
 };
 
 /**
@@ -1553,6 +1601,56 @@ struct rte_flow_action_of_set_nw_ttl {
 };
 
 /**
+ * RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN
+ *
+ * Implements OFPAT_PUSH_VLAN ("push a new VLAN tag") as defined by the
+ * OpenFlow Switch Specification.
+ */
+struct rte_flow_action_of_push_vlan {
+	rte_be16_t ethertype; /**< EtherType. */
+};
+
+/**
+ * RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID
+ *
+ * Implements OFPAT_SET_VLAN_VID ("set the 802.1q VLAN id") as defined by
+ * the OpenFlow Switch Specification.
+ */
+struct rte_flow_action_of_set_vlan_vid {
+	rte_be16_t vlan_vid; /**< VLAN id. */
+};
+
+/**
+ * RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP
+ *
+ * Implements OFPAT_SET_LAN_PCP ("set the 802.1q priority") as defined by
+ * the OpenFlow Switch Specification.
+ */
+struct rte_flow_action_of_set_vlan_pcp {
+	uint8_t vlan_pcp; /**< VLAN priority. */
+};
+
+/**
+ * RTE_FLOW_ACTION_TYPE_OF_POP_MPLS
+ *
+ * Implements OFPAT_POP_MPLS ("pop the outer MPLS tag") as defined by the
+ * OpenFlow Switch Specification.
+ */
+struct rte_flow_action_of_pop_mpls {
+	rte_be16_t ethertype; /**< EtherType. */
+};
+
+/**
+ * RTE_FLOW_ACTION_TYPE_OF_PUSH_MPLS
+ *
+ * Implements OFPAT_PUSH_MPLS ("push a new MPLS tag") as defined by the
+ * OpenFlow Switch Specification.
+ */
+struct rte_flow_action_of_push_mpls {
+	rte_be16_t ethertype; /**< EtherType. */
+};
+
+/**
  * Definition of a single action.
  *
  * A list of actions is terminated by a END action.
-- 
2.11.0

^ permalink raw reply	[flat|nested] 61+ messages in thread

* Re: [dpdk-dev] [PATCH v5 0/3] rte_flow extension for vSwitch acceleration
  2018-04-24 15:58   ` [dpdk-dev] [PATCH v5 0/3] rte_flow extension for vSwitch acceleration Adrien Mazarguil
                       ` (2 preceding siblings ...)
  2018-04-24 15:59     ` [dpdk-dev] [PATCH v5 3/3] ethdev: add VLAN and MPLS " Adrien Mazarguil
@ 2018-04-25 13:54     ` Zhang, Qi Z
  2018-04-25 22:44       ` Ferruh Yigit
  3 siblings, 1 reply; 61+ messages in thread
From: Zhang, Qi Z @ 2018-04-25 13:54 UTC (permalink / raw)
  To: Adrien Mazarguil, Yigit, Ferruh
  Cc: dev, Doherty, Declan, Chandran, Sugesh, Glynn, Michael J, Liu,
	Yu Y, Ananyev, Konstantin, Richardson, Bruce

> -----Original Message-----
> From: Adrien Mazarguil [mailto:adrien.mazarguil@6wind.com]
> Sent: Tuesday, April 24, 2018 11:59 PM
> To: Yigit, Ferruh <ferruh.yigit@intel.com>; Zhang, Qi Z <qi.z.zhang@intel.com>
> Cc: dev@dpdk.org; Doherty, Declan <declan.doherty@intel.com>; Chandran,
> Sugesh <sugesh.chandran@intel.com>; Glynn, Michael J
> <michael.j.glynn@intel.com>; Liu, Yu Y <yu.y.liu@intel.com>; Ananyev,
> Konstantin <konstantin.ananyev@intel.com>; Richardson, Bruce
> <bruce.richardson@intel.com>
> Subject: [PATCH v5 0/3] rte_flow extension for vSwitch acceleration
> 
> v5 (Adrien):
> 
> While the previous version (v4) looked fine, I noticed several issues and
> inconsistencies while testing it. I decided to take over Qi Zhang's series to
> hasten things for RC1.

Acked-by: Qi Zhang <qi.z.zhang@intel.com>

Thanks for the help!

^ permalink raw reply	[flat|nested] 61+ messages in thread

* Re: [dpdk-dev] [PATCH v5 0/3] rte_flow extension for vSwitch acceleration
  2018-04-25 13:54     ` [dpdk-dev] [PATCH v5 0/3] rte_flow extension for vSwitch acceleration Zhang, Qi Z
@ 2018-04-25 22:44       ` Ferruh Yigit
  0 siblings, 0 replies; 61+ messages in thread
From: Ferruh Yigit @ 2018-04-25 22:44 UTC (permalink / raw)
  To: Zhang, Qi Z, Adrien Mazarguil
  Cc: dev, Doherty, Declan, Chandran, Sugesh, Glynn, Michael J, Liu,
	Yu Y, Ananyev, Konstantin, Richardson, Bruce

On 4/25/2018 2:54 PM, Zhang, Qi Z wrote:
>> -----Original Message-----
>> From: Adrien Mazarguil [mailto:adrien.mazarguil@6wind.com]
>> Sent: Tuesday, April 24, 2018 11:59 PM
>> To: Yigit, Ferruh <ferruh.yigit@intel.com>; Zhang, Qi Z <qi.z.zhang@intel.com>
>> Cc: dev@dpdk.org; Doherty, Declan <declan.doherty@intel.com>; Chandran,
>> Sugesh <sugesh.chandran@intel.com>; Glynn, Michael J
>> <michael.j.glynn@intel.com>; Liu, Yu Y <yu.y.liu@intel.com>; Ananyev,
>> Konstantin <konstantin.ananyev@intel.com>; Richardson, Bruce
>> <bruce.richardson@intel.com>
>> Subject: [PATCH v5 0/3] rte_flow extension for vSwitch acceleration
>>
>> v5 (Adrien):
>>
>> While the previous version (v4) looked fine, I noticed several issues and
>> inconsistencies while testing it. I decided to take over Qi Zhang's series to
>> hasten things for RC1.
> 
> Acked-by: Qi Zhang <qi.z.zhang@intel.com>

Series applied to dpdk-next-net/master, thanks.

^ permalink raw reply	[flat|nested] 61+ messages in thread

end of thread, other threads:[~2018-04-25 22:44 UTC | newest]

Thread overview: 61+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-03-28 23:29 [dpdk-dev] [PATCH 0/4] rte_flow extension for vSwitch acceleration Qi Zhang
2018-03-28 23:29 ` [dpdk-dev] [PATCH 1/4] ether: add flow action to redirect packet in a switch domain Qi Zhang
2018-03-29 10:48   ` Pattan, Reshma
2018-03-29 11:20   ` Pattan, Reshma
2018-03-28 23:29 ` [dpdk-dev] [PATCH 2/4] ether: add flow last hit query support Qi Zhang
2018-03-28 23:29 ` [dpdk-dev] [PATCH 3/4] ether: add more protocol support in flow API Qi Zhang
2018-03-29 14:32   ` Pattan, Reshma
2018-03-28 23:29 ` [dpdk-dev] [PATCH 4/4] ether: add packet modification aciton " Qi Zhang
2018-03-29 15:23   ` Pattan, Reshma
2018-04-02  3:35     ` Zhang, Qi Z
2018-04-01 21:19 ` [dpdk-dev] [PATCH v2 0/4] rte_flow extension for vSwitch acceleration Qi Zhang
2018-04-01 21:19   ` [dpdk-dev] [PATCH v2 1/4] ether: add flow action to redirect packet to a port Qi Zhang
2018-04-11 16:30     ` Adrien Mazarguil
2018-04-01 21:19   ` [dpdk-dev] [PATCH v2 2/4] ether: add flow last hit query support Qi Zhang
2018-04-11 16:31     ` Adrien Mazarguil
2018-04-01 21:19   ` [dpdk-dev] [PATCH v2 3/4] ether: add more protocol support in flow API Qi Zhang
2018-04-11 16:32     ` Adrien Mazarguil
2018-04-12  5:12       ` Zhang, Qi Z
2018-04-12  9:19         ` Adrien Mazarguil
2018-04-12 10:00           ` Zhang, Qi Z
2018-04-01 21:19   ` [dpdk-dev] [PATCH v2 4/4] ether: add packet modification aciton " Qi Zhang
2018-04-12  7:03     ` Adrien Mazarguil
2018-04-12  8:50       ` Zhang, Qi Z
2018-04-12 10:22         ` Adrien Mazarguil
2018-04-13 13:47           ` Zhang, Qi Z
2018-04-16 13:30             ` Adrien Mazarguil
2018-04-16 15:03               ` Zhang, Qi Z
2018-04-17  9:55                 ` Adrien Mazarguil
2018-04-17 10:32                   ` Zhang, Qi Z
2018-04-10 14:12   ` [dpdk-dev] [PATCH v2 0/4] rte_flow extension for vSwitch acceleration Thomas Monjalon
2018-04-16  5:16 ` [dpdk-dev] [PATCH v3 " Qi Zhang
2018-04-16  5:16   ` [dpdk-dev] [PATCH v3 1/4] ethdev: add more protocol support in flow API Qi Zhang
2018-04-16  5:16   ` [dpdk-dev] [PATCH v3 2/4] ethdev: add packet field set aciton " Qi Zhang
2018-04-16  5:16   ` [dpdk-dev] [PATCH v3 3/4] ethdev: add TTL change actions " Qi Zhang
2018-04-16  5:48     ` Shahaf Shuler
2018-04-16  8:12       ` Adrien Mazarguil
2018-04-16  8:56         ` Shahaf Shuler
2018-04-16  9:59           ` Adrien Mazarguil
2018-04-16  5:16   ` [dpdk-dev] [PATCH v3 4/4] ethdev: add VLAN and MPLS pop push action " Qi Zhang
2018-04-16  6:10 ` [dpdk-dev] [PATCH v3 0/4] rte_flow extension for vSwitch acceleration Qi Zhang
2018-04-16  6:10   ` [dpdk-dev] [PATCH v3 1/4] ethdev: add more protocol support in flow API Qi Zhang
2018-04-19 14:48     ` Adrien Mazarguil
2018-04-16  6:10   ` [dpdk-dev] [PATCH v3 2/4] ethdev: add packet field set aciton " Qi Zhang
2018-04-19 14:48     ` Adrien Mazarguil
2018-04-20  2:24       ` Zhang, Qi Z
2018-04-20  8:54         ` Adrien Mazarguil
2018-04-16  6:10   ` [dpdk-dev] [PATCH v3 3/4] ethdev: add TTL change actions " Qi Zhang
2018-04-19 14:48     ` Adrien Mazarguil
2018-04-16  6:10   ` [dpdk-dev] [PATCH v3 4/4] ethdev: add VLAN and MPLS pop push action " Qi Zhang
2018-04-17  7:34     ` Shahaf Shuler
2018-04-19 14:49     ` Adrien Mazarguil
2018-04-23  6:36 ` [dpdk-dev] [PATCH v4 0/3] rte_flow extension for vSwitch acceleration Qi Zhang
2018-04-23  6:36   ` [dpdk-dev] [PATCH v4 1/3] ethdev: add more protocol support in flow API Qi Zhang
2018-04-23  6:36   ` [dpdk-dev] [PATCH v4 2/3] ethdev: add TTL change actions " Qi Zhang
2018-04-23  6:36   ` [dpdk-dev] [PATCH v4 3/3] ethdev: add VLAN and MPLS " Qi Zhang
2018-04-24 15:58   ` [dpdk-dev] [PATCH v5 0/3] rte_flow extension for vSwitch acceleration Adrien Mazarguil
2018-04-24 15:58     ` [dpdk-dev] [PATCH v5 1/3] ethdev: add neighbor discovery support to flow API Adrien Mazarguil
2018-04-24 15:59     ` [dpdk-dev] [PATCH v5 2/3] ethdev: add TTL change actions " Adrien Mazarguil
2018-04-24 15:59     ` [dpdk-dev] [PATCH v5 3/3] ethdev: add VLAN and MPLS " Adrien Mazarguil
2018-04-25 13:54     ` [dpdk-dev] [PATCH v5 0/3] rte_flow extension for vSwitch acceleration Zhang, Qi Z
2018-04-25 22:44       ` Ferruh Yigit

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).