aboutsummaryrefslogtreecommitdiff
path: root/test/common_plat/performance/odp_l2fwd.c
diff options
context:
space:
mode:
Diffstat (limited to 'test/common_plat/performance/odp_l2fwd.c')
-rw-r--r--test/common_plat/performance/odp_l2fwd.c155
1 files changed, 123 insertions, 32 deletions
diff --git a/test/common_plat/performance/odp_l2fwd.c b/test/common_plat/performance/odp_l2fwd.c
index 8f5c5e152..78b3633bd 100644
--- a/test/common_plat/performance/odp_l2fwd.c
+++ b/test/common_plat/performance/odp_l2fwd.c
@@ -104,6 +104,7 @@ typedef struct {
int src_change; /**< Change source eth addresses */
int error_check; /**< Check packet errors */
int sched_mode; /**< Scheduler mode */
+ int num_groups; /**< Number of scheduling groups */
} appl_args_t;
static int exit_threads; /**< Break workers loop if set to 1 */
@@ -130,6 +131,7 @@ typedef union {
typedef struct thread_args_t {
int thr_idx;
int num_pktio;
+ int num_groups;
struct {
odp_pktin_queue_t pktin;
@@ -142,7 +144,12 @@ typedef struct thread_args_t {
int tx_queue_idx;
} pktio[MAX_PKTIOS];
- stats_t *stats; /**< Pointer to per thread stats */
+ /* Groups to join */
+ odp_schedule_group_t group[MAX_PKTIOS];
+
+ /* Pointer to per thread stats */
+ stats_t *stats;
+
} thread_args_t;
/**
@@ -297,6 +304,22 @@ static int run_worker_sched_mode(void *arg)
thr = odp_thread_id();
+ if (gbl_args->appl.num_groups) {
+ odp_thrmask_t mask;
+
+ odp_thrmask_zero(&mask);
+ odp_thrmask_set(&mask, thr);
+
+ /* Join non-default groups */
+ for (i = 0; i < thr_args->num_groups; i++) {
+ if (odp_schedule_group_join(thr_args->group[i],
+ &mask)) {
+ LOG_ERR("Join failed\n");
+ return -1;
+ }
+ }
+ }
+
num_pktio = thr_args->num_pktio;
if (num_pktio > MAX_PKTIOS) {
@@ -590,12 +613,13 @@ static int run_worker_direct_mode(void *arg)
* @retval -1 on failure
*/
static int create_pktio(const char *dev, int idx, int num_rx, int num_tx,
- odp_pool_t pool)
+ odp_pool_t pool, odp_schedule_group_t group)
{
odp_pktio_t pktio;
odp_pktio_param_t pktio_param;
odp_schedule_sync_t sync_mode;
odp_pktio_capability_t capa;
+ odp_pktio_config_t config;
odp_pktin_queue_param_t pktin_param;
odp_pktout_queue_param_t pktout_param;
odp_pktio_op_mode_t mode_rx;
@@ -632,6 +656,12 @@ static int create_pktio(const char *dev, int idx, int num_rx, int num_tx,
return -1;
}
+ odp_pktio_config_init(&config);
+ config.parser.layer = gbl_args->appl.error_check ?
+ ODP_PKTIO_PARSER_LAYER_ALL :
+ ODP_PKTIO_PARSER_LAYER_NONE;
+ odp_pktio_config(pktio, &config);
+
odp_pktin_queue_param_init(&pktin_param);
odp_pktout_queue_param_init(&pktout_param);
@@ -650,7 +680,7 @@ static int create_pktio(const char *dev, int idx, int num_rx, int num_tx,
pktin_param.queue_param.sched.prio = ODP_SCHED_PRIO_DEFAULT;
pktin_param.queue_param.sched.sync = sync_mode;
- pktin_param.queue_param.sched.group = ODP_SCHED_GROUP_ALL;
+ pktin_param.queue_param.sched.group = group;
}
if (num_rx > (int)capa.max_input_queues) {
@@ -1016,39 +1046,46 @@ static void usage(char *progname)
printf("\n"
"OpenDataPlane L2 forwarding application.\n"
"\n"
- "Usage: %s OPTIONS\n"
+ "Usage: %s [options]\n"
+ "\n"
" E.g. %s -i eth0,eth1,eth2,eth3 -m 0 -t 1\n"
- " In the above example,\n"
- " eth0 will send pkts to eth1 and vice versa\n"
- " eth2 will send pkts to eth3 and vice versa\n"
+ " In the above example,\n"
+ " eth0 will send pkts to eth1 and vice versa\n"
+ " eth2 will send pkts to eth3 and vice versa\n"
"\n"
"Mandatory OPTIONS:\n"
- " -i, --interface Eth interfaces (comma-separated, no spaces)\n"
- " Interface count min 1, max %i\n"
+ " -i, --interface <name> Eth interfaces (comma-separated, no spaces)\n"
+ " Interface count min 1, max %i\n"
"\n"
"Optional OPTIONS:\n"
- " -m, --mode Packet input mode\n"
- " 0: Direct mode: PKTIN_MODE_DIRECT (default)\n"
- " 1: Scheduler mode with parallel queues: PKTIN_MODE_SCHED + SCHED_SYNC_PARALLEL\n"
- " 2: Scheduler mode with atomic queues: PKTIN_MODE_SCHED + SCHED_SYNC_ATOMIC\n"
- " 3: Scheduler mode with ordered queues: PKTIN_MODE_SCHED + SCHED_SYNC_ORDERED\n"
- " 4: Plain queue mode: ODP_PKTIN_MODE_QUEUE\n"
- " -o, --out_mode Packet output mode\n"
- " 0: Direct mode: PKTOUT_MODE_DIRECT (default)\n"
- " 1: Queue mode: PKTOUT_MODE_QUEUE\n"
- " -c, --count <number> CPU count.\n"
- " -t, --time <number> Time in seconds to run.\n"
- " -a, --accuracy <number> Time in seconds get print statistics\n"
+ " -m, --mode <arg> Packet input mode\n"
+ " 0: Direct mode: PKTIN_MODE_DIRECT (default)\n"
+ " 1: Scheduler mode with parallel queues:\n"
+ " PKTIN_MODE_SCHED + SCHED_SYNC_PARALLEL\n"
+ " 2: Scheduler mode with atomic queues:\n"
+ " PKTIN_MODE_SCHED + SCHED_SYNC_ATOMIC\n"
+ " 3: Scheduler mode with ordered queues:\n"
+ " PKTIN_MODE_SCHED + SCHED_SYNC_ORDERED\n"
+ " 4: Plain queue mode: PKTIN_MODE_QUEUE\n"
+ " -o, --out_mode <arg> Packet output mode\n"
+ " 0: Direct mode: PKTOUT_MODE_DIRECT (default)\n"
+ " 1: Queue mode: PKTOUT_MODE_QUEUE\n"
+ " -c, --count <num> CPU count.\n"
+ " -t, --time <sec> Time in seconds to run.\n"
+ " -a, --accuracy <sec> Time in seconds get print statistics\n"
" (default is 1 second).\n"
- " -d, --dst_change 0: Don't change packets' dst eth addresses\n"
- " 1: Change packets' dst eth addresses (default)\n"
- " -s, --src_change 0: Don't change packets' src eth addresses\n"
- " 1: Change packets' src eth addresses (default)\n"
- " -r, --dst_addr Destination addresses (comma-separated, no spaces)\n"
- " Requires also the -d flag to be set\n"
- " -e, --error_check 0: Don't check packet errors (default)\n"
- " 1: Check packet errors\n"
- " -h, --help Display help and exit.\n\n"
+ " -d, --dst_change <arg> 0: Don't change packets' dst eth addresses\n"
+ " 1: Change packets' dst eth addresses (default)\n"
+ " -s, --src_change <arg> 0: Don't change packets' src eth addresses\n"
+ " 1: Change packets' src eth addresses (default)\n"
+ " -r, --dst_addr <addr> Destination addresses (comma-separated, no spaces)\n"
+ " Requires also the -d flag to be set\n"
+ " -e, --error_check <arg> 0: Don't check packet errors (default)\n"
+ " 1: Check packet errors\n"
+ " -g, --groups <num> Number of groups to use: 0 ... num\n"
+ " 0: SCHED_GROUP_ALL (default)\n"
+ " num: must not exceed number of interfaces or workers\n"
+ " -h, --help Display help and exit.\n\n"
"\n", NO_PATH(progname), NO_PATH(progname), MAX_PKTIOS
);
}
@@ -1079,11 +1116,12 @@ static void parse_args(int argc, char *argv[], appl_args_t *appl_args)
{"dst_change", required_argument, NULL, 'd'},
{"src_change", required_argument, NULL, 's'},
{"error_check", required_argument, NULL, 'e'},
+ {"groups", required_argument, NULL, 'g'},
{"help", no_argument, NULL, 'h'},
{NULL, 0, NULL, 0}
};
- static const char *shortopts = "+c:+t:+a:i:m:o:r:d:s:e:h";
+ static const char *shortopts = "+c:+t:+a:i:m:o:r:d:s:e:g:h";
/* let helper collect its own arguments (e.g. --odph_proc) */
odph_parse_options(argc, argv, shortopts, longopts);
@@ -1092,6 +1130,7 @@ static void parse_args(int argc, char *argv[], appl_args_t *appl_args)
appl_args->accuracy = 1; /* get and print pps stats second */
appl_args->dst_change = 1; /* change eth dst address by default */
appl_args->src_change = 1; /* change eth src address by default */
+ appl_args->num_groups = 0; /* use default group */
appl_args->error_check = 0; /* don't check packet errors by default */
opterr = 0; /* do not issue errors on helper options */
@@ -1217,6 +1256,9 @@ static void parse_args(int argc, char *argv[], appl_args_t *appl_args)
case 'e':
appl_args->error_check = atoi(optarg);
break;
+ case 'g':
+ appl_args->num_groups = atoi(optarg);
+ break;
case 'h':
usage(argv[0]);
exit(EXIT_SUCCESS);
@@ -1305,6 +1347,24 @@ static void gbl_args_init(args_t *args)
}
}
+static void create_groups(int num, odp_schedule_group_t *group)
+{
+ int i;
+ odp_thrmask_t zero;
+
+ odp_thrmask_zero(&zero);
+
+ /* Create groups */
+ for (i = 0; i < num; i++) {
+ group[i] = odp_schedule_group_create(NULL, &zero);
+
+ if (group[i] == ODP_SCHED_GROUP_INVALID) {
+ LOG_ERR("Group create failed\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+}
+
/**
* ODP L2 forwarding main function
*/
@@ -1325,6 +1385,8 @@ int main(int argc, char *argv[])
int if_count;
int (*thr_run_func)(void *);
odp_instance_t instance;
+ int num_groups;
+ odp_schedule_group_t group[MAX_PKTIOS];
/* Init ODP before calling anything else */
if (odp_init_global(&instance, NULL, NULL)) {
@@ -1374,10 +1436,23 @@ int main(int argc, char *argv[])
if_count = gbl_args->appl.if_count;
+ num_groups = gbl_args->appl.num_groups;
+
printf("num worker threads: %i\n", num_workers);
printf("first CPU: %i\n", odp_cpumask_first(&cpumask));
printf("cpu mask: %s\n", cpumaskstr);
+ if (num_groups)
+ printf("num groups: %i\n", num_groups);
+
+ printf("\n");
+
+ if (num_groups > if_count || num_groups > num_workers) {
+ LOG_ERR("Too many groups. Number of groups may not exceed "
+ "number of interfaces or workers.\n");
+ exit(EXIT_FAILURE);
+ }
+
/* Create packet pool */
odp_pool_param_init(&params);
params.pkt.seg_len = SHM_PKT_POOL_BUF_SIZE;
@@ -1399,9 +1474,18 @@ int main(int argc, char *argv[])
bind_workers();
+ /* Default */
+ if (num_groups == 0) {
+ group[0] = ODP_SCHED_GROUP_ALL;
+ num_groups = 1;
+ } else {
+ create_groups(num_groups, group);
+ }
+
for (i = 0; i < if_count; ++i) {
const char *dev = gbl_args->appl.if_names[i];
int num_rx, num_tx;
+ odp_schedule_group_t grp;
/* A queue per worker in scheduled mode */
num_rx = num_workers;
@@ -1413,7 +1497,10 @@ int main(int argc, char *argv[])
num_tx = gbl_args->pktios[i].num_tx_thr;
}
- if (create_pktio(dev, i, num_rx, num_tx, pool))
+ /* Round robin pktios to groups */
+ grp = group[i % num_groups];
+
+ if (create_pktio(dev, i, num_rx, num_tx, pool, grp))
exit(EXIT_FAILURE);
/* Save interface ethernet address */
@@ -1473,6 +1560,10 @@ int main(int argc, char *argv[])
thr_params.thr_type = ODP_THREAD_WORKER;
thr_params.instance = instance;
+ /* Round robin threads to groups */
+ gbl_args->thread[i].num_groups = 1;
+ gbl_args->thread[i].group[0] = group[i % num_groups];
+
gbl_args->thread[i].stats = &stats[i];
odp_cpumask_zero(&thd_mask);