diff --git a/drivers/net/sssnic/base/sssnic_api.c b/drivers/net/sssnic/base/sssnic_api.c
index 0e965442fd..2d829bc884 100644
--- a/drivers/net/sssnic/base/sssnic_api.c
+++ b/drivers/net/sssnic/base/sssnic_api.c
@@ -1899,3 +1899,45 @@ sssnic_tcam_entry_del(struct sssnic_hw *hw, uint32_t entry_idx)
 
 	return 0;
 }
+
+static int
+sssnic_vf_port_register_op(struct sssnic_hw *hw, bool op)
+{
+	int ret;
+	struct sssnic_vf_port_register_cmd cmd;
+	struct sssnic_msg msg;
+	uint32_t cmd_len;
+
+	memset(&cmd, 0, sizeof(cmd));
+	cmd.op = op ? 1 : 0;
+	cmd_len = sizeof(cmd);
+	sssnic_msg_init(&msg, (uint8_t *)&cmd, cmd_len,
+		SSSNIC_REGISTER_VF_PORT_CMD, SSSNIC_PF_FUNC_IDX(hw),
+		SSSNIC_LAN_MODULE, SSSNIC_MSG_TYPE_REQ);
+	ret = sssnic_mbox_send(hw, &msg, (uint8_t *)&cmd, &cmd_len, 0);
+	if (ret != 0) {
+		PMD_DRV_LOG(ERR, "Failed to send mbox message, ret=%d", ret);
+		return ret;
+	}
+
+	if (cmd_len == 0 || cmd.common.status != 0) {
+		PMD_DRV_LOG(ERR,
+			"Bad response to SSSNIC_REGISTER_VF_PORT_CMD, len=%u, status=%u",
+			cmd_len, cmd.common.status);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+int
+sssnic_vf_port_register(struct sssnic_hw *hw)
+{
+	return sssnic_vf_port_register_op(hw, true);
+}
+
+int
+sssnic_vf_port_unregister(struct sssnic_hw *hw)
+{
+	return sssnic_vf_port_register_op(hw, false);
+}
diff --git a/drivers/net/sssnic/base/sssnic_api.h b/drivers/net/sssnic/base/sssnic_api.h
index 7a02ec61ee..2506682821 100644
--- a/drivers/net/sssnic/base/sssnic_api.h
+++ b/drivers/net/sssnic/base/sssnic_api.h
@@ -492,5 +492,7 @@ int sssnic_tcam_packet_type_filter_set(struct sssnic_hw *hw, uint8_t ptype,
 int sssnic_tcam_entry_add(struct sssnic_hw *hw,
 	struct sssnic_tcam_entry *entry);
 int sssnic_tcam_entry_del(struct sssnic_hw *hw, uint32_t entry_idx);
+int sssnic_vf_port_register(struct sssnic_hw *hw);
+int sssnic_vf_port_unregister(struct sssnic_hw *hw);
 
 #endif /* _SSSNIC_API_H_ */
diff --git a/drivers/net/sssnic/base/sssnic_cmd.h b/drivers/net/sssnic/base/sssnic_cmd.h
index c75cb0dad3..058ab298f3 100644
--- a/drivers/net/sssnic/base/sssnic_cmd.h
+++ b/drivers/net/sssnic/base/sssnic_cmd.h
@@ -505,4 +505,10 @@ struct sssnic_tcam_entry_del_cmd {
 	uint32_t num; /* number of entries to be deleted */
 };
 
+struct sssnic_vf_port_register_cmd {
+	struct sssnic_cmd_common common;
+	uint8_t op; /* 0: unregister, 1: register */
+	uint8_t resvd[39];
+};
+
 #endif /* _SSSNIC_CMD_H_ */
diff --git a/drivers/net/sssnic/base/sssnic_hw.c b/drivers/net/sssnic/base/sssnic_hw.c
index 651a0aa7ef..0edd5b9508 100644
--- a/drivers/net/sssnic/base/sssnic_hw.c
+++ b/drivers/net/sssnic/base/sssnic_hw.c
@@ -345,10 +345,16 @@ sssnic_base_init(struct sssnic_hw *hw)
 	pci_dev = hw->pci_dev;
 
 	/* get base addresses of hw registers */
-	hw->cfg_base_addr =
-		(uint8_t *)pci_dev->mem_resource[SSSNIC_PCI_BAR_CFG].addr;
-	hw->mgmt_base_addr =
-		(uint8_t *)pci_dev->mem_resource[SSSNIC_PCI_BAR_MGMT].addr;
+	if (pci_dev->id.device_id == SSSNIC_VF_DEVICE_ID) {
+		uint8_t *addr =
+			(uint8_t *)pci_dev->mem_resource[SSSNIC_VF_PCI_BAR_CFG].addr;
+		hw->cfg_base_addr = addr + SSSNIC_VF_CFG_ADDR_OFFSET;
+	} else {
+		hw->cfg_base_addr =
+			(uint8_t *)pci_dev->mem_resource[SSSNIC_PCI_BAR_CFG].addr;
+		hw->mgmt_base_addr =
+			(uint8_t *)pci_dev->mem_resource[SSSNIC_PCI_BAR_MGMT].addr;
+	}
 	hw->db_base_addr =
 		(uint8_t *)pci_dev->mem_resource[SSSNIC_PCI_BAR_DB].addr;
 	hw->db_mem_len =
@@ -365,7 +371,10 @@ sssnic_base_init(struct sssnic_hw *hw)
 		PMD_DRV_LOG(ERR, "Doorbell is not enabled!");
 		return -EBUSY;
 	}
-	sssnic_af_setup(hw);
+
+	if (SSSNIC_FUNC_TYPE(hw) != SSSNIC_FUNC_TYPE_VF)
+		sssnic_af_setup(hw);
+
 	sssnic_msix_all_disable(hw);
 	sssnic_pf_status_set(hw, SSSNIC_PF_STATUS_INIT);
 
diff --git a/drivers/net/sssnic/base/sssnic_hw.h b/drivers/net/sssnic/base/sssnic_hw.h
index 6a2d980d5a..9d8a3653a7 100644
--- a/drivers/net/sssnic/base/sssnic_hw.h
+++ b/drivers/net/sssnic/base/sssnic_hw.h
@@ -7,11 +7,15 @@
 
 #define SSSNIC_PCI_VENDOR_ID 0x1F3F
 #define SSSNIC_DEVICE_ID_STD 0x9020
+#define SSSNIC_VF_DEVICE_ID 0x9001
 
+#define SSSNIC_VF_PCI_BAR_CFG 0
 #define SSSNIC_PCI_BAR_CFG 1
 #define SSSNIC_PCI_BAR_MGMT 3
 #define SSSNIC_PCI_BAR_DB 4
 
+#define SSSNIC_VF_CFG_ADDR_OFFSET 0x2000
+
 #define SSSNIC_FUNC_TYPE_PF 0
 #define SSSNIC_FUNC_TYPE_VF 1
 #define SSSNIC_FUNC_TYPE_AF 2
diff --git a/drivers/net/sssnic/sssnic_ethdev.c b/drivers/net/sssnic/sssnic_ethdev.c
index d58a1350c4..4025778a43 100644
--- a/drivers/net/sssnic/sssnic_ethdev.c
+++ b/drivers/net/sssnic/sssnic_ethdev.c
@@ -350,6 +350,8 @@ sssnic_ethdev_release(struct rte_eth_dev *ethdev)
 	sssnic_ethdev_rx_queue_all_release(ethdev);
 	sssnic_ethdev_fdir_shutdown(ethdev);
 	sssnic_ethdev_mac_addrs_clean(ethdev);
+	if (SSSNIC_FUNC_TYPE(hw) == SSSNIC_FUNC_TYPE_VF)
+		sssnic_vf_port_unregister(hw);
 	sssnic_hw_shutdown(hw);
 	rte_free(hw);
 }
@@ -958,6 +960,47 @@ static const struct eth_dev_ops sssnic_ethdev_ops = {
 	.flow_ops_get = sssnic_ethdev_flow_ops_get,
 };
 
+static const struct eth_dev_ops sssnic_vf_ethdev_ops = {
+	.dev_start = sssnic_ethdev_start,
+	.dev_stop = sssnic_ethdev_stop,
+	.dev_close = sssnic_ethdev_close,
+	.link_update = sssnic_ethdev_link_update,
+	.dev_configure = sssnic_ethdev_configure,
+	.dev_infos_get = sssnic_ethdev_infos_get,
+	.mtu_set = sssnic_ethdev_mtu_set,
+	.mac_addr_set = sssnic_ethdev_mac_addr_set,
+	.mac_addr_remove = sssnic_ethdev_mac_addr_remove,
+	.mac_addr_add = sssnic_ethdev_mac_addr_add,
+	.set_mc_addr_list = sssnic_ethdev_set_mc_addr_list,
+	.rx_queue_setup = sssnic_ethdev_rx_queue_setup,
+	.rx_queue_release = sssnic_ethdev_rx_queue_release,
+	.tx_queue_setup = sssnic_ethdev_tx_queue_setup,
+	.tx_queue_release = sssnic_ethdev_tx_queue_release,
+	.rx_queue_start = sssnic_ethdev_rx_queue_start,
+	.rx_queue_stop = sssnic_ethdev_rx_queue_stop,
+	.tx_queue_start = sssnic_ethdev_tx_queue_start,
+	.tx_queue_stop = sssnic_ethdev_tx_queue_stop,
+	.rx_queue_intr_enable = sssnic_ethdev_rx_queue_intr_enable,
+	.rx_queue_intr_disable = sssnic_ethdev_rx_queue_intr_disable,
+	.allmulticast_enable = sssnic_ethdev_allmulticast_enable,
+	.allmulticast_disable = sssnic_ethdev_allmulticast_disable,
+	.stats_get = sssnic_ethdev_stats_get,
+	.stats_reset = sssnic_ethdev_stats_reset,
+	.xstats_get_names = sssnic_ethdev_xstats_get_names,
+	.xstats_get = sssnic_ethdev_xstats_get,
+	.xstats_reset = sssnic_ethdev_xstats_reset,
+	.rss_hash_conf_get = sssnic_ethdev_rss_hash_config_get,
+	.rss_hash_update = sssnic_ethdev_rss_hash_update,
+	.reta_update = sssnic_ethdev_rss_reta_update,
+	.reta_query = sssnic_ethdev_rss_reta_query,
+	.rxq_info_get = sssnic_ethdev_rx_queue_info_get,
+	.txq_info_get = sssnic_ethdev_tx_queue_info_get,
+	.fw_version_get = sssnic_ethdev_fw_version_get,
+	.vlan_offload_set = sssnic_ethdev_vlan_offload_set,
+	.vlan_filter_set = sssnic_ethdev_vlan_filter_set,
+	.flow_ops_get = sssnic_ethdev_flow_ops_get,
+};
+
 static int
 sssnic_ethdev_init(struct rte_eth_dev *ethdev)
 {
@@ -990,6 +1033,14 @@ sssnic_ethdev_init(struct rte_eth_dev *ethdev)
 		return ret;
 	}
 
+	if (SSSNIC_FUNC_TYPE(hw) == SSSNIC_FUNC_TYPE_VF) {
+		ret = sssnic_vf_port_register(hw);
+		if (ret != 0) {
+			PMD_DRV_LOG(ERR, "Failed to register VF device");
+			goto vf_register_fail;
+		}
+	}
+
 	ret = sssnic_ethdev_mac_addrs_init(ethdev);
 	if (ret != 0) {
 		PMD_DRV_LOG(ERR, "Failed to initialize MAC addresses");
@@ -1005,7 +1056,10 @@ sssnic_ethdev_init(struct rte_eth_dev *ethdev)
 	netdev->max_num_rxq = SSSNIC_MAX_NUM_RXQ(hw);
 	netdev->max_num_txq = SSSNIC_MAX_NUM_TXQ(hw);
 
-	ethdev->dev_ops = &sssnic_ethdev_ops;
+	if (SSSNIC_FUNC_TYPE(hw) == SSSNIC_FUNC_TYPE_VF)
+		ethdev->dev_ops = &sssnic_vf_ethdev_ops;
+	else
+		ethdev->dev_ops = &sssnic_ethdev_ops;
 
 	sssnic_ethdev_link_update(ethdev, 0);
 	sssnic_ethdev_link_intr_enable(ethdev);
@@ -1015,6 +1069,9 @@ sssnic_ethdev_init(struct rte_eth_dev *ethdev)
 fdir_init_fail:
 	sssnic_ethdev_mac_addrs_clean(ethdev);
 mac_addrs_init_fail:
+	if (SSSNIC_FUNC_TYPE(hw) == SSSNIC_FUNC_TYPE_VF)
+		sssnic_vf_port_unregister(hw);
+vf_register_fail:
 	sssnic_hw_shutdown(0);
 	return ret;
 }
@@ -1060,6 +1117,7 @@ sssnic_pci_remove(struct rte_pci_device *pci_dev)
 
 static const struct rte_pci_id sssnic_pci_id_map[] = {
 	{ RTE_PCI_DEVICE(SSSNIC_PCI_VENDOR_ID, SSSNIC_DEVICE_ID_STD) },
+	{ RTE_PCI_DEVICE(SSSNIC_PCI_VENDOR_ID, SSSNIC_VF_DEVICE_ID) },
 	{ .vendor_id = 0 },
 };
 
diff --git a/drivers/net/sssnic/sssnic_ethdev_stats.c b/drivers/net/sssnic/sssnic_ethdev_stats.c
index 3397a6f62e..48d9f7c1db 100644
--- a/drivers/net/sssnic/sssnic_ethdev_stats.c
+++ b/drivers/net/sssnic/sssnic_ethdev_stats.c
@@ -245,9 +245,19 @@ sssnic_ethdev_stats_reset(struct rte_eth_dev *ethdev)
 static uint32_t
 sssnic_ethdev_xstats_num_calc(struct rte_eth_dev *ethdev)
 {
-	return SSSNIC_ETHDEV_NB_PORT_XSTATS + SSSNIC_ETHDEV_NB_MAC_XSTATS +
-	       (SSSNIC_ETHDEV_NB_TXQ_XSTATS * ethdev->data->nb_tx_queues) +
-	       (SSSNIC_ETHDEV_NB_RXQ_XSTATS * ethdev->data->nb_rx_queues);
+	struct sssnic_hw *hw = SSSNIC_ETHDEV_TO_HW(ethdev);
+	uint32_t num;
+
+	num = SSSNIC_ETHDEV_NB_PORT_XSTATS;
+	num += SSSNIC_ETHDEV_NB_TXQ_XSTATS * ethdev->data->nb_tx_queues;
+	num += SSSNIC_ETHDEV_NB_RXQ_XSTATS * ethdev->data->nb_rx_queues;
+
+	if (SSSNIC_FUNC_TYPE(hw) == SSSNIC_FUNC_TYPE_VF)
+		return num;
+
+	num += SSSNIC_ETHDEV_NB_MAC_XSTATS;
+
+	return num;
 }
 
 int
@@ -256,6 +266,7 @@ sssnic_ethdev_xstats_get_names(struct rte_eth_dev *ethdev,
 	__rte_unused unsigned int limit)
 {
 	uint16_t i, qid, count = 0;
+	struct sssnic_hw *hw = SSSNIC_ETHDEV_TO_HW(ethdev);
 
 	if (xstats_names == NULL)
 		return sssnic_ethdev_xstats_num_calc(ethdev);
@@ -284,6 +295,9 @@ sssnic_ethdev_xstats_get_names(struct rte_eth_dev *ethdev,
 		count++;
 	}
 
+	if (SSSNIC_FUNC_TYPE(hw) == SSSNIC_FUNC_TYPE_VF)
+		return count;
+
 	for (i = 0; i < SSSNIC_ETHDEV_NB_MAC_XSTATS; i++) {
 		snprintf(xstats_names[count].name, RTE_ETH_XSTATS_NAME_SIZE,
 			"mac_%s", mac_stats_strings[i].name);
@@ -349,6 +363,11 @@ sssnic_ethdev_xstats_get(struct rte_eth_dev *ethdev,
 		count++;
 	}
 
+	if (SSSNIC_FUNC_TYPE(hw) == SSSNIC_FUNC_TYPE_VF) {
+		ret = count;
+		goto out;
+	}
+
 	ret = sssnic_mac_stats_get(hw, &stats->mac);
 	if (ret) {
 		PMD_DRV_LOG(ERR, "Failed to get port %u mac stats",
@@ -373,6 +392,7 @@ int
 sssnic_ethdev_xstats_reset(struct rte_eth_dev *ethdev)
 {
 	int ret;
+	struct sssnic_hw *hw = SSSNIC_ETHDEV_TO_HW(ethdev);
 
 	ret = sssnic_ethdev_stats_reset(ethdev);
 	if (ret) {
@@ -381,6 +401,9 @@ sssnic_ethdev_xstats_reset(struct rte_eth_dev *ethdev)
 		return ret;
 	}
 
+	if (SSSNIC_FUNC_TYPE(hw) == SSSNIC_FUNC_TYPE_VF)
+		return 0;
+
 	ret = sssnic_mac_stats_clear(SSSNIC_ETHDEV_TO_HW(ethdev));
 	if (ret) {
 		PMD_DRV_LOG(ERR, "Failed to clear port %u MAC stats",
