Subject: Skipping TCP / UDP / IP checksums on loopback traffic
To: NetBSD-network <tech-net@netbsd.org>
From: Jason Thorpe <thorpej@shagadelic.org>
List: tech-net
Date: 10/23/2004 10:40:59
--Apple-Mail-23--13025068
Content-Type: multipart/mixed; boundary=Apple-Mail-22--13025075


--Apple-Mail-22--13025075
Content-Transfer-Encoding: 7bit
Content-Type: text/plain;
	charset=US-ASCII;
	format=flowed

Folks...

There's no need to compute or check checksums for traffic over the 
loopback interface.  The following patch makes it optional, and 
defaults to "off".  Linux also skips checksums in this case, which 
results in poor results for NetBSD compared to Linux in some 
benchmarks.

Comments?

         -- Jason R. Thorpe <thorpej@shagadelic.org>

--Apple-Mail-22--13025075
Content-Transfer-Encoding: 7bit
Content-Type: text/plain;
	x-unix-mode=0644;
	name="loopback-cksum-diffs.txt"
Content-Disposition: attachment;
	filename=loopback-cksum-diffs.txt

Index: netinet/in.h
===================================================================
RCS file: /cvsroot/src/sys/netinet/in.h,v
retrieving revision 1.68
diff -u -p -r1.68 in.h
--- netinet/in.h	4 Sep 2004 23:30:07 -0000	1.68
+++ netinet/in.h	23 Oct 2004 17:29:36 -0000
@@ -437,7 +437,8 @@ struct ip_mreq {
 #define	IPCTL_CHECKINTERFACE   20	/* drop pkts in from 'wrong' iface */
 #define	IPCTL_IFQ	       21	/* ipintrq node */
 #define	IPCTL_RANDOMID	       22	/* use random IP ids (if configured) */
-#define	IPCTL_MAXID	       23
+#define	IPCTL_LOOPBACKCKSUM    23	/* do IP checksum on loopback */
+#define	IPCTL_MAXID	       24
 
 #define	IPCTL_NAMES { \
 	{ 0, 0 }, \
@@ -463,6 +464,7 @@ struct ip_mreq {
 	{ "checkinterface", CTLTYPE_INT }, \
 	{ "ifq", CTLTYPE_NODE }, \
 	{ "random_id", CTLTYPE_INT }, \
+	{ "do_loopback_cksum", CTLTYPE_INT }, \
 }
 #endif /* _NETBSD_SOURCE */
 
Index: netinet/ip_input.c
===================================================================
RCS file: /cvsroot/src/sys/netinet/ip_input.c,v
retrieving revision 1.205
diff -u -p -r1.205 ip_input.c
--- netinet/ip_input.c	6 Oct 2004 01:34:11 -0000	1.205
+++ netinet/ip_input.c	23 Oct 2004 17:29:38 -0000
@@ -200,6 +200,7 @@ 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
@@ -572,10 +573,16 @@ ip_input(struct mbuf *m)
 		break;
 
 	default:
-		/* Must compute it ourselves. */
-		INET_CSUM_COUNTER_INCR(&ip_swcsum);
-		if (in_cksum(m, hlen) != 0)
-			goto badcsum;
+		/*
+		 * Must compute it ourselves.  Maybe skip checksum on
+		 * loopback interfaces.
+		 */
+		if (__predict_true(!(m->m_pkthdr.rcvif->if_flags &
+				     IFF_LOOPBACK) || ip_do_loopback_cksum)) {
+			INET_CSUM_COUNTER_INCR(&ip_swcsum);
+			if (in_cksum(m, hlen) != 0)
+				goto badcsum;
+		}
 		break;
 	}
 
@@ -2342,4 +2349,11 @@ SYSCTL_SETUP(sysctl_net_inet_ip_setup, "
 		       NULL, 0, &ip_do_randomid, 0,
 		       CTL_NET, PF_INET, IPPROTO_IP,
 		       IPCTL_RANDOMID, CTL_EOL);
+	sysctl_createv(clog, 0, NULL, NULL,
+		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
+		       CTLTYPE_INT, "do_loopback_cksum",
+		       SYSCTL_DESCR("Perform IP checksum on loopback"),
+		       NULL, 0, &ip_do_loopback_cksum, 0,
+		       CTL_NET, PF_INET, IPPROTO_IP,
+		       IPCTL_LOOPBACKCKSUM, CTL_EOL);
 }
Index: netinet/ip_output.c
===================================================================
RCS file: /cvsroot/src/sys/netinet/ip_output.c,v
retrieving revision 1.136
diff -u -p -r1.136 ip_output.c
--- netinet/ip_output.c	6 Oct 2004 05:42:24 -0000	1.136
+++ netinet/ip_output.c	23 Oct 2004 17:29:39 -0000
@@ -745,7 +745,10 @@ spd_done:
 	INADDR_TO_IA(ip->ip_src, ia);
 #endif
 
-	m->m_pkthdr.csum_flags |= M_CSUM_IPv4;
+	/* Maybe skip checksums on loopback interfaces. */
+	if (__predict_true(!(ifp->if_flags & IFF_LOOPBACK) ||
+			   ip_do_loopback_cksum))
+		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, can just send directly.
Index: netinet/ip_var.h
===================================================================
RCS file: /cvsroot/src/sys/netinet/ip_var.h,v
retrieving revision 1.68
diff -u -p -r1.68 ip_var.h
--- netinet/ip_var.h	22 Apr 2004 01:01:41 -0000	1.68
+++ netinet/ip_var.h	23 Oct 2004 17:29:39 -0000
@@ -205,6 +205,7 @@ extern int   anonportmin;		/* minimum ep
 extern int   anonportmax;		/* maximum ephemeral port */
 extern int   lowportmin;		/* minimum reserved port */
 extern int   lowportmax;		/* maximum reserved port */
+extern int   ip_do_loopback_cksum;	/* do IP checksum on loopback? */
 extern struct rttimer_queue *ip_mtudisc_timeout_q;
 #ifdef MBUFTRACE
 extern struct mowner ip_rx_mowner;
Index: netinet/tcp_input.c
===================================================================
RCS file: /cvsroot/src/sys/netinet/tcp_input.c,v
retrieving revision 1.209
diff -u -p -r1.209 tcp_input.c
--- netinet/tcp_input.c	15 Sep 2004 09:21:22 -0000	1.209
+++ netinet/tcp_input.c	23 Oct 2004 17:29:42 -0000
@@ -1135,10 +1135,18 @@ findpcb:
 			break;
 
 		default:
-			/* Must compute it ourselves. */
-			TCP_CSUM_COUNTER_INCR(&tcp_swcsum);
-			if (in4_cksum(m, IPPROTO_TCP, toff, tlen + off) != 0)
-				goto badcsum;
+			/*
+			 * Must compute it ourselves.  Maybe skip checksum
+			 * on loopback interfaces.
+			 */
+			if (__predict_true(!(m->m_pkthdr.rcvif->if_flags &
+					     IFF_LOOPBACK) ||
+					   tcp_do_loopback_cksum)) {
+				TCP_CSUM_COUNTER_INCR(&tcp_swcsum);
+				if (in4_cksum(m, IPPROTO_TCP, toff,
+					      tlen + off) != 0)
+					goto badcsum;
+			}
 			break;
 		}
 		break;
Index: netinet/tcp_output.c
===================================================================
RCS file: /cvsroot/src/sys/netinet/tcp_output.c,v
retrieving revision 1.114
diff -u -p -r1.114 tcp_output.c
--- netinet/tcp_output.c	20 May 2004 22:59:02 -0000	1.114
+++ netinet/tcp_output.c	23 Oct 2004 17:29:43 -0000
@@ -1099,12 +1099,18 @@ send:
 
 	/*
 	 * Set ourselves up to be checksummed just before the packet
-	 * hits the wire.
+	 * hits the wire.  Maybe skip checksums on loopback interfaces.
 	 */
 	switch (af) {
 #ifdef INET
 	case AF_INET:
-		m->m_pkthdr.csum_flags = M_CSUM_TCPv4;
+		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_data = offsetof(struct tcphdr, th_sum);
 		if (len + optlen) {
 			/* Fixup the pseudo-header checksum. */
@@ -1126,7 +1132,13 @@ send:
 		m->m_pkthdr.len = sizeof(struct ip6_hdr)
 			+ sizeof(struct tcphdr) + optlen + len;
 #ifdef notyet
-		m->m_pkthdr.csum_flags = M_CSUM_TCPv6;
+		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_data = offsetof(struct tcphdr, th_sum);
 #endif
 		if (len + optlen) {
@@ -1136,8 +1148,12 @@ send:
 			    htons((u_int16_t) (len + optlen)));
 		}
 #ifndef notyet
-		th->th_sum = in6_cksum(m, 0, sizeof(struct ip6_hdr),
-		    sizeof(struct tcphdr) + optlen + len);
+		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
 		break;
 #endif
Index: netinet/tcp_subr.c
===================================================================
RCS file: /cvsroot/src/sys/netinet/tcp_subr.c,v
retrieving revision 1.173
diff -u -p -r1.173 tcp_subr.c
--- netinet/tcp_subr.c	15 Sep 2004 09:21:22 -0000	1.173
+++ netinet/tcp_subr.c	23 Oct 2004 17:29:45 -0000
@@ -200,6 +200,7 @@ int	tcp_compat_42 = 0;
 #endif
 int	tcp_rst_ppslim = 100;	/* 100pps */
 int	tcp_ackdrop_ppslim = 100;	/* 100pps */
+int	tcp_do_loopback_cksum = 0;
 
 /* tcb hash */
 #ifndef TCBHASHSIZE
Index: netinet/tcp_usrreq.c
===================================================================
RCS file: /cvsroot/src/sys/netinet/tcp_usrreq.c,v
retrieving revision 1.92
diff -u -p -r1.92 tcp_usrreq.c
--- netinet/tcp_usrreq.c	25 May 2004 04:34:00 -0000	1.92
+++ netinet/tcp_usrreq.c	23 Oct 2004 17:29:46 -0000
@@ -1391,6 +1391,13 @@ sysctl_net_inet_tcp_setup2(struct sysctl
 		       SYSCTL_DESCR("RFC1413 Identification Protocol lookups"),
 		       sysctl_net_inet_tcp_ident, 0, NULL, sizeof(uid_t),
 		       CTL_NET, pf, IPPROTO_TCP, TCPCTL_IDENT, CTL_EOL);
+	sysctl_createv(clog, 0, NULL, NULL,
+		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
+		       CTLTYPE_INT, "do_loopback_cksum",
+		       SYSCTL_DESCR("Perform TCP checksum on loopback"),
+		       NULL, 0, &tcp_do_loopback_cksum, 0,
+		       CTL_NET, pf, IPPROTO_TCP, TCPCTL_LOOPBACKCKSUM,
+		       CTL_EOL);
 }
 
 /*
Index: netinet/tcp_var.h
===================================================================
RCS file: /cvsroot/src/sys/netinet/tcp_var.h,v
retrieving revision 1.113
diff -u -p -r1.113 tcp_var.h
--- netinet/tcp_var.h	15 Sep 2004 09:21:22 -0000	1.113
+++ netinet/tcp_var.h	23 Oct 2004 17:29:47 -0000
@@ -622,7 +622,8 @@ struct	tcpstat {
 #define	TCPCTL_INIT_WIN_LOCAL	26	/* initial window for local nets */
 #define	TCPCTL_IDENT		27	/* rfc 931 identd */
 #define	TCPCTL_ACKDROPRATELIMIT	28	/* SYN/RST -> ACK rate limit */
-#define	TCPCTL_MAXID		29
+#define	TCPCTL_LOOPBACKCKSUM	29	/* do TCP checksum on loopback */
+#define	TCPCTL_MAXID		30
 
 #define	TCPCTL_NAMES { \
 	{ 0, 0 }, \
@@ -654,6 +655,7 @@ struct	tcpstat {
 	{ "init_win_local", CTLTYPE_INT }, \
 	{ "ident", CTLTYPE_STRUCT }, \
 	{ "ackdropppslimit", CTLTYPE_INT }, \
+	{ "do_loopback_cksum", CTLTYPE_INT }, \
 }
 
 #ifdef _KERNEL
@@ -676,6 +678,7 @@ extern	int tcp_ack_on_push;	/* ACK immed
 extern	int tcp_syn_cache_limit; /* max entries for compressed state engine */
 extern	int tcp_syn_bucket_limit;/* max entries per hash bucket */
 extern	int tcp_log_refused;	/* log refused connections */
+extern	int tcp_do_loopback_cksum;/* do TCP checksum on loopback? */
 
 extern	int tcp_rst_ppslim;
 extern	int tcp_ackdrop_ppslim;
Index: netinet/udp_usrreq.c
===================================================================
RCS file: /cvsroot/src/sys/netinet/udp_usrreq.c,v
retrieving revision 1.124
diff -u -p -r1.124 udp_usrreq.c
--- netinet/udp_usrreq.c	3 Sep 2004 18:14:09 -0000	1.124
+++ netinet/udp_usrreq.c	23 Oct 2004 17:29:47 -0000
@@ -141,6 +141,7 @@ int	udpcksum = 1;
 #else
 int	udpcksum = 0;		/* XXX */
 #endif
+int	udp_do_loopback_cksum = 0;
 
 struct	inpcbtable udbtable;
 struct	udpstat udpstat;
@@ -287,10 +288,17 @@ udp_input(struct mbuf *m, ...)
 			break;
 
 		default:
-			/* Need to compute it ourselves. */
-			UDP_CSUM_COUNTER_INCR(&udp_swcsum);
-			if (in4_cksum(m, IPPROTO_UDP, iphlen, len) != 0)
-				goto badcsum;
+			/*
+			 * Need to compute it ourselves.  Maybe skip checksum
+			 * on loopback interfaces.
+			 */
+			if (__predict_true(!(m->m_pkthdr.rcvif->if_flags &
+					     IFF_LOOPBACK) ||
+					   udp_do_loopback_cksum)) {
+				UDP_CSUM_COUNTER_INCR(&udp_swcsum);
+				if (in4_cksum(m, IPPROTO_UDP, iphlen, len) != 0)
+					goto badcsum;
+			}
 			break;
 		}
 	}
@@ -419,15 +427,20 @@ udp6_input(struct mbuf **mp, int *offp, 
 	}
 
 	/*
-	 * Checksum extended UDP header and data.
+	 * Checksum extended UDP header and data.  Maybe skip checksum
+	 * on loopback interfaces.
 	 */
-	if (uh->uh_sum == 0) {
-		udp6stat.udp6s_nosum++;
-		goto bad;
-	}
-	if (in6_cksum(m, IPPROTO_UDP, off, ulen) != 0) {
-		udp6stat.udp6s_badsum++;
-		goto bad;
+	if (__predict_true(!(m->m_pkthdr.rcvif->if_flags &
+			     IFF_LOOPBACK) ||
+			   udp_do_loopback_cksum)) {
+		if (uh->uh_sum == 0) {
+			udp6stat.udp6s_nosum++;
+			goto bad;
+		}
+		if (in6_cksum(m, IPPROTO_UDP, off, ulen) != 0) {
+			udp6stat.udp6s_badsum++;
+			goto bad;
+		}
 	}
 
 	/*
@@ -830,6 +843,7 @@ udp_output(struct mbuf *m, ...)
 {
 	struct inpcb *inp;
 	struct udpiphdr *ui;
+	struct route *ro;
 	int len = m->m_pkthdr.len;
 	int error = 0;
 	va_list ap;
@@ -870,6 +884,8 @@ udp_output(struct mbuf *m, ...)
 	ui->ui_dport = inp->inp_fport;
 	ui->ui_ulen = htons((u_int16_t)len + sizeof(struct udphdr));
 
+	ro = &inp->inp_route;
+
 	/*
 	 * Set up checksum and output datagram.
 	 */
@@ -877,11 +893,18 @@ 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));
-		m->m_pkthdr.csum_flags = M_CSUM_UDPv4;
+		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_data = offsetof(struct udphdr, uh_sum);
 	} else
 		ui->ui_sum = 0;
@@ -890,7 +913,7 @@ udp_output(struct mbuf *m, ...)
 	((struct ip *)ui)->ip_tos = inp->inp_ip.ip_tos;	/* XXX */
 	udpstat.udps_opackets++;
 
-	return (ip_output(m, inp->inp_options, &inp->inp_route,
+	return (ip_output(m, inp->inp_options, ro,
 	    inp->inp_socket->so_options & (SO_DONTROUTE | SO_BROADCAST),
 	    inp->inp_moptions, inp->inp_socket));
 
@@ -1117,5 +1140,12 @@ SYSCTL_SETUP(sysctl_net_inet_udp_setup, 
 		       NULL, 0, &udp_recvspace, 0,
 		       CTL_NET, PF_INET, IPPROTO_UDP, UDPCTL_RECVSPACE,
 		       CTL_EOL);
+	sysctl_createv(clog, 0, NULL, NULL,
+		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
+		       CTLTYPE_INT, "do_loopback_cksum",
+		       SYSCTL_DESCR("Perform UDP checksum on loopback"),
+		       NULL, 0, &udp_do_loopback_cksum, 0,
+		       CTL_NET, PF_INET, IPPROTO_UDP, UDPCTL_LOOPBACKCKSUM,
+		       CTL_EOL);
 }
 #endif
Index: netinet/udp_var.h
===================================================================
RCS file: /cvsroot/src/sys/netinet/udp_var.h,v
retrieving revision 1.24
diff -u -p -r1.24 udp_var.h
--- netinet/udp_var.h	21 Apr 2004 17:49:46 -0000	1.24
+++ netinet/udp_var.h	23 Oct 2004 17:29:47 -0000
@@ -71,18 +71,21 @@ struct	udpstat {
 #define	UDPCTL_CHECKSUM		1	/* checksum UDP packets */
 #define	UDPCTL_SENDSPACE	2	/* default send buffer */
 #define	UDPCTL_RECVSPACE	3	/* default recv buffer */
-#define	UDPCTL_MAXID		4
+#define	UDPCTL_LOOPBACKCKSUM	4	/* do UDP checksum on loopback */
+#define	UDPCTL_MAXID		5
 
 #define UDPCTL_NAMES { \
 	{ 0, 0 }, \
 	{ "checksum", CTLTYPE_INT }, \
 	{ "sendspace", CTLTYPE_INT }, \
 	{ "recvspace", CTLTYPE_INT }, \
+	{ "do_loopback_cksum", CTLTYPE_INT }, \
 }
 
 #ifdef _KERNEL
 extern	struct	inpcbtable udbtable;
 extern	struct	udpstat udpstat;
+extern	int	udp_do_loopback_cksum;
 
 #ifdef __NO_STRICT_ALIGNMENT
 #define	UDP_HDR_ALIGNED_P(uh)	1
Index: netinet6/udp6_output.c
===================================================================
RCS file: /cvsroot/src/sys/netinet6/udp6_output.c,v
retrieving revision 1.18
diff -u -p -r1.18 udp6_output.c
--- netinet6/udp6_output.c	11 Jun 2004 04:10:10 -0000	1.18
+++ netinet6/udp6_output.c	23 Oct 2004 17:29:48 -0000
@@ -330,9 +330,15 @@ 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;
+		/* Maybe skip checksum on loopback interfaces. */
+		if (__predict_true(in6p->in6p_route.ro_rt == NULL ||
+				   !(in6p->in6p_route.ro_rt->rt_ifp->if_flags &
+				     IFF_LOOPBACK) ||
+				   udp_do_loopback_cksum)) {
+			if ((udp6->uh_sum = in6_cksum(m, IPPROTO_UDP,
+					sizeof(struct ip6_hdr), plen)) == 0) {
+				udp6->uh_sum = 0xffff;
+			}
 		}
 
 		if (in6p->in6p_flags & IN6P_MINMTU)
@@ -361,9 +367,16 @@ udp6_output(in6p, m, addr6, control, p)
 		flags = (in6p->in6p_socket->so_options &
 			 (SO_DONTROUTE | SO_BROADCAST));
 		bcopy(&faddr->s6_addr[12], &ui->ui_dst, sizeof(ui->ui_dst));
-		udp6->uh_sum = in_cksum(m, hlen + plen);
-		if (udp6->uh_sum == 0)
-			udp6->uh_sum = 0xffff;
+
+		/* Maybe skip checksum on loopback interfaces. */
+		if (__predict_true(in6p->in6p_route.ro_rt == NULL ||
+				   !(in6p->in6p_route.ro_rt->rt_ifp->if_flags &
+				     IFF_LOOPBACK) ||
+				   udp_do_loopback_cksum)) {
+			udp6->uh_sum = in_cksum(m, hlen + plen);
+			if (udp6->uh_sum == 0)
+				udp6->uh_sum = 0xffff;
+		}
 
 		ip->ip_len = htons(hlen + plen);
 		ip->ip_ttl = in6_selecthlim(in6p, NULL); /* XXX */
Index: netinet6/udp6_usrreq.c
===================================================================
RCS file: /cvsroot/src/sys/netinet6/udp6_usrreq.c,v
retrieving revision 1.63
diff -u -p -r1.63 udp6_usrreq.c
--- netinet6/udp6_usrreq.c	25 May 2004 04:34:01 -0000	1.63
+++ netinet6/udp6_usrreq.c	23 Oct 2004 17:29:48 -0000
@@ -445,4 +445,11 @@ SYSCTL_SETUP(sysctl_net_inet6_udp6_setup
 		       NULL, 0, &udp6_recvspace, 0,
 		       CTL_NET, PF_INET6, IPPROTO_UDP, UDP6CTL_RECVSPACE,
 		       CTL_EOL);
+	sysctl_createv(clog, 0, NULL, NULL,
+		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
+		       CTLTYPE_INT, "do_loopback_cksum",
+		       SYSCTL_DESCR("Perform UDP checksum on loopback"),
+		       NULL, 0, &udp_do_loopback_cksum, 0,
+		       CTL_NET, PF_INET6, IPPROTO_UDP, UDP6CTL_LOOPBACKCKSUM,
+		       CTL_EOL);
 }
Index: netinet6/udp6_var.h
===================================================================
RCS file: /cvsroot/src/sys/netinet6/udp6_var.h,v
retrieving revision 1.15
diff -u -p -r1.15 udp6_var.h
--- netinet6/udp6_var.h	4 Sep 2003 09:17:10 -0000	1.15
+++ netinet6/udp6_var.h	23 Oct 2004 17:29:48 -0000
@@ -87,12 +87,14 @@ struct	udp6stat {
  */
 #define UDP6CTL_SENDSPACE	1	/* default send buffer */
 #define UDP6CTL_RECVSPACE	2	/* default recv buffer */
-#define UDP6CTL_MAXID		3
+#define	UDP6CTL_LOOPBACKCKSUM	3	/* do UDP checksum on loopback? */
+#define UDP6CTL_MAXID		4
 
 #define UDP6CTL_NAMES { \
 	{ 0, 0 }, \
 	{ "sendspace", CTLTYPE_INT }, \
 	{ "recvspace", CTLTYPE_INT }, \
+	{ "do_loopback_cksum", CTLTYPE_INT }, \
 }
 
 #ifdef _KERNEL

--Apple-Mail-22--13025075--

--Apple-Mail-23--13025068
content-type: application/pgp-signature; x-mac-type=70674453;
	name=PGP.sig
content-description: This is a digitally signed message part
content-disposition: inline; filename=PGP.sig
content-transfer-encoding: 7bit

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.3 (Darwin)

iD8DBQFBeperOpVKkaBm8XkRAoXHAKCVrIS+Dqq/IDY+rT5LoDnQsm4OeQCghn+f
IceXbFDezswsfyC1KWitEng=
=InT3
-----END PGP SIGNATURE-----

--Apple-Mail-23--13025068--