From f3de38404400689a1ffb32b75e7c0acf5152c7ee Mon Sep 17 00:00:00 2001 From: Ivan Malov Date: Thu, 15 Dec 2016 12:51:01 +0000 Subject: [PATCH] net/sfc: support promiscuous and all-multicast control Signed-off-by: Ivan Malov Signed-off-by: Andrew Rybchenko Reviewed-by: Andrew Lee Reviewed-by: Robert Stonehouse --- doc/guides/nics/features/sfc_efx.ini | 2 + doc/guides/nics/sfc_efx.rst | 4 ++ drivers/net/sfc/sfc.h | 11 ++++++ drivers/net/sfc/sfc_ethdev.c | 57 ++++++++++++++++++++++++++++ drivers/net/sfc/sfc_port.c | 18 ++++++++- 5 files changed, 91 insertions(+), 1 deletion(-) diff --git a/doc/guides/nics/features/sfc_efx.ini b/doc/guides/nics/features/sfc_efx.ini index 60ecca0982..aaea993529 100644 --- a/doc/guides/nics/features/sfc_efx.ini +++ b/doc/guides/nics/features/sfc_efx.ini @@ -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 diff --git a/doc/guides/nics/sfc_efx.rst b/doc/guides/nics/sfc_efx.rst index c482d771e1..984da9ccbd 100644 --- a/doc/guides/nics/sfc_efx.rst +++ b/doc/guides/nics/sfc_efx.rst @@ -59,6 +59,10 @@ SFC EFX PMD has support for: - Jumbo frames up to 9K +- Promiscuous mode + +- Allmulticast mode + Non-supported Features ---------------------- diff --git a/drivers/net/sfc/sfc.h b/drivers/net/sfc/sfc.h index c155bc44c3..26958dbe5d 100644 --- a/drivers/net/sfc/sfc.h +++ b/drivers/net/sfc/sfc.h @@ -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 diff --git a/drivers/net/sfc/sfc_ethdev.c b/drivers/net/sfc/sfc_ethdev.c index b7626c005b..aa02f73668 100644 --- a/drivers/net/sfc/sfc_ethdev.c +++ b/drivers/net/sfc/sfc_ethdev.c @@ -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, diff --git a/drivers/net/sfc/sfc_port.c b/drivers/net/sfc/sfc_port.c index 1241af76cd..dc6ecdf7dc 100644 --- a/drivers/net/sfc/sfc_port.c +++ b/drivers/net/sfc/sfc_port.c @@ -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) -- 2.20.1