/*-
* BSD LICENSE
*
- * Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
+ * Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
#include "pipeline_passthrough.h"
#include "pipeline_firewall.h"
#include "pipeline_flow_classification.h"
+#include "pipeline_flow_actions.h"
#include "pipeline_routing.h"
+#include "thread_fe.h"
#define APP_NAME_SIZE 32
+#define APP_RETA_SIZE_MAX (ETH_RSS_RETA_SIZE_512 / RTE_RETA_GROUP_SIZE)
+
static void
app_init_core_map(struct app_params *app)
{
static void
app_init_eal(struct app_params *app)
{
- char buffer[32];
+ char buffer[256];
struct app_eal_params *p = &app->eal_params;
uint32_t n_args = 0;
+ uint32_t i;
int status;
app->eal_argv[n_args++] = strdup(app->app_name);
app->eal_argv[n_args++] = strdup(buffer);
}
- if (p->pci_blacklist) {
+ for (i = 0; i < APP_MAX_LINKS; i++) {
+ if (p->pci_blacklist[i] == NULL)
+ break;
+
snprintf(buffer,
sizeof(buffer),
"--pci-blacklist=%s",
- p->pci_blacklist);
+ p->pci_blacklist[i]);
app->eal_argv[n_args++] = strdup(buffer);
}
- if (p->pci_whitelist) {
+ if (app->port_mask != 0)
+ for (i = 0; i < APP_MAX_LINKS; i++) {
+ if (p->pci_whitelist[i] == NULL)
+ break;
+
+ snprintf(buffer,
+ sizeof(buffer),
+ "--pci-whitelist=%s",
+ p->pci_whitelist[i]);
+ app->eal_argv[n_args++] = strdup(buffer);
+ }
+ else
+ for (i = 0; i < app->n_links; i++) {
+ char *pci_bdf = app->link_params[i].pci_bdf;
+
+ snprintf(buffer,
+ sizeof(buffer),
+ "--pci-whitelist=%s",
+ pci_bdf);
+ app->eal_argv[n_args++] = strdup(buffer);
+ }
+
+ for (i = 0; i < APP_MAX_LINKS; i++) {
+ if (p->vdev[i] == NULL)
+ break;
+
snprintf(buffer,
sizeof(buffer),
- "--pci-whitelist=%s",
- p->pci_whitelist);
- app->eal_argv[n_args++] = strdup(buffer);
- }
-
- if (p->vdev) {
- snprintf(buffer, sizeof(buffer), "--vdev=%s", p->vdev);
+ "--vdev=%s",
+ p->vdev[i]);
app->eal_argv[n_args++] = strdup(buffer);
}
app->eal_argc = n_args;
APP_LOG(app, HIGH, "Initializing EAL ...");
+ if (app->log_level >= APP_LOG_LEVEL_LOW) {
+ int i;
+
+ fprintf(stdout, "[APP] EAL arguments: \"");
+ for (i = 1; i < app->eal_argc; i++)
+ fprintf(stdout, "%s ", app->eal_argv[i]);
+ fprintf(stdout, "\"\n");
+ }
+
status = rte_eal_init(app->eal_argc, app->eal_argv);
if (status < 0)
rte_panic("EAL init error\n");
{
struct rte_eth_syn_filter filter = {
.hig_pri = 1,
- .queue = link->tcp_syn_local_q,
+ .queue = link->tcp_syn_q,
};
return rte_eth_dev_filter_ctrl(link->pmd_id,
static void
app_link_set_tcp_syn_filter(struct app_params *app, struct app_link_params *cp)
{
- if (cp->tcp_syn_local_q != 0) {
+ if (cp->tcp_syn_q != 0) {
int status = app_link_filter_tcp_syn_add(cp);
APP_LOG(app, LOW, "%s (%" PRIu32 "): "
"Adding TCP SYN filter (queue = %" PRIu32 ")",
- cp->name, cp->pmd_id, cp->tcp_syn_local_q);
+ cp->name, cp->pmd_id, cp->tcp_syn_q);
if (status)
rte_panic("%s (%" PRIu32 "): "
"Error adding TCP SYN filter "
"(queue = %" PRIu32 ") (%" PRId32 ")\n",
- cp->name, cp->pmd_id, cp->tcp_syn_local_q,
+ cp->name, cp->pmd_id, cp->tcp_syn_q,
status);
}
}
+static int
+app_link_is_virtual(struct app_link_params *p)
+{
+ uint32_t pmd_id = p->pmd_id;
+ struct rte_eth_dev *dev = &rte_eth_devices[pmd_id];
+
+ if (dev->dev_type == RTE_ETH_DEV_VIRTUAL)
+ return 1;
+
+ return 0;
+}
+
void
app_link_up_internal(struct app_params *app, struct app_link_params *cp)
{
uint32_t i;
int status;
+ if (app_link_is_virtual(cp)) {
+ cp->state = 1;
+ return;
+ }
+
/* For each link, add filters for IP of current link */
if (cp->ip != 0) {
for (i = 0; i < app->n_links; i++) {
/* PMD link up */
status = rte_eth_dev_set_link_up(cp->pmd_id);
if (status < 0)
- rte_panic("%s (%" PRIu32 "): PMD set up error %" PRId32 "\n",
- cp->name, cp->pmd_id, status);
+ rte_panic("%s (%" PRIu32 "): PMD set link up error %"
+ PRId32 "\n", cp->name, cp->pmd_id, status);
/* Mark link as UP */
cp->state = 1;
app_link_down_internal(struct app_params *app, struct app_link_params *cp)
{
uint32_t i;
+ int status;
+
+ if (app_link_is_virtual(cp)) {
+ cp->state = 0;
+ return;
+ }
/* PMD link down */
- rte_eth_dev_set_link_down(cp->pmd_id);
+ status = rte_eth_dev_set_link_down(cp->pmd_id);
+ if (status < 0)
+ rte_panic("%s (%" PRIu32 "): PMD set link down error %"
+ PRId32 "\n", cp->name, cp->pmd_id, status);
/* Mark link as DOWN */
cp->state = 0;
link_params.link_speed / 1000,
link_params.link_status ? "UP" : "DOWN");
- if (link_params.link_status == 0)
+ if (link_params.link_status == ETH_LINK_DOWN)
all_links_up = 0;
}
}
}
+static inline int
+app_get_cpu_socket_id(uint32_t pmd_id)
+{
+ int status = rte_eth_dev_socket_id(pmd_id);
+
+ return (status != SOCKET_ID_ANY) ? status : 0;
+}
+
+static inline int
+app_link_rss_enabled(struct app_link_params *cp)
+{
+ return (cp->n_rss_qs) ? 1 : 0;
+}
+
+static void
+app_link_rss_setup(struct app_link_params *cp)
+{
+ struct rte_eth_dev_info dev_info;
+ struct rte_eth_rss_reta_entry64 reta_conf[APP_RETA_SIZE_MAX];
+ uint32_t i;
+ int status;
+
+ /* Get RETA size */
+ memset(&dev_info, 0, sizeof(dev_info));
+ rte_eth_dev_info_get(cp->pmd_id, &dev_info);
+
+ if (dev_info.reta_size == 0)
+ rte_panic("%s (%u): RSS setup error (null RETA size)\n",
+ cp->name, cp->pmd_id);
+
+ if (dev_info.reta_size > ETH_RSS_RETA_SIZE_512)
+ rte_panic("%s (%u): RSS setup error (RETA size too big)\n",
+ cp->name, cp->pmd_id);
+
+ /* Setup RETA contents */
+ memset(reta_conf, 0, sizeof(reta_conf));
+
+ for (i = 0; i < dev_info.reta_size; i++)
+ reta_conf[i / RTE_RETA_GROUP_SIZE].mask = UINT64_MAX;
+
+ for (i = 0; i < dev_info.reta_size; i++) {
+ uint32_t reta_id = i / RTE_RETA_GROUP_SIZE;
+ uint32_t reta_pos = i % RTE_RETA_GROUP_SIZE;
+ uint32_t rss_qs_pos = i % cp->n_rss_qs;
+
+ reta_conf[reta_id].reta[reta_pos] =
+ (uint16_t) cp->rss_qs[rss_qs_pos];
+ }
+
+ /* RETA update */
+ status = rte_eth_dev_rss_reta_update(cp->pmd_id,
+ reta_conf,
+ dev_info.reta_size);
+ if (status != 0)
+ rte_panic("%s (%u): RSS setup error (RETA update failed)\n",
+ cp->name, cp->pmd_id);
+}
+
+static void
+app_init_link_set_config(struct app_link_params *p)
+{
+ if (p->n_rss_qs) {
+ p->conf.rxmode.mq_mode = ETH_MQ_RX_RSS;
+ p->conf.rx_adv_conf.rss_conf.rss_hf = p->rss_proto_ipv4 |
+ p->rss_proto_ipv6 |
+ p->rss_proto_l2;
+ }
+}
+
static void
app_init_link(struct app_params *app)
{
sscanf(p_link->name, "LINK%" PRIu32, &link_id);
n_hwq_in = app_link_get_n_rxq(app, p_link);
n_hwq_out = app_link_get_n_txq(app, p_link);
+ app_init_link_set_config(p_link);
APP_LOG(app, HIGH, "Initializing %s (%" PRIu32") "
"(%" PRIu32 " RXQ, %" PRIu32 " TXQ) ...",
p_link->pmd_id,
rxq_queue_id,
p_rxq->size,
- rte_eth_dev_socket_id(p_link->pmd_id),
+ app_get_cpu_socket_id(p_link->pmd_id),
&p_rxq->conf,
app->mempool[p_rxq->mempool_id]);
if (status < 0)
p_link->pmd_id,
txq_queue_id,
p_txq->size,
- rte_eth_dev_socket_id(p_link->pmd_id),
+ app_get_cpu_socket_id(p_link->pmd_id),
&p_txq->conf);
if (status < 0)
rte_panic("%s (%" PRIu32 "): "
rte_panic("Cannot start %s (error %" PRId32 ")\n",
p_link->name, status);
- /* LINK UP */
+ /* LINK FILTERS */
app_link_set_arp_filter(app, p_link);
app_link_set_tcp_syn_filter(app, p_link);
+ if (app_link_rss_enabled(p_link))
+ app_link_rss_setup(p_link);
+
+ /* LINK UP */
app_link_up_internal(app, p_link);
}
/* TM */
p_tm->sched_port_params.name = p_tm->name;
p_tm->sched_port_params.socket =
- rte_eth_dev_socket_id(p_link->pmd_id);
+ app_get_cpu_socket_id(p_link->pmd_id);
p_tm->sched_port_params.rate =
(uint64_t) link_eth_params.link_speed * 1000 * 1000 / 8;
{
uint32_t i;
- strcpy(p_out->name, p_in->name);
+ snprintf(p_out->name, PIPELINE_NAME_SIZE, "%s", p_in->name);
p_out->socket_id = (int) p_in->socket_id;
out->burst_size = app->tm_params[in->id].burst_read;
break;
case APP_PKTQ_IN_SOURCE:
+ {
+ uint32_t mempool_id =
+ app->source_params[in->id].mempool_id;
+
out->type = PIPELINE_PORT_IN_SOURCE;
- out->params.source.mempool = app->mempool[in->id];
+ out->params.source.mempool = app->mempool[mempool_id];
out->burst_size = app->source_params[in->id].burst;
+ out->params.source.file_name =
+ app->source_params[in->id].file_name;
+ out->params.source.n_bytes_per_pkt =
+ app->source_params[in->id].n_bytes_per_pkt;
break;
+ }
default:
break;
}
break;
}
case APP_PKTQ_OUT_SINK:
+ {
out->type = PIPELINE_PORT_OUT_SINK;
+ out->params.sink.file_name =
+ app->sink_params[in->id].file_name;
+ out->params.sink.max_n_pkts =
+ app->sink_params[in->id].
+ n_pkts_to_dump;
+
break;
+ }
default:
break;
}
"init error\n", params->name);
}
- data->timer_period = (rte_get_tsc_hz() * params->timer_period)
- / 1000;
+ data->ptype = ptype;
+
+ data->timer_period = (rte_get_tsc_hz() *
+ params->timer_period) / 100;
}
}
t = &app->thread_data[lcore_id];
+ t->timer_period = (rte_get_tsc_hz() * APP_THREAD_TIMER_PERIOD) / 1000;
+ t->thread_req_deadline = time + t->timer_period;
+
+ t->headroom_cycles = 0;
+ t->headroom_time = rte_get_tsc_cycles();
+ t->headroom_ratio = 0.0;
+
+ t->msgq_in = app_thread_msgq_in_get(app,
+ params->socket_id,
+ params->core_id,
+ params->hyper_th_id);
+ if (t->msgq_in == NULL)
+ rte_panic("Init error: Cannot find MSGQ_IN for thread %" PRId32,
+ lcore_id);
+
+ t->msgq_out = app_thread_msgq_out_get(app,
+ params->socket_id,
+ params->core_id,
+ params->hyper_th_id);
+ if (t->msgq_out == NULL)
+ rte_panic("Init error: Cannot find MSGQ_OUT for thread %" PRId32,
+ lcore_id);
+
ptype = app_pipeline_type_find(app, params->type);
if (ptype == NULL)
rte_panic("Init error: Unknown pipeline "
&t->regular[t->n_regular] :
&t->custom[t->n_custom];
+ p->pipeline_id = p_id;
p->be = data->be;
p->f_run = ptype->be_ops->f_run;
p->f_timer = ptype->be_ops->f_timer;
p->timer_period = data->timer_period;
p->deadline = time + data->timer_period;
+ data->enabled = 1;
+
if (ptype->be_ops->f_run == NULL)
t->n_regular++;
else
app_init_msgq(app);
app_pipeline_common_cmd_push(app);
+ app_pipeline_thread_cmd_push(app);
app_pipeline_type_register(app, &pipeline_master);
app_pipeline_type_register(app, &pipeline_passthrough);
app_pipeline_type_register(app, &pipeline_flow_classification);
+ app_pipeline_type_register(app, &pipeline_flow_actions);
app_pipeline_type_register(app, &pipeline_firewall);
app_pipeline_type_register(app, &pipeline_routing);
/* Push pipeline commands into the application */
memcpy(&app->cmds[app->n_cmds],
cmds,
- n_cmds * sizeof(cmdline_parse_ctx_t *));
+ n_cmds * sizeof(cmdline_parse_ctx_t));
for (i = 0; i < n_cmds; i++)
app->cmds[app->n_cmds + i]->data = app;