diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h
index f6488e1..5cfcf99 100644
--- a/drivers/net/mlx5/mlx5.h
+++ b/drivers/net/mlx5/mlx5.h
@@ -39,6 +39,7 @@
 #include "mlx5_defs.h"
 #include "mlx5_utils.h"
 #include "mlx5_mr.h"
+#include "mlx5_nl.h"
 #include "mlx5_autoconf.h"
 
 /* Request types for IPC. */
@@ -75,24 +76,6 @@ struct mlx5_mp_param {
 /** Key string for IPC. */
 #define MLX5_MP_NAME "net_mlx5_mp"
 
-/* Recognized Infiniband device physical port name types. */
-enum mlx5_phys_port_name_type {
-	MLX5_PHYS_PORT_NAME_TYPE_NOTSET = 0, /* Not set. */
-	MLX5_PHYS_PORT_NAME_TYPE_LEGACY, /* before kernel ver < 5.0 */
-	MLX5_PHYS_PORT_NAME_TYPE_UPLINK, /* p0, kernel ver >= 5.0 */
-	MLX5_PHYS_PORT_NAME_TYPE_PFVF, /* pf0vf0, kernel ver >= 5.0 */
-	MLX5_PHYS_PORT_NAME_TYPE_UNKNOWN, /* Unrecognized. */
-};
-
-/** Switch information returned by mlx5_nl_switch_info(). */
-struct mlx5_switch_info {
-	uint32_t master:1; /**< Master device. */
-	uint32_t representor:1; /**< Representor device. */
-	enum mlx5_phys_port_name_type name_type; /** < Port name type. */
-	int32_t pf_num; /**< PF number (valid for pfxvfx format only). */
-	int32_t port_name; /**< Representor port name. */
-	uint64_t switch_id; /**< Switch identifier. */
-};
 
 LIST_HEAD(mlx5_dev_list, mlx5_ibv_shared);
 
@@ -226,30 +209,12 @@ enum mlx5_verbs_alloc_type {
 	MLX5_VERBS_ALLOC_TYPE_RX_QUEUE,
 };
 
-/* VLAN netdev for VLAN workaround. */
-struct mlx5_vlan_dev {
-	uint32_t refcnt;
-	uint32_t ifindex; /**< Own interface index. */
-};
-
 /* Structure for VF VLAN workaround. */
 struct mlx5_vf_vlan {
 	uint32_t tag:12;
 	uint32_t created:1;
 };
 
-/*
- * Array of VLAN devices created on the base of VF
- * used for workaround in virtual environments.
- */
-struct mlx5_vlan_vmwa_context {
-	int nl_socket;
-	uint32_t nl_sn;
-	uint32_t vf_ifindex;
-	struct rte_eth_dev *dev;
-	struct mlx5_vlan_dev vlan_dev[4096];
-};
-
 /**
  * Verbs allocator needs a context to know in the callback which kind of
  * resources it is allocating.
@@ -574,7 +539,7 @@ struct mlx5_priv {
 	int nl_socket_route; /* Netlink socket (NETLINK_ROUTE). */
 	uint32_t nl_sn; /* Netlink message sequence number. */
 	LIST_HEAD(dbrpage, mlx5_devx_dbr_page) dbrpgs; /* Door-bell pages. */
-	struct mlx5_vlan_vmwa_context *vmwa_context; /* VLAN WA context. */
+	struct mlx5_nl_vlan_vmwa_context *vmwa_context; /* VLAN WA context. */
 	struct mlx5_flow_id_pool *qrss_id_pool;
 	struct mlx5_hlist *mreg_cp_tbl;
 	/* Hash table of Rx metadata register copy table. */
@@ -670,6 +635,8 @@ int mlx5_hairpin_cap_get(struct rte_eth_dev *dev,
 void mlx5_mac_addr_remove(struct rte_eth_dev *dev, uint32_t index);
 int mlx5_mac_addr_add(struct rte_eth_dev *dev, struct rte_ether_addr *mac,
 		      uint32_t index, uint32_t vmdq);
+struct mlx5_nl_vlan_vmwa_context *mlx5_vlan_vmwa_init
+				    (struct rte_eth_dev *dev, uint32_t ifindex);
 int mlx5_mac_addr_set(struct rte_eth_dev *dev, struct rte_ether_addr *mac_addr);
 int mlx5_set_mc_addr_list(struct rte_eth_dev *dev,
 			struct rte_ether_addr *mc_addr_set,
@@ -713,6 +680,11 @@ int mlx5_xstats_get_names(struct rte_eth_dev *dev __rte_unused,
 int mlx5_vlan_filter_set(struct rte_eth_dev *dev, uint16_t vlan_id, int on);
 void mlx5_vlan_strip_queue_set(struct rte_eth_dev *dev, uint16_t queue, int on);
 int mlx5_vlan_offload_set(struct rte_eth_dev *dev, int mask);
+void mlx5_vlan_vmwa_exit(struct mlx5_nl_vlan_vmwa_context *ctx);
+void mlx5_vlan_vmwa_release(struct rte_eth_dev *dev,
+			    struct mlx5_vf_vlan *vf_vlan);
+void mlx5_vlan_vmwa_acquire(struct rte_eth_dev *dev,
+			    struct mlx5_vf_vlan *vf_vlan);
 
 /* mlx5_trigger.c */
 
@@ -794,32 +766,6 @@ int mlx5_mp_req_queue_state_modify(struct rte_eth_dev *dev,
 int mlx5_pmd_socket_init(void);
 void mlx5_pmd_socket_uninit(void);
 
-/* mlx5_nl.c */
-
-int mlx5_nl_init(int protocol);
-int mlx5_nl_mac_addr_add(struct rte_eth_dev *dev, struct rte_ether_addr *mac,
-			 uint32_t index);
-int mlx5_nl_mac_addr_remove(struct rte_eth_dev *dev, struct rte_ether_addr *mac,
-			    uint32_t index);
-void mlx5_nl_mac_addr_sync(struct rte_eth_dev *dev);
-void mlx5_nl_mac_addr_flush(struct rte_eth_dev *dev);
-int mlx5_nl_promisc(struct rte_eth_dev *dev, int enable);
-int mlx5_nl_allmulti(struct rte_eth_dev *dev, int enable);
-unsigned int mlx5_nl_portnum(int nl, const char *name);
-unsigned int mlx5_nl_ifindex(int nl, const char *name, uint32_t pindex);
-int mlx5_nl_vf_mac_addr_modify(struct rte_eth_dev *dev,
-			       struct rte_ether_addr *mac, int vf_index);
-int mlx5_nl_switch_info(int nl, unsigned int ifindex,
-			struct mlx5_switch_info *info);
-
-struct mlx5_vlan_vmwa_context *mlx5_vlan_vmwa_init(struct rte_eth_dev *dev,
-						   uint32_t ifindex);
-void mlx5_vlan_vmwa_exit(struct mlx5_vlan_vmwa_context *ctx);
-void mlx5_vlan_vmwa_release(struct rte_eth_dev *dev,
-			    struct mlx5_vf_vlan *vf_vlan);
-void mlx5_vlan_vmwa_acquire(struct rte_eth_dev *dev,
-			    struct mlx5_vf_vlan *vf_vlan);
-
 /* mlx5_flow_meter.c */
 
 int mlx5_flow_meter_ops_get(struct rte_eth_dev *dev, void *arg);
diff --git a/drivers/net/mlx5/mlx5_nl.c b/drivers/net/mlx5/mlx5_nl.c
index e7ba034..3fe4b6f 100644
--- a/drivers/net/mlx5/mlx5_nl.c
+++ b/drivers/net/mlx5/mlx5_nl.c
@@ -5,7 +5,6 @@
 
 #include <errno.h>
 #include <linux/if_link.h>
-#include <linux/netlink.h>
 #include <linux/rtnetlink.h>
 #include <net/if.h>
 #include <rdma/rdma_netlink.h>
@@ -18,8 +17,6 @@
 #include <unistd.h>
 
 #include <rte_errno.h>
-#include <rte_malloc.h>
-#include <rte_hypervisor.h>
 
 #include "mlx5.h"
 #include "mlx5_utils.h"
@@ -1072,7 +1069,8 @@ struct mlx5_nl_ifindex_data {
  *   0 on success, a negative errno value otherwise and rte_errno is set.
  */
 int
-mlx5_nl_switch_info(int nl, unsigned int ifindex, struct mlx5_switch_info *info)
+mlx5_nl_switch_info(int nl, unsigned int ifindex,
+		    struct mlx5_switch_info *info)
 {
 	uint32_t seq = random();
 	struct {
@@ -1116,12 +1114,12 @@ struct mlx5_nl_ifindex_data {
  * Delete VLAN network device by ifindex.
  *
  * @param[in] tcf
- *   Context object initialized by mlx5_vlan_vmwa_init().
+ *   Context object initialized by mlx5_nl_vlan_vmwa_init().
  * @param[in] ifindex
  *   Interface index of network device to delete.
  */
-static void
-mlx5_vlan_vmwa_delete(struct mlx5_vlan_vmwa_context *vmwa,
+void
+mlx5_nl_vlan_vmwa_delete(struct mlx5_nl_vlan_vmwa_context *vmwa,
 		      uint32_t ifindex)
 {
 	int ret;
@@ -1196,14 +1194,14 @@ struct mlx5_nl_ifindex_data {
  * Create network VLAN device with specified VLAN tag.
  *
  * @param[in] tcf
- *   Context object initialized by mlx5_vlan_vmwa_init().
+ *   Context object initialized by mlx5_nl_vlan_vmwa_init().
  * @param[in] ifindex
  *   Base network interface index.
  * @param[in] tag
  *   VLAN tag for VLAN network device to create.
  */
-static uint32_t
-mlx5_vlan_vmwa_create(struct mlx5_vlan_vmwa_context *vmwa,
+uint32_t
+mlx5_nl_vlan_vmwa_create(struct mlx5_nl_vlan_vmwa_context *vmwa,
 		      uint32_t ifindex,
 		      uint16_t tag)
 {
@@ -1269,134 +1267,3 @@ struct mlx5_nl_ifindex_data {
 	}
 	return ret;
 }
-
-/*
- * Release VLAN network device, created for VM workaround.
- *
- * @param[in] dev
- *   Ethernet device object, Netlink context provider.
- * @param[in] vlan
- *   Object representing the network device to release.
- */
-void mlx5_vlan_vmwa_release(struct rte_eth_dev *dev,
-			    struct mlx5_vf_vlan *vlan)
-{
-	struct mlx5_priv *priv = dev->data->dev_private;
-	struct mlx5_vlan_vmwa_context *vmwa = priv->vmwa_context;
-	struct mlx5_vlan_dev *vlan_dev = &vmwa->vlan_dev[0];
-
-	assert(vlan->created);
-	assert(priv->vmwa_context);
-	if (!vlan->created || !vmwa)
-		return;
-	vlan->created = 0;
-	assert(vlan_dev[vlan->tag].refcnt);
-	if (--vlan_dev[vlan->tag].refcnt == 0 &&
-	    vlan_dev[vlan->tag].ifindex) {
-		mlx5_vlan_vmwa_delete(vmwa, vlan_dev[vlan->tag].ifindex);
-		vlan_dev[vlan->tag].ifindex = 0;
-	}
-}
-
-/**
- * Acquire VLAN interface with specified tag for VM workaround.
- *
- * @param[in] dev
- *   Ethernet device object, Netlink context provider.
- * @param[in] vlan
- *   Object representing the network device to acquire.
- */
-void mlx5_vlan_vmwa_acquire(struct rte_eth_dev *dev,
-			    struct mlx5_vf_vlan *vlan)
-{
-	struct mlx5_priv *priv = dev->data->dev_private;
-	struct mlx5_vlan_vmwa_context *vmwa = priv->vmwa_context;
-	struct mlx5_vlan_dev *vlan_dev = &vmwa->vlan_dev[0];
-
-	assert(!vlan->created);
-	assert(priv->vmwa_context);
-	if (vlan->created || !vmwa)
-		return;
-	if (vlan_dev[vlan->tag].refcnt == 0) {
-		assert(!vlan_dev[vlan->tag].ifindex);
-		vlan_dev[vlan->tag].ifindex =
-			mlx5_vlan_vmwa_create(vmwa,
-					      vmwa->vf_ifindex,
-					      vlan->tag);
-	}
-	if (vlan_dev[vlan->tag].ifindex) {
-		vlan_dev[vlan->tag].refcnt++;
-		vlan->created = 1;
-	}
-}
-
-/*
- * Create per ethernet device VLAN VM workaround context
- */
-struct mlx5_vlan_vmwa_context *
-mlx5_vlan_vmwa_init(struct rte_eth_dev *dev,
-		    uint32_t ifindex)
-{
-	struct mlx5_priv *priv = dev->data->dev_private;
-	struct mlx5_dev_config *config = &priv->config;
-	struct mlx5_vlan_vmwa_context *vmwa;
-	enum rte_hypervisor hv_type;
-
-	/* Do not engage workaround over PF. */
-	if (!config->vf)
-		return NULL;
-	/* Check whether there is desired virtual environment */
-	hv_type = rte_hypervisor_get();
-	switch (hv_type) {
-	case RTE_HYPERVISOR_UNKNOWN:
-	case RTE_HYPERVISOR_VMWARE:
-		/*
-		 * The "white list" of configurations
-		 * to engage the workaround.
-		 */
-		break;
-	default:
-		/*
-		 * The configuration is not found in the "white list".
-		 * We should not engage the VLAN workaround.
-		 */
-		return NULL;
-	}
-	vmwa = rte_zmalloc(__func__, sizeof(*vmwa), sizeof(uint32_t));
-	if (!vmwa) {
-		DRV_LOG(WARNING,
-			"Can not allocate memory"
-			" for VLAN workaround context");
-		return NULL;
-	}
-	vmwa->nl_socket = mlx5_nl_init(NETLINK_ROUTE);
-	if (vmwa->nl_socket < 0) {
-		DRV_LOG(WARNING,
-			"Can not create Netlink socket"
-			" for VLAN workaround context");
-		rte_free(vmwa);
-		return NULL;
-	}
-	vmwa->nl_sn = random();
-	vmwa->vf_ifindex = ifindex;
-	vmwa->dev = dev;
-	/* Cleanup for existing VLAN devices. */
-	return vmwa;
-}
-
-/*
- * Destroy per ethernet device VLAN VM workaround context
- */
-void mlx5_vlan_vmwa_exit(struct mlx5_vlan_vmwa_context *vmwa)
-{
-	unsigned int i;
-
-	/* Delete all remaining VLAN devices. */
-	for (i = 0; i < RTE_DIM(vmwa->vlan_dev); i++) {
-		if (vmwa->vlan_dev[i].ifindex)
-			mlx5_vlan_vmwa_delete(vmwa, vmwa->vlan_dev[i].ifindex);
-	}
-	if (vmwa->nl_socket >= 0)
-		close(vmwa->nl_socket);
-	rte_free(vmwa);
-}
diff --git a/drivers/net/mlx5/mlx5_nl.h b/drivers/net/mlx5/mlx5_nl.h
new file mode 100644
index 0000000..7903673
--- /dev/null
+++ b/drivers/net/mlx5/mlx5_nl.h
@@ -0,0 +1,69 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright 2019 Mellanox Technologies, Ltd
+ */
+
+#ifndef RTE_PMD_MLX5_NL_H_
+#define RTE_PMD_MLX5_NL_H_
+
+#include <linux/netlink.h>
+
+
+/* Recognized Infiniband device physical port name types. */
+enum mlx5_nl_phys_port_name_type {
+	MLX5_PHYS_PORT_NAME_TYPE_NOTSET = 0, /* Not set. */
+	MLX5_PHYS_PORT_NAME_TYPE_LEGACY, /* before kernel ver < 5.0 */
+	MLX5_PHYS_PORT_NAME_TYPE_UPLINK, /* p0, kernel ver >= 5.0 */
+	MLX5_PHYS_PORT_NAME_TYPE_PFVF, /* pf0vf0, kernel ver >= 5.0 */
+	MLX5_PHYS_PORT_NAME_TYPE_UNKNOWN, /* Unrecognized. */
+};
+
+/** Switch information returned by mlx5_nl_switch_info(). */
+struct mlx5_switch_info {
+	uint32_t master:1; /**< Master device. */
+	uint32_t representor:1; /**< Representor device. */
+	enum mlx5_nl_phys_port_name_type name_type; /** < Port name type. */
+	int32_t pf_num; /**< PF number (valid for pfxvfx format only). */
+	int32_t port_name; /**< Representor port name. */
+	uint64_t switch_id; /**< Switch identifier. */
+};
+
+/* VLAN netdev for VLAN workaround. */
+struct mlx5_nl_vlan_dev {
+	uint32_t refcnt;
+	uint32_t ifindex; /**< Own interface index. */
+};
+
+/*
+ * Array of VLAN devices created on the base of VF
+ * used for workaround in virtual environments.
+ */
+struct mlx5_nl_vlan_vmwa_context {
+	int nl_socket;
+	uint32_t nl_sn;
+	uint32_t vf_ifindex;
+	struct mlx5_nl_vlan_dev vlan_dev[4096];
+};
+
+
+int mlx5_nl_init(int protocol);
+int mlx5_nl_mac_addr_add(struct rte_eth_dev *dev, struct rte_ether_addr *mac,
+			 uint32_t index);
+int mlx5_nl_mac_addr_remove(struct rte_eth_dev *dev, struct rte_ether_addr *mac,
+			    uint32_t index);
+void mlx5_nl_mac_addr_sync(struct rte_eth_dev *dev);
+void mlx5_nl_mac_addr_flush(struct rte_eth_dev *dev);
+int mlx5_nl_promisc(struct rte_eth_dev *dev, int enable);
+int mlx5_nl_allmulti(struct rte_eth_dev *dev, int enable);
+unsigned int mlx5_nl_portnum(int nl, const char *name);
+unsigned int mlx5_nl_ifindex(int nl, const char *name, uint32_t pindex);
+int mlx5_nl_vf_mac_addr_modify(struct rte_eth_dev *dev,
+			       struct rte_ether_addr *mac, int vf_index);
+int mlx5_nl_switch_info(int nl, unsigned int ifindex,
+			struct mlx5_switch_info *info);
+
+void mlx5_nl_vlan_vmwa_delete(struct mlx5_nl_vlan_vmwa_context *vmwa,
+			   uint32_t ifindex);
+uint32_t mlx5_nl_vlan_vmwa_create(struct mlx5_nl_vlan_vmwa_context *vmwa,
+				  uint32_t ifindex, uint16_t tag);
+
+#endif /* RTE_PMD_MLX5_NL_H_ */
diff --git a/drivers/net/mlx5/mlx5_vlan.c b/drivers/net/mlx5/mlx5_vlan.c
index b0fa31a..fb52d8f 100644
--- a/drivers/net/mlx5/mlx5_vlan.c
+++ b/drivers/net/mlx5/mlx5_vlan.c
@@ -7,6 +7,8 @@
 #include <errno.h>
 #include <assert.h>
 #include <stdint.h>
+#include <unistd.h>
+
 
 /*
  * Not needed by this file; included to work around the lack of off_t
@@ -26,6 +28,8 @@
 
 #include <rte_ethdev_driver.h>
 #include <rte_common.h>
+#include <rte_malloc.h>
+#include <rte_hypervisor.h>
 
 #include <mlx5_glue.h>
 #include <mlx5_devx_cmds.h>
@@ -33,6 +37,7 @@
 #include "mlx5.h"
 #include "mlx5_autoconf.h"
 #include "mlx5_rxtx.h"
+#include "mlx5_nl.h"
 #include "mlx5_utils.h"
 
 /**
@@ -193,3 +198,132 @@
 	}
 	return 0;
 }
+
+/*
+ * Release VLAN network device, created for VM workaround.
+ *
+ * @param[in] dev
+ *   Ethernet device object, Netlink context provider.
+ * @param[in] vlan
+ *   Object representing the network device to release.
+ */
+void mlx5_vlan_vmwa_release(struct rte_eth_dev *dev,
+			    struct mlx5_vf_vlan *vlan)
+{
+	struct mlx5_priv *priv = dev->data->dev_private;
+	struct mlx5_nl_vlan_vmwa_context *vmwa = priv->vmwa_context;
+	struct mlx5_nl_vlan_dev *vlan_dev = &vmwa->vlan_dev[0];
+
+	assert(vlan->created);
+	assert(priv->vmwa_context);
+	if (!vlan->created || !vmwa)
+		return;
+	vlan->created = 0;
+	assert(vlan_dev[vlan->tag].refcnt);
+	if (--vlan_dev[vlan->tag].refcnt == 0 &&
+	    vlan_dev[vlan->tag].ifindex) {
+		mlx5_nl_vlan_vmwa_delete(vmwa, vlan_dev[vlan->tag].ifindex);
+		vlan_dev[vlan->tag].ifindex = 0;
+	}
+}
+
+/**
+ * Acquire VLAN interface with specified tag for VM workaround.
+ *
+ * @param[in] dev
+ *   Ethernet device object, Netlink context provider.
+ * @param[in] vlan
+ *   Object representing the network device to acquire.
+ */
+void mlx5_vlan_vmwa_acquire(struct rte_eth_dev *dev,
+			    struct mlx5_vf_vlan *vlan)
+{
+	struct mlx5_priv *priv = dev->data->dev_private;
+	struct mlx5_nl_vlan_vmwa_context *vmwa = priv->vmwa_context;
+	struct mlx5_nl_vlan_dev *vlan_dev = &vmwa->vlan_dev[0];
+
+	assert(!vlan->created);
+	assert(priv->vmwa_context);
+	if (vlan->created || !vmwa)
+		return;
+	if (vlan_dev[vlan->tag].refcnt == 0) {
+		assert(!vlan_dev[vlan->tag].ifindex);
+		vlan_dev[vlan->tag].ifindex =
+			mlx5_nl_vlan_vmwa_create(vmwa, vmwa->vf_ifindex,
+						 vlan->tag);
+	}
+	if (vlan_dev[vlan->tag].ifindex) {
+		vlan_dev[vlan->tag].refcnt++;
+		vlan->created = 1;
+	}
+}
+
+/*
+ * Create per ethernet device VLAN VM workaround context
+ */
+struct mlx5_nl_vlan_vmwa_context *
+mlx5_vlan_vmwa_init(struct rte_eth_dev *dev, uint32_t ifindex)
+{
+	struct mlx5_priv *priv = dev->data->dev_private;
+	struct mlx5_dev_config *config = &priv->config;
+	struct mlx5_nl_vlan_vmwa_context *vmwa;
+	enum rte_hypervisor hv_type;
+
+	/* Do not engage workaround over PF. */
+	if (!config->vf)
+		return NULL;
+	/* Check whether there is desired virtual environment */
+	hv_type = rte_hypervisor_get();
+	switch (hv_type) {
+	case RTE_HYPERVISOR_UNKNOWN:
+	case RTE_HYPERVISOR_VMWARE:
+		/*
+		 * The "white list" of configurations
+		 * to engage the workaround.
+		 */
+		break;
+	default:
+		/*
+		 * The configuration is not found in the "white list".
+		 * We should not engage the VLAN workaround.
+		 */
+		return NULL;
+	}
+	vmwa = rte_zmalloc(__func__, sizeof(*vmwa), sizeof(uint32_t));
+	if (!vmwa) {
+		DRV_LOG(WARNING,
+			"Can not allocate memory"
+			" for VLAN workaround context");
+		return NULL;
+	}
+	vmwa->nl_socket = mlx5_nl_init(NETLINK_ROUTE);
+	if (vmwa->nl_socket < 0) {
+		DRV_LOG(WARNING,
+			"Can not create Netlink socket"
+			" for VLAN workaround context");
+		rte_free(vmwa);
+		return NULL;
+	}
+	vmwa->nl_sn = random();
+	vmwa->vf_ifindex = ifindex;
+	/* Cleanup for existing VLAN devices. */
+	return vmwa;
+}
+
+/*
+ * Destroy per ethernet device VLAN VM workaround context
+ */
+void mlx5_vlan_vmwa_exit(struct mlx5_nl_vlan_vmwa_context *vmwa)
+{
+	unsigned int i;
+
+	/* Delete all remaining VLAN devices. */
+	for (i = 0; i < RTE_DIM(vmwa->vlan_dev); i++) {
+		if (vmwa->vlan_dev[i].ifindex)
+			mlx5_nl_vlan_vmwa_delete(vmwa,
+						 vmwa->vlan_dev[i].ifindex);
+	}
+	if (vmwa->nl_socket >= 0)
+		close(vmwa->nl_socket);
+	rte_free(vmwa);
+}
