Enhance description structure with information about embedded flexible arrays in order to handle items and actions through a common function without any dedicated code for special cases.
This commit also moves descriptions to a separate header file for clarity. Signed-off-by: Adrien Mazarguil <adrien.mazarg...@6wind.com> --- lib/librte_ether/rte_flow.c | 183 ++++++------------- lib/librte_ether/rte_flow_conv.h | 333 ++++++++++++++++++++++++++++++++++ 2 files changed, 392 insertions(+), 124 deletions(-) diff --git a/lib/librte_ether/rte_flow.c b/lib/librte_ether/rte_flow.c index f4fb607..46f430e 100644 --- a/lib/librte_ether/rte_flow.c +++ b/lib/librte_ether/rte_flow.c @@ -37,75 +37,14 @@ #include <string.h> #include <rte_common.h> +#include <rte_debug.h> #include <rte_errno.h> #include <rte_branch_prediction.h> #include "rte_ethdev.h" +#include "rte_flow_conv.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)), -}; - -/** 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)), -}; - /* Get generic flow operations structure from a port. */ const struct rte_flow_ops * rte_flow_ops_get(uint8_t port_id, struct rte_flow_error *error) @@ -243,59 +182,39 @@ rte_flow_isolate(uint8_t port_id, NULL, rte_strerror(ENOSYS)); } -/** 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. */ +/** Compute storage space needed for item->spec or action->conf. */ static void -flow_action_conf_size(const struct rte_flow_action *action, - size_t *size, size_t *pad) +rte_flow_conv_res_size(const struct rte_flow_conv_res *res, const void *obj, + size_t *size, size_t *pad) { - if (!action->conf) { + if (!obj) { *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; + } else if (res->flex_off) { + void *flex_len_ptr = + (void *)((uintptr_t)obj + res->flex_len_off); + uint64_t flex_len = 0; + + switch (res->flex_len_type) { + case sizeof(uint8_t): + flex_len = *(uint8_t *)flex_len_ptr; + break; + case sizeof(uint16_t): + flex_len = *(uint16_t *)flex_len_ptr; + break; + case sizeof(uint32_t): + flex_len = *(uint32_t *)flex_len_ptr; + break; + case sizeof(uint64_t): + flex_len = *(uint64_t *)flex_len_ptr; + break; + default: + RTE_ASSERT(!"unsupported flex_len_type in" + " struct rte_flow_conv_res"); + } + *size = res->flex_off + res->flex_elt_size * flex_len; + } else { + *size = res->size; } -empty: *pad = RTE_ALIGN_CEIL(*size, sizeof(double)) - *size; } @@ -315,15 +234,17 @@ rte_flow_conv_pattern(struct rte_flow_item *dst, store: for (off = 0, i = 0; !num || i != num; ++i, ++src, ++dst) { + const struct rte_flow_conv_res *res = + &rte_flow_conv_res_item[src->type]; size_t spec; size_t pad; - if ((size_t)src->type >= RTE_DIM(rte_flow_desc_item) || - !rte_flow_desc_item[src->type].name) + if ((size_t)src->type >= RTE_DIM(rte_flow_conv_res_item) || + !res->name) goto notsup; if (store) *dst = (struct rte_flow_item){ .type = src->type, }; - flow_item_spec_size(src, &spec, &pad); + rte_flow_conv_res_size(res, src->spec, &spec, &pad); if (spec) off = RTE_ALIGN_CEIL(off, sizeof(double)); if (src->spec) { @@ -380,15 +301,17 @@ rte_flow_conv_actions(struct rte_flow_action *dst, store: for (off = 0, i = 0; !num || i != num; ++i, ++src, ++dst) { + const struct rte_flow_conv_res *res = + &rte_flow_conv_res_action[src->type]; size_t conf; size_t pad; - if ((size_t)src->type >= RTE_DIM(rte_flow_desc_action) || - !rte_flow_desc_action[src->type].name) + if ((size_t)src->type >= RTE_DIM(rte_flow_conv_res_action) || + !res->name) goto notsup; if (store) *dst = (struct rte_flow_action){ .type = src->type, }; - flow_action_conf_size(src, &conf, &pad); + rte_flow_conv_res_size(res, src->conf, &conf, &pad); if (conf) off = RTE_ALIGN_CEIL(off, sizeof(double)); if (store && conf) @@ -474,11 +397,17 @@ rte_flow_conv_name(int is_action, struct rte_flow_error *error) { const struct { - const struct rte_flow_desc_data *data; + const struct rte_flow_conv_res *data; size_t num; } res_data[2] = { - { rte_flow_desc_item, RTE_DIM(rte_flow_desc_item), }, - { rte_flow_desc_action, RTE_DIM(rte_flow_desc_action), }, + { + rte_flow_conv_res_item, + RTE_DIM(rte_flow_conv_res_item), + }, + { + rte_flow_conv_res_action, + RTE_DIM(rte_flow_conv_res_action), + }, }, *const res = &res_data[!!is_action]; unsigned int obj_type = (uintptr_t)src; @@ -498,11 +427,17 @@ rte_flow_conv_name_ptr(int is_action, struct rte_flow_error *error) { const struct { - const struct rte_flow_desc_data *data; + const struct rte_flow_conv_res *data; size_t num; } res_data[2] = { - { rte_flow_desc_item, RTE_DIM(rte_flow_desc_item), }, - { rte_flow_desc_action, RTE_DIM(rte_flow_desc_action), }, + { + rte_flow_conv_res_item, + RTE_DIM(rte_flow_conv_res_item), + }, + { + rte_flow_conv_res_action, + RTE_DIM(rte_flow_conv_res_action), + }, }, *const res = &res_data[!!is_action]; unsigned int obj_type = (uintptr_t)src; diff --git a/lib/librte_ether/rte_flow_conv.h b/lib/librte_ether/rte_flow_conv.h new file mode 100644 index 0000000..2244970 --- /dev/null +++ b/lib/librte_ether/rte_flow_conv.h @@ -0,0 +1,333 @@ +/*- + * BSD LICENSE + * + * Copyright 2017 6WIND S.A. + * + * 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. + */ + +/** + * @file + * RTE generic flow API (internal) + * + * This file exports resources needed by rte_flow_conv(). + */ + +#ifndef RTE_FLOW_CONV_H_ +#define RTE_FLOW_CONV_H_ + +#include <stddef.h> + +#include "rte_flow.h" + +/** + * This structure describes either a pattern item or an action as well as + * their associated specification or configuration structure. + */ +struct rte_flow_conv_res { + const char *name; /**< Object name. */ + const void *mask; /**< Default mask for structure if relevant. */ + size_t size; /**< Associated structure size. */ + size_t flex_len_type; /**< Length field type for flexible array. */ + size_t flex_len_off; /**< Length field offset for flexible array. */ + size_t flex_elt_size; /**< Flexible array element size. */ + size_t flex_off; /**< Flexible array field offset. */ +}; + +/** Pattern items description table. */ +static const struct rte_flow_conv_res rte_flow_conv_res_item[] = { + [RTE_FLOW_ITEM_TYPE_END] = { + .name = "end", + .size = 0, + .flex_len_type = 0, + .flex_len_off = 0, + .flex_elt_size = 0, + .flex_off = 0, + }, + [RTE_FLOW_ITEM_TYPE_VOID] = { + .name = "void", + .size = 0, + .flex_len_type = 0, + .flex_len_off = 0, + .flex_elt_size = 0, + .flex_off = 0, + }, + [RTE_FLOW_ITEM_TYPE_INVERT] = { + .name = "invert", + .size = 0, + .flex_len_type = 0, + .flex_len_off = 0, + .flex_elt_size = 0, + .flex_off = 0, + }, + [RTE_FLOW_ITEM_TYPE_ANY] = { + .name = "any", + .size = sizeof(struct rte_flow_item_any), + .flex_len_type = 0, + .flex_len_off = 0, + .flex_elt_size = 0, + .flex_off = 0, + }, + [RTE_FLOW_ITEM_TYPE_PF] = { + .name = "pf", + .size = 0, + .flex_len_type = 0, + .flex_len_off = 0, + .flex_elt_size = 0, + .flex_off = 0, + }, + [RTE_FLOW_ITEM_TYPE_VF] = { + .name = "vf", + .size = sizeof(struct rte_flow_item_vf), + .flex_len_type = 0, + .flex_len_off = 0, + .flex_elt_size = 0, + .flex_off = 0, + }, + [RTE_FLOW_ITEM_TYPE_PORT] = { + .name = "port", + .size = sizeof(struct rte_flow_item_port), + .flex_len_type = 0, + .flex_len_off = 0, + .flex_elt_size = 0, + .flex_off = 0, + }, + [RTE_FLOW_ITEM_TYPE_RAW] = { + .name = "raw", + .size = sizeof(struct rte_flow_item_raw), + .flex_len_type = sizeof(((struct rte_flow_item_raw *)0)->length), + .flex_len_off = offsetof(struct rte_flow_item_raw, length), + .flex_elt_size = sizeof(((struct rte_flow_item_raw *)0)->pattern[0]), + .flex_off = offsetof(struct rte_flow_item_raw, pattern), + }, + [RTE_FLOW_ITEM_TYPE_ETH] = { + .name = "eth", + .size = sizeof(struct rte_flow_item_eth), + .flex_len_type = 0, + .flex_len_off = 0, + .flex_elt_size = 0, + .flex_off = 0, + }, + [RTE_FLOW_ITEM_TYPE_VLAN] = { + .name = "vlan", + .size = sizeof(struct rte_flow_item_vlan), + .flex_len_type = 0, + .flex_len_off = 0, + .flex_elt_size = 0, + .flex_off = 0, + }, + [RTE_FLOW_ITEM_TYPE_IPV4] = { + .name = "ipv4", + .size = sizeof(struct rte_flow_item_ipv4), + .flex_len_type = 0, + .flex_len_off = 0, + .flex_elt_size = 0, + .flex_off = 0, + }, + [RTE_FLOW_ITEM_TYPE_IPV6] = { + .name = "ipv6", + .size = sizeof(struct rte_flow_item_ipv6), + .flex_len_type = 0, + .flex_len_off = 0, + .flex_elt_size = 0, + .flex_off = 0, + }, + [RTE_FLOW_ITEM_TYPE_ICMP] = { + .name = "icmp", + .size = sizeof(struct rte_flow_item_icmp), + .flex_len_type = 0, + .flex_len_off = 0, + .flex_elt_size = 0, + .flex_off = 0, + }, + [RTE_FLOW_ITEM_TYPE_UDP] = { + .name = "udp", + .size = sizeof(struct rte_flow_item_udp), + .flex_len_type = 0, + .flex_len_off = 0, + .flex_elt_size = 0, + .flex_off = 0, + }, + [RTE_FLOW_ITEM_TYPE_TCP] = { + .name = "tcp", + .size = sizeof(struct rte_flow_item_tcp), + .flex_len_type = 0, + .flex_len_off = 0, + .flex_elt_size = 0, + .flex_off = 0, + }, + [RTE_FLOW_ITEM_TYPE_SCTP] = { + .name = "sctp", + .size = sizeof(struct rte_flow_item_sctp), + .flex_len_type = 0, + .flex_len_off = 0, + .flex_elt_size = 0, + .flex_off = 0, + }, + [RTE_FLOW_ITEM_TYPE_VXLAN] = { + .name = "vxlan", + .size = sizeof(struct rte_flow_item_vxlan), + .flex_len_type = 0, + .flex_len_off = 0, + .flex_elt_size = 0, + .flex_off = 0, + }, + [RTE_FLOW_ITEM_TYPE_E_TAG] = { + .name = "e_tag", + .size = sizeof(struct rte_flow_item_e_tag), + .flex_len_type = 0, + .flex_len_off = 0, + .flex_elt_size = 0, + .flex_off = 0, + }, + [RTE_FLOW_ITEM_TYPE_NVGRE] = { + .name = "nvgre", + .size = sizeof(struct rte_flow_item_nvgre), + .flex_len_type = 0, + .flex_len_off = 0, + .flex_elt_size = 0, + .flex_off = 0, + }, + [RTE_FLOW_ITEM_TYPE_MPLS] = { + .name = "mpls", + .size = sizeof(struct rte_flow_item_mpls), + .flex_len_type = 0, + .flex_len_off = 0, + .flex_elt_size = 0, + .flex_off = 0, + }, + [RTE_FLOW_ITEM_TYPE_GRE] = { + .name = "gre", + .size = sizeof(struct rte_flow_item_gre), + .flex_len_type = 0, + .flex_len_off = 0, + .flex_elt_size = 0, + .flex_off = 0, + }, +}; + +/** Actions description table. */ +static const struct rte_flow_conv_res rte_flow_conv_res_action[] = { + [RTE_FLOW_ACTION_TYPE_END] = { + .name = "end", + .size = 0, + .flex_len_type = 0, + .flex_len_off = 0, + .flex_elt_size = 0, + .flex_off = 0, + }, + [RTE_FLOW_ACTION_TYPE_VOID] = { + .name = "void", + .size = 0, + .flex_len_type = 0, + .flex_len_off = 0, + .flex_elt_size = 0, + .flex_off = 0, + }, + [RTE_FLOW_ACTION_TYPE_PASSTHRU] = { + .name = "passthru", + .size = 0, + .flex_len_type = 0, + .flex_len_off = 0, + .flex_elt_size = 0, + .flex_off = 0, + }, + [RTE_FLOW_ACTION_TYPE_MARK] = { + .name = "mark", + .size = sizeof(struct rte_flow_action_mark), + .flex_len_type = 0, + .flex_len_off = 0, + .flex_elt_size = 0, + .flex_off = 0, + }, + [RTE_FLOW_ACTION_TYPE_FLAG] = { + .name = "flag", + .size = 0, + .flex_len_type = 0, + .flex_len_off = 0, + .flex_elt_size = 0, + .flex_off = 0, + }, + [RTE_FLOW_ACTION_TYPE_QUEUE] = { + .name = "queue", + .size = sizeof(struct rte_flow_action_queue), + .flex_len_type = 0, + .flex_len_off = 0, + .flex_elt_size = 0, + .flex_off = 0, + }, + [RTE_FLOW_ACTION_TYPE_DROP] = { + .name = "drop", + .size = 0, + .flex_len_type = 0, + .flex_len_off = 0, + .flex_elt_size = 0, + .flex_off = 0, + }, + [RTE_FLOW_ACTION_TYPE_COUNT] = { + .name = "count", + .size = 0, + .flex_len_type = 0, + .flex_len_off = 0, + .flex_elt_size = 0, + .flex_off = 0, + }, + [RTE_FLOW_ACTION_TYPE_DUP] = { + .name = "dup", + .size = sizeof(struct rte_flow_action_dup), + .flex_len_type = 0, + .flex_len_off = 0, + .flex_elt_size = 0, + .flex_off = 0, + }, + [RTE_FLOW_ACTION_TYPE_RSS] = { + .name = "rss", + .size = sizeof(struct rte_flow_action_rss), + .flex_len_type = sizeof(((struct rte_flow_action_rss *)0)->num), + .flex_len_off = offsetof(struct rte_flow_action_rss, num), + .flex_elt_size = sizeof(((struct rte_flow_action_rss *)0)->queue[0]), + .flex_off = offsetof(struct rte_flow_action_rss, queue), + }, + [RTE_FLOW_ACTION_TYPE_PF] = { + .name = "pf", + .size = 0, + .flex_len_type = 0, + .flex_len_off = 0, + .flex_elt_size = 0, + .flex_off = 0, + }, + [RTE_FLOW_ACTION_TYPE_VF] = { + .name = "vf", + .size = sizeof(struct rte_flow_action_vf), + .flex_len_type = 0, + .flex_len_off = 0, + .flex_elt_size = 0, + .flex_off = 0, + }, +}; + +#endif /* RTE_FLOW_CONV_H_ */ -- 2.1.4