All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jiawen Wu <jiawenwu@trustnetic.com>
To: dev@dpdk.org
Cc: Jiawen Wu <jiawenwu@trustnetic.com>
Subject: [dpdk-dev] [PATCH v1 03/20] net/txgbe: support add and remove VF device MAC address
Date: Fri, 22 Jan 2021 17:47:43 +0800	[thread overview]
Message-ID: <20210122094800.197748-4-jiawenwu@trustnetic.com> (raw)
In-Reply-To: <20210122094800.197748-1-jiawenwu@trustnetic.com>

Generate a random MAC address if none was assigned by PF during
the initialization of VF device. And support to add and remove
MAC address.

Signed-off-by: Jiawen Wu <jiawenwu@trustnetic.com>
---
 drivers/net/txgbe/base/txgbe_vf.c   | 102 +++++++++++++++++
 drivers/net/txgbe/base/txgbe_vf.h   |   5 +
 drivers/net/txgbe/txgbe_ethdev_vf.c | 168 ++++++++++++++++++++++++++++
 3 files changed, 275 insertions(+)

diff --git a/drivers/net/txgbe/base/txgbe_vf.c b/drivers/net/txgbe/base/txgbe_vf.c
index 30bc0e40d..bcd34bfa2 100644
--- a/drivers/net/txgbe/base/txgbe_vf.c
+++ b/drivers/net/txgbe/base/txgbe_vf.c
@@ -21,9 +21,16 @@ s32 txgbe_init_ops_vf(struct txgbe_hw *hw)
 
 	/* MAC */
 	mac->reset_hw = txgbe_reset_hw_vf;
+	mac->start_hw = txgbe_start_hw_vf;
+	/* Cannot clear stats on VF */
+	mac->get_mac_addr = txgbe_get_mac_addr_vf;
 	mac->stop_hw = txgbe_stop_hw_vf;
 	mac->negotiate_api_version = txgbevf_negotiate_api_version;
 
+	/* RAR, Multicast, VLAN */
+	mac->set_rar = txgbe_set_rar_vf;
+	mac->set_uc_addr = txgbevf_set_uc_addr_vf;
+
 	mac->max_tx_queues = 1;
 	mac->max_rx_queues = 1;
 
@@ -60,6 +67,23 @@ static void txgbe_virt_clr_reg(struct txgbe_hw *hw)
 	txgbe_flush(hw);
 }
 
+/**
+ *  txgbe_start_hw_vf - Prepare hardware for Tx/Rx
+ *  @hw: pointer to hardware structure
+ *
+ *  Starts the hardware by filling the bus info structure and media type, clears
+ *  all on chip counters, initializes receive address registers, multicast
+ *  table, VLAN filter table, calls routine to set up link and flow control
+ *  settings, and leaves transmit and receive units disabled and uninitialized
+ **/
+s32 txgbe_start_hw_vf(struct txgbe_hw *hw)
+{
+	/* Clear adapter stopped flag */
+	hw->adapter_stopped = false;
+
+	return 0;
+}
+
 /**
  *  txgbe_reset_hw_vf - Performs hardware reset
  *  @hw: pointer to hardware structure
@@ -195,6 +219,84 @@ STATIC s32 txgbevf_write_msg_read_ack(struct txgbe_hw *hw, u32 *msg,
 	return mbx->read_posted(hw, retmsg, size, 0);
 }
 
+/**
+ *  txgbe_set_rar_vf - set device MAC address
+ *  @hw: pointer to hardware structure
+ *  @index: Receive address register to write
+ *  @addr: Address to put into receive address register
+ *  @vmdq: VMDq "set" or "pool" index
+ *  @enable_addr: set flag that address is active
+ **/
+s32 txgbe_set_rar_vf(struct txgbe_hw *hw, u32 index, u8 *addr, u32 vmdq,
+		     u32 enable_addr)
+{
+	u32 msgbuf[3];
+	u8 *msg_addr = (u8 *)(&msgbuf[1]);
+	s32 ret_val;
+	UNREFERENCED_PARAMETER(vmdq, enable_addr, index);
+
+	memset(msgbuf, 0, 12);
+	msgbuf[0] = TXGBE_VF_SET_MAC_ADDR;
+	memcpy(msg_addr, addr, 6);
+	ret_val = txgbevf_write_msg_read_ack(hw, msgbuf, msgbuf, 3);
+
+	msgbuf[0] &= ~TXGBE_VT_MSGTYPE_CTS;
+
+	/* if nacked the address was rejected, use "perm_addr" */
+	if (!ret_val &&
+	    (msgbuf[0] == (TXGBE_VF_SET_MAC_ADDR | TXGBE_VT_MSGTYPE_NACK))) {
+		txgbe_get_mac_addr_vf(hw, hw->mac.addr);
+		return TXGBE_ERR_MBX;
+	}
+
+	return ret_val;
+}
+
+/**
+ * txgbe_get_mac_addr_vf - Read device MAC address
+ * @hw: pointer to the HW structure
+ * @mac_addr: the MAC address
+ **/
+s32 txgbe_get_mac_addr_vf(struct txgbe_hw *hw, u8 *mac_addr)
+{
+	int i;
+
+	for (i = 0; i < ETH_ADDR_LEN; i++)
+		mac_addr[i] = hw->mac.perm_addr[i];
+
+	return 0;
+}
+
+s32 txgbevf_set_uc_addr_vf(struct txgbe_hw *hw, u32 index, u8 *addr)
+{
+	u32 msgbuf[3], msgbuf_chk;
+	u8 *msg_addr = (u8 *)(&msgbuf[1]);
+	s32 ret_val;
+
+	memset(msgbuf, 0, sizeof(msgbuf));
+	/*
+	 * If index is one then this is the start of a new list and needs
+	 * indication to the PF so it can do it's own list management.
+	 * If it is zero then that tells the PF to just clear all of
+	 * this VF's macvlans and there is no new list.
+	 */
+	msgbuf[0] |= index << TXGBE_VT_MSGINFO_SHIFT;
+	msgbuf[0] |= TXGBE_VF_SET_MACVLAN;
+	msgbuf_chk = msgbuf[0];
+	if (addr)
+		memcpy(msg_addr, addr, 6);
+
+	ret_val = txgbevf_write_msg_read_ack(hw, msgbuf, msgbuf, 3);
+	if (!ret_val) {
+		msgbuf[0] &= ~TXGBE_VT_MSGTYPE_CTS;
+
+		if (msgbuf[0] == (msgbuf_chk | TXGBE_VT_MSGTYPE_NACK))
+			return TXGBE_ERR_OUT_OF_MEM;
+	}
+
+	return ret_val;
+}
+
 /**
  *  txgbevf_negotiate_api_version - Negotiate supported API version
  *  @hw: pointer to the HW structure
diff --git a/drivers/net/txgbe/base/txgbe_vf.h b/drivers/net/txgbe/base/txgbe_vf.h
index 70f90c262..f8c6532f6 100644
--- a/drivers/net/txgbe/base/txgbe_vf.h
+++ b/drivers/net/txgbe/base/txgbe_vf.h
@@ -11,8 +11,13 @@
 #define TXGBE_VF_MAX_RX_QUEUES	8
 
 s32 txgbe_init_ops_vf(struct txgbe_hw *hw);
+s32 txgbe_start_hw_vf(struct txgbe_hw *hw);
 s32 txgbe_reset_hw_vf(struct txgbe_hw *hw);
 s32 txgbe_stop_hw_vf(struct txgbe_hw *hw);
+s32 txgbe_get_mac_addr_vf(struct txgbe_hw *hw, u8 *mac_addr);
+s32 txgbe_set_rar_vf(struct txgbe_hw *hw, u32 index, u8 *addr, u32 vmdq,
+		     u32 enable_addr);
+s32 txgbevf_set_uc_addr_vf(struct txgbe_hw *hw, u32 index, u8 *addr);
 int txgbevf_negotiate_api_version(struct txgbe_hw *hw, int api);
 int txgbevf_get_queues(struct txgbe_hw *hw, unsigned int *num_tcs,
 		       unsigned int *default_tc);
diff --git a/drivers/net/txgbe/txgbe_ethdev_vf.c b/drivers/net/txgbe/txgbe_ethdev_vf.c
index a6bead4d1..62b1568cb 100644
--- a/drivers/net/txgbe/txgbe_ethdev_vf.c
+++ b/drivers/net/txgbe/txgbe_ethdev_vf.c
@@ -19,6 +19,7 @@
 static int txgbevf_dev_close(struct rte_eth_dev *dev);
 static void txgbevf_intr_disable(struct rte_eth_dev *dev);
 static void txgbevf_intr_enable(struct rte_eth_dev *dev);
+static void txgbevf_remove_mac_addr(struct rte_eth_dev *dev, uint32_t index);
 
 /*
  * The set of PCI devices this driver supports (for VF)
@@ -57,6 +58,22 @@ txgbevf_negotiate_api(struct txgbe_hw *hw)
 	}
 }
 
+static void
+generate_random_mac_addr(struct rte_ether_addr *mac_addr)
+{
+	uint64_t random;
+
+	/* Set Organizationally Unique Identifier (OUI) prefix. */
+	mac_addr->addr_bytes[0] = 0x00;
+	mac_addr->addr_bytes[1] = 0x09;
+	mac_addr->addr_bytes[2] = 0xC0;
+	/* Force indication of locally assigned MAC address. */
+	mac_addr->addr_bytes[0] |= RTE_ETHER_LOCAL_ADMIN_ADDR;
+	/* Generate the last 3 bytes of the MAC address with a random number. */
+	random = rte_rand();
+	memcpy(&mac_addr->addr_bytes[3], &random, 3);
+}
+
 /*
  * Virtual Function device init
  */
@@ -67,6 +84,8 @@ eth_txgbevf_dev_init(struct rte_eth_dev *eth_dev)
 	uint32_t tc, tcs;
 	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
 	struct txgbe_hw *hw = TXGBE_DEV_HW(eth_dev);
+	struct rte_ether_addr *perm_addr =
+			(struct rte_ether_addr *)hw->mac.perm_addr;
 
 	PMD_INIT_FUNC_TRACE();
 
@@ -142,8 +161,53 @@ eth_txgbevf_dev_init(struct rte_eth_dev *eth_dev)
 	/* Get Rx/Tx queue count via mailbox, which is ready after reset_hw */
 	txgbevf_get_queues(hw, &tcs, &tc);
 
+	/* Allocate memory for storing MAC addresses */
+	eth_dev->data->mac_addrs = rte_zmalloc("txgbevf", RTE_ETHER_ADDR_LEN *
+					       hw->mac.num_rar_entries, 0);
+	if (eth_dev->data->mac_addrs == NULL) {
+		PMD_INIT_LOG(ERR,
+			     "Failed to allocate %u bytes needed to store "
+			     "MAC addresses",
+			     RTE_ETHER_ADDR_LEN * hw->mac.num_rar_entries);
+		return -ENOMEM;
+	}
+
+	/* Generate a random MAC address, if none was assigned by PF. */
+	if (rte_is_zero_ether_addr(perm_addr)) {
+		generate_random_mac_addr(perm_addr);
+		err = txgbe_set_rar_vf(hw, 1, perm_addr->addr_bytes, 0, 1);
+		if (err) {
+			rte_free(eth_dev->data->mac_addrs);
+			eth_dev->data->mac_addrs = NULL;
+			return err;
+		}
+		PMD_INIT_LOG(INFO, "\tVF MAC address not assigned by Host PF");
+		PMD_INIT_LOG(INFO, "\tAssign randomly generated MAC address "
+			     "%02x:%02x:%02x:%02x:%02x:%02x",
+			     perm_addr->addr_bytes[0],
+			     perm_addr->addr_bytes[1],
+			     perm_addr->addr_bytes[2],
+			     perm_addr->addr_bytes[3],
+			     perm_addr->addr_bytes[4],
+			     perm_addr->addr_bytes[5]);
+	}
+
+	/* Copy the permanent MAC address */
+	rte_ether_addr_copy(perm_addr, &eth_dev->data->mac_addrs[0]);
+
+	/* reset the hardware with the new settings */
+	err = hw->mac.start_hw(hw);
+	if (err) {
+		PMD_INIT_LOG(ERR, "VF Initialization Failure: %d", err);
+		return -EIO;
+	}
+
 	txgbevf_intr_enable(eth_dev);
 
+	PMD_INIT_LOG(DEBUG, "port %d vendorID=0x%x deviceID=0x%x mac.type=%s",
+		     eth_dev->data->port_id, pci_dev->id.vendor_id,
+		     pci_dev->id.device_id, "txgbe_mac_raptor_vf");
+
 	return 0;
 }
 
@@ -232,11 +296,112 @@ txgbevf_dev_close(struct rte_eth_dev *dev)
 
 	txgbe_dev_free_queues(dev);
 
+	/**
+	 * Remove the VF MAC address ro ensure
+	 * that the VF traffic goes to the PF
+	 * after stop, close and detach of the VF
+	 **/
+	txgbevf_remove_mac_addr(dev, 0);
+
 	dev->dev_ops = NULL;
 
 	/* Disable the interrupts for VF */
 	txgbevf_intr_disable(dev);
 
+	rte_free(dev->data->mac_addrs);
+	dev->data->mac_addrs = NULL;
+
+	return 0;
+}
+
+static int
+txgbevf_add_mac_addr(struct rte_eth_dev *dev, struct rte_ether_addr *mac_addr,
+		     __rte_unused uint32_t index,
+		     __rte_unused uint32_t pool)
+{
+	struct txgbe_hw *hw = TXGBE_DEV_HW(dev);
+	int err;
+
+	/*
+	 * On a VF, adding again the same MAC addr is not an idempotent
+	 * operation. Trap this case to avoid exhausting the [very limited]
+	 * set of PF resources used to store VF MAC addresses.
+	 */
+	if (memcmp(hw->mac.perm_addr, mac_addr,
+			sizeof(struct rte_ether_addr)) == 0)
+		return -1;
+	err = txgbevf_set_uc_addr_vf(hw, 2, mac_addr->addr_bytes);
+	if (err != 0)
+		PMD_DRV_LOG(ERR, "Unable to add MAC address "
+			    "%02x:%02x:%02x:%02x:%02x:%02x - err=%d",
+			    mac_addr->addr_bytes[0],
+			    mac_addr->addr_bytes[1],
+			    mac_addr->addr_bytes[2],
+			    mac_addr->addr_bytes[3],
+			    mac_addr->addr_bytes[4],
+			    mac_addr->addr_bytes[5],
+			    err);
+	return err;
+}
+
+static void
+txgbevf_remove_mac_addr(struct rte_eth_dev *dev, uint32_t index)
+{
+	struct txgbe_hw *hw = TXGBE_DEV_HW(dev);
+	struct rte_ether_addr *perm_addr =
+			(struct rte_ether_addr *)hw->mac.perm_addr;
+	struct rte_ether_addr *mac_addr;
+	uint32_t i;
+	int err;
+
+	/*
+	 * The TXGBE_VF_SET_MACVLAN command of the txgbe-pf driver does
+	 * not support the deletion of a given MAC address.
+	 * Instead, it imposes to delete all MAC addresses, then to add again
+	 * all MAC addresses with the exception of the one to be deleted.
+	 */
+	(void)txgbevf_set_uc_addr_vf(hw, 0, NULL);
+
+	/*
+	 * Add again all MAC addresses, with the exception of the deleted one
+	 * and of the permanent MAC address.
+	 */
+	for (i = 0, mac_addr = dev->data->mac_addrs;
+	     i < hw->mac.num_rar_entries; i++, mac_addr++) {
+		/* Skip the deleted MAC address */
+		if (i == index)
+			continue;
+		/* Skip NULL MAC addresses */
+		if (rte_is_zero_ether_addr(mac_addr))
+			continue;
+		/* Skip the permanent MAC address */
+		if (memcmp(perm_addr, mac_addr,
+				sizeof(struct rte_ether_addr)) == 0)
+			continue;
+		err = txgbevf_set_uc_addr_vf(hw, 2, mac_addr->addr_bytes);
+		if (err != 0)
+			PMD_DRV_LOG(ERR,
+				    "Adding again MAC address "
+				    "%02x:%02x:%02x:%02x:%02x:%02x failed "
+				    "err=%d",
+				    mac_addr->addr_bytes[0],
+				    mac_addr->addr_bytes[1],
+				    mac_addr->addr_bytes[2],
+				    mac_addr->addr_bytes[3],
+				    mac_addr->addr_bytes[4],
+				    mac_addr->addr_bytes[5],
+				    err);
+	}
+}
+
+static int
+txgbevf_set_default_mac_addr(struct rte_eth_dev *dev,
+		struct rte_ether_addr *addr)
+{
+	struct txgbe_hw *hw = TXGBE_DEV_HW(dev);
+
+	hw->mac.set_rar(hw, 0, (void *)addr, 0, 0);
+
 	return 0;
 }
 
@@ -245,6 +410,9 @@ txgbevf_dev_close(struct rte_eth_dev *dev)
  * operation have been implemented
  */
 static const struct eth_dev_ops txgbevf_eth_dev_ops = {
+	.mac_addr_add         = txgbevf_add_mac_addr,
+	.mac_addr_remove      = txgbevf_remove_mac_addr,
+	.mac_addr_set         = txgbevf_set_default_mac_addr,
 };
 
 RTE_PMD_REGISTER_PCI(net_txgbe_vf, rte_txgbevf_pmd);
-- 
2.27.0




  parent reply	other threads:[~2021-01-22  9:48 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-01-22  9:47 [dpdk-dev] [PATCH v1 00/20] net/txgbe: add VF driver support Jiawen Wu
2021-01-22  9:47 ` [dpdk-dev] [PATCH v1 01/20] net/txgbe: add ethdev probe and remove for VF device Jiawen Wu
2021-02-02 17:48   ` Ferruh Yigit
2021-01-22  9:47 ` [dpdk-dev] [PATCH v1 02/20] net/txgbe: add base code for VF driver Jiawen Wu
2021-02-02 17:51   ` Ferruh Yigit
2021-01-22  9:47 ` Jiawen Wu [this message]
2021-01-22  9:47 ` [dpdk-dev] [PATCH v1 04/20] net/txgbe: get VF device information Jiawen Wu
2021-01-22  9:47 ` [dpdk-dev] [PATCH v1 05/20] net/txgbe: add interrupt operation for VF device Jiawen Wu
2021-02-02 17:49   ` Ferruh Yigit
2021-01-22  9:47 ` [dpdk-dev] [PATCH v1 06/20] net/txgbe: get link status of " Jiawen Wu
2021-01-22  9:47 ` [dpdk-dev] [PATCH v1 07/20] net/txgbe: add Rx and Tx unit init for " Jiawen Wu
2021-02-02 17:49   ` Ferruh Yigit
2021-01-22  9:47 ` [dpdk-dev] [PATCH v1 08/20] net/txgbe: add VF device stats and xstats get operation Jiawen Wu
2021-01-22  9:47 ` [dpdk-dev] [PATCH v1 09/20] net/txgbe: add VLAN handle support to VF driver Jiawen Wu
2021-02-02 17:52   ` Ferruh Yigit
2021-01-22  9:47 ` [dpdk-dev] [PATCH v1 10/20] net/txgbe: add RSS support for VF device Jiawen Wu
2021-01-22  9:47 ` [dpdk-dev] [PATCH v1 11/20] net/txgbe: add VF device promiscuous and allmulticast mode Jiawen Wu
2021-01-22  9:47 ` [dpdk-dev] [PATCH v1 12/20] net/txgbe: support multicast MAC filter for VF driver Jiawen Wu
2021-01-22  9:47 ` [dpdk-dev] [PATCH v1 13/20] net/txgbe: support to update MTU on VF device Jiawen Wu
2021-01-22  9:47 ` [dpdk-dev] [PATCH v1 14/20] net/txgbe: support register dump " Jiawen Wu
2021-01-22  9:47 ` [dpdk-dev] [PATCH v1 15/20] net/txgbe: start and stop " Jiawen Wu
2021-01-22  9:47 ` [dpdk-dev] [PATCH v1 16/20] net/txgbe: add some supports as PF driver implemented Jiawen Wu
2021-02-02 17:50   ` Ferruh Yigit
2021-01-22  9:47 ` [dpdk-dev] [PATCH v1 17/20] net/txgbe: support VF representor Jiawen Wu
2021-01-22  9:47 ` [dpdk-dev] [PATCH v1 18/20] net/txgbe: hardware support for " Jiawen Wu
2021-02-02 17:50   ` Ferruh Yigit
2021-01-22  9:47 ` [dpdk-dev] [PATCH v1 19/20] net/txgbe: support VLAN filter " Jiawen Wu
2021-01-22  9:48 ` [dpdk-dev] [PATCH v1 20/20] doc: update release note for txgbe Jiawen Wu
2021-02-02 17:50   ` Ferruh Yigit
2021-02-02 18:07 ` [dpdk-dev] [PATCH v1 00/20] net/txgbe: add VF driver support Ferruh Yigit
2021-02-03  7:48   ` Jiawen Wu
2021-02-10 13:24     ` Ferruh Yigit

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210122094800.197748-4-jiawenwu@trustnetic.com \
    --to=jiawenwu@trustnetic.com \
    --cc=dev@dpdk.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.