Date: Thu, 02 Apr 2015 12:26:16 +0200 From: Sebastian Huber <sebastian.huber@embedded-brains.de> To: freebsd-hackers@freebsd.org Subject: A tcp_do_segment() question Message-ID: <551D1948.3090805@embedded-brains.de>
next in thread | raw e-mail | index | archive | help
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= .
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?551D1948.3090805>