net/sfc: support promiscuous and all-multicast control

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: Robert Stonehouse <rstonehouse@solarflare.com>
This commit is contained in:
Ivan Malov 2016-12-15 12:51:01 +00:00 committed by Ferruh Yigit
parent 2a05f337ce
commit f3de384044
5 changed files with 91 additions and 1 deletions

View File

@ -9,6 +9,8 @@ Link status = Y
Link status event = Y
MTU update = Y
Jumbo frame = Y
Promiscuous mode = Y
Allmulticast mode = Y
Flow control = Y
L3 checksum offload = P
L4 checksum offload = P

View File

@ -59,6 +59,10 @@ SFC EFX PMD has support for:
- Jumbo frames up to 9K
- Promiscuous mode
- Allmulticast mode
Non-supported Features
----------------------

View File

@ -96,6 +96,13 @@ enum sfc_adapter_state {
SFC_ADAPTER_NSTATES
};
enum sfc_dev_filter_mode {
SFC_DEV_FILTER_MODE_PROMISC = 0,
SFC_DEV_FILTER_MODE_ALLMULTI,
SFC_DEV_FILTER_NMODES
};
enum sfc_mcdi_state {
SFC_MCDI_UNINITIALIZED = 0,
SFC_MCDI_INITIALIZED,
@ -133,6 +140,9 @@ struct sfc_port {
boolean_t flow_ctrl_autoneg;
size_t pdu;
boolean_t promisc;
boolean_t allmulti;
rte_spinlock_t mac_stats_lock;
uint64_t *mac_stats_buf;
efsys_mem_t mac_stats_dma_mem;
@ -252,6 +262,7 @@ void sfc_port_stop(struct sfc_adapter *sa);
void sfc_port_link_mode_to_info(efx_link_mode_t link_mode,
struct rte_eth_link *link_info);
int sfc_port_update_mac_stats(struct sfc_adapter *sa);
int sfc_set_rx_mode(struct sfc_adapter *sa);
#ifdef __cplusplus

View File

@ -252,6 +252,59 @@ sfc_dev_close(struct rte_eth_dev *dev)
sfc_log_init(sa, "done");
}
static void
sfc_dev_filter_set(struct rte_eth_dev *dev, enum sfc_dev_filter_mode mode,
boolean_t enabled)
{
struct sfc_port *port;
boolean_t *toggle;
struct sfc_adapter *sa = dev->data->dev_private;
boolean_t allmulti = (mode == SFC_DEV_FILTER_MODE_ALLMULTI);
const char *desc = (allmulti) ? "all-multi" : "promiscuous";
sfc_adapter_lock(sa);
port = &sa->port;
toggle = (allmulti) ? (&port->allmulti) : (&port->promisc);
if (*toggle != enabled) {
*toggle = enabled;
if ((sa->state == SFC_ADAPTER_STARTED) &&
(sfc_set_rx_mode(sa) != 0)) {
*toggle = !(enabled);
sfc_warn(sa, "Failed to %s %s mode",
((enabled) ? "enable" : "disable"), desc);
}
}
sfc_adapter_unlock(sa);
}
static void
sfc_dev_promisc_enable(struct rte_eth_dev *dev)
{
sfc_dev_filter_set(dev, SFC_DEV_FILTER_MODE_PROMISC, B_TRUE);
}
static void
sfc_dev_promisc_disable(struct rte_eth_dev *dev)
{
sfc_dev_filter_set(dev, SFC_DEV_FILTER_MODE_PROMISC, B_FALSE);
}
static void
sfc_dev_allmulti_enable(struct rte_eth_dev *dev)
{
sfc_dev_filter_set(dev, SFC_DEV_FILTER_MODE_ALLMULTI, B_TRUE);
}
static void
sfc_dev_allmulti_disable(struct rte_eth_dev *dev)
{
sfc_dev_filter_set(dev, SFC_DEV_FILTER_MODE_ALLMULTI, B_FALSE);
}
static int
sfc_rx_queue_setup(struct rte_eth_dev *dev, uint16_t rx_queue_id,
uint16_t nb_rx_desc, unsigned int socket_id,
@ -660,6 +713,10 @@ static const struct eth_dev_ops sfc_eth_dev_ops = {
.dev_set_link_up = sfc_dev_set_link_up,
.dev_set_link_down = sfc_dev_set_link_down,
.dev_close = sfc_dev_close,
.promiscuous_enable = sfc_dev_promisc_enable,
.promiscuous_disable = sfc_dev_promisc_disable,
.allmulticast_enable = sfc_dev_allmulti_enable,
.allmulticast_disable = sfc_dev_allmulti_disable,
.link_update = sfc_dev_link_update,
.stats_get = sfc_stats_get,
.xstats_get = sfc_xstats_get,

View File

@ -103,7 +103,11 @@ sfc_port_start(struct sfc_adapter *sa)
goto fail_mac_addr_set;
sfc_log_init(sa, "set MAC filters");
rc = efx_mac_filter_set(sa->nic, B_TRUE, B_TRUE, B_TRUE, B_TRUE);
port->promisc = (sa->eth_dev->data->promiscuous != 0) ?
B_TRUE : B_FALSE;
port->allmulti = (sa->eth_dev->data->all_multicast != 0) ?
B_TRUE : B_FALSE;
rc = sfc_set_rx_mode(sa);
if (rc != 0)
goto fail_mac_filter_set;
@ -219,6 +223,18 @@ sfc_port_fini(struct sfc_adapter *sa)
sfc_log_init(sa, "done");
}
int
sfc_set_rx_mode(struct sfc_adapter *sa)
{
struct sfc_port *port = &sa->port;
int rc;
rc = efx_mac_filter_set(sa->nic, port->promisc, B_TRUE,
port->promisc || port->allmulti, B_TRUE);
return rc;
}
void
sfc_port_link_mode_to_info(efx_link_mode_t link_mode,
struct rte_eth_link *link_info)