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:
parent
8cb45c97d3
commit
295f647a38
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user