From patchwork Fri May 29 15:43:18 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Maciej Gajdzica X-Patchwork-Id: 4998 Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [IPv6:::1]) by dpdk.org (Postfix) with ESMTP id D54E79A8A; Fri, 29 May 2015 18:24:47 +0200 (CEST) Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by dpdk.org (Postfix) with ESMTP id CB34E5A96 for ; Fri, 29 May 2015 18:24:44 +0200 (CEST) Received: from orsmga001.jf.intel.com ([10.7.209.18]) by fmsmga103.fm.intel.com with ESMTP; 29 May 2015 09:24:43 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.13,517,1427785200"; d="scan'208";a="702191750" Received: from unknown (HELO stargo) ([10.217.248.233]) by orsmga001.jf.intel.com with SMTP; 29 May 2015 09:24:42 -0700 Received: by stargo (sSMTP sendmail emulation); Fri, 29 May 2015 18:25:15 +0200 From: Maciej Gajdzica To: dev@dpdk.org Date: Fri, 29 May 2015 17:43:18 +0200 Message-Id: <1432914198-11812-12-git-send-email-maciejx.t.gajdzica@intel.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1432914198-11812-1-git-send-email-maciejx.t.gajdzica@intel.com> References: <1432914198-11812-1-git-send-email-maciejx.t.gajdzica@intel.com> Subject: [dpdk-dev] [PATCH 11/11] ip_pipeline: added new implementation of flow classification pipeline X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: patches and discussions about DPDK List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" Flow classification pipeline implementation is split to two files. pipeline_flow_classification.c file handles front-end functions (cli commands parsing) pipeline_flow_classification_ops.c contains implementation of functions done by pipeline (back-end). Signed-off-by: Maciej Gajdzica --- examples/ip_pipeline/Makefile | 3 +- examples/ip_pipeline/init.c | 2 + .../pipeline/pipeline_flow_classification.c | 1761 +++++++++++++++++--- .../pipeline/pipeline_flow_classification.h | 41 + .../pipeline/pipeline_flow_classification_ops.c | 559 +++++++ .../pipeline/pipeline_flow_classification_ops.h | 150 ++ 6 files changed, 2292 insertions(+), 224 deletions(-) create mode 100644 examples/ip_pipeline/pipeline/pipeline_flow_classification.h create mode 100644 examples/ip_pipeline/pipeline/pipeline_flow_classification_ops.c create mode 100644 examples/ip_pipeline/pipeline/pipeline_flow_classification_ops.h diff --git a/examples/ip_pipeline/Makefile b/examples/ip_pipeline/Makefile index f8c7c5f..4a1d970 100644 --- a/examples/ip_pipeline/Makefile +++ b/examples/ip_pipeline/Makefile @@ -65,7 +65,8 @@ SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_firewall_ops.c SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_firewall.c SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_routing_ops.c SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_routing.c -#SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_flow_classification.c +SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_flow_classification.c +SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_flow_classification_ops.c CFLAGS += -I$(SRCDIR) -I$(SRCDIR)/pipeline CFLAGS += -O3 diff --git a/examples/ip_pipeline/init.c b/examples/ip_pipeline/init.c index 29caae8..a8d2f67 100644 --- a/examples/ip_pipeline/init.c +++ b/examples/ip_pipeline/init.c @@ -47,6 +47,7 @@ #include "pipeline_passthrough.h" #include "pipeline_firewall.h" #include "pipeline_routing.h" +#include "pipeline_flow_classification.h" #define APP_NAME_SIZE 32 @@ -1150,6 +1151,7 @@ int app_init(struct app_params *app) app_pipeline_type_register(app, &pipeline_passthrough); app_pipeline_type_register(app, &pipeline_firewall); app_pipeline_type_register(app, &pipeline_routing); + app_pipeline_type_register(app, &pipeline_flow_classification); app_init_pipelines(app); app_init_threads(app); diff --git a/examples/ip_pipeline/pipeline/pipeline_flow_classification.c b/examples/ip_pipeline/pipeline/pipeline_flow_classification.c index cc0cbf1..928e2ab 100644 --- a/examples/ip_pipeline/pipeline/pipeline_flow_classification.c +++ b/examples/ip_pipeline/pipeline/pipeline_flow_classification.c @@ -1,7 +1,7 @@ /*- * BSD LICENSE * - * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. + * Copyright(c) 2010-2015 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -32,275 +32,1590 @@ */ #include -#include -#include +#include +#include +#include +#include #include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include -#include -#include -#include +#include "app.h" +#include "pipeline_flow_classification_ops.h" +#include "pipeline_flow_classification.h" +#include "pipeline_common.h" -#include "main.h" +#define MSG_TIMEOUT 1000 -struct app_core_fc_message_handle_params { - struct rte_ring *ring_req; - struct rte_ring *ring_resp; +struct app_pipeline_fc_flow { + struct pipeline_fc_key key; + uint32_t port_id; + void *entry_ptr; - struct rte_pipeline *p; - uint32_t *port_out_id; - uint32_t table_id; + TAILQ_ENTRY(app_pipeline_fc_flow) node; }; +struct app_pipeline_fc { + TAILQ_HEAD(, app_pipeline_fc_flow) flows; + + uint32_t n_flows; +}; + +static struct app_pipeline_fc_flow * +app_pipeline_fc_flow_find(struct app_pipeline_fc *p, + struct pipeline_fc_key *key) +{ + struct app_pipeline_fc_flow *f; + + TAILQ_FOREACH(f, &p->flows, node) + if (memcmp(key, &f->key, sizeof(struct pipeline_fc_key)) == 0) + return f; + + return NULL; +} + +static void +print_fc_qinq_flow(struct app_pipeline_fc_flow *flow) +{ + printf("svlan = %u, " + "cvlan = %u " + "=> Port = %u " + "(entry_ptr = %p)\n", + + flow->key.key.qinq.svlan, + flow->key.key.qinq.cvlan, + flow->port_id, + flow->entry_ptr); +} + static void -app_message_handle(struct app_core_fc_message_handle_params *params); +print_fc_ipv4_5tuple_flow(struct app_pipeline_fc_flow *flow) +{ + printf("SA = %u.%u.%u.%u " + "DA = %u.%u.%u.%u " + "SP = %u " + "DP = %u " + "Proto = %u " + "=> Port = %u " + "(entry_ptr = %p)\n", + + (flow->key.key.ipv4_5tuple.ip_src >> 24) & 0xFF, + (flow->key.key.ipv4_5tuple.ip_src >> 16) & 0xFF, + (flow->key.key.ipv4_5tuple.ip_src >> 8) & 0xFF, + flow->key.key.ipv4_5tuple.ip_src & 0xFF, + + (flow->key.key.ipv4_5tuple.ip_dst >> 24) & 0xFF, + (flow->key.key.ipv4_5tuple.ip_dst >> 16) & 0xFF, + (flow->key.key.ipv4_5tuple.ip_dst >> 8) & 0xFF, + flow->key.key.ipv4_5tuple.ip_dst & 0xFF, + + flow->key.key.ipv4_5tuple.port_src, + flow->key.key.ipv4_5tuple.port_dst, + + flow->key.key.ipv4_5tuple.proto, + + flow->port_id, + flow->entry_ptr); +} + +static void +print_fc_ipv6_5tuple_flow(struct app_pipeline_fc_flow *flow) +{ + printf("SA = %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x " + "DA = %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x " + "SP = %u " + "DP = %u " + "Proto = %u " + "=> Port = %u " + "(entry_ptr = %p)\n", + + flow->key.key.ipv6_5tuple.ip_src[0], + flow->key.key.ipv6_5tuple.ip_src[1], + flow->key.key.ipv6_5tuple.ip_src[2], + flow->key.key.ipv6_5tuple.ip_src[3], + flow->key.key.ipv6_5tuple.ip_src[4], + flow->key.key.ipv6_5tuple.ip_src[5], + flow->key.key.ipv6_5tuple.ip_src[6], + flow->key.key.ipv6_5tuple.ip_src[7], + flow->key.key.ipv6_5tuple.ip_src[8], + flow->key.key.ipv6_5tuple.ip_src[9], + flow->key.key.ipv6_5tuple.ip_src[10], + flow->key.key.ipv6_5tuple.ip_src[11], + flow->key.key.ipv6_5tuple.ip_src[12], + flow->key.key.ipv6_5tuple.ip_src[13], + flow->key.key.ipv6_5tuple.ip_src[14], + flow->key.key.ipv6_5tuple.ip_src[15], + + flow->key.key.ipv6_5tuple.ip_dst[0], + flow->key.key.ipv6_5tuple.ip_dst[1], + flow->key.key.ipv6_5tuple.ip_dst[2], + flow->key.key.ipv6_5tuple.ip_dst[3], + flow->key.key.ipv6_5tuple.ip_dst[4], + flow->key.key.ipv6_5tuple.ip_dst[5], + flow->key.key.ipv6_5tuple.ip_dst[6], + flow->key.key.ipv6_5tuple.ip_dst[7], + flow->key.key.ipv6_5tuple.ip_dst[8], + flow->key.key.ipv6_5tuple.ip_dst[9], + flow->key.key.ipv6_5tuple.ip_dst[10], + flow->key.key.ipv6_5tuple.ip_dst[11], + flow->key.key.ipv6_5tuple.ip_dst[12], + flow->key.key.ipv6_5tuple.ip_dst[13], + flow->key.key.ipv6_5tuple.ip_dst[14], + flow->key.key.ipv6_5tuple.ip_dst[15], -static int app_flow_classification_table_init( - struct rte_pipeline *p, - uint32_t *port_out_id, - uint32_t table_id) + flow->key.key.ipv6_5tuple.port_src, + flow->key.key.ipv6_5tuple.port_dst, + + flow->key.key.ipv6_5tuple.proto, + + flow->port_id, + flow->entry_ptr); +} + +static void +print_fc_flow(struct app_pipeline_fc_flow *flow) { - struct app_flow_key flow_key; - uint32_t i; - - /* Add entries to tables */ - for (i = 0; i < (1 << 24); i++) { - struct rte_pipeline_table_entry entry = { - .action = RTE_PIPELINE_ACTION_PORT, - {.port_id = port_out_id[i & (app.n_ports - 1)]}, - }; - struct rte_pipeline_table_entry *entry_ptr; - int key_found, status; - - flow_key.ttl = 0; - flow_key.proto = 6; /* TCP */ - flow_key.header_checksum = 0; - flow_key.ip_src = 0; - flow_key.ip_dst = rte_bswap32(i); - flow_key.port_src = 0; - flow_key.port_dst = 0; - - status = rte_pipeline_table_entry_add(p, table_id, - (void *) &flow_key, &entry, &key_found, &entry_ptr); - if (status < 0) - rte_panic("Unable to add entry to table %u (%d)\n", - table_id, status); + switch(flow->key.type) { + case FLOW_KEY_QINQ: + print_fc_qinq_flow(flow); + break; + case FLOW_KEY_IPV4_5TUPLE: + print_fc_ipv4_5tuple_flow(flow); + break; + case FLOW_KEY_IPV6_5TUPLE: + print_fc_ipv6_5tuple_flow(flow); + break; } +} - return 0; +static void +app_pipeline_fc_qinq_default_set(struct pipeline_fc_key *default_key) +{ + default_key->key.qinq.svlan = 0xFFFF; + default_key->key.qinq.cvlan = 0xFFFF; } -void -app_main_loop_pipeline_flow_classification(void) { - struct rte_pipeline_params pipeline_params = { - .name = "pipeline", - .socket_id = rte_socket_id(), - }; +static void +app_pipeline_fc_ipv4_5tuple_default_set(struct pipeline_fc_key *default_key) +{ + default_key->key.ipv4_5tuple.ip_src = 0; + default_key->key.ipv4_5tuple.ip_dst = 0; + default_key->key.ipv4_5tuple.port_src = 0; + default_key->key.ipv4_5tuple.port_dst = 0; + default_key->key.ipv4_5tuple.proto = 0xFF; +} + +static void +app_pipeline_fc_ipv6_5tuple_default_set(struct pipeline_fc_key *default_key) +{ + memset(default_key->key.ipv6_5tuple.ip_src, 0, 16); + memset(default_key->key.ipv6_5tuple.ip_dst, 0, 16); + default_key->key.ipv6_5tuple.port_src = 0; + default_key->key.ipv6_5tuple.port_dst = 0; + default_key->key.ipv6_5tuple.proto = 0xFF; +} - struct rte_pipeline *p; - uint32_t port_in_id[APP_MAX_PORTS]; - uint32_t port_out_id[APP_MAX_PORTS]; - uint32_t table_id; - uint32_t i; +static void* +app_pipeline_fc_init(struct pipeline_params *params, + __rte_unused void *arg) +{ + struct app_pipeline_fc *p; + uint32_t size; + + /* Check input arguments */ + if ((params == NULL)) + return NULL; + + /* Memory allocation */ + size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct app_pipeline_fc)); + p = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE); + if (p == NULL) + return NULL; - uint32_t core_id = rte_lcore_id(); - struct app_core_params *core_params = app_get_core_params(core_id); - struct app_core_fc_message_handle_params mh_params; + /* Initialization */ + TAILQ_INIT(&p->flows); + p->n_flows = 0; - if ((core_params == NULL) || (core_params->core_type != APP_CORE_FC)) - rte_panic("Core %u misconfiguration\n", core_id); + return (void *) p; +} - RTE_LOG(INFO, USER1, "Core %u is doing flow classification " - "(pipeline with hash table, 16-byte key, LRU)\n", core_id); +static int +app_pipeline_fc_free(void *pipeline) +{ + struct app_pipeline_fc *p = pipeline; + struct app_pipeline_fc_flow *flow; - /* Pipeline configuration */ - p = rte_pipeline_create(&pipeline_params); + /* Check input arguments */ if (p == NULL) - rte_panic("Unable to configure the pipeline\n"); - - /* Input port configuration */ - for (i = 0; i < app.n_ports; i++) { - struct rte_port_ring_reader_params port_ring_params = { - .ring = app.rings[core_params->swq_in[i]], - }; - - struct rte_pipeline_port_in_params port_params = { - .ops = &rte_port_ring_reader_ops, - .arg_create = (void *) &port_ring_params, - .f_action = NULL, - .arg_ah = NULL, - .burst_size = app.bsz_swq_rd, - }; - - if (rte_pipeline_port_in_create(p, &port_params, - &port_in_id[i])) - rte_panic("Unable to configure input port for " - "ring %d\n", i); + return -1; + + /* Free resources */ + TAILQ_FOREACH(flow, &p->flows, node) { + TAILQ_REMOVE(&p->flows, flow, node); + rte_free(flow); } - /* Output port configuration */ - for (i = 0; i < app.n_ports; i++) { - struct rte_port_ring_writer_params port_ring_params = { - .ring = app.rings[core_params->swq_out[i]], - .tx_burst_sz = app.bsz_swq_wr, - }; - - struct rte_pipeline_port_out_params port_params = { - .ops = &rte_port_ring_writer_ops, - .arg_create = (void *) &port_ring_params, - .f_action = NULL, - .f_action_bulk = NULL, - .arg_ah = NULL, - }; - - if (rte_pipeline_port_out_create(p, &port_params, - &port_out_id[i])) - rte_panic("Unable to configure output port for " - "ring %d\n", i); + rte_free(p); + return 0; +} + +static int +app_pipeline_fc_add(struct app_params *app, + uint32_t pipeline_id, + struct pipeline_fc_key *key, + uint32_t port_id) +{ + struct app_pipeline_params *params; + struct app_pipeline_data *data; + struct app_pipeline_fc *p; + struct app_pipeline_fc_flow *flow; + + struct pipeline_fc_add_msg_req *req; + struct pipeline_fc_add_msg_rsp *rsp; + + int new_flow; + + /* Check input arguments */ + if ((app == NULL) || + (key == NULL)) + return -1; + + APP_PARAM_FIND_BY_ID(app->pipeline_params, "PIPELINE", pipeline_id, params); + if ((params == NULL)) + return -1; + + data = &app->pipeline_data[params - app->pipeline_params]; + p = data->fe; + + /* Find existing flow or allocate new flow */ + flow = app_pipeline_fc_flow_find(p, key); + new_flow = (flow == NULL); + if (flow == NULL) { + flow = rte_malloc(NULL, sizeof(*flow), RTE_CACHE_LINE_SIZE); + + if (flow == NULL) + return -1; } - /* Table configuration */ - { - struct rte_table_hash_key16_lru_params table_hash_params = { - .n_entries = 1 << 24, - .signature_offset = __builtin_offsetof( - struct app_pkt_metadata, signature), - .key_offset = __builtin_offsetof( - struct app_pkt_metadata, flow_key), - .f_hash = test_hash, - .seed = 0, - }; - - struct rte_pipeline_table_params table_params = { - .ops = &rte_table_hash_key16_lru_ops, - .arg_create = &table_hash_params, - .f_action_hit = NULL, - .f_action_miss = NULL, - .arg_ah = NULL, - .action_data_size = 0, - }; - - if (rte_pipeline_table_create(p, &table_params, &table_id)) - rte_panic("Unable to configure the hash table\n"); + /* Allocate and write request */ + req = app_msg_alloc(app); + if (req == NULL) + return -1; + + req->type = PIPELINE_MSG_REQ_CUSTOM; + req->subtype = PIPELINE_FC_MSG_REQ_FLOW_ADD; + memcpy(&req->key, key, sizeof(*key)); + req->port_id = port_id; + + /* Send request and wait for response */ + rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT); + if (rsp == NULL) { + if (new_flow) + rte_free(flow); + return -1; } - /* Interconnecting ports and tables */ - for (i = 0; i < app.n_ports; i++) - if (rte_pipeline_port_in_connect_to_table(p, port_in_id[i], - table_id)) - rte_panic("Unable to connect input port %u to " - "table %u\n", port_in_id[i], table_id); - - /* Enable input ports */ - for (i = 0; i < app.n_ports; i++) - if (rte_pipeline_port_in_enable(p, port_in_id[i])) - rte_panic("Unable to enable input port %u\n", - port_in_id[i]); - - /* Check pipeline consistency */ - if (rte_pipeline_check(p) < 0) - rte_panic("Pipeline consistency check failed\n"); - - /* Message handling */ - mh_params.ring_req = app_get_ring_req( - app_get_first_core_id(APP_CORE_FC)); - mh_params.ring_resp = app_get_ring_resp( - app_get_first_core_id(APP_CORE_FC)); - mh_params.p = p; - mh_params.port_out_id = port_out_id; - mh_params.table_id = table_id; - - /* Run-time */ - for (i = 0; ; i++) { - rte_pipeline_run(p); - - if ((i & APP_FLUSH) == 0) { - rte_pipeline_flush(p); - app_message_handle(&mh_params); - } + /* Read response and write flow */ + if (rsp->status || (rsp->entry_ptr == NULL)){ + app_msg_free(app, rsp); + if (new_flow) + rte_free(flow); + return -1; + } + + memcpy(&flow->key, key, sizeof(*key)); + flow->port_id = port_id; + flow->entry_ptr = rsp->entry_ptr; + + /* Commit rule */ + if (new_flow) { + TAILQ_INSERT_TAIL(&p->flows, flow, node); + p->n_flows++; } + + print_fc_flow(flow); + + /* Free response */ + app_msg_free(app, rsp); + + return 0; } -void -app_message_handle(struct app_core_fc_message_handle_params *params) +static int +app_pipeline_fc_del(struct app_params *app, + uint32_t pipeline_id, + struct pipeline_fc_key *key) { - struct rte_ring *ring_req = params->ring_req; - struct rte_ring *ring_resp; - void *msg; - struct app_msg_req *req; - struct app_msg_resp *resp; - struct rte_pipeline *p; - uint32_t *port_out_id; - uint32_t table_id; - int result; - - /* Read request message */ - result = rte_ring_sc_dequeue(ring_req, &msg); - if (result != 0) - return; + struct app_pipeline_params *params; + struct app_pipeline_data *data; + struct app_pipeline_fc *p; + struct app_pipeline_fc_flow *flow; - ring_resp = params->ring_resp; - p = params->p; - port_out_id = params->port_out_id; - table_id = params->table_id; - - /* Handle request */ - req = (struct app_msg_req *)rte_ctrlmbuf_data((struct rte_mbuf *)msg); - switch (req->type) { - case APP_MSG_REQ_PING: - { - result = 0; - break; + struct pipeline_fc_del_msg_req *req; + struct pipeline_fc_del_msg_rsp *rsp; + + /* Check input arguments */ + if ((app == NULL) || + (key == NULL)) + return -1; + + APP_PARAM_FIND_BY_ID(app->pipeline_params, "PIPELINE", pipeline_id, params); + if (params == NULL) + return -1; + + data = &app->pipeline_data[params - app->pipeline_params]; + p = data->fe; + + /* Find rule */ + flow = app_pipeline_fc_flow_find(p, key); + if (flow == NULL) + return 0; + + /* Allocate and write request */ + req = app_msg_alloc(app); + if (req == NULL) + return -1; + + req->type = PIPELINE_MSG_REQ_CUSTOM; + req->subtype = PIPELINE_FC_MSG_REQ_FLOW_DEL; + memcpy(&req->key, key, sizeof(*key)); + + /* Send request and wait for response */ + rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT); + if (rsp == NULL) + return -1; + + /* Read response */ + if (rsp->status) { + app_msg_free(app, rsp); + return -1; } - case APP_MSG_REQ_FC_ADD_ALL: - { - result = app_flow_classification_table_init(p, port_out_id, - table_id); + /* Remove rule */ + TAILQ_REMOVE(&p->flows, flow, node); + p->n_flows--; + + /* Free response */ + app_msg_free(app, rsp); + + return 0; +} + +static int +app_pipeline_fc_add_default(struct app_params *app, + uint32_t pipeline_id, + enum flow_key_type type, + uint32_t port_id) +{ + struct app_pipeline_params *params; + struct app_pipeline_data *data; + struct app_pipeline_fc *p; + struct app_pipeline_fc_flow *flow; + struct pipeline_fc_key *default_key; + + struct pipeline_fc_add_default_msg_req *req; + struct pipeline_fc_add_default_msg_rsp *rsp; + + int new_flow; + + /* Check input arguments */ + if (app == NULL) + return -1; + + APP_PARAM_FIND_BY_ID(app->pipeline_params, "PIPELINE", pipeline_id, params); + if ((params == NULL)) + return -1; + + data = &app->pipeline_data[params - app->pipeline_params]; + p = data->fe; + + /* Set default flow settings */ + default_key = rte_malloc(NULL, sizeof(*default_key), RTE_CACHE_LINE_SIZE); + if (default_key == NULL) + return -1; + + switch (type) { + case FLOW_KEY_QINQ: + app_pipeline_fc_qinq_default_set(default_key); + break; + case FLOW_KEY_IPV4_5TUPLE: + app_pipeline_fc_ipv4_5tuple_default_set(default_key); + break; + case FLOW_KEY_IPV6_5TUPLE: + app_pipeline_fc_ipv6_5tuple_default_set(default_key); break; } - case APP_MSG_REQ_FC_ADD: - { - struct rte_pipeline_table_entry entry = { - .action = RTE_PIPELINE_ACTION_PORT, - {.port_id = port_out_id[req->flow_classif_add.port]}, - }; + /* Find existing flow or allocate new flow */ + flow = app_pipeline_fc_flow_find(p, default_key); + new_flow = (flow == NULL); + if (flow == NULL) { + flow = rte_malloc(NULL, sizeof(*flow), RTE_CACHE_LINE_SIZE); + + if (flow == NULL) { + rte_free(default_key); + return -1; + } + } + + /* Allocate and write request */ + req = app_msg_alloc(app); + if (req == NULL) { + rte_free(default_key); + return -1; + } - struct rte_pipeline_table_entry *entry_ptr; + req->type = PIPELINE_MSG_REQ_CUSTOM; + req->subtype = PIPELINE_FC_MSG_REQ_FLOW_ADD_DEFAULT; + req->port_id = port_id; - int key_found; + /* Send request and wait for response */ + rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT); + if (rsp == NULL) { + if (new_flow) { + rte_free(flow); + rte_free(default_key); + } + return -1; + } - result = rte_pipeline_table_entry_add(p, table_id, - req->flow_classif_add.key_raw, &entry, &key_found, - &entry_ptr); - break; + /* Read response and write flow */ + if (rsp->status || (rsp->default_entry_ptr == NULL)){ + app_msg_free(app, rsp); + if (new_flow) { + rte_free(flow); + rte_free(default_key); + } + return -1; } - case APP_MSG_REQ_FC_DEL: - { - int key_found; + memcpy(&flow->key, default_key, sizeof(*default_key)); + flow->port_id = port_id; + flow->entry_ptr = rsp->default_entry_ptr; - result = rte_pipeline_table_entry_delete(p, table_id, - req->flow_classif_add.key_raw, &key_found, NULL); + /* Commit rule */ + if (new_flow) { + TAILQ_INSERT_TAIL(&p->flows, flow, node); + p->n_flows++; + } + + /* Free response */ + app_msg_free(app, rsp); + rte_free(default_key); + + return 0; +} + +static int +app_pipeline_fc_del_default(struct app_params *app, + enum flow_key_type type, + uint32_t pipeline_id) +{ + struct app_pipeline_params *params; + struct app_pipeline_data *data; + struct app_pipeline_fc *p; + struct app_pipeline_fc_flow *flow; + struct pipeline_fc_key *default_key; + + struct pipeline_fc_del_default_msg_req *req; + struct pipeline_fc_del_default_msg_rsp *rsp; + + /* Check input arguments */ + if (app == NULL) + return -1; + + APP_PARAM_FIND_BY_ID(app->pipeline_params, "PIPELINE", pipeline_id, params); + if ((params == NULL)) + return -1; + + data = &app->pipeline_data[params - app->pipeline_params]; + p = data->fe; + + /* Set default flow settings */ + default_key = rte_malloc(NULL, sizeof(*default_key), RTE_CACHE_LINE_SIZE); + if (default_key == NULL) + return -1; + + switch (type) { + case FLOW_KEY_QINQ: + app_pipeline_fc_qinq_default_set(default_key); break; + case FLOW_KEY_IPV4_5TUPLE: + app_pipeline_fc_ipv4_5tuple_default_set(default_key); + break; + case FLOW_KEY_IPV6_5TUPLE: + app_pipeline_fc_ipv6_5tuple_default_set(default_key); + break; + } + + /* Find rule */ + flow = app_pipeline_fc_flow_find(p, default_key); + if (flow == NULL) { + rte_free(default_key); + return 0; + } + + /* Allocate and write request */ + req = app_msg_alloc(app); + if (req == NULL) { + rte_free(default_key); + return -1; } - default: - rte_panic("FC Unrecognized message type (%u)\n", req->type); + req->type = PIPELINE_MSG_REQ_CUSTOM; + req->subtype = PIPELINE_FC_MSG_REQ_FLOW_DEL_DEFAULT; + + /* Send request and wait for response */ + rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT); + if (rsp == NULL) { + rte_free(default_key); + return -1; + } + + /* Read response */ + if (rsp->status) { + app_msg_free(app, rsp); + rte_free(default_key); + return -1; } - /* Fill in response message */ - resp = (struct app_msg_resp *)rte_ctrlmbuf_data((struct rte_mbuf *)msg); - resp->result = result; + /* Remove rule */ + TAILQ_REMOVE(&p->flows, flow, node); + p->n_flows--; + + /* Free response */ + app_msg_free(app, rsp); + rte_free(default_key); + + return 0; +} + +static void +app_pipeline_fc_ls(struct app_params *app, + uint32_t pipeline_id) +{ + struct app_pipeline_params *pipeline_params; + struct app_pipeline_data *pipeline_data; + struct app_pipeline_fc *p; + struct app_pipeline_fc_flow *flow; + + /* Check input arguments */ + if (app == NULL) + return; + + APP_PARAM_FIND_BY_ID(app->pipeline_params, "PIPELINE", pipeline_id, pipeline_params); + if (pipeline_params == NULL) + return; + + pipeline_data = &app->pipeline_data[pipeline_params - app->pipeline_params]; + p = pipeline_data->fe; + + TAILQ_FOREACH(flow, &p->flows, node) { + print_fc_flow(flow); + } +} + +struct cmd_fc_add_qinq_result { + cmdline_fixed_string_t p_string; + uint32_t pipeline_id; + cmdline_fixed_string_t flow_string; + cmdline_fixed_string_t add_string; + cmdline_fixed_string_t qinq_string; + uint16_t svlan; + uint16_t cvlan; + uint8_t port; +}; + +static void +cmd_fc_add_qinq_parsed( + void *parsed_result, + __rte_unused struct cmdline *cl, + void *data) +{ + struct cmd_fc_add_qinq_result *params = parsed_result; + struct app_params *app = data; + struct pipeline_fc_key key; + int status; + + memset(&key, 0, sizeof(key)); + key.type = FLOW_KEY_QINQ; + key.key.qinq.svlan = params->svlan; + key.key.qinq.cvlan = params->cvlan; + status = app_pipeline_fc_add(app, params->pipeline_id, &key, params->port); + + if(status != 0) + printf("Command failed\n"); +} + +cmdline_parse_token_string_t cmd_fc_add_qinq_p_string = + TOKEN_STRING_INITIALIZER(struct cmd_fc_add_qinq_result, p_string, "p"); + +cmdline_parse_token_num_t cmd_fc_add_qinq_pipeline_id = + TOKEN_NUM_INITIALIZER(struct cmd_fc_add_qinq_result, pipeline_id, UINT32); + +cmdline_parse_token_string_t cmd_fc_add_qinq_flow_string = + TOKEN_STRING_INITIALIZER(struct cmd_fc_add_qinq_result, flow_string, "flow"); + +cmdline_parse_token_string_t cmd_fc_add_qinq_add_string = + TOKEN_STRING_INITIALIZER(struct cmd_fc_add_qinq_result, add_string, "add"); + +cmdline_parse_token_string_t cmd_fc_add_qinq_qinq_string = + TOKEN_STRING_INITIALIZER(struct cmd_fc_add_qinq_result, add_string, "qinq"); + +cmdline_parse_token_num_t cmd_fc_add_qinq_svlan = + TOKEN_NUM_INITIALIZER(struct cmd_fc_add_qinq_result, svlan, UINT16); + +cmdline_parse_token_num_t cmd_fc_add_qinq_cvlan = + TOKEN_NUM_INITIALIZER(struct cmd_fc_add_qinq_result, cvlan, UINT16); + +cmdline_parse_token_num_t cmd_fc_add_qinq_port = + TOKEN_NUM_INITIALIZER(struct cmd_fc_add_qinq_result, port, UINT8); + +cmdline_parse_inst_t cmd_fc_add_qinq = { + .f = cmd_fc_add_qinq_parsed, + .data = NULL, + .help_str = "p flow add qinq ", + .tokens = { + (void *) &cmd_fc_add_qinq_p_string, + (void *) &cmd_fc_add_qinq_pipeline_id, + (void *) &cmd_fc_add_qinq_flow_string, + (void *) &cmd_fc_add_qinq_add_string, + (void *) &cmd_fc_add_qinq_qinq_string, + (void *) &cmd_fc_add_qinq_svlan, + (void *) &cmd_fc_add_qinq_cvlan, + (void *) &cmd_fc_add_qinq_port, + NULL, + }, +}; + +/* + * flow add ipv4_5tuple + */ + +struct cmd_fc_add_ipv4_5tuple_result { + cmdline_fixed_string_t p_string; + uint32_t pipeline_id; + cmdline_fixed_string_t flow_string; + cmdline_fixed_string_t add_string; + cmdline_fixed_string_t ipv4_5tuple_string; + cmdline_ipaddr_t ip_src; + cmdline_ipaddr_t ip_dst; + uint16_t port_src; + uint16_t port_dst; + uint32_t proto; + uint8_t port; +}; + +static void +cmd_fc_add_ipv4_5tuple_parsed( + void *parsed_result, + __rte_unused struct cmdline *cl, + void *data) +{ + struct cmd_fc_add_ipv4_5tuple_result *params = parsed_result; + struct app_params *app = data; + struct pipeline_fc_key key; + int status; + + memset(&key, 0, sizeof(key)); + key.type = FLOW_KEY_IPV4_5TUPLE; + key.key.ipv4_5tuple.ip_src = params->ip_src.addr.ipv4.s_addr; + key.key.ipv4_5tuple.ip_dst = params->ip_dst.addr.ipv4.s_addr; + key.key.ipv4_5tuple.port_src = params->port_src; + key.key.ipv4_5tuple.port_dst = params->port_dst; + key.key.ipv4_5tuple.proto = params->proto; + status = app_pipeline_fc_add(app, params->pipeline_id, &key, params->port); + + if(status != 0) + printf("Command failed\n"); +} + +cmdline_parse_token_string_t cmd_fc_add_ipv4_5tuple_p_string = + TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_result, p_string, "p"); + +cmdline_parse_token_num_t cmd_fc_add_ipv4_5tuple_pipeline_id = + TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_result, pipeline_id, UINT32); + +cmdline_parse_token_string_t cmd_fc_add_ipv4_5tuple_flow_string = + TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_result, flow_string, "flow"); + +cmdline_parse_token_string_t cmd_fc_add_ipv4_5tuple_add_string = + TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_result, add_string, "add"); + +cmdline_parse_token_string_t cmd_fc_add_ipv4_5tuple_ipv4_5tuple_string = + TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_result, ipv4_5tuple_string, "ipv4_5tuple"); + +cmdline_parse_token_ipaddr_t cmd_fc_add_ipv4_5tuple_ip_src = + TOKEN_IPADDR_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_result, ip_src); + +cmdline_parse_token_ipaddr_t cmd_fc_add_ipv4_5tuple_ip_dst = + TOKEN_IPADDR_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_result, ip_dst); + +cmdline_parse_token_num_t cmd_fc_add_ipv4_5tuple_port_src = + TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_result, port_src, UINT16); + +cmdline_parse_token_num_t cmd_fc_add_ipv4_5tuple_port_dst = + TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_result, port_dst, UINT16); + +cmdline_parse_token_num_t cmd_fc_add_ipv4_5tuple_proto = + TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_result, proto, UINT32); + +cmdline_parse_token_num_t cmd_fc_add_ipv4_5tuple_port = + TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv4_5tuple_result, port, UINT8); + +cmdline_parse_inst_t cmd_fc_add_ipv4_5tuple = { + .f = cmd_fc_add_ipv4_5tuple_parsed, + .data = NULL, + .help_str = "p flow add ipv4_5tuple ", + .tokens = { + (void *) &cmd_fc_add_ipv4_5tuple_p_string, + (void *) &cmd_fc_add_ipv4_5tuple_pipeline_id, + (void *) &cmd_fc_add_ipv4_5tuple_flow_string, + (void *) &cmd_fc_add_ipv4_5tuple_add_string, + (void *) &cmd_fc_add_ipv4_5tuple_ipv4_5tuple_string, + (void *) &cmd_fc_add_ipv4_5tuple_ip_src, + (void *) &cmd_fc_add_ipv4_5tuple_ip_dst, + (void *) &cmd_fc_add_ipv4_5tuple_port_src, + (void *) &cmd_fc_add_ipv4_5tuple_port_dst, + (void *) &cmd_fc_add_ipv4_5tuple_proto, + (void *) &cmd_fc_add_ipv4_5tuple_port, + NULL, + }, +}; + +/* + * flow add ipv6_5tuple + */ + +struct cmd_fc_add_ipv6_5tuple_result { + cmdline_fixed_string_t p_string; + uint32_t pipeline_id; + cmdline_fixed_string_t flow_string; + cmdline_fixed_string_t add_string; + cmdline_fixed_string_t ipv6_5tuple_string; + cmdline_ipaddr_t ip_src; + cmdline_ipaddr_t ip_dst; + uint16_t port_src; + uint16_t port_dst; + uint32_t proto; + uint8_t port; +}; + +static void +cmd_fc_add_ipv6_5tuple_parsed( + void *parsed_result, + __rte_unused struct cmdline *cl, + void *data) +{ + struct cmd_fc_add_ipv6_5tuple_result *params = parsed_result; + struct app_params *app = data; + struct pipeline_fc_key key; + int status; + + memset(&key, 0, sizeof(key)); + key.type = FLOW_KEY_IPV6_5TUPLE; + memcpy(key.key.ipv6_5tuple.ip_src, params->ip_src.addr.ipv6.s6_addr, 16); + memcpy(key.key.ipv6_5tuple.ip_dst, params->ip_dst.addr.ipv6.s6_addr, 16); + key.key.ipv6_5tuple.port_src = params->port_src; + key.key.ipv6_5tuple.port_dst = params->port_dst; + key.key.ipv6_5tuple.proto = params->proto; + status = app_pipeline_fc_add(app, params->pipeline_id, &key, params->port); + + if(status != 0) + printf("Command failed\n"); +} + +cmdline_parse_token_string_t cmd_fc_add_ipv6_5tuple_p_string = + TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_result, p_string, "p"); + +cmdline_parse_token_num_t cmd_fc_add_ipv6_5tuple_pipeline_id = + TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_result, pipeline_id, UINT32); + +cmdline_parse_token_string_t cmd_fc_add_ipv6_5tuple_flow_string = + TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_result, flow_string, "flow"); + +cmdline_parse_token_string_t cmd_fc_add_ipv6_5tuple_add_string = + TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_result, add_string, "add"); + +cmdline_parse_token_string_t cmd_fc_add_ipv6_5tuple_ipv6_5tuple_string = + TOKEN_STRING_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_result, ipv6_5tuple_string, "ipv6_5tuple"); + +cmdline_parse_token_ipaddr_t cmd_fc_add_ipv6_5tuple_ip_src = + TOKEN_IPADDR_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_result, ip_src); - /* Send response */ - do { - result = rte_ring_sp_enqueue(ring_resp, msg); - } while (result == -ENOBUFS); +cmdline_parse_token_ipaddr_t cmd_fc_add_ipv6_5tuple_ip_dst = + TOKEN_IPADDR_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_result, ip_dst); + +cmdline_parse_token_num_t cmd_fc_add_ipv6_5tuple_port_src = + TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_result, port_src, UINT16); + +cmdline_parse_token_num_t cmd_fc_add_ipv6_5tuple_port_dst = + TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_result, port_dst, UINT16); + +cmdline_parse_token_num_t cmd_fc_add_ipv6_5tuple_proto = + TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_result, proto, UINT32); + +cmdline_parse_token_num_t cmd_fc_add_ipv6_5tuple_port = + TOKEN_NUM_INITIALIZER(struct cmd_fc_add_ipv6_5tuple_result, port, UINT8); + +cmdline_parse_inst_t cmd_fc_add_ipv6_5tuple = { + .f = cmd_fc_add_ipv6_5tuple_parsed, + .data = NULL, + .help_str = "p flow add ipv6_5tuple ", + .tokens = { + (void *) &cmd_fc_add_ipv6_5tuple_p_string, + (void *) &cmd_fc_add_ipv6_5tuple_pipeline_id, + (void *) &cmd_fc_add_ipv6_5tuple_flow_string, + (void *) &cmd_fc_add_ipv6_5tuple_add_string, + (void *) &cmd_fc_add_ipv6_5tuple_ipv6_5tuple_string, + (void *) &cmd_fc_add_ipv6_5tuple_ip_src, + (void *) &cmd_fc_add_ipv6_5tuple_ip_dst, + (void *) &cmd_fc_add_ipv6_5tuple_port_src, + (void *) &cmd_fc_add_ipv6_5tuple_port_dst, + (void *) &cmd_fc_add_ipv6_5tuple_proto, + (void *) &cmd_fc_add_ipv6_5tuple_port, + NULL, + }, +}; + +/* + * flow del qinq + */ +struct cmd_fc_del_qinq_result { + cmdline_fixed_string_t p_string; + uint32_t pipeline_id; + cmdline_fixed_string_t flow_string; + cmdline_fixed_string_t del_string; + cmdline_fixed_string_t qinq_string; + uint16_t svlan; + uint16_t cvlan; +}; + +static void +cmd_fc_del_qinq_parsed( + void *parsed_result, + __rte_unused struct cmdline *cl, + void *data) +{ + struct cmd_fc_del_qinq_result *params = parsed_result; + struct app_params *app = data; + struct pipeline_fc_key key; + int status; + + memset(&key, 0, sizeof(key)); + key.type = FLOW_KEY_QINQ; + key.key.qinq.svlan = params->svlan; + key.key.qinq.cvlan = params->cvlan; + status = app_pipeline_fc_del(app, params->pipeline_id, &key); + + if(status != 0) + printf("Command failed\n"); +} + +cmdline_parse_token_string_t cmd_fc_del_qinq_p_string = + TOKEN_STRING_INITIALIZER(struct cmd_fc_del_qinq_result, p_string, "p"); + +cmdline_parse_token_num_t cmd_fc_del_qinq_pipeline_id = + TOKEN_NUM_INITIALIZER(struct cmd_fc_del_qinq_result, pipeline_id, UINT32); + +cmdline_parse_token_string_t cmd_fc_del_qinq_flow_string = + TOKEN_STRING_INITIALIZER(struct cmd_fc_del_qinq_result, flow_string, "flow"); + +cmdline_parse_token_string_t cmd_fc_del_qinq_del_string = + TOKEN_STRING_INITIALIZER(struct cmd_fc_del_qinq_result, del_string, "del"); + +cmdline_parse_token_string_t cmd_fc_del_qinq_qinq_string = + TOKEN_STRING_INITIALIZER(struct cmd_fc_del_qinq_result, qinq_string, "qinq"); + +cmdline_parse_token_num_t cmd_fc_del_qinq_svlan = + TOKEN_NUM_INITIALIZER(struct cmd_fc_del_qinq_result, svlan, UINT16); + +cmdline_parse_token_num_t cmd_fc_del_qinq_cvlan = + TOKEN_NUM_INITIALIZER(struct cmd_fc_del_qinq_result, cvlan, UINT16); + +cmdline_parse_inst_t cmd_fc_del_qinq = { + .f = cmd_fc_del_qinq_parsed, + .data = NULL, + .help_str = "p flow del qinq ", + .tokens = { + (void *) &cmd_fc_del_qinq_p_string, + (void *) &cmd_fc_del_qinq_pipeline_id, + (void *) &cmd_fc_del_qinq_flow_string, + (void *) &cmd_fc_del_qinq_del_string, + (void *) &cmd_fc_del_qinq_qinq_string, + (void *) &cmd_fc_del_qinq_svlan, + (void *) &cmd_fc_del_qinq_cvlan, + NULL, + }, +}; + +/* + * flow del ipv4_5tuple + */ + +struct cmd_fc_del_ipv4_5tuple_result { + cmdline_fixed_string_t p_string; + uint32_t pipeline_id; + cmdline_fixed_string_t flow_string; + cmdline_fixed_string_t del_string; + cmdline_fixed_string_t ipv4_5tuple_string; + cmdline_ipaddr_t ip_src; + cmdline_ipaddr_t ip_dst; + uint16_t port_src; + uint16_t port_dst; + uint32_t proto; + uint8_t port; +}; + +static void +cmd_fc_del_ipv4_5tuple_parsed( + void *parsed_result, + __rte_unused struct cmdline *cl, + void *data) +{ + struct cmd_fc_del_ipv4_5tuple_result *params = parsed_result; + struct app_params *app = data; + struct pipeline_fc_key key; + int status; + + memset(&key, 0, sizeof(key)); + key.type = FLOW_KEY_IPV4_5TUPLE; + key.key.ipv4_5tuple.ip_src = params->ip_src.addr.ipv4.s_addr; + key.key.ipv4_5tuple.ip_dst = params->ip_dst.addr.ipv4.s_addr; + key.key.ipv4_5tuple.port_src = params->port_src; + key.key.ipv4_5tuple.port_dst = params->port_dst; + key.key.ipv4_5tuple.proto = params->proto; + status = app_pipeline_fc_del(app, params->pipeline_id, &key); + + if(status != 0) + printf("Command failed\n"); +} + +cmdline_parse_token_string_t cmd_fc_del_ipv4_5tuple_p_string = + TOKEN_STRING_INITIALIZER(struct cmd_fc_del_ipv4_5tuple_result, p_string, "p"); + +cmdline_parse_token_num_t cmd_fc_del_ipv4_5tuple_pipeline_id = + TOKEN_NUM_INITIALIZER(struct cmd_fc_del_ipv4_5tuple_result, pipeline_id, UINT32); + +cmdline_parse_token_string_t cmd_fc_del_ipv4_5tuple_flow_string = + TOKEN_STRING_INITIALIZER(struct cmd_fc_del_ipv4_5tuple_result, flow_string, "flow"); + +cmdline_parse_token_string_t cmd_fc_del_ipv4_5tuple_del_string = + TOKEN_STRING_INITIALIZER(struct cmd_fc_del_ipv4_5tuple_result, del_string, "del"); + +cmdline_parse_token_string_t cmd_fc_del_ipv4_5tuple_ipv4_5tuple_string = + TOKEN_STRING_INITIALIZER(struct cmd_fc_del_ipv4_5tuple_result, ipv4_5tuple_string, "ipv4_5tuple"); + +cmdline_parse_token_ipaddr_t cmd_fc_del_ipv4_5tuple_ip_src = + TOKEN_IPADDR_INITIALIZER(struct cmd_fc_del_ipv4_5tuple_result, ip_src); + +cmdline_parse_token_ipaddr_t cmd_fc_del_ipv4_5tuple_ip_dst = + TOKEN_IPADDR_INITIALIZER(struct cmd_fc_del_ipv4_5tuple_result, ip_dst); + +cmdline_parse_token_num_t cmd_fc_del_ipv4_5tuple_port_src = + TOKEN_NUM_INITIALIZER(struct cmd_fc_del_ipv4_5tuple_result, port_src, UINT16); + +cmdline_parse_token_num_t cmd_fc_del_ipv4_5tuple_port_dst = + TOKEN_NUM_INITIALIZER(struct cmd_fc_del_ipv4_5tuple_result, port_dst, UINT16); + +cmdline_parse_token_num_t cmd_fc_del_ipv4_5tuple_proto = + TOKEN_NUM_INITIALIZER(struct cmd_fc_del_ipv4_5tuple_result, proto, UINT32); + +cmdline_parse_inst_t cmd_fc_del_ipv4_5tuple = { + .f = cmd_fc_del_ipv4_5tuple_parsed, + .data = NULL, + .help_str = "p flow del ipv4_5tuple ", + .tokens = { + (void *) &cmd_fc_add_ipv4_5tuple_p_string, + (void *) &cmd_fc_add_ipv4_5tuple_pipeline_id, + (void *) &cmd_fc_add_ipv4_5tuple_flow_string, + (void *) &cmd_fc_add_ipv4_5tuple_add_string, + (void *) &cmd_fc_add_ipv4_5tuple_ipv4_5tuple_string, + (void *) &cmd_fc_add_ipv4_5tuple_ip_src, + (void *) &cmd_fc_add_ipv4_5tuple_ip_dst, + (void *) &cmd_fc_add_ipv4_5tuple_port_src, + (void *) &cmd_fc_add_ipv4_5tuple_port_dst, + (void *) &cmd_fc_add_ipv4_5tuple_proto, + NULL, + }, +}; + +/* + * flow del ipv6_5tuple + */ + +struct cmd_fc_del_ipv6_5tuple_result { + cmdline_fixed_string_t p_string; + uint32_t pipeline_id; + cmdline_fixed_string_t flow_string; + cmdline_fixed_string_t del_string; + cmdline_fixed_string_t ipv6_5tuple_string; + cmdline_ipaddr_t ip_src; + cmdline_ipaddr_t ip_dst; + uint16_t port_src; + uint16_t port_dst; + uint32_t proto; + uint8_t port; +}; + +static void +cmd_fc_del_ipv6_5tuple_parsed( + void *parsed_result, + __rte_unused struct cmdline *cl, + void *data) +{ + struct cmd_fc_del_ipv6_5tuple_result *params = parsed_result; + struct app_params *app = data; + struct pipeline_fc_key key; + int status; + + memset(&key, 0, sizeof(key)); + key.type = FLOW_KEY_IPV6_5TUPLE; + memcpy(key.key.ipv6_5tuple.ip_src, params->ip_src.addr.ipv6.s6_addr, 16); + memcpy(key.key.ipv6_5tuple.ip_dst, params->ip_dst.addr.ipv6.s6_addr, 16); + key.key.ipv6_5tuple.port_src = params->port_src; + key.key.ipv6_5tuple.port_dst = params->port_dst; + key.key.ipv6_5tuple.proto = params->proto; + status = app_pipeline_fc_del(app, params->pipeline_id, &key); + + if(status != 0) + printf("Command failed\n"); +} + +cmdline_parse_token_string_t cmd_fc_del_ipv6_5tuple_p_string = + TOKEN_STRING_INITIALIZER(struct cmd_fc_del_ipv6_5tuple_result, p_string, "p"); + +cmdline_parse_token_num_t cmd_fc_del_ipv6_5tuple_pipeline_id = + TOKEN_NUM_INITIALIZER(struct cmd_fc_del_ipv6_5tuple_result, pipeline_id, UINT32); + +cmdline_parse_token_string_t cmd_fc_del_ipv6_5tuple_flow_string = + TOKEN_STRING_INITIALIZER(struct cmd_fc_del_ipv6_5tuple_result, flow_string, "flow"); + +cmdline_parse_token_string_t cmd_fc_del_ipv6_5tuple_add_string = + TOKEN_STRING_INITIALIZER(struct cmd_fc_del_ipv6_5tuple_result, del_string, "del"); + +cmdline_parse_token_string_t cmd_fc_del_ipv6_5tuple_ipv6_5tuple_string = + TOKEN_STRING_INITIALIZER(struct cmd_fc_del_ipv6_5tuple_result, ipv6_5tuple_string, "ipv6_5tuple"); + +cmdline_parse_token_ipaddr_t cmd_fc_del_ipv6_5tuple_ip_src = + TOKEN_IPADDR_INITIALIZER(struct cmd_fc_del_ipv6_5tuple_result, ip_src); + +cmdline_parse_token_ipaddr_t cmd_fc_del_ipv6_5tuple_ip_dst = + TOKEN_IPADDR_INITIALIZER(struct cmd_fc_del_ipv6_5tuple_result, ip_dst); + +cmdline_parse_token_num_t cmd_fc_del_ipv6_5tuple_port_src = + TOKEN_NUM_INITIALIZER(struct cmd_fc_del_ipv6_5tuple_result, port_src, UINT16); + +cmdline_parse_token_num_t cmd_fc_del_ipv6_5tuple_port_dst = + TOKEN_NUM_INITIALIZER(struct cmd_fc_del_ipv6_5tuple_result, port_dst, UINT16); + +cmdline_parse_token_num_t cmd_fc_del_ipv6_5tuple_proto = + TOKEN_NUM_INITIALIZER(struct cmd_fc_del_ipv6_5tuple_result, proto, UINT32); + +cmdline_parse_token_num_t cmd_fc_del_ipv6_5tuple_port = + TOKEN_NUM_INITIALIZER(struct cmd_fc_del_ipv6_5tuple_result, port, UINT8); + +cmdline_parse_inst_t cmd_fc_del_ipv6_5tuple = { + .f = cmd_fc_del_ipv6_5tuple_parsed, + .data = NULL, + .help_str = "p flow del ipv6_5tuple ", + .tokens = { + (void *) &cmd_fc_del_ipv6_5tuple_p_string, + (void *) &cmd_fc_del_ipv6_5tuple_pipeline_id, + (void *) &cmd_fc_del_ipv6_5tuple_flow_string, + (void *) &cmd_fc_del_ipv6_5tuple_add_string, + (void *) &cmd_fc_del_ipv6_5tuple_ipv6_5tuple_string, + (void *) &cmd_fc_del_ipv6_5tuple_ip_src, + (void *) &cmd_fc_del_ipv6_5tuple_ip_dst, + (void *) &cmd_fc_del_ipv6_5tuple_port_src, + (void *) &cmd_fc_del_ipv6_5tuple_port_dst, + (void *) &cmd_fc_del_ipv6_5tuple_proto, + NULL, + }, +}; + +/* + * flow add default qinq + */ + +struct cmd_fc_add_default_qinq_result { + cmdline_fixed_string_t p_string; + uint32_t pipeline_id; + cmdline_fixed_string_t flow_string; + cmdline_fixed_string_t add_string; + cmdline_fixed_string_t default_string; + cmdline_fixed_string_t qinq_string; + uint8_t port; +}; + +static void +cmd_fc_add_default_qinq_parsed( + void *parsed_result, + __rte_unused struct cmdline *cl, + void *data) +{ + struct cmd_fc_add_default_qinq_result *params = parsed_result; + struct app_params *app = data; + enum flow_key_type type; + int status; + + type = FLOW_KEY_QINQ; + status = app_pipeline_fc_add_default(app, params->pipeline_id, type, + params->port); + + if(status != 0) + printf("Command failed\n"); +} + +cmdline_parse_token_string_t cmd_fc_add_default_qinq_p_string = + TOKEN_STRING_INITIALIZER(struct cmd_fc_add_default_qinq_result, p_string, "p"); + +cmdline_parse_token_num_t cmd_fc_add_default_qinq_pipeline_id = + TOKEN_NUM_INITIALIZER(struct cmd_fc_add_default_qinq_result, pipeline_id, UINT32); + +cmdline_parse_token_string_t cmd_fc_add_default_qinq_flow_string = + TOKEN_STRING_INITIALIZER(struct cmd_fc_add_default_qinq_result, flow_string, "flow"); + +cmdline_parse_token_string_t cmd_fc_add_default_qinq_add_string = + TOKEN_STRING_INITIALIZER(struct cmd_fc_add_default_qinq_result, add_string, "add"); + +cmdline_parse_token_string_t cmd_fc_add_default_qinq_default_string = + TOKEN_STRING_INITIALIZER(struct cmd_fc_add_default_qinq_result, default_string, "default"); + +cmdline_parse_token_string_t cmd_fc_add_default_qinq_qinq_string = + TOKEN_STRING_INITIALIZER(struct cmd_fc_add_default_qinq_result, qinq_string, "qinq"); + +cmdline_parse_token_num_t cmd_fc_add_default_qinq_port = + TOKEN_NUM_INITIALIZER(struct cmd_fc_add_default_qinq_result, port, UINT8); + +cmdline_parse_inst_t cmd_fc_add_default_qinq = { + .f = cmd_fc_add_default_qinq_parsed, + .data = NULL, + .help_str = "p flow add default qinq ", + .tokens = { + (void *) &cmd_fc_add_default_qinq_p_string, + (void *) &cmd_fc_add_default_qinq_pipeline_id, + (void *) &cmd_fc_add_default_qinq_flow_string, + (void *) &cmd_fc_add_default_qinq_add_string, + (void *) &cmd_fc_add_default_qinq_default_string, + (void *) &cmd_fc_add_default_qinq_qinq_string, + (void *) &cmd_fc_add_default_qinq_port, + NULL, + }, +}; + +/* + * flow add default ipv4_5tuple + */ + +struct cmd_fc_add_default_ipv4_5tuple_result { + cmdline_fixed_string_t p_string; + uint32_t pipeline_id; + cmdline_fixed_string_t flow_string; + cmdline_fixed_string_t add_string; + cmdline_fixed_string_t default_string; + cmdline_fixed_string_t ipv4_5tuple_string; + uint8_t port; +}; + +static void +cmd_fc_add_default_ipv4_5tuple_parsed( + void *parsed_result, + __rte_unused struct cmdline *cl, + void *data) +{ + struct cmd_fc_add_default_ipv4_5tuple_result *params = parsed_result; + struct app_params *app = data; + enum flow_key_type type; + int status; + + type = FLOW_KEY_IPV4_5TUPLE; + status = app_pipeline_fc_add_default(app, params->pipeline_id, type, + params->port); + + if(status != 0) + printf("Command failed\n"); +} + +cmdline_parse_token_string_t cmd_fc_add_default_ipv4_5tuple_p_string = + TOKEN_STRING_INITIALIZER(struct cmd_fc_add_default_ipv4_5tuple_result, p_string, "p"); + +cmdline_parse_token_num_t cmd_fc_add_default_ipv4_5tuple_pipeline_id = + TOKEN_NUM_INITIALIZER(struct cmd_fc_add_default_ipv4_5tuple_result, pipeline_id, UINT32); + +cmdline_parse_token_string_t cmd_fc_add_default_ipv4_5tuple_flow_string = + TOKEN_STRING_INITIALIZER(struct cmd_fc_add_default_ipv4_5tuple_result, flow_string, "flow"); + +cmdline_parse_token_string_t cmd_fc_add_default_ipv4_5tuple_add_string = + TOKEN_STRING_INITIALIZER(struct cmd_fc_add_default_ipv4_5tuple_result, add_string, "add"); + +cmdline_parse_token_string_t cmd_fc_add_default_ipv4_5tuple_default_string = + TOKEN_STRING_INITIALIZER(struct cmd_fc_add_default_ipv4_5tuple_result, default_string, "default"); + +cmdline_parse_token_string_t cmd_fc_add_default_ipv4_5tuple_ipv4_5tuple_string = + TOKEN_STRING_INITIALIZER(struct cmd_fc_add_default_ipv4_5tuple_result, ipv4_5tuple_string, "ipv4_5tuple"); + +cmdline_parse_token_num_t cmd_fc_add_default_ipv4_5tuple_port = + TOKEN_NUM_INITIALIZER(struct cmd_fc_add_default_ipv4_5tuple_result, port, UINT8); + +cmdline_parse_inst_t cmd_fc_add_default_ipv4_5tuple = { + .f = cmd_fc_add_default_ipv4_5tuple_parsed, + .data = NULL, + .help_str = "p flow add default ipv4_5tuple ", + .tokens = { + (void *) &cmd_fc_add_default_ipv4_5tuple_p_string, + (void *) &cmd_fc_add_default_ipv4_5tuple_pipeline_id, + (void *) &cmd_fc_add_default_ipv4_5tuple_flow_string, + (void *) &cmd_fc_add_default_ipv4_5tuple_add_string, + (void *) &cmd_fc_add_default_ipv4_5tuple_default_string, + (void *) &cmd_fc_add_default_ipv4_5tuple_ipv4_5tuple_string, + (void *) &cmd_fc_add_default_ipv4_5tuple_port, + NULL, + }, +}; + +/* + * flow add default ipv6_5tuple + */ + +struct cmd_fc_add_default_ipv6_5tuple_result { + cmdline_fixed_string_t p_string; + uint32_t pipeline_id; + cmdline_fixed_string_t flow_string; + cmdline_fixed_string_t add_string; + cmdline_fixed_string_t default_string; + cmdline_fixed_string_t ipv6_5tuple_string; + uint8_t port; +}; + +static void +cmd_fc_add_default_ipv6_5tuple_parsed( + void *parsed_result, + __rte_unused struct cmdline *cl, + void *data) +{ + struct cmd_fc_add_default_ipv6_5tuple_result *params = parsed_result; + struct app_params *app = data; + enum flow_key_type type; + int status; + + type = FLOW_KEY_IPV6_5TUPLE; + status = app_pipeline_fc_add_default(app, params->pipeline_id, type, + params->port); + + if(status != 0) + printf("Command failed\n"); +} + +cmdline_parse_token_string_t cmd_fc_add_default_ipv6_5tuple_p_string = + TOKEN_STRING_INITIALIZER(struct cmd_fc_add_default_ipv6_5tuple_result, p_string, "p"); + +cmdline_parse_token_num_t cmd_fc_add_default_ipv6_5tuple_pipeline_id = + TOKEN_NUM_INITIALIZER(struct cmd_fc_add_default_ipv6_5tuple_result, pipeline_id, UINT32); + +cmdline_parse_token_string_t cmd_fc_add_default_ipv6_5tuple_flow_string = + TOKEN_STRING_INITIALIZER(struct cmd_fc_add_default_ipv6_5tuple_result, flow_string, "flow"); + +cmdline_parse_token_string_t cmd_fc_add_default_ipv6_5tuple_add_string = + TOKEN_STRING_INITIALIZER(struct cmd_fc_add_default_ipv6_5tuple_result, add_string, "add"); + +cmdline_parse_token_string_t cmd_fc_add_default_ipv6_5tuple_default_string = + TOKEN_STRING_INITIALIZER(struct cmd_fc_add_default_ipv6_5tuple_result, default_string, "default"); + +cmdline_parse_token_string_t cmd_fc_add_default_ipv6_5tuple_ipv6_5tuple_string = + TOKEN_STRING_INITIALIZER(struct cmd_fc_add_default_ipv6_5tuple_result, ipv6_5tuple_string, "ipv6_5tuple"); + +cmdline_parse_token_num_t cmd_fc_add_default_ipv6_5tuple_port = + TOKEN_NUM_INITIALIZER(struct cmd_fc_add_default_ipv6_5tuple_result, port, UINT8); + +cmdline_parse_inst_t cmd_fc_add_default_ipv6_5tuple = { + .f = cmd_fc_add_default_ipv6_5tuple_parsed, + .data = NULL, + .help_str = "p flow add default ipv6_5tuple ", + .tokens = { + (void *) &cmd_fc_add_default_ipv6_5tuple_p_string, + (void *) &cmd_fc_add_default_ipv6_5tuple_pipeline_id, + (void *) &cmd_fc_add_default_ipv6_5tuple_flow_string, + (void *) &cmd_fc_add_default_ipv6_5tuple_add_string, + (void *) &cmd_fc_add_default_ipv6_5tuple_default_string, + (void *) &cmd_fc_add_default_ipv6_5tuple_ipv6_5tuple_string, + (void *) &cmd_fc_add_default_ipv6_5tuple_port, + NULL, + }, +}; + +/* + * flow del default qinq + */ + +struct cmd_fc_del_default_qinq_result { + cmdline_fixed_string_t p_string; + uint32_t pipeline_id; + cmdline_fixed_string_t flow_string; + cmdline_fixed_string_t del_string; + cmdline_fixed_string_t default_string; + cmdline_fixed_string_t qinq_string; +}; + +static void +cmd_fc_del_default_qinq_parsed( + void *parsed_result, + __rte_unused struct cmdline *cl, + void *data) +{ + struct cmd_fc_del_default_qinq_result *params = parsed_result; + struct app_params *app = data; + enum flow_key_type type; + int status; + + type = FLOW_KEY_QINQ; + status = app_pipeline_fc_del_default(app, params->pipeline_id, type); + + if(status != 0) + printf("Command failed\n"); +} + +cmdline_parse_token_string_t cmd_fc_del_default_qinq_p_string = + TOKEN_STRING_INITIALIZER(struct cmd_fc_del_default_qinq_result, p_string, "p"); + +cmdline_parse_token_num_t cmd_fc_del_default_qinq_pipeline_id = + TOKEN_NUM_INITIALIZER(struct cmd_fc_del_default_qinq_result, pipeline_id, UINT32); + +cmdline_parse_token_string_t cmd_fc_del_default_qinq_flow_string = + TOKEN_STRING_INITIALIZER(struct cmd_fc_del_default_qinq_result, flow_string, "flow"); + +cmdline_parse_token_string_t cmd_fc_del_default_qinq_del_string = + TOKEN_STRING_INITIALIZER(struct cmd_fc_del_default_qinq_result, del_string, "del"); + +cmdline_parse_token_string_t cmd_fc_del_default_qinq_default_string = + TOKEN_STRING_INITIALIZER(struct cmd_fc_del_default_qinq_result, default_string, "default"); + +cmdline_parse_token_string_t cmd_fc_del_default_qinq_qinq_string = + TOKEN_STRING_INITIALIZER(struct cmd_fc_del_default_qinq_result, qinq_string, "qinq"); + +cmdline_parse_inst_t cmd_fc_del_default_qinq = { + .f = cmd_fc_del_default_qinq_parsed, + .data = NULL, + .help_str = "p flow del default qinq", + .tokens = { + (void *) &cmd_fc_del_default_qinq_p_string, + (void *) &cmd_fc_del_default_qinq_pipeline_id, + (void *) &cmd_fc_del_default_qinq_flow_string, + (void *) &cmd_fc_del_default_qinq_del_string, + (void *) &cmd_fc_del_default_qinq_default_string, + (void *) &cmd_fc_del_default_qinq_qinq_string, + NULL, + }, +}; + +/* + * flow del default ipv4_5tuple + */ + +struct cmd_fc_del_default_ipv4_5tuple_result { + cmdline_fixed_string_t p_string; + uint32_t pipeline_id; + cmdline_fixed_string_t flow_string; + cmdline_fixed_string_t del_string; + cmdline_fixed_string_t default_string; + cmdline_fixed_string_t ipv4_5tuple_string; +}; + +static void +cmd_fc_del_default_ipv4_5tuple_parsed( + void *parsed_result, + __rte_unused struct cmdline *cl, + void *data) +{ + struct cmd_fc_del_default_ipv4_5tuple_result *params = parsed_result; + struct app_params *app = data; + enum flow_key_type type; + int status; + + type = FLOW_KEY_IPV4_5TUPLE; + status = app_pipeline_fc_del_default(app, params->pipeline_id, type); + + if(status != 0) + printf("Command failed\n"); +} + +cmdline_parse_token_string_t cmd_fc_del_default_ipv4_5tuple_p_string = + TOKEN_STRING_INITIALIZER(struct cmd_fc_del_default_ipv4_5tuple_result, p_string, "p"); + +cmdline_parse_token_num_t cmd_fc_del_default_ipv4_5tuple_pipeline_id = + TOKEN_NUM_INITIALIZER(struct cmd_fc_del_default_ipv4_5tuple_result, pipeline_id, UINT32); + +cmdline_parse_token_string_t cmd_fc_del_default_ipv4_5tuple_flow_string = + TOKEN_STRING_INITIALIZER(struct cmd_fc_del_default_ipv4_5tuple_result, flow_string, "flow"); + +cmdline_parse_token_string_t cmd_fc_del_default_ipv4_5tuple_del_string = + TOKEN_STRING_INITIALIZER(struct cmd_fc_del_default_ipv4_5tuple_result, del_string, "del"); + +cmdline_parse_token_string_t cmd_fc_del_default_ipv4_5tuple_default_string = + TOKEN_STRING_INITIALIZER(struct cmd_fc_del_default_ipv4_5tuple_result, default_string, "default"); + +cmdline_parse_token_string_t cmd_fc_del_default_ipv4_5tuple_ipv4_5tuple_string = + TOKEN_STRING_INITIALIZER(struct cmd_fc_del_default_ipv4_5tuple_result, ipv4_5tuple_string, "ipv4_5tuple"); + +cmdline_parse_inst_t cmd_fc_del_default_ipv4_5tuple = { + .f = cmd_fc_del_default_ipv4_5tuple_parsed, + .data = NULL, + .help_str = "p flow del default ipv4_5tuple", + .tokens = { + (void *) &cmd_fc_del_default_ipv4_5tuple_p_string, + (void *) &cmd_fc_del_default_ipv4_5tuple_pipeline_id, + (void *) &cmd_fc_del_default_ipv4_5tuple_flow_string, + (void *) &cmd_fc_del_default_ipv4_5tuple_del_string, + (void *) &cmd_fc_del_default_ipv4_5tuple_default_string, + (void *) &cmd_fc_del_default_ipv4_5tuple_ipv4_5tuple_string, + NULL, + }, +}; + +/* + * flow del default ipv6_5tuple + */ + +struct cmd_fc_del_default_ipv6_5tuple_result { + cmdline_fixed_string_t p_string; + uint32_t pipeline_id; + cmdline_fixed_string_t flow_string; + cmdline_fixed_string_t del_string; + cmdline_fixed_string_t default_string; + cmdline_fixed_string_t ipv6_5tuple_string; +}; + +static void +cmd_fc_del_default_ipv6_5tuple_parsed( + void *parsed_result, + __rte_unused struct cmdline *cl, + void *data) +{ + struct cmd_fc_del_default_ipv6_5tuple_result *params = parsed_result; + struct app_params *app = data; + enum flow_key_type type; + int status; + + type = FLOW_KEY_IPV6_5TUPLE; + status = app_pipeline_fc_del_default(app, params->pipeline_id, type); + + if(status != 0) + printf("Command failed\n"); +} + +cmdline_parse_token_string_t cmd_fc_del_default_ipv6_5tuple_p_string = + TOKEN_STRING_INITIALIZER(struct cmd_fc_del_default_ipv6_5tuple_result, p_string, "p"); + +cmdline_parse_token_num_t cmd_fc_del_default_ipv6_5tuple_pipeline_id = + TOKEN_NUM_INITIALIZER(struct cmd_fc_del_default_ipv6_5tuple_result, pipeline_id, UINT32); + +cmdline_parse_token_string_t cmd_fc_del_default_ipv6_5tuple_flow_string = + TOKEN_STRING_INITIALIZER(struct cmd_fc_del_default_ipv6_5tuple_result, flow_string, "flow"); + +cmdline_parse_token_string_t cmd_fc_del_default_ipv6_5tuple_del_string = + TOKEN_STRING_INITIALIZER(struct cmd_fc_del_default_ipv6_5tuple_result, del_string, "del"); + +cmdline_parse_token_string_t cmd_fc_del_default_ipv6_5tuple_default_string = + TOKEN_STRING_INITIALIZER(struct cmd_fc_del_default_ipv6_5tuple_result, default_string, "default"); + +cmdline_parse_token_string_t cmd_fc_del_default_ipv6_5tuple_ipv6_5tuple_string = + TOKEN_STRING_INITIALIZER(struct cmd_fc_del_default_ipv6_5tuple_result, ipv6_5tuple_string, "ipv6_5tuple"); + +cmdline_parse_inst_t cmd_fc_del_default_ipv6_5tuple = { + .f = cmd_fc_del_default_ipv6_5tuple_parsed, + .data = NULL, + .help_str = "p flow del default ipv6_5tuple", + .tokens = { + (void *) &cmd_fc_del_default_ipv6_5tuple_p_string, + (void *) &cmd_fc_del_default_ipv6_5tuple_pipeline_id, + (void *) &cmd_fc_del_default_ipv6_5tuple_flow_string, + (void *) &cmd_fc_del_default_ipv6_5tuple_del_string, + (void *) &cmd_fc_del_default_ipv6_5tuple_default_string, + (void *) &cmd_fc_del_default_ipv6_5tuple_ipv6_5tuple_string, + NULL, + }, +}; + +/* + * flow ls + */ + +struct cmd_fc_ls_result { + cmdline_fixed_string_t p_string; + uint32_t pipeline_id; + cmdline_fixed_string_t flow_string; + cmdline_fixed_string_t ls_string; +}; + +static void +cmd_fc_ls_parsed( + void *parsed_result, + __attribute__((unused)) struct cmdline *cl, + void *data) +{ + struct cmd_fc_ls_result *params = parsed_result; + struct app_params *app = data; + + app_pipeline_fc_ls(app, params->pipeline_id); } + +cmdline_parse_token_string_t cmd_fc_ls_p_string = + TOKEN_STRING_INITIALIZER(struct cmd_fc_ls_result, p_string, "p"); + +cmdline_parse_token_num_t cmd_fc_ls_pipeline_id = + TOKEN_NUM_INITIALIZER(struct cmd_fc_ls_result, pipeline_id, UINT32); + +cmdline_parse_token_string_t cmd_fc_ls_flow_string = + TOKEN_STRING_INITIALIZER(struct cmd_fc_ls_result, + flow_string, "flow"); + +cmdline_parse_token_string_t cmd_fc_ls_ls_string = + TOKEN_STRING_INITIALIZER(struct cmd_fc_ls_result, ls_string, + "ls"); + +cmdline_parse_inst_t cmd_fc_ls = { + .f = cmd_fc_ls_parsed, + .data = NULL, + .help_str = "p flow ls", + .tokens = { + (void *) &cmd_fc_ls_p_string, + (void *) &cmd_fc_ls_pipeline_id, + (void *) &cmd_fc_ls_flow_string, + (void *) &cmd_fc_ls_ls_string, + NULL, + }, +}; + +static cmdline_parse_ctx_t pipeline_cmds[] = { + (cmdline_parse_inst_t *) &cmd_fc_add_qinq, + (cmdline_parse_inst_t *) &cmd_fc_add_ipv4_5tuple, + (cmdline_parse_inst_t *) &cmd_fc_add_ipv6_5tuple, + (cmdline_parse_inst_t *) &cmd_fc_del_qinq, + (cmdline_parse_inst_t *) &cmd_fc_del_ipv4_5tuple, + (cmdline_parse_inst_t *) &cmd_fc_del_ipv6_5tuple, + (cmdline_parse_inst_t *) &cmd_fc_add_default_qinq, + (cmdline_parse_inst_t *) &cmd_fc_add_default_ipv4_5tuple, + (cmdline_parse_inst_t *) &cmd_fc_add_default_ipv6_5tuple, + (cmdline_parse_inst_t *) &cmd_fc_del_default_qinq, + (cmdline_parse_inst_t *) &cmd_fc_del_default_ipv4_5tuple, + (cmdline_parse_inst_t *) &cmd_fc_del_default_ipv6_5tuple, + (cmdline_parse_inst_t *) &cmd_fc_ls, + NULL, +}; + +static struct pipeline_fe_ops pipeline_flow_classification_fe_ops = { + .f_init = app_pipeline_fc_init, + .f_free = app_pipeline_fc_free, + .cmds = pipeline_cmds, +}; + +struct pipeline_type pipeline_flow_classification = { + .name = "FLOW_CLASSIF", + .ops = &pipeline_flow_classification_ops, + .fe_ops = &pipeline_flow_classification_fe_ops, +}; diff --git a/examples/ip_pipeline/pipeline/pipeline_flow_classification.h b/examples/ip_pipeline/pipeline/pipeline_flow_classification.h new file mode 100644 index 0000000..3f0b2aa --- /dev/null +++ b/examples/ip_pipeline/pipeline/pipeline_flow_classification.h @@ -0,0 +1,41 @@ +/*- + * 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. + */ + +#ifndef __INCLUDE_PIPELINE_FLOW_CLASSIFICATION_H__ +#define __INCLUDE_PIPELINE_FLOW_CLASSIFICATION_H__ + +#include "pipeline.h" + +extern struct pipeline_type pipeline_flow_classification; + +#endif diff --git a/examples/ip_pipeline/pipeline/pipeline_flow_classification_ops.c b/examples/ip_pipeline/pipeline/pipeline_flow_classification_ops.c new file mode 100644 index 0000000..213894e --- /dev/null +++ b/examples/ip_pipeline/pipeline/pipeline_flow_classification_ops.c @@ -0,0 +1,559 @@ +/*- + * 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. + */ + +#include + +#include +#include +#include +#include + +#include "pipeline_common_ops.h" +#include "pipeline_flow_classification_ops.h" + +enum flow_meter_type { + METER_TYPE_SRTCM, + METER_TYPE_TRTCM, +}; + +struct pipeline_flow_classification { + struct pipeline p; + pipeline_msg_req_handler custom_handlers[PIPELINE_FC_MSG_REQS]; + + uint32_t n_flows; + uint32_t key_offset; + uint32_t key_size; + uint32_t hash_offset; + uint32_t flow_id_offset; + uint32_t flow_stats; + uint32_t color_offset; + uint32_t input_color_offset; + enum flow_meter_type meter_type; +} __rte_cache_aligned; + +static void * +pipeline_fc_msg_req_custom_handler(struct pipeline *p, void *msg); + +static pipeline_msg_req_handler handlers[] = { + [PIPELINE_MSG_REQ_PING] = pipeline_msg_req_ping_handler, + [PIPELINE_MSG_REQ_STATS_PORT_IN] = pipeline_msg_req_stats_port_in_handler, + [PIPELINE_MSG_REQ_STATS_PORT_OUT] = pipeline_msg_req_stats_port_out_handler, + [PIPELINE_MSG_REQ_STATS_TABLE] = pipeline_msg_req_stats_table_handler, + [PIPELINE_MSG_REQ_PORT_IN_ENABLE] = pipeline_msg_req_port_in_enable_handler, + [PIPELINE_MSG_REQ_PORT_IN_DISABLE] = pipeline_msg_req_port_in_disable_handler, + [PIPELINE_MSG_REQ_CUSTOM] = pipeline_fc_msg_req_custom_handler, +}; + +static void * +pipeline_fc_msg_req_add_handler(struct pipeline *p, void *msg); + +static void * +pipeline_fc_msg_req_del_handler(struct pipeline *p, void *msg); + +static void * +pipeline_fc_msg_req_add_default_handler(struct pipeline *p, void *msg); + +static void * +pipeline_fc_msg_req_del_default_handler(struct pipeline *p, void *msg); + +static void * +pipeline_fc_msg_req_add_all_handler(struct pipeline *p, void *msg); + +static void * +pipeline_fc_msg_req_meter_handler(struct pipeline *p, void *msg); + +static void * +pipeline_fc_msg_req_ls_handler(struct pipeline *p, void *msg); + +static pipeline_msg_req_handler custom_handlers[] = { + [PIPELINE_FC_MSG_REQ_FLOW_ADD] = pipeline_fc_msg_req_add_handler, + [PIPELINE_FC_MSG_REQ_FLOW_DEL] = pipeline_fc_msg_req_del_handler, + [PIPELINE_FC_MSG_REQ_FLOW_ADD_DEFAULT] = pipeline_fc_msg_req_add_default_handler, + [PIPELINE_FC_MSG_REQ_FLOW_DEL_DEFAULT] = pipeline_fc_msg_req_del_default_handler, + [PIPELINE_FC_MSG_REQ_FLOW_ADD_ALL] = pipeline_fc_msg_req_add_all_handler, + [PIPELINE_FC_MSG_REQ_FLOW_METER] = pipeline_fc_msg_req_meter_handler, + [PIPELINE_FC_MSG_REQ_FLOW_LS] = pipeline_fc_msg_req_ls_handler, +}; + +static uint64_t +test_hash( + void *key, + __attribute__((unused)) uint32_t key_size, + __attribute__((unused)) uint64_t seed) +{ + uint32_t *k32 = (uint32_t *) key; + uint32_t ip_dst = rte_be_to_cpu_32(k32[0]); + uint64_t signature = (ip_dst >> 2) | ((ip_dst & 0x3) << 30); + + return signature; +} + +static int +pipeline_fc_parse_args(struct pipeline_flow_classification *p, + struct pipeline_params *params) +{ + uint32_t n_flows_present = 0; + uint32_t key_offset_present = 0; + uint32_t key_size_present = 0; + uint32_t hash_offset_present = 0; + uint32_t flow_id_offset_present = 0; + uint32_t flow_stats_present = 0; + uint32_t color_offset_present = 0; + uint32_t input_color_offset_present = 0; + uint32_t meter_type_present = 0; + + uint32_t i; + + for (i = 0; i < params->n_args; i++) { + char *arg_name = params->args_name[i]; + char *arg_value = params->args_value[i]; + + if (strcmp(arg_name, "n_flows") == 0) { + if (n_flows_present) + return -1; + n_flows_present = 1; + + p->n_flows = atoi(arg_value); + } else if (strcmp(arg_name, "key_offset") == 0) { + if (key_offset_present) + return -1; + key_offset_present = 1; + + p->key_offset = atoi(arg_value); + } else if (strcmp(arg_name, "key_size") == 0) { + if (key_size_present) + return -1; + key_size_present = 1; + + p->key_size = atoi(arg_value); + } else if (strcmp(arg_name, "hash_offset") == 0) { + if (hash_offset_present) + return -1; + hash_offset_present = 1; + + p->hash_offset = atoi(arg_value); + } else if (strcmp(arg_name, "flow_id_offset") == 0) { + if (flow_id_offset_present) + return -1; + flow_id_offset_present = 1; + + p->flow_id_offset = atoi(arg_value); + } else if (strcmp(arg_name, "flow_stats") == 0) { + if (flow_stats_present) + return -1; + flow_stats_present = 1; + + if (strcmp(arg_value, "off") == 0) + p->flow_stats = 0; + else if (strcmp(arg_value, "on") == 0) + p->flow_stats = 1; + else + return -1; + } else if (strcmp(arg_name, "color_offset") == 0) { + if (color_offset_present) + return -1; + color_offset_present = 1; + + p->color_offset = atoi(arg_value); + } else if (strcmp(arg_name, "input_color_offset") == 0) { + if (input_color_offset_present) + return -1; + input_color_offset_present = 1; + + p->input_color_offset = atoi(arg_value); + } else if (strcmp(arg_name, "meter_type") == 0) { + if (meter_type_present) + return -1; + meter_type_present = 1; + + if (strcmp(arg_value, "srtcm") == 0) + p->meter_type = METER_TYPE_SRTCM; + else if (strcmp(arg_value, "trtcm") == 0) + p->meter_type = METER_TYPE_TRTCM; + else + return -1; + } else { + /* Unknown command */ + return -1; + } + } + + return 0; +} + +static void * pipeline_init(struct pipeline_params *params, + __rte_unused void *arg) +{ + struct pipeline *p; + struct pipeline_flow_classification *p_fc; + uint32_t size, i; + + /* Check input arguments */ + if (params == NULL) + return NULL; + + /* Memory allocation */ + size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct pipeline_flow_classification)); + p_fc = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE); + if (p_fc == NULL) + return NULL; + p = &p_fc->p; + + strcpy(p->name, params->name); + + /* Parse arguments */ + if (pipeline_fc_parse_args(p_fc, params)) + return NULL; + + /* Pipeline */ + { + struct rte_pipeline_params pipeline_params = { + .name = "FLOW_CLASSIF", + .socket_id = params->socket_id, + .offset_port_id = 0, + }; + + p->p = rte_pipeline_create(&pipeline_params); + if (p->p == NULL) { + rte_free(p); + return NULL; + } + } + + /* Input ports */ + p->n_ports_in = params->n_ports_in; + for (i = 0; i < p->n_ports_in; i++) { + struct rte_pipeline_port_in_params port_params = { + .ops = pipeline_port_in_params_get_ops(¶ms->port_in[i]), + .arg_create = pipeline_port_in_params_convert(¶ms->port_in[i]), + .f_action = NULL, + .arg_ah = NULL, + .burst_size = params->port_in[i].burst_size, + }; + + int status = rte_pipeline_port_in_create(p->p, + &port_params, + &p->port_in_id[i]); + + if (status) { + rte_pipeline_free(p->p); + rte_free(p); + return NULL; + } + } + + /* Output ports */ + p->n_ports_out = params->n_ports_out; + for (i = 0; i < p->n_ports_out; i++) { + struct rte_pipeline_port_out_params port_params = { + .ops = pipeline_port_out_params_get_ops(¶ms->port_out[i]), + .arg_create = pipeline_port_out_params_convert(¶ms->port_out[i]), + .f_action = NULL, + .f_action_bulk = NULL, + .arg_ah = NULL, + }; + + int status = rte_pipeline_port_out_create(p->p, + &port_params, + &p->port_out_id[i]); + + if (status) { + rte_pipeline_free(p->p); + rte_free(p); + return NULL; + } + } + + /* Tables */ + { + p->n_tables = 1; + struct rte_table_hash_key8_ext_params table_hash_params = { + .n_entries = p_fc->n_flows, + .n_entries_ext = 1, + .signature_offset = 0, + .key_offset = p_fc->key_offset, + .f_hash = &test_hash, + .seed = 0, + }; + + struct rte_pipeline_table_params table_params = { + .ops = &rte_table_hash_key8_ext_ops, + .arg_create = &table_hash_params, + .f_action_hit = NULL, + .f_action_miss = NULL, + .arg_ah = NULL, + .action_data_size = 0, + }; + + int status = rte_pipeline_table_create(p->p, + &table_params, + &p->table_id[0]); + + + if (status) { + rte_pipeline_free(p->p); + rte_free(p); + return NULL; + } + } + + /* Connecting input ports to tables */ + for (i = 0; i < p->n_ports_in; i++) { + int status = rte_pipeline_port_in_connect_to_table(p->p, + p->port_in_id[i], + p->table_id[0]); + + if (status) { + rte_pipeline_free(p->p); + rte_free(p); + return NULL; + } + } + + /* Enable input ports */ + for (i = 0; i < p->n_ports_in; i++) { + int status = rte_pipeline_port_in_enable(p->p, + p->port_in_id[i]); + + if (status) { + rte_pipeline_free(p->p); + rte_free(p); + return NULL; + } + } + + /* Check pipeline consistency */ + if (rte_pipeline_check(p->p) < 0) { + rte_pipeline_free(p->p); + rte_free(p); + return NULL; + } + + /* Message queues */ + p->n_msgq = params->n_msgq; + for (i = 0; i < p->n_msgq; i++) + p->msgq_in[i] = params->msgq_in[i]; + for (i = 0; i < p->n_msgq; i++) + p->msgq_out[i] = params->msgq_out[i]; + + /* Message handlers */ + memcpy(p->handlers, handlers, sizeof(p->handlers)); + memcpy(p_fc->custom_handlers, + custom_handlers, + sizeof(p_fc->custom_handlers)); + + return p; +} + +static int +pipeline_free(void *pipeline) +{ + struct pipeline *p = (struct pipeline *) pipeline; + + /* Check input arguments */ + if (p == NULL) + return -1; + + /* Free resources */ + rte_pipeline_free(p->p); + rte_free(p); + return 0; +} + +static int +pipeline_timer(void *pipeline) +{ + struct pipeline *p = (struct pipeline *) pipeline; + + pipeline_msg_req_handle(p); + rte_pipeline_flush(p->p); + + return 0; +} + +static void * +pipeline_fc_msg_req_custom_handler(struct pipeline *p, void *msg) +{ + struct pipeline_flow_classification *p_fc = + (struct pipeline_flow_classification *) p; + struct pipeline_custom_msg_req *req = msg; + pipeline_msg_req_handler f_handle; + + f_handle = (req->subtype < PIPELINE_FC_MSG_REQS)? + p_fc->custom_handlers[req->subtype] : + pipeline_msg_req_invalid_handler; + + if (f_handle == NULL) + f_handle = pipeline_msg_req_invalid_handler; + + return f_handle(p, req); +} + +static void * +pipeline_fc_msg_req_add_handler(struct pipeline *p, void *msg) +{ + struct pipeline_fc_add_msg_req *req = msg; + struct pipeline_fc_add_msg_rsp *rsp = msg; + + struct rte_pipeline_table_entry entry = { + .action = RTE_PIPELINE_ACTION_PORT, + {.port_id = p->port_out_id[req->port_id]}, + }; + + switch (req->key.type) { + case FLOW_KEY_QINQ: { + uint64_t svlan = req->key.key.qinq.svlan; + uint64_t cvlan = req->key.key.qinq.cvlan; + uint64_t key = rte_bswap64((svlan << 48) | (cvlan << 16)); + + rsp->status = rte_pipeline_table_entry_add(p->p, p->table_id[0], &key, + &entry, &rsp->key_found, + (struct rte_pipeline_table_entry **) &rsp->entry_ptr); + break; + } + case FLOW_KEY_IPV4_5TUPLE: { + rsp->status = rte_pipeline_table_entry_add(p->p, p->table_id[0], + req->key.key.raw, &entry, &rsp->key_found, + (struct rte_pipeline_table_entry **) &rsp->entry_ptr); + break; + } + case FLOW_KEY_IPV6_5TUPLE: { + rsp->status = rte_pipeline_table_entry_add(p->p, p->table_id[0], + req->key.key.raw, &entry, &rsp->key_found, + (struct rte_pipeline_table_entry **) &rsp->entry_ptr); + break; + } + } + + RTE_LOG(INFO, USER1, "%s Back-End: Key %s\n", + p->name, + (rsp->key_found)? "found" : "not found"); + + return rsp; +} + +static void * +pipeline_fc_msg_req_del_handler(struct pipeline *p, void *msg) +{ + struct pipeline_fc_del_msg_req *req = msg; + struct pipeline_fc_del_msg_rsp *rsp = msg; + + switch (req->key.type) { + case FLOW_KEY_QINQ: { + uint64_t svlan = req->key.key.qinq.svlan; + uint64_t cvlan = req->key.key.qinq.cvlan; + uint64_t key = rte_bswap64((svlan << 48) | (cvlan << 16)); + + rsp->status = rte_pipeline_table_entry_delete(p->p, p->table_id[0], + &key, &rsp->key_found, NULL); + break; + } + case FLOW_KEY_IPV4_5TUPLE: { + rsp->status = rte_pipeline_table_entry_delete(p->p, p->table_id[0], + req->key.key.raw, &rsp->key_found, NULL); + break; + } + case FLOW_KEY_IPV6_5TUPLE: { + rsp->status = rte_pipeline_table_entry_delete(p->p, p->table_id[0], + req->key.key.raw, &rsp->key_found, NULL); + break; + } + } + + RTE_LOG(INFO, USER1, "%s Back-End: Key %s\n", + p->name, + (rsp->key_found)? "found" : "not found"); + + return rsp; +} + +static void * +pipeline_fc_msg_req_add_default_handler(struct pipeline *p, void *msg) +{ + struct pipeline_fc_add_default_msg_req *req = msg; + struct pipeline_fc_add_default_msg_rsp *rsp = msg; + + struct rte_pipeline_table_entry default_entry = { + .action = RTE_PIPELINE_ACTION_PORT, + {.port_id = p->port_out_id[req->port_id]}, + }; + + rsp->status = rte_pipeline_table_default_entry_add(p->p, p->table_id[0], + &default_entry, + (struct rte_pipeline_table_entry **) &rsp->default_entry_ptr); + + return rsp; +} + +static void * +pipeline_fc_msg_req_del_default_handler(struct pipeline *p, void *msg) +{ + struct pipeline_fc_del_default_msg_rsp *rsp = msg; + + rsp->status = rte_pipeline_table_default_entry_delete(p->p, + p->table_id[0], NULL); + + return rsp; +} + +static void * +pipeline_fc_msg_req_add_all_handler(struct pipeline *p, void *msg) +{ + (void) p; + (void) msg; + return NULL; +} + +static void * +pipeline_fc_msg_req_meter_handler(struct pipeline *p, void *msg) +{ + (void) p; + (void) msg; + return NULL; +} + +static void * +pipeline_fc_msg_req_ls_handler(struct pipeline *p, void *msg) +{ + (void) p; + (void) msg; + return NULL; +} + +struct pipeline_ops pipeline_flow_classification_ops = { + .f_init = pipeline_init, + .f_free = pipeline_free, + .f_run = NULL, + .f_timer = pipeline_timer, + .f_track = NULL, +}; diff --git a/examples/ip_pipeline/pipeline/pipeline_flow_classification_ops.h b/examples/ip_pipeline/pipeline/pipeline_flow_classification_ops.h new file mode 100644 index 0000000..a3f9b00 --- /dev/null +++ b/examples/ip_pipeline/pipeline/pipeline_flow_classification_ops.h @@ -0,0 +1,150 @@ +/*- + * 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. + */ + +#ifndef __INCLUDE_PIPELINE_FLOW_CLASSIFICATION_OPS_H__ +#define __INCLUDE_PIPELINE_FLOW_CLASSIFICATION_OPS_H__ + +#include "pipeline.h" +#include "pipeline_common.h" + +enum pipeline_fc_msg_req_type { + PIPELINE_FC_MSG_REQ_FLOW_ADD = 0, + PIPELINE_FC_MSG_REQ_FLOW_DEL, + PIPELINE_FC_MSG_REQ_FLOW_ADD_DEFAULT, + PIPELINE_FC_MSG_REQ_FLOW_DEL_DEFAULT, + PIPELINE_FC_MSG_REQ_FLOW_ADD_ALL, + PIPELINE_FC_MSG_REQ_FLOW_METER, + PIPELINE_FC_MSG_REQ_FLOW_LS, + PIPELINE_FC_MSG_REQS, +}; + +enum flow_key_type { + FLOW_KEY_QINQ, + FLOW_KEY_IPV4_5TUPLE, + FLOW_KEY_IPV6_5TUPLE, +}; + +struct flow_key_qinq { + uint16_t svlan; + uint16_t cvlan; +}; + +struct flow_key_ipv4_5tuple { + uint32_t ip_src; + uint32_t ip_dst; + uint16_t port_src; + uint16_t port_dst; + uint32_t proto; +}; + +struct flow_key_ipv6_5tuple { + uint8_t ip_src[16]; + uint8_t ip_dst[16]; + uint16_t port_src; + uint16_t port_dst; + uint32_t proto; +}; + +struct pipeline_fc_key { + enum flow_key_type type; + union { + struct flow_key_qinq qinq; + struct flow_key_ipv4_5tuple ipv4_5tuple; + struct flow_key_ipv6_5tuple ipv6_5tuple; + uint8_t raw[40]; + } key; +}; + +/* + * MSG ADD + */ +struct pipeline_fc_add_msg_req { + enum pipeline_msg_req_type type; + enum pipeline_fc_msg_req_type subtype; + + struct pipeline_fc_key key; + + uint32_t port_id; +}; + +struct pipeline_fc_add_msg_rsp { + int status; + int key_found; + void *entry_ptr; +}; + +/* + * MSG DEL + */ +struct pipeline_fc_del_msg_req { + enum pipeline_msg_req_type type; + enum pipeline_fc_msg_req_type subtype; + + struct pipeline_fc_key key; +}; + +struct pipeline_fc_del_msg_rsp { + int status; + int key_found; +}; + +/* + * MSG ADD DEFAULT + */ +struct pipeline_fc_add_default_msg_req { + enum pipeline_msg_req_type type; + enum pipeline_fc_msg_req_type subtype; + + uint32_t port_id; +}; + +struct pipeline_fc_add_default_msg_rsp { + int status; + void *default_entry_ptr; +}; + +/* + * MSG DEL DEFAULT + */ +struct pipeline_fc_del_default_msg_req { + enum pipeline_msg_req_type type; + enum pipeline_fc_msg_req_type subtype; +}; + +struct pipeline_fc_del_default_msg_rsp { + int status; +}; + +extern struct pipeline_ops pipeline_flow_classification_ops; + +#endif