From 67ebdbef0c315cc4165e95e34e57362d894d2ce1 Mon Sep 17 00:00:00 2001 From: Marcin Kerlin Date: Tue, 20 Oct 2015 15:01:26 +0200 Subject: [PATCH] examples/ip_pipeline: add bulk update of firewall rules Added two new cli commands to firewall pipeline. Commands bulk add and bulk delete takes as argument a file with rules to add/delete. The file is parsed, and then rules are passed to backend functions which add/delete records from pipeline tables. Signed-off-by: Maciej Gajdzica Acked-by: Cristian Dumitrescu --- .../ip_pipeline/pipeline/pipeline_firewall.c | 858 ++++++++++++++++++ .../ip_pipeline/pipeline/pipeline_firewall.h | 14 + .../pipeline/pipeline_firewall_be.c | 157 ++++ .../pipeline/pipeline_firewall_be.h | 38 + 4 files changed, 1067 insertions(+) diff --git a/examples/ip_pipeline/pipeline/pipeline_firewall.c b/examples/ip_pipeline/pipeline/pipeline_firewall.c index f6924ab54a..4137923c45 100644 --- a/examples/ip_pipeline/pipeline/pipeline_firewall.c +++ b/examples/ip_pipeline/pipeline/pipeline_firewall.c @@ -51,6 +51,8 @@ #include "pipeline_common_fe.h" #include "pipeline_firewall.h" +#define BUF_SIZE 1024 + struct app_pipeline_firewall_rule { struct pipeline_firewall_key key; int32_t priority; @@ -73,6 +75,18 @@ struct app_pipeline_firewall { void *default_rule_entry_ptr; }; +struct app_pipeline_add_bulk_params { + struct pipeline_firewall_key *keys; + uint32_t n_keys; + uint32_t *priorities; + uint32_t *port_ids; +}; + +struct app_pipeline_del_bulk_params { + struct pipeline_firewall_key *keys; + uint32_t n_keys; +}; + static void print_firewall_ipv4_rule(struct app_pipeline_firewall_rule *rule) { @@ -256,6 +270,358 @@ app_pipeline_firewall_key_check_and_normalize(struct pipeline_firewall_key *key) } } +static int +app_pipeline_add_bulk_parse_file(char *filename, + struct app_pipeline_add_bulk_params *params) +{ + FILE *f; + char file_buf[BUF_SIZE]; + uint32_t i; + int status = 0; + + f = fopen(filename, "r"); + if (f == NULL) + return -1; + + params->n_keys = 0; + while (fgets(file_buf, BUF_SIZE, f) != NULL) + params->n_keys++; + rewind(f); + + if (params->n_keys == 0) { + status = -1; + goto end; + } + + params->keys = rte_malloc(NULL, + params->n_keys * sizeof(struct pipeline_firewall_key), + RTE_CACHE_LINE_SIZE); + if (params->keys == NULL) { + status = -1; + goto end; + } + + params->priorities = rte_malloc(NULL, + params->n_keys * sizeof(uint32_t), + RTE_CACHE_LINE_SIZE); + if (params->priorities == NULL) { + status = -1; + goto end; + } + + params->port_ids = rte_malloc(NULL, + params->n_keys * sizeof(uint32_t), + RTE_CACHE_LINE_SIZE); + if (params->port_ids == NULL) { + status = -1; + goto end; + } + + i = 0; + while (fgets(file_buf, BUF_SIZE, f) != NULL) { + char *str; + + str = strtok(file_buf, " "); + if (str == NULL) { + status = -1; + goto end; + } + params->priorities[i] = atoi(str); + + str = strtok(NULL, " ."); + if (str == NULL) { + status = -1; + goto end; + } + params->keys[i].key.ipv4_5tuple.src_ip = atoi(str)<<24; + + str = strtok(NULL, " ."); + if (str == NULL) { + status = -1; + goto end; + } + params->keys[i].key.ipv4_5tuple.src_ip |= atoi(str)<<16; + + str = strtok(NULL, " ."); + if (str == NULL) { + status = -1; + goto end; + } + params->keys[i].key.ipv4_5tuple.src_ip |= atoi(str)<<8; + + str = strtok(NULL, " ."); + if (str == NULL) { + status = -1; + goto end; + } + params->keys[i].key.ipv4_5tuple.src_ip |= atoi(str); + + str = strtok(NULL, " "); + if (str == NULL) { + status = -1; + goto end; + } + params->keys[i].key.ipv4_5tuple.src_ip_mask = atoi(str); + + str = strtok(NULL, " ."); + if (str == NULL) { + status = -1; + goto end; + } + params->keys[i].key.ipv4_5tuple.dst_ip = atoi(str)<<24; + + str = strtok(NULL, " ."); + if (str == NULL) { + status = -1; + goto end; + } + params->keys[i].key.ipv4_5tuple.dst_ip |= atoi(str)<<16; + + str = strtok(NULL, " ."); + if (str == NULL) { + status = -1; + goto end; + } + params->keys[i].key.ipv4_5tuple.dst_ip |= atoi(str)<<8; + + str = strtok(NULL, " ."); + if (str == NULL) { + status = -1; + goto end; + } + params->keys[i].key.ipv4_5tuple.dst_ip |= atoi(str); + + str = strtok(NULL, " "); + if (str == NULL) { + status = -1; + goto end; + } + params->keys[i].key.ipv4_5tuple.dst_ip_mask = atoi(str); + + str = strtok(NULL, " "); + if (str == NULL) { + status = -1; + goto end; + } + params->keys[i].key.ipv4_5tuple.src_port_from = atoi(str); + + str = strtok(NULL, " "); + if (str == NULL) { + status = -1; + goto end; + } + params->keys[i].key.ipv4_5tuple.src_port_to = atoi(str); + + str = strtok(NULL, " "); + if (str == NULL) { + status = -1; + goto end; + } + params->keys[i].key.ipv4_5tuple.dst_port_from = atoi(str); + + str = strtok(NULL, " "); + if (str == NULL) { + status = -1; + goto end; + } + params->keys[i].key.ipv4_5tuple.dst_port_to = atoi(str); + + str = strtok(NULL, " "); + if (str == NULL) { + status = -1; + goto end; + } + params->keys[i].key.ipv4_5tuple.proto = atoi(str); + + str = strtok(NULL, " "); + if (str == NULL) { + status = -1; + goto end; + } + /* Need to add 2 to str to skip leading 0x */ + params->keys[i].key.ipv4_5tuple.proto_mask = strtol(str+2, NULL, 16); + + str = strtok(NULL, " "); + if (str == NULL) { + status = -1; + goto end; + } + params->port_ids[i] = atoi(str); + params->keys[i].type = PIPELINE_FIREWALL_IPV4_5TUPLE; + + i++; + } + +end: + fclose(f); + return status; +} + +static int +app_pipeline_del_bulk_parse_file(char *filename, + struct app_pipeline_del_bulk_params *params) +{ + FILE *f; + char file_buf[BUF_SIZE]; + uint32_t i; + int status = 0; + + f = fopen(filename, "r"); + if (f == NULL) + return -1; + + params->n_keys = 0; + while (fgets(file_buf, BUF_SIZE, f) != NULL) + params->n_keys++; + rewind(f); + + if (params->n_keys == 0) { + status = -1; + goto end; + } + + params->keys = rte_malloc(NULL, + params->n_keys * sizeof(struct pipeline_firewall_key), + RTE_CACHE_LINE_SIZE); + if (params->keys == NULL) { + status = -1; + goto end; + } + + i = 0; + while (fgets(file_buf, BUF_SIZE, f) != NULL) { + char *str; + + str = strtok(file_buf, " ."); + if (str == NULL) { + status = -1; + goto end; + } + params->keys[i].key.ipv4_5tuple.src_ip = atoi(str)<<24; + + str = strtok(NULL, " ."); + if (str == NULL) { + status = -1; + goto end; + } + params->keys[i].key.ipv4_5tuple.src_ip |= atoi(str)<<16; + + str = strtok(NULL, " ."); + if (str == NULL) { + status = -1; + goto end; + } + params->keys[i].key.ipv4_5tuple.src_ip |= atoi(str)<<8; + + str = strtok(NULL, " ."); + if (str == NULL) { + status = -1; + goto end; + } + params->keys[i].key.ipv4_5tuple.src_ip |= atoi(str); + + str = strtok(NULL, " "); + if (str == NULL) { + status = -1; + goto end; + } + params->keys[i].key.ipv4_5tuple.src_ip_mask = atoi(str); + + str = strtok(NULL, " ."); + if (str == NULL) { + status = -1; + goto end; + } + params->keys[i].key.ipv4_5tuple.dst_ip = atoi(str)<<24; + + str = strtok(NULL, " ."); + if (str == NULL) { + status = -1; + goto end; + } + params->keys[i].key.ipv4_5tuple.dst_ip |= atoi(str)<<16; + + str = strtok(NULL, " ."); + if (str == NULL) { + status = -1; + goto end; + } + params->keys[i].key.ipv4_5tuple.dst_ip |= atoi(str)<<8; + + str = strtok(NULL, " ."); + if (str == NULL) { + status = -1; + goto end; + } + params->keys[i].key.ipv4_5tuple.dst_ip |= atoi(str); + + str = strtok(NULL, " "); + if (str == NULL) { + status = -1; + goto end; + } + params->keys[i].key.ipv4_5tuple.dst_ip_mask = atoi(str); + + str = strtok(NULL, " "); + if (str == NULL) { + status = -1; + goto end; + } + params->keys[i].key.ipv4_5tuple.src_port_from = atoi(str); + + str = strtok(NULL, " "); + if (str == NULL) { + status = -1; + goto end; + } + params->keys[i].key.ipv4_5tuple.src_port_to = atoi(str); + + str = strtok(NULL, " "); + if (str == NULL) { + status = -1; + goto end; + } + params->keys[i].key.ipv4_5tuple.dst_port_from = atoi(str); + + str = strtok(NULL, " "); + if (str == NULL) { + status = -1; + goto end; + } + params->keys[i].key.ipv4_5tuple.dst_port_to = atoi(str); + + str = strtok(NULL, " "); + if (str == NULL) { + status = -1; + goto end; + } + params->keys[i].key.ipv4_5tuple.proto = atoi(str); + + str = strtok(NULL, " "); + if (str == NULL) { + status = -1; + goto end; + } + /* Need to add 2 to str to skip leading 0x */ + params->keys[i].key.ipv4_5tuple.proto_mask = strtol(str+2, NULL, 16); + + params->keys[i].type = PIPELINE_FIREWALL_IPV4_5TUPLE; + + i++; + } + + for (i = 0; i < params->n_keys; i++) { + if (app_pipeline_firewall_key_check_and_normalize(¶ms->keys[i]) != 0) { + status = -1; + goto end; + } + } + +end: + fclose(f); + return status; +} + int app_pipeline_firewall_add_rule(struct app_params *app, uint32_t pipeline_id, @@ -406,6 +772,332 @@ app_pipeline_firewall_delete_rule(struct app_params *app, return 0; } +int +app_pipeline_firewall_add_bulk(struct app_params *app, + uint32_t pipeline_id, + struct pipeline_firewall_key *keys, + uint32_t n_keys, + uint32_t *priorities, + uint32_t *port_ids) +{ + struct app_pipeline_firewall *p; + struct pipeline_firewall_add_bulk_msg_req *req; + struct pipeline_firewall_add_bulk_msg_rsp *rsp; + + struct app_pipeline_firewall_rule **rules; + int *new_rules; + + int *keys_found; + void **entries_ptr; + + uint32_t i; + int status = 0; + + /* Check input arguments */ + if (app == NULL) + return -1; + + p = app_pipeline_data_fe(app, pipeline_id); + if (p == NULL) + return -1; + + rules = rte_malloc(NULL, + n_keys * sizeof(struct app_pipeline_firewall_rule *), + RTE_CACHE_LINE_SIZE); + if (rules == NULL) + return -1; + + new_rules = rte_malloc(NULL, + n_keys * sizeof(int), + RTE_CACHE_LINE_SIZE); + if (new_rules == NULL) { + rte_free(rules); + return -1; + } + + /* check data integrity and add to rule list */ + for (i = 0; i < n_keys; i++) { + if (port_ids[i] >= p->n_ports_out) { + rte_free(rules); + rte_free(new_rules); + return -1; + } + + if (app_pipeline_firewall_key_check_and_normalize(&keys[i]) != 0) { + rte_free(rules); + rte_free(new_rules); + return -1; + } + + rules[i] = app_pipeline_firewall_rule_find(p, &keys[i]); + new_rules[i] = (rules[i] == NULL); + if (rules[i] == NULL) { + rules[i] = rte_malloc(NULL, sizeof(rules[i]), + RTE_CACHE_LINE_SIZE); + + if (rules[i] == NULL) { + uint32_t j; + + for (j = 0; j <= i; j++) + if (new_rules[j]) + rte_free(rules[j]); + + rte_free(rules); + rte_free(new_rules); + return -1; + } + } + } + + keys_found = rte_malloc(NULL, + n_keys * sizeof(int), + RTE_CACHE_LINE_SIZE); + if (keys_found == NULL) { + uint32_t j; + + for (j = 0; j < n_keys; j++) + if (new_rules[j]) + rte_free(rules[j]); + + rte_free(rules); + rte_free(new_rules); + return -1; + } + + entries_ptr = rte_malloc(NULL, + n_keys * sizeof(struct rte_pipeline_table_entry *), + RTE_CACHE_LINE_SIZE); + if (entries_ptr == NULL) { + uint32_t j; + + for (j = 0; j < n_keys; j++) + if (new_rules[j]) + rte_free(rules[j]); + + rte_free(rules); + rte_free(new_rules); + rte_free(keys_found); + return -1; + } + for (i = 0; i < n_keys; i++) { + entries_ptr[i] = rte_malloc(NULL, + sizeof(struct rte_pipeline_table_entry), + RTE_CACHE_LINE_SIZE); + + if (entries_ptr[i] == NULL) { + uint32_t j; + + for (j = 0; j < n_keys; j++) + if (new_rules[j]) + rte_free(rules[j]); + + for (j = 0; j <= i; j++) + rte_free(entries_ptr[j]); + + rte_free(rules); + rte_free(new_rules); + rte_free(keys_found); + rte_free(entries_ptr); + return -1; + } + } + + /* Allocate and write request */ + req = app_msg_alloc(app); + if (req == NULL) { + uint32_t j; + + for (j = 0; j < n_keys; j++) + if (new_rules[j]) + rte_free(rules[j]); + + for (j = 0; j < n_keys; j++) + rte_free(entries_ptr[j]); + + rte_free(rules); + rte_free(new_rules); + rte_free(keys_found); + rte_free(entries_ptr); + return -1; + } + + req->type = PIPELINE_MSG_REQ_CUSTOM; + req->subtype = PIPELINE_FIREWALL_MSG_REQ_ADD_BULK; + + req->keys = keys; + req->n_keys = n_keys; + req->port_ids = port_ids; + req->priorities = priorities; + req->keys_found = keys_found; + req->entries_ptr = entries_ptr; + + /* Send request and wait for response */ + rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT); + if (rsp == NULL) { + uint32_t j; + + for (j = 0; j < n_keys; j++) + if (new_rules[j]) + rte_free(rules[j]); + + for (j = 0; j < n_keys; j++) + rte_free(entries_ptr[j]); + + rte_free(rules); + rte_free(new_rules); + rte_free(keys_found); + rte_free(entries_ptr); + return -1; + } + + if (rsp->status) { + for (i = 0; i < n_keys; i++) + if (new_rules[i]) + rte_free(rules[i]); + + for (i = 0; i < n_keys; i++) + rte_free(entries_ptr[i]); + + status = -1; + goto cleanup; + } + + for (i = 0; i < n_keys; i++) { + if (entries_ptr[i] == NULL || + ((new_rules[i] == 0) && (keys_found[i] == 0)) || + ((new_rules[i] == 1) && (keys_found[i] == 1))) { + for (i = 0; i < n_keys; i++) + if (new_rules[i]) + rte_free(rules[i]); + + for (i = 0; i < n_keys; i++) + rte_free(entries_ptr[i]); + + status = -1; + goto cleanup; + } + } + + for (i = 0; i < n_keys; i++) { + memcpy(&rules[i]->key, &keys[i], sizeof(keys[i])); + rules[i]->priority = priorities[i]; + rules[i]->port_id = port_ids[i]; + rules[i]->entry_ptr = entries_ptr[i]; + + /* Commit rule */ + if (new_rules[i]) { + TAILQ_INSERT_TAIL(&p->rules, rules[i], node); + p->n_rules++; + } + + print_firewall_ipv4_rule(rules[i]); + } + +cleanup: + app_msg_free(app, rsp); + rte_free(rules); + rte_free(new_rules); + rte_free(keys_found); + rte_free(entries_ptr); + + return status; +} + +int +app_pipeline_firewall_delete_bulk(struct app_params *app, + uint32_t pipeline_id, + struct pipeline_firewall_key *keys, + uint32_t n_keys) +{ + struct app_pipeline_firewall *p; + struct pipeline_firewall_del_bulk_msg_req *req; + struct pipeline_firewall_del_bulk_msg_rsp *rsp; + + struct app_pipeline_firewall_rule **rules; + int *keys_found; + + uint32_t i; + int status = 0; + + /* Check input arguments */ + if (app == NULL) + return -1; + + p = app_pipeline_data_fe(app, pipeline_id); + if (p == NULL) + return -1; + + rules = rte_malloc(NULL, + n_keys * sizeof(struct app_pipeline_firewall_rule *), + RTE_CACHE_LINE_SIZE); + if (rules == NULL) + return -1; + + for (i = 0; i < n_keys; i++) { + if (app_pipeline_firewall_key_check_and_normalize(&keys[i]) != 0) { + return -1; + } + + rules[i] = app_pipeline_firewall_rule_find(p, &keys[i]); + } + + keys_found = rte_malloc(NULL, + n_keys * sizeof(int), + RTE_CACHE_LINE_SIZE); + if (keys_found == NULL) { + rte_free(rules); + return -1; + } + + /* Allocate and write request */ + req = app_msg_alloc(app); + if (req == NULL) { + rte_free(rules); + rte_free(keys_found); + return -1; + } + + req->type = PIPELINE_MSG_REQ_CUSTOM; + req->subtype = PIPELINE_FIREWALL_MSG_REQ_DEL_BULK; + + req->keys = keys; + req->n_keys = n_keys; + req->keys_found = keys_found; + + /* Send request and wait for response */ + rsp = app_msg_send_recv(app, pipeline_id, req, MSG_TIMEOUT_DEFAULT); + if (rsp == NULL) { + rte_free(rules); + rte_free(keys_found); + return -1; + } + + if (rsp->status) { + status = -1; + goto cleanup; + } + + for (i = 0; i < n_keys; i++) { + if (keys_found[i] == 0) { + status = -1; + goto cleanup; + } + } + + for (i = 0; i < n_keys; i++) { + TAILQ_REMOVE(&p->rules, rules[i], node); + p->n_rules--; + rte_free(rules[i]); + } + +cleanup: + app_msg_free(app, rsp); + rte_free(rules); + rte_free(keys_found); + + return status; +} + int app_pipeline_firewall_add_default_rule(struct app_params *app, uint32_t pipeline_id, @@ -794,6 +1486,170 @@ cmdline_parse_inst_t cmd_firewall_del_ipv4 = { }, }; +/* + * p firewall add bulk + */ + +struct cmd_firewall_add_bulk_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 bulk_string; + cmdline_fixed_string_t file_path; +}; + +static void +cmd_firewall_add_bulk_parsed( + void *parsed_result, + __attribute__((unused)) struct cmdline *cl, + void *data) +{ + struct cmd_firewall_add_bulk_result *params = parsed_result; + struct app_params *app = data; + int status; + + struct app_pipeline_add_bulk_params add_bulk_params; + + status = app_pipeline_add_bulk_parse_file(params->file_path, &add_bulk_params); + if (status != 0) { + printf("Command failed\n"); + goto end; + } + + status = app_pipeline_firewall_add_bulk(app, params->pipeline_id, add_bulk_params.keys, + add_bulk_params.n_keys, add_bulk_params.priorities, add_bulk_params.port_ids); + if (status != 0) { + printf("Command failed\n"); + goto end; + } + +end: + rte_free(add_bulk_params.keys); + rte_free(add_bulk_params.priorities); + rte_free(add_bulk_params.port_ids); +} + +cmdline_parse_token_string_t cmd_firewall_add_bulk_p_string = + TOKEN_STRING_INITIALIZER(struct cmd_firewall_add_bulk_result, p_string, + "p"); + +cmdline_parse_token_num_t cmd_firewall_add_bulk_pipeline_id = + TOKEN_NUM_INITIALIZER(struct cmd_firewall_add_bulk_result, pipeline_id, + UINT32); + +cmdline_parse_token_string_t cmd_firewall_add_bulk_firewall_string = + TOKEN_STRING_INITIALIZER(struct cmd_firewall_add_bulk_result, + firewall_string, "firewall"); + +cmdline_parse_token_string_t cmd_firewall_add_bulk_add_string = + TOKEN_STRING_INITIALIZER(struct cmd_firewall_add_bulk_result, + add_string, "add"); + +cmdline_parse_token_string_t cmd_firewall_add_bulk_bulk_string = + TOKEN_STRING_INITIALIZER(struct cmd_firewall_add_bulk_result, + bulk_string, "bulk"); + +cmdline_parse_token_string_t cmd_firewall_add_bulk_file_path_string = + TOKEN_STRING_INITIALIZER(struct cmd_firewall_add_bulk_result, + file_path, NULL); + +cmdline_parse_inst_t cmd_firewall_add_bulk = { + .f = cmd_firewall_add_bulk_parsed, + .data = NULL, + .help_str = "Firewall rule add bulk", + .tokens = { + (void *) &cmd_firewall_add_bulk_p_string, + (void *) &cmd_firewall_add_bulk_pipeline_id, + (void *) &cmd_firewall_add_bulk_firewall_string, + (void *) &cmd_firewall_add_bulk_add_string, + (void *) &cmd_firewall_add_bulk_bulk_string, + (void *) &cmd_firewall_add_bulk_file_path_string, + NULL, + }, +}; + +/* + * p firewall del bulk + */ + +struct cmd_firewall_del_bulk_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 bulk_string; + cmdline_fixed_string_t file_path; +}; + +static void +cmd_firewall_del_bulk_parsed( + void *parsed_result, + __attribute__((unused)) struct cmdline *cl, + void *data) +{ + struct cmd_firewall_del_bulk_result *params = parsed_result; + struct app_params *app = data; + int status; + + struct app_pipeline_del_bulk_params del_bulk_params; + + status = app_pipeline_del_bulk_parse_file(params->file_path, &del_bulk_params); + if (status != 0) { + printf("Command failed\n"); + goto end; + } + + status = app_pipeline_firewall_delete_bulk(app, params->pipeline_id, + del_bulk_params.keys, del_bulk_params.n_keys); + if (status != 0) { + printf("Command failed\n"); + goto end; + } + +end: + rte_free(del_bulk_params.keys); +} + +cmdline_parse_token_string_t cmd_firewall_del_bulk_p_string = + TOKEN_STRING_INITIALIZER(struct cmd_firewall_del_bulk_result, p_string, + "p"); + +cmdline_parse_token_num_t cmd_firewall_del_bulk_pipeline_id = + TOKEN_NUM_INITIALIZER(struct cmd_firewall_del_bulk_result, pipeline_id, + UINT32); + +cmdline_parse_token_string_t cmd_firewall_del_bulk_firewall_string = + TOKEN_STRING_INITIALIZER(struct cmd_firewall_del_bulk_result, + firewall_string, "firewall"); + +cmdline_parse_token_string_t cmd_firewall_del_bulk_add_string = + TOKEN_STRING_INITIALIZER(struct cmd_firewall_del_bulk_result, + del_string, "del"); + +cmdline_parse_token_string_t cmd_firewall_del_bulk_bulk_string = + TOKEN_STRING_INITIALIZER(struct cmd_firewall_del_bulk_result, + bulk_string, "bulk"); + +cmdline_parse_token_string_t cmd_firewall_del_bulk_file_path_string = + TOKEN_STRING_INITIALIZER(struct cmd_firewall_del_bulk_result, + file_path, NULL); + +cmdline_parse_inst_t cmd_firewall_del_bulk = { + .f = cmd_firewall_del_bulk_parsed, + .data = NULL, + .help_str = "Firewall rule del bulk", + .tokens = { + (void *) &cmd_firewall_del_bulk_p_string, + (void *) &cmd_firewall_del_bulk_pipeline_id, + (void *) &cmd_firewall_del_bulk_firewall_string, + (void *) &cmd_firewall_del_bulk_add_string, + (void *) &cmd_firewall_del_bulk_bulk_string, + (void *) &cmd_firewall_del_bulk_file_path_string, + NULL, + }, +}; + /* * p firewall add default */ @@ -984,6 +1840,8 @@ cmdline_parse_inst_t cmd_firewall_ls = { 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_bulk, + (cmdline_parse_inst_t *) &cmd_firewall_del_bulk, (cmdline_parse_inst_t *) &cmd_firewall_add_default, (cmdline_parse_inst_t *) &cmd_firewall_del_default, (cmdline_parse_inst_t *) &cmd_firewall_ls, diff --git a/examples/ip_pipeline/pipeline/pipeline_firewall.h b/examples/ip_pipeline/pipeline/pipeline_firewall.h index 82e905d8b3..ccc4e64bc1 100644 --- a/examples/ip_pipeline/pipeline/pipeline_firewall.h +++ b/examples/ip_pipeline/pipeline/pipeline_firewall.h @@ -49,6 +49,20 @@ app_pipeline_firewall_delete_rule(struct app_params *app, uint32_t pipeline_id, struct pipeline_firewall_key *key); +int +app_pipeline_firewall_add_bulk(struct app_params *app, + uint32_t pipeline_id, + struct pipeline_firewall_key *keys, + uint32_t n_keys, + uint32_t *priorities, + uint32_t *port_ids); + +int +app_pipeline_firewall_delete_bulk(struct app_params *app, + uint32_t pipeline_id, + struct pipeline_firewall_key *keys, + uint32_t n_keys); + int app_pipeline_firewall_add_default_rule(struct app_params *app, uint32_t pipeline_id, diff --git a/examples/ip_pipeline/pipeline/pipeline_firewall_be.c b/examples/ip_pipeline/pipeline/pipeline_firewall_be.c index b6f305fc43..1c376f7eaf 100644 --- a/examples/ip_pipeline/pipeline/pipeline_firewall_be.c +++ b/examples/ip_pipeline/pipeline/pipeline_firewall_be.c @@ -79,6 +79,12 @@ 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_bulk_handler(struct pipeline *p, void *msg); + +static void * +pipeline_firewall_msg_req_del_bulk_handler(struct pipeline *p, void *msg); + static void * pipeline_firewall_msg_req_add_default_handler(struct pipeline *p, void *msg); @@ -90,6 +96,10 @@ static pipeline_msg_req_handler custom_handlers[] = { pipeline_firewall_msg_req_add_handler, [PIPELINE_FIREWALL_MSG_REQ_DEL] = pipeline_firewall_msg_req_del_handler, + [PIPELINE_FIREWALL_MSG_REQ_ADD_BULK] = + pipeline_firewall_msg_req_add_bulk_handler, + [PIPELINE_FIREWALL_MSG_REQ_DEL_BULK] = + pipeline_firewall_msg_req_del_bulk_handler, [PIPELINE_FIREWALL_MSG_REQ_ADD_DEFAULT] = pipeline_firewall_msg_req_add_default_handler, [PIPELINE_FIREWALL_MSG_REQ_DEL_DEFAULT] = @@ -698,6 +708,153 @@ pipeline_firewall_msg_req_del_handler(struct pipeline *p, void *msg) return rsp; } +static void * +pipeline_firewall_msg_req_add_bulk_handler(struct pipeline *p, void *msg) +{ + struct pipeline_firewall_add_bulk_msg_req *req = msg; + struct pipeline_firewall_add_bulk_msg_rsp *rsp = msg; + + struct rte_table_acl_rule_add_params *params[req->n_keys]; + struct firewall_table_entry *entries[req->n_keys]; + + uint32_t i, n_keys; + + n_keys = req->n_keys; + + for (i = 0; i < n_keys; i++) { + entries[i] = rte_malloc(NULL, + sizeof(struct firewall_table_entry), + RTE_CACHE_LINE_SIZE); + if (entries[i] == NULL) { + rsp->status = -1; + return rsp; + } + + params[i] = rte_malloc(NULL, + sizeof(struct rte_table_acl_rule_add_params), + RTE_CACHE_LINE_SIZE); + if (params[i] == NULL) { + rsp->status = -1; + return rsp; + } + + entries[i]->head.action = RTE_PIPELINE_ACTION_PORT; + entries[i]->head.port_id = p->port_out_id[req->port_ids[i]]; + + switch (req->keys[i].type) { + case PIPELINE_FIREWALL_IPV4_5TUPLE: + params[i]->priority = req->priorities[i]; + params[i]->field_value[0].value.u8 = + req->keys[i].key.ipv4_5tuple.proto; + params[i]->field_value[0].mask_range.u8 = + req->keys[i].key.ipv4_5tuple.proto_mask; + params[i]->field_value[1].value.u32 = + req->keys[i].key.ipv4_5tuple.src_ip; + params[i]->field_value[1].mask_range.u32 = + req->keys[i].key.ipv4_5tuple.src_ip_mask; + params[i]->field_value[2].value.u32 = + req->keys[i].key.ipv4_5tuple.dst_ip; + params[i]->field_value[2].mask_range.u32 = + req->keys[i].key.ipv4_5tuple.dst_ip_mask; + params[i]->field_value[3].value.u16 = + req->keys[i].key.ipv4_5tuple.src_port_from; + params[i]->field_value[3].mask_range.u16 = + req->keys[i].key.ipv4_5tuple.src_port_to; + params[i]->field_value[4].value.u16 = + req->keys[i].key.ipv4_5tuple.dst_port_from; + params[i]->field_value[4].mask_range.u16 = + req->keys[i].key.ipv4_5tuple.dst_port_to; + break; + + default: + rsp->status = -1; /* Error */ + + for (i = 0; i < n_keys; i++) { + rte_free(entries[i]); + rte_free(params[i]); + } + + return rsp; + } + } + + rsp->status = rte_pipeline_table_entry_add_bulk(p->p, p->table_id[0], + (void *)params, (struct rte_pipeline_table_entry **)entries, + n_keys, req->keys_found, + (struct rte_pipeline_table_entry **)req->entries_ptr); + + for (i = 0; i < n_keys; i++) { + rte_free(entries[i]); + rte_free(params[i]); + } + + return rsp; +} + +static void * +pipeline_firewall_msg_req_del_bulk_handler(struct pipeline *p, void *msg) +{ + struct pipeline_firewall_del_bulk_msg_req *req = msg; + struct pipeline_firewall_del_bulk_msg_rsp *rsp = msg; + + struct rte_table_acl_rule_delete_params *params[req->n_keys]; + + uint32_t i, n_keys; + + n_keys = req->n_keys; + + for (i = 0; i < n_keys; i++) { + params[i] = rte_malloc(NULL, + sizeof(struct rte_table_acl_rule_delete_params), + RTE_CACHE_LINE_SIZE); + if (params[i] == NULL) { + rsp->status = -1; + return rsp; + } + + switch (req->keys[i].type) { + case PIPELINE_FIREWALL_IPV4_5TUPLE: + params[i]->field_value[0].value.u8 = + req->keys[i].key.ipv4_5tuple.proto; + params[i]->field_value[0].mask_range.u8 = + req->keys[i].key.ipv4_5tuple.proto_mask; + params[i]->field_value[1].value.u32 = + req->keys[i].key.ipv4_5tuple.src_ip; + params[i]->field_value[1].mask_range.u32 = + req->keys[i].key.ipv4_5tuple.src_ip_mask; + params[i]->field_value[2].value.u32 = + req->keys[i].key.ipv4_5tuple.dst_ip; + params[i]->field_value[2].mask_range.u32 = + req->keys[i].key.ipv4_5tuple.dst_ip_mask; + params[i]->field_value[3].value.u16 = + req->keys[i].key.ipv4_5tuple.src_port_from; + params[i]->field_value[3].mask_range.u16 = + req->keys[i].key.ipv4_5tuple.src_port_to; + params[i]->field_value[4].value.u16 = + req->keys[i].key.ipv4_5tuple.dst_port_from; + params[i]->field_value[4].mask_range.u16 = + req->keys[i].key.ipv4_5tuple.dst_port_to; + break; + + default: + rsp->status = -1; /* Error */ + + for (i = 0; i < n_keys; i++) + rte_free(params[i]); + + return rsp; + } + } + + rsp->status = rte_pipeline_table_entry_delete_bulk(p->p, p->table_id[0], + (void **)¶ms, n_keys, req->keys_found, NULL); + + for (i = 0; i < n_keys; i++) + rte_free(params[i]); + + return rsp; +} + void * pipeline_firewall_msg_req_add_default_handler(struct pipeline *p, void *msg) { diff --git a/examples/ip_pipeline/pipeline/pipeline_firewall_be.h b/examples/ip_pipeline/pipeline/pipeline_firewall_be.h index 8e1fd69848..f5b0522f4c 100644 --- a/examples/ip_pipeline/pipeline/pipeline_firewall_be.h +++ b/examples/ip_pipeline/pipeline/pipeline_firewall_be.h @@ -63,6 +63,8 @@ struct pipeline_firewall_key { enum pipeline_firewall_msg_req_type { PIPELINE_FIREWALL_MSG_REQ_ADD = 0, PIPELINE_FIREWALL_MSG_REQ_DEL, + PIPELINE_FIREWALL_MSG_REQ_ADD_BULK, + PIPELINE_FIREWALL_MSG_REQ_DEL_BULK, PIPELINE_FIREWALL_MSG_REQ_ADD_DEFAULT, PIPELINE_FIREWALL_MSG_REQ_DEL_DEFAULT, PIPELINE_FIREWALL_MSG_REQS @@ -105,6 +107,42 @@ struct pipeline_firewall_del_msg_rsp { int key_found; }; +/* + * MSG ADD BULK + */ +struct pipeline_firewall_add_bulk_msg_req { + enum pipeline_msg_req_type type; + enum pipeline_firewall_msg_req_type subtype; + + struct pipeline_firewall_key *keys; + uint32_t n_keys; + + uint32_t *priorities; + uint32_t *port_ids; + int *keys_found; + void **entries_ptr; +}; +struct pipeline_firewall_add_bulk_msg_rsp { + int status; +}; + +/* + * MSG DEL BULK + */ +struct pipeline_firewall_del_bulk_msg_req { + enum pipeline_msg_req_type type; + enum pipeline_firewall_msg_req_type subtype; + + /* key */ + struct pipeline_firewall_key *keys; + uint32_t n_keys; + int *keys_found; +}; + +struct pipeline_firewall_del_bulk_msg_rsp { + int status; +}; + /* * MSG ADD DEFAULT */