1*5075Swnj /* tcp_output.c 4.18 81/11/25 */ 24677Swnj 34677Swnj #include "../h/param.h" 44677Swnj #include "../h/systm.h" 54677Swnj #include "../h/mbuf.h" 64677Swnj #include "../h/socket.h" 74804Swnj #include "../h/socketvar.h" 84804Swnj #include "../net/inet.h" 94885Swnj #include "../net/inet_pcb.h" 104804Swnj #include "../net/inet_systm.h" 114804Swnj #include "../net/imp.h" 124804Swnj #include "../net/ip.h" 134900Swnj #include "../net/ip_var.h" 144804Swnj #include "../net/tcp.h" 154804Swnj #include "../net/tcp_var.h" 164804Swnj #include "../net/tcp_fsm.h" 174804Swnj #include "/usr/include/errno.h" 184677Swnj 194678Swnj /* 20*5075Swnj * Tcp output routine: figure out what should be sent 21*5075Swnj * and, if nothing, send a null segment anyways if force is nonzero 22*5075Swnj * (e.g. to be sure to send an ACK). 23*5075Swnj * 24*5075Swnj * This routine can be called only after SYNs have been exchanged. 254678Swnj */ 26*5075Swnj tcp_output(tp) 27*5075Swnj register struct tcpcb *tp; 284678Swnj { 29*5075Swnj register struct socket *so = tp->t_inpcb->inp_socket; 30*5075Swnj register int len; 31*5075Swnj struct mbuf *m0; 32*5075Swnj int off, flags; 33*5075Swnj register struct mbuf *m; 34*5075Swnj register struct tcpiphdr *ti; 35*5075Swnj int win; 364678Swnj 37*5075Swnj COUNT(TCP_OUTPUT); 384678Swnj 39*5075Swnj /* 40*5075Swnj * Determine length of data that can be transmitted. 41*5075Swnj * If will transmit to end of data and no more data 42*5075Swnj * is coming, then send FIN also. 43*5075Swnj * Make a copy of the data (if any). If no data 44*5075Swnj * and not forced to transmit, just return. 45*5075Swnj */ 46*5075Swnj off = tp->snd_nxt - tp->snd_una; 47*5075Swnj len = MIN(so->so_snd.sb_cc, tp->snd_wnd) - off; 48*5075Swnj if (len > tp->mtu) 49*5075Swnj len = tp->mtu; 50*5075Swnj if (len == so->so_snd.sb_cc && (so->so_state & SS_CANTSNDMORE)) 51*5075Swnj flags = TH_FIN; 52*5075Swnj else 53*5075Swnj flags = 0; 54*5075Swnj if (len) 55*5075Swnj goto send; 564678Swnj 57*5075Swnj /* 58*5075Swnj * No data to send: see if something else makes us want to send. 59*5075Swnj * First check if we owe peer and ack or have a unacked FIN to send. 60*5075Swnj */ 61*5075Swnj if (tp->t_flags & TF_OWEACK) 62*5075Swnj goto send; 63*5075Swnj if ((so->so_state & SS_CANTSNDMORE) && 64*5075Swnj TCPS_OURFINISACKED(tp->t_state) == 0) 65*5075Swnj goto send; 66*5075Swnj if (tp->t_state == TCPS_SYN_SENT) { 67*5075Swnj flags = TH_SYN; 68*5075Swnj goto send; 694678Swnj } 70*5075Swnj if (tp->t_state == TCPS_CLOSED) { 71*5075Swnj flags = TH_RST; 72*5075Swnj goto send; 73*5075Swnj } 744678Swnj 75*5075Swnj /* 76*5075Swnj * Calculate available window in i, and also amount 77*5075Swnj * of window known to peer (as advertised window less 78*5075Swnj * next expected input.) If this is 35% or more of the 79*5075Swnj * maximum possible window, then want to send a segment to peer. 80*5075Swnj */ 81*5075Swnj i = sbspace(&so->so_rcv) - tp->seqcnt; 82*5075Swnj if (i > 0 && 83*5075Swnj ((100*(i-(tp->rcv_adv-tp->rcv_nxt))/so->so_rcv.sb_hiwat) >= 35)) 84*5075Swnj goto send; 854678Swnj 86*5075Swnj /* 87*5075Swnj * No reason to send a segment, just return. 88*5075Swnj */ 89*5075Swnj return; 904678Swnj 91*5075Swnj send: 92*5075Swnj /* 93*5075Swnj * Grab a header mbuf, attaching a copy of data to 94*5075Swnj * be transmitted, and initialize the header from 95*5075Swnj * the template for sends on this connection. 96*5075Swnj */ 974677Swnj MGET(m, 0); 984677Swnj if (m == 0) 994677Swnj return (0); 1004885Swnj m->m_off = MMAXOFF - sizeof(struct tcpiphdr); 1014885Swnj m->m_len = sizeof (struct tcpiphdr); 102*5075Swnj if (len) { 103*5075Swnj m->m_next = m_copy(so->so_snd.sb_mb, off, len); 104*5075Swnj if (m->m_next == 0) 105*5075Swnj len = 0; 106*5075Swnj } 107*5075Swnj ti = mtod(m, struct tcpiphdr *); 108*5075Swnj if (tp->t_template == 0) 109*5075Swnj panic("tcp_output"); 110*5075Swnj bcopy((caddr_t)tp->t_template, ti, sizeof (struct tcpiphdr)); 111*5075Swnj 112*5075Swnj /* 113*5075Swnj * Fill in fields, remembering maximum advertised 114*5075Swnj * window for use in delaying messages about window sizes. 115*5075Swnj */ 116*5075Swnj ti->ti_seq = htonl(tp->snd_nxt); 117*5075Swnj ti->ti_ackno = htonl(tp->rcv_nxt); 118*5075Swnj /* OPTIONS */ 1194677Swnj if (flags & TH_SYN) 120*5075Swnj ti->ti_flags = flags; 121*5075Swnj else 122*5075Swnj ti->ti_flags = flags | TH_ACK; 123*5075Swnj win = sbspace(&so->so_rcv); 124*5075Swnj if (win > 0) 125*5075Swnj ti->ti_win = htons(win); 126*5075Swnj if (SEQ_GT(tp->snd_urp, tp->snd_nxt)) 127*5075Swnj ti->ti_urp = htons((u_short)(tp->snd_urp - tp->snd_nxt)); 128*5075Swnj ti->ti_flags |= TH_URG; 129*5075Swnj } else 130*5075Swnj /* 131*5075Swnj * If no urgent pointer to send, then we pull 132*5075Swnj * the urgent pointer to the left edge of the send window 133*5075Swnj * so that it doesn't drift into the send window on sequence 134*5075Swnj * number wraparound. 135*5075Swnj */ 136*5075Swnj tp->snd_urp = tp->snd_una; /* drag it along */ 137*5075Swnj 138*5075Swnj /* 139*5075Swnj * Put TCP length in extended header, and then 140*5075Swnj * checksum extended header and data. 141*5075Swnj */ 142*5075Swnj if (len) 143*5075Swnj ti->ti_len = htons((u_short)(len + sizeof (struct tcphdr))); 144*5075Swnj ti->ti_sum = inet_cksum(m, sizeof (struct tcpiphdr) + len); 145*5075Swnj 146*5075Swnj /* 147*5075Swnj * Fill in IP length and desired time to live and 148*5075Swnj * send to IP level. 149*5075Swnj */ 150*5075Swnj ((struct ip *)ti)->ip_len = len + sizeof (struct tcpiphdr); 151*5075Swnj ((struct ip *)ti)->ip_ttl = TCP_TTL; 152*5075Swnj if (ip_output(m) == 0) 153*5075Swnj return; 154*5075Swnj 155*5075Swnj /* 156*5075Swnj * Data sent (as far as we can tell). 157*5075Swnj * If this advertises a larger window than any other segment, 158*5075Swnj * then record its sequence to be used in suppressing messages. 159*5075Swnj * Advance snd_nxt to reflect transmitted sequence space, 160*5075Swnj * drop send for purpose of ACK requirements, 161*5075Swnj * and time transmission if not a retransmit. 162*5075Swnj */ 163*5075Swnj if (win > 0 && SEQ_GT(tp->rcv_nxt+win, tp->rcv_adv)) 164*5075Swnj tp->rcv_adv = tp->rcv_nxt + win; 165*5075Swnj tp->snd_nxt += len; 166*5075Swnj tp->t_flags &= ~(TF_OWEACK|TF_DELACK); 1674677Swnj if (flags & TH_FIN) 168*5075Swnj tp->snd_nxt++; 169*5075Swnj if (SEQ_GT(tp->snd_nxt, tp->snd_hi)) { 170*5075Swnj tp->snd_hi = tp->snd_nxt; 171*5075Swnj /* TIME TRANSMIT */ 1724677Swnj } 173*5075Swnj return; 1744677Swnj } 175