examples/ip_pipeline: add bulk update of firewall rules
authorMarcin Kerlin <marcinx.kerlin@intel.com>
Tue, 20 Oct 2015 13:01:26 +0000 (15:01 +0200)
committerThomas Monjalon <thomas.monjalon@6wind.com>
Wed, 25 Nov 2015 23:32:12 +0000 (00:32 +0100)
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 <maciejx.t.gajdzica@intel.com>
Acked-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
examples/ip_pipeline/pipeline/pipeline_firewall.c
examples/ip_pipeline/pipeline/pipeline_firewall.h
examples/ip_pipeline/pipeline/pipeline_firewall_be.c
examples/ip_pipeline/pipeline/pipeline_firewall_be.h

index f6924ab..4137923 100644 (file)
@@ -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(&params->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,
index 82e905d..ccc4e64 100644 (file)
@@ -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,
index b6f305f..1c376f7 100644 (file)
@@ -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 **)&params, 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)
 {
index 8e1fd69..f5b0522 100644 (file)
@@ -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
  */