From patchwork Thu Oct 12 12:19:34 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adrien Mazarguil X-Patchwork-Id: 30271 X-Patchwork-Delegate: ferruh.yigit@amd.com Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id E14AF1B320; Thu, 12 Oct 2017 14:20:44 +0200 (CEST) Received: from mail-wm0-f41.google.com (mail-wm0-f41.google.com [74.125.82.41]) by dpdk.org (Postfix) with ESMTP id 8141D1B2FC for ; Thu, 12 Oct 2017 14:20:33 +0200 (CEST) Received: by mail-wm0-f41.google.com with SMTP id q124so12694114wmb.0 for ; Thu, 12 Oct 2017 05:20:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=6wind-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=m0mVuQaH4qUqnMkh3ISNO8JbGI7l4VDwE+vyQfP1mnU=; b=Jb1lOSDWMGTOQgMs+l6Iay+DTuP3TrhqpcduOSRwJlN/qj2zTgW/ODB0xGQQM066zp GNDCST0u1LPbHxypvV4KNsNDddVXKhwiL9GoPewtsBZfHmI9zQlHKJfaUeqKBvB/nx+a Tpl3p0oOFZ4Azd6nz/eER+fN27PxaO2VrrKCS40fd3XHG2qndWZdU8126bXz8ocwxT20 n7YC50ha0b+ikHEBIwRPjVPKarAp/VrI+kUJ5iIknF+Lu6c2UfCdnS8+Jlf2XW1pY2E+ AlwMbkAC9sBrYjc6++I6RCl34XmMsGmy8nqBd/ogiKsHGmZNCOnmHBWdMEpC6apCpcIz 2Msg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=m0mVuQaH4qUqnMkh3ISNO8JbGI7l4VDwE+vyQfP1mnU=; b=MzeO4it9e74vneNxSEu5Azx5tZP/p7EGCGYU5GsAc17kKQOZqhBKStegAOl4yh6Uo6 Gypj4oMzLbTtZlvHxfqs3pBdesHvoc6lwnIrs7nudYNYTca5uW2XTBnU+9HfvnbWwXwQ +tigMwK4Y3eJ5nDp2ta0fPBYbXSz524dPqXOBQ229CiRF2MXaJTRzrRgJCdSX0FCYEER V6avBH2t0tH5bxBI43om61DAOflTrdktEWDoxzWqyLV78KJbtTvw4qokMVY4JKSfJjDu Lsl3Ojz6nCYYANL5i8hV5/AFcPn5DFxPbY4zqfZ8XYssIubGu1yOV1mXymG0bDZFqKTQ iusQ== X-Gm-Message-State: AMCzsaWNrkavM8pHrjTe5zD0JTYgD0SBKQ17L6VtTgCT2+YK74R5GXYk 18C9t4WvOHnHsorei0P96Jif0k2r X-Google-Smtp-Source: AOwi7QCgkfFDTQNgNaYNaWa9bxdddHKJhk1B23yuxd6puf6ZF5vJ/arPNHJR/jAWgRfWLJ7SXGbjVA== X-Received: by 10.223.192.66 with SMTP id c2mr1879523wrf.95.1507810832993; Thu, 12 Oct 2017 05:20:32 -0700 (PDT) Received: from 6wind.com (host.78.145.23.62.rev.coltfrance.com. [62.23.145.78]) by smtp.gmail.com with ESMTPSA id i13sm13928832wre.93.2017.10.12.05.20.31 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 12 Oct 2017 05:20:31 -0700 (PDT) From: Adrien Mazarguil To: Ferruh Yigit Cc: Nelio Laranjeiro , dev@dpdk.org Date: Thu, 12 Oct 2017 14:19:34 +0200 Message-Id: <1a8be6830c2d113d64c35bd8dfa79705b666ea7f.1507809961.git.adrien.mazarguil@6wind.com> X-Mailer: git-send-email 2.1.4 In-Reply-To: References: Subject: [dpdk-dev] [PATCH v2 20/29] net/mlx4: restore promisc and allmulti support X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" Implement promiscuous and all multicast through internal flow rules automatically generated according to the configured mode. Signed-off-by: Adrien Mazarguil Acked-by: Nelio Laranjeiro --- doc/guides/nics/features/mlx4.ini | 2 + drivers/net/mlx4/mlx4.c | 4 ++ drivers/net/mlx4/mlx4.h | 4 ++ drivers/net/mlx4/mlx4_ethdev.c | 95 ++++++++++++++++++++++++++++++++++ drivers/net/mlx4/mlx4_flow.c | 63 +++++++++++++++++++--- 5 files changed, 162 insertions(+), 6 deletions(-) diff --git a/doc/guides/nics/features/mlx4.ini b/doc/guides/nics/features/mlx4.ini index 9e3ba34..6f8c82a 100644 --- a/doc/guides/nics/features/mlx4.ini +++ b/doc/guides/nics/features/mlx4.ini @@ -12,6 +12,8 @@ Rx interrupt = Y Queue start/stop = Y MTU update = Y Jumbo frame = Y +Promiscuous mode = Y +Allmulticast mode = Y Unicast MAC filter = Y Multicast MAC filter = Y SR-IOV = Y diff --git a/drivers/net/mlx4/mlx4.c b/drivers/net/mlx4/mlx4.c index e25e958..f02508a 100644 --- a/drivers/net/mlx4/mlx4.c +++ b/drivers/net/mlx4/mlx4.c @@ -221,6 +221,10 @@ static const struct eth_dev_ops mlx4_dev_ops = { .dev_set_link_up = mlx4_dev_set_link_up, .dev_close = mlx4_dev_close, .link_update = mlx4_link_update, + .promiscuous_enable = mlx4_promiscuous_enable, + .promiscuous_disable = mlx4_promiscuous_disable, + .allmulticast_enable = mlx4_allmulticast_enable, + .allmulticast_disable = mlx4_allmulticast_disable, .mac_addr_remove = mlx4_mac_addr_remove, .mac_addr_add = mlx4_mac_addr_add, .mac_addr_set = mlx4_mac_addr_set, diff --git a/drivers/net/mlx4/mlx4.h b/drivers/net/mlx4/mlx4.h index cc403ea..a27399a 100644 --- a/drivers/net/mlx4/mlx4.h +++ b/drivers/net/mlx4/mlx4.h @@ -124,6 +124,10 @@ int mlx4_mtu_get(struct priv *priv, uint16_t *mtu); int mlx4_mtu_set(struct rte_eth_dev *dev, uint16_t mtu); int mlx4_dev_set_link_down(struct rte_eth_dev *dev); int mlx4_dev_set_link_up(struct rte_eth_dev *dev); +void mlx4_promiscuous_enable(struct rte_eth_dev *dev); +void mlx4_promiscuous_disable(struct rte_eth_dev *dev); +void mlx4_allmulticast_enable(struct rte_eth_dev *dev); +void mlx4_allmulticast_disable(struct rte_eth_dev *dev); void mlx4_mac_addr_remove(struct rte_eth_dev *dev, uint32_t index); int mlx4_mac_addr_add(struct rte_eth_dev *dev, struct ether_addr *mac_addr, uint32_t index, uint32_t vmdq); diff --git a/drivers/net/mlx4/mlx4_ethdev.c b/drivers/net/mlx4/mlx4_ethdev.c index 7721f13..01fb195 100644 --- a/drivers/net/mlx4/mlx4_ethdev.c +++ b/drivers/net/mlx4/mlx4_ethdev.c @@ -520,6 +520,101 @@ mlx4_dev_set_link_up(struct rte_eth_dev *dev) } /** + * Supported Rx mode toggles. + * + * Even and odd values respectively stand for off and on. + */ +enum rxmode_toggle { + RXMODE_TOGGLE_PROMISC_OFF, + RXMODE_TOGGLE_PROMISC_ON, + RXMODE_TOGGLE_ALLMULTI_OFF, + RXMODE_TOGGLE_ALLMULTI_ON, +}; + +/** + * Helper function to toggle promiscuous and all multicast modes. + * + * @param dev + * Pointer to Ethernet device structure. + * @param toggle + * Toggle to set. + */ +static void +mlx4_rxmode_toggle(struct rte_eth_dev *dev, enum rxmode_toggle toggle) +{ + struct priv *priv = dev->data->dev_private; + const char *mode; + struct rte_flow_error error; + + switch (toggle) { + case RXMODE_TOGGLE_PROMISC_OFF: + case RXMODE_TOGGLE_PROMISC_ON: + mode = "promiscuous"; + dev->data->promiscuous = toggle & 1; + break; + case RXMODE_TOGGLE_ALLMULTI_OFF: + case RXMODE_TOGGLE_ALLMULTI_ON: + mode = "all multicast"; + dev->data->all_multicast = toggle & 1; + break; + } + if (!mlx4_flow_sync(priv, &error)) + return; + ERROR("cannot toggle %s mode (code %d, \"%s\")," + " flow error type %d, cause %p, message: %s", + mode, rte_errno, strerror(rte_errno), error.type, error.cause, + error.message ? error.message : "(unspecified)"); +} + +/** + * DPDK callback to enable promiscuous mode. + * + * @param dev + * Pointer to Ethernet device structure. + */ +void +mlx4_promiscuous_enable(struct rte_eth_dev *dev) +{ + mlx4_rxmode_toggle(dev, RXMODE_TOGGLE_PROMISC_ON); +} + +/** + * DPDK callback to disable promiscuous mode. + * + * @param dev + * Pointer to Ethernet device structure. + */ +void +mlx4_promiscuous_disable(struct rte_eth_dev *dev) +{ + mlx4_rxmode_toggle(dev, RXMODE_TOGGLE_PROMISC_OFF); +} + +/** + * DPDK callback to enable all multicast mode. + * + * @param dev + * Pointer to Ethernet device structure. + */ +void +mlx4_allmulticast_enable(struct rte_eth_dev *dev) +{ + mlx4_rxmode_toggle(dev, RXMODE_TOGGLE_ALLMULTI_ON); +} + +/** + * DPDK callback to disable all multicast mode. + * + * @param dev + * Pointer to Ethernet device structure. + */ +void +mlx4_allmulticast_disable(struct rte_eth_dev *dev) +{ + mlx4_rxmode_toggle(dev, RXMODE_TOGGLE_ALLMULTI_OFF); +} + +/** * DPDK callback to remove a MAC address. * * @param dev diff --git a/drivers/net/mlx4/mlx4_flow.c b/drivers/net/mlx4/mlx4_flow.c index 15526af..41423cd 100644 --- a/drivers/net/mlx4/mlx4_flow.c +++ b/drivers/net/mlx4/mlx4_flow.c @@ -1047,6 +1047,14 @@ mlx4_flow_internal_next_vlan(struct priv *priv, uint16_t vlan) /** * Generate internal flow rules. * + * Various flow rules are created depending on the mode the device is in: + * + * 1. Promiscuous: port MAC + catch-all (VLAN filtering is ignored). + * 2. All multicast: port MAC/VLAN + catch-all multicast. + * 3. Otherwise: port MAC/VLAN + broadcast MAC/VLAN. + * + * About MAC flow rules: + * * - MAC flow rules are generated from @p dev->data->mac_addrs * (@p priv->mac array). * - An additional flow rule for Ethernet broadcasts is also generated. @@ -1072,6 +1080,9 @@ mlx4_flow_internal(struct priv *priv, struct rte_flow_error *error) const struct rte_flow_item_eth eth_mask = { .dst.addr_bytes = "\xff\xff\xff\xff\xff\xff", }; + const struct rte_flow_item_eth eth_allmulti = { + .dst.addr_bytes = "\x01\x00\x00\x00\x00\x00", + }; struct rte_flow_item_vlan vlan_spec; const struct rte_flow_item_vlan vlan_mask = { .tci = RTE_BE16(0x0fff), @@ -1106,9 +1117,13 @@ mlx4_flow_internal(struct priv *priv, struct rte_flow_error *error) }; struct ether_addr *rule_mac = ð_spec.dst; rte_be16_t *rule_vlan = - priv->dev->data->dev_conf.rxmode.hw_vlan_filter ? + priv->dev->data->dev_conf.rxmode.hw_vlan_filter && + !priv->dev->data->promiscuous ? &vlan_spec.tci : NULL; + int broadcast = + !priv->dev->data->promiscuous && + !priv->dev->data->all_multicast; uint16_t vlan = 0; struct rte_flow *flow; unsigned int i; @@ -1132,7 +1147,7 @@ mlx4_flow_internal(struct priv *priv, struct rte_flow_error *error) rule_vlan = NULL; } } - for (i = 0; i != RTE_DIM(priv->mac) + 1; ++i) { + for (i = 0; i != RTE_DIM(priv->mac) + broadcast; ++i) { const struct ether_addr *mac; /* Broadcasts are handled by an extra iteration. */ @@ -1178,23 +1193,59 @@ mlx4_flow_internal(struct priv *priv, struct rte_flow_error *error) actions, error); if (!flow) { err = -rte_errno; - break; + goto error; } } flow->select = 1; flow->mac = 1; } - if (!err && rule_vlan) { + if (rule_vlan) { vlan = mlx4_flow_internal_next_vlan(priv, vlan + 1); if (vlan < 4096) goto next_vlan; } - /* Clear selection and clean up stale MAC flow rules. */ + /* Take care of promiscuous and all multicast flow rules. */ + if (!broadcast) { + for (flow = LIST_FIRST(&priv->flows); + flow && flow->internal; + flow = LIST_NEXT(flow, next)) { + if (priv->dev->data->promiscuous) { + if (flow->promisc) + break; + } else { + assert(priv->dev->data->all_multicast); + if (flow->allmulti) + break; + } + } + if (!flow || !flow->internal) { + /* Not found, create a new flow rule. */ + if (priv->dev->data->promiscuous) { + pattern[1].spec = NULL; + pattern[1].mask = NULL; + } else { + assert(priv->dev->data->all_multicast); + pattern[1].spec = ð_allmulti; + pattern[1].mask = ð_allmulti; + } + pattern[2] = pattern[3]; + flow = mlx4_flow_create(priv->dev, &attr, pattern, + actions, error); + if (!flow) { + err = -rte_errno; + goto error; + } + } + assert(flow->promisc || flow->allmulti); + flow->select = 1; + } +error: + /* Clear selection and clean up stale internal flow rules. */ flow = LIST_FIRST(&priv->flows); while (flow && flow->internal) { struct rte_flow *next = LIST_NEXT(flow, next); - if (flow->mac && !flow->select) + if (!flow->select) claim_zero(mlx4_flow_destroy(priv->dev, flow, error)); else flow->select = 0;