X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=examples%2Fip_pipeline%2Fthread.c;h=adb83167cd842d41a603379c2cbe782ffc309fa1;hb=5d4a54fd1646585adfedb1675e78a513cf194b25;hp=3f5e15e6a391ab367a4d7759e02dbb305fb7a50a;hpb=3186282f8e12dad3e1b1b8b287a9d62d31886c01;p=dpdk.git diff --git a/examples/ip_pipeline/thread.c b/examples/ip_pipeline/thread.c index 3f5e15e6a3..adb83167cd 100644 --- a/examples/ip_pipeline/thread.c +++ b/examples/ip_pipeline/thread.c @@ -155,6 +155,29 @@ thread_init(void) return 0; } +static inline int +thread_is_running(uint32_t thread_id) +{ + enum rte_lcore_state_t thread_state; + + thread_state = rte_eal_get_lcore_state(thread_id); + return (thread_state == RUNNING) ? 1 : 0; +} + +/** + * Pipeline is running when: + * (A) Pipeline is mapped to a data plane thread AND + * (B) Its data plane thread is in RUNNING state. + */ +static inline int +pipeline_is_running(struct pipeline *p) +{ + if (p->enabled == 0) + return 0; + + return thread_is_running(p->thread_id); +} + /** * Master thread & data plane threads: message passing */ @@ -254,6 +277,36 @@ thread_pipeline_enable(uint32_t thread_id, p->enabled) return -1; + if (!thread_is_running(thread_id)) { + struct thread_data *td = &thread_data[thread_id]; + struct pipeline_data *tdp = &td->pipeline_data[td->n_pipelines]; + + if (td->n_pipelines >= THREAD_PIPELINES_MAX) + return -1; + + /* Data plane thread */ + td->p[td->n_pipelines] = p->p; + + tdp->p = p->p; + for (i = 0; i < p->n_tables; i++) + tdp->table_data[i].a = p->table[i].a; + + tdp->n_tables = p->n_tables; + + tdp->msgq_req = p->msgq_req; + tdp->msgq_rsp = p->msgq_rsp; + tdp->timer_period = (rte_get_tsc_hz() * p->timer_period_ms) / 1000; + tdp->time_next = rte_get_tsc_cycles() + tdp->timer_period; + + td->n_pipelines++; + + /* Pipeline */ + p->thread_id = thread_id; + p->enabled = 1; + + return 0; + } + /* Allocate request */ req = thread_msg_alloc(); if (req == NULL) @@ -272,8 +325,6 @@ thread_pipeline_enable(uint32_t thread_id, /* Send request and wait for response */ rsp = thread_msg_send_recv(thread_id, req); - if (rsp == NULL) - return -1; /* Read response */ status = rsp->status; @@ -316,6 +367,38 @@ thread_pipeline_disable(uint32_t thread_id, if (p->thread_id != thread_id) return -1; + if (!thread_is_running(thread_id)) { + struct thread_data *td = &thread_data[thread_id]; + uint32_t i; + + for (i = 0; i < td->n_pipelines; i++) { + struct pipeline_data *tdp = &td->pipeline_data[i]; + + if (tdp->p != p->p) + continue; + + /* Data plane thread */ + if (i < td->n_pipelines - 1) { + struct rte_pipeline *pipeline_last = + td->p[td->n_pipelines - 1]; + struct pipeline_data *tdp_last = + &td->pipeline_data[td->n_pipelines - 1]; + + td->p[i] = pipeline_last; + memcpy(tdp, tdp_last, sizeof(*tdp)); + } + + td->n_pipelines--; + + /* Pipeline */ + p->enabled = 0; + + break; + } + + return 0; + } + /* Allocate request */ req = thread_msg_alloc(); if (req == NULL) @@ -327,8 +410,6 @@ thread_pipeline_disable(uint32_t thread_id, /* Send request and wait for response */ rsp = thread_msg_send_recv(thread_id, req); - if (rsp == NULL) - return -1; /* Read response */ status = rsp->status; @@ -493,6 +574,13 @@ enum pipeline_req_type { PIPELINE_REQ_TABLE_RULE_ADD_BULK, PIPELINE_REQ_TABLE_RULE_DELETE, PIPELINE_REQ_TABLE_RULE_DELETE_DEFAULT, + PIPELINE_REQ_TABLE_RULE_STATS_READ, + PIPELINE_REQ_TABLE_MTR_PROFILE_ADD, + PIPELINE_REQ_TABLE_MTR_PROFILE_DELETE, + PIPELINE_REQ_TABLE_RULE_MTR_READ, + PIPELINE_REQ_TABLE_DSCP_TABLE_UPDATE, + PIPELINE_REQ_TABLE_RULE_TTL_READ, + PIPELINE_REQ_TABLE_RULE_TIME_READ, PIPELINE_REQ_MAX }; @@ -518,10 +606,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; }; @@ -529,6 +614,40 @@ struct pipeline_msg_req_table_rule_delete { struct table_rule_match match; }; +struct pipeline_msg_req_table_rule_stats_read { + void *data; + int clear; +}; + +struct pipeline_msg_req_table_mtr_profile_add { + uint32_t meter_profile_id; + struct rte_table_action_meter_profile profile; +}; + +struct pipeline_msg_req_table_mtr_profile_delete { + uint32_t meter_profile_id; +}; + +struct pipeline_msg_req_table_rule_mtr_read { + void *data; + uint32_t tc_mask; + int clear; +}; + +struct pipeline_msg_req_table_dscp_table_update { + uint64_t dscp_mask; + struct rte_table_action_dscp_table dscp_table; +}; + +struct pipeline_msg_req_table_rule_ttl_read { + void *data; + int clear; +}; + +struct pipeline_msg_req_table_rule_time_read { + void *data; +}; + struct pipeline_msg_req { enum pipeline_req_type type; uint32_t id; /* Port IN, port OUT or table ID */ @@ -542,6 +661,13 @@ struct pipeline_msg_req { struct pipeline_msg_req_table_rule_add_default table_rule_add_default; struct pipeline_msg_req_table_rule_add_bulk table_rule_add_bulk; struct pipeline_msg_req_table_rule_delete table_rule_delete; + struct pipeline_msg_req_table_rule_stats_read table_rule_stats_read; + struct pipeline_msg_req_table_mtr_profile_add table_mtr_profile_add; + struct pipeline_msg_req_table_mtr_profile_delete table_mtr_profile_delete; + struct pipeline_msg_req_table_rule_mtr_read table_rule_mtr_read; + struct pipeline_msg_req_table_dscp_table_update table_dscp_table_update; + struct pipeline_msg_req_table_rule_ttl_read table_rule_ttl_read; + struct pipeline_msg_req_table_rule_time_read table_rule_time_read; }; }; @@ -569,6 +695,22 @@ struct pipeline_msg_rsp_table_rule_add_bulk { uint32_t n_rules; }; +struct pipeline_msg_rsp_table_rule_stats_read { + struct rte_table_action_stats_counters stats; +}; + +struct pipeline_msg_rsp_table_rule_mtr_read { + struct rte_table_action_mtr_counters stats; +}; + +struct pipeline_msg_rsp_table_rule_ttl_read { + struct rte_table_action_ttl_counters stats; +}; + +struct pipeline_msg_rsp_table_rule_time_read { + uint64_t timestamp; +}; + struct pipeline_msg_rsp { int status; @@ -580,6 +722,10 @@ struct pipeline_msg_rsp { struct pipeline_msg_rsp_table_rule_add table_rule_add; struct pipeline_msg_rsp_table_rule_add_default table_rule_add_default; struct pipeline_msg_rsp_table_rule_add_bulk table_rule_add_bulk; + struct pipeline_msg_rsp_table_rule_stats_read table_rule_stats_read; + struct pipeline_msg_rsp_table_rule_mtr_read table_rule_mtr_read; + struct pipeline_msg_rsp_table_rule_ttl_read table_rule_ttl_read; + struct pipeline_msg_rsp_table_rule_time_read table_rule_time_read; }; }; @@ -641,10 +787,18 @@ pipeline_port_in_stats_read(const char *pipeline_name, p = pipeline_find(pipeline_name); if ((p == NULL) || - (p->enabled == 0) || (port_id >= p->n_ports_in)) return -1; + if (!pipeline_is_running(p)) { + status = rte_pipeline_port_in_stats_read(p->p, + port_id, + stats, + clear); + + return status; + } + /* Allocate request */ req = pipeline_msg_alloc(); if (req == NULL) @@ -657,12 +811,10 @@ pipeline_port_in_stats_read(const char *pipeline_name, /* Send request and wait for response */ rsp = pipeline_msg_send_recv(p, req); - if (rsp == NULL) - return -1; /* Read response */ status = rsp->status; - if (status) + if (status == 0) memcpy(stats, &rsp->port_in_stats_read.stats, sizeof(*stats)); /* Free response */ @@ -686,10 +838,14 @@ pipeline_port_in_enable(const char *pipeline_name, p = pipeline_find(pipeline_name); if ((p == NULL) || - (p->enabled == 0) || (port_id >= p->n_ports_in)) return -1; + if (!pipeline_is_running(p)) { + status = rte_pipeline_port_in_enable(p->p, port_id); + return status; + } + /* Allocate request */ req = pipeline_msg_alloc(); if (req == NULL) @@ -701,8 +857,6 @@ pipeline_port_in_enable(const char *pipeline_name, /* Send request and wait for response */ rsp = pipeline_msg_send_recv(p, req); - if (rsp == NULL) - return -1; /* Read response */ status = rsp->status; @@ -728,10 +882,14 @@ pipeline_port_in_disable(const char *pipeline_name, p = pipeline_find(pipeline_name); if ((p == NULL) || - (p->enabled == 0) || (port_id >= p->n_ports_in)) return -1; + if (!pipeline_is_running(p)) { + status = rte_pipeline_port_in_disable(p->p, port_id); + return status; + } + /* Allocate request */ req = pipeline_msg_alloc(); if (req == NULL) @@ -743,8 +901,6 @@ pipeline_port_in_disable(const char *pipeline_name, /* Send request and wait for response */ rsp = pipeline_msg_send_recv(p, req); - if (rsp == NULL) - return -1; /* Read response */ status = rsp->status; @@ -773,10 +929,18 @@ pipeline_port_out_stats_read(const char *pipeline_name, p = pipeline_find(pipeline_name); if ((p == NULL) || - (p->enabled == 0) || (port_id >= p->n_ports_out)) return -1; + if (!pipeline_is_running(p)) { + status = rte_pipeline_port_out_stats_read(p->p, + port_id, + stats, + clear); + + return status; + } + /* Allocate request */ req = pipeline_msg_alloc(); if (req == NULL) @@ -789,12 +953,10 @@ pipeline_port_out_stats_read(const char *pipeline_name, /* Send request and wait for response */ rsp = pipeline_msg_send_recv(p, req); - if (rsp == NULL) - return -1; /* Read response */ status = rsp->status; - if (status) + if (status == 0) memcpy(stats, &rsp->port_out_stats_read.stats, sizeof(*stats)); /* Free response */ @@ -821,10 +983,18 @@ pipeline_table_stats_read(const char *pipeline_name, p = pipeline_find(pipeline_name); if ((p == NULL) || - (p->enabled == 0) || (table_id >= p->n_tables)) return -1; + if (!pipeline_is_running(p)) { + status = rte_pipeline_table_stats_read(p->p, + table_id, + stats, + clear); + + return status; + } + /* Allocate request */ req = pipeline_msg_alloc(); if (req == NULL) @@ -837,12 +1007,10 @@ pipeline_table_stats_read(const char *pipeline_name, /* Send request and wait for response */ rsp = pipeline_msg_send_recv(p, req); - if (rsp == NULL) - return -1; /* Read response */ status = rsp->status; - if (status) + if (status == 0) memcpy(stats, &rsp->table_stats_read.stats, sizeof(*stats)); /* Free response */ @@ -1013,37 +1181,238 @@ action_default_check(struct table_rule_action *action, return 0; } +union table_rule_match_low_level { + struct rte_table_acl_rule_add_params acl_add; + struct rte_table_acl_rule_delete_params acl_delete; + struct rte_table_array_key array; + uint8_t hash[TABLE_RULE_MATCH_SIZE_MAX]; + struct rte_table_lpm_key lpm_ipv4; + struct rte_table_lpm_ipv6_key lpm_ipv6; +}; + +static int +match_convert(struct table_rule_match *mh, + union table_rule_match_low_level *ml, + int add); + +static int +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, struct table_rule_match *match, - struct table_rule_action *action, - void **data) + struct table_rule_action *action) { struct pipeline *p; + struct table *table; struct pipeline_msg_req *req; struct pipeline_msg_rsp *rsp; + struct table_rule *rule; int status; /* Check input params */ if ((pipeline_name == NULL) || (match == NULL) || - (action == NULL) || - (data == NULL)) + (action == NULL)) return -1; p = pipeline_find(pipeline_name); if ((p == NULL) || - (p->enabled == 0) || (table_id >= p->n_tables) || match_check(match, p, table_id) || action_check(action, p, table_id)) return -1; + table = &p->table[table_id]; + + rule = calloc(1, sizeof(struct table_rule)); + if (rule == NULL) + return -1; + + memcpy(&rule->match, match, sizeof(*match)); + memcpy(&rule->action, action, sizeof(*action)); + + if (!pipeline_is_running(p)) { + union table_rule_match_low_level match_ll; + struct rte_pipeline_table_entry *data_in, *data_out; + int key_found; + uint8_t *buffer; + + buffer = calloc(TABLE_RULE_ACTION_SIZE_MAX, sizeof(uint8_t)); + if (buffer == NULL) { + free(rule); + return -1; + } + + /* Table match-action rule conversion */ + data_in = (struct rte_pipeline_table_entry *)buffer; + + status = match_convert(match, &match_ll, 1); + if (status) { + free(buffer); + free(rule); + return -1; + } + + status = action_convert(table->a, action, data_in); + if (status) { + free(buffer); + free(rule); + return -1; + } + + /* Add rule (match, action) to table */ + status = rte_pipeline_table_entry_add(p->p, + table_id, + &match_ll, + data_in, + &key_found, + &data_out); + if (status) { + free(buffer); + free(rule); + return -1; + } + + /* Write Response */ + rule->data = data_out; + table_rule_add(table, rule); + + free(buffer); + return 0; + } + /* Allocate request */ req = pipeline_msg_alloc(); - if (req == NULL) + if (req == NULL) { + free(rule); return -1; + } /* Write request */ req->type = PIPELINE_REQ_TABLE_RULE_ADD; @@ -1053,13 +1422,14 @@ pipeline_table_rule_add(const char *pipeline_name, /* Send request and wait for response */ rsp = pipeline_msg_send_recv(p, req); - if (rsp == NULL) - return -1; /* Read response */ status = rsp->status; - if (status == 0) - *data = rsp->table_rule_add.data; + if (status == 0) { + rule->data = rsp->table_rule_add.data; + table_rule_add(table, rule); + } else + free(rule); /* Free response */ pipeline_msg_free(rsp); @@ -1070,31 +1440,78 @@ pipeline_table_rule_add(const char *pipeline_name, int pipeline_table_rule_add_default(const char *pipeline_name, uint32_t table_id, - struct table_rule_action *action, - void **data) + struct table_rule_action *action) { struct pipeline *p; + struct table *table; struct pipeline_msg_req *req; struct pipeline_msg_rsp *rsp; + struct table_rule *rule; int status; /* Check input params */ if ((pipeline_name == NULL) || - (action == NULL) || - (data == NULL)) + (action == NULL)) return -1; p = pipeline_find(pipeline_name); if ((p == NULL) || - (p->enabled == 0) || (table_id >= p->n_tables) || action_default_check(action, p, table_id)) return -1; + table = &p->table[table_id]; + + rule = calloc(1, sizeof(struct table_rule)); + if (rule == NULL) + return -1; + + memcpy(&rule->action, action, sizeof(*action)); + + if (!pipeline_is_running(p)) { + struct rte_pipeline_table_entry *data_in, *data_out; + uint8_t *buffer; + + buffer = calloc(TABLE_RULE_ACTION_SIZE_MAX, sizeof(uint8_t)); + if (buffer == NULL) { + free(rule); + return -1; + } + + /* Apply actions */ + data_in = (struct rte_pipeline_table_entry *)buffer; + + data_in->action = action->fwd.action; + if (action->fwd.action == RTE_PIPELINE_ACTION_PORT) + data_in->port_id = action->fwd.id; + if (action->fwd.action == RTE_PIPELINE_ACTION_TABLE) + data_in->table_id = action->fwd.id; + + /* Add default rule to table */ + status = rte_pipeline_table_default_entry_add(p->p, + table_id, + data_in, + &data_out); + if (status) { + free(buffer); + free(rule); + return -1; + } + + /* Write Response */ + rule->data = data_out; + table_rule_default_add(table, rule); + + free(buffer); + return 0; + } + /* Allocate request */ req = pipeline_msg_alloc(); - if (req == NULL) + if (req == NULL) { + free(rule); return -1; + } /* Write request */ req->type = PIPELINE_REQ_TABLE_RULE_ADD_DEFAULT; @@ -1103,13 +1520,14 @@ pipeline_table_rule_add_default(const char *pipeline_name, /* Send request and wait for response */ rsp = pipeline_msg_send_recv(p, req); - if (rsp == NULL) - return -1; /* Read response */ status = rsp->status; - if (status == 0) - *data = rsp->table_rule_add_default.data; + if (status == 0) { + rule->data = rsp->table_rule_add_default.data; + table_rule_default_add(table, rule); + } else + free(rule); /* Free response */ pipeline_msg_free(rsp); @@ -1117,64 +1535,115 @@ 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) || - (p->enabled == 0) || - (table_id >= p->n_tables)) - return -1; + (table_id >= p->n_tables)) { + table_rule_list_free(list); + return -EINVAL; + } - for (i = 0; i < *n_rules; i++) - if (match_check(match, p, table_id) || - action_check(action, p, table_id)) - return -1; + table = &p->table[table_id]; + + 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; + } + + 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; + } + + 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; /* 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); @@ -1188,6 +1657,7 @@ pipeline_table_rule_delete(const char *pipeline_name, struct table_rule_match *match) { struct pipeline *p; + struct table *table; struct pipeline_msg_req *req; struct pipeline_msg_rsp *rsp; int status; @@ -1199,11 +1669,32 @@ pipeline_table_rule_delete(const char *pipeline_name, p = pipeline_find(pipeline_name); if ((p == NULL) || - (p->enabled == 0) || (table_id >= p->n_tables) || match_check(match, p, table_id)) return -1; + table = &p->table[table_id]; + + if (!pipeline_is_running(p)) { + union table_rule_match_low_level match_ll; + int key_found; + + status = match_convert(match, &match_ll, 0); + if (status) + return -1; + + status = rte_pipeline_table_entry_delete(p->p, + table_id, + &match_ll, + &key_found, + NULL); + + if (status == 0) + table_rule_delete(table, match); + + return status; + } + /* Allocate request */ req = pipeline_msg_alloc(); if (req == NULL) @@ -1216,11 +1707,11 @@ pipeline_table_rule_delete(const char *pipeline_name, /* Send request and wait for response */ rsp = pipeline_msg_send_recv(p, req); - if (rsp == NULL) - return -1; /* Read response */ status = rsp->status; + if (status == 0) + table_rule_delete(table, match); /* Free response */ pipeline_msg_free(rsp); @@ -1233,6 +1724,7 @@ pipeline_table_rule_delete_default(const char *pipeline_name, uint32_t table_id) { struct pipeline *p; + struct table *table; struct pipeline_msg_req *req; struct pipeline_msg_rsp *rsp; int status; @@ -1243,10 +1735,22 @@ pipeline_table_rule_delete_default(const char *pipeline_name, p = pipeline_find(pipeline_name); if ((p == NULL) || - (p->enabled == 0) || (table_id >= p->n_tables)) return -1; + table = &p->table[table_id]; + + if (!pipeline_is_running(p)) { + status = rte_pipeline_table_default_entry_delete(p->p, + table_id, + NULL); + + if (status == 0) + table_rule_default_delete(table); + + return status; + } + /* Allocate request */ req = pipeline_msg_alloc(); if (req == NULL) @@ -1258,9 +1762,303 @@ pipeline_table_rule_delete_default(const char *pipeline_name, /* Send request and wait for response */ rsp = pipeline_msg_send_recv(p, req); - if (rsp == NULL) + + /* Read response */ + status = rsp->status; + if (status == 0) + table_rule_default_delete(table); + + /* Free response */ + pipeline_msg_free(rsp); + + return status; +} + +int +pipeline_table_rule_stats_read(const char *pipeline_name, + uint32_t table_id, + struct table_rule_match *match, + struct rte_table_action_stats_counters *stats, + int clear) +{ + struct pipeline *p; + struct table *table; + struct pipeline_msg_req *req; + struct pipeline_msg_rsp *rsp; + struct table_rule *rule; + int status; + + /* Check input params */ + if ((pipeline_name == NULL) || + (match == NULL) || + (stats == NULL)) + return -1; + + p = pipeline_find(pipeline_name); + if ((p == NULL) || + (table_id >= p->n_tables) || + match_check(match, p, table_id)) + return -1; + + table = &p->table[table_id]; + rule = table_rule_find(table, match); + if (rule == NULL) + return -1; + + if (!pipeline_is_running(p)) { + status = rte_table_action_stats_read(table->a, + rule->data, + stats, + clear); + + return status; + } + + /* Allocate request */ + req = pipeline_msg_alloc(); + if (req == NULL) + return -1; + + /* Write request */ + req->type = PIPELINE_REQ_TABLE_RULE_STATS_READ; + req->id = table_id; + req->table_rule_stats_read.data = rule->data; + req->table_rule_stats_read.clear = clear; + + /* Send request and wait for response */ + rsp = pipeline_msg_send_recv(p, req); + + /* Read response */ + status = rsp->status; + if (status == 0) + memcpy(stats, &rsp->table_rule_stats_read.stats, sizeof(*stats)); + + /* Free response */ + pipeline_msg_free(rsp); + + return status; +} + +int +pipeline_table_mtr_profile_add(const char *pipeline_name, + uint32_t table_id, + uint32_t meter_profile_id, + struct rte_table_action_meter_profile *profile) +{ + struct pipeline *p; + struct pipeline_msg_req *req; + struct pipeline_msg_rsp *rsp; + int status; + + /* Check input params */ + if ((pipeline_name == NULL) || + (profile == NULL)) + return -1; + + p = pipeline_find(pipeline_name); + if ((p == NULL) || + (table_id >= p->n_tables)) + return -1; + + if (!pipeline_is_running(p)) { + struct rte_table_action *a = p->table[table_id].a; + + status = rte_table_action_meter_profile_add(a, + meter_profile_id, + profile); + + return status; + } + + /* Allocate request */ + req = pipeline_msg_alloc(); + if (req == NULL) + return -1; + + /* Write request */ + req->type = PIPELINE_REQ_TABLE_MTR_PROFILE_ADD; + req->id = table_id; + req->table_mtr_profile_add.meter_profile_id = meter_profile_id; + memcpy(&req->table_mtr_profile_add.profile, profile, sizeof(*profile)); + + /* Send request and wait for response */ + rsp = pipeline_msg_send_recv(p, req); + + /* Read response */ + status = rsp->status; + + /* Free response */ + pipeline_msg_free(rsp); + + return status; +} + +int +pipeline_table_mtr_profile_delete(const char *pipeline_name, + uint32_t table_id, + uint32_t meter_profile_id) +{ + struct pipeline *p; + struct pipeline_msg_req *req; + struct pipeline_msg_rsp *rsp; + int status; + + /* Check input params */ + if (pipeline_name == NULL) + return -1; + + p = pipeline_find(pipeline_name); + if ((p == NULL) || + (table_id >= p->n_tables)) + return -1; + + if (!pipeline_is_running(p)) { + struct rte_table_action *a = p->table[table_id].a; + + status = rte_table_action_meter_profile_delete(a, + meter_profile_id); + + return status; + } + + /* Allocate request */ + req = pipeline_msg_alloc(); + if (req == NULL) + return -1; + + /* Write request */ + req->type = PIPELINE_REQ_TABLE_MTR_PROFILE_DELETE; + req->id = table_id; + req->table_mtr_profile_delete.meter_profile_id = meter_profile_id; + + /* Send request and wait for response */ + rsp = pipeline_msg_send_recv(p, req); + + /* Read response */ + status = rsp->status; + + /* Free response */ + pipeline_msg_free(rsp); + + return status; +} + +int +pipeline_table_rule_mtr_read(const char *pipeline_name, + uint32_t table_id, + struct table_rule_match *match, + struct rte_table_action_mtr_counters *stats, + int clear) +{ + struct pipeline *p; + struct table *table; + struct pipeline_msg_req *req; + struct pipeline_msg_rsp *rsp; + struct table_rule *rule; + uint32_t tc_mask; + int status; + + /* Check input params */ + if ((pipeline_name == NULL) || + (match == NULL) || + (stats == NULL)) + return -1; + + p = pipeline_find(pipeline_name); + if ((p == NULL) || + (table_id >= p->n_tables) || + match_check(match, p, table_id)) + return -1; + + table = &p->table[table_id]; + tc_mask = (1 << table->ap->params.mtr.n_tc) - 1; + + rule = table_rule_find(table, match); + if (rule == NULL) + return -1; + + if (!pipeline_is_running(p)) { + status = rte_table_action_meter_read(table->a, + rule->data, + tc_mask, + stats, + clear); + + return status; + } + + /* Allocate request */ + req = pipeline_msg_alloc(); + if (req == NULL) + return -1; + + /* Write request */ + req->type = PIPELINE_REQ_TABLE_RULE_MTR_READ; + req->id = table_id; + req->table_rule_mtr_read.data = rule->data; + req->table_rule_mtr_read.tc_mask = tc_mask; + req->table_rule_mtr_read.clear = clear; + + /* Send request and wait for response */ + rsp = pipeline_msg_send_recv(p, req); + + /* Read response */ + status = rsp->status; + if (status == 0) + memcpy(stats, &rsp->table_rule_mtr_read.stats, sizeof(*stats)); + + /* Free response */ + pipeline_msg_free(rsp); + + return status; +} + +int +pipeline_table_dscp_table_update(const char *pipeline_name, + uint32_t table_id, + uint64_t dscp_mask, + struct rte_table_action_dscp_table *dscp_table) +{ + struct pipeline *p; + struct pipeline_msg_req *req; + struct pipeline_msg_rsp *rsp; + int status; + + /* Check input params */ + if ((pipeline_name == NULL) || + (dscp_table == NULL)) return -1; + p = pipeline_find(pipeline_name); + if ((p == NULL) || + (table_id >= p->n_tables)) + return -1; + + if (!pipeline_is_running(p)) { + struct rte_table_action *a = p->table[table_id].a; + + status = rte_table_action_dscp_table_update(a, + dscp_mask, + dscp_table); + + return status; + } + + /* Allocate request */ + req = pipeline_msg_alloc(); + if (req == NULL) + return -1; + + /* Write request */ + req->type = PIPELINE_REQ_TABLE_DSCP_TABLE_UPDATE; + req->id = table_id; + req->table_dscp_table_update.dscp_mask = dscp_mask; + memcpy(&req->table_dscp_table_update.dscp_table, + dscp_table, sizeof(*dscp_table)); + + /* Send request and wait for response */ + rsp = pipeline_msg_send_recv(p, req); + /* Read response */ status = rsp->status; @@ -1270,6 +2068,137 @@ pipeline_table_rule_delete_default(const char *pipeline_name, return status; } +int +pipeline_table_rule_ttl_read(const char *pipeline_name, + uint32_t table_id, + struct table_rule_match *match, + struct rte_table_action_ttl_counters *stats, + int clear) +{ + struct pipeline *p; + struct table *table; + struct pipeline_msg_req *req; + struct pipeline_msg_rsp *rsp; + struct table_rule *rule; + int status; + + /* Check input params */ + if ((pipeline_name == NULL) || + (match == NULL) || + (stats == NULL)) + return -1; + + p = pipeline_find(pipeline_name); + if ((p == NULL) || + (table_id >= p->n_tables) || + match_check(match, p, table_id)) + return -1; + + table = &p->table[table_id]; + if (!table->ap->params.ttl.n_packets_enabled) + return -1; + + rule = table_rule_find(table, match); + if (rule == NULL) + return -1; + + if (!pipeline_is_running(p)) { + status = rte_table_action_ttl_read(table->a, + rule->data, + stats, + clear); + + return status; + } + + /* Allocate request */ + req = pipeline_msg_alloc(); + if (req == NULL) + return -1; + + /* Write request */ + req->type = PIPELINE_REQ_TABLE_RULE_TTL_READ; + req->id = table_id; + req->table_rule_ttl_read.data = rule->data; + req->table_rule_ttl_read.clear = clear; + + /* Send request and wait for response */ + rsp = pipeline_msg_send_recv(p, req); + + /* Read response */ + status = rsp->status; + if (status == 0) + memcpy(stats, &rsp->table_rule_ttl_read.stats, sizeof(*stats)); + + /* Free response */ + pipeline_msg_free(rsp); + + return status; +} + +int +pipeline_table_rule_time_read(const char *pipeline_name, + uint32_t table_id, + struct table_rule_match *match, + uint64_t *timestamp) +{ + struct pipeline *p; + struct table *table; + struct pipeline_msg_req *req; + struct pipeline_msg_rsp *rsp; + struct table_rule *rule; + int status; + + /* Check input params */ + if ((pipeline_name == NULL) || + (match == NULL) || + (timestamp == NULL)) + return -1; + + p = pipeline_find(pipeline_name); + if ((p == NULL) || + (table_id >= p->n_tables) || + match_check(match, p, table_id)) + return -1; + + table = &p->table[table_id]; + + rule = table_rule_find(table, match); + if (rule == NULL) + return -1; + + if (!pipeline_is_running(p)) { + status = rte_table_action_time_read(table->a, + rule->data, + timestamp); + + return status; + } + + /* Allocate request */ + req = pipeline_msg_alloc(); + if (req == NULL) + return -1; + + /* Write request */ + req->type = PIPELINE_REQ_TABLE_RULE_TIME_READ; + req->id = table_id; + req->table_rule_time_read.data = rule->data; + + /* Send request and wait for response */ + rsp = pipeline_msg_send_recv(p, req); + + /* Read response */ + status = rsp->status; + if (status == 0) + *timestamp = rsp->table_rule_time_read.timestamp; + + /* Free response */ + pipeline_msg_free(rsp); + + return status; +} + /** * Data plane threads: message handling */ @@ -1371,15 +2300,6 @@ pipeline_msg_handle_table_stats_read(struct pipeline_data *p, return rsp; } -union table_rule_match_low_level { - struct rte_table_acl_rule_add_params acl_add; - struct rte_table_acl_rule_delete_params acl_delete; - struct rte_table_array_key array; - uint8_t hash[TABLE_RULE_MATCH_SIZE_MAX]; - struct rte_table_lpm_key lpm_ipv4; - struct rte_table_lpm_ipv6_key lpm_ipv6; -}; - static int match_convert_ipv6_depth(uint32_t depth, uint32_t *depth32) { @@ -1517,29 +2437,37 @@ match_convert(struct table_rule_match *mh, ml->acl_add.field_value[0].mask_range.u8 = mh->match.acl.proto_mask; - ml->acl_add.field_value[1].value.u32 = sa32[0]; + ml->acl_add.field_value[1].value.u32 = + rte_be_to_cpu_32(sa32[0]); ml->acl_add.field_value[1].mask_range.u32 = sa32_depth[0]; - ml->acl_add.field_value[2].value.u32 = sa32[1]; + ml->acl_add.field_value[2].value.u32 = + rte_be_to_cpu_32(sa32[1]); ml->acl_add.field_value[2].mask_range.u32 = sa32_depth[1]; - ml->acl_add.field_value[3].value.u32 = sa32[2]; + ml->acl_add.field_value[3].value.u32 = + rte_be_to_cpu_32(sa32[2]); ml->acl_add.field_value[3].mask_range.u32 = sa32_depth[2]; - ml->acl_add.field_value[4].value.u32 = sa32[3]; + ml->acl_add.field_value[4].value.u32 = + rte_be_to_cpu_32(sa32[3]); ml->acl_add.field_value[4].mask_range.u32 = sa32_depth[3]; - ml->acl_add.field_value[5].value.u32 = da32[0]; + ml->acl_add.field_value[5].value.u32 = + rte_be_to_cpu_32(da32[0]); ml->acl_add.field_value[5].mask_range.u32 = da32_depth[0]; - ml->acl_add.field_value[6].value.u32 = da32[1]; + ml->acl_add.field_value[6].value.u32 = + rte_be_to_cpu_32(da32[1]); ml->acl_add.field_value[6].mask_range.u32 = da32_depth[1]; - ml->acl_add.field_value[7].value.u32 = da32[2]; + ml->acl_add.field_value[7].value.u32 = + rte_be_to_cpu_32(da32[2]); ml->acl_add.field_value[7].mask_range.u32 = da32_depth[2]; - ml->acl_add.field_value[8].value.u32 = da32[3]; + ml->acl_add.field_value[8].value.u32 = + rte_be_to_cpu_32(da32[3]); ml->acl_add.field_value[8].mask_range.u32 = da32_depth[3]; @@ -1581,36 +2509,36 @@ match_convert(struct table_rule_match *mh, mh->match.acl.proto_mask; ml->acl_delete.field_value[1].value.u32 = - sa32[0]; + rte_be_to_cpu_32(sa32[0]); ml->acl_delete.field_value[1].mask_range.u32 = sa32_depth[0]; ml->acl_delete.field_value[2].value.u32 = - sa32[1]; + rte_be_to_cpu_32(sa32[1]); ml->acl_delete.field_value[2].mask_range.u32 = sa32_depth[1]; ml->acl_delete.field_value[3].value.u32 = - sa32[2]; + rte_be_to_cpu_32(sa32[2]); ml->acl_delete.field_value[3].mask_range.u32 = sa32_depth[2]; ml->acl_delete.field_value[4].value.u32 = - sa32[3]; + rte_be_to_cpu_32(sa32[3]); ml->acl_delete.field_value[4].mask_range.u32 = sa32_depth[3]; ml->acl_delete.field_value[5].value.u32 = - da32[0]; + rte_be_to_cpu_32(da32[0]); ml->acl_delete.field_value[5].mask_range.u32 = da32_depth[0]; ml->acl_delete.field_value[6].value.u32 = - da32[1]; + rte_be_to_cpu_32(da32[1]); ml->acl_delete.field_value[6].mask_range.u32 = da32_depth[1]; ml->acl_delete.field_value[7].value.u32 = - da32[2]; + rte_be_to_cpu_32(da32[2]); ml->acl_delete.field_value[7].mask_range.u32 = da32_depth[2]; ml->acl_delete.field_value[8].value.u32 = - da32[3]; + rte_be_to_cpu_32(da32[3]); ml->acl_delete.field_value[8].mask_range.u32 = da32_depth[3]; @@ -1651,126 +2579,166 @@ match_convert(struct table_rule_match *mh, } } -static struct pipeline_msg_rsp * -pipeline_msg_handle_table_rule_add(struct pipeline_data *p, - struct pipeline_msg_req *req) -{ - union table_rule_match_low_level match_ll; - struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *) req; - struct table_rule_match *match = &req->table_rule_add.match; - struct table_rule_action *action = &req->table_rule_add.action; - struct rte_pipeline_table_entry *data_in, *data_out; - uint32_t table_id = req->id; - int key_found, status; - struct rte_table_action *a = p->table_data[table_id].a; - - /* Apply actions */ - memset(p->buffer, 0, sizeof(p->buffer)); - data_in = (struct rte_pipeline_table_entry *) p->buffer; +static int +action_convert(struct rte_table_action *a, + struct table_rule_action *action, + struct rte_pipeline_table_entry *data) +{ + int status; + /* Apply actions */ if (action->action_mask & (1LLU << RTE_TABLE_ACTION_FWD)) { status = rte_table_action_apply(a, - data_in, + data, RTE_TABLE_ACTION_FWD, &action->fwd); - if (status) { - rsp->status = -1; - return rsp; - } + if (status) + return status; + } + + if (action->action_mask & (1LLU << RTE_TABLE_ACTION_LB)) { + status = rte_table_action_apply(a, + data, + RTE_TABLE_ACTION_LB, + &action->lb); + + if (status) + return status; } if (action->action_mask & (1LLU << RTE_TABLE_ACTION_MTR)) { status = rte_table_action_apply(a, - data_in, + data, RTE_TABLE_ACTION_MTR, &action->mtr); - if (status) { - rsp->status = -1; - return rsp; - } + if (status) + return status; } if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TM)) { status = rte_table_action_apply(a, - data_in, + data, RTE_TABLE_ACTION_TM, &action->tm); - if (status) { - rsp->status = -1; - return rsp; - } + if (status) + return status; } if (action->action_mask & (1LLU << RTE_TABLE_ACTION_ENCAP)) { status = rte_table_action_apply(a, - data_in, + data, RTE_TABLE_ACTION_ENCAP, &action->encap); - if (status) { - rsp->status = -1; - return rsp; - } + if (status) + return status; } if (action->action_mask & (1LLU << RTE_TABLE_ACTION_NAT)) { status = rte_table_action_apply(a, - data_in, + data, RTE_TABLE_ACTION_NAT, &action->nat); - if (status) { - rsp->status = -1; - return rsp; - } + if (status) + return status; } if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TTL)) { status = rte_table_action_apply(a, - data_in, + data, RTE_TABLE_ACTION_TTL, &action->ttl); - if (status) { - rsp->status = -1; - return rsp; - } + if (status) + return status; } if (action->action_mask & (1LLU << RTE_TABLE_ACTION_STATS)) { status = rte_table_action_apply(a, - data_in, + data, RTE_TABLE_ACTION_STATS, &action->stats); - if (status) { - rsp->status = -1; - return rsp; - } + if (status) + return status; } if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TIME)) { status = rte_table_action_apply(a, - data_in, + data, RTE_TABLE_ACTION_TIME, &action->time); - if (status) { - rsp->status = -1; - return rsp; - } + if (status) + return status; } - /* Add rule (match, action) to table */ + if (action->action_mask & (1LLU << RTE_TABLE_ACTION_SYM_CRYPTO)) { + status = rte_table_action_apply(a, + data, + RTE_TABLE_ACTION_SYM_CRYPTO, + &action->sym_crypto); + + if (status) + return status; + } + + if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TAG)) { + status = rte_table_action_apply(a, + data, + RTE_TABLE_ACTION_TAG, + &action->tag); + + if (status) + return status; + } + + if (action->action_mask & (1LLU << RTE_TABLE_ACTION_DECAP)) { + status = rte_table_action_apply(a, + data, + RTE_TABLE_ACTION_DECAP, + &action->decap); + + if (status) + return status; + } + + return 0; +} + +static struct pipeline_msg_rsp * +pipeline_msg_handle_table_rule_add(struct pipeline_data *p, + struct pipeline_msg_req *req) +{ + union table_rule_match_low_level match_ll; + struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *) req; + struct table_rule_match *match = &req->table_rule_add.match; + struct table_rule_action *action = &req->table_rule_add.action; + struct rte_pipeline_table_entry *data_in, *data_out; + uint32_t table_id = req->id; + int key_found, status; + struct rte_table_action *a = p->table_data[table_id].a; + + /* Apply actions */ + memset(p->buffer, 0, sizeof(p->buffer)); + data_in = (struct rte_pipeline_table_entry *) p->buffer; + status = match_convert(match, &match_ll, 1); if (status) { rsp->status = -1; return rsp; } + status = action_convert(a, action, data_in); + if (status) { + rsp->status = -1; + return rsp; + } + status = rte_pipeline_table_entry_add(p->p, table_id, &match_ll, @@ -1830,224 +2798,194 @@ 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; + uint32_t n_rules_added; + int status; - /* 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]; - } + struct table_ll table_ll = { + .p = p->p, + .table_id = table_id, + .a = p->table_data[table_id].a, + .bulk_supported = bulk, + }; - /* Rule match conversion */ - for (i = 0; i < n_rules; i++) { - status = match_convert(&match[i], match_ll_ptr[i], 1); - 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; } - /* Rule action conversion */ - for (i = 0; i < n_rules; i++) { - void *data_in = action_ll_ptr[i]; - struct table_rule_action *act = &action[i]; - - if (act->action_mask & (1LLU << RTE_TABLE_ACTION_FWD)) { - status = rte_table_action_apply(a, - data_in, - RTE_TABLE_ACTION_FWD, - &act->fwd); + /* Write response */ + rsp->status = 0; + rsp->table_rule_add_bulk.n_rules = n_rules_added; + return rsp; +} - if (status) - goto fail; - } +static struct pipeline_msg_rsp * +pipeline_msg_handle_table_rule_delete(struct pipeline_data *p, + struct pipeline_msg_req *req) +{ + union table_rule_match_low_level match_ll; + struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *) req; + struct table_rule_match *match = &req->table_rule_delete.match; + uint32_t table_id = req->id; + int key_found, status; - if (act->action_mask & (1LLU << RTE_TABLE_ACTION_MTR)) { - status = rte_table_action_apply(a, - data_in, - RTE_TABLE_ACTION_MTR, - &act->mtr); + status = match_convert(match, &match_ll, 0); + if (status) { + rsp->status = -1; + return rsp; + } - if (status) - goto fail; - } + rsp->status = rte_pipeline_table_entry_delete(p->p, + table_id, + &match_ll, + &key_found, + NULL); - if (act->action_mask & (1LLU << RTE_TABLE_ACTION_TM)) { - status = rte_table_action_apply(a, - data_in, - RTE_TABLE_ACTION_TM, - &act->tm); + return rsp; +} - if (status) - goto fail; - } +static struct pipeline_msg_rsp * +pipeline_msg_handle_table_rule_delete_default(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; - if (act->action_mask & (1LLU << RTE_TABLE_ACTION_ENCAP)) { - status = rte_table_action_apply(a, - data_in, - RTE_TABLE_ACTION_ENCAP, - &act->encap); + rsp->status = rte_pipeline_table_default_entry_delete(p->p, + table_id, + NULL); - if (status) - goto fail; - } + return rsp; +} - if (act->action_mask & (1LLU << RTE_TABLE_ACTION_NAT)) { - status = rte_table_action_apply(a, - data_in, - RTE_TABLE_ACTION_NAT, - &act->nat); +static struct pipeline_msg_rsp * +pipeline_msg_handle_table_rule_stats_read(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; + void *data = req->table_rule_stats_read.data; + int clear = req->table_rule_stats_read.clear; + struct rte_table_action *a = p->table_data[table_id].a; - if (status) - goto fail; - } + rsp->status = rte_table_action_stats_read(a, + data, + &rsp->table_rule_stats_read.stats, + clear); - if (act->action_mask & (1LLU << RTE_TABLE_ACTION_TTL)) { - status = rte_table_action_apply(a, - data_in, - RTE_TABLE_ACTION_TTL, - &act->ttl); + return rsp; +} - if (status) - goto fail; - } +static struct pipeline_msg_rsp * +pipeline_msg_handle_table_mtr_profile_add(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; + uint32_t meter_profile_id = req->table_mtr_profile_add.meter_profile_id; + struct rte_table_action_meter_profile *profile = + &req->table_mtr_profile_add.profile; + struct rte_table_action *a = p->table_data[table_id].a; - if (act->action_mask & (1LLU << RTE_TABLE_ACTION_STATS)) { - status = rte_table_action_apply(a, - data_in, - RTE_TABLE_ACTION_STATS, - &act->stats); + rsp->status = rte_table_action_meter_profile_add(a, + meter_profile_id, + profile); - if (status) - goto fail; - } + return rsp; +} - if (act->action_mask & (1LLU << RTE_TABLE_ACTION_TIME)) { - status = rte_table_action_apply(a, - data_in, - RTE_TABLE_ACTION_TIME, - &act->time); +static struct pipeline_msg_rsp * +pipeline_msg_handle_table_mtr_profile_delete(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; + uint32_t meter_profile_id = + req->table_mtr_profile_delete.meter_profile_id; + struct rte_table_action *a = p->table_data[table_id].a; - if (status) - goto fail; - } - } + rsp->status = rte_table_action_meter_profile_delete(a, + meter_profile_id); - /* 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; - } - } + return rsp; +} - /* Write response */ - rsp->status = 0; - rsp->table_rule_add_bulk.n_rules = n_rules; +static struct pipeline_msg_rsp * +pipeline_msg_handle_table_rule_mtr_read(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; + void *data = req->table_rule_mtr_read.data; + uint32_t tc_mask = req->table_rule_mtr_read.tc_mask; + int clear = req->table_rule_mtr_read.clear; + struct rte_table_action *a = p->table_data[table_id].a; - /* Free */ - free(found); - free(action_ll_ptr); - free(match_ll_ptr); - free(action_ll); - free(match_ll); + rsp->status = rte_table_action_meter_read(a, + data, + tc_mask, + &rsp->table_rule_mtr_read.stats, + clear); return rsp; +} -fail: - free(found); - free(action_ll_ptr); - free(match_ll_ptr); - free(action_ll); - free(match_ll); +static struct pipeline_msg_rsp * +pipeline_msg_handle_table_dscp_table_update(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; + uint64_t dscp_mask = req->table_dscp_table_update.dscp_mask; + struct rte_table_action_dscp_table *dscp_table = + &req->table_dscp_table_update.dscp_table; + struct rte_table_action *a = p->table_data[table_id].a; + + rsp->status = rte_table_action_dscp_table_update(a, + dscp_mask, + dscp_table); - rsp->status = -1; - rsp->table_rule_add_bulk.n_rules = 0; return rsp; } static struct pipeline_msg_rsp * -pipeline_msg_handle_table_rule_delete(struct pipeline_data *p, +pipeline_msg_handle_table_rule_ttl_read(struct pipeline_data *p, struct pipeline_msg_req *req) { - union table_rule_match_low_level match_ll; struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *) req; - struct table_rule_match *match = &req->table_rule_delete.match; uint32_t table_id = req->id; - int key_found, status; - - status = match_convert(match, &match_ll, 0); - if (status) { - rsp->status = -1; - return rsp; - } + void *data = req->table_rule_ttl_read.data; + int clear = req->table_rule_ttl_read.clear; + struct rte_table_action *a = p->table_data[table_id].a; - rsp->status = rte_pipeline_table_entry_delete(p->p, - table_id, - &match_ll, - &key_found, - NULL); + rsp->status = rte_table_action_ttl_read(a, + data, + &rsp->table_rule_ttl_read.stats, + clear); return rsp; } static struct pipeline_msg_rsp * -pipeline_msg_handle_table_rule_delete_default(struct pipeline_data *p, +pipeline_msg_handle_table_rule_time_read(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; + void *data = req->table_rule_time_read.data; + struct rte_table_action *a = p->table_data[table_id].a; - rsp->status = rte_pipeline_table_default_entry_delete(p->p, - table_id, - NULL); + rsp->status = rte_table_action_time_read(a, + data, + &rsp->table_rule_time_read.timestamp); return rsp; } @@ -2104,6 +3042,34 @@ pipeline_msg_handle(struct pipeline_data *p) rsp = pipeline_msg_handle_table_rule_delete_default(p, req); break; + case PIPELINE_REQ_TABLE_RULE_STATS_READ: + rsp = pipeline_msg_handle_table_rule_stats_read(p, req); + break; + + case PIPELINE_REQ_TABLE_MTR_PROFILE_ADD: + rsp = pipeline_msg_handle_table_mtr_profile_add(p, req); + break; + + case PIPELINE_REQ_TABLE_MTR_PROFILE_DELETE: + rsp = pipeline_msg_handle_table_mtr_profile_delete(p, req); + break; + + case PIPELINE_REQ_TABLE_RULE_MTR_READ: + rsp = pipeline_msg_handle_table_rule_mtr_read(p, req); + break; + + case PIPELINE_REQ_TABLE_DSCP_TABLE_UPDATE: + rsp = pipeline_msg_handle_table_dscp_table_update(p, req); + break; + + case PIPELINE_REQ_TABLE_RULE_TTL_READ: + rsp = pipeline_msg_handle_table_rule_ttl_read(p, req); + break; + + case PIPELINE_REQ_TABLE_RULE_TIME_READ: + rsp = pipeline_msg_handle_table_rule_time_read(p, req); + break; + default: rsp = (struct pipeline_msg_rsp *) req; rsp->status = -1;