DPDK patches and discussions
 help / color / mirror / Atom feed
From: Zaiyu Wang <zaiyuwang@trustnetic.com>
To: dev@dpdk.org
Cc: Zaiyu Wang <zaiyuwang@trustnetic.com>,
	Jiawen Wu <jiawenwu@trustnetic.com>
Subject: [PATCH 06/15] net/ngbe: add add/remove/set mac addr ops for VF device
Date: Thu,  9 Jan 2025 12:02:16 +0800	[thread overview]
Message-ID: <20250109040227.1016-7-zaiyuwang@trustnetic.com> (raw)
In-Reply-To: <20250109040227.1016-1-zaiyuwang@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.
---
 doc/guides/nics/features/ngbe_vf.ini |   1 +
 drivers/net/ngbe/base/ngbe_type.h    |   1 +
 drivers/net/ngbe/base/ngbe_vf.c      |  82 +++++++++++++++
 drivers/net/ngbe/base/ngbe_vf.h      |   4 +
 drivers/net/ngbe/ngbe_ethdev_vf.c    | 146 +++++++++++++++++++++++++++
 5 files changed, 234 insertions(+)

diff --git a/doc/guides/nics/features/ngbe_vf.ini b/doc/guides/nics/features/ngbe_vf.ini
index 333f02c854..bbeb8aeb00 100644
--- a/doc/guides/nics/features/ngbe_vf.ini
+++ b/doc/guides/nics/features/ngbe_vf.ini
@@ -4,6 +4,7 @@
 ; Refer to default.ini for the full list of available PMD features.
 ;
 [Features]
+Unicast MAC filter   = Y
 MTU update           = Y
 Promiscuous mode     = Y
 Allmulticast mode    = Y
diff --git a/drivers/net/ngbe/base/ngbe_type.h b/drivers/net/ngbe/base/ngbe_type.h
index f780b92efa..7a3b52ffd4 100644
--- a/drivers/net/ngbe/base/ngbe_type.h
+++ b/drivers/net/ngbe/base/ngbe_type.h
@@ -335,6 +335,7 @@ struct ngbe_mac_info {
 	/* RAR */
 	s32 (*set_rar)(struct ngbe_hw *hw, u32 index, u8 *addr, u32 vmdq,
 			  u32 enable_addr);
+	s32 (*set_uc_addr)(struct ngbe_hw *hw, u32 index, u8 *addr);
 	s32 (*clear_rar)(struct ngbe_hw *hw, u32 index);
 	s32 (*set_vmdq)(struct ngbe_hw *hw, u32 rar, u32 vmdq);
 	s32 (*clear_vmdq)(struct ngbe_hw *hw, u32 rar, u32 vmdq);
diff --git a/drivers/net/ngbe/base/ngbe_vf.c b/drivers/net/ngbe/base/ngbe_vf.c
index 2d00d5998d..18bb8d263f 100644
--- a/drivers/net/ngbe/base/ngbe_vf.c
+++ b/drivers/net/ngbe/base/ngbe_vf.c
@@ -191,6 +191,39 @@ STATIC s32 ngbevf_write_msg_read_ack(struct ngbe_hw *hw, u32 *msg,
 	return mbx->read_posted(hw, retmsg, size, 0);
 }
 
+/**
+ *  ngbe_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 ngbe_set_rar_vf(struct ngbe_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] = NGBE_VF_SET_MAC_ADDR;
+	memcpy(msg_addr, addr, 6);
+	ret_val = ngbevf_write_msg_read_ack(hw, msgbuf, msgbuf, 3);
+
+	msgbuf[0] &= ~NGBE_VT_MSGTYPE_CTS;
+
+	/* if nacked the address was rejected, use "perm_addr" */
+	if (!ret_val &&
+	    (msgbuf[0] == (NGBE_VF_SET_MAC_ADDR | NGBE_VT_MSGTYPE_NACK))) {
+		ngbe_get_mac_addr_vf(hw, hw->mac.addr);
+		return NGBE_ERR_MBX;
+	}
+
+	return ret_val;
+}
+
 /**
  *  ngbevf_update_xcast_mode - Update Multicast mode
  *  @hw: pointer to the HW structure
@@ -228,6 +261,51 @@ s32 ngbevf_update_xcast_mode(struct ngbe_hw *hw, int xcast_mode)
 	return 0;
 }
 
+/**
+ * ngbe_get_mac_addr_vf - Read device MAC address
+ * @hw: pointer to the HW structure
+ * @mac_addr: the MAC address
+ **/
+s32 ngbe_get_mac_addr_vf(struct ngbe_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 ngbevf_set_uc_addr_vf(struct ngbe_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 << NGBE_VT_MSGINFO_SHIFT;
+	msgbuf[0] |= NGBE_VF_SET_MACVLAN;
+	msgbuf_chk = msgbuf[0];
+	if (addr)
+		memcpy(msg_addr, addr, 6);
+
+	ret_val = ngbevf_write_msg_read_ack(hw, msgbuf, msgbuf, 3);
+	if (!ret_val) {
+		msgbuf[0] &= ~NGBE_VT_MSGTYPE_CTS;
+
+		if (msgbuf[0] == (msgbuf_chk | NGBE_VT_MSGTYPE_NACK))
+			return NGBE_ERR_OUT_OF_MEM;
+	}
+
+	return ret_val;
+}
+
 /**
  *  ngbevf_rlpml_set_vf - Set the maximum receive packet length
  *  @hw: pointer to the HW structure
@@ -359,8 +437,12 @@ s32 ngbe_init_ops_vf(struct ngbe_hw *hw)
 	mac->reset_hw = ngbe_reset_hw_vf;
 	mac->start_hw = ngbe_start_hw_vf;
 	mac->stop_hw = ngbe_stop_hw_vf;
+	mac->get_mac_addr = ngbe_get_mac_addr_vf;
 	mac->negotiate_api_version = ngbevf_negotiate_api_version;
 
+	/* RAR, Multicast */
+	mac->set_rar = ngbe_set_rar_vf;
+	mac->set_uc_addr = ngbevf_set_uc_addr_vf;
 	mac->update_xcast_mode = ngbevf_update_xcast_mode;
 	mac->set_rlpml = ngbevf_rlpml_set_vf;
 
diff --git a/drivers/net/ngbe/base/ngbe_vf.h b/drivers/net/ngbe/base/ngbe_vf.h
index a64de9d332..3f328a0221 100644
--- a/drivers/net/ngbe/base/ngbe_vf.h
+++ b/drivers/net/ngbe/base/ngbe_vf.h
@@ -16,6 +16,10 @@ s32 ngbe_init_hw_vf(struct ngbe_hw *hw);
 s32 ngbe_start_hw_vf(struct ngbe_hw *hw);
 s32 ngbe_reset_hw_vf(struct ngbe_hw *hw);
 s32 ngbe_stop_hw_vf(struct ngbe_hw *hw);
+s32 ngbe_get_mac_addr_vf(struct ngbe_hw *hw, u8 *mac_addr);
+s32 ngbe_set_rar_vf(struct ngbe_hw *hw, u32 index, u8 *addr, u32 vmdq,
+		     u32 enable_addr);
+s32 ngbevf_set_uc_addr_vf(struct ngbe_hw *hw, u32 index, u8 *addr);
 s32 ngbevf_update_xcast_mode(struct ngbe_hw *hw, int xcast_mode);
 s32 ngbevf_rlpml_set_vf(struct ngbe_hw *hw, u16 max_size);
 int ngbevf_negotiate_api_version(struct ngbe_hw *hw, int api);
diff --git a/drivers/net/ngbe/ngbe_ethdev_vf.c b/drivers/net/ngbe/ngbe_ethdev_vf.c
index 5ce0c2df98..29979785cf 100644
--- a/drivers/net/ngbe/ngbe_ethdev_vf.c
+++ b/drivers/net/ngbe/ngbe_ethdev_vf.c
@@ -22,6 +22,7 @@ static int ngbevf_dev_info_get(struct rte_eth_dev *dev,
 static int ngbevf_dev_close(struct rte_eth_dev *dev);
 static int ngbevf_dev_promiscuous_enable(struct rte_eth_dev *dev);
 static int ngbevf_dev_promiscuous_disable(struct rte_eth_dev *dev);
+static void ngbevf_remove_mac_addr(struct rte_eth_dev *dev, uint32_t index);
 
 /*
  * The set of PCI devices this driver supports (for VF)
@@ -84,6 +85,22 @@ ngbevf_negotiate_api(struct ngbe_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
  */
@@ -94,6 +111,8 @@ eth_ngbevf_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 ngbe_hw *hw = ngbe_dev_hw(eth_dev);
+	struct rte_ether_addr *perm_addr =
+			(struct rte_ether_addr *)hw->mac.perm_addr;
 
 	PMD_INIT_FUNC_TRACE();
 
@@ -153,6 +172,29 @@ eth_ngbevf_dev_init(struct rte_eth_dev *eth_dev)
 		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 = ngbe_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) {
@@ -266,12 +308,113 @@ ngbevf_dev_close(struct rte_eth_dev *dev)
 
 	hw->mac.reset_hw(hw);
 
+	/**
+	 * Remove the VF MAC address ro ensure
+	 * that the VF traffic goes to the PF
+	 * after stop, close and detach of the VF
+	 **/
+	ngbevf_remove_mac_addr(dev, 0);
+
+	dev->rx_pkt_burst = NULL;
+	dev->tx_pkt_burst = NULL;
+
 	rte_free(dev->data->mac_addrs);
 	dev->data->mac_addrs = NULL;
 
 	return 0;
 }
 
+static int
+ngbevf_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 ngbe_hw *hw = ngbe_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 = ngbevf_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
+ngbevf_remove_mac_addr(struct rte_eth_dev *dev, uint32_t index)
+{
+	struct ngbe_hw *hw = ngbe_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 NGBE_VF_SET_MACVLAN command of the ngbe-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)ngbevf_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 = ngbevf_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
+ngbevf_set_default_mac_addr(struct rte_eth_dev *dev,
+		struct rte_ether_addr *addr)
+{
+	struct ngbe_hw *hw = ngbe_dev_hw(dev);
+
+	hw->mac.set_rar(hw, 0, (void *)addr, 0, 0);
+
+	return 0;
+}
+
 static int
 ngbevf_dev_set_mtu(struct rte_eth_dev *dev, uint16_t mtu)
 {
@@ -405,6 +548,9 @@ static const struct eth_dev_ops ngbevf_eth_dev_ops = {
 	.allmulticast_disable = ngbevf_dev_allmulticast_disable,
 	.dev_infos_get        = ngbevf_dev_info_get,
 	.mtu_set              = ngbevf_dev_set_mtu,
+	.mac_addr_add         = ngbevf_add_mac_addr,
+	.mac_addr_remove      = ngbevf_remove_mac_addr,
+	.mac_addr_set         = ngbevf_set_default_mac_addr,
 };
 
 RTE_PMD_REGISTER_PCI(net_ngbe_vf, rte_ngbevf_pmd);
-- 
2.21.0.windows.1


  parent reply	other threads:[~2025-01-09  4:04 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-01-09  4:02 [PATCH 00/15] net/ngbe: add VF driver support Zaiyu Wang
2025-01-09  4:02 ` [PATCH 01/15] net/ngbe: add ethdev probe and remove for VF device Zaiyu Wang
2025-01-09  4:02 ` [PATCH 02/15] net/ngbe: add support for PF-VF mailbox interface Zaiyu Wang
2025-01-09  4:02 ` [PATCH 03/15] net/ngbe: add hardware configuration code for VF device Zaiyu Wang
2025-01-09  4:02 ` [PATCH 04/15] net/ngbe: add promiscuous and allmulticast ops " Zaiyu Wang
2025-01-09  4:02 ` [PATCH 05/15] net/ngbe: add set MTU " Zaiyu Wang
2025-01-09  4:02 ` Zaiyu Wang [this message]
2025-01-09  4:02 ` [PATCH 07/15] net/ngbe: add datapath init code " Zaiyu Wang
2025-01-09  4:02 ` [PATCH 08/15] net/ngbe: add vlan related ops " Zaiyu Wang
2025-01-09  4:02 ` [PATCH 09/15] net/ngbe: add interrupt support " Zaiyu Wang
2025-01-09  4:02 ` [PATCH 10/15] net/ngbe: add link update ops " Zaiyu Wang
2025-01-09  4:02 ` [PATCH 11/15] net/ngbe: add stats and xstats " Zaiyu Wang
2025-01-09  4:02 ` [PATCH 12/15] net/ngbe: add start/stop/reset/close " Zaiyu Wang
2025-01-09  4:02 ` [PATCH 13/15] net/ngbe: add multicast MAC filter " Zaiyu Wang
2025-01-09  4:02 ` [PATCH 14/15] net/ngbe: add dump registers " Zaiyu Wang
2025-01-09  4:02 ` [PATCH 15/15] net/ngbe: add some ops which PF has implemented Zaiyu Wang

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=20250109040227.1016-7-zaiyuwang@trustnetic.com \
    --to=zaiyuwang@trustnetic.com \
    --cc=dev@dpdk.org \
    --cc=jiawenwu@trustnetic.com \
    /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).