summaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
authorCristian Dumitrescu <cristian.dumitrescu@intel.com>2018-10-30 18:04:09 +0000
committerCristian Dumitrescu <cristian.dumitrescu@intel.com>2018-11-02 12:25:05 +0100
commit27b333b232372c37be2f228e71063504e949ba25 (patch)
treef0771b51473afb00c1209bd8cb4e8560e76a641c /examples
parent4c65163ec2466c1ed139553c17f9838a833a6d2f (diff)
downloaddpdk-27b333b232372c37be2f228e71063504e949ba25.zip
dpdk-27b333b232372c37be2f228e71063504e949ba25.tar.gz
dpdk-27b333b232372c37be2f228e71063504e949ba25.tar.xz
examples/ip_pipeline: track table rules on add bulk
Support table rule tracking on table rule add bulk operation. Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com> Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com>
Diffstat (limited to 'examples')
-rw-r--r--examples/ip_pipeline/cli.c149
-rw-r--r--examples/ip_pipeline/pipeline.h7
-rw-r--r--examples/ip_pipeline/thread.c429
3 files changed, 299 insertions, 286 deletions
diff --git a/examples/ip_pipeline/cli.c b/examples/ip_pipeline/cli.c
index 65600b7..5011cad 100644
--- a/examples/ip_pipeline/cli.c
+++ b/examples/ip_pipeline/cli.c
@@ -4523,7 +4523,7 @@ cmd_pipeline_table_rule_add_default(char **tokens,
static const char cmd_pipeline_table_rule_add_bulk_help[] =
-"pipeline <pipeline_name> table <table_id> rule add bulk <file_name> <n_rules>\n"
+"pipeline <pipeline_name> table <table_id> rule add bulk <file_name>\n"
"\n"
" File <file_name>:\n"
" - line format: match <match> action <action>\n";
@@ -4531,8 +4531,7 @@ static const char cmd_pipeline_table_rule_add_bulk_help[] =
static int
cli_rule_file_process(const char *file_name,
size_t line_len_max,
- struct table_rule_match *m,
- struct table_rule_action *a,
+ struct table_rule_list **rule_list,
uint32_t *n_rules,
uint32_t *line_number,
char *out,
@@ -4544,14 +4543,12 @@ cmd_pipeline_table_rule_add_bulk(char **tokens,
char *out,
size_t out_size)
{
- struct table_rule_match *match;
- struct table_rule_action *action;
- void **data;
+ struct table_rule_list *list = NULL;
char *pipeline_name, *file_name;
- uint32_t table_id, n_rules, n_rules_parsed, line_number;
+ uint32_t table_id, n_rules, n_rules_added, n_rules_not_added, line_number;
int status;
- if (n_tokens != 9) {
+ if (n_tokens != 8) {
snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
return;
}
@@ -4585,68 +4582,33 @@ cmd_pipeline_table_rule_add_bulk(char **tokens,
file_name = tokens[7];
- if ((parser_read_uint32(&n_rules, tokens[8]) != 0) ||
- (n_rules == 0)) {
- snprintf(out, out_size, MSG_ARG_INVALID, "n_rules");
- return;
- }
-
- /* Memory allocation. */
- match = calloc(n_rules, sizeof(struct table_rule_match));
- action = calloc(n_rules, sizeof(struct table_rule_action));
- data = calloc(n_rules, sizeof(void *));
- if ((match == NULL) || (action == NULL) || (data == NULL)) {
- snprintf(out, out_size, MSG_OUT_OF_MEMORY);
- free(data);
- free(action);
- free(match);
- return;
- }
-
- /* Load rule file */
- n_rules_parsed = n_rules;
+ /* Load rules from file. */
status = cli_rule_file_process(file_name,
1024,
- match,
- action,
- &n_rules_parsed,
+ &list,
+ &n_rules,
&line_number,
out,
out_size);
if (status) {
snprintf(out, out_size, MSG_FILE_ERR, file_name, line_number);
- free(data);
- free(action);
- free(match);
- return;
- }
- if (n_rules_parsed != n_rules) {
- snprintf(out, out_size, MSG_FILE_NOT_ENOUGH, file_name);
- free(data);
- free(action);
- free(match);
return;
}
/* Rule bulk add */
status = pipeline_table_rule_add_bulk(pipeline_name,
table_id,
- match,
- action,
- data,
- &n_rules);
+ list,
+ &n_rules_added,
+ &n_rules_not_added);
if (status) {
snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
- free(data);
- free(action);
- free(match);
return;
}
- /* Memory free */
- free(data);
- free(action);
- free(match);
+ snprintf(out, out_size, "Added %u rules out of %u.\n",
+ n_rules_added,
+ n_rules);
}
@@ -5950,44 +5912,56 @@ cli_script_process(const char *file_name,
static int
cli_rule_file_process(const char *file_name,
size_t line_len_max,
- struct table_rule_match *m,
- struct table_rule_action *a,
+ struct table_rule_list **rule_list,
uint32_t *n_rules,
uint32_t *line_number,
char *out,
size_t out_size)
{
- FILE *f = NULL;
+ struct table_rule_list *list = NULL;
char *line = NULL;
- uint32_t rule_id, line_id;
+ FILE *f = NULL;
+ uint32_t rule_id = 0, line_id = 0;
int status = 0;
/* Check input arguments */
if ((file_name == NULL) ||
(strlen(file_name) == 0) ||
- (line_len_max == 0)) {
- *line_number = 0;
- return -EINVAL;
+ (line_len_max == 0) ||
+ (rule_list == NULL) ||
+ (n_rules == NULL) ||
+ (line_number == NULL) ||
+ (out == NULL)) {
+ status = -EINVAL;
+ goto cli_rule_file_process_free;
}
/* Memory allocation */
+ list = malloc(sizeof(struct table_rule_list));
+ if (list == NULL) {
+ status = -ENOMEM;
+ goto cli_rule_file_process_free;
+ }
+
+ TAILQ_INIT(list);
+
line = malloc(line_len_max + 1);
if (line == NULL) {
- *line_number = 0;
- return -ENOMEM;
+ status = -ENOMEM;
+ goto cli_rule_file_process_free;
}
/* Open file */
f = fopen(file_name, "r");
if (f == NULL) {
- *line_number = 0;
- free(line);
- return -EIO;
+ status = -EIO;
+ goto cli_rule_file_process_free;
}
/* Read file */
- for (line_id = 1, rule_id = 0; rule_id < *n_rules; line_id++) {
+ for (line_id = 1, rule_id = 0; ; line_id++) {
char *tokens[CMD_MAX_TOKENS];
+ struct table_rule *rule = NULL;
uint32_t n_tokens, n_tokens_parsed, t0;
/* Read next line from file. */
@@ -6003,7 +5977,7 @@ cli_rule_file_process(const char *file_name,
status = parse_tokenize_string(line, tokens, &n_tokens);
if (status) {
status = -EINVAL;
- break;
+ goto cli_rule_file_process_free;
}
/* Empty line. */
@@ -6011,15 +5985,24 @@ cli_rule_file_process(const char *file_name,
continue;
t0 = 0;
+ /* Rule alloc and insert. */
+ rule = calloc(1, sizeof(struct table_rule));
+ if (rule == NULL) {
+ status = -ENOMEM;
+ goto cli_rule_file_process_free;
+ }
+
+ TAILQ_INSERT_TAIL(list, rule, node);
+
/* Rule match. */
n_tokens_parsed = parse_match(tokens + t0,
n_tokens - t0,
out,
out_size,
- &m[rule_id]);
+ &rule->match);
if (n_tokens_parsed == 0) {
status = -EINVAL;
- break;
+ goto cli_rule_file_process_free;
}
t0 += n_tokens_parsed;
@@ -6028,17 +6011,17 @@ cli_rule_file_process(const char *file_name,
n_tokens - t0,
out,
out_size,
- &a[rule_id]);
+ &rule->action);
if (n_tokens_parsed == 0) {
status = -EINVAL;
- break;
+ goto cli_rule_file_process_free;
}
t0 += n_tokens_parsed;
/* Line completed. */
if (t0 < n_tokens) {
status = -EINVAL;
- break;
+ goto cli_rule_file_process_free;
}
/* Increment rule count */
@@ -6051,7 +6034,31 @@ cli_rule_file_process(const char *file_name,
/* Memory free */
free(line);
+ *rule_list = list;
+ *n_rules = rule_id;
+ *line_number = line_id;
+ return 0;
+
+cli_rule_file_process_free:
+ *rule_list = NULL;
*n_rules = rule_id;
*line_number = line_id;
+
+ for ( ; ; ) {
+ struct table_rule *rule;
+
+ rule = TAILQ_FIRST(list);
+ if (rule == NULL)
+ break;
+
+ TAILQ_REMOVE(list, rule, node);
+ free(rule);
+ }
+
+ if (f)
+ fclose(f);
+ free(line);
+ free(list);
+
return status;
}
diff --git a/examples/ip_pipeline/pipeline.h b/examples/ip_pipeline/pipeline.h
index 58067ed..8a364a9 100644
--- a/examples/ip_pipeline/pipeline.h
+++ b/examples/ip_pipeline/pipeline.h
@@ -334,10 +334,9 @@ pipeline_table_rule_add(const char *pipeline_name,
int
pipeline_table_rule_add_bulk(const char *pipeline_name,
uint32_t table_id,
- struct table_rule_match *match,
- struct table_rule_action *action,
- void **data,
- uint32_t *n_rules);
+ struct table_rule_list *list,
+ uint32_t *n_rules_added,
+ uint32_t *n_rules_not_added);
int
pipeline_table_rule_add_default(const char *pipeline_name,
diff --git a/examples/ip_pipeline/thread.c b/examples/ip_pipeline/thread.c
index 5019de9..2c0570f 100644
--- a/examples/ip_pipeline/thread.c
+++ b/examples/ip_pipeline/thread.c
@@ -609,10 +609,7 @@ struct pipeline_msg_req_table_rule_add_default {
};
struct pipeline_msg_req_table_rule_add_bulk {
- struct table_rule_match *match;
- struct table_rule_action *action;
- void **data;
- uint32_t n_rules;
+ struct table_rule_list *list;
int bulk;
};
@@ -1206,6 +1203,128 @@ action_convert(struct rte_table_action *a,
struct table_rule_action *action,
struct rte_pipeline_table_entry *data);
+struct table_ll {
+ struct rte_pipeline *p;
+ int table_id;
+ struct rte_table_action *a;
+ int bulk_supported;
+};
+
+static int
+table_rule_add_bulk_ll(struct table_ll *table,
+ struct table_rule_list *list,
+ uint32_t *n_rules)
+{
+ union table_rule_match_low_level *match_ll = NULL;
+ uint8_t *action_ll = NULL;
+ void **match_ll_ptr = NULL;
+ struct rte_pipeline_table_entry **action_ll_ptr = NULL;
+ struct rte_pipeline_table_entry **entries_ptr = NULL;
+ int *found = NULL;
+ struct table_rule *rule;
+ uint32_t n, i;
+ int status = 0;
+
+ n = 0;
+ TAILQ_FOREACH(rule, list, node)
+ n++;
+
+ /* Memory allocation */
+ match_ll = calloc(n, sizeof(union table_rule_match_low_level));
+ action_ll = calloc(n, TABLE_RULE_ACTION_SIZE_MAX);
+
+ match_ll_ptr = calloc(n, sizeof(void *));
+ action_ll_ptr = calloc(n, sizeof(struct rte_pipeline_table_entry *));
+
+ entries_ptr = calloc(n, sizeof(struct rte_pipeline_table_entry *));
+ found = calloc(n, sizeof(int));
+
+ if (match_ll == NULL ||
+ action_ll == NULL ||
+ match_ll_ptr == NULL ||
+ action_ll_ptr == NULL ||
+ entries_ptr == NULL ||
+ found == NULL) {
+ status = -ENOMEM;
+ goto table_rule_add_bulk_ll_free;
+ }
+
+ /* Init */
+ for (i = 0; i < n; i++) {
+ match_ll_ptr[i] = (void *)&match_ll[i];
+ action_ll_ptr[i] = (struct rte_pipeline_table_entry *)
+ &action_ll[i * TABLE_RULE_ACTION_SIZE_MAX];
+ }
+
+ /* Rule (match, action) conversion */
+ i = 0;
+ TAILQ_FOREACH(rule, list, node) {
+ status = match_convert(&rule->match, match_ll_ptr[i], 1);
+ if (status)
+ goto table_rule_add_bulk_ll_free;
+
+ status = action_convert(table->a, &rule->action, action_ll_ptr[i]);
+ if (status)
+ goto table_rule_add_bulk_ll_free;
+
+ i++;
+ }
+
+ /* Add rule (match, action) to table */
+ if (table->bulk_supported) {
+ status = rte_pipeline_table_entry_add_bulk(table->p,
+ table->table_id,
+ match_ll_ptr,
+ action_ll_ptr,
+ n,
+ found,
+ entries_ptr);
+ if (status)
+ goto table_rule_add_bulk_ll_free;
+ } else
+ for (i = 0; i < n; i++) {
+ status = rte_pipeline_table_entry_add(table->p,
+ table->table_id,
+ match_ll_ptr[i],
+ action_ll_ptr[i],
+ &found[i],
+ &entries_ptr[i]);
+ if (status) {
+ if (i == 0)
+ goto table_rule_add_bulk_ll_free;
+
+ /* No roll-back. */
+ status = 0;
+ n = i;
+ break;
+ }
+ }
+
+ /* Write back to the rule list. */
+ i = 0;
+ TAILQ_FOREACH(rule, list, node) {
+ if (i >= n)
+ break;
+
+ rule->data = entries_ptr[i];
+
+ i++;
+ }
+
+ *n_rules = n;
+
+ /* Free */
+table_rule_add_bulk_ll_free:
+ free(found);
+ free(entries_ptr);
+ free(action_ll_ptr);
+ free(match_ll_ptr);
+ free(action_ll);
+ free(match_ll);
+
+ return status;
+}
+
int
pipeline_table_rule_add(const char *pipeline_name,
uint32_t table_id,
@@ -1408,156 +1527,119 @@ pipeline_table_rule_add_default(const char *pipeline_name,
return status;
}
+static uint32_t
+table_rule_list_free(struct table_rule_list *list)
+{
+ uint32_t n = 0;
+
+ if (!list)
+ return 0;
+
+ for ( ; ; ) {
+ struct table_rule *rule;
+
+ rule = TAILQ_FIRST(list);
+ if (rule == NULL)
+ break;
+
+ TAILQ_REMOVE(list, rule, node);
+ free(rule);
+ n++;
+ }
+
+ free(list);
+ return n;
+}
+
int
pipeline_table_rule_add_bulk(const char *pipeline_name,
uint32_t table_id,
- struct table_rule_match *match,
- struct table_rule_action *action,
- void **data,
- uint32_t *n_rules)
+ struct table_rule_list *list,
+ uint32_t *n_rules_added,
+ uint32_t *n_rules_not_added)
{
struct pipeline *p;
+ struct table *table;
struct pipeline_msg_req *req;
struct pipeline_msg_rsp *rsp;
- uint32_t i;
- int status;
+ struct table_rule *rule;
+ int status = 0;
/* Check input params */
if ((pipeline_name == NULL) ||
- (match == NULL) ||
- (action == NULL) ||
- (data == NULL) ||
- (n_rules == NULL) ||
- (*n_rules == 0))
- return -1;
+ (list == NULL) ||
+ TAILQ_EMPTY(list) ||
+ (n_rules_added == NULL) ||
+ (n_rules_not_added == NULL)) {
+ table_rule_list_free(list);
+ return -EINVAL;
+ }
p = pipeline_find(pipeline_name);
if ((p == NULL) ||
- (table_id >= p->n_tables))
- return -1;
-
- for (i = 0; i < *n_rules; i++)
- if (match_check(match, p, table_id) ||
- action_check(action, p, table_id))
- return -1;
-
- if (!pipeline_is_running(p)) {
- struct rte_table_action *a = p->table[table_id].a;
- union table_rule_match_low_level *match_ll;
- uint8_t *action_ll;
- void **match_ll_ptr;
- struct rte_pipeline_table_entry **action_ll_ptr;
- struct rte_pipeline_table_entry **entries_ptr =
- (struct rte_pipeline_table_entry **)data;
- uint32_t bulk =
- (p->table[table_id].params.match_type == TABLE_ACL) ? 1 : 0;
- int *found;
-
- /* Memory allocation */
- match_ll = calloc(*n_rules, sizeof(union table_rule_match_low_level));
- action_ll = calloc(*n_rules, TABLE_RULE_ACTION_SIZE_MAX);
- match_ll_ptr = calloc(*n_rules, sizeof(void *));
- action_ll_ptr =
- calloc(*n_rules, sizeof(struct rte_pipeline_table_entry *));
- found = calloc(*n_rules, sizeof(int));
-
- if (match_ll == NULL ||
- action_ll == NULL ||
- match_ll_ptr == NULL ||
- action_ll_ptr == NULL ||
- found == NULL)
- goto fail;
-
- for (i = 0; i < *n_rules; i++) {
- match_ll_ptr[i] = (void *)&match_ll[i];
- action_ll_ptr[i] =
- (struct rte_pipeline_table_entry *)&action_ll[i * TABLE_RULE_ACTION_SIZE_MAX];
- }
+ (table_id >= p->n_tables)) {
+ table_rule_list_free(list);
+ return -EINVAL;
+ }
- /* Rule match conversion */
- for (i = 0; i < *n_rules; i++) {
- status = match_convert(&match[i], match_ll_ptr[i], 1);
- if (status)
- goto fail;
- }
+ table = &p->table[table_id];
- /* Rule action conversion */
- for (i = 0; i < *n_rules; i++) {
- status = action_convert(a, &action[i], action_ll_ptr[i]);
- if (status)
- goto fail;
+ TAILQ_FOREACH(rule, list, node)
+ if (match_check(&rule->match, p, table_id) ||
+ action_check(&rule->action, p, table_id)) {
+ table_rule_list_free(list);
+ return -EINVAL;
}
- /* Add rule (match, action) to table */
- if (bulk) {
- status = rte_pipeline_table_entry_add_bulk(p->p,
- table_id,
- match_ll_ptr,
- action_ll_ptr,
- *n_rules,
- found,
- entries_ptr);
- if (status)
- *n_rules = 0;
- } else {
- for (i = 0; i < *n_rules; i++) {
- status = rte_pipeline_table_entry_add(p->p,
- table_id,
- match_ll_ptr[i],
- action_ll_ptr[i],
- &found[i],
- &entries_ptr[i]);
- if (status) {
- *n_rules = i;
- break;
- }
- }
+ if (!pipeline_is_running(p)) {
+ struct table_ll table_ll = {
+ .p = p->p,
+ .table_id = table_id,
+ .a = table->a,
+ .bulk_supported = table->params.match_type == TABLE_ACL,
+ };
+
+ status = table_rule_add_bulk_ll(&table_ll, list, n_rules_added);
+ if (status) {
+ table_rule_list_free(list);
+ return status;
}
- /* Free */
- free(found);
- free(action_ll_ptr);
- free(match_ll_ptr);
- free(action_ll);
- free(match_ll);
-
- return status;
-
-fail:
- free(found);
- free(action_ll_ptr);
- free(match_ll_ptr);
- free(action_ll);
- free(match_ll);
-
- *n_rules = 0;
- return -1;
+ table_rule_add_bulk(table, list, *n_rules_added);
+ *n_rules_not_added = table_rule_list_free(list);
+ return 0;
}
/* Allocate request */
req = pipeline_msg_alloc();
- if (req == NULL)
- return -1;
+ if (req == NULL) {
+ table_rule_list_free(list);
+ return -ENOMEM;
+ }
/* Write request */
req->type = PIPELINE_REQ_TABLE_RULE_ADD_BULK;
req->id = table_id;
- req->table_rule_add_bulk.match = match;
- req->table_rule_add_bulk.action = action;
- req->table_rule_add_bulk.data = data;
- req->table_rule_add_bulk.n_rules = *n_rules;
- req->table_rule_add_bulk.bulk =
- (p->table[table_id].params.match_type == TABLE_ACL) ? 1 : 0;
+ req->table_rule_add_bulk.list = list;
+ req->table_rule_add_bulk.bulk = table->params.match_type == TABLE_ACL;
/* Send request and wait for response */
rsp = pipeline_msg_send_recv(p, req);
- if (rsp == NULL)
- return -1;
+ if (rsp == NULL) {
+ table_rule_list_free(list);
+ return -ENOMEM;
+ }
/* Read response */
status = rsp->status;
- if (status == 0)
- *n_rules = rsp->table_rule_add_bulk.n_rules;
+ if (status == 0) {
+ *n_rules_added = rsp->table_rule_add_bulk.n_rules;
+
+ table_rule_add_bulk(table, list, *n_rules_added);
+ *n_rules_not_added = table_rule_list_free(list);
+ } else
+ table_rule_list_free(list);
+
/* Free response */
pipeline_msg_free(rsp);
@@ -2626,107 +2708,32 @@ static struct pipeline_msg_rsp *
pipeline_msg_handle_table_rule_add_bulk(struct pipeline_data *p,
struct pipeline_msg_req *req)
{
-
struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *) req;
uint32_t table_id = req->id;
- struct table_rule_match *match = req->table_rule_add_bulk.match;
- struct table_rule_action *action = req->table_rule_add_bulk.action;
- struct rte_pipeline_table_entry **data =
- (struct rte_pipeline_table_entry **)req->table_rule_add_bulk.data;
- uint32_t n_rules = req->table_rule_add_bulk.n_rules;
+ struct table_rule_list *list = req->table_rule_add_bulk.list;
uint32_t bulk = req->table_rule_add_bulk.bulk;
- struct rte_table_action *a = p->table_data[table_id].a;
- union table_rule_match_low_level *match_ll;
- uint8_t *action_ll;
- void **match_ll_ptr;
- struct rte_pipeline_table_entry **action_ll_ptr;
- int *found, status;
- uint32_t i;
-
- /* Memory allocation */
- match_ll = calloc(n_rules, sizeof(union table_rule_match_low_level));
- action_ll = calloc(n_rules, TABLE_RULE_ACTION_SIZE_MAX);
- match_ll_ptr = calloc(n_rules, sizeof(void *));
- action_ll_ptr =
- calloc(n_rules, sizeof(struct rte_pipeline_table_entry *));
- found = calloc(n_rules, sizeof(int));
-
- if ((match_ll == NULL) ||
- (action_ll == NULL) ||
- (match_ll_ptr == NULL) ||
- (action_ll_ptr == NULL) ||
- (found == NULL))
- goto fail;
-
- for (i = 0; i < n_rules; i++) {
- match_ll_ptr[i] = (void *)&match_ll[i];
- action_ll_ptr[i] =
- (struct rte_pipeline_table_entry *)&action_ll[i * TABLE_RULE_ACTION_SIZE_MAX];
- }
+ uint32_t n_rules_added;
+ int status;
- /* Rule match conversion */
- for (i = 0; i < n_rules; i++) {
- status = match_convert(&match[i], match_ll_ptr[i], 1);
- if (status)
- goto fail;
- }
+ struct table_ll table_ll = {
+ .p = p->p,
+ .table_id = table_id,
+ .a = p->table_data[table_id].a,
+ .bulk_supported = bulk,
+ };
- /* Rule action conversion */
- for (i = 0; i < n_rules; i++) {
- status = action_convert(a, &action[i], action_ll_ptr[i]);
- if (status)
- goto fail;
+ status = table_rule_add_bulk_ll(&table_ll, list, &n_rules_added);
+ if (status) {
+ rsp->status = -1;
+ rsp->table_rule_add_bulk.n_rules = 0;
+ return rsp;
}
- /* Add rule (match, action) to table */
- if (bulk) {
- status = rte_pipeline_table_entry_add_bulk(p->p,
- table_id,
- match_ll_ptr,
- action_ll_ptr,
- n_rules,
- found,
- data);
- if (status)
- n_rules = 0;
- } else
- for (i = 0; i < n_rules; i++) {
- status = rte_pipeline_table_entry_add(p->p,
- table_id,
- match_ll_ptr[i],
- action_ll_ptr[i],
- &found[i],
- &data[i]);
- if (status) {
- n_rules = i;
- break;
- }
- }
-
/* Write response */
rsp->status = 0;
- rsp->table_rule_add_bulk.n_rules = n_rules;
-
- /* Free */
- free(found);
- free(action_ll_ptr);
- free(match_ll_ptr);
- free(action_ll);
- free(match_ll);
-
- return rsp;
-
-fail:
- free(found);
- free(action_ll_ptr);
- free(match_ll_ptr);
- free(action_ll);
- free(match_ll);
-
- rsp->status = -1;
- rsp->table_rule_add_bulk.n_rules = 0;
+ rsp->table_rule_add_bulk.n_rules = n_rules_added;
return rsp;
}