27#include <odp/helper/odph_api.h>
36#define MAX_WORKERS (ODP_THREAD_COUNT_MAX - 1)
41#define MAX_PKT_BURST 64
46#define DEF_PKT_BURST 32
51#define SHM_PKT_POOL_SIZE 10000
56#define SHM_PKT_POOL_BUF_SIZE 1856
61#define MAX_PMR_COUNT 32
66#define DISPLAY_STRING_LEN 32
69#define MAX_VAL_SIZE 16
72#define NO_PATH(file_name) (strrchr((file_name), '/') ? \
73 strrchr((file_name), '/') + 1 : (file_name))
86 uint8_t value_be[MAX_VAL_SIZE];
87 uint8_t mask_be[MAX_VAL_SIZE];
91 char value[DISPLAY_STRING_LEN];
92 char mask[DISPLAY_STRING_LEN];
113 global_statistics stats[MAX_PMR_COUNT];
114 ci_pass_counters ci_pass_rules[MAX_PMR_COUNT];
115 cos_q_param_t cos_q_param[MAX_PMR_COUNT];
117 int num_ci_pass_rules;
121 unsigned int cpu_count;
128 int classifier_enable;
133 uint32_t vector_size;
142static appl_args_t *appl_args_gbl;
144static int drop_err_pkts(
odp_packet_t pkt_tbl[],
unsigned len);
145static void swap_pkt_addrs(
odp_packet_t pkt_tbl[],
unsigned len);
146static int parse_args(
int argc,
char *argv[], appl_args_t *appl_args);
147static void print_info(
char *progname, appl_args_t *appl_args);
148static void usage(
void);
150static inline int check_ci_pass_count(appl_args_t *args)
155 if (args->num_ci_pass_rules == 0)
158 for (i = 0; i < args->num_ci_pass_rules; i++) {
159 for (j = 0; j < args->policy_count; j++) {
160 if (!strcmp(args->stats[j].cos_name,
161 args->ci_pass_rules[i].cos_name)) {
163 if (args->ci_pass_rules[i].count > count) {
164 ODPH_ERR(
"Error: Cos = %s, expected packets = %" PRIu64
","
165 "received packet = %" PRIu64
"\n",
166 args->stats[j].cos_name,
167 args->ci_pass_rules[i].count, count);
173 if (j == args->policy_count) {
174 ODPH_ERR(
"Error: invalid Cos:%s specified for CI pass count\n",
175 args->ci_pass_rules[i].cos_name);
182static inline void print_cls_statistics(appl_args_t *args)
189 for (i = 0; i < 40; i++)
193 printf(
"CLASSIFIER EXAMPLE STATISTICS\n");
194 for (i = 0; i < 40; i++)
197 printf(
"CONFIGURATION\n");
199 printf(
"COS\tVALUE\t\tMASK\n");
200 for (i = 0; i < 40; i++)
203 for (i = 0; i < args->policy_count - 1; i++) {
204 printf(
"%s\t", args->stats[i].cos_name);
205 printf(
"%s\t", args->stats[i].value);
206 printf(
"%s\n", args->stats[i].mask);
209 printf(
"RECEIVED PACKETS\n");
210 for (i = 0; i < 40; i++)
213 for (i = 0; i < args->policy_count; i++)
214 printf(
"%-12s |", args->stats[i].cos_name);
215 printf(
"%-6s %-6s",
"Total",
"Mpps");
217 for (i = 0; i < args->policy_count; i++)
218 printf(
"%-6s %-6s|",
"queue",
"pool");
221 timeout = args->time;
228 uint64_t total_packets, last_total_packets = 0;
232 for (; timeout > 0 || infinite; timeout--) {
234 for (i = 0; i < args->policy_count; i++) {
235 printf(
"%-6" PRIu64
" ",
238 printf(
"%-6" PRIu64
"|",
245 mpps = (total_packets - last_total_packets) /
247 printf(
"%-6" PRIu64
" %-6.3f\n", total_packets, mpps);
248 last_total_packets = total_packets;
251 if (args->shutdown_sig)
258static int parse_custom(
const char *str, uint8_t *buf_be,
int max_size)
264 if (len > 2 * max_size)
267 for (i = 0; i < len; i += 2)
268 if (sscanf(&str[i],
"%2" SCNx8, &buf_be[i / 2]) != 1)
299 ODPH_ERR(
"pktio create failed for %s\n", dev);
304 ODPH_ERR(
"pktio capability failed for %s\n", dev);
312 ODPH_ERR(
"pktin queue config failed for %s\n", dev);
316 num_tx = appl_args_gbl->cpu_count;
319 printf(
"Sharing %i output queues between %i workers\n",
324 appl_args_gbl->num_pktout = num_tx;
330 ODPH_ERR(
"pktout queue config failed for %s\n", dev);
335 ODPH_ERR(
"Pktout queue query failed: %s\n", dev);
341 ODPH_ERR(
"enabling promisc mode not supported %s\n", dev);
346 ODPH_ERR(
"failed to enable promisc mode for %s\n", dev);
357 for (
int c = 0; c < (int)
sizeof(mac); c++)
358 printf(
":%02x", mac.addr[c]);
366 ODPH_ERR(
"failed to configure pktio %s\n", dev);
378 int i, j, dropped, sent;
379 global_statistics *stats;
380 unsigned long err_cnt = 0;
383 static __thread uint64_t batch;
388 const char *orig = was_vector ?
"vector" :
"packet";
392 for (j = 0; j < num; j++) {
395 printf(
"Queue: %s, origin: %s, thread: %d, batch: %" PRIu64
"\n", qname,
412 dropped = drop_err_pkts(pkts, num);
416 ODPH_ERR(
"Drop frame - err_cnt:%lu\n", err_cnt);
419 for (j = 0; j < num; j++) {
422 for (i = 0; i < MAX_PMR_COUNT; i++) {
423 stats = &appl->stats[i];
424 if (in_q == stats->queue)
426 if (pool == stats->pool)
431 if (appl->appl_mode == APPL_MODE_DROP) {
437 swap_pkt_addrs(pkts, num);
440 sent = sent < 0 ? 0 : sent;
443 ODPH_ERR(
" [%i] Packet send failed\n", thr);
452static int pktio_receive_thread(
void *arg)
459 int num_recv, num_pkts, vector_size;
461 appl_args_t *appl = (appl_args_t *)arg;
479 for (
int i = 0; i < num_recv; i++) {
483 if (type == ODP_EVENT_VECTOR) {
490 process_packets(vector_pkts, vector_size, queue, pktout, appl, thr,
494 }
else if (type == ODP_EVENT_PACKET) {
497 ODPH_ERR(
"Unexpected event received, type: %d, freeing\n", type);
503 process_packets(single_pkts, num_pkts, queue, pktout, appl, thr,
false);
509static odp_pool_t create_vector_pool(appl_args_t *args)
525 ODPH_ERR(
"Error: failed to create event vector pool\n");
529 printf(
"created singleton event vector pool: %" PRIu64
", size: %u, vector size: %u\n",
535static void destroy_vector_pool(
odp_pool_t pool)
547static odp_pool_t pool_create(
const char *name)
556 pool_params.
pkt.
seg_len = SHM_PKT_POOL_BUF_SIZE;
557 pool_params.
pkt.
len = SHM_PKT_POOL_BUF_SIZE;
558 pool_params.
pkt.
num = appl_args_gbl->pool_size;
563 ODPH_ERR(
"Error: failed to create pool %s\n", name);
573 const char *queue_name =
"DefaultQueue";
574 const char *pool_name =
"DefaultPool";
575 const char *cos_name =
"DefaultCos";
580 global_statistics *stats = args->stats;
589 ODPH_ERR(
"Error: default queue create failed\n");
593 pool_default = pool_create(pool_name);
596 cls_param.
pool = pool_default;
597 cls_param.
queue = queue_default;
602 ODPH_ERR(
"Error: default cos create failed\n");
607 ODPH_ERR(
"odp_pktio_default_cos_set failed\n");
610 stats[args->policy_count].cos = cos_default;
612 stats[args->policy_count].queue = queue_default;
613 if (appl_args_gbl->cos_pools)
614 stats[args->policy_count].pool = pool_default;
615 snprintf(stats[args->policy_count].cos_name,
616 sizeof(stats[args->policy_count].cos_name),
620 args->policy_count++;
624static cos_q_param_t *find_cos_q_param(appl_args_t *args,
const char *name)
628 for (i = 0; i < args->num_cos_q_param; i++) {
629 if (strcmp(args->cos_q_param[i].cos_name, name) == 0)
630 return &args->cos_q_param[i];
636static int find_cos(appl_args_t *args,
const char *name,
odp_cos_t *cos)
638 global_statistics *stats;
641 for (i = 0; i < args->policy_count - 1; i++) {
642 stats = &args->stats[i];
644 if (strcmp(stats->cos_name, name) == 0) {
653static void configure_cos(
odp_cos_t default_cos, appl_args_t *args)
657 const char *queue_name;
660 cos_q_param_t *cq_param;
661 global_statistics *stats;
664 for (i = 0; i < args->policy_count - 1; i++) {
665 stats = &args->stats[i];
666 queue_name = stats->cos_name;
671 cq_param = find_cos_q_param(args, queue_name);
673 if (cq_param != NULL) {
676 qparam.
num_aggr = cq_param->num_aggr;
677 qparam.
aggr = &cq_param->q_aggr;
685 ODPH_ERR(
"odp_queue_create failed\n");
689 snprintf(pool_name,
sizeof(pool_name),
"%sPool%d",
690 args->stats[i].cos_name, i);
692 snprintf(cos_name,
sizeof(cos_name),
"CoS%s",
694 cls_param.
pool = pool_create(pool_name);
695 if (appl_args_gbl->cos_pools)
696 stats->pool = cls_param.
pool;
698 if (cq_param != NULL && cq_param->num_aggr > 0)
701 cls_param.
queue = stats->queue;
706 ODPH_ERR(
"odp_cls_cos_create failed\n");
714 for (i = 0; i < args->policy_count - 1; i++) {
718 stats = &args->stats[i];
720 if (stats->has_src_cos) {
721 if (find_cos(args, stats->src_cos_name, &src_cos)) {
722 ODPH_ERR(
"find_cos failed\n");
728 pmr_param.
term = stats->rule.term;
730 pmr_param.
match.
mask = stats->rule.mask_be;
731 pmr_param.
val_sz = stats->rule.val_sz;
732 pmr_param.
offset = stats->rule.offset;
737 ODPH_ERR(
"odp_pktio_pmr_cos failed\n");
744static void sig_handler(
int signo)
748 if (appl_args_gbl == NULL)
750 appl_args_gbl->shutdown_sig = 1;
756int main(
int argc,
char *argv[])
758 odph_helper_options_t helper_options;
759 odph_thread_t thread_tbl[MAX_WORKERS];
772 odph_thread_common_param_t thr_common;
773 odph_thread_param_t thr_param;
775 signal(SIGINT, sig_handler);
778 argc = odph_parse_options(argc, argv);
779 if (odph_options(&helper_options)) {
780 ODPH_ERR(
"Error: reading ODP helper options failed\n");
785 init_param.
mem_model = helper_options.mem_model;
789 ODPH_ERR(
"Error: ODP global init failed\n");
795 ODPH_ERR(
"Error: ODP local init failed\n");
801 ODP_CACHE_LINE_SIZE, 0);
804 ODPH_ERR(
"Error: shared mem reserve failed\n");
811 ODPH_ERR(
"Error: shared mem alloc failed\n");
815 appl_args_gbl = args;
816 memset(args, 0,
sizeof(*args));
819 if (parse_args(argc, argv, args))
823 print_info(NO_PATH(argv[0]), args);
825 num_workers = MAX_WORKERS;
826 if (args->cpu_count && args->cpu_count < MAX_WORKERS)
827 num_workers = args->cpu_count;
833 printf(
"num worker threads: %i\n", num_workers);
835 printf(
"cpu mask: %s\n", cpumaskstr);
838 pool = pool_create(
"packet_pool");
840 for (i = 0; i < args->num_cos_q_param; i++) {
841 if (args->cos_q_param[i].num_aggr > 0)
842 args->cos_q_param[i].q_aggr.pool = create_vector_pool(args);
852 pktio = create_pktio(args->if_name, pool);
855 default_cos = configure_default_cos(pktio, args);
857 configure_cos(default_cos, args);
865 ODPH_ERR(
"Error: unable to start pktio\n");
870 memset(thread_tbl, 0,
sizeof(thread_tbl));
871 odph_thread_common_param_init(&thr_common);
872 odph_thread_param_init(&thr_param);
874 thr_param.start = pktio_receive_thread;
875 thr_param.arg = args;
878 thr_common.instance = instance;
879 thr_common.cpumask = &cpumask;
880 thr_common.share_param = 1;
882 odph_thread_create(thread_tbl, &thr_common, &thr_param, num_workers);
884 if (args->verbose == 0) {
885 print_cls_statistics(args);
887 int timeout = args->time;
889 for (i = 0; timeout == 0 || i < timeout; i++) {
890 if (args->shutdown_sig)
899 odph_thread_join(thread_tbl, num_workers);
901 if (check_ci_pass_count(args)) {
902 ODPH_ERR(
"Error: Packet count verification failed\n");
906 for (i = 0; i < args->policy_count; i++) {
907 if ((i != args->policy_count - 1) &&
909 ODPH_ERR(
"err: odp_cls_pmr_destroy for %d\n", i);
911 ODPH_ERR(
"err: odp_cos_destroy for %d\n", i);
913 ODPH_ERR(
"err: odp_queue_destroy for %d\n", i);
915 ODPH_ERR(
"err: odp_pool_destroy for %d\n", i);
919 ODPH_ERR(
"err: close pktio error\n");
921 for (i = 0; i < args->num_cos_q_param; i++) {
922 cos_q_param_t *cos_q_param = &args->cos_q_param[i];
925 destroy_vector_pool(cos_q_param->q_aggr.pool);
929 ODPH_ERR(
"err: odp_pool_destroy error\n");
938 ODPH_ERR(
"odp_term_local error %d\n", ret);
941 ODPH_ERR(
"odp_term_global error %d\n", ret);
957static int drop_err_pkts(
odp_packet_t pkt_tbl[],
unsigned len)
963 for (i = 0, j = 0; i < len; ++i) {
983static void swap_pkt_addrs(
odp_packet_t pkt_tbl[],
unsigned len)
987 odph_ethaddr_t tmp_addr;
992 for (i = 0; i < len; ++i) {
1003 ip = (odph_ipv4hdr_t *)
1006 ip_tmp_addr = ip->src_addr;
1007 ip->src_addr = ip->dst_addr;
1008 ip->dst_addr = ip_tmp_addr;
1019 if (strcasecmp(token,
"ODP_PMR_ETHTYPE_0") == 0) {
1022 }
else if (strcasecmp(token,
"ODP_PMR_ETHTYPE_X") == 0) {
1025 }
else if (strcasecmp(token,
"ODP_PMR_VLAN_ID_0") == 0) {
1028 }
else if (strcasecmp(token,
"ODP_PMR_VLAN_ID_X") == 0) {
1031 }
else if (strcasecmp(token,
"ODP_PMR_UDP_DPORT") == 0) {
1034 }
else if (strcasecmp(token,
"ODP_PMR_TCP_DPORT") == 0) {
1037 }
else if (strcasecmp(token,
"ODP_PMR_UDP_SPORT") == 0) {
1040 }
else if (strcasecmp(token,
"ODP_PMR_TCP_SPORT") == 0) {
1043 }
else if (strcasecmp(token,
"ODP_PMR_DIP_ADDR") == 0) {
1046 }
else if (strcasecmp(token,
"ODP_PMR_SIP_ADDR") == 0) {
1049 }
else if (strcasecmp(token,
"ODP_PMR_DMAC") == 0) {
1052 }
else if (strcasecmp(token,
"ODP_PMR_CUSTOM_FRAME") == 0) {
1055 }
else if (strcasecmp(token,
"ODP_PMR_CUSTOM_L3") == 0) {
1063static int parse_pmr_policy(appl_args_t *appl_args,
char *optarg)
1066 char *token, *cos0, *cos1, *cur_char;
1069 global_statistics *stats;
1072 uint32_t offset, ip_addr, u32;
1073 unsigned long int value, mask;
1075 int val_sz, mask_sz;
1077 policy_count = appl_args->policy_count;
1078 stats = appl_args->stats;
1081 if (policy_count >= MAX_PMR_COUNT - 1) {
1082 ODPH_ERR(
"Too many policies. Max count is %i.\n",
1087 len = strlen(optarg);
1089 pmr_str = malloc(len);
1090 if (pmr_str == NULL) {
1091 ODPH_ERR(
"Memory allocation failed\n");
1094 strcpy(pmr_str, optarg);
1098 token = strtok(pmr_str,
":");
1099 if (convert_str_to_pmr_enum(token, &term)) {
1100 ODPH_ERR(
"Invalid ODP_PMR_TERM string\n");
1103 stats[policy_count].rule.term = term;
1104 stats[policy_count].rule.offset = 0;
1126 token = strtok(NULL,
":");
1127 odph_strcpy(stats[policy_count].value, token,
1128 DISPLAY_STRING_LEN);
1129 value = strtoul(token, NULL, 0);
1132 memcpy(stats[policy_count].rule.value_be, &u16,
sizeof(u16));
1134 token = strtok(NULL,
":");
1135 odph_strcpy(stats[policy_count].mask, token,
1136 DISPLAY_STRING_LEN);
1137 mask = strtoul(token, NULL, 0);
1140 memcpy(stats[policy_count].rule.mask_be, &u16,
sizeof(u16));
1142 stats[policy_count].rule.val_sz = 2;
1148 token = strtok(NULL,
":");
1149 odph_strcpy(stats[policy_count].value, token,
1150 DISPLAY_STRING_LEN);
1152 if (odph_ipv4_addr_parse(&ip_addr, token)) {
1153 ODPH_ERR(
"Bad IP address\n");
1158 memcpy(stats[policy_count].rule.value_be, &u32,
sizeof(u32));
1160 token = strtok(NULL,
":");
1161 odph_strcpy(stats[policy_count].mask, token,
1162 DISPLAY_STRING_LEN);
1163 mask = strtoul(token, NULL, 0);
1166 memcpy(stats[policy_count].rule.mask_be, &u32,
sizeof(u32));
1168 stats[policy_count].rule.val_sz = 4;
1172 token = strtok(NULL,
":");
1173 odph_strcpy(stats[policy_count].value, token,
1174 DISPLAY_STRING_LEN);
1179 while ((cur_char = strchr(cur_char,
'-')) != NULL)
1182 if (odph_eth_addr_parse(&mac, token)) {
1183 ODPH_ERR(
"Invalid MAC address. Use format 11-22-33-44-55-66.\n");
1187 memcpy(stats[policy_count].rule.value_be, mac.addr, ODPH_ETHADDR_LEN);
1188 stats[policy_count].rule.val_sz = 6;
1190 token = strtok(NULL,
":");
1191 odph_strcpy(stats[policy_count].mask, token, DISPLAY_STRING_LEN);
1192 mask_sz = parse_custom(token, stats[policy_count].rule.mask_be, ODPH_ETHADDR_LEN);
1193 if (mask_sz != ODPH_ETHADDR_LEN) {
1194 ODPH_ERR(
"Invalid mask. Provide mask without 0x prefix.\n");
1202 token = strtok(NULL,
":");
1204 offset = strtoul(token, NULL, 0);
1205 stats[policy_count].rule.offset = offset;
1209 token = strtok(NULL,
":");
1210 odph_strcpy(stats[policy_count].value, token,
1211 DISPLAY_STRING_LEN);
1212 val_sz = parse_custom(token,
1213 stats[policy_count].rule.value_be,
1215 stats[policy_count].rule.val_sz = val_sz;
1219 token = strtok(NULL,
":");
1220 odph_strcpy(stats[policy_count].mask, token,
1221 DISPLAY_STRING_LEN);
1222 mask_sz = parse_custom(token,
1223 stats[policy_count].rule.mask_be,
1225 if (mask_sz != val_sz)
1234 cos0 = strtok(NULL,
":");
1235 cos1 = strtok(NULL,
":");
1240 stats[policy_count].has_src_cos = 1;
1241 odph_strcpy(stats[policy_count].src_cos_name, cos0,
1243 odph_strcpy(stats[policy_count].cos_name, cos1,
1246 odph_strcpy(stats[policy_count].cos_name, cos0,
1250 appl_args->policy_count++;
1259static int parse_cos_q_param(appl_args_t *appl_args,
char *optarg)
1261 char *tmp_str = strdup(optarg), *tmp;
1262 cos_q_param_t *cos_q_param;
1265 if (tmp_str == NULL)
1266 ODPH_ABORT(
"Failed to allocate memory, aborting.\n");
1268 if (appl_args->num_cos_q_param >= MAX_PMR_COUNT) {
1269 ODPH_ERR(
"Too many queue CoS configurations. Max count is %i.\n", MAX_PMR_COUNT);
1274 cos_q_param = &appl_args->cos_q_param[appl_args->num_cos_q_param];
1276 tmp = strtok(tmp_str,
":");
1279 ODPH_ERR(
"CoS queue name missing.\n");
1284 if (find_cos_q_param(appl_args, tmp) != NULL) {
1285 printf(
"Warning: duplicate CoS queue parameter entry for \"%s\", skipping.\n",
1291 tmp = strtok(NULL,
":");
1294 ODPH_ERR(
"CoS queue priority missing.\n");
1299 cos_q_param->q_prio = strcmp(tmp,
"default") == 0 ?
1301 tmp = strtok(NULL,
":");
1304 ODPH_ERR(
"CoS queue synchronization type missing.\n");
1309 if (strcmp(tmp,
"ODP_SCHED_SYNC_PARALLEL") == 0) {
1311 }
else if (strcmp(tmp,
"ODP_SCHED_SYNC_ATOMIC") == 0) {
1313 }
else if (strcmp(tmp,
"ODP_SCHED_SYNC_ORDERED") == 0) {
1316 ODPH_ERR(
"Invalid queue synchronization type: \"%s\".\n", tmp);
1321 tmp = strtok(NULL,
":");
1324 ODPH_ERR(
"CoS queue aggregator enqueue profile type missing.\n");
1329 if (strcmp(tmp,
"ODP_AEP_TYPE_NONE") == 0) {
1330 cos_q_param->cos_enq_prof.type = ODP_AEP_TYPE_NONE;
1331 }
else if (strcmp(tmp,
"ODP_AEP_TYPE_IPV4_FRAG") == 0) {
1332 cos_q_param->cos_enq_prof.type = ODP_AEP_TYPE_IPV4_FRAG;
1333 }
else if (strcmp(tmp,
"ODP_AEP_TYPE_IPV6_FRAG") == 0) {
1334 cos_q_param->cos_enq_prof.type = ODP_AEP_TYPE_IPV6_FRAG;
1335 }
else if (strcmp(tmp,
"ODP_AEP_TYPE_CUSTOM") == 0) {
1336 cos_q_param->cos_enq_prof.type = ODP_AEP_TYPE_CUSTOM;
1337 tmp = strtok(NULL,
":");
1340 ODPH_ERR(
"Custom aggregator enqueue profile param missing.\n");
1345 cos_q_param->cos_enq_prof.param = (uintptr_t)strtoll(tmp, NULL, 16);
1347 ODPH_ERR(
"Invalid queue aggregator enqueue profile type: \"%s\".\n", tmp);
1352 tmp = strtok(NULL,
":");
1355 cos_q_param->q_aggr.max_tmo_ns = atoll(tmp);
1356 tmp = strtok(NULL,
":");
1359 ODPH_ERR(
"Malformed aggregator parameter format.\n");
1364 cos_q_param->q_aggr.max_size = atoi(tmp);
1365 cos_q_param->q_aggr.event_type = ODP_EVENT_PACKET;
1366 cos_q_param->num_aggr = 1;
1369 appl_args->num_cos_q_param++;
1370 appl_args->vector_size = ODPH_MAX(appl_args->vector_size, cos_q_param->q_aggr.max_size);
1378static int check_cos_q_param_policies(appl_args_t *appl_args)
1382 for (
int i = 0; i < appl_args->num_cos_q_param; i++) {
1383 const char *cq_name = appl_args->cos_q_param[i].cos_name;
1385 for (j = 0; j < appl_args->policy_count; j++) {
1386 if (strcmp(appl_args->stats[j].cos_name, cq_name) == 0)
1390 if (j == appl_args->policy_count) {
1391 ODPH_ERR(
"No matching policy found for cos_queue_param \"%s\"\n", cq_name);
1399static int parse_policy_ci_pass_count(appl_args_t *appl_args,
char *optarg)
1401 int num_ci_pass_rules;
1402 char *token, *value;
1404 ci_pass_counters *ci_pass_rules;
1407 num_ci_pass_rules = appl_args->num_ci_pass_rules;
1408 ci_pass_rules = appl_args->ci_pass_rules;
1411 if (num_ci_pass_rules >= MAX_PMR_COUNT) {
1412 ODPH_ERR(
"Too many ci pass counters. Max count is %i.\n",
1417 len = strlen(optarg);
1419 count_str = malloc(len);
1420 if (count_str == NULL) {
1421 ODPH_ERR(
"Memory allocation failed\n");
1424 strcpy(count_str, optarg);
1426 token = strtok(count_str,
":");
1427 value = strtok(NULL,
":");
1428 if (!token || !value) {
1432 odph_strcpy(ci_pass_rules[num_ci_pass_rules].cos_name, token,
ODP_COS_NAME_LEN);
1433 ci_pass_rules[num_ci_pass_rules].count = atoll(value);
1434 appl_args->num_ci_pass_rules++;
1446static int parse_args(
int argc,
char *argv[], appl_args_t *appl_args)
1454 static const struct option longopts[] = {
1455 {
"count", required_argument, NULL,
'c'},
1456 {
"interface", required_argument, NULL,
'i'},
1457 {
"policy", required_argument, NULL,
'p'},
1458 {
"cos_queue_param", required_argument, NULL,
'q'},
1459 {
"mode", required_argument, NULL,
'm'},
1460 {
"time", required_argument, NULL,
't'},
1461 {
"ci_pass", required_argument, NULL,
'C'},
1462 {
"promisc_mode", no_argument, NULL,
'P'},
1463 {
"verbose", no_argument, NULL,
'v'},
1464 {
"help", no_argument, NULL,
'h'},
1465 {
"enable", required_argument, NULL,
'e'},
1466 {
"layer", required_argument, NULL,
'l'},
1467 {
"dedicated", required_argument, NULL,
'd'},
1468 {
"size", required_argument, NULL,
's'},
1469 {
"burst", required_argument, NULL,
'b'},
1473 static const char *shortopts =
"+c:t:i:p:q:m:t:C:Pvhe:l:d:s:b:";
1475 appl_args->cpu_count = 1;
1476 appl_args->verbose = 0;
1477 appl_args->promisc_mode = 0;
1478 appl_args->classifier_enable = 1;
1480 appl_args->cos_pools = 1;
1481 appl_args->pool_size = SHM_PKT_POOL_SIZE;
1482 appl_args->burst_size = DEF_PKT_BURST;
1485 opt = getopt_long(argc, argv, shortopts,
1493 appl_args->cpu_count = atoi(optarg);
1496 if (parse_pmr_policy(appl_args, optarg)) {
1502 if (parse_cos_q_param(appl_args, optarg)) {
1508 appl_args->time = atoi(optarg);
1511 len = strlen(optarg);
1518 appl_args->if_name = malloc(len);
1519 if (appl_args->if_name == NULL) {
1524 strcpy(appl_args->if_name, optarg);
1530 appl_args->appl_mode = APPL_MODE_DROP;
1532 appl_args->appl_mode = APPL_MODE_REPLY;
1535 if (parse_policy_ci_pass_count(appl_args, optarg)) {
1541 appl_args->promisc_mode = 1;
1544 appl_args->verbose = 1;
1550 appl_args->classifier_enable = atoi(optarg);
1553 appl_args->parse_layer = atoi(optarg);
1556 appl_args->cos_pools = atoi(optarg);
1559 appl_args->pool_size = atoi(optarg);
1562 appl_args->burst_size = atoi(optarg);
1572 if (appl_args->if_name == NULL)
1575 if (!ret && check_cos_q_param_policies(appl_args))
1580 free(appl_args->if_name);
1592static void print_info(
char *progname, appl_args_t *appl_args)
1596 printf(
"Running ODP appl: \"%s\"\n"
1597 "-----------------\n"
1599 progname, appl_args->if_name);
1600 printf(
"Promisc mode: %s\n", appl_args->promisc_mode ?
"enabled" :
"disabled");
1608static void usage(
void)
1611 "ODP Classifier example.\n"
1612 "Usage: odp_classifier OPTIONS\n"
1613 " E.g. odp_classifier -i eth1 -m 0 -p \"ODP_PMR_SIP_ADDR:10.10.10.0:0xFFFFFF00:queue1\" \\\n"
1614 " -p \"ODP_PMR_SIP_ADDR:10.10.10.10:0xFFFFFFFF:queue1:queue2\" \\\n"
1615 " -q \"queue1:1:ODP_SCHED_SYNC_PARALLEL:ODP_AEP_TYPE_NONE\" \\\n"
1616 " -q \"queue2:3:ODP_SCHED_SYNC_ATOMIC:ODP_AEP_TYPE_CUSTOM:1234:0:4\"\n"
1618 "The above example would classify:\n"
1619 " 1) Packets from source IP address 10.10.10.0/24 to queue1, except ...\n"
1620 " 2) Packets from source IP address 10.10.10.10 to queue2\n"
1621 " 3) All other packets to DefaultCos\n"
1623 "Mandatory OPTIONS:\n"
1624 " -i, --interface <interface name>\n"
1626 "Optional OPTIONS\n"
1627 " -p, --policy <PMR term>:<offset>:<value>:<mask>:<src queue>:<dst queue>\n"
1629 " <PMR term> PMR term name defined in odp_cls_pmr_term_t\n"
1630 " <offset> If term is ODP_PMR_CUSTOM_FRAME or _CUSTOM_L3, offset in bytes is used\n"
1631 " <value> PMR value to be matched\n"
1632 " <mask> PMR mask bits to be applied on the PMR value.\n"
1633 " CUSTOM PMR terms accept plain hex string, other PMR terms require\n"
1634 " hex string with '0x' prefix.\n"
1635 " <src queue> Optional name of the source queue (CoS). The default CoS is used when\n"
1636 " this is not defined.\n"
1637 " <dst queue> Name of the destination queue (CoS).\n"
1639 " -q, --cos_queue_param <name>:<queue prio>:<queue sync>:<cos enqueue profile type>:<optional custom value>:<optional tmo ns>:<optional size>\n"
1641 " <name> Configuration for a queue (CoS) defined with '--policy' 'dst queue'.\n"
1642 " <queue prio> CoS queue priority. Use priority value or \"default\" for default priority.\n"
1643 " <queue sync> CoS queue synchronization. Use ODP_SCHED_SYNC_PARALLEL,\n"
1644 " ODP_SCHED_SYNC_ATOMIC or ODP_SCHED_SYNC_ORDERED.\n"
1645 " <cos enqueue profile type>\n"
1646 " Aggregator enqueue profile type for CoS. Use odp_aggr_enq_profile_t::type\n"
1648 " <optional custom value>\n"
1649 " If ODP_AEP_TYPE_CUSTOM aggregator enqueue profile was used,\n"
1650 " pass a hex value (without '0x') for odp_aggr_enq_profile_t::param.\n"
1651 " <optional tmo ns>\n"
1652 " Aggregator configuration parameter timeout in nanoseconds. Optional,\n"
1653 " if not passed, aggregation for queue disabled.\n"
1654 " <optional size>\n"
1655 " Aggregator configuration parameter vector size. Mandatory if 'optional tmo ns'\n"
1656 " passed, optional otherwise.\n"
1658 printf(
" -c, --count <num> CPU count, 0=all available, default=1\n"
1660 " -m, --mode <mode> 0: Packet Drop mode. Received packets will be dropped\n"
1661 " !0: Echo mode. Received packets will be sent back\n"
1662 " default: Packet Drop mode\n"
1664 " -t, --time <sec> !0: Time for which the classifier will be run in seconds\n"
1665 " 0: Runs in infinite loop\n"
1666 " default: Runs in infinite loop\n"
1668 " -e, --enable <enable> 0: Classifier is disabled\n"
1669 " 1: Classifier is enabled\n"
1670 " default: Classifier is enabled\n"
1672 " -l, --layer <layer> Parse packets up to and including this layer. See odp_proto_layer_t\n"
1673 " default: ODP_PROTO_LAYER_ALL\n"
1675 " -d, --dedicated <enable> 0: One pool for pktio and all CoSes\n"
1676 " 1: Dedicated pools for pktio and each CoS\n"
1677 " default: Dedicated pools\n"
1679 " -s, --size <num> Number of packets in each packet pool\n"
1682 " -b, --burst <num> Packet burst size\n"
1685 " -C, --ci_pass <dst queue:count>\n"
1686 " Minimum acceptable packet count for a CoS destination queue.\n"
1687 " If the received packet count is smaller than this value,\n"
1688 " the application will exit with an error.\n"
1689 " E.g: -C \"queue1:100\" -C \"queue2:200\" -C \"DefaultQueue:100\"\n"
1690 " -P, --promisc_mode Enable promiscuous mode.\n"
1691 " -v, --verbose Verbose output.\n"
1692 " -h, --help Display help and exit.\n"
1693 "\n", SHM_PKT_POOL_SIZE, DEF_PKT_BURST);
void odp_atomic_init_u64(odp_atomic_u64_t *atom, uint64_t val)
Initialize atomic uint64 variable.
void odp_atomic_inc_u64(odp_atomic_u64_t *atom)
Increment atomic uint64 variable.
void odp_atomic_add_u64(odp_atomic_u64_t *atom, uint64_t val)
Add to atomic uint64 variable.
uint64_t odp_atomic_load_u64(odp_atomic_u64_t *atom)
Load value of atomic uint64 variable.
#define ODP_COS_NAME_LEN
Maximum class of service name length, including the null character.
int odp_cos_destroy(odp_cos_t cos)
Discard a class-of-service along with all its associated resources.
odp_pmr_t odp_cls_pmr_create(const odp_pmr_param_t *terms, int num_terms, odp_cos_t src_cos, odp_cos_t dst_cos)
Create Packet Matching Rule (PMR)
odp_cls_pmr_term_t
Packet Matching Rule terms.
#define ODP_PMR_INVALID
Invalid packet matching rule handle.
void odp_cls_print_all(void)
Print classifier info.
int odp_cls_pmr_destroy(odp_pmr_t pmr)
Function to destroy a packet match rule.
#define ODP_COS_INVALID
Invalid class of service handle.
odp_cos_t odp_cls_cos_create(const char *name, const odp_cls_cos_param_t *param)
Create a class-of-service.
void odp_cls_cos_param_init(odp_cls_cos_param_t *param)
Initialize class of service parameters.
void odp_cls_pmr_param_init(odp_pmr_param_t *param)
Initialize packet matching rule parameters.
@ ODP_PMR_TCP_DPORT
Destination TCP port (val_sz = 2)
@ ODP_PMR_ETHTYPE_0
Initial (outer) Ethertype only (val_sz = 2)
@ ODP_PMR_SIP_ADDR
Source IPv4 address (val_sz = 4)
@ ODP_PMR_DIP_ADDR
Destination IPv4 address (val_sz = 4)
@ ODP_PMR_TCP_SPORT
Source TCP port (val_sz = 2)
@ ODP_PMR_VLAN_ID_X
Last (most inner) VLAN ID (val_sz = 2)
@ ODP_PMR_CUSTOM_FRAME
Custom frame match rule.
@ ODP_PMR_UDP_SPORT
Source UDP port (val_sz = 2)
@ ODP_PMR_VLAN_ID_0
First (outer) VLAN ID (val_sz = 2)
@ ODP_PMR_UDP_DPORT
Destination UDP port (val_sz = 2)
@ ODP_PMR_DMAC
Destination MAC address (val_sz = 6)
@ ODP_PMR_ETHTYPE_X
Ethertype of most inner VLAN tag (val_sz = 2)
@ ODP_PMR_CUSTOM_L3
Custom layer 3 match rule.
#define odp_unlikely(x)
Branch unlikely taken.
uint32_t odp_u32be_t
unsigned 32bit big endian
odp_u16be_t odp_cpu_to_be_16(uint16_t cpu16)
Convert cpu native uint16_t to 16bit big endian.
odp_u32be_t odp_cpu_to_be_32(uint32_t cpu32)
Convert cpu native uint32_t to 32bit big endian.
int odp_cpumask_default_worker(odp_cpumask_t *mask, int num)
Default CPU mask for worker threads.
int odp_cpumask_first(const odp_cpumask_t *mask)
Find first set CPU in mask.
int32_t odp_cpumask_to_str(const odp_cpumask_t *mask, char *str, int32_t size)
Format a string from CPU mask.
#define ODP_CPUMASK_STR_SIZE
The maximum number of characters needed to record any CPU mask as a string (output of odp_cpumask_to_...
void odp_event_vector_free(odp_event_vector_t evv)
Free event vector.
odp_event_vector_t odp_event_vector_from_event(odp_event_t ev)
Get event vector handle from event.
uint32_t odp_event_vector_tbl(odp_event_vector_t evv, odp_event_t **event_tbl)
Get event vector table.
void odp_event_free(odp_event_t event)
Free event.
odp_event_type_t odp_event_type(odp_event_t event)
Event type of an event.
odp_event_type_t
Event type.
void odp_init_param_init(odp_init_t *param)
Initialize the odp_init_t to default values for all fields.
int odp_init_local(odp_instance_t instance, odp_thread_type_t thr_type)
Thread local ODP initialization.
int odp_init_global(odp_instance_t *instance, const odp_init_t *params, const odp_platform_init_t *platform_params)
Global ODP initialization.
int odp_term_local(void)
Thread local ODP termination.
int odp_term_global(odp_instance_t instance)
Global ODP termination.
uint64_t odp_instance_t
ODP instance ID.
void odp_spinlock_lock(odp_spinlock_t *splock)
Acquire spin lock.
void odp_spinlock_init(odp_spinlock_t *splock)
Initialize spin lock.
void odp_spinlock_unlock(odp_spinlock_t *splock)
Release spin lock.
int odp_pktio_mac_addr(odp_pktio_t pktio, void *mac_addr, int size)
Get the default MAC address of a packet IO interface.
void odp_pktin_queue_param_init(odp_pktin_queue_param_t *param)
Initialize packet input queue parameters.
void odp_pktio_param_init(odp_pktio_param_t *param)
Initialize pktio params.
int odp_pktio_promisc_mode(odp_pktio_t pktio)
Determine if promiscuous mode is enabled for a packet IO interface.
int odp_pktio_close(odp_pktio_t pktio)
Close a packet IO interface.
int odp_pktout_queue(odp_pktio_t pktio, odp_pktout_queue_t queues[], int num)
Direct packet output queues.
int odp_pktio_promisc_mode_set(odp_pktio_t pktio, odp_bool_t enable)
Set promiscuous mode.
void odp_pktio_config_init(odp_pktio_config_t *config)
Initialize packet IO configuration options.
odp_pktio_t odp_pktio_open(const char *name, odp_pool_t pool, const odp_pktio_param_t *param)
Open a packet IO interface.
int odp_pktio_config(odp_pktio_t pktio, const odp_pktio_config_t *config)
Configure packet IO interface options.
int odp_pktio_start(odp_pktio_t pktio)
Start packet receive and transmit.
#define ODP_PKTIO_INVALID
Invalid packet IO handle.
void odp_pktout_queue_param_init(odp_pktout_queue_param_t *param)
Initialize packet output queue parameters.
int odp_pktio_stop(odp_pktio_t pktio)
Stop packet receive and transmit.
int odp_pktio_capability(odp_pktio_t pktio, odp_pktio_capability_t *capa)
Query packet IO interface capabilities.
int odp_pktout_send(odp_pktout_queue_t queue, const odp_packet_t packets[], int num)
Send packets directly to an interface output queue.
uint64_t odp_pktio_to_u64(odp_pktio_t pktio)
Get printable value for an odp_pktio_t.
int odp_pktio_default_cos_set(odp_pktio_t pktio, odp_cos_t default_cos)
Set interface default class-of-service.
int odp_pktin_queue_config(odp_pktio_t pktio, const odp_pktin_queue_param_t *param)
Configure packet input queues.
int odp_pktout_queue_config(odp_pktio_t pktio, const odp_pktout_queue_param_t *param)
Configure packet output queues.
@ ODP_PKTIN_MODE_SCHED
Packet input through scheduler and scheduled event queues.
void odp_packet_print_data(odp_packet_t pkt, uint32_t offset, uint32_t len)
Print packet data.
void odp_packet_from_event_multi(odp_packet_t pkt[], const odp_event_t ev[], int num)
Convert multiple packet events to packet handles.
int odp_packet_has_ipv4(odp_packet_t pkt)
Check for IPv4.
int odp_packet_has_eth(odp_packet_t pkt)
Check for Ethernet header.
uint32_t odp_packet_len(odp_packet_t pkt)
Packet data length.
int odp_packet_has_error(odp_packet_t pkt)
Check for all parse errors in packet.
void * odp_packet_l3_ptr(odp_packet_t pkt, uint32_t *len)
Layer 3 start pointer.
odp_packet_t odp_packet_from_event(odp_event_t ev)
Get packet handle from event.
void odp_packet_free(odp_packet_t pkt)
Free packet.
void * odp_packet_l2_ptr(odp_packet_t pkt, uint32_t *len)
Layer 2 start pointer.
void odp_packet_free_multi(const odp_packet_t pkt[], int num)
Free multiple packets.
odp_pool_t odp_packet_pool(odp_packet_t pkt)
Packet pool.
@ ODP_PROTO_LAYER_ALL
All layers.
uint64_t odp_pool_to_u64(odp_pool_t hdl)
Get printable value for an odp_pool_t.
#define ODP_POOL_NAME_LEN
Maximum pool name length, including the null character.
odp_pool_t odp_pool_create(const char *name, const odp_pool_param_t *param)
Create a pool.
void odp_pool_param_init(odp_pool_param_t *param)
Initialize pool params.
int odp_pool_destroy(odp_pool_t pool)
Destroy a pool previously created by odp_pool_create()
void odp_pool_print_all(void)
Print debug info about all pools.
#define ODP_POOL_INVALID
Invalid pool.
@ ODP_POOL_PACKET
Packet pool.
@ ODP_POOL_EVENT_VECTOR
Event vector pool.
odp_queue_t odp_queue_aggr(odp_queue_t queue, uint32_t aggr_index)
Get a queue handle of an event aggregator associated with a queue.
void odp_queue_param_init(odp_queue_param_t *param)
Initialize queue params.
#define ODP_QUEUE_INVALID
Invalid queue.
void odp_queue_print_all(void)
Print debug info about all queues.
odp_queue_t odp_queue_create(const char *name, const odp_queue_param_t *param)
Queue create.
int odp_queue_destroy(odp_queue_t queue)
Destroy ODP queue.
int odp_queue_info(odp_queue_t queue, odp_queue_info_t *info)
Retrieve information about a queue.
@ ODP_QUEUE_TYPE_SCHED
Scheduled queue.
int odp_schedule_sync_t
Scheduler synchronization method.
#define ODP_SCHED_SYNC_PARALLEL
Parallel scheduled queues.
int odp_schedule_prio_t
Scheduling priority level.
int odp_schedule_multi(odp_queue_t *from, uint64_t wait, odp_event_t events[], int num)
Schedule multiple events.
#define ODP_SCHED_SYNC_ATOMIC
Atomic queue synchronization.
#define ODP_SCHED_SYNC_ORDERED
Ordered queue synchronization.
int odp_schedule_default_prio(void)
Default scheduling priority level.
int odp_schedule_config(const odp_schedule_config_t *config)
Global schedule configuration.
uint64_t odp_schedule_wait_time(uint64_t ns)
Schedule wait time.
#define ODP_SCHED_GROUP_ALL
Group of all threads.
int odp_shm_free(odp_shm_t shm)
Free a contiguous block of shared memory.
void * odp_shm_addr(odp_shm_t shm)
Shared memory block address.
#define ODP_SHM_INVALID
Invalid shared memory block.
odp_shm_t odp_shm_reserve(const char *name, uint64_t size, uint64_t align, uint32_t flags)
Reserve a contiguous block of shared memory.
bool odp_bool_t
Boolean type.
void odp_sys_info_print(void)
Print system info.
int odp_thread_id(void)
Get thread identifier.
@ ODP_THREAD_WORKER
Worker thread.
@ ODP_THREAD_CONTROL
Control thread.
odp_time_t odp_time_local(void)
Current local time.
#define ODP_TIME_MSEC_IN_NS
A millisecond in nanoseconds.
uint64_t odp_time_diff_ns(odp_time_t t2, odp_time_t t1)
Time difference in nanoseconds.
Dummy type for strong typing.
Event aggregator enqueuing profile.
Class of service parameters Used to communicate class of service creation options.
odp_queue_t queue
Mapping used when num_queue = 1, hashing is disabled in this case and application has to configure th...
odp_aggr_enq_profile_t aggr_enq_profile
Event aggregator enqueuing profile.
odp_pool_t pool
Pool associated with CoS.
Event vector configuration.
Global initialization parameters.
odp_mem_model_t mem_model
Application memory model.
Packet input queue parameters.
odp_bool_t classifier_enable
Enable classifier.
odp_pktio_set_op_t set_op
Supported set operations.
uint32_t max_output_queues
Maximum number of output queues.
Packet IO configuration options.
odp_pktio_parser_config_t parser
Packet input parser configuration.
odp_pktin_mode_t in_mode
Packet input mode.
odp_proto_layer_t layer
Protocol parsing level in packet input.
Packet output queue parameters.
uint32_t num_queues
Number of output queues to be created.
Packet Matching Rule parameter structure.
uint32_t offset
Offset to the value.
uint32_t val_sz
Size of the value to be matched.
struct odp_pmr_param_t::@4::@6 match
Parameters for single-valued matches.
const void * value
Points to the value to be matched.
const void * mask
Mask of the bits to be matched.
odp_cls_pmr_term_t term
Packet Matching Rule term.
uint32_t num
Number of buffers in the pool.
struct odp_pool_param_t::@139 pkt
Parameters for packet pools.
struct odp_pool_param_t::@142 event_vector
Parameters for event vector pools.
odp_pool_type_t type
Pool type.
uint32_t len
Minimum length of 'num' packets.
uint32_t max_size
Maximum number of handles (such as odp_packet_t) in a vector.
uint32_t seg_len
Minimum number of packet data bytes that can be stored in the first segment of a newly allocated pack...
const char * name
Queue name.
odp_schedule_param_t sched
Scheduler parameters.
odp_queue_type_t type
Queue type.
const odp_event_aggr_config_t * aggr
Event aggregator configuration parameters.
uint32_t num_aggr
Number of event aggregators.
odp_schedule_group_t group
Thread group.
odp_schedule_prio_t prio
Priority level.
odp_schedule_sync_t sync
Synchronization method.
struct odp_pktio_set_op_t::@112 op
Operation flags.
uint32_t promisc_mode
Promiscuous mode.