From patchwork Tue Jul 18 12:48:17 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?q?Ga=C3=ABtan_Rivet?= X-Patchwork-Id: 27026 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 [IPv6:::1]) by dpdk.org (Postfix) with ESMTP id E8D367CBE; Tue, 18 Jul 2017 14:48:59 +0200 (CEST) Received: from mail-wr0-f176.google.com (mail-wr0-f176.google.com [209.85.128.176]) by dpdk.org (Postfix) with ESMTP id E45AC567E for ; Tue, 18 Jul 2017 14:48:45 +0200 (CEST) Received: by mail-wr0-f176.google.com with SMTP id 12so27971077wrb.1 for ; Tue, 18 Jul 2017 05:48:45 -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 :in-reply-to:references; bh=HdlVIbMJCQ54Dv5lrd6Y0kX9UYCIPZ1lNdLtJUM932U=; b=ZBbY0+gpMNlpoqAJCoxW7bTXv7IibSteJoSoWrt7Y+qo4iLBmiYf5SLlCpYpdjagvX ulJfgGxIXgk7Yj1eok20hfCDCYwQ6BQ2qo1IcgrWeaTY8UzCSBHLPveNEN48LJ3DXa2L GROLggR1LeZOjkLzMzcrGWCUS3qslJV2f1hvBffnhyPB8sRwc+m//qNNqRzpEQWfBPie UXlR2Wk3zaINuBlN9fvnDbuHlNJe8IoGiNGigmrhWNv32O8tBWUO6Mte9/hycvbtXAP9 sV6vFTPhtKLK9xiScJvHBApOb7wXiJVKMBCsugdPvJmns1PPaZ8/pXCWKiRyTQo0RaZc uKMw== 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:in-reply-to:references; bh=HdlVIbMJCQ54Dv5lrd6Y0kX9UYCIPZ1lNdLtJUM932U=; b=L6vZSIRNpns3zxqWX4W5IrkMFFwI2DnqzvAhWE104nlqBZfetGSLOJJExzmFR8OD79 sIAoIDttGuUdSRjeKn/XZFRaIs19Ck2UOjVo6iQ8xqTJSkwmb1nhijvZFdYsrgVtsacW 0j+gePKvYJ+yl6PjgF84Cgk9xZ8ZL6CJrTZ5m1SFu/wJ6DDeoXwZsx2vw3aQVTSmB64z KgLpZvJrrvTGw80CyMQ7QhVwt24IoWYM+sUpxQ3FhuhEg31T6OUlDbQTgwrOWZCTv8aH 8bfG6bblw9wKMiQSWDzG8VYt9jv/+hEsIFvJR3Cfj3ygnfaizyqvswM9v2vv8iagp4Gi 6GwA== X-Gm-Message-State: AIVw111hIcfdl6azMDCXbnBbpUlS+tQCje37IcwB0cxc/LSziuaFff0O V9wafyi1TptfCS9oRgQ= X-Received: by 10.28.137.146 with SMTP id l140mr2079856wmd.101.1500382124968; Tue, 18 Jul 2017 05:48:44 -0700 (PDT) Received: from bidouze.dev.6wind.com (host.78.145.23.62.rev.coltfrance.com. [62.23.145.78]) by smtp.gmail.com with ESMTPSA id j8sm1033960wrj.10.2017.07.18.05.48.43 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 18 Jul 2017 05:48:44 -0700 (PDT) From: Gaetan Rivet To: dev@dpdk.org Cc: Gaetan Rivet Date: Tue, 18 Jul 2017 14:48:17 +0200 Message-Id: X-Mailer: git-send-email 2.1.4 In-Reply-To: References: In-Reply-To: References: Subject: [dpdk-dev] [PATCH v11 06/11] net/failsafe: support flow API 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" Signed-off-by: Gaetan Rivet Acked-by: Olga Shern --- doc/guides/nics/features/failsafe.ini | 1 + drivers/net/failsafe/Makefile | 1 + drivers/net/failsafe/failsafe.c | 1 + drivers/net/failsafe/failsafe_eal.c | 1 + drivers/net/failsafe/failsafe_ether.c | 70 +++++++++++ drivers/net/failsafe/failsafe_flow.c | 215 ++++++++++++++++++++++++++++++++ drivers/net/failsafe/failsafe_ops.c | 29 +++++ drivers/net/failsafe/failsafe_private.h | 18 +++ 8 files changed, 336 insertions(+) create mode 100644 drivers/net/failsafe/failsafe_flow.c diff --git a/doc/guides/nics/features/failsafe.ini b/doc/guides/nics/features/failsafe.ini index cf3e1af..2e802aa 100644 --- a/doc/guides/nics/features/failsafe.ini +++ b/doc/guides/nics/features/failsafe.ini @@ -13,6 +13,7 @@ Unicast MAC filter = Y Multicast MAC filter = Y VLAN filter = Y Flow control = Y +Flow API = Y Packet type parsing = Y Basic stats = Y Stats per queue = Y diff --git a/drivers/net/failsafe/Makefile b/drivers/net/failsafe/Makefile index 3488198..cec33df 100644 --- a/drivers/net/failsafe/Makefile +++ b/drivers/net/failsafe/Makefile @@ -45,6 +45,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += failsafe_eal.c SRCS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += failsafe_ops.c SRCS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += failsafe_rxtx.c SRCS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += failsafe_ether.c +SRCS-$(CONFIG_RTE_LIBRTE_PMD_FAILSAFE) += failsafe_flow.c # No exported include files diff --git a/drivers/net/failsafe/failsafe.c b/drivers/net/failsafe/failsafe.c index 8db6355..12d79ac 100644 --- a/drivers/net/failsafe/failsafe.c +++ b/drivers/net/failsafe/failsafe.c @@ -179,6 +179,7 @@ fs_eth_dev_create(struct rte_vdev_device *vdev) dev->data->mac_addrs = &PRIV(dev)->mac_addrs[0]; dev->data->dev_link = eth_link; PRIV(dev)->nb_mac_addr = 1; + TAILQ_INIT(&PRIV(dev)->flow_list); dev->rx_pkt_burst = (eth_rx_burst_t)&failsafe_rx_burst; dev->tx_pkt_burst = (eth_tx_burst_t)&failsafe_tx_burst; ret = fs_sub_device_alloc(dev, params); diff --git a/drivers/net/failsafe/failsafe_eal.c b/drivers/net/failsafe/failsafe_eal.c index 8a3836c..d11ea67 100644 --- a/drivers/net/failsafe/failsafe_eal.c +++ b/drivers/net/failsafe/failsafe_eal.c @@ -62,6 +62,7 @@ fs_bus_init(struct rte_eth_dev *dev) ERROR("sub_device %d init went wrong", i); return -ENODEV; } + SUB_ID(sdev) = i; sdev->dev = ETH(sdev)->device; ETH(sdev)->state = RTE_ETH_DEV_DEFERRED; sdev->state = DEV_PROBED; diff --git a/drivers/net/failsafe/failsafe_ether.c b/drivers/net/failsafe/failsafe_ether.c index 2a1535e..2958207 100644 --- a/drivers/net/failsafe/failsafe_ether.c +++ b/drivers/net/failsafe/failsafe_ether.c @@ -33,8 +33,46 @@ #include +#include +#include + #include "failsafe_private.h" +/** Print a message out of a flow error. */ +static int +fs_flow_complain(struct rte_flow_error *error) +{ + static const char *const errstrlist[] = { + [RTE_FLOW_ERROR_TYPE_NONE] = "no error", + [RTE_FLOW_ERROR_TYPE_UNSPECIFIED] = "cause unspecified", + [RTE_FLOW_ERROR_TYPE_HANDLE] = "flow rule (handle)", + [RTE_FLOW_ERROR_TYPE_ATTR_GROUP] = "group field", + [RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY] = "priority field", + [RTE_FLOW_ERROR_TYPE_ATTR_INGRESS] = "ingress field", + [RTE_FLOW_ERROR_TYPE_ATTR_EGRESS] = "egress field", + [RTE_FLOW_ERROR_TYPE_ATTR] = "attributes structure", + [RTE_FLOW_ERROR_TYPE_ITEM_NUM] = "pattern length", + [RTE_FLOW_ERROR_TYPE_ITEM] = "specific pattern item", + [RTE_FLOW_ERROR_TYPE_ACTION_NUM] = "number of actions", + [RTE_FLOW_ERROR_TYPE_ACTION] = "specific action", + }; + const char *errstr; + char buf[32]; + int err = rte_errno; + + if ((unsigned int)error->type >= RTE_DIM(errstrlist) || + !errstrlist[error->type]) + errstr = "unknown type"; + else + errstr = errstrlist[error->type]; + ERROR("Caught error type %d (%s): %s%s\n", + error->type, errstr, + error->cause ? (snprintf(buf, sizeof(buf), "cause: %p, ", + error->cause), buf) : "", + error->message ? error->message : "(no stated reason)"); + return -err; +} + static int fs_eth_dev_conf_apply(struct rte_eth_dev *dev, struct sub_device *sdev) @@ -42,6 +80,8 @@ fs_eth_dev_conf_apply(struct rte_eth_dev *dev, struct rte_eth_dev *edev; struct rte_vlan_filter_conf *vfc1; struct rte_vlan_filter_conf *vfc2; + struct rte_flow *flow; + struct rte_flow_error ferror; uint32_t i; int ret; @@ -177,6 +217,36 @@ fs_eth_dev_conf_apply(struct rte_eth_dev *dev, } else { DEBUG("VLAN filter already set"); } + /* rte_flow */ + if (TAILQ_EMPTY(&PRIV(dev)->flow_list)) { + DEBUG("rte_flow already set"); + } else { + DEBUG("Resetting rte_flow configuration"); + ret = rte_flow_flush(PORT_ID(sdev), &ferror); + if (ret) { + fs_flow_complain(&ferror); + return ret; + } + i = 0; + rte_errno = 0; + DEBUG("Configuring rte_flow"); + TAILQ_FOREACH(flow, &PRIV(dev)->flow_list, next) { + DEBUG("Creating flow #%" PRIu32, i++); + flow->flows[SUB_ID(sdev)] = + rte_flow_create(PORT_ID(sdev), + &flow->fd->attr, + flow->fd->items, + flow->fd->actions, + &ferror); + ret = rte_errno; + if (ret) + break; + } + if (ret) { + fs_flow_complain(&ferror); + return ret; + } + } return 0; } diff --git a/drivers/net/failsafe/failsafe_flow.c b/drivers/net/failsafe/failsafe_flow.c new file mode 100644 index 0000000..0098672 --- /dev/null +++ b/drivers/net/failsafe/failsafe_flow.c @@ -0,0 +1,215 @@ +/*- + * BSD LICENSE + * + * Copyright 2017 6WIND S.A. + * Copyright 2017 Mellanox. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of 6WIND S.A. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include +#include +#include +#include + +#include "failsafe_private.h" + +static struct rte_flow * +fs_flow_allocate(const struct rte_flow_attr *attr, + const struct rte_flow_item *items, + const struct rte_flow_action *actions) +{ + struct rte_flow *flow; + size_t fdsz; + + fdsz = rte_flow_copy(NULL, 0, attr, items, actions); + flow = rte_zmalloc(NULL, + sizeof(struct rte_flow) + fdsz, + RTE_CACHE_LINE_SIZE); + if (flow == NULL) { + ERROR("Could not allocate new flow"); + return NULL; + } + flow->fd = (void *)((uintptr_t)flow + sizeof(*flow)); + if (rte_flow_copy(flow->fd, fdsz, attr, items, actions) != fdsz) { + ERROR("Failed to copy flow description"); + rte_free(flow); + return NULL; + } + return flow; +} + +static void +fs_flow_release(struct rte_flow **flow) +{ + rte_free(*flow); + *flow = NULL; +} + +static int +fs_flow_validate(struct rte_eth_dev *dev, + const struct rte_flow_attr *attr, + const struct rte_flow_item patterns[], + const struct rte_flow_action actions[], + struct rte_flow_error *error) +{ + struct sub_device *sdev; + uint8_t i; + int ret; + + FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) { + DEBUG("Calling rte_flow_validate on sub_device %d", i); + ret = rte_flow_validate(PORT_ID(sdev), + attr, patterns, actions, error); + if (ret) { + ERROR("Operation rte_flow_validate failed for sub_device %d" + " with error %d", i, ret); + return ret; + } + } + return 0; +} + +static struct rte_flow * +fs_flow_create(struct rte_eth_dev *dev, + const struct rte_flow_attr *attr, + const struct rte_flow_item patterns[], + const struct rte_flow_action actions[], + struct rte_flow_error *error) +{ + struct sub_device *sdev; + struct rte_flow *flow; + uint8_t i; + + flow = fs_flow_allocate(attr, patterns, actions); + FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) { + flow->flows[i] = rte_flow_create(PORT_ID(sdev), + attr, patterns, actions, error); + if (flow->flows[i] == NULL) { + ERROR("Failed to create flow on sub_device %d", + i); + goto err; + } + } + TAILQ_INSERT_TAIL(&PRIV(dev)->flow_list, flow, next); + return flow; +err: + FOREACH_SUBDEV(sdev, i, dev) { + if (flow->flows[i] != NULL) + rte_flow_destroy(PORT_ID(sdev), + flow->flows[i], error); + } + fs_flow_release(&flow); + return NULL; +} + +static int +fs_flow_destroy(struct rte_eth_dev *dev, + struct rte_flow *flow, + struct rte_flow_error *error) +{ + struct sub_device *sdev; + uint8_t i; + int ret; + + if (flow == NULL) { + ERROR("Invalid flow"); + return -EINVAL; + } + ret = 0; + FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) { + int local_ret; + + if (flow->flows[i] == NULL) + continue; + local_ret = rte_flow_destroy(PORT_ID(sdev), + flow->flows[i], error); + if (local_ret) { + ERROR("Failed to destroy flow on sub_device %d: %d", + i, local_ret); + if (ret == 0) + ret = local_ret; + } + } + TAILQ_REMOVE(&PRIV(dev)->flow_list, flow, next); + fs_flow_release(&flow); + return ret; +} + +static int +fs_flow_flush(struct rte_eth_dev *dev, + struct rte_flow_error *error) +{ + struct sub_device *sdev; + struct rte_flow *flow; + void *tmp; + uint8_t i; + int ret; + + FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) { + DEBUG("Calling rte_flow_flush on sub_device %d", i); + ret = rte_flow_flush(PORT_ID(sdev), error); + if (ret) { + ERROR("Operation rte_flow_flush failed for sub_device %d" + " with error %d", i, ret); + return ret; + } + } + TAILQ_FOREACH_SAFE(flow, &PRIV(dev)->flow_list, next, tmp) { + TAILQ_REMOVE(&PRIV(dev)->flow_list, flow, next); + fs_flow_release(&flow); + } + return 0; +} + +static int +fs_flow_query(struct rte_eth_dev *dev, + struct rte_flow *flow, + enum rte_flow_action_type type, + void *arg, + struct rte_flow_error *error) +{ + struct sub_device *sdev; + + sdev = TX_SUBDEV(dev); + if (sdev != NULL) { + return rte_flow_query(PORT_ID(sdev), + flow->flows[SUB_ID(sdev)], type, arg, error); + } + WARN("No active sub_device to query about its flow"); + return -1; +} + +const struct rte_flow_ops fs_flow_ops = { + .validate = fs_flow_validate, + .create = fs_flow_create, + .destroy = fs_flow_destroy, + .flush = fs_flow_flush, + .query = fs_flow_query, +}; diff --git a/drivers/net/failsafe/failsafe_ops.c b/drivers/net/failsafe/failsafe_ops.c index fdef019..223f26a 100644 --- a/drivers/net/failsafe/failsafe_ops.c +++ b/drivers/net/failsafe/failsafe_ops.c @@ -36,6 +36,7 @@ #include #include #include +#include #include "failsafe_private.h" @@ -627,6 +628,33 @@ fs_mac_addr_set(struct rte_eth_dev *dev, struct ether_addr *mac_addr) rte_eth_dev_default_mac_addr_set(PORT_ID(sdev), mac_addr); } +static int +fs_filter_ctrl(struct rte_eth_dev *dev, + enum rte_filter_type type, + enum rte_filter_op op, + void *arg) +{ + struct sub_device *sdev; + uint8_t i; + int ret; + + if (type == RTE_ETH_FILTER_GENERIC && + op == RTE_ETH_FILTER_GET) { + *(const void **)arg = &fs_flow_ops; + return 0; + } + FOREACH_SUBDEV_STATE(sdev, i, dev, DEV_ACTIVE) { + DEBUG("Calling rte_eth_dev_filter_ctrl on sub_device %d", i); + ret = rte_eth_dev_filter_ctrl(PORT_ID(sdev), type, op, arg); + if (ret) { + ERROR("Operation rte_eth_dev_filter_ctrl failed for sub_device %d" + " with error %d", i, ret); + return ret; + } + } + return 0; +} + const struct eth_dev_ops failsafe_ops = { .dev_configure = fs_dev_configure, .dev_start = fs_dev_start, @@ -654,4 +682,5 @@ const struct eth_dev_ops failsafe_ops = { .mac_addr_remove = fs_mac_addr_remove, .mac_addr_add = fs_mac_addr_add, .mac_addr_set = fs_mac_addr_set, + .filter_ctrl = fs_filter_ctrl, }; diff --git a/drivers/net/failsafe/failsafe_private.h b/drivers/net/failsafe/failsafe_private.h index 2342646..82d969d 100644 --- a/drivers/net/failsafe/failsafe_private.h +++ b/drivers/net/failsafe/failsafe_private.h @@ -34,6 +34,8 @@ #ifndef _RTE_ETH_FAILSAFE_PRIVATE_H_ #define _RTE_ETH_FAILSAFE_PRIVATE_H_ +#include + #include #include #include @@ -72,6 +74,14 @@ struct txq { struct rte_eth_txq_info info; }; +struct rte_flow { + TAILQ_ENTRY(rte_flow) next; + /* sub_flows */ + struct rte_flow *flows[FAILSAFE_MAX_ETHPORTS]; + /* flow description for synchronization */ + struct rte_flow_desc *fd; +}; + enum dev_state { DEV_UNDEFINED, DEV_PARSED, @@ -86,6 +96,7 @@ struct sub_device { struct rte_bus *bus; struct rte_device *dev; struct rte_eth_dev *edev; + uint8_t sid; /* Device state machine */ enum dev_state state; /* Some device are defined as a command line */ @@ -104,6 +115,8 @@ struct fs_priv { uint8_t subs_tail; /* first invalid */ uint8_t subs_tx; /* current emitting device */ uint8_t current_probed; + /* flow mapping */ + TAILQ_HEAD(sub_flows, rte_flow) flow_list; /* current number of mac_addr slots allocated. */ uint32_t nb_mac_addr; struct ether_addr mac_addrs[FAILSAFE_MAX_ETHADDR]; @@ -153,6 +166,7 @@ int failsafe_eth_dev_state_sync(struct rte_eth_dev *dev); extern const char pmd_failsafe_driver_name[]; extern const struct eth_dev_ops failsafe_ops; +extern const struct rte_flow_ops fs_flow_ops; extern uint64_t hotplug_poll; extern int mac_from_arg; @@ -170,6 +184,10 @@ extern int mac_from_arg; #define PORT_ID(sdev) \ (ETH(sdev)->data->port_id) +/* sdev: (struct sub_device *) */ +#define SUB_ID(sdev) \ + ((sdev)->sid) + /** * Stateful iterator construct over fail-safe sub-devices: * s: (struct sub_device *), iterator