From owner-freebsd-bugs Tue Dec 3 7: 0:20 2002 Delivered-To: freebsd-bugs@hub.freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 877A837B404 for ; Tue, 3 Dec 2002 07:00:10 -0800 (PST) Received: from freefall.freebsd.org (freefall.freebsd.org [216.136.204.21]) by mx1.FreeBSD.org (Postfix) with ESMTP id 83CAC43EAF for ; Tue, 3 Dec 2002 07:00:09 -0800 (PST) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) by freefall.freebsd.org (8.12.6/8.12.6) with ESMTP id gB3F09x3049430 for ; Tue, 3 Dec 2002 07:00:09 -0800 (PST) (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.12.6/8.12.6/Submit) id gB3F09Ze049429; Tue, 3 Dec 2002 07:00:09 -0800 (PST) Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 6459E37B401 for ; Tue, 3 Dec 2002 06:59:56 -0800 (PST) Received: from mailhub.fokus.gmd.de (mailhub.fokus.gmd.de [193.174.154.14]) by mx1.FreeBSD.org (Postfix) with ESMTP id 1241643E4A for ; Tue, 3 Dec 2002 06:59:55 -0800 (PST) (envelope-from brandt@fokus.gmd.de) Received: from beagle.fokus.gmd.de (beagle [193.175.132.100]) by mailhub.fokus.gmd.de (8.11.6/8.11.6) with ESMTP id gB3Exln23284 for ; Tue, 3 Dec 2002 15:59:47 +0100 (MET) Received: from beagle.fokus.gmd.de (localhost [127.0.0.1]) by beagle.fokus.gmd.de (8.12.6/8.12.6) with ESMTP id gB3ExkeU002104 for ; Tue, 3 Dec 2002 15:59:46 +0100 (CET) (envelope-from hbb@beagle.fokus.gmd.de) Received: (from root@localhost) by beagle.fokus.gmd.de (8.12.6/8.12.6/Submit) id gB3ExkS3002103; Tue, 3 Dec 2002 15:59:46 +0100 (CET) (envelope-from hbb) Message-Id: <200212031459.gB3ExkS3002103@beagle.fokus.gmd.de> Date: Tue, 3 Dec 2002 15:59:46 +0100 (CET) From: Hartmut Brandt Reply-To: Hartmut Brandt To: FreeBSD-gnats-submit@FreeBSD.org X-Send-Pr-Version: 3.113 Subject: kern/45966: TCPDEBUG kernel option broken by changes in TCP code Sender: owner-freebsd-bugs@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.org >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 #include *************** *** 68,77 **** --- 69,80 ---- #include #endif #include + #include #include #include #include #include + #include #ifdef INET6 #include #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