diff --git a/app/test-flow-perf/items_gen.c b/app/test-flow-perf/items_gen.c
index a58245239ba1..85928349eee0 100644
--- a/app/test-flow-perf/items_gen.c
+++ b/app/test-flow-perf/items_gen.c
@@ -213,10 +213,10 @@ add_gtp(struct rte_flow_item *items,
 	__rte_unused struct additional_para para)
 {
 	static struct rte_flow_item_gtp gtp_spec = {
-		.teid = RTE_BE32(TEID_VALUE),
+		.hdr.teid = RTE_BE32(TEID_VALUE),
 	};
 	static struct rte_flow_item_gtp gtp_mask = {
-		.teid = RTE_BE32(0xffffffff),
+		.hdr.teid = RTE_BE32(0xffffffff),
 	};
 
 	items[items_counter].type = RTE_FLOW_ITEM_TYPE_GTP;
diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c
index b904f8c3d45c..429d9cab8217 100644
--- a/app/test-pmd/cmdline_flow.c
+++ b/app/test-pmd/cmdline_flow.c
@@ -4137,19 +4137,19 @@ static const struct token token_list[] = {
 		.help = "GTP flags",
 		.next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
 		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_gtp,
-					v_pt_rsv_flags)),
+					hdr.gtp_hdr_info)),
 	},
 	[ITEM_GTP_MSG_TYPE] = {
 		.name = "msg_type",
 		.help = "GTP message type",
 		.next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
-		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_gtp, msg_type)),
+		.args = ARGS(ARGS_ENTRY(struct rte_flow_item_gtp, hdr.msg_type)),
 	},
 	[ITEM_GTP_TEID] = {
 		.name = "teid",
 		.help = "tunnel endpoint identifier",
 		.next = NEXT(item_gtp, NEXT_ENTRY(COMMON_UNSIGNED), item_param),
-		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gtp, teid)),
+		.args = ARGS(ARGS_ENTRY_HTON(struct rte_flow_item_gtp, hdr.teid)),
 	},
 	[ITEM_GTPC] = {
 		.name = "gtpc",
@@ -11224,7 +11224,7 @@ cmd_set_raw_parsed(const struct buffer *in)
 				goto error;
 			}
 			gtp = item->spec;
-			if ((gtp->v_pt_rsv_flags & 0x07) != 0x04) {
+			if (gtp->hdr.s == 1 || gtp->hdr.pn == 1) {
 				/* Only E flag should be set. */
 				fprintf(stderr,
 					"Error - GTP unsupported flags\n");
diff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst
index 116722351486..c4b96b5d324b 100644
--- a/doc/guides/prog_guide/rte_flow.rst
+++ b/doc/guides/prog_guide/rte_flow.rst
@@ -1068,12 +1068,7 @@ Note: GTP, GTPC and GTPU use the same structure. GTPC and GTPU item
 are defined for a user-friendly API when creating GTP-C and GTP-U
 flow rules.
 
-- ``v_pt_rsv_flags``: version (3b), protocol type (1b), reserved (1b),
-  extension header flag (1b), sequence number flag (1b), N-PDU number
-  flag (1b).
-- ``msg_type``: message type.
-- ``msg_len``: message length.
-- ``teid``: tunnel endpoint identifier.
+- ``hdr``:  header definition (``rte_gtp.h``).
 - Default ``mask`` matches teid only.
 
 Item: ``ESP``
@@ -1239,8 +1234,7 @@ Item: ``GTP_PSC``
 
 Matches a GTP PDU extension header with type 0x85.
 
-- ``pdu_type``: PDU type.
-- ``qfi``: QoS flow identifier.
+- ``hdr``:  header definition (``rte_gtp.h``).
 - Default ``mask`` matches QFI only.
 
 Item: ``PPPOES``, ``PPPOED``
diff --git a/doc/guides/rel_notes/deprecation.rst b/doc/guides/rel_notes/deprecation.rst
index df8b5bcb1b64..838d5854ad9b 100644
--- a/doc/guides/rel_notes/deprecation.rst
+++ b/doc/guides/rel_notes/deprecation.rst
@@ -74,7 +74,6 @@ Deprecation Notices
   - ``rte_flow_item_geneve``
   - ``rte_flow_item_geneve_opt``
   - ``rte_flow_item_gre``
-  - ``rte_flow_item_gtp``
   - ``rte_flow_item_icmp6``
   - ``rte_flow_item_icmp6_nd_na``
   - ``rte_flow_item_icmp6_nd_ns``
diff --git a/drivers/net/i40e/i40e_fdir.c b/drivers/net/i40e/i40e_fdir.c
index afcaa593eb58..47f79ecf11cc 100644
--- a/drivers/net/i40e/i40e_fdir.c
+++ b/drivers/net/i40e/i40e_fdir.c
@@ -761,26 +761,26 @@ i40e_flow_fdir_construct_pkt(struct i40e_pf *pf,
 			gtp = (struct rte_flow_item_gtp *)
 				((unsigned char *)udp +
 					sizeof(struct rte_udp_hdr));
-			gtp->msg_len =
+			gtp->hdr.plen =
 				rte_cpu_to_be_16(I40E_FDIR_GTP_DEFAULT_LEN);
-			gtp->teid = fdir_input->flow.gtp_flow.teid;
-			gtp->msg_type = I40E_FDIR_GTP_MSG_TYPE_0X01;
+			gtp->hdr.teid = fdir_input->flow.gtp_flow.teid;
+			gtp->hdr.msg_type = I40E_FDIR_GTP_MSG_TYPE_0X01;
 
 			/* GTP-C message type is not supported. */
 			if (cus_pctype->index == I40E_CUSTOMIZED_GTPC) {
 				udp->dst_port =
 				      rte_cpu_to_be_16(I40E_FDIR_GTPC_DST_PORT);
-				gtp->v_pt_rsv_flags =
+				gtp->hdr.gtp_hdr_info =
 					I40E_FDIR_GTP_VER_FLAG_0X32;
 			} else {
 				udp->dst_port =
 				      rte_cpu_to_be_16(I40E_FDIR_GTPU_DST_PORT);
-				gtp->v_pt_rsv_flags =
+				gtp->hdr.gtp_hdr_info =
 					I40E_FDIR_GTP_VER_FLAG_0X30;
 			}
 
 			if (cus_pctype->index == I40E_CUSTOMIZED_GTPU_IPV4) {
-				gtp->msg_type = I40E_FDIR_GTP_MSG_TYPE_0XFF;
+				gtp->hdr.msg_type = I40E_FDIR_GTP_MSG_TYPE_0XFF;
 				gtp_ipv4 = (struct rte_ipv4_hdr *)
 					((unsigned char *)gtp +
 					 sizeof(struct rte_flow_item_gtp));
@@ -794,7 +794,7 @@ i40e_flow_fdir_construct_pkt(struct i40e_pf *pf,
 					sizeof(struct rte_ipv4_hdr);
 			} else if (cus_pctype->index ==
 				   I40E_CUSTOMIZED_GTPU_IPV6) {
-				gtp->msg_type = I40E_FDIR_GTP_MSG_TYPE_0XFF;
+				gtp->hdr.msg_type = I40E_FDIR_GTP_MSG_TYPE_0XFF;
 				gtp_ipv6 = (struct rte_ipv6_hdr *)
 					((unsigned char *)gtp +
 					 sizeof(struct rte_flow_item_gtp));
diff --git a/drivers/net/i40e/i40e_flow.c b/drivers/net/i40e/i40e_flow.c
index 2855b14fe679..3c550733f2bb 100644
--- a/drivers/net/i40e/i40e_flow.c
+++ b/drivers/net/i40e/i40e_flow.c
@@ -2135,10 +2135,10 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev,
 			gtp_mask = item->mask;
 
 			if (gtp_spec && gtp_mask) {
-				if (gtp_mask->v_pt_rsv_flags ||
-				    gtp_mask->msg_type ||
-				    gtp_mask->msg_len ||
-				    gtp_mask->teid != UINT32_MAX) {
+				if (gtp_mask->hdr.gtp_hdr_info ||
+				    gtp_mask->hdr.msg_type ||
+				    gtp_mask->hdr.plen ||
+				    gtp_mask->hdr.teid != UINT32_MAX) {
 					rte_flow_error_set(error, EINVAL,
 						   RTE_FLOW_ERROR_TYPE_ITEM,
 						   item,
@@ -2147,7 +2147,7 @@ i40e_flow_parse_fdir_pattern(struct rte_eth_dev *dev,
 				}
 
 				filter->input.flow.gtp_flow.teid =
-					gtp_spec->teid;
+					gtp_spec->hdr.teid;
 				filter->input.flow_ext.customized_pctype = true;
 				cus_proto = item_type;
 			}
@@ -3570,10 +3570,10 @@ i40e_flow_parse_gtp_pattern(struct rte_eth_dev *dev,
 				return -rte_errno;
 			}
 
-			if (gtp_mask->v_pt_rsv_flags ||
-			    gtp_mask->msg_type ||
-			    gtp_mask->msg_len ||
-			    gtp_mask->teid != UINT32_MAX) {
+			if (gtp_mask->hdr.gtp_hdr_info ||
+			    gtp_mask->hdr.msg_type ||
+			    gtp_mask->hdr.plen ||
+			    gtp_mask->hdr.teid != UINT32_MAX) {
 				rte_flow_error_set(error, EINVAL,
 						   RTE_FLOW_ERROR_TYPE_ITEM,
 						   item,
@@ -3586,7 +3586,7 @@ i40e_flow_parse_gtp_pattern(struct rte_eth_dev *dev,
 			else if (item_type == RTE_FLOW_ITEM_TYPE_GTPU)
 				filter->tunnel_type = I40E_TUNNEL_TYPE_GTPU;
 
-			filter->tenant_id = rte_be_to_cpu_32(gtp_spec->teid);
+			filter->tenant_id = rte_be_to_cpu_32(gtp_spec->hdr.teid);
 
 			break;
 		default:
diff --git a/drivers/net/iavf/iavf_fdir.c b/drivers/net/iavf/iavf_fdir.c
index a6c88cb55b88..811a10287b70 100644
--- a/drivers/net/iavf/iavf_fdir.c
+++ b/drivers/net/iavf/iavf_fdir.c
@@ -1277,16 +1277,16 @@ iavf_fdir_parse_pattern(__rte_unused struct iavf_adapter *ad,
 			VIRTCHNL_SET_PROTO_HDR_TYPE(hdr, GTPU_IP);
 
 			if (gtp_spec && gtp_mask) {
-				if (gtp_mask->v_pt_rsv_flags ||
-					gtp_mask->msg_type ||
-					gtp_mask->msg_len) {
+				if (gtp_mask->hdr.gtp_hdr_info ||
+					gtp_mask->hdr.msg_type ||
+					gtp_mask->hdr.plen) {
 					rte_flow_error_set(error, EINVAL,
 						RTE_FLOW_ERROR_TYPE_ITEM,
 						item, "Invalid GTP mask");
 					return -rte_errno;
 				}
 
-				if (gtp_mask->teid == UINT32_MAX) {
+				if (gtp_mask->hdr.teid == UINT32_MAX) {
 					input_set |= IAVF_INSET_GTPU_TEID;
 					VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(hdr, GTPU_IP, TEID);
 				}
diff --git a/drivers/net/ice/ice_fdir_filter.c b/drivers/net/ice/ice_fdir_filter.c
index 5d297afc290e..480b369af816 100644
--- a/drivers/net/ice/ice_fdir_filter.c
+++ b/drivers/net/ice/ice_fdir_filter.c
@@ -2341,9 +2341,9 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 			if (!(gtp_spec && gtp_mask))
 				break;
 
-			if (gtp_mask->v_pt_rsv_flags ||
-			    gtp_mask->msg_type ||
-			    gtp_mask->msg_len) {
+			if (gtp_mask->hdr.gtp_hdr_info ||
+			    gtp_mask->hdr.msg_type ||
+			    gtp_mask->hdr.plen) {
 				rte_flow_error_set(error, EINVAL,
 						   RTE_FLOW_ERROR_TYPE_ITEM,
 						   item,
@@ -2351,10 +2351,10 @@ ice_fdir_parse_pattern(__rte_unused struct ice_adapter *ad,
 				return -rte_errno;
 			}
 
-			if (gtp_mask->teid == UINT32_MAX)
+			if (gtp_mask->hdr.teid == UINT32_MAX)
 				input_set_o |= ICE_INSET_GTPU_TEID;
 
-			filter->input.gtpu_data.teid = gtp_spec->teid;
+			filter->input.gtpu_data.teid = gtp_spec->hdr.teid;
 			break;
 		case RTE_FLOW_ITEM_TYPE_GTP_PSC:
 			tunnel_type = ICE_FDIR_TUNNEL_TYPE_GTPU_EH;
diff --git a/drivers/net/ice/ice_switch_filter.c b/drivers/net/ice/ice_switch_filter.c
index 7cb20fa0b4f8..110d8895fea3 100644
--- a/drivers/net/ice/ice_switch_filter.c
+++ b/drivers/net/ice/ice_switch_filter.c
@@ -1405,9 +1405,9 @@ ice_switch_parse_pattern(const struct rte_flow_item pattern[],
 				return false;
 			}
 			if (gtp_spec && gtp_mask) {
-				if (gtp_mask->v_pt_rsv_flags ||
-				    gtp_mask->msg_type ||
-				    gtp_mask->msg_len) {
+				if (gtp_mask->hdr.gtp_hdr_info ||
+				    gtp_mask->hdr.msg_type ||
+				    gtp_mask->hdr.plen) {
 					rte_flow_error_set(error, EINVAL,
 						RTE_FLOW_ERROR_TYPE_ITEM,
 						item,
@@ -1415,13 +1415,13 @@ ice_switch_parse_pattern(const struct rte_flow_item pattern[],
 					return false;
 				}
 				input = &outer_input_set;
-				if (gtp_mask->teid)
+				if (gtp_mask->hdr.teid)
 					*input |= ICE_INSET_GTPU_TEID;
 				list[t].type = ICE_GTP;
 				list[t].h_u.gtp_hdr.teid =
-					gtp_spec->teid;
+					gtp_spec->hdr.teid;
 				list[t].m_u.gtp_hdr.teid =
-					gtp_mask->teid;
+					gtp_mask->hdr.teid;
 				input_set_byte += 4;
 				t++;
 			}
diff --git a/drivers/net/mlx5/hws/mlx5dr_definer.c b/drivers/net/mlx5/hws/mlx5dr_definer.c
index 604384a24253..fbcfe3665748 100644
--- a/drivers/net/mlx5/hws/mlx5dr_definer.c
+++ b/drivers/net/mlx5/hws/mlx5dr_definer.c
@@ -145,9 +145,9 @@ struct mlx5dr_definer_conv_data {
 	X(SET_BE16,	tcp_src_port,		v->hdr.src_port,	rte_flow_item_tcp) \
 	X(SET_BE16,	tcp_dst_port,		v->hdr.dst_port,	rte_flow_item_tcp) \
 	X(SET,		gtp_udp_port,		RTE_GTPU_UDP_PORT,	rte_flow_item_gtp) \
-	X(SET_BE32,	gtp_teid,		v->teid,		rte_flow_item_gtp) \
-	X(SET,		gtp_msg_type,		v->msg_type,		rte_flow_item_gtp) \
-	X(SET,		gtp_ext_flag,		!!v->v_pt_rsv_flags,	rte_flow_item_gtp) \
+	X(SET_BE32,	gtp_teid,		v->hdr.teid,		rte_flow_item_gtp) \
+	X(SET,		gtp_msg_type,		v->hdr.msg_type,	rte_flow_item_gtp) \
+	X(SET,		gtp_ext_flag,		!!v->hdr.gtp_hdr_info,	rte_flow_item_gtp) \
 	X(SET,		gtp_next_ext_hdr,	GTP_PDU_SC,		rte_flow_item_gtp_psc) \
 	X(SET,		gtp_ext_hdr_pdu,	v->hdr.type,		rte_flow_item_gtp_psc) \
 	X(SET,		gtp_ext_hdr_qfi,	v->hdr.qfi,		rte_flow_item_gtp_psc) \
@@ -830,12 +830,12 @@ mlx5dr_definer_conv_item_gtp(struct mlx5dr_definer_conv_data *cd,
 	if (!m)
 		return 0;
 
-	if (m->msg_len || m->v_pt_rsv_flags & ~MLX5DR_DEFINER_GTP_EXT_HDR_BIT) {
+	if (m->hdr.plen || m->hdr.gtp_hdr_info & ~MLX5DR_DEFINER_GTP_EXT_HDR_BIT) {
 		rte_errno = ENOTSUP;
 		return rte_errno;
 	}
 
-	if (m->teid) {
+	if (m->hdr.teid) {
 		if (!(cd->caps->flex_protocols & MLX5_HCA_FLEX_GTPU_TEID_ENABLED)) {
 			rte_errno = ENOTSUP;
 			return rte_errno;
@@ -847,7 +847,7 @@ mlx5dr_definer_conv_item_gtp(struct mlx5dr_definer_conv_data *cd,
 		fc->byte_off = cd->caps->format_select_gtpu_dw_1 * DW_SIZE;
 	}
 
-	if (m->v_pt_rsv_flags) {
+	if (m->hdr.gtp_hdr_info) {
 		if (!(cd->caps->flex_protocols & MLX5_HCA_FLEX_GTPU_DW_0_ENABLED)) {
 			rte_errno = ENOTSUP;
 			return rte_errno;
@@ -861,7 +861,7 @@ mlx5dr_definer_conv_item_gtp(struct mlx5dr_definer_conv_data *cd,
 	}
 
 
-	if (m->msg_type) {
+	if (m->hdr.msg_type) {
 		if (!(cd->caps->flex_protocols & MLX5_HCA_FLEX_GTPU_DW_0_ENABLED)) {
 			rte_errno = ENOTSUP;
 			return rte_errno;
diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index 261c60a5c33a..54cd4ca7344c 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -2458,9 +2458,9 @@ flow_dv_validate_item_gtp(struct rte_eth_dev *dev,
 	const struct rte_flow_item_gtp *spec = item->spec;
 	const struct rte_flow_item_gtp *mask = item->mask;
 	const struct rte_flow_item_gtp nic_mask = {
-		.v_pt_rsv_flags = MLX5_GTP_FLAGS_MASK,
-		.msg_type = 0xff,
-		.teid = RTE_BE32(0xffffffff),
+		.hdr.gtp_hdr_info = MLX5_GTP_FLAGS_MASK,
+		.hdr.msg_type = 0xff,
+		.hdr.teid = RTE_BE32(0xffffffff),
 	};
 
 	if (!priv->sh->cdev->config.hca_attr.tunnel_stateless_gtp)
@@ -2478,7 +2478,7 @@ flow_dv_validate_item_gtp(struct rte_eth_dev *dev,
 					  "no outer UDP layer found");
 	if (!mask)
 		mask = &rte_flow_item_gtp_mask;
-	if (spec && spec->v_pt_rsv_flags & ~MLX5_GTP_FLAGS_MASK)
+	if (spec && spec->hdr.gtp_hdr_info & ~MLX5_GTP_FLAGS_MASK)
 		return rte_flow_error_set(error, ENOTSUP,
 					  RTE_FLOW_ERROR_TYPE_ITEM, item,
 					  "Match is supported for GTP"
@@ -2529,8 +2529,8 @@ flow_dv_validate_item_gtp_psc(const struct rte_flow_item *item,
 	gtp_mask = gtp_item->mask ? gtp_item->mask : &rte_flow_item_gtp_mask;
 	/* GTP spec and E flag is requested to match zero. */
 	if (gtp_spec &&
-		(gtp_mask->v_pt_rsv_flags &
-		~gtp_spec->v_pt_rsv_flags & MLX5_GTP_EXT_HEADER_FLAG))
+		(gtp_mask->hdr.gtp_hdr_info &
+		~gtp_spec->hdr.gtp_hdr_info & MLX5_GTP_EXT_HEADER_FLAG))
 		return rte_flow_error_set
 			(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM, item,
 			 "GTP E flag must be 1 to match GTP PSC");
@@ -9318,7 +9318,7 @@ flow_dv_translate_item_vxlan_gpe(void *key, const struct rte_flow_item *item,
 				 const uint64_t pattern_flags,
 				 uint32_t key_type)
 {
-	static const struct rte_flow_item_vxlan_gpe dummy_vxlan_gpe_hdr = {0, };
+	static const struct rte_flow_item_vxlan_gpe dummy_vxlan_gpe_hdr = {{{0}}};
 	const struct rte_flow_item_vxlan_gpe *vxlan_m = item->mask;
 	const struct rte_flow_item_vxlan_gpe *vxlan_v = item->spec;
 	/* The item was validated to be on the outer side */
@@ -10356,11 +10356,11 @@ flow_dv_translate_item_gtp(void *key, const struct rte_flow_item *item,
 	MLX5_ITEM_UPDATE(item, key_type, gtp_v, gtp_m,
 		&rte_flow_item_gtp_mask);
 	MLX5_SET(fte_match_set_misc3, misc3_v, gtpu_msg_flags,
-		 gtp_v->v_pt_rsv_flags & gtp_m->v_pt_rsv_flags);
+		 gtp_v->hdr.gtp_hdr_info & gtp_m->hdr.gtp_hdr_info);
 	MLX5_SET(fte_match_set_misc3, misc3_v, gtpu_msg_type,
-		 gtp_v->msg_type & gtp_m->msg_type);
+		 gtp_v->hdr.msg_type & gtp_m->hdr.msg_type);
 	MLX5_SET(fte_match_set_misc3, misc3_v, gtpu_teid,
-		 rte_be_to_cpu_32(gtp_v->teid & gtp_m->teid));
+		 rte_be_to_cpu_32(gtp_v->hdr.teid & gtp_m->hdr.teid));
 }
 
 /**
diff --git a/lib/ethdev/rte_flow.h b/lib/ethdev/rte_flow.h
index e2364823d622..8e8925277eb3 100644
--- a/lib/ethdev/rte_flow.h
+++ b/lib/ethdev/rte_flow.h
@@ -1139,23 +1139,33 @@ static const struct rte_flow_item_fuzzy rte_flow_item_fuzzy_mask = {
  *
  * Matches a GTPv1 header.
  */
+RTE_STD_C11
 struct rte_flow_item_gtp {
-	/**
-	 * Version (3b), protocol type (1b), reserved (1b),
-	 * Extension header flag (1b),
-	 * Sequence number flag (1b),
-	 * N-PDU number flag (1b).
-	 */
-	uint8_t v_pt_rsv_flags;
-	uint8_t msg_type; /**< Message type. */
-	rte_be16_t msg_len; /**< Message length. */
-	rte_be32_t teid; /**< Tunnel endpoint identifier. */
+	union {
+		struct {
+			/*
+			 * These are old fields kept for compatibility.
+			 * Please prefer hdr field below.
+			 */
+			/**
+			 * Version (3b), protocol type (1b), reserved (1b),
+			 * Extension header flag (1b),
+			 * Sequence number flag (1b),
+			 * N-PDU number flag (1b).
+			 */
+			uint8_t v_pt_rsv_flags;
+			uint8_t msg_type; /**< Message type. */
+			rte_be16_t msg_len; /**< Message length. */
+			rte_be32_t teid; /**< Tunnel endpoint identifier. */
+		};
+		struct rte_gtp_hdr hdr; /**< GTP header definition. */
+	};
 };
 
 /** Default mask for RTE_FLOW_ITEM_TYPE_GTP. */
 #ifndef __cplusplus
 static const struct rte_flow_item_gtp rte_flow_item_gtp_mask = {
-	.teid = RTE_BE32(0xffffffff),
+	.hdr.teid = RTE_BE32(UINT32_MAX),
 };
 #endif
 
