Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. =================================================================== RCS file: /ftp/cvs/cvsroot/src/sys/netinet6/in6_cksum.c,v retrieving revision 1.22 retrieving revision 1.23 diff -u -p -r1.22 -r1.23 --- src/sys/netinet6/in6_cksum.c 2008/01/25 21:12:15 1.22 +++ src/sys/netinet6/in6_cksum.c 2008/02/12 13:02:24 1.23 @@ -1,153 +1,121 @@ -/* $NetBSD: in6_cksum.c,v 1.22 2008/01/25 21:12:15 joerg Exp $ */ -/* $KAME: in6_cksum.c,v 1.9 2000/09/09 15:33:31 itojun Exp $ */ +/* $NetBSD: in6_cksum.c,v 1.23 2008/02/12 13:02:24 joerg Exp $ */ -/* - * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. +/*- + * Copyright (c) 2008 Joerg Sonnenberger . * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the project nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -/* - * Copyright (c) 1988, 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)in_cksum.c 8.1 (Berkeley) 6/10/93 */ #include -__KERNEL_RCSID(0, "$NetBSD: in6_cksum.c,v 1.22 2008/01/25 21:12:15 joerg Exp $"); +__KERNEL_RCSID(0, "$NetBSD: in6_cksum.c,v 1.23 2008/02/12 13:02:24 joerg Exp $"); #include #include -#include #include #include -#include - -#include /* - * Checksum routine for Internet Protocol family headers (Portable Version). + * Checksum of the IPv6 pseudo header. * - * This routine is very heavily used in the network - * code and should be modified for each CPU to be as fast as possible. - */ - -#define ADDCARRY(x) (x > 65535 ? x -= 65535 : x) -#define REDUCE {l_util.l = sum; sum = l_util.s[0] + l_util.s[1]; ADDCARRY(sum);} - -/* - * m MUST contain a continuous IP6 header. - * off is a offset where TCP/UDP/ICMP6 header starts. - * len is a total length of a transport segment. - * (e.g. TCP header + TCP payload) + * off is supposed to be the skipped IPv6 header, len is the payload size. */ int -in6_cksum(struct mbuf *m, u_int8_t nxt, u_int32_t off, u_int32_t len) +in6_cksum(struct mbuf *m, u_int8_t nxt, uint32_t off, uint32_t len) { - u_int16_t *w; - uint32_t sum = 0; - struct ip6_hdr *ip6; - struct in6_addr in6; union { - u_int16_t phs[4]; + uint16_t words[16]; struct { - u_int32_t ph_len; - u_int8_t ph_zero[3]; - u_int8_t ph_nxt; - } ph __packed; - } uph; - - /* sanity check */ - if (m->m_pkthdr.len < off + len) { - panic("in6_cksum: mbuf len (%d) < off+len (%d+%d)", - m->m_pkthdr.len, off, len); - } + struct in6_addr ip6_src; + struct in6_addr ip6_dst; + } addrs; + } u; + struct in6_addr *in6_src, *in6_dst; + uint32_t sum; + uint16_t *w; + + if (off < sizeof(struct ip6_hdr)) + panic("in6_cksum: offset too short for IPv6 header"); + if (m->m_len < sizeof(struct ip6_hdr)) + panic("in6_cksum: mbuf too short for IPv6 header"); - /* Skip pseudo-header if nxt == 0. */ if (nxt == 0) - goto skip_phdr; - - bzero(&uph, sizeof(uph)); + return cpu_in_cksum(m, len, off, 0); /* - * First create IP6 pseudo header and calculate a summary. + * Compute the equivalent of: + * struct ip6_hdr_pseudo ip6; + * + * bzero(sizeof(*ip6)); + * ip6.ip6ph_nxt = nxt; + * ip6.ip6ph_len = htonl(len); + * ipv6.ip6ph_src = mtod(m, struct ip6_hdr *)->ip6_src; + * in6_clearscope(&ip6->ip6ph_src); + * ipv6.ip6ph_dst = mtod(m, struct ip6_hdr *)->ip6_dst; + * in6_clearscope(&ip6->ip6ph_dst); + * sum = one_add(&ip6); */ - ip6 = mtod(m, struct ip6_hdr *); - w = (u_int16_t *)&ip6->ip6_src; - uph.ph.ph_len = htonl(len); - uph.ph.ph_nxt = nxt; - /* - * IPv6 source address - * XXX: we'd like to avoid copying the address, but we can't due to - * the possibly embedded scope zone ID. - */ - in6 = ip6->ip6_src; - in6_clearscope(&in6); - w = (u_int16_t *)&in6; - sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3]; - sum += w[4]; sum += w[5]; sum += w[6]; sum += w[7]; - - /* IPv6 destination address */ - in6 = ip6->ip6_dst; - in6_clearscope(&in6); - w = (u_int16_t *)&in6; - sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3]; - sum += w[4]; sum += w[5]; sum += w[6]; sum += w[7]; - - /* Payload length and upper layer identifier */ - sum += uph.phs[0]; sum += uph.phs[1]; - sum += uph.phs[2]; sum += uph.phs[3]; +#if BYTE_ORDER == LITTLE_ENDIAN + sum = ((len & 0xffff) + ((len >> 16) & 0xffff) + nxt) << 8; +#else + sum = (len & 0xffff) + ((len >> 16) & 0xffff) + nxt; +#endif + w = (uint16_t *)(mtod(m, char *) + offsetof(struct ip6_hdr, ip6_src)); + if (__predict_true((uintptr_t)w % 2 == 0)) { + in6_src = &mtod(m, struct ip6_hdr *)->ip6_src; + in6_dst = &mtod(m, struct ip6_hdr *)->ip6_dst; + } else { + memcpy(&u, &mtod(m, struct ip6_hdr *)->ip6_src, 32); + w = u.words; + in6_src = &u.addrs.ip6_src; + in6_dst = &u.addrs.ip6_dst; + } + + sum += w[0]; + if (!IN6_IS_SCOPE_LINKLOCAL(in6_src) && + !IN6_IS_ADDR_MC_INTFACELOCAL(in6_src)) + sum += w[1]; + sum += w[2]; + sum += w[3]; + sum += w[4]; + sum += w[5]; + sum += w[6]; + sum += w[7]; + w += 8; + sum += w[0]; + if (!IN6_IS_SCOPE_LINKLOCAL(in6_dst) && + !IN6_IS_ADDR_MC_INTFACELOCAL(in6_dst)) + sum += w[1]; + sum += w[2]; + sum += w[3]; + sum += w[4]; + sum += w[5]; + sum += w[6]; + sum += w[7]; - skip_phdr: return cpu_in_cksum(m, len, off, sum); }