From patchwork Sat Jan 13 23:00:12 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Github ODP bot X-Patchwork-Id: 124434 Delivered-To: patch@linaro.org Received: by 10.46.64.148 with SMTP id r20csp231141lje; Sat, 13 Jan 2018 15:05:12 -0800 (PST) X-Google-Smtp-Source: ACJfBotzfQT3Rgpfwy3lEym2tgNFhC2UchxH1r6RQ76zOCTxi4DH8y9aSwglvZ4f2wPPTIrWWt/D X-Received: by 10.200.16.13 with SMTP id z13mr40751800qti.111.1515884711998; Sat, 13 Jan 2018 15:05:11 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1515884711; cv=none; d=google.com; s=arc-20160816; b=PGlIiE5fMOSWLntl1gkYRsa2hHZgAVTzX94/jm96RomfEIz062h+4W2S547/WUmcaO 5WNKi/jMuAh5XGhrOTDShZtpByVL8dYBF1beBe4s3MSF28puLaZPD8fRH0SFcaAIsxTq trC8ERoPspmCuZZ0wBZY6IWJZmHoLZbJpQysh3+BUvLjvVYfd8yPLM1/KTHx0/nS5Ka8 1H7/d3I+dDWkYanpBLSxKXdneZsVgVwbpyHthOtABQvcSvjBENggS0LPTwZoGrCMv1YA zXV5/K5/L4M3Yk3Ob4NY1ncRdWboyerNWUP5hD7dm2s23swimT9R+PNNBJPJj2knAzHq 6miQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:subject:github-pr-num :references:in-reply-to:message-id:date:to:from:delivered-to :arc-authentication-results; bh=bp1vflRIt9lCPt2bFC/czGiGEdv5EWW3ZR6KNqXtIZY=; b=LzhwPK24WggZLPgWBqAofC/32PxIXv+Lvw+tGj9GkbqFfL/LDrPxRUTUHN3+oOWe5T 4HysZHPCN4wmMYjUz0Ax5LpJrOy4NPRcdb9hO06EZ2heQzs4Rna9NoZvj6j9n8z/T2OF 3TYkMkqapNT6eLHhpnHd6p9+KMXVMNfstrsCGZZ6ijoRwqXhKbhxX9vqgOndPpNKjjhV GvdZ3CGjF/qWT2RHzzacwtHI/gu6eP2w0vs8FiYmsxSSvAsB2vwvbwEHn+vhMmcktiqH POo9oMzcBMAxL5uXwsTLWNJTGTsxWPLVK8tkZGf3qmDdbUg1BB81BDEFeauO6EOSwxRW 7Z5w== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of lng-odp-bounces@lists.linaro.org designates 54.197.127.237 as permitted sender) smtp.mailfrom=lng-odp-bounces@lists.linaro.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=yandex.ru Return-Path: Received: from lists.linaro.org (ec2-54-197-127-237.compute-1.amazonaws.com. [54.197.127.237]) by mx.google.com with ESMTP id d66si235820qkf.148.2018.01.13.15.05.11; Sat, 13 Jan 2018 15:05:11 -0800 (PST) Received-SPF: pass (google.com: domain of lng-odp-bounces@lists.linaro.org designates 54.197.127.237 as permitted sender) client-ip=54.197.127.237; Authentication-Results: mx.google.com; spf=pass (google.com: domain of lng-odp-bounces@lists.linaro.org designates 54.197.127.237 as permitted sender) smtp.mailfrom=lng-odp-bounces@lists.linaro.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=yandex.ru Received: by lists.linaro.org (Postfix, from userid 109) id AA8C561742; Sat, 13 Jan 2018 23:05:11 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on ip-10-142-244-252 X-Spam-Level: X-Spam-Status: No, score=-2.6 required=5.0 tests=BAYES_00,FREEMAIL_FROM, RCVD_IN_DNSWL_LOW, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL autolearn=disabled version=3.4.0 Received: from [127.0.0.1] (localhost [127.0.0.1]) by lists.linaro.org (Postfix) with ESMTP id C6A2B6175E; Sat, 13 Jan 2018 23:00:50 +0000 (UTC) X-Original-To: lng-odp@lists.linaro.org Delivered-To: lng-odp@lists.linaro.org Received: by lists.linaro.org (Postfix, from userid 109) id 8C64860975; Sat, 13 Jan 2018 23:00:25 +0000 (UTC) Received: from forward105j.mail.yandex.net (forward105j.mail.yandex.net [5.45.198.248]) by lists.linaro.org (Postfix) with ESMTPS id 985DA60721 for ; Sat, 13 Jan 2018 23:00:20 +0000 (UTC) Received: from mxback14g.mail.yandex.net (mxback14g.mail.yandex.net [IPv6:2a02:6b8:0:1472:2741:0:8b7:93]) by forward105j.mail.yandex.net (Yandex) with ESMTP id 2FEB9182E91 for ; Sun, 14 Jan 2018 02:00:19 +0300 (MSK) Received: from smtp3o.mail.yandex.net (smtp3o.mail.yandex.net [2a02:6b8:0:1a2d::27]) by mxback14g.mail.yandex.net (nwsmtp/Yandex) with ESMTP id 5jEYibpREv-0J08YQuG; Sun, 14 Jan 2018 02:00:19 +0300 Received: by smtp3o.mail.yandex.net (nwsmtp/Yandex) with ESMTPSA id OeJ5YhkKll-0IxKpjH1; Sun, 14 Jan 2018 02:00:18 +0300 (using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits)) (Client certificate not present) From: Github ODP bot To: lng-odp@lists.linaro.org Date: Sun, 14 Jan 2018 02:00:12 +0300 Message-Id: <1515884413-15125-7-git-send-email-odpbot@yandex.ru> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1515884413-15125-1-git-send-email-odpbot@yandex.ru> References: <1515884413-15125-1-git-send-email-odpbot@yandex.ru> Github-pr-num: 389 Subject: [lng-odp] [PATCH v3][WIP 6/7] linux-gen: packet: check UDP checksums X-BeenThere: lng-odp@lists.linaro.org X-Mailman-Version: 2.1.16 Precedence: list List-Id: "The OpenDataPlane \(ODP\) List" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: lng-odp-bounces@lists.linaro.org Sender: "lng-odp" From: Dmitry Eremin-Solenikov Add code to enable checking of UDP checksums. Signed-off-by: Dmitry Eremin-Solenikov --- /** Email created from pull request 389 (lumag:parse-checksums) ** https://github.com/Linaro/odp/pull/389 ** Patch: https://github.com/Linaro/odp/pull/389.patch ** Base sha: 49ebafae0edebbc750742d8874ad0a7588286dea ** Merge commit sha: e6a448356c90f142122e5b5d4796bdf19e04e8c6 **/ .../linux-generic/include/odp_packet_internal.h | 6 + platform/linux-generic/odp_packet.c | 134 +++++++++++++++++++-- 2 files changed, 132 insertions(+), 8 deletions(-) diff --git a/platform/linux-generic/include/odp_packet_internal.h b/platform/linux-generic/include/odp_packet_internal.h index 86f0d80a5..f8b698335 100644 --- a/platform/linux-generic/include/odp_packet_internal.h +++ b/platform/linux-generic/include/odp_packet_internal.h @@ -100,6 +100,12 @@ typedef struct { /* offset to L4 hdr (TCP, UDP, SCTP, also ICMP) */ uint16_t l4_offset; + + /* Partial sum for L4 checksumming */ + uint32_t l4_part_sum; + + /* L4 checksum */ + uint32_t l4_sum; } packet_parser_t; /* Packet extra data length */ diff --git a/platform/linux-generic/odp_packet.c b/platform/linux-generic/odp_packet.c index d3c608ab0..98ecf714e 100644 --- a/platform/linux-generic/odp_packet.c +++ b/platform/linux-generic/odp_packet.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -1948,6 +1949,35 @@ int _odp_packet_copy_md_to_packet(odp_packet_t srcpkt, odp_packet_t dstpkt) return dst_uarea_size < src_uarea_size; } +static uint16_t packet_sum_ones_comp16(odp_packet_hdr_t *pkt_hdr, + uint32_t offset, + uint32_t len) +{ + uint32_t sum = pkt_hdr->p.l4_part_sum; + odp_bool_t odd_offset = false; + + if (offset + len > pkt_hdr->frame_len) + return 0; + + while (len > 0) { + uint32_t seglen = 0; /* GCC */ + void *mapaddr = packet_map(pkt_hdr, offset, &seglen, NULL); + + if (seglen < len) + seglen = len; + + len -= seglen; + sum += _odp_chksum_ones_comp16_32(mapaddr, seglen, odd_offset); + odd_offset ^= (seglen % 2); + } + + /* Not more than two additions */ + sum = (sum & 0xffff) + (sum >> 16); + sum = (sum & 0xffff) + (sum >> 16); + + return ~sum; +} + /** Parser helper function for Ethernet packets */ static inline uint16_t parse_eth(packet_parser_t *prs, const uint8_t **parseptr, uint32_t *offset, uint32_t frame_len) @@ -2033,6 +2063,7 @@ static inline uint8_t parse_ipv4(packet_parser_t *prs, const uint8_t **parseptr, uint16_t frag_offset; uint32_t dstaddr = odp_be_to_cpu_32(ipv4->dst_addr); uint32_t l3_len = odp_be_to_cpu_16(ipv4->tot_len); + uint32_t l4_part_sum = 0; if (odp_unlikely(ihl < _ODP_IPV4HDR_IHL_MIN) || odp_unlikely(ver != 4) || @@ -2052,6 +2083,18 @@ static inline uint8_t parse_ipv4(packet_parser_t *prs, const uint8_t **parseptr, *offset += ihl * 4; *parseptr += ihl * 4; + if (chksums.chksum.udp || chksums.chksum.tcp) { + l4_part_sum = _odp_chksum_ones_comp16_32( + (const uint16_t *)&ipv4->src_addr, + 2 * _ODP_IPV4ADDR_LEN, false); +#if ODP_BYTE_ORDER == ODP_BIG_ENDIAN + l4_part_sum += ipv4->proto; +#else + l4_part_sum += ((uint16_t)ipv4->proto) << 8; +#endif + prs->l4_part_sum = l4_part_sum; + } + if (odp_unlikely(ihl > _ODP_IPV4HDR_IHL_MIN)) prs->input_flags.ipopt = 1; @@ -2076,13 +2119,15 @@ static inline uint8_t parse_ipv4(packet_parser_t *prs, const uint8_t **parseptr, */ static inline uint8_t parse_ipv6(packet_parser_t *prs, const uint8_t **parseptr, uint32_t *offset, uint32_t frame_len, - uint32_t seg_len) + uint32_t seg_len, + odp_proto_chksums_t chksums) { const _odp_ipv6hdr_t *ipv6 = (const _odp_ipv6hdr_t *)*parseptr; const _odp_ipv6hdr_ext_t *ipv6ext; uint32_t dstaddr0 = odp_be_to_cpu_32(ipv6->dst_addr.u8[0]); uint32_t l3_len = odp_be_to_cpu_16(ipv6->payload_len) + _ODP_IPV6HDR_LEN; + uint32_t l4_part_sum = 0; /* Basic sanity checks on IPv6 header */ if ((odp_be_to_cpu_32(ipv6->ver_tc_flow) >> 28) != 6 || @@ -2099,6 +2144,18 @@ static inline uint8_t parse_ipv6(packet_parser_t *prs, const uint8_t **parseptr, *offset += sizeof(_odp_ipv6hdr_t); *parseptr += sizeof(_odp_ipv6hdr_t); + if (chksums.chksum.udp || chksums.chksum.tcp) { + l4_part_sum = _odp_chksum_ones_comp16_32( + (const uint16_t *)(uintptr_t)&ipv6->src_addr, + 2 * _ODP_IPV6ADDR_LEN, false); +#if ODP_BYTE_ORDER == ODP_BIG_ENDIAN + l4_part_sum += ipv6->next_hdr; +#else + l4_part_sum += ((uint16_t)ipv6->next_hdr) << 8; +#endif + prs->l4_part_sum = l4_part_sum; + } + /* Skip past any IPv6 extension headers */ if (ipv6->next_hdr == _ODP_IPPROTO_HOPOPTS || ipv6->next_hdr == _ODP_IPPROTO_ROUTE) { @@ -2155,14 +2212,35 @@ static inline void parse_tcp(packet_parser_t *prs, /** * Parser helper function for UDP */ -static inline void parse_udp(packet_parser_t *prs, - const uint8_t **parseptr, uint32_t *offset) +static inline void parse_udp(packet_parser_t *prs, const uint8_t **parseptr, + uint32_t *offset, odp_proto_chksums_t chksums) { const _odp_udphdr_t *udp = (const _odp_udphdr_t *)*parseptr; uint32_t udplen = odp_be_to_cpu_16(udp->length); - if (odp_unlikely(udplen < sizeof(_odp_udphdr_t))) + if (odp_unlikely(udplen < sizeof(_odp_udphdr_t))) { prs->error_flags.udp_err = 1; + return; + } + + if (chksums.chksum.udp && + !prs->input_flags.ipfrag) { + if (udp->chksum == 0) { + prs->input_flags.l4_chksum_done = + (prs->input_flags.ipv4 != 1); + prs->error_flags.l4_chksum = + (prs->input_flags.ipv4 != 1); + } else { + prs->input_flags.l4_chksum_done = 1; + prs->l4_part_sum += udp->length; + /* Do not include checksum into partial sum */ + prs->l4_part_sum += _odp_chksum_ones_comp16_32( + (const void *)udp, + _ODP_UDPHDR_LEN - 2, + false); + } + prs->l4_sum = udp->chksum; + } if (odp_cpu_to_be_16(_ODP_UDP_IPSEC_PORT) == udp->dst_port && udplen > 4) { @@ -2208,7 +2286,7 @@ int packet_parse_common_l3_l4(packet_parser_t *prs, const uint8_t *parseptr, case _ODP_ETHTYPE_IPV6: prs->input_flags.ipv6 = 1; ip_proto = parse_ipv6(prs, &parseptr, &offset, frame_len, - seg_len); + seg_len, chksums); prs->l4_offset = offset; break; @@ -2252,7 +2330,7 @@ int packet_parse_common_l3_l4(packet_parser_t *prs, const uint8_t *parseptr, if (odp_unlikely(offset + _ODP_UDPHDR_LEN > seg_len)) return -1; prs->input_flags.udp = 1; - parse_udp(prs, &parseptr, NULL); + parse_udp(prs, &parseptr, NULL, chksums); break; case _ODP_IPPROTO_AH: @@ -2309,6 +2387,35 @@ int packet_parse_common(packet_parser_t *prs, const uint8_t *ptr, seg_len, layer, ethtype, chksums); } +static int packet_l4_chksum(odp_packet_hdr_t *pkt_hdr, + odp_proto_chksums_t chksums) +{ + /* UDP chksum == 0 case is covered in parse_udp() */ + if (chksums.chksum.udp && + pkt_hdr->p.input_flags.udp && + !pkt_hdr->p.input_flags.ipfrag && + pkt_hdr->p.l4_sum != 0) { + uint16_t sum = packet_sum_ones_comp16(pkt_hdr, + pkt_hdr->p.l4_offset + + _ODP_UDPHDR_LEN, + pkt_hdr->frame_len - + pkt_hdr->p.l4_offset - + _ODP_UDPHDR_LEN); + + if (sum == 0) + sum = 0xffff; + + if (sum != pkt_hdr->p.l4_sum) { + pkt_hdr->p.error_flags.l4_chksum = 1; + ODP_DBG("UDP chksum fail (%x)!\n", sum); + } else { + ODP_DBG("UDP chksum OK!\n"); + } + } + + return pkt_hdr->p.error_flags.all != 0; +} + /** * Simple packet parser */ @@ -2318,9 +2425,15 @@ int packet_parse_layer(odp_packet_hdr_t *pkt_hdr, { uint32_t seg_len = packet_first_seg_len(pkt_hdr); void *base = packet_data(pkt_hdr); + int rc; + + rc = packet_parse_common(&pkt_hdr->p, base, pkt_hdr->frame_len, + seg_len, layer, chksums); - return packet_parse_common(&pkt_hdr->p, base, pkt_hdr->frame_len, - seg_len, layer, chksums); + if (rc != 0) + return rc; + + return packet_l4_chksum(pkt_hdr, chksums); } int odp_packet_parse(odp_packet_t pkt, uint32_t offset, @@ -2363,7 +2476,12 @@ int odp_packet_parse(odp_packet_t pkt, uint32_t offset, layer, ethtype, param->chksums); + if (ret) + return -1; + } + if (layer == ODP_PROTO_LAYER_L4) { + ret = packet_l4_chksum(pkt_hdr, param->chksums); if (ret) return -1; }