X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=examples%2Fip_pipeline%2Fpipeline%2Fpipeline_flow_classification_be.c;h=097ec3469b7efc77946aaed22bb1e7f474954290;hb=0fe99cf73eec0426ef9cb5eb71c1b8b4de40162c;hp=c9fd1a7a452577b0b7e34cd7b8cd015ff7c44fc7;hpb=984d0d24e6061e6023f8d20d14bd57b946a0f030;p=dpdk.git diff --git a/examples/ip_pipeline/pipeline/pipeline_flow_classification_be.c b/examples/ip_pipeline/pipeline/pipeline_flow_classification_be.c index c9fd1a7a45..097ec3469b 100644 --- a/examples/ip_pipeline/pipeline/pipeline_flow_classification_be.c +++ b/examples/ip_pipeline/pipeline/pipeline_flow_classification_be.c @@ -1,34 +1,5 @@ -/*- - * BSD LICENSE - * - * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2016 Intel Corporation */ #include @@ -40,6 +11,8 @@ #include #include "pipeline_flow_classification_be.h" +#include "pipeline_actions_common.h" +#include "parser.h" #include "hash_func.h" struct pipeline_flow_classification { @@ -47,10 +20,15 @@ struct pipeline_flow_classification { pipeline_msg_req_handler custom_handlers[PIPELINE_FC_MSG_REQS]; uint32_t n_flows; - uint32_t key_offset; uint32_t key_size; + uint32_t flow_id; + + uint32_t key_offset; uint32_t hash_offset; - uint8_t *key_mask; + uint8_t key_mask[PIPELINE_FC_FLOW_KEY_MAX_SIZE]; + uint32_t key_mask_present; + uint32_t flow_id_offset; + } __rte_cache_aligned; static void * @@ -106,6 +84,9 @@ static pipeline_msg_req_handler custom_handlers[] = { */ struct flow_table_entry { struct rte_pipeline_table_entry head; + + uint32_t flow_id; + uint32_t pad; }; rte_table_hash_op_hash hash_func[] = { @@ -119,6 +100,86 @@ rte_table_hash_op_hash hash_func[] = { hash_default_key64 }; +/* + * Flow table AH - Write flow_id to packet meta-data + */ +static inline void +pkt_work_flow_id( + struct rte_mbuf *pkt, + struct rte_pipeline_table_entry *table_entry, + void *arg) +{ + struct pipeline_flow_classification *p_fc = arg; + uint32_t *flow_id_ptr = + RTE_MBUF_METADATA_UINT32_PTR(pkt, p_fc->flow_id_offset); + struct flow_table_entry *entry = + (struct flow_table_entry *) table_entry; + + /* Read */ + uint32_t flow_id = entry->flow_id; + + /* Compute */ + + /* Write */ + *flow_id_ptr = flow_id; +} + +static inline void +pkt4_work_flow_id( + struct rte_mbuf **pkts, + struct rte_pipeline_table_entry **table_entries, + void *arg) +{ + struct pipeline_flow_classification *p_fc = arg; + + uint32_t *flow_id_ptr0 = + RTE_MBUF_METADATA_UINT32_PTR(pkts[0], p_fc->flow_id_offset); + uint32_t *flow_id_ptr1 = + RTE_MBUF_METADATA_UINT32_PTR(pkts[1], p_fc->flow_id_offset); + uint32_t *flow_id_ptr2 = + RTE_MBUF_METADATA_UINT32_PTR(pkts[2], p_fc->flow_id_offset); + uint32_t *flow_id_ptr3 = + RTE_MBUF_METADATA_UINT32_PTR(pkts[3], p_fc->flow_id_offset); + + struct flow_table_entry *entry0 = + (struct flow_table_entry *) table_entries[0]; + struct flow_table_entry *entry1 = + (struct flow_table_entry *) table_entries[1]; + struct flow_table_entry *entry2 = + (struct flow_table_entry *) table_entries[2]; + struct flow_table_entry *entry3 = + (struct flow_table_entry *) table_entries[3]; + + /* Read */ + uint32_t flow_id0 = entry0->flow_id; + uint32_t flow_id1 = entry1->flow_id; + uint32_t flow_id2 = entry2->flow_id; + uint32_t flow_id3 = entry3->flow_id; + + /* Compute */ + + /* Write */ + *flow_id_ptr0 = flow_id0; + *flow_id_ptr1 = flow_id1; + *flow_id_ptr2 = flow_id2; + *flow_id_ptr3 = flow_id3; +} + +PIPELINE_TABLE_AH_HIT(fc_table_ah_hit, + pkt_work_flow_id, pkt4_work_flow_id); + +static rte_pipeline_table_action_handler_hit +get_fc_table_ah_hit(struct pipeline_flow_classification *p) +{ + if (p->flow_id) + return fc_table_ah_hit; + + return NULL; +} + +/* + * Argument parsing + */ static int pipeline_fc_parse_args(struct pipeline_flow_classification *p, struct pipeline_params *params) @@ -128,112 +189,185 @@ pipeline_fc_parse_args(struct pipeline_flow_classification *p, uint32_t key_size_present = 0; uint32_t hash_offset_present = 0; uint32_t key_mask_present = 0; + uint32_t flow_id_offset_present = 0; uint32_t i; - char *key_mask_str = NULL; + char key_mask_str[PIPELINE_FC_FLOW_KEY_MAX_SIZE * 2 + 1]; p->hash_offset = 0; + /* default values */ + p->flow_id = 0; + for (i = 0; i < params->n_args; i++) { char *arg_name = params->args_name[i]; char *arg_value = params->args_value[i]; /* n_flows */ if (strcmp(arg_name, "n_flows") == 0) { - if (n_flows_present) - goto error_parse; + int status; + + PIPELINE_PARSE_ERR_DUPLICATE( + n_flows_present == 0, params->name, + arg_name); n_flows_present = 1; - p->n_flows = atoi(arg_value); - if (p->n_flows == 0) - goto error_parse; + status = parser_read_uint32(&p->n_flows, + arg_value); + PIPELINE_PARSE_ERR_INV_VAL(((status != -EINVAL) && + (p->n_flows != 0)), params->name, + arg_name, arg_value); + PIPELINE_PARSE_ERR_OUT_RNG((status != -ERANGE), + params->name, arg_name, arg_value); continue; } /* key_offset */ if (strcmp(arg_name, "key_offset") == 0) { - if (key_offset_present) - goto error_parse; + int status; + PIPELINE_PARSE_ERR_DUPLICATE( + key_offset_present == 0, params->name, + arg_name); key_offset_present = 1; - p->key_offset = atoi(arg_value); + status = parser_read_uint32(&p->key_offset, + arg_value); + PIPELINE_PARSE_ERR_INV_VAL((status != -EINVAL), + params->name, arg_name, arg_value); + PIPELINE_PARSE_ERR_OUT_RNG((status != -ERANGE), + params->name, arg_name, arg_value); continue; } /* key_size */ if (strcmp(arg_name, "key_size") == 0) { - if (key_size_present) - goto error_parse; + int status; + + PIPELINE_PARSE_ERR_DUPLICATE( + key_size_present == 0, params->name, + arg_name); key_size_present = 1; - p->key_size = atoi(arg_value); - if ((p->key_size == 0) || - (p->key_size > PIPELINE_FC_FLOW_KEY_MAX_SIZE) || - (p->key_size % 8)) - goto error_parse; + status = parser_read_uint32(&p->key_size, + arg_value); + PIPELINE_PARSE_ERR_INV_VAL(((status != -EINVAL) && + (p->key_size != 0) && + (p->key_size % 8 == 0)), + params->name, arg_name, arg_value); + PIPELINE_PARSE_ERR_OUT_RNG(((status != -ERANGE) && + (p->key_size <= + PIPELINE_FC_FLOW_KEY_MAX_SIZE)), + params->name, arg_name, arg_value); continue; } /* key_mask */ if (strcmp(arg_name, "key_mask") == 0) { - if (key_mask_present) - goto error_parse; - - key_mask_str = strdup(arg_value); - if (key_mask_str == NULL) - goto error_parse; + int mask_str_len = strlen(arg_value); + PIPELINE_PARSE_ERR_DUPLICATE( + key_mask_present == 0, + params->name, arg_name); key_mask_present = 1; + PIPELINE_ARG_CHECK((mask_str_len <= + (PIPELINE_FC_FLOW_KEY_MAX_SIZE * 2)), + "Parse error in section \"%s\": entry " + "\"%s\" is too long", params->name, + arg_name); + + snprintf(key_mask_str, mask_str_len + 1, "%s", + arg_value); + continue; } /* hash_offset */ if (strcmp(arg_name, "hash_offset") == 0) { - if (hash_offset_present) - goto error_parse; + int status; + + PIPELINE_PARSE_ERR_DUPLICATE( + hash_offset_present == 0, params->name, + arg_name); hash_offset_present = 1; - p->hash_offset = atoi(arg_value); + status = parser_read_uint32(&p->hash_offset, + arg_value); + PIPELINE_PARSE_ERR_INV_VAL((status != -EINVAL), + params->name, arg_name, arg_value); + PIPELINE_PARSE_ERR_OUT_RNG((status != -ERANGE), + params->name, arg_name, arg_value); + + continue; + } + + /* flow_id_offset */ + if (strcmp(arg_name, "flowid_offset") == 0) { + int status; + + PIPELINE_PARSE_ERR_DUPLICATE( + flow_id_offset_present == 0, params->name, + arg_name); + flow_id_offset_present = 1; + + status = parser_read_uint32(&p->flow_id_offset, + arg_value); + PIPELINE_PARSE_ERR_INV_VAL((status != -EINVAL), + params->name, arg_name, arg_value); + PIPELINE_PARSE_ERR_OUT_RNG((status != -ERANGE), + params->name, arg_name, arg_value); + + p->flow_id = 1; continue; } /* Unknown argument */ - return -1; + PIPELINE_PARSE_ERR_INV_ENT(0, params->name, arg_name); } /* Check that mandatory arguments are present */ - if ((n_flows_present == 0) || - (key_offset_present == 0) || - (key_size_present == 0)) - goto error_parse; + PIPELINE_PARSE_ERR_MANDATORY((n_flows_present), params->name, + "n_flows"); + PIPELINE_PARSE_ERR_MANDATORY((key_offset_present), params->name, + "key_offset"); + PIPELINE_PARSE_ERR_MANDATORY((key_size_present), params->name, + "key_size"); if (key_mask_present) { - p->key_mask = rte_malloc(NULL, p->key_size, 0); - if (p->key_mask == NULL) - goto error_parse; + uint32_t key_size = p->key_size; + int status; - if (parse_hex_string(key_mask_str, p->key_mask, &p->key_size) - != 0) { - goto error_parse; - } + PIPELINE_ARG_CHECK(((key_size == 8) || (key_size == 16)), + "Parse error in section \"%s\": entry key_mask " + "only allowed for key_size of 8 or 16 bytes", + params->name); + + PIPELINE_ARG_CHECK((strlen(key_mask_str) == + (key_size * 2)), "Parse error in section " + "\"%s\": key_mask should have exactly %u hex " + "digits", params->name, (key_size * 2)); - free(key_mask_str); + PIPELINE_ARG_CHECK((hash_offset_present == 0), "Parse " + "error in section \"%s\": entry hash_offset only " + "allowed when key_mask is not present", + params->name); + + status = parse_hex_string(key_mask_str, p->key_mask, + &p->key_size); + + PIPELINE_PARSE_ERR_INV_VAL(((status == 0) && + (key_size == p->key_size)), params->name, + "key_mask", key_mask_str); } - return 0; + p->key_mask_present = key_mask_present; -error_parse: - if (key_mask_str != NULL) - free(key_mask_str); - if (p->key_mask != NULL) - free(p->key_mask); - return -1; + return 0; } static void *pipeline_fc_init(struct pipeline_params *params, @@ -312,7 +446,6 @@ static void *pipeline_fc_init(struct pipeline_params *params, .arg_create = pipeline_port_out_params_convert( ¶ms->port_out[i]), .f_action = NULL, - .f_action_bulk = NULL, .arg_ah = NULL, }; @@ -330,46 +463,24 @@ static void *pipeline_fc_init(struct pipeline_params *params, /* Tables */ p->n_tables = 1; { - struct rte_table_hash_key8_ext_params - table_hash_key8_params = { - .n_entries = p_fc->n_flows, - .n_entries_ext = p_fc->n_flows, - .signature_offset = p_fc->hash_offset, - .key_offset = p_fc->key_offset, - .f_hash = hash_func[(p_fc->key_size / 8) - 1], - .key_mask = p_fc->key_mask, - .seed = 0, - }; - - struct rte_table_hash_key16_ext_params - table_hash_key16_params = { - .n_entries = p_fc->n_flows, - .n_entries_ext = p_fc->n_flows, - .signature_offset = p_fc->hash_offset, - .key_offset = p_fc->key_offset, - .f_hash = hash_func[(p_fc->key_size / 8) - 1], - .key_mask = p_fc->key_mask, - .seed = 0, - }; - - struct rte_table_hash_ext_params - table_hash_params = { + struct rte_table_hash_params table_hash_params = { + .name = p->name, .key_size = p_fc->key_size, + .key_offset = p_fc->key_offset, + .key_mask = (p_fc->key_mask_present) ? + p_fc->key_mask : NULL, .n_keys = p_fc->n_flows, - .n_buckets = p_fc->n_flows / 4, - .n_buckets_ext = p_fc->n_flows / 4, + .n_buckets = rte_align32pow2(p_fc->n_flows / 4), .f_hash = hash_func[(p_fc->key_size / 8) - 1], .seed = 0, - .signature_offset = p_fc->hash_offset, - .key_offset = p_fc->key_offset, }; struct rte_pipeline_table_params table_params = { .ops = NULL, /* set below */ .arg_create = NULL, /* set below */ - .f_action_hit = NULL, + .f_action_hit = get_fc_table_ah_hit(p_fc), .f_action_miss = NULL, - .arg_ah = NULL, + .arg_ah = p_fc, .action_data_size = sizeof(struct flow_table_entry) - sizeof(struct rte_pipeline_table_entry), }; @@ -378,33 +489,19 @@ static void *pipeline_fc_init(struct pipeline_params *params, switch (p_fc->key_size) { case 8: - if (p_fc->hash_offset != 0) { - table_params.ops = - &rte_table_hash_key8_ext_ops; - } else { - table_params.ops = - &rte_table_hash_key8_ext_dosig_ops; - } - table_params.arg_create = &table_hash_key8_params; - break; + table_params.ops = &rte_table_hash_key8_ext_ops; break; case 16: - if (p_fc->hash_offset != 0) { - table_params.ops = - &rte_table_hash_key16_ext_ops; - } else { - table_params.ops = - &rte_table_hash_key16_ext_dosig_ops; - } - table_params.arg_create = &table_hash_key16_params; + table_params.ops = &rte_table_hash_key16_ext_ops; break; default: table_params.ops = &rte_table_hash_ext_ops; - table_params.arg_create = &table_hash_params; } + table_params.arg_create = &table_hash_params; + status = rte_pipeline_table_create(p->p, &table_params, &p->table_id[0]); @@ -479,27 +576,6 @@ pipeline_fc_free(void *pipeline) return 0; } -static int -pipeline_fc_track(void *pipeline, - __rte_unused uint32_t port_in, - uint32_t *port_out) -{ - struct pipeline *p = (struct pipeline *) pipeline; - - /* Check input arguments */ - if ((p == NULL) || - (port_in >= p->n_ports_in) || - (port_out == NULL)) - return -1; - - if (p->n_ports_in == 1) { - *port_out = 0; - return 0; - } - - return -1; -} - static int pipeline_fc_timer(void *pipeline) { @@ -540,6 +616,7 @@ pipeline_fc_msg_req_add_handler(struct pipeline *p, void *msg) .action = RTE_PIPELINE_ACTION_PORT, {.port_id = p->port_out_id[req->port_id]}, }, + .flow_id = req->flow_id, }; rsp->status = rte_pipeline_table_entry_add(p->p, @@ -568,6 +645,7 @@ pipeline_fc_msg_req_add_bulk_handler(struct pipeline *p, void *msg) .action = RTE_PIPELINE_ACTION_PORT, {.port_id = p->port_out_id[flow_req->port_id]}, }, + .flow_id = flow_req->flow_id, }; int status = rte_pipeline_table_entry_add(p->p, @@ -613,6 +691,8 @@ pipeline_fc_msg_req_add_default_handler(struct pipeline *p, void *msg) .action = RTE_PIPELINE_ACTION_PORT, {.port_id = p->port_out_id[req->port_id]}, }, + + .flow_id = 0, }; rsp->status = rte_pipeline_table_default_entry_add(p->p, @@ -640,5 +720,4 @@ struct pipeline_be_ops pipeline_flow_classification_be_ops = { .f_free = pipeline_fc_free, .f_run = NULL, .f_timer = pipeline_fc_timer, - .f_track = pipeline_fc_track, };