From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-wg0-f49.google.com (mail-wg0-f49.google.com [74.125.82.49]) by dpdk.org (Postfix) with ESMTP id 09A3D7F80 for ; Mon, 10 Nov 2014 16:50:21 +0100 (CET) Received: by mail-wg0-f49.google.com with SMTP id x13so9316105wgg.8 for ; Mon, 10 Nov 2014 08:00:03 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=mD8KkiOZpT1TVpztA37z9/QEb0ZSDzKoUHUT0z8Uf9c=; b=S0IIiCx4hvniPMPcV1B3HE7x/D/8JsndJQHqy1eLJRU01+uvEv7c1YEytg+gsd/0CL w4/0ZXocet/iVgD9ux3xgUsv9CZtCaswhNJOrT7D1WyFS4+witvCMV/dChYqRbo5ggjo bxZ+451dkzYqzIVN4BLmO5esnz2XUFM6vLBf7bJYiv3vVaNStnZ+z64J74+7wBPyMrtD RBCBmx/QFObV/xId8mPkl1y6SyQWUrS9hgCK0OblkX53nRh3MkC3OOQ7sKsvmILLFi/K uFhM4RB+M4LdZXD/yW6svpNiQ70ycMlM0tFasHjOh+MoQoqdNIto3ZMPKFDSK4Zrf62i FRMA== X-Gm-Message-State: ALoCoQlLjhdSsZyyuwfE/KqsShQiQSSaEahTvUSeUgAdR5JCcK/sVq0m9smWRm3LnQGwNU5bk6Bw X-Received: by 10.194.63.145 with SMTP id g17mr45594577wjs.80.1415635203524; Mon, 10 Nov 2014 08:00:03 -0800 (PST) Received: from glumotte.dev.6wind.com (guy78-3-82-239-227-177.fbx.proxad.net. [82.239.227.177]) by mx.google.com with ESMTPSA id ll2sm10966561wjb.11.2014.11.10.08.00.01 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 10 Nov 2014 08:00:03 -0800 (PST) From: Olivier Matz To: dev@dpdk.org Date: Mon, 10 Nov 2014 16:59:25 +0100 Message-Id: <1415635166-1364-12-git-send-email-olivier.matz@6wind.com> X-Mailer: git-send-email 2.1.0 In-Reply-To: <1415635166-1364-1-git-send-email-olivier.matz@6wind.com> References: <1415635166-1364-1-git-send-email-olivier.matz@6wind.com> Cc: jigsaw@gmail.com Subject: [dpdk-dev] [PATCH 11/12] testpmd: support TSO in csum forward engine X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: patches and discussions about DPDK List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 10 Nov 2014 15:50:21 -0000 Add two new commands in testpmd: - tso set - tso show These commands can be used enable TSO when transmitting TCP packets in the csum forward engine. Ex: set fwd csum tx_checksum set ip hw 0 tso set 800 0 start Signed-off-by: Olivier Matz --- app/test-pmd/cmdline.c | 92 +++++++++++++++++++++++++++++++++++++++++++++++++ app/test-pmd/csumonly.c | 53 +++++++++++++++++++++------- app/test-pmd/testpmd.h | 1 + 3 files changed, 133 insertions(+), 13 deletions(-) diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c index 0361e58..5460415 100644 --- a/app/test-pmd/cmdline.c +++ b/app/test-pmd/cmdline.c @@ -318,6 +318,14 @@ static void cmd_help_long_parsed(void *parsed_result, "tx_checksum show (port_id)\n" " Display tx checksum offload configuration\n\n" + "tso set (segsize) (portid)\n" + " Enable TCP Segmentation Offload in csum forward" + " engine.\n" + " Please check the NIC datasheet for HW limits.\n\n" + + "tso show (portid)" + " Display the status of TCP Segmentation Offload.\n\n" + "set fwd (%s)\n" " Set packet forwarding mode.\n\n" @@ -2862,6 +2870,88 @@ cmdline_parse_inst_t cmd_tx_cksum_show = { }, }; +/* *** ENABLE HARDWARE SEGMENTATION IN TX PACKETS *** */ +struct cmd_tso_set_result { + cmdline_fixed_string_t tso; + cmdline_fixed_string_t mode; + uint16_t tso_segsz; + uint8_t port_id; +}; + +static void +cmd_tso_set_parsed(void *parsed_result, + __attribute__((unused)) struct cmdline *cl, + __attribute__((unused)) void *data) +{ + struct cmd_tso_set_result *res = parsed_result; + struct rte_eth_dev_info dev_info; + + if (port_id_is_invalid(res->port_id)) + return; + + if (!strcmp(res->mode, "set")) + ports[res->port_id].tso_segsz = res->tso_segsz; + + if (ports[res->port_id].tso_segsz == 0) + printf("TSO is disabled\n"); + else + printf("TSO segment size is %d\n", + ports[res->port_id].tso_segsz); + + /* display warnings if configuration is not supported by the NIC */ + rte_eth_dev_info_get(res->port_id, &dev_info); + if ((ports[res->port_id].tso_segsz != 0) && + (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_TCP_TSO) == 0) { + printf("Warning: TSO enabled but not " + "supported by port %d\n", res->port_id); + } +} + +cmdline_parse_token_string_t cmd_tso_set_tso = + TOKEN_STRING_INITIALIZER(struct cmd_tso_set_result, + tso, "tso"); +cmdline_parse_token_string_t cmd_tso_set_mode = + TOKEN_STRING_INITIALIZER(struct cmd_tso_set_result, + mode, "set"); +cmdline_parse_token_num_t cmd_tso_set_tso_segsz = + TOKEN_NUM_INITIALIZER(struct cmd_tso_set_result, + tso_segsz, UINT16); +cmdline_parse_token_num_t cmd_tso_set_portid = + TOKEN_NUM_INITIALIZER(struct cmd_tso_set_result, + port_id, UINT8); + +cmdline_parse_inst_t cmd_tso_set = { + .f = cmd_tso_set_parsed, + .data = NULL, + .help_str = "Set TSO segment size for csum engine (0 to disable): " + "tso set ", + .tokens = { + (void *)&cmd_tso_set_tso, + (void *)&cmd_tso_set_mode, + (void *)&cmd_tso_set_tso_segsz, + (void *)&cmd_tso_set_portid, + NULL, + }, +}; + +cmdline_parse_token_string_t cmd_tso_show_mode = + TOKEN_STRING_INITIALIZER(struct cmd_tso_set_result, + mode, "show"); + + +cmdline_parse_inst_t cmd_tso_show = { + .f = cmd_tso_set_parsed, + .data = NULL, + .help_str = "Show TSO segment size for csum engine: " + "tso show ", + .tokens = { + (void *)&cmd_tso_set_tso, + (void *)&cmd_tso_show_mode, + (void *)&cmd_tso_set_portid, + NULL, + }, +}; + /* *** ENABLE/DISABLE FLUSH ON RX STREAMS *** */ struct cmd_set_flush_rx { cmdline_fixed_string_t set; @@ -7875,6 +7965,8 @@ cmdline_parse_ctx_t main_ctx[] = { (cmdline_parse_inst_t *)&cmd_tx_vlan_set_pvid, (cmdline_parse_inst_t *)&cmd_tx_cksum_set, (cmdline_parse_inst_t *)&cmd_tx_cksum_show, + (cmdline_parse_inst_t *)&cmd_tso_set, + (cmdline_parse_inst_t *)&cmd_tso_show, (cmdline_parse_inst_t *)&cmd_link_flow_control_set, (cmdline_parse_inst_t *)&cmd_link_flow_control_set_rx, (cmdline_parse_inst_t *)&cmd_link_flow_control_set_tx, diff --git a/app/test-pmd/csumonly.c b/app/test-pmd/csumonly.c index abc525c..7995ff5 100644 --- a/app/test-pmd/csumonly.c +++ b/app/test-pmd/csumonly.c @@ -222,14 +222,15 @@ get_udptcp_checksum(void *l3_hdr, void *l4_hdr, uint16_t ethertype) /* * Parse an ethernet header to fill the ethertype, l2_len, l3_len and * ipproto. This function is able to recognize IPv4/IPv6 with one optional vlan - * header. + * header. The l4_len argument is only set in case of TCP (useful for TSO). */ static void parse_ethernet(struct ether_hdr *eth_hdr, uint16_t *ethertype, uint16_t *l2_len, - uint16_t *l3_len, uint8_t *l4_proto) + uint16_t *l3_len, uint8_t *l4_proto, uint16_t *l4_len) { struct ipv4_hdr *ipv4_hdr; struct ipv6_hdr *ipv6_hdr; + struct tcp_hdr *tcp_hdr; *l2_len = sizeof(struct ether_hdr); *ethertype = eth_hdr->ether_type; @@ -257,6 +258,14 @@ parse_ethernet(struct ether_hdr *eth_hdr, uint16_t *ethertype, uint16_t *l2_len, *l4_proto = 0; break; } + + if (*l4_proto == IPPROTO_TCP) { + tcp_hdr = (struct tcp_hdr *)((char *)eth_hdr + + *l2_len + *l3_len); + *l4_len = (tcp_hdr->data_off & 0xf0) >> 2; + } + else + *l4_len = 0; } /* modify the IPv4 or IPv4 source address of a packet */ @@ -279,7 +288,7 @@ change_ip_addresses(void *l3_hdr, uint16_t ethertype) * depending on the testpmd command line configuration */ static uint64_t process_inner_cksums(void *l3_hdr, uint16_t ethertype, uint16_t l3_len, - uint8_t l4_proto, uint16_t testpmd_ol_flags) + uint8_t l4_proto, uint16_t tso_segsz, uint16_t testpmd_ol_flags) { struct ipv4_hdr *ipv4_hdr = l3_hdr; struct udp_hdr *udp_hdr; @@ -291,11 +300,15 @@ process_inner_cksums(void *l3_hdr, uint16_t ethertype, uint16_t l3_len, ipv4_hdr = l3_hdr; ipv4_hdr->hdr_checksum = 0; - if (testpmd_ol_flags & TESTPMD_TX_OFFLOAD_IP_CKSUM) + if (tso_segsz != 0 && l4_proto == IPPROTO_TCP) { ol_flags |= PKT_TX_IP_CKSUM; - else - ipv4_hdr->hdr_checksum = get_ipv4_cksum(ipv4_hdr); - + } + else { + if (testpmd_ol_flags & TESTPMD_TX_OFFLOAD_IP_CKSUM) + ol_flags |= PKT_TX_IP_CKSUM; + else + ipv4_hdr->hdr_checksum = get_ipv4_cksum(ipv4_hdr); + } } else if (ethertype != _htons(ETHER_TYPE_IPv6)) return 0; /* packet type not supported nothing to do */ @@ -320,7 +333,11 @@ process_inner_cksums(void *l3_hdr, uint16_t ethertype, uint16_t l3_len, else if (l4_proto == IPPROTO_TCP) { tcp_hdr = (struct tcp_hdr *)((char *)l3_hdr + l3_len); tcp_hdr->cksum = 0; - if (testpmd_ol_flags & TESTPMD_TX_OFFLOAD_TCP_CKSUM) { + if (tso_segsz != 0) { + ol_flags |= PKT_TX_TCP_SEG; + tcp_hdr->cksum = get_psd_sum(l3_hdr, ethertype); + } + else if (testpmd_ol_flags & TESTPMD_TX_OFFLOAD_TCP_CKSUM) { ol_flags |= PKT_TX_TCP_CKSUM; tcp_hdr->cksum = get_psd_sum(l3_hdr, ethertype); } @@ -393,6 +410,8 @@ process_outer_cksums(void *outer_l3_hdr, uint16_t outer_ethertype, * - modify the IPs * - reprocess the checksum in SW or HW, depending on testpmd command line * configuration + * - if TSO is enabled in testpmd command line, also flag the mbuf for TCP + * segmentation offload (this implies HW checksum) * Then packets are transmitted on the output port. * * Supported packets are: @@ -418,7 +437,9 @@ pkt_burst_checksum_forward(struct fwd_stream *fs) uint16_t testpmd_ol_flags; uint8_t l4_proto; uint16_t ethertype = 0, outer_ethertype = 0; - uint16_t l2_len = 0, l3_len = 0, outer_l2_len = 0, outer_l3_len = 0; + uint16_t l2_len = 0, l3_len = 0, l4_len = 0; + uint16_t outer_l2_len = 0, outer_l3_len = 0; + uint16_t tso_segsz; int tunnel = 0; uint32_t rx_bad_ip_csum; uint32_t rx_bad_l4_csum; @@ -448,6 +469,7 @@ pkt_burst_checksum_forward(struct fwd_stream *fs) txp = &ports[fs->tx_port]; testpmd_ol_flags = txp->tx_ol_flags; + tso_segsz = txp->tso_segsz; for (i = 0; i < nb_rx; i++) { @@ -463,7 +485,8 @@ pkt_burst_checksum_forward(struct fwd_stream *fs) * and inner headers */ eth_hdr = rte_pktmbuf_mtod(m, struct ether_hdr *); - parse_ethernet(eth_hdr, ðertype, &l2_len, &l3_len, &l4_proto); + parse_ethernet(eth_hdr, ðertype, &l2_len, &l3_len, + &l4_proto, &l4_len); l3_hdr = (char *)eth_hdr + l2_len; /* check if it's a supported tunnel (only vxlan for now) */ @@ -491,7 +514,7 @@ pkt_burst_checksum_forward(struct fwd_stream *fs) sizeof(struct vxlan_hdr)); parse_ethernet(eth_hdr, ðertype, &l2_len, - &l3_len, &l4_proto); + &l3_len, &l4_proto, &l4_len); l3_hdr = (char *)eth_hdr + l2_len; } } @@ -505,11 +528,12 @@ pkt_burst_checksum_forward(struct fwd_stream *fs) /* step 3: depending on user command line configuration, * recompute checksum either in software or flag the - * mbuf to offload the calculation to the NIC */ + * mbuf to offload the calculation to the NIC. If TSO + * is configured, prepare the mbuf for TCP segmentation. */ /* process checksums of inner headers first */ ol_flags |= process_inner_cksums(l3_hdr, ethertype, - l3_len, l4_proto, testpmd_ol_flags); + l3_len, l4_proto, tso_segsz, testpmd_ol_flags); /* Then process outer headers if any. Note that the software * checksum will be wrong if one of the inner checksums is @@ -538,6 +562,7 @@ pkt_burst_checksum_forward(struct fwd_stream *fs) sizeof(struct udp_hdr) + sizeof(struct vxlan_hdr) + l2_len; m->l3_len = l3_len; + m->l4_len = l4_len; } } else { /* this is only useful if an offload flag is @@ -545,7 +570,9 @@ pkt_burst_checksum_forward(struct fwd_stream *fs) * case */ m->l2_len = l2_len; m->l3_len = l3_len; + m->l4_len = l4_len; } + m->tso_segsz = tso_segsz; m->ol_flags = ol_flags; } diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h index c753d37..c22863f 100644 --- a/app/test-pmd/testpmd.h +++ b/app/test-pmd/testpmd.h @@ -149,6 +149,7 @@ struct rte_port { struct fwd_stream *tx_stream; /**< Port TX stream, if unique */ unsigned int socket_id; /**< For NUMA support */ uint16_t tx_ol_flags;/**< TX Offload Flags (TESTPMD_TX_OFFLOAD...). */ + uint16_t tso_segsz; /**< MSS for segmentation offload. */ uint16_t tx_vlan_id; /**< Tag Id. in TX VLAN packets. */ void *fwd_ctx; /**< Forwarding mode context */ uint64_t rx_bad_ip_csum; /**< rx pkts with bad ip checksum */ -- 2.1.0