From 659ba2606be997631d736070d2efd92472496a11 Mon Sep 17 00:00:00 2001 From: Martin Weiser Date: Fri, 15 Jul 2016 15:59:54 +0200 Subject: add option to use DPDK tx checksum offloading to generate packets with correct IP, TCP and UDP checksums --- linux_dpdk/ws_main.py | 1 + src/bp_sim.h | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++- src/main_dpdk.cpp | 24 ++++++++++++++++++++- 3 files changed, 81 insertions(+), 2 deletions(-) diff --git a/linux_dpdk/ws_main.py b/linux_dpdk/ws_main.py index dde94dc4..72ea5e3d 100755 --- a/linux_dpdk/ws_main.py +++ b/linux_dpdk/ws_main.py @@ -492,6 +492,7 @@ includes_path =''' ../src/pal/linux_dpdk/ ../src/dpdk22/lib/librte_mempool/ ../src/dpdk22/lib/librte_pipeline/ ../src/dpdk22/lib/librte_ring/ +../src/dpdk22/lib/librte_net/ ../src/dpdk22/ '''; diff --git a/src/bp_sim.h b/src/bp_sim.h index e396a710..18db61ca 100755 --- a/src/bp_sim.h +++ b/src/bp_sim.h @@ -62,6 +62,10 @@ limitations under the License. #include +#ifdef RTE_DPDK +# include +#endif /* RTE_DPDK */ + class CGenNodePCAP; #undef NAT_TRACE_ @@ -707,6 +711,14 @@ public: return (btGetMaskBit32(m_flags1, 7, 7) ? true : false); } + void setChecksumOffloadEnable(bool enable) { + btSetMaskBit32(m_flags1, 8, 8, (enable ? 1 : 0) ); + } + + bool getChecksumOffloadEnable(){ + return (btGetMaskBit32(m_flags1, 8, 8) ? true : false); + } + public: void Dump(FILE *fd); @@ -3106,7 +3118,15 @@ inline void CFlowPktInfo::update_pkt_info(char *p, } } +#ifdef RTE_DPDK + if (CGlobalInfo::m_options.preview.getChecksumOffloadEnable()) { + ipv4->myChecksum = 0; + } else { + ipv4->updateCheckSum(); + } +#else ipv4->updateCheckSum(); +#endif } @@ -3120,16 +3140,36 @@ inline void CFlowPktInfo::update_pkt_info(char *p, }else{ m_tcp->setDestPort(src_port); } + +#ifdef RTE_DPDK + if (CGlobalInfo::m_options.preview.getChecksumOffloadEnable()) { + /* set pseudo-header checksum */ + m_tcp->setChecksum(PKT_NTOHS(rte_ipv4_phdr_cksum((struct ipv4_hdr *)ipv4->getPointer(), + PKT_TX_IPV4 | PKT_TX_IP_CKSUM | PKT_TX_TCP_CKSUM))); + } +#endif }else { if ( m_pkt_indication.m_desc.IsUdp() ){ UDPHeader * m_udp =(UDPHeader *)(p +m_pkt_indication.getFastTcpOffset() ); BP_ASSERT(m_udp); - m_udp->setChecksum(0); + if ( port_dir == CLIENT_SIDE ) { m_udp->setSourcePort(src_port); }else{ m_udp->setDestPort(src_port); } + +#ifdef RTE_DPDK + if (CGlobalInfo::m_options.preview.getChecksumOffloadEnable()) { + /* set pseudo-header checksum */ + m_udp->setChecksum(PKT_NTOHS(rte_ipv4_phdr_cksum((struct ipv4_hdr *) ipv4->getPointer(), + PKT_TX_IPV4 | PKT_TX_IP_CKSUM | PKT_TX_UDP_CKSUM))); + } else { + m_udp->setChecksum(0); + } +#else + m_udp->setChecksum(0); +#endif }else{ #ifdef _DEBUG if (!m_pkt_indication.m_desc.IsIcmp()) { @@ -3260,6 +3300,22 @@ inline rte_mbuf_t * CFlowPktInfo::do_generate_new_mbuf(CGenNode * node){ memcpy(p,m_packet->raw,len); +#ifdef RTE_DPDK + if (CGlobalInfo::m_options.preview.getChecksumOffloadEnable()) { + if (m_pkt_indication.m_desc.IsTcp()) { + m->l2_len = 14; + m->l3_len = 20; + m->ol_flags |= PKT_TX_IPV4 | PKT_TX_IP_CKSUM | PKT_TX_TCP_CKSUM; + } else { + if (m_pkt_indication.m_desc.IsUdp()) { + m->l2_len = 14; + m->l3_len = 20; + m->ol_flags |= PKT_TX_IPV4 | PKT_TX_IP_CKSUM | PKT_TX_UDP_CKSUM; + } + } + } +#endif + update_pkt_info(p,node); append_big_mbuf(m,node); diff --git a/src/main_dpdk.cpp b/src/main_dpdk.cpp index 45e46810..820371ab 100644 --- a/src/main_dpdk.cpp +++ b/src/main_dpdk.cpp @@ -50,6 +50,7 @@ #include #include #include +#include #include "bp_sim.h" #include "os_time.h" @@ -555,7 +556,8 @@ enum { OPT_HELP, OPT_MAC_SPLIT, OPT_SEND_DEBUG_PKT, OPT_NO_WATCHDOG, - OPT_ALLOW_COREDUMP + OPT_ALLOW_COREDUMP, + OPT_CHECKSUM_OFFLOAD, }; @@ -620,6 +622,7 @@ static CSimpleOpt::SOption parser_options[] = { OPT_MBUF_FACTOR , "--mbuf-factor", SO_REQ_SEP }, { OPT_NO_WATCHDOG , "--no-watchdog", SO_NONE }, { OPT_ALLOW_COREDUMP , "--allow-coredump", SO_NONE }, + { OPT_CHECKSUM_OFFLOAD, "--checksum-offload", SO_NONE }, SO_END_OF_OPTIONS @@ -725,6 +728,8 @@ static int usage(){ printf(" --allow-coredump : allow a creation of core dump \n"); printf(" \n"); printf(" --vm-sim : simulate vm with driver of one input queue and one output queue \n"); + printf(" \n"); + printf(" --checksum-offload : enable IP, TCP and UDP tx checksum offloading with DPDK. This requires all used interfaces to support this \n"); printf(" \n"); printf(" Examples: "); printf(" basic trex run for 10 sec and multiplier of x10 \n"); @@ -987,6 +992,10 @@ static int parse_options(int argc, char *argv[], CParserOption* po, bool first_t po->m_debug_pkt_proto = (uint8_t)tmp_data; break; + case OPT_CHECKSUM_OFFLOAD: + po->preview.setChecksumOffloadEnable(true); + break; + default: usage(); @@ -1341,6 +1350,19 @@ void CPhyEthIF::configure(uint16_t nb_rx_queue, /* get device info */ rte_eth_dev_info_get(m_port_id, &m_dev_info); + if (CGlobalInfo::m_options.preview.getChecksumOffloadEnable()) { + /* check if the device supports TCP and UDP checksum offloading */ + if ((m_dev_info.tx_offload_capa & DEV_TX_OFFLOAD_UDP_CKSUM) == 0) { + rte_exit(EXIT_FAILURE, "Device does not support UDP checksum offload: " + "port=%u\n", + m_port_id); + } + if ((m_dev_info.tx_offload_capa & DEV_TX_OFFLOAD_TCP_CKSUM) == 0) { + rte_exit(EXIT_FAILURE, "Device does not support TCP checksum offload: " + "port=%u\n", + m_port_id); + } + } } -- cgit 1.2.3-korg