diff --git a/drivers/common/mlx5/mlx5_prm.h b/drivers/common/mlx5/mlx5_prm.h
index abff8e4dc3..50c681704a 100644
--- a/drivers/common/mlx5/mlx5_prm.h
+++ b/drivers/common/mlx5/mlx5_prm.h
@@ -2132,7 +2132,10 @@ struct mlx5_ifc_flow_table_prop_layout_bits {
 struct mlx5_ifc_roce_caps_bits {
 	u8 reserved_0[0x1e];
 	u8 qp_ts_format[0x2];
-	u8 reserved_at_20[0x7e0];
+	u8 reserved_at_20[0xa0];
+	u8 r_roce_max_src_udp_port[0x10];
+	u8 r_roce_min_src_udp_port[0x10];
+	u8 reserved_at_e0[0x720];
 };
 
 struct mlx5_ifc_ft_fields_support_bits {
@@ -2370,7 +2373,8 @@ struct mlx5_ifc_cmd_hca_cap_2_bits {
 	u8 format_select_dw_gtpu_first_ext_dw_0[0x8];
 	u8 generate_wqe_type[0x20];
 	u8 reserved_at_2c0[0x160];
-	u8 reserved_at_420[0x1c];
+	u8 reserved_at_420[0x18];
+	u8 encap_entropy_hash_type[0x4];
 	u8 flow_table_hash_type[0x4];
 	u8 reserved_at_440[0x3c0];
 };
diff --git a/drivers/net/mlx5/hws/mlx5dr.h b/drivers/net/mlx5/hws/mlx5dr.h
index d88f73ab57..321b649f8c 100644
--- a/drivers/net/mlx5/hws/mlx5dr.h
+++ b/drivers/net/mlx5/hws/mlx5dr.h
@@ -279,6 +279,27 @@ struct mlx5dr_action_dest_attr {
 	} reformat;
 };
 
+union mlx5dr_crc_encap_entropy_hash_ip_field {
+	uint8_t  ipv6_addr[16];
+	struct {
+		uint8_t  reserved[12];
+		rte_be32_t  ipv4_addr;
+	};
+};
+
+struct mlx5dr_crc_encap_entropy_hash_fields {
+	union mlx5dr_crc_encap_entropy_hash_ip_field dst;
+	union mlx5dr_crc_encap_entropy_hash_ip_field src;
+	uint8_t next_protocol;
+	rte_be16_t dst_port;
+	rte_be16_t src_port;
+}__rte_packed;
+
+enum mlx5dr_crc_encap_entropy_hash_size {
+	MLX5DR_CRC_ENCAP_ENTROPY_HASH_SIZE_8,
+	MLX5DR_CRC_ENCAP_ENTROPY_HASH_SIZE_16,
+};
+
 /* Open a context used for direct rule insertion using hardware steering.
  * Each context can contain multiple tables of different types.
  *
@@ -845,4 +866,21 @@ int mlx5dr_send_queue_action(struct mlx5dr_context *ctx,
  */
 int mlx5dr_debug_dump(struct mlx5dr_context *ctx, FILE *f);
 
+/* Calculate encap entropy hash value
+ *
+ * @param[in] ctx
+ *	The context to get from it's capabilities the entropy hash type.
+ * @param[in] data
+ *	The fields for the hash calculation.
+ * @param[in] entropy_res
+ *	An array to store the hash value to it.
+ * @param[in] res_size
+ *	The result size.
+ * @return zero on success non zero otherwise.
+ */
+int mlx5dr_crc_encap_entropy_hash_calc(struct mlx5dr_context *ctx,
+				       struct mlx5dr_crc_encap_entropy_hash_fields *data,
+				       uint8_t entropy_res[],
+				       enum mlx5dr_crc_encap_entropy_hash_size res_size);
+
 #endif
diff --git a/drivers/net/mlx5/hws/mlx5dr_cmd.c b/drivers/net/mlx5/hws/mlx5dr_cmd.c
index 876a47147d..f77b194708 100644
--- a/drivers/net/mlx5/hws/mlx5dr_cmd.c
+++ b/drivers/net/mlx5/hws/mlx5dr_cmd.c
@@ -1103,6 +1103,8 @@ int mlx5dr_cmd_query_caps(struct ibv_context *ctx,
 	caps->ipsec_offload = MLX5_GET(query_hca_cap_out, out,
 				      capability.cmd_hca_cap.ipsec_offload);
 
+	caps->roce = MLX5_GET(query_hca_cap_out, out, capability.cmd_hca_cap.roce);
+
 	MLX5_SET(query_hca_cap_in, in, op_mod,
 		 MLX5_GET_HCA_CAP_OP_MOD_GENERAL_DEVICE_2 |
 		 MLX5_HCA_CAP_OPMOD_GET_CUR);
@@ -1158,6 +1160,9 @@ int mlx5dr_cmd_query_caps(struct ibv_context *ctx,
 	caps->flow_table_hash_type = MLX5_GET(query_hca_cap_out, out,
 					      capability.cmd_hca_cap_2.flow_table_hash_type);
 
+	caps->encap_entropy_hash_type = MLX5_GET(query_hca_cap_out, out,
+						 capability.cmd_hca_cap_2.encap_entropy_hash_type);
+
 	MLX5_SET(query_hca_cap_in, in, op_mod,
 		 MLX5_GET_HCA_CAP_OP_MOD_NIC_FLOW_TABLE |
 		 MLX5_HCA_CAP_OPMOD_GET_CUR);
@@ -1306,6 +1311,24 @@ int mlx5dr_cmd_query_caps(struct ibv_context *ctx,
 						capability.esw_cap.merged_eswitch);
 	}
 
+	if (caps->roce) {
+		MLX5_SET(query_hca_cap_in, in, op_mod,
+			 MLX5_GET_HCA_CAP_OP_MOD_ROCE |
+			 MLX5_HCA_CAP_OPMOD_GET_CUR);
+
+		ret = mlx5_glue->devx_general_cmd(ctx, in, sizeof(in), out, sizeof(out));
+		if (ret) {
+			DR_LOG(ERR, "Failed to query roce caps");
+			rte_errno = errno;
+			return rte_errno;
+		}
+
+		caps->roce_max_src_udp_port = MLX5_GET(query_hca_cap_out, out,
+						capability.roce_caps.r_roce_max_src_udp_port);
+		caps->roce_min_src_udp_port = MLX5_GET(query_hca_cap_out, out,
+						capability.roce_caps.r_roce_min_src_udp_port);
+	}
+
 	ret = mlx5_glue->query_device_ex(ctx, NULL, &attr_ex);
 	if (ret) {
 		DR_LOG(ERR, "Failed to query device attributes");
diff --git a/drivers/net/mlx5/hws/mlx5dr_cmd.h b/drivers/net/mlx5/hws/mlx5dr_cmd.h
index 18c2b07fc8..694231e08f 100644
--- a/drivers/net/mlx5/hws/mlx5dr_cmd.h
+++ b/drivers/net/mlx5/hws/mlx5dr_cmd.h
@@ -246,6 +246,10 @@ struct mlx5dr_cmd_query_caps {
 	uint32_t shared_vhca_id;
 	char fw_ver[64];
 	bool ipsec_offload;
+	uint8_t encap_entropy_hash_type;
+	bool roce;
+	uint16_t roce_max_src_udp_port;
+	uint16_t roce_min_src_udp_port;
 };
 
 int mlx5dr_cmd_destroy_obj(struct mlx5dr_devx_obj *devx_obj);
diff --git a/drivers/net/mlx5/hws/mlx5dr_crc32.c b/drivers/net/mlx5/hws/mlx5dr_crc32.c
index 9c454eda0c..7431462e14 100644
--- a/drivers/net/mlx5/hws/mlx5dr_crc32.c
+++ b/drivers/net/mlx5/hws/mlx5dr_crc32.c
@@ -50,6 +50,42 @@ uint32_t dr_ste_crc_tab32[] = {
 	0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
 };
 
+/* CRC table for the CRC-16, the polynome is 0x100b */
+uint16_t dr_crc_inner_crc_tab16[] = {
+	0x0000, 0x100B, 0x2016, 0x301D, 0x402C, 0x5027, 0x603A, 0x7031,
+	0x8058, 0x9053, 0xA04E, 0xB045, 0xC074, 0xD07F, 0xE062, 0xF069,
+	0x10BB, 0x00B0, 0x30AD, 0x20A6, 0x5097, 0x409C, 0x7081, 0x608A,
+	0x90E3, 0x80E8, 0xB0F5, 0xA0FE, 0xD0CF, 0xC0C4, 0xF0D9, 0xE0D2,
+	0x2176, 0x317D, 0x0160, 0x116B, 0x615A, 0x7151, 0x414C, 0x5147,
+	0xA12E, 0xB125, 0x8138, 0x9133, 0xE102, 0xF109, 0xC114, 0xD11F,
+	0x31CD, 0x21C6, 0x11DB, 0x01D0, 0x71E1, 0x61EA, 0x51F7, 0x41FC,
+	0xB195, 0xA19E, 0x9183, 0x8188, 0xF1B9, 0xE1B2, 0xD1AF, 0xC1A4,
+	0x42EC, 0x52E7, 0x62FA, 0x72F1, 0x02C0, 0x12CB, 0x22D6, 0x32DD,
+	0xC2B4, 0xD2BF, 0xE2A2, 0xF2A9, 0x8298, 0x9293, 0xA28E, 0xB285,
+	0x5257, 0x425C, 0x7241, 0x624A, 0x127B, 0x0270, 0x326D, 0x2266,
+	0xD20F, 0xC204, 0xF219, 0xE212, 0x9223, 0x8228, 0xB235, 0xA23E,
+	0x639A, 0x7391, 0x438C, 0x5387, 0x23B6, 0x33BD, 0x03A0, 0x13AB,
+	0xE3C2, 0xF3C9, 0xC3D4, 0xD3DF, 0xA3EE, 0xB3E5, 0x83F8, 0x93F3,
+	0x7321, 0x632A, 0x5337, 0x433C, 0x330D, 0x2306, 0x131B, 0x0310,
+	0xF379, 0xE372, 0xD36F, 0xC364, 0xB355, 0xA35E, 0x9343, 0x8348,
+	0x85D8, 0x95D3, 0xA5CE, 0xB5C5, 0xC5F4, 0xD5FF, 0xE5E2, 0xF5E9,
+	0x0580, 0x158B, 0x2596, 0x359D, 0x45AC, 0x55A7, 0x65BA, 0x75B1,
+	0x9563, 0x8568, 0xB575, 0xA57E, 0xD54F, 0xC544, 0xF559, 0xE552,
+	0x153B, 0x0530, 0x352D, 0x2526, 0x5517, 0x451C, 0x7501, 0x650A,
+	0xA4AE, 0xB4A5, 0x84B8, 0x94B3, 0xE482, 0xF489, 0xC494, 0xD49F,
+	0x24F6, 0x34FD, 0x04E0, 0x14EB, 0x64DA, 0x74D1, 0x44CC, 0x54C7,
+	0xB415, 0xA41E, 0x9403, 0x8408, 0xF439, 0xE432, 0xD42F, 0xC424,
+	0x344D, 0x2446, 0x145B, 0x0450, 0x7461, 0x646A, 0x5477, 0x447C,
+	0xC734, 0xD73F, 0xE722, 0xF729, 0x8718, 0x9713, 0xA70E, 0xB705,
+	0x476C, 0x5767, 0x677A, 0x7771, 0x0740, 0x174B, 0x2756, 0x375D,
+	0xD78F, 0xC784, 0xF799, 0xE792, 0x97A3, 0x87A8, 0xB7B5, 0xA7BE,
+	0x57D7, 0x47DC, 0x77C1, 0x67CA, 0x17FB, 0x07F0, 0x37ED, 0x27E6,
+	0xE642, 0xF649, 0xC654, 0xD65F, 0xA66E, 0xB665, 0x8678, 0x9673,
+	0x661A, 0x7611, 0x460C, 0x5607, 0x2636, 0x363D, 0x0620, 0x162B,
+	0xF6F9, 0xE6F2, 0xD6EF, 0xC6E4, 0xB6D5, 0xA6DE, 0x96C3, 0x86C8,
+	0x76A1, 0x66AA, 0x56B7, 0x46BC, 0x368D, 0x2686, 0x169B, 0x0690
+};
+
 uint32_t mlx5dr_crc32_calc(uint8_t *p, size_t len)
 {
 	uint32_t crc = 0;
@@ -59,3 +95,45 @@ uint32_t mlx5dr_crc32_calc(uint8_t *p, size_t len)
 
 	return rte_be_to_cpu_32(crc);
 }
+
+uint16_t mlx5dr_crc16_calc(uint8_t *p, size_t len, uint16_t crc_tab16[])
+{
+	uint16_t crc = 0;
+
+	while (len--)
+		crc = (crc << 8) ^ crc_tab16[((crc >> 8) ^ *p++) & 0xff];
+
+	return crc;
+}
+
+int mlx5dr_crc_encap_entropy_hash_calc(struct mlx5dr_context *ctx,
+				       struct mlx5dr_crc_encap_entropy_hash_fields *data,
+				       uint8_t entropy_res[],
+				       enum mlx5dr_crc_encap_entropy_hash_size res_size)
+{
+	struct mlx5dr_cmd_query_caps *caps = ctx->caps;
+	uint16_t max_hash, min_hash, res;
+
+	if (caps->encap_entropy_hash_type) {
+		DR_LOG(ERR, "calculation of encap_entropy_hash_type 0x%x not supported",
+		       caps->encap_entropy_hash_type);
+		rte_errno = ENOTSUP;
+		return rte_errno;
+	}
+
+	max_hash = caps->roce_max_src_udp_port;
+	min_hash = caps->roce_min_src_udp_port;
+
+	res = mlx5dr_crc16_calc((uint8_t *)data, sizeof(*data), dr_crc_inner_crc_tab16);
+
+	if (res_size == MLX5DR_CRC_ENCAP_ENTROPY_HASH_SIZE_16) {
+		*(uint16_t *)entropy_res = rte_cpu_to_be_16((min_hash | res) & max_hash);
+	} else if (res_size == MLX5DR_CRC_ENCAP_ENTROPY_HASH_SIZE_8) {
+		*entropy_res = (uint8_t)(res & 0xff);
+	} else {
+		rte_errno = ENOTSUP;
+		return rte_errno;
+	}
+
+	return 0;
+}
diff --git a/drivers/net/mlx5/hws/mlx5dr_crc32.h b/drivers/net/mlx5/hws/mlx5dr_crc32.h
index 9aab9e06ca..75b6009a15 100644
--- a/drivers/net/mlx5/hws/mlx5dr_crc32.h
+++ b/drivers/net/mlx5/hws/mlx5dr_crc32.h
@@ -10,4 +10,9 @@
  */
 uint32_t mlx5dr_crc32_calc(uint8_t *p, size_t len);
 
+/* Standard CRC16 calculation using the crc_tab16 param to indicate
+ * the pre-calculated polynome hash values.
+ */
+uint16_t mlx5dr_crc16_calc(uint8_t *p, size_t len, uint16_t crc_tab16[]);
+
 #endif /* MLX5DR_CRC32_C_ */
