aboutsummaryrefslogtreecommitdiff
path: root/example/classifier/odp_classifier.c
diff options
context:
space:
mode:
Diffstat (limited to 'example/classifier/odp_classifier.c')
-rw-r--r--example/classifier/odp_classifier.c1087
1 files changed, 759 insertions, 328 deletions
diff --git a/example/classifier/odp_classifier.c b/example/classifier/odp_classifier.c
index d67fe5ace..d24224e6f 100644
--- a/example/classifier/odp_classifier.c
+++ b/example/classifier/odp_classifier.c
@@ -1,7 +1,15 @@
-/* Copyright (c) 2015, Linaro Limited
- * All rights reserved.
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright (c) 2015-2018 Linaro Limited
+ * Copyright (c) 2019-2022 Nokia
+ * Copyright (c) 2020 Marvell
+ */
+
+/**
+ * @example odp_classifier.c
*
- * SPDX-License-Identifier: BSD-3-Clause
+ * Classifier API example application
+ *
+ * @cond _ODP_HIDE_FROM_DOXYGEN_
*/
#include <stdlib.h>
@@ -9,10 +17,11 @@
#include <getopt.h>
#include <unistd.h>
#include <inttypes.h>
-#include <example_debug.h>
+#include <signal.h>
#include <odp_api.h>
#include <odp/helper/odph_api.h>
+
#include <strings.h>
#include <errno.h>
#include <stdio.h>
@@ -20,12 +29,22 @@
/** @def MAX_WORKERS
* @brief Maximum number of worker threads
*/
-#define MAX_WORKERS 32
+#define MAX_WORKERS (ODP_THREAD_COUNT_MAX - 1)
+
+/** @def MAX_PKT_BURST
+ * @brief Maximum packet burst size
+ */
+#define MAX_PKT_BURST 64
+
+/** @def DEF_PKT_BURST
+ * @brief Default packet burst size
+ */
+#define DEF_PKT_BURST 32
/** @def SHM_PKT_POOL_SIZE
- * @brief Size of the shared memory block
+ * @brief Packet pool size (number of packets)
*/
-#define SHM_PKT_POOL_SIZE (512*2048)
+#define SHM_PKT_POOL_SIZE 10000
/** @def SHM_PKT_POOL_BUF_SIZE
* @brief Buffer size of the packet pool buffer
@@ -35,13 +54,16 @@
/** @def MAX_PMR_COUNT
* @brief Maximum number of Classification Policy
*/
-#define MAX_PMR_COUNT 8
+#define MAX_PMR_COUNT 32
/** @def DISPLAY_STRING_LEN
* @brief Length of string used to display term value
*/
#define DISPLAY_STRING_LEN 32
+/** Maximum PMR value size */
+#define MAX_VAL_SIZE 16
+
/** Get rid of path in filename - only for unix-type paths using '/' */
#define NO_PATH(file_name) (strrchr((file_name), '/') ? \
strrchr((file_name), '/') + 1 : (file_name))
@@ -54,25 +76,46 @@ typedef struct {
odp_atomic_u64_t queue_pkt_count; /**< count of received packets */
odp_atomic_u64_t pool_pkt_count; /**< count of received packets */
char cos_name[ODP_COS_NAME_LEN]; /**< cos name */
+ char src_cos_name[ODP_COS_NAME_LEN]; /**< source cos name */
struct {
odp_cls_pmr_term_t term; /**< odp pmr term value */
- uint64_t val; /**< pmr term value */
- uint64_t mask; /**< pmr term mask */
+ uint8_t value_be[MAX_VAL_SIZE]; /**< value in big endian */
+ uint8_t mask_be[MAX_VAL_SIZE]; /**< mask in big endian */
uint32_t val_sz; /**< size of the pmr term */
uint32_t offset; /**< pmr term offset */
} rule;
char value[DISPLAY_STRING_LEN]; /**< Display string for value */
char mask[DISPLAY_STRING_LEN]; /**< Display string for mask */
+ int has_src_cos;
+
} global_statistics;
typedef struct {
+ char cos_name[ODP_COS_NAME_LEN];
+ uint64_t count;
+} ci_pass_counters;
+
+typedef struct {
+ odp_pktout_queue_t pktout[MAX_WORKERS];
+ int num_pktout;
global_statistics stats[MAX_PMR_COUNT];
+ ci_pass_counters ci_pass_rules[MAX_PMR_COUNT];
int policy_count; /**< global policy count */
+ int num_ci_pass_rules; /**< ci pass count */
int appl_mode; /**< application mode */
odp_atomic_u64_t total_packets; /**< total received packets */
- int cpu_count; /**< Number of CPUs to use */
+ unsigned int cpu_count; /**< Number of CPUs to use */
uint32_t time; /**< Number of seconds to run */
char *if_name; /**< pointer to interface names */
+ int shutdown; /**< Shutdown threads if !0 */
+ int shutdown_sig;
+ int verbose;
+ int promisc_mode; /**< Promiscuous mode enabled */
+ int classifier_enable;
+ int parse_layer;
+ int cos_pools;
+ int pool_size;
+ int burst_size;
} appl_args_t;
enum packet_mode {
@@ -80,22 +123,47 @@ enum packet_mode {
APPL_MODE_REPLY /**< Packet is sent back */
};
-static int shutdown; /**< Shutdown threads if !0 */
+static appl_args_t *appl_args_gbl;
-/* helper funcs */
static int drop_err_pkts(odp_packet_t pkt_tbl[], unsigned len);
static void swap_pkt_addrs(odp_packet_t pkt_tbl[], unsigned len);
-static void parse_args(int argc, char *argv[], appl_args_t *appl_args);
+static int parse_args(int argc, char *argv[], appl_args_t *appl_args);
static void print_info(char *progname, appl_args_t *appl_args);
-static void usage(char *progname);
-static void configure_cos(odp_cos_t default_cos, appl_args_t *args);
-static odp_cos_t configure_default_cos(odp_pktio_t pktio, appl_args_t *args);
-static int convert_str_to_pmr_enum(char *token, odp_cls_pmr_term_t *term,
- uint32_t *offset);
-static int parse_pmr_policy(appl_args_t *appl_args, char *argv[], char *optarg);
-
-static inline
-void print_cls_statistics(appl_args_t *args)
+static void usage(void);
+
+static inline int check_ci_pass_count(appl_args_t *args)
+{
+ int i, j;
+ uint64_t count;
+
+ if (args->num_ci_pass_rules == 0)
+ return 0;
+
+ for (i = 0; i < args->num_ci_pass_rules; i++) {
+ for (j = 0; j < args->policy_count; j++) {
+ if (!strcmp(args->stats[j].cos_name,
+ args->ci_pass_rules[i].cos_name)) {
+ count = odp_atomic_load_u64(&args->stats[i].queue_pkt_count);
+ if (args->ci_pass_rules[i].count > count) {
+ ODPH_ERR("Error: Cos = %s, expected packets = %" PRIu64 ","
+ "received packet = %" PRIu64 "\n",
+ args->stats[j].cos_name,
+ args->ci_pass_rules[i].count, count);
+ return -1;
+ }
+ break;
+ }
+ }
+ if (j == args->policy_count) {
+ ODPH_ERR("Error: invalid Cos:%s specified for CI pass count\n",
+ args->ci_pass_rules[i].cos_name);
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static inline void print_cls_statistics(appl_args_t *args)
{
int i;
uint32_t timeout;
@@ -128,7 +196,7 @@ void print_cls_statistics(appl_args_t *args)
printf("\n");
for (i = 0; i < args->policy_count; i++)
printf("%-12s |", args->stats[i].cos_name);
- printf("Total Packets");
+ printf("%-6s %-6s", "Total", "Mpps");
printf("\n");
for (i = 0; i < args->policy_count; i++)
printf("%-6s %-6s|", "queue", "pool");
@@ -141,7 +209,12 @@ void print_cls_statistics(appl_args_t *args)
if (timeout == 0)
infinite = 1;
+ uint64_t total_packets, last_total_packets = 0;
+ odp_time_t start = odp_time_local(), end;
+ float mpps;
+
for (; timeout > 0 || infinite; timeout--) {
+ sleep(1);
for (i = 0; i < args->policy_count; i++) {
printf("%-6" PRIu64 " ",
odp_atomic_load_u64(&args->stats[i]
@@ -151,52 +224,35 @@ void print_cls_statistics(appl_args_t *args)
.pool_pkt_count));
}
- printf("%-" PRIu64, odp_atomic_load_u64(&args->
- total_packets));
+ end = odp_time_local();
+ total_packets = odp_atomic_load_u64(&args->total_packets);
+ mpps = (total_packets - last_total_packets) /
+ (odp_time_diff_ns(end, start) / 1000.0);
+ printf("%-6" PRIu64 " %-6.3f\n", total_packets, mpps);
+ last_total_packets = total_packets;
+ start = end;
- sleep(1);
- printf("\r");
- fflush(stdout);
+ if (args->shutdown_sig)
+ break;
}
printf("\n");
}
-static inline
-int parse_mask(const char *str, uint64_t *mask)
-{
- uint64_t b;
- int ret;
-
- ret = sscanf(str, "%" SCNx64, &b);
- *mask = b;
- return ret != 1;
-}
-
-static
-int parse_value(const char *str, uint64_t *val, uint32_t *val_sz)
+static int parse_custom(const char *str, uint8_t *buf_be, int max_size)
{
- size_t len;
- size_t i;
- int converted;
- union {
- uint64_t u64;
- uint8_t u8[8];
- } buf = {.u64 = 0};
+ int i, len;
+ /* hex string without 0x prefix */
len = strlen(str);
- if (len > 2 * sizeof(buf))
+ if (len > 2 * max_size)
return -1;
- for (i = 0; i < len; i += 2) {
- converted = sscanf(&str[i], "%2" SCNx8, &buf.u8[i / 2]);
- if (1 != converted)
+ for (i = 0; i < len; i += 2)
+ if (sscanf(&str[i], "%2" SCNx8, &buf_be[i / 2]) != 1)
return -1;
- }
- *val = buf.u64;
- *val_sz = len / 2;
- return 0;
+ return len / 2;
}
/**
@@ -213,6 +269,10 @@ static odp_pktio_t create_pktio(const char *dev, odp_pool_t pool)
odp_pktio_t pktio;
odp_pktio_param_t pktio_param;
odp_pktin_queue_param_t pktin_param;
+ odp_pktio_capability_t capa;
+ odp_pktio_config_t cfg;
+ odp_pktout_queue_param_t pktout_queue_param;
+ int num_tx;
odp_pktio_param_init(&pktio_param);
pktio_param.in_mode = ODP_PKTIN_MODE_SCHED;
@@ -220,31 +280,76 @@ static odp_pktio_t create_pktio(const char *dev, odp_pool_t pool)
/* Open a packet IO instance */
pktio = odp_pktio_open(dev, pool, &pktio_param);
if (pktio == ODP_PKTIO_INVALID) {
- if (odp_errno() == EPERM)
- EXAMPLE_ERR("Root level permission required\n");
+ ODPH_ERR("pktio create failed for %s\n", dev);
+ exit(EXIT_FAILURE);
+ }
- EXAMPLE_ERR("pktio create failed for %s\n", dev);
+ if (odp_pktio_capability(pktio, &capa)) {
+ ODPH_ERR("pktio capability failed for %s\n", dev);
exit(EXIT_FAILURE);
}
odp_pktin_queue_param_init(&pktin_param);
- pktin_param.queue_param.sched.sync = ODP_SCHED_SYNC_ATOMIC;
+ pktin_param.classifier_enable = appl_args_gbl->classifier_enable;
if (odp_pktin_queue_config(pktio, &pktin_param)) {
- EXAMPLE_ERR("pktin queue config failed for %s\n", dev);
+ ODPH_ERR("pktin queue config failed for %s\n", dev);
exit(EXIT_FAILURE);
}
- if (odp_pktout_queue_config(pktio, NULL)) {
- EXAMPLE_ERR("pktout queue config failed for %s\n", dev);
+ num_tx = appl_args_gbl->cpu_count;
+
+ if (num_tx > (int)capa.max_output_queues) {
+ printf("Sharing %i output queues between %i workers\n",
+ capa.max_output_queues, num_tx);
+ num_tx = capa.max_output_queues;
+ }
+
+ appl_args_gbl->num_pktout = num_tx;
+
+ odp_pktout_queue_param_init(&pktout_queue_param);
+ pktout_queue_param.num_queues = num_tx;
+
+ if (odp_pktout_queue_config(pktio, &pktout_queue_param)) {
+ ODPH_ERR("pktout queue config failed for %s\n", dev);
exit(EXIT_FAILURE);
}
- printf(" created pktio:%02" PRIu64
- ", dev:%s, queue mode (ATOMIC queues)\n"
- " \tdefault pktio%02" PRIu64 "\n",
- odp_pktio_to_u64(pktio), dev,
- odp_pktio_to_u64(pktio));
+ if (odp_pktout_queue(pktio, appl_args_gbl->pktout, num_tx) != num_tx) {
+ ODPH_ERR("Pktout queue query failed: %s\n", dev);
+ exit(EXIT_FAILURE);
+ }
+
+ if (appl_args_gbl->promisc_mode && odp_pktio_promisc_mode(pktio) != 1) {
+ if (!capa.set_op.op.promisc_mode) {
+ ODPH_ERR("enabling promisc mode not supported %s\n", dev);
+ exit(EXIT_FAILURE);
+ }
+
+ if (odp_pktio_promisc_mode_set(pktio, true)) {
+ ODPH_ERR("failed to enable promisc mode for %s\n", dev);
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ printf("created pktio:%" PRIu64 ", dev:%s", odp_pktio_to_u64(pktio), dev);
+
+ odph_ethaddr_t mac;
+
+ if (odp_pktio_mac_addr(pktio, &mac, sizeof(mac)) == sizeof(mac)) {
+ printf(", mac");
+ for (int c = 0; c < (int)sizeof(mac); c++)
+ printf(":%02x", mac.addr[c]);
+ }
+
+ printf("\n");
+
+ odp_pktio_config_init(&cfg);
+ cfg.parser.layer = appl_args_gbl->parse_layer;
+ if (odp_pktio_config(pktio, &cfg)) {
+ ODPH_ERR("failed to configure pktio %s\n", dev);
+ exit(EXIT_FAILURE);
+ }
return pktio;
}
@@ -256,76 +361,113 @@ static odp_pktio_t create_pktio(const char *dev, odp_pool_t pool)
static int pktio_receive_thread(void *arg)
{
int thr;
- odp_pktout_queue_t pktout;
- odp_packet_t pkt;
+ odp_packet_t pkt[MAX_PKT_BURST];
odp_pool_t pool;
- odp_event_t ev;
- unsigned long err_cnt = 0;
+ odp_event_t ev[MAX_PKT_BURST];
odp_queue_t queue;
- int i;
+ int i, j, num, dropped, sent;
+ global_statistics *stats;
+ unsigned long err_cnt = 0;
thr = odp_thread_id();
appl_args_t *appl = (appl_args_t *)arg;
- global_statistics *stats;
+ uint64_t wait_time = odp_schedule_wait_time(100 * ODP_TIME_MSEC_IN_NS);
+ odp_pktout_queue_t pktout = appl_args_gbl->pktout[thr % appl_args_gbl->num_pktout];
/* Loop packets */
for (;;) {
- odp_pktio_t pktio_tmp;
-
- if (shutdown)
+ if (appl->shutdown)
break;
/* Use schedule to get buf from any input queue */
- ev = odp_schedule(&queue,
- odp_schedule_wait_time(ODP_TIME_SEC_IN_NS));
+ num = odp_schedule_multi(&queue, wait_time, ev, appl_args_gbl->burst_size);
/* Loop back to receive packets incase of invalid event */
- if (odp_unlikely(ev == ODP_EVENT_INVALID))
+ if (odp_unlikely(!num))
continue;
- pkt = odp_packet_from_event(ev);
+ odp_packet_from_event_multi(pkt, ev, num);
- /* Total packets received */
- odp_atomic_inc_u64(&appl->total_packets);
+ if (odp_unlikely(appl->verbose)) {
+ for (j = 0; j < num; j++) {
+ odp_queue_info_t info;
+ uint32_t len = odp_packet_len(pkt[j]);
- /* Drop packets with errors */
- if (odp_unlikely(drop_err_pkts(&pkt, 1) == 0)) {
- EXAMPLE_ERR("Drop frame - err_cnt:%lu\n", ++err_cnt);
- continue;
+ if (odp_queue_info(queue, &info) == 0)
+ printf("Queue: %s\n", info.name);
+
+ if (len > 96)
+ len = 96;
+
+ odp_packet_print_data(pkt[j], 0, len);
+ }
}
- pktio_tmp = odp_packet_input(pkt);
+ /* Total packets received */
+ odp_atomic_add_u64(&appl->total_packets, num);
- if (odp_pktout_queue(pktio_tmp, &pktout, 1) != 1) {
- EXAMPLE_ERR(" [%02i] Error: no output queue\n", thr);
- return -1;
+ /* Drop packets with errors */
+ dropped = drop_err_pkts(pkt, num);
+ if (odp_unlikely(dropped)) {
+ num -= dropped;
+ err_cnt += dropped;
+ ODPH_ERR("Drop frame - err_cnt:%lu\n", err_cnt);
}
- pool = odp_packet_pool(pkt);
+ for (j = 0; j < num; j++) {
+ pool = odp_packet_pool(pkt[j]);
- /* Swap Eth MACs and possibly IP-addrs before sending back */
- swap_pkt_addrs(&pkt, 1);
- for (i = 0; i < MAX_PMR_COUNT; i++) {
- stats = &appl->stats[i];
- if (queue == stats->queue)
- odp_atomic_inc_u64(&stats->queue_pkt_count);
- if (pool == stats->pool)
- odp_atomic_inc_u64(&stats->pool_pkt_count);
+ for (i = 0; i < MAX_PMR_COUNT; i++) {
+ stats = &appl->stats[i];
+ if (queue == stats->queue)
+ odp_atomic_inc_u64(&stats->queue_pkt_count);
+ if (pool == stats->pool)
+ odp_atomic_inc_u64(&stats->pool_pkt_count);
+ }
}
if (appl->appl_mode == APPL_MODE_DROP) {
- odp_packet_free(pkt);
+ odp_packet_free_multi(pkt, num);
continue;
}
- if (odp_pktout_send(pktout, &pkt, 1) < 1) {
- EXAMPLE_ERR(" [%i] Packet send failed.\n", thr);
- odp_packet_free(pkt);
+ /* Swap Eth MACs and possibly IP-addrs before sending back */
+ swap_pkt_addrs(pkt, num);
+
+ sent = odp_pktout_send(pktout, pkt, num);
+ sent = sent < 0 ? 0 : sent;
+
+ if (sent != num) {
+ ODPH_ERR(" [%i] Packet send failed\n", thr);
+ odp_packet_free_multi(pkt + sent, num - sent);
}
}
return 0;
}
+static odp_pool_t pool_create(const char *name)
+{
+ static odp_pool_t pool = ODP_POOL_INVALID;
+ odp_pool_param_t pool_params;
+
+ if (!appl_args_gbl->cos_pools && pool != ODP_POOL_INVALID)
+ return pool;
+
+ odp_pool_param_init(&pool_params);
+ pool_params.pkt.seg_len = SHM_PKT_POOL_BUF_SIZE;
+ pool_params.pkt.len = SHM_PKT_POOL_BUF_SIZE;
+ pool_params.pkt.num = appl_args_gbl->pool_size;
+ pool_params.type = ODP_POOL_PACKET;
+ pool = odp_pool_create(name, &pool_params);
+
+ if (pool == ODP_POOL_INVALID) {
+ ODPH_ERR("Error: failed to create pool %s\n", name);
+ exit(EXIT_FAILURE);
+ }
+
+ return pool;
+}
+
static odp_cos_t configure_default_cos(odp_pktio_t pktio, appl_args_t *args)
{
odp_queue_param_t qparam;
@@ -335,53 +477,42 @@ static odp_cos_t configure_default_cos(odp_pktio_t pktio, appl_args_t *args)
odp_queue_t queue_default;
odp_pool_t pool_default;
odp_cos_t cos_default;
- odp_pool_param_t pool_params;
odp_cls_cos_param_t cls_param;
global_statistics *stats = args->stats;
odp_queue_param_init(&qparam);
qparam.type = ODP_QUEUE_TYPE_SCHED;
- qparam.sched.prio = ODP_SCHED_PRIO_DEFAULT;
qparam.sched.sync = ODP_SCHED_SYNC_PARALLEL;
qparam.sched.group = ODP_SCHED_GROUP_ALL;
queue_default = odp_queue_create(queue_name, &qparam);
if (queue_default == ODP_QUEUE_INVALID) {
- EXAMPLE_ERR("Error: default queue create failed.\n");
+ ODPH_ERR("Error: default queue create failed\n");
exit(EXIT_FAILURE);
}
- odp_pool_param_init(&pool_params);
- pool_params.pkt.seg_len = SHM_PKT_POOL_BUF_SIZE;
- pool_params.pkt.len = SHM_PKT_POOL_BUF_SIZE;
- pool_params.pkt.num = SHM_PKT_POOL_SIZE / SHM_PKT_POOL_BUF_SIZE;
- pool_params.type = ODP_POOL_PACKET;
- pool_default = odp_pool_create(pool_name, &pool_params);
-
- if (pool_default == ODP_POOL_INVALID) {
- EXAMPLE_ERR("Error: default pool create failed.\n");
- exit(EXIT_FAILURE);
- }
+ pool_default = pool_create(pool_name);
odp_cls_cos_param_init(&cls_param);
cls_param.pool = pool_default;
cls_param.queue = queue_default;
- cls_param.drop_policy = ODP_COS_DROP_POOL;
+
cos_default = odp_cls_cos_create(cos_name, &cls_param);
if (cos_default == ODP_COS_INVALID) {
- EXAMPLE_ERR("Error: default cos create failed.\n");
+ ODPH_ERR("Error: default cos create failed\n");
exit(EXIT_FAILURE);
}
if (0 > odp_pktio_default_cos_set(pktio, cos_default)) {
- EXAMPLE_ERR("odp_pktio_default_cos_set failed");
+ ODPH_ERR("odp_pktio_default_cos_set failed\n");
exit(EXIT_FAILURE);
}
stats[args->policy_count].cos = cos_default;
/* add default queue to global stats */
stats[args->policy_count].queue = queue_default;
- stats[args->policy_count].pool = pool_default;
+ if (appl_args_gbl->cos_pools)
+ stats[args->policy_count].pool = pool_default;
snprintf(stats[args->policy_count].cos_name,
sizeof(stats[args->policy_count].cos_name),
"%s", cos_name);
@@ -391,14 +522,29 @@ static odp_cos_t configure_default_cos(odp_pktio_t pktio, appl_args_t *args)
return cos_default;
}
+static int find_cos(appl_args_t *args, const char *name, odp_cos_t *cos)
+{
+ global_statistics *stats;
+ int i;
+
+ for (i = 0; i < args->policy_count - 1; i++) {
+ stats = &args->stats[i];
+
+ if (strcmp(stats->cos_name, name) == 0) {
+ *cos = stats->cos;
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
static void configure_cos(odp_cos_t default_cos, appl_args_t *args)
{
char cos_name[ODP_COS_NAME_LEN];
- char queue_name[ODP_QUEUE_NAME_LEN];
char pool_name[ODP_POOL_NAME_LEN];
- odp_pool_param_t pool_params;
+ const char *queue_name;
odp_cls_cos_param_t cls_param;
- odp_pmr_param_t pmr_param;
int i;
global_statistics *stats;
odp_queue_param_t qparam;
@@ -408,59 +554,70 @@ static void configure_cos(odp_cos_t default_cos, appl_args_t *args)
odp_queue_param_init(&qparam);
qparam.type = ODP_QUEUE_TYPE_SCHED;
- qparam.sched.prio = i % odp_schedule_num_prio();
qparam.sched.sync = ODP_SCHED_SYNC_PARALLEL;
qparam.sched.group = ODP_SCHED_GROUP_ALL;
- snprintf(queue_name, sizeof(queue_name), "%sQueue%d",
- args->stats[i].cos_name, i);
+ queue_name = args->stats[i].cos_name;
stats->queue = odp_queue_create(queue_name, &qparam);
if (ODP_QUEUE_INVALID == stats->queue) {
- EXAMPLE_ERR("odp_queue_create failed");
+ ODPH_ERR("odp_queue_create failed\n");
exit(EXIT_FAILURE);
}
- odp_pool_param_init(&pool_params);
- pool_params.pkt.seg_len = SHM_PKT_POOL_BUF_SIZE;
- pool_params.pkt.len = SHM_PKT_POOL_BUF_SIZE;
- pool_params.pkt.num = SHM_PKT_POOL_SIZE /
- SHM_PKT_POOL_BUF_SIZE;
- pool_params.type = ODP_POOL_PACKET;
-
snprintf(pool_name, sizeof(pool_name), "%sPool%d",
args->stats[i].cos_name, i);
- stats->pool = odp_pool_create(pool_name, &pool_params);
-
- if (stats->pool == ODP_POOL_INVALID) {
- EXAMPLE_ERR("Error: default pool create failed.\n");
- exit(EXIT_FAILURE);
- }
snprintf(cos_name, sizeof(cos_name), "CoS%s",
stats->cos_name);
odp_cls_cos_param_init(&cls_param);
- cls_param.pool = stats->pool;
+ cls_param.pool = pool_create(pool_name);
+ if (appl_args_gbl->cos_pools)
+ stats->pool = cls_param.pool;
cls_param.queue = stats->queue;
- cls_param.drop_policy = ODP_COS_DROP_POOL;
+
stats->cos = odp_cls_cos_create(cos_name, &cls_param);
+ odp_atomic_init_u64(&stats->queue_pkt_count, 0);
+ odp_atomic_init_u64(&stats->pool_pkt_count, 0);
+ }
+
+ for (i = 0; i < args->policy_count - 1; i++) {
+ odp_pmr_param_t pmr_param;
+ odp_cos_t src_cos = default_cos;
+
+ stats = &args->stats[i];
+
+ if (stats->has_src_cos) {
+ if (find_cos(args, stats->src_cos_name, &src_cos)) {
+ ODPH_ERR("find_cos failed\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+
odp_cls_pmr_param_init(&pmr_param);
pmr_param.term = stats->rule.term;
- pmr_param.match.value = &stats->rule.val;
- pmr_param.match.mask = &stats->rule.mask;
+ pmr_param.match.value = stats->rule.value_be;
+ pmr_param.match.mask = stats->rule.mask_be;
pmr_param.val_sz = stats->rule.val_sz;
pmr_param.offset = stats->rule.offset;
- stats->pmr = odp_cls_pmr_create(&pmr_param, 1, default_cos,
+ stats->pmr = odp_cls_pmr_create(&pmr_param, 1, src_cos,
stats->cos);
- if (stats->pmr == ODP_PMR_INVAL) {
- EXAMPLE_ERR("odp_pktio_pmr_cos failed");
+ if (stats->pmr == ODP_PMR_INVALID) {
+ ODPH_ERR("odp_pktio_pmr_cos failed\n");
exit(EXIT_FAILURE);
}
-
- odp_atomic_init_u64(&stats->queue_pkt_count, 0);
- odp_atomic_init_u64(&stats->pool_pkt_count, 0);
}
+
+}
+
+static void sig_handler(int signo)
+{
+ (void)signo;
+
+ if (appl_args_gbl == NULL)
+ return;
+ appl_args_gbl->shutdown_sig = 1;
}
/**
@@ -468,30 +625,44 @@ static void configure_cos(odp_cos_t default_cos, appl_args_t *args)
*/
int main(int argc, char *argv[])
{
- odph_odpthread_t thread_tbl[MAX_WORKERS];
+ odph_helper_options_t helper_options;
+ odph_thread_t thread_tbl[MAX_WORKERS];
odp_pool_t pool;
int num_workers;
int i;
odp_cpumask_t cpumask;
char cpumaskstr[ODP_CPUMASK_STR_SIZE];
- odp_pool_param_t params;
odp_pktio_t pktio;
appl_args_t *args;
odp_cos_t default_cos;
odp_shm_t shm;
int ret;
odp_instance_t instance;
- odph_odpthread_params_t thr_params;
+ odp_init_t init_param;
+ odph_thread_common_param_t thr_common;
+ odph_thread_param_t thr_param;
+
+ signal(SIGINT, sig_handler);
+
+ /* Let helper collect its own arguments (e.g. --odph_proc) */
+ argc = odph_parse_options(argc, argv);
+ if (odph_options(&helper_options)) {
+ ODPH_ERR("Error: reading ODP helper options failed\n");
+ exit(EXIT_FAILURE);
+ }
+
+ odp_init_param_init(&init_param);
+ init_param.mem_model = helper_options.mem_model;
/* Init ODP before calling anything else */
- if (odp_init_global(&instance, NULL, NULL)) {
- EXAMPLE_ERR("Error: ODP global init failed.\n");
+ if (odp_init_global(&instance, &init_param, NULL)) {
+ ODPH_ERR("Error: ODP global init failed\n");
exit(EXIT_FAILURE);
}
/* Init this thread */
if (odp_init_local(instance, ODP_THREAD_CONTROL)) {
- EXAMPLE_ERR("Error: ODP local init failed.\n");
+ ODPH_ERR("Error: ODP local init failed\n");
exit(EXIT_FAILURE);
}
@@ -500,27 +671,28 @@ int main(int argc, char *argv[])
ODP_CACHE_LINE_SIZE, 0);
if (shm == ODP_SHM_INVALID) {
- EXAMPLE_ERR("Error: shared mem reserve failed.\n");
+ ODPH_ERR("Error: shared mem reserve failed\n");
exit(EXIT_FAILURE);
}
args = odp_shm_addr(shm);
if (args == NULL) {
- EXAMPLE_ERR("Error: shared mem alloc failed.\n");
+ ODPH_ERR("Error: shared mem alloc failed\n");
exit(EXIT_FAILURE);
}
+ appl_args_gbl = args;
memset(args, 0, sizeof(*args));
/* Parse and store the application arguments */
- parse_args(argc, argv, args);
+ if (parse_args(argc, argv, args))
+ goto args_error;
/* Print both system and application information */
print_info(NO_PATH(argv[0]), args);
- /* Default to system CPU count unless user specified */
num_workers = MAX_WORKERS;
- if (args->cpu_count)
+ if (args->cpu_count && args->cpu_count < MAX_WORKERS)
num_workers = args->cpu_count;
/* Get default worker cpumask */
@@ -532,18 +704,10 @@ int main(int argc, char *argv[])
printf("cpu mask: %s\n", cpumaskstr);
/* Create packet pool */
- odp_pool_param_init(&params);
- params.pkt.seg_len = SHM_PKT_POOL_BUF_SIZE;
- params.pkt.len = SHM_PKT_POOL_BUF_SIZE;
- params.pkt.num = SHM_PKT_POOL_SIZE / SHM_PKT_POOL_BUF_SIZE;
- params.type = ODP_POOL_PACKET;
-
- pool = odp_pool_create("packet_pool", &params);
+ pool = pool_create("packet_pool");
- if (pool == ODP_POOL_INVALID) {
- EXAMPLE_ERR("Error: packet pool create failed.\n");
- exit(EXIT_FAILURE);
- }
+ /* Configure scheduler */
+ odp_schedule_config(NULL);
/* odp_pool_print(pool); */
odp_atomic_init_u64(&args->total_packets, 0);
@@ -556,52 +720,80 @@ int main(int argc, char *argv[])
configure_cos(default_cos, args);
+ printf("\n");
+ odp_pool_print_all();
+ odp_cls_print_all();
+
if (odp_pktio_start(pktio)) {
- EXAMPLE_ERR("Error: unable to start pktio.\n");
+ ODPH_ERR("Error: unable to start pktio\n");
exit(EXIT_FAILURE);
}
/* Create and init worker threads */
memset(thread_tbl, 0, sizeof(thread_tbl));
+ odph_thread_common_param_init(&thr_common);
+ odph_thread_param_init(&thr_param);
+
+ thr_param.start = pktio_receive_thread;
+ thr_param.arg = args;
+ thr_param.thr_type = ODP_THREAD_WORKER;
- memset(&thr_params, 0, sizeof(thr_params));
- thr_params.start = pktio_receive_thread;
- thr_params.arg = args;
- thr_params.thr_type = ODP_THREAD_WORKER;
- thr_params.instance = instance;
- odph_odpthreads_create(thread_tbl, &cpumask, &thr_params);
+ thr_common.instance = instance;
+ thr_common.cpumask = &cpumask;
+ thr_common.share_param = 1;
- print_cls_statistics(args);
+ odph_thread_create(thread_tbl, &thr_common, &thr_param, num_workers);
+
+ if (args->verbose == 0) {
+ print_cls_statistics(args);
+ } else {
+ int timeout = args->time;
+
+ for (i = 0; timeout == 0 || i < timeout; i++) {
+ if (args->shutdown_sig)
+ break;
+
+ sleep(1);
+ }
+ }
odp_pktio_stop(pktio);
- shutdown = 1;
- odph_odpthreads_join(thread_tbl);
+ args->shutdown = 1;
+ odph_thread_join(thread_tbl, num_workers);
+
+ if (check_ci_pass_count(args)) {
+ ODPH_ERR("Error: Packet count verification failed\n");
+ exit(EXIT_FAILURE);
+ }
for (i = 0; i < args->policy_count; i++) {
if ((i != args->policy_count - 1) &&
odp_cls_pmr_destroy(args->stats[i].pmr))
- EXAMPLE_ERR("err: odp_cls_pmr_destroy for %d\n", i);
+ ODPH_ERR("err: odp_cls_pmr_destroy for %d\n", i);
if (odp_cos_destroy(args->stats[i].cos))
- EXAMPLE_ERR("err: odp_cos_destroy for %d\n", i);
+ ODPH_ERR("err: odp_cos_destroy for %d\n", i);
if (odp_queue_destroy(args->stats[i].queue))
- EXAMPLE_ERR("err: odp_queue_destroy for %d\n", i);
- if (odp_pool_destroy(args->stats[i].pool))
- EXAMPLE_ERR("err: odp_pool_destroy for %d\n", i);
+ ODPH_ERR("err: odp_queue_destroy for %d\n", i);
+ if (args->cos_pools && odp_pool_destroy(args->stats[i].pool))
+ ODPH_ERR("err: odp_pool_destroy for %d\n", i);
}
- free(args->if_name);
- odp_shm_free(shm);
if (odp_pktio_close(pktio))
- EXAMPLE_ERR("err: close pktio error\n");
+ ODPH_ERR("err: close pktio error\n");
if (odp_pool_destroy(pool))
- EXAMPLE_ERR("err: odp_pool_destroy error\n");
+ ODPH_ERR("err: odp_pool_destroy error\n");
+
+ free(args->if_name);
+
+args_error:
+ odp_shm_free(shm);
ret = odp_term_local();
if (ret)
- EXAMPLE_ERR("odp_term_local error %d\n", ret);
+ ODPH_ERR("odp_term_local error %d\n", ret);
ret = odp_term_global(instance);
if (ret)
- EXAMPLE_ERR("odp_term_global error %d\n", ret);
+ ODPH_ERR("odp_term_global error %d\n", ret);
printf("Exit\n\n");
return ret;
}
@@ -615,26 +807,26 @@ int main(int argc, char *argv[])
* @param pkt_tbl Array of packet
* @param len Length of pkt_tbl[]
*
- * @return Number of packets with no detected error
+ * @return Number of packets dropped
*/
static int drop_err_pkts(odp_packet_t pkt_tbl[], unsigned len)
{
odp_packet_t pkt;
- unsigned pkt_cnt = len;
unsigned i, j;
+ int dropped = 0;
for (i = 0, j = 0; i < len; ++i) {
pkt = pkt_tbl[i];
if (odp_unlikely(odp_packet_has_error(pkt))) {
odp_packet_free(pkt); /* Drop */
- pkt_cnt--;
+ dropped++;
} else if (odp_unlikely(i != j++)) {
pkt_tbl[j-1] = pkt;
}
}
- return pkt_cnt;
+ return dropped;
}
/**
@@ -674,105 +866,289 @@ static void swap_pkt_addrs(odp_packet_t pkt_tbl[], unsigned len)
}
}
-static int convert_str_to_pmr_enum(char *token, odp_cls_pmr_term_t *term,
- uint32_t *offset)
+static int convert_str_to_pmr_enum(char *token, odp_cls_pmr_term_t *term)
{
if (NULL == token)
return -1;
- if (0 == strcasecmp(token, "ODP_PMR_SIP_ADDR")) {
+ if (strcasecmp(token, "ODP_PMR_ETHTYPE_0") == 0) {
+ *term = ODP_PMR_ETHTYPE_0;
+ return 0;
+ } else if (strcasecmp(token, "ODP_PMR_ETHTYPE_X") == 0) {
+ *term = ODP_PMR_ETHTYPE_X;
+ return 0;
+ } else if (strcasecmp(token, "ODP_PMR_VLAN_ID_0") == 0) {
+ *term = ODP_PMR_VLAN_ID_0;
+ return 0;
+ } else if (strcasecmp(token, "ODP_PMR_VLAN_ID_X") == 0) {
+ *term = ODP_PMR_VLAN_ID_X;
+ return 0;
+ } else if (strcasecmp(token, "ODP_PMR_UDP_DPORT") == 0) {
+ *term = ODP_PMR_UDP_DPORT;
+ return 0;
+ } else if (strcasecmp(token, "ODP_PMR_TCP_DPORT") == 0) {
+ *term = ODP_PMR_TCP_DPORT;
+ return 0;
+ } else if (strcasecmp(token, "ODP_PMR_UDP_SPORT") == 0) {
+ *term = ODP_PMR_UDP_SPORT;
+ return 0;
+ } else if (strcasecmp(token, "ODP_PMR_TCP_SPORT") == 0) {
+ *term = ODP_PMR_TCP_SPORT;
+ return 0;
+ } else if (strcasecmp(token, "ODP_PMR_DIP_ADDR") == 0) {
+ *term = ODP_PMR_DIP_ADDR;
+ return 0;
+ } else if (strcasecmp(token, "ODP_PMR_SIP_ADDR") == 0) {
*term = ODP_PMR_SIP_ADDR;
return 0;
- } else {
- errno = 0;
- *offset = strtoul(token, NULL, 0);
- if (errno)
- return -1;
+ } else if (strcasecmp(token, "ODP_PMR_DMAC") == 0) {
+ *term = ODP_PMR_DMAC;
+ return 0;
+ } else if (strcasecmp(token, "ODP_PMR_CUSTOM_FRAME") == 0) {
*term = ODP_PMR_CUSTOM_FRAME;
return 0;
+ } else if (strcasecmp(token, "ODP_PMR_CUSTOM_L3") == 0) {
+ *term = ODP_PMR_CUSTOM_L3;
+ return 0;
}
+
return -1;
}
-
-static int parse_pmr_policy(appl_args_t *appl_args, char *argv[], char *optarg)
+static int parse_pmr_policy(appl_args_t *appl_args, char *optarg)
{
int policy_count;
- char *token;
+ char *token, *cos0, *cos1, *cur_char;
size_t len;
odp_cls_pmr_term_t term;
global_statistics *stats;
+ odph_ethaddr_t mac;
char *pmr_str;
- uint32_t offset;
- uint32_t ip_addr;
+ uint32_t offset, ip_addr, u32;
+ unsigned long int value, mask;
+ uint16_t u16;
+ int val_sz, mask_sz;
policy_count = appl_args->policy_count;
stats = appl_args->stats;
/* last array index is needed for default queue */
if (policy_count >= MAX_PMR_COUNT - 1) {
- EXAMPLE_ERR("Maximum allowed PMR reached\n");
+ ODPH_ERR("Too many policies. Max count is %i.\n",
+ MAX_PMR_COUNT - 1);
return -1;
}
len = strlen(optarg);
len++;
pmr_str = malloc(len);
+ if (pmr_str == NULL) {
+ ODPH_ERR("Memory allocation failed\n");
+ return -1;
+ }
strcpy(pmr_str, optarg);
/* PMR TERM */
+ /* <term>:<xxx>:<yyy>:<src_cos>:<dst_cos> */
token = strtok(pmr_str, ":");
- if (convert_str_to_pmr_enum(token, &term, &offset)) {
- EXAMPLE_ERR("Invalid ODP_PMR_TERM string\n");
- exit(EXIT_FAILURE);
+ if (convert_str_to_pmr_enum(token, &term)) {
+ ODPH_ERR("Invalid ODP_PMR_TERM string\n");
+ goto error;
}
stats[policy_count].rule.term = term;
+ stats[policy_count].rule.offset = 0;
/* PMR value */
- switch (term) {
+ switch (term) {
+ case ODP_PMR_ETHTYPE_0:
+ /* Fall through */
+ case ODP_PMR_ETHTYPE_X:
+ /* Fall through */
+ /* :<type>:<mask> */
+ case ODP_PMR_VLAN_ID_0:
+ /* Fall through */
+ case ODP_PMR_VLAN_ID_X:
+ /* Fall through */
+ /* :<vlan_id>:<mask> */
+ case ODP_PMR_UDP_DPORT:
+ /* Fall through */
+ case ODP_PMR_TCP_DPORT:
+ /* Fall through */
+ case ODP_PMR_UDP_SPORT:
+ /* Fall through */
+ case ODP_PMR_TCP_SPORT:
+ /* :<port>:<mask> */
+ token = strtok(NULL, ":");
+ odph_strcpy(stats[policy_count].value, token,
+ DISPLAY_STRING_LEN);
+ value = strtoul(token, NULL, 0);
+ u16 = value;
+ u16 = odp_cpu_to_be_16(u16);
+ memcpy(stats[policy_count].rule.value_be, &u16, sizeof(u16));
+
+ token = strtok(NULL, ":");
+ odph_strcpy(stats[policy_count].mask, token,
+ DISPLAY_STRING_LEN);
+ mask = strtoul(token, NULL, 0);
+ u16 = mask;
+ u16 = odp_cpu_to_be_16(u16);
+ memcpy(stats[policy_count].rule.mask_be, &u16, sizeof(u16));
+
+ stats[policy_count].rule.val_sz = 2;
+ break;
+ case ODP_PMR_DIP_ADDR:
+ /* Fall through */
case ODP_PMR_SIP_ADDR:
+ /* :<IP addr>:<mask> */
token = strtok(NULL, ":");
- strncpy(stats[policy_count].value, token,
- DISPLAY_STRING_LEN - 1);
+ odph_strcpy(stats[policy_count].value, token,
+ DISPLAY_STRING_LEN);
if (odph_ipv4_addr_parse(&ip_addr, token)) {
- EXAMPLE_ERR("Bad IP address\n");
- exit(EXIT_FAILURE);
+ ODPH_ERR("Bad IP address\n");
+ goto error;
}
- stats[policy_count].rule.val = ip_addr;
+ u32 = odp_cpu_to_be_32(ip_addr);
+ memcpy(stats[policy_count].rule.value_be, &u32, sizeof(u32));
token = strtok(NULL, ":");
- strncpy(stats[policy_count].mask, token,
- DISPLAY_STRING_LEN - 1);
- parse_mask(token, &stats[policy_count].rule.mask);
+ odph_strcpy(stats[policy_count].mask, token,
+ DISPLAY_STRING_LEN);
+ mask = strtoul(token, NULL, 0);
+ u32 = mask;
+ u32 = odp_cpu_to_be_32(u32);
+ memcpy(stats[policy_count].rule.mask_be, &u32, sizeof(u32));
+
stats[policy_count].rule.val_sz = 4;
- stats[policy_count].rule.offset = 0;
break;
- case ODP_PMR_CUSTOM_FRAME:
+ case ODP_PMR_DMAC:
+ /* :<MAC addr>:<mask> */
token = strtok(NULL, ":");
- strncpy(stats[policy_count].value, token,
- DISPLAY_STRING_LEN - 1);
- parse_value(token, &stats[policy_count].rule.val,
- &stats[policy_count].rule.val_sz);
+ odph_strcpy(stats[policy_count].value, token,
+ DISPLAY_STRING_LEN);
+
+ /* Replace hyphens in the MAC string with colons to be compatible with
+ * odph_eth_addr_parse(). */
+ cur_char = token;
+ while ((cur_char = strchr(cur_char, '-')) != NULL)
+ *cur_char++ = ':';
+
+ if (odph_eth_addr_parse(&mac, token)) {
+ ODPH_ERR("Invalid MAC address. Use format 11-22-33-44-55-66.\n");
+ goto error;
+ }
+
+ memcpy(stats[policy_count].rule.value_be, mac.addr, ODPH_ETHADDR_LEN);
+ stats[policy_count].rule.val_sz = 6;
+
token = strtok(NULL, ":");
- strncpy(stats[policy_count].mask, token,
- DISPLAY_STRING_LEN - 1);
- parse_mask(token, &stats[policy_count].rule.mask);
+ odph_strcpy(stats[policy_count].mask, token, DISPLAY_STRING_LEN);
+ mask_sz = parse_custom(token, stats[policy_count].rule.mask_be, ODPH_ETHADDR_LEN);
+ if (mask_sz != ODPH_ETHADDR_LEN) {
+ ODPH_ERR("Invalid mask. Provide mask without 0x prefix.\n");
+ goto error;
+ }
+ break;
+ case ODP_PMR_CUSTOM_FRAME:
+ /* Fall through */
+ case ODP_PMR_CUSTOM_L3:
+ /* :<offset>:<value>:<mask> */
+ token = strtok(NULL, ":");
+ errno = 0;
+ offset = strtoul(token, NULL, 0);
stats[policy_count].rule.offset = offset;
+ if (errno)
+ goto error;
+
+ token = strtok(NULL, ":");
+ odph_strcpy(stats[policy_count].value, token,
+ DISPLAY_STRING_LEN);
+ val_sz = parse_custom(token,
+ stats[policy_count].rule.value_be,
+ MAX_VAL_SIZE);
+ stats[policy_count].rule.val_sz = val_sz;
+ if (val_sz <= 0)
+ goto error;
+
+ token = strtok(NULL, ":");
+ odph_strcpy(stats[policy_count].mask, token,
+ DISPLAY_STRING_LEN);
+ mask_sz = parse_custom(token,
+ stats[policy_count].rule.mask_be,
+ MAX_VAL_SIZE);
+ if (mask_sz != val_sz)
+ goto error;
break;
default:
- usage(argv[0]);
- exit(EXIT_FAILURE);
+ goto error;
}
- /* Queue Name */
- token = strtok(NULL, ":");
+ /* Optional source CoS name and name of this CoS
+ * :<src_cos>:<cos> */
+ cos0 = strtok(NULL, ":");
+ cos1 = strtok(NULL, ":");
+ if (cos0 == NULL)
+ goto error;
+
+ if (cos1) {
+ stats[policy_count].has_src_cos = 1;
+ odph_strcpy(stats[policy_count].src_cos_name, cos0,
+ ODP_COS_NAME_LEN);
+ odph_strcpy(stats[policy_count].cos_name, cos1,
+ ODP_COS_NAME_LEN);
+ } else {
+ odph_strcpy(stats[policy_count].cos_name, cos0,
+ ODP_COS_NAME_LEN);
+ }
- strncpy(stats[policy_count].cos_name, token, ODP_QUEUE_NAME_LEN - 1);
appl_args->policy_count++;
free(pmr_str);
return 0;
+
+error:
+ free(pmr_str);
+ return -1;
+}
+
+static int parse_policy_ci_pass_count(appl_args_t *appl_args, char *optarg)
+{
+ int num_ci_pass_rules;
+ char *token, *value;
+ size_t len;
+ ci_pass_counters *ci_pass_rules;
+ char *count_str;
+
+ num_ci_pass_rules = appl_args->num_ci_pass_rules;
+ ci_pass_rules = appl_args->ci_pass_rules;
+
+ /* last array index is needed for default queue */
+ if (num_ci_pass_rules >= MAX_PMR_COUNT) {
+ ODPH_ERR("Too many ci pass counters. Max count is %i.\n",
+ MAX_PMR_COUNT);
+ return -1;
+ }
+
+ len = strlen(optarg);
+ len++;
+ count_str = malloc(len);
+ if (count_str == NULL) {
+ ODPH_ERR("Memory allocation failed\n");
+ return -1;
+ }
+ strcpy(count_str, optarg);
+
+ token = strtok(count_str, ":");
+ value = strtok(NULL, ":");
+ if (!token || !value) {
+ free(count_str);
+ return -1;
+ }
+ strcpy(ci_pass_rules[num_ci_pass_rules].cos_name, token);
+ ci_pass_rules[num_ci_pass_rules].count = atoll(value);
+ appl_args->num_ci_pass_rules++;
+ free(count_str);
+ return 0;
}
/**
@@ -782,33 +1158,45 @@ static int parse_pmr_policy(appl_args_t *appl_args, char *argv[], char *optarg)
* @param argv[] argument vector
* @param appl_args Store application arguments here
*/
-static void parse_args(int argc, char *argv[], appl_args_t *appl_args)
+static int parse_args(int argc, char *argv[], appl_args_t *appl_args)
{
int opt;
int long_index;
size_t len;
int i;
int interface = 0;
- int policy = 0;
+ int ret = 0;
static const struct option longopts[] = {
{"count", required_argument, NULL, 'c'},
- {"interface", required_argument, NULL, 'i'}, /* return 'i' */
- {"policy", required_argument, NULL, 'p'}, /* return 'p' */
- {"mode", required_argument, NULL, 'm'}, /* return 'm' */
- {"time", required_argument, NULL, 't'}, /* return 't' */
- {"help", no_argument, NULL, 'h'}, /* return 'h' */
+ {"interface", required_argument, NULL, 'i'},
+ {"policy", required_argument, NULL, 'p'},
+ {"mode", required_argument, NULL, 'm'},
+ {"time", required_argument, NULL, 't'},
+ {"ci_pass", required_argument, NULL, 'C'},
+ {"promisc_mode", no_argument, NULL, 'P'},
+ {"verbose", no_argument, NULL, 'v'},
+ {"help", no_argument, NULL, 'h'},
+ {"enable", required_argument, NULL, 'e'},
+ {"layer", required_argument, NULL, 'l'},
+ {"dedicated", required_argument, NULL, 'd'},
+ {"size", required_argument, NULL, 's'},
+ {"burst", required_argument, NULL, 'b'},
{NULL, 0, NULL, 0}
};
- static const char *shortopts = "+c:t:i:p:m:t:h";
-
- /* let helper collect its own arguments (e.g. --odph_proc) */
- odph_parse_options(argc, argv, shortopts, longopts);
+ static const char *shortopts = "+c:t:i:p:m:t:C:Pvhe:l:d:s:b:";
- opterr = 0; /* do not issue errors on helper options */
+ appl_args->cpu_count = 1; /* Use one worker by default */
+ appl_args->verbose = 0;
+ appl_args->promisc_mode = 0;
+ appl_args->classifier_enable = 1;
+ appl_args->parse_layer = ODP_PROTO_LAYER_ALL;
+ appl_args->cos_pools = 1;
+ appl_args->pool_size = SHM_PKT_POOL_SIZE;
+ appl_args->burst_size = DEF_PKT_BURST;
- while (1) {
+ while (ret == 0) {
opt = getopt_long(argc, argv, shortopts,
longopts, &long_index);
@@ -820,9 +1208,10 @@ static void parse_args(int argc, char *argv[], appl_args_t *appl_args)
appl_args->cpu_count = atoi(optarg);
break;
case 'p':
- if (0 > parse_pmr_policy(appl_args, argv, optarg))
- continue;
- policy = 1;
+ if (parse_pmr_policy(appl_args, optarg)) {
+ ret = -1;
+ break;
+ }
break;
case 't':
appl_args->time = atoi(optarg);
@@ -830,25 +1219,20 @@ static void parse_args(int argc, char *argv[], appl_args_t *appl_args)
case 'i':
len = strlen(optarg);
if (len == 0) {
- usage(argv[0]);
- exit(EXIT_FAILURE);
+ ret = -1;
+ break;
}
len += 1; /* add room for '\0' */
appl_args->if_name = malloc(len);
if (appl_args->if_name == NULL) {
- usage(argv[0]);
- exit(EXIT_FAILURE);
+ ret = -1;
+ break;
}
strcpy(appl_args->if_name, optarg);
interface = 1;
break;
-
- case 'h':
- usage(argv[0]);
- exit(EXIT_SUCCESS);
- break;
case 'm':
i = atoi(optarg);
if (i == 0)
@@ -856,22 +1240,56 @@ static void parse_args(int argc, char *argv[], appl_args_t *appl_args)
else
appl_args->appl_mode = APPL_MODE_REPLY;
break;
-
+ case 'C':
+ if (parse_policy_ci_pass_count(appl_args, optarg)) {
+ ret = -1;
+ break;
+ }
+ break;
+ case 'P':
+ appl_args->promisc_mode = 1;
+ break;
+ case 'v':
+ appl_args->verbose = 1;
+ break;
+ case 'h':
+ ret = -1;
+ break;
+ case 'e':
+ appl_args->classifier_enable = atoi(optarg);
+ break;
+ case 'l':
+ appl_args->parse_layer = atoi(optarg);
+ break;
+ case 'd':
+ appl_args->cos_pools = atoi(optarg);
+ break;
+ case 's':
+ appl_args->pool_size = atoi(optarg);
+ break;
+ case 'b':
+ appl_args->burst_size = atoi(optarg);
+ break;
default:
break;
}
}
- if (!interface || !policy) {
- usage(argv[0]);
- exit(EXIT_FAILURE);
- }
- if (appl_args->if_name == NULL) {
- usage(argv[0]);
- exit(EXIT_FAILURE);
+ if (!interface)
+ ret = -1;
+
+ if (appl_args->if_name == NULL)
+ ret = -1;
+
+ if (ret) {
+ usage();
+ free(appl_args->if_name);
}
- optind = 1; /* reset 'extern optind' from the getopt lib */
+ /* reset optind from the getopt lib */
+ optind = 1;
+
+ return ret;
}
/**
@@ -879,70 +1297,83 @@ static void parse_args(int argc, char *argv[], appl_args_t *appl_args)
*/
static void print_info(char *progname, appl_args_t *appl_args)
{
- printf("\n"
- "ODP system info\n"
- "---------------\n"
- "ODP API version: %s\n"
- "CPU model: %s\n"
- "CPU freq (hz): %"PRIu64"\n"
- "Cache line size: %i\n"
- "CPU count: %i\n"
- "\n",
- odp_version_api_str(), odp_cpu_model_str(),
- odp_cpu_hz_max(), odp_sys_cache_line_size(),
- odp_cpu_count());
+ odp_sys_info_print();
printf("Running ODP appl: \"%s\"\n"
"-----------------\n"
- "Using IF:%s ",
+ "Using IF: %s\n",
progname, appl_args->if_name);
+ printf("Promisc mode: %s\n", appl_args->promisc_mode ? "enabled" : "disabled");
printf("\n\n");
fflush(NULL);
}
/**
- * Prinf usage information
+ * Print usage information
*/
-static void usage(char *progname)
+static void usage(void)
{
printf("\n"
- "OpenDataPlane Classifier example.\n"
- "Usage: %s OPTIONS\n"
- " E.g. %s -i eth1 -m 0 -p \"ODP_PMR_SIP_ADDR:10.10.10.5:FFFFFFFF:queue1\" \\\n"
- "\t\t\t-p \"ODP_PMR_SIP_ADDR:10.10.10.7:000000FF:queue2\" \\\n"
- "\t\t\t-p \"ODP_PMR_SIP_ADDR:10.5.5.10:FFFFFF00:queue3\"\n"
- "\n"
- "For the above example configuration the following will be the packet distribution\n"
- "queue1\t\tPackets with source ip address 10.10.10.5\n"
- "queue2\t\tPackets with source ip address whose last 8 bits match 7\n"
- "queue3\t\tPackets with source ip address in the subnet 10.5.5.0\n"
- "\n"
- "Mandatory OPTIONS:\n"
- " -i, --interface Eth interface\n"
- " -p, --policy [<odp_cls_pmr_term_t>|<offset>]:<value>:<mask bits>:<queue name>\n"
- "\n"
- "<odp_cls_pmr_term_t> Packet Matching Rule defined with odp_cls_pmr_term_t "
- "for the policy\n"
- "<offset> Absolute offset in bytes from frame start to define a "
- "ODP_PMR_CUSTOM_FRAME Packet Matching Rule for the policy\n"
- "\n"
- "<value> PMR value to be matched.\n"
- "\n"
- "<mask bits> PMR mask bits to be applied on the PMR term value\n"
- "\n"
- "Optional OPTIONS\n"
- " -c, --count <number> CPU count.\n"
- " default: CPU core count.\n"
- "\n"
- " -m, --mode 0: Packet Drop mode. Received packets will be dropped\n"
- " !0: Packet ICMP mode. Received packets will be sent back\n"
- " default: Packet Drop mode\n"
- "\n"
- " -t, --timeout !0: Time for which the classifier will be run in seconds\n"
- " 0: Runs in infinite loop\n"
- " default: Runs in infinite loop\n"
- "\n"
- " -h, --help Display help and exit.\n"
- "\n", NO_PATH(progname), NO_PATH(progname)
- );
+ "ODP Classifier example.\n"
+ "Usage: odp_classifier OPTIONS\n"
+ " E.g. odp_classifier -i eth1 -m 0 -p \"ODP_PMR_SIP_ADDR:10.10.10.0:0xFFFFFF00:queue1\" \\\n"
+ " -p \"ODP_PMR_SIP_ADDR:10.10.10.10:0xFFFFFFFF:queue1:queue2\"\n"
+ "\n"
+ "The above example would classify:\n"
+ " 1) Packets from source IP address 10.10.10.0/24 to queue1, except ...\n"
+ " 2) Packets from source IP address 10.10.10.10 to queue2\n"
+ " 3) All other packets to DefaultCos\n"
+ "\n"
+ "Mandatory OPTIONS:\n"
+ " -i, --interface <interface name>\n"
+ "\n"
+ "Optional OPTIONS\n"
+ " -p, --policy <PMR term>:<offset>:<value>:<mask>:<src queue>:<dst queue>\n"
+ "\n"
+ " <PMR term> PMR term name defined in odp_cls_pmr_term_t\n"
+ " <offset> If term is ODP_PMR_CUSTOM_FRAME or _CUSTOM_L3, offset in bytes is used\n"
+ " <value> PMR value to be matched\n"
+ " <mask> PMR mask bits to be applied on the PMR value.\n"
+ " CUSTOM PMR terms accept plain hex string, other PMR terms require\n"
+ " hex string with '0x' prefix.\n"
+ " <src queue> Optional name of the source queue (CoS). The default CoS is used when\n"
+ " this is not defined.\n"
+ " <dst queue> Name of the destination queue (CoS).\n"
+ "\n"
+ " -c, --count <num> CPU count, 0=all available, default=1\n"
+ "\n"
+ " -m, --mode <mode> 0: Packet Drop mode. Received packets will be dropped\n"
+ " !0: Echo mode. Received packets will be sent back\n"
+ " default: Packet Drop mode\n"
+ "\n"
+ " -t, --time <sec> !0: Time for which the classifier will be run in seconds\n"
+ " 0: Runs in infinite loop\n"
+ " default: Runs in infinite loop\n"
+ "\n"
+ " -e, --enable <enable> 0: Classifier is disabled\n"
+ " 1: Classifier is enabled\n"
+ " default: Classifier is enabled\n"
+ "\n"
+ " -l, --layer <layer> Parse packets up to and including this layer. See odp_proto_layer_t\n"
+ " default: ODP_PROTO_LAYER_ALL\n"
+ "\n"
+ " -d, --dedicated <enable> 0: One pool for pktio and all CoSes\n"
+ " 1: Dedicated pools for pktio and each CoS\n"
+ " default: Dedicated pools\n"
+ "\n"
+ " -s, --size <num> Number of packets in each packet pool\n"
+ " default: %d\n"
+ "\n"
+ " -b, --burst <num> Packet burst size\n"
+ " default: %d\n"
+ "\n"
+ " -C, --ci_pass <dst queue:count>\n"
+ " Minimum acceptable packet count for a CoS destination queue.\n"
+ " If the received packet count is smaller than this value,\n"
+ " the application will exit with an error.\n"
+ " E.g: -C \"queue1:100\" -C \"queue2:200\" -C \"DefaultQueue:100\"\n"
+ " -P, --promisc_mode Enable promiscuous mode.\n"
+ " -v, --verbose Verbose output.\n"
+ " -h, --help Display help and exit.\n"
+ "\n", SHM_PKT_POOL_SIZE, DEF_PKT_BURST);
}