- if ((t = tp->t_template) == 0)
- return (0);
- MGET(m, 0);
- if (m == 0)
- return (0);
- m->m_off = MMAXOFF - sizeof(struct tcpiphdr);
- m->m_len = sizeof (struct tcpiphdr);
- m->m_next = dat;
- if (flags & TH_SYN)
- len--;
- if (flags & TH_FIN)
- len--;
- if (len < 0)
- panic("tcp_output");
- bcopy((caddr_t)t, mtod(m, caddr_t), sizeof (struct tcpiphdr));
- t = mtod(m, struct tcpiphdr *);
- if (tp->tc_flags&TC_SND_RST) {
- flags &= ~TH_SYN;
- flags |= TH_RST;
- }
- if (tp->tc_flags&TC_SYN_RCVD)
- flags |= TH_ACK;
- t->ti_flags = flags;
- if (flags & TH_URG)
- t->ti_urp = htons((u_short)tp->snd_urp); /*XXX */
- t->ti_win =
- so->so_rcv.sb_hiwat -
- (so->so_rcv.sb_cc + tp->seqcnt);
- if (tp->rcv_nxt + t->ti_win > tp->rcv_adv)
- tp->rcv_adv = tp->rcv_nxt + t->ti_win;
- if (len)
- t->ti_len = htons((u_short)(len + TCPSIZE));
- t->ti_win = htons(t->ti_win);
-#ifdef TCPDEBUG
- if ((so->so_options & SO_DEBUG) || tcpconsdebug) {
- t->ti_seq = tp->snd_nxt;
- t->ti_ackno = tp->rcv_nxt;
- tdb_setup(tp, t, INSEND, &tdb);
- tdb_stuff(&tdb, -2);
- }
+ /*
+ * Set retransmit timer if not currently set,
+ * and not doing an ack or a keep-alive probe.
+ * Initial value for retransmit timer is smoothed
+ * round-trip time + 2 * round-trip time variance.
+ * Initialize shift counter which is used for backoff
+ * of retransmit time.
+ */
+ if (tp->t_timer[TCPT_REXMT] == 0 &&
+ tp->snd_nxt != tp->snd_una) {
+ tp->t_timer[TCPT_REXMT] = tp->t_rxtcur;
+ if (tp->t_timer[TCPT_PERSIST]) {
+ tp->t_timer[TCPT_PERSIST] = 0;
+ tp->t_rxtshift = 0;
+ }
+ }
+ } else
+ if (SEQ_GT(tp->snd_nxt + len, tp->snd_max))
+ tp->snd_max = tp->snd_nxt + len;
+
+ /*
+ * Trace.
+ */
+ if (so->so_options & SO_DEBUG)
+ tcp_trace(TA_OUTPUT, tp->t_state, tp, ti, 0);
+
+ /*
+ * Fill in IP length and desired time to live and
+ * send to IP level.
+ */
+ ((struct ip *)ti)->ip_len = sizeof (struct tcpiphdr) + optlen + len;
+ ((struct ip *)ti)->ip_ttl = TCP_TTL;
+#if BSD>=43
+ error = ip_output(m, tp->t_inpcb->inp_options, &tp->t_inpcb->inp_route,
+ so->so_options & SO_DONTROUTE);
+#else
+ error = ip_output(m, (struct mbuf *)0, &tp->t_inpcb->inp_route,
+ so->so_options & SO_DONTROUTE);