void app_main_loop_pipeline_tx(void) { struct rte_pipeline *p; uint32_t port_in_id[APP_MAX_PORTS]; uint32_t port_out_id[APP_MAX_PORTS]; uint32_t table_id[APP_MAX_PORTS]; uint32_t i; uint32_t core_id = rte_lcore_id(); struct app_core_params *core_params = app_get_core_params(core_id); if ((core_params == NULL) || (core_params->core_type != APP_CORE_TX)) rte_panic("Core %u misconfiguration\n", core_id); RTE_LOG(INFO, USER1, "Core %u is doing TX\n", core_id); /* Pipeline configuration */ struct rte_pipeline_params pipeline_params = { .name = "pipeline", .socket_id = rte_socket_id(), }; p = rte_pipeline_create(&pipeline_params); if (p == NULL) rte_panic("%s: Unable to configure the pipeline\n", __func__); /* Input port configuration */ for (i = 0; i < app.n_ports; i++) { struct rte_port_ring_reader_params port_ring_params = { .ring = app.rings[core_params->swq_in[i]], }; struct rte_pipeline_port_in_params port_params = { .ops = &rte_port_ring_reader_ops, .arg_create = (void *) &port_ring_params, .f_action = (app.ether_hdr_pop_push) ? app_pipeline_tx_port_in_action_handler : NULL, .arg_ah = NULL, .burst_size = app.bsz_swq_rd, }; if (rte_pipeline_port_in_create(p, &port_params, &port_in_id[i])) { rte_panic("%s: Unable to configure input port for " "ring TX %i\n", __func__, i); } } /* Output port configuration */ for (i = 0; i < app.n_ports; i++) { struct rte_port_ethdev_writer_params port_ethdev_params = { .port_id = app.ports[i], .queue_id = 0, .tx_burst_sz = app.bsz_hwq_wr, }; struct rte_pipeline_port_out_params port_params = { .ops = &rte_port_ethdev_writer_ops, .arg_create = (void *) &port_ethdev_params, .f_action = NULL, .f_action_bulk = NULL, .arg_ah = NULL, }; if (rte_pipeline_port_out_create(p, &port_params, &port_out_id[i])) { rte_panic("%s: Unable to configure output port for " "port %d\n", __func__, app.ports[i]); } } /* Table configuration */ for (i = 0; i < app.n_ports; i++) { struct rte_pipeline_table_params table_params = { .ops = &rte_table_stub_ops, .arg_create = NULL, .f_action_hit = NULL, .f_action_miss = NULL, .arg_ah = NULL, .action_data_size = 0, }; if (rte_pipeline_table_create(p, &table_params, &table_id[i])) { rte_panic("%s: Unable to configure table %u\n", __func__, table_id[i]); } } /* Interconnecting ports and tables */ for (i = 0; i < app.n_ports; i++) if (rte_pipeline_port_in_connect_to_table(p, port_in_id[i], table_id[i])) rte_panic("%s: Unable to connect input port %u to " "table %u\n", __func__, port_in_id[i], table_id[i]); /* Add entries to tables */ for (i = 0; i < app.n_ports; i++) { struct rte_pipeline_table_entry default_entry = { .action = RTE_PIPELINE_ACTION_PORT, {.port_id = port_out_id[i]}, }; struct rte_pipeline_table_entry *default_entry_ptr; if (rte_pipeline_table_default_entry_add(p, table_id[i], &default_entry, &default_entry_ptr)) rte_panic("%s: Unable to add default entry to " "table %u\n", __func__, table_id[i]); } /* Enable input ports */ for (i = 0; i < app.n_ports; i++) if (rte_pipeline_port_in_enable(p, port_in_id[i])) rte_panic("Unable to enable input port %u\n", port_in_id[i]); /* Check pipeline consistency */ if (rte_pipeline_check(p) < 0) rte_panic("%s: Pipeline consistency check failed\n", __func__); /* Run-time */ for (i = 0; ; i++) { rte_pipeline_run(p); if ((i & APP_FLUSH) == 0) rte_pipeline_flush(p); } } void app_main_loop_tx(void) { struct app_mbuf_array *m[APP_MAX_PORTS]; uint32_t i; uint32_t core_id = rte_lcore_id(); struct app_core_params *core_params = app_get_core_params(core_id); if ((core_params == NULL) || (core_params->core_type != APP_CORE_TX)) rte_panic("Core %u misconfiguration\n", core_id); RTE_LOG(INFO, USER1, "Core %u is doing TX (no pipeline)\n", core_id); for (i = 0; i < APP_MAX_PORTS; i++) { m[i] = rte_malloc_socket(NULL, sizeof(struct app_mbuf_array), CACHE_LINE_SIZE, rte_socket_id()); if (m[i] == NULL) rte_panic("%s: Cannot allocate buffer space\n", __func__); } for (i = 0; ; i = ((i + 1) & (app.n_ports - 1))) { uint32_t n_mbufs, n_pkts; int ret; n_mbufs = m[i]->n_mbufs; ret = rte_ring_sc_dequeue_bulk( app.rings[core_params->swq_in[i]], (void **) &m[i]->array[n_mbufs], app.bsz_swq_rd); if (ret == -ENOENT) continue; n_mbufs += app.bsz_swq_rd; if (n_mbufs < app.bsz_hwq_wr) { m[i]->n_mbufs = n_mbufs; continue; } n_pkts = rte_eth_tx_burst( app.ports[i], 0, m[i]->array, n_mbufs); if (n_pkts < n_mbufs) { uint32_t k; for (k = n_pkts; k < n_mbufs; k++) { struct rte_mbuf *pkt_to_free; pkt_to_free = m[i]->array[k]; rte_pktmbuf_free(pkt_to_free); } } m[i]->n_mbufs = 0; } }
int app_thread(void *arg) { struct app_params *app = (struct app_params *) arg; uint32_t core_id = rte_lcore_id(), i, j; struct app_thread_data *t = &app->thread_data[core_id]; uint32_t n_regular = RTE_MIN(t->n_regular, RTE_DIM(t->regular)); uint32_t n_custom = RTE_MIN(t->n_custom, RTE_DIM(t->custom)); for (i = 0; ; i++) { /* Run regular pipelines */ for (j = 0; j < n_regular; j++) { struct app_thread_pipeline_data *data = &t->regular[j]; struct pipeline *p = data->be; rte_pipeline_run(p->p); } /* Run custom pipelines */ for (j = 0; j < n_custom; j++) { struct app_thread_pipeline_data *data = &t->custom[j]; data->f_run(data->be); } /* Timer */ if ((i & 0xF) == 0) { uint64_t time = rte_get_tsc_cycles(); uint64_t t_deadline = UINT64_MAX; if (time < t->deadline) continue; /* Timer for regular pipelines */ for (j = 0; j < n_regular; j++) { struct app_thread_pipeline_data *data = &t->regular[j]; uint64_t p_deadline = data->deadline; if (p_deadline <= time) { data->f_timer(data->be); p_deadline = time + data->timer_period; data->deadline = p_deadline; } if (p_deadline < t_deadline) t_deadline = p_deadline; } /* Timer for custom pipelines */ for (j = 0; j < n_custom; j++) { struct app_thread_pipeline_data *data = &t->custom[j]; uint64_t p_deadline = data->deadline; if (p_deadline <= time) { data->f_timer(data->be); p_deadline = time + data->timer_period; data->deadline = p_deadline; } if (p_deadline < t_deadline) t_deadline = p_deadline; } t->deadline = t_deadline; } } return 0; }
void app_main_loop_worker_pipeline_acl(void) { struct rte_pipeline_params pipeline_params = { .name = "pipeline", .socket_id = rte_socket_id(), }; struct rte_pipeline *p; uint32_t port_in_id[APP_MAX_PORTS]; uint32_t port_out_id[APP_MAX_PORTS]; uint32_t table_id; uint32_t i; RTE_LOG(INFO, USER1, "Core %u is doing work (pipeline with ACL table)\n", rte_lcore_id()); /* Pipeline configuration */ p = rte_pipeline_create(&pipeline_params); if (p == NULL) rte_panic("Unable to configure the pipeline\n"); /* Input port configuration */ for (i = 0; i < app.n_ports; i++) { struct rte_port_ring_reader_params port_ring_params = { .ring = app.rings_rx[i], }; struct rte_pipeline_port_in_params port_params = { .ops = &rte_port_ring_reader_ops, .arg_create = (void *) &port_ring_params, .f_action = NULL, .arg_ah = NULL, .burst_size = app.burst_size_worker_read, }; if (rte_pipeline_port_in_create(p, &port_params, &port_in_id[i])) rte_panic("Unable to configure input port for " "ring %d\n", i); } /* Output port configuration */ for (i = 0; i < app.n_ports; i++) { struct rte_port_ring_writer_params port_ring_params = { .ring = app.rings_tx[i], .tx_burst_sz = app.burst_size_worker_write, }; struct rte_pipeline_port_out_params port_params = { .ops = &rte_port_ring_writer_ops, .arg_create = (void *) &port_ring_params, .f_action = NULL, .arg_ah = NULL, }; if (rte_pipeline_port_out_create(p, &port_params, &port_out_id[i])) rte_panic("Unable to configure output port for " "ring %d\n", i); } /* Table configuration */ { struct rte_table_acl_params table_acl_params = { .name = "test", /* unique identifier for acl contexts */ .n_rules = 1 << 5, .n_rule_fields = DIM(ipv4_field_formats), }; /* Copy in the rule meta-data defined above into the params */ memcpy(table_acl_params.field_format, ipv4_field_formats, sizeof(ipv4_field_formats)); struct rte_pipeline_table_params table_params = { .ops = &rte_table_acl_ops, .arg_create = &table_acl_params, .f_action_hit = NULL, .f_action_miss = NULL, .arg_ah = NULL, .action_data_size = 0, }; if (rte_pipeline_table_create(p, &table_params, &table_id)) rte_panic("Unable to configure the ACL table\n"); } /* Interconnecting ports and tables */ for (i = 0; i < app.n_ports; i++) if (rte_pipeline_port_in_connect_to_table(p, port_in_id[i], table_id)) rte_panic("Unable to connect input port %u to " "table %u\n", port_in_id[i], table_id); /* Add entries to tables */ for (i = 0; i < app.n_ports; i++) { struct rte_pipeline_table_entry table_entry = { .action = RTE_PIPELINE_ACTION_PORT, {.port_id = port_out_id[i & (app.n_ports - 1)]}, }; struct rte_table_acl_rule_add_params rule_params; struct rte_pipeline_table_entry *entry_ptr; int key_found, ret; memset(&rule_params, 0, sizeof(rule_params)); /* Set the rule values */ rule_params.field_value[SRC_FIELD_IPV4].value.u32 = 0; rule_params.field_value[SRC_FIELD_IPV4].mask_range.u32 = 0; rule_params.field_value[DST_FIELD_IPV4].value.u32 = i << (24 - __builtin_popcount(app.n_ports - 1)); rule_params.field_value[DST_FIELD_IPV4].mask_range.u32 = 8 + __builtin_popcount(app.n_ports - 1); rule_params.field_value[SRCP_FIELD_IPV4].value.u16 = 0; rule_params.field_value[SRCP_FIELD_IPV4].mask_range.u16 = UINT16_MAX; rule_params.field_value[DSTP_FIELD_IPV4].value.u16 = 0; rule_params.field_value[DSTP_FIELD_IPV4].mask_range.u16 = UINT16_MAX; rule_params.field_value[PROTO_FIELD_IPV4].value.u8 = 0; rule_params.field_value[PROTO_FIELD_IPV4].mask_range.u8 = 0; rule_params.priority = 0; uint32_t dst_addr = rule_params.field_value[DST_FIELD_IPV4]. value.u32; uint32_t dst_mask = rule_params.field_value[DST_FIELD_IPV4].mask_range.u32; printf("Adding rule to ACL table (IPv4 destination = " "%u.%u.%u.%u/%u => port out = %u)\n", (dst_addr & 0xFF000000) >> 24, (dst_addr & 0x00FF0000) >> 16, (dst_addr & 0x0000FF00) >> 8, dst_addr & 0x000000FF, dst_mask, table_entry.port_id); /* For ACL, add needs an rte_table_acl_rule_add_params struct */ ret = rte_pipeline_table_entry_add(p, table_id, &rule_params, &table_entry, &key_found, &entry_ptr); if (ret < 0) rte_panic("Unable to add entry to table %u (%d)\n", table_id, ret); } /* Enable input ports */ for (i = 0; i < app.n_ports; i++) if (rte_pipeline_port_in_enable(p, port_in_id[i])) rte_panic("Unable to enable input port %u\n", port_in_id[i]); /* Check pipeline consistency */ if (rte_pipeline_check(p) < 0) rte_panic("Pipeline consistency check failed\n"); /* Run-time */ #if APP_FLUSH == 0 for ( ; ; ) rte_pipeline_run(p); #else for (i = 0; ; i++) { rte_pipeline_run(p); if ((i & APP_FLUSH) == 0) rte_pipeline_flush(p); } #endif }
void app_main_loop_pipeline_passthrough(void) { struct rte_pipeline_params pipeline_params = { .name = "pipeline", .socket_id = rte_socket_id(), }; struct rte_pipeline *p; uint32_t port_in_id[APP_MAX_PORTS]; uint32_t port_out_id[APP_MAX_PORTS]; uint32_t table_id[APP_MAX_PORTS]; uint32_t i; uint32_t core_id = rte_lcore_id(); struct app_core_params *core_params = app_get_core_params(core_id); if ((core_params == NULL) || (core_params->core_type != APP_CORE_PT)) rte_panic("Core %u misconfiguration\n", core_id); RTE_LOG(INFO, USER1, "Core %u is doing pass-through\n", core_id); /* Pipeline configuration */ p = rte_pipeline_create(&pipeline_params); if (p == NULL) rte_panic("%s: Unable to configure the pipeline\n", __func__); /* Input port configuration */ for (i = 0; i < app.n_ports; i++) { struct rte_port_ring_reader_params port_ring_params = { .ring = app.rings[core_params->swq_in[i]], }; struct rte_pipeline_port_in_params port_params = { .ops = &rte_port_ring_reader_ops, .arg_create = (void *) &port_ring_params, .f_action = NULL, .arg_ah = NULL, .burst_size = app.bsz_swq_rd, }; if (rte_pipeline_port_in_create(p, &port_params, &port_in_id[i])) { rte_panic("%s: Unable to configure input port for " "ring %d\n", __func__, i); } } /* Output port configuration */ for (i = 0; i < app.n_ports; i++) { struct rte_port_ring_writer_params port_ring_params = { .ring = app.rings[core_params->swq_out[i]], .tx_burst_sz = app.bsz_swq_wr, }; struct rte_pipeline_port_out_params port_params = { .ops = &rte_port_ring_writer_ops, .arg_create = (void *) &port_ring_params, .f_action = NULL, .f_action_bulk = NULL, .arg_ah = NULL, }; if (rte_pipeline_port_out_create(p, &port_params, &port_out_id[i])) { rte_panic("%s: Unable to configure output port for " "ring %d\n", __func__, i); } } /* Table configuration */ for (i = 0; i < app.n_ports; i++) { struct rte_pipeline_table_params table_params = { .ops = &rte_table_stub_ops, .arg_create = NULL, .f_action_hit = NULL, .f_action_miss = NULL, .arg_ah = NULL, .action_data_size = 0, }; if (rte_pipeline_table_create(p, &table_params, &table_id[i])) rte_panic("%s: Unable to configure table %u\n", __func__, i); } /* Interconnecting ports and tables */ for (i = 0; i < app.n_ports; i++) { if (rte_pipeline_port_in_connect_to_table(p, port_in_id[i], table_id[i])) { rte_panic("%s: Unable to connect input port %u to " "table %u\n", __func__, port_in_id[i], table_id[i]); } } /* Add entries to tables */ for (i = 0; i < app.n_ports; i++) { struct rte_pipeline_table_entry default_entry = { .action = RTE_PIPELINE_ACTION_PORT, {.port_id = port_out_id[i]}, }; struct rte_pipeline_table_entry *default_entry_ptr; if (rte_pipeline_table_default_entry_add(p, table_id[i], &default_entry, &default_entry_ptr)) rte_panic("%s: Unable to add default entry to " "table %u\n", __func__, table_id[i]); } /* Enable input ports */ for (i = 0; i < app.n_ports; i++) if (rte_pipeline_port_in_enable(p, port_in_id[i])) rte_panic("Unable to enable input port %u\n", port_in_id[i]); /* Check pipeline consistency */ if (rte_pipeline_check(p) < 0) rte_panic("%s: Pipeline consistency check failed\n", __func__); /* Run-time */ for (i = 0; ; i++) { rte_pipeline_run(p); if ((i & APP_FLUSH) == 0) rte_pipeline_flush(p); } } void app_main_loop_passthrough(void) { struct app_mbuf_array *m; uint32_t i; uint32_t core_id = rte_lcore_id(); struct app_core_params *core_params = app_get_core_params(core_id); if ((core_params == NULL) || (core_params->core_type != APP_CORE_PT)) rte_panic("Core %u misconfiguration\n", core_id); RTE_LOG(INFO, USER1, "Core %u is doing pass-through (no pipeline)\n", core_id); m = rte_malloc_socket(NULL, sizeof(struct app_mbuf_array), RTE_CACHE_LINE_SIZE, rte_socket_id()); if (m == NULL) rte_panic("%s: cannot allocate buffer space\n", __func__); for (i = 0; ; i = ((i + 1) & (app.n_ports - 1))) { int ret; ret = rte_ring_sc_dequeue_bulk( app.rings[core_params->swq_in[i]], (void **) m->array, app.bsz_swq_rd); if (ret == -ENOENT) continue; do { ret = rte_ring_sp_enqueue_bulk( app.rings[core_params->swq_out[i]], (void **) m->array, app.bsz_swq_wr); } while (ret < 0); } }
void app_main_loop_worker_pipeline_lpm_ipv6(void) { struct rte_pipeline_params pipeline_params = { .name = "pipeline", .socket_id = rte_socket_id(), }; struct rte_pipeline *p; uint32_t port_in_id[APP_MAX_PORTS]; uint32_t port_out_id[APP_MAX_PORTS]; uint32_t table_id; uint32_t i; RTE_LOG(INFO, USER1, "Core %u is doing work (pipeline with IPv6 LPM table)\n", rte_lcore_id()); /* Pipeline configuration */ p = rte_pipeline_create(&pipeline_params); if (p == NULL) rte_panic("Unable to configure the pipeline\n"); /* Input port configuration */ for (i = 0; i < app.n_ports; i++) { struct rte_port_ring_reader_params port_ring_params = { .ring = app.rings_rx[i], }; struct rte_pipeline_port_in_params port_params = { .ops = &rte_port_ring_reader_ops, .arg_create = (void *) &port_ring_params, .f_action = NULL, .arg_ah = NULL, .burst_size = app.burst_size_worker_read, }; if (rte_pipeline_port_in_create(p, &port_params, &port_in_id[i])) rte_panic("Unable to configure input port for " "ring %d\n", i); } /* Output port configuration */ for (i = 0; i < app.n_ports; i++) { struct rte_port_ring_writer_params port_ring_params = { .ring = app.rings_tx[i], .tx_burst_sz = app.burst_size_worker_write, }; struct rte_pipeline_port_out_params port_params = { .ops = &rte_port_ring_writer_ops, .arg_create = (void *) &port_ring_params, .f_action = NULL, .f_action_bulk = NULL, .arg_ah = NULL, }; if (rte_pipeline_port_out_create(p, &port_params, &port_out_id[i])) rte_panic("Unable to configure output port for " "ring %d\n", i); } /* Table configuration */ { struct rte_table_lpm_ipv6_params table_lpm_ipv6_params = { .name = "LPM", .n_rules = 1 << 24, .number_tbl8s = 1 << 21, .entry_unique_size = sizeof(struct rte_pipeline_table_entry), .offset = APP_METADATA_OFFSET(32), }; struct rte_pipeline_table_params table_params = { .ops = &rte_table_lpm_ipv6_ops, .arg_create = &table_lpm_ipv6_params, .f_action_hit = NULL, .f_action_miss = NULL, .arg_ah = NULL, .action_data_size = 0, }; if (rte_pipeline_table_create(p, &table_params, &table_id)) rte_panic("Unable to configure the IPv6 LPM table\n"); } /* Interconnecting ports and tables */ for (i = 0; i < app.n_ports; i++) if (rte_pipeline_port_in_connect_to_table(p, port_in_id[i], table_id)) rte_panic("Unable to connect input port %u to " "table %u\n", port_in_id[i], table_id); /* Add entries to tables */ for (i = 0; i < app.n_ports; i++) { struct rte_pipeline_table_entry entry = { .action = RTE_PIPELINE_ACTION_PORT, {.port_id = port_out_id[i & (app.n_ports - 1)]}, }; struct rte_table_lpm_ipv6_key key; struct rte_pipeline_table_entry *entry_ptr; uint32_t ip; int key_found, status; key.depth = 8 + __builtin_popcount(app.n_ports - 1); ip = rte_bswap32(i << (24 - __builtin_popcount(app.n_ports - 1))); memcpy(key.ip, &ip, sizeof(uint32_t)); printf("Adding rule to IPv6 LPM table (IPv6 destination = " "%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:" "%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x/%u => " "port out = %u)\n", key.ip[0], key.ip[1], key.ip[2], key.ip[3], key.ip[4], key.ip[5], key.ip[6], key.ip[7], key.ip[8], key.ip[9], key.ip[10], key.ip[11], key.ip[12], key.ip[13], key.ip[14], key.ip[15], key.depth, i); status = rte_pipeline_table_entry_add(p, table_id, &key, &entry, &key_found, &entry_ptr); if (status < 0) rte_panic("Unable to add entry to table %u (%d)\n", table_id, status); } /* Enable input ports */ for (i = 0; i < app.n_ports; i++) if (rte_pipeline_port_in_enable(p, port_in_id[i])) rte_panic("Unable to enable input port %u\n", port_in_id[i]); /* Check pipeline consistency */ if (rte_pipeline_check(p) < 0) rte_panic("Pipeline consistency check failed\n"); /* Run-time */ #if APP_FLUSH == 0 for ( ; ; ) rte_pipeline_run(p); #else for (i = 0; ; i++) { rte_pipeline_run(p); if ((i & APP_FLUSH) == 0) rte_pipeline_flush(p); } #endif }