From patchwork Fri Apr 15 07:21:14 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Elo, Matias \(Nokia - FI/Espoo\)" X-Patchwork-Id: 65882 Delivered-To: patch@linaro.org Received: by 10.140.93.198 with SMTP id d64csp1028383qge; Fri, 15 Apr 2016 00:28:01 -0700 (PDT) X-Received: by 10.141.4.69 with SMTP id g66mr24880031qhd.31.1460705281937; Fri, 15 Apr 2016 00:28:01 -0700 (PDT) Return-Path: Received: from lists.linaro.org (lists.linaro.org. [54.225.227.206]) by mx.google.com with ESMTP id k9si15335771qge.20.2016.04.15.00.28.01; Fri, 15 Apr 2016 00:28:01 -0700 (PDT) Received-SPF: pass (google.com: domain of lng-odp-bounces@lists.linaro.org designates 54.225.227.206 as permitted sender) client-ip=54.225.227.206; Authentication-Results: mx.google.com; spf=pass (google.com: domain of lng-odp-bounces@lists.linaro.org designates 54.225.227.206 as permitted sender) smtp.mailfrom=lng-odp-bounces@lists.linaro.org; dmarc=fail (p=NONE dis=NONE) header.from=nokia.com Received: by lists.linaro.org (Postfix, from userid 109) id E426762CE6; Fri, 15 Apr 2016 07:28:00 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on ip-10-142-244-252 X-Spam-Level: X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, URIBL_BLOCKED autolearn=disabled version=3.4.0 Received: from [127.0.0.1] (localhost [127.0.0.1]) by lists.linaro.org (Postfix) with ESMTP id D9A0E6752E; Fri, 15 Apr 2016 07:22:09 +0000 (UTC) X-Original-To: lng-odp@lists.linaro.org Delivered-To: lng-odp@lists.linaro.org Received: by lists.linaro.org (Postfix, from userid 109) id F37CF67543; Fri, 15 Apr 2016 07:22:00 +0000 (UTC) Received: from demumfd001.nsn-inter.net (demumfd001.nsn-inter.net [93.183.12.32]) by lists.linaro.org (Postfix) with ESMTPS id 2ED2067447 for ; Fri, 15 Apr 2016 07:21:21 +0000 (UTC) Received: from demuprx016.emea.nsn-intra.net ([10.150.129.55]) by demumfd001.nsn-inter.net (8.15.2/8.15.2) with ESMTPS id u3F7LJ57027146 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Fri, 15 Apr 2016 07:21:20 GMT Received: from 10.144.19.15 ([10.144.104.112]) by demuprx016.emea.nsn-intra.net (8.12.11.20060308/8.12.11) with ESMTP id u3F7LEvb001646 (version=TLSv1/SSLv3 cipher=AES128-SHA bits=128 verify=NO) for ; Fri, 15 Apr 2016 09:21:19 +0200 From: Matias Elo To: lng-odp@lists.linaro.org Date: Fri, 15 Apr 2016 10:21:14 +0300 Message-Id: <1460704874-21163-12-git-send-email-matias.elo@nokia.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1460704874-21163-1-git-send-email-matias.elo@nokia.com> References: <1460704874-21163-1-git-send-email-matias.elo@nokia.com> X-purgate-type: clean X-purgate-Ad: Categorized by eleven eXpurgate (R) http://www.eleven.de X-purgate: clean X-purgate: This mail is considered clean (visit http://www.eleven.de for further information) X-purgate-size: 23238 X-purgate-ID: 151667::1460704880-00001B3D-C71C23CF/0/0 X-Topics: patch Subject: [lng-odp] [API-NEXT PATCH 11/11] linux-generic: pktio: add pktin timestamping support X-BeenThere: lng-odp@lists.linaro.org X-Mailman-Version: 2.1.16 Precedence: list List-Id: "The OpenDataPlane \(ODP\) List" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: lng-odp-bounces@lists.linaro.org Sender: "lng-odp" 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 --- 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