From 9fd72e3cbd291f54c3261ddcc0e4d977aec4bb5f Mon Sep 17 00:00:00 2001 From: Jijiang Liu Date: Fri, 5 Feb 2016 15:31:41 +0800 Subject: [PATCH] examples/vhost: add virtio offload Change the codes in vhost sample to test virtio offload feature. These changes include, 1. add two test options: tx-csum and tso. 2. add virtio_tx_offload() function to test vhost TX offload feature for VM to NIC case; however, for VM to VM case, it doesn't need to call this function, the reason is explained in patch 2. Signed-off-by: Jijiang Liu Acked-by: Yuanhan Liu --- examples/vhost/main.c | 105 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 102 insertions(+), 3 deletions(-) diff --git a/examples/vhost/main.c b/examples/vhost/main.c index 43183971c9..e08f451bd2 100644 --- a/examples/vhost/main.c +++ b/examples/vhost/main.c @@ -51,6 +51,9 @@ #include #include #include +#include +#include +#include #include "main.h" @@ -200,6 +203,13 @@ typedef enum { static uint32_t enable_stats = 0; /* Enable retries on RX. */ static uint32_t enable_retry = 1; + +/* Disable TX checksum offload */ +static uint32_t enable_tx_csum; + +/* Disable TSO offload */ +static uint32_t enable_tso; + /* Specify timeout (in useconds) between retries on RX. */ static uint32_t burst_rx_delay_time = BURST_RX_WAIT_US; /* Specify the number of retries on RX. */ @@ -430,6 +440,14 @@ port_init(uint8_t port) if (port >= rte_eth_dev_count()) return -1; + if (enable_tx_csum == 0) + rte_vhost_feature_disable(1ULL << VIRTIO_NET_F_CSUM); + + if (enable_tso == 0) { + rte_vhost_feature_disable(1ULL << VIRTIO_NET_F_HOST_TSO4); + rte_vhost_feature_disable(1ULL << VIRTIO_NET_F_HOST_TSO6); + } + rx_rings = (uint16_t)dev_info.max_rx_queues; /* Configure ethernet device. */ retval = rte_eth_dev_configure(port, rx_rings, tx_rings, &port_conf); @@ -565,7 +583,9 @@ us_vhost_usage(const char *prgname) " --rx-desc-num [0-N]: the number of descriptors on rx, " "used only when zero copy is enabled.\n" " --tx-desc-num [0-N]: the number of descriptors on tx, " - "used only when zero copy is enabled.\n", + "used only when zero copy is enabled.\n" + " --tx-csum [0|1] disable/enable TX checksum offload.\n" + " --tso [0|1] disable/enable TCP segment offload.\n", prgname); } @@ -591,6 +611,8 @@ us_vhost_parse_args(int argc, char **argv) {"zero-copy", required_argument, NULL, 0}, {"rx-desc-num", required_argument, NULL, 0}, {"tx-desc-num", required_argument, NULL, 0}, + {"tx-csum", required_argument, NULL, 0}, + {"tso", required_argument, NULL, 0}, {NULL, 0, 0, 0}, }; @@ -645,6 +667,28 @@ us_vhost_parse_args(int argc, char **argv) } } + /* Enable/disable TX checksum offload. */ + if (!strncmp(long_option[option_index].name, "tx-csum", MAX_LONG_OPT_SZ)) { + ret = parse_num_opt(optarg, 1); + if (ret == -1) { + RTE_LOG(INFO, VHOST_CONFIG, "Invalid argument for tx-csum [0|1]\n"); + us_vhost_usage(prgname); + return -1; + } else + enable_tx_csum = ret; + } + + /* Enable/disable TSO offload. */ + if (!strncmp(long_option[option_index].name, "tso", MAX_LONG_OPT_SZ)) { + ret = parse_num_opt(optarg, 1); + if (ret == -1) { + RTE_LOG(INFO, VHOST_CONFIG, "Invalid argument for tso [0|1]\n"); + us_vhost_usage(prgname); + return -1; + } else + enable_tso = ret; + } + /* Specify the retries delay time (in useconds) on RX. */ if (!strncmp(long_option[option_index].name, "rx-retry-delay", MAX_LONG_OPT_SZ)) { ret = parse_num_opt(optarg, INT32_MAX); @@ -1103,6 +1147,58 @@ find_local_dest(struct virtio_net *dev, struct rte_mbuf *m, return 0; } +static uint16_t +get_psd_sum(void *l3_hdr, uint64_t ol_flags) +{ + if (ol_flags & PKT_TX_IPV4) + return rte_ipv4_phdr_cksum(l3_hdr, ol_flags); + else /* assume ethertype == ETHER_TYPE_IPv6 */ + return rte_ipv6_phdr_cksum(l3_hdr, ol_flags); +} + +static void virtio_tx_offload(struct rte_mbuf *m) +{ + void *l3_hdr; + struct ipv4_hdr *ipv4_hdr = NULL; + struct tcp_hdr *tcp_hdr = NULL; + struct udp_hdr *udp_hdr = NULL; + struct sctp_hdr *sctp_hdr = NULL; + struct ether_hdr *eth_hdr = rte_pktmbuf_mtod(m, struct ether_hdr *); + + l3_hdr = (char *)eth_hdr + m->l2_len; + + if (m->tso_segsz != 0) { + ipv4_hdr = (struct ipv4_hdr *)l3_hdr; + tcp_hdr = (struct tcp_hdr *)((char *)l3_hdr + m->l3_len); + m->ol_flags |= PKT_TX_IP_CKSUM; + ipv4_hdr->hdr_checksum = 0; + tcp_hdr->cksum = get_psd_sum(l3_hdr, m->ol_flags); + return; + } + + if (m->ol_flags & PKT_TX_L4_MASK) { + switch (m->ol_flags & PKT_TX_L4_MASK) { + case PKT_TX_TCP_CKSUM: + tcp_hdr = (struct tcp_hdr *) + ((char *)l3_hdr + m->l3_len); + tcp_hdr->cksum = get_psd_sum(l3_hdr, m->ol_flags); + break; + case PKT_TX_UDP_CKSUM: + udp_hdr = (struct udp_hdr *) + ((char *)l3_hdr + m->l3_len); + udp_hdr->dgram_cksum = get_psd_sum(l3_hdr, m->ol_flags); + break; + case PKT_TX_SCTP_CKSUM: + sctp_hdr = (struct sctp_hdr *) + ((char *)l3_hdr + m->l3_len); + sctp_hdr->cksum = 0; + break; + default: + break; + } + } +} + /* * This function routes the TX packet to the correct interface. This may be a local device * or the physical port. @@ -1145,7 +1241,7 @@ virtio_tx_route(struct vhost_dev *vdev, struct rte_mbuf *m, uint16_t vlan_tag) (vh->vlan_tci != vlan_tag_be)) vh->vlan_tci = vlan_tag_be; } else { - m->ol_flags = PKT_TX_VLAN_PKT; + m->ol_flags |= PKT_TX_VLAN_PKT; /* * Find the right seg to adjust the data len when offset is @@ -1169,6 +1265,9 @@ virtio_tx_route(struct vhost_dev *vdev, struct rte_mbuf *m, uint16_t vlan_tag) m->vlan_tci = vlan_tag; } + if ((m->ol_flags & PKT_TX_L4_MASK) || (m->ol_flags & PKT_TX_TCP_SEG)) + virtio_tx_offload(m); + tx_q->m_table[len] = m; len++; if (enable_stats) { @@ -1834,7 +1933,7 @@ virtio_tx_route_zcp(struct virtio_net *dev, struct rte_mbuf *m, mbuf->buf_physaddr = m->buf_physaddr; mbuf->buf_addr = m->buf_addr; } - mbuf->ol_flags = PKT_TX_VLAN_PKT; + mbuf->ol_flags |= PKT_TX_VLAN_PKT; mbuf->vlan_tci = vlan_tag; mbuf->l2_len = sizeof(struct ether_hdr); mbuf->l3_len = sizeof(struct ipv4_hdr); -- 2.20.1