hw->qcp_cfg = hw->tx_bar + NFP_QCP_QUEUE_ADDR_SZ;
 }
 
-static void nfp_net_read_mac(struct nfp_net_hw *hw)
+#define ETH_ADDR_LEN   6
+
+static void
+nfp_eth_copy_mac_reverse(uint8_t *dst, const uint8_t *src)
+{
+       int i;
+
+       for (i = 0; i < ETH_ADDR_LEN; i++)
+               dst[ETH_ADDR_LEN - i - 1] = src[i];
+}
+
+static int
+nfp_net_pf_read_mac(struct nfp_net_hw *hw, int port)
+{
+       union eth_table_entry *entry;
+       int idx, i;
+
+       idx = port;
+       entry = hw->eth_table;
+
+       /* Reading NFP ethernet table obtained before */
+       for (i = 0; i < NSP_ETH_MAX_COUNT; i++) {
+               if (!(entry->port & NSP_ETH_PORT_LANES_MASK)) {
+                       /* port not in use */
+                       entry++;
+                       continue;
+               }
+               if (idx == 0)
+                       break;
+               idx--;
+               entry++;
+       }
+
+       if (i == NSP_ETH_MAX_COUNT)
+               return -EINVAL;
+
+       /*
+        * hw points to port0 private data. We need hw now pointing to
+        * right port.
+        */
+       hw += port;
+       nfp_eth_copy_mac_reverse((uint8_t *)&hw->mac_addr,
+                                (uint8_t *)&entry->mac_addr);
+
+       return 0;
+}
+
+static void
+nfp_net_vf_read_mac(struct nfp_net_hw *hw)
 {
        uint32_t tmp;
 
 
                /* vNIC PF tx/rx BARs are a subset of PF PCI device */
                hwport0->hw_queues += bar_offset;
+
+               /* Lets seize the chance to read eth table from hw */
+               if (nfp_nsp_eth_read_table(nspu_desc, &hw->eth_table))
+                       return -ENODEV;
        }
 
        if (hw->is_pf) {
                return -ENOMEM;
        }
 
-       nfp_net_read_mac(hw);
+       if (hw->is_pf)
+               nfp_net_pf_read_mac(hwport0, port);
+       else
+               nfp_net_vf_read_mac(hw);
 
        if (!is_valid_assigned_ether_addr((struct ether_addr *)&hw->mac_addr)) {
                /* Using random mac addresses for VFs */
 
 #include <rte_byteorder.h>
 
 #include "nfp_nfpu.h"
-#include "nfp_net_eth.h"
 
 #define CFG_EXP_BAR_ADDR_SZ     1
 #define CFG_EXP_BAR_MAP_TYPE   1
        rte_spinlock_unlock(&desc->nsp_lock);
        return ret;
 }
+
+int
+nfp_nsp_eth_read_table(nspu_desc_t *desc, union eth_table_entry **table)
+{
+       int ret;
+
+       RTE_LOG(INFO, PMD, "Reading hw ethernet table...\n");
+       /* port 0 allocates the eth table and read it using NSPU */
+       *table = malloc(NSP_ETH_TABLE_SIZE);
+       if (!table)
+               return -ENOMEM;
+
+       ret = nspu_command(desc, NSP_CMD_READ_ETH_TABLE, 1, 0, *table,
+                          NSP_ETH_TABLE_SIZE, 0);
+       if (ret)
+               return ret;
+
+       RTE_LOG(INFO, PMD, "Done\n");
+
+       return 0;
+}
 
  */
 
 #include <rte_spinlock.h>
+#include "nfp_net_eth.h"
 
 typedef struct {
        int nfp;        /* NFP device */
 int nfp_nsp_map_ctrl_bar(nspu_desc_t *desc, uint64_t *pcie_offset);
 void nfp_nsp_map_queues_bar(nspu_desc_t *desc, uint64_t *pcie_offset);
 int nfp_nsp_eth_config(nspu_desc_t *desc, int port, int up);
+int nfp_nsp_eth_read_table(nspu_desc_t *desc, union eth_table_entry **table);