Hi Maxim,

I will update these comments in the next version.

Regards,
Bala

On 20/03/15 8:20 pm, Maxim Uvarov wrote:
Hello Bala, please find some comments bellow.

Best regards,
Maxim.

On 03/20/15 10:07, bala.manoha...@linaro.org wrote:
From: Balasubramanian Manoharan <bala.manoha...@linaro.org>

ODP Classifier example

This programs gets pmr rules as command-line parameter and configures the classification engine
in the system.

This initial version supports the following
* ODP_PMR_SIP_ADDR pmr term
* PMR term MATCH and RANGE type
* Multiple PMR rule can be set on a single pktio interface with different queues associated to each PMR rule * Automatically configures a default queue and provides statistics for the same * Prints statistics interms of the number of packets dispatched to each queue

Signed-off-by: Balasubramanian Manoharan <bala.manoha...@linaro.org>
---
  configure.ac                        |   1 +
  example/Makefile.am                 |   2 +-
  example/classifier/Makefile.am      |  10 +
example/classifier/odp_classifier.c | 759 ++++++++++++++++++++++++++++++++++++
  4 files changed, 771 insertions(+), 1 deletion(-)
  create mode 100644 example/classifier/Makefile.am
  create mode 100644 example/classifier/odp_classifier.c

diff --git a/configure.ac b/configure.ac
index 57054c5..51e4834 100644
--- a/configure.ac
+++ b/configure.ac
@@ -255,6 +255,7 @@ AC_CONFIG_FILES([Makefile
           example/l2fwd/Makefile
           example/packet/Makefile
           example/timer/Makefile
+         example/classifier/Makefile
alphabetic order
Agreed.
           pkgconfig/libodp.pc
           platform/Makefile
           platform/linux-generic/Makefile
diff --git a/example/Makefile.am b/example/Makefile.am
index 3021571..aa09a8e 100644
--- a/example/Makefile.am
+++ b/example/Makefile.am
@@ -1 +1 @@
-SUBDIRS = generator ipsec l2fwd packet timer
+SUBDIRS = generator ipsec l2fwd packet timer classifier
alphabetic order
diff --git a/example/classifier/Makefile.am b/example/classifier/Makefile.am
new file mode 100644
index 0000000..938f094
--- /dev/null
+++ b/example/classifier/Makefile.am
@@ -0,0 +1,10 @@
+include $(top_srcdir)/example/Makefile.inc
+
+bin_PROGRAMS = odp_classifier
+odp_classifier_LDFLAGS = $(AM_LDFLAGS) -static
+odp_classifier_CFLAGS = $(AM_CFLAGS) -I${top_srcdir}/example
+
+noinst_HEADERS = \
+          $(top_srcdir)/example/example_debug.h
+
+dist_odp_classifier_SOURCES = odp_classifier.c
diff --git a/example/classifier/odp_classifier.c b/example/classifier/odp_classifier.c
new file mode 100644
index 0000000..8b34e7d
--- /dev/null
+++ b/example/classifier/odp_classifier.c
@@ -0,0 +1,759 @@
+/* Copyright (c) 2015, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier:     BSD-3-Clause
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <getopt.h>
+#include <unistd.h>
+#include <example_debug.h>
+
+#include <odp.h>
+#include <odp/helper/linux.h>
+#include <odp/helper/eth.h>
+#include <odp/helper/ip.h>
+#include <strings.h>
+#include <stdio.h>
+
+/** @def MAX_WORKERS
+ * @brief Maximum number of worker threads
+ */
+#define MAX_WORKERS            32
+
+/** @def SHM_PKT_POOL_SIZE
+ * @brief Size of the shared memory block
+ */
+#define SHM_PKT_POOL_SIZE      (512*2048)
+
+/** @def SHM_PKT_POOL_BUF_SIZE
+ * @brief Buffer size of the packet pool buffer
+ */
+#define SHM_PKT_POOL_BUF_SIZE  1856
+
+/** @def MAX_PMR_COUNT
+ * @brief Maximum number of Classification Policy
+ */
+#define MAX_PMR_COUNT    8
+
+/** @def DISPLAY_STRING_LEN
+ * @brief Length of string used to display term value
+ */
+#define DISPLAY_STRING_LEN    32
+
+/** 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))
+
+typedef struct {
+    odp_queue_t queue;    /**< Associated queue handle */
+    odp_cos_t cos;        /**< Associated cos handle */
+    odp_pmr_t pmr;        /**< Associated pmr handle */
+    odp_atomic_u64_t packet_count;    /**< count of received packets */
+    odp_pmr_term_e term;        /**< odp pmr term value */
+    char queuename[ODP_QUEUE_NAME_LEN];    /**< queue name */
queue_name is better for reading.
+    odp_pmr_match_type_e match_type; /**< pmr match type */
+    int val_sz;    /**< size of the pmr term */
+    union {
+        struct {
+            uint32_t val;    /**< pmr term value */
+            uint32_t mask;    /**< pmr term mask */
+        } match;
+        struct  {
+            uint32_t val1;    /**< pmr term start range */
+            uint32_t val2;    /**< pmr term end range */
+        } range;
+    };
+    char value1[DISPLAY_STRING_LEN];    /**< Display string1 */
+    char value2[DISPLAY_STRING_LEN];    /**< Display string2 */
+} global_statistics;
+
+static global_statistics stats[MAX_PMR_COUNT];
+static int policy_count;
+static int queue_count;
+static int appl_mode;
+static odp_atomic_u64_t total_packets;
+
+enum packet_mode {
+    APPL_MODE_DROP,        /**< Packet is dropped */
+    APPL_MODE_REPLY        /**< Packet is sent back */
+};
+
+/**
+ * Parsed command line application arguments
+ */
+typedef struct {
+    int cpu_count;        /**< Number of CPUs to use */
+    char *if_name;        /**< pointer to interface names */
+} appl_args_t;
+
+/** Global pointer to args */
+static appl_args_t *args;
+
+/* 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 void print_info(char *progname, appl_args_t *appl_args);
+static void usage(char *progname);
+static void configure_cos_queue(odp_pktio_t pktio);
+static void configure_default_queue(odp_pktio_t pktio);
+static int convert_str_to_pmr_enum(char *token, odp_pmr_term_e *term);
+
+static inline
+void print_cls_statistics(void)
+{
+    int i;
empty line here
+    printf("\n");
+    for (i = 0; i < 40; i++)
+        printf("-");
+    printf("\n");
+    /* print statistics */
+    printf("CLASSIFIER EXAMPLE STATISTICS\n");
+    for (i = 0; i < 40; i++)
+        printf("-");
+    printf("\n");
+    printf("CONFIGURATION\n");
+    printf("\n");
+    printf("QUEUE\tMATCH\tVALUE1\t\tVALUE2\n");
+    for (i = 0; i < 40; i++)
+        printf("-");
+    printf("\n");
+    for (i = 0; i < queue_count; i++) {
+        printf("%s\t", stats[i].queuename);
+        if (stats[i].match_type == ODP_PMR_MASK)
+            printf("MATCH\t");
+        else
+            printf("RANGE\t");
+        printf("%s\t", stats[i].value1);
+        printf("%s\n", stats[i].value2);
+    }
+    printf("\n");
+    printf("RECEIVED PACKETS\n");
+    for (i = 0; i < 40; i++)
+        printf("-");
+    printf("\n");
+    for (i = 0; i < policy_count; i++)
+        printf("%s\t", stats[i].queuename);
+    printf("Total Packets");
+    printf("\n");
+    do {
+        for (i = 0; i < policy_count; i++)
+            printf("%"PRIu64"\t",
+ odp_atomic_load_u64(&stats[i].packet_count));
+
+        printf("\t%"PRIu64"\t", odp_atomic_load_u64(&total_packets));
+
+        sleep(1);
+        printf("\r");
+        fflush(stdout);
+    } while (1);
+}
+
+static inline
+int parse_ipv4_addr(const char *ipaddress, uint32_t *addr)
+{
+    int b[4];
+    int converted;
+
+    converted = sscanf(ipaddress, "%d.%d.%d.%d",
+            &b[3], &b[2], &b[1], &b[0]);
+    if (4 != converted)
+        return -1;
+
+    if ((b[0] > 255) || (b[1] > 255) || (b[2] > 255) || (b[3] > 255))
+        return -1;
+
+    *addr = b[0] | b[1] << 8 | b[2] << 16 | b[3] << 24;
+
+    return 0;
+}
+
+static inline
+int parse_ipv4_mask(const char *str, uint32_t *mask)
+{
+    uint32_t b;
empty line here
+    sscanf(str, "%x", &b);
+    *mask = b;
+    return 0;
+}
+
+/**
+ * Create a pktio handle, optionally associating a default input queue.
+ *
+ * @param dev Device name
+ * @param pool Associated Packet Pool
+ *
+ * @return The handle of the created pktio object.
+ * @retval ODP_PKTIO_INVALID if the create fails.
+ */
+static odp_pktio_t create_pktio(const char *dev, odp_pool_t pool)
+{
+    odp_pktio_t pktio;
+    odp_queue_t inq_def;
+    odp_queue_param_t qparam;
+    char inq_name[ODP_QUEUE_NAME_LEN];
+    int ret;
separate with empty line here
+    /* Open a packet IO instance */
+    pktio = odp_pktio_open(dev, pool);
+    if (pktio == ODP_PKTIO_INVALID)
+        EXAMPLE_ABORT("pktio create failed for %s\n", dev);
+
+    qparam.sched.prio  = ODP_SCHED_PRIO_DEFAULT;
+    qparam.sched.sync  = ODP_SCHED_SYNC_ATOMIC;
+    qparam.sched.group = ODP_SCHED_GROUP_DEFAULT;
+    snprintf(inq_name, sizeof(inq_name), "%" PRIu64 "-pktio_inq_def",
+         odp_pktio_to_u64(pktio));
+    inq_name[ODP_QUEUE_NAME_LEN - 1] = '\0';
+
+ inq_def = odp_queue_create(inq_name, ODP_QUEUE_TYPE_PKTIN, &qparam);
+    if (inq_def == ODP_QUEUE_INVALID)
+        EXAMPLE_ABORT("pktio inq create failed for %s\n", dev);
+
+    ret = odp_pktio_inq_setdef(pktio, inq_def);
+    if (ret != 0)
+        EXAMPLE_ABORT("default input-Q setup for %s\n", dev);
+
+    printf("  created pktio:%02" PRIu64
+            ", dev:%s, queue mode (ATOMIC queues)\n"
+            "  \tdefault pktio%02" PRIu64
+            "-INPUT queue:%" PRIu64 "\n",
+            odp_pktio_to_u64(pktio), dev,
+            odp_pktio_to_u64(pktio), odp_queue_to_u64(inq_def));
+
+    return pktio;
+}
+
+/**
+ * Worker threads to receive the packet
+ *
+ */
+static void *pktio_receive_thread(void *arg ODP_UNUSED)
+{
+    int thr;
+    odp_queue_t outq_def;
+    odp_packet_t pkt;
+    odp_event_t ev;
+    unsigned long err_cnt = 0;
+    odp_queue_t queue;
+    int i;
+    thr = odp_thread_id();
+
+    /* Init this thread */
+    if (odp_init_local())
+        EXAMPLE_ABORT("ODP thread local init failed.\n");
+
+    /* Loop packets */
+    for (;;) {
+        odp_pktio_t pktio_tmp;
+
+        /* Use schedule to get buf from any input queue */
+        ev = odp_schedule(&queue, ODP_SCHED_WAIT);
+

After odp_schedule in some cases (timer example) we check ev for ODP_EVENT_INVALID, in other (l2fwd) we don't. Because it's test example it might be reasonable to check it with odp_unlikely().

+        pkt = odp_packet_from_event(ev);
+
+        /* Total packets received */
+        odp_atomic_inc_u64(&total_packets);
+
+        /* Drop packets with errors */
+        if (odp_unlikely(drop_err_pkts(&pkt, 1) == 0)) {
+            EXAMPLE_ERR("Drop frame - err_cnt:%lu\n", ++err_cnt);
+            continue;
+        }
+
+        pktio_tmp = odp_packet_input(pkt);
+        outq_def = odp_pktio_outq_getdef(pktio_tmp);
+
+        if (outq_def == ODP_QUEUE_INVALID) {
+            EXAMPLE_ERR("  [%02i] Error: def output-Q query\n",
+                    thr);
+            return NULL;
+        }
+
+        /* Swap Eth MACs and possibly IP-addrs before sending back */
+        swap_pkt_addrs(&pkt, 1);
+
+        for (i = 0; i <  MAX_PMR_COUNT; i++) {
+            if (queue == stats[i].queue)
+                odp_atomic_inc_u64(&stats[i].packet_count);
+        }
+
+        if (appl_mode == APPL_MODE_DROP)
+            odp_packet_free(pkt);
+        else
+            odp_queue_enq(outq_def, ev);
+    }
+
+    return NULL;
+}
+
+static void configure_default_queue(odp_pktio_t pktio)
+{
+    odp_queue_param_t qparam;
+    odp_cos_t cos_default;
+    char cosname[ODP_COS_NAME_LEN];
+    char queuename[ODP_QUEUE_NAME_LEN];
same here I would name it cos_name and queue_name. It also consistent with queue_default bellow.
+    odp_queue_t queue_default;
+
+    sprintf(cosname, "Default%s", args->if_name);
+    cos_default = odp_cos_create(cosname);
+
+    qparam.sched.prio = ODP_SCHED_PRIO_DEFAULT;
+    qparam.sched.sync = ODP_SCHED_SYNC_NONE;
+    qparam.sched.group = ODP_SCHED_GROUP_ALL;
+    sprintf(queuename, "%s", "DefaultQueue");
+    queue_default = odp_queue_create(queuename,
+            ODP_QUEUE_TYPE_SCHED, &qparam);
+
+    odp_cos_set_queue(cos_default, queue_default);
+    odp_pktio_default_cos_set(pktio, cos_default);
+    /* add default queue to global stats */
+    stats[policy_count].queue = queue_default;
+    strcpy(stats[policy_count].queuename, "DefaultQueue");
+    odp_atomic_init_u64(&stats[policy_count].packet_count, 0);
+    policy_count++;
+}
+
+static void configure_cos_queue(odp_pktio_t pktio)
+{
+    char cosname[ODP_COS_NAME_LEN];
+    char queuename[ODP_QUEUE_NAME_LEN];
+    int i;
empty lines + names with _
+    for (i = 0; i < policy_count; i++) {
+        sprintf(cosname, "CoS%s", stats[i].queuename);
+        stats[i].cos = odp_cos_create(cosname);
+        odp_queue_param_t qparam;
variable definitions should go to be begging of the scope, i.e. juse after for here.
+
+        if (stats[i].match_type == ODP_PMR_MASK) {
+            stats[i].pmr = odp_pmr_create_match(stats[i].term,
+                    &stats[i].match.val,
+                    &stats[i].match.mask,
+                    stats[i].val_sz);
+        } else {
+            stats[i].pmr = odp_pmr_create_range(stats[i].term,
+                    &stats[i].range.val1,
+                    &stats[i].range.val2,
+                    stats[i].val_sz);
+        }
+        qparam.sched.prio = i % odp_schedule_num_prio();
+        qparam.sched.sync = ODP_SCHED_SYNC_NONE;
+        qparam.sched.group = ODP_SCHED_GROUP_ALL;
+
+        sprintf(queuename, "%s%d", stats[i].queuename, i);
+        stats[i].queue = odp_queue_create(queuename,
+                         ODP_QUEUE_TYPE_SCHED,
+                         &qparam);
+        odp_cos_set_queue(stats[i].cos, stats[i].queue);
+        odp_pktio_pmr_cos(stats[i].pmr, pktio, stats[i].cos);
+
+        odp_atomic_init_u64(&stats[i].packet_count, 0);
+        queue_count++;
+    }
+}
+
+/**
+ * ODP Classifier example main function
+ */
+int main(int argc, char *argv[])
+{
+    odph_linux_pthread_t thread_tbl[MAX_WORKERS];
+    odp_pool_t pool;
+    int num_workers;
+    int i;
+    int cpu;
+    odp_cpumask_t cpumask;
+    char cpumaskstr[ODP_CPUMASK_STR_SIZE];
+    odp_pool_param_t params;
+    odp_pktio_t pktio;
+
+    args = calloc(1, sizeof(appl_args_t));
+    if (args == NULL) {
+        EXAMPLE_ERR("Error: args mem alloc failed.\n");
+        exit(EXIT_FAILURE);
+    }
+
+    /* Parse and store the application arguments */
+    parse_args(argc, argv, args);
+
+    /* Init ODP before calling anything else */
+    if (odp_init_global(NULL, NULL)) {
+        EXAMPLE_ERR("Error: ODP global init failed.\n");
+        exit(EXIT_FAILURE);
+    }
+
+    /* Init this thread */
+    if (odp_init_local()) {
+        EXAMPLE_ERR("Error: ODP local init failed.\n");
+        exit(EXIT_FAILURE);
+    }
+
+    /* 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)
+        num_workers = args->cpu_count;
+
+    /*
+     * By default CPU #0 runs Linux kernel background tasks.
+     * Start mapping thread from CPU #1
+     */
+    num_workers = odph_linux_cpumask_default(&cpumask, num_workers);
+    (void)odp_cpumask_to_str(&cpumask, cpumaskstr, sizeof(cpumaskstr));
+
+    printf("num worker threads: %i\n", num_workers);
+    printf("first CPU:          %i\n", odp_cpumask_first(&cpumask));
+    printf("cpu mask:           %s\n", cpumaskstr);
+
+    /* Create packet pool */
+    memset(&params, 0, sizeof(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", ODP_SHM_NULL, &params);
+
+    if (pool == ODP_POOL_INVALID) {
+        EXAMPLE_ERR("Error: packet pool create failed.\n");
+        exit(EXIT_FAILURE);
+    }
+    /* odp_pool_print(pool); */
+    odp_atomic_init_u64(&total_packets, 0);
+
+    /* create pktio per interface */
+    pktio = create_pktio(args->if_name, pool);
+
+    configure_cos_queue(pktio);
+
+    /* configure default Cos and default queue */
+    configure_default_queue(pktio);
+
+    /* Create and init worker threads */
+    memset(thread_tbl, 0, sizeof(thread_tbl));
+
+    cpu = odp_cpumask_first(&cpumask);
+    for (i = 0; i < num_workers; ++i) {
+        odp_cpumask_t thd_mask;
+        void *(*thr_run_func) (void *);
+
+        thr_run_func = pktio_receive_thread;
+        /*
+         * Calls odp_thread_create(cpu) for each thread
+         */
+        odp_cpumask_zero(&thd_mask);
+        odp_cpumask_set(&thd_mask, cpu);
+        odph_linux_pthread_create(&thread_tbl[i], &thd_mask,
+                      thr_run_func,
+                      NULL);
thr_run_func is not needed here. We used here to provide pointer to 2 functions burst and scheduled,
here only one pktio_receive_thread.

+        cpu = odp_cpumask_next(&cpumask, cpu);
+    }
+
+    print_cls_statistics();
+
+    /* Master thread wait*/
+    odph_linux_pthread_join(thread_tbl, num_workers);
+
+    free(args->if_name);
+    free(args);
+    printf("Exit\n\n");
+
+    return 0;
+}
+
+/**
+ * Drop packets which input parsing marked as containing errors.
+ *
+ * Frees packets with error and modifies pkt_tbl[] to only contain packets with
+ * no detected errors.
+ *
+ * @param pkt_tbl  Array of packet
+ * @param len      Length of pkt_tbl[]
+ *
+ * @return Number of packets with no detected error
+ */
+static int drop_err_pkts(odp_packet_t pkt_tbl[], unsigned len)
+{
+    odp_packet_t pkt;
+    unsigned pkt_cnt = len;
+    unsigned i, j;
+
+    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--;
+        } else if (odp_unlikely(i != j++)) {
+            pkt_tbl[j-1] = pkt;
+        }
+    }
+
+    return pkt_cnt;
+}
+
+/**
+ * Swap eth src<->dst and IP src<->dst addresses
+ *
+ * @param pkt_tbl  Array of packets
+ * @param len      Length of pkt_tbl[]
+ */
+static void swap_pkt_addrs(odp_packet_t pkt_tbl[], unsigned len)
+{
+    odp_packet_t pkt;
+    odph_ethhdr_t *eth;
+    odph_ethaddr_t tmp_addr;
+    odph_ipv4hdr_t *ip;
+    uint32be_t ip_tmp_addr; /* tmp ip addr */
+    unsigned i;
+
+    for (i = 0; i < len; ++i) {
+        pkt = pkt_tbl[i];
+        if (odp_packet_has_eth(pkt)) {
+            eth = (odph_ethhdr_t *)odp_packet_l2_ptr(pkt, NULL);
+
+            tmp_addr = eth->dst;
+            eth->dst = eth->src;
+            eth->src = tmp_addr;
+
+            if (odp_packet_has_ipv4(pkt)) {
+                /* IPv4 */
+                ip = (odph_ipv4hdr_t *)
+                    odp_packet_l3_ptr(pkt, NULL);
+
+                ip_tmp_addr  = ip->src_addr;
+                ip->src_addr = ip->dst_addr;
+                ip->dst_addr = ip_tmp_addr;
+            }
+        }
+    }
+}
+
+static int convert_str_to_pmr_enum(char *token, odp_pmr_term_e *term)
+{
+    if (0 == strcasecmp(token, "ODP_PMR_SIP_ADDR")) {
+        *term = ODP_PMR_SIP_ADDR;
+        return 0;
+    }
+    return -1;
+}
+
+/**
+ * Parse and store the command line arguments
+ *
+ * @param argc       argument count
+ * @param argv[]     argument vector
+ * @param appl_args  Store application arguments here
+ */
+static void parse_args(int argc, char *argv[], appl_args_t *appl_args)
+{
+    int opt;
+    int long_index;
+    char *token;
+    size_t len;
+    odp_pmr_term_e term;
+    int i;
empty line here.
+    static 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' */
+        {"help", no_argument, NULL, 'h'},        /* return 'h' */
+        {NULL, 0, NULL, 0}
+    };
+
+
+    while (1) {
+        opt = getopt_long(argc, argv, "+c:i:p:m:t:h",
+                longopts, &long_index);
+
+        if (opt == -1)
+            break;    /* No more options */
+
+        switch (opt) {
+        case 'c':
+            appl_args->cpu_count = atoi(optarg);
+            break;
+        case 'p':
Bala I think it's better to move p case to separate function, in that case you will have more
space in lines for code.

+            /* last array index is needed for default queue */
+            if (policy_count >= MAX_PMR_COUNT - 1) {
+                EXAMPLE_ERR("Maximum allowed PMR reached\n");
+                continue;
+            }
+
+            len = strlen(optarg);
+            len++;
+            char *pmr_str = malloc(len);
char * also has to be in the beginning of the scope.
+            strcpy(pmr_str, optarg);
+
+            /* PMR TERM */
+            token = strtok(pmr_str, ":");
+            if (convert_str_to_pmr_enum(token, &term))
+                EXAMPLE_ABORT("Invalid ODP_PMR_TERM string");
+            stats[policy_count].term = term;
+            /* PMR RANGE vs MATCH */
+            token = strtok(NULL, ":");
+            if (0 == strcasecmp(token, "range")) {
+                stats[policy_count].match_type = ODP_PMR_RANGE;
+            } else if (0 == strcasecmp(token, "match")) {
+                stats[policy_count].match_type = ODP_PMR_MASK;
+            } else {
+                usage(argv[0]);
+                exit(EXIT_FAILURE);
+            }
+
+            /* PMR value */
+            switch (term)    {
+            case ODP_PMR_SIP_ADDR:
+                if (stats[policy_count].match_type
+                    == ODP_PMR_MASK) {
+                    token = strtok(NULL, ":");
+                    strcpy(stats[policy_count].value1,
+                           token);
+                    parse_ipv4_addr(token,
+                            &stats[policy_count]
+                            .match.val);
+                    token = strtok(NULL, ":");
+                    strcpy(stats[policy_count].value2,
+                           token);
+                    parse_ipv4_mask(token,
+                            &stats[policy_count]
+                            .match.mask);
+                    stats[policy_count].val_sz = 4;
+                } else {
+                    token = strtok(NULL, ":");
+                    strcpy(stats[policy_count].value1,
+                           token);
+                    parse_ipv4_addr(token,
+                            &stats[policy_count]
+                            .range.val1);
+                    token = strtok(NULL, ":");
+                    strcpy(stats[policy_count].value2,
+                           token);
+                    parse_ipv4_addr(token,
+                            &stats[policy_count]
+                            .range.val2);
+                    stats[policy_count].val_sz = 4;
+                }
+                break;
+            default:
+                usage(argv[0]);
+                EXAMPLE_ABORT("PMR term not supported");
+            }
+            /* Queue Name */
+            token = strtok(NULL, ":");
+            strcpy(stats[policy_count].queuename, token);
+            policy_count++;
+            free(pmr_str);
+            break;
+        case 'i':
+            len = strlen(optarg);
+            if (len == 0) {
+                usage(argv[0]);
+                exit(EXIT_FAILURE);
+            }
+            len += 1;    /* add room for '\0' */
+
+            appl_args->if_name = malloc(len);
+            if (appl_args->if_name == NULL) {
+                usage(argv[0]);
+                exit(EXIT_FAILURE);
+            }
+
+            strcpy(appl_args->if_name, optarg);
+            break;
+
+        case 'h':
+            usage(argv[0]);
+            exit(EXIT_SUCCESS);
+            break;
+        case 'm':
+            i = atoi(optarg);
+            if (i == 0)
+                appl_mode = APPL_MODE_DROP;
+            else
+                appl_mode = APPL_MODE_REPLY;
+            break;
+
+        default:
+            break;
+        }
+    }
+
+    if (appl_args->if_name == NULL) {
+        usage(argv[0]);
+        exit(EXIT_FAILURE);
+    }
+
+    optind = 1;        /* reset 'extern optind' from the getopt lib */
+}
+
+/**
+ * Print system and application info
+ */
+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_sys_cpu_model_str(),
+            odp_sys_cpu_hz(), odp_sys_cache_line_size(),
+            odp_cpu_count());
+
+    printf("Running ODP appl: \"%s\"\n"
+            "-----------------\n"
+            "Using IF:%s      ",
+            progname, appl_args->if_name);
+    printf("\n\n");
+    fflush(NULL);
+}
+
+/**
+ * Prinf usage information
+ */
+static void usage(char *progname)
+{
+    printf("\n"
+            "Usage: %s OPTIONS\n"
+ " E.g. %s -i eth1 -m 0 -p \"ODP_PMR_SIP_ADDR:match:10.10.10.5:FFFFFFFF:queue1\" \\\n" + "\t\t\t-p \"ODP_PMR_SIP_ADDR:MATCH:10.10.10.6:FFFFFFFF:queue2\" \\\n" + "\t\t\t-p \"ODP_PMR_SIP_ADDR:MATCH:10.10.10.7:000000FF:queue3\" \\\n"
why not \n and \\\n here?

I think it's better to describe which packets will be in queue3. Which IP goes to 10.10.10.7:000000FF ?

+ "\t\t\t-p \"ODP_PMR_SIP_ADDR:RANGE:10.10.10.10:10.10.10.20:queue3\"\n"
+
+            "\n"
+            "OpenDataPlane Classifier example.\n"
+            "\n"
+            "Mandatory OPTIONS:\n"
+            "  -i, --interface Eth interface\n"
+ " -p, --policy <odp_pmr_term_e>:<match type>:<value1>:<value2>:<queue name>\n"
+            "\n"
+            "<odp_pmr_term_e>    ODP PMR TERM for the policy\n"
A little bit confusing description, at least for first reading. How about:
"Packet Matching Rule defined with odp_pmr_term_e enum field name."

+            "\n"
+            "<match type>        PMR Match type.\n"
+            "            MATCH: PMR rule type MATCH\n"
+            "            RANGE: PMR rule type RANCE\n"
+            "\n"
+            "<value1>        PMR value1.\n"
+ " If match type is MATCH is the the matching value.\n"
+            "            If match type is RANGE it is start range.\n"
+            "\n"
+            "<value2>        PMR value2.\n"
+ " If match type is \"MATCH\" it is the MASK value\n"
+            "            If match type is \"RANCE\" it is end range.\n"
+            "\n\n"
+            "Optional OPTIONS\n"
+            "  -c, --count <number> CPU count.\n"
+ " -m, --mode 0: Packet Drop mode. Received packets will be dropped\n" + " 1: Packet ICMP mode. Received packets will be sent back\n"
From code is 0 for drop and !0 for not drop. Please correct code and write here text about default values for optional options.
+            "  -h, --help        Display help and exit.\n"
+            "\n", NO_PATH(progname), NO_PATH(progname)
+          );
+}


_______________________________________________
lng-odp mailing list
lng-odp@lists.linaro.org
http://lists.linaro.org/mailman/listinfo/lng-odp


_______________________________________________
lng-odp mailing list
lng-odp@lists.linaro.org
http://lists.linaro.org/mailman/listinfo/lng-odp

Reply via email to