From owner-freebsd-hackers@FreeBSD.ORG Thu Apr 2 10:26:28 2015 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id C476C18B for ; Thu, 2 Apr 2015 10:26:28 +0000 (UTC) Received: from mail.embedded-brains.de (host-82-135-62-35.customer.m-online.net [82.135.62.35]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 4EDFABB6 for ; Thu, 2 Apr 2015 10:26:27 +0000 (UTC) Received: from localhost (localhost.localhost [127.0.0.1]) by mail.embedded-brains.de (Postfix) with ESMTP id B62F92A1930 for ; Thu, 2 Apr 2015 12:26:52 +0200 (CEST) Received: from mail.embedded-brains.de ([127.0.0.1]) by localhost (zimbra.eb.localhost [127.0.0.1]) (amavisd-new, port 10032) with ESMTP id 2Z3SH0EG9c8C for ; Thu, 2 Apr 2015 12:26:52 +0200 (CEST) Received: from localhost (localhost.localhost [127.0.0.1]) by mail.embedded-brains.de (Postfix) with ESMTP id 19F3A2A194E for ; Thu, 2 Apr 2015 12:26:52 +0200 (CEST) X-Virus-Scanned: amavisd-new at zimbra.eb.localhost Received: from mail.embedded-brains.de ([127.0.0.1]) by localhost (zimbra.eb.localhost [127.0.0.1]) (amavisd-new, port 10026) with ESMTP id s4heCwig_PKW for ; Thu, 2 Apr 2015 12:26:52 +0200 (CEST) Received: from [192.168.96.129] (unknown [192.168.96.129]) by mail.embedded-brains.de (Postfix) with ESMTPSA id F1E132A1930 for ; Thu, 2 Apr 2015 12:26:51 +0200 (CEST) Message-ID: <551D1948.3090805@embedded-brains.de> Date: Thu, 02 Apr 2015 12:26:16 +0200 From: Sebastian Huber User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.5.0 MIME-Version: 1.0 To: freebsd-hackers@freebsd.org Subject: A tcp_do_segment() question Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: quoted-printable X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 02 Apr 2015 10:26:28 -0000 Hello, I do currently some tests with a port of the FreeBSD 9.3 network stack=20 to the RTEMS real-time operating system. I do an FTP transfer from my=20 development machine to the target (curl -T /dev/zero=20 ftp://anonymous@192.168.96.157/dev/null). So this is a one-sided TCP=20 transfer. In tcp_do_segment() there is one path as explained here: /* * Header prediction: check for the two common cases * of a uni-directional data xfer. If the packet has * no control flags, is in-sequence, the window didn't * change and we're not retransmitting, it's a * candidate. If the length is zero and the ack moved * forward, we're the sender side of the xfer. Just * free the data acked & wake any higher level process * that was blocked waiting for space. If the length * is non-zero and the ack didn't move, we're the * receiver side. If we're getting packets in-order * (the reassembly queue is empty), add the data to * the socket buffer and note that we need a delayed ack. * Make sure that the hidden state-flags are also off. * Since we check for TCPS_ESTABLISHED first, it can only * be TH_NEEDSYN. */ if (tp->t_state =3D=3D TCPS_ESTABLISHED && th->th_seq =3D=3D tp->rcv_nxt && (thflags & (TH_SYN|TH_FIN|TH_RST|TH_URG|TH_ACK)) =3D=3D TH_ACK &= & tp->snd_nxt =3D=3D tp->snd_max && tiwin && tiwin =3D=3D tp->snd_wnd && ((tp->t_flags & (TF_NEEDSYN|TF_NEEDFIN)) =3D=3D 0) && LIST_EMPTY(&tp->t_segq) && ((to.to_flags & TOF_TS) =3D=3D 0 || TSTMP_GEQ(to.to_tsval, tp->ts_recent)) ) { It seems that after some initial setup phase I end up always in this=20 branch. The problem is now that the retransmit timer is ticking (TT_REXMT= ). In this branch there are three alternatives: 1. if (tlen =3D=3D 0) { Since I transfer to the target, tlen !=3D 0. 2. } else if (th->th_ack =3D=3D tp->snd_una && tlen <=3D sbspace(&so->so_rcv)) { It seems I always end up here. 3. Otherwise. In the (1) alternative we end up in: if (tp->snd_una =3D=3D tp->snd_max) tcp_timer_activate(tp, TT_REXMT, 0); else if (!tcp_timer_active(tp, TT_PERSIST)) tcp_timer_activate(tp, TT_REXMT, tp->t_rxtcur); sowwakeup(so); if (so->so_snd.sb_cc) (void) tcp_output(tp); goto check_delack; So here we reset the retransmit timer if possible. In the (2) alternative we don't reset the retransmit timer! All my=20 connections stop after approx. 2:30min via tcp_timer_rexmt(). If I apply=20 the following hack @@ -1852,6 +1866,13 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th,=20 struct socket *so, } /* NB: sorwakeup_locked() does an implicit=20 unlock. */ sorwakeup_locked(so); + + if (tp->snd_una =3D=3D tp->snd_max) + tcp_timer_activate(tp, TT_REXMT, 0); + else if (!tcp_timer_active(tp, TT_PERSIST)) + tcp_timer_activate(tp, TT_REXMT, + tp->t_rxtcur); + if (DELAY_ACK(tp)) { tp->t_flags |=3D TF_DELACK; } else { in the (2) alternative, then I can transfer for hours. Does anyone know why the retransmit timer is not reset in the (2)=20 alternative? --=20 Sebastian Huber, embedded brains GmbH Address : Dornierstr. 4, D-82178 Puchheim, Germany Phone : +49 89 189 47 41-16 Fax : +49 89 189 47 41-09 E-Mail : sebastian.huber@embedded-brains.de PGP : Public key available on request. Diese Nachricht ist keine gesch=C3=A4ftliche Mitteilung im Sinne des EHUG= .