From: Jiawen Wu <jiawenwu@trustnetic.com>
To: dev@dpdk.org
Cc: Jiawen Wu <jiawenwu@trustnetic.com>
Subject: [dpdk-dev] [PATCH v3 03/17] net/txgbe: support add and remove VF device MAC address
Date: Thu, 25 Feb 2021 16:08:47 +0800 [thread overview]
Message-ID: <20210225080901.3645291-4-jiawenwu@trustnetic.com> (raw)
In-Reply-To: <20210225080901.3645291-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>
---
doc/guides/nics/features/txgbe_vf.ini | 1 +
drivers/net/txgbe/base/txgbe_vf.c | 102 ++++++++++++++++
drivers/net/txgbe/base/txgbe_vf.h | 5 +
drivers/net/txgbe/txgbe_ethdev_vf.c | 168 ++++++++++++++++++++++++++
4 files changed, 276 insertions(+)
diff --git a/doc/guides/nics/features/txgbe_vf.ini b/doc/guides/nics/features/txgbe_vf.ini
index 5035c5eea..97c881d96 100644
--- a/doc/guides/nics/features/txgbe_vf.ini
+++ b/doc/guides/nics/features/txgbe_vf.ini
@@ -4,6 +4,7 @@
; Refer to default.ini for the full list of available PMD features.
;
[Features]
+Unicast MAC filter = Y
Multiprocess aware = Y
Linux = Y
ARMv8 = Y
diff --git a/drivers/net/txgbe/base/txgbe_vf.c b/drivers/net/txgbe/base/txgbe_vf.c
index 5d4e10158..fadecaa11 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 4fbb4f154..86b1e2bfb 100644
--- a/drivers/net/txgbe/txgbe_ethdev_vf.c
+++ b/drivers/net/txgbe/txgbe_ethdev_vf.c
@@ -18,6 +18,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)
@@ -56,6 +57,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
*/
@@ -66,6 +83,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();
@@ -141,8 +160,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, ð_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;
}
@@ -230,9 +294,110 @@ 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);
+
/* 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;
}
@@ -241,6 +406,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
next prev parent reply other threads:[~2021-02-25 8:09 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-02-25 8:08 [dpdk-dev] [PATCH v3 00/17] net/txgbe: add VF driver support Jiawen Wu
2021-02-25 8:08 ` [dpdk-dev] [PATCH v3 01/17] net/txgbe: add ethdev probe and remove for VF device Jiawen Wu
2021-02-25 8:08 ` [dpdk-dev] [PATCH v3 02/17] net/txgbe: add base code for VF driver Jiawen Wu
2021-02-25 8:08 ` Jiawen Wu [this message]
2021-02-25 8:08 ` [dpdk-dev] [PATCH v3 04/17] net/txgbe: get VF device information Jiawen Wu
2021-02-25 8:08 ` [dpdk-dev] [PATCH v3 05/17] net/txgbe: add interrupt operation for VF device Jiawen Wu
2021-02-25 8:08 ` [dpdk-dev] [PATCH v3 06/17] net/txgbe: get link status of " Jiawen Wu
2021-02-25 8:08 ` [dpdk-dev] [PATCH v3 07/17] net/txgbe: add Rx and Tx unit init for " Jiawen Wu
2021-02-25 8:08 ` [dpdk-dev] [PATCH v3 08/17] net/txgbe: add VF device stats and xstats get operation Jiawen Wu
2021-02-25 8:08 ` [dpdk-dev] [PATCH v3 09/17] net/txgbe: add VLAN handle support to VF driver Jiawen Wu
2021-02-25 8:08 ` [dpdk-dev] [PATCH v3 10/17] net/txgbe: add RSS support for VF device Jiawen Wu
2021-02-25 8:08 ` [dpdk-dev] [PATCH v3 11/17] net/txgbe: add VF device promiscuous and allmulticast mode Jiawen Wu
2021-02-25 8:08 ` [dpdk-dev] [PATCH v3 12/17] net/txgbe: support multicast MAC filter for VF driver Jiawen Wu
2021-02-25 8:08 ` [dpdk-dev] [PATCH v3 13/17] net/txgbe: support to update MTU on VF device Jiawen Wu
2021-02-25 8:08 ` [dpdk-dev] [PATCH v3 14/17] net/txgbe: support register dump " Jiawen Wu
2021-02-25 8:08 ` [dpdk-dev] [PATCH v3 15/17] net/txgbe: start and stop " Jiawen Wu
2021-02-25 8:09 ` [dpdk-dev] [PATCH v3 16/17] net/txgbe: add some supports as PF driver implemented Jiawen Wu
2021-02-25 8:09 ` [dpdk-dev] [PATCH v3 17/17] doc: update release note for txgbe Jiawen Wu
2021-02-26 13:27 ` [dpdk-dev] [PATCH v3 00/17] net/txgbe: add VF driver support 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=20210225080901.3645291-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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).