diff --git a/drivers/net/mlx5/Makefile b/drivers/net/mlx5/Makefile
index 2694916..4a4225e 100644
--- a/drivers/net/mlx5/Makefile
+++ b/drivers/net/mlx5/Makefile
@@ -8,7 +8,7 @@ include $(RTE_SDK)/mk/rte.vars.mk
 LIB = librte_pmd_mlx5.a
 LIB_GLUE = $(LIB_GLUE_BASE).$(LIB_GLUE_VERSION)
 LIB_GLUE_BASE = librte_pmd_mlx5_glue.so
-LIB_GLUE_VERSION = 19.05.0
+LIB_GLUE_VERSION = 19.08.0
 
 # Sources.
 SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) += mlx5.c
diff --git a/drivers/net/mlx5/meson.build b/drivers/net/mlx5/meson.build
index ac3b529..f1f97a1 100644
--- a/drivers/net/mlx5/meson.build
+++ b/drivers/net/mlx5/meson.build
@@ -4,7 +4,7 @@
 
 pmd_dlopen = (get_option('ibverbs_link') == 'dlopen')
 LIB_GLUE_BASE = 'librte_pmd_mlx5_glue.so'
-LIB_GLUE_VERSION = '19.05.0'
+LIB_GLUE_VERSION = '19.08.0'
 LIB_GLUE = LIB_GLUE_BASE + '.' + LIB_GLUE_VERSION
 if pmd_dlopen
 	dpdk_conf.set('RTE_IBVERBS_LINK_DLOPEN', 1)
diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c
index 9f5ec97..2000350 100644
--- a/drivers/net/mlx5/mlx5.c
+++ b/drivers/net/mlx5/mlx5.c
@@ -369,6 +369,7 @@ struct mlx5_dev_spawn_data {
 	}
 	pthread_mutex_init(&sh->dv_mutex, NULL);
 	sh->tx_domain = domain;
+	sh->pop_vlan_action = mlx5_glue->dr_create_flow_action_pop_vlan();
 #ifdef HAVE_MLX5DV_DR_ESWITCH
 	if (priv->config.dv_esw_en) {
 		domain  = mlx5_glue->dr_create_domain
@@ -400,6 +401,10 @@ struct mlx5_dev_spawn_data {
 		mlx5_glue->dr_destroy_domain(sh->fdb_domain);
 		sh->fdb_domain = NULL;
 	}
+	if (sh->pop_vlan_action) {
+		mlx5_glue->destroy_flow_action(sh->pop_vlan_action);
+		sh->pop_vlan_action = NULL;
+	}
 	if (sh->esw_drop_action) {
 		mlx5_glue->destroy_flow_action(sh->esw_drop_action);
 		sh->esw_drop_action = NULL;
@@ -439,6 +444,10 @@ struct mlx5_dev_spawn_data {
 		mlx5_glue->dr_destroy_domain(sh->tx_domain);
 		sh->tx_domain = NULL;
 	}
+	if (sh->pop_vlan_action) {
+		mlx5_glue->destroy_flow_action(sh->pop_vlan_action);
+		sh->pop_vlan_action = NULL;
+	}
 #ifdef HAVE_MLX5DV_DR_ESWITCH
 	if (sh->fdb_domain) {
 		mlx5_glue->dr_destroy_domain(sh->fdb_domain);
diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h
index 3eaaafd..b9e621d 100644
--- a/drivers/net/mlx5/mlx5.h
+++ b/drivers/net/mlx5/mlx5.h
@@ -297,6 +297,7 @@ struct mlx5_ibv_shared {
 	void *tx_domain; /* TX Direct Rules name space handle. */
 	struct mlx5_flow_tbl_resource tx_tbl[MLX5_MAX_TABLES];
 	void *esw_drop_action; /* Pointer to DR E-Switch drop action. */
+	void *pop_vlan_action; /* Pointer to DR pop VLAN action. */
 	/* TX Direct Rules tables/ */
 	LIST_HEAD(matchers, mlx5_flow_dv_matcher) matchers;
 	LIST_HEAD(encap_decap, mlx5_flow_dv_encap_decap_resource) encaps_decaps;
diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h
index b665420..0fdba46 100644
--- a/drivers/net/mlx5/mlx5_flow.h
+++ b/drivers/net/mlx5/mlx5_flow.h
@@ -125,11 +125,13 @@
 
 #define MLX5_FLOW_ENCAP_ACTIONS	(MLX5_FLOW_ACTION_VXLAN_ENCAP | \
 				 MLX5_FLOW_ACTION_NVGRE_ENCAP | \
-				 MLX5_FLOW_ACTION_RAW_ENCAP)
+				 MLX5_FLOW_ACTION_RAW_ENCAP | \
+				 MLX5_FLOW_ACTION_OF_PUSH_VLAN)
 
 #define MLX5_FLOW_DECAP_ACTIONS	(MLX5_FLOW_ACTION_VXLAN_DECAP | \
 				 MLX5_FLOW_ACTION_NVGRE_DECAP | \
-				 MLX5_FLOW_ACTION_RAW_DECAP)
+				 MLX5_FLOW_ACTION_RAW_DECAP | \
+				 MLX5_FLOW_ACTION_OF_POP_VLAN)
 
 #define MLX5_FLOW_MODIFY_HDR_ACTIONS (MLX5_FLOW_ACTION_SET_IPV4_SRC | \
 				      MLX5_FLOW_ACTION_SET_IPV4_DST | \
@@ -140,7 +142,13 @@
 				      MLX5_FLOW_ACTION_SET_TTL | \
 				      MLX5_FLOW_ACTION_DEC_TTL | \
 				      MLX5_FLOW_ACTION_SET_MAC_SRC | \
-				      MLX5_FLOW_ACTION_SET_MAC_DST)
+				      MLX5_FLOW_ACTION_SET_MAC_DST | \
+				      MLX5_FLOW_ACTION_OF_SET_VLAN_VID | \
+				      MLX5_FLOW_ACTION_OF_SET_VLAN_PCP)
+
+#define MLX5_FLOW_VLAN_ACTIONS \
+	(MLX5_FLOW_ACTION_OF_POP_VLAN | MLX5_FLOW_ACTION_OF_PUSH_VLAN | \
+	 MLX5_FLOW_ACTION_OF_SET_VLAN_VID | MLX5_FLOW_ACTION_OF_SET_VLAN_PCP)
 
 #ifndef IPPROTO_MPLS
 #define IPPROTO_MPLS 137
@@ -258,6 +266,16 @@ struct mlx5_flow_dv_modify_hdr_resource {
 	uint64_t flags; /**< Flags for RDMA API. */
 };
 
+/* Push VLAN action resource structure */
+struct mlx5_flow_dv_push_vlan_action_resource {
+	LIST_ENTRY(mlx5_flow_dv_push_vlan_action_resource) next;
+	/* Pointer to next element. */
+	rte_atomic32_t refcnt; /**< Reference counter. */
+	void *action;
+	/**< Direct verbs action object. */
+	uint32_t vlan_hdr; /**< VLAN header value. */
+};
+
 /* Jump action resource structure. */
 struct mlx5_flow_dv_jump_tbl_resource {
 	LIST_ENTRY(mlx5_flow_dv_jump_tbl_resource) next;
@@ -297,6 +315,8 @@ struct mlx5_flow_dv {
 	/**< Pointer to encap/decap resource in cache. */
 	struct mlx5_flow_dv_modify_hdr_resource *modify_hdr;
 	/**< Pointer to modify header resource in cache. */
+	struct mlx5_flow_dv_push_vlan_action_resource *push_vlan_action;
+	/**< Pointer to push VLAN action resource in cache. */
 	struct ibv_flow *flow; /**< Installed flow. */
 	struct mlx5_flow_dv_jump_tbl_resource *jump;
 	/**< Pointer to the jump action resource. */
diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c
index cf255ca..b8b4e58 100644
--- a/drivers/net/mlx5/mlx5_flow_dv.c
+++ b/drivers/net/mlx5/mlx5_flow_dv.c
@@ -49,6 +49,17 @@
 #define MLX5DV_DR_ACTION_FLAGS_ROOT_LEVEL 1
 #endif
 
+union flow_dr_vlan_hdr {
+	struct vlan_hdr vhdr;
+	struct {
+	    uint32_t vid:12;
+	    uint32_t dei:1;
+	    uint32_t pcp:3;
+	    uint32_t tpid:16;
+	};
+	uint32_t tag;
+} __attribute__((__packed__));
+
 union flow_dv_attr {
 	struct {
 		uint32_t valid:1;
@@ -107,6 +118,12 @@ struct field_modify_info modify_eth[] = {
 	{0, 0, 0},
 };
 
+struct field_modify_info modify_vlan[] = {
+	/* TODO: Fill with correct values */
+	{4,  0, MLX5_MODI_OUT_FIRST_VID},
+	{0, 0, 0},
+};
+
 struct field_modify_info modify_ipv4[] = {
 	{1,  8, MLX5_MODI_OUT_IPV4_TTL},
 	{4, 12, MLX5_MODI_OUT_SIPV4},
@@ -238,6 +255,37 @@ struct field_modify_info modify_tcp[] = {
 }
 
 /**
+ * Convert modify-header set Modify-VLAN action to DV specification or create
+ * a new VLAN push action.
+ *
+ * @param[in,out] resource
+ *   Pointer to the modify-header resource.
+ * @param[in] action
+ *   Pointer to action specification.
+ * @param[out] error
+ *   Pointer to the error structure.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+static int
+flow_dv_create_action_modify_vlan
+			(struct mlx5_flow_dv_modify_hdr_resource *res,
+			 const union flow_dr_vlan_hdr *vlan,
+			 const uint64_t action_flags,
+			 const struct rte_flow_item *items,
+			 struct rte_flow_error *error)
+{
+	(void)res;
+	(void)vlan;
+	(void)action_flags;
+	(void)items;
+	return rte_flow_error_set(error, ENOTSUP,
+				  RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+				  "unsupported action");
+}
+
+/**
  * Convert modify-header set IPv4 address action to DV specification.
  *
  * @param[in,out] resource
@@ -819,6 +867,68 @@ struct field_modify_info modify_tcp[] = {
 }
 
 /**
+ * Validate the push VLAN action.
+ *
+ * @param[in] action_flags
+ *   Holds the actions detected until now.
+ * @param[in] action
+ *   Pointer to the encap action.
+ * @param[in] attr
+ *   Pointer to flow attributes
+ * @param[out] error
+ *   Pointer to error structure.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+static int
+flow_dv_validate_action_push_vlan(uint64_t action_flags,
+				  const struct rte_flow_action *action,
+				  const struct rte_flow_attr *attr,
+				  struct rte_flow_error *error)
+{
+	(void)action_flags;
+	(void)action;
+	(void)attr;
+	return rte_flow_error_set(error, ENOTSUP,
+				  RTE_FLOW_ERROR_TYPE_ACTION, action,
+				  "unsupported action");
+}
+
+/**
+ * Validate the pop VLAN action.
+ *
+ * @param[in] action_flags
+ *   Holds the actions detected until now.
+ * @param[in] action
+ *   Pointer to the pop vlan action.
+ * @param[in] item_flags
+ *   The items found in this flow rule.
+ * @param[in] attr
+ *   Pointer to flow attributes.
+ * @param[out] error
+ *   Pointer to error structure.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+static int
+flow_dv_validate_action_pop_vlan(uint64_t action_flags,
+				 const struct rte_flow_action *action,
+				 uint64_t item_flags,
+				 const struct rte_flow_attr *attr,
+				 struct rte_flow_error *error)
+{
+	(void)action_flags;
+	(void)action;
+	(void)item_flags;
+	(void)attr;
+	return rte_flow_error_set(error, ENOTSUP,
+				  RTE_FLOW_ERROR_TYPE_ACTION, action,
+				  "unsupported action");
+}
+
+/**
  * Validate the raw encap action.
  *
  * @param[in] action_flags
@@ -1502,6 +1612,37 @@ struct field_modify_info modify_tcp[] = {
 }
 
 /**
+ * Create action push VLAN.
+ *
+ * @param[in] dev
+ *   Pointer to rte_eth_dev structure.
+ * @param[in] vlan_tag
+ *   the vlan tag to push to the Ethernet header.
+ * @param[in, out] dev_flow
+ *   Pointer to the mlx5_flow.
+ * @param[in] attr
+ *   Pointer to the flow attributes.
+ * @param[out] error
+ *   Pointer to the error structure.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+static int
+flow_dv_create_action_push_vlan(struct rte_eth_dev *dev,
+				const uint32_t vlan_tag,
+				struct mlx5_flow *dev_flow,
+				struct rte_flow_error *error)
+{
+	(void)dev;
+	(void)vlan_tag;
+	(void)dev_flow;
+	return rte_flow_error_set(error, ENOTSUP,
+				  RTE_FLOW_ERROR_TYPE_ACTION,
+				  NULL, "unsupported action");
+}
+
+/**
  * Validate the modify-header actions.
  *
  * @param[in] action_flags
@@ -1566,6 +1707,34 @@ struct field_modify_info modify_tcp[] = {
 }
 
 /**
+ * Validate the modify-header VLAN actions.
+ *
+ * @param[in] action_flags
+ *   Holds the actions detected until now.
+ * @param[in] action
+ *   Pointer to the modify action.
+ * @param[in] item_flags
+ *   Holds the items detected.
+ * @param[out] error
+ *   Pointer to error structure.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+static int
+flow_dv_validate_action_modify_vlan(const uint64_t action_flags,
+				    const struct rte_flow_action *action,
+				    const uint64_t item_flags,
+				    struct rte_flow_error *error)
+{
+	(void)action_flags;
+	(void)action;
+	(void)item_flags;
+	return rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION,
+				  NULL, "unsupported action");
+}
+
+/**
  * Validate the modify-header IPv4 address actions.
  *
  * @param[in] action_flags
@@ -2277,6 +2446,26 @@ struct field_modify_info modify_tcp[] = {
 			action_flags |= MLX5_FLOW_ACTION_COUNT;
 			++actions_n;
 			break;
+		case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN:
+			ret = flow_dv_validate_action_push_vlan(action_flags,
+								actions, attr,
+								error);
+			if (ret < 0)
+				return ret;
+			action_flags |= MLX5_FLOW_ACTION_OF_PUSH_VLAN;
+			++actions_n;
+			break;
+		case RTE_FLOW_ACTION_TYPE_OF_POP_VLAN:
+			ret = flow_dv_validate_action_pop_vlan(action_flags,
+							       actions,
+							       item_flags, attr,
+							       error);
+				return -rte_errno;
+			if (ret < 0)
+				return ret;
+			action_flags |= MLX5_FLOW_ACTION_OF_POP_VLAN;
+			++actions_n;
+			break;
 		case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
 		case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
 			ret = flow_dv_validate_action_l2_encap(action_flags,
@@ -2336,7 +2525,22 @@ struct field_modify_info modify_tcp[] = {
 						MLX5_FLOW_ACTION_SET_MAC_SRC :
 						MLX5_FLOW_ACTION_SET_MAC_DST;
 			break;
-
+		case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID:
+		case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP:
+			ret = flow_dv_validate_action_modify_vlan(action_flags,
+								  actions,
+								  item_flags,
+								  error);
+			if (ret < 0)
+				return ret;
+			/* Count all modify-header actions as one action. */
+			if (!(action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS))
+				++actions_n;
+			action_flags |= actions->type ==
+					RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID ?
+					MLX5_FLOW_ACTION_OF_SET_VLAN_VID :
+					MLX5_FLOW_ACTION_OF_SET_VLAN_PCP;
+			break;
 		case RTE_FLOW_ACTION_TYPE_SET_IPV4_SRC:
 		case RTE_FLOW_ACTION_TYPE_SET_IPV4_DST:
 			ret = flow_dv_validate_action_modify_ipv4(action_flags,
@@ -3634,6 +3838,7 @@ struct field_modify_info modify_tcp[] = {
 	uint32_t modify_action_position = UINT32_MAX;
 	void *match_mask = matcher.mask.buf;
 	void *match_value = dev_flow->dv.value.buf;
+	union flow_dr_vlan_hdr vlan;
 
 	flow->group = attr->group;
 	if (attr->transfer)
@@ -3740,6 +3945,37 @@ struct field_modify_info modify_tcp[] = {
 						 action,
 						 "cannot create counter"
 						  " object.");
+			break;
+		case RTE_FLOW_ACTION_TYPE_OF_POP_VLAN:
+			if (!priv->sh->pop_vlan_action)
+				return rte_flow_error_set
+						(error, ENOTSUP,
+						 RTE_FLOW_ERROR_TYPE_ACTION,
+						 action,
+						 "cannot create pop vlan"
+						  " action.");
+			dev_flow->dv.actions[actions_n++] =
+						    priv->sh->pop_vlan_action;
+			action_flags |= MLX5_FLOW_ACTION_OF_POP_VLAN;
+			break;
+		case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN:
+			vlan.tpid =
+				((const struct rte_flow_action_of_push_vlan *)
+						      actions->conf)->ethertype;
+			action_flags |= MLX5_FLOW_ACTION_OF_PUSH_VLAN;
+			break;
+		case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID:
+			vlan.vid =
+			       ((const struct rte_flow_action_of_set_vlan_vid *)
+						       actions->conf)->vlan_vid;
+			action_flags |= MLX5_FLOW_ACTION_OF_SET_VLAN_VID;
+			break;
+		case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP:
+			vlan.pcp =
+			   ((const struct rte_flow_action_of_set_vlan_pcp *)
+						       actions->conf)->vlan_pcp;
+			action_flags |= MLX5_FLOW_ACTION_OF_SET_VLAN_PCP;
+			break;
 		case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
 		case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
 			if (flow_dv_create_action_l2_encap(dev, actions,
@@ -3886,12 +4122,31 @@ struct field_modify_info modify_tcp[] = {
 			break;
 		case RTE_FLOW_ACTION_TYPE_END:
 			actions_end = true;
+			/*
+			 * Finally we can handle the VLAN commands.
+			 * If we have a push VLAN action it will handle all
+			 * other VLAN modify-header actions.
+			 */
+			if (action_flags & MLX5_FLOW_ACTION_OF_PUSH_VLAN) {
+				action_flags &=
+					~(MLX5_FLOW_ACTION_OF_SET_VLAN_VID |
+					  MLX5_FLOW_ACTION_OF_SET_VLAN_PCP);
+				if (flow_dv_create_action_push_vlan
+					    (dev, vlan.tag, dev_flow, error))
+					return -rte_errno;
+				dev_flow->dv.actions[actions_n++] =
+						dev_flow->dv.push_vlan_action;
+			} else if (action_flags & MLX5_FLOW_VLAN_ACTIONS) {
+				if (flow_dv_create_action_modify_vlan
+						(&res, &vlan,
+						 action_flags, items, error))
+					return -rte_errno;
+			}
 			if (action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS) {
 				/* create modify action if needed. */
 				if (flow_dv_modify_hdr_resource_register
-								(dev, &res,
-								 dev_flow,
-								 error))
+							(dev, &res,
+							 dev_flow, error))
 					return -rte_errno;
 				dev_flow->dv.actions[modify_action_position] =
 					dev_flow->dv.modify_hdr->verbs_action;
diff --git a/drivers/net/mlx5/mlx5_glue.c b/drivers/net/mlx5/mlx5_glue.c
index 21cd3bb..66bc66e 100644
--- a/drivers/net/mlx5/mlx5_glue.c
+++ b/drivers/net/mlx5/mlx5_glue.c
@@ -408,6 +408,29 @@
 }
 
 static void *
+mlx5_glue_dr_create_flow_action_push_vlan(uint32_t vlan_tag)
+{
+#ifdef HAVE_MLX5DV_DR_VLAN
+	return mlx5dv_dr_create_action_pop_vlan(vlan_tag);
+#else
+	(void)vlan_tag;
+	errno = ENOTSUP;
+	return NULL;
+#endif
+}
+
+static void *
+mlx5_glue_dr_create_flow_action_pop_vlan(void)
+{
+#ifdef HAVE_MLX5DV_DR_VLAN
+	return mlx5dv_dr_create_action_pop_vlan();
+#else
+	errno = ENOTSUP;
+	return NULL;
+#endif
+}
+
+static void *
 mlx5_glue_dr_create_flow_tbl(void *domain, uint32_t level)
 {
 #ifdef HAVE_MLX5DV_DR
@@ -893,6 +916,10 @@
 		mlx5_glue_dr_create_flow_action_dest_vport,
 	.dr_create_flow_action_drop =
 		mlx5_glue_dr_create_flow_action_drop,
+	.dr_create_flow_action_push_vlan =
+		mlx5_glue_dr_create_flow_action_push_vlan,
+	.dr_create_flow_action_pop_vlan =
+		mlx5_glue_dr_create_flow_action_pop_vlan,
 	.dr_create_flow_tbl = mlx5_glue_dr_create_flow_tbl,
 	.dr_destroy_flow_tbl = mlx5_glue_dr_destroy_flow_tbl,
 	.dr_create_domain = mlx5_glue_dr_create_domain,
diff --git a/drivers/net/mlx5/mlx5_glue.h b/drivers/net/mlx5/mlx5_glue.h
index b5c63cb..39bbf00 100644
--- a/drivers/net/mlx5/mlx5_glue.h
+++ b/drivers/net/mlx5/mlx5_glue.h
@@ -148,6 +148,8 @@ struct mlx5_glue {
 	void *(*dr_create_flow_action_dest_flow_tbl)(void *tbl);
 	void *(*dr_create_flow_action_dest_vport)(void *domain, uint32_t vport);
 	void *(*dr_create_flow_action_drop)();
+	void *(*dr_create_flow_action_push_vlan)(uint32_t vlan_tag);
+	void *(*dr_create_flow_action_pop_vlan)();
 	void *(*dr_create_flow_tbl)(void *domain, uint32_t level);
 	int (*dr_destroy_flow_tbl)(void *tbl);
 	void *(*dr_create_domain)(struct ibv_context *ctx,
diff --git a/drivers/net/mlx5/mlx5_prm.h b/drivers/net/mlx5/mlx5_prm.h
index 8c42380..d106aff 100644
--- a/drivers/net/mlx5/mlx5_prm.h
+++ b/drivers/net/mlx5/mlx5_prm.h
@@ -310,6 +310,7 @@ enum mlx5_modification_field {
 	MLX5_MODI_OUT_DIPV6_31_0,
 	MLX5_MODI_OUT_SIPV4,
 	MLX5_MODI_OUT_DIPV4,
+	MLX5_MODI_OUT_FIRST_VID,
 	MLX5_MODI_IN_SMAC_47_16 = 0x31,
 	MLX5_MODI_IN_SMAC_15_0,
 	MLX5_MODI_IN_ETHERTYPE,
