[dpdk-dev] [PATCH v2] net/sfc: set multicast address list in started state only

Andrew Rybchenko arybchenko at solarflare.com
Thu Mar 9 17:21:30 CET 2017


From: Ivan Malov <ivan.malov at oktetlabs.ru>

According to 'libefx' API requirements, one is allowed to
apply multicast address list to the port in started state
only, otherwise the new array should be copied to a local
storage in order to be applied during the next port start

Fixes: 0fa0070e4391 ("net/sfc: support multicast addresses list controls")
Coverity issue: 141296

Fixes: e9ddf37a507d ("net/sfc: fix setting empty multicast list")
Cc: stable at dpdk.org

Signed-off-by: Ivan Malov <ivan.malov at oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko at solarflare.com>
Reviewed-by: Andrew Lee <alee at solarflare.com>
Reviewed-by: Andy Moreton <amoreton at solarflare.com>
---
 drivers/net/sfc/sfc.h        |  4 ++++
 drivers/net/sfc/sfc_ethdev.c | 35 ++++++++++++++++-------------------
 drivers/net/sfc/sfc_port.c   | 19 +++++++++++++++++++
 3 files changed, 39 insertions(+), 19 deletions(-)

diff --git a/drivers/net/sfc/sfc.h b/drivers/net/sfc/sfc.h
index 655328f..0b3b318 100644
--- a/drivers/net/sfc/sfc.h
+++ b/drivers/net/sfc/sfc.h
@@ -150,6 +150,10 @@ struct sfc_port {
 	boolean_t			promisc;
 	boolean_t			allmulti;
 
+	unsigned int			max_mcast_addrs;
+	unsigned int			nb_mcast_addrs;
+	uint8_t				*mcast_addrs;
+
 	rte_spinlock_t			mac_stats_lock;
 	uint64_t			*mac_stats_buf;
 	efsys_mem_t			mac_stats_dma_mem;
diff --git a/drivers/net/sfc/sfc_ethdev.c b/drivers/net/sfc/sfc_ethdev.c
index cac01ac..135f3da 100644
--- a/drivers/net/sfc/sfc_ethdev.c
+++ b/drivers/net/sfc/sfc_ethdev.c
@@ -826,36 +826,33 @@ sfc_set_mc_addr_list(struct rte_eth_dev *dev, struct ether_addr *mc_addr_set,
 		     uint32_t nb_mc_addr)
 {
 	struct sfc_adapter *sa = dev->data->dev_private;
-	uint8_t *mc_addrs_p = NULL;
+	struct sfc_port *port = &sa->port;
+	uint8_t *mc_addrs = port->mcast_addrs;
 	int rc;
 	unsigned int i;
 
-	if (nb_mc_addr > EFX_MAC_MULTICAST_LIST_MAX) {
+	if (mc_addrs == NULL)
+		return -ENOBUFS;
+
+	if (nb_mc_addr > port->max_mcast_addrs) {
 		sfc_err(sa, "too many multicast addresses: %u > %u",
-			 nb_mc_addr, EFX_MAC_MULTICAST_LIST_MAX);
+			 nb_mc_addr, port->max_mcast_addrs);
 		return -EINVAL;
 	}
 
-	if (nb_mc_addr != 0) {
-		uint8_t *mc_addrs;
-
-		mc_addrs_p = rte_calloc("mc-addrs", nb_mc_addr,
-					EFX_MAC_ADDR_LEN, 0);
-		if (mc_addrs_p == NULL)
-			return -ENOMEM;
-
-		mc_addrs = mc_addrs_p;
-		for (i = 0; i < nb_mc_addr; ++i) {
-			(void)rte_memcpy(mc_addrs, mc_addr_set[i].addr_bytes,
-					 EFX_MAC_ADDR_LEN);
-			mc_addrs += EFX_MAC_ADDR_LEN;
-		}
+	for (i = 0; i < nb_mc_addr; ++i) {
+		(void)rte_memcpy(mc_addrs, mc_addr_set[i].addr_bytes,
+				 EFX_MAC_ADDR_LEN);
+		mc_addrs += EFX_MAC_ADDR_LEN;
 	}
 
-	rc = efx_mac_multicast_list_set(sa->nic, mc_addrs_p, nb_mc_addr);
+	port->nb_mcast_addrs = nb_mc_addr;
 
-	rte_free(mc_addrs_p);
+	if (sa->state != SFC_ADAPTER_STARTED)
+		return 0;
 
+	rc = efx_mac_multicast_list_set(sa->nic, port->mcast_addrs,
+					port->nb_mcast_addrs);
 	if (rc != 0)
 		sfc_err(sa, "cannot set multicast address list (rc = %u)", rc);
 
diff --git a/drivers/net/sfc/sfc_port.c b/drivers/net/sfc/sfc_port.c
index e2f5043..e77848d 100644
--- a/drivers/net/sfc/sfc_port.c
+++ b/drivers/net/sfc/sfc_port.c
@@ -153,6 +153,12 @@ sfc_port_start(struct sfc_adapter *sa)
 	if (rc != 0)
 		goto fail_mac_filter_set;
 
+	sfc_log_init(sa, "set multicast address list");
+	rc = efx_mac_multicast_list_set(sa->nic, port->mcast_addrs,
+					port->nb_mcast_addrs);
+	if (rc != 0)
+		goto fail_mcast_address_list_set;
+
 	if (port->mac_stats_reset_pending) {
 		rc = sfc_port_reset_mac_stats(sa);
 		if (rc != 0)
@@ -196,6 +202,7 @@ sfc_port_start(struct sfc_adapter *sa)
 				     0, B_FALSE);
 
 fail_mac_stats_periodic:
+fail_mcast_address_list_set:
 fail_mac_filter_set:
 fail_mac_addr_set:
 fail_mac_pdu_set:
@@ -245,6 +252,17 @@ sfc_port_init(struct sfc_adapter *sa)
 	else
 		port->pdu = EFX_MAC_PDU(dev_data->mtu);
 
+	port->max_mcast_addrs = EFX_MAC_MULTICAST_LIST_MAX;
+	port->nb_mcast_addrs = 0;
+	port->mcast_addrs = rte_calloc_socket("mcast_addr_list_buf",
+					      port->max_mcast_addrs,
+					      EFX_MAC_ADDR_LEN, 0,
+					      sa->socket_id);
+	if (port->mcast_addrs == NULL) {
+		rc = ENOMEM;
+		goto fail_mcast_addr_list_buf_alloc;
+	}
+
 	rte_spinlock_init(&port->mac_stats_lock);
 
 	rc = ENOMEM;
@@ -267,6 +285,7 @@ sfc_port_init(struct sfc_adapter *sa)
 fail_mac_stats_dma_alloc:
 	rte_free(port->mac_stats_buf);
 fail_mac_stats_buf_alloc:
+fail_mcast_addr_list_buf_alloc:
 	sfc_log_init(sa, "failed %d", rc);
 	return rc;
 }
-- 
2.9.3



More information about the dev mailing list