From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by dpdk.org (Postfix) with ESMTP id 0A86F5A87 for ; Fri, 29 May 2015 18:20:12 +0200 (CEST) Received: from orsmga002.jf.intel.com ([10.7.209.21]) by fmsmga103.fm.intel.com with ESMTP; 29 May 2015 09:20:11 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.13,517,1427785200"; d="scan'208";a="737445990" Received: from unknown (HELO stargo) ([10.217.248.233]) by orsmga002.jf.intel.com with SMTP; 29 May 2015 09:20:09 -0700 Received: by stargo (sSMTP sendmail emulation); Fri, 29 May 2015 18:14:21 +0200 From: Maciej Gajdzica To: dev@dpdk.org Date: Fri, 29 May 2015 17:43:16 +0200 Message-Id: <1432914198-11812-10-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 09/11] ip_pipeline: added new implementation of firewall 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: , X-List-Received-Date: Fri, 29 May 2015 16:20:15 -0000 Firewall pipeline implementation is split to two files. pipeline_firewall.c file handles front-end functions (cli commands parsing) pipeline_firewall_ops.c contains implementation of functions done by pipeline (back-end). Signed-off-by: Daniel Mrzyglod --- examples/ip_pipeline/Makefile | 6 +- examples/ip_pipeline/init.c | 2 + examples/ip_pipeline/pipeline/pipeline_firewall.c | 1099 +++++++++++++++----- examples/ip_pipeline/pipeline/pipeline_firewall.h | 63 ++ .../ip_pipeline/pipeline/pipeline_firewall_ops.c | 538 ++++++++++ .../ip_pipeline/pipeline/pipeline_firewall_ops.h | 139 +++ 6 files changed, 1604 insertions(+), 243 deletions(-) create mode 100644 examples/ip_pipeline/pipeline/pipeline_firewall.h create mode 100644 examples/ip_pipeline/pipeline/pipeline_firewall_ops.c create mode 100644 examples/ip_pipeline/pipeline/pipeline_firewall_ops.h diff --git a/examples/ip_pipeline/Makefile b/examples/ip_pipeline/Makefile index fc845ce..0f8b1cc 100644 --- a/examples/ip_pipeline/Makefile +++ b/examples/ip_pipeline/Makefile @@ -61,13 +61,11 @@ SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_master_ops.c SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_master.c SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_passthrough_ops.c SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_passthrough.c +SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_firewall_ops.c +SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_firewall.c #SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_flow_classification.c #SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_routing.c -#ifeq ($(CONFIG_RTE_LIBRTE_ACL),y) -#SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_firewall.c -#endif - CFLAGS += -I$(SRCDIR) -I$(SRCDIR)/pipeline CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) -Wno-error=unused-function -Wno-error=unused-variable diff --git a/examples/ip_pipeline/init.c b/examples/ip_pipeline/init.c index 22b2c77..29d87ae 100644 --- a/examples/ip_pipeline/init.c +++ b/examples/ip_pipeline/init.c @@ -45,6 +45,7 @@ #include "pipeline.h" #include "pipeline_master.h" #include "pipeline_passthrough.h" +#include "pipeline_firewall.h" #define APP_NAME_SIZE 32 @@ -1146,6 +1147,7 @@ int app_init(struct app_params *app) app_pipeline_type_register(app, &pipeline_master); app_pipeline_type_register(app, &pipeline_passthrough); + app_pipeline_type_register(app, &pipeline_firewall); app_init_pipelines(app); app_init_threads(app); diff --git a/examples/ip_pipeline/pipeline/pipeline_firewall.c b/examples/ip_pipeline/pipeline/pipeline_firewall.c index b70260e..21ae403 100644 --- a/examples/ip_pipeline/pipeline/pipeline_firewall.c +++ b/examples/ip_pipeline/pipeline/pipeline_firewall.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,282 +32,903 @@ */ #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_firewall_ops.h" +#include "pipeline_firewall.h" +#include "pipeline_common.h" + +#define MSG_TIMEOUT 1000 + +struct app_pipeline_firewall_rule { + struct pipeline_firewall_key key; + int32_t priority; + uint32_t port_id; + void *entry_ptr; + + TAILQ_ENTRY(app_pipeline_firewall_rule) node; +}; + +struct app_pipeline_firewall { + /* parameters */ + uint32_t n_ports_in; + uint32_t n_ports_out; + + /* rules */ + TAILQ_HEAD(, app_pipeline_firewall_rule) rules; + uint32_t n_rules; + uint32_t default_rule_present; + uint32_t default_rule_port_id; + void *default_rule_entry_ptr; +}; -#include -#include -#include +static void +print_firewall_ipv4_rule(struct app_pipeline_firewall_rule *rule) +{ + printf("Prio = %d (SA = %u.%u.%u.%u/%u, " + "DA = %u.%u.%u.%u/%u, " + "SP = %u-%u, " + "DP = %u-%u, " + "Proto = %u / 0x%x) => " + "Port = %u (entry ptr = %p)\n", + + rule->priority, + + (rule->key.key.ipv4_5tuple.src_ip >> 24) & 0xFF, + (rule->key.key.ipv4_5tuple.src_ip >> 16) & 0xFF, + (rule->key.key.ipv4_5tuple.src_ip >> 8) & 0xFF, + rule->key.key.ipv4_5tuple.src_ip & 0xFF, + rule->key.key.ipv4_5tuple.src_ip_mask, + + (rule->key.key.ipv4_5tuple.dst_ip >> 24) & 0xFF, + (rule->key.key.ipv4_5tuple.dst_ip >> 16) & 0xFF, + (rule->key.key.ipv4_5tuple.dst_ip >> 8) & 0xFF, + rule->key.key.ipv4_5tuple.dst_ip & 0xFF, + rule->key.key.ipv4_5tuple.dst_ip_mask, + + rule->key.key.ipv4_5tuple.src_port_from, + rule->key.key.ipv4_5tuple.src_port_to, + + rule->key.key.ipv4_5tuple.dst_port_from, + rule->key.key.ipv4_5tuple.dst_port_to, + + rule->key.key.ipv4_5tuple.proto, + rule->key.key.ipv4_5tuple.proto_mask, + + rule->port_id, + rule->entry_ptr); +} -#include "main.h" +static struct app_pipeline_firewall_rule * +app_pipeline_firewall_rule_find(struct app_pipeline_firewall *p, + struct pipeline_firewall_key *key) +{ + struct app_pipeline_firewall_rule *r; -struct app_core_firewall_message_handle_params { - struct rte_ring *ring_req; - struct rte_ring *ring_resp; + TAILQ_FOREACH(r, &p->rules, node) + if (memcmp(key, &r->key, sizeof(struct pipeline_firewall_key)) == 0) + return r; - struct rte_pipeline *p; - uint32_t *port_out_id; - uint32_t table_id; -}; + return NULL; +} static void -app_message_handle(struct app_core_firewall_message_handle_params *params); - -enum { - PROTO_FIELD_IPV4, - SRC_FIELD_IPV4, - DST_FIELD_IPV4, - SRCP_FIELD_IPV4, - DSTP_FIELD_IPV4, - NUM_FIELDS_IPV4 -}; +app_pipeline_firewall_ls( + struct app_params *app, + uint32_t pipeline_id) +{ + struct app_pipeline_params *pipeline_params; + struct app_pipeline_data *pipeline_data; + struct app_pipeline_firewall *p; + struct app_pipeline_firewall_rule *rule; + uint32_t n_rules; + int priority; + + /* Check input arguments */ + if (app == NULL) + return; -struct rte_acl_field_def ipv4_field_formats[NUM_FIELDS_IPV4] = { - { - .type = RTE_ACL_FIELD_TYPE_BITMASK, - .size = sizeof(uint8_t), - .field_index = PROTO_FIELD_IPV4, - .input_index = PROTO_FIELD_IPV4, - .offset = sizeof(struct ether_hdr) + - offsetof(struct ipv4_hdr, next_proto_id), - }, - { - .type = RTE_ACL_FIELD_TYPE_MASK, - .size = sizeof(uint32_t), - .field_index = SRC_FIELD_IPV4, - .input_index = SRC_FIELD_IPV4, - .offset = sizeof(struct ether_hdr) + - offsetof(struct ipv4_hdr, src_addr), - }, - { - .type = RTE_ACL_FIELD_TYPE_MASK, - .size = sizeof(uint32_t), - .field_index = DST_FIELD_IPV4, - .input_index = DST_FIELD_IPV4, - .offset = sizeof(struct ether_hdr) + - offsetof(struct ipv4_hdr, dst_addr), - }, - { - .type = RTE_ACL_FIELD_TYPE_RANGE, - .size = sizeof(uint16_t), - .field_index = SRCP_FIELD_IPV4, - .input_index = SRCP_FIELD_IPV4, - .offset = sizeof(struct ether_hdr) + sizeof(struct ipv4_hdr), - }, - { - .type = RTE_ACL_FIELD_TYPE_RANGE, - .size = sizeof(uint16_t), - .field_index = DSTP_FIELD_IPV4, - .input_index = SRCP_FIELD_IPV4, - .offset = sizeof(struct ether_hdr) + sizeof(struct ipv4_hdr) + - sizeof(uint16_t), - }, -}; + APP_PARAM_FIND_BY_ID(app->pipeline_params, "PIPELINE", pipeline_id, pipeline_params); + if (pipeline_params == NULL) + return; -void -app_main_loop_pipeline_firewall(void) { - struct rte_pipeline_params pipeline_params = { - .name = "pipeline", - .socket_id = rte_socket_id(), - }; + pipeline_data = &app->pipeline_data[pipeline_params - app->pipeline_params]; + p = pipeline_data->fe; + + n_rules = p->n_rules; + for (priority = 0; n_rules; priority++) + TAILQ_FOREACH(rule, &p->rules, node) + if (rule->priority == priority) { + print_firewall_ipv4_rule(rule); + n_rules --; + } + + if (p->default_rule_present) + printf("Default rule: port %u (entry ptr = %p)\n", + p->default_rule_port_id, + p->default_rule_entry_ptr); + else + printf("Default rule: DROP\n"); + + printf("\n"); +} - 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_firewall_init(struct pipeline_params *params, + __rte_unused void *arg) +{ + struct app_pipeline_firewall *p; + uint32_t size; + + /* Check input arguments */ + if ((params == NULL) || + (params->n_ports_in == 0) || + (params->n_ports_out == 0)) + return NULL; + + /* Memory allocation */ + size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct app_pipeline_firewall)); + 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_firewall_message_handle_params mh_params; + /* Initialization */ + p->n_ports_in = params->n_ports_in; + p->n_ports_out = params->n_ports_out; - if ((core_params == NULL) || (core_params->core_type != APP_CORE_FW)) - rte_panic("Core %u misconfiguration\n", core_id); + TAILQ_INIT(&p->rules); + p->n_rules = 0; + p->default_rule_present = 0; + p->default_rule_port_id = 0; + p->default_rule_entry_ptr = NULL; - RTE_LOG(INFO, USER1, "Core %u is doing firewall\n", core_id); + return (void *) p; +} - /* Pipeline configuration */ - p = rte_pipeline_create(&pipeline_params); +static int +app_pipeline_firewall_free(void *pipeline) +{ + struct app_pipeline_firewall *p = pipeline; + struct app_pipeline_firewall_rule *rule; + + /* 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 */ + while (!TAILQ_EMPTY(&p->rules)) { + rule = TAILQ_FIRST(&p->rules); + TAILQ_REMOVE(&p->rules, rule, node); + rte_free(rule); + } + + rte_free(p); + return 0; +} + +int +app_pipeline_firewall_add_rule(struct app_params *app, + uint32_t pipeline_id, + struct pipeline_firewall_key *key, + uint32_t priority, + uint32_t port_id) +{ + struct app_pipeline_params *params; + struct app_pipeline_data *data; + struct app_pipeline_firewall *p; + struct app_pipeline_firewall_rule *rule; + struct pipeline_firewall_add_msg_req *req; + struct pipeline_firewall_add_msg_rsp *rsp; + int new_rule; + + /* Check input arguments */ + if ((app == NULL) || + (key == NULL) || + (key->type != PIPELINE_FIREWALL_IPV4_5TUPLE)) + return -1; + + APP_PARAM_FIND_BY_ID(app->pipeline_params, "PIPELINE", pipeline_id, params); + if ((params == NULL) || + (port_id >= params->n_pktq_out)) + return -1; + + data = &app->pipeline_data[params - app->pipeline_params]; + p = data->fe; + + /* Find existing rule or allocate new rule */ + rule = app_pipeline_firewall_rule_find(p, key); + new_rule = (rule == NULL); + if (rule == NULL) { + rule = rte_malloc(NULL, sizeof(*rule), RTE_CACHE_LINE_SIZE); + + if (rule == NULL) + return -1; + } + + /* Allocate and write request */ + req = app_msg_alloc(app); + if (req == NULL) { + if (new_rule) + rte_free(rule); + return -1; } - /* 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); + req->type = PIPELINE_MSG_REQ_CUSTOM; + req->subtype = PIPELINE_FIREWALL_MSG_REQ_ADD; + memcpy(&req->key, key, sizeof(*key)); + req->priority = priority; + 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_rule) + rte_free(rule); + return -1; } - /* Table configuration */ - { - struct rte_table_acl_params table_acl_params = { - .name = "test", /* unique identifier for acl contexts */ - .n_rules = app.max_firewall_rules, - .n_rule_fields = DIM(ipv4_field_formats), - }; - - struct rte_pipeline_table_params table_params = { - .ops = &rte_table_acl_ops, - .arg_create = &table_acl_params, - .f_action_hit = NULL, - .f_action_miss = NULL, - .arg_ah = NULL, - .action_data_size = 0, - }; - - memcpy(table_acl_params.field_format, ipv4_field_formats, - sizeof(ipv4_field_formats)); - - if (rte_pipeline_table_create(p, &table_params, &table_id)) - rte_panic("Unable to configure the ACL table\n"); + /* Read response and write rule */ + if (rsp->status || (rsp->entry_ptr == NULL)){ + app_msg_free(app, rsp); + if (new_rule) + rte_free(rule); + 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_FW)); - mh_params.ring_resp = app_get_ring_resp( - app_get_first_core_id(APP_CORE_FW)); - 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); - } + memcpy(&rule->key, key, sizeof(*key)); + rule->priority = priority; + rule->port_id = port_id; + rule->entry_ptr = rsp->entry_ptr; + + /* Commit rule */ + if (new_rule) { + TAILQ_INSERT_TAIL(&p->rules, rule, node); + p->n_rules ++; } + + print_firewall_ipv4_rule(rule); + + /* Free response */ + app_msg_free(app, rsp); + + return 0; } -void -app_message_handle(struct app_core_firewall_message_handle_params *params) +int +app_pipeline_firewall_delete_rule(struct app_params *app, + uint32_t pipeline_id, + struct pipeline_firewall_key *key) { - struct rte_ring *ring_req = params->ring_req; - struct rte_ring *ring_resp; - struct rte_mbuf *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, (void **) &msg); - if (result != 0) - return; + struct app_pipeline_params *params; + struct app_pipeline_data *data; + struct app_pipeline_firewall *p; + struct app_pipeline_firewall_rule *rule; + struct pipeline_firewall_del_msg_req *req; + struct pipeline_firewall_del_msg_rsp *rsp; + + /* Check input arguments */ + if ((app == NULL) || + (key == NULL) || + (key->type != PIPELINE_FIREWALL_IPV4_5TUPLE)) + 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 */ + rule = app_pipeline_firewall_rule_find(p, key); + if (rule == 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_FIREWALL_MSG_REQ_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; + } + + /* Remove rule */ + TAILQ_REMOVE(&p->rules, rule, node); + p->n_rules --; + + /* Free response */ + app_msg_free(app, rsp); + + return 0; +} + +int +app_pipeline_firewall_add_default_rule(struct app_params *app, + uint32_t pipeline_id, + uint32_t port_id) +{ + struct app_pipeline_params *params; + struct app_pipeline_data *data; + struct app_pipeline_firewall *p; + struct pipeline_firewall_add_default_msg_req *req; + struct pipeline_firewall_add_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) || + (port_id >= params->n_pktq_out)) + return -1; + + data = &app->pipeline_data[params - app->pipeline_params]; + p = data->fe; + + /* Allocate and write request */ + req = app_msg_alloc(app); + if (req == NULL) + return -1; + + req->type = PIPELINE_MSG_REQ_CUSTOM; + req->subtype = PIPELINE_FIREWALL_MSG_REQ_ADD_DEFAULT; + 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) + return -1; + + /* Read response and write rule */ + if (rsp->status || (rsp->entry_ptr == NULL)){ + app_msg_free(app, rsp); + return -1; + } + + p->default_rule_port_id = port_id; + p->default_rule_entry_ptr = rsp->entry_ptr; + + /* Commit rule */ + p->default_rule_present = 1; + + /* Free response */ + app_msg_free(app, rsp); + + return 0; +} + +int +app_pipeline_firewall_delete_default_rule(struct app_params *app, + uint32_t pipeline_id) +{ + struct app_pipeline_params *params; + struct app_pipeline_data *data; + struct app_pipeline_firewall *p; + struct pipeline_firewall_del_default_msg_req *req; + struct pipeline_firewall_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; + + /* Allocate and write request */ + req = app_msg_alloc(app); + if (req == NULL) + return -1; + + req->type = PIPELINE_MSG_REQ_CUSTOM; + req->subtype = PIPELINE_FIREWALL_MSG_REQ_DEL_DEFAULT; + + /* Send request and wait for response */ + rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT); + if (rsp == NULL) + return -1; + + /* Read response and write rule */ + if (rsp->status) { + app_msg_free(app, rsp); + return -1; + } + + /* Commit rule */ + p->default_rule_present = 0; + + /* Free response */ + app_msg_free(app, rsp); - 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(msg); - switch (req->type) { - case APP_MSG_REQ_PING: - { - result = 0; - break; + return 0; +} + +/* + * p firewall add ipv4 + */ + +struct cmd_firewall_add_ipv4_result { + cmdline_fixed_string_t p_string; + uint32_t pipeline_id; + cmdline_fixed_string_t firewall_string; + cmdline_fixed_string_t add_string; + cmdline_fixed_string_t ipv4_string; + int32_t priority; + cmdline_ipaddr_t src_ip; + uint32_t src_ip_mask; + cmdline_ipaddr_t dst_ip; + uint32_t dst_ip_mask; + uint16_t src_port_from; + uint16_t src_port_to; + uint16_t dst_port_from; + uint16_t dst_port_to; + uint8_t proto; + uint8_t proto_mask; + uint8_t port_id; +}; + +static void +cmd_firewall_add_ipv4_parsed( + void *parsed_result, + __attribute__((unused)) struct cmdline *cl, + void *data) +{ + struct cmd_firewall_add_ipv4_result *params = parsed_result; + struct app_params *app = data; + struct pipeline_firewall_key key; + int status; + + key.type = PIPELINE_FIREWALL_IPV4_5TUPLE; + key.key.ipv4_5tuple.src_ip = rte_bswap32((uint32_t) params->src_ip.addr.ipv4.s_addr); + key.key.ipv4_5tuple.src_ip_mask = params->src_ip_mask; + key.key.ipv4_5tuple.dst_ip = rte_bswap32((uint32_t) params->dst_ip.addr.ipv4.s_addr); + key.key.ipv4_5tuple.dst_ip_mask = params->dst_ip_mask; + key.key.ipv4_5tuple.src_port_from = params->src_port_from; + key.key.ipv4_5tuple.src_port_to = params->src_port_to; + key.key.ipv4_5tuple.dst_port_from = params->dst_port_from; + key.key.ipv4_5tuple.dst_port_to = params->dst_port_to; + key.key.ipv4_5tuple.proto = params->proto; + key.key.ipv4_5tuple.proto_mask = params->proto_mask; + + status = app_pipeline_firewall_add_rule(app, + params->pipeline_id, + &key, + params->priority, + params->port_id); + + if(status != 0) { + printf("Command failed\n"); + return; } +} + +cmdline_parse_token_string_t cmd_firewall_add_ipv4_p_string = + TOKEN_STRING_INITIALIZER(struct cmd_firewall_add_ipv4_result, p_string, "p"); + +cmdline_parse_token_num_t cmd_firewall_add_ipv4_pipeline_id = + TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_ipv4_result, pipeline_id, UINT32); + +cmdline_parse_token_string_t cmd_firewall_add_ipv4_firewall_string = + TOKEN_STRING_INITIALIZER(struct cmd_firewall_add_ipv4_result, firewall_string, "firewall"); + +cmdline_parse_token_string_t cmd_firewall_add_ipv4_add_string = + TOKEN_STRING_INITIALIZER(struct cmd_firewall_add_ipv4_result, add_string, "add"); + +cmdline_parse_token_string_t cmd_firewall_add_ipv4_ipv4_string = + TOKEN_STRING_INITIALIZER(struct cmd_firewall_add_ipv4_result, ipv4_string, "ipv4"); + +cmdline_parse_token_num_t cmd_firewall_add_ipv4_priority = + TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_ipv4_result, priority, INT32); + +cmdline_parse_token_ipaddr_t cmd_firewall_add_ipv4_src_ip = + TOKEN_IPADDR_INITIALIZER(struct cmd_firewall_add_ipv4_result, src_ip); + +cmdline_parse_token_num_t cmd_firewall_add_ipv4_src_ip_mask = + TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_ipv4_result, src_ip_mask, UINT32); - case APP_MSG_REQ_FW_ADD: - { - struct rte_pipeline_table_entry entry = { - .action = RTE_PIPELINE_ACTION_PORT, - {.port_id = port_out_id[req->firewall_add.port]}, - }; +cmdline_parse_token_ipaddr_t cmd_firewall_add_ipv4_dst_ip = + TOKEN_IPADDR_INITIALIZER(struct cmd_firewall_add_ipv4_result, dst_ip); - struct rte_pipeline_table_entry *entry_ptr; +cmdline_parse_token_num_t cmd_firewall_add_ipv4_dst_ip_mask = + TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_ipv4_result, dst_ip_mask, UINT32); - int key_found; +cmdline_parse_token_num_t cmd_firewall_add_ipv4_src_port_from = + TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_ipv4_result, src_port_from, UINT16); - result = rte_pipeline_table_entry_add(p, table_id, - &req->firewall_add.add_params, &entry, &key_found, - &entry_ptr); - break; +cmdline_parse_token_num_t cmd_firewall_add_ipv4_src_port_to = + TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_ipv4_result, src_port_to, UINT16); + +cmdline_parse_token_num_t cmd_firewall_add_ipv4_dst_port_from = + TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_ipv4_result, dst_port_from, UINT16); + +cmdline_parse_token_num_t cmd_firewall_add_ipv4_dst_port_to = + TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_ipv4_result, dst_port_to, UINT16); + +cmdline_parse_token_num_t cmd_firewall_add_ipv4_proto = + TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_ipv4_result, proto, UINT8); + +cmdline_parse_token_num_t cmd_firewall_add_ipv4_proto_mask = + TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_ipv4_result, proto_mask, UINT8); + +cmdline_parse_token_num_t cmd_firewall_add_ipv4_port_id = + TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_ipv4_result, port_id, UINT8); + +cmdline_parse_inst_t cmd_firewall_add_ipv4 = { + .f = cmd_firewall_add_ipv4_parsed, + .data = NULL, + .help_str = "Firewall rule add", + .tokens = { + (void *) &cmd_firewall_add_ipv4_p_string, + (void *) &cmd_firewall_add_ipv4_pipeline_id, + (void *) &cmd_firewall_add_ipv4_firewall_string, + (void *) &cmd_firewall_add_ipv4_add_string, + (void *) &cmd_firewall_add_ipv4_ipv4_string, + (void *) &cmd_firewall_add_ipv4_priority, + (void *) &cmd_firewall_add_ipv4_src_ip, + (void *) &cmd_firewall_add_ipv4_src_ip_mask, + (void *) &cmd_firewall_add_ipv4_dst_ip, + (void *) &cmd_firewall_add_ipv4_dst_ip_mask, + (void *) &cmd_firewall_add_ipv4_src_port_from, + (void *) &cmd_firewall_add_ipv4_src_port_to, + (void *) &cmd_firewall_add_ipv4_dst_port_from, + (void *) &cmd_firewall_add_ipv4_dst_port_to, + (void *) &cmd_firewall_add_ipv4_proto, + (void *) &cmd_firewall_add_ipv4_proto_mask, + (void *) &cmd_firewall_add_ipv4_port_id, + NULL, + }, +}; + +/* + * p firewall del ipv4 + */ + +struct cmd_firewall_del_ipv4_result { + cmdline_fixed_string_t p_string; + uint32_t pipeline_id; + cmdline_fixed_string_t firewall_string; + cmdline_fixed_string_t del_string; + cmdline_fixed_string_t ipv4_string; + cmdline_ipaddr_t src_ip; + uint32_t src_ip_mask; + cmdline_ipaddr_t dst_ip; + uint32_t dst_ip_mask; + uint16_t src_port_from; + uint16_t src_port_to; + uint16_t dst_port_from; + uint16_t dst_port_to; + uint8_t proto; + uint8_t proto_mask; +}; + +static void +cmd_firewall_del_ipv4_parsed( + void *parsed_result, + __attribute__((unused)) struct cmdline *cl, + void *data) +{ + struct cmd_firewall_del_ipv4_result *params = parsed_result; + struct app_params *app = data; + struct pipeline_firewall_key key; + int status; + + key.type = PIPELINE_FIREWALL_IPV4_5TUPLE; + key.key.ipv4_5tuple.src_ip = rte_bswap32((uint32_t) params->src_ip.addr.ipv4.s_addr); + key.key.ipv4_5tuple.src_ip_mask = params->src_ip_mask; + key.key.ipv4_5tuple.dst_ip = rte_bswap32((uint32_t) params->dst_ip.addr.ipv4.s_addr); + key.key.ipv4_5tuple.dst_ip_mask = params->dst_ip_mask; + key.key.ipv4_5tuple.src_port_from = params->src_port_from; + key.key.ipv4_5tuple.src_port_to = params->src_port_to; + key.key.ipv4_5tuple.dst_port_from = params->dst_port_from; + key.key.ipv4_5tuple.dst_port_to = params->dst_port_to; + key.key.ipv4_5tuple.proto = params->proto; + key.key.ipv4_5tuple.proto_mask = params->proto_mask; + + status = app_pipeline_firewall_delete_rule(app, + params->pipeline_id, + &key); + + if(status != 0) { + printf("Command failed\n"); + return; } +} + +cmdline_parse_token_string_t cmd_firewall_del_ipv4_p_string = + TOKEN_STRING_INITIALIZER(struct cmd_firewall_del_ipv4_result, p_string, "p"); + +cmdline_parse_token_num_t cmd_firewall_del_ipv4_pipeline_id = + TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_ipv4_result, pipeline_id, UINT32); - case APP_MSG_REQ_FW_DEL: - { - int key_found; +cmdline_parse_token_string_t cmd_firewall_del_ipv4_firewall_string = + TOKEN_STRING_INITIALIZER(struct cmd_firewall_del_ipv4_result, firewall_string, "firewall"); + +cmdline_parse_token_string_t cmd_firewall_del_ipv4_del_string = + TOKEN_STRING_INITIALIZER(struct cmd_firewall_del_ipv4_result, del_string, "del"); + +cmdline_parse_token_string_t cmd_firewall_del_ipv4_ipv4_string = + TOKEN_STRING_INITIALIZER(struct cmd_firewall_del_ipv4_result, ipv4_string, "ipv4"); + +cmdline_parse_token_ipaddr_t cmd_firewall_del_ipv4_src_ip = + TOKEN_IPADDR_INITIALIZER(struct cmd_firewall_del_ipv4_result, src_ip); + +cmdline_parse_token_num_t cmd_firewall_del_ipv4_src_ip_mask = + TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_ipv4_result, src_ip_mask, UINT32); + +cmdline_parse_token_ipaddr_t cmd_firewall_del_ipv4_dst_ip = + TOKEN_IPADDR_INITIALIZER(struct cmd_firewall_del_ipv4_result, dst_ip); + +cmdline_parse_token_num_t cmd_firewall_del_ipv4_dst_ip_mask = + TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_ipv4_result, dst_ip_mask, UINT32); + +cmdline_parse_token_num_t cmd_firewall_del_ipv4_src_port_from = + TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_ipv4_result, src_port_from, UINT16); + +cmdline_parse_token_num_t cmd_firewall_del_ipv4_src_port_to = + TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_ipv4_result, src_port_to, UINT16); + +cmdline_parse_token_num_t cmd_firewall_del_ipv4_dst_port_from = + TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_ipv4_result, dst_port_from, UINT16); + +cmdline_parse_token_num_t cmd_firewall_del_ipv4_dst_port_to = + TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_ipv4_result, dst_port_to, UINT16); + +cmdline_parse_token_num_t cmd_firewall_del_ipv4_proto = + TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_ipv4_result, proto, UINT8); + +cmdline_parse_token_num_t cmd_firewall_del_ipv4_proto_mask = + TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_ipv4_result, proto_mask, UINT8); + +cmdline_parse_inst_t cmd_firewall_del_ipv4 = { + .f = cmd_firewall_del_ipv4_parsed, + .data = NULL, + .help_str = "Firewall rule delete", + .tokens = { + (void *) &cmd_firewall_del_ipv4_p_string, + (void *) &cmd_firewall_del_ipv4_pipeline_id, + (void *) &cmd_firewall_del_ipv4_firewall_string, + (void *) &cmd_firewall_del_ipv4_del_string, + (void *) &cmd_firewall_del_ipv4_ipv4_string, + (void *) &cmd_firewall_del_ipv4_src_ip, + (void *) &cmd_firewall_del_ipv4_src_ip_mask, + (void *) &cmd_firewall_del_ipv4_dst_ip, + (void *) &cmd_firewall_del_ipv4_dst_ip_mask, + (void *) &cmd_firewall_del_ipv4_src_port_from, + (void *) &cmd_firewall_del_ipv4_src_port_to, + (void *) &cmd_firewall_del_ipv4_dst_port_from, + (void *) &cmd_firewall_del_ipv4_dst_port_to, + (void *) &cmd_firewall_del_ipv4_proto, + (void *) &cmd_firewall_del_ipv4_proto_mask, + NULL, + }, +}; + +/* + * p firewall add default + */ +struct cmd_firewall_add_default_result { + cmdline_fixed_string_t p_string; + uint32_t pipeline_id; + cmdline_fixed_string_t firewall_string; + cmdline_fixed_string_t add_string; + cmdline_fixed_string_t default_string; + uint8_t port_id; +}; - result = rte_pipeline_table_entry_delete(p, table_id, - &req->firewall_del.delete_params, &key_found, NULL); - break; +static void +cmd_firewall_add_default_parsed( + void *parsed_result, + __attribute__((unused)) struct cmdline *cl, + void *data) +{ + struct cmd_firewall_add_default_result *params = parsed_result; + struct app_params *app = data; + int status; + + status = app_pipeline_firewall_add_default_rule(app, + params->pipeline_id, + params->port_id); + + if(status != 0) { + printf("Command failed\n"); + return; } +} + +cmdline_parse_token_string_t cmd_firewall_add_default_p_string = + TOKEN_STRING_INITIALIZER(struct cmd_firewall_add_default_result, p_string, "p"); + +cmdline_parse_token_num_t cmd_firewall_add_default_pipeline_id = + TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_default_result, pipeline_id, UINT32); + +cmdline_parse_token_string_t cmd_firewall_add_default_firewall_string = + TOKEN_STRING_INITIALIZER(struct cmd_firewall_add_default_result, + firewall_string, "firewall"); + +cmdline_parse_token_string_t cmd_firewall_add_default_add_string = + TOKEN_STRING_INITIALIZER(struct cmd_firewall_add_default_result, add_string, + "add"); + +cmdline_parse_token_string_t cmd_firewall_add_default_default_string = + TOKEN_STRING_INITIALIZER(struct cmd_firewall_add_default_result, default_string, + "default"); + +cmdline_parse_token_num_t cmd_firewall_add_default_port_id = + TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_default_result, port_id, UINT8); + +cmdline_parse_inst_t cmd_firewall_add_default = { + .f = cmd_firewall_add_default_parsed, + .data = NULL, + .help_str = "Firewall default rule add", + .tokens = { + (void *) &cmd_firewall_add_default_p_string, + (void *) &cmd_firewall_add_default_pipeline_id, + (void *) &cmd_firewall_add_default_firewall_string, + (void *) &cmd_firewall_add_default_add_string, + (void *) &cmd_firewall_add_default_default_string, + (void *) &cmd_firewall_add_default_port_id, + NULL, + }, +}; - default: - rte_panic("FW unrecognized message type (%u)\n", req->type); +/* + * p firewall del default + */ +struct cmd_firewall_del_default_result { + cmdline_fixed_string_t p_string; + uint32_t pipeline_id; + cmdline_fixed_string_t firewall_string; + cmdline_fixed_string_t del_string; + cmdline_fixed_string_t default_string; +}; + +static void +cmd_firewall_del_default_parsed( + void *parsed_result, + __attribute__((unused)) struct cmdline *cl, + void *data) +{ + struct cmd_firewall_del_default_result *params = parsed_result; + struct app_params *app = data; + int status; + + status = app_pipeline_firewall_delete_default_rule(app, + params->pipeline_id); + + if(status != 0) { + printf("Command failed\n"); + return; } +} - /* Fill in response message */ - resp = (struct app_msg_resp *)rte_ctrlmbuf_data(msg); - resp->result = result; +cmdline_parse_token_string_t cmd_firewall_del_default_p_string = + TOKEN_STRING_INITIALIZER(struct cmd_firewall_del_default_result, p_string, "p"); + +cmdline_parse_token_num_t cmd_firewall_del_default_pipeline_id = + TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_default_result, pipeline_id, UINT32); + +cmdline_parse_token_string_t cmd_firewall_del_default_firewall_string = + TOKEN_STRING_INITIALIZER(struct cmd_firewall_del_default_result, + firewall_string, "firewall"); + +cmdline_parse_token_string_t cmd_firewall_del_default_del_string = + TOKEN_STRING_INITIALIZER(struct cmd_firewall_del_default_result, del_string, + "del"); + +cmdline_parse_token_string_t cmd_firewall_del_default_default_string = + TOKEN_STRING_INITIALIZER(struct cmd_firewall_del_default_result, default_string, + "default"); + +cmdline_parse_inst_t cmd_firewall_del_default = { + .f = cmd_firewall_del_default_parsed, + .data = NULL, + .help_str = "Firewall default rule delete", + .tokens = { + (void *) &cmd_firewall_del_default_p_string, + (void *) &cmd_firewall_del_default_pipeline_id, + (void *) &cmd_firewall_del_default_firewall_string, + (void *) &cmd_firewall_del_default_del_string, + (void *) &cmd_firewall_del_default_default_string, + NULL, + }, +}; + +/* + * p firewall ls + */ + +struct cmd_firewall_ls_result { + cmdline_fixed_string_t p_string; + uint32_t pipeline_id; + cmdline_fixed_string_t firewall_string; + cmdline_fixed_string_t ls_string; +}; + +static void +cmd_firewall_ls_parsed( + void *parsed_result, + __attribute__((unused)) struct cmdline *cl, + void *data) +{ + struct cmd_firewall_ls_result *params = parsed_result; + struct app_params *app = data; - /* Send response */ - do { - result = rte_ring_sp_enqueue(ring_resp, (void *) msg); - } while (result == -ENOBUFS); + app_pipeline_firewall_ls(app, params->pipeline_id); } + +cmdline_parse_token_string_t cmd_firewall_ls_p_string = + TOKEN_STRING_INITIALIZER(struct cmd_firewall_ls_result, p_string, "p"); + +cmdline_parse_token_num_t cmd_firewall_ls_pipeline_id = + TOKEN_NUM_INITIALIZER(struct cmd_firewall_ls_result, pipeline_id, UINT32); + +cmdline_parse_token_string_t cmd_firewall_ls_firewall_string = + TOKEN_STRING_INITIALIZER(struct cmd_firewall_ls_result, + firewall_string, "firewall"); + +cmdline_parse_token_string_t cmd_firewall_ls_ls_string = + TOKEN_STRING_INITIALIZER(struct cmd_firewall_ls_result, ls_string, + "ls"); + +cmdline_parse_inst_t cmd_firewall_ls = { + .f = cmd_firewall_ls_parsed, + .data = NULL, + .help_str = "Firewall rule list", + .tokens = { + (void *) &cmd_firewall_ls_p_string, + (void *) &cmd_firewall_ls_pipeline_id, + (void *) &cmd_firewall_ls_firewall_string, + (void *) &cmd_firewall_ls_ls_string, + NULL, + }, +}; + +static cmdline_parse_ctx_t pipeline_cmds[] = { + (cmdline_parse_inst_t *) &cmd_firewall_add_ipv4, + (cmdline_parse_inst_t *) &cmd_firewall_del_ipv4, + (cmdline_parse_inst_t *) &cmd_firewall_add_default, + (cmdline_parse_inst_t *) &cmd_firewall_del_default, + (cmdline_parse_inst_t *) &cmd_firewall_ls, + NULL, +}; + +static struct pipeline_fe_ops pipeline_firewall_fe_ops = { + .f_init = app_pipeline_firewall_init, + .f_free = app_pipeline_firewall_free, + .cmds = pipeline_cmds, +}; + +struct pipeline_type pipeline_firewall = { + .name = "FIREWALL", + .ops = &pipeline_firewall_ops, + .fe_ops = &pipeline_firewall_fe_ops, +}; diff --git a/examples/ip_pipeline/pipeline/pipeline_firewall.h b/examples/ip_pipeline/pipeline/pipeline_firewall.h new file mode 100644 index 0000000..a938fa2 --- /dev/null +++ b/examples/ip_pipeline/pipeline/pipeline_firewall.h @@ -0,0 +1,63 @@ +/*- + * 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_FIREWALL_H__ +#define __INCLUDE_PIPELINE_FIREWALL_H__ + +#include "pipeline.h" +#include "pipeline_firewall_ops.h" + +int +app_pipeline_firewall_add_rule(struct app_params *app, + uint32_t pipeline_id, + struct pipeline_firewall_key *key, + uint32_t priority, + uint32_t port_id); + +int +app_pipeline_firewall_delete_rule(struct app_params *app, + uint32_t pipeline_id, + struct pipeline_firewall_key *key); + +int +app_pipeline_firewall_add_default_rule(struct app_params *app, + uint32_t pipeline_id, + uint32_t port_id); + +int +app_pipeline_firewall_delete_default_rule(struct app_params *app, + uint32_t pipeline_id); + +extern struct pipeline_type pipeline_firewall; + +#endif diff --git a/examples/ip_pipeline/pipeline/pipeline_firewall_ops.c b/examples/ip_pipeline/pipeline/pipeline_firewall_ops.c new file mode 100644 index 0000000..834330b --- /dev/null +++ b/examples/ip_pipeline/pipeline/pipeline_firewall_ops.c @@ -0,0 +1,538 @@ +/*- + * 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 +#include + +#include "pipeline_common_ops.h" +#include "pipeline_firewall_ops.h" + +struct pipeline_firewall { + struct pipeline p; + pipeline_msg_req_handler custom_handlers[PIPELINE_FIREWALL_MSG_REQS]; + + uint32_t n_rules; +} __rte_cache_aligned; + +static void * +pipeline_firewall_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_firewall_msg_req_custom_handler, +}; + +static void * +pipeline_firewall_msg_req_add_handler(struct pipeline *p, void *msg); + +static void * +pipeline_firewall_msg_req_del_handler(struct pipeline *p, void *msg); + +static void * +pipeline_firewall_msg_req_add_default_handler(struct pipeline *p, void *msg); + +static void * +pipeline_firewall_msg_req_del_default_handler(struct pipeline *p, void *msg); + +static pipeline_msg_req_handler custom_handlers[] = { + [PIPELINE_FIREWALL_MSG_REQ_ADD] = pipeline_firewall_msg_req_add_handler, + [PIPELINE_FIREWALL_MSG_REQ_DEL] = pipeline_firewall_msg_req_del_handler, + [PIPELINE_FIREWALL_MSG_REQ_ADD_DEFAULT] = pipeline_firewall_msg_req_add_default_handler, + [PIPELINE_FIREWALL_MSG_REQ_DEL_DEFAULT] = pipeline_firewall_msg_req_del_default_handler, +}; + +enum { + PROTO_FIELD_IPV4, + SRC_FIELD_IPV4, + DST_FIELD_IPV4, + SRCP_FIELD_IPV4, + DSTP_FIELD_IPV4, + NUM_FIELDS_IPV4 +}; + +struct rte_acl_field_def ipv4_field_formats[NUM_FIELDS_IPV4] = { + { + .type = RTE_ACL_FIELD_TYPE_BITMASK, + .size = sizeof(uint8_t), + .field_index = PROTO_FIELD_IPV4, + .input_index = PROTO_FIELD_IPV4, + .offset = sizeof(struct ether_hdr) + + offsetof(struct ipv4_hdr, next_proto_id), + }, + { + .type = RTE_ACL_FIELD_TYPE_MASK, + .size = sizeof(uint32_t), + .field_index = SRC_FIELD_IPV4, + .input_index = SRC_FIELD_IPV4, + .offset = sizeof(struct ether_hdr) + + offsetof(struct ipv4_hdr, src_addr), + }, + { + .type = RTE_ACL_FIELD_TYPE_MASK, + .size = sizeof(uint32_t), + .field_index = DST_FIELD_IPV4, + .input_index = DST_FIELD_IPV4, + .offset = sizeof(struct ether_hdr) + + offsetof(struct ipv4_hdr, dst_addr), + }, + { + .type = RTE_ACL_FIELD_TYPE_RANGE, + .size = sizeof(uint16_t), + .field_index = SRCP_FIELD_IPV4, + .input_index = SRCP_FIELD_IPV4, + .offset = sizeof(struct ether_hdr) + sizeof(struct ipv4_hdr), + }, + { + .type = RTE_ACL_FIELD_TYPE_RANGE, + .size = sizeof(uint16_t), + .field_index = DSTP_FIELD_IPV4, + .input_index = DSTP_FIELD_IPV4, + .offset = sizeof(struct ether_hdr) + sizeof(struct ipv4_hdr) + + sizeof(uint16_t), + }, +}; + +static int +pipeline_firewall_parse_args(struct pipeline_firewall *p, + struct pipeline_params *params) +{ + uint32_t n_rules_present = 0; + uint32_t pkt_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_rules") == 0) { + if (n_rules_present) + return -1; + n_rules_present = 1; + + p->n_rules = atoi(arg_value); + continue; + } + + if (strcmp(arg_name, "pkt_type") == 0){ + if (pkt_type_present) + return -1; + pkt_type_present = 1; + + if (strcmp(arg_value, "ipv4") != 0) + return -1; + + continue; + } + + return -1; + } + + /* Check that mandatory arguments are present */ + if (n_rules_present == 0) + return -1; + + return 0; +} + +static void * +pipeline_firewall_init(struct pipeline_params *params, + __rte_unused void *arg) +{ + struct pipeline *p; + struct pipeline_firewall *p_fw; + uint32_t size, i; + + /* Check input arguments */ + if ((params == NULL) || + (params->n_ports_in == 0) || + (params->n_ports_out == 0)) + return NULL; + + /* Memory allocation */ + size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct pipeline_firewall)); + p = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE); + p_fw = (struct pipeline_firewall *) p; + if (p == NULL) + return NULL; + + strcpy(p->name, params->name); + + /* Parse arguments */ + if (pipeline_firewall_parse_args(p_fw, params)) + return NULL; + + /* Pipeline */ + { + struct rte_pipeline_params pipeline_params = { + .name = params->name, + .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_acl_params table_acl_params = { + .name = "FIREWALL", + .n_rules = p_fw->n_rules, + .n_rule_fields = DIM(ipv4_field_formats), + }; + + struct rte_pipeline_table_params table_params = { + .ops = &rte_table_acl_ops, + .arg_create = &table_acl_params, + .f_action_hit = NULL, + .f_action_miss = NULL, + .arg_ah = NULL, + .action_data_size = 0, + }; + + int status; + + memcpy(table_acl_params.field_format, + ipv4_field_formats, + sizeof(ipv4_field_formats)); + + + 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_fw->custom_handlers, + custom_handlers, + sizeof(p_fw->custom_handlers)); + + return p; +} + +static int +pipeline_firewall_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_firewall_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_firewall_timer(void *pipeline) +{ + struct pipeline *p = (struct pipeline *) pipeline; + + pipeline_msg_req_handle(p); + rte_pipeline_flush(p->p); + + return 0; +} + +void * +pipeline_firewall_msg_req_custom_handler(struct pipeline *p, + void *msg) +{ + struct pipeline_firewall *p_fw = (struct pipeline_firewall *) p; + struct pipeline_custom_msg_req *req = msg; + pipeline_msg_req_handler f_handle; + + f_handle = (req->subtype < PIPELINE_FIREWALL_MSG_REQS)? + p_fw->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); +} + +void * +pipeline_firewall_msg_req_add_handler(struct pipeline *p, void *msg) +{ + struct pipeline_firewall_add_msg_req *req = msg; + struct pipeline_firewall_add_msg_rsp *rsp = msg; + + struct rte_table_acl_rule_add_params params; + 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 PIPELINE_FIREWALL_IPV4_5TUPLE: + params.priority = req->priority; + memset(¶ms.field_value[0], 0, sizeof(params.field_value[0]) * 5); + params.field_value[0].value.u8 = req->key.key.ipv4_5tuple.proto; + params.field_value[0].mask_range.u8 = req->key.key.ipv4_5tuple.proto_mask; + params.field_value[1].value.u32 = req->key.key.ipv4_5tuple.src_ip; + params.field_value[1].mask_range.u32 = req->key.key.ipv4_5tuple.src_ip_mask; + params.field_value[2].value.u32 = req->key.key.ipv4_5tuple.dst_ip; + params.field_value[2].mask_range.u32 = req->key.key.ipv4_5tuple.dst_ip_mask; + params.field_value[3].value.u16 = req->key.key.ipv4_5tuple.src_port_from; + params.field_value[3].mask_range.u16 = req->key.key.ipv4_5tuple.src_port_to; + params.field_value[4].value.u16 = req->key.key.ipv4_5tuple.dst_port_from; + params.field_value[4].mask_range.u16 = req->key.key.ipv4_5tuple.dst_port_to; + break; + + default: + rsp->status = -1; /* Error */ + return rsp; + } + + rsp->status = rte_pipeline_table_entry_add(p->p, + p->table_id[0], + ¶ms, + &entry, + &rsp->key_found, + (struct rte_pipeline_table_entry **) &rsp->entry_ptr); + + RTE_LOG(INFO, USER1, "%s Back-End: Key %s\n", + p->name, + (rsp->key_found)? "found" : "not found"); + + return rsp; +} + +void * +pipeline_firewall_msg_req_del_handler(struct pipeline *p, void *msg) +{ + struct pipeline_firewall_del_msg_req *req = msg; + struct pipeline_firewall_del_msg_rsp *rsp = msg; + + struct rte_table_acl_rule_delete_params params; + + switch(req->key.type) { + case PIPELINE_FIREWALL_IPV4_5TUPLE: + memset(¶ms.field_value[0], 0, sizeof(params.field_value[0]) * 5); + params.field_value[0].value.u8 = req->key.key.ipv4_5tuple.proto; + params.field_value[0].mask_range.u8 = req->key.key.ipv4_5tuple.proto_mask; + params.field_value[1].value.u32 = req->key.key.ipv4_5tuple.src_ip; + params.field_value[1].mask_range.u32 = req->key.key.ipv4_5tuple.src_ip_mask; + params.field_value[2].value.u32 = req->key.key.ipv4_5tuple.dst_ip; + params.field_value[2].mask_range.u32 = req->key.key.ipv4_5tuple.dst_ip_mask; + params.field_value[3].value.u16 = req->key.key.ipv4_5tuple.src_port_from; + params.field_value[3].mask_range.u16 = req->key.key.ipv4_5tuple.src_port_to; + params.field_value[4].value.u16 = req->key.key.ipv4_5tuple.dst_port_from; + params.field_value[4].mask_range.u16 = req->key.key.ipv4_5tuple.dst_port_to; + break; + + default: + rsp->status = -1; /* Error */ + return rsp; + } + + rsp->status = rte_pipeline_table_entry_delete(p->p, + p->table_id[0], + ¶ms, + &rsp->key_found, + NULL); + + RTE_LOG(INFO, USER1, "%s Back-End: Key %s\n", + p->name, + (rsp->key_found)? "found" : "not found"); + + return rsp; +} + +void * +pipeline_firewall_msg_req_add_default_handler(struct pipeline *p, void *msg) +{ + struct pipeline_firewall_add_default_msg_req *req = msg; + struct pipeline_firewall_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->entry_ptr); + + return rsp; +} + +void * +pipeline_firewall_msg_req_del_default_handler(struct pipeline *p, void *msg) +{ + struct pipeline_firewall_del_default_msg_rsp *rsp = msg; + + rsp->status = rte_pipeline_table_default_entry_delete(p->p, + p->table_id[0], + NULL); + + return rsp; +} + +struct pipeline_ops pipeline_firewall_ops = { + .f_init = pipeline_firewall_init, + .f_free = pipeline_firewall_free, + .f_run = NULL, + .f_timer = pipeline_firewall_timer, + .f_track = pipeline_firewall_track, +}; diff --git a/examples/ip_pipeline/pipeline/pipeline_firewall_ops.h b/examples/ip_pipeline/pipeline/pipeline_firewall_ops.h new file mode 100644 index 0000000..9882b9f --- /dev/null +++ b/examples/ip_pipeline/pipeline/pipeline_firewall_ops.h @@ -0,0 +1,139 @@ +/*- + * 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_FIREWALL_OPS_H__ +#define __INCLUDE_PIPELINE_FIREWALL_OPS_H__ + +#include "pipeline_ops.h" +#include "pipeline_common.h" + +enum pipeline_firewall_key_type { + PIPELINE_FIREWALL_IPV4_5TUPLE, +}; + +struct pipeline_firewall_key_ipv4_5tuple { + uint32_t src_ip; + uint32_t src_ip_mask; + uint32_t dst_ip; + uint32_t dst_ip_mask; + uint16_t src_port_from; + uint16_t src_port_to; + uint16_t dst_port_from; + uint16_t dst_port_to; + uint8_t proto; + uint8_t proto_mask; +}; + +struct pipeline_firewall_key { + enum pipeline_firewall_key_type type; + union { + struct pipeline_firewall_key_ipv4_5tuple ipv4_5tuple; + } key; +}; + +enum pipeline_firewall_msg_req_type { + PIPELINE_FIREWALL_MSG_REQ_ADD = 0, + PIPELINE_FIREWALL_MSG_REQ_DEL, + PIPELINE_FIREWALL_MSG_REQ_ADD_DEFAULT, + PIPELINE_FIREWALL_MSG_REQ_DEL_DEFAULT, + PIPELINE_FIREWALL_MSG_REQS +}; + +/* + * MSG ADD + */ +struct pipeline_firewall_add_msg_req { + enum pipeline_msg_req_type type; + enum pipeline_firewall_msg_req_type subtype; + + /* key */ + struct pipeline_firewall_key key; + + /* data */ + int32_t priority; + uint32_t port_id; +}; + +struct pipeline_firewall_add_msg_rsp { + int status; + int key_found; + void *entry_ptr; +}; + +/* + * MSG DEL + */ +struct pipeline_firewall_del_msg_req { + enum pipeline_msg_req_type type; + enum pipeline_firewall_msg_req_type subtype; + + /* key */ + struct pipeline_firewall_key key; +}; + +struct pipeline_firewall_del_msg_rsp { + int status; + int key_found; +}; + +/* + * MSG ADD DEFAULT + */ +struct pipeline_firewall_add_default_msg_req { + enum pipeline_msg_req_type type; + enum pipeline_firewall_msg_req_type subtype; + + /* data */ + uint32_t port_id; +}; + +struct pipeline_firewall_add_default_msg_rsp { + int status; + void *entry_ptr; +}; + +/* + * MSG DEL DEFAULT + */ +struct pipeline_firewall_del_default_msg_req { + enum pipeline_msg_req_type type; + enum pipeline_firewall_msg_req_type subtype; +}; + +struct pipeline_firewall_del_default_msg_rsp { + int status; +}; + +extern struct pipeline_ops pipeline_firewall_ops; + +#endif -- 1.7.9.5