* [RFC PATCH 0/3] add feature arc in rte_graph @ 2024-09-07 7:31 Nitin Saxena 2024-09-07 7:31 ` [RFC PATCH 1/3] graph: add feature arc support Nitin Saxena ` (4 more replies) 0 siblings, 5 replies; 46+ messages in thread From: Nitin Saxena @ 2024-09-07 7:31 UTC (permalink / raw) To: Jerin Jacob, Kiran Kumar K, Nithin Dabilpuram, Zhirun Yan Cc: dev, Nitin Saxena Feature arc represents an ordered list of features/protocols at a given networking layer. It is a high level abstraction to connect various rte_graph nodes, as feature nodes, and allow packets steering across these nodes in a generic manner. Features (or feature nodes) are nodes which handles partial or complete handling of a protocol in fast path. Like ipv4-rewrite node, which adds rewrite data to an outgoing IPv4 packet. However in above example, outgoing interface(say "eth0") may have outbound IPsec policy enabled, hence packets must be steered from ipv4-rewrite node to ipsec-outbound-policy node for outbound IPsec policy lookup. On the other hand, packets routed to another interface (eth1) will not be sent to ipsec-outbound-policy node as IPsec feature is disabled on eth1. Feature-arc allows rte_graph applications to manage such constraints easily Feature arc abstraction allows rte_graph based application to 1. Seamlessly steer packets across feature nodes based on wheter feature is enabled or disabled on an interface. Features enabled on one interface may not be enabled on another interface with in a same feature arc. 2. Allow enabling/disabling of features on an interface at runtime, so that if a feature is disabled, packets associated with that interface won't be steered to corresponding feature node. 3. Provides mechanism to hook custom/user-defined nodes to a feature node and allow packet steering from feature node to custom node without changing former's fast path function 4. Allow expressing features in a particular sequential order so that packets are steered in an ordered way across nodes in fast path. For eg: if IPsec and IPv4 features are enabled on an ingress interface, packets must be sent to IPsec inbound policy node first and then to ipv4 lookup node. This patch series adds feature arc library in rte_graph and also adds "ipv4-output" feature arc handling in "ipv4-rewrite" node. Nitin Saxena (3): graph: add feature arc support graph: add feature arc option in graph create graph: add IPv4 output feature arc lib/graph/graph.c | 1 + lib/graph/graph_feature_arc.c | 959 +++++++++++++++++++++++ lib/graph/graph_populate.c | 7 +- lib/graph/graph_private.h | 3 + lib/graph/meson.build | 2 + lib/graph/node.c | 2 + lib/graph/rte_graph.h | 3 + lib/graph/rte_graph_feature_arc.h | 373 +++++++++ lib/graph/rte_graph_feature_arc_worker.h | 548 +++++++++++++ lib/graph/version.map | 17 + lib/node/ip4_rewrite.c | 476 ++++++++--- lib/node/ip4_rewrite_priv.h | 9 +- lib/node/node_private.h | 19 +- lib/node/rte_node_ip4_api.h | 3 + 14 files changed, 2325 insertions(+), 97 deletions(-) create mode 100644 lib/graph/graph_feature_arc.c create mode 100644 lib/graph/rte_graph_feature_arc.h create mode 100644 lib/graph/rte_graph_feature_arc_worker.h -- 2.43.0 ^ permalink raw reply [flat|nested] 46+ messages in thread
* [RFC PATCH 1/3] graph: add feature arc support 2024-09-07 7:31 [RFC PATCH 0/3] add feature arc in rte_graph Nitin Saxena @ 2024-09-07 7:31 ` Nitin Saxena 2024-09-11 4:41 ` Kiran Kumar Kokkilagadda 2024-09-07 7:31 ` [RFC PATCH 2/3] graph: add feature arc option in graph create Nitin Saxena ` (3 subsequent siblings) 4 siblings, 1 reply; 46+ messages in thread From: Nitin Saxena @ 2024-09-07 7:31 UTC (permalink / raw) To: Jerin Jacob, Kiran Kumar K, Nithin Dabilpuram, Zhirun Yan Cc: dev, Nitin Saxena add feature arc to allow dynamic steering of packets across graph nodes based on protocol features enabled on incoming or outgoing interface Signed-off-by: Nitin Saxena <nsaxena@marvell.com> --- lib/graph/graph_feature_arc.c | 959 +++++++++++++++++++++++ lib/graph/meson.build | 2 + lib/graph/rte_graph_feature_arc.h | 373 +++++++++ lib/graph/rte_graph_feature_arc_worker.h | 548 +++++++++++++ lib/graph/version.map | 17 + 5 files changed, 1899 insertions(+) create mode 100644 lib/graph/graph_feature_arc.c create mode 100644 lib/graph/rte_graph_feature_arc.h create mode 100644 lib/graph/rte_graph_feature_arc_worker.h diff --git a/lib/graph/graph_feature_arc.c b/lib/graph/graph_feature_arc.c new file mode 100644 index 0000000000..3b05bac137 --- /dev/null +++ b/lib/graph/graph_feature_arc.c @@ -0,0 +1,959 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(C) 2024 Marvell International Ltd. + */ + +#include "graph_private.h" +#include <rte_graph_feature_arc_worker.h> +#include <rte_malloc.h> + +#define __RTE_GRAPH_FEATURE_ARC_MAX 32 + +#define ARC_PASSIVE_LIST(arc) (arc->active_feature_list ^ 0x1) + +#define rte_graph_uint_cast(x) ((unsigned int)x) +#define feat_dbg graph_err + +rte_graph_feature_arc_main_t *__feature_arc_main; + +/* Make sure fast path cache line is compact */ +_Static_assert((offsetof(struct rte_graph_feature_arc, slow_path_variables) + - offsetof(struct rte_graph_feature_arc, fast_path_variables)) + <= RTE_CACHE_LINE_SIZE); + + +static int +feature_lookup(struct rte_graph_feature_arc *arc, const char *feat_name, + struct rte_graph_feature_node_list **ffinfo, uint32_t *slot) +{ + struct rte_graph_feature_node_list *finfo = NULL; + const char *name; + + if (!feat_name) + return -1; + + if (slot) + *slot = 0; + + STAILQ_FOREACH(finfo, &arc->all_features, next_feature) { + RTE_VERIFY(finfo->feature_arc == arc); + name = rte_node_id_to_name(finfo->feature_node->id); + if (!strncmp(name, feat_name, RTE_GRAPH_NAMESIZE)) { + if (ffinfo) + *ffinfo = finfo; + return 0; + } + if (slot) + (*slot)++; + } + return -1; +} + +static int +feature_arc_node_info_lookup(struct rte_graph_feature_arc *arc, uint32_t feature_index, + struct rte_graph_feature_node_list **ppfinfo) +{ + struct rte_graph_feature_node_list *finfo = NULL; + uint32_t index = 0; + + if (!ppfinfo) + return -1; + + *ppfinfo = NULL; + STAILQ_FOREACH(finfo, &arc->all_features, next_feature) { + if (index == feature_index) { + if (finfo->node_index == feature_index) + return -1; + *ppfinfo = finfo; + } + index++; + } + if (feature_index && (index >= feature_index)) + return -1; + + return 0; +} + +static void +prepare_feature_arc(struct rte_graph_feature_arc *arc) +{ + struct rte_graph_feature_node_list *finfo = NULL; + uint32_t index = 0; + + STAILQ_FOREACH(finfo, &arc->all_features, next_feature) { + finfo->node_index = index; + index++; + } +} + +static int +feature_arc_lookup(rte_graph_feature_arc_t _arc) +{ + struct rte_graph_feature_arc *arc = rte_graph_feature_arc_get(_arc); + rte_graph_feature_arc_main_t *dm = __feature_arc_main; + uint32_t iter; + + if (!__feature_arc_main) + return -1; + + for (iter = 0; iter < dm->max_feature_arcs; iter++) { + if (dm->feature_arcs[iter] == RTE_GRAPH_FEATURE_ARC_INITIALIZER) + continue; + + if (arc == (rte_graph_feature_arc_get(dm->feature_arcs[iter]))) + return 0; + } + return -1; +} + +static int +get_existing_edge(const char *arc_name, struct rte_node_register *parent_node, + struct rte_node_register *child_node, rte_edge_t *_edge) +{ + char **next_edges = NULL; + uint32_t count, i; + + RTE_SET_USED(arc_name); + + count = rte_node_edge_get(parent_node->id, NULL); + next_edges = malloc(count); + + if (!next_edges) + return -1; + + count = rte_node_edge_get(parent_node->id, next_edges); + for (i = 0; i < count; i++) { + if (strstr(child_node->name, next_edges[i])) { + feat_dbg("%s: Edge exists [%s[%u]: \"%s\"]", arc_name, + parent_node->name, i, child_node->name); + if (_edge) + *_edge = (rte_edge_t)i; + + free(next_edges); + return 0; + } + } + free(next_edges); + + return -1; +} + +static int +connect_graph_nodes(struct rte_node_register *parent_node, struct rte_node_register *child_node, + rte_edge_t *_edge, char *arc_name) +{ + const char *next_node = NULL; + rte_edge_t edge; + + if (!get_existing_edge(arc_name, parent_node, child_node, &edge)) { + feat_dbg("%s: add_feature: Edge reused [%s[%u]: \"%s\"]", arc_name, + parent_node->name, edge, child_node->name); + + if (_edge) + *_edge = edge; + + return 0; + } + + /* Node to be added */ + next_node = child_node->name; + + edge = rte_node_edge_update(parent_node->id, RTE_EDGE_ID_INVALID, &next_node, 1); + + if (edge == RTE_EDGE_ID_INVALID) { + graph_err("edge invalid"); + return -1; + } + edge = rte_node_edge_count(parent_node->id) - 1; + + feat_dbg("%s: add_feature: edge added [%s[%u]: \"%s\"]", arc_name, parent_node->name, edge, + child_node->name); + + if (_edge) + *_edge = edge; + + return 0; +} + +static int +feature_arc_init(rte_graph_feature_arc_main_t **pfl, uint32_t max_feature_arcs) +{ + rte_graph_feature_arc_main_t *pm = NULL; + uint32_t i; + size_t sz; + + if (!pfl) + return -1; + + sz = sizeof(rte_graph_feature_arc_main_t) + + (sizeof(pm->feature_arcs[0]) * max_feature_arcs); + + pm = malloc(sz); + if (!pm) + return -1; + + memset(pm, 0, sz); + + for (i = 0; i < max_feature_arcs; i++) + pm->feature_arcs[i] = RTE_GRAPH_FEATURE_ARC_INITIALIZER; + + pm->max_feature_arcs = max_feature_arcs; + + *pfl = pm; + + return 0; +} + +int +rte_graph_feature_arc_init(int max_feature_arcs) +{ + if (!max_feature_arcs) + return -1; + + if (__feature_arc_main) + return -1; + + return feature_arc_init(&__feature_arc_main, max_feature_arcs); +} + +static void +feature_arc_list_reset(struct rte_graph_feature_arc *arc, uint32_t list_index) +{ + rte_graph_feature_data_t *fdata = NULL; + rte_graph_feature_list_t *list = NULL; + struct rte_graph_feature *feat = NULL; + uint32_t i, j; + + list = arc->feature_list[list_index]; + feat = arc->features[list_index]; + + /*Initialize variables*/ + memset(feat, 0, arc->feature_size); + memset(list, 0, arc->feature_list_size); + + /* Initialize feature and feature_data */ + for (i = 0; i < arc->max_features; i++) { + feat = __rte_graph_feature_get(arc, i, list_index); + feat->this_feature_index = i; + + for (j = 0; j < arc->max_indexes; j++) { + fdata = rte_graph_feature_data_get(arc, feat, j); + fdata->next_enabled_feature = RTE_GRAPH_FEATURE_INVALID; + fdata->next_edge = UINT16_MAX; + fdata->user_data = UINT32_MAX; + } + } + + for (i = 0; i < arc->max_indexes; i++) + list->first_enabled_feature_by_index[i] = RTE_GRAPH_FEATURE_INVALID; +} + +static int +feature_arc_list_init(struct rte_graph_feature_arc *arc, const char *flist_name, + rte_graph_feature_list_t **pplist, + struct rte_graph_feature **ppfeature, uint32_t list_index) +{ + char fname[2 * RTE_GRAPH_FEATURE_ARC_NAMELEN]; + size_t list_size, feat_size, fdata_size; + rte_graph_feature_list_t *list = NULL; + struct rte_graph_feature *feat = NULL; + + list_size = sizeof(list->first_enabled_feature_by_index[0]) * arc->max_indexes; + + list = rte_malloc(flist_name, list_size, RTE_CACHE_LINE_SIZE); + if (!list) + return -ENOMEM; + + fdata_size = arc->max_indexes * sizeof(rte_graph_feature_data_t); + + /* Let one feature capture complete cache lines */ + feat_size = RTE_ALIGN_CEIL(sizeof(struct rte_graph_feature) + fdata_size, + RTE_CACHE_LINE_SIZE); + + snprintf(fname, sizeof(fname), "%s-%s", arc->feature_arc_name, "feat"); + + feat = rte_malloc(fname, feat_size * arc->max_features, RTE_CACHE_LINE_SIZE); + if (!feat) { + rte_free(list); + return -ENOMEM; + } + arc->feature_size = feat_size; + arc->feature_data_size = fdata_size; + arc->feature_list_size = list_size; + + /* Initialize list */ + list->indexed_by_features = feat; + *pplist = list; + *ppfeature = feat; + + feature_arc_list_reset(arc, list_index); + + return 0; +} + +static void +feature_arc_list_destroy(rte_graph_feature_list_t *list) +{ + rte_free(list->indexed_by_features); + rte_free(list); +} + +int +rte_graph_feature_arc_create(const char *feature_arc_name, int max_features, int max_indexes, + struct rte_node_register *start_node, rte_graph_feature_arc_t *_arc) +{ + char name[2 * RTE_GRAPH_FEATURE_ARC_NAMELEN]; + rte_graph_feature_arc_main_t *dfm = NULL; + struct rte_graph_feature_arc *arc = NULL; + struct rte_graph_feature_data *gfd = NULL; + struct rte_graph_feature *df = NULL; + uint32_t iter, j, arc_index; + size_t sz; + + if (!_arc) + return -1; + + if (max_features < 2) + return -1; + + if (!start_node) + return -1; + + if (!feature_arc_name) + return -1; + + if (max_features > RTE_GRAPH_FEATURE_MAX_PER_ARC) { + graph_err("Invalid max features: %u", max_features); + return -1; + } + + /* + * Application hasn't called rte_graph_feature_arc_init(). Initialize with + * default values + */ + if (!__feature_arc_main) { + if (rte_graph_feature_arc_init((int)__RTE_GRAPH_FEATURE_ARC_MAX) < 0) { + graph_err("rte_graph_feature_arc_init() failed"); + return -1; + } + } + + dfm = __feature_arc_main; + + /* threshold check */ + if (dfm->num_feature_arcs > (dfm->max_feature_arcs - 1)) { + graph_err("max threshold for num_feature_arcs: %d reached", + dfm->max_feature_arcs - 1); + return -1; + } + /* Find the free slot for feature arc */ + for (iter = 0; iter < dfm->max_feature_arcs; iter++) { + if (dfm->feature_arcs[iter] == RTE_GRAPH_FEATURE_ARC_INITIALIZER) + break; + } + arc_index = iter; + + if (arc_index >= dfm->max_feature_arcs) { + graph_err("No free slot found for num_feature_arc"); + return -1; + } + + /* This should not happen */ + RTE_VERIFY(dfm->feature_arcs[arc_index] == RTE_GRAPH_FEATURE_ARC_INITIALIZER); + + /* size of feature arc + feature_bit_mask_by_index */ + sz = sizeof(*arc) + (sizeof(uint64_t) * max_indexes); + + arc = rte_malloc(feature_arc_name, sz, RTE_CACHE_LINE_SIZE); + + if (!arc) { + graph_err("malloc failed for feature_arc_create()"); + return -1; + } + + memset(arc, 0, sz); + + /* Initialize rte_graph port group fixed variables */ + STAILQ_INIT(&arc->all_features); + strncpy(arc->feature_arc_name, feature_arc_name, RTE_GRAPH_FEATURE_ARC_NAMELEN - 1); + arc->feature_arc_main = (void *)dfm; + arc->start_node = start_node; + arc->max_features = max_features; + arc->max_indexes = max_indexes; + + snprintf(name, sizeof(name), "%s-%s", feature_arc_name, "flist0"); + + if (feature_arc_list_init(arc, name, &arc->feature_list[0], &arc->features[0], 0) < 0) { + rte_free(arc); + graph_err("feature_arc_list_init(0) failed"); + return -1; + } + snprintf(name, sizeof(name), "%s-%s", feature_arc_name, "flist1"); + + if (feature_arc_list_init(arc, name, &arc->feature_list[1], &arc->features[1], 1) < 0) { + feature_arc_list_destroy(arc->feature_list[0]); + graph_err("feature_arc_list_init(1) failed"); + return -1; + } + + for (iter = 0; iter < arc->max_features; iter++) { + df = rte_graph_feature_get(arc, iter); + for (j = 0; j < arc->max_indexes; j++) { + gfd = rte_graph_feature_data_get(arc, df, j); + gfd->next_enabled_feature = RTE_GRAPH_FEATURE_INVALID; + } + } + arc->feature_arc_index = arc_index; + dfm->feature_arcs[arc->feature_arc_index] = (rte_graph_feature_arc_t)arc; + dfm->num_feature_arcs++; + + if (_arc) + *_arc = (rte_graph_feature_arc_t)arc; + + return 0; +} + +int +rte_graph_feature_add(rte_graph_feature_arc_t _arc, struct rte_node_register *feature_node, + const char *after_feature, const char *before_feature) +{ + struct rte_graph_feature_node_list *after_finfo = NULL, *before_finfo = NULL; + struct rte_graph_feature_node_list *temp = NULL, *finfo = NULL; + struct rte_graph_feature_arc *arc = rte_graph_feature_arc_get(_arc); + uint32_t slot, add_flag; + rte_edge_t edge = -1; + + RTE_VERIFY(arc->feature_arc_main == __feature_arc_main); + + if (feature_arc_lookup(_arc)) { + graph_err("invalid feature arc: 0x%016" PRIx64, (uint64_t)_arc); + return -1; + } + + if (arc->runtime_enabled_features) { + graph_err("adding features after enabling any one of them is not supported"); + return -1; + } + + if ((after_feature != NULL) && (before_feature != NULL) && + (after_feature == before_feature)) { + graph_err("after_feature and before_feature are same '%s:%s]", after_feature, + before_feature); + return -1; + } + + if (!feature_node) { + graph_err("feature_node: %p invalid", feature_node); + return -1; + } + + arc = rte_graph_feature_arc_get(_arc); + + if (feature_node->id == RTE_NODE_ID_INVALID) { + graph_err("Invalid node: %s", feature_node->name); + return -1; + } + + if (!feature_lookup(arc, feature_node->name, &finfo, &slot)) { + graph_err("%s feature already added", feature_node->name); + return -1; + } + + if (slot >= RTE_GRAPH_FEATURE_MAX_PER_ARC) { + graph_err("Max slot %u reached for feature addition", slot); + return -1; + } + + if (strstr(feature_node->name, arc->start_node->name)) { + graph_err("Feature %s cannot point to itself: %s", feature_node->name, + arc->start_node->name); + return -1; + } + + if (connect_graph_nodes(arc->start_node, feature_node, &edge, arc->feature_arc_name)) { + graph_err("unable to connect %s -> %s", arc->start_node->name, feature_node->name); + return -1; + } + + finfo = malloc(sizeof(*finfo)); + if (!finfo) + return -1; + + memset(finfo, 0, sizeof(*finfo)); + + finfo->feature_arc = (void *)arc; + finfo->feature_node = feature_node; + finfo->edge_to_this_feature = edge; + + /* Check for before and after constraints */ + if (before_feature) { + /* before_feature sanity */ + if (feature_lookup(arc, before_feature, &before_finfo, NULL)) + SET_ERR_JMP(EINVAL, finfo_free, + "Invalid before feature name: %s", before_feature); + + if (!before_finfo) + SET_ERR_JMP(EINVAL, finfo_free, + "before_feature %s does not exist", before_feature); + + /* + * Starting from 0 to before_feature, continue connecting edges + */ + add_flag = 1; + STAILQ_FOREACH(temp, &arc->all_features, next_feature) { + /* + * As soon as we see before_feature. stop adding edges + */ + if (!strncmp(temp->feature_node->name, before_feature, + RTE_GRAPH_NAMESIZE)) + if (!connect_graph_nodes(finfo->feature_node, temp->feature_node, + &edge, arc->feature_arc_name)) + add_flag = 0; + + if (add_flag) + connect_graph_nodes(temp->feature_node, finfo->feature_node, NULL, + arc->feature_arc_name); + } + } + + if (after_feature) { + if (feature_lookup(arc, after_feature, &after_finfo, NULL)) + SET_ERR_JMP(EINVAL, finfo_free, + "Invalid after feature_name %s", after_feature); + + if (!after_finfo) + SET_ERR_JMP(EINVAL, finfo_free, + "after_feature %s does not exist", after_feature); + + /* Starting from after_feature to end continue connecting edges */ + add_flag = 0; + STAILQ_FOREACH(temp, &arc->all_features, next_feature) { + /* We have already seen after_feature now */ + if (add_flag) + /* Add all features as next node to current feature*/ + connect_graph_nodes(finfo->feature_node, temp->feature_node, NULL, + arc->feature_arc_name); + + /* as soon as we see after_feature. start adding edges + * from next iteration + */ + if (!strncmp(temp->feature_node->name, after_feature, RTE_GRAPH_NAMESIZE)) + /* connect after_feature to this feature */ + if (!connect_graph_nodes(temp->feature_node, finfo->feature_node, + &edge, arc->feature_arc_name)) + add_flag = 1; + } + + /* add feature next to after_feature */ + STAILQ_INSERT_AFTER(&arc->all_features, after_finfo, finfo, next_feature); + } else { + if (before_finfo) { + after_finfo = NULL; + STAILQ_FOREACH(temp, &arc->all_features, next_feature) { + if (before_finfo == temp) { + if (after_finfo) + STAILQ_INSERT_AFTER(&arc->all_features, after_finfo, + finfo, next_feature); + else + STAILQ_INSERT_HEAD(&arc->all_features, finfo, + next_feature); + + return 0; + } + after_finfo = temp; + } + } else { + STAILQ_INSERT_TAIL(&arc->all_features, finfo, next_feature); + } + } + + return 0; + +finfo_free: + free(finfo); + + return -1; +} + +int +rte_graph_feature_lookup(rte_graph_feature_arc_t _arc, const char *feature_name, + rte_graph_feature_t *feat) +{ + struct rte_graph_feature_arc *arc = rte_graph_feature_arc_get(_arc); + struct rte_graph_feature_node_list *finfo = NULL; + uint32_t slot; + + if (!feature_lookup(arc, feature_name, &finfo, &slot)) { + *feat = (rte_graph_feature_t) slot; + return 0; + } + + return -1; +} + +int +rte_graph_feature_validate(rte_graph_feature_arc_t _arc, uint32_t index, const char *feature_name, + int is_enable_disable) +{ + struct rte_graph_feature_arc *arc = rte_graph_feature_arc_get(_arc); + struct rte_graph_feature_node_list *finfo = NULL; + struct rte_graph_feature *gf = NULL; + uint32_t slot; + + /* validate _arc */ + if (arc->feature_arc_main != __feature_arc_main) { + graph_err("invalid feature arc: 0x%016" PRIx64, (uint64_t)_arc); + return -EINVAL; + } + + /* validate index */ + if (index >= arc->max_indexes) { + graph_err("%s: Invalid provided index: %u >= %u configured", arc->feature_arc_name, + index, arc->max_indexes); + return -1; + } + + /* validate feature_name is already added or not */ + if (feature_lookup(arc, feature_name, &finfo, &slot)) { + graph_err("%s: No feature %s added", arc->feature_arc_name, feature_name); + return -EINVAL; + } + + if (!finfo) { + graph_err("%s: No feature: %s found", arc->feature_arc_name, feature_name); + return -EINVAL; + } + + /* slot should be in valid range */ + if (slot >= arc->max_features) { + graph_err("%s/%s: Invalid free slot %u(max=%u) for feature", arc->feature_arc_name, + feature_name, slot, arc->max_features); + return -EINVAL; + } + + /* slot should be in range of 0 - 63 */ + if (slot > (RTE_GRAPH_FEATURE_MAX_PER_ARC - 1)) { + graph_err("%s/%s: Invalid slot: %u", arc->feature_arc_name, + feature_name, slot); + return -EINVAL; + } + + if (finfo->node_index != slot) { + graph_err("%s/%s: feature lookup slot mismatch with finfo index: %u and lookup slot: %u", + arc->feature_arc_name, feature_name, finfo->node_index, slot); + return -1; + } + + /* Get feature from active list */ + gf = __rte_graph_feature_get(arc, slot, ARC_PASSIVE_LIST(arc)); + if (gf->this_feature_index != slot) { + graph_err("%s: %s received feature_index: %u does not match with saved feature_index: %u", + arc->feature_arc_name, feature_name, slot, gf->this_feature_index); + return -1; + } + + if (is_enable_disable && (arc->feature_bit_mask_by_index[index] & + RTE_BIT64(slot))) { + graph_err("%s: %s already enabled on index: %u", + arc->feature_arc_name, feature_name, index); + return -1; + } + + if (!is_enable_disable && !arc->runtime_enabled_features) { + graph_err("%s: No feature enabled to disable", arc->feature_arc_name); + return -1; + } + + if (!is_enable_disable && !(arc->feature_bit_mask_by_index[index] & RTE_BIT64(slot))) { + graph_err("%s: %s not enabled in bitmask for index: %u", + arc->feature_arc_name, feature_name, index); + return -1; + } + + return 0; +} + +static void +copy_fastpath_user_data(struct rte_graph_feature_arc *arc, uint16_t dest_list_index, + uint16_t src_list_index) +{ + rte_graph_feature_data_t *sgfd = NULL, *dgfd = NULL; + struct rte_graph_feature *sgf = NULL, *dgf = NULL; + uint32_t i, j; + + for (i = 0; i < arc->max_features; i++) { + sgf = __rte_graph_feature_get(arc, i, src_list_index); + dgf = __rte_graph_feature_get(arc, i, dest_list_index); + for (j = 0; j < arc->max_indexes; j++) { + sgfd = rte_graph_feature_data_get(arc, sgf, j); + dgfd = rte_graph_feature_data_get(arc, dgf, j); + dgfd->user_data = sgfd->user_data; + } + } +} + +static void +refill_feature_fastpath_data(struct rte_graph_feature_arc *arc, uint16_t list_index) +{ + struct rte_graph_feature_node_list *finfo = NULL, *prev_finfo = NULL; + struct rte_graph_feature_data *gfd = NULL, *prev_gfd = NULL; + struct rte_graph_feature *gf = NULL, *prev_gf = NULL; + rte_graph_feature_list_t *flist = NULL; + uint32_t fi, di, prev_fi; + uint64_t bitmask; + rte_edge_t edge; + + flist = arc->feature_list[list_index]; + + for (di = 0; di < arc->max_indexes; di++) { + bitmask = arc->feature_bit_mask_by_index[di]; + prev_fi = RTE_GRAPH_FEATURE_INVALID; + /* for each feature set for index, set fast path data */ + while (rte_bsf64_safe(bitmask, &fi)) { + gf = __rte_graph_feature_get(arc, fi, list_index); + gfd = rte_graph_feature_data_get(arc, gf, di); + feature_arc_node_info_lookup(arc, fi, &finfo); + + /* If previous feature_index was valid in last loop */ + if (prev_fi != RTE_GRAPH_FEATURE_INVALID) { + prev_gf = __rte_graph_feature_get(arc, prev_fi, list_index); + prev_gfd = rte_graph_feature_data_get(arc, prev_gf, di); + /* + * Get edge of previous feature node connecting to this feature node + */ + feature_arc_node_info_lookup(arc, prev_fi, &prev_finfo); + if (!get_existing_edge(arc->feature_arc_name, + prev_finfo->feature_node, + finfo->feature_node, &edge)) { + feat_dbg("[%s/%s(%2u)/idx:%2u]: %s[%u] = %s", + arc->feature_arc_name, + prev_finfo->feature_node->name, prev_fi, di, + prev_finfo->feature_node->name, + edge, finfo->feature_node->name); + /* Copy feature index for next iteration*/ + gfd->next_edge = edge; + prev_fi = fi; + /* + * Fill current feature as next enabled + * feature to previous one + */ + prev_gfd->next_enabled_feature = fi; + } else { + /* Should not fail */ + RTE_VERIFY(0); + } + } + /* On first feature edge of the node to be added */ + if (fi == rte_bsf64(arc->feature_bit_mask_by_index[di])) { + if (!get_existing_edge(arc->feature_arc_name, arc->start_node, + finfo->feature_node, + &edge)) { + feat_dbg("[%s/%s/%2u/idx:%2u]: 1st feat %s[%u] = %s", + arc->feature_arc_name, + arc->start_node->name, fi, di, + arc->start_node->name, edge, + finfo->feature_node->name); + /* Copy feature index for next iteration*/ + gfd->next_edge = edge; + prev_fi = fi; + /* Set first feature set array for index*/ + flist->first_enabled_feature_by_index[di] = fi; + } else { + /* Should not fail */ + RTE_VERIFY(0); + } + } + /* Clear current feature index */ + bitmask &= ~RTE_BIT64(fi); + } + } +} + +int +rte_graph_feature_enable(rte_graph_feature_arc_t _arc, uint32_t index, const + char *feature_name, int32_t user_data) +{ + struct rte_graph_feature_arc *arc = rte_graph_feature_arc_get(_arc); + struct rte_graph_feature_node_list *finfo = NULL; + struct rte_graph_feature_data *gfd = NULL; + rte_graph_feature_rt_list_t passive_list; + struct rte_graph_feature *gf = NULL; + uint64_t fp_bitmask; + uint32_t slot; + + if (rte_graph_feature_validate(_arc, index, feature_name, 1)) + return -1; + + /** This should not fail as validate() has passed */ + if (feature_lookup(arc, feature_name, &finfo, &slot)) + RTE_VERIFY(0); + + if (!arc->runtime_enabled_features) + prepare_feature_arc(arc); + + passive_list = ARC_PASSIVE_LIST(arc); + + gf = __rte_graph_feature_get(arc, slot, passive_list); + gfd = rte_graph_feature_data_get(arc, gf, index); + + feat_dbg("%s/%s: Enabling feature on list: %u for index: %u at feature slot %u", + arc->feature_arc_name, feature_name, passive_list, index, slot); + + /* Reset feature list */ + feature_arc_list_reset(arc, passive_list); + + /* Copy user-data */ + copy_fastpath_user_data(arc, passive_list, arc->active_feature_list); + + /* Set current user-data */ + gfd->user_data = user_data; + + /* Set bitmask in control path bitmask */ + rte_bit_relaxed_set64(rte_graph_uint_cast(slot), &arc->feature_bit_mask_by_index[index]); + refill_feature_fastpath_data(arc, passive_list); + + /* Set fast path enable bitmask */ + fp_bitmask = __atomic_load_n(&arc->feature_enable_bitmask[passive_list], __ATOMIC_RELAXED); + fp_bitmask |= RTE_BIT64(slot); + __atomic_store(&arc->feature_enable_bitmask[passive_list], &fp_bitmask, __ATOMIC_RELAXED); + + /* Slow path updates */ + arc->runtime_enabled_features++; + + /* Increase feature node info reference count */ + finfo->ref_count++; + + /* Store release semantics for active_list update */ + __atomic_store(&arc->active_feature_list, &passive_list, __ATOMIC_RELEASE); + + return 0; +} + +int +rte_graph_feature_disable(rte_graph_feature_arc_t _arc, uint32_t index, const char *feature_name) +{ + struct rte_graph_feature_arc *arc = rte_graph_feature_arc_get(_arc); + struct rte_graph_feature_data *gfd = NULL; + struct rte_graph_feature_node_list *finfo = NULL; + rte_graph_feature_rt_list_t passive_list; + struct rte_graph_feature *gf = NULL; + uint32_t slot; + + if (rte_graph_feature_validate(_arc, index, feature_name, 0)) + return -1; + + if (feature_lookup(arc, feature_name, &finfo, &slot)) + return -1; + + passive_list = ARC_PASSIVE_LIST(arc); + + gf = __rte_graph_feature_get(arc, slot, passive_list); + gfd = rte_graph_feature_data_get(arc, gf, index); + + feat_dbg("%s/%s: Disabling feature for index: %u at feature slot %u", arc->feature_arc_name, + feature_name, index, slot); + + rte_bit_relaxed_clear64(rte_graph_uint_cast(slot), &arc->feature_bit_mask_by_index[index]); + + /* Set fast path enable bitmask */ + arc->feature_enable_bitmask[passive_list] &= ~(RTE_BIT64(slot)); + + /* Reset feature list */ + feature_arc_list_reset(arc, passive_list); + + /* Copy user-data */ + copy_fastpath_user_data(arc, passive_list, arc->active_feature_list); + + /* Reset current user-data */ + gfd->user_data = ~0; + + refill_feature_fastpath_data(arc, passive_list); + + finfo->ref_count--; + arc->runtime_enabled_features--; + + /* Store release semantics for active_list update */ + __atomic_store(&arc->active_feature_list, &passive_list, __ATOMIC_RELEASE); + + return 0; +} + +int +rte_graph_feature_arc_destroy(rte_graph_feature_arc_t _arc) +{ + struct rte_graph_feature_arc *arc = rte_graph_feature_arc_get(_arc); + rte_graph_feature_arc_main_t *dm = __feature_arc_main; + struct rte_graph_feature_node_list *node_info = NULL; + + while (!STAILQ_EMPTY(&arc->all_features)) { + node_info = STAILQ_FIRST(&arc->all_features); + STAILQ_REMOVE_HEAD(&arc->all_features, next_feature); + free(node_info); + } + feature_arc_list_destroy(arc->feature_list[0]); + feature_arc_list_destroy(arc->feature_list[1]); + rte_free(arc->features[0]); + rte_free(arc->features[1]); + + dm->feature_arcs[arc->feature_arc_index] = RTE_GRAPH_FEATURE_ARC_INITIALIZER; + + rte_free(arc); + return 0; +} + +int +rte_graph_feature_arc_cleanup(void) +{ + rte_graph_feature_arc_main_t *dm = __feature_arc_main; + uint32_t iter; + + if (!__feature_arc_main) + return -1; + + for (iter = 0; iter < dm->max_feature_arcs; iter++) { + if (dm->feature_arcs[iter] == RTE_GRAPH_FEATURE_ARC_INITIALIZER) + continue; + + rte_graph_feature_arc_destroy((rte_graph_feature_arc_t)dm->feature_arcs[iter]); + } + free(dm); + + __feature_arc_main = NULL; + + return 0; +} + +int +rte_graph_feature_arc_lookup_by_name(const char *arc_name, rte_graph_feature_arc_t *_arc) +{ + rte_graph_feature_arc_main_t *dm = __feature_arc_main; + struct rte_graph_feature_arc *arc = NULL; + uint32_t iter; + + if (!__feature_arc_main) + return -1; + + for (iter = 0; iter < dm->max_feature_arcs; iter++) { + if (dm->feature_arcs[iter] == RTE_GRAPH_FEATURE_ARC_INITIALIZER) + continue; + + arc = rte_graph_feature_arc_get(dm->feature_arcs[iter]); + + if (strstr(arc_name, arc->feature_arc_name)) { + if (_arc) + *_arc = (rte_graph_feature_arc_t)arc; + return 0; + } + } + + return -1; +} + +int +rte_graph_feature_arc_num_enabled_features(rte_graph_feature_arc_t _arc) +{ + struct rte_graph_feature_arc *arc = rte_graph_feature_arc_get(_arc); + + return arc->runtime_enabled_features; +} + + diff --git a/lib/graph/meson.build b/lib/graph/meson.build index 0cb15442ab..d916176fb7 100644 --- a/lib/graph/meson.build +++ b/lib/graph/meson.build @@ -14,11 +14,13 @@ sources = files( 'graph_debug.c', 'graph_stats.c', 'graph_populate.c', + 'graph_feature_arc.c', 'graph_pcap.c', 'rte_graph_worker.c', 'rte_graph_model_mcore_dispatch.c', ) headers = files('rte_graph.h', 'rte_graph_worker.h') +headers += files('rte_graph_feature_arc.h', 'rte_graph_feature_arc_worker.h') indirect_headers += files( 'rte_graph_model_mcore_dispatch.h', 'rte_graph_model_rtc.h', diff --git a/lib/graph/rte_graph_feature_arc.h b/lib/graph/rte_graph_feature_arc.h new file mode 100644 index 0000000000..e3bf4eb73d --- /dev/null +++ b/lib/graph/rte_graph_feature_arc.h @@ -0,0 +1,373 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(C) 2024 Marvell International Ltd. + */ + +#ifndef _RTE_GRAPH_FEATURE_ARC_H_ +#define _RTE_GRAPH_FEATURE_ARC_H_ + +#include <assert.h> +#include <errno.h> +#include <signal.h> +#include <stddef.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <rte_common.h> +#include <rte_compat.h> +#include <rte_debug.h> +#include <rte_graph.h> +#include <rte_graph_worker.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @file + * + * rte_graph_feature_arc.h + * + * Define APIs and structures/variables with respect to feature arc + * + * - Feature arc(s) + * - Feature(s) + * + * A feature arc represents an ordered list of features/protocol-nodes at a + * given networking layer. Feature arc provides a high level abstraction to + * connect various *rte_graph* nodes, designated as *feature nodes*, and + * allowing steering of packets across these feature nodes fast path processing + * in a generic manner. In a typical network stack, often a protocol or feature + * must be first enabled on a given interface, before any packet is steered + * towards it for feature processing. For eg: incoming IPv4 packets are sent to + * routing sub-system only after a valid IPv4 address is assigned to the + * received interface. In other words, often packets needs to be steered across + * features not based on the packet content but based on whether a feature is + * enable or disable on a given incoming/outgoing interface. Feature arc + * provides mechanism to enable/disable feature(s) on each interface at runtime + * and allow seamless packet steering across runtime enabled feature nodes in + * fast path. + * + * Feature arc also provides a way to steer packets from standard nodes to + * custom/user-defined *feature nodes* without any change in standard node's + * fast path functions + * + * On a given interface multiple feature(s) might be enabled in a particular + * feature arc. For instance, both "ipv4-output" and "IPsec policy output" + * features may be enabled on "eth0" interface in "L3-output" feature arc. + * Similarly, "ipv6-output" and "ipsec-output" may be enabled on "eth1" + * interface in same "L3-output" feature arc. + * + * When multiple features are present in a given feature arc, its imperative + * to allow each feature processing in a particular sequential order. For + * instance, in "L3-input" feature arc it may be required to run "IPsec + * input" feature first, for packet decryption, before "ip-lookup". So a + * sequential order must be maintained among features present in a feature arc. + * + * Features are enabled/disabled multiple times at runtime to some or all + * available interfaces present in the system. Features can be enabled/disabled + * even after @b rte_graph_create() is called. Enable/disabling features on one + * interface is independent of other interface. + * + * A given feature might consume packet (if it's configured to consume) or may + * forward it to next enabled feature. For instance, "IPsec input" feature may + * consume/drop all packets with "Protect" policy action while all packets with + * policy action as "Bypass" may be forwarded to next enabled feature (with in + * same feature arc) + * + * This library facilitates rte graph based applications to steer packets in + * fast path to different feature nodes with-in a feature arc and support all + * functionalities described above + * + * In order to use feature-arc APIs, applications needs to do following in + * control path: + * - Initialize feature arc library via rte_graph_feature_arc_init() + * - Create feature arc via rte_graph_feature_arc_create() + * - *Before calling rte_graph_create()*, features must be added to feature-arc + * via rte_graph_feature_add(). rte_graph_feature_add() allows adding + * features in a sequential order with "runs_after" and "runs_before" + * constraints. + * - Post rte_graph_create(), features can be enabled/disabled at runtime on + * any interface via rte_graph_feature_enable()/rte_graph_feature_disable() + * - Feature arc can be destroyed via rte_graph_feature_arc_destroy() + * + * In fast path, APIs are provided to steer packets towards feature path from + * - start_node (provided as an argument to rte_graph_feature_arc_create()) + * - feature nodes (which are added via rte_graph_feature_add()) + * + * For typical steering of packets across feature nodes, application required + * to know "rte_edges" which are saved in feature data object. Feature data + * object is unique for every interface per feature with in a feature arc. + * + * When steering packets from start_node to feature node: + * - rte_graph_feature_arc_first_feature_get() provides first enabled feature. + * - Next rte_edge from start_node to first enabled feature can be obtained via + * rte_graph_feature_arc_feature_set() + * + * rte_mbuf can carry [current feature, index] from start_node of an arc to other + * feature nodes + * + * In feature node, application can get 32-bit user_data + * via_rte_graph_feature_user_data_get() which is provided in + * rte_graph_feature_enable(). User data can hold feature specific cookie like + * IPsec policy database index (if more than one are supported) + * + * If feature node is not consuming packet, next enabled feature and next + * rte_edge can be obtained via rte_graph_feature_arc_next_feature_get() + * + * It is application responsibility to ensure that at-least *last feature*(or sink + * feature) must be enabled from where packet can exit feature-arc path, if + * *NO* intermediate feature is consuming the packet and it has reached till + * the end of feature arc path + * + * Synchronization among cores + * --------------------------- + * Subsequent calls to rte_graph_feature_enable() is allowed while worker cores + * are processing in rte_graph_walk() loop. However, for + * rte_graph_feature_disable() application must use RCU based synchronization + */ + +/**< Initializer value for rte_graph_feature_arc_t */ +#define RTE_GRAPH_FEATURE_ARC_INITIALIZER ((rte_graph_feature_arc_t)UINT64_MAX) + +/** Max number of features supported in a given feature arc */ +#define RTE_GRAPH_FEATURE_MAX_PER_ARC 64 + +/** Length of feature arc name */ +#define RTE_GRAPH_FEATURE_ARC_NAMELEN RTE_NODE_NAMESIZE + +/** @internal */ +#define rte_graph_feature_cast(x) ((rte_graph_feature_t)x) + +/**< Initializer value for rte_graph_feature_arc_t */ +#define RTE_GRAPH_FEATURE_INVALID rte_graph_feature_cast(UINT8_MAX) + +/** rte_graph feature arc object */ +typedef uint64_t rte_graph_feature_arc_t; + +/** rte_graph feature object */ +typedef uint8_t rte_graph_feature_t; + +/** runtime active feature list index with in feature arc*/ +typedef uint8_t rte_graph_feature_rt_list_t; + +/** per feature arc monotonically increasing counter to synchronize fast path APIs */ +typedef uint16_t rte_graph_feature_counter_t; + +/** + * Initialize feature arc subsystem + * + * @param max_feature_arcs + * Maximum number of feature arcs required to be supported + * + * @return + * 0: Success + * <0: Failure + */ +__rte_experimental +int rte_graph_feature_arc_init(int max_feature_arcs); + +/** + * Create a feature arc + * + * @param feature_arc_name + * Feature arc name with max length of @ref RTE_GRAPH_FEATURE_ARC_NAMELEN + * @param max_features + * Maximum number of features to be supported in this feature arc + * @param max_indexes + * Maximum number of interfaces/ports/indexes to be supported + * @param start_node + * Base node where this feature arc's features are checked in fast path + * @param[out] _arc + * Feature arc object + * + * @return + * 0: Success + * <0: Failure + */ +__rte_experimental +int rte_graph_feature_arc_create(const char *feature_arc_name, int max_features, int max_indexes, + struct rte_node_register *start_node, + rte_graph_feature_arc_t *_arc); + +/** + * Get feature arc object with name + * + * @param arc_name + * Feature arc name provided to successful @ref rte_graph_feature_arc_create + * @param[out] _arc + * Feature arc object returned + * + * @return + * 0: Success + * <0: Failure. + */ +__rte_experimental +int rte_graph_feature_arc_lookup_by_name(const char *arc_name, rte_graph_feature_arc_t *_arc); + +/** + * Add a feature to already created feature arc. For instance + * + * 1. Add first feature node: "ipv4-input" to input arc + * rte_graph_feature_add(ipv4_input_arc, "ipv4-input", NULL, NULL); + * + * 2. Add "ipsec-input" feature node after "ipv4-input" node + * rte_graph_feature_add(ipv4_input_arc, "ipsec-input", "ipv4-input", NULL); + * + * 3. Add "ipv4-pre-classify-input" node before "ipv4-input" node + * rte_graph_feature_add(ipv4_input_arc, "ipv4-pre-classify-input"", NULL, "ipv4-input"); + * + * 4. Add "acl-classify-input" node after ipv4-input but before ipsec-input + * rte_graph_feature_add(ipv4_input_arc, "acl-classify-input", "ipv4-input", "ipsec-input"); + * + * @param _arc + * Feature arc handle returned from @ref rte_graph_feature_arc_create() + * @param feature_node + * Graph node representing feature. On success, feature_node is next_node of + * feature_arc->start_node + * @param runs_after + * Add this feature_node after already added "runs_after". Creates + * start_node -> runs_after -> this_feature sequence + * @param runs_before + * Add this feature_node before already added "runs_before". Creates + * start_node -> this_feature -> runs_before sequence + * + * <I> Must be called before rte_graph_create() </I> + * <I> rte_graph_feature_add() is not allowed after call to + * rte_graph_feature_enable() so all features must be added before they can be + * enabled </I> + * + * @return + * 0: Success + * <0: Failure + */ +__rte_experimental +int rte_graph_feature_add(rte_graph_feature_arc_t _arc, struct rte_node_register *feature_node, + const char *runs_after, const char *runs_before); + +/** + * Enable feature within a feature arc + * + * Must be called after @b rte_graph_create(). + * + * @param _arc + * Feature arc object returned by @ref rte_graph_feature_arc_create or @ref + * rte_graph_feature_arc_lookup_by_name + * @param index + * Application specific index. Can be corresponding to interface_id/port_id etc + * @param feature_name + * Name of the node which is already added via @ref rte_graph_feature_add + * @param user_data + * Application specific data which is retrieved in fast path + * + * @return + * 0: Success + * <0: Failure + */ +__rte_experimental +int rte_graph_feature_enable(rte_graph_feature_arc_t _arc, uint32_t index, const char *feature_name, + int32_t user_data); + +/** + * Validate whether subsequent enable/disable feature would succeed or not. + * API is thread-safe + * + * @param _arc + * Feature arc object returned by @ref rte_graph_feature_arc_create or @ref + * rte_graph_feature_arc_lookup_by_name + * @param index + * Application specific index. Can be corresponding to interface_id/port_id etc + * @param feature_name + * Name of the node which is already added via @ref rte_graph_feature_add + * @param is_enable_disable + * If 1, validate whether subsequent @ref rte_graph_feature_enable would pass or not + * If 0, validate whether subsequent @ref rte_graph_feature_disable would pass or not + * + * @return + * 0: Subsequent enable/disable API would pass + * <0: Subsequent enable/disable API would not pass + */ +__rte_experimental +int rte_graph_feature_validate(rte_graph_feature_arc_t _arc, uint32_t index, + const char *feature_name, int is_enable_disable); + +/** + * Disable already enabled feature within a feature arc + * + * Must be called after @b rte_graph_create(). API is *NOT* Thread-safe + * + * @param _arc + * Feature arc object returned by @ref rte_graph_feature_arc_create or @ref + * rte_graph_feature_arc_lookup_by_name + * @param index + * Application specific index. Can be corresponding to interface_id/port_id etc + * @param feature_name + * Name of the node which is already added via @ref rte_graph_feature_add + * + * @return + * 0: Success + * <0: Failure + */ +__rte_experimental +int rte_graph_feature_disable(rte_graph_feature_arc_t _arc, uint32_t index, + const char *feature_name); + +/** + * Get rte_graph_feature_t object from feature name + * + * @param arc + * Feature arc object returned by @ref rte_graph_feature_arc_create or @ref + * rte_graph_feature_arc_lookup_by_name + * @param feature_name + * Feature name provided to @ref rte_graph_feature_add + * @param[out] feature + * Feature object + * + * @return + * 0: Success + * <0: Failure + */ +__rte_experimental +int rte_graph_feature_lookup(rte_graph_feature_arc_t _arc, const char *feature_name, + rte_graph_feature_t *feature); + +/** + * Delete feature_arc object + * + * @param _arc + * Feature arc object returned by @ref rte_graph_feature_arc_create or @ref + * rte_graph_feature_arc_lookup_by_name + * + * @return + * 0: Success + * <0: Failure + */ +__rte_experimental +int rte_graph_feature_arc_destroy(rte_graph_feature_arc_t _arc); + +/** + * Cleanup all feature arcs + * + * @return + * 0: Success + * <0: Failure + */ +__rte_experimental +int rte_graph_feature_arc_cleanup(void); + +/** + * Slow path API to know how many features are currently enabled within a featur-arc + * + * @param _arc + * Feature arc object + * + * @return: Number of enabled features + */ +__rte_experimental +int rte_graph_feature_arc_num_enabled_features(rte_graph_feature_arc_t _arc); +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/graph/rte_graph_feature_arc_worker.h b/lib/graph/rte_graph_feature_arc_worker.h new file mode 100644 index 0000000000..6019d74853 --- /dev/null +++ b/lib/graph/rte_graph_feature_arc_worker.h @@ -0,0 +1,548 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(C) 2024 Marvell International Ltd. + */ + +#ifndef _RTE_GRAPH_FEATURE_ARC_WORKER_H_ +#define _RTE_GRAPH_FEATURE_ARC_WORKER_H_ + +#include <stddef.h> +#include <rte_graph_feature_arc.h> +#include <rte_bitops.h> + +/** + * @file + * + * rte_graph_feature_arc_worker.h + * + * Defines fast path structure + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** @internal + * + * Slow path feature node info list + */ +struct rte_graph_feature_node_list { + /** Next feature */ + STAILQ_ENTRY(rte_graph_feature_node_list) next_feature; + + /** node representing feature */ + struct rte_node_register *feature_node; + + /** How many indexes/interfaces using this feature */ + int32_t ref_count; + + /* node_index in list (after feature_enable())*/ + uint32_t node_index; + + /** Back pointer to feature arc */ + void *feature_arc; + + /** rte_edge_t to this feature node from feature_arc->start_node */ + rte_edge_t edge_to_this_feature; +}; + +/** + * Fast path holding rte_edge_t and next enabled feature for an feature + */ +typedef struct __rte_packed rte_graph_feature_data { + /* next node to which current mbuf should go*/ + rte_edge_t next_edge; + + /* next enabled feature on this arc for current index */ + union { + uint16_t reserved; + struct { + rte_graph_feature_t next_enabled_feature; + }; + }; + + /* user_data */ + int32_t user_data; +} rte_graph_feature_data_t; + +/** + * Fast path feature structure. Holds re_graph_feature_data_t per index + */ +struct __rte_cache_aligned rte_graph_feature { + uint16_t this_feature_index; + + /* Array of size arc->feature_data_size + * [data-index-0][data-index-1]... + * Each index of size: sizeof(rte_graph_feature_data_t) + */ + uint8_t feature_data_by_index[]; +}; + +/** + * fast path cache aligned feature list holding all features + * There are two feature lists: active, passive + * + * Fast APIs works on active list while control plane updates passive list + * A atomic update to arc->active_feature_list is done to switch between active + * and passive + */ +typedef struct __rte_cache_aligned rte_graph_feature_list { + /** + * fast path array holding per_feature data. + * Duplicate entry as feature-arc also hold this pointer + * arc->features[] + * + *<-------------feature-0 ---------><CEIL><---------feature-1 -------------->... + *[index-0][index-1]...[max_index-1] [index-0][index-1] ...[max_index-1]... + */ + struct rte_graph_feature *indexed_by_features; + /* + * fast path array holding first enabled feature per index + * (Required in start_node. In non start_node, mbuf can hold next enabled + * feature) + */ + rte_graph_feature_t first_enabled_feature_by_index[]; +} rte_graph_feature_list_t; + +/** + * rte_graph feature arc object + * + * A feature-arc can only hold RTE_GRAPH_FEATURE_MAX_PER_ARC features but no + * limit to interface index + * + * Representing a feature arc holding all features which are enabled/disabled + * on any interfaces + */ +struct __rte_cache_aligned rte_graph_feature_arc { + /* First 64B is fast path variables */ + RTE_MARKER fast_path_variables; + + /** runtime active feature list */ + rte_graph_feature_rt_list_t active_feature_list; + + /* Actual Size of feature_list0 */ + uint16_t feature_list_size; + + /** + * Size each feature in fastpath. + * sizeof(arc->active_list->indexed_by_feature[0]) + */ + uint16_t feature_size; + + /* Size of arc->max_index * sizeof(rte_graph_feature_data_t) */ + uint16_t feature_data_size; + + /** + * Fast path bitmask indicating if a feature is enabled or not Number + * of bits: RTE_GRAPH_FEATURE_MAX_PER_ARC + */ + uint64_t feature_enable_bitmask[2]; + rte_graph_feature_list_t *feature_list[2]; + struct rte_graph_feature *features[2]; + + /** index in feature_arc_main */ + uint16_t feature_arc_index; + + uint16_t reserved[3]; + + /** Slow path variables follows*/ + RTE_MARKER slow_path_variables; + + /** feature arc name */ + char feature_arc_name[RTE_GRAPH_FEATURE_ARC_NAMELEN]; + + /** All feature lists */ + STAILQ_HEAD(, rte_graph_feature_node_list) all_features; + + uint32_t runtime_enabled_features; + + /** Back pointer to feature_arc_main */ + void *feature_arc_main; + + /* start_node */ + struct rte_node_register *start_node; + + /* maximum number of features supported by this arc */ + uint32_t max_features; + + /* maximum number of index supported by this arc */ + uint32_t max_indexes; + + /* Slow path bit mask per feature per index */ + uint64_t feature_bit_mask_by_index[]; +}; + +/** Feature arc main */ +typedef struct feature_arc_main { + /** number of feature arcs created by application */ + uint32_t num_feature_arcs; + + /** max features arcs allowed */ + uint32_t max_feature_arcs; + + /** feature arcs */ + rte_graph_feature_arc_t feature_arcs[]; +} rte_graph_feature_arc_main_t; + +/** @internal Get feature arc pointer from object */ +#define rte_graph_feature_arc_get(arc) ((struct rte_graph_feature_arc *)arc) + +extern rte_graph_feature_arc_main_t *__feature_arc_main; + +/** + * API to know if feature is valid or not + */ + +static __rte_always_inline int +rte_graph_feature_is_valid(rte_graph_feature_t feature) +{ + return (feature != RTE_GRAPH_FEATURE_INVALID); +} + +/** + * Get rte_graph_feature object with no checks + * + * @param arc + * Feature arc pointer + * @param feature + * Feature index + * @param feature_list + * active feature list retrieved from rte_graph_feature_arc_has_any_feature() + * or rte_graph_feature_arc_has_feature() + * + * @return + * Internal feature object. + */ +static __rte_always_inline struct rte_graph_feature * +__rte_graph_feature_get(struct rte_graph_feature_arc *arc, rte_graph_feature_t feature, + const rte_graph_feature_rt_list_t feature_list) +{ + return ((struct rte_graph_feature *)((uint8_t *)(arc->features[feature_list] + + (feature * arc->feature_size)))); +} + +/** + * Get rte_graph_feature object for a given interface/index from feature arc + * + * @param arc + * Feature arc pointer + * @param feature + * Feature index + * + * @return + * Internal feature object. + */ +static __rte_always_inline struct rte_graph_feature * +rte_graph_feature_get(struct rte_graph_feature_arc *arc, rte_graph_feature_t feature) +{ + RTE_VERIFY(feature < arc->max_features); + + if (likely(rte_graph_feature_is_valid(feature))) + return __rte_graph_feature_get(arc, feature, arc->active_feature_list); + + return NULL; +} + +static __rte_always_inline rte_graph_feature_data_t * +__rte_graph_feature_data_get(struct rte_graph_feature_arc *arc, struct rte_graph_feature *feature, + uint8_t index) +{ + RTE_SET_USED(arc); + return ((rte_graph_feature_data_t *)(feature->feature_data_by_index + + (index * sizeof(rte_graph_feature_data_t)))); +} + +/** + * Get rte_graph feature data object for a index in feature + * + * @param arc + * feature arc + * @param feature + * Pointer to feature object + * @param index + * Index of feature maintained in slow path linked list + * + * @return + * Valid feature data + */ +static __rte_always_inline rte_graph_feature_data_t * +rte_graph_feature_data_get(struct rte_graph_feature_arc *arc, struct rte_graph_feature *feature, + uint8_t index) +{ + if (likely(index < arc->max_indexes)) + return __rte_graph_feature_data_get(arc, feature, index); + + RTE_VERIFY(0); +} + +/** + * Fast path API to check if any feature enabled on a feature arc + * Typically from arc->start_node process function + * + * @param arc + * Feature arc object + * @param[out] plist + * Pointer to runtime active feature list which needs to be provided to other + * fast path APIs + * + * @return + * 0: If no feature enabled + * Non-Zero: Bitmask of features enabled. plist is valid + * + */ +static __rte_always_inline uint64_t +rte_graph_feature_arc_has_any_feature(struct rte_graph_feature_arc *arc, + rte_graph_feature_rt_list_t *plist) +{ + *plist = __atomic_load_n(&arc->active_feature_list, __ATOMIC_RELAXED); + + return (__atomic_load_n(arc->feature_enable_bitmask + (uint8_t)*plist, + __ATOMIC_RELAXED)); +} + +/** + * Fast path API to check if provided feature is enabled on any interface/index + * or not + * + * @param arc + * Feature arc object + * @param feature + * Input rte_graph_feature_t that needs to be checked + * @param[out] plist + * Returns active list to caller which needs to be provided to other fast path + * APIs + * + * @return + * 1: If feature is enabled in arc + * 0: If feature is not enabled in arc + */ +static __rte_always_inline int +rte_graph_feature_arc_has_feature(struct rte_graph_feature_arc *arc, + rte_graph_feature_t feature, + rte_graph_feature_rt_list_t *plist) +{ + uint64_t bitmask = RTE_BIT64(feature); + + *plist = __atomic_load_n(&arc->active_feature_list, __ATOMIC_RELAXED); + + return (bitmask & __atomic_load_n(arc->feature_enable_bitmask + (uint8_t)*plist, + __ATOMIC_RELAXED)); +} + +/** + * Prefetch feature arc fast path cache line + * + * @param arc + * RTE_GRAPH feature arc object + */ +static __rte_always_inline void +rte_graph_feature_arc_prefetch(struct rte_graph_feature_arc *arc) +{ + rte_prefetch0((void *)&arc->fast_path_variables); +} + +/** + * Prefetch feature related fast path cache line + * + * @param arc + * RTE_GRAPH feature arc object + * @param list + * Pointer to runtime active feature list from rte_graph_feature_arc_has_any_feature(); + * @param feature + * Pointer to feature object + */ +static __rte_always_inline void +rte_graph_feature_arc_feature_prefetch(struct rte_graph_feature_arc *arc, + const rte_graph_feature_rt_list_t list, + rte_graph_feature_t feature) +{ + /* feature cache line */ + if (likely(rte_graph_feature_is_valid(feature))) + rte_prefetch0((void *)__rte_graph_feature_get(arc, feature, list)); +} + +/** + * Prefetch feature data upfront. Perform sanity + * + * @param _arc + * RTE_GRAPH feature arc object + * @param list + * Pointer to runtime active feature list from rte_graph_feature_arc_has_any_feature(); + * @param feature + * Pointer to feature object returned from @ref + * rte_graph_feature_arc_first_feature_get() + * @param index + * Interface/index + */ +static __rte_always_inline void +rte_graph_feature_arc_data_prefetch(struct rte_graph_feature_arc *arc, + const rte_graph_feature_rt_list_t list, + rte_graph_feature_t feature, uint32_t index) +{ + if (likely(rte_graph_feature_is_valid(feature))) + rte_prefetch0((void *)((uint8_t *)arc->features[list] + + offsetof(struct rte_graph_feature, feature_data_by_index) + + (index * sizeof(rte_graph_feature_data_t)))); +} + +/** + * Fast path API to get first enabled feature on interface index + * Typically required in arc->start_node so that from returned feature, + * feature-data can be retrieved to steer packets + * + * @param arc + * Feature arc object + * @param list + * Pointer to runtime active feature list from + * rte_graph_feature_arc_has_any_feature() or + * rte_graph_feature_arc_has_feature() + * @param index + * Interface Index + * @param[out] feature + * Pointer to rte_graph_feature_t. + * + * @return + * 0. Success. feature field is valid + * 1. Failure. feature field is invalid + * + */ +static __rte_always_inline int +rte_graph_feature_arc_first_feature_get(struct rte_graph_feature_arc *arc, + const rte_graph_feature_rt_list_t list, + uint32_t index, + rte_graph_feature_t *feature) +{ + struct rte_graph_feature_list *feature_list = arc->feature_list[list]; + + *feature = feature_list->first_enabled_feature_by_index[index]; + + return rte_graph_feature_is_valid(*feature); +} + +/** + * Fast path API to get next enabled feature on interface index with provided + * input feature + * + * @param arc + * Feature arc object + * @param list + * Pointer to runtime active feature list from + * rte_graph_feature_arc_has_any_feature() or + * @param index + * Interface Index + * @param[in][out] feature + * Pointer to rte_graph_feature_t. Input feature set to next enabled feature + * after success return + * @param[out] next_edge + * Edge from current feature to next feature. Valid only if next feature is valid + * + * @return + * 0. Success. next enabled feature is valid. + * 1. Failure. next enabled feature is invalid + */ +static __rte_always_inline int +rte_graph_feature_arc_next_feature_get(struct rte_graph_feature_arc *arc, + const rte_graph_feature_rt_list_t list, + uint32_t index, + rte_graph_feature_t *feature, + rte_edge_t *next_edge) +{ + rte_graph_feature_data_t *feature_data = NULL; + struct rte_graph_feature *f = NULL; + + if (likely(rte_graph_feature_is_valid(*feature))) { + f = __rte_graph_feature_get(arc, *feature, list); + feature_data = rte_graph_feature_data_get(arc, f, index); + *feature = feature_data->next_enabled_feature; + *next_edge = feature_data->next_edge; + return (*feature == RTE_GRAPH_FEATURE_INVALID); + } + + return 1; +} + +/** + * Set fields with respect to first enabled feature in an arc and return edge + * Typically returned feature and interface index must be saved in rte_mbuf + * structure to pass this information to next feature node + * + * @param arc + * Feature arc object + * @param list + * Pointer to runtime active feature list from rte_graph_feature_arc_has_any_feature(); + * @param index + * Index (of interface) + * @param[out] gf + * Pointer to rte_graph_feature_t. Valid if API returns Success + * @param[out] edge + * Edge to steer packet from arc->start_node to first enabled feature. Valid + * only if API returns Success + * + * @return + * 0: If valid feature is set by API + * 1: If valid feature is NOT set by API + */ +static __rte_always_inline rte_graph_feature_t +rte_graph_feature_arc_feature_set(struct rte_graph_feature_arc *arc, + const rte_graph_feature_rt_list_t list, + uint32_t index, + rte_graph_feature_t *gf, + rte_edge_t *edge) +{ + struct rte_graph_feature_list *feature_list = arc->feature_list[list]; + struct rte_graph_feature_data *feature_data = NULL; + struct rte_graph_feature *feature = NULL; + rte_graph_feature_t f; + + /* reset */ + *gf = RTE_GRAPH_FEATURE_INVALID; + f = feature_list->first_enabled_feature_by_index[index]; + + if (unlikely(rte_graph_feature_is_valid(f))) { + feature = __rte_graph_feature_get(arc, f, list); + feature_data = rte_graph_feature_data_get(arc, feature, index); + *gf = f; + *edge = feature_data->next_edge; + return 0; + } + + return 1; +} + +/** + * Get user data corresponding to current feature set by application in + * rte_graph_feature_enable() + * + * @param arc + * Feature arc object + * @param list + * Pointer to runtime active feature list from rte_graph_feature_arc_has_any_feature(); + * @param feature + * Feature index + * @param index + * Interface index + * + * @return + * UINT32_MAX: Failure + * Valid user data: Success + */ +static __rte_always_inline uint32_t +rte_graph_feature_user_data_get(struct rte_graph_feature_arc *arc, + const rte_graph_feature_rt_list_t list, + rte_graph_feature_t feature, + uint32_t index) +{ + rte_graph_feature_data_t *fdata = NULL; + struct rte_graph_feature *f = NULL; + + if (likely(rte_graph_feature_is_valid(feature))) { + f = __rte_graph_feature_get(arc, feature, list); + fdata = rte_graph_feature_data_get(arc, f, index); + return fdata->user_data; + } + + return UINT32_MAX; +} +#ifdef __cplusplus +} +#endif +#endif diff --git a/lib/graph/version.map b/lib/graph/version.map index 2c83425ddc..82b2469fba 100644 --- a/lib/graph/version.map +++ b/lib/graph/version.map @@ -52,3 +52,20 @@ DPDK_25 { local: *; }; + +EXPERIMENTAL { + global: + + # added in 24.11 + rte_graph_feature_arc_init; + rte_graph_feature_arc_create; + rte_graph_feature_arc_lookup_by_name; + rte_graph_feature_add; + rte_graph_feature_enable; + rte_graph_feature_validate; + rte_graph_feature_disable; + rte_graph_feature_lookup; + rte_graph_feature_arc_destroy; + rte_graph_feature_arc_cleanup; + rte_graph_feature_arc_num_enabled_features; +}; -- 2.43.0 ^ permalink raw reply [flat|nested] 46+ messages in thread
* RE: [RFC PATCH 1/3] graph: add feature arc support 2024-09-07 7:31 ` [RFC PATCH 1/3] graph: add feature arc support Nitin Saxena @ 2024-09-11 4:41 ` Kiran Kumar Kokkilagadda 2024-10-10 4:42 ` Nitin Saxena 0 siblings, 1 reply; 46+ messages in thread From: Kiran Kumar Kokkilagadda @ 2024-09-11 4:41 UTC (permalink / raw) To: Nitin Saxena, Jerin Jacob, Nithin Kumar Dabilpuram, Zhirun Yan Cc: dev, Nitin Saxena > -----Original Message----- > From: Nitin Saxena <nsaxena@marvell.com> > Sent: Saturday, September 7, 2024 1:01 PM > To: Jerin Jacob <jerinj@marvell.com>; Kiran Kumar Kokkilagadda > <kirankumark@marvell.com>; Nithin Kumar Dabilpuram > <ndabilpuram@marvell.com>; Zhirun Yan <yanzhirun_163@163.com> > Cc: dev@dpdk.org; Nitin Saxena <nsaxena16@gmail.com> > Subject: [RFC PATCH 1/3] graph: add feature arc support > > add feature arc to allow dynamic steering of packets across graph nodes > based on protocol features enabled on incoming or outgoing interface > > Signed-off-by: Nitin Saxena <nsaxena@marvell.com> > --- > lib/graph/graph_feature_arc.c | 959 +++++++++++++++++++++++ > lib/graph/meson.build | 2 + > lib/graph/rte_graph_feature_arc.h | 373 +++++++++ > lib/graph/rte_graph_feature_arc_worker.h | 548 +++++++++++++ > lib/graph/version.map | 17 + > 5 files changed, 1899 insertions(+) > create mode 100644 lib/graph/graph_feature_arc.c > create mode 100644 lib/graph/rte_graph_feature_arc.h > create mode 100644 lib/graph/rte_graph_feature_arc_worker.h > > diff --git a/lib/graph/graph_feature_arc.c b/lib/graph/graph_feature_arc.c > new file mode 100644 > index 0000000000..3b05bac137 > --- /dev/null > +++ b/lib/graph/graph_feature_arc.c > @@ -0,0 +1,959 @@ > +/* SPDX-License-Identifier: BSD-3-Clause > + * Copyright(C) 2024 Marvell International Ltd. > + */ > + > +#include "graph_private.h" > +#include <rte_graph_feature_arc_worker.h> > +#include <rte_malloc.h> > + > +#define __RTE_GRAPH_FEATURE_ARC_MAX 32 > + > +#define ARC_PASSIVE_LIST(arc) (arc->active_feature_list ^ 0x1) > + > +#define rte_graph_uint_cast(x) ((unsigned int)x) > +#define feat_dbg graph_err > + > +rte_graph_feature_arc_main_t *__feature_arc_main; > + > +/* Make sure fast path cache line is compact */ > +_Static_assert((offsetof(struct rte_graph_feature_arc, slow_path_variables) > + - offsetof(struct rte_graph_feature_arc, fast_path_variables)) > + <= RTE_CACHE_LINE_SIZE); > + > + > +static int > +feature_lookup(struct rte_graph_feature_arc *arc, const char *feat_name, > + struct rte_graph_feature_node_list **ffinfo, uint32_t *slot) > +{ > + struct rte_graph_feature_node_list *finfo = NULL; > + const char *name; > + > + if (!feat_name) > + return -1; > + > + if (slot) > + *slot = 0; > + > + STAILQ_FOREACH(finfo, &arc->all_features, next_feature) { > + RTE_VERIFY(finfo->feature_arc == arc); > + name = rte_node_id_to_name(finfo->feature_node->id); > + if (!strncmp(name, feat_name, RTE_GRAPH_NAMESIZE)) { > + if (ffinfo) > + *ffinfo = finfo; > + return 0; > + } > + if (slot) > + (*slot)++; > + } > + return -1; > +} > + > +static int > +feature_arc_node_info_lookup(struct rte_graph_feature_arc *arc, uint32_t > feature_index, > + struct rte_graph_feature_node_list **ppfinfo) > +{ > + struct rte_graph_feature_node_list *finfo = NULL; > + uint32_t index = 0; > + > + if (!ppfinfo) > + return -1; > + > + *ppfinfo = NULL; > + STAILQ_FOREACH(finfo, &arc->all_features, next_feature) { > + if (index == feature_index) { > + if (finfo->node_index == feature_index) > + return -1; > + *ppfinfo = finfo; > + } > + index++; > + } > + if (feature_index && (index >= feature_index)) > + return -1; > + > + return 0; > +} > + > +static void > +prepare_feature_arc(struct rte_graph_feature_arc *arc) > +{ > + struct rte_graph_feature_node_list *finfo = NULL; > + uint32_t index = 0; > + > + STAILQ_FOREACH(finfo, &arc->all_features, next_feature) { > + finfo->node_index = index; > + index++; > + } > +} > + > +static int > +feature_arc_lookup(rte_graph_feature_arc_t _arc) > +{ > + struct rte_graph_feature_arc *arc = rte_graph_feature_arc_get(_arc); > + rte_graph_feature_arc_main_t *dm = __feature_arc_main; > + uint32_t iter; > + > + if (!__feature_arc_main) > + return -1; > + > + for (iter = 0; iter < dm->max_feature_arcs; iter++) { > + if (dm->feature_arcs[iter] == > RTE_GRAPH_FEATURE_ARC_INITIALIZER) > + continue; > + > + if (arc == (rte_graph_feature_arc_get(dm- > >feature_arcs[iter]))) > + return 0; > + } > + return -1; > +} > + > +static int > +get_existing_edge(const char *arc_name, struct rte_node_register > *parent_node, > + struct rte_node_register *child_node, rte_edge_t *_edge) > +{ > + char **next_edges = NULL; > + uint32_t count, i; > + > + RTE_SET_USED(arc_name); > + > + count = rte_node_edge_get(parent_node->id, NULL); > + next_edges = malloc(count); > + > + if (!next_edges) > + return -1; > + > + count = rte_node_edge_get(parent_node->id, next_edges); > + for (i = 0; i < count; i++) { > + if (strstr(child_node->name, next_edges[i])) { > + feat_dbg("%s: Edge exists [%s[%u]: \"%s\"]", > arc_name, > + parent_node->name, i, child_node->name); > + if (_edge) > + *_edge = (rte_edge_t)i; > + > + free(next_edges); > + return 0; > + } > + } > + free(next_edges); > + > + return -1; > +} > + > +static int > +connect_graph_nodes(struct rte_node_register *parent_node, struct > rte_node_register *child_node, > + rte_edge_t *_edge, char *arc_name) > +{ > + const char *next_node = NULL; > + rte_edge_t edge; > + > + if (!get_existing_edge(arc_name, parent_node, child_node, &edge)) { > + feat_dbg("%s: add_feature: Edge reused [%s[%u]: \"%s\"]", > arc_name, > + parent_node->name, edge, child_node->name); > + > + if (_edge) > + *_edge = edge; > + > + return 0; > + } > + > + /* Node to be added */ > + next_node = child_node->name; > + > + edge = rte_node_edge_update(parent_node->id, > RTE_EDGE_ID_INVALID, &next_node, 1); > + > + if (edge == RTE_EDGE_ID_INVALID) { > + graph_err("edge invalid"); > + return -1; > + } > + edge = rte_node_edge_count(parent_node->id) - 1; > + > + feat_dbg("%s: add_feature: edge added [%s[%u]: \"%s\"]", arc_name, > parent_node->name, edge, > + child_node->name); > + > + if (_edge) > + *_edge = edge; > + > + return 0; > +} > + > +static int > +feature_arc_init(rte_graph_feature_arc_main_t **pfl, uint32_t > max_feature_arcs) > +{ > + rte_graph_feature_arc_main_t *pm = NULL; > + uint32_t i; > + size_t sz; > + > + if (!pfl) > + return -1; > + > + sz = sizeof(rte_graph_feature_arc_main_t) + > + (sizeof(pm->feature_arcs[0]) * max_feature_arcs); > + > + pm = malloc(sz); > + if (!pm) > + return -1; > + > + memset(pm, 0, sz); > + > + for (i = 0; i < max_feature_arcs; i++) > + pm->feature_arcs[i] = > RTE_GRAPH_FEATURE_ARC_INITIALIZER; > + > + pm->max_feature_arcs = max_feature_arcs; > + > + *pfl = pm; > + > + return 0; > +} > + > +int > +rte_graph_feature_arc_init(int max_feature_arcs) > +{ > + if (!max_feature_arcs) > + return -1; > + > + if (__feature_arc_main) > + return -1; > + > + return feature_arc_init(&__feature_arc_main, max_feature_arcs); > +} > + > +static void > +feature_arc_list_reset(struct rte_graph_feature_arc *arc, uint32_t list_index) > +{ > + rte_graph_feature_data_t *fdata = NULL; > + rte_graph_feature_list_t *list = NULL; > + struct rte_graph_feature *feat = NULL; > + uint32_t i, j; > + > + list = arc->feature_list[list_index]; > + feat = arc->features[list_index]; > + > + /*Initialize variables*/ > + memset(feat, 0, arc->feature_size); > + memset(list, 0, arc->feature_list_size); > + > + /* Initialize feature and feature_data */ > + for (i = 0; i < arc->max_features; i++) { > + feat = __rte_graph_feature_get(arc, i, list_index); > + feat->this_feature_index = i; > + > + for (j = 0; j < arc->max_indexes; j++) { > + fdata = rte_graph_feature_data_get(arc, feat, j); > + fdata->next_enabled_feature = > RTE_GRAPH_FEATURE_INVALID; > + fdata->next_edge = UINT16_MAX; > + fdata->user_data = UINT32_MAX; > + } > + } > + > + for (i = 0; i < arc->max_indexes; i++) > + list->first_enabled_feature_by_index[i] = > RTE_GRAPH_FEATURE_INVALID; > +} > + > +static int > +feature_arc_list_init(struct rte_graph_feature_arc *arc, const char > *flist_name, > + rte_graph_feature_list_t **pplist, > + struct rte_graph_feature **ppfeature, uint32_t > list_index) > +{ > + char fname[2 * RTE_GRAPH_FEATURE_ARC_NAMELEN]; > + size_t list_size, feat_size, fdata_size; > + rte_graph_feature_list_t *list = NULL; > + struct rte_graph_feature *feat = NULL; > + > + list_size = sizeof(list->first_enabled_feature_by_index[0]) * arc- > >max_indexes; > + > + list = rte_malloc(flist_name, list_size, RTE_CACHE_LINE_SIZE); > + if (!list) > + return -ENOMEM; > + > + fdata_size = arc->max_indexes * sizeof(rte_graph_feature_data_t); > + > + /* Let one feature capture complete cache lines */ > + feat_size = RTE_ALIGN_CEIL(sizeof(struct rte_graph_feature) + > fdata_size, > + RTE_CACHE_LINE_SIZE); > + > + snprintf(fname, sizeof(fname), "%s-%s", arc->feature_arc_name, > "feat"); > + > + feat = rte_malloc(fname, feat_size * arc->max_features, > RTE_CACHE_LINE_SIZE); > + if (!feat) { > + rte_free(list); > + return -ENOMEM; > + } > + arc->feature_size = feat_size; > + arc->feature_data_size = fdata_size; > + arc->feature_list_size = list_size; > + > + /* Initialize list */ > + list->indexed_by_features = feat; > + *pplist = list; > + *ppfeature = feat; > + > + feature_arc_list_reset(arc, list_index); > + > + return 0; > +} > + > +static void > +feature_arc_list_destroy(rte_graph_feature_list_t *list) > +{ > + rte_free(list->indexed_by_features); Do you need to free individual rte_graph_feature here, that is allocated in arc_list_init? > + rte_free(list); > +} > + > +int > +rte_graph_feature_arc_create(const char *feature_arc_name, int > max_features, int max_indexes, > + struct rte_node_register *start_node, > rte_graph_feature_arc_t *_arc) > +{ > + char name[2 * RTE_GRAPH_FEATURE_ARC_NAMELEN]; > + rte_graph_feature_arc_main_t *dfm = NULL; > + struct rte_graph_feature_arc *arc = NULL; > + struct rte_graph_feature_data *gfd = NULL; > + struct rte_graph_feature *df = NULL; > + uint32_t iter, j, arc_index; > + size_t sz; > + > + if (!_arc) > + return -1; > + > + if (max_features < 2) > + return -1; > + > + if (!start_node) > + return -1; > + > + if (!feature_arc_name) > + return -1; > + > + if (max_features > RTE_GRAPH_FEATURE_MAX_PER_ARC) { > + graph_err("Invalid max features: %u", max_features); > + return -1; > + } > + > + /* > + * Application hasn't called rte_graph_feature_arc_init(). Initialize with > + * default values > + */ > + if (!__feature_arc_main) { > + if > (rte_graph_feature_arc_init((int)__RTE_GRAPH_FEATURE_ARC_MAX) < 0) { > + graph_err("rte_graph_feature_arc_init() failed"); > + return -1; > + } > + } > + > + dfm = __feature_arc_main; > + > + /* threshold check */ > + if (dfm->num_feature_arcs > (dfm->max_feature_arcs - 1)) { > + graph_err("max threshold for num_feature_arcs: %d > reached", > + dfm->max_feature_arcs - 1); > + return -1; > + } > + /* Find the free slot for feature arc */ > + for (iter = 0; iter < dfm->max_feature_arcs; iter++) { > + if (dfm->feature_arcs[iter] == > RTE_GRAPH_FEATURE_ARC_INITIALIZER) > + break; > + } > + arc_index = iter; > + > + if (arc_index >= dfm->max_feature_arcs) { > + graph_err("No free slot found for num_feature_arc"); > + return -1; > + } > + > + /* This should not happen */ > + RTE_VERIFY(dfm->feature_arcs[arc_index] == > RTE_GRAPH_FEATURE_ARC_INITIALIZER); > + > + /* size of feature arc + feature_bit_mask_by_index */ > + sz = sizeof(*arc) + (sizeof(uint64_t) * max_indexes); > + > + arc = rte_malloc(feature_arc_name, sz, RTE_CACHE_LINE_SIZE); > + > + if (!arc) { > + graph_err("malloc failed for feature_arc_create()"); > + return -1; > + } > + > + memset(arc, 0, sz); > + > + /* Initialize rte_graph port group fixed variables */ > + STAILQ_INIT(&arc->all_features); > + strncpy(arc->feature_arc_name, feature_arc_name, > RTE_GRAPH_FEATURE_ARC_NAMELEN - 1); > + arc->feature_arc_main = (void *)dfm; > + arc->start_node = start_node; > + arc->max_features = max_features; > + arc->max_indexes = max_indexes; > + > + snprintf(name, sizeof(name), "%s-%s", feature_arc_name, "flist0"); > + > + if (feature_arc_list_init(arc, name, &arc->feature_list[0], &arc- > >features[0], 0) < 0) { > + rte_free(arc); > + graph_err("feature_arc_list_init(0) failed"); > + return -1; > + } > + snprintf(name, sizeof(name), "%s-%s", feature_arc_name, "flist1"); > + > + if (feature_arc_list_init(arc, name, &arc->feature_list[1], &arc- > >features[1], 1) < 0) { > + feature_arc_list_destroy(arc->feature_list[0]); > + graph_err("feature_arc_list_init(1) failed"); > + return -1; > + } > + > + for (iter = 0; iter < arc->max_features; iter++) { > + df = rte_graph_feature_get(arc, iter); > + for (j = 0; j < arc->max_indexes; j++) { > + gfd = rte_graph_feature_data_get(arc, df, j); > + gfd->next_enabled_feature = > RTE_GRAPH_FEATURE_INVALID; > + } > + } > + arc->feature_arc_index = arc_index; > + dfm->feature_arcs[arc->feature_arc_index] = > (rte_graph_feature_arc_t)arc; > + dfm->num_feature_arcs++; > + > + if (_arc) > + *_arc = (rte_graph_feature_arc_t)arc; > + > + return 0; > +} > + > +int > +rte_graph_feature_add(rte_graph_feature_arc_t _arc, struct > rte_node_register *feature_node, > + const char *after_feature, const char *before_feature) > +{ > + struct rte_graph_feature_node_list *after_finfo = NULL, *before_finfo > = NULL; > + struct rte_graph_feature_node_list *temp = NULL, *finfo = NULL; > + struct rte_graph_feature_arc *arc = rte_graph_feature_arc_get(_arc); > + uint32_t slot, add_flag; > + rte_edge_t edge = -1; > + > + RTE_VERIFY(arc->feature_arc_main == __feature_arc_main); > + > + if (feature_arc_lookup(_arc)) { > + graph_err("invalid feature arc: 0x%016" PRIx64, > (uint64_t)_arc); > + return -1; > + } > + > + if (arc->runtime_enabled_features) { > + graph_err("adding features after enabling any one of them is > not supported"); > + return -1; > + } > + > + if ((after_feature != NULL) && (before_feature != NULL) && > + (after_feature == before_feature)) { > + graph_err("after_feature and before_feature are same > '%s:%s]", after_feature, > + before_feature); > + return -1; > + } > + > + if (!feature_node) { > + graph_err("feature_node: %p invalid", feature_node); > + return -1; > + } > + > + arc = rte_graph_feature_arc_get(_arc); > + > + if (feature_node->id == RTE_NODE_ID_INVALID) { > + graph_err("Invalid node: %s", feature_node->name); > + return -1; > + } > + > + if (!feature_lookup(arc, feature_node->name, &finfo, &slot)) { > + graph_err("%s feature already added", feature_node->name); > + return -1; > + } > + > + if (slot >= RTE_GRAPH_FEATURE_MAX_PER_ARC) { > + graph_err("Max slot %u reached for feature addition", slot); > + return -1; > + } > + > + if (strstr(feature_node->name, arc->start_node->name)) { > + graph_err("Feature %s cannot point to itself: %s", > feature_node->name, > + arc->start_node->name); > + return -1; > + } > + > + if (connect_graph_nodes(arc->start_node, feature_node, &edge, arc- > >feature_arc_name)) { > + graph_err("unable to connect %s -> %s", arc->start_node- > >name, feature_node->name); > + return -1; > + } > + > + finfo = malloc(sizeof(*finfo)); > + if (!finfo) > + return -1; > + > + memset(finfo, 0, sizeof(*finfo)); > + > + finfo->feature_arc = (void *)arc; > + finfo->feature_node = feature_node; > + finfo->edge_to_this_feature = edge; > + > + /* Check for before and after constraints */ > + if (before_feature) { > + /* before_feature sanity */ > + if (feature_lookup(arc, before_feature, &before_finfo, NULL)) > + SET_ERR_JMP(EINVAL, finfo_free, > + "Invalid before feature name: %s", > before_feature); > + > + if (!before_finfo) > + SET_ERR_JMP(EINVAL, finfo_free, > + "before_feature %s does not exist", > before_feature); > + > + /* > + * Starting from 0 to before_feature, continue connecting > edges > + */ > + add_flag = 1; > + STAILQ_FOREACH(temp, &arc->all_features, next_feature) { > + /* > + * As soon as we see before_feature. stop adding > edges > + */ > + if (!strncmp(temp->feature_node->name, > before_feature, > + RTE_GRAPH_NAMESIZE)) > + if (!connect_graph_nodes(finfo- > >feature_node, temp->feature_node, > + &edge, arc- > >feature_arc_name)) > + add_flag = 0; > + > + if (add_flag) > + connect_graph_nodes(temp->feature_node, > finfo->feature_node, NULL, > + arc->feature_arc_name); > + } > + } > + > + if (after_feature) { > + if (feature_lookup(arc, after_feature, &after_finfo, NULL)) > + SET_ERR_JMP(EINVAL, finfo_free, > + "Invalid after feature_name %s", > after_feature); > + > + if (!after_finfo) > + SET_ERR_JMP(EINVAL, finfo_free, > + "after_feature %s does not exist", > after_feature); > + > + /* Starting from after_feature to end continue connecting > edges */ > + add_flag = 0; > + STAILQ_FOREACH(temp, &arc->all_features, next_feature) { > + /* We have already seen after_feature now */ > + if (add_flag) > + /* Add all features as next node to current > feature*/ > + connect_graph_nodes(finfo->feature_node, > temp->feature_node, NULL, > + arc->feature_arc_name); > + > + /* as soon as we see after_feature. start adding edges > + * from next iteration > + */ > + if (!strncmp(temp->feature_node->name, > after_feature, RTE_GRAPH_NAMESIZE)) > + /* connect after_feature to this feature */ > + if (!connect_graph_nodes(temp- > >feature_node, finfo->feature_node, > + &edge, arc- > >feature_arc_name)) > + add_flag = 1; > + } > + > + /* add feature next to after_feature */ > + STAILQ_INSERT_AFTER(&arc->all_features, after_finfo, finfo, > next_feature); > + } else { > + if (before_finfo) { > + after_finfo = NULL; > + STAILQ_FOREACH(temp, &arc->all_features, > next_feature) { > + if (before_finfo == temp) { > + if (after_finfo) > + STAILQ_INSERT_AFTER(&arc- > >all_features, after_finfo, > + finfo, > next_feature); > + else > + STAILQ_INSERT_HEAD(&arc- > >all_features, finfo, > + > next_feature); > + > + return 0; > + } > + after_finfo = temp; > + } > + } else { > + STAILQ_INSERT_TAIL(&arc->all_features, finfo, > next_feature); > + } > + } > + > + return 0; > + > +finfo_free: > + free(finfo); > + > + return -1; > +} > + > +int > +rte_graph_feature_lookup(rte_graph_feature_arc_t _arc, const char > *feature_name, > + rte_graph_feature_t *feat) > +{ > + struct rte_graph_feature_arc *arc = rte_graph_feature_arc_get(_arc); > + struct rte_graph_feature_node_list *finfo = NULL; > + uint32_t slot; > + > + if (!feature_lookup(arc, feature_name, &finfo, &slot)) { > + *feat = (rte_graph_feature_t) slot; > + return 0; > + } > + > + return -1; > +} > + > +int > +rte_graph_feature_validate(rte_graph_feature_arc_t _arc, uint32_t index, > const char *feature_name, > + int is_enable_disable) > +{ > + struct rte_graph_feature_arc *arc = rte_graph_feature_arc_get(_arc); > + struct rte_graph_feature_node_list *finfo = NULL; > + struct rte_graph_feature *gf = NULL; > + uint32_t slot; > + > + /* validate _arc */ > + if (arc->feature_arc_main != __feature_arc_main) { > + graph_err("invalid feature arc: 0x%016" PRIx64, > (uint64_t)_arc); > + return -EINVAL; > + } > + > + /* validate index */ > + if (index >= arc->max_indexes) { > + graph_err("%s: Invalid provided index: %u >= %u configured", > arc->feature_arc_name, > + index, arc->max_indexes); > + return -1; > + } > + > + /* validate feature_name is already added or not */ > + if (feature_lookup(arc, feature_name, &finfo, &slot)) { > + graph_err("%s: No feature %s added", arc- > >feature_arc_name, feature_name); > + return -EINVAL; > + } > + > + if (!finfo) { > + graph_err("%s: No feature: %s found", arc- > >feature_arc_name, feature_name); > + return -EINVAL; > + } > + > + /* slot should be in valid range */ > + if (slot >= arc->max_features) { > + graph_err("%s/%s: Invalid free slot %u(max=%u) for feature", > arc->feature_arc_name, > + feature_name, slot, arc->max_features); > + return -EINVAL; > + } > + > + /* slot should be in range of 0 - 63 */ > + if (slot > (RTE_GRAPH_FEATURE_MAX_PER_ARC - 1)) { > + graph_err("%s/%s: Invalid slot: %u", arc->feature_arc_name, > + feature_name, slot); > + return -EINVAL; > + } > + > + if (finfo->node_index != slot) { > + graph_err("%s/%s: feature lookup slot mismatch with finfo > index: %u and lookup slot: %u", > + arc->feature_arc_name, feature_name, finfo- > >node_index, slot); > + return -1; > + } > + > + /* Get feature from active list */ > + gf = __rte_graph_feature_get(arc, slot, ARC_PASSIVE_LIST(arc)); > + if (gf->this_feature_index != slot) { > + graph_err("%s: %s received feature_index: %u does not match > with saved feature_index: %u", > + arc->feature_arc_name, feature_name, slot, gf- > >this_feature_index); > + return -1; > + } > + > + if (is_enable_disable && (arc->feature_bit_mask_by_index[index] & > + RTE_BIT64(slot))) { > + graph_err("%s: %s already enabled on index: %u", > + arc->feature_arc_name, feature_name, index); > + return -1; > + } > + > + if (!is_enable_disable && !arc->runtime_enabled_features) { > + graph_err("%s: No feature enabled to disable", arc- > >feature_arc_name); > + return -1; > + } > + > + if (!is_enable_disable && !(arc->feature_bit_mask_by_index[index] & > RTE_BIT64(slot))) { > + graph_err("%s: %s not enabled in bitmask for index: %u", > + arc->feature_arc_name, feature_name, index); > + return -1; > + } > + > + return 0; > +} > + > +static void > +copy_fastpath_user_data(struct rte_graph_feature_arc *arc, uint16_t > dest_list_index, > + uint16_t src_list_index) > +{ > + rte_graph_feature_data_t *sgfd = NULL, *dgfd = NULL; > + struct rte_graph_feature *sgf = NULL, *dgf = NULL; > + uint32_t i, j; > + > + for (i = 0; i < arc->max_features; i++) { > + sgf = __rte_graph_feature_get(arc, i, src_list_index); > + dgf = __rte_graph_feature_get(arc, i, dest_list_index); > + for (j = 0; j < arc->max_indexes; j++) { > + sgfd = rte_graph_feature_data_get(arc, sgf, j); > + dgfd = rte_graph_feature_data_get(arc, dgf, j); > + dgfd->user_data = sgfd->user_data; > + } > + } > +} > + > +static void > +refill_feature_fastpath_data(struct rte_graph_feature_arc *arc, uint16_t > list_index) > +{ > + struct rte_graph_feature_node_list *finfo = NULL, *prev_finfo = NULL; > + struct rte_graph_feature_data *gfd = NULL, *prev_gfd = NULL; > + struct rte_graph_feature *gf = NULL, *prev_gf = NULL; > + rte_graph_feature_list_t *flist = NULL; > + uint32_t fi, di, prev_fi; > + uint64_t bitmask; > + rte_edge_t edge; > + > + flist = arc->feature_list[list_index]; > + > + for (di = 0; di < arc->max_indexes; di++) { > + bitmask = arc->feature_bit_mask_by_index[di]; > + prev_fi = RTE_GRAPH_FEATURE_INVALID; > + /* for each feature set for index, set fast path data */ > + while (rte_bsf64_safe(bitmask, &fi)) { > + gf = __rte_graph_feature_get(arc, fi, list_index); > + gfd = rte_graph_feature_data_get(arc, gf, di); > + feature_arc_node_info_lookup(arc, fi, &finfo); > + > + /* If previous feature_index was valid in last loop */ > + if (prev_fi != RTE_GRAPH_FEATURE_INVALID) { > + prev_gf = __rte_graph_feature_get(arc, > prev_fi, list_index); > + prev_gfd = rte_graph_feature_data_get(arc, > prev_gf, di); > + /* > + * Get edge of previous feature node > connecting to this feature node > + */ > + feature_arc_node_info_lookup(arc, prev_fi, > &prev_finfo); > + if (!get_existing_edge(arc->feature_arc_name, > + prev_finfo->feature_node, > + finfo->feature_node, > &edge)) { > + feat_dbg("[%s/%s(%2u)/idx:%2u]: > %s[%u] = %s", > + arc->feature_arc_name, > + prev_finfo->feature_node- > >name, prev_fi, di, > + prev_finfo->feature_node- > >name, > + edge, finfo->feature_node- > >name); > + /* Copy feature index for next > iteration*/ > + gfd->next_edge = edge; > + prev_fi = fi; > + /* > + * Fill current feature as next enabled > + * feature to previous one > + */ > + prev_gfd->next_enabled_feature = fi; > + } else { > + /* Should not fail */ > + RTE_VERIFY(0); > + } > + } > + /* On first feature edge of the node to be added */ > + if (fi == rte_bsf64(arc- > >feature_bit_mask_by_index[di])) { > + if (!get_existing_edge(arc->feature_arc_name, > arc->start_node, > + finfo->feature_node, > + &edge)) { > + feat_dbg("[%s/%s/%2u/idx:%2u]: 1st > feat %s[%u] = %s", > + arc->feature_arc_name, > + arc->start_node->name, fi, di, > + arc->start_node->name, > edge, > + finfo->feature_node->name); > + /* Copy feature index for next > iteration*/ > + gfd->next_edge = edge; > + prev_fi = fi; > + /* Set first feature set array for > index*/ > + flist- > >first_enabled_feature_by_index[di] = fi; > + } else { > + /* Should not fail */ > + RTE_VERIFY(0); > + } > + } > + /* Clear current feature index */ > + bitmask &= ~RTE_BIT64(fi); > + } > + } > +} > + > +int > +rte_graph_feature_enable(rte_graph_feature_arc_t _arc, uint32_t index, > const > + char *feature_name, int32_t user_data) > +{ > + struct rte_graph_feature_arc *arc = rte_graph_feature_arc_get(_arc); > + struct rte_graph_feature_node_list *finfo = NULL; > + struct rte_graph_feature_data *gfd = NULL; > + rte_graph_feature_rt_list_t passive_list; > + struct rte_graph_feature *gf = NULL; > + uint64_t fp_bitmask; > + uint32_t slot; > + > + if (rte_graph_feature_validate(_arc, index, feature_name, 1)) > + return -1; > + > + /** This should not fail as validate() has passed */ > + if (feature_lookup(arc, feature_name, &finfo, &slot)) > + RTE_VERIFY(0); > + > + if (!arc->runtime_enabled_features) > + prepare_feature_arc(arc); > + > + passive_list = ARC_PASSIVE_LIST(arc); > + > + gf = __rte_graph_feature_get(arc, slot, passive_list); > + gfd = rte_graph_feature_data_get(arc, gf, index); > + > + feat_dbg("%s/%s: Enabling feature on list: %u for index: %u at feature > slot %u", > + arc->feature_arc_name, feature_name, passive_list, index, > slot); > + > + /* Reset feature list */ > + feature_arc_list_reset(arc, passive_list); > + > + /* Copy user-data */ > + copy_fastpath_user_data(arc, passive_list, arc->active_feature_list); > + > + /* Set current user-data */ > + gfd->user_data = user_data; > + > + /* Set bitmask in control path bitmask */ > + rte_bit_relaxed_set64(rte_graph_uint_cast(slot), &arc- > >feature_bit_mask_by_index[index]); > + refill_feature_fastpath_data(arc, passive_list); > + > + /* Set fast path enable bitmask */ > + fp_bitmask = __atomic_load_n(&arc- > >feature_enable_bitmask[passive_list], __ATOMIC_RELAXED); > + fp_bitmask |= RTE_BIT64(slot); > + __atomic_store(&arc->feature_enable_bitmask[passive_list], > &fp_bitmask, __ATOMIC_RELAXED); > + > + /* Slow path updates */ > + arc->runtime_enabled_features++; > + > + /* Increase feature node info reference count */ > + finfo->ref_count++; > + > + /* Store release semantics for active_list update */ > + __atomic_store(&arc->active_feature_list, &passive_list, > __ATOMIC_RELEASE); > + > + return 0; > +} > + > +int > +rte_graph_feature_disable(rte_graph_feature_arc_t _arc, uint32_t index, > const char *feature_name) > +{ > + struct rte_graph_feature_arc *arc = rte_graph_feature_arc_get(_arc); > + struct rte_graph_feature_data *gfd = NULL; > + struct rte_graph_feature_node_list *finfo = NULL; > + rte_graph_feature_rt_list_t passive_list; > + struct rte_graph_feature *gf = NULL; > + uint32_t slot; > + > + if (rte_graph_feature_validate(_arc, index, feature_name, 0)) > + return -1; > + > + if (feature_lookup(arc, feature_name, &finfo, &slot)) > + return -1; > + > + passive_list = ARC_PASSIVE_LIST(arc); > + > + gf = __rte_graph_feature_get(arc, slot, passive_list); > + gfd = rte_graph_feature_data_get(arc, gf, index); > + > + feat_dbg("%s/%s: Disabling feature for index: %u at feature slot %u", > arc->feature_arc_name, > + feature_name, index, slot); > + > + rte_bit_relaxed_clear64(rte_graph_uint_cast(slot), &arc- > >feature_bit_mask_by_index[index]); > + > + /* Set fast path enable bitmask */ > + arc->feature_enable_bitmask[passive_list] &= ~(RTE_BIT64(slot)); > + > + /* Reset feature list */ > + feature_arc_list_reset(arc, passive_list); > + > + /* Copy user-data */ > + copy_fastpath_user_data(arc, passive_list, arc->active_feature_list); > + > + /* Reset current user-data */ > + gfd->user_data = ~0; > + > + refill_feature_fastpath_data(arc, passive_list); > + > + finfo->ref_count--; > + arc->runtime_enabled_features--; > + > + /* Store release semantics for active_list update */ > + __atomic_store(&arc->active_feature_list, &passive_list, > __ATOMIC_RELEASE); > + > + return 0; > +} > + > +int > +rte_graph_feature_arc_destroy(rte_graph_feature_arc_t _arc) > +{ > + struct rte_graph_feature_arc *arc = rte_graph_feature_arc_get(_arc); > + rte_graph_feature_arc_main_t *dm = __feature_arc_main; > + struct rte_graph_feature_node_list *node_info = NULL; > + > + while (!STAILQ_EMPTY(&arc->all_features)) { > + node_info = STAILQ_FIRST(&arc->all_features); > + STAILQ_REMOVE_HEAD(&arc->all_features, next_feature); > + free(node_info); > + } > + feature_arc_list_destroy(arc->feature_list[0]); > + feature_arc_list_destroy(arc->feature_list[1]); > + rte_free(arc->features[0]); > + rte_free(arc->features[1]); > + > + dm->feature_arcs[arc->feature_arc_index] = > RTE_GRAPH_FEATURE_ARC_INITIALIZER; > + > + rte_free(arc); > + return 0; > +} > + > +int > +rte_graph_feature_arc_cleanup(void) > +{ > + rte_graph_feature_arc_main_t *dm = __feature_arc_main; > + uint32_t iter; > + > + if (!__feature_arc_main) > + return -1; > + > + for (iter = 0; iter < dm->max_feature_arcs; iter++) { > + if (dm->feature_arcs[iter] == > RTE_GRAPH_FEATURE_ARC_INITIALIZER) > + continue; > + > + rte_graph_feature_arc_destroy((rte_graph_feature_arc_t)dm- > >feature_arcs[iter]); > + } > + free(dm); > + > + __feature_arc_main = NULL; > + > + return 0; > +} > + > +int > +rte_graph_feature_arc_lookup_by_name(const char *arc_name, > rte_graph_feature_arc_t *_arc) > +{ > + rte_graph_feature_arc_main_t *dm = __feature_arc_main; > + struct rte_graph_feature_arc *arc = NULL; > + uint32_t iter; > + > + if (!__feature_arc_main) > + return -1; > + > + for (iter = 0; iter < dm->max_feature_arcs; iter++) { > + if (dm->feature_arcs[iter] == > RTE_GRAPH_FEATURE_ARC_INITIALIZER) > + continue; > + > + arc = rte_graph_feature_arc_get(dm->feature_arcs[iter]); > + > + if (strstr(arc_name, arc->feature_arc_name)) { > + if (_arc) > + *_arc = (rte_graph_feature_arc_t)arc; > + return 0; > + } > + } > + > + return -1; > +} > + > +int > +rte_graph_feature_arc_num_enabled_features(rte_graph_feature_arc_t > _arc) > +{ > + struct rte_graph_feature_arc *arc = rte_graph_feature_arc_get(_arc); > + > + return arc->runtime_enabled_features; > +} > + > + > diff --git a/lib/graph/meson.build b/lib/graph/meson.build > index 0cb15442ab..d916176fb7 100644 > --- a/lib/graph/meson.build > +++ b/lib/graph/meson.build > @@ -14,11 +14,13 @@ sources = files( > 'graph_debug.c', > 'graph_stats.c', > 'graph_populate.c', > + 'graph_feature_arc.c', > 'graph_pcap.c', > 'rte_graph_worker.c', > 'rte_graph_model_mcore_dispatch.c', > ) > headers = files('rte_graph.h', 'rte_graph_worker.h') > +headers += files('rte_graph_feature_arc.h', 'rte_graph_feature_arc_worker.h') > indirect_headers += files( > 'rte_graph_model_mcore_dispatch.h', > 'rte_graph_model_rtc.h', > diff --git a/lib/graph/rte_graph_feature_arc.h > b/lib/graph/rte_graph_feature_arc.h > new file mode 100644 > index 0000000000..e3bf4eb73d > --- /dev/null > +++ b/lib/graph/rte_graph_feature_arc.h > @@ -0,0 +1,373 @@ > +/* SPDX-License-Identifier: BSD-3-Clause > + * Copyright(C) 2024 Marvell International Ltd. > + */ > + > +#ifndef _RTE_GRAPH_FEATURE_ARC_H_ > +#define _RTE_GRAPH_FEATURE_ARC_H_ > + > +#include <assert.h> > +#include <errno.h> > +#include <signal.h> > +#include <stddef.h> > +#include <stdint.h> > +#include <stdio.h> > +#include <stdlib.h> > +#include <string.h> > + > +#include <rte_common.h> > +#include <rte_compat.h> > +#include <rte_debug.h> > +#include <rte_graph.h> > +#include <rte_graph_worker.h> > + > +#ifdef __cplusplus > +extern "C" { > +#endif > + > +/** > + * @file > + * > + * rte_graph_feature_arc.h > + * > + * Define APIs and structures/variables with respect to feature arc > + * > + * - Feature arc(s) > + * - Feature(s) > + * > + * A feature arc represents an ordered list of features/protocol-nodes at a > + * given networking layer. Feature arc provides a high level abstraction to > + * connect various *rte_graph* nodes, designated as *feature nodes*, and > + * allowing steering of packets across these feature nodes fast path > processing > + * in a generic manner. In a typical network stack, often a protocol or feature > + * must be first enabled on a given interface, before any packet is steered > + * towards it for feature processing. For eg: incoming IPv4 packets are sent to > + * routing sub-system only after a valid IPv4 address is assigned to the > + * received interface. In other words, often packets needs to be steered across > + * features not based on the packet content but based on whether a feature is > + * enable or disable on a given incoming/outgoing interface. Feature arc > + * provides mechanism to enable/disable feature(s) on each interface at > runtime > + * and allow seamless packet steering across runtime enabled feature nodes > in > + * fast path. > + * > + * Feature arc also provides a way to steer packets from standard nodes to > + * custom/user-defined *feature nodes* without any change in standard > node's > + * fast path functions > + * > + * On a given interface multiple feature(s) might be enabled in a particular > + * feature arc. For instance, both "ipv4-output" and "IPsec policy output" > + * features may be enabled on "eth0" interface in "L3-output" feature arc. > + * Similarly, "ipv6-output" and "ipsec-output" may be enabled on "eth1" > + * interface in same "L3-output" feature arc. > + * > + * When multiple features are present in a given feature arc, its imperative > + * to allow each feature processing in a particular sequential order. For > + * instance, in "L3-input" feature arc it may be required to run "IPsec > + * input" feature first, for packet decryption, before "ip-lookup". So a > + * sequential order must be maintained among features present in a feature > arc. > + * > + * Features are enabled/disabled multiple times at runtime to some or all > + * available interfaces present in the system. Features can be > enabled/disabled > + * even after @b rte_graph_create() is called. Enable/disabling features on > one > + * interface is independent of other interface. > + * > + * A given feature might consume packet (if it's configured to consume) or > may > + * forward it to next enabled feature. For instance, "IPsec input" feature may > + * consume/drop all packets with "Protect" policy action while all packets with > + * policy action as "Bypass" may be forwarded to next enabled feature (with > in > + * same feature arc) > + * > + * This library facilitates rte graph based applications to steer packets in > + * fast path to different feature nodes with-in a feature arc and support all > + * functionalities described above > + * > + * In order to use feature-arc APIs, applications needs to do following in > + * control path: > + * - Initialize feature arc library via rte_graph_feature_arc_init() > + * - Create feature arc via rte_graph_feature_arc_create() > + * - *Before calling rte_graph_create()*, features must be added to feature- > arc > + * via rte_graph_feature_add(). rte_graph_feature_add() allows adding > + * features in a sequential order with "runs_after" and "runs_before" > + * constraints. > + * - Post rte_graph_create(), features can be enabled/disabled at runtime on > + * any interface via rte_graph_feature_enable()/rte_graph_feature_disable() > + * - Feature arc can be destroyed via rte_graph_feature_arc_destroy() > + * > + * In fast path, APIs are provided to steer packets towards feature path from > + * - start_node (provided as an argument to rte_graph_feature_arc_create()) > + * - feature nodes (which are added via rte_graph_feature_add()) > + * > + * For typical steering of packets across feature nodes, application required > + * to know "rte_edges" which are saved in feature data object. Feature data > + * object is unique for every interface per feature with in a feature arc. > + * > + * When steering packets from start_node to feature node: > + * - rte_graph_feature_arc_first_feature_get() provides first enabled feature. > + * - Next rte_edge from start_node to first enabled feature can be obtained > via > + * rte_graph_feature_arc_feature_set() > + * > + * rte_mbuf can carry [current feature, index] from start_node of an arc to > other > + * feature nodes > + * > + * In feature node, application can get 32-bit user_data > + * via_rte_graph_feature_user_data_get() which is provided in > + * rte_graph_feature_enable(). User data can hold feature specific cookie like > + * IPsec policy database index (if more than one are supported) > + * > + * If feature node is not consuming packet, next enabled feature and next > + * rte_edge can be obtained via rte_graph_feature_arc_next_feature_get() > + * > + * It is application responsibility to ensure that at-least *last feature*(or sink > + * feature) must be enabled from where packet can exit feature-arc path, if > + * *NO* intermediate feature is consuming the packet and it has reached till > + * the end of feature arc path > + * > + * Synchronization among cores > + * --------------------------- > + * Subsequent calls to rte_graph_feature_enable() is allowed while worker > cores > + * are processing in rte_graph_walk() loop. However, for > + * rte_graph_feature_disable() application must use RCU based > synchronization > + */ > + > +/**< Initializer value for rte_graph_feature_arc_t */ > +#define RTE_GRAPH_FEATURE_ARC_INITIALIZER > ((rte_graph_feature_arc_t)UINT64_MAX) > + > +/** Max number of features supported in a given feature arc */ > +#define RTE_GRAPH_FEATURE_MAX_PER_ARC 64 > + > +/** Length of feature arc name */ > +#define RTE_GRAPH_FEATURE_ARC_NAMELEN RTE_NODE_NAMESIZE > + > +/** @internal */ > +#define rte_graph_feature_cast(x) ((rte_graph_feature_t)x) > + > +/**< Initializer value for rte_graph_feature_arc_t */ > +#define RTE_GRAPH_FEATURE_INVALID > rte_graph_feature_cast(UINT8_MAX) > + > +/** rte_graph feature arc object */ > +typedef uint64_t rte_graph_feature_arc_t; > + > +/** rte_graph feature object */ > +typedef uint8_t rte_graph_feature_t; > + > +/** runtime active feature list index with in feature arc*/ > +typedef uint8_t rte_graph_feature_rt_list_t; > + > +/** per feature arc monotonically increasing counter to synchronize fast path > APIs */ > +typedef uint16_t rte_graph_feature_counter_t; > + > +/** > + * Initialize feature arc subsystem > + * > + * @param max_feature_arcs > + * Maximum number of feature arcs required to be supported > + * > + * @return > + * 0: Success > + * <0: Failure > + */ > +__rte_experimental > +int rte_graph_feature_arc_init(int max_feature_arcs); > + > +/** > + * Create a feature arc > + * > + * @param feature_arc_name > + * Feature arc name with max length of @ref > RTE_GRAPH_FEATURE_ARC_NAMELEN > + * @param max_features > + * Maximum number of features to be supported in this feature arc > + * @param max_indexes > + * Maximum number of interfaces/ports/indexes to be supported > + * @param start_node > + * Base node where this feature arc's features are checked in fast path > + * @param[out] _arc > + * Feature arc object > + * > + * @return > + * 0: Success > + * <0: Failure > + */ > +__rte_experimental > +int rte_graph_feature_arc_create(const char *feature_arc_name, int > max_features, int max_indexes, > + struct rte_node_register *start_node, > + rte_graph_feature_arc_t *_arc); > + > +/** > + * Get feature arc object with name > + * > + * @param arc_name > + * Feature arc name provided to successful @ref > rte_graph_feature_arc_create > + * @param[out] _arc > + * Feature arc object returned > + * > + * @return > + * 0: Success > + * <0: Failure. > + */ > +__rte_experimental > +int rte_graph_feature_arc_lookup_by_name(const char *arc_name, > rte_graph_feature_arc_t *_arc); > + > +/** > + * Add a feature to already created feature arc. For instance > + * > + * 1. Add first feature node: "ipv4-input" to input arc > + * rte_graph_feature_add(ipv4_input_arc, "ipv4-input", NULL, NULL); > + * > + * 2. Add "ipsec-input" feature node after "ipv4-input" node > + * rte_graph_feature_add(ipv4_input_arc, "ipsec-input", "ipv4-input", > NULL); > + * > + * 3. Add "ipv4-pre-classify-input" node before "ipv4-input" node > + * rte_graph_feature_add(ipv4_input_arc, "ipv4-pre-classify-input"", NULL, > "ipv4-input"); > + * > + * 4. Add "acl-classify-input" node after ipv4-input but before ipsec-input > + * rte_graph_feature_add(ipv4_input_arc, "acl-classify-input", "ipv4-input", > "ipsec-input"); > + * > + * @param _arc > + * Feature arc handle returned from @ref rte_graph_feature_arc_create() > + * @param feature_node > + * Graph node representing feature. On success, feature_node is next_node > of > + * feature_arc->start_node > + * @param runs_after > + * Add this feature_node after already added "runs_after". Creates > + * start_node -> runs_after -> this_feature sequence > + * @param runs_before > + * Add this feature_node before already added "runs_before". Creates > + * start_node -> this_feature -> runs_before sequence > + * > + * <I> Must be called before rte_graph_create() </I> > + * <I> rte_graph_feature_add() is not allowed after call to > + * rte_graph_feature_enable() so all features must be added before they can > be > + * enabled </I> > + * > + * @return > + * 0: Success > + * <0: Failure > + */ > +__rte_experimental > +int rte_graph_feature_add(rte_graph_feature_arc_t _arc, struct > rte_node_register *feature_node, > + const char *runs_after, const char *runs_before); > + > +/** > + * Enable feature within a feature arc > + * > + * Must be called after @b rte_graph_create(). > + * > + * @param _arc > + * Feature arc object returned by @ref rte_graph_feature_arc_create or > @ref > + * rte_graph_feature_arc_lookup_by_name > + * @param index > + * Application specific index. Can be corresponding to interface_id/port_id > etc > + * @param feature_name > + * Name of the node which is already added via @ref rte_graph_feature_add > + * @param user_data > + * Application specific data which is retrieved in fast path > + * > + * @return > + * 0: Success > + * <0: Failure > + */ > +__rte_experimental > +int rte_graph_feature_enable(rte_graph_feature_arc_t _arc, uint32_t index, > const char *feature_name, > + int32_t user_data); > + > +/** > + * Validate whether subsequent enable/disable feature would succeed or not. > + * API is thread-safe > + * > + * @param _arc > + * Feature arc object returned by @ref rte_graph_feature_arc_create or > @ref > + * rte_graph_feature_arc_lookup_by_name > + * @param index > + * Application specific index. Can be corresponding to interface_id/port_id > etc > + * @param feature_name > + * Name of the node which is already added via @ref rte_graph_feature_add > + * @param is_enable_disable > + * If 1, validate whether subsequent @ref rte_graph_feature_enable would > pass or not > + * If 0, validate whether subsequent @ref rte_graph_feature_disable would > pass or not > + * > + * @return > + * 0: Subsequent enable/disable API would pass > + * <0: Subsequent enable/disable API would not pass > + */ > +__rte_experimental > +int rte_graph_feature_validate(rte_graph_feature_arc_t _arc, uint32_t index, > + const char *feature_name, int is_enable_disable); > + > +/** > + * Disable already enabled feature within a feature arc > + * > + * Must be called after @b rte_graph_create(). API is *NOT* Thread-safe > + * > + * @param _arc > + * Feature arc object returned by @ref rte_graph_feature_arc_create or > @ref > + * rte_graph_feature_arc_lookup_by_name > + * @param index > + * Application specific index. Can be corresponding to interface_id/port_id > etc > + * @param feature_name > + * Name of the node which is already added via @ref rte_graph_feature_add > + * > + * @return > + * 0: Success > + * <0: Failure > + */ > +__rte_experimental > +int rte_graph_feature_disable(rte_graph_feature_arc_t _arc, uint32_t index, > + const char *feature_name); > + > +/** > + * Get rte_graph_feature_t object from feature name > + * > + * @param arc > + * Feature arc object returned by @ref rte_graph_feature_arc_create or > @ref > + * rte_graph_feature_arc_lookup_by_name > + * @param feature_name > + * Feature name provided to @ref rte_graph_feature_add > + * @param[out] feature > + * Feature object > + * > + * @return > + * 0: Success > + * <0: Failure > + */ > +__rte_experimental > +int rte_graph_feature_lookup(rte_graph_feature_arc_t _arc, const char > *feature_name, > + rte_graph_feature_t *feature); > + > +/** > + * Delete feature_arc object > + * > + * @param _arc > + * Feature arc object returned by @ref rte_graph_feature_arc_create or > @ref > + * rte_graph_feature_arc_lookup_by_name > + * > + * @return > + * 0: Success > + * <0: Failure > + */ > +__rte_experimental > +int rte_graph_feature_arc_destroy(rte_graph_feature_arc_t _arc); > + > +/** > + * Cleanup all feature arcs > + * > + * @return > + * 0: Success > + * <0: Failure > + */ > +__rte_experimental > +int rte_graph_feature_arc_cleanup(void); > + > +/** > + * Slow path API to know how many features are currently enabled within a > featur-arc > + * > + * @param _arc > + * Feature arc object > + * > + * @return: Number of enabled features > + */ > +__rte_experimental > +int rte_graph_feature_arc_num_enabled_features(rte_graph_feature_arc_t > _arc); > +#ifdef __cplusplus > +} > +#endif > + > +#endif > diff --git a/lib/graph/rte_graph_feature_arc_worker.h > b/lib/graph/rte_graph_feature_arc_worker.h > new file mode 100644 > index 0000000000..6019d74853 > --- /dev/null > +++ b/lib/graph/rte_graph_feature_arc_worker.h > @@ -0,0 +1,548 @@ > +/* SPDX-License-Identifier: BSD-3-Clause > + * Copyright(C) 2024 Marvell International Ltd. > + */ > + > +#ifndef _RTE_GRAPH_FEATURE_ARC_WORKER_H_ > +#define _RTE_GRAPH_FEATURE_ARC_WORKER_H_ > + > +#include <stddef.h> > +#include <rte_graph_feature_arc.h> > +#include <rte_bitops.h> > + > +/** > + * @file > + * > + * rte_graph_feature_arc_worker.h > + * > + * Defines fast path structure > + */ > + > +#ifdef __cplusplus > +extern "C" { > +#endif > + > +/** @internal > + * > + * Slow path feature node info list > + */ > +struct rte_graph_feature_node_list { > + /** Next feature */ > + STAILQ_ENTRY(rte_graph_feature_node_list) next_feature; > + > + /** node representing feature */ > + struct rte_node_register *feature_node; > + > + /** How many indexes/interfaces using this feature */ > + int32_t ref_count; > + > + /* node_index in list (after feature_enable())*/ > + uint32_t node_index; > + > + /** Back pointer to feature arc */ > + void *feature_arc; > + > + /** rte_edge_t to this feature node from feature_arc->start_node */ > + rte_edge_t edge_to_this_feature; > +}; > + > +/** > + * Fast path holding rte_edge_t and next enabled feature for an feature > + */ > +typedef struct __rte_packed rte_graph_feature_data { > + /* next node to which current mbuf should go*/ > + rte_edge_t next_edge; > + > + /* next enabled feature on this arc for current index */ > + union { > + uint16_t reserved; > + struct { > + rte_graph_feature_t next_enabled_feature; > + }; > + }; > + > + /* user_data */ > + int32_t user_data; > +} rte_graph_feature_data_t; > + > +/** > + * Fast path feature structure. Holds re_graph_feature_data_t per index > + */ > +struct __rte_cache_aligned rte_graph_feature { > + uint16_t this_feature_index; > + > + /* Array of size arc->feature_data_size > + * [data-index-0][data-index-1]... > + * Each index of size: sizeof(rte_graph_feature_data_t) > + */ > + uint8_t feature_data_by_index[]; > +}; > + > +/** > + * fast path cache aligned feature list holding all features > + * There are two feature lists: active, passive > + * > + * Fast APIs works on active list while control plane updates passive list > + * A atomic update to arc->active_feature_list is done to switch between > active > + * and passive > + */ > +typedef struct __rte_cache_aligned rte_graph_feature_list { > + /** > + * fast path array holding per_feature data. > + * Duplicate entry as feature-arc also hold this pointer > + * arc->features[] > + * > + *<-------------feature-0 ---------><CEIL><---------feature-1 -------------- > >... > + *[index-0][index-1]...[max_index-1] [index-0][index-1] > ...[max_index-1]... > + */ > + struct rte_graph_feature *indexed_by_features; > + /* > + * fast path array holding first enabled feature per index > + * (Required in start_node. In non start_node, mbuf can hold next > enabled > + * feature) > + */ > + rte_graph_feature_t first_enabled_feature_by_index[]; > +} rte_graph_feature_list_t; > + > +/** > + * rte_graph feature arc object > + * > + * A feature-arc can only hold RTE_GRAPH_FEATURE_MAX_PER_ARC features > but no > + * limit to interface index > + * > + * Representing a feature arc holding all features which are enabled/disabled > + * on any interfaces > + */ > +struct __rte_cache_aligned rte_graph_feature_arc { > + /* First 64B is fast path variables */ > + RTE_MARKER fast_path_variables; > + > + /** runtime active feature list */ > + rte_graph_feature_rt_list_t active_feature_list; > + > + /* Actual Size of feature_list0 */ > + uint16_t feature_list_size; > + > + /** > + * Size each feature in fastpath. > + * sizeof(arc->active_list->indexed_by_feature[0]) > + */ > + uint16_t feature_size; > + > + /* Size of arc->max_index * sizeof(rte_graph_feature_data_t) */ > + uint16_t feature_data_size; > + > + /** > + * Fast path bitmask indicating if a feature is enabled or not Number > + * of bits: RTE_GRAPH_FEATURE_MAX_PER_ARC > + */ > + uint64_t feature_enable_bitmask[2]; > + rte_graph_feature_list_t *feature_list[2]; > + struct rte_graph_feature *features[2]; > + > + /** index in feature_arc_main */ > + uint16_t feature_arc_index; > + > + uint16_t reserved[3]; > + > + /** Slow path variables follows*/ > + RTE_MARKER slow_path_variables; > + > + /** feature arc name */ > + char feature_arc_name[RTE_GRAPH_FEATURE_ARC_NAMELEN]; > + > + /** All feature lists */ > + STAILQ_HEAD(, rte_graph_feature_node_list) all_features; > + > + uint32_t runtime_enabled_features; > + > + /** Back pointer to feature_arc_main */ > + void *feature_arc_main; > + > + /* start_node */ > + struct rte_node_register *start_node; > + > + /* maximum number of features supported by this arc */ > + uint32_t max_features; > + > + /* maximum number of index supported by this arc */ > + uint32_t max_indexes; > + > + /* Slow path bit mask per feature per index */ > + uint64_t feature_bit_mask_by_index[]; > +}; > + > +/** Feature arc main */ > +typedef struct feature_arc_main { > + /** number of feature arcs created by application */ > + uint32_t num_feature_arcs; > + > + /** max features arcs allowed */ > + uint32_t max_feature_arcs; > + > + /** feature arcs */ > + rte_graph_feature_arc_t feature_arcs[]; > +} rte_graph_feature_arc_main_t; > + > +/** @internal Get feature arc pointer from object */ > +#define rte_graph_feature_arc_get(arc) ((struct rte_graph_feature_arc *)arc) > + > +extern rte_graph_feature_arc_main_t *__feature_arc_main; > + > +/** > + * API to know if feature is valid or not > + */ > + > +static __rte_always_inline int > +rte_graph_feature_is_valid(rte_graph_feature_t feature) > +{ > + return (feature != RTE_GRAPH_FEATURE_INVALID); > +} > + > +/** > + * Get rte_graph_feature object with no checks > + * > + * @param arc > + * Feature arc pointer > + * @param feature > + * Feature index > + * @param feature_list > + * active feature list retrieved from > rte_graph_feature_arc_has_any_feature() > + * or rte_graph_feature_arc_has_feature() > + * > + * @return > + * Internal feature object. > + */ > +static __rte_always_inline struct rte_graph_feature * > +__rte_graph_feature_get(struct rte_graph_feature_arc *arc, > rte_graph_feature_t feature, > + const rte_graph_feature_rt_list_t feature_list) > +{ > + return ((struct rte_graph_feature *)((uint8_t *)(arc- > >features[feature_list] + > + (feature * arc->feature_size)))); > +} > + > +/** > + * Get rte_graph_feature object for a given interface/index from feature arc > + * > + * @param arc > + * Feature arc pointer > + * @param feature > + * Feature index > + * > + * @return > + * Internal feature object. > + */ > +static __rte_always_inline struct rte_graph_feature * > +rte_graph_feature_get(struct rte_graph_feature_arc *arc, > rte_graph_feature_t feature) > +{ > + RTE_VERIFY(feature < arc->max_features); > + > + if (likely(rte_graph_feature_is_valid(feature))) > + return __rte_graph_feature_get(arc, feature, arc- > >active_feature_list); > + > + return NULL; > +} > + > +static __rte_always_inline rte_graph_feature_data_t * > +__rte_graph_feature_data_get(struct rte_graph_feature_arc *arc, struct > rte_graph_feature *feature, > + uint8_t index) > +{ > + RTE_SET_USED(arc); > + return ((rte_graph_feature_data_t *)(feature->feature_data_by_index > + > + (index * > sizeof(rte_graph_feature_data_t)))); > +} > + > +/** > + * Get rte_graph feature data object for a index in feature > + * > + * @param arc > + * feature arc > + * @param feature > + * Pointer to feature object > + * @param index > + * Index of feature maintained in slow path linked list > + * > + * @return > + * Valid feature data > + */ > +static __rte_always_inline rte_graph_feature_data_t * > +rte_graph_feature_data_get(struct rte_graph_feature_arc *arc, struct > rte_graph_feature *feature, > + uint8_t index) > +{ > + if (likely(index < arc->max_indexes)) > + return __rte_graph_feature_data_get(arc, feature, index); > + > + RTE_VERIFY(0); > +} > + > +/** > + * Fast path API to check if any feature enabled on a feature arc > + * Typically from arc->start_node process function > + * > + * @param arc > + * Feature arc object > + * @param[out] plist > + * Pointer to runtime active feature list which needs to be provided to other > + * fast path APIs > + * > + * @return > + * 0: If no feature enabled > + * Non-Zero: Bitmask of features enabled. plist is valid > + * > + */ > +static __rte_always_inline uint64_t > +rte_graph_feature_arc_has_any_feature(struct rte_graph_feature_arc *arc, > + rte_graph_feature_rt_list_t *plist) > +{ > + *plist = __atomic_load_n(&arc->active_feature_list, > __ATOMIC_RELAXED); > + > + return (__atomic_load_n(arc->feature_enable_bitmask + > (uint8_t)*plist, > + __ATOMIC_RELAXED)); > +} > + > +/** > + * Fast path API to check if provided feature is enabled on any interface/index > + * or not > + * > + * @param arc > + * Feature arc object > + * @param feature > + * Input rte_graph_feature_t that needs to be checked > + * @param[out] plist > + * Returns active list to caller which needs to be provided to other fast path > + * APIs > + * > + * @return > + * 1: If feature is enabled in arc > + * 0: If feature is not enabled in arc > + */ > +static __rte_always_inline int > +rte_graph_feature_arc_has_feature(struct rte_graph_feature_arc *arc, > + rte_graph_feature_t feature, > + rte_graph_feature_rt_list_t *plist) > +{ > + uint64_t bitmask = RTE_BIT64(feature); > + > + *plist = __atomic_load_n(&arc->active_feature_list, > __ATOMIC_RELAXED); > + > + return (bitmask & __atomic_load_n(arc->feature_enable_bitmask + > (uint8_t)*plist, > + __ATOMIC_RELAXED)); > +} > + > +/** > + * Prefetch feature arc fast path cache line > + * > + * @param arc > + * RTE_GRAPH feature arc object > + */ > +static __rte_always_inline void > +rte_graph_feature_arc_prefetch(struct rte_graph_feature_arc *arc) > +{ > + rte_prefetch0((void *)&arc->fast_path_variables); > +} > + > +/** > + * Prefetch feature related fast path cache line > + * > + * @param arc > + * RTE_GRAPH feature arc object > + * @param list > + * Pointer to runtime active feature list from > rte_graph_feature_arc_has_any_feature(); > + * @param feature > + * Pointer to feature object > + */ > +static __rte_always_inline void > +rte_graph_feature_arc_feature_prefetch(struct rte_graph_feature_arc *arc, > + const rte_graph_feature_rt_list_t list, > + rte_graph_feature_t feature) > +{ > + /* feature cache line */ > + if (likely(rte_graph_feature_is_valid(feature))) > + rte_prefetch0((void *)__rte_graph_feature_get(arc, feature, > list)); > +} > + > +/** > + * Prefetch feature data upfront. Perform sanity > + * > + * @param _arc > + * RTE_GRAPH feature arc object > + * @param list > + * Pointer to runtime active feature list from > rte_graph_feature_arc_has_any_feature(); > + * @param feature > + * Pointer to feature object returned from @ref > + * rte_graph_feature_arc_first_feature_get() > + * @param index > + * Interface/index > + */ > +static __rte_always_inline void > +rte_graph_feature_arc_data_prefetch(struct rte_graph_feature_arc *arc, > + const rte_graph_feature_rt_list_t list, > + rte_graph_feature_t feature, uint32_t index) > +{ > + if (likely(rte_graph_feature_is_valid(feature))) > + rte_prefetch0((void *)((uint8_t *)arc->features[list] + > + offsetof(struct rte_graph_feature, > feature_data_by_index) + > + (index * sizeof(rte_graph_feature_data_t)))); > +} > + > +/** > + * Fast path API to get first enabled feature on interface index > + * Typically required in arc->start_node so that from returned feature, > + * feature-data can be retrieved to steer packets > + * > + * @param arc > + * Feature arc object > + * @param list > + * Pointer to runtime active feature list from > + * rte_graph_feature_arc_has_any_feature() or > + * rte_graph_feature_arc_has_feature() > + * @param index > + * Interface Index > + * @param[out] feature > + * Pointer to rte_graph_feature_t. > + * > + * @return > + * 0. Success. feature field is valid > + * 1. Failure. feature field is invalid > + * > + */ > +static __rte_always_inline int > +rte_graph_feature_arc_first_feature_get(struct rte_graph_feature_arc *arc, > + const rte_graph_feature_rt_list_t list, > + uint32_t index, > + rte_graph_feature_t *feature) > +{ > + struct rte_graph_feature_list *feature_list = arc->feature_list[list]; > + > + *feature = feature_list->first_enabled_feature_by_index[index]; > + > + return rte_graph_feature_is_valid(*feature); > +} > + > +/** > + * Fast path API to get next enabled feature on interface index with provided > + * input feature > + * > + * @param arc > + * Feature arc object > + * @param list > + * Pointer to runtime active feature list from > + * rte_graph_feature_arc_has_any_feature() or > + * @param index > + * Interface Index > + * @param[in][out] feature > + * Pointer to rte_graph_feature_t. Input feature set to next enabled feature > + * after success return > + * @param[out] next_edge > + * Edge from current feature to next feature. Valid only if next feature is > valid > + * > + * @return > + * 0. Success. next enabled feature is valid. > + * 1. Failure. next enabled feature is invalid > + */ > +static __rte_always_inline int > +rte_graph_feature_arc_next_feature_get(struct rte_graph_feature_arc *arc, > + const rte_graph_feature_rt_list_t list, > + uint32_t index, > + rte_graph_feature_t *feature, > + rte_edge_t *next_edge) > +{ > + rte_graph_feature_data_t *feature_data = NULL; > + struct rte_graph_feature *f = NULL; > + > + if (likely(rte_graph_feature_is_valid(*feature))) { > + f = __rte_graph_feature_get(arc, *feature, list); > + feature_data = rte_graph_feature_data_get(arc, f, index); > + *feature = feature_data->next_enabled_feature; > + *next_edge = feature_data->next_edge; > + return (*feature == RTE_GRAPH_FEATURE_INVALID); > + } > + > + return 1; > +} > + > +/** > + * Set fields with respect to first enabled feature in an arc and return edge > + * Typically returned feature and interface index must be saved in rte_mbuf > + * structure to pass this information to next feature node > + * > + * @param arc > + * Feature arc object > + * @param list > + * Pointer to runtime active feature list from > rte_graph_feature_arc_has_any_feature(); > + * @param index > + * Index (of interface) > + * @param[out] gf > + * Pointer to rte_graph_feature_t. Valid if API returns Success > + * @param[out] edge > + * Edge to steer packet from arc->start_node to first enabled feature. Valid > + * only if API returns Success > + * > + * @return > + * 0: If valid feature is set by API > + * 1: If valid feature is NOT set by API > + */ > +static __rte_always_inline rte_graph_feature_t > +rte_graph_feature_arc_feature_set(struct rte_graph_feature_arc *arc, > + const rte_graph_feature_rt_list_t list, > + uint32_t index, > + rte_graph_feature_t *gf, > + rte_edge_t *edge) > +{ > + struct rte_graph_feature_list *feature_list = arc->feature_list[list]; > + struct rte_graph_feature_data *feature_data = NULL; > + struct rte_graph_feature *feature = NULL; > + rte_graph_feature_t f; > + > + /* reset */ > + *gf = RTE_GRAPH_FEATURE_INVALID; > + f = feature_list->first_enabled_feature_by_index[index]; > + > + if (unlikely(rte_graph_feature_is_valid(f))) { > + feature = __rte_graph_feature_get(arc, f, list); > + feature_data = rte_graph_feature_data_get(arc, feature, > index); > + *gf = f; > + *edge = feature_data->next_edge; > + return 0; > + } > + > + return 1; > +} > + > +/** > + * Get user data corresponding to current feature set by application in > + * rte_graph_feature_enable() > + * > + * @param arc > + * Feature arc object > + * @param list > + * Pointer to runtime active feature list from > rte_graph_feature_arc_has_any_feature(); > + * @param feature > + * Feature index > + * @param index > + * Interface index > + * > + * @return > + * UINT32_MAX: Failure > + * Valid user data: Success > + */ > +static __rte_always_inline uint32_t > +rte_graph_feature_user_data_get(struct rte_graph_feature_arc *arc, > + const rte_graph_feature_rt_list_t list, > + rte_graph_feature_t feature, > + uint32_t index) > +{ > + rte_graph_feature_data_t *fdata = NULL; > + struct rte_graph_feature *f = NULL; > + > + if (likely(rte_graph_feature_is_valid(feature))) { > + f = __rte_graph_feature_get(arc, feature, list); > + fdata = rte_graph_feature_data_get(arc, f, index); > + return fdata->user_data; > + } > + > + return UINT32_MAX; > +} > +#ifdef __cplusplus > +} > +#endif > +#endif > diff --git a/lib/graph/version.map b/lib/graph/version.map > index 2c83425ddc..82b2469fba 100644 > --- a/lib/graph/version.map > +++ b/lib/graph/version.map > @@ -52,3 +52,20 @@ DPDK_25 { > > local: *; > }; > + > +EXPERIMENTAL { > + global: > + > + # added in 24.11 > + rte_graph_feature_arc_init; > + rte_graph_feature_arc_create; > + rte_graph_feature_arc_lookup_by_name; > + rte_graph_feature_add; > + rte_graph_feature_enable; > + rte_graph_feature_validate; > + rte_graph_feature_disable; > + rte_graph_feature_lookup; > + rte_graph_feature_arc_destroy; > + rte_graph_feature_arc_cleanup; > + rte_graph_feature_arc_num_enabled_features; > +}; > -- > 2.43.0 ^ permalink raw reply [flat|nested] 46+ messages in thread
* RE: [RFC PATCH 1/3] graph: add feature arc support 2024-09-11 4:41 ` Kiran Kumar Kokkilagadda @ 2024-10-10 4:42 ` Nitin Saxena 0 siblings, 0 replies; 46+ messages in thread From: Nitin Saxena @ 2024-10-10 4:42 UTC (permalink / raw) To: Kiran Kumar Kokkilagadda, Jerin Jacob, Nithin Kumar Dabilpuram, Zhirun Yan Cc: dev, Nitin Saxena Hi Kiran, See my inline comments. Somehow I forgot to respond earlier Thanks, Nitin > -----Original Message----- > From: Kiran Kumar Kokkilagadda <kirankumark@marvell.com> > Sent: Wednesday, September 11, 2024 10:11 AM > To: Nitin Saxena <nsaxena@marvell.com>; Jerin Jacob <jerinj@marvell.com>; > Nithin Kumar Dabilpuram <ndabilpuram@marvell.com>; Zhirun Yan > <yanzhirun_163@163.com> > Cc: dev@dpdk.org; Nitin Saxena <nsaxena16@gmail.com> > Subject: RE: [RFC PATCH 1/3] graph: add feature arc support > > > > > -----Original Message----- > > From: Nitin Saxena <nsaxena@marvell.com> > > Sent: Saturday, September 7, 2024 1:01 PM > > To: Jerin Jacob <jerinj@marvell.com>; Kiran Kumar Kokkilagadda > > <kirankumark@marvell.com>; Nithin Kumar Dabilpuram > > <ndabilpuram@marvell.com>; Zhirun Yan <yanzhirun_163@163.com> > > Cc: dev@dpdk.org; Nitin Saxena <nsaxena16@gmail.com> > > Subject: [RFC PATCH 1/3] graph: add feature arc support > > > > add feature arc to allow dynamic steering of packets across graph nodes > > based on protocol features enabled on incoming or outgoing interface > > > > Signed-off-by: Nitin Saxena <nsaxena@marvell.com> > > --- > > lib/graph/graph_feature_arc.c | 959 +++++++++++++++++++++++ > > lib/graph/meson.build | 2 + > > lib/graph/rte_graph_feature_arc.h | 373 +++++++++ > > lib/graph/rte_graph_feature_arc_worker.h | 548 +++++++++++++ > > lib/graph/version.map | 17 + > > 5 files changed, 1899 insertions(+) > > create mode 100644 lib/graph/graph_feature_arc.c > > create mode 100644 lib/graph/rte_graph_feature_arc.h > > create mode 100644 lib/graph/rte_graph_feature_arc_worker.h > > > > diff --git a/lib/graph/graph_feature_arc.c b/lib/graph/graph_feature_arc.c > > new file mode 100644 > > index 0000000000..3b05bac137 > > --- /dev/null > > +++ b/lib/graph/graph_feature_arc.c > > @@ -0,0 +1,959 @@ > > +/* SPDX-License-Identifier: BSD-3-Clause > > + * Copyright(C) 2024 Marvell International Ltd. > > + */ > > + > > +#include "graph_private.h" > > +#include <rte_graph_feature_arc_worker.h> > > +#include <rte_malloc.h> > > + > > +#define __RTE_GRAPH_FEATURE_ARC_MAX 32 > > + > > +#define ARC_PASSIVE_LIST(arc) (arc->active_feature_list ^ 0x1) > > + > > +#define rte_graph_uint_cast(x) ((unsigned int)x) > > +#define feat_dbg graph_err > > + > > +rte_graph_feature_arc_main_t *__feature_arc_main; > > + > > +/* Make sure fast path cache line is compact */ > > +_Static_assert((offsetof(struct rte_graph_feature_arc, > slow_path_variables) > > + - offsetof(struct rte_graph_feature_arc, fast_path_variables)) > > + <= RTE_CACHE_LINE_SIZE); > > + > > + > > +static int > > +feature_lookup(struct rte_graph_feature_arc *arc, const char *feat_name, > > + struct rte_graph_feature_node_list **ffinfo, uint32_t *slot) > > +{ > > + struct rte_graph_feature_node_list *finfo = NULL; > > + const char *name; > > + > > + if (!feat_name) > > + return -1; > > + > > + if (slot) > > + *slot = 0; > > + > > + STAILQ_FOREACH(finfo, &arc->all_features, next_feature) { > > + RTE_VERIFY(finfo->feature_arc == arc); > > + name = rte_node_id_to_name(finfo->feature_node->id); > > + if (!strncmp(name, feat_name, RTE_GRAPH_NAMESIZE)) { > > + if (ffinfo) > > + *ffinfo = finfo; > > + return 0; > > + } > > + if (slot) > > + (*slot)++; > > + } > > + return -1; > > +} > > + > > +static int > > +feature_arc_node_info_lookup(struct rte_graph_feature_arc *arc, uint32_t > > feature_index, > > + struct rte_graph_feature_node_list **ppfinfo) > > +{ > > + struct rte_graph_feature_node_list *finfo = NULL; > > + uint32_t index = 0; > > + > > + if (!ppfinfo) > > + return -1; > > + > > + *ppfinfo = NULL; > > + STAILQ_FOREACH(finfo, &arc->all_features, next_feature) { > > + if (index == feature_index) { > > + if (finfo->node_index == feature_index) > > + return -1; > > + *ppfinfo = finfo; > > + } > > + index++; > > + } > > + if (feature_index && (index >= feature_index)) > > + return -1; > > + > > + return 0; > > +} > > + > > +static void > > +prepare_feature_arc(struct rte_graph_feature_arc *arc) > > +{ > > + struct rte_graph_feature_node_list *finfo = NULL; > > + uint32_t index = 0; > > + > > + STAILQ_FOREACH(finfo, &arc->all_features, next_feature) { > > + finfo->node_index = index; > > + index++; > > + } > > +} > > + > > +static int > > +feature_arc_lookup(rte_graph_feature_arc_t _arc) > > +{ > > + struct rte_graph_feature_arc *arc = rte_graph_feature_arc_get(_arc); > > + rte_graph_feature_arc_main_t *dm = __feature_arc_main; > > + uint32_t iter; > > + > > + if (!__feature_arc_main) > > + return -1; > > + > > + for (iter = 0; iter < dm->max_feature_arcs; iter++) { > > + if (dm->feature_arcs[iter] == > > RTE_GRAPH_FEATURE_ARC_INITIALIZER) > > + continue; > > + > > + if (arc == (rte_graph_feature_arc_get(dm- > > >feature_arcs[iter]))) > > + return 0; > > + } > > + return -1; > > +} > > + > > +static int > > +get_existing_edge(const char *arc_name, struct rte_node_register > > *parent_node, > > + struct rte_node_register *child_node, rte_edge_t *_edge) > > +{ > > + char **next_edges = NULL; > > + uint32_t count, i; > > + > > + RTE_SET_USED(arc_name); > > + > > + count = rte_node_edge_get(parent_node->id, NULL); > > + next_edges = malloc(count); > > + > > + if (!next_edges) > > + return -1; > > + > > + count = rte_node_edge_get(parent_node->id, next_edges); > > + for (i = 0; i < count; i++) { > > + if (strstr(child_node->name, next_edges[i])) { > > + feat_dbg("%s: Edge exists [%s[%u]: \"%s\"]", > > arc_name, > > + parent_node->name, i, child_node->name); > > + if (_edge) > > + *_edge = (rte_edge_t)i; > > + > > + free(next_edges); > > + return 0; > > + } > > + } > > + free(next_edges); > > + > > + return -1; > > +} > > + > > +static int > > +connect_graph_nodes(struct rte_node_register *parent_node, struct > > rte_node_register *child_node, > > + rte_edge_t *_edge, char *arc_name) > > +{ > > + const char *next_node = NULL; > > + rte_edge_t edge; > > + > > + if (!get_existing_edge(arc_name, parent_node, child_node, &edge)) { > > + feat_dbg("%s: add_feature: Edge reused [%s[%u]: \"%s\"]", > > arc_name, > > + parent_node->name, edge, child_node->name); > > + > > + if (_edge) > > + *_edge = edge; > > + > > + return 0; > > + } > > + > > + /* Node to be added */ > > + next_node = child_node->name; > > + > > + edge = rte_node_edge_update(parent_node->id, > > RTE_EDGE_ID_INVALID, &next_node, 1); > > + > > + if (edge == RTE_EDGE_ID_INVALID) { > > + graph_err("edge invalid"); > > + return -1; > > + } > > + edge = rte_node_edge_count(parent_node->id) - 1; > > + > > + feat_dbg("%s: add_feature: edge added [%s[%u]: \"%s\"]", arc_name, > > parent_node->name, edge, > > + child_node->name); > > + > > + if (_edge) > > + *_edge = edge; > > + > > + return 0; > > +} > > + > > +static int > > +feature_arc_init(rte_graph_feature_arc_main_t **pfl, uint32_t > > max_feature_arcs) > > +{ > > + rte_graph_feature_arc_main_t *pm = NULL; > > + uint32_t i; > > + size_t sz; > > + > > + if (!pfl) > > + return -1; > > + > > + sz = sizeof(rte_graph_feature_arc_main_t) + > > + (sizeof(pm->feature_arcs[0]) * max_feature_arcs); > > + > > + pm = malloc(sz); > > + if (!pm) > > + return -1; > > + > > + memset(pm, 0, sz); > > + > > + for (i = 0; i < max_feature_arcs; i++) > > + pm->feature_arcs[i] = > > RTE_GRAPH_FEATURE_ARC_INITIALIZER; > > + > > + pm->max_feature_arcs = max_feature_arcs; > > + > > + *pfl = pm; > > + > > + return 0; > > +} > > + > > +int > > +rte_graph_feature_arc_init(int max_feature_arcs) > > +{ > > + if (!max_feature_arcs) > > + return -1; > > + > > + if (__feature_arc_main) > > + return -1; > > + > > + return feature_arc_init(&__feature_arc_main, max_feature_arcs); > > +} > > + > > +static void > > +feature_arc_list_reset(struct rte_graph_feature_arc *arc, uint32_t > list_index) > > +{ > > + rte_graph_feature_data_t *fdata = NULL; > > + rte_graph_feature_list_t *list = NULL; > > + struct rte_graph_feature *feat = NULL; > > + uint32_t i, j; > > + > > + list = arc->feature_list[list_index]; > > + feat = arc->features[list_index]; > > + > > + /*Initialize variables*/ > > + memset(feat, 0, arc->feature_size); > > + memset(list, 0, arc->feature_list_size); > > + > > + /* Initialize feature and feature_data */ > > + for (i = 0; i < arc->max_features; i++) { > > + feat = __rte_graph_feature_get(arc, i, list_index); > > + feat->this_feature_index = i; > > + > > + for (j = 0; j < arc->max_indexes; j++) { > > + fdata = rte_graph_feature_data_get(arc, feat, j); > > + fdata->next_enabled_feature = > > RTE_GRAPH_FEATURE_INVALID; > > + fdata->next_edge = UINT16_MAX; > > + fdata->user_data = UINT32_MAX; > > + } > > + } > > + > > + for (i = 0; i < arc->max_indexes; i++) > > + list->first_enabled_feature_by_index[i] = > > RTE_GRAPH_FEATURE_INVALID; > > +} > > + > > +static int > > +feature_arc_list_init(struct rte_graph_feature_arc *arc, const char > > *flist_name, > > + rte_graph_feature_list_t **pplist, > > + struct rte_graph_feature **ppfeature, uint32_t > > list_index) > > +{ > > + char fname[2 * RTE_GRAPH_FEATURE_ARC_NAMELEN]; > > + size_t list_size, feat_size, fdata_size; > > + rte_graph_feature_list_t *list = NULL; > > + struct rte_graph_feature *feat = NULL; > > + > > + list_size = sizeof(list->first_enabled_feature_by_index[0]) * arc- > > >max_indexes; > > + > > + list = rte_malloc(flist_name, list_size, RTE_CACHE_LINE_SIZE); > > + if (!list) > > + return -ENOMEM; > > + > > + fdata_size = arc->max_indexes * sizeof(rte_graph_feature_data_t); > > + > > + /* Let one feature capture complete cache lines */ > > + feat_size = RTE_ALIGN_CEIL(sizeof(struct rte_graph_feature) + > > fdata_size, > > + RTE_CACHE_LINE_SIZE); > > + > > + snprintf(fname, sizeof(fname), "%s-%s", arc->feature_arc_name, > > "feat"); > > + > > + feat = rte_malloc(fname, feat_size * arc->max_features, > > RTE_CACHE_LINE_SIZE); > > + if (!feat) { > > + rte_free(list); > > + return -ENOMEM; > > + } > > + arc->feature_size = feat_size; > > + arc->feature_data_size = fdata_size; > > + arc->feature_list_size = list_size; > > + > > + /* Initialize list */ > > + list->indexed_by_features = feat; > > + *pplist = list; > > + *ppfeature = feat; > > + > > + feature_arc_list_reset(arc, list_index); > > + > > + return 0; > > +} > > + > > +static void > > +feature_arc_list_destroy(rte_graph_feature_list_t *list) > > +{ > > + rte_free(list->indexed_by_features); > Do you need to free individual rte_graph_feature here, that is allocated in > arc_list_init? Nitin> It seems correct to me. feature_arc_list_destroy() frees all memory allocated in feature_arc_list_init(). So feature_arc_list_destroy() is calling rte_free() for every rte_malloc() happened in feature_arc_list_init(). To make it clear, I have refactor the function and has added appropriate comment from v2 patch set onwards > > > + rte_free(list); > > +} > > + > > +int > > +rte_graph_feature_arc_create(const char *feature_arc_name, int > > max_features, int max_indexes, > > + struct rte_node_register *start_node, > > rte_graph_feature_arc_t *_arc) > > +{ > > + char name[2 * RTE_GRAPH_FEATURE_ARC_NAMELEN]; > > + rte_graph_feature_arc_main_t *dfm = NULL; > > + struct rte_graph_feature_arc *arc = NULL; > > + struct rte_graph_feature_data *gfd = NULL; > > + struct rte_graph_feature *df = NULL; > > + uint32_t iter, j, arc_index; > > + size_t sz; > > + > > + if (!_arc) > > + return -1; > > + > > + if (max_features < 2) > > + return -1; > > + > > + if (!start_node) > > + return -1; > > + > > + if (!feature_arc_name) > > + return -1; > > + > > + if (max_features > RTE_GRAPH_FEATURE_MAX_PER_ARC) { > > + graph_err("Invalid max features: %u", max_features); > > + return -1; > > + } > > + > > + /* > > + * Application hasn't called rte_graph_feature_arc_init(). Initialize > with > > + * default values > > + */ > > + if (!__feature_arc_main) { > > + if > > (rte_graph_feature_arc_init((int)__RTE_GRAPH_FEATURE_ARC_MAX) < 0) { > > + graph_err("rte_graph_feature_arc_init() failed"); > > + return -1; > > + } > > + } > > + > > + dfm = __feature_arc_main; > > + > > + /* threshold check */ > > + if (dfm->num_feature_arcs > (dfm->max_feature_arcs - 1)) { > > + graph_err("max threshold for num_feature_arcs: %d > > reached", > > + dfm->max_feature_arcs - 1); > > + return -1; > > + } > > + /* Find the free slot for feature arc */ > > + for (iter = 0; iter < dfm->max_feature_arcs; iter++) { > > + if (dfm->feature_arcs[iter] == > > RTE_GRAPH_FEATURE_ARC_INITIALIZER) > > + break; > > + } > > + arc_index = iter; > > + > > + if (arc_index >= dfm->max_feature_arcs) { > > + graph_err("No free slot found for num_feature_arc"); > > + return -1; > > + } > > + > > + /* This should not happen */ > > + RTE_VERIFY(dfm->feature_arcs[arc_index] == > > RTE_GRAPH_FEATURE_ARC_INITIALIZER); > > + > > + /* size of feature arc + feature_bit_mask_by_index */ > > + sz = sizeof(*arc) + (sizeof(uint64_t) * max_indexes); > > + > > + arc = rte_malloc(feature_arc_name, sz, RTE_CACHE_LINE_SIZE); > > + > > + if (!arc) { > > + graph_err("malloc failed for feature_arc_create()"); > > + return -1; > > + } > > + > > + memset(arc, 0, sz); > > + > > + /* Initialize rte_graph port group fixed variables */ > > + STAILQ_INIT(&arc->all_features); > > + strncpy(arc->feature_arc_name, feature_arc_name, > > RTE_GRAPH_FEATURE_ARC_NAMELEN - 1); > > + arc->feature_arc_main = (void *)dfm; > > + arc->start_node = start_node; > > + arc->max_features = max_features; > > + arc->max_indexes = max_indexes; > > + > > + snprintf(name, sizeof(name), "%s-%s", feature_arc_name, "flist0"); > > + > > + if (feature_arc_list_init(arc, name, &arc->feature_list[0], &arc- > > >features[0], 0) < 0) { > > + rte_free(arc); > > + graph_err("feature_arc_list_init(0) failed"); > > + return -1; > > + } > > + snprintf(name, sizeof(name), "%s-%s", feature_arc_name, "flist1"); > > + > > + if (feature_arc_list_init(arc, name, &arc->feature_list[1], &arc- > > >features[1], 1) < 0) { > > + feature_arc_list_destroy(arc->feature_list[0]); > > + graph_err("feature_arc_list_init(1) failed"); > > + return -1; > > + } > > + > > + for (iter = 0; iter < arc->max_features; iter++) { > > + df = rte_graph_feature_get(arc, iter); > > + for (j = 0; j < arc->max_indexes; j++) { > > + gfd = rte_graph_feature_data_get(arc, df, j); > > + gfd->next_enabled_feature = > > RTE_GRAPH_FEATURE_INVALID; > > + } > > + } > > + arc->feature_arc_index = arc_index; > > + dfm->feature_arcs[arc->feature_arc_index] = > > (rte_graph_feature_arc_t)arc; > > + dfm->num_feature_arcs++; > > + > > + if (_arc) > > + *_arc = (rte_graph_feature_arc_t)arc; > > + > > + return 0; > > +} > > + > > +int > > +rte_graph_feature_add(rte_graph_feature_arc_t _arc, struct > > rte_node_register *feature_node, > > + const char *after_feature, const char *before_feature) > > +{ > > + struct rte_graph_feature_node_list *after_finfo = NULL, *before_finfo > > = NULL; > > + struct rte_graph_feature_node_list *temp = NULL, *finfo = NULL; > > + struct rte_graph_feature_arc *arc = rte_graph_feature_arc_get(_arc); > > + uint32_t slot, add_flag; > > + rte_edge_t edge = -1; > > + > > + RTE_VERIFY(arc->feature_arc_main == __feature_arc_main); > > + > > + if (feature_arc_lookup(_arc)) { > > + graph_err("invalid feature arc: 0x%016" PRIx64, > > (uint64_t)_arc); > > + return -1; > > + } > > + > > + if (arc->runtime_enabled_features) { > > + graph_err("adding features after enabling any one of them is > > not supported"); > > + return -1; > > + } > > + > > + if ((after_feature != NULL) && (before_feature != NULL) && > > + (after_feature == before_feature)) { > > + graph_err("after_feature and before_feature are same > > '%s:%s]", after_feature, > > + before_feature); > > + return -1; > > + } > > + > > + if (!feature_node) { > > + graph_err("feature_node: %p invalid", feature_node); > > + return -1; > > + } > > + > > + arc = rte_graph_feature_arc_get(_arc); > > + > > + if (feature_node->id == RTE_NODE_ID_INVALID) { > > + graph_err("Invalid node: %s", feature_node->name); > > + return -1; > > + } > > + > > + if (!feature_lookup(arc, feature_node->name, &finfo, &slot)) { > > + graph_err("%s feature already added", feature_node->name); > > + return -1; > > + } > > + > > + if (slot >= RTE_GRAPH_FEATURE_MAX_PER_ARC) { > > + graph_err("Max slot %u reached for feature addition", slot); > > + return -1; > > + } > > + > > + if (strstr(feature_node->name, arc->start_node->name)) { > > + graph_err("Feature %s cannot point to itself: %s", > > feature_node->name, > > + arc->start_node->name); > > + return -1; > > + } > > + > > + if (connect_graph_nodes(arc->start_node, feature_node, &edge, arc- > > >feature_arc_name)) { > > + graph_err("unable to connect %s -> %s", arc->start_node- > > >name, feature_node->name); > > + return -1; > > + } > > + > > + finfo = malloc(sizeof(*finfo)); > > + if (!finfo) > > + return -1; > > + > > + memset(finfo, 0, sizeof(*finfo)); > > + > > + finfo->feature_arc = (void *)arc; > > + finfo->feature_node = feature_node; > > + finfo->edge_to_this_feature = edge; > > + > > + /* Check for before and after constraints */ > > + if (before_feature) { > > + /* before_feature sanity */ > > + if (feature_lookup(arc, before_feature, &before_finfo, NULL)) > > + SET_ERR_JMP(EINVAL, finfo_free, > > + "Invalid before feature name: %s", > > before_feature); > > + > > + if (!before_finfo) > > + SET_ERR_JMP(EINVAL, finfo_free, > > + "before_feature %s does not exist", > > before_feature); > > + > > + /* > > + * Starting from 0 to before_feature, continue connecting > > edges > > + */ > > + add_flag = 1; > > + STAILQ_FOREACH(temp, &arc->all_features, next_feature) { > > + /* > > + * As soon as we see before_feature. stop adding > > edges > > + */ > > + if (!strncmp(temp->feature_node->name, > > before_feature, > > + RTE_GRAPH_NAMESIZE)) > > + if (!connect_graph_nodes(finfo- > > >feature_node, temp->feature_node, > > + &edge, arc- > > >feature_arc_name)) > > + add_flag = 0; > > + > > + if (add_flag) > > + connect_graph_nodes(temp->feature_node, > > finfo->feature_node, NULL, > > + arc->feature_arc_name); > > + } > > + } > > + > > + if (after_feature) { > > + if (feature_lookup(arc, after_feature, &after_finfo, NULL)) > > + SET_ERR_JMP(EINVAL, finfo_free, > > + "Invalid after feature_name %s", > > after_feature); > > + > > + if (!after_finfo) > > + SET_ERR_JMP(EINVAL, finfo_free, > > + "after_feature %s does not exist", > > after_feature); > > + > > + /* Starting from after_feature to end continue connecting > > edges */ > > + add_flag = 0; > > + STAILQ_FOREACH(temp, &arc->all_features, next_feature) { > > + /* We have already seen after_feature now */ > > + if (add_flag) > > + /* Add all features as next node to current > > feature*/ > > + connect_graph_nodes(finfo->feature_node, > > temp->feature_node, NULL, > > + arc->feature_arc_name); > > + > > + /* as soon as we see after_feature. start adding edges > > + * from next iteration > > + */ > > + if (!strncmp(temp->feature_node->name, > > after_feature, RTE_GRAPH_NAMESIZE)) > > + /* connect after_feature to this feature */ > > + if (!connect_graph_nodes(temp- > > >feature_node, finfo->feature_node, > > + &edge, arc- > > >feature_arc_name)) > > + add_flag = 1; > > + } > > + > > + /* add feature next to after_feature */ > > + STAILQ_INSERT_AFTER(&arc->all_features, after_finfo, finfo, > > next_feature); > > + } else { > > + if (before_finfo) { > > + after_finfo = NULL; > > + STAILQ_FOREACH(temp, &arc->all_features, > > next_feature) { > > + if (before_finfo == temp) { > > + if (after_finfo) > > + STAILQ_INSERT_AFTER(&arc- > > >all_features, after_finfo, > > + finfo, > > next_feature); > > + else > > + STAILQ_INSERT_HEAD(&arc- > > >all_features, finfo, > > + > > next_feature); > > + > > + return 0; > > + } > > + after_finfo = temp; > > + } > > + } else { > > + STAILQ_INSERT_TAIL(&arc->all_features, finfo, > > next_feature); > > + } > > + } > > + > > + return 0; > > + > > +finfo_free: > > + free(finfo); > > + > > + return -1; > > +} > > + > > +int > > +rte_graph_feature_lookup(rte_graph_feature_arc_t _arc, const char > > *feature_name, > > + rte_graph_feature_t *feat) > > +{ > > + struct rte_graph_feature_arc *arc = rte_graph_feature_arc_get(_arc); > > + struct rte_graph_feature_node_list *finfo = NULL; > > + uint32_t slot; > > + > > + if (!feature_lookup(arc, feature_name, &finfo, &slot)) { > > + *feat = (rte_graph_feature_t) slot; > > + return 0; > > + } > > + > > + return -1; > > +} > > + > > +int > > +rte_graph_feature_validate(rte_graph_feature_arc_t _arc, uint32_t index, > > const char *feature_name, > > + int is_enable_disable) > > +{ > > + struct rte_graph_feature_arc *arc = rte_graph_feature_arc_get(_arc); > > + struct rte_graph_feature_node_list *finfo = NULL; > > + struct rte_graph_feature *gf = NULL; > > + uint32_t slot; > > + > > + /* validate _arc */ > > + if (arc->feature_arc_main != __feature_arc_main) { > > + graph_err("invalid feature arc: 0x%016" PRIx64, > > (uint64_t)_arc); > > + return -EINVAL; > > + } > > + > > + /* validate index */ > > + if (index >= arc->max_indexes) { > > + graph_err("%s: Invalid provided index: %u >= %u configured", > > arc->feature_arc_name, > > + index, arc->max_indexes); > > + return -1; > > + } > > + > > + /* validate feature_name is already added or not */ > > + if (feature_lookup(arc, feature_name, &finfo, &slot)) { > > + graph_err("%s: No feature %s added", arc- > > >feature_arc_name, feature_name); > > + return -EINVAL; > > + } > > + > > + if (!finfo) { > > + graph_err("%s: No feature: %s found", arc- > > >feature_arc_name, feature_name); > > + return -EINVAL; > > + } > > + > > + /* slot should be in valid range */ > > + if (slot >= arc->max_features) { > > + graph_err("%s/%s: Invalid free slot %u(max=%u) for feature", > > arc->feature_arc_name, > > + feature_name, slot, arc->max_features); > > + return -EINVAL; > > + } > > + > > + /* slot should be in range of 0 - 63 */ > > + if (slot > (RTE_GRAPH_FEATURE_MAX_PER_ARC - 1)) { > > + graph_err("%s/%s: Invalid slot: %u", arc->feature_arc_name, > > + feature_name, slot); > > + return -EINVAL; > > + } > > + > > + if (finfo->node_index != slot) { > > + graph_err("%s/%s: feature lookup slot mismatch with finfo > > index: %u and lookup slot: %u", > > + arc->feature_arc_name, feature_name, finfo- > > >node_index, slot); > > + return -1; > > + } > > + > > + /* Get feature from active list */ > > + gf = __rte_graph_feature_get(arc, slot, ARC_PASSIVE_LIST(arc)); > > + if (gf->this_feature_index != slot) { > > + graph_err("%s: %s received feature_index: %u does not > match > > with saved feature_index: %u", > > + arc->feature_arc_name, feature_name, slot, gf- > > >this_feature_index); > > + return -1; > > + } > > + > > + if (is_enable_disable && (arc->feature_bit_mask_by_index[index] & > > + RTE_BIT64(slot))) { > > + graph_err("%s: %s already enabled on index: %u", > > + arc->feature_arc_name, feature_name, index); > > + return -1; > > + } > > + > > + if (!is_enable_disable && !arc->runtime_enabled_features) { > > + graph_err("%s: No feature enabled to disable", arc- > > >feature_arc_name); > > + return -1; > > + } > > + > > + if (!is_enable_disable && !(arc->feature_bit_mask_by_index[index] & > > RTE_BIT64(slot))) { > > + graph_err("%s: %s not enabled in bitmask for index: %u", > > + arc->feature_arc_name, feature_name, index); > > + return -1; > > + } > > + > > + return 0; > > +} > > + > > +static void > > +copy_fastpath_user_data(struct rte_graph_feature_arc *arc, uint16_t > > dest_list_index, > > + uint16_t src_list_index) > > +{ > > + rte_graph_feature_data_t *sgfd = NULL, *dgfd = NULL; > > + struct rte_graph_feature *sgf = NULL, *dgf = NULL; > > + uint32_t i, j; > > + > > + for (i = 0; i < arc->max_features; i++) { > > + sgf = __rte_graph_feature_get(arc, i, src_list_index); > > + dgf = __rte_graph_feature_get(arc, i, dest_list_index); > > + for (j = 0; j < arc->max_indexes; j++) { > > + sgfd = rte_graph_feature_data_get(arc, sgf, j); > > + dgfd = rte_graph_feature_data_get(arc, dgf, j); > > + dgfd->user_data = sgfd->user_data; > > + } > > + } > > +} > > + > > +static void > > +refill_feature_fastpath_data(struct rte_graph_feature_arc *arc, uint16_t > > list_index) > > +{ > > + struct rte_graph_feature_node_list *finfo = NULL, *prev_finfo = NULL; > > + struct rte_graph_feature_data *gfd = NULL, *prev_gfd = NULL; > > + struct rte_graph_feature *gf = NULL, *prev_gf = NULL; > > + rte_graph_feature_list_t *flist = NULL; > > + uint32_t fi, di, prev_fi; > > + uint64_t bitmask; > > + rte_edge_t edge; > > + > > + flist = arc->feature_list[list_index]; > > + > > + for (di = 0; di < arc->max_indexes; di++) { > > + bitmask = arc->feature_bit_mask_by_index[di]; > > + prev_fi = RTE_GRAPH_FEATURE_INVALID; > > + /* for each feature set for index, set fast path data */ > > + while (rte_bsf64_safe(bitmask, &fi)) { > > + gf = __rte_graph_feature_get(arc, fi, list_index); > > + gfd = rte_graph_feature_data_get(arc, gf, di); > > + feature_arc_node_info_lookup(arc, fi, &finfo); > > + > > + /* If previous feature_index was valid in last loop */ > > + if (prev_fi != RTE_GRAPH_FEATURE_INVALID) { > > + prev_gf = __rte_graph_feature_get(arc, > > prev_fi, list_index); > > + prev_gfd = rte_graph_feature_data_get(arc, > > prev_gf, di); > > + /* > > + * Get edge of previous feature node > > connecting to this feature node > > + */ > > + feature_arc_node_info_lookup(arc, prev_fi, > > &prev_finfo); > > + if (!get_existing_edge(arc->feature_arc_name, > > + prev_finfo->feature_node, > > + finfo->feature_node, > > &edge)) { > > + feat_dbg("[%s/%s(%2u)/idx:%2u]: > > %s[%u] = %s", > > + arc->feature_arc_name, > > + prev_finfo->feature_node- > > >name, prev_fi, di, > > + prev_finfo->feature_node- > > >name, > > + edge, finfo->feature_node- > > >name); > > + /* Copy feature index for next > > iteration*/ > > + gfd->next_edge = edge; > > + prev_fi = fi; > > + /* > > + * Fill current feature as next enabled > > + * feature to previous one > > + */ > > + prev_gfd->next_enabled_feature = fi; > > + } else { > > + /* Should not fail */ > > + RTE_VERIFY(0); > > + } > > + } > > + /* On first feature edge of the node to be added */ > > + if (fi == rte_bsf64(arc- > > >feature_bit_mask_by_index[di])) { > > + if (!get_existing_edge(arc->feature_arc_name, > > arc->start_node, > > + finfo->feature_node, > > + &edge)) { > > + feat_dbg("[%s/%s/%2u/idx:%2u]: 1st > > feat %s[%u] = %s", > > + arc->feature_arc_name, > > + arc->start_node->name, fi, di, > > + arc->start_node->name, > > edge, > > + finfo->feature_node->name); > > + /* Copy feature index for next > > iteration*/ > > + gfd->next_edge = edge; > > + prev_fi = fi; > > + /* Set first feature set array for > > index*/ > > + flist- > > >first_enabled_feature_by_index[di] = fi; > > + } else { > > + /* Should not fail */ > > + RTE_VERIFY(0); > > + } > > + } > > + /* Clear current feature index */ > > + bitmask &= ~RTE_BIT64(fi); > > + } > > + } > > +} > > + > > +int > > +rte_graph_feature_enable(rte_graph_feature_arc_t _arc, uint32_t index, > > const > > + char *feature_name, int32_t user_data) > > +{ > > + struct rte_graph_feature_arc *arc = rte_graph_feature_arc_get(_arc); > > + struct rte_graph_feature_node_list *finfo = NULL; > > + struct rte_graph_feature_data *gfd = NULL; > > + rte_graph_feature_rt_list_t passive_list; > > + struct rte_graph_feature *gf = NULL; > > + uint64_t fp_bitmask; > > + uint32_t slot; > > + > > + if (rte_graph_feature_validate(_arc, index, feature_name, 1)) > > + return -1; > > + > > + /** This should not fail as validate() has passed */ > > + if (feature_lookup(arc, feature_name, &finfo, &slot)) > > + RTE_VERIFY(0); > > + > > + if (!arc->runtime_enabled_features) > > + prepare_feature_arc(arc); > > + > > + passive_list = ARC_PASSIVE_LIST(arc); > > + > > + gf = __rte_graph_feature_get(arc, slot, passive_list); > > + gfd = rte_graph_feature_data_get(arc, gf, index); > > + > > + feat_dbg("%s/%s: Enabling feature on list: %u for index: %u at feature > > slot %u", > > + arc->feature_arc_name, feature_name, passive_list, index, > > slot); > > + > > + /* Reset feature list */ > > + feature_arc_list_reset(arc, passive_list); > > + > > + /* Copy user-data */ > > + copy_fastpath_user_data(arc, passive_list, arc->active_feature_list); > > + > > + /* Set current user-data */ > > + gfd->user_data = user_data; > > + > > + /* Set bitmask in control path bitmask */ > > + rte_bit_relaxed_set64(rte_graph_uint_cast(slot), &arc- > > >feature_bit_mask_by_index[index]); > > + refill_feature_fastpath_data(arc, passive_list); > > + > > + /* Set fast path enable bitmask */ > > + fp_bitmask = __atomic_load_n(&arc- > > >feature_enable_bitmask[passive_list], __ATOMIC_RELAXED); > > + fp_bitmask |= RTE_BIT64(slot); > > + __atomic_store(&arc->feature_enable_bitmask[passive_list], > > &fp_bitmask, __ATOMIC_RELAXED); > > + > > + /* Slow path updates */ > > + arc->runtime_enabled_features++; > > + > > + /* Increase feature node info reference count */ > > + finfo->ref_count++; > > + > > + /* Store release semantics for active_list update */ > > + __atomic_store(&arc->active_feature_list, &passive_list, > > __ATOMIC_RELEASE); > > + > > + return 0; > > +} > > + > > +int > > +rte_graph_feature_disable(rte_graph_feature_arc_t _arc, uint32_t index, > > const char *feature_name) > > +{ > > + struct rte_graph_feature_arc *arc = rte_graph_feature_arc_get(_arc); > > + struct rte_graph_feature_data *gfd = NULL; > > + struct rte_graph_feature_node_list *finfo = NULL; > > + rte_graph_feature_rt_list_t passive_list; > > + struct rte_graph_feature *gf = NULL; > > + uint32_t slot; > > + > > + if (rte_graph_feature_validate(_arc, index, feature_name, 0)) > > + return -1; > > + > > + if (feature_lookup(arc, feature_name, &finfo, &slot)) > > + return -1; > > + > > + passive_list = ARC_PASSIVE_LIST(arc); > > + > > + gf = __rte_graph_feature_get(arc, slot, passive_list); > > + gfd = rte_graph_feature_data_get(arc, gf, index); > > + > > + feat_dbg("%s/%s: Disabling feature for index: %u at feature slot %u", > > arc->feature_arc_name, > > + feature_name, index, slot); > > + > > + rte_bit_relaxed_clear64(rte_graph_uint_cast(slot), &arc- > > >feature_bit_mask_by_index[index]); > > + > > + /* Set fast path enable bitmask */ > > + arc->feature_enable_bitmask[passive_list] &= ~(RTE_BIT64(slot)); > > + > > + /* Reset feature list */ > > + feature_arc_list_reset(arc, passive_list); > > + > > + /* Copy user-data */ > > + copy_fastpath_user_data(arc, passive_list, arc->active_feature_list); > > + > > + /* Reset current user-data */ > > + gfd->user_data = ~0; > > + > > + refill_feature_fastpath_data(arc, passive_list); > > + > > + finfo->ref_count--; > > + arc->runtime_enabled_features--; > > + > > + /* Store release semantics for active_list update */ > > + __atomic_store(&arc->active_feature_list, &passive_list, > > __ATOMIC_RELEASE); > > + > > + return 0; > > +} > > + > > +int > > +rte_graph_feature_arc_destroy(rte_graph_feature_arc_t _arc) > > +{ > > + struct rte_graph_feature_arc *arc = rte_graph_feature_arc_get(_arc); > > + rte_graph_feature_arc_main_t *dm = __feature_arc_main; > > + struct rte_graph_feature_node_list *node_info = NULL; > > + > > + while (!STAILQ_EMPTY(&arc->all_features)) { > > + node_info = STAILQ_FIRST(&arc->all_features); > > + STAILQ_REMOVE_HEAD(&arc->all_features, next_feature); > > + free(node_info); > > + } > > + feature_arc_list_destroy(arc->feature_list[0]); > > + feature_arc_list_destroy(arc->feature_list[1]); > > + rte_free(arc->features[0]); > > + rte_free(arc->features[1]); > > + > > + dm->feature_arcs[arc->feature_arc_index] = > > RTE_GRAPH_FEATURE_ARC_INITIALIZER; > > + > > + rte_free(arc); > > + return 0; > > +} > > + > > +int > > +rte_graph_feature_arc_cleanup(void) > > +{ > > + rte_graph_feature_arc_main_t *dm = __feature_arc_main; > > + uint32_t iter; > > + > > + if (!__feature_arc_main) > > + return -1; > > + > > + for (iter = 0; iter < dm->max_feature_arcs; iter++) { > > + if (dm->feature_arcs[iter] == > > RTE_GRAPH_FEATURE_ARC_INITIALIZER) > > + continue; > > + > > + rte_graph_feature_arc_destroy((rte_graph_feature_arc_t)dm- > > >feature_arcs[iter]); > > + } > > + free(dm); > > + > > + __feature_arc_main = NULL; > > + > > + return 0; > > +} > > + > > +int > > +rte_graph_feature_arc_lookup_by_name(const char *arc_name, > > rte_graph_feature_arc_t *_arc) > > +{ > > + rte_graph_feature_arc_main_t *dm = __feature_arc_main; > > + struct rte_graph_feature_arc *arc = NULL; > > + uint32_t iter; > > + > > + if (!__feature_arc_main) > > + return -1; > > + > > + for (iter = 0; iter < dm->max_feature_arcs; iter++) { > > + if (dm->feature_arcs[iter] == > > RTE_GRAPH_FEATURE_ARC_INITIALIZER) > > + continue; > > + > > + arc = rte_graph_feature_arc_get(dm->feature_arcs[iter]); > > + > > + if (strstr(arc_name, arc->feature_arc_name)) { > > + if (_arc) > > + *_arc = (rte_graph_feature_arc_t)arc; > > + return 0; > > + } > > + } > > + > > + return -1; > > +} > > + > > +int > > +rte_graph_feature_arc_num_enabled_features(rte_graph_feature_arc_t > > _arc) > > +{ > > + struct rte_graph_feature_arc *arc = rte_graph_feature_arc_get(_arc); > > + > > + return arc->runtime_enabled_features; > > +} > > + > > + > > diff --git a/lib/graph/meson.build b/lib/graph/meson.build > > index 0cb15442ab..d916176fb7 100644 > > --- a/lib/graph/meson.build > > +++ b/lib/graph/meson.build > > @@ -14,11 +14,13 @@ sources = files( > > 'graph_debug.c', > > 'graph_stats.c', > > 'graph_populate.c', > > + 'graph_feature_arc.c', > > 'graph_pcap.c', > > 'rte_graph_worker.c', > > 'rte_graph_model_mcore_dispatch.c', > > ) > > headers = files('rte_graph.h', 'rte_graph_worker.h') > > +headers += files('rte_graph_feature_arc.h', > 'rte_graph_feature_arc_worker.h') > > indirect_headers += files( > > 'rte_graph_model_mcore_dispatch.h', > > 'rte_graph_model_rtc.h', > > diff --git a/lib/graph/rte_graph_feature_arc.h > > b/lib/graph/rte_graph_feature_arc.h > > new file mode 100644 > > index 0000000000..e3bf4eb73d > > --- /dev/null > > +++ b/lib/graph/rte_graph_feature_arc.h > > @@ -0,0 +1,373 @@ > > +/* SPDX-License-Identifier: BSD-3-Clause > > + * Copyright(C) 2024 Marvell International Ltd. > > + */ > > + > > +#ifndef _RTE_GRAPH_FEATURE_ARC_H_ > > +#define _RTE_GRAPH_FEATURE_ARC_H_ > > + > > +#include <assert.h> > > +#include <errno.h> > > +#include <signal.h> > > +#include <stddef.h> > > +#include <stdint.h> > > +#include <stdio.h> > > +#include <stdlib.h> > > +#include <string.h> > > + > > +#include <rte_common.h> > > +#include <rte_compat.h> > > +#include <rte_debug.h> > > +#include <rte_graph.h> > > +#include <rte_graph_worker.h> > > + > > +#ifdef __cplusplus > > +extern "C" { > > +#endif > > + > > +/** > > + * @file > > + * > > + * rte_graph_feature_arc.h > > + * > > + * Define APIs and structures/variables with respect to feature arc > > + * > > + * - Feature arc(s) > > + * - Feature(s) > > + * > > + * A feature arc represents an ordered list of features/protocol-nodes at a > > + * given networking layer. Feature arc provides a high level abstraction to > > + * connect various *rte_graph* nodes, designated as *feature nodes*, and > > + * allowing steering of packets across these feature nodes fast path > > processing > > + * in a generic manner. In a typical network stack, often a protocol or > feature > > + * must be first enabled on a given interface, before any packet is steered > > + * towards it for feature processing. For eg: incoming IPv4 packets are sent > to > > + * routing sub-system only after a valid IPv4 address is assigned to the > > + * received interface. In other words, often packets needs to be steered > across > > + * features not based on the packet content but based on whether a > feature is > > + * enable or disable on a given incoming/outgoing interface. Feature arc > > + * provides mechanism to enable/disable feature(s) on each interface at > > runtime > > + * and allow seamless packet steering across runtime enabled feature > nodes > > in > > + * fast path. > > + * > > + * Feature arc also provides a way to steer packets from standard nodes to > > + * custom/user-defined *feature nodes* without any change in standard > > node's > > + * fast path functions > > + * > > + * On a given interface multiple feature(s) might be enabled in a particular > > + * feature arc. For instance, both "ipv4-output" and "IPsec policy output" > > + * features may be enabled on "eth0" interface in "L3-output" feature arc. > > + * Similarly, "ipv6-output" and "ipsec-output" may be enabled on "eth1" > > + * interface in same "L3-output" feature arc. > > + * > > + * When multiple features are present in a given feature arc, its imperative > > + * to allow each feature processing in a particular sequential order. For > > + * instance, in "L3-input" feature arc it may be required to run "IPsec > > + * input" feature first, for packet decryption, before "ip-lookup". So a > > + * sequential order must be maintained among features present in a > feature > > arc. > > + * > > + * Features are enabled/disabled multiple times at runtime to some or all > > + * available interfaces present in the system. Features can be > > enabled/disabled > > + * even after @b rte_graph_create() is called. Enable/disabling features on > > one > > + * interface is independent of other interface. > > + * > > + * A given feature might consume packet (if it's configured to consume) or > > may > > + * forward it to next enabled feature. For instance, "IPsec input" feature > may > > + * consume/drop all packets with "Protect" policy action while all packets > with > > + * policy action as "Bypass" may be forwarded to next enabled feature > (with > > in > > + * same feature arc) > > + * > > + * This library facilitates rte graph based applications to steer packets in > > + * fast path to different feature nodes with-in a feature arc and support all > > + * functionalities described above > > + * > > + * In order to use feature-arc APIs, applications needs to do following in > > + * control path: > > + * - Initialize feature arc library via rte_graph_feature_arc_init() > > + * - Create feature arc via rte_graph_feature_arc_create() > > + * - *Before calling rte_graph_create()*, features must be added to feature- > > arc > > + * via rte_graph_feature_add(). rte_graph_feature_add() allows adding > > + * features in a sequential order with "runs_after" and "runs_before" > > + * constraints. > > + * - Post rte_graph_create(), features can be enabled/disabled at runtime > on > > + * any interface via > rte_graph_feature_enable()/rte_graph_feature_disable() > > + * - Feature arc can be destroyed via rte_graph_feature_arc_destroy() > > + * > > + * In fast path, APIs are provided to steer packets towards feature path > from > > + * - start_node (provided as an argument to > rte_graph_feature_arc_create()) > > + * - feature nodes (which are added via rte_graph_feature_add()) > > + * > > + * For typical steering of packets across feature nodes, application required > > + * to know "rte_edges" which are saved in feature data object. Feature > data > > + * object is unique for every interface per feature with in a feature arc. > > + * > > + * When steering packets from start_node to feature node: > > + * - rte_graph_feature_arc_first_feature_get() provides first enabled > feature. > > + * - Next rte_edge from start_node to first enabled feature can be obtained > > via > > + * rte_graph_feature_arc_feature_set() > > + * > > + * rte_mbuf can carry [current feature, index] from start_node of an arc to > > other > > + * feature nodes > > + * > > + * In feature node, application can get 32-bit user_data > > + * via_rte_graph_feature_user_data_get() which is provided in > > + * rte_graph_feature_enable(). User data can hold feature specific cookie > like > > + * IPsec policy database index (if more than one are supported) > > + * > > + * If feature node is not consuming packet, next enabled feature and next > > + * rte_edge can be obtained via rte_graph_feature_arc_next_feature_get() > > + * > > + * It is application responsibility to ensure that at-least *last feature*(or > sink > > + * feature) must be enabled from where packet can exit feature-arc path, if > > + * *NO* intermediate feature is consuming the packet and it has reached > till > > + * the end of feature arc path > > + * > > + * Synchronization among cores > > + * --------------------------- > > + * Subsequent calls to rte_graph_feature_enable() is allowed while worker > > cores > > + * are processing in rte_graph_walk() loop. However, for > > + * rte_graph_feature_disable() application must use RCU based > > synchronization > > + */ > > + > > +/**< Initializer value for rte_graph_feature_arc_t */ > > +#define RTE_GRAPH_FEATURE_ARC_INITIALIZER > > ((rte_graph_feature_arc_t)UINT64_MAX) > > + > > +/** Max number of features supported in a given feature arc */ > > +#define RTE_GRAPH_FEATURE_MAX_PER_ARC 64 > > + > > +/** Length of feature arc name */ > > +#define RTE_GRAPH_FEATURE_ARC_NAMELEN RTE_NODE_NAMESIZE > > + > > +/** @internal */ > > +#define rte_graph_feature_cast(x) ((rte_graph_feature_t)x) > > + > > +/**< Initializer value for rte_graph_feature_arc_t */ > > +#define RTE_GRAPH_FEATURE_INVALID > > rte_graph_feature_cast(UINT8_MAX) > > + > > +/** rte_graph feature arc object */ > > +typedef uint64_t rte_graph_feature_arc_t; > > + > > +/** rte_graph feature object */ > > +typedef uint8_t rte_graph_feature_t; > > + > > +/** runtime active feature list index with in feature arc*/ > > +typedef uint8_t rte_graph_feature_rt_list_t; > > + > > +/** per feature arc monotonically increasing counter to synchronize fast > path > > APIs */ > > +typedef uint16_t rte_graph_feature_counter_t; > > + > > +/** > > + * Initialize feature arc subsystem > > + * > > + * @param max_feature_arcs > > + * Maximum number of feature arcs required to be supported > > + * > > + * @return > > + * 0: Success > > + * <0: Failure > > + */ > > +__rte_experimental > > +int rte_graph_feature_arc_init(int max_feature_arcs); > > + > > +/** > > + * Create a feature arc > > + * > > + * @param feature_arc_name > > + * Feature arc name with max length of @ref > > RTE_GRAPH_FEATURE_ARC_NAMELEN > > + * @param max_features > > + * Maximum number of features to be supported in this feature arc > > + * @param max_indexes > > + * Maximum number of interfaces/ports/indexes to be supported > > + * @param start_node > > + * Base node where this feature arc's features are checked in fast path > > + * @param[out] _arc > > + * Feature arc object > > + * > > + * @return > > + * 0: Success > > + * <0: Failure > > + */ > > +__rte_experimental > > +int rte_graph_feature_arc_create(const char *feature_arc_name, int > > max_features, int max_indexes, > > + struct rte_node_register *start_node, > > + rte_graph_feature_arc_t *_arc); > > + > > +/** > > + * Get feature arc object with name > > + * > > + * @param arc_name > > + * Feature arc name provided to successful @ref > > rte_graph_feature_arc_create > > + * @param[out] _arc > > + * Feature arc object returned > > + * > > + * @return > > + * 0: Success > > + * <0: Failure. > > + */ > > +__rte_experimental > > +int rte_graph_feature_arc_lookup_by_name(const char *arc_name, > > rte_graph_feature_arc_t *_arc); > > + > > +/** > > + * Add a feature to already created feature arc. For instance > > + * > > + * 1. Add first feature node: "ipv4-input" to input arc > > + * rte_graph_feature_add(ipv4_input_arc, "ipv4-input", NULL, NULL); > > + * > > + * 2. Add "ipsec-input" feature node after "ipv4-input" node > > + * rte_graph_feature_add(ipv4_input_arc, "ipsec-input", "ipv4-input", > > NULL); > > + * > > + * 3. Add "ipv4-pre-classify-input" node before "ipv4-input" node > > + * rte_graph_feature_add(ipv4_input_arc, "ipv4-pre-classify-input"", > NULL, > > "ipv4-input"); > > + * > > + * 4. Add "acl-classify-input" node after ipv4-input but before ipsec-input > > + * rte_graph_feature_add(ipv4_input_arc, "acl-classify-input", "ipv4- > input", > > "ipsec-input"); > > + * > > + * @param _arc > > + * Feature arc handle returned from @ref rte_graph_feature_arc_create() > > + * @param feature_node > > + * Graph node representing feature. On success, feature_node is > next_node > > of > > + * feature_arc->start_node > > + * @param runs_after > > + * Add this feature_node after already added "runs_after". Creates > > + * start_node -> runs_after -> this_feature sequence > > + * @param runs_before > > + * Add this feature_node before already added "runs_before". Creates > > + * start_node -> this_feature -> runs_before sequence > > + * > > + * <I> Must be called before rte_graph_create() </I> > > + * <I> rte_graph_feature_add() is not allowed after call to > > + * rte_graph_feature_enable() so all features must be added before they > can > > be > > + * enabled </I> > > + * > > + * @return > > + * 0: Success > > + * <0: Failure > > + */ > > +__rte_experimental > > +int rte_graph_feature_add(rte_graph_feature_arc_t _arc, struct > > rte_node_register *feature_node, > > + const char *runs_after, const char *runs_before); > > + > > +/** > > + * Enable feature within a feature arc > > + * > > + * Must be called after @b rte_graph_create(). > > + * > > + * @param _arc > > + * Feature arc object returned by @ref rte_graph_feature_arc_create or > > @ref > > + * rte_graph_feature_arc_lookup_by_name > > + * @param index > > + * Application specific index. Can be corresponding to > interface_id/port_id > > etc > > + * @param feature_name > > + * Name of the node which is already added via @ref > rte_graph_feature_add > > + * @param user_data > > + * Application specific data which is retrieved in fast path > > + * > > + * @return > > + * 0: Success > > + * <0: Failure > > + */ > > +__rte_experimental > > +int rte_graph_feature_enable(rte_graph_feature_arc_t _arc, uint32_t > index, > > const char *feature_name, > > + int32_t user_data); > > + > > +/** > > + * Validate whether subsequent enable/disable feature would succeed or > not. > > + * API is thread-safe > > + * > > + * @param _arc > > + * Feature arc object returned by @ref rte_graph_feature_arc_create or > > @ref > > + * rte_graph_feature_arc_lookup_by_name > > + * @param index > > + * Application specific index. Can be corresponding to > interface_id/port_id > > etc > > + * @param feature_name > > + * Name of the node which is already added via @ref > rte_graph_feature_add > > + * @param is_enable_disable > > + * If 1, validate whether subsequent @ref rte_graph_feature_enable > would > > pass or not > > + * If 0, validate whether subsequent @ref rte_graph_feature_disable > would > > pass or not > > + * > > + * @return > > + * 0: Subsequent enable/disable API would pass > > + * <0: Subsequent enable/disable API would not pass > > + */ > > +__rte_experimental > > +int rte_graph_feature_validate(rte_graph_feature_arc_t _arc, uint32_t > index, > > + const char *feature_name, int is_enable_disable); > > + > > +/** > > + * Disable already enabled feature within a feature arc > > + * > > + * Must be called after @b rte_graph_create(). API is *NOT* Thread-safe > > + * > > + * @param _arc > > + * Feature arc object returned by @ref rte_graph_feature_arc_create or > > @ref > > + * rte_graph_feature_arc_lookup_by_name > > + * @param index > > + * Application specific index. Can be corresponding to > interface_id/port_id > > etc > > + * @param feature_name > > + * Name of the node which is already added via @ref > rte_graph_feature_add > > + * > > + * @return > > + * 0: Success > > + * <0: Failure > > + */ > > +__rte_experimental > > +int rte_graph_feature_disable(rte_graph_feature_arc_t _arc, uint32_t > index, > > + const char *feature_name); > > + > > +/** > > + * Get rte_graph_feature_t object from feature name > > + * > > + * @param arc > > + * Feature arc object returned by @ref rte_graph_feature_arc_create or > > @ref > > + * rte_graph_feature_arc_lookup_by_name > > + * @param feature_name > > + * Feature name provided to @ref rte_graph_feature_add > > + * @param[out] feature > > + * Feature object > > + * > > + * @return > > + * 0: Success > > + * <0: Failure > > + */ > > +__rte_experimental > > +int rte_graph_feature_lookup(rte_graph_feature_arc_t _arc, const char > > *feature_name, > > + rte_graph_feature_t *feature); > > + > > +/** > > + * Delete feature_arc object > > + * > > + * @param _arc > > + * Feature arc object returned by @ref rte_graph_feature_arc_create or > > @ref > > + * rte_graph_feature_arc_lookup_by_name > > + * > > + * @return > > + * 0: Success > > + * <0: Failure > > + */ > > +__rte_experimental > > +int rte_graph_feature_arc_destroy(rte_graph_feature_arc_t _arc); > > + > > +/** > > + * Cleanup all feature arcs > > + * > > + * @return > > + * 0: Success > > + * <0: Failure > > + */ > > +__rte_experimental > > +int rte_graph_feature_arc_cleanup(void); > > + > > +/** > > + * Slow path API to know how many features are currently enabled within a > > featur-arc > > + * > > + * @param _arc > > + * Feature arc object > > + * > > + * @return: Number of enabled features > > + */ > > +__rte_experimental > > +int > rte_graph_feature_arc_num_enabled_features(rte_graph_feature_arc_t > > _arc); > > +#ifdef __cplusplus > > +} > > +#endif > > + > > +#endif > > diff --git a/lib/graph/rte_graph_feature_arc_worker.h > > b/lib/graph/rte_graph_feature_arc_worker.h > > new file mode 100644 > > index 0000000000..6019d74853 > > --- /dev/null > > +++ b/lib/graph/rte_graph_feature_arc_worker.h > > @@ -0,0 +1,548 @@ > > +/* SPDX-License-Identifier: BSD-3-Clause > > + * Copyright(C) 2024 Marvell International Ltd. > > + */ > > + > > +#ifndef _RTE_GRAPH_FEATURE_ARC_WORKER_H_ > > +#define _RTE_GRAPH_FEATURE_ARC_WORKER_H_ > > + > > +#include <stddef.h> > > +#include <rte_graph_feature_arc.h> > > +#include <rte_bitops.h> > > + > > +/** > > + * @file > > + * > > + * rte_graph_feature_arc_worker.h > > + * > > + * Defines fast path structure > > + */ > > + > > +#ifdef __cplusplus > > +extern "C" { > > +#endif > > + > > +/** @internal > > + * > > + * Slow path feature node info list > > + */ > > +struct rte_graph_feature_node_list { > > + /** Next feature */ > > + STAILQ_ENTRY(rte_graph_feature_node_list) next_feature; > > + > > + /** node representing feature */ > > + struct rte_node_register *feature_node; > > + > > + /** How many indexes/interfaces using this feature */ > > + int32_t ref_count; > > + > > + /* node_index in list (after feature_enable())*/ > > + uint32_t node_index; > > + > > + /** Back pointer to feature arc */ > > + void *feature_arc; > > + > > + /** rte_edge_t to this feature node from feature_arc->start_node */ > > + rte_edge_t edge_to_this_feature; > > +}; > > + > > +/** > > + * Fast path holding rte_edge_t and next enabled feature for an feature > > + */ > > +typedef struct __rte_packed rte_graph_feature_data { > > + /* next node to which current mbuf should go*/ > > + rte_edge_t next_edge; > > + > > + /* next enabled feature on this arc for current index */ > > + union { > > + uint16_t reserved; > > + struct { > > + rte_graph_feature_t next_enabled_feature; > > + }; > > + }; > > + > > + /* user_data */ > > + int32_t user_data; > > +} rte_graph_feature_data_t; > > + > > +/** > > + * Fast path feature structure. Holds re_graph_feature_data_t per index > > + */ > > +struct __rte_cache_aligned rte_graph_feature { > > + uint16_t this_feature_index; > > + > > + /* Array of size arc->feature_data_size > > + * [data-index-0][data-index-1]... > > + * Each index of size: sizeof(rte_graph_feature_data_t) > > + */ > > + uint8_t feature_data_by_index[]; > > +}; > > + > > +/** > > + * fast path cache aligned feature list holding all features > > + * There are two feature lists: active, passive > > + * > > + * Fast APIs works on active list while control plane updates passive list > > + * A atomic update to arc->active_feature_list is done to switch between > > active > > + * and passive > > + */ > > +typedef struct __rte_cache_aligned rte_graph_feature_list { > > + /** > > + * fast path array holding per_feature data. > > + * Duplicate entry as feature-arc also hold this pointer > > + * arc->features[] > > + * > > + *<-------------feature-0 ---------><CEIL><---------feature-1 -------------- > > >... > > + *[index-0][index-1]...[max_index-1] [index-0][index-1] > > ...[max_index-1]... > > + */ > > + struct rte_graph_feature *indexed_by_features; > > + /* > > + * fast path array holding first enabled feature per index > > + * (Required in start_node. In non start_node, mbuf can hold next > > enabled > > + * feature) > > + */ > > + rte_graph_feature_t first_enabled_feature_by_index[]; > > +} rte_graph_feature_list_t; > > + > > +/** > > + * rte_graph feature arc object > > + * > > + * A feature-arc can only hold RTE_GRAPH_FEATURE_MAX_PER_ARC > features > > but no > > + * limit to interface index > > + * > > + * Representing a feature arc holding all features which are > enabled/disabled > > + * on any interfaces > > + */ > > +struct __rte_cache_aligned rte_graph_feature_arc { > > + /* First 64B is fast path variables */ > > + RTE_MARKER fast_path_variables; > > + > > + /** runtime active feature list */ > > + rte_graph_feature_rt_list_t active_feature_list; > > + > > + /* Actual Size of feature_list0 */ > > + uint16_t feature_list_size; > > + > > + /** > > + * Size each feature in fastpath. > > + * sizeof(arc->active_list->indexed_by_feature[0]) > > + */ > > + uint16_t feature_size; > > + > > + /* Size of arc->max_index * sizeof(rte_graph_feature_data_t) */ > > + uint16_t feature_data_size; > > + > > + /** > > + * Fast path bitmask indicating if a feature is enabled or not Number > > + * of bits: RTE_GRAPH_FEATURE_MAX_PER_ARC > > + */ > > + uint64_t feature_enable_bitmask[2]; > > + rte_graph_feature_list_t *feature_list[2]; > > + struct rte_graph_feature *features[2]; > > + > > + /** index in feature_arc_main */ > > + uint16_t feature_arc_index; > > + > > + uint16_t reserved[3]; > > + > > + /** Slow path variables follows*/ > > + RTE_MARKER slow_path_variables; > > + > > + /** feature arc name */ > > + char feature_arc_name[RTE_GRAPH_FEATURE_ARC_NAMELEN]; > > + > > + /** All feature lists */ > > + STAILQ_HEAD(, rte_graph_feature_node_list) all_features; > > + > > + uint32_t runtime_enabled_features; > > + > > + /** Back pointer to feature_arc_main */ > > + void *feature_arc_main; > > + > > + /* start_node */ > > + struct rte_node_register *start_node; > > + > > + /* maximum number of features supported by this arc */ > > + uint32_t max_features; > > + > > + /* maximum number of index supported by this arc */ > > + uint32_t max_indexes; > > + > > + /* Slow path bit mask per feature per index */ > > + uint64_t feature_bit_mask_by_index[]; > > +}; > > + > > +/** Feature arc main */ > > +typedef struct feature_arc_main { > > + /** number of feature arcs created by application */ > > + uint32_t num_feature_arcs; > > + > > + /** max features arcs allowed */ > > + uint32_t max_feature_arcs; > > + > > + /** feature arcs */ > > + rte_graph_feature_arc_t feature_arcs[]; > > +} rte_graph_feature_arc_main_t; > > + > > +/** @internal Get feature arc pointer from object */ > > +#define rte_graph_feature_arc_get(arc) ((struct rte_graph_feature_arc > *)arc) > > + > > +extern rte_graph_feature_arc_main_t *__feature_arc_main; > > + > > +/** > > + * API to know if feature is valid or not > > + */ > > + > > +static __rte_always_inline int > > +rte_graph_feature_is_valid(rte_graph_feature_t feature) > > +{ > > + return (feature != RTE_GRAPH_FEATURE_INVALID); > > +} > > + > > +/** > > + * Get rte_graph_feature object with no checks > > + * > > + * @param arc > > + * Feature arc pointer > > + * @param feature > > + * Feature index > > + * @param feature_list > > + * active feature list retrieved from > > rte_graph_feature_arc_has_any_feature() > > + * or rte_graph_feature_arc_has_feature() > > + * > > + * @return > > + * Internal feature object. > > + */ > > +static __rte_always_inline struct rte_graph_feature * > > +__rte_graph_feature_get(struct rte_graph_feature_arc *arc, > > rte_graph_feature_t feature, > > + const rte_graph_feature_rt_list_t feature_list) > > +{ > > + return ((struct rte_graph_feature *)((uint8_t *)(arc- > > >features[feature_list] + > > + (feature * arc->feature_size)))); > > +} > > + > > +/** > > + * Get rte_graph_feature object for a given interface/index from feature arc > > + * > > + * @param arc > > + * Feature arc pointer > > + * @param feature > > + * Feature index > > + * > > + * @return > > + * Internal feature object. > > + */ > > +static __rte_always_inline struct rte_graph_feature * > > +rte_graph_feature_get(struct rte_graph_feature_arc *arc, > > rte_graph_feature_t feature) > > +{ > > + RTE_VERIFY(feature < arc->max_features); > > + > > + if (likely(rte_graph_feature_is_valid(feature))) > > + return __rte_graph_feature_get(arc, feature, arc- > > >active_feature_list); > > + > > + return NULL; > > +} > > + > > +static __rte_always_inline rte_graph_feature_data_t * > > +__rte_graph_feature_data_get(struct rte_graph_feature_arc *arc, struct > > rte_graph_feature *feature, > > + uint8_t index) > > +{ > > + RTE_SET_USED(arc); > > + return ((rte_graph_feature_data_t *)(feature->feature_data_by_index > > + > > + (index * > > sizeof(rte_graph_feature_data_t)))); > > +} > > + > > +/** > > + * Get rte_graph feature data object for a index in feature > > + * > > + * @param arc > > + * feature arc > > + * @param feature > > + * Pointer to feature object > > + * @param index > > + * Index of feature maintained in slow path linked list > > + * > > + * @return > > + * Valid feature data > > + */ > > +static __rte_always_inline rte_graph_feature_data_t * > > +rte_graph_feature_data_get(struct rte_graph_feature_arc *arc, struct > > rte_graph_feature *feature, > > + uint8_t index) > > +{ > > + if (likely(index < arc->max_indexes)) > > + return __rte_graph_feature_data_get(arc, feature, index); > > + > > + RTE_VERIFY(0); > > +} > > + > > +/** > > + * Fast path API to check if any feature enabled on a feature arc > > + * Typically from arc->start_node process function > > + * > > + * @param arc > > + * Feature arc object > > + * @param[out] plist > > + * Pointer to runtime active feature list which needs to be provided to > other > > + * fast path APIs > > + * > > + * @return > > + * 0: If no feature enabled > > + * Non-Zero: Bitmask of features enabled. plist is valid > > + * > > + */ > > +static __rte_always_inline uint64_t > > +rte_graph_feature_arc_has_any_feature(struct rte_graph_feature_arc *arc, > > + rte_graph_feature_rt_list_t *plist) > > +{ > > + *plist = __atomic_load_n(&arc->active_feature_list, > > __ATOMIC_RELAXED); > > + > > + return (__atomic_load_n(arc->feature_enable_bitmask + > > (uint8_t)*plist, > > + __ATOMIC_RELAXED)); > > +} > > + > > +/** > > + * Fast path API to check if provided feature is enabled on any > interface/index > > + * or not > > + * > > + * @param arc > > + * Feature arc object > > + * @param feature > > + * Input rte_graph_feature_t that needs to be checked > > + * @param[out] plist > > + * Returns active list to caller which needs to be provided to other fast > path > > + * APIs > > + * > > + * @return > > + * 1: If feature is enabled in arc > > + * 0: If feature is not enabled in arc > > + */ > > +static __rte_always_inline int > > +rte_graph_feature_arc_has_feature(struct rte_graph_feature_arc *arc, > > + rte_graph_feature_t feature, > > + rte_graph_feature_rt_list_t *plist) > > +{ > > + uint64_t bitmask = RTE_BIT64(feature); > > + > > + *plist = __atomic_load_n(&arc->active_feature_list, > > __ATOMIC_RELAXED); > > + > > + return (bitmask & __atomic_load_n(arc->feature_enable_bitmask + > > (uint8_t)*plist, > > + __ATOMIC_RELAXED)); > > +} > > + > > +/** > > + * Prefetch feature arc fast path cache line > > + * > > + * @param arc > > + * RTE_GRAPH feature arc object > > + */ > > +static __rte_always_inline void > > +rte_graph_feature_arc_prefetch(struct rte_graph_feature_arc *arc) > > +{ > > + rte_prefetch0((void *)&arc->fast_path_variables); > > +} > > + > > +/** > > + * Prefetch feature related fast path cache line > > + * > > + * @param arc > > + * RTE_GRAPH feature arc object > > + * @param list > > + * Pointer to runtime active feature list from > > rte_graph_feature_arc_has_any_feature(); > > + * @param feature > > + * Pointer to feature object > > + */ > > +static __rte_always_inline void > > +rte_graph_feature_arc_feature_prefetch(struct rte_graph_feature_arc *arc, > > + const rte_graph_feature_rt_list_t list, > > + rte_graph_feature_t feature) > > +{ > > + /* feature cache line */ > > + if (likely(rte_graph_feature_is_valid(feature))) > > + rte_prefetch0((void *)__rte_graph_feature_get(arc, feature, > > list)); > > +} > > + > > +/** > > + * Prefetch feature data upfront. Perform sanity > > + * > > + * @param _arc > > + * RTE_GRAPH feature arc object > > + * @param list > > + * Pointer to runtime active feature list from > > rte_graph_feature_arc_has_any_feature(); > > + * @param feature > > + * Pointer to feature object returned from @ref > > + * rte_graph_feature_arc_first_feature_get() > > + * @param index > > + * Interface/index > > + */ > > +static __rte_always_inline void > > +rte_graph_feature_arc_data_prefetch(struct rte_graph_feature_arc *arc, > > + const rte_graph_feature_rt_list_t list, > > + rte_graph_feature_t feature, uint32_t > index) > > +{ > > + if (likely(rte_graph_feature_is_valid(feature))) > > + rte_prefetch0((void *)((uint8_t *)arc->features[list] + > > + offsetof(struct rte_graph_feature, > > feature_data_by_index) + > > + (index * sizeof(rte_graph_feature_data_t)))); > > +} > > + > > +/** > > + * Fast path API to get first enabled feature on interface index > > + * Typically required in arc->start_node so that from returned feature, > > + * feature-data can be retrieved to steer packets > > + * > > + * @param arc > > + * Feature arc object > > + * @param list > > + * Pointer to runtime active feature list from > > + * rte_graph_feature_arc_has_any_feature() or > > + * rte_graph_feature_arc_has_feature() > > + * @param index > > + * Interface Index > > + * @param[out] feature > > + * Pointer to rte_graph_feature_t. > > + * > > + * @return > > + * 0. Success. feature field is valid > > + * 1. Failure. feature field is invalid > > + * > > + */ > > +static __rte_always_inline int > > +rte_graph_feature_arc_first_feature_get(struct rte_graph_feature_arc *arc, > > + const rte_graph_feature_rt_list_t list, > > + uint32_t index, > > + rte_graph_feature_t *feature) > > +{ > > + struct rte_graph_feature_list *feature_list = arc->feature_list[list]; > > + > > + *feature = feature_list->first_enabled_feature_by_index[index]; > > + > > + return rte_graph_feature_is_valid(*feature); > > +} > > + > > +/** > > + * Fast path API to get next enabled feature on interface index with > provided > > + * input feature > > + * > > + * @param arc > > + * Feature arc object > > + * @param list > > + * Pointer to runtime active feature list from > > + * rte_graph_feature_arc_has_any_feature() or > > + * @param index > > + * Interface Index > > + * @param[in][out] feature > > + * Pointer to rte_graph_feature_t. Input feature set to next enabled > feature > > + * after success return > > + * @param[out] next_edge > > + * Edge from current feature to next feature. Valid only if next feature is > > valid > > + * > > + * @return > > + * 0. Success. next enabled feature is valid. > > + * 1. Failure. next enabled feature is invalid > > + */ > > +static __rte_always_inline int > > +rte_graph_feature_arc_next_feature_get(struct rte_graph_feature_arc > *arc, > > + const rte_graph_feature_rt_list_t list, > > + uint32_t index, > > + rte_graph_feature_t *feature, > > + rte_edge_t *next_edge) > > +{ > > + rte_graph_feature_data_t *feature_data = NULL; > > + struct rte_graph_feature *f = NULL; > > + > > + if (likely(rte_graph_feature_is_valid(*feature))) { > > + f = __rte_graph_feature_get(arc, *feature, list); > > + feature_data = rte_graph_feature_data_get(arc, f, index); > > + *feature = feature_data->next_enabled_feature; > > + *next_edge = feature_data->next_edge; > > + return (*feature == RTE_GRAPH_FEATURE_INVALID); > > + } > > + > > + return 1; > > +} > > + > > +/** > > + * Set fields with respect to first enabled feature in an arc and return edge > > + * Typically returned feature and interface index must be saved in > rte_mbuf > > + * structure to pass this information to next feature node > > + * > > + * @param arc > > + * Feature arc object > > + * @param list > > + * Pointer to runtime active feature list from > > rte_graph_feature_arc_has_any_feature(); > > + * @param index > > + * Index (of interface) > > + * @param[out] gf > > + * Pointer to rte_graph_feature_t. Valid if API returns Success > > + * @param[out] edge > > + * Edge to steer packet from arc->start_node to first enabled feature. Valid > > + * only if API returns Success > > + * > > + * @return > > + * 0: If valid feature is set by API > > + * 1: If valid feature is NOT set by API > > + */ > > +static __rte_always_inline rte_graph_feature_t > > +rte_graph_feature_arc_feature_set(struct rte_graph_feature_arc *arc, > > + const rte_graph_feature_rt_list_t list, > > + uint32_t index, > > + rte_graph_feature_t *gf, > > + rte_edge_t *edge) > > +{ > > + struct rte_graph_feature_list *feature_list = arc->feature_list[list]; > > + struct rte_graph_feature_data *feature_data = NULL; > > + struct rte_graph_feature *feature = NULL; > > + rte_graph_feature_t f; > > + > > + /* reset */ > > + *gf = RTE_GRAPH_FEATURE_INVALID; > > + f = feature_list->first_enabled_feature_by_index[index]; > > + > > + if (unlikely(rte_graph_feature_is_valid(f))) { > > + feature = __rte_graph_feature_get(arc, f, list); > > + feature_data = rte_graph_feature_data_get(arc, feature, > > index); > > + *gf = f; > > + *edge = feature_data->next_edge; > > + return 0; > > + } > > + > > + return 1; > > +} > > + > > +/** > > + * Get user data corresponding to current feature set by application in > > + * rte_graph_feature_enable() > > + * > > + * @param arc > > + * Feature arc object > > + * @param list > > + * Pointer to runtime active feature list from > > rte_graph_feature_arc_has_any_feature(); > > + * @param feature > > + * Feature index > > + * @param index > > + * Interface index > > + * > > + * @return > > + * UINT32_MAX: Failure > > + * Valid user data: Success > > + */ > > +static __rte_always_inline uint32_t > > +rte_graph_feature_user_data_get(struct rte_graph_feature_arc *arc, > > + const rte_graph_feature_rt_list_t list, > > + rte_graph_feature_t feature, > > + uint32_t index) > > +{ > > + rte_graph_feature_data_t *fdata = NULL; > > + struct rte_graph_feature *f = NULL; > > + > > + if (likely(rte_graph_feature_is_valid(feature))) { > > + f = __rte_graph_feature_get(arc, feature, list); > > + fdata = rte_graph_feature_data_get(arc, f, index); > > + return fdata->user_data; > > + } > > + > > + return UINT32_MAX; > > +} > > +#ifdef __cplusplus > > +} > > +#endif > > +#endif > > diff --git a/lib/graph/version.map b/lib/graph/version.map > > index 2c83425ddc..82b2469fba 100644 > > --- a/lib/graph/version.map > > +++ b/lib/graph/version.map > > @@ -52,3 +52,20 @@ DPDK_25 { > > > > local: *; > > }; > > + > > +EXPERIMENTAL { > > + global: > > + > > + # added in 24.11 > > + rte_graph_feature_arc_init; > > + rte_graph_feature_arc_create; > > + rte_graph_feature_arc_lookup_by_name; > > + rte_graph_feature_add; > > + rte_graph_feature_enable; > > + rte_graph_feature_validate; > > + rte_graph_feature_disable; > > + rte_graph_feature_lookup; > > + rte_graph_feature_arc_destroy; > > + rte_graph_feature_arc_cleanup; > > + rte_graph_feature_arc_num_enabled_features; > > +}; > > -- > > 2.43.0 ^ permalink raw reply [flat|nested] 46+ messages in thread
* [RFC PATCH 2/3] graph: add feature arc option in graph create 2024-09-07 7:31 [RFC PATCH 0/3] add feature arc in rte_graph Nitin Saxena 2024-09-07 7:31 ` [RFC PATCH 1/3] graph: add feature arc support Nitin Saxena @ 2024-09-07 7:31 ` Nitin Saxena 2024-09-07 7:31 ` [RFC PATCH 3/3] graph: add IPv4 output feature arc Nitin Saxena ` (2 subsequent siblings) 4 siblings, 0 replies; 46+ messages in thread From: Nitin Saxena @ 2024-09-07 7:31 UTC (permalink / raw) To: Jerin Jacob, Kiran Kumar K, Nithin Dabilpuram, Zhirun Yan Cc: dev, Nitin Saxena, Pavan Nikhilesh Added option in graph create to call feature-specific process node functions. This removes extra overhead for checking feature arc status in nodes where application is not using feature arc processing Signed-off-by: Pavan Nikhilesh <pbhagavatula@marvell.com> --- lib/graph/graph.c | 1 + lib/graph/graph_populate.c | 7 ++++++- lib/graph/graph_private.h | 3 +++ lib/graph/node.c | 2 ++ lib/graph/rte_graph.h | 3 +++ 5 files changed, 15 insertions(+), 1 deletion(-) diff --git a/lib/graph/graph.c b/lib/graph/graph.c index d5b8c9f918..b0ad3a83ae 100644 --- a/lib/graph/graph.c +++ b/lib/graph/graph.c @@ -455,6 +455,7 @@ rte_graph_create(const char *name, struct rte_graph_param *prm) graph->parent_id = RTE_GRAPH_ID_INVALID; graph->lcore_id = RTE_MAX_LCORE; graph->num_pkt_to_capture = prm->num_pkt_to_capture; + graph->feature_arc_enabled = prm->feature_arc_enable; if (prm->pcap_filename) rte_strscpy(graph->pcap_filename, prm->pcap_filename, RTE_GRAPH_PCAP_FILE_SZ); diff --git a/lib/graph/graph_populate.c b/lib/graph/graph_populate.c index ed596a7711..2892f3cce2 100644 --- a/lib/graph/graph_populate.c +++ b/lib/graph/graph_populate.c @@ -79,8 +79,13 @@ graph_nodes_populate(struct graph *_graph) if (graph_pcap_is_enable()) { node->process = graph_pcap_dispatch; node->original_process = graph_node->node->process; - } else + if (_graph->feature_arc_enabled) + node->original_process = graph_node->node->feat_arc_proc; + } else { node->process = graph_node->node->process; + if (_graph->feature_arc_enabled) + node->process = graph_node->node->feat_arc_proc; + } memcpy(node->name, graph_node->node->name, RTE_GRAPH_NAMESIZE); pid = graph_node->node->parent_id; if (pid != RTE_NODE_ID_INVALID) { /* Cloned node */ diff --git a/lib/graph/graph_private.h b/lib/graph/graph_private.h index d557d55f2d..58ba0abeff 100644 --- a/lib/graph/graph_private.h +++ b/lib/graph/graph_private.h @@ -56,6 +56,7 @@ struct node { unsigned int lcore_id; /**< Node runs on the Lcore ID used for mcore dispatch model. */ rte_node_process_t process; /**< Node process function. */ + rte_node_process_t feat_arc_proc; /**< Node feature-arch process function. */ rte_node_init_t init; /**< Node init function. */ rte_node_fini_t fini; /**< Node fini function. */ rte_node_t id; /**< Allocated identifier for the node. */ @@ -126,6 +127,8 @@ struct graph { /**< Number of packets to be captured per core. */ char pcap_filename[RTE_GRAPH_PCAP_FILE_SZ]; /**< pcap file name/path. */ + uint8_t feature_arc_enabled; + /**< Graph feature arc. */ STAILQ_HEAD(gnode_list, graph_node) node_list; /**< Nodes in a graph. */ }; diff --git a/lib/graph/node.c b/lib/graph/node.c index 99a9622779..d8fd273543 100644 --- a/lib/graph/node.c +++ b/lib/graph/node.c @@ -90,6 +90,7 @@ __rte_node_register(const struct rte_node_register *reg) goto free; node->flags = reg->flags; node->process = reg->process; + node->feat_arc_proc = reg->feat_arc_proc; node->init = reg->init; node->fini = reg->fini; node->nb_edges = reg->nb_edges; @@ -137,6 +138,7 @@ node_clone(struct node *node, const char *name) /* Clone the source node */ reg->flags = node->flags; reg->process = node->process; + reg->feat_arc_proc = node->feat_arc_proc; reg->init = node->init; reg->fini = node->fini; reg->nb_edges = node->nb_edges; diff --git a/lib/graph/rte_graph.h b/lib/graph/rte_graph.h index ecfec2068a..ebbdbbea48 100644 --- a/lib/graph/rte_graph.h +++ b/lib/graph/rte_graph.h @@ -163,6 +163,8 @@ struct rte_graph_param { uint64_t num_pkt_to_capture; /**< Number of packets to capture. */ char *pcap_filename; /**< Filename in which packets to be captured.*/ + bool feature_arc_enable; /**< Enable Graph feature arc. */ + union { struct { uint64_t rsvd; /**< Reserved for rtc model. */ @@ -470,6 +472,7 @@ struct rte_node_register { uint64_t flags; /**< Node configuration flag. */ #define RTE_NODE_SOURCE_F (1ULL << 0) /**< Node type is source. */ rte_node_process_t process; /**< Node process function. */ + rte_node_process_t feat_arc_proc; /**< Node feature-arch process function. */ rte_node_init_t init; /**< Node init function. */ rte_node_fini_t fini; /**< Node fini function. */ rte_node_t id; /**< Node Identifier. */ -- 2.43.0 ^ permalink raw reply [flat|nested] 46+ messages in thread
* [RFC PATCH 3/3] graph: add IPv4 output feature arc 2024-09-07 7:31 [RFC PATCH 0/3] add feature arc in rte_graph Nitin Saxena 2024-09-07 7:31 ` [RFC PATCH 1/3] graph: add feature arc support Nitin Saxena 2024-09-07 7:31 ` [RFC PATCH 2/3] graph: add feature arc option in graph create Nitin Saxena @ 2024-09-07 7:31 ` Nitin Saxena 2024-10-08 8:04 ` [RFC PATCH 0/3] add feature arc in rte_graph David Marchand 2024-10-08 13:30 ` [RFC PATCH v2 0/5] " Nitin Saxena 4 siblings, 0 replies; 46+ messages in thread From: Nitin Saxena @ 2024-09-07 7:31 UTC (permalink / raw) To: Jerin Jacob, Kiran Kumar K, Nithin Dabilpuram, Zhirun Yan Cc: dev, Nitin Saxena add ipv4-output feature arc in ipv4-rewrite node to allow custom/standard nodes(like outbound IPsec policy node) in outgoing forwarding path Signed-off-by: Nitin Saxena <nsaxena@marvell.com> --- lib/node/ip4_rewrite.c | 476 +++++++++++++++++++++++++++++------- lib/node/ip4_rewrite_priv.h | 9 +- lib/node/node_private.h | 19 +- lib/node/rte_node_ip4_api.h | 3 + 4 files changed, 411 insertions(+), 96 deletions(-) diff --git a/lib/node/ip4_rewrite.c b/lib/node/ip4_rewrite.c index 34a920df5e..916f180a3d 100644 --- a/lib/node/ip4_rewrite.c +++ b/lib/node/ip4_rewrite.c @@ -15,39 +15,156 @@ #include "ip4_rewrite_priv.h" #include "node_private.h" +#define ALL_PKT_MASK 0xf + struct ip4_rewrite_node_ctx { + rte_graph_feature_arc_t output_feature_arc; /* Dynamic offset to mbuf priv1 */ int mbuf_priv1_off; /* Cached next index */ uint16_t next_index; + uint16_t last_tx; }; +typedef struct rewrite_priv_vars { + union { + struct { + rte_xmm_t xmm1; + }; + struct __rte_packed { + uint16_t next0; + uint16_t next1; + uint16_t next2; + uint16_t next3; + uint16_t last_tx_interface; + uint16_t last_if_feature; + uint16_t actual_feat_mask; + uint16_t speculative_feat_mask; + }; + }; +} rewrite_priv_vars_t; + static struct ip4_rewrite_node_main *ip4_rewrite_nm; #define IP4_REWRITE_NODE_LAST_NEXT(ctx) \ (((struct ip4_rewrite_node_ctx *)ctx)->next_index) +#define IP4_REWRITE_NODE_LAST_TX(ctx) \ + (((struct ip4_rewrite_node_ctx *)ctx)->last_tx) + #define IP4_REWRITE_NODE_PRIV1_OFF(ctx) \ (((struct ip4_rewrite_node_ctx *)ctx)->mbuf_priv1_off) -static uint16_t -ip4_rewrite_node_process(struct rte_graph *graph, struct rte_node *node, - void **objs, uint16_t nb_objs) +#define IP4_REWRITE_NODE_OUTPUT_FEATURE_ARC(ctx) \ + (((struct ip4_rewrite_node_ctx *)ctx)->output_feature_arc) + +static __rte_always_inline void +prefetch_mbuf_and_dynfield(struct rte_mbuf *mbuf) { + /* prefetch first cache line required for accessing buf_addr */ + rte_prefetch0((void *)mbuf); +} + +static __rte_always_inline void +check_output_feature_x4(struct rte_graph_feature_arc *arc, + const rte_graph_feature_rt_list_t flist, + rewrite_priv_vars_t *pvar, struct node_mbuf_priv1 *priv0, + struct node_mbuf_priv1 *priv1, struct node_mbuf_priv1 *priv2, + struct node_mbuf_priv1 *priv3) +{ + uint32_t mask = 0; + uint16_t xor = 0; + + /* + * interface edge's start from 1 and not from 0 as "pkt_drop" + * is next node at 0th index + */ + priv0->if_index = pvar->next0 - 1; + priv1->if_index = pvar->next1 - 1; + priv2->if_index = pvar->next2 - 1; + priv3->if_index = pvar->next3 - 1; + + /* Find out if all packets are sent to last_tx_interface */ + xor = pvar->last_tx_interface ^ priv0->if_index; + xor += priv0->if_index ^ priv1->if_index; + xor += priv1->if_index ^ priv2->if_index; + xor += priv2->if_index ^ priv3->if_index; + + if (likely(!xor)) { + /* copy last interface feature and feature mask */ + priv0->current_feature = priv1->current_feature = + priv2->current_feature = priv3->current_feature = + pvar->last_if_feature; + pvar->actual_feat_mask = pvar->speculative_feat_mask; + } else { + /* create a mask for index which does not have feature + * Also override next edge and if feature enabled, get feature + */ + mask = rte_graph_feature_arc_feature_set(arc, flist, priv0->if_index, + &priv0->current_feature, + &pvar->next0); + + mask |= ((rte_graph_feature_arc_feature_set(arc, flist, priv1->if_index, + &priv1->current_feature, + &pvar->next1)) << 1); + + mask |= ((rte_graph_feature_arc_feature_set(arc, flist, priv2->if_index, + &priv2->current_feature, + &pvar->next2)) << 2); + + mask |= ((rte_graph_feature_arc_feature_set(arc, flist, priv3->if_index, + &priv3->current_feature, + &pvar->next3)) << 3); + + /* + * add last tx and last feature regardless even if feature is + * valid or not + */ + pvar->last_tx_interface = priv3->if_index; + pvar->last_if_feature = priv3->current_feature; + /* Set 0xf if invalid feature to last packet, else 0 */ + pvar->speculative_feat_mask = (priv3->current_feature == + RTE_GRAPH_FEATURE_INVALID) ? ALL_PKT_MASK : 0x0; + pvar->actual_feat_mask = mask; + } +} + +static __rte_always_inline uint16_t +__ip4_rewrite_node_process(struct rte_graph *graph, struct rte_node *node, + struct rte_graph_feature_arc *out_feature_arc, + void **objs, uint16_t nb_objs, + const int dyn, const int check_enabled_features, + const rte_graph_feature_rt_list_t flist) +{ + struct node_mbuf_priv1 *priv0 = NULL, *priv1 = NULL, *priv2 = NULL, *priv3 = NULL; struct rte_mbuf *mbuf0, *mbuf1, *mbuf2, *mbuf3, **pkts; struct ip4_rewrite_nh_header *nh = ip4_rewrite_nm->nh; - const int dyn = IP4_REWRITE_NODE_PRIV1_OFF(node->ctx); - uint16_t next0, next1, next2, next3, next_index; - struct rte_ipv4_hdr *ip0, *ip1, *ip2, *ip3; uint16_t n_left_from, held = 0, last_spec = 0; + struct rte_ipv4_hdr *ip0, *ip1, *ip2, *ip3; + rewrite_priv_vars_t pvar; + int64_t fd0, fd1, fd2, fd3; + rte_edge_t fix_spec = 0; void *d0, *d1, *d2, *d3; void **to_next, **from; + uint16_t next_index; rte_xmm_t priv01; rte_xmm_t priv23; int i; - /* Speculative next as last next */ + RTE_SET_USED(fd0); + RTE_SET_USED(fd1); + RTE_SET_USED(fd2); + RTE_SET_USED(fd3); + + /* Initialize speculative variables.*/ + + /* Last interface */ + pvar.last_tx_interface = IP4_REWRITE_NODE_LAST_TX(node->ctx); + /*last next from node ctx*/ next_index = IP4_REWRITE_NODE_LAST_NEXT(node->ctx); + pvar.speculative_feat_mask = ALL_PKT_MASK; + pvar.actual_feat_mask = 0; + rte_prefetch0(nh); pkts = (struct rte_mbuf **)objs; @@ -55,20 +172,47 @@ ip4_rewrite_node_process(struct rte_graph *graph, struct rte_node *node, n_left_from = nb_objs; for (i = 0; i < 4 && i < n_left_from; i++) - rte_prefetch0(pkts[i]); + prefetch_mbuf_and_dynfield(pkts[i]); /* Get stream for the speculated next node */ to_next = rte_node_next_stream_get(graph, node, next_index, nb_objs); + + /* prefetch speculative feature and corresponding data */ + if (check_enabled_features) { + /* + * Get first feature enabled, if any, on last_tx_interface + */ + if (unlikely(!rte_graph_feature_arc_first_feature_get(out_feature_arc, + flist, + pvar.last_tx_interface, + (rte_graph_feature_t *) + &pvar.last_if_feature))) { + /* prefetch feature cache line */ + rte_graph_feature_arc_feature_prefetch(out_feature_arc, flist, + pvar.last_if_feature); + + /* prefetch feature data cache line */ + rte_graph_feature_arc_data_prefetch(out_feature_arc, flist, + pvar.last_if_feature, + pvar.last_tx_interface); + /* + * Set speculativa_feat mask to indicate, all 4 packets + * going to feature path + */ + pvar.speculative_feat_mask = 0; + } + } + /* Update Ethernet header of pkts */ while (n_left_from >= 4) { if (likely(n_left_from > 7)) { /* Prefetch only next-mbuf struct and priv area. * Data need not be prefetched as we only write. */ - rte_prefetch0(pkts[4]); - rte_prefetch0(pkts[5]); - rte_prefetch0(pkts[6]); - rte_prefetch0(pkts[7]); + prefetch_mbuf_and_dynfield(pkts[4]); + prefetch_mbuf_and_dynfield(pkts[5]); + prefetch_mbuf_and_dynfield(pkts[6]); + prefetch_mbuf_and_dynfield(pkts[7]); } mbuf0 = pkts[0]; @@ -78,66 +222,138 @@ ip4_rewrite_node_process(struct rte_graph *graph, struct rte_node *node, pkts += 4; n_left_from -= 4; + + /* Copy mbuf private data into private variables */ priv01.u64[0] = node_mbuf_priv1(mbuf0, dyn)->u; priv01.u64[1] = node_mbuf_priv1(mbuf1, dyn)->u; priv23.u64[0] = node_mbuf_priv1(mbuf2, dyn)->u; priv23.u64[1] = node_mbuf_priv1(mbuf3, dyn)->u; - /* Increment checksum by one. */ - priv01.u32[1] += rte_cpu_to_be_16(0x0100); - priv01.u32[3] += rte_cpu_to_be_16(0x0100); - priv23.u32[1] += rte_cpu_to_be_16(0x0100); - priv23.u32[3] += rte_cpu_to_be_16(0x0100); - - /* Update ttl,cksum rewrite ethernet hdr on mbuf0 */ - d0 = rte_pktmbuf_mtod(mbuf0, void *); - rte_memcpy(d0, nh[priv01.u16[0]].rewrite_data, - nh[priv01.u16[0]].rewrite_len); - - next0 = nh[priv01.u16[0]].tx_node; - ip0 = (struct rte_ipv4_hdr *)((uint8_t *)d0 + - sizeof(struct rte_ether_hdr)); - ip0->time_to_live = priv01.u16[1] - 1; - ip0->hdr_checksum = priv01.u16[2] + priv01.u16[3]; - - /* Update ttl,cksum rewrite ethernet hdr on mbuf1 */ - d1 = rte_pktmbuf_mtod(mbuf1, void *); - rte_memcpy(d1, nh[priv01.u16[4]].rewrite_data, - nh[priv01.u16[4]].rewrite_len); - - next1 = nh[priv01.u16[4]].tx_node; - ip1 = (struct rte_ipv4_hdr *)((uint8_t *)d1 + - sizeof(struct rte_ether_hdr)); - ip1->time_to_live = priv01.u16[5] - 1; - ip1->hdr_checksum = priv01.u16[6] + priv01.u16[7]; - - /* Update ttl,cksum rewrite ethernet hdr on mbuf2 */ - d2 = rte_pktmbuf_mtod(mbuf2, void *); - rte_memcpy(d2, nh[priv23.u16[0]].rewrite_data, - nh[priv23.u16[0]].rewrite_len); - next2 = nh[priv23.u16[0]].tx_node; - ip2 = (struct rte_ipv4_hdr *)((uint8_t *)d2 + - sizeof(struct rte_ether_hdr)); - ip2->time_to_live = priv23.u16[1] - 1; - ip2->hdr_checksum = priv23.u16[2] + priv23.u16[3]; - - /* Update ttl,cksum rewrite ethernet hdr on mbuf3 */ - d3 = rte_pktmbuf_mtod(mbuf3, void *); - rte_memcpy(d3, nh[priv23.u16[4]].rewrite_data, - nh[priv23.u16[4]].rewrite_len); - - next3 = nh[priv23.u16[4]].tx_node; - ip3 = (struct rte_ipv4_hdr *)((uint8_t *)d3 + - sizeof(struct rte_ether_hdr)); - ip3->time_to_live = priv23.u16[5] - 1; - ip3->hdr_checksum = priv23.u16[6] + priv23.u16[7]; + /* Copy next edge from next hop */ + pvar.next0 = nh[priv01.u16[0]].tx_node; + pvar.next1 = nh[priv01.u16[4]].tx_node; + pvar.next2 = nh[priv23.u16[0]].tx_node; + pvar.next3 = nh[priv23.u16[4]].tx_node; + + if (check_enabled_features) { + priv0 = node_mbuf_priv1(mbuf0, dyn); + priv1 = node_mbuf_priv1(mbuf1, dyn); + priv2 = node_mbuf_priv1(mbuf2, dyn); + priv3 = node_mbuf_priv1(mbuf3, dyn); + + /* If feature is enabled, override next edge for each mbuf + * and set node_mbuf_priv data appropriately + */ + check_output_feature_x4(out_feature_arc, flist, + &pvar, priv0, priv1, priv2, priv3); + + /* check_output_feature_x4() returns bit mask which indicates + * which packet is not following feature path, hence normal processing + * has to happen on them + */ + if (unlikely(pvar.actual_feat_mask)) { + if (pvar.actual_feat_mask & 0x1) { + priv01.u32[1] += rte_cpu_to_be_16(0x0100); + /* Update ttl,cksum rewrite ethernet hdr on mbuf0 */ + d0 = rte_pktmbuf_mtod(mbuf0, void *); + rte_memcpy(d0, nh[priv01.u16[0]].rewrite_data, + nh[priv01.u16[0]].rewrite_len); + ip0 = (struct rte_ipv4_hdr *)((uint8_t *)d0 + + sizeof(struct rte_ether_hdr)); + ip0->time_to_live = priv01.u16[1] - 1; + ip0->hdr_checksum = priv01.u16[2] + priv01.u16[3]; + } + if (pvar.actual_feat_mask & 0x2) { + priv01.u32[3] += rte_cpu_to_be_16(0x0100); + /* Update ttl,cksum rewrite ethernet hdr on mbuf1 */ + d1 = rte_pktmbuf_mtod(mbuf1, void *); + rte_memcpy(d1, nh[priv01.u16[4]].rewrite_data, + nh[priv01.u16[4]].rewrite_len); + + ip1 = (struct rte_ipv4_hdr *)((uint8_t *)d1 + + sizeof(struct rte_ether_hdr)); + ip1->time_to_live = priv01.u16[5] - 1; + ip1->hdr_checksum = priv01.u16[6] + priv01.u16[7]; + } + if (pvar.actual_feat_mask & 0x4) { + priv23.u32[1] += rte_cpu_to_be_16(0x0100); + /* Update ttl,cksum rewrite ethernet hdr on mbuf2 */ + d2 = rte_pktmbuf_mtod(mbuf2, void *); + rte_memcpy(d2, nh[priv23.u16[0]].rewrite_data, + nh[priv23.u16[0]].rewrite_len); + ip2 = (struct rte_ipv4_hdr *)((uint8_t *)d2 + + sizeof(struct rte_ether_hdr)); + ip2->time_to_live = priv23.u16[1] - 1; + ip2->hdr_checksum = priv23.u16[2] + priv23.u16[3]; + } + if (pvar.actual_feat_mask & 0x8) { + priv23.u32[3] += rte_cpu_to_be_16(0x0100); + /* Update ttl,cksum rewrite ethernet hdr on mbuf3 */ + d3 = rte_pktmbuf_mtod(mbuf3, void *); + rte_memcpy(d3, nh[priv23.u16[4]].rewrite_data, + nh[priv23.u16[4]].rewrite_len); + ip3 = (struct rte_ipv4_hdr *)((uint8_t *)d3 + + sizeof(struct rte_ether_hdr)); + ip3->time_to_live = priv23.u16[5] - 1; + ip3->hdr_checksum = priv23.u16[6] + priv23.u16[7]; + } + } + } else { + /* Case when no feature is enabled */ + + /* Increment checksum by one. */ + priv01.u32[1] += rte_cpu_to_be_16(0x0100); + priv01.u32[3] += rte_cpu_to_be_16(0x0100); + priv23.u32[1] += rte_cpu_to_be_16(0x0100); + priv23.u32[3] += rte_cpu_to_be_16(0x0100); + + /* Update ttl,cksum rewrite ethernet hdr on mbuf0 */ + d0 = rte_pktmbuf_mtod(mbuf0, void *); + rte_memcpy(d0, nh[priv01.u16[0]].rewrite_data, + nh[priv01.u16[0]].rewrite_len); + + ip0 = (struct rte_ipv4_hdr *)((uint8_t *)d0 + + sizeof(struct rte_ether_hdr)); + ip0->time_to_live = priv01.u16[1] - 1; + ip0->hdr_checksum = priv01.u16[2] + priv01.u16[3]; + + /* Update ttl,cksum rewrite ethernet hdr on mbuf1 */ + d1 = rte_pktmbuf_mtod(mbuf1, void *); + rte_memcpy(d1, nh[priv01.u16[4]].rewrite_data, + nh[priv01.u16[4]].rewrite_len); + + ip1 = (struct rte_ipv4_hdr *)((uint8_t *)d1 + + sizeof(struct rte_ether_hdr)); + ip1->time_to_live = priv01.u16[5] - 1; + ip1->hdr_checksum = priv01.u16[6] + priv01.u16[7]; + + /* Update ttl,cksum rewrite ethernet hdr on mbuf2 */ + d2 = rte_pktmbuf_mtod(mbuf2, void *); + rte_memcpy(d2, nh[priv23.u16[0]].rewrite_data, + nh[priv23.u16[0]].rewrite_len); + ip2 = (struct rte_ipv4_hdr *)((uint8_t *)d2 + + sizeof(struct rte_ether_hdr)); + ip2->time_to_live = priv23.u16[1] - 1; + ip2->hdr_checksum = priv23.u16[2] + priv23.u16[3]; + + /* Update ttl,cksum rewrite ethernet hdr on mbuf3 */ + d3 = rte_pktmbuf_mtod(mbuf3, void *); + rte_memcpy(d3, nh[priv23.u16[4]].rewrite_data, + nh[priv23.u16[4]].rewrite_len); + + ip3 = (struct rte_ipv4_hdr *)((uint8_t *)d3 + + sizeof(struct rte_ether_hdr)); + ip3->time_to_live = priv23.u16[5] - 1; + ip3->hdr_checksum = priv23.u16[6] + priv23.u16[7]; + } /* Enqueue four to next node */ - rte_edge_t fix_spec = - ((next_index == next0) && (next0 == next1) && - (next1 == next2) && (next2 == next3)); + fix_spec = next_index ^ pvar.next0; + fix_spec += next_index ^ pvar.next1; + fix_spec += next_index ^ pvar.next2; + fix_spec += next_index ^ pvar.next3; - if (unlikely(fix_spec == 0)) { + if (unlikely(fix_spec != 0)) { /* Copy things successfully speculated till now */ rte_memcpy(to_next, from, last_spec * sizeof(from[0])); from += last_spec; @@ -146,56 +362,56 @@ ip4_rewrite_node_process(struct rte_graph *graph, struct rte_node *node, last_spec = 0; /* next0 */ - if (next_index == next0) { + if (next_index == pvar.next0) { to_next[0] = from[0]; to_next++; held++; } else { - rte_node_enqueue_x1(graph, node, next0, + rte_node_enqueue_x1(graph, node, pvar.next0, from[0]); } /* next1 */ - if (next_index == next1) { + if (next_index == pvar.next1) { to_next[0] = from[1]; to_next++; held++; } else { - rte_node_enqueue_x1(graph, node, next1, + rte_node_enqueue_x1(graph, node, pvar.next1, from[1]); } /* next2 */ - if (next_index == next2) { + if (next_index == pvar.next2) { to_next[0] = from[2]; to_next++; held++; } else { - rte_node_enqueue_x1(graph, node, next2, + rte_node_enqueue_x1(graph, node, pvar.next2, from[2]); } /* next3 */ - if (next_index == next3) { + if (next_index == pvar.next3) { to_next[0] = from[3]; to_next++; held++; } else { - rte_node_enqueue_x1(graph, node, next3, + rte_node_enqueue_x1(graph, node, pvar.next3, from[3]); } from += 4; /* Change speculation if last two are same */ - if ((next_index != next3) && (next2 == next3)) { + if ((next_index != pvar.next3) && (pvar.next2 == pvar.next3)) { /* Put the current speculated node */ rte_node_next_stream_put(graph, node, next_index, held); held = 0; /* Get next speculated stream */ - next_index = next3; + next_index = pvar.next3; to_next = rte_node_next_stream_get( graph, node, next_index, nb_objs); } @@ -212,20 +428,41 @@ ip4_rewrite_node_process(struct rte_graph *graph, struct rte_node *node, pkts += 1; n_left_from -= 1; - d0 = rte_pktmbuf_mtod(mbuf0, void *); - rte_memcpy(d0, nh[node_mbuf_priv1(mbuf0, dyn)->nh].rewrite_data, - nh[node_mbuf_priv1(mbuf0, dyn)->nh].rewrite_len); - - next0 = nh[node_mbuf_priv1(mbuf0, dyn)->nh].tx_node; - ip0 = (struct rte_ipv4_hdr *)((uint8_t *)d0 + - sizeof(struct rte_ether_hdr)); - chksum = node_mbuf_priv1(mbuf0, dyn)->cksum + - rte_cpu_to_be_16(0x0100); - chksum += chksum >= 0xffff; - ip0->hdr_checksum = chksum; - ip0->time_to_live = node_mbuf_priv1(mbuf0, dyn)->ttl - 1; - - if (unlikely(next_index ^ next0)) { + pvar.next0 = nh[node_mbuf_priv1(mbuf0, dyn)->nh].tx_node; + if (check_enabled_features) { + priv0 = node_mbuf_priv1(mbuf0, dyn); + if (pvar.next0 != (pvar.last_tx_interface + 1)) { + priv0->if_index = pvar.next0 - 1; + rte_graph_feature_arc_feature_set(out_feature_arc, flist, + priv0->if_index, + &priv0->current_feature, + &pvar.next0); + pvar.last_tx_interface = priv0->if_index; + pvar.last_if_feature = priv0->current_feature; + } else { + /* current mbuf index is same as last_tx_interface */ + priv0->if_index = pvar.last_tx_interface; + priv0->current_feature = pvar.last_if_feature; + } + } + /* Do the needful if either feature arc is disabled OR + * Invalid feature is present + */ + if (!check_enabled_features || + (priv0->current_feature == RTE_GRAPH_FEATURE_INVALID)) { + d0 = rte_pktmbuf_mtod(mbuf0, void *); + rte_memcpy(d0, nh[node_mbuf_priv1(mbuf0, dyn)->nh].rewrite_data, + nh[node_mbuf_priv1(mbuf0, dyn)->nh].rewrite_len); + + ip0 = (struct rte_ipv4_hdr *)((uint8_t *)d0 + + sizeof(struct rte_ether_hdr)); + chksum = node_mbuf_priv1(mbuf0, dyn)->cksum + + rte_cpu_to_be_16(0x0100); + chksum += chksum >= 0xffff; + ip0->hdr_checksum = chksum; + ip0->time_to_live = node_mbuf_priv1(mbuf0, dyn)->ttl - 1; + } + if (unlikely(next_index ^ pvar.next0)) { /* Copy things successfully speculated till now */ rte_memcpy(to_next, from, last_spec * sizeof(from[0])); from += last_spec; @@ -233,13 +470,15 @@ ip4_rewrite_node_process(struct rte_graph *graph, struct rte_node *node, held += last_spec; last_spec = 0; - rte_node_enqueue_x1(graph, node, next0, from[0]); + rte_node_enqueue_x1(graph, node, pvar.next0, from[0]); from += 1; } else { last_spec += 1; } } + IP4_REWRITE_NODE_LAST_TX(node->ctx) = pvar.last_tx_interface; + /* !!! Home run !!! */ if (likely(last_spec == nb_objs)) { rte_node_next_stream_move(graph, node, next_index); @@ -255,22 +494,78 @@ ip4_rewrite_node_process(struct rte_graph *graph, struct rte_node *node, return nb_objs; } +static uint16_t +ip4_rewrite_feature_node_process(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + struct rte_graph_feature_arc *arc = + rte_graph_feature_arc_get(IP4_REWRITE_NODE_OUTPUT_FEATURE_ARC(node->ctx)); + const int dyn = IP4_REWRITE_NODE_PRIV1_OFF(node->ctx); + rte_graph_feature_rt_list_t flist; + + /* If any feature is enabled on this arc */ + if (unlikely(rte_graph_feature_arc_has_any_feature(arc, &flist))) { + if (flist) + return __ip4_rewrite_node_process(graph, node, arc, objs, nb_objs, + dyn, + 1 /* check features */, + (rte_graph_feature_rt_list_t)1); + else + return __ip4_rewrite_node_process(graph, node, arc, objs, nb_objs, + dyn, + 1 /* check features */, + (rte_graph_feature_rt_list_t)0); + } else { + return __ip4_rewrite_node_process(graph, node, arc, objs, nb_objs, dyn, + 0/* don't check features*/, + 0/* don't care */); + } + return 0; +} + +static uint16_t +ip4_rewrite_node_process(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + const int dyn = IP4_REWRITE_NODE_PRIV1_OFF(node->ctx); + + return __ip4_rewrite_node_process(graph, node, NULL, objs, nb_objs, dyn, + 0/* don't check features*/, + 0/* don't care */); +} + static int ip4_rewrite_node_init(const struct rte_graph *graph, struct rte_node *node) { + rte_graph_feature_arc_t feature_arc = RTE_GRAPH_FEATURE_ARC_INITIALIZER; static bool init_once; RTE_SET_USED(graph); RTE_BUILD_BUG_ON(sizeof(struct ip4_rewrite_node_ctx) > RTE_NODE_CTX_SZ); + RTE_BUILD_BUG_ON(sizeof(struct ip4_rewrite_nh_header) != RTE_CACHE_LINE_MIN_SIZE); if (!init_once) { node_mbuf_priv1_dynfield_offset = rte_mbuf_dynfield_register( &node_mbuf_priv1_dynfield_desc); if (node_mbuf_priv1_dynfield_offset < 0) return -rte_errno; - init_once = true; + + /* Create ipv4-output feature arc, if not created + */ + if (rte_graph_feature_arc_lookup_by_name(RTE_IP4_OUTPUT_FEATURE_ARC_NAME, + NULL) < 0) { + if (rte_graph_feature_arc_create(RTE_IP4_OUTPUT_FEATURE_ARC_NAME, + RTE_GRAPH_FEATURE_MAX_PER_ARC, + RTE_MAX_ETHPORTS, + ip4_rewrite_node_get(), &feature_arc)) { + return -rte_errno; + } + init_once = true; + } } IP4_REWRITE_NODE_PRIV1_OFF(node->ctx) = node_mbuf_priv1_dynfield_offset; + IP4_REWRITE_NODE_OUTPUT_FEATURE_ARC(node->ctx) = feature_arc; + IP4_REWRITE_NODE_LAST_TX(node->ctx) = UINT16_MAX; node_dbg("ip4_rewrite", "Initialized ip4_rewrite node initialized"); @@ -329,6 +624,7 @@ rte_node_ip4_rewrite_add(uint16_t next_hop, uint8_t *rewrite_data, static struct rte_node_register ip4_rewrite_node = { .process = ip4_rewrite_node_process, + .feat_arc_proc = ip4_rewrite_feature_node_process, .name = "ip4_rewrite", /* Default edge i.e '0' is pkt drop */ .nb_edges = 1, diff --git a/lib/node/ip4_rewrite_priv.h b/lib/node/ip4_rewrite_priv.h index 5105ec1d29..27ccc67489 100644 --- a/lib/node/ip4_rewrite_priv.h +++ b/lib/node/ip4_rewrite_priv.h @@ -5,6 +5,7 @@ #define __INCLUDE_IP4_REWRITE_PRIV_H__ #include <rte_common.h> +#include <rte_graph_feature_arc.h> #define RTE_GRAPH_IP4_REWRITE_MAX_NH 64 #define RTE_GRAPH_IP4_REWRITE_MAX_LEN 56 @@ -15,11 +16,9 @@ * Ipv4 rewrite next hop header data structure. Used to store port specific * rewrite data. */ -struct ip4_rewrite_nh_header { - uint16_t rewrite_len; /**< Header rewrite length. */ +struct __rte_cache_min_aligned ip4_rewrite_nh_header { uint16_t tx_node; /**< Tx node next index identifier. */ - uint16_t enabled; /**< NH enable flag */ - uint16_t rsvd; + uint16_t rewrite_len; /**< Header rewrite length. */ union { struct { struct rte_ether_addr dst; @@ -30,6 +29,8 @@ struct ip4_rewrite_nh_header { uint8_t rewrite_data[RTE_GRAPH_IP4_REWRITE_MAX_LEN]; /**< Generic rewrite data */ }; + /* used in control path */ + uint8_t enabled; /**< NH enable flag */ }; /** diff --git a/lib/node/node_private.h b/lib/node/node_private.h index 1de7306792..7c26686948 100644 --- a/lib/node/node_private.h +++ b/lib/node/node_private.h @@ -12,6 +12,9 @@ #include <rte_mbuf.h> #include <rte_mbuf_dyn.h> +#include <rte_graph_worker_common.h> +#include <rte_graph_feature_arc_worker.h> + extern int rte_node_logtype; #define RTE_LOGTYPE_NODE rte_node_logtype @@ -29,13 +32,25 @@ extern int rte_node_logtype; */ struct node_mbuf_priv1 { union { - /* IP4/IP6 rewrite */ + /** + * IP4/IP6 rewrite + * only used to pass lookup data from + * ip4-lookup to ip4-rewrite + */ struct { uint16_t nh; uint16_t ttl; uint32_t cksum; }; - + /** + * Feature arc data + */ + struct { + /** interface index */ + uint16_t if_index; + /** feature that current mbuf holds */ + rte_graph_feature_t current_feature; + }; uint64_t u; }; }; diff --git a/lib/node/rte_node_ip4_api.h b/lib/node/rte_node_ip4_api.h index 24f8ec843a..0de06f7fc7 100644 --- a/lib/node/rte_node_ip4_api.h +++ b/lib/node/rte_node_ip4_api.h @@ -23,6 +23,7 @@ extern "C" { #include <rte_compat.h> #include <rte_graph.h> +#include <rte_graph_feature_arc_worker.h> /** * IP4 lookup next nodes. @@ -67,6 +68,8 @@ struct rte_node_ip4_reassembly_cfg { /**< Node identifier to configure. */ }; +#define RTE_IP4_OUTPUT_FEATURE_ARC_NAME "ipv4-output" + /** * Add ipv4 route to lookup table. * -- 2.43.0 ^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [RFC PATCH 0/3] add feature arc in rte_graph 2024-09-07 7:31 [RFC PATCH 0/3] add feature arc in rte_graph Nitin Saxena ` (2 preceding siblings ...) 2024-09-07 7:31 ` [RFC PATCH 3/3] graph: add IPv4 output feature arc Nitin Saxena @ 2024-10-08 8:04 ` David Marchand 2024-10-08 14:26 ` [EXTERNAL] " Nitin Saxena 2024-10-14 11:11 ` Nitin Saxena 2024-10-08 13:30 ` [RFC PATCH v2 0/5] " Nitin Saxena 4 siblings, 2 replies; 46+ messages in thread From: David Marchand @ 2024-10-08 8:04 UTC (permalink / raw) To: Nitin Saxena Cc: Jerin Jacob, Kiran Kumar K, Nithin Dabilpuram, Zhirun Yan, dev, Nitin Saxena, Robin Jarry, Christophe Fontaine Hi graph guys, On Sat, Sep 7, 2024 at 9:31 AM Nitin Saxena <nsaxena@marvell.com> wrote: > > Feature arc represents an ordered list of features/protocols at a given > networking layer. It is a high level abstraction to connect various > rte_graph nodes, as feature nodes, and allow packets steering across > these nodes in a generic manner. > > Features (or feature nodes) are nodes which handles partial or complete > handling of a protocol in fast path. Like ipv4-rewrite node, which adds > rewrite data to an outgoing IPv4 packet. > > However in above example, outgoing interface(say "eth0") may have > outbound IPsec policy enabled, hence packets must be steered from > ipv4-rewrite node to ipsec-outbound-policy node for outbound IPsec > policy lookup. On the other hand, packets routed to another interface > (eth1) will not be sent to ipsec-outbound-policy node as IPsec feature > is disabled on eth1. Feature-arc allows rte_graph applications to manage > such constraints easily > > Feature arc abstraction allows rte_graph based application to > > 1. Seamlessly steer packets across feature nodes based on wheter feature > is enabled or disabled on an interface. Features enabled on one > interface may not be enabled on another interface with in a same feature > arc. > > 2. Allow enabling/disabling of features on an interface at runtime, > so that if a feature is disabled, packets associated with that interface > won't be steered to corresponding feature node. > > 3. Provides mechanism to hook custom/user-defined nodes to a feature > node and allow packet steering from feature node to custom node without > changing former's fast path function > > 4. Allow expressing features in a particular sequential order so that > packets are steered in an ordered way across nodes in fast path. For > eg: if IPsec and IPv4 features are enabled on an ingress interface, > packets must be sent to IPsec inbound policy node first and then to ipv4 > lookup node. > > This patch series adds feature arc library in rte_graph and also adds > "ipv4-output" feature arc handling in "ipv4-rewrite" node. > > Nitin Saxena (3): > graph: add feature arc support > graph: add feature arc option in graph create > graph: add IPv4 output feature arc > > lib/graph/graph.c | 1 + > lib/graph/graph_feature_arc.c | 959 +++++++++++++++++++++++ > lib/graph/graph_populate.c | 7 +- > lib/graph/graph_private.h | 3 + > lib/graph/meson.build | 2 + > lib/graph/node.c | 2 + > lib/graph/rte_graph.h | 3 + > lib/graph/rte_graph_feature_arc.h | 373 +++++++++ > lib/graph/rte_graph_feature_arc_worker.h | 548 +++++++++++++ > lib/graph/version.map | 17 + > lib/node/ip4_rewrite.c | 476 ++++++++--- > lib/node/ip4_rewrite_priv.h | 9 +- > lib/node/node_private.h | 19 +- > lib/node/rte_node_ip4_api.h | 3 + > 14 files changed, 2325 insertions(+), 97 deletions(-) > create mode 100644 lib/graph/graph_feature_arc.c > create mode 100644 lib/graph/rte_graph_feature_arc.h > create mode 100644 lib/graph/rte_graph_feature_arc_worker.h I see no non-RFC series following this original submission. It will slip to next release unless there is an objection. Btw, I suggest copying Robin (and Christophe) for graph related changes. -- David Marchand ^ permalink raw reply [flat|nested] 46+ messages in thread
* RE: [EXTERNAL] Re: [RFC PATCH 0/3] add feature arc in rte_graph 2024-10-08 8:04 ` [RFC PATCH 0/3] add feature arc in rte_graph David Marchand @ 2024-10-08 14:26 ` Nitin Saxena 2024-10-14 11:11 ` Nitin Saxena 1 sibling, 0 replies; 46+ messages in thread From: Nitin Saxena @ 2024-10-08 14:26 UTC (permalink / raw) To: David Marchand Cc: Jerin Jacob, Kiran Kumar Kokkilagadda, Nithin Kumar Dabilpuram, Zhirun Yan, dev, Nitin Saxena, Robin Jarry, Christophe Fontaine Hi David, I just sent v2 version for this patch series. Will add Robin and Christophe from next version onwards Thanks, Nitin > -----Original Message----- > From: David Marchand <david.marchand@redhat.com> > Sent: Tuesday, October 8, 2024 1:34 PM > To: Nitin Saxena <nsaxena@marvell.com> > Cc: Jerin Jacob <jerinj@marvell.com>; Kiran Kumar Kokkilagadda > <kirankumark@marvell.com>; Nithin Kumar Dabilpuram > <ndabilpuram@marvell.com>; Zhirun Yan <yanzhirun_163@163.com>; > dev@dpdk.org; Nitin Saxena <nsaxena16@gmail.com>; Robin Jarry > <rjarry@redhat.com>; Christophe Fontaine <cfontain@redhat.com> > Subject: [EXTERNAL] Re: [RFC PATCH 0/3] add feature arc in rte_graph > > Hi graph guys, On Sat, Sep 7, 2024 at 9: 31 AM Nitin Saxena > <nsaxena@ marvell. com> wrote: > > Feature arc represents an ordered list of > features/protocols at a given > networking layer. It is a high level abstraction > to connect > Hi graph guys, > > On Sat, Sep 7, 2024 at 9:31 AM Nitin Saxena <nsaxena@marvell.com> wrote: > > > > Feature arc represents an ordered list of features/protocols at a > > given networking layer. It is a high level abstraction to connect > > various rte_graph nodes, as feature nodes, and allow packets steering > > across these nodes in a generic manner. > > > > Features (or feature nodes) are nodes which handles partial or > > complete handling of a protocol in fast path. Like ipv4-rewrite node, > > which adds rewrite data to an outgoing IPv4 packet. > > > > However in above example, outgoing interface(say "eth0") may have > > outbound IPsec policy enabled, hence packets must be steered from > > ipv4-rewrite node to ipsec-outbound-policy node for outbound IPsec > > policy lookup. On the other hand, packets routed to another interface > > (eth1) will not be sent to ipsec-outbound-policy node as IPsec feature > > is disabled on eth1. Feature-arc allows rte_graph applications to > > manage such constraints easily > > > > Feature arc abstraction allows rte_graph based application to > > > > 1. Seamlessly steer packets across feature nodes based on wheter > > feature is enabled or disabled on an interface. Features enabled on > > one interface may not be enabled on another interface with in a same > > feature arc. > > > > 2. Allow enabling/disabling of features on an interface at runtime, so > > that if a feature is disabled, packets associated with that interface > > won't be steered to corresponding feature node. > > > > 3. Provides mechanism to hook custom/user-defined nodes to a feature > > node and allow packet steering from feature node to custom node > > without changing former's fast path function > > > > 4. Allow expressing features in a particular sequential order so that > > packets are steered in an ordered way across nodes in fast path. For > > eg: if IPsec and IPv4 features are enabled on an ingress interface, > > packets must be sent to IPsec inbound policy node first and then to > > ipv4 lookup node. > > > > This patch series adds feature arc library in rte_graph and also adds > > "ipv4-output" feature arc handling in "ipv4-rewrite" node. > > > > Nitin Saxena (3): > > graph: add feature arc support > > graph: add feature arc option in graph create > > graph: add IPv4 output feature arc > > > > lib/graph/graph.c | 1 + > > lib/graph/graph_feature_arc.c | 959 +++++++++++++++++++++++ > > lib/graph/graph_populate.c | 7 +- > > lib/graph/graph_private.h | 3 + > > lib/graph/meson.build | 2 + > > lib/graph/node.c | 2 + > > lib/graph/rte_graph.h | 3 + > > lib/graph/rte_graph_feature_arc.h | 373 +++++++++ > > lib/graph/rte_graph_feature_arc_worker.h | 548 +++++++++++++ > > lib/graph/version.map | 17 + > > lib/node/ip4_rewrite.c | 476 ++++++++--- > > lib/node/ip4_rewrite_priv.h | 9 +- > > lib/node/node_private.h | 19 +- > > lib/node/rte_node_ip4_api.h | 3 + > > 14 files changed, 2325 insertions(+), 97 deletions(-) create mode > > 100644 lib/graph/graph_feature_arc.c create mode 100644 > > lib/graph/rte_graph_feature_arc.h create mode 100644 > > lib/graph/rte_graph_feature_arc_worker.h > > I see no non-RFC series following this original submission. > It will slip to next release unless there is an objection. > > Btw, I suggest copying Robin (and Christophe) for graph related changes. > > > -- > David Marchand ^ permalink raw reply [flat|nested] 46+ messages in thread
* RE: [EXTERNAL] Re: [RFC PATCH 0/3] add feature arc in rte_graph 2024-10-08 8:04 ` [RFC PATCH 0/3] add feature arc in rte_graph David Marchand 2024-10-08 14:26 ` [EXTERNAL] " Nitin Saxena @ 2024-10-14 11:11 ` Nitin Saxena 2024-10-16 9:24 ` David Marchand 1 sibling, 1 reply; 46+ messages in thread From: Nitin Saxena @ 2024-10-14 11:11 UTC (permalink / raw) To: David Marchand Cc: Jerin Jacob, Kiran Kumar Kokkilagadda, Nithin Kumar Dabilpuram, Zhirun Yan, dev, Nitin Saxena, Robin Jarry, Christophe Fontaine Hi David and all, >> I see no non-RFC series following this original submission. >> It will slip to next release unless there is an objection. I had pushed non RFC patch series before -rc1 date (11th oct). We have an ABI change in this patch series https://patches.dpdk.org/project/dpdk/patch/20241010133111.2764712-3-nsaxena@marvell.com/ Could you help merge this patch series in rc2 otherwise it has to wait for next LTS Thanks, Nitin > -----Original Message----- > From: David Marchand <david.marchand@redhat.com> > Sent: Tuesday, October 8, 2024 1:34 PM > To: Nitin Saxena <nsaxena@marvell.com> > Cc: Jerin Jacob <jerinj@marvell.com>; Kiran Kumar Kokkilagadda > <kirankumark@marvell.com>; Nithin Kumar Dabilpuram > <ndabilpuram@marvell.com>; Zhirun Yan <yanzhirun_163@163.com>; > dev@dpdk.org; Nitin Saxena <nsaxena16@gmail.com>; Robin Jarry > <rjarry@redhat.com>; Christophe Fontaine <cfontain@redhat.com> > Subject: [EXTERNAL] Re: [RFC PATCH 0/3] add feature arc in rte_graph > > Hi graph guys, On Sat, Sep 7, 2024 at 9: 31 AM Nitin Saxena > <nsaxena@ marvell. com> wrote: > > Feature arc represents an ordered list of > features/protocols at a given > networking layer. It is a high level abstraction > to connect > Hi graph guys, > > On Sat, Sep 7, 2024 at 9:31 AM Nitin Saxena <nsaxena@marvell.com> wrote: > > > > Feature arc represents an ordered list of features/protocols at a > > given networking layer. It is a high level abstraction to connect > > various rte_graph nodes, as feature nodes, and allow packets steering > > across these nodes in a generic manner. > > > > Features (or feature nodes) are nodes which handles partial or > > complete handling of a protocol in fast path. Like ipv4-rewrite node, > > which adds rewrite data to an outgoing IPv4 packet. > > > > However in above example, outgoing interface(say "eth0") may have > > outbound IPsec policy enabled, hence packets must be steered from > > ipv4-rewrite node to ipsec-outbound-policy node for outbound IPsec > > policy lookup. On the other hand, packets routed to another interface > > (eth1) will not be sent to ipsec-outbound-policy node as IPsec feature > > is disabled on eth1. Feature-arc allows rte_graph applications to > > manage such constraints easily > > > > Feature arc abstraction allows rte_graph based application to > > > > 1. Seamlessly steer packets across feature nodes based on wheter > > feature is enabled or disabled on an interface. Features enabled on > > one interface may not be enabled on another interface with in a same > > feature arc. > > > > 2. Allow enabling/disabling of features on an interface at runtime, so > > that if a feature is disabled, packets associated with that interface > > won't be steered to corresponding feature node. > > > > 3. Provides mechanism to hook custom/user-defined nodes to a feature > > node and allow packet steering from feature node to custom node > > without changing former's fast path function > > > > 4. Allow expressing features in a particular sequential order so that > > packets are steered in an ordered way across nodes in fast path. For > > eg: if IPsec and IPv4 features are enabled on an ingress interface, > > packets must be sent to IPsec inbound policy node first and then to > > ipv4 lookup node. > > > > This patch series adds feature arc library in rte_graph and also adds > > "ipv4-output" feature arc handling in "ipv4-rewrite" node. > > > > Nitin Saxena (3): > > graph: add feature arc support > > graph: add feature arc option in graph create > > graph: add IPv4 output feature arc > > > > lib/graph/graph.c | 1 + > > lib/graph/graph_feature_arc.c | 959 +++++++++++++++++++++++ > > lib/graph/graph_populate.c | 7 +- > > lib/graph/graph_private.h | 3 + > > lib/graph/meson.build | 2 + > > lib/graph/node.c | 2 + > > lib/graph/rte_graph.h | 3 + > > lib/graph/rte_graph_feature_arc.h | 373 +++++++++ > > lib/graph/rte_graph_feature_arc_worker.h | 548 +++++++++++++ > > lib/graph/version.map | 17 + > > lib/node/ip4_rewrite.c | 476 ++++++++--- > > lib/node/ip4_rewrite_priv.h | 9 +- > > lib/node/node_private.h | 19 +- > > lib/node/rte_node_ip4_api.h | 3 + > > 14 files changed, 2325 insertions(+), 97 deletions(-) create mode > > 100644 lib/graph/graph_feature_arc.c create mode 100644 > > lib/graph/rte_graph_feature_arc.h create mode 100644 > > lib/graph/rte_graph_feature_arc_worker.h > > I see no non-RFC series following this original submission. > It will slip to next release unless there is an objection. > > Btw, I suggest copying Robin (and Christophe) for graph related changes. > > > -- > David Marchand ^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [EXTERNAL] Re: [RFC PATCH 0/3] add feature arc in rte_graph 2024-10-14 11:11 ` Nitin Saxena @ 2024-10-16 9:24 ` David Marchand 2024-10-16 9:38 ` Robin Jarry 0 siblings, 1 reply; 46+ messages in thread From: David Marchand @ 2024-10-16 9:24 UTC (permalink / raw) To: Nitin Saxena Cc: Jerin Jacob, Kiran Kumar Kokkilagadda, Nithin Kumar Dabilpuram, Zhirun Yan, dev, Nitin Saxena, Robin Jarry, Christophe Fontaine On Mon, Oct 14, 2024 at 1:12 PM Nitin Saxena <nsaxena@marvell.com> wrote: > I had pushed non RFC patch series before -rc1 date (11th oct). > We have an ABI change in this patch series https://patches.dpdk.org/project/dpdk/patch/20241010133111.2764712-3-nsaxena@marvell.com/ > Could you help merge this patch series in rc2 otherwise it has to wait for next LTS Just read through the series, I am not confident with this addition. It requires a lot of changes in the node code for supporting it, where it should be something handled in/facilitated by the graph library itself. I did not read much from Robin or Christophe who have been writing more node code than me. I would prefer their opinion before going forward. On the ABI topic. As far as I can see, the only issue would be in extending struct rte_node_register, but this can be solved with function versioning. That change would have to be announced. Am I missing something else? -- David Marchand ^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [EXTERNAL] Re: [RFC PATCH 0/3] add feature arc in rte_graph 2024-10-16 9:24 ` David Marchand @ 2024-10-16 9:38 ` Robin Jarry 2024-10-16 13:50 ` Nitin Saxena 0 siblings, 1 reply; 46+ messages in thread From: Robin Jarry @ 2024-10-16 9:38 UTC (permalink / raw) To: David Marchand, Nitin Saxena Cc: Jerin Jacob, Kiran Kumar Kokkilagadda, Nithin Kumar Dabilpuram, Zhirun Yan, dev, Nitin Saxena, Christophe Fontaine Hi folks, David Marchand, Oct 16, 2024 at 11:24: > On Mon, Oct 14, 2024 at 1:12 PM Nitin Saxena <nsaxena@marvell.com> wrote: >> I had pushed non RFC patch series before -rc1 date (11th oct). >> We have an ABI change in this patch series https://patches.dpdk.org/project/dpdk/patch/20241010133111.2764712-3-nsaxena@marvell.com/ >> Could you help merge this patch series in rc2 otherwise it has to wait for next LTS > > Just read through the series, I am not confident with this addition. > It requires a lot of changes in the node code for supporting it, where > it should be something handled in/facilitated by the graph library > itself. As far as I can tell, it will be very complicated (if not impossible) to determine in a generic manner whether a packet must be steered towards a sub tree or not. The decision *must* come from the originating node in some way or another. > I did not read much from Robin or Christophe who have been writing > more node code than me. > I would prefer their opinion before going forward. This series is indeed very dense. I like the concept of having extensible sub trees in the graph but it feels like the implementation is more complex than it should be. Lacking of another solution, we went for a naive approach in grout. Basically, some nodes have undefined next nodes which are extended using a dedicated API. https://github.com/DPDK/grout/blob/v0.2/modules/infra/datapath/eth_input.c#L23-L31 This API can be used by other nodes to attach themselves to these extensible nodes: https://github.com/DPDK/grout/blob/v0.2/modules/ip/datapath/arp_input.c#L143 https://github.com/DPDK/grout/blob/v0.2/modules/ip/datapath/ip_input.c#L124 https://github.com/DPDK/grout/blob/v0.2/modules/ip6/datapath/ip6_input.c#L122 After which, the extensible nodes can steer the packets towards the correct downstream edge based on the dedicated classifier field: https://github.com/DPDK/grout/blob/v0.2/modules/infra/datapath/eth_input.c#L79 Obviously, this does not natively support a per-interface sub tree traversal, but it can be done in the originating node based on packet private context data. This raises a more important question: how can we standardize the way private application data is passed from node to node? And how could we enforce this declaratively in the node register API? Do you think we could find some middle ground that would not require such extensive changes? Cheers, Robin ^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [EXTERNAL] Re: [RFC PATCH 0/3] add feature arc in rte_graph 2024-10-16 9:38 ` Robin Jarry @ 2024-10-16 13:50 ` Nitin Saxena 2024-10-17 7:03 ` Nitin Saxena 0 siblings, 1 reply; 46+ messages in thread From: Nitin Saxena @ 2024-10-16 13:50 UTC (permalink / raw) To: Robin Jarry Cc: David Marchand, Nitin Saxena, Jerin Jacob, Kiran Kumar Kokkilagadda, Nithin Kumar Dabilpuram, Zhirun Yan, dev, Christophe Fontaine Hi Robin, Thanks for the review Please see my replies inline Thanks, Nitin On Wed, Oct 16, 2024 at 3:08 PM Robin Jarry <rjarry@redhat.com> wrote: > > Hi folks, > > David Marchand, Oct 16, 2024 at 11:24: > > On Mon, Oct 14, 2024 at 1:12 PM Nitin Saxena <nsaxena@marvell.com> wrote: > >> I had pushed non RFC patch series before -rc1 date (11th oct). > >> We have an ABI change in this patch series https://patches.dpdk.org/project/dpdk/patch/20241010133111.2764712-3-nsaxena@marvell.com/ > >> Could you help merge this patch series in rc2 otherwise it has to wait for next LTS > > > > Just read through the series, I am not confident with this addition. > > It requires a lot of changes in the node code for supporting it, where > > it should be something handled in/facilitated by the graph library > > itself. > > As far as I can tell, it will be very complicated (if not impossible) to > determine in a generic manner whether a packet must be steered towards > a sub tree or not. The decision *must* come from the originating node in > some way or another. Nitin> I am not sure if it *must* always be from the originating node? What about a control plane which wants to enable "IP4 feature" on interface 'X' by assigning IP address? A originating node (say: ip4-input) *must not* activate IP4 lookup sub-graph for interface "X " until control plane assigns any IP address to it. Regarding the complexity of adopting feature arc changes in fast path, - a sub-optimal change for feature-arc would be simple and trivial but at the cost of performance. - Complexity increases when feature arc changes are optimally integrated (like "ip4_rewrite" changes in the patch) with no performance regression > > > I did not read much from Robin or Christophe who have been writing > > more node code than me. > > I would prefer their opinion before going forward. > > This series is indeed very dense. I like the concept of having > extensible sub trees in the graph but it feels like the implementation > is more complex than it should be. > > Lacking of another solution, we went for a naive approach in grout. > Basically, some nodes have undefined next nodes which are extended using > a dedicated API. Nitin> With an initial glance, it looks like "grout" is trying to solve a use-case where a child is being added to the parent's undefined next node. This is trying to create a runtime parent-child relationship On the other hand, feature arc not just create parent-child relationships but also sibling-sibling relationships as well. Also enabling sub-graph per interface is critical functionality in feature arc that adds complexity Let's assume a use-case in ingress direction, at the IPv4 layer, where IPv4-input is the *originating node* and - On interface X, IPsec-policy, IP4-classify() and IPv4-lookup sub-graphs are enabled in a sequential order - On interface Y, IP4-classify() and IPv4-lookup sub-graphs are enabled. in a sequential order. i.e. IPsec-policy is *disabled* on interface Y In fast path, following processing should happen for "mbuf0" which is received on interface "X" - "ipv4-input" sends mbuf0 to the first enabled sub-graph node for interface X, "IPsec-policy" - In "IPsec-policy" node processing, if policy action results in "bypass" action for mbuf0, it must then be sent to next enabled sub-graph i.e. "IPv4-classify" (from "IPsec-policy" node) - In "IPv4-classify" node processing, if classify fails for mbuf0 then it should finally be sent to "IPv4-lookup" node (from "IPv4-classify" node) whereas for "mbuf1" received on interface Y following fast path processing must happen - "Ipv4-input" sends mbuf1 to the first enabled sub-graph node for interface Y, "IPv4-classify" - If "IPv4-classify" fails for mbuf1, then it should finally be sent to IPv4-lookup node To behave differently for interface X and interface Y as above - First of all, IPsec-policy/IPv4-classify/IPv4-lookup must be connected to "ipv4-input" node (Parent-Child relationship) - Also, IPsec-policy/IPv4-classify/IPv4-lookup must also be connected with each other (Sibling-Sibling relationship) - Fast path APIs provide *rte_edges_t* to send mbuf from one node to another node 1. Based on interface (either Interface X or Interface Y) 2. Based on which node, fast path APIs are called. Next enabled feature/sub-graph can only be determined from previous enabled feature/sub-graph in fast path Not sure if grout handles above use-cases in the same manner. AFAIR , for any control plane change grout re-creates "graph" objects which may not be required with feature arc. > > https://github.com/DPDK/grout/blob/v0.2/modules/infra/datapath/eth_input.c#L23-L31 > > This API can be used by other nodes to attach themselves to these > extensible nodes: > > https://github.com/DPDK/grout/blob/v0.2/modules/ip/datapath/arp_input.c#L143 > https://github.com/DPDK/grout/blob/v0.2/modules/ip/datapath/ip_input.c#L124 > https://github.com/DPDK/grout/blob/v0.2/modules/ip6/datapath/ip6_input.c#L122 > > After which, the extensible nodes can steer the packets towards the > correct downstream edge based on the dedicated classifier field: > > https://github.com/DPDK/grout/blob/v0.2/modules/infra/datapath/eth_input.c#L79 > > Obviously, this does not natively support a per-interface sub tree > traversal, but it can be done in the originating node based on packet > private context data. Nitin> Expressing per interface sub-tree traversal is the key functionality of feature arc. > > This raises a more important question: how can we standardize the way > private application data is passed from node to node? And how could we > enforce this declaratively in the node register API? Nitin> What you are suggesting here (node to node application data exchange) can be done in rte_node_register API but, IMO, this is not related to feature arc. Feature arc is not just between parent and child nodes but also between siblings (as explained above) > > Do you think we could find some middle ground that would not require > such extensive changes? Nitin> If you are pointing to ipv4-rewrite changes, I had an internal review comment of adding those changes without any *performance regression*. A sub-optimal code would be much simpler but at the cost of performance. > > Cheers, > Robin > ^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [EXTERNAL] Re: [RFC PATCH 0/3] add feature arc in rte_graph 2024-10-16 13:50 ` Nitin Saxena @ 2024-10-17 7:03 ` Nitin Saxena 2024-10-17 7:50 ` Robin Jarry 0 siblings, 1 reply; 46+ messages in thread From: Nitin Saxena @ 2024-10-17 7:03 UTC (permalink / raw) To: Robin Jarry Cc: David Marchand, Nitin Saxena, Jerin Jacob, Kiran Kumar Kokkilagadda, Nithin Kumar Dabilpuram, Zhirun Yan, dev, Christophe Fontaine Hi Robin/David and all, We realized the feature arc patch series is difficult to understand as a new concept. Our objectives are following with feature arc changes 1. Allow reusability of standard DPDK nodes (defined in lib/nodes/*) with out-of-tree applications (like grout). Currently out-of-tree graph applications are duplicating standard nodes but not reusing the standard ones which are available. In the long term, we would like to mature standard DPDK nodes with flexibility of hooking them to out-of-tree application nodes. 2. Flexibility to enable/disable sub-graphs per interface based on the runtime configuration updates. Protocol sub-graphs can be selectively enabled for few (or all interfaces) at runtime 3. More than one sub-graphs/features can be enabled on an interface. So a packet has to follow a sequential ordering node path on worker cores. Packets may need to move from one sub-graph to another sub-graph per interface 4. Last but not least, an optimized implementation which does not (or minimally) stop worker cores for any control plane runtime updates. Any performance regression should also be avoided I am planning to create a draft presentation on feature arc which I can share, when ready, to discuss. If needed, I can also plan to present that in one of the DPDK community meetings. Their we can also discuss if there are any alternatives of achieving above objectives Thanks, Nitin . On Wed, Oct 16, 2024 at 7:20 PM Nitin Saxena <nsaxena16@gmail.com> wrote: > > Hi Robin, > > Thanks for the review > Please see my replies inline > > Thanks, > Nitin > > On Wed, Oct 16, 2024 at 3:08 PM Robin Jarry <rjarry@redhat.com> wrote: > > > > Hi folks, > > > > David Marchand, Oct 16, 2024 at 11:24: > > > On Mon, Oct 14, 2024 at 1:12 PM Nitin Saxena <nsaxena@marvell.com> wrote: > > >> I had pushed non RFC patch series before -rc1 date (11th oct). > > >> We have an ABI change in this patch series https://patches.dpdk.org/project/dpdk/patch/20241010133111.2764712-3-nsaxena@marvell.com/ > > >> Could you help merge this patch series in rc2 otherwise it has to wait for next LTS > > > > > > Just read through the series, I am not confident with this addition. > > > It requires a lot of changes in the node code for supporting it, where > > > it should be something handled in/facilitated by the graph library > > > itself. > > > > As far as I can tell, it will be very complicated (if not impossible) to > > determine in a generic manner whether a packet must be steered towards > > a sub tree or not. The decision *must* come from the originating node in > > some way or another. > > Nitin> I am not sure if it *must* always be from the originating node? > What about a control plane which wants to enable "IP4 feature" on > interface 'X' by assigning IP address? > A originating node (say: ip4-input) *must not* activate IP4 lookup > sub-graph for interface "X " until control plane assigns any IP > address to it. > > Regarding the complexity of adopting feature arc changes in fast path, > - a sub-optimal change for feature-arc would be simple and trivial but > at the cost of performance. > - Complexity increases when feature arc changes are optimally > integrated (like "ip4_rewrite" changes in the patch) with no > performance regression > > > > > > I did not read much from Robin or Christophe who have been writing > > > more node code than me. > > > I would prefer their opinion before going forward. > > > > This series is indeed very dense. I like the concept of having > > extensible sub trees in the graph but it feels like the implementation > > is more complex than it should be. > > > > Lacking of another solution, we went for a naive approach in grout. > > Basically, some nodes have undefined next nodes which are extended using > > a dedicated API. > > Nitin> With an initial glance, it looks like "grout" is trying to > solve a use-case where a child is being added to the parent's > undefined next node. This is trying to create a runtime parent-child > relationship > > On the other hand, feature arc not just create parent-child > relationships but also sibling-sibling relationships as well. Also > enabling sub-graph per interface is critical functionality in feature > arc that adds complexity > > Let's assume a use-case in ingress direction, at the IPv4 layer, > where IPv4-input is the *originating node* and > > - On interface X, IPsec-policy, IP4-classify() and IPv4-lookup > sub-graphs are enabled in a sequential order > - On interface Y, IP4-classify() and IPv4-lookup sub-graphs are > enabled. in a sequential order. i.e. IPsec-policy is *disabled* on > interface Y > > In fast path, following processing should happen for "mbuf0" which is > received on interface "X" > - "ipv4-input" sends mbuf0 to the first enabled sub-graph node for > interface X, "IPsec-policy" > - In "IPsec-policy" node processing, if policy action results in > "bypass" action for mbuf0, it must then be sent to next enabled > sub-graph i.e. "IPv4-classify" (from "IPsec-policy" node) > - In "IPv4-classify" node processing, if classify fails for mbuf0 then > it should finally be sent to "IPv4-lookup" node (from "IPv4-classify" > node) > > whereas for "mbuf1" received on interface Y following fast path > processing must happen > - "Ipv4-input" sends mbuf1 to the first enabled sub-graph node for > interface Y, "IPv4-classify" > - If "IPv4-classify" fails for mbuf1, then it should finally be sent > to IPv4-lookup node > > To behave differently for interface X and interface Y as above > - First of all, IPsec-policy/IPv4-classify/IPv4-lookup must be > connected to "ipv4-input" node (Parent-Child relationship) > - Also, IPsec-policy/IPv4-classify/IPv4-lookup must also be connected > with each other (Sibling-Sibling relationship) > - Fast path APIs provide *rte_edges_t* to send mbuf from one node to > another node > 1. Based on interface (either Interface X or Interface Y) > 2. Based on which node, fast path APIs are called. Next enabled > feature/sub-graph can only be determined from previous enabled > feature/sub-graph in fast path > > Not sure if grout handles above use-cases in the same manner. AFAIR , > for any control plane change grout re-creates "graph" objects which > may not be required with feature arc. > > > > > https://github.com/DPDK/grout/blob/v0.2/modules/infra/datapath/eth_input.c#L23-L31 > > > > This API can be used by other nodes to attach themselves to these > > extensible nodes: > > > > https://github.com/DPDK/grout/blob/v0.2/modules/ip/datapath/arp_input.c#L143 > > https://github.com/DPDK/grout/blob/v0.2/modules/ip/datapath/ip_input.c#L124 > > https://github.com/DPDK/grout/blob/v0.2/modules/ip6/datapath/ip6_input.c#L122 > > > > After which, the extensible nodes can steer the packets towards the > > correct downstream edge based on the dedicated classifier field: > > > > https://github.com/DPDK/grout/blob/v0.2/modules/infra/datapath/eth_input.c#L79 > > > > Obviously, this does not natively support a per-interface sub tree > > traversal, but it can be done in the originating node based on packet > > private context data. > > Nitin> Expressing per interface sub-tree traversal is the key > functionality of feature arc. > > > > > This raises a more important question: how can we standardize the way > > private application data is passed from node to node? And how could we > > enforce this declaratively in the node register API? > > Nitin> What you are suggesting here (node to node application data > exchange) can be done in rte_node_register API but, IMO, this is not > related to feature arc. > Feature arc is not just between parent and child nodes but also > between siblings (as explained above) > > > > > Do you think we could find some middle ground that would not require > > such extensive changes? > > Nitin> If you are pointing to ipv4-rewrite changes, I had an internal > review comment of adding those changes without any *performance > regression*. > A sub-optimal code would be much simpler but at the cost of performance. > > > > > Cheers, > > Robin > > ^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [EXTERNAL] Re: [RFC PATCH 0/3] add feature arc in rte_graph 2024-10-17 7:03 ` Nitin Saxena @ 2024-10-17 7:50 ` Robin Jarry 2024-10-17 8:32 ` [EXTERNAL] " Christophe Fontaine 2024-10-17 8:48 ` [EXTERNAL] " Nitin Saxena 0 siblings, 2 replies; 46+ messages in thread From: Robin Jarry @ 2024-10-17 7:50 UTC (permalink / raw) To: Nitin Saxena Cc: David Marchand, Nitin Saxena, Jerin Jacob, Kiran Kumar Kokkilagadda, Nithin Kumar Dabilpuram, Zhirun Yan, dev, Christophe Fontaine Hi Nitin, all, Nitin Saxena, Oct 17, 2024 at 09:03: > Hi Robin/David and all, > > We realized the feature arc patch series is difficult to understand as > a new concept. Our objectives are following with feature arc changes > > 1. Allow reusability of standard DPDK nodes (defined in lib/nodes/*) > with out-of-tree applications (like grout). Currently out-of-tree > graph applications are duplicating standard nodes but not reusing > the standard ones which are available. In the long term, we would > like to mature standard DPDK nodes with flexibility of hooking them > to out-of-tree application nodes. It would be ideal if the in-built nodes could be reused. When we started working on grout, I tried multiple approaches where I could reuse these nodes, but all failed. The nodes public API seems tailored for app/graph but does not fit well with other control plane implementations. One of the main issues I had is that the ethdev_rx and ethdev_tx nodes are cloned per rxq / txq associated with a graph worker. The rte_node API requires that every clone has a unique name. This in turn makes hot plugging of DPDK ports very complex, if not impossible. For example, with the in-built nodes, it is not possible to change the number of ports or their number of RX queues without destroying the whole graph and creating a new one from scratch. Also, the current implementation of "ip{4,6}-rewrite" handles writing ethernet header data. This would prevent it from using this node for an IP-in-IP tunnel interface as we did in grout. Do you think we could change the in-built nodes to enforce OSI layer separation of concerns? It would make them much more flexible. It may cause a slight drop of performance because you'd be splitting processing in two different nodes. But I think flexibility is more important. Otherwise, the in-built nodes can only be used for very specific use-cases. Finally, I would like to improve the rte_node API to allow defining and enforcing per-packet metadata that every node expects as input. The current in-built nodes rely on mbuf dynamic fields for this but this means you only have 9x32 bits available. And using all of these may break some drivers (ixgbe) that rely on dynfields to work. Have you considered using mbuf private data for this? > > 2. Flexibility to enable/disable sub-graphs per interface based on the > runtime configuration updates. Protocol sub-graphs can be > selectively enabled for few (or all interfaces) at runtime > > 3. More than one sub-graphs/features can be enabled on an interface. > So a packet has to follow a sequential ordering node path on worker > cores. Packets may need to move from one sub-graph to another > sub-graph per interface > > 4. Last but not least, an optimized implementation which does not (or > minimally) stop worker cores for any control plane runtime updates. > Any performance regression should also be avoided > > I am planning to create a draft presentation on feature arc which > I can share, when ready, to discuss. If needed, I can also plan to > present that in one of the DPDK community meetings. Their we can also > discuss if there are any alternatives of achieving above objectives Looking forward to this. Thanks! ^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [EXTERNAL] [RFC PATCH 0/3] add feature arc in rte_graph 2024-10-17 7:50 ` Robin Jarry @ 2024-10-17 8:32 ` Christophe Fontaine 2024-10-17 10:56 ` Nitin Saxena 2024-10-17 8:48 ` [EXTERNAL] " Nitin Saxena 1 sibling, 1 reply; 46+ messages in thread From: Christophe Fontaine @ 2024-10-17 8:32 UTC (permalink / raw) To: Robin Jarry Cc: Nitin Saxena, David Marchand, Nitin Saxena, Jerin Jacob, Kiran Kumar Kokkilagadda, Nithin Kumar Dabilpuram, Zhirun Yan, dev Hi all, What about the following steps: - update the nodes so they work on the current layer (example: for all L3 nodes, the current mbuf data offset *must* be pointing to the IP header) - define a public data structure that would be shared across nodes through priv data, and not dynfields ? This structure would be the "internal api" (so, that has to be tracked across dpdk releases) between nodes. We’d need common data shared for all the nodes as well as specific data between 2 nodes. As we get to this point, this (hopefully) will help with the node reusability. - Update the feature arcs to leverage this well known structure, and refine the api - Define which part of the stack needs to be defined as a feature arc, with the benefit of the generic API to enable/disable that feature, and which part needs to be dynamically pluggable. For instance, for a router, it may not make sense to define IPv4 support as a feature arc. So, we’d statically connect eth_input to ip_input. Yet, lldp support is a good candidate for a feature arc: we need to configure it per interface, and this is independent of the main graph. WDYT? Christophe > On 17 Oct 2024, at 09:50, Robin Jarry <rjarry@redhat.com> wrote: > > Hi Nitin, all, > > Nitin Saxena, Oct 17, 2024 at 09:03: >> Hi Robin/David and all, >> >> We realized the feature arc patch series is difficult to understand as a new concept. Our objectives are following with feature arc changes >> >> 1. Allow reusability of standard DPDK nodes (defined in lib/nodes/*) with out-of-tree applications (like grout). Currently out-of-tree graph applications are duplicating standard nodes but not reusing the standard ones which are available. In the long term, we would like to mature standard DPDK nodes with flexibility of hooking them to out-of-tree application nodes. > > It would be ideal if the in-built nodes could be reused. When we started working on grout, I tried multiple approaches where I could reuse these nodes, but all failed. The nodes public API seems tailored for app/graph but does not fit well with other control plane implementations. > > One of the main issues I had is that the ethdev_rx and ethdev_tx nodes are cloned per rxq / txq associated with a graph worker. The rte_node API requires that every clone has a unique name. This in turn makes hot plugging of DPDK ports very complex, if not impossible. > > For example, with the in-built nodes, it is not possible to change the number of ports or their number of RX queues without destroying the whole graph and creating a new one from scratch. > > Also, the current implementation of "ip{4,6}-rewrite" handles writing ethernet header data. This would prevent it from using this node for an IP-in-IP tunnel interface as we did in grout. > > Do you think we could change the in-built nodes to enforce OSI layer separation of concerns? It would make them much more flexible. It may cause a slight drop of performance because you'd be splitting processing in two different nodes. But I think flexibility is more important. Otherwise, the in-built nodes can only be used for very specific use-cases. > > Finally, I would like to improve the rte_node API to allow defining and enforcing per-packet metadata that every node expects as input. The current in-built nodes rely on mbuf dynamic fields for this but this means you only have 9x32 bits available. And using all of these may break some drivers (ixgbe) that rely on dynfields to work. Have you considered using mbuf private data for this? > >> >> 2. Flexibility to enable/disable sub-graphs per interface based on the runtime configuration updates. Protocol sub-graphs can be selectively enabled for few (or all interfaces) at runtime >> >> 3. More than one sub-graphs/features can be enabled on an interface. So a packet has to follow a sequential ordering node path on worker cores. Packets may need to move from one sub-graph to another sub-graph per interface >> >> 4. Last but not least, an optimized implementation which does not (or minimally) stop worker cores for any control plane runtime updates. Any performance regression should also be avoided >> >> I am planning to create a draft presentation on feature arc which I can share, when ready, to discuss. If needed, I can also plan to present that in one of the DPDK community meetings. Their we can also discuss if there are any alternatives of achieving above objectives > > Looking forward to this. > > Thanks! > ^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [EXTERNAL] [RFC PATCH 0/3] add feature arc in rte_graph 2024-10-17 8:32 ` [EXTERNAL] " Christophe Fontaine @ 2024-10-17 10:56 ` Nitin Saxena 0 siblings, 0 replies; 46+ messages in thread From: Nitin Saxena @ 2024-10-17 10:56 UTC (permalink / raw) To: Christophe Fontaine Cc: Robin Jarry, David Marchand, Nitin Saxena, Jerin Jacob, Kiran Kumar Kokkilagadda, Nithin Kumar Dabilpuram, Zhirun Yan, dev Hi Christophe, Please see inline comments Thanks, Nitin On Thu, Oct 17, 2024 at 2:02 PM Christophe Fontaine <cfontain@redhat.com> wrote: > > Hi all, > > What about the following steps: > - update the nodes so they work on the current layer (example: for all L3 nodes, the current mbuf data offset *must* be pointing to the IP header) Agreed. It would be better if nodes uses rte_pktmbuf_[append()/shrink() etc..] APIs to manipulate layer data offset > - define a public data structure that would be shared across nodes through priv data, and not dynfields ? Eventually public data structures should be defined to serve *a purpose*. Do you refer to creating a generic public structure? If yes, IMO, it may not be tuned for performance IMO, we need to create public structures for each specific purpose. Feature arc is also a public data structure which optimally saves following variables in 8 byte compact structure (rte_graph_feature_daa_t) for every interface - rte_edge_t (uint16_t) - next enabled feature (uint8_t) per index (from current node) - Per interface feature specific user_data (uint32_t) Due to its compact nature, 8 such objects per interface can be saved in one 64B cache line. So IMO, it is better to create public structures for a given purpose and optimally define them fields and APIs. Also feature arc specific 3B data is saved in mbuf dynfield. Hard to say if priv data would provide a better solution. > This structure would be the "internal api" (so, that has to be tracked across dpdk releases) between nodes. > We’d need common data shared for all the nodes as well as specific data between 2 nodes. > As we get to this point, this (hopefully) will help with the node reusability. Feature arc also maintains data between 2 nodes per interface and also for all nodes which are added as features. > > - Update the feature arcs to leverage this well known structure, and refine the api > - Define which part of the stack needs to be defined as a feature arc, with the benefit of the generic API to enable/disable that feature, and which part needs to be dynamically pluggable. > For instance, for a router, it may not make sense to define IPv4 support as a feature arc. > So, we’d statically connect eth_input to ip_input. Agreed > Yet, lldp support is a good candidate for a feature arc: we need to configure it per interface, and this is independent of the main graph. > There would be more protocols which need to be enabled per interface > WDYT? > Christophe > > > On 17 Oct 2024, at 09:50, Robin Jarry <rjarry@redhat.com> wrote: > > > > Hi Nitin, all, > > > > Nitin Saxena, Oct 17, 2024 at 09:03: > >> Hi Robin/David and all, > >> > >> We realized the feature arc patch series is difficult to understand as a new concept. Our objectives are following with feature arc changes > >> > >> 1. Allow reusability of standard DPDK nodes (defined in lib/nodes/*) with out-of-tree applications (like grout). Currently out-of-tree graph applications are duplicating standard nodes but not reusing the standard ones which are available. In the long term, we would like to mature standard DPDK nodes with flexibility of hooking them to out-of-tree application nodes. > > > > It would be ideal if the in-built nodes could be reused. When we started working on grout, I tried multiple approaches where I could reuse these nodes, but all failed. The nodes public API seems tailored for app/graph but does not fit well with other control plane implementations. > > > > One of the main issues I had is that the ethdev_rx and ethdev_tx nodes are cloned per rxq / txq associated with a graph worker. The rte_node API requires that every clone has a unique name. This in turn makes hot plugging of DPDK ports very complex, if not impossible. > > > > For example, with the in-built nodes, it is not possible to change the number of ports or their number of RX queues without destroying the whole graph and creating a new one from scratch. > > > > Also, the current implementation of "ip{4,6}-rewrite" handles writing ethernet header data. This would prevent it from using this node for an IP-in-IP tunnel interface as we did in grout. > > > > Do you think we could change the in-built nodes to enforce OSI layer separation of concerns? It would make them much more flexible. It may cause a slight drop of performance because you'd be splitting processing in two different nodes. But I think flexibility is more important. Otherwise, the in-built nodes can only be used for very specific use-cases. > > > > Finally, I would like to improve the rte_node API to allow defining and enforcing per-packet metadata that every node expects as input. The current in-built nodes rely on mbuf dynamic fields for this but this means you only have 9x32 bits available. And using all of these may break some drivers (ixgbe) that rely on dynfields to work. Have you considered using mbuf private data for this? > > > >> > >> 2. Flexibility to enable/disable sub-graphs per interface based on the runtime configuration updates. Protocol sub-graphs can be selectively enabled for few (or all interfaces) at runtime > >> > >> 3. More than one sub-graphs/features can be enabled on an interface. So a packet has to follow a sequential ordering node path on worker cores. Packets may need to move from one sub-graph to another sub-graph per interface > >> > >> 4. Last but not least, an optimized implementation which does not (or minimally) stop worker cores for any control plane runtime updates. Any performance regression should also be avoided > >> > >> I am planning to create a draft presentation on feature arc which I can share, when ready, to discuss. If needed, I can also plan to present that in one of the DPDK community meetings. Their we can also discuss if there are any alternatives of achieving above objectives > > > > Looking forward to this. > > > > Thanks! > > > ^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [EXTERNAL] Re: [RFC PATCH 0/3] add feature arc in rte_graph 2024-10-17 7:50 ` Robin Jarry 2024-10-17 8:32 ` [EXTERNAL] " Christophe Fontaine @ 2024-10-17 8:48 ` Nitin Saxena 1 sibling, 0 replies; 46+ messages in thread From: Nitin Saxena @ 2024-10-17 8:48 UTC (permalink / raw) To: Robin Jarry Cc: David Marchand, Nitin Saxena, Jerin Jacob, Kiran Kumar Kokkilagadda, Nithin Kumar Dabilpuram, Zhirun Yan, dev, Christophe Fontaine Hi Robin, See inline comments Thanks, Nitin On Thu, Oct 17, 2024 at 1:20 PM Robin Jarry <rjarry@redhat.com> wrote: > > Hi Nitin, all, > > Nitin Saxena, Oct 17, 2024 at 09:03: > > Hi Robin/David and all, > > > > We realized the feature arc patch series is difficult to understand as > > a new concept. Our objectives are following with feature arc changes > > > > 1. Allow reusability of standard DPDK nodes (defined in lib/nodes/*) > > with out-of-tree applications (like grout). Currently out-of-tree > > graph applications are duplicating standard nodes but not reusing > > the standard ones which are available. In the long term, we would > > like to mature standard DPDK nodes with flexibility of hooking them > > to out-of-tree application nodes. > > It would be ideal if the in-built nodes could be reused. When we started > working on grout, I tried multiple approaches where I could reuse these > nodes, but all failed. The nodes public API seems tailored for app/graph > but does not fit well with other control plane implementations. > > One of the main issues I had is that the ethdev_rx and ethdev_tx nodes > are cloned per rxq / txq associated with a graph worker. The rte_node > API requires that every clone has a unique name. This in turn makes hot > plugging of DPDK ports very complex, if not impossible. Agreed. I guess hot plugging of DPDK ports was not the objective when initial changes went in. But we can add hot-plugging functionality without affecting performance > > For example, with the in-built nodes, it is not possible to change the > number of ports or their number of RX queues without destroying the > whole graph and creating a new one from scratch. Coincidentally, I have also encountered these technical issues while writing an out-of-tree application [1]. I had internal discussions with @Jerin Jacob and other graph maintainers to fix these shortcomings. If you want, we can collaborate on fixing these issues For [port, rq] pair mapping to worker core, I have an alternate design [2] which currently stops worker cores. It can be enhanced by RCU based scheme for an ideal DPDK implementation [1]: https://marvellembeddedprocessors.github.io/dao/guides/applications/secgw-graph.html [2]: https://github.com/MarvellEmbeddedProcessors/dao/blob/dao-devel/app/secgw-graph/nodes/rxtx/ethdev-rx.c#L27 > > Also, the current implementation of "ip{4,6}-rewrite" handles writing > ethernet header data. This would prevent it from using this node for an > IP-in-IP tunnel interface as we did in grout. For IP-in-IP, a separate rewrite node would be required which computes checksum etc. but not add rewrite data. > > Do you think we could change the in-built nodes to enforce OSI layer > separation of concerns? It would make them much more flexible. Yes. We are also in agreement to make RFC compliant optimized in-built nodes with such flexibility in place. > It may > cause a slight drop of performance because you'd be splitting processing > in two different nodes. But I think flexibility is more important. > Otherwise, the in-built nodes can only be used for very specific > use-cases. > > Finally, I would like to improve the rte_node API to allow defining and > enforcing per-packet metadata that every node expects as input. The > current in-built nodes rely on mbuf dynamic fields for this but this > means you only have 9x32 bits available. And using all of these may > break some drivers (ixgbe) that rely on dynfields to work. Have you > considered using mbuf private data for this? IMO, "node_mbuf_priv_t" would be ideal for most of the use-cases as it fits in second 64B cache line. With mbuf private data, fast path have to access another cache line per packet which may not be efficient from performance PoV. But we can discuss in more detail about it. Although, I thought of adding "sw_if_index" (which is not same as port_id) to accommodate IP-in-IP like software interfaces > > > > > 2. Flexibility to enable/disable sub-graphs per interface based on the > > runtime configuration updates. Protocol sub-graphs can be > > selectively enabled for few (or all interfaces) at runtime > > > > 3. More than one sub-graphs/features can be enabled on an interface. > > So a packet has to follow a sequential ordering node path on worker > > cores. Packets may need to move from one sub-graph to another > > sub-graph per interface > > > > 4. Last but not least, an optimized implementation which does not (or > > minimally) stop worker cores for any control plane runtime updates. > > Any performance regression should also be avoided > > > > I am planning to create a draft presentation on feature arc which > > I can share, when ready, to discuss. If needed, I can also plan to > > present that in one of the DPDK community meetings. Their we can also > > discuss if there are any alternatives of achieving above objectives > > Looking forward to this. Sure. Will share ppt asap > > Thanks! > ^ permalink raw reply [flat|nested] 46+ messages in thread
* [RFC PATCH v2 0/5] add feature arc in rte_graph 2024-09-07 7:31 [RFC PATCH 0/3] add feature arc in rte_graph Nitin Saxena ` (3 preceding siblings ...) 2024-10-08 8:04 ` [RFC PATCH 0/3] add feature arc in rte_graph David Marchand @ 2024-10-08 13:30 ` Nitin Saxena 2024-10-08 13:30 ` [RFC PATCH v2 1/5] graph: add feature arc support Nitin Saxena ` (5 more replies) 4 siblings, 6 replies; 46+ messages in thread From: Nitin Saxena @ 2024-10-08 13:30 UTC (permalink / raw) To: Jerin Jacob, Kiran Kumar K, Nithin Dabilpuram, Zhirun Yan Cc: dev, Nitin Saxena Feature arc represents an ordered list of features/protocols at a given networking layer. It is a high level abstraction to connect various rte_graph nodes, as feature nodes, and allow packets steering across these nodes in a generic manner. Features (or feature nodes) are nodes which handles partial or complete handling of a protocol in fast path. Like ipv4-rewrite node, which adds rewrite data to an outgoing IPv4 packet. However in above example, outgoing interface(say "eth0") may have outbound IPsec policy enabled, hence packets must be steered from ipv4-rewrite node to ipsec-outbound-policy node for outbound IPsec policy lookup. On the other hand, packets routed to another interface (eth1) will not be sent to ipsec-outbound-policy node as IPsec feature is disabled on eth1. Feature-arc allows rte_graph applications to manage such constraints easily Feature arc abstraction allows rte_graph based application to 1. Seamlessly steer packets across feature nodes based on whether feature is enabled or disabled on an interface. Features enabled on one interface may not be enabled on another interface with in a same feature arc. 2. Allow enabling/disabling of features on an interface at runtime, so that if a feature is disabled, packets associated with that interface won't be steered to corresponding feature node. 3. Provides mechanism to hook custom/user-defined nodes to a feature node and allow packet steering from feature node to custom node without changing former's fast path function 4. Allow expressing features in a particular sequential order so that packets are steered in an ordered way across nodes in fast path. For eg: if IPsec and IPv4 features are enabled on an ingress interface, packets must be sent to IPsec inbound policy node first and then to ipv4 lookup node. This patch series adds feature arc library in rte_graph and also adds "ipv4-output" feature arc handling in "ipv4-rewrite" node. Changes in v2: - Added unit tests for feature arc - Fixed issues found in testing - Added new public APIs rte_graph_feature_arc_feature_to_node(), rte_graph_feature_arc_feature_to_name(), rte_graph_feature_arc_num_features() - Added programming guide for feature arc - Added release notes for feature arc Nitin Saxena (5): graph: add feature arc support graph: add feature arc option in graph create graph: add IPv4 output feature arc test/graph_feature_arc: add functional tests docs: add programming guide for feature arc app/test/meson.build | 1 + app/test/test_graph_feature_arc.c | 1415 +++++++++++++++++++ doc/guides/prog_guide/graph_lib.rst | 289 ++++ doc/guides/prog_guide/img/feature_arc-1.jpg | Bin 0 -> 48984 bytes doc/guides/prog_guide/img/feature_arc-2.jpg | Bin 0 -> 113287 bytes doc/guides/prog_guide/img/feature_arc-3.jpg | Bin 0 -> 93408 bytes doc/guides/rel_notes/release_24_11.rst | 11 +- lib/graph/graph.c | 1 + lib/graph/graph_feature_arc.c | 1223 ++++++++++++++++ lib/graph/graph_populate.c | 7 +- lib/graph/graph_private.h | 3 + lib/graph/meson.build | 2 + lib/graph/node.c | 2 + lib/graph/rte_graph.h | 3 + lib/graph/rte_graph_feature_arc.h | 429 ++++++ lib/graph/rte_graph_feature_arc_worker.h | 672 +++++++++ lib/graph/version.map | 20 + lib/node/ip4_rewrite.c | 476 +++++-- lib/node/ip4_rewrite_priv.h | 15 +- lib/node/node_private.h | 20 +- lib/node/rte_node_ip4_api.h | 3 + 21 files changed, 4493 insertions(+), 99 deletions(-) create mode 100644 app/test/test_graph_feature_arc.c create mode 100644 doc/guides/prog_guide/img/feature_arc-1.jpg create mode 100644 doc/guides/prog_guide/img/feature_arc-2.jpg create mode 100644 doc/guides/prog_guide/img/feature_arc-3.jpg create mode 100644 lib/graph/graph_feature_arc.c create mode 100644 lib/graph/rte_graph_feature_arc.h create mode 100644 lib/graph/rte_graph_feature_arc_worker.h -- 2.43.0 ^ permalink raw reply [flat|nested] 46+ messages in thread
* [RFC PATCH v2 1/5] graph: add feature arc support 2024-10-08 13:30 ` [RFC PATCH v2 0/5] " Nitin Saxena @ 2024-10-08 13:30 ` Nitin Saxena 2024-10-08 13:30 ` [RFC PATCH v2 2/5] graph: add feature arc option in graph create Nitin Saxena ` (4 subsequent siblings) 5 siblings, 0 replies; 46+ messages in thread From: Nitin Saxena @ 2024-10-08 13:30 UTC (permalink / raw) To: Jerin Jacob, Kiran Kumar K, Nithin Dabilpuram, Zhirun Yan Cc: dev, Nitin Saxena add feature arc to allow dynamic steering of packets across graph nodes based on protocol features enabled on incoming or outgoing interface Signed-off-by: Nitin Saxena <nsaxena@marvell.com> --- doc/guides/rel_notes/release_24_11.rst | 11 +- lib/graph/graph_feature_arc.c | 1223 ++++++++++++++++++++++ lib/graph/meson.build | 2 + lib/graph/rte_graph_feature_arc.h | 429 ++++++++ lib/graph/rte_graph_feature_arc_worker.h | 672 ++++++++++++ lib/graph/version.map | 20 + 6 files changed, 2356 insertions(+), 1 deletion(-) create mode 100644 lib/graph/graph_feature_arc.c create mode 100644 lib/graph/rte_graph_feature_arc.h create mode 100644 lib/graph/rte_graph_feature_arc_worker.h diff --git a/doc/guides/rel_notes/release_24_11.rst b/doc/guides/rel_notes/release_24_11.rst index 0ff70d9057..24852aa8e0 100644 --- a/doc/guides/rel_notes/release_24_11.rst +++ b/doc/guides/rel_notes/release_24_11.rst @@ -23,7 +23,6 @@ DPDK Release 24.11 New Features ------------ - .. This section should contain new features added in this release. Sample format: @@ -55,6 +54,16 @@ New Features Also, make sure to start the actual text at the margin. ======================================================= +* **Added feature arc abstraction in graph library.** + + Feature arc abstraction helps ``rte_graph`` based applications to steer + packets across different node path(s) based on the features (or protocols) + enabled on interfaces. Different feature node paths can be enabled/disabled + at runtime on some or on all interfaces. This abstraction also help + applications to hook their ``custom nodes`` in standard DPDK node paths + without any code changes in the later. + + * Added ``ip4-output`` feature arc processing in ``ip4_rewrite`` node. Removed Items ------------- diff --git a/lib/graph/graph_feature_arc.c b/lib/graph/graph_feature_arc.c new file mode 100644 index 0000000000..ff99f7b26a --- /dev/null +++ b/lib/graph/graph_feature_arc.c @@ -0,0 +1,1223 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(C) 2024 Marvell International Ltd. + */ + +#include "graph_private.h" +#include <rte_graph_feature_arc_worker.h> +#include <rte_malloc.h> + +#define ARC_PASSIVE_LIST(arc) (arc->active_feature_list ^ 0x1) + +#define rte_graph_uint_cast(x) ((unsigned int)x) +#define feat_dbg graph_dbg + +static rte_graph_feature_arc_main_t *__rte_graph_feature_arc_main; + +/* Make sure fast path cache line is compact */ +_Static_assert((offsetof(struct rte_graph_feature_arc, slow_path_variables) + - offsetof(struct rte_graph_feature_arc, fast_path_variables)) + <= RTE_CACHE_LINE_SIZE, + "Fast path feature arc variables exceed cache line size"); + +#define connect_graph_nodes(node1, node2, edge, arc_name) \ + __connect_graph_nodes(node1, node2, edge, arc_name, __LINE__) + +#define FEAT_COND_ERR(cond, fmt, ...) \ + do { \ + if (cond) \ + graph_err(fmt, ##__VA_ARGS__); \ + } while (0) + +/* + * lookup feature name and get control path node_list as well as feature index + * at which it is inserted + */ +static int +feature_lookup(struct rte_graph_feature_arc *arc, const char *feat_name, + struct rte_graph_feature_node_list **ffinfo, uint32_t *slot) +{ + struct rte_graph_feature_node_list *finfo = NULL; + const char *name; + uint32_t fi = 0; + + if (!feat_name) + return -1; + + if (slot) + *slot = UINT32_MAX; + + STAILQ_FOREACH(finfo, &arc->all_features, next_feature) { + RTE_VERIFY(finfo->feature_arc == arc); + name = rte_node_id_to_name(finfo->feature_node->id); + if (!strncmp(name, feat_name, strlen(name))) { + if (ffinfo) + *ffinfo = finfo; + if (slot) + *slot = fi; + return 0; + } + fi++; + } + return -1; +} + +/* Lookup used only during rte_graph_feature_add() */ +static int +feature_add_lookup(struct rte_graph_feature_arc *arc, const char *feat_name, + struct rte_graph_feature_node_list **ffinfo, uint32_t *slot) +{ + struct rte_graph_feature_node_list *finfo = NULL; + const char *name; + uint32_t fi = 0; + + if (!feat_name) + return -1; + + if (slot) + *slot = 0; + + STAILQ_FOREACH(finfo, &arc->all_features, next_feature) { + RTE_VERIFY(finfo->feature_arc == arc); + name = rte_node_id_to_name(finfo->feature_node->id); + if (!strncmp(name, feat_name, strlen(name))) { + if (ffinfo) + *ffinfo = finfo; + if (slot) + *slot = fi; + return 0; + } + /* Update slot where new feature can be added */ + if (slot) + *slot = fi; + fi++; + } + + return -1; +} + +/* Get control path node info from provided input feature_index */ +static int +feature_arc_node_info_lookup(struct rte_graph_feature_arc *arc, uint32_t feature_index, + struct rte_graph_feature_node_list **ppfinfo, + const int do_sanity_check) +{ + struct rte_graph_feature_node_list *finfo = NULL; + uint32_t index = 0; + + if (!ppfinfo) + return -1; + + *ppfinfo = NULL; + STAILQ_FOREACH(finfo, &arc->all_features, next_feature) { + /* Check sanity */ + if (do_sanity_check) + if (finfo->node_index != index) + RTE_VERIFY(0); + if (index == feature_index) { + *ppfinfo = finfo; + return 0; + } + index++; + } + return -1; +} + +/* prepare feature arc after addition of all features */ +static void +prepare_feature_arc_before_first_enable(struct rte_graph_feature_arc *arc) +{ + struct rte_graph_feature_node_list *finfo = NULL; + uint32_t index = 0; + + arc->active_feature_list = 0; + STAILQ_FOREACH(finfo, &arc->all_features, next_feature) { + finfo->node_index = index; + feat_dbg("\t%s prepare: %s added to list at index: %u", arc->feature_arc_name, + finfo->feature_node->name, index); + index++; + } +} + +/* feature arc lookup in array */ +static int +feature_arc_lookup(rte_graph_feature_arc_t _arc) +{ + struct rte_graph_feature_arc *arc = rte_graph_feature_arc_get(_arc); + rte_graph_feature_arc_main_t *dm = __rte_graph_feature_arc_main; + uint32_t iter; + + if (!__rte_graph_feature_arc_main) + return -1; + + for (iter = 0; iter < dm->max_feature_arcs; iter++) { + if (dm->feature_arcs[iter] == RTE_GRAPH_FEATURE_ARC_INITIALIZER) + continue; + + if (arc == (rte_graph_feature_arc_get(dm->feature_arcs[iter]))) + return 0; + } + return -1; +} + +/* Check valid values for known fields in arc to make sure arc is sane */ +static int check_feature_arc_sanity(rte_graph_feature_arc_t _arc, int iter) +{ +#ifdef FEATURE_ARC_DEBUG + struct rte_graph_feature_arc *arc = rte_graph_feature_arc_get(_arc); + + RTE_VERIFY(arc->feature_arc_main == __rte_graph_feature_arc_main); + RTE_VERIFY(arc->feature_arc_index == iter); + + RTE_VERIFY(arc->feature_list[0]->indexed_by_features = arc->features[0]); + RTE_VERIFY(arc->feature_list[1]->indexed_by_features = arc->features[1]); + + RTE_VERIFY(arc->active_feature_list < 2); +#else + RTE_SET_USED(_arc); + RTE_SET_USED(iter); +#endif + return 0; +} + +/* Perform sanity on all arc if any corruption occurred */ +static int do_sanity_all_arcs(void) +{ + rte_graph_feature_arc_main_t *dm = __rte_graph_feature_arc_main; + uint32_t iter; + + if (!dm) + return -1; + + for (iter = 0; iter < dm->max_feature_arcs; iter++) { + if (dm->feature_arcs[iter] == RTE_GRAPH_FEATURE_ARC_INITIALIZER) + continue; + + if (check_feature_arc_sanity(dm->feature_arcs[iter], iter)) + return -1; + } + return 0; +} + +/* get existing edge from parent_node -> child_node */ +static int +get_existing_edge(const char *arc_name, struct rte_node_register *parent_node, + struct rte_node_register *child_node, rte_edge_t *_edge) +{ + char **next_edges = NULL; + uint32_t i, count = 0; + + RTE_SET_USED(arc_name); + + count = rte_node_edge_get(parent_node->id, NULL); + + if (!count) + return -1; + + next_edges = malloc(count); + + if (!next_edges) + return -1; + + count = rte_node_edge_get(parent_node->id, next_edges); + for (i = 0; i < count; i++) { + if (strstr(child_node->name, next_edges[i])) { + if (_edge) + *_edge = (rte_edge_t)i; + + free(next_edges); + return 0; + } + } + free(next_edges); + + return -1; +} + +/* create or retrieve already existing edge from parent_node -> child_node */ +static int +__connect_graph_nodes(struct rte_node_register *parent_node, struct rte_node_register *child_node, + rte_edge_t *_edge, char *arc_name, int lineno) +{ + const char *next_node = NULL; + rte_edge_t edge; + + if (!get_existing_edge(arc_name, parent_node, child_node, &edge)) { + feat_dbg("\t%s/%d: %s[%u]: \"%s\", edge reused", arc_name, lineno, + parent_node->name, edge, child_node->name); + + if (_edge) + *_edge = edge; + + return 0; + } + + /* Node to be added */ + next_node = child_node->name; + + edge = rte_node_edge_update(parent_node->id, RTE_EDGE_ID_INVALID, &next_node, 1); + + if (edge == RTE_EDGE_ID_INVALID) { + graph_err("edge invalid"); + return -1; + } + edge = rte_node_edge_count(parent_node->id) - 1; + + feat_dbg("\t%s/%d: %s[%u]: \"%s\", new edge added", arc_name, lineno, parent_node->name, + edge, child_node->name); + + if (_edge) + *_edge = edge; + + return 0; +} + +/* feature arc initialization */ +static int +feature_arc_main_init(rte_graph_feature_arc_main_t **pfl, uint32_t max_feature_arcs) +{ + rte_graph_feature_arc_main_t *pm = NULL; + uint32_t i; + size_t sz; + + if (!pfl) + return -1; + + sz = sizeof(rte_graph_feature_arc_main_t) + + (sizeof(pm->feature_arcs[0]) * max_feature_arcs); + + pm = rte_malloc("rte_graph_feature_arc_main", sz, 0); + if (!pm) + return -1; + + memset(pm, 0, sz); + + for (i = 0; i < max_feature_arcs; i++) + pm->feature_arcs[i] = RTE_GRAPH_FEATURE_ARC_INITIALIZER; + + pm->max_feature_arcs = max_feature_arcs; + + *pfl = pm; + + return 0; +} + +/* feature arc initialization, public API */ +int +rte_graph_feature_arc_init(int max_feature_arcs) +{ + if (!max_feature_arcs) + return -1; + + if (__rte_graph_feature_arc_main) + return -1; + + return feature_arc_main_init(&__rte_graph_feature_arc_main, max_feature_arcs); +} + +/* reset feature list before switching to passive list */ +static void +feature_arc_list_reset(struct rte_graph_feature_arc *arc, uint32_t list_index) +{ + rte_graph_feature_data_t *fdata = NULL; + rte_graph_feature_list_t *list = NULL; + struct rte_graph_feature *feat = NULL; + uint32_t i, j; + + list = arc->feature_list[list_index]; + feat = arc->features[list_index]; + + /*Initialize variables*/ + memset(feat, 0, arc->feature_size * arc->max_features); + memset(list, 0, arc->feature_list_size); + + /* Initialize feature and feature_data */ + for (i = 0; i < arc->max_features; i++) { + feat = __rte_graph_feature_get(arc, i, list_index); + feat->this_feature_index = i; + + for (j = 0; j < arc->max_indexes; j++) { + fdata = rte_graph_feature_data_get(arc, feat, j); + fdata->next_enabled_feature = RTE_GRAPH_FEATURE_INVALID; + fdata->next_edge = UINT16_MAX; + fdata->user_data = UINT32_MAX; + } + } + + for (i = 0; i < arc->max_indexes; i++) + list->first_enabled_feature_by_index[i] = RTE_GRAPH_FEATURE_INVALID; +} + +static int +feature_arc_list_init(struct rte_graph_feature_arc *arc, const char *flist_name, + rte_graph_feature_list_t **pplist, + struct rte_graph_feature **ppfeature, uint32_t list_index) +{ + char fname[2 * RTE_GRAPH_FEATURE_ARC_NAMELEN]; + size_t list_size, feat_size, fdata_size; + rte_graph_feature_list_t *list = NULL; + struct rte_graph_feature *feat = NULL; + + list_size = sizeof(struct rte_graph_feature_list) + + (sizeof(list->first_enabled_feature_by_index[0]) * arc->max_indexes); + + list_size = RTE_ALIGN_CEIL(list_size, RTE_CACHE_LINE_SIZE); + + list = rte_malloc(flist_name, list_size, RTE_CACHE_LINE_SIZE); + if (!list) + return -ENOMEM; + + memset(list, 0, list_size); + fdata_size = arc->max_indexes * sizeof(rte_graph_feature_data_t); + + /* Let one feature and its associated data per index capture complete + * cache lines + */ + feat_size = RTE_ALIGN_CEIL(sizeof(struct rte_graph_feature) + fdata_size, + RTE_CACHE_LINE_SIZE); + + snprintf(fname, sizeof(fname), "%s-%s", arc->feature_arc_name, "feat"); + + feat = rte_malloc(fname, feat_size * arc->max_features, RTE_CACHE_LINE_SIZE); + if (!feat) { + rte_free(list); + return -ENOMEM; + } + arc->feature_size = feat_size; + arc->feature_data_size = fdata_size; + arc->feature_list_size = list_size; + + /* Initialize list */ + list->indexed_by_features = feat; + *pplist = list; + *ppfeature = feat; + + feature_arc_list_reset(arc, list_index); + + return 0; +} + +/* free resources allocated in feature_arc_list_init() */ +static void +feature_arc_list_destroy(struct rte_graph_feature_arc *arc, int list_index) +{ + rte_graph_feature_list_t *list = NULL; + + list = arc->feature_list[list_index]; + + rte_free(list->indexed_by_features); + + arc->features[list_index] = NULL; + + rte_free(list); + + arc->feature_list[list_index] = NULL; +} + +int +rte_graph_feature_arc_create(const char *feature_arc_name, int max_features, int max_indexes, + struct rte_node_register *start_node, rte_graph_feature_arc_t *_arc) +{ + char name[2 * RTE_GRAPH_FEATURE_ARC_NAMELEN]; + struct rte_graph_feature_data *gfd = NULL; + rte_graph_feature_arc_main_t *dfm = NULL; + struct rte_graph_feature_arc *arc = NULL; + struct rte_graph_feature *df = NULL; + uint32_t iter, j, arc_index; + size_t sz; + + if (!_arc) + SET_ERR_JMP(EINVAL, err, "%s: Invalid _arc", feature_arc_name); + + if (max_features < 2) + SET_ERR_JMP(EINVAL, err, "%s: max_features must be greater than 1", + feature_arc_name); + + if (!start_node) + SET_ERR_JMP(EINVAL, err, "%s: start_node cannot be NULL", + feature_arc_name); + + if (!feature_arc_name) + SET_ERR_JMP(EINVAL, err, "%s: feature_arc name cannot be NULL", + feature_arc_name); + + if (max_features > RTE_GRAPH_FEATURE_MAX_PER_ARC) + SET_ERR_JMP(EAGAIN, err, "%s: number of features cannot be greater than 64", + feature_arc_name); + + /* + * Application hasn't called rte_graph_feature_arc_init(). Initialize with + * default values + */ + if (!__rte_graph_feature_arc_main) { + if (rte_graph_feature_arc_init((int)RTE_GRAPH_FEATURE_ARC_MAX) < 0) { + graph_err("rte_graph_feature_arc_init() failed"); + return -1; + } + } + + /* If name is not unique */ + if (!rte_graph_feature_arc_lookup_by_name(feature_arc_name, NULL)) + SET_ERR_JMP(EINVAL, err, "%s: feature arc name already exists", + feature_arc_name); + + dfm = __rte_graph_feature_arc_main; + + /* threshold check */ + if (dfm->num_feature_arcs > (dfm->max_feature_arcs - 1)) + SET_ERR_JMP(EAGAIN, err, "%s: max number (%u) of feature arcs reached", + feature_arc_name, dfm->max_feature_arcs); + + /* Find the free slot for feature arc */ + for (iter = 0; iter < dfm->max_feature_arcs; iter++) { + if (dfm->feature_arcs[iter] == RTE_GRAPH_FEATURE_ARC_INITIALIZER) + break; + } + arc_index = iter; + + if (arc_index >= dfm->max_feature_arcs) { + graph_err("No free slot found for num_feature_arc"); + return -1; + } + + /* This should not happen */ + RTE_VERIFY(dfm->feature_arcs[arc_index] == RTE_GRAPH_FEATURE_ARC_INITIALIZER); + + /* size of feature arc + feature_bit_mask_by_index */ + sz = RTE_ALIGN_CEIL(sizeof(*arc) + (sizeof(uint64_t) * max_indexes), RTE_CACHE_LINE_SIZE); + + arc = rte_malloc(feature_arc_name, sz, RTE_CACHE_LINE_SIZE); + + if (!arc) { + graph_err("malloc failed for feature_arc_create()"); + return -1; + } + + memset(arc, 0, sz); + + /* Initialize rte_graph port group fixed variables */ + STAILQ_INIT(&arc->all_features); + strncpy(arc->feature_arc_name, feature_arc_name, RTE_GRAPH_FEATURE_ARC_NAMELEN - 1); + arc->feature_arc_main = (void *)dfm; + arc->start_node = start_node; + arc->max_features = max_features; + arc->max_indexes = max_indexes; + arc->feature_arc_index = arc_index; + + snprintf(name, sizeof(name), "%s-%s", feature_arc_name, "flist0"); + + if (feature_arc_list_init(arc, name, &arc->feature_list[0], &arc->features[0], 0) < 0) { + rte_free(arc); + graph_err("feature_arc_list_init(0) failed"); + return -1; + } + snprintf(name, sizeof(name), "%s-%s", feature_arc_name, "flist1"); + + if (feature_arc_list_init(arc, name, &arc->feature_list[1], &arc->features[1], 1) < 0) { + feature_arc_list_destroy(arc, 0); + rte_free(arc); + graph_err("feature_arc_list_init(1) failed"); + return -1; + } + + for (iter = 0; iter < arc->max_features; iter++) { + df = rte_graph_feature_get(arc, iter); + for (j = 0; j < arc->max_indexes; j++) { + gfd = rte_graph_feature_data_get(arc, df, j); + gfd->next_enabled_feature = RTE_GRAPH_FEATURE_INVALID; + } + } + dfm->feature_arcs[arc->feature_arc_index] = (rte_graph_feature_arc_t)arc; + dfm->num_feature_arcs++; + + if (_arc) + *_arc = (rte_graph_feature_arc_t)arc; + + do_sanity_all_arcs(); + + feat_dbg("Feature arc %s[%p] created with max_features: %u and indexes: %u", + feature_arc_name, (void *)arc, max_features, max_indexes); + return 0; + +err: + return -rte_errno; +} + +int +rte_graph_feature_add(rte_graph_feature_arc_t _arc, struct rte_node_register *feature_node, + const char *_runs_after, const char *runs_before) +{ + struct rte_graph_feature_node_list *after_finfo = NULL, *before_finfo = NULL; + struct rte_graph_feature_arc *arc = rte_graph_feature_arc_get(_arc); + struct rte_graph_feature_node_list *temp = NULL, *finfo = NULL; + char feature_name[3*RTE_GRAPH_FEATURE_ARC_NAMELEN]; + const char *runs_after = NULL; + uint32_t num_feature = 0; + uint32_t slot, add_flag; + rte_edge_t edge = -1; + + /* sanity */ + if (arc->feature_arc_main != __rte_graph_feature_arc_main) { + graph_err("feature arc not created: 0x%016" PRIx64, (uint64_t)_arc); + return -1; + } + + if (feature_arc_lookup(_arc)) { + graph_err("invalid feature arc: 0x%016" PRIx64, (uint64_t)_arc); + return -1; + } + + if (arc->runtime_enabled_features) { + graph_err("adding features after enabling any one of them is not supported"); + return -1; + } + + if ((_runs_after != NULL) && (runs_before != NULL) && + (_runs_after == runs_before)) { + graph_err("runs_after and runs_before are same '%s:%s]", _runs_after, + runs_before); + return -1; + } + + if (!feature_node) { + graph_err("feature_node: %p invalid", feature_node); + return -1; + } + + arc = rte_graph_feature_arc_get(_arc); + + if (feature_node->id == RTE_NODE_ID_INVALID) { + graph_err("Invalid node: %s", feature_node->name); + return -1; + } + + if (!feature_add_lookup(arc, feature_node->name, &finfo, &slot)) { + graph_err("%s feature already added", feature_node->name); + return -1; + } + + if (slot >= arc->max_features) { + graph_err("%s: Max features %u added to feature arc", + arc->feature_arc_name, slot); + return -1; + } + + if (strstr(feature_node->name, arc->start_node->name)) { + graph_err("Feature %s cannot point to itself: %s", feature_node->name, + arc->start_node->name); + return -1; + } + + feat_dbg("%s: adding feature node: %s at feature index: %u", arc->feature_arc_name, + feature_node->name, slot); + + if (connect_graph_nodes(arc->start_node, feature_node, &edge, arc->feature_arc_name)) { + graph_err("unable to connect %s -> %s", arc->start_node->name, feature_node->name); + return -1; + } + + snprintf(feature_name, sizeof(feature_name), "%s-%s-finfo", + arc->feature_arc_name, feature_node->name); + + finfo = rte_malloc(feature_name, sizeof(*finfo), 0); + if (!finfo) { + graph_err("%s/%s: rte_malloc failed", arc->feature_arc_name, feature_node->name); + return -1; + } + + memset(finfo, 0, sizeof(*finfo)); + + finfo->feature_arc = (void *)arc; + finfo->feature_node = feature_node; + finfo->edge_to_this_feature = edge; + arc->runtime_enabled_features = 0; + + /* + * if no constraints given and provided feature is not the first feature, + * explicitly set "runs_after" as last_feature. Handles the case: + * + * add(f1, NULL, NULL); + * add(f2, NULL, NULL); + */ + num_feature = rte_graph_feature_arc_num_features(_arc); + if (!_runs_after && !runs_before && num_feature) + runs_after = rte_graph_feature_arc_feature_to_name(_arc, num_feature - 1); + else + runs_after = _runs_after; + + /* Check for before and after constraints */ + if (runs_before) { + /* runs_before sanity */ + if (feature_lookup(arc, runs_before, &before_finfo, NULL)) + SET_ERR_JMP(EINVAL, finfo_free, + "Invalid before feature name: %s", runs_before); + + if (!before_finfo) + SET_ERR_JMP(EINVAL, finfo_free, + "runs_before %s does not exist", runs_before); + + /* + * Starting from 0 to runs_before, continue connecting edges + */ + add_flag = 1; + STAILQ_FOREACH(temp, &arc->all_features, next_feature) { + if (!add_flag) + /* Nodes after seeing "runs_before", finfo connects to temp*/ + connect_graph_nodes(finfo->feature_node, temp->feature_node, + NULL, arc->feature_arc_name); + /* + * As soon as we see runs_before. stop adding edges + */ + if (!strncmp(temp->feature_node->name, runs_before, + RTE_GRAPH_NAMESIZE)) { + if (!connect_graph_nodes(finfo->feature_node, temp->feature_node, + &edge, arc->feature_arc_name)) + add_flag = 0; + } + + if (add_flag) + /* Nodes before seeing "run_before" are connected to finfo */ + connect_graph_nodes(temp->feature_node, finfo->feature_node, NULL, + arc->feature_arc_name); + } + } + + if (runs_after) { + if (feature_lookup(arc, runs_after, &after_finfo, NULL)) + SET_ERR_JMP(EINVAL, finfo_free, + "Invalid after feature_name %s", runs_after); + + if (!after_finfo) + SET_ERR_JMP(EINVAL, finfo_free, + "runs_after %s does not exist", runs_after); + + /* Starting from runs_after to end continue connecting edges */ + add_flag = 0; + STAILQ_FOREACH(temp, &arc->all_features, next_feature) { + if (add_flag) + /* We have already seen runs_after now */ + /* Add all features as next node to current feature*/ + connect_graph_nodes(finfo->feature_node, temp->feature_node, NULL, + arc->feature_arc_name); + else + /* Connect initial nodes to newly added node*/ + connect_graph_nodes(temp->feature_node, finfo->feature_node, NULL, + arc->feature_arc_name); + + /* as soon as we see runs_after. start adding edges + * from next iteration + */ + if (!strncmp(temp->feature_node->name, runs_after, RTE_GRAPH_NAMESIZE)) + add_flag = 1; + } + + /* add feature next to runs_after */ + STAILQ_INSERT_AFTER(&arc->all_features, after_finfo, finfo, next_feature); + } else { + if (before_finfo) { + /* add finfo before "before_finfo" element in the list */ + after_finfo = NULL; + STAILQ_FOREACH(temp, &arc->all_features, next_feature) { + if (before_finfo == temp) { + if (after_finfo) + STAILQ_INSERT_AFTER(&arc->all_features, after_finfo, + finfo, next_feature); + else + STAILQ_INSERT_HEAD(&arc->all_features, finfo, + next_feature); + + return 0; + } + after_finfo = temp; + } + } else { + /* Very first feature just needs to be added to list */ + STAILQ_INSERT_TAIL(&arc->all_features, finfo, next_feature); + } + } + + return 0; + +finfo_free: + rte_free(finfo); + + return -1; +} + +int +rte_graph_feature_lookup(rte_graph_feature_arc_t _arc, const char *feature_name, + rte_graph_feature_t *feat) +{ + struct rte_graph_feature_arc *arc = rte_graph_feature_arc_get(_arc); + struct rte_graph_feature_node_list *finfo = NULL; + uint32_t slot; + + if (!feature_lookup(arc, feature_name, &finfo, &slot)) { + *feat = (rte_graph_feature_t) slot; + return 0; + } + + return -1; +} + +int +rte_graph_feature_validate(rte_graph_feature_arc_t _arc, uint32_t index, const char *feature_name, + int is_enable_disable, bool emit_logs) +{ + struct rte_graph_feature_arc *arc = rte_graph_feature_arc_get(_arc); + struct rte_graph_feature_node_list *finfo = NULL; + struct rte_graph_feature *gf = NULL; + uint32_t slot; + + /* validate _arc */ + if (arc->feature_arc_main != __rte_graph_feature_arc_main) { + FEAT_COND_ERR(emit_logs, "invalid feature arc: 0x%016" PRIx64, (uint64_t)_arc); + return -EINVAL; + } + + /* validate index */ + if (index >= arc->max_indexes) { + FEAT_COND_ERR(emit_logs, "%s: Invalid provided index: %u >= %u configured", + arc->feature_arc_name, index, arc->max_indexes); + return -1; + } + + /* validate feature_name is already added or not */ + if (feature_lookup(arc, feature_name, &finfo, &slot)) { + FEAT_COND_ERR(emit_logs, "%s: No feature %s added", + arc->feature_arc_name, feature_name); + return -EINVAL; + } + + if (!finfo) { + FEAT_COND_ERR(emit_logs, "%s: No feature: %s found", + arc->feature_arc_name, feature_name); + return -EINVAL; + } + + /* slot should be in valid range */ + if (slot >= arc->max_features) { + FEAT_COND_ERR(emit_logs, "%s/%s: Invalid free slot %u(max=%u) for feature", + arc->feature_arc_name, feature_name, slot, arc->max_features); + return -EINVAL; + } + + /* slot should be in range of 0 - 63 */ + if (slot > (RTE_GRAPH_FEATURE_MAX_PER_ARC - 1)) { + FEAT_COND_ERR(emit_logs, "%s/%s: Invalid slot: %u", arc->feature_arc_name, + feature_name, slot); + return -EINVAL; + } + + if (finfo->node_index != slot) { + FEAT_COND_ERR(emit_logs, + "%s/%s: lookup slot mismatch for finfo idx: %u and lookup slot: %u", + arc->feature_arc_name, feature_name, finfo->node_index, slot); + return -1; + } + + /* Get feature from active list */ + gf = __rte_graph_feature_get(arc, slot, ARC_PASSIVE_LIST(arc)); + if (gf->this_feature_index != slot) { + FEAT_COND_ERR(emit_logs, + "%s: %s rcvd feature_idx: %u does not match with saved: %u", + arc->feature_arc_name, feature_name, slot, gf->this_feature_index); + return -1; + } + + if (is_enable_disable && (arc->feature_bit_mask_by_index[index] & + RTE_BIT64(slot))) { + FEAT_COND_ERR(emit_logs, "%s: %s already enabled on index: %u", + arc->feature_arc_name, feature_name, index); + return -1; + } + + if (!is_enable_disable && !arc->runtime_enabled_features) { + FEAT_COND_ERR(emit_logs, "%s: No feature enabled to disable", + arc->feature_arc_name); + return -1; + } + + if (!is_enable_disable && !(arc->feature_bit_mask_by_index[index] & RTE_BIT64(slot))) { + FEAT_COND_ERR(emit_logs, "%s: %s not enabled in bitmask for index: %u", + arc->feature_arc_name, feature_name, index); + return -1; + } + + return 0; +} + +/* + * Before switch to passive list, user_data needs to be copied from active list to passive list + */ +static void +copy_fastpath_user_data(struct rte_graph_feature_arc *arc, uint16_t dest_list_index, + uint16_t src_list_index) +{ + rte_graph_feature_data_t *sgfd = NULL, *dgfd = NULL; + struct rte_graph_feature *sgf = NULL, *dgf = NULL; + uint32_t i, j; + + for (i = 0; i < arc->max_features; i++) { + sgf = __rte_graph_feature_get(arc, i, src_list_index); + dgf = __rte_graph_feature_get(arc, i, dest_list_index); + for (j = 0; j < arc->max_indexes; j++) { + sgfd = rte_graph_feature_data_get(arc, sgf, j); + dgfd = rte_graph_feature_data_get(arc, dgf, j); + dgfd->user_data = sgfd->user_data; + } + } +} +/* + * Fill fast path information like + * - next_edge + * - next_enabled_feature + */ +static void +refill_feature_fastpath_data(struct rte_graph_feature_arc *arc, uint16_t list_index) +{ + struct rte_graph_feature_node_list *finfo = NULL, *prev_finfo = NULL; + struct rte_graph_feature_data *gfd = NULL, *prev_gfd = NULL; + uint32_t fi = UINT32_MAX, di = UINT32_MAX, prev_fi = UINT32_MAX; + struct rte_graph_feature *gf = NULL, *prev_gf = NULL; + rte_graph_feature_list_t *flist = NULL; + rte_edge_t edge = UINT16_MAX; + uint64_t bitmask = 0; + + flist = arc->feature_list[list_index]; + + for (di = 0; di < arc->max_indexes; di++) { + bitmask = arc->feature_bit_mask_by_index[di]; + prev_fi = RTE_GRAPH_FEATURE_INVALID; + /* for each feature set for index, set fast path data */ + while (rte_bsf64_safe(bitmask, &fi)) { + gf = __rte_graph_feature_get(arc, fi, list_index); + gfd = rte_graph_feature_data_get(arc, gf, di); + RTE_VERIFY(!feature_arc_node_info_lookup(arc, fi, &finfo, 1)); + + /* If previous feature_index was valid in last loop */ + if (prev_fi != RTE_GRAPH_FEATURE_INVALID) { + prev_gf = __rte_graph_feature_get(arc, prev_fi, list_index); + prev_gfd = rte_graph_feature_data_get(arc, prev_gf, di); + /* + * Get edge of previous feature node connecting + * to this feature node + */ + RTE_VERIFY(!feature_arc_node_info_lookup(arc, prev_fi, + &prev_finfo, 1)); + if (!get_existing_edge(arc->feature_arc_name, + prev_finfo->feature_node, + finfo->feature_node, &edge)) { + feat_dbg("\t[%s/%u/di:%2u,cookie:%u]: (%u->%u)%s[%u] = %s", + arc->feature_arc_name, list_index, di, + prev_gfd->user_data, prev_fi, fi, + prev_finfo->feature_node->name, + edge, finfo->feature_node->name); + /* Copy feature index for next iteration*/ + gfd->next_edge = edge; + prev_fi = fi; + /* + * Fill current feature as next enabled + * feature to previous one + */ + prev_gfd->next_enabled_feature = fi; + } else { + /* Should not fail */ + RTE_VERIFY(0); + } + } + /* On first feature edge of the node to be added */ + if (fi == rte_bsf64(arc->feature_bit_mask_by_index[di])) { + if (!get_existing_edge(arc->feature_arc_name, arc->start_node, + finfo->feature_node, + &edge)) { + feat_dbg("\t[%s/%u/di:%2u,cookie:%u]: (->%u)%s[%u]=%s", + arc->feature_arc_name, list_index, di, + gfd->user_data, fi, + arc->start_node->name, edge, + finfo->feature_node->name); + /* Copy feature index for next iteration*/ + gfd->next_edge = edge; + prev_fi = fi; + /* Set first feature set array for index*/ + flist->first_enabled_feature_by_index[di] = + (rte_graph_feature_t)fi; + } else { + /* Should not fail */ + RTE_VERIFY(0); + } + } + /* Clear current feature index */ + bitmask &= ~RTE_BIT64(fi); + } + } +} + +int +rte_graph_feature_enable(rte_graph_feature_arc_t _arc, uint32_t index, const + char *feature_name, int32_t user_data) +{ + struct rte_graph_feature_arc *arc = rte_graph_feature_arc_get(_arc); + struct rte_graph_feature_node_list *finfo = NULL; + struct rte_graph_feature_data *gfd = NULL; + rte_graph_feature_rt_list_t passive_list; + struct rte_graph_feature *gf = NULL; + uint64_t bitmask; + uint32_t slot; + + feat_dbg("%s: Enabling feature: %s for index: %u", + arc->feature_arc_name, feature_name, index); + + if (!arc->runtime_enabled_features) + prepare_feature_arc_before_first_enable(arc); + + if (rte_graph_feature_validate(_arc, index, feature_name, 1, true)) + return -1; + + /** This should not fail as validate() has passed */ + if (feature_lookup(arc, feature_name, &finfo, &slot)) + RTE_VERIFY(0); + + passive_list = ARC_PASSIVE_LIST(arc); + + feat_dbg("\t%s/%s: index: %u, passive list: %u, feature index: %u", + arc->feature_arc_name, feature_name, index, passive_list, slot); + + gf = __rte_graph_feature_get(arc, slot, passive_list); + gfd = rte_graph_feature_data_get(arc, gf, index); + + /* Reset feature list */ + feature_arc_list_reset(arc, passive_list); + + /* Copy user-data */ + copy_fastpath_user_data(arc, passive_list, arc->active_feature_list); + + /* Set current user-data */ + gfd->user_data = user_data; + + /* Set bitmask in control path bitmask */ + rte_bit_relaxed_set64(rte_graph_uint_cast(slot), &arc->feature_bit_mask_by_index[index]); + refill_feature_fastpath_data(arc, passive_list); + + /* If first time feature getting enabled */ + bitmask = rte_atomic_load_explicit(&arc->feature_enable_bitmask[arc->active_feature_list], + rte_memory_order_relaxed); + + /* On very first feature enable instance */ + if (!finfo->ref_count) + bitmask |= RTE_BIT64(slot); + + rte_atomic_store_explicit(&arc->feature_enable_bitmask[passive_list], + bitmask, rte_memory_order_relaxed); + + /* Slow path updates */ + arc->runtime_enabled_features++; + + /* Increase feature node info reference count */ + finfo->ref_count++; + + /* Store release semantics for active_list update */ + rte_atomic_store_explicit(&arc->active_feature_list, passive_list, + rte_memory_order_release); + + feat_dbg("%s/%s: After enable, switched active feature list to %u", + arc->feature_arc_name, feature_name, arc->active_feature_list); + + return 0; +} + +int +rte_graph_feature_disable(rte_graph_feature_arc_t _arc, uint32_t index, const char *feature_name) +{ + struct rte_graph_feature_arc *arc = rte_graph_feature_arc_get(_arc); + struct rte_graph_feature_data *gfd = NULL; + struct rte_graph_feature_node_list *finfo = NULL; + rte_graph_feature_rt_list_t passive_list; + struct rte_graph_feature *gf = NULL; + uint64_t bitmask; + uint32_t slot; + + feat_dbg("%s: Disable feature: %s for index: %u", + arc->feature_arc_name, feature_name, index); + + if (rte_graph_feature_validate(_arc, index, feature_name, 0, true)) + return -1; + + if (feature_lookup(arc, feature_name, &finfo, &slot)) + return -1; + + passive_list = ARC_PASSIVE_LIST(arc); + + gf = __rte_graph_feature_get(arc, slot, passive_list); + gfd = rte_graph_feature_data_get(arc, gf, index); + + feat_dbg("\t%s/%s: index: %u, passive list: %u, feature index: %u", + arc->feature_arc_name, feature_name, index, passive_list, slot); + + rte_bit_relaxed_clear64(rte_graph_uint_cast(slot), &arc->feature_bit_mask_by_index[index]); + + /* Reset feature list */ + feature_arc_list_reset(arc, passive_list); + + /* Copy user-data */ + copy_fastpath_user_data(arc, passive_list, arc->active_feature_list); + + /* Reset current user-data */ + gfd->user_data = ~0; + + refill_feature_fastpath_data(arc, passive_list); + + finfo->ref_count--; + arc->runtime_enabled_features--; + + /* If no feature enabled, reset feature in u64 fast path bitmask */ + bitmask = rte_atomic_load_explicit(&arc->feature_enable_bitmask[arc->active_feature_list], + rte_memory_order_relaxed); + + /* When last feature is disabled */ + if (!finfo->ref_count) + bitmask &= ~(RTE_BIT64(slot)); + + rte_atomic_store_explicit(&arc->feature_enable_bitmask[passive_list], bitmask, + rte_memory_order_relaxed); + + /* Store release semantics for active_list update */ + rte_atomic_store_explicit(&arc->active_feature_list, passive_list, + rte_memory_order_release); + + feat_dbg("%s/%s: After disable, switched active feature list to %u", + arc->feature_arc_name, feature_name, arc->active_feature_list); + + return 0; +} + +int +rte_graph_feature_arc_destroy(rte_graph_feature_arc_t _arc) +{ + struct rte_graph_feature_arc *arc = rte_graph_feature_arc_get(_arc); + rte_graph_feature_arc_main_t *dm = __rte_graph_feature_arc_main; + struct rte_graph_feature_node_list *node_info = NULL; + + while (!STAILQ_EMPTY(&arc->all_features)) { + node_info = STAILQ_FIRST(&arc->all_features); + STAILQ_REMOVE_HEAD(&arc->all_features, next_feature); + rte_free(node_info); + } + feature_arc_list_destroy(arc, 0); + feature_arc_list_destroy(arc, 1); + + dm->feature_arcs[arc->feature_arc_index] = RTE_GRAPH_FEATURE_ARC_INITIALIZER; + + rte_free(arc); + + do_sanity_all_arcs(); + + return 0; +} + +int +rte_graph_feature_arc_cleanup(void) +{ + rte_graph_feature_arc_main_t *dm = __rte_graph_feature_arc_main; + uint32_t iter; + + if (!__rte_graph_feature_arc_main) + return -1; + + for (iter = 0; iter < dm->max_feature_arcs; iter++) { + if (dm->feature_arcs[iter] == RTE_GRAPH_FEATURE_ARC_INITIALIZER) + continue; + + rte_graph_feature_arc_destroy((rte_graph_feature_arc_t)dm->feature_arcs[iter]); + } + rte_free(dm); + + __rte_graph_feature_arc_main = NULL; + + return 0; +} + +int +rte_graph_feature_arc_lookup_by_name(const char *arc_name, rte_graph_feature_arc_t *_arc) +{ + rte_graph_feature_arc_main_t *dm = __rte_graph_feature_arc_main; + struct rte_graph_feature_arc *arc = NULL; + uint32_t iter; + + if (!__rte_graph_feature_arc_main) + return -1; + + if (_arc) + *_arc = RTE_GRAPH_FEATURE_ARC_INITIALIZER; + + for (iter = 0; iter < dm->max_feature_arcs; iter++) { + if (dm->feature_arcs[iter] == RTE_GRAPH_FEATURE_ARC_INITIALIZER) + continue; + + arc = rte_graph_feature_arc_get(dm->feature_arcs[iter]); + + if ((strstr(arc->feature_arc_name, arc_name)) && + (strlen(arc->feature_arc_name) == strlen(arc_name))) { + if (_arc) + *_arc = (rte_graph_feature_arc_t)arc; + return 0; + } + } + + return -1; +} + +uint32_t +rte_graph_feature_arc_num_enabled_features(rte_graph_feature_arc_t _arc) +{ + struct rte_graph_feature_arc *arc = rte_graph_feature_arc_get(_arc); + + return arc->runtime_enabled_features; +} + +uint32_t +rte_graph_feature_arc_num_features(rte_graph_feature_arc_t _arc) +{ + struct rte_graph_feature_arc *arc = rte_graph_feature_arc_get(_arc); + struct rte_graph_feature_node_list *finfo = NULL; + uint32_t count = 0; + + STAILQ_FOREACH(finfo, &arc->all_features, next_feature) + count++; + + return count; +} + +char * +rte_graph_feature_arc_feature_to_name(rte_graph_feature_arc_t _arc, rte_graph_feature_t feat) +{ + struct rte_graph_feature_arc *arc = rte_graph_feature_arc_get(_arc); + struct rte_graph_feature_node_list *finfo = NULL; + uint32_t slot = feat; + + if (feat >= rte_graph_feature_arc_num_features(_arc)) { + graph_err("%s: feature %u does not exist", arc->feature_arc_name, feat); + return NULL; + } + if (!feature_arc_node_info_lookup(arc, slot, &finfo, 0/* ignore sanity*/)) + return finfo->feature_node->name; + + return NULL; +} + +struct rte_node_register * +rte_graph_feature_arc_feature_to_node(rte_graph_feature_arc_t _arc, rte_graph_feature_t feat) +{ + struct rte_graph_feature_arc *arc = rte_graph_feature_arc_get(_arc); + struct rte_graph_feature_node_list *finfo = NULL; + uint32_t slot = feat; + + if (feat >= rte_graph_feature_arc_num_features(_arc)) { + graph_err("%s: feature %u does not exist", arc->feature_arc_name, feat); + return NULL; + } + if (!feature_arc_node_info_lookup(arc, slot, &finfo, 0/* ignore sanity*/)) + return finfo->feature_node; + + return NULL; + +} diff --git a/lib/graph/meson.build b/lib/graph/meson.build index 0cb15442ab..d916176fb7 100644 --- a/lib/graph/meson.build +++ b/lib/graph/meson.build @@ -14,11 +14,13 @@ sources = files( 'graph_debug.c', 'graph_stats.c', 'graph_populate.c', + 'graph_feature_arc.c', 'graph_pcap.c', 'rte_graph_worker.c', 'rte_graph_model_mcore_dispatch.c', ) headers = files('rte_graph.h', 'rte_graph_worker.h') +headers += files('rte_graph_feature_arc.h', 'rte_graph_feature_arc_worker.h') indirect_headers += files( 'rte_graph_model_mcore_dispatch.h', 'rte_graph_model_rtc.h', diff --git a/lib/graph/rte_graph_feature_arc.h b/lib/graph/rte_graph_feature_arc.h new file mode 100644 index 0000000000..d1c52bb3fb --- /dev/null +++ b/lib/graph/rte_graph_feature_arc.h @@ -0,0 +1,429 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(C) 2024 Marvell International Ltd. + */ + +#ifndef _RTE_GRAPH_FEATURE_ARC_H_ +#define _RTE_GRAPH_FEATURE_ARC_H_ + +#include <assert.h> +#include <errno.h> +#include <signal.h> +#include <stddef.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <rte_common.h> +#include <rte_compat.h> +#include <rte_debug.h> +#include <rte_graph.h> +#include <rte_graph_worker.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @file + * + * rte_graph_feature_arc.h + * + * Define APIs and structures/variables with respect to feature arc + * + * - Feature arc(s) + * - Feature(s) + * + * A feature arc represents an ordered list of features/protocol-nodes at a + * given networking layer. Feature arc provides a high level abstraction to + * connect various *rte_graph* nodes, designated as *feature nodes*, and + * allowing steering of packets across these feature nodes fast path processing + * in a generic manner. In a typical network stack, often a protocol or feature + * must be first enabled on a given interface, before any packet is steered + * towards it for feature processing. For eg: incoming IPv4 packets are sent to + * routing sub-system only after a valid IPv4 address is assigned to the + * received interface. In other words, often packets needs to be steered across + * features not based on the packet content but based on whether a feature is + * enable or disable on a given incoming/outgoing interface. Feature arc + * provides mechanism to enable/disable feature(s) on each interface at runtime + * and allow seamless packet steering across runtime enabled feature nodes in + * fast path. + * + * Feature arc also provides a way to steer packets from standard nodes to + * custom/user-defined *feature nodes* without any change in standard node's + * fast path functions + * + * On a given interface multiple feature(s) might be enabled in a particular + * feature arc. For instance, both "ipv4-output" and "IPsec policy output" + * features may be enabled on "eth0" interface in "L3-output" feature arc. + * Similarly, "ipv6-output" and "ipsec-output" may be enabled on "eth1" + * interface in same "L3-output" feature arc. + * + * When multiple features are present in a given feature arc, its imperative + * to allow each feature processing in a particular sequential order. For + * instance, in "L3-input" feature arc it may be required to run "IPsec + * input" feature first, for packet decryption, before "ip-lookup". So a + * sequential order must be maintained among features present in a feature arc. + * + * Features are enabled/disabled multiple times at runtime to some or all + * available interfaces present in the system. Enable/disabling features on one + * interface is independent of other interface. + * + * A given feature might consume packet (if it's configured to consume) or may + * forward it to next enabled feature. For instance, "IPsec input" feature may + * consume/drop all packets with "Protect" policy action while all packets with + * policy action as "Bypass" may be forwarded to next enabled feature (with in + * same feature arc) + * + * This library facilitates rte graph based applications to steer packets in + * fast path to different feature nodes with-in a feature arc and support all + * functionalities described above + * + * In order to use feature-arc APIs, applications needs to do following in + * control path: + * - Initialize feature arc library via rte_graph_feature_arc_init() + * - Create feature arc via rte_graph_feature_arc_create() + * - *Before calling rte_graph_create()*, features must be added to feature-arc + * via rte_graph_feature_add(). rte_graph_feature_add() allows adding + * features in a sequential order with "runs_after" and "runs_before" + * constraints. + * - Post rte_graph_create(), features can be enabled/disabled at runtime on + * any interface via rte_graph_feature_enable()/rte_graph_feature_disable() + * - Feature arc can be destroyed via rte_graph_feature_arc_destroy() + * + * In fast path, APIs are provided to steer packets towards feature path from + * - start_node (provided as an argument to rte_graph_feature_arc_create()) + * - feature nodes (which are added via rte_graph_feature_add()) + * + * For typical steering of packets across feature nodes, application required + * to know "rte_edges" which are saved in feature data object. Feature data + * object is unique for every interface per feature with in a feature arc. + * + * When steering packets from start_node to feature node: + * - rte_graph_feature_arc_first_feature_get() provides first enabled feature. + * - Next rte_edge from start_node to first enabled feature can be obtained via + * rte_graph_feature_arc_feature_set() + * + * rte_mbuf can carry [current feature, index] from start_node of an arc to other + * feature nodes + * + * In feature node, application can get 32-bit user_data + * via_rte_graph_feature_user_data_get() which is provided in + * rte_graph_feature_enable(). User data can hold feature specific cookie like + * IPsec policy database index (if more than one are supported) + * + * If feature node is not consuming packet, next enabled feature and next + * rte_edge can be obtained via rte_graph_feature_arc_next_feature_get() + * + * It is application responsibility to ensure that at-least *last feature*(or sink + * feature) must be enabled from where packet can exit feature-arc path, if + * *NO* intermediate feature is consuming the packet and it has reached till + * the end of feature arc path + * + * It is recommended that all features *MUST* be added to feature arc before calling + * `rte_graph_create()`. Addition of features after `rte_graph_create()` may + * not work functionally. Although,rte_graph_feature_enable()/rte_graph_feature_disable() + * should be called after `rte_graph_create()` in control plane. + * + * Synchronization among cores + * --------------------------- + * Subsequent calls to rte_graph_feature_enable() is allowed while worker cores + * are processing in rte_graph_walk() loop. However, for + * rte_graph_feature_disable() application must use RCU based synchronization + */ + +/** Initializer value for rte_graph_feature_arc_t */ +#define RTE_GRAPH_FEATURE_ARC_INITIALIZER ((rte_graph_feature_arc_t)UINT64_MAX) + +/** Max number of feature arcs which can be created */ +#define RTE_GRAPH_FEATURE_ARC_MAX 64 + +/** Max number of features supported in a given feature arc */ +#define RTE_GRAPH_FEATURE_MAX_PER_ARC 64 + +/** Length of feature arc name */ +#define RTE_GRAPH_FEATURE_ARC_NAMELEN RTE_NODE_NAMESIZE + +/** @internal */ +#define rte_graph_feature_cast(x) ((rte_graph_feature_t)x) + +/**< Initializer value for rte_graph_feature_arc_t */ +#define RTE_GRAPH_FEATURE_INVALID rte_graph_feature_cast(UINT8_MAX) + +/** rte_graph feature arc object */ +typedef uint64_t rte_graph_feature_arc_t; + +/** rte_graph feature object */ +typedef uint8_t rte_graph_feature_t; + +/** runtime active feature list index with in feature arc*/ +typedef uint16_t rte_graph_feature_rt_list_t; + +/** per feature arc monotonically increasing counter to synchronize fast path APIs */ +typedef uint16_t rte_graph_feature_counter_t; + +/** + * Initialize feature arc subsystem + * + * @param max_feature_arcs + * Maximum number of feature arcs required to be supported + * + * @return + * 0: Success + * <0: Failure + */ +__rte_experimental +int rte_graph_feature_arc_init(int max_feature_arcs); + +/** + * Create a feature arc + * + * @param feature_arc_name + * Feature arc name with max length of @ref RTE_GRAPH_FEATURE_ARC_NAMELEN + * @param max_features + * Maximum number of features to be supported in this feature arc + * @param max_indexes + * Maximum number of interfaces/ports/indexes to be supported + * @param start_node + * Base node where this feature arc's features are checked in fast path + * @param[out] _arc + * Feature arc object + * + * @return + * 0: Success + * <0: Failure + */ +__rte_experimental +int rte_graph_feature_arc_create(const char *feature_arc_name, int max_features, int max_indexes, + struct rte_node_register *start_node, + rte_graph_feature_arc_t *_arc); + +/** + * Get feature arc object with name + * + * @param arc_name + * Feature arc name provided to successful @ref rte_graph_feature_arc_create + * @param[out] _arc + * Feature arc object returned. Valid only when API returns SUCCESS + * + * @return + * 0: Success + * <0: Failure. + */ +__rte_experimental +int rte_graph_feature_arc_lookup_by_name(const char *arc_name, rte_graph_feature_arc_t *_arc); + +/** + * Add a feature to already created feature arc. For instance + * + * 1. Add first feature node: "ipv4-input" to input arc + * rte_graph_feature_add(ipv4_input_arc, "ipv4-input", NULL, NULL); + * + * 2. Add "ipsec-input" feature node after "ipv4-input" feature + * rte_graph_feature_add(ipv4_input_arc, "ipsec-input", "ipv4-input", NULL); + * + * 3. Add "ipv4-pre-classify-input" node before "ipv4-input" feature + * rte_graph_feature_add(ipv4_input_arc, "ipv4-pre-classify-input"", NULL, "ipv4-input"); + * + * 4. Add "acl-classify-input" node after ipv4-input but before ipsec-input + * rte_graph_feature_add(ipv4_input_arc, "acl-classify-input", "ipv4-input", "ipsec-input"); + * + * @param _arc + * Feature arc handle returned from @ref rte_graph_feature_arc_create() + * @param feature_node + * Graph node representing feature. On success, feature_node is next_node of + * feature_arc->start_node + * @param runs_after + * Add this feature_node after already added "runs_after". Creates + * start_node -> runs_after -> this_feature sequence + * @param runs_before + * Add this feature_node before already added "runs_before". Creates + * start_node -> this_feature -> runs_before sequence + * + * <I> Must be called before rte_graph_create() </I> + * <I> rte_graph_feature_add() is not allowed after call to + * rte_graph_feature_enable() so all features must be added before they can be + * enabled </I> + * + * @return + * 0: Success + * <0: Failure + */ +__rte_experimental +int rte_graph_feature_add(rte_graph_feature_arc_t _arc, struct rte_node_register *feature_node, + const char *runs_after, const char *runs_before); + +/** + * Enable feature within a feature arc + * + * Must be called after @b rte_graph_create(). + * + * @param _arc + * Feature arc object returned by @ref rte_graph_feature_arc_create or @ref + * rte_graph_feature_arc_lookup_by_name + * @param index + * Application specific index. Can be corresponding to interface_id/port_id etc + * @param feature_name + * Name of the node which is already added via @ref rte_graph_feature_add + * @param user_data + * Application specific data which is retrieved in fast path + * + * @return + * 0: Success + * <0: Failure + */ +__rte_experimental +int rte_graph_feature_enable(rte_graph_feature_arc_t _arc, uint32_t index, const char *feature_name, + int32_t user_data); + +/** + * Validate whether subsequent enable/disable feature would succeed or not. + * API is thread-safe + * + * @param _arc + * Feature arc object returned by @ref rte_graph_feature_arc_create or @ref + * rte_graph_feature_arc_lookup_by_name + * @param index + * Application specific index. Can be corresponding to interface_id/port_id etc + * @param feature_name + * Name of the node which is already added via @ref rte_graph_feature_add + * @param is_enable_disable + * If 1, validate whether subsequent @ref rte_graph_feature_enable would pass or not + * If 0, validate whether subsequent @ref rte_graph_feature_disable would pass or not + * @param emit_logs + * If passed true, emit error logs when failure is returned + * If passed false, do not emit error logs when failure is returned + * + * @return + * 0: Subsequent enable/disable API would pass + * <0: Subsequent enable/disable API would not pass + */ +__rte_experimental +int rte_graph_feature_validate(rte_graph_feature_arc_t _arc, uint32_t index, + const char *feature_name, int is_enable_disable, bool emit_logs); + +/** + * Disable already enabled feature within a feature arc + * + * Must be called after @b rte_graph_create(). API is *NOT* Thread-safe + * + * @param _arc + * Feature arc object returned by @ref rte_graph_feature_arc_create or @ref + * rte_graph_feature_arc_lookup_by_name + * @param index + * Application specific index. Can be corresponding to interface_id/port_id etc + * @param feature_name + * Name of the node which is already added via @ref rte_graph_feature_add + * + * @return + * 0: Success + * <0: Failure + */ +__rte_experimental +int rte_graph_feature_disable(rte_graph_feature_arc_t _arc, uint32_t index, + const char *feature_name); + +/** + * Get rte_graph_feature_t object from feature name + * + * @param arc + * Feature arc object returned by @ref rte_graph_feature_arc_create or @ref + * rte_graph_feature_arc_lookup_by_name + * @param feature_name + * Feature name provided to @ref rte_graph_feature_add + * @param[out] feature + * Feature object + * + * @return + * 0: Success + * <0: Failure + */ +__rte_experimental +int rte_graph_feature_lookup(rte_graph_feature_arc_t arc, const char *feature_name, + rte_graph_feature_t *feature); + +/** + * Delete feature_arc object + * + * @param _arc + * Feature arc object returned by @ref rte_graph_feature_arc_create or @ref + * rte_graph_feature_arc_lookup_by_name + * + * @return + * 0: Success + * <0: Failure + */ +__rte_experimental +int rte_graph_feature_arc_destroy(rte_graph_feature_arc_t _arc); + +/** + * Cleanup all feature arcs + * + * @return + * 0: Success + * <0: Failure + */ +__rte_experimental +int rte_graph_feature_arc_cleanup(void); + +/** + * Slow path API to know how many features are added (NOT enabled) within a + * feature arc + * + * @param _arc + * Feature arc object + * + * @return: Number of added features to arc + */ +__rte_experimental +uint32_t rte_graph_feature_arc_num_features(rte_graph_feature_arc_t _arc); + +/** + * Slow path API to know how many features are currently enabled within a + * feature arc across all indexes. If a single feature is enabled on all interfaces, + * this API would return "number_of_interfaces" as count (but not "1") + * + * @param _arc + * Feature arc object + * + * @return: Number of enabled features across all indexes + */ +__rte_experimental +uint32_t rte_graph_feature_arc_num_enabled_features(rte_graph_feature_arc_t _arc); + +/** + * Slow path API to get feature node name from rte_graph_feature_t object + * + * @param _arc + * Feature arc object + * @param feature + * Feature object + * + * @return: Name of the feature node + */ +__rte_experimental +char *rte_graph_feature_arc_feature_to_name(rte_graph_feature_arc_t _arc, + rte_graph_feature_t feature); + +/** + * Slow path API to get corresponding struct rte_node_register * from + * rte_graph_feature_t + * + * @param _arc + * Feature arc object + * @param feature + * Feature object + * + * @return: struct rte_node_register * of feature node on SUCCESS else NULL + */ +__rte_experimental +struct rte_node_register * +rte_graph_feature_arc_feature_to_node(rte_graph_feature_arc_t _arc, + rte_graph_feature_t feature); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/graph/rte_graph_feature_arc_worker.h b/lib/graph/rte_graph_feature_arc_worker.h new file mode 100644 index 0000000000..5c76cb1151 --- /dev/null +++ b/lib/graph/rte_graph_feature_arc_worker.h @@ -0,0 +1,672 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(C) 2024 Marvell International Ltd. + */ + +#ifndef _RTE_GRAPH_FEATURE_ARC_WORKER_H_ +#define _RTE_GRAPH_FEATURE_ARC_WORKER_H_ + +#include <stddef.h> +#include <rte_graph_feature_arc.h> +#include <rte_bitops.h> + +/** + * @file + * + * rte_graph_feature_arc_worker.h + * + * Defines fast path structure + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** @internal + * + * Slow path feature node info list + */ +struct rte_graph_feature_node_list { + /** Next feature */ + STAILQ_ENTRY(rte_graph_feature_node_list) next_feature; + + /** node representing feature */ + struct rte_node_register *feature_node; + + /** How many indexes/interfaces using this feature */ + int32_t ref_count; + + /* node_index in list (after feature_enable())*/ + uint32_t node_index; + + /** Back pointer to feature arc */ + void *feature_arc; + + /** rte_edge_t to this feature node from feature_arc->start_node */ + rte_edge_t edge_to_this_feature; +}; + +/** + * Feature data object: + * + * Feature data stores information to steer packets for: + * - a feature with in feature arc + * - Index i.e. Port/Interface index + * + * Each feature data object holds + * - User data of current feature retrieved via rte_graph_feature_user_data_get() + * - next_edge is used in two conditions when packet to be steered from + * -- start_node to first enabled feature on an interface index + * -- current feature node to next enabled feature on an interface index + * - next_enabled_feature on interface index, if current feature is not + * consuming packet + * + * While user_data corresponds to current enabled feature node, while + * next_edge and next_enabled_feature corresponds to be next enabled feature + * node on an interface index + * + * First enabled feature on interface index can be retrieved via: + * - rte_graph_feature_first_feature_get() if arc's start_node is trying to + * steer packet from start_node to first enabled feature on interface index + * + * Next enabled feature on interface index can be retrieved via: + * - rte_graph_feature_next_feature_get() if current node is not arc's + * start_node. Input to rte_graph_feature_next_feature_get() is current + * enabled feature and interface index + */ +typedef struct __rte_packed rte_graph_feature_data { + /** edge from current node to next enabled feature */ + rte_edge_t next_edge; + + union { + uint16_t reserved; + struct { + /** next enabled feature on index from current feature */ + rte_graph_feature_t next_enabled_feature; + }; + }; + + /** user_data set by application in rte_graph_feature_enable() for + * - current feature + * - interface index + */ + int32_t user_data; +} rte_graph_feature_data_t; + +/** + * Feature object + * + * Feature object holds feature data object for every index/interface within + * feature + * + * Within a given arc and interface index, first feature object can be + * retrieved in arc's start_node via: + * - rte_graph_feature_arc_first_feature_get() + * + * Feature data information can be retrieved for first feature in start node via + * - rte_graph_feature_arc_feature_set() + * + * Next enabled feature on interface index can be retrieved via: + * - rte_graph_feature_arc_next_feature_get() + * + * Typically application stores rte_graph_feature_t object in rte_mbuf. + * rte_graph_feature_t can be translated to (struct rte_graph_feature *) via + * rte_graph_feature_get() in fast path. Further if needed, feature data for an + * index within a feature can be retrieved via rte_graph_feature_data_get() + */ +struct __rte_cache_aligned rte_graph_feature { + /** feature index or rte_graph_feature_t */ + uint16_t this_feature_index; + + /* + * Array of size arc->feature_data_size + * + * <----------------- Feature --------------------------> + * [data-index-0][data-index-1]...[data-index-max_index-1] + * + * sizeof(feature_data_by_index[0] == sizeof(rte_graph_feature_data_t) + * + */ + uint8_t feature_data_by_index[]; +}; + +/** + * Feature list object + * + * Feature list is required to decouple fast path APIs with control path APIs. + * + * There are two feature lists: active, passive + * + * While fast path APIs always work on active list, control plane updates + * passive lists and atomically switch passive list to active list to make it + * available to fast path APIs + * + * Each feature node in start of it's fast path function, must grab active list from + * arc via + * - rte_graph_feature_arc_has_any_feature() or + * rte_graph_feature_arc_has_feature() + * + * Retrieved list must be provided to other feature arc fast path APIs so that + * any control plane changes of active list should not impact current node + * execution iteration. Active list change would be reflected to current node + * in next iteration + * + * With active/passive list mechanism and integrating RCU APIs in graph worker + * loop, application can update features at runtime without stopping fast path + * cores. A RCU synchronization is required when a feature needs to be disabled via + * rte_graph_feature_disable(). On enabling a feature, RCU synchronization may + * not be required + * + */ +typedef struct __rte_cache_aligned rte_graph_feature_list { + /** + * fast path array holding per_feature data. + * Duplicate entry as feature-arc also hold this pointer + * arc->features[] + * + *<-------------feature-0 ---------><---------feature-1 -------------->... + *[index-0][index-1]...[max_index-1]<-ALIGN->[index-0][index-1] ...[max_index-1]... + */ + struct rte_graph_feature *indexed_by_features; + /* + * fast path array holding first enabled feature per index + * (Required in start_node. In non start_node, mbuf can hold next enabled + * feature) + */ + rte_graph_feature_t first_enabled_feature_by_index[]; +} rte_graph_feature_list_t; + +/** + * rte_graph Feature arc object + * + * Feature arc object holds control plane and fast path information for all + * features and all interface index information for steering packets across + * feature nodes + * + * Within a feature arc, only RTE_GRAPH_FEATURE_MAX_PER_ARC features can be + * added. If more features needs to be added, another feature arc can be + * created + * + * Application gets rte_graph_feature_arc_t object via + * - rte_graph_feature_arc_create() OR + * - rte_graph_feature_arc_lookup_by_name() + * + * In fast path, rte_graph_feature_arc_t can be translated to (struct + * rte_graph_feature_arc *) via rte_graph_feature_arc_get(). Later is needed to + * add as an input argument to all fast path feature arc APIs + */ +struct __rte_cache_aligned rte_graph_feature_arc { + /* First 64B is fast path variables */ + RTE_MARKER fast_path_variables; + + /** runtime active feature list */ + rte_graph_feature_rt_list_t active_feature_list; + + /** Actual Size of feature_list object */ + uint16_t feature_list_size; + + /** + * Size each feature in fastpath. + * Required to navigate from feature to another feature in fast path + */ + uint16_t feature_size; + + /** + * Size of all feature data for an index + * Required to navigate through various feature data within a feature + * in fast path + */ + uint16_t feature_data_size; + + /** + * Quick fast path bitmask indicating if any feature enabled or not on + * any of the indexes. Helps in optimally process packets for the case + * when features are added but not enabled + * + * Separate for active and passive list + */ + uint64_t feature_enable_bitmask[2]; + + /** + * Pointer to both active and passive feature list object + */ + rte_graph_feature_list_t *feature_list[2]; + + /** + * Feature objects for each list + */ + struct rte_graph_feature *features[2]; + + /** index in feature_arc_main */ + uint16_t feature_arc_index; + + uint16_t reserved[3]; + + /** Slow path variables follows*/ + RTE_MARKER slow_path_variables; + + /** feature arc name */ + char feature_arc_name[RTE_GRAPH_FEATURE_ARC_NAMELEN]; + + /** All feature lists */ + STAILQ_HEAD(, rte_graph_feature_node_list) all_features; + + /** control plane counter to track enabled features */ + uint32_t runtime_enabled_features; + + /** Back pointer to feature_arc_main */ + void *feature_arc_main; + + /** Arc's start/base node */ + struct rte_node_register *start_node; + + /** maximum number of features supported by this arc */ + uint32_t max_features; + + /** maximum number of index supported by this arc */ + uint32_t max_indexes; + + /** Slow path bit mask per feature per index */ + uint64_t feature_bit_mask_by_index[]; +}; + +/** + * Feature arc main object + * + * Holds all feature arcs created by application + * + * RTE_GRAPH_FEATURE_ARC_MAX number of feature arcs can be created by + * application via rte_graph_feature_arc_create() + */ +typedef struct feature_arc_main { + /** number of feature arcs created by application */ + uint32_t num_feature_arcs; + + /** max features arcs allowed */ + uint32_t max_feature_arcs; + + /** feature arcs */ + rte_graph_feature_arc_t feature_arcs[]; +} rte_graph_feature_arc_main_t; + +/** @internal Get feature arc pointer from object */ +#define rte_graph_feature_arc_get(arc) ((struct rte_graph_feature_arc *)arc) + +extern rte_graph_feature_arc_main_t *__feature_arc_main; + +/** + * API to know if feature is valid or not + */ +__rte_experimental +static __rte_always_inline int +rte_graph_feature_is_valid(rte_graph_feature_t feature) +{ + return (feature != RTE_GRAPH_FEATURE_INVALID); +} + +/** + * Get rte_graph_feature object with no checks + * + * @param arc + * Feature arc pointer + * @param feature + * Feature index + * @param feature_list + * active feature list retrieved from rte_graph_feature_arc_has_any_feature() + * or rte_graph_feature_arc_has_feature() + * + * @return + * Internal feature object. + */ +__rte_experimental +static __rte_always_inline struct rte_graph_feature * +__rte_graph_feature_get(struct rte_graph_feature_arc *arc, rte_graph_feature_t feature, + const rte_graph_feature_rt_list_t feature_list) +{ + return ((struct rte_graph_feature *)(((uint8_t *)arc->features[feature_list]) + + (feature * arc->feature_size))); +} + +/** + * Get rte_graph_feature object for a given interface/index from feature arc + * + * @param arc + * Feature arc pointer + * @param feature + * Feature index + * + * @return + * Internal feature object. + */ +__rte_experimental +static __rte_always_inline struct rte_graph_feature * +rte_graph_feature_get(struct rte_graph_feature_arc *arc, rte_graph_feature_t feature) +{ + if (unlikely(feature >= arc->max_features)) + RTE_VERIFY(0); + + if (likely(rte_graph_feature_is_valid(feature))) + return __rte_graph_feature_get(arc, feature, arc->active_feature_list); + + return NULL; +} + +__rte_experimental +static __rte_always_inline rte_graph_feature_data_t * +__rte_graph_feature_data_get(struct rte_graph_feature_arc *arc, struct rte_graph_feature *feature, + uint8_t index) +{ + RTE_SET_USED(arc); + return ((rte_graph_feature_data_t *)(((uint8_t *)feature->feature_data_by_index) + + (index * sizeof(rte_graph_feature_data_t)))); +} + +/** + * Get rte_graph feature data object for a index in feature + * + * @param arc + * feature arc + * @param feature + * Pointer to feature object + * @param index + * Index of feature maintained in slow path linked list + * + * @return + * Valid feature data + */ +__rte_experimental +static __rte_always_inline rte_graph_feature_data_t * +rte_graph_feature_data_get(struct rte_graph_feature_arc *arc, struct rte_graph_feature *feature, + uint8_t index) +{ + if (likely(index < arc->max_indexes)) + return __rte_graph_feature_data_get(arc, feature, index); + + RTE_VERIFY(0); +} + +/** + * Fast path API to check if any feature enabled on a feature arc + * Typically from arc->start_node process function + * + * @param arc + * Feature arc object + * @param[out] plist + * Pointer to runtime active feature list which needs to be provided to other + * fast path APIs + * + * @return + * 0: If no feature enabled + * Non-Zero: Bitmask of features enabled. plist is valid + * + */ +__rte_experimental +static __rte_always_inline uint64_t +rte_graph_feature_arc_has_any_feature(struct rte_graph_feature_arc *arc, + rte_graph_feature_rt_list_t *plist) +{ + *plist = rte_atomic_load_explicit(&arc->active_feature_list, rte_memory_order_relaxed); + + return (rte_atomic_load_explicit(arc->feature_enable_bitmask + (uint8_t)*plist, + rte_memory_order_relaxed)); +} + +/** + * Fast path API to check if provided feature is enabled on any interface/index + * or not + * + * @param arc + * Feature arc object + * @param feature + * Input rte_graph_feature_t that needs to be checked + * @param[out] plist + * Returns active list to caller which needs to be provided to other fast path + * APIs + * + * @return + * 1: If input [feature] is enabled in arc + * 0: If input [feature] is not enabled in arc + */ +__rte_experimental +static __rte_always_inline int +rte_graph_feature_arc_has_feature(struct rte_graph_feature_arc *arc, + rte_graph_feature_t feature, + rte_graph_feature_rt_list_t *plist) +{ + uint64_t bitmask = RTE_BIT64(feature); + + *plist = rte_atomic_load_explicit(&arc->active_feature_list, rte_memory_order_relaxed); + + return (bitmask & rte_atomic_load_explicit(arc->feature_enable_bitmask + (uint8_t)*plist, + rte_memory_order_relaxed)); +} + +/** + * Prefetch feature arc fast path cache line + * + * @param arc + * RTE_GRAPH feature arc object + */ +__rte_experimental +static __rte_always_inline void +rte_graph_feature_arc_prefetch(struct rte_graph_feature_arc *arc) +{ + rte_prefetch0((void *)&arc->fast_path_variables); +} + +/** + * Prefetch feature related fast path cache line + * + * @param arc + * RTE_GRAPH feature arc object + * @param list + * Pointer to runtime active feature list from rte_graph_feature_arc_has_any_feature(); + * @param feature + * Pointer to feature object + */ +__rte_experimental +static __rte_always_inline void +rte_graph_feature_arc_feature_prefetch(struct rte_graph_feature_arc *arc, + const rte_graph_feature_rt_list_t list, + rte_graph_feature_t feature) +{ + /* feature cache line */ + if (likely(rte_graph_feature_is_valid(feature))) + rte_prefetch0((void *)__rte_graph_feature_get(arc, feature, list)); +} + +/** + * Prefetch feature data upfront. Perform sanity + * + * @param arc + * RTE_GRAPH feature arc object + * @param list + * Pointer to runtime active feature list from rte_graph_feature_arc_has_any_feature(); + * @param feature + * Pointer to feature object returned from @ref + * rte_graph_feature_arc_first_feature_get() + * @param index + * Interface/index + */ +__rte_experimental +static __rte_always_inline void +rte_graph_feature_arc_data_prefetch(struct rte_graph_feature_arc *arc, + const rte_graph_feature_rt_list_t list, + rte_graph_feature_t feature, uint32_t index) +{ + if (likely(rte_graph_feature_is_valid(feature))) + rte_prefetch0((void *)((uint8_t *)arc->features[list] + + offsetof(struct rte_graph_feature, feature_data_by_index) + + (index * sizeof(rte_graph_feature_data_t)))); +} + +/** + * Fast path API to get first enabled feature on interface index + * Typically required in arc->start_node so that from returned feature, + * feature-data can be retrieved to steer packets + * + * @param arc + * Feature arc object + * @param list + * Pointer to runtime active feature list from + * rte_graph_feature_arc_has_any_feature() or + * rte_graph_feature_arc_has_feature() + * @param index + * Interface Index + * @param[out] feature + * Pointer to rte_graph_feature_t. + * + * @return + * 1. Success. If first feature field is enabled and returned [feature] is valid + * 0. Failure. If first feature field is disabled in arc + * + */ +__rte_experimental +static __rte_always_inline int +rte_graph_feature_arc_first_feature_get(struct rte_graph_feature_arc *arc, + const rte_graph_feature_rt_list_t list, + uint32_t index, + rte_graph_feature_t *feature) +{ + struct rte_graph_feature_list *feature_list = arc->feature_list[list]; + + *feature = feature_list->first_enabled_feature_by_index[index]; + + return rte_graph_feature_is_valid(*feature); +} + +/** + * Fast path API to get next enabled feature on interface index with provided + * input feature + * + * @param arc + * Feature arc object + * @param list + * Pointer to runtime active feature list from + * rte_graph_feature_arc_has_any_feature() or + * @param index + * Interface Index + * @param[out] feature + * Pointer to rte_graph_feature_t. API sets next enabled feature on [index] + * from provided input feature. Valid only if API returns Success + * @param[out] next_edge + * Edge from current feature to next feature. Valid only if next feature is valid + * + * @return + * 1. Success. first feature field is enabled/valid + * 0. Failure. first feature field is disabled/invalid + */ +__rte_experimental +static __rte_always_inline int +rte_graph_feature_arc_next_feature_get(struct rte_graph_feature_arc *arc, + const rte_graph_feature_rt_list_t list, + uint32_t index, + rte_graph_feature_t *feature, + rte_edge_t *next_edge) +{ + rte_graph_feature_data_t *feature_data = NULL; + struct rte_graph_feature *f = NULL; + + if (likely(rte_graph_feature_is_valid(*feature))) { + f = __rte_graph_feature_get(arc, *feature, list); + feature_data = rte_graph_feature_data_get(arc, f, index); + *feature = feature_data->next_enabled_feature; + *next_edge = feature_data->next_edge; + return rte_graph_feature_is_valid(*feature); + } + + return 0; +} + +/** + * Set fields with respect to first enabled feature in an arc and return edge + * Typically returned feature and interface index must be saved in rte_mbuf + * structure to pass this information to next feature node + * + * @param arc + * Feature arc object + * @param list + * Pointer to runtime active feature list from rte_graph_feature_arc_has_any_feature(); + * @param index + * Index (of interface) + * @param[out] gf + * Pointer to rte_graph_feature_t. Valid if API returns Success + * @param[out] edge + * Edge to steer packet from arc->start_node to first enabled feature. Valid + * only if API returns Success + * + * @return + * 0: If valid feature is enabled and set by API in *gf + * 1: If valid feature is NOT enabled + */ +__rte_experimental +static __rte_always_inline rte_graph_feature_t +rte_graph_feature_arc_feature_set(struct rte_graph_feature_arc *arc, + const rte_graph_feature_rt_list_t list, + uint32_t index, + rte_graph_feature_t *gf, + rte_edge_t *edge) +{ + struct rte_graph_feature_list *feature_list = arc->feature_list[list]; + struct rte_graph_feature_data *feature_data = NULL; + struct rte_graph_feature *feature = NULL; + rte_graph_feature_t f; + + f = feature_list->first_enabled_feature_by_index[index]; + + if (unlikely(rte_graph_feature_is_valid(f))) { + feature = __rte_graph_feature_get(arc, f, list); + feature_data = rte_graph_feature_data_get(arc, feature, index); + *gf = f; + *edge = feature_data->next_edge; + return 0; + } + + return 1; +} + +__rte_experimental +static __rte_always_inline int32_t +__rte_graph_feature_user_data_get(rte_graph_feature_data_t *fdata) +{ + return fdata->user_data; +} + +/** + * Get user data corresponding to current feature set by application in + * rte_graph_feature_enable() + * + * @param arc + * Feature arc object + * @param list + * Pointer to runtime active feature list from rte_graph_feature_arc_has_any_feature(); + * @param feature + * Feature index + * @param index + * Interface index + * + * @return + * -1: Failure + * Valid user data: Success + */ +__rte_experimental +static __rte_always_inline int32_t +rte_graph_feature_user_data_get(struct rte_graph_feature_arc *arc, + const rte_graph_feature_rt_list_t list, + rte_graph_feature_t feature, + uint32_t index) +{ + rte_graph_feature_data_t *fdata = NULL; + struct rte_graph_feature *f = NULL; + + if (likely(rte_graph_feature_is_valid(feature))) { + f = __rte_graph_feature_get(arc, feature, list); + fdata = rte_graph_feature_data_get(arc, f, index); + return __rte_graph_feature_user_data_get(fdata); + } + + return -1; +} +#ifdef __cplusplus +} +#endif +#endif diff --git a/lib/graph/version.map b/lib/graph/version.map index 2c83425ddc..3b7f475afd 100644 --- a/lib/graph/version.map +++ b/lib/graph/version.map @@ -52,3 +52,23 @@ DPDK_25 { local: *; }; + +EXPERIMENTAL { + global: + + # added in 24.11 + rte_graph_feature_arc_init; + rte_graph_feature_arc_create; + rte_graph_feature_arc_lookup_by_name; + rte_graph_feature_add; + rte_graph_feature_enable; + rte_graph_feature_validate; + rte_graph_feature_disable; + rte_graph_feature_lookup; + rte_graph_feature_arc_destroy; + rte_graph_feature_arc_cleanup; + rte_graph_feature_arc_num_enabled_features; + rte_graph_feature_arc_num_features; + rte_graph_feature_arc_feature_to_name; + rte_graph_feature_arc_feature_to_node; +}; -- 2.43.0 ^ permalink raw reply [flat|nested] 46+ messages in thread
* [RFC PATCH v2 2/5] graph: add feature arc option in graph create 2024-10-08 13:30 ` [RFC PATCH v2 0/5] " Nitin Saxena 2024-10-08 13:30 ` [RFC PATCH v2 1/5] graph: add feature arc support Nitin Saxena @ 2024-10-08 13:30 ` Nitin Saxena 2024-10-08 13:30 ` [RFC PATCH v2 3/5] graph: add IPv4 output feature arc Nitin Saxena ` (3 subsequent siblings) 5 siblings, 0 replies; 46+ messages in thread From: Nitin Saxena @ 2024-10-08 13:30 UTC (permalink / raw) To: Jerin Jacob, Kiran Kumar K, Nithin Dabilpuram, Zhirun Yan Cc: dev, Nitin Saxena, Pavan Nikhilesh Added option in graph create to call feature-specific process node functions. This removes extra overhead for checking feature arc status in nodes where application is not using feature arc processing Signed-off-by: Pavan Nikhilesh <pbhagavatula@marvell.com> Signed-off-by: Nitin Saxena <nsaxena@marvell.com> --- lib/graph/graph.c | 1 + lib/graph/graph_populate.c | 7 ++++++- lib/graph/graph_private.h | 3 +++ lib/graph/node.c | 2 ++ lib/graph/rte_graph.h | 3 +++ 5 files changed, 15 insertions(+), 1 deletion(-) diff --git a/lib/graph/graph.c b/lib/graph/graph.c index d5b8c9f918..b0ad3a83ae 100644 --- a/lib/graph/graph.c +++ b/lib/graph/graph.c @@ -455,6 +455,7 @@ rte_graph_create(const char *name, struct rte_graph_param *prm) graph->parent_id = RTE_GRAPH_ID_INVALID; graph->lcore_id = RTE_MAX_LCORE; graph->num_pkt_to_capture = prm->num_pkt_to_capture; + graph->feature_arc_enabled = prm->feature_arc_enable; if (prm->pcap_filename) rte_strscpy(graph->pcap_filename, prm->pcap_filename, RTE_GRAPH_PCAP_FILE_SZ); diff --git a/lib/graph/graph_populate.c b/lib/graph/graph_populate.c index ed596a7711..5d8aa7b903 100644 --- a/lib/graph/graph_populate.c +++ b/lib/graph/graph_populate.c @@ -79,8 +79,13 @@ graph_nodes_populate(struct graph *_graph) if (graph_pcap_is_enable()) { node->process = graph_pcap_dispatch; node->original_process = graph_node->node->process; - } else + if (_graph->feature_arc_enabled && graph_node->node->feat_arc_proc) + node->original_process = graph_node->node->feat_arc_proc; + } else { node->process = graph_node->node->process; + if (_graph->feature_arc_enabled && graph_node->node->feat_arc_proc) + node->process = graph_node->node->feat_arc_proc; + } memcpy(node->name, graph_node->node->name, RTE_GRAPH_NAMESIZE); pid = graph_node->node->parent_id; if (pid != RTE_NODE_ID_INVALID) { /* Cloned node */ diff --git a/lib/graph/graph_private.h b/lib/graph/graph_private.h index d557d55f2d..58ba0abeff 100644 --- a/lib/graph/graph_private.h +++ b/lib/graph/graph_private.h @@ -56,6 +56,7 @@ struct node { unsigned int lcore_id; /**< Node runs on the Lcore ID used for mcore dispatch model. */ rte_node_process_t process; /**< Node process function. */ + rte_node_process_t feat_arc_proc; /**< Node feature-arch process function. */ rte_node_init_t init; /**< Node init function. */ rte_node_fini_t fini; /**< Node fini function. */ rte_node_t id; /**< Allocated identifier for the node. */ @@ -126,6 +127,8 @@ struct graph { /**< Number of packets to be captured per core. */ char pcap_filename[RTE_GRAPH_PCAP_FILE_SZ]; /**< pcap file name/path. */ + uint8_t feature_arc_enabled; + /**< Graph feature arc. */ STAILQ_HEAD(gnode_list, graph_node) node_list; /**< Nodes in a graph. */ }; diff --git a/lib/graph/node.c b/lib/graph/node.c index 99a9622779..d8fd273543 100644 --- a/lib/graph/node.c +++ b/lib/graph/node.c @@ -90,6 +90,7 @@ __rte_node_register(const struct rte_node_register *reg) goto free; node->flags = reg->flags; node->process = reg->process; + node->feat_arc_proc = reg->feat_arc_proc; node->init = reg->init; node->fini = reg->fini; node->nb_edges = reg->nb_edges; @@ -137,6 +138,7 @@ node_clone(struct node *node, const char *name) /* Clone the source node */ reg->flags = node->flags; reg->process = node->process; + reg->feat_arc_proc = node->feat_arc_proc; reg->init = node->init; reg->fini = node->fini; reg->nb_edges = node->nb_edges; diff --git a/lib/graph/rte_graph.h b/lib/graph/rte_graph.h index ecfec2068a..ebbdbbea48 100644 --- a/lib/graph/rte_graph.h +++ b/lib/graph/rte_graph.h @@ -163,6 +163,8 @@ struct rte_graph_param { uint64_t num_pkt_to_capture; /**< Number of packets to capture. */ char *pcap_filename; /**< Filename in which packets to be captured.*/ + bool feature_arc_enable; /**< Enable Graph feature arc. */ + union { struct { uint64_t rsvd; /**< Reserved for rtc model. */ @@ -470,6 +472,7 @@ struct rte_node_register { uint64_t flags; /**< Node configuration flag. */ #define RTE_NODE_SOURCE_F (1ULL << 0) /**< Node type is source. */ rte_node_process_t process; /**< Node process function. */ + rte_node_process_t feat_arc_proc; /**< Node feature-arch process function. */ rte_node_init_t init; /**< Node init function. */ rte_node_fini_t fini; /**< Node fini function. */ rte_node_t id; /**< Node Identifier. */ -- 2.43.0 ^ permalink raw reply [flat|nested] 46+ messages in thread
* [RFC PATCH v2 3/5] graph: add IPv4 output feature arc 2024-10-08 13:30 ` [RFC PATCH v2 0/5] " Nitin Saxena 2024-10-08 13:30 ` [RFC PATCH v2 1/5] graph: add feature arc support Nitin Saxena 2024-10-08 13:30 ` [RFC PATCH v2 2/5] graph: add feature arc option in graph create Nitin Saxena @ 2024-10-08 13:30 ` Nitin Saxena 2024-10-08 13:30 ` [RFC PATCH v2 4/5] test/graph_feature_arc: add functional tests Nitin Saxena ` (2 subsequent siblings) 5 siblings, 0 replies; 46+ messages in thread From: Nitin Saxena @ 2024-10-08 13:30 UTC (permalink / raw) To: Jerin Jacob, Kiran Kumar K, Nithin Dabilpuram, Zhirun Yan Cc: dev, Nitin Saxena add ipv4-output feature arc in ipv4-rewrite node to allow custom/standard nodes(like outbound IPsec policy node) in outgoing forwarding path Signed-off-by: Nitin Saxena <nsaxena@marvell.com> --- lib/node/ip4_rewrite.c | 476 +++++++++++++++++++++++++++++------- lib/node/ip4_rewrite_priv.h | 15 +- lib/node/node_private.h | 20 +- lib/node/rte_node_ip4_api.h | 3 + 4 files changed, 417 insertions(+), 97 deletions(-) diff --git a/lib/node/ip4_rewrite.c b/lib/node/ip4_rewrite.c index 34a920df5e..5a160335f2 100644 --- a/lib/node/ip4_rewrite.c +++ b/lib/node/ip4_rewrite.c @@ -15,39 +15,156 @@ #include "ip4_rewrite_priv.h" #include "node_private.h" +#define ALL_PKT_MASK 0xf + struct ip4_rewrite_node_ctx { + rte_graph_feature_arc_t output_feature_arc; /* Dynamic offset to mbuf priv1 */ int mbuf_priv1_off; /* Cached next index */ uint16_t next_index; + uint16_t last_tx; }; +typedef struct rewrite_priv_vars { + union { + struct { + rte_xmm_t xmm1; + }; + struct __rte_packed { + uint16_t next0; + uint16_t next1; + uint16_t next2; + uint16_t next3; + uint16_t last_tx_interface; + uint16_t last_if_feature; + uint16_t actual_feat_mask; + uint16_t speculative_feat_mask; + }; + }; +} rewrite_priv_vars_t; + static struct ip4_rewrite_node_main *ip4_rewrite_nm; #define IP4_REWRITE_NODE_LAST_NEXT(ctx) \ (((struct ip4_rewrite_node_ctx *)ctx)->next_index) +#define IP4_REWRITE_NODE_LAST_TX(ctx) \ + (((struct ip4_rewrite_node_ctx *)ctx)->last_tx) + #define IP4_REWRITE_NODE_PRIV1_OFF(ctx) \ (((struct ip4_rewrite_node_ctx *)ctx)->mbuf_priv1_off) -static uint16_t -ip4_rewrite_node_process(struct rte_graph *graph, struct rte_node *node, - void **objs, uint16_t nb_objs) +#define IP4_REWRITE_NODE_OUTPUT_FEATURE_ARC(ctx) \ + (((struct ip4_rewrite_node_ctx *)ctx)->output_feature_arc) + +static __rte_always_inline void +prefetch_mbuf_and_dynfield(struct rte_mbuf *mbuf) { + /* prefetch first cache line required for accessing buf_addr */ + rte_prefetch0((void *)mbuf); +} + +static __rte_always_inline void +check_output_feature_x4(struct rte_graph_feature_arc *arc, + const rte_graph_feature_rt_list_t flist, + rewrite_priv_vars_t *pvar, struct node_mbuf_priv1 *priv0, + struct node_mbuf_priv1 *priv1, struct node_mbuf_priv1 *priv2, + struct node_mbuf_priv1 *priv3) +{ + uint32_t mask = 0; + uint16_t xor = 0; + + /* + * interface edge's start from 1 and not from 0 as "pkt_drop" + * is next node at 0th index + */ + priv0->if_index = pvar->next0 - 1; + priv1->if_index = pvar->next1 - 1; + priv2->if_index = pvar->next2 - 1; + priv3->if_index = pvar->next3 - 1; + + /* Find out if all packets are sent to last_tx_interface */ + xor = pvar->last_tx_interface ^ priv0->if_index; + xor += priv0->if_index ^ priv1->if_index; + xor += priv1->if_index ^ priv2->if_index; + xor += priv2->if_index ^ priv3->if_index; + + if (likely(!xor)) { + /* copy last interface feature and feature mask */ + priv0->current_feature = priv1->current_feature = + priv2->current_feature = priv3->current_feature = + pvar->last_if_feature; + pvar->actual_feat_mask = pvar->speculative_feat_mask; + } else { + /* create a mask for index which does not have feature + * Also override next edge and if feature enabled, get feature + */ + mask = rte_graph_feature_arc_feature_set(arc, flist, priv0->if_index, + &priv0->current_feature, + &pvar->next0); + + mask |= ((rte_graph_feature_arc_feature_set(arc, flist, priv1->if_index, + &priv1->current_feature, + &pvar->next1)) << 1); + + mask |= ((rte_graph_feature_arc_feature_set(arc, flist, priv2->if_index, + &priv2->current_feature, + &pvar->next2)) << 2); + + mask |= ((rte_graph_feature_arc_feature_set(arc, flist, priv3->if_index, + &priv3->current_feature, + &pvar->next3)) << 3); + + /* + * add last tx and last feature regardless even if feature is + * valid or not + */ + pvar->last_tx_interface = priv3->if_index; + pvar->last_if_feature = priv3->current_feature; + /* Set 0xf if invalid feature to last packet, else 0 */ + pvar->speculative_feat_mask = (priv3->current_feature == + RTE_GRAPH_FEATURE_INVALID) ? ALL_PKT_MASK : 0x0; + pvar->actual_feat_mask = mask; + } +} + +static __rte_always_inline uint16_t +__ip4_rewrite_node_process(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs, + const int dyn, const int check_enabled_features, + struct rte_graph_feature_arc *out_feature_arc, + const rte_graph_feature_rt_list_t flist) +{ + struct node_mbuf_priv1 *priv0 = NULL, *priv1 = NULL, *priv2 = NULL, *priv3 = NULL; struct rte_mbuf *mbuf0, *mbuf1, *mbuf2, *mbuf3, **pkts; struct ip4_rewrite_nh_header *nh = ip4_rewrite_nm->nh; - const int dyn = IP4_REWRITE_NODE_PRIV1_OFF(node->ctx); - uint16_t next0, next1, next2, next3, next_index; - struct rte_ipv4_hdr *ip0, *ip1, *ip2, *ip3; uint16_t n_left_from, held = 0, last_spec = 0; + struct rte_ipv4_hdr *ip0, *ip1, *ip2, *ip3; + rewrite_priv_vars_t pvar; + int64_t fd0, fd1, fd2, fd3; + rte_edge_t fix_spec = 0; void *d0, *d1, *d2, *d3; void **to_next, **from; + uint16_t next_index; rte_xmm_t priv01; rte_xmm_t priv23; int i; - /* Speculative next as last next */ + RTE_SET_USED(fd0); + RTE_SET_USED(fd1); + RTE_SET_USED(fd2); + RTE_SET_USED(fd3); + + /* Initialize speculative variables.*/ + + /* Last interface */ + pvar.last_tx_interface = IP4_REWRITE_NODE_LAST_TX(node->ctx); + /*last next from node ctx*/ next_index = IP4_REWRITE_NODE_LAST_NEXT(node->ctx); + pvar.speculative_feat_mask = ALL_PKT_MASK; + pvar.actual_feat_mask = 0; + rte_prefetch0(nh); pkts = (struct rte_mbuf **)objs; @@ -55,20 +172,47 @@ ip4_rewrite_node_process(struct rte_graph *graph, struct rte_node *node, n_left_from = nb_objs; for (i = 0; i < 4 && i < n_left_from; i++) - rte_prefetch0(pkts[i]); + prefetch_mbuf_and_dynfield(pkts[i]); /* Get stream for the speculated next node */ to_next = rte_node_next_stream_get(graph, node, next_index, nb_objs); + + /* prefetch speculative feature and corresponding data */ + if (check_enabled_features) { + /* + * Get first feature enabled, if any, on last_tx_interface + */ + if (unlikely(rte_graph_feature_arc_first_feature_get(out_feature_arc, + flist, + pvar.last_tx_interface, + (rte_graph_feature_t *) + &pvar.last_if_feature))) { + /* prefetch feature cache line */ + rte_graph_feature_arc_feature_prefetch(out_feature_arc, flist, + pvar.last_if_feature); + + /* prefetch feature data cache line */ + rte_graph_feature_arc_data_prefetch(out_feature_arc, flist, + pvar.last_if_feature, + pvar.last_tx_interface); + /* + * Set speculativa_feat mask to indicate, all 4 packets + * going to feature path + */ + pvar.speculative_feat_mask = 0; + } + } + /* Update Ethernet header of pkts */ while (n_left_from >= 4) { if (likely(n_left_from > 7)) { /* Prefetch only next-mbuf struct and priv area. * Data need not be prefetched as we only write. */ - rte_prefetch0(pkts[4]); - rte_prefetch0(pkts[5]); - rte_prefetch0(pkts[6]); - rte_prefetch0(pkts[7]); + prefetch_mbuf_and_dynfield(pkts[4]); + prefetch_mbuf_and_dynfield(pkts[5]); + prefetch_mbuf_and_dynfield(pkts[6]); + prefetch_mbuf_and_dynfield(pkts[7]); } mbuf0 = pkts[0]; @@ -78,66 +222,138 @@ ip4_rewrite_node_process(struct rte_graph *graph, struct rte_node *node, pkts += 4; n_left_from -= 4; + + /* Copy mbuf private data into private variables */ priv01.u64[0] = node_mbuf_priv1(mbuf0, dyn)->u; priv01.u64[1] = node_mbuf_priv1(mbuf1, dyn)->u; priv23.u64[0] = node_mbuf_priv1(mbuf2, dyn)->u; priv23.u64[1] = node_mbuf_priv1(mbuf3, dyn)->u; - /* Increment checksum by one. */ - priv01.u32[1] += rte_cpu_to_be_16(0x0100); - priv01.u32[3] += rte_cpu_to_be_16(0x0100); - priv23.u32[1] += rte_cpu_to_be_16(0x0100); - priv23.u32[3] += rte_cpu_to_be_16(0x0100); - - /* Update ttl,cksum rewrite ethernet hdr on mbuf0 */ - d0 = rte_pktmbuf_mtod(mbuf0, void *); - rte_memcpy(d0, nh[priv01.u16[0]].rewrite_data, - nh[priv01.u16[0]].rewrite_len); - - next0 = nh[priv01.u16[0]].tx_node; - ip0 = (struct rte_ipv4_hdr *)((uint8_t *)d0 + - sizeof(struct rte_ether_hdr)); - ip0->time_to_live = priv01.u16[1] - 1; - ip0->hdr_checksum = priv01.u16[2] + priv01.u16[3]; - - /* Update ttl,cksum rewrite ethernet hdr on mbuf1 */ - d1 = rte_pktmbuf_mtod(mbuf1, void *); - rte_memcpy(d1, nh[priv01.u16[4]].rewrite_data, - nh[priv01.u16[4]].rewrite_len); - - next1 = nh[priv01.u16[4]].tx_node; - ip1 = (struct rte_ipv4_hdr *)((uint8_t *)d1 + - sizeof(struct rte_ether_hdr)); - ip1->time_to_live = priv01.u16[5] - 1; - ip1->hdr_checksum = priv01.u16[6] + priv01.u16[7]; - - /* Update ttl,cksum rewrite ethernet hdr on mbuf2 */ - d2 = rte_pktmbuf_mtod(mbuf2, void *); - rte_memcpy(d2, nh[priv23.u16[0]].rewrite_data, - nh[priv23.u16[0]].rewrite_len); - next2 = nh[priv23.u16[0]].tx_node; - ip2 = (struct rte_ipv4_hdr *)((uint8_t *)d2 + - sizeof(struct rte_ether_hdr)); - ip2->time_to_live = priv23.u16[1] - 1; - ip2->hdr_checksum = priv23.u16[2] + priv23.u16[3]; - - /* Update ttl,cksum rewrite ethernet hdr on mbuf3 */ - d3 = rte_pktmbuf_mtod(mbuf3, void *); - rte_memcpy(d3, nh[priv23.u16[4]].rewrite_data, - nh[priv23.u16[4]].rewrite_len); - - next3 = nh[priv23.u16[4]].tx_node; - ip3 = (struct rte_ipv4_hdr *)((uint8_t *)d3 + - sizeof(struct rte_ether_hdr)); - ip3->time_to_live = priv23.u16[5] - 1; - ip3->hdr_checksum = priv23.u16[6] + priv23.u16[7]; + /* Copy next edge from next hop */ + pvar.next0 = nh[priv01.u16[0]].tx_node; + pvar.next1 = nh[priv01.u16[4]].tx_node; + pvar.next2 = nh[priv23.u16[0]].tx_node; + pvar.next3 = nh[priv23.u16[4]].tx_node; + + if (check_enabled_features) { + priv0 = node_mbuf_priv1(mbuf0, dyn); + priv1 = node_mbuf_priv1(mbuf1, dyn); + priv2 = node_mbuf_priv1(mbuf2, dyn); + priv3 = node_mbuf_priv1(mbuf3, dyn); + + /* If feature is enabled, override next edge for each mbuf + * and set node_mbuf_priv data appropriately + */ + check_output_feature_x4(out_feature_arc, flist, + &pvar, priv0, priv1, priv2, priv3); + + /* check_output_feature_x4() returns bit mask which indicates + * which packet is not following feature path, hence normal processing + * has to happen on them + */ + if (unlikely(pvar.actual_feat_mask)) { + if (pvar.actual_feat_mask & 0x1) { + priv01.u32[1] += rte_cpu_to_be_16(0x0100); + /* Update ttl,cksum rewrite ethernet hdr on mbuf0 */ + d0 = rte_pktmbuf_mtod(mbuf0, void *); + rte_memcpy(d0, nh[priv01.u16[0]].rewrite_data, + nh[priv01.u16[0]].rewrite_len); + ip0 = (struct rte_ipv4_hdr *)((uint8_t *)d0 + + sizeof(struct rte_ether_hdr)); + ip0->time_to_live = priv01.u16[1] - 1; + ip0->hdr_checksum = priv01.u16[2] + priv01.u16[3]; + } + if (pvar.actual_feat_mask & 0x2) { + priv01.u32[3] += rte_cpu_to_be_16(0x0100); + /* Update ttl,cksum rewrite ethernet hdr on mbuf1 */ + d1 = rte_pktmbuf_mtod(mbuf1, void *); + rte_memcpy(d1, nh[priv01.u16[4]].rewrite_data, + nh[priv01.u16[4]].rewrite_len); + + ip1 = (struct rte_ipv4_hdr *)((uint8_t *)d1 + + sizeof(struct rte_ether_hdr)); + ip1->time_to_live = priv01.u16[5] - 1; + ip1->hdr_checksum = priv01.u16[6] + priv01.u16[7]; + } + if (pvar.actual_feat_mask & 0x4) { + priv23.u32[1] += rte_cpu_to_be_16(0x0100); + /* Update ttl,cksum rewrite ethernet hdr on mbuf2 */ + d2 = rte_pktmbuf_mtod(mbuf2, void *); + rte_memcpy(d2, nh[priv23.u16[0]].rewrite_data, + nh[priv23.u16[0]].rewrite_len); + ip2 = (struct rte_ipv4_hdr *)((uint8_t *)d2 + + sizeof(struct rte_ether_hdr)); + ip2->time_to_live = priv23.u16[1] - 1; + ip2->hdr_checksum = priv23.u16[2] + priv23.u16[3]; + } + if (pvar.actual_feat_mask & 0x8) { + priv23.u32[3] += rte_cpu_to_be_16(0x0100); + /* Update ttl,cksum rewrite ethernet hdr on mbuf3 */ + d3 = rte_pktmbuf_mtod(mbuf3, void *); + rte_memcpy(d3, nh[priv23.u16[4]].rewrite_data, + nh[priv23.u16[4]].rewrite_len); + ip3 = (struct rte_ipv4_hdr *)((uint8_t *)d3 + + sizeof(struct rte_ether_hdr)); + ip3->time_to_live = priv23.u16[5] - 1; + ip3->hdr_checksum = priv23.u16[6] + priv23.u16[7]; + } + } + } else { + /* Case when no feature is enabled */ + + /* Increment checksum by one. */ + priv01.u32[1] += rte_cpu_to_be_16(0x0100); + priv01.u32[3] += rte_cpu_to_be_16(0x0100); + priv23.u32[1] += rte_cpu_to_be_16(0x0100); + priv23.u32[3] += rte_cpu_to_be_16(0x0100); + + /* Update ttl,cksum rewrite ethernet hdr on mbuf0 */ + d0 = rte_pktmbuf_mtod(mbuf0, void *); + rte_memcpy(d0, nh[priv01.u16[0]].rewrite_data, + nh[priv01.u16[0]].rewrite_len); + + ip0 = (struct rte_ipv4_hdr *)((uint8_t *)d0 + + sizeof(struct rte_ether_hdr)); + ip0->time_to_live = priv01.u16[1] - 1; + ip0->hdr_checksum = priv01.u16[2] + priv01.u16[3]; + + /* Update ttl,cksum rewrite ethernet hdr on mbuf1 */ + d1 = rte_pktmbuf_mtod(mbuf1, void *); + rte_memcpy(d1, nh[priv01.u16[4]].rewrite_data, + nh[priv01.u16[4]].rewrite_len); + + ip1 = (struct rte_ipv4_hdr *)((uint8_t *)d1 + + sizeof(struct rte_ether_hdr)); + ip1->time_to_live = priv01.u16[5] - 1; + ip1->hdr_checksum = priv01.u16[6] + priv01.u16[7]; + + /* Update ttl,cksum rewrite ethernet hdr on mbuf2 */ + d2 = rte_pktmbuf_mtod(mbuf2, void *); + rte_memcpy(d2, nh[priv23.u16[0]].rewrite_data, + nh[priv23.u16[0]].rewrite_len); + ip2 = (struct rte_ipv4_hdr *)((uint8_t *)d2 + + sizeof(struct rte_ether_hdr)); + ip2->time_to_live = priv23.u16[1] - 1; + ip2->hdr_checksum = priv23.u16[2] + priv23.u16[3]; + + /* Update ttl,cksum rewrite ethernet hdr on mbuf3 */ + d3 = rte_pktmbuf_mtod(mbuf3, void *); + rte_memcpy(d3, nh[priv23.u16[4]].rewrite_data, + nh[priv23.u16[4]].rewrite_len); + + ip3 = (struct rte_ipv4_hdr *)((uint8_t *)d3 + + sizeof(struct rte_ether_hdr)); + ip3->time_to_live = priv23.u16[5] - 1; + ip3->hdr_checksum = priv23.u16[6] + priv23.u16[7]; + } /* Enqueue four to next node */ - rte_edge_t fix_spec = - ((next_index == next0) && (next0 == next1) && - (next1 == next2) && (next2 == next3)); + fix_spec = next_index ^ pvar.next0; + fix_spec += next_index ^ pvar.next1; + fix_spec += next_index ^ pvar.next2; + fix_spec += next_index ^ pvar.next3; - if (unlikely(fix_spec == 0)) { + if (unlikely(fix_spec != 0)) { /* Copy things successfully speculated till now */ rte_memcpy(to_next, from, last_spec * sizeof(from[0])); from += last_spec; @@ -146,56 +362,56 @@ ip4_rewrite_node_process(struct rte_graph *graph, struct rte_node *node, last_spec = 0; /* next0 */ - if (next_index == next0) { + if (next_index == pvar.next0) { to_next[0] = from[0]; to_next++; held++; } else { - rte_node_enqueue_x1(graph, node, next0, + rte_node_enqueue_x1(graph, node, pvar.next0, from[0]); } /* next1 */ - if (next_index == next1) { + if (next_index == pvar.next1) { to_next[0] = from[1]; to_next++; held++; } else { - rte_node_enqueue_x1(graph, node, next1, + rte_node_enqueue_x1(graph, node, pvar.next1, from[1]); } /* next2 */ - if (next_index == next2) { + if (next_index == pvar.next2) { to_next[0] = from[2]; to_next++; held++; } else { - rte_node_enqueue_x1(graph, node, next2, + rte_node_enqueue_x1(graph, node, pvar.next2, from[2]); } /* next3 */ - if (next_index == next3) { + if (next_index == pvar.next3) { to_next[0] = from[3]; to_next++; held++; } else { - rte_node_enqueue_x1(graph, node, next3, + rte_node_enqueue_x1(graph, node, pvar.next3, from[3]); } from += 4; /* Change speculation if last two are same */ - if ((next_index != next3) && (next2 == next3)) { + if ((next_index != pvar.next3) && (pvar.next2 == pvar.next3)) { /* Put the current speculated node */ rte_node_next_stream_put(graph, node, next_index, held); held = 0; /* Get next speculated stream */ - next_index = next3; + next_index = pvar.next3; to_next = rte_node_next_stream_get( graph, node, next_index, nb_objs); } @@ -212,20 +428,41 @@ ip4_rewrite_node_process(struct rte_graph *graph, struct rte_node *node, pkts += 1; n_left_from -= 1; - d0 = rte_pktmbuf_mtod(mbuf0, void *); - rte_memcpy(d0, nh[node_mbuf_priv1(mbuf0, dyn)->nh].rewrite_data, - nh[node_mbuf_priv1(mbuf0, dyn)->nh].rewrite_len); - - next0 = nh[node_mbuf_priv1(mbuf0, dyn)->nh].tx_node; - ip0 = (struct rte_ipv4_hdr *)((uint8_t *)d0 + - sizeof(struct rte_ether_hdr)); - chksum = node_mbuf_priv1(mbuf0, dyn)->cksum + - rte_cpu_to_be_16(0x0100); - chksum += chksum >= 0xffff; - ip0->hdr_checksum = chksum; - ip0->time_to_live = node_mbuf_priv1(mbuf0, dyn)->ttl - 1; - - if (unlikely(next_index ^ next0)) { + pvar.next0 = nh[node_mbuf_priv1(mbuf0, dyn)->nh].tx_node; + if (check_enabled_features) { + priv0 = node_mbuf_priv1(mbuf0, dyn); + if (pvar.next0 != (pvar.last_tx_interface + 1)) { + priv0->if_index = pvar.next0 - 1; + rte_graph_feature_arc_feature_set(out_feature_arc, flist, + priv0->if_index, + &priv0->current_feature, + &pvar.next0); + pvar.last_tx_interface = priv0->if_index; + pvar.last_if_feature = priv0->current_feature; + } else { + /* current mbuf index is same as last_tx_interface */ + priv0->if_index = pvar.last_tx_interface; + priv0->current_feature = pvar.last_if_feature; + } + } + /* Do the needful if either feature arc is disabled OR + * Invalid feature is present + */ + if (!check_enabled_features || + (priv0->current_feature == RTE_GRAPH_FEATURE_INVALID)) { + d0 = rte_pktmbuf_mtod(mbuf0, void *); + rte_memcpy(d0, nh[node_mbuf_priv1(mbuf0, dyn)->nh].rewrite_data, + nh[node_mbuf_priv1(mbuf0, dyn)->nh].rewrite_len); + + ip0 = (struct rte_ipv4_hdr *)((uint8_t *)d0 + + sizeof(struct rte_ether_hdr)); + chksum = node_mbuf_priv1(mbuf0, dyn)->cksum + + rte_cpu_to_be_16(0x0100); + chksum += chksum >= 0xffff; + ip0->hdr_checksum = chksum; + ip0->time_to_live = node_mbuf_priv1(mbuf0, dyn)->ttl - 1; + } + if (unlikely(next_index ^ pvar.next0)) { /* Copy things successfully speculated till now */ rte_memcpy(to_next, from, last_spec * sizeof(from[0])); from += last_spec; @@ -233,13 +470,15 @@ ip4_rewrite_node_process(struct rte_graph *graph, struct rte_node *node, held += last_spec; last_spec = 0; - rte_node_enqueue_x1(graph, node, next0, from[0]); + rte_node_enqueue_x1(graph, node, pvar.next0, from[0]); from += 1; } else { last_spec += 1; } } + IP4_REWRITE_NODE_LAST_TX(node->ctx) = pvar.last_tx_interface; + /* !!! Home run !!! */ if (likely(last_spec == nb_objs)) { rte_node_next_stream_move(graph, node, next_index); @@ -255,22 +494,78 @@ ip4_rewrite_node_process(struct rte_graph *graph, struct rte_node *node, return nb_objs; } +static uint16_t +ip4_rewrite_feature_node_process(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + struct rte_graph_feature_arc *arc = + rte_graph_feature_arc_get(IP4_REWRITE_NODE_OUTPUT_FEATURE_ARC(node->ctx)); + const int dyn = IP4_REWRITE_NODE_PRIV1_OFF(node->ctx); + rte_graph_feature_rt_list_t flist; + + /* If any feature is enabled on this arc */ + if (unlikely(rte_graph_feature_arc_has_any_feature(arc, &flist))) { + if (flist) + return __ip4_rewrite_node_process(graph, node, objs, nb_objs, + dyn, + 1 /* check features */, arc, + (rte_graph_feature_rt_list_t)1); + else + return __ip4_rewrite_node_process(graph, node, objs, nb_objs, + dyn, + 1 /* check features */, arc, + (rte_graph_feature_rt_list_t)0); + } else { + return __ip4_rewrite_node_process(graph, node, objs, nb_objs, dyn, + 0/* don't check features*/, NULL, + 0/* don't care */); + } + return 0; +} + +static uint16_t +ip4_rewrite_node_process(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + const int dyn = IP4_REWRITE_NODE_PRIV1_OFF(node->ctx); + + return __ip4_rewrite_node_process(graph, node, objs, nb_objs, dyn, + 0/* don't check features*/, NULL, + 0/* don't care */); +} + static int ip4_rewrite_node_init(const struct rte_graph *graph, struct rte_node *node) { + rte_graph_feature_arc_t feature_arc = RTE_GRAPH_FEATURE_ARC_INITIALIZER; static bool init_once; RTE_SET_USED(graph); RTE_BUILD_BUG_ON(sizeof(struct ip4_rewrite_node_ctx) > RTE_NODE_CTX_SZ); + RTE_BUILD_BUG_ON(sizeof(struct ip4_rewrite_nh_header) != RTE_CACHE_LINE_MIN_SIZE); if (!init_once) { node_mbuf_priv1_dynfield_offset = rte_mbuf_dynfield_register( &node_mbuf_priv1_dynfield_desc); if (node_mbuf_priv1_dynfield_offset < 0) return -rte_errno; - init_once = true; + + /* Create ipv4-output feature arc, if not created + */ + if (rte_graph_feature_arc_lookup_by_name(RTE_IP4_OUTPUT_FEATURE_ARC_NAME, + NULL) < 0) { + if (rte_graph_feature_arc_create(RTE_IP4_OUTPUT_FEATURE_ARC_NAME, + RTE_GRAPH_FEATURE_MAX_PER_ARC, + RTE_MAX_ETHPORTS, + ip4_rewrite_node_get(), &feature_arc)) { + return -rte_errno; + } + init_once = true; + } } IP4_REWRITE_NODE_PRIV1_OFF(node->ctx) = node_mbuf_priv1_dynfield_offset; + IP4_REWRITE_NODE_OUTPUT_FEATURE_ARC(node->ctx) = feature_arc; + IP4_REWRITE_NODE_LAST_TX(node->ctx) = UINT16_MAX; node_dbg("ip4_rewrite", "Initialized ip4_rewrite node initialized"); @@ -329,6 +624,7 @@ rte_node_ip4_rewrite_add(uint16_t next_hop, uint8_t *rewrite_data, static struct rte_node_register ip4_rewrite_node = { .process = ip4_rewrite_node_process, + .feat_arc_proc = ip4_rewrite_feature_node_process, .name = "ip4_rewrite", /* Default edge i.e '0' is pkt drop */ .nb_edges = 1, diff --git a/lib/node/ip4_rewrite_priv.h b/lib/node/ip4_rewrite_priv.h index 5105ec1d29..52f39601bd 100644 --- a/lib/node/ip4_rewrite_priv.h +++ b/lib/node/ip4_rewrite_priv.h @@ -5,9 +5,11 @@ #define __INCLUDE_IP4_REWRITE_PRIV_H__ #include <rte_common.h> +#include <rte_graph_feature_arc.h> #define RTE_GRAPH_IP4_REWRITE_MAX_NH 64 -#define RTE_GRAPH_IP4_REWRITE_MAX_LEN 56 +#define RTE_GRAPH_IP4_REWRITE_MAX_LEN (sizeof(struct rte_ether_hdr) + \ + (2 * sizeof(struct rte_vlan_hdr))) /** * @internal @@ -15,11 +17,9 @@ * Ipv4 rewrite next hop header data structure. Used to store port specific * rewrite data. */ -struct ip4_rewrite_nh_header { - uint16_t rewrite_len; /**< Header rewrite length. */ +struct __rte_cache_aligned ip4_rewrite_nh_header { uint16_t tx_node; /**< Tx node next index identifier. */ - uint16_t enabled; /**< NH enable flag */ - uint16_t rsvd; + uint16_t rewrite_len; /**< Header rewrite length. */ union { struct { struct rte_ether_addr dst; @@ -30,8 +30,13 @@ struct ip4_rewrite_nh_header { uint8_t rewrite_data[RTE_GRAPH_IP4_REWRITE_MAX_LEN]; /**< Generic rewrite data */ }; + /* used in control path */ + uint8_t enabled; /**< NH enable flag */ }; +_Static_assert(sizeof(struct ip4_rewrite_nh_header) <= (size_t)RTE_CACHE_LINE_SIZE, + "ip4_rewrite_nh_header size must be less or equal to cache line"); + /** * @internal * diff --git a/lib/node/node_private.h b/lib/node/node_private.h index 1de7306792..25db04a9a6 100644 --- a/lib/node/node_private.h +++ b/lib/node/node_private.h @@ -12,6 +12,9 @@ #include <rte_mbuf.h> #include <rte_mbuf_dyn.h> +#include <rte_graph_worker_common.h> +#include <rte_graph_feature_arc_worker.h> + extern int rte_node_logtype; #define RTE_LOGTYPE_NODE rte_node_logtype @@ -29,15 +32,28 @@ extern int rte_node_logtype; */ struct node_mbuf_priv1 { union { - /* IP4/IP6 rewrite */ + /** + * IP4/IP6 rewrite + * only used to pass lookup data from + * ip4-lookup to ip4-rewrite + */ struct { uint16_t nh; uint16_t ttl; uint32_t cksum; }; - uint64_t u; }; + /** + * Feature arc data + */ + struct { + /** interface index */ + uint16_t if_index; + /** feature that current mbuf holds */ + rte_graph_feature_t current_feature; + uint8_t rsvd; + }; }; static const struct rte_mbuf_dynfield node_mbuf_priv1_dynfield_desc = { diff --git a/lib/node/rte_node_ip4_api.h b/lib/node/rte_node_ip4_api.h index 24f8ec843a..0de06f7fc7 100644 --- a/lib/node/rte_node_ip4_api.h +++ b/lib/node/rte_node_ip4_api.h @@ -23,6 +23,7 @@ extern "C" { #include <rte_compat.h> #include <rte_graph.h> +#include <rte_graph_feature_arc_worker.h> /** * IP4 lookup next nodes. @@ -67,6 +68,8 @@ struct rte_node_ip4_reassembly_cfg { /**< Node identifier to configure. */ }; +#define RTE_IP4_OUTPUT_FEATURE_ARC_NAME "ipv4-output" + /** * Add ipv4 route to lookup table. * -- 2.43.0 ^ permalink raw reply [flat|nested] 46+ messages in thread
* [RFC PATCH v2 4/5] test/graph_feature_arc: add functional tests 2024-10-08 13:30 ` [RFC PATCH v2 0/5] " Nitin Saxena ` (2 preceding siblings ...) 2024-10-08 13:30 ` [RFC PATCH v2 3/5] graph: add IPv4 output feature arc Nitin Saxena @ 2024-10-08 13:30 ` Nitin Saxena 2024-10-08 13:30 ` [RFC PATCH v2 5/5] docs: add programming guide for feature arc Nitin Saxena 2024-10-09 13:29 ` [PATCH v3 0/5] add feature arc in rte_graph Nitin Saxena 5 siblings, 0 replies; 46+ messages in thread From: Nitin Saxena @ 2024-10-08 13:30 UTC (permalink / raw) To: Jerin Jacob, Kiran Kumar K, Nithin Dabilpuram, Zhirun Yan Cc: dev, Nitin Saxena Added functional unit test case for verifying feature arc control plane and fast path APIs How to run: $ echo "graph_feature_arc_autotest" | ./bin/dpdk-test Signed-off-by: Nitin Saxena <nsaxena@marvell.com> --- app/test/meson.build | 1 + app/test/test_graph_feature_arc.c | 1415 +++++++++++++++++++++++++++++ 2 files changed, 1416 insertions(+) create mode 100644 app/test/test_graph_feature_arc.c diff --git a/app/test/meson.build b/app/test/meson.build index e29258e6ec..740fa1bfb4 100644 --- a/app/test/meson.build +++ b/app/test/meson.build @@ -90,6 +90,7 @@ source_file_deps = { 'test_func_reentrancy.c': ['hash', 'lpm'], 'test_graph.c': ['graph'], 'test_graph_perf.c': ['graph'], + 'test_graph_feature_arc.c': ['graph'], 'test_hash.c': ['net', 'hash'], 'test_hash_functions.c': ['hash'], 'test_hash_multiwriter.c': ['hash'], diff --git a/app/test/test_graph_feature_arc.c b/app/test/test_graph_feature_arc.c new file mode 100644 index 0000000000..e185fcd393 --- /dev/null +++ b/app/test/test_graph_feature_arc.c @@ -0,0 +1,1415 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(C) 2024 Marvell International Ltd. + */ + +#include "test.h" + +#include <assert.h> +#include <inttypes.h> +#include <signal.h> +#include <stdalign.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> + +#include <rte_errno.h> + +#ifndef RTE_EXEC_ENV_WINDOWS +#include <rte_graph.h> +#include <rte_graph_worker.h> +#include <rte_mbuf.h> +#include <rte_mbuf_dyn.h> +#include <rte_random.h> +#include <rte_graph_feature_arc.h> +#include <rte_graph_feature_arc_worker.h> + +#define MBUFF_SIZE 512 +#define TEST_ARC1_NAME "arc1" +#define TEST_ARC2_NAME "arc2" +#define MAX_INDEXES 10 +#define MAX_FEATURES 5 + +#define SOURCE1 "test_node_arc_source1" +#define INPUT_STATIC "test_node_arc_input_static" +#define OUTPUT_STATIC "test_node_arc_output_static" +#define PKT_FREE_STATIC "test_node_arc_pkt_free_static" +#define ARC1_FEATURE1 "test_node_arc1_feature1" +#define ARC1_FEATURE2 "test_node_arc1_feature2" +#define ARC2_FEATURE1 "test_node_arc2_feature1" +#define ARC2_FEATURE2 "test_node_arc2_feature2" +#define ARC2_FEATURE3 "test_node_arc2_feature3" +#define DUMMY1_STATIC "test_node_arc_dummy1_static" +#define DUMMY2_STATIC "test_node_arc_dummy2_static" + +/* (Node index, Node Name, feature user data base */ +#define FOREACH_TEST_NODE_ARC { \ + R(0, SOURCE1, 64) \ + R(1, INPUT_STATIC, 128) \ + R(2, OUTPUT_STATIC, 256) \ + R(3, PKT_FREE_STATIC, 512) \ + R(4, ARC1_FEATURE1, 1024) \ + R(5, ARC1_FEATURE2, 2048) \ + R(6, ARC2_FEATURE1, 4096) \ + R(7, ARC2_FEATURE2, 8192) \ + R(8, ARC2_FEATURE3, 16384) \ + R(9, DUMMY1_STATIC, 32768) \ + R(10, DUMMY2_STATIC, 65536) \ + } + +/** + * ARC1: Feature arc on ingress interface + * ARC2: Feature arc on egress interface + * XX_static: Static nodes + * XX_featureX: Feature X on arc + * + * -----> ARC1_FEATURE1 + * | | | + * | | v + * | | ARC1_FEATURE2 + * | | | + * | v v + * SOURCE1 ->-----> INPUT_STATIC --> OUTPUT_STATIC -----> PKT_FREE_STATIC + * | | | ^ ^ ^ + * | | | | | | + * | | --> ARC2_FEATURE1 | | + * | | ^ ^ | | + * | | | | | | + * | ----------c-> ARC2_FEATURE2 | + * | | ^ | + * | | | | + * ----------> ARC2_FEATURE3 ------- + */ +const char *node_names_feature_arc[] = { + SOURCE1, INPUT_STATIC, OUTPUT_STATIC, PKT_FREE_STATIC, + ARC1_FEATURE1, ARC1_FEATURE2, ARC2_FEATURE1, ARC2_FEATURE2, ARC2_FEATURE3, + DUMMY1_STATIC, DUMMY2_STATIC +}; + +#define MAX_NODES RTE_DIM(node_names_feature_arc) + +/* Function declaraions */ +static uint16_t +source1_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs); +static uint16_t +input_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs); +static uint16_t +input_fa_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs); +static uint16_t +output_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs); +static uint16_t +output_fa_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs); +static uint16_t +pkt_free_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs); +static uint16_t +pkt_free_fa_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs); +static uint16_t +dummy1_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs); +static uint16_t +dummy2_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs); +static uint16_t +arc1_feature1_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs); +static uint16_t +arc1_feature1_fa_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs); +static uint16_t +arc1_feature2_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs); +static uint16_t +arc1_feature2_fa_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs); +static uint16_t +arc2_feature1_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs); +static uint16_t +arc2_feature1_fa_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs); +static uint16_t +arc2_feature2_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs); +static uint16_t +arc2_feature2_fa_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs); +static uint16_t +arc2_feature3_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs); +static uint16_t +arc2_feature3_fa_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs); +static int +common_node_init(const struct rte_graph *graph, struct rte_node *node); + +typedef struct test_node_priv { + /* index fom 0 - MAX_NODES -1 */ + uint8_t node_index; + + /* feature */ + rte_graph_feature_t feature; + + /* rte_graph node id */ + uint32_t node_id; + + rte_graph_feature_arc_t arc; +} test_node_priv_t; + +typedef struct { + rte_graph_feature_t feature; + uint16_t egress_interface; + uint16_t ingress_interface; +} graph_dynfield_t; + +static int graph_dynfield_offset = -1; +static rte_graph_feature_arc_t arcs[RTE_GRAPH_FEATURE_ARC_MAX + 128]; +static struct rte_mbuf mbuf[MAX_NODES + 1][MBUFF_SIZE]; +static void *mbuf_p[MAX_NODES + 1][MBUFF_SIZE]; +static rte_graph_t graph_id = RTE_GRAPH_ID_INVALID; + +const char *node_patterns_feature_arc[] = { + "test_node_arc*" +}; + +static inline graph_dynfield_t * +graph_field(struct rte_mbuf *mbuf) +{ + return RTE_MBUF_DYNFIELD(mbuf, graph_dynfield_offset, graph_dynfield_t *); +} + +static int32_t +compute_unique_user_data(const char *parent, const char *child, uint32_t interface_index) +{ + uint32_t user_data = interface_index; + + RTE_SET_USED(parent); +#define R(idx, node, node_cookie) { \ + if (!strcmp(child, node)) { \ + user_data += node_cookie; \ + } \ + } + + FOREACH_TEST_NODE_ARC +#undef R + + return user_data; +} + +static int +get_edge(struct rte_node_register *parent_node, + struct rte_node_register *child_node, rte_edge_t *_edge) +{ + char **next_edges = NULL; + uint32_t count, i; + + count = rte_node_edge_get(parent_node->id, NULL); + + if (!count) + return -1; + + next_edges = malloc(count); + + if (!next_edges) + return -1; + + count = rte_node_edge_get(parent_node->id, next_edges); + for (i = 0; i < count; i++) { + if (strstr(child_node->name, next_edges[i])) { + if (_edge) + *_edge = (rte_edge_t)i; + + free(next_edges); + return 0; + } + } + free(next_edges); + + return -1; +} + +int +common_node_init(const struct rte_graph *graph, struct rte_node *node) +{ + test_node_priv_t *priv = (test_node_priv_t *)node->ctx; + + RTE_SET_USED(graph); + + priv->node_id = node->id; + priv->feature = RTE_GRAPH_FEATURE_INVALID; + priv->arc = RTE_GRAPH_FEATURE_ARC_INITIALIZER; + +#define R(idx, _name, user_data) { \ + if (!strcmp(node->name, _name)) { \ + priv->node_index = idx; \ + } \ + } + FOREACH_TEST_NODE_ARC +#undef R + + return 0; +} + +uint16_t +source1_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + RTE_SET_USED(graph); + RTE_SET_USED(node); + RTE_SET_USED(objs); + RTE_SET_USED(nb_objs); + return 0; +} + +static struct rte_node_register source1 = { + .name = SOURCE1, + .process = source1_fn, + .flags = RTE_NODE_SOURCE_F, + .nb_edges = 3, + .init = common_node_init, + .next_nodes = {INPUT_STATIC, DUMMY1_STATIC, DUMMY2_STATIC}, +}; +RTE_NODE_REGISTER(source1); + +uint16_t +input_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + RTE_SET_USED(graph); + RTE_SET_USED(node); + RTE_SET_USED(objs); + RTE_SET_USED(nb_objs); + return 0; +} + +uint16_t +input_fa_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + RTE_SET_USED(graph); + RTE_SET_USED(node); + RTE_SET_USED(objs); + RTE_SET_USED(nb_objs); + return 0; +} + +static struct rte_node_register input = { + .name = INPUT_STATIC, + .process = input_fn, + .feat_arc_proc = input_fa_fn, + .nb_edges = 2, + .init = common_node_init, + .next_nodes = {OUTPUT_STATIC, DUMMY1_STATIC}, +}; +RTE_NODE_REGISTER(input); + +uint16_t +output_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + RTE_SET_USED(graph); + RTE_SET_USED(node); + RTE_SET_USED(objs); + RTE_SET_USED(nb_objs); + return 0; +} + +uint16_t +output_fa_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + RTE_SET_USED(graph); + RTE_SET_USED(node); + RTE_SET_USED(objs); + RTE_SET_USED(nb_objs); + return 0; +} + +static struct rte_node_register output = { + .name = OUTPUT_STATIC, + .process = output_fn, + .feat_arc_proc = output_fa_fn, + .nb_edges = 3, + .init = common_node_init, + .next_nodes = {DUMMY1_STATIC, PKT_FREE_STATIC, DUMMY2_STATIC}, +}; +RTE_NODE_REGISTER(output); + +uint16_t +pkt_free_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + RTE_SET_USED(graph); + RTE_SET_USED(node); + RTE_SET_USED(objs); + RTE_SET_USED(nb_objs); + return 0; +} + +uint16_t +pkt_free_fa_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + RTE_SET_USED(graph); + RTE_SET_USED(node); + RTE_SET_USED(objs); + RTE_SET_USED(nb_objs); + return 0; +} + +static struct rte_node_register pkt_free = { + .name = PKT_FREE_STATIC, + .process = pkt_free_fn, + .feat_arc_proc = pkt_free_fa_fn, + .nb_edges = 1, + .init = common_node_init, + .next_nodes = {DUMMY1_STATIC}, +}; +RTE_NODE_REGISTER(pkt_free); + +uint16_t +dummy1_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + RTE_SET_USED(graph); + RTE_SET_USED(node); + RTE_SET_USED(objs); + RTE_SET_USED(nb_objs); + return 0; +} + +static struct rte_node_register dummy1 = { + .name = DUMMY1_STATIC, + .process = dummy1_fn, + .nb_edges = 0, + .init = common_node_init, +}; +RTE_NODE_REGISTER(dummy1); + +uint16_t +dummy2_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + RTE_SET_USED(graph); + RTE_SET_USED(node); + RTE_SET_USED(objs); + RTE_SET_USED(nb_objs); + return 0; +} + +static struct rte_node_register dummy2 = { + .name = DUMMY2_STATIC, + .process = dummy2_fn, + .nb_edges = 5, + .init = common_node_init, + .next_nodes = { ARC1_FEATURE1, ARC1_FEATURE2, ARC2_FEATURE1, + ARC2_FEATURE2, ARC2_FEATURE3}, +}; +RTE_NODE_REGISTER(dummy2); + +uint16_t +arc1_feature1_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + RTE_SET_USED(graph); + RTE_SET_USED(node); + RTE_SET_USED(objs); + RTE_SET_USED(nb_objs); + + return 0; +} + +uint16_t +arc1_feature1_fa_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + RTE_SET_USED(graph); + RTE_SET_USED(node); + RTE_SET_USED(objs); + RTE_SET_USED(nb_objs); + + return 0; +} + +static struct rte_node_register arc1_feature1 = { + .name = ARC1_FEATURE1, + .process = arc1_feature1_fn, + .feat_arc_proc = arc1_feature1_fa_fn, + .nb_edges = 0, + .init = common_node_init, +}; +RTE_NODE_REGISTER(arc1_feature1); + +uint16_t +arc1_feature2_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + RTE_SET_USED(graph); + RTE_SET_USED(node); + RTE_SET_USED(objs); + RTE_SET_USED(nb_objs); + + return 0; +} + +uint16_t +arc1_feature2_fa_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + RTE_SET_USED(graph); + RTE_SET_USED(node); + RTE_SET_USED(objs); + RTE_SET_USED(nb_objs); + + return 0; +} + +static struct rte_node_register arc1_feature2 = { + .name = ARC1_FEATURE2, + .process = arc1_feature2_fn, + .feat_arc_proc = arc1_feature2_fa_fn, + .nb_edges = 0, + .init = common_node_init, +}; +RTE_NODE_REGISTER(arc1_feature2); + +uint16_t +arc2_feature1_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + RTE_SET_USED(graph); + RTE_SET_USED(node); + RTE_SET_USED(objs); + RTE_SET_USED(nb_objs); + + return 0; +} + +uint16_t +arc2_feature1_fa_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + RTE_SET_USED(graph); + RTE_SET_USED(node); + RTE_SET_USED(objs); + RTE_SET_USED(nb_objs); + + return 0; +} + +static struct rte_node_register arc2_feature1 = { + .name = ARC2_FEATURE1, + .process = arc2_feature1_fn, + .feat_arc_proc = arc2_feature1_fa_fn, + .nb_edges = 0, + .init = common_node_init, +}; +RTE_NODE_REGISTER(arc2_feature1); + +uint16_t +arc2_feature2_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + RTE_SET_USED(graph); + RTE_SET_USED(node); + RTE_SET_USED(objs); + RTE_SET_USED(nb_objs); + + return 0; +} + +uint16_t +arc2_feature2_fa_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + RTE_SET_USED(graph); + RTE_SET_USED(node); + RTE_SET_USED(objs); + RTE_SET_USED(nb_objs); + + return 0; +} + +static struct rte_node_register arc2_feature2 = { + .name = ARC2_FEATURE2, + .process = arc2_feature2_fn, + .feat_arc_proc = arc2_feature2_fa_fn, + .nb_edges = 0, + .init = common_node_init, +}; +RTE_NODE_REGISTER(arc2_feature2); + +uint16_t +arc2_feature3_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + RTE_SET_USED(graph); + RTE_SET_USED(node); + RTE_SET_USED(objs); + RTE_SET_USED(nb_objs); + + return 0; +} + +uint16_t +arc2_feature3_fa_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + RTE_SET_USED(graph); + RTE_SET_USED(node); + RTE_SET_USED(objs); + RTE_SET_USED(nb_objs); + + return 0; +} + +static struct rte_node_register arc2_feature3 = { + .name = ARC2_FEATURE3, + .process = arc2_feature3_fn, + .feat_arc_proc = arc2_feature3_fa_fn, + .nb_edges = 0, + .init = common_node_init, +}; +RTE_NODE_REGISTER(arc2_feature3); + +static int +create_graph(void) +{ + struct rte_graph_param gconf = { + .socket_id = SOCKET_ID_ANY, + .nb_node_patterns = 1, + .node_patterns = node_patterns_feature_arc, + }; + + graph_id = rte_graph_create("worker0", &gconf); + if (graph_id == RTE_GRAPH_ID_INVALID) { + printf("Graph creation failed with error = %d\n", rte_errno); + return TEST_FAILED; + } + + return TEST_SUCCESS; +} + +static int +__test_create_feature_arc(rte_graph_feature_arc_t *arcs, int max_arcs) +{ + rte_graph_feature_arc_t arc; + const char *sample_arc_name = "sample_arc"; + char arc_name[256]; + int n_arcs; + + /* Create max number of feature arcs first */ + for (n_arcs = 0; n_arcs < max_arcs; n_arcs++) { + snprintf(arc_name, sizeof(arc_name), "%s-%u", sample_arc_name, n_arcs); + if (rte_graph_feature_arc_create(arc_name, MAX_FEATURES, + MAX_INDEXES, &dummy1, &arcs[n_arcs])) { + printf("Feature arc creation failed for %u\n", n_arcs); + return TEST_FAILED; + } + } + /* Verify feature arc created more than max_arcs must fail */ + if (!rte_graph_feature_arc_create("negative_test_create_arc", MAX_FEATURES, + MAX_INDEXES, &dummy2, &arc)) { + printf("Feature arc creation success for more than max configured: %u\n", n_arcs); + return TEST_FAILED; + } + /* Make sure lookup passes for all feature arcs */ + for (n_arcs = 0; n_arcs < max_arcs; n_arcs++) { + snprintf(arc_name, sizeof(arc_name), "%s-%u", sample_arc_name, n_arcs); + arc = RTE_GRAPH_FEATURE_ARC_INITIALIZER; + if (!rte_graph_feature_arc_lookup_by_name(arc_name, &arc)) { + if (arc != arcs[n_arcs]) { + printf("%s: Feature arc lookup mismatch for arc [%p, exp: %p]\n", + arc_name, (void *)arc, (void *)arcs[n_arcs]); + return TEST_FAILED; + } + } else { + printf("Feature arc lookup %s failed after creation\n", arc_name); + return TEST_FAILED; + } + } + return TEST_SUCCESS; +} + +static int +test_graph_feature_arc_create(void) +{ + int ret = 0, i; + + /* Create arcs with RTE_GRAPH_FEATURE_ARC_MAX */ + ret = __test_create_feature_arc(arcs, RTE_GRAPH_FEATURE_ARC_MAX); + if (ret) { + printf("Feature arc creation test failed for RTE_GRAPH_FEATURE_ARC_MAX arcs\n"); + return TEST_FAILED; + } + /* destroy all arcs via cleanup API*/ + ret = rte_graph_feature_arc_cleanup(); + if (ret) { + printf("Feature arc cleanup failed\n"); + return TEST_FAILED; + } + +#define NUM_FEAT_ARCS 128 + /* create 128 dummy feature arcs */ + ret = rte_graph_feature_arc_init(NUM_FEAT_ARCS); + if (ret) { + printf("Feature arc init failed for NUM_FEAT_ARCS"); + return TEST_FAILED; + } + ret = __test_create_feature_arc(arcs, NUM_FEAT_ARCS); + if (ret) { + printf("Feature arc creation test failed for NUM_FEAT_ARCS\n"); + return TEST_FAILED; + } + /* destroy all of them*/ + for (i = 0; i < NUM_FEAT_ARCS; i++) { + if (rte_graph_feature_arc_destroy(arcs[i])) { + printf("Feature arc destroy failed for %u\n", i); + return TEST_FAILED; + } + } + rte_graph_feature_arc_cleanup(); + + /* Create two arcs as per test plan */ + /* First arc start/source node is node: SOURCE1 */ + if (rte_graph_feature_arc_create(TEST_ARC1_NAME, MAX_FEATURES, + MAX_INDEXES, &source1, &arcs[0])) { + printf("Feature arc creation failed for %s\n", TEST_ARC1_NAME); + return TEST_FAILED; + } + + /* Duplicate name should fail */ + if (!rte_graph_feature_arc_create(TEST_ARC1_NAME, MAX_FEATURES, + MAX_INDEXES, &source1, &arcs[1])) { + printf("Duplicate feature arc %s creation is not caught\n", TEST_ARC1_NAME); + return TEST_FAILED; + } + /* Second arc start/source node is node: OUTPUT_STATIC */ + if (rte_graph_feature_arc_create(TEST_ARC2_NAME, MAX_FEATURES, + MAX_INDEXES, &output, &arcs[1])) { + printf("Feature arc creation failed for %s\n", TEST_ARC1_NAME); + return TEST_FAILED; + } + return TEST_SUCCESS; +} + +static int +test_graph_feature_arc_features_add(void) +{ + rte_graph_feature_t temp; + + /* First feature to SOURCE1 start node -> ARC1_FEATURE1 */ + if (rte_graph_feature_add(arcs[0], &arc1_feature1, NULL, NULL)) { + printf("%s: Feature add failed for adding feature %s\n", + TEST_ARC1_NAME, ARC1_FEATURE1); + return TEST_FAILED; + } + /* Second feature to SOURCE1 -> ARC1_FEATURE2 */ + if (rte_graph_feature_add(arcs[0], &arc1_feature2, NULL, NULL)) { + printf("%s: Feature add failed for adding feature %s\n", + TEST_ARC1_NAME, ARC1_FEATURE2); + return TEST_FAILED; + } + /* adding statically connected INPUT_STATIC as a last feature */ + if (rte_graph_feature_add(arcs[0], &input, ARC1_FEATURE2, NULL)) { + printf("%s: Feature add failed for adding feature %s after %s\n", + TEST_ARC1_NAME, INPUT_STATIC, ARC1_FEATURE2); + return TEST_FAILED; + } + /* First feature to OUTPUT_STATIC start node -> ARC2_FEATURE3 */ + if (rte_graph_feature_add(arcs[1], &arc2_feature3, NULL, NULL)) { + printf("%s: Feature add failed for adding feature %s\n", + TEST_ARC2_NAME, ARC2_FEATURE3); + return TEST_FAILED; + } + /* Second feature to OUTPUT_STATIC -> ARC2_FEATURE1 and before feature to + * ARC2_FEATURE3 + */ + if (rte_graph_feature_add(arcs[1], &arc2_feature1, NULL, ARC2_FEATURE3)) { + printf("%s: Feature add failed for adding feature %s after %s\n", + TEST_ARC2_NAME, ARC2_FEATURE3, ARC2_FEATURE1); + return TEST_FAILED; + } + /* Add PKT_FREE node as last feature, next to arc2_feature3 */ + if (rte_graph_feature_add(arcs[1], &pkt_free, ARC2_FEATURE3, NULL)) { + printf("%s: Feature add failed for adding feature %s after %s\n", + TEST_ARC2_NAME, PKT_FREE_STATIC, ARC2_FEATURE3); + return TEST_FAILED; + } + /* Adding feature ARC2_FEATURE2 between ARC2_FEATURE1 and ARC2_FEATURE3. */ + if (rte_graph_feature_add(arcs[1], &arc2_feature2, ARC2_FEATURE1, ARC2_FEATURE3)) { + printf("%s: Feature add failed for adding feature %s between [%s - %s]\n", + TEST_ARC2_NAME, ARC2_FEATURE2, ARC2_FEATURE1, ARC2_FEATURE3); + return TEST_FAILED; + } + /* Now check feature sequencing is correct for both ARCS */ + + /* arc1_featur1 must be first feature to arcs[0] */ + if (!strstr(ARC1_FEATURE1, + rte_graph_feature_arc_feature_to_name(arcs[0], + rte_graph_feature_cast(0)))) { + printf("%s: %s is not the first feature instead %s\n", + TEST_ARC1_NAME, ARC1_FEATURE1, + rte_graph_feature_arc_feature_to_name(arcs[0], rte_graph_feature_cast(0))); + return TEST_FAILED; + } + + /* arc1_feature2 must be second feature to arcs[0] */ + if (!strstr(ARC1_FEATURE2, + rte_graph_feature_arc_feature_to_name(arcs[0], + rte_graph_feature_cast(1)))) { + printf("%s: %s is not the second feature instead %s\n", + TEST_ARC1_NAME, ARC1_FEATURE2, + rte_graph_feature_arc_feature_to_name(arcs[0], rte_graph_feature_cast(1))); + return TEST_FAILED; + } + + /* Make sure INPUT_STATIC is the last feature in arcs[0] */ + temp = rte_graph_feature_arc_num_features(arcs[0]); + if (!strstr(INPUT_STATIC, + rte_graph_feature_arc_feature_to_name(arcs[0], + temp - rte_graph_feature_cast(1)))) { + printf("%s: %s is not the last feature instead %s\n", + TEST_ARC1_NAME, INPUT_STATIC, + rte_graph_feature_arc_feature_to_name(arcs[0], + temp - rte_graph_feature_cast(1))); + return TEST_FAILED; + } + + /* arc2_featur1 must be first feature to arcs[1] */ + if (!strstr(ARC2_FEATURE1, + rte_graph_feature_arc_feature_to_name(arcs[1], + rte_graph_feature_cast(0)))) { + printf("%s: %s is not the first feature instead %s\n", + TEST_ARC2_NAME, ARC2_FEATURE1, + rte_graph_feature_arc_feature_to_name(arcs[1], rte_graph_feature_cast(0))); + return TEST_FAILED; + } + + /* arc2_feature2 must be second feature to arcs[1] */ + if (!strstr(ARC2_FEATURE2, + rte_graph_feature_arc_feature_to_name(arcs[1], + rte_graph_feature_cast(1)))) { + printf("%s: %s is not the second feature instead %s\n", + TEST_ARC2_NAME, ARC2_FEATURE2, + rte_graph_feature_arc_feature_to_name(arcs[1], rte_graph_feature_cast(1))); + return TEST_FAILED; + } + + /* arc2_feature3 must be third feature to arcs[1] */ + if (!strstr(ARC2_FEATURE3, + rte_graph_feature_arc_feature_to_name(arcs[1], + rte_graph_feature_cast(2)))) { + printf("%s: %s is not the third feature instead %s\n", + TEST_ARC2_NAME, ARC2_FEATURE3, + rte_graph_feature_arc_feature_to_name(arcs[1], rte_graph_feature_cast(2))); + return TEST_FAILED; + } + + /* Make sure PKT_FREE is the last feature in arcs[1] */ + temp = rte_graph_feature_arc_num_features(arcs[1]); + if (!strstr(PKT_FREE_STATIC, + rte_graph_feature_arc_feature_to_name(arcs[1], + temp - rte_graph_feature_cast(1)))) { + printf("%s: %s is not the last feature instead %s\n", + TEST_ARC2_NAME, PKT_FREE_STATIC, + rte_graph_feature_arc_feature_to_name(arcs[1], + temp - rte_graph_feature_cast(1))); + return TEST_FAILED; + } + + if (get_edge(&arc2_feature1, &pkt_free, NULL)) { + printf("%s: Edge not found between %s and %s\n", + TEST_ARC2_NAME, ARC2_FEATURE1, PKT_FREE_STATIC); + return TEST_FAILED; + } + + return create_graph(); +} + +static int +test_graph_feature_arc_first_feature_enable(void) +{ + uint32_t n_indexes, n_features, count = 0; + rte_graph_feature_rt_list_t feature_list, temp = 0; + struct rte_node_register *parent, *child; + rte_graph_feature_data_t *fdata = NULL; + struct rte_graph_feature_arc *arc; + rte_graph_feature_t feature; + char *feature_name = NULL; + int32_t user_data; + rte_edge_t edge = ~0; + + arc = rte_graph_feature_arc_get(arcs[0]); + + if (rte_graph_feature_arc_has_any_feature(arc, &feature_list)) { + printf("%s: Feature arc should not have any feature enabled by now\n", + TEST_ARC1_NAME); + return TEST_FAILED; + } + + if (rte_graph_feature_arc_num_enabled_features(arcs[0])) { + printf("%s: Feature arc should not have any_feature() enabled by now\n", + TEST_ARC1_NAME); + return TEST_FAILED; + } + /* + * On interface 0, enable feature 0, + * On interface 1, enable feature 1 and so on so forth + * + * later verify first feature on every interface index is unique + * and check [rte_edge, user_data] retrieved via fast path APIs + */ + for (n_indexes = 0; n_indexes < MAX_INDEXES; n_indexes++) { + n_features = n_indexes % 3 /* 3 features added to arc1 */; + feature_name = rte_graph_feature_arc_feature_to_name(arcs[0], n_features); + user_data = compute_unique_user_data(arc->start_node->name, feature_name, + n_indexes); + if (rte_graph_feature_validate(arcs[0], n_indexes, feature_name, 1, true)) { + printf("%s: Feature validate failed for %s on index %u\n", + TEST_ARC1_NAME, feature_name, n_indexes); + return TEST_FAILED; + } + /* negative test case. enable feature on invalid index */ + if (!n_indexes && !rte_graph_feature_enable(arcs[0], MAX_INDEXES, feature_name, + (int32_t)user_data)) { + printf("%s: Feature %s should not be enabled on invalid index\n", + TEST_ARC1_NAME, feature_name); + return TEST_FAILED; + } + if (rte_graph_feature_enable(arcs[0], n_indexes, feature_name, + (int32_t)user_data)) { + printf("%s: Feature enable failed for %s on index %u\n", + TEST_ARC1_NAME, feature_name, n_indexes); + return TEST_FAILED; + } + /* has any feature should be valid */ + if (!rte_graph_feature_arc_has_any_feature(arc, &feature_list)) { + printf("%s: Feature arc should have any_feature enabled by now\n", + TEST_ARC1_NAME); + return TEST_FAILED; + } + if (temp == feature_list) { + printf("%s: Activer feature list not switched from %u -> %u\n", + TEST_ARC1_NAME, temp, feature_list); + return TEST_FAILED; + } + temp = feature_list; + if ((count + 1) != rte_graph_feature_arc_num_enabled_features(arcs[0])) { + printf("%s: Number of enabled mismatches [found: %u, exp: %u]\n", + TEST_ARC1_NAME, + rte_graph_feature_arc_num_enabled_features(arcs[0]), + count + 1); + return TEST_FAILED; + } + count++; + } + if (!rte_graph_feature_arc_has_any_feature(arc, &feature_list)) { + printf("%s: Feature arc should have any_feature enabled by now\n", + TEST_ARC1_NAME); + return TEST_FAILED; + } + /* Negative test case */ + user_data = compute_unique_user_data(arc->start_node->name, ARC2_FEATURE1, 1); + if (!rte_graph_feature_enable(arcs[0], 1 /* index */, ARC2_FEATURE1, user_data)) { + printf("%s: Invalid feature %s is enabled on index 1\n", + TEST_ARC1_NAME, ARC2_FEATURE1); + return TEST_FAILED; + } + /* Duplicate enable */ + if (!rte_graph_feature_enable(arcs[0], 1 /* index */, ARC1_FEATURE2, user_data)) { + printf("%s: Duplicate feature %s shouldn't be enabled again on index 1\n", + TEST_ARC1_NAME, ARC1_FEATURE2); + return TEST_FAILED; + } + for (n_indexes = 0; n_indexes < MAX_INDEXES; n_indexes++) { + if (!rte_graph_feature_arc_first_feature_get(arc, feature_list, n_indexes, + &feature)) { + printf("%s: No first feature enabled on index: %u\n", + TEST_ARC1_NAME, n_indexes); + return TEST_FAILED; + } + /* Get first feature data and ensure edge and user_data are correct */ + fdata = rte_graph_feature_data_get(arc, rte_graph_feature_get(arc, feature), + n_indexes); + parent = arc->start_node; + if (0 == (n_indexes % 3)) + child = &arc1_feature1; + else if (1 == (n_indexes % 3)) + child = &arc1_feature2; + else + child = &input; + + if (get_edge(parent, child, &edge)) { + printf("%s: Edge not found between %s and %s\n", + TEST_ARC1_NAME, parent->name, child->name); + return TEST_FAILED; + } + if (fdata->next_edge != edge) { + printf("%s: Edge mismatch for first feature on index %u [%u, exp: %u]\n", + TEST_ARC1_NAME, n_indexes, fdata->next_edge, edge); + return TEST_FAILED; + } + if (fdata->user_data != compute_unique_user_data(parent->name, child->name, + n_indexes)) { + printf("%s: First feature user data mismatch on index %u [%u, exp: %u]\n", + TEST_ARC1_NAME, n_indexes, fdata->user_data, + compute_unique_user_data(parent->name, child->name, n_indexes)); + return TEST_FAILED; + } + } + return TEST_SUCCESS; +} + +static int +verify_feature_sequencing(struct rte_graph_feature_arc *arc) +{ + rte_graph_feature_rt_list_t feature_list; + struct rte_node_register *parent, *child; + rte_graph_feature_data_t *fdata = NULL; + rte_graph_feature_t feature; + uint32_t n_indexes; + rte_edge_t edge = ~0; + int32_t user_data; + + if (!rte_graph_feature_arc_has_any_feature(arc, &feature_list)) { + printf("%s: feature_list can't be obtained\n", + arc->feature_arc_name); + return TEST_FAILED; + } + /* Verify next features on interface 0 and interface 1*/ + for (n_indexes = 0; n_indexes < 2; n_indexes++) { + if (!rte_graph_feature_arc_first_feature_get(arc, feature_list, n_indexes, + &feature)) { + printf("%s: No first feature enabled on index: 0\n", + arc->feature_arc_name); + return TEST_FAILED; + } + parent = arc->start_node; + child = rte_graph_feature_arc_feature_to_node(arcs[1], feature); + /* until fast path API reaches last feature i.e pkt_free */ + while (child != &pkt_free) { + fdata = rte_graph_feature_data_get(arc, + rte_graph_feature_get(arc, feature), + n_indexes); + + if (get_edge(parent, child, &edge)) { + printf("%s: Edge not found between %s and %s\n", + arc->feature_arc_name, parent->name, child->name); + return TEST_FAILED; + } + user_data = compute_unique_user_data(parent->name, child->name, n_indexes); + if (fdata->next_edge != edge) { + printf("%s: Edge mismatch for %s->%s on index %u [%u, exp: %u]\n", + arc->feature_arc_name, parent->name, child->name, n_indexes, + fdata->next_edge, edge); + return TEST_FAILED; + } + if (fdata->user_data != user_data) { + printf("%s: Udata mismatch for %s->%s on index %u [%u, exp: %u]\n", + arc->feature_arc_name, parent->name, child->name, n_indexes, + fdata->user_data, user_data); + return TEST_FAILED; + } + + feature = fdata->next_enabled_feature; + + parent = child; + child = rte_graph_feature_arc_feature_to_node(arcs[1], + fdata->next_enabled_feature); + } + } + return TEST_SUCCESS; +} + +static int +test_graph_feature_arc_next_feature_enable(void) +{ + rte_graph_feature_rt_list_t feature_list; + struct rte_node_register *parent, *child; + rte_graph_feature_data_t *fdata = NULL; + struct rte_graph_feature_arc *arc; + uint32_t n_indexes, n_features; + rte_graph_feature_t feature; + char *feature_name = NULL; + rte_edge_t edge = ~0; + int32_t user_data; + + arc = rte_graph_feature_arc_get(arcs[1]); + + if (rte_graph_feature_arc_has_any_feature(arc, &feature_list)) { + printf("%s: Feature arc should not have any feature enabled by now\n", + TEST_ARC2_NAME); + return TEST_FAILED; + } + + if (rte_graph_feature_arc_num_enabled_features(arcs[1])) { + printf("%s: Feature arc should not have any_feature() enabled by now\n", + TEST_ARC2_NAME); + return TEST_FAILED; + } + /* + * On interface 0, enable feature 2, skip feature 1 for later + * On interface 1, enable feature 3 + * On interface 2, enable pkt_free feature + * On interface 3, continue as interface 0 + * + * later enable next feature sequence for interface 0 from feature2 -> pkt_free + * later enable next feature sequence for interface 1 from feature3 -> pkt_free + * + * also later enable feature-1 and see first feature changes for all indexes + */ + for (n_indexes = 0; n_indexes < MAX_INDEXES; n_indexes++) { + n_features = (n_indexes % 3) + 1; /* feature2 to pkt_free are 3 features */ + feature_name = rte_graph_feature_arc_feature_to_name(arcs[1], n_features); + user_data = compute_unique_user_data(arc->start_node->name, feature_name, + n_indexes); + if (rte_graph_feature_enable(arcs[1], n_indexes, feature_name, + (int32_t)user_data)) { + printf("%s: Feature enable failed for %s on index %u\n", + TEST_ARC2_NAME, feature_name, n_indexes); + return TEST_FAILED; + } + /* has any feature should be valid */ + if (!rte_graph_feature_arc_has_any_feature(arc, &feature_list)) { + printf("%s: Feature arc should have any_feature enabled by now\n", + TEST_ARC2_NAME); + return TEST_FAILED; + } + } + /* Retrieve latest feature_list */ + rte_graph_feature_arc_has_any_feature(arc, &feature_list); + /* verify first feature */ + for (n_indexes = 0; n_indexes < MAX_INDEXES; n_indexes++) { + if (!rte_graph_feature_arc_first_feature_get(arc, feature_list, n_indexes, + &feature)) { + printf("%s: No first feature enabled on index: %u\n", + TEST_ARC2_NAME, n_indexes); + return TEST_FAILED; + } + /* Get first feature data and ensure edge and user_data are correct */ + fdata = rte_graph_feature_data_get(arc, rte_graph_feature_get(arc, feature), + n_indexes); + parent = arc->start_node; + if (0 == (n_indexes % 3)) + child = &arc2_feature2; + else if (1 == (n_indexes % 3)) + child = &arc2_feature3; + else + child = &pkt_free; + + if (get_edge(parent, child, &edge)) { + printf("%s: Edge not found between %s and %s\n", + TEST_ARC2_NAME, parent->name, child->name); + return TEST_FAILED; + } + if (fdata->next_edge != edge) { + printf("%s: Edge mismatch for first feature on index %u [%u, exp: %u]\n", + TEST_ARC2_NAME, n_indexes, fdata->next_edge, edge); + return TEST_FAILED; + } + if (fdata->user_data != compute_unique_user_data(parent->name, child->name, + n_indexes)) { + printf("%s: First feature user data mismatch on index %u [%u, exp: %u]\n", + TEST_ARC2_NAME, n_indexes, fdata->user_data, + compute_unique_user_data(parent->name, child->name, n_indexes)); + return TEST_FAILED; + } + } + /* add next_features now + * On interface 0, enable feature-3 and pkt_free + * On interface 1, enable pkt_free + * Skip interface 2 + * On interface 3, same as interface 0 + * On interface 4, same as interface 1 + */ + for (n_indexes = 0; n_indexes < MAX_INDEXES; n_indexes++) { + if (0 == (n_indexes % 3)) { + if (rte_graph_feature_enable(arcs[1], n_indexes, ARC2_FEATURE3, + compute_unique_user_data(ARC2_FEATURE2, + ARC2_FEATURE3, + n_indexes))) { + printf("%s: Feature enable failed for %s -> (%s) on index %u\n", + TEST_ARC2_NAME, ARC2_FEATURE2, ARC2_FEATURE3, n_indexes); + return TEST_FAILED; + } + } + /* pkt_free on interface-0, 1, 3, 4 and so on */ + if ((0 == (n_indexes % 3)) || (1 == (n_indexes % 3))) { + if (rte_graph_feature_enable(arcs[1], n_indexes, PKT_FREE_STATIC, + compute_unique_user_data(ARC2_FEATURE3, + PKT_FREE_STATIC, + n_indexes))) { + printf("%s: Feature enable failed %s -> (%s) on index %u\n", + TEST_ARC2_NAME, ARC2_FEATURE3, PKT_FREE_STATIC, n_indexes); + return TEST_FAILED; + } + } + } + + if (verify_feature_sequencing(arc) == TEST_FAILED) + return TEST_FAILED; + + /* Enable feature-1 on all interfaces and check first feature changes */ + for (n_indexes = 0; n_indexes < MAX_INDEXES; n_indexes++) { + user_data = compute_unique_user_data(arc->start_node->name, ARC2_FEATURE1, + n_indexes); + if (rte_graph_feature_enable(arcs[1], n_indexes, ARC2_FEATURE1, + (int32_t)user_data)) { + printf("%s: Feature enable failed for %s on index %u\n", + TEST_ARC2_NAME, feature_name, n_indexes); + return TEST_FAILED; + } + } + rte_graph_feature_arc_has_any_feature(arc, &feature_list); + for (n_indexes = 0; n_indexes < MAX_INDEXES; n_indexes++) { + if (!rte_graph_feature_arc_first_feature_get(arc, feature_list, n_indexes, + &feature)) { + printf("%s: None first feature enabled on index: %u\n", + TEST_ARC2_NAME, n_indexes); + return TEST_FAILED; + } + if (feature != rte_graph_feature_cast(0)) { + printf("%s: First feature mismatch on index %u [%u, exp: %u]\n", + TEST_ARC2_NAME, n_indexes, feature, rte_graph_feature_cast(0)); + return TEST_FAILED; + } + } + if (verify_feature_sequencing(arc) == TEST_FAILED) + return TEST_FAILED; + + return TEST_SUCCESS; +} + +static int +test_graph_feature_arc_first_feature_disable(void) +{ + rte_graph_feature_rt_list_t feature_list; + struct rte_graph_feature_arc *arc; + rte_graph_feature_t feature; + uint32_t n_indexes; + + arc = rte_graph_feature_arc_get(arcs[1]); + + /* Disable feature-1 on all interfaces and check first feature changes */ + for (n_indexes = 0; n_indexes < MAX_INDEXES; n_indexes++) { + if (rte_graph_feature_disable(arcs[1], n_indexes, ARC2_FEATURE1)) { + printf("%s: Feature disable failed for %s on index %u\n", + TEST_ARC2_NAME, ARC2_FEATURE1, n_indexes); + return TEST_FAILED; + } + } + rte_graph_feature_arc_has_any_feature(arc, &feature_list); + for (n_indexes = 0; n_indexes < MAX_INDEXES; n_indexes++) { + if (!rte_graph_feature_arc_first_feature_get(arc, feature_list, n_indexes, + &feature)) { + printf("%s: First feature get failed on index: %u\n", + TEST_ARC2_NAME, n_indexes); + return TEST_FAILED; + } + if (feature == rte_graph_feature_cast(0)) { + printf("%s: First feature not disabled on index %u [%u, exp: %u]\n", + TEST_ARC2_NAME, n_indexes, feature, rte_graph_feature_cast(1)); + return TEST_FAILED; + } + if (!strncmp(ARC2_FEATURE1, + rte_graph_feature_arc_feature_to_name(arcs[1], feature), + strlen(ARC2_FEATURE1))) { + printf("%s: First feature mismatch on index %u [%s, exp: %s]\n", + TEST_ARC2_NAME, n_indexes, + rte_graph_feature_arc_feature_to_name(arcs[1], feature), + ARC2_FEATURE2); + return TEST_FAILED; + } + } + if (verify_feature_sequencing(arc) == TEST_FAILED) + return TEST_FAILED; + + return TEST_SUCCESS; +} + +static int +test_graph_feature_arc_next_feature_disable(void) +{ + rte_graph_feature_rt_list_t feature_list; + struct rte_graph_feature_arc *arc; + rte_graph_feature_t feature; + uint32_t n_indexes; + + arc = rte_graph_feature_arc_get(arcs[1]); + + /* + * On interface 0, disable feature 2, keep feature3 and pkt_free enabled + * On interface 1, skip interface 1 where feature3 and pkt_free are enabled + * skip interface 2 as only pkt_free is enabled + */ + for (n_indexes = 0; n_indexes < MAX_INDEXES; n_indexes++) { + if (!(n_indexes % 3)) { + if (rte_graph_feature_disable(arcs[1], n_indexes, ARC2_FEATURE2)) { + printf("%s: Feature disable failed for %s on index %u\n", + TEST_ARC2_NAME, ARC2_FEATURE2, n_indexes); + return TEST_FAILED; + } + } + + if (verify_feature_sequencing(arc) == TEST_FAILED) + return TEST_FAILED; + } + + /** + * Disable feature 3 on all interface 0 and 1 and check first feature + * is pkt_free on all indexes + */ + for (n_indexes = 0; n_indexes < MAX_INDEXES; n_indexes++) { + if ((0 == (n_indexes % 3)) || (1 == (n_indexes % 3))) { + if (rte_graph_feature_disable(arcs[1], n_indexes, ARC2_FEATURE3)) { + printf("%s: Feature disable failed for %s on index %u\n", + TEST_ARC2_NAME, ARC2_FEATURE3, n_indexes); + return TEST_FAILED; + } + } + } + /* Make sure pkt_free is first feature for all indexes */ + rte_graph_feature_arc_has_any_feature(arc, &feature_list); + for (n_indexes = 0; n_indexes < MAX_INDEXES; n_indexes++) { + if (!rte_graph_feature_arc_first_feature_get(arc, feature_list, n_indexes, + &feature)) { + printf("%s: First feature get failed on index: %u\n", + TEST_ARC2_NAME, n_indexes); + return TEST_FAILED; + } + if (strncmp(PKT_FREE_STATIC, + rte_graph_feature_arc_feature_to_name(arcs[1], feature), + strlen(PKT_FREE_STATIC))) { + printf("%s: %s is not first feature found on index %u [%s, exp: %s]\n", + TEST_ARC2_NAME, PKT_FREE_STATIC, n_indexes, + rte_graph_feature_arc_feature_to_name(arcs[1], feature), + PKT_FREE_STATIC); + return TEST_FAILED; + } + } + + /* Disable PKT_FREE_STATIC from all indexes with no feature enabled on any interface */ + for (n_indexes = 0; n_indexes < MAX_INDEXES; n_indexes++) { + if (rte_graph_feature_disable(arcs[1], n_indexes, PKT_FREE_STATIC)) { + printf("%s: Feat disable failed for %s on index %u\n", + TEST_ARC2_NAME, PKT_FREE_STATIC, n_indexes); + return TEST_FAILED; + } + } + /* Make sure no feature is enabled now on any interface */ + rte_graph_feature_arc_has_any_feature(arc, &feature_list); + for (n_indexes = 0; n_indexes < MAX_INDEXES; n_indexes++) { + if (rte_graph_feature_arc_first_feature_get(arc, feature_list, n_indexes, + &feature)) { + printf("%s: Index: %u should not have first feature enabled\n", + TEST_ARC2_NAME, n_indexes); + return TEST_FAILED; + } + } + return TEST_SUCCESS; +} + +static int +test_graph_feature_arc_destroy(void) +{ + rte_graph_feature_arc_t arc; + + if (rte_graph_feature_arc_lookup_by_name(TEST_ARC1_NAME, &arc)) { + printf("Feature arc lookup failed for %s\n", TEST_ARC1_NAME); + return TEST_FAILED; + } + + if (arc != arcs[0]) { + printf("Feature arc lookup mismatch for %s [%p, exp: %p]\n", + TEST_ARC1_NAME, (void *)arc, (void *)arcs[0]); + return TEST_FAILED; + } + + if (rte_graph_feature_arc_destroy(arc)) { + printf("Feature arc destroy failed for %s\n", TEST_ARC1_NAME); + return TEST_FAILED; + } + + if (rte_graph_feature_arc_lookup_by_name(TEST_ARC2_NAME, &arc)) { + printf("Feature arc lookup success after destroy for %s\n", TEST_ARC2_NAME); + return TEST_FAILED; + } + + if (arc != arcs[1]) { + printf("Feature arc lookup mismatch for %s [%p, exp: %p]\n", + TEST_ARC2_NAME, (void *)arc, (void *)arcs[1]); + return TEST_FAILED; + } + if (rte_graph_feature_arc_destroy(arc)) { + printf("Feature arc destroy failed for %s\n", TEST_ARC2_NAME); + return TEST_FAILED; + } + return TEST_SUCCESS; +} + +static int +graph_feature_arc_setup(void) +{ + unsigned long i, j; + + static const struct rte_mbuf_dynfield graph_dynfield_desc = { + .name = "test_graph_dynfield", + .size = sizeof(graph_dynfield_t), + .align = alignof(graph_dynfield_t), + }; + + graph_dynfield_offset = + rte_mbuf_dynfield_register(&graph_dynfield_desc); + if (graph_dynfield_offset < 0) { + printf("Cannot register mbuf field\n"); + return TEST_FAILED; + } + + for (i = 0; i <= MAX_NODES; i++) { + for (j = 0; j < MBUFF_SIZE; j++) + mbuf_p[i][j] = &mbuf[i][j]; + } + + return TEST_SUCCESS; + +} + +static void +graph_feature_arc_teardown(void) +{ + if (graph_id != RTE_GRAPH_ID_INVALID) + rte_graph_destroy(graph_id); + + rte_graph_feature_arc_cleanup(); +} + +static struct unit_test_suite graph_feature_arc_testsuite = { + .suite_name = "Graph Feature arc library test suite", + .setup = graph_feature_arc_setup, + .teardown = graph_feature_arc_teardown, + .unit_test_cases = { + TEST_CASE(test_graph_feature_arc_create), + TEST_CASE(test_graph_feature_arc_features_add), + TEST_CASE(test_graph_feature_arc_first_feature_enable), + TEST_CASE(test_graph_feature_arc_next_feature_enable), + TEST_CASE(test_graph_feature_arc_first_feature_disable), + TEST_CASE(test_graph_feature_arc_next_feature_disable), + TEST_CASE(test_graph_feature_arc_destroy), + TEST_CASES_END(), /**< NULL terminate unit test array */ + }, +}; + +static int +graph_feature_arc_autotest_fn(void) +{ + return unit_test_suite_runner(&graph_feature_arc_testsuite); +} + +REGISTER_FAST_TEST(graph_feature_arc_autotest, true, true, graph_feature_arc_autotest_fn); +#endif /* !RTE_EXEC_ENV_WINDOWS */ -- 2.43.0 ^ permalink raw reply [flat|nested] 46+ messages in thread
* [RFC PATCH v2 5/5] docs: add programming guide for feature arc 2024-10-08 13:30 ` [RFC PATCH v2 0/5] " Nitin Saxena ` (3 preceding siblings ...) 2024-10-08 13:30 ` [RFC PATCH v2 4/5] test/graph_feature_arc: add functional tests Nitin Saxena @ 2024-10-08 13:30 ` Nitin Saxena 2024-10-09 13:29 ` [PATCH v3 0/5] add feature arc in rte_graph Nitin Saxena 5 siblings, 0 replies; 46+ messages in thread From: Nitin Saxena @ 2024-10-08 13:30 UTC (permalink / raw) To: Jerin Jacob, Kiran Kumar K, Nithin Dabilpuram, Zhirun Yan Cc: dev, Nitin Saxena Updated graph library guide with feature arc Signed-off-by: Nitin Saxena <nsaxena@marvell.com> --- doc/guides/prog_guide/graph_lib.rst | 289 ++++++++++++++++++++ doc/guides/prog_guide/img/feature_arc-1.jpg | Bin 0 -> 48984 bytes doc/guides/prog_guide/img/feature_arc-2.jpg | Bin 0 -> 113287 bytes doc/guides/prog_guide/img/feature_arc-3.jpg | Bin 0 -> 93408 bytes 4 files changed, 289 insertions(+) create mode 100644 doc/guides/prog_guide/img/feature_arc-1.jpg create mode 100644 doc/guides/prog_guide/img/feature_arc-2.jpg create mode 100644 doc/guides/prog_guide/img/feature_arc-3.jpg diff --git a/doc/guides/prog_guide/graph_lib.rst b/doc/guides/prog_guide/graph_lib.rst index ad09bdfe26..45c7695c80 100644 --- a/doc/guides/prog_guide/graph_lib.rst +++ b/doc/guides/prog_guide/graph_lib.rst @@ -547,3 +547,292 @@ on success packet is enqueued to ``udp4_input`` node. Hash lookup is performed in ``udp4_input`` node with registered destination port and destination port in UDP packet , on success packet is handed to ``udp_user_node``. + +Feature Arc +----------- +`Feature arc` represents an ordered list of `protocols/features` at a given +networking layer. It is a high level abstraction to connect various `feature` +nodes in `rte_graph` instance and allows seamless packets steering based on the +sequence of enabled features at runtime on each interface. + +`Features` (or feature nodes) are nodes which handle partial or complete +protocol processing in a given direction. For instance, `ipv4-rewrite` and +`IPv4 IPsec encryption` are outbound features while `ipv4-lookup` and `IPv4 +IPsec decryption` are inbound features. Further, `ipv4-rewrite` and `IPv4 +IPsec encryption` can collectively represent a `feature arc` towards egress +direction with ordering constraints that `IPv4 IPsec encryption` must be +performed before `ipv4-rewrite`. Similarly, `IPv4 IPsec decryption` and +`ipv4-lookup` can represent a `feature arc` in an ingress direction. Both of +these `feature arc` can co-exist at an IPv4 layer in egress and ingress +direction respectively. + +A `feature` can be represented by a single node or collection of multiple nodes +performing feature processing collectively. + +.. figure:: img/feature_arc-1.jpg + :alt: feature-arc-1 + :width: 350px + :align: center + + Feature Arc overview + +Each `feature arc` is associated with a `Start` node from which all features in +a feature arc are connected. A `start` node itself is not a `feature` node but +it is where `first enabled feature` is checked in fast path. In above figure, +`Node-A` represents a `start node`. There may be a `Sink` node as well which +is child node for every feature in an arc. 'Sink` node is responsible of +consuming those packets which are not consumed by intermediate enabled features +between `start` and `sink` node. `Sink` node, if present, is the last enabled +feature in a feature arc. A `feature` node statically connected to `start` node +must also be added via feature arc API, `rte_graph_feature_add()``. Here `Node-B` +acts as a `sink` node which is statically linked to `Node A`. `Feature` nodes +are connected via `rte_graph_feature_add()` which takes care of connecting +all `feature` nodes with each other and start node. + +.. code-block:: bash + :linenos: + :emphasize-lines: 8 + :caption: Node-B statically linked to Node-A + + static struct rte_node_register node_A_node = { + .process = node_A_process_func, + ... + ... + .name = "Node-A", + .next_nodes = + { + [0] = "Node-B", + }, + .nb_edges = 1, + }; + +When multiple features are enabled on an interface, it may be required to steer +packets across `features` in a given order. For instance, if `Feature 1` and +`Feature 2` both are enabled on an interface ``X``, it may be required to send +packets to `Feature-1` before `Feature-2`. Such ordering constrainsts +can be easily expressed with `feature arc`. In this case, `Feature 1` is called as +``First Feature`` and `Feature 2` is called as ``Next Feature`` to `Feature 1`. + +.. figure:: img/feature_arc-2.jpg + :alt: feature-arc-2 + :width: 600px + :align: center + + First and Next features and their ordering + +In similar manner, even application specific ``custom features`` can be hooked +to standard nodes. It is to be noted that this `custom feature` hooking to +`feature arc` aware node does not require any code changes. + +It may be obvious by now that `features` enabled on one interface does not +affect packets on other interfaces. In above example, if no feature is +enabled on an interface ``X``, packets destined to interface ``X`` would be +directly sent to `Node-B` from `Node-A`. + +.. figure:: img/feature_arc-3.jpg + :alt: feature-arc-3 + :width: 450px + :align: center + + Feature-2 consumed/non-consumed packet path + +When a `Feature-X` node receives packets via feature arc, it may decide whether +to ``consume packet`` or send to `next enabled feature`. A node can consume +packet by freeing it, sending it on wire or enqueuing it to hardware queue. If a +packet is not consumed by a `Feature-X` node, it may send to `next enabled +feature` on an interface. In above figure, `Feature-2` nodes are represented to +consume packets. Classic example for a node performing consume and non-consume +operation on packets would be IPsec policy node where all packets with +``protect`` actions are consumed while remanining packets with ``bypass`` +actions are sent to next enabled feature. + +In fast path feature node may require to lookup local data structures for each +interface. For example, retrieving policy database per interface for IPsec +processing. ``rte_graph_feature_enable`` API allows to set application +specific cookie per feature per interface. `Feature data` object maintains this +cookie in fast path for each interface. + +`Feature arc design` allows to enable subsequent features in a control plane +without stopping workers which are accessing feature arc's fast path APIs in +``rte_graph_walk()`` context. However for disabling features require RCU like +scheme for synchronization. + +Programming model +~~~~~~~~~~~~~~~~~ +Feature Arc Objects +^^^^^^^^^^^^^^^^^^^ +Control plane and fast path APIs deals with following objects: + +Feature arc +*********** +``rte_graph_feature_arc_t`` is a handle to feature arc which is created via +``rte_graph_feature_arc_create()``. It is a `uint64_t` size object which can be +saved in feature node's context. This object can be translated to fast path +feature arc object ``struct rte_graph_feature_arc`` which is an input +argument to all fast path APIs. Control plane APIs majorly takes +`rte_graph_feature_arc_t` object as an input. + +Feature List +************ +Each feature arc holds two feature lists: `active` and `passive`. While worker +cores uses `active` list, control plane APIs uses `passive` list for +enabling/disabling a feature on any interface with in a arc. After successful +feature enable/disable, ``rte_graph_feature_enable()``/ +``rte_graph_feature_disable()`` atomically switches passive list to active list +and vice-versa. Most of the fast path APIs takes active list as an argument +(``rte_graph_feature_rt_list_t``), which feature node can obtain in start of +it's `process_func()` via ``rte_graph_feature_arc_has_any_feature()`` (in `start` +node) or ``rte_graph_feature_arc_has_feature()`` (in next feature nodes). + +Each feature list holds RTE_GRAPH_MAX_FEATURES number of features and +associated feature data for every interface index + +Feature +******** +Feature is a data structure which holds `feature data` object for every +interface. It is represented via ``rte_graph_feature_t`` which is a `uint8_t` +size object. Fast path internal structure ``struct rte_graph_feature`` can be +obtained from ``rte_graph_feature_t`` via ``rte_graph_feature_get()`` API. + +In `start` node `rte_graph_feature_arc_first_feature_get()` can be used to get +first enabled `rte_graph_feature_t` object for an interface. `rte_edge` from +`start` node to first enabled feature is provided by +``rte_graph_feature_arc_feature_set()`` API. + +In `feature nodes`, next enabled feature is obtained by providing current feature +as an input to ``rte_graph_feature_arc_next_feature_get()`` API. + +Feature data +************ +Feature data object is maintained per feature per interface which holds +following information in fast path + +- ``rte_edge_t`` to send packet to next enabled feature +- ``Next enabled feature`` on current interface +- ``User_data`` per feature per interface set by application via `rte_graph_feature_enable()` + +Enabling Feature Arc processing +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +By default, feature arc processing is disabled in `rte_graph_create()`. To +enable feature arc processing in fast path, `rte_graph_create()` API should be +invoked with `feature_arc_enable` flag set as `true` + +.. code-block:: bash + :linenos: + :emphasize-lines: 3 + :caption: Enabling feature are processing in rte_graph_create() + + struct rte_graph_param graph_conf; + + graph_conf.feature_arc_enable = true; + struct rte_graph *graph = rte_graph_create("graph_name", &graph_conf); + +Further as an optimization technique, `rte_graph_walk()` would call newly added +``feat_arc_proc()`` node callback function (if non-NULL) instead of +``preocess_func`` + +.. code-block:: bash + :linenos: + :emphasize-lines: 3 + :caption: Feature arc specific node callback function + + static struct rte_node_register ip4_rewrite_node = { + .process = ip4_rewrite_node_process, + .feat_arc_proc = ip4_rewrite_feature_node_process, + .name = "ip4_rewrite", + ... + ... + }; + +If `feat_arc_proc` is not provided in node registration, `process_func` would +be called by `rte_graph_walk()` + +Sample Usage +^^^^^^^^^^^^ +.. code-block:: bash + :linenos: + :emphasize-lines: 29,38,49, 53,68,69,74 + :caption: Feature arc sample usage + + #define MAX_FEATURES 10 + #define MAX_INDEXES 5 + + static uint16_t + feature2_feature_node_process (struct rte_graph *graph, struct + rte_node *node, void **objs, uint16_t nb_objs) + { + /* features may be enabled */ + } + static uint16_t + feature2_node_process (struct rte_graph *graph, struct + rte_node *node, void **objs, uint16_t nb_objs) + { + /* Feature arc is disabled in rte_graph_create() */ + } + + static uint16_t + feature2_node_process (struct rte_graph *graph, struct + rte_node *node, void **objs, uint16_t nb_objs) + { + /* Feature arc may be enabled or disabled as this process_func() would + * be called for the case when feature arc is enabled in rte_graph_create() + * and also the case when it is disabled + */ + } + + static struct rte_node_register feature2_node = { + .process = feature2_node_process, + .feat_arc_proc = feature2_feature_node_process, + .name = "feature2", + .init = feature2_init_func, + ... + ... + }; + + static struct rte_node_register feature1_node = { + .process = feature1_node_process, + .feat_arc_proc = NULL, + .name = "feature1", + ... + ... + }; + + int worker_cb(void *_em) + { + rte_graph_feature_arc_t arc; + uint32_t user_data; + + rte_graph_feature_arc_lookup_by_name("sample_arc", &arc); + user_data = 0x1234; + + /* enable feature2 on interface index 4 */ + rte_graph_feature_enable(arc, 4 /* interface index */, "feature2", user_data); + + while(1) { + rte_graph_walk); + } + } + + int main(void) + { + struct rte_graph_param graph_conf; + rte_graph_feature_arc_t arc; + + if (rte_graph_feature_arc_create("sample_arc", MAX_FEATURES, MAX_INDEXES, &arc)) + return -1; + + rte_graph_feature_add(arc, "feature1", NULL, NULL); + rte_graph_feature_add(arc, "feature2", "feature1" /* add feature2 after feature 1*/, NULL); + + /* create graph*/ + ... + ... + graph_conf.feature_arc_enable = true; + + struct rte_graph *graph = rte_graph_create("sample_graph", &graph_conf); + + rte_eal_mp_remote_launch(worker_cb, arg, CALL_MAIN); + } + + + diff --git a/doc/guides/prog_guide/img/feature_arc-1.jpg b/doc/guides/prog_guide/img/feature_arc-1.jpg new file mode 100644 index 0000000000000000000000000000000000000000..7103286b2e75c49b5f7dc77b2f8b0c61d8c5302d GIT binary patch literal 48984 zcmcG#2T)U8*e)7GKm?@s5<dYEDN(A_AV?Pw3kV2NsR02IkkAs4-W3!SgoreeCcP6% z01*-CO$Z51dO`^s2;t^C?VfvQ&VTQJX3k39NoKN>S#Q=}Z+V_)olc(4gE&kKj153^ zbabHCv<K*P2BZf%Lr3@T^S=#x2Ks*o<Jq(H3`~qnO#j+BW)|ji=gyyFVmi-u{yYmS zZ7?xkU}s~!@bCM7f8^h<|NAZ4ll2_axqq+t&yCY|5a&6%o-=0jbeBM9IO*s)=}xgA zFbG7)K%4Eq6aH_5?hO4|21eSH&a==isO6wdpPv2<ZL$n!&(f|ArF{-M%gMm?&-I&( z+?G$6F8S~%gulr>C$3xB!FzXzD53cD#Vh9XeEb4}LXwxIu1H^1QdUvDp{A~POW(lI z$k^oG{RdXo4{dB6ot#}<-Qe!Ne*P~55P?Avkx|hxv2pRKX>Z@9XT1NA`8hAYps?sm z@z<*An%cVhhQ_AOE^K#C@AtkR!y}_(;}erp(|E$d;?nZU-_<qJ&hFkm`2aXP`qwWy z5dD93>wkFm|MH8I=GPh88k}YN*Dty=0W_oMJj?LUbw;k6mP}84xGyP$pX1SelUv!r zEUtK$$ourg(0M)yCA=i*U)TPNXaD~kd-cEN+5d3t|MqJd#7a*`TReJB5EOJm`5b=* z^#8Pq;<dUaxvW19k2>JqU^&_0b3@2{;*~Sqyo+r&PFksq6eSlJM~D+(_xXE^z_#WC zN7fH}=Z3eW{>lur7@mR{%1_=><j^$~U!rVt&`I*rHgwOV&W(OeU1mWB1KiLfYgQef zf`pWIPeG6N<g6@C7)Qs9Q1b-z<TSx7Z$VZkWgFpWYk8QZd52$n@^hQk@F{4%4Ohii zamA=j`ER^k5xUTwgMDDLop%P|O+CMT3<17;sRj0lO<E_~QxzSqhlfAkQ{3qP{*Xx^ zLN>*T+l1snz#t@e9>W=k_B~d#t81R!+xfHHYy!ISIsQMkFI!uLZ?&m`i^&2{^dwS^ zI;@oGB~lTf3;XyWZwgQI{CIKTlX`5>sJeCu>g0nXL8IclJ9$p9?PIe+j(Mfz*VP?~ z<O0Vx^5;!VB3=G8f)3)Zd=5MRU##4E!MX>>iW~%A@NThLV6!-u(jA$*vh?1r-&ed( zwuHyhkkw?TU;O*u1QGY2KifgZpDuijCl2zXIt;0t2pP+X&rRbk`u=dd=?B^U0lV8o zWOec1X$ca@HGbQ&t|oPO7XN)W-S~dzO|EAb7ly@wB|J+C58$dFfwg@wSG*u2sBFeH zH}3P?U--t5=vJQe>&It|PC-HDolZK;vY*2I{VeZO^awKS=K$of)mTO8-T>rwed^ZE z&X#lZ+_1oCOKP7u$Cvm|sn{@(L?)<F-vt5b5kg@hOmKDT8?~lk|NblfEYg`$u>)tn zNF>GIxX@_D#7ZaF0UFN+@mT8rZ<+)1u{)~6w2d9vK7HGa#MI5qS09vBa|&XIS7yyR z-d&;ZuQ%6`3ftkiO=^nFda3KFZ@&>d`vNMctqp+50mNz#q$VjKnj)H?NLYV3`m{P( z7aGNysH!S{zEMh?K9iCP?9*=Lgp<5ekb9g|Ef87+$ADUdp+7R}zZDh}g5M9G-F&h* zv*?=CJeni2Uy*f>?D=~i$7f8i5U}@va)vy39$-<5C_LQPh_h2${pTu3V%{;u_P7+? z^%E!db_wjvG;Rxh8*seQGT4Kt=tc7NIsF~^LgKZaDsoBN&8k7JTy6&Eqj+ie{vvyX z(1U^Qj4m)6<tEUJ;uaVW<u>xrlD#&+-Pky(Gbo&{!c^HEa=35`0_0Ge4@eL4VJrwK zylZE+`csp-Vqfjn;!cexX-;R4meoo99&Q_D!&e-QJ|}wK(m(%I3nY5g<U|-k%#$xD zm(TwSh4>>YNYFEb+G#dq$%du3(!Wyz0{gdLrch0+Ng3UP(~1i$&4^xd2JkMfjUvXs z6Qari{sVToW3)La)f(7Va(ofc>plu=CEd!AAY}t9o3>kx{(<trJCE3hTXo})HXw|P z?@@Ss-tHsZ(SyPMY6#yAjL1yI`}?qY<lrgDXz7N%F!>1(@F|>(VgS6w^Gu(J{DktK zow)ggxX?9irQQGOZ{6hT(nIWfN_yRw3iotaQ~~9xk3*dJ;&ruU=hy)3Qz@uTAN5%U zUxp{spZaj<Y~uNM^TzzF@rJoPM=~Yv<TzK<`kL$RH4?Ybh<r0g*DG3jon`2sR@%8l z?@pm_P<LWQ^p@|$z{o!#R1bSe-nYb2S5i0hesZQ-^woq`q12Q-j~&es+mmFZ!1~lK zML53@wKAzyPfc(xp>hJ!Uno~*PC@6`v4aUH_DI+o;dh9Q|5=%hJJn~}dYXU8{J=gR zzh{p;U}HK3dF500i}xDXIU3Msx1)Q<9UO+uLI-LA;heK4^%#$eR~wi~jPQo0hckF~ zgyM?->qSS~rOO=EA5TH84tOGtdf@_4F)#J7?J9-7ZlcUUbM{`l5azx0gy*|oPTt2y zGArsb%h%@woodHcrSG9;11OTH-zUPCk8Y7(vK7RAl<7St8lMoCj%Nplx2I;PEJer4 z$RYKbAQRv(f*)(HqYh1y%hGGO8wB|P*%FMKziQH})hKwh{DUlN@=GQm&@pGuk4s<n znV`g71wo_vSL&RwFtO`EXf8!>q^++UE`%)ePUc!;Nb_z=RbX%U3O*;ReF^#9Hf9FN z7-CL>gxy1BU5@aDkPE~8d{c$SLx1EizFOa9B}KsKGl2&wpFR@rJ+StUh9#rpp`Lhj zew}fmd%BOo!$4?FD-g2rHiLTR#Nw}cJf->MBXl00g{HT+b3@l)Ua?2kS7CFMi7hX1 ze-+Zggb+yhX7ecs1)a5o<zrZpR}tO|*5S0+!HqDqA8s+mpIBX&E6go=RMy?H7Aj~g zD0*&<{VY8!lR)$**4m5Q7LjODc0A&i8Te+CF8XxmsIu5>^GeMGexhksc+XPbS1im@ zp9l0m8QluFHYKTrZ5|gc^askhucnl84#>XOd5|H^Q+{*wk&VHJIDx{IZ0kVb``=`B z1S`@t4IN2L<nw_4JURx<>)Ap_Iv~Fst7VgFw{(EPUkze|?#?=BwPxaMuBG?itB*o< zbEf`tws-k;=aNm<>fm%y=bSVUH6MX51LJXB-f?2!i6@yj`;it}dP=%H*}Ee!c2`bi z&n&Gad(NRV)_{PtKqJA_?@*355uoJO_+vnkxNg@%98^~TvdD3yfH=7t*J&P8560Yl z3m)#PYzeY%RadL8JT7ey3v6p#NHSeOZAg)_$k`+*?6w$SVKwALq6e-H>XNkPJ`@19 zqGIH&=^nw-r*AyHR~j0^lzMj5T87kbo%#GV<<3bK$_>gzxqVX7Vn;v;t*cVOL|i90 zO6WWy<+exh(-HiHvH<u#Cg&l~285yX<quV9Cz~wz;lSNd%+qZ_4=|U!rls#Olp>V5 zylr<1icAlcYg0p{Q8^Fy%{~dQ3_~lS)zgdLc3BH?ff)z+AGCuiNWo+wQa~?^3sHTK z1ZlU3thZQbxXaFEYfA|wnMG%pZ^ZN^ZIy2BxosA{<G5n%pm<4O!TIs`d{AJ(M*1m; z3+0ZB12fd1IB6j{ssP?5PDI6O%OUEf`>`46*8EmY<6lbhR!bzj#Lnf`vvS<};kdK7 zGp*Ix<o!yUx%DLf6y!LANyyypO%V=}9`oKmtl2)ZW-WHTRmdW;bVE6ya-^($)43@b zXPxu1{!Ad`XVs(HJ~P~Nb{8U3=XL^`r6n+c;K?!{(0<J3esJp>aWO3=QGGOC=@_iK zQMW4mmx1%%uZ*{M9@hV~qZi3ZI0hqTx@hxWAU&wxI0X^yHph>;fcWViSkm03Ed9zc zk!zm1Y;t>wjto<{e|8tbon|GHntdxTrZ7w(HA75Jazn&P>jdrULW<YOW{Yb18f}&2 zEAVJBH!3d?6PY)>m^vk2@dRyCtIE~qmn7Lclbdrfoa=hEMr*JEP#JJ+8ggqW#Ehh3 z^sI&cSQc=f=+;(G{~cQOYrO|ORUDvXO!mI+#eKW(^<b<XmAWk2=vHZ`zP;hS0OJnP zYavN)w}T@TAGzCBtshLgQXsTdkNDz#m4jt!@6Bfx=5j?5&*eUPHN;TgTyBgjF$O=_ z!yXP}b0VfhBbg`{YJbbi%WrKxZUQi6u)a{`(F*0CX#+m^L&@yLK#^*rpXNTlL3B9} zd_M!nROX>$O(3BccA?hdT*%Xt4-Ramz5HT)6M3Gh_CtI9-N*i&lQ7V4hg-uI{x@E& zom-sj=lC$W+<>a3Xc750!%5W(&TprCBQ=GI+<0VoAp+TN(TGW~7?Fo;F1B)9{@|(f z{QYg$+p{h@aru*rGRU1)u=z=ZrgcGQI-Dqsf0iQ>PsADGZB9XMP(BO%L-gRW?$^H+ zdD&`DjVmwd%3*z~a`o*?l4G#ostGJRFAzac$tw;y3&;fF_)5onyX(?IJV^BLqfXiD z?d9XBNtml~<ei?+hy@#iIk1`%-GT!f36s*sg`5IcqoTd?PCofr@FSLYA2gA23Kj<W zAKI^KOI1c#q%ZFn)g;(kk!Q?jo<F``%F+HUcjw)ECu=mt90)E){>BhZ?7T&Q>RvQ= zEs7ucJLh_WIdMFjJyBW19%439JK)#L_Mtl7DW1Sv`3~nq>Z_sS+Drn0_5Py1p%eBX z!gh%F6lMVS6_MG0yLrfSKiiQUMRF<o(&gyS8E^NXp=oIGtzPZN{NOt5un{RTP&BK6 zl(B&$$@HSnYDy8;j_18QCR?QD^&ZcOz3N(siLE&<6D@V*wAEC7c_j2GuP1^oGAl(* zO6lBD0zRcH6oO|DtHH3jp{HR}>Y7m3TA}D7-{L<Kk5hTe<(*Ppd!DN{wu4wfpt;gh z5VQ7YD(}dJ3J<triLg=9W^KXxT!*)I$FhWPpNO}Dj1#kvk_(6{-h3!mr!)S_r!)Uq z`{46D{k3LQQ?H1-{p>GZ&|+%v`B0=Ds>2cEopg^}4q!@<zi=1)Lk*3I&?pxVRGiRK zngIG<gNUdQ|9WNM?)SA9F;SPy|6m{$$yh^{=%f`X=aZNA7UEii*8;WA6gt1RNPnmN z@)RV|T(@UhqHZzMPh|<OpxBV)i-<V#lgvpwTa9TCG}qRX-DjmAMU-sa!RZ8tyaBbF zl#8#b*pow8h_2?ul-LT2UZ{UD0^OtjGdk1)8#LDC;BLKhtxM75@FMu;B<l+AZ-i@? zIx0em#U5f(6Wwc3m8gG~Q=U&5JkcnXYAltBfemXy+5y?Z^Z6NCUR9yc&ZeNPQxH9c zN&@%D;^MFNvzwbI^A{*lCFeXtEc)^GSz~W4^+PKG;D5@d|8r*jAMg9-O}~h#aXKaI zU;W#4wVilVwA+_fd{wkvL}GK)v$}C~ng$_?TG-B&`^4-ic!(N7gw->ZHJtlRd#YAJ z(3!@|P3kgz13S0*Tn#53FXlICmkem5#|8`WNXS4#Fkj^dGgoGRyB^b;ylPnd-x25? zT3w!nCO)WOJOy>=?0IAhnW|B^NftVh+Rb=2eOi41nit$egC5zX8i*Pg7|bgav=vvZ zWDp=-n|gQ0_bT`hh7X&G8CckPV{#citjaUZ_J`te{d`PRm7e&Sb1w6*+NrImj;ql5 z&*^C59aLD_th)+o62+y-e-*B+IApTP7m#H>Mc9A!Jn`=fpXf)~%_+MmK4NxAdXw4i z-Ha~C&>=OrycqRKj2}Qp5GdU6U`>4uUs?|EN<m=SAcjMjFSPFWkbD2)=QmmIi$o@g zoU!Ggm`#B;nbr(*Ag}<MwEfv7-tKSVv37#f!o@i6bIvc=87|s93a}gx)4CcsJk6hK z_>h+T6|cA7QIkN^TGj1oCt#RruYoU*gCu(``0_M;%GzjR%c75HBbG2f^xd&5EfQy| zE|WnH?1q?Rd$nEmkRx=nH7d#YdDt_GnbX^CU0w|H$%^*BarTnXK8ws1znL3ln}qmt z|J-@gEyQ3n`W!?b##C@k6W4`4<8KyhUo}n%CD^5KuBj+Wj+K9KDs%iiX;NTgbCK27 z#oGSIZu9HFJGHAdmPY?|YhKl8%$yrH=8~3j((UJQ)-%#M&hw#{Dw1Hodxaj434_)h zVA;88{k5iL(fZL+%PELSQ;#s~jUS9E<@+_u_@Q)_&x)Vbtn<^mfj*(8%{MdbZfC;I z{o3wK0j@aj$6&n^>T|?Hy}SA9F+7Dp0CA+FNiwQ>Ei<vn|D((o0hT}=tUSY?szHDC z?(>~fh>6Eu9{5wx29(6#1tXfESymO?irIT%Y{2UfGd`KXXSbVH$k@!py0(B1WZz{y z*}B}sER_byZ_MSsWY?2KZ5e9+OK|lH)|9r9W)T=HQe>p%ZjK7E?OpLCoB80KiSpsY z^3A2D#`s}J;m-6ORKE0;`^9Nq(`Q3Ppz{Sty5B8K3)%O&GXoMr*vmpRTB=9(D_Gs@ zI0wsE68?m~l0j@NHN^j&<&JF|lnr~`5&!min<vSTdS0@4^%PXQ(uresS3!yc&;s~T zKx_z%bfybSTur?(BwKpl?x&aBa#Pfk;Np&1*15+jsp3&*U0;!K8`dOLPn&upa1e_3 z2&BLRNsumwt59~&{b28!?oWTo8RK_sLyP~|DpNOg?drt5)7q{jT<>hiJ2s+rqXkj( zpTsl)Qn|+*OFiHVFQX`aBf5rrDx0~F2PgboGyCEoxnN^_Ej&Ls7=h~#xGD0+)Ah;a z->xHI7S#M_Z7`6skirPJo?`~$=37+>uxY~xWgO?jX}d{8c5dQNE{Wu2)2x8>SqDV= z4$F(bN#U4t$nc7|wlmb;i8<wyTuo*In>F4wg~E*Yj=57;%md@lzUtm~6%+d8^EDl% zb+_8A<|~h*rO+V<pzqYDpLN1&A~rMsW0>jx1BN<0rk>9@wlO{Crgoq?wJ$#W9#`=Y zj(hq$+-#{<INdJzDK|jwyVU5gE^NI3X|IUx#k+QyvZ)6;H;r9p+`ZqFsV7mNkxJP$ z+Ax+i<?fT1KYw!J6cq99as#*$+6CN4eX^(A`~7*;4*CM;IpT^tNC2<EIIK6tIOpN@ zu|3c@TbVwM`h(R2@OPYv=5mW;_>cKb^G72YSyqY2_5N)dpoMt`ef{6_AG^Qzq@z{a zNs_EK1RjJYC%&i|49ze5U|n6GOn4~t<f3m2y?~1_zk8+HVc-(V2{*Ms6-rnTt&hai zo`Swnhdh;gr>TA9>^9r2o`Kbg3I9+v;siM{gY15iM5TA%!Fnsn=^j5E*)O?7&r)L8 zk`?d+A=`3ozvEF@Pc6z7I@O7rSEcZ%>bL!Nvcu6M>Wx}PDbPTXoTo~19FBZjORB75 zFG^$7q`+DC36DHQv=x*K;8Hfj?=mROZ!=`9s(q^551Np-so}YJvSoa)vtsAX2IZ)S zUjx$jbD6Kk&8;cE@OkNxZfyI*2)Gb`WJ&{-0-|X3)Q`+lQ1><$5MV~K`ZC@0*8x1@ zZ;^@ZTZ#^J&`y00TY~Ol7X<&PXkH6}9J~IDc5oDBbvW=60}`p=)v|J12jJ!4hSkCN zU%~u%qnp!4%wbbfvey$ia29s4;^w}{fu`rFkwyM_FYO#QFAsZ<_f1l^S=y`14Bk3i zlHs)a__gz0LBQGk{dbM`^Yf$xTF1&q+zzdpak0>|Q2bdyn7G@6nnt<P+N9lM(-ZcM z8SO5zMpVr9md3%>;H-T^ua?Ij&EPKx53&q!ok;GPX>VgEStqtQ=Nne69cW99P^X^} z-m=RJ5F`W+|1>U~*!fE>{nge&1n8d>gfJW{z;lE~#EErjgyvZXZdYzTGp(F0+@`hz zD$;m`SM++#<Ma4p?7erkyy8qk3Li((>MA3zsur$osoD>(218-&?f2pM%C}b^B;9@_ zeb+s6*_^w?HqyE^-`Q=T$JAL`#=fK?@k_<;Z2<~1Nh+-EpHt9dz=HgoXx=){rj|NY z;m=c>VKw@j)mY(=X2<Ka>_&$_3pd0Bk9ANT8WbaRO+{>oGI7E%&3eRB&U4>rKJ`c- zr$_LBPFQJJenZoXk@*I_l;+su8~yaLXgT96QesYj=Eur2T3xqVtx~p|#5IU$wf5na zT;}mqbhXd@uZ4@F*{i$y!A8eb2YIz=?gNU;CP(MH$Y;hN7$;ZYqw=Tv&R=GhO5D!J zy;a7#N>uL;?NcAFSHDRPEVtSvUn8wVQ5AuE9om<MW(-FuHqYap@ezc}D*2~((9)Bj zFh!9!oteif3zj777^wFw*sz*t7>~hQtu|dk$PCyEEo}(RE-?L^EB<ydqhI&1{g%{4 zSCKzAu?mI7ry$n{3BwP>ii>rHUKGuF>wEgS=C!vlnO9>`-uM-8kN~2vh~K=-EHpp0 zy7o%`bVl>GOd-<K(!PFEm>BIHh7-{=#;eu88}=5In@zr5w;2;PNS`MBkM`mOH_S1n z;{0BoZCZ;{nnTKcq-Ao4RR_WS$@TLiMN)$DzvKr(|I!MK$;JNyc2^!>4S{Eo6;DC0 zQbVqj{_xAW;xVxqar01q1LGYR(;V4yaMk-F<_z&jh8Ofg6%IDXj%Lb59pOICzluFe z;i;=@(D-=={Th_|p@VY!NVii%?CA0J7Y^p?r=a#jbOA!|qji4+hW>5@Rbos{p7iC= z{zM-A^)@wvVoh4;Y-0wB@fZeo+ZH~mB+1FQzi>*-)+vgmS?tHPvR9LT?uVz!WRGFs z>)sq|)vHi;zpRv4p&BlMqMTor7g8QC2y){%99b2A`Y=0#|A=}luqUI5MzBOwja0A4 zDG0od<Iv<gDwzGAF6_&Ots}qAJ(+DPzAZ5J{G9l5KX+;`^s_ei&_vf9|H#JO5sPnp zb);^x$2m&#!*h4eV;cl?e8a<gWDf18z^h(G*&WBwH5ixfpAfV0-dM{psjlgu+QKN# zg(bv}Q}fZUZe~GFDU-c*mUBuaSIWwA<LBnia(43=af;u$#;Y?A(m0<P|0asZQitLH zfPo>X4ri$I`YC97hRQraV(AK!P#h#A$&YF3eafd-=nHlt;KgtLu8B|KU}|}H2qp#) z9u#%sqJyBZ&!*11tE}x@LhmaiOC%nbM1!MHy2=2W2DMw9ByM5mvv4(+^GJ%i^$l6` zuGkaHEq}zP`X30Xhaakb=_bnMZ~ophI7A%MQzP&=u6zC0e<lAjoo#pdSh*T$TSKMB z;2kudGaxVZ;S<^oGuwnV^}Vk&`|1Y-UCyvms&!@3H-rc9o|O7_Nci4VU=~kRVXcxD zJj>Z}HlSGM$XH`7Wp}?Y`#r7M!2Zik1jlrv62(MGkPSUzMJJzaN;Uz)MhpDzDrnbt z$X``|Oi0;Fx+)LeQc8Vtd>raeL1+J-v}kG((OqSDSZsaajLFb!g&*6^GN%TW+w-O0 zo+`U`T=-ceAo$#3mX}n(yW8+fpo8%3Ui&ykwm=$ZS|qKep%GYHJ!0s)t$^nAeN?ZS z_YoiXz{C%4nm(9%r|4YgRnyFEd}4Oy!Mm{<ty2*B1u!!|t2fUSOXa5Mwv77O3tM6A zVP@lHo=FpA&mUilaU6&790{E%1muT5DvyCY;tUN~XJ62wZ>L^vC2hyIpx`GT{J)4^ zwO1cBuhxk8VvKzG()vk{fzODS@N$rhNefiBz{dEO30LaJT>l@7WhEn7pFO1|HoyMq zV(Go{Lm<d+?5bDU4U>;oYaws}(+^6mOH9tvlF~Q(r1FOBR<jKW7G2Qkg!z<LN@zi# z{D4;N#)r^9Zn_nqXOv-CGg`*OV37{_VE=$WRj1FZQP`8>caq=2GQSC)e@cO1nny8s z>sg$sl4{+sU7xfn$Bh8VmxTHJiYSRMAsj{VhhFi&G?il>T>7(!=f6ywVdLoAwn63A z6_0-NOgBFZtgPRc`-yHN58MqtIzNyOHYhgXiU1C|%|CjL@+-HlH!JT;VN1YM#|!n{ zf+5~etej)#b&oWb6Ij>gr$L|RQr?+Qc>c0F20JZAcRURe&Fe&}t+#QJ__4DFD0;V4 z0M$ho`O>QTk+D+gr^nwnHn4nZ8aLYoMB_A*cqhVsAis{4n48GFlU8<WGqzv#=>KrI zHYlS>2>76DjECQQyELe#tFZjGc3s-^okrb)nXcScjnx5aQjvg(pq@dDV3A5B$wfz- zA-}-1t~xdk*=X{P{*$iHRlQLR%ujE;KN2E%p**1R)&UA8I8KV6kb%6eN4?Rfv>cur zpkTUihfsYO*+7us8ec31H}9V_&d;l|g*ST-90{VzY!VfY)V#!yzp|xNx7751+;iW_ zX{t$$AF`1@@cx@Jld=#HiGoAe0G94Lp?Fm1i>9ZmREd%9QqqRsVY>d)HXGqYw0~Sz zQEu<AJxklA#!$@*qECud7KEoyxC83?^{aN&8X`0+J~|e?C*<+oeYw13c6r$J!z?Dq zs-;O~rizvtng@CQC1J0obiyKckQ31Q!H&TwzREt|C-73k1t?Eos9a4y{qoiCs3?~# zCq0oZ=he(kppoP<h&Kr58P@YDcAtLxdC+LsQ(R$oZQ{0WFRSGjS!|_c`;G5wMojy{ z)N^CBow+=Ua)d+$)hD(Dk>)}k1L(y$AS~)`ro=h+H-(+3W&!Vy5z(mavsTay#5?R; z;-qT&-GJhIsIA_?fsK}mMU>%*7)2ZFqE>^5;TC@K7fORvyb6EJ-I>KKS8aROxP6YN zhCrKi|FZzlf9CpXP1pGWDFP&NUzEvV<XLSJzjb}E>ALWDD>r$(PwktbaMpaWn`P=( z=t&9W30kH#1ZW}R%qXPAhUn631*8yNA-=(QNk{EQyuOsLat_j?#3%J7s?>4<s`L(z zVWR=qD8g2(ca5ll3^s8y2hylqateB3H25=VU$kKWb#tGD+w7zLo0h=6V@Duop-0_u z4a!25>TgVm4^iTihCEux`hFvMQRIdBgci&EQ;aSi#o_bekrkMuwLo%Y({PBqgSwp3 z8DdC;$PlFa!C@$CY^$B=pDgO0)xar8VWQ+NRQYe2MGCAkWmEc?yH5jXZch!dCWcms zcRMgf4nBXALTDU01&!y@r#p$+h9MotTXyjiy@Tf{4-S>=U;H9$h-iIGTAampeQ`ry zxb{NbG5!Q2Mfh2vX#C`Bx%X0#=~ghMJY}KnDzQHn2r^q1aNU@gNoi$waIVj9guR&< z(&ycCZU0}UPhQcn(U(@+vcnRV2C5p(3=hQebKZ5?Qjpc8`h<xtFnf(RM~EfqQ4Dhd z!m4|FO08#ALdTLL;3@JBvvNnuz_s^Rf^XaFGc2EiB%2S##!b5#3w`X?4xO1FWE|Xk zxgRXKJZ%{KC^$raO#33mBnE%b#m){3F#r;RUK$p_^R7+4RG1w+xR~U-%O@^M`ZzHH zuI{C9GA+P1)ro6RAzF#c)bfusYls{^>uvLdH^;(aL+kRD7tG*h_ME7j%NR41Gk9_W zU$J3KoYIsb4t6#LMAvlHZskV>%(^RF>CN&{bTLL($eJsLhj$}Qu@2HQ>VmgWn}?8- z%g~bJl(h@=M=FCkH-1UyWF23DcKX8JLW$zbP~b9z!r3`Oen?^k^B`s1t#UMg5nsmd zMMk>?fVs-Azp|Xs0gqpgycS3d<KcrG*z;H~D6fx}S&o%RNo&~!)uC+XiGJ7Kibr>L z=yF<Fn)J!{UHlv`BcA_neE2_YGVK_5Z$J{)ZZUIxxq);F>at*WSI7Q21$o-u@;kY& z>Y{pw=iRqJx~YuG#fi2d9q-0NI7x%bHcVoVxLr*V2KEWUEdG+8heA9Z#VWm%a~X!8 zr7DRsawco!6t!!jjv0^>IQnUeP49>!eyoPT1+XR2B39h9Ys}N@rTNqz3#{?J^{_L= z{^R3!U!F>O4bH**D!ktuQUmd>=Uq1Yg<r)e9$P+2-S-kHqimtn#pF+NNAOx5F$Dfs zNXZbD><bexPT=X<*iG`|(sNoVLDl%}X<z(y{Qc0B9tSbWCW(nSdNjZqWw8nylBkp= zDX7O7GT1zHx~6rLcM-#dc?=832^0o~+#{m!In6$oeSHG)C2CR>iR;_o@QSidpdwSx zWDgH*h5o{YA0nOiobW#e`k5Tcq^3!!l&5IwZRGV;hl`aHjyUIFIHEP+rowlquKN-) z6&R$Rqd&fcAUMj>@HC}<=G}K`rZhSe`h@(@^}&fu;uv&(1~t|6>=fjJ>g*>T6p;fG zwve!*thUxB2Z#Z#wey6w<u@%}V^4Tjg7LeOy9GyI(YZuVUh*i8=xNw7ehRur(j&*x zXxwt`>j^2pMkiLJHfYWD*=hiN><^#2K8h5hn2tRw*AyC;pB5{t!0CzQiV$A(^Ztgj zdQ+2iw+-$(2|Ax?6@kW2nv@k=`s@b<c^>{nOs3>rfE!DRI7zNDq3mEgqkBS%u=^BN z8h8@iCgg!W>qpDFcgLtI2&g?@l|`A`0gUr0rfwvp?m6~Pw^w|BZNTDldjA^(LC|pM z{9MWuQ}+>DVHsaS8L(p7YN5i?sOf?7@qUS(vwr1oB_ejS+;&cGBx>||+05}8F6j1V zS1A8=#p;sx-LP5}+@BTh-3ePD4Uc16IW}|{dZw~}Y_@0VNIiP;$ff?+DMb1A)>$a= zoek`fqNh;}u-F0@{sxnN$PG+v)Q6+y<6%{_;uJka0}C}-e5#Ac*(GZqj!p{l2NxW+ zi8J$%@HRHP*cR|Sh8ehfQ6+L{FCmzheuVSVL`p2lS6K2mo-?K71*OrVxIL6#;XRc6 z$J6)}6n#Br<rk72!DSJT77;Y;LWiOGC=W!?Yun|15&5fCV2`Y%;{Cmf=YThDMM6)? zs7mT8t^UN3`MOMCPO^d4at*B<7xNz}I?ml3K>iwnT~8*_YhqV78~NSxF`_hXe(zCM z`!BZs%#5+n(hS?w7pI^;zZj|sGJrz+G~&57_iD!PH85X`{X#{OdgLwWl)vdnq1#&5 z>wfq%y$eCn@7~UzQD51zh``WMxR13EmP*hw2-B_{_F-<OjZAGc??-c;o@LH2f96W3 zq@*r4{g7Fdu`agtDzH&A-uK!jLGO1y{sx$sMDu-o!cY}&3`zY>i%8#B|ErMezYDtl z<5#E_@-lJ=#Y&Y#by#T2x`BDM)li*H#F#D!yIZE%htEabb{NLX1;u~jw!O;9GY&IK z10r{4bd6>63hAZG2B+?kqe&SN7RgXN>@N*B(uN?|yQ#|cBieix1UaiCgw@zH%YB*S zY=<Rzd2S=qsMmTLann}LMi07*D?(19pe{+lWM3jCWh=zaKW`4GAV897oZTANYO1kZ z3*7gb=|kSdTfR%S-CplyI;=qTbD9C0eaC{dR<8!q3j-mVa5M>0+ZDj0v*~4?W8geW zY_8uU-_+;%lk4u+-&MC7G{iZkUK3+)RP^-M(ow`w&&SSj47G$7AS&7wx=D&1+R`JM z!X9|cg>{({J4DL8(RtGZfiiE&_{p%RFLniUQ~HeZpJ_9CAcxTPs#xz=P`WmizJ-)% z*N&r=2nz4zdi<uV&e)dn0E=}a`e$8zooS!!rjSN$(@uCK*3Kz@&FDsjEFej{$r4Dt z9gwqqB@dyUS>B?we@oDgfP7QnMjnBS2{%-EYCS_$eNSc#zV@c?g`;0`$Tfq<$CHq+ zlxHW&R0wjSjWI?SC@2FiuXN6dlXB9E*QspZ(v6i`W%Ndt0;#<WQ?<zpcXHMcn+`77 zkCS*!dJ?|Xd=f!-SO8b{P>dMozse<>5PMR6=XTVQaz>25MeKz7h=aSB7K!U@Z91D6 zqoJpf@+znD%pfbH)oX)c3G@EdBkRrj1q>6#Xt)JTQp9J(wD1zx`2m<Ei9cGqdqHKa zwEXhOLb7Rz@M>E(bIm(GggKD9d>N)xf|h04p#gkE<5r6YfHlb#PmT;>@}6hG39q6! z+rVzB<Utj*M<}<U7Bvm^?9$GJSwjxr`AfShl8YbWBA=>V9>L7NpYGm{K}xS>x`v}% z(GfJ|7XK@MC^K-+gb0h-bd9lSY^uBBFH;6PRv#xey1HRGbt@$vS2NFsCDISk*sxS6 zcbjC0&q;C(S}f$Ysl_H3{AiG1rbZZZYIgqC^d`S9vUB`*!MAvN9``pjxnx08#y4+Y zILOe-)Lfv;g6Q32A@mo=^v_tED20urlAF8UR7#bzGu^z4v$)POlcYU5tuP=VwW;wr z(~Y;~EwfB@Q}-5z*|F*5J<8Ec2+I4=?Z`Aljrg@Y(6hk(F3hHjA*pU?>5nNZYkN1> z#~RaDMvH8{3n^2=<Xb>5DT~TnfrmzC4je?*RDePr)rm=wtlFBAx)A9yTDE#$aI2Lz zC+Ll3<D9@t{ASNJ8&;rycQl{mgO02T^_$@fS)q2YQ&1F~*f!Cf364?{*xxj?C#hhd z(MszbvWx_oU}o*E7hcYsXNEI44LK2`jV_OK^dOs!3)|CZa^*>8nYIA@+7yDR8_AhP zaB24by6#;#H~X-u*ZuX+*VBXH+;b9NUfrozz<%#h(%JEW)<7s+kRB*!4JK(?K6@TF zwTqoVaaL5wQ<N9B1$vdYFnA4PCE#NH$Uk)+f*}p_h}%A9yo6Y*o7d`H^>}h(@{t`- z9;6V^Y~M(1$)QW1hJ^<Obka1F7QQ93)5f11rn>zjmJD48cJRxYd<ubamt-Gu*7MM{ zBYS9ikvp(hswf~@5TZ|lL{w02&O;M0eDZ#?ko#kr_i@wDZx*jB*sS&!Jq%PRnba2u zV>{sc=_4ayo+X*J37(E2zow~pod=_eu(narxn&M>xaq&s@+n18szJ*I{#T->hvgP8 z!X=)hzu>*E$aN-@G=+L>Z`;+5sVaI^vuS9Y&~XYn1KHTu@)0xEJTVUzz3SnicmB{x z#mjluF8K19S9Fg-C<?E`_N}2deu~EUK9nEf+YwX|NeL}PMBHp6U1^BWX>6^x!3=qC zUrHMPA)TA*$NgQU<Zb&4-Pf$_!ZaG!vUYH4VnK%((*ub<vW~!46LazwvMp?fTJ9f> zqdf|2uS#tl*x2>U4K@0(=sN0)Io(b*v3aBJ&4`>sUaKWxx{PQQ`_+UFZ4sbXs~a6v z{)u#DwDyL4`s~(b*}jZLwLWiY+Kj%mnAyO0V;*si3#46G43Zg<K|Q}q7@QWjo$#+< znn8HnA?9SygBjOygx~BBvd5+VUE@z;TYS^*FOa@0teko)Ug@dWMdpa$V@Nv=kaDKR zkYdb8*)%F{Di6=r8?~1ZTQdWr1H4A=HjMhi)1KnYP(Fpz10Jj((RA{9<Fu86`H#;k zpj})Tlz5jt7J2q0yTy*=OE5^omt?WWqPYj7HQ9xMA4Yxy%G%@8Zpnl|S#eXlbD6*3 z)bV23>cg`459<CorYFAyh6vknLFfb}m`I3rBM}m-DHY7yZ0s2*U-WtX+5kto+J<+| z+@D{JHWK%^YP|9}f28debz&wf7NDIKlg;zAG8^?RM3f{K^QzQ!h}Pbgy&&7+*nzd# zAzO{=VEN45nL*Lc54WH$sVdy+)z|MoS%(qLF;f~3PhM+tdNlDB`8c||mH^S)4~JW> z7pz$erN5c)H-5=5vau!4rIw%YLaFyUHhjh3Xq4?2XfOp`8-s<?0~x)1ZH$1W2SE#h z?|E}lT)HkMN#bb}s%-V8Yv7yqd-db5y-_7(TQt$q;8*;k?BnZx?7)>ITyL3ON0VU( znjVs%jNt}UElB$SN&cH33-|&&;BU{6d{Ok=K6Oe)-1F6q4=)Y2oLIi~%|mNeC|vh? zQG(B?8t~UNsv?wRUO_Uo8ugdsCm1H)^`Nmu$Z5har3mxn*;1#Sbf%Q=(TECAv_iEk zqyA3TcnkNj2<72PdI+j)4aeNu<!JyB03bTV*=a<~ot7#X>+C9Ds_o35nO=sP&*U?y z>29KB58sDzeF^!*Bt<~aKo+EWEv7Zdp2Uin78c)mM$%cKig-=$Paa33)6RR+g+{VV zHLj-8Hf6{WP3|s*O*^bk=|9#q{qZCXJ~*laYDuPD>P|@3@tP#51)dz)@tW+ryWOhl zRo{<Pav9NeH(bo>h92o^|E|>Oyh41L_rcaA6Ey{1fJC2y;51Opn}B8orcc^9>cc-z z)Fz}4)t;*j*BThHKS>`RnBTelek!7J=(CYIpA{I&MuJh9A1nl8rmV>U0BW9H0ItnH zh7^Fm09>&_ed$kR;PpoyHfw1Qd1KKv8QM-7lyB$GR=vJLKTM%fK@3bJ)gCCjd@k`A zZ?+OI*J4UYC}ZiU-&sqYh6j};p(&vr{0EnYExy@o+1x!->?7HAc+>LM2bk1J33NUW z#id*^WkE2A!?UxlBDsM6TwvP_fXUb)B5{*bbM7v5-T_ZuJnMS&&F;OgNIFT$>HG7Z zYZ6-+I2e$6)<mQJpwSa^0yK#pDi(bqgdQ)Pa(+5Qi!`<|-ei!zZ0GWdI(ZU*DC8f{ z7q%U#(s?c|op%Yx2%S%(N%Lq*SVdy(yA;Y*jR8|5U<KMOYI=J_dkDWNw)K75l%Z5* zU9@!b+3)L7={UziZn2jJ1iFnnXx%9&Wk2a&w-_%FO2phEm6s6{%#+!L{>%Z(9(Dr$ z&}xYVvu{nF+Q!~nn$;PpZe?$5UMqUJFb8*`h<E9ZbsYd1Q$QRq(BfH+sPC+6Q*9Qz zIDR3b2oYe?F!ws4Iks#YyqS7CG4Aa1hD*{Pzke-R4uoJ~fCRb7pCn9ZhJ)ELu3(;C zk|~xO@oJ=ps`5MS-ULP9z*Oi@uV`ZW-EL&1g622bjF;<8cgst^1{^`7QI6iR(5l`| zx(Y<Z{1~Ro4s!t*=?sEIZ<p1Q(~P{?|G-gj)8Lt4PwkP7gX>N9--m50COZ(L5|t&C zFfLTbb)+JYMt)CH?M1~3jb`pgX9O>xH`u^kM^OuAVquwHXb*2+9(dzt164G9m-SX& zlj0czwkHT$QL4z^rDaHf#VMg;+Afo<3Oq=9CV+9lYC2W=-6;q!(ZZ=GF+4qEK}~QO zk{f9E%(~SxaWMSpcJDfvXm$#kN}-AFz#HNC3I+gkZ=`lmP+yB&OkgwVm@V7h-iEj~ zW!{pH#kxET?LNl%SttL?@e<A1g%RLxFvGT{bur*@1ZG4Ob)z_19+2&3K4jgU*tc%r zO9COd{hsUltJwdjTe>a1_?xK$If$wqjBS%Z4$mn9HVcrm@Ejfzf0UA$2G;oUJA!zb zota0VBo;36b9{VR_?^n)`%$Av6)W9q7A@BC$e+0CLJYBgp_i7w#emQ2#*L$Gmx1VU zGi6!H)SK|UDI0xHSDu1}+oqUJ1%>h@MlZoCnxf`^c_xGRFzXb=xP}^datdmIP#0zP zeqa<)^RpI*rO*S0Q_!C%Tfhe5hfG66bdkkme|!72-u*FhcSKnxP!1xyg}3?C9Ibzq z^gZ!>lS1nG*Ei2bz@z}$ZfC;}hCv1P2Ki`p-$ar&+YAcc6;OfjFmF_kiK#vI_lH06 z(1>=9n+o{)J?6l{k=Nnf{t|DQ$OBvBuU>syP0$CG@1DtBEmKc;P`%bFwvtMnz|`?Y z9P<If<|Ng)J$9kBX@)Uk4W^YyO}d<)$zvxtFgt0Hd4ujwL6~FXD9FQu9DMSXDuNuN za#Lpj-vtYHM3=>#!h1#brK!{0-)%k<jO;`<-#ln7`7JZpCPMuIV{79Gu^6XG@nL5X zzFj#|BncMJudvlR(`N_Y%P=eVJ5%jaC;wns)53NAL}iS%ktg7<tLv!OndM(+mHTGC z?x70WTt5xLWT_+28m7&Ej#WcoWBz6Qc=;4k#QffyPT~y0_l^oxc39xn=cm6-ckGK_ zbH$z8)%Hyb?`@zCf<<b!r%mUV6Bg`cZj%_3oXheP)76(E9<K3~rfQm}=^9UWylH-o zxcJ(wIO?PH*QOh71JJZJ^p|_sPJdCk`x$-{1AZRAH)*i-iu!+7ZTzoa^9UB)@VN^^ zQlqsV$6AW!wf4LA_CLRMaqPQ11yRfbf1+v(a!CR_fG<7)!=<+@@T<0110JNXP$E&D zq};xD4g1&Upw||(ui{yf)-IA7Z2i##RkIv@RC8n<Rpt*7Teqqf4&3w;7<VgO6txO2 za;}d|UfW^XyBGiE6jWV+!|E-E7?R{x;-AV^oFq6U6}rV5To?}*>3goA#?SS===fDD zSckYD6QvaUOsQE|OQmz_WtXSN`7TzyAxj-lD1#R02jK5Z$eL9Mq&)D*T|Kzl-!wOJ zJIC~mC*ROcpUl_5l;)QvpOYg#I_)X_H?>%cDY@mOwT1tf7ZK5Ji%O8C=mkh&*>10r zhv6@Weq}y$8<L&Kuv^rv8ww<OJ6-5{-YG<$1`-wqI|d-+6<TNW9_Vei-7yWoL+L33 zjYH+VZv~%ix9IzQw>MtBSUWQIHc=#TW$6=pA@wqKI0)Q{Ny4yE=!4;3XV)=2QltM2 z4}8A$q|Q#}o-ZwOzp-&-slBQ1+jdI;wA^|gBcyrn*dDP<aEK#dVvBt=!5kP@X!s!B z)B6rbpKKF<T!sI{h`;b`<ntlD{DB*DYE}|q{Ni&^I4atK`6M2x6vAvVwX0K!is#fX z0TLXVM{vI|B<pDWaJj>BsEgYvC@`p=ANTZn|MQ2n?LQ4sI_%9DH(0VdWMhyh(~aY3 zF_6#FBf6ydmOAvhf1ThqWPP@LBciJK4XIX7;nh#Ni@x^!QMF4Xi)g=1Gr6rYZp+&E z)yIuGX*#0x&z>{WML*Y(dL5{IC{4<k$8^DjknPawS7ycV>Fu8F=@@(BhI(&&rcvR9 zrWx;O`p!D%pW6yMlXkZ{q1CBRqCVHs@eXU=B(y^9ffb_T!gjZJTn;aw_jNsBPH~JP zor}oB&RrYDPf&&X;4jA2os-`^@yN5+YQ?^YY_x=5$y_$>YBLtrfj;)=fIfo&S1@6i zrzk;$;!To%eeAxLX-~kFII$$S==Y(`%&qak&55W*i>s559PD}<yj)y6^E{tvbke$O zdCEniLzXXz+W>ILxj<}-;vI}@ahOwSvl}xFzIG50-M#ltM>RjGw%mGY@io$xasrGH zyB1tGA;-MPA(+@cI|wjC;XM(49%A4I49Ro05QFz-gBxx(`PbM6t)|`@(de9T<u_ig z#XjDU)&W=eSto{gHYbqZ({8XpL{sp?bR*=&5cQT+f$u-6=HST>d~)8uzEFF(l8+p| zJ7s!&jrzNuZ)fdDEFm8n5pvztOSP@U7aXy@()2LdXxFP&KOW2Wr}otg?WgVFLNpgm zbKc62r?ulT+KeqVV_y51xO&y`qbD`VD$!HVHf`4eU0wXIhU<Qr6ixUZAs~@V#VEDW zA-im$Sm;dsEg}qSszh=^vmn9!gcPCTH(BNrnwA95n@dgnmRpwy>{r{rcFQli5h6LP zBzYIXjE_mK-8g3IFDgB8IR>AAivsh8ST0~<t*Gb6l^ZG0Pix~=M`^}|ZjG;oS5COD zEO}HrFTQtq&?P^r20BUnjFAX=fS=i<)z!ctait4Qe1)*?gbGt75drw*1U&A{T0s2~ zG^)ZW#AA8dE=m2@nKBR7RQ2f|Qhu?@_D2PDf%f^3Gc?j32godKW^}cR;dDk?n22qP zgyt+qiF(@;YVj9t_(`s>xKh1uz6!UIWOn}RLmXmP2dqyW1J|0T9bW-pT>;a{F$4%V z4CumI<?s&qC9%mRZRMg~NVpA|{Uqvs<&zftuz2TdWDZ?%8xO^o1jSnLh(fIaWs+3; z%U6tV-Ger_W0q@W&z+I0Q_uc6lWYubp4s{MZ2@|NI-LoNr$T8xsyUSj5bg-V#MIbr zM^VMb+9Y6))-#o+yJJ(IHa&RlfhaF~)aKOcto^*>_Wb5W0;<Dgn+gR~=UpR1R8b3< zn4^3cxAw)qIb5x1y<uhcvnQFIzRwRhO}_}wni%Q#>$83B<GK0zk6&o}9j3Ya)=PCI zgcRTjEFLTrV)hxZ!&h{ku;8~lhl+rr4jhaBOvz98`he@%m#FZ|!?GK4+q@EJh>S7x z%~c~(i~Bn}9Uy>dg9bM<fKPH-IBAk>?=DCT^3urOKrq%pfy5rI>FQsO$iN2O5Aw^! z*?y?$7nC~IU+$~_KAfJ;<b3Xq6a8K=UaA+vPVpWOafRbonj2wf)`t-ucN<f=MdVOC zmZnOU-2JhXMXP6?a{^~xeth}vQ1bXj2qW<`vIkZ*7+Hg6Mg;577y>vh))G;VEpaaD zaP!_Xm97ZUt-Gt~&eFkSIo&1VgtyG{ntRuH>;rtAAU6Y*q~-O_qt@C*?i3d4uO`u@ zuLT2*En~`VUbS^>sm$?${}>8fR4)EbXM7R-RmpleqsMzH`W$LLZ`!r9;ymRVU`Jq& znG*vLIm&IsmH7QBzXX_&dzC|<>*b2#AL;yMB^F+9J~<*v`z7b!HwK(NvY>D$9~02D zp2=m_WEbBPMU3gDUYO8yEu~2UzathNj_jc?z@dNFd2`T8P29=@4NZ1CNg|f*mG4^$ z-`FjJj=aeQC*^IT)E+R)R*O9ej6Dj7QTk%}Q(7r()?L1&q095!;c^<i#vLw@?DJ1= zrV#W!oFTfz%Lx@79)Zq`jZYYJMO&x8{;?~qEDe`9|1-D!nP_R(#rZb_A+*Ym!JDX$ zNyfNn(cfzR-2!!7z$FSD#Iy+yezEJRzc+2`;C|;3%+AnnD8Ir>ygvK;<fq6v$GbO< zRvgAlTX^xo0|tu)b=mpTtv|6K+R^4*mpu@}y~8_awS`H%bB(AHJ>O4jO-e!jxT&(0 zmei@dF~`Xya_lWdqfX7r+qWzGnp6%|HeJRm`fw3A)^dy+bSh)sA<a?hRfs8x8`eCA zRQJHJhWPVhgA7yrW*v4`!vnE*Z;j~GbG~oEzL$-bme6T7K31eMtA*l|yvaA~$3nmb z2y~Z_d~x|&6{_=k$*i6~Q)GEwb1F-#szo{jCyf^PsrcT6&%WHJTI~K~u<3tv48eNY zn<7k8+$qOU=P}2xD@LwTXoPlzKXmyUtu*GR(dfJ$c&FB(BWHb{`#k^Zi+nI(j2k-> zwI9R0?=6DZeN;=_j#j#5-Q4<7(NngAlb44-z{UB2KEwOhpbBN+pW~Ml&6D!|P{Vd| z$wCSfkbVj>P2Ca|$4;}Y#3*ab@Cmameahzf5!P_HAW?krwF2`F1dxMue4t7Ls(8MF zQn;8biM@;c9AaAQUQZJ$+IHpGO8B0K<{cQe4tu+EJiu7smTCAdgJ%&~X&octsi{ne zqiVW=1zQ|RG5Fq%lESsjvPg$3#1L}EL_kwPWZkt%`EO4m?Rz9Mxi9bSas)cnygxLH zYKs|}1DzzH;OtZMy|zkVR;p4j4bV<o<IqFl2jjjT*rumB4Kt*hni*V_c$25AqJQx| z-8F^h>?2Si3>*bQ{!({I2&SDv`m4=VNn$&KXNLYN^82Re^ZffS{=mcgo(3B4qePr` z6p5~zs>Re%Xr<~#bw1@@3xEk;fW@^bH`7jgQJ8)6r@BAueQ{492S4<~$t!0|);6T7 z^cxYJ;|{J!J>N?b??qKjY|si?K#vRqY6&!Q67g!gtLYYVnT?0l3wNu2-|INJ*+0>$ z$s+?f0dIs}CZ;HH1W!1T9H!kLOq3X3rmeuo*Inw@d_JAX&zSC4l9#iJXV%sITbDl4 z;2Ha#>YJMKVrp-~uC8^x%ICN#!r>ltNW)ZUk^EIqi1tZhi+wpwiOZ(!&Hs=FZ#;jZ zDSNb+(Iz&ssNn69@DS{iY^cdM*ChgC^c_Uf7*OK9Rw!8(=+pi{(!dX<)Ig%QUWX<S zB$M8c`MJLN&2Ji6KdW3fE(vmyT@v`Z*~Rm%ZM>u?x&^~@U_W~(lSF8J2Z6^Opm+~v z^p`h6_4IvF=cu$uwSemyQ0>lPov0b)MtEE6Nz%^0{<{3?u|NrHa$>2Vjk%zW(M1k@ zzjyst8rp2U{0&S@Gc{=9LZc`8JpUJK?-|up1Fh>uY0`TyL8?kqX;PyiO#}o51cZpF zlnAJ_AR$qaULqhMAVivo^e#1Ylr9KJC?P>Wnk0fDkPz?s?m1(hZ=bWzz2lZ2VdO`C zEM0BR`M&QnuOIu5&m(vJqe6ti(t_U}>_!AJK%kP1q8@Xsy$!7l8fyB{1f{Hb&qR*g zGc88gQY$`f=r*Fb_99Qu`MrPhN9}?4fc0)m4xD}MOv=cd0MkY3&|XX;Qk-gfpLy}* z)OHZ16{S8gziL&srT}`?{p^d%6XToquoUzFp0DG~aYIeQcZ6th7Dtj(-#N{N!ANSs zBoNr-^)#$GyL>J$eUffSl_sF0_5<C0p89V)u3w(t$V@X@Eev6!?=`=!FE?0fWVHcR zHolPwe#aO-6nZ++QAKqA!z&G&u2hVsxd-L?DM<ZlYI1Oe^Pu7{^aKq_ITd_0mHkf& zASuaY$*W&lg@}qbG$o+K=qJX1kkz`gN-_yXTZhF{Z3Y?B2Cbj|eD0Va_0BQ9zBJ@_ zh0S~a=_#hwF>d4#RtzCt29N&>GADa&%@#x99Rc;Q866Z$z@1FjG%no*ed;suIj)}b zA{RV2o$+jtyE}2vx^kBn2;*tUeeCh~<({w=(thVq#aZ_^`(Y34SUXxNI|%<#-A4WF zJrr(;Qqy#l?boJK{M|cLMxBiBRlEMPLzuLus{%VJej@L4FRbKFH>Y=@S=fEt%1y+F zt;-l4z(}-IRELlwg$|q~gS(~yM<lw7m&cS?maBVpCg;Xv@SIAl66}Uwm|{iS^F_E~ z)BV(ikPG&lWlR@^3^iyV_)I6`bVQ(O8pUctyE&L;3Uj@d%5KySpf1uKe+*`mJkJV_ zGH1;*PXz8Z2FxRS|AP2`G0rLXS_VUBAK1q7FMGvdmfXHhi}Hubi=yTjk9wi4G<@L7 zdY>f$I=A0<2o$T)3@K_HDTl#lpb@VxQd;hlk1#zdt?)sYxL$hvSa|!TWBzsF*DufB zw)t`3v79ttplf=BHG~zxdkA*qfo?GMGF^>~anjd~N$il<glF1jZLhX8F(xN)(^?H` zTs-$~RhFF9yZJcv(XrO$9iXCFM)#pkxKmL;iuEWDVfoJYs=%)G6q3hRG$Yhk?5u#P za;&oytAi|G7>H7qi9G@F=C<mYSl0y$7$3JSw)KCwQkzB)DVqL$(a9sO(D)?odMWN^ zqGzJhFrEz?fQ^N4ZXpfn9@7YoQfkxEc2l2gg{*IA-f8dR39TIGiux)8tI1&vsm4vM zCqt(-=Q7l(PWK-ec_pFzT`?~qjbr@_jzqu^Qp>G`;-IUOATPEw8ZTAClYfg>t<JVb zwW$hh@anJHc*ZaMw&_iJW;{#{C-72D7?R#knMptI_&mKQfk^Su51=5k4L@a^Z=@9e z_$|B4F8YQh%Gq3#mhM9{gfrQa@X_^fL+&MN5SnG7_%A4?-1Dnn#@wZ5>p7+RM5XTv zZaXoFrzPj|tl_qC*rj4Wnz1j^cmk;f*8y|D@;FFS*aW{jq{eE7d}Oa<s3_DUTGA;4 zH)`9cy>7v*AyDc=Fn%E3NCGBUDDSZZ#;KzM>;rr>Fll``)+2pm!2P_8Tsqx|xE^fr zD=105o4E12|M!)qCU)iQX&(h>`-@9T0+z;p@4%ie2t(3QbaTbVBk!k%`k8U|r~ZV0 z+A4JZ;}FO7I3b29D4#F=`j2h<i=E}Xf{bCH4-X(=ZAfMfBwCjQ_Qf7rV@rbNR}}1V z@obo{Bjn8NcyEsI8}%tM=I7JRSX=-lKXWN27ASNyc&I_tA)-ca_-q9NQqZtNiKt3@ zn4q?@y)cuhoB|7wJo(_(N=n|X6!{ROVH%N*E_{4<X#fzol4cgqQUM<nAClel{g+U} zf`*%ZR7UI3heh`+idB!FRLR(DvDk2jpkP_~q~d4B$u(5zrHb=CJtB>ZyrhQqsuz-> zF((tQK9?Wo&A2;K@UpM@_iWmJIMPu*zt6{e5y*NO5R<%IC->Zx23*MeQ4M~V7e_Bt zHfVB$Jpy_Y38<Q}!=la9(jBK*gw9c2oAXEHw2N*xUV^UONb;MBZ#x%8%$2h+w3aCg z^JA$eT_$bt4IJ+aIIYVW$<jA`uk6^#epnrKhuqWG!A@?9F+9Cw3mRIs<%hp8NGSDh z;9RfIWioAyGIRgUFo30|4sHpE*^By|coHI~3F7%ZNnk{JEW^eGFBSOkQPI~MlKVFu zl1H`Mo12od3Zqt;!p#zYIatby++|bBT?X8@7(qkjh<8-9`2_t^{zgieZgxnqkMu(E zd_;()(6hoSrfBBJP*q<n$w99kJv-HAV=UpTUy`)lp@fdogxg-5_P}gEt#v!lJW3{i z74V)usqpc>g<evItuoi<PfQ(tJCLXm2d-~QWQf3rx+J`!fQP!Zpbc5TvKSt_={V`K zX!%&eTvNNDIeNvqSxH;qBzO9&M1f=L#=J+EHWtz@p&0*SkCz#4ZbAxqmu4EA?{jF> z-k9|y?X+|H_E+X>3ic+)v1c#nm1AR|wYuHt$bFFssud7Z#&Ztcn^E&WG>=i;%4T|! zV*coQpTze0BEGWaomfxqSA{aBG;7A(Q*b9R{dd=LGcli1Cjxn$#?68K%tnTMb3;RV zrE;oR(80r3VS-k&wIP-dxW4+!xG?^V++W9#>@;M27SB^3zlS$1Q7}t=)T(#BEtN6c zJBe4aqoPJJB^5tve9so=C*xSZIAotL3FhWc6<f$w08tXK-|LoE{(`z`0nE0f9Kzd0 z&e{(B+>YnUQCqH7FSg1~f3orveO<d9D%t(3r+Q4OQ42ELLs*N}8ZuDR?L=}-ZtWd8 zXwSKZ`w8GqRWvZiUe1jD_)M+4_c*(m)F}?03ss4byBO*za4!u%OCyxKpCpZBCUu-e zpqhc{R8&2dYMIArV8l0Ao3*o|b8E7qqM|rj!9uPD76-a7S@ddPT}BhAuS#r5GXzM& z%8aq}HRLI(^1xH`X8{Q5_pr+wMprj)WK2~k*0jUrc2lhk^3TV4L^bu2t1rb_uziJy zp}cHk@byMX=}kb!ZwW6o=TocI_!u5(+W2ka>vzzI#AqVlE0BWc1>xyiw=Nam>Vd(y z9H*zhmS67?V75px6Lv8F2ZR>Xhu|gG5qbNoa9|1*5NGOo-DM^X`3X=S_|x5f#;Hg^ zeHRHXV{hO#wj|U(&s!a^ZG2<Rsr@a%SK)Vwck=oxxy(NnSRn3ro>T$oey)9x6JDgI zXU59ZN_^L$R(3S@47GL?mZp!hjVK!Oj^nVn!!_8HYAyAoOe@TpA7uQRto&RHA`V^G zb?Hbd_HA-u!Be6$wO5J)zr3H{g43za&(D3SHFw*LZ20cQJT($%QcE_D3wyue7}64* z`{5#G#<A&~YW3~j4Tt5RI}YiuU)_9hLP6pHImzG<UDl9-yYCKkuuy@?0_0_e@kxEL zDK+gl2tjU&ki72audTwZsHWhWaOHIe=Ypw9(fJFBr|iGA`2oG8)^uh!R=_ZP2^0Mo zjwSGROSa}f1mMvD{7DcyEKD3sv)jwjsI!!w5BXYpa;>?+Iam7nww*jE9N!C_^(3JC z{(?BYao_}`6kvjq(1_tPEm}Xs#%yc&1=XMUAabHODMOau;nA~4?}CJ9{t2cBylB%c z`H9oPcowZoSl5R*>gZfo6`8(nmM<TFYMkYY>Gh8vfs@9{q7j3*<V76g{l3wH=w9u) z(UklPcjtsapIo#V=$YBg$j@WiA^#oV^<VhCR5Ac_NfR)l#6SCGXt#{!_c0bGZ5Iv* z9VQn)s&?(2ID3U_yHmCI*e}?w6#>8PMzW>EwUC|S0EcJ*e6HJAHm&!tqShP7o2<5H zt<>MI^2PqMi<z9<t?VfeltG}TR???vmYYm}T>dBRB?3=7wMY%LJHi-h>%MGzTuQej zZT6h3C9CI`CfTexK=pp_JOT*_`+a%)h>vHA6!Y(HwG7Is_zOLG=2XGEcLe|vu2Pc{ zOJyfuap<L(xDGJ9W7=wr2VUE^rBN7ftA4TKg|sBqO-$u<SI?=Xy~@#e5Valaft7@N zQQ`pkWG4|NlMmP-G$N-%ohTuPD^ZQ9HyrM}hPw`xT$D>MjJHI;-8zxxaZ~aQ<}H#P ziGy;XJjT8|Et|(MRIW+_7^~PnWBl_#Z?3CjZ~1}RNTK|KmtW(!u}?{zGx}H_f6cdi zK_5H`Nk*|CjA&+b8Q?NEbbb&(*CV#F2Q6G?dDTB66v<r1;}FAq_UA>Tvb6{ZgB=ht zgyEB&P*QD&F1(QF^t?lSBW2S?BSvEnW?<IR_Ke?0?Pyq58~@5?MUqbw1br;^3;`oy z{y84(Ql5nFbJYC>wtgI2_bLe)7f^w)p=J>ScotyO`bcbPWJtF6J@__J@pg*#@P`U1 zSmY;Zd?=$6+7MDfyS9$yqbo0qlJXje0nyoQE;{+;aQ{m>F+^9_9E-||s+0CR)nB+e zE%`%FY;>MuW8z&F-3lWcbV2J;$;L`_!5JhtqL5gL@$y{e<$<r+G&fIbJg9p)H@DEE z*2>QRl5G$kU#tHNF6&f;?1k1MF*F6bq}wT<JdQfDag*LRx^*bQkIx$yQivS<a4-40 z=811|1xtKIWf!if-vm8X%2|@sV4-sOadtblctzc@@De%gbtl2kQ#A@d%%?sDX?wB) zpSS$7ru{qgIZ}l&1FhXp3i4wkLV?#C+MNg67T*aU=yKIscra`!S1=M@V&N#qYIW{e z?AI{0u1Zk`2NRiR=n4==P;XvtMWMlUE2B}O6jTgS6>dY?G!}2GXIXH%S(j+VWwmOM zn<=uCGM4?0D_o;%4Ce$e6EL%(cI2@{^&kx#n^`<j@ZBbay?*y`Xyy0%D8=TCZ-bt@ zawnS<+t9f$kF~ByYdx0Ayb+%ov45alwd}v9eH&u*R)IL<*Wt5%NHGSSKXG53r>-S6 z9J`?Y$cC-7Q<<c7cmOahnzjhQvnh{iV|Wf=f5^_@d-m5qavRUsefrvViO~8pJ>^08 zU3++u?YVE_@~7V}Ul<9(){Jd6kX<Qv$Qh;Y;W5kZW#k)#4>kNhGdkoZm-QK0#(#*e zD|*e=&zpnU)Gr)E-j}$UtE?Vw83aR_RZ+kDS2#FjrjjFW%uV@FZy(CUlOf{3oc9WY z2cdaXxJJD}tddyo5F{stjJsVDX=v%5K6oH*8ohe`WXd6T{%!{7_!G7U(=#IyEoblD z0Xp?dY@f>4%!&j8t)UL9J{;9KzT5`h^cY9mXhc{6b*yK=X`;cE+r-LQ>E%M#`8I=s zl)_g5Y+#i_roAe_O8eruH&hf6NV*H<qRZ9SxS6{-HGOMPN%+y2I{N*Y_{oL8AT@<A zlAmzzmRDt~B7q}4{}<%JD}hiO2e1M32PEtq9pYv9H2OI+ZV>9@qbVX7Q}2B3;k?<# znE1fh3-(pD;-QX`$$d=yu#8H21yaVlsRPn7&$sAe(RircJjx!vb|A%5bWsUK343o! z^6J9~gjz1|h>Qs5Ty+c5;IvfF^)8)NYWdvq<}lscu5LJZ<Lt$Z@uJ5C076CB!R+|+ zPEd%@A?rP=MyHE%PZE!j=EaGiZBbivdQ)xFEzhx14pz%wwn_~j3SRy1;*nr2BpzQ) zV|-iGp?VPK0=Vf0<SBd)tlb0^)fOm9w+wED{S-KDa#iiuHO(tuO%(ztVXW6nnL-FF znE=FL#Ont2Qki!KPPq%kjEQx>F#ZQD=)K54uC|xME#Ko3G4G`Ies00!zVvARW0i}X zRzY%?{T05yDmVz(cMv-E+jcvF#!6kI<WsxIOwh@;8}H$cDmzh5GAyK|AEJT{zc8rK zP)fpF*5!iOlnG9YOGyiqI2+awj220kF0j_8ud(ez$|OF>BGpkIP#wHT-D6I?Mes`x zG9vsBmu<ttVOcwnx{BOFOUc-)BIvcWk*q9x$hgEQrlm39i~?STgbaMG#&fI}TFQ6v zSPr2hF2d&{HM3X3F&}<77T4%jS)!At<~}R`T!vb!J>DFWDz^K>Y?5Dm8A4TL#V%u* z{(@ke(<p9)=dwkI#s*&Cm!VN*oVuZACC**mS?%R-qk6Pt@w3MJnOhT4+4J0qJmmdc zp<^VQI>5S{`i*WyLJt77d?d+$5R?4J+T`jKLZg6c-lH@AGuvc6v}Uo#FZ4s7mtO=t z)4m7%c7^}0B;wPp{%akjO98Vz#Qk3I+<wnrkeIO&<XKP^58R{+7afxihxHs5FP11q z=Z6J8oLn#(o^I^6QxGB8$XR3Mw*B6l9mdClNW3^FN-#OEigt}|K<y&!Gx#fR^vZBf zYD0Jzy^UqRJ(yH&P?6kG9F7a+ZXfE=y5V~H;#vI`&BXj3r&mx^mv&p&@?VhTEVZ={ zH}kT}(0ti8P6C|R7RFs(mmq1aawY!8dvD6g{Dmh1OT9a)ixz3;n=*7+zyWp_WmJ}+ zvy<+1M{OOl2<Mr~`qKJ2pv+k}79>@)*H38o6_=l%UvO{euJ`>oaobwVE%CrYs7C4x zy^4mIL+A#~<=9UnphWyExc>o|W6t|D0h}mvwy`d)OB4y4KWgDTt@eu<;~noUK7N$7 z;E^D(eaC6<YCMRZf0V2R22MRl>z`<VIhk!+o~C+x9n68aM8t?}0#lNW{u6)H><_JC z>!+I<59}`x8k!>pZ#{hUF=r|ioR4}CfGb=I?a@GkCF$WrG)|N9^naL53{fSY)wIG@ zPF0i>U$?$j#8a}wot{MMa?L7r%oaR@r~|zqgrh^7TD9yjjIYOTjc}v;p<-}rjq7yN zdJVQHEtKMF(}4W;4J%6iO61BmCQCnl69uzPz_SBlWk6D%4%s+|b`3xy1gVi?oJbmx zBV)as${7Pr-{x}?zP!@;mZ;$PfkP{)_hrdNl<CiRyn|Jex}9kLMT8{T=r1T40ytX0 zzDN-19Eqo72`h@QsBRmdSdb8HY_ID`9d&Yzr6&~`z2eF|&%IeKI!nEcKW@kwOiBwK zzycOI%ewKlut4CXi#o$^+#07tywlWkf&)r!Ih*@`^!I4YCRk=~x2^piq8F9hG4kv# zg7fmUsjZ~Q0k9a>M?*+s+nFTVGlLPL3wkVJS$(rZ(d9@y;WMG3ZCCjf`wiGpC8_1W z-}T{D6L}d!6$1J>gWU%!%>Yrep%TCo7}6o(gE>)UI$e(dFNbsHy7vCA#HgNrG~)+* z*z<5z`8OE3J-mAN^GAHO&~>)efvr-Si8r*aqz4>>Wmg3Nr|4O)%K)lobtRo{T>_`s zw$IRSlngxDVR@aQ%YT&J+vYFgGeIPvGZ4kGpCvSuNi$tLvuiyqS_~FwETo$GP%2Np z<r|9dz}Mw{WI4RAe)iXoHk~AoP+!W(lMb(0$5pFR{<{uopH-PX|1jb~k=G{G>aBGa zM@JVqtqd$O#AKt-Nj>U+$6{*N{Q(4G199a2FIeLLz!WpZ92L+Z%V0se?3AA&6Cf#? z(-kXL8uJX@JdA!N4=dPrdlOO=R&@RD2c$Q?J<II0#um-EK=-4{RS;0IU{TakuDcYO z2ZIWxY-$L*4{Ik}3D1&dde?sGxuix$3A6c1nRHhYvTSCxD)yg1k`RK2n&4Np0j+~m z3-1$9{P6daZmHcyI)`fmE{@oc84~nFrS!ErS4%EFYbhYZ7$??0BJK;K=~8&#x*@+T z^1Xr2T%tyM#S@*#tkLJ*;|<)d4Xf1-UprTG?zC!e`NdRAZL-t9%ke7UIk<#b1kH4a zFb0sU;|R+l-IxX={ZUgl>0cs*J(y#jQ$wAPQ2K)x3;D6HEQY<9{{UU{|7yj`vNIKC z`JZ2N+}T3SQH3cE%a0t=qfMB;@w=a-U1aoRd-b7ts3BlBcoWcEvHpRwH4JB~;a^lv z_fHEx+Ef@aN}hxTO14C+sNVZg!(t^6(H{>wh@?C{N~b>t9#boZR%GmDs=;y<A5}+{ zYD+XuDl*Qhnm>qBIA6R_!<AAUhdyl1hP?5(BrZcHr_S{2V!5>~5XZs@3y{7EIrZGY zO58|bNoT+5;)JPSVTU}vo(-DgZ=>mE1jo{alzNEfv5<QjVm~qLLA&A0SV7nKF&?@& z&n5{MH;ZcPr*5;TZ<l{x)mf>H1dX!|qewP8F^7LabRiT_)%9rzBFCRr#URg7Iqk{J z9bnS^`aJN9v1>H#1WWGzLLV^=1!U05l;Zg;ow>;Lc@Rx>$#(02fS=V}@+*1HkXcW~ z{d_8LTPNKk^ux#_`SX?v-5UCiVLEJ23KbhG*)Eh}>jpZv1u5QCaRLMce*#v%LW<60 z&GbDNDcAq}TGEW_n(BaIouFH~&vwa|tzQSBO;(5EG_gRMmAYTm%#N`-DS$2<=}I+S z_A}@P*Q2|6Md<R=+A1HmRNG8SuHg2gg7u30QeL(+IeKTC-8-)1sItnv@(8vqalfxV z^zp+Ct(5bUuu8K_pD$2k!QE{Glm@Ce5sSuiy_=v5lMQ+y>~vEPpfmHS@Nukhi@xUs zRU)#Vt-Bcd%X?q_s=5s;&u+Rz9s10Voif<3sjBujm$geT?HVI-3XCH`TFQo&)97DN ztw<~Fs&^jb8$yv>XF}p>%K!ddGRa^dPqG6Ru&s9`wk*InZ?jqP)bQ3%$8*(Zq8C!O zr?CPEqwwXSDo&HipTDWu{Zks1T2bwZ_)GpjUS{Qwk|p^rKG8`%!6rNH;Qh%eU5h?l zcKAoT*v-ap8ukSU?^K!i#-A#;e)0b#EdBrDx4e0%rT5#g56F>_r!u8w^WJ$f<bZ@A zZZ`Mk=)LbXlm5X5@LvU*FSuX|rpphQrIUN)^{Nz)-UgwcV`^--OO#`fqSS<L8DSDQ z0U>BySn3n9C~v9N_pL(1uORxKv(o)|FQ9U#JzhOA{_5&#M-z2`WYrBMJAhGv#xj~` z-S`Y?du~AWFr?VOZf@{vb&zUO*O^ZKUn>1r!Z@mS|A;Rj8cdaop`T*<3Ff7uZOISN zJo&{?=Zz3i**E@vO3wMOk6${oVPW{<g3+a_kt(Y04F-(&s0+1!5?X-b>=1zmE@7V4 z?{HGBOefn62n#1A4Ak_y`MKLa*44d=y#T5^cbEoE0F%s7pf2+607P_8+G%+$se`NX z?V-JkPlxdImR7>T{cE8-USaC88J5EAvL_m!xBXI>(uhjkH~*zAOwR1|y9#KW!AI3? z(xf$$qj!d;WUM*aJ@<ok+0RAgj_RpkG`Cv)RkH8#jp<XlC&P5+Ugz4ZWnFEw+okwf zUiuF?@!!(ozrI6_k<$>;HRwxxBU@ZPS*N*p19+bQd1YGzAL<buDTYm(3Vl33ugv3M z$u#T)@??rX<cXh7diuI}%(9-ISY}t^XqfIWleLDagLWsOme{(ifRR0BAnznKr_{&K zAUDvVDJh`x<atd~$rJr<DIAqVD?MiNtHLipE{duW(}ho71lq%wCidU{K%!CncRi#S z0_485pV`?KaE?5G`8TON%>K8Yrxt4OZ9l?GKpq6dVC&r~-n#3PpwVqkN4aNgy_AYQ zq;{QKs_%TYFr$u|lTuz;7z(KP273?M!(aY7EK@;L1Y|@zoSsU&TfOZZ6dHQ4xH)s9 zxu9)~QiVzYlz&cUpi@oj+@*F;|JKW%>3cwUSXFUTH;bbl0)QaYry-~0-!i2fEYko| zVOOuQ=22?L88}lnlpo3N%U~f3>0*7zmAPtr5-)Z2Z>X3`_vbv8e75z#8O)Ra7-YQ` zc5j9)!>Mom^2lcK6k}QHftLv<J-m2v6d!ijV0s6kN-ZYrBw=~#Q6d2Cw|)j7DstXz zo7~yXIX8c0f%k%J@+HS(uV0*C=6C(mIhjy5zhiCb_7HGAoc!Mg>;FHnYNSvD=)^{7 z-F|objXqp*8qvtN$Ku2!?x#!OhUixLMpiQO!H=#x7S}C6Z|_JPKnS*U(Hp?zoWD(v zWf;T3FfxsJ93BXCYyr>yNMF@GH~)phFGbF6v`eVgZ_wbpRQea%3+!2K-uP*x+EKpR zj-e~<3cRpWKWZnT&5aPiM|J7xyZ$pnhN=3+q#cc`;5&<B)=QCnmCy^pDJz2>Hm8{O z<N;JmX&J(gs!;$hb0uX|EV-FDTRza2`5@-*Y^D^PFyeIOUTB>C<;3S{!?>^;&`h8c zGYyyxB?N4%c#zG&ae1ty0N`p!GqYly3Hq*{H}ylev)ooL<MPT)z9Rq5(Z|pN0G+1X zn;S~p--=iQv_JIq2rv6@Te&k1;dZ{bk=hYCSE$&tW88f$eR|hHG6A5Vsv!UwuXt3S z>CQnuk*xcwsuvTJ+;#KqsVRSU$VENv|K?cfAxTmmQoU$;KA|B1gI;)Phi$GcM?=tL z@=m?a?ZCKezT$6K!HCpj(q-5x{-fmWq9$_HfTx203uv4!Pt@zA&7<_<M6}&2^Cj5a zM~?rbnE%Hz1YnkWMrH12(9mgrbwz+^v>;)5KjlS{H!wvq1cAONb#NS20AO#_OE9x` z>liovLhY2XF13I1v?4Y}!C^v8>fYUmOV1Ozl5128XM~Csg~J|t#`b>gnG7!bVx|&; zvwYf=zd!W|Dh2U{M&s*j(kS>?V}Ruq={Fc)yB%RK>GTFwo!s@7c1j5=h%`WT*#MPs z0Pdsnayxmus+*VR_C0m<QfwoX<)`ijZ&u`=FR>rr?uiNSGIB}0J!fGzd|RU4cF0Xv zVn#lFYbc$&-tq~xQ#WWkGH}}|9je#UV?i7HOpk$(2V%}s)(OR`S7v@|gaWCy5a@+n za0Nsdvb4fGyWhQk14oq`B8v7UeEMRF;_>Fm2p_mU=_Xc<-9A&j_j$FAZ2(Vt9NIr7 zdUd%IbDS<u@YXjCB#!Y}BFBD?aM$+UI9gcSgvxatcfDNGpCBRI{V|b6raRZ&?b=}( zRW1`?eP>6U+<jV6&MG4`vtOnA7t~nQl~=W_0r0xFlgQ#Zp?$V&R0&<$I5n{Q(QU4$ zY;C(z5rNseC;@s9^=O%hpTpN<`knCmnHJNKnyL00kR94L-}JGSPM_5_(!6Kc@D6d_ zWJZM8YIYVHp9G}0-%im5E8rN&98{n~b+ff&pAwT$rL^$ppe(oLD7{Vm!|46ix^Ef} zjP8B<Rw+HV(YNcKV0tF3Qs-@R>C|gz8tk`mxbT3XNt|Ov(uWx;{vhum>K-(P@qk=# zwKiz6C21UTc)r4gG2$*h`9`~NlX49k{BF8(ylQek9skvN=xpEB+Y_ZqN6tc2d~9ju zEzdFq?D~(tpy93wz~cnv@}!9pvHeDz0Sk;Va?%e2Bt|==L;R=+;*ACQF}jb6kt%dd zD9!hm5p0)sxe+Dtx!|K-hN7R&(@!Wt>c_~obCU-+=%Kw=4P1l4L8f`qbyctf7@iK< zk0{<)x_YDOK)#NW#%OyQVTUe-BAawir~)c4$mehbORvWQblt{UR4eRJR1Sl|L0ygC zhz^ZI_j&#P3zFXe{>WS?<e6!D^by<6iCX7@q#S0FA{jh7M>)nPp(dV0Kl463$Dh-r zGPZ=h(|(0szYKpOzCQ!}j<aTvGc<XE`2d)O9!erjwFwgO+*Ir}S#X0l?zQe$^{2<b z)`23>hEBU<5gx3izT>xhgnKo5%+Ihn9!B;(2?6K^Rb23Fqwwxbm$7Gb(*TUT18Fp0 zDJz)Q<oBCcrdI|bRhN?^*otq>jUOok+XU`>)aIJxJcWA7Z5c6^Ue%77^b@8!kR%zL zEHpdD(C;3RvX4J8(sWG_?qS3CnQPN2Y!{L#in#5W)vSAldsXAm@4)hbDv}AMYDSH& z{c#bGP$B>LZubt}>^MB%yd4mTQMzNhAelaAs2DDEE(oSFnLdWA<vIJM?o;6XH?boW zoYl1Y1T+|355)6-8o&Pk0~<0%h9m@4F|YG}fa&L9if);8xvx?PY6N>5kopgh<x(K@ z4XU1ZTcyaIF>bY_A%c)Q%IQ!+IL`cGpX&k(8eYcP(&e$Ub{QEu*z~6Pfl%Mp>vNYi zbr#6AiOYL+#DH!zC!jODWPr(;(e=C{KXq+Vt>16D1nE)&&!4@gCiL<1)oNye3$pxB zF2u2;I3zFfD})ny7N(2j0IVm9VLZ(re@ghZm-I+;eIae#nxA)7&4hYKwH>TjEH?+} zIi8iitUi_nSUirhw*J6)pXbS--N+f~%SX2_ZwFWTgw(jqx;Lkf%El|*yH)r(&W!k2 z?2B499YFuQu!he$k~ChnIT@#*j4^6}*xbhUeqPI*73T9t<;{DbL9YEdT=IQposBMt z>eX31eH4da3iB$WdYU!pq?rgAOHB$|PxxO6)ikG+xdt8Fjb8S`37eTIN#&Ig1E{j# z=RjN>N52_)t0tPErVr#nTXJiM-kJmkDDG7co}*iAlpFQ^pRuBd8JZe!Fyxp7<oQdb z__1)2sO9y&1*7|VA{jl_lg0cRw390-9hI;d7+YtaG>P)6r2_Dy6x47MB`M!_*6Lqb zG-WDXAo^G`C(X$v!M9#C{cm1H2UrG&Fi>4xrUFVO^Cl_14xSO76x#1Hk&+L$z1o|d z_mTc=4z==HPwYHaN;?0$pCN`W+{54q`v-4vNOkadPxZwO^g=`p{YU%=Ng`fH^RkZ> z|9qB8fOiyzBi=oe&LpQ<k84|p_P3NI8TypZQ?W$e*cDxg#%6e^r9Ak+i*H@(D#*bU z5F|T6$GVb-Pev!VeAz;ewp}7ivh;`rk2Y_PgagLXxuQdJa)9Yn<tC-#sGM;g)n(S; zm`TiQMCdL>bZr|l5jJDuyDpA$|LELlPLqBT5;++4MfeLqEz6J*npm!#RNXFDlcUvK z5;K*dN*^6&x0)iNmBk%f+s%LfM2V8kB_7Z(x#Cu}UESpBUq;9uwsvd*_tc8<_5Z6o zOGUZgnE5M1cHL~qWwN3{((~*6Yp;zzF5INO;D*`VEF%7D(#el4yIfFl+2*{<``m1# zwJ+M_2#p02n3AZax4*kQiWV0Tu2d&>2NVa)>B@%7HRmB|<DV<hY!+|Ndp>)YJ4I8W z2_YAu+}MDfD3d-Y&!4KsBCeC)>W7N?d|gzJ2+ffSg^wPY*;QYy<AIU#>gcBdm^zSH zZoN;25Oh9vNRfYK^?vL*V(aC*CtBZ@$fsb|xds%he3xsFSef*EKEjh)|AMlPz=XAA z;nHu(&|dr1$gd6?*ntI9c<?l>YW;lt!Cw%A9rzW?G13}c$d(e^Kt`qutjnC7`~kd3 zbYp&GM)XG_3)kXmkDY5;Od{!?-WnV<epdA!^3hZARH^C0SwL((_3!`51OI{LHDLUL z#x#QauuKSp86dF_?Z&XrSX5)K&j9i2%J~hK^o2S%TY)#h23n@kN=?ij$?GQ+JcSoF zG4(5$t)Y^i+2B5msL!GTc^a$m`_?V0N|%07Q)nYOX++K^WMV`2@`cWxQP&}s*V2HC zh~=M)_9)tqp-ewT*66K@twy+#&`HKB)E;ND^{;fFWuTOF*t(PP+hU8DJv#ks!C`vh zlpdTuQhZ6-d*C0r_W9Gbtx4Kb#AUK4Jd*NyA}9jdEn%Fwv~AMma-6!lc0KyrHUFT^ zvK$)sRc|GlRe79ZZ}oue+l*JSqn*6fe{AOh2*^y5RS%wTAie-g8c28_KW7r5Gq`rW zV_IF|ZUGKAcw%t_7Nw$`#c}0c!k5ga@8YdHJZP4vE(b$yQVHcU8QP0wS1KVc+%Wkz z)8lx^oULB$g_3DfVSX|CduqFHB>(Q<rEG<H@#CrY(4nJ9DXR1`YPQUUYVJwo42Wm2 zkH4Qpm@IRfKuG}V+xR3EZ9+CK4ig-^v+L?z*W)MXI-;lH=P99ikWxMxxkl&^r=Oyt zA<xyc$6{r;sm+1P$q=7bztG-_GU_9|FWI}r;hjDrGX!_PDT8b{9Wr>o3BA>svMVh6 zigyAU4XrPUM#@rK2D<Gwbd~!92xS3+3+t2KnYf@vApbgERNEIQ(a;=bf3bSl@u9rH zCwo{z4uivk<m^W`9EVrZ>~i|bN_Ap<O5lMvJKCqsFd=Fh#v=jTbtC7J@4~MrrYNL@ znk8@Uh9)yK;WLzA>K7W6+A%{w^#RMNtjM6+Nkew8LOA3)wzgw(t3I8kwT_Z98`r>9 zR{nsu?HHW0^Yqcl-$dO3e`oA2Rc%}PvF5*n;?}Wj#{5)NC(f)m(C<{FJ+>u-xbKw5 zek<%rO^VvfB=H01c=G3Wys#<YUdFNoL4<6J-Qal)k(!o<>Tgx(m|)FfZ>Lbz1n$aw zq#9$$^O4J~*FC|i_VO0-gTTeO3{8cwV($e=xgq-<F?EX#;WSHkIHniZzL>l0#-gRB zY)NV{e;lDT)6zs&5S0)jdOKUBi%6FKaxO}i{UF>{HJxJ+P&3=dbD;S9mC}J^U<d2@ zfo7wh$6fy2Y5Z5;>3P%@(&Vk928gepfom<5iKgOfPaTB{@N(m+9g+vyYBy-ChXy*L z+Yg!j6ljUD#rHXdY%1}mxDQQew#ac2Y@Ke`+>Wqqk#C+{t80Rv!L_gTQ#V4(p$oRs z4Hf0#vDe*wu8Vj^xedc_KxODUN4bVZG&{O085)HMUDAlh*A4Wdo0NO4Re$C|Twj{M zwe|}Sdw<(i)12w*?)injYBry{PsFNyL5G<XZYsJQU;?BX3Rh6$hb~S0S+BU?_)TkD z;A_Q0t>&dXtI+!B^E*+`dhdR|%bu9>>>@Y?QlprjKG2O9wI&|v_8!i3bJ`003`AV6 z9>4SH(<h9zNcQKblIZ!ciP>U8Ls+U|?nid6_zje=F&kZM9P5RNl2DE`)aLHhSC3>% zVZ*7*5W_6*{<cz0wz5=69{tt3lJ$MRsu%semS~qhk8?xVlLNX?9KJ}+@ohs>;<n&T ziAOb!I{I@1T$5+d_1DcS@T;cMV@J=kpE)zr{Uy9`ql&7ST)Kpjpg*8K0>=757(Q1> zR7IPW$FkLCgg&Lm#9FvP5{S`=?mC>zSTZDAowzuf!v6cFl+$`2(hYHavL1R2;rkU! zxQ(2}3L`98FfrP>0WMDDsrRj3gl~0?=jS#=QLWw`qm$du^WPx%M_9zKJ%sJSmdul? z7>Wp9Qb6n<*K;Ks*^H?BrS2}z%xB+cFDSrCVF%8!YZLDZ%l@&({QFbBBTB98=|l=l zX^%J()U?_qCR{ha;D2>-S-8#9SnN?8U#n7pQGP2!{}VL~c+R4!3n<@Rg-i)8eNVBv z)XdNfO7ev*`v+{_-;T2_d&MGkVBp5g0jvl;h-_$PWZvJzswOgW!07u*R8*_TtX34# zOxb^vvC&^O1?KVrZp5Ca5ihTn38&XTl68M}CQ6L{@edLeU%BZJ48B1p5Qh&N19O~) zVFtTj<_1+Ps#2R)ff-C7MqkLzeFQijz*n0#PxS#L{7=}Fiqk!LzS6V!^repG#KM<Y zjr!M~5!=HP?e*<d^W<!mohmdSlVKlnOD+#2mD4pn$kKFO7(h}hYG{hQLeegnw>WuP zc{b<ifybj+JuyAK5ja~9{)M~zQ4PWh2=qbt+MIZ!_Ru^JGkfz+etQ^t_ATSr1^K2# zrGw=0R#9d|`|PEkrP1}xCqw8{SV@f48&Z)E5n22^*vs*^`_ZY1q=KB+uNRzE6e{N| z70bLyS5;;in#eEH#(Y#0KQdb<<6PtbgHw0Fs=duk$69~Qs-^S3<-3r(!mkrA++~*y z72kS)^b#St<Q905w1!5Wou#_=<F-U5|AOwhP@nqQs4zWdlq!F+ba040W6LH!diB)+ z<m0#Y3Thc_t!Ay~<*we%paZ$`f?pdquKR|r)X%?G9Pxr#E{@eT4S#c*gVX?v9Iyol zMQR1@BK*dH{+`IwooGYuGTgZYOW61A@*nYPhi`2^Ne>An#8yjZ+|}jchZ<0uDDdhD zh*!=|Y>QJI*l|*hT+a}wi`$#@pLtYV{mH8P+ROZ4*)UU^`J>&5x1_qnFbrm}|NAKa zfJb#o@8}G2GFum|W%RcBe(*>H9j#u_K45y32<&EH2q8|AA#{a2C|xap-}pHtV2chw zc(z+;kR0sD(awG&!ANtlk)g)uero=Lp*lyuKpN`>2DrU(e~Kn@%wsNROrMZ{G^!l_ zJ|%7CVv^hk1J1KU50x^fd~uZRso*Iwb-@ug4Zp1^jAHvwH=0E$5KeZtf9>|o{>kqa zuhAf<Z=z6=Es7hK2Ly8Y2^tB9=5ZZLKIecdPXN5-Q{lJsAj--*fMwaj?#K0tF1yr{ zcU<PfnwKfNT2EBu^Un<Suvl!I_)uyV#L(EKCmT-6_peMJezUi(&wl-&N-|KT>&t1C zvcA@`vWn}tQw6n#&k8!WW}FE3F?2zbW!79$$E1C0!^9tH8EKPV{nvL5DndL%#peaZ zlZC*KZFq-!D=i;TZCX^mQXHrEo#@a5ut~2TFXiS3b6kH(eaRSnQ+Q`o$9CH_ljvfc z>G%+UQNBG`0v-TNB}egCpK$bdPRegm40<Uzri)?F64`C6)ATc%{Rd|NBAoSwTTzo+ z&g+O>=y(O{9KPN^MWzWzO`je7IG7#O#1y(;D03H6dDCe_qZdn6Yj1jny3ZT)G&GWp zves)2luy8Z&WLbH$p|^0^8Az@)~<|4w|+!SLExzzGqd;7?>ok*(DV`LZRqjc!|x0* z{Gmx}zWSBFpw@fD4wvE|DTmIc@UfmTTxc&!kj|37amf3R*%WVDwochE4G$0Y@bHpN z)qdm@w0(|EkJ;qKIals5GP?K7<y(jgq&NP|sqTxg%8nK0kVxaXvFY}3a6?|MY1j+8 zBzg1`o~%!;D8KSXJmKQk@_Op`{ndM)ULkpm>kBECq+Gz{759yChI|PU7L4J?yIo|w z>%7mmJU2AZAghm&L_7e1ccx>pbO*u+8>3tQwGQ@Bl4IotrH%9eh|kHI5N(Ch_9ab7 z+edU>fWA2)2m%UB3zncfcB(L77p=nfEb@~^<CJeGCTDT+4CsBif8BCSPpPFvi%GOI zPaV_W0-o~%+(^7>@^Y@eaRN3Q=i+n*<e!xovYz~;XXj*SO`saO6536!wxk}axY^*W zEb|5_FqPMqLWN=_QK`3X9}oE=SytNR$js#Q;T<m@&_za2c^Q#-Ni1m>-t!lf5j^IO z9K^E*0sqpFJkC$l1hNjV7=Bi#7?y8I#`js3&g06?XHCp+bil5N-xB3)I%5W}DpCPP zIm;2fhcVl3<Q+=(Brz;zYi$|I?OknA5;#<RYyEc;^4PNwwDRpwuaa{r?kXJT21SHm zYR0;K41<-UW(FW4ym1B9ZjRQnh$m#Pxzv#&?~ET^M`f!guEqWYOIoRL{or@OlXkGj z{({ECmqQsc0b;1%qa7EgA>ILe3&?qtSOXTc;H&}Mg>ZZip1DoF66$*Ne(Yjn&BXgD zZPz~uk6fb@=WRR_tDVw5j}5JIY@@uZ=AcATy5KT#EQzidMl8c80<H@V3a_xY05!G0 ze{|Po%4@nJ2nO@{F<G&lA8z@+&3yHw>~Ezbf*9`DuMQ1hV}~H!sJf|ThW?oBWzx{r z8e`j(bDg?O9P(ak&gy;CS$_C|TOqm2flaj+#QqO*n1@CJAF*}lq6n+xn7<&^%@y0Z zr!xcC6UHixQ5+b}P;{qXnS?Y}0x9oQ10eS?w53L<I1gKQ>{EM})bV*=psPWhYggVp zfVP~eokQxOkf>wJ=or8=krfb34tD}ZI>FoLm#<TO0!S$PgziRt>G@KwIFXNsE`z&W z0kSPL=Z>=mg?Ht}Z@%NLLJ{ytroW(f`~5p~!^N|IK`Xi85&x2;{x^~pTO1PaevCYT zMzZ^q5T=ugsWE+kq-d5z<g_-h`)1tb7oxgz_fwEhW8?5gnGj4dVlBLifz!p-n`M#N z7($}mD;R6i3O*((ldfu;YWk_U;nVpYn$D#g4@Je+P<F}4gDPGsly(`uzq|unm$6R) zS&Dv|Fyv~jbGUCwGTFejMKT1$w<^`uyt21FV{>k~5Rcb9U)8hCO1I>^C=*9Aa3iDQ zkiy>ki$>!?crJJgQCB}Xvt$Dt&{+Rio`v0bYLSCQ52tt6z=;T<3l?a^w`3-2qffv! zh-}aIq#;EA*7rX}Lu3?5K`!lYt1FT#;C%_B`QO!w@;$yIrn8=W=4$}V;=>S0ETMqG z;w^JF;@qB9g|%Y*zD?Lm{GHYpK5D-_1VGHsmEui#fVFG#707>b?hub!Ae9A)Me#xi zpsx%CV8NYwL;iY;OnRB``SlFPv>w(9`2NJ=Wv*%BiHaY0#*uq<XQ~zz{@bW1pOi*< zLPl*x(wyLeolb`{T??KBOrJr7qmjAEc!$_`>QmyzD(>5`ghRBWv+R$IS1%lfEp8sP z4lFbrd;#jBCX!MPuu#&P<hEK&n!6I|K+U~h?tPZpjqk-})P=!5_+&P{Shkt_V3=y| zqw1I!6d?J`MM*&Es>G4xhyT>j|I^&7bYYi1fI(F#UtS=G0JQZ!ajP3GGco>>wh8`- z%@2<sbD>D5<xIyOuC}kngBV^&ZulSsOb0xbw>~Saer0|Kz-P>6z>%z#+3ipUM=nid z0oA3Cg+-Y6O8CX3kz9$t-p^zQ5Bt4A=#^XOj(N%U%O^W7D7Xo6efSG<>~AaR5CumC zsa)6#2d~Y<wkf*Gj(#K*gBM1cZ$wDB&P^LYthUAhuShpS)~OEFWeEAPZ!CfO?yvC! z*6&?$dMwp9A`73sj4VkkOlZ=rdwt)pYH+gQPs8^2eLQY}l1@!}$M^=k)wdoZP|Gj_ z6^QW0E7!TMN;h*M{)+jJAL6B0u7g0wp0PX~qYLg3o#=|d;BclF6_f3sM&K2KZ|pcG z^oqDZ;-7~@`OJhxZjB$*WMpx<c0OQI<uy#FzK>rNYc?zV@CQ#ejycvZR&MNN*d6-z z{^;A=jY(G~E$b(I4~-q`r?m4a*lqDrx(PLart15YEwN3I6izUUB#yXD>+L1Uh^M)= z|GsBw{8dQBu;!uLC#B0J)wDs|S~&1h(WlyyRZL?D>RF_nF354&<o@k8AE6MQ8J!mj zJ}Y^veiMczT!l>G9>)Hb;5V-whors2jdO!1j{NGdRx(pyK4JaT>|&#L1yiQt#cVpu z!=+VEZ2Sh#Cdwo%Ld@Gt3vUA}NjY3;*4{d?Rb|vNLIowK$ki}G5;{NR>9Nuu70cYn zF0~BGd(jq7*x%YFR>kA1V`4ibyc_xF>6b|Xy-nYOHFz6_?H0`gC@hWY`EOW{JIKo} zMJdSW9dN{FdCDuz7q%bn&(w^?Ek86?s<@g?8l4QTOuy2On^>(ypcfNpjy@H7j%z=G zH-NZ1z^s<0DN$iJ@&?^puTdizxzgpE`YzUrzpvg=FDeb<5pGOnVimtI5(a(FIOl_5 z!!A_=_D{N1(2c7#<o*WO<G^$CjbBt2T;*$&U!s9EPYxHP?snJ|yspVE5r%0oRy<X` zr1Tu}o!HIOz7HlAyluutp6EVJt7$**U(7{Mz%;lKx2a)d<ZiDEsykqI?DC{mbEU=- zd3)Ht>&{odKnhx0L*m-!A`;)*nlW+h1N<_c--`GbB(>>MzdBVirLoqUQsFRte8OV% zng`=fmLcn!*qC;jsaI@o_?1-X%skp4mYVh8QPi31ujR$BI=(JcyYJWR!Rf62(fW_q zCm5=6hl1}hKy#zI3#ecpO45aOJg#w3`1hX+buwc{4|d@>)TZT~z<AQ(sd6v-8&ote zIQwo*<@w&BoOEaJ42%N0)R-AHsEPz8*WUw7|AHoB%T`)WmDrc)$8S|on+|hU!%AjO zdz3zz`#$+&aesf!V5@?R!)=Fe-UDv8lpicYH`LVyCIGG7f|z90+T8t4D%IBG;)LI< zRKP%)>y7|iPJ{C&Iid_o?mKFV(JDhM&EH<QT65-bPq_hQLc!OvJ^O=sffOb=#UnJ| z!QYQ{<FwzS1JwS+8^&gk$}jf!2B4!L!7(>Bp@3_Ebh+w#291(`^llq)PNIc;sziJ6 zOyb*yY{LEKl+j|0x*xD=yN_=%)|Ou1C3Y_RD7&h0uzDi@^2EXhDuim<9bBs#eYQ`< z;p4%NRyT#hjnvkyIWx#JL-u0&S(0NGVOwCKd@n*`K~1${xJo01gG-L}$*pH+SuK}1 zz8A#rp})QOw=t&;LkQgpAb_KQih_<>BH=Qci|E$V!MOpwY&YR~R$qdhLRxGW`s3ws zG$Fswrq?a|VbiDH@n&{Nqq>xkG6?k}j27y+kIR0t2%sHwsGuZ$+|@IFPth-VmbFUH zoMenqLRrsyc>j35?43Mqwv-f(r7A(6A?%hkVqLrvf`O%{cqkPk+@=p8I$+;DrzyD4 zinSu!eq3i=5_}vK<L*R>4qxA@>`mJPtl7K3ezK*U4vAXo7M7pxwrm@V5^THHA=XBU z-Vt1wm9(vP)3TOJ2)A;Dr;{bsSFYc_M%!=fw=@<-bzNxFB<(r@X`jqQW7&VIFD~#X z;0K|bg!!mv60$@zg#`LfHpauU)CdofMcXq71#C}Jlw>-h{)>>&e=)u~kAPNe=u20m ztphZe`8538oUN48xr=^x!j2C;y7rRw*6YkuSWTAh7Z$<??PSfRsy?@HA}S$(A%i$` zR7}?(_=UT+wYD{o%=<MsoxQV%w>4Gw?fMK;tshR-*6H_>&px<&xx*Uy5)n*=unl0M zS^&POHsE=MyBl3ordu1HD<3KH&4`k|t)<J)H<bEG{?(v`Y$P;IUpcZ(6!7t<!j&(P zmFYrgBJcN|;JE|<bq#;#x~{+ReM83m-SlJattZ2BpFUaqNYx%r)e9ay1RY&Dir;z| zgqii~%5VvIi6yYqRM+Ud`f2XeG_}}iDnAg@+LUUs7BbiV)<9r%E_r+E04N=qgOA?q zp>a8#P~rL{6NeePUa9xYp-4pm3@1F^Fr{Vi&DusgkDa5Mc|f(Mwl+N|W$HOMv;a)9 z$=TuY#n#yN(D3ZujFUiC_QNfsmGt-R$R^zTS+7*HjE(!L7bgdYCpvDwn&5kMiD?=A zFMpL|hltez*arC-OR{#;q_~rdn_?S)0*236VFPzFbo^&eudc|ZSAN1e<7=2=dwZMR zyKEo!1r>k465s9Hk$VmQoeJ^~8RXxe$EbSct%D_C-4bSr(XeDI{WGHlK(1?35jm}v z{rY^4S3GtVVmr^byc!%lp(jjrruj1fYYQK0DV-s!?C53=(Epe#)eS3@`^aYZTgFq8 z1?KEc!Rp2v!>s+wV#;^_f-e4Xa{a1Gw<=ul!6g+pFfb8<uJd!Zduw|hOCB#zPCRj6 z_SGdZ*%@PHZksl}GxBQ}Fi}so0FNliIZ?euyQqNHw}*<HeUDy~w3<?DXg5}A)g!bt z<eK!U+DI$Nyi4Y`g@!X`@g)E4@~3?}3D^g@{zIMFZ-0!0E{!-8W%e{}zp#8By{;yW z_IUjhlw^v8(;YsMowiz+6-i_LC{`Gh>rdm|SJsF;|MU;bFQ)h7-W0jBZw_1zgsLPA zs@PA<{ARR(Ki~FP8VyYwbf|s|k2fN=|G>6$Gak2WY{9<TIYUiKaSD`O)5pw(Pb?*) z&Hp(nD|fpCuC#=e41%eUy~4j`nE&+sW6N~=eL}n5uRolvFv(jC`s8PMQ@X9NZYT6O z!s@8u4`l+NGV$7x5s$yD+@{7Kxb*ZKKHlkA>0C79{hZ}Vmz^=?Qga#oHZ@j2U<i)X zwR8-r=AYgVH+}l$X9taPnu_Uj34O8W9L(+bn^W=>tGlx+D4gd<Ugs0o0(J=lCS45> z2S82@Y6g8sNc9wgn<M}j(p;{(%sG*}OIa=_OK@s_`_lDzUo&@|0^ZU9&I}z6A+WaJ zUk*r?D8}{yV>?&jjOoE!SK)yskDeGNJQ#S}L)+z&;mr{9ullNZJsu<mtX1_rM6lX% zXym=GrSl)T5q2UkTuXgCu<Ga7t7cE*Lpo70IWE9ZXNaWxd=C|k<es1#5w_0{nT_vR z-P$TwRVDIY^5OComN%7R0fAV2znX?C|N0+vkpKIB>A(6dD{pUAJW`B$ZfO(42cWf{ z@<tg#?tN~O$gBHc>gjbX<izup^mL)R^B=zac*UlK)mH0JhaV5ABRh5D=XjUE(Z3AU zh)Dr<q>QX($+?ph6{D-fWtvU*mfD7;7I)yvyz8~&)k%EP8(lFAm?m&Cv<p(#m@i!w zO@|PVTzj*lF@zBn^O?e3t=6HT&Ch-wx)&qg$om-1h<&*g3w=|82wlcJvv*@mw(xdh zBcVJfFDMr^va3TVvVT#BtX{F?Fy$xmdv$$Uh4Y@5pjqwbCV`bA)sz$eM|a;H)YRYR zi<K^@bb%;EI!G@<Vgp13q^p#OfDj@eAQB)DMFHtu6oe?fN4nHV7Z8wM1rnN+Ktc%t zl6cQ=?|o<Y-Q9QR?(W@x?hI!*lQNLZIp6Q|e4bBfy&@BGY|oQ=-fp)J`xt$yFPrj) zQZcp&wKXh>vZ#qNuS-0{Z9a)q@v{ughusad3s3zLc5%7+`oHoN+J|fel5SBS)6yFi z%M3oR(ghk64ITV*@2jmFf!Buo<y<1qSNojnWqWmIFlD*}2{0G`g@xz;M&5UOA|?NA z*YdY}K!&#qXvmQek|V$Z;f++01GT4#Z*SBM?-^=r5?q911YZ^hi_`!}N&mnU2c5kR zU@#lq*s=noYY=WK*O&(%HX+xL_Bl%#jSrNH4Omz*Fx7`B<ac3t0caesWJZ7EzZ?kA zS+6e0$8bpb;AppD^$8}{HFZ<DfZJ*Wx>oh5Sl7p@Ww4Zbd*<Njeu%d$eoL`U&zlZ^ z2&HhjE40&}Abm*k>+{XUG&EpQLf4|e3p^&55OFuYR$D_hz(XbZm1mfWX9X!AaC5u` zT2Jb7p*(axkA#mw)|#NVnAMvWL#4ibU>n0}R|Po_UZ*bue2JR8gUO3$_b?gFil`P4 z_K8C5POth~Iy2>LnZ!W4S014Ja2k-(nKHb2K55e!-dh+yh&q`@HR(|{$sRL$Q1{5| ze9qBTBNPF%l|U)f4Sq-IrL$+y(0iAk5Nog`AKd=F$e{K;dv3Cfk6?Qog?GW;6Az`R z`B_y1Dmx|&K@R^*o1?ydJWS5l_K4?P#{vH9QoQAn5_EhP30D5So(A0475LR&>K#*R z@<3PtrlcB0QHL+|znd5aU!|~GYV^e1Y~7ynI6UyyK~5i;0DUzW;-)Z(!IwqNH$jYk zHcP+{mr}`Z02>vKHESO7&x1U<;hEc_k)mI{S&2*%$HFY-g*q+K;#bwz=`X;3yz|!Q z92WW{j4)CVx~?)BfSLh9(^*k+4+$Ga*s4AaSnMz_fpo%33!sL6yyF{%D$wMxdN`DF z5kfHc{$`83Mmg`6Ul^ieY=*t|GkV10yW+j1*EJa#<FjwG=b>B{k*TuWM?G_)WynE* zlbM5RsROEgUu_hO{!^HJ$Y=Zr(#q~vySjYmL)my6g!r^~2H<GC!I0xg<U$$%zuTP~ z)*l#_Q<IFnX}3APK-Vt~Khz<y&21H%MeZe`4)xcNV#cR@GQ}w^I8P=i`Vi@Kl3N@7 zL3Pgu$kt0kP!HBx8{mGN9uDrCQWiyIK_k#--)cJG6}XM6=~*M!JAycfE_7!2krsVm zSYJI9%tnQLX$Tj#TRgn$SL+4fuiCgp&}(Z8rBmdU{eNO_Whb9E5sLBb;jG02YOW!Z zR)xRpOCqqYGUcAcS{$|=5^+v(N@7UGpt%F|wENlGImJw+8S7yPBWfPt*HlBgV2_j9 z_l21#m$L61iyzP!-+SLe-?*3Hf#~<UlOq_oKqfPpO>xDl09o8OiVD8n(_rAZ6BNMZ z9j&V4j)Jart!k>jwv|h*R=+-)xNf?GTCCRx!l%G&v~)l+vIQ{37^~s#o?WaMB#b1+ z=KzT+J2{0^nCmUSCNkaiE46Q{FKF=7ZyqquU}+UWsb|=Dc;lz8C;TsWRVFQIk(XQ? z*Q9@OuZksBK#V`%NMUhH;VbBPnpj~U0Z32oj{I#Q`S1M3LtNutJ@g}hh?#)(M12gs zFvow#W_Hpo%_)kToaFDW?Z-2IPgzDXQ7S8@)8cg%U{e6%rUU}D&jGL%#GRn()(r-$ zP{N>5P_Am$s~LV>hneBdKF{R{@i)1vo3fY)IEy#mIYTcATLqQw!`A>cWIW{*(fl^; zBb|-n(;{%*-Y^g0(Jd#ExeZlYUJbjO1hCvYWMd!9%pdQ6#(>8{{!V`r{NZ02!u@NB z{lA<e{@r=e`opEvu-(F~>I)4vtTN7XsvSQ7zdVIvWln~}wE18rAV-P~1%q-SlJtp; zF@P3|6<99b>y^}7ey@ui?pFdXnt-~PZHJ^y#m-r;gmjB#{PMdfl!(x6DM|I>=^wk1 zugyjXyY5=}?QMj+oSY~uKhuR-Q1a8e7mnZV9TUrB;NIRRu;v3{eB8l`Zq0%e{~%%; z4%*i1DA0mmZ%?ur+j=chsiGFm!`G9zcB`)YZrH`~I^=PRV+mE3qL71d>9AKA2^LxB zF};&IMb38@R9<sl^gCEENw`t`hQVd&dZMwByIIH^u9;!atWoMA5`z+z_MKVAe;Ts0 zk6J3Fzo`ANGy4~@CZ7T+qTY;ZMX`S(p*#Cf1jU=aysuO=eXqLf2ww|>c?91_R-erH zzM%o|q0j^);&2z5htAa;MO?>UKwcSNZU{x&8VL)TF4UYnD9<sA|NLGUR3K76$ADBP z?zhIVwPaDC*9WPZ*;COs9djr3VV(fq|3u@P>4DX#<(-jijb4rmHch#xl+x{Tl~v1R zTX@et0WrN2NZmw^AIShqsuEQlu$wdoaqgimQ14LENkS#d<w1cR0@T{$8o7^#^tmfi z!Zf-qTe;mE^v>wPSMNxc6a(2pwtGU8r2<^PyAsnX07`VZ>ObT~|2ys8fBLom#*FaL z8TtWB^vI`<fsR7{Fl^o^MarhuL+%!2MTY!ckN!{ny3ESJ6yW)RBEBXolWu_pNXE4V zZeX>hP>Bj+O=w<Uq1%2Bp;}F!Zz}h##*UEB>*%p6SBp~lJEraj{8kv_WdF5p@#P>! z(_gc?4sJUpvd`Miz4I4)RP@ppxZW^Yv}C&W+8iKya;2IVQ^6$9wg>Vaxsh|XNn!?P zvVO{|-6a)*?WyR5IzAmeW+FR^&UBDR4It%`F{EKUwjC4AV-D5n!-Pv<>7B&A5_<<k zw%UtazvK(nUS16zcXlGDGFaR^RF`@^dbXB^NqXiOb*7#-{+M5r$U{2YA$$Sd@tJrN zcexxth?_f4X@s4X%{Cw|#W#&?)oSHkd{eO{`U0;WH2PRM+Ij%6q+S6evPSfubG*AY zM{^-sjIF3QxE%Lul;Vdlsv$~v{Oo)8`3vqdYOUQGn#W#xT*nmb3Y{Bo(-O)|cjOG| zHF+ghif1!P6_B*FO*Ht%;O%3z1{-^Gap8M<klpUCbv4aHE7?V}(5EU@*FDG%<7p_Y zd1Mvbf?`9tr_ZrN+MCX-x4+2bPJB?ZaVFQx-9_fRqgWr8an@7+o5!|KFE1q7ZMC9b z3v*JqaZW#}+_;z%tpVCj6_YTYvkzL5y01FkV_w|$U#@qPQMWG+$yq$G>Nx}ieW9xA zmbyMVzp9T~0mW6!jeiN&{7;_$D>IY-i`6qX2a#$#zS0oeN$(*WfjujKi8ro`+89)+ zbuna=RwvKzgm45LUz(CxjEe?U19{d9kjS)^*I;()F|~5n@lr>LnBa?Uq9%h*(o4wo zKv#pzWu6n>^;fi`F>d>PthiYWiI@D$gqdotrB_<KUVna7Si+q@ueP#DsrB*KD@irC zN88jiPx-XWTN~X~&gYh@#@rf4dDEWyn70=tdW8h|!gBYqKNo^UfHgutm=Tc7<O3k1 zH6<1I3Qt3s)($=0jWR^n{0hqRzh#<J%!Cs25S5ev$td>922$PB)p?5&<iOY>sm(-} zY#Pa~ZKxwT_RChSE5+L5%s`n2C!{5f!-Gv&e?TieH)MeO^2V^)9B!a(jvZmI8`lj) zCtMe&u7AWE7OERbKxTcWe_EG}8b80J@;h&c4u@~s1Z~_4^=~Qa157O69U^A|gHo_R zEgtK<6@_9&`k?T0Q4k?jbVNW+etvcQpxpDXDorQu%1Ik6-(+DQ5P35p_L$lF>Fb0z zUlV4SDJ9Fu>v^9x+-zDdeeL)pc!VgUEURbhA;~`z+JEec#^P8Ecgn+^LV5pSX7PO) z(K{BGjI|S}HlAA!x?EP5TmHcW?ceJN|6e`Em`Wc3;uYRt9sknUPYp!tVT98QXVNuR zDk|Wiv39v3%^bb)7la#3a)Y0sT6j?K0p{Qz^vk4oarjHcy@iP76@$vb`7agfa$eG^ zL);poC#y)W){|DD`KW5l#*V|0dGJ897}0Y7U0jjPdFQKfl-+uhH2wf5hj0B_g$}dW zb96SUJHQ-04{sM1r2u?v4Zu9Q_1ui>EElmVrUnoQG2|rn(!R?jFU`a?$p(6lj)u1N zH#Vh+`-8*PB+jyM`nomf`a)2W7@!0Qc^*6tBF@Z}ON4;MbjkO9W8lVD))K^?ewkjo zm&E>!IinS#%Ad^B-)SE>9y=Y}4y_s>2o>u4k>bb^=`Csc?-N06RLM%MhwP;d?1gvP zy9XG`W`w=0z91`;WsI(OOwR5fh+)5nM=if`(UW((vo==SzeOF$$GW1YAT6kh@Ydq3 z3y41q4^22IF2)FaCaH7@4gZc4y_X<!mFF=-Yi9KVq+*}S6|zspQtDhBa3Emg;c^EH z4tQ!;AlBP?yjIm@e{-ZRUKjPR?7C#vkh*NvTgNbCy&Bl3#jZDU(}&AiF-(72`t+%U z*D{Zyovxe|Za=PNv6n1u8l#rW+P&8twOCIjEW)&Wb4@k+2kqpF51P?32bs)A4#92a z^oe?UeCi(t?%>N5_0|_J2t3)J5H@CZS~{@CZ#_@mOC@=zO92y=*YWx~)*IzVyi^rh zBvsTei>gX&stuP@m9oMgv~SPMKzoiIH^@s#)Aum3T9Dwwm}Z4XmaGN}d-~Oypi%E- z<;1P0y^nq!QX7!KR$Aus>AzF@{+Hg1iABLt6nW@3%%lsnjyU?RxBzKPn$a|&=p!#M zj68`rd<=WVsT&gf$hLlGTR4Tp+X<q`<P$89ZmayHxND07nx>>g(JMFVx87=3PUgl3 zWiSg3sXB}8#4D~lf8cR=-<!&4Fffqc*Tg%E>^kd}ryt*jR%`D}b^5hP6TwJq>u<zG zQXO(A95>P}##N23>J7VxJ!xpJGen38mu%jMYaa&&t^APrCQwCJOT)oa2+n1aQfqa? zQWh!Y0<Ic9J0kl<^!mYfnQg;%RAqI3ha3V9I;U;0pb+_R3=bHLko2l`=Jj-L=zkT# zJo<X^j7&Lk{B;%j^aIu)QN!WguMAzOFpqf5;wS6h{-`$-Q&H*s53g+7@6dSh1Fgyf zIb_r8U!Cti7z<h))i}gNnk*-fd84uOi~PQRUc_}ku9tx6L_{vM*N0-lO#%3|WhZua z;j`#aBenxXv;j>GcgD_51T#^@=cB9$g+{2NU-^UC&!f>r<8gyfn^0o0RDLO}-*Z%) zB14y0I!GOYMy%I-sVX#s;=ECTDcEiEobf*lp6F?b&S>OT>=Z|ssAtoei1~DW{hvCm zm2qW0w#|j4RB{4I9tGr@!nPt@{Gc1ZOM&y=p6ii`k>piGP`o+x8@40|h(BFa1Z$F- zT*_2)mssF`7@lJBkBtIJkvlX$g8I=d)HI0CkawGV3Cam^XyAyP6-$3eg2Xk8Ba$A} zX{H@nk3Mexn!LBP__lm4AZ?#Traq2waU{3zPKZf;(;o)q@1^(wUMt&buVHxQQtdCt z*A#W)3V;h$#sQ<7av)pvIi(WEe$jYbq_xZ9R@IKp1#}P7d9NuYuYQ@q=h!J5axt+R zH2K#Di42=-pk?Fw)J>_>iGH_g?wDZ4@9W+Dr6;G?{h>QrfbqUprhv4H*O0;UrPt8t z2Q!pFI!oY@3q^*Hw9<;@2Ri;wE1_w_sPT>H_f(mmR8gQ&*r9#a22~-j^Xjh}?Xx2; z6S0wE!y21bS96llc_;y*mP}_m!XeSZ9-piu4y1?L9)4sTQjWf|wLg?^O}$r3kDm`J zoHwCpUd7#aj>4<AVWLp%V!+mz>Zc_+QZ;gD<nd!g=nsQ0^d5ZxOEe#t+$ZO~lSHxu zEZ2aJjfw3I@n#<DZI_{`d3^w5YnIuT{`!YOh&})ay55)4YH=ANWW9Cucu_Q+ei^if zdEbT5+i$^x&7ehp7#2+iy*+b9>SNts?WJg<2o=yHf7%&S=s<02kU4&9qg2U&7`R{( z)2IMHqvjgWxL`YY8`LVdsm`>mA&XVND|{-*oM=Kn!$Juqrrj=~gOQR(Hil+r8_kKk zRqK4K&2Z-QA16LPvHrH=CVUEc2Hv9CY5%ck$UAZ!<R2`6Nz*6HC@(Owti+hNJ+_dB zl$+0_W?}2+lAQ*|SY*1f&I;4%I0&H*r#4FGLrm+FZrv+@r{DkB5#;#MOSS5ib6iq% z#mm6+_LWe{;Iw}^z4$lh)}g^e*y^~5VBX-LkTcDEhzl)g3em_13+r;`7LGuYn;lP= zLFJeG>V~rA4}LZ92ENff4sN>5J&2INd$z}L96>FB(K$La^CU4WF0T*eRRU|)sUHRR zExA8|jjb3~#7gp9lBvowuYGjz%utfCaL^VSf`Wm<0rg^F0m8a1Q-=tBt8J3gLM|qN zjK&CMn2pap97^{^eMBxh#VtFZSb>__LrFlhqdE@>pE?O5hQfn6Dd~WDM_$x?#IBKO zdrhAjI<R1t_CfcrJnsr=+wKb83(b8ZOV94S3}V(r4jkPF;Cf(i<%hpqo5R5dMW9WH zPhPv1Q1TA@NupYJ_xH>1uL=an$amE>WK1N;#+O`acYbmy#h4s(q>HpCrp6&997v4w z{b=XUi29WyRbP`+h|HA^j?Z=#;n8bXz!|QOsvn72)y3rApSk#q$7ue<Yyn1txKEJ7 zy&F<cl?wy}G0*$t?Y#GI56Kg>ExAXu!Y55<EnYm2aIBB(u2Y)+oZ4ga;_}Tf*6&C^ z8Wzb7ta#caPXJLoxt1wNDa@t#IG2`yLF11y=gdaL)A%k`@+$fl#BR^rXyS{zB9t%k zQfDf1xe653EHIAr3&Jrq>f`FDu<R*a{~}kl`W*AQ)xqyvC5bnfQXJje;1!aO^h=*t zG5kjk`v3SjB(TVw0^&A9KItBvLR>W<uDsd(u5C>U?~-1{^>NQ}PIlID6xhv&)R5wz zX((NhW@6c>HU79}WS&<x8zDEX*#20`Vf9XvzhtXa&2)u<+jP*mtAKc_m(F599H29= z&le~lT?&i>@j?%7|D-DBe)>AP*R33_%Y(Q}bV6QSO`I@4fE*bGPhf?x^I6uZij>}m z4HR?Y(0l@82vRk`YK?q8nq6<#Ay-1M^RqcEMO5MqaiEQ+Z%Uf|yf7fN?iZ{^NyQ`{ zW;P+GCw%}$oBMdqm4X9Hi(@ZOGqlFmV100&Y`=#h+m~l|0Zw+--X^tX4-(yY`|u{7 zq$=?e7rwFjbZvSrm2#e9{e-qfd>?#_0{=vnAG9_h(o<Y=AF??=x~mdCIzjCZnn<!q zHied&<+9wfSk1|*F}&5RzjH?7yv<oFOVT-?kJauq(?Qb#UjRPq&A;QbXZ=0D{X`^5 z{o5~fQ&K24^0`c(O^dy1IZAD~9V}cAXQe<#>K#!}H@iinBM-4;01ONHjaVnU)Kw4% z2r@uT&1~}KM})gON%U4#`xxxyv5}IW!jvE7s5yB9)%mL4bk{BS#W2^Q`?+SZu?;CB z(VW-kLuBxjs8<ymqng`CTG&1it?ua`28i-r{|Qnm7+2UC2dQZ*UG1CgJxZJfr*$3W zZ(?5pVJ0Z<M&3M1T-(DMG{#ly2dl4R!TtWq>0j-?goF%ET6F}U4(^?+2E{<;lZ7=> z+rca$N9}WrTg%Fn{BNy~gWEY2g7Q5yVl4%$kTS1czpBor^-^R=scon#_12gZowJ-H z^J7R=JY1#uOXC}otouZ4QO|WN^PY+?fGIxe>dFTm1?l!iH97d;F1(&z1!+WFjo$9R z+&kv*?#?<)mwGQK2P+@r_F)8|d@P`?{&`Kj`?W51=rq9n$i7~eG0l=alEx6k-L{IZ zLcj6_M(Z~}!-B<!tDCG~+S#X*AO2zZ?l9ixdb8x3pAz@+hDe6LDnsfbWprWSH42#b zet~e#;paN!WN^RoTL+H+o)sK&L`5i5w6@pQ=nwW-^9|(62zd!7A&%B&9hz?!L{$rq z?A%Z+jj$trTPlQdm2}zjEilxM-ZcrY<wX%Iwx~`ua4+vf`%{U_+ly^6Ivx++DdmKe z+;o7id7cM)A(in)g97M700!Yxu>q3oB*Kj=hLO_bF{U369NzY28%W(cDg8mruQldJ zm)IaMwKgTK&;$nn79}?YVEH9m93v@Ex$?iAn*k(A=&;~(Ff-SBzYP-64DL$MR(K+k zYUqx-7sj6z<7n5Cba!|&&(gF(Nk-my9=L^`f~Hx?e#2mGAn1;WDN_MlrbXug0wUfu zhgi2mxLxxlmi?-3ZQ7NdeQ*1j`^$5eZz(W8%d?cX|;!l=O?R1csvhra&9aG<MC zRf>y){9X=LN6lke0MnqXPaKT(#J>EE7(f{XC#|%o*(;S(_VBDxnCPk9QgRdrOP`-d zpXW+Z=fRg6MVkk*9SgCiZY9^RFh&v?I|n#|dr<tMsFzqiRUj$%#B(ScJYX*7xnUe9 zCUO@V{$lK*Ym!NzyS0*$d$XZh#M9ib@k)l;5dv@bIf_xZWF(*#(N`w@1%U>00DMz! z5U~fW{f8m@0|gikg<u)~Fl<M@1k2H)gBd2NmXy#VDXKat>_a~M3R0fp1;mlHTk$4D z;OzWt8my|%b?VJ2si)pcxek(%bQm=9@|)!wM?KXEmI0lhgtWD#VF{;5)8?d<%u*kx z)G=}ZW2lIYVPH8d<w4Z1>4#s>AZwr8n=gDye~oIBr0mdRT>x@13l;Q-p+_3>@BFjJ zwU6jblkmLXa}{#^QI|h>I+8eAXD^ScD7+m9JEiglbiF04h^*0<@n%CN;yo(rEF0}i zK=JX^EfRa*`Yh2Cr`JSmJJLV$#Jj}MMQ9B@+bG<n>cM&Xz$Df$g@$&7WgMmYrDJIi z3DY|sgx`Gsc<<o)M|;k(Ze##uFpJ)gI;Cy7FmSf#=Wlz?p)ytY*!5IbTy&j<(691p z{TCPgFyFRLBGTJIRr>8FXQ}R_sdprF`-i^8XH}&lu4ypM>hf?u=?LMu8;F66<EtE0 z!I*^$F%ooUoFne7huABy7-CMB*zql<ri!GE@g7_$7?{-a8ab|Y9(uav_``1roka<q zpDisONeVK^>|t5FBYn$Nz4k0=8OcF*n{-2y57fHd5BMUA?P-u$TTf5Z5=5hOEH2w) ziz*q!WeROXcU=EJ@Cl<sA@vw3IDzPAOrjpjX18jU5Io%rN(SpIiyNJkWO%PPtMfZE z#9#5}FC?Y|oRYWAngG+3gJNS$9~oVaS-!1J`PB2NS7=BHb7Hm`M>$JUZVTq8g#nsB z^Ug0fCEhe&GA#Z*K5Wo6v8Z0DqU=Ez!cd{Dx1YvTx6#|N$AQ2GKnHybDO0qpSM{Ya zacuFDMN_S7cdRp6G~}4Zquxvz;IEGLkUmF~<L~4uxZ;{}`3$<6S26x}9%(bQV)~`n zGYCLXZkb$w55@>gl?C|9+)$Nmn)dEdqD{lr`6XUdQ#vEb*vSDh{HHdISlbRgtL<Ov zrlk;q)O=PW{(Qp9kf663lE7tCQKUyXc%<Lg&mi`69a;%}36?>gBY~p9T<gM8aP;Ym zU&mCSXT?CSM~VYm*@>K-FS)w~KT7@fYWQ8WGV#ziL(0DAj=UAJ$au`y#@GJN8Ue%@ zHvh4wnMdQj_w2Kj+b#XlIiD}=+_};;weK|atDu%^aOamNB^(!4hl8F#1h%J=!Fo}6 zEYS2g+a3(oPBjl)jP*>pUqSF@>^~joWL@=;-Vb4?b0GPMm<S+yefCO_c_;A#LHQ1G zYC62O>YI#8sfM)QX)}h4)QJ@~eTSom)XU{f6p14(g!#9r<V?}>(UmdLA^F_69{<q3 zUkzE`A))cz<zLsLpJ`bO8H?tSxL~Fx@5~atVcS!j>Bx#{16>8xKtKCZVTSguW0CFn zG;;Fl@JCpumycPoRq~^JcDr2WTIV8U<5&~Ao6CAQSf0X8<i+u}pCYP9Y6E3D`kW0H zU<vE4#%ehvE6>MPsDIk*yyy$&t`SacKXNREqcFH{j#pKI#m!uN`T^nH?54_8YP`lw z;<2RYSf=h4HYKmLt#2#$krtyGJ`&=6!mibQLaNqtzAHsPNj|ZhT}xHY_LXmv#k;`< zoyO<=+>~qjrmO;rJBoktqnMjHfOy5!=xji^7FxAMFtT@@b$UGz$yUTx{!3JvsIxw@ z0xXZt)MquJ8I5NaCA(RR@0U{<-X~G4wy5XebQ6#fV3Om$LXRqSSD-VGlKLUB97U`3 zfI~yn<zn%6EiAdZOzz(I`?sw$AKvUDhHCaRt=sd!+qs`n4&OsP?<6}ibqC&>PV%re zoQoZ^xx5D+2>W`0Beq*|*^n`!y+8NCuv>KEJ=1%zhQUIt@~r7Y&j#=#5@YyQqg3fH zSbaurN7!fQOJVp~M2`V$EK5b^^&;ObAc%L1A2zE>!)V`>M?0(LPdJ8jt{J#bF*c-W ze1qM&!XE8@&t%rZOo<6|5|i6Q^67ZA`q)iBrC+LgYHekuQU9G;Z>6pA@lX>Oi+Qp| zLqQFO2AjSHRCtY~zd-zx&NE*{FA}eB*;fN4z9lW^GA$1Ebd}CD+kKJZLyGDjp~}XI z@>Ll<;ZpE=`jVJ1z$eSNKcs59qw25fKThDsM>GTWmXNM7@1~m1#QlzX;|5PJ{x;o; zRqp1ZoAa+*wxH*`4s^9WOw8N^cazeB(=lmO_X*nTZ**x)63I$9+WDyQrp0nS*u@oV zdAWLHY7M2QV!Z+(yaM*Px@ux-r=3I_`b_qbM|jpcCx~;6aISphQmnJG&BL$-xTLev zM;FSoD=QoC8{s6wPOsOw6!q)Gj7Ic}g?6plsm*Mmi0Uf#3qjx!2q3reuCAj;&Fmf) zm#n|D7y1%ddSe@KF$CMgBdjFHv4H!!y*KbR0A8t|P&jc48sqQ51UEVJ;Cl9SJZf45 z9v?L3W%b--QUbS}6e#qoD~wQ0&{MAStUhoW^JsIt@TS&Cv=H3xs}iOwLGYOmJg}EL zP2cbI$>y5GWq^b1P6Vj@l(`X3+c$05%|l0k&LOS5vXED6e&RI#Fx)2T)pE%*7KHq; z^*B_Cuuo-Uc0bo8AnTgVQgnqYkR^!0-y11IiNOQWzhD5WaMqiUbH~}8yP*AO1(x=E zrfz^=nscvHxxEGrnDpj;eX!T0wbQA7=ca%2<q?Uo<6r3FvA8M80h*7l;769-9?7qq zur#}xC`X~{j7FY!KMU^T!xRNB3Ne^|<JS2bDT~{%{T=T^Ot>fEsYfR|(8pcOYF`hc zyfLH{U*SH}P?LB@oo%6D{Te6@S}yTc9tk>ntUx#+fd(ee0|Y4&Z#(_;*R)68=SHbb zr-4lAuS1>=f{#@3(K}y%{{=L=L}^<u3~)^$RceU4&6>1NR3IJ-aJwjbXyliN@N5&X z9Bqy}IdIbKy7+L<BW5<Zila}@2JW6HjUO-;c{2W2cj1FDnb%9l*8&8%^Jmh1b0}px z8VB#Dno?%`%GZw1^)t#n3!T*7jBP^&bW(u+<7C$;#6^x3C%)1Kd8;M>i3t`!sF|FY zbJN-icN(o4ICsBS%uiYSo!6{QHyie8^xfE030FV8o$G9$V!e;(EJh1hMj%6Uj>)si zgb5L~kcVD?gHE}QYazat|5O#n4)+)G<f}GxtB^@kli@Hz`;c-YpMk~QJct;r1i&Xf z&jGTRnnS?V_84(LLiP`X3p6YsF4A4TQPt_tsHV=pbao2%PL05}ug>l+|Jx%zNw!Gz z_`TEH5nEW|`uQvb>e_e}^zHfl&J3B(eEg~X7+-gO&(gipJ8)%3U$*)HBc5KKYDcbn zx?0-D97U`gL=E%-oHE4Z7xgwO<`5m%EHR6S>VWc%Ur(H~{PHt<c)V5Fb<;!c)JFx` zw(mA221^a+dK#Sk`KogGV~&7+xWz~n#1lM>X45`ZLe-;X(!~u(#?$vWT!;(zb~YP@ z{NYc=n=Q73Y8LIU4R)zK_Tt722%rH;Lhu~sBE^I#+BF8^nd?NI1z$#U+1tPfd9Zqk z@aGM29EcaALa)2M<kDyDbovIRxeR1G9Ipdz0U7DzzyG5S^gnv;1P(&csKxc|M*%dl zbnDqm!$3}}XIQiNP@^qL;;@bDJYTN!ABGp2lW|AVqX(osw|nb=OU|#V5Sze)cdi)$ zT31e<-8*T$IneGIKBeD*4nJH8ZM^Qxll>VH+Zv>7T9veEJKc9dUj$TC4vGmrxdvhM z-I{<dkZXy&ou^52H(~Nrp<>$tOOo*0`v*!=g8ZTk*#$?rw}0o1ug&tfSP&=b-?Q}3 zj?G~4*2BwaoJanS`jGh>MLudptZ!({Ea-!g!eUC(*6nIca{8o@I8e-CLG6E=Z!r#G zg&<1;b0@GH;>CX$R&Doot*PgI7VJ}x^t(QF;Q5tFthnl`v9Vgu%g&=JljbgcnfJ4w zvKimLWQ;<L9<%^XE)K00Bm_TB$k3qQ+syF(PIpadkY#$*C^U#;R7rtLX6ZwpU_TdE zVP}efcivJCE&38)54CwC`BOfxOK<fQ&>xx6`^PxxL!ffVTQJw^IGLweb=Y@ryeeHL zD#1<lKJ`l}-{Wh3pvHNkvhcIhxJu#z?#1ULPI^C@3q!xylo?k>S<p>tJ5+nCAey#` zQnV9(V)6L6{GR5(HJ|7L&v@6ev>Aw*ccGDGwRDnsvcGRVtSYxJ%U$NEbnA&f#aJ_2 zFGFCb&F68!P>Q5U=FcTJQ)7#R3*OOALvAov46l1|Go_puXG!}CW};ph4;H3HJshRV ze7cDvc<S3sxaU_OUb0F?d~mdQEV$^nB-L_aX_`{aj@^jBZB2R}>5+#m!duf~OXYJ_ zlQW;Yc5ePEGi9MIoY#)nbnHMH=|2AImS3mmi_tsduAd4GR*v~tSMSphSX|k>V$pab zE9I%3tjzuT@?3rka%$+Raq>tC*zjn!N4vXky{Mudl?Aw;p>SD98<H7(D;z9Gq?ZzR zY|{w=!6kCL*{9K-5`7hBBz}|BMCGt23{LOFI5NRX^l`u(jGg{-iaIMu$>xZ}7*z?l z&(@v^b!M|R<XJwO6KHoOMl@zUrc3AA>1NNYe0iJ}7f22<{L#YyX`!xqO=SS!C6WTQ zs;OR?m2mVb9AMPiEz;cig?BU3*Q<l+dQ0lhqIk6v2MuKAHZT*s<Zx0P;p~yeZ{AtO zQNRyQzKSM7X7xJ~<Doy~p3xK0Wkj2%E&7^JBqX{RDcOOA6TeUB#~SIua3is`FwPpQ z7b16a@^t6Pwnx@Ko?C5QD%R(gK0xA(l_KM0@}HM1?pDpG9Av(85k!o$NA(uY@AO#0 zM?wuo$dUEY>1l7=<=rf8YDFr|?jG6zB$EXKZzqHg331MMvr5}6#{D`Yr2cSJ?yc)) zS<3q_Ga8TUG<RjKi{instjN9Xl4cD-u`BU@rdHU!+I*w9RJ<)Y&nM05$6AN(h+oCn z)C0FYk6x?&0Kj?D{uK_Oq+L7p49$n+_99^bypz3|e?pg>p^uk{e%`0}c;k!gy6krC z5mUrFa@o}3p^#D!JUzlO1n?t#;FM5P;+8EQvBAK-t3c&UCz~|UKGC(I!Nd0A!({}d z!Y7-)&s4RLH683zC6CyB3l@Kdmku{)v@?DRP#~N;MF`ov=L%b+wuSzXh(mEoRq*J% z3DaZc*vr|`OSFFeqQoHiW~ReB`0o#gKt3?p7g%Qs-jZBiH>%@#G}>#YkY+#Luh!g9 z$D9y6+r>QwtADNq&hUgi&9rPPfwSFazIyf=gU`S<=>VC7kAE0$0<*_Y$N#5}W&oiI zNkFw|YRdry91jKJp5x}{2Nojvg<l5dPppWvAE;c{R3}G`?>m=}l8H*!9vwTWRLqf8 zkk7ACE%|$pTdFh1_HtQfj7}OPbB+rVjeP=&f)lX|_OaTE3)e0jT{VLqoJ16HU)Al% znURu+?tIo`e1)S&%Z-*xD}*><!m%}|)?(~w>TTj^T!e}tI!#fDklADV$mnEoc;xlT z_}9^|<8MQf=c>l3=QtKpH!S^q3aE<kt=K;dYzyKGLmpxlB>O1N&a)=00ogS_1s9G1 z1IemqwGrLA4wZ4q<MbJ<<&K@nBI+DCwj#w~Sy0B^_qk0ioi%A_?pI3b;6|Ks)>nW@ z7D$|H*SX`acA@ZjU%=oG>j3$}vy~&IVjzEE-Zm${>3AJ@1!m&Q*LuD*w;EwL(;)MD zNV1PChCg*2Ve2bpUQipIWU`5R55R*%&;IH9{OcP1H;09FY66Um(cbPlsVKjasK-*E zW1xM^puw#($)nf%;b*)j7i^a8=ccNT)%Kjpm#P~(CRammfuPXqBbg}!hzo$jEfCM? zE)fc5rl>!l6yqf)#I{$z>F2;c%&YdT<HhX5%Q)^XH}BA*Q1h>>;^Fn4u~?YSlVQAi z1VPNEfrI%$A(ZuZTx{G0<apwV*}D?=EIS3T5WK=!C2Erv!iC^QhO+FTvKn?F-t&-S zJ2Pa{c1JvMB6!=Ln!5jJ@1Uo*XnEowiVV!rLS7(h=`5us6O`BO<h1b+tjle&2m1!~ z<K`s#*!S48`&pG5%f_r{crzVoHAHl%%G@ykr5IF!U$9fYJtUW1Sy5RNt<PSfSa2(b z>lwENz+ttm1_I-zG#p|sg>f?rx_-9gVq;*KXSiySLZziYp_KHVBi*mFH`z3-u;bmU zqjk3l%Dp4fk88fLHc4dNN?Ml!m;Pb+W@T^@=$iV#Z~jYjcL0(7&%BQ~H?=}%t|OY0 z7c08jQO95coq2E1u|GMb7EoOV-s~-i><zuhnH%ZVlhA?WC56-3sgy!uMqWKdoD??R zK4t4v1s0^d_UIFH)e>>zWdGsS8WwZyTlX&QNmj!%&36i?Ah0(D^VE!HIxxiT>PMht z`+gs>^}mtss>;e}5?(zhRz9FoGH}osRHZ>O(t>h!fpBhYCgF1Vr*HM-L<V308lzh0 zDR+B?{rhh{cp8wnt2565Iwjy4x%(pJ@Vb}!WZpntw^|K~g&rx>4b}uGYNt>zmoyV0 zsw`0=qHL2{A<#d&)zdp5;ThK*$Z78VNmS&6YLFjiwyA$HqzOg=y<I`;_49YsYM)$l zm~%Q<*uMi9C3MGieqVZ!%@)mn-|33xN%P_@jtfAAS_`QxE7q={+*rW7v@r{&n&RTP zjmxuzeQFj>Is@4_?pnX2WYgJ4Nd1u;v#hjy-|wG5FUH$5xoSoxY06r?7dTpE*1t5% z&F9idH%xckplGRs7tXtOee-i8ipk5^=3I{6j|X9qWVt{(Q_7JI!a0r%iKU;UWC5Mn zr(~_z4COcnE|0pyw54hj%4J?c1`hC4={QBi*mu!RG@AYNIQ0KrO)w*=i=sO;^~V%; z>$dsO*;xLe7on0SLpdn&rg>Oay%hG**0kC<-F^Kwzy&V@Lx#p7`@@l8kclYrj}J9~ zlu>!QgFZ~v9efK({!oUYyln*Va^Pp%05~MlsHYZ^fmCVicCG^bZd+D;6tFdq6VeL- z0+DGm-*6?>53E(5V7(?PHbw>rFDKvADycX0sdoSc{)L7$EyC^*xcQdRp_MsF;!^CW z&2BW-A~p@8zo}M0kX3P9Hv{E-SW&TVKmcEY>X88=2{aAR@WBEI8^2k48*$_?b0B|8 zK$fohJM%1{M{(aJ+=P(;$}oUB>z5?_mV)Cb&SYsG$Jz<?1$!&e4rCeYzRHTk??mbr z1!VN{P{~W&DpR^i06u1h@{WWaD3Y2R@PO+*8SOf<$111Aaj@#E)rwB%lnDif2F1io z45lm&msEmSw@sy4rQ>4M?9A}c{acPOVA5W^hsHsuoUCMPicLUmB~@KmY4o(ZJ*C*Z zZZz#KDnJVK9kRdKTukvK#<ikP??N^Pm=KO_v)sc7h|}Qi#M4I$ueNU$H3rEnE6&P2 zUM_v}na{twF4z`Zc&KKyYu~e~Dm%=tm3c2R<Y?|HHLe5t27r(}364ibchD1PHkG+h z0a;+yAAya-Ad6o%ktbROe4lACb4f|?3ofkv#jhuNSiizG*N!%8Ay(S40;-Y^ob4o6 z^nPCS8lVQ=I9hD^)_eQJu^kBw%;1{Le5J8upR$mmZ+e__PVkcRKDy@Fc(|Z?{L}-F zbBbw4p0jBBDVgeRm>_VOaD)o;QKaUlp=T(Nwkd_s-3yoAs?el+t{S@5JH5Gf+W54w bQsDS?UG901$3M@V{$64D|NG;pKa>9pi3Yx6 literal 0 HcmV?d00001 diff --git a/doc/guides/prog_guide/img/feature_arc-2.jpg b/doc/guides/prog_guide/img/feature_arc-2.jpg new file mode 100644 index 0000000000000000000000000000000000000000..1a3e3dd0a62028bae7090edc6f536a73910b58da GIT binary patch literal 113287 zcmce-2|Sd4xHmkO$ew+RA!`ZQ%bJ8_nM!3hMY5A@gJDSaWkM**WGBmH&pP(8Bs(F? zjF5eX;>H;7{GW54=Q*Eq-p_g7^FGh}{>)`C_kFvs-|u%{%lG<TXFtxCKo{;B7#V=5 zsHi}1C|{tnIglQRnu_Y5*S`*$b2R@9I$BzqbM$od^#90t1}28{=NZq_(=)O#GBPn! z20a5S8w)e*KR^F-k$+DA=Pb&L`8@ske~$RCjk9(T`+2Gk+DkN4mq66)R5a{VXWbw$ z2t;*`a<~87@V^c!Y8u*ebd+0SWTG5UcY$*IG&Izdn>|NMOF24}@;Qi>{Tzp=f-W8B z{ipPoe7F=NQgY9W-Ky%~elSW9S8{myih+@bmycgSLQ+cl@)czjRkiCk)b(!b8yMa( zx@-RM(PIlsD{IGRPS2fPT-|*A`~w1ELBWx)qoQMC<Kk1(-lk_{zI&gQmtRm=R9sT} zxw@vduD;=GV^e2WcTX?2uYX`{d}4BH`p3*H4!`_sWp(ZM`UY`t|IgopL*VH6AHAqR zH2<R3|IqB;>BUabi<+_qwDkYzMMWJ*5gK;dbD|1#9J=@EpZaiKQj9pybt@&es)IpH z=>dV;;pHeJkGL{Ug7}YW|4p<1XNtZ0f2G;~Q0#x|H49><p`t7v4Le8&bV|yLmj?a+ zCnVrB^9<yT<^*I8;Dm-mvjjXkA@~fmEk+EqgD|?dmS26jK6^!LF<qkZtK-FhFSG0G zQkhLErzhG5mT%Zbf@Su14_ePauae+a2}{@>6pf282Vw1Xm;w;kBYcsd)jIVa-!QS| zkOoZ_bNBVUngxHU)&2aQ0B?ic=iBkS;YpkIh<aqVtZz42gdpFAj27Tc)-)xQ8AoWk zs~jdjuNn9Bzbu=dC8XF(Sl=5ev3=L?Dtt$Flp#@RH{c=YI4Ax{$&m8@KN%5gdUY88 zKwb+|Yb!MYWlOFkf7+(+b*Ble5pHR7on>&xS1Xym{mLP^R)`SB5(`7c;v^Caa6+`` zJp*0TR)ISZ10yw!Dy?B+-R?^e20*C;bHP9RM>N`<rM0yi`ozZFU9ikmvgvE8&1T^c zX2$H2%!Rk%VF{y9nN29+K~NhlY#Q4J21b`o)jF+XUcvc!lQW=9o4a@oJA+>1;u_0` zgRah3?6f**?|jn-!@56Q<8+5M>?VfMTkBVno&$zz5t>ZCxaLK6)y4w%2b*iRPLz!l zswc&GUKCag=5Oh8HL$nzjg~bGbkl5Hky(Y%ge?fmC15ek6>Xv<*#?4qG+FWIuoEt% zuf_PZu+;izLSS=!q<QVh)%&w8Q=@kgK0baN`s`I53+f0!8oe!ALH>rQ;od35UH7bn z`{PZ`x;k^XqH${7$CdfMLKV%5XCRK=XNufpQGTJ{H1pEvWDjK);{$`!=C*Tyya{ow z8_X-;JtPPfmVs~p(VG^=GgoD|R}=0f^MA~*a#Svll6}l~=be1!p5$Ux$$z@9%aN?4 zn<H>&`KCZXTE)6RQ7&#Ss&>-TQ(i2`Q}MZeio-{)jJN^CFBYKmCq9wZe~*GrG~jMT zBEYa@=ZFg{EBLLgbz0u0;jVqjxcOA=<StVv-K=}YyFqp*SFsb;kJMBbQ>v_{pH(R= zfOPI{RK`@!z)-hqCTiyf?exqhM2xd-%3L2?$~pKmr;3$c85q!IW}v;G9|jGZ#c;Gq zyDu=D=7%vg^yqNHicQiU6P&|qTOVwij6K0LVWt-cCX_p;rmFORG1<i0qGX1k*Gk^} zTK-ypS`0V!A!2(M8T^K0Q3521C3M6=Kn`CGkv@vdtrq_m!nv_aJuEgq=$UV8IX5@k zc|eqHxu<uva8^&m?o)VJ+_WfOewL}-o(;$^1i+7pnAge}fz3AwNork(!96XMiQ<>b z#nn4=^cD1ooO_r^+0FCUfn8k8wgPeUAdfiR4x!Up%_pSUPHD220oiy1O)X}NsZN=% z9v-typ0}jjT_w_=r_+`Ua3}wIBPlZ!#tK9AoPlTr4?X|`XCPjG7RMfI6jBth!0iG? zwb?e=p#k{z4kzX$=R()PARiyD{SDzqb?@#=PAwF#z5|8jj6$>2*GOFBJ*XOR_in7} zWAbGHNpv?P>~<Cr9d(KH?J=Fa2U-0SxGz=7Amwe%y2A0F*F%X$4O@*y5mpyY0(&qQ z;2x(@Z5R8AAw7$nPl5M11QX!>XoBRAD{EC9G>h_j{L}ckvRZwO)u{f!5wm;|>X6g> z>NDgj=!80+v=3;U*peLWoR`RrA?5HV#GIOCS?h&GY#Rq^slGHH=HA7V>C?BX67?(V znQw%XRJ!nH!XQ$MIjNSTS-X=!k3Ho)NT{BwMY19~2MF^UR@Vfg%a*ikZid`i${X~W zt%%pXT4J`8{p=!3pM^+xpk7a~713zq3{+dLQ=c&b71G&eILP&~{ggfMeODeP)6CZ= zcB6t3NFy_Z5G+gyYulkG4`E%9Z0N-H83-pnM&jftt909U%RGMF^!y{I-Jp1NjlxjR zoE-1@R}x9wJl7((n?TZe@&6x5UTa&7Np%JuZ&|UuJz9`q#dpOZ{8<fWJBT^eh1yzX z2{W5dW~BolgcxWG0ox^{_83@S)-Wl^APe~0T^c>&L*0Mka6e^ALF8`-I$m3mya=wd z*tQcNEF;~j1#aM)6C?6qJhBbAV3y;=_vz3|liQbvbt90zmvJqFiij=051FC)hpjs1 z%P>^8Fc=4%fjTQCuVwC`gT2Y~NsB`TEyF){lfiZJUEVXrMkn6gU?Bj~QNN;Ae9%_P zQua;fhvAd&p>H{%!f@j=P~;nJYL`s&Ss0TEW$V4%QM{)U-J*4ACPqll^rb^5a`(!Y zKYgnhWo5P*=Z;{rI=QmYBAqz@!OVRx71Q8=iOL;t(SfUxU~4<~Z=M6<OncSsI4&2} z&zH6z35PSD3d$2wYb&n$`-7#+$a0HmI@H5qZ!Im=m{D|VryHsFp#XDG_8F)><qvNX zVyW#61lIHvL(;(M2#D7e!xw%6m~L<QFnL_pt*RQ){Pom*fMjt7I>&ihO%_*BBH0t5 z5n_l|wrIHMxjyWtkf9yz#-W#QEv9jBh5pM34n<Ts=1ACl@7v%ycQ0SY>Ff1T=+9S( zW9W@+JR2X}pSZ3=ctakC3Q8;<P8&|qB_?gha`|lA7L^hdce~${=YTXK0y=+)sf9ZR zsqUh`$+YIR4%qUijE`M+Ax)lvG*CiuME67=*1t-O2_#vHhc&vh7k3777^YfCJ1Fyf zxs_Ao`I1<321>c|^)#}LM`jnwYF3SayG>^!msh9Jqjv7mFa6Iz*J{r|g!7ccRxlTU z!seC%44I|$4Ad|D$n%6B5Q99Ka>WbsK%1tH|Kih+!}c1KF_BrAXyR!C5xV?1qG9I@ z<P00z5yC*;P5bIQX>;`#xAB0b3y*}j;3oJ1GvYUQ_=XYL^DRk>D0A?dz@vi$pB9J7 zRSq|wHv0249-ZczAq4(_84w*N7>~v1!T^#!;7(*W2jIrI`%i3xIUPpH{yq2Y?Zvu& zMx#kzSHd2oo_YdcqX^=7(u)d2y>I2%Yw+?QqWf6BeUb3OxtERpPAQT8Ab7lP&ilv} zv9!nm>L+hkbY^;-fu?os*9nvd<;v*?xOa)(Q+)FxKU`{Jt+N7?=*QrBAN6%Vci(~L zwAhJ{RJOzz`Cx3jE?cdkx#88uf^JN_OILoV?$Y$P<raw!Qz(P=eZ<0DW5NpJ{jo6Q z&!?evm5aj+W_i1GOJ^Wqe?aU|24{!`pCbhl2$L<G_(c`~V<G~sbD4dsHYyiPJz4__ zMQU1@L%;iyziA7OwwPocMoCPC2?MFj?^F<sZXB)__c$Z>-o@VU6Kb|-Bk@rJsobzh zM0IzH#A;10JdDsnL)T@W<k#wR!8dl-LC~&=G%k}9Y|*jWcF~zndClxfIieXurrsiN zqUs3K$e)+9>h880#$>PGx7Gm!T0F^8oCjm^!0>?%<<hGp?$Z*IE`8MBvI;|-4sxXv z$p&=r^v&NGCWY9p^}pjhG*}53W`I7o=rrSa{Xw#P+8}JypjCZh(pvFB!ld#})}9N+ z1g72luLsDhZHgp|F>P9s7|}4P?l4u0vs3-iR880@=-Hku-WBR1PTlh`oPl4Qd4%3r zAASa+O!1s^Pn#woBeT*KQ3J(Z{xkG^OlH%_{-pC>?VEv!(Rl5zm9NWa>cXFngu~FE zq-nmNf!q<idP|5IBsOyomfuNc%0A&(of@<u3Kum!PcL48@V}bek+Wpy;Qtlp8-3#m zb(IJ>7URsuLt+Ayh~R@z_r+O_gO{0|P-<;{2yV{OQ(MIHv}m`R7x659XW#J}RJ_Yu zZb}~GKS+wFnm^XF4<%|GAV;;i;m-l@C7U@d`&}C#H!#$_F#Gy_TpdpU(qFTI`Fo+* z`CQ$5-7T>S-*3{d1r*{TF=Zjeup}K9<c#?v;>9zN&>B!$zJ3VilC7xl^7~VlHEh;k zT*Z|dR8N%6=eia<Gi9Pqu+hLfM~8tH;FbV7umE-jI-n&cg1P<2(KawF)|#ABvbn&R zikE)cm@K3A%CheKvI75-VN*R+(b?jh!Ro2_=_iCsEAN5NxTdU6`K(*R?lK$a`U2<p zr}5>am5}Bc_}7^htUh}Q^Uh4)Ll3&^^q5a<ug*Zv!HI|(Y&+YmQa4%BdzSaW_YCwp zNK@z&Os$LO7?J4buJ&r7Z+<vXynZC;@rd%YnntG$Ql9B!X(y7qF%oA^#$s4WQYB#{ zsOp$RxPC6_CWg3}NYW~U8`LIr39GsfHm}dl2B{9rIjG%h@~-ofcWX3D)OlRFga1;O z8uTlf@2Q@6>Ya|qDm3D$Fc9nC?yzr&TAq}X$8c&wL$@9Epv8DCg!e~ft|MJ3qh7$5 zDpCGXp$RY0wJu@4P-&Vyj1eGDFt<Q1|DA*Tp2m~;f5J_w2>pbjv?UDJ`m!<Mv^OPe zdR6evxvGznS%RkfdHG)z$=j+1Y;|x1aEb%ZW#ZVnAxv<C(~>ig(;0}`#a?`5`tF#f z3T{`}wN13fxHe1X?S!|yoMT;<-s){Jo>9Y#4vH%|2L5~Gw*+1im*Uzo_+WcFoO~V* zCDupgx;K!)>XT8}7}@gO%Bz*a3(v#tHbzWFgJS2b@@=O_w1p>Dr&@FzgM5qaU3qx} zh(oebbGN5?%mx_Z^*H<4{lrTZnu~O2zg@dSzgpZ*@wqcO;3RcOyrxy<8K^@mOvqK8 zHC+pRARqA;!nTpRd6<UIIOJTkotZQCr1jZ-*brfS<9%XUwS2}r6x)pau>*+?C?mMz zp<6M8<(^~uI6oxs50#9Dy!8zA)`j;koL|lUtq^*)XRBP=La%UC*s0B^_S?w^%1hP; z0+%xKaZEzbZ89cW0@1p-d5(c8&a2az4`lkVUo7#jE*GWz2<Ny&xAx2sbc8)nBYMBa zxFY6wZ2{D0_ya%zzZ=WbCP?lcX^~jc;n&4q*OV_{$O~!C$bP0cB-_&;1IIYWIqEX& z1xYM!sY`#Nj{onnKg><?Zw7qu8t>qSIJOHNxnew#c4N8fbw%HtmGsZ6T}bIQip#f$ zybm|^w?7BOd?J~Rm_H<}))cun`Ng<2erYt0J!JiSH<gBUX-{K>Ziwst&2#@vESOFp z@aG8!ey7=_(B<_he$I|CVayb%(TwMLLqpJG?R<^+DA2{!c2*afro1)}K!t5vgQ$d~ zkJ2<MA>9JNxf{YFquVMn6)ItT8<}E|43`In;gp49pbpCBkKg^#T)*b>T_z9@A#ova z^c_eZ7`jVal;|{xjU$6+y8`hcEP`FZMWxzEnmO6w+12<lhAf$<oHEMY@0J(hclg6a zge!;+ou(Ez=QvM?x+(d>#<9vgV^2wA*k7h-7fad(_h?I==ie`U8{~6Pd()^wT<Zi! zal*N$$n5j$h#K^^gb%m_!e|SFbk%1D@4m8Ulf!vVh4jDLWE}F_^!ij?-AmIZ#?N;w zhKFqT69#b}v$xf<R`bi|-J5O_Sw5npYgr7t17(XYo@;~E0#dMwcVC#4<EyG@WjG4h z6iy3tmI||^x}bdIVI4x;Mld*5Q<j)RKE@lL*vPb6<JXMqzPSGQVKeKM<sSWU+mW%V z&)|Sgn@NN|9Y7z1v=JqfK4a-Sz_a;=Q!0=+9YSqygKGthYPUkg3E3aT{(Pb!q9QN$ ziulX!U$hUbvR5nE;-CyFyTY)OUiI(UgusIuf@w@Qss_dPJ4cAf8zH*|zdO<^Dlazp z*~r&p&*rn9*bKz$du*|2@9|$~GKO%^hC#;}Ll2bUxEE6Jo`zU$&9N4i;-W%V-wSnL zvreD3CgUf+DfKAx5a$(=A+jlNl&I;ZHg_owD;IIzZ!t~@u!nG)Oa}xn5r(Gnc@hwE zQO;#T`6t?*kDjQq+j%+ZF?|>3P|UseOBNKQ(^;Xuzl7<TL-7J32M)mBXWKYWwT^oA z2ODjSc4`LW9?x>_<kctne_C%Wb~yQ1Q+18*20n9%c?wa}7DqV7E=g_c7gHi@TeA9C zixDek$$847E~YJuSm`TSelYgzrzyM96F-GJx(|N%{5b=4gXes4nVn~#IJGd&Ns`|6 zDZko=P@An_{q57Da5+U!O8zAGDQbI5b3_s4mMXhU`|N@nlEk@t@M`)D<Tm`{qyxd; zV&qipI*Uvc`8wg)P!)aWsj)#*_EwBX@^;JId8UuuyjKml!a>@W4X1A{ET_XnH`=ZN z+$R?BTa)C=urM}OAo|dbs1`A0l=lj6w3KnKZt|0{m6$BweQGS<o|w1%H$@}KoovG0 zO}oaa9kLjlni5Ycx&^Pr6ce)T0gNp{?nL&APuzCJ81_+Jyx3(>%LdBDq4fQWczXYn z>m)y5{p8s!u-GHaLA2=fW`M~U6LZkGVb-F;B|AN<riraBIhKYwVZSL^^TX7FANMb` z>wY()8P)VY@q=+51bhH|@w^EZ4~PK~1x2NJs}>cU)`Oj4!$?=joo(5S-4oUMSIwo( zA6R0CTGOq<>7(J26zc<tA!`zbV@djyJy!{!N?|;GKL86dN2_nUJZ}tl{<VJb%dVw! z<!LRJNyT6Hi)PPT*zI{ALIJm3VZ>+++>2teizClKM<I5+J@RvGxZTdnEjo1h<@Oty z3s>shw=Z>d1*;s!?xMFJ%BV~P%)*tvdG`MLHmBLr#4_VV--mEP0#`C4TWFS0k;mu= z?V06n09!dXvtHwB%~Sk26a_H|oRD&neG-)PjlD}TH070<xRsiu$UA8|?3R^lDO@OP zzw-;64;cSs1uO0rK*!ZVIbdZE39SRNE5EAe?~Em|m>J#8lwo$bE=V)@^94V4%)etU zY+ReZr5T7}4*ug2#<c|d45={@9W$!4=`1qM7I%tB|6yQRxx`29W9yajPl5#);UQe> zO+4w9o59~3%Upw>H+UDjwsB9Qy?UZQ<v7(%r09DLb7=$|rQYFwqS#%-_pK@#bg&`Q z)51$Rp9#<-vSFJLF|`P8(?Hdl64Qe9;FMAH^2pzW9}PztQ(5`#SG}GK+eQvX2Rb;s zppyQP2Bn0);czJewtJ@KatL1I2YS2iUCRxhuqM`g$vD^2fszNkcK4sCD%gS*6;?EH zU3Wg;d`=y%mGM7(%zyVa|GV!pzYu_o6p5=>=Z6%oC_5jp9>aDc_%!{t-EpBD&Zj>` zd?Zf$E+)X5{tEu^qy=p?n0?qVHGkC{EHVGy0)02?^5Y5#z8=-NQSmy@w!RI_(kB$b zd@)9c0MTKZMRe-P4##S`R$jKF?^HLFm{f88MbkjG(o2byA$H92M~@#VoZKM=09eXI z3QTH`6C-W4FA}s@Qpa&?F>>~Tv^3Y%Y9iZKP5jqfG)rt#Y!@TLgekMvY4;g6-5cD4 zO>7efGW2}PVXqEXGYqbuPKXuUE1`PCMHNm5qB69BHWMfgLE7N@he_YzFi3SP;yqco z8P#JiaVkQ5H=8yHJU2_{&M&K7BZGe-oryX-Th4$@r?vAdWy{)aFr;?e<0)92XY~9? z$dbQQ<A(dKc$vSkx30w}a;NINcboiZ)s$}YHm9Q1Cd`A9hU8!SPtp(?HtZscA2?oJ zbi75k&}yST=DN|iq|!#B_A~7b-Ae3%&FNR|>y(F1tss87tDynGOXj+HGp$o#e$><a zPQnex;`t9BsK%t2zb?rwH&vIQKMup7@<X{E54Cnut&QNv#~S&&*X6t6`_VF&S0)jG zp{|3LI+=!Rf;vhEQU_N~TeJnqizp`g_%LC2sE1A91-D?ku^@q*1f3hvtIVlM9Uc6S zJFa}Yfp$c%Rmy;Q;H*H6E72TBR|<~S7F*Xl{Dl0&#@^8pV*I0nYV^ysd0o)23+0$< z48aUMci6Q^xVJd7I@gosL1RD^&b~a}0>Q0I%=>(DV>rZngqwK28f~Ln`QzjS{th?o z1j;knw>CpYGP@)wkbz`V{>gF|nnQ6%u0tJwzATp=Hf?n{sU(Ji7t%%!kEQe4o}FI! zuV7s=D`4R2-}!~+6SjGP-Xv&wl4A3b`UIAI{lmA=#m>x&Z*GE}Y?2`~rAq?GO^wh5 z42>q|$xWD-kRUdPmC%q>o8X?_8jXdHJ(;M;`}k<o$#T`;9`2bxGu_Pq{tjiTF1XHV zCfsVt)X^vdg2eFrZB@Dp+b>vjUEnn~{+b5T6VuJ_xps?=A^En4-;*Hpuy+EAp+$m- zI-or*Bx`Mw!L>y1_%J0{*S%3VtxAmhyFUbPF~Vw!zbg&L8@sS|an9bh=RNno_I|SX zje4c?1Q~%~ZZUVQgn2JvI=$I81I}g5-5ZCC7SGz*@H|L-V2NjLeC%{xGg_?Ge`=9h zlg)W)o4%_Grqr1NLv&8xgSs?1xbkc|=l{HUvXnJ@AzL(6?I`69b@3bBPi#YMvuLYP zxaksjmIg1M&~k1`K7N58Q1h1RN-2duASURkq7Y6`z1Ic{UHgmdu9`2{{xrB<5zxTd z)b;Jog{g+EL&8ZHrgm)`LeT3#@S}5y?*W|?Eh`}MQ8kfeq^W+=pGALLe<IW8+ufg7 z<`*_K{1Jk`BIZ^fsvI6BU>tW}qb_KMhTvO6aNb=N-aP{8H8b;@ykvozMod%0_E1fa z_%46SXvIw470XC|X@l{2h#(mYJ>Mp2ttl)9SP_=HFWe#AA#T_UR5u&Ai0+9vh$p^s zeEp7sz%mNu)5L>FQvg%NM%K_;M}=UQb?9m_PKVKbk-be0kkU`jd4$xh;<SQ=QvXWv z+H<4t$BI&)!=)!XcS54uE)&69rxXNOjR!^d1ehnfcU$Yk`XS?omt`Rjh#8G9hb|rl zRCv?He#^**Se38To!qIZPgr^L+8j022dB!lfpx(3gyRZ|+A?VF+L?MR^Cmn8f8*)2 z_1+64E!YR_tnpWdv_oqsKxUM^_9WZ_hlp7?Pgsms*;PA%SdRUXvC%j+9C~9c^-<HM z+NkZOP=mrC2qLC@p7aeEN5iDL5d;(OBycUbn_){nOl>nqe3}v@44#y7|3xw^bbOw- zT+b5Du~D4s71LF&|IIs;j9*!`NcttUi@e}gPcha|K#FS`+>|_xqYtO<Z8ney5d@Wd zy~wdEfPA^|cWM(+wcAOl=ggTC<?;y)xbL}mEtg(@p~q`oj~^^79=+5T5Azt}4^lOv zWo?e@(&N9Fw~QuEhx^ILYjd=XXqx7&YhN0vQ{F=>&zpVMXg03x(|8tt^M3Em>mqyS zXteby4iQGFJb}qH<Q@!*riLRCjMGMW3nO{*eO*gPYLqngX=97z-ip&#)0Yw%5bYpe zktiDB0A_p}glLbdB>4gg#6x^T_b?+#bke_hmw$uIHPUh)@6G4-V)G2d@~gJdT}Tmo z_e<SqWzGWr#x2{D+P9{@;<!ceB+M6;uAgDwFf5g11*vYMFfi;AB$j>IISzHJPQ4Q^ zFYd7G{6T?thkW?+DA?yF_#FHZkp^~xmr7Ov$1czTzC`=!10RA{N<L5yze{u-C*ANY zg*@fS^$m3_Rz(KbyXs;2n!YOBG2F>dGC0VLJ`E3JbOqNQA`y<K@>nu>w8fIl0O))M z7JMshk{-r-*YSNClQp)bcgP^}n^^TjMa^D*cK=gMDdbc)bg{*uE>ytn@Q`RSHIY7k z>;9$ssXBSKS-TCM->=_3%(?R|o~z~w-LenXx~3>>Xp!{~lpS!itRe8e+Ezi(&Il=W zHH`eu82$NMHA+Cq+f~GLis%t&my&K*-o+;wu5%-%`v=_g3`F~t7?AJzdCms5e=rY3 zA&Okir(SN#m@}WqG)@4$>D368lXw{{(ykF`-r`GWFd<NUm;9XAa@%{{kW{zzTGz*0 zP&SfI!^Bk%@?7U8Zb*IMo7**g5tp8CY7D+o*|pU{%rsY;3&SE{-UrHn?$RQUYHI=f zGT>S0jx3QYpG`tVdwgnk@7bsR`Tp@W@{9eV?)N`6r`J|*Y>|YPwAgS9=@Q78Kb|tT zs<T$zXJr4J+}U<W4JuGHz5Ecw8~8lH!|8pTc-l>H7KXWv-X6{lES_lSKg}lz5>UyB z)j+l_F)U(P$gw*|3P{P5{ZQ?ey1}e`Cz1HmSlqlkGf<G0*qI`<!c$FBTSBp+lI@v* zl+Uxj7qkh*SY-TtcLZyj8cf^2me`h}`6FXmf8t4VL_r8Uvzn?&%8lFg^**vK;y4|{ zFc$K+MHUKb4cP_*7K>~x>`Rbsq|7!221mL)Zi3FWRFI+Bzb<*ttQs{0__S6{OhW0% z{U}DV5d3Zv5fww`C+Uo|JPq47@~vE75UQ!0s1$Ipejf5V@lNk8BL|yRsShLcpGNh$ zKo;kgQ8UGz!s^r6*6Q#k`8W#B{$?TJ#j#gjsM-*N`ISUes@;13QIN{Q=uP2A!taR| zxFGME#dRG{zjxR{mgAzdiW2@aP{t^F#@XuwUj_E6@gMF&9A?(HOT7r~UFa@JS>)i; zagPLJ;zjCS*F{t+zv7dxn&7`2{UiGwXuZ$&mk0|V@uxh?rjzAY>rB<R10e2!)Wgh! zzx&!tg}d*ao0S=yJ9ybhFcwF#wOD)x^c~g<=e;KXSR9-vR|<14!RyCwsS{I8DK>$r zj8b)E1wk$Xm-a&RMQv;dMca?3!3(L=)H~WYM8)14utJM&YCUdyM6n-(t^(L3gagy! z`E_;qIF)xT-gp+l+mp#L`Sxyy>S6B=3H>22J-5YDAL}>7-weq8z625v4~qwah!$N4 zp4#X(!c;@iX258Dzx9}ZO2y)v2l^+YUqxP((@>umi~lW6^9%CYp6>Lm99h~$hmb)2 z{>4RGEdH1R0^fzstUVrm+_|dCcCquoQ&M_+hF_0C;P&iIk;wQxV{}ZLPBxk0<B2XT z(u@!o??IL%kJ&3sK5ZDEyWL2h8uyS#TNu{5#||)DN@h`2cwyD~`SSB4t14*T#69{| zba$u@UaEap82-G9Fj?G-VRFx+OLzQ4y8Z<~5caz6)f2tmI~R%6sx?hcW%_;Y*D$LP zoY!6XjFOW~g`jv3R0)-JCo&{UK(G`xjl=W^A{j}FfZ)@7EW&wd$na4Xw)?mR<JlJH zS%FJkmf>zl7thnG(uiGo=6X+ULxPLy2u&D1umMnbWD<gvwFWoj*cH=FRv|X@el)mT zF>5T(WM^wd+26l20y(iwoWTkHYt?0;z-s#whDzRp;M2Eo8#K8O!-{dvJ~{)rBI;x( zt^tc()4`Hyxqx%mDihH^D2S&)HAZUgQDw|W#@YGdtK=t=x9^K59QRm~*?@>V(#`k- zQ_lPKlcM80S>J;yvf;*x;Z`)r^!PP;*XvIPf*yeA*LagjhReusMAh0hlt7k$jp88L z5Ph*^X`+5lnQI$oOUroOpsWdPZJV90m}<4S>dPMR3~5-)dM1DGreN9D`XBc*(2rd* z!?E8YlgspM8=5fJ?l664>`${)GbIYC{W8O>a4RCqFo^vo=wilNBicDHoI){(p+GGe zWM1IWi6}{Z<nO!%ej63*`A5dJ?wyCWGz@jO!SvQMPP^^;228Sajb>^pH?MfAfe{+D z6~;t?%$Mq0Pj3IdZ%-cG1IF<>$#tfBMx&ZHaNCN@y2QsH1H_{H3#ZYwA${dzGPe5C zUz;8yxAqio4_}Hy+$*6(ZaBhWFQ$gAXK;~W4$-+ivQ1*3nBp#bcEI0%Nr!fQL8OuB z*>dljWIbkDt~TVIY?eklC#Oo{Wj>=U%^OdXD3+cKXf4ZwV5kG7S|TP&)AzZu4il`Q zd$#cJa5Vba1t8m^*`zDj@pZywT3)pR6>P@4=eBDu=<&}KARE84iw&OMawh8GoG@L` z_<o}C@?j5)^>oh|qEn(ow-E3)oA8fxI5fNmo0?sn_j~8?D0SBAriFobidET<7N!$< zSXuWX9mbPsk>z(&OjL^}@zU-+LgwqX8JZtF<9}KOw3LkZ5<fZcyt8dGVYpRu6uzH! zC`;Lw#RU3;&?#++budVi%E{-%XaNYp74{<WLKddP=MjZ~p*|t$dq$jWYsptnI*lZw zq0S%)PpK4sO>9Uam!jShiUlaM0cr~SDFGLS*y5*wiEC3o@$NxIl5Y?Sdux_LRBfWw zvg$JGRPwCLqQmWaJ$EE*;)I!R76zbyliHNVmWZ#_X){L*%YRze{ZUO0=vThdAvCT7 zlTnQB4cN6^e)0Vyi0i)o|50&<VR{0DX$Tpmm2M3Tu7$s+QWx#b&Oia@9d7Nc{kW0_ zSnO}-k<2MoTMuLsCB8kym%v*su$gqStYbGBMwKm%jBT8@7#=bI3O&$hszOi619E4e z<VtN}M28qz4LaM>FVUOC`mXotufqA2*8F4*uJ;iKQYuHjOY@BKOfbE><0235_?=v@ z$bWc}d!ITn?9nkQ%F0gDK)XmT4^w@2p}Gwtj#@ydoJs(xZA=om=_3Kh-%x5Fo<3jR zf0=YDJ293QFLO*w7G#vp3;#znSZJ2m5=iERw1>ngRNi19&XecYto;I3`Pp0_?XyVX z-D}|zw=6H;W0Q(Zgi-_Ghd?I&R7ZDIHf*lUt>(P!lYI^ym0{h+zWcx%nXSbi&daJO zg4zN5q>7!_fUI8Ebeo2!lEte#r1q(_85{8!Z;h%qcb9fR$$zoG!8JaoA23UKP`0J< zUnkzL|8ASf8s2QvYn78liA$0b``<7Oi{$%!WdyzwRUTRJ-YS3aV$E-%K2zLleA?e{ zzQXU%460&+u*-5)&ML9%;oE$hnJdKcEL2@~qLYv|gH^$7K-Og2Gh_zI0++B$3(J2n zT6bN0sMMAB!Hiv3D|8@BO?tD@$UORiA_M(Jfn2BwdTYj+ICt<Fm??8V?)ojvN_gB@ z>LxI>bw8+vR?T-iS!HeQ2{JPBFqq?JNsG*hGU@7RfuB~`IL^LqImDaSB>-8XR|KSL zJU6xGYJbYv2{P!1wm|OpDh{s8iFe&%nzLWmA1Z0HY!shdG~JyVd<;`uV(zRkx+*VQ zcqRU=)AiDchrh;Gk~1e&#<Pq{=6}PdZ72~-xymp=@wSBbr!nNq=xyj0v_5F`41`@w zUkkEP^F9MveBW*kan`h`fXh)T-rTw5;d>-w;A0sqe$Hsh8wD9v9-?}B;<+#ClzMCI zReX3EtIuKZuM(|AEZcdQ@hyrY_gR-;GPQU#<!9=R=L$?QEV)%0;&geuFs@>SVXr1q z_+>t=`m&Y@9u}R2X5``wEbW_1Si#I19YX!bZ89?n5<yQkmK9PHJ@uy&xt52Wy^OAJ z965y?)<ACWz%%tj<(Iu@FgWnmjATkK+;kf5AG9pEX}PmoK~fVcsT=J^`HL%2fA2yM zPOwJGpwv!FG0srH8N=(E*JUoS8x1#pDqNB0=AeagZ3w&hbY@!Y`Uc|%<|Y57{hxA@ z1+L?m)<B-|yGGsv$A|mY6>Rb<OWy|NbJhPIL2G;-iSd`-&CVF`v2o8|7(2AfiFs$? zvm`%*>BVri32lbSjMUzc|HH;guO2n_^Hz>Q9|_y36ayEf-8P^48hlDaKy<q!espdw zS#+KhAjwkw5{C&6{<JX|I=;!1r$Vt>2c25(*|EMJ2CN^%BI7?A+0C4RuA0BCKayAz z55CCI#dmSG)oQg)0>Wmhf5TvUtyG24{o$Wx-%NYUyHn0<E8M>+e4389Fc3V1C?EBn z-?Ln9a7O9bQARbK@FAzzQCer4PN-~nbFRzbGG4m3RSMQG*(zL&UA@lu<KiO|9tmr| zU&|6RJu_rceXhrAeD^6)sX5{~3b{`S94RG#Z+UvSajjEi2U)Y3@=c?G=KRR8h>iRH z4`mKdiKe$d^LMlSgVwg4a`o}@Gc~<$OiBiY(^W=TMwG>d%>NEBTMQAsEFj>wQ~4^N z&5Q@`TR>NS&m7Z7k&K|?cn`@d3Ds{WB%3=uB~eA2Lt@ABc`b7X%EU=*58Dh44ie|J z;3`MbTiO;g|F}B*Zdm25qJqc%hpO-HW9~<qXCSlxS;qUXK&vvbzzWe|4Yw2J>XdII znU7y&|K_2rA^9EqF0poOIfYi{y}0*ICH=R7^Yo6Mh;v&t1xordb4DvBCAdULt?Cp_ z?(D#ekZW2SZYyLq(zOP_aLGlvWXE|zZf0Tg-h>>h^F-w@jiMaAjc;c3`u9Fx`wZHU z29>A?nJwO_Rhl1WDQA3Sl6L*}x!8M(uwQTJ8@aXa5p|-KcLjie!#k5(6?L-m527k6 zE4;)w^nC=G6{~a3i;SE*mchcs&>PSi=h$+REZ%)H$+#oy^`JX$_<~*Ev#ef&>qxV< zH+x3cExq{2`>{WdnytMZ{!OX#Kh6=W44!^#9|w+8pLIJtzEe-6m8lnUH_I|+F=Ouq zHAZFFVXmw&af>`Dz4(|bOaRCx^eUXDSFE3b*p>T+d9nz08V?`!;k=fR{b@9xLi}Zs zS@y<k5Awn_7mZI#;9A}Y?_!`x2-2=zH+Xb^4i-=4$-IYnDOe}#uJj_za^?AYIzRuP z_=<9usT|R9$!bhpeOt{}yVMRJj()DP-vjNhwCh%1h7G=fT~|i2lJv?*+F^Is53;@f z+=6(28G46@x;s)Wqwi6&ipIq_Ft?xl>sjT%toh#!ClB)$#uk)aE77Z(u}`9?f}Uxm zQ)zOJaN4t!k*6{2SBs}=wPZTg4HI{3UBiZh@ZPLUWvw!19=Mjxo6*i6=_O}pjplY< zt><W<XBrF%7I7+qXbvl&Xc0?RNiwZ3EVENgn7{skr{36}<#iC~Nc7<c>Xo@wx%r-# z&j=Rr2p0n@l6`|P7a=5R6nH+ncB=8f9CdUa!rz(8H`H=f_m^fegYJg9aEue~qwpML zyh678>eYNp&+Q64dk?jA`=k5eAfYJhyf>Zyu8hEHj^FKc*GUMwm^^Efkfii*e1$jI ztinCQzrYT3YlvObPr{1z@$KgZ=Pcs~fEz@&{ch{@wJ7)_Z@SFo3Ra2KorS9jo)3P0 zEJL_JWNC63f7L?vbO<%a=X@6VwJ+!qZ4B#R^3Ee9!@L2nKc;Rox+s&cy-JbYDc6sl z#kE;oc=O`LO?pTD7mM`dtG2*^@eo_Ls>1Ia<&jB5ZS9|zgl|c2G6TN9cvhcA@48W- zc#XNh!uMY*;{Uxe{=fGwOi9nr-2~2soZLfnXlu&?f+i5PM^h~tFJ|F3zH4@R39*i6 zpa>%lxe#X+pz%ZpAj?y@Z|6vA72WOG&3xVM7q{Ni_45+^pF&4g!YJ&S4g<uqITRo{ zy&YPzaS&i{*uj<<oNvFLd1vt};d`CPyw-=v0w0r(9JzS<0qtdhQ>L!O;~eO_CYAZz zM-pK}aJ9X8_;4p2vD9J^^v00;6;j1k>1FkN2Rc+<#YtZKaYp&7OI|!VRcCnQUyBYj z>rlos(17$mWJf0|oj<9wtx9BuQX<+IXcUg35GeM%CgGxCS<|n*pQRlp)JWRggNS>` zM+^@@Xa=o;;P@jCZ)Wpuocq%ijT=MX6^$+HQ+F#fA?`(^#|99*EF7cI>F7FUrtE6) zc4;A9jQ@svansItGBV@-gK5WY9cp)V=j1l=uyH6OTE$oh{E*nz94MEdHL>WN98%(4 z{FKRPdR0<W-Uk!;;h|2ocYA2yfdJ8~hA4w~`vG`$8H~$OARI$XwEIVgmG;>bagVtO zs^;W7S~Tp$bncI4{Mp6kY>ZRIkMvDnZftY&4ji>EIB|!R1_|*Y*eR}v+22E6Rg8Ic z-FVhoChKJ>_w_wBZKI(&R|;u<xLlcy7IN}5tSg6^fPL*;-9$upm7R3><h4!&R4>>- z#I9#4OWg1K8D8_`m(h2~Pzb)EGgR;32_+s01A@mNW(<S|v&CI-%RIPeD^4NlZgFro zq`XPN4Bq*%^dTscpHF3vg&Td0v6z+aZP-aSG|$Ymsh_j`IcHbjI#;=NW%+|r?&V=d za`kV6nA(G!-K!5B`9rh~j*c9;D4i4i&8U2gK#MmKz04cy0k<INbO+lvEL8;0N}cG; z)DCMHzLU1%@UAt)@C!CN=w7`BvIW$()lT%`27n;3*Z>xG<p->+Cs_6EL4yU4y2RUn zS!0v?g>?@u6cj6zUcJX2(Jm2w<Q2a<2)h+6a6fVK#;wa`A=0JFe-2mBs#z}iVGUZ$ zXP_QUFGq%n!YdP-X7|$&Rwe5_#erL;m5-PP9}QjJ+ZOZ+H9gUU8xnW7|DG5CI(o!~ zT9qNDE;Y7F+cL}9xq|z*xjrt~x;NU9zV_X~o%rW3BPcu)GAAV7dgv#VMVkW_-K&xL zs`JE}aAI#i?2&le>6a`0qcuLh?=mY{GIfMDMoW~tbm4hy#<lpB`^{bugSw25Jo69< zSW>ng)nAu~X=OL|C(3Sw7@3XUF9wHdNXxmq?GBB~fbGM6jv1an$V2wjz?`!ut@>Lx zKY4b2uh-&=(GD@^;vRB%_Zn$9Bc<YxSmR|dQiEZ+F~{Xju%aWsS=o8Rzz`3Vy9*5d zs9R?aw!6(g{;O2F$8>?TpZL&r+i7s<+3d7U^9Ci63oagt`iF`W)Uf^dunF6V0`zNR zqbNnr5QIA}>C#*POV7~HG7dEQ)_mEhS7m-xeX480ou^U8{bFAp>HjNNY#Tw)ht9Ab z9yFg8RGfia5FD;(-Y#zt{}zdcyVv5x`+?M8w)qc3h1+W4&(1)DCf7QWqTm)nYZH50 zl`k;6SETsRc7jLpz1Yn*CW5_~4qja)2;m#^*3I<Kq1`grO2s{(`FB_q91Mi;c0yj~ z@DK_(7@iQmr??hiMeLfV&OZ?GnG;pFFx2NJwIlMM>T}(r`Y#GyU;^B#7{=Mfd;A?8 z$P)d&=;ooC1xG!H^u)6?Tl)6h^KSN1M4{bo1n2CabH!!`e){fs5uYc$@qDZ3)7c<1 ziFbeJtJH7T={<-gk72mOdRfmvR4^WrV8@ge;&E)WC1&>3<d>nDVn)nfPsHEjCzRP2 z`6pGB1~R*>5frXoNWsR`<Jsi*C7n};j~m$IF6F55IXP)w&<{dJx0sfMea{iCCSc=s zz5K!FH<V=2F)e!jqNz4F`0!fV$9nw^FTVU#JN_=_ySnY#`m*GIc~y{oUJJ6zUUEXm z8FFC;=GcAMppJa)&z~{fwIJH`reF3$qK_~tRP<LBC0r6bb!Kne52#&e{7)Q}MK-Kv zx#hSacBe&UNmg5)6Nnz|wwQ*9no8+Ok;9&YgKys0yYwxFCNP8b7_`wQ1~(hk=7PaC ztXKA|Z`$fJKQ&349|+sJ*ZrxbTJ70Q%VP@^WNDY1Ji2Amz35GFekI;#N4Ky%IH~fw z4?8EBxO%?t`_rg~3t>U(g?<$HnsyFwv=<he-d!a^6AKasLam9^6`zGo9=}1R&dPm| z`u5}8eBV%DZF@cr!{WNYGUDmiD%m@3GVYPjZZkXES*1svJn$Jrvu;aa@<1c(xqwoC zmW8T<TgQc;-_}jaexy*%t|8WvCiI^pr&oMNf-UUyMKs$W=SYTtJEvL<+|X&+PK(vT zn5cM~Ly$jo#6<YC_ffluJEpv+W03JYdH6f)+*W|S+Ly^NA!y&AfNE206MPFsE%SS3 zJ6kHRHbJy+;PQ1eq-0n2(uAzUD_DLG!w6RVrS!9uI~@<$XxS(3QFo}@cBUF^QvT@V zbc2~qByt^smO&ldA8S$Ykys4(_jJS!Emx)Fj)_~0tva5bFzDGN?x%4Wtmz=aZxwg5 z#V)d}?2#Zi8*g6M5)gTskne$-FC1SB-O$-g9IqPw$v1RO%PfASO$hErXy`%QP?mLA z*x8xXv;EPB_Cz>+aQt5X_UcHEA;+a0_tJuY`=HTt6OlMJ(pA`16(Plw6SkfOuyeNl z<dnS9*0*;0=!bp#o`sBgcdFGu1>Amy4*@MAjC3o0-*~bd^QFZx*TdBDj;q?yxteMi zlxC<t&7E%r<jh>oJvtiVhSOFgiG3y3)(afQ?23-Ic;o*17P@hWx;Pnjq>il^D%u#= z1+spAWcT7X3n<Xf0!)a+{{eH=p7cr8r0Emo;x5g(2g`Oxtc^>GiLLT++*)2uekAzJ z9wwR|!uWrz<wPdoG*`!Yn4Uaw2BQCqriSg_uA3$)pu2v}&zdQWys8#sdoON4l|B*u z_?~WG<rt-kD{x9NnU0uPDB-RtOb;(w3R_<CI}|oUE?>`Avip4=%ivj>ml&?S@r`b3 znNP}L&1H77IJWkye7W3{)|y6LaitCs*oyhjYfJH`TT_3GbvS+>S_kC2dLoJ!Z%-Yn zPAgpf^3$NbOe~+8|Bm<tgYzm!`6m?UqXXlpJ1q}~o+xY{gwamO@eKtneY7jc?g~zL zlKNE4FC!Uy(r6YQ<R<f1o11v4o>8H5_44<uQR8iW#P%T3J_J0JBXJ5QG`1S8TG2do zZ*`(4m>xa`#7}S7{H}BE_p=Zr(%{)*b)KX7q@u`bFeMwn0^Q6N?WwD|E%pF=t^#eY zpiY3;vc6tzYSnnqFm=_ju{MX&fSBp`vJ*F^yTSKDKWsk3neS>Rs<vao+};NLsOcyl z*o}pmtM!$gLRGs4($@X+&p^zX&GKo_{!qM`^YFhAOaJe}=SN@)@M}g$PM0_+3w15F z(i<H1RqPQswTk6deCzO`U@N6i-M3W5EX%Vsb+Y=e6M*e)f^_Y&4S(LWIGFW9c_@jG zw@nI%2Z|rih#zpH2%c@1!e(ao*TGaRG^MZ~hEnOic;mmGI$c?=yKO7&`{z53#Ey`J zRg5me0R@NzMv(<!se@P@p}(=(3b5mu*Yz2So#tKEOwoNOTBX<zUC5lLk>LS!f@S-a zqC_$I_F`kY(+Y@uRB&5c!mi=2Ez=*wu+n=&_H3!B+|!kletGFol$G_|Ud=BG&L2pL zjhCUo71sP>AQP)9fC<Mq_pNYZ-4)#J9I^2Q+*B}^tHTdSynHhsc993!?F;myWC|m~ zm~a?VJ18rtH!AB`{pCwdtp2$Ig_4I!TraplAnuaS>^EsZFF@PI(1_K>dKraoO*1*$ zF~m!|)ZfVMHUV5>gGf78ZeV@S92yepB-QMV>9-Pp6)%mxe)#Y6GU|Vqr~QZDTb7s6 zNh-$K3G%eC$Il}vw5Fu@=nKv#bln$fplY678kfuu3!ip8g!^H*$P$)t34;DYU099D zm$&f?Q&deMCvkk@sziCBky!O-<l{9O$uDGDk_v`Uk(`SL()zP|b7WHF>H^~$ur8m^ zM-NbHe>vA=xWNn0Q-<YSBPL*i9oB(e$n&np!fEs~f3_95UvXWviWRbYxAzSz@ouj> zHAtmGpDX;|@^<p^P!?CR65;PoTA7uNoBH#7CYyQdp9bRbupdv;-x74WSI8HMj}EtR zco{Y(poknoAt$?~RiI)tbptO4c{+JF7TY)eYFuaDCf871{0ES*FJI(^8JZ9eqvdPu z+<NEC$Lg+IFKkTV)Ub+bwCrS`n*t9l5@Citv#70Ud<ghFtnGNsoRCwjI14y;Pea=7 z*nKrsKOH93ZF8-idNX2&I?`r-|A*Gpa`{*k#~+<2VZl(FZh=Gr|I{x@#w$5Nf;(6N zX<6|^*u$HaIpNb%%Sa@rt@~jZA3+ku8{cB#VG?+|zs6)#kcMv0XS9*N-*gPM^O@8M zi9ywDsY}I;_h?_9ct(s#y4I;>uqu*qY~5g4Ua|LhUZLZLt03^pE$ov+5ptPrR!eQ8 z>mh(xiVNGxW-by6v`R!C!O~eh@^4U3SN?q@QPcUdeKwAbe%&5KSSdp0xlRQ?&UDDJ zYpp21bv+O2bkYCUajH?pmCK-iP`Q62RNvtGfD+C-L4i_qWuS|5DuH;SYV6V#7OaHB zT;wjqJ@tYN310rSKlIWWSKJMb?tr{*f%3+ci}48<CMxdGA39EmLT`lCU|;_H+fLnT z77yB^G$pu|u`!s*l0{sChr9Z#xfV9=NRAdbp3VUYw<5=f6%^K1mX^nB=kG3BeTm)} zgLzeWT`=Mr`ARX)eNIn1=qDalch_|HZB!;RR)6Vx68uVLNQG_2=H|FRzX}_@-3EsB z?+u1P1l!#&RzGiOB$z(in5tH|G5D^5G!#R-8m^@pzkiMh?M6kPf#e!KS;BTrO(;=H zS66wx#qY+YekUKv-u7R$<{1vGKMWZI+k{AP0;)%F-NUcKUZHF*@u#a=l~zWv$Bk8E zt5+uZk<l`dwM!rFQE-ZX36|-ph#@$k>Da&7U~a$xzj&9}8^fvR?t6v2Y+iqrf6MC& z!?hdy%!;GhLcaSl8zgC<%86)W(3mPMr#x?Q_p7RPeY$^yf8oz?hIk4M<`uut%TzI$ z(kt!LkL&}9?l|q-K)eQmA5gam0SmakIbyr`?ZI$2&!>zNp((2Cv}s(Qc%pv1;TO0w zAMyLGg#sZPUymY&bgtd2NnRaToeHd;@Y}3o2rRUd)Eo?Y%RwWjOUqGSURju)j)dI# z52oaQWorJD&zYfM(hW+*u?NX$=VC8CQj6el$sDX+gG^psZm#<fto)L?0*D9HmeC}^ zY(iOgaQXt8kkF$o2Z&bKR=t^9S3<bBc&!0By}p~sbP4^7xKJHE=?a(WQUkZb%h&t; z&4zakRpsepddB<|?wLo<8%d%*2ZQ4fT!^L2#k%ROBk>_hUnDOPtsj%#OxP(<t}rP+ zEU0gsjiPj*#5Q=jcfjpVZea<L4+Rk2=<~1>TtI%aa~dAX_R~7Q;e_Mdm4OhoTQbLT zpO1^u-78)9X6@&6gWO*<OGLxEQ~KHxi$#zXp_Nd)YG9OYb;)P>-7@l(;a%rn{JY_{ z;P-0kes&DnwJT0%pzt;q^xOL+5)86TX}Ji9_d~G%&PwrKdbOwKvt^+XaUB19^RM?Z zFNytx!mZ!ctbrkyP!R%n_)&v^C-T5#FKxb{R^f*BuhkZ@9t6P?(VmbYivx3#9032* zzFK+in$ET!FUNN&+s#BYx)W#~=Zrq;h2}#`kDfdIv6>u||E6soL!ReHY!`R=SxhX5 zQ2Jh9!cB|Q&Oql;+q%n4AngtJ9NyZ={Vkhs3Hv=Svx-R<3=iVRd{489n>cb+GHO<v zGj%+0dLV^pzar1Q_g+5iqyAn3rS}b^w_K%TU@skcI^?DV#b+TBWq}+9{SXRpK)8*W z-TR3W!|K$m3>SaMDi1mXwK=HlV=4TNne2l`z-bvJ2zVP3oFlcx+`z1<{dLoXkFArV zG23t6FR|;2$N6aA^Ihq_^Ta?Q+8e@zS2c}A)g)$xxh*CQv+@23!ILz#3UcXMiV>Yy zQ+;Q0`(jnYwiX3}V*o-cV3~JX0skdW4gE=!LAuJR>aomw=Opd|27#TE>`Ak2jH;m{ zQUr)`B+7T_)H=tJ1&4^#p3WA8wnDi~9g--Sd;G6eQHCUwe5R+?AM=ms^c6Zw$FCI< z*qPw6D;Hj`Nbfp<hx$bdm)JN4-nu{hC~aV4|A6#XP^<0D$9&0F%34xjq6-^{T1clX zZ%^A*V4aB7{l8dy�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 literal 0 HcmV?d00001 diff --git a/doc/guides/prog_guide/img/feature_arc-3.jpg b/doc/guides/prog_guide/img/feature_arc-3.jpg new file mode 100644 index 0000000000000000000000000000000000000000..36b754bbd4072dbf558fce3db69aea436d34757e GIT binary patch literal 93408 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 NzYt1cf1LmSO#nJ?14IA- literal 0 HcmV?d00001 -- 2.43.0 ^ permalink raw reply [flat|nested] 46+ messages in thread
* [PATCH v3 0/5] add feature arc in rte_graph 2024-10-08 13:30 ` [RFC PATCH v2 0/5] " Nitin Saxena ` (4 preceding siblings ...) 2024-10-08 13:30 ` [RFC PATCH v2 5/5] docs: add programming guide for feature arc Nitin Saxena @ 2024-10-09 13:29 ` Nitin Saxena 2024-10-09 13:29 ` [PATCH v3 1/5] graph: add feature arc support Nitin Saxena ` (7 more replies) 5 siblings, 8 replies; 46+ messages in thread From: Nitin Saxena @ 2024-10-09 13:29 UTC (permalink / raw) To: Jerin Jacob, Kiran Kumar K, Nithin Dabilpuram, Zhirun Yan, Robin Jarry, Christophe Fontaine Cc: dev, Nitin Saxena Feature arc represents an ordered list of features/protocols at a given networking layer. It is a high level abstraction to connect various rte_graph nodes, as feature nodes, and allow packets steering across these nodes in a generic manner. Features (or feature nodes) are nodes which handles partial or complete handling of a protocol in fast path. Like ipv4-rewrite node, which adds rewrite data to an outgoing IPv4 packet. However in above example, outgoing interface(say "eth0") may have outbound IPsec policy enabled, hence packets must be steered from ipv4-rewrite node to ipsec-outbound-policy node for outbound IPsec policy lookup. On the other hand, packets routed to another interface (eth1) will not be sent to ipsec-outbound-policy node as IPsec feature is disabled on eth1. Feature-arc allows rte_graph applications to manage such constraints easily Feature arc abstraction allows rte_graph based application to 1. Seamlessly steer packets across feature nodes based on whether feature is enabled or disabled on an interface. Features enabled on one interface may not be enabled on another interface with in a same feature arc. 2. Allow enabling/disabling of features on an interface at runtime, so that if a feature is disabled, packets associated with that interface won't be steered to corresponding feature node. 3. Provides mechanism to hook custom/user-defined nodes to a feature node and allow packet steering from feature node to custom node without changing former's fast path function 4. Allow expressing features in a particular sequential order so that packets are steered in an ordered way across nodes in fast path. For eg: if IPsec and IPv4 features are enabled on an ingress interface, packets must be sent to IPsec inbound policy node first and then to ipv4 lookup node. This patch series adds feature arc library in rte_graph and also adds "ipv4-output" feature arc handling in "ipv4-rewrite" node. Changes in v3: - rte_graph_feature_arc_t typedef from uint64_t to uintptr_t to fix compilation on 32-bit machine - Updated images in .png format - Added ABI change section in release notes - Fixed DPDK CI failures Changes in v2: - Added unit tests for feature arc - Fixed issues found in testing - Added new public APIs rte_graph_feature_arc_feature_to_node(), rte_graph_feature_arc_feature_to_name(), rte_graph_feature_arc_num_features() - Added programming guide for feature arc - Added release notes for feature arc Nitin Saxena (5): graph: add feature arc support graph: add feature arc option in graph create graph: add IPv4 output feature arc test/graph_feature_arc: add functional tests docs: add programming guide for feature arc app/test/meson.build | 1 + app/test/test_graph_feature_arc.c | 1410 +++++++++++++++++++ doc/guides/prog_guide/graph_lib.rst | 288 ++++ doc/guides/prog_guide/img/feature_arc-1.png | Bin 0 -> 61532 bytes doc/guides/prog_guide/img/feature_arc-2.png | Bin 0 -> 155806 bytes doc/guides/prog_guide/img/feature_arc-3.png | Bin 0 -> 143697 bytes doc/guides/rel_notes/release_24_11.rst | 13 + lib/graph/graph.c | 1 + lib/graph/graph_feature_arc.c | 1223 ++++++++++++++++ lib/graph/graph_populate.c | 7 +- lib/graph/graph_private.h | 3 + lib/graph/meson.build | 2 + lib/graph/node.c | 2 + lib/graph/rte_graph.h | 3 + lib/graph/rte_graph_feature_arc.h | 431 ++++++ lib/graph/rte_graph_feature_arc_worker.h | 674 +++++++++ lib/graph/version.map | 20 + lib/node/ip4_rewrite.c | 476 +++++-- lib/node/ip4_rewrite_priv.h | 15 +- lib/node/node_private.h | 20 +- lib/node/rte_node_ip4_api.h | 3 + 21 files changed, 4494 insertions(+), 98 deletions(-) create mode 100644 app/test/test_graph_feature_arc.c create mode 100644 doc/guides/prog_guide/img/feature_arc-1.png create mode 100644 doc/guides/prog_guide/img/feature_arc-2.png create mode 100644 doc/guides/prog_guide/img/feature_arc-3.png create mode 100644 lib/graph/graph_feature_arc.c create mode 100644 lib/graph/rte_graph_feature_arc.h create mode 100644 lib/graph/rte_graph_feature_arc_worker.h -- 2.43.0 ^ permalink raw reply [flat|nested] 46+ messages in thread
* [PATCH v3 1/5] graph: add feature arc support 2024-10-09 13:29 ` [PATCH v3 0/5] add feature arc in rte_graph Nitin Saxena @ 2024-10-09 13:29 ` Nitin Saxena 2024-10-09 13:29 ` [PATCH v3 2/5] graph: add feature arc option in graph create Nitin Saxena ` (6 subsequent siblings) 7 siblings, 0 replies; 46+ messages in thread From: Nitin Saxena @ 2024-10-09 13:29 UTC (permalink / raw) To: Jerin Jacob, Kiran Kumar K, Nithin Dabilpuram, Zhirun Yan, Robin Jarry, Christophe Fontaine Cc: dev, Nitin Saxena add feature arc to allow dynamic steering of packets across graph nodes based on protocol features enabled on incoming or outgoing interface Signed-off-by: Nitin Saxena <nsaxena@marvell.com> --- doc/guides/rel_notes/release_24_11.rst | 10 + lib/graph/graph_feature_arc.c | 1223 ++++++++++++++++++++++ lib/graph/meson.build | 2 + lib/graph/rte_graph_feature_arc.h | 431 ++++++++ lib/graph/rte_graph_feature_arc_worker.h | 674 ++++++++++++ lib/graph/version.map | 20 + 6 files changed, 2360 insertions(+) create mode 100644 lib/graph/graph_feature_arc.c create mode 100644 lib/graph/rte_graph_feature_arc.h create mode 100644 lib/graph/rte_graph_feature_arc_worker.h diff --git a/doc/guides/rel_notes/release_24_11.rst b/doc/guides/rel_notes/release_24_11.rst index e0a9aa55a1..d6d64518e0 100644 --- a/doc/guides/rel_notes/release_24_11.rst +++ b/doc/guides/rel_notes/release_24_11.rst @@ -67,6 +67,16 @@ New Features The new statistics are useful for debugging and profiling. +* **Added feature arc abstraction in graph library.** + + Feature arc abstraction helps ``rte_graph`` based applications to steer + packets across different node path(s) based on the features (or protocols) + enabled on interfaces. Different feature node paths can be enabled/disabled + at runtime on some or on all interfaces. This abstraction also help + applications to hook their ``custom nodes`` in standard DPDK node paths + without any code changes in the later. + + * Added ``ip4-output`` feature arc processing in ``ip4_rewrite`` node. Removed Items ------------- diff --git a/lib/graph/graph_feature_arc.c b/lib/graph/graph_feature_arc.c new file mode 100644 index 0000000000..ff99f7b26a --- /dev/null +++ b/lib/graph/graph_feature_arc.c @@ -0,0 +1,1223 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(C) 2024 Marvell International Ltd. + */ + +#include "graph_private.h" +#include <rte_graph_feature_arc_worker.h> +#include <rte_malloc.h> + +#define ARC_PASSIVE_LIST(arc) (arc->active_feature_list ^ 0x1) + +#define rte_graph_uint_cast(x) ((unsigned int)x) +#define feat_dbg graph_dbg + +static rte_graph_feature_arc_main_t *__rte_graph_feature_arc_main; + +/* Make sure fast path cache line is compact */ +_Static_assert((offsetof(struct rte_graph_feature_arc, slow_path_variables) + - offsetof(struct rte_graph_feature_arc, fast_path_variables)) + <= RTE_CACHE_LINE_SIZE, + "Fast path feature arc variables exceed cache line size"); + +#define connect_graph_nodes(node1, node2, edge, arc_name) \ + __connect_graph_nodes(node1, node2, edge, arc_name, __LINE__) + +#define FEAT_COND_ERR(cond, fmt, ...) \ + do { \ + if (cond) \ + graph_err(fmt, ##__VA_ARGS__); \ + } while (0) + +/* + * lookup feature name and get control path node_list as well as feature index + * at which it is inserted + */ +static int +feature_lookup(struct rte_graph_feature_arc *arc, const char *feat_name, + struct rte_graph_feature_node_list **ffinfo, uint32_t *slot) +{ + struct rte_graph_feature_node_list *finfo = NULL; + const char *name; + uint32_t fi = 0; + + if (!feat_name) + return -1; + + if (slot) + *slot = UINT32_MAX; + + STAILQ_FOREACH(finfo, &arc->all_features, next_feature) { + RTE_VERIFY(finfo->feature_arc == arc); + name = rte_node_id_to_name(finfo->feature_node->id); + if (!strncmp(name, feat_name, strlen(name))) { + if (ffinfo) + *ffinfo = finfo; + if (slot) + *slot = fi; + return 0; + } + fi++; + } + return -1; +} + +/* Lookup used only during rte_graph_feature_add() */ +static int +feature_add_lookup(struct rte_graph_feature_arc *arc, const char *feat_name, + struct rte_graph_feature_node_list **ffinfo, uint32_t *slot) +{ + struct rte_graph_feature_node_list *finfo = NULL; + const char *name; + uint32_t fi = 0; + + if (!feat_name) + return -1; + + if (slot) + *slot = 0; + + STAILQ_FOREACH(finfo, &arc->all_features, next_feature) { + RTE_VERIFY(finfo->feature_arc == arc); + name = rte_node_id_to_name(finfo->feature_node->id); + if (!strncmp(name, feat_name, strlen(name))) { + if (ffinfo) + *ffinfo = finfo; + if (slot) + *slot = fi; + return 0; + } + /* Update slot where new feature can be added */ + if (slot) + *slot = fi; + fi++; + } + + return -1; +} + +/* Get control path node info from provided input feature_index */ +static int +feature_arc_node_info_lookup(struct rte_graph_feature_arc *arc, uint32_t feature_index, + struct rte_graph_feature_node_list **ppfinfo, + const int do_sanity_check) +{ + struct rte_graph_feature_node_list *finfo = NULL; + uint32_t index = 0; + + if (!ppfinfo) + return -1; + + *ppfinfo = NULL; + STAILQ_FOREACH(finfo, &arc->all_features, next_feature) { + /* Check sanity */ + if (do_sanity_check) + if (finfo->node_index != index) + RTE_VERIFY(0); + if (index == feature_index) { + *ppfinfo = finfo; + return 0; + } + index++; + } + return -1; +} + +/* prepare feature arc after addition of all features */ +static void +prepare_feature_arc_before_first_enable(struct rte_graph_feature_arc *arc) +{ + struct rte_graph_feature_node_list *finfo = NULL; + uint32_t index = 0; + + arc->active_feature_list = 0; + STAILQ_FOREACH(finfo, &arc->all_features, next_feature) { + finfo->node_index = index; + feat_dbg("\t%s prepare: %s added to list at index: %u", arc->feature_arc_name, + finfo->feature_node->name, index); + index++; + } +} + +/* feature arc lookup in array */ +static int +feature_arc_lookup(rte_graph_feature_arc_t _arc) +{ + struct rte_graph_feature_arc *arc = rte_graph_feature_arc_get(_arc); + rte_graph_feature_arc_main_t *dm = __rte_graph_feature_arc_main; + uint32_t iter; + + if (!__rte_graph_feature_arc_main) + return -1; + + for (iter = 0; iter < dm->max_feature_arcs; iter++) { + if (dm->feature_arcs[iter] == RTE_GRAPH_FEATURE_ARC_INITIALIZER) + continue; + + if (arc == (rte_graph_feature_arc_get(dm->feature_arcs[iter]))) + return 0; + } + return -1; +} + +/* Check valid values for known fields in arc to make sure arc is sane */ +static int check_feature_arc_sanity(rte_graph_feature_arc_t _arc, int iter) +{ +#ifdef FEATURE_ARC_DEBUG + struct rte_graph_feature_arc *arc = rte_graph_feature_arc_get(_arc); + + RTE_VERIFY(arc->feature_arc_main == __rte_graph_feature_arc_main); + RTE_VERIFY(arc->feature_arc_index == iter); + + RTE_VERIFY(arc->feature_list[0]->indexed_by_features = arc->features[0]); + RTE_VERIFY(arc->feature_list[1]->indexed_by_features = arc->features[1]); + + RTE_VERIFY(arc->active_feature_list < 2); +#else + RTE_SET_USED(_arc); + RTE_SET_USED(iter); +#endif + return 0; +} + +/* Perform sanity on all arc if any corruption occurred */ +static int do_sanity_all_arcs(void) +{ + rte_graph_feature_arc_main_t *dm = __rte_graph_feature_arc_main; + uint32_t iter; + + if (!dm) + return -1; + + for (iter = 0; iter < dm->max_feature_arcs; iter++) { + if (dm->feature_arcs[iter] == RTE_GRAPH_FEATURE_ARC_INITIALIZER) + continue; + + if (check_feature_arc_sanity(dm->feature_arcs[iter], iter)) + return -1; + } + return 0; +} + +/* get existing edge from parent_node -> child_node */ +static int +get_existing_edge(const char *arc_name, struct rte_node_register *parent_node, + struct rte_node_register *child_node, rte_edge_t *_edge) +{ + char **next_edges = NULL; + uint32_t i, count = 0; + + RTE_SET_USED(arc_name); + + count = rte_node_edge_get(parent_node->id, NULL); + + if (!count) + return -1; + + next_edges = malloc(count); + + if (!next_edges) + return -1; + + count = rte_node_edge_get(parent_node->id, next_edges); + for (i = 0; i < count; i++) { + if (strstr(child_node->name, next_edges[i])) { + if (_edge) + *_edge = (rte_edge_t)i; + + free(next_edges); + return 0; + } + } + free(next_edges); + + return -1; +} + +/* create or retrieve already existing edge from parent_node -> child_node */ +static int +__connect_graph_nodes(struct rte_node_register *parent_node, struct rte_node_register *child_node, + rte_edge_t *_edge, char *arc_name, int lineno) +{ + const char *next_node = NULL; + rte_edge_t edge; + + if (!get_existing_edge(arc_name, parent_node, child_node, &edge)) { + feat_dbg("\t%s/%d: %s[%u]: \"%s\", edge reused", arc_name, lineno, + parent_node->name, edge, child_node->name); + + if (_edge) + *_edge = edge; + + return 0; + } + + /* Node to be added */ + next_node = child_node->name; + + edge = rte_node_edge_update(parent_node->id, RTE_EDGE_ID_INVALID, &next_node, 1); + + if (edge == RTE_EDGE_ID_INVALID) { + graph_err("edge invalid"); + return -1; + } + edge = rte_node_edge_count(parent_node->id) - 1; + + feat_dbg("\t%s/%d: %s[%u]: \"%s\", new edge added", arc_name, lineno, parent_node->name, + edge, child_node->name); + + if (_edge) + *_edge = edge; + + return 0; +} + +/* feature arc initialization */ +static int +feature_arc_main_init(rte_graph_feature_arc_main_t **pfl, uint32_t max_feature_arcs) +{ + rte_graph_feature_arc_main_t *pm = NULL; + uint32_t i; + size_t sz; + + if (!pfl) + return -1; + + sz = sizeof(rte_graph_feature_arc_main_t) + + (sizeof(pm->feature_arcs[0]) * max_feature_arcs); + + pm = rte_malloc("rte_graph_feature_arc_main", sz, 0); + if (!pm) + return -1; + + memset(pm, 0, sz); + + for (i = 0; i < max_feature_arcs; i++) + pm->feature_arcs[i] = RTE_GRAPH_FEATURE_ARC_INITIALIZER; + + pm->max_feature_arcs = max_feature_arcs; + + *pfl = pm; + + return 0; +} + +/* feature arc initialization, public API */ +int +rte_graph_feature_arc_init(int max_feature_arcs) +{ + if (!max_feature_arcs) + return -1; + + if (__rte_graph_feature_arc_main) + return -1; + + return feature_arc_main_init(&__rte_graph_feature_arc_main, max_feature_arcs); +} + +/* reset feature list before switching to passive list */ +static void +feature_arc_list_reset(struct rte_graph_feature_arc *arc, uint32_t list_index) +{ + rte_graph_feature_data_t *fdata = NULL; + rte_graph_feature_list_t *list = NULL; + struct rte_graph_feature *feat = NULL; + uint32_t i, j; + + list = arc->feature_list[list_index]; + feat = arc->features[list_index]; + + /*Initialize variables*/ + memset(feat, 0, arc->feature_size * arc->max_features); + memset(list, 0, arc->feature_list_size); + + /* Initialize feature and feature_data */ + for (i = 0; i < arc->max_features; i++) { + feat = __rte_graph_feature_get(arc, i, list_index); + feat->this_feature_index = i; + + for (j = 0; j < arc->max_indexes; j++) { + fdata = rte_graph_feature_data_get(arc, feat, j); + fdata->next_enabled_feature = RTE_GRAPH_FEATURE_INVALID; + fdata->next_edge = UINT16_MAX; + fdata->user_data = UINT32_MAX; + } + } + + for (i = 0; i < arc->max_indexes; i++) + list->first_enabled_feature_by_index[i] = RTE_GRAPH_FEATURE_INVALID; +} + +static int +feature_arc_list_init(struct rte_graph_feature_arc *arc, const char *flist_name, + rte_graph_feature_list_t **pplist, + struct rte_graph_feature **ppfeature, uint32_t list_index) +{ + char fname[2 * RTE_GRAPH_FEATURE_ARC_NAMELEN]; + size_t list_size, feat_size, fdata_size; + rte_graph_feature_list_t *list = NULL; + struct rte_graph_feature *feat = NULL; + + list_size = sizeof(struct rte_graph_feature_list) + + (sizeof(list->first_enabled_feature_by_index[0]) * arc->max_indexes); + + list_size = RTE_ALIGN_CEIL(list_size, RTE_CACHE_LINE_SIZE); + + list = rte_malloc(flist_name, list_size, RTE_CACHE_LINE_SIZE); + if (!list) + return -ENOMEM; + + memset(list, 0, list_size); + fdata_size = arc->max_indexes * sizeof(rte_graph_feature_data_t); + + /* Let one feature and its associated data per index capture complete + * cache lines + */ + feat_size = RTE_ALIGN_CEIL(sizeof(struct rte_graph_feature) + fdata_size, + RTE_CACHE_LINE_SIZE); + + snprintf(fname, sizeof(fname), "%s-%s", arc->feature_arc_name, "feat"); + + feat = rte_malloc(fname, feat_size * arc->max_features, RTE_CACHE_LINE_SIZE); + if (!feat) { + rte_free(list); + return -ENOMEM; + } + arc->feature_size = feat_size; + arc->feature_data_size = fdata_size; + arc->feature_list_size = list_size; + + /* Initialize list */ + list->indexed_by_features = feat; + *pplist = list; + *ppfeature = feat; + + feature_arc_list_reset(arc, list_index); + + return 0; +} + +/* free resources allocated in feature_arc_list_init() */ +static void +feature_arc_list_destroy(struct rte_graph_feature_arc *arc, int list_index) +{ + rte_graph_feature_list_t *list = NULL; + + list = arc->feature_list[list_index]; + + rte_free(list->indexed_by_features); + + arc->features[list_index] = NULL; + + rte_free(list); + + arc->feature_list[list_index] = NULL; +} + +int +rte_graph_feature_arc_create(const char *feature_arc_name, int max_features, int max_indexes, + struct rte_node_register *start_node, rte_graph_feature_arc_t *_arc) +{ + char name[2 * RTE_GRAPH_FEATURE_ARC_NAMELEN]; + struct rte_graph_feature_data *gfd = NULL; + rte_graph_feature_arc_main_t *dfm = NULL; + struct rte_graph_feature_arc *arc = NULL; + struct rte_graph_feature *df = NULL; + uint32_t iter, j, arc_index; + size_t sz; + + if (!_arc) + SET_ERR_JMP(EINVAL, err, "%s: Invalid _arc", feature_arc_name); + + if (max_features < 2) + SET_ERR_JMP(EINVAL, err, "%s: max_features must be greater than 1", + feature_arc_name); + + if (!start_node) + SET_ERR_JMP(EINVAL, err, "%s: start_node cannot be NULL", + feature_arc_name); + + if (!feature_arc_name) + SET_ERR_JMP(EINVAL, err, "%s: feature_arc name cannot be NULL", + feature_arc_name); + + if (max_features > RTE_GRAPH_FEATURE_MAX_PER_ARC) + SET_ERR_JMP(EAGAIN, err, "%s: number of features cannot be greater than 64", + feature_arc_name); + + /* + * Application hasn't called rte_graph_feature_arc_init(). Initialize with + * default values + */ + if (!__rte_graph_feature_arc_main) { + if (rte_graph_feature_arc_init((int)RTE_GRAPH_FEATURE_ARC_MAX) < 0) { + graph_err("rte_graph_feature_arc_init() failed"); + return -1; + } + } + + /* If name is not unique */ + if (!rte_graph_feature_arc_lookup_by_name(feature_arc_name, NULL)) + SET_ERR_JMP(EINVAL, err, "%s: feature arc name already exists", + feature_arc_name); + + dfm = __rte_graph_feature_arc_main; + + /* threshold check */ + if (dfm->num_feature_arcs > (dfm->max_feature_arcs - 1)) + SET_ERR_JMP(EAGAIN, err, "%s: max number (%u) of feature arcs reached", + feature_arc_name, dfm->max_feature_arcs); + + /* Find the free slot for feature arc */ + for (iter = 0; iter < dfm->max_feature_arcs; iter++) { + if (dfm->feature_arcs[iter] == RTE_GRAPH_FEATURE_ARC_INITIALIZER) + break; + } + arc_index = iter; + + if (arc_index >= dfm->max_feature_arcs) { + graph_err("No free slot found for num_feature_arc"); + return -1; + } + + /* This should not happen */ + RTE_VERIFY(dfm->feature_arcs[arc_index] == RTE_GRAPH_FEATURE_ARC_INITIALIZER); + + /* size of feature arc + feature_bit_mask_by_index */ + sz = RTE_ALIGN_CEIL(sizeof(*arc) + (sizeof(uint64_t) * max_indexes), RTE_CACHE_LINE_SIZE); + + arc = rte_malloc(feature_arc_name, sz, RTE_CACHE_LINE_SIZE); + + if (!arc) { + graph_err("malloc failed for feature_arc_create()"); + return -1; + } + + memset(arc, 0, sz); + + /* Initialize rte_graph port group fixed variables */ + STAILQ_INIT(&arc->all_features); + strncpy(arc->feature_arc_name, feature_arc_name, RTE_GRAPH_FEATURE_ARC_NAMELEN - 1); + arc->feature_arc_main = (void *)dfm; + arc->start_node = start_node; + arc->max_features = max_features; + arc->max_indexes = max_indexes; + arc->feature_arc_index = arc_index; + + snprintf(name, sizeof(name), "%s-%s", feature_arc_name, "flist0"); + + if (feature_arc_list_init(arc, name, &arc->feature_list[0], &arc->features[0], 0) < 0) { + rte_free(arc); + graph_err("feature_arc_list_init(0) failed"); + return -1; + } + snprintf(name, sizeof(name), "%s-%s", feature_arc_name, "flist1"); + + if (feature_arc_list_init(arc, name, &arc->feature_list[1], &arc->features[1], 1) < 0) { + feature_arc_list_destroy(arc, 0); + rte_free(arc); + graph_err("feature_arc_list_init(1) failed"); + return -1; + } + + for (iter = 0; iter < arc->max_features; iter++) { + df = rte_graph_feature_get(arc, iter); + for (j = 0; j < arc->max_indexes; j++) { + gfd = rte_graph_feature_data_get(arc, df, j); + gfd->next_enabled_feature = RTE_GRAPH_FEATURE_INVALID; + } + } + dfm->feature_arcs[arc->feature_arc_index] = (rte_graph_feature_arc_t)arc; + dfm->num_feature_arcs++; + + if (_arc) + *_arc = (rte_graph_feature_arc_t)arc; + + do_sanity_all_arcs(); + + feat_dbg("Feature arc %s[%p] created with max_features: %u and indexes: %u", + feature_arc_name, (void *)arc, max_features, max_indexes); + return 0; + +err: + return -rte_errno; +} + +int +rte_graph_feature_add(rte_graph_feature_arc_t _arc, struct rte_node_register *feature_node, + const char *_runs_after, const char *runs_before) +{ + struct rte_graph_feature_node_list *after_finfo = NULL, *before_finfo = NULL; + struct rte_graph_feature_arc *arc = rte_graph_feature_arc_get(_arc); + struct rte_graph_feature_node_list *temp = NULL, *finfo = NULL; + char feature_name[3*RTE_GRAPH_FEATURE_ARC_NAMELEN]; + const char *runs_after = NULL; + uint32_t num_feature = 0; + uint32_t slot, add_flag; + rte_edge_t edge = -1; + + /* sanity */ + if (arc->feature_arc_main != __rte_graph_feature_arc_main) { + graph_err("feature arc not created: 0x%016" PRIx64, (uint64_t)_arc); + return -1; + } + + if (feature_arc_lookup(_arc)) { + graph_err("invalid feature arc: 0x%016" PRIx64, (uint64_t)_arc); + return -1; + } + + if (arc->runtime_enabled_features) { + graph_err("adding features after enabling any one of them is not supported"); + return -1; + } + + if ((_runs_after != NULL) && (runs_before != NULL) && + (_runs_after == runs_before)) { + graph_err("runs_after and runs_before are same '%s:%s]", _runs_after, + runs_before); + return -1; + } + + if (!feature_node) { + graph_err("feature_node: %p invalid", feature_node); + return -1; + } + + arc = rte_graph_feature_arc_get(_arc); + + if (feature_node->id == RTE_NODE_ID_INVALID) { + graph_err("Invalid node: %s", feature_node->name); + return -1; + } + + if (!feature_add_lookup(arc, feature_node->name, &finfo, &slot)) { + graph_err("%s feature already added", feature_node->name); + return -1; + } + + if (slot >= arc->max_features) { + graph_err("%s: Max features %u added to feature arc", + arc->feature_arc_name, slot); + return -1; + } + + if (strstr(feature_node->name, arc->start_node->name)) { + graph_err("Feature %s cannot point to itself: %s", feature_node->name, + arc->start_node->name); + return -1; + } + + feat_dbg("%s: adding feature node: %s at feature index: %u", arc->feature_arc_name, + feature_node->name, slot); + + if (connect_graph_nodes(arc->start_node, feature_node, &edge, arc->feature_arc_name)) { + graph_err("unable to connect %s -> %s", arc->start_node->name, feature_node->name); + return -1; + } + + snprintf(feature_name, sizeof(feature_name), "%s-%s-finfo", + arc->feature_arc_name, feature_node->name); + + finfo = rte_malloc(feature_name, sizeof(*finfo), 0); + if (!finfo) { + graph_err("%s/%s: rte_malloc failed", arc->feature_arc_name, feature_node->name); + return -1; + } + + memset(finfo, 0, sizeof(*finfo)); + + finfo->feature_arc = (void *)arc; + finfo->feature_node = feature_node; + finfo->edge_to_this_feature = edge; + arc->runtime_enabled_features = 0; + + /* + * if no constraints given and provided feature is not the first feature, + * explicitly set "runs_after" as last_feature. Handles the case: + * + * add(f1, NULL, NULL); + * add(f2, NULL, NULL); + */ + num_feature = rte_graph_feature_arc_num_features(_arc); + if (!_runs_after && !runs_before && num_feature) + runs_after = rte_graph_feature_arc_feature_to_name(_arc, num_feature - 1); + else + runs_after = _runs_after; + + /* Check for before and after constraints */ + if (runs_before) { + /* runs_before sanity */ + if (feature_lookup(arc, runs_before, &before_finfo, NULL)) + SET_ERR_JMP(EINVAL, finfo_free, + "Invalid before feature name: %s", runs_before); + + if (!before_finfo) + SET_ERR_JMP(EINVAL, finfo_free, + "runs_before %s does not exist", runs_before); + + /* + * Starting from 0 to runs_before, continue connecting edges + */ + add_flag = 1; + STAILQ_FOREACH(temp, &arc->all_features, next_feature) { + if (!add_flag) + /* Nodes after seeing "runs_before", finfo connects to temp*/ + connect_graph_nodes(finfo->feature_node, temp->feature_node, + NULL, arc->feature_arc_name); + /* + * As soon as we see runs_before. stop adding edges + */ + if (!strncmp(temp->feature_node->name, runs_before, + RTE_GRAPH_NAMESIZE)) { + if (!connect_graph_nodes(finfo->feature_node, temp->feature_node, + &edge, arc->feature_arc_name)) + add_flag = 0; + } + + if (add_flag) + /* Nodes before seeing "run_before" are connected to finfo */ + connect_graph_nodes(temp->feature_node, finfo->feature_node, NULL, + arc->feature_arc_name); + } + } + + if (runs_after) { + if (feature_lookup(arc, runs_after, &after_finfo, NULL)) + SET_ERR_JMP(EINVAL, finfo_free, + "Invalid after feature_name %s", runs_after); + + if (!after_finfo) + SET_ERR_JMP(EINVAL, finfo_free, + "runs_after %s does not exist", runs_after); + + /* Starting from runs_after to end continue connecting edges */ + add_flag = 0; + STAILQ_FOREACH(temp, &arc->all_features, next_feature) { + if (add_flag) + /* We have already seen runs_after now */ + /* Add all features as next node to current feature*/ + connect_graph_nodes(finfo->feature_node, temp->feature_node, NULL, + arc->feature_arc_name); + else + /* Connect initial nodes to newly added node*/ + connect_graph_nodes(temp->feature_node, finfo->feature_node, NULL, + arc->feature_arc_name); + + /* as soon as we see runs_after. start adding edges + * from next iteration + */ + if (!strncmp(temp->feature_node->name, runs_after, RTE_GRAPH_NAMESIZE)) + add_flag = 1; + } + + /* add feature next to runs_after */ + STAILQ_INSERT_AFTER(&arc->all_features, after_finfo, finfo, next_feature); + } else { + if (before_finfo) { + /* add finfo before "before_finfo" element in the list */ + after_finfo = NULL; + STAILQ_FOREACH(temp, &arc->all_features, next_feature) { + if (before_finfo == temp) { + if (after_finfo) + STAILQ_INSERT_AFTER(&arc->all_features, after_finfo, + finfo, next_feature); + else + STAILQ_INSERT_HEAD(&arc->all_features, finfo, + next_feature); + + return 0; + } + after_finfo = temp; + } + } else { + /* Very first feature just needs to be added to list */ + STAILQ_INSERT_TAIL(&arc->all_features, finfo, next_feature); + } + } + + return 0; + +finfo_free: + rte_free(finfo); + + return -1; +} + +int +rte_graph_feature_lookup(rte_graph_feature_arc_t _arc, const char *feature_name, + rte_graph_feature_t *feat) +{ + struct rte_graph_feature_arc *arc = rte_graph_feature_arc_get(_arc); + struct rte_graph_feature_node_list *finfo = NULL; + uint32_t slot; + + if (!feature_lookup(arc, feature_name, &finfo, &slot)) { + *feat = (rte_graph_feature_t) slot; + return 0; + } + + return -1; +} + +int +rte_graph_feature_validate(rte_graph_feature_arc_t _arc, uint32_t index, const char *feature_name, + int is_enable_disable, bool emit_logs) +{ + struct rte_graph_feature_arc *arc = rte_graph_feature_arc_get(_arc); + struct rte_graph_feature_node_list *finfo = NULL; + struct rte_graph_feature *gf = NULL; + uint32_t slot; + + /* validate _arc */ + if (arc->feature_arc_main != __rte_graph_feature_arc_main) { + FEAT_COND_ERR(emit_logs, "invalid feature arc: 0x%016" PRIx64, (uint64_t)_arc); + return -EINVAL; + } + + /* validate index */ + if (index >= arc->max_indexes) { + FEAT_COND_ERR(emit_logs, "%s: Invalid provided index: %u >= %u configured", + arc->feature_arc_name, index, arc->max_indexes); + return -1; + } + + /* validate feature_name is already added or not */ + if (feature_lookup(arc, feature_name, &finfo, &slot)) { + FEAT_COND_ERR(emit_logs, "%s: No feature %s added", + arc->feature_arc_name, feature_name); + return -EINVAL; + } + + if (!finfo) { + FEAT_COND_ERR(emit_logs, "%s: No feature: %s found", + arc->feature_arc_name, feature_name); + return -EINVAL; + } + + /* slot should be in valid range */ + if (slot >= arc->max_features) { + FEAT_COND_ERR(emit_logs, "%s/%s: Invalid free slot %u(max=%u) for feature", + arc->feature_arc_name, feature_name, slot, arc->max_features); + return -EINVAL; + } + + /* slot should be in range of 0 - 63 */ + if (slot > (RTE_GRAPH_FEATURE_MAX_PER_ARC - 1)) { + FEAT_COND_ERR(emit_logs, "%s/%s: Invalid slot: %u", arc->feature_arc_name, + feature_name, slot); + return -EINVAL; + } + + if (finfo->node_index != slot) { + FEAT_COND_ERR(emit_logs, + "%s/%s: lookup slot mismatch for finfo idx: %u and lookup slot: %u", + arc->feature_arc_name, feature_name, finfo->node_index, slot); + return -1; + } + + /* Get feature from active list */ + gf = __rte_graph_feature_get(arc, slot, ARC_PASSIVE_LIST(arc)); + if (gf->this_feature_index != slot) { + FEAT_COND_ERR(emit_logs, + "%s: %s rcvd feature_idx: %u does not match with saved: %u", + arc->feature_arc_name, feature_name, slot, gf->this_feature_index); + return -1; + } + + if (is_enable_disable && (arc->feature_bit_mask_by_index[index] & + RTE_BIT64(slot))) { + FEAT_COND_ERR(emit_logs, "%s: %s already enabled on index: %u", + arc->feature_arc_name, feature_name, index); + return -1; + } + + if (!is_enable_disable && !arc->runtime_enabled_features) { + FEAT_COND_ERR(emit_logs, "%s: No feature enabled to disable", + arc->feature_arc_name); + return -1; + } + + if (!is_enable_disable && !(arc->feature_bit_mask_by_index[index] & RTE_BIT64(slot))) { + FEAT_COND_ERR(emit_logs, "%s: %s not enabled in bitmask for index: %u", + arc->feature_arc_name, feature_name, index); + return -1; + } + + return 0; +} + +/* + * Before switch to passive list, user_data needs to be copied from active list to passive list + */ +static void +copy_fastpath_user_data(struct rte_graph_feature_arc *arc, uint16_t dest_list_index, + uint16_t src_list_index) +{ + rte_graph_feature_data_t *sgfd = NULL, *dgfd = NULL; + struct rte_graph_feature *sgf = NULL, *dgf = NULL; + uint32_t i, j; + + for (i = 0; i < arc->max_features; i++) { + sgf = __rte_graph_feature_get(arc, i, src_list_index); + dgf = __rte_graph_feature_get(arc, i, dest_list_index); + for (j = 0; j < arc->max_indexes; j++) { + sgfd = rte_graph_feature_data_get(arc, sgf, j); + dgfd = rte_graph_feature_data_get(arc, dgf, j); + dgfd->user_data = sgfd->user_data; + } + } +} +/* + * Fill fast path information like + * - next_edge + * - next_enabled_feature + */ +static void +refill_feature_fastpath_data(struct rte_graph_feature_arc *arc, uint16_t list_index) +{ + struct rte_graph_feature_node_list *finfo = NULL, *prev_finfo = NULL; + struct rte_graph_feature_data *gfd = NULL, *prev_gfd = NULL; + uint32_t fi = UINT32_MAX, di = UINT32_MAX, prev_fi = UINT32_MAX; + struct rte_graph_feature *gf = NULL, *prev_gf = NULL; + rte_graph_feature_list_t *flist = NULL; + rte_edge_t edge = UINT16_MAX; + uint64_t bitmask = 0; + + flist = arc->feature_list[list_index]; + + for (di = 0; di < arc->max_indexes; di++) { + bitmask = arc->feature_bit_mask_by_index[di]; + prev_fi = RTE_GRAPH_FEATURE_INVALID; + /* for each feature set for index, set fast path data */ + while (rte_bsf64_safe(bitmask, &fi)) { + gf = __rte_graph_feature_get(arc, fi, list_index); + gfd = rte_graph_feature_data_get(arc, gf, di); + RTE_VERIFY(!feature_arc_node_info_lookup(arc, fi, &finfo, 1)); + + /* If previous feature_index was valid in last loop */ + if (prev_fi != RTE_GRAPH_FEATURE_INVALID) { + prev_gf = __rte_graph_feature_get(arc, prev_fi, list_index); + prev_gfd = rte_graph_feature_data_get(arc, prev_gf, di); + /* + * Get edge of previous feature node connecting + * to this feature node + */ + RTE_VERIFY(!feature_arc_node_info_lookup(arc, prev_fi, + &prev_finfo, 1)); + if (!get_existing_edge(arc->feature_arc_name, + prev_finfo->feature_node, + finfo->feature_node, &edge)) { + feat_dbg("\t[%s/%u/di:%2u,cookie:%u]: (%u->%u)%s[%u] = %s", + arc->feature_arc_name, list_index, di, + prev_gfd->user_data, prev_fi, fi, + prev_finfo->feature_node->name, + edge, finfo->feature_node->name); + /* Copy feature index for next iteration*/ + gfd->next_edge = edge; + prev_fi = fi; + /* + * Fill current feature as next enabled + * feature to previous one + */ + prev_gfd->next_enabled_feature = fi; + } else { + /* Should not fail */ + RTE_VERIFY(0); + } + } + /* On first feature edge of the node to be added */ + if (fi == rte_bsf64(arc->feature_bit_mask_by_index[di])) { + if (!get_existing_edge(arc->feature_arc_name, arc->start_node, + finfo->feature_node, + &edge)) { + feat_dbg("\t[%s/%u/di:%2u,cookie:%u]: (->%u)%s[%u]=%s", + arc->feature_arc_name, list_index, di, + gfd->user_data, fi, + arc->start_node->name, edge, + finfo->feature_node->name); + /* Copy feature index for next iteration*/ + gfd->next_edge = edge; + prev_fi = fi; + /* Set first feature set array for index*/ + flist->first_enabled_feature_by_index[di] = + (rte_graph_feature_t)fi; + } else { + /* Should not fail */ + RTE_VERIFY(0); + } + } + /* Clear current feature index */ + bitmask &= ~RTE_BIT64(fi); + } + } +} + +int +rte_graph_feature_enable(rte_graph_feature_arc_t _arc, uint32_t index, const + char *feature_name, int32_t user_data) +{ + struct rte_graph_feature_arc *arc = rte_graph_feature_arc_get(_arc); + struct rte_graph_feature_node_list *finfo = NULL; + struct rte_graph_feature_data *gfd = NULL; + rte_graph_feature_rt_list_t passive_list; + struct rte_graph_feature *gf = NULL; + uint64_t bitmask; + uint32_t slot; + + feat_dbg("%s: Enabling feature: %s for index: %u", + arc->feature_arc_name, feature_name, index); + + if (!arc->runtime_enabled_features) + prepare_feature_arc_before_first_enable(arc); + + if (rte_graph_feature_validate(_arc, index, feature_name, 1, true)) + return -1; + + /** This should not fail as validate() has passed */ + if (feature_lookup(arc, feature_name, &finfo, &slot)) + RTE_VERIFY(0); + + passive_list = ARC_PASSIVE_LIST(arc); + + feat_dbg("\t%s/%s: index: %u, passive list: %u, feature index: %u", + arc->feature_arc_name, feature_name, index, passive_list, slot); + + gf = __rte_graph_feature_get(arc, slot, passive_list); + gfd = rte_graph_feature_data_get(arc, gf, index); + + /* Reset feature list */ + feature_arc_list_reset(arc, passive_list); + + /* Copy user-data */ + copy_fastpath_user_data(arc, passive_list, arc->active_feature_list); + + /* Set current user-data */ + gfd->user_data = user_data; + + /* Set bitmask in control path bitmask */ + rte_bit_relaxed_set64(rte_graph_uint_cast(slot), &arc->feature_bit_mask_by_index[index]); + refill_feature_fastpath_data(arc, passive_list); + + /* If first time feature getting enabled */ + bitmask = rte_atomic_load_explicit(&arc->feature_enable_bitmask[arc->active_feature_list], + rte_memory_order_relaxed); + + /* On very first feature enable instance */ + if (!finfo->ref_count) + bitmask |= RTE_BIT64(slot); + + rte_atomic_store_explicit(&arc->feature_enable_bitmask[passive_list], + bitmask, rte_memory_order_relaxed); + + /* Slow path updates */ + arc->runtime_enabled_features++; + + /* Increase feature node info reference count */ + finfo->ref_count++; + + /* Store release semantics for active_list update */ + rte_atomic_store_explicit(&arc->active_feature_list, passive_list, + rte_memory_order_release); + + feat_dbg("%s/%s: After enable, switched active feature list to %u", + arc->feature_arc_name, feature_name, arc->active_feature_list); + + return 0; +} + +int +rte_graph_feature_disable(rte_graph_feature_arc_t _arc, uint32_t index, const char *feature_name) +{ + struct rte_graph_feature_arc *arc = rte_graph_feature_arc_get(_arc); + struct rte_graph_feature_data *gfd = NULL; + struct rte_graph_feature_node_list *finfo = NULL; + rte_graph_feature_rt_list_t passive_list; + struct rte_graph_feature *gf = NULL; + uint64_t bitmask; + uint32_t slot; + + feat_dbg("%s: Disable feature: %s for index: %u", + arc->feature_arc_name, feature_name, index); + + if (rte_graph_feature_validate(_arc, index, feature_name, 0, true)) + return -1; + + if (feature_lookup(arc, feature_name, &finfo, &slot)) + return -1; + + passive_list = ARC_PASSIVE_LIST(arc); + + gf = __rte_graph_feature_get(arc, slot, passive_list); + gfd = rte_graph_feature_data_get(arc, gf, index); + + feat_dbg("\t%s/%s: index: %u, passive list: %u, feature index: %u", + arc->feature_arc_name, feature_name, index, passive_list, slot); + + rte_bit_relaxed_clear64(rte_graph_uint_cast(slot), &arc->feature_bit_mask_by_index[index]); + + /* Reset feature list */ + feature_arc_list_reset(arc, passive_list); + + /* Copy user-data */ + copy_fastpath_user_data(arc, passive_list, arc->active_feature_list); + + /* Reset current user-data */ + gfd->user_data = ~0; + + refill_feature_fastpath_data(arc, passive_list); + + finfo->ref_count--; + arc->runtime_enabled_features--; + + /* If no feature enabled, reset feature in u64 fast path bitmask */ + bitmask = rte_atomic_load_explicit(&arc->feature_enable_bitmask[arc->active_feature_list], + rte_memory_order_relaxed); + + /* When last feature is disabled */ + if (!finfo->ref_count) + bitmask &= ~(RTE_BIT64(slot)); + + rte_atomic_store_explicit(&arc->feature_enable_bitmask[passive_list], bitmask, + rte_memory_order_relaxed); + + /* Store release semantics for active_list update */ + rte_atomic_store_explicit(&arc->active_feature_list, passive_list, + rte_memory_order_release); + + feat_dbg("%s/%s: After disable, switched active feature list to %u", + arc->feature_arc_name, feature_name, arc->active_feature_list); + + return 0; +} + +int +rte_graph_feature_arc_destroy(rte_graph_feature_arc_t _arc) +{ + struct rte_graph_feature_arc *arc = rte_graph_feature_arc_get(_arc); + rte_graph_feature_arc_main_t *dm = __rte_graph_feature_arc_main; + struct rte_graph_feature_node_list *node_info = NULL; + + while (!STAILQ_EMPTY(&arc->all_features)) { + node_info = STAILQ_FIRST(&arc->all_features); + STAILQ_REMOVE_HEAD(&arc->all_features, next_feature); + rte_free(node_info); + } + feature_arc_list_destroy(arc, 0); + feature_arc_list_destroy(arc, 1); + + dm->feature_arcs[arc->feature_arc_index] = RTE_GRAPH_FEATURE_ARC_INITIALIZER; + + rte_free(arc); + + do_sanity_all_arcs(); + + return 0; +} + +int +rte_graph_feature_arc_cleanup(void) +{ + rte_graph_feature_arc_main_t *dm = __rte_graph_feature_arc_main; + uint32_t iter; + + if (!__rte_graph_feature_arc_main) + return -1; + + for (iter = 0; iter < dm->max_feature_arcs; iter++) { + if (dm->feature_arcs[iter] == RTE_GRAPH_FEATURE_ARC_INITIALIZER) + continue; + + rte_graph_feature_arc_destroy((rte_graph_feature_arc_t)dm->feature_arcs[iter]); + } + rte_free(dm); + + __rte_graph_feature_arc_main = NULL; + + return 0; +} + +int +rte_graph_feature_arc_lookup_by_name(const char *arc_name, rte_graph_feature_arc_t *_arc) +{ + rte_graph_feature_arc_main_t *dm = __rte_graph_feature_arc_main; + struct rte_graph_feature_arc *arc = NULL; + uint32_t iter; + + if (!__rte_graph_feature_arc_main) + return -1; + + if (_arc) + *_arc = RTE_GRAPH_FEATURE_ARC_INITIALIZER; + + for (iter = 0; iter < dm->max_feature_arcs; iter++) { + if (dm->feature_arcs[iter] == RTE_GRAPH_FEATURE_ARC_INITIALIZER) + continue; + + arc = rte_graph_feature_arc_get(dm->feature_arcs[iter]); + + if ((strstr(arc->feature_arc_name, arc_name)) && + (strlen(arc->feature_arc_name) == strlen(arc_name))) { + if (_arc) + *_arc = (rte_graph_feature_arc_t)arc; + return 0; + } + } + + return -1; +} + +uint32_t +rte_graph_feature_arc_num_enabled_features(rte_graph_feature_arc_t _arc) +{ + struct rte_graph_feature_arc *arc = rte_graph_feature_arc_get(_arc); + + return arc->runtime_enabled_features; +} + +uint32_t +rte_graph_feature_arc_num_features(rte_graph_feature_arc_t _arc) +{ + struct rte_graph_feature_arc *arc = rte_graph_feature_arc_get(_arc); + struct rte_graph_feature_node_list *finfo = NULL; + uint32_t count = 0; + + STAILQ_FOREACH(finfo, &arc->all_features, next_feature) + count++; + + return count; +} + +char * +rte_graph_feature_arc_feature_to_name(rte_graph_feature_arc_t _arc, rte_graph_feature_t feat) +{ + struct rte_graph_feature_arc *arc = rte_graph_feature_arc_get(_arc); + struct rte_graph_feature_node_list *finfo = NULL; + uint32_t slot = feat; + + if (feat >= rte_graph_feature_arc_num_features(_arc)) { + graph_err("%s: feature %u does not exist", arc->feature_arc_name, feat); + return NULL; + } + if (!feature_arc_node_info_lookup(arc, slot, &finfo, 0/* ignore sanity*/)) + return finfo->feature_node->name; + + return NULL; +} + +struct rte_node_register * +rte_graph_feature_arc_feature_to_node(rte_graph_feature_arc_t _arc, rte_graph_feature_t feat) +{ + struct rte_graph_feature_arc *arc = rte_graph_feature_arc_get(_arc); + struct rte_graph_feature_node_list *finfo = NULL; + uint32_t slot = feat; + + if (feat >= rte_graph_feature_arc_num_features(_arc)) { + graph_err("%s: feature %u does not exist", arc->feature_arc_name, feat); + return NULL; + } + if (!feature_arc_node_info_lookup(arc, slot, &finfo, 0/* ignore sanity*/)) + return finfo->feature_node; + + return NULL; + +} diff --git a/lib/graph/meson.build b/lib/graph/meson.build index 0cb15442ab..d916176fb7 100644 --- a/lib/graph/meson.build +++ b/lib/graph/meson.build @@ -14,11 +14,13 @@ sources = files( 'graph_debug.c', 'graph_stats.c', 'graph_populate.c', + 'graph_feature_arc.c', 'graph_pcap.c', 'rte_graph_worker.c', 'rte_graph_model_mcore_dispatch.c', ) headers = files('rte_graph.h', 'rte_graph_worker.h') +headers += files('rte_graph_feature_arc.h', 'rte_graph_feature_arc_worker.h') indirect_headers += files( 'rte_graph_model_mcore_dispatch.h', 'rte_graph_model_rtc.h', diff --git a/lib/graph/rte_graph_feature_arc.h b/lib/graph/rte_graph_feature_arc.h new file mode 100644 index 0000000000..1615f8e1c8 --- /dev/null +++ b/lib/graph/rte_graph_feature_arc.h @@ -0,0 +1,431 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(C) 2024 Marvell International Ltd. + */ + +#ifndef _RTE_GRAPH_FEATURE_ARC_H_ +#define _RTE_GRAPH_FEATURE_ARC_H_ + +#include <assert.h> +#include <errno.h> +#include <signal.h> +#include <stddef.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <rte_common.h> +#include <rte_compat.h> +#include <rte_debug.h> +#include <rte_graph.h> +#include <rte_graph_worker.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @file + * + * rte_graph_feature_arc.h + * + * Define APIs and structures/variables with respect to feature arc + * + * - Feature arc(s) + * - Feature(s) + * + * A feature arc represents an ordered list of features/protocol-nodes at a + * given networking layer. Feature arc provides a high level abstraction to + * connect various *rte_graph* nodes, designated as *feature nodes*, and + * allowing steering of packets across these feature nodes fast path processing + * in a generic manner. In a typical network stack, often a protocol or feature + * must be first enabled on a given interface, before any packet is steered + * towards it for feature processing. For eg: incoming IPv4 packets are sent to + * routing sub-system only after a valid IPv4 address is assigned to the + * received interface. In other words, often packets needs to be steered across + * features not based on the packet content but based on whether a feature is + * enable or disable on a given incoming/outgoing interface. Feature arc + * provides mechanism to enable/disable feature(s) on each interface at runtime + * and allow seamless packet steering across runtime enabled feature nodes in + * fast path. + * + * Feature arc also provides a way to steer packets from standard nodes to + * custom/user-defined *feature nodes* without any change in standard node's + * fast path functions + * + * On a given interface multiple feature(s) might be enabled in a particular + * feature arc. For instance, both "ipv4-output" and "IPsec policy output" + * features may be enabled on "eth0" interface in "L3-output" feature arc. + * Similarly, "ipv6-output" and "ipsec-output" may be enabled on "eth1" + * interface in same "L3-output" feature arc. + * + * When multiple features are present in a given feature arc, its imperative + * to allow each feature processing in a particular sequential order. For + * instance, in "L3-input" feature arc it may be required to run "IPsec + * input" feature first, for packet decryption, before "ip-lookup". So a + * sequential order must be maintained among features present in a feature arc. + * + * Features are enabled/disabled multiple times at runtime to some or all + * available interfaces present in the system. Enable/disabling features on one + * interface is independent of other interface. + * + * A given feature might consume packet (if it's configured to consume) or may + * forward it to next enabled feature. For instance, "IPsec input" feature may + * consume/drop all packets with "Protect" policy action while all packets with + * policy action as "Bypass" may be forwarded to next enabled feature (with in + * same feature arc) + * + * This library facilitates rte graph based applications to steer packets in + * fast path to different feature nodes with-in a feature arc and support all + * functionalities described above + * + * In order to use feature-arc APIs, applications needs to do following in + * control path: + * - Initialize feature arc library via rte_graph_feature_arc_init() + * - Create feature arc via rte_graph_feature_arc_create() + * - *Before calling rte_graph_create()*, features must be added to feature-arc + * via rte_graph_feature_add(). rte_graph_feature_add() allows adding + * features in a sequential order with "runs_after" and "runs_before" + * constraints. + * - Post rte_graph_create(), features can be enabled/disabled at runtime on + * any interface via rte_graph_feature_enable()/rte_graph_feature_disable() + * - Feature arc can be destroyed via rte_graph_feature_arc_destroy() + * + * In fast path, APIs are provided to steer packets towards feature path from + * - start_node (provided as an argument to rte_graph_feature_arc_create()) + * - feature nodes (which are added via rte_graph_feature_add()) + * + * For typical steering of packets across feature nodes, application required + * to know "rte_edges" which are saved in feature data object. Feature data + * object is unique for every interface per feature with in a feature arc. + * + * When steering packets from start_node to feature node: + * - rte_graph_feature_arc_first_feature_get() provides first enabled feature. + * - Next rte_edge from start_node to first enabled feature can be obtained via + * rte_graph_feature_arc_feature_set() + * + * rte_mbuf can carry [current feature, interface index] from start_node of an + * arc to other feature nodes + * + * At the time of feature enable(rte_graph_feature_enable), application can set + * 32-bit unique user_data specific to feature per interface. In fast path + * user_data can be retrieved via rte_graph_feature_user_data_get(). User data + * can hold application specific cookie like IPsec policy database index, FIB + * table index etc. + * + * If feature node is not consuming packet, next enabled feature and next + * rte_edge can be obtained via rte_graph_feature_arc_next_feature_get() + * + * It is application responsibility to ensure that at-least *last feature*(or + * sink feature) must be enabled from where packet can exit feature-arc path, + * if *NO* intermediate feature is consuming the packet and it has reached till + * the end of feature arc path + * + * It is recommended that all features *MUST* be added to feature arc before + * calling `rte_graph_create()`. Addition of features after + * `rte_graph_create()` may not work functionally. + * Although,rte_graph_feature_enable()/rte_graph_feature_disable() should be + * called after `rte_graph_create()` in control plane. + * + * Synchronization among cores + * --------------------------- + * Subsequent calls to rte_graph_feature_enable() is allowed while worker cores + * are processing in rte_graph_walk() loop. However, for + * rte_graph_feature_disable() application must use RCU based synchronization + */ + +/** Initializer value for rte_graph_feature_arc_t */ +#define RTE_GRAPH_FEATURE_ARC_INITIALIZER ((rte_graph_feature_arc_t)UINT64_MAX) + +/** Max number of feature arcs which can be created */ +#define RTE_GRAPH_FEATURE_ARC_MAX 64 + +/** Max number of features supported in a given feature arc */ +#define RTE_GRAPH_FEATURE_MAX_PER_ARC 64 + +/** Length of feature arc name */ +#define RTE_GRAPH_FEATURE_ARC_NAMELEN RTE_NODE_NAMESIZE + +/** @internal */ +#define rte_graph_feature_cast(x) ((rte_graph_feature_t)x) + +/**< Initializer value for rte_graph_feature_arc_t */ +#define RTE_GRAPH_FEATURE_INVALID rte_graph_feature_cast(UINT8_MAX) + +/** rte_graph feature arc object */ +typedef uintptr_t rte_graph_feature_arc_t; + +/** rte_graph feature object */ +typedef uint8_t rte_graph_feature_t; + +/** runtime active feature list index with in feature arc*/ +typedef uint16_t rte_graph_feature_rt_list_t; + +/** per feature arc monotonically increasing counter to synchronize fast path APIs */ +typedef uint16_t rte_graph_feature_counter_t; + +/** + * Initialize feature arc subsystem + * + * @param max_feature_arcs + * Maximum number of feature arcs required to be supported + * + * @return + * 0: Success + * <0: Failure + */ +__rte_experimental +int rte_graph_feature_arc_init(int max_feature_arcs); + +/** + * Create a feature arc + * + * @param feature_arc_name + * Feature arc name with max length of @ref RTE_GRAPH_FEATURE_ARC_NAMELEN + * @param max_features + * Maximum number of features to be supported in this feature arc + * @param max_indexes + * Maximum number of interfaces/ports/indexes to be supported + * @param start_node + * Base node where this feature arc's features are checked in fast path + * @param[out] _arc + * Feature arc object + * + * @return + * 0: Success + * <0: Failure + */ +__rte_experimental +int rte_graph_feature_arc_create(const char *feature_arc_name, int max_features, int max_indexes, + struct rte_node_register *start_node, + rte_graph_feature_arc_t *_arc); + +/** + * Get feature arc object with name + * + * @param arc_name + * Feature arc name provided to successful @ref rte_graph_feature_arc_create + * @param[out] _arc + * Feature arc object returned. Valid only when API returns SUCCESS + * + * @return + * 0: Success + * <0: Failure. + */ +__rte_experimental +int rte_graph_feature_arc_lookup_by_name(const char *arc_name, rte_graph_feature_arc_t *_arc); + +/** + * Add a feature to already created feature arc. For instance + * + * 1. Add first feature node: "ipv4-input" to input arc + * rte_graph_feature_add(ipv4_input_arc, "ipv4-input", NULL, NULL); + * + * 2. Add "ipsec-input" feature node after "ipv4-input" feature + * rte_graph_feature_add(ipv4_input_arc, "ipsec-input", "ipv4-input", NULL); + * + * 3. Add "ipv4-pre-classify-input" node before "ipv4-input" feature + * rte_graph_feature_add(ipv4_input_arc, "ipv4-pre-classify-input"", NULL, "ipv4-input"); + * + * 4. Add "acl-classify-input" node after ipv4-input but before ipsec-input + * rte_graph_feature_add(ipv4_input_arc, "acl-classify-input", "ipv4-input", "ipsec-input"); + * + * @param _arc + * Feature arc handle returned from @ref rte_graph_feature_arc_create() + * @param feature_node + * Graph node representing feature. On success, feature_node is next_node of + * feature_arc->start_node + * @param runs_after + * Add this feature_node after already added "runs_after". Creates + * start_node -> runs_after -> this_feature sequence + * @param runs_before + * Add this feature_node before already added "runs_before". Creates + * start_node -> this_feature -> runs_before sequence + * + * <I> Must be called before rte_graph_create() </I> + * <I> rte_graph_feature_add() is not allowed after call to + * rte_graph_feature_enable() so all features must be added before they can be + * enabled </I> + * + * @return + * 0: Success + * <0: Failure + */ +__rte_experimental +int rte_graph_feature_add(rte_graph_feature_arc_t _arc, struct rte_node_register *feature_node, + const char *runs_after, const char *runs_before); + +/** + * Enable feature within a feature arc + * + * Must be called after @b rte_graph_create(). + * + * @param _arc + * Feature arc object returned by @ref rte_graph_feature_arc_create or @ref + * rte_graph_feature_arc_lookup_by_name + * @param index + * Application specific index. Can be corresponding to interface_id/port_id etc + * @param feature_name + * Name of the node which is already added via @ref rte_graph_feature_add + * @param user_data + * Application specific data which is retrieved in fast path + * + * @return + * 0: Success + * <0: Failure + */ +__rte_experimental +int rte_graph_feature_enable(rte_graph_feature_arc_t _arc, uint32_t index, const char *feature_name, + int32_t user_data); + +/** + * Validate whether subsequent enable/disable feature would succeed or not. + * API is thread-safe + * + * @param _arc + * Feature arc object returned by @ref rte_graph_feature_arc_create or @ref + * rte_graph_feature_arc_lookup_by_name + * @param index + * Application specific index. Can be corresponding to interface_id/port_id etc + * @param feature_name + * Name of the node which is already added via @ref rte_graph_feature_add + * @param is_enable_disable + * If 1, validate whether subsequent @ref rte_graph_feature_enable would pass or not + * If 0, validate whether subsequent @ref rte_graph_feature_disable would pass or not + * @param emit_logs + * If passed true, emit error logs when failure is returned + * If passed false, do not emit error logs when failure is returned + * + * @return + * 0: Subsequent enable/disable API would pass + * <0: Subsequent enable/disable API would not pass + */ +__rte_experimental +int rte_graph_feature_validate(rte_graph_feature_arc_t _arc, uint32_t index, + const char *feature_name, int is_enable_disable, bool emit_logs); + +/** + * Disable already enabled feature within a feature arc + * + * Must be called after @b rte_graph_create(). API is *NOT* Thread-safe + * + * @param _arc + * Feature arc object returned by @ref rte_graph_feature_arc_create or @ref + * rte_graph_feature_arc_lookup_by_name + * @param index + * Application specific index. Can be corresponding to interface_id/port_id etc + * @param feature_name + * Name of the node which is already added via @ref rte_graph_feature_add + * + * @return + * 0: Success + * <0: Failure + */ +__rte_experimental +int rte_graph_feature_disable(rte_graph_feature_arc_t _arc, uint32_t index, + const char *feature_name); + +/** + * Get rte_graph_feature_t object from feature name + * + * @param arc + * Feature arc object returned by @ref rte_graph_feature_arc_create or @ref + * rte_graph_feature_arc_lookup_by_name + * @param feature_name + * Feature name provided to @ref rte_graph_feature_add + * @param[out] feature + * Feature object + * + * @return + * 0: Success + * <0: Failure + */ +__rte_experimental +int rte_graph_feature_lookup(rte_graph_feature_arc_t arc, const char *feature_name, + rte_graph_feature_t *feature); + +/** + * Delete feature_arc object + * + * @param _arc + * Feature arc object returned by @ref rte_graph_feature_arc_create or @ref + * rte_graph_feature_arc_lookup_by_name + * + * @return + * 0: Success + * <0: Failure + */ +__rte_experimental +int rte_graph_feature_arc_destroy(rte_graph_feature_arc_t _arc); + +/** + * Cleanup all feature arcs + * + * @return + * 0: Success + * <0: Failure + */ +__rte_experimental +int rte_graph_feature_arc_cleanup(void); + +/** + * Slow path API to know how many features are added (NOT enabled) within a + * feature arc + * + * @param _arc + * Feature arc object + * + * @return: Number of added features to arc + */ +__rte_experimental +uint32_t rte_graph_feature_arc_num_features(rte_graph_feature_arc_t _arc); + +/** + * Slow path API to know how many features are currently enabled within a + * feature arc across all indexes. If a single feature is enabled on all interfaces, + * this API would return "number_of_interfaces" as count (but not "1") + * + * @param _arc + * Feature arc object + * + * @return: Number of enabled features across all indexes + */ +__rte_experimental +uint32_t rte_graph_feature_arc_num_enabled_features(rte_graph_feature_arc_t _arc); + +/** + * Slow path API to get feature node name from rte_graph_feature_t object + * + * @param _arc + * Feature arc object + * @param feature + * Feature object + * + * @return: Name of the feature node + */ +__rte_experimental +char *rte_graph_feature_arc_feature_to_name(rte_graph_feature_arc_t _arc, + rte_graph_feature_t feature); + +/** + * Slow path API to get corresponding struct rte_node_register * from + * rte_graph_feature_t + * + * @param _arc + * Feature arc object + * @param feature + * Feature object + * + * @return: struct rte_node_register * of feature node on SUCCESS else NULL + */ +__rte_experimental +struct rte_node_register * +rte_graph_feature_arc_feature_to_node(rte_graph_feature_arc_t _arc, + rte_graph_feature_t feature); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/graph/rte_graph_feature_arc_worker.h b/lib/graph/rte_graph_feature_arc_worker.h new file mode 100644 index 0000000000..ca12b3ffd0 --- /dev/null +++ b/lib/graph/rte_graph_feature_arc_worker.h @@ -0,0 +1,674 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(C) 2024 Marvell International Ltd. + */ + +#ifndef _RTE_GRAPH_FEATURE_ARC_WORKER_H_ +#define _RTE_GRAPH_FEATURE_ARC_WORKER_H_ + +#include <stddef.h> +#include <rte_graph_feature_arc.h> +#include <rte_bitops.h> + +/** + * @file + * + * rte_graph_feature_arc_worker.h + * + * Defines fast path structure + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** @internal + * + * Slow path feature node info list + */ +struct rte_graph_feature_node_list { + /** Next feature */ + STAILQ_ENTRY(rte_graph_feature_node_list) next_feature; + + /** node representing feature */ + struct rte_node_register *feature_node; + + /** How many indexes/interfaces using this feature */ + int32_t ref_count; + + /* node_index in list (after feature_enable())*/ + uint32_t node_index; + + /** Back pointer to feature arc */ + void *feature_arc; + + /** rte_edge_t to this feature node from feature_arc->start_node */ + rte_edge_t edge_to_this_feature; +}; + +/** + * Feature data object: + * + * Feature data stores information to steer packets for: + * - a feature with in feature arc + * - Index i.e. Port/Interface index + * + * Each feature data object holds + * - User data of current feature retrieved via rte_graph_feature_user_data_get() + * - next_edge is used in two conditions when packet to be steered from + * -- start_node to first enabled feature on an interface index + * -- current feature node to next enabled feature on an interface index + * - next_enabled_feature on interface index, if current feature is not + * consuming packet + * + * While user_data corresponds to current enabled feature node however + * next_edge and next_enabled_feature corresponds to next enabled feature + * node on an interface index + * + * First enabled feature on interface index can be retrieved via: + * - rte_graph_feature_first_feature_get() if arc's start_node is trying to + * steer packet from start_node to first enabled feature on interface index + * + * Next enabled feature on interface index can be retrieved via: + * - rte_graph_feature_next_feature_get() if current node is not arc's + * start_node. Input to rte_graph_feature_next_feature_get() is current + * enabled feature and interface index + */ +typedef struct __rte_packed rte_graph_feature_data { + /** edge from current node to next enabled feature */ + rte_edge_t next_edge; + + union { + uint16_t reserved; + struct { + /** next enabled feature on index from current feature */ + rte_graph_feature_t next_enabled_feature; + }; + }; + + /** user_data set by application in rte_graph_feature_enable() for + * - current feature + * - interface index + */ + int32_t user_data; +} rte_graph_feature_data_t; + +/** + * Feature object + * + * Feature object holds feature data object for every index/interface within + * feature + * + * Within a given arc and interface index, first feature object can be + * retrieved in arc's start_node via: + * - rte_graph_feature_arc_first_feature_get() + * + * Feature data information can be retrieved for first feature in start node via + * - rte_graph_feature_arc_feature_set() + * + * Next enabled feature on interface index can be retrieved via: + * - rte_graph_feature_arc_next_feature_get() + * + * Typically application stores rte_graph_feature_t object in rte_mbuf. + * rte_graph_feature_t can be translated to (struct rte_graph_feature *) via + * rte_graph_feature_get() in fast path. Further if needed, feature data for an + * index within a feature can be retrieved via rte_graph_feature_data_get() + */ +struct __rte_cache_aligned rte_graph_feature { + /** feature index or rte_graph_feature_t */ + uint16_t this_feature_index; + + /* + * Array of size arc->feature_data_size + * + * <----------------- Feature --------------------------> + * [data-index-0][data-index-1]...[data-index-max_index-1] + * + * sizeof(feature_data_by_index[0] == sizeof(rte_graph_feature_data_t) + * + */ + uint8_t feature_data_by_index[]; +}; + +/** + * Feature list object + * + * Feature list is required to decouple fast path APIs with control path APIs. + * + * There are two feature lists: active, passive + * Passive list is duplicate of active list in terms of memory. + * + * While fast path APIs always work on active list but control plane work on + * passive list. When control plane needs to enable/disable any feature, it + * populates passive list afresh and atomically switch passive list to active + * list to make it available for fast path APIs + * + * Each feature node in start of its fast path function, must grab active list from + * arc via + * - rte_graph_feature_arc_has_any_feature() or + * rte_graph_feature_arc_has_feature() + * + * Retrieved list must be provided to other feature arc fast path APIs so that + * any control plane changes of active list should not impact current node + * execution iteration. Active list change would be reflected to current node + * in next iteration + * + * With active/passive lists and RCU mechanism in graph worker + * loop, application can update features at runtime without stopping fast path + * cores. A RCU synchronization is required when a feature needs to be + * disabled via rte_graph_feature_disable(). On enabling a feature, RCU + * synchronization may not be required + * + */ +typedef struct __rte_cache_aligned rte_graph_feature_list { + /** + * fast path array holding per_feature data. + * Duplicate entry as feature-arc also hold this pointer + * arc->features[] + * + *<-------------feature-0 ---------><---------feature-1 -------------->... + *[index-0][index-1]...[max_index-1]<-ALIGN->[index-0][index-1] ...[max_index-1]... + */ + struct rte_graph_feature *indexed_by_features; + /* + * fast path array holding first enabled feature per index + * (Required in start_node. In non start_node, mbuf can hold next enabled + * feature) + */ + rte_graph_feature_t first_enabled_feature_by_index[]; +} rte_graph_feature_list_t; + +/** + * rte_graph Feature arc object + * + * Feature arc object holds control plane and fast path information for all + * features and all interface index information for steering packets across + * feature nodes + * + * Within a feature arc, only RTE_GRAPH_FEATURE_MAX_PER_ARC features can be + * added. If more features needs to be added, another feature arc can be + * created + * + * Application gets rte_graph_feature_arc_t object via + * - rte_graph_feature_arc_create() OR + * - rte_graph_feature_arc_lookup_by_name() + * + * In fast path, rte_graph_feature_arc_t can be translated to (struct + * rte_graph_feature_arc *) via rte_graph_feature_arc_get(). Later is needed to + * add as an input argument to all fast path feature arc APIs + */ +struct __rte_cache_aligned rte_graph_feature_arc { + /* First 64B is fast path variables */ + RTE_MARKER fast_path_variables; + + /** runtime active feature list */ + rte_graph_feature_rt_list_t active_feature_list; + + /** Actual Size of feature_list object */ + uint16_t feature_list_size; + + /** + * Size each feature in fastpath. + * Required to navigate from feature to another feature in fast path + */ + uint16_t feature_size; + + /** + * Size of all feature data for an index + * Required to navigate through various feature data within a feature + * in fast path + */ + uint16_t feature_data_size; + + /** + * Quick fast path bitmask indicating if any feature enabled or not on + * any of the indexes. Helps in optimally process packets for the case + * when features are added but not enabled + * + * Separate for active and passive list + */ + uint64_t feature_enable_bitmask[2]; + + /** + * Pointer to both active and passive feature list object + */ + rte_graph_feature_list_t *feature_list[2]; + + /** + * Feature objects for each list + */ + struct rte_graph_feature *features[2]; + + /** index in feature_arc_main */ + uint16_t feature_arc_index; + + uint16_t reserved[3]; + + /** Slow path variables follows*/ + RTE_MARKER slow_path_variables; + + /** feature arc name */ + char feature_arc_name[RTE_GRAPH_FEATURE_ARC_NAMELEN]; + + /** All feature lists */ + STAILQ_HEAD(, rte_graph_feature_node_list) all_features; + + /** control plane counter to track enabled features */ + uint32_t runtime_enabled_features; + + /** Back pointer to feature_arc_main */ + void *feature_arc_main; + + /** Arc's start/base node */ + struct rte_node_register *start_node; + + /** maximum number of features supported by this arc */ + uint32_t max_features; + + /** maximum number of index supported by this arc */ + uint32_t max_indexes; + + /** Slow path bit mask per feature per index */ + uint64_t feature_bit_mask_by_index[]; +}; + +/** + * Feature arc main object + * + * Holds all feature arcs created by application + * + * RTE_GRAPH_FEATURE_ARC_MAX number of feature arcs can be created by + * application via rte_graph_feature_arc_create() + */ +typedef struct feature_arc_main { + /** number of feature arcs created by application */ + uint32_t num_feature_arcs; + + /** max features arcs allowed */ + uint32_t max_feature_arcs; + + /** feature arcs */ + rte_graph_feature_arc_t feature_arcs[]; +} rte_graph_feature_arc_main_t; + +/** @internal Get feature arc pointer from object */ +#define rte_graph_feature_arc_get(arc) ((struct rte_graph_feature_arc *)arc) + +extern rte_graph_feature_arc_main_t *__feature_arc_main; + +/** + * API to know if feature is valid or not + */ +__rte_experimental +static __rte_always_inline int +rte_graph_feature_is_valid(rte_graph_feature_t feature) +{ + return (feature != RTE_GRAPH_FEATURE_INVALID); +} + +/** + * Get rte_graph_feature object with no checks + * + * @param arc + * Feature arc pointer + * @param feature + * Feature index + * @param feature_list + * active feature list retrieved from rte_graph_feature_arc_has_any_feature() + * or rte_graph_feature_arc_has_feature() + * + * @return + * Internal feature object. + */ +__rte_experimental +static __rte_always_inline struct rte_graph_feature * +__rte_graph_feature_get(struct rte_graph_feature_arc *arc, rte_graph_feature_t feature, + const rte_graph_feature_rt_list_t feature_list) +{ + return ((struct rte_graph_feature *)(((uint8_t *)arc->features[feature_list]) + + (feature * arc->feature_size))); +} + +/** + * Get rte_graph_feature object for a given interface/index from feature arc + * + * @param arc + * Feature arc pointer + * @param feature + * Feature index + * + * @return + * Internal feature object. + */ +__rte_experimental +static __rte_always_inline struct rte_graph_feature * +rte_graph_feature_get(struct rte_graph_feature_arc *arc, rte_graph_feature_t feature) +{ + if (unlikely(feature >= arc->max_features)) + RTE_VERIFY(0); + + if (likely(rte_graph_feature_is_valid(feature))) + return __rte_graph_feature_get(arc, feature, arc->active_feature_list); + + return NULL; +} + +__rte_experimental +static __rte_always_inline rte_graph_feature_data_t * +__rte_graph_feature_data_get(struct rte_graph_feature_arc *arc, struct rte_graph_feature *feature, + uint8_t index) +{ + RTE_SET_USED(arc); + return ((rte_graph_feature_data_t *)(((uint8_t *)feature->feature_data_by_index) + + (index * sizeof(rte_graph_feature_data_t)))); +} + +/** + * Get rte_graph feature data object for a index in feature + * + * @param arc + * feature arc + * @param feature + * Pointer to feature object + * @param index + * Index of feature maintained in slow path linked list + * + * @return + * Valid feature data + */ +__rte_experimental +static __rte_always_inline rte_graph_feature_data_t * +rte_graph_feature_data_get(struct rte_graph_feature_arc *arc, struct rte_graph_feature *feature, + uint8_t index) +{ + if (likely(index < arc->max_indexes)) + return __rte_graph_feature_data_get(arc, feature, index); + + RTE_VERIFY(0); +} + +/** + * Fast path API to check if any feature enabled on a feature arc + * Typically from arc->start_node process function + * + * @param arc + * Feature arc object + * @param[out] plist + * Pointer to runtime active feature list which needs to be provided to other + * fast path APIs + * + * @return + * 0: If no feature enabled + * Non-Zero: Bitmask of features enabled. plist is valid + * + */ +__rte_experimental +static __rte_always_inline uint64_t +rte_graph_feature_arc_has_any_feature(struct rte_graph_feature_arc *arc, + rte_graph_feature_rt_list_t *plist) +{ + *plist = rte_atomic_load_explicit(&arc->active_feature_list, rte_memory_order_relaxed); + + return (rte_atomic_load_explicit(arc->feature_enable_bitmask + (uint8_t)*plist, + rte_memory_order_relaxed)); +} + +/** + * Fast path API to check if provided feature is enabled on any interface/index + * or not + * + * @param arc + * Feature arc object + * @param feature + * Input rte_graph_feature_t that needs to be checked + * @param[out] plist + * Returns active list to caller which needs to be provided to other fast path + * APIs + * + * @return + * 1: If input [feature] is enabled in arc + * 0: If input [feature] is not enabled in arc + */ +__rte_experimental +static __rte_always_inline int +rte_graph_feature_arc_has_feature(struct rte_graph_feature_arc *arc, + rte_graph_feature_t feature, + rte_graph_feature_rt_list_t *plist) +{ + uint64_t bitmask = RTE_BIT64(feature); + + *plist = rte_atomic_load_explicit(&arc->active_feature_list, rte_memory_order_relaxed); + + return (bitmask & rte_atomic_load_explicit(arc->feature_enable_bitmask + (uint8_t)*plist, + rte_memory_order_relaxed)); +} + +/** + * Prefetch feature arc fast path cache line + * + * @param arc + * RTE_GRAPH feature arc object + */ +__rte_experimental +static __rte_always_inline void +rte_graph_feature_arc_prefetch(struct rte_graph_feature_arc *arc) +{ + rte_prefetch0((void *)&arc->fast_path_variables); +} + +/** + * Prefetch feature related fast path cache line + * + * @param arc + * RTE_GRAPH feature arc object + * @param list + * Pointer to runtime active feature list from rte_graph_feature_arc_has_any_feature(); + * @param feature + * Pointer to feature object + */ +__rte_experimental +static __rte_always_inline void +rte_graph_feature_arc_feature_prefetch(struct rte_graph_feature_arc *arc, + const rte_graph_feature_rt_list_t list, + rte_graph_feature_t feature) +{ + /* feature cache line */ + if (likely(rte_graph_feature_is_valid(feature))) + rte_prefetch0((void *)__rte_graph_feature_get(arc, feature, list)); +} + +/** + * Prefetch feature data upfront. Perform sanity + * + * @param arc + * RTE_GRAPH feature arc object + * @param list + * Pointer to runtime active feature list from rte_graph_feature_arc_has_any_feature(); + * @param feature + * Pointer to feature object returned from @ref + * rte_graph_feature_arc_first_feature_get() + * @param index + * Interface/index + */ +__rte_experimental +static __rte_always_inline void +rte_graph_feature_arc_data_prefetch(struct rte_graph_feature_arc *arc, + const rte_graph_feature_rt_list_t list, + rte_graph_feature_t feature, uint32_t index) +{ + if (likely(rte_graph_feature_is_valid(feature))) + rte_prefetch0((void *)((uint8_t *)arc->features[list] + + offsetof(struct rte_graph_feature, feature_data_by_index) + + (index * sizeof(rte_graph_feature_data_t)))); +} + +/** + * Fast path API to get first enabled feature on interface index + * Typically required in arc->start_node so that from returned feature, + * feature-data can be retrieved to steer packets + * + * @param arc + * Feature arc object + * @param list + * Pointer to runtime active feature list from + * rte_graph_feature_arc_has_any_feature() or + * rte_graph_feature_arc_has_feature() + * @param index + * Interface Index + * @param[out] feature + * Pointer to rte_graph_feature_t. + * + * @return + * 1. Success. If first feature field is enabled and returned [feature] is valid + * 0. Failure. If first feature field is disabled in arc + * + */ +__rte_experimental +static __rte_always_inline int +rte_graph_feature_arc_first_feature_get(struct rte_graph_feature_arc *arc, + const rte_graph_feature_rt_list_t list, + uint32_t index, + rte_graph_feature_t *feature) +{ + struct rte_graph_feature_list *feature_list = arc->feature_list[list]; + + *feature = feature_list->first_enabled_feature_by_index[index]; + + return rte_graph_feature_is_valid(*feature); +} + +/** + * Fast path API to get next enabled feature on interface index with provided + * input feature + * + * @param arc + * Feature arc object + * @param list + * Pointer to runtime active feature list from + * rte_graph_feature_arc_has_any_feature() or + * @param index + * Interface Index + * @param[out] feature + * Pointer to rte_graph_feature_t. API sets next enabled feature on [index] + * from provided input feature. Valid only if API returns Success + * @param[out] next_edge + * Edge from current feature to next feature. Valid only if next feature is valid + * + * @return + * 1. Success. first feature field is enabled/valid + * 0. Failure. first feature field is disabled/invalid + */ +__rte_experimental +static __rte_always_inline int +rte_graph_feature_arc_next_feature_get(struct rte_graph_feature_arc *arc, + const rte_graph_feature_rt_list_t list, + uint32_t index, + rte_graph_feature_t *feature, + rte_edge_t *next_edge) +{ + rte_graph_feature_data_t *feature_data = NULL; + struct rte_graph_feature *f = NULL; + + if (likely(rte_graph_feature_is_valid(*feature))) { + f = __rte_graph_feature_get(arc, *feature, list); + feature_data = rte_graph_feature_data_get(arc, f, index); + *feature = feature_data->next_enabled_feature; + *next_edge = feature_data->next_edge; + return rte_graph_feature_is_valid(*feature); + } + + return 0; +} + +/** + * Set fields with respect to first enabled feature in an arc and return edge + * Typically returned feature and interface index must be saved in rte_mbuf + * structure to pass this information to next feature node + * + * @param arc + * Feature arc object + * @param list + * Pointer to runtime active feature list from rte_graph_feature_arc_has_any_feature(); + * @param index + * Index (of interface) + * @param[out] gf + * Pointer to rte_graph_feature_t. Valid if API returns Success + * @param[out] edge + * Edge to steer packet from arc->start_node to first enabled feature. Valid + * only if API returns Success + * + * @return + * 0: If valid feature is enabled and set by API in *gf + * 1: If valid feature is NOT enabled + */ +__rte_experimental +static __rte_always_inline rte_graph_feature_t +rte_graph_feature_arc_feature_set(struct rte_graph_feature_arc *arc, + const rte_graph_feature_rt_list_t list, + uint32_t index, + rte_graph_feature_t *gf, + rte_edge_t *edge) +{ + struct rte_graph_feature_list *feature_list = arc->feature_list[list]; + struct rte_graph_feature_data *feature_data = NULL; + struct rte_graph_feature *feature = NULL; + rte_graph_feature_t f; + + f = feature_list->first_enabled_feature_by_index[index]; + + if (unlikely(rte_graph_feature_is_valid(f))) { + feature = __rte_graph_feature_get(arc, f, list); + feature_data = rte_graph_feature_data_get(arc, feature, index); + *gf = f; + *edge = feature_data->next_edge; + return 0; + } + + return 1; +} + +__rte_experimental +static __rte_always_inline int32_t +__rte_graph_feature_user_data_get(rte_graph_feature_data_t *fdata) +{ + return fdata->user_data; +} + +/** + * Get user data corresponding to current feature set by application in + * rte_graph_feature_enable() + * + * @param arc + * Feature arc object + * @param list + * Pointer to runtime active feature list from rte_graph_feature_arc_has_any_feature(); + * @param feature + * Feature index + * @param index + * Interface index + * + * @return + * -1: Failure + * Valid user data: Success + */ +__rte_experimental +static __rte_always_inline int32_t +rte_graph_feature_user_data_get(struct rte_graph_feature_arc *arc, + const rte_graph_feature_rt_list_t list, + rte_graph_feature_t feature, + uint32_t index) +{ + rte_graph_feature_data_t *fdata = NULL; + struct rte_graph_feature *f = NULL; + + if (likely(rte_graph_feature_is_valid(feature))) { + f = __rte_graph_feature_get(arc, feature, list); + fdata = rte_graph_feature_data_get(arc, f, index); + return __rte_graph_feature_user_data_get(fdata); + } + + return -1; +} +#ifdef __cplusplus +} +#endif +#endif diff --git a/lib/graph/version.map b/lib/graph/version.map index 2c83425ddc..3b7f475afd 100644 --- a/lib/graph/version.map +++ b/lib/graph/version.map @@ -52,3 +52,23 @@ DPDK_25 { local: *; }; + +EXPERIMENTAL { + global: + + # added in 24.11 + rte_graph_feature_arc_init; + rte_graph_feature_arc_create; + rte_graph_feature_arc_lookup_by_name; + rte_graph_feature_add; + rte_graph_feature_enable; + rte_graph_feature_validate; + rte_graph_feature_disable; + rte_graph_feature_lookup; + rte_graph_feature_arc_destroy; + rte_graph_feature_arc_cleanup; + rte_graph_feature_arc_num_enabled_features; + rte_graph_feature_arc_num_features; + rte_graph_feature_arc_feature_to_name; + rte_graph_feature_arc_feature_to_node; +}; -- 2.43.0 ^ permalink raw reply [flat|nested] 46+ messages in thread
* [PATCH v3 2/5] graph: add feature arc option in graph create 2024-10-09 13:29 ` [PATCH v3 0/5] add feature arc in rte_graph Nitin Saxena 2024-10-09 13:29 ` [PATCH v3 1/5] graph: add feature arc support Nitin Saxena @ 2024-10-09 13:29 ` Nitin Saxena 2024-10-09 13:30 ` [PATCH v3 3/5] graph: add IPv4 output feature arc Nitin Saxena ` (5 subsequent siblings) 7 siblings, 0 replies; 46+ messages in thread From: Nitin Saxena @ 2024-10-09 13:29 UTC (permalink / raw) To: Jerin Jacob, Kiran Kumar K, Nithin Dabilpuram, Zhirun Yan, Robin Jarry, Christophe Fontaine Cc: dev, Nitin Saxena, Pavan Nikhilesh Added option in graph create to call feature-specific process node functions. This removes extra overhead for checking feature arc status in nodes where application is not using feature arc processing Signed-off-by: Pavan Nikhilesh <pbhagavatula@marvell.com> Signed-off-by: Nitin Saxena <nsaxena@marvell.com> --- doc/guides/rel_notes/release_24_11.rst | 3 +++ lib/graph/graph.c | 1 + lib/graph/graph_populate.c | 7 ++++++- lib/graph/graph_private.h | 3 +++ lib/graph/node.c | 2 ++ lib/graph/rte_graph.h | 3 +++ 6 files changed, 18 insertions(+), 1 deletion(-) diff --git a/doc/guides/rel_notes/release_24_11.rst b/doc/guides/rel_notes/release_24_11.rst index d6d64518e0..5195badf54 100644 --- a/doc/guides/rel_notes/release_24_11.rst +++ b/doc/guides/rel_notes/release_24_11.rst @@ -122,6 +122,9 @@ ABI Changes Also, make sure to start the actual text at the margin. ======================================================= +* graph: Added new `feature_arc_enable` parameter in `struct rte_graph_param` to + allow `rte_graph_walk()` call `feat_arc_proc` node callback function, if it + is provided in node registration Known Issues ------------ diff --git a/lib/graph/graph.c b/lib/graph/graph.c index d5b8c9f918..b0ad3a83ae 100644 --- a/lib/graph/graph.c +++ b/lib/graph/graph.c @@ -455,6 +455,7 @@ rte_graph_create(const char *name, struct rte_graph_param *prm) graph->parent_id = RTE_GRAPH_ID_INVALID; graph->lcore_id = RTE_MAX_LCORE; graph->num_pkt_to_capture = prm->num_pkt_to_capture; + graph->feature_arc_enabled = prm->feature_arc_enable; if (prm->pcap_filename) rte_strscpy(graph->pcap_filename, prm->pcap_filename, RTE_GRAPH_PCAP_FILE_SZ); diff --git a/lib/graph/graph_populate.c b/lib/graph/graph_populate.c index ed596a7711..5d8aa7b903 100644 --- a/lib/graph/graph_populate.c +++ b/lib/graph/graph_populate.c @@ -79,8 +79,13 @@ graph_nodes_populate(struct graph *_graph) if (graph_pcap_is_enable()) { node->process = graph_pcap_dispatch; node->original_process = graph_node->node->process; - } else + if (_graph->feature_arc_enabled && graph_node->node->feat_arc_proc) + node->original_process = graph_node->node->feat_arc_proc; + } else { node->process = graph_node->node->process; + if (_graph->feature_arc_enabled && graph_node->node->feat_arc_proc) + node->process = graph_node->node->feat_arc_proc; + } memcpy(node->name, graph_node->node->name, RTE_GRAPH_NAMESIZE); pid = graph_node->node->parent_id; if (pid != RTE_NODE_ID_INVALID) { /* Cloned node */ diff --git a/lib/graph/graph_private.h b/lib/graph/graph_private.h index d557d55f2d..58ba0abeff 100644 --- a/lib/graph/graph_private.h +++ b/lib/graph/graph_private.h @@ -56,6 +56,7 @@ struct node { unsigned int lcore_id; /**< Node runs on the Lcore ID used for mcore dispatch model. */ rte_node_process_t process; /**< Node process function. */ + rte_node_process_t feat_arc_proc; /**< Node feature-arch process function. */ rte_node_init_t init; /**< Node init function. */ rte_node_fini_t fini; /**< Node fini function. */ rte_node_t id; /**< Allocated identifier for the node. */ @@ -126,6 +127,8 @@ struct graph { /**< Number of packets to be captured per core. */ char pcap_filename[RTE_GRAPH_PCAP_FILE_SZ]; /**< pcap file name/path. */ + uint8_t feature_arc_enabled; + /**< Graph feature arc. */ STAILQ_HEAD(gnode_list, graph_node) node_list; /**< Nodes in a graph. */ }; diff --git a/lib/graph/node.c b/lib/graph/node.c index 99a9622779..d8fd273543 100644 --- a/lib/graph/node.c +++ b/lib/graph/node.c @@ -90,6 +90,7 @@ __rte_node_register(const struct rte_node_register *reg) goto free; node->flags = reg->flags; node->process = reg->process; + node->feat_arc_proc = reg->feat_arc_proc; node->init = reg->init; node->fini = reg->fini; node->nb_edges = reg->nb_edges; @@ -137,6 +138,7 @@ node_clone(struct node *node, const char *name) /* Clone the source node */ reg->flags = node->flags; reg->process = node->process; + reg->feat_arc_proc = node->feat_arc_proc; reg->init = node->init; reg->fini = node->fini; reg->nb_edges = node->nb_edges; diff --git a/lib/graph/rte_graph.h b/lib/graph/rte_graph.h index ecfec2068a..1a3bd7e1ba 100644 --- a/lib/graph/rte_graph.h +++ b/lib/graph/rte_graph.h @@ -172,6 +172,8 @@ struct rte_graph_param { uint32_t mp_capacity; /**< Capacity of memory pool for dispatch model. */ } dispatch; }; + + bool feature_arc_enable; /**< Enable Graph feature arc. */ }; /** @@ -470,6 +472,7 @@ struct rte_node_register { uint64_t flags; /**< Node configuration flag. */ #define RTE_NODE_SOURCE_F (1ULL << 0) /**< Node type is source. */ rte_node_process_t process; /**< Node process function. */ + rte_node_process_t feat_arc_proc; /**< Node feature-arch process function. */ rte_node_init_t init; /**< Node init function. */ rte_node_fini_t fini; /**< Node fini function. */ rte_node_t id; /**< Node Identifier. */ -- 2.43.0 ^ permalink raw reply [flat|nested] 46+ messages in thread
* [PATCH v3 3/5] graph: add IPv4 output feature arc 2024-10-09 13:29 ` [PATCH v3 0/5] add feature arc in rte_graph Nitin Saxena 2024-10-09 13:29 ` [PATCH v3 1/5] graph: add feature arc support Nitin Saxena 2024-10-09 13:29 ` [PATCH v3 2/5] graph: add feature arc option in graph create Nitin Saxena @ 2024-10-09 13:30 ` Nitin Saxena 2024-10-09 13:30 ` [PATCH v3 4/5] test/graph_feature_arc: add functional tests Nitin Saxena ` (4 subsequent siblings) 7 siblings, 0 replies; 46+ messages in thread From: Nitin Saxena @ 2024-10-09 13:30 UTC (permalink / raw) To: Jerin Jacob, Kiran Kumar K, Nithin Dabilpuram, Zhirun Yan, Robin Jarry, Christophe Fontaine Cc: dev, Nitin Saxena add ipv4-output feature arc in ipv4-rewrite node to allow custom/standard nodes(like outbound IPsec policy node) in outgoing forwarding path Signed-off-by: Nitin Saxena <nsaxena@marvell.com> --- lib/node/ip4_rewrite.c | 476 +++++++++++++++++++++++++++++------- lib/node/ip4_rewrite_priv.h | 15 +- lib/node/node_private.h | 20 +- lib/node/rte_node_ip4_api.h | 3 + 4 files changed, 417 insertions(+), 97 deletions(-) diff --git a/lib/node/ip4_rewrite.c b/lib/node/ip4_rewrite.c index 34a920df5e..5a160335f2 100644 --- a/lib/node/ip4_rewrite.c +++ b/lib/node/ip4_rewrite.c @@ -15,39 +15,156 @@ #include "ip4_rewrite_priv.h" #include "node_private.h" +#define ALL_PKT_MASK 0xf + struct ip4_rewrite_node_ctx { + rte_graph_feature_arc_t output_feature_arc; /* Dynamic offset to mbuf priv1 */ int mbuf_priv1_off; /* Cached next index */ uint16_t next_index; + uint16_t last_tx; }; +typedef struct rewrite_priv_vars { + union { + struct { + rte_xmm_t xmm1; + }; + struct __rte_packed { + uint16_t next0; + uint16_t next1; + uint16_t next2; + uint16_t next3; + uint16_t last_tx_interface; + uint16_t last_if_feature; + uint16_t actual_feat_mask; + uint16_t speculative_feat_mask; + }; + }; +} rewrite_priv_vars_t; + static struct ip4_rewrite_node_main *ip4_rewrite_nm; #define IP4_REWRITE_NODE_LAST_NEXT(ctx) \ (((struct ip4_rewrite_node_ctx *)ctx)->next_index) +#define IP4_REWRITE_NODE_LAST_TX(ctx) \ + (((struct ip4_rewrite_node_ctx *)ctx)->last_tx) + #define IP4_REWRITE_NODE_PRIV1_OFF(ctx) \ (((struct ip4_rewrite_node_ctx *)ctx)->mbuf_priv1_off) -static uint16_t -ip4_rewrite_node_process(struct rte_graph *graph, struct rte_node *node, - void **objs, uint16_t nb_objs) +#define IP4_REWRITE_NODE_OUTPUT_FEATURE_ARC(ctx) \ + (((struct ip4_rewrite_node_ctx *)ctx)->output_feature_arc) + +static __rte_always_inline void +prefetch_mbuf_and_dynfield(struct rte_mbuf *mbuf) { + /* prefetch first cache line required for accessing buf_addr */ + rte_prefetch0((void *)mbuf); +} + +static __rte_always_inline void +check_output_feature_x4(struct rte_graph_feature_arc *arc, + const rte_graph_feature_rt_list_t flist, + rewrite_priv_vars_t *pvar, struct node_mbuf_priv1 *priv0, + struct node_mbuf_priv1 *priv1, struct node_mbuf_priv1 *priv2, + struct node_mbuf_priv1 *priv3) +{ + uint32_t mask = 0; + uint16_t xor = 0; + + /* + * interface edge's start from 1 and not from 0 as "pkt_drop" + * is next node at 0th index + */ + priv0->if_index = pvar->next0 - 1; + priv1->if_index = pvar->next1 - 1; + priv2->if_index = pvar->next2 - 1; + priv3->if_index = pvar->next3 - 1; + + /* Find out if all packets are sent to last_tx_interface */ + xor = pvar->last_tx_interface ^ priv0->if_index; + xor += priv0->if_index ^ priv1->if_index; + xor += priv1->if_index ^ priv2->if_index; + xor += priv2->if_index ^ priv3->if_index; + + if (likely(!xor)) { + /* copy last interface feature and feature mask */ + priv0->current_feature = priv1->current_feature = + priv2->current_feature = priv3->current_feature = + pvar->last_if_feature; + pvar->actual_feat_mask = pvar->speculative_feat_mask; + } else { + /* create a mask for index which does not have feature + * Also override next edge and if feature enabled, get feature + */ + mask = rte_graph_feature_arc_feature_set(arc, flist, priv0->if_index, + &priv0->current_feature, + &pvar->next0); + + mask |= ((rte_graph_feature_arc_feature_set(arc, flist, priv1->if_index, + &priv1->current_feature, + &pvar->next1)) << 1); + + mask |= ((rte_graph_feature_arc_feature_set(arc, flist, priv2->if_index, + &priv2->current_feature, + &pvar->next2)) << 2); + + mask |= ((rte_graph_feature_arc_feature_set(arc, flist, priv3->if_index, + &priv3->current_feature, + &pvar->next3)) << 3); + + /* + * add last tx and last feature regardless even if feature is + * valid or not + */ + pvar->last_tx_interface = priv3->if_index; + pvar->last_if_feature = priv3->current_feature; + /* Set 0xf if invalid feature to last packet, else 0 */ + pvar->speculative_feat_mask = (priv3->current_feature == + RTE_GRAPH_FEATURE_INVALID) ? ALL_PKT_MASK : 0x0; + pvar->actual_feat_mask = mask; + } +} + +static __rte_always_inline uint16_t +__ip4_rewrite_node_process(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs, + const int dyn, const int check_enabled_features, + struct rte_graph_feature_arc *out_feature_arc, + const rte_graph_feature_rt_list_t flist) +{ + struct node_mbuf_priv1 *priv0 = NULL, *priv1 = NULL, *priv2 = NULL, *priv3 = NULL; struct rte_mbuf *mbuf0, *mbuf1, *mbuf2, *mbuf3, **pkts; struct ip4_rewrite_nh_header *nh = ip4_rewrite_nm->nh; - const int dyn = IP4_REWRITE_NODE_PRIV1_OFF(node->ctx); - uint16_t next0, next1, next2, next3, next_index; - struct rte_ipv4_hdr *ip0, *ip1, *ip2, *ip3; uint16_t n_left_from, held = 0, last_spec = 0; + struct rte_ipv4_hdr *ip0, *ip1, *ip2, *ip3; + rewrite_priv_vars_t pvar; + int64_t fd0, fd1, fd2, fd3; + rte_edge_t fix_spec = 0; void *d0, *d1, *d2, *d3; void **to_next, **from; + uint16_t next_index; rte_xmm_t priv01; rte_xmm_t priv23; int i; - /* Speculative next as last next */ + RTE_SET_USED(fd0); + RTE_SET_USED(fd1); + RTE_SET_USED(fd2); + RTE_SET_USED(fd3); + + /* Initialize speculative variables.*/ + + /* Last interface */ + pvar.last_tx_interface = IP4_REWRITE_NODE_LAST_TX(node->ctx); + /*last next from node ctx*/ next_index = IP4_REWRITE_NODE_LAST_NEXT(node->ctx); + pvar.speculative_feat_mask = ALL_PKT_MASK; + pvar.actual_feat_mask = 0; + rte_prefetch0(nh); pkts = (struct rte_mbuf **)objs; @@ -55,20 +172,47 @@ ip4_rewrite_node_process(struct rte_graph *graph, struct rte_node *node, n_left_from = nb_objs; for (i = 0; i < 4 && i < n_left_from; i++) - rte_prefetch0(pkts[i]); + prefetch_mbuf_and_dynfield(pkts[i]); /* Get stream for the speculated next node */ to_next = rte_node_next_stream_get(graph, node, next_index, nb_objs); + + /* prefetch speculative feature and corresponding data */ + if (check_enabled_features) { + /* + * Get first feature enabled, if any, on last_tx_interface + */ + if (unlikely(rte_graph_feature_arc_first_feature_get(out_feature_arc, + flist, + pvar.last_tx_interface, + (rte_graph_feature_t *) + &pvar.last_if_feature))) { + /* prefetch feature cache line */ + rte_graph_feature_arc_feature_prefetch(out_feature_arc, flist, + pvar.last_if_feature); + + /* prefetch feature data cache line */ + rte_graph_feature_arc_data_prefetch(out_feature_arc, flist, + pvar.last_if_feature, + pvar.last_tx_interface); + /* + * Set speculativa_feat mask to indicate, all 4 packets + * going to feature path + */ + pvar.speculative_feat_mask = 0; + } + } + /* Update Ethernet header of pkts */ while (n_left_from >= 4) { if (likely(n_left_from > 7)) { /* Prefetch only next-mbuf struct and priv area. * Data need not be prefetched as we only write. */ - rte_prefetch0(pkts[4]); - rte_prefetch0(pkts[5]); - rte_prefetch0(pkts[6]); - rte_prefetch0(pkts[7]); + prefetch_mbuf_and_dynfield(pkts[4]); + prefetch_mbuf_and_dynfield(pkts[5]); + prefetch_mbuf_and_dynfield(pkts[6]); + prefetch_mbuf_and_dynfield(pkts[7]); } mbuf0 = pkts[0]; @@ -78,66 +222,138 @@ ip4_rewrite_node_process(struct rte_graph *graph, struct rte_node *node, pkts += 4; n_left_from -= 4; + + /* Copy mbuf private data into private variables */ priv01.u64[0] = node_mbuf_priv1(mbuf0, dyn)->u; priv01.u64[1] = node_mbuf_priv1(mbuf1, dyn)->u; priv23.u64[0] = node_mbuf_priv1(mbuf2, dyn)->u; priv23.u64[1] = node_mbuf_priv1(mbuf3, dyn)->u; - /* Increment checksum by one. */ - priv01.u32[1] += rte_cpu_to_be_16(0x0100); - priv01.u32[3] += rte_cpu_to_be_16(0x0100); - priv23.u32[1] += rte_cpu_to_be_16(0x0100); - priv23.u32[3] += rte_cpu_to_be_16(0x0100); - - /* Update ttl,cksum rewrite ethernet hdr on mbuf0 */ - d0 = rte_pktmbuf_mtod(mbuf0, void *); - rte_memcpy(d0, nh[priv01.u16[0]].rewrite_data, - nh[priv01.u16[0]].rewrite_len); - - next0 = nh[priv01.u16[0]].tx_node; - ip0 = (struct rte_ipv4_hdr *)((uint8_t *)d0 + - sizeof(struct rte_ether_hdr)); - ip0->time_to_live = priv01.u16[1] - 1; - ip0->hdr_checksum = priv01.u16[2] + priv01.u16[3]; - - /* Update ttl,cksum rewrite ethernet hdr on mbuf1 */ - d1 = rte_pktmbuf_mtod(mbuf1, void *); - rte_memcpy(d1, nh[priv01.u16[4]].rewrite_data, - nh[priv01.u16[4]].rewrite_len); - - next1 = nh[priv01.u16[4]].tx_node; - ip1 = (struct rte_ipv4_hdr *)((uint8_t *)d1 + - sizeof(struct rte_ether_hdr)); - ip1->time_to_live = priv01.u16[5] - 1; - ip1->hdr_checksum = priv01.u16[6] + priv01.u16[7]; - - /* Update ttl,cksum rewrite ethernet hdr on mbuf2 */ - d2 = rte_pktmbuf_mtod(mbuf2, void *); - rte_memcpy(d2, nh[priv23.u16[0]].rewrite_data, - nh[priv23.u16[0]].rewrite_len); - next2 = nh[priv23.u16[0]].tx_node; - ip2 = (struct rte_ipv4_hdr *)((uint8_t *)d2 + - sizeof(struct rte_ether_hdr)); - ip2->time_to_live = priv23.u16[1] - 1; - ip2->hdr_checksum = priv23.u16[2] + priv23.u16[3]; - - /* Update ttl,cksum rewrite ethernet hdr on mbuf3 */ - d3 = rte_pktmbuf_mtod(mbuf3, void *); - rte_memcpy(d3, nh[priv23.u16[4]].rewrite_data, - nh[priv23.u16[4]].rewrite_len); - - next3 = nh[priv23.u16[4]].tx_node; - ip3 = (struct rte_ipv4_hdr *)((uint8_t *)d3 + - sizeof(struct rte_ether_hdr)); - ip3->time_to_live = priv23.u16[5] - 1; - ip3->hdr_checksum = priv23.u16[6] + priv23.u16[7]; + /* Copy next edge from next hop */ + pvar.next0 = nh[priv01.u16[0]].tx_node; + pvar.next1 = nh[priv01.u16[4]].tx_node; + pvar.next2 = nh[priv23.u16[0]].tx_node; + pvar.next3 = nh[priv23.u16[4]].tx_node; + + if (check_enabled_features) { + priv0 = node_mbuf_priv1(mbuf0, dyn); + priv1 = node_mbuf_priv1(mbuf1, dyn); + priv2 = node_mbuf_priv1(mbuf2, dyn); + priv3 = node_mbuf_priv1(mbuf3, dyn); + + /* If feature is enabled, override next edge for each mbuf + * and set node_mbuf_priv data appropriately + */ + check_output_feature_x4(out_feature_arc, flist, + &pvar, priv0, priv1, priv2, priv3); + + /* check_output_feature_x4() returns bit mask which indicates + * which packet is not following feature path, hence normal processing + * has to happen on them + */ + if (unlikely(pvar.actual_feat_mask)) { + if (pvar.actual_feat_mask & 0x1) { + priv01.u32[1] += rte_cpu_to_be_16(0x0100); + /* Update ttl,cksum rewrite ethernet hdr on mbuf0 */ + d0 = rte_pktmbuf_mtod(mbuf0, void *); + rte_memcpy(d0, nh[priv01.u16[0]].rewrite_data, + nh[priv01.u16[0]].rewrite_len); + ip0 = (struct rte_ipv4_hdr *)((uint8_t *)d0 + + sizeof(struct rte_ether_hdr)); + ip0->time_to_live = priv01.u16[1] - 1; + ip0->hdr_checksum = priv01.u16[2] + priv01.u16[3]; + } + if (pvar.actual_feat_mask & 0x2) { + priv01.u32[3] += rte_cpu_to_be_16(0x0100); + /* Update ttl,cksum rewrite ethernet hdr on mbuf1 */ + d1 = rte_pktmbuf_mtod(mbuf1, void *); + rte_memcpy(d1, nh[priv01.u16[4]].rewrite_data, + nh[priv01.u16[4]].rewrite_len); + + ip1 = (struct rte_ipv4_hdr *)((uint8_t *)d1 + + sizeof(struct rte_ether_hdr)); + ip1->time_to_live = priv01.u16[5] - 1; + ip1->hdr_checksum = priv01.u16[6] + priv01.u16[7]; + } + if (pvar.actual_feat_mask & 0x4) { + priv23.u32[1] += rte_cpu_to_be_16(0x0100); + /* Update ttl,cksum rewrite ethernet hdr on mbuf2 */ + d2 = rte_pktmbuf_mtod(mbuf2, void *); + rte_memcpy(d2, nh[priv23.u16[0]].rewrite_data, + nh[priv23.u16[0]].rewrite_len); + ip2 = (struct rte_ipv4_hdr *)((uint8_t *)d2 + + sizeof(struct rte_ether_hdr)); + ip2->time_to_live = priv23.u16[1] - 1; + ip2->hdr_checksum = priv23.u16[2] + priv23.u16[3]; + } + if (pvar.actual_feat_mask & 0x8) { + priv23.u32[3] += rte_cpu_to_be_16(0x0100); + /* Update ttl,cksum rewrite ethernet hdr on mbuf3 */ + d3 = rte_pktmbuf_mtod(mbuf3, void *); + rte_memcpy(d3, nh[priv23.u16[4]].rewrite_data, + nh[priv23.u16[4]].rewrite_len); + ip3 = (struct rte_ipv4_hdr *)((uint8_t *)d3 + + sizeof(struct rte_ether_hdr)); + ip3->time_to_live = priv23.u16[5] - 1; + ip3->hdr_checksum = priv23.u16[6] + priv23.u16[7]; + } + } + } else { + /* Case when no feature is enabled */ + + /* Increment checksum by one. */ + priv01.u32[1] += rte_cpu_to_be_16(0x0100); + priv01.u32[3] += rte_cpu_to_be_16(0x0100); + priv23.u32[1] += rte_cpu_to_be_16(0x0100); + priv23.u32[3] += rte_cpu_to_be_16(0x0100); + + /* Update ttl,cksum rewrite ethernet hdr on mbuf0 */ + d0 = rte_pktmbuf_mtod(mbuf0, void *); + rte_memcpy(d0, nh[priv01.u16[0]].rewrite_data, + nh[priv01.u16[0]].rewrite_len); + + ip0 = (struct rte_ipv4_hdr *)((uint8_t *)d0 + + sizeof(struct rte_ether_hdr)); + ip0->time_to_live = priv01.u16[1] - 1; + ip0->hdr_checksum = priv01.u16[2] + priv01.u16[3]; + + /* Update ttl,cksum rewrite ethernet hdr on mbuf1 */ + d1 = rte_pktmbuf_mtod(mbuf1, void *); + rte_memcpy(d1, nh[priv01.u16[4]].rewrite_data, + nh[priv01.u16[4]].rewrite_len); + + ip1 = (struct rte_ipv4_hdr *)((uint8_t *)d1 + + sizeof(struct rte_ether_hdr)); + ip1->time_to_live = priv01.u16[5] - 1; + ip1->hdr_checksum = priv01.u16[6] + priv01.u16[7]; + + /* Update ttl,cksum rewrite ethernet hdr on mbuf2 */ + d2 = rte_pktmbuf_mtod(mbuf2, void *); + rte_memcpy(d2, nh[priv23.u16[0]].rewrite_data, + nh[priv23.u16[0]].rewrite_len); + ip2 = (struct rte_ipv4_hdr *)((uint8_t *)d2 + + sizeof(struct rte_ether_hdr)); + ip2->time_to_live = priv23.u16[1] - 1; + ip2->hdr_checksum = priv23.u16[2] + priv23.u16[3]; + + /* Update ttl,cksum rewrite ethernet hdr on mbuf3 */ + d3 = rte_pktmbuf_mtod(mbuf3, void *); + rte_memcpy(d3, nh[priv23.u16[4]].rewrite_data, + nh[priv23.u16[4]].rewrite_len); + + ip3 = (struct rte_ipv4_hdr *)((uint8_t *)d3 + + sizeof(struct rte_ether_hdr)); + ip3->time_to_live = priv23.u16[5] - 1; + ip3->hdr_checksum = priv23.u16[6] + priv23.u16[7]; + } /* Enqueue four to next node */ - rte_edge_t fix_spec = - ((next_index == next0) && (next0 == next1) && - (next1 == next2) && (next2 == next3)); + fix_spec = next_index ^ pvar.next0; + fix_spec += next_index ^ pvar.next1; + fix_spec += next_index ^ pvar.next2; + fix_spec += next_index ^ pvar.next3; - if (unlikely(fix_spec == 0)) { + if (unlikely(fix_spec != 0)) { /* Copy things successfully speculated till now */ rte_memcpy(to_next, from, last_spec * sizeof(from[0])); from += last_spec; @@ -146,56 +362,56 @@ ip4_rewrite_node_process(struct rte_graph *graph, struct rte_node *node, last_spec = 0; /* next0 */ - if (next_index == next0) { + if (next_index == pvar.next0) { to_next[0] = from[0]; to_next++; held++; } else { - rte_node_enqueue_x1(graph, node, next0, + rte_node_enqueue_x1(graph, node, pvar.next0, from[0]); } /* next1 */ - if (next_index == next1) { + if (next_index == pvar.next1) { to_next[0] = from[1]; to_next++; held++; } else { - rte_node_enqueue_x1(graph, node, next1, + rte_node_enqueue_x1(graph, node, pvar.next1, from[1]); } /* next2 */ - if (next_index == next2) { + if (next_index == pvar.next2) { to_next[0] = from[2]; to_next++; held++; } else { - rte_node_enqueue_x1(graph, node, next2, + rte_node_enqueue_x1(graph, node, pvar.next2, from[2]); } /* next3 */ - if (next_index == next3) { + if (next_index == pvar.next3) { to_next[0] = from[3]; to_next++; held++; } else { - rte_node_enqueue_x1(graph, node, next3, + rte_node_enqueue_x1(graph, node, pvar.next3, from[3]); } from += 4; /* Change speculation if last two are same */ - if ((next_index != next3) && (next2 == next3)) { + if ((next_index != pvar.next3) && (pvar.next2 == pvar.next3)) { /* Put the current speculated node */ rte_node_next_stream_put(graph, node, next_index, held); held = 0; /* Get next speculated stream */ - next_index = next3; + next_index = pvar.next3; to_next = rte_node_next_stream_get( graph, node, next_index, nb_objs); } @@ -212,20 +428,41 @@ ip4_rewrite_node_process(struct rte_graph *graph, struct rte_node *node, pkts += 1; n_left_from -= 1; - d0 = rte_pktmbuf_mtod(mbuf0, void *); - rte_memcpy(d0, nh[node_mbuf_priv1(mbuf0, dyn)->nh].rewrite_data, - nh[node_mbuf_priv1(mbuf0, dyn)->nh].rewrite_len); - - next0 = nh[node_mbuf_priv1(mbuf0, dyn)->nh].tx_node; - ip0 = (struct rte_ipv4_hdr *)((uint8_t *)d0 + - sizeof(struct rte_ether_hdr)); - chksum = node_mbuf_priv1(mbuf0, dyn)->cksum + - rte_cpu_to_be_16(0x0100); - chksum += chksum >= 0xffff; - ip0->hdr_checksum = chksum; - ip0->time_to_live = node_mbuf_priv1(mbuf0, dyn)->ttl - 1; - - if (unlikely(next_index ^ next0)) { + pvar.next0 = nh[node_mbuf_priv1(mbuf0, dyn)->nh].tx_node; + if (check_enabled_features) { + priv0 = node_mbuf_priv1(mbuf0, dyn); + if (pvar.next0 != (pvar.last_tx_interface + 1)) { + priv0->if_index = pvar.next0 - 1; + rte_graph_feature_arc_feature_set(out_feature_arc, flist, + priv0->if_index, + &priv0->current_feature, + &pvar.next0); + pvar.last_tx_interface = priv0->if_index; + pvar.last_if_feature = priv0->current_feature; + } else { + /* current mbuf index is same as last_tx_interface */ + priv0->if_index = pvar.last_tx_interface; + priv0->current_feature = pvar.last_if_feature; + } + } + /* Do the needful if either feature arc is disabled OR + * Invalid feature is present + */ + if (!check_enabled_features || + (priv0->current_feature == RTE_GRAPH_FEATURE_INVALID)) { + d0 = rte_pktmbuf_mtod(mbuf0, void *); + rte_memcpy(d0, nh[node_mbuf_priv1(mbuf0, dyn)->nh].rewrite_data, + nh[node_mbuf_priv1(mbuf0, dyn)->nh].rewrite_len); + + ip0 = (struct rte_ipv4_hdr *)((uint8_t *)d0 + + sizeof(struct rte_ether_hdr)); + chksum = node_mbuf_priv1(mbuf0, dyn)->cksum + + rte_cpu_to_be_16(0x0100); + chksum += chksum >= 0xffff; + ip0->hdr_checksum = chksum; + ip0->time_to_live = node_mbuf_priv1(mbuf0, dyn)->ttl - 1; + } + if (unlikely(next_index ^ pvar.next0)) { /* Copy things successfully speculated till now */ rte_memcpy(to_next, from, last_spec * sizeof(from[0])); from += last_spec; @@ -233,13 +470,15 @@ ip4_rewrite_node_process(struct rte_graph *graph, struct rte_node *node, held += last_spec; last_spec = 0; - rte_node_enqueue_x1(graph, node, next0, from[0]); + rte_node_enqueue_x1(graph, node, pvar.next0, from[0]); from += 1; } else { last_spec += 1; } } + IP4_REWRITE_NODE_LAST_TX(node->ctx) = pvar.last_tx_interface; + /* !!! Home run !!! */ if (likely(last_spec == nb_objs)) { rte_node_next_stream_move(graph, node, next_index); @@ -255,22 +494,78 @@ ip4_rewrite_node_process(struct rte_graph *graph, struct rte_node *node, return nb_objs; } +static uint16_t +ip4_rewrite_feature_node_process(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + struct rte_graph_feature_arc *arc = + rte_graph_feature_arc_get(IP4_REWRITE_NODE_OUTPUT_FEATURE_ARC(node->ctx)); + const int dyn = IP4_REWRITE_NODE_PRIV1_OFF(node->ctx); + rte_graph_feature_rt_list_t flist; + + /* If any feature is enabled on this arc */ + if (unlikely(rte_graph_feature_arc_has_any_feature(arc, &flist))) { + if (flist) + return __ip4_rewrite_node_process(graph, node, objs, nb_objs, + dyn, + 1 /* check features */, arc, + (rte_graph_feature_rt_list_t)1); + else + return __ip4_rewrite_node_process(graph, node, objs, nb_objs, + dyn, + 1 /* check features */, arc, + (rte_graph_feature_rt_list_t)0); + } else { + return __ip4_rewrite_node_process(graph, node, objs, nb_objs, dyn, + 0/* don't check features*/, NULL, + 0/* don't care */); + } + return 0; +} + +static uint16_t +ip4_rewrite_node_process(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + const int dyn = IP4_REWRITE_NODE_PRIV1_OFF(node->ctx); + + return __ip4_rewrite_node_process(graph, node, objs, nb_objs, dyn, + 0/* don't check features*/, NULL, + 0/* don't care */); +} + static int ip4_rewrite_node_init(const struct rte_graph *graph, struct rte_node *node) { + rte_graph_feature_arc_t feature_arc = RTE_GRAPH_FEATURE_ARC_INITIALIZER; static bool init_once; RTE_SET_USED(graph); RTE_BUILD_BUG_ON(sizeof(struct ip4_rewrite_node_ctx) > RTE_NODE_CTX_SZ); + RTE_BUILD_BUG_ON(sizeof(struct ip4_rewrite_nh_header) != RTE_CACHE_LINE_MIN_SIZE); if (!init_once) { node_mbuf_priv1_dynfield_offset = rte_mbuf_dynfield_register( &node_mbuf_priv1_dynfield_desc); if (node_mbuf_priv1_dynfield_offset < 0) return -rte_errno; - init_once = true; + + /* Create ipv4-output feature arc, if not created + */ + if (rte_graph_feature_arc_lookup_by_name(RTE_IP4_OUTPUT_FEATURE_ARC_NAME, + NULL) < 0) { + if (rte_graph_feature_arc_create(RTE_IP4_OUTPUT_FEATURE_ARC_NAME, + RTE_GRAPH_FEATURE_MAX_PER_ARC, + RTE_MAX_ETHPORTS, + ip4_rewrite_node_get(), &feature_arc)) { + return -rte_errno; + } + init_once = true; + } } IP4_REWRITE_NODE_PRIV1_OFF(node->ctx) = node_mbuf_priv1_dynfield_offset; + IP4_REWRITE_NODE_OUTPUT_FEATURE_ARC(node->ctx) = feature_arc; + IP4_REWRITE_NODE_LAST_TX(node->ctx) = UINT16_MAX; node_dbg("ip4_rewrite", "Initialized ip4_rewrite node initialized"); @@ -329,6 +624,7 @@ rte_node_ip4_rewrite_add(uint16_t next_hop, uint8_t *rewrite_data, static struct rte_node_register ip4_rewrite_node = { .process = ip4_rewrite_node_process, + .feat_arc_proc = ip4_rewrite_feature_node_process, .name = "ip4_rewrite", /* Default edge i.e '0' is pkt drop */ .nb_edges = 1, diff --git a/lib/node/ip4_rewrite_priv.h b/lib/node/ip4_rewrite_priv.h index 5105ec1d29..52f39601bd 100644 --- a/lib/node/ip4_rewrite_priv.h +++ b/lib/node/ip4_rewrite_priv.h @@ -5,9 +5,11 @@ #define __INCLUDE_IP4_REWRITE_PRIV_H__ #include <rte_common.h> +#include <rte_graph_feature_arc.h> #define RTE_GRAPH_IP4_REWRITE_MAX_NH 64 -#define RTE_GRAPH_IP4_REWRITE_MAX_LEN 56 +#define RTE_GRAPH_IP4_REWRITE_MAX_LEN (sizeof(struct rte_ether_hdr) + \ + (2 * sizeof(struct rte_vlan_hdr))) /** * @internal @@ -15,11 +17,9 @@ * Ipv4 rewrite next hop header data structure. Used to store port specific * rewrite data. */ -struct ip4_rewrite_nh_header { - uint16_t rewrite_len; /**< Header rewrite length. */ +struct __rte_cache_aligned ip4_rewrite_nh_header { uint16_t tx_node; /**< Tx node next index identifier. */ - uint16_t enabled; /**< NH enable flag */ - uint16_t rsvd; + uint16_t rewrite_len; /**< Header rewrite length. */ union { struct { struct rte_ether_addr dst; @@ -30,8 +30,13 @@ struct ip4_rewrite_nh_header { uint8_t rewrite_data[RTE_GRAPH_IP4_REWRITE_MAX_LEN]; /**< Generic rewrite data */ }; + /* used in control path */ + uint8_t enabled; /**< NH enable flag */ }; +_Static_assert(sizeof(struct ip4_rewrite_nh_header) <= (size_t)RTE_CACHE_LINE_SIZE, + "ip4_rewrite_nh_header size must be less or equal to cache line"); + /** * @internal * diff --git a/lib/node/node_private.h b/lib/node/node_private.h index 1de7306792..25db04a9a6 100644 --- a/lib/node/node_private.h +++ b/lib/node/node_private.h @@ -12,6 +12,9 @@ #include <rte_mbuf.h> #include <rte_mbuf_dyn.h> +#include <rte_graph_worker_common.h> +#include <rte_graph_feature_arc_worker.h> + extern int rte_node_logtype; #define RTE_LOGTYPE_NODE rte_node_logtype @@ -29,15 +32,28 @@ extern int rte_node_logtype; */ struct node_mbuf_priv1 { union { - /* IP4/IP6 rewrite */ + /** + * IP4/IP6 rewrite + * only used to pass lookup data from + * ip4-lookup to ip4-rewrite + */ struct { uint16_t nh; uint16_t ttl; uint32_t cksum; }; - uint64_t u; }; + /** + * Feature arc data + */ + struct { + /** interface index */ + uint16_t if_index; + /** feature that current mbuf holds */ + rte_graph_feature_t current_feature; + uint8_t rsvd; + }; }; static const struct rte_mbuf_dynfield node_mbuf_priv1_dynfield_desc = { diff --git a/lib/node/rte_node_ip4_api.h b/lib/node/rte_node_ip4_api.h index 24f8ec843a..0de06f7fc7 100644 --- a/lib/node/rte_node_ip4_api.h +++ b/lib/node/rte_node_ip4_api.h @@ -23,6 +23,7 @@ extern "C" { #include <rte_compat.h> #include <rte_graph.h> +#include <rte_graph_feature_arc_worker.h> /** * IP4 lookup next nodes. @@ -67,6 +68,8 @@ struct rte_node_ip4_reassembly_cfg { /**< Node identifier to configure. */ }; +#define RTE_IP4_OUTPUT_FEATURE_ARC_NAME "ipv4-output" + /** * Add ipv4 route to lookup table. * -- 2.43.0 ^ permalink raw reply [flat|nested] 46+ messages in thread
* [PATCH v3 4/5] test/graph_feature_arc: add functional tests 2024-10-09 13:29 ` [PATCH v3 0/5] add feature arc in rte_graph Nitin Saxena ` (2 preceding siblings ...) 2024-10-09 13:30 ` [PATCH v3 3/5] graph: add IPv4 output feature arc Nitin Saxena @ 2024-10-09 13:30 ` Nitin Saxena 2024-10-09 13:30 ` [PATCH v3 5/5] docs: add programming guide for feature arc Nitin Saxena ` (3 subsequent siblings) 7 siblings, 0 replies; 46+ messages in thread From: Nitin Saxena @ 2024-10-09 13:30 UTC (permalink / raw) To: Jerin Jacob, Kiran Kumar K, Nithin Dabilpuram, Zhirun Yan, Robin Jarry, Christophe Fontaine Cc: dev, Nitin Saxena Added functional unit test case for verifying feature arc control plane and fast path APIs How to run: $ echo "graph_feature_arc_autotest" | ./bin/dpdk-test Signed-off-by: Nitin Saxena <nsaxena@marvell.com> --- app/test/meson.build | 1 + app/test/test_graph_feature_arc.c | 1410 +++++++++++++++++++++++++++++ 2 files changed, 1411 insertions(+) create mode 100644 app/test/test_graph_feature_arc.c diff --git a/app/test/meson.build b/app/test/meson.build index e29258e6ec..740fa1bfb4 100644 --- a/app/test/meson.build +++ b/app/test/meson.build @@ -90,6 +90,7 @@ source_file_deps = { 'test_func_reentrancy.c': ['hash', 'lpm'], 'test_graph.c': ['graph'], 'test_graph_perf.c': ['graph'], + 'test_graph_feature_arc.c': ['graph'], 'test_hash.c': ['net', 'hash'], 'test_hash_functions.c': ['hash'], 'test_hash_multiwriter.c': ['hash'], diff --git a/app/test/test_graph_feature_arc.c b/app/test/test_graph_feature_arc.c new file mode 100644 index 0000000000..8ea7a7d3eb --- /dev/null +++ b/app/test/test_graph_feature_arc.c @@ -0,0 +1,1410 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(C) 2024 Marvell International Ltd. + */ + +#include "test.h" + +#include <assert.h> +#include <inttypes.h> +#include <signal.h> +#include <stdalign.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> + +#include <rte_errno.h> + +#ifndef RTE_EXEC_ENV_WINDOWS +#include <rte_graph.h> +#include <rte_graph_worker.h> +#include <rte_mbuf.h> +#include <rte_mbuf_dyn.h> +#include <rte_random.h> +#include <rte_graph_feature_arc.h> +#include <rte_graph_feature_arc_worker.h> + +#define MBUFF_SIZE 512 +#define TEST_ARC1_NAME "arc1" +#define TEST_ARC2_NAME "arc2" +#define MAX_INDEXES 10 +#define MAX_FEATURES 5 + +#define SOURCE1 "test_node_arc_source1" +#define INPUT_STATIC "test_node_arc_input_static" +#define OUTPUT_STATIC "test_node_arc_output_static" +#define PKT_FREE_STATIC "test_node_arc_pkt_free_static" +#define ARC1_FEATURE1 "test_node_arc1_feature1" +#define ARC1_FEATURE2 "test_node_arc1_feature2" +#define ARC2_FEATURE1 "test_node_arc2_feature1" +#define ARC2_FEATURE2 "test_node_arc2_feature2" +#define ARC2_FEATURE3 "test_node_arc2_feature3" +#define DUMMY1_STATIC "test_node_arc_dummy1_static" +#define DUMMY2_STATIC "test_node_arc_dummy2_static" + +/* (Node index, Node Name, feature user data base */ +#define FOREACH_TEST_NODE_ARC { \ + R(0, SOURCE1, 64) \ + R(1, INPUT_STATIC, 128) \ + R(2, OUTPUT_STATIC, 256) \ + R(3, PKT_FREE_STATIC, 512) \ + R(4, ARC1_FEATURE1, 1024) \ + R(5, ARC1_FEATURE2, 2048) \ + R(6, ARC2_FEATURE1, 4096) \ + R(7, ARC2_FEATURE2, 8192) \ + R(8, ARC2_FEATURE3, 16384) \ + R(9, DUMMY1_STATIC, 32768) \ + R(10, DUMMY2_STATIC, 65536) \ + } + +/** + * ARC1: Feature arc on ingress interface + * ARC2: Feature arc on egress interface + * XX_static: Static nodes + * XX_featureX: Feature X on arc + * + * -----> ARC1_FEATURE1 + * | | | + * | | v + * | | ARC1_FEATURE2 + * | | | + * | v v + * SOURCE1 ->-----> INPUT_STATIC --> OUTPUT_STATIC -----> PKT_FREE_STATIC + * | | | ^ ^ ^ + * | | | | | | + * | | --> ARC2_FEATURE1 | | + * | | ^ ^ | | + * | | | | | | + * | ----------c-> ARC2_FEATURE2 | + * | | ^ | + * | | | | + * ----------> ARC2_FEATURE3 ------- + */ +const char *node_names_feature_arc[] = { + SOURCE1, INPUT_STATIC, OUTPUT_STATIC, PKT_FREE_STATIC, + ARC1_FEATURE1, ARC1_FEATURE2, ARC2_FEATURE1, ARC2_FEATURE2, ARC2_FEATURE3, + DUMMY1_STATIC, DUMMY2_STATIC +}; + +#define MAX_NODES RTE_DIM(node_names_feature_arc) + +/* Function declarations */ +static uint16_t +source1_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs); +static uint16_t +input_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs); +static uint16_t +input_fa_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs); +static uint16_t +output_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs); +static uint16_t +output_fa_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs); +static uint16_t +pkt_free_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs); +static uint16_t +pkt_free_fa_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs); +static uint16_t +dummy1_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs); +static uint16_t +dummy2_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs); +static uint16_t +arc1_feature1_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs); +static uint16_t +arc1_feature1_fa_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs); +static uint16_t +arc1_feature2_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs); +static uint16_t +arc1_feature2_fa_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs); +static uint16_t +arc2_feature1_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs); +static uint16_t +arc2_feature1_fa_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs); +static uint16_t +arc2_feature2_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs); +static uint16_t +arc2_feature2_fa_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs); +static uint16_t +arc2_feature3_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs); +static uint16_t +arc2_feature3_fa_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs); +static int +common_node_init(const struct rte_graph *graph, struct rte_node *node); + +typedef struct test_node_priv { + /* index from 0 - MAX_NODES -1 */ + uint8_t node_index; + + /* feature */ + rte_graph_feature_t feature; + + /* rte_graph node id */ + uint32_t node_id; + + rte_graph_feature_arc_t arc; +} test_node_priv_t; + +typedef struct { + rte_graph_feature_t feature; + uint16_t egress_interface; + uint16_t ingress_interface; +} graph_dynfield_t; + +static int graph_dynfield_offset = -1; +static rte_graph_feature_arc_t arcs[RTE_GRAPH_FEATURE_ARC_MAX + 128]; +static struct rte_mbuf mbuf[MAX_NODES + 1][MBUFF_SIZE]; +static void *mbuf_p[MAX_NODES + 1][MBUFF_SIZE]; +static rte_graph_t graph_id = RTE_GRAPH_ID_INVALID; + +const char *node_patterns_feature_arc[] = { + "test_node_arc*" +}; + +static int32_t +compute_unique_user_data(const char *parent, const char *child, uint32_t interface_index) +{ + uint32_t user_data = interface_index; + + RTE_SET_USED(parent); +#define R(idx, node, node_cookie) { \ + if (!strcmp(child, node)) { \ + user_data += node_cookie; \ + } \ + } + + FOREACH_TEST_NODE_ARC +#undef R + + return user_data; +} + +static int +get_edge(struct rte_node_register *parent_node, + struct rte_node_register *child_node, rte_edge_t *_edge) +{ + char **next_edges = NULL; + uint32_t count, i; + + count = rte_node_edge_get(parent_node->id, NULL); + + if (!count) + return -1; + + next_edges = malloc(count); + + if (!next_edges) + return -1; + + count = rte_node_edge_get(parent_node->id, next_edges); + for (i = 0; i < count; i++) { + if (strstr(child_node->name, next_edges[i])) { + if (_edge) + *_edge = (rte_edge_t)i; + + free(next_edges); + return 0; + } + } + free(next_edges); + + return -1; +} + +int +common_node_init(const struct rte_graph *graph, struct rte_node *node) +{ + test_node_priv_t *priv = (test_node_priv_t *)node->ctx; + + RTE_SET_USED(graph); + + priv->node_id = node->id; + priv->feature = RTE_GRAPH_FEATURE_INVALID; + priv->arc = RTE_GRAPH_FEATURE_ARC_INITIALIZER; + +#define R(idx, _name, user_data) { \ + if (!strcmp(node->name, _name)) { \ + priv->node_index = idx; \ + } \ + } + FOREACH_TEST_NODE_ARC +#undef R + + return 0; +} + +uint16_t +source1_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + RTE_SET_USED(graph); + RTE_SET_USED(node); + RTE_SET_USED(objs); + RTE_SET_USED(nb_objs); + return 0; +} + +static struct rte_node_register source1 = { + .name = SOURCE1, + .process = source1_fn, + .flags = RTE_NODE_SOURCE_F, + .nb_edges = 3, + .init = common_node_init, + .next_nodes = {INPUT_STATIC, DUMMY1_STATIC, DUMMY2_STATIC}, +}; +RTE_NODE_REGISTER(source1); + +uint16_t +input_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + RTE_SET_USED(graph); + RTE_SET_USED(node); + RTE_SET_USED(objs); + RTE_SET_USED(nb_objs); + return 0; +} + +uint16_t +input_fa_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + RTE_SET_USED(graph); + RTE_SET_USED(node); + RTE_SET_USED(objs); + RTE_SET_USED(nb_objs); + return 0; +} + +static struct rte_node_register input = { + .name = INPUT_STATIC, + .process = input_fn, + .feat_arc_proc = input_fa_fn, + .nb_edges = 2, + .init = common_node_init, + .next_nodes = {OUTPUT_STATIC, DUMMY1_STATIC}, +}; +RTE_NODE_REGISTER(input); + +uint16_t +output_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + RTE_SET_USED(graph); + RTE_SET_USED(node); + RTE_SET_USED(objs); + RTE_SET_USED(nb_objs); + return 0; +} + +uint16_t +output_fa_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + RTE_SET_USED(graph); + RTE_SET_USED(node); + RTE_SET_USED(objs); + RTE_SET_USED(nb_objs); + return 0; +} + +static struct rte_node_register output = { + .name = OUTPUT_STATIC, + .process = output_fn, + .feat_arc_proc = output_fa_fn, + .nb_edges = 3, + .init = common_node_init, + .next_nodes = {DUMMY1_STATIC, PKT_FREE_STATIC, DUMMY2_STATIC}, +}; +RTE_NODE_REGISTER(output); + +uint16_t +pkt_free_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + RTE_SET_USED(graph); + RTE_SET_USED(node); + RTE_SET_USED(objs); + RTE_SET_USED(nb_objs); + return 0; +} + +uint16_t +pkt_free_fa_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + RTE_SET_USED(graph); + RTE_SET_USED(node); + RTE_SET_USED(objs); + RTE_SET_USED(nb_objs); + return 0; +} + +static struct rte_node_register pkt_free = { + .name = PKT_FREE_STATIC, + .process = pkt_free_fn, + .feat_arc_proc = pkt_free_fa_fn, + .nb_edges = 1, + .init = common_node_init, + .next_nodes = {DUMMY1_STATIC}, +}; +RTE_NODE_REGISTER(pkt_free); + +uint16_t +dummy1_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + RTE_SET_USED(graph); + RTE_SET_USED(node); + RTE_SET_USED(objs); + RTE_SET_USED(nb_objs); + return 0; +} + +static struct rte_node_register dummy1 = { + .name = DUMMY1_STATIC, + .process = dummy1_fn, + .nb_edges = 0, + .init = common_node_init, +}; +RTE_NODE_REGISTER(dummy1); + +uint16_t +dummy2_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + RTE_SET_USED(graph); + RTE_SET_USED(node); + RTE_SET_USED(objs); + RTE_SET_USED(nb_objs); + return 0; +} + +static struct rte_node_register dummy2 = { + .name = DUMMY2_STATIC, + .process = dummy2_fn, + .nb_edges = 5, + .init = common_node_init, + .next_nodes = { ARC1_FEATURE1, ARC1_FEATURE2, ARC2_FEATURE1, + ARC2_FEATURE2, ARC2_FEATURE3}, +}; +RTE_NODE_REGISTER(dummy2); + +uint16_t +arc1_feature1_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + RTE_SET_USED(graph); + RTE_SET_USED(node); + RTE_SET_USED(objs); + RTE_SET_USED(nb_objs); + + return 0; +} + +uint16_t +arc1_feature1_fa_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + RTE_SET_USED(graph); + RTE_SET_USED(node); + RTE_SET_USED(objs); + RTE_SET_USED(nb_objs); + + return 0; +} + +static struct rte_node_register arc1_feature1 = { + .name = ARC1_FEATURE1, + .process = arc1_feature1_fn, + .feat_arc_proc = arc1_feature1_fa_fn, + .nb_edges = 0, + .init = common_node_init, +}; +RTE_NODE_REGISTER(arc1_feature1); + +uint16_t +arc1_feature2_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + RTE_SET_USED(graph); + RTE_SET_USED(node); + RTE_SET_USED(objs); + RTE_SET_USED(nb_objs); + + return 0; +} + +uint16_t +arc1_feature2_fa_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + RTE_SET_USED(graph); + RTE_SET_USED(node); + RTE_SET_USED(objs); + RTE_SET_USED(nb_objs); + + return 0; +} + +static struct rte_node_register arc1_feature2 = { + .name = ARC1_FEATURE2, + .process = arc1_feature2_fn, + .feat_arc_proc = arc1_feature2_fa_fn, + .nb_edges = 0, + .init = common_node_init, +}; +RTE_NODE_REGISTER(arc1_feature2); + +uint16_t +arc2_feature1_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + RTE_SET_USED(graph); + RTE_SET_USED(node); + RTE_SET_USED(objs); + RTE_SET_USED(nb_objs); + + return 0; +} + +uint16_t +arc2_feature1_fa_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + RTE_SET_USED(graph); + RTE_SET_USED(node); + RTE_SET_USED(objs); + RTE_SET_USED(nb_objs); + + return 0; +} + +static struct rte_node_register arc2_feature1 = { + .name = ARC2_FEATURE1, + .process = arc2_feature1_fn, + .feat_arc_proc = arc2_feature1_fa_fn, + .nb_edges = 0, + .init = common_node_init, +}; +RTE_NODE_REGISTER(arc2_feature1); + +uint16_t +arc2_feature2_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + RTE_SET_USED(graph); + RTE_SET_USED(node); + RTE_SET_USED(objs); + RTE_SET_USED(nb_objs); + + return 0; +} + +uint16_t +arc2_feature2_fa_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + RTE_SET_USED(graph); + RTE_SET_USED(node); + RTE_SET_USED(objs); + RTE_SET_USED(nb_objs); + + return 0; +} + +static struct rte_node_register arc2_feature2 = { + .name = ARC2_FEATURE2, + .process = arc2_feature2_fn, + .feat_arc_proc = arc2_feature2_fa_fn, + .nb_edges = 0, + .init = common_node_init, +}; +RTE_NODE_REGISTER(arc2_feature2); + +uint16_t +arc2_feature3_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + RTE_SET_USED(graph); + RTE_SET_USED(node); + RTE_SET_USED(objs); + RTE_SET_USED(nb_objs); + + return 0; +} + +uint16_t +arc2_feature3_fa_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + RTE_SET_USED(graph); + RTE_SET_USED(node); + RTE_SET_USED(objs); + RTE_SET_USED(nb_objs); + + return 0; +} + +static struct rte_node_register arc2_feature3 = { + .name = ARC2_FEATURE3, + .process = arc2_feature3_fn, + .feat_arc_proc = arc2_feature3_fa_fn, + .nb_edges = 0, + .init = common_node_init, +}; +RTE_NODE_REGISTER(arc2_feature3); + +static int +create_graph(void) +{ + struct rte_graph_param gconf = { + .socket_id = SOCKET_ID_ANY, + .nb_node_patterns = 1, + .node_patterns = node_patterns_feature_arc, + }; + + graph_id = rte_graph_create("worker0", &gconf); + if (graph_id == RTE_GRAPH_ID_INVALID) { + printf("Graph creation failed with error = %d\n", rte_errno); + return TEST_FAILED; + } + + return TEST_SUCCESS; +} + +static int +__test_create_feature_arc(rte_graph_feature_arc_t *arcs, int max_arcs) +{ + rte_graph_feature_arc_t arc; + const char *sample_arc_name = "sample_arc"; + char arc_name[256]; + int n_arcs; + + /* Create max number of feature arcs first */ + for (n_arcs = 0; n_arcs < max_arcs; n_arcs++) { + snprintf(arc_name, sizeof(arc_name), "%s-%u", sample_arc_name, n_arcs); + if (rte_graph_feature_arc_create(arc_name, MAX_FEATURES, + MAX_INDEXES, &dummy1, &arcs[n_arcs])) { + printf("Feature arc creation failed for %u\n", n_arcs); + return TEST_FAILED; + } + } + /* Verify feature arc created more than max_arcs must fail */ + if (!rte_graph_feature_arc_create("negative_test_create_arc", MAX_FEATURES, + MAX_INDEXES, &dummy2, &arc)) { + printf("Feature arc creation success for more than max configured: %u\n", n_arcs); + return TEST_FAILED; + } + /* Make sure lookup passes for all feature arcs */ + for (n_arcs = 0; n_arcs < max_arcs; n_arcs++) { + snprintf(arc_name, sizeof(arc_name), "%s-%u", sample_arc_name, n_arcs); + arc = RTE_GRAPH_FEATURE_ARC_INITIALIZER; + if (!rte_graph_feature_arc_lookup_by_name(arc_name, &arc)) { + if (arc != arcs[n_arcs]) { + printf("%s: Feature arc lookup mismatch for arc [%p, exp: %p]\n", + arc_name, (void *)arc, (void *)arcs[n_arcs]); + return TEST_FAILED; + } + } else { + printf("Feature arc lookup %s failed after creation\n", arc_name); + return TEST_FAILED; + } + } + return TEST_SUCCESS; +} + +static int +test_graph_feature_arc_create(void) +{ + int ret = 0, i; + + /* Create arcs with RTE_GRAPH_FEATURE_ARC_MAX */ + ret = __test_create_feature_arc(arcs, RTE_GRAPH_FEATURE_ARC_MAX); + if (ret) { + printf("Feature arc creation test failed for RTE_GRAPH_FEATURE_ARC_MAX arcs\n"); + return TEST_FAILED; + } + /* destroy all arcs via cleanup API*/ + ret = rte_graph_feature_arc_cleanup(); + if (ret) { + printf("Feature arc cleanup failed\n"); + return TEST_FAILED; + } + +#define NUM_FEAT_ARCS 128 + /* create 128 dummy feature arcs */ + ret = rte_graph_feature_arc_init(NUM_FEAT_ARCS); + if (ret) { + printf("Feature arc init failed for NUM_FEAT_ARCS"); + return TEST_FAILED; + } + ret = __test_create_feature_arc(arcs, NUM_FEAT_ARCS); + if (ret) { + printf("Feature arc creation test failed for NUM_FEAT_ARCS\n"); + return TEST_FAILED; + } + /* destroy all of them*/ + for (i = 0; i < NUM_FEAT_ARCS; i++) { + if (rte_graph_feature_arc_destroy(arcs[i])) { + printf("Feature arc destroy failed for %u\n", i); + return TEST_FAILED; + } + } + rte_graph_feature_arc_cleanup(); + + /* Create two arcs as per test plan */ + /* First arc start/source node is node: SOURCE1 */ + if (rte_graph_feature_arc_create(TEST_ARC1_NAME, MAX_FEATURES, + MAX_INDEXES, &source1, &arcs[0])) { + printf("Feature arc creation failed for %s\n", TEST_ARC1_NAME); + return TEST_FAILED; + } + + /* Duplicate name should fail */ + if (!rte_graph_feature_arc_create(TEST_ARC1_NAME, MAX_FEATURES, + MAX_INDEXES, &source1, &arcs[1])) { + printf("Duplicate feature arc %s creation is not caught\n", TEST_ARC1_NAME); + return TEST_FAILED; + } + /* Second arc start/source node is node: OUTPUT_STATIC */ + if (rte_graph_feature_arc_create(TEST_ARC2_NAME, MAX_FEATURES, + MAX_INDEXES, &output, &arcs[1])) { + printf("Feature arc creation failed for %s\n", TEST_ARC1_NAME); + return TEST_FAILED; + } + return TEST_SUCCESS; +} + +static int +test_graph_feature_arc_features_add(void) +{ + rte_graph_feature_t temp; + + /* First feature to SOURCE1 start node -> ARC1_FEATURE1 */ + if (rte_graph_feature_add(arcs[0], &arc1_feature1, NULL, NULL)) { + printf("%s: Feature add failed for adding feature %s\n", + TEST_ARC1_NAME, ARC1_FEATURE1); + return TEST_FAILED; + } + /* Second feature to SOURCE1 -> ARC1_FEATURE2 */ + if (rte_graph_feature_add(arcs[0], &arc1_feature2, NULL, NULL)) { + printf("%s: Feature add failed for adding feature %s\n", + TEST_ARC1_NAME, ARC1_FEATURE2); + return TEST_FAILED; + } + /* adding statically connected INPUT_STATIC as a last feature */ + if (rte_graph_feature_add(arcs[0], &input, ARC1_FEATURE2, NULL)) { + printf("%s: Feature add failed for adding feature %s after %s\n", + TEST_ARC1_NAME, INPUT_STATIC, ARC1_FEATURE2); + return TEST_FAILED; + } + /* First feature to OUTPUT_STATIC start node -> ARC2_FEATURE3 */ + if (rte_graph_feature_add(arcs[1], &arc2_feature3, NULL, NULL)) { + printf("%s: Feature add failed for adding feature %s\n", + TEST_ARC2_NAME, ARC2_FEATURE3); + return TEST_FAILED; + } + /* Second feature to OUTPUT_STATIC -> ARC2_FEATURE1 and before feature to + * ARC2_FEATURE3 + */ + if (rte_graph_feature_add(arcs[1], &arc2_feature1, NULL, ARC2_FEATURE3)) { + printf("%s: Feature add failed for adding feature %s after %s\n", + TEST_ARC2_NAME, ARC2_FEATURE3, ARC2_FEATURE1); + return TEST_FAILED; + } + /* Add PKT_FREE node as last feature, next to arc2_feature3 */ + if (rte_graph_feature_add(arcs[1], &pkt_free, ARC2_FEATURE3, NULL)) { + printf("%s: Feature add failed for adding feature %s after %s\n", + TEST_ARC2_NAME, PKT_FREE_STATIC, ARC2_FEATURE3); + return TEST_FAILED; + } + /* Adding feature ARC2_FEATURE2 between ARC2_FEATURE1 and ARC2_FEATURE3. */ + if (rte_graph_feature_add(arcs[1], &arc2_feature2, ARC2_FEATURE1, ARC2_FEATURE3)) { + printf("%s: Feature add failed for adding feature %s between [%s - %s]\n", + TEST_ARC2_NAME, ARC2_FEATURE2, ARC2_FEATURE1, ARC2_FEATURE3); + return TEST_FAILED; + } + /* Now check feature sequencing is correct for both ARCS */ + + /* arc1_featur1 must be first feature to arcs[0] */ + if (!strstr(ARC1_FEATURE1, + rte_graph_feature_arc_feature_to_name(arcs[0], + rte_graph_feature_cast(0)))) { + printf("%s: %s is not the first feature instead %s\n", + TEST_ARC1_NAME, ARC1_FEATURE1, + rte_graph_feature_arc_feature_to_name(arcs[0], rte_graph_feature_cast(0))); + return TEST_FAILED; + } + + /* arc1_feature2 must be second feature to arcs[0] */ + if (!strstr(ARC1_FEATURE2, + rte_graph_feature_arc_feature_to_name(arcs[0], + rte_graph_feature_cast(1)))) { + printf("%s: %s is not the second feature instead %s\n", + TEST_ARC1_NAME, ARC1_FEATURE2, + rte_graph_feature_arc_feature_to_name(arcs[0], rte_graph_feature_cast(1))); + return TEST_FAILED; + } + + /* Make sure INPUT_STATIC is the last feature in arcs[0] */ + temp = rte_graph_feature_arc_num_features(arcs[0]); + if (!strstr(INPUT_STATIC, + rte_graph_feature_arc_feature_to_name(arcs[0], + temp - rte_graph_feature_cast(1)))) { + printf("%s: %s is not the last feature instead %s\n", + TEST_ARC1_NAME, INPUT_STATIC, + rte_graph_feature_arc_feature_to_name(arcs[0], + temp - rte_graph_feature_cast(1))); + return TEST_FAILED; + } + + /* arc2_featur1 must be first feature to arcs[1] */ + if (!strstr(ARC2_FEATURE1, + rte_graph_feature_arc_feature_to_name(arcs[1], + rte_graph_feature_cast(0)))) { + printf("%s: %s is not the first feature instead %s\n", + TEST_ARC2_NAME, ARC2_FEATURE1, + rte_graph_feature_arc_feature_to_name(arcs[1], rte_graph_feature_cast(0))); + return TEST_FAILED; + } + + /* arc2_feature2 must be second feature to arcs[1] */ + if (!strstr(ARC2_FEATURE2, + rte_graph_feature_arc_feature_to_name(arcs[1], + rte_graph_feature_cast(1)))) { + printf("%s: %s is not the second feature instead %s\n", + TEST_ARC2_NAME, ARC2_FEATURE2, + rte_graph_feature_arc_feature_to_name(arcs[1], rte_graph_feature_cast(1))); + return TEST_FAILED; + } + + /* arc2_feature3 must be third feature to arcs[1] */ + if (!strstr(ARC2_FEATURE3, + rte_graph_feature_arc_feature_to_name(arcs[1], + rte_graph_feature_cast(2)))) { + printf("%s: %s is not the third feature instead %s\n", + TEST_ARC2_NAME, ARC2_FEATURE3, + rte_graph_feature_arc_feature_to_name(arcs[1], rte_graph_feature_cast(2))); + return TEST_FAILED; + } + + /* Make sure PKT_FREE is the last feature in arcs[1] */ + temp = rte_graph_feature_arc_num_features(arcs[1]); + if (!strstr(PKT_FREE_STATIC, + rte_graph_feature_arc_feature_to_name(arcs[1], + temp - rte_graph_feature_cast(1)))) { + printf("%s: %s is not the last feature instead %s\n", + TEST_ARC2_NAME, PKT_FREE_STATIC, + rte_graph_feature_arc_feature_to_name(arcs[1], + temp - rte_graph_feature_cast(1))); + return TEST_FAILED; + } + + if (get_edge(&arc2_feature1, &pkt_free, NULL)) { + printf("%s: Edge not found between %s and %s\n", + TEST_ARC2_NAME, ARC2_FEATURE1, PKT_FREE_STATIC); + return TEST_FAILED; + } + + return create_graph(); +} + +static int +test_graph_feature_arc_first_feature_enable(void) +{ + uint32_t n_indexes, n_features, count = 0; + rte_graph_feature_rt_list_t feature_list, temp = 0; + struct rte_node_register *parent, *child; + rte_graph_feature_data_t *fdata = NULL; + struct rte_graph_feature_arc *arc; + rte_graph_feature_t feature; + char *feature_name = NULL; + int32_t user_data; + rte_edge_t edge = ~0; + + arc = rte_graph_feature_arc_get(arcs[0]); + + if (rte_graph_feature_arc_has_any_feature(arc, &feature_list)) { + printf("%s: Feature arc should not have any feature enabled by now\n", + TEST_ARC1_NAME); + return TEST_FAILED; + } + + if (rte_graph_feature_arc_num_enabled_features(arcs[0])) { + printf("%s: Feature arc should not have any_feature() enabled by now\n", + TEST_ARC1_NAME); + return TEST_FAILED; + } + /* + * On interface 0, enable feature 0, + * On interface 1, enable feature 1 and so on so forth + * + * later verify first feature on every interface index is unique + * and check [rte_edge, user_data] retrieved via fast path APIs + */ + for (n_indexes = 0; n_indexes < MAX_INDEXES; n_indexes++) { + n_features = n_indexes % 3 /* 3 features added to arc1 */; + feature_name = rte_graph_feature_arc_feature_to_name(arcs[0], n_features); + user_data = compute_unique_user_data(arc->start_node->name, feature_name, + n_indexes); + if (rte_graph_feature_validate(arcs[0], n_indexes, feature_name, 1, true)) { + printf("%s: Feature validate failed for %s on index %u\n", + TEST_ARC1_NAME, feature_name, n_indexes); + return TEST_FAILED; + } + /* negative test case. enable feature on invalid index */ + if (!n_indexes && !rte_graph_feature_enable(arcs[0], MAX_INDEXES, feature_name, + (int32_t)user_data)) { + printf("%s: Feature %s should not be enabled on invalid index\n", + TEST_ARC1_NAME, feature_name); + return TEST_FAILED; + } + if (rte_graph_feature_enable(arcs[0], n_indexes, feature_name, + (int32_t)user_data)) { + printf("%s: Feature enable failed for %s on index %u\n", + TEST_ARC1_NAME, feature_name, n_indexes); + return TEST_FAILED; + } + /* has any feature should be valid */ + if (!rte_graph_feature_arc_has_any_feature(arc, &feature_list)) { + printf("%s: Feature arc should have any_feature enabled by now\n", + TEST_ARC1_NAME); + return TEST_FAILED; + } + if (temp == feature_list) { + printf("%s: Activer feature list not switched from %u -> %u\n", + TEST_ARC1_NAME, temp, feature_list); + return TEST_FAILED; + } + temp = feature_list; + if ((count + 1) != rte_graph_feature_arc_num_enabled_features(arcs[0])) { + printf("%s: Number of enabled mismatches [found: %u, exp: %u]\n", + TEST_ARC1_NAME, + rte_graph_feature_arc_num_enabled_features(arcs[0]), + count + 1); + return TEST_FAILED; + } + count++; + } + if (!rte_graph_feature_arc_has_any_feature(arc, &feature_list)) { + printf("%s: Feature arc should have any_feature enabled by now\n", + TEST_ARC1_NAME); + return TEST_FAILED; + } + /* Negative test case */ + user_data = compute_unique_user_data(arc->start_node->name, ARC2_FEATURE1, 1); + if (!rte_graph_feature_enable(arcs[0], 1 /* index */, ARC2_FEATURE1, user_data)) { + printf("%s: Invalid feature %s is enabled on index 1\n", + TEST_ARC1_NAME, ARC2_FEATURE1); + return TEST_FAILED; + } + /* Duplicate enable */ + if (!rte_graph_feature_enable(arcs[0], 1 /* index */, ARC1_FEATURE2, user_data)) { + printf("%s: Duplicate feature %s shouldn't be enabled again on index 1\n", + TEST_ARC1_NAME, ARC1_FEATURE2); + return TEST_FAILED; + } + for (n_indexes = 0; n_indexes < MAX_INDEXES; n_indexes++) { + if (!rte_graph_feature_arc_first_feature_get(arc, feature_list, n_indexes, + &feature)) { + printf("%s: No first feature enabled on index: %u\n", + TEST_ARC1_NAME, n_indexes); + return TEST_FAILED; + } + /* Get first feature data and ensure edge and user_data are correct */ + fdata = rte_graph_feature_data_get(arc, rte_graph_feature_get(arc, feature), + n_indexes); + parent = arc->start_node; + if (0 == (n_indexes % 3)) + child = &arc1_feature1; + else if (1 == (n_indexes % 3)) + child = &arc1_feature2; + else + child = &input; + + if (get_edge(parent, child, &edge)) { + printf("%s: Edge not found between %s and %s\n", + TEST_ARC1_NAME, parent->name, child->name); + return TEST_FAILED; + } + if (fdata->next_edge != edge) { + printf("%s: Edge mismatch for first feature on index %u [%u, exp: %u]\n", + TEST_ARC1_NAME, n_indexes, fdata->next_edge, edge); + return TEST_FAILED; + } + if (fdata->user_data != compute_unique_user_data(parent->name, child->name, + n_indexes)) { + printf("%s: First feature user data mismatch on index %u [%u, exp: %u]\n", + TEST_ARC1_NAME, n_indexes, fdata->user_data, + compute_unique_user_data(parent->name, child->name, n_indexes)); + return TEST_FAILED; + } + } + return TEST_SUCCESS; +} + +static int +verify_feature_sequencing(struct rte_graph_feature_arc *arc) +{ + rte_graph_feature_rt_list_t feature_list; + struct rte_node_register *parent, *child; + rte_graph_feature_data_t *fdata = NULL; + rte_graph_feature_t feature; + uint32_t n_indexes; + rte_edge_t edge = ~0; + int32_t user_data; + + if (!rte_graph_feature_arc_has_any_feature(arc, &feature_list)) { + printf("%s: feature_list can't be obtained\n", + arc->feature_arc_name); + return TEST_FAILED; + } + /* Verify next features on interface 0 and interface 1*/ + for (n_indexes = 0; n_indexes < 2; n_indexes++) { + if (!rte_graph_feature_arc_first_feature_get(arc, feature_list, n_indexes, + &feature)) { + printf("%s: No first feature enabled on index: 0\n", + arc->feature_arc_name); + return TEST_FAILED; + } + parent = arc->start_node; + child = rte_graph_feature_arc_feature_to_node(arcs[1], feature); + /* until fast path API reaches last feature i.e pkt_free */ + while (child != &pkt_free) { + fdata = rte_graph_feature_data_get(arc, + rte_graph_feature_get(arc, feature), + n_indexes); + + if (get_edge(parent, child, &edge)) { + printf("%s: Edge not found between %s and %s\n", + arc->feature_arc_name, parent->name, child->name); + return TEST_FAILED; + } + user_data = compute_unique_user_data(parent->name, child->name, n_indexes); + if (fdata->next_edge != edge) { + printf("%s: Edge mismatch for %s->%s on index %u [%u, exp: %u]\n", + arc->feature_arc_name, parent->name, child->name, n_indexes, + fdata->next_edge, edge); + return TEST_FAILED; + } + if (fdata->user_data != user_data) { + printf("%s: Udata mismatch for %s->%s on index %u [%u, exp: %u]\n", + arc->feature_arc_name, parent->name, child->name, n_indexes, + fdata->user_data, user_data); + return TEST_FAILED; + } + + feature = fdata->next_enabled_feature; + + parent = child; + child = rte_graph_feature_arc_feature_to_node(arcs[1], + fdata->next_enabled_feature); + } + } + return TEST_SUCCESS; +} + +static int +test_graph_feature_arc_next_feature_enable(void) +{ + rte_graph_feature_rt_list_t feature_list; + struct rte_node_register *parent, *child; + rte_graph_feature_data_t *fdata = NULL; + struct rte_graph_feature_arc *arc; + uint32_t n_indexes, n_features; + rte_graph_feature_t feature; + char *feature_name = NULL; + rte_edge_t edge = ~0; + int32_t user_data; + + arc = rte_graph_feature_arc_get(arcs[1]); + + if (rte_graph_feature_arc_has_any_feature(arc, &feature_list)) { + printf("%s: Feature arc should not have any feature enabled by now\n", + TEST_ARC2_NAME); + return TEST_FAILED; + } + + if (rte_graph_feature_arc_num_enabled_features(arcs[1])) { + printf("%s: Feature arc should not have any_feature() enabled by now\n", + TEST_ARC2_NAME); + return TEST_FAILED; + } + /* + * On interface 0, enable feature 2, skip feature 1 for later + * On interface 1, enable feature 3 + * On interface 2, enable pkt_free feature + * On interface 3, continue as interface 0 + * + * later enable next feature sequence for interface 0 from feature2 -> pkt_free + * later enable next feature sequence for interface 1 from feature3 -> pkt_free + * + * also later enable feature-1 and see first feature changes for all indexes + */ + for (n_indexes = 0; n_indexes < MAX_INDEXES; n_indexes++) { + n_features = (n_indexes % 3) + 1; /* feature2 to pkt_free are 3 features */ + feature_name = rte_graph_feature_arc_feature_to_name(arcs[1], n_features); + user_data = compute_unique_user_data(arc->start_node->name, feature_name, + n_indexes); + if (rte_graph_feature_enable(arcs[1], n_indexes, feature_name, + (int32_t)user_data)) { + printf("%s: Feature enable failed for %s on index %u\n", + TEST_ARC2_NAME, feature_name, n_indexes); + return TEST_FAILED; + } + /* has any feature should be valid */ + if (!rte_graph_feature_arc_has_any_feature(arc, &feature_list)) { + printf("%s: Feature arc should have any_feature enabled by now\n", + TEST_ARC2_NAME); + return TEST_FAILED; + } + } + /* Retrieve latest feature_list */ + rte_graph_feature_arc_has_any_feature(arc, &feature_list); + /* verify first feature */ + for (n_indexes = 0; n_indexes < MAX_INDEXES; n_indexes++) { + if (!rte_graph_feature_arc_first_feature_get(arc, feature_list, n_indexes, + &feature)) { + printf("%s: No first feature enabled on index: %u\n", + TEST_ARC2_NAME, n_indexes); + return TEST_FAILED; + } + /* Get first feature data and ensure edge and user_data are correct */ + fdata = rte_graph_feature_data_get(arc, rte_graph_feature_get(arc, feature), + n_indexes); + parent = arc->start_node; + if (0 == (n_indexes % 3)) + child = &arc2_feature2; + else if (1 == (n_indexes % 3)) + child = &arc2_feature3; + else + child = &pkt_free; + + if (get_edge(parent, child, &edge)) { + printf("%s: Edge not found between %s and %s\n", + TEST_ARC2_NAME, parent->name, child->name); + return TEST_FAILED; + } + if (fdata->next_edge != edge) { + printf("%s: Edge mismatch for first feature on index %u [%u, exp: %u]\n", + TEST_ARC2_NAME, n_indexes, fdata->next_edge, edge); + return TEST_FAILED; + } + if (fdata->user_data != compute_unique_user_data(parent->name, child->name, + n_indexes)) { + printf("%s: First feature user data mismatch on index %u [%u, exp: %u]\n", + TEST_ARC2_NAME, n_indexes, fdata->user_data, + compute_unique_user_data(parent->name, child->name, n_indexes)); + return TEST_FAILED; + } + } + /* add next_features now + * On interface 0, enable feature-3 and pkt_free + * On interface 1, enable pkt_free + * Skip interface 2 + * On interface 3, same as interface 0 + * On interface 4, same as interface 1 + */ + for (n_indexes = 0; n_indexes < MAX_INDEXES; n_indexes++) { + if (0 == (n_indexes % 3)) { + if (rte_graph_feature_enable(arcs[1], n_indexes, ARC2_FEATURE3, + compute_unique_user_data(ARC2_FEATURE2, + ARC2_FEATURE3, + n_indexes))) { + printf("%s: Feature enable failed for %s -> (%s) on index %u\n", + TEST_ARC2_NAME, ARC2_FEATURE2, ARC2_FEATURE3, n_indexes); + return TEST_FAILED; + } + } + /* pkt_free on interface-0, 1, 3, 4 and so on */ + if ((0 == (n_indexes % 3)) || (1 == (n_indexes % 3))) { + if (rte_graph_feature_enable(arcs[1], n_indexes, PKT_FREE_STATIC, + compute_unique_user_data(ARC2_FEATURE3, + PKT_FREE_STATIC, + n_indexes))) { + printf("%s: Feature enable failed %s -> (%s) on index %u\n", + TEST_ARC2_NAME, ARC2_FEATURE3, PKT_FREE_STATIC, n_indexes); + return TEST_FAILED; + } + } + } + + if (verify_feature_sequencing(arc) == TEST_FAILED) + return TEST_FAILED; + + /* Enable feature-1 on all interfaces and check first feature changes */ + for (n_indexes = 0; n_indexes < MAX_INDEXES; n_indexes++) { + user_data = compute_unique_user_data(arc->start_node->name, ARC2_FEATURE1, + n_indexes); + if (rte_graph_feature_enable(arcs[1], n_indexes, ARC2_FEATURE1, + (int32_t)user_data)) { + printf("%s: Feature enable failed for %s on index %u\n", + TEST_ARC2_NAME, feature_name, n_indexes); + return TEST_FAILED; + } + } + rte_graph_feature_arc_has_any_feature(arc, &feature_list); + for (n_indexes = 0; n_indexes < MAX_INDEXES; n_indexes++) { + if (!rte_graph_feature_arc_first_feature_get(arc, feature_list, n_indexes, + &feature)) { + printf("%s: None first feature enabled on index: %u\n", + TEST_ARC2_NAME, n_indexes); + return TEST_FAILED; + } + if (feature != rte_graph_feature_cast(0)) { + printf("%s: First feature mismatch on index %u [%u, exp: %u]\n", + TEST_ARC2_NAME, n_indexes, feature, rte_graph_feature_cast(0)); + return TEST_FAILED; + } + } + if (verify_feature_sequencing(arc) == TEST_FAILED) + return TEST_FAILED; + + return TEST_SUCCESS; +} + +static int +test_graph_feature_arc_first_feature_disable(void) +{ + rte_graph_feature_rt_list_t feature_list; + struct rte_graph_feature_arc *arc; + rte_graph_feature_t feature; + uint32_t n_indexes; + + arc = rte_graph_feature_arc_get(arcs[1]); + + /* Disable feature-1 on all interfaces and check first feature changes */ + for (n_indexes = 0; n_indexes < MAX_INDEXES; n_indexes++) { + if (rte_graph_feature_disable(arcs[1], n_indexes, ARC2_FEATURE1)) { + printf("%s: Feature disable failed for %s on index %u\n", + TEST_ARC2_NAME, ARC2_FEATURE1, n_indexes); + return TEST_FAILED; + } + } + rte_graph_feature_arc_has_any_feature(arc, &feature_list); + for (n_indexes = 0; n_indexes < MAX_INDEXES; n_indexes++) { + if (!rte_graph_feature_arc_first_feature_get(arc, feature_list, n_indexes, + &feature)) { + printf("%s: First feature get failed on index: %u\n", + TEST_ARC2_NAME, n_indexes); + return TEST_FAILED; + } + if (feature == rte_graph_feature_cast(0)) { + printf("%s: First feature not disabled on index %u [%u, exp: %u]\n", + TEST_ARC2_NAME, n_indexes, feature, rte_graph_feature_cast(1)); + return TEST_FAILED; + } + if (!strncmp(ARC2_FEATURE1, + rte_graph_feature_arc_feature_to_name(arcs[1], feature), + strlen(ARC2_FEATURE1))) { + printf("%s: First feature mismatch on index %u [%s, exp: %s]\n", + TEST_ARC2_NAME, n_indexes, + rte_graph_feature_arc_feature_to_name(arcs[1], feature), + ARC2_FEATURE2); + return TEST_FAILED; + } + } + if (verify_feature_sequencing(arc) == TEST_FAILED) + return TEST_FAILED; + + return TEST_SUCCESS; +} + +static int +test_graph_feature_arc_next_feature_disable(void) +{ + rte_graph_feature_rt_list_t feature_list; + struct rte_graph_feature_arc *arc; + rte_graph_feature_t feature; + uint32_t n_indexes; + + arc = rte_graph_feature_arc_get(arcs[1]); + + /* + * On interface 0, disable feature 2, keep feature3 and pkt_free enabled + * On interface 1, skip interface 1 where feature3 and pkt_free are enabled + * skip interface 2 as only pkt_free is enabled + */ + for (n_indexes = 0; n_indexes < MAX_INDEXES; n_indexes++) { + if (!(n_indexes % 3)) { + if (rte_graph_feature_disable(arcs[1], n_indexes, ARC2_FEATURE2)) { + printf("%s: Feature disable failed for %s on index %u\n", + TEST_ARC2_NAME, ARC2_FEATURE2, n_indexes); + return TEST_FAILED; + } + } + + if (verify_feature_sequencing(arc) == TEST_FAILED) + return TEST_FAILED; + } + + /** + * Disable feature 3 on all interface 0 and 1 and check first feature + * is pkt_free on all indexes + */ + for (n_indexes = 0; n_indexes < MAX_INDEXES; n_indexes++) { + if ((0 == (n_indexes % 3)) || (1 == (n_indexes % 3))) { + if (rte_graph_feature_disable(arcs[1], n_indexes, ARC2_FEATURE3)) { + printf("%s: Feature disable failed for %s on index %u\n", + TEST_ARC2_NAME, ARC2_FEATURE3, n_indexes); + return TEST_FAILED; + } + } + } + /* Make sure pkt_free is first feature for all indexes */ + rte_graph_feature_arc_has_any_feature(arc, &feature_list); + for (n_indexes = 0; n_indexes < MAX_INDEXES; n_indexes++) { + if (!rte_graph_feature_arc_first_feature_get(arc, feature_list, n_indexes, + &feature)) { + printf("%s: First feature get failed on index: %u\n", + TEST_ARC2_NAME, n_indexes); + return TEST_FAILED; + } + if (strncmp(PKT_FREE_STATIC, + rte_graph_feature_arc_feature_to_name(arcs[1], feature), + strlen(PKT_FREE_STATIC))) { + printf("%s: %s is not first feature found on index %u [%s, exp: %s]\n", + TEST_ARC2_NAME, PKT_FREE_STATIC, n_indexes, + rte_graph_feature_arc_feature_to_name(arcs[1], feature), + PKT_FREE_STATIC); + return TEST_FAILED; + } + } + + /* Disable PKT_FREE_STATIC from all indexes with no feature enabled on any interface */ + for (n_indexes = 0; n_indexes < MAX_INDEXES; n_indexes++) { + if (rte_graph_feature_disable(arcs[1], n_indexes, PKT_FREE_STATIC)) { + printf("%s: Feat disable failed for %s on index %u\n", + TEST_ARC2_NAME, PKT_FREE_STATIC, n_indexes); + return TEST_FAILED; + } + } + /* Make sure no feature is enabled now on any interface */ + rte_graph_feature_arc_has_any_feature(arc, &feature_list); + for (n_indexes = 0; n_indexes < MAX_INDEXES; n_indexes++) { + if (rte_graph_feature_arc_first_feature_get(arc, feature_list, n_indexes, + &feature)) { + printf("%s: Index: %u should not have first feature enabled\n", + TEST_ARC2_NAME, n_indexes); + return TEST_FAILED; + } + } + return TEST_SUCCESS; +} + +static int +test_graph_feature_arc_destroy(void) +{ + rte_graph_feature_arc_t arc; + + if (rte_graph_feature_arc_lookup_by_name(TEST_ARC1_NAME, &arc)) { + printf("Feature arc lookup failed for %s\n", TEST_ARC1_NAME); + return TEST_FAILED; + } + + if (arc != arcs[0]) { + printf("Feature arc lookup mismatch for %s [%p, exp: %p]\n", + TEST_ARC1_NAME, (void *)arc, (void *)arcs[0]); + return TEST_FAILED; + } + + if (rte_graph_feature_arc_destroy(arc)) { + printf("Feature arc destroy failed for %s\n", TEST_ARC1_NAME); + return TEST_FAILED; + } + + if (rte_graph_feature_arc_lookup_by_name(TEST_ARC2_NAME, &arc)) { + printf("Feature arc lookup success after destroy for %s\n", TEST_ARC2_NAME); + return TEST_FAILED; + } + + if (arc != arcs[1]) { + printf("Feature arc lookup mismatch for %s [%p, exp: %p]\n", + TEST_ARC2_NAME, (void *)arc, (void *)arcs[1]); + return TEST_FAILED; + } + if (rte_graph_feature_arc_destroy(arc)) { + printf("Feature arc destroy failed for %s\n", TEST_ARC2_NAME); + return TEST_FAILED; + } + return TEST_SUCCESS; +} + +static int +graph_feature_arc_setup(void) +{ + unsigned long i, j; + + static const struct rte_mbuf_dynfield graph_dynfield_desc = { + .name = "test_graph_dynfield", + .size = sizeof(graph_dynfield_t), + .align = alignof(graph_dynfield_t), + }; + + graph_dynfield_offset = + rte_mbuf_dynfield_register(&graph_dynfield_desc); + if (graph_dynfield_offset < 0) { + printf("Cannot register mbuf field\n"); + return TEST_FAILED; + } + RTE_SET_USED(graph_dynfield_offset); + + for (i = 0; i <= MAX_NODES; i++) { + for (j = 0; j < MBUFF_SIZE; j++) + mbuf_p[i][j] = &mbuf[i][j]; + } + + return TEST_SUCCESS; + +} + +static void +graph_feature_arc_teardown(void) +{ + if (graph_id != RTE_GRAPH_ID_INVALID) + rte_graph_destroy(graph_id); + + rte_graph_feature_arc_cleanup(); +} + +static struct unit_test_suite graph_feature_arc_testsuite = { + .suite_name = "Graph Feature arc library test suite", + .setup = graph_feature_arc_setup, + .teardown = graph_feature_arc_teardown, + .unit_test_cases = { + TEST_CASE(test_graph_feature_arc_create), + TEST_CASE(test_graph_feature_arc_features_add), + TEST_CASE(test_graph_feature_arc_first_feature_enable), + TEST_CASE(test_graph_feature_arc_next_feature_enable), + TEST_CASE(test_graph_feature_arc_first_feature_disable), + TEST_CASE(test_graph_feature_arc_next_feature_disable), + TEST_CASE(test_graph_feature_arc_destroy), + TEST_CASES_END(), /**< NULL terminate unit test array */ + }, +}; + +static int +graph_feature_arc_autotest_fn(void) +{ + return unit_test_suite_runner(&graph_feature_arc_testsuite); +} + +REGISTER_FAST_TEST(graph_feature_arc_autotest, true, true, graph_feature_arc_autotest_fn); +#endif /* !RTE_EXEC_ENV_WINDOWS */ -- 2.43.0 ^ permalink raw reply [flat|nested] 46+ messages in thread
* [PATCH v3 5/5] docs: add programming guide for feature arc 2024-10-09 13:29 ` [PATCH v3 0/5] add feature arc in rte_graph Nitin Saxena ` (3 preceding siblings ...) 2024-10-09 13:30 ` [PATCH v3 4/5] test/graph_feature_arc: add functional tests Nitin Saxena @ 2024-10-09 13:30 ` Nitin Saxena 2024-10-09 14:21 ` [PATCH v3 0/5] add feature arc in rte_graph Christophe Fontaine ` (2 subsequent siblings) 7 siblings, 0 replies; 46+ messages in thread From: Nitin Saxena @ 2024-10-09 13:30 UTC (permalink / raw) To: Jerin Jacob, Kiran Kumar K, Nithin Dabilpuram, Zhirun Yan, Robin Jarry, Christophe Fontaine Cc: dev, Nitin Saxena Updated graph library guide with feature arc Signed-off-by: Nitin Saxena <nsaxena@marvell.com> --- doc/guides/prog_guide/graph_lib.rst | 288 ++++++++++++++++++++ doc/guides/prog_guide/img/feature_arc-1.png | Bin 0 -> 61532 bytes doc/guides/prog_guide/img/feature_arc-2.png | Bin 0 -> 155806 bytes doc/guides/prog_guide/img/feature_arc-3.png | Bin 0 -> 143697 bytes 4 files changed, 288 insertions(+) create mode 100644 doc/guides/prog_guide/img/feature_arc-1.png create mode 100644 doc/guides/prog_guide/img/feature_arc-2.png create mode 100644 doc/guides/prog_guide/img/feature_arc-3.png diff --git a/doc/guides/prog_guide/graph_lib.rst b/doc/guides/prog_guide/graph_lib.rst index ad09bdfe26..fc231ace99 100644 --- a/doc/guides/prog_guide/graph_lib.rst +++ b/doc/guides/prog_guide/graph_lib.rst @@ -547,3 +547,291 @@ on success packet is enqueued to ``udp4_input`` node. Hash lookup is performed in ``udp4_input`` node with registered destination port and destination port in UDP packet , on success packet is handed to ``udp_user_node``. + +Feature Arc +----------- +`Feature arc` represents an ordered list of `protocols/features` at a given +networking layer. It is a high level abstraction to connect various `feature` +nodes in `rte_graph` instance and allows seamless packets steering based on the +sequence of enabled features at runtime on each interface. + +`Features` (or feature nodes) are nodes which handle partial or complete +protocol processing in a given direction. For instance, `ipv4-rewrite` and +`IPv4 IPsec encryption` are outbound features while `ipv4-lookup` and `IPv4 +IPsec decryption` are inbound features. Further, `ipv4-rewrite` and `IPv4 +IPsec encryption` can collectively represent a `feature arc` towards egress +direction with ordering constraints that `IPv4 IPsec encryption` must be +performed before `ipv4-rewrite`. Similarly, `IPv4 IPsec decryption` and +`ipv4-lookup` can represent a `feature arc` in an ingress direction. Both of +these `feature arc` can co-exist at an IPv4 layer in egress and ingress +direction respectively. + +A `feature` can be represented by a single node or collection of multiple nodes +performing feature processing collectively. + +.. figure:: img/feature_arc-1.png + :alt: feature-arc-1 + :width: 350px + :align: center + + Feature Arc overview + +Each `feature arc` is associated with a `Start` node from which all features in +a feature arc are connected. A `start` node itself is not a `feature` node but +it is where `first enabled feature` is checked in fast path. In above figure, +`Node-A` represents a `start node`. There may be a `Sink` node as well which +is child node for every feature in an arc. 'Sink` node is responsible of +consuming those packets which are not consumed by intermediate enabled features +between `start` and `sink` node. `Sink` node, if present, is the last enabled +feature in a feature arc. A `feature` node statically connected to `start` node +must also be added via feature arc API, `rte_graph_feature_add()``. Here `Node-B` +acts as a `sink` node which is statically linked to `Node A`. `Feature` nodes +are connected via `rte_graph_feature_add()` which takes care of connecting +all `feature` nodes with each other and start node. + +.. code-block:: bash + :linenos: + :emphasize-lines: 8 + :caption: Node-B statically linked to Node-A + + static struct rte_node_register node_A_node = { + .process = node_A_process_func, + ... + ... + .name = "Node-A", + .next_nodes = + { + [0] = "Node-B", + }, + .nb_edges = 1, + }; + +When multiple features are enabled on an interface, it may be required to steer +packets across `features` in a given order. For instance, if `Feature 1` and +`Feature 2` both are enabled on an interface ``X``, it may be required to send +packets to `Feature-1` before `Feature-2`. Such ordering constraints can be +easily expressed with `feature arc`. In this case, `Feature 1` is called as +``First Feature`` and `Feature 2` is called as ``Next Feature`` to `Feature 1`. + +.. figure:: img/feature_arc-2.png + :alt: feature-arc-2 + :width: 600px + :align: center + + First and Next features and their ordering + +In similar manner, even application specific ``custom features`` can be hooked +to standard nodes. It is to be noted that this `custom feature` hooking to +`feature arc` aware node does not require any code changes. + +It may be obvious by now that `features` enabled on one interface does not +affect packets on other interfaces. In above example, if no feature is +enabled on an interface ``X``, packets destined to interface ``X`` would be +directly sent to `Node-B` from `Node-A`. + +.. figure:: img/feature_arc-3.png + :alt: feature-arc-3 + :width: 550px + :align: center + + Feature-2 consumed/non-consumed packet path + +When a `Feature-X` node receives packets via feature arc, it may decide whether +to ``consume packet`` or send to `next enabled feature`. A node can consume +packet by freeing it, sending it on wire or enqueuing it to hardware queue. If a +packet is not consumed by a `Feature-X` node, it may send to `next enabled +feature` on an interface. In above figure, `Feature-2` nodes are represented to +consume packets. Classic example for a node performing consume and non-consume +operation on packets would be IPsec policy node where all packets with +``protect`` actions are consumed while remaining packets with ``bypass`` +actions are sent to next enabled feature. + +In fast path feature node may require to lookup local data structures for each +interface. For example, retrieving policy database per interface for IPsec +processing. ``rte_graph_feature_enable`` API allows to set application +specific cookie per feature per interface. `Feature data` object maintains this +cookie in fast path for each interface. + +`Feature arc design` allows to enable subsequent features in a control plane +without stopping workers which are accessing feature arc's fast path APIs in +``rte_graph_walk()`` context. However for disabling features require RCU like +scheme for synchronization. + +Programming model +~~~~~~~~~~~~~~~~~ +Feature Arc Objects +^^^^^^^^^^^^^^^^^^^ +Control plane and fast path APIs deals with following objects: + +Feature arc +*********** +``rte_graph_feature_arc_t`` is a handle to feature arc which is created via +``rte_graph_feature_arc_create()``. It is a `uint64_t` size object which can be +saved in feature node's context. This object can be translated to fast path +feature arc object ``struct rte_graph_feature_arc`` which is an input +argument to all fast path APIs. Control plane APIs majorly takes +`rte_graph_feature_arc_t` object as an input. + +Feature List +************ +Each feature arc holds two feature lists: `active` and `passive`. While worker +cores uses `active` list, control plane APIs uses `passive` list for +enabling/disabling a feature on any interface with in a arc. After successful +feature enable/disable, ``rte_graph_feature_enable()``/ +``rte_graph_feature_disable()`` atomically switches passive list to active list +and vice-versa. Most of the fast path APIs takes active list as an argument +(``rte_graph_feature_rt_list_t``), which feature node can obtain in start of +it's `process_func()` via ``rte_graph_feature_arc_has_any_feature()`` (in `start` +node) or ``rte_graph_feature_arc_has_feature()`` (in next feature nodes). + +Each feature list holds RTE_GRAPH_MAX_FEATURES number of features and +associated feature data for every interface index + +Feature +******** +Feature is a data structure which holds `feature data` object for every +interface. It is represented via ``rte_graph_feature_t`` which is a `uint8_t` +size object. Fast path internal structure ``struct rte_graph_feature`` can be +obtained from ``rte_graph_feature_t`` via ``rte_graph_feature_get()`` API. + +In `start` node `rte_graph_feature_arc_first_feature_get()` can be used to get +first enabled `rte_graph_feature_t` object for an interface. `rte_edge` from +`start` node to first enabled feature is provided by +``rte_graph_feature_arc_feature_set()`` API. + +In `feature nodes`, next enabled feature is obtained by providing current feature +as an input to ``rte_graph_feature_arc_next_feature_get()`` API. + +Feature data +************ +Feature data object is maintained per feature per interface which holds +following information in fast path + +- ``rte_edge_t`` to send packet to next enabled feature +- ``Next enabled feature`` on current interface +- ``User_data`` per feature per interface set by application via `rte_graph_feature_enable()` + +Enabling Feature Arc processing +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +By default, feature arc processing is disabled in `rte_graph_create()`. To +enable feature arc processing in fast path, `rte_graph_create()` API should be +invoked with `feature_arc_enable` flag set as `true` + +.. code-block:: bash + :linenos: + :emphasize-lines: 3 + :caption: Enabling feature are processing in rte_graph_create() + + struct rte_graph_param graph_conf; + + graph_conf.feature_arc_enable = true; + struct rte_graph *graph = rte_graph_create("graph_name", &graph_conf); + +Further as an optimization technique, `rte_graph_walk()` would call newly added +``feat_arc_proc()`` node callback function (if non-NULL) instead of +``preocess_func`` + +.. code-block:: bash + :linenos: + :emphasize-lines: 3 + :caption: Feature arc specific node callback function + + static struct rte_node_register ip4_rewrite_node = { + .process = ip4_rewrite_node_process, + .feat_arc_proc = ip4_rewrite_feature_node_process, + .name = "ip4_rewrite", + ... + ... + }; + +If `feat_arc_proc` is not provided in node registration, `process_func` would +be called by `rte_graph_walk()` + +Sample Usage +^^^^^^^^^^^^ +.. code-block:: bash + :linenos: + :caption: Feature arc sample usage + + #define MAX_FEATURES 10 + #define MAX_INDEXES 5 + + static uint16_t + feature2_feature_node_process (struct rte_graph *graph, struct + rte_node *node, void **objs, uint16_t nb_objs) + { + /* features may be enabled */ + } + static uint16_t + feature2_node_process (struct rte_graph *graph, struct + rte_node *node, void **objs, uint16_t nb_objs) + { + /* Feature arc is disabled in rte_graph_create() */ + } + + static uint16_t + feature2_node_process (struct rte_graph *graph, struct + rte_node *node, void **objs, uint16_t nb_objs) + { + /* Feature arc may be enabled or disabled as this process_func() would + * be called for the case when feature arc is enabled in rte_graph_create() + * and also the case when it is disabled + */ + } + + static struct rte_node_register feature2_node = { + .process = feature2_node_process, + .feat_arc_proc = feature2_feature_node_process, + .name = "feature2", + .init = feature2_init_func, + ... + ... + }; + + static struct rte_node_register feature1_node = { + .process = feature1_node_process, + .feat_arc_proc = NULL, + .name = "feature1", + ... + ... + }; + + int worker_cb(void *_em) + { + rte_graph_feature_arc_t arc; + uint32_t user_data; + + rte_graph_feature_arc_lookup_by_name("sample_arc", &arc); + + /* From control thread context (like CLII): + * Enable feature 2 on interface index 4 + */ + if (rte_lcore_id() == rte_get_main_lcore) { + user_data = 0x1234; + rte_graph_feature_enable(arc, 4 /* interface index */, "feature2", user_data); + } else { + while(1) + rte_graph_walk); + } + } + + int main(void) + { + struct rte_graph_param graph_conf; + rte_graph_feature_arc_t arc; + + if (rte_graph_feature_arc_create("sample_arc", MAX_FEATURES, MAX_INDEXES, &arc)) + return -1; + + rte_graph_feature_add(arc, "feature1", NULL, NULL); + rte_graph_feature_add(arc, "feature2", "feature1" /* add feature2 after feature 1*/, NULL); + + /* create graph*/ + ... + ... + graph_conf.feature_arc_enable = true; + + struct rte_graph *graph = rte_graph_create("sample_graph", &graph_conf); + + rte_eal_mp_remote_launch(worker_cb, arg, CALL_MAIN); + } diff --git a/doc/guides/prog_guide/img/feature_arc-1.png b/doc/guides/prog_guide/img/feature_arc-1.png new file mode 100644 index 0000000000000000000000000000000000000000..d518000f42753ea7a1a71668c2735c48fc75c3ed GIT binary patch literal 61532 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 literal 0 HcmV?d00001 diff --git a/doc/guides/prog_guide/img/feature_arc-2.png b/doc/guides/prog_guide/img/feature_arc-2.png new file mode 100644 index 0000000000000000000000000000000000000000..604a67229b29a9c8ace59d28a7324e02c2bc4a89 GIT binary patch literal 155806 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�!fv6yo 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ΐMNRyBlZP4r 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 VhL3#7$M&;o^tFw(Dm5IV{|}tHa(Vy& literal 0 HcmV?d00001 diff --git a/doc/guides/prog_guide/img/feature_arc-3.png b/doc/guides/prog_guide/img/feature_arc-3.png new file mode 100644 index 0000000000000000000000000000000000000000..3991e0aed2933bfa01e9ffad654f4c40a639bc53 GIT binary patch literal 143697 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 JynBzl{|6wHR9pZ6 literal 0 HcmV?d00001 -- 2.43.0 ^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [PATCH v3 0/5] add feature arc in rte_graph 2024-10-09 13:29 ` [PATCH v3 0/5] add feature arc in rte_graph Nitin Saxena ` (4 preceding siblings ...) 2024-10-09 13:30 ` [PATCH v3 5/5] docs: add programming guide for feature arc Nitin Saxena @ 2024-10-09 14:21 ` Christophe Fontaine 2024-10-10 4:13 ` [EXTERNAL] " Nitin Saxena 2024-10-09 17:37 ` Stephen Hemminger 2024-10-10 13:31 ` [PATCH v4 " Nitin Saxena 7 siblings, 1 reply; 46+ messages in thread From: Christophe Fontaine @ 2024-10-09 14:21 UTC (permalink / raw) To: Nitin Saxena Cc: Jerin Jacob, Kiran Kumar K, Nithin Dabilpuram, Zhirun Yan, Robin Jarry, dev, Nitin Saxena > On 9 Oct 2024, at 15:29, Nitin Saxena <nsaxena@marvell.com> wrote: > > Feature arc represents an ordered list of features/protocols at a given > networking layer. It is a high level abstraction to connect various > rte_graph nodes, as feature nodes, and allow packets steering across > these nodes in a generic manner. > > Features (or feature nodes) are nodes which handles partial or complete > handling of a protocol in fast path. Like ipv4-rewrite node, which adds > rewrite data to an outgoing IPv4 packet. > > However in above example, outgoing interface(say "eth0") may have > outbound IPsec policy enabled, hence packets must be steered from > ipv4-rewrite node to ipsec-outbound-policy node for outbound IPsec > policy lookup. On the other hand, packets routed to another interface > (eth1) will not be sent to ipsec-outbound-policy node as IPsec feature > is disabled on eth1. Feature-arc allows rte_graph applications to manage > such constraints easily > > Feature arc abstraction allows rte_graph based application to > > 1. Seamlessly steer packets across feature nodes based on whether > feature is enabled or disabled on an interface. Features enabled on one > interface may not be enabled on another interface with in a same feature > arc. > > 2. Allow enabling/disabling of features on an interface at runtime, > so that if a feature is disabled, packets associated with that interface > won't be steered to corresponding feature node. > > 3. Provides mechanism to hook custom/user-defined nodes to a feature > node and allow packet steering from feature node to custom node without > changing former's fast path function Hi, As a general comment, I would have expected a modification on rte_graph_walk so the nodes would *not* need to be aware of the enabled feature arcs. Yet, in the series, the nodes need to be aware if a feature arc is enabled or not. Isn’t this a contradiction or did I miss something ? Christophe > > 4. Allow expressing features in a particular sequential order so that > packets are steered in an ordered way across nodes in fast path. For > eg: if IPsec and IPv4 features are enabled on an ingress interface, > packets must be sent to IPsec inbound policy node first and then to ipv4 > lookup node. > > This patch series adds feature arc library in rte_graph and also adds > "ipv4-output" feature arc handling in "ipv4-rewrite" node. > > Changes in v3: > - rte_graph_feature_arc_t typedef from uint64_t to uintptr_t to fix > compilation on 32-bit machine > - Updated images in .png format > - Added ABI change section in release notes > - Fixed DPDK CI failures > > Changes in v2: > - Added unit tests for feature arc > - Fixed issues found in testing > - Added new public APIs rte_graph_feature_arc_feature_to_node(), > rte_graph_feature_arc_feature_to_name(), > rte_graph_feature_arc_num_features() > - Added programming guide for feature arc > - Added release notes for feature arc > > Nitin Saxena (5): > graph: add feature arc support > graph: add feature arc option in graph create > graph: add IPv4 output feature arc > test/graph_feature_arc: add functional tests > docs: add programming guide for feature arc > > app/test/meson.build | 1 + > app/test/test_graph_feature_arc.c | 1410 +++++++++++++++++++ > doc/guides/prog_guide/graph_lib.rst | 288 ++++ > doc/guides/prog_guide/img/feature_arc-1.png | Bin 0 -> 61532 bytes > doc/guides/prog_guide/img/feature_arc-2.png | Bin 0 -> 155806 bytes > doc/guides/prog_guide/img/feature_arc-3.png | Bin 0 -> 143697 bytes > doc/guides/rel_notes/release_24_11.rst | 13 + > lib/graph/graph.c | 1 + > lib/graph/graph_feature_arc.c | 1223 ++++++++++++++++ > lib/graph/graph_populate.c | 7 +- > lib/graph/graph_private.h | 3 + > lib/graph/meson.build | 2 + > lib/graph/node.c | 2 + > lib/graph/rte_graph.h | 3 + > lib/graph/rte_graph_feature_arc.h | 431 ++++++ > lib/graph/rte_graph_feature_arc_worker.h | 674 +++++++++ > lib/graph/version.map | 20 + > lib/node/ip4_rewrite.c | 476 +++++-- > lib/node/ip4_rewrite_priv.h | 15 +- > lib/node/node_private.h | 20 +- > lib/node/rte_node_ip4_api.h | 3 + > 21 files changed, 4494 insertions(+), 98 deletions(-) > create mode 100644 app/test/test_graph_feature_arc.c > create mode 100644 doc/guides/prog_guide/img/feature_arc-1.png > create mode 100644 doc/guides/prog_guide/img/feature_arc-2.png > create mode 100644 doc/guides/prog_guide/img/feature_arc-3.png > create mode 100644 lib/graph/graph_feature_arc.c > create mode 100644 lib/graph/rte_graph_feature_arc.h > create mode 100644 lib/graph/rte_graph_feature_arc_worker.h > > -- > 2.43.0 > ^ permalink raw reply [flat|nested] 46+ messages in thread
* RE: [EXTERNAL] Re: [PATCH v3 0/5] add feature arc in rte_graph 2024-10-09 14:21 ` [PATCH v3 0/5] add feature arc in rte_graph Christophe Fontaine @ 2024-10-10 4:13 ` Nitin Saxena 0 siblings, 0 replies; 46+ messages in thread From: Nitin Saxena @ 2024-10-10 4:13 UTC (permalink / raw) To: Christophe Fontaine Cc: Jerin Jacob, Kiran Kumar Kokkilagadda, Nithin Kumar Dabilpuram, Zhirun Yan, Robin Jarry, dev, Nitin Saxena Hi Christophe, Thanks for the review. See my comments inline Thanks, Nitin > -----Original Message----- > From: Christophe Fontaine <cfontain@redhat.com> > Sent: Wednesday, October 9, 2024 7:51 PM > To: Nitin Saxena <nsaxena@marvell.com> > Cc: Jerin Jacob <jerinj@marvell.com>; Kiran Kumar Kokkilagadda > <kirankumark@marvell.com>; Nithin Kumar Dabilpuram > <ndabilpuram@marvell.com>; Zhirun Yan <yanzhirun_163@163.com>; Robin > Jarry <rjarry@redhat.com>; dev@dpdk.org; Nitin Saxena > <nsaxena16@gmail.com> > Subject: [EXTERNAL] Re: [PATCH v3 0/5] add feature arc in rte_graph > > > On 9 Oct 2024, at 15:29, Nitin Saxena <nsaxena@marvell.com> wrote: > > > > Feature arc represents an ordered list of features/protocols at a > > given networking layer. It is a high level abstraction to connect > > various rte_graph nodes, as feature nodes, and allow packets steering > > across these nodes in a generic manner. > > > > Features (or feature nodes) are nodes which handles partial or > > complete handling of a protocol in fast path. Like ipv4-rewrite node, > > which adds rewrite data to an outgoing IPv4 packet. > > > > However in above example, outgoing interface(say "eth0") may have > > outbound IPsec policy enabled, hence packets must be steered from > > ipv4-rewrite node to ipsec-outbound-policy node for outbound IPsec > > policy lookup. On the other hand, packets routed to another interface > > (eth1) will not be sent to ipsec-outbound-policy node as IPsec feature > > is disabled on eth1. Feature-arc allows rte_graph applications to > > manage such constraints easily > > > > Feature arc abstraction allows rte_graph based application to > > > > 1. Seamlessly steer packets across feature nodes based on whether > > feature is enabled or disabled on an interface. Features enabled on > > one interface may not be enabled on another interface with in a same > > feature arc. > > > > 2. Allow enabling/disabling of features on an interface at runtime, so > > that if a feature is disabled, packets associated with that interface > > won't be steered to corresponding feature node. > > > > 3. Provides mechanism to hook custom/user-defined nodes to a feature > > node and allow packet steering from feature node to custom node > > without changing former's fast path function > > Hi, > > As a general comment, I would have expected a modification on > rte_graph_walk so the nodes would *not* need to be aware of the enabled > feature arcs. If your point is that nodes has to adopt rte_feature_xxx() APIs in its "process_func()" to take advantage of feature arc, then your assessment is true. So it is true that each feature node knows on which *arc* it sits on. However *unaware* part comes from the fact that once a node is integrated with feature_arc APIs, then the node does not need to know what is the next node to which current mbuf needs to be sent. So unaware functionality comes after integrating feature arc APIs. Regarding your rte_graph_walk() comment: IMO, decision of determining next_edge ( or next node) lies with each *node* and not with rte_graph_walk(). Feature arc is extending the functionality of determining next_edge to control plane as well (as control plane enables/disable features). This way without changing feature node code, control plane is able to steer packets to different nodes. This is the major functionality feature arc is trying to simplify > Yet, in the series, the nodes need to be aware if a feature arc is enabled or > not. > Isn’t this a contradiction or did I miss something ? > > Christophe > > > > > 4. Allow expressing features in a particular sequential order so that > > packets are steered in an ordered way across nodes in fast path. For > > eg: if IPsec and IPv4 features are enabled on an ingress interface, > > packets must be sent to IPsec inbound policy node first and then to > > ipv4 lookup node. > > > > This patch series adds feature arc library in rte_graph and also adds > > "ipv4-output" feature arc handling in "ipv4-rewrite" node. > > > > Changes in v3: > > - rte_graph_feature_arc_t typedef from uint64_t to uintptr_t to fix > > compilation on 32-bit machine > > - Updated images in .png format > > - Added ABI change section in release notes > > - Fixed DPDK CI failures > > > > Changes in v2: > > - Added unit tests for feature arc > > - Fixed issues found in testing > > - Added new public APIs rte_graph_feature_arc_feature_to_node(), > > rte_graph_feature_arc_feature_to_name(), > > rte_graph_feature_arc_num_features() > > - Added programming guide for feature arc > > - Added release notes for feature arc > > > > Nitin Saxena (5): > > graph: add feature arc support > > graph: add feature arc option in graph create > > graph: add IPv4 output feature arc > > test/graph_feature_arc: add functional tests > > docs: add programming guide for feature arc > > > > app/test/meson.build | 1 + > > app/test/test_graph_feature_arc.c | 1410 +++++++++++++++++++ > > doc/guides/prog_guide/graph_lib.rst | 288 ++++ > > doc/guides/prog_guide/img/feature_arc-1.png | Bin 0 -> 61532 bytes > > doc/guides/prog_guide/img/feature_arc-2.png | Bin 0 -> 155806 bytes > > doc/guides/prog_guide/img/feature_arc-3.png | Bin 0 -> 143697 bytes > > doc/guides/rel_notes/release_24_11.rst | 13 + > > lib/graph/graph.c | 1 + > > lib/graph/graph_feature_arc.c | 1223 ++++++++++++++++ > > lib/graph/graph_populate.c | 7 +- > > lib/graph/graph_private.h | 3 + > > lib/graph/meson.build | 2 + > > lib/graph/node.c | 2 + > > lib/graph/rte_graph.h | 3 + > > lib/graph/rte_graph_feature_arc.h | 431 ++++++ > > lib/graph/rte_graph_feature_arc_worker.h | 674 +++++++++ > > lib/graph/version.map | 20 + > > lib/node/ip4_rewrite.c | 476 +++++-- > > lib/node/ip4_rewrite_priv.h | 15 +- > > lib/node/node_private.h | 20 +- > > lib/node/rte_node_ip4_api.h | 3 + > > 21 files changed, 4494 insertions(+), 98 deletions(-) create mode > > 100644 app/test/test_graph_feature_arc.c create mode 100644 > > doc/guides/prog_guide/img/feature_arc-1.png > > create mode 100644 doc/guides/prog_guide/img/feature_arc-2.png > > create mode 100644 doc/guides/prog_guide/img/feature_arc-3.png > > create mode 100644 lib/graph/graph_feature_arc.c create mode 100644 > > lib/graph/rte_graph_feature_arc.h create mode 100644 > > lib/graph/rte_graph_feature_arc_worker.h > > > > -- > > 2.43.0 > > ^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [PATCH v3 0/5] add feature arc in rte_graph 2024-10-09 13:29 ` [PATCH v3 0/5] add feature arc in rte_graph Nitin Saxena ` (5 preceding siblings ...) 2024-10-09 14:21 ` [PATCH v3 0/5] add feature arc in rte_graph Christophe Fontaine @ 2024-10-09 17:37 ` Stephen Hemminger 2024-10-10 4:24 ` [EXTERNAL] " Nitin Saxena 2024-10-10 13:31 ` [PATCH v4 " Nitin Saxena 7 siblings, 1 reply; 46+ messages in thread From: Stephen Hemminger @ 2024-10-09 17:37 UTC (permalink / raw) To: Nitin Saxena Cc: Jerin Jacob, Kiran Kumar K, Nithin Dabilpuram, Zhirun Yan, Robin Jarry, Christophe Fontaine, dev, Nitin Saxena On Wed, 9 Oct 2024 18:59:57 +0530 Nitin Saxena <nsaxena@marvell.com> wrote: > Feature arc represents an ordered list of features/protocols at a given > networking layer. It is a high level abstraction to connect various > rte_graph nodes, as feature nodes, and allow packets steering across > these nodes in a generic manner. > > Features (or feature nodes) are nodes which handles partial or complete > handling of a protocol in fast path. Like ipv4-rewrite node, which adds > rewrite data to an outgoing IPv4 packet. > > However in above example, outgoing interface(say "eth0") may have > outbound IPsec policy enabled, hence packets must be steered from > ipv4-rewrite node to ipsec-outbound-policy node for outbound IPsec > policy lookup. On the other hand, packets routed to another interface > (eth1) will not be sent to ipsec-outbound-policy node as IPsec feature > is disabled on eth1. Feature-arc allows rte_graph applications to manage > such constraints easily > > Feature arc abstraction allows rte_graph based application to > > 1. Seamlessly steer packets across feature nodes based on whether > feature is enabled or disabled on an interface. Features enabled on one > interface may not be enabled on another interface with in a same feature > arc. > > 2. Allow enabling/disabling of features on an interface at runtime, > so that if a feature is disabled, packets associated with that interface > won't be steered to corresponding feature node. > > 3. Provides mechanism to hook custom/user-defined nodes to a feature > node and allow packet steering from feature node to custom node without > changing former's fast path function > > 4. Allow expressing features in a particular sequential order so that > packets are steered in an ordered way across nodes in fast path. For > eg: if IPsec and IPv4 features are enabled on an ingress interface, > packets must be sent to IPsec inbound policy node first and then to ipv4 > lookup node. > > This patch series adds feature arc library in rte_graph and also adds > "ipv4-output" feature arc handling in "ipv4-rewrite" node. > > Changes in v3: > - rte_graph_feature_arc_t typedef from uint64_t to uintptr_t to fix > compilation on 32-bit machine > - Updated images in .png format > - Added ABI change section in release notes > - Fixed DPDK CI failures > > Changes in v2: > - Added unit tests for feature arc > - Fixed issues found in testing > - Added new public APIs rte_graph_feature_arc_feature_to_node(), > rte_graph_feature_arc_feature_to_name(), > rte_graph_feature_arc_num_features() > - Added programming guide for feature arc > - Added release notes for feature arc > > Nitin Saxena (5): > graph: add feature arc support > graph: add feature arc option in graph create > graph: add IPv4 output feature arc > test/graph_feature_arc: add functional tests > docs: add programming guide for feature arc > > app/test/meson.build | 1 + > app/test/test_graph_feature_arc.c | 1410 +++++++++++++++++++ > doc/guides/prog_guide/graph_lib.rst | 288 ++++ > doc/guides/prog_guide/img/feature_arc-1.png | Bin 0 -> 61532 bytes > doc/guides/prog_guide/img/feature_arc-2.png | Bin 0 -> 155806 bytes > doc/guides/prog_guide/img/feature_arc-3.png | Bin 0 -> 143697 bytes > doc/guides/rel_notes/release_24_11.rst | 13 + > lib/graph/graph.c | 1 + > lib/graph/graph_feature_arc.c | 1223 ++++++++++++++++ > lib/graph/graph_populate.c | 7 +- > lib/graph/graph_private.h | 3 + > lib/graph/meson.build | 2 + > lib/graph/node.c | 2 + > lib/graph/rte_graph.h | 3 + > lib/graph/rte_graph_feature_arc.h | 431 ++++++ > lib/graph/rte_graph_feature_arc_worker.h | 674 +++++++++ > lib/graph/version.map | 20 + > lib/node/ip4_rewrite.c | 476 +++++-- > lib/node/ip4_rewrite_priv.h | 15 +- > lib/node/node_private.h | 20 +- > lib/node/rte_node_ip4_api.h | 3 + > 21 files changed, 4494 insertions(+), 98 deletions(-) > create mode 100644 app/test/test_graph_feature_arc.c > create mode 100644 doc/guides/prog_guide/img/feature_arc-1.png > create mode 100644 doc/guides/prog_guide/img/feature_arc-2.png > create mode 100644 doc/guides/prog_guide/img/feature_arc-3.png > create mode 100644 lib/graph/graph_feature_arc.c > create mode 100644 lib/graph/rte_graph_feature_arc.h > create mode 100644 lib/graph/rte_graph_feature_arc_worker.h > Looks good, but likely missing an RTE_ATOMIC() around the feature enable bitmask. Build fails: #################################################################################### #### [Begin job log] "ubuntu-22.04-clang-stdatomic" at step Build and test #################################################################################### rte_atomic_store_explicit(&arc->feature_enable_bitmask[passive_list], bitmask, ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ../lib/eal/include/rte_stdatomic.h:76:2: note: expanded from macro 'rte_atomic_store_explicit' atomic_store_explicit(ptr, val, memorder) ^ ~~~ /usr/lib/llvm-14/lib/clang/14.0.0/include/stdatomic.h:127:31: note: expanded from macro 'atomic_store_explicit' #define atomic_store_explicit __c11_atomic_store ^ ../lib/graph/graph_feature_arc.c:1084:2: error: address argument to atomic operation must be a pointer to _Atomic type ('rte_graph_feature_rt_list_t *' (aka 'unsigned short *') invalid) rte_atomic_store_explicit(&arc->active_feature_list, passive_list, ^ ~~~~~~~~~~~~~~~~~~~~~~~~~ ../lib/eal/include/rte_stdatomic.h:76:2: note: expanded from macro 'rte_atomic_store_explicit' atomic_store_explicit(ptr, val, memorder) ^ ~~~ /usr/lib/llvm-14/lib/clang/14.0.0/include/stdatomic.h:127:31: note: expanded from macro 'atomic_store_explicit' #define atomic_store_explicit __c11_atomic_store ^ 10 errors generated. ^ permalink raw reply [flat|nested] 46+ messages in thread
* RE: [EXTERNAL] Re: [PATCH v3 0/5] add feature arc in rte_graph 2024-10-09 17:37 ` Stephen Hemminger @ 2024-10-10 4:24 ` Nitin Saxena 0 siblings, 0 replies; 46+ messages in thread From: Nitin Saxena @ 2024-10-10 4:24 UTC (permalink / raw) To: Stephen Hemminger Cc: Jerin Jacob, Kiran Kumar Kokkilagadda, Nithin Kumar Dabilpuram, Zhirun Yan, Robin Jarry, Christophe Fontaine, dev, Nitin Saxena Thanks Stephen. Will fix compilation in next version. Thanks, Nitin > -----Original Message----- > From: Stephen Hemminger <stephen@networkplumber.org> > Sent: Wednesday, October 9, 2024 11:08 PM > To: Nitin Saxena <nsaxena@marvell.com> > Cc: Jerin Jacob <jerinj@marvell.com>; Kiran Kumar Kokkilagadda > <kirankumark@marvell.com>; Nithin Kumar Dabilpuram > <ndabilpuram@marvell.com>; Zhirun Yan <yanzhirun_163@163.com>; Robin > Jarry <rjarry@redhat.com>; Christophe Fontaine <cfontain@redhat.com>; > dev@dpdk.org; Nitin Saxena <nsaxena16@gmail.com> > Subject: [EXTERNAL] Re: [PATCH v3 0/5] add feature arc in rte_graph > > On Wed, 9 Oct 2024 18: 59: 57 +0530 Nitin Saxena <nsaxena@ marvell. com> > wrote: > Feature arc represents an ordered list of features/protocols at a given > > networking layer. It is a high level abstraction to connect various > rte_graph > > On Wed, 9 Oct 2024 18:59:57 +0530 > Nitin Saxena <nsaxena@marvell.com> wrote: > > > Feature arc represents an ordered list of features/protocols at a > > given networking layer. It is a high level abstraction to connect > > various rte_graph nodes, as feature nodes, and allow packets steering > > across these nodes in a generic manner. > > > > Features (or feature nodes) are nodes which handles partial or > > complete handling of a protocol in fast path. Like ipv4-rewrite node, > > which adds rewrite data to an outgoing IPv4 packet. > > > > However in above example, outgoing interface(say "eth0") may have > > outbound IPsec policy enabled, hence packets must be steered from > > ipv4-rewrite node to ipsec-outbound-policy node for outbound IPsec > > policy lookup. On the other hand, packets routed to another interface > > (eth1) will not be sent to ipsec-outbound-policy node as IPsec feature > > is disabled on eth1. Feature-arc allows rte_graph applications to > > manage such constraints easily > > > > Feature arc abstraction allows rte_graph based application to > > > > 1. Seamlessly steer packets across feature nodes based on whether > > feature is enabled or disabled on an interface. Features enabled on > > one interface may not be enabled on another interface with in a same > > feature arc. > > > > 2. Allow enabling/disabling of features on an interface at runtime, so > > that if a feature is disabled, packets associated with that interface > > won't be steered to corresponding feature node. > > > > 3. Provides mechanism to hook custom/user-defined nodes to a feature > > node and allow packet steering from feature node to custom node > > without changing former's fast path function > > > > 4. Allow expressing features in a particular sequential order so that > > packets are steered in an ordered way across nodes in fast path. For > > eg: if IPsec and IPv4 features are enabled on an ingress interface, > > packets must be sent to IPsec inbound policy node first and then to > > ipv4 lookup node. > > > > This patch series adds feature arc library in rte_graph and also adds > > "ipv4-output" feature arc handling in "ipv4-rewrite" node. > > > > Changes in v3: > > - rte_graph_feature_arc_t typedef from uint64_t to uintptr_t to fix > > compilation on 32-bit machine > > - Updated images in .png format > > - Added ABI change section in release notes > > - Fixed DPDK CI failures > > > > Changes in v2: > > - Added unit tests for feature arc > > - Fixed issues found in testing > > - Added new public APIs rte_graph_feature_arc_feature_to_node(), > > rte_graph_feature_arc_feature_to_name(), > > rte_graph_feature_arc_num_features() > > - Added programming guide for feature arc > > - Added release notes for feature arc > > > > Nitin Saxena (5): > > graph: add feature arc support > > graph: add feature arc option in graph create > > graph: add IPv4 output feature arc > > test/graph_feature_arc: add functional tests > > docs: add programming guide for feature arc > > > > app/test/meson.build | 1 + > > app/test/test_graph_feature_arc.c | 1410 +++++++++++++++++++ > > doc/guides/prog_guide/graph_lib.rst | 288 ++++ > > doc/guides/prog_guide/img/feature_arc-1.png | Bin 0 -> 61532 bytes > > doc/guides/prog_guide/img/feature_arc-2.png | Bin 0 -> 155806 bytes > > doc/guides/prog_guide/img/feature_arc-3.png | Bin 0 -> 143697 bytes > > doc/guides/rel_notes/release_24_11.rst | 13 + > > lib/graph/graph.c | 1 + > > lib/graph/graph_feature_arc.c | 1223 ++++++++++++++++ > > lib/graph/graph_populate.c | 7 +- > > lib/graph/graph_private.h | 3 + > > lib/graph/meson.build | 2 + > > lib/graph/node.c | 2 + > > lib/graph/rte_graph.h | 3 + > > lib/graph/rte_graph_feature_arc.h | 431 ++++++ > > lib/graph/rte_graph_feature_arc_worker.h | 674 +++++++++ > > lib/graph/version.map | 20 + > > lib/node/ip4_rewrite.c | 476 +++++-- > > lib/node/ip4_rewrite_priv.h | 15 +- > > lib/node/node_private.h | 20 +- > > lib/node/rte_node_ip4_api.h | 3 + > > 21 files changed, 4494 insertions(+), 98 deletions(-) create mode > > 100644 app/test/test_graph_feature_arc.c create mode 100644 > > doc/guides/prog_guide/img/feature_arc-1.png > > create mode 100644 doc/guides/prog_guide/img/feature_arc-2.png > > create mode 100644 doc/guides/prog_guide/img/feature_arc-3.png > > create mode 100644 lib/graph/graph_feature_arc.c create mode 100644 > > lib/graph/rte_graph_feature_arc.h create mode 100644 > > lib/graph/rte_graph_feature_arc_worker.h > > > > Looks good, but likely missing an RTE_ATOMIC() around the feature enable > bitmask. > Build fails: > > ################################################################ > #################### > #### [Begin job log] "ubuntu-22.04-clang-stdatomic" at step Build and test > ################################################################ > #################### > rte_atomic_store_explicit(&arc->feature_enable_bitmask[passive_list], > bitmask, > ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > ../lib/eal/include/rte_stdatomic.h:76:2: note: expanded from macro > 'rte_atomic_store_explicit' > atomic_store_explicit(ptr, val, memorder) > ^ ~~~ > /usr/lib/llvm-14/lib/clang/14.0.0/include/stdatomic.h:127:31: note: expanded > from macro 'atomic_store_explicit' > #define atomic_store_explicit __c11_atomic_store > ^ > ../lib/graph/graph_feature_arc.c:1084:2: error: address argument to atomic > operation must be a pointer to _Atomic type ('rte_graph_feature_rt_list_t *' > (aka 'unsigned short *') invalid) > rte_atomic_store_explicit(&arc->active_feature_list, passive_list, > ^ ~~~~~~~~~~~~~~~~~~~~~~~~~ > ../lib/eal/include/rte_stdatomic.h:76:2: note: expanded from macro > 'rte_atomic_store_explicit' > atomic_store_explicit(ptr, val, memorder) > ^ ~~~ > /usr/lib/llvm-14/lib/clang/14.0.0/include/stdatomic.h:127:31: note: expanded > from macro 'atomic_store_explicit' > #define atomic_store_explicit __c11_atomic_store > ^ > 10 errors generated. ^ permalink raw reply [flat|nested] 46+ messages in thread
* [PATCH v4 0/5] add feature arc in rte_graph 2024-10-09 13:29 ` [PATCH v3 0/5] add feature arc in rte_graph Nitin Saxena ` (6 preceding siblings ...) 2024-10-09 17:37 ` Stephen Hemminger @ 2024-10-10 13:31 ` Nitin Saxena 2024-10-10 13:31 ` [PATCH v4 1/5] graph: add feature arc support Nitin Saxena ` (5 more replies) 7 siblings, 6 replies; 46+ messages in thread From: Nitin Saxena @ 2024-10-10 13:31 UTC (permalink / raw) To: Jerin Jacob, Kiran Kumar K, Nithin Dabilpuram, Zhirun Yan, Robin Jarry, Christophe Fontaine Cc: dev, Nitin Saxena Feature arc represents an ordered list of features/protocols at a given networking layer. It is a high level abstraction to connect various rte_graph nodes, as feature nodes, and allow packets steering across these nodes in a generic manner. Features (or feature nodes) are nodes which handles partial or complete handling of a protocol in fast path. Like ipv4-rewrite node, which adds rewrite data to an outgoing IPv4 packet. However in above example, outgoing interface(say "eth0") may have outbound IPsec policy enabled, hence packets must be steered from ipv4-rewrite node to ipsec-outbound-policy node for outbound IPsec policy lookup. On the other hand, packets routed to another interface (eth1) will not be sent to ipsec-outbound-policy node as IPsec feature is disabled on eth1. Feature-arc allows rte_graph applications to manage such constraints easily Feature arc abstraction allows rte_graph based application to 1. Seamlessly steer packets across feature nodes based on whether feature is enabled or disabled on an interface. Features enabled on one interface may not be enabled on another interface with in a same feature arc. 2. Allow enabling/disabling of features on an interface at runtime, so that if a feature is disabled, packets associated with that interface won't be steered to corresponding feature node. 3. Provides mechanism to hook custom/user-defined nodes to a feature node and allow packet steering from feature node to custom node without changing former's fast path function 4. Allow expressing features in a particular sequential order so that packets are steered in an ordered way across nodes in fast path. For eg: if IPsec and IPv4 features are enabled on an ingress interface, packets must be sent to IPsec inbound policy node first and then to ipv4 lookup node. This patch series adds feature arc library in rte_graph and also adds "ipv4-output" feature arc handling in "ipv4-rewrite" node. Changes in v4: - Fixed clang build compilations - Captured `feat_arc_proc` function in ABI change section of release notes Changes in v3: - rte_graph_feature_arc_t typedef from uint64_t to uintptr_t to fix compilation on 32-bit machine - Updated images in .png format - Added ABI change section in release notes - Fixed DPDK CI failures Changes in v2: - Added unit tests for feature arc - Fixed issues found in testing - Added new public APIs rte_graph_feature_arc_feature_to_node(), rte_graph_feature_arc_feature_to_name(), rte_graph_feature_arc_num_features() - Added programming guide for feature arc - Added release notes for feature arc Nitin Saxena (5): graph: add feature arc support graph: add feature arc option in graph create graph: add IPv4 output feature arc test/graph_feature_arc: add functional tests docs: add programming guide for feature arc app/test/meson.build | 1 + app/test/test_graph_feature_arc.c | 1410 +++++++++++++++++++ doc/guides/prog_guide/graph_lib.rst | 288 ++++ doc/guides/prog_guide/img/feature_arc-1.png | Bin 0 -> 61532 bytes doc/guides/prog_guide/img/feature_arc-2.png | Bin 0 -> 155806 bytes doc/guides/prog_guide/img/feature_arc-3.png | Bin 0 -> 143697 bytes doc/guides/rel_notes/release_24_11.rst | 17 + lib/graph/graph.c | 1 + lib/graph/graph_feature_arc.c | 1236 ++++++++++++++++ lib/graph/graph_populate.c | 7 +- lib/graph/graph_private.h | 3 + lib/graph/meson.build | 2 + lib/graph/node.c | 2 + lib/graph/rte_graph.h | 3 + lib/graph/rte_graph_feature_arc.h | 431 ++++++ lib/graph/rte_graph_feature_arc_worker.h | 679 +++++++++ lib/graph/version.map | 20 + lib/node/ip4_rewrite.c | 476 +++++-- lib/node/ip4_rewrite_priv.h | 15 +- lib/node/node_private.h | 20 +- lib/node/rte_node_ip4_api.h | 3 + 21 files changed, 4516 insertions(+), 98 deletions(-) create mode 100644 app/test/test_graph_feature_arc.c create mode 100644 doc/guides/prog_guide/img/feature_arc-1.png create mode 100644 doc/guides/prog_guide/img/feature_arc-2.png create mode 100644 doc/guides/prog_guide/img/feature_arc-3.png create mode 100644 lib/graph/graph_feature_arc.c create mode 100644 lib/graph/rte_graph_feature_arc.h create mode 100644 lib/graph/rte_graph_feature_arc_worker.h -- 2.43.0 ^ permalink raw reply [flat|nested] 46+ messages in thread
* [PATCH v4 1/5] graph: add feature arc support 2024-10-10 13:31 ` [PATCH v4 " Nitin Saxena @ 2024-10-10 13:31 ` Nitin Saxena 2024-10-10 13:31 ` [PATCH v4 2/5] graph: add feature arc option in graph create Nitin Saxena ` (4 subsequent siblings) 5 siblings, 0 replies; 46+ messages in thread From: Nitin Saxena @ 2024-10-10 13:31 UTC (permalink / raw) To: Jerin Jacob, Kiran Kumar K, Nithin Dabilpuram, Zhirun Yan, Robin Jarry, Christophe Fontaine Cc: dev, Nitin Saxena add feature arc to allow dynamic steering of packets across graph nodes based on protocol features enabled on incoming or outgoing interface Signed-off-by: Nitin Saxena <nsaxena@marvell.com> --- doc/guides/rel_notes/release_24_11.rst | 10 + lib/graph/graph_feature_arc.c | 1236 ++++++++++++++++++++++ lib/graph/meson.build | 2 + lib/graph/rte_graph_feature_arc.h | 431 ++++++++ lib/graph/rte_graph_feature_arc_worker.h | 679 ++++++++++++ lib/graph/version.map | 20 + 6 files changed, 2378 insertions(+) create mode 100644 lib/graph/graph_feature_arc.c create mode 100644 lib/graph/rte_graph_feature_arc.h create mode 100644 lib/graph/rte_graph_feature_arc_worker.h diff --git a/doc/guides/rel_notes/release_24_11.rst b/doc/guides/rel_notes/release_24_11.rst index 2f78f2d125..bd5589b01c 100644 --- a/doc/guides/rel_notes/release_24_11.rst +++ b/doc/guides/rel_notes/release_24_11.rst @@ -82,6 +82,16 @@ New Features The new statistics are useful for debugging and profiling. +* **Added feature arc abstraction in graph library.** + + Feature arc abstraction helps ``rte_graph`` based applications to steer + packets across different node path(s) based on the features (or protocols) + enabled on interfaces. Different feature node paths can be enabled/disabled + at runtime on some or on all interfaces. This abstraction also help + applications to hook their ``custom nodes`` in standard DPDK node paths + without any code changes in the later. + + * Added ``ip4-output`` feature arc processing in ``ip4_rewrite`` node. Removed Items ------------- diff --git a/lib/graph/graph_feature_arc.c b/lib/graph/graph_feature_arc.c new file mode 100644 index 0000000000..0f8633c317 --- /dev/null +++ b/lib/graph/graph_feature_arc.c @@ -0,0 +1,1236 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(C) 2024 Marvell International Ltd. + */ + +#include "graph_private.h" +#include <rte_graph_feature_arc_worker.h> +#include <rte_malloc.h> + +#define ARC_PASSIVE_LIST(list) (list ^ 0x1) + +#define rte_graph_uint_cast(x) ((unsigned int)x) +#define feat_dbg graph_dbg + +static rte_graph_feature_arc_main_t *__rte_graph_feature_arc_main; + +/* Make sure fast path cache line is compact */ +_Static_assert((offsetof(struct rte_graph_feature_arc, slow_path_variables) + - offsetof(struct rte_graph_feature_arc, fast_path_variables)) + <= RTE_CACHE_LINE_SIZE, + "Fast path feature arc variables exceed cache line size"); + +#define connect_graph_nodes(node1, node2, edge, arc_name) \ + __connect_graph_nodes(node1, node2, edge, arc_name, __LINE__) + +#define FEAT_COND_ERR(cond, fmt, ...) \ + do { \ + if (cond) \ + graph_err(fmt, ##__VA_ARGS__); \ + } while (0) + +/* + * lookup feature name and get control path node_list as well as feature index + * at which it is inserted + */ +static int +feature_lookup(struct rte_graph_feature_arc *arc, const char *feat_name, + struct rte_graph_feature_node_list **ffinfo, uint32_t *slot) +{ + struct rte_graph_feature_node_list *finfo = NULL; + const char *name; + uint32_t fi = 0; + + if (!feat_name) + return -1; + + if (slot) + *slot = UINT32_MAX; + + STAILQ_FOREACH(finfo, &arc->all_features, next_feature) { + RTE_VERIFY(finfo->feature_arc == arc); + name = rte_node_id_to_name(finfo->feature_node->id); + if (!strncmp(name, feat_name, strlen(name))) { + if (ffinfo) + *ffinfo = finfo; + if (slot) + *slot = fi; + return 0; + } + fi++; + } + return -1; +} + +/* Lookup used only during rte_graph_feature_add() */ +static int +feature_add_lookup(struct rte_graph_feature_arc *arc, const char *feat_name, + struct rte_graph_feature_node_list **ffinfo, uint32_t *slot) +{ + struct rte_graph_feature_node_list *finfo = NULL; + const char *name; + uint32_t fi = 0; + + if (!feat_name) + return -1; + + if (slot) + *slot = 0; + + STAILQ_FOREACH(finfo, &arc->all_features, next_feature) { + RTE_VERIFY(finfo->feature_arc == arc); + name = rte_node_id_to_name(finfo->feature_node->id); + if (!strncmp(name, feat_name, strlen(name))) { + if (ffinfo) + *ffinfo = finfo; + if (slot) + *slot = fi; + return 0; + } + /* Update slot where new feature can be added */ + if (slot) + *slot = fi; + fi++; + } + + return -1; +} + +/* Get control path node info from provided input feature_index */ +static int +feature_arc_node_info_lookup(struct rte_graph_feature_arc *arc, uint32_t feature_index, + struct rte_graph_feature_node_list **ppfinfo, + const int do_sanity_check) +{ + struct rte_graph_feature_node_list *finfo = NULL; + uint32_t index = 0; + + if (!ppfinfo) + return -1; + + *ppfinfo = NULL; + STAILQ_FOREACH(finfo, &arc->all_features, next_feature) { + /* Check sanity */ + if (do_sanity_check) + if (finfo->node_index != index) + RTE_VERIFY(0); + if (index == feature_index) { + *ppfinfo = finfo; + return 0; + } + index++; + } + return -1; +} + +/* prepare feature arc after addition of all features */ +static void +prepare_feature_arc_before_first_enable(struct rte_graph_feature_arc *arc) +{ + struct rte_graph_feature_node_list *finfo = NULL; + uint32_t index = 0; + + rte_atomic_store_explicit(&arc->active_feature_list, 0, + rte_memory_order_relaxed); + + STAILQ_FOREACH(finfo, &arc->all_features, next_feature) { + finfo->node_index = index; + feat_dbg("\t%s prepare: %s added to list at index: %u", arc->feature_arc_name, + finfo->feature_node->name, index); + index++; + } +} + +/* feature arc lookup in array */ +static int +feature_arc_lookup(rte_graph_feature_arc_t _arc) +{ + struct rte_graph_feature_arc *arc = rte_graph_feature_arc_get(_arc); + rte_graph_feature_arc_main_t *dm = __rte_graph_feature_arc_main; + uint32_t iter; + + if (!__rte_graph_feature_arc_main) + return -1; + + for (iter = 0; iter < dm->max_feature_arcs; iter++) { + if (dm->feature_arcs[iter] == RTE_GRAPH_FEATURE_ARC_INITIALIZER) + continue; + + if (arc == (rte_graph_feature_arc_get(dm->feature_arcs[iter]))) + return 0; + } + return -1; +} + +/* Check valid values for known fields in arc to make sure arc is sane */ +static int check_feature_arc_sanity(rte_graph_feature_arc_t _arc, int iter) +{ +#ifdef FEATURE_ARC_DEBUG + struct rte_graph_feature_arc *arc = rte_graph_feature_arc_get(_arc); + + RTE_VERIFY(arc->feature_arc_main == __rte_graph_feature_arc_main); + RTE_VERIFY(arc->feature_arc_index == iter); + + RTE_VERIFY(arc->feature_list[0]->indexed_by_features = arc->features[0]); + RTE_VERIFY(arc->feature_list[1]->indexed_by_features = arc->features[1]); + + RTE_VERIFY(rte_atomic_load_explicit(&arc->active_feature_list, + rte_memory_order_relaxed) < 2); +#else + RTE_SET_USED(_arc); + RTE_SET_USED(iter); +#endif + return 0; +} + +/* Perform sanity on all arc if any corruption occurred */ +static int do_sanity_all_arcs(void) +{ + rte_graph_feature_arc_main_t *dm = __rte_graph_feature_arc_main; + uint32_t iter; + + if (!dm) + return -1; + + for (iter = 0; iter < dm->max_feature_arcs; iter++) { + if (dm->feature_arcs[iter] == RTE_GRAPH_FEATURE_ARC_INITIALIZER) + continue; + + if (check_feature_arc_sanity(dm->feature_arcs[iter], iter)) + return -1; + } + return 0; +} + +/* get existing edge from parent_node -> child_node */ +static int +get_existing_edge(const char *arc_name, struct rte_node_register *parent_node, + struct rte_node_register *child_node, rte_edge_t *_edge) +{ + char **next_edges = NULL; + uint32_t i, count = 0; + + RTE_SET_USED(arc_name); + + count = rte_node_edge_get(parent_node->id, NULL); + + if (!count) + return -1; + + next_edges = malloc(count); + + if (!next_edges) + return -1; + + count = rte_node_edge_get(parent_node->id, next_edges); + for (i = 0; i < count; i++) { + if (strstr(child_node->name, next_edges[i])) { + if (_edge) + *_edge = (rte_edge_t)i; + + free(next_edges); + return 0; + } + } + free(next_edges); + + return -1; +} + +/* create or retrieve already existing edge from parent_node -> child_node */ +static int +__connect_graph_nodes(struct rte_node_register *parent_node, struct rte_node_register *child_node, + rte_edge_t *_edge, char *arc_name, int lineno) +{ + const char *next_node = NULL; + rte_edge_t edge; + + if (!get_existing_edge(arc_name, parent_node, child_node, &edge)) { + feat_dbg("\t%s/%d: %s[%u]: \"%s\", edge reused", arc_name, lineno, + parent_node->name, edge, child_node->name); + + if (_edge) + *_edge = edge; + + return 0; + } + + /* Node to be added */ + next_node = child_node->name; + + edge = rte_node_edge_update(parent_node->id, RTE_EDGE_ID_INVALID, &next_node, 1); + + if (edge == RTE_EDGE_ID_INVALID) { + graph_err("edge invalid"); + return -1; + } + edge = rte_node_edge_count(parent_node->id) - 1; + + feat_dbg("\t%s/%d: %s[%u]: \"%s\", new edge added", arc_name, lineno, parent_node->name, + edge, child_node->name); + + if (_edge) + *_edge = edge; + + return 0; +} + +/* feature arc initialization */ +static int +feature_arc_main_init(rte_graph_feature_arc_main_t **pfl, uint32_t max_feature_arcs) +{ + rte_graph_feature_arc_main_t *pm = NULL; + uint32_t i; + size_t sz; + + if (!pfl) + return -1; + + sz = sizeof(rte_graph_feature_arc_main_t) + + (sizeof(pm->feature_arcs[0]) * max_feature_arcs); + + pm = rte_malloc("rte_graph_feature_arc_main", sz, 0); + if (!pm) + return -1; + + memset(pm, 0, sz); + + for (i = 0; i < max_feature_arcs; i++) + pm->feature_arcs[i] = RTE_GRAPH_FEATURE_ARC_INITIALIZER; + + pm->max_feature_arcs = max_feature_arcs; + + *pfl = pm; + + return 0; +} + +/* feature arc initialization, public API */ +int +rte_graph_feature_arc_init(int max_feature_arcs) +{ + if (!max_feature_arcs) + return -1; + + if (__rte_graph_feature_arc_main) + return -1; + + return feature_arc_main_init(&__rte_graph_feature_arc_main, max_feature_arcs); +} + +/* reset feature list before switching to passive list */ +static void +feature_arc_list_reset(struct rte_graph_feature_arc *arc, uint32_t list_index) +{ + rte_graph_feature_data_t *fdata = NULL; + rte_graph_feature_list_t *list = NULL; + struct rte_graph_feature *feat = NULL; + uint32_t i, j; + + list = arc->feature_list[list_index]; + feat = arc->features[list_index]; + + /*Initialize variables*/ + memset(feat, 0, arc->feature_size * arc->max_features); + memset(list, 0, arc->feature_list_size); + + /* Initialize feature and feature_data */ + for (i = 0; i < arc->max_features; i++) { + feat = __rte_graph_feature_get(arc, i, list_index); + feat->this_feature_index = i; + + for (j = 0; j < arc->max_indexes; j++) { + fdata = rte_graph_feature_data_get(arc, feat, j); + fdata->next_enabled_feature = RTE_GRAPH_FEATURE_INVALID; + fdata->next_edge = UINT16_MAX; + fdata->user_data = UINT32_MAX; + } + } + + for (i = 0; i < arc->max_indexes; i++) + list->first_enabled_feature_by_index[i] = RTE_GRAPH_FEATURE_INVALID; +} + +static int +feature_arc_list_init(struct rte_graph_feature_arc *arc, const char *flist_name, + rte_graph_feature_list_t **pplist, + struct rte_graph_feature **ppfeature, uint32_t list_index) +{ + char fname[2 * RTE_GRAPH_FEATURE_ARC_NAMELEN]; + size_t list_size, feat_size, fdata_size; + rte_graph_feature_list_t *list = NULL; + struct rte_graph_feature *feat = NULL; + + list_size = sizeof(struct rte_graph_feature_list) + + (sizeof(list->first_enabled_feature_by_index[0]) * arc->max_indexes); + + list_size = RTE_ALIGN_CEIL(list_size, RTE_CACHE_LINE_SIZE); + + list = rte_malloc(flist_name, list_size, RTE_CACHE_LINE_SIZE); + if (!list) + return -ENOMEM; + + memset(list, 0, list_size); + fdata_size = arc->max_indexes * sizeof(rte_graph_feature_data_t); + + /* Let one feature and its associated data per index capture complete + * cache lines + */ + feat_size = RTE_ALIGN_CEIL(sizeof(struct rte_graph_feature) + fdata_size, + RTE_CACHE_LINE_SIZE); + + snprintf(fname, sizeof(fname), "%s-%s", arc->feature_arc_name, "feat"); + + feat = rte_malloc(fname, feat_size * arc->max_features, RTE_CACHE_LINE_SIZE); + if (!feat) { + rte_free(list); + return -ENOMEM; + } + arc->feature_size = feat_size; + arc->feature_data_size = fdata_size; + arc->feature_list_size = list_size; + + /* Initialize list */ + list->indexed_by_features = feat; + *pplist = list; + *ppfeature = feat; + + feature_arc_list_reset(arc, list_index); + + return 0; +} + +/* free resources allocated in feature_arc_list_init() */ +static void +feature_arc_list_destroy(struct rte_graph_feature_arc *arc, int list_index) +{ + rte_graph_feature_list_t *list = NULL; + + list = arc->feature_list[list_index]; + + rte_free(list->indexed_by_features); + + arc->features[list_index] = NULL; + + rte_free(list); + + arc->feature_list[list_index] = NULL; +} + +int +rte_graph_feature_arc_create(const char *feature_arc_name, int max_features, int max_indexes, + struct rte_node_register *start_node, rte_graph_feature_arc_t *_arc) +{ + char name[2 * RTE_GRAPH_FEATURE_ARC_NAMELEN]; + struct rte_graph_feature_data *gfd = NULL; + rte_graph_feature_arc_main_t *dfm = NULL; + struct rte_graph_feature_arc *arc = NULL; + struct rte_graph_feature *df = NULL; + uint32_t iter, j, arc_index; + size_t sz; + + if (!_arc) + SET_ERR_JMP(EINVAL, err, "%s: Invalid _arc", feature_arc_name); + + if (max_features < 2) + SET_ERR_JMP(EINVAL, err, "%s: max_features must be greater than 1", + feature_arc_name); + + if (!start_node) + SET_ERR_JMP(EINVAL, err, "%s: start_node cannot be NULL", + feature_arc_name); + + if (!feature_arc_name) + SET_ERR_JMP(EINVAL, err, "%s: feature_arc name cannot be NULL", + feature_arc_name); + + if (max_features > RTE_GRAPH_FEATURE_MAX_PER_ARC) + SET_ERR_JMP(EAGAIN, err, "%s: number of features cannot be greater than 64", + feature_arc_name); + + /* + * Application hasn't called rte_graph_feature_arc_init(). Initialize with + * default values + */ + if (!__rte_graph_feature_arc_main) { + if (rte_graph_feature_arc_init((int)RTE_GRAPH_FEATURE_ARC_MAX) < 0) { + graph_err("rte_graph_feature_arc_init() failed"); + return -1; + } + } + + /* If name is not unique */ + if (!rte_graph_feature_arc_lookup_by_name(feature_arc_name, NULL)) + SET_ERR_JMP(EINVAL, err, "%s: feature arc name already exists", + feature_arc_name); + + dfm = __rte_graph_feature_arc_main; + + /* threshold check */ + if (dfm->num_feature_arcs > (dfm->max_feature_arcs - 1)) + SET_ERR_JMP(EAGAIN, err, "%s: max number (%u) of feature arcs reached", + feature_arc_name, dfm->max_feature_arcs); + + /* Find the free slot for feature arc */ + for (iter = 0; iter < dfm->max_feature_arcs; iter++) { + if (dfm->feature_arcs[iter] == RTE_GRAPH_FEATURE_ARC_INITIALIZER) + break; + } + arc_index = iter; + + if (arc_index >= dfm->max_feature_arcs) { + graph_err("No free slot found for num_feature_arc"); + return -1; + } + + /* This should not happen */ + RTE_VERIFY(dfm->feature_arcs[arc_index] == RTE_GRAPH_FEATURE_ARC_INITIALIZER); + + /* size of feature arc + feature_bit_mask_by_index */ + sz = RTE_ALIGN_CEIL(sizeof(*arc) + (sizeof(uint64_t) * max_indexes), RTE_CACHE_LINE_SIZE); + + arc = rte_malloc(feature_arc_name, sz, RTE_CACHE_LINE_SIZE); + + if (!arc) { + graph_err("malloc failed for feature_arc_create()"); + return -1; + } + + memset(arc, 0, sz); + + /* Initialize rte_graph port group fixed variables */ + STAILQ_INIT(&arc->all_features); + strncpy(arc->feature_arc_name, feature_arc_name, RTE_GRAPH_FEATURE_ARC_NAMELEN - 1); + arc->feature_arc_main = (void *)dfm; + arc->start_node = start_node; + arc->max_features = max_features; + arc->max_indexes = max_indexes; + arc->feature_arc_index = arc_index; + + snprintf(name, sizeof(name), "%s-%s", feature_arc_name, "flist0"); + + if (feature_arc_list_init(arc, name, &arc->feature_list[0], &arc->features[0], 0) < 0) { + rte_free(arc); + graph_err("feature_arc_list_init(0) failed"); + return -1; + } + snprintf(name, sizeof(name), "%s-%s", feature_arc_name, "flist1"); + + if (feature_arc_list_init(arc, name, &arc->feature_list[1], &arc->features[1], 1) < 0) { + feature_arc_list_destroy(arc, 0); + rte_free(arc); + graph_err("feature_arc_list_init(1) failed"); + return -1; + } + + for (iter = 0; iter < arc->max_features; iter++) { + df = rte_graph_feature_get(arc, iter); + for (j = 0; j < arc->max_indexes; j++) { + gfd = rte_graph_feature_data_get(arc, df, j); + gfd->next_enabled_feature = RTE_GRAPH_FEATURE_INVALID; + } + } + dfm->feature_arcs[arc->feature_arc_index] = (rte_graph_feature_arc_t)arc; + dfm->num_feature_arcs++; + + if (_arc) + *_arc = (rte_graph_feature_arc_t)arc; + + do_sanity_all_arcs(); + + feat_dbg("Feature arc %s[%p] created with max_features: %u and indexes: %u", + feature_arc_name, (void *)arc, max_features, max_indexes); + return 0; + +err: + return -rte_errno; +} + +int +rte_graph_feature_add(rte_graph_feature_arc_t _arc, struct rte_node_register *feature_node, + const char *_runs_after, const char *runs_before) +{ + struct rte_graph_feature_node_list *after_finfo = NULL, *before_finfo = NULL; + struct rte_graph_feature_arc *arc = rte_graph_feature_arc_get(_arc); + struct rte_graph_feature_node_list *temp = NULL, *finfo = NULL; + char feature_name[3*RTE_GRAPH_FEATURE_ARC_NAMELEN]; + const char *runs_after = NULL; + uint32_t num_feature = 0; + uint32_t slot, add_flag; + rte_edge_t edge = -1; + + /* sanity */ + if (arc->feature_arc_main != __rte_graph_feature_arc_main) { + graph_err("feature arc not created: 0x%016" PRIx64, (uint64_t)_arc); + return -1; + } + + if (feature_arc_lookup(_arc)) { + graph_err("invalid feature arc: 0x%016" PRIx64, (uint64_t)_arc); + return -1; + } + + if (arc->runtime_enabled_features) { + graph_err("adding features after enabling any one of them is not supported"); + return -1; + } + + if ((_runs_after != NULL) && (runs_before != NULL) && + (_runs_after == runs_before)) { + graph_err("runs_after and runs_before are same '%s:%s]", _runs_after, + runs_before); + return -1; + } + + if (!feature_node) { + graph_err("feature_node: %p invalid", feature_node); + return -1; + } + + arc = rte_graph_feature_arc_get(_arc); + + if (feature_node->id == RTE_NODE_ID_INVALID) { + graph_err("Invalid node: %s", feature_node->name); + return -1; + } + + if (!feature_add_lookup(arc, feature_node->name, &finfo, &slot)) { + graph_err("%s feature already added", feature_node->name); + return -1; + } + + if (slot >= arc->max_features) { + graph_err("%s: Max features %u added to feature arc", + arc->feature_arc_name, slot); + return -1; + } + + if (strstr(feature_node->name, arc->start_node->name)) { + graph_err("Feature %s cannot point to itself: %s", feature_node->name, + arc->start_node->name); + return -1; + } + + feat_dbg("%s: adding feature node: %s at feature index: %u", arc->feature_arc_name, + feature_node->name, slot); + + if (connect_graph_nodes(arc->start_node, feature_node, &edge, arc->feature_arc_name)) { + graph_err("unable to connect %s -> %s", arc->start_node->name, feature_node->name); + return -1; + } + + snprintf(feature_name, sizeof(feature_name), "%s-%s-finfo", + arc->feature_arc_name, feature_node->name); + + finfo = rte_malloc(feature_name, sizeof(*finfo), 0); + if (!finfo) { + graph_err("%s/%s: rte_malloc failed", arc->feature_arc_name, feature_node->name); + return -1; + } + + memset(finfo, 0, sizeof(*finfo)); + + finfo->feature_arc = (void *)arc; + finfo->feature_node = feature_node; + finfo->edge_to_this_feature = edge; + arc->runtime_enabled_features = 0; + + /* + * if no constraints given and provided feature is not the first feature, + * explicitly set "runs_after" as last_feature. Handles the case: + * + * add(f1, NULL, NULL); + * add(f2, NULL, NULL); + */ + num_feature = rte_graph_feature_arc_num_features(_arc); + if (!_runs_after && !runs_before && num_feature) + runs_after = rte_graph_feature_arc_feature_to_name(_arc, num_feature - 1); + else + runs_after = _runs_after; + + /* Check for before and after constraints */ + if (runs_before) { + /* runs_before sanity */ + if (feature_lookup(arc, runs_before, &before_finfo, NULL)) + SET_ERR_JMP(EINVAL, finfo_free, + "Invalid before feature name: %s", runs_before); + + if (!before_finfo) + SET_ERR_JMP(EINVAL, finfo_free, + "runs_before %s does not exist", runs_before); + + /* + * Starting from 0 to runs_before, continue connecting edges + */ + add_flag = 1; + STAILQ_FOREACH(temp, &arc->all_features, next_feature) { + if (!add_flag) + /* Nodes after seeing "runs_before", finfo connects to temp*/ + connect_graph_nodes(finfo->feature_node, temp->feature_node, + NULL, arc->feature_arc_name); + /* + * As soon as we see runs_before. stop adding edges + */ + if (!strncmp(temp->feature_node->name, runs_before, + RTE_GRAPH_NAMESIZE)) { + if (!connect_graph_nodes(finfo->feature_node, temp->feature_node, + &edge, arc->feature_arc_name)) + add_flag = 0; + } + + if (add_flag) + /* Nodes before seeing "run_before" are connected to finfo */ + connect_graph_nodes(temp->feature_node, finfo->feature_node, NULL, + arc->feature_arc_name); + } + } + + if (runs_after) { + if (feature_lookup(arc, runs_after, &after_finfo, NULL)) + SET_ERR_JMP(EINVAL, finfo_free, + "Invalid after feature_name %s", runs_after); + + if (!after_finfo) + SET_ERR_JMP(EINVAL, finfo_free, + "runs_after %s does not exist", runs_after); + + /* Starting from runs_after to end continue connecting edges */ + add_flag = 0; + STAILQ_FOREACH(temp, &arc->all_features, next_feature) { + if (add_flag) + /* We have already seen runs_after now */ + /* Add all features as next node to current feature*/ + connect_graph_nodes(finfo->feature_node, temp->feature_node, NULL, + arc->feature_arc_name); + else + /* Connect initial nodes to newly added node*/ + connect_graph_nodes(temp->feature_node, finfo->feature_node, NULL, + arc->feature_arc_name); + + /* as soon as we see runs_after. start adding edges + * from next iteration + */ + if (!strncmp(temp->feature_node->name, runs_after, RTE_GRAPH_NAMESIZE)) + add_flag = 1; + } + + /* add feature next to runs_after */ + STAILQ_INSERT_AFTER(&arc->all_features, after_finfo, finfo, next_feature); + } else { + if (before_finfo) { + /* add finfo before "before_finfo" element in the list */ + after_finfo = NULL; + STAILQ_FOREACH(temp, &arc->all_features, next_feature) { + if (before_finfo == temp) { + if (after_finfo) + STAILQ_INSERT_AFTER(&arc->all_features, after_finfo, + finfo, next_feature); + else + STAILQ_INSERT_HEAD(&arc->all_features, finfo, + next_feature); + + return 0; + } + after_finfo = temp; + } + } else { + /* Very first feature just needs to be added to list */ + STAILQ_INSERT_TAIL(&arc->all_features, finfo, next_feature); + } + } + + return 0; + +finfo_free: + rte_free(finfo); + + return -1; +} + +int +rte_graph_feature_lookup(rte_graph_feature_arc_t _arc, const char *feature_name, + rte_graph_feature_t *feat) +{ + struct rte_graph_feature_arc *arc = rte_graph_feature_arc_get(_arc); + struct rte_graph_feature_node_list *finfo = NULL; + uint32_t slot; + + if (!feature_lookup(arc, feature_name, &finfo, &slot)) { + *feat = (rte_graph_feature_t) slot; + return 0; + } + + return -1; +} + +int +rte_graph_feature_validate(rte_graph_feature_arc_t _arc, uint32_t index, const char *feature_name, + int is_enable_disable, bool emit_logs) +{ + struct rte_graph_feature_arc *arc = rte_graph_feature_arc_get(_arc); + struct rte_graph_feature_node_list *finfo = NULL; + rte_graph_feature_rt_list_t active_list; + struct rte_graph_feature *gf = NULL; + uint32_t slot; + + /* validate _arc */ + if (arc->feature_arc_main != __rte_graph_feature_arc_main) { + FEAT_COND_ERR(emit_logs, "invalid feature arc: 0x%016" PRIx64, (uint64_t)_arc); + return -EINVAL; + } + + /* validate index */ + if (index >= arc->max_indexes) { + FEAT_COND_ERR(emit_logs, "%s: Invalid provided index: %u >= %u configured", + arc->feature_arc_name, index, arc->max_indexes); + return -1; + } + + /* validate feature_name is already added or not */ + if (feature_lookup(arc, feature_name, &finfo, &slot)) { + FEAT_COND_ERR(emit_logs, "%s: No feature %s added", + arc->feature_arc_name, feature_name); + return -EINVAL; + } + + if (!finfo) { + FEAT_COND_ERR(emit_logs, "%s: No feature: %s found", + arc->feature_arc_name, feature_name); + return -EINVAL; + } + + /* slot should be in valid range */ + if (slot >= arc->max_features) { + FEAT_COND_ERR(emit_logs, "%s/%s: Invalid free slot %u(max=%u) for feature", + arc->feature_arc_name, feature_name, slot, arc->max_features); + return -EINVAL; + } + + /* slot should be in range of 0 - 63 */ + if (slot > (RTE_GRAPH_FEATURE_MAX_PER_ARC - 1)) { + FEAT_COND_ERR(emit_logs, "%s/%s: Invalid slot: %u", arc->feature_arc_name, + feature_name, slot); + return -EINVAL; + } + + if (finfo->node_index != slot) { + FEAT_COND_ERR(emit_logs, + "%s/%s: lookup slot mismatch for finfo idx: %u and lookup slot: %u", + arc->feature_arc_name, feature_name, finfo->node_index, slot); + return -1; + } + + active_list = rte_atomic_load_explicit(&arc->active_feature_list, + rte_memory_order_relaxed); + + /* Get feature from active list */ + gf = __rte_graph_feature_get(arc, slot, ARC_PASSIVE_LIST(active_list)); + if (gf->this_feature_index != slot) { + FEAT_COND_ERR(emit_logs, + "%s: %s rcvd feature_idx: %u does not match with saved: %u", + arc->feature_arc_name, feature_name, slot, gf->this_feature_index); + return -1; + } + + if (is_enable_disable && (arc->feature_bit_mask_by_index[index] & + RTE_BIT64(slot))) { + FEAT_COND_ERR(emit_logs, "%s: %s already enabled on index: %u", + arc->feature_arc_name, feature_name, index); + return -1; + } + + if (!is_enable_disable && !arc->runtime_enabled_features) { + FEAT_COND_ERR(emit_logs, "%s: No feature enabled to disable", + arc->feature_arc_name); + return -1; + } + + if (!is_enable_disable && !(arc->feature_bit_mask_by_index[index] & RTE_BIT64(slot))) { + FEAT_COND_ERR(emit_logs, "%s: %s not enabled in bitmask for index: %u", + arc->feature_arc_name, feature_name, index); + return -1; + } + + return 0; +} + +/* + * Before switch to passive list, user_data needs to be copied from active list to passive list + */ +static void +copy_fastpath_user_data(struct rte_graph_feature_arc *arc, uint16_t dest_list_index, + uint16_t src_list_index) +{ + rte_graph_feature_data_t *sgfd = NULL, *dgfd = NULL; + struct rte_graph_feature *sgf = NULL, *dgf = NULL; + uint32_t i, j; + + for (i = 0; i < arc->max_features; i++) { + sgf = __rte_graph_feature_get(arc, i, src_list_index); + dgf = __rte_graph_feature_get(arc, i, dest_list_index); + for (j = 0; j < arc->max_indexes; j++) { + sgfd = rte_graph_feature_data_get(arc, sgf, j); + dgfd = rte_graph_feature_data_get(arc, dgf, j); + dgfd->user_data = sgfd->user_data; + } + } +} +/* + * Fill fast path information like + * - next_edge + * - next_enabled_feature + */ +static void +refill_feature_fastpath_data(struct rte_graph_feature_arc *arc, uint16_t list_index) +{ + struct rte_graph_feature_node_list *finfo = NULL, *prev_finfo = NULL; + struct rte_graph_feature_data *gfd = NULL, *prev_gfd = NULL; + uint32_t fi = UINT32_MAX, di = UINT32_MAX, prev_fi = UINT32_MAX; + struct rte_graph_feature *gf = NULL, *prev_gf = NULL; + rte_graph_feature_list_t *flist = NULL; + rte_edge_t edge = UINT16_MAX; + uint64_t bitmask = 0; + + flist = arc->feature_list[list_index]; + + for (di = 0; di < arc->max_indexes; di++) { + bitmask = arc->feature_bit_mask_by_index[di]; + prev_fi = RTE_GRAPH_FEATURE_INVALID; + /* for each feature set for index, set fast path data */ + while (rte_bsf64_safe(bitmask, &fi)) { + gf = __rte_graph_feature_get(arc, fi, list_index); + gfd = rte_graph_feature_data_get(arc, gf, di); + RTE_VERIFY(!feature_arc_node_info_lookup(arc, fi, &finfo, 1)); + + /* If previous feature_index was valid in last loop */ + if (prev_fi != RTE_GRAPH_FEATURE_INVALID) { + prev_gf = __rte_graph_feature_get(arc, prev_fi, list_index); + prev_gfd = rte_graph_feature_data_get(arc, prev_gf, di); + /* + * Get edge of previous feature node connecting + * to this feature node + */ + RTE_VERIFY(!feature_arc_node_info_lookup(arc, prev_fi, + &prev_finfo, 1)); + if (!get_existing_edge(arc->feature_arc_name, + prev_finfo->feature_node, + finfo->feature_node, &edge)) { + feat_dbg("\t[%s/%u/di:%2u,cookie:%u]: (%u->%u)%s[%u] = %s", + arc->feature_arc_name, list_index, di, + prev_gfd->user_data, prev_fi, fi, + prev_finfo->feature_node->name, + edge, finfo->feature_node->name); + /* Copy feature index for next iteration*/ + gfd->next_edge = edge; + prev_fi = fi; + /* + * Fill current feature as next enabled + * feature to previous one + */ + prev_gfd->next_enabled_feature = fi; + } else { + /* Should not fail */ + RTE_VERIFY(0); + } + } + /* On first feature edge of the node to be added */ + if (fi == rte_bsf64(arc->feature_bit_mask_by_index[di])) { + if (!get_existing_edge(arc->feature_arc_name, arc->start_node, + finfo->feature_node, + &edge)) { + feat_dbg("\t[%s/%u/di:%2u,cookie:%u]: (->%u)%s[%u]=%s", + arc->feature_arc_name, list_index, di, + gfd->user_data, fi, + arc->start_node->name, edge, + finfo->feature_node->name); + /* Copy feature index for next iteration*/ + gfd->next_edge = edge; + prev_fi = fi; + /* Set first feature set array for index*/ + flist->first_enabled_feature_by_index[di] = + (rte_graph_feature_t)fi; + } else { + /* Should not fail */ + RTE_VERIFY(0); + } + } + /* Clear current feature index */ + bitmask &= ~RTE_BIT64(fi); + } + } +} + +int +rte_graph_feature_enable(rte_graph_feature_arc_t _arc, uint32_t index, const + char *feature_name, int32_t user_data) +{ + struct rte_graph_feature_arc *arc = rte_graph_feature_arc_get(_arc); + rte_graph_feature_rt_list_t passive_list, active_list; + struct rte_graph_feature_node_list *finfo = NULL; + struct rte_graph_feature_data *gfd = NULL; + struct rte_graph_feature *gf = NULL; + uint64_t bitmask; + uint32_t slot; + + feat_dbg("%s: Enabling feature: %s for index: %u", + arc->feature_arc_name, feature_name, index); + + if (!arc->runtime_enabled_features) + prepare_feature_arc_before_first_enable(arc); + + if (rte_graph_feature_validate(_arc, index, feature_name, 1, true)) + return -1; + + /** This should not fail as validate() has passed */ + if (feature_lookup(arc, feature_name, &finfo, &slot)) + RTE_VERIFY(0); + + active_list = rte_atomic_load_explicit(&arc->active_feature_list, + rte_memory_order_relaxed); + + passive_list = ARC_PASSIVE_LIST(active_list); + + feat_dbg("\t%s/%s: index: %u, passive list: %u, feature index: %u", + arc->feature_arc_name, feature_name, index, passive_list, slot); + + gf = __rte_graph_feature_get(arc, slot, passive_list); + gfd = rte_graph_feature_data_get(arc, gf, index); + + /* Reset feature list */ + feature_arc_list_reset(arc, passive_list); + + /* Copy user-data */ + copy_fastpath_user_data(arc, passive_list, active_list); + + /* Set current user-data */ + gfd->user_data = user_data; + + /* Set bitmask in control path bitmask */ + rte_bit_relaxed_set64(rte_graph_uint_cast(slot), &arc->feature_bit_mask_by_index[index]); + refill_feature_fastpath_data(arc, passive_list); + + /* If first time feature getting enabled */ + bitmask = rte_atomic_load_explicit(&arc->feature_enable_bitmask[active_list], + rte_memory_order_relaxed); + + /* On very first feature enable instance */ + if (!finfo->ref_count) + bitmask |= RTE_BIT64(slot); + + rte_atomic_store_explicit(&arc->feature_enable_bitmask[passive_list], + bitmask, rte_memory_order_relaxed); + + /* Slow path updates */ + arc->runtime_enabled_features++; + + /* Increase feature node info reference count */ + finfo->ref_count++; + + /* Store release semantics for active_list update */ + rte_atomic_store_explicit(&arc->active_feature_list, passive_list, + rte_memory_order_release); + + feat_dbg("%s/%s: After enable, switched active feature list to %u", + arc->feature_arc_name, feature_name, passive_list); + + return 0; +} + +int +rte_graph_feature_disable(rte_graph_feature_arc_t _arc, uint32_t index, const char *feature_name) +{ + struct rte_graph_feature_arc *arc = rte_graph_feature_arc_get(_arc); + rte_graph_feature_rt_list_t passive_list, active_list; + struct rte_graph_feature_data *gfd = NULL; + struct rte_graph_feature_node_list *finfo = NULL; + struct rte_graph_feature *gf = NULL; + uint64_t bitmask; + uint32_t slot; + + feat_dbg("%s: Disable feature: %s for index: %u", + arc->feature_arc_name, feature_name, index); + + if (rte_graph_feature_validate(_arc, index, feature_name, 0, true)) + return -1; + + if (feature_lookup(arc, feature_name, &finfo, &slot)) + return -1; + + active_list = rte_atomic_load_explicit(&arc->active_feature_list, + rte_memory_order_relaxed); + + passive_list = ARC_PASSIVE_LIST(active_list); + + gf = __rte_graph_feature_get(arc, slot, passive_list); + gfd = rte_graph_feature_data_get(arc, gf, index); + + feat_dbg("\t%s/%s: index: %u, passive list: %u, feature index: %u", + arc->feature_arc_name, feature_name, index, passive_list, slot); + + rte_bit_relaxed_clear64(rte_graph_uint_cast(slot), &arc->feature_bit_mask_by_index[index]); + + /* Reset feature list */ + feature_arc_list_reset(arc, passive_list); + + /* Copy user-data */ + copy_fastpath_user_data(arc, passive_list, active_list); + + /* Reset current user-data */ + gfd->user_data = ~0; + + refill_feature_fastpath_data(arc, passive_list); + + finfo->ref_count--; + arc->runtime_enabled_features--; + + /* If no feature enabled, reset feature in u64 fast path bitmask */ + bitmask = rte_atomic_load_explicit(&arc->feature_enable_bitmask[active_list], + rte_memory_order_relaxed); + + /* When last feature is disabled */ + if (!finfo->ref_count) + bitmask &= ~(RTE_BIT64(slot)); + + rte_atomic_store_explicit(&arc->feature_enable_bitmask[passive_list], bitmask, + rte_memory_order_relaxed); + + /* Store release semantics for active_list update */ + rte_atomic_store_explicit(&arc->active_feature_list, passive_list, + rte_memory_order_release); + + feat_dbg("%s/%s: After disable, switched active feature list to %u", + arc->feature_arc_name, feature_name, passive_list); + + return 0; +} + +int +rte_graph_feature_arc_destroy(rte_graph_feature_arc_t _arc) +{ + struct rte_graph_feature_arc *arc = rte_graph_feature_arc_get(_arc); + rte_graph_feature_arc_main_t *dm = __rte_graph_feature_arc_main; + struct rte_graph_feature_node_list *node_info = NULL; + + while (!STAILQ_EMPTY(&arc->all_features)) { + node_info = STAILQ_FIRST(&arc->all_features); + STAILQ_REMOVE_HEAD(&arc->all_features, next_feature); + rte_free(node_info); + } + feature_arc_list_destroy(arc, 0); + feature_arc_list_destroy(arc, 1); + + dm->feature_arcs[arc->feature_arc_index] = RTE_GRAPH_FEATURE_ARC_INITIALIZER; + + rte_free(arc); + + do_sanity_all_arcs(); + + return 0; +} + +int +rte_graph_feature_arc_cleanup(void) +{ + rte_graph_feature_arc_main_t *dm = __rte_graph_feature_arc_main; + uint32_t iter; + + if (!__rte_graph_feature_arc_main) + return -1; + + for (iter = 0; iter < dm->max_feature_arcs; iter++) { + if (dm->feature_arcs[iter] == RTE_GRAPH_FEATURE_ARC_INITIALIZER) + continue; + + rte_graph_feature_arc_destroy((rte_graph_feature_arc_t)dm->feature_arcs[iter]); + } + rte_free(dm); + + __rte_graph_feature_arc_main = NULL; + + return 0; +} + +int +rte_graph_feature_arc_lookup_by_name(const char *arc_name, rte_graph_feature_arc_t *_arc) +{ + rte_graph_feature_arc_main_t *dm = __rte_graph_feature_arc_main; + struct rte_graph_feature_arc *arc = NULL; + uint32_t iter; + + if (!__rte_graph_feature_arc_main) + return -1; + + if (_arc) + *_arc = RTE_GRAPH_FEATURE_ARC_INITIALIZER; + + for (iter = 0; iter < dm->max_feature_arcs; iter++) { + if (dm->feature_arcs[iter] == RTE_GRAPH_FEATURE_ARC_INITIALIZER) + continue; + + arc = rte_graph_feature_arc_get(dm->feature_arcs[iter]); + + if ((strstr(arc->feature_arc_name, arc_name)) && + (strlen(arc->feature_arc_name) == strlen(arc_name))) { + if (_arc) + *_arc = (rte_graph_feature_arc_t)arc; + return 0; + } + } + + return -1; +} + +uint32_t +rte_graph_feature_arc_num_enabled_features(rte_graph_feature_arc_t _arc) +{ + struct rte_graph_feature_arc *arc = rte_graph_feature_arc_get(_arc); + + return arc->runtime_enabled_features; +} + +uint32_t +rte_graph_feature_arc_num_features(rte_graph_feature_arc_t _arc) +{ + struct rte_graph_feature_arc *arc = rte_graph_feature_arc_get(_arc); + struct rte_graph_feature_node_list *finfo = NULL; + uint32_t count = 0; + + STAILQ_FOREACH(finfo, &arc->all_features, next_feature) + count++; + + return count; +} + +char * +rte_graph_feature_arc_feature_to_name(rte_graph_feature_arc_t _arc, rte_graph_feature_t feat) +{ + struct rte_graph_feature_arc *arc = rte_graph_feature_arc_get(_arc); + struct rte_graph_feature_node_list *finfo = NULL; + uint32_t slot = feat; + + if (feat >= rte_graph_feature_arc_num_features(_arc)) { + graph_err("%s: feature %u does not exist", arc->feature_arc_name, feat); + return NULL; + } + if (!feature_arc_node_info_lookup(arc, slot, &finfo, 0/* ignore sanity*/)) + return finfo->feature_node->name; + + return NULL; +} + +struct rte_node_register * +rte_graph_feature_arc_feature_to_node(rte_graph_feature_arc_t _arc, rte_graph_feature_t feat) +{ + struct rte_graph_feature_arc *arc = rte_graph_feature_arc_get(_arc); + struct rte_graph_feature_node_list *finfo = NULL; + uint32_t slot = feat; + + if (feat >= rte_graph_feature_arc_num_features(_arc)) { + graph_err("%s: feature %u does not exist", arc->feature_arc_name, feat); + return NULL; + } + if (!feature_arc_node_info_lookup(arc, slot, &finfo, 0/* ignore sanity*/)) + return finfo->feature_node; + + return NULL; + +} diff --git a/lib/graph/meson.build b/lib/graph/meson.build index 0cb15442ab..d916176fb7 100644 --- a/lib/graph/meson.build +++ b/lib/graph/meson.build @@ -14,11 +14,13 @@ sources = files( 'graph_debug.c', 'graph_stats.c', 'graph_populate.c', + 'graph_feature_arc.c', 'graph_pcap.c', 'rte_graph_worker.c', 'rte_graph_model_mcore_dispatch.c', ) headers = files('rte_graph.h', 'rte_graph_worker.h') +headers += files('rte_graph_feature_arc.h', 'rte_graph_feature_arc_worker.h') indirect_headers += files( 'rte_graph_model_mcore_dispatch.h', 'rte_graph_model_rtc.h', diff --git a/lib/graph/rte_graph_feature_arc.h b/lib/graph/rte_graph_feature_arc.h new file mode 100644 index 0000000000..1615f8e1c8 --- /dev/null +++ b/lib/graph/rte_graph_feature_arc.h @@ -0,0 +1,431 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(C) 2024 Marvell International Ltd. + */ + +#ifndef _RTE_GRAPH_FEATURE_ARC_H_ +#define _RTE_GRAPH_FEATURE_ARC_H_ + +#include <assert.h> +#include <errno.h> +#include <signal.h> +#include <stddef.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <rte_common.h> +#include <rte_compat.h> +#include <rte_debug.h> +#include <rte_graph.h> +#include <rte_graph_worker.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @file + * + * rte_graph_feature_arc.h + * + * Define APIs and structures/variables with respect to feature arc + * + * - Feature arc(s) + * - Feature(s) + * + * A feature arc represents an ordered list of features/protocol-nodes at a + * given networking layer. Feature arc provides a high level abstraction to + * connect various *rte_graph* nodes, designated as *feature nodes*, and + * allowing steering of packets across these feature nodes fast path processing + * in a generic manner. In a typical network stack, often a protocol or feature + * must be first enabled on a given interface, before any packet is steered + * towards it for feature processing. For eg: incoming IPv4 packets are sent to + * routing sub-system only after a valid IPv4 address is assigned to the + * received interface. In other words, often packets needs to be steered across + * features not based on the packet content but based on whether a feature is + * enable or disable on a given incoming/outgoing interface. Feature arc + * provides mechanism to enable/disable feature(s) on each interface at runtime + * and allow seamless packet steering across runtime enabled feature nodes in + * fast path. + * + * Feature arc also provides a way to steer packets from standard nodes to + * custom/user-defined *feature nodes* without any change in standard node's + * fast path functions + * + * On a given interface multiple feature(s) might be enabled in a particular + * feature arc. For instance, both "ipv4-output" and "IPsec policy output" + * features may be enabled on "eth0" interface in "L3-output" feature arc. + * Similarly, "ipv6-output" and "ipsec-output" may be enabled on "eth1" + * interface in same "L3-output" feature arc. + * + * When multiple features are present in a given feature arc, its imperative + * to allow each feature processing in a particular sequential order. For + * instance, in "L3-input" feature arc it may be required to run "IPsec + * input" feature first, for packet decryption, before "ip-lookup". So a + * sequential order must be maintained among features present in a feature arc. + * + * Features are enabled/disabled multiple times at runtime to some or all + * available interfaces present in the system. Enable/disabling features on one + * interface is independent of other interface. + * + * A given feature might consume packet (if it's configured to consume) or may + * forward it to next enabled feature. For instance, "IPsec input" feature may + * consume/drop all packets with "Protect" policy action while all packets with + * policy action as "Bypass" may be forwarded to next enabled feature (with in + * same feature arc) + * + * This library facilitates rte graph based applications to steer packets in + * fast path to different feature nodes with-in a feature arc and support all + * functionalities described above + * + * In order to use feature-arc APIs, applications needs to do following in + * control path: + * - Initialize feature arc library via rte_graph_feature_arc_init() + * - Create feature arc via rte_graph_feature_arc_create() + * - *Before calling rte_graph_create()*, features must be added to feature-arc + * via rte_graph_feature_add(). rte_graph_feature_add() allows adding + * features in a sequential order with "runs_after" and "runs_before" + * constraints. + * - Post rte_graph_create(), features can be enabled/disabled at runtime on + * any interface via rte_graph_feature_enable()/rte_graph_feature_disable() + * - Feature arc can be destroyed via rte_graph_feature_arc_destroy() + * + * In fast path, APIs are provided to steer packets towards feature path from + * - start_node (provided as an argument to rte_graph_feature_arc_create()) + * - feature nodes (which are added via rte_graph_feature_add()) + * + * For typical steering of packets across feature nodes, application required + * to know "rte_edges" which are saved in feature data object. Feature data + * object is unique for every interface per feature with in a feature arc. + * + * When steering packets from start_node to feature node: + * - rte_graph_feature_arc_first_feature_get() provides first enabled feature. + * - Next rte_edge from start_node to first enabled feature can be obtained via + * rte_graph_feature_arc_feature_set() + * + * rte_mbuf can carry [current feature, interface index] from start_node of an + * arc to other feature nodes + * + * At the time of feature enable(rte_graph_feature_enable), application can set + * 32-bit unique user_data specific to feature per interface. In fast path + * user_data can be retrieved via rte_graph_feature_user_data_get(). User data + * can hold application specific cookie like IPsec policy database index, FIB + * table index etc. + * + * If feature node is not consuming packet, next enabled feature and next + * rte_edge can be obtained via rte_graph_feature_arc_next_feature_get() + * + * It is application responsibility to ensure that at-least *last feature*(or + * sink feature) must be enabled from where packet can exit feature-arc path, + * if *NO* intermediate feature is consuming the packet and it has reached till + * the end of feature arc path + * + * It is recommended that all features *MUST* be added to feature arc before + * calling `rte_graph_create()`. Addition of features after + * `rte_graph_create()` may not work functionally. + * Although,rte_graph_feature_enable()/rte_graph_feature_disable() should be + * called after `rte_graph_create()` in control plane. + * + * Synchronization among cores + * --------------------------- + * Subsequent calls to rte_graph_feature_enable() is allowed while worker cores + * are processing in rte_graph_walk() loop. However, for + * rte_graph_feature_disable() application must use RCU based synchronization + */ + +/** Initializer value for rte_graph_feature_arc_t */ +#define RTE_GRAPH_FEATURE_ARC_INITIALIZER ((rte_graph_feature_arc_t)UINT64_MAX) + +/** Max number of feature arcs which can be created */ +#define RTE_GRAPH_FEATURE_ARC_MAX 64 + +/** Max number of features supported in a given feature arc */ +#define RTE_GRAPH_FEATURE_MAX_PER_ARC 64 + +/** Length of feature arc name */ +#define RTE_GRAPH_FEATURE_ARC_NAMELEN RTE_NODE_NAMESIZE + +/** @internal */ +#define rte_graph_feature_cast(x) ((rte_graph_feature_t)x) + +/**< Initializer value for rte_graph_feature_arc_t */ +#define RTE_GRAPH_FEATURE_INVALID rte_graph_feature_cast(UINT8_MAX) + +/** rte_graph feature arc object */ +typedef uintptr_t rte_graph_feature_arc_t; + +/** rte_graph feature object */ +typedef uint8_t rte_graph_feature_t; + +/** runtime active feature list index with in feature arc*/ +typedef uint16_t rte_graph_feature_rt_list_t; + +/** per feature arc monotonically increasing counter to synchronize fast path APIs */ +typedef uint16_t rte_graph_feature_counter_t; + +/** + * Initialize feature arc subsystem + * + * @param max_feature_arcs + * Maximum number of feature arcs required to be supported + * + * @return + * 0: Success + * <0: Failure + */ +__rte_experimental +int rte_graph_feature_arc_init(int max_feature_arcs); + +/** + * Create a feature arc + * + * @param feature_arc_name + * Feature arc name with max length of @ref RTE_GRAPH_FEATURE_ARC_NAMELEN + * @param max_features + * Maximum number of features to be supported in this feature arc + * @param max_indexes + * Maximum number of interfaces/ports/indexes to be supported + * @param start_node + * Base node where this feature arc's features are checked in fast path + * @param[out] _arc + * Feature arc object + * + * @return + * 0: Success + * <0: Failure + */ +__rte_experimental +int rte_graph_feature_arc_create(const char *feature_arc_name, int max_features, int max_indexes, + struct rte_node_register *start_node, + rte_graph_feature_arc_t *_arc); + +/** + * Get feature arc object with name + * + * @param arc_name + * Feature arc name provided to successful @ref rte_graph_feature_arc_create + * @param[out] _arc + * Feature arc object returned. Valid only when API returns SUCCESS + * + * @return + * 0: Success + * <0: Failure. + */ +__rte_experimental +int rte_graph_feature_arc_lookup_by_name(const char *arc_name, rte_graph_feature_arc_t *_arc); + +/** + * Add a feature to already created feature arc. For instance + * + * 1. Add first feature node: "ipv4-input" to input arc + * rte_graph_feature_add(ipv4_input_arc, "ipv4-input", NULL, NULL); + * + * 2. Add "ipsec-input" feature node after "ipv4-input" feature + * rte_graph_feature_add(ipv4_input_arc, "ipsec-input", "ipv4-input", NULL); + * + * 3. Add "ipv4-pre-classify-input" node before "ipv4-input" feature + * rte_graph_feature_add(ipv4_input_arc, "ipv4-pre-classify-input"", NULL, "ipv4-input"); + * + * 4. Add "acl-classify-input" node after ipv4-input but before ipsec-input + * rte_graph_feature_add(ipv4_input_arc, "acl-classify-input", "ipv4-input", "ipsec-input"); + * + * @param _arc + * Feature arc handle returned from @ref rte_graph_feature_arc_create() + * @param feature_node + * Graph node representing feature. On success, feature_node is next_node of + * feature_arc->start_node + * @param runs_after + * Add this feature_node after already added "runs_after". Creates + * start_node -> runs_after -> this_feature sequence + * @param runs_before + * Add this feature_node before already added "runs_before". Creates + * start_node -> this_feature -> runs_before sequence + * + * <I> Must be called before rte_graph_create() </I> + * <I> rte_graph_feature_add() is not allowed after call to + * rte_graph_feature_enable() so all features must be added before they can be + * enabled </I> + * + * @return + * 0: Success + * <0: Failure + */ +__rte_experimental +int rte_graph_feature_add(rte_graph_feature_arc_t _arc, struct rte_node_register *feature_node, + const char *runs_after, const char *runs_before); + +/** + * Enable feature within a feature arc + * + * Must be called after @b rte_graph_create(). + * + * @param _arc + * Feature arc object returned by @ref rte_graph_feature_arc_create or @ref + * rte_graph_feature_arc_lookup_by_name + * @param index + * Application specific index. Can be corresponding to interface_id/port_id etc + * @param feature_name + * Name of the node which is already added via @ref rte_graph_feature_add + * @param user_data + * Application specific data which is retrieved in fast path + * + * @return + * 0: Success + * <0: Failure + */ +__rte_experimental +int rte_graph_feature_enable(rte_graph_feature_arc_t _arc, uint32_t index, const char *feature_name, + int32_t user_data); + +/** + * Validate whether subsequent enable/disable feature would succeed or not. + * API is thread-safe + * + * @param _arc + * Feature arc object returned by @ref rte_graph_feature_arc_create or @ref + * rte_graph_feature_arc_lookup_by_name + * @param index + * Application specific index. Can be corresponding to interface_id/port_id etc + * @param feature_name + * Name of the node which is already added via @ref rte_graph_feature_add + * @param is_enable_disable + * If 1, validate whether subsequent @ref rte_graph_feature_enable would pass or not + * If 0, validate whether subsequent @ref rte_graph_feature_disable would pass or not + * @param emit_logs + * If passed true, emit error logs when failure is returned + * If passed false, do not emit error logs when failure is returned + * + * @return + * 0: Subsequent enable/disable API would pass + * <0: Subsequent enable/disable API would not pass + */ +__rte_experimental +int rte_graph_feature_validate(rte_graph_feature_arc_t _arc, uint32_t index, + const char *feature_name, int is_enable_disable, bool emit_logs); + +/** + * Disable already enabled feature within a feature arc + * + * Must be called after @b rte_graph_create(). API is *NOT* Thread-safe + * + * @param _arc + * Feature arc object returned by @ref rte_graph_feature_arc_create or @ref + * rte_graph_feature_arc_lookup_by_name + * @param index + * Application specific index. Can be corresponding to interface_id/port_id etc + * @param feature_name + * Name of the node which is already added via @ref rte_graph_feature_add + * + * @return + * 0: Success + * <0: Failure + */ +__rte_experimental +int rte_graph_feature_disable(rte_graph_feature_arc_t _arc, uint32_t index, + const char *feature_name); + +/** + * Get rte_graph_feature_t object from feature name + * + * @param arc + * Feature arc object returned by @ref rte_graph_feature_arc_create or @ref + * rte_graph_feature_arc_lookup_by_name + * @param feature_name + * Feature name provided to @ref rte_graph_feature_add + * @param[out] feature + * Feature object + * + * @return + * 0: Success + * <0: Failure + */ +__rte_experimental +int rte_graph_feature_lookup(rte_graph_feature_arc_t arc, const char *feature_name, + rte_graph_feature_t *feature); + +/** + * Delete feature_arc object + * + * @param _arc + * Feature arc object returned by @ref rte_graph_feature_arc_create or @ref + * rte_graph_feature_arc_lookup_by_name + * + * @return + * 0: Success + * <0: Failure + */ +__rte_experimental +int rte_graph_feature_arc_destroy(rte_graph_feature_arc_t _arc); + +/** + * Cleanup all feature arcs + * + * @return + * 0: Success + * <0: Failure + */ +__rte_experimental +int rte_graph_feature_arc_cleanup(void); + +/** + * Slow path API to know how many features are added (NOT enabled) within a + * feature arc + * + * @param _arc + * Feature arc object + * + * @return: Number of added features to arc + */ +__rte_experimental +uint32_t rte_graph_feature_arc_num_features(rte_graph_feature_arc_t _arc); + +/** + * Slow path API to know how many features are currently enabled within a + * feature arc across all indexes. If a single feature is enabled on all interfaces, + * this API would return "number_of_interfaces" as count (but not "1") + * + * @param _arc + * Feature arc object + * + * @return: Number of enabled features across all indexes + */ +__rte_experimental +uint32_t rte_graph_feature_arc_num_enabled_features(rte_graph_feature_arc_t _arc); + +/** + * Slow path API to get feature node name from rte_graph_feature_t object + * + * @param _arc + * Feature arc object + * @param feature + * Feature object + * + * @return: Name of the feature node + */ +__rte_experimental +char *rte_graph_feature_arc_feature_to_name(rte_graph_feature_arc_t _arc, + rte_graph_feature_t feature); + +/** + * Slow path API to get corresponding struct rte_node_register * from + * rte_graph_feature_t + * + * @param _arc + * Feature arc object + * @param feature + * Feature object + * + * @return: struct rte_node_register * of feature node on SUCCESS else NULL + */ +__rte_experimental +struct rte_node_register * +rte_graph_feature_arc_feature_to_node(rte_graph_feature_arc_t _arc, + rte_graph_feature_t feature); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/graph/rte_graph_feature_arc_worker.h b/lib/graph/rte_graph_feature_arc_worker.h new file mode 100644 index 0000000000..9b720e366c --- /dev/null +++ b/lib/graph/rte_graph_feature_arc_worker.h @@ -0,0 +1,679 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(C) 2024 Marvell International Ltd. + */ + +#ifndef _RTE_GRAPH_FEATURE_ARC_WORKER_H_ +#define _RTE_GRAPH_FEATURE_ARC_WORKER_H_ + +#include <stddef.h> +#include <rte_graph_feature_arc.h> +#include <rte_bitops.h> + +/** + * @file + * + * rte_graph_feature_arc_worker.h + * + * Defines fast path structure + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** @internal + * + * Slow path feature node info list + */ +struct rte_graph_feature_node_list { + /** Next feature */ + STAILQ_ENTRY(rte_graph_feature_node_list) next_feature; + + /** node representing feature */ + struct rte_node_register *feature_node; + + /** How many indexes/interfaces using this feature */ + int32_t ref_count; + + /* node_index in list (after feature_enable())*/ + uint32_t node_index; + + /** Back pointer to feature arc */ + void *feature_arc; + + /** rte_edge_t to this feature node from feature_arc->start_node */ + rte_edge_t edge_to_this_feature; +}; + +/** + * Feature data object: + * + * Feature data stores information to steer packets for: + * - a feature with in feature arc + * - Index i.e. Port/Interface index + * + * Each feature data object holds + * - User data of current feature retrieved via rte_graph_feature_user_data_get() + * - next_edge is used in two conditions when packet to be steered from + * -- start_node to first enabled feature on an interface index + * -- current feature node to next enabled feature on an interface index + * - next_enabled_feature on interface index, if current feature is not + * consuming packet + * + * While user_data corresponds to current enabled feature node however + * next_edge and next_enabled_feature corresponds to next enabled feature + * node on an interface index + * + * First enabled feature on interface index can be retrieved via: + * - rte_graph_feature_first_feature_get() if arc's start_node is trying to + * steer packet from start_node to first enabled feature on interface index + * + * Next enabled feature on interface index can be retrieved via: + * - rte_graph_feature_next_feature_get() if current node is not arc's + * start_node. Input to rte_graph_feature_next_feature_get() is current + * enabled feature and interface index + */ +typedef struct __rte_packed rte_graph_feature_data { + /** edge from current node to next enabled feature */ + rte_edge_t next_edge; + + union { + uint16_t reserved; + struct { + /** next enabled feature on index from current feature */ + rte_graph_feature_t next_enabled_feature; + }; + }; + + /** user_data set by application in rte_graph_feature_enable() for + * - current feature + * - interface index + */ + int32_t user_data; +} rte_graph_feature_data_t; + +/** + * Feature object + * + * Feature object holds feature data object for every index/interface within + * feature + * + * Within a given arc and interface index, first feature object can be + * retrieved in arc's start_node via: + * - rte_graph_feature_arc_first_feature_get() + * + * Feature data information can be retrieved for first feature in start node via + * - rte_graph_feature_arc_feature_set() + * + * Next enabled feature on interface index can be retrieved via: + * - rte_graph_feature_arc_next_feature_get() + * + * Typically application stores rte_graph_feature_t object in rte_mbuf. + * rte_graph_feature_t can be translated to (struct rte_graph_feature *) via + * rte_graph_feature_get() in fast path. Further if needed, feature data for an + * index within a feature can be retrieved via rte_graph_feature_data_get() + */ +struct __rte_cache_aligned rte_graph_feature { + /** feature index or rte_graph_feature_t */ + uint16_t this_feature_index; + + /* + * Array of size arc->feature_data_size + * + * <----------------- Feature --------------------------> + * [data-index-0][data-index-1]...[data-index-max_index-1] + * + * sizeof(feature_data_by_index[0] == sizeof(rte_graph_feature_data_t) + * + */ + uint8_t feature_data_by_index[]; +}; + +/** + * Feature list object + * + * Feature list is required to decouple fast path APIs with control path APIs. + * + * There are two feature lists: active, passive + * Passive list is duplicate of active list in terms of memory. + * + * While fast path APIs always work on active list but control plane work on + * passive list. When control plane needs to enable/disable any feature, it + * populates passive list afresh and atomically switch passive list to active + * list to make it available for fast path APIs + * + * Each feature node in start of its fast path function, must grab active list from + * arc via + * - rte_graph_feature_arc_has_any_feature() or + * rte_graph_feature_arc_has_feature() + * + * Retrieved list must be provided to other feature arc fast path APIs so that + * any control plane changes of active list should not impact current node + * execution iteration. Active list change would be reflected to current node + * in next iteration + * + * With active/passive lists and RCU mechanism in graph worker + * loop, application can update features at runtime without stopping fast path + * cores. A RCU synchronization is required when a feature needs to be + * disabled via rte_graph_feature_disable(). On enabling a feature, RCU + * synchronization may not be required + * + */ +typedef struct __rte_cache_aligned rte_graph_feature_list { + /** + * fast path array holding per_feature data. + * Duplicate entry as feature-arc also hold this pointer + * arc->features[] + * + *<-------------feature-0 ---------><---------feature-1 -------------->... + *[index-0][index-1]...[max_index-1]<-ALIGN->[index-0][index-1] ...[max_index-1]... + */ + struct rte_graph_feature *indexed_by_features; + /* + * fast path array holding first enabled feature per index + * (Required in start_node. In non start_node, mbuf can hold next enabled + * feature) + */ + rte_graph_feature_t first_enabled_feature_by_index[]; +} rte_graph_feature_list_t; + +/** + * rte_graph Feature arc object + * + * Feature arc object holds control plane and fast path information for all + * features and all interface index information for steering packets across + * feature nodes + * + * Within a feature arc, only RTE_GRAPH_FEATURE_MAX_PER_ARC features can be + * added. If more features needs to be added, another feature arc can be + * created + * + * Application gets rte_graph_feature_arc_t object via + * - rte_graph_feature_arc_create() OR + * - rte_graph_feature_arc_lookup_by_name() + * + * In fast path, rte_graph_feature_arc_t can be translated to (struct + * rte_graph_feature_arc *) via rte_graph_feature_arc_get(). Later is needed to + * add as an input argument to all fast path feature arc APIs + */ +struct __rte_cache_aligned rte_graph_feature_arc { + /* First 64B is fast path variables */ + RTE_MARKER fast_path_variables; + + /** runtime active feature list */ + RTE_ATOMIC(rte_graph_feature_rt_list_t) active_feature_list; + + /** Actual Size of feature_list object */ + uint16_t feature_list_size; + + /** + * Size each feature in fastpath. + * Required to navigate from feature to another feature in fast path + */ + uint16_t feature_size; + + /** + * Size of all feature data for an index + * Required to navigate through various feature data within a feature + * in fast path + */ + uint16_t feature_data_size; + + /** + * Quick fast path bitmask indicating if any feature enabled or not on + * any of the indexes. Helps in optimally process packets for the case + * when features are added but not enabled + * + * Separate for active and passive list + */ + RTE_ATOMIC(uint64_t) feature_enable_bitmask[2]; + + /** + * Pointer to both active and passive feature list object + */ + rte_graph_feature_list_t *feature_list[2]; + + /** + * Feature objects for each list + */ + struct rte_graph_feature *features[2]; + + /** index in feature_arc_main */ + uint16_t feature_arc_index; + + uint16_t reserved[3]; + + /** Slow path variables follows*/ + RTE_MARKER slow_path_variables; + + /** feature arc name */ + char feature_arc_name[RTE_GRAPH_FEATURE_ARC_NAMELEN]; + + /** All feature lists */ + STAILQ_HEAD(, rte_graph_feature_node_list) all_features; + + /** control plane counter to track enabled features */ + uint32_t runtime_enabled_features; + + /** Back pointer to feature_arc_main */ + void *feature_arc_main; + + /** Arc's start/base node */ + struct rte_node_register *start_node; + + /** maximum number of features supported by this arc */ + uint32_t max_features; + + /** maximum number of index supported by this arc */ + uint32_t max_indexes; + + /** Slow path bit mask per feature per index */ + uint64_t feature_bit_mask_by_index[]; +}; + +/** + * Feature arc main object + * + * Holds all feature arcs created by application + * + * RTE_GRAPH_FEATURE_ARC_MAX number of feature arcs can be created by + * application via rte_graph_feature_arc_create() + */ +typedef struct feature_arc_main { + /** number of feature arcs created by application */ + uint32_t num_feature_arcs; + + /** max features arcs allowed */ + uint32_t max_feature_arcs; + + /** feature arcs */ + rte_graph_feature_arc_t feature_arcs[]; +} rte_graph_feature_arc_main_t; + +/** @internal Get feature arc pointer from object */ +#define rte_graph_feature_arc_get(arc) ((struct rte_graph_feature_arc *)arc) + +extern rte_graph_feature_arc_main_t *__feature_arc_main; + +/** + * API to know if feature is valid or not + */ +__rte_experimental +static __rte_always_inline int +rte_graph_feature_is_valid(rte_graph_feature_t feature) +{ + return (feature != RTE_GRAPH_FEATURE_INVALID); +} + +/** + * Get rte_graph_feature object with no checks + * + * @param arc + * Feature arc pointer + * @param feature + * Feature index + * @param feature_list + * active feature list retrieved from rte_graph_feature_arc_has_any_feature() + * or rte_graph_feature_arc_has_feature() + * + * @return + * Internal feature object. + */ +__rte_experimental +static __rte_always_inline struct rte_graph_feature * +__rte_graph_feature_get(struct rte_graph_feature_arc *arc, rte_graph_feature_t feature, + const rte_graph_feature_rt_list_t feature_list) +{ + return ((struct rte_graph_feature *)(((uint8_t *)arc->features[feature_list]) + + (feature * arc->feature_size))); +} + +/** + * Get rte_graph_feature object for a given interface/index from feature arc + * + * @param arc + * Feature arc pointer + * @param feature + * Feature index + * + * @return + * Internal feature object. + */ +__rte_experimental +static __rte_always_inline struct rte_graph_feature * +rte_graph_feature_get(struct rte_graph_feature_arc *arc, rte_graph_feature_t feature) +{ + rte_graph_feature_rt_list_t list; + + if (unlikely(feature >= arc->max_features)) + RTE_VERIFY(0); + + if (likely(rte_graph_feature_is_valid(feature))) { + list = rte_atomic_load_explicit(&arc->active_feature_list, + rte_memory_order_relaxed); + return __rte_graph_feature_get(arc, feature, list); + } + + return NULL; +} + +__rte_experimental +static __rte_always_inline rte_graph_feature_data_t * +__rte_graph_feature_data_get(struct rte_graph_feature_arc *arc, struct rte_graph_feature *feature, + uint8_t index) +{ + RTE_SET_USED(arc); + return ((rte_graph_feature_data_t *)(((uint8_t *)feature->feature_data_by_index) + + (index * sizeof(rte_graph_feature_data_t)))); +} + +/** + * Get rte_graph feature data object for a index in feature + * + * @param arc + * feature arc + * @param feature + * Pointer to feature object + * @param index + * Index of feature maintained in slow path linked list + * + * @return + * Valid feature data + */ +__rte_experimental +static __rte_always_inline rte_graph_feature_data_t * +rte_graph_feature_data_get(struct rte_graph_feature_arc *arc, struct rte_graph_feature *feature, + uint8_t index) +{ + if (likely(index < arc->max_indexes)) + return __rte_graph_feature_data_get(arc, feature, index); + + RTE_VERIFY(0); +} + +/** + * Fast path API to check if any feature enabled on a feature arc + * Typically from arc->start_node process function + * + * @param arc + * Feature arc object + * @param[out] plist + * Pointer to runtime active feature list which needs to be provided to other + * fast path APIs + * + * @return + * 0: If no feature enabled + * Non-Zero: Bitmask of features enabled. plist is valid + * + */ +__rte_experimental +static __rte_always_inline uint64_t +rte_graph_feature_arc_has_any_feature(struct rte_graph_feature_arc *arc, + rte_graph_feature_rt_list_t *plist) +{ + *plist = rte_atomic_load_explicit(&arc->active_feature_list, rte_memory_order_relaxed); + + return (rte_atomic_load_explicit(arc->feature_enable_bitmask + (uint8_t)*plist, + rte_memory_order_relaxed)); +} + +/** + * Fast path API to check if provided feature is enabled on any interface/index + * or not + * + * @param arc + * Feature arc object + * @param feature + * Input rte_graph_feature_t that needs to be checked + * @param[out] plist + * Returns active list to caller which needs to be provided to other fast path + * APIs + * + * @return + * 1: If input [feature] is enabled in arc + * 0: If input [feature] is not enabled in arc + */ +__rte_experimental +static __rte_always_inline int +rte_graph_feature_arc_has_feature(struct rte_graph_feature_arc *arc, + rte_graph_feature_t feature, + rte_graph_feature_rt_list_t *plist) +{ + uint64_t bitmask = RTE_BIT64(feature); + + *plist = rte_atomic_load_explicit(&arc->active_feature_list, rte_memory_order_relaxed); + + return (bitmask & rte_atomic_load_explicit(arc->feature_enable_bitmask + (uint8_t)*plist, + rte_memory_order_relaxed)); +} + +/** + * Prefetch feature arc fast path cache line + * + * @param arc + * RTE_GRAPH feature arc object + */ +__rte_experimental +static __rte_always_inline void +rte_graph_feature_arc_prefetch(struct rte_graph_feature_arc *arc) +{ + rte_prefetch0((void *)&arc->fast_path_variables); +} + +/** + * Prefetch feature related fast path cache line + * + * @param arc + * RTE_GRAPH feature arc object + * @param list + * Pointer to runtime active feature list from rte_graph_feature_arc_has_any_feature(); + * @param feature + * Pointer to feature object + */ +__rte_experimental +static __rte_always_inline void +rte_graph_feature_arc_feature_prefetch(struct rte_graph_feature_arc *arc, + const rte_graph_feature_rt_list_t list, + rte_graph_feature_t feature) +{ + /* feature cache line */ + if (likely(rte_graph_feature_is_valid(feature))) + rte_prefetch0((void *)__rte_graph_feature_get(arc, feature, list)); +} + +/** + * Prefetch feature data upfront. Perform sanity + * + * @param arc + * RTE_GRAPH feature arc object + * @param list + * Pointer to runtime active feature list from rte_graph_feature_arc_has_any_feature(); + * @param feature + * Pointer to feature object returned from @ref + * rte_graph_feature_arc_first_feature_get() + * @param index + * Interface/index + */ +__rte_experimental +static __rte_always_inline void +rte_graph_feature_arc_data_prefetch(struct rte_graph_feature_arc *arc, + const rte_graph_feature_rt_list_t list, + rte_graph_feature_t feature, uint32_t index) +{ + if (likely(rte_graph_feature_is_valid(feature))) + rte_prefetch0((void *)((uint8_t *)arc->features[list] + + offsetof(struct rte_graph_feature, feature_data_by_index) + + (index * sizeof(rte_graph_feature_data_t)))); +} + +/** + * Fast path API to get first enabled feature on interface index + * Typically required in arc->start_node so that from returned feature, + * feature-data can be retrieved to steer packets + * + * @param arc + * Feature arc object + * @param list + * Pointer to runtime active feature list from + * rte_graph_feature_arc_has_any_feature() or + * rte_graph_feature_arc_has_feature() + * @param index + * Interface Index + * @param[out] feature + * Pointer to rte_graph_feature_t. + * + * @return + * 1. Success. If first feature field is enabled and returned [feature] is valid + * 0. Failure. If first feature field is disabled in arc + * + */ +__rte_experimental +static __rte_always_inline int +rte_graph_feature_arc_first_feature_get(struct rte_graph_feature_arc *arc, + const rte_graph_feature_rt_list_t list, + uint32_t index, + rte_graph_feature_t *feature) +{ + struct rte_graph_feature_list *feature_list = arc->feature_list[list]; + + *feature = feature_list->first_enabled_feature_by_index[index]; + + return rte_graph_feature_is_valid(*feature); +} + +/** + * Fast path API to get next enabled feature on interface index with provided + * input feature + * + * @param arc + * Feature arc object + * @param list + * Pointer to runtime active feature list from + * rte_graph_feature_arc_has_any_feature() or + * @param index + * Interface Index + * @param[out] feature + * Pointer to rte_graph_feature_t. API sets next enabled feature on [index] + * from provided input feature. Valid only if API returns Success + * @param[out] next_edge + * Edge from current feature to next feature. Valid only if next feature is valid + * + * @return + * 1. Success. first feature field is enabled/valid + * 0. Failure. first feature field is disabled/invalid + */ +__rte_experimental +static __rte_always_inline int +rte_graph_feature_arc_next_feature_get(struct rte_graph_feature_arc *arc, + const rte_graph_feature_rt_list_t list, + uint32_t index, + rte_graph_feature_t *feature, + rte_edge_t *next_edge) +{ + rte_graph_feature_data_t *feature_data = NULL; + struct rte_graph_feature *f = NULL; + + if (likely(rte_graph_feature_is_valid(*feature))) { + f = __rte_graph_feature_get(arc, *feature, list); + feature_data = rte_graph_feature_data_get(arc, f, index); + *feature = feature_data->next_enabled_feature; + *next_edge = feature_data->next_edge; + return rte_graph_feature_is_valid(*feature); + } + + return 0; +} + +/** + * Set fields with respect to first enabled feature in an arc and return edge + * Typically returned feature and interface index must be saved in rte_mbuf + * structure to pass this information to next feature node + * + * @param arc + * Feature arc object + * @param list + * Pointer to runtime active feature list from rte_graph_feature_arc_has_any_feature(); + * @param index + * Index (of interface) + * @param[out] gf + * Pointer to rte_graph_feature_t. Valid if API returns Success + * @param[out] edge + * Edge to steer packet from arc->start_node to first enabled feature. Valid + * only if API returns Success + * + * @return + * 0: If valid feature is enabled and set by API in *gf + * 1: If valid feature is NOT enabled + */ +__rte_experimental +static __rte_always_inline rte_graph_feature_t +rte_graph_feature_arc_feature_set(struct rte_graph_feature_arc *arc, + const rte_graph_feature_rt_list_t list, + uint32_t index, + rte_graph_feature_t *gf, + rte_edge_t *edge) +{ + struct rte_graph_feature_list *feature_list = arc->feature_list[list]; + struct rte_graph_feature_data *feature_data = NULL; + struct rte_graph_feature *feature = NULL; + rte_graph_feature_t f; + + f = feature_list->first_enabled_feature_by_index[index]; + + if (unlikely(rte_graph_feature_is_valid(f))) { + feature = __rte_graph_feature_get(arc, f, list); + feature_data = rte_graph_feature_data_get(arc, feature, index); + *gf = f; + *edge = feature_data->next_edge; + return 0; + } + + return 1; +} + +__rte_experimental +static __rte_always_inline int32_t +__rte_graph_feature_user_data_get(rte_graph_feature_data_t *fdata) +{ + return fdata->user_data; +} + +/** + * Get user data corresponding to current feature set by application in + * rte_graph_feature_enable() + * + * @param arc + * Feature arc object + * @param list + * Pointer to runtime active feature list from rte_graph_feature_arc_has_any_feature(); + * @param feature + * Feature index + * @param index + * Interface index + * + * @return + * -1: Failure + * Valid user data: Success + */ +__rte_experimental +static __rte_always_inline int32_t +rte_graph_feature_user_data_get(struct rte_graph_feature_arc *arc, + const rte_graph_feature_rt_list_t list, + rte_graph_feature_t feature, + uint32_t index) +{ + rte_graph_feature_data_t *fdata = NULL; + struct rte_graph_feature *f = NULL; + + if (likely(rte_graph_feature_is_valid(feature))) { + f = __rte_graph_feature_get(arc, feature, list); + fdata = rte_graph_feature_data_get(arc, f, index); + return __rte_graph_feature_user_data_get(fdata); + } + + return -1; +} +#ifdef __cplusplus +} +#endif +#endif diff --git a/lib/graph/version.map b/lib/graph/version.map index 2c83425ddc..3b7f475afd 100644 --- a/lib/graph/version.map +++ b/lib/graph/version.map @@ -52,3 +52,23 @@ DPDK_25 { local: *; }; + +EXPERIMENTAL { + global: + + # added in 24.11 + rte_graph_feature_arc_init; + rte_graph_feature_arc_create; + rte_graph_feature_arc_lookup_by_name; + rte_graph_feature_add; + rte_graph_feature_enable; + rte_graph_feature_validate; + rte_graph_feature_disable; + rte_graph_feature_lookup; + rte_graph_feature_arc_destroy; + rte_graph_feature_arc_cleanup; + rte_graph_feature_arc_num_enabled_features; + rte_graph_feature_arc_num_features; + rte_graph_feature_arc_feature_to_name; + rte_graph_feature_arc_feature_to_node; +}; -- 2.43.0 ^ permalink raw reply [flat|nested] 46+ messages in thread
* [PATCH v4 2/5] graph: add feature arc option in graph create 2024-10-10 13:31 ` [PATCH v4 " Nitin Saxena 2024-10-10 13:31 ` [PATCH v4 1/5] graph: add feature arc support Nitin Saxena @ 2024-10-10 13:31 ` Nitin Saxena 2024-10-10 13:31 ` [PATCH v4 3/5] graph: add IPv4 output feature arc Nitin Saxena ` (3 subsequent siblings) 5 siblings, 0 replies; 46+ messages in thread From: Nitin Saxena @ 2024-10-10 13:31 UTC (permalink / raw) To: Jerin Jacob, Kiran Kumar K, Nithin Dabilpuram, Zhirun Yan, Robin Jarry, Christophe Fontaine Cc: dev, Nitin Saxena, Pavan Nikhilesh Added option in graph create to call feature-specific process node functions. This removes extra overhead for checking feature arc status in nodes where application is not using feature arc processing Signed-off-by: Pavan Nikhilesh <pbhagavatula@marvell.com> Signed-off-by: Nitin Saxena <nsaxena@marvell.com> --- doc/guides/rel_notes/release_24_11.rst | 7 +++++++ lib/graph/graph.c | 1 + lib/graph/graph_populate.c | 7 ++++++- lib/graph/graph_private.h | 3 +++ lib/graph/node.c | 2 ++ lib/graph/rte_graph.h | 3 +++ 6 files changed, 22 insertions(+), 1 deletion(-) diff --git a/doc/guides/rel_notes/release_24_11.rst b/doc/guides/rel_notes/release_24_11.rst index bd5589b01c..237c057647 100644 --- a/doc/guides/rel_notes/release_24_11.rst +++ b/doc/guides/rel_notes/release_24_11.rst @@ -137,6 +137,13 @@ ABI Changes Also, make sure to start the actual text at the margin. ======================================================= +* graph: Added feature arc specific `feat_arc_proc` node callback function in + `struct rte_node_register`. If this function is not NULL and + `feature_arc_enable` is set to `true` in `struct rte_graph_param`, + rte_graph_walk() calls `feat_arc_proc` callback function instead of `process` + +* graph: Added `feature_arc_enable` parameter in `struct rte_graph_param` for + calling non-NULL `feat_arc_proc` callback function by `rte_graph_walk()` Known Issues ------------ diff --git a/lib/graph/graph.c b/lib/graph/graph.c index d5b8c9f918..b0ad3a83ae 100644 --- a/lib/graph/graph.c +++ b/lib/graph/graph.c @@ -455,6 +455,7 @@ rte_graph_create(const char *name, struct rte_graph_param *prm) graph->parent_id = RTE_GRAPH_ID_INVALID; graph->lcore_id = RTE_MAX_LCORE; graph->num_pkt_to_capture = prm->num_pkt_to_capture; + graph->feature_arc_enabled = prm->feature_arc_enable; if (prm->pcap_filename) rte_strscpy(graph->pcap_filename, prm->pcap_filename, RTE_GRAPH_PCAP_FILE_SZ); diff --git a/lib/graph/graph_populate.c b/lib/graph/graph_populate.c index ed596a7711..5d8aa7b903 100644 --- a/lib/graph/graph_populate.c +++ b/lib/graph/graph_populate.c @@ -79,8 +79,13 @@ graph_nodes_populate(struct graph *_graph) if (graph_pcap_is_enable()) { node->process = graph_pcap_dispatch; node->original_process = graph_node->node->process; - } else + if (_graph->feature_arc_enabled && graph_node->node->feat_arc_proc) + node->original_process = graph_node->node->feat_arc_proc; + } else { node->process = graph_node->node->process; + if (_graph->feature_arc_enabled && graph_node->node->feat_arc_proc) + node->process = graph_node->node->feat_arc_proc; + } memcpy(node->name, graph_node->node->name, RTE_GRAPH_NAMESIZE); pid = graph_node->node->parent_id; if (pid != RTE_NODE_ID_INVALID) { /* Cloned node */ diff --git a/lib/graph/graph_private.h b/lib/graph/graph_private.h index d557d55f2d..58ba0abeff 100644 --- a/lib/graph/graph_private.h +++ b/lib/graph/graph_private.h @@ -56,6 +56,7 @@ struct node { unsigned int lcore_id; /**< Node runs on the Lcore ID used for mcore dispatch model. */ rte_node_process_t process; /**< Node process function. */ + rte_node_process_t feat_arc_proc; /**< Node feature-arch process function. */ rte_node_init_t init; /**< Node init function. */ rte_node_fini_t fini; /**< Node fini function. */ rte_node_t id; /**< Allocated identifier for the node. */ @@ -126,6 +127,8 @@ struct graph { /**< Number of packets to be captured per core. */ char pcap_filename[RTE_GRAPH_PCAP_FILE_SZ]; /**< pcap file name/path. */ + uint8_t feature_arc_enabled; + /**< Graph feature arc. */ STAILQ_HEAD(gnode_list, graph_node) node_list; /**< Nodes in a graph. */ }; diff --git a/lib/graph/node.c b/lib/graph/node.c index 99a9622779..d8fd273543 100644 --- a/lib/graph/node.c +++ b/lib/graph/node.c @@ -90,6 +90,7 @@ __rte_node_register(const struct rte_node_register *reg) goto free; node->flags = reg->flags; node->process = reg->process; + node->feat_arc_proc = reg->feat_arc_proc; node->init = reg->init; node->fini = reg->fini; node->nb_edges = reg->nb_edges; @@ -137,6 +138,7 @@ node_clone(struct node *node, const char *name) /* Clone the source node */ reg->flags = node->flags; reg->process = node->process; + reg->feat_arc_proc = node->feat_arc_proc; reg->init = node->init; reg->fini = node->fini; reg->nb_edges = node->nb_edges; diff --git a/lib/graph/rte_graph.h b/lib/graph/rte_graph.h index ecfec2068a..f07272b308 100644 --- a/lib/graph/rte_graph.h +++ b/lib/graph/rte_graph.h @@ -172,6 +172,8 @@ struct rte_graph_param { uint32_t mp_capacity; /**< Capacity of memory pool for dispatch model. */ } dispatch; }; + + bool feature_arc_enable; /**< Enable Graph feature arc. */ }; /** @@ -470,6 +472,7 @@ struct rte_node_register { uint64_t flags; /**< Node configuration flag. */ #define RTE_NODE_SOURCE_F (1ULL << 0) /**< Node type is source. */ rte_node_process_t process; /**< Node process function. */ + rte_node_process_t feat_arc_proc; /**< Node feature-arc specific process function. */ rte_node_init_t init; /**< Node init function. */ rte_node_fini_t fini; /**< Node fini function. */ rte_node_t id; /**< Node Identifier. */ -- 2.43.0 ^ permalink raw reply [flat|nested] 46+ messages in thread
* [PATCH v4 3/5] graph: add IPv4 output feature arc 2024-10-10 13:31 ` [PATCH v4 " Nitin Saxena 2024-10-10 13:31 ` [PATCH v4 1/5] graph: add feature arc support Nitin Saxena 2024-10-10 13:31 ` [PATCH v4 2/5] graph: add feature arc option in graph create Nitin Saxena @ 2024-10-10 13:31 ` Nitin Saxena 2024-10-10 13:31 ` [PATCH v4 4/5] test/graph_feature_arc: add functional tests Nitin Saxena ` (2 subsequent siblings) 5 siblings, 0 replies; 46+ messages in thread From: Nitin Saxena @ 2024-10-10 13:31 UTC (permalink / raw) To: Jerin Jacob, Kiran Kumar K, Nithin Dabilpuram, Zhirun Yan, Robin Jarry, Christophe Fontaine Cc: dev, Nitin Saxena add ipv4-output feature arc in ipv4-rewrite node to allow custom/standard nodes(like outbound IPsec policy node) in outgoing forwarding path Signed-off-by: Nitin Saxena <nsaxena@marvell.com> --- lib/node/ip4_rewrite.c | 476 +++++++++++++++++++++++++++++------- lib/node/ip4_rewrite_priv.h | 15 +- lib/node/node_private.h | 20 +- lib/node/rte_node_ip4_api.h | 3 + 4 files changed, 417 insertions(+), 97 deletions(-) diff --git a/lib/node/ip4_rewrite.c b/lib/node/ip4_rewrite.c index 34a920df5e..824ef9a4cd 100644 --- a/lib/node/ip4_rewrite.c +++ b/lib/node/ip4_rewrite.c @@ -15,39 +15,156 @@ #include "ip4_rewrite_priv.h" #include "node_private.h" +#define ALL_PKT_MASK 0xf + struct ip4_rewrite_node_ctx { + rte_graph_feature_arc_t output_feature_arc; /* Dynamic offset to mbuf priv1 */ int mbuf_priv1_off; /* Cached next index */ uint16_t next_index; + uint16_t last_tx; }; +typedef struct rewrite_priv_vars { + union { + struct { + rte_xmm_t xmm1; + }; + struct __rte_packed { + uint16_t next0; + uint16_t next1; + uint16_t next2; + uint16_t next3; + uint16_t last_tx_interface; + uint16_t last_if_feature; + uint16_t actual_feat_mask; + uint16_t speculative_feat_mask; + }; + }; +} rewrite_priv_vars_t; + static struct ip4_rewrite_node_main *ip4_rewrite_nm; #define IP4_REWRITE_NODE_LAST_NEXT(ctx) \ (((struct ip4_rewrite_node_ctx *)ctx)->next_index) +#define IP4_REWRITE_NODE_LAST_TX(ctx) \ + (((struct ip4_rewrite_node_ctx *)ctx)->last_tx) + #define IP4_REWRITE_NODE_PRIV1_OFF(ctx) \ (((struct ip4_rewrite_node_ctx *)ctx)->mbuf_priv1_off) -static uint16_t -ip4_rewrite_node_process(struct rte_graph *graph, struct rte_node *node, - void **objs, uint16_t nb_objs) +#define IP4_REWRITE_NODE_OUTPUT_FEATURE_ARC(ctx) \ + (((struct ip4_rewrite_node_ctx *)ctx)->output_feature_arc) + +static __rte_always_inline void +prefetch_mbuf_and_dynfield(struct rte_mbuf *mbuf) { + /* prefetch first cache line required for accessing buf_addr */ + rte_prefetch0((void *)mbuf); +} + +static __rte_always_inline void +check_output_feature_x4(struct rte_graph_feature_arc *arc, + const rte_graph_feature_rt_list_t flist, + rewrite_priv_vars_t *pvar, struct node_mbuf_priv1 *priv0, + struct node_mbuf_priv1 *priv1, struct node_mbuf_priv1 *priv2, + struct node_mbuf_priv1 *priv3) +{ + uint32_t mask = 0; + uint16_t xor = 0; + + /* + * interface edge's start from 1 and not from 0 as "pkt_drop" + * is next node at 0th index + */ + priv0->if_index = pvar->next0 - 1; + priv1->if_index = pvar->next1 - 1; + priv2->if_index = pvar->next2 - 1; + priv3->if_index = pvar->next3 - 1; + + /* Find out if all packets are sent to last_tx_interface */ + xor = pvar->last_tx_interface ^ priv0->if_index; + xor += priv0->if_index ^ priv1->if_index; + xor += priv1->if_index ^ priv2->if_index; + xor += priv2->if_index ^ priv3->if_index; + + if (likely(!xor)) { + /* copy last interface feature and feature mask */ + priv0->current_feature = priv1->current_feature = + priv2->current_feature = priv3->current_feature = + pvar->last_if_feature; + pvar->actual_feat_mask = pvar->speculative_feat_mask; + } else { + /* create a mask for index which does not have feature + * Also override next edge and if feature enabled, get feature + */ + mask = rte_graph_feature_arc_feature_set(arc, flist, priv0->if_index, + &priv0->current_feature, + &pvar->next0); + + mask |= ((rte_graph_feature_arc_feature_set(arc, flist, priv1->if_index, + &priv1->current_feature, + &pvar->next1)) << 1); + + mask |= ((rte_graph_feature_arc_feature_set(arc, flist, priv2->if_index, + &priv2->current_feature, + &pvar->next2)) << 2); + + mask |= ((rte_graph_feature_arc_feature_set(arc, flist, priv3->if_index, + &priv3->current_feature, + &pvar->next3)) << 3); + + /* + * add last tx and last feature regardless even if feature is + * valid or not + */ + pvar->last_tx_interface = priv3->if_index; + pvar->last_if_feature = priv3->current_feature; + /* Set 0xf if invalid feature to last packet, else 0 */ + pvar->speculative_feat_mask = (priv3->current_feature == + RTE_GRAPH_FEATURE_INVALID) ? ALL_PKT_MASK : 0x0; + pvar->actual_feat_mask = mask; + } +} + +static __rte_always_inline uint16_t +__ip4_rewrite_node_process(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs, + const int dyn, const int check_enabled_features, + struct rte_graph_feature_arc *out_feature_arc, + const rte_graph_feature_rt_list_t flist) +{ + struct node_mbuf_priv1 *priv0 = NULL, *priv1 = NULL, *priv2 = NULL, *priv3 = NULL; struct rte_mbuf *mbuf0, *mbuf1, *mbuf2, *mbuf3, **pkts; struct ip4_rewrite_nh_header *nh = ip4_rewrite_nm->nh; - const int dyn = IP4_REWRITE_NODE_PRIV1_OFF(node->ctx); - uint16_t next0, next1, next2, next3, next_index; - struct rte_ipv4_hdr *ip0, *ip1, *ip2, *ip3; uint16_t n_left_from, held = 0, last_spec = 0; + struct rte_ipv4_hdr *ip0, *ip1, *ip2, *ip3; + rewrite_priv_vars_t pvar; + int64_t fd0, fd1, fd2, fd3; + rte_edge_t fix_spec = 0; void *d0, *d1, *d2, *d3; void **to_next, **from; + uint16_t next_index; rte_xmm_t priv01; rte_xmm_t priv23; int i; - /* Speculative next as last next */ + RTE_SET_USED(fd0); + RTE_SET_USED(fd1); + RTE_SET_USED(fd2); + RTE_SET_USED(fd3); + + /* Initialize speculative variables.*/ + + /* Last interface */ + pvar.last_tx_interface = IP4_REWRITE_NODE_LAST_TX(node->ctx); + /*last next from node ctx*/ next_index = IP4_REWRITE_NODE_LAST_NEXT(node->ctx); + pvar.speculative_feat_mask = ALL_PKT_MASK; + pvar.actual_feat_mask = 0; + rte_prefetch0(nh); pkts = (struct rte_mbuf **)objs; @@ -55,20 +172,47 @@ ip4_rewrite_node_process(struct rte_graph *graph, struct rte_node *node, n_left_from = nb_objs; for (i = 0; i < 4 && i < n_left_from; i++) - rte_prefetch0(pkts[i]); + prefetch_mbuf_and_dynfield(pkts[i]); /* Get stream for the speculated next node */ to_next = rte_node_next_stream_get(graph, node, next_index, nb_objs); + + /* prefetch speculative feature and corresponding data */ + if (check_enabled_features) { + /* + * Get first feature enabled, if any, on last_tx_interface + */ + if (unlikely(rte_graph_feature_arc_first_feature_get(out_feature_arc, + flist, + pvar.last_tx_interface, + (rte_graph_feature_t *) + &pvar.last_if_feature))) { + /* prefetch feature cache line */ + rte_graph_feature_arc_feature_prefetch(out_feature_arc, flist, + pvar.last_if_feature); + + /* prefetch feature data cache line */ + rte_graph_feature_arc_data_prefetch(out_feature_arc, flist, + pvar.last_if_feature, + pvar.last_tx_interface); + /* + * Set speculativa_feat mask to indicate, all 4 packets + * going to feature path + */ + pvar.speculative_feat_mask = 0; + } + } + /* Update Ethernet header of pkts */ while (n_left_from >= 4) { if (likely(n_left_from > 7)) { /* Prefetch only next-mbuf struct and priv area. * Data need not be prefetched as we only write. */ - rte_prefetch0(pkts[4]); - rte_prefetch0(pkts[5]); - rte_prefetch0(pkts[6]); - rte_prefetch0(pkts[7]); + prefetch_mbuf_and_dynfield(pkts[4]); + prefetch_mbuf_and_dynfield(pkts[5]); + prefetch_mbuf_and_dynfield(pkts[6]); + prefetch_mbuf_and_dynfield(pkts[7]); } mbuf0 = pkts[0]; @@ -78,66 +222,138 @@ ip4_rewrite_node_process(struct rte_graph *graph, struct rte_node *node, pkts += 4; n_left_from -= 4; + + /* Copy mbuf private data into private variables */ priv01.u64[0] = node_mbuf_priv1(mbuf0, dyn)->u; priv01.u64[1] = node_mbuf_priv1(mbuf1, dyn)->u; priv23.u64[0] = node_mbuf_priv1(mbuf2, dyn)->u; priv23.u64[1] = node_mbuf_priv1(mbuf3, dyn)->u; - /* Increment checksum by one. */ - priv01.u32[1] += rte_cpu_to_be_16(0x0100); - priv01.u32[3] += rte_cpu_to_be_16(0x0100); - priv23.u32[1] += rte_cpu_to_be_16(0x0100); - priv23.u32[3] += rte_cpu_to_be_16(0x0100); - - /* Update ttl,cksum rewrite ethernet hdr on mbuf0 */ - d0 = rte_pktmbuf_mtod(mbuf0, void *); - rte_memcpy(d0, nh[priv01.u16[0]].rewrite_data, - nh[priv01.u16[0]].rewrite_len); - - next0 = nh[priv01.u16[0]].tx_node; - ip0 = (struct rte_ipv4_hdr *)((uint8_t *)d0 + - sizeof(struct rte_ether_hdr)); - ip0->time_to_live = priv01.u16[1] - 1; - ip0->hdr_checksum = priv01.u16[2] + priv01.u16[3]; - - /* Update ttl,cksum rewrite ethernet hdr on mbuf1 */ - d1 = rte_pktmbuf_mtod(mbuf1, void *); - rte_memcpy(d1, nh[priv01.u16[4]].rewrite_data, - nh[priv01.u16[4]].rewrite_len); - - next1 = nh[priv01.u16[4]].tx_node; - ip1 = (struct rte_ipv4_hdr *)((uint8_t *)d1 + - sizeof(struct rte_ether_hdr)); - ip1->time_to_live = priv01.u16[5] - 1; - ip1->hdr_checksum = priv01.u16[6] + priv01.u16[7]; - - /* Update ttl,cksum rewrite ethernet hdr on mbuf2 */ - d2 = rte_pktmbuf_mtod(mbuf2, void *); - rte_memcpy(d2, nh[priv23.u16[0]].rewrite_data, - nh[priv23.u16[0]].rewrite_len); - next2 = nh[priv23.u16[0]].tx_node; - ip2 = (struct rte_ipv4_hdr *)((uint8_t *)d2 + - sizeof(struct rte_ether_hdr)); - ip2->time_to_live = priv23.u16[1] - 1; - ip2->hdr_checksum = priv23.u16[2] + priv23.u16[3]; - - /* Update ttl,cksum rewrite ethernet hdr on mbuf3 */ - d3 = rte_pktmbuf_mtod(mbuf3, void *); - rte_memcpy(d3, nh[priv23.u16[4]].rewrite_data, - nh[priv23.u16[4]].rewrite_len); - - next3 = nh[priv23.u16[4]].tx_node; - ip3 = (struct rte_ipv4_hdr *)((uint8_t *)d3 + - sizeof(struct rte_ether_hdr)); - ip3->time_to_live = priv23.u16[5] - 1; - ip3->hdr_checksum = priv23.u16[6] + priv23.u16[7]; + /* Copy next edge from next hop */ + pvar.next0 = nh[priv01.u16[0]].tx_node; + pvar.next1 = nh[priv01.u16[4]].tx_node; + pvar.next2 = nh[priv23.u16[0]].tx_node; + pvar.next3 = nh[priv23.u16[4]].tx_node; + + if (check_enabled_features) { + priv0 = node_mbuf_priv1(mbuf0, dyn); + priv1 = node_mbuf_priv1(mbuf1, dyn); + priv2 = node_mbuf_priv1(mbuf2, dyn); + priv3 = node_mbuf_priv1(mbuf3, dyn); + + /* If feature is enabled, override next edge for each mbuf + * and set node_mbuf_priv data appropriately + */ + check_output_feature_x4(out_feature_arc, flist, + &pvar, priv0, priv1, priv2, priv3); + + /* check_output_feature_x4() returns bit mask which indicates + * which packet is not following feature path, hence normal processing + * has to happen on them + */ + if (unlikely(pvar.actual_feat_mask)) { + if (pvar.actual_feat_mask & 0x1) { + priv01.u32[1] += rte_cpu_to_be_16(0x0100); + /* Update ttl,cksum rewrite ethernet hdr on mbuf0 */ + d0 = rte_pktmbuf_mtod(mbuf0, void *); + rte_memcpy(d0, nh[priv01.u16[0]].rewrite_data, + nh[priv01.u16[0]].rewrite_len); + ip0 = (struct rte_ipv4_hdr *)((uint8_t *)d0 + + sizeof(struct rte_ether_hdr)); + ip0->time_to_live = priv01.u16[1] - 1; + ip0->hdr_checksum = priv01.u16[2] + priv01.u16[3]; + } + if (pvar.actual_feat_mask & 0x2) { + priv01.u32[3] += rte_cpu_to_be_16(0x0100); + /* Update ttl,cksum rewrite ethernet hdr on mbuf1 */ + d1 = rte_pktmbuf_mtod(mbuf1, void *); + rte_memcpy(d1, nh[priv01.u16[4]].rewrite_data, + nh[priv01.u16[4]].rewrite_len); + + ip1 = (struct rte_ipv4_hdr *)((uint8_t *)d1 + + sizeof(struct rte_ether_hdr)); + ip1->time_to_live = priv01.u16[5] - 1; + ip1->hdr_checksum = priv01.u16[6] + priv01.u16[7]; + } + if (pvar.actual_feat_mask & 0x4) { + priv23.u32[1] += rte_cpu_to_be_16(0x0100); + /* Update ttl,cksum rewrite ethernet hdr on mbuf2 */ + d2 = rte_pktmbuf_mtod(mbuf2, void *); + rte_memcpy(d2, nh[priv23.u16[0]].rewrite_data, + nh[priv23.u16[0]].rewrite_len); + ip2 = (struct rte_ipv4_hdr *)((uint8_t *)d2 + + sizeof(struct rte_ether_hdr)); + ip2->time_to_live = priv23.u16[1] - 1; + ip2->hdr_checksum = priv23.u16[2] + priv23.u16[3]; + } + if (pvar.actual_feat_mask & 0x8) { + priv23.u32[3] += rte_cpu_to_be_16(0x0100); + /* Update ttl,cksum rewrite ethernet hdr on mbuf3 */ + d3 = rte_pktmbuf_mtod(mbuf3, void *); + rte_memcpy(d3, nh[priv23.u16[4]].rewrite_data, + nh[priv23.u16[4]].rewrite_len); + ip3 = (struct rte_ipv4_hdr *)((uint8_t *)d3 + + sizeof(struct rte_ether_hdr)); + ip3->time_to_live = priv23.u16[5] - 1; + ip3->hdr_checksum = priv23.u16[6] + priv23.u16[7]; + } + } + } else { + /* Case when no feature is enabled */ + + /* Increment checksum by one. */ + priv01.u32[1] += rte_cpu_to_be_16(0x0100); + priv01.u32[3] += rte_cpu_to_be_16(0x0100); + priv23.u32[1] += rte_cpu_to_be_16(0x0100); + priv23.u32[3] += rte_cpu_to_be_16(0x0100); + + /* Update ttl,cksum rewrite ethernet hdr on mbuf0 */ + d0 = rte_pktmbuf_mtod(mbuf0, void *); + rte_memcpy(d0, nh[priv01.u16[0]].rewrite_data, + nh[priv01.u16[0]].rewrite_len); + + ip0 = (struct rte_ipv4_hdr *)((uint8_t *)d0 + + sizeof(struct rte_ether_hdr)); + ip0->time_to_live = priv01.u16[1] - 1; + ip0->hdr_checksum = priv01.u16[2] + priv01.u16[3]; + + /* Update ttl,cksum rewrite ethernet hdr on mbuf1 */ + d1 = rte_pktmbuf_mtod(mbuf1, void *); + rte_memcpy(d1, nh[priv01.u16[4]].rewrite_data, + nh[priv01.u16[4]].rewrite_len); + + ip1 = (struct rte_ipv4_hdr *)((uint8_t *)d1 + + sizeof(struct rte_ether_hdr)); + ip1->time_to_live = priv01.u16[5] - 1; + ip1->hdr_checksum = priv01.u16[6] + priv01.u16[7]; + + /* Update ttl,cksum rewrite ethernet hdr on mbuf2 */ + d2 = rte_pktmbuf_mtod(mbuf2, void *); + rte_memcpy(d2, nh[priv23.u16[0]].rewrite_data, + nh[priv23.u16[0]].rewrite_len); + ip2 = (struct rte_ipv4_hdr *)((uint8_t *)d2 + + sizeof(struct rte_ether_hdr)); + ip2->time_to_live = priv23.u16[1] - 1; + ip2->hdr_checksum = priv23.u16[2] + priv23.u16[3]; + + /* Update ttl,cksum rewrite ethernet hdr on mbuf3 */ + d3 = rte_pktmbuf_mtod(mbuf3, void *); + rte_memcpy(d3, nh[priv23.u16[4]].rewrite_data, + nh[priv23.u16[4]].rewrite_len); + + ip3 = (struct rte_ipv4_hdr *)((uint8_t *)d3 + + sizeof(struct rte_ether_hdr)); + ip3->time_to_live = priv23.u16[5] - 1; + ip3->hdr_checksum = priv23.u16[6] + priv23.u16[7]; + } /* Enqueue four to next node */ - rte_edge_t fix_spec = - ((next_index == next0) && (next0 == next1) && - (next1 == next2) && (next2 == next3)); + fix_spec = next_index ^ pvar.next0; + fix_spec += next_index ^ pvar.next1; + fix_spec += next_index ^ pvar.next2; + fix_spec += next_index ^ pvar.next3; - if (unlikely(fix_spec == 0)) { + if (unlikely(fix_spec != 0)) { /* Copy things successfully speculated till now */ rte_memcpy(to_next, from, last_spec * sizeof(from[0])); from += last_spec; @@ -146,56 +362,56 @@ ip4_rewrite_node_process(struct rte_graph *graph, struct rte_node *node, last_spec = 0; /* next0 */ - if (next_index == next0) { + if (next_index == pvar.next0) { to_next[0] = from[0]; to_next++; held++; } else { - rte_node_enqueue_x1(graph, node, next0, + rte_node_enqueue_x1(graph, node, pvar.next0, from[0]); } /* next1 */ - if (next_index == next1) { + if (next_index == pvar.next1) { to_next[0] = from[1]; to_next++; held++; } else { - rte_node_enqueue_x1(graph, node, next1, + rte_node_enqueue_x1(graph, node, pvar.next1, from[1]); } /* next2 */ - if (next_index == next2) { + if (next_index == pvar.next2) { to_next[0] = from[2]; to_next++; held++; } else { - rte_node_enqueue_x1(graph, node, next2, + rte_node_enqueue_x1(graph, node, pvar.next2, from[2]); } /* next3 */ - if (next_index == next3) { + if (next_index == pvar.next3) { to_next[0] = from[3]; to_next++; held++; } else { - rte_node_enqueue_x1(graph, node, next3, + rte_node_enqueue_x1(graph, node, pvar.next3, from[3]); } from += 4; /* Change speculation if last two are same */ - if ((next_index != next3) && (next2 == next3)) { + if ((next_index != pvar.next3) && (pvar.next2 == pvar.next3)) { /* Put the current speculated node */ rte_node_next_stream_put(graph, node, next_index, held); held = 0; /* Get next speculated stream */ - next_index = next3; + next_index = pvar.next3; to_next = rte_node_next_stream_get( graph, node, next_index, nb_objs); } @@ -212,20 +428,41 @@ ip4_rewrite_node_process(struct rte_graph *graph, struct rte_node *node, pkts += 1; n_left_from -= 1; - d0 = rte_pktmbuf_mtod(mbuf0, void *); - rte_memcpy(d0, nh[node_mbuf_priv1(mbuf0, dyn)->nh].rewrite_data, - nh[node_mbuf_priv1(mbuf0, dyn)->nh].rewrite_len); - - next0 = nh[node_mbuf_priv1(mbuf0, dyn)->nh].tx_node; - ip0 = (struct rte_ipv4_hdr *)((uint8_t *)d0 + - sizeof(struct rte_ether_hdr)); - chksum = node_mbuf_priv1(mbuf0, dyn)->cksum + - rte_cpu_to_be_16(0x0100); - chksum += chksum >= 0xffff; - ip0->hdr_checksum = chksum; - ip0->time_to_live = node_mbuf_priv1(mbuf0, dyn)->ttl - 1; - - if (unlikely(next_index ^ next0)) { + pvar.next0 = nh[node_mbuf_priv1(mbuf0, dyn)->nh].tx_node; + if (check_enabled_features) { + priv0 = node_mbuf_priv1(mbuf0, dyn); + if (pvar.next0 != (pvar.last_tx_interface + 1)) { + priv0->if_index = pvar.next0 - 1; + rte_graph_feature_arc_feature_set(out_feature_arc, flist, + priv0->if_index, + &priv0->current_feature, + &pvar.next0); + pvar.last_tx_interface = priv0->if_index; + pvar.last_if_feature = priv0->current_feature; + } else { + /* current mbuf index is same as last_tx_interface */ + priv0->if_index = pvar.last_tx_interface; + priv0->current_feature = pvar.last_if_feature; + } + } + /* Do the needful if either feature arc is disabled OR + * Invalid feature is present + */ + if (!check_enabled_features || + (priv0->current_feature == RTE_GRAPH_FEATURE_INVALID)) { + d0 = rte_pktmbuf_mtod(mbuf0, void *); + rte_memcpy(d0, nh[node_mbuf_priv1(mbuf0, dyn)->nh].rewrite_data, + nh[node_mbuf_priv1(mbuf0, dyn)->nh].rewrite_len); + + ip0 = (struct rte_ipv4_hdr *)((uint8_t *)d0 + + sizeof(struct rte_ether_hdr)); + chksum = node_mbuf_priv1(mbuf0, dyn)->cksum + + rte_cpu_to_be_16(0x0100); + chksum += chksum >= 0xffff; + ip0->hdr_checksum = chksum; + ip0->time_to_live = node_mbuf_priv1(mbuf0, dyn)->ttl - 1; + } + if (unlikely(next_index ^ pvar.next0)) { /* Copy things successfully speculated till now */ rte_memcpy(to_next, from, last_spec * sizeof(from[0])); from += last_spec; @@ -233,13 +470,15 @@ ip4_rewrite_node_process(struct rte_graph *graph, struct rte_node *node, held += last_spec; last_spec = 0; - rte_node_enqueue_x1(graph, node, next0, from[0]); + rte_node_enqueue_x1(graph, node, pvar.next0, from[0]); from += 1; } else { last_spec += 1; } } + IP4_REWRITE_NODE_LAST_TX(node->ctx) = pvar.last_tx_interface; + /* !!! Home run !!! */ if (likely(last_spec == nb_objs)) { rte_node_next_stream_move(graph, node, next_index); @@ -255,22 +494,78 @@ ip4_rewrite_node_process(struct rte_graph *graph, struct rte_node *node, return nb_objs; } +static uint16_t +ip4_rewrite_feature_node_process(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + struct rte_graph_feature_arc *arc = + rte_graph_feature_arc_get(IP4_REWRITE_NODE_OUTPUT_FEATURE_ARC(node->ctx)); + const int dyn = IP4_REWRITE_NODE_PRIV1_OFF(node->ctx); + rte_graph_feature_rt_list_t flist; + + /* If any feature is enabled on this arc */ + if (unlikely(rte_graph_feature_arc_has_any_feature(arc, &flist))) { + if (flist) + return __ip4_rewrite_node_process(graph, node, objs, nb_objs, + dyn, + 1 /* check features */, arc, + (rte_graph_feature_rt_list_t)1); + else + return __ip4_rewrite_node_process(graph, node, objs, nb_objs, + dyn, + 1 /* check features */, arc, + (rte_graph_feature_rt_list_t)0); + } else { + return __ip4_rewrite_node_process(graph, node, objs, nb_objs, dyn, + 0/* don't check features*/, NULL, + 0/* don't care */); + } + return 0; +} + +static uint16_t +ip4_rewrite_node_process(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + const int dyn = IP4_REWRITE_NODE_PRIV1_OFF(node->ctx); + + return __ip4_rewrite_node_process(graph, node, objs, nb_objs, dyn, + 0/* don't check features*/, NULL, + 0/* don't care */); +} + static int ip4_rewrite_node_init(const struct rte_graph *graph, struct rte_node *node) { + rte_graph_feature_arc_t feature_arc = RTE_GRAPH_FEATURE_ARC_INITIALIZER; static bool init_once; RTE_SET_USED(graph); RTE_BUILD_BUG_ON(sizeof(struct ip4_rewrite_node_ctx) > RTE_NODE_CTX_SZ); + RTE_BUILD_BUG_ON(sizeof(struct ip4_rewrite_nh_header) != RTE_CACHE_LINE_SIZE); if (!init_once) { node_mbuf_priv1_dynfield_offset = rte_mbuf_dynfield_register( &node_mbuf_priv1_dynfield_desc); if (node_mbuf_priv1_dynfield_offset < 0) return -rte_errno; - init_once = true; + + /* Create ipv4-output feature arc, if not created + */ + if (rte_graph_feature_arc_lookup_by_name(RTE_IP4_OUTPUT_FEATURE_ARC_NAME, + NULL) < 0) { + if (rte_graph_feature_arc_create(RTE_IP4_OUTPUT_FEATURE_ARC_NAME, + RTE_GRAPH_FEATURE_MAX_PER_ARC, + RTE_MAX_ETHPORTS, + ip4_rewrite_node_get(), &feature_arc)) { + return -rte_errno; + } + init_once = true; + } } IP4_REWRITE_NODE_PRIV1_OFF(node->ctx) = node_mbuf_priv1_dynfield_offset; + IP4_REWRITE_NODE_OUTPUT_FEATURE_ARC(node->ctx) = feature_arc; + IP4_REWRITE_NODE_LAST_TX(node->ctx) = UINT16_MAX; node_dbg("ip4_rewrite", "Initialized ip4_rewrite node initialized"); @@ -329,6 +624,7 @@ rte_node_ip4_rewrite_add(uint16_t next_hop, uint8_t *rewrite_data, static struct rte_node_register ip4_rewrite_node = { .process = ip4_rewrite_node_process, + .feat_arc_proc = ip4_rewrite_feature_node_process, .name = "ip4_rewrite", /* Default edge i.e '0' is pkt drop */ .nb_edges = 1, diff --git a/lib/node/ip4_rewrite_priv.h b/lib/node/ip4_rewrite_priv.h index 5105ec1d29..52f39601bd 100644 --- a/lib/node/ip4_rewrite_priv.h +++ b/lib/node/ip4_rewrite_priv.h @@ -5,9 +5,11 @@ #define __INCLUDE_IP4_REWRITE_PRIV_H__ #include <rte_common.h> +#include <rte_graph_feature_arc.h> #define RTE_GRAPH_IP4_REWRITE_MAX_NH 64 -#define RTE_GRAPH_IP4_REWRITE_MAX_LEN 56 +#define RTE_GRAPH_IP4_REWRITE_MAX_LEN (sizeof(struct rte_ether_hdr) + \ + (2 * sizeof(struct rte_vlan_hdr))) /** * @internal @@ -15,11 +17,9 @@ * Ipv4 rewrite next hop header data structure. Used to store port specific * rewrite data. */ -struct ip4_rewrite_nh_header { - uint16_t rewrite_len; /**< Header rewrite length. */ +struct __rte_cache_aligned ip4_rewrite_nh_header { uint16_t tx_node; /**< Tx node next index identifier. */ - uint16_t enabled; /**< NH enable flag */ - uint16_t rsvd; + uint16_t rewrite_len; /**< Header rewrite length. */ union { struct { struct rte_ether_addr dst; @@ -30,8 +30,13 @@ struct ip4_rewrite_nh_header { uint8_t rewrite_data[RTE_GRAPH_IP4_REWRITE_MAX_LEN]; /**< Generic rewrite data */ }; + /* used in control path */ + uint8_t enabled; /**< NH enable flag */ }; +_Static_assert(sizeof(struct ip4_rewrite_nh_header) <= (size_t)RTE_CACHE_LINE_SIZE, + "ip4_rewrite_nh_header size must be less or equal to cache line"); + /** * @internal * diff --git a/lib/node/node_private.h b/lib/node/node_private.h index 1de7306792..25db04a9a6 100644 --- a/lib/node/node_private.h +++ b/lib/node/node_private.h @@ -12,6 +12,9 @@ #include <rte_mbuf.h> #include <rte_mbuf_dyn.h> +#include <rte_graph_worker_common.h> +#include <rte_graph_feature_arc_worker.h> + extern int rte_node_logtype; #define RTE_LOGTYPE_NODE rte_node_logtype @@ -29,15 +32,28 @@ extern int rte_node_logtype; */ struct node_mbuf_priv1 { union { - /* IP4/IP6 rewrite */ + /** + * IP4/IP6 rewrite + * only used to pass lookup data from + * ip4-lookup to ip4-rewrite + */ struct { uint16_t nh; uint16_t ttl; uint32_t cksum; }; - uint64_t u; }; + /** + * Feature arc data + */ + struct { + /** interface index */ + uint16_t if_index; + /** feature that current mbuf holds */ + rte_graph_feature_t current_feature; + uint8_t rsvd; + }; }; static const struct rte_mbuf_dynfield node_mbuf_priv1_dynfield_desc = { diff --git a/lib/node/rte_node_ip4_api.h b/lib/node/rte_node_ip4_api.h index 950751a525..da4995662a 100644 --- a/lib/node/rte_node_ip4_api.h +++ b/lib/node/rte_node_ip4_api.h @@ -19,6 +19,7 @@ #include <rte_compat.h> #include <rte_graph.h> +#include <rte_graph_feature_arc_worker.h> #ifdef __cplusplus extern "C" { @@ -67,6 +68,8 @@ struct rte_node_ip4_reassembly_cfg { /**< Node identifier to configure. */ }; +#define RTE_IP4_OUTPUT_FEATURE_ARC_NAME "ipv4-output" + /** * Add ipv4 route to lookup table. * -- 2.43.0 ^ permalink raw reply [flat|nested] 46+ messages in thread
* [PATCH v4 4/5] test/graph_feature_arc: add functional tests 2024-10-10 13:31 ` [PATCH v4 " Nitin Saxena ` (2 preceding siblings ...) 2024-10-10 13:31 ` [PATCH v4 3/5] graph: add IPv4 output feature arc Nitin Saxena @ 2024-10-10 13:31 ` Nitin Saxena 2024-10-10 13:31 ` [PATCH v4 5/5] docs: add programming guide for feature arc Nitin Saxena 2024-10-14 14:33 ` [PATCH v5 0/5] add feature arc in rte_graph Nitin Saxena 5 siblings, 0 replies; 46+ messages in thread From: Nitin Saxena @ 2024-10-10 13:31 UTC (permalink / raw) To: Jerin Jacob, Kiran Kumar K, Nithin Dabilpuram, Zhirun Yan, Robin Jarry, Christophe Fontaine Cc: dev, Nitin Saxena Added functional unit test case for verifying feature arc control plane and fast path APIs How to run: $ echo "graph_feature_arc_autotest" | ./bin/dpdk-test Signed-off-by: Nitin Saxena <nsaxena@marvell.com> --- app/test/meson.build | 1 + app/test/test_graph_feature_arc.c | 1410 +++++++++++++++++++++++++++++ 2 files changed, 1411 insertions(+) create mode 100644 app/test/test_graph_feature_arc.c diff --git a/app/test/meson.build b/app/test/meson.build index e29258e6ec..740fa1bfb4 100644 --- a/app/test/meson.build +++ b/app/test/meson.build @@ -90,6 +90,7 @@ source_file_deps = { 'test_func_reentrancy.c': ['hash', 'lpm'], 'test_graph.c': ['graph'], 'test_graph_perf.c': ['graph'], + 'test_graph_feature_arc.c': ['graph'], 'test_hash.c': ['net', 'hash'], 'test_hash_functions.c': ['hash'], 'test_hash_multiwriter.c': ['hash'], diff --git a/app/test/test_graph_feature_arc.c b/app/test/test_graph_feature_arc.c new file mode 100644 index 0000000000..58b676e215 --- /dev/null +++ b/app/test/test_graph_feature_arc.c @@ -0,0 +1,1410 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(C) 2024 Marvell International Ltd. + */ + +#include "test.h" + +#include <assert.h> +#include <inttypes.h> +#include <signal.h> +#include <stdalign.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> + +#include <rte_errno.h> + +#ifndef RTE_EXEC_ENV_WINDOWS +#include <rte_graph.h> +#include <rte_graph_worker.h> +#include <rte_mbuf.h> +#include <rte_mbuf_dyn.h> +#include <rte_random.h> +#include <rte_graph_feature_arc.h> +#include <rte_graph_feature_arc_worker.h> + +#define MBUFF_SIZE 512 +#define TEST_ARC1_NAME "arc1" +#define TEST_ARC2_NAME "arc2" +#define MAX_INDEXES 10 +#define MAX_FEATURES 5 + +#define SOURCE1 "test_node_arc_source1" +#define INPUT_STATIC "test_node_arc_input_static" +#define OUTPUT_STATIC "test_node_arc_output_static" +#define PKT_FREE_STATIC "test_node_arc_pkt_free_static" +#define ARC1_FEATURE1 "test_node_arc1_feature1" +#define ARC1_FEATURE2 "test_node_arc1_feature2" +#define ARC2_FEATURE1 "test_node_arc2_feature1" +#define ARC2_FEATURE2 "test_node_arc2_feature2" +#define ARC2_FEATURE3 "test_node_arc2_feature3" +#define DUMMY1_STATIC "test_node_arc_dummy1_static" +#define DUMMY2_STATIC "test_node_arc_dummy2_static" + +/* (Node index, Node Name, feature user data base */ +#define FOREACH_TEST_NODE_ARC { \ + R(0, SOURCE1, 64) \ + R(1, INPUT_STATIC, 128) \ + R(2, OUTPUT_STATIC, 256) \ + R(3, PKT_FREE_STATIC, 512) \ + R(4, ARC1_FEATURE1, 1024) \ + R(5, ARC1_FEATURE2, 2048) \ + R(6, ARC2_FEATURE1, 4096) \ + R(7, ARC2_FEATURE2, 8192) \ + R(8, ARC2_FEATURE3, 16384) \ + R(9, DUMMY1_STATIC, 32768) \ + R(10, DUMMY2_STATIC, 65536) \ + } + +/** + * ARC1: Feature arc on ingress interface + * ARC2: Feature arc on egress interface + * XX_static: Static nodes + * XX_featureX: Feature X on arc + * + * -----> ARC1_FEATURE1 + * | | | + * | | v + * | | ARC1_FEATURE2 + * | | | + * | v v + * SOURCE1 ->-----> INPUT_STATIC --> OUTPUT_STATIC -----> PKT_FREE_STATIC + * | | | ^ ^ ^ + * | | | | | | + * | | --> ARC2_FEATURE1 | | + * | | ^ ^ | | + * | | | | | | + * | ----------c-> ARC2_FEATURE2 | + * | | ^ | + * | | | | + * ----------> ARC2_FEATURE3 ------- + */ +const char *node_names_feature_arc[] = { + SOURCE1, INPUT_STATIC, OUTPUT_STATIC, PKT_FREE_STATIC, + ARC1_FEATURE1, ARC1_FEATURE2, ARC2_FEATURE1, ARC2_FEATURE2, ARC2_FEATURE3, + DUMMY1_STATIC, DUMMY2_STATIC +}; + +#define MAX_NODES RTE_DIM(node_names_feature_arc) + +/* Function declarations */ +static uint16_t +source1_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs); +static uint16_t +input_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs); +static uint16_t +input_fa_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs); +static uint16_t +output_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs); +static uint16_t +output_fa_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs); +static uint16_t +pkt_free_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs); +static uint16_t +pkt_free_fa_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs); +static uint16_t +dummy1_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs); +static uint16_t +dummy2_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs); +static uint16_t +arc1_feature1_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs); +static uint16_t +arc1_feature1_fa_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs); +static uint16_t +arc1_feature2_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs); +static uint16_t +arc1_feature2_fa_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs); +static uint16_t +arc2_feature1_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs); +static uint16_t +arc2_feature1_fa_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs); +static uint16_t +arc2_feature2_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs); +static uint16_t +arc2_feature2_fa_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs); +static uint16_t +arc2_feature3_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs); +static uint16_t +arc2_feature3_fa_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs); +static int +common_node_init(const struct rte_graph *graph, struct rte_node *node); + +typedef struct test_node_priv { + /* index from 0 - MAX_NODES -1 */ + uint8_t node_index; + + /* feature */ + rte_graph_feature_t feature; + + /* rte_graph node id */ + uint32_t node_id; + + rte_graph_feature_arc_t arc; +} test_node_priv_t; + +typedef struct { + rte_graph_feature_t feature; + uint16_t egress_interface; + uint16_t ingress_interface; +} graph_dynfield_t; + +static int graph_dynfield_offset = -1; +static rte_graph_feature_arc_t arcs[RTE_GRAPH_FEATURE_ARC_MAX + 128]; +static struct rte_mbuf mbuf[MAX_NODES + 1][MBUFF_SIZE]; +static void *mbuf_p[MAX_NODES + 1][MBUFF_SIZE]; +static rte_graph_t graph_id = RTE_GRAPH_ID_INVALID; + +const char *node_patterns_feature_arc[] = { + "test_node_arc*" +}; + +static int32_t +compute_unique_user_data(const char *parent, const char *child, uint32_t interface_index) +{ + uint32_t user_data = interface_index; + + RTE_SET_USED(parent); +#define R(idx, node, node_cookie) { \ + if (!strcmp(child, node)) { \ + user_data += node_cookie; \ + } \ + } + + FOREACH_TEST_NODE_ARC +#undef R + + return user_data; +} + +static int +get_edge(struct rte_node_register *parent_node, + struct rte_node_register *child_node, rte_edge_t *_edge) +{ + char **next_edges = NULL; + uint32_t count, i; + + count = rte_node_edge_get(parent_node->id, NULL); + + if (!count) + return -1; + + next_edges = malloc(count); + + if (!next_edges) + return -1; + + count = rte_node_edge_get(parent_node->id, next_edges); + for (i = 0; i < count; i++) { + if (strstr(child_node->name, next_edges[i])) { + if (_edge) + *_edge = (rte_edge_t)i; + + free(next_edges); + return 0; + } + } + free(next_edges); + + return -1; +} + +int +common_node_init(const struct rte_graph *graph, struct rte_node *node) +{ + test_node_priv_t *priv = (test_node_priv_t *)node->ctx; + + RTE_SET_USED(graph); + + priv->node_id = node->id; + priv->feature = RTE_GRAPH_FEATURE_INVALID; + priv->arc = RTE_GRAPH_FEATURE_ARC_INITIALIZER; + +#define R(idx, _name, user_data) { \ + if (!strcmp(node->name, _name)) { \ + priv->node_index = idx; \ + } \ + } + FOREACH_TEST_NODE_ARC +#undef R + + return 0; +} + +uint16_t +source1_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + RTE_SET_USED(graph); + RTE_SET_USED(node); + RTE_SET_USED(objs); + RTE_SET_USED(nb_objs); + return 0; +} + +static struct rte_node_register source1 = { + .name = SOURCE1, + .process = source1_fn, + .flags = RTE_NODE_SOURCE_F, + .nb_edges = 3, + .init = common_node_init, + .next_nodes = {INPUT_STATIC, DUMMY1_STATIC, DUMMY2_STATIC}, +}; +RTE_NODE_REGISTER(source1); + +uint16_t +input_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + RTE_SET_USED(graph); + RTE_SET_USED(node); + RTE_SET_USED(objs); + RTE_SET_USED(nb_objs); + return 0; +} + +uint16_t +input_fa_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + RTE_SET_USED(graph); + RTE_SET_USED(node); + RTE_SET_USED(objs); + RTE_SET_USED(nb_objs); + return 0; +} + +static struct rte_node_register input = { + .name = INPUT_STATIC, + .process = input_fn, + .feat_arc_proc = input_fa_fn, + .nb_edges = 2, + .init = common_node_init, + .next_nodes = {OUTPUT_STATIC, DUMMY1_STATIC}, +}; +RTE_NODE_REGISTER(input); + +uint16_t +output_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + RTE_SET_USED(graph); + RTE_SET_USED(node); + RTE_SET_USED(objs); + RTE_SET_USED(nb_objs); + return 0; +} + +uint16_t +output_fa_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + RTE_SET_USED(graph); + RTE_SET_USED(node); + RTE_SET_USED(objs); + RTE_SET_USED(nb_objs); + return 0; +} + +static struct rte_node_register output = { + .name = OUTPUT_STATIC, + .process = output_fn, + .feat_arc_proc = output_fa_fn, + .nb_edges = 3, + .init = common_node_init, + .next_nodes = {DUMMY1_STATIC, PKT_FREE_STATIC, DUMMY2_STATIC}, +}; +RTE_NODE_REGISTER(output); + +uint16_t +pkt_free_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + RTE_SET_USED(graph); + RTE_SET_USED(node); + RTE_SET_USED(objs); + RTE_SET_USED(nb_objs); + return 0; +} + +uint16_t +pkt_free_fa_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + RTE_SET_USED(graph); + RTE_SET_USED(node); + RTE_SET_USED(objs); + RTE_SET_USED(nb_objs); + return 0; +} + +static struct rte_node_register pkt_free = { + .name = PKT_FREE_STATIC, + .process = pkt_free_fn, + .feat_arc_proc = pkt_free_fa_fn, + .nb_edges = 1, + .init = common_node_init, + .next_nodes = {DUMMY1_STATIC}, +}; +RTE_NODE_REGISTER(pkt_free); + +uint16_t +dummy1_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + RTE_SET_USED(graph); + RTE_SET_USED(node); + RTE_SET_USED(objs); + RTE_SET_USED(nb_objs); + return 0; +} + +static struct rte_node_register dummy1 = { + .name = DUMMY1_STATIC, + .process = dummy1_fn, + .nb_edges = 0, + .init = common_node_init, +}; +RTE_NODE_REGISTER(dummy1); + +uint16_t +dummy2_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + RTE_SET_USED(graph); + RTE_SET_USED(node); + RTE_SET_USED(objs); + RTE_SET_USED(nb_objs); + return 0; +} + +static struct rte_node_register dummy2 = { + .name = DUMMY2_STATIC, + .process = dummy2_fn, + .nb_edges = 5, + .init = common_node_init, + .next_nodes = { ARC1_FEATURE1, ARC1_FEATURE2, ARC2_FEATURE1, + ARC2_FEATURE2, ARC2_FEATURE3}, +}; +RTE_NODE_REGISTER(dummy2); + +uint16_t +arc1_feature1_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + RTE_SET_USED(graph); + RTE_SET_USED(node); + RTE_SET_USED(objs); + RTE_SET_USED(nb_objs); + + return 0; +} + +uint16_t +arc1_feature1_fa_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + RTE_SET_USED(graph); + RTE_SET_USED(node); + RTE_SET_USED(objs); + RTE_SET_USED(nb_objs); + + return 0; +} + +static struct rte_node_register arc1_feature1 = { + .name = ARC1_FEATURE1, + .process = arc1_feature1_fn, + .feat_arc_proc = arc1_feature1_fa_fn, + .nb_edges = 0, + .init = common_node_init, +}; +RTE_NODE_REGISTER(arc1_feature1); + +uint16_t +arc1_feature2_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + RTE_SET_USED(graph); + RTE_SET_USED(node); + RTE_SET_USED(objs); + RTE_SET_USED(nb_objs); + + return 0; +} + +uint16_t +arc1_feature2_fa_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + RTE_SET_USED(graph); + RTE_SET_USED(node); + RTE_SET_USED(objs); + RTE_SET_USED(nb_objs); + + return 0; +} + +static struct rte_node_register arc1_feature2 = { + .name = ARC1_FEATURE2, + .process = arc1_feature2_fn, + .feat_arc_proc = arc1_feature2_fa_fn, + .nb_edges = 0, + .init = common_node_init, +}; +RTE_NODE_REGISTER(arc1_feature2); + +uint16_t +arc2_feature1_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + RTE_SET_USED(graph); + RTE_SET_USED(node); + RTE_SET_USED(objs); + RTE_SET_USED(nb_objs); + + return 0; +} + +uint16_t +arc2_feature1_fa_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + RTE_SET_USED(graph); + RTE_SET_USED(node); + RTE_SET_USED(objs); + RTE_SET_USED(nb_objs); + + return 0; +} + +static struct rte_node_register arc2_feature1 = { + .name = ARC2_FEATURE1, + .process = arc2_feature1_fn, + .feat_arc_proc = arc2_feature1_fa_fn, + .nb_edges = 0, + .init = common_node_init, +}; +RTE_NODE_REGISTER(arc2_feature1); + +uint16_t +arc2_feature2_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + RTE_SET_USED(graph); + RTE_SET_USED(node); + RTE_SET_USED(objs); + RTE_SET_USED(nb_objs); + + return 0; +} + +uint16_t +arc2_feature2_fa_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + RTE_SET_USED(graph); + RTE_SET_USED(node); + RTE_SET_USED(objs); + RTE_SET_USED(nb_objs); + + return 0; +} + +static struct rte_node_register arc2_feature2 = { + .name = ARC2_FEATURE2, + .process = arc2_feature2_fn, + .feat_arc_proc = arc2_feature2_fa_fn, + .nb_edges = 0, + .init = common_node_init, +}; +RTE_NODE_REGISTER(arc2_feature2); + +uint16_t +arc2_feature3_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + RTE_SET_USED(graph); + RTE_SET_USED(node); + RTE_SET_USED(objs); + RTE_SET_USED(nb_objs); + + return 0; +} + +uint16_t +arc2_feature3_fa_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + RTE_SET_USED(graph); + RTE_SET_USED(node); + RTE_SET_USED(objs); + RTE_SET_USED(nb_objs); + + return 0; +} + +static struct rte_node_register arc2_feature3 = { + .name = ARC2_FEATURE3, + .process = arc2_feature3_fn, + .feat_arc_proc = arc2_feature3_fa_fn, + .nb_edges = 0, + .init = common_node_init, +}; +RTE_NODE_REGISTER(arc2_feature3); + +static int +create_graph(void) +{ + struct rte_graph_param gconf = { + .socket_id = SOCKET_ID_ANY, + .nb_node_patterns = 1, + .node_patterns = node_patterns_feature_arc, + }; + + graph_id = rte_graph_create("worker0", &gconf); + if (graph_id == RTE_GRAPH_ID_INVALID) { + printf("Graph creation failed with error = %d\n", rte_errno); + return TEST_FAILED; + } + + return TEST_SUCCESS; +} + +static int +__test_create_feature_arc(rte_graph_feature_arc_t *arcs, int max_arcs) +{ + rte_graph_feature_arc_t arc; + const char *sample_arc_name = "sample_arc"; + char arc_name[256]; + int n_arcs; + + /* Create max number of feature arcs first */ + for (n_arcs = 0; n_arcs < max_arcs; n_arcs++) { + snprintf(arc_name, sizeof(arc_name), "%s-%u", sample_arc_name, n_arcs); + if (rte_graph_feature_arc_create(arc_name, MAX_FEATURES, + MAX_INDEXES, &dummy1, &arcs[n_arcs])) { + printf("Feature arc creation failed for %u\n", n_arcs); + return TEST_FAILED; + } + } + /* Verify feature arc created more than max_arcs must fail */ + if (!rte_graph_feature_arc_create("negative_test_create_arc", MAX_FEATURES, + MAX_INDEXES, &dummy2, &arc)) { + printf("Feature arc creation success for more than max configured: %u\n", n_arcs); + return TEST_FAILED; + } + /* Make sure lookup passes for all feature arcs */ + for (n_arcs = 0; n_arcs < max_arcs; n_arcs++) { + snprintf(arc_name, sizeof(arc_name), "%s-%u", sample_arc_name, n_arcs); + arc = RTE_GRAPH_FEATURE_ARC_INITIALIZER; + if (!rte_graph_feature_arc_lookup_by_name(arc_name, &arc)) { + if (arc != arcs[n_arcs]) { + printf("%s: Feature arc lookup mismatch for arc [%p, exp: %p]\n", + arc_name, (void *)arc, (void *)arcs[n_arcs]); + return TEST_FAILED; + } + } else { + printf("Feature arc lookup %s failed after creation\n", arc_name); + return TEST_FAILED; + } + } + return TEST_SUCCESS; +} + +static int +test_graph_feature_arc_create(void) +{ + int ret = 0, i; + + /* Create arcs with RTE_GRAPH_FEATURE_ARC_MAX */ + ret = __test_create_feature_arc(arcs, RTE_GRAPH_FEATURE_ARC_MAX); + if (ret) { + printf("Feature arc creation test failed for RTE_GRAPH_FEATURE_ARC_MAX arcs\n"); + return TEST_FAILED; + } + /* destroy all arcs via cleanup API*/ + ret = rte_graph_feature_arc_cleanup(); + if (ret) { + printf("Feature arc cleanup failed\n"); + return TEST_FAILED; + } + +#define NUM_FEAT_ARCS 128 + /* create 128 dummy feature arcs */ + ret = rte_graph_feature_arc_init(NUM_FEAT_ARCS); + if (ret) { + printf("Feature arc init failed for NUM_FEAT_ARCS"); + return TEST_FAILED; + } + ret = __test_create_feature_arc(arcs, NUM_FEAT_ARCS); + if (ret) { + printf("Feature arc creation test failed for NUM_FEAT_ARCS\n"); + return TEST_FAILED; + } + /* destroy all of them*/ + for (i = 0; i < NUM_FEAT_ARCS; i++) { + if (rte_graph_feature_arc_destroy(arcs[i])) { + printf("Feature arc destroy failed for %u\n", i); + return TEST_FAILED; + } + } + rte_graph_feature_arc_cleanup(); + + /* Create two arcs as per test plan */ + /* First arc start/source node is node: SOURCE1 */ + if (rte_graph_feature_arc_create(TEST_ARC1_NAME, MAX_FEATURES, + MAX_INDEXES, &source1, &arcs[0])) { + printf("Feature arc creation failed for %s\n", TEST_ARC1_NAME); + return TEST_FAILED; + } + + /* Duplicate name should fail */ + if (!rte_graph_feature_arc_create(TEST_ARC1_NAME, MAX_FEATURES, + MAX_INDEXES, &source1, &arcs[1])) { + printf("Duplicate feature arc %s creation is not caught\n", TEST_ARC1_NAME); + return TEST_FAILED; + } + /* Second arc start/source node is node: OUTPUT_STATIC */ + if (rte_graph_feature_arc_create(TEST_ARC2_NAME, MAX_FEATURES, + MAX_INDEXES, &output, &arcs[1])) { + printf("Feature arc creation failed for %s\n", TEST_ARC1_NAME); + return TEST_FAILED; + } + return TEST_SUCCESS; +} + +static int +test_graph_feature_arc_features_add(void) +{ + rte_graph_feature_t temp; + + /* First feature to SOURCE1 start node -> ARC1_FEATURE1 */ + if (rte_graph_feature_add(arcs[0], &arc1_feature1, NULL, NULL)) { + printf("%s: Feature add failed for adding feature %s\n", + TEST_ARC1_NAME, ARC1_FEATURE1); + return TEST_FAILED; + } + /* Second feature to SOURCE1 -> ARC1_FEATURE2 */ + if (rte_graph_feature_add(arcs[0], &arc1_feature2, NULL, NULL)) { + printf("%s: Feature add failed for adding feature %s\n", + TEST_ARC1_NAME, ARC1_FEATURE2); + return TEST_FAILED; + } + /* adding statically connected INPUT_STATIC as a last feature */ + if (rte_graph_feature_add(arcs[0], &input, ARC1_FEATURE2, NULL)) { + printf("%s: Feature add failed for adding feature %s after %s\n", + TEST_ARC1_NAME, INPUT_STATIC, ARC1_FEATURE2); + return TEST_FAILED; + } + /* First feature to OUTPUT_STATIC start node -> ARC2_FEATURE3 */ + if (rte_graph_feature_add(arcs[1], &arc2_feature3, NULL, NULL)) { + printf("%s: Feature add failed for adding feature %s\n", + TEST_ARC2_NAME, ARC2_FEATURE3); + return TEST_FAILED; + } + /* Second feature to OUTPUT_STATIC -> ARC2_FEATURE1 and before feature to + * ARC2_FEATURE3 + */ + if (rte_graph_feature_add(arcs[1], &arc2_feature1, NULL, ARC2_FEATURE3)) { + printf("%s: Feature add failed for adding feature %s after %s\n", + TEST_ARC2_NAME, ARC2_FEATURE3, ARC2_FEATURE1); + return TEST_FAILED; + } + /* Add PKT_FREE node as last feature, next to arc2_feature3 */ + if (rte_graph_feature_add(arcs[1], &pkt_free, ARC2_FEATURE3, NULL)) { + printf("%s: Feature add failed for adding feature %s after %s\n", + TEST_ARC2_NAME, PKT_FREE_STATIC, ARC2_FEATURE3); + return TEST_FAILED; + } + /* Adding feature ARC2_FEATURE2 between ARC2_FEATURE1 and ARC2_FEATURE3. */ + if (rte_graph_feature_add(arcs[1], &arc2_feature2, ARC2_FEATURE1, ARC2_FEATURE3)) { + printf("%s: Feature add failed for adding feature %s between [%s - %s]\n", + TEST_ARC2_NAME, ARC2_FEATURE2, ARC2_FEATURE1, ARC2_FEATURE3); + return TEST_FAILED; + } + /* Now check feature sequencing is correct for both ARCS */ + + /* arc1_feature1 must be first feature to arcs[0] */ + if (!strstr(ARC1_FEATURE1, + rte_graph_feature_arc_feature_to_name(arcs[0], + rte_graph_feature_cast(0)))) { + printf("%s: %s is not the first feature instead %s\n", + TEST_ARC1_NAME, ARC1_FEATURE1, + rte_graph_feature_arc_feature_to_name(arcs[0], rte_graph_feature_cast(0))); + return TEST_FAILED; + } + + /* arc1_feature2 must be second feature to arcs[0] */ + if (!strstr(ARC1_FEATURE2, + rte_graph_feature_arc_feature_to_name(arcs[0], + rte_graph_feature_cast(1)))) { + printf("%s: %s is not the second feature instead %s\n", + TEST_ARC1_NAME, ARC1_FEATURE2, + rte_graph_feature_arc_feature_to_name(arcs[0], rte_graph_feature_cast(1))); + return TEST_FAILED; + } + + /* Make sure INPUT_STATIC is the last feature in arcs[0] */ + temp = rte_graph_feature_arc_num_features(arcs[0]); + if (!strstr(INPUT_STATIC, + rte_graph_feature_arc_feature_to_name(arcs[0], + temp - rte_graph_feature_cast(1)))) { + printf("%s: %s is not the last feature instead %s\n", + TEST_ARC1_NAME, INPUT_STATIC, + rte_graph_feature_arc_feature_to_name(arcs[0], + temp - rte_graph_feature_cast(1))); + return TEST_FAILED; + } + + /* arc2_feature1 must be first feature to arcs[1] */ + if (!strstr(ARC2_FEATURE1, + rte_graph_feature_arc_feature_to_name(arcs[1], + rte_graph_feature_cast(0)))) { + printf("%s: %s is not the first feature instead %s\n", + TEST_ARC2_NAME, ARC2_FEATURE1, + rte_graph_feature_arc_feature_to_name(arcs[1], rte_graph_feature_cast(0))); + return TEST_FAILED; + } + + /* arc2_feature2 must be second feature to arcs[1] */ + if (!strstr(ARC2_FEATURE2, + rte_graph_feature_arc_feature_to_name(arcs[1], + rte_graph_feature_cast(1)))) { + printf("%s: %s is not the second feature instead %s\n", + TEST_ARC2_NAME, ARC2_FEATURE2, + rte_graph_feature_arc_feature_to_name(arcs[1], rte_graph_feature_cast(1))); + return TEST_FAILED; + } + + /* arc2_feature3 must be third feature to arcs[1] */ + if (!strstr(ARC2_FEATURE3, + rte_graph_feature_arc_feature_to_name(arcs[1], + rte_graph_feature_cast(2)))) { + printf("%s: %s is not the third feature instead %s\n", + TEST_ARC2_NAME, ARC2_FEATURE3, + rte_graph_feature_arc_feature_to_name(arcs[1], rte_graph_feature_cast(2))); + return TEST_FAILED; + } + + /* Make sure PKT_FREE is the last feature in arcs[1] */ + temp = rte_graph_feature_arc_num_features(arcs[1]); + if (!strstr(PKT_FREE_STATIC, + rte_graph_feature_arc_feature_to_name(arcs[1], + temp - rte_graph_feature_cast(1)))) { + printf("%s: %s is not the last feature instead %s\n", + TEST_ARC2_NAME, PKT_FREE_STATIC, + rte_graph_feature_arc_feature_to_name(arcs[1], + temp - rte_graph_feature_cast(1))); + return TEST_FAILED; + } + + if (get_edge(&arc2_feature1, &pkt_free, NULL)) { + printf("%s: Edge not found between %s and %s\n", + TEST_ARC2_NAME, ARC2_FEATURE1, PKT_FREE_STATIC); + return TEST_FAILED; + } + + return create_graph(); +} + +static int +test_graph_feature_arc_first_feature_enable(void) +{ + uint32_t n_indexes, n_features, count = 0; + rte_graph_feature_rt_list_t feature_list, temp = 0; + struct rte_node_register *parent, *child; + rte_graph_feature_data_t *fdata = NULL; + struct rte_graph_feature_arc *arc; + rte_graph_feature_t feature; + char *feature_name = NULL; + int32_t user_data; + rte_edge_t edge = ~0; + + arc = rte_graph_feature_arc_get(arcs[0]); + + if (rte_graph_feature_arc_has_any_feature(arc, &feature_list)) { + printf("%s: Feature arc should not have any feature enabled by now\n", + TEST_ARC1_NAME); + return TEST_FAILED; + } + + if (rte_graph_feature_arc_num_enabled_features(arcs[0])) { + printf("%s: Feature arc should not have any_feature() enabled by now\n", + TEST_ARC1_NAME); + return TEST_FAILED; + } + /* + * On interface 0, enable feature 0, + * On interface 1, enable feature 1 and so on so forth + * + * later verify first feature on every interface index is unique + * and check [rte_edge, user_data] retrieved via fast path APIs + */ + for (n_indexes = 0; n_indexes < MAX_INDEXES; n_indexes++) { + n_features = n_indexes % 3 /* 3 features added to arc1 */; + feature_name = rte_graph_feature_arc_feature_to_name(arcs[0], n_features); + user_data = compute_unique_user_data(arc->start_node->name, feature_name, + n_indexes); + if (rte_graph_feature_validate(arcs[0], n_indexes, feature_name, 1, true)) { + printf("%s: Feature validate failed for %s on index %u\n", + TEST_ARC1_NAME, feature_name, n_indexes); + return TEST_FAILED; + } + /* negative test case. enable feature on invalid index */ + if (!n_indexes && !rte_graph_feature_enable(arcs[0], MAX_INDEXES, feature_name, + (int32_t)user_data)) { + printf("%s: Feature %s should not be enabled on invalid index\n", + TEST_ARC1_NAME, feature_name); + return TEST_FAILED; + } + if (rte_graph_feature_enable(arcs[0], n_indexes, feature_name, + (int32_t)user_data)) { + printf("%s: Feature enable failed for %s on index %u\n", + TEST_ARC1_NAME, feature_name, n_indexes); + return TEST_FAILED; + } + /* has any feature should be valid */ + if (!rte_graph_feature_arc_has_any_feature(arc, &feature_list)) { + printf("%s: Feature arc should have any_feature enabled by now\n", + TEST_ARC1_NAME); + return TEST_FAILED; + } + if (temp == feature_list) { + printf("%s: Activer feature list not switched from %u -> %u\n", + TEST_ARC1_NAME, temp, feature_list); + return TEST_FAILED; + } + temp = feature_list; + if ((count + 1) != rte_graph_feature_arc_num_enabled_features(arcs[0])) { + printf("%s: Number of enabled mismatches [found: %u, exp: %u]\n", + TEST_ARC1_NAME, + rte_graph_feature_arc_num_enabled_features(arcs[0]), + count + 1); + return TEST_FAILED; + } + count++; + } + if (!rte_graph_feature_arc_has_any_feature(arc, &feature_list)) { + printf("%s: Feature arc should have any_feature enabled by now\n", + TEST_ARC1_NAME); + return TEST_FAILED; + } + /* Negative test case */ + user_data = compute_unique_user_data(arc->start_node->name, ARC2_FEATURE1, 1); + if (!rte_graph_feature_enable(arcs[0], 1 /* index */, ARC2_FEATURE1, user_data)) { + printf("%s: Invalid feature %s is enabled on index 1\n", + TEST_ARC1_NAME, ARC2_FEATURE1); + return TEST_FAILED; + } + /* Duplicate enable */ + if (!rte_graph_feature_enable(arcs[0], 1 /* index */, ARC1_FEATURE2, user_data)) { + printf("%s: Duplicate feature %s shouldn't be enabled again on index 1\n", + TEST_ARC1_NAME, ARC1_FEATURE2); + return TEST_FAILED; + } + for (n_indexes = 0; n_indexes < MAX_INDEXES; n_indexes++) { + if (!rte_graph_feature_arc_first_feature_get(arc, feature_list, n_indexes, + &feature)) { + printf("%s: No first feature enabled on index: %u\n", + TEST_ARC1_NAME, n_indexes); + return TEST_FAILED; + } + /* Get first feature data and ensure edge and user_data are correct */ + fdata = rte_graph_feature_data_get(arc, rte_graph_feature_get(arc, feature), + n_indexes); + parent = arc->start_node; + if (0 == (n_indexes % 3)) + child = &arc1_feature1; + else if (1 == (n_indexes % 3)) + child = &arc1_feature2; + else + child = &input; + + if (get_edge(parent, child, &edge)) { + printf("%s: Edge not found between %s and %s\n", + TEST_ARC1_NAME, parent->name, child->name); + return TEST_FAILED; + } + if (fdata->next_edge != edge) { + printf("%s: Edge mismatch for first feature on index %u [%u, exp: %u]\n", + TEST_ARC1_NAME, n_indexes, fdata->next_edge, edge); + return TEST_FAILED; + } + if (fdata->user_data != compute_unique_user_data(parent->name, child->name, + n_indexes)) { + printf("%s: First feature user data mismatch on index %u [%u, exp: %u]\n", + TEST_ARC1_NAME, n_indexes, fdata->user_data, + compute_unique_user_data(parent->name, child->name, n_indexes)); + return TEST_FAILED; + } + } + return TEST_SUCCESS; +} + +static int +verify_feature_sequencing(struct rte_graph_feature_arc *arc) +{ + rte_graph_feature_rt_list_t feature_list; + struct rte_node_register *parent, *child; + rte_graph_feature_data_t *fdata = NULL; + rte_graph_feature_t feature; + uint32_t n_indexes; + rte_edge_t edge = ~0; + int32_t user_data; + + if (!rte_graph_feature_arc_has_any_feature(arc, &feature_list)) { + printf("%s: feature_list can't be obtained\n", + arc->feature_arc_name); + return TEST_FAILED; + } + /* Verify next features on interface 0 and interface 1*/ + for (n_indexes = 0; n_indexes < 2; n_indexes++) { + if (!rte_graph_feature_arc_first_feature_get(arc, feature_list, n_indexes, + &feature)) { + printf("%s: No first feature enabled on index: 0\n", + arc->feature_arc_name); + return TEST_FAILED; + } + parent = arc->start_node; + child = rte_graph_feature_arc_feature_to_node(arcs[1], feature); + /* until fast path API reaches last feature i.e pkt_free */ + while (child != &pkt_free) { + fdata = rte_graph_feature_data_get(arc, + rte_graph_feature_get(arc, feature), + n_indexes); + + if (get_edge(parent, child, &edge)) { + printf("%s: Edge not found between %s and %s\n", + arc->feature_arc_name, parent->name, child->name); + return TEST_FAILED; + } + user_data = compute_unique_user_data(parent->name, child->name, n_indexes); + if (fdata->next_edge != edge) { + printf("%s: Edge mismatch for %s->%s on index %u [%u, exp: %u]\n", + arc->feature_arc_name, parent->name, child->name, n_indexes, + fdata->next_edge, edge); + return TEST_FAILED; + } + if (fdata->user_data != user_data) { + printf("%s: Udata mismatch for %s->%s on index %u [%u, exp: %u]\n", + arc->feature_arc_name, parent->name, child->name, n_indexes, + fdata->user_data, user_data); + return TEST_FAILED; + } + + feature = fdata->next_enabled_feature; + + parent = child; + child = rte_graph_feature_arc_feature_to_node(arcs[1], + fdata->next_enabled_feature); + } + } + return TEST_SUCCESS; +} + +static int +test_graph_feature_arc_next_feature_enable(void) +{ + rte_graph_feature_rt_list_t feature_list; + struct rte_node_register *parent, *child; + rte_graph_feature_data_t *fdata = NULL; + struct rte_graph_feature_arc *arc; + uint32_t n_indexes, n_features; + rte_graph_feature_t feature; + char *feature_name = NULL; + rte_edge_t edge = ~0; + int32_t user_data; + + arc = rte_graph_feature_arc_get(arcs[1]); + + if (rte_graph_feature_arc_has_any_feature(arc, &feature_list)) { + printf("%s: Feature arc should not have any feature enabled by now\n", + TEST_ARC2_NAME); + return TEST_FAILED; + } + + if (rte_graph_feature_arc_num_enabled_features(arcs[1])) { + printf("%s: Feature arc should not have any_feature() enabled by now\n", + TEST_ARC2_NAME); + return TEST_FAILED; + } + /* + * On interface 0, enable feature 2, skip feature 1 for later + * On interface 1, enable feature 3 + * On interface 2, enable pkt_free feature + * On interface 3, continue as interface 0 + * + * later enable next feature sequence for interface 0 from feature2 -> pkt_free + * later enable next feature sequence for interface 1 from feature3 -> pkt_free + * + * also later enable feature-1 and see first feature changes for all indexes + */ + for (n_indexes = 0; n_indexes < MAX_INDEXES; n_indexes++) { + n_features = (n_indexes % 3) + 1; /* feature2 to pkt_free are 3 features */ + feature_name = rte_graph_feature_arc_feature_to_name(arcs[1], n_features); + user_data = compute_unique_user_data(arc->start_node->name, feature_name, + n_indexes); + if (rte_graph_feature_enable(arcs[1], n_indexes, feature_name, + (int32_t)user_data)) { + printf("%s: Feature enable failed for %s on index %u\n", + TEST_ARC2_NAME, feature_name, n_indexes); + return TEST_FAILED; + } + /* has any feature should be valid */ + if (!rte_graph_feature_arc_has_any_feature(arc, &feature_list)) { + printf("%s: Feature arc should have any_feature enabled by now\n", + TEST_ARC2_NAME); + return TEST_FAILED; + } + } + /* Retrieve latest feature_list */ + rte_graph_feature_arc_has_any_feature(arc, &feature_list); + /* verify first feature */ + for (n_indexes = 0; n_indexes < MAX_INDEXES; n_indexes++) { + if (!rte_graph_feature_arc_first_feature_get(arc, feature_list, n_indexes, + &feature)) { + printf("%s: No first feature enabled on index: %u\n", + TEST_ARC2_NAME, n_indexes); + return TEST_FAILED; + } + /* Get first feature data and ensure edge and user_data are correct */ + fdata = rte_graph_feature_data_get(arc, rte_graph_feature_get(arc, feature), + n_indexes); + parent = arc->start_node; + if (0 == (n_indexes % 3)) + child = &arc2_feature2; + else if (1 == (n_indexes % 3)) + child = &arc2_feature3; + else + child = &pkt_free; + + if (get_edge(parent, child, &edge)) { + printf("%s: Edge not found between %s and %s\n", + TEST_ARC2_NAME, parent->name, child->name); + return TEST_FAILED; + } + if (fdata->next_edge != edge) { + printf("%s: Edge mismatch for first feature on index %u [%u, exp: %u]\n", + TEST_ARC2_NAME, n_indexes, fdata->next_edge, edge); + return TEST_FAILED; + } + if (fdata->user_data != compute_unique_user_data(parent->name, child->name, + n_indexes)) { + printf("%s: First feature user data mismatch on index %u [%u, exp: %u]\n", + TEST_ARC2_NAME, n_indexes, fdata->user_data, + compute_unique_user_data(parent->name, child->name, n_indexes)); + return TEST_FAILED; + } + } + /* add next_features now + * On interface 0, enable feature-3 and pkt_free + * On interface 1, enable pkt_free + * Skip interface 2 + * On interface 3, same as interface 0 + * On interface 4, same as interface 1 + */ + for (n_indexes = 0; n_indexes < MAX_INDEXES; n_indexes++) { + if (0 == (n_indexes % 3)) { + if (rte_graph_feature_enable(arcs[1], n_indexes, ARC2_FEATURE3, + compute_unique_user_data(ARC2_FEATURE2, + ARC2_FEATURE3, + n_indexes))) { + printf("%s: Feature enable failed for %s -> (%s) on index %u\n", + TEST_ARC2_NAME, ARC2_FEATURE2, ARC2_FEATURE3, n_indexes); + return TEST_FAILED; + } + } + /* pkt_free on interface-0, 1, 3, 4 and so on */ + if ((0 == (n_indexes % 3)) || (1 == (n_indexes % 3))) { + if (rte_graph_feature_enable(arcs[1], n_indexes, PKT_FREE_STATIC, + compute_unique_user_data(ARC2_FEATURE3, + PKT_FREE_STATIC, + n_indexes))) { + printf("%s: Feature enable failed %s -> (%s) on index %u\n", + TEST_ARC2_NAME, ARC2_FEATURE3, PKT_FREE_STATIC, n_indexes); + return TEST_FAILED; + } + } + } + + if (verify_feature_sequencing(arc) == TEST_FAILED) + return TEST_FAILED; + + /* Enable feature-1 on all interfaces and check first feature changes */ + for (n_indexes = 0; n_indexes < MAX_INDEXES; n_indexes++) { + user_data = compute_unique_user_data(arc->start_node->name, ARC2_FEATURE1, + n_indexes); + if (rte_graph_feature_enable(arcs[1], n_indexes, ARC2_FEATURE1, + (int32_t)user_data)) { + printf("%s: Feature enable failed for %s on index %u\n", + TEST_ARC2_NAME, feature_name, n_indexes); + return TEST_FAILED; + } + } + rte_graph_feature_arc_has_any_feature(arc, &feature_list); + for (n_indexes = 0; n_indexes < MAX_INDEXES; n_indexes++) { + if (!rte_graph_feature_arc_first_feature_get(arc, feature_list, n_indexes, + &feature)) { + printf("%s: None first feature enabled on index: %u\n", + TEST_ARC2_NAME, n_indexes); + return TEST_FAILED; + } + if (feature != rte_graph_feature_cast(0)) { + printf("%s: First feature mismatch on index %u [%u, exp: %u]\n", + TEST_ARC2_NAME, n_indexes, feature, rte_graph_feature_cast(0)); + return TEST_FAILED; + } + } + if (verify_feature_sequencing(arc) == TEST_FAILED) + return TEST_FAILED; + + return TEST_SUCCESS; +} + +static int +test_graph_feature_arc_first_feature_disable(void) +{ + rte_graph_feature_rt_list_t feature_list; + struct rte_graph_feature_arc *arc; + rte_graph_feature_t feature; + uint32_t n_indexes; + + arc = rte_graph_feature_arc_get(arcs[1]); + + /* Disable feature-1 on all interfaces and check first feature changes */ + for (n_indexes = 0; n_indexes < MAX_INDEXES; n_indexes++) { + if (rte_graph_feature_disable(arcs[1], n_indexes, ARC2_FEATURE1)) { + printf("%s: Feature disable failed for %s on index %u\n", + TEST_ARC2_NAME, ARC2_FEATURE1, n_indexes); + return TEST_FAILED; + } + } + rte_graph_feature_arc_has_any_feature(arc, &feature_list); + for (n_indexes = 0; n_indexes < MAX_INDEXES; n_indexes++) { + if (!rte_graph_feature_arc_first_feature_get(arc, feature_list, n_indexes, + &feature)) { + printf("%s: First feature get failed on index: %u\n", + TEST_ARC2_NAME, n_indexes); + return TEST_FAILED; + } + if (feature == rte_graph_feature_cast(0)) { + printf("%s: First feature not disabled on index %u [%u, exp: %u]\n", + TEST_ARC2_NAME, n_indexes, feature, rte_graph_feature_cast(1)); + return TEST_FAILED; + } + if (!strncmp(ARC2_FEATURE1, + rte_graph_feature_arc_feature_to_name(arcs[1], feature), + strlen(ARC2_FEATURE1))) { + printf("%s: First feature mismatch on index %u [%s, exp: %s]\n", + TEST_ARC2_NAME, n_indexes, + rte_graph_feature_arc_feature_to_name(arcs[1], feature), + ARC2_FEATURE2); + return TEST_FAILED; + } + } + if (verify_feature_sequencing(arc) == TEST_FAILED) + return TEST_FAILED; + + return TEST_SUCCESS; +} + +static int +test_graph_feature_arc_next_feature_disable(void) +{ + rte_graph_feature_rt_list_t feature_list; + struct rte_graph_feature_arc *arc; + rte_graph_feature_t feature; + uint32_t n_indexes; + + arc = rte_graph_feature_arc_get(arcs[1]); + + /* + * On interface 0, disable feature 2, keep feature3 and pkt_free enabled + * On interface 1, skip interface 1 where feature3 and pkt_free are enabled + * skip interface 2 as only pkt_free is enabled + */ + for (n_indexes = 0; n_indexes < MAX_INDEXES; n_indexes++) { + if (!(n_indexes % 3)) { + if (rte_graph_feature_disable(arcs[1], n_indexes, ARC2_FEATURE2)) { + printf("%s: Feature disable failed for %s on index %u\n", + TEST_ARC2_NAME, ARC2_FEATURE2, n_indexes); + return TEST_FAILED; + } + } + + if (verify_feature_sequencing(arc) == TEST_FAILED) + return TEST_FAILED; + } + + /** + * Disable feature 3 on all interface 0 and 1 and check first feature + * is pkt_free on all indexes + */ + for (n_indexes = 0; n_indexes < MAX_INDEXES; n_indexes++) { + if ((0 == (n_indexes % 3)) || (1 == (n_indexes % 3))) { + if (rte_graph_feature_disable(arcs[1], n_indexes, ARC2_FEATURE3)) { + printf("%s: Feature disable failed for %s on index %u\n", + TEST_ARC2_NAME, ARC2_FEATURE3, n_indexes); + return TEST_FAILED; + } + } + } + /* Make sure pkt_free is first feature for all indexes */ + rte_graph_feature_arc_has_any_feature(arc, &feature_list); + for (n_indexes = 0; n_indexes < MAX_INDEXES; n_indexes++) { + if (!rte_graph_feature_arc_first_feature_get(arc, feature_list, n_indexes, + &feature)) { + printf("%s: First feature get failed on index: %u\n", + TEST_ARC2_NAME, n_indexes); + return TEST_FAILED; + } + if (strncmp(PKT_FREE_STATIC, + rte_graph_feature_arc_feature_to_name(arcs[1], feature), + strlen(PKT_FREE_STATIC))) { + printf("%s: %s is not first feature found on index %u [%s, exp: %s]\n", + TEST_ARC2_NAME, PKT_FREE_STATIC, n_indexes, + rte_graph_feature_arc_feature_to_name(arcs[1], feature), + PKT_FREE_STATIC); + return TEST_FAILED; + } + } + + /* Disable PKT_FREE_STATIC from all indexes with no feature enabled on any interface */ + for (n_indexes = 0; n_indexes < MAX_INDEXES; n_indexes++) { + if (rte_graph_feature_disable(arcs[1], n_indexes, PKT_FREE_STATIC)) { + printf("%s: Feat disable failed for %s on index %u\n", + TEST_ARC2_NAME, PKT_FREE_STATIC, n_indexes); + return TEST_FAILED; + } + } + /* Make sure no feature is enabled now on any interface */ + rte_graph_feature_arc_has_any_feature(arc, &feature_list); + for (n_indexes = 0; n_indexes < MAX_INDEXES; n_indexes++) { + if (rte_graph_feature_arc_first_feature_get(arc, feature_list, n_indexes, + &feature)) { + printf("%s: Index: %u should not have first feature enabled\n", + TEST_ARC2_NAME, n_indexes); + return TEST_FAILED; + } + } + return TEST_SUCCESS; +} + +static int +test_graph_feature_arc_destroy(void) +{ + rte_graph_feature_arc_t arc; + + if (rte_graph_feature_arc_lookup_by_name(TEST_ARC1_NAME, &arc)) { + printf("Feature arc lookup failed for %s\n", TEST_ARC1_NAME); + return TEST_FAILED; + } + + if (arc != arcs[0]) { + printf("Feature arc lookup mismatch for %s [%p, exp: %p]\n", + TEST_ARC1_NAME, (void *)arc, (void *)arcs[0]); + return TEST_FAILED; + } + + if (rte_graph_feature_arc_destroy(arc)) { + printf("Feature arc destroy failed for %s\n", TEST_ARC1_NAME); + return TEST_FAILED; + } + + if (rte_graph_feature_arc_lookup_by_name(TEST_ARC2_NAME, &arc)) { + printf("Feature arc lookup success after destroy for %s\n", TEST_ARC2_NAME); + return TEST_FAILED; + } + + if (arc != arcs[1]) { + printf("Feature arc lookup mismatch for %s [%p, exp: %p]\n", + TEST_ARC2_NAME, (void *)arc, (void *)arcs[1]); + return TEST_FAILED; + } + if (rte_graph_feature_arc_destroy(arc)) { + printf("Feature arc destroy failed for %s\n", TEST_ARC2_NAME); + return TEST_FAILED; + } + return TEST_SUCCESS; +} + +static int +graph_feature_arc_setup(void) +{ + unsigned long i, j; + + static const struct rte_mbuf_dynfield graph_dynfield_desc = { + .name = "test_graph_dynfield", + .size = sizeof(graph_dynfield_t), + .align = alignof(graph_dynfield_t), + }; + + graph_dynfield_offset = + rte_mbuf_dynfield_register(&graph_dynfield_desc); + if (graph_dynfield_offset < 0) { + printf("Cannot register mbuf field\n"); + return TEST_FAILED; + } + RTE_SET_USED(graph_dynfield_offset); + + for (i = 0; i <= MAX_NODES; i++) { + for (j = 0; j < MBUFF_SIZE; j++) + mbuf_p[i][j] = &mbuf[i][j]; + } + + return TEST_SUCCESS; + +} + +static void +graph_feature_arc_teardown(void) +{ + if (graph_id != RTE_GRAPH_ID_INVALID) + rte_graph_destroy(graph_id); + + rte_graph_feature_arc_cleanup(); +} + +static struct unit_test_suite graph_feature_arc_testsuite = { + .suite_name = "Graph Feature arc library test suite", + .setup = graph_feature_arc_setup, + .teardown = graph_feature_arc_teardown, + .unit_test_cases = { + TEST_CASE(test_graph_feature_arc_create), + TEST_CASE(test_graph_feature_arc_features_add), + TEST_CASE(test_graph_feature_arc_first_feature_enable), + TEST_CASE(test_graph_feature_arc_next_feature_enable), + TEST_CASE(test_graph_feature_arc_first_feature_disable), + TEST_CASE(test_graph_feature_arc_next_feature_disable), + TEST_CASE(test_graph_feature_arc_destroy), + TEST_CASES_END(), /**< NULL terminate unit test array */ + }, +}; + +static int +graph_feature_arc_autotest_fn(void) +{ + return unit_test_suite_runner(&graph_feature_arc_testsuite); +} + +REGISTER_FAST_TEST(graph_feature_arc_autotest, true, true, graph_feature_arc_autotest_fn); +#endif /* !RTE_EXEC_ENV_WINDOWS */ -- 2.43.0 ^ permalink raw reply [flat|nested] 46+ messages in thread
* [PATCH v4 5/5] docs: add programming guide for feature arc 2024-10-10 13:31 ` [PATCH v4 " Nitin Saxena ` (3 preceding siblings ...) 2024-10-10 13:31 ` [PATCH v4 4/5] test/graph_feature_arc: add functional tests Nitin Saxena @ 2024-10-10 13:31 ` Nitin Saxena 2024-10-14 14:33 ` [PATCH v5 0/5] add feature arc in rte_graph Nitin Saxena 5 siblings, 0 replies; 46+ messages in thread From: Nitin Saxena @ 2024-10-10 13:31 UTC (permalink / raw) To: Jerin Jacob, Kiran Kumar K, Nithin Dabilpuram, Zhirun Yan, Robin Jarry, Christophe Fontaine Cc: dev, Nitin Saxena Updated graph library guide with feature arc Signed-off-by: Nitin Saxena <nsaxena@marvell.com> --- doc/guides/prog_guide/graph_lib.rst | 288 ++++++++++++++++++++ doc/guides/prog_guide/img/feature_arc-1.png | Bin 0 -> 61532 bytes doc/guides/prog_guide/img/feature_arc-2.png | Bin 0 -> 155806 bytes doc/guides/prog_guide/img/feature_arc-3.png | Bin 0 -> 143697 bytes 4 files changed, 288 insertions(+) create mode 100644 doc/guides/prog_guide/img/feature_arc-1.png create mode 100644 doc/guides/prog_guide/img/feature_arc-2.png create mode 100644 doc/guides/prog_guide/img/feature_arc-3.png diff --git a/doc/guides/prog_guide/graph_lib.rst b/doc/guides/prog_guide/graph_lib.rst index ad09bdfe26..0db7b6d99c 100644 --- a/doc/guides/prog_guide/graph_lib.rst +++ b/doc/guides/prog_guide/graph_lib.rst @@ -547,3 +547,291 @@ on success packet is enqueued to ``udp4_input`` node. Hash lookup is performed in ``udp4_input`` node with registered destination port and destination port in UDP packet , on success packet is handed to ``udp_user_node``. + +Feature Arc +----------- +`Feature arc` represents an ordered list of `protocols/features` at a given +networking layer. It is a high level abstraction to connect various `feature` +nodes in `rte_graph` instance and allows seamless packets steering based on the +sequence of enabled features at runtime on each interface. + +`Features` (or feature nodes) are nodes which handle partial or complete +protocol processing in a given direction. For instance, `ipv4-rewrite` and +`IPv4 IPsec encryption` are outbound features while `ipv4-lookup` and `IPv4 +IPsec decryption` are inbound features. Further, `ipv4-rewrite` and `IPv4 +IPsec encryption` can collectively represent a `feature arc` towards egress +direction with ordering constraints that `IPv4 IPsec encryption` must be +performed before `ipv4-rewrite`. Similarly, `IPv4 IPsec decryption` and +`ipv4-lookup` can represent a `feature arc` in an ingress direction. Both of +these `feature arc` can co-exist at an IPv4 layer in egress and ingress +direction respectively. + +A `feature` can be represented by a single node or collection of multiple nodes +performing feature processing collectively. + +.. figure:: img/feature_arc-1.png + :alt: feature-arc-1 + :width: 350px + :align: center + + Feature Arc overview + +Each `feature arc` is associated with a `Start` node from which all features in +a feature arc are connected. A `start` node itself is not a `feature` node but +it is where `first enabled feature` is checked in fast path. In above figure, +`Node-A` represents a `start node`. There may be a `Sink` node as well which +is child node for every feature in an arc. 'Sink` node is responsible of +consuming those packets which are not consumed by intermediate enabled features +between `start` and `sink` node. `Sink` node, if present, is the last enabled +feature in a feature arc. A `feature` node statically connected to `start` node +must also be added via feature arc API, `rte_graph_feature_add()``. Here `Node-B` +acts as a `sink` node which is statically linked to `Node A`. `Feature` nodes +are connected via `rte_graph_feature_add()` which takes care of connecting +all `feature` nodes with each other and start node. + +.. code-block:: bash + :linenos: + :emphasize-lines: 8 + :caption: Node-B statically linked to Node-A + + static struct rte_node_register node_A_node = { + .process = node_A_process_func, + ... + ... + .name = "Node-A", + .next_nodes = + { + [0] = "Node-B", + }, + .nb_edges = 1, + }; + +When multiple features are enabled on an interface, it may be required to steer +packets across `features` in a given order. For instance, if `Feature 1` and +`Feature 2` both are enabled on an interface ``X``, it may be required to send +packets to `Feature-1` before `Feature-2`. Such ordering constraints can be +easily expressed with `feature arc`. In this case, `Feature 1` is called as +``First Feature`` and `Feature 2` is called as ``Next Feature`` to `Feature 1`. + +.. figure:: img/feature_arc-2.png + :alt: feature-arc-2 + :width: 600px + :align: center + + First and Next features and their ordering + +In similar manner, even application specific ``custom features`` can be hooked +to standard nodes. It is to be noted that this `custom feature` hooking to +`feature arc` aware node does not require any code changes. + +It may be obvious by now that `features` enabled on one interface does not +affect packets on other interfaces. In above example, if no feature is +enabled on an interface ``X``, packets destined to interface ``X`` would be +directly sent to `Node-B` from `Node-A`. + +.. figure:: img/feature_arc-3.png + :alt: feature-arc-3 + :width: 550px + :align: center + + Feature-2 consumed/non-consumed packet path + +When a `Feature-X` node receives packets via feature arc, it may decide whether +to ``consume packet`` or send to `next enabled feature`. A node can consume +packet by freeing it, sending it on wire or enqueuing it to hardware queue. If a +packet is not consumed by a `Feature-X` node, it may send to `next enabled +feature` on an interface. In above figure, `Feature-2` nodes are represented to +consume packets. Classic example for a node performing consume and non-consume +operation on packets would be IPsec policy node where all packets with +``protect`` actions are consumed while remaining packets with ``bypass`` +actions are sent to next enabled feature. + +In fast path feature node may require to lookup local data structures for each +interface. For example, retrieving policy database per interface for IPsec +processing. ``rte_graph_feature_enable`` API allows to set application +specific cookie per feature per interface. `Feature data` object maintains this +cookie in fast path for each interface. + +`Feature arc design` allows to enable subsequent features in a control plane +without stopping workers which are accessing feature arc's fast path APIs in +``rte_graph_walk()`` context. However for disabling features require RCU like +scheme for synchronization. + +Programming model +~~~~~~~~~~~~~~~~~ +Feature Arc Objects +^^^^^^^^^^^^^^^^^^^ +Control plane and fast path APIs deals with following objects: + +Feature arc +*********** +``rte_graph_feature_arc_t`` is a handle to feature arc which is created via +``rte_graph_feature_arc_create()``. It is a `uint64_t` size object which can be +saved in feature node's context. This object can be translated to fast path +feature arc object ``struct rte_graph_feature_arc`` which is an input +argument to all fast path APIs. Control plane APIs majorly takes +`rte_graph_feature_arc_t` object as an input. + +Feature List +************ +Each feature arc holds two feature lists: `active` and `passive`. While worker +cores uses `active` list, control plane APIs uses `passive` list for +enabling/disabling a feature on any interface with in a arc. After successful +feature enable/disable, ``rte_graph_feature_enable()``/ +``rte_graph_feature_disable()`` atomically switches passive list to active list +and vice-versa. Most of the fast path APIs takes active list as an argument +(``rte_graph_feature_rt_list_t``), which feature node can obtain in start of +it's `process_func()` via ``rte_graph_feature_arc_has_any_feature()`` (in `start` +node) or ``rte_graph_feature_arc_has_feature()`` (in next feature nodes). + +Each feature list holds RTE_GRAPH_MAX_FEATURES number of features and +associated feature data for every interface index + +Feature +******** +Feature is a data structure which holds `feature data` object for every +interface. It is represented via ``rte_graph_feature_t`` which is a `uint8_t` +size object. Fast path internal structure ``struct rte_graph_feature`` can be +obtained from ``rte_graph_feature_t`` via ``rte_graph_feature_get()`` API. + +In `start` node `rte_graph_feature_arc_first_feature_get()` can be used to get +first enabled `rte_graph_feature_t` object for an interface. `rte_edge` from +`start` node to first enabled feature is provided by +``rte_graph_feature_arc_feature_set()`` API. + +In `feature nodes`, next enabled feature is obtained by providing current feature +as an input to ``rte_graph_feature_arc_next_feature_get()`` API. + +Feature data +************ +Feature data object is maintained per feature per interface which holds +following information in fast path + +- ``rte_edge_t`` to send packet to next enabled feature +- ``Next enabled feature`` on current interface +- ``User_data`` per feature per interface set by application via `rte_graph_feature_enable()` + +Enabling Feature Arc processing +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +By default, feature arc processing is disabled in `rte_graph_create()`. To +enable feature arc processing in fast path, `rte_graph_create()` API should be +invoked with `feature_arc_enable` flag set as `true` + +.. code-block:: bash + :linenos: + :emphasize-lines: 3 + :caption: Enabling feature are processing in rte_graph_create() + + struct rte_graph_param graph_conf; + + graph_conf.feature_arc_enable = true; + struct rte_graph *graph = rte_graph_create("graph_name", &graph_conf); + +Further as an optimization technique, `rte_graph_walk()` would call newly added +``feat_arc_proc()`` node callback function (if non-NULL) instead of +``process`` + +.. code-block:: bash + :linenos: + :emphasize-lines: 3 + :caption: Feature arc specific node callback function + + static struct rte_node_register ip4_rewrite_node = { + .process = ip4_rewrite_node_process, + .feat_arc_proc = ip4_rewrite_feature_node_process, + .name = "ip4_rewrite", + ... + ... + }; + +If `feat_arc_proc` is not provided in node registration, `process_func` would +be called by `rte_graph_walk()` + +Sample Usage +^^^^^^^^^^^^ +.. code-block:: bash + :linenos: + :caption: Feature arc sample usage + + #define MAX_FEATURES 10 + #define MAX_INDEXES 5 + + static uint16_t + feature2_feature_node_process (struct rte_graph *graph, struct + rte_node *node, void **objs, uint16_t nb_objs) + { + /* features may be enabled */ + } + static uint16_t + feature2_node_process (struct rte_graph *graph, struct + rte_node *node, void **objs, uint16_t nb_objs) + { + /* Feature arc is disabled in rte_graph_create() */ + } + + static uint16_t + feature2_node_process (struct rte_graph *graph, struct + rte_node *node, void **objs, uint16_t nb_objs) + { + /* Feature arc may be enabled or disabled as this process_func() would + * be called for the case when feature arc is enabled in rte_graph_create() + * and also the case when it is disabled + */ + } + + static struct rte_node_register feature2_node = { + .process = feature2_node_process, + .feat_arc_proc = feature2_feature_node_process, + .name = "feature2", + .init = feature2_init_func, + ... + ... + }; + + static struct rte_node_register feature1_node = { + .process = feature1_node_process, + .feat_arc_proc = NULL, + .name = "feature1", + ... + ... + }; + + int worker_cb(void *_em) + { + rte_graph_feature_arc_t arc; + uint32_t user_data; + + rte_graph_feature_arc_lookup_by_name("sample_arc", &arc); + + /* From control thread context (like CLII): + * Enable feature 2 on interface index 4 + */ + if (rte_lcore_id() == rte_get_main_lcore) { + user_data = 0x1234; + rte_graph_feature_enable(arc, 4 /* interface index */, "feature2", user_data); + } else { + while(1) + rte_graph_walk); + } + } + + int main(void) + { + struct rte_graph_param graph_conf; + rte_graph_feature_arc_t arc; + + if (rte_graph_feature_arc_create("sample_arc", MAX_FEATURES, MAX_INDEXES, &arc)) + return -1; + + rte_graph_feature_add(arc, "feature1", NULL, NULL); + rte_graph_feature_add(arc, "feature2", "feature1" /* add feature2 after feature 1*/, NULL); + + /* create graph*/ + ... + ... + graph_conf.feature_arc_enable = true; + + struct rte_graph *graph = rte_graph_create("sample_graph", &graph_conf); + + rte_eal_mp_remote_launch(worker_cb, arg, CALL_MAIN); + } diff --git a/doc/guides/prog_guide/img/feature_arc-1.png b/doc/guides/prog_guide/img/feature_arc-1.png new file mode 100644 index 0000000000000000000000000000000000000000..d518000f42753ea7a1a71668c2735c48fc75c3ed GIT binary patch literal 61532 zcmbq*WmH^2w`Fh-1W0gqx5nMwlK{a&@L<6m(r9pZ3mSo-!QI^xn#R3xcbyCQ-di(o z*8G|uG~K=Kt*Tpf>eSxn?9*WyYVug<#OTkSJ;PE|kkNYf3_<nTGx*P_$iO!e@CnDj zKR9PCd8ucmBcxlv2SiIrRmo@1Dq=8hO^|@kXrC1HoS!{=Mfdmzr>I4H`0Uxik)n*` zYY(H{ER<C3zf&P)%`4T0gUwULr}U~nU&C!F;9*c2GQp#N|El|}VvIF0;&Xr!3KKjt znT#Zp8(ak#s~w(^dEMB*MN}^>i|58HKCNHH;<$OVikwdHF4OEhqxxdz0Y?gzD(La0 zMI-$`?`Yu@>HqU>*t5d0|6D;WVNLyXVNfjU|Hq|78{cyL;`=#NlJy-L-`snjy>VK9 z^T4ZFxa~SoYixXFJIi;~`f$^_G(n3yDt1w_#-ZD0(Aau^J=j#^eqiM6JNw&?MrXZM zX!m+y@`C*8v}$ysxn;VCXH<-4vPeB4Up@xec$j>u`7GIGXF>J;{^nqbB?u>8I2RPh zd4GGNe&sky4sG#mY`WQRJl?1@=k^{UO%t%rizF1(A}0kYc%ALjxw|xK3%Tvn+Rauc zWH{98rPtb0MP=~CU1O0b><PIRyo=h_`k`dbq;vnSzQ~1%>0MJQKI7}L+lpTQBZsEw ziwe@@UN2pW+4l2tLtBcQ_WN?<U5Z}tY8tP1ji4AQLo`8e)G9-e88!~RkCC08Q@1il zYvNwi*&K4$#tiy;XDNY^&CG5Orm=BSA@}+~`uc(&%udj4SNCxK5?=4)Z0RopL&{c{ z-9K>?GN}D$8tL)RZn@^GZBlIK>NGbvQaMa}qmodNMHvkbHktXW?b-PMlrg+yev?Su z9bR;0nn{8H1D~{eF5iC27BJ4_AMsypBpE(?PZJ$G1eSC3!t#n*XL-xHiVvrgymfwF z8)}|HjpQeB?DuVp&oyoLR<r-!`}oh{x3#`Fns#?oDq43b>j8w@+mq4bqh5+Z5{DKh z4z)Du7%XoUuZ6$b?|$1-y=2irzgzxLfMt-g!Iqw}b2eRWvT?mEwBohWfGag;3$3Ip zk@UL|bq{S=p+ev_-N0lrtWnwYHH(IRa$6nXUcP?CYQVUA{ZU7RRov#hL<1RZ{CZ=` zx>8Wo>zp%<yvaXd_0FThb>}V9>w-_4(+j%i^!^3ZL2F)&s`Xze{BJd<e(5tL7<)(} zW0F$-dbdbhIGFhS&SW6GF7Lf$eaUOR`T{4c`Z_n$`tp9e<Fbr{*b|}ilq&D%aaH?d zY?fl&dLxAA;hFbqtb%r327+f>!A{%G%Ik@agKKMO#cKuqJ8K0@Bx_wM{QYP=VzH~1 zzO22Yv+TWWw_5iV9w}EG_fe1|vE<HUUF;oG;c4=kh&@yBX^QiRyH$Y^EYi_d`<6-4 z#ctR1)YWds)k{NI(s<ihw`<Q?k8AH)uP-GnRIkd-E)_&3<|A;a#%wh`JLq$~_076c zb$TRgejhaN>RRuGwLSPHj%F>C!Vi`G<p@mJJ*44=n$LC`r^YZcS5r>{!l^$MA}Ypu zN-nc@bI_V{gEHq}#G<!NobY0j-B!TwX8N#&EtK6QOKZxVC)%WYAgN_#X@EP|JA+NN zlr`?++VAwJccaeUc43Gg;maz-yKw%3nAe)L=2jJa(3E2A3H5B6uCZt>Y5~3Bvzx)+ z4hh}KpZ$aseULipN)r?-6FQOjc`4>Hz1qfXqCgQWzJX96Tbyiy6&~4DSXh?i5BW$- z@OzUH=GJ07vMv5@#ADZ-h92kTmqEv}eNL@}+5cg;4~x~r={w5}YU9ZJDEk=u*!y_< z1p6dZ{Q)}ZV|Nf1+&+OHa}q(j=7;2K^ja4@C9Bs4(8|vt4dEeL#ph>KXoUQJ2D+=Q z^Lu+z2f4GUY?!gH%uGMo;=r|<c8WFUA;VRe55Fv}kS}G$J5-t!K4?m?5W$`L8yRi1 zNS5PIp1gk4)1+g}dm}+#ym40TvyOf=)`?x%|NIsEJK9sRg8mUVS#;8z3$Yhc3ibgL ziJd+-d$pAw{U3;~r%mbeHCNK(N5lo<R*pZ=t%<*}84Qkch&!1*ORn<9PT-+PvkF@7 zO5q!DjA(HhkgY^1#VExt#VdtCo5^_~*pMS}h@nGi@s5`~`keTj{G9rn&YZE-F*Qy^ zB_tWc`+jn;W4eGrg?MucHvGZb0`<T&$E}lGk5Qkm$;lK0iMBr(IVssHoMT##YOGoQ z;!8)+XItOfeg>0XV86lX7lA&Nj=vs6Fxr}6P5fY)ABzS!%!8qu1xJl@uLV1=vK;o= z7U`Svn@(z+pxCBog-j%p7vWeW{C$@Xck26?AVLjZwTEdLyp)u>9+x!XR#lEG%f%N? zGhYOqRt66QgFnadf_EZzB6p&8qIY6$mKwzUz&DXMQ8&>yqv-y$W#wl5xRyn5c|88@ z0U*7X-Lt<i^-x`mr2|POoEPsdg3-R{_-MFlFP>O9P@CsYmFg2r{lW&@Cd^}vv0&Ap zdM)bL_|%h%y0H#lZSqw-m+4Ga7Cu=|G1p3FHQa7$A#BCpx`w~eZHB;^M#m~Pu21O? zxh^z&yHB50S1G!I(GIRm8%tMfA|#f41e2q1;t9Tjx?kKL$=BPzwwETrxuc0UGI*Pp zXkhT|N9JNpO6FgO*I&oQ)YW{<tEx0d`_kI(+I-vZ+I>6jI((hy)peFU+nm8Lgi$oA z`j;tdR+M<lKhq&=Jw>^gNXe4Poe^wuHCA8s)7ZooY)i9(kE1O+eB|Bo7iV3ur=esz z$rx$Oq&y3gj^b_>0~uHFHMY}9Yo{JfTBd<JHaQ7oUcSw+XBwUd+wbW)lBsbPsGmEu zX1yz#V`p9VRX?)G*F_A#iP!lGGN<xB-;MJu8{xqd%3G_xAOC`%Lcm5(@YjI}HYcc{ z=KrA~lhZe%DsH5Y415!M^W`S&Cj4fn;b5WdBp{3#Hj*(Yg-5Fs&?6d-KK=3pWRxW? zUb1Y<KVY~5zgr>SDUXTGW*ULb{o3e97%01++!=BCFg%DKZ(Y=$;Jhx+sw25*XXg)J z@5j~+`GTF|)kIs{tCLwVMA(*PcCu!^yyAoRO$J(c^Qz_EkjGW{OR2IO*GBK<Zi0@k z)3IFXf5(lq^#Eegj_gv*E}pvB3s-tH)0nYgmPG_p)m(U;&WyNP_zS_sHZG@oJNLAk z126U_Fl_6Hfjp(!24XR5mKbFAa<kNef1iqxnSTKuccIihJj=SWus``nD21nh3Nq)& zz=+e=o6Nf_MRnSyG{)B57_56_kH%YB^p}Er6QQgLwcZ9^?+qJg$xF+8OK@2A*P5IK zJRuhtug7n84ifjgcr;2qbKBZbkVCrulu&f@(gwxO0Xsyl#%`8Afk8d_d6rPo&CZHB zBry&nqlOm=S&iiCC#kr5MwRBULTQ`x=TcwG3u0yhK5Nr#Jjh8t7=}4I+ohPWRy8Vy zAr=<2hPg=&sk2Uqt*dL8f{W~R1U5suLDa_s?jlSN4d&eg!yDHnGX1reVG2@6yY?=n zrJn3f6ZpSqFU`}MAQ1KMpM3Z3W{9W`ywCXzx=AT>FkZ2P);ssYz0NC^XRh}~d)O7D zx4lDS3jDFqsA%~mti$0?XUR{;q@4__f98r4`Z;PgZ^*@~5#5ATwGX|ogCE7nCJ_-Y zg$+Cx3B`U+OuGXqi`jx$OI5;yw(Yo%b~-i~R4r8Ed2`ZjeDRsaLWH@wX0TY}KT!>u z@n1Gi;3<B`*H2eDr%yG9n-;4y-o*U^k8ZJ0_}RtNoHd=@*NYW!!KE?HqB;;^9L01_ zf;ZEiy0CCT*e-kc`F*n?7GRhJGZ$^(Ez8*Q7DJg21Amydj4-57``I+oeI$~q<Wa=a z?SmVYnct+G%v|uU>PBbO&O<3JI6t6?$a`cT8W?KT7oF5kww+w{<;V01lPu&)#MyS1 zB8P^w>fn!kt!?!8>?Mcpc(cGvKIk^$*Drd|2kjGZn_F7CG}Fjy^9Y<5)cEPq9;DLm zDTS^c+b^<{mFm$nMW2kXVCrJaaub6-GOj-Gi@gr!Xs%Fk<L|I4D`Vqwdx07$S~>dH zZ?w_h!Bs^6`z~huqN8_}?gBRqK&=_MAib|P9kIF6G!}{M97bB~Rtu8HScEhTs?a6d zQ*J^%A_nB_Dj$Sir0m9MFl@ASPB446T{@)C`=Gfu1U-y}QQ<2*uBr#irfg%2P7U?1 zP;<K<M{ccEEa#rRQqbvO+S?8mtOeF&<M*uqd_EcGW-{_r<Y-!r*tLyu4|wNLq_{q+ z-v*ZpEmk06Bsp+An5m9flnsg%k)BYVO#Y=m#1Z?~W(w7J+<UchVtuV?_8@Ljj_niQ zN218xNZ=i&NQ^JSsQI>pr^Aw`pY611rRSgp-#Z0^wv(jnO9{;1thEHK+%v?nUk_Rz z#Ohqo`{t(8D6v5IaZwc{y9@iKZu#O`1VSz`Cu%b`p~VFP3I{$e%~mWM&@`^rwlmk^ z1T)KoU2{j(PkwH3SO?tat#8tsh-k&3C+y$Ak%k4%bime=&{CSbzq>J?SW|S8zVotf znd4<|Ec%_fSX!IO=agNwJn)`Y>T6ry)!wxXD?J$Ivr-UtJnPVkBn}s3hGq5H=7L99 zIB?%#bD?B@{8l2QXot*joq4puFAr&q7wa!wg*fP#iYB(0h{rOhpnvvmWOi?VRb9Jr zs(#Gg)eT8v=qkuQDDJ1;%Jf*XhB-<v<cBgW@kkwf5(Y}{4_-X$UaN^K<%p(O|ErwD zME0(Czvx@S?6#wnhU2i#FQdK0e2{4~>1rCjS;^`BrrVh6DEqV|Dph@4L447020zOE zv#ST<FQw{?D1I}Cf+NVxfpL9~Gl%tHSgre#pqqMS1nhp{W}jzXW74MN#Ur(geSO>n zGNC*?C7LXh9egzsLQ78}`cOmebdAT8g{6s1!{4)|K7=j;5nVt2(495vd-7^{cp5z! zf&P&KD&~l=sHTo?j8g>`cJb0>MfCu{%`9AywDwThGC!fc4+9JnUPM@3TZA++827+d z<Jw~e0NO`<yY`Pva(Jqxzb(_F0r-_OA5K}*HFLrnp|iB^5oG$nxD<rZyDK}dfuwA> z6=J)Y8eUW4Y1f#?8)-8|XjF^e{)(TSsd3~(e$Xx~x;@GMwsxsUAxx5hDaVZ@hVrm0 zY;f;v$OeP0Px00E4=gnaKCxC>Yy~`G_u4tP;;N(2t3=&D;Pyjo{Fu70vhoSRXMTS6 zEoZOvmeY(wpE@Gyub%kr)9qAGH}?I6?-U1C-I#$l%1y|HD8`W*F~p=^JI6Yh%#knh zIGeQA{jL*1J^DKt4r-I-(qG5jSN=qe$WaBhD~KOn36}X9e-oMi(@@=1zpFZc_sF*6 zqYY?ODg2MaTsHr3sY*Ww%aNOhwf8k}9{<VB(ayF%7+X+ztLXX2w-qX54<~{=le2xc z`$1UzU7lp{m8TQlBXSgh?R`E=C$2{FwIZVTU8|X}C#J3_DWyCafP_)-?rhtd*aqgh z%fZm1qW6KblI74-xNNf7dhN%@>W|$1_dXU`PH>Ix{wzF}!%4&XHOGFB55pB7JMr6Y zmTzmWP+4~s(@`^U%4wj^d_;~cu>Fhw(uupKbR-jI$~Uzv;S97w#gz*8MKK!X3oJrf z2UdOd)`xrfL$XH;lTq$aoCL^72eIjwL8X)gAM8kXz7;}DxpVmzlm~{Cq<X$#OV`UU z%R?V%QEOP68{TV93{I>O&@0~uAW4mG#nH$I92A)EHMnYh)sWN{JU(2$bdxl!bol`# zh>kEt0!}4IMMCSDI>-D!KlJ%a;6fyHnpTbGmu>5~2qQBweAo>Q&p$$b&>S?KJSXuN z?4s}|&0`g;^KZLzas}UR5dG3R6S@LOP~btqIuw@88*p|=gDsy}T=IT;wR6ZZiPbgg z_6%a&u7gGuL`#fDrHaR(ifQ9Q#r_jwphi^n2dZnzNf?IrEz;AF{pTX}VLevLH?&dp zuL9;YMtaxQ2MbHWh@kq4AGiFJmt?}Op!nnM+bgHj&GDtiWtW46dDfGOL5?f-gg3t% zo3jj(9zI(8I`4d;mIv&~vR~6$$m8(q>GnKJNv^BxGIhMelCI@yWczzs`!(<PnFg8# zR@1PnQX}_%z^w)5c;I5&>ZOaB@|pLytBc>!2BQ;jkFJGak*K%}^d%Ud^}eev;|~Zn zUuC-wj=<;YJp;)5O7>sCzTzF7RMMx)j5&Be{>8L;Z)i}PmI=CIvkZLf%Wvt#`v_|o zAqV!SMEfkA*KEGQbx6pZE3t6%C|XmC>3VHaeNrSP=U|Qr2_aw|V))!NAE1M_Q@tlq zrGA7oXPwyMmtw0`7Nh9;C>`fpmO1?Z^OIgpOJ*}BPyXBC_*L0ttI}L5hpwdd!}>s- zWh-Df1$6QS)^nFfx#IA|FgNlg+aO>)=LleKM6nhnlhcl?jB0wH*_0EEQl<3511xiV zr(9|$xs-&W`;z7*O^_okk6(c$YLpr;p`+Du&B$l#jR!5tCy}$JKXyMS&ijte=U%uS zERek;h%c07F^D6ZM+O!+DB;(H%jOu>)<Tv1bjrhew^AQb;5PvhBTQtPiyk8BqJi~p z<q+S6gWUyHzlXbvC4TrYB>m)UvJ>&EjSR!YF~+S|9{amoO8PanTtwtLlBjI(%P)Tx z4cmh{5TO-?Nbzrq4D?QXqyu(ccd4<@h1}@G5u>H6-nsFL+F}zi%~=kMY@OTo11o~- zU#XgYzBkJN1S#;ZX~1>gC0PU=2aqiTBii4u-M7I=a-16*jZTu;%to_C+Z~YO$zuzV zB3^l$F<sJ!h1;+s@&n(?DOSlX1mL_&ZTB;jMXy{Th6U|^V-{lO*;()!tlc3Svs>{^ z`qk`x5fbe>cj;(d`F^QqV|d7sXI2K43aVVAFj+d^SYVPbw}B1r5p);Xv^4{kp@{(C z2#h6-Mt8_qYsF=)=zh{T1U0Opf<CX8yfl-!0~QJC_TXV`sJRozM+`YZYYN5@w9LWb z_<Vzel0t4O4HpVO+F-+COf|11W6KSPC31^%jISJ9RS1D2=@Qr7dZxxsKRp1uB)a!K zt?}1}Y&JDUoTIS6oODbY$(6|prirgzV#(my+b5`Tjkb<glIZVh7c<RERsQVlIq>VT zHzgZAh9+sf!-_$6(1teyIwd&gvi=*L37J^T$boSet3&eiC|yj|nqQ0$7iWKmt>AyI z#HVmEc)>hJCP>UqBqXQ6Bbx48iKNUUOiyF3m_nc*4;)kprB=|1Q<$-TI^_4Q2S^f# zgvRdD*-xClUBZ?+il@_RT|>YsoTSLvuvGx2X)SCrCzVQPL!AuKxJ1TL56{YszF0sq zIr*1v8ng1^E_#b}C48i&Q<Ncmx~!DD0BT(EPb1L$GAJV$MigIQnn`KwPvNGnTYST9 zcofjh_&Qy84U8j&8&ju%=VxBkNN8YGkop8%;JV*)#&f8V2pY3<q+jQw6IZAD)29)K z10E>75}!cI@UZ2M?@~$NJW~}oYkB<}#|-zUD@-?hljvJ36eS|$H@TTr-QI|hG%f`u zOQJBVQuy9-J%)U7BUw|59NhNeoz}~+cthA(4AlUq*9HCbfs?SG<jLu=BuspgS@K>T zEIamdMD3fHx)A@$YK{=66v4tQyP5Y5uYa46;j7_!Io43;T6ea#VlR(LD<MfRMC_XO z*E8!l)FuallsYcmsX30~!kr2ma;hLRaXofbH$6wx$$mT?VG<Qg<Uq&cE?$$BKY4Ek zL5AOt(V3NFFp1>!2Izki8y2v}z4DjP5kig7Dc9hX@<)}?5%OLr=nWBl6;B~-idb5v zJ!^}-1H?qRen*cG6^=F;GD^h|nC9-ruWsH$itI=dhC9w%?#}fs@&KdB=-0B|_Frty z6-WFsDOavc4jg!--=chYO9W(Ey>DPljsdK8vo)f$%BhxNX4nf-*nTbt+38nD$&@JP zsdPGZ1w-toOHot&wS4ev%=o!bdWaW35J>MAtW-(wi6$X9U-z5xRTm~v03K^Os%qb# zzJ&BDwZhcdw{wg|ImfpqDr(+Vj-kA|m$AOQar(;DS30HfX1|r=PcU}JWWBN_&ns-h zV*`oI{arW9)L4@%0B)w<UA+vKNNJZ-B@SIfs|4NquliP*1Gr&DJy~ILr>vFyd~n*6 z>_(78?y*+_nCmtLy;=kT$4GU2h40Pt0bBr&#E16%2JKB((3JeXl#Q}?<NHDg_`T-3 z??-l2j#5m=qcuoDG?#`6B<1GTC&|AO=^jB(Osuu__IQ=0LMl6xv8-C^6}XD4>pdso zRyP`tc%m}%TMXZCE(hZ@I*|@}tdGdTGebpj^5>i4j)wJh63!kd4q!@=Ry2!k6(+${ z$sESn<+vXPCrAd92LUGV!siKyd4{PdYFBLxOJil6%+9UbKH~xqM2Vx{>_V=+m#RY( z*K(!mzv0yPm4ljZj|Ztt8i0VVpvjDd<!WgAd(ID0ctv(`Ea(JizP&1GLcCO!s?5sR z*nW|ffTIhdeL)moBpv!(@iEeXm0sm7x?y|C3G^Yiy1URR1uX*HX$k_$bHr9~B}Lza zHjSKi@*{kvrIVgG?MhG&3PKC4d8oL|0AZ0M1AxrdK<kIxX5$7BY={wnsEKIkHC)`I zFeyI*Ib6Id&@#lR@v<{5M#YKGjc{CkRNW7YrMSswF~=#>v|eF(zUL^~+)1eBE?bCe zwSxk?+b3F(Xw=7-bNAZs(^5HUYgaQX&Cbe@JVWry;LG(C;{bQc7K!AZ$P5X+N3i&X z%ECHb)Kcv`ob%CH6g(D*MH)AW(K1{!d|5a3%fzC~o~gUgK>2K?YAkQ3zk+L1b#-c! zZ5OHo*t|RzBau7P^ht${*QbR~>qRRwH1VfiIVBc!2Y~F%C{j7w<@h3Be~JW_w|)l( z3y<x|Cb^&YRV;Pity*orF{(IFx5%iZx`(=ZSlMd#s%5QcDPmWGoTm()%uFh?i&hoL z<k;v!n()50tlF+|e!xfpfpr_UG}BiI%8;Yql(ESuK2X5RT8H~*3b+Ouq>1})dRrbW zG`9;cS=`N%<c-MvV4dfGk7ND>c3Xf30rZN=YrtOWonHm+{33c=fF?7m8Z&|4dbw5h zX9a=Z0m{&LuQKc+a&gvf;7ndG$X*JeK5R}n4jlfyHR)4m1r1M{_+jG?<b|@ASnS>Q zW>lZ%QsEEKIGK<ursAaDotzK}f8=y0i-;RRxmDxiaPiJvyPG8}tOsiSgN$Zh2ryV= ztWa2<QM}yFbN3ECA7S^x$z5>2NQgFU=r15B66g+pGPu}CoNCY=kSSR<JTdZvK<iAp z$c>hXZm;gk{pBYg$DO15Fu0hz)36L_jiQ8_W<JA^>JnG;xoR$F_wp7=D-gdIppAL% zJBOMOl4Up3=s@vrDv0PmT6;M|GpMW^E<-j(La=B|mtT^D+7`uejDE2-+j~_gO|G-F z@|*wG6q?O|cG!&eOz-VBd{$t^=$p4M-XX3zQ<DJwL|*9Ru28~@#)iPnYJMsaXxZI- z6>8&hsIXlv2@#ox)dc>4bp+r*@dzL`F9-OV?|XJk(r8g%G^_&$<ZkNG@#I1?m7bSt zJN3UM=a%_10dkw09xH1Cs0hsV4=494c5A7?y9>gGt!`@77@rn#+gZQ&IltI64<oML z<{}c{kSUCuGZy}M^FGI$P4k#$W_8eN+L_11xP}mVP(dkk-sPEf9a^we&ovrcpxDa= z?I-|yCNn<nG1PumO=azz#)IdI+AUzytSDl+o(?)y58t1>Zpf@(D2d0F65Qk8ewGvO z*`VAlNx)?)4&03=Fv}=s6P8BYwYyQo3+iWaIX|keA>wen-q83swY%Qdd}yRCjL{u{ za})!x7z|aH*+z8=o>DZ^L@%UXu6lTAk*S-p(j)1K#ROKD*M35PR`r|MNqUuLXP@q+ zB3{SH$TM-tFLLQkgAx*)eglo7Uy|6^aq#v&ScbZL$I=}*>GqWJeXA=#GrVnr^6J#e z9Pl~%=#+;0sTEswMCzm4Q`GgaL07XVU55C&`PF>gtgQ^RJLRy}+rWX`K3!IetO;^n zNvFUFaHJ+^K3f0OEVfWcSMxfuv&;{Pt2i78ofo(WN9^jF^^o_d1$J>x2`g3*t(LpE zLr<>)*fPz5)v?|2$`0EQYtJ04oIdq%?S43)xMxVTeAzVHHO<tz`%Z2})kcgyGS><1 zMQI${+w)Wgxv5@7juyQ5qHSKAzEh&AiI?<<RjU8J3{W7SQLq(6L?J-J8yP7}Yb_-+ zsmdX0Erqb?C!T(l(`0zH%c@l}dqSS0lTIn=*2tH>T2&intNqr(%dc|7BK*(Uh>=?H zPJObenV4GYQLcd=rEK~~$gdrI+SbeM;<7;ZCnrGbmX};4C5sN2MBP=6@Ka}A6F~}P z8Ae_cW&}18$xJgPk&AUeI5hTUxP^Dkdyhi2Zl;cC4yCK|7!Km`aQa<SMfILt!Hku0 z)z~=V-r+@}*dlnXI$cfc+1x7a=-UA3Q$pM<BvNs*gCq0Ntf+~tmHzdR!YQv)W3}E< zrgAy^R;R(L*3!N8L@9yIH5QxgHrD99UiaU14jOQUl9Csc#vvpUiE4#_S@rTc^ShGN z-9`Vlq0z^a2nW}JdrH)Sz7b|_E<>aGMPdGQBB97?(AT@OG#W*5e9yux@11^R(~fO* z0ek-R>~EOnac5?X{Ff$Nd=~nh9(FHBv_@~EG$-@*zPQr^u18Z)c-tn0gN8G%gx3KK zwW*;0RhEZRLUVIu{L6{8my?lgfJvh{P@yV41tlsYz85l;tX)<`Jnb9mSJuZnMJZ%y z^xCrQmtG=;Of1aH=C9Lt>(f5jRj7bW-0{pLzg%|x7-dCc5mb8;2Pn9`s0KMY&0fl~ zP6T~&oor+wvsMb?QpMpEw>}=UGPm?#fq#pE`tdhpYq<Fbtmm<R$Xd;#$xuNh|9Og7 zP!^;j=V|M7F{`3F@HeN3Qm-dH*H@}+@G|;6TU8}sWPO~>KZ>?h4zmb%wT*Wlp`VM% z#A$6JeMC30Ma4tzW6q}82@f~oH(`(SfEq@jsXSS^KDgG}jy%}S4|3=GNJtbBsgO{c zkv%Vp=|QrqC#sHjPBD01-o*CO$Xe;ZSLZcaY5x2sx4zTdD;Wj#lG(~a&g9Ci$jy}% zuU}FVzfaE!|EVO*NPxCS#UDuH>AS)>T6b)xIX}ciD&SFTjl=6CcaEs#YWjC8J=i{{ z9ZcrdNfB(^A+K>S96i^F+t2tsJzZDOr;phoOpwH1v#-AAlnP~cG?I)gw8;(;wZ!ZD z>6uU12*1dG5ZuE<b-oM5YZ`c(tRsex*6@#q6Ysl`ZT^X;V}vM)J_vZ8m3aCCKT4rM z@x>eqe;ic()X&QAo1iRaK23R_F(=q#IN?%2p0ZffL6I>!`>`g++3ujU9||TIx+R7u zAeD{521-`cI9JEF51P5GlY3+{&LaP;BPq4OdZQ!_IA7}aqegnLXwLg0L7t6UOn$4@ zO++uB2|B(3Yg4OEZ_kjMVa^8lOi$0ACy+wUKa*3`?9o;IJ^!7N6CYRVNnGOt_bR9_ zy{^tEqU}O09Hg2d7G-$yxCP>W{Rbd;5H$Zd5FinVoTlb^GNcIF7r;re$n?&Ll5yOH zE5gDXhvfCuWFfVA$S2Wrp|!s5a9@85rBs}Sos^{cTU{LL6UUW5SSE%i=lk;{O%4An zOj>0EQOJD@_hZvz*zgI_#OYZ}c{COmLNs~>X!-*98xb`-d{jo|`q=BGYAr2O0R4t? zH_L>GYU$_CUtc%yHwKv+k;l^E7xnd3ANQ#H7uqil$tH!dyVgB-lSCsGZrn6yf5boE zZHxf?GtK)Hw}h$<O@O>dGGjr8KEC-9`5PIaDAGr``13#bD;zYODwyz}N!aURRYiGD zin^2MzCnYRg+=xREHke**T#Zsz8L#m(Os%Od5m~p;L4>ih8$Gh59~iQc*p8YYQoyz zoB0}O)m!`np(&=lc_ce>Pm`NurjY)eOo$eccA)ZFjO?GKR<(BmfSo7`NH=3dnK#r( zc_yqs1$g_>xM@|F0DSpeaq=Y+#sJzRpD>9SKp<Y&WOCX?7--fhYzkWp{P{sT_&AbS zQku>Q#B^Q<@{fNq7dP1d3wfW+o<BEFOJDGyVcB>Jl*;!ff_}ZLW-eirX@N7%#G(Wq z?F-*A7AeWwTa&Bf^&#&6z6?w*>K#JNpORQc%`kM^_Kz)`t^}n~4A8wS4sOwIxY%rG zeKJj_OcmwHXfojfkAB=-xsfLZ6Y}2-CfDAxTM0j9w8jo2<1+2h)6g;ibO#JE_7^S5 zSa{+_GXKquaOt~Nx+9=$PwR#znXG^ZNCbSoR|E>|w0z6Lq5%ec*rRtLjz_OD8bu^+ z@)V-&h&7);yk2y7NEOK9`;c7)e&j*KPt@^H8laBOq)+3-4QEZFANzTxn%gsKUO3qQ z#Br5?t{*wBlU~|!?m^_MU+=V1pO)*BSv|<N$|fbPdGXaZ?H*P~zEpsh9QQDp8e!uV z0V)0jj@E1DOVvl*ffFwPTnz>iF@0~Yv>Rvt#RuXI&wx9WfIvZuff1;Bn;yNtM7KVE z^<Vq3U9#zI`VP%6--eT#zEbn|Nw0c}CNKag;1GkfR*B6<xWaBoiQa!bBrd--ync;+ z((y}{f^coh5g(8EDk>oUaO{_P)wfojhrKy)vrwe^NO=Kb1#(QHF9+htKL99_DzHu> zFa`Yz5I#@-V^L1_k`fOfoVb>tE|$yrwBpNQjUcdLqq}0KTvSKbR;Dny3ttH^_=O1P zeNudSl`|4hY*~xNILc$&YtJizp||+n6s)WM0<O-xW?S!KBFT(m1wuSG2ssB4#0$VZ zj4Umd0Ho(fcsdGK66_`rAI*Q>`y3VT+h9aeEDy4}BVQfR%YGD3h)U96L<;6j(;~Dv z;}#H&wL2g__7yuPS)-J|ZGU@N9)iCzH*z8TFDBSsZ-^XXo`M4ityV7|`Ebyhl9Nn& z+x6MbB>tDWI(r^L>tp>9IYJ-_aN7pESRqMA5gT1bq5xz_^8c)+l&-e`ja0-#!|P&; z?4toyDWgHq-!sBU1H$jo?y_-tCONQd_p`*in+p{2qbCPepFo;KZw}<9Ot9FxWY5wE znM{*~NGt)a?zoc3RW>MlrjICAyF7nHFCq?x{u>n<u2gzkPZUX^+I)ja6g!YVxOo)Q zeBzq|9()8zECuG;z&|`)IODqA2k2Y=v)I{GCIyN_Tuw5&2$+s~TTbx@;G>Zc62N8M z_gySKtW|PDimpnYQ*dSeV>Kf39g29<HFg;;`xA7kfxCIgzaFJgnNb3O&v<Bq9pr`Z zqlm>ULkoet!5|Q{eRYe7_cUv4xLWCnNEojas<;1k5?i9WK!uOiFEXQqfVDgWk7g9J z82$bD*X;iGYKZ;GRMZp3CJ>`ZMXA-r&dhYBRacvy`>uDTFsft9HNoeU0je!!8s#s& zIUWYjDFjJx3vi#hF~l`WPmB@2k`Z#*PAysv5h(MO$S$&X;kyQ=VHZ3)=}9(M=>ib9 z<MCb!p2jDyRzL+&NT{^E;<onX>3JQ*zlH;w_rqQX5;Zb}dLI`dOv;baItO;|gnyGz zKm$=ssC>*C0a}s?(C%Z_NM9|zvK`83#z|<6kVA00xfEXr2nwOMx|07$W@Wrhp`u>B zQ{kM`>@RC#uP+$s?y-|0qmF#IM3_CLZ7|bPgR#7P{bc)Q*|#PCb=O3~4sciX$E3Nb z8rAd=iWTuU9|yz_Je8tz&MK;w``*)PFF7BMwsfwGL;gDX8QI%8XIyawJPi{kUMf3| z-W=F}6E%jymZmtZMLGWZ*n*Ggw;tO6E&X;?=H@3h^V^Q4_-$FyQ$!%hqtAJw;C<e( zd?;ozE+o-~59h(KIBtzZ;BB=2WnmS#|NUBU+esAcb`iqw=J)*Y%ERn1A5f{~AdCOY z!gVQUC($FFh^Xdp83MAvWm}Mu(eKoLv8?+pm8Z;Ml;bsC75u2HdVQ0wBg}cRN!B@y z&zBhXG+U@)0U{i#d>Q->$v{}lxRgD15gOanbjj=Fmtn+8-rko4&U+54-6HddRu;^0 z5V^QmaL=)w`5k6>2y9RssSlJt3KXHO{;ewMB8v9kjYpw%G6rs{)`G2u4uW=TB9;hA z?FvBxc5B68*l+bEPqtN`=ocO%3~K3&tw5CU5KrP?GgM54{T72$Y}~s?CR)uFSeAi! zkDJ8edB#)f+u;95eXm!Kz+Qr3R~05P{Tpl<X>R~gBH^C!?~A?pTu1GljJ3a4C+nNz z`R&z}1fo6lCmY>+gaBw^c@)1sYE%W?vg6v0MEN)BLA|y6ziJB<D)KgZYk{B@lJT(U zP?~Tr=D2{5fV;bF?;R13TjXQ7bN9Zf+OHX(MRU$4<SAWI4DFrsbRIstdrWwhb;V58 z&e@86YxcSb-!^Dm7=MF~&&*iHW|V1uA-+}Ek363of=R{<c~iW7`$66SU=C>yXn{NG zYlsbzwx}v184hjJZO)K!7b;iL6jYJgz);M%iv{nPJQ-9))UhQuU*me}><QekyzYp! zJO7hme#fi*xvOpht=tc?RWaiCmo%3jSKddLX$>5aiFj~ceni(UQi%%)#!$>@yy?sF zzbEqHbssw}dRr9Ne0m1K(|Vo19?^F9<8@)>?ZtMniaJw<<7%(sa-Qr^%mdWd-@c)~ zy1peMg*B`(aeuZ}T`7s(E_>WE+n4^QGn*k_A<76x>n*Mi-3cHCnJ#w>6cM`AJo&nk zchgOmWYg!lcQdf1u9C94Vdu{0MHHzEKl&n@K}09z_3`Lu>O&u~<4v05kq~!ArJ&d# zc)f6`V2q4|pN5TYg01;ti}l*}4*reSK5u?_8P@RM4spF=B88|7#1|?Li^XCo$Q*rs z{dGBN^~5L;h1{p@_T9ruB7yUp8sxOJ6*?f0e9#6)XxDLOC~G|md2y3DKwtm4E0Hzn zm}bAM^`6*=*RRC?W^e3nXkbXQL?b<KX|HXV7*OH7;L#u^_-n&%dEuq<q`{H=e`s*N zF}{$(edQuQXk7mJkBx@${q;`SQn58yK$7|JE_vRtZHx{}>ktqvcK?bPe-u+)_?jV$ zwn$=QDLMPN?#xpHQtNjM=zZq)15*;9*!8X>hHxvh#BU+u=9RwK&%HQJ3P>OX^YD(o zRnkhl`5^~iN`^?g(f>>8M6aG4oh2OHvUUd_c*0>jK|e-F&ipMZm7#ZZe#4fNC!Xby z^y_B?+O3WvJDOLH5=(+Mixq(?>7f20aR9Z}Kcc`?%=ozA&Ny?)#v{+dtzZJ<SRmM) z5hA?MTQ=*y=v?bVe90~XXrn*<_+&Af#^&zUIJrA(1Owz7swdLgqm5qa>rI9T6<DCx z759lhwEu~gwJNpe8{Czv?$pKZK)b1+h+y;G&jkex>V3QKA9T-woM8eO8xsT{ekSa; z%}By$dzeIM7QMSV>H3(vtcfNndkwO?P!tt2vl-*;vDvH%UFT)_0s)Tly{4iqu%n!+ zz3ukg^GdWn0WVn;LsUnsfkYOYh94%)&%vz`3(oMRSAubc<E3#HK4Ym|S|``<a$!G@ zUEi$rf6GpEXuX-bs6R%4A8(d-r^#**k4*4(hH?w8ILC0lvTkdG(>kAV$~|cp0&?4G zn?6Gxg)7$Iu!zpPR^_tC?64siun2qa@koabLRz1xropC%`<spHnO+2{j;aISx5`P1 zTlALl#ToB{?G7S1T0!wJ(N_MH=B*66<I+Iy01DnurG^b|To8hrFu4hGzcrH+=!x69 zbc(2maqIngM!k{yS%We<@&QSYQf`EO!Hqhg#=HDnre8ba)4rrU@Avr@IFD=wuWIM% zu8^bS5*SLH_<j<3vV6)p5#^jptm?gU7bO7Xgr^=$5srH^)m;8yJShcgjg}8cC%z#e zDaHsC-wh<hUZ;<hH&=L8Y2;6l=)P)}*gcRh$<N!Ujdq`lk6yo8>cp0w)iUWgHcG2p z?<Vn5X%Io)FZO_PS?<q$fgpU<Cp{0`#g=Jr#M;GZ#%h}7n&0w?#x`-UIuUMxI&Tmv zg0x=RzQ?BEnyY6GVo2UaA?~g*u==_jb4Q&qMn&mSBO+Z18eBsEQk|VZUgb_CtekI} z)ig*+iEjLD@>9)`Fa;KA#sx}X#cGe-?Ks)IpraUl<BG2R)Gl<x*P&Ka<bgSIp+a5h zE(B}Ha)3OvfO>sC2H8w17;k><b-`Yn^S2Ak*-6KMQi-$e*8At9BGNOQb8Tmyy_RYR z;`id|j^KBoj{Sj9)84asQA!7oY(v;w<r`(Ff1B?fASJ|rR$0ajdAnwx?m_rZWiyT5 zJIzOI*CqmZ*{rAHNy522{C`V0ozxe-hf;<CCrs#*2T&pRO4pq!jn2dT81ZCNF(|5j zbnLHj<LV>R0=K;?mK~Eu)r@(oWcl;1{d3D8`Z0|F4T(Q~m&>7v6#NKSTTbiRKci+0 z*TytDxmHpv?GB+GW*9hQrXAj!+-G+eiy3>S!d@y?Z8Nywi`e0Ip$dGk)k0-3lzghw z(+`ju7g5DH*8{ZEnSDBijX;R6-}}CAg0dJct;2f(6M;Bp0Rm=w<3W)|Xx3b=O2gfL zv%^Ndj8aNb6B@!2jUA;o=Wm90>S{(<Zrm*Ir8bR?s9F|ikxj{}dr(}~f{sUK##H{R zdS@zRUiu|xi7COC&z~iZE1pMB&VF~#HGEdV*7u?`YG-<PsBi8w=g!qqsOGTR2eLV5 z(CHp~aGiK8zO7{|LucOnIp_p&%$H(xIJphh#qtMGB324BvoO+wSKGbnIB;x5r+96q zg3R?@#TOvev*c4?Ti?rZc?<7!*@>GbXV}QtU5EE2<_GUSxn&eg!(Ns;xjJf>Go&Ib z8BP)l_jQto)+6xfhk@qa6OpUn{#<W9hlQpwNBQl0dFybR&2Lf0YUHRQjN=x0I4Mbt zbOaD<W?1bWo#h#cdBb_u<$#4HO;#Ka_y&9va1(eFbQ65D(U4QxcJdhpKZ=qK!0dkI zuP@NrB~1JN_O)Lu4C(O{%Kb_&$_<x`j4PHvkn0tImO-s7(4)lXYg$4Mbjo(0B~f{k zk<u7Rn+t#@qFj)=I~uXPZ*~^dGL|K2wEgSd%zrg;Cy~#5J_)C4tFSVidX?3{Ul1uS zML%fY$GkZZ>}uN&mf5WSjfDAi2bZ{{j@;pwx^Pi{wW#=~AunHp)qGn??X-5@zds#E z^{CDBqdp4HBEpUD!1e|TZ`!ZC=-vhooMmI6ik8+|_%$sxEE9ruOmnb%ZahbO#q14H z^74Dvl4eE>g)(4&M~Lf<v_XSG<g8wIas6Fq<vfmj)8uBe3*=_VE8x}N5fTz_U;EuM z&sldjE5ey*az*_)dp`SGvh$wLZXt66dh~%?iB7o)O754a85g|kSr+qlRv&=YCw}ls z+I#^hsBf-%9uEASEHCUgIs-}Y?F@`oh#w0@CWm)&eB}{|_nd*Mk40y`Z6ZCqx|X_; zx`n#^y8Alp(wkL+y3xADx`VohireK!39v$ez0(3`{IQycPNRYq7!5@GhS9}Vi-JWz ziM-)?CHcj?zp=vct|MJIJIRk!0OFAiaXU0!Sy=g+u>pI`KVOtRiP`|rOK#58^>Ey5 z@lu1?-qozh2#ML{*DXXO<~qS$byiER&bgA={+L+p^ku@g8k1+<_=;;rk#F(YfZFPy zcf`P)7pF6?o&6)TgaE}Hf?0ds@JM~7Vz?4f58sv`AsYIex{sVKbjmlQ)Gah`&|?PI zOgX_Kp=mYM$ZLx(p+D?3X@@>F*=QVkY7Wki*CzE=%x6^jLB1Z1$8U-?=QA<rZ!Yd} zmQ%8hfvO-A&P&Im_-^jgir#`ZO9-Xd>a32Q6}ZPaJEbWYB#YFr+8sM|Odx<D^Hfr^ zqD-=0Cu=MiObJDRAVE+dXpkKs5j%9&>Do0-W1s^$i^i|>uZyY6sVl2%1>zpI2FBlN zu4L!WM8hOZOSDr)iop5veYUZ79c6z3?O>d~eRH?W-|fF0HP#rBd>V07;WaM|U?B|_ z-c|<rk}+p?FRI4(<nd}i^)k$&zflpn-<O)g0SPL41R?_b_A#5OubQ1>Wv8eP)~-ou zg$_ZZ=0PR$;~$t{yL;EjzrC}SRhpLSPCf2^9{w1b4k+j?>Lq8gwRQ?ij0*o!nxUof zLGRCnJWy$6<XKkhJ9K_UX%l#1phqvRvcXtBvQoI5MzdEFIvU5uSn8Q!dj)MWS57~X z;lmIoo}1dJ8S{Lf<MkZ1Q8;UHPJ^E1Wh{xeXzQ4(tNvy(jG?FE6?iN%o=u*@=MWsH z@_XFxiuV`(^2rbCJ}%XI%+my;Dz~T~$!-sy;U@ClC<AqBr-rQtj@DZ?>p<1a01}(f zKz-IhO4W5tG7q^o6cqveW#;8Ez2N>|GPU|XJMc-{)l$<ZKLPbjju8^r!@;|#p|ekh z->eWW5H64|P%h9eFfO71DI?jQQRu;dF0EVz3&ay4$|Z>b6kYuuyw5S?C~bxKu?G$= zO@g1&7P4=IvimsGls{~{xgGZrunX|Pob$V+Se~FM*G6OiyJ{#q@%THBP7(qBy>z4( z6(kMafrh(H9|}yvZVOPQR#I}0^Q3~1cO-K{D%ed4lE+LV=yz8&pvOCWD3rl{GSh$O zKQMg+?-*8S6>^3_J~J+RtrAk2r9;PuVqbZELDu0z+q|T$^4&?3cf<kRJ1)MKx}`<o zUf01#fR;b1HjaaCEC`Y{1k<^kEv7x|er{g{lSiOy7NFU<5*-}fjF&sooRpNkYi9nV zdRCZX%$-AIHe=w#_hAjyIjRZD#F1EJfQXLx_1)qcfe~k*P~12pS*J9ys)1(tSA(}d zOVWN{tO%*Db<o%L1I1q2BYV@vBm06fBMt7q0sA)-G@WK~x=yHC`~AW>DmC+ZPD{{y zj+=&=LDh%>P<y}cS_e{TeMePd$*VBCl+{;$Y1F*nhm}PSvIA2=)|j($v6{d=lg4SW z^T0ck)@kwR)uy(i+no*Jp`+YE(x-|;_beSb1PB3y2tooOgX9Dgqf&L{=v7$~ZAk`l z%*cKJfI&dqdP2Y&Yd2dPiY7n)b@zMb_dl2BVFuG5icHg8A`@ycvhBsE&_3}rWWNF* z?s$co%GdImVgHsaT}>-5`@x}_1n@u(Tf>)V`s|V4@!7UTT23o@y&~PXki=hqp*Ann zFoVD8^mFz1lS(0<F@+6sw5qs^qB0J|<ZGZJqQXd2U!anWB1%d@YTXyT`FDk^-uBya zT&nzhcJ-#_B#*9l&o(K*-UA115^Ge*XjsC8%muFNYFV(orFo@rHSJS#c@|J<7@`<E z@M=cl{Qgb!?k?V;w<s>NOc|S_x-Le=WC0xQ@EPmO`=*y8FJWfx>yx-^Kyidb@gCc| z+jla#g`jmfzxyl8tIO4xVTxFSZz^%UAy_<jWf`?r>_F4p*!p>0>sJ_kTZI|@-NDqO zs)>f+ok{A$^_a(+#@;7Sb=Kud2PE`JE~{T*;eh^3+N^mvM(I?xmz^>TUq_S=ge}rG zFe}6ciU%IpjHBqs#`;REl1HgDI+o2|v}BXJ@i*$02D+J_B+#1?eDWRN>~?eXv6{=P z*c`A*+jnfg^4qnW>4hcfC$X}L@6)}?)wJ$7bG{phS)GJOs|nf?t3j5boRJeKfFnXW zXgMV;7u6x)0Q89Nk$lsy&cPw|JGYKv%=Yxf_)UJysz#o0KoNqkaW54W!iMkuSQO?( z@0-K+WS&I+UOof8ben*|`Wm?3R)Njzr5yVh+?qyL+SX34aHrCR{bkJA;UqPUt0$wA zzR!2<-OhcVo9B?qlIH<y$f&CLjC=v0$^AX<`~$a0C&QtrNwW<L<GhEVKdP^!1L7gq z!SR2`b5F7+DwO&03e)GP9==ci?do5*kMn=|YsG+p=YKe%R>xI2XVJVn4FJ=Gk&}%E zA;%QAlc6Qi>$D?*<f=skTNbP1%v1O;ln|!IS0!m)$H@2ccs8zBx1)Ho)7eTth|L%t z;5QjJ+LJjOoZm28^kvIjpUuc2q24&Tj#lxQdF?htvzQ_d&8dPzn5M3nr?W===3RZ_ z3KWpK9Q=)JsXmz(?bb){!lTW&4spx|m%jbJYtdSEj8JhJUbY~e5+q4~BxVMa5RxT+ zoo+xx`924mo1%dOl_>j#POapZ7gH5T{TvyHwp_;nLpY@*1JTlQ6~++X*VazvA-``Z z7IFk_-fnsv360G2BKOnj@x?l4#@w~ESTqdZy=W0dO&|ECJYf(?k)wqOe>1kTnc}N; zD>H~x7#0LZx#|`5HoH0BI|hpM(usZ@!O1H*clE`AIRYg&mRs`mC4z+9<7@V2`iFtg zkJcGb&CGS@VFUSL`ZIB<Gd!^t9go_$8sFr&hYnI5&kTX^|6f(ApF}Q^FndE+yN*`s z3@Kg%VO1ysq7=!U1FJF%;a0BJXSrz63Rb_0-bG}PP=%cXy%HTNmZ!HGjrTpRp%ESG z%^}~l>qFn~=~<mLDFl3f_fH1X&l{+xnp%>fwfy-7vXr)Z%GksAOQdJS5}D;3dtzTM zY{$nj(^~9DDgNfmd%Tp^R{~`O`OZXnl!Wdr8yKz%mt&KLvPiFo?qgiYmr+EMym?i< z`B_Km)BG6Lizvfg?J_pRZ$NS9(0TcD89kCaFWb^1#cBR*q>{j$pRh<+fnLOh1;CVT zD(P^f@}2KecgO@NUeX86k5S-TwJwQfVz0fp>8;V2F*JTSE`HrVL5)*)aPDm0u!nT+ z(6A&}FkC_~G_{h+NfD<k<eEt`^OkWh#v8u9tx4~iNNzffarpK<*+EtA-;+<|b?jbb zi>PyDv$Ko#BQJVwF*211&jTG*8MA{g4u$+~r$)UCq+ak{#*yAsG#;Di*BMQR6n|X) z@`7nKZETjYnF5Ycm3H4{dq$L2RdsfO>1yYjMMl%O%^wwLrLWGX$2?FyTH}p@7Zwgd zEW$9ob^h>kyGyS^G$?)6>EG&+{rN^|qF17FWrR#Zg3VdMQma#CWAGg;DiVc?DPeNi z0Qjl-cGBY^-M9`-Ezx{03OV)~K73%eo>+gK?XpkbbbyPR)!NUZANN^fsX>a})t`8# z&K)hnI2S%hC-t*Z0=uaLUS%QP^vvvd+j+~m?I^Zz#@b9Yc@>+gM~$Y$fU6h|R%BX@ zznO;hg!$`iYS&o=w-i1ztJ_KjH@<$7bHTa-#gvnQ1dEJQU*V>X0xJU1gJS`=tb8V| zTvQS^7W)(q3b79!;rMz`h77A-9yleuFyR^yl<VU)cYWoR#5a*Q2Vzq69A3hQ^6Yhw zxdJrohVIR>Id-ZrWDxrS#V3CS;#fyX1V2FRSGidYQOTd?^+Q|v^UJ$dBOfab7nBM* z$@?ly5dEU?n_(2~-rLX>#Pb^g_9mTXiztmwlHTACFWpRaz>HQ!7_h?{(+NWkw-;ZA z!6C*M<nz+7KwmcfmN|D49AuSOB>_R+pMRP#Zk4uf%+8;D^5N%Ge({==g1O9Owoc5d z>)JI!8|{RJVn5U(`P4@UaTMi(_@=5#k<WunPtFiK%E6`9oh`z<AdQ3-W4!!;Dq8X& z*NDLu`{H``K&z5;JYZESdAwzTu>(Am;O6kV5e7#}5u{vvE}2XzUV4@H$sdGZq5P)6 z-n%WCs`W?-J)37<e!BYdd^WaxX8wfp9wn~;0!iu)(B-YKu%6~~{B>J^GTU`i{n6N= zl+Fxol-zG~%y!x)Vm_GK_O@a92Y!9ci$M>1;3ps)d)3oVBfRg^e`)3SDhQ6ysOf-6 zD8(rh#L1K&vtUTSXLUe^amVOHNt{xZB#&#f1!P5Bd)ckUUBXFqm}JwDRdr)6h=BE> z<p`+Y-IPNN>r;UA$jCOreITv8NbzGE`&{y#JB+$NOCw!jF6?c(t=y;qRV%52@UtW! zf7>51P1nW)gpFQo{Vh(3qwiY^rSJtx%|kw*3ib4ru~1TlAr^*pWko7z{~j`K<Soxy z5(h>WYY_el+;$m#+T*ZB54aKg(9$nOAIPX4f8wGm%R_Op4CNu#d1ub9;W&4DA!Tt7 zt3~?pf!KGcaXjs8W0F_p9I@H*!0>R4nXxH|acg#u`>{(oojkivA-WjfsHI8q!Lib5 zlF#J$NtXmvnI_WXy06fwa<Kc&)|y@M+J*M5$?jAYU{F40BTyCXpIUHM!E384I+r%a zd^3N7+_?W}xk0f*k8{niFj3&4oa}9Sa_$hI{FKSU!4-XMwNg3VR-<xmzaezrt9SZM z3{HH+bc=83P$sVqpMzwQhMzxBa;_%z*aky^q9ml5SX6G{D~zCWToP5$<Nk6rHm<Ne zMwIGe;o&Q*@2aYxM{I&0E^v$V(=Cq@a3_S=LfMFv0UGI${)A5Xen6S~D1M~{e+9+W zCFmERt>&gL2&(}bE<;Klwg1)m{wzZktce+@1u`?+0s=5<*9STOi>I#)h^qU(exw_u zyE_F&Lb^MoYv@kt5)dirZlpmG9b`~Cl<pJ(Nok}T1mS;1fA9OjPcrwOdvc$(*ItXv z{J9JkDX;D3NucwUt``7bSHzsYc2|L#fUJC=!Vvc7-0*1n>Z9$BP8}ch3_4vXdtVX_ zb~{lRA_oE_D<C(##=r7j*aAi{+s)VYmPV-vT1w`y`#=6i(+dwazr;Z%U^JqlI|m@Y zVfQ;>r|ICgqP4|J3k>9j*AIdZlCH05ghLC6c}?UI$_GkpvXzMDQ<V>>XP64xm738Y zKlb|V1?sYxd5f`^8t*kAaEQkp<J{?#)>r?2P{KPnje3$F?UMO!M!}U?;%1>Pt;6y` z;P%g$)uk`bR|nXJ+r4B>^z=T-+@H^gvdsW+bZDW7>`iOVE^B2}<opc3j`WiE>McEK zBS=y34hRz6TYIgM@|fnG=ACugUhf{xhOTV?_*@MXM6}IKTSb&=FcC9yfnJ0B#;4Vx z)C@O^8)$`~Zoh1}+sCzUC2U!__O>~-_tL+suCRHNRGIqNe@R?4=*;nG@fpzDnBo?+ z`<3yEqUwEdNX&)3#a!w%d=6w^O7<`=5^bb=yASia^QnH#2wrae!I$j+?rLgKEQ|C& zvzr@FAdUsb;dF40C@QMiG*5xPJYrHS7ibPT|J4{~um&Ox(5^{|!|KD!fi5Dl0Z+-3 zZ{_zQxeY;TD~%CcfN@3~(8pDaT`1)UaYo+VZ&(&u{7DZ;&I><$cl*O?+6TF*4$+=Z zto96hN?d<SpZl?5z`y71Pe&o@Tt1Ld%#cUa(I~ePN6KXnck8$>Y>A{BGXV7!!xCn{ zfA5O2zD^xKhyYoMlwDZO2$@AF$5>*ZChUXu(sN1u90CNj_*vBg`rlR>VRV|p7w~)* zO`DwZKMu%Y#71V}%<u**Kd+02XW%XIt8yxUVh2x3j^EF>G&#)5UpalDd*Z`><;=Nl zKK)k3CY?ma1{eA#I+>hzIqbgeFeFF9p&sJ?gZUF)<o=qLWa?v=ndn}@w&TrwD_r+i z-7mtC%YEhqN}?IQo3>jkR8nm=(sHJfD?N6(;AYYwc<WdP^{f1~@-^bCq3*{%)h0M! z0PbSxnM6NY68a_j%=6I#QG_PNX3$Sbc|z3!HE^aR{%0N5|8_<ESqQYV8cOI%7k2d% zeF~!{FodVBW^hKIpQ7KW`{B*Z?#FxSJ!9(k%ViGu-V$e5{09SvR}Y#iaH&PK2hB}+ zneho2Z57)9n1X*eAHMtk1f}F<<9yAWWqzY@8&Y3+5jr(pl0WEYxYHEt&UkIaj&<Cw z|H_vKbqV$nXOfCfdL5f~HouqLEL8jR1zu-nBg3J3CX3%VM+9?d$(N%}6)R^XJzmX4 zM9`{xyB)W7a}lW{wh>{~^q20z`!Ve~tT&Ks3O3nS$XPgJ)S&N^rH&h~8>;D1ump>r zet20Sjq)kJNJw&D`Vzj_;{WEFDza8@HrqcCV$UA{UB21O_mJI{g)=6m4!AaaeIoqr z@m9%XDPhGVAy1ywv5*lzuS)VVmqud};)ZtEc5kI>C{98_9KIc-G^5=$n?y!!^Lo5d zf9?oveeJ`Sz(7>p7KhS@3qX8fG^8huf6``5nUt+<&7#2_nzxoC=I^c?0DVw05q$Oi z_j!qWCCzM2($3VeQ5RAX=8T9GNjZ=&!dvVEYCt(#=#wa-22JBHu~M2<^*L`s4d}%w zC_2!cUP_07#P?>iBSQ>2(iYK>H};Vn`uEQOjm$Y>QZ8RhQmRavlwZ|!&tkRPO@dBt z?aV0_iah0I=*CuycEG)2p-Z&MO#EQlkcX38O&^IxN}2A*1dYOk+o)kPSDRhCXp~`5 z;F%K8<IHCH(?Dk3I66HY%f?`pG5aOq7`5ZW>F#4$?~SxeY8xJ;PW1Y6C(35B9vZP@ z$iEqVJ^c7mb*iArd-(e2!r71NeoNDSgB6pV&xW-}STyzVr!UNk8U8H#FXwv8M6~^l zk$Ew{+4Kg@9s-JpO%lyaaUdufwn>VlZQ)^@D2BgW`*Me<qwy|k>$|_9tGYxU`_C37 z?WOP8+?U$5_IK(Zpe;gsp>Ht)EYNpIUNyo@^y?0?zBnk>5G7HBJ7DNUC46uvTP^8~ zTvI|LnLnpxiX8gfVYEH@IX+Oxez<_*{Ev>wvR9p`M+-)GSF$*F6w)Qi*x~mtAzwrp zY@)XwQt(jwi^nM<;)Mb1N!z-hQ$N2Erbu!l0dbcJnDqrYOD4SsD9RhQ?7&OqB*-9f z?J}pO*DWh8W3=wr+z&$UO`sqe6nN`eVpY}mOSl~aH<-GC$7+Jm=_c<_Y{gy^Rs@em zWsAu~X=QlA>17-?Ww}V`h`<8~yw<~Zw^hKgp3Lzh2z+NgCUNCQo^l(MHU`oqS}fv6 z%FoEzEOUwGJ(l$stZ}`55cuVyG!|ek`7Z8s9cs4EZaMugj`1lW{o;b5FTaB#A8#r8 zr63OmlOUc}1^SP45}}6S7-oF$UHn^2J3>PogIR5S*u`xkZC=a<x3qDjD2S6$j0nwT zaO(b`?gQ1}Q)XRf<L)&bw<l^xnctj)`Xy<83*O#Qm0(df1o90!Fqt5Nj`hb*acHmf zi{3a4@S$I+2{HseY_Ywn#?}@nAQ2M8?qx5jMgCb!CH4aq4>#<_&^a>>U+Rwio6+<P zV{DwgvtG)cEH=#It6P;$_yi8|`qvt(O57VGI0M#qnX>UwR}KPH>O(NU%Ch*gAtgQ{ zl;w_(%6=ZE(TEM%#wS#pQp1{-*xdRreoYVUk)5pg<DSj#xmla`Gq2o2af58%TQ}9$ z-<Ff5q$7WIPaud^K0$usuSrtucz}-b)+>|KYkJx+MkSpz{E;!&n5dFi;lRPk8|dmY zNeh(7VN%yj?t;V7FI%IbTE_Pm^Y*z0k~ayYd)R$1uFe}~<D^%}k6dL}+>Aes;d(_L z)Wf{{oe^EaTn4cM(Exf++D7C$E|@s&#SdbmA5lhw?dr$M^j>r|M&w|kVRLIhh06W@ zp!x&TJRh17ub-dK7!91@8{Mx`w{rB}TF=4!X?XBTh`t3?sBBro70?#XvCv@=MeNR( z;x~;Sp@-*3*ufSlB(^ez*stE~Qh%;C`DBx)XK4fA42J>V_pl>XqF%_N|9yy;Y5x2= zP)Xze8Dj66OCjuD5IFkmPwUI9)MNGEd1_aBPxfq%<A+t#Ef``P19mpDhrNH%ltsb< z`ZIvAS3(L~!670ro<2=^`uF?t!AM*;`RcF@PQU#g5~*(fNm6Tw5sW<8lWE6|zVWLr zS?u|CnnFU43+;<szfQse`_1Iv722sy0)qb}35Zxe<)^tb<!Q%$3HzMt5Mw9{NneMK zQi*7F?8T6Id{?{w0KKIb4x%RD%phrC!P-9F6>4?#mnX?Jf{S68z8D|DSqtCe^@!Uc zG-OohZNL3B^i}{TkKfDp{FLeYnxRwY@n^?Ofz)b$iUPx3OFL1>*=H`AM~fRsH7+yK z`Pwou?BLedf)VLYv!AymA!+y);#5EMIl-bHD@PVDd@LE-&tNh>jW@Of#NgJ<$a2|j z<Mzj<yH$vcC6d?8)A*+%-vt9OGGk4AHL|gE?mr5M)dMPMB(sR$z%!q(HUmdjtCVHs zZyNzoVj1#k{MjW|mMW3C_hasG`?~SQm;defwaxKREoSow{|HE^=#MDEnM;dV)0I)< zWAw#6D^+083wR`indlF-=;JGCUP8u~w4^Lq;!dijdX4mS{J`9#M5_Y1@4Cf7T!Y!i zHQ8cD9I}+ka;yqv*6SSqFnKt4RN6=9;-@O;p2FC_GpNti1&;y*LtF{(3%|$J8$eei z%%zw2$FX{Ux8;54?pw%6!DFspyCBul8EST;{Ru-}5la=~_-$M~dq?9{^+w-$9ZfPL z!3)GWBLL3gS`9x#36GDvv<$HdKhk~<&7$(<k6WDk?|ThZNjOX)YG`o-TAoFy>J|kb z_}R<8h|5i~&~frgq(Mq~K*LsHHy*C4%iTj>Dx;RLcE$L|1oo29&4zX>7LBiYtxaH` z#C!B2hn=Lfrv3L|0iUX3a7~QRLT$ojft$?a`PpNs>*FpTWE|>hi_{pSK0%5q_Cl{V zvs^Bzy)~(;;4^RRs$1z7_+pg5e|#qByWg_lm?I*g+Z!5{3_t4?bP^W7HLS@7sI#e3 z#lXQR86WuEa@P#(SIdtp)N*}4V?@SLZ3ds1vlT1Qw=Q18u@G0!0d9>!aIbqrwAs8~ z1+Hh@R+`FqU1>i>)ygMVvC1)UC2oT(KxOt+4qQ;;haLX>vym>_v8r--R4?a6{EQh= zxdP)+JJd|JrSw{3^WCn({73X3c6f;gX97mP9?AnaO`MZW+D@`elpVK*)lVh9O%s4g z$s%z(b62s%q97Es_e2qEc8;xMFGIETPrJP{+*v%GROOZa(zEBBacbsTrt1$5*Me5A z_K(#|5+<^pTJU~&3(qYcJvvZQm@usxeI>h6XgMly=zzStlZ;#cUzJ&7ui%3Z30rLX zx)yoP-^ca>Sb12(xs4EA!GmOlomQB=eBq<Xb}K@-%iKJHxJAZH663A!3~nOJO@6YT z63TkS#vG%}K_QvU(&bIAo5(w^-OCIQO)Hr`A0L-1o8vNa?9Qq&`U;_+$oX@XuBBc^ zvTG%d8i{>4N5S+02=^EnDQzKjK6&Cm{9WdKSa8VORM_<CxU`}_m)mXW@j^Y+w2roZ zD@~YeJFSx9gQL6}_TyG^f|rgh3?&cVB|bj{%#I_;-o5~;1KrAUz23U&ow?abJGx|p zF*znO3L-P9g*V`URQd2@Cg0{bNpR9ey+%IpQ{rkuf`g6^R3g-;u8Uv#%bz4VsPegQ z2%2YD5!I=g^7unmB9c}E6O_(TQjP%JzW*LdlakIy?Aa91na}Lcu}t{Vbf~A<*MFq# zR;?b}@$;;i*dNummmuAf#anXVl+a5Vhw9Bly?U3i8bn`K3C9ZWcEFgCG+)a@?4H_r z3ziF0a$|h9$cZV`^cA*OrzOX#QmB-&%v<BK_%_J6EQfr*h3fl@OAg$~OBmwNiiDWk zesXdpamOv@e3nDS#eM8yV^F67JGXwwdh`VupS&spqgg=I98yQ5#;R7w`l_ZK@7`0o z0{t+s2i@@k{pQcjvmbwUZZ!_WQl7ja(x!;a_|?9DgryXulL1ZuPOE-B#o!Ob)E$~S zyApnpmsjC_d_FwM$4`S^Lnq6J=1$6u*+aCDbs}7;VA=j=sifhrm?iSuPTUO}UK?8> zU4<i!Re_U3d8IDS!5s+WSQU9^a?E%#txiA2N5oMj5WB)@(|UB6;Sn7uY<tK_A$fMJ zP1d>`mb^csMM&p^WEz~1hTRhXx_XdS+OPv?3DV^e6LlhU7`0nR9o91d!m&R#kpQ<8 z5Ob`Pf=q(!qZ}hbEijD@GCuJ(Ug!q-(=PS*K9Mp<%6E?3WnZb{#T{$WX974fA1UW^ zF|B+^a6qnQ2ilrVqp)61c?=yhfWwXZ{vv2>KQ#||JmTAV!KCu^JxKewa$32}*r_8u zyG>ENxtjOiTM-XM^_uxKmsqleIYZlb2X3O#oV#<2ryucc@gI9fs#k`DZd<?2<*{u` zNmclcIfgencJMvh{2>MvHCr#bGnhGwWJAyvT>+C^RGYPDFk>i+Z1rYlTfLdGqbVAU z3#KbBppFG@nl!4qn=c;GSX|>ZRqhj54S2~~v)Q#y68e2*0_kb1e{)Ab30>)2LT~YA zL;CsTSmZj1kw5{WJPQa3fYq5H`deHgpJfO$me6qE*}oqe|N9{v&0|_Z?42*wS6DD} z6+iUI+?3Ejpa7mBHl8*Bit1X?+K6O3fwXBOkVG@l_N`G&PW3XY_;li<Q1<}tA$9*E zZT$gDm&1tW&da`I)g~g)+Lx2^$`}9J7wGB_W?A+n)?R~~hYIO9s>fbH77iO|xWvCH zP;oM)B{cx#r`Gc(D`YzeOVwSLLqqItl4!nGSffKPN2|R32j!c5Sksgy(takxZAAcd z<r)nR9J~sSD4<QGRwYo;)vO<2v;H=9_{+o92k=ivkN>^G``;^K_pWYFA6dPmcCyD5 zn7&`SE5ZD+%A@%>I4Q%t%%S!dtxCYZ-YWgqW@bcOB&!2)`wiJ@(kg)Pe;TgepO2`q z$8jB+Uesb6)BuQ%fdO2NPKCaerOP5L{V)4>T^s?Mr9tz)zlU-GQsa+)ZNSW0@1qOD zX;05`e*Dhi$^6-m)gFdxlO|{VSwAzP4Mx>^n$ENhW~B+<0B#CR0DV0~^mO{(<hS!A z7(?uY^v@WLd?D0qWmE;mk9#1o!u=P!qNK{3mJN?B>q|nj(6GDvaXF>8SQkOGnYM?* z()AgewvP)yd@6c~5oT_IIAvin`V4(&h{Pl|H*Iu$x^1#O%bJZS2$BPmVdN&4&CdE7 zip~hF4;GzX&7Hf+A%nI<cH@K0Hx_u$?(hlez_1NBVuBW?Mf2PADSz#ZS}%#AO9NUw zVpq<#fD`HVeP_0+?Dl%A=&RwH98eA!UQU+uzl^<UKOqEqAZl@>e5}Hs+f_pEnNGt5 zfsz{6l!JQmZ;AmNkWflTN0)Fc<o`s)X<?{P7;u8Q6h`;A>2;7f=&4>3y-*5M%bo~| zW9KPRx%0X6=JM+nA3P{s21mzvz3G%~HDr%B%ugm(dGWutV%zJ?5%kK3Z^r!ZiOpW7 z441KV&7meUGf5o&;xHuZ=hLm!1j0W_C>Du0lpj&CNFeu#4opFy{#ys=Xq+}6dtF}s zyb_*0#cDK1sES-}1C}gSdmg{Z(ziizCIGLccE#YMTO`u0^(LoxD#S;A<^ZT)!sI&g zzoi-n3G5@2iB^=7c*3meCtVDx4GvnFm}T>FO~Bs59kl;hdlR#UX|4Q5_Oc_v%))1} zdcvk0pw<=2-4ix}_q3^3$i^lg9r;^UQp+nxaeYVp&j4mg?t8h5M<bS_c(&`&%Ak~7 zx$pj3pWalb-0|t@rOggiO`oqtH*WW5AeJ>EG20Oq1|ZK#Pzbbn9dyy;AlDhQr>hu) zzV7>P(JxHeM!@|2gjA}x=19)X7*UR$XB$%k>E<|~7j2hIL*LF7X4*c4Th?XSqJgEv z9QE4bIfFtR$zvOh`zxm3d++SS+V7sUOF<lGWcGIdB2FrPNc_EmIt@#>CpU-3hm`oD zou?R2hj>+n_7SU4<$_=1iPThC1f9lZ0lx#$Zvh)oj8s_sL2zit?W}e5v&5J<GIp!G zP8W|l26fp0wdgu*+5ycJ{+;h_`Pb*v%Q23`OF&xZ1W5ddc94PdxM1fln%7(E_9)`I zr%iE$aufY6r+!U3ptp<G@%Ceh1HmdCiAL^=sEs1ZyNu^RQpc&CD4QGV-2BYSb+WJM zIU~^Z#h_v8B?tkMsZQU&HWlxF!#&>}D3ObKSyTBRCe@>7FEV&dS<e=e-S|M>MObYe ziry#Yw_r4di?h2L@QAmsg-_}kF5oxMNZ+IVG<wqxnQm|~MxcqI45%U<2NKO{cPqZz zi*FiEpOm8?0C|i2Xc!ywe>220bG~EeW)1E4?K`|uN8#ZJy6vXq>g{sq&Hh_Kx5i2W z)4kKb#O)q4!-Ycx#@&8%AjVYjxTeMqM%0TtQYgr_NBL8<r*__|SK0XFOu^FPqSiY1 zg679i{!o@^jWCR@aKA?_E2mSp-(-`|h<+q=&xp!VYrCm~u2FL7kIeS7wm;2rp~oB9 zo4MoO)4tEz!^Dyvu134)0*ugVs6%9<$CYA=gzJBs+9yWZcAS(4Ug7HL(D4T=kD+58 z?raM8M)ag6Q7o$(9|}33*GBLHM>6pwLq<_l%77pLU7}G|z<M81zP`GXm;2~B#cCxb z?bM1uGj~h)1KpxdoU*1~i0m!3iS6BJ3yL~^oG-PhsdF(5U?s&>dXN0zW8Yx0h<u5q zK|cu}+Gx-Gt6u(W5H&X47RR9F_I|z#gCy#^*2q@GIn`H$qqX>(CF~#>y?@(;hL8xg ztKWO2|3kaA^X|q0U4HY!7s<9u>Kdl;l)lFk9d#E$79r>QdQy_ke*LB>NPskGmQo3{ zlzeEJ<S8$AKAi7rFkl|uu#Xqd5cDv#+9dDg+;*-*E^*ghAB)T7J*znr_Y7U~{(c4Y zyGEL4=|+b><CGd6nmY+pHj)B}&?_{WV5wFoAevLZYOh87B9(@s!RT*RV{g*dzod)K zUGMW$tV62tq<dgL>j#szCqB?mJ^|(2>7^F^FuU3?pVO{T?Y0`V8QvXLBZ%eg6y|sN zCQ5GOLbH#yA}T0HyF#G~eg5xX@5^-IBpN`5$3LFqeVgg!{4Qq`y4IUmnVN`poj8)8 zdyY_bdxSZ`>1`C+6^&b>C`$QtW6;8-9$f`KGf}G&fKPZf@TMs5&>15Iw#IXD^d$m6 z#~a@88In_b;;vMu9E95r^ryzR2o9@OR&pLAN6h4ZcBK9881*(VYAC)<qMufPCTPU` zIlsc$(Gqr{Ta`%ZM3T+7J=!Gi(FIWkj#u@;^at4WF~cYVFPr%mybH)+!mt(|D^7P# zyvEHSTz!<|-;*;I*-W%^Uf~Y7eJ}QB$4E!<w_g5P$?G^B6)SN8$~<b`u0}w4QilbJ zLSzA3Y#y1O>34ywqSW2GjVPsv`G~koKrP*^>HQs3M8wRQiA`IwB;I=mH!|y(EmR%5 zWj5P*PQxneB-GM~-LgJOyTOd{5R*E4jkm?IJknPT)*;d;zBDaQmPcQUjqqF31+{;0 zceVo=bjyo}0la#%j}C2v#%%olrn=@TFs02H^}omku(eN1ecbWgorl}0Z6_B(rIA*! z`(Tp}=oc{=A&Q4xhRcWPF>JhPYayyxWhvc*8uLi=_%P`cVsMNSqCz6|nNu_-qsv}K z=LmJ~G2%FG&mpb;sR$j;;jfg5Q>+ns^%<qHdWiZ3xg|}_e?Q3rmj9sGA?Y~W6V`ZD z&Jh;G48|D_5<~m4=%}Uc3LD`f7eZ|_efW#Cuy7uSxI+A;`!#K6p;E&db9)KMI+TLm zXR(XFap~0BKi-?BZZP$-V1j-|Q3@`-<T6|3&E}o3UAfby#S2id0d|=jxA5^=$COOD zuxJbK{bux%Dc8h8{O`4WWIykU#pn*IIKChGH=ZFYqbGeG6_PRW31;Q8T}0o=E1s?D zXYUtUy_?JBrRvY}yP4X3QzMgOHpf8xp;L7G$<?vY<VnB$sw9g^eeAy&jwC_qMAI+c zBE0pK=fQK#)jwx&Srcxg`PvHX&T@e$X@*#!*_%5a7t)MZ&MSD8$*uHp*L>*#^r*i5 zJ{*Vkw+J{WBW2VAmGbVDTYk<#_s1O-*9bZST2L@nBP>?iax0a6wo}rc!YeQn9rY@^ zE<dOVjDMMlZWSV!F#5jtvb}Qg{5BHz?Z@rAk#?F+$1=jmHMN>>XOBaWyL#rX6@@x9 zYg{&{&zaw$&ujek+L=j;3+w4Dqq7AUq;tZ^-<J-><V5U;IuVQ_i6WP%jg-?qg=VH{ zc8+5N66JeZcM$H*rQ?agL*?!tHZ{{q!LHDQ*XNkrql$0)5h7QP6zP`9o~v{20fMF- ztQup<XJ$rAT&{z^L1v2(mmy)}Y8CfyWRXsVLEOA`9nR<eyoy`hAwlOe<@AV`pQ3Z$ zR#8lxGAN5M)xb|HKS8sSBgM&OYYDbgl+Kpu!1Sgo_$ZykaxF3T0kL)1>hYFhn&#=% zkALwS$uBpi0&=p-Uv0W*1)*;zHYiG#8z{XuM{z%t&2boJVFJR0MO~eiA6dtlY=z3k z1MBrP6ao&S4VJw9rg9ZK?8J?Tq+Tgzg)!ka8|{?WG7QN=Zu5}`$al0qq)3D6SW-}K z7f=1dkqLw$-)hYv)9ZTT^bhN)t8%XGs`Z9_)IsgDd%=L@93!eaSu^`#6OTrUEOmrM zy>cJ-wO!EBUC8A!*+oKdvRsrB>WGJ_xtX`zwZf1A4~GVG6HuDQ$;Jt+RZDZp^|I9R z+BFQNUX7IE{jEm9sAGI)Bt76&Bkozcun+?kc>X(K4zcd=Amg9op%5$V6hAd@JInDG z-=jNT(+KpiVpV>Sjy`;viGO?Z;k*huJWim9{GF78>ce{nhZH?cG~+qJk#2b+PK_Y- z*+PqY_3Q~>Mk|jo593T$z^>!}dVOUV;PX7qf@wKk0&S3rfG?9xIg|EHYQZW;+M4r% zOFf&8L7!ssSD(7N<_@cytDE>=&tY4tb=-bv${UWLqQmNP;O?ftd=}`5gg;yKw{1BZ z4vZJ1PcPTmT9k~eJ0JNla+>U|UHc6dxa4+S0zGY=_XpWhW}1x3gz#98<DPgv4bxY| z33ihf!p9XA7VZ54JA7_C8eY{stRK1CZJ}Y~g4oRm=d=>>#+7DBYSHNnk*c~ty>N;+ z@D)lZixTo&jZ0x14&}<yvHDfJyx|vcjO87S{HAfiE`S=Vx9kN98Vn*hwa=wlRr}sM zlH$Nij2~rI8g07j41^OjUbr>)pvoi7D?Ao8>>W{Th#5{<UdHYxgQdTI{1T_6WbaoV z`kuSz&L0|h-@UZaX4~&~*Hli}adEM25}DLep4eQ!R>;NH6~+ce*>^xuj#iw7uy`hu zhvAcs8Kx4Ds3^4P9ahdO!-xdB<-bMv#Mdrv@>paWL?uEqS*2u7OD7>Vo5MaV5)+7X z7F<@z`%#>xCG>hs$@eN_W}YT3@E%z@yxQB-4N715u`zDpnee)^9Z2sHVcm+E-v*`N zo)$#1bg8(@EA(iE-fBO1iPC6`jq7k2z)C|FHDi`2@jjxLp0eAo%&Y~!xmQre1hQs_ zokp7UvCfhcYl7HCThHtE-Kvu!_IzUHuwT%8*R|fe0s+4Pb2MYfZO#_wiDfrWfcr#( z!=z1p#js)z3J@A0W*Df2YYEjRIbfMe1}xvgwc=dF(-%j^^7WrO{eb&cSLKl50>Ft2 z2pXfT3McFB;MayC`AmV?AUbc%lF6!^;z9#JIcAQdc2y!QLwTk*f2k<|Gw78O!n6>% zB0R;meYGd$<G&CXa~(mVQROuP`5Aw`UHeUnFog*tv-*S<ZfGJP!4>FvELIsQs+Q%z z2Ud!gpyM+a<hjg&uQxL@Rc`HDdzYW{X((4Fk{keB>su$+Ww_-I$JPPJ<4h2zN&Ojv zX}EXiCH!^mq)q1&nBqOO?LeT<p`)fImpe-d&$r-V5-zl+_4J@o`}l=;6a4XSNdXdz zkk^b>c_Ck2jQI;yDll(OXps+uVML>I^COx)Zu`wXy@E8#Vd6v}#aJf_+e=RbeKY#i z)^JMK=h{k3{GfH|iQhmL`3PDQ3|~4GbphY32pPSLMWbRszxY94mDGQ;FC!g5R_0IO z;WF?)u`T2mw+MRuNq`ov&#Us?m+%7y%KzpHH39i+2h6Z5kM<3F-PQ;9$$Wesz7ix1 z++-?wAECDoz6yPmSVS|Q!O2FeM-`n4TT50j7(Tc44jFrDWmBvTFVMeSMF(rD^`)O( zM8K>!+DM*+n)A1JPVM+@3go{Qv}anA2sdD8p9UirU+GWCuFV(vqu)$4WfAzXs&Xy; z6eB7jL`#*HBTLkHZ{uH7*MjyV(LC6c0Nw4A?2{jhOQUAU)cF!ByaLXgZU7st$rE(Y zoaMh!Ng<=DiS!+}1X(DLkqdguhK7zsYUCw3Ln#T#k#<YErIUH-KEdmOVzNbA=HVrL zScydHdmbyR)hx}1Cdc)MGY^1>sGtwgW9v;_N2Hs++PTsS1^Q<aZIgge__0tz61%T@ zhN{of0aL%+jA#jIv9g-DDJiNm_(=^BC$jaj5qe+JN5QA{>JmgCPpBkfDDKgm)Fxg? z(uQ}X{xh(rcFp&eY7A+~qE5({_N{#QzaxLQwoh!1g0XlqV<~{u=eULQBXxV@p3cUF z2%BpcZ&cE;j^Du9S@XRD_U3a=?;CAVUUqfA3|B#UMNNxd{-?$-vTz*8#M82`o^Oq6 zXZ4YoTb-mc_B<}coSkF#SZN`j3wbX5W3s$7D*7D{hu`et$qRcOGeU%1q920wm;L1M zBt>1q-n4U4uFhs@-zk9YbI%E&;IajO?xRycy40#uf&GzVJSybT*!c_p>51<hKMmC> zpY5}Z&r(gN?Jz8a%$Fa||0H28UR@&;E?&z5+lM{f=XZt6?Pnsbi<c?T9-+2fdb7nN z$o#sA<kKk3e^^uxdIooqq)kxX?%TBtM&B_xA(g2k0wyRxly7|bChY61?as4k+F6Dk z`X}abSb$Jx7@XPzyTxChSg!n6WnQPatwht`d5elY387|Ca9jzjP?qVM6Dw2+7x6uu zkoXo58L)u3Cxf6qT0qI~QaqCy@~v%m^$M7@q-<V&`XoX*2UFxjdGj>Amm%;acZph7 z(b>umdfgZAslI>Zmm@^nGt)i0T-26dX&Mn@Xf_-y%5J?pFl@vFa?&b!9hjgVNPR9w zF7BCY|9@6gU_aCONE`V{y$QY<T2_*{+vIxfWqkI-rShkTL%1u4SF9<(PeDK2mMeQE zIv|OV`IPBBRH(%{<X^oL0^GpuptXfZDlq>h$2jRvSk!d&Yr^iBTNCdUPCthHtb6gk z)SPYRiiO$+fb}tjYCaAMn=^+^^54%dF81ZN5*;vP-{iiLkNh{Wg2UB!vcE@ev5C~w zB?Wg1_|;?J;<ZLgS9y2Ts$Fz90klBwX!<>JE}PzB7dczD_-Crym(&uyTWk`45kQOq z%6|X}oG!SK)iwb*%-F(&ZI${Ie@cky+Qz5Q7%e~E;R%iHxiNm+kWQzCzP{5jf*!4+ z3s=vG$9c#|`cYgh8X-GjjQtM|y8UXz<TF&)M>n^+P6jLxa2C;9Zbi%+`gj@WjZAJI z=>LJ?VHvbmsN{BBgiQG!7CiB18<B5XyAys2SP4V~^Jg_ReqYxD{t9C5{)1uTq{!n@ zz8)vp$QnxYPw_M?Sz8~ad@T`JU9y9&W$5+pO|BW?&+C-@22NLXt`JLZ5=Oz|U2}nt zu05(dUP}Hub2qf2UfmtZ5{R~@q4HplDi{9KdX(A%uYeRkb<uMCMK&Q6%As+rRK4>P zn|0E1NqOxxBZ>c)HpRKqchl8TA-OWe))e9iYmqM$DETr;EK3)54=FQU)Uv7{?Ks$t z{Aidg09zt>0j{d<2_jTs2C@p8Q|w8^<XeQeK-w|lz-xyj>_1LL_GFiA3Um`{qzzT3 z*c1ug!NO$@O6{Hg(CFJ<H9Jzlr|y{<jD&y%YRNjh=uhwVxJ=%52DUhPQ+Q`pL^2{& zf=&Cc*XQsnV#&vGhYntnXlUmVVh5`e+V;{eqwMi(^47wK5|sq+2@7+LT7Fp3j0o*` zM}CQXVJvFQ3s;B1H)74<)X;r2@uQEYrvf`s992Ns)}BNhj3qO0_Iem0)R=15|I1xB zqjIl{l*u;z(ZySf`%o(i`HrScdg*BwJ>j7h(IflP|GJ&OZ9mOz_n#%J-}rT~McAIO z@~-*K(+~4Uk-N<?+>@`Kj$MVCYh&`+wdy=W1<#MPrOIHnmiFg@n5^-SMown5SuUhO z4Hl9>`Joaqq0i}*iU$LfJUB9ekrn$>^-jf16d&nr(hP5AA;q|UjZaI-UqC(*797FK zt^7)~NSkBqu&(sjhP0pguP8;#q&yC%1`J2uz67#?vyBzAirbGPA$5HH78PZ6oehf7 zuLoJYbRA~_z7c97=C*@-u;BhUyUc<QOYp7??n}RUu@*nNxtrba6&+DzEGgjmgW)qV z^llee1VpB6BYMYg%%(Dy-2`UVGS1MFkqYxpDXGR@$5+t~vdP|44Y?5432+14$=pzP zZTR!EVG=Ld4dTEc`WQit2`nNcRE8Wkgw7G1PL+ti*b3X}*W_oltRb8Vj;8SE`q)XC zldpXD2<26|4jHC0GuH~+hrf0bu-`tqs%0xE!tV(9GqQ2JhY((x13yub3G_T{RWp(Q zuLl{pBxQhFX?au8#7X%V(067Vm`IVeYCCo!QuxYkS@JW!4~-uma7b*{gh<gF9vA76 z_0ZGnyaFP;Ls=gV^8;M|h@EVnkO+kRblL3q-z%`eD<=5Wb1}21*(hZCcmq)}pqG<W zmneZJNx_r848M;9Djz*PxIX`#2YasZJ2`VBzy5d*l<UZ*;i&4S0T@9PS0Iy};3ub8 zyY=+otFah~gMk*_&Emm0Sn!}A`8{y~yJ4AaK7)YgM388&Lk@z-i}i0`QVy~ltwc+t zjD~9!0i&1SKIJpG#JkPSfBtxM-ow`^g6~hElec%rqXS+KC6q=oLT<wFc{LED)QV9N zYm4DiyPCtAHeKx4eM-a@U5J|@rL-YIb4k1t`xWlj&_Tk*<WOymdh*S4n^;uxrTG4> zyGOSTGibW<0oY=3en9#10`tZzuyA$##+Z&b+iwoBhv*dq{Zv{G?50o8uSZ{dIW&lA z^hmyD!h~MHoF%oBy!)r%{!$xth*qrgvukt{#6xxpGy$yW!I&5vWcT|MH%-er>h#^- zus%Xe{jcMjuC#ueiG*Tw^8s|pRXRy41Ht@Gc@HvK<=Y|z8DvV9I2e@Czdbs>puG9< zEYXkAOqFN=>$aCy;>p!S1}r%Dc_FJto^5@y!@^Qb?@&$aUJL$y^X2#{_Qv*8$r;24 znMZ(!t&lzUnA<c$vQaN}E7!?WHhAf&1xwoqV4dPJK0t3?*#N+)Yp@@E-NuN39dX7Z zkhlU}0erT)XNeX{y(lPS9DRNe%{C(`&|4#dn+NhBWz~9e4^Zl!TUVLxj~@VdF>p#$ zgdc*Z9f>qg4ay4~#dYlieNGrTrrqCi7>8yQJwWU+h9LKZmY^$p*%I&y2b>*5wi*+@ zH74iItn(TAUN&SUS3oif<e>0ubMHvN1c}hUM080vSlb{I7Hdm3k@ZyzAIP>F#LfQV z5nJ!(T<k1YDO0(xh2OTh-I^g*2PT*U<qvSRJhH_-aA*aL5C&>yOad9KY4ZV_a}Ki5 zQ-R4vJ_*K5ZoWDDSL$Z{uwcaZGJ+%`gSPdY=?_tzkLw}>@heIZ2+u$V>Qh-e{RbFi z?8Zx>V8VQL=v>$$d;ia}0uzwl$+Z{0>f6teyk-7g6D9?gOCVuF@+9{Zh+g0uqSI*` z=7FUU1Q|W{0pgEEaV8^0o%N!92u=5+W84GZ!eg2|t#kD<Cgr_|5bgngL<q*X)9J>B zO&AP6le7OV3-By8Lv$ZQG2|gK>$$w#1nry1gP@d3V3dG?nPgusqD3?iUwqbRpUbFW zpHI_zf9)QMP^(Kp0pkUB#lQKqG=XFyl%0vM$<dFOK>e8h-LA0^A?OxU$Eo_nz|B;R zk#_=X$0*jmV^ei@TMgXCAXOLHO$0V8pr{I*6@EcZg`Er~Nng?jVzvy6gtGVl{d=N~ zLTwg1YGTzat<}gTL|2-DW=8nmroD6yx|&|h;sCQYel~rsw`@4T0MG!)p29~ga~ofr zAk?93S-`0<eyqlhVnr4>4h!H^X777%Hy{c=h-=oax6VsoJ|JSi3#xw!2};W05c97C zv>T9EMI?4nIM+%h9I+n`^2t@ExXB7j=n;3_TzPz&1myeJ(Wx<Ux8~B-IrCaCJ6Nz# z$6aWV_!Ium)rG>8mvmf1%Zt5Z)QBg^Af6QJ=AY>HE6n3wyMZM!DxUOdo^qkgP{NFh zwv^Iff&<IgusIkFYWBXs?kbappI%qW2mQr=2Nex5+w6MU=+_|5XY521n$FcA2xg3+ z!+xZRzo=<Zc%fPt$V>J<#Nvq&^wPd&mbvdL7v!{M1rXI0G^#`lqA^)4%a`+qUkyQj z5D<b~g!QJ)B==<LjQNmPE;x76#H6h-LwPa5czyyNmE^%V=``%W35Iei&OlG6UC}f7 zPWmpcpV%XpZ@ta+V$RkhK<s94WK~^48^a-Qg-@rCDgd23rJK#JbU~~uPU)kqDB{zR z5Sx5pF1->_VG#i#IdQml?%y-%6#(N>x*dM4`mevs!Y{9Cj&b}J_FmoWlX(*DnnM;C zVlP=IRUII1WL=J!P?f1<uhOwHp+Vwhz&Bt(LLGXNl;I?$m*lOUV+sbFLeedlT4HdF z7kt4w*jLK8jaWN)1K2wX^r2_$8j<Ug+Qg+ys#%79S~)E?Gs)p&&z@N!CVa9Scn#2R zJzGjf1wGZ2UDL75Ha2X=z-F*RO33OnvnG$2acP+Uj-1HuLBTr1etjPF!M)7<b#^IG z+Af=h@xTAH&9K0~dw45_c(7<OgoOhLk1C5-ExLSywD}jbUd|cbzDKA$AbdcH!P}V4 z%hfaHB_L?;z=#WY{tPl$L~s#YO2AJ!70#)IQb1Kai$(^wuSWOf!+aq(EO#ET&B&(3 zSE((h64j{jP?vaKC;l6hb@q5=usaPv5f9I-9G3rN%nsf$fDYH7iP1<Ude^9ybxF;y z>vyn3bw!H-Lr7#XKgy_NMoph@hAY*g2x>&8IF7#y?$cN0(qgx0zg={@m81vl8UJ_Z zdMNu}^M0n26og*u=iD1%;n2ZDWbmb!e{oeQC)r9wz$OsTzw!~sAR7i9-UYeoY>D6t zlm^f$uJ=oDrf<H<L>r(uW&juQ#A8+6F4mFqXSJoHo;tAY`5L~B*c9>p8L7SWn)c;B zPlP}*AuWO&Ru9qt@Klgl?(KNYFd<xZX?v!lsA|E1uO*}}X@wM%VE{!y7nJUZy-V8& zDSAEh>p5a>QX_uJsiBeIAb^z7VJTA;BG>k|_Ys1`pj{z_LE0xlkoFuz+iMYP#bDtx zi22{I4{I`b`&#`8wKsp;kxY%*u8P<{{x*SABhT*Tqo2zYSmOxa7X4~N!Cg?ClZ<ek z8Td~%yU0}|qdHZ`_fSyOJ|r2Zu+>QOeVTxjUcQp~iV+9sCS$OSyJ<2jC+&tPk9Wqe zM{~+C6GDSNA#}2a7qo|k9;TUz3kFx1O`kk)7&u9DLmTQw^%!VJ?#Sm(|FaZ%y<7Tg z5_rx;mLtk0Xlfvzoo0ZDd}pf;VnXCcxh!XIBKHnq7N%{at|lfHMcS2tKTb(Na54Jk zC2D}{rA->E&ls0}C8TBRp)Afee8zKDPZz$xqUu)wZAo^$JyW}zMNC~?#OOSAat?73 zW0J(c(1T0^HcP7rq!6>BZ|;a8a#sFV^BcsxTko^DK%W6qMAjN{ekQ3Bm6~@c0w)5; zIZwmcp^{sXEoa8aMn}<SFAKCqy}nm*a{U5Z+5ie78S3gJ`>An<6sXEXJ>oct-+iZ_ znOdeO&?T=-SQ~a9dTl?$d%azjjIgpn)Bvt;7@DU7)<nNeSG3Cg%|YgYM36F=X5~8{ zXx1Y!j9JA_GTj&qN!aNT^aQZMrUKo&4A9%kQE?>0{u(2@E-H&b!pdd6iRH$pn~0>o zmrMS9`QOT$SvF8`^QCqr=b5XBA~jbMMIVAha)@C4^l@oW_EUcVh(Te|)$_aox8o<9 zjzAd>7mrq)UCeLqQPIBB)Ek7G>qcRFNMg#u?EBn@q!`2cK$Y+A#VVNtSq%w6DX$aC z0N<VdS@V}5!-_dg1GLcxTQ9vkn|@Lswr|mbimPW#CR~QF3=lC7gd?NBGz6v!%B6@B zFHpsoBf-dgcm!Df1Hdbe4V#QN<9Mxas5pi;O%wV=EkY4jF3Jr4gm=tBT9bWQCW&wP zsb*{ahXS($Qld9mZY*!I-B}&7oS7Xm-#e_fu1;&*Ry$^XX+8#+^C}<<tw;YpFPD3h zByjW<-F9!b_5=ua4+0%ZyUT;c+d?3Qf;iz3u~ABE*C=0m3Xo%k7KR*%?o792Q+OBw z&!;y8wh&&vpwDI|u$0?3&JUZmqY1ra>L$JJKG<z6@RF<-wQ;Jo-&7A$B!5qtiusl@ zMO(x2M#8tP;0e6G;6$B9^t!3p>*R`Ry?kqTAU1t>2ve785VHo7w&no-*$Zcd4ZBz) z-6zi+(Pn*x8=>!7Q_Ygr$GX|j&5~WjhOCi~Vp3x#VfIDabc4X$a}VY{=!meRR@Mii zVuRqAW>U-I<~I%q4FiR97vSa)jWFbJ_nf$8P`u2$yS&Iou!AgOLBN=@fGU}f@JUj$ zu;3gMzj?nfy~|rQQ{3+KrG@fhqMIZNmZio?nic;mGv(BSgKNvDn*AD0FLNqpI!(6_ z2JHUcvaz);XeZ^*=-u&4`J?~;f%b%nY@K@W+Q7cDkYMGztTr1=p!C{V-RdV7O4y!F zX$`Hi#A_%_+Vmx%9x{TJ`yO#qXjt;AzLujNp<9^HO2*TGP~n2rPMAL?d81xAmcsyK zXgUU*i)9Yn%HNP>XY$hD!;BYf%}4jO%}1MC;tKd1D+^9sp-cq4O_t^TB(R5YqelBi zzsBgstj0>13k}Dk!gqihQ*qyRImk6tIlxx*yz|fmtWYE%3NW}ilCROLjJ$?-gigk2 z+i`%a7YENyL<5IPEHZ1ndHwTT96Ekkcb9p^xNPo+-?ugS#!>f6(O5LrXy=G*b;d_V zSWps%(P2EzSesNv`lI_s=Df~EI=pT5DW^+U3blki8(H)2nQTQts!IW<8oH4&%iuUA zq(YoYNRh6oyZEk<@axRdeKas+%v-a+?+gMx2Z?t={OJ&4wcm<@A;Ww)fTE~9CR}VH zo#c#8d6f7XH(2ok{h)_q>>FOc-eb`Q-N2@gPo*mdmH2e0o%OO?f-Zrnc`JQ>gR6am zB)AfygBT{lQ{_o2H#0_<^8SF`pHcuwJWX~$n5)C_6BJ%D`yNax0P0m%W$j*^+7M|5 zc3xIm*u^`>H%Z0R8=E4b_BNuvdT!SaMVw&T>v%aeZO8c#a~SCT@ZY8fW@KqV(s=Ds zkRdVv1XFU{HhI=jfZ2C@1-Op31CuNQ2;xeaeWH(`iXm~UDsOvx<Bqw1Z`brj_W*7| zqKD#AERlsHy@R;PqHQ@ZOxFy?o)KDK3+^;thas1PoeJ0+TSZ}bl5XIrZq?3vCDSL; z6QMj=u79I_uHxCIh@pa-yY!|g(8T0(I|o!nwx>DlGdGjNqHa%u)bGCPgXqUhO{*CW zyZy$0-t~95b24S?adI1)?}vs$5O(TJib*NBR6-xQ=opweK&;4?gDxL0Wx3MWp7oGX zCEdPpuaxk@WmxecV`XaG$#UE8Gfn@}*`fGNVd(zoFaOsZf&0#n1j&~~oUA28cb9h6 zv)hN_6<~$0FaujI_ZZ^MO_^ix>F^{gK=T^_Z1#v=g_DPp6CxLlmkI!~9&qd+LOya2 zz#$5`ITxHB+Z!tvzJu1~6nHBsi24S&*{6{k6Xwj4ovQx1`EC8MPMchKrrO`b7+BCz zO9Vl#*1@V@ikOs_EjBHvu1>~E9K?xJwAKGBr~mW4$!FDrwtLA_m-bM!ws83J*0PS~ zXu#WO>U*rA5W!WdJ}nn!2XP&_(T)#h-CkQ)^Ur|biLJ5p1&20(1Hh?HK7OuA<;0|v z2ssT1V5?OCw}gc*m$#*4A3)%Q5j*_D*F}RN2Hf<bDT|k`v^E&MG-t59PI8(@qj@4y zp`Is=&0d-fSU_nh?#jMIHJir<OXa=U=QJb*i~%Aro>o9dSTUMjos-ktNoQOEKa7~c z06`aL=4tUe6hPJDG=LF1I|d;uP>=4I$!G?$(yQ+I^(lW5*=Twpz4%myw`$Kqz4Unx z)?X)hU<S78|Ac{g2COMG5)#u$;KO2*Z&q^y4m)NNpN`${Wi8h@PGyrxYA_yK)(i<d z2-hONm!Tzm(YqxhTaA<Wgyb!+zmMIegsd_Qu}5)o`f(To+koIjd{rV9zfe#poO^V8 zs`JL3<_$O0M2KE>zvgkoA%|*0E5Vy2JPf@zE+Ku=(=c7r-b6aK;LCmNP!MM^*Mhkv zHzU@ZCuQpwjxHstQx)q+%L1NguoQeKu><^`+KnsXe`Q06hIKN?14T#4&7i!_W;(Fp zq6@(n(#Nm-mjYwv*kqMu!Lf<<p}>JG;F(G~uRpNCeTofYRAwq{GM==o4<@2^z>o}e zec@tbW8JerE;iN7^W^^5K+|ik{*4)8<<ll<NZYYuu9yeyMl3;E3J8W?0jMZX$_x>Z zgR@?x<L-~_WaM@JCogau-GE)9)0jA=f+}CwdvLPnbKKvfPHOY9rw}_uLV2uVzH&Qy z^<a;0yjY*)W7h@c&8LMRY6cT0a<(<l`>lX^If#8d)CEAZ17AmBlc@rJTV-a&tzqsz z_seH}99lELZ9FTT3mZyvH;0K5+Mh4x&x>ds0cah0PCVw~iP_1wCKs})eRhM?SY~kH zvA?z5iIYY?D&QsAxH6=CLKO$pr^S<szH5)}7^uM5^Q89bB8!17CgERs25?KCG5Tm3 zj;Ndcz)gbJuVXk!7?C;wj4mbUwR$E8iJFtfas^|+m3rVIK%ZXV=yF>MnE7nQM=MW8 zb`s{SOu@Rhf)Z2YE!SG8D$aR?-(*%Wrc_`(Fm_&d#SkD*m|eYcN<=!*dkSMOG$_pb z?8v+Oy+a|8G13-sAC(^PY*}ceBVd^kDOY}`PBgH83vzKMM@-3AwpmDUV#k#x%24nH z-k!H-#p0p@T9^3b^ud=0xS^`RV6q)7lLw_b@NbVF_Nb_(?9#n=WX1+v<8J@sY)1!n z`?+MxJObWrX>0LT9BNE|8xyZ%r#b{QM*qTOTHFkbTDW1VSfqYh@AncBaU(K1KHAK1 z=#oi?dC=J&1JHNFYL_J>0Z0W7#glG~RJ8(ace9~XrbpSjpE`kp4zn=aZr8wR3g(u# zH;F2om6gu=EQtk;i4CmX^Yxcmc9ZHE!64mi*VUWo1%j*<wj5?b9uH?0Lo((3*FHTO zA3V|!a=VT87Y~e^+y3ltip={v7BTfnTO&3u%Yrl>P4X?k<KZK1mHc^)$sZ45m37vm z7?<sjee3UTf3l?TRq4r(29%?z#R!sP5;)*gG2A!79P<JT(IjqDb~M$}$b9Cw&EfL1 z-VZqt>|jvO-tp4KfzDBPhabW6JOQqGXv++-fGZyv&WOXQ2~>qCe@olAS0e6k*>Si4 zWZ`*_C+@BP&YUdh;PE&~GU!oe^Md_txM7KoLf~4Wun{|>N}$BE!+2tB4Bw+bBTx&D zdC85CH3hWb<8gjo<7PcPI!Ws1+02|^#-Wk0Jx^iKsvoyS0T0I&zgh5hYW6mpy`mHi zT)-Xer39Mn2_n~F!u_ZtsueqMVe55e(cxN6l|Ep`)(NuOBG2frG<|@yvQo3}A#24@ z7Ut)uAO3sv;H=o>vM@p@%5>gEfBWDcAr6YzPY}fg&51!#qg1BI0#SAd{xrBK@Yh%k z16ya&6(zTQ+~Ym(u|bQl3j0CCY3W0qZjr-%*nR`^!JrNUey8OK<yWAXAaHZFI>e`u zg*)Z2eG))dGuNlCgE$-OMSw{Lk1i0@V~oWScndvjWIAhQ;^orU9)14tNu3&wB5#}^ z9gH_S3zzP8xm^x@t}R&jK8yJwFdoHG`LCBt!PN4>;_riBzS%%!;L#ohd=2R6Vhmwe z(FBLVUWoqz=%xL&Oa$7syOe8Fj867xlK=13c)reNIvA+jRo~om4@;>8!vB$X?dQK1 z)$T;jVp4@|ZTCBZ{Z@?hV9K0`;L0Xbdz?XMmQH-;=6#`(ml&4;ECtj=#}s;ZN8#3_ z5?QRTf5K68Pavv<WMI4Fj6H#xmb7vkH%Bg>r=i%|pDjs=Y|C7qj&1j1$*?nG5+Tih zcP02(ea4`6dWTMzbGa0>%fn&PYUC)<|9v^;UTF6PNWsL&SNj(&Id#KABhX6J(~K_< zzxk#{O}b_d$nG!GJy){*^ZVRt@$Q-W#nl2Zx$V!Ao*e@AG&8)$2qcA*H5b#=2LYkR z_Je@_b>(cAsK0@&AJBM5_Vi0u^@?(MPt>gHxuCpc50y4x^bI?Wwoe*w(`@Nt*yDAc zt$dv+<1dn#1GtI#bg2`W9v20oR%6*bitJ~W{v~x`8TAe5t!uBf2hQJS9>-=xQ3{8e z%?3)pYn{~ZuzHsQWE0;LB~cj*zDiRqHtff!;Bb<;YyqIO9cTUF?85~UTd)VDUIF5M zh3-nSv5|l4B<lKE$zu+697Wo=DY_btY;&qYQODq5vFo2PbXN^5$*VMD8Rm{NLM`&5 z0#Zvj*!8Awm90+OtLhyvQ|Q<^*9mz%NC!<(5dP>4$F(hc9Q9{8$La<fQq(Q4c~1Qn zBk1RD6gLO*!+RDSe&78Sq0amdfq8(1#ct^;mtLvS8M)KhTd^L=0m4XLAk*Kn7FmV6 z{&F*1v3MF<6B_Xw?!BdX7cvl0F5KRaXR8CQv^lke8(9zr!N^*<EB-)`51j<=i&X|? zK}K3=Op0Gind^xeTIZ-upSMESC#lA4$zE-5Y+uA2L~@2rpj2=G&;`>5FzJQ>R<Cv1 zhmy<joI*Yy3P&7Cwq!-<h5JBXBJz)nNQ)_peKvUl^Q*eUchujZH9+U|WI~C~vpAR* z*(Tsjsn)S?z57RnR-Ix>1&|TYm>QWU0k&d2^xAJb^Htz22Y?wO#*Mu(LOeHr?zd~& zYO6Ba{2vtUse)E^Eb(4pHYsSy1ODbpAC6NikjFt3f}AX`pgV!`7Jf{S-&}{#g<h3h z+c@9Lh@5_PCT2xriUods?}kWFb$hC0d$8a@!z@mh_Q9kjc2vXUYdUkMA7S(%Po@2^ z6e9J;>B;*E+HMDj;9k?56oBDgLp}$6&}MxJbO_pYQ1*`1m-c_4GMeoondTwt8lq^e z5usB5qpC+%+GWCJpMpjxcK{eXPSy?5?D9N7Dkd%66$29YNZIf{g<dl(V-56<ElvXT zQx9gxueC!euHB8$*2SegPXE+dpb=t4LFwVw7uE0#I0+RLk;~N68#Na;D0ek_uE{QL zwd$;oFb7t!rD<~*DfT_LYW)@-Q9ELlx%dCV$ydKGcB!7)1N~aptS-7d$FSFBkkkU} z>38~8e;R7opMNg6kmtc7ib(AS_T(mBfyduG`K~rXb|x!`-<Tyq1*j#k%_dj+0MEao zialoQf$U>&iJ1gq928>i@1FyE38$OcD29aM+tg-0TiBj!Dv#9?BY}BsU7w%~>`0Px ziy_{2tReEqufxSIHqU}|AV0Cw%Y=nsD}i?pAr(Fxd_Mga?lXW0uRmSMLTs`iYZ)Y` zkcWhP2w86-`YSjg>iW0TN!NfN6{I&hV%V{U0x2hL_+GQde)?f%=SOKX=_DQ$0 zz+rde>Gn^M5_1|%-wifFL0YxDPl@TotB2$scuPic(|cbmLt1VYfmKPTfDte%JjtYO z`9H$mGAgU6YZpcl1W`c*>244Zq`SMjk#3M~kdj6^Zb~`@K{^HL6p)gVmX>ZfYopJ5 zp7)GzjPI}9d%5<iJ=dI9Tx96K(bk?{=o=1r2tNFUETVC|xYtMKhe2=Do5DeE-I%>F z!o;<=u}X)8(_Kc_Y#Dg^kej9Pl$GfyF@1m6%vGIrwogSQe(V}e{$ifNWjM;6p>#%@ zMIeNwfBBJi$M?Z9(UL?1^c=tS9(h<(3gr`e20xi->G|kE|F;{S^SiF|k~YoErUAA- z*dJD@<T!lnT!leO9n^S!-y=#iuM{6(i4j56KN{3xLA@UFf0fRXmGNZ+c-q8r%fU1l zWzuljZP3{?se1`>ag3@Mj3RxU6u0JcJT<U5<C%ONrz=@z#(LlEF!&`4;LOd1X`8e) z8|A(_DejGw{TA52n;&d13lSx9#cGi?zjVKJZ(Nv;`)QaC|B&>9s*vfUnepp4yvCJB zXXoGifPNIyM+ZXO6zcoW29qfV5YRpyfdI^9v{t|Mv;Mi9_ohdb0kD;6@w07I$B?=n zsw+`1PyT`du25hz1{P{H!_EWlk-*rzVMWv+8^VvH*nVr2L1`0F=|Lzdl7aV{va}zN zH;R>#fe%PS%$}d6f$H)55BP0<e*&XlK^2x2iT)_@up`=ScS(5|u_-oH-st=9`$}%j z;5u)y7D?LCZxxOe?Ci=>Yvc}=c3TM7(1w;^Srz5i^w+Ko-Ogx2LQphK`>L=k+m{24 znrS}IDycA>e@Y~ll3#J`+T8CEK5A#^+5WUyX3&$e=Fj#tcg=7zm=m6P#`CXwK2RO1 zv7G~634v&LG$wuv{|6Q>$VNq=er{YT_4|I|XqD-Xmc{qNEKSOZ$5@htuimORM(HV4 zgy7#wk(mXA03TG+&iygGUf<#uPcYvLApZthIdo^T!bp;);2n3*B*%akrmQfQZ@kKT zoz;PuYg*O(s&n`*{i~3qRl4?dqdr&uZYE%D93kE!xVW6Er#*0<ibN7mxnuy2<y7Pw zu}DHpCR`S4G-q{QkhFK@M~damDqFx;&|1SU2d2{2w$>8^Jb31_X|CFw(EIf`rOn*@ z{C-Ax<ic^Zp7o3UDG9kIxTm9m3pz3@Ury+N)boZF18$cSu!y%OX=FuGE=GSSR5#H* z(x<0tn)*5o2j)FOV<|8Rw{MjKCGch*U?$u-(bGQ0qs68{kvm1FYO;a@zEHpt>KXgZ z!VP;E^G9;dhCxwbk5LTie43xg&XV&FpDRFQXCC1Y-;>gTmr&0t&!Cix=&Ko(25X$x zB-AA2?jQ&YFiqJuMA7r}BR3Jz1Gn4OSp)44PkmTG$v#~HYqX0=R>U1rgL3pkd=kcg zWu*7q>>Ff2%Zz(lr1nw;<Gv%N!>G1UEEZVO<`#C`TRGDOAT#|w7jY>NeX$2!bVhba z9;U!6-ybQQ_Svo+VgQm=MR?<r*F%;iD~!oMo!15g$5TwedutM!@oABjQg=W??pH5J zD-ODef{jmi?M${ViF(>66MO!|$oGE>Ad1^-xy|sMkt_ou0HB`gLitdXg!t9G(gMsT z%w?XO-=dw3iKNIBW&6+2^G<hI$l&($7h%jpC|h)8l+k!+5S9`N(vnDnb4LgLjE>gI zTxY!_&8Ph4H<!TgliBV@Xu8Th-0N_V;r#lP-`@&7b_xuB8-*-fz;?4HMXSBI4_N8% zc3m5M?LJBqRw`gn8jh_3{^WF59lU7@*mg}znb&0~kv0v@!k$Aj#ua<(nX3TZA8$gZ z);FN(xH^*cp<mbg0$0#ut=^v5yUW_$XxicYV$04U2*3I7CBWXX+|JTF4u=~LnP4k& z9(CUs;tVdqVomiKo6hbxhOVK3+n~ZTEkLkLCf?|%tdZF`D=3YnL`b1`LazGO_?V>i z>OvYarllHpWOIt8Xz+a{7<HxJwH{r6nbYgg?vIx~BNzYsrp?WLYu(1-!2iY2DNf3V z{`qb41;Pu>Kan%1Ian(l2!rYU6h>)hhTh8Q%B_wqmp6^MmotIeBT)pI{Rasp?JI?5 zd!8%%RN_5V8($m}@Xvu?0X~gRmBep7yC)Ly3mTiwcFh!`;aG7E$F@jmhoHK;{0*=Q z4NiiLv>ILL*Pry0fQ#}QEbY&ol8sBUZa)6*Px?2o$vm%=$+HtEg|ZEROJ9-hp=FZ9 zMVY(1CXB)J%NOg5okIcPo7<Jc1>b1p7fP_DXK4B94}D)v;wZpIyF`zr-#7d=C=O`) zDaxq1((?iMdr%;tV8ueDMxu2>{G*R|>`~WmDa_7c&r0XLJuVsIR3q^C<sM<tSZB1l znN^4IgYt_I0y2@*r>KHX;y*9~O+}>pmw!wXM^Pm3ByG8zcQHIDhYcs2SVoV|_ZIr2 zu$K~LbI{db(FUWAIV_!2w4a*wTh6Y#qhH;VQvS(Na_gMsk7o0;dhl5H$Z2+DX3sia z^UFHSUK~=GTlt+O9^BW_%h<PN#}EgKXEIL-BkW#K#F)D)(;eo_Lae1n3A8YxSX4qD zY%g|vBvn5lgw^Twj7U${dT?>T3l&ak`%k|S8#Yuw>CwxCD6|c|pc(){0Yx{7Uc;aU zd?!uzpi@lKH^|{}p4HC5+YFv6rJYW;U?q#e8gf+5El=wABeVE|5T9QKY`72&bdP`( z(u~fCc6&KBe5H7FPJH&`@CbZhbiut*a7^tky9v~YNFzwNyw2Xf4OQ7>Ewt<MZfxk! z;?@P4UxOD@gk5ALWXJndnP+;-wG-t@zyl?4La>(K`r+k7h4QxyH=dUzK^1aFT~RTx z$;n5uM^VSo2+MT^0DvQs-A-tSLFWUY8jMY<2gFLa(XTIg?S4rIF2(D-)NbLaw$e*q zdI|Rocz%*iV4rv1pFW%{SF;5Xb{sc@W%5r^yAi8!(kME=(t(V_;!@A89cvt4bO!No zZ`z5xzGrk3c?d@FVHk9{xH*B=&u?~Uk?v{I=v4-~zi66URjH}^WcYB!0@T(lGC~2@ z^L=DqCH#zVlHk>CDL7Z|2WMj@(5kzfAPOBllK2UzoCB5QRuIVhxrI#J3)okD5L~(c zjtVv*mVnLqe|3JMCV!YHOy!Puv^AkWHq>~nC8bPEEgPYct^Er|c+>i4pMz-kR?CIx zXE&4VMn`>mUw=Xyt;g?##Xdebq=7T!xZM79-qj7W?hA&bXV#n`NnNp=nI!)HF-lyH zI@ZfrP{yrHbB(C$qE>Aw3$w6tLlH86hBT(T`{Bo~0~h6^VI;~o;$rAqf^R`)$=2uS z8`}<pZx5y5(C49Lc^*QohbdG}&#Lmw`zJm*u>6_F0z}+|;#{QXQHzo63oOGp#-L)r z`2K-4V4Z4STv2d?Yx2XmaXG+RkDn7fF&kU^-8e5AkO_HU&UyVBORaj*tx+sv5$9gn zT2(w=XxoBur8GyrHv+<)??lmFr)qgD2*6s2Wivde^7?dd<us>gnZ4x+OPTuBQPvN) zEkRCOp9`a`&ylsh)0B-eIXnr#uN#SFqBVBCMJG1j&$d4{eA35DUG7oFy7)tvAl%CW z21}e80=p}Bmc0Ep53Ci>oJUVT@029Yky!cOkiVU$c|wK1l}$A7thR@T!_hkY^g=&p zIj2r+8mETk8lR)QyJnbal4wc9A`Jf=Q4J;1YSVpE_aG_f@_88b?A%_<_XSQTzkYLe zn)pLC&V$6m_xP(d4)dXM<@3#>5sFI42QLBzlIkG)-sUpWp!IL@2>kdy3nVPGTrj3~ ztArAjn3A%VpGaewzInUw0%>8G@-%)=r@7w#dgrd&%~8Ggolo|~<6m_s2vMoi`K3V+ z_AB8}lV5#IC2hbml`Ldrqfa<8@VU%nXs1HOWy8@lH8voho$ZO_SP_{eHy&H>i~Z>Q z7khjZ{5Qu|Z^LbGkR;lt%10l`znoEs=+Nj+9~-UO`ab{bg|eh3mGdS2ytk51$R=(x zA;(0=Gc<{@wFQ^H?>k?<?GohCTyr=(+0<t%NaZ&QenT{fRNRRQ-j2O?eHw&0N{8#` zTx+)wBNp{}_qlvzF22cg_8;X*rV*o{{Q2sTElWH75sE@vWjFVRRgVh6#TY$pG=Xty zbdW!>g-ibnQbw)}Nrc`E=|?zJlc?QWfYD*1!9jWl>gbuDYG1(>2a*U?FJoek9tn!X z(Nt3X7&mfg7CT@A3=skkK6zO5?BQz*<7yT`mlN&IdkT@L(;xMS<l@C^2jflnn~5xS z;FCDARL;u9m2MS;IrQeMyR4VXP&3(Q1W$VBqv(Y+h}K!1CuuoxudK;D0}g&`v~D)| zWxZ5alYTDp@C{A~!pUh@#%bQL_;cZPWP^)AN1wW<9+C5pb;x*aUoo_G^a8{9qvc%5 zqC?iKf&dWR^+)1gmpZlN1RvUgDzvZNjhJE-deUbmsfX>|)E1(=o;)#-=9X-(dwkPq z?roHc->~+B_IRRGoZA(ETAqNQJXNF_ylN67qs!EzXz~`Dll*xl<3huM4Gg%5-F!AP zExcz^oAzBwy&qO=`_xO(E{xu`|3DmiFIy?9COwAb`|--@kxvSFxyHDcm4b$PGv`7p zy?B83^q>By=*RBghN!bp($tN!amM1uM;{QIyQuZz(KzDf{h|`lt7!1K{usDbZ1xbE z_r=xsBo?%~H4!oSsC-un7e~#L=j?Lux<}vh<oey^Jq*HPa)$Y4D1l<k*3}5(`iQ+~ zSvD%yBK?|eJMZN7^9*?U`w(pmhlWv4GEA(>DWy|dxr@qTlBX$APXSi>0$_ob(yJyA zHL06|QPWB|giC?3IJ3yq2kBYsBaIy<Ss<FU<shSc@bS9yS@)p%iuDw^wp$*JR<z(j z-{USKg6r1!VP*1ZK@lyNjf}xc-p}4F?I<rBUlXfXOioT&tRYFY(a~~J$o^JZr+UI+ z$4i;!n!AL7y_ef>+ffOu)RaJ=@BviKfwlUGVW;t?^w_9Vw__*Wm}#H7K0+DeDz!ly zHpS!=#hVYJ7a&qJ=^f1@X#<McK0zebp9v%|Gl;C=@8=4wup4~RB^PR3Dq@*VVT6Q6 zV&k>#8ppkmNEjHZiqjV^K^j~34Bk+_Fr3jJ<idjPr%>-On1?6u+NpSml1t2!%D_xn zUD&K+=_{3BY}Y65g^ONR7;*DAm>5suD8h&}VwQ3Oibmt8M^)&A)PB$DE0vGfq>4Q( zQ+&Pdfa^;ryWtRE6+gefY7AZpH6g#<Pt3YM)z0}w*HKhW{X3Z^Dy8hHOWT(b<|XWJ zfm!#^UOH8b?OW2yf)w>SH_q;qy^-ubQlm$PR9r1rrr`scw>nygyhmCBFv`|fDUM7g zufZ`-!3$iZuQfu*Wd%^U%#Eh-(5Sed=Vb>mMwRvi#>@(9oHiv*@uDs!Q1*O}qBiW5 zC(7MWJLzBip)cWlrI34e@qxF^v_|5_iCGF4jU?hS<@Vcq76dGGQJ9?W587>BZl4?O zYC()a){DLdF$6WI@ZzO6av)W9{kd^HflgmfPrFh@EW+cbE3k&Yy(E0I%+|I~M_*Qm zkrhrDrh)kfXx%e-mX*0s&nr|oP<;8&9k84NM~-5YBU8;g{5l&5n#d~akaE12qq{hF zZXP?HVr2vb2MQXHa)WbZ<mI=|?q!%>9mZ-t(SpgKH>{CJ9JC3cS&-3nvs^o~c->@Z zyc0<KWnr$a>Dt=VVivwpY?icgLdGr;XBx%a&g*A|@hM{9#@4&=GKc8YIBOP~idG>s zIHS~j8Sm+70A+sU0i=~IozRjcV*Qp-v0uES_3V*yM<{VzkKdR2?H?R!k4nU82=0jU zxmI-X?Cr*85nmzgfyXZ<Qh3dxVqTR7?D_|VV?4cX{)S!HdL!rletXls=iSbH^9=q& zJ)*O(0yNmOdb##W<VMgU6o~`DvmZtGm{>ND;A15~VQbeF&{0qv9%563DFHmP+q0sT zx+f1T+p;^EfB6Lq``%Xh6H4+l1rc6-e$8LzkJ`hwF-7%q`3ce(K(i1~YN3&*7xXsr zFpEaNx@uK_w=L<^ENBo$1Xc&A)H{%+&9d2a2*a3Piy<4R55t>BGhP|w(DZtbd4BuW zB}K86oNt~>Gj9}6EgOn8B4fLS5I2|I!9lxP-{2jSCXUb%q4>xYlr?n!Ts`6w@c*0+ zf<flFU8iYa!y)^6`jh_-sjv!U6laa`VCRd?j8gwc?nj~@B|3o48)_(K12(B+UJ6w# zgc^)bi_R}*wUpYZG!f34`(uclh$V0Pia+Rvglq4_ibmEiL_NQk4s+zaYg9h?;D=7Z z4fk!jSI-|X{(4vD?|ZA?cW$DZPc!OJPfsno(R~+(At>b{cfx7R`u#;t7GjuCW@FMO zP=>@>aaTMz>3ytv0K8Qzzn5ELP149&JQ7ip8l$4zifjMwWZcczl<nvcxa{}l8WRI2 zS`$dnm5gE^O;`P~F;Rf={k)Ym_uW7?uze(@d||KnE!M&0Ccae^+pd3CK9C#>+I>{H zMV+#>;OqQJ$nQ8a^Q=iy+=z4zlv#r?-86vI3k`4CArn)-2=Mw?|15bem!`8YT_>5} zBV|#!uIG?IUJKtI(5pQn`(*sgX<8%KV(9d@f8qsMh&l{SYho5;Br23+$V~@Z<b{-? zalkVcQqxhsSk2INu=UFOl~W`sed?GX2#ToWEYN80`vK{7yK{I#5=le=U2W45KS`6o z3Ekm#c~JWTr<F-ogGeaQ)-~qlOdwaKG;05Y%IH{yW5M^j{4cv@u}2`ViKh(tj_P}j zJ{x=cpjKnIpI@nQe7e8d?X>9o{+0a^<HC7{(gXVAIzh4A-ua>0;1f>iOwZE<9E<jP z-%~T-kV=3R*t_e|(`)1Cnl`@2RZlv_T5i)=Q~F+90v(i<AV8Rc5`N@@`HJ+qsbNhh zP!fM#9j>>7e(=G4S4^%FOwaT7M8bD3k&9=uLg3d3+OMQMZ{-N$A2T)lB%>wL?j-ng zQ#Dt#B|ld!Rdaiz``bGtDlDkPGhOOA_T~7NDYxq6lgERu4?-)}liE+Ze5yNMo(?3H z_nNhNFLJzPAO=S7=KH&G4pW<IAv;U>o)3rZ=TGrgsD@dkRybj3@%cUWir0W&js3%S zMPl=sDv<mkg!coP7#zy0dtv!~D2Q`HFpm7ttAj1ZMcpGxic>FHO?p|Rkg*TG*SNFU z{AlsGcD%`Ahzd@N!A=vw=5J<y{Ln2C);-dh+tSJFkD04zyk2xWB|0ZNv(+M|ueHIY z$RwP#=^*|x8u*SQ&ov5el3K|xOaxgf&KKP9H?L$u_F7OwIBuUli**7yzS;da%7J16 zn-hudH%wz90!iEr;8uP8Mc%=6Bs`dfBpUcYrD6gt26-8j>GQX@>Ibt)(xhyq6*sec z3r|ynkq`VUl#K3g-MCH@P;w(Ia^my&u*}MzI605)Oij~=gs6Ksk?MN-YS@CWMc;Uv zw|5mk1$-jrXrKTVk4}ya-=w+qFCO_miUUE5gAcx1x`(!V-!p)#yrk0KBww8F14Bqh zDsRkxUtMDt2upFE!Z8hG@N!p&&mVWjwS*Ib{H4B*O1Vg()jaU#87OlPBnNQgyJ5~& zsrFz!3`P<<`u$5>wv*?HM1t<B9WY_tMi+dX{Cjv8_|<>he91rb=2a!nkXMzMxsdjM z@>7B2fJAlI%KgATw<ox)kFNzC5c(o>@HvA*r`}9B?_|45c9Md%CYu&X2pQg+UlnLE z)gNqveNC-*bh=O!hX=@NC{QIT1_;_?HI=zKvFaYH#4Au60_CY}1{=B9a8T<OhQhqq zEhw31eV5Gp>Ly9h4`uSEYwh&^%mkywMnH2FDhAL$NYvM!syFe)YK6AW?ct!DMFbhr zQ^>g$W$EZKSEIaY2zLY?^SuD)5m*6SZU%`SmVYOH9$1Eq(|aL8Cp%ReWp=SqkSSFD z3_TPtl@-N#jC-%fVSo)}N@cq1cghp!0yHU|NcjI(h7&EvN-Bxjm%M3w`@8dQYn%S8 zSQIXfaw0Xag+KW;0ufsB2V@8jfD!(t$bPB&0JC2>;Rp@D0rNOOyN|^I?js1(*Ue_% z%Hhb|Qq%Vi)lQ0N?4*+XDzPV3(SPcwwbu7HmUjeem|7YDQzbs1<d?&xm8Dh2UKX(@ z^>G4JRFFH|FK2OJdyfs^4@&s_%`pIDIij#13{oSGdXz#T5CH?A%vd6aTCOj|;z?8* zzd1xFo3G0p#8HN%gyB}I_t-`Pr15kM2<115N(I*pd*8;aEPfg0i-U}R&5-R4maUR) zK(>;p8(~m7c+HqrCHJ%STtmVkJi5?hkdONwAqPq@Du&sES7(xOa<*2kr-xE;N}t4> z9lg@X0?zh<9-G135kUB5EP?Vvc9dg-8d9W@5U9*2%^e_-K#8!AqZosXmOh5d!I>;1 zj=&s-bfwlN!e(?b#fH>}huu`B5JpJ4;Elfk8W{cHg&O$52$#<x5TDPB<7^PXlEJck z5JdPVm=w0HsAd9Ffmtg8-=#}uu+T&ne69z+WJhKyXExk*z-t+lhE~IbiWYEOk2gCd zt&vGAAj-%KV+p(2=qQVZGOh8#)lPX>gVT;-jY)q}CW{57^~}i*U`W^p?6QFRGg9bS z-s+=X$>*D#c+z0x>z5%UM{HP-a1asDMzp3Jq6|c11f9B{*Ss$dF9hA`zI#ccQC#t_ zS&Y6nS5p~IW%F*B&Y-tsuu#hSW^XUR5c)oy+ZBd$wO?Ayk<OD}_P18^T8>biT_#yd zM_GvvDDm8+lLT@=`SobBPo`Kjqa~l$K}SD7k--hInXsGs8lu&DL!(<lEIZG<?#7>Z z9lK&WeemZzm4Qz2tJ61o)(nuSb?7Y0vFgvuLwVmqgch#1>?IS3<_nIN$Hs}#JANHg zzA_4i_;VXgb8Fcou`Gf=SiWJ>7-F&teJxfkk(qwu9aZ+P1Q=y+_$rn|4o^>-fidGE zKng%0jG-bR;5CRqM-@mIf6QKsrILAB_jZKz(evI{cx<+hw~B)~u18=PRET8A%b*JW zt$1beq2Q6_$5+pUMgg8>NzMZRAe+vA1)%2kIjgpJYz#asQA`8nU;vINBBYdArBjP` zUGPpaN=7146a=?N1swxGF39S&K3=F0VR^oIAK=0s@ZDZH7U|Z?C3B?DeM0XHZIkfl zxGd{)2x7IjiPU0U&H2EW4gSaM_ka&#j%-Je1FohN*#rwB07TFZTz2v#$0)OwNJCKY zl41eW;VoMg7`ol4=lN{WD6phNy2FB-o#KU$Ek&PuTLlB7f$$Us4Jdjr<+V6Rkzc#M zjG6AWIe!?w@__&L>WkCnD5p#s1D)>I2<JBw0G7aQf3eKEI%@TeZl$`pIsNL-Hz0}v z+zoL4)#yWbt_Q{-Ylv^SDrO6cF<|4Y_;ECvQPhuaMg_Ya6j81IS^U;!2L~*)0QQFI z_k)^|&){f-yffBXApl@#UswWNu2Mpu!IKgcJUuc{Z23NoX7ma>lmG-X)L63`w58nh z)tG(#z~owk1Xz#IK>N@LmW_iEe(;Oyo(&5)U`fB24HIs7bQ3Jj9ZO-xza}ajDg}k# z@TGy^lKwmslpwzDkP`x~<cf$ZPhq6qm*6-EQG>lIPy$%JK418LK=;#I0@>QQ5|msy zx6r!J`>YNJb$Dq{SU_PG8$j!9!Dt4VC7}TzY5X@J8OXl~ke-|nz!(TVfAi5CmiUEr zVGfduv+bMXC3#ZgTcbQ%>rS7(Lfv?0?{XSu(Z!%zsG>OUw*17Un=H_n1_X}zK*7+! z*E~BCA`XCXQS`2co(d=#{KfziHHr~hm#g%Qb2$b#9xTIqOA#cjEBup~33TO8Z!cMZ zDacCgf)9!h44}uh{tK4tK&D+|o4~g7GrzY-@2!yqr-cx&nQ&Cwn+|qRQk7>g*QAtH zZ%Vbbr3VXr#ke{!x(;AcAUt_b;YiLBDZ~OyO#vG}p3c`s1OAC0gC_uxf;&F=Ae2Tf z7qG`V;_L29CD70V1;qq1{6-O^(AUrx7wo3mfL%UR{sReE=@@2Ec|H#lw*BLTJi4$T zEDOO|{x|Qo=Nj41Xea`s&p;e#@Mbqpw7l80QZ6PNq_6;vCpIc_&o&+y#;2)eggsc@ z!0ZF#hv`Q|8u1cSo=zGRiIbeS77Vi<3Q5#}21o$83SC*07eZLRc&R}QjK=nRc~l?w zJg4e5dBuzlx{V#3Cp9#n1mri3f$2p&g^)xPSa$Enfrl>cyTT|}AciT?t2CMHyL`Lj zyNrreylya*56xs#UwaTr9w;M^^(kk)<8jUc?=tc}CeQYsCM`@Y5y)jy1GnA0m(PS8 z01t}EJh8~GwS^=F2db{aOyh|qulIKB^k%9+ew7}Q5-4A$l2>1Al^SZzOG{%eekz^t z8as+(HHFK;XU4(7B<m0QEm9vk33&{3$S2}2v>1s4P5te$9z`-?e|UQc1rp~Trse^f z($uIjkC~ln($sQ))bYR2nuPxwtyus*jF6LL3cDSl34mHEK*cgv`R8FmANS47GT)h| zo@`G)_o9Gi-1_C?9_4<uPiY5E?)z5`wwDJE2OLAk9TH^#y>`4ZJA}D%VD%{XT!$Do z@0K$Fy*N7b;%Bn9Agn1FGfrrlJAqEdSjd)9{$jzkTsZ>`Yn+kBj7KM3_Y~Wm>mS^e zc`&dF*Y&hneBOPX0D9#tsNxxh=0j3zg6Q41FFu$^LvRaDIC3tZ^J8^)pQS^k)AtQ> zehpRDB%HO^)ef6IKQXAqGD4KaClejHb?K7yw5bOVqY8BkYCxGt510dCUBv_Ti6OwF zz6Zjvsa^QAE7ME4y8Dzo{B2F|S6}5L`yOrY%R_@5+XucFx!NCg<=lmI(9MlAW-6M} z(9NBcK4RC?DEwHQWmsK}eRNOJAwpHisXnLVrFKn(CRj&h5UR0|co8*Kt^12~%nZm# z1R6)_HoB&SW&<=@{Muojy<}&*gWUQfzb<p#M;K%z%kk@*eVnc;(bBY7CzyEv<JP16 zEi<;f<tA+55|~B-rHDX3TMxj@Lb?3LX0#UZ%D$aP?j@(3#6*S5oE8q0MNlrY)-W22 zx>aEy1qTc<)dysx_?-Q|H^%B|JPgEAbF@9aWpqn)QUFO9<GI(Uu2!biTM7nQ9xQuB zKPitME|NR!{?W%v!Z2}jb`5oi^OADA5fN<Ja~Gvq<3yB(Ef=uHz9uXpSzk~aa*aU0 zKi9aoF_|>CheYCz4rcvLsZy2D13ws_QNy_%ID#Q?J0fo8>Cp~drxb=On-c5)MYnTw z3o=zwD#Wj(*<!9POky1lQj!2F0%h~%Q4EE2l2SZq6Bk-Z3HYvUvCDzRjAuFw-rhw= zn`7GGlu6HDwCr9LJ?ux2mG0HNE{g-WR0e7>C;QP34~L27$zA}g>|O0V;LfCfVl4Ro zg~xv;Tr~>eF(m)zxJT;6d6oZX!z?3F?UUWXr}hFrL-boqO|hYdf-tZF2u!oFDdpU2 z<OE7f{?Q2z7?(bdG?}2_FgXNTPkkmSCYl6*?{etFPALaVwl$(_p88@Y|JEu7EM|0m zAl}Ii!26*z<cbh2f`9Tqw1~8stfmx=(>q#(<^QEc=nn0u==~!`+_?HyZ;s251Os4a zA5;qT`U(Ck01KdCDvVvfFiO$;=rIo<6xoS@)<-hkz0U307p|NyvCg17;P!mdYzi+a zk>0%F==zH~Ca1HA4X2Nok=b%;%$fbwK$pX2;m?C%K2;g@M(KV`r+G)a|6i8JP{r}} zC$Vggg*kDcV}#@U9!GVQ!CGTfrYhA=fR%IAqECes;f}46=mlSr@^~~TQmQX+^_p(R zJx42Y(*cNKGM@)w86PGNZaV<_-v(HThy$I0p=`?}5ET^tVT80!jaU7DF>w~HRW1?w z()E836Dt!CE2|E26fK*5-ga-gKY0>ww)tSCu=v?j_<d5mqU~Bb1@Ha;;@~_PtA_pK z;M{$Z0?FAjy-!kPGMR*T8*hE;vwV2#8w6H1Ez0Ujo$j5x4lY4FFR{WqveCZz6VBD? z28Z_kC+R|8%`MBGl#Sp7Si!8`TLoK%ScO_`HcZ4U6<?`Kr{ir(-FogNsOQVZ$@85D zE>wev00BaR9J17d>yn`|{T}esh-ni>>^~vk_TLi$7@<367B*fG^ZI|&vQ`+eJ<0Tz z!-UlP0j;WE^jNCroIQ!j5spOJ`Qoz{rFPK4Z?ur*wfa?3c7*?ji$!BqcCQ$B307C8 z%5tybllC6s#>ki82%ifJ%_ifDb01T7ZV-E+f?(sJQZ53CLf2IOZS!^dGLaz-@RkD@ zdjc1q{h+3si>(8I8kPiwvRt2Uh)N$7oH`M+Bm2YkY#Q#}{Nuw>9^SFx02=>4Y&h7< zi49@P9*Yl?v11tx^D<pww$@bq>gsZYz5!`RUc8+44&IywmcpEi31a!FGxlHb`T?nc z$?vw?$_=&ujb>?pbHx*Dl$nm23e;_s%Z?WN$Loku2;G53-<Xy(><2hpCOJ)5h>Lq} zj+;sfK(P6`(zqA>bp=N&KZtoep&fzUZ7dzbyN7NpwXii?9gedXXdTC}g;^>Aok^Eo zr*p0cfP2yFkAPx)b+&)-OE@4G7<Y>mkETYmb1(5DNcT;5mM6WIW(Cr34Tjj$&yuNM zXf{1f=jwwGAdIgt>h8NbKQsY4s+FFnwm$NJhT|^)_WUbseBaW2@ka2?w`iENVC6-M zyB62}B0oP#24bl|d>%Iimj^9oYUO(LWBKw)&&b64c)c&BE}!nKc9{<50wycu-(@Nj zMUR;hDvg5iBt(gxvwoKT;6s?Mu)U<;Z>b71mbXtiu+p9nJy~}<<vj&oir{`AUqMQz z{wenV<ycB70aN<z7<D~j6`09EA4WsaZ_kmF^a3EMU}$iAbA2#arVC+HdmEg$j7O}> zai+0fyF~D?StlR0?&)pJ=L9=#{Om;P{bXYs2TsIT)4|mKCy}_)i!gc${nZnLY~${8 z3QI|lf5`)~(vh<&g&J)G{11EEII_ed@ltFIQm5EX{Jae^r`V(Jb^9B&S1e-NmvWfm za|0G&6DV3qjzo+AlxS`Y)($M#mX)Cb0+7W}HgfBegH;&qcCgjPZw#pPxiXjCD`{Nb zY1vLLJA6u?X5OaMy=mT_x%Ip=9VO=iF?X0tt7GUe(20*=0U95Q1ydqglR#7m4PE|% zk6T@?(4nB5`blPu%*nNwB9M}awFl2gk?)Vl#Of#TfD@BEMj(G9zIcvC3b1~c?sBBF z(rB6Bv<>Q&&fS*@d-@~FWrz~`<-C)}6$K8bcgpsa3y>3|I0LLkv{+FniyazAiOVUp z%A>7UB@npaM(N#ZTx6wz<d24q70s#DY!W<scw}8)d@gXl^#}M6g8xcl2wFMYv~EA2 zpq6il)B?Jd3>j;W(8i_Da=H#!uOu4=;iK;Cvjl8x8|UX+E58+e^dUMtbkT@-;q~sp zwBKl>=gBrQ14X6#q3M^>p{+nbtoHGMp7oi+$y=rk!gBcjo73<;KBosu9U|1(YtUKz za*izR`Fz<_|GoT=K}0IaO?w4^f{kW)c(dNPIuaV5E7O>DPqE<}ja1SChX5gVs{otL z?fV5x&}#>Phi01F1?q@K%u)=*YRL~=!8Ml2BpG7=cbG2zJYCJ*YRG#=q0+L&X_#+) zv5j}W`jx0H4^m=C`=?2QW*D$9jWw}{g`US2p#PB?(xf+sF5jT%l7z$}BYy_AF@c?B z%{yv)21wv46r7fKx)1JnA)~Lqs7a*E1ov?|U-U%jdfw06`;`ifCn01ubI0m^C}IJm z@AIrL4aDNND<rX#IxJnmFAmWEUP}PgStTB}z|Ti4wdhD=@g_nk?#5{K&ol4_V0r$P zYX`y!sgQ625E@80^b$b^Dot;3_@J4$Wo%r7DBu4)1fIn<3ciQdPkJ_s`TcbzXo;PI zWCswMBqcwMYaJ)%jLHV89psY#`A2)rW)pFh%+6E(1$u4Q?WJ`{96||7goELcFubSe z;kHCdGiO_fufFlr-KUL<vu~IT%-zyo<uD+AfyylUK_lDvgRJGOZz;Y(H8|8sIsmv2 zLdpv{AgVNb{t%C6Q6O#F`Gv(%jt-vv4<$;d63aN@)rK{>V!MtM(DR^d#XsY%djWnS zbOmlXcb&fMUDy;<-WhrU<}me(1BxhQDH;k!=dSt6%$DIH*0>R&cuEE>Mt)@wt^tb< z@UnNkpLi!}x?b)Lq!w(;b5A$gDv?0f{s|6%zA-=TFgs4%8HH4Y3Wk7Ypf27ETZnC6 z35ZB{%^M1f76C04SuAdXB;ybATwW^@Z!MrUI_~^jK^vn~yo#e=vGW9<zvyXM;1Gj) z*URv4^@KhS?A6{GiUMK-c#1zOukn0rq5k3jXK5T+Fuf6)YLZG~$0J5nxa)i1|NJeb z;f#QD?|ow)Pz0$Ag(fYK9OK_jR?{5_C>{Li5M{PIo+!+4O+<nef6#%_3)Jmc838Xs zaA+5~2(Q*j73uCgB{B$o3%X5S`)^(kxX|(n%*vvf?<sN>xMY5>BL__TpK-f^RiGIp zNtwU>m(Y8VeYCXXN*ac~rd&K>6A0;t_;7wjUj)CBumz<%Xo0VY_PJoc*z{RP&x;vL z>g5ZAW;mAW-~749cxI&2Q$3Il{5v;IAcG9;9Uyk&Ie+XL$s9N2vp=T?#MnWb2e1CU zA3Gc}IHeko+&yZJ2zjNW2v-j!p^?M**D=yB9{o?rq}G4bb6e}6O9w(yb|U{)bSR<- za@^2QM;dpdCI4eDF|gIq4FB~eRDdNr@Ue2a;%k%s6TADvW^YBI*(ASnk_Bx)`^{l3 zC6K68Ja-<7-o*;Z!vwnhr`@kt)qDM+s=JRvp&e@S{B9+ZD1v|yT5Ra|dK3@uEt|}5 z(jTDQZ9E}~$54J9JnjaE>;Ys;l^W(0>Vex9r$hYsE@&AI{mwrE{7CJdq7Zu{3^>z* zV<a$A_QLBl<ChXN7ynV{d*1sPjY5WN#^-nZ=lb|<u;QM9!Dix9hJF+Z|8LyLK8m=J zD+;M>vFQMBVPbusTK2!&Nn+yPo?vbtd#&DsoG_M%q^`K61AS%wXT3^@3Dh<{FW)j1 zDFU)y7|>A{xPtw+>5hIN6pnJEZyart4V{oA<OTo61+Ehx82>6rRpZfit8UYJ`f_7? z0d)oN3&1#q_OO)R{6YmCu~fJabV$JJ-tyi_Nd>O_6AOz)acVw%PVt2P*^t>g=)wBG zjLG~JxVb&40x~HeP8OGtS_2IFZjs7Fp@EA%`#Z7}4-Y3>GV?_^M2fUdpE0|Sc!1-5 zuZ;qlb0G(;zg_SBHcn536gt|o(NF#NeF5tinwM4ESNfxygER1_bZ0^j6wdDTL+dDT zh2rljb0DIX+6k76aohw}$Ukj<o<#nMx_fh+zwgyYP)L33?%^U4zirNbhQQh7c_-LJ z4u~jVU(nb~%Ez++;}pX#>ivxWeoji})y?l#dPFV?<a>&^ECzno(?hoI&_w+8K?aI| z&y7>$O1;dIsk06U{w_1}JGqtk{Eoco>*ZAtgyc>ZrijIBoJZXaHT~aLorY%VPR^aN zbq3F?lSl&n-{ase1LeT>A1=N2SbGFCz03<s=8*m#cSybHf8Tg1fL;na988js&WQCp zAUJ6yb2r-m@!)wHGI~|5?JbJz2l(GaBym`u)>%Q89;_gsX8?UKD-k19xys8t87MHJ z!=Rt>p$}>qq`n8vRFF~zhf{v(GVO4a)ObT)$SAOuMq&8(S8&I^`)dw#+=^KM1vIcj zbs_Z^@T>&S-w{7}XcVtzGfx<urO9kJIPsMgx#jQU=s+|9dc3L>bn)9TV?14IflI9w zG%I3O(8+=%$?>;`N(zd!<F*o0b>vSl967q~jxr<?WDsz4q#GyZf8urle!kbD$oDii zSuOLer*9%R${<x3aJt@=+<Iwc(LOHIEiBSW?I5;FKrtM6eQ>t|-XUu;%E4L6D|J#d zOAi!*cmRiHy#?OC@y7y@w>?!#9`bUs<q<Z`p_*Nc{@>L|QV((#q1^70uxJukt7%ER zCA$hGqgE!y(%t_X3phm*i4|`~3{$R_ey}W}QwCa1<GfxcPYWreo^xAp;{*rzXM4#~ zm%l%UzV<JdKOOI#nI>dM0%)fcl7&CD!RYjfa6u2Jvyy1<Q;9JwVCwyEUJf9lXx=RQ zn`q_t*`XQDdoc^X!_)Ts*a1J*H#9-qHA5p6VmT+?13a_)5_cN?t?o|6=q5mrHKs}F zWup*E+yJW?%9KD;1<s4uRb%p*cpw?`%401|A@q;c&!;hh&;Pw`FQfv;iPOtwBA!SC ztB?6S0Q{2`|2+)AxS=Q&#;HpwChgdH!I}Ehc|V`T<ex^x8NGZ4iJ1W<9B6w9y#z>r zA!eJo3TeWOWKya53Q7LGTi!Yh=od&NBhX-z!K~xx`X6kBV(zG|qf<PIN7ApbNPRU4 zeMmtwkm!mS%QU53B6546!va{#s7-`kO!uj0;S~MR&O?=scgc*Q!(1A}2t=?@yZg}B zlR~McH`PSRz<;|6@5)d`_vF?2wtd2EHjDen%t8OXyRRQu5%^%gsgs(dZohmU2ps2% z9LWW}vT1(4^4(EWCe;zOSUFn#d%&W_=0S_c9{OpVdNK>p4t}9pv(ec(aCgjtWHj_L z-3d0MFXJ*_k;v3+Xkfqt#tGD+P%<#s^i$K6gUsH?*L?a0qf<@SslQ(Q{cA4{Sn}GR zzsUA5i;~HNfCxooT=WApKHyFR8l6V01b_0bbaYi|4>TY3#m|F+7jXVjgT8lV`rgp+ z?@p7=)Y>J1Qjz++PK^w3P$C1B(0J&^7!ZI6-N;v>Y+a?ghthLx8eJR?>Di@$KR_<< zP*G|%fG^T5h*Bw0)CJ}uFM*i{-DEt&9iAUl6q3SNxB4YlXE+ghF{#vdX=|OgjZcEF z4R1M~;tvCa^x*y?hkX-=Ek6I>8P!D2qe15II4a!!SuM?GJ4=0tHIP)X+;w*m1_khh zRIS=XVC4-o%xI-z3`JM_N^bBbd-Okl)Y1A_sH2hF1Vni-IUCQ89W1BS9G0qW(nkZo zI+WR*BMiZ>2OPGaFY?&8aM-2YcDb^{w*0oBfdH!+++Gggpz@Q~)qeLuSE?P9%mNZg zgmD?J$ML|sT%xltA<ZzRa1pZ@+|!wFo#|6C{kF!ML>(QQ3Gvtlboh0|b>wx_|F%ah zTOUH?d!;z>Nt-H8-%SwlF+TApVE&%hAMes9AhsOlkFZ*)WU?CD$GWogGjg?^vbML? zwncboYf67;ms4b@!L=&wyvLZ+Xo}9^BJRsd)icM{9|c%_MZ@$7%3btvaa5(Tag^n8 zarxHK&-LfYsRqsjqB4&w@cHc;@oWD`pLZ|muC<=A>vdmhJnc8)E&Z_b#&e3H=EL<H z-zmnE56c|vZ+UJT&gC4vuqG`Gqp-RomtE7<#o#BgCUGY5CJ82qPW|py2|38yJXpEh zYfS?7-#xjKaVt0X;Bx`r&QvG5M3KlwN9#iC-1U=~gJ5`+gYEj|YUxeRYDBjlo8f&$ zzdHQW&8K9n^}KHhIf&A*fR9S(VW<1@)vazxRy|?a7KY6)pI<G%ZhrAC`Yg8mJ8-~F zJ@_1;hfMZkJDHCvx@E+2z<obG@<_toy#oCpv$%S-y{oq8e8;1Ix;eNv<%0}M``aaH zywy5Uea=<VY4}Nm$%nxDduv<oL&{e0)>-CO8T;h8b2AyjF3~R8F4ZpGF5}&D>zxCi zvS%tTGoS4PB5oIMSB7@yWSlwGzs)c*Fxp3MFuVGs>KzQXkU`_W(vh^__~;&))&2h( zqc&&XtNW)or+B9Xr<s^HcZ&(cBl#Q$KzlS_hn=>T)pB%d`lCyy358T|r!%bY+{P0m zki`&icMexN)Y-W4jw8~LXHjRdW{GC0W*KMMC$F6lG9L0^x$*r0mU+-7?f@X~AV5<R zUu)))2ZU2ADZNJA{`tBlbEf)2A8F3@Awh?W=VPmZ8`^1+PGY-Av;4E-v+}d*v-*?X zr-&Izo)`0Ej_ZRaS;%+oJpj-?<eR<Qn_(4YPr%^H9wIl`e%9c=>iMRWM&*~K+v@|h zUwrF$9AZPQI}DDuy2C;2e|UIrZg<ijCS#~hobo@wQWTtA)D=93(?@t9>Hk1CA(xui zULs)So*J@0IytpeG;y2mv-igc7|9ex4_p<E5z+45liXr35NUNrE+M8wQyg_&;OkTw z`~;ifog3qQJ@>kG;qZzmPuN-Y_!I1K&vCb2xuEa^--U#3ix;PN$2~YWI03zP7LQ`8 zs#vPuwA~+Xl+SMXB4uLq)vCmL@aN_l+uSEa_)gO@CH3Yw)5pb%ZLtyXG&_y<f223p zCgw`*4RQHvjMIAEQrUf5xSW0~Tu3|sZN8hmKZfxDY}E?f%XXAaKSWgA04?1-Sf@5+ z(eE_Wh<mSvD0|&v?8%n9S<0MxIlO>tRkh6w8{G^tcp8oqCBGMSbk+JQa9`7<j?PhE z7<1Apne{{7_rBqXdrU%E5?wJ7R5<D;J_}PEyVkvD`0PGuKU<8r5g&o4iG#ngSOC8% zZCS64ymvTx4&#=E3!SHGo#Ml4>Ws4nk3F7+<%XSgY3?&gw%8~A#`C?IN$;;qe`TNj zv)T&lZyWv?Zevxh3wo^Xea7RU%w|MPORHTH6}H8xg6U}z$y6vx&91tg;Of0>pKPZy z!5XC=6R|ECM^(h@dHUuf^b+m40<iqC0{N12l(iD^RQA`1Y1x&mRz<PA?+XoItK-6} z2WAV7zR5NIPyo*s7j4gHcf)fG%ES5k_uvpv&+WIP!Z0HyLnK4J(Z_-8%IHG+mjMr( z#A1b_?Bn`V{<C)%z?Et&v%bAZxj<#^;<$7ji;7V#i9xrLZ~<6K;Bs2#T7pE}#U8h< z>q)btkXgc2lJUATCD5{Zvi{m?R`<1Gxb0+PZOa!TNyoS!o#9wxnfKsAY#zm1{QP3} zVGnhHy49B>?@02eA6Dv34U>Q<HB8m|g1cp(yMsMyFnqhO&evr{qU3SH_Hzstty-I9 z<`<e4KaVWxU;H`!JuN(^xA=6+F%#zkNP$($CfF9LHC4AW@!tF>6?JsJI<sFs=6m~H zVBIbYyW?<uxPU*-`($TkeUp|>HeQ4I9^3)S`8<nmlanI7ZjB0{XUx~fY{hnpOS=#h zmZdk$Vuz4ogg3ZsK3b?F%<WVCWQu>fzq33JkOV)1!s`#ExdikM2H6)1x#<=xnqFMd zP_VL2-oNQnE#}B9F^hemoG8gGli<&jA%~nE`JS4JS%@>C`953-;=w12*kkK1`LvJ4 zlckGS2H%~f;}X?g2Mg`p^kX}b#uJe*H=a34ZYBl~gfsRZGugJgIsf_9c0~7(_;!E( za<8$H8RP;&VAdtrAH!VL98PvJFHaj!05t*^(D36Z&>brQGN9XBvZmnn-A!3o*f9;w zJ?Uf8pp53tAN9)l%))T*G$<ER@=@9C)aE>o-ri``Id$)-scpd2Cvo9r0uR0z&n9iN zNz5hcA+D$b+5Yi-RQ_Bi)B}Pqrh^VC5efn403N`V=N+2>sEy_0pzNPkFJfp8^w@UU zwaN0F=(TGdYDi2RYetY+GJ6+v@-vz}xK_Px`jCh$FFqf-D;*RJ5651QM8YzjS>i1W zxs{IUP?i{t^N-Cla=x$G`N?@n2k4ImBFx%waP^WcOhBB@MhVnL9c}v>Y@1sv8Vr83 zIFE;2cfCQ+@+Yr<YKzULJ9i=QeEImmt+vb(<lB>}df0o?NVt>bf5)OZ1U&T4h{6v2 z>AY)y^Qm83iz;OC`xn0XN!P>cxdZmh-gpyqr?HiCgCLfc=+iJsFZ<c>vYjZx*FO`U zjrO0?E+i<@V*l2_qSssDniy_9Yj@7zlh7=eOXDzLk*SY42D8e-WCtU!+ZsK#Uw>aJ zJ)xXk1TS<$F-Yb!$v4v1?opl@*xgtNM8w`?5U-5{xYJ2H(44*O7T2z+t7JA5+P*!N zVwPyQ*IR6q>8jnZagbz!ezYAgA(PPi`TSe_GxR3Myh<*$xgN<ADc`-39C0QYxajf_ z&9V3f5>@AY1m}}MP>B6trs4J?3ypj-yj0YbMP3(OMauHg8nPjJ`3ABWkSCV*bu|qj zMb9BIu^N4o?fGGs!RQTMXtU>OgG^v@1OR4fO~xe0so7|8cXdvHosz!x{H9Wd&7-C_ zF&UpJD0p=AO0RrABARc3ro<>=_=oIAy$SZUdZr;qhtfeJt3@up$Isz9xR}gf<ZfGO z(Z6OxoF%`j8;{5tDTJW)X*pbX9OHt1rE|HSAZTnc$)hR%K1}hCVb{)O*F|%G&E>%+ zIU&yFyV&P>T*<@q+OXrus(S`bNG~UqjJqGB@JqU}E5Mzl^?HTsx$PqykE`pOH0Z$( znvLRdhBQ&Qx%6i8tlJ!YG%Ih)KIVX1d1%<hvcvyY;CMIAyop3QI#^SP+M#kld2dnd z@W&U|av6daxNJ;sKIK;jLv)pc;XN!wQg-NB!vv!X>*bmO^Oic9spMT^1EIavDbc&{ zE@r8<=h3;^th}583TsJfWk%djJ@X_3uW=0fwvA$yguEHz)%QwuBomS03^NMZWtBW{ z4yuwO*_Z0(`My-SB{BULMharAZ&^YgT(bb0CZ&fD6hGMN38fE{Q@D7jiP`PYhiHD6 zp4(n;&U06CS!d;&Ka~>eov%r+-Z!hcBFS@|cUhjdj+rNrXXl#_vS=3TZfw0cH2iu0 z6CQ=wk190`IDwbX#`7%(VXVc1-`=O#ezgxJQ;9JiKo_c~sGncD;7RS};hp;Er?rEE z(aR;svc$@p#h_tj=Cysg<(M8wpK-3_qSkX+XCW8sI&<QcFQ7@;i$2~^P;=}t_s4A{ zGRC&4smpA&ST$;YKXE6e54ky#aC`lDJ3)e3r}9POwWh<%mrf{f6>=)DeDJj&uhr*Y zN3<?c2_GspR|;b)6h>NYTDhP*P9C6fN-f~?zSKgIf){y?GOzLL(VFZU1=>Xuxw1vZ zJcnQ=$||d@;Y5>WDkUoa3N{{?rH?P;_*(l^Jj|AdStP}JGMNr)NKO;i+&`$^S~pwE zXK?#m)m7_yM`2KSz@cr4q+7t49N#+!jH}kD5vX3(*LM*=C5gYJy}8O%o&M?kTDL^$ zCij->Np#ZhJj-d#Ov%i0V`e61{XRC73olALG4Y7NIZpXX{rMqxFcPI}%+332cnr^} zP3#_`5;*8lt-8-UXB}C`W;|oY$rR}RS)$Hp*66qPdSgvuLErtu963B3@rzL0F>+tP z0yqe9T&||ba|==<U_-P;%4&+!Ny?9H4o+ob9a@Czu{k=IY3tjKqN1;HUS0<4;rFm- z<L1VDTDs}OluB4XIU+^8(I)xaRaL!+TK`-ANc<xsCX*m1quk-RgT$Q;S;M1~wHvJh zc({&7iUzQ?!OZp9w>AluFUrG)d={`vNdmLQMa{~U^I)~7y0x~4M;EtEQTF~k!uL-E z29d8M*Oq$fj?4DQQ-}!ckTaaz#=9Gh<9Ca+yWRDYj1!Nnqpx~C1OCH1O-j6J+vQ+b z9kVKBsKLds@6Ga0xzAlxCFe2?Or!lLGF=jOqH<gIa3LlKKUl5-Xu=Zc=L|(^sI)j> zs(KCJ8@+vx7N&>k%OIIh?vS+Q;bZwndGlyvY(t$#V0Y1`3N7NOUNmJu;2kI5O(nJA z+l$j->Syt>bt|ppC9O9*c2SF!{IBDq++%TKm*d!$S*_-5Y`W(^0MxHm=HehmkdfDY z-h~oZvFVH=>G^mX<+M|!?1yj_G8rlPpysI=e$X5FLv2I+XHf~3H7lYqQr7Pzoz^^} z$Wz^6oK}B!>)D<Q)%gX+btt$Rk;_QV&#iY%f7dr5>n)BK@G4MYdn4Z`=k=g7EG|CK z{yqpolgZU($Lbx|f4mcf*Y#7WFCHIve*OX%o)P?ZvmrEGrQVWNXYw)*{-Okc4D%PB zK`k2w=)9H%2Cbhqr|RSA-qDU{=g?NZ4QBc!gw)xxa*?>D!#Ekf_gycY$DR3l2zmnT zdL_()%VWFHqtry2${hXrBy>Ge@P!cd?MAJ9lykxstKEo@_xT><*d7}6`w`iwRImf9 zWS$TKin2mmoYUl3WE@Kf$1jVq$54BbD}@$68|^ZSUG2P+3>t1a&%53|B8k6szOF;y zTaK^zRqzss>74=rEbwa)R!&nGko71AG~Wz^WG}zbYUM<1c$z?kwvlS(q@o#G9nD%% z2y$Ny>WY6Kq31M&@f{%u)T;NKvDWJ(6c<koBy_<&B2oFHV!dXmx?2`Oq-v}<`~;8P zFb(`4#I&Jx7F-TTg~iI{WzQccd{Pz1Oux=xdMkv4se_r`ESK;}ceq}?$9q{{e-s}K zJzVyOkW|X%Pj%S&3j>$mv0sq{ez#k*alt77c!@&kB!;{NSz_4v`MTrg?-3(flW$_j zUG1HgE59o?mpa2YhCvf6jHH$@u?VjTWFL`EQ-#=Iv`3{NY_5k1KlXKb&_(m;S=`aI zSulMZi%l2NxUxK|GNW8_ZX$!Hw9WKI1((AL^=bkfT(n(ivISTWE6g$!VmH0m#Nghi zP9fI3X(`U<IfQ@z4^J1Hq}5G>T4XARCNKA<dp9`&SA70Z#x>`40<kW!$?Qa3V?LM9 zmD|^fnH)1zt06lnOUtNRj_+(O>8$#HQnH2%f#Pv4Ke%{IlaS^^l=X?o>8EZ>=)rjK zKrQ{CppK7Br^^Dc_OT0eI*eoWGH$}Os@KYsbK$&hI<bnCR=Lyd8#&zV1ztOuCG<^f zMG<f(<}6?SC{i9WqZpLUc0z|EmT6~`1uCR2)h`&wncJ|@NCFkqXvd37jM8#3&$Fsn zf^7P5I>>h}FAK!t$n#tdc#H=<_gc$oRf-GIFUgC!Y1I?}zEXXCI8)wtVsO6MlRm)t zHUPCy-}jpJdL+#N(9WY$v@>Icdg<T<k^^mEh);1>u=AOZch!TEd@UcpM-!r^!_>P$ zRb87$9O5<k`ql4&=d-1$ie<~amR4<9ybkgwxXdbpFkY-U49d6ynVNx7fMWVVlyMet zd<$}5?4~hy;lBo_E(7~kwdRCbuk#TghWs5kikD+m7Gsp^ntJ;qUm~Fd2|~$|(OMm@ zaBhCSQa%=`;k%<Dmj=lTVv2<PC(lGObE>S*nfnWS@JW?9XF-JfQki1aVV(${9EH{4 zhlJ`@#?PTCEJup1r1Q%~0V#Ns)Dutg0M^rC$4|q%(<KEB-)i;K(Yeg}yh7crrU8%O zRC}J?yUXbq+^AkNz`<RiC0bZw5$(;+O1pUWVZ(vpE~K6I4pGjZ%(v05l+}DQES~*E zcQ<EP@nS92uGCjr7-=jm55(PCVx2P&+J^+DedU{(2jkG=R10joU?B}qOl0PHa9iUS z=Pq{wJOIgJN83wrHR0eeR4Q#?v2k(fcsA!!2`Y;eo)K-RLP$Zy?b0X3K<I<xG#Q{5 zp7mHvQHBn=xQAmWLDz~wMd&(_Aj^zHF!N^PFvVCd-ddP2X<)QXIJmUJ)-1+Y`(T#; zbkDWyp8JrV$oyr-gw0Hy%m^S<qyc8<M(@q$CDr9y`8lqMt-OKgd~o!o^d?$xx$dSx zr_Or5*YYpPuCEVC0xL`Kf@NGPWk*NP2U1>dxPJ5x?j;|YX4upG)8#MY7{A?xHvb-N zG+A&U=BCcrXWM1<M(QGWK(6mr5C1g#u<2UEOn4)`MK;E!W}8#aFj+?P)%4!1rP4h( zv~c5o7FloiVn^Xb$(dWTofw&W(3_VqpRzjavH}3IViKdiTr0}z|7q;X<Du@_zPlnt zNZchPVyt1t7P3`jn4ua>w#a&qwX(}nq*B%yS;j6#W^7rrQ^F9+sA-a=ER($~S;q37 zao^ALzR%}<|9IywpO3Sj>vyi}e6R1hF7I}6+i8zAHH{&C=+2as*5Jxb+2_yI9+V$R z_KKV9+$X?4H20Z}ywF-GD5mf`1R{N`s@7ew=o!hvx%(askQa>nQ#zPaJVa9_mo){? z>~7v(j&0*&b~fADAD|M&OuIr^ytKiA`7-8Plded{d@0`?Zn=rgJ3$qa=zTvVyt*=% zK(?nL#SyWh9*qR@PCyP<$OwcdnDNX00cIad7ov+WT~a&h?^RqN;x^6U(FKbl=^YHa zRicmEoL3+weDk|MG2CJPkUCL4(C3nr)p+;2O;=|sWhv`T@%ryA=hf*n4!2*wvduSQ z?F4G0U!$i9o*`@LvO0qx-p1GUp5Wq}0X5b?r^Hg=6`DhOE6){9&Gzz=zvgMm+F{sl z>HyO33WVnw$%Z_)?tWE15Q(+LAOEY(YDk&3jGOcP9NtjLOE|=GT1hmW0Ccjt+9$z> zCQ5ATQp#x&t8LAl7ohy9grEFG%)rLRz%KfjwvMo0XOf8ToAT+tuY`8((5)RYkrKmX zsk8G+)!M*zqnU7GhpTSR*38d5?$_0ud+FSh3<Sb=P7a&&CiC3w*MF6JP*!@%c92ho z8{1TMYcN*XZa2y;)O`G<vpn%DCc!}0ofJ(YfJk?3=6G-y@pnv!ynvIwo+4);MdLuA z)(>|o)9f?E%EX@fzW|DC`ZNTaqlkZr#J2SLCw-aZ_BfN5GB*9$v)!2sS6nU5CYx&< zp%E_n#-2tXkA4+zD((x5^~58FHx6i#oYX?fMR1|yX?;I{F35s@CuNg0?;8V)<K%uJ zzWOcJ+1#Y*oA}pgg3o%^hF{IZDk-!xx8*X-q}DUfOkqG~xVUMt*=O=#I$*Y5GLOz8 zi%)0HE5bK$x+QN}8=ht+{eVkn0vVCGOHfBHh28B-8j<MVvBCZErPe#!v0`P4*WcPF zeD*S#v9Cmdm4!tVPZ$a16{eUutRoz6MP5MXa9%EV4*q)=DpVGhDWz)?BD?A`{o!(? z_Q&W9-lnXky8@A5EP0xe5js%40h$S3`8}<4%pu_UQ25xr(c3O+;Xl4gw519UR9>jR z&5NUepm#lr(TN{)F50o9N0z|}XWdU8ub%zts3nh8zY<K#X=)h|x?o40{%BdIu}Go% z0_Cfwmrej-Mf+^=DO=IdS9-ZUg2l!)uOXjdT3}bYOEJ8{>M2M668bIdDz&I@NitlL zM@Ns4agvn&8t{ts=OE?HV49Lnfetnl9NgDjF1u>-REi1+H+_ga)TH&QYw%~TXRs<c zELNVj11thq^_N=XmBzA^xq<yhPWe`#gDracRD(txIo=##;YrOwQZ|!T`(m3`p8x7- zWpg$ivA3Oi`(u}jfZ(R^HNS=;Nma~&^}X<|j5Ddh3?H10X<2xB|ELdz&b{Bvp=D>L zwN19=#iNK3nu!|R-&GUA`<df&w@^Xx6gy2K5azWlAZJ-t1VZHY&F0s&uLw{w<*>)4 zhjE-&K|tK%wa1nfcB2#D9u;?fDs=MV6Lk*UKDdGopq4s^#-+lfml+c{)5Gsh{sn9R ziN7eyl9)I@9RFJhE;Tk4sk=*Tvks7*u#W9V=SZ-oD@asbtX&a$cN_N+Hk3}ocDih2 zal9QoU%s7h^ee5wvBhaCG1=2|_giD|`?ZWlh#5tkAxYP(aXiD2VXRp_W*m=EM1Cj% zR)r8{<;xru#)@-ragl6VH~~paddCVwE}cTTYC;j#HDMkCQot0u2bK?nBppvB0F`<o z@??@$8UmM!uM|z1j&i^|am6)zhIhI8k1#xwr`m@&+n$~fhN@??V(=Q9+RI5UNn1zf zc34Tb5V#vzwQa7apvXk@FFH0O%Inej?W$R{FI4ThLA>8P>{&98ZF9!2k}nWAUiC42 zKyzrG)?k{c#qimbW#Y^*_AkoSZo}PBB(-r<&GAZPg(MDx?L02LOIuyXvlyJYP7$XG zZu>=~o+QUTUMa>QbBg1fQW_0w;57xVj}L?n?I3U`AZ59fwf?GJLxI9MJY<n^a_*c! z;<lcbt<r3$>kW$ISrMNpcS8^`&6K;xDfJRoT_aHOEXuXPxo4D6DGY{j0QsH(*Vy<> zn4VG7QQg}hSNx@5e}kW{JP}aj2=(zF&=Ohk4kI;r2gDq&rtQdlwB=H>$qgSfSz0AD z4I=$(*@cR5jvn#s-qFwN4IucWMq#kjr<lRfGoAdg%jBiV(lDO}N4%5#qf|)4w@9)g z4X@z|$(#qhpO%YIMXn8&fZcfAqpk9feAL5#o;(DF&{UA4e_5V{ir??vZWIt91Gp^c zl9GId-A;{U!NW~=RvhNb?~4X^ZD=E&fBf!mK&EN(ms<YHdUJ(m+<^2e!~B~wNZ(}M z=zyR3R92QOXZsD`GGRK<Dmv)0ck$5BONUsl_o*VIEW*7w-LCxR>r#%6kf!u>D@Pw1 z$mVw0mh_g+&eA{ZcXwoa84rQ#eHp~%{5BmWq$b~@AB}Rvw@<KE_DeBjsx~>YF~k?Z zzRb6(owZjsgapx5n4A2-=r@AWu-kuPFlSC$mLlFwL@3Bo^3~iE<WS`TiP`cl9_HCY z`GV?D&Nh$5bUP)O?F~x40+0K=T>_ioXv;06@i_w70Cp!)ivLntK{|o4&|+6&vt9b} zohZoz2l8xe3xICeAI&|ZpDjGEfIZxy3?c@kJi`oFry5IJmruR6OaB>PeXZWUwlHNh z2#NEW5qEb|3+pmkvJym*?WDSWxhfUCu%0-N4C;F;2<%<)@ou@M^JV^-cWpQV7Jv!; z$)R!wF&HiP=NoWFv#=kCJ)Ni9mI}F=18XWqpvvc)n+6)jqv0=W(=(&o{2V7j`?Y%q zosWm6V|40bV-C#*D*GG*TC{qev0S<~)vj@k)s|quvy%`PT=5%QJR}|~mP%zhNxtz^ zVeV85WmkXNTP+~|OK3t0iU3#BP{-g`=ABa-m62jiTL~Vh3BO*_qJVYW!Tq+&pyp{I zAVqRs={|?wDsRYAdZa1&u6S)NA5k;{C9d&pG74i=Ae?;<^Q3s+SuYMyApv*56F(*1 zdmDkW`F@M}?G;`@;JVBRYi55Eq)$#MPrIK4Yt<5C;dPk8H~eH)>9s4~t9C)JtT!z7 zjwWcKO9gZ(T_iozLfM}@5Z@ulJV>J4@RvqlT9#+J_{;C!C`-p02K00I-@V-D?8F94 zq@j`X3L5Wk;`6Kv(*1l96vpgGr!tTd-O{5~n9YTTMInl~3>GMua=lzxO#<1PP#BPS ztPuhkm{lgzA5~}tg?7YbzavPK=*W7VZLMp0QnVt&S|RR_D~g5EbTjdw6s2sqFV-uN zImM@7iVuK3&CDri|C!b?#uimNmkLR&MVNLbZG5OiVTEN{K7^}YMkIT6BP4u+r?Wg3 zRdt4NQSR~UhzD_GzMyoyKx*ES+vs!*_98U)n@b_kEF*F_A-i(g`J`&2n83GW*y`Ny z(+vc(KhgsyJc#(XkV+VcuTo)Clk#<@Dn~au2dfh94Kvgod?6uW8WcMGAzTd+L2eDK zL}P7#xqy3!@1SGq0UT!Oqzd%HHUA$f0oa>Mrvenyii-J&7+xi*r%S<W61;3&b>{V! zcSl3%PcT*$zK05e{?%#N`nQ7t(Ia{D9V`c<2;g9@Mf7*rCBL!0BWakRkS3m3`_7cT zYAOM9*P+A7+9A((#gn0=PMAORdxu=pbSZBrtBaxKbR2h7pN3A<*R&}JDm2M7(xHI% zS?Vqt65t@-fA+D)uZq5SXqR5DG}tBBvuRe?QLHdj;H-kfm54M+zIVUdKO3g#FwF16 zF5b~L5qOsvePncp_a*GrEhMU(&Jjfre25G%TIOY}<SKK6mhWUHASu?~E%RW#xT{xK zRW8F=f$bUP4n&CeWpT`dq~vJYl1qyC&y>|v7uGKMG$(J<etELLvvo}(dzA?ej`hP@ zOpnZA=X{9$a&X5dh9{H22Gfp1A2_AlF)0A)H;27TQwiX?Gzx!^ITsUPk%K!+DR0wk zXRi{Q2D>O<X{ks{tL1x(mF>0B!qI5vl<&kRAaRPTlSL*xD8f!;^Vma=V;7{BWR@8n zeN8R^3Z7Y-9P3tPo^E3B8Uzzi0-W4g&9-;3k&*)YPd(u2F7*<E(b9U%YQwZ-dyasD z3CF?J<`9`oj>E{<6=7u>o#LTC_1JT-m<N(?m;=0xeyS2YNS*?IE*9OaL{Ex%)zkQZ z2t0N;3&y4c#z{2t7y0g#_NB_xxbr+{unYAX#`Lq?QHhe$4z7WMSGT$LOwbO!{Ah5{ ztYS|h3m-V+AKZ^*Q*T421+S4__vomw0nc>Ov%?Czk7Rtj_tUdr_G7w#7p8+-K8ST+ z3}B;$1L_4<kQ0%>dEaeRVCCo6y+pJqBXAWIL{*O|g5Gt-*@u)5&3-EJc{aUg)&LUF zgz4>2gL4nzRsQo<-Aka*X_?25F}&ERKEDXztI>(!FgC#Fn=p^QT2{|Vaj$fBOl1~w zdz^~lWx_hn8BcnzV>lCdE_7MEOe5LEiagZOj0j>*gvb2Spz<MM&44=**%j3@FZLiL zslOp43ukw#&w>Dmc+#rKT)e@fw<*4WP4B)MHhgXml(PQ^l<IR%1t{s|?b#jxyorNm zSw38BN8)~do9dnUeOO>pb&_ai{?_Fh@exmb9zd2zcLJP!hm#Co;N`5-sXb^-0^np1 zN~~+^trB}OqTCDRplnyzb0eO+7s{h*&0qZZDwtor4$=?-hYuKa^#qt2c%N7}Gi<H% z=G=zw_S5Cq`+NWgoZY<5VS^OOPYR$e44;62!jIkVfGJ`y7$Qi}EkAC?gkN=|c)D9; zc5JYul0aZ~4uV8mihB*OPQ1eK#+}k6o^q!RIA?@0+Lt?8nSkKRkYr~)Cu;f6vx6zS zgz5dD;dZt<FlO(TZ4192gCCqTj8qnLp2z{GcLmRdm%zVato4cPoSI*<&NS8+IYAAU z52mGQkZ)h>eB4@d?t`(Ey7~DHKZxqM$05qsQ1A6!%)Hd<2z7O5;@-{-pi4{#?0NV< zpGG5b$bqkQrMgDGsL`t(t)Teb`l8VjXn(k}q;&L#F=(3yHxZ5Dt??X6F4DX7Z*2GG z|HO6|9&%gPc(m>9<~yt_0lp3bVGJe|K04R->_y0=j4$<~6r05GuWoc*kDnHIuv>yg z=%()`Kl4!GNuMafRHUheXUV?j{WqkZ@t=_T!ktFyF5Rz!Ii3WC$A>B6b6@LFDxnic z(eEXm7z^bdF46Gd{KRu1NU~0T9Qa`{3j=SE>BRY=+P`IXlt+a?cIkL0P|AWZ`<KI_ z^~irZEI>BFPC2GTHlLY6;1ZIP34l_PB7Iu+V_u~UKFNXeJI@7mg}NOht>m$WQ^T|Z z;9((Ne8g2?*9OMLvhnnVGE&w3Q}NX!Csln}UB#qnve?F+6N91;#1!gA5CwtUs(<Bx zH%CZ+CPiXN<tos2PgCTHDTPgQhX+00uAU-1k?S}wnuNm6%F5pkgj9;-L5$V<TfZ)B zK4a1%62hZ{DNdEUt$zTLhXbJ%$w%#R&H8g*nJtt(_q_xaW#e6GIYVnm*`)7mJEedc zIjuZO1TsWIMc>aPL7jg=*MyJiBQ<p>SJ5f0;KrL6mm(Cs&n>h&_#H1O&3DeBPnnkQ zWoT}DY7r}4e(ddPpn+`@fX<~Zu{$T*C@ejXB+E(o!pp;oTlZE<Pr?O>>jk;o%u`C^ zT@SBZYI(X?@&p+^bV6M0LEL6(e8Ax17fF2Yz_{(;!y|%<%niIU799j;0noya)pu(V z_p^U|VhEA|l7T{(eD>xPIx1s`ogI64lk%~ITN!#oAwFQ%ZTrN1OC~7&>H=_9tBQDy z6xXl)xXH;jNnOF(9wfTouyyBz9PRGM-nOe4I_+m2r5QuL{Euh7ojFpLz^(vbmHzof zNauD0@kZrCs4mFmZp=J?&3_Ds3ozaCkxn5!=UOInEjng(OXF`J>mWrQ<R;jugW4=( z5~FyCpd}qMT~R;;8T~qPUVgPTFPWnNfL<`t<blIgs)_A4L24w^M-elw-5lD;RQa=e zeIL+kRzqrlr$JZ2qoQj8X2tfL;yvc1A|ro6#4<Y{4ol#YXgKmKcDx~W+`41C^2}x8 za6<qpf~f*|_OW&=(=xO}t$OVg?X<o$ra@ovJu9&^el`ca#GhU_a3V*H?}&`5&ol1~ z?Rmkn>e%t?;^QGBTR}6OBH@S@=Blxr<~y8^8K5<Im*LMlSGawCl?WXJjhJ^@y&-&- zb&t6(d!eq#p{#LMF#b)*ctz>$#wSkaP4Va9;Qsfhm?;{%senzBf5zGPm|ZYj>;0G> zlTCvzd04%JLzF7K-d8VmT%4o-PZ6z7wFTZ1-fNUseB^)gaSWL9emcS)zg6x?=TZp+ zgp1Mb7B#jPHQigyiBD!#5Vo3rMKV=ON{;WJUXjAy79WRqn5QweTy^zf+MTf?g&+k+ z+*RgOx<nO`dOv@4ijZC^H1a6!cP5!t2KoV{lekApg8tv6q?o-a$p6EVQVDO{_v~|R z{2oi{in}p{KKivjUExF+oIm~LHQQAaJk;KR)fmQ=e?KxcKYhrT`*XXV_;@ke!CNJK zC&Yal3I@W`Wvht1dAeoEn^vLEgh1VBUm62nplh|)%VlV*(m=92R@13!0+DV>E#jj- zzvxrf=jSFFYOx$;PUn$n8v3CtA1(vKq-XjJ7qh*keF)S6^`NDEt2(!Wld2)9M39iG z!~V0ZrA@8bGS>`nL{(3{<hxN%JrVf)b3#b?l2-Sc^e8E$g|Ij*E1+=k(Gl~-;*iS# zwi64z#1wg5<$IWJJ?-7^9IKy(yh-#9Z4qCHky*{=FwvKyN_1LlBewrU7Y{Uxh0`24 z2d<77Hgj*>m|!F>!kZN~Mi8TgaM&p)o38Z)rY{a?84iN<@r}t8yW-LipWQ9jRiI8R z{il|RHmi8z%A1m6Sef9%-k+@V-Xt+{LyVr*lbDIE?x5u5vvk|OmJn{jVrTZm-Q-2< z=75bIXCY>jx^rNNj&UM7rJtH>Et-@uSf<Zz@B948m4C;aM6wnMG#vg)d@4h8eEiXV z44}S)D&fIse#=G_|K@Cp!Nn`@CFuHn@fnipc4}N{9+^7o@vt?+KGJl^LG1rnBxY|s zL-zQ*gtF#MBhQ_`DnFj}9Q^Tt7~082bSW7#Zb59eRL>Bt@#hJERC0BAFd#_=`aOQ8 z9!^fanP9-Gj}0JQAaM!y>KDV~F2-GsGmbNjL&c%vtmAf*A!kdLZ)%vf8U4o!GW$He zdmr;eG+*zY@2vID4nen-)DIR0&n@PyI&!od_AJZ0Yg(W3nt<_Zp;o&<+>!kT_d|VW z_Z!cNCbn0Gn^EJfb4t^<j{D8`$eO(rSiIgbfv1k3^>Nqap5IxGI6E^Fr71UlEs$0? zL*!?CG?&#uMU8Az`BCGHvMuXVDfCIdrQo3KM!T9bL%8|w-;+KQ%M(76%g#FALm10; zhfJ?CBqe+*S}H~>b_wI%rT@KUI<Y62GdTQbDj}p5FrW*6FOHUJUvIh5RCg;EuN+iy za%J!||ETtjVFrT{<HBN_n34Tk_=`2&eP9CqX#=+`MMw3?GMiu_6tUcz9+2=``Ej*+ z8JFp{ivQ?lG9X0q8DjdE0Bx!=xGG4AH0k$@7$6Y)zgIY%-k14lBVl<@4iorOA-6;` zhfOlh7ilx*lvY7j$rpfx<@VOvyC`UxUIb#L5b2$9=8=y$ElgL!uSxu#e-89TE^oc~ zi*>GfbCPO_`EsY#3&0OB2LZ^c>N`Fbp{e*?A9OX5_&pPCM4tfPb&yR~3Y9!N8M+ik zi}Nt8ksV6uPwdC_KkHA~PS{TLAFc?m$Y!paFM(;c-7|~?J_P2EodtmO%-?C2RHmf} p{>NgE-}{4Q-@X4wp{=~Z-F;h55Us2a?>;c=!Szipm0qxq_%EcAi=hAj literal 0 HcmV?d00001 diff --git a/doc/guides/prog_guide/img/feature_arc-2.png b/doc/guides/prog_guide/img/feature_arc-2.png new file mode 100644 index 0000000000000000000000000000000000000000..604a67229b29a9c8ace59d28a7324e02c2bc4a89 GIT binary patch literal 155806 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�!fv6yo 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ΐMNRyBlZP4r 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 VhL3#7$M&;o^tFw(Dm5IV{|}tHa(Vy& literal 0 HcmV?d00001 diff --git a/doc/guides/prog_guide/img/feature_arc-3.png b/doc/guides/prog_guide/img/feature_arc-3.png new file mode 100644 index 0000000000000000000000000000000000000000..3991e0aed2933bfa01e9ffad654f4c40a639bc53 GIT binary patch literal 143697 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 JynBzl{|6wHR9pZ6 literal 0 HcmV?d00001 -- 2.43.0 ^ permalink raw reply [flat|nested] 46+ messages in thread
* [PATCH v5 0/5] add feature arc in rte_graph 2024-10-10 13:31 ` [PATCH v4 " Nitin Saxena ` (4 preceding siblings ...) 2024-10-10 13:31 ` [PATCH v4 5/5] docs: add programming guide for feature arc Nitin Saxena @ 2024-10-14 14:33 ` Nitin Saxena 2024-10-14 14:33 ` [PATCH v5 1/5] graph: add feature arc support Nitin Saxena ` (4 more replies) 5 siblings, 5 replies; 46+ messages in thread From: Nitin Saxena @ 2024-10-14 14:33 UTC (permalink / raw) To: Jerin Jacob, Kiran Kumar K, Nithin Dabilpuram, Zhirun Yan, Robin Jarry, Christophe Fontaine Cc: dev, Nitin Saxena Feature arc represents an ordered list of features/protocols at a given networking layer. It is a high level abstraction to connect various rte_graph nodes, as feature nodes, and allow packets steering across these nodes in a generic manner. Features (or feature nodes) are nodes which handles partial or complete handling of a protocol in fast path. Like ipv4-rewrite node, which adds rewrite data to an outgoing IPv4 packet. However in above example, outgoing interface(say "eth0") may have outbound IPsec policy enabled, hence packets must be steered from ipv4-rewrite node to ipsec-outbound-policy node for outbound IPsec policy lookup. On the other hand, packets routed to another interface (eth1) will not be sent to ipsec-outbound-policy node as IPsec feature is disabled on eth1. Feature-arc allows rte_graph applications to manage such constraints easily Feature arc abstraction allows rte_graph based application to 1. Seamlessly steer packets across feature nodes based on whether feature is enabled or disabled on an interface. Features enabled on one interface may not be enabled on another interface with in a same feature arc. 2. Allow enabling/disabling of features on an interface at runtime, so that if a feature is disabled, packets associated with that interface won't be steered to corresponding feature node. 3. Provides mechanism to hook custom/user-defined nodes to a feature node and allow packet steering from feature node to custom node without changing former's fast path function 4. Allow expressing features in a particular sequential order so that packets are steered in an ordered way across nodes in fast path. For eg: if IPsec and IPv4 features are enabled on an ingress interface, packets must be sent to IPsec inbound policy node first and then to ipv4 lookup node. This patch series adds feature arc library in rte_graph and also adds "ipv4-output" feature arc handling in "ipv4-rewrite" node. Changes in v2: - Added unit tests for feature arc - Fixed issues found in testing - Added new public APIs rte_graph_feature_arc_feature_to_node(), rte_graph_feature_arc_feature_to_name(), rte_graph_feature_arc_num_features() - Added programming guide for feature arc - Added release notes for feature arc Changes in v3: - rte_graph_feature_arc_t typedef from uint64_t to uintptr_t to fix compilation on 32-bit machine - Updated images in .png format - Added ABI change section in release notes - Fixed DPDK CI failures Changes in v4: - Fixed clang build compilations - Captured `feat_arc_proc` function in ABI change section of release notes Changes in v5: - Updated images in .svg format Nitin Saxena (5): graph: add feature arc support graph: add feature arc option in graph create graph: add IPv4 output feature arc test/graph_feature_arc: add functional tests docs: add programming guide for feature arc app/test/meson.build | 1 + app/test/test_graph_feature_arc.c | 1410 +++++++++++++++++++ doc/guides/prog_guide/graph_lib.rst | 288 ++++ doc/guides/prog_guide/img/feature_arc-1.svg | 277 ++++ doc/guides/prog_guide/img/feature_arc-2.svg | 511 +++++++ doc/guides/prog_guide/img/feature_arc-3.svg | 318 +++++ doc/guides/rel_notes/release_24_11.rst | 17 + lib/graph/graph.c | 1 + lib/graph/graph_feature_arc.c | 1236 ++++++++++++++++ lib/graph/graph_populate.c | 7 +- lib/graph/graph_private.h | 3 + lib/graph/meson.build | 2 + lib/graph/node.c | 2 + lib/graph/rte_graph.h | 3 + lib/graph/rte_graph_feature_arc.h | 431 ++++++ lib/graph/rte_graph_feature_arc_worker.h | 679 +++++++++ lib/graph/version.map | 20 + lib/node/ip4_rewrite.c | 476 +++++-- lib/node/ip4_rewrite_priv.h | 15 +- lib/node/node_private.h | 20 +- lib/node/rte_node_ip4_api.h | 3 + 21 files changed, 5622 insertions(+), 98 deletions(-) create mode 100644 app/test/test_graph_feature_arc.c create mode 100644 doc/guides/prog_guide/img/feature_arc-1.svg create mode 100644 doc/guides/prog_guide/img/feature_arc-2.svg create mode 100644 doc/guides/prog_guide/img/feature_arc-3.svg create mode 100644 lib/graph/graph_feature_arc.c create mode 100644 lib/graph/rte_graph_feature_arc.h create mode 100644 lib/graph/rte_graph_feature_arc_worker.h -- 2.43.0 ^ permalink raw reply [flat|nested] 46+ messages in thread
* [PATCH v5 1/5] graph: add feature arc support 2024-10-14 14:33 ` [PATCH v5 0/5] add feature arc in rte_graph Nitin Saxena @ 2024-10-14 14:33 ` Nitin Saxena 2024-10-14 14:33 ` [PATCH v5 2/5] graph: add feature arc option in graph create Nitin Saxena ` (3 subsequent siblings) 4 siblings, 0 replies; 46+ messages in thread From: Nitin Saxena @ 2024-10-14 14:33 UTC (permalink / raw) To: Jerin Jacob, Kiran Kumar K, Nithin Dabilpuram, Zhirun Yan, Robin Jarry, Christophe Fontaine Cc: dev, Nitin Saxena add feature arc to allow dynamic steering of packets across graph nodes based on protocol features enabled on incoming or outgoing interface Signed-off-by: Nitin Saxena <nsaxena@marvell.com> --- doc/guides/rel_notes/release_24_11.rst | 10 + lib/graph/graph_feature_arc.c | 1236 ++++++++++++++++++++++ lib/graph/meson.build | 2 + lib/graph/rte_graph_feature_arc.h | 431 ++++++++ lib/graph/rte_graph_feature_arc_worker.h | 679 ++++++++++++ lib/graph/version.map | 20 + 6 files changed, 2378 insertions(+) create mode 100644 lib/graph/graph_feature_arc.c create mode 100644 lib/graph/rte_graph_feature_arc.h create mode 100644 lib/graph/rte_graph_feature_arc_worker.h diff --git a/doc/guides/rel_notes/release_24_11.rst b/doc/guides/rel_notes/release_24_11.rst index a563812d02..1299de886a 100644 --- a/doc/guides/rel_notes/release_24_11.rst +++ b/doc/guides/rel_notes/release_24_11.rst @@ -162,6 +162,16 @@ New Features * Added independent enqueue feature. +* **Added feature arc abstraction in graph library.** + + Feature arc abstraction helps ``rte_graph`` based applications to steer + packets across different node path(s) based on the features (or protocols) + enabled on interfaces. Different feature node paths can be enabled/disabled + at runtime on some or on all interfaces. This abstraction also help + applications to hook their ``custom nodes`` in standard DPDK node paths + without any code changes in the later. + + * Added ``ip4-output`` feature arc processing in ``ip4_rewrite`` node. Removed Items ------------- diff --git a/lib/graph/graph_feature_arc.c b/lib/graph/graph_feature_arc.c new file mode 100644 index 0000000000..0f8633c317 --- /dev/null +++ b/lib/graph/graph_feature_arc.c @@ -0,0 +1,1236 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(C) 2024 Marvell International Ltd. + */ + +#include "graph_private.h" +#include <rte_graph_feature_arc_worker.h> +#include <rte_malloc.h> + +#define ARC_PASSIVE_LIST(list) (list ^ 0x1) + +#define rte_graph_uint_cast(x) ((unsigned int)x) +#define feat_dbg graph_dbg + +static rte_graph_feature_arc_main_t *__rte_graph_feature_arc_main; + +/* Make sure fast path cache line is compact */ +_Static_assert((offsetof(struct rte_graph_feature_arc, slow_path_variables) + - offsetof(struct rte_graph_feature_arc, fast_path_variables)) + <= RTE_CACHE_LINE_SIZE, + "Fast path feature arc variables exceed cache line size"); + +#define connect_graph_nodes(node1, node2, edge, arc_name) \ + __connect_graph_nodes(node1, node2, edge, arc_name, __LINE__) + +#define FEAT_COND_ERR(cond, fmt, ...) \ + do { \ + if (cond) \ + graph_err(fmt, ##__VA_ARGS__); \ + } while (0) + +/* + * lookup feature name and get control path node_list as well as feature index + * at which it is inserted + */ +static int +feature_lookup(struct rte_graph_feature_arc *arc, const char *feat_name, + struct rte_graph_feature_node_list **ffinfo, uint32_t *slot) +{ + struct rte_graph_feature_node_list *finfo = NULL; + const char *name; + uint32_t fi = 0; + + if (!feat_name) + return -1; + + if (slot) + *slot = UINT32_MAX; + + STAILQ_FOREACH(finfo, &arc->all_features, next_feature) { + RTE_VERIFY(finfo->feature_arc == arc); + name = rte_node_id_to_name(finfo->feature_node->id); + if (!strncmp(name, feat_name, strlen(name))) { + if (ffinfo) + *ffinfo = finfo; + if (slot) + *slot = fi; + return 0; + } + fi++; + } + return -1; +} + +/* Lookup used only during rte_graph_feature_add() */ +static int +feature_add_lookup(struct rte_graph_feature_arc *arc, const char *feat_name, + struct rte_graph_feature_node_list **ffinfo, uint32_t *slot) +{ + struct rte_graph_feature_node_list *finfo = NULL; + const char *name; + uint32_t fi = 0; + + if (!feat_name) + return -1; + + if (slot) + *slot = 0; + + STAILQ_FOREACH(finfo, &arc->all_features, next_feature) { + RTE_VERIFY(finfo->feature_arc == arc); + name = rte_node_id_to_name(finfo->feature_node->id); + if (!strncmp(name, feat_name, strlen(name))) { + if (ffinfo) + *ffinfo = finfo; + if (slot) + *slot = fi; + return 0; + } + /* Update slot where new feature can be added */ + if (slot) + *slot = fi; + fi++; + } + + return -1; +} + +/* Get control path node info from provided input feature_index */ +static int +feature_arc_node_info_lookup(struct rte_graph_feature_arc *arc, uint32_t feature_index, + struct rte_graph_feature_node_list **ppfinfo, + const int do_sanity_check) +{ + struct rte_graph_feature_node_list *finfo = NULL; + uint32_t index = 0; + + if (!ppfinfo) + return -1; + + *ppfinfo = NULL; + STAILQ_FOREACH(finfo, &arc->all_features, next_feature) { + /* Check sanity */ + if (do_sanity_check) + if (finfo->node_index != index) + RTE_VERIFY(0); + if (index == feature_index) { + *ppfinfo = finfo; + return 0; + } + index++; + } + return -1; +} + +/* prepare feature arc after addition of all features */ +static void +prepare_feature_arc_before_first_enable(struct rte_graph_feature_arc *arc) +{ + struct rte_graph_feature_node_list *finfo = NULL; + uint32_t index = 0; + + rte_atomic_store_explicit(&arc->active_feature_list, 0, + rte_memory_order_relaxed); + + STAILQ_FOREACH(finfo, &arc->all_features, next_feature) { + finfo->node_index = index; + feat_dbg("\t%s prepare: %s added to list at index: %u", arc->feature_arc_name, + finfo->feature_node->name, index); + index++; + } +} + +/* feature arc lookup in array */ +static int +feature_arc_lookup(rte_graph_feature_arc_t _arc) +{ + struct rte_graph_feature_arc *arc = rte_graph_feature_arc_get(_arc); + rte_graph_feature_arc_main_t *dm = __rte_graph_feature_arc_main; + uint32_t iter; + + if (!__rte_graph_feature_arc_main) + return -1; + + for (iter = 0; iter < dm->max_feature_arcs; iter++) { + if (dm->feature_arcs[iter] == RTE_GRAPH_FEATURE_ARC_INITIALIZER) + continue; + + if (arc == (rte_graph_feature_arc_get(dm->feature_arcs[iter]))) + return 0; + } + return -1; +} + +/* Check valid values for known fields in arc to make sure arc is sane */ +static int check_feature_arc_sanity(rte_graph_feature_arc_t _arc, int iter) +{ +#ifdef FEATURE_ARC_DEBUG + struct rte_graph_feature_arc *arc = rte_graph_feature_arc_get(_arc); + + RTE_VERIFY(arc->feature_arc_main == __rte_graph_feature_arc_main); + RTE_VERIFY(arc->feature_arc_index == iter); + + RTE_VERIFY(arc->feature_list[0]->indexed_by_features = arc->features[0]); + RTE_VERIFY(arc->feature_list[1]->indexed_by_features = arc->features[1]); + + RTE_VERIFY(rte_atomic_load_explicit(&arc->active_feature_list, + rte_memory_order_relaxed) < 2); +#else + RTE_SET_USED(_arc); + RTE_SET_USED(iter); +#endif + return 0; +} + +/* Perform sanity on all arc if any corruption occurred */ +static int do_sanity_all_arcs(void) +{ + rte_graph_feature_arc_main_t *dm = __rte_graph_feature_arc_main; + uint32_t iter; + + if (!dm) + return -1; + + for (iter = 0; iter < dm->max_feature_arcs; iter++) { + if (dm->feature_arcs[iter] == RTE_GRAPH_FEATURE_ARC_INITIALIZER) + continue; + + if (check_feature_arc_sanity(dm->feature_arcs[iter], iter)) + return -1; + } + return 0; +} + +/* get existing edge from parent_node -> child_node */ +static int +get_existing_edge(const char *arc_name, struct rte_node_register *parent_node, + struct rte_node_register *child_node, rte_edge_t *_edge) +{ + char **next_edges = NULL; + uint32_t i, count = 0; + + RTE_SET_USED(arc_name); + + count = rte_node_edge_get(parent_node->id, NULL); + + if (!count) + return -1; + + next_edges = malloc(count); + + if (!next_edges) + return -1; + + count = rte_node_edge_get(parent_node->id, next_edges); + for (i = 0; i < count; i++) { + if (strstr(child_node->name, next_edges[i])) { + if (_edge) + *_edge = (rte_edge_t)i; + + free(next_edges); + return 0; + } + } + free(next_edges); + + return -1; +} + +/* create or retrieve already existing edge from parent_node -> child_node */ +static int +__connect_graph_nodes(struct rte_node_register *parent_node, struct rte_node_register *child_node, + rte_edge_t *_edge, char *arc_name, int lineno) +{ + const char *next_node = NULL; + rte_edge_t edge; + + if (!get_existing_edge(arc_name, parent_node, child_node, &edge)) { + feat_dbg("\t%s/%d: %s[%u]: \"%s\", edge reused", arc_name, lineno, + parent_node->name, edge, child_node->name); + + if (_edge) + *_edge = edge; + + return 0; + } + + /* Node to be added */ + next_node = child_node->name; + + edge = rte_node_edge_update(parent_node->id, RTE_EDGE_ID_INVALID, &next_node, 1); + + if (edge == RTE_EDGE_ID_INVALID) { + graph_err("edge invalid"); + return -1; + } + edge = rte_node_edge_count(parent_node->id) - 1; + + feat_dbg("\t%s/%d: %s[%u]: \"%s\", new edge added", arc_name, lineno, parent_node->name, + edge, child_node->name); + + if (_edge) + *_edge = edge; + + return 0; +} + +/* feature arc initialization */ +static int +feature_arc_main_init(rte_graph_feature_arc_main_t **pfl, uint32_t max_feature_arcs) +{ + rte_graph_feature_arc_main_t *pm = NULL; + uint32_t i; + size_t sz; + + if (!pfl) + return -1; + + sz = sizeof(rte_graph_feature_arc_main_t) + + (sizeof(pm->feature_arcs[0]) * max_feature_arcs); + + pm = rte_malloc("rte_graph_feature_arc_main", sz, 0); + if (!pm) + return -1; + + memset(pm, 0, sz); + + for (i = 0; i < max_feature_arcs; i++) + pm->feature_arcs[i] = RTE_GRAPH_FEATURE_ARC_INITIALIZER; + + pm->max_feature_arcs = max_feature_arcs; + + *pfl = pm; + + return 0; +} + +/* feature arc initialization, public API */ +int +rte_graph_feature_arc_init(int max_feature_arcs) +{ + if (!max_feature_arcs) + return -1; + + if (__rte_graph_feature_arc_main) + return -1; + + return feature_arc_main_init(&__rte_graph_feature_arc_main, max_feature_arcs); +} + +/* reset feature list before switching to passive list */ +static void +feature_arc_list_reset(struct rte_graph_feature_arc *arc, uint32_t list_index) +{ + rte_graph_feature_data_t *fdata = NULL; + rte_graph_feature_list_t *list = NULL; + struct rte_graph_feature *feat = NULL; + uint32_t i, j; + + list = arc->feature_list[list_index]; + feat = arc->features[list_index]; + + /*Initialize variables*/ + memset(feat, 0, arc->feature_size * arc->max_features); + memset(list, 0, arc->feature_list_size); + + /* Initialize feature and feature_data */ + for (i = 0; i < arc->max_features; i++) { + feat = __rte_graph_feature_get(arc, i, list_index); + feat->this_feature_index = i; + + for (j = 0; j < arc->max_indexes; j++) { + fdata = rte_graph_feature_data_get(arc, feat, j); + fdata->next_enabled_feature = RTE_GRAPH_FEATURE_INVALID; + fdata->next_edge = UINT16_MAX; + fdata->user_data = UINT32_MAX; + } + } + + for (i = 0; i < arc->max_indexes; i++) + list->first_enabled_feature_by_index[i] = RTE_GRAPH_FEATURE_INVALID; +} + +static int +feature_arc_list_init(struct rte_graph_feature_arc *arc, const char *flist_name, + rte_graph_feature_list_t **pplist, + struct rte_graph_feature **ppfeature, uint32_t list_index) +{ + char fname[2 * RTE_GRAPH_FEATURE_ARC_NAMELEN]; + size_t list_size, feat_size, fdata_size; + rte_graph_feature_list_t *list = NULL; + struct rte_graph_feature *feat = NULL; + + list_size = sizeof(struct rte_graph_feature_list) + + (sizeof(list->first_enabled_feature_by_index[0]) * arc->max_indexes); + + list_size = RTE_ALIGN_CEIL(list_size, RTE_CACHE_LINE_SIZE); + + list = rte_malloc(flist_name, list_size, RTE_CACHE_LINE_SIZE); + if (!list) + return -ENOMEM; + + memset(list, 0, list_size); + fdata_size = arc->max_indexes * sizeof(rte_graph_feature_data_t); + + /* Let one feature and its associated data per index capture complete + * cache lines + */ + feat_size = RTE_ALIGN_CEIL(sizeof(struct rte_graph_feature) + fdata_size, + RTE_CACHE_LINE_SIZE); + + snprintf(fname, sizeof(fname), "%s-%s", arc->feature_arc_name, "feat"); + + feat = rte_malloc(fname, feat_size * arc->max_features, RTE_CACHE_LINE_SIZE); + if (!feat) { + rte_free(list); + return -ENOMEM; + } + arc->feature_size = feat_size; + arc->feature_data_size = fdata_size; + arc->feature_list_size = list_size; + + /* Initialize list */ + list->indexed_by_features = feat; + *pplist = list; + *ppfeature = feat; + + feature_arc_list_reset(arc, list_index); + + return 0; +} + +/* free resources allocated in feature_arc_list_init() */ +static void +feature_arc_list_destroy(struct rte_graph_feature_arc *arc, int list_index) +{ + rte_graph_feature_list_t *list = NULL; + + list = arc->feature_list[list_index]; + + rte_free(list->indexed_by_features); + + arc->features[list_index] = NULL; + + rte_free(list); + + arc->feature_list[list_index] = NULL; +} + +int +rte_graph_feature_arc_create(const char *feature_arc_name, int max_features, int max_indexes, + struct rte_node_register *start_node, rte_graph_feature_arc_t *_arc) +{ + char name[2 * RTE_GRAPH_FEATURE_ARC_NAMELEN]; + struct rte_graph_feature_data *gfd = NULL; + rte_graph_feature_arc_main_t *dfm = NULL; + struct rte_graph_feature_arc *arc = NULL; + struct rte_graph_feature *df = NULL; + uint32_t iter, j, arc_index; + size_t sz; + + if (!_arc) + SET_ERR_JMP(EINVAL, err, "%s: Invalid _arc", feature_arc_name); + + if (max_features < 2) + SET_ERR_JMP(EINVAL, err, "%s: max_features must be greater than 1", + feature_arc_name); + + if (!start_node) + SET_ERR_JMP(EINVAL, err, "%s: start_node cannot be NULL", + feature_arc_name); + + if (!feature_arc_name) + SET_ERR_JMP(EINVAL, err, "%s: feature_arc name cannot be NULL", + feature_arc_name); + + if (max_features > RTE_GRAPH_FEATURE_MAX_PER_ARC) + SET_ERR_JMP(EAGAIN, err, "%s: number of features cannot be greater than 64", + feature_arc_name); + + /* + * Application hasn't called rte_graph_feature_arc_init(). Initialize with + * default values + */ + if (!__rte_graph_feature_arc_main) { + if (rte_graph_feature_arc_init((int)RTE_GRAPH_FEATURE_ARC_MAX) < 0) { + graph_err("rte_graph_feature_arc_init() failed"); + return -1; + } + } + + /* If name is not unique */ + if (!rte_graph_feature_arc_lookup_by_name(feature_arc_name, NULL)) + SET_ERR_JMP(EINVAL, err, "%s: feature arc name already exists", + feature_arc_name); + + dfm = __rte_graph_feature_arc_main; + + /* threshold check */ + if (dfm->num_feature_arcs > (dfm->max_feature_arcs - 1)) + SET_ERR_JMP(EAGAIN, err, "%s: max number (%u) of feature arcs reached", + feature_arc_name, dfm->max_feature_arcs); + + /* Find the free slot for feature arc */ + for (iter = 0; iter < dfm->max_feature_arcs; iter++) { + if (dfm->feature_arcs[iter] == RTE_GRAPH_FEATURE_ARC_INITIALIZER) + break; + } + arc_index = iter; + + if (arc_index >= dfm->max_feature_arcs) { + graph_err("No free slot found for num_feature_arc"); + return -1; + } + + /* This should not happen */ + RTE_VERIFY(dfm->feature_arcs[arc_index] == RTE_GRAPH_FEATURE_ARC_INITIALIZER); + + /* size of feature arc + feature_bit_mask_by_index */ + sz = RTE_ALIGN_CEIL(sizeof(*arc) + (sizeof(uint64_t) * max_indexes), RTE_CACHE_LINE_SIZE); + + arc = rte_malloc(feature_arc_name, sz, RTE_CACHE_LINE_SIZE); + + if (!arc) { + graph_err("malloc failed for feature_arc_create()"); + return -1; + } + + memset(arc, 0, sz); + + /* Initialize rte_graph port group fixed variables */ + STAILQ_INIT(&arc->all_features); + strncpy(arc->feature_arc_name, feature_arc_name, RTE_GRAPH_FEATURE_ARC_NAMELEN - 1); + arc->feature_arc_main = (void *)dfm; + arc->start_node = start_node; + arc->max_features = max_features; + arc->max_indexes = max_indexes; + arc->feature_arc_index = arc_index; + + snprintf(name, sizeof(name), "%s-%s", feature_arc_name, "flist0"); + + if (feature_arc_list_init(arc, name, &arc->feature_list[0], &arc->features[0], 0) < 0) { + rte_free(arc); + graph_err("feature_arc_list_init(0) failed"); + return -1; + } + snprintf(name, sizeof(name), "%s-%s", feature_arc_name, "flist1"); + + if (feature_arc_list_init(arc, name, &arc->feature_list[1], &arc->features[1], 1) < 0) { + feature_arc_list_destroy(arc, 0); + rte_free(arc); + graph_err("feature_arc_list_init(1) failed"); + return -1; + } + + for (iter = 0; iter < arc->max_features; iter++) { + df = rte_graph_feature_get(arc, iter); + for (j = 0; j < arc->max_indexes; j++) { + gfd = rte_graph_feature_data_get(arc, df, j); + gfd->next_enabled_feature = RTE_GRAPH_FEATURE_INVALID; + } + } + dfm->feature_arcs[arc->feature_arc_index] = (rte_graph_feature_arc_t)arc; + dfm->num_feature_arcs++; + + if (_arc) + *_arc = (rte_graph_feature_arc_t)arc; + + do_sanity_all_arcs(); + + feat_dbg("Feature arc %s[%p] created with max_features: %u and indexes: %u", + feature_arc_name, (void *)arc, max_features, max_indexes); + return 0; + +err: + return -rte_errno; +} + +int +rte_graph_feature_add(rte_graph_feature_arc_t _arc, struct rte_node_register *feature_node, + const char *_runs_after, const char *runs_before) +{ + struct rte_graph_feature_node_list *after_finfo = NULL, *before_finfo = NULL; + struct rte_graph_feature_arc *arc = rte_graph_feature_arc_get(_arc); + struct rte_graph_feature_node_list *temp = NULL, *finfo = NULL; + char feature_name[3*RTE_GRAPH_FEATURE_ARC_NAMELEN]; + const char *runs_after = NULL; + uint32_t num_feature = 0; + uint32_t slot, add_flag; + rte_edge_t edge = -1; + + /* sanity */ + if (arc->feature_arc_main != __rte_graph_feature_arc_main) { + graph_err("feature arc not created: 0x%016" PRIx64, (uint64_t)_arc); + return -1; + } + + if (feature_arc_lookup(_arc)) { + graph_err("invalid feature arc: 0x%016" PRIx64, (uint64_t)_arc); + return -1; + } + + if (arc->runtime_enabled_features) { + graph_err("adding features after enabling any one of them is not supported"); + return -1; + } + + if ((_runs_after != NULL) && (runs_before != NULL) && + (_runs_after == runs_before)) { + graph_err("runs_after and runs_before are same '%s:%s]", _runs_after, + runs_before); + return -1; + } + + if (!feature_node) { + graph_err("feature_node: %p invalid", feature_node); + return -1; + } + + arc = rte_graph_feature_arc_get(_arc); + + if (feature_node->id == RTE_NODE_ID_INVALID) { + graph_err("Invalid node: %s", feature_node->name); + return -1; + } + + if (!feature_add_lookup(arc, feature_node->name, &finfo, &slot)) { + graph_err("%s feature already added", feature_node->name); + return -1; + } + + if (slot >= arc->max_features) { + graph_err("%s: Max features %u added to feature arc", + arc->feature_arc_name, slot); + return -1; + } + + if (strstr(feature_node->name, arc->start_node->name)) { + graph_err("Feature %s cannot point to itself: %s", feature_node->name, + arc->start_node->name); + return -1; + } + + feat_dbg("%s: adding feature node: %s at feature index: %u", arc->feature_arc_name, + feature_node->name, slot); + + if (connect_graph_nodes(arc->start_node, feature_node, &edge, arc->feature_arc_name)) { + graph_err("unable to connect %s -> %s", arc->start_node->name, feature_node->name); + return -1; + } + + snprintf(feature_name, sizeof(feature_name), "%s-%s-finfo", + arc->feature_arc_name, feature_node->name); + + finfo = rte_malloc(feature_name, sizeof(*finfo), 0); + if (!finfo) { + graph_err("%s/%s: rte_malloc failed", arc->feature_arc_name, feature_node->name); + return -1; + } + + memset(finfo, 0, sizeof(*finfo)); + + finfo->feature_arc = (void *)arc; + finfo->feature_node = feature_node; + finfo->edge_to_this_feature = edge; + arc->runtime_enabled_features = 0; + + /* + * if no constraints given and provided feature is not the first feature, + * explicitly set "runs_after" as last_feature. Handles the case: + * + * add(f1, NULL, NULL); + * add(f2, NULL, NULL); + */ + num_feature = rte_graph_feature_arc_num_features(_arc); + if (!_runs_after && !runs_before && num_feature) + runs_after = rte_graph_feature_arc_feature_to_name(_arc, num_feature - 1); + else + runs_after = _runs_after; + + /* Check for before and after constraints */ + if (runs_before) { + /* runs_before sanity */ + if (feature_lookup(arc, runs_before, &before_finfo, NULL)) + SET_ERR_JMP(EINVAL, finfo_free, + "Invalid before feature name: %s", runs_before); + + if (!before_finfo) + SET_ERR_JMP(EINVAL, finfo_free, + "runs_before %s does not exist", runs_before); + + /* + * Starting from 0 to runs_before, continue connecting edges + */ + add_flag = 1; + STAILQ_FOREACH(temp, &arc->all_features, next_feature) { + if (!add_flag) + /* Nodes after seeing "runs_before", finfo connects to temp*/ + connect_graph_nodes(finfo->feature_node, temp->feature_node, + NULL, arc->feature_arc_name); + /* + * As soon as we see runs_before. stop adding edges + */ + if (!strncmp(temp->feature_node->name, runs_before, + RTE_GRAPH_NAMESIZE)) { + if (!connect_graph_nodes(finfo->feature_node, temp->feature_node, + &edge, arc->feature_arc_name)) + add_flag = 0; + } + + if (add_flag) + /* Nodes before seeing "run_before" are connected to finfo */ + connect_graph_nodes(temp->feature_node, finfo->feature_node, NULL, + arc->feature_arc_name); + } + } + + if (runs_after) { + if (feature_lookup(arc, runs_after, &after_finfo, NULL)) + SET_ERR_JMP(EINVAL, finfo_free, + "Invalid after feature_name %s", runs_after); + + if (!after_finfo) + SET_ERR_JMP(EINVAL, finfo_free, + "runs_after %s does not exist", runs_after); + + /* Starting from runs_after to end continue connecting edges */ + add_flag = 0; + STAILQ_FOREACH(temp, &arc->all_features, next_feature) { + if (add_flag) + /* We have already seen runs_after now */ + /* Add all features as next node to current feature*/ + connect_graph_nodes(finfo->feature_node, temp->feature_node, NULL, + arc->feature_arc_name); + else + /* Connect initial nodes to newly added node*/ + connect_graph_nodes(temp->feature_node, finfo->feature_node, NULL, + arc->feature_arc_name); + + /* as soon as we see runs_after. start adding edges + * from next iteration + */ + if (!strncmp(temp->feature_node->name, runs_after, RTE_GRAPH_NAMESIZE)) + add_flag = 1; + } + + /* add feature next to runs_after */ + STAILQ_INSERT_AFTER(&arc->all_features, after_finfo, finfo, next_feature); + } else { + if (before_finfo) { + /* add finfo before "before_finfo" element in the list */ + after_finfo = NULL; + STAILQ_FOREACH(temp, &arc->all_features, next_feature) { + if (before_finfo == temp) { + if (after_finfo) + STAILQ_INSERT_AFTER(&arc->all_features, after_finfo, + finfo, next_feature); + else + STAILQ_INSERT_HEAD(&arc->all_features, finfo, + next_feature); + + return 0; + } + after_finfo = temp; + } + } else { + /* Very first feature just needs to be added to list */ + STAILQ_INSERT_TAIL(&arc->all_features, finfo, next_feature); + } + } + + return 0; + +finfo_free: + rte_free(finfo); + + return -1; +} + +int +rte_graph_feature_lookup(rte_graph_feature_arc_t _arc, const char *feature_name, + rte_graph_feature_t *feat) +{ + struct rte_graph_feature_arc *arc = rte_graph_feature_arc_get(_arc); + struct rte_graph_feature_node_list *finfo = NULL; + uint32_t slot; + + if (!feature_lookup(arc, feature_name, &finfo, &slot)) { + *feat = (rte_graph_feature_t) slot; + return 0; + } + + return -1; +} + +int +rte_graph_feature_validate(rte_graph_feature_arc_t _arc, uint32_t index, const char *feature_name, + int is_enable_disable, bool emit_logs) +{ + struct rte_graph_feature_arc *arc = rte_graph_feature_arc_get(_arc); + struct rte_graph_feature_node_list *finfo = NULL; + rte_graph_feature_rt_list_t active_list; + struct rte_graph_feature *gf = NULL; + uint32_t slot; + + /* validate _arc */ + if (arc->feature_arc_main != __rte_graph_feature_arc_main) { + FEAT_COND_ERR(emit_logs, "invalid feature arc: 0x%016" PRIx64, (uint64_t)_arc); + return -EINVAL; + } + + /* validate index */ + if (index >= arc->max_indexes) { + FEAT_COND_ERR(emit_logs, "%s: Invalid provided index: %u >= %u configured", + arc->feature_arc_name, index, arc->max_indexes); + return -1; + } + + /* validate feature_name is already added or not */ + if (feature_lookup(arc, feature_name, &finfo, &slot)) { + FEAT_COND_ERR(emit_logs, "%s: No feature %s added", + arc->feature_arc_name, feature_name); + return -EINVAL; + } + + if (!finfo) { + FEAT_COND_ERR(emit_logs, "%s: No feature: %s found", + arc->feature_arc_name, feature_name); + return -EINVAL; + } + + /* slot should be in valid range */ + if (slot >= arc->max_features) { + FEAT_COND_ERR(emit_logs, "%s/%s: Invalid free slot %u(max=%u) for feature", + arc->feature_arc_name, feature_name, slot, arc->max_features); + return -EINVAL; + } + + /* slot should be in range of 0 - 63 */ + if (slot > (RTE_GRAPH_FEATURE_MAX_PER_ARC - 1)) { + FEAT_COND_ERR(emit_logs, "%s/%s: Invalid slot: %u", arc->feature_arc_name, + feature_name, slot); + return -EINVAL; + } + + if (finfo->node_index != slot) { + FEAT_COND_ERR(emit_logs, + "%s/%s: lookup slot mismatch for finfo idx: %u and lookup slot: %u", + arc->feature_arc_name, feature_name, finfo->node_index, slot); + return -1; + } + + active_list = rte_atomic_load_explicit(&arc->active_feature_list, + rte_memory_order_relaxed); + + /* Get feature from active list */ + gf = __rte_graph_feature_get(arc, slot, ARC_PASSIVE_LIST(active_list)); + if (gf->this_feature_index != slot) { + FEAT_COND_ERR(emit_logs, + "%s: %s rcvd feature_idx: %u does not match with saved: %u", + arc->feature_arc_name, feature_name, slot, gf->this_feature_index); + return -1; + } + + if (is_enable_disable && (arc->feature_bit_mask_by_index[index] & + RTE_BIT64(slot))) { + FEAT_COND_ERR(emit_logs, "%s: %s already enabled on index: %u", + arc->feature_arc_name, feature_name, index); + return -1; + } + + if (!is_enable_disable && !arc->runtime_enabled_features) { + FEAT_COND_ERR(emit_logs, "%s: No feature enabled to disable", + arc->feature_arc_name); + return -1; + } + + if (!is_enable_disable && !(arc->feature_bit_mask_by_index[index] & RTE_BIT64(slot))) { + FEAT_COND_ERR(emit_logs, "%s: %s not enabled in bitmask for index: %u", + arc->feature_arc_name, feature_name, index); + return -1; + } + + return 0; +} + +/* + * Before switch to passive list, user_data needs to be copied from active list to passive list + */ +static void +copy_fastpath_user_data(struct rte_graph_feature_arc *arc, uint16_t dest_list_index, + uint16_t src_list_index) +{ + rte_graph_feature_data_t *sgfd = NULL, *dgfd = NULL; + struct rte_graph_feature *sgf = NULL, *dgf = NULL; + uint32_t i, j; + + for (i = 0; i < arc->max_features; i++) { + sgf = __rte_graph_feature_get(arc, i, src_list_index); + dgf = __rte_graph_feature_get(arc, i, dest_list_index); + for (j = 0; j < arc->max_indexes; j++) { + sgfd = rte_graph_feature_data_get(arc, sgf, j); + dgfd = rte_graph_feature_data_get(arc, dgf, j); + dgfd->user_data = sgfd->user_data; + } + } +} +/* + * Fill fast path information like + * - next_edge + * - next_enabled_feature + */ +static void +refill_feature_fastpath_data(struct rte_graph_feature_arc *arc, uint16_t list_index) +{ + struct rte_graph_feature_node_list *finfo = NULL, *prev_finfo = NULL; + struct rte_graph_feature_data *gfd = NULL, *prev_gfd = NULL; + uint32_t fi = UINT32_MAX, di = UINT32_MAX, prev_fi = UINT32_MAX; + struct rte_graph_feature *gf = NULL, *prev_gf = NULL; + rte_graph_feature_list_t *flist = NULL; + rte_edge_t edge = UINT16_MAX; + uint64_t bitmask = 0; + + flist = arc->feature_list[list_index]; + + for (di = 0; di < arc->max_indexes; di++) { + bitmask = arc->feature_bit_mask_by_index[di]; + prev_fi = RTE_GRAPH_FEATURE_INVALID; + /* for each feature set for index, set fast path data */ + while (rte_bsf64_safe(bitmask, &fi)) { + gf = __rte_graph_feature_get(arc, fi, list_index); + gfd = rte_graph_feature_data_get(arc, gf, di); + RTE_VERIFY(!feature_arc_node_info_lookup(arc, fi, &finfo, 1)); + + /* If previous feature_index was valid in last loop */ + if (prev_fi != RTE_GRAPH_FEATURE_INVALID) { + prev_gf = __rte_graph_feature_get(arc, prev_fi, list_index); + prev_gfd = rte_graph_feature_data_get(arc, prev_gf, di); + /* + * Get edge of previous feature node connecting + * to this feature node + */ + RTE_VERIFY(!feature_arc_node_info_lookup(arc, prev_fi, + &prev_finfo, 1)); + if (!get_existing_edge(arc->feature_arc_name, + prev_finfo->feature_node, + finfo->feature_node, &edge)) { + feat_dbg("\t[%s/%u/di:%2u,cookie:%u]: (%u->%u)%s[%u] = %s", + arc->feature_arc_name, list_index, di, + prev_gfd->user_data, prev_fi, fi, + prev_finfo->feature_node->name, + edge, finfo->feature_node->name); + /* Copy feature index for next iteration*/ + gfd->next_edge = edge; + prev_fi = fi; + /* + * Fill current feature as next enabled + * feature to previous one + */ + prev_gfd->next_enabled_feature = fi; + } else { + /* Should not fail */ + RTE_VERIFY(0); + } + } + /* On first feature edge of the node to be added */ + if (fi == rte_bsf64(arc->feature_bit_mask_by_index[di])) { + if (!get_existing_edge(arc->feature_arc_name, arc->start_node, + finfo->feature_node, + &edge)) { + feat_dbg("\t[%s/%u/di:%2u,cookie:%u]: (->%u)%s[%u]=%s", + arc->feature_arc_name, list_index, di, + gfd->user_data, fi, + arc->start_node->name, edge, + finfo->feature_node->name); + /* Copy feature index for next iteration*/ + gfd->next_edge = edge; + prev_fi = fi; + /* Set first feature set array for index*/ + flist->first_enabled_feature_by_index[di] = + (rte_graph_feature_t)fi; + } else { + /* Should not fail */ + RTE_VERIFY(0); + } + } + /* Clear current feature index */ + bitmask &= ~RTE_BIT64(fi); + } + } +} + +int +rte_graph_feature_enable(rte_graph_feature_arc_t _arc, uint32_t index, const + char *feature_name, int32_t user_data) +{ + struct rte_graph_feature_arc *arc = rte_graph_feature_arc_get(_arc); + rte_graph_feature_rt_list_t passive_list, active_list; + struct rte_graph_feature_node_list *finfo = NULL; + struct rte_graph_feature_data *gfd = NULL; + struct rte_graph_feature *gf = NULL; + uint64_t bitmask; + uint32_t slot; + + feat_dbg("%s: Enabling feature: %s for index: %u", + arc->feature_arc_name, feature_name, index); + + if (!arc->runtime_enabled_features) + prepare_feature_arc_before_first_enable(arc); + + if (rte_graph_feature_validate(_arc, index, feature_name, 1, true)) + return -1; + + /** This should not fail as validate() has passed */ + if (feature_lookup(arc, feature_name, &finfo, &slot)) + RTE_VERIFY(0); + + active_list = rte_atomic_load_explicit(&arc->active_feature_list, + rte_memory_order_relaxed); + + passive_list = ARC_PASSIVE_LIST(active_list); + + feat_dbg("\t%s/%s: index: %u, passive list: %u, feature index: %u", + arc->feature_arc_name, feature_name, index, passive_list, slot); + + gf = __rte_graph_feature_get(arc, slot, passive_list); + gfd = rte_graph_feature_data_get(arc, gf, index); + + /* Reset feature list */ + feature_arc_list_reset(arc, passive_list); + + /* Copy user-data */ + copy_fastpath_user_data(arc, passive_list, active_list); + + /* Set current user-data */ + gfd->user_data = user_data; + + /* Set bitmask in control path bitmask */ + rte_bit_relaxed_set64(rte_graph_uint_cast(slot), &arc->feature_bit_mask_by_index[index]); + refill_feature_fastpath_data(arc, passive_list); + + /* If first time feature getting enabled */ + bitmask = rte_atomic_load_explicit(&arc->feature_enable_bitmask[active_list], + rte_memory_order_relaxed); + + /* On very first feature enable instance */ + if (!finfo->ref_count) + bitmask |= RTE_BIT64(slot); + + rte_atomic_store_explicit(&arc->feature_enable_bitmask[passive_list], + bitmask, rte_memory_order_relaxed); + + /* Slow path updates */ + arc->runtime_enabled_features++; + + /* Increase feature node info reference count */ + finfo->ref_count++; + + /* Store release semantics for active_list update */ + rte_atomic_store_explicit(&arc->active_feature_list, passive_list, + rte_memory_order_release); + + feat_dbg("%s/%s: After enable, switched active feature list to %u", + arc->feature_arc_name, feature_name, passive_list); + + return 0; +} + +int +rte_graph_feature_disable(rte_graph_feature_arc_t _arc, uint32_t index, const char *feature_name) +{ + struct rte_graph_feature_arc *arc = rte_graph_feature_arc_get(_arc); + rte_graph_feature_rt_list_t passive_list, active_list; + struct rte_graph_feature_data *gfd = NULL; + struct rte_graph_feature_node_list *finfo = NULL; + struct rte_graph_feature *gf = NULL; + uint64_t bitmask; + uint32_t slot; + + feat_dbg("%s: Disable feature: %s for index: %u", + arc->feature_arc_name, feature_name, index); + + if (rte_graph_feature_validate(_arc, index, feature_name, 0, true)) + return -1; + + if (feature_lookup(arc, feature_name, &finfo, &slot)) + return -1; + + active_list = rte_atomic_load_explicit(&arc->active_feature_list, + rte_memory_order_relaxed); + + passive_list = ARC_PASSIVE_LIST(active_list); + + gf = __rte_graph_feature_get(arc, slot, passive_list); + gfd = rte_graph_feature_data_get(arc, gf, index); + + feat_dbg("\t%s/%s: index: %u, passive list: %u, feature index: %u", + arc->feature_arc_name, feature_name, index, passive_list, slot); + + rte_bit_relaxed_clear64(rte_graph_uint_cast(slot), &arc->feature_bit_mask_by_index[index]); + + /* Reset feature list */ + feature_arc_list_reset(arc, passive_list); + + /* Copy user-data */ + copy_fastpath_user_data(arc, passive_list, active_list); + + /* Reset current user-data */ + gfd->user_data = ~0; + + refill_feature_fastpath_data(arc, passive_list); + + finfo->ref_count--; + arc->runtime_enabled_features--; + + /* If no feature enabled, reset feature in u64 fast path bitmask */ + bitmask = rte_atomic_load_explicit(&arc->feature_enable_bitmask[active_list], + rte_memory_order_relaxed); + + /* When last feature is disabled */ + if (!finfo->ref_count) + bitmask &= ~(RTE_BIT64(slot)); + + rte_atomic_store_explicit(&arc->feature_enable_bitmask[passive_list], bitmask, + rte_memory_order_relaxed); + + /* Store release semantics for active_list update */ + rte_atomic_store_explicit(&arc->active_feature_list, passive_list, + rte_memory_order_release); + + feat_dbg("%s/%s: After disable, switched active feature list to %u", + arc->feature_arc_name, feature_name, passive_list); + + return 0; +} + +int +rte_graph_feature_arc_destroy(rte_graph_feature_arc_t _arc) +{ + struct rte_graph_feature_arc *arc = rte_graph_feature_arc_get(_arc); + rte_graph_feature_arc_main_t *dm = __rte_graph_feature_arc_main; + struct rte_graph_feature_node_list *node_info = NULL; + + while (!STAILQ_EMPTY(&arc->all_features)) { + node_info = STAILQ_FIRST(&arc->all_features); + STAILQ_REMOVE_HEAD(&arc->all_features, next_feature); + rte_free(node_info); + } + feature_arc_list_destroy(arc, 0); + feature_arc_list_destroy(arc, 1); + + dm->feature_arcs[arc->feature_arc_index] = RTE_GRAPH_FEATURE_ARC_INITIALIZER; + + rte_free(arc); + + do_sanity_all_arcs(); + + return 0; +} + +int +rte_graph_feature_arc_cleanup(void) +{ + rte_graph_feature_arc_main_t *dm = __rte_graph_feature_arc_main; + uint32_t iter; + + if (!__rte_graph_feature_arc_main) + return -1; + + for (iter = 0; iter < dm->max_feature_arcs; iter++) { + if (dm->feature_arcs[iter] == RTE_GRAPH_FEATURE_ARC_INITIALIZER) + continue; + + rte_graph_feature_arc_destroy((rte_graph_feature_arc_t)dm->feature_arcs[iter]); + } + rte_free(dm); + + __rte_graph_feature_arc_main = NULL; + + return 0; +} + +int +rte_graph_feature_arc_lookup_by_name(const char *arc_name, rte_graph_feature_arc_t *_arc) +{ + rte_graph_feature_arc_main_t *dm = __rte_graph_feature_arc_main; + struct rte_graph_feature_arc *arc = NULL; + uint32_t iter; + + if (!__rte_graph_feature_arc_main) + return -1; + + if (_arc) + *_arc = RTE_GRAPH_FEATURE_ARC_INITIALIZER; + + for (iter = 0; iter < dm->max_feature_arcs; iter++) { + if (dm->feature_arcs[iter] == RTE_GRAPH_FEATURE_ARC_INITIALIZER) + continue; + + arc = rte_graph_feature_arc_get(dm->feature_arcs[iter]); + + if ((strstr(arc->feature_arc_name, arc_name)) && + (strlen(arc->feature_arc_name) == strlen(arc_name))) { + if (_arc) + *_arc = (rte_graph_feature_arc_t)arc; + return 0; + } + } + + return -1; +} + +uint32_t +rte_graph_feature_arc_num_enabled_features(rte_graph_feature_arc_t _arc) +{ + struct rte_graph_feature_arc *arc = rte_graph_feature_arc_get(_arc); + + return arc->runtime_enabled_features; +} + +uint32_t +rte_graph_feature_arc_num_features(rte_graph_feature_arc_t _arc) +{ + struct rte_graph_feature_arc *arc = rte_graph_feature_arc_get(_arc); + struct rte_graph_feature_node_list *finfo = NULL; + uint32_t count = 0; + + STAILQ_FOREACH(finfo, &arc->all_features, next_feature) + count++; + + return count; +} + +char * +rte_graph_feature_arc_feature_to_name(rte_graph_feature_arc_t _arc, rte_graph_feature_t feat) +{ + struct rte_graph_feature_arc *arc = rte_graph_feature_arc_get(_arc); + struct rte_graph_feature_node_list *finfo = NULL; + uint32_t slot = feat; + + if (feat >= rte_graph_feature_arc_num_features(_arc)) { + graph_err("%s: feature %u does not exist", arc->feature_arc_name, feat); + return NULL; + } + if (!feature_arc_node_info_lookup(arc, slot, &finfo, 0/* ignore sanity*/)) + return finfo->feature_node->name; + + return NULL; +} + +struct rte_node_register * +rte_graph_feature_arc_feature_to_node(rte_graph_feature_arc_t _arc, rte_graph_feature_t feat) +{ + struct rte_graph_feature_arc *arc = rte_graph_feature_arc_get(_arc); + struct rte_graph_feature_node_list *finfo = NULL; + uint32_t slot = feat; + + if (feat >= rte_graph_feature_arc_num_features(_arc)) { + graph_err("%s: feature %u does not exist", arc->feature_arc_name, feat); + return NULL; + } + if (!feature_arc_node_info_lookup(arc, slot, &finfo, 0/* ignore sanity*/)) + return finfo->feature_node; + + return NULL; + +} diff --git a/lib/graph/meson.build b/lib/graph/meson.build index 0cb15442ab..d916176fb7 100644 --- a/lib/graph/meson.build +++ b/lib/graph/meson.build @@ -14,11 +14,13 @@ sources = files( 'graph_debug.c', 'graph_stats.c', 'graph_populate.c', + 'graph_feature_arc.c', 'graph_pcap.c', 'rte_graph_worker.c', 'rte_graph_model_mcore_dispatch.c', ) headers = files('rte_graph.h', 'rte_graph_worker.h') +headers += files('rte_graph_feature_arc.h', 'rte_graph_feature_arc_worker.h') indirect_headers += files( 'rte_graph_model_mcore_dispatch.h', 'rte_graph_model_rtc.h', diff --git a/lib/graph/rte_graph_feature_arc.h b/lib/graph/rte_graph_feature_arc.h new file mode 100644 index 0000000000..1615f8e1c8 --- /dev/null +++ b/lib/graph/rte_graph_feature_arc.h @@ -0,0 +1,431 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(C) 2024 Marvell International Ltd. + */ + +#ifndef _RTE_GRAPH_FEATURE_ARC_H_ +#define _RTE_GRAPH_FEATURE_ARC_H_ + +#include <assert.h> +#include <errno.h> +#include <signal.h> +#include <stddef.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <rte_common.h> +#include <rte_compat.h> +#include <rte_debug.h> +#include <rte_graph.h> +#include <rte_graph_worker.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @file + * + * rte_graph_feature_arc.h + * + * Define APIs and structures/variables with respect to feature arc + * + * - Feature arc(s) + * - Feature(s) + * + * A feature arc represents an ordered list of features/protocol-nodes at a + * given networking layer. Feature arc provides a high level abstraction to + * connect various *rte_graph* nodes, designated as *feature nodes*, and + * allowing steering of packets across these feature nodes fast path processing + * in a generic manner. In a typical network stack, often a protocol or feature + * must be first enabled on a given interface, before any packet is steered + * towards it for feature processing. For eg: incoming IPv4 packets are sent to + * routing sub-system only after a valid IPv4 address is assigned to the + * received interface. In other words, often packets needs to be steered across + * features not based on the packet content but based on whether a feature is + * enable or disable on a given incoming/outgoing interface. Feature arc + * provides mechanism to enable/disable feature(s) on each interface at runtime + * and allow seamless packet steering across runtime enabled feature nodes in + * fast path. + * + * Feature arc also provides a way to steer packets from standard nodes to + * custom/user-defined *feature nodes* without any change in standard node's + * fast path functions + * + * On a given interface multiple feature(s) might be enabled in a particular + * feature arc. For instance, both "ipv4-output" and "IPsec policy output" + * features may be enabled on "eth0" interface in "L3-output" feature arc. + * Similarly, "ipv6-output" and "ipsec-output" may be enabled on "eth1" + * interface in same "L3-output" feature arc. + * + * When multiple features are present in a given feature arc, its imperative + * to allow each feature processing in a particular sequential order. For + * instance, in "L3-input" feature arc it may be required to run "IPsec + * input" feature first, for packet decryption, before "ip-lookup". So a + * sequential order must be maintained among features present in a feature arc. + * + * Features are enabled/disabled multiple times at runtime to some or all + * available interfaces present in the system. Enable/disabling features on one + * interface is independent of other interface. + * + * A given feature might consume packet (if it's configured to consume) or may + * forward it to next enabled feature. For instance, "IPsec input" feature may + * consume/drop all packets with "Protect" policy action while all packets with + * policy action as "Bypass" may be forwarded to next enabled feature (with in + * same feature arc) + * + * This library facilitates rte graph based applications to steer packets in + * fast path to different feature nodes with-in a feature arc and support all + * functionalities described above + * + * In order to use feature-arc APIs, applications needs to do following in + * control path: + * - Initialize feature arc library via rte_graph_feature_arc_init() + * - Create feature arc via rte_graph_feature_arc_create() + * - *Before calling rte_graph_create()*, features must be added to feature-arc + * via rte_graph_feature_add(). rte_graph_feature_add() allows adding + * features in a sequential order with "runs_after" and "runs_before" + * constraints. + * - Post rte_graph_create(), features can be enabled/disabled at runtime on + * any interface via rte_graph_feature_enable()/rte_graph_feature_disable() + * - Feature arc can be destroyed via rte_graph_feature_arc_destroy() + * + * In fast path, APIs are provided to steer packets towards feature path from + * - start_node (provided as an argument to rte_graph_feature_arc_create()) + * - feature nodes (which are added via rte_graph_feature_add()) + * + * For typical steering of packets across feature nodes, application required + * to know "rte_edges" which are saved in feature data object. Feature data + * object is unique for every interface per feature with in a feature arc. + * + * When steering packets from start_node to feature node: + * - rte_graph_feature_arc_first_feature_get() provides first enabled feature. + * - Next rte_edge from start_node to first enabled feature can be obtained via + * rte_graph_feature_arc_feature_set() + * + * rte_mbuf can carry [current feature, interface index] from start_node of an + * arc to other feature nodes + * + * At the time of feature enable(rte_graph_feature_enable), application can set + * 32-bit unique user_data specific to feature per interface. In fast path + * user_data can be retrieved via rte_graph_feature_user_data_get(). User data + * can hold application specific cookie like IPsec policy database index, FIB + * table index etc. + * + * If feature node is not consuming packet, next enabled feature and next + * rte_edge can be obtained via rte_graph_feature_arc_next_feature_get() + * + * It is application responsibility to ensure that at-least *last feature*(or + * sink feature) must be enabled from where packet can exit feature-arc path, + * if *NO* intermediate feature is consuming the packet and it has reached till + * the end of feature arc path + * + * It is recommended that all features *MUST* be added to feature arc before + * calling `rte_graph_create()`. Addition of features after + * `rte_graph_create()` may not work functionally. + * Although,rte_graph_feature_enable()/rte_graph_feature_disable() should be + * called after `rte_graph_create()` in control plane. + * + * Synchronization among cores + * --------------------------- + * Subsequent calls to rte_graph_feature_enable() is allowed while worker cores + * are processing in rte_graph_walk() loop. However, for + * rte_graph_feature_disable() application must use RCU based synchronization + */ + +/** Initializer value for rte_graph_feature_arc_t */ +#define RTE_GRAPH_FEATURE_ARC_INITIALIZER ((rte_graph_feature_arc_t)UINT64_MAX) + +/** Max number of feature arcs which can be created */ +#define RTE_GRAPH_FEATURE_ARC_MAX 64 + +/** Max number of features supported in a given feature arc */ +#define RTE_GRAPH_FEATURE_MAX_PER_ARC 64 + +/** Length of feature arc name */ +#define RTE_GRAPH_FEATURE_ARC_NAMELEN RTE_NODE_NAMESIZE + +/** @internal */ +#define rte_graph_feature_cast(x) ((rte_graph_feature_t)x) + +/**< Initializer value for rte_graph_feature_arc_t */ +#define RTE_GRAPH_FEATURE_INVALID rte_graph_feature_cast(UINT8_MAX) + +/** rte_graph feature arc object */ +typedef uintptr_t rte_graph_feature_arc_t; + +/** rte_graph feature object */ +typedef uint8_t rte_graph_feature_t; + +/** runtime active feature list index with in feature arc*/ +typedef uint16_t rte_graph_feature_rt_list_t; + +/** per feature arc monotonically increasing counter to synchronize fast path APIs */ +typedef uint16_t rte_graph_feature_counter_t; + +/** + * Initialize feature arc subsystem + * + * @param max_feature_arcs + * Maximum number of feature arcs required to be supported + * + * @return + * 0: Success + * <0: Failure + */ +__rte_experimental +int rte_graph_feature_arc_init(int max_feature_arcs); + +/** + * Create a feature arc + * + * @param feature_arc_name + * Feature arc name with max length of @ref RTE_GRAPH_FEATURE_ARC_NAMELEN + * @param max_features + * Maximum number of features to be supported in this feature arc + * @param max_indexes + * Maximum number of interfaces/ports/indexes to be supported + * @param start_node + * Base node where this feature arc's features are checked in fast path + * @param[out] _arc + * Feature arc object + * + * @return + * 0: Success + * <0: Failure + */ +__rte_experimental +int rte_graph_feature_arc_create(const char *feature_arc_name, int max_features, int max_indexes, + struct rte_node_register *start_node, + rte_graph_feature_arc_t *_arc); + +/** + * Get feature arc object with name + * + * @param arc_name + * Feature arc name provided to successful @ref rte_graph_feature_arc_create + * @param[out] _arc + * Feature arc object returned. Valid only when API returns SUCCESS + * + * @return + * 0: Success + * <0: Failure. + */ +__rte_experimental +int rte_graph_feature_arc_lookup_by_name(const char *arc_name, rte_graph_feature_arc_t *_arc); + +/** + * Add a feature to already created feature arc. For instance + * + * 1. Add first feature node: "ipv4-input" to input arc + * rte_graph_feature_add(ipv4_input_arc, "ipv4-input", NULL, NULL); + * + * 2. Add "ipsec-input" feature node after "ipv4-input" feature + * rte_graph_feature_add(ipv4_input_arc, "ipsec-input", "ipv4-input", NULL); + * + * 3. Add "ipv4-pre-classify-input" node before "ipv4-input" feature + * rte_graph_feature_add(ipv4_input_arc, "ipv4-pre-classify-input"", NULL, "ipv4-input"); + * + * 4. Add "acl-classify-input" node after ipv4-input but before ipsec-input + * rte_graph_feature_add(ipv4_input_arc, "acl-classify-input", "ipv4-input", "ipsec-input"); + * + * @param _arc + * Feature arc handle returned from @ref rte_graph_feature_arc_create() + * @param feature_node + * Graph node representing feature. On success, feature_node is next_node of + * feature_arc->start_node + * @param runs_after + * Add this feature_node after already added "runs_after". Creates + * start_node -> runs_after -> this_feature sequence + * @param runs_before + * Add this feature_node before already added "runs_before". Creates + * start_node -> this_feature -> runs_before sequence + * + * <I> Must be called before rte_graph_create() </I> + * <I> rte_graph_feature_add() is not allowed after call to + * rte_graph_feature_enable() so all features must be added before they can be + * enabled </I> + * + * @return + * 0: Success + * <0: Failure + */ +__rte_experimental +int rte_graph_feature_add(rte_graph_feature_arc_t _arc, struct rte_node_register *feature_node, + const char *runs_after, const char *runs_before); + +/** + * Enable feature within a feature arc + * + * Must be called after @b rte_graph_create(). + * + * @param _arc + * Feature arc object returned by @ref rte_graph_feature_arc_create or @ref + * rte_graph_feature_arc_lookup_by_name + * @param index + * Application specific index. Can be corresponding to interface_id/port_id etc + * @param feature_name + * Name of the node which is already added via @ref rte_graph_feature_add + * @param user_data + * Application specific data which is retrieved in fast path + * + * @return + * 0: Success + * <0: Failure + */ +__rte_experimental +int rte_graph_feature_enable(rte_graph_feature_arc_t _arc, uint32_t index, const char *feature_name, + int32_t user_data); + +/** + * Validate whether subsequent enable/disable feature would succeed or not. + * API is thread-safe + * + * @param _arc + * Feature arc object returned by @ref rte_graph_feature_arc_create or @ref + * rte_graph_feature_arc_lookup_by_name + * @param index + * Application specific index. Can be corresponding to interface_id/port_id etc + * @param feature_name + * Name of the node which is already added via @ref rte_graph_feature_add + * @param is_enable_disable + * If 1, validate whether subsequent @ref rte_graph_feature_enable would pass or not + * If 0, validate whether subsequent @ref rte_graph_feature_disable would pass or not + * @param emit_logs + * If passed true, emit error logs when failure is returned + * If passed false, do not emit error logs when failure is returned + * + * @return + * 0: Subsequent enable/disable API would pass + * <0: Subsequent enable/disable API would not pass + */ +__rte_experimental +int rte_graph_feature_validate(rte_graph_feature_arc_t _arc, uint32_t index, + const char *feature_name, int is_enable_disable, bool emit_logs); + +/** + * Disable already enabled feature within a feature arc + * + * Must be called after @b rte_graph_create(). API is *NOT* Thread-safe + * + * @param _arc + * Feature arc object returned by @ref rte_graph_feature_arc_create or @ref + * rte_graph_feature_arc_lookup_by_name + * @param index + * Application specific index. Can be corresponding to interface_id/port_id etc + * @param feature_name + * Name of the node which is already added via @ref rte_graph_feature_add + * + * @return + * 0: Success + * <0: Failure + */ +__rte_experimental +int rte_graph_feature_disable(rte_graph_feature_arc_t _arc, uint32_t index, + const char *feature_name); + +/** + * Get rte_graph_feature_t object from feature name + * + * @param arc + * Feature arc object returned by @ref rte_graph_feature_arc_create or @ref + * rte_graph_feature_arc_lookup_by_name + * @param feature_name + * Feature name provided to @ref rte_graph_feature_add + * @param[out] feature + * Feature object + * + * @return + * 0: Success + * <0: Failure + */ +__rte_experimental +int rte_graph_feature_lookup(rte_graph_feature_arc_t arc, const char *feature_name, + rte_graph_feature_t *feature); + +/** + * Delete feature_arc object + * + * @param _arc + * Feature arc object returned by @ref rte_graph_feature_arc_create or @ref + * rte_graph_feature_arc_lookup_by_name + * + * @return + * 0: Success + * <0: Failure + */ +__rte_experimental +int rte_graph_feature_arc_destroy(rte_graph_feature_arc_t _arc); + +/** + * Cleanup all feature arcs + * + * @return + * 0: Success + * <0: Failure + */ +__rte_experimental +int rte_graph_feature_arc_cleanup(void); + +/** + * Slow path API to know how many features are added (NOT enabled) within a + * feature arc + * + * @param _arc + * Feature arc object + * + * @return: Number of added features to arc + */ +__rte_experimental +uint32_t rte_graph_feature_arc_num_features(rte_graph_feature_arc_t _arc); + +/** + * Slow path API to know how many features are currently enabled within a + * feature arc across all indexes. If a single feature is enabled on all interfaces, + * this API would return "number_of_interfaces" as count (but not "1") + * + * @param _arc + * Feature arc object + * + * @return: Number of enabled features across all indexes + */ +__rte_experimental +uint32_t rte_graph_feature_arc_num_enabled_features(rte_graph_feature_arc_t _arc); + +/** + * Slow path API to get feature node name from rte_graph_feature_t object + * + * @param _arc + * Feature arc object + * @param feature + * Feature object + * + * @return: Name of the feature node + */ +__rte_experimental +char *rte_graph_feature_arc_feature_to_name(rte_graph_feature_arc_t _arc, + rte_graph_feature_t feature); + +/** + * Slow path API to get corresponding struct rte_node_register * from + * rte_graph_feature_t + * + * @param _arc + * Feature arc object + * @param feature + * Feature object + * + * @return: struct rte_node_register * of feature node on SUCCESS else NULL + */ +__rte_experimental +struct rte_node_register * +rte_graph_feature_arc_feature_to_node(rte_graph_feature_arc_t _arc, + rte_graph_feature_t feature); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/graph/rte_graph_feature_arc_worker.h b/lib/graph/rte_graph_feature_arc_worker.h new file mode 100644 index 0000000000..9b720e366c --- /dev/null +++ b/lib/graph/rte_graph_feature_arc_worker.h @@ -0,0 +1,679 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(C) 2024 Marvell International Ltd. + */ + +#ifndef _RTE_GRAPH_FEATURE_ARC_WORKER_H_ +#define _RTE_GRAPH_FEATURE_ARC_WORKER_H_ + +#include <stddef.h> +#include <rte_graph_feature_arc.h> +#include <rte_bitops.h> + +/** + * @file + * + * rte_graph_feature_arc_worker.h + * + * Defines fast path structure + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** @internal + * + * Slow path feature node info list + */ +struct rte_graph_feature_node_list { + /** Next feature */ + STAILQ_ENTRY(rte_graph_feature_node_list) next_feature; + + /** node representing feature */ + struct rte_node_register *feature_node; + + /** How many indexes/interfaces using this feature */ + int32_t ref_count; + + /* node_index in list (after feature_enable())*/ + uint32_t node_index; + + /** Back pointer to feature arc */ + void *feature_arc; + + /** rte_edge_t to this feature node from feature_arc->start_node */ + rte_edge_t edge_to_this_feature; +}; + +/** + * Feature data object: + * + * Feature data stores information to steer packets for: + * - a feature with in feature arc + * - Index i.e. Port/Interface index + * + * Each feature data object holds + * - User data of current feature retrieved via rte_graph_feature_user_data_get() + * - next_edge is used in two conditions when packet to be steered from + * -- start_node to first enabled feature on an interface index + * -- current feature node to next enabled feature on an interface index + * - next_enabled_feature on interface index, if current feature is not + * consuming packet + * + * While user_data corresponds to current enabled feature node however + * next_edge and next_enabled_feature corresponds to next enabled feature + * node on an interface index + * + * First enabled feature on interface index can be retrieved via: + * - rte_graph_feature_first_feature_get() if arc's start_node is trying to + * steer packet from start_node to first enabled feature on interface index + * + * Next enabled feature on interface index can be retrieved via: + * - rte_graph_feature_next_feature_get() if current node is not arc's + * start_node. Input to rte_graph_feature_next_feature_get() is current + * enabled feature and interface index + */ +typedef struct __rte_packed rte_graph_feature_data { + /** edge from current node to next enabled feature */ + rte_edge_t next_edge; + + union { + uint16_t reserved; + struct { + /** next enabled feature on index from current feature */ + rte_graph_feature_t next_enabled_feature; + }; + }; + + /** user_data set by application in rte_graph_feature_enable() for + * - current feature + * - interface index + */ + int32_t user_data; +} rte_graph_feature_data_t; + +/** + * Feature object + * + * Feature object holds feature data object for every index/interface within + * feature + * + * Within a given arc and interface index, first feature object can be + * retrieved in arc's start_node via: + * - rte_graph_feature_arc_first_feature_get() + * + * Feature data information can be retrieved for first feature in start node via + * - rte_graph_feature_arc_feature_set() + * + * Next enabled feature on interface index can be retrieved via: + * - rte_graph_feature_arc_next_feature_get() + * + * Typically application stores rte_graph_feature_t object in rte_mbuf. + * rte_graph_feature_t can be translated to (struct rte_graph_feature *) via + * rte_graph_feature_get() in fast path. Further if needed, feature data for an + * index within a feature can be retrieved via rte_graph_feature_data_get() + */ +struct __rte_cache_aligned rte_graph_feature { + /** feature index or rte_graph_feature_t */ + uint16_t this_feature_index; + + /* + * Array of size arc->feature_data_size + * + * <----------------- Feature --------------------------> + * [data-index-0][data-index-1]...[data-index-max_index-1] + * + * sizeof(feature_data_by_index[0] == sizeof(rte_graph_feature_data_t) + * + */ + uint8_t feature_data_by_index[]; +}; + +/** + * Feature list object + * + * Feature list is required to decouple fast path APIs with control path APIs. + * + * There are two feature lists: active, passive + * Passive list is duplicate of active list in terms of memory. + * + * While fast path APIs always work on active list but control plane work on + * passive list. When control plane needs to enable/disable any feature, it + * populates passive list afresh and atomically switch passive list to active + * list to make it available for fast path APIs + * + * Each feature node in start of its fast path function, must grab active list from + * arc via + * - rte_graph_feature_arc_has_any_feature() or + * rte_graph_feature_arc_has_feature() + * + * Retrieved list must be provided to other feature arc fast path APIs so that + * any control plane changes of active list should not impact current node + * execution iteration. Active list change would be reflected to current node + * in next iteration + * + * With active/passive lists and RCU mechanism in graph worker + * loop, application can update features at runtime without stopping fast path + * cores. A RCU synchronization is required when a feature needs to be + * disabled via rte_graph_feature_disable(). On enabling a feature, RCU + * synchronization may not be required + * + */ +typedef struct __rte_cache_aligned rte_graph_feature_list { + /** + * fast path array holding per_feature data. + * Duplicate entry as feature-arc also hold this pointer + * arc->features[] + * + *<-------------feature-0 ---------><---------feature-1 -------------->... + *[index-0][index-1]...[max_index-1]<-ALIGN->[index-0][index-1] ...[max_index-1]... + */ + struct rte_graph_feature *indexed_by_features; + /* + * fast path array holding first enabled feature per index + * (Required in start_node. In non start_node, mbuf can hold next enabled + * feature) + */ + rte_graph_feature_t first_enabled_feature_by_index[]; +} rte_graph_feature_list_t; + +/** + * rte_graph Feature arc object + * + * Feature arc object holds control plane and fast path information for all + * features and all interface index information for steering packets across + * feature nodes + * + * Within a feature arc, only RTE_GRAPH_FEATURE_MAX_PER_ARC features can be + * added. If more features needs to be added, another feature arc can be + * created + * + * Application gets rte_graph_feature_arc_t object via + * - rte_graph_feature_arc_create() OR + * - rte_graph_feature_arc_lookup_by_name() + * + * In fast path, rte_graph_feature_arc_t can be translated to (struct + * rte_graph_feature_arc *) via rte_graph_feature_arc_get(). Later is needed to + * add as an input argument to all fast path feature arc APIs + */ +struct __rte_cache_aligned rte_graph_feature_arc { + /* First 64B is fast path variables */ + RTE_MARKER fast_path_variables; + + /** runtime active feature list */ + RTE_ATOMIC(rte_graph_feature_rt_list_t) active_feature_list; + + /** Actual Size of feature_list object */ + uint16_t feature_list_size; + + /** + * Size each feature in fastpath. + * Required to navigate from feature to another feature in fast path + */ + uint16_t feature_size; + + /** + * Size of all feature data for an index + * Required to navigate through various feature data within a feature + * in fast path + */ + uint16_t feature_data_size; + + /** + * Quick fast path bitmask indicating if any feature enabled or not on + * any of the indexes. Helps in optimally process packets for the case + * when features are added but not enabled + * + * Separate for active and passive list + */ + RTE_ATOMIC(uint64_t) feature_enable_bitmask[2]; + + /** + * Pointer to both active and passive feature list object + */ + rte_graph_feature_list_t *feature_list[2]; + + /** + * Feature objects for each list + */ + struct rte_graph_feature *features[2]; + + /** index in feature_arc_main */ + uint16_t feature_arc_index; + + uint16_t reserved[3]; + + /** Slow path variables follows*/ + RTE_MARKER slow_path_variables; + + /** feature arc name */ + char feature_arc_name[RTE_GRAPH_FEATURE_ARC_NAMELEN]; + + /** All feature lists */ + STAILQ_HEAD(, rte_graph_feature_node_list) all_features; + + /** control plane counter to track enabled features */ + uint32_t runtime_enabled_features; + + /** Back pointer to feature_arc_main */ + void *feature_arc_main; + + /** Arc's start/base node */ + struct rte_node_register *start_node; + + /** maximum number of features supported by this arc */ + uint32_t max_features; + + /** maximum number of index supported by this arc */ + uint32_t max_indexes; + + /** Slow path bit mask per feature per index */ + uint64_t feature_bit_mask_by_index[]; +}; + +/** + * Feature arc main object + * + * Holds all feature arcs created by application + * + * RTE_GRAPH_FEATURE_ARC_MAX number of feature arcs can be created by + * application via rte_graph_feature_arc_create() + */ +typedef struct feature_arc_main { + /** number of feature arcs created by application */ + uint32_t num_feature_arcs; + + /** max features arcs allowed */ + uint32_t max_feature_arcs; + + /** feature arcs */ + rte_graph_feature_arc_t feature_arcs[]; +} rte_graph_feature_arc_main_t; + +/** @internal Get feature arc pointer from object */ +#define rte_graph_feature_arc_get(arc) ((struct rte_graph_feature_arc *)arc) + +extern rte_graph_feature_arc_main_t *__feature_arc_main; + +/** + * API to know if feature is valid or not + */ +__rte_experimental +static __rte_always_inline int +rte_graph_feature_is_valid(rte_graph_feature_t feature) +{ + return (feature != RTE_GRAPH_FEATURE_INVALID); +} + +/** + * Get rte_graph_feature object with no checks + * + * @param arc + * Feature arc pointer + * @param feature + * Feature index + * @param feature_list + * active feature list retrieved from rte_graph_feature_arc_has_any_feature() + * or rte_graph_feature_arc_has_feature() + * + * @return + * Internal feature object. + */ +__rte_experimental +static __rte_always_inline struct rte_graph_feature * +__rte_graph_feature_get(struct rte_graph_feature_arc *arc, rte_graph_feature_t feature, + const rte_graph_feature_rt_list_t feature_list) +{ + return ((struct rte_graph_feature *)(((uint8_t *)arc->features[feature_list]) + + (feature * arc->feature_size))); +} + +/** + * Get rte_graph_feature object for a given interface/index from feature arc + * + * @param arc + * Feature arc pointer + * @param feature + * Feature index + * + * @return + * Internal feature object. + */ +__rte_experimental +static __rte_always_inline struct rte_graph_feature * +rte_graph_feature_get(struct rte_graph_feature_arc *arc, rte_graph_feature_t feature) +{ + rte_graph_feature_rt_list_t list; + + if (unlikely(feature >= arc->max_features)) + RTE_VERIFY(0); + + if (likely(rte_graph_feature_is_valid(feature))) { + list = rte_atomic_load_explicit(&arc->active_feature_list, + rte_memory_order_relaxed); + return __rte_graph_feature_get(arc, feature, list); + } + + return NULL; +} + +__rte_experimental +static __rte_always_inline rte_graph_feature_data_t * +__rte_graph_feature_data_get(struct rte_graph_feature_arc *arc, struct rte_graph_feature *feature, + uint8_t index) +{ + RTE_SET_USED(arc); + return ((rte_graph_feature_data_t *)(((uint8_t *)feature->feature_data_by_index) + + (index * sizeof(rte_graph_feature_data_t)))); +} + +/** + * Get rte_graph feature data object for a index in feature + * + * @param arc + * feature arc + * @param feature + * Pointer to feature object + * @param index + * Index of feature maintained in slow path linked list + * + * @return + * Valid feature data + */ +__rte_experimental +static __rte_always_inline rte_graph_feature_data_t * +rte_graph_feature_data_get(struct rte_graph_feature_arc *arc, struct rte_graph_feature *feature, + uint8_t index) +{ + if (likely(index < arc->max_indexes)) + return __rte_graph_feature_data_get(arc, feature, index); + + RTE_VERIFY(0); +} + +/** + * Fast path API to check if any feature enabled on a feature arc + * Typically from arc->start_node process function + * + * @param arc + * Feature arc object + * @param[out] plist + * Pointer to runtime active feature list which needs to be provided to other + * fast path APIs + * + * @return + * 0: If no feature enabled + * Non-Zero: Bitmask of features enabled. plist is valid + * + */ +__rte_experimental +static __rte_always_inline uint64_t +rte_graph_feature_arc_has_any_feature(struct rte_graph_feature_arc *arc, + rte_graph_feature_rt_list_t *plist) +{ + *plist = rte_atomic_load_explicit(&arc->active_feature_list, rte_memory_order_relaxed); + + return (rte_atomic_load_explicit(arc->feature_enable_bitmask + (uint8_t)*plist, + rte_memory_order_relaxed)); +} + +/** + * Fast path API to check if provided feature is enabled on any interface/index + * or not + * + * @param arc + * Feature arc object + * @param feature + * Input rte_graph_feature_t that needs to be checked + * @param[out] plist + * Returns active list to caller which needs to be provided to other fast path + * APIs + * + * @return + * 1: If input [feature] is enabled in arc + * 0: If input [feature] is not enabled in arc + */ +__rte_experimental +static __rte_always_inline int +rte_graph_feature_arc_has_feature(struct rte_graph_feature_arc *arc, + rte_graph_feature_t feature, + rte_graph_feature_rt_list_t *plist) +{ + uint64_t bitmask = RTE_BIT64(feature); + + *plist = rte_atomic_load_explicit(&arc->active_feature_list, rte_memory_order_relaxed); + + return (bitmask & rte_atomic_load_explicit(arc->feature_enable_bitmask + (uint8_t)*plist, + rte_memory_order_relaxed)); +} + +/** + * Prefetch feature arc fast path cache line + * + * @param arc + * RTE_GRAPH feature arc object + */ +__rte_experimental +static __rte_always_inline void +rte_graph_feature_arc_prefetch(struct rte_graph_feature_arc *arc) +{ + rte_prefetch0((void *)&arc->fast_path_variables); +} + +/** + * Prefetch feature related fast path cache line + * + * @param arc + * RTE_GRAPH feature arc object + * @param list + * Pointer to runtime active feature list from rte_graph_feature_arc_has_any_feature(); + * @param feature + * Pointer to feature object + */ +__rte_experimental +static __rte_always_inline void +rte_graph_feature_arc_feature_prefetch(struct rte_graph_feature_arc *arc, + const rte_graph_feature_rt_list_t list, + rte_graph_feature_t feature) +{ + /* feature cache line */ + if (likely(rte_graph_feature_is_valid(feature))) + rte_prefetch0((void *)__rte_graph_feature_get(arc, feature, list)); +} + +/** + * Prefetch feature data upfront. Perform sanity + * + * @param arc + * RTE_GRAPH feature arc object + * @param list + * Pointer to runtime active feature list from rte_graph_feature_arc_has_any_feature(); + * @param feature + * Pointer to feature object returned from @ref + * rte_graph_feature_arc_first_feature_get() + * @param index + * Interface/index + */ +__rte_experimental +static __rte_always_inline void +rte_graph_feature_arc_data_prefetch(struct rte_graph_feature_arc *arc, + const rte_graph_feature_rt_list_t list, + rte_graph_feature_t feature, uint32_t index) +{ + if (likely(rte_graph_feature_is_valid(feature))) + rte_prefetch0((void *)((uint8_t *)arc->features[list] + + offsetof(struct rte_graph_feature, feature_data_by_index) + + (index * sizeof(rte_graph_feature_data_t)))); +} + +/** + * Fast path API to get first enabled feature on interface index + * Typically required in arc->start_node so that from returned feature, + * feature-data can be retrieved to steer packets + * + * @param arc + * Feature arc object + * @param list + * Pointer to runtime active feature list from + * rte_graph_feature_arc_has_any_feature() or + * rte_graph_feature_arc_has_feature() + * @param index + * Interface Index + * @param[out] feature + * Pointer to rte_graph_feature_t. + * + * @return + * 1. Success. If first feature field is enabled and returned [feature] is valid + * 0. Failure. If first feature field is disabled in arc + * + */ +__rte_experimental +static __rte_always_inline int +rte_graph_feature_arc_first_feature_get(struct rte_graph_feature_arc *arc, + const rte_graph_feature_rt_list_t list, + uint32_t index, + rte_graph_feature_t *feature) +{ + struct rte_graph_feature_list *feature_list = arc->feature_list[list]; + + *feature = feature_list->first_enabled_feature_by_index[index]; + + return rte_graph_feature_is_valid(*feature); +} + +/** + * Fast path API to get next enabled feature on interface index with provided + * input feature + * + * @param arc + * Feature arc object + * @param list + * Pointer to runtime active feature list from + * rte_graph_feature_arc_has_any_feature() or + * @param index + * Interface Index + * @param[out] feature + * Pointer to rte_graph_feature_t. API sets next enabled feature on [index] + * from provided input feature. Valid only if API returns Success + * @param[out] next_edge + * Edge from current feature to next feature. Valid only if next feature is valid + * + * @return + * 1. Success. first feature field is enabled/valid + * 0. Failure. first feature field is disabled/invalid + */ +__rte_experimental +static __rte_always_inline int +rte_graph_feature_arc_next_feature_get(struct rte_graph_feature_arc *arc, + const rte_graph_feature_rt_list_t list, + uint32_t index, + rte_graph_feature_t *feature, + rte_edge_t *next_edge) +{ + rte_graph_feature_data_t *feature_data = NULL; + struct rte_graph_feature *f = NULL; + + if (likely(rte_graph_feature_is_valid(*feature))) { + f = __rte_graph_feature_get(arc, *feature, list); + feature_data = rte_graph_feature_data_get(arc, f, index); + *feature = feature_data->next_enabled_feature; + *next_edge = feature_data->next_edge; + return rte_graph_feature_is_valid(*feature); + } + + return 0; +} + +/** + * Set fields with respect to first enabled feature in an arc and return edge + * Typically returned feature and interface index must be saved in rte_mbuf + * structure to pass this information to next feature node + * + * @param arc + * Feature arc object + * @param list + * Pointer to runtime active feature list from rte_graph_feature_arc_has_any_feature(); + * @param index + * Index (of interface) + * @param[out] gf + * Pointer to rte_graph_feature_t. Valid if API returns Success + * @param[out] edge + * Edge to steer packet from arc->start_node to first enabled feature. Valid + * only if API returns Success + * + * @return + * 0: If valid feature is enabled and set by API in *gf + * 1: If valid feature is NOT enabled + */ +__rte_experimental +static __rte_always_inline rte_graph_feature_t +rte_graph_feature_arc_feature_set(struct rte_graph_feature_arc *arc, + const rte_graph_feature_rt_list_t list, + uint32_t index, + rte_graph_feature_t *gf, + rte_edge_t *edge) +{ + struct rte_graph_feature_list *feature_list = arc->feature_list[list]; + struct rte_graph_feature_data *feature_data = NULL; + struct rte_graph_feature *feature = NULL; + rte_graph_feature_t f; + + f = feature_list->first_enabled_feature_by_index[index]; + + if (unlikely(rte_graph_feature_is_valid(f))) { + feature = __rte_graph_feature_get(arc, f, list); + feature_data = rte_graph_feature_data_get(arc, feature, index); + *gf = f; + *edge = feature_data->next_edge; + return 0; + } + + return 1; +} + +__rte_experimental +static __rte_always_inline int32_t +__rte_graph_feature_user_data_get(rte_graph_feature_data_t *fdata) +{ + return fdata->user_data; +} + +/** + * Get user data corresponding to current feature set by application in + * rte_graph_feature_enable() + * + * @param arc + * Feature arc object + * @param list + * Pointer to runtime active feature list from rte_graph_feature_arc_has_any_feature(); + * @param feature + * Feature index + * @param index + * Interface index + * + * @return + * -1: Failure + * Valid user data: Success + */ +__rte_experimental +static __rte_always_inline int32_t +rte_graph_feature_user_data_get(struct rte_graph_feature_arc *arc, + const rte_graph_feature_rt_list_t list, + rte_graph_feature_t feature, + uint32_t index) +{ + rte_graph_feature_data_t *fdata = NULL; + struct rte_graph_feature *f = NULL; + + if (likely(rte_graph_feature_is_valid(feature))) { + f = __rte_graph_feature_get(arc, feature, list); + fdata = rte_graph_feature_data_get(arc, f, index); + return __rte_graph_feature_user_data_get(fdata); + } + + return -1; +} +#ifdef __cplusplus +} +#endif +#endif diff --git a/lib/graph/version.map b/lib/graph/version.map index 2c83425ddc..3b7f475afd 100644 --- a/lib/graph/version.map +++ b/lib/graph/version.map @@ -52,3 +52,23 @@ DPDK_25 { local: *; }; + +EXPERIMENTAL { + global: + + # added in 24.11 + rte_graph_feature_arc_init; + rte_graph_feature_arc_create; + rte_graph_feature_arc_lookup_by_name; + rte_graph_feature_add; + rte_graph_feature_enable; + rte_graph_feature_validate; + rte_graph_feature_disable; + rte_graph_feature_lookup; + rte_graph_feature_arc_destroy; + rte_graph_feature_arc_cleanup; + rte_graph_feature_arc_num_enabled_features; + rte_graph_feature_arc_num_features; + rte_graph_feature_arc_feature_to_name; + rte_graph_feature_arc_feature_to_node; +}; -- 2.43.0 ^ permalink raw reply [flat|nested] 46+ messages in thread
* [PATCH v5 2/5] graph: add feature arc option in graph create 2024-10-14 14:33 ` [PATCH v5 0/5] add feature arc in rte_graph Nitin Saxena 2024-10-14 14:33 ` [PATCH v5 1/5] graph: add feature arc support Nitin Saxena @ 2024-10-14 14:33 ` Nitin Saxena 2024-10-14 14:33 ` [PATCH v5 3/5] graph: add IPv4 output feature arc Nitin Saxena ` (2 subsequent siblings) 4 siblings, 0 replies; 46+ messages in thread From: Nitin Saxena @ 2024-10-14 14:33 UTC (permalink / raw) To: Jerin Jacob, Kiran Kumar K, Nithin Dabilpuram, Zhirun Yan, Robin Jarry, Christophe Fontaine Cc: dev, Nitin Saxena, Pavan Nikhilesh Added option in graph create to call feature-specific process node functions. This removes extra overhead for checking feature arc status in nodes where application is not using feature arc processing Signed-off-by: Pavan Nikhilesh <pbhagavatula@marvell.com> Signed-off-by: Nitin Saxena <nsaxena@marvell.com> --- doc/guides/rel_notes/release_24_11.rst | 7 +++++++ lib/graph/graph.c | 1 + lib/graph/graph_populate.c | 7 ++++++- lib/graph/graph_private.h | 3 +++ lib/graph/node.c | 2 ++ lib/graph/rte_graph.h | 3 +++ 6 files changed, 22 insertions(+), 1 deletion(-) diff --git a/doc/guides/rel_notes/release_24_11.rst b/doc/guides/rel_notes/release_24_11.rst index 1299de886a..451627a331 100644 --- a/doc/guides/rel_notes/release_24_11.rst +++ b/doc/guides/rel_notes/release_24_11.rst @@ -251,6 +251,13 @@ ABI Changes * eventdev: Added ``preschedule_type`` field to ``rte_event_dev_config`` structure. +* graph: Added feature arc specific `feat_arc_proc` node callback function in + `struct rte_node_register`. If this function is not NULL and + `feature_arc_enable` is set to `true` in `struct rte_graph_param`, + rte_graph_walk() calls `feat_arc_proc` callback function instead of `process` + +* graph: Added `feature_arc_enable` parameter in `struct rte_graph_param` for + calling non-NULL `feat_arc_proc` callback function by `rte_graph_walk()` Known Issues ------------ diff --git a/lib/graph/graph.c b/lib/graph/graph.c index dff8e690a8..a764c5824e 100644 --- a/lib/graph/graph.c +++ b/lib/graph/graph.c @@ -455,6 +455,7 @@ rte_graph_create(const char *name, struct rte_graph_param *prm) graph->parent_id = RTE_GRAPH_ID_INVALID; graph->lcore_id = RTE_MAX_LCORE; graph->num_pkt_to_capture = prm->num_pkt_to_capture; + graph->feature_arc_enabled = prm->feature_arc_enable; if (prm->pcap_filename) rte_strscpy(graph->pcap_filename, prm->pcap_filename, RTE_GRAPH_PCAP_FILE_SZ); diff --git a/lib/graph/graph_populate.c b/lib/graph/graph_populate.c index ed596a7711..5d8aa7b903 100644 --- a/lib/graph/graph_populate.c +++ b/lib/graph/graph_populate.c @@ -79,8 +79,13 @@ graph_nodes_populate(struct graph *_graph) if (graph_pcap_is_enable()) { node->process = graph_pcap_dispatch; node->original_process = graph_node->node->process; - } else + if (_graph->feature_arc_enabled && graph_node->node->feat_arc_proc) + node->original_process = graph_node->node->feat_arc_proc; + } else { node->process = graph_node->node->process; + if (_graph->feature_arc_enabled && graph_node->node->feat_arc_proc) + node->process = graph_node->node->feat_arc_proc; + } memcpy(node->name, graph_node->node->name, RTE_GRAPH_NAMESIZE); pid = graph_node->node->parent_id; if (pid != RTE_NODE_ID_INVALID) { /* Cloned node */ diff --git a/lib/graph/graph_private.h b/lib/graph/graph_private.h index d557d55f2d..58ba0abeff 100644 --- a/lib/graph/graph_private.h +++ b/lib/graph/graph_private.h @@ -56,6 +56,7 @@ struct node { unsigned int lcore_id; /**< Node runs on the Lcore ID used for mcore dispatch model. */ rte_node_process_t process; /**< Node process function. */ + rte_node_process_t feat_arc_proc; /**< Node feature-arch process function. */ rte_node_init_t init; /**< Node init function. */ rte_node_fini_t fini; /**< Node fini function. */ rte_node_t id; /**< Allocated identifier for the node. */ @@ -126,6 +127,8 @@ struct graph { /**< Number of packets to be captured per core. */ char pcap_filename[RTE_GRAPH_PCAP_FILE_SZ]; /**< pcap file name/path. */ + uint8_t feature_arc_enabled; + /**< Graph feature arc. */ STAILQ_HEAD(gnode_list, graph_node) node_list; /**< Nodes in a graph. */ }; diff --git a/lib/graph/node.c b/lib/graph/node.c index 99a9622779..d8fd273543 100644 --- a/lib/graph/node.c +++ b/lib/graph/node.c @@ -90,6 +90,7 @@ __rte_node_register(const struct rte_node_register *reg) goto free; node->flags = reg->flags; node->process = reg->process; + node->feat_arc_proc = reg->feat_arc_proc; node->init = reg->init; node->fini = reg->fini; node->nb_edges = reg->nb_edges; @@ -137,6 +138,7 @@ node_clone(struct node *node, const char *name) /* Clone the source node */ reg->flags = node->flags; reg->process = node->process; + reg->feat_arc_proc = node->feat_arc_proc; reg->init = node->init; reg->fini = node->fini; reg->nb_edges = node->nb_edges; diff --git a/lib/graph/rte_graph.h b/lib/graph/rte_graph.h index ecfec2068a..f07272b308 100644 --- a/lib/graph/rte_graph.h +++ b/lib/graph/rte_graph.h @@ -172,6 +172,8 @@ struct rte_graph_param { uint32_t mp_capacity; /**< Capacity of memory pool for dispatch model. */ } dispatch; }; + + bool feature_arc_enable; /**< Enable Graph feature arc. */ }; /** @@ -470,6 +472,7 @@ struct rte_node_register { uint64_t flags; /**< Node configuration flag. */ #define RTE_NODE_SOURCE_F (1ULL << 0) /**< Node type is source. */ rte_node_process_t process; /**< Node process function. */ + rte_node_process_t feat_arc_proc; /**< Node feature-arc specific process function. */ rte_node_init_t init; /**< Node init function. */ rte_node_fini_t fini; /**< Node fini function. */ rte_node_t id; /**< Node Identifier. */ -- 2.43.0 ^ permalink raw reply [flat|nested] 46+ messages in thread
* [PATCH v5 3/5] graph: add IPv4 output feature arc 2024-10-14 14:33 ` [PATCH v5 0/5] add feature arc in rte_graph Nitin Saxena 2024-10-14 14:33 ` [PATCH v5 1/5] graph: add feature arc support Nitin Saxena 2024-10-14 14:33 ` [PATCH v5 2/5] graph: add feature arc option in graph create Nitin Saxena @ 2024-10-14 14:33 ` Nitin Saxena 2024-10-14 14:33 ` [PATCH v5 4/5] test/graph_feature_arc: add functional tests Nitin Saxena 2024-10-14 14:33 ` [PATCH v5 5/5] docs: add programming guide for feature arc Nitin Saxena 4 siblings, 0 replies; 46+ messages in thread From: Nitin Saxena @ 2024-10-14 14:33 UTC (permalink / raw) To: Jerin Jacob, Kiran Kumar K, Nithin Dabilpuram, Zhirun Yan, Robin Jarry, Christophe Fontaine Cc: dev, Nitin Saxena add ipv4-output feature arc in ipv4-rewrite node to allow custom/standard nodes(like outbound IPsec policy node) in outgoing forwarding path Signed-off-by: Nitin Saxena <nsaxena@marvell.com> --- lib/node/ip4_rewrite.c | 476 +++++++++++++++++++++++++++++------- lib/node/ip4_rewrite_priv.h | 15 +- lib/node/node_private.h | 20 +- lib/node/rte_node_ip4_api.h | 3 + 4 files changed, 417 insertions(+), 97 deletions(-) diff --git a/lib/node/ip4_rewrite.c b/lib/node/ip4_rewrite.c index 34a920df5e..824ef9a4cd 100644 --- a/lib/node/ip4_rewrite.c +++ b/lib/node/ip4_rewrite.c @@ -15,39 +15,156 @@ #include "ip4_rewrite_priv.h" #include "node_private.h" +#define ALL_PKT_MASK 0xf + struct ip4_rewrite_node_ctx { + rte_graph_feature_arc_t output_feature_arc; /* Dynamic offset to mbuf priv1 */ int mbuf_priv1_off; /* Cached next index */ uint16_t next_index; + uint16_t last_tx; }; +typedef struct rewrite_priv_vars { + union { + struct { + rte_xmm_t xmm1; + }; + struct __rte_packed { + uint16_t next0; + uint16_t next1; + uint16_t next2; + uint16_t next3; + uint16_t last_tx_interface; + uint16_t last_if_feature; + uint16_t actual_feat_mask; + uint16_t speculative_feat_mask; + }; + }; +} rewrite_priv_vars_t; + static struct ip4_rewrite_node_main *ip4_rewrite_nm; #define IP4_REWRITE_NODE_LAST_NEXT(ctx) \ (((struct ip4_rewrite_node_ctx *)ctx)->next_index) +#define IP4_REWRITE_NODE_LAST_TX(ctx) \ + (((struct ip4_rewrite_node_ctx *)ctx)->last_tx) + #define IP4_REWRITE_NODE_PRIV1_OFF(ctx) \ (((struct ip4_rewrite_node_ctx *)ctx)->mbuf_priv1_off) -static uint16_t -ip4_rewrite_node_process(struct rte_graph *graph, struct rte_node *node, - void **objs, uint16_t nb_objs) +#define IP4_REWRITE_NODE_OUTPUT_FEATURE_ARC(ctx) \ + (((struct ip4_rewrite_node_ctx *)ctx)->output_feature_arc) + +static __rte_always_inline void +prefetch_mbuf_and_dynfield(struct rte_mbuf *mbuf) { + /* prefetch first cache line required for accessing buf_addr */ + rte_prefetch0((void *)mbuf); +} + +static __rte_always_inline void +check_output_feature_x4(struct rte_graph_feature_arc *arc, + const rte_graph_feature_rt_list_t flist, + rewrite_priv_vars_t *pvar, struct node_mbuf_priv1 *priv0, + struct node_mbuf_priv1 *priv1, struct node_mbuf_priv1 *priv2, + struct node_mbuf_priv1 *priv3) +{ + uint32_t mask = 0; + uint16_t xor = 0; + + /* + * interface edge's start from 1 and not from 0 as "pkt_drop" + * is next node at 0th index + */ + priv0->if_index = pvar->next0 - 1; + priv1->if_index = pvar->next1 - 1; + priv2->if_index = pvar->next2 - 1; + priv3->if_index = pvar->next3 - 1; + + /* Find out if all packets are sent to last_tx_interface */ + xor = pvar->last_tx_interface ^ priv0->if_index; + xor += priv0->if_index ^ priv1->if_index; + xor += priv1->if_index ^ priv2->if_index; + xor += priv2->if_index ^ priv3->if_index; + + if (likely(!xor)) { + /* copy last interface feature and feature mask */ + priv0->current_feature = priv1->current_feature = + priv2->current_feature = priv3->current_feature = + pvar->last_if_feature; + pvar->actual_feat_mask = pvar->speculative_feat_mask; + } else { + /* create a mask for index which does not have feature + * Also override next edge and if feature enabled, get feature + */ + mask = rte_graph_feature_arc_feature_set(arc, flist, priv0->if_index, + &priv0->current_feature, + &pvar->next0); + + mask |= ((rte_graph_feature_arc_feature_set(arc, flist, priv1->if_index, + &priv1->current_feature, + &pvar->next1)) << 1); + + mask |= ((rte_graph_feature_arc_feature_set(arc, flist, priv2->if_index, + &priv2->current_feature, + &pvar->next2)) << 2); + + mask |= ((rte_graph_feature_arc_feature_set(arc, flist, priv3->if_index, + &priv3->current_feature, + &pvar->next3)) << 3); + + /* + * add last tx and last feature regardless even if feature is + * valid or not + */ + pvar->last_tx_interface = priv3->if_index; + pvar->last_if_feature = priv3->current_feature; + /* Set 0xf if invalid feature to last packet, else 0 */ + pvar->speculative_feat_mask = (priv3->current_feature == + RTE_GRAPH_FEATURE_INVALID) ? ALL_PKT_MASK : 0x0; + pvar->actual_feat_mask = mask; + } +} + +static __rte_always_inline uint16_t +__ip4_rewrite_node_process(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs, + const int dyn, const int check_enabled_features, + struct rte_graph_feature_arc *out_feature_arc, + const rte_graph_feature_rt_list_t flist) +{ + struct node_mbuf_priv1 *priv0 = NULL, *priv1 = NULL, *priv2 = NULL, *priv3 = NULL; struct rte_mbuf *mbuf0, *mbuf1, *mbuf2, *mbuf3, **pkts; struct ip4_rewrite_nh_header *nh = ip4_rewrite_nm->nh; - const int dyn = IP4_REWRITE_NODE_PRIV1_OFF(node->ctx); - uint16_t next0, next1, next2, next3, next_index; - struct rte_ipv4_hdr *ip0, *ip1, *ip2, *ip3; uint16_t n_left_from, held = 0, last_spec = 0; + struct rte_ipv4_hdr *ip0, *ip1, *ip2, *ip3; + rewrite_priv_vars_t pvar; + int64_t fd0, fd1, fd2, fd3; + rte_edge_t fix_spec = 0; void *d0, *d1, *d2, *d3; void **to_next, **from; + uint16_t next_index; rte_xmm_t priv01; rte_xmm_t priv23; int i; - /* Speculative next as last next */ + RTE_SET_USED(fd0); + RTE_SET_USED(fd1); + RTE_SET_USED(fd2); + RTE_SET_USED(fd3); + + /* Initialize speculative variables.*/ + + /* Last interface */ + pvar.last_tx_interface = IP4_REWRITE_NODE_LAST_TX(node->ctx); + /*last next from node ctx*/ next_index = IP4_REWRITE_NODE_LAST_NEXT(node->ctx); + pvar.speculative_feat_mask = ALL_PKT_MASK; + pvar.actual_feat_mask = 0; + rte_prefetch0(nh); pkts = (struct rte_mbuf **)objs; @@ -55,20 +172,47 @@ ip4_rewrite_node_process(struct rte_graph *graph, struct rte_node *node, n_left_from = nb_objs; for (i = 0; i < 4 && i < n_left_from; i++) - rte_prefetch0(pkts[i]); + prefetch_mbuf_and_dynfield(pkts[i]); /* Get stream for the speculated next node */ to_next = rte_node_next_stream_get(graph, node, next_index, nb_objs); + + /* prefetch speculative feature and corresponding data */ + if (check_enabled_features) { + /* + * Get first feature enabled, if any, on last_tx_interface + */ + if (unlikely(rte_graph_feature_arc_first_feature_get(out_feature_arc, + flist, + pvar.last_tx_interface, + (rte_graph_feature_t *) + &pvar.last_if_feature))) { + /* prefetch feature cache line */ + rte_graph_feature_arc_feature_prefetch(out_feature_arc, flist, + pvar.last_if_feature); + + /* prefetch feature data cache line */ + rte_graph_feature_arc_data_prefetch(out_feature_arc, flist, + pvar.last_if_feature, + pvar.last_tx_interface); + /* + * Set speculativa_feat mask to indicate, all 4 packets + * going to feature path + */ + pvar.speculative_feat_mask = 0; + } + } + /* Update Ethernet header of pkts */ while (n_left_from >= 4) { if (likely(n_left_from > 7)) { /* Prefetch only next-mbuf struct and priv area. * Data need not be prefetched as we only write. */ - rte_prefetch0(pkts[4]); - rte_prefetch0(pkts[5]); - rte_prefetch0(pkts[6]); - rte_prefetch0(pkts[7]); + prefetch_mbuf_and_dynfield(pkts[4]); + prefetch_mbuf_and_dynfield(pkts[5]); + prefetch_mbuf_and_dynfield(pkts[6]); + prefetch_mbuf_and_dynfield(pkts[7]); } mbuf0 = pkts[0]; @@ -78,66 +222,138 @@ ip4_rewrite_node_process(struct rte_graph *graph, struct rte_node *node, pkts += 4; n_left_from -= 4; + + /* Copy mbuf private data into private variables */ priv01.u64[0] = node_mbuf_priv1(mbuf0, dyn)->u; priv01.u64[1] = node_mbuf_priv1(mbuf1, dyn)->u; priv23.u64[0] = node_mbuf_priv1(mbuf2, dyn)->u; priv23.u64[1] = node_mbuf_priv1(mbuf3, dyn)->u; - /* Increment checksum by one. */ - priv01.u32[1] += rte_cpu_to_be_16(0x0100); - priv01.u32[3] += rte_cpu_to_be_16(0x0100); - priv23.u32[1] += rte_cpu_to_be_16(0x0100); - priv23.u32[3] += rte_cpu_to_be_16(0x0100); - - /* Update ttl,cksum rewrite ethernet hdr on mbuf0 */ - d0 = rte_pktmbuf_mtod(mbuf0, void *); - rte_memcpy(d0, nh[priv01.u16[0]].rewrite_data, - nh[priv01.u16[0]].rewrite_len); - - next0 = nh[priv01.u16[0]].tx_node; - ip0 = (struct rte_ipv4_hdr *)((uint8_t *)d0 + - sizeof(struct rte_ether_hdr)); - ip0->time_to_live = priv01.u16[1] - 1; - ip0->hdr_checksum = priv01.u16[2] + priv01.u16[3]; - - /* Update ttl,cksum rewrite ethernet hdr on mbuf1 */ - d1 = rte_pktmbuf_mtod(mbuf1, void *); - rte_memcpy(d1, nh[priv01.u16[4]].rewrite_data, - nh[priv01.u16[4]].rewrite_len); - - next1 = nh[priv01.u16[4]].tx_node; - ip1 = (struct rte_ipv4_hdr *)((uint8_t *)d1 + - sizeof(struct rte_ether_hdr)); - ip1->time_to_live = priv01.u16[5] - 1; - ip1->hdr_checksum = priv01.u16[6] + priv01.u16[7]; - - /* Update ttl,cksum rewrite ethernet hdr on mbuf2 */ - d2 = rte_pktmbuf_mtod(mbuf2, void *); - rte_memcpy(d2, nh[priv23.u16[0]].rewrite_data, - nh[priv23.u16[0]].rewrite_len); - next2 = nh[priv23.u16[0]].tx_node; - ip2 = (struct rte_ipv4_hdr *)((uint8_t *)d2 + - sizeof(struct rte_ether_hdr)); - ip2->time_to_live = priv23.u16[1] - 1; - ip2->hdr_checksum = priv23.u16[2] + priv23.u16[3]; - - /* Update ttl,cksum rewrite ethernet hdr on mbuf3 */ - d3 = rte_pktmbuf_mtod(mbuf3, void *); - rte_memcpy(d3, nh[priv23.u16[4]].rewrite_data, - nh[priv23.u16[4]].rewrite_len); - - next3 = nh[priv23.u16[4]].tx_node; - ip3 = (struct rte_ipv4_hdr *)((uint8_t *)d3 + - sizeof(struct rte_ether_hdr)); - ip3->time_to_live = priv23.u16[5] - 1; - ip3->hdr_checksum = priv23.u16[6] + priv23.u16[7]; + /* Copy next edge from next hop */ + pvar.next0 = nh[priv01.u16[0]].tx_node; + pvar.next1 = nh[priv01.u16[4]].tx_node; + pvar.next2 = nh[priv23.u16[0]].tx_node; + pvar.next3 = nh[priv23.u16[4]].tx_node; + + if (check_enabled_features) { + priv0 = node_mbuf_priv1(mbuf0, dyn); + priv1 = node_mbuf_priv1(mbuf1, dyn); + priv2 = node_mbuf_priv1(mbuf2, dyn); + priv3 = node_mbuf_priv1(mbuf3, dyn); + + /* If feature is enabled, override next edge for each mbuf + * and set node_mbuf_priv data appropriately + */ + check_output_feature_x4(out_feature_arc, flist, + &pvar, priv0, priv1, priv2, priv3); + + /* check_output_feature_x4() returns bit mask which indicates + * which packet is not following feature path, hence normal processing + * has to happen on them + */ + if (unlikely(pvar.actual_feat_mask)) { + if (pvar.actual_feat_mask & 0x1) { + priv01.u32[1] += rte_cpu_to_be_16(0x0100); + /* Update ttl,cksum rewrite ethernet hdr on mbuf0 */ + d0 = rte_pktmbuf_mtod(mbuf0, void *); + rte_memcpy(d0, nh[priv01.u16[0]].rewrite_data, + nh[priv01.u16[0]].rewrite_len); + ip0 = (struct rte_ipv4_hdr *)((uint8_t *)d0 + + sizeof(struct rte_ether_hdr)); + ip0->time_to_live = priv01.u16[1] - 1; + ip0->hdr_checksum = priv01.u16[2] + priv01.u16[3]; + } + if (pvar.actual_feat_mask & 0x2) { + priv01.u32[3] += rte_cpu_to_be_16(0x0100); + /* Update ttl,cksum rewrite ethernet hdr on mbuf1 */ + d1 = rte_pktmbuf_mtod(mbuf1, void *); + rte_memcpy(d1, nh[priv01.u16[4]].rewrite_data, + nh[priv01.u16[4]].rewrite_len); + + ip1 = (struct rte_ipv4_hdr *)((uint8_t *)d1 + + sizeof(struct rte_ether_hdr)); + ip1->time_to_live = priv01.u16[5] - 1; + ip1->hdr_checksum = priv01.u16[6] + priv01.u16[7]; + } + if (pvar.actual_feat_mask & 0x4) { + priv23.u32[1] += rte_cpu_to_be_16(0x0100); + /* Update ttl,cksum rewrite ethernet hdr on mbuf2 */ + d2 = rte_pktmbuf_mtod(mbuf2, void *); + rte_memcpy(d2, nh[priv23.u16[0]].rewrite_data, + nh[priv23.u16[0]].rewrite_len); + ip2 = (struct rte_ipv4_hdr *)((uint8_t *)d2 + + sizeof(struct rte_ether_hdr)); + ip2->time_to_live = priv23.u16[1] - 1; + ip2->hdr_checksum = priv23.u16[2] + priv23.u16[3]; + } + if (pvar.actual_feat_mask & 0x8) { + priv23.u32[3] += rte_cpu_to_be_16(0x0100); + /* Update ttl,cksum rewrite ethernet hdr on mbuf3 */ + d3 = rte_pktmbuf_mtod(mbuf3, void *); + rte_memcpy(d3, nh[priv23.u16[4]].rewrite_data, + nh[priv23.u16[4]].rewrite_len); + ip3 = (struct rte_ipv4_hdr *)((uint8_t *)d3 + + sizeof(struct rte_ether_hdr)); + ip3->time_to_live = priv23.u16[5] - 1; + ip3->hdr_checksum = priv23.u16[6] + priv23.u16[7]; + } + } + } else { + /* Case when no feature is enabled */ + + /* Increment checksum by one. */ + priv01.u32[1] += rte_cpu_to_be_16(0x0100); + priv01.u32[3] += rte_cpu_to_be_16(0x0100); + priv23.u32[1] += rte_cpu_to_be_16(0x0100); + priv23.u32[3] += rte_cpu_to_be_16(0x0100); + + /* Update ttl,cksum rewrite ethernet hdr on mbuf0 */ + d0 = rte_pktmbuf_mtod(mbuf0, void *); + rte_memcpy(d0, nh[priv01.u16[0]].rewrite_data, + nh[priv01.u16[0]].rewrite_len); + + ip0 = (struct rte_ipv4_hdr *)((uint8_t *)d0 + + sizeof(struct rte_ether_hdr)); + ip0->time_to_live = priv01.u16[1] - 1; + ip0->hdr_checksum = priv01.u16[2] + priv01.u16[3]; + + /* Update ttl,cksum rewrite ethernet hdr on mbuf1 */ + d1 = rte_pktmbuf_mtod(mbuf1, void *); + rte_memcpy(d1, nh[priv01.u16[4]].rewrite_data, + nh[priv01.u16[4]].rewrite_len); + + ip1 = (struct rte_ipv4_hdr *)((uint8_t *)d1 + + sizeof(struct rte_ether_hdr)); + ip1->time_to_live = priv01.u16[5] - 1; + ip1->hdr_checksum = priv01.u16[6] + priv01.u16[7]; + + /* Update ttl,cksum rewrite ethernet hdr on mbuf2 */ + d2 = rte_pktmbuf_mtod(mbuf2, void *); + rte_memcpy(d2, nh[priv23.u16[0]].rewrite_data, + nh[priv23.u16[0]].rewrite_len); + ip2 = (struct rte_ipv4_hdr *)((uint8_t *)d2 + + sizeof(struct rte_ether_hdr)); + ip2->time_to_live = priv23.u16[1] - 1; + ip2->hdr_checksum = priv23.u16[2] + priv23.u16[3]; + + /* Update ttl,cksum rewrite ethernet hdr on mbuf3 */ + d3 = rte_pktmbuf_mtod(mbuf3, void *); + rte_memcpy(d3, nh[priv23.u16[4]].rewrite_data, + nh[priv23.u16[4]].rewrite_len); + + ip3 = (struct rte_ipv4_hdr *)((uint8_t *)d3 + + sizeof(struct rte_ether_hdr)); + ip3->time_to_live = priv23.u16[5] - 1; + ip3->hdr_checksum = priv23.u16[6] + priv23.u16[7]; + } /* Enqueue four to next node */ - rte_edge_t fix_spec = - ((next_index == next0) && (next0 == next1) && - (next1 == next2) && (next2 == next3)); + fix_spec = next_index ^ pvar.next0; + fix_spec += next_index ^ pvar.next1; + fix_spec += next_index ^ pvar.next2; + fix_spec += next_index ^ pvar.next3; - if (unlikely(fix_spec == 0)) { + if (unlikely(fix_spec != 0)) { /* Copy things successfully speculated till now */ rte_memcpy(to_next, from, last_spec * sizeof(from[0])); from += last_spec; @@ -146,56 +362,56 @@ ip4_rewrite_node_process(struct rte_graph *graph, struct rte_node *node, last_spec = 0; /* next0 */ - if (next_index == next0) { + if (next_index == pvar.next0) { to_next[0] = from[0]; to_next++; held++; } else { - rte_node_enqueue_x1(graph, node, next0, + rte_node_enqueue_x1(graph, node, pvar.next0, from[0]); } /* next1 */ - if (next_index == next1) { + if (next_index == pvar.next1) { to_next[0] = from[1]; to_next++; held++; } else { - rte_node_enqueue_x1(graph, node, next1, + rte_node_enqueue_x1(graph, node, pvar.next1, from[1]); } /* next2 */ - if (next_index == next2) { + if (next_index == pvar.next2) { to_next[0] = from[2]; to_next++; held++; } else { - rte_node_enqueue_x1(graph, node, next2, + rte_node_enqueue_x1(graph, node, pvar.next2, from[2]); } /* next3 */ - if (next_index == next3) { + if (next_index == pvar.next3) { to_next[0] = from[3]; to_next++; held++; } else { - rte_node_enqueue_x1(graph, node, next3, + rte_node_enqueue_x1(graph, node, pvar.next3, from[3]); } from += 4; /* Change speculation if last two are same */ - if ((next_index != next3) && (next2 == next3)) { + if ((next_index != pvar.next3) && (pvar.next2 == pvar.next3)) { /* Put the current speculated node */ rte_node_next_stream_put(graph, node, next_index, held); held = 0; /* Get next speculated stream */ - next_index = next3; + next_index = pvar.next3; to_next = rte_node_next_stream_get( graph, node, next_index, nb_objs); } @@ -212,20 +428,41 @@ ip4_rewrite_node_process(struct rte_graph *graph, struct rte_node *node, pkts += 1; n_left_from -= 1; - d0 = rte_pktmbuf_mtod(mbuf0, void *); - rte_memcpy(d0, nh[node_mbuf_priv1(mbuf0, dyn)->nh].rewrite_data, - nh[node_mbuf_priv1(mbuf0, dyn)->nh].rewrite_len); - - next0 = nh[node_mbuf_priv1(mbuf0, dyn)->nh].tx_node; - ip0 = (struct rte_ipv4_hdr *)((uint8_t *)d0 + - sizeof(struct rte_ether_hdr)); - chksum = node_mbuf_priv1(mbuf0, dyn)->cksum + - rte_cpu_to_be_16(0x0100); - chksum += chksum >= 0xffff; - ip0->hdr_checksum = chksum; - ip0->time_to_live = node_mbuf_priv1(mbuf0, dyn)->ttl - 1; - - if (unlikely(next_index ^ next0)) { + pvar.next0 = nh[node_mbuf_priv1(mbuf0, dyn)->nh].tx_node; + if (check_enabled_features) { + priv0 = node_mbuf_priv1(mbuf0, dyn); + if (pvar.next0 != (pvar.last_tx_interface + 1)) { + priv0->if_index = pvar.next0 - 1; + rte_graph_feature_arc_feature_set(out_feature_arc, flist, + priv0->if_index, + &priv0->current_feature, + &pvar.next0); + pvar.last_tx_interface = priv0->if_index; + pvar.last_if_feature = priv0->current_feature; + } else { + /* current mbuf index is same as last_tx_interface */ + priv0->if_index = pvar.last_tx_interface; + priv0->current_feature = pvar.last_if_feature; + } + } + /* Do the needful if either feature arc is disabled OR + * Invalid feature is present + */ + if (!check_enabled_features || + (priv0->current_feature == RTE_GRAPH_FEATURE_INVALID)) { + d0 = rte_pktmbuf_mtod(mbuf0, void *); + rte_memcpy(d0, nh[node_mbuf_priv1(mbuf0, dyn)->nh].rewrite_data, + nh[node_mbuf_priv1(mbuf0, dyn)->nh].rewrite_len); + + ip0 = (struct rte_ipv4_hdr *)((uint8_t *)d0 + + sizeof(struct rte_ether_hdr)); + chksum = node_mbuf_priv1(mbuf0, dyn)->cksum + + rte_cpu_to_be_16(0x0100); + chksum += chksum >= 0xffff; + ip0->hdr_checksum = chksum; + ip0->time_to_live = node_mbuf_priv1(mbuf0, dyn)->ttl - 1; + } + if (unlikely(next_index ^ pvar.next0)) { /* Copy things successfully speculated till now */ rte_memcpy(to_next, from, last_spec * sizeof(from[0])); from += last_spec; @@ -233,13 +470,15 @@ ip4_rewrite_node_process(struct rte_graph *graph, struct rte_node *node, held += last_spec; last_spec = 0; - rte_node_enqueue_x1(graph, node, next0, from[0]); + rte_node_enqueue_x1(graph, node, pvar.next0, from[0]); from += 1; } else { last_spec += 1; } } + IP4_REWRITE_NODE_LAST_TX(node->ctx) = pvar.last_tx_interface; + /* !!! Home run !!! */ if (likely(last_spec == nb_objs)) { rte_node_next_stream_move(graph, node, next_index); @@ -255,22 +494,78 @@ ip4_rewrite_node_process(struct rte_graph *graph, struct rte_node *node, return nb_objs; } +static uint16_t +ip4_rewrite_feature_node_process(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + struct rte_graph_feature_arc *arc = + rte_graph_feature_arc_get(IP4_REWRITE_NODE_OUTPUT_FEATURE_ARC(node->ctx)); + const int dyn = IP4_REWRITE_NODE_PRIV1_OFF(node->ctx); + rte_graph_feature_rt_list_t flist; + + /* If any feature is enabled on this arc */ + if (unlikely(rte_graph_feature_arc_has_any_feature(arc, &flist))) { + if (flist) + return __ip4_rewrite_node_process(graph, node, objs, nb_objs, + dyn, + 1 /* check features */, arc, + (rte_graph_feature_rt_list_t)1); + else + return __ip4_rewrite_node_process(graph, node, objs, nb_objs, + dyn, + 1 /* check features */, arc, + (rte_graph_feature_rt_list_t)0); + } else { + return __ip4_rewrite_node_process(graph, node, objs, nb_objs, dyn, + 0/* don't check features*/, NULL, + 0/* don't care */); + } + return 0; +} + +static uint16_t +ip4_rewrite_node_process(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + const int dyn = IP4_REWRITE_NODE_PRIV1_OFF(node->ctx); + + return __ip4_rewrite_node_process(graph, node, objs, nb_objs, dyn, + 0/* don't check features*/, NULL, + 0/* don't care */); +} + static int ip4_rewrite_node_init(const struct rte_graph *graph, struct rte_node *node) { + rte_graph_feature_arc_t feature_arc = RTE_GRAPH_FEATURE_ARC_INITIALIZER; static bool init_once; RTE_SET_USED(graph); RTE_BUILD_BUG_ON(sizeof(struct ip4_rewrite_node_ctx) > RTE_NODE_CTX_SZ); + RTE_BUILD_BUG_ON(sizeof(struct ip4_rewrite_nh_header) != RTE_CACHE_LINE_SIZE); if (!init_once) { node_mbuf_priv1_dynfield_offset = rte_mbuf_dynfield_register( &node_mbuf_priv1_dynfield_desc); if (node_mbuf_priv1_dynfield_offset < 0) return -rte_errno; - init_once = true; + + /* Create ipv4-output feature arc, if not created + */ + if (rte_graph_feature_arc_lookup_by_name(RTE_IP4_OUTPUT_FEATURE_ARC_NAME, + NULL) < 0) { + if (rte_graph_feature_arc_create(RTE_IP4_OUTPUT_FEATURE_ARC_NAME, + RTE_GRAPH_FEATURE_MAX_PER_ARC, + RTE_MAX_ETHPORTS, + ip4_rewrite_node_get(), &feature_arc)) { + return -rte_errno; + } + init_once = true; + } } IP4_REWRITE_NODE_PRIV1_OFF(node->ctx) = node_mbuf_priv1_dynfield_offset; + IP4_REWRITE_NODE_OUTPUT_FEATURE_ARC(node->ctx) = feature_arc; + IP4_REWRITE_NODE_LAST_TX(node->ctx) = UINT16_MAX; node_dbg("ip4_rewrite", "Initialized ip4_rewrite node initialized"); @@ -329,6 +624,7 @@ rte_node_ip4_rewrite_add(uint16_t next_hop, uint8_t *rewrite_data, static struct rte_node_register ip4_rewrite_node = { .process = ip4_rewrite_node_process, + .feat_arc_proc = ip4_rewrite_feature_node_process, .name = "ip4_rewrite", /* Default edge i.e '0' is pkt drop */ .nb_edges = 1, diff --git a/lib/node/ip4_rewrite_priv.h b/lib/node/ip4_rewrite_priv.h index 5105ec1d29..52f39601bd 100644 --- a/lib/node/ip4_rewrite_priv.h +++ b/lib/node/ip4_rewrite_priv.h @@ -5,9 +5,11 @@ #define __INCLUDE_IP4_REWRITE_PRIV_H__ #include <rte_common.h> +#include <rte_graph_feature_arc.h> #define RTE_GRAPH_IP4_REWRITE_MAX_NH 64 -#define RTE_GRAPH_IP4_REWRITE_MAX_LEN 56 +#define RTE_GRAPH_IP4_REWRITE_MAX_LEN (sizeof(struct rte_ether_hdr) + \ + (2 * sizeof(struct rte_vlan_hdr))) /** * @internal @@ -15,11 +17,9 @@ * Ipv4 rewrite next hop header data structure. Used to store port specific * rewrite data. */ -struct ip4_rewrite_nh_header { - uint16_t rewrite_len; /**< Header rewrite length. */ +struct __rte_cache_aligned ip4_rewrite_nh_header { uint16_t tx_node; /**< Tx node next index identifier. */ - uint16_t enabled; /**< NH enable flag */ - uint16_t rsvd; + uint16_t rewrite_len; /**< Header rewrite length. */ union { struct { struct rte_ether_addr dst; @@ -30,8 +30,13 @@ struct ip4_rewrite_nh_header { uint8_t rewrite_data[RTE_GRAPH_IP4_REWRITE_MAX_LEN]; /**< Generic rewrite data */ }; + /* used in control path */ + uint8_t enabled; /**< NH enable flag */ }; +_Static_assert(sizeof(struct ip4_rewrite_nh_header) <= (size_t)RTE_CACHE_LINE_SIZE, + "ip4_rewrite_nh_header size must be less or equal to cache line"); + /** * @internal * diff --git a/lib/node/node_private.h b/lib/node/node_private.h index 1de7306792..25db04a9a6 100644 --- a/lib/node/node_private.h +++ b/lib/node/node_private.h @@ -12,6 +12,9 @@ #include <rte_mbuf.h> #include <rte_mbuf_dyn.h> +#include <rte_graph_worker_common.h> +#include <rte_graph_feature_arc_worker.h> + extern int rte_node_logtype; #define RTE_LOGTYPE_NODE rte_node_logtype @@ -29,15 +32,28 @@ extern int rte_node_logtype; */ struct node_mbuf_priv1 { union { - /* IP4/IP6 rewrite */ + /** + * IP4/IP6 rewrite + * only used to pass lookup data from + * ip4-lookup to ip4-rewrite + */ struct { uint16_t nh; uint16_t ttl; uint32_t cksum; }; - uint64_t u; }; + /** + * Feature arc data + */ + struct { + /** interface index */ + uint16_t if_index; + /** feature that current mbuf holds */ + rte_graph_feature_t current_feature; + uint8_t rsvd; + }; }; static const struct rte_mbuf_dynfield node_mbuf_priv1_dynfield_desc = { diff --git a/lib/node/rte_node_ip4_api.h b/lib/node/rte_node_ip4_api.h index 950751a525..da4995662a 100644 --- a/lib/node/rte_node_ip4_api.h +++ b/lib/node/rte_node_ip4_api.h @@ -19,6 +19,7 @@ #include <rte_compat.h> #include <rte_graph.h> +#include <rte_graph_feature_arc_worker.h> #ifdef __cplusplus extern "C" { @@ -67,6 +68,8 @@ struct rte_node_ip4_reassembly_cfg { /**< Node identifier to configure. */ }; +#define RTE_IP4_OUTPUT_FEATURE_ARC_NAME "ipv4-output" + /** * Add ipv4 route to lookup table. * -- 2.43.0 ^ permalink raw reply [flat|nested] 46+ messages in thread
* [PATCH v5 4/5] test/graph_feature_arc: add functional tests 2024-10-14 14:33 ` [PATCH v5 0/5] add feature arc in rte_graph Nitin Saxena ` (2 preceding siblings ...) 2024-10-14 14:33 ` [PATCH v5 3/5] graph: add IPv4 output feature arc Nitin Saxena @ 2024-10-14 14:33 ` Nitin Saxena 2024-10-14 19:54 ` Stephen Hemminger 2024-10-14 14:33 ` [PATCH v5 5/5] docs: add programming guide for feature arc Nitin Saxena 4 siblings, 1 reply; 46+ messages in thread From: Nitin Saxena @ 2024-10-14 14:33 UTC (permalink / raw) To: Jerin Jacob, Kiran Kumar K, Nithin Dabilpuram, Zhirun Yan, Robin Jarry, Christophe Fontaine Cc: dev, Nitin Saxena Added functional unit test case for verifying feature arc control plane and fast path APIs How to run: $ echo "graph_feature_arc_autotest" | ./bin/dpdk-test Signed-off-by: Nitin Saxena <nsaxena@marvell.com> --- app/test/meson.build | 1 + app/test/test_graph_feature_arc.c | 1410 +++++++++++++++++++++++++++++ 2 files changed, 1411 insertions(+) create mode 100644 app/test/test_graph_feature_arc.c diff --git a/app/test/meson.build b/app/test/meson.build index e29258e6ec..740fa1bfb4 100644 --- a/app/test/meson.build +++ b/app/test/meson.build @@ -90,6 +90,7 @@ source_file_deps = { 'test_func_reentrancy.c': ['hash', 'lpm'], 'test_graph.c': ['graph'], 'test_graph_perf.c': ['graph'], + 'test_graph_feature_arc.c': ['graph'], 'test_hash.c': ['net', 'hash'], 'test_hash_functions.c': ['hash'], 'test_hash_multiwriter.c': ['hash'], diff --git a/app/test/test_graph_feature_arc.c b/app/test/test_graph_feature_arc.c new file mode 100644 index 0000000000..58b676e215 --- /dev/null +++ b/app/test/test_graph_feature_arc.c @@ -0,0 +1,1410 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(C) 2024 Marvell International Ltd. + */ + +#include "test.h" + +#include <assert.h> +#include <inttypes.h> +#include <signal.h> +#include <stdalign.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> + +#include <rte_errno.h> + +#ifndef RTE_EXEC_ENV_WINDOWS +#include <rte_graph.h> +#include <rte_graph_worker.h> +#include <rte_mbuf.h> +#include <rte_mbuf_dyn.h> +#include <rte_random.h> +#include <rte_graph_feature_arc.h> +#include <rte_graph_feature_arc_worker.h> + +#define MBUFF_SIZE 512 +#define TEST_ARC1_NAME "arc1" +#define TEST_ARC2_NAME "arc2" +#define MAX_INDEXES 10 +#define MAX_FEATURES 5 + +#define SOURCE1 "test_node_arc_source1" +#define INPUT_STATIC "test_node_arc_input_static" +#define OUTPUT_STATIC "test_node_arc_output_static" +#define PKT_FREE_STATIC "test_node_arc_pkt_free_static" +#define ARC1_FEATURE1 "test_node_arc1_feature1" +#define ARC1_FEATURE2 "test_node_arc1_feature2" +#define ARC2_FEATURE1 "test_node_arc2_feature1" +#define ARC2_FEATURE2 "test_node_arc2_feature2" +#define ARC2_FEATURE3 "test_node_arc2_feature3" +#define DUMMY1_STATIC "test_node_arc_dummy1_static" +#define DUMMY2_STATIC "test_node_arc_dummy2_static" + +/* (Node index, Node Name, feature user data base */ +#define FOREACH_TEST_NODE_ARC { \ + R(0, SOURCE1, 64) \ + R(1, INPUT_STATIC, 128) \ + R(2, OUTPUT_STATIC, 256) \ + R(3, PKT_FREE_STATIC, 512) \ + R(4, ARC1_FEATURE1, 1024) \ + R(5, ARC1_FEATURE2, 2048) \ + R(6, ARC2_FEATURE1, 4096) \ + R(7, ARC2_FEATURE2, 8192) \ + R(8, ARC2_FEATURE3, 16384) \ + R(9, DUMMY1_STATIC, 32768) \ + R(10, DUMMY2_STATIC, 65536) \ + } + +/** + * ARC1: Feature arc on ingress interface + * ARC2: Feature arc on egress interface + * XX_static: Static nodes + * XX_featureX: Feature X on arc + * + * -----> ARC1_FEATURE1 + * | | | + * | | v + * | | ARC1_FEATURE2 + * | | | + * | v v + * SOURCE1 ->-----> INPUT_STATIC --> OUTPUT_STATIC -----> PKT_FREE_STATIC + * | | | ^ ^ ^ + * | | | | | | + * | | --> ARC2_FEATURE1 | | + * | | ^ ^ | | + * | | | | | | + * | ----------c-> ARC2_FEATURE2 | + * | | ^ | + * | | | | + * ----------> ARC2_FEATURE3 ------- + */ +const char *node_names_feature_arc[] = { + SOURCE1, INPUT_STATIC, OUTPUT_STATIC, PKT_FREE_STATIC, + ARC1_FEATURE1, ARC1_FEATURE2, ARC2_FEATURE1, ARC2_FEATURE2, ARC2_FEATURE3, + DUMMY1_STATIC, DUMMY2_STATIC +}; + +#define MAX_NODES RTE_DIM(node_names_feature_arc) + +/* Function declarations */ +static uint16_t +source1_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs); +static uint16_t +input_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs); +static uint16_t +input_fa_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs); +static uint16_t +output_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs); +static uint16_t +output_fa_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs); +static uint16_t +pkt_free_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs); +static uint16_t +pkt_free_fa_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs); +static uint16_t +dummy1_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs); +static uint16_t +dummy2_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs); +static uint16_t +arc1_feature1_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs); +static uint16_t +arc1_feature1_fa_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs); +static uint16_t +arc1_feature2_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs); +static uint16_t +arc1_feature2_fa_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs); +static uint16_t +arc2_feature1_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs); +static uint16_t +arc2_feature1_fa_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs); +static uint16_t +arc2_feature2_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs); +static uint16_t +arc2_feature2_fa_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs); +static uint16_t +arc2_feature3_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs); +static uint16_t +arc2_feature3_fa_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs); +static int +common_node_init(const struct rte_graph *graph, struct rte_node *node); + +typedef struct test_node_priv { + /* index from 0 - MAX_NODES -1 */ + uint8_t node_index; + + /* feature */ + rte_graph_feature_t feature; + + /* rte_graph node id */ + uint32_t node_id; + + rte_graph_feature_arc_t arc; +} test_node_priv_t; + +typedef struct { + rte_graph_feature_t feature; + uint16_t egress_interface; + uint16_t ingress_interface; +} graph_dynfield_t; + +static int graph_dynfield_offset = -1; +static rte_graph_feature_arc_t arcs[RTE_GRAPH_FEATURE_ARC_MAX + 128]; +static struct rte_mbuf mbuf[MAX_NODES + 1][MBUFF_SIZE]; +static void *mbuf_p[MAX_NODES + 1][MBUFF_SIZE]; +static rte_graph_t graph_id = RTE_GRAPH_ID_INVALID; + +const char *node_patterns_feature_arc[] = { + "test_node_arc*" +}; + +static int32_t +compute_unique_user_data(const char *parent, const char *child, uint32_t interface_index) +{ + uint32_t user_data = interface_index; + + RTE_SET_USED(parent); +#define R(idx, node, node_cookie) { \ + if (!strcmp(child, node)) { \ + user_data += node_cookie; \ + } \ + } + + FOREACH_TEST_NODE_ARC +#undef R + + return user_data; +} + +static int +get_edge(struct rte_node_register *parent_node, + struct rte_node_register *child_node, rte_edge_t *_edge) +{ + char **next_edges = NULL; + uint32_t count, i; + + count = rte_node_edge_get(parent_node->id, NULL); + + if (!count) + return -1; + + next_edges = malloc(count); + + if (!next_edges) + return -1; + + count = rte_node_edge_get(parent_node->id, next_edges); + for (i = 0; i < count; i++) { + if (strstr(child_node->name, next_edges[i])) { + if (_edge) + *_edge = (rte_edge_t)i; + + free(next_edges); + return 0; + } + } + free(next_edges); + + return -1; +} + +int +common_node_init(const struct rte_graph *graph, struct rte_node *node) +{ + test_node_priv_t *priv = (test_node_priv_t *)node->ctx; + + RTE_SET_USED(graph); + + priv->node_id = node->id; + priv->feature = RTE_GRAPH_FEATURE_INVALID; + priv->arc = RTE_GRAPH_FEATURE_ARC_INITIALIZER; + +#define R(idx, _name, user_data) { \ + if (!strcmp(node->name, _name)) { \ + priv->node_index = idx; \ + } \ + } + FOREACH_TEST_NODE_ARC +#undef R + + return 0; +} + +uint16_t +source1_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + RTE_SET_USED(graph); + RTE_SET_USED(node); + RTE_SET_USED(objs); + RTE_SET_USED(nb_objs); + return 0; +} + +static struct rte_node_register source1 = { + .name = SOURCE1, + .process = source1_fn, + .flags = RTE_NODE_SOURCE_F, + .nb_edges = 3, + .init = common_node_init, + .next_nodes = {INPUT_STATIC, DUMMY1_STATIC, DUMMY2_STATIC}, +}; +RTE_NODE_REGISTER(source1); + +uint16_t +input_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + RTE_SET_USED(graph); + RTE_SET_USED(node); + RTE_SET_USED(objs); + RTE_SET_USED(nb_objs); + return 0; +} + +uint16_t +input_fa_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + RTE_SET_USED(graph); + RTE_SET_USED(node); + RTE_SET_USED(objs); + RTE_SET_USED(nb_objs); + return 0; +} + +static struct rte_node_register input = { + .name = INPUT_STATIC, + .process = input_fn, + .feat_arc_proc = input_fa_fn, + .nb_edges = 2, + .init = common_node_init, + .next_nodes = {OUTPUT_STATIC, DUMMY1_STATIC}, +}; +RTE_NODE_REGISTER(input); + +uint16_t +output_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + RTE_SET_USED(graph); + RTE_SET_USED(node); + RTE_SET_USED(objs); + RTE_SET_USED(nb_objs); + return 0; +} + +uint16_t +output_fa_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + RTE_SET_USED(graph); + RTE_SET_USED(node); + RTE_SET_USED(objs); + RTE_SET_USED(nb_objs); + return 0; +} + +static struct rte_node_register output = { + .name = OUTPUT_STATIC, + .process = output_fn, + .feat_arc_proc = output_fa_fn, + .nb_edges = 3, + .init = common_node_init, + .next_nodes = {DUMMY1_STATIC, PKT_FREE_STATIC, DUMMY2_STATIC}, +}; +RTE_NODE_REGISTER(output); + +uint16_t +pkt_free_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + RTE_SET_USED(graph); + RTE_SET_USED(node); + RTE_SET_USED(objs); + RTE_SET_USED(nb_objs); + return 0; +} + +uint16_t +pkt_free_fa_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + RTE_SET_USED(graph); + RTE_SET_USED(node); + RTE_SET_USED(objs); + RTE_SET_USED(nb_objs); + return 0; +} + +static struct rte_node_register pkt_free = { + .name = PKT_FREE_STATIC, + .process = pkt_free_fn, + .feat_arc_proc = pkt_free_fa_fn, + .nb_edges = 1, + .init = common_node_init, + .next_nodes = {DUMMY1_STATIC}, +}; +RTE_NODE_REGISTER(pkt_free); + +uint16_t +dummy1_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + RTE_SET_USED(graph); + RTE_SET_USED(node); + RTE_SET_USED(objs); + RTE_SET_USED(nb_objs); + return 0; +} + +static struct rte_node_register dummy1 = { + .name = DUMMY1_STATIC, + .process = dummy1_fn, + .nb_edges = 0, + .init = common_node_init, +}; +RTE_NODE_REGISTER(dummy1); + +uint16_t +dummy2_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + RTE_SET_USED(graph); + RTE_SET_USED(node); + RTE_SET_USED(objs); + RTE_SET_USED(nb_objs); + return 0; +} + +static struct rte_node_register dummy2 = { + .name = DUMMY2_STATIC, + .process = dummy2_fn, + .nb_edges = 5, + .init = common_node_init, + .next_nodes = { ARC1_FEATURE1, ARC1_FEATURE2, ARC2_FEATURE1, + ARC2_FEATURE2, ARC2_FEATURE3}, +}; +RTE_NODE_REGISTER(dummy2); + +uint16_t +arc1_feature1_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + RTE_SET_USED(graph); + RTE_SET_USED(node); + RTE_SET_USED(objs); + RTE_SET_USED(nb_objs); + + return 0; +} + +uint16_t +arc1_feature1_fa_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + RTE_SET_USED(graph); + RTE_SET_USED(node); + RTE_SET_USED(objs); + RTE_SET_USED(nb_objs); + + return 0; +} + +static struct rte_node_register arc1_feature1 = { + .name = ARC1_FEATURE1, + .process = arc1_feature1_fn, + .feat_arc_proc = arc1_feature1_fa_fn, + .nb_edges = 0, + .init = common_node_init, +}; +RTE_NODE_REGISTER(arc1_feature1); + +uint16_t +arc1_feature2_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + RTE_SET_USED(graph); + RTE_SET_USED(node); + RTE_SET_USED(objs); + RTE_SET_USED(nb_objs); + + return 0; +} + +uint16_t +arc1_feature2_fa_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + RTE_SET_USED(graph); + RTE_SET_USED(node); + RTE_SET_USED(objs); + RTE_SET_USED(nb_objs); + + return 0; +} + +static struct rte_node_register arc1_feature2 = { + .name = ARC1_FEATURE2, + .process = arc1_feature2_fn, + .feat_arc_proc = arc1_feature2_fa_fn, + .nb_edges = 0, + .init = common_node_init, +}; +RTE_NODE_REGISTER(arc1_feature2); + +uint16_t +arc2_feature1_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + RTE_SET_USED(graph); + RTE_SET_USED(node); + RTE_SET_USED(objs); + RTE_SET_USED(nb_objs); + + return 0; +} + +uint16_t +arc2_feature1_fa_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + RTE_SET_USED(graph); + RTE_SET_USED(node); + RTE_SET_USED(objs); + RTE_SET_USED(nb_objs); + + return 0; +} + +static struct rte_node_register arc2_feature1 = { + .name = ARC2_FEATURE1, + .process = arc2_feature1_fn, + .feat_arc_proc = arc2_feature1_fa_fn, + .nb_edges = 0, + .init = common_node_init, +}; +RTE_NODE_REGISTER(arc2_feature1); + +uint16_t +arc2_feature2_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + RTE_SET_USED(graph); + RTE_SET_USED(node); + RTE_SET_USED(objs); + RTE_SET_USED(nb_objs); + + return 0; +} + +uint16_t +arc2_feature2_fa_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + RTE_SET_USED(graph); + RTE_SET_USED(node); + RTE_SET_USED(objs); + RTE_SET_USED(nb_objs); + + return 0; +} + +static struct rte_node_register arc2_feature2 = { + .name = ARC2_FEATURE2, + .process = arc2_feature2_fn, + .feat_arc_proc = arc2_feature2_fa_fn, + .nb_edges = 0, + .init = common_node_init, +}; +RTE_NODE_REGISTER(arc2_feature2); + +uint16_t +arc2_feature3_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + RTE_SET_USED(graph); + RTE_SET_USED(node); + RTE_SET_USED(objs); + RTE_SET_USED(nb_objs); + + return 0; +} + +uint16_t +arc2_feature3_fa_fn(struct rte_graph *graph, struct rte_node *node, + void **objs, uint16_t nb_objs) +{ + RTE_SET_USED(graph); + RTE_SET_USED(node); + RTE_SET_USED(objs); + RTE_SET_USED(nb_objs); + + return 0; +} + +static struct rte_node_register arc2_feature3 = { + .name = ARC2_FEATURE3, + .process = arc2_feature3_fn, + .feat_arc_proc = arc2_feature3_fa_fn, + .nb_edges = 0, + .init = common_node_init, +}; +RTE_NODE_REGISTER(arc2_feature3); + +static int +create_graph(void) +{ + struct rte_graph_param gconf = { + .socket_id = SOCKET_ID_ANY, + .nb_node_patterns = 1, + .node_patterns = node_patterns_feature_arc, + }; + + graph_id = rte_graph_create("worker0", &gconf); + if (graph_id == RTE_GRAPH_ID_INVALID) { + printf("Graph creation failed with error = %d\n", rte_errno); + return TEST_FAILED; + } + + return TEST_SUCCESS; +} + +static int +__test_create_feature_arc(rte_graph_feature_arc_t *arcs, int max_arcs) +{ + rte_graph_feature_arc_t arc; + const char *sample_arc_name = "sample_arc"; + char arc_name[256]; + int n_arcs; + + /* Create max number of feature arcs first */ + for (n_arcs = 0; n_arcs < max_arcs; n_arcs++) { + snprintf(arc_name, sizeof(arc_name), "%s-%u", sample_arc_name, n_arcs); + if (rte_graph_feature_arc_create(arc_name, MAX_FEATURES, + MAX_INDEXES, &dummy1, &arcs[n_arcs])) { + printf("Feature arc creation failed for %u\n", n_arcs); + return TEST_FAILED; + } + } + /* Verify feature arc created more than max_arcs must fail */ + if (!rte_graph_feature_arc_create("negative_test_create_arc", MAX_FEATURES, + MAX_INDEXES, &dummy2, &arc)) { + printf("Feature arc creation success for more than max configured: %u\n", n_arcs); + return TEST_FAILED; + } + /* Make sure lookup passes for all feature arcs */ + for (n_arcs = 0; n_arcs < max_arcs; n_arcs++) { + snprintf(arc_name, sizeof(arc_name), "%s-%u", sample_arc_name, n_arcs); + arc = RTE_GRAPH_FEATURE_ARC_INITIALIZER; + if (!rte_graph_feature_arc_lookup_by_name(arc_name, &arc)) { + if (arc != arcs[n_arcs]) { + printf("%s: Feature arc lookup mismatch for arc [%p, exp: %p]\n", + arc_name, (void *)arc, (void *)arcs[n_arcs]); + return TEST_FAILED; + } + } else { + printf("Feature arc lookup %s failed after creation\n", arc_name); + return TEST_FAILED; + } + } + return TEST_SUCCESS; +} + +static int +test_graph_feature_arc_create(void) +{ + int ret = 0, i; + + /* Create arcs with RTE_GRAPH_FEATURE_ARC_MAX */ + ret = __test_create_feature_arc(arcs, RTE_GRAPH_FEATURE_ARC_MAX); + if (ret) { + printf("Feature arc creation test failed for RTE_GRAPH_FEATURE_ARC_MAX arcs\n"); + return TEST_FAILED; + } + /* destroy all arcs via cleanup API*/ + ret = rte_graph_feature_arc_cleanup(); + if (ret) { + printf("Feature arc cleanup failed\n"); + return TEST_FAILED; + } + +#define NUM_FEAT_ARCS 128 + /* create 128 dummy feature arcs */ + ret = rte_graph_feature_arc_init(NUM_FEAT_ARCS); + if (ret) { + printf("Feature arc init failed for NUM_FEAT_ARCS"); + return TEST_FAILED; + } + ret = __test_create_feature_arc(arcs, NUM_FEAT_ARCS); + if (ret) { + printf("Feature arc creation test failed for NUM_FEAT_ARCS\n"); + return TEST_FAILED; + } + /* destroy all of them*/ + for (i = 0; i < NUM_FEAT_ARCS; i++) { + if (rte_graph_feature_arc_destroy(arcs[i])) { + printf("Feature arc destroy failed for %u\n", i); + return TEST_FAILED; + } + } + rte_graph_feature_arc_cleanup(); + + /* Create two arcs as per test plan */ + /* First arc start/source node is node: SOURCE1 */ + if (rte_graph_feature_arc_create(TEST_ARC1_NAME, MAX_FEATURES, + MAX_INDEXES, &source1, &arcs[0])) { + printf("Feature arc creation failed for %s\n", TEST_ARC1_NAME); + return TEST_FAILED; + } + + /* Duplicate name should fail */ + if (!rte_graph_feature_arc_create(TEST_ARC1_NAME, MAX_FEATURES, + MAX_INDEXES, &source1, &arcs[1])) { + printf("Duplicate feature arc %s creation is not caught\n", TEST_ARC1_NAME); + return TEST_FAILED; + } + /* Second arc start/source node is node: OUTPUT_STATIC */ + if (rte_graph_feature_arc_create(TEST_ARC2_NAME, MAX_FEATURES, + MAX_INDEXES, &output, &arcs[1])) { + printf("Feature arc creation failed for %s\n", TEST_ARC1_NAME); + return TEST_FAILED; + } + return TEST_SUCCESS; +} + +static int +test_graph_feature_arc_features_add(void) +{ + rte_graph_feature_t temp; + + /* First feature to SOURCE1 start node -> ARC1_FEATURE1 */ + if (rte_graph_feature_add(arcs[0], &arc1_feature1, NULL, NULL)) { + printf("%s: Feature add failed for adding feature %s\n", + TEST_ARC1_NAME, ARC1_FEATURE1); + return TEST_FAILED; + } + /* Second feature to SOURCE1 -> ARC1_FEATURE2 */ + if (rte_graph_feature_add(arcs[0], &arc1_feature2, NULL, NULL)) { + printf("%s: Feature add failed for adding feature %s\n", + TEST_ARC1_NAME, ARC1_FEATURE2); + return TEST_FAILED; + } + /* adding statically connected INPUT_STATIC as a last feature */ + if (rte_graph_feature_add(arcs[0], &input, ARC1_FEATURE2, NULL)) { + printf("%s: Feature add failed for adding feature %s after %s\n", + TEST_ARC1_NAME, INPUT_STATIC, ARC1_FEATURE2); + return TEST_FAILED; + } + /* First feature to OUTPUT_STATIC start node -> ARC2_FEATURE3 */ + if (rte_graph_feature_add(arcs[1], &arc2_feature3, NULL, NULL)) { + printf("%s: Feature add failed for adding feature %s\n", + TEST_ARC2_NAME, ARC2_FEATURE3); + return TEST_FAILED; + } + /* Second feature to OUTPUT_STATIC -> ARC2_FEATURE1 and before feature to + * ARC2_FEATURE3 + */ + if (rte_graph_feature_add(arcs[1], &arc2_feature1, NULL, ARC2_FEATURE3)) { + printf("%s: Feature add failed for adding feature %s after %s\n", + TEST_ARC2_NAME, ARC2_FEATURE3, ARC2_FEATURE1); + return TEST_FAILED; + } + /* Add PKT_FREE node as last feature, next to arc2_feature3 */ + if (rte_graph_feature_add(arcs[1], &pkt_free, ARC2_FEATURE3, NULL)) { + printf("%s: Feature add failed for adding feature %s after %s\n", + TEST_ARC2_NAME, PKT_FREE_STATIC, ARC2_FEATURE3); + return TEST_FAILED; + } + /* Adding feature ARC2_FEATURE2 between ARC2_FEATURE1 and ARC2_FEATURE3. */ + if (rte_graph_feature_add(arcs[1], &arc2_feature2, ARC2_FEATURE1, ARC2_FEATURE3)) { + printf("%s: Feature add failed for adding feature %s between [%s - %s]\n", + TEST_ARC2_NAME, ARC2_FEATURE2, ARC2_FEATURE1, ARC2_FEATURE3); + return TEST_FAILED; + } + /* Now check feature sequencing is correct for both ARCS */ + + /* arc1_feature1 must be first feature to arcs[0] */ + if (!strstr(ARC1_FEATURE1, + rte_graph_feature_arc_feature_to_name(arcs[0], + rte_graph_feature_cast(0)))) { + printf("%s: %s is not the first feature instead %s\n", + TEST_ARC1_NAME, ARC1_FEATURE1, + rte_graph_feature_arc_feature_to_name(arcs[0], rte_graph_feature_cast(0))); + return TEST_FAILED; + } + + /* arc1_feature2 must be second feature to arcs[0] */ + if (!strstr(ARC1_FEATURE2, + rte_graph_feature_arc_feature_to_name(arcs[0], + rte_graph_feature_cast(1)))) { + printf("%s: %s is not the second feature instead %s\n", + TEST_ARC1_NAME, ARC1_FEATURE2, + rte_graph_feature_arc_feature_to_name(arcs[0], rte_graph_feature_cast(1))); + return TEST_FAILED; + } + + /* Make sure INPUT_STATIC is the last feature in arcs[0] */ + temp = rte_graph_feature_arc_num_features(arcs[0]); + if (!strstr(INPUT_STATIC, + rte_graph_feature_arc_feature_to_name(arcs[0], + temp - rte_graph_feature_cast(1)))) { + printf("%s: %s is not the last feature instead %s\n", + TEST_ARC1_NAME, INPUT_STATIC, + rte_graph_feature_arc_feature_to_name(arcs[0], + temp - rte_graph_feature_cast(1))); + return TEST_FAILED; + } + + /* arc2_feature1 must be first feature to arcs[1] */ + if (!strstr(ARC2_FEATURE1, + rte_graph_feature_arc_feature_to_name(arcs[1], + rte_graph_feature_cast(0)))) { + printf("%s: %s is not the first feature instead %s\n", + TEST_ARC2_NAME, ARC2_FEATURE1, + rte_graph_feature_arc_feature_to_name(arcs[1], rte_graph_feature_cast(0))); + return TEST_FAILED; + } + + /* arc2_feature2 must be second feature to arcs[1] */ + if (!strstr(ARC2_FEATURE2, + rte_graph_feature_arc_feature_to_name(arcs[1], + rte_graph_feature_cast(1)))) { + printf("%s: %s is not the second feature instead %s\n", + TEST_ARC2_NAME, ARC2_FEATURE2, + rte_graph_feature_arc_feature_to_name(arcs[1], rte_graph_feature_cast(1))); + return TEST_FAILED; + } + + /* arc2_feature3 must be third feature to arcs[1] */ + if (!strstr(ARC2_FEATURE3, + rte_graph_feature_arc_feature_to_name(arcs[1], + rte_graph_feature_cast(2)))) { + printf("%s: %s is not the third feature instead %s\n", + TEST_ARC2_NAME, ARC2_FEATURE3, + rte_graph_feature_arc_feature_to_name(arcs[1], rte_graph_feature_cast(2))); + return TEST_FAILED; + } + + /* Make sure PKT_FREE is the last feature in arcs[1] */ + temp = rte_graph_feature_arc_num_features(arcs[1]); + if (!strstr(PKT_FREE_STATIC, + rte_graph_feature_arc_feature_to_name(arcs[1], + temp - rte_graph_feature_cast(1)))) { + printf("%s: %s is not the last feature instead %s\n", + TEST_ARC2_NAME, PKT_FREE_STATIC, + rte_graph_feature_arc_feature_to_name(arcs[1], + temp - rte_graph_feature_cast(1))); + return TEST_FAILED; + } + + if (get_edge(&arc2_feature1, &pkt_free, NULL)) { + printf("%s: Edge not found between %s and %s\n", + TEST_ARC2_NAME, ARC2_FEATURE1, PKT_FREE_STATIC); + return TEST_FAILED; + } + + return create_graph(); +} + +static int +test_graph_feature_arc_first_feature_enable(void) +{ + uint32_t n_indexes, n_features, count = 0; + rte_graph_feature_rt_list_t feature_list, temp = 0; + struct rte_node_register *parent, *child; + rte_graph_feature_data_t *fdata = NULL; + struct rte_graph_feature_arc *arc; + rte_graph_feature_t feature; + char *feature_name = NULL; + int32_t user_data; + rte_edge_t edge = ~0; + + arc = rte_graph_feature_arc_get(arcs[0]); + + if (rte_graph_feature_arc_has_any_feature(arc, &feature_list)) { + printf("%s: Feature arc should not have any feature enabled by now\n", + TEST_ARC1_NAME); + return TEST_FAILED; + } + + if (rte_graph_feature_arc_num_enabled_features(arcs[0])) { + printf("%s: Feature arc should not have any_feature() enabled by now\n", + TEST_ARC1_NAME); + return TEST_FAILED; + } + /* + * On interface 0, enable feature 0, + * On interface 1, enable feature 1 and so on so forth + * + * later verify first feature on every interface index is unique + * and check [rte_edge, user_data] retrieved via fast path APIs + */ + for (n_indexes = 0; n_indexes < MAX_INDEXES; n_indexes++) { + n_features = n_indexes % 3 /* 3 features added to arc1 */; + feature_name = rte_graph_feature_arc_feature_to_name(arcs[0], n_features); + user_data = compute_unique_user_data(arc->start_node->name, feature_name, + n_indexes); + if (rte_graph_feature_validate(arcs[0], n_indexes, feature_name, 1, true)) { + printf("%s: Feature validate failed for %s on index %u\n", + TEST_ARC1_NAME, feature_name, n_indexes); + return TEST_FAILED; + } + /* negative test case. enable feature on invalid index */ + if (!n_indexes && !rte_graph_feature_enable(arcs[0], MAX_INDEXES, feature_name, + (int32_t)user_data)) { + printf("%s: Feature %s should not be enabled on invalid index\n", + TEST_ARC1_NAME, feature_name); + return TEST_FAILED; + } + if (rte_graph_feature_enable(arcs[0], n_indexes, feature_name, + (int32_t)user_data)) { + printf("%s: Feature enable failed for %s on index %u\n", + TEST_ARC1_NAME, feature_name, n_indexes); + return TEST_FAILED; + } + /* has any feature should be valid */ + if (!rte_graph_feature_arc_has_any_feature(arc, &feature_list)) { + printf("%s: Feature arc should have any_feature enabled by now\n", + TEST_ARC1_NAME); + return TEST_FAILED; + } + if (temp == feature_list) { + printf("%s: Activer feature list not switched from %u -> %u\n", + TEST_ARC1_NAME, temp, feature_list); + return TEST_FAILED; + } + temp = feature_list; + if ((count + 1) != rte_graph_feature_arc_num_enabled_features(arcs[0])) { + printf("%s: Number of enabled mismatches [found: %u, exp: %u]\n", + TEST_ARC1_NAME, + rte_graph_feature_arc_num_enabled_features(arcs[0]), + count + 1); + return TEST_FAILED; + } + count++; + } + if (!rte_graph_feature_arc_has_any_feature(arc, &feature_list)) { + printf("%s: Feature arc should have any_feature enabled by now\n", + TEST_ARC1_NAME); + return TEST_FAILED; + } + /* Negative test case */ + user_data = compute_unique_user_data(arc->start_node->name, ARC2_FEATURE1, 1); + if (!rte_graph_feature_enable(arcs[0], 1 /* index */, ARC2_FEATURE1, user_data)) { + printf("%s: Invalid feature %s is enabled on index 1\n", + TEST_ARC1_NAME, ARC2_FEATURE1); + return TEST_FAILED; + } + /* Duplicate enable */ + if (!rte_graph_feature_enable(arcs[0], 1 /* index */, ARC1_FEATURE2, user_data)) { + printf("%s: Duplicate feature %s shouldn't be enabled again on index 1\n", + TEST_ARC1_NAME, ARC1_FEATURE2); + return TEST_FAILED; + } + for (n_indexes = 0; n_indexes < MAX_INDEXES; n_indexes++) { + if (!rte_graph_feature_arc_first_feature_get(arc, feature_list, n_indexes, + &feature)) { + printf("%s: No first feature enabled on index: %u\n", + TEST_ARC1_NAME, n_indexes); + return TEST_FAILED; + } + /* Get first feature data and ensure edge and user_data are correct */ + fdata = rte_graph_feature_data_get(arc, rte_graph_feature_get(arc, feature), + n_indexes); + parent = arc->start_node; + if (0 == (n_indexes % 3)) + child = &arc1_feature1; + else if (1 == (n_indexes % 3)) + child = &arc1_feature2; + else + child = &input; + + if (get_edge(parent, child, &edge)) { + printf("%s: Edge not found between %s and %s\n", + TEST_ARC1_NAME, parent->name, child->name); + return TEST_FAILED; + } + if (fdata->next_edge != edge) { + printf("%s: Edge mismatch for first feature on index %u [%u, exp: %u]\n", + TEST_ARC1_NAME, n_indexes, fdata->next_edge, edge); + return TEST_FAILED; + } + if (fdata->user_data != compute_unique_user_data(parent->name, child->name, + n_indexes)) { + printf("%s: First feature user data mismatch on index %u [%u, exp: %u]\n", + TEST_ARC1_NAME, n_indexes, fdata->user_data, + compute_unique_user_data(parent->name, child->name, n_indexes)); + return TEST_FAILED; + } + } + return TEST_SUCCESS; +} + +static int +verify_feature_sequencing(struct rte_graph_feature_arc *arc) +{ + rte_graph_feature_rt_list_t feature_list; + struct rte_node_register *parent, *child; + rte_graph_feature_data_t *fdata = NULL; + rte_graph_feature_t feature; + uint32_t n_indexes; + rte_edge_t edge = ~0; + int32_t user_data; + + if (!rte_graph_feature_arc_has_any_feature(arc, &feature_list)) { + printf("%s: feature_list can't be obtained\n", + arc->feature_arc_name); + return TEST_FAILED; + } + /* Verify next features on interface 0 and interface 1*/ + for (n_indexes = 0; n_indexes < 2; n_indexes++) { + if (!rte_graph_feature_arc_first_feature_get(arc, feature_list, n_indexes, + &feature)) { + printf("%s: No first feature enabled on index: 0\n", + arc->feature_arc_name); + return TEST_FAILED; + } + parent = arc->start_node; + child = rte_graph_feature_arc_feature_to_node(arcs[1], feature); + /* until fast path API reaches last feature i.e pkt_free */ + while (child != &pkt_free) { + fdata = rte_graph_feature_data_get(arc, + rte_graph_feature_get(arc, feature), + n_indexes); + + if (get_edge(parent, child, &edge)) { + printf("%s: Edge not found between %s and %s\n", + arc->feature_arc_name, parent->name, child->name); + return TEST_FAILED; + } + user_data = compute_unique_user_data(parent->name, child->name, n_indexes); + if (fdata->next_edge != edge) { + printf("%s: Edge mismatch for %s->%s on index %u [%u, exp: %u]\n", + arc->feature_arc_name, parent->name, child->name, n_indexes, + fdata->next_edge, edge); + return TEST_FAILED; + } + if (fdata->user_data != user_data) { + printf("%s: Udata mismatch for %s->%s on index %u [%u, exp: %u]\n", + arc->feature_arc_name, parent->name, child->name, n_indexes, + fdata->user_data, user_data); + return TEST_FAILED; + } + + feature = fdata->next_enabled_feature; + + parent = child; + child = rte_graph_feature_arc_feature_to_node(arcs[1], + fdata->next_enabled_feature); + } + } + return TEST_SUCCESS; +} + +static int +test_graph_feature_arc_next_feature_enable(void) +{ + rte_graph_feature_rt_list_t feature_list; + struct rte_node_register *parent, *child; + rte_graph_feature_data_t *fdata = NULL; + struct rte_graph_feature_arc *arc; + uint32_t n_indexes, n_features; + rte_graph_feature_t feature; + char *feature_name = NULL; + rte_edge_t edge = ~0; + int32_t user_data; + + arc = rte_graph_feature_arc_get(arcs[1]); + + if (rte_graph_feature_arc_has_any_feature(arc, &feature_list)) { + printf("%s: Feature arc should not have any feature enabled by now\n", + TEST_ARC2_NAME); + return TEST_FAILED; + } + + if (rte_graph_feature_arc_num_enabled_features(arcs[1])) { + printf("%s: Feature arc should not have any_feature() enabled by now\n", + TEST_ARC2_NAME); + return TEST_FAILED; + } + /* + * On interface 0, enable feature 2, skip feature 1 for later + * On interface 1, enable feature 3 + * On interface 2, enable pkt_free feature + * On interface 3, continue as interface 0 + * + * later enable next feature sequence for interface 0 from feature2 -> pkt_free + * later enable next feature sequence for interface 1 from feature3 -> pkt_free + * + * also later enable feature-1 and see first feature changes for all indexes + */ + for (n_indexes = 0; n_indexes < MAX_INDEXES; n_indexes++) { + n_features = (n_indexes % 3) + 1; /* feature2 to pkt_free are 3 features */ + feature_name = rte_graph_feature_arc_feature_to_name(arcs[1], n_features); + user_data = compute_unique_user_data(arc->start_node->name, feature_name, + n_indexes); + if (rte_graph_feature_enable(arcs[1], n_indexes, feature_name, + (int32_t)user_data)) { + printf("%s: Feature enable failed for %s on index %u\n", + TEST_ARC2_NAME, feature_name, n_indexes); + return TEST_FAILED; + } + /* has any feature should be valid */ + if (!rte_graph_feature_arc_has_any_feature(arc, &feature_list)) { + printf("%s: Feature arc should have any_feature enabled by now\n", + TEST_ARC2_NAME); + return TEST_FAILED; + } + } + /* Retrieve latest feature_list */ + rte_graph_feature_arc_has_any_feature(arc, &feature_list); + /* verify first feature */ + for (n_indexes = 0; n_indexes < MAX_INDEXES; n_indexes++) { + if (!rte_graph_feature_arc_first_feature_get(arc, feature_list, n_indexes, + &feature)) { + printf("%s: No first feature enabled on index: %u\n", + TEST_ARC2_NAME, n_indexes); + return TEST_FAILED; + } + /* Get first feature data and ensure edge and user_data are correct */ + fdata = rte_graph_feature_data_get(arc, rte_graph_feature_get(arc, feature), + n_indexes); + parent = arc->start_node; + if (0 == (n_indexes % 3)) + child = &arc2_feature2; + else if (1 == (n_indexes % 3)) + child = &arc2_feature3; + else + child = &pkt_free; + + if (get_edge(parent, child, &edge)) { + printf("%s: Edge not found between %s and %s\n", + TEST_ARC2_NAME, parent->name, child->name); + return TEST_FAILED; + } + if (fdata->next_edge != edge) { + printf("%s: Edge mismatch for first feature on index %u [%u, exp: %u]\n", + TEST_ARC2_NAME, n_indexes, fdata->next_edge, edge); + return TEST_FAILED; + } + if (fdata->user_data != compute_unique_user_data(parent->name, child->name, + n_indexes)) { + printf("%s: First feature user data mismatch on index %u [%u, exp: %u]\n", + TEST_ARC2_NAME, n_indexes, fdata->user_data, + compute_unique_user_data(parent->name, child->name, n_indexes)); + return TEST_FAILED; + } + } + /* add next_features now + * On interface 0, enable feature-3 and pkt_free + * On interface 1, enable pkt_free + * Skip interface 2 + * On interface 3, same as interface 0 + * On interface 4, same as interface 1 + */ + for (n_indexes = 0; n_indexes < MAX_INDEXES; n_indexes++) { + if (0 == (n_indexes % 3)) { + if (rte_graph_feature_enable(arcs[1], n_indexes, ARC2_FEATURE3, + compute_unique_user_data(ARC2_FEATURE2, + ARC2_FEATURE3, + n_indexes))) { + printf("%s: Feature enable failed for %s -> (%s) on index %u\n", + TEST_ARC2_NAME, ARC2_FEATURE2, ARC2_FEATURE3, n_indexes); + return TEST_FAILED; + } + } + /* pkt_free on interface-0, 1, 3, 4 and so on */ + if ((0 == (n_indexes % 3)) || (1 == (n_indexes % 3))) { + if (rte_graph_feature_enable(arcs[1], n_indexes, PKT_FREE_STATIC, + compute_unique_user_data(ARC2_FEATURE3, + PKT_FREE_STATIC, + n_indexes))) { + printf("%s: Feature enable failed %s -> (%s) on index %u\n", + TEST_ARC2_NAME, ARC2_FEATURE3, PKT_FREE_STATIC, n_indexes); + return TEST_FAILED; + } + } + } + + if (verify_feature_sequencing(arc) == TEST_FAILED) + return TEST_FAILED; + + /* Enable feature-1 on all interfaces and check first feature changes */ + for (n_indexes = 0; n_indexes < MAX_INDEXES; n_indexes++) { + user_data = compute_unique_user_data(arc->start_node->name, ARC2_FEATURE1, + n_indexes); + if (rte_graph_feature_enable(arcs[1], n_indexes, ARC2_FEATURE1, + (int32_t)user_data)) { + printf("%s: Feature enable failed for %s on index %u\n", + TEST_ARC2_NAME, feature_name, n_indexes); + return TEST_FAILED; + } + } + rte_graph_feature_arc_has_any_feature(arc, &feature_list); + for (n_indexes = 0; n_indexes < MAX_INDEXES; n_indexes++) { + if (!rte_graph_feature_arc_first_feature_get(arc, feature_list, n_indexes, + &feature)) { + printf("%s: None first feature enabled on index: %u\n", + TEST_ARC2_NAME, n_indexes); + return TEST_FAILED; + } + if (feature != rte_graph_feature_cast(0)) { + printf("%s: First feature mismatch on index %u [%u, exp: %u]\n", + TEST_ARC2_NAME, n_indexes, feature, rte_graph_feature_cast(0)); + return TEST_FAILED; + } + } + if (verify_feature_sequencing(arc) == TEST_FAILED) + return TEST_FAILED; + + return TEST_SUCCESS; +} + +static int +test_graph_feature_arc_first_feature_disable(void) +{ + rte_graph_feature_rt_list_t feature_list; + struct rte_graph_feature_arc *arc; + rte_graph_feature_t feature; + uint32_t n_indexes; + + arc = rte_graph_feature_arc_get(arcs[1]); + + /* Disable feature-1 on all interfaces and check first feature changes */ + for (n_indexes = 0; n_indexes < MAX_INDEXES; n_indexes++) { + if (rte_graph_feature_disable(arcs[1], n_indexes, ARC2_FEATURE1)) { + printf("%s: Feature disable failed for %s on index %u\n", + TEST_ARC2_NAME, ARC2_FEATURE1, n_indexes); + return TEST_FAILED; + } + } + rte_graph_feature_arc_has_any_feature(arc, &feature_list); + for (n_indexes = 0; n_indexes < MAX_INDEXES; n_indexes++) { + if (!rte_graph_feature_arc_first_feature_get(arc, feature_list, n_indexes, + &feature)) { + printf("%s: First feature get failed on index: %u\n", + TEST_ARC2_NAME, n_indexes); + return TEST_FAILED; + } + if (feature == rte_graph_feature_cast(0)) { + printf("%s: First feature not disabled on index %u [%u, exp: %u]\n", + TEST_ARC2_NAME, n_indexes, feature, rte_graph_feature_cast(1)); + return TEST_FAILED; + } + if (!strncmp(ARC2_FEATURE1, + rte_graph_feature_arc_feature_to_name(arcs[1], feature), + strlen(ARC2_FEATURE1))) { + printf("%s: First feature mismatch on index %u [%s, exp: %s]\n", + TEST_ARC2_NAME, n_indexes, + rte_graph_feature_arc_feature_to_name(arcs[1], feature), + ARC2_FEATURE2); + return TEST_FAILED; + } + } + if (verify_feature_sequencing(arc) == TEST_FAILED) + return TEST_FAILED; + + return TEST_SUCCESS; +} + +static int +test_graph_feature_arc_next_feature_disable(void) +{ + rte_graph_feature_rt_list_t feature_list; + struct rte_graph_feature_arc *arc; + rte_graph_feature_t feature; + uint32_t n_indexes; + + arc = rte_graph_feature_arc_get(arcs[1]); + + /* + * On interface 0, disable feature 2, keep feature3 and pkt_free enabled + * On interface 1, skip interface 1 where feature3 and pkt_free are enabled + * skip interface 2 as only pkt_free is enabled + */ + for (n_indexes = 0; n_indexes < MAX_INDEXES; n_indexes++) { + if (!(n_indexes % 3)) { + if (rte_graph_feature_disable(arcs[1], n_indexes, ARC2_FEATURE2)) { + printf("%s: Feature disable failed for %s on index %u\n", + TEST_ARC2_NAME, ARC2_FEATURE2, n_indexes); + return TEST_FAILED; + } + } + + if (verify_feature_sequencing(arc) == TEST_FAILED) + return TEST_FAILED; + } + + /** + * Disable feature 3 on all interface 0 and 1 and check first feature + * is pkt_free on all indexes + */ + for (n_indexes = 0; n_indexes < MAX_INDEXES; n_indexes++) { + if ((0 == (n_indexes % 3)) || (1 == (n_indexes % 3))) { + if (rte_graph_feature_disable(arcs[1], n_indexes, ARC2_FEATURE3)) { + printf("%s: Feature disable failed for %s on index %u\n", + TEST_ARC2_NAME, ARC2_FEATURE3, n_indexes); + return TEST_FAILED; + } + } + } + /* Make sure pkt_free is first feature for all indexes */ + rte_graph_feature_arc_has_any_feature(arc, &feature_list); + for (n_indexes = 0; n_indexes < MAX_INDEXES; n_indexes++) { + if (!rte_graph_feature_arc_first_feature_get(arc, feature_list, n_indexes, + &feature)) { + printf("%s: First feature get failed on index: %u\n", + TEST_ARC2_NAME, n_indexes); + return TEST_FAILED; + } + if (strncmp(PKT_FREE_STATIC, + rte_graph_feature_arc_feature_to_name(arcs[1], feature), + strlen(PKT_FREE_STATIC))) { + printf("%s: %s is not first feature found on index %u [%s, exp: %s]\n", + TEST_ARC2_NAME, PKT_FREE_STATIC, n_indexes, + rte_graph_feature_arc_feature_to_name(arcs[1], feature), + PKT_FREE_STATIC); + return TEST_FAILED; + } + } + + /* Disable PKT_FREE_STATIC from all indexes with no feature enabled on any interface */ + for (n_indexes = 0; n_indexes < MAX_INDEXES; n_indexes++) { + if (rte_graph_feature_disable(arcs[1], n_indexes, PKT_FREE_STATIC)) { + printf("%s: Feat disable failed for %s on index %u\n", + TEST_ARC2_NAME, PKT_FREE_STATIC, n_indexes); + return TEST_FAILED; + } + } + /* Make sure no feature is enabled now on any interface */ + rte_graph_feature_arc_has_any_feature(arc, &feature_list); + for (n_indexes = 0; n_indexes < MAX_INDEXES; n_indexes++) { + if (rte_graph_feature_arc_first_feature_get(arc, feature_list, n_indexes, + &feature)) { + printf("%s: Index: %u should not have first feature enabled\n", + TEST_ARC2_NAME, n_indexes); + return TEST_FAILED; + } + } + return TEST_SUCCESS; +} + +static int +test_graph_feature_arc_destroy(void) +{ + rte_graph_feature_arc_t arc; + + if (rte_graph_feature_arc_lookup_by_name(TEST_ARC1_NAME, &arc)) { + printf("Feature arc lookup failed for %s\n", TEST_ARC1_NAME); + return TEST_FAILED; + } + + if (arc != arcs[0]) { + printf("Feature arc lookup mismatch for %s [%p, exp: %p]\n", + TEST_ARC1_NAME, (void *)arc, (void *)arcs[0]); + return TEST_FAILED; + } + + if (rte_graph_feature_arc_destroy(arc)) { + printf("Feature arc destroy failed for %s\n", TEST_ARC1_NAME); + return TEST_FAILED; + } + + if (rte_graph_feature_arc_lookup_by_name(TEST_ARC2_NAME, &arc)) { + printf("Feature arc lookup success after destroy for %s\n", TEST_ARC2_NAME); + return TEST_FAILED; + } + + if (arc != arcs[1]) { + printf("Feature arc lookup mismatch for %s [%p, exp: %p]\n", + TEST_ARC2_NAME, (void *)arc, (void *)arcs[1]); + return TEST_FAILED; + } + if (rte_graph_feature_arc_destroy(arc)) { + printf("Feature arc destroy failed for %s\n", TEST_ARC2_NAME); + return TEST_FAILED; + } + return TEST_SUCCESS; +} + +static int +graph_feature_arc_setup(void) +{ + unsigned long i, j; + + static const struct rte_mbuf_dynfield graph_dynfield_desc = { + .name = "test_graph_dynfield", + .size = sizeof(graph_dynfield_t), + .align = alignof(graph_dynfield_t), + }; + + graph_dynfield_offset = + rte_mbuf_dynfield_register(&graph_dynfield_desc); + if (graph_dynfield_offset < 0) { + printf("Cannot register mbuf field\n"); + return TEST_FAILED; + } + RTE_SET_USED(graph_dynfield_offset); + + for (i = 0; i <= MAX_NODES; i++) { + for (j = 0; j < MBUFF_SIZE; j++) + mbuf_p[i][j] = &mbuf[i][j]; + } + + return TEST_SUCCESS; + +} + +static void +graph_feature_arc_teardown(void) +{ + if (graph_id != RTE_GRAPH_ID_INVALID) + rte_graph_destroy(graph_id); + + rte_graph_feature_arc_cleanup(); +} + +static struct unit_test_suite graph_feature_arc_testsuite = { + .suite_name = "Graph Feature arc library test suite", + .setup = graph_feature_arc_setup, + .teardown = graph_feature_arc_teardown, + .unit_test_cases = { + TEST_CASE(test_graph_feature_arc_create), + TEST_CASE(test_graph_feature_arc_features_add), + TEST_CASE(test_graph_feature_arc_first_feature_enable), + TEST_CASE(test_graph_feature_arc_next_feature_enable), + TEST_CASE(test_graph_feature_arc_first_feature_disable), + TEST_CASE(test_graph_feature_arc_next_feature_disable), + TEST_CASE(test_graph_feature_arc_destroy), + TEST_CASES_END(), /**< NULL terminate unit test array */ + }, +}; + +static int +graph_feature_arc_autotest_fn(void) +{ + return unit_test_suite_runner(&graph_feature_arc_testsuite); +} + +REGISTER_FAST_TEST(graph_feature_arc_autotest, true, true, graph_feature_arc_autotest_fn); +#endif /* !RTE_EXEC_ENV_WINDOWS */ -- 2.43.0 ^ permalink raw reply [flat|nested] 46+ messages in thread
* Re: [PATCH v5 4/5] test/graph_feature_arc: add functional tests 2024-10-14 14:33 ` [PATCH v5 4/5] test/graph_feature_arc: add functional tests Nitin Saxena @ 2024-10-14 19:54 ` Stephen Hemminger 0 siblings, 0 replies; 46+ messages in thread From: Stephen Hemminger @ 2024-10-14 19:54 UTC (permalink / raw) To: Nitin Saxena Cc: Jerin Jacob, Kiran Kumar K, Nithin Dabilpuram, Zhirun Yan, Robin Jarry, Christophe Fontaine, dev, Nitin Saxena On Mon, 14 Oct 2024 20:03:57 +0530 Nitin Saxena <nsaxena@marvell.com> wrote: > Added functional unit test case for verifying feature arc control plane > and fast path APIs > > How to run: > $ echo "graph_feature_arc_autotest" | ./bin/dpdk-test > > Signed-off-by: Nitin Saxena <nsaxena@marvell.com> With current upstream kernel checkpatch additional warnings: WARNING:MACRO_ARG_UNUSED: Argument 'idx' is not used in function-like macro #217: FILE: app/test/test_graph_feature_arc.c:186: +#define R(idx, node, node_cookie) { \ + if (!strcmp(child, node)) { \ + user_data += node_cookie; \ + } \ + } WARNING:MACRO_ARG_UNUSED: Argument 'user_data' is not used in function-like macro #272: FILE: app/test/test_graph_feature_arc.c:241: +#define R(idx, _name, user_data) { \ + if (!strcmp(node->name, _name)) { \ + priv->node_index = idx; \ + } \ + } Personally, using macros to generate tests like this can get confusing. ^ permalink raw reply [flat|nested] 46+ messages in thread
* [PATCH v5 5/5] docs: add programming guide for feature arc 2024-10-14 14:33 ` [PATCH v5 0/5] add feature arc in rte_graph Nitin Saxena ` (3 preceding siblings ...) 2024-10-14 14:33 ` [PATCH v5 4/5] test/graph_feature_arc: add functional tests Nitin Saxena @ 2024-10-14 14:33 ` Nitin Saxena 4 siblings, 0 replies; 46+ messages in thread From: Nitin Saxena @ 2024-10-14 14:33 UTC (permalink / raw) To: Jerin Jacob, Kiran Kumar K, Nithin Dabilpuram, Zhirun Yan, Robin Jarry, Christophe Fontaine Cc: dev, Nitin Saxena Updated graph library guide with feature arc Signed-off-by: Nitin Saxena <nsaxena@marvell.com> --- doc/guides/prog_guide/graph_lib.rst | 288 +++++++++++ doc/guides/prog_guide/img/feature_arc-1.svg | 277 +++++++++++ doc/guides/prog_guide/img/feature_arc-2.svg | 511 ++++++++++++++++++++ doc/guides/prog_guide/img/feature_arc-3.svg | 318 ++++++++++++ 4 files changed, 1394 insertions(+) create mode 100644 doc/guides/prog_guide/img/feature_arc-1.svg create mode 100644 doc/guides/prog_guide/img/feature_arc-2.svg create mode 100644 doc/guides/prog_guide/img/feature_arc-3.svg diff --git a/doc/guides/prog_guide/graph_lib.rst b/doc/guides/prog_guide/graph_lib.rst index ad09bdfe26..d98b48b0e5 100644 --- a/doc/guides/prog_guide/graph_lib.rst +++ b/doc/guides/prog_guide/graph_lib.rst @@ -547,3 +547,291 @@ on success packet is enqueued to ``udp4_input`` node. Hash lookup is performed in ``udp4_input`` node with registered destination port and destination port in UDP packet , on success packet is handed to ``udp_user_node``. + +Feature Arc +----------- +`Feature arc` represents an ordered list of `protocols/features` at a given +networking layer. It is a high level abstraction to connect various `feature` +nodes in `rte_graph` instance and allows seamless packets steering based on the +sequence of enabled features at runtime on each interface. + +`Features` (or feature nodes) are nodes which handle partial or complete +protocol processing in a given direction. For instance, `ipv4-rewrite` and +`IPv4 IPsec encryption` are outbound features while `ipv4-lookup` and `IPv4 +IPsec decryption` are inbound features. Further, `ipv4-rewrite` and `IPv4 +IPsec encryption` can collectively represent a `feature arc` towards egress +direction with ordering constraints that `IPv4 IPsec encryption` must be +performed before `ipv4-rewrite`. Similarly, `IPv4 IPsec decryption` and +`ipv4-lookup` can represent a `feature arc` in an ingress direction. Both of +these `feature arc` can co-exist at an IPv4 layer in egress and ingress +direction respectively. + +A `feature` can be represented by a single node or collection of multiple nodes +performing feature processing collectively. + +.. figure:: img/feature_arc-1.* + :alt: feature-arc-1 + :width: 350px + :align: center + + Feature Arc overview + +Each `feature arc` is associated with a `Start` node from which all features in +a feature arc are connected. A `start` node itself is not a `feature` node but +it is where `first enabled feature` is checked in fast path. In above figure, +`Node-A` represents a `start node`. There may be a `Sink` node as well which +is child node for every feature in an arc. 'Sink` node is responsible of +consuming those packets which are not consumed by intermediate enabled features +between `start` and `sink` node. `Sink` node, if present, is the last enabled +feature in a feature arc. A `feature` node statically connected to `start` node +must also be added via feature arc API, `rte_graph_feature_add()``. Here `Node-B` +acts as a `sink` node which is statically linked to `Node A`. `Feature` nodes +are connected via `rte_graph_feature_add()` which takes care of connecting +all `feature` nodes with each other and start node. + +.. code-block:: bash + :linenos: + :emphasize-lines: 8 + :caption: Node-B statically linked to Node-A + + static struct rte_node_register node_A_node = { + .process = node_A_process_func, + ... + ... + .name = "Node-A", + .next_nodes = + { + [0] = "Node-B", + }, + .nb_edges = 1, + }; + +When multiple features are enabled on an interface, it may be required to steer +packets across `features` in a given order. For instance, if `Feature 1` and +`Feature 2` both are enabled on an interface ``X``, it may be required to send +packets to `Feature-1` before `Feature-2`. Such ordering constraints can be +easily expressed with `feature arc`. In this case, `Feature 1` is called as +``First Feature`` and `Feature 2` is called as ``Next Feature`` to `Feature 1`. + +.. figure:: img/feature_arc-2.* + :alt: feature-arc-2 + :width: 600px + :align: center + + First and Next features and their ordering + +In similar manner, even application specific ``custom features`` can be hooked +to standard nodes. It is to be noted that this `custom feature` hooking to +`feature arc` aware node does not require any code changes. + +It may be obvious by now that `features` enabled on one interface does not +affect packets on other interfaces. In above example, if no feature is +enabled on an interface ``X``, packets destined to interface ``X`` would be +directly sent to `Node-B` from `Node-A`. + +.. figure:: img/feature_arc-3.* + :alt: feature-arc-3 + :width: 550px + :align: center + + Feature-2 consumed/non-consumed packet path + +When a `Feature-X` node receives packets via feature arc, it may decide whether +to ``consume packet`` or send to `next enabled feature`. A node can consume +packet by freeing it, sending it on wire or enqueuing it to hardware queue. If a +packet is not consumed by a `Feature-X` node, it may send to `next enabled +feature` on an interface. In above figure, `Feature-2` nodes are represented to +consume packets. Classic example for a node performing consume and non-consume +operation on packets would be IPsec policy node where all packets with +``protect`` actions are consumed while remaining packets with ``bypass`` +actions are sent to next enabled feature. + +In fast path feature node may require to lookup local data structures for each +interface. For example, retrieving policy database per interface for IPsec +processing. ``rte_graph_feature_enable`` API allows to set application +specific cookie per feature per interface. `Feature data` object maintains this +cookie in fast path for each interface. + +`Feature arc design` allows to enable subsequent features in a control plane +without stopping workers which are accessing feature arc's fast path APIs in +``rte_graph_walk()`` context. However for disabling features require RCU like +scheme for synchronization. + +Programming model +~~~~~~~~~~~~~~~~~ +Feature Arc Objects +^^^^^^^^^^^^^^^^^^^ +Control plane and fast path APIs deals with following objects: + +Feature arc +*********** +``rte_graph_feature_arc_t`` is a handle to feature arc which is created via +``rte_graph_feature_arc_create()``. It is a `uint64_t` size object which can be +saved in feature node's context. This object can be translated to fast path +feature arc object ``struct rte_graph_feature_arc`` which is an input +argument to all fast path APIs. Control plane APIs majorly takes +`rte_graph_feature_arc_t` object as an input. + +Feature List +************ +Each feature arc holds two feature lists: `active` and `passive`. While worker +cores uses `active` list, control plane APIs uses `passive` list for +enabling/disabling a feature on any interface with in a arc. After successful +feature enable/disable, ``rte_graph_feature_enable()``/ +``rte_graph_feature_disable()`` atomically switches passive list to active list +and vice-versa. Most of the fast path APIs takes active list as an argument +(``rte_graph_feature_rt_list_t``), which feature node can obtain in start of +it's `process_func()` via ``rte_graph_feature_arc_has_any_feature()`` (in `start` +node) or ``rte_graph_feature_arc_has_feature()`` (in next feature nodes). + +Each feature list holds RTE_GRAPH_MAX_FEATURES number of features and +associated feature data for every interface index + +Feature +******** +Feature is a data structure which holds `feature data` object for every +interface. It is represented via ``rte_graph_feature_t`` which is a `uint8_t` +size object. Fast path internal structure ``struct rte_graph_feature`` can be +obtained from ``rte_graph_feature_t`` via ``rte_graph_feature_get()`` API. + +In `start` node `rte_graph_feature_arc_first_feature_get()` can be used to get +first enabled `rte_graph_feature_t` object for an interface. `rte_edge` from +`start` node to first enabled feature is provided by +``rte_graph_feature_arc_feature_set()`` API. + +In `feature nodes`, next enabled feature is obtained by providing current feature +as an input to ``rte_graph_feature_arc_next_feature_get()`` API. + +Feature data +************ +Feature data object is maintained per feature per interface which holds +following information in fast path + +- ``rte_edge_t`` to send packet to next enabled feature +- ``Next enabled feature`` on current interface +- ``User_data`` per feature per interface set by application via `rte_graph_feature_enable()` + +Enabling Feature Arc processing +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +By default, feature arc processing is disabled in `rte_graph_create()`. To +enable feature arc processing in fast path, `rte_graph_create()` API should be +invoked with `feature_arc_enable` flag set as `true` + +.. code-block:: bash + :linenos: + :emphasize-lines: 3 + :caption: Enabling feature are processing in rte_graph_create() + + struct rte_graph_param graph_conf; + + graph_conf.feature_arc_enable = true; + struct rte_graph *graph = rte_graph_create("graph_name", &graph_conf); + +Further as an optimization technique, `rte_graph_walk()` would call newly added +``feat_arc_proc()`` node callback function (if non-NULL) instead of +``process`` + +.. code-block:: bash + :linenos: + :emphasize-lines: 3 + :caption: Feature arc specific node callback function + + static struct rte_node_register ip4_rewrite_node = { + .process = ip4_rewrite_node_process, + .feat_arc_proc = ip4_rewrite_feature_node_process, + .name = "ip4_rewrite", + ... + ... + }; + +If `feat_arc_proc` is not provided in node registration, `process_func` would +be called by `rte_graph_walk()` + +Sample Usage +^^^^^^^^^^^^ +.. code-block:: bash + :linenos: + :caption: Feature arc sample usage + + #define MAX_FEATURES 10 + #define MAX_INDEXES 5 + + static uint16_t + feature2_feature_node_process (struct rte_graph *graph, struct + rte_node *node, void **objs, uint16_t nb_objs) + { + /* features may be enabled */ + } + static uint16_t + feature2_node_process (struct rte_graph *graph, struct + rte_node *node, void **objs, uint16_t nb_objs) + { + /* Feature arc is disabled in rte_graph_create() */ + } + + static uint16_t + feature2_node_process (struct rte_graph *graph, struct + rte_node *node, void **objs, uint16_t nb_objs) + { + /* Feature arc may be enabled or disabled as this process_func() would + * be called for the case when feature arc is enabled in rte_graph_create() + * and also the case when it is disabled + */ + } + + static struct rte_node_register feature2_node = { + .process = feature2_node_process, + .feat_arc_proc = feature2_feature_node_process, + .name = "feature2", + .init = feature2_init_func, + ... + ... + }; + + static struct rte_node_register feature1_node = { + .process = feature1_node_process, + .feat_arc_proc = NULL, + .name = "feature1", + ... + ... + }; + + int worker_cb(void *_em) + { + rte_graph_feature_arc_t arc; + uint32_t user_data; + + rte_graph_feature_arc_lookup_by_name("sample_arc", &arc); + + /* From control thread context (like CLII): + * Enable feature 2 on interface index 4 + */ + if (rte_lcore_id() == rte_get_main_lcore) { + user_data = 0x1234; + rte_graph_feature_enable(arc, 4 /* interface index */, "feature2", user_data); + } else { + while(1) + rte_graph_walk); + } + } + + int main(void) + { + struct rte_graph_param graph_conf; + rte_graph_feature_arc_t arc; + + if (rte_graph_feature_arc_create("sample_arc", MAX_FEATURES, MAX_INDEXES, &arc)) + return -1; + + rte_graph_feature_add(arc, "feature1", NULL, NULL); + rte_graph_feature_add(arc, "feature2", "feature1" /* add feature2 after feature 1*/, NULL); + + /* create graph*/ + ... + ... + graph_conf.feature_arc_enable = true; + + struct rte_graph *graph = rte_graph_create("sample_graph", &graph_conf); + + rte_eal_mp_remote_launch(worker_cb, arg, CALL_MAIN); + } diff --git a/doc/guides/prog_guide/img/feature_arc-1.svg b/doc/guides/prog_guide/img/feature_arc-1.svg new file mode 100644 index 0000000000..dada169e11 --- /dev/null +++ b/doc/guides/prog_guide/img/feature_arc-1.svg @@ -0,0 +1,277 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<!-- SPDX-License-Identifier: BSD-3-Clause --> +<!-- Copyright(C) 2024 Marvell International Ltd. --> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + id="svg4977" + version="1.1" + overflow="hidden" + xml:space="preserve" + height="1455" + width="1995"><metadata + id="metadata4983"><rdf:RDF><cc:Work + rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs + id="defs4981" /><g + id="g4975" + transform="translate(-637 -359)"><path + id="path4901" + fill-rule="evenodd" + fill="#00B5E2" + stroke-miterlimit="8" + stroke-width="6.875" + stroke="#212322" + d="M640.5 543.5C640.5 460.657 788.917 393.5 972 393.5 1155.08 393.5 1303.5 460.657 1303.5 543.5 1303.5 626.343 1155.08 693.5 972 693.5 788.917 693.5 640.5 626.343 640.5 543.5Z" /><text + id="text4903" + transform="matrix(1 0 0 1 831.669 574)" + font-size="83" + font-weight="400" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#FFFFFF">Node</text> +<text + id="text4905" + transform="matrix(1 0 0 1 1028.75 574)" + font-size="83" + font-weight="400" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#FFFFFF">-</text> +<text + id="text4907" + transform="matrix(1 0 0 1 1056.25 574)" + font-size="83" + font-weight="400" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#FFFFFF">A</text> +<path + id="path4909" + fill-rule="evenodd" + fill="#00B5E2" + stroke-miterlimit="8" + stroke-width="6.875" + stroke="#212322" + d="M640.5 1660.5C640.5 1577.66 788.917 1510.5 972 1510.5 1155.08 1510.5 1303.5 1577.66 1303.5 1660.5 1303.5 1743.34 1155.08 1810.5 972 1810.5 788.917 1810.5 640.5 1743.34 640.5 1660.5Z" /><text + id="text4911" + transform="matrix(1 0 0 1 831.669 1691)" + font-size="83" + font-weight="400" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#FFFFFF">Node</text> +<text + id="text4913" + transform="matrix(1 0 0 1 1028.75 1691)" + font-size="83" + font-weight="400" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#FFFFFF">-</text> +<text + id="text4915" + transform="matrix(1 0 0 1 1056.25 1691)" + font-size="83" + font-weight="400" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#FFFFFF">B</text> +<path + id="path4917" + fill-rule="evenodd" + fill="#00B050" + stroke-miterlimit="8" + stroke-width="6.875" + stroke="#212322" + d="M1303.5 1132.5C1303.5 1049.66 1452.14 982.5 1635.5 982.5 1818.86 982.5 1967.5 1049.66 1967.5 1132.5 1967.5 1215.34 1818.86 1282.5 1635.5 1282.5 1452.14 1282.5 1303.5 1215.34 1303.5 1132.5Z" /><text + id="text4919" + transform="matrix(1 0 0 1 1455.56 1159)" + font-size="73" + font-weight="400" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#FFFFFF">Feature </text> +<text + id="text4921" + transform="matrix(1 0 0 1 1728.84 1159)" + font-size="73" + font-weight="400" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#FFFFFF">-</text> +<text + id="text4923" + transform="matrix(1 0 0 1 1774.1 1159)" + font-size="73" + font-weight="400" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#FFFFFF">1</text> +<path + id="path4925" + fill="#63666A" + d="M977.875 693 977.875 1475.28 964.125 1475.28 964.125 693ZM991.625 1468.41 971 1509.66 950.375 1468.41Z" /><path + id="path4927" + fill="#003967" + d="M972.869 690.347 998.093 701.303 995.354 707.609 970.13 696.653ZM1017.01 709.52 1042.23 720.476 1039.49 726.782 1014.27 715.826ZM1061.15 728.693 1086.37 739.649 1083.64 745.955 1058.41 734.999ZM1105.29 747.866 1130.52 758.822 1127.78 765.127 1102.55 754.172ZM1149.43 767.039 1174.66 777.995 1171.92 784.3 1146.69 773.344ZM1193.57 786.211 1218.8 797.167 1216.06 803.473 1190.83 792.517ZM1237.71 805.384 1262.94 816.34 1260.2 822.646 1234.98 811.69ZM1281.86 824.557 1307.08 835.513 1304.34 841.819 1279.12 830.863ZM1326 843.73 1351.22 854.686 1348.48 860.992 1323.26 850.036ZM1370.14 862.903 1395.36 873.859 1392.62 880.165 1367.4 869.209ZM1414.28 882.076 1439.5 893.032 1436.76 899.338 1411.54 888.382ZM1458.42 901.249 1483.64 912.205 1480.9 918.511 1455.68 907.555ZM1502.56 920.422 1527.78 931.378 1525.04 937.684 1499.82 926.728ZM1546.7 939.595 1571.92 950.551 1569.18 956.857 1543.96 945.901ZM1590.84 958.768 1615.56 969.504 1612.82 975.81 1588.1 965.074ZM1615.46 958.219 1635.21 981.786 1604.51 983.442Z" /><path + id="path4929" + transform="matrix(-1 0 0 1 1635.21 1282.5)" + fill="#003967" + d="M1.11695-3.25097 27.1247 5.68467 24.8908 12.1866-1.11695 3.25097ZM46.6306 12.3864 72.6383 21.322 70.4044 27.824 44.3967 18.8883ZM92.1442 28.0238 118.152 36.9594 115.918 43.4613 89.9103 34.5257ZM137.658 43.6611 163.666 52.5968 161.432 59.0987 135.424 50.1631ZM183.171 59.2985 209.179 68.2341 206.945 74.7361 180.937 65.8004ZM228.685 74.9359 254.693 83.8715 252.459 90.3734 226.451 81.4378ZM274.199 90.5732 300.206 99.5089 297.972 106.011 271.965 97.0752ZM319.712 106.211 345.72 115.146 343.486 121.648 317.478 112.713ZM365.226 121.848 391.234 130.784 389 137.286 362.992 128.35ZM410.739 137.485 436.747 146.421 434.513 152.923 408.505 143.987ZM456.253 153.123 482.261 162.058 480.027 168.56 454.019 159.625ZM501.767 168.76 527.774 177.696 525.54 184.198 499.533 175.262ZM547.28 184.397 573.288 193.333 571.054 199.835 545.046 190.899ZM592.794 200.035 618.802 208.97 616.568 215.472 590.56 206.537ZM638.307 215.672 643.152 217.337 640.918 223.839 636.073 222.174ZM642.168 206.094 663.708 228.034 633.232 232.102Z" /><text + id="text4931" + transform="matrix(-1.83697e-16 -1 1 -1.83697e-16 943.025 1309)" + font-size="55" + font-weight="400" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">Static Packet Path</text> +<text + id="text4933" + transform="matrix(-1.83697e-16 -1 1 -1.83697e-16 1009.03 1200)" + font-size="55" + font-weight="400" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">edge == 0</text> +<text + id="text4935" + transform="matrix(0.916122 0.4009 -0.4009 0.916122 1103.93 809)" + font-size="64" + font-weight="400" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">edge == 1</text> +<text + id="text4937" + transform="matrix(1 0 0 1 1522.09 429)" + font-size="55" + font-weight="700" + font-style="italic" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">Source/Start </text> +<text + id="text4939" + transform="matrix(1 0 0 1 1620.06 495)" + font-size="55" + font-weight="400" + font-style="italic" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">Node</text> +<text + id="text4941" + transform="matrix(1 0 0 1 1618.96 1583)" + font-size="55" + font-weight="700" + font-style="italic" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">End/Sink</text> +<text + id="text4943" + transform="matrix(1 0 0 1 1671.66 1649)" + font-size="55" + font-weight="400" + font-style="italic" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">Node</text> +<text + id="text4945" + transform="matrix(1 0 0 1 2196.79 1078)" + font-size="55" + font-weight="700" + font-style="italic" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">Feature</text> +<text + id="text4947" + transform="matrix(1 0 0 1 2230.59 1144)" + font-size="55" + font-weight="400" + font-style="italic" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">Node</text> +<path + id="path4949" + transform="matrix(-1 0 0 1 1486.34 450.5)" + fill="#63666A" + d="M0.259414-0.510821 162.664 81.9641 162.145 82.9858-0.259414 0.510821ZM164.544 68.1399 182.837 92.8515 152.092 92.6593Z" /><path + id="path4951" + transform="matrix(-1 0 0 1 1537.94 1604.5)" + fill="#63666A" + d="M0.133795-0.557075 212.291 50.3976 212.023 51.5117-0.133795 0.557075ZM210.911 36.5145 234.44 56.3064 204.489 63.2541Z" /><path + id="path4953" + transform="matrix(-1 0 0 1 2159.31 1099.5)" + fill="#63666A" + d="M0.0965444-0.564724 169.317 28.3649 169.124 29.4944-0.0965444 0.564724ZM167.019 14.6039 191.809 32.7914 162.385 41.7106Z" /><path + id="path4955" + transform="matrix(-1 0 0 1 1737.41 724.5)" + fill="#63666A" + d="M0.229683-0.524861 295.142 128.531 294.683 129.581-0.229683 0.524861ZM296.226 114.622 315.907 138.243 285.201 139.815Z" /><text + id="text4957" + transform="matrix(1 0 0 1 1833.68 703)" + font-size="55" + font-weight="400" + font-style="italic" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">Packet path gets activated in </text> +<text + id="text4959" + transform="matrix(1 0 0 1 1865.62 769)" + text-decoration="underline" + font-size="55" + font-weight="400" + font-style="italic" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">Node</text> +<text + id="text4961" + transform="matrix(1 0 0 1 1996.25 769)" + text-decoration="underline" + font-size="55" + font-weight="400" + font-style="italic" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">-</text> +<text + id="text4963" + transform="matrix(1 0 0 1 2014.58 769)" + text-decoration="underline" + font-size="55" + font-weight="400" + font-style="italic" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">A</text> +<text + id="text4965" + transform="matrix(1 0 0 1 2064.68 769)" + font-size="55" + font-weight="400" + font-style="italic" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">when Feature</text> +<text + id="text4967" + transform="matrix(1 0 0 1 2399.83 769)" + font-size="55" + font-weight="400" + font-style="italic" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">-</text> +<text + id="text4969" + transform="matrix(1 0 0 1 2418.17 769)" + font-size="55" + font-weight="400" + font-style="italic" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">1 is </text> +<text + id="text4971" + transform="matrix(1 0 0 1 1898.42 835)" + font-size="55" + font-weight="400" + font-style="italic" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">enabled on </text> +<text + id="text4973" + transform="matrix(1 0 0 1 2184.3 835)" + text-decoration="underline" + font-size="55" + font-weight="400" + font-style="italic" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">an interface</text> +</g></svg> diff --git a/doc/guides/prog_guide/img/feature_arc-2.svg b/doc/guides/prog_guide/img/feature_arc-2.svg new file mode 100644 index 0000000000..eb5fb37e04 --- /dev/null +++ b/doc/guides/prog_guide/img/feature_arc-2.svg @@ -0,0 +1,511 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<!-- SPDX-License-Identifier: BSD-3-Clause --> +<!-- Copyright(C) 2024 Marvell International Ltd. --> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + id="svg152" + version="1.1" + overflow="hidden" + xml:space="preserve" + height="1483" + width="3471"><metadata + id="metadata158"><rdf:RDF><cc:Work + rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs + id="defs156" /><g + id="g150" + transform="translate(-637 -331)"><path + id="path2" + fill-rule="evenodd" + fill="#00B5E2" + stroke-miterlimit="8" + stroke-width="6.875" + stroke="#212322" + d="M640.5 543.5C640.5 460.657 788.917 393.5 972 393.5 1155.08 393.5 1303.5 460.657 1303.5 543.5 1303.5 626.343 1155.08 693.5 972 693.5 788.917 693.5 640.5 626.343 640.5 543.5Z" /><text + id="text4" + transform="matrix(1 0 0 1 831.669 574)" + font-size="83" + font-weight="400" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#FFFFFF">Node</text> +<text + id="text6" + transform="matrix(1 0 0 1 1028.75 574)" + font-size="83" + font-weight="400" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#FFFFFF">-</text> +<text + id="text8" + transform="matrix(1 0 0 1 1056.25 574)" + font-size="83" + font-weight="400" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#FFFFFF">A</text> +<path + id="path10" + fill-rule="evenodd" + fill="#00B5E2" + stroke-miterlimit="8" + stroke-width="6.875" + stroke="#212322" + d="M640.5 1660.5C640.5 1577.66 788.917 1510.5 972 1510.5 1155.08 1510.5 1303.5 1577.66 1303.5 1660.5 1303.5 1743.34 1155.08 1810.5 972 1810.5 788.917 1810.5 640.5 1743.34 640.5 1660.5Z" /><text + id="text12" + transform="matrix(1 0 0 1 831.669 1691)" + font-size="83" + font-weight="400" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#FFFFFF">Node</text> +<text + id="text14" + transform="matrix(1 0 0 1 1028.75 1691)" + font-size="83" + font-weight="400" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#FFFFFF">-</text> +<text + id="text16" + transform="matrix(1 0 0 1 1056.25 1691)" + font-size="83" + font-weight="400" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#FFFFFF">B</text> +<path + id="path18" + fill-rule="evenodd" + fill="#00B050" + stroke-miterlimit="8" + stroke-width="6.875" + stroke="#212322" + d="M1303.5 1132.5C1303.5 1049.66 1452.14 982.5 1635.5 982.5 1818.86 982.5 1967.5 1049.66 1967.5 1132.5 1967.5 1215.34 1818.86 1282.5 1635.5 1282.5 1452.14 1282.5 1303.5 1215.34 1303.5 1132.5Z" /><text + id="text20" + transform="matrix(1 0 0 1 1455.56 1159)" + font-size="73" + font-weight="400" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#FFFFFF">Feature </text> +<text + id="text22" + transform="matrix(1 0 0 1 1728.84 1159)" + font-size="73" + font-weight="400" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#FFFFFF">-</text> +<text + id="text24" + transform="matrix(1 0 0 1 1774.1 1159)" + font-size="73" + font-weight="400" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#FFFFFF">1</text> +<path + id="path26" + fill="#63666A" + d="M974.937 693.5 974.938 1487.24 968.063 1487.24 968.062 693.5ZM985.25 1482.66 971.5 1510.16 957.75 1482.66Z" /><path + id="path28" + fill="#003967" + d="M972.869 690.347 998.093 701.303 995.354 707.609 970.13 696.653ZM1017.01 709.52 1042.23 720.476 1039.49 726.782 1014.27 715.826ZM1061.15 728.693 1086.37 739.649 1083.64 745.955 1058.41 734.999ZM1105.29 747.866 1130.52 758.822 1127.78 765.127 1102.55 754.172ZM1149.43 767.039 1174.66 777.995 1171.92 784.3 1146.69 773.344ZM1193.57 786.211 1218.8 797.167 1216.06 803.473 1190.83 792.517ZM1237.71 805.384 1262.94 816.34 1260.2 822.646 1234.98 811.69ZM1281.86 824.557 1307.08 835.513 1304.34 841.819 1279.12 830.863ZM1326 843.73 1351.22 854.686 1348.48 860.992 1323.26 850.036ZM1370.14 862.903 1395.36 873.859 1392.62 880.165 1367.4 869.209ZM1414.28 882.076 1439.5 893.032 1436.76 899.338 1411.54 888.382ZM1458.42 901.249 1483.64 912.205 1480.9 918.511 1455.68 907.555ZM1502.56 920.422 1527.78 931.378 1525.04 937.684 1499.82 926.728ZM1546.7 939.595 1571.92 950.551 1569.18 956.857 1543.96 945.901ZM1590.84 958.768 1615.56 969.504 1612.82 975.81 1588.1 965.074ZM1615.46 958.219 1635.21 981.786 1604.51 983.442Z" /><path + id="path30" + transform="matrix(-1 0 0 1 1400.55 1238.5)" + fill="#003967" + d="M1.84062-2.90319 25.0662 11.8217 21.3849 17.6281-1.84062 2.90319ZM42.4853 22.8654 65.7109 37.5903 62.0297 43.3967 38.8041 28.6718ZM83.1301 48.634 106.356 63.359 102.674 69.1653 79.4488 54.4404ZM123.775 74.4026 147 89.1276 143.319 94.934 120.094 80.209ZM164.42 100.171 187.645 114.896 183.964 120.703 160.738 105.978ZM205.064 125.94 228.29 140.665 224.609 146.471 201.383 131.746ZM245.709 151.708 268.935 166.433 265.253 172.24 242.028 157.515ZM286.354 177.477 309.579 192.202 305.898 198.008 282.672 183.283ZM326.998 203.246 350.224 217.971 346.543 223.777 323.317 209.052ZM367.643 229.014 390.869 243.739 387.188 249.546 363.962 234.821ZM408.288 254.783 411.537 256.843 407.856 262.649 404.607 260.589ZM413.188 245.68 429.052 272.017 398.464 268.905Z" /><text + id="text32" + transform="matrix(-1.83697e-16 -1 1 -1.83697e-16 961.015 1340)" + font-size="64" + font-weight="400" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">Static Packet</text> +<text + id="text34" + transform="matrix(-1.83697e-16 -1 1 -1.83697e-16 961.015 945)" + font-size="64" + font-weight="400" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">Path</text> +<text + id="text36" + transform="matrix(-1.83697e-16 -1 1 -1.83697e-16 1040.01 1221)" + font-size="64" + font-weight="400" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">edge == 0</text> +<text + id="text38" + transform="matrix(0.916122 0.4009 -0.4009 0.916122 1100.07 807)" + font-size="64" + font-weight="400" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">edge == 1</text> +<path + id="path40" + fill-rule="evenodd" + fill="#A6A6A6" + stroke-miterlimit="8" + stroke-width="6.875" + stroke="#212322" + d="M3429.5 1088C3429.5 1004.88 3577.92 937.5 3761 937.5 3944.08 937.5 4092.5 1004.88 4092.5 1088 4092.5 1171.12 3944.08 1238.5 3761 1238.5 3577.92 1238.5 3429.5 1171.12 3429.5 1088Z" /><text + id="text42" + transform="matrix(1 0 0 1 3583.93 1068)" + font-size="83" + font-weight="400" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#FFFFFF">Custom </text> +<text + id="text44" + transform="matrix(1 0 0 1 3891.02 1068)" + font-size="83" + font-weight="400" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#FFFFFF">–</text> +<text + id="text46" + transform="matrix(1 0 0 1 3618.31 1167)" + font-size="83" + font-weight="400" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#FFFFFF">Feature</text> +<path + id="path48" + fill="#003967" + d="M971.811 690.076 999.198 692.567 998.576 699.413 971.189 696.923ZM1019.74 694.434 1047.13 696.924 1046.5 703.771 1019.12 701.281ZM1067.67 698.792 1095.05 701.282 1094.43 708.129 1067.04 705.639ZM1115.59 703.15 1142.98 705.64 1142.36 712.487 1114.97 709.996ZM1163.52 707.507 1190.91 709.997 1190.28 716.844 1162.9 714.354ZM1211.45 711.865 1238.83 714.355 1238.21 721.202 1210.83 718.712ZM1259.38 716.223 1286.76 718.713 1286.14 725.56 1258.75 723.07ZM1307.3 720.581 1334.69 723.071 1334.07 729.917 1306.68 727.427ZM1355.23 724.938 1382.62 727.428 1381.99 734.275 1354.61 731.785ZM1403.16 729.296 1430.54 731.786 1429.92 738.633 1402.53 736.143ZM1451.08 733.654 1478.47 736.144 1477.85 742.991 1450.46 740.5ZM1499.01 738.011 1526.4 740.502 1525.78 747.348 1498.39 744.858ZM1546.94 742.369 1574.33 744.859 1573.7 751.706 1546.32 749.216ZM1594.87 746.727 1622.25 749.217 1621.63 756.064 1594.24 753.574ZM1642.79 751.085 1670.18 753.575 1669.56 760.421 1642.17 757.931ZM1690.72 755.442 1718.11 757.932 1717.49 764.779 1690.1 762.289ZM1738.65 759.8 1766.04 762.29 1765.41 769.137 1738.03 766.647ZM1786.58 764.158 1813.96 766.648 1813.34 773.495 1785.95 771.004ZM1834.5 768.515 1861.89 771.006 1861.27 777.852 1833.88 775.362ZM1882.43 772.873 1909.82 775.363 1909.19 782.21 1881.81 779.72ZM1930.36 777.231 1957.74 779.721 1957.12 786.568 1929.73 784.078ZM1978.28 781.589 2005.67 784.079 2005.05 790.925 1977.66 788.435ZM2026.21 785.946 2053.6 788.436 2052.98 795.283 2025.59 792.793ZM2074.14 790.304 2101.53 792.794 2100.9 799.641 2073.52 797.151ZM2122.07 794.662 2149.45 797.152 2148.83 803.999 2121.44 801.509ZM2169.99 799.019 2197.38 801.51 2196.76 808.356 2169.37 805.866ZM2217.92 803.377 2245.31 805.867 2244.69 812.714 2217.3 810.224ZM2265.85 807.735 2293.24 810.225 2292.61 817.072 2265.23 814.582ZM2313.78 812.093 2341.16 814.583 2340.54 821.43 2313.15 818.939ZM2361.7 816.45 2389.09 818.94 2388.47 825.787 2361.08 823.297ZM2409.63 820.808 2437.02 823.298 2436.4 830.145 2409.01 827.655ZM2457.56 825.166 2484.95 827.656 2484.32 834.503 2456.94 832.013ZM2505.49 829.523 2532.87 832.014 2532.25 838.86 2504.86 836.37ZM2553.41 833.881 2580.8 836.371 2580.18 843.218 2552.79 840.728ZM2601.34 838.239 2628.73 840.729 2628.1 847.576 2600.72 845.086ZM2649.27 842.597 2676.65 845.087 2676.03 851.934 2648.64 849.443ZM2697.19 846.954 2724.58 849.445 2723.96 856.291 2696.57 853.801ZM2745.12 851.312 2772.51 853.802 2771.89 860.649 2744.5 858.159ZM2793.05 855.67 2820.44 858.16 2819.81 865.007 2792.43 862.517ZM2840.98 860.028 2868.36 862.518 2867.74 869.364 2840.35 866.874ZM2888.9 864.385 2916.29 866.875 2915.67 873.722 2888.28 871.232ZM2936.83 868.743 2964.22 871.233 2963.59 878.08 2936.21 875.59ZM2984.76 873.101 3012.14 875.591 3011.52 882.438 2984.14 879.947ZM3032.68 877.458 3060.07 879.949 3059.45 886.795 3032.06 884.305ZM3080.61 881.816 3108 884.306 3107.38 891.153 3079.99 888.663ZM3128.54 886.174 3155.93 888.664 3155.3 895.511 3127.92 893.021ZM3176.47 890.532 3203.85 893.022 3203.23 899.869 3175.84 897.378ZM3224.39 894.889 3251.78 897.379 3251.16 904.226 3223.77 901.736ZM3272.32 899.247 3299.71 901.737 3299.09 908.584 3271.7 906.094ZM3320.25 903.605 3347.64 906.095 3347.01 912.942 3319.63 910.452ZM3368.18 907.963 3395.56 910.453 3394.94 917.299 3367.55 914.809ZM3416.1 912.32 3443.49 914.81 3442.87 921.657 3415.48 919.167ZM3464.03 916.678 3491.42 919.168 3490.8 926.015 3463.41 923.525ZM3511.96 921.036 3539.34 923.526 3538.72 930.373 3511.34 927.882ZM3559.89 925.393 3587.27 927.884 3586.65 934.73 3559.26 932.24ZM3607.81 929.751 3630.27 931.793 3629.65 938.64 3607.19 936.598ZM3626.64 921.108 3652.78 937.292 3624.15 948.495Z" /><text + id="text50" + transform="matrix(0.993978 0.109578 -0.109578 0.993978 1324.46 704)" + font-size="64" + font-weight="400" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">edge == 3</text> +<path + id="path52" + fill-rule="evenodd" + fill="#00B050" + stroke-miterlimit="8" + stroke-width="6.875" + stroke="#212322" + d="M2326.5 1136.5C2326.5 1053.66 2475.14 986.5 2658.5 986.5 2841.86 986.5 2990.5 1053.66 2990.5 1136.5 2990.5 1219.34 2841.86 1286.5 2658.5 1286.5 2475.14 1286.5 2326.5 1219.34 2326.5 1136.5Z" /><text + id="text54" + transform="matrix(1 0 0 1 2478.16 1163)" + font-size="73" + font-weight="400" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#FFFFFF">Feature </text> +<text + id="text56" + transform="matrix(1 0 0 1 2751.44 1163)" + font-size="73" + font-weight="400" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#FFFFFF">-</text> +<text + id="text58" + transform="matrix(1 0 0 1 2796.7 1163)" + font-size="73" + font-weight="400" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#FFFFFF">2</text> +<path + id="path60" + fill="#003967" + d="M972.27 690.15 999.071 696.312 997.53 703.012 970.73 696.85ZM1019.17 700.934 1045.97 707.096 1044.43 713.796 1017.63 707.634ZM1066.07 711.717 1092.87 717.88 1091.33 724.58 1064.53 718.417ZM1112.97 722.501 1139.77 728.663 1138.23 735.363 1111.43 729.201ZM1159.88 733.285 1186.68 739.447 1185.14 746.147 1158.33 739.985ZM1206.78 744.069 1233.58 750.231 1232.04 756.931 1205.24 750.769ZM1253.68 754.853 1280.48 761.015 1278.94 767.715 1252.14 761.553ZM1300.58 765.636 1327.38 771.799 1325.84 778.499 1299.04 772.336ZM1347.48 776.42 1374.28 782.582 1372.74 789.282 1345.94 783.12ZM1394.38 787.204 1421.18 793.366 1419.64 800.066 1392.84 793.904ZM1441.28 797.988 1468.08 804.15 1466.54 810.85 1439.74 804.688ZM1488.18 808.772 1514.98 814.934 1513.44 821.634 1486.64 815.472ZM1535.08 819.555 1561.89 825.718 1560.34 832.418 1533.54 826.255ZM1581.99 830.339 1608.79 836.501 1607.25 843.201 1580.45 837.039ZM1628.89 841.123 1655.69 847.285 1654.15 853.985 1627.35 847.823ZM1675.79 851.907 1702.59 858.069 1701.05 864.769 1674.25 858.607ZM1722.69 862.691 1749.49 868.853 1747.95 875.553 1721.15 869.391ZM1769.59 873.474 1796.39 879.637 1794.85 886.337 1768.05 880.175ZM1816.49 884.258 1843.29 890.42 1841.75 897.121 1814.95 890.958ZM1863.39 895.042 1890.19 901.204 1888.65 907.904 1861.85 901.742ZM1910.29 905.826 1937.1 911.988 1935.55 918.688 1908.75 912.526ZM1957.2 916.61 1984 922.772 1982.46 929.472 1955.66 923.31ZM2004.1 927.393 2030.9 933.556 2029.36 940.256 2002.56 934.094ZM2051 938.177 2077.8 944.339 2076.26 951.04 2049.46 944.877ZM2097.9 948.961 2124.7 955.123 2123.16 961.823 2096.36 955.661ZM2144.8 959.745 2171.6 965.907 2170.06 972.607 2143.26 966.445ZM2191.7 970.529 2218.5 976.691 2216.96 983.391 2190.16 977.229ZM2238.6 981.312 2265.4 987.475 2263.86 994.175 2237.06 988.013ZM2285.5 992.096 2312.31 998.258 2310.76 1004.96 2283.96 998.796ZM2332.41 1002.88 2359.21 1009.04 2357.67 1015.74 2330.87 1009.58ZM2379.31 1013.66 2406.06 1019.81 2404.52 1026.52 2377.77 1020.36ZM2403.91 1008.74 2427.62 1028.3 2397.74 1035.54Z" /><path + id="path62" + transform="matrix(-1 0 0 1 2658.15 1286.5)" + fill="#003967" + d="M0.62373-3.38044 27.6672 1.6094 26.4198 8.37028-0.62373 3.38044ZM47.9499 5.35178 74.9934 10.3416 73.7459 17.1025 46.7024 12.1127ZM95.276 14.084 122.32 19.0738 121.072 25.8347 94.0286 20.8449ZM142.602 22.8162 169.646 27.8061 168.398 34.5669 141.355 29.5771ZM189.928 31.5484 216.972 36.5383 215.724 43.2991 188.681 38.3093ZM237.254 40.2806 264.298 45.2705 263.051 52.0314 236.007 47.0415ZM284.581 49.0129 311.624 54.0027 310.377 60.7636 283.333 55.7737ZM331.907 57.7451 358.95 62.7349 357.703 69.4958 330.659 64.506ZM379.233 66.4773 406.276 71.4671 405.029 78.228 377.985 73.2382ZM426.559 75.2095 453.603 80.1994 452.355 86.9602 425.312 81.9704ZM473.885 83.9417 500.929 88.9316 499.681 95.6925 472.638 90.7026ZM521.211 92.674 548.255 97.6638 547.008 104.425 519.964 99.4348ZM568.538 101.406 595.581 106.396 594.334 113.157 567.29 108.167ZM615.864 110.138 642.907 115.128 641.66 121.889 614.616 116.899ZM663.19 118.871 690.233 123.86 688.986 130.621 661.942 125.631ZM710.516 127.603 737.56 132.593 736.312 139.354 709.269 134.364ZM757.842 136.335 784.886 141.325 783.638 148.086 756.595 143.096ZM805.168 145.067 832.212 150.057 830.964 156.818 803.921 151.828ZM852.494 153.799 879.538 158.789 878.29 165.55 851.247 160.56ZM899.82 162.532 926.864 167.522 925.617 174.282 898.573 169.293ZM947.147 171.264 974.19 176.254 972.943 183.015 945.899 178.025ZM994.473 179.996 1021.52 184.986 1020.27 191.747 993.225 186.757ZM1041.8 188.728 1068.84 193.718 1067.59 200.479 1040.55 195.489ZM1089.12 197.461 1116.17 202.45 1114.92 209.211 1087.88 204.221ZM1136.45 206.193 1163.49 211.183 1162.25 217.943 1135.2 212.954ZM1183.78 214.925 1210.82 219.915 1209.57 226.676 1182.53 221.686ZM1231.1 223.657 1258.15 228.647 1256.9 235.408 1229.86 230.418ZM1278.43 232.389 1305.47 237.379 1304.23 244.14 1277.18 239.15ZM1325.76 241.122 1352.8 246.111 1351.55 252.872 1324.51 247.883ZM1373.08 249.854 1400.13 254.844 1398.88 261.605 1371.83 256.615ZM1420.41 258.586 1429.74 260.308 1428.49 267.068 1419.16 265.347ZM1427.1 249.334 1451.65 267.846 1422.11 276.378Z" /><path + id="path64" + transform="matrix(-1 0 0 1 3760.78 1238.5)" + fill="#003967" + d="M0.422723-3.41141 27.714-0.0296238 26.8685 6.79319-0.422723 3.41141ZM48.1824 2.50672 75.4737 5.8885 74.6283 12.7113 47.337 9.32953ZM95.9422 8.42484 123.233 11.8066 122.388 18.6294 95.0967 15.2477ZM143.702 14.343 170.993 17.7248 170.148 24.5476 142.856 21.1658ZM191.462 20.2611 218.753 23.6429 217.907 30.4657 190.616 27.0839ZM239.221 26.1792 266.513 29.561 265.667 36.3838 238.376 33.002ZM286.981 32.0973 314.272 35.4791 313.427 42.3019 286.136 38.9202ZM334.741 38.0155 362.032 41.3972 361.187 48.2201 333.895 44.8383ZM382.501 43.9336 409.792 47.3154 408.946 54.1382 381.655 50.7564ZM430.26 49.8517 457.552 53.2335 456.706 60.0563 429.415 56.6745ZM478.02 55.7698 505.311 59.1516 504.466 65.9744 477.175 62.5927ZM525.78 61.688 553.071 65.0697 552.226 71.8926 524.934 68.5108ZM573.539 67.6061 600.831 70.9879 599.985 77.8107 572.694 74.4289ZM621.299 73.5242 648.59 76.906 647.745 83.7288 620.454 80.347ZM669.059 79.4423 696.35 82.8241 695.505 89.6469 668.213 86.2652ZM716.819 85.3605 744.11 88.7423 743.264 95.5651 715.973 92.1833ZM764.578 91.2786 791.87 94.6604 791.024 101.483 763.733 98.1014ZM812.338 97.1967 839.629 100.579 838.784 107.401 811.493 104.02ZM860.098 103.115 887.389 106.497 886.544 113.319 859.253 109.938ZM907.858 109.033 935.149 112.415 934.304 119.238 907.012 115.856ZM955.617 114.951 982.909 118.333 982.063 125.156 954.772 121.774ZM1003.38 120.869 1030.67 124.251 1029.82 131.074 1002.53 127.692ZM1051.14 126.787 1078.43 130.169 1077.58 136.992 1050.29 133.61ZM1098.9 132.705 1126.19 136.087 1125.34 142.91 1098.05 139.528ZM1146.66 138.624 1173.95 142.005 1173.1 148.828 1145.81 145.446ZM1194.42 144.542 1221.71 147.924 1220.86 154.746 1193.57 151.365ZM1242.18 150.46 1269.47 153.842 1268.62 160.664 1241.33 157.283ZM1289.94 156.378 1317.23 159.76 1316.38 166.583 1289.09 163.201ZM1337.7 162.296 1364.99 165.678 1364.14 172.501 1336.85 169.119ZM1385.45 168.214 1412.75 171.596 1411.9 178.419 1384.61 175.037ZM1433.21 174.132 1460.51 177.514 1459.66 184.337 1432.37 180.955ZM1480.97 180.051 1508.27 183.432 1507.42 190.255 1480.13 186.873ZM1528.73 185.969 1556.03 189.35 1555.18 196.173 1527.89 192.791ZM1576.49 191.887 1603.78 195.269 1602.94 202.091 1575.65 198.71ZM1624.25 197.805 1651.54 201.187 1650.7 208.009 1623.41 204.628ZM1672.01 203.723 1699.3 207.105 1698.46 213.928 1671.17 210.546ZM1719.77 209.641 1747.06 213.023 1746.22 219.846 1718.93 216.464ZM1767.53 215.559 1794.82 218.941 1793.98 225.764 1766.69 222.382ZM1815.29 221.477 1842.58 224.859 1841.74 231.682 1814.45 228.3ZM1863.05 227.395 1890.34 230.777 1889.5 237.6 1862.21 234.218ZM1910.81 233.314 1938.1 236.695 1937.26 243.518 1909.97 240.136ZM1958.57 239.232 1985.86 242.613 1985.02 249.436 1957.73 246.054ZM2006.33 245.15 2033.62 248.532 2032.78 255.354 2005.49 251.973ZM2054.09 251.068 2081.38 254.45 2080.54 261.273 2053.25 257.891ZM2101.85 256.986 2129.14 260.368 2128.3 267.191 2101 263.809ZM2149.61 262.904 2176.9 266.286 2176.06 273.109 2148.76 269.727ZM2197.37 268.822 2224.66 272.204 2223.82 279.027 2196.52 275.645ZM2245.13 274.74 2272.42 278.122 2271.58 284.945 2244.28 281.563ZM2292.89 280.659 2320.18 284.04 2319.34 290.863 2292.04 287.481ZM2340.65 286.577 2367.94 289.958 2367.09 296.781 2339.8 293.399ZM2388.41 292.495 2415.7 295.877 2414.85 302.699 2387.56 299.318ZM2436.17 298.413 2463.46 301.795 2462.61 308.618 2435.32 305.236ZM2483.93 304.331 2511.22 307.713 2510.37 314.536 2483.08 311.154ZM2531.69 310.249 2531.97 310.284 2531.12 317.107 2530.84 317.072ZM2528.68 299.485 2554.28 316.512 2525.29 326.776Z" /><text + id="text66" + transform="matrix(0.974105 0.226098 -0.226098 0.974105 1319.22 820)" + font-size="64" + font-weight="400" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">edge == 2</text> +<text + id="text68" + transform="matrix(1 0 0 1 1572.39 1639)" + font-size="64" + font-weight="700" + font-style="italic" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">First Feature</text> +<text + id="text70" + transform="matrix(1 0 0 1 1505.08 1716)" + font-size="64" + font-weight="400" + font-style="italic" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">For Interface </text> +<text + id="text72" + transform="matrix(1 0 0 1 1884.92 1716)" + font-size="64" + font-weight="400" + font-style="italic" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">–</text> +<text + id="text74" + transform="matrix(1 0 0 1 1938.2 1716)" + font-size="64" + font-weight="400" + font-style="italic" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">0,1</text> +<path + id="path76" + fill="#63666A" + d="M1764.3 1561.88 1643.18 1304.21 1647.32 1302.26 1768.45 1559.93ZM1634.76 1313.24 1635.5 1282.5 1659.64 1301.54Z" /><path + id="path78" + fill="#63666A" + d="M1967.54 1129.06 1995.04 1129.38 1994.96 1136.26 1967.46 1135.94ZM2015.66 1129.62 2043.16 1129.94 2043.08 1136.82 2015.58 1136.5ZM2063.78 1130.18 2091.28 1130.5 2091.2 1137.38 2063.7 1137.06ZM2111.91 1130.74 2139.4 1131.06 2139.32 1137.94 2111.83 1137.62ZM2160.03 1131.3 2187.53 1131.62 2187.45 1138.49 2159.95 1138.17ZM2208.15 1131.86 2235.65 1132.18 2235.57 1139.05 2208.07 1138.73ZM2256.27 1132.42 2283.77 1132.74 2283.69 1139.61 2256.19 1139.29ZM2299.05 1122.6 2326.39 1136.67 2298.73 1150.1Z" /><text + id="text80" + transform="matrix(1 0 0 1 2008.67 1117)" + font-size="64" + font-weight="400" + font-style="italic" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">edge == 1 </text> +<text + id="text82" + transform="matrix(1 0 0 1 2307.19 1624)" + font-size="64" + font-weight="700" + font-style="italic" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">Next Feature to Feature</text> +<text + id="text84" + transform="matrix(1 0 0 1 3021.04 1624)" + font-size="64" + font-weight="700" + font-style="italic" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">-</text> +<text + id="text86" + transform="matrix(1 0 0 1 3042.24 1624)" + font-size="64" + font-weight="700" + font-style="italic" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">1</text> +<text + id="text88" + transform="matrix(1 0 0 1 2493.66 1701)" + font-size="64" + font-weight="400" + font-style="italic" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">for Interface</text> +<text + id="text90" + transform="matrix(1 0 0 1 2834.55 1701)" + font-size="64" + font-weight="400" + font-style="italic" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">-</text> +<text + id="text92" + transform="matrix(1 0 0 1 2855.74 1701)" + font-size="64" + font-weight="400" + font-style="italic" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">0</text> +<path + id="path94" + fill="#63666A" + d="M2690.94 1546.47 2659.26 1309.52 2663.81 1308.91 2695.48 1545.86ZM2648.51 1315.58 2658.5 1286.5 2675.77 1311.94Z" /><text + id="text96" + transform="matrix(1 0 0 1 3080.93 1096)" + font-size="64" + font-weight="400" + font-style="italic" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">edge == 0</text> +<path + id="path98" + transform="matrix(1 0 0 -1 2990.5 1125.64)" + fill="#63666A" + d="M0.219926-3.43046 27.6636-1.67105 27.2237 5.18986-0.219926 3.43046ZM48.2463-0.351496 75.69 1.40791 75.2501 8.26883 47.8065 6.50942ZM96.2728 2.72747 123.716 4.48687 123.277 11.3478 95.8329 9.58838ZM144.299 5.80643 171.743 7.56583 171.303 14.4267 143.859 12.6673ZM192.326 8.88539 219.769 10.6448 219.329 17.5057 191.886 15.7463ZM240.352 11.9644 267.796 13.7238 267.356 20.5847 239.912 18.8253ZM288.378 15.0433 315.822 16.8027 315.382 23.6636 287.939 21.9042ZM336.405 18.1223 363.848 19.8817 363.409 26.7426 335.965 24.9832ZM384.431 21.2012 411.875 22.9606 411.435 29.8216 383.991 28.0622ZM412.357 12.6579 438.921 28.1391 410.598 40.1016Z" /><text + id="text100" + transform="matrix(1 0 0 1 3280.81 1634)" + font-size="64" + font-weight="700" + font-style="italic" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">Next Feature to Feature</text> +<text + id="text102" + transform="matrix(1 0 0 1 3994.67 1634)" + font-size="64" + font-weight="700" + font-style="italic" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">-</text> +<text + id="text104" + transform="matrix(1 0 0 1 4015.87 1634)" + font-size="64" + font-weight="700" + font-style="italic" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">1</text> +<text + id="text106" + transform="matrix(1 0 0 1 3480.19 1711)" + font-size="64" + font-weight="400" + font-style="italic" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">for Interface</text> +<text + id="text108" + transform="matrix(1 0 0 1 3821.08 1711)" + font-size="55" + font-weight="400" + font-style="italic" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">-</text> +<text + id="text110" + transform="matrix(1 0 0 1 3839.41 1711)" + font-size="55" + font-weight="400" + font-style="italic" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">1</text> +<path + id="path112" + transform="matrix(1 0 0 -1 3666.5 1556.2)" + fill="#63666A" + d="M2.19695-0.652044 89.9684 295.078 85.5745 296.382-2.19695 0.652044ZM99.6489 287.424 94.2918 317.699 73.2856 295.248Z" /><path + id="path114" + fill="#63666A" + d="M1867.07 1025.81 1867.42 1018.62 1868.49 1011.28 1870.26 1003.97 1872.27 997.989 1878.79 1000.18 1876.82 1006.02 1876.91 1005.73 1875.21 1012.74 1875.27 1012.43 1874.25 1019.45 1874.28 1019.12 1873.93 1026.15ZM1881.7 978.819 1883.97 975.115 1888.98 968.018 1894.59 960.969 1898.61 956.437 1903.75 960.998 1899.8 965.462 1899.91 965.323 1894.42 972.222 1894.54 972.063 1889.65 978.99 1889.77 978.808 1887.55 982.418ZM1913.37 941.594 1914.93 940.127 1922.84 933.284 1931.3 926.497 1934.85 923.839 1938.97 929.343 1935.46 931.966 1935.55 931.895 1927.19 938.606 1927.29 938.525 1919.48 945.281 1919.58 945.188 1918.07 946.609ZM1951.82 911.768 1959.83 906.488 1970.37 899.942 1975.26 897.066 1978.75 902.994 1973.89 905.849 1973.96 905.805 1963.5 912.303 1963.58 912.254 1955.6 917.508ZM1993.34 886.825 2004.89 880.719 2017.33 874.457 2017.91 874.18 2020.88 880.379 2020.34 880.642 2020.39 880.613 2008.01 886.844 2008.07 886.812 1996.55 892.902ZM2036.62 865.351 2043.57 862.173 2057.34 856.155 2061.9 854.247 2064.55 860.591 2060.01 862.488 2060.06 862.466 2046.35 868.46 2046.4 868.437 2039.48 871.603ZM2081.04 846.419 2086.12 844.388 2101.11 838.643 2106.81 836.551 2109.18 843.005 2103.51 845.089 2103.55 845.072 2088.6 850.799 2088.65 850.78 2083.59 852.803ZM2126.26 829.558 2132.27 827.446 2152.4 820.792 2154.55 827.32 2134.45 833.964 2134.52 833.942 2128.55 836.044ZM2172.11 814.467 2198.42 806.467 2200.42 813.044 2174.11 821.045ZM2218.36 800.882 2234.13 796.472 2244.98 793.688 2246.69 800.347 2235.88 803.122 2235.95 803.103 2220.21 807.503ZM2264.95 788.558 2270.62 787.103 2291.76 782.131 2293.34 788.824 2272.23 793.788 2272.3 793.771 2266.66 795.217ZM2311.92 777.466 2338.81 771.695 2340.25 778.417 2313.36 784.188ZM2359.09 767.584 2386.08 762.324 2387.39 769.072 2360.4 774.332ZM2406.45 758.735 2426.94 755.133 2433.62 754.084 2434.69 760.876 2428.04 761.92 2428.1 761.91 2407.64 765.506ZM2453.99 750.883 2468.18 748.653 2481.26 746.839 2482.2 753.649 2469.16 755.459 2469.22 755.45 2455.06 757.674ZM2501.69 744.003 2510.12 742.833 2529.03 740.551 2529.85 747.376 2510.97 749.655 2511.03 749.647 2502.63 750.813ZM2549.51 738.08 2552.66 737.699 2576.92 735.21 2577.62 742.049 2553.39 744.535 2553.45 744.529 2550.33 744.905ZM2597.5 733.13 2624.9 730.813 2625.48 737.664 2598.08 739.98ZM2645.52 729.185 2672.96 727.365 2673.42 734.224 2645.98 736.045ZM2693.62 726.19 2721.08 724.875 2721.41 731.742 2693.94 733.057ZM2741.76 724.16 2769.25 723.361 2769.45 730.233 2741.96 731.032ZM2789.94 723.116 2815.78 722.863 2817.49 722.875 2817.45 729.749 2815.76 729.738 2815.82 729.738 2790.01 729.991ZM2838.12 723.017 2860.13 723.169 2865.66 723.283 2865.52 730.156 2860.01 730.043 2860.06 730.044 2838.07 729.892ZM2886.28 723.705 2904.38 724.076 2913.82 724.394 2913.59 731.265 2904.17 730.948 2904.22 730.949 2886.14 730.579ZM2934.43 725.09 2948.46 725.563 2961.96 726.194 2961.64 733.061 2948.16 732.432 2948.21 732.433 2934.2 731.961ZM2982.56 727.157 2992.28 727.611 3010.06 728.671 3009.65 735.533 2991.9 734.476 2991.94 734.478 2982.24 734.024ZM3030.65 729.897 3035.76 730.202 3058.13 731.82 3057.63 738.677 3035.28 737.06 3035.33 737.063 3030.24 736.76ZM3078.7 733.307 3078.8 733.315 3106.14 735.64 3105.56 742.49 3078.24 740.167 3078.28 740.17 3078.2 740.164ZM3126.73 737.46 3154.1 740.137 3153.43 746.98 3126.06 744.302ZM3174.65 742.296 3201.99 745.322 3201.23 752.155 3173.9 749.129ZM3222.5 747.831 3244.91 750.607 3249.83 751.283 3248.9 758.094 3243.99 757.421 3244.04 757.427 3221.66 754.654ZM3270.26 754.089 3284.49 756.043 3297.53 758.016 3296.5 764.813 3283.48 762.844 3283.53 762.851 3269.33 760.9ZM3317.92 761.1 3323.12 761.886 3345.11 765.531 3343.99 772.314 3322.02 768.673 3322.07 768.68 3316.89 767.898ZM3365.5 768.983 3392.56 773.88 3391.33 780.645 3364.27 775.748ZM3412.86 777.806 3432.45 781.666 3439.87 783.257 3438.43 789.979 3431.04 788.394 3431.09 788.406 3411.53 784.551ZM3460.04 787.579 3466.42 788.945 3486.91 793.718 3485.35 800.414 3464.89 795.648 3464.95 795.661 3458.6 794.301ZM3507.01 798.523 3514.75 800.443 3530.13 804.42 3533.71 805.389 3531.92 812.026 3528.35 811.062 3528.39 811.071 3513.05 807.103 3513.08 807.111 3505.36 805.196ZM3553.64 810.869 3559.7 812.577 3573.87 816.753 3580.09 818.669 3578.07 825.239 3571.87 823.33 3571.91 823.342 3557.77 819.178 3557.81 819.189 3551.77 817.487ZM3599.8 824.913 3600.96 825.287 3613.84 829.641 3625.89 833.912 3623.59 840.391 3611.57 836.129 3611.62 836.146 3598.78 831.808 3598.82 831.823 3597.69 831.457ZM3645.28 841.269 3649.75 843.025 3660.77 847.587 3670.76 851.959 3668 858.257 3658.04 853.898 3658.11 853.926 3647.15 849.389 3647.21 849.413 3642.77 847.669ZM3689.52 860.9 3690.83 861.548 3699.81 866.289 3708.27 871.071 3713.79 874.438 3710.21 880.308 3704.74 876.97 3704.83 877.027 3696.47 872.297 3696.56 872.346 3687.66 867.65 3687.74 867.692 3686.47 867.064ZM3731.16 886.32 3736.55 890.61 3742.19 895.601 3747.24 900.64 3751.56 905.593 3746.37 910.111 3742.13 905.247 3742.3 905.421 3737.41 900.539 3737.56 900.68 3732.06 895.818 3732.2 895.935 3726.88 891.701ZM3764.7 906.97 3761.07 937.5 3738.83 916.273Z" /><text + id="text116" + transform="matrix(0.998741 -0.050158 0.050158 0.998741 2571.92 793)" + font-size="64" + font-weight="400" + font-style="italic" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">edge == 0</text> +<text + id="text118" + transform="matrix(1 0 0 1 1933.46 420)" + text-decoration="underline" + font-size="64" + font-weight="700" + font-style="italic" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">Interface</text> +<text + id="text120" + transform="matrix(1 0 0 1 2199.86 420)" + text-decoration="underline" + font-size="64" + font-weight="700" + font-style="italic" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">-</text> +<text + id="text122" + transform="matrix(1 0 0 1 2221.06 420)" + text-decoration="underline" + font-size="64" + font-weight="700" + font-style="italic" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">0</text> +<text + id="text124" + transform="matrix(1 0 0 1 1842.64 497)" + font-size="64" + font-weight="400" + font-style="italic" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">Enabled Features</text> +<text + id="text126" + transform="matrix(1 0 0 1 2828.07 412)" + text-decoration="underline" + font-size="64" + font-weight="700" + font-style="italic" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">Interface</text> +<text + id="text128" + transform="matrix(1 0 0 1 3094.47 412)" + text-decoration="underline" + font-size="64" + font-weight="700" + font-style="italic" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">-</text> +<text + id="text130" + transform="matrix(1 0 0 1 3115.67 412)" + text-decoration="underline" + font-size="64" + font-weight="700" + font-style="italic" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">1</text> +<text + id="text132" + transform="matrix(1 0 0 1 2737.25 489)" + font-size="64" + font-weight="400" + font-style="italic" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">Enabled Features</text> +<path + id="path134" + transform="matrix(-1 0 0 1 1993.37 532.5)" + fill="#63666A" + d="M0.513174-0.254726 224.189 450.366 223.163 450.875-0.513174 0.254726ZM233.954 440.402 233.865 471.148 209.322 452.629Z" /><path + id="path136" + fill="#63666A" + d="M2095.86 523.058 2640.92 971.389 2640.19 972.274 2095.14 523.943ZM2645.75 958.301 2658.26 986.389 2628.28 979.539Z" /><path + id="path138" + transform="matrix(-1 0 0 1 2834.66 536.5)" + fill="#63666A" + d="M0.307156-0.48362 857.122 543.695 856.508 544.663-0.307156 0.48362ZM860.318 530.115 876.16 556.465 845.574 553.329Z" /><path + id="path140" + fill="#63666A" + d="M2990.87 529.062 3509.46 966.033 3508.73 966.91 2990.13 529.938ZM3514.45 953.003 3526.62 981.238 3496.73 974.033Z" /><path + id="path142" + fill="#63666A" + d="M2381.7 431.962 3739.81 929.039 3739.42 930.115 2381.3 433.038ZM3740.03 915.088 3761.13 937.452 3730.58 940.913Z" /><text + id="text144" + transform="matrix(0.838284 -0.545233 0.545233 0.838284 1136.13 1461)" + font-size="64" + font-weight="400" + font-style="italic" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">edge == 2 </text> +<text + id="text146" + transform="matrix(0.98675 -0.162247 0.162247 0.98675 2069.25 1383)" + font-size="64" + font-weight="400" + font-style="italic" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">edge == 0 </text> +<text + id="text148" + transform="matrix(0.994324 -0.106397 0.106397 0.994324 2994.86 1316)" + font-size="64" + font-weight="400" + font-style="italic" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">edge == 0 </text> +</g></svg> diff --git a/doc/guides/prog_guide/img/feature_arc-3.svg b/doc/guides/prog_guide/img/feature_arc-3.svg new file mode 100644 index 0000000000..382f259e42 --- /dev/null +++ b/doc/guides/prog_guide/img/feature_arc-3.svg @@ -0,0 +1,318 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<!-- SPDX-License-Identifier: BSD-3-Clause --> +<!-- Copyright(C) 2024 Marvell International Ltd. --> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + id="svg100" + version="1.1" + overflow="hidden" + xml:space="preserve" + height="2075" + width="3423"><metadata + id="metadata106"><rdf:RDF><cc:Work + rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs + id="defs104" /><g + id="g98" + transform="translate(-590 -205)"><path + id="path2" + fill-rule="evenodd" + fill="#00B5E2" + stroke-miterlimit="8" + stroke-width="6.875" + stroke="#212322" + d="M593.5 358.5C593.5 275.657 735.426 208.5 910.5 208.5 1085.57 208.5 1227.5 275.657 1227.5 358.5 1227.5 441.343 1085.57 508.5 910.5 508.5 735.426 508.5 593.5 441.343 593.5 358.5Z" /><text + id="text4" + transform="matrix(1 0 0 1 770.408 388)" + font-size="83" + font-weight="400" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">Node</text> +<text + id="text6" + transform="matrix(1 0 0 1 967.492 388)" + font-size="83" + font-weight="400" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">-</text> +<text + id="text8" + transform="matrix(1 0 0 1 994.992 388)" + font-size="83" + font-weight="400" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">A</text> +<path + id="path10" + fill-rule="evenodd" + fill="#00B5E2" + stroke-miterlimit="8" + stroke-width="6.875" + stroke="#212322" + d="M596.5 1475.5C596.5 1392.66 738.65 1325.5 914 1325.5 1089.35 1325.5 1231.5 1392.66 1231.5 1475.5 1231.5 1558.34 1089.35 1625.5 914 1625.5 738.65 1625.5 596.5 1558.34 596.5 1475.5Z" /><text + id="text12" + transform="matrix(1 0 0 1 773.708 1505)" + font-size="83" + font-weight="400" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">Node</text> +<text + id="text14" + transform="matrix(1 0 0 1 970.792 1505)" + font-size="83" + font-weight="400" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">-</text> +<text + id="text16" + transform="matrix(1 0 0 1 998.292 1505)" + font-size="83" + font-weight="400" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">B</text> +<path + id="path18" + fill-rule="evenodd" + fill="#00B050" + stroke-miterlimit="8" + stroke-width="6.875" + stroke="#212322" + d="M1297.5 947C1297.5 863.881 1435.62 796.5 1606 796.5 1776.38 796.5 1914.5 863.881 1914.5 947 1914.5 1030.12 1776.38 1097.5 1606 1097.5 1435.62 1097.5 1297.5 1030.12 1297.5 947Z" /><text + id="text20" + transform="matrix(1 0 0 1 1425.81 974)" + font-size="73" + font-weight="400" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">Feature </text> +<text + id="text22" + transform="matrix(1 0 0 1 1699.09 974)" + font-size="73" + font-weight="400" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">-</text> +<text + id="text24" + transform="matrix(1 0 0 1 1744.35 974)" + font-size="73" + font-weight="400" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">1</text> +<path + id="path26" + fill="#63666A" + d="M913.938 508.486 917.145 1302.23 910.27 1302.25 907.063 508.514ZM927.439 1297.6 913.8 1325.16 899.939 1297.71Z" /><path + id="path28" + fill="#003967" + d="M911.378 506.383 928.313 513.406 926.557 517.639 909.622 510.617ZM941.014 518.672 957.949 525.695 956.194 529.929 939.259 522.906ZM970.651 530.962 987.586 537.984 985.83 542.218 968.895 535.195ZM1000.29 543.251 1017.22 550.274 1015.47 554.507 998.531 547.485ZM1029.92 555.54 1046.86 562.563 1045.1 566.797 1028.17 559.774ZM1059.56 567.83 1076.49 574.852 1074.74 579.086 1057.8 572.064ZM1089.2 580.119 1106.13 587.142 1104.38 591.375 1087.44 584.353ZM1118.83 592.409 1135.77 599.431 1134.01 603.665 1117.08 596.642ZM1148.47 604.698 1165.4 611.72 1163.65 615.954 1146.71 608.932ZM1178.1 616.987 1195.04 624.01 1193.28 628.244 1176.35 621.221ZM1207.74 629.277 1224.68 636.299 1222.92 640.533 1205.99 633.51ZM1237.38 641.566 1254.31 648.589 1252.56 652.822 1235.62 645.8ZM1267.01 653.855 1283.95 660.878 1282.19 665.112 1265.26 658.089ZM1296.65 666.145 1313.59 673.167 1311.83 677.401 1294.89 670.379ZM1326.29 678.434 1343.22 685.457 1341.47 689.69 1324.53 682.668ZM1355.92 690.724 1372.86 697.746 1371.1 701.98 1354.17 694.957ZM1385.56 703.013 1402.49 710.035 1400.74 714.269 1383.8 707.247ZM1415.2 715.302 1432.13 722.325 1430.38 726.558 1413.44 719.536ZM1444.83 727.592 1461.77 734.614 1460.01 738.848 1443.08 731.825ZM1474.47 739.881 1491.4 746.903 1489.65 751.137 1472.71 744.115ZM1504.1 752.17 1521.04 759.193 1519.28 763.427 1502.35 756.404ZM1533.74 764.46 1550.68 771.482 1548.92 775.716 1531.99 768.693ZM1563.38 776.749 1580.31 783.772 1578.56 788.005 1561.62 780.983ZM1585.58 773.552 1605.72 796.786 1575.05 798.954Z" /><path + id="path30" + transform="matrix(-1 0 0 1 1606.42 1097.5)" + fill="#003967" + d="M0.71731-2.17651 18.1294 3.56197 16.6948 7.91499-0.71731 2.17651ZM31.1885 7.86584 48.6006 13.6043 47.1659 17.9573 29.7538 12.2189ZM61.6596 17.9082 79.0717 23.6467 77.6371 27.9997 60.225 22.2612ZM92.1308 27.9505 109.543 33.689 108.108 38.042 90.6962 32.3035ZM122.602 37.9929 140.014 43.7314 138.579 48.0844 121.167 42.3459ZM153.073 48.0352 170.485 53.7737 169.051 58.1267 151.638 52.3882ZM183.544 58.0776 200.956 63.816 199.522 68.1691 182.11 62.4306ZM214.015 68.1199 231.428 73.8584 229.993 78.2114 212.581 72.4729ZM244.487 78.1622 261.899 83.9007 260.464 88.2538 243.052 82.5153ZM274.958 88.2046 292.37 93.9431 290.935 98.2961 273.523 92.5576ZM305.429 98.247 322.841 103.985 321.406 108.338 303.994 102.6ZM335.9 108.289 353.312 114.028 351.878 118.381 334.465 112.642ZM366.371 118.332 383.783 124.07 382.349 128.423 364.937 122.685ZM396.842 128.374 414.255 134.112 412.82 138.465 395.408 132.727ZM427.314 138.416 444.726 144.155 443.291 148.508 425.879 142.769ZM457.785 148.459 475.197 154.197 473.762 158.55 456.35 152.812ZM488.256 158.501 505.668 164.24 504.233 168.593 486.821 162.854ZM518.727 168.543 536.139 174.282 534.705 178.635 517.292 172.896ZM549.198 178.586 566.61 184.324 565.176 188.677 547.764 182.939ZM579.669 188.628 597.081 194.367 595.647 198.72 578.235 192.981ZM610.141 198.67 627.553 204.409 626.118 208.762 608.706 203.023ZM640.612 208.713 658.024 214.451 656.589 218.804 639.177 213.066ZM670.101 206.367 691.916 228.034 661.494 232.485Z" /><path + id="path32" + fill-rule="evenodd" + fill="#00B050" + stroke-miterlimit="8" + stroke-width="6.875" + stroke="#212322" + d="M3375.5 902.5C3375.5 819.657 3517.43 752.5 3692.5 752.5 3867.57 752.5 4009.5 819.657 4009.5 902.5 4009.5 985.343 3867.57 1052.5 3692.5 1052.5 3517.43 1052.5 3375.5 985.343 3375.5 902.5Z" /><text + id="text34" + transform="matrix(1 0 0 1 3513.57 933)" + font-size="83" + font-weight="400" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">Feature</text> +<text + id="text36" + transform="matrix(1 0 0 1 3797.73 933)" + font-size="83" + font-weight="400" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">-</text> +<text + id="text38" + transform="matrix(1 0 0 1 3825.23 933)" + font-size="83" + font-weight="400" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">3</text> +<path + id="path40" + fill="#003967" + d="M910.7 506.217 928.964 507.817 928.563 512.383 910.3 510.783ZM942.661 509.018 960.924 510.618 960.524 515.184 942.261 513.583ZM974.622 511.818 992.885 513.419 992.485 517.985 974.222 516.384ZM1006.58 514.619 1024.85 516.219 1024.45 520.785 1006.18 519.185ZM1038.54 517.42 1056.81 519.02 1056.41 523.586 1038.14 521.986ZM1070.5 520.22 1088.77 521.821 1088.37 526.387 1070.1 524.786ZM1102.47 523.021 1120.73 524.621 1120.33 529.187 1102.07 527.587ZM1134.43 525.822 1152.69 527.422 1152.29 531.988 1134.03 530.388ZM1166.39 528.622 1184.65 530.223 1184.25 534.789 1165.99 533.188ZM1198.35 531.423 1216.61 533.023 1216.21 537.589 1197.95 535.989ZM1230.31 534.224 1248.57 535.824 1248.17 540.39 1229.91 538.79ZM1262.27 537.024 1280.53 538.625 1280.13 543.191 1261.87 541.59ZM1294.23 539.825 1312.49 541.425 1312.09 545.991 1293.83 544.391ZM1326.19 542.626 1344.45 544.226 1344.05 548.792 1325.79 547.192ZM1358.15 545.426 1376.42 547.027 1376.02 551.593 1357.75 549.992ZM1390.11 548.227 1408.38 549.827 1407.98 554.393 1389.71 552.793ZM1422.07 551.028 1440.34 552.628 1439.94 557.194 1421.67 555.594ZM1454.03 553.828 1472.3 555.429 1471.9 559.995 1453.63 558.394ZM1486 556.629 1504.26 558.229 1503.86 562.795 1485.6 561.195ZM1517.96 559.43 1536.22 561.03 1535.82 565.596 1517.56 563.996ZM1549.92 562.23 1568.18 563.831 1567.78 568.397 1549.52 566.796ZM1581.88 565.031 1600.14 566.631 1599.74 571.197 1581.48 569.597ZM1613.84 567.832 1632.1 569.432 1631.7 573.998 1613.44 572.398ZM1645.8 570.632 1664.06 572.233 1663.66 576.799 1645.4 575.198ZM1677.76 573.433 1696.02 575.034 1695.62 579.599 1677.36 577.999ZM1709.72 576.234 1727.98 577.834 1727.58 582.4 1709.32 580.8ZM1741.68 579.034 1759.95 580.635 1759.55 585.201 1741.28 583.6ZM1773.64 581.835 1791.91 583.435 1791.51 588.001 1773.24 586.401ZM1805.6 584.636 1823.87 586.236 1823.47 590.802 1805.2 589.202ZM1837.56 587.436 1855.83 589.037 1855.43 593.603 1837.16 592.002ZM1869.53 590.237 1887.79 591.838 1887.39 596.403 1869.13 594.803ZM1901.49 593.038 1919.75 594.638 1919.35 599.204 1901.09 597.604ZM1933.45 595.839 1951.71 597.439 1951.31 602.005 1933.05 600.404ZM1965.41 598.639 1983.67 600.24 1983.27 604.805 1965.01 603.205ZM1997.37 601.44 2015.63 603.04 2015.23 607.606 1996.97 606.006ZM2029.33 604.24 2047.59 605.841 2047.19 610.407 2028.93 608.806ZM2061.29 607.041 2079.55 608.642 2079.15 613.207 2060.89 611.607ZM2093.25 609.842 2111.51 611.442 2111.11 616.008 2092.85 614.408ZM2125.21 612.643 2143.48 614.243 2143.08 618.809 2124.81 617.208ZM2157.17 615.443 2175.44 617.044 2175.04 621.609 2156.77 620.009ZM2189.13 618.244 2207.4 619.844 2207 624.41 2188.73 622.81ZM2221.09 621.045 2239.36 622.645 2238.96 627.211 2220.69 625.61ZM2253.06 623.845 2271.32 625.446 2270.92 630.011 2252.66 628.411ZM2285.02 626.646 2303.28 628.246 2302.88 632.812 2284.62 631.212ZM2316.98 629.447 2335.24 631.047 2334.84 635.613 2316.58 634.012ZM2348.94 632.247 2367.2 633.848 2366.8 638.413 2348.54 636.813ZM2380.9 635.048 2399.16 636.648 2398.76 641.214 2380.5 639.614ZM2412.86 637.849 2431.12 639.449 2430.72 644.015 2412.46 642.414ZM2444.82 640.649 2463.08 642.25 2462.68 646.815 2444.42 645.215ZM2476.78 643.45 2495.04 645.05 2494.64 649.616 2476.38 648.016ZM2508.74 646.251 2527.01 647.851 2526.6 652.417 2508.34 650.816ZM2540.7 649.051 2558.97 650.652 2558.57 655.217 2540.3 653.617ZM2572.66 651.852 2590.93 653.452 2590.53 658.018 2572.26 656.418ZM2604.62 654.653 2622.89 656.253 2622.49 660.819 2604.22 659.218ZM2636.58 657.453 2654.85 659.054 2654.45 663.62 2636.18 662.019ZM2668.55 660.254 2686.81 661.854 2686.41 666.42 2668.15 664.82ZM2700.51 663.055 2718.77 664.655 2718.37 669.221 2700.11 667.62ZM2732.47 665.855 2750.73 667.456 2750.33 672.021 2732.07 670.421ZM2764.43 668.656 2782.69 670.256 2782.29 674.822 2764.03 673.222ZM2796.39 671.457 2814.65 673.057 2814.25 677.623 2795.99 676.022ZM2828.35 674.257 2846.61 675.858 2846.21 680.424 2827.95 678.823ZM2860.31 677.058 2878.57 678.658 2878.17 683.224 2859.91 681.624ZM2892.27 679.859 2910.53 681.459 2910.13 686.025 2891.87 684.424ZM2924.23 682.659 2942.5 684.26 2942.1 688.826 2923.83 687.225ZM2956.19 685.46 2974.46 687.06 2974.06 691.626 2955.79 690.026ZM2988.15 688.261 3006.42 689.861 3006.02 694.427 2987.75 692.826ZM3020.11 691.061 3038.38 692.662 3037.98 697.228 3019.71 695.627ZM3052.08 693.862 3070.34 695.462 3069.94 700.028 3051.68 698.428ZM3084.04 696.663 3102.3 698.263 3101.9 702.829 3083.64 701.229ZM3116 699.463 3134.26 701.064 3133.86 705.63 3115.6 704.029ZM3147.96 702.264 3166.22 703.864 3165.82 708.43 3147.56 706.83ZM3179.92 705.065 3198.18 706.665 3197.78 711.231 3179.52 709.63ZM3211.88 707.865 3230.14 709.466 3229.74 714.031 3211.48 712.431ZM3243.84 710.666 3262.1 712.266 3261.7 716.832 3243.44 715.232ZM3275.8 713.467 3294.07 715.067 3293.67 719.633 3275.4 718.032ZM3307.76 716.267 3326.03 717.868 3325.63 722.433 3307.36 720.833ZM3339.72 719.068 3357.99 720.668 3357.59 725.234 3339.32 723.634ZM3371.69 721.869 3389.95 723.469 3389.55 728.035 3371.29 726.434ZM3403.65 724.669 3421.91 726.27 3421.51 730.836 3403.25 729.235ZM3435.61 727.47 3453.87 729.07 3453.47 733.636 3435.21 732.036ZM3467.57 730.271 3485.83 731.871 3485.43 736.437 3467.17 734.837ZM3499.53 733.071 3517.79 734.672 3517.39 739.238 3499.13 737.637ZM3531.49 735.872 3549.75 737.472 3549.35 742.038 3531.09 740.438ZM3563.45 738.673 3581.71 740.273 3581.31 744.839 3563.05 743.239ZM3595.41 741.473 3613.68 743.074 3613.28 747.64 3595.01 746.039ZM3627.37 744.274 3645.64 745.875 3645.24 750.44 3626.97 748.84ZM3659.33 747.075 3669.97 748.007 3669.57 752.573 3658.93 751.641ZM3666.42 736.194 3692.62 752.292 3664.02 763.589Z" /><path + id="path42" + fill-rule="evenodd" + fill="#92D050" + stroke-miterlimit="8" + stroke-width="6.875" + stroke="#212322" + d="M2273.5 951.5C2273.5 868.657 2409.16 801.5 2576.5 801.5 2743.84 801.5 2879.5 868.657 2879.5 951.5 2879.5 1034.34 2743.84 1101.5 2576.5 1101.5 2409.16 1101.5 2273.5 1034.34 2273.5 951.5Z" /><text + id="text44" + transform="matrix(1 0 0 1 2396.44 978)" + font-size="73" + font-weight="400" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">Feature </text> +<text + id="text46" + transform="matrix(1 0 0 1 2669.72 978)" + font-size="73" + font-weight="400" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">-</text> +<text + id="text48" + transform="matrix(1 0 0 1 2714.98 978)" + font-size="73" + font-weight="400" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">2</text> +<path + id="path50" + fill="#003967" + d="M910.896 506.243 928.954 509.413 928.161 513.927 910.104 510.757ZM942.496 511.79 960.554 514.961 959.761 519.475 941.704 516.305ZM974.096 517.338 992.154 520.508 991.361 525.023 973.304 521.853ZM1005.7 522.886 1023.75 526.056 1022.96 530.57 1004.9 527.4ZM1037.3 528.434 1055.35 531.604 1054.56 536.118 1036.5 532.948ZM1068.9 533.981 1086.95 537.152 1086.16 541.666 1068.1 538.496ZM1100.5 539.529 1118.55 542.699 1117.76 547.214 1099.7 544.043ZM1132.1 545.077 1150.15 548.247 1149.36 552.761 1131.3 549.591ZM1163.7 550.625 1181.75 553.795 1180.96 558.309 1162.9 555.139ZM1195.3 556.172 1213.35 559.343 1212.56 563.857 1194.5 560.687ZM1226.9 561.72 1244.95 564.89 1244.16 569.405 1226.1 566.234ZM1258.5 567.268 1276.55 570.438 1275.76 574.952 1257.7 571.782ZM1290.1 572.816 1308.15 575.986 1307.36 580.5 1289.3 577.33ZM1321.7 578.363 1339.75 581.534 1338.96 586.048 1320.9 582.878ZM1353.3 583.911 1371.35 587.081 1370.56 591.596 1352.5 588.425ZM1384.9 589.459 1402.95 592.629 1402.16 597.143 1384.1 593.973ZM1416.5 595.007 1434.55 598.177 1433.76 602.691 1415.7 599.521ZM1448.1 600.554 1466.15 603.724 1465.36 608.239 1447.3 605.069ZM1479.7 606.102 1497.75 609.272 1496.96 613.786 1478.9 610.616ZM1511.3 611.65 1529.35 614.82 1528.56 619.334 1510.5 616.164ZM1542.9 617.198 1560.95 620.368 1560.16 624.882 1542.1 621.712ZM1574.5 622.745 1592.55 625.915 1591.76 630.43 1573.7 627.26ZM1606.1 628.293 1624.15 631.463 1623.36 635.977 1605.3 632.807ZM1637.7 633.841 1655.75 637.011 1654.96 641.525 1636.91 638.355ZM1669.3 639.388 1687.35 642.559 1686.56 647.073 1668.5 643.903ZM1700.9 644.936 1718.95 648.106 1718.16 652.621 1700.1 649.451ZM1732.5 650.484 1750.55 653.654 1749.76 658.168 1731.7 654.998ZM1764.1 656.032 1782.15 659.202 1781.36 663.716 1763.3 660.546ZM1795.7 661.579 1813.75 664.75 1812.96 669.264 1794.91 666.094ZM1827.3 667.127 1845.35 670.297 1844.56 674.812 1826.51 671.641ZM1858.9 672.675 1876.95 675.845 1876.16 680.359 1858.1 677.189ZM1890.5 678.223 1908.55 681.393 1907.76 685.907 1889.71 682.737ZM1922.1 683.77 1940.15 686.941 1939.36 691.455 1921.3 688.285ZM1953.7 689.318 1971.75 692.488 1970.96 697.003 1952.91 693.832ZM1985.3 694.866 2003.35 698.036 2002.56 702.55 1984.51 699.38ZM2016.9 700.414 2034.95 703.584 2034.16 708.098 2016.11 704.928ZM2048.5 705.961 2066.55 709.131 2065.76 713.646 2047.71 710.476ZM2080.1 711.509 2098.15 714.679 2097.36 719.194 2079.31 716.023ZM2111.7 717.057 2129.75 720.227 2128.96 724.741 2110.91 721.571ZM2143.3 722.605 2161.35 725.775 2160.56 730.289 2142.51 727.119ZM2174.9 728.152 2192.96 731.322 2192.16 735.837 2174.11 732.667ZM2206.5 733.7 2224.56 736.87 2223.76 741.384 2205.71 738.214ZM2238.1 739.248 2256.16 742.418 2255.36 746.932 2237.31 743.762ZM2269.7 744.795 2287.76 747.966 2286.96 752.48 2268.91 749.31ZM2301.3 750.343 2319.36 753.513 2318.56 758.028 2300.51 754.858ZM2332.9 755.891 2350.96 759.061 2350.16 763.575 2332.11 760.405ZM2364.5 761.439 2382.56 764.609 2381.76 769.123 2363.71 765.953ZM2396.1 766.986 2414.16 770.157 2413.36 774.671 2395.31 771.501ZM2427.7 772.534 2445.76 775.704 2444.96 780.219 2426.91 777.048ZM2459.3 778.082 2477.36 781.252 2476.56 785.766 2458.51 782.596ZM2490.9 783.63 2508.96 786.8 2508.16 791.314 2490.11 788.144ZM2522.5 789.177 2540.56 792.348 2539.76 796.862 2521.71 793.692ZM2554.1 794.725 2554.18 794.739 2553.39 799.254 2553.31 799.24ZM2551.64 782.66 2576.35 800.958 2546.89 809.746Z" /><path + id="path52" + transform="matrix(-1 0 0 1 2577.05 1101.5)" + fill="#003967" + d="M0.305813-2.27117 18.4752 0.175336 17.8635 4.71768-0.305813 2.27117ZM32.1022 2.01022 50.2716 4.45672 49.6599 8.99906 31.4906 6.55256ZM63.8986 6.2916 82.0679 8.73811 81.4563 13.2804 63.287 10.8339ZM95.695 10.573 113.864 13.0195 113.253 17.5618 95.0833 15.1153ZM127.491 14.8544 145.661 17.3009 145.049 21.8432 126.88 19.3967ZM159.288 19.1358 177.457 21.5823 176.845 26.1246 158.676 23.6781ZM191.084 23.4171 209.253 25.8636 208.642 30.406 190.472 27.9595ZM222.88 27.6985 241.05 30.145 240.438 34.6874 222.269 32.2409ZM254.677 31.9799 272.846 34.4264 272.235 38.9688 254.065 36.5223ZM286.473 36.2613 304.643 38.7078 304.031 43.2501 285.862 40.8036ZM318.27 40.5427 336.439 42.9892 335.827 47.5315 317.658 45.085ZM350.066 44.8241 368.235 47.2706 367.624 51.8129 349.454 49.3664ZM381.862 49.1054 400.032 51.552 399.42 56.0943 381.251 53.6478ZM413.659 53.3868 431.828 55.8333 431.216 60.3757 413.047 57.9292ZM445.455 57.6682 463.624 60.1147 463.013 64.6571 444.843 62.2106ZM477.251 61.9496 495.421 64.3961 494.809 68.9384 476.64 66.4919ZM509.048 66.231 527.217 68.6775 526.606 73.2198 508.436 70.7733ZM540.844 70.5124 559.014 72.9589 558.402 77.5012 540.233 75.0547ZM572.641 74.7938 590.81 77.2403 590.198 81.7826 572.029 79.3361ZM604.437 79.0751 622.606 81.5217 621.995 86.064 603.825 83.6175ZM636.233 83.3565 654.403 85.803 653.791 90.3454 635.622 87.8989ZM668.03 87.6379 686.199 90.0844 685.587 94.6268 667.418 92.1803ZM699.826 91.9193 717.995 94.3658 717.384 98.9081 699.215 96.4616ZM731.622 96.2007 749.792 98.6472 749.18 103.19 731.011 100.743ZM763.419 100.482 781.588 102.929 780.977 107.471 762.807 105.024ZM795.215 104.763 813.385 107.21 812.773 111.752 794.604 109.306ZM827.012 109.045 845.181 111.491 844.569 116.034 826.4 113.587ZM858.808 113.326 876.978 115.773 876.366 120.315 858.197 117.869ZM890.605 117.608 908.774 120.054 908.162 124.596 889.993 122.15ZM922.401 121.889 940.57 124.335 939.959 128.878 921.789 126.431ZM954.198 126.17 972.367 128.617 971.755 133.159 953.586 130.713ZM985.994 130.452 1004.16 132.898 1003.55 137.441 985.382 134.994ZM1017.79 134.733 1035.96 137.18 1035.35 141.722 1017.18 139.275ZM1049.59 139.015 1067.76 141.461 1067.14 146.003 1048.98 143.557ZM1081.38 143.296 1099.55 145.742 1098.94 150.285 1080.77 147.838ZM1113.18 147.577 1131.35 150.024 1130.74 154.566 1112.57 152.12ZM1144.98 151.859 1163.15 154.305 1162.53 158.848 1144.36 156.401ZM1176.77 156.14 1194.94 158.587 1194.33 163.129 1176.16 160.682ZM1208.57 160.421 1226.74 162.868 1226.13 167.41 1207.96 164.964ZM1240.36 164.703 1258.53 167.149 1257.92 171.692 1239.75 169.245ZM1272.16 168.984 1290.33 171.431 1289.72 175.973 1271.55 173.527ZM1303.96 173.266 1322.13 175.712 1321.52 180.254 1303.35 177.808ZM1335.75 177.547 1353.92 179.993 1353.31 184.536 1335.14 182.089ZM1367.55 181.828 1385.72 184.275 1385.11 188.817 1366.94 186.371ZM1399.35 186.11 1417.52 188.556 1416.9 193.099 1398.74 190.652ZM1431.14 190.391 1449.31 192.838 1448.7 197.38 1430.53 194.934ZM1462.94 194.673 1481.11 197.119 1480.5 201.661 1462.33 199.215ZM1494.74 198.954 1512.91 201.4 1512.29 205.943 1494.12 203.496ZM1526.53 203.235 1544.7 205.682 1544.09 210.224 1525.92 207.778ZM1558.33 207.517 1576.5 209.963 1575.89 214.506 1557.72 212.059ZM1590.12 211.798 1608.29 214.245 1607.68 218.787 1589.51 216.34ZM1621.92 216.079 1640.09 218.526 1639.48 223.068 1621.31 220.622ZM1637.13 206.566 1662.55 223.862 1633.46 233.82Z" /><path + id="path54" + transform="matrix(-1 0 0 1 3693.32 1052.5)" + fill="#003967" + d="M0.223679-2.28072 18.4695-0.491293 18.0221 4.07016-0.223679 2.28072ZM32.1538 0.850781 50.3996 2.64021 49.9523 7.20166 31.7065 5.41223ZM64.084 3.98229 82.3298 5.77172 81.8824 10.3332 63.6366 8.54373ZM96.0141 7.11379 114.26 8.90322 113.813 13.4647 95.5667 11.6752ZM127.944 10.2453 146.19 12.0347 145.743 16.5962 127.497 14.8067ZM159.874 13.3768 178.12 15.1662 177.673 19.7277 159.427 17.9382ZM191.805 16.5083 210.05 18.2977 209.603 22.8592 191.357 21.0698ZM223.735 19.6398 241.98 21.4292 241.533 25.9907 223.287 24.2013ZM255.665 22.7713 273.911 24.5607 273.463 29.1222 255.217 27.3328ZM287.595 25.9028 305.841 27.6923 305.393 32.2537 287.148 30.4643ZM319.525 29.0343 337.771 30.8238 337.323 35.3852 319.078 33.5958ZM351.455 32.1658 369.701 33.9553 369.254 38.5167 351.008 36.7273ZM383.385 35.2973 401.631 37.0868 401.184 41.6482 382.938 39.8588ZM415.315 38.4288 433.561 40.2183 433.114 44.7797 414.868 42.9903ZM447.246 41.5603 465.491 43.3498 465.044 47.9112 446.798 46.1218ZM479.176 44.6919 497.422 46.4813 496.974 51.0427 478.728 49.2533ZM511.106 47.8234 529.352 49.6128 528.904 54.1742 510.659 52.3848ZM543.036 50.9549 561.282 52.7443 560.835 57.3058 542.589 55.5163ZM574.966 54.0864 593.212 55.8758 592.765 60.4373 574.519 58.6478ZM606.896 57.2179 625.142 59.0073 624.695 63.5688 606.449 61.7793ZM638.827 60.3494 657.072 62.1388 656.625 66.7003 638.379 64.9108ZM670.757 63.4809 689.003 65.2703 688.555 69.8318 670.309 68.0423ZM702.687 66.6124 720.933 68.4018 720.485 72.9633 702.24 71.1739ZM734.617 69.7439 752.863 71.5333 752.416 76.0948 734.17 74.3054ZM766.547 72.8754 784.793 74.6648 784.346 79.2263 766.1 77.4369ZM798.477 76.0069 816.723 77.7963 816.276 82.3578 798.03 80.5684ZM830.407 79.1384 848.653 80.9278 848.206 85.4893 829.96 83.6999ZM862.338 82.2699 880.583 84.0594 880.136 88.6208 861.89 86.8314ZM894.268 85.4014 912.513 87.1909 912.066 91.7523 893.82 89.9629ZM926.198 88.5329 944.444 90.3224 943.996 94.8838 925.75 93.0944ZM958.128 91.6644 976.374 93.4539 975.926 98.0153 957.681 96.2259ZM990.058 94.7959 1008.3 96.5854 1007.86 101.147 989.611 99.3574ZM1021.99 97.9274 1040.23 99.7169 1039.79 104.278 1021.54 102.489ZM1053.92 101.059 1072.16 102.848 1071.72 107.41 1053.47 105.62ZM1085.85 104.19 1104.09 105.98 1103.65 110.541 1085.4 108.752ZM1117.78 107.322 1136.02 109.111 1135.58 113.673 1117.33 111.883ZM1149.71 110.453 1167.95 112.243 1167.51 116.804 1149.26 115.015ZM1181.64 113.585 1199.88 115.374 1199.44 119.936 1181.19 118.146ZM1213.57 116.716 1231.81 118.506 1231.37 123.067 1213.12 121.278ZM1245.5 119.848 1263.74 121.637 1263.3 126.199 1245.05 124.409ZM1277.43 122.979 1295.68 124.769 1295.23 129.33 1276.98 127.541ZM1309.36 126.111 1327.61 127.9 1327.16 132.462 1308.91 130.672ZM1341.29 129.242 1359.54 131.032 1359.09 135.593 1340.84 133.804ZM1373.22 132.374 1391.47 134.163 1391.02 138.725 1372.77 136.935ZM1405.15 135.505 1423.4 137.295 1422.95 141.856 1404.7 140.067ZM1437.08 138.637 1455.33 140.426 1454.88 144.988 1436.63 143.198ZM1469.01 141.768 1487.26 143.558 1486.81 148.119 1468.56 146.33ZM1500.94 144.9 1519.19 146.689 1518.74 151.251 1500.49 149.461ZM1532.87 148.031 1551.12 149.821 1550.67 154.382 1532.42 152.593ZM1564.8 151.163 1583.05 152.952 1582.6 157.514 1564.35 155.724ZM1596.73 154.294 1614.98 156.084 1614.53 160.645 1596.28 158.856ZM1628.66 157.426 1646.91 159.215 1646.46 163.777 1628.21 161.987ZM1660.59 160.557 1678.84 162.347 1678.39 166.908 1660.14 165.119ZM1692.52 163.689 1710.77 165.478 1710.32 170.04 1692.07 168.25ZM1724.45 166.82 1742.7 168.61 1742.25 173.171 1724 171.382ZM1756.38 169.952 1774.63 171.741 1774.18 176.303 1755.93 174.513ZM1788.31 173.084 1806.56 174.873 1806.11 179.434 1787.86 177.645ZM1820.24 176.215 1838.49 178.004 1838.04 182.566 1819.79 180.776ZM1852.17 179.347 1870.42 181.136 1869.97 185.697 1851.72 183.908ZM1884.1 182.478 1902.35 184.267 1901.9 188.829 1883.65 187.039ZM1916.03 185.61 1934.28 187.399 1933.83 191.96 1915.58 190.171ZM1947.96 188.741 1966.21 190.53 1965.76 195.092 1947.51 193.302ZM1979.89 191.873 1998.14 193.662 1997.69 198.223 1979.44 196.434ZM2011.82 195.004 2030.07 196.793 2029.62 201.355 2011.37 199.566ZM2043.75 198.136 2062 199.925 2061.55 204.486 2043.31 202.697ZM2075.68 201.267 2093.93 203.057 2093.48 207.618 2075.24 205.829ZM2107.61 204.399 2125.86 206.188 2125.41 210.749 2107.17 208.96ZM2139.54 207.53 2157.79 209.32 2157.34 213.881 2139.1 212.092ZM2171.47 210.662 2189.72 212.451 2189.27 217.012 2171.03 215.223ZM2203.4 213.793 2221.65 215.583 2221.2 220.144 2202.96 218.355ZM2235.33 216.925 2253.58 218.714 2253.13 223.275 2234.89 221.486ZM2267.26 220.056 2285.51 221.846 2285.06 226.407 2266.82 224.618ZM2299.19 223.188 2317.44 224.977 2316.99 229.539 2298.75 227.749ZM2331.12 226.319 2349.37 228.109 2348.92 232.67 2330.68 230.881ZM2363.05 229.451 2381.3 231.24 2380.85 235.802 2362.61 234.012ZM2394.98 232.582 2413.23 234.372 2412.78 238.933 2394.54 237.144ZM2426.91 235.714 2445.16 237.503 2444.71 242.065 2426.47 240.275ZM2458.84 238.845 2477.09 240.635 2476.64 245.196 2458.4 243.407ZM2490.77 241.977 2509.02 243.766 2508.57 248.328 2490.33 246.538ZM2522.7 245.108 2540.95 246.898 2540.5 251.459 2522.26 249.67ZM2554.63 248.24 2572.88 250.029 2572.43 254.591 2554.19 252.801ZM2586.56 251.371 2604.81 253.161 2604.36 257.722 2586.12 255.933ZM2618.49 254.503 2636.74 256.292 2636.29 260.854 2618.05 259.064ZM2650.43 257.634 2668.67 259.424 2668.22 263.985 2649.98 262.196ZM2682.36 260.766 2700.6 262.555 2700.15 267.117 2681.91 265.327ZM2714.29 263.897 2732.53 265.687 2732.08 270.248 2713.84 268.459ZM2746.22 267.029 2756.22 268.01 2755.77 272.571 2745.77 271.59ZM2752.79 256.16 2778.82 272.529 2750.11 283.529Z" /><path + id="path56" + fill="#63666A" + d="M1914.53 945.208 1932.86 945.421 1932.81 950.004 1914.47 949.791ZM1946.61 945.581 1964.94 945.794 1964.89 950.377 1946.55 950.164ZM1978.69 945.954 1997.02 946.167 1996.97 950.75 1978.64 950.537ZM2010.77 946.327 2029.1 946.54 2029.05 951.123 2010.72 950.91ZM2042.85 946.7 2061.18 946.913 2061.13 951.496 2042.8 951.283ZM2074.93 947.073 2093.26 947.286 2093.21 951.869 2074.88 951.656ZM2107.01 947.446 2125.35 947.659 2125.29 952.242 2106.96 952.029ZM2139.09 947.819 2157.43 948.032 2157.37 952.615 2139.04 952.402ZM2171.18 948.192 2189.51 948.405 2189.45 952.988 2171.12 952.775ZM2203.26 948.564 2221.59 948.778 2221.54 953.361 2203.2 953.147ZM2235.34 948.937 2250.5 949.114 2250.45 953.697 2235.28 953.52ZM2246.05 937.603 2273.39 951.671 2245.73 965.101Z" /><text + id="text58" + transform="matrix(1 0 0 1 2945.81 935)" + font-size="55" + font-weight="700" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">Not consumed</text> +<path + id="path60" + transform="matrix(1 0 0 -1 2879 950.275)" + fill="#63666A" + d="M0.117146-5.15492 41.3565-4.21775 41.1222 6.09209-0.117146 5.15492ZM72.286-3.51487 113.525-2.5777 113.291 7.73214 72.0517 6.79497ZM144.455-1.87482 185.694-0.937654 185.46 9.37218 144.221 8.43501ZM216.624-0.234776 257.863 0.702394 257.629 11.0122 216.389 10.0751ZM288.793 1.40527 330.032 2.34244 329.798 12.6523 288.558 11.7151ZM360.961 3.04532 402.201 3.98249 401.967 14.2923 360.727 13.3552ZM433.13 4.68537 470.489 5.53436 470.255 15.8442 432.896 14.9952ZM465.568-4.89263 496.147 11.275 464.866 26.0369Z" /><path + id="path62" + fill-rule="evenodd" + fill="none" + stroke-miterlimit="8" + stroke-width="4.58333" + stroke="#212322" + d="M2229.48 937.978 2673.33 630.043 3601.57 1967.99 3157.72 2275.92Z" /><path + id="path64" + fill-rule="evenodd" + fill="#92D050" + stroke-miterlimit="8" + stroke-width="6.875" + stroke="#212322" + d="M2653.5 1505.5C2653.5 1422.66 2789.38 1355.5 2957 1355.5 3124.62 1355.5 3260.5 1422.66 3260.5 1505.5 3260.5 1588.34 3124.62 1655.5 2957 1655.5 2789.38 1655.5 2653.5 1588.34 2653.5 1505.5Z" /><text + id="text66" + transform="matrix(1 0 0 1 2777.09 1532)" + font-size="73" + font-weight="400" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">Feature</text> +<text + id="text68" + transform="matrix(1 0 0 1 3029.75 1532)" + font-size="73" + font-weight="400" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">-</text> +<text + id="text70" + transform="matrix(1 0 0 1 3054.38 1532)" + font-size="73" + font-weight="400" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">2b</text> +<path + id="path72" + fill-rule="evenodd" + fill="#92D050" + stroke-miterlimit="8" + stroke-width="6.875" + stroke="#212322" + d="M2956.5 1942C2956.5 1858.88 3092.38 1791.5 3260 1791.5 3427.62 1791.5 3563.5 1858.88 3563.5 1942 3563.5 2025.12 3427.62 2092.5 3260 2092.5 3092.38 2092.5 2956.5 2025.12 2956.5 1942Z" /><text + id="text74" + transform="matrix(1 0 0 1 3082.34 1969)" + font-size="73" + font-weight="400" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">Feature</text> +<text + id="text76" + transform="matrix(1 0 0 1 3334.99 1969)" + font-size="73" + font-weight="400" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">-</text> +<text + id="text78" + transform="matrix(1 0 0 1 3359.63 1969)" + font-size="73" + font-weight="400" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">2c</text> +<path + id="path80" + fill="#003967" + d="M2794.5 1054.49 2814.58 1090.53 2805.57 1095.55 2785.5 1059.51ZM2829.63 1117.56 2849.7 1153.59 2840.69 1158.61 2820.62 1122.57ZM2864.76 1180.62 2884.83 1216.66 2875.82 1221.68 2855.75 1185.64ZM2899.88 1243.68 2919.96 1279.72 2910.95 1284.74 2890.88 1248.7ZM2935.01 1306.75 2947.9 1329.89 2938.89 1334.91 2926 1311.77ZM2954.4 1320.37 2955.94 1354.92 2927.37 1335.42Z" /><path + id="path82" + fill="#003967" + d="M3175.63 1608.72 3193.86 1645.72 3184.61 1650.28 3166.37 1613.28ZM3207.53 1673.47 3225.76 1710.48 3216.51 1715.03 3198.28 1678.03ZM3239.44 1738.23 3253.05 1765.85 3243.8 1770.41 3230.19 1742.79ZM3260.02 1756.67 3259.82 1791.25 3232.27 1770.34Z" /><text + id="text84" + transform="matrix(0.494621 0.869109 -0.869109 0.494621 2827.66 1101)" + font-size="55" + font-weight="700" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">Consumed</text> +<text + id="text86" + transform="matrix(0.993011 0.118018 -0.118018 0.993011 2156.49 595)" + font-size="64" + font-weight="400" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">rte_edge == 3</text> +<text + id="text88" + transform="matrix(0.998819 0.0485938 -0.0485938 0.998819 1925.41 932)" + font-size="64" + font-weight="400" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">edge == 0</text> +<text + id="text90" + transform="matrix(0.977645 0.210262 -0.210262 0.977645 1670.89 687)" + font-size="64" + font-weight="400" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">rte_edge == 2</text> +<text + id="text92" + transform="matrix(0.922018 0.387147 -0.387147 0.922018 1082.78 630)" + font-size="64" + font-weight="400" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">rte_edge == 1</text> +<text + id="text94" + transform="matrix(-1.83697e-16 -1 1 -1.83697e-16 974.705 1097)" + font-size="64" + font-weight="400" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">rte_edge == 0</text> +<text + id="text96" + transform="matrix(-1.83697e-16 -1 1 -1.83697e-16 896.661 1024)" + font-size="64" + font-weight="400" + font-family="Arial,Arial_MSFontService,sans-serif" + fill="#212322">Static Path</text> +</g></svg> -- 2.43.0 ^ permalink raw reply [flat|nested] 46+ messages in thread
end of thread, other threads:[~2024-10-17 11:13 UTC | newest] Thread overview: 46+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2024-09-07 7:31 [RFC PATCH 0/3] add feature arc in rte_graph Nitin Saxena 2024-09-07 7:31 ` [RFC PATCH 1/3] graph: add feature arc support Nitin Saxena 2024-09-11 4:41 ` Kiran Kumar Kokkilagadda 2024-10-10 4:42 ` Nitin Saxena 2024-09-07 7:31 ` [RFC PATCH 2/3] graph: add feature arc option in graph create Nitin Saxena 2024-09-07 7:31 ` [RFC PATCH 3/3] graph: add IPv4 output feature arc Nitin Saxena 2024-10-08 8:04 ` [RFC PATCH 0/3] add feature arc in rte_graph David Marchand 2024-10-08 14:26 ` [EXTERNAL] " Nitin Saxena 2024-10-14 11:11 ` Nitin Saxena 2024-10-16 9:24 ` David Marchand 2024-10-16 9:38 ` Robin Jarry 2024-10-16 13:50 ` Nitin Saxena 2024-10-17 7:03 ` Nitin Saxena 2024-10-17 7:50 ` Robin Jarry 2024-10-17 8:32 ` [EXTERNAL] " Christophe Fontaine 2024-10-17 10:56 ` Nitin Saxena 2024-10-17 8:48 ` [EXTERNAL] " Nitin Saxena 2024-10-08 13:30 ` [RFC PATCH v2 0/5] " Nitin Saxena 2024-10-08 13:30 ` [RFC PATCH v2 1/5] graph: add feature arc support Nitin Saxena 2024-10-08 13:30 ` [RFC PATCH v2 2/5] graph: add feature arc option in graph create Nitin Saxena 2024-10-08 13:30 ` [RFC PATCH v2 3/5] graph: add IPv4 output feature arc Nitin Saxena 2024-10-08 13:30 ` [RFC PATCH v2 4/5] test/graph_feature_arc: add functional tests Nitin Saxena 2024-10-08 13:30 ` [RFC PATCH v2 5/5] docs: add programming guide for feature arc Nitin Saxena 2024-10-09 13:29 ` [PATCH v3 0/5] add feature arc in rte_graph Nitin Saxena 2024-10-09 13:29 ` [PATCH v3 1/5] graph: add feature arc support Nitin Saxena 2024-10-09 13:29 ` [PATCH v3 2/5] graph: add feature arc option in graph create Nitin Saxena 2024-10-09 13:30 ` [PATCH v3 3/5] graph: add IPv4 output feature arc Nitin Saxena 2024-10-09 13:30 ` [PATCH v3 4/5] test/graph_feature_arc: add functional tests Nitin Saxena 2024-10-09 13:30 ` [PATCH v3 5/5] docs: add programming guide for feature arc Nitin Saxena 2024-10-09 14:21 ` [PATCH v3 0/5] add feature arc in rte_graph Christophe Fontaine 2024-10-10 4:13 ` [EXTERNAL] " Nitin Saxena 2024-10-09 17:37 ` Stephen Hemminger 2024-10-10 4:24 ` [EXTERNAL] " Nitin Saxena 2024-10-10 13:31 ` [PATCH v4 " Nitin Saxena 2024-10-10 13:31 ` [PATCH v4 1/5] graph: add feature arc support Nitin Saxena 2024-10-10 13:31 ` [PATCH v4 2/5] graph: add feature arc option in graph create Nitin Saxena 2024-10-10 13:31 ` [PATCH v4 3/5] graph: add IPv4 output feature arc Nitin Saxena 2024-10-10 13:31 ` [PATCH v4 4/5] test/graph_feature_arc: add functional tests Nitin Saxena 2024-10-10 13:31 ` [PATCH v4 5/5] docs: add programming guide for feature arc Nitin Saxena 2024-10-14 14:33 ` [PATCH v5 0/5] add feature arc in rte_graph Nitin Saxena 2024-10-14 14:33 ` [PATCH v5 1/5] graph: add feature arc support Nitin Saxena 2024-10-14 14:33 ` [PATCH v5 2/5] graph: add feature arc option in graph create Nitin Saxena 2024-10-14 14:33 ` [PATCH v5 3/5] graph: add IPv4 output feature arc Nitin Saxena 2024-10-14 14:33 ` [PATCH v5 4/5] test/graph_feature_arc: add functional tests Nitin Saxena 2024-10-14 19:54 ` Stephen Hemminger 2024-10-14 14:33 ` [PATCH v5 5/5] docs: add programming guide for feature arc Nitin Saxena
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).