From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-wm0-f47.google.com (mail-wm0-f47.google.com [74.125.82.47]) by dpdk.org (Postfix) with ESMTP id 03B0990F9 for ; Thu, 8 Jun 2017 02:00:23 +0200 (CEST) Received: by mail-wm0-f47.google.com with SMTP id m7so35449286wmg.0 for ; Wed, 07 Jun 2017 17:00:23 -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=+kPFOcsAqwTRQ0SC8tK7B0FbUFibrOccpgeQL4Fh98U=; b=IK2n6/+5Snr5HcTN5zP1PvIttlfO0PSQ7bn8B6URufcZ94uubcfDH7uA+SUm58pllU d7JSbIaEtmHOBp++5ZOXEmDMA56ez7pd8dTmdDbd9FZYRKbq17BGYFZcBLBf0JxLO0Mb DecBk1a7+58apeZBFM0y1TEUsdR8w8GGVBfp70pEIE8agTeuC1fWXwArZn/oYhuFMq95 gHT6sdSc619+OKgEd6thbl/QsgtdVj5CmDRG0PUmyn5gXjifHDddllW+fKijjNYwtWLV QfxLWLc9XAy9oZksrzKV/HdDb/LCAIpbmxqhfvwvjQUVQ424YKfsxai2OCpfVLRcAOml kUhQ== 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=+kPFOcsAqwTRQ0SC8tK7B0FbUFibrOccpgeQL4Fh98U=; b=d3ceMh4SEO8zUBqUqN62gbAOnCmMYvR5bIlpijAJQjFNSpZYO1u/PgHAd8dhZvM3Gj N7tF2KRMm47V5mGSFxv+Z66lbPd6cPAjJJeLHS1rirgk9o71oLIhh2NEG6dpJ9uJjzqx aKdn1tqJ08bzDqgv3kGkv/nc91a8hOLBUNyFNDpPQrYD6WX8vrwD/avMCWizqgRViJGt lnl2QFy2jGgjjOKk3RB9rlU619SAnlInjVRkzUpWOKYRIb+AGagCdlDpJrTNpM7jD8hF UC2ntDgK4+QJFI0BudhWTyS1OYNcDIAHAc4ml0b0cljG0wkgqYZbuj4R2LuWjGE+EkE6 boKA== X-Gm-Message-State: AODbwcAbgPwq+a67yF9SkQnyvUqSUpxJScVnQKuHQIbiebhnV0oRNPi4 VIr6cETcg54gzjNcVyM= X-Received: by 10.28.128.198 with SMTP id b189mr1308323wmd.79.1496880022215; Wed, 07 Jun 2017 17:00:22 -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 s10sm4337785wmb.8.2017.06.07.17.00.20 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 07 Jun 2017 17:00:21 -0700 (PDT) From: Gaetan Rivet To: dev@dpdk.org Cc: Gaetan Rivet Date: Thu, 8 Jun 2017 01:59:57 +0200 Message-Id: X-Mailer: git-send-email 2.1.4 In-Reply-To: References: In-Reply-To: References: Subject: [dpdk-dev] [PATCH v5 07/12] 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: , X-List-Received-Date: Thu, 08 Jun 2017 00:00:23 -0000 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 | 216 ++++++++++++++++++++++++++++++++ drivers/net/failsafe/failsafe_ops.c | 29 +++++ drivers/net/failsafe/failsafe_private.h | 18 +++ 8 files changed, 337 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 3c52823..9167b59 100644 --- a/doc/guides/nics/features/failsafe.ini +++ b/doc/guides/nics/features/failsafe.ini @@ -13,6 +13,7 @@ Allmulticast mode = Y Unicast MAC filter = Y Multicast MAC filter = Y VLAN filter = 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 4567961..a53bb75 100644 --- a/drivers/net/failsafe/Makefile +++ b/drivers/net/failsafe/Makefile @@ -41,6 +41,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 888f07b..6557255 100644 --- a/drivers/net/failsafe/failsafe.c +++ b/drivers/net/failsafe/failsafe.c @@ -177,6 +177,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; if (params == NULL) { diff --git a/drivers/net/failsafe/failsafe_eal.c b/drivers/net/failsafe/failsafe_eal.c index ec0f221..4ae99e0 100644 --- a/drivers/net/failsafe/failsafe_eal.c +++ b/drivers/net/failsafe/failsafe_eal.c @@ -81,6 +81,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..d8f59a1 --- /dev/null +++ b/drivers/net/failsafe/failsafe_flow.c @@ -0,0 +1,216 @@ +/*- + * 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)->fd); + 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_ST(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_ST(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_ST(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); + rte_free(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_ST(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 4044473..4cb2e90 100644 --- a/drivers/net/failsafe/failsafe_ops.c +++ b/drivers/net/failsafe/failsafe_ops.c @@ -35,6 +35,7 @@ #include #include #include +#include #include "failsafe_private.h" @@ -628,6 +629,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_ST(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, @@ -655,4 +683,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 554d7a3..f40ea2f 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 = 0, 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 -- 2.1.4