From: Pascal Mazon Date: Thu, 23 Mar 2017 08:33:55 +0000 (+0100) Subject: net/tap: add preliminary support for flow API X-Git-Url: http://git.droids-corp.org/?a=commitdiff_plain;h=268483dc2086;p=dpdk.git net/tap: add preliminary support for flow API The flow API provides the ability to classify packets received by a tap netdevice. This patch only implements skeleton functions for flow API support, no patterns are supported yet. Signed-off-by: Pascal Mazon Acked-by: Olga Shern Acked-by: Keith Wiles --- diff --git a/doc/guides/nics/features/tap.ini b/doc/guides/nics/features/tap.ini index a51712dce0..9d73f61cca 100644 --- a/doc/guides/nics/features/tap.ini +++ b/doc/guides/nics/features/tap.ini @@ -9,6 +9,7 @@ Jumbo frame = Y Promiscuous mode = Y Allmulticast mode = Y Basic stats = Y +Flow API = Y MTU update = Y Multicast MAC filter = Y Speed capabilities = Y diff --git a/drivers/net/tap/Makefile b/drivers/net/tap/Makefile index fa4658bd1e..45c67de8e9 100644 --- a/drivers/net/tap/Makefile +++ b/drivers/net/tap/Makefile @@ -47,6 +47,7 @@ CFLAGS += $(WERROR_FLAGS) # all source are stored in SRCS-y # SRCS-$(CONFIG_RTE_LIBRTE_PMD_TAP) += rte_eth_tap.c +SRCS-$(CONFIG_RTE_LIBRTE_PMD_TAP) += tap_flow.c # this lib depends upon: DEPDIRS-$(CONFIG_RTE_LIBRTE_PMD_TAP) += lib/librte_eal diff --git a/drivers/net/tap/rte_eth_tap.c b/drivers/net/tap/rte_eth_tap.c index 6bb63e5ec8..9127c739a2 100644 --- a/drivers/net/tap/rte_eth_tap.c +++ b/drivers/net/tap/rte_eth_tap.c @@ -56,6 +56,7 @@ #include #include +#include /* Linux based path to the TUN device */ #define TUN_TAP_DEV_PATH "/dev/net/tun" @@ -482,6 +483,7 @@ tap_dev_close(struct rte_eth_dev *dev __rte_unused) struct pmd_internals *internals = dev->data->dev_private; tap_link_set_down(dev); + tap_flow_flush(dev, NULL); for (i = 0; i < internals->nb_queues; i++) { if (internals->rxq[i].fd != -1) @@ -806,6 +808,7 @@ static const struct eth_dev_ops ops = { .stats_get = tap_stats_get, .stats_reset = tap_stats_reset, .dev_supported_ptypes_get = tap_dev_supported_ptypes_get, + .filter_ctrl = tap_dev_filter_ctrl, }; static int @@ -877,6 +880,8 @@ eth_dev_tap_create(const char *name, char *tap_name) pmd->txq[i].fd = -1; } + LIST_INIT(&pmd->flows); + return 0; error_exit: @@ -990,6 +995,7 @@ rte_pmd_tap_remove(const char *name) return 0; internals = eth_dev->data->dev_private; + tap_flow_flush(eth_dev, NULL); for (i = 0; i < internals->nb_queues; i++) if (internals->rxq[i].fd != -1) close(internals->rxq[i].fd); diff --git a/drivers/net/tap/rte_eth_tap.h b/drivers/net/tap/rte_eth_tap.h index aafdef1faa..bf82267366 100644 --- a/drivers/net/tap/rte_eth_tap.h +++ b/drivers/net/tap/rte_eth_tap.h @@ -34,6 +34,7 @@ #ifndef _RTE_ETH_TAP_H_ #define _RTE_ETH_TAP_H_ +#include #include #include @@ -68,6 +69,7 @@ struct pmd_internals { struct ether_addr eth_addr; /* Mac address of the device port */ int if_index; /* IF_INDEX for the port */ int ioctl_sock; /* socket for ioctl calls */ + LIST_HEAD(tap_flows, rte_flow) flows; /* rte_flow rules */ struct rx_queue rxq[RTE_PMD_TAP_MAX_QUEUES]; /* List of RX queues */ struct tx_queue txq[RTE_PMD_TAP_MAX_QUEUES]; /* List of TX queues */ }; diff --git a/drivers/net/tap/tap_flow.c b/drivers/net/tap/tap_flow.c new file mode 100644 index 0000000000..c32ed382d7 --- /dev/null +++ b/drivers/net/tap/tap_flow.c @@ -0,0 +1,185 @@ +/*- + * 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 + +struct rte_flow { + LIST_ENTRY(rte_flow) next; /* Pointer to the next rte_flow structure */ +}; + +static int +tap_flow_validate(struct rte_eth_dev *dev, + const struct rte_flow_attr *attr, + const struct rte_flow_item items[], + const struct rte_flow_action actions[], + struct rte_flow_error *error); + +static struct rte_flow * +tap_flow_create(struct rte_eth_dev *dev, + const struct rte_flow_attr *attr, + const struct rte_flow_item items[], + const struct rte_flow_action actions[], + struct rte_flow_error *error); + +static int +tap_flow_destroy(struct rte_eth_dev *dev, + struct rte_flow *flow, + struct rte_flow_error *error); + +static const struct rte_flow_ops tap_flow_ops = { + .validate = tap_flow_validate, + .create = tap_flow_create, + .destroy = tap_flow_destroy, + .flush = tap_flow_flush, +}; + +/** + * Validate a flow. + * + * @see rte_flow_validate() + * @see rte_flow_ops + */ +static int +tap_flow_validate(struct rte_eth_dev *dev __rte_unused, + const struct rte_flow_attr *attr __rte_unused, + const struct rte_flow_item items[] __rte_unused, + const struct rte_flow_action actions[] __rte_unused, + struct rte_flow_error *error) +{ + return -rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, + NULL, "not implemented yet"); +} + +/** + * Create a flow. + * + * @see rte_flow_create() + * @see rte_flow_ops + */ +static struct rte_flow * +tap_flow_create(struct rte_eth_dev *dev, + const struct rte_flow_attr *attr, + const struct rte_flow_item items[], + const struct rte_flow_action actions[], + struct rte_flow_error *error) +{ + struct pmd_internals *pmd = dev->data->dev_private; + struct rte_flow *flow = NULL; + + if (tap_flow_validate(dev, attr, items, actions, error)) + return NULL; + flow = rte_malloc(__func__, sizeof(struct rte_flow), 0); + if (!flow) { + rte_flow_error_set(error, ENOMEM, RTE_FLOW_ERROR_TYPE_HANDLE, + NULL, "cannot allocate memory for rte_flow"); + return NULL; + } + LIST_INSERT_HEAD(&pmd->flows, flow, next); + return flow; +} + +/** + * Destroy a flow. + * + * @see rte_flow_destroy() + * @see rte_flow_ops + */ +static int +tap_flow_destroy(struct rte_eth_dev *dev __rte_unused, + struct rte_flow *flow, + struct rte_flow_error *error __rte_unused) +{ + LIST_REMOVE(flow, next); + rte_free(flow); + return 0; +} + +/** + * Destroy all flows. + * + * @see rte_flow_flush() + * @see rte_flow_ops + */ +int +tap_flow_flush(struct rte_eth_dev *dev, struct rte_flow_error *error) +{ + struct pmd_internals *pmd = dev->data->dev_private; + struct rte_flow *flow; + + while (!LIST_EMPTY(&pmd->flows)) { + flow = LIST_FIRST(&pmd->flows); + if (tap_flow_destroy(dev, flow, error) < 0) + return -1; + } + return 0; +} + +/** + * Manage filter operations. + * + * @param dev + * Pointer to Ethernet device structure. + * @param filter_type + * Filter type. + * @param filter_op + * Operation to perform. + * @param arg + * Pointer to operation-specific structure. + * + * @return + * 0 on success, negative errno value on failure. + */ +int +tap_dev_filter_ctrl(struct rte_eth_dev *dev, + enum rte_filter_type filter_type, + enum rte_filter_op filter_op, + void *arg) +{ + switch (filter_type) { + case RTE_ETH_FILTER_GENERIC: + if (filter_op != RTE_ETH_FILTER_GET) + return -EINVAL; + *(const void **)arg = &tap_flow_ops; + return 0; + default: + RTE_LOG(ERR, PMD, "%p: filter type (%d) not supported", + (void *)dev, filter_type); + } + return -EINVAL; +} + diff --git a/drivers/net/tap/tap_flow.h b/drivers/net/tap/tap_flow.h new file mode 100644 index 0000000000..377a9f7b75 --- /dev/null +++ b/drivers/net/tap/tap_flow.h @@ -0,0 +1,46 @@ +/*- + * 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. + */ + +#ifndef _TAP_FLOW_H_ +#define _TAP_FLOW_H_ + +#include +#include + +int tap_dev_filter_ctrl(struct rte_eth_dev *dev, + enum rte_filter_type filter_type, + enum rte_filter_op filter_op, + void *arg); +int tap_flow_flush(struct rte_eth_dev *dev, struct rte_flow_error *error); + +#endif /* _TAP_FLOW_H_ */