From patchwork Sat Apr 23 10:58:07 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jean-Christophe Dubois X-Patchwork-Id: 614034 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3qsTxm6TTFz9t5W for ; Sat, 23 Apr 2016 20:58:52 +1000 (AEST) Received: from localhost ([::1]:51658 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1atvH1-0003uL-0k for incoming@patchwork.ozlabs.org; Sat, 23 Apr 2016 06:58:51 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:58670) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1atvGR-0002qo-LP for qemu-devel@nongnu.org; Sat, 23 Apr 2016 06:58:16 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1atvGO-0001tX-Cp for qemu-devel@nongnu.org; Sat, 23 Apr 2016 06:58:15 -0400 Received: from zose-mta02.web4all.fr ([185.49.20.43]:44993) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1atvGO-0001tA-21 for qemu-devel@nongnu.org; Sat, 23 Apr 2016 06:58:12 -0400 Received: from localhost (localhost [127.0.0.1]) by zose-mta02.web4all.fr (Postfix) with ESMTP id 177AA40340; Sat, 23 Apr 2016 12:58:11 +0200 (CEST) Received: from zose-mta02.web4all.fr ([127.0.0.1]) by localhost (zose-mta02.web4all.fr [127.0.0.1]) (amavisd-new, port 10032) with ESMTP id Dl7KGygJro12; Sat, 23 Apr 2016 12:58:09 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by zose-mta02.web4all.fr (Postfix) with ESMTP id A2BEF4050D; Sat, 23 Apr 2016 12:58:09 +0200 (CEST) X-Virus-Scanned: amavisd-new at zose-mta-02.w4a.fr Received: from zose-mta02.web4all.fr ([127.0.0.1]) by localhost (zose-mta02.web4all.fr [127.0.0.1]) (amavisd-new, port 10026) with ESMTP id oSd7t2qUNs5C; Sat, 23 Apr 2016 12:58:09 +0200 (CEST) Received: from localhost.localdomain (smm49-1-78-235-240-156.fbx.proxad.net [78.235.240.156]) by zose-mta02.web4all.fr (Postfix) with ESMTPSA id 453C040340; Sat, 23 Apr 2016 12:58:09 +0200 (CEST) From: Jean-Christophe Dubois To: qemu-devel@nongnu.org, peter.maydell@linaro.org, jasowang@redhat.com Date: Sat, 23 Apr 2016 12:58:07 +0200 Message-Id: <1be6bcd29de76deb739506d16baf03b08d6c185f.1461407169.git.jcd@tribudubois.net> X-Mailer: git-send-email 2.7.4 In-Reply-To: References: X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 185.49.20.43 Subject: [Qemu-devel] [PATCH v2 1/3] net: improve UDP/TCP checksum computation. X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Jean-Christophe Dubois Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" This patch adds: * based on Eth, UDP, TCP struct present in eth.h instead of hardcoded indexes. * based on various macros present in eth.h. * allow to account for optional VLAN header. Signed-off-by: Jean-Christophe Dubois --- net/checksum.c | 83 ++++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 57 insertions(+), 26 deletions(-) diff --git a/net/checksum.c b/net/checksum.c index d0fa424..fd25209 100644 --- a/net/checksum.c +++ b/net/checksum.c @@ -18,9 +18,7 @@ #include "qemu/osdep.h" #include "qemu-common.h" #include "net/checksum.h" - -#define PROTO_TCP 6 -#define PROTO_UDP 17 +#include "net/eth.h" uint32_t net_checksum_add_cont(int len, uint8_t *buf, int seq) { @@ -57,40 +55,73 @@ uint16_t net_checksum_tcpudp(uint16_t length, uint16_t proto, void net_checksum_calculate(uint8_t *data, int length) { - int hlen, plen, proto, csum_offset; - uint16_t csum; + int plen; + struct ip_header *ip; + + /* Ensure we have at least a Eth header */ + if (length < sizeof(struct eth_header)) { + return; + } - /* Ensure data has complete L2 & L3 headers. */ - if (length < 14 + 20) { + /* Now check we have an IP header (with an optonnal VLAN header */ + if (length < eth_get_l2_hdr_length(data) + sizeof(struct ip_header)) { return; } - if ((data[14] & 0xf0) != 0x40) + ip = PKT_GET_IP_HDR(data); + + if (IP_HEADER_VERSION(ip) != IP_HEADER_VERSION_4) { return; /* not IPv4 */ - hlen = (data[14] & 0x0f) * 4; - plen = (data[16] << 8 | data[17]) - hlen; - proto = data[23]; + } + + /* Last, check that we have enough data for the IP frame */ + if (length < eth_get_l2_hdr_length(data) + be16_to_cpu(ip->ip_len)) { + return; + } + + plen = be16_to_cpu(ip->ip_len) - IP_HDR_GET_LEN(ip); + + switch (ip->ip_p) { + case IP_PROTO_TCP: + { + uint16_t csum; + tcp_header *tcp = (tcp_header *)(ip + 1); + + if (plen < sizeof(tcp_header)) { + return; + } - switch (proto) { - case PROTO_TCP: - csum_offset = 16; + tcp->th_sum = 0; + + csum = net_checksum_tcpudp(plen, ip->ip_p, + (uint8_t *)&ip->ip_src, + (uint8_t *)tcp); + + tcp->th_sum = cpu_to_be16(csum); + } break; - case PROTO_UDP: - csum_offset = 6; + case IP_PROTO_UDP: + { + uint16_t csum; + udp_header *udp = (udp_header *)(ip + 1); + + if (plen < sizeof(udp_header)) { + return; + } + + udp->uh_sum = 0; + + csum = net_checksum_tcpudp(plen, ip->ip_p, + (uint8_t *)&ip->ip_src, + (uint8_t *)udp); + + udp->uh_sum = cpu_to_be16(csum); + } break; default: + /* Can't handle any other protocol */ return; } - - if (plen < csum_offset + 2 || 14 + hlen + plen > length) { - return; - } - - data[14+hlen+csum_offset] = 0; - data[14+hlen+csum_offset+1] = 0; - csum = net_checksum_tcpudp(plen, proto, data+14+12, data+14+hlen); - data[14+hlen+csum_offset] = csum >> 8; - data[14+hlen+csum_offset+1] = csum & 0xff; } uint32_t