aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaxim Uvarov <maxim.uvarov@linaro.org>2018-05-17 16:00:00 +0300
committerMaxim Uvarov <maxim.uvarov@linaro.org>2018-05-17 16:00:44 +0300
commit1e370abc3d53d6863d24d68c56bc77167863b23c (patch)
tree1742a543b21819d5aee633d1515537c4ab1c03a9
parentc484446b4930b5398e958f855917d54a97e6f2c7 (diff)
parentfec028212184490aba4c3673ee33710306428aa2 (diff)
Merge https://github.com/Linaro/odp-dpdk/pull/43
Signed-off-by: Maxim Uvarov <maxim.uvarov@linaro.org> Reviewed-by: Bill Fischofer <bill.fischofer@linaro.org>
-rw-r--r--example/classifier/odp_classifier.c4
-rw-r--r--example/generator/odp_generator.c4
-rw-r--r--example/ipsec/odp_ipsec.c4
-rw-r--r--example/ipsec_api/odp_ipsec.c4
-rwxr-xr-xexample/l2fwd_simple/l2fwd_simple_run.sh1
-rw-r--r--example/l2fwd_simple/odp_l2fwd_simple.c30
-rw-r--r--example/packet/odp_pktio.c4
-rw-r--r--example/switch/odp_switch.c4
-rw-r--r--example/time/time_global_test.c2
-rw-r--r--example/timer/odp_timer_test.c4
-rw-r--r--helper/include/odp/helper/threads.h75
-rw-r--r--helper/test/odpthreads.c2
-rw-r--r--helper/threads.c131
-rw-r--r--platform/linux-dpdk/odp_packet_dpdk.c2
-rw-r--r--platform/linux-generic/Makefile.am1
-rw-r--r--platform/linux-generic/include/odp_classification_internal.h2
-rw-r--r--platform/linux-generic/include/odp_packet_dpdk.h20
-rw-r--r--platform/linux-generic/odp_classification.c12
-rw-r--r--platform/linux-generic/pktio/dpdk.c124
-rw-r--r--platform/linux-generic/pktio/dpdk_parse.c492
-rw-r--r--platform/linux-generic/pktio/loop.c2
-rw-r--r--platform/linux-generic/pktio/netmap.c2
-rw-r--r--platform/linux-generic/pktio/socket.c3
-rw-r--r--platform/linux-generic/pktio/socket_mmap.c3
-rw-r--r--platform/linux-generic/pktio/tap.c2
-rw-r--r--platform/linux-generic/test/mmap_vlan_ins/mmap_vlan_ins.c38
-rw-r--r--test/common/odp_cunit_common.c3
-rw-r--r--test/performance/odp_bench_packet.c4
-rw-r--r--test/performance/odp_crypto.c4
-rw-r--r--test/performance/odp_ipsec.c4
-rw-r--r--test/performance/odp_l2fwd.c4
-rw-r--r--test/performance/odp_pktio_ordered.c4
-rw-r--r--test/performance/odp_pktio_perf.c4
-rw-r--r--test/performance/odp_sched_latency.c3
-rw-r--r--test/performance/odp_sched_pktio.c2
-rw-r--r--test/performance/odp_scheduling.c3
36 files changed, 622 insertions, 385 deletions
diff --git a/example/classifier/odp_classifier.c b/example/classifier/odp_classifier.c
index ddb934bed..3afe7645b 100644
--- a/example/classifier/odp_classifier.c
+++ b/example/classifier/odp_classifier.c
@@ -805,9 +805,7 @@ static void parse_args(int argc, char *argv[], appl_args_t *appl_args)
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);
-
- opterr = 0; /* do not issue errors on helper options */
+ argc = odph_parse_options(argc, argv);
while (1) {
opt = getopt_long(argc, argv, shortopts,
diff --git a/example/generator/odp_generator.c b/example/generator/odp_generator.c
index 9b62d1457..4392fe5e1 100644
--- a/example/generator/odp_generator.c
+++ b/example/generator/odp_generator.c
@@ -1492,7 +1492,7 @@ static void parse_args(int argc, char *argv[], appl_args_t *appl_args)
static const char *shortopts = "+I:a:b:s:d:p:i:m:n:t:w:c:x:he:f:yr:z";
/* let helper collect its own arguments (e.g. --odph_proc) */
- odph_parse_options(argc, argv, shortopts, longopts);
+ argc = odph_parse_options(argc, argv);
appl_args->mode = -1; /* Invalid, must be changed by parsing */
appl_args->number = -1;
@@ -1506,8 +1506,6 @@ static void parse_args(int argc, char *argv[], appl_args_t *appl_args)
appl_args->csum = 0;
appl_args->sched = 0;
- opterr = 0; /* do not issue errors on helper options */
-
while (1) {
opt = getopt_long(argc, argv, shortopts, longopts, &long_index);
if (opt == -1)
diff --git a/example/ipsec/odp_ipsec.c b/example/ipsec/odp_ipsec.c
index 9f7efcaa2..05001a5eb 100644
--- a/example/ipsec/odp_ipsec.c
+++ b/example/ipsec/odp_ipsec.c
@@ -1366,14 +1366,12 @@ static void parse_args(int argc, char *argv[], appl_args_t *appl_args)
static const char *shortopts = "+c:i:m:h:r:p:a:e:t:s:";
/* let helper collect its own arguments (e.g. --odph_proc) */
- odph_parse_options(argc, argv, shortopts, longopts);
+ argc = odph_parse_options(argc, argv);
printf("\nParsing command line options\n");
appl_args->mode = 0; /* turn off async crypto API by default */
- opterr = 0; /* do not issue errors on helper options */
-
while (!rc) {
opt = getopt_long(argc, argv, shortopts, longopts, &long_index);
diff --git a/example/ipsec_api/odp_ipsec.c b/example/ipsec_api/odp_ipsec.c
index c428927df..8cd4caa96 100644
--- a/example/ipsec_api/odp_ipsec.c
+++ b/example/ipsec_api/odp_ipsec.c
@@ -1059,12 +1059,10 @@ static void parse_args(int argc, char *argv[], appl_args_t *appl_args)
static const char *shortopts = "+c:i:h:lm:r:p:a:e:t:s:";
/* let helper collect its own arguments (e.g. --odph_proc) */
- odph_parse_options(argc, argv, shortopts, longopts);
+ argc = odph_parse_options(argc, argv);
printf("\nParsing command line options\n");
- opterr = 0; /* do not issue errors on helper options */
-
while (!rc) {
opt = getopt_long(argc, argv, shortopts, longopts, &long_index);
diff --git a/example/l2fwd_simple/l2fwd_simple_run.sh b/example/l2fwd_simple/l2fwd_simple_run.sh
index 6ebfb9803..9ed174f7a 100755
--- a/example/l2fwd_simple/l2fwd_simple_run.sh
+++ b/example/l2fwd_simple/l2fwd_simple_run.sh
@@ -32,6 +32,7 @@ if [ `stat -c %s pcapout.pcap` -ne `stat -c %s ${PCAP_IN}` ]; then
fi
rm -f pcapout.pcap
+unset ODP_PLATFORM_PARAMS
./odp_l2fwd_simple${EXEEXT} null:0 null:1 \
02:00:00:00:00:01 02:00:00:00:00:02 &
diff --git a/example/l2fwd_simple/odp_l2fwd_simple.c b/example/l2fwd_simple/odp_l2fwd_simple.c
index 36b76ee1c..8fca73072 100644
--- a/example/l2fwd_simple/odp_l2fwd_simple.c
+++ b/example/l2fwd_simple/odp_l2fwd_simple.c
@@ -143,31 +143,15 @@ int main(int argc, char **argv)
odph_odpthread_t thd[MAX_WORKERS];
odp_instance_t instance;
odph_odpthread_params_t thr_params;
- int opt;
- int long_index;
odph_ethaddr_t correct_src;
uint32_t mtu1, mtu2;
- static const struct option longopts[] = { {NULL, 0, NULL, 0} };
- static const char *shortopts = "";
-
/* let helper collect its own arguments (e.g. --odph_proc) */
- odph_parse_options(argc, argv, shortopts, longopts);
-
- /*
- * parse own options: currentely none, but this will move optind
- * to the first non-option argument. (in case there where helprt args)
- */
- opterr = 0; /* do not issue errors on helper options */
- while (1) {
- opt = getopt_long(argc, argv, shortopts, longopts, &long_index);
- if (-1 == opt)
- break; /* No more options */
- }
+ argc = odph_parse_options(argc, argv);
- if (argc != optind + 4 ||
- odph_eth_addr_parse(&global.dst, argv[optind + 2]) != 0 ||
- odph_eth_addr_parse(&global.src, argv[optind + 3]) != 0) {
+ if (argc != 5 ||
+ odph_eth_addr_parse(&global.dst, argv[3]) != 0 ||
+ odph_eth_addr_parse(&global.src, argv[4]) != 0) {
printf("Usage: odp_l2fwd_simple eth0 eth1 01:02:03:04:05:06"
" 07:08:09:0a:0b:0c\n");
printf("Where eth0 and eth1 are the used interfaces"
@@ -201,10 +185,8 @@ int main(int argc, char **argv)
exit(1);
}
- global.if0 = create_pktio(argv[optind], pool, &global.if0in,
- &global.if0out);
- global.if1 = create_pktio(argv[optind + 1], pool, &global.if1in,
- &global.if1out);
+ global.if0 = create_pktio(argv[1], pool, &global.if0in, &global.if0out);
+ global.if1 = create_pktio(argv[2], pool, &global.if1in, &global.if1out);
/* Do some operations to increase code coverage in tests */
if (odp_pktio_mac_addr(global.if0, &correct_src, sizeof(correct_src))
diff --git a/example/packet/odp_pktio.c b/example/packet/odp_pktio.c
index caf82b7b2..fcce92b10 100644
--- a/example/packet/odp_pktio.c
+++ b/example/packet/odp_pktio.c
@@ -570,13 +570,11 @@ static void parse_args(int argc, char *argv[], appl_args_t *appl_args)
static const char *shortopts = "+c:i:+m:t:h";
/* let helper collect its own arguments (e.g. --odph_proc) */
- odph_parse_options(argc, argv, shortopts, longopts);
+ argc = odph_parse_options(argc, argv);
appl_args->mode = APPL_MODE_PKT_SCHED;
appl_args->time = 0; /**< loop forever */
- opterr = 0; /* do not issue errors on helper options */
-
while (1) {
opt = getopt_long(argc, argv, shortopts, longopts, &long_index);
diff --git a/example/switch/odp_switch.c b/example/switch/odp_switch.c
index cc28eb6ca..26fcbbccc 100644
--- a/example/switch/odp_switch.c
+++ b/example/switch/odp_switch.c
@@ -760,13 +760,11 @@ static void parse_args(int argc, char *argv[], appl_args_t *appl_args)
static const char *shortopts = "+c:+t:+a:i:h";
/* let helper collect its own arguments (e.g. --odph_proc) */
- odph_parse_options(argc, argv, shortopts, longopts);
+ argc = odph_parse_options(argc, argv);
appl_args->time = 0; /* loop forever if time to run is 0 */
appl_args->accuracy = 10; /* get and print pps stats second */
- opterr = 0; /* do not issue errors on helper options */
-
while (1) {
opt = getopt_long(argc, argv, shortopts, longopts, &long_index);
diff --git a/example/time/time_global_test.c b/example/time/time_global_test.c
index a879745d3..317f9a270 100644
--- a/example/time/time_global_test.c
+++ b/example/time/time_global_test.c
@@ -259,7 +259,7 @@ int main(int argc, char *argv[])
odph_odpthread_params_t thr_params;
/* let helper collect its own arguments (e.g. --odph_proc) */
- odph_parse_options(argc, argv, NULL, NULL);
+ argc = odph_parse_options(argc, argv);
printf("\nODP global time test starts\n");
diff --git a/example/timer/odp_timer_test.c b/example/timer/odp_timer_test.c
index 1b0645a84..45eea7921 100644
--- a/example/timer/odp_timer_test.c
+++ b/example/timer/odp_timer_test.c
@@ -275,7 +275,7 @@ static void parse_args(int argc, char *argv[], test_args_t *args)
static const char *shortopts = "+c:r:m:x:p:t:h";
/* let helper collect its own arguments (e.g. --odph_proc) */
- odph_parse_options(argc, argv, shortopts, longopts);
+ argc = odph_parse_options(argc, argv);
/* defaults */
odp_timer_capability(ODP_CLOCK_CPU, &timer_capa);
@@ -289,8 +289,6 @@ static void parse_args(int argc, char *argv[], test_args_t *args)
args->period_us = 1000000;
args->tmo_count = 30;
- opterr = 0; /* do not issue errors on helper options */
-
while (1) {
opt = getopt_long(argc, argv, shortopts, longopts, &long_index);
diff --git a/helper/include/odp/helper/threads.h b/helper/include/odp/helper/threads.h
index ed7d7f39a..9d03c7192 100644
--- a/helper/include/odp/helper/threads.h
+++ b/helper/include/odp/helper/threads.h
@@ -146,74 +146,19 @@ int odph_odpthread_setaffinity(const int cpu);
int odph_odpthread_getaffinity(void);
/**
- * Merge getopt options
- *
- * Given two sets of getopt options (each containing possibly both short
- * options -a string- and long options -a option array-) this function
- * return a single set (i.e. a string for short and an array for long)
- * being the concatenation of the two given sets.
- * Due to the fact that the size of these arrays is unknown at compilation
- * time, this function actually mallocs the the resulting arrays.
- * The fourth and fith parameters are actually pointers where these malloc'ed
- * areas are returned.
- * This means that the caller of this function has to free the two returned
- * areas!
- *
- * @param shortopts1 first set of short options (a string)
- * @param shortopts2 second set of short options (a string)
- * @param longopts1 first set of long options (a getopt option array)
- * @param longopts2 second set of long options (a getopt option array)
- * @param shortopts a pointer where the address of the short options list
- * (a string) is returned. It contains the concatenation of
- * the two given short option strings.
- * @param longopts a pointer where the address of the long options list
- * (a getopt option array) is returned.
- * It contains the concatenation of the two given long
- * option arrays.
- * if any of shortopts1, shortopts2, longopts1, longopts2 is NULL, the
- * corresponding list as assumed to be empty.
- * if any of shortopts, longopts is NULL, the corresponding malloc is not
- * performed.
- *
- * @return On success: 0 : both shortopts and longopts are returned (assuming
- * the given pointer where not null), possibly
- * pointing to an empty string or an empty option array.
- * On success, the caller is due to free these areas.
- * On failure: -1: Nothing is malloc'ed.
- */
-int odph_merge_getopt_options(const char *shortopts1,
- const char *shortopts2,
- const struct option *longopts1,
- const struct option *longopts2,
- char **shortopts,
- struct option **longopts);
-
-/**
* Parse linux helper options
*
- * Parse the command line options. Pick up options meant for the helper itself.
- * If the caller is also having a set of option to parse, it should include
- * their description here (shortopts desribes the short options and longopts
- * describes the long options, as for getopt_long()).
- * This function will issue errors on unknown arguments, so callers failing
- * to pass their own command line options description here will see their
- * options rejected.
- * (the caller wants to set opterr to zero when parsing its own stuff
- * with getopts to avoid reacting on helper's options).
- *
- * @param argc argument count
- * @param argv argument values
- * @param caller_shortopts caller's set of short options (string). or NULL.
- * @param caller_longopts caller's set of long options (getopt option array).
- * or NULL.
- *
- * @return On success: 0
- * On failure: -1 failure occurs if a value passed for a helper
- * option is invalid, or on meeting unknown options.
+ * Parse the command line options. Pick up (--odph_ prefixed) options meant for
+ * the helper itself. When helper options are found, those are removed from
+ * argv[] and remaining options are packed to the beginning of the array.
+ *
+ * @param argc Argument count
+ * @param argv Argument vector
+ *
+ * @return New argument count. Original argument count decremented by
+ * the number of removed helper options.
*/
-int odph_parse_options(int argc, char *argv[],
- const char *caller_shortopts,
- const struct option *caller_longopts);
+int odph_parse_options(int argc, char *argv[]);
/**
* @}
diff --git a/helper/test/odpthreads.c b/helper/test/odpthreads.c
index aa61e6352..ad48ec2d5 100644
--- a/helper/test/odpthreads.c
+++ b/helper/test/odpthreads.c
@@ -73,7 +73,7 @@ int main(int argc, char *argv[])
char cpumaskstr[ODP_CPUMASK_STR_SIZE];
/* let helper collect its own arguments (e.g. --odph_proc) */
- odph_parse_options(argc, argv, NULL, NULL);
+ argc = odph_parse_options(argc, argv);
if (odp_init_global(&odp_instance, NULL, NULL)) {
ODPH_ERR("Error: ODP global init failed.\n");
diff --git a/helper/threads.c b/helper/threads.c
index f9216c7ed..86d6bf7be 100644
--- a/helper/threads.c
+++ b/helper/threads.c
@@ -330,129 +330,26 @@ int odph_odpthread_getaffinity(void)
return -1;
}
-/*
- * return the number of elements in an array of getopt options, excluding the
- * terminating {0,0,0,0}
- */
-static int get_getopt_options_length(const struct option *longopts)
+int odph_parse_options(int argc, char *argv[])
{
- int l = 0;
-
- if (!longopts)
- return 0;
-
- while (longopts[l].name)
- l++;
-
- return l;
-}
-
-/* Merge getopt options */
-int odph_merge_getopt_options(const char *shortopts1,
- const char *shortopts2,
- const struct option *longopts1,
- const struct option *longopts2,
- char **shortopts,
- struct option **longopts)
-{
- int shortopts1_len;
- int shortopts2_len;
- int longopts1_len;
- int longopts2_len;
- int index;
- int res_index = 0;
- struct option termination = {0, 0, 0, 0};
-
- /* merge short options: */
- if (shortopts) {
- shortopts1_len = (shortopts1) ? strlen(shortopts1) : 0;
- shortopts2_len = (shortopts2) ? strlen(shortopts2) : 0;
- *shortopts = malloc(shortopts1_len + shortopts2_len + 1);
- if (!*shortopts)
- return -1;
-
- (*shortopts)[0] = 0;
-
- if (shortopts1)
- strcpy((*shortopts), shortopts1);
- if (shortopts2)
- strcat((*shortopts), shortopts2);
- }
-
- /* merge long options */
- if (!longopts)
- return 0;
-
- longopts1_len = get_getopt_options_length(longopts1);
- longopts2_len = get_getopt_options_length(longopts2);
- *longopts = malloc(sizeof(struct option) *
- (longopts1_len + longopts2_len + 1));
- if (!*longopts) {
- if (shortopts)
- free(*shortopts);
- return -1;
- }
+ int i, j;
- for (index = 0; (longopts1) && (longopts1[index].name); index++)
- (*longopts)[res_index++] = longopts1[index];
+ helper_options.proc = 0;
- for (index = 0; (longopts2) && (longopts2[index].name); index++)
- (*longopts)[res_index++] = longopts2[index];
+ /* Find and remove option */
+ for (i = 0; i < argc;) {
+ if (strcmp(argv[i], "--odph_proc") == 0) {
+ helper_options.proc = 1;
- (*longopts)[res_index] = termination;
+ for (j = i; j < argc - 1; j++)
+ argv[j] = argv[j + 1];
- return 0;
-}
-
-/*
- * Parse command line options to extract options affecting helpers.
- */
-int odph_parse_options(int argc, char *argv[],
- const char *caller_shortopts,
- const struct option *caller_longopts)
-{
- int c;
- char *shortopts;
- struct option *longopts;
- int res = 0;
-
- static struct option helper_long_options[] = {
- /* These options set a flag. */
- {"odph_proc", no_argument, &helper_options.proc, 1},
- {0, 0, 0, 0}
- };
-
- static const char *helper_short_options = "";
-
- /* defaults: */
- helper_options.proc = false;
-
- /* merge caller's command line options descriptions with helper's: */
- if (odph_merge_getopt_options(caller_shortopts, helper_short_options,
- caller_longopts, helper_long_options,
- &shortopts, &longopts) < 0)
- return -1;
-
- while (1) {
- /* getopt_long stores the option index here. */
- int option_index = 0;
-
- c = getopt_long (argc, argv,
- shortopts, longopts, &option_index);
-
- /* Detect the end of the options. */
- if (c == -1)
- break;
+ argc--;
+ continue;
+ }
- /* check for unknown options or missing arguments */
- if (c == '?' || c == ':')
- res = -1;
+ i++;
}
- optind = 0; /* caller expects this to be zero if it parses too*/
-
- free(shortopts);
- free(longopts);
-
- return res;
+ return argc;
}
diff --git a/platform/linux-dpdk/odp_packet_dpdk.c b/platform/linux-dpdk/odp_packet_dpdk.c
index eae2da1dc..5076fa222 100644
--- a/platform/linux-dpdk/odp_packet_dpdk.c
+++ b/platform/linux-dpdk/odp_packet_dpdk.c
@@ -753,7 +753,7 @@ static int recv_pkt_dpdk(pktio_entry_t *pktio_entry, int index,
ret = cls_classify_packet(pktio_entry, pkt_addr,
odp_packet_len(pkt_table[i]),
odp_packet_len(pkt_table[i]),
- &new_pool, &parsed_hdr);
+ &new_pool, &parsed_hdr, true);
if (ret) {
failed++;
odp_packet_free(pkt_table[i]);
diff --git a/platform/linux-generic/Makefile.am b/platform/linux-generic/Makefile.am
index f9e99afd6..b904877cd 100644
--- a/platform/linux-generic/Makefile.am
+++ b/platform/linux-generic/Makefile.am
@@ -201,6 +201,7 @@ __LIB__libodp_linux_la_SOURCES = \
odp_version.c \
odp_weak.c \
pktio/dpdk.c \
+ pktio/dpdk_parse.c \
pktio/ethtool.c \
pktio/io_ops.c \
pktio/ipc.c \
diff --git a/platform/linux-generic/include/odp_classification_internal.h b/platform/linux-generic/include/odp_classification_internal.h
index 47f80dc25..84d605e6b 100644
--- a/platform/linux-generic/include/odp_classification_internal.h
+++ b/platform/linux-generic/include/odp_classification_internal.h
@@ -39,7 +39,7 @@ selects destination queue and packet pool based on selected PMR and CoS.
**/
int cls_classify_packet(pktio_entry_t *entry, const uint8_t *base,
uint16_t pkt_len, uint32_t seg_len, odp_pool_t *pool,
- odp_packet_hdr_t *pkt_hdr);
+ odp_packet_hdr_t *pkt_hdr, odp_bool_t parse);
/**
Packet IO classifier init
diff --git a/platform/linux-generic/include/odp_packet_dpdk.h b/platform/linux-generic/include/odp_packet_dpdk.h
index 7600b57e7..020c2b976 100644
--- a/platform/linux-generic/include/odp_packet_dpdk.h
+++ b/platform/linux-generic/include/odp_packet_dpdk.h
@@ -72,4 +72,24 @@ typedef struct ODP_ALIGNED_CACHE {
dpdk_opt_t opt;
} pkt_dpdk_t;
+/** Packet parser using DPDK interface */
+int dpdk_packet_parse_common(packet_parser_t *pkt_hdr,
+ const uint8_t *ptr,
+ uint32_t pkt_len,
+ uint32_t seg_len,
+ struct rte_mbuf *mbuf,
+ int layer,
+ odp_pktin_config_opt_t pktin_cfg);
+
+static inline int dpdk_packet_parse_layer(odp_packet_hdr_t *pkt_hdr,
+ struct rte_mbuf *mbuf,
+ odp_pktio_parser_layer_t layer,
+ odp_pktin_config_opt_t pktin_cfg)
+{
+ uint32_t seg_len = pkt_hdr->buf_hdr.seg[0].len;
+ void *base = pkt_hdr->buf_hdr.seg[0].data;
+
+ return dpdk_packet_parse_common(&pkt_hdr->p, base, pkt_hdr->frame_len,
+ seg_len, mbuf, layer, pktin_cfg);
+}
#endif
diff --git a/platform/linux-generic/odp_classification.c b/platform/linux-generic/odp_classification.c
index 14720924c..46fcf67ee 100644
--- a/platform/linux-generic/odp_classification.c
+++ b/platform/linux-generic/odp_classification.c
@@ -987,17 +987,19 @@ static uint32_t packet_rss_hash(odp_packet_hdr_t *pkt_hdr,
*/
int cls_classify_packet(pktio_entry_t *entry, const uint8_t *base,
uint16_t pkt_len, uint32_t seg_len, odp_pool_t *pool,
- odp_packet_hdr_t *pkt_hdr)
+ odp_packet_hdr_t *pkt_hdr, odp_bool_t parse)
{
cos_t *cos;
uint32_t tbl_index;
uint32_t hash;
- packet_parse_reset(pkt_hdr);
- packet_set_len(pkt_hdr, pkt_len);
+ if (parse) {
+ packet_parse_reset(pkt_hdr);
+ packet_set_len(pkt_hdr, pkt_len);
- packet_parse_common(&pkt_hdr->p, base, pkt_len, seg_len,
- ODP_PROTO_LAYER_ALL);
+ packet_parse_common(&pkt_hdr->p, base, pkt_len, seg_len,
+ ODP_PROTO_LAYER_ALL);
+ }
cos = cls_select_cos(entry, base, pkt_hdr);
if (cos == NULL)
diff --git a/platform/linux-generic/pktio/dpdk.c b/platform/linux-generic/pktio/dpdk.c
index 14d59d8e0..206a6a458 100644
--- a/platform/linux-generic/pktio/dpdk.c
+++ b/platform/linux-generic/pktio/dpdk.c
@@ -418,74 +418,6 @@ static struct rte_mempool_ops ops_stack = {
MEMPOOL_REGISTER_OPS(ops_stack);
-#define IP4_CSUM_RESULT(m) (m->ol_flags & PKT_RX_IP_CKSUM_MASK)
-#define L4_CSUM_RESULT(m) (m->ol_flags & PKT_RX_L4_CKSUM_MASK)
-#define HAS_L4_PROTO(m, proto) ((m->packet_type & RTE_PTYPE_L4_MASK) == proto)
-#define UDP4_CSUM(_p) (((_odp_udphdr_t *)_odp_packet_l4_ptr(_p, NULL))->chksum)
-
-#define PKTIN_CSUM_BITS 0x1C
-
-static inline int pkt_set_ol_rx(odp_pktin_config_opt_t *pktin_cfg,
- odp_packet_hdr_t *pkt_hdr,
- struct rte_mbuf *mbuf)
-{
- uint64_t packet_csum_result;
-
- if (pktin_cfg->bit.ipv4_chksum &&
- RTE_ETH_IS_IPV4_HDR(mbuf->packet_type)) {
- packet_csum_result = IP4_CSUM_RESULT(mbuf);
-
- if (packet_csum_result == PKT_RX_IP_CKSUM_GOOD) {
- pkt_hdr->p.input_flags.l3_chksum_done = 1;
- } else if (packet_csum_result != PKT_RX_IP_CKSUM_UNKNOWN) {
- if (pktin_cfg->bit.drop_ipv4_err)
- return -1;
-
- pkt_hdr->p.input_flags.l3_chksum_done = 1;
- pkt_hdr->p.flags.ip_err = 1;
- pkt_hdr->p.flags.l3_chksum_err = 1;
- }
- }
-
- if (pktin_cfg->bit.udp_chksum &&
- HAS_L4_PROTO(mbuf, RTE_PTYPE_L4_UDP)) {
- packet_csum_result = L4_CSUM_RESULT(mbuf);
-
- if (packet_csum_result == PKT_RX_L4_CKSUM_GOOD) {
- pkt_hdr->p.input_flags.l4_chksum_done = 1;
- } else if (packet_csum_result != PKT_RX_L4_CKSUM_UNKNOWN) {
- if (pkt_hdr->p.input_flags.ipv4 &&
- pkt_hdr->p.input_flags.udp &&
- !UDP4_CSUM(packet_handle(pkt_hdr))) {
- pkt_hdr->p.input_flags.l4_chksum_done = 1;
- return 0;
- }
- if (pktin_cfg->bit.drop_udp_err)
- return -1;
-
- pkt_hdr->p.input_flags.l4_chksum_done = 1;
- pkt_hdr->p.flags.udp_err = 1;
- pkt_hdr->p.flags.l4_chksum_err = 1;
- }
- } else if (pktin_cfg->bit.tcp_chksum &&
- HAS_L4_PROTO(mbuf, RTE_PTYPE_L4_TCP)) {
- packet_csum_result = L4_CSUM_RESULT(mbuf);
-
- if (packet_csum_result == PKT_RX_L4_CKSUM_GOOD) {
- pkt_hdr->p.input_flags.l4_chksum_done = 1;
- } else if (packet_csum_result != PKT_RX_L4_CKSUM_UNKNOWN) {
- if (pktin_cfg->bit.drop_tcp_err)
- return -1;
-
- pkt_hdr->p.input_flags.l4_chksum_done = 1;
- pkt_hdr->p.flags.tcp_err = 1;
- pkt_hdr->p.flags.l4_chksum_err = 1;
- }
- }
-
- return 0;
-}
-
static inline int mbuf_to_pkt(pktio_entry_t *pktio_entry,
odp_packet_t pkt_table[],
struct rte_mbuf *mbuf_table[],
@@ -500,7 +432,7 @@ static inline int mbuf_to_pkt(pktio_entry_t *pktio_entry,
int nb_pkts = 0;
int alloc_len, num;
odp_pool_t pool = pktio_entry->s.pkt_dpdk.pool;
- odp_pktin_config_opt_t *pktin_cfg = &pktio_entry->s.config.pktin;
+ odp_pktin_config_opt_t pktin_cfg = pktio_entry->s.config.pktin;
odp_proto_layer_t parse_layer = pktio_entry->s.config.parser.layer;
odp_pktio_t input = pktio_entry->s.handle;
@@ -530,10 +462,20 @@ static inline int mbuf_to_pkt(pktio_entry_t *pktio_entry,
pkt_len = rte_pktmbuf_pkt_len(mbuf);
if (pktio_cls_enabled(pktio_entry)) {
+ packet_parse_reset(&parsed_hdr);
+ packet_set_len(&parsed_hdr, pkt_len);
+ if (dpdk_packet_parse_common(&parsed_hdr.p, data,
+ pkt_len, pkt_len, mbuf,
+ ODP_PROTO_LAYER_ALL,
+ pktin_cfg)) {
+ odp_packet_free(pkt_table[i]);
+ rte_pktmbuf_free(mbuf);
+ continue;
+ }
if (cls_classify_packet(pktio_entry,
(const uint8_t *)data,
pkt_len, pkt_len, &pool,
- &parsed_hdr))
+ &parsed_hdr, false))
goto fail;
}
@@ -549,21 +491,18 @@ static inline int mbuf_to_pkt(pktio_entry_t *pktio_entry,
if (pktio_cls_enabled(pktio_entry))
copy_packet_cls_metadata(&parsed_hdr, pkt_hdr);
else if (parse_layer != ODP_PROTO_LAYER_NONE)
- packet_parse_layer(pkt_hdr, parse_layer);
+ if (dpdk_packet_parse_layer(pkt_hdr, mbuf, parse_layer,
+ pktin_cfg)) {
+ odp_packet_free(pkt);
+ rte_pktmbuf_free(mbuf);
+ continue;
+ }
if (mbuf->ol_flags & PKT_RX_RSS_HASH)
packet_set_flow_hash(pkt_hdr, mbuf->hash.rss);
packet_set_ts(pkt_hdr, ts);
- if (pktin_cfg->all_bits & PKTIN_CSUM_BITS) {
- if (pkt_set_ol_rx(pktin_cfg, pkt_hdr, mbuf)) {
- odp_packet_free(pkt);
- rte_pktmbuf_free(mbuf);
- continue;
- }
- }
-
pkt_table[nb_pkts++] = pkt;
rte_pktmbuf_free(mbuf);
@@ -752,7 +691,7 @@ static inline int mbuf_to_pkt_zero(pktio_entry_t *pktio_entry,
int i;
int nb_pkts = 0;
odp_pool_t pool = pktio_entry->s.pkt_dpdk.pool;
- odp_pktin_config_opt_t *pktin_cfg = &pktio_entry->s.config.pktin;
+ odp_pktin_config_opt_t pktin_cfg = pktio_entry->s.config.pktin;
odp_proto_layer_t parse_layer = pktio_entry->s.config.parser.layer;
odp_pktio_t input = pktio_entry->s.handle;
@@ -775,13 +714,23 @@ static inline int mbuf_to_pkt_zero(pktio_entry_t *pktio_entry,
pkt_hdr = packet_hdr(pkt);
if (pktio_cls_enabled(pktio_entry)) {
+ packet_parse_reset(&parsed_hdr);
+ packet_set_len(&parsed_hdr, pkt_len);
+ if (dpdk_packet_parse_common(&parsed_hdr.p, data,
+ pkt_len, pkt_len, mbuf,
+ ODP_PROTO_LAYER_ALL,
+ pktin_cfg)) {
+ rte_pktmbuf_free(mbuf);
+ continue;
+ }
if (cls_classify_packet(pktio_entry,
(const uint8_t *)data,
pkt_len, pkt_len, &pool,
- &parsed_hdr))
+ &parsed_hdr, false)) {
ODP_ERR("Unable to classify packet\n");
rte_pktmbuf_free(mbuf);
continue;
+ }
}
/* Init buffer segments. Currently, only single segment packets
@@ -794,20 +743,17 @@ static inline int mbuf_to_pkt_zero(pktio_entry_t *pktio_entry,
if (pktio_cls_enabled(pktio_entry))
copy_packet_cls_metadata(&parsed_hdr, pkt_hdr);
else if (parse_layer != ODP_PROTO_LAYER_NONE)
- packet_parse_layer(pkt_hdr, parse_layer);
+ if (dpdk_packet_parse_layer(pkt_hdr, mbuf, parse_layer,
+ pktin_cfg)) {
+ rte_pktmbuf_free(mbuf);
+ continue;
+ }
if (mbuf->ol_flags & PKT_RX_RSS_HASH)
packet_set_flow_hash(pkt_hdr, mbuf->hash.rss);
packet_set_ts(pkt_hdr, ts);
- if (pktin_cfg->all_bits & PKTIN_CSUM_BITS) {
- if (pkt_set_ol_rx(pktin_cfg, pkt_hdr, mbuf)) {
- rte_pktmbuf_free(mbuf);
- continue;
- }
- }
-
pkt_table[nb_pkts++] = pkt;
}
diff --git a/platform/linux-generic/pktio/dpdk_parse.c b/platform/linux-generic/pktio/dpdk_parse.c
new file mode 100644
index 000000000..155c68326
--- /dev/null
+++ b/platform/linux-generic/pktio/dpdk_parse.c
@@ -0,0 +1,492 @@
+/* Copyright (c) 2018, Linaro Limited
+ * All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "config.h"
+
+#ifdef ODP_PKTIO_DPDK
+
+#include <odp_packet_io_internal.h>
+#include <odp_packet_dpdk.h>
+#include <odp/api/byteorder.h>
+#include <odp/api/plat/byteorder_inlines.h>
+
+#include <protocols/eth.h>
+#include <protocols/udp.h>
+#include <protocols/tcp.h>
+
+#include <rte_config.h>
+#include <rte_mbuf.h>
+
+#define IP4_CSUM_RESULT(ol_flags) (ol_flags & PKT_RX_IP_CKSUM_MASK)
+#define L4_CSUM_RESULT(ol_flags) (ol_flags & PKT_RX_L4_CKSUM_MASK)
+
+/** Parser helper function for Ethernet packets */
+static inline uint16_t dpdk_parse_eth(packet_parser_t *prs,
+ const uint8_t **parseptr,
+ uint32_t *offset, uint32_t frame_len,
+ uint32_t mbuf_packet_type)
+{
+ uint16_t ethtype;
+ const _odp_ethhdr_t *eth;
+ uint16_t macaddr0, macaddr2, macaddr4;
+ const _odp_vlanhdr_t *vlan;
+ _odp_packet_input_flags_t input_flags;
+ uint32_t l2_packet_type;
+
+ input_flags.all = 0;
+ input_flags.l2 = 1;
+ input_flags.eth = 1;
+
+ eth = (const _odp_ethhdr_t *)*parseptr;
+
+ /* Detect jumbo frames */
+ if (odp_unlikely(frame_len > _ODP_ETH_LEN_MAX))
+ input_flags.jumbo = 1;
+
+ /* Handle Ethernet broadcast/multicast addresses */
+ macaddr0 = _odp_be_to_cpu_16(*((const uint16_t *)(const void *)eth));
+ if (odp_unlikely((macaddr0 & 0x0100) == 0x0100))
+ input_flags.eth_mcast = 1;
+
+ if (odp_unlikely(macaddr0 == 0xffff)) {
+ macaddr2 =
+ _odp_be_to_cpu_16(*((const uint16_t *)
+ (const void *)eth + 1));
+ macaddr4 =
+ _odp_be_to_cpu_16(*((const uint16_t *)
+ (const void *)eth + 2));
+
+ if ((macaddr2 == 0xffff) && (macaddr4 == 0xffff))
+ input_flags.eth_bcast = 1;
+ }
+
+ /* Get Ethertype */
+ l2_packet_type = mbuf_packet_type & RTE_PTYPE_L2_MASK;
+ switch (l2_packet_type) {
+ case RTE_PTYPE_L2_ETHER:
+ if (RTE_ETH_IS_IPV4_HDR(mbuf_packet_type))
+ ethtype = _ODP_ETHTYPE_IPV4;
+ else if (RTE_ETH_IS_IPV6_HDR(mbuf_packet_type))
+ ethtype = _ODP_ETHTYPE_IPV6;
+ else
+ ethtype = _odp_be_to_cpu_16(eth->type);
+ break;
+ case RTE_PTYPE_L2_ETHER_VLAN:
+ ethtype = _ODP_ETHTYPE_VLAN;
+ break;
+ default:
+ ethtype = _odp_be_to_cpu_16(eth->type);
+ }
+
+ *offset += sizeof(*eth);
+ *parseptr += sizeof(*eth);
+
+ /* Check for SNAP vs. DIX */
+ if (odp_unlikely(ethtype < _ODP_ETH_LEN_MAX)) {
+ input_flags.snap = 1;
+ if (ethtype > frame_len - *offset) {
+ prs->flags.snap_len_err = 1;
+ ethtype = 0;
+ goto error;
+ }
+ ethtype = _odp_be_to_cpu_16(*((const uint16_t *)(uintptr_t)
+ (parseptr + 6)));
+ *offset += 8;
+ *parseptr += 8;
+ }
+
+ /* Parse the VLAN header(s), if present */
+ if (odp_unlikely(ethtype == _ODP_ETHTYPE_VLAN_OUTER)) {
+ input_flags.vlan_qinq = 1;
+ input_flags.vlan = 1;
+
+ vlan = (const _odp_vlanhdr_t *)*parseptr;
+ ethtype = _odp_be_to_cpu_16(vlan->type);
+ *offset += sizeof(_odp_vlanhdr_t);
+ *parseptr += sizeof(_odp_vlanhdr_t);
+ }
+
+ if (ethtype == _ODP_ETHTYPE_VLAN) {
+ input_flags.vlan = 1;
+ vlan = (const _odp_vlanhdr_t *)*parseptr;
+ ethtype = _odp_be_to_cpu_16(vlan->type);
+ *offset += sizeof(_odp_vlanhdr_t);
+ *parseptr += sizeof(_odp_vlanhdr_t);
+ }
+
+error:
+ prs->input_flags.all |= input_flags.all;
+
+ return ethtype;
+}
+
+/**
+ * Parser helper function for IPv4
+ */
+static inline uint8_t dpdk_parse_ipv4(packet_parser_t *prs,
+ const uint8_t **parseptr,
+ uint32_t *offset, uint32_t frame_len,
+ uint32_t mbuf_packet_type,
+ uint64_t mbuf_ol,
+ uint32_t do_csum)
+{
+ const _odp_ipv4hdr_t *ipv4 = (const _odp_ipv4hdr_t *)*parseptr;
+ uint32_t dstaddr = _odp_be_to_cpu_32(ipv4->dst_addr);
+ uint32_t l3_len = _odp_be_to_cpu_16(ipv4->tot_len);
+ uint8_t ver = _ODP_IPV4HDR_VER(ipv4->ver_ihl);
+ uint8_t ihl = _ODP_IPV4HDR_IHL(ipv4->ver_ihl);
+ uint32_t l4_packet_type = mbuf_packet_type & RTE_PTYPE_L4_MASK;
+ uint16_t frag_offset;
+ uint8_t proto;
+
+ if (odp_unlikely(ihl < _ODP_IPV4HDR_IHL_MIN ||
+ ver != 4 ||
+ (l3_len > frame_len - *offset))) {
+ prs->flags.ip_err = 1;
+ return 0;
+ }
+
+ *offset += ihl * 4;
+ *parseptr += ihl * 4;
+
+ if (do_csum) {
+ uint64_t packet_csum_result = IP4_CSUM_RESULT(mbuf_ol);
+
+ if (packet_csum_result == PKT_RX_IP_CKSUM_GOOD) {
+ prs->input_flags.l3_chksum_done = 1;
+ } else if (packet_csum_result != PKT_RX_IP_CKSUM_UNKNOWN) {
+ prs->input_flags.l3_chksum_done = 1;
+ prs->flags.ip_err = 1;
+ prs->flags.l3_chksum_err = 1;
+ }
+ }
+
+ if (odp_unlikely(ihl > _ODP_IPV4HDR_IHL_MIN))
+ prs->input_flags.ipopt = 1;
+
+ if (l4_packet_type == RTE_PTYPE_L4_UDP) {
+ proto = _ODP_IPPROTO_UDP;
+ } else if (l4_packet_type == RTE_PTYPE_L4_TCP) {
+ proto = _ODP_IPPROTO_TCP;
+ } else {
+ proto = ipv4->proto;
+ frag_offset = _odp_be_to_cpu_16(ipv4->frag_offset);
+
+ /* A packet is a fragment if:
+ * "more fragments" flag is set (all fragments except the last)
+ * OR
+ * "fragment offset" field is nonzero (all fragments except
+ * the first)
+ */
+ if (odp_unlikely(l4_packet_type == RTE_PTYPE_L4_FRAG ||
+ _ODP_IPV4HDR_IS_FRAGMENT(frag_offset)))
+ prs->input_flags.ipfrag = 1;
+ }
+
+ /**/
+ /* Handle IPv4 broadcast / multicast */
+ if (odp_unlikely(dstaddr == 0xffffffff))
+ prs->input_flags.ip_bcast = 1;
+
+ if (odp_unlikely((dstaddr >> 28) == 0xe))
+ prs->input_flags.ip_mcast = 1;
+
+ return proto;
+}
+
+static inline uint8_t dpdk_parse_ipv6(packet_parser_t *prs,
+ const uint8_t **parseptr,
+ uint32_t *offset, uint32_t frame_len,
+ uint32_t seg_len,
+ uint32_t mbuf_packet_type)
+{
+ const _odp_ipv6hdr_t *ipv6 = (const _odp_ipv6hdr_t *)*parseptr;
+ const _odp_ipv6hdr_ext_t *ipv6ext;
+ uint32_t dstaddr0 = _odp_be_to_cpu_32(ipv6->dst_addr.u8[0]);
+ uint32_t l3_len = _odp_be_to_cpu_16(ipv6->payload_len) +
+ _ODP_IPV6HDR_LEN;
+ uint32_t l4_packet_type = mbuf_packet_type & RTE_PTYPE_L4_MASK;
+
+ /* Basic sanity checks on IPv6 header */
+ if ((_odp_be_to_cpu_32(ipv6->ver_tc_flow) >> 28) != 6 ||
+ l3_len > frame_len - *offset) {
+ prs->flags.ip_err = 1;
+ return 0;
+ }
+
+ /* IPv6 broadcast / multicast flags */
+ prs->input_flags.ip_mcast = (dstaddr0 & 0xff000000) == 0xff000000;
+ prs->input_flags.ip_bcast = 0;
+
+ /* Skip past IPv6 header */
+ *offset += sizeof(_odp_ipv6hdr_t);
+ *parseptr += sizeof(_odp_ipv6hdr_t);
+
+ if (l4_packet_type == RTE_PTYPE_L4_UDP)
+ return _ODP_IPPROTO_UDP;
+ else if (l4_packet_type == RTE_PTYPE_L4_TCP)
+ return _ODP_IPPROTO_TCP;
+
+ /* Skip past any IPv6 extension headers */
+ if (ipv6->next_hdr == _ODP_IPPROTO_HOPOPTS ||
+ ipv6->next_hdr == _ODP_IPPROTO_ROUTE) {
+ prs->input_flags.ipopt = 1;
+
+ do {
+ ipv6ext = (const _odp_ipv6hdr_ext_t *)*parseptr;
+ uint16_t extlen = 8 + ipv6ext->ext_len * 8;
+
+ *offset += extlen;
+ *parseptr += extlen;
+ } while ((ipv6ext->next_hdr == _ODP_IPPROTO_HOPOPTS ||
+ ipv6ext->next_hdr == _ODP_IPPROTO_ROUTE) &&
+ *offset < seg_len);
+
+ if (*offset >= prs->l3_offset +
+ _odp_be_to_cpu_16(ipv6->payload_len)) {
+ prs->flags.ip_err = 1;
+ return 0;
+ }
+
+ if (ipv6ext->next_hdr == _ODP_IPPROTO_FRAG)
+ prs->input_flags.ipfrag = 1;
+
+ return ipv6ext->next_hdr;
+ }
+
+ if (odp_unlikely(ipv6->next_hdr == _ODP_IPPROTO_FRAG)) {
+ prs->input_flags.ipopt = 1;
+ prs->input_flags.ipfrag = 1;
+ }
+
+ return ipv6->next_hdr;
+}
+
+/**
+ * Parser helper function for TCP
+ */
+static inline void dpdk_parse_tcp(packet_parser_t *prs,
+ const uint8_t **parseptr,
+ uint64_t mbuf_ol,
+ uint32_t do_csum)
+{
+ const _odp_tcphdr_t *tcp = (const _odp_tcphdr_t *)*parseptr;
+ uint32_t len = tcp->hl * 4;
+
+ if (odp_unlikely(tcp->hl < sizeof(_odp_tcphdr_t) / sizeof(uint32_t)))
+ prs->flags.tcp_err = 1;
+
+ if (do_csum) {
+ uint64_t packet_csum_result = L4_CSUM_RESULT(mbuf_ol);
+
+ if (packet_csum_result == PKT_RX_L4_CKSUM_GOOD) {
+ prs->input_flags.l4_chksum_done = 1;
+ } else if (packet_csum_result != PKT_RX_L4_CKSUM_UNKNOWN) {
+ prs->input_flags.l4_chksum_done = 1;
+ prs->flags.tcp_err = 1;
+ prs->flags.l4_chksum_err = 1;
+ }
+ }
+
+ *parseptr += len;
+}
+
+/**
+ * Parser helper function for UDP
+ */
+static inline void dpdk_parse_udp(packet_parser_t *prs,
+ const uint8_t **parseptr,
+ uint64_t mbuf_ol,
+ uint32_t do_csum)
+{
+ const _odp_udphdr_t *udp = (const _odp_udphdr_t *)*parseptr;
+ uint32_t udplen = _odp_be_to_cpu_16(udp->length);
+ uint16_t ipsec_port = _odp_cpu_to_be_16(_ODP_UDP_IPSEC_PORT);
+
+ if (odp_unlikely(udplen < sizeof(_odp_udphdr_t)))
+ prs->flags.udp_err = 1;
+
+ if (do_csum) {
+ uint64_t packet_csum_result = L4_CSUM_RESULT(mbuf_ol);
+
+ if (packet_csum_result == PKT_RX_L4_CKSUM_GOOD) {
+ prs->input_flags.l4_chksum_done = 1;
+ } else if (packet_csum_result != PKT_RX_L4_CKSUM_UNKNOWN) {
+ if (prs->input_flags.ipv4 && !udp->chksum) {
+ prs->input_flags.l4_chksum_done = 1;
+ } else {
+ prs->input_flags.l4_chksum_done = 1;
+ prs->flags.udp_err = 1;
+ prs->flags.l4_chksum_err = 1;
+ }
+ }
+ }
+
+ if (odp_unlikely(ipsec_port == udp->dst_port && udplen > 4)) {
+ uint32_t val;
+
+ memcpy(&val, udp + 1, 4);
+ if (val != 0) {
+ prs->input_flags.ipsec = 1;
+ prs->input_flags.ipsec_udp = 1;
+ }
+ }
+
+ *parseptr += sizeof(_odp_udphdr_t);
+}
+
+static inline
+int dpdk_packet_parse_common_l3_l4(packet_parser_t *prs,
+ const uint8_t *parseptr,
+ uint32_t offset,
+ uint32_t frame_len, uint32_t seg_len,
+ int layer, uint16_t ethtype,
+ uint32_t mbuf_packet_type,
+ uint64_t mbuf_ol,
+ odp_pktin_config_opt_t pktin_cfg)
+{
+ uint8_t ip_proto;
+
+ prs->l3_offset = offset;
+
+ if (odp_unlikely(layer <= ODP_PROTO_LAYER_L2))
+ return 0;
+
+ /* Set l3 flag only for known ethtypes */
+ prs->input_flags.l3 = 1;
+
+ /* Parse Layer 3 headers */
+ switch (ethtype) {
+ case _ODP_ETHTYPE_IPV4:
+ prs->input_flags.ipv4 = 1;
+ ip_proto = dpdk_parse_ipv4(prs, &parseptr, &offset, frame_len,
+ mbuf_packet_type, mbuf_ol,
+ pktin_cfg.bit.ipv4_chksum);
+ prs->l4_offset = offset;
+ if (prs->flags.ip_err && pktin_cfg.bit.drop_ipv4_err)
+ return -1; /* drop */
+ break;
+
+ case _ODP_ETHTYPE_IPV6:
+ prs->input_flags.ipv6 = 1;
+ ip_proto = dpdk_parse_ipv6(prs, &parseptr, &offset, frame_len,
+ seg_len, mbuf_packet_type);
+ prs->l4_offset = offset;
+ if (prs->flags.ip_err && pktin_cfg.bit.drop_ipv6_err)
+ return -1; /* drop */
+ break;
+
+ case _ODP_ETHTYPE_ARP:
+ prs->input_flags.arp = 1;
+ ip_proto = 255; /* Reserved invalid by IANA */
+ break;
+
+ default:
+ prs->input_flags.l3 = 0;
+ ip_proto = 255; /* Reserved invalid by IANA */
+ }
+
+ if (layer == ODP_PROTO_LAYER_L3)
+ return 0;
+
+ /* Set l4 flag only for known ip_proto */
+ prs->input_flags.l4 = 1;
+
+ /* Parse Layer 4 headers */
+ switch (ip_proto) {
+ case _ODP_IPPROTO_ICMPV4:
+ /* Fall through */
+
+ case _ODP_IPPROTO_ICMPV6:
+ prs->input_flags.icmp = 1;
+ break;
+
+ case _ODP_IPPROTO_IPIP:
+ /* Do nothing */
+ break;
+
+ case _ODP_IPPROTO_TCP:
+ if (odp_unlikely(offset + _ODP_TCPHDR_LEN > seg_len))
+ return -1; /* drop */
+ prs->input_flags.tcp = 1;
+ dpdk_parse_tcp(prs, &parseptr, mbuf_ol,
+ pktin_cfg.bit.tcp_chksum);
+ if (prs->flags.tcp_err && pktin_cfg.bit.drop_tcp_err)
+ return -1; /* drop */
+ break;
+
+ case _ODP_IPPROTO_UDP:
+ if (odp_unlikely(offset + _ODP_UDPHDR_LEN > seg_len))
+ return -1; /* drop */
+ prs->input_flags.udp = 1;
+ dpdk_parse_udp(prs, &parseptr, mbuf_ol,
+ pktin_cfg.bit.udp_chksum);
+ if (prs->flags.udp_err && pktin_cfg.bit.drop_udp_err)
+ return -1; /* drop */
+ break;
+
+ case _ODP_IPPROTO_AH:
+ prs->input_flags.ipsec = 1;
+ prs->input_flags.ipsec_ah = 1;
+ break;
+
+ case _ODP_IPPROTO_ESP:
+ prs->input_flags.ipsec = 1;
+ prs->input_flags.ipsec_esp = 1;
+ break;
+
+ case _ODP_IPPROTO_SCTP:
+ prs->input_flags.sctp = 1;
+ break;
+
+ case _ODP_IPPROTO_NO_NEXT:
+ prs->input_flags.no_next_hdr = 1;
+ break;
+
+ default:
+ prs->input_flags.l4 = 0;
+ break;
+ }
+
+ return 0;
+}
+
+/**
+ * DPDK packet parser
+ */
+int dpdk_packet_parse_common(packet_parser_t *prs, const uint8_t *ptr,
+ uint32_t frame_len, uint32_t seg_len,
+ struct rte_mbuf *mbuf, int layer,
+ odp_pktin_config_opt_t pktin_cfg)
+{
+ uint32_t offset;
+ uint16_t ethtype;
+ const uint8_t *parseptr;
+ uint32_t mbuf_packet_type;
+ uint64_t mbuf_ol;
+
+ parseptr = ptr;
+ offset = 0;
+
+ if (odp_unlikely(layer == ODP_PROTO_LAYER_NONE))
+ return 0;
+
+ mbuf_packet_type = mbuf->packet_type;
+ mbuf_ol = mbuf->ol_flags;
+
+ /* Assume valid L2 header, no CRC/FCS check in SW */
+ prs->l2_offset = offset;
+
+ ethtype = dpdk_parse_eth(prs, &parseptr, &offset, frame_len,
+ mbuf_packet_type);
+
+ return dpdk_packet_parse_common_l3_l4(prs, parseptr, offset, frame_len,
+ seg_len, layer, ethtype,
+ mbuf_packet_type, mbuf_ol,
+ pktin_cfg);
+}
+
+#endif /* ODP_PKTIO_DPDK */
diff --git a/platform/linux-generic/pktio/loop.c b/platform/linux-generic/pktio/loop.c
index fc80e8019..779e4c62b 100644
--- a/platform/linux-generic/pktio/loop.c
+++ b/platform/linux-generic/pktio/loop.c
@@ -131,7 +131,7 @@ static int loopback_recv(pktio_entry_t *pktio_entry, int index ODP_UNUSED,
ret = cls_classify_packet(pktio_entry, pkt_addr,
pkt_len, seg_len,
- &new_pool, pkt_hdr);
+ &new_pool, pkt_hdr, true);
if (ret) {
failed++;
odp_packet_free(pkt);
diff --git a/platform/linux-generic/pktio/netmap.c b/platform/linux-generic/pktio/netmap.c
index 835d81ebb..567bc9f95 100644
--- a/platform/linux-generic/pktio/netmap.c
+++ b/platform/linux-generic/pktio/netmap.c
@@ -705,7 +705,7 @@ static inline int netmap_pkt_to_odp(pktio_entry_t *pktio_entry,
if (pktio_cls_enabled(pktio_entry)) {
if (cls_classify_packet(pktio_entry,
(const uint8_t *)slot.buf, len,
- len, &pool, &parsed_hdr))
+ len, &pool, &parsed_hdr, true))
goto fail;
}
diff --git a/platform/linux-generic/pktio/socket.c b/platform/linux-generic/pktio/socket.c
index f6f3288c2..8b7200e6f 100644
--- a/platform/linux-generic/pktio/socket.c
+++ b/platform/linux-generic/pktio/socket.c
@@ -655,7 +655,8 @@ static int sock_mmsg_recv(pktio_entry_t *pktio_entry, int index ODP_UNUSED,
seg_len = msgvec[i].msg_hdr.msg_iov->iov_len;
if (cls_classify_packet(pktio_entry, base, pkt_len,
- seg_len, &pool, pkt_hdr)) {
+ seg_len, &pool, pkt_hdr,
+ true)) {
ODP_ERR("cls_classify_packet failed");
odp_packet_free(pkt);
continue;
diff --git a/platform/linux-generic/pktio/socket_mmap.c b/platform/linux-generic/pktio/socket_mmap.c
index deaa6da15..847eb71ad 100644
--- a/platform/linux-generic/pktio/socket_mmap.c
+++ b/platform/linux-generic/pktio/socket_mmap.c
@@ -228,7 +228,8 @@ static inline unsigned pkt_mmap_v2_rx(pktio_entry_t *pktio_entry,
if (pktio_cls_enabled(pktio_entry)) {
if (cls_classify_packet(pktio_entry, pkt_buf, pkt_len,
- pkt_len, &pool, &parsed_hdr)) {
+ pkt_len, &pool, &parsed_hdr,
+ true)) {
mmap_rx_user_ready(ppd.raw); /* drop */
frame_num = next_frame_num;
continue;
diff --git a/platform/linux-generic/pktio/tap.c b/platform/linux-generic/pktio/tap.c
index 56f90b31b..af766e0de 100644
--- a/platform/linux-generic/pktio/tap.c
+++ b/platform/linux-generic/pktio/tap.c
@@ -264,7 +264,7 @@ static odp_packet_t pack_odp_pkt(pktio_entry_t *pktio_entry, const void *data,
if (pktio_cls_enabled(pktio_entry)) {
if (cls_classify_packet(pktio_entry, data, len, len,
&pktio_entry->s.pkt_tap.pool,
- &parsed_hdr)) {
+ &parsed_hdr, true)) {
return ODP_PACKET_INVALID;
}
}
diff --git a/platform/linux-generic/test/mmap_vlan_ins/mmap_vlan_ins.c b/platform/linux-generic/test/mmap_vlan_ins/mmap_vlan_ins.c
index 678978bee..cf3d6d932 100644
--- a/platform/linux-generic/test/mmap_vlan_ins/mmap_vlan_ins.c
+++ b/platform/linux-generic/test/mmap_vlan_ins/mmap_vlan_ins.c
@@ -137,36 +137,14 @@ int main(int argc, char **argv)
odph_odpthread_t thd[MAX_WORKERS];
odp_instance_t instance;
odph_odpthread_params_t thr_params;
- int opt;
- int long_index;
-
- static const struct option longopts[] = { {NULL, 0, NULL, 0} };
- static const char *shortopts = "";
/* let helper collect its own arguments (e.g. --odph_proc) */
- odph_parse_options(argc, argv, shortopts, longopts);
+ argc = odph_parse_options(argc, argv);
- /*
- * parse own options: currentely none, but this will move optind
- * to the first non-option argument. (in case there where helprt args)
- */
- opterr = 0; /* do not issue errors on helper options */
- while (1) {
- opt = getopt_long(argc, argv, shortopts, longopts, &long_index);
- if (-1 == opt)
- break; /* No more options */
- }
-
- if (argc != optind + 4 ||
- odph_eth_addr_parse(&global.dst, argv[optind + 2]) != 0 ||
- odph_eth_addr_parse(&global.src, argv[optind + 3]) != 0) {
- printf("Usage: odp_l2fwd_simple eth0 eth1 01:02:03:04:05:06"
- " 07:08:09:0a:0b:0c\n");
- printf("Where eth0 and eth1 are the used interfaces"
- " (must have 2 of them)\n");
- printf("And the hexadecimal numbers are destination MAC address"
- " and source MAC address\n");
- exit(1);
+ if (argc < 3) {
+ printf("Too few arguments (%i).\n"
+ "Two interface names needed as arguments.\n", argc);
+ exit(0);
}
if (odp_init_global(&instance, NULL, NULL)) {
@@ -193,10 +171,8 @@ int main(int argc, char **argv)
exit(1);
}
- global.if0 = create_pktio(argv[optind], pool, &global.if0in,
- &global.if0out);
- global.if1 = create_pktio(argv[optind + 1], pool, &global.if1in,
- &global.if1out);
+ global.if0 = create_pktio(argv[1], pool, &global.if0in, &global.if0out);
+ global.if1 = create_pktio(argv[2], pool, &global.if1in, &global.if1out);
odp_cpumask_default_worker(&cpumask, MAX_WORKERS);
diff --git a/test/common/odp_cunit_common.c b/test/common/odp_cunit_common.c
index 79c3df1ef..f7c9af43b 100644
--- a/test/common/odp_cunit_common.c
+++ b/test/common/odp_cunit_common.c
@@ -394,5 +394,6 @@ int odp_cunit_register(odp_suiteinfo_t testsuites[])
int odp_cunit_parse_options(int argc, char *argv[])
{
progname = argv[0];
- return odph_parse_options(argc, argv, NULL, NULL);
+ odph_parse_options(argc, argv);
+ return 0;
}
diff --git a/test/performance/odp_bench_packet.c b/test/performance/odp_bench_packet.c
index df41b41f4..b4f1905a9 100644
--- a/test/performance/odp_bench_packet.c
+++ b/test/performance/odp_bench_packet.c
@@ -1318,9 +1318,7 @@ static void parse_args(int argc, char *argv[], appl_args_t *appl_args)
static const char *shortopts = "b:i:h";
/* Let helper collect its own arguments (e.g. --odph_proc) */
- odph_parse_options(argc, argv, shortopts, longopts);
-
- opterr = 0; /* Do not issue errors on helper options */
+ argc = odph_parse_options(argc, argv);
appl_args->bench_idx = 0; /* Run all benchmarks */
appl_args->burst_size = TEST_DEF_BURST;
diff --git a/test/performance/odp_crypto.c b/test/performance/odp_crypto.c
index 0404aca25..61da80e8a 100644
--- a/test/performance/odp_crypto.c
+++ b/test/performance/odp_crypto.c
@@ -1197,7 +1197,7 @@ static void parse_args(int argc, char *argv[], crypto_args_t *cargs)
static const char *shortopts = "+a:c:df:hi:m:nl:spr";
/* let helper collect its own arguments (e.g. --odph_proc) */
- odph_parse_options(argc, argv, shortopts, longopts);
+ argc = odph_parse_options(argc, argv);
cargs->in_place = 0;
cargs->in_flight = 1;
@@ -1208,8 +1208,6 @@ static void parse_args(int argc, char *argv[], crypto_args_t *cargs)
cargs->reuse_packet = 0;
cargs->schedule = 0;
- opterr = 0; /* do not issue errors on helper options */
-
while (1) {
opt = getopt_long(argc, argv, shortopts, longopts, &long_index);
diff --git a/test/performance/odp_ipsec.c b/test/performance/odp_ipsec.c
index 587293dbe..551c021af 100644
--- a/test/performance/odp_ipsec.c
+++ b/test/performance/odp_ipsec.c
@@ -929,7 +929,7 @@ static void parse_args(int argc, char *argv[], ipsec_args_t *cargs)
static const char *shortopts = "+a:c:df:hi:m:nl:sptu";
/* let helper collect its own arguments (e.g. --odph_proc) */
- odph_parse_options(argc, argv, shortopts, longopts);
+ argc = odph_parse_options(argc, argv);
cargs->in_place = 0;
cargs->in_flight = 1;
@@ -940,8 +940,6 @@ static void parse_args(int argc, char *argv[], ipsec_args_t *cargs)
cargs->schedule = 0;
cargs->ah = 0;
- opterr = 0; /* do not issue errors on helper options */
-
while (1) {
opt = getopt_long(argc, argv, shortopts, longopts, &long_index);
diff --git a/test/performance/odp_l2fwd.c b/test/performance/odp_l2fwd.c
index 2859000d5..ff14ab2f8 100644
--- a/test/performance/odp_l2fwd.c
+++ b/test/performance/odp_l2fwd.c
@@ -1184,7 +1184,7 @@ static void parse_args(int argc, char *argv[], appl_args_t *appl_args)
static const char *shortopts = "+c:+t:+a:i:m:o:r:d:s:e:k:g:vh";
/* let helper collect its own arguments (e.g. --odph_proc) */
- odph_parse_options(argc, argv, shortopts, longopts);
+ argc = odph_parse_options(argc, argv);
appl_args->time = 0; /* loop forever if time to run is 0 */
appl_args->accuracy = 1; /* get and print pps stats second */
@@ -1195,8 +1195,6 @@ static void parse_args(int argc, char *argv[], appl_args_t *appl_args)
appl_args->verbose = 0;
appl_args->chksum = 0; /* don't use checksum offload by default */
- opterr = 0; /* do not issue errors on helper options */
-
while (1) {
opt = getopt_long(argc, argv, shortopts, longopts, &long_index);
diff --git a/test/performance/odp_pktio_ordered.c b/test/performance/odp_pktio_ordered.c
index 5647b1eb5..ec6c4faa3 100644
--- a/test/performance/odp_pktio_ordered.c
+++ b/test/performance/odp_pktio_ordered.c
@@ -868,7 +868,7 @@ static void parse_args(int argc, char *argv[], appl_args_t *appl_args)
static const char *shortopts = "+c:+t:+a:i:m:d:r:f:e:h";
/* let helper collect its own arguments (e.g. --odph_proc) */
- odph_parse_options(argc, argv, shortopts, longopts);
+ argc = odph_parse_options(argc, argv);
appl_args->time = 0; /* loop forever if time to run is 0 */
appl_args->accuracy = DEF_STATS_INT;
@@ -876,8 +876,6 @@ static void parse_args(int argc, char *argv[], appl_args_t *appl_args)
appl_args->num_flows = DEF_NUM_FLOWS;
appl_args->extra_rounds = DEF_EXTRA_ROUNDS;
- opterr = 0; /* do not issue errors on helper options */
-
while (1) {
opt = getopt_long(argc, argv, shortopts, longopts, &long_index);
diff --git a/test/performance/odp_pktio_perf.c b/test/performance/odp_pktio_perf.c
index 75f4abf24..2791856aa 100644
--- a/test/performance/odp_pktio_perf.c
+++ b/test/performance/odp_pktio_perf.c
@@ -961,7 +961,7 @@ static void parse_args(int argc, char *argv[], test_args_t *args)
static const char *shortopts = "+c:t:b:pR:l:r:i:d:vh";
/* let helper collect its own arguments (e.g. --odph_proc) */
- odph_parse_options(argc, argv, shortopts, longopts);
+ argc = odph_parse_options(argc, argv);
args->cpu_count = 0; /* all CPUs */
args->num_tx_workers = 0; /* defaults to cpu_count+1/2 */
@@ -973,8 +973,6 @@ static void parse_args(int argc, char *argv[], test_args_t *args)
args->schedule = 1;
args->verbose = 0;
- opterr = 0; /* do not issue errors on helper options */
-
while (1) {
opt = getopt_long(argc, argv, shortopts,
longopts, &long_index);
diff --git a/test/performance/odp_sched_latency.c b/test/performance/odp_sched_latency.c
index ca7201193..7e98db184 100644
--- a/test/performance/odp_sched_latency.c
+++ b/test/performance/odp_sched_latency.c
@@ -550,7 +550,7 @@ static void parse_args(int argc, char *argv[], test_args_t *args)
static const char *shortopts = "+c:s:l:t:m:n:o:p:rh";
/* Let helper collect its own arguments (e.g. --odph_proc) */
- odph_parse_options(argc, argv, shortopts, longopts);
+ argc = odph_parse_options(argc, argv);
args->sync_type = ODP_SCHED_SYNC_PARALLEL;
args->sample_per_prio = SAMPLE_EVENT_PER_PRIO;
@@ -561,7 +561,6 @@ static void parse_args(int argc, char *argv[], test_args_t *args)
args->prio[LO_PRIO].events_per_queue = EVENTS_PER_LO_PRIO_QUEUE;
args->prio[HI_PRIO].events_per_queue = EVENTS_PER_HI_PRIO_QUEUE;
- opterr = 0; /* Do not issue errors on helper options */
while (1) {
opt = getopt_long(argc, argv, shortopts, longopts, &long_index);
diff --git a/test/performance/odp_sched_pktio.c b/test/performance/odp_sched_pktio.c
index 46a08c925..109ae87e2 100644
--- a/test/performance/odp_sched_pktio.c
+++ b/test/performance/odp_sched_pktio.c
@@ -364,7 +364,7 @@ static int parse_options(int argc, char *argv[], test_options_t *test_options)
test_options->num_pktio_queue = 0;
/* let helper collect its own arguments (e.g. --odph_proc) */
- odph_parse_options(argc, argv, shortopts, longopts);
+ argc = odph_parse_options(argc, argv);
while (1) {
opt = getopt_long(argc, argv, shortopts, longopts, &long_index);
diff --git a/test/performance/odp_scheduling.c b/test/performance/odp_scheduling.c
index 6b7cff77c..8dd86c3c3 100644
--- a/test/performance/odp_scheduling.c
+++ b/test/performance/odp_scheduling.c
@@ -761,9 +761,8 @@ static void parse_args(int argc, char *argv[], test_args_t *args)
static const char *shortopts = "+c:fh";
/* let helper collect its own arguments (e.g. --odph_proc) */
- odph_parse_options(argc, argv, shortopts, longopts);
+ argc = odph_parse_options(argc, argv);
- opterr = 0; /* do not issue errors on helper options */
while (1) {
opt = getopt_long(argc, argv, shortopts, longopts, &long_index);