4 Copyright 1995 Philip Homburg
22 FORWARD acc_t
*make_pack
ARGS(( tcp_conn_t
*tcp_conn
));
23 FORWARD
void tcp_send_timeout
ARGS(( int conn
, struct timer
*timer
));
24 FORWARD
void do_snd_event
ARGS(( event_t
*ev
, ev_arg_t arg
));
26 PUBLIC
void tcp_conn_write (tcp_conn
, enq
)
28 int enq
; /* Writes need to be enqueued. */
33 assert (tcp_conn
->tc_flags
& TCF_INUSE
);
35 tcp_port
= tcp_conn
->tc_port
;
36 if (tcp_conn
->tc_flags
& TCF_MORE2WRITE
)
39 /* Do we really have something to send here? */
40 if (tcp_conn
->tc_SND_UNA
== tcp_conn
->tc_SND_NXT
&&
41 !(tcp_conn
->tc_flags
& TCF_SEND_ACK
) &&
42 !tcp_conn
->tc_frag2send
)
47 tcp_conn
->tc_flags
|= TCF_MORE2WRITE
;
48 tcp_conn
->tc_send_link
= NULL
;
49 if (!tcp_port
->tp_snd_head
)
51 tcp_port
->tp_snd_head
= tcp_conn
;
52 tcp_port
->tp_snd_tail
= tcp_conn
;
55 snd_arg
.ev_ptr
= tcp_port
;
56 if (!ev_in_queue(&tcp_port
->tp_snd_event
))
58 ev_enqueue(&tcp_port
->tp_snd_event
,
59 do_snd_event
, snd_arg
);
63 tcp_port_write(tcp_port
);
67 tcp_port
->tp_snd_tail
->tc_send_link
= tcp_conn
;
68 tcp_port
->tp_snd_tail
= tcp_conn
;
72 PRIVATE
void do_snd_event(ev
, arg
)
80 assert(ev
== &tcp_port
->tp_snd_event
);
81 tcp_port_write(tcp_port
);
84 PUBLIC
void tcp_port_write(tcp_port
)
91 assert (!(tcp_port
->tp_flags
& TPF_WRITE_IP
));
93 while(tcp_port
->tp_snd_head
)
95 tcp_conn
= tcp_port
->tp_snd_head
;
96 assert(tcp_conn
->tc_flags
& TCF_MORE2WRITE
);
100 if (tcp_conn
->tc_frag2send
)
102 pack2write
= tcp_conn
->tc_frag2send
;
103 tcp_conn
->tc_frag2send
= 0;
108 pack2write
= make_pack(tcp_conn
);
113 r
= ip_send(tcp_port
->tp_ipfd
, pack2write
,
114 bf_bufsize(pack2write
));
117 if (r
== NW_WOULDBLOCK
)
121 tcp_mtu_exceeded(tcp_conn
);
126 tcp_notreach(tcp_conn
);
133 (printf("ip_send failed, error %d\n", r
),0));
138 tcp_port
->tp_flags
|= TPF_WRITE_IP
;
139 tcp_port
->tp_pack
= pack2write
;
141 r
= ip_write (tcp_port
->tp_ipfd
,
142 bf_bufsize(pack2write
));
145 tcp_port
->tp_flags
|= TPF_WRITE_SP
;
149 tcp_port
->tp_flags
&= ~TPF_WRITE_IP
;
150 assert(!(tcp_port
->tp_flags
&
151 (TPF_WRITE_IP
|TPF_WRITE_SP
)));
154 tcp_conn
->tc_flags
&= ~TCF_MORE2WRITE
;
155 tcp_port
->tp_snd_head
= tcp_conn
->tc_send_link
;
160 PRIVATE acc_t
*make_pack(tcp_conn
)
161 tcp_conn_t
*tcp_conn
;
163 acc_t
*pack2write
, *tmp_pack
, *tcp_pack
;
166 int tot_hdr_size
, ip_hdr_len
, no_push
, head
, more2write
;
167 u32_t seg_seq
, seg_lo_data
, queue_lo_data
, seg_hi
, seg_hi_data
;
171 clock_t curr_time
, new_dis
;
174 mss
= tcp_conn
->tc_mtu
-IP_TCP_MIN_HDR_SIZE
;
176 assert(tcp_conn
->tc_busy
);
177 curr_time
= get_time();
178 switch (tcp_conn
->tc_state
)
183 case TCS_SYN_RECEIVED
:
186 if (tcp_conn
->tc_SND_TRM
== tcp_conn
->tc_SND_NXT
&&
187 !(tcp_conn
->tc_flags
& TCF_SEND_ACK
))
192 tcp_conn
->tc_flags
&= ~TCF_SEND_ACK
;
194 /* Advertise a mss based on the port mtu. The current mtu may
195 * be lower if the other side sends a smaller mss.
197 mss
= tcp_conn
->tc_port
->tp_mtu
-IP_TCP_MIN_HDR_SIZE
;
199 /* Include a max segment size option. */
200 assert(tcp_conn
->tc_tcpopt
== NULL
);
201 tcp_conn
->tc_tcpopt
= bf_memreq(4);
202 optptr
= (u8_t
*)ptr2acc_data(tcp_conn
->tc_tcpopt
);
203 optptr
[0]= TCP_OPT_MSS
;
206 optptr
[3]= mss
& 0xFF;
208 pack2write
= tcp_make_header(tcp_conn
, &ip_hdr
, &tcp_hdr
,
211 bf_afree(tcp_conn
->tc_tcpopt
);
212 tcp_conn
->tc_tcpopt
= NULL
;
216 DBLOCK(1, printf("connection closed while inuse\n"));
219 tot_hdr_size
= bf_bufsize(pack2write
);
220 seg_seq
= tcp_conn
->tc_SND_TRM
;
221 if (tcp_conn
->tc_state
== TCS_SYN_SENT
)
224 seg_flags
= THF_ACK
; /* except for TCS_SYN_SENT
225 * ack is always present */
227 if (seg_seq
== tcp_conn
->tc_ISS
)
229 assert(tcp_conn
->tc_transmit_timer
.tim_active
||
230 (tcp_print_conn(tcp_conn
), printf("\n"), 0));
231 seg_flags
|= THF_SYN
;
232 tcp_conn
->tc_SND_TRM
++;
235 tcp_hdr
->th_seq_nr
= htonl(seg_seq
);
236 tcp_hdr
->th_ack_nr
= htonl(tcp_conn
->tc_RCV_NXT
);
237 tcp_hdr
->th_flags
= seg_flags
;
238 tcp_hdr
->th_window
= htons(mss
);
239 /* Initially we allow one segment */
241 ip_hdr
->ih_length
= htons(tot_hdr_size
);
243 pack2write
->acc_linkC
++;
244 ip_hdr_len
= (ip_hdr
->ih_vers_ihl
& IH_IHL_MASK
) << 2;
245 tcp_pack
= bf_delhead(pack2write
, ip_hdr_len
);
246 tcp_hdr
->th_chksum
= ~tcp_pack_oneCsum(ip_hdr
, tcp_pack
);
249 new_dis
= curr_time
+ 2*HZ
*tcp_conn
->tc_ttl
;
250 if (new_dis
> tcp_conn
->tc_senddis
)
251 tcp_conn
->tc_senddis
= new_dis
;
254 case TCS_ESTABLISHED
:
256 seg_seq
= tcp_conn
->tc_SND_TRM
;
261 if (tcp_conn
->tc_flags
& TCF_SEND_ACK
)
264 tcp_conn
->tc_flags
&= ~TCF_SEND_ACK
;
266 pack2write
= tcp_make_header (tcp_conn
, &ip_hdr
,
267 &tcp_hdr
, (acc_t
*)0);
274 if (tcp_conn
->tc_SND_UNA
!= tcp_conn
->tc_SND_NXT
)
276 assert(tcp_LEmod4G(seg_seq
, tcp_conn
->tc_SND_NXT
));
278 if (seg_seq
== tcp_conn
->tc_snd_cwnd
)
281 printf("no data: window is closed\n"));
285 /* Assert that our SYN has been ACKed. */
286 assert(tcp_conn
->tc_SND_UNA
!= tcp_conn
->tc_ISS
);
288 seg_lo_data
= seg_seq
;
289 queue_lo_data
= tcp_conn
->tc_SND_UNA
;
291 seg_hi
= tcp_conn
->tc_SND_NXT
;
293 if (tcp_conn
->tc_flags
& TCF_FIN_SENT
)
295 if (seg_seq
!= seg_hi
)
296 seg_flags
|= THF_FIN
;
297 if (queue_lo_data
== seg_hi_data
)
299 if (seg_lo_data
== seg_hi_data
)
306 pack2write
= tcp_make_header (tcp_conn
,
307 &ip_hdr
, &tcp_hdr
, (acc_t
*)0);
314 tot_hdr_size
= bf_bufsize(pack2write
);
316 no_push
= (tcp_LEmod4G(tcp_conn
->tc_SND_PSH
, seg_seq
));
317 head
= (seg_seq
== tcp_conn
->tc_SND_UNA
);
320 /* Shutdown sets SND_PSH */
321 seg_flags
&= ~THF_FIN
;
322 if (seg_hi_data
-seg_lo_data
<= 1)
324 /* Allways keep at least one byte
328 printf("no data: no push\n"));
332 "no data: setting TCF_NO_PUSH\n"));
333 tcp_conn
->tc_flags
|=
341 if (tot_hdr_size
!= IP_TCP_MIN_HDR_SIZE
)
344 "tcp_write`make_pack: tot_hdr_size = %d\n",
346 mss
= tcp_conn
->tc_mtu
-tot_hdr_size
;
348 if (seg_hi_data
- seg_lo_data
> mss
)
350 /* Truncate to at most one segment */
351 seg_hi_data
= seg_lo_data
+ mss
;
353 seg_flags
&= ~THF_FIN
;
357 seg_hi_data
-seg_lo_data
!= mss
)
360 "no data: no push for partial segment\n"));
361 more2write
= (tcp_conn
->tc_fd
&&
362 (tcp_conn
->tc_fd
->tf_flags
&
364 DIFBLOCK(2, more2write
,
366 "tcp_send`make_pack: more2write -> !TCF_NO_PUSH\n");
368 if (head
&& !more2write
)
371 "partial segment: setting TCF_NO_PUSH\n"));
372 tcp_conn
->tc_flags
|= TCF_NO_PUSH
;
378 if (tcp_Gmod4G(seg_hi
, tcp_conn
->tc_snd_cwnd
))
380 seg_hi_data
= tcp_conn
->tc_snd_cwnd
;
382 seg_flags
&= ~THF_FIN
;
386 seg_hi_data
-seg_lo_data
< mss
)
388 if (tcp_conn
->tc_flags
& TCF_PUSH_NOW
)
391 printf("push: no Nagle\n"));
396 printf("no data: partial packet\n"));
397 seg_flags
&= ~THF_FIN
;
402 if (seg_hi
-seg_seq
== 0)
405 printf("no data: no data available\n"));
409 if (tcp_GEmod4G(tcp_conn
->tc_SND_UP
, seg_lo_data
))
411 extern int killer_inet
;
413 if (tcp_GEmod4G(tcp_conn
->tc_SND_UP
,
416 seg_up
= seg_hi_data
-seg_seq
;
420 seg_up
= tcp_conn
->tc_SND_UP
-seg_seq
;
422 seg_flags
|= THF_URG
;
424 (tcp_conn
->tc_flags
& TCF_BSD_URG
) &&
427 /* A zero urgent pointer doesn't mean
428 * anything when BSD semantics are
429 * used (urgent pointer points to the
430 * first no urgent byte). The use of
431 * a zero urgent pointer also crashes
432 * a Solaris 2.3 kernel. If urgent
433 * pointer doesn't have BSD semantics
434 * then an urgent pointer of zero
435 * simply indicates that there is one
438 seg_flags
&= ~THF_URG
;
444 if (tcp_Gmod4G(tcp_conn
->tc_SND_PSH
, seg_lo_data
) &&
445 tcp_LEmod4G(tcp_conn
->tc_SND_PSH
, seg_hi_data
))
447 seg_flags
|= THF_PSH
;
450 tcp_conn
->tc_SND_TRM
= seg_hi
;
452 assert(tcp_conn
->tc_transmit_timer
.tim_active
||
453 (tcp_print_conn(tcp_conn
), printf("\n"), 0));
454 if (tcp_conn
->tc_rt_seq
== 0 &&
455 tcp_Gmod4G(seg_seq
, tcp_conn
->tc_rt_threshold
))
457 tcp_conn
->tc_rt_time
= curr_time
;
459 tcp_conn
->tc_rt_threshold
= seg_seq
;
462 if (seg_hi_data
-seg_lo_data
)
465 assert(tcp_check_conn(tcp_conn
));
466 assert((seg_hi_data
-queue_lo_data
<=
467 bf_bufsize(tcp_conn
->tc_send_data
) &&
468 seg_lo_data
-queue_lo_data
<=
469 bf_bufsize(tcp_conn
->tc_send_data
) &&
470 seg_hi_data
>seg_lo_data
)||
471 (tcp_print_conn(tcp_conn
),
473 " seg_hi_data= 0x%x, seg_lo_data= 0x%x, queue_lo_data= 0x%x\n",
474 seg_hi_data
, seg_lo_data
,
478 tmp_pack
= pack2write
;
479 while (tmp_pack
->acc_next
)
480 tmp_pack
= tmp_pack
->acc_next
;
482 bf_cut(tcp_conn
->tc_send_data
,
483 (unsigned)(seg_lo_data
-queue_lo_data
),
484 (unsigned) (seg_hi_data
-seg_lo_data
));
486 seg_flags
|= THF_ACK
;
490 if (!(seg_flags
& THF_ACK
))
493 bf_afree(pack2write
);
497 tcp_hdr
->th_seq_nr
= htonl(seg_seq
);
498 tcp_hdr
->th_ack_nr
= htonl(tcp_conn
->tc_RCV_NXT
);
499 tcp_hdr
->th_flags
= seg_flags
;
500 tcp_hdr
->th_window
= htons(tcp_conn
->tc_RCV_HI
-
501 tcp_conn
->tc_RCV_NXT
);
502 tcp_hdr
->th_urgptr
= htons(seg_up
);
504 pack_size
= bf_bufsize(pack2write
);
505 ip_hdr
->ih_length
= htons(pack_size
);
507 pack2write
->acc_linkC
++;
508 ip_hdr_len
= (ip_hdr
->ih_vers_ihl
& IH_IHL_MASK
) << 2;
509 tcp_pack
= bf_delhead(pack2write
, ip_hdr_len
);
510 tcp_hdr
->th_chksum
= ~tcp_pack_oneCsum(ip_hdr
, tcp_pack
);
513 new_dis
= curr_time
+ 2*HZ
*tcp_conn
->tc_ttl
;
514 if (new_dis
> tcp_conn
->tc_senddis
)
515 tcp_conn
->tc_senddis
= new_dis
;
519 DBLOCK(1, tcp_print_conn(tcp_conn
); printf("\n"));
520 ip_panic(( "Illegal state" ));
530 PUBLIC
void tcp_release_retrans(tcp_conn
, seg_ack
, new_win
)
531 tcp_conn_t
*tcp_conn
;
538 clock_t retrans_time
, curr_time
, rtt
, artt
, drtt
, srtt
;
539 u32_t queue_lo
, queue_hi
;
543 DBLOCK(0x10, printf("tcp_release_retrans, conn[%d]: ack %lu, win %u\n",
544 tcp_conn
-tcp_conn_table
, (unsigned long)seg_ack
, new_win
););
546 assert(tcp_conn
->tc_busy
);
547 assert (tcp_GEmod4G(seg_ack
, tcp_conn
->tc_SND_UNA
));
548 assert (tcp_LEmod4G(seg_ack
, tcp_conn
->tc_SND_NXT
));
550 tcp_conn
->tc_snd_dack
= 0;
551 mss
= tcp_conn
->tc_mtu
-IP_TCP_MIN_HDR_SIZE
;
553 curr_time
= get_time();
554 if (tcp_conn
->tc_rt_seq
!= 0 &&
555 tcp_Gmod4G(seg_ack
, tcp_conn
->tc_rt_seq
))
557 assert(curr_time
>= tcp_conn
->tc_rt_time
);
558 retrans_time
= curr_time
-tcp_conn
->tc_rt_time
;
559 rtt
= tcp_conn
->tc_rtt
;
561 tcp_conn
->tc_rt_seq
= 0;
563 if (rtt
== TCP_RTT_GRAN
*CLOCK_GRAN
&&
564 retrans_time
<= TCP_RTT_GRAN
*CLOCK_GRAN
)
566 /* Common in fast networks. Nothing to do. */
570 srtt
= retrans_time
* TCP_RTT_SCALE
;
572 artt
= tcp_conn
->tc_artt
;
573 artt
= ((TCP_RTT_SMOOTH
-1)*artt
+srtt
)/TCP_RTT_SMOOTH
;
578 drtt
= tcp_conn
->tc_drtt
;
579 drtt
= ((TCP_RTT_SMOOTH
-1)*drtt
+srtt
)/TCP_RTT_SMOOTH
;
581 rtt
= (artt
+TCP_DRTT_MULT
*drtt
-1)/TCP_RTT_SCALE
+1;
582 if (rtt
< TCP_RTT_GRAN
*CLOCK_GRAN
)
584 rtt
= TCP_RTT_GRAN
*CLOCK_GRAN
;
586 else if (rtt
> TCP_RTT_MAX
)
589 static int warned
/* = 0 */;
594 "tcp_release_retrans: warning retransmission time is limited to %d ms\n",
595 TCP_RTT_MAX
*1000/HZ
);
602 "tcp_release_retrans, conn[%d]: retrans_time= %ld ms, rtt = %ld ms\n",
603 tcp_conn
-tcp_conn_table
,
604 retrans_time
*1000/HZ
,
608 "tcp_release_retrans: artt= %ld -> %ld, drtt= %ld -> %ld\n",
609 tcp_conn
->tc_artt
, artt
,
610 tcp_conn
->tc_drtt
, drtt
));
612 tcp_conn
->tc_artt
= artt
;
613 tcp_conn
->tc_drtt
= drtt
;
614 tcp_conn
->tc_rtt
= rtt
;
617 if (tcp_conn
->tc_mtu
!= tcp_conn
->tc_max_mtu
&&
618 curr_time
> tcp_conn
->tc_mtutim
+TCP_PMTU_INCR_IV
)
620 tcp_mtu_incr(tcp_conn
);
624 /* Update the current window. */
625 window
= tcp_conn
->tc_snd_cwnd
-tcp_conn
->tc_SND_UNA
;
626 assert(seg_ack
!= tcp_conn
->tc_SND_UNA
);
628 /* For every real ACK we try to increase the current window
633 /* If the window becomes larger than the current threshold,
634 * increment the threshold by a small amount and set the
635 * window to the threshold.
637 cthresh
= tcp_conn
->tc_snd_cthresh
;
638 if (window
> cthresh
)
640 cthresh
+= tcp_conn
->tc_snd_cinc
;
641 tcp_conn
->tc_snd_cthresh
= cthresh
;
645 /* If the window is larger than the window advertised by the
646 * receiver, set the window size to the advertisement.
648 if (window
> new_win
)
651 tcp_conn
->tc_snd_cwnd
= seg_ack
+window
;
653 /* Release data queued for retransmissions. */
654 queue_lo
= tcp_conn
->tc_SND_UNA
;
655 queue_hi
= tcp_conn
->tc_SND_NXT
;
657 tcp_conn
->tc_SND_UNA
= seg_ack
;
658 if (tcp_Lmod4G(tcp_conn
->tc_SND_TRM
, seg_ack
))
660 tcp_conn
->tc_SND_TRM
= seg_ack
;
662 assert(tcp_GEmod4G(tcp_conn
->tc_snd_cwnd
, seg_ack
));
664 /* Advance ISS every 0.5GB to avoid problem with wrap around */
665 if (tcp_conn
->tc_SND_UNA
- tcp_conn
->tc_ISS
> 0x40000000)
667 tcp_conn
->tc_ISS
+= 0x20000000;
669 "tcp_release_retrans: updating ISS to 0x%lx\n",
670 (unsigned long)tcp_conn
->tc_ISS
););
671 if (tcp_Lmod4G(tcp_conn
->tc_SND_UP
, tcp_conn
->tc_ISS
))
673 tcp_conn
->tc_SND_UP
= tcp_conn
->tc_ISS
;
675 "tcp_release_retrans: updating SND_UP to 0x%lx\n",
676 (unsigned long)tcp_conn
->tc_SND_UP
););
680 if (queue_lo
== tcp_conn
->tc_ISS
)
683 if (tcp_conn
->tc_flags
& TCF_FIN_SENT
)
685 if (seg_ack
== queue_hi
)
687 if (queue_lo
== queue_hi
)
692 offset
= seg_ack
- queue_lo
;
693 size
= queue_hi
- seg_ack
;
694 pack
= tcp_conn
->tc_send_data
;
695 tcp_conn
->tc_send_data
= 0;
703 pack
= bf_delhead(pack
, offset
);
704 tcp_conn
->tc_send_data
= pack
;
707 if (tcp_Gmod4G(tcp_conn
->tc_SND_TRM
, tcp_conn
->tc_snd_cwnd
))
708 tcp_conn
->tc_SND_TRM
= tcp_conn
->tc_snd_cwnd
;
710 /* Copy in new data if an ioctl is pending or if a write request is
711 * pending and either the write can be completed or at least one
712 * mss buffer space is available.
714 tcp_fd
= tcp_conn
->tc_fd
;
717 if (tcp_fd
->tf_flags
& TFF_IOCTL_IP
)
719 tcp_fd_write(tcp_conn
);
721 if ((tcp_fd
->tf_flags
& TFF_WRITE_IP
) &&
722 (size
+tcp_fd
->tf_write_count
<= TCP_MAX_SND_WND_SIZE
||
723 size
<= TCP_MAX_SND_WND_SIZE
-mss
))
725 tcp_fd_write(tcp_conn
);
727 if (tcp_fd
->tf_flags
& TFF_SEL_WRITE
)
728 tcp_rsel_write(tcp_conn
);
732 if (tcp_conn
->tc_SND_UNA
== tcp_conn
->tc_SND_NXT
)
734 assert(tcp_conn
->tc_state
== TCS_CLOSING
);
736 printf("all data sent in abondoned connection\n"));
737 tcp_close_connection(tcp_conn
, ENOTCONN
);
742 if (!size
&& !tcp_conn
->tc_send_data
)
744 /* Reset window if a write is completed */
745 tcp_conn
->tc_snd_cwnd
= tcp_conn
->tc_SND_UNA
+ mss
;
748 DIFBLOCK(2, (tcp_conn
->tc_snd_cwnd
== tcp_conn
->tc_SND_TRM
),
749 printf("not sending: zero window\n"));
751 if (tcp_conn
->tc_snd_cwnd
!= tcp_conn
->tc_SND_TRM
&&
752 tcp_conn
->tc_SND_NXT
!= tcp_conn
->tc_SND_TRM
)
754 tcp_conn_write(tcp_conn
, 1);
763 PUBLIC
void tcp_fast_retrans(tcp_conn
)
764 tcp_conn_t
*tcp_conn
;
768 /* Update threshold sequence number for retransmission calculation. */
769 if (tcp_Gmod4G(tcp_conn
->tc_SND_TRM
, tcp_conn
->tc_rt_threshold
))
770 tcp_conn
->tc_rt_threshold
= tcp_conn
->tc_SND_TRM
;
772 tcp_conn
->tc_SND_TRM
= tcp_conn
->tc_SND_UNA
;
774 mss
= tcp_conn
->tc_mtu
-IP_TCP_MIN_HDR_SIZE
;
777 if (tcp_conn
->tc_snd_cwnd
== tcp_conn
->tc_SND_UNA
)
778 tcp_conn
->tc_snd_cwnd
++;
779 if (tcp_Gmod4G(tcp_conn
->tc_snd_cwnd
, tcp_conn
->tc_SND_UNA
+ mss2
))
781 tcp_conn
->tc_snd_cwnd
= tcp_conn
->tc_SND_UNA
+ mss2
;
782 if (tcp_Gmod4G(tcp_conn
->tc_SND_TRM
, tcp_conn
->tc_snd_cwnd
))
783 tcp_conn
->tc_SND_TRM
= tcp_conn
->tc_snd_cwnd
;
785 tcp_conn
->tc_snd_cthresh
/= 2;
786 if (tcp_conn
->tc_snd_cthresh
< mss2
)
787 tcp_conn
->tc_snd_cthresh
= mss2
;
790 tcp_conn_write(tcp_conn
, 1);
794 PUBLIC
void do_tcp_timeout(tcp_conn
)
795 tcp_conn_t
*tcp_conn
;
797 tcp_send_timeout(tcp_conn
-tcp_conn_table
,
798 &tcp_conn
->tc_transmit_timer
);
806 PRIVATE
void tcp_send_timeout(conn
, timer
)
810 tcp_conn_t
*tcp_conn
;
812 u32_t snd_una
, snd_nxt
;
813 clock_t curr_time
, rtt
, stt
, timeout
;
815 int new_ttl
, no_push
;
817 DBLOCK(0x20, printf("tcp_send_timeout: conn[%d]\n", conn
));
819 curr_time
= get_time();
821 tcp_conn
= &tcp_conn_table
[conn
];
822 assert(tcp_conn
->tc_flags
& TCF_INUSE
);
823 assert(tcp_conn
->tc_state
!= TCS_CLOSED
);
824 assert(tcp_conn
->tc_state
!= TCS_LISTEN
);
826 snd_una
= tcp_conn
->tc_SND_UNA
;
827 snd_nxt
= tcp_conn
->tc_SND_NXT
;
828 no_push
= (tcp_conn
->tc_flags
& TCF_NO_PUSH
);
829 if (snd_nxt
== snd_una
|| no_push
)
831 /* Nothing more to send */
832 assert(tcp_conn
->tc_SND_TRM
== snd_una
|| no_push
);
834 /* A new write sets the timer if tc_transmit_seq == SND_UNA */
835 tcp_conn
->tc_transmit_seq
= tcp_conn
->tc_SND_UNA
;
837 tcp_conn
->tc_0wnd_to
= 0;
838 assert(!tcp_conn
->tc_fd
||
839 !(tcp_conn
->tc_fd
->tf_flags
& TFF_WRITE_IP
) ||
840 (tcp_print_conn(tcp_conn
), printf("\n"), 0));
842 if (snd_nxt
!= snd_una
)
845 DBLOCK(1, printf("not setting keepalive timer\n"););
847 /* No point in setting the keepalive timer if we
848 * still have to send more data.
853 assert(tcp_conn
->tc_send_data
== NULL
);
854 DBLOCK(0x20, printf("keep alive timer\n"));
855 if (tcp_conn
->tc_ka_snd
!= tcp_conn
->tc_SND_NXT
||
856 tcp_conn
->tc_ka_rcv
!= tcp_conn
->tc_RCV_NXT
)
858 tcp_conn
->tc_ka_snd
= tcp_conn
->tc_SND_NXT
;
859 tcp_conn
->tc_ka_rcv
= tcp_conn
->tc_RCV_NXT
;
861 "tcp_send_timeout: conn[%d] setting keepalive timer (+%ld ms)\n",
862 tcp_conn
-tcp_conn_table
,
863 tcp_conn
->tc_ka_time
*1000/HZ
));
864 clck_timer(&tcp_conn
->tc_transmit_timer
,
865 curr_time
+tcp_conn
->tc_ka_time
,
867 tcp_conn
-tcp_conn_table
);
871 "tcp_send_timeout, conn[%d]: triggering keep alive probe\n",
872 tcp_conn
-tcp_conn_table
));
873 tcp_conn
->tc_ka_snd
--;
874 if (!(tcp_conn
->tc_flags
& TCF_FIN_SENT
))
877 *ptr2acc_data(pkt
)= '\xff'; /* a random char */
878 tcp_conn
->tc_send_data
= pkt
; pkt
= NULL
;
880 tcp_conn
->tc_SND_UNA
--;
881 if (tcp_conn
->tc_SND_UNA
== tcp_conn
->tc_ISS
)
883 /* We didn't send anything so far. Retrying the
884 * SYN is too hard. Decrement ISS and hope
885 * that the other side doesn't care.
890 /* Set tc_transmit_seq and tc_stt to trigger packet */
891 tcp_conn
->tc_transmit_seq
= tcp_conn
->tc_SND_UNA
;
892 tcp_conn
->tc_stt
= curr_time
;
894 /* Set tc_rt_seq for round trip measurements */
895 tcp_conn
->tc_rt_time
= curr_time
;
896 tcp_conn
->tc_rt_seq
= tcp_conn
->tc_SND_UNA
;
898 /* Set PSH to make sure that data gets sent */
899 tcp_conn
->tc_SND_PSH
= tcp_conn
->tc_SND_NXT
;
900 assert(tcp_check_conn(tcp_conn
));
905 rtt
= tcp_conn
->tc_rtt
;
907 if (tcp_conn
->tc_transmit_seq
!= tcp_conn
->tc_SND_UNA
)
909 /* Some data has been acknowledged since the last time the
910 * timer was set, set the timer again. */
911 tcp_conn
->tc_transmit_seq
= tcp_conn
->tc_SND_UNA
;
913 tcp_conn
->tc_0wnd_to
= 0;
916 "tcp_send_timeout: conn[%d] setting timer to %ld ms (+%ld ms)\n",
917 tcp_conn
-tcp_conn_table
,
918 (curr_time
+rtt
)*1000/HZ
, rtt
*1000/HZ
));
920 clck_timer(&tcp_conn
->tc_transmit_timer
,
921 curr_time
+rtt
, tcp_send_timeout
,
922 tcp_conn
-tcp_conn_table
);
926 stt
= tcp_conn
->tc_stt
;
929 /* Some packet arrived but did not acknowledge any data.
930 * Apparently, the other side is still alive and has a
931 * reason to transmit. We can asume a zero window.
934 DBLOCK(0x10, printf("conn[%d] setting zero window timer\n",
935 tcp_conn
-tcp_conn_table
));
937 if (tcp_conn
->tc_0wnd_to
< TCP_0WND_MIN
)
938 tcp_conn
->tc_0wnd_to
= TCP_0WND_MIN
;
939 else if (tcp_conn
->tc_0wnd_to
< rtt
)
940 tcp_conn
->tc_0wnd_to
= rtt
;
943 tcp_conn
->tc_0wnd_to
*= 2;
944 if (tcp_conn
->tc_0wnd_to
> TCP_0WND_MAX
)
945 tcp_conn
->tc_0wnd_to
= TCP_0WND_MAX
;
947 tcp_conn
->tc_stt
= curr_time
;
948 tcp_conn
->tc_rt_seq
= 0;
951 "tcp_send_timeout: conn[%d] setting timer to %ld ms (+%ld ms)\n",
952 tcp_conn
-tcp_conn_table
,
953 (curr_time
+tcp_conn
->tc_0wnd_to
)*1000/HZ
,
954 tcp_conn
->tc_0wnd_to
*1000/HZ
));
956 clck_timer(&tcp_conn
->tc_transmit_timer
,
957 curr_time
+tcp_conn
->tc_0wnd_to
,
958 tcp_send_timeout
, tcp_conn
-tcp_conn_table
);
961 assert(stt
<= curr_time
);
963 DIFBLOCK(0x10, (tcp_conn
->tc_fd
== 0),
964 printf("conn[%d] timeout in abondoned connection\n",
965 tcp_conn
-tcp_conn_table
));
967 /* At this point, we have do a retransmission, or send a zero window
968 * probe, which is almost the same.
971 DBLOCK(0x20, printf("tcp_send_timeout: conn[%d] una= %lu, rtt= %ldms\n",
972 tcp_conn
-tcp_conn_table
,
973 (unsigned long)tcp_conn
->tc_SND_UNA
, rtt
*1000/HZ
));
975 /* Update threshold sequence number for retransmission calculation. */
976 if (tcp_Gmod4G(tcp_conn
->tc_SND_TRM
, tcp_conn
->tc_rt_threshold
))
977 tcp_conn
->tc_rt_threshold
= tcp_conn
->tc_SND_TRM
;
979 tcp_conn
->tc_SND_TRM
= tcp_conn
->tc_SND_UNA
;
981 if (tcp_conn
->tc_flags
& TCF_PMTU
&&
982 curr_time
> stt
+TCP_PMTU_BLACKHOLE
)
984 /* We can't tell the difference between a PMTU blackhole
985 * and a broken link. Assume a PMTU blackhole, and switch
986 * off PMTU discovery.
989 "tcp[%d]: PMTU blackhole (or broken link) on route to ",
990 tcp_conn
-tcp_conn_table
);
991 writeIpAddr(tcp_conn
->tc_remaddr
);
992 printf(", max mtu = %u\n", tcp_conn
->tc_max_mtu
););
993 tcp_conn
->tc_flags
&= ~TCF_PMTU
;
994 tcp_conn
->tc_mtutim
= curr_time
;
995 if (tcp_conn
->tc_max_mtu
> IP_DEF_MTU
)
996 tcp_conn
->tc_mtu
= IP_DEF_MTU
;
999 mss
= tcp_conn
->tc_mtu
-IP_TCP_MIN_HDR_SIZE
;
1002 if (tcp_conn
->tc_snd_cwnd
== tcp_conn
->tc_SND_UNA
)
1003 tcp_conn
->tc_snd_cwnd
++;
1004 if (tcp_Gmod4G(tcp_conn
->tc_snd_cwnd
, tcp_conn
->tc_SND_UNA
+ mss2
))
1006 tcp_conn
->tc_snd_cwnd
= tcp_conn
->tc_SND_UNA
+ mss2
;
1007 if (tcp_Gmod4G(tcp_conn
->tc_SND_TRM
, tcp_conn
->tc_snd_cwnd
))
1008 tcp_conn
->tc_SND_TRM
= tcp_conn
->tc_snd_cwnd
;
1010 tcp_conn
->tc_snd_cthresh
/= 2;
1011 if (tcp_conn
->tc_snd_cthresh
< mss2
)
1012 tcp_conn
->tc_snd_cthresh
= mss2
;
1015 if (curr_time
-stt
> tcp_conn
->tc_rt_dead
)
1017 tcp_close_connection(tcp_conn
, ETIMEDOUT
);
1021 timeout
= (curr_time
-stt
) >> 3;
1024 timeout
+= curr_time
;
1026 DBLOCK(0x20, printf(
1027 "tcp_send_timeout: conn[%d] setting timer to %ld ms (+%ld ms)\n",
1028 tcp_conn
-tcp_conn_table
, timeout
*1000/HZ
,
1029 (timeout
-curr_time
)*1000/HZ
));
1031 clck_timer(&tcp_conn
->tc_transmit_timer
, timeout
,
1032 tcp_send_timeout
, tcp_conn
-tcp_conn_table
);
1035 if (tcp_conn
->tc_rt_seq
== 0)
1037 printf("tcp_send_timeout: conn[%d]: setting tc_rt_time\n",
1038 tcp_conn
-tcp_conn_table
);
1039 tcp_conn
->tc_rt_time
= curr_time
-rtt
;
1040 tcp_conn
->tc_rt_seq
= tcp_conn
->tc_SND_UNA
;
1044 if (tcp_conn
->tc_state
== TCS_SYN_SENT
||
1045 (curr_time
-stt
>= tcp_conn
->tc_ttl
*HZ
))
1047 new_ttl
= tcp_conn
->tc_ttl
+1;
1048 if (new_ttl
> IP_MAX_TTL
)
1049 new_ttl
= IP_MAX_TTL
;
1050 tcp_conn
->tc_ttl
= new_ttl
;
1053 tcp_conn_write(tcp_conn
, 0);
1057 PUBLIC
void tcp_fd_write(tcp_conn
)
1058 tcp_conn_t
*tcp_conn
;
1061 int urg
, nourg
, push
;
1063 size_t max_trans
, write_count
;
1064 acc_t
*data
, *send_data
;
1066 assert(tcp_conn
->tc_busy
);
1067 tcp_fd
= tcp_conn
->tc_fd
;
1069 if ((tcp_fd
->tf_flags
& TFF_IOCTL_IP
) &&
1070 !(tcp_fd
->tf_flags
& TFF_WRITE_IP
))
1072 if (tcp_fd
->tf_ioreq
!= NWIOTCPSHUTDOWN
)
1074 DBLOCK(0x10, printf("NWIOTCPSHUTDOWN\n"));
1075 if (tcp_conn
->tc_state
== TCS_CLOSED
)
1077 tcp_reply_ioctl (tcp_fd
, tcp_conn
->tc_error
);
1080 if (!(tcp_conn
->tc_flags
& TCF_FIN_SENT
))
1082 DBLOCK(0x10, printf("calling tcp_shutdown\n"));
1083 tcp_shutdown (tcp_conn
);
1087 if (tcp_conn
->tc_SND_UNA
== tcp_conn
->tc_SND_NXT
)
1089 tcp_reply_ioctl (tcp_fd
, NW_OK
);
1090 DBLOCK(0x10, printf("shutdown completed\n"));
1095 printf("shutdown still inprogress\n"));
1101 assert (tcp_fd
->tf_flags
& TFF_WRITE_IP
);
1102 if (tcp_conn
->tc_state
== TCS_CLOSED
)
1104 if (tcp_fd
->tf_write_offset
)
1106 tcp_reply_write(tcp_fd
,
1107 tcp_fd
->tf_write_offset
);
1110 tcp_reply_write(tcp_fd
, tcp_conn
->tc_error
);
1114 urg
= (tcp_fd
->tf_flags
& TFF_WR_URG
);
1115 push
= (tcp_fd
->tf_flags
& TFF_PUSH_DATA
);
1117 max_seq
= tcp_conn
->tc_SND_UNA
+ TCP_MAX_SND_WND_SIZE
;
1118 max_trans
= max_seq
- tcp_conn
->tc_SND_NXT
;
1119 if (tcp_fd
->tf_write_count
<= max_trans
)
1120 write_count
= tcp_fd
->tf_write_count
;
1122 write_count
= max_trans
;
1125 if (tcp_conn
->tc_flags
& TCF_BSD_URG
)
1127 if (tcp_Gmod4G(tcp_conn
->tc_SND_NXT
,
1128 tcp_conn
->tc_SND_UNA
))
1130 nourg
= tcp_LEmod4G(tcp_conn
->tc_SND_UP
,
1131 tcp_conn
->tc_SND_UNA
);
1132 if ((urg
&& nourg
) || (!urg
&& !nourg
))
1135 printf("not sending\n"));
1140 data
= (*tcp_fd
->tf_get_userdata
)
1141 (tcp_fd
->tf_srfd
, tcp_fd
->tf_write_offset
,
1142 write_count
, FALSE
);
1146 if (tcp_fd
->tf_write_offset
)
1148 tcp_reply_write(tcp_fd
,
1149 tcp_fd
->tf_write_offset
);
1152 tcp_reply_write(tcp_fd
, EFAULT
);
1155 tcp_fd
->tf_write_offset
+= write_count
;
1156 tcp_fd
->tf_write_count
-= write_count
;
1158 send_data
= tcp_conn
->tc_send_data
;
1159 tcp_conn
->tc_send_data
= 0;
1160 send_data
= bf_append(send_data
, data
);
1161 tcp_conn
->tc_send_data
= send_data
;
1162 tcp_conn
->tc_SND_NXT
+= write_count
;
1165 if (tcp_conn
->tc_flags
& TCF_BSD_URG
)
1166 tcp_conn
->tc_SND_UP
= tcp_conn
->tc_SND_NXT
;
1168 tcp_conn
->tc_SND_UP
= tcp_conn
->tc_SND_NXT
-1;
1170 if (push
&& !tcp_fd
->tf_write_count
)
1171 tcp_conn
->tc_SND_PSH
= tcp_conn
->tc_SND_NXT
;
1173 if (!tcp_fd
->tf_write_count
)
1175 tcp_reply_write(tcp_fd
, tcp_fd
->tf_write_offset
);
1179 PUBLIC
unsigned tcp_sel_write(tcp_conn
)
1180 tcp_conn_t
*tcp_conn
;
1187 tcp_fd
= tcp_conn
->tc_fd
;
1189 if (tcp_conn
->tc_state
== TCS_CLOSED
)
1192 urg
= (tcp_fd
->tf_flags
& TFF_WR_URG
);
1194 max_seq
= tcp_conn
->tc_SND_UNA
+ TCP_MAX_SND_WND_SIZE
;
1195 max_trans
= max_seq
- tcp_conn
->tc_SND_NXT
;
1198 if (tcp_conn
->tc_flags
& TCF_BSD_URG
)
1200 if (tcp_Gmod4G(tcp_conn
->tc_SND_NXT
,
1201 tcp_conn
->tc_SND_UNA
))
1203 nourg
= tcp_LEmod4G(tcp_conn
->tc_SND_UP
,
1204 tcp_conn
->tc_SND_UNA
);
1205 if ((urg
&& nourg
) || (!urg
&& !nourg
))
1208 printf("not sending\n"));
1220 tcp_rsel_write(tcp_conn
)
1221 tcp_conn_t
*tcp_conn
;
1225 if (tcp_sel_write(tcp_conn
) == 0)
1228 tcp_fd
= tcp_conn
->tc_fd
;
1229 tcp_fd
->tf_flags
&= ~TFF_SEL_WRITE
;
1230 if (tcp_fd
->tf_select_res
)
1231 tcp_fd
->tf_select_res(tcp_fd
->tf_srfd
, SR_SELECT_WRITE
);
1233 printf("tcp_rsel_write: no select_res\n");
1240 PUBLIC
void tcp_shutdown(tcp_conn
)
1241 tcp_conn_t
*tcp_conn
;
1243 switch (tcp_conn
->tc_state
)
1248 case TCS_SYN_RECEIVED
:
1249 tcp_close_connection(tcp_conn
, ENOTCONN
);
1253 if (tcp_conn
->tc_flags
& TCF_FIN_SENT
)
1255 tcp_conn
->tc_flags
|= TCF_FIN_SENT
;
1256 tcp_conn
->tc_flags
&= ~TCF_NO_PUSH
;
1257 tcp_conn
->tc_SND_NXT
++;
1258 tcp_conn
->tc_SND_PSH
= tcp_conn
->tc_SND_NXT
;
1260 assert (tcp_check_conn(tcp_conn
) ||
1261 (tcp_print_conn(tcp_conn
), printf("\n"), 0));
1263 tcp_conn_write(tcp_conn
, 1);
1265 /* Start the timer */
1266 tcp_set_send_timer(tcp_conn
);
1269 PUBLIC
void tcp_set_send_timer(tcp_conn
)
1270 tcp_conn_t
*tcp_conn
;
1275 assert(tcp_conn
->tc_state
!= TCS_CLOSED
);
1276 assert(tcp_conn
->tc_state
!= TCS_LISTEN
);
1278 curr_time
= get_time();
1279 rtt
= tcp_conn
->tc_rtt
;
1281 DBLOCK(0x20, printf(
1282 "tcp_set_send_timer: conn[%d] setting timer to %ld ms (+%ld ms)\n",
1283 tcp_conn
-tcp_conn_table
,
1284 (curr_time
+rtt
)*1000/HZ
, rtt
*1000/HZ
));
1286 /* Start the timer */
1287 clck_timer(&tcp_conn
->tc_transmit_timer
,
1288 curr_time
+rtt
, tcp_send_timeout
, tcp_conn
-tcp_conn_table
);
1289 tcp_conn
->tc_stt
= curr_time
;
1293 tcp_close_connection
1297 PUBLIC
void tcp_close_connection(tcp_conn
, error
)
1298 tcp_conn_t
*tcp_conn
;
1302 tcp_port_t
*tcp_port
;
1306 assert (tcp_check_conn(tcp_conn
) ||
1307 (tcp_print_conn(tcp_conn
), printf("\n"), 0));
1308 assert (tcp_conn
->tc_flags
& TCF_INUSE
);
1310 tcp_conn
->tc_error
= error
;
1311 tcp_port
= tcp_conn
->tc_port
;
1312 tcp_fd
= tcp_conn
->tc_fd
;
1313 if (tcp_conn
->tc_state
== TCS_CLOSED
)
1316 tcp_conn
->tc_state
= TCS_CLOSED
;
1317 DBLOCK(0x10, tcp_print_state(tcp_conn
); printf("\n"));
1319 if (tcp_fd
&& (tcp_fd
->tf_flags
& TFF_LISTENQ
))
1321 for (i
= 0; i
<TFL_LISTEN_MAX
; i
++)
1323 if (tcp_fd
->tf_listenq
[i
] == tcp_conn
)
1326 assert(i
< TFL_LISTEN_MAX
);
1327 tcp_fd
->tf_listenq
[i
]= NULL
;
1329 assert(tcp_conn
->tc_connInprogress
);
1330 tcp_conn
->tc_connInprogress
= 0;
1332 tcp_conn
->tc_fd
= NULL
;
1338 tcp_conn
->tc_busy
++;
1339 assert(tcp_fd
->tf_conn
== tcp_conn
);
1341 if (tcp_fd
->tf_flags
& TFF_READ_IP
)
1342 tcp_fd_read (tcp_conn
, 1);
1343 assert (!(tcp_fd
->tf_flags
& TFF_READ_IP
));
1344 if (tcp_fd
->tf_flags
& TFF_SEL_READ
)
1345 tcp_rsel_read (tcp_conn
);
1347 if (tcp_fd
->tf_flags
& TFF_WRITE_IP
)
1349 tcp_fd_write(tcp_conn
);
1350 tcp_conn_write(tcp_conn
, 1);
1352 assert (!(tcp_fd
->tf_flags
& TFF_WRITE_IP
));
1353 if (tcp_fd
->tf_flags
& TFF_IOCTL_IP
)
1355 tcp_fd_write(tcp_conn
);
1356 tcp_conn_write(tcp_conn
, 1);
1358 if (tcp_fd
->tf_flags
& TFF_IOCTL_IP
)
1359 assert(tcp_fd
->tf_ioreq
!= NWIOTCPSHUTDOWN
);
1360 if (tcp_fd
->tf_flags
& TFF_SEL_WRITE
)
1361 tcp_rsel_write(tcp_conn
);
1363 if (tcp_conn
->tc_connInprogress
)
1364 tcp_restart_connect(tcp_conn
);
1365 assert (!tcp_conn
->tc_connInprogress
);
1366 assert (!(tcp_fd
->tf_flags
& TFF_IOCTL_IP
) ||
1367 (printf("req= 0x%lx\n",
1368 (unsigned long)tcp_fd
->tf_ioreq
), 0));
1369 tcp_conn
->tc_busy
--;
1372 if (tcp_conn
->tc_rcvd_data
)
1374 bf_afree(tcp_conn
->tc_rcvd_data
);
1375 tcp_conn
->tc_rcvd_data
= NULL
;
1377 tcp_conn
->tc_flags
&= ~TCF_FIN_RECV
;
1378 tcp_conn
->tc_RCV_LO
= tcp_conn
->tc_RCV_NXT
;
1380 if (tcp_conn
->tc_adv_data
)
1382 bf_afree(tcp_conn
->tc_adv_data
);
1383 tcp_conn
->tc_adv_data
= NULL
;
1386 if (tcp_conn
->tc_send_data
)
1388 bf_afree(tcp_conn
->tc_send_data
);
1389 tcp_conn
->tc_send_data
= NULL
;
1390 tcp_conn
->tc_SND_TRM
=
1391 tcp_conn
->tc_SND_NXT
= tcp_conn
->tc_SND_UNA
;
1393 tcp_conn
->tc_SND_TRM
= tcp_conn
->tc_SND_NXT
= tcp_conn
->tc_SND_UNA
;
1395 if (tcp_conn
->tc_remipopt
)
1397 bf_afree(tcp_conn
->tc_remipopt
);
1398 tcp_conn
->tc_remipopt
= NULL
;
1401 if (tcp_conn
->tc_tcpopt
)
1403 bf_afree(tcp_conn
->tc_tcpopt
);
1404 tcp_conn
->tc_tcpopt
= NULL
;
1407 if (tcp_conn
->tc_frag2send
)
1409 bf_afree(tcp_conn
->tc_frag2send
);
1410 tcp_conn
->tc_frag2send
= NULL
;
1412 if (tcp_conn
->tc_flags
& TCF_MORE2WRITE
)
1414 for (tc
= tcp_port
->tp_snd_head
; tc
; tc
= tc
->tc_send_link
)
1416 if (tc
->tc_send_link
== tcp_conn
)
1421 assert(tcp_port
->tp_snd_head
== tcp_conn
);
1422 tcp_port
->tp_snd_head
= tcp_conn
->tc_send_link
;
1426 tc
->tc_send_link
= tcp_conn
->tc_send_link
;
1427 if (tc
->tc_send_link
== NULL
)
1428 tcp_port
->tp_snd_tail
= tc
;
1430 tcp_conn
->tc_flags
&= ~TCF_MORE2WRITE
;
1433 clck_untimer (&tcp_conn
->tc_transmit_timer
);
1434 tcp_conn
->tc_transmit_seq
= 0;
1436 /* clear all flags but TCF_INUSE */
1437 tcp_conn
->tc_flags
&= TCF_INUSE
;
1438 assert (tcp_check_conn(tcp_conn
));
1442 * $PchId: tcp_send.c,v 1.32 2005/06/28 14:21:52 philip Exp $