Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 3 Dec 2002 15:59:46 +0100 (CET)
From:      Hartmut Brandt <brandt@fokus.gmd.de>
To:        FreeBSD-gnats-submit@FreeBSD.org
Subject:   kern/45966: TCPDEBUG kernel option broken by changes in TCP code
Message-ID:  <200212031459.gB3ExkS3002103@beagle.fokus.gmd.de>

next in thread | raw e-mail | index | archive | help

>Number:         45966
>Category:       kern
>Synopsis:       TCPDEBUG kernel option broken by changes in TCP code
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Tue Dec 03 07:00:08 PST 2002
>Closed-Date:
>Last-Modified:
>Originator:     Hartmut Brandt
>Release:        FreeBSD 5.0-CURRENT i386
>Organization:
Fraunhofer Fokus
>Environment:
System: FreeBSD beagle.fokus.gmd.de 5.0-CURRENT FreeBSD 5.0-CURRENT #4: Thu Oct 17 15:52:15 CEST 2002 hbb@beagle.fokus.gmd.de:/opt/obj/usr/src/sys/BEAGLE i386


	
>Description:

The TCPDEBUG kernel option is used to enable the collection of information
about TCP in an in kernel array. This is used by several tools like
trpt and dbs. It is also an excellent tool to understand the inner working
of TCP.

Several changes to the TCP code have broken this option. While in the original
TCP code (described by Stevens) there was only one exit from the tcp_input
and tcp_output functions where debugging information needs to be collected,
now there are several return statements which effectively skip the collection
of debug information. Also the syncache prevents getting information about
connection establishment.

	
>How-To-Repeat:
	

	Compile a kernel with option TCPDEBUG.

	Install the DBS port (/usr/ports/benchmarks/dbs) and run a test.

	Observe, that several of the output files of DBS contain no data.

	Use trpt and observe, that you can't see packets with TH_SYN set.
>Fix:

	Insert calls to tcp_trace at the appropriate places with the
	attached patch.


Index: tcp_input.c
===================================================================
RCS file: /usr/ncvs/src/sys/netinet/tcp_input.c,v
retrieving revision 1.182
diff -c -r1.182 tcp_input.c
*** tcp_input.c	10 Nov 2002 17:17:32 -0000	1.182
--- tcp_input.c	3 Dec 2002 14:49:44 -0000
***************
*** 436,441 ****
--- 436,445 ----
  							ip->ip_len +
  							IPPROTO_TCP));
  			th->th_sum ^= 0xffff;
+ #ifdef TCPDEBUG
+ 			ipov->ih_len = (u_short)tlen;
+ 			ipov->ih_len = htons(ipov->ih_len);
+ #endif
  		} else {
  			/*
  			 * Checksum extended TCP header and data.
***************
*** 851,856 ****
--- 855,865 ----
  		 * for syncache, or perform t/tcp connection.
  		 */
  		if (so->so_qlen <= so->so_qlimit) {
+ #ifdef TCPDEBUG
+ 			if (so->so_options & SO_DEBUG)
+ 				tcp_trace(TA_INPUT, ostate, tp,
+ 				    (void *)tcp_saveipgen, &tcp_savetcp, 0);
+ #endif
  			tcp_dooptions(&to, optp, optlen, 1);
  			if (!syncache_add(&inc, &to, th, &so, m))
  				goto drop;
***************
*** 1052,1057 ****
--- 1061,1073 ----
  						      tcp_timer_rexmt, tp);
  
  				sowwakeup(so);
+ 
+ #ifdef TCPDEBUG
+ 				if (so->so_options & SO_DEBUG)
+ 					tcp_trace(TA_INPUT, ostate, tp,
+ 					    (void *)tcp_saveipgen,
+ 					    &tcp_savetcp, 0);
+ #endif
  				if (so->so_snd.sb_cc)
  					(void) tcp_output(tp);
  				INP_UNLOCK(inp);
***************
*** 1093,1098 ****
--- 1109,1119 ----
  				sbappend(&so->so_rcv, m);
  			}
  			sorwakeup(so);
+ #ifdef TCPDEBUG
+ 			if (so->so_options & SO_DEBUG)
+ 				tcp_trace(TA_INPUT, ostate, tp,
+ 				    (void *)tcp_saveipgen, &tcp_savetcp, 0);
+ #endif
  			if (DELAY_ACK(tp)) {
  	                        callout_reset(tp->tt_delack, tcp_delacktime,
  	                            tcp_timer_delack, tp);
Index: tcp_output.c
===================================================================
RCS file: /usr/ncvs/src/sys/netinet/tcp_output.c,v
retrieving revision 1.73
diff -c -r1.73 tcp_output.c
*** tcp_output.c	16 Oct 2002 19:16:33 -0000	1.73
--- tcp_output.c	3 Dec 2002 14:05:01 -0000
***************
*** 852,859 ****
  	/*
  	 * Trace.
  	 */
! 	if (so->so_options & SO_DEBUG)
  		tcp_trace(TA_OUTPUT, tp->t_state, tp, mtod(m, void *), th, 0);
  #endif
  
  	/*
--- 852,863 ----
  	/*
  	 * Trace.
  	 */
! 	if (so->so_options & SO_DEBUG) {
! 		u_short save = ipov->ih_len;
! 		ipov->ih_len = htons(m->m_pkthdr.len /* - hdrlen + (th->th_off << 2) */);
  		tcp_trace(TA_OUTPUT, tp->t_state, tp, mtod(m, void *), th, 0);
+ 		ipov->ih_len = save;
+ 	}
  #endif
  
  	/*
Index: tcp_syncache.c
===================================================================
RCS file: /usr/ncvs/src/sys/netinet/tcp_syncache.c,v
retrieving revision 1.28
diff -c -r1.28 tcp_syncache.c
*** tcp_syncache.c	9 Nov 2002 12:55:07 -0000	1.28
--- tcp_syncache.c	3 Dec 2002 14:12:30 -0000
***************
*** 37,42 ****
--- 37,43 ----
  #include "opt_inet6.h"
  #include "opt_ipsec.h"
  #include "opt_mac.h"
+ #include "opt_tcpdebug.h"
  
  #include <sys/param.h>
  #include <sys/systm.h>
***************
*** 68,77 ****
--- 69,80 ----
  #include <netinet6/in6_pcb.h>
  #endif
  #include <netinet/tcp.h>
+ #include <netinet/tcpip.h>
  #include <netinet/tcp_fsm.h>
  #include <netinet/tcp_seq.h>
  #include <netinet/tcp_timer.h>
  #include <netinet/tcp_var.h>
+ #include <netinet/tcp_debug.h>
  #ifdef INET6
  #include <netinet6/tcp6_var.h>
  #endif
***************
*** 104,110 ****
  static void	 syncache_free(struct syncache *);
  static void	 syncache_insert(struct syncache *, struct syncache_head *);
  struct syncache *syncache_lookup(struct in_conninfo *, struct syncache_head **);
! static int	 syncache_respond(struct syncache *, struct mbuf *);
  static struct 	 socket *syncache_socket(struct syncache *, struct socket *,
  		    struct mbuf *m);
  static void	 syncache_timer(void *);
--- 107,113 ----
  static void	 syncache_free(struct syncache *);
  static void	 syncache_insert(struct syncache *, struct syncache_head *);
  struct syncache *syncache_lookup(struct in_conninfo *, struct syncache_head **);
! static int	 syncache_respond(struct syncache *, struct mbuf *, struct socket *);
  static struct 	 socket *syncache_socket(struct syncache *, struct socket *,
  		    struct mbuf *m);
  static void	 syncache_timer(void *);
***************
*** 398,404 ****
  		 * to modify another entry, so do not obtain the next
  		 * entry on the timer chain until it has completed.
  		 */
! 		(void) syncache_respond(sc, NULL);
  		INP_UNLOCK(inp);
  		nsc = TAILQ_NEXT(sc, sc_timerq);
  		tcpstat.tcps_sc_retransmitted++;
--- 401,407 ----
  		 * to modify another entry, so do not obtain the next
  		 * entry on the timer chain until it has completed.
  		 */
! 		(void) syncache_respond(sc, NULL, NULL);
  		INP_UNLOCK(inp);
  		nsc = TAILQ_NEXT(sc, sc_timerq);
  		tcpstat.tcps_sc_retransmitted++;
***************
*** 872,878 ****
  		 */
  		sc->sc_tp = tp;
  		sc->sc_inp_gencnt = tp->t_inpcb->inp_gencnt;
! 		if (syncache_respond(sc, m) == 0) {
  		        s = splnet();
  			TAILQ_REMOVE(&tcp_syncache.timerq[sc->sc_rxtslot],
  			    sc, sc_timerq);
--- 875,881 ----
  		 */
  		sc->sc_tp = tp;
  		sc->sc_inp_gencnt = tp->t_inpcb->inp_gencnt;
! 		if (syncache_respond(sc, m, so) == 0) {
  		        s = splnet();
  			TAILQ_REMOVE(&tcp_syncache.timerq[sc->sc_rxtslot],
  			    sc, sc_timerq);
***************
*** 1029,1035 ****
  	 * TAO test failed or there was no CC option,
  	 *    do a standard 3-way handshake.
  	 */
! 	if (syncache_respond(sc, m) == 0) {
  		syncache_insert(sc, sch);
  		tcpstat.tcps_sndacks++;
  		tcpstat.tcps_sndtotal++;
--- 1032,1038 ----
  	 * TAO test failed or there was no CC option,
  	 *    do a standard 3-way handshake.
  	 */
! 	if (syncache_respond(sc, m, so) == 0) {
  		syncache_insert(sc, sch);
  		tcpstat.tcps_sndacks++;
  		tcpstat.tcps_sndtotal++;
***************
*** 1042,1050 ****
  }
  
  static int
! syncache_respond(sc, m)
  	struct syncache *sc;
  	struct mbuf *m;
  {
  	u_int8_t *optp;
  	int optlen, error;
--- 1045,1054 ----
  }
  
  static int
! syncache_respond(sc, m, so)
  	struct syncache *sc;
  	struct mbuf *m;
+ 	struct socket *so;
  {
  	u_int8_t *optp;
  	int optlen, error;
***************
*** 1222,1227 ****
--- 1226,1241 ----
  		    htons(tlen - hlen + IPPROTO_TCP));
  		m->m_pkthdr.csum_flags = CSUM_TCP;
  		m->m_pkthdr.csum_data = offsetof(struct tcphdr, th_sum);
+ #ifdef TCPDEBUG
+ 		/*
+ 		 * Trace.
+ 		 */
+ 		if (so != NULL && so->so_options & SO_DEBUG) {
+ 			struct tcpcb *tp = sototcpcb(so);
+ 			tcp_trace(TA_OUTPUT, tp->t_state, tp,
+ 			    mtod(m, void *), th, 0);
+ 		}
+ #endif
  		error = ip_output(m, sc->sc_ipopts, &sc->sc_route, 0, NULL,
  				sc->sc_tp->t_inpcb);
  	}
>Release-Note:
>Audit-Trail:
>Unformatted:

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200212031459.gB3ExkS3002103>