ipv6 tx checksum offloading. reviewed by Jason Thorpe.
This commit is contained in:
parent
55ca57f0a2
commit
40a140d919
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: tcp_output.c,v 1.137 2005/07/19 17:00:02 christos Exp $ */
|
||||
/* $NetBSD: tcp_output.c,v 1.138 2005/08/10 12:58:37 yamt Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
|
||||
|
@ -140,7 +140,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: tcp_output.c,v 1.137 2005/07/19 17:00:02 christos Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: tcp_output.c,v 1.138 2005/08/10 12:58:37 yamt Exp $");
|
||||
|
||||
#include "opt_inet.h"
|
||||
#include "opt_ipsec.h"
|
||||
|
@ -1344,27 +1344,14 @@ send:
|
|||
#endif
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
/*
|
||||
* XXX Actually delaying the checksum is Hard
|
||||
* XXX (well, maybe not for Itojun, but it is
|
||||
* XXX for me), but we can still take advantage
|
||||
* XXX of the cached pseudo-header checksum.
|
||||
*/
|
||||
/* equals to hdrlen + len */
|
||||
m->m_pkthdr.len = sizeof(struct ip6_hdr)
|
||||
+ sizeof(struct tcphdr) + optlen + len;
|
||||
#ifdef notyet
|
||||
m->m_pkthdr.csum_flags = M_CSUM_TCPv6;
|
||||
m->m_pkthdr.csum_data = offsetof(struct tcphdr, th_sum);
|
||||
#endif
|
||||
m->m_pkthdr.csum_flags = M_CSUM_TCPv6;
|
||||
if (len + optlen) {
|
||||
/* Fixup the pseudo-header checksum. */
|
||||
/* XXXJRT: Not IPv6 Jumbogram safe. */
|
||||
th->th_sum = in_cksum_addword(th->th_sum,
|
||||
htons((u_int16_t) (len + optlen)));
|
||||
}
|
||||
th->th_sum = in6_cksum(m, 0, sizeof(struct ip6_hdr),
|
||||
sizeof(struct tcphdr) + optlen + len);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: in6.h,v 1.45 2004/06/11 04:10:10 itojun Exp $ */
|
||||
/* $NetBSD: in6.h,v 1.46 2005/08/10 12:58:37 yamt Exp $ */
|
||||
/* $KAME: in6.h,v 1.83 2001/03/29 02:55:07 jinmei Exp $ */
|
||||
|
||||
/*
|
||||
|
@ -647,6 +647,7 @@ in6_cksum_phdr(const struct in6_addr *src, const struct in6_addr *dst,
|
|||
}
|
||||
|
||||
int in6_cksum __P((struct mbuf *, u_int8_t, u_int32_t, u_int32_t));
|
||||
void in6_delayed_cksum __P((struct mbuf *));
|
||||
int in6_localaddr __P((struct in6_addr *));
|
||||
int in6_addrscope __P((struct in6_addr *));
|
||||
struct in6_ifaddr *in6_ifawithscope __P((struct ifnet *, struct in6_addr *));
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: ip6_output.c,v 1.88 2005/02/28 09:27:07 itojun Exp $ */
|
||||
/* $NetBSD: ip6_output.c,v 1.89 2005/08/10 12:58:37 yamt Exp $ */
|
||||
/* $KAME: ip6_output.c,v 1.172 2001/03/25 09:55:56 itojun Exp $ */
|
||||
|
||||
/*
|
||||
|
@ -62,7 +62,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: ip6_output.c,v 1.88 2005/02/28 09:27:07 itojun Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: ip6_output.c,v 1.89 2005/08/10 12:58:37 yamt Exp $");
|
||||
|
||||
#include "opt_inet.h"
|
||||
#include "opt_ipsec.h"
|
||||
|
@ -167,6 +167,8 @@ ip6_output(m0, opt, ro, flags, im6o, so, ifpp)
|
|||
ip6 = mtod(m, struct ip6_hdr *);
|
||||
#endif /* IPSEC */
|
||||
|
||||
M_CSUM_DATA_IPv6_HL_SET(m->m_pkthdr.csum_data, sizeof(struct ip6_hdr));
|
||||
|
||||
#define MAKE_EXTHDR(hp, mp) \
|
||||
do { \
|
||||
if (hp) { \
|
||||
|
@ -248,6 +250,12 @@ ip6_output(m0, opt, ro, flags, im6o, so, ifpp)
|
|||
skippolicycheck:;
|
||||
#endif /* IPSEC */
|
||||
|
||||
if (needipsec &&
|
||||
(m->m_pkthdr.csum_flags & (M_CSUM_UDPv6|M_CSUM_TCPv6)) != 0) {
|
||||
in6_delayed_cksum(m);
|
||||
m->m_pkthdr.csum_flags &= ~(M_CSUM_UDPv6|M_CSUM_TCPv6);
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the total length of the extension header chain.
|
||||
* Keep the length of the unfragmentable part for fragmentation.
|
||||
|
@ -294,6 +302,7 @@ ip6_output(m0, opt, ro, flags, im6o, so, ifpp)
|
|||
ip6 = mtod(m, struct ip6_hdr *);
|
||||
if ((error = ip6_insert_jumboopt(&exthdrs, plen)) != 0)
|
||||
goto freehdrs;
|
||||
optlen += 8; /* XXX JUMBOOPTLEN */
|
||||
ip6->ip6_plen = 0;
|
||||
} else
|
||||
ip6->ip6_plen = htons(plen);
|
||||
|
@ -353,6 +362,9 @@ ip6_output(m0, opt, ro, flags, im6o, so, ifpp)
|
|||
MAKE_CHAIN(exthdrs.ip6e_rthdr, mprev, nexthdrp,
|
||||
IPPROTO_ROUTING);
|
||||
|
||||
M_CSUM_DATA_IPv6_HL_SET(m->m_pkthdr.csum_data,
|
||||
sizeof(struct ip6_hdr) + optlen);
|
||||
|
||||
#ifdef IPSEC
|
||||
if (!needipsec)
|
||||
goto skip_ipsec2;
|
||||
|
@ -868,6 +880,7 @@ skip_ipsec2:;
|
|||
*/
|
||||
if (dontfrag || (!alwaysfrag && tlen <= mtu)) { /* case 1-a and 2-a */
|
||||
struct in6_ifaddr *ia6;
|
||||
int sw_csum;
|
||||
|
||||
ip6 = mtod(m, struct ip6_hdr *);
|
||||
ia6 = in6_ifawithifp(ifp, &ip6->ip6_src);
|
||||
|
@ -879,6 +892,13 @@ skip_ipsec2:;
|
|||
/* clean ipsec history once it goes out of the node */
|
||||
ipsec_delaux(m);
|
||||
#endif
|
||||
|
||||
sw_csum = m->m_pkthdr.csum_flags & ~ifp->if_csum_flags_tx;
|
||||
if ((sw_csum & (M_CSUM_UDPv6|M_CSUM_TCPv6)) != 0) {
|
||||
in6_delayed_cksum(m);
|
||||
m->m_pkthdr.csum_flags &= ~(M_CSUM_UDPv6|M_CSUM_TCPv6);
|
||||
}
|
||||
|
||||
error = nd6_output(ifp, origifp, m, dst, ro->ro_rt);
|
||||
goto done;
|
||||
}
|
||||
|
@ -947,6 +967,12 @@ skip_ipsec2:;
|
|||
ip6->ip6_nxt = IPPROTO_FRAGMENT;
|
||||
}
|
||||
|
||||
if ((m->m_pkthdr.csum_flags & (M_CSUM_UDPv6|M_CSUM_TCPv6))
|
||||
!= 0) {
|
||||
in6_delayed_cksum(m);
|
||||
m->m_pkthdr.csum_flags &= ~(M_CSUM_UDPv6|M_CSUM_TCPv6);
|
||||
}
|
||||
|
||||
/*
|
||||
* Loop through length of segment after first fragment,
|
||||
* make new header and copy data of each part and link onto
|
||||
|
@ -1091,6 +1117,33 @@ ip6_copyexthdr(mp, hdr, hlen)
|
|||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Process a delayed payload checksum calculation.
|
||||
*/
|
||||
void
|
||||
in6_delayed_cksum(struct mbuf *m)
|
||||
{
|
||||
uint16_t csum, offset;
|
||||
|
||||
KASSERT((m->m_pkthdr.csum_flags & (M_CSUM_UDPv6|M_CSUM_TCPv6)) != 0);
|
||||
KASSERT((~m->m_pkthdr.csum_flags & (M_CSUM_UDPv6|M_CSUM_TCPv6)) != 0);
|
||||
KASSERT((m->m_pkthdr.csum_flags
|
||||
& (M_CSUM_UDPv4|M_CSUM_TCPv4|M_CSUM_TSOv4)) == 0);
|
||||
|
||||
offset = M_CSUM_DATA_IPv6_HL(m->m_pkthdr.csum_data);
|
||||
csum = in6_cksum(m, 0, offset, m->m_pkthdr.len - offset);
|
||||
if (csum == 0 && (m->m_pkthdr.csum_flags & M_CSUM_UDPv6) != 0) {
|
||||
csum = 0xffff;
|
||||
}
|
||||
|
||||
offset += M_CSUM_DATA_IPv6_OFFSET(m->m_pkthdr.csum_data);
|
||||
if ((offset + sizeof(csum)) > m->m_len) {
|
||||
m_copyback(m, offset, sizeof(csum), &csum);
|
||||
} else {
|
||||
*(uint16_t *)(mtod(m, caddr_t) + offset) = csum;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Insert jumbo payload option.
|
||||
*/
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: udp6_output.c,v 1.20 2005/04/22 11:56:33 yamt Exp $ */
|
||||
/* $NetBSD: udp6_output.c,v 1.21 2005/08/10 12:58:37 yamt Exp $ */
|
||||
/* $KAME: udp6_output.c,v 1.43 2001/10/15 09:19:52 itojun Exp $ */
|
||||
|
||||
/*
|
||||
|
@ -62,7 +62,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: udp6_output.c,v 1.20 2005/04/22 11:56:33 yamt Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: udp6_output.c,v 1.21 2005/08/10 12:58:37 yamt Exp $");
|
||||
|
||||
#include "opt_inet.h"
|
||||
|
||||
|
@ -330,10 +330,10 @@ udp6_output(in6p, m, addr6, control, p)
|
|||
ip6->ip6_src = *laddr;
|
||||
ip6->ip6_dst = *faddr;
|
||||
|
||||
if ((udp6->uh_sum = in6_cksum(m, IPPROTO_UDP,
|
||||
sizeof(struct ip6_hdr), plen)) == 0) {
|
||||
udp6->uh_sum = 0xffff;
|
||||
}
|
||||
udp6->uh_sum = in6_cksum_phdr(laddr, faddr,
|
||||
htonl(plen), htonl(IPPROTO_UDP));
|
||||
m->m_pkthdr.csum_flags = M_CSUM_UDPv6;
|
||||
m->m_pkthdr.csum_data = offsetof(struct udphdr, uh_sum);
|
||||
|
||||
if (in6p->in6p_flags & IN6P_MINMTU)
|
||||
flags |= IPV6_MINMTU;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: mbuf.h,v 1.113 2005/07/26 22:52:48 dyoung Exp $ */
|
||||
/* $NetBSD: mbuf.h,v 1.114 2005/08/10 12:58:37 yamt Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1996, 1997, 1999, 2001 The NetBSD Foundation, Inc.
|
||||
|
@ -188,6 +188,19 @@ struct pkthdr {
|
|||
#define M_CSUM_DATA_IPv4_IPHL(x) ((x) >> 16)
|
||||
#define M_CSUM_DATA_IPv4_OFFSET(x) ((x) & 0xffff)
|
||||
|
||||
/*
|
||||
* Macros for M_CSUM_TCPv6 and M_CSUM_UDPv6
|
||||
*
|
||||
* M_CSUM_DATA_IPv6_HL: length of ip6_hdr + ext header.
|
||||
* ie. offset of UDP/TCP header in the packet.
|
||||
*
|
||||
* M_CSUM_DATA_IPv6_OFFSET: offset of the checksum field in UDP/TCP header.
|
||||
*/
|
||||
|
||||
#define M_CSUM_DATA_IPv6_HL(x) ((x) >> 16)
|
||||
#define M_CSUM_DATA_IPv6_HL_SET(x, v) (x) = ((x) & 0xffff) | ((v) << 16)
|
||||
#define M_CSUM_DATA_IPv6_OFFSET(x) ((x) & 0xffff)
|
||||
|
||||
/*
|
||||
* Max # of pages we can attach to m_ext. This is carefully chosen
|
||||
* to be able to handle SOSEND_LOAN_CHUNK with our minimum sized page.
|
||||
|
|
Loading…
Reference in New Issue