diff options
Diffstat (limited to 'lib/librte_ether/rte_flow.c')
-rw-r--r-- | lib/librte_ether/rte_flow.c | 420 |
1 files changed, 0 insertions, 420 deletions
diff --git a/lib/librte_ether/rte_flow.c b/lib/librte_ether/rte_flow.c deleted file mode 100644 index 38f2d27b..00000000 --- a/lib/librte_ether/rte_flow.c +++ /dev/null @@ -1,420 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright 2016 6WIND S.A. - * Copyright 2016 Mellanox. - */ - -#include <errno.h> -#include <stddef.h> -#include <stdint.h> -#include <string.h> - -#include <rte_common.h> -#include <rte_errno.h> -#include <rte_branch_prediction.h> -#include "rte_ethdev.h" -#include "rte_flow_driver.h" -#include "rte_flow.h" - -/** - * Flow elements description tables. - */ -struct rte_flow_desc_data { - const char *name; - size_t size; -}; - -/** Generate flow_item[] entry. */ -#define MK_FLOW_ITEM(t, s) \ - [RTE_FLOW_ITEM_TYPE_ ## t] = { \ - .name = # t, \ - .size = s, \ - } - -/** Information about known flow pattern items. */ -static const struct rte_flow_desc_data rte_flow_desc_item[] = { - MK_FLOW_ITEM(END, 0), - MK_FLOW_ITEM(VOID, 0), - MK_FLOW_ITEM(INVERT, 0), - MK_FLOW_ITEM(ANY, sizeof(struct rte_flow_item_any)), - MK_FLOW_ITEM(PF, 0), - MK_FLOW_ITEM(VF, sizeof(struct rte_flow_item_vf)), - MK_FLOW_ITEM(PORT, sizeof(struct rte_flow_item_port)), - MK_FLOW_ITEM(RAW, sizeof(struct rte_flow_item_raw)), /* +pattern[] */ - MK_FLOW_ITEM(ETH, sizeof(struct rte_flow_item_eth)), - MK_FLOW_ITEM(VLAN, sizeof(struct rte_flow_item_vlan)), - MK_FLOW_ITEM(IPV4, sizeof(struct rte_flow_item_ipv4)), - MK_FLOW_ITEM(IPV6, sizeof(struct rte_flow_item_ipv6)), - MK_FLOW_ITEM(ICMP, sizeof(struct rte_flow_item_icmp)), - MK_FLOW_ITEM(UDP, sizeof(struct rte_flow_item_udp)), - MK_FLOW_ITEM(TCP, sizeof(struct rte_flow_item_tcp)), - MK_FLOW_ITEM(SCTP, sizeof(struct rte_flow_item_sctp)), - MK_FLOW_ITEM(VXLAN, sizeof(struct rte_flow_item_vxlan)), - MK_FLOW_ITEM(MPLS, sizeof(struct rte_flow_item_mpls)), - MK_FLOW_ITEM(GRE, sizeof(struct rte_flow_item_gre)), - MK_FLOW_ITEM(E_TAG, sizeof(struct rte_flow_item_e_tag)), - MK_FLOW_ITEM(NVGRE, sizeof(struct rte_flow_item_nvgre)), - MK_FLOW_ITEM(GENEVE, sizeof(struct rte_flow_item_geneve)), -}; - -/** Generate flow_action[] entry. */ -#define MK_FLOW_ACTION(t, s) \ - [RTE_FLOW_ACTION_TYPE_ ## t] = { \ - .name = # t, \ - .size = s, \ - } - -/** Information about known flow actions. */ -static const struct rte_flow_desc_data rte_flow_desc_action[] = { - MK_FLOW_ACTION(END, 0), - MK_FLOW_ACTION(VOID, 0), - MK_FLOW_ACTION(PASSTHRU, 0), - MK_FLOW_ACTION(MARK, sizeof(struct rte_flow_action_mark)), - MK_FLOW_ACTION(FLAG, 0), - MK_FLOW_ACTION(QUEUE, sizeof(struct rte_flow_action_queue)), - MK_FLOW_ACTION(DROP, 0), - MK_FLOW_ACTION(COUNT, 0), - MK_FLOW_ACTION(DUP, sizeof(struct rte_flow_action_dup)), - MK_FLOW_ACTION(RSS, sizeof(struct rte_flow_action_rss)), /* +queue[] */ - MK_FLOW_ACTION(PF, 0), - MK_FLOW_ACTION(VF, sizeof(struct rte_flow_action_vf)), -}; - -static int -flow_err(uint16_t port_id, int ret, struct rte_flow_error *error) -{ - if (ret == 0) - return 0; - if (rte_eth_dev_is_removed(port_id)) - return rte_flow_error_set(error, EIO, - RTE_FLOW_ERROR_TYPE_UNSPECIFIED, - NULL, rte_strerror(EIO)); - return ret; -} - -/* Get generic flow operations structure from a port. */ -const struct rte_flow_ops * -rte_flow_ops_get(uint16_t port_id, struct rte_flow_error *error) -{ - struct rte_eth_dev *dev = &rte_eth_devices[port_id]; - const struct rte_flow_ops *ops; - int code; - - if (unlikely(!rte_eth_dev_is_valid_port(port_id))) - code = ENODEV; - else if (unlikely(!dev->dev_ops->filter_ctrl || - dev->dev_ops->filter_ctrl(dev, - RTE_ETH_FILTER_GENERIC, - RTE_ETH_FILTER_GET, - &ops) || - !ops)) - code = ENOSYS; - else - return ops; - rte_flow_error_set(error, code, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, - NULL, rte_strerror(code)); - return NULL; -} - -/* Check whether a flow rule can be created on a given port. */ -int -rte_flow_validate(uint16_t port_id, - const struct rte_flow_attr *attr, - const struct rte_flow_item pattern[], - const struct rte_flow_action actions[], - struct rte_flow_error *error) -{ - const struct rte_flow_ops *ops = rte_flow_ops_get(port_id, error); - struct rte_eth_dev *dev = &rte_eth_devices[port_id]; - - if (unlikely(!ops)) - return -rte_errno; - if (likely(!!ops->validate)) - return flow_err(port_id, ops->validate(dev, attr, pattern, - actions, error), error); - return rte_flow_error_set(error, ENOSYS, - RTE_FLOW_ERROR_TYPE_UNSPECIFIED, - NULL, rte_strerror(ENOSYS)); -} - -/* Create a flow rule on a given port. */ -struct rte_flow * -rte_flow_create(uint16_t port_id, - const struct rte_flow_attr *attr, - const struct rte_flow_item pattern[], - const struct rte_flow_action actions[], - struct rte_flow_error *error) -{ - struct rte_eth_dev *dev = &rte_eth_devices[port_id]; - struct rte_flow *flow; - const struct rte_flow_ops *ops = rte_flow_ops_get(port_id, error); - - if (unlikely(!ops)) - return NULL; - if (likely(!!ops->create)) { - flow = ops->create(dev, attr, pattern, actions, error); - if (flow == NULL) - flow_err(port_id, -rte_errno, error); - return flow; - } - rte_flow_error_set(error, ENOSYS, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, - NULL, rte_strerror(ENOSYS)); - return NULL; -} - -/* Destroy a flow rule on a given port. */ -int -rte_flow_destroy(uint16_t port_id, - struct rte_flow *flow, - struct rte_flow_error *error) -{ - struct rte_eth_dev *dev = &rte_eth_devices[port_id]; - const struct rte_flow_ops *ops = rte_flow_ops_get(port_id, error); - - if (unlikely(!ops)) - return -rte_errno; - if (likely(!!ops->destroy)) - return flow_err(port_id, ops->destroy(dev, flow, error), - error); - return rte_flow_error_set(error, ENOSYS, - RTE_FLOW_ERROR_TYPE_UNSPECIFIED, - NULL, rte_strerror(ENOSYS)); -} - -/* Destroy all flow rules associated with a port. */ -int -rte_flow_flush(uint16_t port_id, - struct rte_flow_error *error) -{ - struct rte_eth_dev *dev = &rte_eth_devices[port_id]; - const struct rte_flow_ops *ops = rte_flow_ops_get(port_id, error); - - if (unlikely(!ops)) - return -rte_errno; - if (likely(!!ops->flush)) - return flow_err(port_id, ops->flush(dev, error), error); - return rte_flow_error_set(error, ENOSYS, - RTE_FLOW_ERROR_TYPE_UNSPECIFIED, - NULL, rte_strerror(ENOSYS)); -} - -/* Query an existing flow rule. */ -int -rte_flow_query(uint16_t port_id, - struct rte_flow *flow, - enum rte_flow_action_type action, - void *data, - struct rte_flow_error *error) -{ - struct rte_eth_dev *dev = &rte_eth_devices[port_id]; - const struct rte_flow_ops *ops = rte_flow_ops_get(port_id, error); - - if (!ops) - return -rte_errno; - if (likely(!!ops->query)) - return flow_err(port_id, ops->query(dev, flow, action, data, - error), error); - return rte_flow_error_set(error, ENOSYS, - RTE_FLOW_ERROR_TYPE_UNSPECIFIED, - NULL, rte_strerror(ENOSYS)); -} - -/* Restrict ingress traffic to the defined flow rules. */ -int -rte_flow_isolate(uint16_t port_id, - int set, - struct rte_flow_error *error) -{ - struct rte_eth_dev *dev = &rte_eth_devices[port_id]; - const struct rte_flow_ops *ops = rte_flow_ops_get(port_id, error); - - if (!ops) - return -rte_errno; - if (likely(!!ops->isolate)) - return flow_err(port_id, ops->isolate(dev, set, error), error); - return rte_flow_error_set(error, ENOSYS, - RTE_FLOW_ERROR_TYPE_UNSPECIFIED, - NULL, rte_strerror(ENOSYS)); -} - -/* Initialize flow error structure. */ -int -rte_flow_error_set(struct rte_flow_error *error, - int code, - enum rte_flow_error_type type, - const void *cause, - const char *message) -{ - if (error) { - *error = (struct rte_flow_error){ - .type = type, - .cause = cause, - .message = message, - }; - } - rte_errno = code; - return -code; -} - -/** Compute storage space needed by item specification. */ -static void -flow_item_spec_size(const struct rte_flow_item *item, - size_t *size, size_t *pad) -{ - if (!item->spec) { - *size = 0; - goto empty; - } - switch (item->type) { - union { - const struct rte_flow_item_raw *raw; - } spec; - - /* Not a fall-through */ - case RTE_FLOW_ITEM_TYPE_RAW: - spec.raw = item->spec; - *size = offsetof(struct rte_flow_item_raw, pattern) + - spec.raw->length * sizeof(*spec.raw->pattern); - break; - default: - *size = rte_flow_desc_item[item->type].size; - break; - } -empty: - *pad = RTE_ALIGN_CEIL(*size, sizeof(double)) - *size; -} - -/** Compute storage space needed by action configuration. */ -static void -flow_action_conf_size(const struct rte_flow_action *action, - size_t *size, size_t *pad) -{ - if (!action->conf) { - *size = 0; - goto empty; - } - switch (action->type) { - union { - const struct rte_flow_action_rss *rss; - } conf; - - /* Not a fall-through. */ - case RTE_FLOW_ACTION_TYPE_RSS: - conf.rss = action->conf; - *size = offsetof(struct rte_flow_action_rss, queue) + - conf.rss->num * sizeof(*conf.rss->queue); - break; - default: - *size = rte_flow_desc_action[action->type].size; - break; - } -empty: - *pad = RTE_ALIGN_CEIL(*size, sizeof(double)) - *size; -} - -/** Store a full rte_flow description. */ -size_t -rte_flow_copy(struct rte_flow_desc *desc, size_t len, - const struct rte_flow_attr *attr, - const struct rte_flow_item *items, - const struct rte_flow_action *actions) -{ - struct rte_flow_desc *fd = NULL; - size_t tmp; - size_t pad; - size_t off1 = 0; - size_t off2 = 0; - size_t size = 0; - -store: - if (items) { - const struct rte_flow_item *item; - - item = items; - if (fd) - fd->items = (void *)&fd->data[off1]; - do { - struct rte_flow_item *dst = NULL; - - if ((size_t)item->type >= - RTE_DIM(rte_flow_desc_item) || - !rte_flow_desc_item[item->type].name) { - rte_errno = ENOTSUP; - return 0; - } - if (fd) - dst = memcpy(fd->data + off1, item, - sizeof(*item)); - off1 += sizeof(*item); - flow_item_spec_size(item, &tmp, &pad); - if (item->spec) { - if (fd) - dst->spec = memcpy(fd->data + off2, - item->spec, tmp); - off2 += tmp + pad; - } - if (item->last) { - if (fd) - dst->last = memcpy(fd->data + off2, - item->last, tmp); - off2 += tmp + pad; - } - if (item->mask) { - if (fd) - dst->mask = memcpy(fd->data + off2, - item->mask, tmp); - off2 += tmp + pad; - } - off2 = RTE_ALIGN_CEIL(off2, sizeof(double)); - } while ((item++)->type != RTE_FLOW_ITEM_TYPE_END); - off1 = RTE_ALIGN_CEIL(off1, sizeof(double)); - } - if (actions) { - const struct rte_flow_action *action; - - action = actions; - if (fd) - fd->actions = (void *)&fd->data[off1]; - do { - struct rte_flow_action *dst = NULL; - - if ((size_t)action->type >= - RTE_DIM(rte_flow_desc_action) || - !rte_flow_desc_action[action->type].name) { - rte_errno = ENOTSUP; - return 0; - } - if (fd) - dst = memcpy(fd->data + off1, action, - sizeof(*action)); - off1 += sizeof(*action); - flow_action_conf_size(action, &tmp, &pad); - if (action->conf) { - if (fd) - dst->conf = memcpy(fd->data + off2, - action->conf, tmp); - off2 += tmp + pad; - } - off2 = RTE_ALIGN_CEIL(off2, sizeof(double)); - } while ((action++)->type != RTE_FLOW_ACTION_TYPE_END); - } - if (fd != NULL) - return size; - off1 = RTE_ALIGN_CEIL(off1, sizeof(double)); - tmp = RTE_ALIGN_CEIL(offsetof(struct rte_flow_desc, data), - sizeof(double)); - size = tmp + off1 + off2; - if (size > len) - return size; - fd = desc; - if (fd != NULL) { - *fd = (const struct rte_flow_desc) { - .size = size, - .attr = *attr, - }; - tmp -= offsetof(struct rte_flow_desc, data); - off2 = tmp + off1; - off1 = tmp; - goto store; - } - return 0; -} |