From 72f6ca05ac81d0ca5e7eb93c6ffe7a93648c2b00 Mon Sep 17 00:00:00 2001 From: Andriy Berestovskyy Date: Fri, 4 Sep 2015 12:18:59 +0200 Subject: [PATCH] DPDK: update to DPDK 2.1 - support both DPDK 2.0 and 2.1 - use mbuf priv_size for vr_packet - use new packet type flags - use rte_pktmbuf_mtod_offset() - count out HW XEC counter from ierrors - use RTE_PORT_STATS_COLLECT Change-Id: I2015961e95bb02a78b7419f7098a1e48bd622356 Closes-bug: 1430629 --- dpdk/dpdk_vrouter.c | 30 ++++++++++++++++++++--- dpdk/vr_dpdk_ethdev.c | 19 +++++++++++--- dpdk/vr_dpdk_host.c | 4 +-- dpdk/vr_dpdk_interface.c | 29 ++++++++++++++++++++++ dpdk/vr_dpdk_knidev.c | 4 +-- dpdk/vr_dpdk_usocket.c | 2 +- dpdk/vr_dpdk_virtio.c | 6 ++--- include/vr_dpdk.h | 13 +++------- include/vr_dpdk_compat.h | 53 ++++++++++++++++++++++++++++++++++++++++ 9 files changed, 135 insertions(+), 25 deletions(-) create mode 100644 include/vr_dpdk_compat.h diff --git a/dpdk/dpdk_vrouter.c b/dpdk/dpdk_vrouter.c index abf78aa6e..6d9759045 100644 --- a/dpdk/dpdk_vrouter.c +++ b/dpdk/dpdk_vrouter.c @@ -65,7 +65,27 @@ static int dpdk_argc = RTE_DIM(dpdk_argv) - 10; /* Timestamp logger */ static FILE *timestamp_log_stream; -/* Pktmbuf constructor with vr_packet support */ +#if (RTE_VERSION >= RTE_VERSION_NUM(2, 1, 0, 0)) +/* A packet mbuf pool constructor with vr_packet support */ +void vr_dpdk_pktmbuf_pool_init(struct rte_mempool *mp, void *opaque_arg) +{ + struct rte_pktmbuf_pool_private priv; + + /* Set private mbuf size for vr_packet. */ + priv.mbuf_data_room_size = mp->elt_size - sizeof(struct rte_mbuf) + - sizeof(struct vr_packet); + priv.mbuf_priv_size = sizeof(struct vr_packet); + + rte_pktmbuf_pool_init(mp, &priv); +} +#else +void vr_dpdk_pktmbuf_pool_init(struct rte_mempool *mp, void *opaque_arg) +{ + rte_pktmbuf_pool_init(mp, opaque_arg); +} +#endif + +/* The packet mbuf constructor with vr_packet support */ void vr_dpdk_pktmbuf_init(struct rte_mempool *mp, void *opaque_arg, void *_m, unsigned i) { @@ -73,6 +93,7 @@ vr_dpdk_pktmbuf_init(struct rte_mempool *mp, void *opaque_arg, void *_m, unsigne struct vr_packet *pkt; rte_pktmbuf_init(mp, opaque_arg, _m, i); +#if (RTE_VERSION < RTE_VERSION_NUM(2, 1, 0, 0)) /* decrease rte packet size to fit vr_packet struct */ m->buf_len -= sizeof(struct vr_packet); RTE_VERIFY(0 < m->buf_len); @@ -80,6 +101,7 @@ vr_dpdk_pktmbuf_init(struct rte_mempool *mp, void *opaque_arg, void *_m, unsigne /* start of buffer is just after vr_packet structure */ m->buf_addr += sizeof(struct vr_packet); m->buf_physaddr += sizeof(struct vr_packet); +#endif /* basic vr_packet initialization */ pkt = vr_dpdk_mbuf_to_pkt(m); @@ -95,7 +117,7 @@ dpdk_mempools_create(void) vr_dpdk.rss_mempool = rte_mempool_create("rss_mempool", VR_DPDK_RSS_MEMPOOL_SZ, VR_DPDK_MBUF_SZ, VR_DPDK_RSS_MEMPOOL_CACHE_SZ, sizeof(struct rte_pktmbuf_pool_private), - rte_pktmbuf_pool_init, NULL, vr_dpdk_pktmbuf_init, NULL, + vr_dpdk_pktmbuf_pool_init, NULL, vr_dpdk_pktmbuf_init, NULL, rte_socket_id(), 0); if (vr_dpdk.rss_mempool == NULL) { RTE_LOG(CRIT, VROUTER, "Error creating RSS mempool: %s (%d)\n", @@ -107,7 +129,7 @@ dpdk_mempools_create(void) vr_dpdk.frag_direct_mempool = rte_mempool_create("frag_direct_mempool", VR_DPDK_FRAG_DIRECT_MEMPOOL_SZ, VR_DPDK_FRAG_DIRECT_MBUF_SZ, VR_DPDK_FRAG_DIRECT_MEMPOOL_CACHE_SZ, - sizeof(struct rte_pktmbuf_pool_private), rte_pktmbuf_pool_init, + sizeof(struct rte_pktmbuf_pool_private), vr_dpdk_pktmbuf_pool_init, NULL, vr_dpdk_pktmbuf_init, NULL, rte_socket_id(), 0); if (vr_dpdk.frag_direct_mempool == NULL) { RTE_LOG(CRIT, VROUTER, "Error creating FRAG_DIRECT mempool: %s (%d)\n", @@ -141,7 +163,7 @@ dpdk_mempools_create(void) vr_dpdk.free_mempools[i] = rte_mempool_create(mempool_name, VR_DPDK_VM_MEMPOOL_SZ, VR_DPDK_MBUF_SZ, VR_DPDK_VM_MEMPOOL_CACHE_SZ, sizeof(struct rte_pktmbuf_pool_private), - rte_pktmbuf_pool_init, NULL, vr_dpdk_pktmbuf_init, NULL, + vr_dpdk_pktmbuf_pool_init, NULL, vr_dpdk_pktmbuf_init, NULL, rte_socket_id(), 0); if (vr_dpdk.free_mempools[i] == NULL) { RTE_LOG(CRIT, VROUTER, "Error creating VM mempool %d: %s (%d)\n", diff --git a/dpdk/vr_dpdk_ethdev.c b/dpdk/vr_dpdk_ethdev.c index de9bc42e4..6f5364647 100644 --- a/dpdk/vr_dpdk_ethdev.c +++ b/dpdk/vr_dpdk_ethdev.c @@ -704,7 +704,9 @@ dpdk_mbuf_rss_hash(struct rte_mbuf *mbuf) /* TODO: IPv6 support */ /* TODO: VLAN support */ if (likely(eth_hdr->ether_type == rte_cpu_to_be_16(ETHER_TYPE_IPv4))) { - mbuf->ol_flags |= PKT_RX_IPV4_HDR; +#if (RTE_VERSION >= RTE_VERSION_NUM(2, 1, 0, 0)) + mbuf->packet_type |= RTE_PTYPE_L3_IPV4; +#endif ipv4_hdr = (struct ipv4_hdr *)((uintptr_t)eth_hdr + sizeof(struct ether_hdr)); ipv4_addr_ptr = (uint64_t *)((uintptr_t)ipv4_hdr @@ -723,8 +725,17 @@ dpdk_mbuf_rss_hash(struct rte_mbuf *mbuf) !vr_ip_fragment((struct vr_ip *)ipv4_hdr))) { switch (ipv4_hdr->next_proto_id) { case IPPROTO_TCP: +#if (RTE_VERSION >= RTE_VERSION_NUM(2, 1, 0, 0)) + mbuf->packet_type |= RTE_PTYPE_L4_TCP; +#endif + l4_ptr = (uint32_t *)((uintptr_t)ipv4_hdr + iph_len); + + hash = rte_hash_crc_4byte(*l4_ptr, hash); + break; case IPPROTO_UDP: - mbuf->ol_flags |= PKT_RX_IPV4_HDR_EXT; +#if (RTE_VERSION >= RTE_VERSION_NUM(2, 1, 0, 0)) + mbuf->packet_type |= RTE_PTYPE_L4_UDP; +#endif l4_ptr = (uint32_t *)((uintptr_t)ipv4_hdr + iph_len); hash = rte_hash_crc_4byte(*l4_ptr, hash); @@ -754,8 +765,8 @@ vr_dpdk_ethdev_rx_emulate(struct vr_interface *vif, struct rte_mbuf *pkts[VR_DPD /* prefetch the mbufs */ for (i = 0; i < nb_pkts; i++) { - rte_prefetch0(rte_pktmbuf_mtod(pkts[i], void *)); - rte_prefetch0(rte_pktmbuf_mtod(pkts[i], uint8_t *) + RTE_CACHE_LINE_SIZE); + rte_prefetch0(rte_pktmbuf_mtod(pkts[i], uint8_t *)); + rte_prefetch0(rte_pktmbuf_mtod_offset(pkts[i], uint8_t *, RTE_CACHE_LINE_SIZE)); } /* emulate VLAN stripping if needed */ diff --git a/dpdk/vr_dpdk_host.c b/dpdk/vr_dpdk_host.c index 13c2ce1bc..23a591545 100644 --- a/dpdk/vr_dpdk_host.c +++ b/dpdk/vr_dpdk_host.c @@ -323,7 +323,7 @@ dpdk_pktmbuf_copy_bits(const struct rte_mbuf *mbuf, int offset, do { if (offset < rte_pktmbuf_data_len(mbuf)) { /* copy a piece of data */ - from = (void *)(rte_pktmbuf_mtod(mbuf, uintptr_t) + offset); + from = (void *)(rte_pktmbuf_mtod_offset(mbuf, uintptr_t, offset)); copy = rte_pktmbuf_data_len(mbuf) - offset; if (copy > len) copy = len; @@ -640,7 +640,7 @@ dpdk_pheader_pointer(struct vr_packet *pkt, unsigned short hdr_len, void *buf) int len = rte_pktmbuf_data_len(m) - offset; void *tmp_buf = buf; - rte_memcpy(tmp_buf, rte_pktmbuf_mtod(m, char *) + offset, len); + rte_memcpy(tmp_buf, rte_pktmbuf_mtod_offset(m, char *, offset), len); hdr_len -= len; tmp_buf = (void *)((uintptr_t)tmp_buf + len); diff --git a/dpdk/vr_dpdk_interface.c b/dpdk/vr_dpdk_interface.c index cc2c1e0f4..fa15c5371 100644 --- a/dpdk/vr_dpdk_interface.c +++ b/dpdk/vr_dpdk_interface.c @@ -1303,6 +1303,35 @@ dpdk_dev_stats_update(struct vr_interface *vif, unsigned lcore_id) if (rte_eth_stats_get(port_id, ð_stats) != 0) return; +#if (RTE_VERSION >= RTE_VERSION_NUM(2, 1, 0, 0)) + /* + * TODO: In DPDK 2.1 ierrors includes XEC (l3_l4_xsum_error) counter. + * The counter seems to include no check sum UDP packets. As a workaround + * we count out the XEC from ierrors using rte_eth_xstats_get(). + */ + struct rte_eth_xstats *eth_xstats = NULL; + int nb_xstats, i; + nb_xstats = rte_eth_xstats_get(port_id, eth_xstats, 0); + if (nb_xstats > 0) { + eth_xstats = rte_malloc("xstats", + sizeof(*eth_xstats)*nb_xstats, 0); + if (eth_xstats != NULL) { + if (rte_eth_xstats_get(port_id, eth_xstats, nb_xstats) + == nb_xstats) { + /* look for XEC counter */ + for (i = 0; i < nb_xstats; i++) { + if (strncmp(eth_xstats[i].name, "l3_l4_xsum_error", + sizeof(eth_xstats[i].name)) == 0) { + eth_stats.ierrors -= eth_xstats[i].value; + break; + } + } + } + rte_free(eth_xstats); + } + } +#endif + /* per-lcore device counters */ lcore = vr_dpdk.lcores[lcore_id]; if (lcore == NULL) diff --git a/dpdk/vr_dpdk_knidev.c b/dpdk/vr_dpdk_knidev.c index 4555f1037..9878950cd 100644 --- a/dpdk/vr_dpdk_knidev.c +++ b/dpdk/vr_dpdk_knidev.c @@ -24,7 +24,7 @@ /* * KNI Reader */ -#if DPDK_KNIDEV_READER_STATS_COLLECT == 1 +#ifdef RTE_PORT_STATS_COLLECT #define DPDK_KNIDEV_READER_STATS_PKTS_IN_ADD(port, val) \ port->stats.n_pkts_in += val @@ -121,7 +121,7 @@ dpdk_knidev_reader_stats_read(void *port, /* * KNI Writer */ -#if DPDK_KNIDEV_WRITER_STATS_COLLECT == 1 +#ifdef RTE_PORT_STATS_COLLECT #define DPDK_KNIDEV_WRITER_STATS_PKTS_IN_ADD(port, val) \ port->stats.n_pkts_in += val diff --git a/dpdk/vr_dpdk_usocket.c b/dpdk/vr_dpdk_usocket.c index 5971b4f07..d57a4338e 100644 --- a/dpdk/vr_dpdk_usocket.c +++ b/dpdk/vr_dpdk_usocket.c @@ -785,7 +785,7 @@ usock_alloc(unsigned short proto, unsigned short type) usockp->usock_mbuf_pool = rte_mempool_create("packet_mbuf_pool", PKT0_MBUF_POOL_SIZE, PKT0_MBUF_PACKET_SIZE, PKT0_MBUF_POOL_CACHE_SZ, sizeof(struct rte_pktmbuf_pool_private), - rte_pktmbuf_pool_init, NULL, vr_dpdk_pktmbuf_init, NULL, + vr_dpdk_pktmbuf_pool_init, NULL, vr_dpdk_pktmbuf_init, NULL, rte_socket_id(), 0); if (!usockp->usock_mbuf_pool) goto error_exit; diff --git a/dpdk/vr_dpdk_virtio.c b/dpdk/vr_dpdk_virtio.c index 84b81c2a8..23a91088d 100644 --- a/dpdk/vr_dpdk_virtio.c +++ b/dpdk/vr_dpdk_virtio.c @@ -469,7 +469,7 @@ vr_dpdk_guest_phys_to_host_virt(vr_uvh_client_t *vru_cl, uint64_t paddr) return NULL; } -#if DPDK_VIRTIO_READER_STATS_COLLECT == 1 +#ifdef RTE_PORT_STATS_COLLECT #define DPDK_VIRTIO_READER_STATS_PKTS_IN_ADD(port, val) \ port->stats.n_pkts_in += val @@ -626,7 +626,7 @@ dpdk_virtio_from_vm_rx(void *port, struct rte_mbuf **pkts, uint32_t max_pkts) return pkts_sent; } -#if DPDK_VIRTIO_WRITER_STATS_COLLECT == 1 +#ifdef RTE_PORT_STATS_COLLECT #define DPDK_VIRTIO_WRITER_STATS_PKTS_IN_ADD(port, val) \ port->stats.n_pkts_in += val @@ -754,7 +754,7 @@ dpdk_virtio_dev_to_vm_tx_burst(struct dpdk_virtio_writer *p, while (total_copied < pkt_len) { /* Copy mbuf data to buffer */ rte_memcpy((void *)(uintptr_t)(buff_addr + vb_offset), - rte_pktmbuf_mtod(buff, const void *) + offset, + rte_pktmbuf_mtod_offset(buff, const void *, offset), len_to_cpy); offset += len_to_cpy; diff --git a/include/vr_dpdk.h b/include/vr_dpdk.h index b464389a5..dff1ae8ed 100644 --- a/include/vr_dpdk.h +++ b/include/vr_dpdk.h @@ -18,6 +18,7 @@ #define _VR_DPDK_H_ #include "vr_os.h" +#include "vr_dpdk_compat.h" #include "vr_interface.h" #include "vr_packet.h" #include "vr_fragment.h" @@ -477,14 +478,6 @@ struct vr_dpdk_global { extern struct vr_dpdk_global vr_dpdk; -/** - * Enable sent/received/dropped packets statistics - */ -#define DPDK_KNIDEV_WRITER_STATS_COLLECT 1 -#define DPDK_KNIDEV_READER_STATS_COLLECT 1 -#define DPDK_VIRTIO_WRITER_STATS_COLLECT 1 -#define DPDK_VIRTIO_READER_STATS_COLLECT 1 - /* * rte_mbuf <=> vr_packet conversion * @@ -540,7 +533,9 @@ vr_dpdk_mbuf_reset(struct vr_packet *pkt) /* * dpdk_vrouter.c */ -/* pktmbuf constructor with vr_packet support */ +/* A packet mbuf pool constructor with vr_packet support */ +void vr_dpdk_pktmbuf_pool_init(struct rte_mempool *mp, void *opaque_arg); +/* The packet mbuf constructor with vr_packet support */ void vr_dpdk_pktmbuf_init(struct rte_mempool *mp, void *opaque_arg, void *_m, unsigned i); /* Check if the stop flag is set */ int vr_dpdk_is_stop_flag_set(void); diff --git a/include/vr_dpdk_compat.h b/include/vr_dpdk_compat.h new file mode 100644 index 000000000..33ccc1dd4 --- /dev/null +++ b/include/vr_dpdk_compat.h @@ -0,0 +1,53 @@ +/* + * vr_dpdk_compat.h - DPDK compatibility definitions + * + * Copyright (c) 2015 Semihalf. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation version 2. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include + +#ifndef __VRDPDKCOMPAT_H__ +#define __VRDPDKCOMPAT_H__ + +/* + * DPDK 2.1 + */ +#if (RTE_VERSION >= RTE_VERSION_NUM(2, 1, 0, 0)) + +/* + * DPDK 2.0 + */ +#elif (RTE_VERSION >= RTE_VERSION_NUM(2, 0, 0, 0)) + +/* Enable port statistics. */ +#define RTE_PORT_STATS_COLLECT + +/** + * A macro that points to an offset into the data in the mbuf. + * + * The returned pointer is cast to type t. Before using this + * function, the user must ensure that the first segment is large + * enough to accommodate its data. + * + * @param m + * The packet mbuf. + * @param o + * The offset into the mbuf data. + * @param t + * The type to cast the result into. + */ +#define rte_pktmbuf_mtod_offset(m, t, o) \ + ((t)((char *)(m)->buf_addr + (m)->data_off + (o))) + +#endif /* RTE_VERSION */ + +#endif /* __VRDPDKCOMPAT_H__ */