diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c
index 495871394..79bce43e7 100644
--- a/app/test-pmd/cmdline_flow.c
+++ b/app/test-pmd/cmdline_flow.c
@@ -167,6 +167,13 @@ enum index {
 	ITEM_GTP_TEID,
 	ITEM_GTPC,
 	ITEM_GTPU,
+	ITEM_GTP_PSC,
+	ITEM_GTP_PSC_QFI,
+	ITEM_GTP_PSC_PDU_T,
+	ITEM_PPPOES,
+	ITEM_PPPOED,
+	ITEM_PPPOE_SEID,
+	ITEM_PPPOE_PROTO,
 	ITEM_GENEVE,
 	ITEM_GENEVE_VNI,
 	ITEM_GENEVE_PROTO,
@@ -651,6 +658,9 @@ static const enum index next_item[] = {
 	ITEM_GTP,
 	ITEM_GTPC,
 	ITEM_GTPU,
+	ITEM_GTP_PSC,
+	ITEM_PPPOES,
+	ITEM_PPPOED,
 	ITEM_GENEVE,
 	ITEM_VXLAN_GPE,
 	ITEM_ARP_ETH_IPV4,
@@ -831,6 +841,20 @@ static const enum index item_gtp[] = {
 	ZERO,
 };
 
+static const enum index item_gtp_psc[] = {
+	ITEM_GTP_PSC_QFI,
+	ITEM_GTP_PSC_PDU_T,
+	ITEM_NEXT,
+	ZERO,
+};
+
+static const enum index item_pppoe[] = {
+	ITEM_PPPOE_SEID,
+	ITEM_PPPOE_PROTO,
+	ITEM_NEXT,
+	ZERO,
+};
+
 static const enum index item_geneve[] = {
 	ITEM_GENEVE_VNI,
 	ITEM_GENEVE_PROTO,
@@ -2108,6 +2132,56 @@ static const struct token token_list[] = {
 		.next = NEXT(item_gtp),
 		.call = parse_vc,
 	},
+	[ITEM_GTP_PSC] = {
+		.name = "gtp_psc",
+		.help = "match GTP extension header (type is 0x85)",
+		.priv = PRIV_ITEM(GTP_PSC,
+				sizeof(struct rte_flow_item_gtp_psc)),
+		.next = NEXT(item_gtp_psc),
+		.call = parse_vc,
+	},
+	[ITEM_GTP_PSC_QFI] = {
+		.name = "qfi",
+		.help = "QoS flow identifier",
+		.next = NEXT(item_gtp_psc, NEXT_ENTRY(UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gtp_psc,
+					qfi)),
+	},
+	[ITEM_GTP_PSC_PDU_T] = {
+		.name = "pdu_t",
+		.help = "PDU type",
+		.next = NEXT(item_gtp_psc, NEXT_ENTRY(UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gtp_psc,
+					pdu_type)),
+	},
+	[ITEM_PPPOES] = {
+		.name = "pppoes",
+		.help = "match PPPoE Session header",
+		.priv = PRIV_ITEM(PPPOES, sizeof(struct rte_flow_item_pppoe)),
+		.next = NEXT(item_pppoe),
+		.call = parse_vc,
+	},
+	[ITEM_PPPOED] = {
+		.name = "pppoed",
+		.help = "match PPPoE Discovery stage header",
+		.priv = PRIV_ITEM(PPPOED, sizeof(struct rte_flow_item_pppoe)),
+		.next = NEXT(item_pppoe),
+		.call = parse_vc,
+	},
+	[ITEM_PPPOE_SEID] = {
+		.name = "seid",
+		.help = "Session identifier",
+		.next = NEXT(item_pppoe, NEXT_ENTRY(UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pppoe,
+					session_id)),
+	},
+	[ITEM_PPPOE_PROTO] = {
+		.name = "proto_id",
+		.help = "PPPOE protocol identifier",
+		.next = NEXT(item_pppoe, NEXT_ENTRY(UNSIGNED), item_param),
+		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_pppoe,
+					proto_id)),
+	},
 	[ITEM_GENEVE] = {
 		.name = "geneve",
 		.help = "match GENEVE header",
@@ -5753,6 +5827,12 @@ flow_item_default_mask(const struct rte_flow_item *item)
 	case RTE_FLOW_ITEM_TYPE_GTP:
 		mask = &rte_flow_item_gtp_mask;
 		break;
+	case RTE_FLOW_ITEM_TYPE_GTP_PSC:
+		mask = &rte_flow_item_gtp_psc_mask;
+		break;
+	case RTE_FLOW_ITEM_TYPE_PPPOES:
+		mask = &rte_flow_item_pppoe_mask;
+		break;
 	case RTE_FLOW_ITEM_TYPE_ESP:
 		mask = &rte_flow_item_esp_mask;
 		break;
diff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst
index 821b524b3..d09c42071 100644
--- a/doc/guides/prog_guide/rte_flow.rst
+++ b/doc/guides/prog_guide/rte_flow.rst
@@ -1055,6 +1055,31 @@ flow rules.
 - ``teid``: tunnel endpoint identifier.
 - Default ``mask`` matches teid only.
 
+Item: ``GTP_PSC``
+^^^^^^^^^^^^^^^^^^^^^^^
+
+Matches a GTP Extension header (type is 0x85).
+
+- ``pdu_type``: PDU type.
+- ``qfi``: QoS flow identifier.
+- Default ``mask`` matches QFI only.
+
+Item: ``PPPOES``, ``PPPOED``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Matches a PPPOE header.
+
+Note: PPPOES and PPPOED use the same structure. PPPOES and PPPOED item
+are defined for a user-friendly API when creating PPPOE-Session and
+PPPOE-Discovery flow rules.
+
+- ``v_t_flags``: version (4b), type (4b).
+- ``code``: Message type.
+- ``session_id``: Session identifier.
+- ``length``: Payload length.
+- ``proto_id``: PPP Protocol identifier.
+- Default ``mask`` matches session_id,proto_id.
+
 Item: ``ESP``
 ^^^^^^^^^^^^^
 
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index 313e0707e..0da36d5f1 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -3904,6 +3904,16 @@ This section lists supported pattern items and their attributes, if any.
 
   - ``teid {unsigned}``: tunnel endpoint identifier.
 
+- ``gtp_psc``: match GTPv1 entension header (type is 0x85).
+
+  - ``pdu_type {unsigned}``: PDU type (0 or 1).
+  - ``qfi {unsigned}``: QoS flow identifier.
+
+- ``pppoes``, ``pppoed``: match PPPOE header.
+
+  - ``session_id {unsigned}``: Session identifier.
+  - ``proto_id {unsigned}``: PPP Protocol identifier.
+
 - ``geneve``: match GENEVE header.
 
   - ``vni {unsigned}``: virtual network identifier.
diff --git a/lib/librte_ethdev/rte_flow.c b/lib/librte_ethdev/rte_flow.c
index 18fcb018e..246390da3 100644
--- a/lib/librte_ethdev/rte_flow.c
+++ b/lib/librte_ethdev/rte_flow.c
@@ -59,6 +59,9 @@ static const struct rte_flow_desc_data rte_flow_desc_item[] = {
 	MK_FLOW_ITEM(GTP, sizeof(struct rte_flow_item_gtp)),
 	MK_FLOW_ITEM(GTPC, sizeof(struct rte_flow_item_gtp)),
 	MK_FLOW_ITEM(GTPU, sizeof(struct rte_flow_item_gtp)),
+	MK_FLOW_ITEM(GTP_PSC, sizeof(struct rte_flow_item_gtp_psc)),
+	MK_FLOW_ITEM(PPPOES, sizeof(struct rte_flow_item_pppoe)),
+	MK_FLOW_ITEM(PPPOED, sizeof(struct rte_flow_item_pppoe)),
 	MK_FLOW_ITEM(ESP, sizeof(struct rte_flow_item_esp)),
 	MK_FLOW_ITEM(GENEVE, sizeof(struct rte_flow_item_geneve)),
 	MK_FLOW_ITEM(VXLAN_GPE, sizeof(struct rte_flow_item_vxlan_gpe)),
diff --git a/lib/librte_ethdev/rte_flow.h b/lib/librte_ethdev/rte_flow.h
index b66bf1495..ad5e46190 100644
--- a/lib/librte_ethdev/rte_flow.h
+++ b/lib/librte_ethdev/rte_flow.h
@@ -328,6 +328,34 @@ enum rte_flow_item_type {
 	 */
 	RTE_FLOW_ITEM_TYPE_GTPU,
 
+	/**
+	 * Matches a GTP PDU extension header (type is 0x85:
+	 * PDU Session Container).
+	 *
+	 * Configure flow for GTP packets with extension header type 0x85.
+	 *
+	 * See struct rte_flow_item_gtp_psc.
+	 */
+	RTE_FLOW_ITEM_TYPE_GTP_PSC,
+
+	/**
+	 * Matches a PPPOE header.
+	 *
+	 * Configure flow for PPPoE Session packets.
+	 *
+	 * See struct rte_flow_item_pppoe.
+	 */
+	RTE_FLOW_ITEM_TYPE_PPPOES,
+
+	/**
+	 * Matches a PPPOE header.
+	 *
+	 * Configure flow for PPPoE Discovery stage packets.
+	 *
+	 * See struct rte_flow_item_pppoe.
+	 */
+	RTE_FLOW_ITEM_TYPE_PPPOED,
+
 	/**
 	 * Matches a ESP header.
 	 *
@@ -922,6 +950,49 @@ static const struct rte_flow_item_gtp rte_flow_item_gtp_mask = {
 };
 #endif
 
+/**
+ * RTE_FLOW_ITEM_TYPE_GTP_PSC.
+ *
+ * Matches a GTP-extension header
+ * (type is 0x85: PDU Session Container).
+ */
+struct rte_flow_item_gtp_psc {
+	uint8_t pdu_type; /**< PDU type (0 or 1). */
+	uint8_t qfi; /**< QoS flow identifier. */
+};
+
+/** Default mask for RTE_FLOW_ITEM_TYPE_GTP_PSC. */
+#ifndef __cplusplus
+static const struct rte_flow_item_gtp_psc
+rte_flow_item_gtp_psc_mask = {
+	.qfi = 0x3f,
+};
+#endif
+
+/**
+ * RTE_FLOW_ITEM_TYPE_PPPOE.
+ *
+ * Matches a PPPOE header.
+ */
+struct rte_flow_item_pppoe {
+	/**
+	 * Version (4b), type (4b).
+	 */
+	uint8_t v_t_flags;
+	uint8_t code; /**< Message type. */
+	rte_be16_t session_id; /**< Session identifier. */
+	rte_be16_t length; /**< Payload length. */
+	rte_be16_t proto_id; /**< PPP Protocol identifier. */
+};
+
+/** Default mask for RTE_FLOW_ITEM_TYPE_PPPOE. */
+#ifndef __cplusplus
+static const struct rte_flow_item_pppoe rte_flow_item_pppoe_mask = {
+	.session_id = RTE_BE16(0xffff),
+	.proto_id = RTE_BE16(0xffff),
+};
+#endif
+
 /**
  * RTE_FLOW_ITEM_TYPE_ESP
  *
