net/sfc: set multicast address list in started state only

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

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

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

Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andrew Lee <alee@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@solarflare.com>
This commit is contained in:
Ivan Malov 2017-03-09 16:21:30 +00:00 committed by Ferruh Yigit
parent 8cb45c97d3
commit 295f647a38
3 changed files with 39 additions and 19 deletions

View File

@ -152,6 +152,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;

View File

@ -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);

View File

@ -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;
}