#include <rte_common.h>
#include <rte_cycles.h>
#include <rte_lcore.h>
+#include <rte_service_component.h>
#include <rte_ring.h>
#include <rte_table_acl.h>
#include "rte_eth_softnic_internals.h"
/**
- * Master thread: data plane thread init
+ * Main thread: data plane thread init
*/
void
softnic_thread_free(struct pmd_internals *softnic)
{
uint32_t i;
- RTE_LCORE_FOREACH_SLAVE(i) {
+ RTE_LCORE_FOREACH_WORKER(i) {
struct softnic_thread *t = &softnic->thread[i];
/* MSGQs */
{
uint32_t i;
- RTE_LCORE_FOREACH_SLAVE(i) {
+ for (i = 0; i < RTE_MAX_LCORE; i++) {
char ring_name[NAME_MAX];
struct rte_ring *msgq_req, *msgq_rsp;
struct softnic_thread *t = &softnic->thread[i];
return -1;
}
- /* Master thread records */
+ /* Main thread records */
t->msgq_req = msgq_req;
t->msgq_rsp = msgq_rsp;
- t->enabled = 1;
+ t->service_id = UINT32_MAX;
/* Data plane thread records */
t_data->n_pipelines = 0;
return 0;
}
+static inline int
+thread_is_valid(struct pmd_internals *softnic, uint32_t thread_id)
+{
+ if (thread_id == rte_get_main_lcore())
+ return 0; /* FALSE */
+
+ if (softnic->params.sc && rte_lcore_has_role(thread_id, ROLE_SERVICE))
+ return 1; /* TRUE */
+ if (!softnic->params.sc && rte_lcore_has_role(thread_id, ROLE_RTE))
+ return 1; /* TRUE */
+
+ return 0; /* FALSE */
+}
+
static inline int
thread_is_running(uint32_t thread_id)
{
return (thread_state == RUNNING)? 1 : 0;
}
+static int32_t
+rte_pmd_softnic_run_internal(void *arg);
+
+static inline int
+thread_sc_service_up(struct pmd_internals *softnic, uint32_t thread_id)
+{
+ struct rte_service_spec service_params;
+ struct softnic_thread *t = &softnic->thread[thread_id];
+ struct rte_eth_dev *dev;
+ int status;
+ uint16_t port_id;
+
+ /* service params */
+ status = rte_eth_dev_get_port_by_name(softnic->params.name, &port_id);
+ if (status)
+ return status;
+
+ dev = &rte_eth_devices[port_id];
+ snprintf(service_params.name, sizeof(service_params.name), "%s_%u",
+ softnic->params.name,
+ thread_id);
+ service_params.callback = rte_pmd_softnic_run_internal;
+ service_params.callback_userdata = dev;
+ service_params.capabilities = 0;
+ service_params.socket_id = (int)softnic->params.cpu_id;
+
+ /* service register */
+ status = rte_service_component_register(&service_params, &t->service_id);
+ if (status)
+ return status;
+
+ status = rte_service_component_runstate_set(t->service_id, 1);
+ if (status) {
+ rte_service_component_unregister(t->service_id);
+ t->service_id = UINT32_MAX;
+ return status;
+ }
+
+ status = rte_service_runstate_set(t->service_id, 1);
+ if (status) {
+ rte_service_component_runstate_set(t->service_id, 0);
+ rte_service_component_unregister(t->service_id);
+ t->service_id = UINT32_MAX;
+ return status;
+ }
+
+ /* service map to thread */
+ status = rte_service_map_lcore_set(t->service_id, thread_id, 1);
+ if (status) {
+ rte_service_runstate_set(t->service_id, 0);
+ rte_service_component_runstate_set(t->service_id, 0);
+ rte_service_component_unregister(t->service_id);
+ t->service_id = UINT32_MAX;
+ return status;
+ }
+
+ return 0;
+}
+
+static inline void
+thread_sc_service_down(struct pmd_internals *softnic, uint32_t thread_id)
+{
+ struct softnic_thread *t = &softnic->thread[thread_id];
+
+ /* service unmap from thread */
+ rte_service_map_lcore_set(t->service_id, thread_id, 0);
+
+ /* service unregister */
+ rte_service_runstate_set(t->service_id, 0);
+ rte_service_component_runstate_set(t->service_id, 0);
+ rte_service_component_unregister(t->service_id);
+
+ t->service_id = UINT32_MAX;
+}
+
/**
* Pipeline is running when:
* (A) Pipeline is mapped to a data plane thread AND
}
/**
- * Master thread & data plane threads: message passing
+ * Main thread & data plane threads: message passing
*/
enum thread_req_type {
THREAD_REQ_PIPELINE_ENABLE = 0,
};
/**
- * Master thread
+ * Main thread
*/
static struct thread_msg_req *
thread_msg_alloc(void)
const char *pipeline_name)
{
struct pipeline *p = softnic_pipeline_find(softnic, pipeline_name);
- struct softnic_thread *t;
struct thread_msg_req *req;
struct thread_msg_rsp *rsp;
- uint32_t i;
+ uint32_t n_pipelines, i;
int status;
/* Check input params */
- if ((thread_id >= RTE_MAX_LCORE) ||
+ if (!thread_is_valid(softnic, thread_id) ||
(p == NULL) ||
(p->n_ports_in == 0) ||
(p->n_ports_out == 0) ||
- (p->n_tables == 0))
+ (p->n_tables == 0) ||
+ p->enabled)
return -1;
- t = &softnic->thread[thread_id];
- if ((t->enabled == 0) ||
- p->enabled)
+ n_pipelines = softnic_pipeline_thread_count(softnic, thread_id);
+ if (n_pipelines >= THREAD_PIPELINES_MAX)
return -1;
+ if (softnic->params.sc && (n_pipelines == 0)) {
+ status = thread_sc_service_up(softnic, thread_id);
+ if (status)
+ return status;
+ }
+
if (!thread_is_running(thread_id)) {
struct softnic_thread_data *td = &softnic->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;
/* Send request and wait for response */
rsp = thread_msg_send_recv(softnic, thread_id, req);
- if (rsp == NULL)
- return -1;
/* Read response */
status = rsp->status;
const char *pipeline_name)
{
struct pipeline *p = softnic_pipeline_find(softnic, pipeline_name);
- struct softnic_thread *t;
struct thread_msg_req *req;
struct thread_msg_rsp *rsp;
+ uint32_t n_pipelines;
int status;
/* Check input params */
- if ((thread_id >= RTE_MAX_LCORE) ||
- (p == NULL))
- return -1;
-
- t = &softnic->thread[thread_id];
- if (t->enabled == 0)
+ if (!thread_is_valid(softnic, thread_id) ||
+ (p == NULL) ||
+ (p->enabled && (p->thread_id != thread_id)))
return -1;
if (p->enabled == 0)
return 0;
- if (p->thread_id != thread_id)
- return -1;
-
if (!thread_is_running(thread_id)) {
struct softnic_thread_data *td = &softnic->thread_data[thread_id];
uint32_t i;
break;
}
+ if (softnic->params.sc && (td->n_pipelines == 0))
+ thread_sc_service_down(softnic, thread_id);
+
return 0;
}
/* Send request and wait for response */
rsp = thread_msg_send_recv(softnic, thread_id, req);
- if (rsp == NULL)
- return -1;
/* Read response */
status = rsp->status;
p->enabled = 0;
+ n_pipelines = softnic_pipeline_thread_count(softnic, thread_id);
+ if (softnic->params.sc && (n_pipelines == 0))
+ thread_sc_service_down(softnic, thread_id);
+
return 0;
}
uint32_t i;
/* Request */
- if (t->n_pipelines >= THREAD_PIPELINES_MAX) {
- rsp->status = -1;
- return rsp;
- }
-
t->p[t->n_pipelines] = req->pipeline_enable.p;
p->p = req->pipeline_enable.p;
}
/**
- * Master thread & data plane threads: message passing
+ * Main thread & data plane threads: message passing
*/
enum pipeline_req_type {
/* Port IN */
+ PIPELINE_REQ_PORT_IN_STATS_READ,
PIPELINE_REQ_PORT_IN_ENABLE,
PIPELINE_REQ_PORT_IN_DISABLE,
+ /* Port OUT */
+ PIPELINE_REQ_PORT_OUT_STATS_READ,
+
/* Table */
+ PIPELINE_REQ_TABLE_STATS_READ,
PIPELINE_REQ_TABLE_RULE_ADD,
PIPELINE_REQ_TABLE_RULE_ADD_DEFAULT,
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_MAX
};
+struct pipeline_msg_req_port_in_stats_read {
+ int clear;
+};
+
+struct pipeline_msg_req_port_out_stats_read {
+ int clear;
+};
+
+struct pipeline_msg_req_table_stats_read {
+ int clear;
+};
+
struct pipeline_msg_req_table_rule_add {
struct softnic_table_rule_match match;
struct softnic_table_rule_action action;
struct softnic_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 {
enum pipeline_req_type type;
uint32_t id; /* Port IN, port OUT or table ID */
RTE_STD_C11
union {
+ struct pipeline_msg_req_port_in_stats_read port_in_stats_read;
+ struct pipeline_msg_req_port_out_stats_read port_out_stats_read;
+ struct pipeline_msg_req_table_stats_read table_stats_read;
struct pipeline_msg_req_table_rule_add table_rule_add;
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_rsp_port_in_stats_read {
+ struct rte_pipeline_port_in_stats stats;
+};
+
+struct pipeline_msg_rsp_port_out_stats_read {
+ struct rte_pipeline_port_out_stats stats;
+};
+
+struct pipeline_msg_rsp_table_stats_read {
+ struct rte_pipeline_table_stats stats;
+};
+
struct pipeline_msg_rsp_table_rule_add {
void *data;
};
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 {
int status;
RTE_STD_C11
union {
+ struct pipeline_msg_rsp_port_in_stats_read port_in_stats_read;
+ struct pipeline_msg_rsp_port_out_stats_read port_out_stats_read;
+ struct pipeline_msg_rsp_table_stats_read table_stats_read;
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;
};
};
/**
- * Master thread
+ * Main thread
*/
static struct pipeline_msg_req *
pipeline_msg_alloc(void)
return rsp;
}
+int
+softnic_pipeline_port_in_stats_read(struct pmd_internals *softnic,
+ const char *pipeline_name,
+ uint32_t port_id,
+ struct rte_pipeline_port_in_stats *stats,
+ int clear)
+{
+ struct pipeline *p;
+ struct pipeline_msg_req *req;
+ struct pipeline_msg_rsp *rsp;
+ int status;
+
+ /* Check input params */
+ if (pipeline_name == NULL ||
+ stats == NULL)
+ return -1;
+
+ p = softnic_pipeline_find(softnic, pipeline_name);
+ if (p == NULL ||
+ 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)
+ return -1;
+
+ /* Write request */
+ req->type = PIPELINE_REQ_PORT_IN_STATS_READ;
+ req->id = port_id;
+ req->port_in_stats_read.clear = clear;
+
+ /* Send request and wait for response */
+ rsp = pipeline_msg_send_recv(p, req);
+
+ /* Read response */
+ status = rsp->status;
+ if (status)
+ memcpy(stats, &rsp->port_in_stats_read.stats, sizeof(*stats));
+
+ /* Free response */
+ pipeline_msg_free(rsp);
+
+ return status;
+}
+
int
softnic_pipeline_port_in_enable(struct pmd_internals *softnic,
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;
/* Send request and wait for response */
rsp = pipeline_msg_send_recv(p, req);
- if (rsp == NULL)
+
+ /* Read response */
+ status = rsp->status;
+
+ /* Free response */
+ pipeline_msg_free(rsp);
+
+ return status;
+}
+
+int
+softnic_pipeline_port_out_stats_read(struct pmd_internals *softnic,
+ const char *pipeline_name,
+ uint32_t port_id,
+ struct rte_pipeline_port_out_stats *stats,
+ int clear)
+{
+ struct pipeline *p;
+ struct pipeline_msg_req *req;
+ struct pipeline_msg_rsp *rsp;
+ int status;
+
+ /* Check input params */
+ if (pipeline_name == NULL ||
+ stats == NULL)
+ return -1;
+
+ p = softnic_pipeline_find(softnic, pipeline_name);
+ if (p == NULL ||
+ 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)
+ return -1;
+
+ /* Write request */
+ req->type = PIPELINE_REQ_PORT_OUT_STATS_READ;
+ req->id = port_id;
+ req->port_out_stats_read.clear = clear;
+
+ /* Send request and wait for response */
+ rsp = pipeline_msg_send_recv(p, req);
+
+ /* Read response */
+ status = rsp->status;
+ if (status)
+ memcpy(stats, &rsp->port_out_stats_read.stats, sizeof(*stats));
+
+ /* Free response */
+ pipeline_msg_free(rsp);
+
+ return status;
+}
+
+int
+softnic_pipeline_table_stats_read(struct pmd_internals *softnic,
+ const char *pipeline_name,
+ uint32_t table_id,
+ struct rte_pipeline_table_stats *stats,
+ int clear)
+{
+ struct pipeline *p;
+ struct pipeline_msg_req *req;
+ struct pipeline_msg_rsp *rsp;
+ int status;
+
+ /* Check input params */
+ if (pipeline_name == NULL ||
+ stats == NULL)
+ return -1;
+
+ p = softnic_pipeline_find(softnic, pipeline_name);
+ if (p == NULL ||
+ 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)
return -1;
+ /* Write request */
+ req->type = PIPELINE_REQ_TABLE_STATS_READ;
+ req->id = table_id;
+ req->table_stats_read.clear = clear;
+
+ /* Send request and wait for response */
+ rsp = pipeline_msg_send_recv(p, req);
+
/* Read response */
status = rsp->status;
+ if (status)
+ memcpy(stats, &rsp->table_stats_read.stats, sizeof(*stats));
/* Free response */
pipeline_msg_free(rsp);
/* Send request and wait for response */
rsp = pipeline_msg_send_recv(p, req);
- if (rsp == NULL)
- return -1;
/* Read response */
status = rsp->status;
/* Send request and wait for response */
rsp = pipeline_msg_send_recv(p, req);
- if (rsp == NULL)
- return -1;
/* Read response */
status = rsp->status;
/* Send request and wait for response */
rsp = pipeline_msg_send_recv(p, req);
- if (rsp == NULL)
- return -1;
/* Read response */
status = rsp->status;
/* Send request and wait for response */
rsp = pipeline_msg_send_recv(p, req);
- if (rsp == NULL)
- return -1;
/* Read response */
status = rsp->status;
/* Send request and wait for response */
rsp = pipeline_msg_send_recv(p, req);
- if (rsp == NULL)
- return -1;
/* Read response */
status = rsp->status;
return status;
}
-/**
- * Data plane threads: message handling
- */
-static inline struct pipeline_msg_req *
-pipeline_msg_recv(struct rte_ring *msgq_req)
+int
+softnic_pipeline_table_rule_stats_read(struct pmd_internals *softnic,
+ const char *pipeline_name,
+ uint32_t table_id,
+ void *data,
+ struct rte_table_action_stats_counters *stats,
+ int clear)
{
+ struct pipeline *p;
struct pipeline_msg_req *req;
+ struct pipeline_msg_rsp *rsp;
+ int status;
- int status = rte_ring_sc_dequeue(msgq_req, (void **)&req);
+ /* Check input params */
+ if (pipeline_name == NULL ||
+ data == NULL ||
+ stats == NULL)
+ return -1;
- if (status != 0)
- return NULL;
+ p = softnic_pipeline_find(softnic, pipeline_name);
+ if (p == NULL ||
+ table_id >= p->n_tables)
+ return -1;
- return req;
+ if (!pipeline_is_running(p)) {
+ struct rte_table_action *a = p->table[table_id].a;
+
+ status = rte_table_action_stats_read(a,
+ 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 = 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)
+ memcpy(stats, &rsp->table_rule_stats_read.stats, sizeof(*stats));
+
+ /* Free response */
+ pipeline_msg_free(rsp);
+
+ return status;
+}
+
+int
+softnic_pipeline_table_mtr_profile_add(struct pmd_internals *softnic,
+ 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;
+ struct softnic_table *table;
+ struct softnic_table_meter_profile *mp;
+ int status;
+
+ /* Check input params */
+ if (pipeline_name == NULL ||
+ profile == NULL)
+ return -1;
+
+ p = softnic_pipeline_find(softnic, pipeline_name);
+ if (p == NULL ||
+ table_id >= p->n_tables)
+ return -1;
+
+ table = &p->table[table_id];
+ mp = softnic_pipeline_table_meter_profile_find(table, meter_profile_id);
+ if (mp)
+ return -1;
+
+ /* Resource Allocation */
+ mp = calloc(1, sizeof(struct softnic_table_meter_profile));
+ if (mp == NULL)
+ return -1;
+
+ mp->meter_profile_id = meter_profile_id;
+ memcpy(&mp->profile, profile, sizeof(mp->profile));
+
+ if (!pipeline_is_running(p)) {
+ status = rte_table_action_meter_profile_add(table->a,
+ meter_profile_id,
+ profile);
+ if (status) {
+ free(mp);
+ return status;
+ }
+
+ /* Add profile to the table. */
+ TAILQ_INSERT_TAIL(&table->meter_profiles, mp, node);
+
+ return status;
+ }
+
+ /* Allocate request */
+ req = pipeline_msg_alloc();
+ if (req == NULL) {
+ free(mp);
+ 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;
+ if (status == 0)
+ TAILQ_INSERT_TAIL(&table->meter_profiles, mp, node);
+ else
+ free(mp);
+
+ /* Free response */
+ pipeline_msg_free(rsp);
+
+ return status;
+}
+
+int
+softnic_pipeline_table_mtr_profile_delete(struct pmd_internals *softnic,
+ 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 = softnic_pipeline_find(softnic, 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
+softnic_pipeline_table_rule_mtr_read(struct pmd_internals *softnic,
+ const char *pipeline_name,
+ uint32_t table_id,
+ void *data,
+ uint32_t tc_mask,
+ struct rte_table_action_mtr_counters *stats,
+ int clear)
+{
+ struct pipeline *p;
+ struct pipeline_msg_req *req;
+ struct pipeline_msg_rsp *rsp;
+ int status;
+
+ /* Check input params */
+ if (pipeline_name == NULL ||
+ data == NULL ||
+ stats == NULL)
+ return -1;
+
+ p = softnic_pipeline_find(softnic, 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_read(a,
+ 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 = 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)
+ memcpy(stats, &rsp->table_rule_mtr_read.stats, sizeof(*stats));
+
+ /* Free response */
+ pipeline_msg_free(rsp);
+
+ return status;
+}
+
+int
+softnic_pipeline_table_dscp_table_update(struct pmd_internals *softnic,
+ 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 = softnic_pipeline_find(softnic, 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);
+
+ /* Update table dscp table */
+ if (!status)
+ memcpy(&p->table[table_id].dscp_table, dscp_table,
+ sizeof(p->table[table_id].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;
+
+ /* Update table dscp table */
+ if (!status)
+ memcpy(&p->table[table_id].dscp_table, dscp_table,
+ sizeof(p->table[table_id].dscp_table));
+
+ /* Free response */
+ pipeline_msg_free(rsp);
+
+ return status;
+}
+
+int
+softnic_pipeline_table_rule_ttl_read(struct pmd_internals *softnic,
+ const char *pipeline_name,
+ uint32_t table_id,
+ void *data,
+ struct rte_table_action_ttl_counters *stats,
+ int clear)
+{
+ struct pipeline *p;
+ struct pipeline_msg_req *req;
+ struct pipeline_msg_rsp *rsp;
+ int status;
+
+ /* Check input params */
+ if (pipeline_name == NULL ||
+ data == NULL ||
+ stats == NULL)
+ return -1;
+
+ p = softnic_pipeline_find(softnic, 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_ttl_read(a,
+ 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 = 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)
+ memcpy(stats, &rsp->table_rule_ttl_read.stats, sizeof(*stats));
+
+ /* Free response */
+ pipeline_msg_free(rsp);
+
+ return status;
+}
+
+/**
+ * Data plane threads: message handling
+ */
+static inline struct pipeline_msg_req *
+pipeline_msg_recv(struct rte_ring *msgq_req)
+{
+ struct pipeline_msg_req *req;
+
+ int status = rte_ring_sc_dequeue(msgq_req, (void **)&req);
+
+ if (status != 0)
+ return NULL;
+
+ return req;
}
static inline void
} while (status == -ENOBUFS);
}
+static struct pipeline_msg_rsp *
+pipeline_msg_handle_port_in_stats_read(struct pipeline_data *p,
+ struct pipeline_msg_req *req)
+{
+ struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
+ uint32_t port_id = req->id;
+ int clear = req->port_in_stats_read.clear;
+
+ rsp->status = rte_pipeline_port_in_stats_read(p->p,
+ port_id,
+ &rsp->port_in_stats_read.stats,
+ clear);
+
+ return rsp;
+}
+
static struct pipeline_msg_rsp *
pipeline_msg_handle_port_in_enable(struct pipeline_data *p,
struct pipeline_msg_req *req)
return rsp;
}
+static struct pipeline_msg_rsp *
+pipeline_msg_handle_port_out_stats_read(struct pipeline_data *p,
+ struct pipeline_msg_req *req)
+{
+ struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
+ uint32_t port_id = req->id;
+ int clear = req->port_out_stats_read.clear;
+
+ rsp->status = rte_pipeline_port_out_stats_read(p->p,
+ port_id,
+ &rsp->port_out_stats_read.stats,
+ clear);
+
+ return rsp;
+}
+
+static struct pipeline_msg_rsp *
+pipeline_msg_handle_table_stats_read(struct pipeline_data *p,
+ struct pipeline_msg_req *req)
+{
+ struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *)req;
+ uint32_t port_id = req->id;
+ int clear = req->table_stats_read.clear;
+
+ rsp->status = rte_pipeline_table_stats_read(p->p,
+ port_id,
+ &rsp->table_stats_read.stats,
+ clear);
+
+ return rsp;
+}
+
static int
match_convert_ipv6_depth(uint32_t depth, uint32_t *depth32)
{
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];
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];
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;
+ }
+
+ 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;
+ }
+
return 0;
}
return rsp;
}
+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;
+
+ rsp->status = rte_table_action_stats_read(a,
+ data,
+ &rsp->table_rule_stats_read.stats,
+ clear);
+
+ return rsp;
+}
+
+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;
+
+ rsp->status = rte_table_action_meter_profile_add(a,
+ meter_profile_id,
+ profile);
+
+ return rsp;
+}
+
+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;
+
+ rsp->status = rte_table_action_meter_profile_delete(a,
+ meter_profile_id);
+
+ return rsp;
+}
+
+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;
+
+ rsp->status = rte_table_action_meter_read(a,
+ data,
+ tc_mask,
+ &rsp->table_rule_mtr_read.stats,
+ clear);
+
+ return rsp;
+}
+
+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);
+
+ return rsp;
+}
+
+static struct pipeline_msg_rsp *
+pipeline_msg_handle_table_rule_ttl_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_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_table_action_ttl_read(a,
+ data,
+ &rsp->table_rule_ttl_read.stats,
+ clear);
+
+ return rsp;
+}
+
static void
pipeline_msg_handle(struct pipeline_data *p)
{
break;
switch (req->type) {
+ case PIPELINE_REQ_PORT_IN_STATS_READ:
+ rsp = pipeline_msg_handle_port_in_stats_read(p, req);
+ break;
+
case PIPELINE_REQ_PORT_IN_ENABLE:
rsp = pipeline_msg_handle_port_in_enable(p, req);
break;
rsp = pipeline_msg_handle_port_in_disable(p, req);
break;
+ case PIPELINE_REQ_PORT_OUT_STATS_READ:
+ rsp = pipeline_msg_handle_port_out_stats_read(p, req);
+ break;
+
+ case PIPELINE_REQ_TABLE_STATS_READ:
+ rsp = pipeline_msg_handle_table_stats_read(p, req);
+ break;
+
case PIPELINE_REQ_TABLE_RULE_ADD:
rsp = pipeline_msg_handle_table_rule_add(p, req);
break;
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;
+
default:
rsp = (struct pipeline_msg_rsp *)req;
rsp->status = -1;
/**
* Data plane threads: main
*/
-int
-rte_pmd_softnic_run(uint16_t port_id)
+static int32_t
+rte_pmd_softnic_run_internal(void *arg)
{
- struct rte_eth_dev *dev = &rte_eth_devices[port_id];
+ struct rte_eth_dev *dev = arg;
struct pmd_internals *softnic;
struct softnic_thread_data *t;
uint32_t thread_id, j;
-#ifdef RTE_LIBRTE_ETHDEV_DEBUG
- RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, 0);
-#endif
-
softnic = dev->data->dev_private;
thread_id = rte_lcore_id();
t = &softnic->thread_data[thread_id];
return 0;
}
+
+int
+rte_pmd_softnic_run(uint16_t port_id)
+{
+ struct rte_eth_dev *dev = &rte_eth_devices[port_id];
+
+#ifdef RTE_LIBRTE_ETHDEV_DEBUG
+ RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, 0);
+#endif
+
+ return (int)rte_pmd_softnic_run_internal(dev);
+}