Adds packet input timestamping support using odp global
time. Also implements odp_pktio_capability() for pktio types
still lacking it.

Signed-off-by: Matias Elo <[email protected]>
---
 platform/linux-generic/pktio/dpdk.c        | 49 +++++++++++++-----
 platform/linux-generic/pktio/loop.c        | 27 +++++++++-
 platform/linux-generic/pktio/netmap.c      | 83 +++++++++++++++++++++---------
 platform/linux-generic/pktio/pcap.c        | 28 +++++++++-
 platform/linux-generic/pktio/socket.c      | 35 +++++++++++--
 platform/linux-generic/pktio/socket_mmap.c | 30 ++++++++++-
 platform/linux-generic/pktio/tap.c         | 37 +++++++++++--
 7 files changed, 241 insertions(+), 48 deletions(-)

diff --git a/platform/linux-generic/pktio/dpdk.c 
b/platform/linux-generic/pktio/dpdk.c
index 3845448..9089715 100644
--- a/platform/linux-generic/pktio/dpdk.c
+++ b/platform/linux-generic/pktio/dpdk.c
@@ -485,6 +485,27 @@ static int dpdk_output_queues_config(pktio_entry_t 
*pktio_entry,
        return 0;
 }
 
+static void dpdk_init_capability(pktio_entry_t *pktio_entry)
+{
+       pkt_dpdk_t *pkt_dpdk = &pktio_entry->s.pkt_dpdk;
+       odp_pktio_capability_t *capa = &pkt_dpdk->capa;
+       struct rte_eth_dev_info dev_info;
+
+       memset(&dev_info, 0, sizeof(struct rte_eth_dev_info));
+       memset(capa, 0, sizeof(odp_pktio_capability_t));
+
+       rte_eth_dev_info_get(pkt_dpdk->port_id, &dev_info);
+       capa->max_input_queues = RTE_MIN(dev_info.max_rx_queues,
+                                        PKTIO_MAX_QUEUES);
+       capa->max_output_queues = RTE_MIN(dev_info.max_tx_queues,
+                                         PKTIO_MAX_QUEUES);
+       capa->set_op.op.promisc_mode = 1;
+
+       odp_pktio_config_init(&capa->config);
+       capa->config.pktin.bit.ts_all = 1;
+       capa->config.pktin.bit.ts_ptp = 1;
+}
+
 static int dpdk_open(odp_pktio_t id ODP_UNUSED,
                     pktio_entry_t *pktio_entry,
                     const char *netdev,
@@ -535,13 +556,7 @@ static int dpdk_open(odp_pktio_t id ODP_UNUSED,
                return -1;
        }
 
-       memset(&dev_info, 0, sizeof(struct rte_eth_dev_info));
-       rte_eth_dev_info_get(pkt_dpdk->port_id, &dev_info);
-       pkt_dpdk->capa.max_input_queues = RTE_MIN(dev_info.max_rx_queues,
-                                                 PKTIO_MAX_QUEUES);
-       pkt_dpdk->capa.max_output_queues = RTE_MIN(dev_info.max_tx_queues,
-                                                  PKTIO_MAX_QUEUES);
-       pkt_dpdk->capa.set_op.op.promisc_mode = 1;
+       dpdk_init_capability(pktio_entry);
 
        mtu = dpdk_mtu_get(pktio_entry);
        if (mtu == 0) {
@@ -652,7 +667,7 @@ static int dpdk_stop(pktio_entry_t *pktio_entry)
 static inline int mbuf_to_pkt(pktio_entry_t *pktio_entry,
                              odp_packet_t pkt_table[],
                              struct rte_mbuf *mbuf_table[],
-                             uint16_t num)
+                             uint16_t num, odp_time_t *ts)
 {
        odp_packet_t pkt;
        odp_packet_hdr_t *pkt_hdr;
@@ -677,7 +692,7 @@ static inline int mbuf_to_pkt(pktio_entry_t *pktio_entry,
                if (pktio_cls_enabled(pktio_entry)) {
                        if (_odp_packet_cls_enq(pktio_entry,
                                                (const uint8_t *)buf, pkt_len,
-                                               NULL, &pkt_table[nb_pkts]))
+                                               ts, &pkt_table[nb_pkts]))
                                nb_pkts++;
                } else {
                        pkt = packet_alloc(pktio_entry->s.pkt_dpdk.pool,
@@ -704,6 +719,8 @@ static inline int mbuf_to_pkt(pktio_entry_t *pktio_entry,
                        if (mbuf->ol_flags & PKT_RX_RSS_HASH)
                                odp_packet_flow_hash_set(pkt, mbuf->hash.rss);
 
+                       packet_set_ts(pkt_hdr, ts);
+
                        pkt_table[nb_pkts++] = pkt;
                }
                rte_pktmbuf_free(mbuf);
@@ -765,6 +782,8 @@ static int dpdk_recv_queue(pktio_entry_t *pktio_entry,
 {
        pkt_dpdk_t *pkt_dpdk = &pktio_entry->s.pkt_dpdk;
        pkt_cache_t *rx_cache = &pkt_dpdk->rx_cache[index];
+       odp_time_t ts_val;
+       odp_time_t *ts = NULL;
        int nb_rx;
        struct rte_mbuf *rx_mbufs[num];
        int i;
@@ -795,7 +814,6 @@ static int dpdk_recv_queue(pktio_entry_t *pktio_entry,
 
                nb_rx = rte_eth_rx_burst(pktio_entry->s.pkt_dpdk.port_id, index,
                                         new_mbufs, pkt_dpdk->min_rx_burst);
-
                rx_cache->s.idx = 0;
                for (i = 0; i < nb_rx; i++) {
                        if (i < num) {
@@ -813,8 +831,15 @@ static int dpdk_recv_queue(pktio_entry_t *pktio_entry,
                                         rx_mbufs, num);
        }
 
-       if (nb_rx > 0)
-               nb_rx = mbuf_to_pkt(pktio_entry, pkt_table, rx_mbufs, nb_rx);
+       if (nb_rx > 0) {
+               if (pktio_entry->s.config.pktin.bit.ts_all ||
+                   pktio_entry->s.config.pktin.bit.ts_ptp) {
+                       ts_val = odp_time_global();
+                       ts = &ts_val;
+               }
+               nb_rx = mbuf_to_pkt(pktio_entry, pkt_table, rx_mbufs, nb_rx,
+                                   ts);
+       }
 
        if (!pktio_entry->s.pkt_dpdk.lockless_rx)
                odp_ticketlock_unlock(&pkt_dpdk->rx_lock[index]);
diff --git a/platform/linux-generic/pktio/loop.c 
b/platform/linux-generic/pktio/loop.c
index 2fc1381..f04824f 100644
--- a/platform/linux-generic/pktio/loop.c
+++ b/platform/linux-generic/pktio/loop.c
@@ -56,6 +56,8 @@ static int loopback_recv(pktio_entry_t *pktio_entry, 
odp_packet_t pkts[],
        queue_entry_t *qentry;
        odp_packet_hdr_t *pkt_hdr;
        odp_packet_t pkt;
+       odp_time_t ts_val;
+       odp_time_t *ts = NULL;
 
        if (odp_unlikely(len > QUEUE_MULTI_MAX))
                len = QUEUE_MULTI_MAX;
@@ -63,6 +65,12 @@ static int loopback_recv(pktio_entry_t *pktio_entry, 
odp_packet_t pkts[],
        qentry = queue_to_qentry(pktio_entry->s.pkt_loop.loopq);
        nbr = queue_deq_multi(qentry, hdr_tbl, len);
 
+       if (pktio_entry->s.config.pktin.bit.ts_all ||
+           pktio_entry->s.config.pktin.bit.ts_ptp) {
+               ts_val = odp_time_global();
+               ts = &ts_val;
+       }
+
        if (pktio_cls_enabled(pktio_entry)) {
                for (i = 0, j = 0; i < nbr; i++) {
                        pkt = _odp_packet_from_buffer(odp_hdr_to_buf
@@ -71,6 +79,7 @@ static int loopback_recv(pktio_entry_t *pktio_entry, 
odp_packet_t pkts[],
                        packet_parse_reset(pkt_hdr);
                        packet_parse_l2(pkt_hdr);
                        if (0 > _odp_packet_classifier(pktio_entry, pkt)) {
+                               packet_set_ts(pkt_hdr, ts);
                                pkts[j++] = pkt;
                                pktio_entry->s.stats.in_octets +=
                                        odp_packet_len(pkts[i]);
@@ -84,6 +93,7 @@ static int loopback_recv(pktio_entry_t *pktio_entry, 
odp_packet_t pkts[],
                        pkt_hdr = odp_packet_hdr(pkts[i]);
                        packet_parse_reset(pkt_hdr);
                        packet_parse_l2(pkt_hdr);
+                       packet_set_ts(pkt_hdr, ts);
                        pktio_entry->s.stats.in_octets +=
                                odp_packet_len(pkts[i]);
                }
@@ -140,6 +150,21 @@ static int loopback_link_status(pktio_entry_t *pktio_entry 
ODP_UNUSED)
        return 1;
 }
 
+static int loopback_capability(pktio_entry_t *pktio_entry ODP_UNUSED,
+                              odp_pktio_capability_t *capa)
+{
+       memset(capa, 0, sizeof(odp_pktio_capability_t));
+
+       capa->max_input_queues  = 1;
+       capa->max_output_queues = 1;
+       capa->set_op.op.promisc_mode = 1;
+
+       odp_pktio_config_init(&capa->config);
+       capa->config.pktin.bit.ts_all = 1;
+       capa->config.pktin.bit.ts_ptp = 1;
+       return 0;
+}
+
 static int loopback_promisc_mode_set(pktio_entry_t *pktio_entry,
                                     odp_bool_t enable)
 {
@@ -183,7 +208,7 @@ const pktio_if_ops_t loopback_pktio_ops = {
        .promisc_mode_get = loopback_promisc_mode_get,
        .mac_get = loopback_mac_addr_get,
        .link_status = loopback_link_status,
-       .capability = NULL,
+       .capability = loopback_capability,
        .pktin_ts_res = NULL,
        .pktin_ts_from_ns = NULL,
        .config = NULL,
diff --git a/platform/linux-generic/pktio/netmap.c 
b/platform/linux-generic/pktio/netmap.c
index 9112ba3..60e8d8e 100644
--- a/platform/linux-generic/pktio/netmap.c
+++ b/platform/linux-generic/pktio/netmap.c
@@ -251,6 +251,47 @@ static inline int netmap_wait_for_link(pktio_entry_t 
*pktio_entry)
 }
 
 /**
+ * Initialize netmap capability values
+ *
+ * @param pktio_entry    Packet IO entry
+ */
+static void netmap_init_capability(pktio_entry_t *pktio_entry)
+{
+       pkt_netmap_t *pkt_nm = &pktio_entry->s.pkt_nm;
+       odp_pktio_capability_t *capa = &pkt_nm->capa;
+
+       memset(&pkt_nm->capa, 0, sizeof(odp_pktio_capability_t));
+
+       capa->max_input_queues = PKTIO_MAX_QUEUES;
+       if (pkt_nm->num_rx_rings < PKTIO_MAX_QUEUES)
+               capa->max_input_queues = pkt_nm->num_rx_rings;
+       if (capa->max_input_queues > NM_MAX_DESC) {
+               /* Have to use a single descriptor to fetch packets from all
+                * netmap rings */
+               capa->max_input_queues = 1;
+               ODP_DBG("Unable to store all %" PRIu32 " rx rings (max %d)\n"
+                       "  max input queues: %u\n", pkt_nm->num_rx_rings,
+                       NM_MAX_DESC, capa->max_input_queues);
+       }
+
+       capa->max_output_queues = PKTIO_MAX_QUEUES;
+       if (pkt_nm->num_tx_rings < PKTIO_MAX_QUEUES)
+               capa->max_output_queues = pkt_nm->num_tx_rings;
+       if (capa->max_output_queues > NM_MAX_DESC) {
+               capa->max_output_queues = NM_MAX_DESC;
+               ODP_DBG("Unable to store all %" PRIu32 " tx rings (max %d)\n"
+                       "  max output queues: %u\n", pkt_nm->num_tx_rings,
+                       NM_MAX_DESC, capa->max_output_queues);
+       }
+
+       capa->set_op.op.promisc_mode = 1;
+
+       odp_pktio_config_init(&capa->config);
+       capa->config.pktin.bit.ts_all = 1;
+       capa->config.pktin.bit.ts_ptp = 1;
+}
+
+/**
  * Open a netmap interface
  *
  * In addition to standard interfaces (with or without modified netmap drivers)
@@ -326,29 +367,9 @@ static int netmap_open(odp_pktio_t id ODP_UNUSED, 
pktio_entry_t *pktio_entry,
                goto error;
        }
        pkt_nm->num_rx_rings = desc->nifp->ni_rx_rings;
-       pkt_nm->capa.max_input_queues = PKTIO_MAX_QUEUES;
-       if (pkt_nm->num_rx_rings < PKTIO_MAX_QUEUES)
-               pkt_nm->capa.max_input_queues = pkt_nm->num_rx_rings;
-       if (pkt_nm->capa.max_input_queues > NM_MAX_DESC) {
-               /* Have to use a single descriptor to fetch packets from all
-                * netmap rings */
-               pkt_nm->capa.max_input_queues = 1;
-               ODP_DBG("Unable to store all %" PRIu32 " rx rings (max %d)\n"
-                       "  max input queues: %u\n", pkt_nm->num_rx_rings,
-                       NM_MAX_DESC, pkt_nm->capa.max_input_queues);
-       }
        pkt_nm->num_tx_rings = desc->nifp->ni_tx_rings;
-       pkt_nm->capa.max_output_queues = PKTIO_MAX_QUEUES;
-       if (pkt_nm->num_tx_rings < PKTIO_MAX_QUEUES)
-               pkt_nm->capa.max_output_queues = pkt_nm->num_tx_rings;
-       if (pkt_nm->capa.max_output_queues > NM_MAX_DESC) {
-               pkt_nm->capa.max_output_queues = NM_MAX_DESC;
-               ODP_DBG("Unable to store all %" PRIu32 " tx rings (max %d)\n"
-                       "  max output queues: %u\n", pkt_nm->num_tx_rings,
-                       NM_MAX_DESC, pkt_nm->capa.max_output_queues);
-       }
 
-       pkt_nm->capa.set_op.op.promisc_mode = 1;
+       netmap_init_capability(pktio_entry);
 
        ring = NETMAP_RXRING(desc->nifp, desc->cur_rx_ring);
        buf_size = ring->nr_buf_size;
@@ -562,13 +583,14 @@ static int netmap_stop(pktio_entry_t *pktio_entry 
ODP_UNUSED)
  * @param pkt_out        Storage for new ODP packet handle
  * @param buf            Netmap buffer address
  * @param len            Netmap buffer length
+ * @param ts             Pointer to pktin timestamp
  *
  * @retval 0 on success
  * @retval <0 on failure
  */
 static inline int netmap_pkt_to_odp(pktio_entry_t *pktio_entry,
                                    odp_packet_t *pkt_out, const char *buf,
-                                   uint16_t len)
+                                   uint16_t len, odp_time_t *ts)
 {
        odp_packet_t pkt;
        int ret;
@@ -586,7 +608,7 @@ static inline int netmap_pkt_to_odp(pktio_entry_t 
*pktio_entry,
 
        if (pktio_cls_enabled(pktio_entry)) {
                ret = _odp_packet_cls_enq(pktio_entry, (const uint8_t *)buf,
-                                         len, NULL, pkt_out);
+                                         len, ts, pkt_out);
                if (ret)
                        return 0;
                return -1;
@@ -610,6 +632,8 @@ static inline int netmap_pkt_to_odp(pktio_entry_t 
*pktio_entry,
 
                pkt_hdr->input = pktio_entry->s.handle;
 
+               packet_set_ts(pkt_hdr, ts);
+
                *pkt_out = pkt;
        }
 
@@ -621,6 +645,8 @@ static inline int netmap_recv_desc(pktio_entry_t 
*pktio_entry,
                                   odp_packet_t pkt_table[], int num)
 {
        struct netmap_ring *ring;
+       odp_time_t ts_val;
+       odp_time_t *ts = NULL;
        char *buf;
        uint32_t slot_id;
        int i;
@@ -628,12 +654,20 @@ static inline int netmap_recv_desc(pktio_entry_t 
*pktio_entry,
        int num_rx = 0;
        int num_rings = desc->last_rx_ring - desc->first_rx_ring + 1;
 
+       if (pktio_entry->s.config.pktin.bit.ts_all ||
+           pktio_entry->s.config.pktin.bit.ts_ptp)
+               ts = &ts_val;
+
        for (i = 0; i < num_rings && num_rx != num; i++) {
                if (ring_id > desc->last_rx_ring)
                        ring_id = desc->first_rx_ring;
 
                ring = NETMAP_RXRING(desc->nifp, ring_id);
 
+               /* Take timestamp beforehand per ring to improve performance */
+               if (ts != NULL)
+                       ts_val = odp_time_global();
+
                while (!nm_ring_empty(ring) && num_rx != num) {
                        slot_id = ring->cur;
                        buf = NETMAP_BUF(ring, ring->slot[slot_id].buf_idx);
@@ -641,7 +675,8 @@ static inline int netmap_recv_desc(pktio_entry_t 
*pktio_entry,
                        odp_prefetch(buf);
 
                        if (!netmap_pkt_to_odp(pktio_entry, &pkt_table[num_rx],
-                                              buf, ring->slot[slot_id].len))
+                                              buf, ring->slot[slot_id].len,
+                                              ts))
                                num_rx++;
 
                        ring->cur = nm_ring_next(ring, slot_id);
diff --git a/platform/linux-generic/pktio/pcap.c 
b/platform/linux-generic/pktio/pcap.c
index a47d2cc..2b5a63c 100644
--- a/platform/linux-generic/pktio/pcap.c
+++ b/platform/linux-generic/pktio/pcap.c
@@ -211,6 +211,8 @@ static int pcapif_recv_pkt(pktio_entry_t *pktio_entry, 
odp_packet_t pkts[],
        odp_packet_hdr_t *pkt_hdr;
        uint32_t pkt_len;
        pkt_pcap_t *pcap = &pktio_entry->s.pkt_pcap;
+       odp_time_t ts_val;
+       odp_time_t *ts = NULL;
 
        if (pktio_entry->s.state != STATE_STARTED)
                return 0;
@@ -218,6 +220,10 @@ static int pcapif_recv_pkt(pktio_entry_t *pktio_entry, 
odp_packet_t pkts[],
        if (!pcap->rx)
                return 0;
 
+       if (pktio_entry->s.config.pktin.bit.ts_all ||
+           pktio_entry->s.config.pktin.bit.ts_ptp)
+               ts = &ts_val;
+
        pkt = ODP_PACKET_INVALID;
        pkt_len = 0;
 
@@ -240,6 +246,9 @@ static int pcapif_recv_pkt(pktio_entry_t *pktio_entry, 
odp_packet_t pkts[],
                if (ret != 1)
                        break;
 
+               if (ts != NULL)
+                       ts_val = odp_time_global();
+
                pkt_hdr = odp_packet_hdr(pkt);
 
                if (!odp_packet_pull_tail(pkt, pkt_len - hdr->caplen)) {
@@ -256,6 +265,8 @@ static int pcapif_recv_pkt(pktio_entry_t *pktio_entry, 
odp_packet_t pkts[],
                packet_parse_l2(pkt_hdr);
                pktio_entry->s.stats.in_octets += pkt_hdr->frame_len;
 
+               packet_set_ts(pkt_hdr, ts);
+
                pkts[i] = pkt;
                pkt = ODP_PACKET_INVALID;
 
@@ -331,6 +342,21 @@ static int pcapif_mac_addr_get(pktio_entry_t *pktio_entry 
ODP_UNUSED,
        return ODPH_ETHADDR_LEN;
 }
 
+static int pcapif_capability(pktio_entry_t *pktio_entry ODP_UNUSED,
+                            odp_pktio_capability_t *capa)
+{
+       memset(capa, 0, sizeof(odp_pktio_capability_t));
+
+       capa->max_input_queues  = 1;
+       capa->max_output_queues = 1;
+       capa->set_op.op.promisc_mode = 1;
+
+       odp_pktio_config_init(&capa->config);
+       capa->config.pktin.bit.ts_all = 1;
+       capa->config.pktin.bit.ts_ptp = 1;
+       return 0;
+}
+
 static int pcapif_promisc_mode_set(pktio_entry_t *pktio_entry,
                                   odp_bool_t enable)
 {
@@ -406,7 +432,7 @@ const pktio_if_ops_t pcap_pktio_ops = {
        .promisc_mode_set = pcapif_promisc_mode_set,
        .promisc_mode_get = pcapif_promisc_mode_get,
        .mac_get = pcapif_mac_addr_get,
-       .capability = NULL,
+       .capability = pcapif_capability,
        .pktin_ts_res = NULL,
        .pktin_ts_from_ns = NULL,
        .config = NULL,
diff --git a/platform/linux-generic/pktio/socket.c 
b/platform/linux-generic/pktio/socket.c
index e28fd07..da5c4ec 100644
--- a/platform/linux-generic/pktio/socket.c
+++ b/platform/linux-generic/pktio/socket.c
@@ -610,6 +610,8 @@ static int sock_mmsg_recv(pktio_entry_t *pktio_entry,
                          odp_packet_t pkt_table[], unsigned len)
 {
        pkt_sock_t *pkt_sock = &pktio_entry->s.pkt_sock;
+       odp_time_t ts_val;
+       odp_time_t *ts = NULL;
        const int sockfd = pkt_sock->sockfd;
        int msgvec_len;
        struct mmsghdr msgvec[ODP_PACKET_SOCKET_MAX_BURST_RX];
@@ -622,6 +624,10 @@ static int sock_mmsg_recv(pktio_entry_t *pktio_entry,
        if (odp_unlikely(len > ODP_PACKET_SOCKET_MAX_BURST_RX))
                return -1;
 
+       if (pktio_entry->s.config.pktin.bit.ts_all ||
+           pktio_entry->s.config.pktin.bit.ts_ptp)
+               ts = &ts_val;
+
        memset(msgvec, 0, sizeof(msgvec));
        recv_cache = pkt_sock->cache_ptr;
 
@@ -639,6 +645,10 @@ static int sock_mmsg_recv(pktio_entry_t *pktio_entry,
 
                recv_msgs = recvmmsg(sockfd, msgvec, msgvec_len,
                                     MSG_DONTWAIT, NULL);
+
+               if (ts != NULL)
+                       ts_val = odp_time_global();
+
                for (i = 0; i < recv_msgs; i++) {
                        void *base = msgvec[i].msg_hdr.msg_iov->iov_base;
                        struct ethhdr *eth_hdr = base;
@@ -650,7 +660,7 @@ static int sock_mmsg_recv(pktio_entry_t *pktio_entry,
                                continue;
 
                        ret = _odp_packet_cls_enq(pktio_entry, base,
-                                                 pkt_len, NULL,
+                                                 pkt_len, ts,
                                                  &pkt_table[nb_rx]);
                        if (ret)
                                nb_rx++;
@@ -677,6 +687,9 @@ static int sock_mmsg_recv(pktio_entry_t *pktio_entry,
                recv_msgs = recvmmsg(sockfd, msgvec, msgvec_len,
                                     MSG_DONTWAIT, NULL);
 
+               if (ts != NULL)
+                       ts_val = odp_time_global();
+
                for (i = 0; i < recv_msgs; i++) {
                        void *base = msgvec[i].msg_hdr.msg_iov->iov_base;
                        struct ethhdr *eth_hdr = base;
@@ -693,8 +706,9 @@ static int sock_mmsg_recv(pktio_entry_t *pktio_entry,
                        odp_packet_pull_tail(pkt_table[i],
                                             odp_packet_len(pkt_table[i]) -
                                             msgvec[i].msg_len);
-
                        packet_parse_l2(pkt_hdr);
+                       packet_set_ts(pkt_hdr, ts);
+
                        pkt_table[nb_rx] = pkt_table[i];
                        nb_rx++;
                }
@@ -813,6 +827,21 @@ static int sock_link_status(pktio_entry_t *pktio_entry)
                              pktio_entry->s.name);
 }
 
+static int sock_capability(pktio_entry_t *pktio_entry ODP_UNUSED,
+                          odp_pktio_capability_t *capa)
+{
+       memset(capa, 0, sizeof(odp_pktio_capability_t));
+
+       capa->max_input_queues  = 1;
+       capa->max_output_queues = 1;
+       capa->set_op.op.promisc_mode = 1;
+
+       odp_pktio_config_init(&capa->config);
+       capa->config.pktin.bit.ts_all = 1;
+       capa->config.pktin.bit.ts_ptp = 1;
+       return 0;
+}
+
 static int sock_stats(pktio_entry_t *pktio_entry,
                      odp_pktio_stats_t *stats)
 {
@@ -856,7 +885,7 @@ const pktio_if_ops_t sock_mmsg_pktio_ops = {
        .promisc_mode_get = sock_promisc_mode_get,
        .mac_get = sock_mac_addr_get,
        .link_status = sock_link_status,
-       .capability = NULL,
+       .capability = sock_capability,
        .pktin_ts_res = NULL,
        .pktin_ts_from_ns = NULL,
        .config = NULL,
diff --git a/platform/linux-generic/pktio/socket_mmap.c 
b/platform/linux-generic/pktio/socket_mmap.c
index 5cd1ad6..8fadc5a 100644
--- a/platform/linux-generic/pktio/socket_mmap.c
+++ b/platform/linux-generic/pktio/socket_mmap.c
@@ -116,6 +116,8 @@ static inline unsigned pkt_mmap_v2_rx(pktio_entry_t 
*pktio_entry,
                                      unsigned char if_mac[])
 {
        union frame_map ppd;
+       odp_time_t ts_val;
+       odp_time_t *ts = NULL;
        unsigned frame_num, next_frame_num;
        uint8_t *pkt_buf;
        int pkt_len;
@@ -125,6 +127,10 @@ static inline unsigned pkt_mmap_v2_rx(pktio_entry_t 
*pktio_entry,
        struct ring *ring;
        int ret;
 
+       if (pktio_entry->s.config.pktin.bit.ts_all ||
+           pktio_entry->s.config.pktin.bit.ts_ptp)
+               ts = &ts_val;
+
        ring  = &pkt_sock->rx_ring;
        frame_num = ring->frame_num;
 
@@ -132,6 +138,9 @@ static inline unsigned pkt_mmap_v2_rx(pktio_entry_t 
*pktio_entry,
                if (!mmap_rx_kernel_ready(ring->rd[frame_num].iov_base))
                        break;
 
+               if (ts != NULL)
+                       ts_val = odp_time_global();
+
                ppd.raw = ring->rd[frame_num].iov_base;
                next_frame_num = (frame_num + 1) % ring->rd_num;
 
@@ -149,7 +158,7 @@ static inline unsigned pkt_mmap_v2_rx(pktio_entry_t 
*pktio_entry,
 
                if (pktio_cls_enabled(pktio_entry)) {
                        ret = _odp_packet_cls_enq(pktio_entry, pkt_buf,
-                                                 pkt_len, NULL,
+                                                 pkt_len, ts,
                                                  &pkt_table[nb_rx]);
                        if (ret)
                                nb_rx++;
@@ -173,6 +182,8 @@ static inline unsigned pkt_mmap_v2_rx(pktio_entry_t 
*pktio_entry,
                        }
 
                        packet_parse_l2(hdr);
+                       packet_set_ts(hdr, ts);
+
                        nb_rx++;
                }
 
@@ -582,6 +593,21 @@ static int sock_mmap_link_status(pktio_entry_t 
*pktio_entry)
                              pktio_entry->s.name);
 }
 
+static int sock_mmap_capability(pktio_entry_t *pktio_entry ODP_UNUSED,
+                               odp_pktio_capability_t *capa)
+{
+       memset(capa, 0, sizeof(odp_pktio_capability_t));
+
+       capa->max_input_queues  = 1;
+       capa->max_output_queues = 1;
+       capa->set_op.op.promisc_mode = 1;
+
+       odp_pktio_config_init(&capa->config);
+       capa->config.pktin.bit.ts_all = 1;
+       capa->config.pktin.bit.ts_ptp = 1;
+       return 0;
+}
+
 static int sock_mmap_stats(pktio_entry_t *pktio_entry,
                           odp_pktio_stats_t *stats)
 {
@@ -625,7 +651,7 @@ const pktio_if_ops_t sock_mmap_pktio_ops = {
        .promisc_mode_get = sock_mmap_promisc_mode_get,
        .mac_get = sock_mmap_mac_addr_get,
        .link_status = sock_mmap_link_status,
-       .capability = NULL,
+       .capability = sock_mmap_capability,
        .pktin_ts_res = NULL,
        .pktin_ts_from_ns = NULL,
        .config = NULL,
diff --git a/platform/linux-generic/pktio/tap.c 
b/platform/linux-generic/pktio/tap.c
index e02d311..8baf1f3 100644
--- a/platform/linux-generic/pktio/tap.c
+++ b/platform/linux-generic/pktio/tap.c
@@ -179,11 +179,11 @@ static int tap_pktio_close(pktio_entry_t *pktio_entry)
        return ret;
 }
 
-static odp_packet_t pack_odp_pkt(odp_pool_t pool,
-                                const void *data,
-                                unsigned int len)
+static odp_packet_t pack_odp_pkt(odp_pool_t pool, const void *data,
+                                unsigned int len, odp_time_t *ts)
 {
        odp_packet_t pkt;
+       odp_packet_hdr_t *pkt_hdr;
 
        pkt = packet_alloc(pool, len, 1);
 
@@ -196,7 +196,9 @@ static odp_packet_t pack_odp_pkt(odp_pool_t pool,
                return ODP_PACKET_INVALID;
        }
 
-       packet_parse_l2(odp_packet_hdr(pkt));
+       pkt_hdr = odp_packet_hdr(pkt);
+       packet_parse_l2(pkt_hdr);
+       packet_set_ts(pkt_hdr, ts);
 
        return pkt;
 }
@@ -208,18 +210,27 @@ static int tap_pktio_recv(pktio_entry_t *pktio_entry, 
odp_packet_t pkts[],
        unsigned i;
        uint8_t buf[BUF_SIZE];
        pkt_tap_t *tap = &pktio_entry->s.pkt_tap;
+       odp_time_t ts_val;
+       odp_time_t *ts = NULL;
+
+       if (pktio_entry->s.config.pktin.bit.ts_all ||
+           pktio_entry->s.config.pktin.bit.ts_ptp)
+               ts = &ts_val;
 
        for (i = 0; i < len; i++) {
                do {
                        retval = read(tap->fd, buf, BUF_SIZE);
                } while (retval < 0 && errno == EINTR);
 
+               if (ts != NULL)
+                       ts_val = odp_time_global();
+
                if (retval < 0) {
                        __odp_errno = errno;
                        break;
                }
 
-               pkts[i] = pack_odp_pkt(tap->pool, buf, retval);
+               pkts[i] = pack_odp_pkt(tap->pool, buf, retval, ts);
                if (pkts[i] == ODP_PACKET_INVALID)
                        break;
        }
@@ -310,6 +321,21 @@ static int tap_mac_addr_get(pktio_entry_t *pktio_entry, 
void *mac_addr)
        return ETH_ALEN;
 }
 
+static int tap_capability(pktio_entry_t *pktio_entry ODP_UNUSED,
+                         odp_pktio_capability_t *capa)
+{
+       memset(capa, 0, sizeof(odp_pktio_capability_t));
+
+       capa->max_input_queues  = 1;
+       capa->max_output_queues = 1;
+       capa->set_op.op.promisc_mode = 1;
+
+       odp_pktio_config_init(&capa->config);
+       capa->config.pktin.bit.ts_all = 1;
+       capa->config.pktin.bit.ts_ptp = 1;
+       return 0;
+}
+
 const pktio_if_ops_t tap_pktio_ops = {
        .init_global = NULL,
        .init_local = NULL,
@@ -324,6 +350,7 @@ const pktio_if_ops_t tap_pktio_ops = {
        .promisc_mode_set = tap_promisc_mode_set,
        .promisc_mode_get = tap_promisc_mode_get,
        .mac_get = tap_mac_addr_get,
+       .capability = tap_capability,
        .pktin_ts_res = NULL,
        .pktin_ts_from_ns = NULL,
        .config = NULL
-- 
1.9.1

_______________________________________________
lng-odp mailing list
[email protected]
https://lists.linaro.org/mailman/listinfo/lng-odp

Reply via email to