fix problems related to loopback interface checksum omission. PR/29971.

- for ipv4, defer decision to ip layer as h/w checksum offloading does
  so that it can check the actual interface the packet is going to.
- for ipv6, disable it.
  (maybe will be revisited when it implements h/w checksum offloading.)

ok'ed by Jason Thorpe.
This commit is contained in:
yamt 2005-04-18 21:50:25 +00:00
parent 367b093823
commit e5a2b5a4a4
5 changed files with 37 additions and 48 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: ip_input.c,v 1.213 2005/03/29 09:37:08 yamt Exp $ */
/* $NetBSD: ip_input.c,v 1.214 2005/04/18 21:50:25 yamt Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@ -98,7 +98,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: ip_input.c,v 1.213 2005/03/29 09:37:08 yamt Exp $");
__KERNEL_RCSID(0, "$NetBSD: ip_input.c,v 1.214 2005/04/18 21:50:25 yamt Exp $");
#include "opt_inet.h"
#include "opt_gateway.h"
@ -200,7 +200,6 @@ int ipprintfs = 0;
#endif
int ip_do_randomid = 0;
int ip_do_loopback_cksum = 0;
/*
* XXX - Setting ip_checkinterface mostly implements the receive side of

View File

@ -1,4 +1,4 @@
/* $NetBSD: ip_output.c,v 1.150 2005/04/07 12:22:47 yamt Exp $ */
/* $NetBSD: ip_output.c,v 1.151 2005/04/18 21:50:25 yamt Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@ -98,7 +98,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: ip_output.c,v 1.150 2005/04/07 12:22:47 yamt Exp $");
__KERNEL_RCSID(0, "$NetBSD: ip_output.c,v 1.151 2005/04/18 21:50:25 yamt Exp $");
#include "opt_pfil_hooks.h"
#include "opt_inet.h"
@ -158,6 +158,16 @@ static void ip_mloopback(struct ifnet *, struct mbuf *, struct sockaddr_in *);
extern struct pfil_head inet_pfil_hook; /* XXX */
#endif
int udp_do_loopback_cksum = 0;
int tcp_do_loopback_cksum = 0;
int ip_do_loopback_cksum = 0;
#define IN_NEED_CHECKSUM(ifp, csum_flags) \
(__predict_true(((ifp)->if_flags & IFF_LOOPBACK) == 0 || \
(((csum_flags) & M_CSUM_UDPv4) != 0 && udp_do_loopback_cksum) || \
(((csum_flags) & M_CSUM_TCPv4) != 0 && tcp_do_loopback_cksum) || \
(((csum_flags) & M_CSUM_IPv4) != 0 && ip_do_loopback_cksum)))
/*
* IP output. The packet in mbuf chain m contains a skeletal IP
* header (with len, off, ttl, proto, tos, src, dst).
@ -788,9 +798,9 @@ spd_done:
#endif
/* Maybe skip checksums on loopback interfaces. */
if (__predict_true(!(ifp->if_flags & IFF_LOOPBACK) ||
ip_do_loopback_cksum))
if (IN_NEED_CHECKSUM(ifp, M_CSUM_IPv4)) {
m->m_pkthdr.csum_flags |= M_CSUM_IPv4;
}
sw_csum = m->m_pkthdr.csum_flags & ~ifp->if_csum_flags_tx;
/*
* If small enough for mtu of path, or if using TCP segmentation
@ -817,11 +827,15 @@ spd_done:
* XXX fields to be 0?
*/
if (sw_csum & M_CSUM_IPv4) {
KASSERT(IN_NEED_CHECKSUM(ifp, M_CSUM_IPv4));
ip->ip_sum = in_cksum(m, hlen);
m->m_pkthdr.csum_flags &= ~M_CSUM_IPv4;
}
if (sw_csum & (M_CSUM_TCPv4|M_CSUM_UDPv4)) {
in_delayed_cksum(m);
if (IN_NEED_CHECKSUM(ifp,
sw_csum & (M_CSUM_TCPv4|M_CSUM_UDPv4))) {
in_delayed_cksum(m);
}
m->m_pkthdr.csum_flags &=
~(M_CSUM_TCPv4|M_CSUM_UDPv4);
}
@ -842,7 +856,10 @@ spd_done:
* XXX Some hardware can do this.
*/
if (m->m_pkthdr.csum_flags & (M_CSUM_TCPv4|M_CSUM_UDPv4)) {
in_delayed_cksum(m);
if (IN_NEED_CHECKSUM(ifp,
m->m_pkthdr.csum_flags & (M_CSUM_TCPv4|M_CSUM_UDPv4))) {
in_delayed_cksum(m);
}
m->m_pkthdr.csum_flags &= ~(M_CSUM_TCPv4|M_CSUM_UDPv4);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: tcp_output.c,v 1.129 2005/03/29 20:09:24 yamt Exp $ */
/* $NetBSD: tcp_output.c,v 1.130 2005/04/18 21:50:25 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.129 2005/03/29 20:09:24 yamt Exp $");
__KERNEL_RCSID(0, "$NetBSD: tcp_output.c,v 1.130 2005/04/18 21:50:25 yamt Exp $");
#include "opt_inet.h"
#include "opt_ipsec.h"
@ -1306,7 +1306,7 @@ send:
/*
* Set ourselves up to be checksummed just before the packet
* hits the wire. Maybe skip checksums on loopback interfaces.
* hits the wire.
*/
switch (af) {
#ifdef INET
@ -1316,13 +1316,7 @@ send:
m->m_pkthdr.segsz = txsegsize;
m->m_pkthdr.csum_flags = M_CSUM_TSOv4;
} else {
if (__predict_true(ro->ro_rt == NULL ||
!(ro->ro_rt->rt_ifp->if_flags &
IFF_LOOPBACK) ||
tcp_do_loopback_cksum))
m->m_pkthdr.csum_flags = M_CSUM_TCPv4;
else
m->m_pkthdr.csum_flags = 0;
m->m_pkthdr.csum_flags = M_CSUM_TCPv4;
if (len + optlen) {
/* Fixup the pseudo-header checksum. */
/* XXXJRT Not IP Jumbogram safe. */
@ -1344,13 +1338,7 @@ send:
m->m_pkthdr.len = sizeof(struct ip6_hdr)
+ sizeof(struct tcphdr) + optlen + len;
#ifdef notyet
if (__predict_true(ro->ro_rt == NULL ||
!(ro->ro_rt->rt_ifp->if_flags &
IFF_LOOPBACK) ||
tcp_do_loopback_cksum))
m->m_pkthdr.csum_flags = M_CSUM_TCPv6;
else
m->m_pkthdr.csum_flags = 0;
m->m_pkthdr.csum_flags = M_CSUM_TCPv6;
m->m_pkthdr.csum_data = offsetof(struct tcphdr, th_sum);
#endif
if (len + optlen) {
@ -1359,14 +1347,8 @@ send:
th->th_sum = in_cksum_addword(th->th_sum,
htons((u_int16_t) (len + optlen)));
}
#ifndef notyet
if (__predict_true(ro->ro_rt == NULL ||
!(ro->ro_rt->rt_ifp->if_flags &
IFF_LOOPBACK) ||
tcp_do_loopback_cksum))
th->th_sum = in6_cksum(m, 0, sizeof(struct ip6_hdr),
sizeof(struct tcphdr) + optlen + len);
#endif
th->th_sum = in6_cksum(m, 0, sizeof(struct ip6_hdr),
sizeof(struct tcphdr) + optlen + len);
break;
#endif
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: tcp_subr.c,v 1.189 2005/04/05 01:07:17 kurahone Exp $ */
/* $NetBSD: tcp_subr.c,v 1.190 2005/04/18 21:50:25 yamt Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@ -98,7 +98,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: tcp_subr.c,v 1.189 2005/04/05 01:07:17 kurahone Exp $");
__KERNEL_RCSID(0, "$NetBSD: tcp_subr.c,v 1.190 2005/04/18 21:50:25 yamt Exp $");
#include "opt_inet.h"
#include "opt_ipsec.h"
@ -200,7 +200,6 @@ int tcp_compat_42 = 0;
#endif
int tcp_rst_ppslim = 100; /* 100pps */
int tcp_ackdrop_ppslim = 100; /* 100pps */
int tcp_do_loopback_cksum = 0;
int tcp_sack_tp_maxholes = 32;
int tcp_sack_globalmaxholes = 1024;
int tcp_sack_globalholes = 0;

View File

@ -1,4 +1,4 @@
/* $NetBSD: udp_usrreq.c,v 1.134 2005/03/11 06:16:16 atatat Exp $ */
/* $NetBSD: udp_usrreq.c,v 1.135 2005/04/18 21:50:25 yamt Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@ -61,7 +61,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: udp_usrreq.c,v 1.134 2005/03/11 06:16:16 atatat Exp $");
__KERNEL_RCSID(0, "$NetBSD: udp_usrreq.c,v 1.135 2005/04/18 21:50:25 yamt Exp $");
#include "opt_inet.h"
#include "opt_ipsec.h"
@ -146,7 +146,6 @@ int udpcksum = 1;
#else
int udpcksum = 0; /* XXX */
#endif
int udp_do_loopback_cksum = 0;
struct inpcbtable udbtable;
struct udpstat udpstat;
@ -1080,18 +1079,11 @@ udp_output(struct mbuf *m, ...)
/*
* XXX Cache pseudo-header checksum part for
* XXX "connected" UDP sockets.
* Maybe skip checksums on loopback interfaces.
*/
ui->ui_sum = in_cksum_phdr(ui->ui_src.s_addr,
ui->ui_dst.s_addr, htons((u_int16_t)len +
sizeof(struct udphdr) + IPPROTO_UDP));
if (__predict_true(ro->ro_rt == NULL ||
!(ro->ro_rt->rt_ifp->if_flags &
IFF_LOOPBACK) ||
udp_do_loopback_cksum))
m->m_pkthdr.csum_flags = M_CSUM_UDPv4;
else
m->m_pkthdr.csum_flags = 0;
m->m_pkthdr.csum_flags = M_CSUM_UDPv4;
m->m_pkthdr.csum_data = offsetof(struct udphdr, uh_sum);
} else
ui->ui_sum = 0;