aboutsummaryrefslogtreecommitdiff
path: root/platform/linux-dpdk
diff options
context:
space:
mode:
authorZoltan Kiss <zoltan.kiss@linaro.org>2016-01-20 17:15:18 +0000
committerZoltan Kiss <zoltan.kiss@linaro.org>2016-01-25 14:54:48 +0000
commitc6aee2829bc5badf05ba6074f496a3b92bbd52f7 (patch)
tree4a49901861d3270267447a61afec570c6e584dd6 /platform/linux-dpdk
parentc986883f6184aa3f22ae28e0b7419ce751fd7bfc (diff)
linux-dpdk: packet_io: reuse linux-generic code and enable classification
This patch reuses odp_packet_io.c and pktio/loop.c from linux-generic's codebase, and plugs the DPDK specific pieces from odp_packet_dpdk.c into that framework. In order to do that the following steps were taken: - sync up odp_packet_io_internal.h: this file is nearly the same, except we use only loop and our DPDK specific parts - move DPDK specific functionality to odp_packet_dpdk.c, and use those functions in dpdk_pktio_ops. The old pktio code will be deleted in a separate patch - enable classification in Makefiles and init: linux-generic code refers to that, that's why we can't do this in separate patches Signed-off-by: Zoltan Kiss <zoltan.kiss@linaro.org>
Diffstat (limited to 'platform/linux-dpdk')
-rw-r--r--platform/linux-dpdk/Makefile.am5
-rw-r--r--platform/linux-dpdk/include/odp_packet_dpdk.h30
-rw-r--r--platform/linux-dpdk/include/odp_packet_internal.h2
-rw-r--r--platform/linux-dpdk/include/odp_packet_io_internal.h85
-rw-r--r--platform/linux-dpdk/odp_init.c4
-rw-r--r--platform/linux-dpdk/odp_packet_dpdk.c269
-rw-r--r--platform/linux-dpdk/test/Makefile.am2
7 files changed, 341 insertions, 56 deletions
diff --git a/platform/linux-dpdk/Makefile.am b/platform/linux-dpdk/Makefile.am
index cfc3c18dd..506d7cff2 100644
--- a/platform/linux-dpdk/Makefile.am
+++ b/platform/linux-dpdk/Makefile.am
@@ -95,6 +95,7 @@ odpplatinclude_HEADERS = \
noinst_HEADERS = \
$(srcdir)/include/odp_buffer_internal.h \
+ $(top_srcdir)/platform/linux-generic/include/odp_classification_internal.h \
$(top_srcdir)/platform/linux-generic/include/odp_debug_internal.h \
$(srcdir)/include/odp_packet_dpdk.h \
$(srcdir)/include/odp_packet_internal.h \
@@ -118,6 +119,7 @@ subdirheaders_HEADERS = \
__LIB__libodp_la_SOURCES = \
../linux-generic/odp_barrier.c \
odp_buffer.c \
+ ../linux-generic/odp_classification.c \
../linux-generic/odp_cpu.c \
../linux-generic/odp_cpumask.c \
../linux-generic/odp_cpumask_task.c \
@@ -130,7 +132,8 @@ __LIB__libodp_la_SOURCES = \
odp_packet.c \
odp_packet_dpdk.c \
odp_packet_flags.c \
- odp_packet_io.c \
+ ../linux-generic/odp_packet_io.c \
+ ../linux-generic/pktio/loop.c \
odp_pool.c \
../linux-generic/odp_queue.c \
../../helper/ring.c \
diff --git a/platform/linux-dpdk/include/odp_packet_dpdk.h b/platform/linux-dpdk/include/odp_packet_dpdk.h
index 49a0fc817..676bc801b 100644
--- a/platform/linux-dpdk/include/odp_packet_dpdk.h
+++ b/platform/linux-dpdk/include/odp_packet_dpdk.h
@@ -54,35 +54,5 @@
#define RTE_TEST_RX_DESC_DEFAULT 128
#define RTE_TEST_TX_DESC_DEFAULT 512
-/** Packet socket using dpdk mmaped rings for both Rx and Tx */
-typedef struct {
- odp_pool_t pool;
-
- /********************************/
- char ifname[32];
- uint8_t min_rx_burst;
- uint8_t portid;
- uint16_t queueid;
- odp_bool_t vdev_sysc_promisc; /**< promiscuous mode defined with
- system call */
-} pkt_dpdk_t;
-
-/**
- * Configure an interface to work in dpdk mode
- */
-int setup_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk, const char *netdev,
- odp_pool_t pool);
-
-/**
- * Switch interface from dpdk mode to normal mode
- */
-int close_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk);
-
-/**
- * Receive packets using dpdk
- */
-int recv_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk, odp_packet_t pkt_table[],
- unsigned len);
-
int odp_init_dpdk(const char *cmdline);
#endif
diff --git a/platform/linux-dpdk/include/odp_packet_internal.h b/platform/linux-dpdk/include/odp_packet_internal.h
index 48a736c63..0dbc617ea 100644
--- a/platform/linux-dpdk/include/odp_packet_internal.h
+++ b/platform/linux-dpdk/include/odp_packet_internal.h
@@ -207,7 +207,7 @@ static inline int packet_parse_full(odp_packet_hdr_t *pkt_hdr)
return _odp_packet_parse(pkt_hdr);
}
-static inline uint32_t packet_hdr_len(odp_packet_hdr_t* pkt_hdr)
+static inline uint32_t packet_len(odp_packet_hdr_t* pkt_hdr)
{
return rte_pktmbuf_pkt_len(&pkt_hdr->buf_hdr.mb);
}
diff --git a/platform/linux-dpdk/include/odp_packet_io_internal.h b/platform/linux-dpdk/include/odp_packet_io_internal.h
index 8e6b156ef..a2a41dc80 100644
--- a/platform/linux-dpdk/include/odp_packet_io_internal.h
+++ b/platform/linux-dpdk/include/odp_packet_io_internal.h
@@ -19,45 +19,63 @@ extern "C" {
#endif
#include <odp/spinlock.h>
+#include <odp/ticketlock.h>
#include <odp_packet_socket.h>
#include <odp_classification_datamodel.h>
#include <odp_align_internal.h>
+#include <odp_debug_internal.h>
#include <odp/config.h>
#include <odp/hints.h>
#include <odp_packet_dpdk.h>
-/**
- * Packet IO types
- */
+#define PKTIO_NAME_LEN 256
-typedef enum {
- ODP_PKTIO_TYPE_DPDK = 0x1,
- ODP_PKTIO_TYPE_LOOPBACK,
-} odp_pktio_type_t;
+/* Forward declaration */
+struct pktio_if_ops;
+struct pkt_dpdk_t;
+typedef struct {
+ odp_queue_t loopq; /**< loopback queue for "loop" device */
+ odp_bool_t promisc; /**< promiscuous mode state */
+} pkt_loop_t;
+
+/** Packet socket using dpdk mmaped rings for both Rx and Tx */
+typedef struct {
+ odp_pool_t pool;
+
+ /********************************/
+ char ifname[32];
+ uint8_t min_rx_burst;
+ uint8_t portid;
+ uint16_t queueid;
+ odp_bool_t vdev_sysc_promisc; /**< promiscuous mode defined with
+ system call */
+} pkt_dpdk_t;
struct pktio_entry {
- odp_spinlock_t lock; /**< entry spinlock */
- odp_ticketlock_t rxl; /**< RX ticket lock */
- odp_ticketlock_t txl; /**< TX ticket lock */
+ const struct pktio_if_ops *ops; /**< Implementation specific methods */
+ /* These two locks together lock the whole pktio device */
+ odp_ticketlock_t rxl; /**< RX ticketlock */
+ odp_ticketlock_t txl; /**< TX ticketlock */
int taken; /**< is entry taken(1) or free(0) */
int cls_enabled; /**< is classifier enabled */
odp_pktio_t handle; /**< pktio handle */
odp_queue_t inq_default; /**< default input queue, if set */
odp_queue_t outq_default; /**< default out queue */
- odp_queue_t loopq; /**< loopback queue for "loop" device */
- odp_pktio_type_t type; /**< pktio type */
- pkt_dpdk_t pkt_dpdk; /**< using DPDK API for IO */
+ union {
+ pkt_loop_t pkt_loop; /**< Using loopback for IO */
+ pkt_dpdk_t pkt_dpdk; /**< using DPDK API for IO */
+ };
enum {
STATE_START = 0,
STATE_STOP
} state;
classifier_t cls; /**< classifier linked with this pktio*/
- char name[IFNAMSIZ]; /**< name of pktio provided to
+ char name[PKTIO_NAME_LEN]; /**< name of pktio provided to
pktio_open() */
- odp_bool_t promisc; /**< promiscuous mode state */
+ odp_pktio_t id;
odp_pktio_param_t param;
};
@@ -71,6 +89,29 @@ typedef struct {
pktio_entry_t entries[ODP_CONFIG_PKTIO_ENTRIES];
} pktio_table_t;
+int is_free(pktio_entry_t *entry);
+
+typedef struct pktio_if_ops {
+ int (*init)(void);
+ int (*term)(void);
+ int (*open)(odp_pktio_t pktio, pktio_entry_t *pktio_entry,
+ const char *devname, odp_pool_t pool);
+ int (*close)(pktio_entry_t *pktio_entry);
+ int (*start)(pktio_entry_t *pktio_entry);
+ int (*stop)(pktio_entry_t *pktio_entry);
+ int (*recv)(pktio_entry_t *pktio_entry, odp_packet_t pkt_table[],
+ unsigned len);
+ int (*send)(pktio_entry_t *pktio_entry, odp_packet_t pkt_table[],
+ unsigned len);
+ int (*mtu_get)(pktio_entry_t *pktio_entry);
+ int (*promisc_mode_set)(pktio_entry_t *pktio_entry, int enable);
+ int (*promisc_mode_get)(pktio_entry_t *pktio_entry);
+ int (*mac_get)(pktio_entry_t *pktio_entry, void *mac_addr);
+} pktio_if_ops_t;
+
+int _odp_packet_cls_enq(pktio_entry_t *pktio_entry, const uint8_t *base,
+ uint16_t buf_len, odp_packet_t *pkt_ret);
+
extern void *pktio_entry_ptr[];
static inline int pktio_to_id(odp_pktio_t pktio)
@@ -92,8 +133,22 @@ static inline pktio_entry_t *get_pktio_entry(odp_pktio_t pktio)
return pktio_entry_ptr[pktio_to_id(pktio)];
}
+static inline int pktio_cls_enabled(pktio_entry_t *entry)
+{
+ return entry->s.cls_enabled;
+}
+
+static inline void pktio_cls_enabled_set(pktio_entry_t *entry, int ena)
+{
+ entry->s.cls_enabled = ena;
+}
+
int pktin_poll(pktio_entry_t *entry);
+extern const pktio_if_ops_t loopback_pktio_ops;
+extern const pktio_if_ops_t dpdk_pktio_ops;
+extern const pktio_if_ops_t * const pktio_if_ops[];
+
#ifdef __cplusplus
}
#endif
diff --git a/platform/linux-dpdk/odp_init.c b/platform/linux-dpdk/odp_init.c
index 7fc5ecd5e..1a0c22823 100644
--- a/platform/linux-dpdk/odp_init.c
+++ b/platform/linux-dpdk/odp_init.c
@@ -294,12 +294,10 @@ int odp_init_global(const odp_init_t *params,
return -1;
}
-#if 0 /* for now classification is disabled */
if (odp_classification_init_global()) {
ODP_ERR("ODP classification init failed.\n");
return -1;
}
-#endif
return 0;
}
@@ -308,12 +306,10 @@ int odp_term_global(void)
{
int rc = 0;
-#if 0 /* for now classification is disabled */
if (odp_classification_term_global()) {
ODP_ERR("ODP classificatio term failed.\n");
rc = -1;
}
-#endif
if (odp_crypto_term_global()) {
ODP_ERR("ODP crypto term failed.\n");
diff --git a/platform/linux-dpdk/odp_packet_dpdk.c b/platform/linux-dpdk/odp_packet_dpdk.c
index 3a24b0334..d130ac0e2 100644
--- a/platform/linux-dpdk/odp_packet_dpdk.c
+++ b/platform/linux-dpdk/odp_packet_dpdk.c
@@ -26,10 +26,23 @@
#include <odp/system_info.h>
#include <odp_debug_internal.h>
+#include <odp_packet_io_internal.h>
#include <odp_packet_dpdk.h>
#include <net/if.h>
#include <math.h>
+/* Ops for all implementation of pktio.
+ * Order matters. The first implementation to setup successfully
+ * will be picked.
+ * Array must be NULL terminated */
+const pktio_if_ops_t * const pktio_if_ops[] = {
+ &loopback_pktio_ops,
+ &dpdk_pktio_ops,
+ NULL
+};
+
+extern pktio_table_t *pktio_tbl;
+
/* Test if s has only digits or not. Dpdk pktio uses only digits.*/
static int _dpdk_netdev_is_valid(const char *s)
{
@@ -58,8 +71,8 @@ static void _dpdk_print_port_mac(uint8_t portid)
eth_addr.addr_bytes[5]);
}
-int setup_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk, const char *netdev,
- odp_pool_t pool)
+static int setup_pkt_dpdk(odp_pktio_t pktio ODP_UNUSED, pktio_entry_t *pktio_entry,
+ const char *netdev, odp_pool_t pool)
{
uint8_t portid = 0;
uint16_t nbrxq, nbtxq;
@@ -70,6 +83,7 @@ int setup_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk, const char *netdev,
uint16_t nb_rxd = RTE_TEST_RX_DESC_DEFAULT;
uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT;
struct rte_eth_dev_info dev_info;
+ pkt_dpdk_t * const pkt_dpdk = &pktio_entry->s.pkt_dpdk;
struct rte_eth_conf port_conf = {
.rxmode = {
@@ -162,17 +176,82 @@ int setup_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk, const char *netdev,
return 0;
}
-int close_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk)
+static int close_pkt_dpdk(pktio_entry_t *pktio_entry)
{
+ pkt_dpdk_t * const pkt_dpdk = &pktio_entry->s.pkt_dpdk;
+
rte_eth_dev_close(pkt_dpdk->portid);
return 0;
}
-int recv_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk, odp_packet_t pkt_table[],
+static int start_pkt_dpdk(pktio_entry_t *pktio_entry)
+{
+ int ret;
+
+ ret = rte_eth_dev_start(pktio_entry->s.pkt_dpdk.portid);
+ if (ret < 0) {
+ ODP_ERR("rte_eth_dev_start:err=%d, port=%u\n",
+ ret, pktio_entry->s.pkt_dpdk.portid);
+ return ret;
+ }
+ return 0;
+}
+
+static int stop_pkt_dpdk(pktio_entry_t *pktio_entry)
+{
+ rte_eth_dev_stop(pktio_entry->s.pkt_dpdk.portid);
+ return 0;
+}
+
+static unsigned rte_mempool_available(const struct rte_mempool *mp)
+{
+#if RTE_MEMPOOL_CACHE_MAX_SIZE > 0
+ return rte_ring_count(mp->ring) + mp->local_cache[rte_lcore_id()].len;
+#else
+ return rte_ring_count(mp->ring);
+#endif
+}
+
+static void _odp_pktio_send_completion(pktio_entry_t *pktio_entry ODP_UNUSED)
+{
+ int i;
+ struct rte_mbuf* dummy;
+ pool_entry_t *pool_entry =
+ get_pool_entry(_odp_typeval(pktio_entry->s.pkt_dpdk.pool));
+ struct rte_mempool *rte_mempool = pool_entry->s.rte_mempool;
+ pkt_dpdk_t * pkt_dpdk = &pktio_entry->s.pkt_dpdk;
+
+ rte_eth_tx_burst(pkt_dpdk->portid, pkt_dpdk->queueid, &dummy, 0);
+
+ for (i = 0; i < ODP_CONFIG_PKTIO_ENTRIES; ++i) {
+ pktio_entry_t *entry = &pktio_tbl->entries[i];
+
+ if (rte_mempool_available(rte_mempool) != 0)
+ return;
+
+ if (entry == pktio_entry)
+ continue;
+
+ if (odp_ticketlock_trylock(&entry->s.txl)) {
+ if (!is_free(entry) &&
+ entry->s.ops == &dpdk_pktio_ops) {
+ pkt_dpdk = &entry->s.pkt_dpdk;
+ rte_eth_tx_burst(pkt_dpdk->portid,
+ pkt_dpdk->queueid, &dummy, 0);
+ }
+ odp_ticketlock_unlock(&entry->s.txl);
+ }
+ }
+
+ return;
+}
+
+static int recv_pkt_dpdk(pktio_entry_t *pktio_entry, odp_packet_t pkt_table[],
unsigned len)
{
uint16_t nb_rx, i = 0;
odp_packet_t *saved_pkt_table;
+ pkt_dpdk_t * const pkt_dpdk = &pktio_entry->s.pkt_dpdk;
uint8_t min = pkt_dpdk->min_rx_burst;
if (odp_unlikely(min > len)) {
@@ -187,6 +266,17 @@ int recv_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk, odp_packet_t pkt_table[],
(struct rte_mbuf **)pkt_table,
(uint16_t)RTE_MAX(len, min));
+ if (nb_rx == 0) {
+ pool_entry_t *pool_entry =
+ get_pool_entry(_odp_typeval(pkt_dpdk->pool));
+ struct rte_mempool *rte_mempool =
+ pool_entry->s.rte_mempool;
+ if (rte_mempool_available(rte_mempool) == 0)
+ _odp_pktio_send_completion(pktio_entry);
+ }
+ for (i = 0; i < nb_rx; ++i)
+ _odp_packet_reset_parse(pkt_table[i]);
+
if (odp_unlikely(min > len)) {
memcpy(saved_pkt_table, pkt_table,
len * sizeof(odp_packet_t));
@@ -198,3 +288,174 @@ int recv_pkt_dpdk(pkt_dpdk_t * const pkt_dpdk, odp_packet_t pkt_table[],
return nb_rx;
}
+
+static int send_pkt_dpdk(pktio_entry_t *pktio_entry, odp_packet_t pkt_table[],
+ unsigned len)
+{
+ int pkts;
+ pkt_dpdk_t * const pkt_dpdk = &pktio_entry->s.pkt_dpdk;
+
+ pkts = rte_eth_tx_burst(pkt_dpdk->portid, pkt_dpdk->queueid,
+ (struct rte_mbuf **)pkt_table, len);
+ if (pkts) {
+ return pkts;
+ } else {
+ if (!rte_errno)
+ rte_errno = -1;
+ return -1;
+ }
+}
+
+static int _dpdk_vdev_mtu(uint8_t port_id)
+{
+ struct rte_eth_dev_info dev_info = {0};
+ struct ifreq ifr;
+ int ret;
+ int sockfd;
+
+ rte_eth_dev_info_get(port_id, &dev_info);
+ if_indextoname(dev_info.if_index, ifr.ifr_name);
+ sockfd = socket(AF_INET, SOCK_DGRAM, 0);
+ ret = ioctl(sockfd, SIOCGIFMTU, &ifr);
+ close(sockfd);
+ if (ret < 0) {
+ ODP_DBG("ioctl SIOCGIFMTU error\n");
+ return -1;
+ }
+
+ return ifr.ifr_mtu;
+}
+
+static int mtu_get_pkt_dpdk(pktio_entry_t *pktio_entry)
+{
+ uint16_t mtu;
+ int ret;
+
+ ret = rte_eth_dev_get_mtu(pktio_entry->s.pkt_dpdk.portid,
+ &mtu);
+ if (ret < 0)
+ return -2;
+
+ /* some dpdk PMD vdev does not support getting mtu size,
+ * try to use system call if dpdk cannot get mtu value.
+ */
+ if (mtu == 0)
+ mtu = _dpdk_vdev_mtu(pktio_entry->s.pkt_dpdk.portid);
+ return mtu;
+}
+
+static int _dpdk_vdev_promisc_mode_set(uint8_t port_id, int enable)
+{
+ struct rte_eth_dev_info dev_info = {0};
+ struct ifreq ifr;
+ int ret;
+ int sockfd;
+
+ rte_eth_dev_info_get(port_id, &dev_info);
+ if_indextoname(dev_info.if_index, ifr.ifr_name);
+ sockfd = socket(AF_INET, SOCK_DGRAM, 0);
+
+ ret = ioctl(sockfd, SIOCGIFFLAGS, &ifr);
+ if (ret < 0) {
+ close(sockfd);
+ ODP_DBG("ioctl SIOCGIFFLAGS error\n");
+ return -1;
+ }
+
+ if (enable)
+ ifr.ifr_flags |= IFF_PROMISC;
+ else
+ ifr.ifr_flags &= ~(IFF_PROMISC);
+
+ ret = ioctl(sockfd, SIOCSIFFLAGS, &ifr);
+ if (ret < 0) {
+ close(sockfd);
+ ODP_DBG("ioctl SIOCSIFFLAGS error\n");
+ return -1;
+ }
+
+ ret = ioctl(sockfd, SIOCGIFMTU, &ifr);
+ if (ret < 0) {
+ close(sockfd);
+ ODP_DBG("ioctl SIOCGIFMTU error\n");
+ return -1;
+ }
+
+ ODP_DBG("vdev promisc set to %d\n", enable);
+ close(sockfd);
+ return 0;
+}
+
+static int promisc_mode_set_pkt_dpdk(pktio_entry_t *pktio_entry, int enable)
+{
+ uint8_t portid = pktio_entry->s.pkt_dpdk.portid;
+ if (enable)
+ rte_eth_promiscuous_enable(portid);
+ else
+ rte_eth_promiscuous_disable(portid);
+
+ if (pktio_entry->s.pkt_dpdk.vdev_sysc_promisc) {
+ int ret = _dpdk_vdev_promisc_mode_set(portid, enable);
+ if (ret < 0)
+ ODP_DBG("vdev promisc mode fail\n");
+ }
+
+ return 0;
+}
+
+static int _dpdk_vdev_promisc_mode(uint8_t port_id)
+{
+ struct rte_eth_dev_info dev_info = {0};
+ struct ifreq ifr;
+ int ret;
+ int sockfd;
+
+ rte_eth_dev_info_get(port_id, &dev_info);
+ if_indextoname(dev_info.if_index, ifr.ifr_name);
+ sockfd = socket(AF_INET, SOCK_DGRAM, 0);
+ ret = ioctl(sockfd, SIOCGIFFLAGS, &ifr);
+ close(sockfd);
+ if (ret < 0) {
+ ODP_DBG("ioctl SIOCGIFFLAGS error\n");
+ return -1;
+ }
+
+ if (ifr.ifr_flags & IFF_PROMISC) {
+ ODP_DBG("promisc is 1\n");
+ return 1;
+ } else
+ return 0;
+}
+
+static int promisc_mode_get_pkt_dpdk(pktio_entry_t *pktio_entry)
+{
+ uint8_t portid = pktio_entry->s.pkt_dpdk.portid;
+ if (pktio_entry->s.pkt_dpdk.vdev_sysc_promisc)
+ return _dpdk_vdev_promisc_mode(portid);
+ else
+ return rte_eth_promiscuous_get(portid);
+
+}
+
+static int mac_get_pkt_dpdk(pktio_entry_t *pktio_entry, void *mac_addr)
+{
+ rte_eth_macaddr_get(pktio_entry->s.pkt_dpdk.portid,
+ (struct ether_addr *)mac_addr);
+ return ETH_ALEN;
+}
+
+
+const pktio_if_ops_t dpdk_pktio_ops = {
+ .init = NULL,
+ .term = NULL,
+ .open = setup_pkt_dpdk,
+ .close = close_pkt_dpdk,
+ .start = start_pkt_dpdk,
+ .stop = stop_pkt_dpdk,
+ .recv = recv_pkt_dpdk,
+ .send = send_pkt_dpdk,
+ .mtu_get = mtu_get_pkt_dpdk,
+ .promisc_mode_set = promisc_mode_set_pkt_dpdk,
+ .promisc_mode_get = promisc_mode_get_pkt_dpdk,
+ .mac_get = mac_get_pkt_dpdk
+};
diff --git a/platform/linux-dpdk/test/Makefile.am b/platform/linux-dpdk/test/Makefile.am
index 3eda00df9..dc09cdb40 100644
--- a/platform/linux-dpdk/test/Makefile.am
+++ b/platform/linux-dpdk/test/Makefile.am
@@ -6,7 +6,7 @@ ODP_MODULES = pktio
if test_vald
TESTS = pktio/pktio_run \
${top_builddir}/test/validation/buffer/buffer_main$(EXEEXT) \
-## ${top_builddir}/test/validation/classification/classification_main$(EXEEXT) \
+ ${top_builddir}/test/validation/classification/classification_main$(EXEEXT) \
${top_builddir}/test/validation/cpumask/cpumask_main$(EXEEXT) \
${top_builddir}/test/validation/crypto/crypto_main$(EXEEXT) \
${top_builddir}/test/validation/errno/errno_main$(EXEEXT) \