add/re-enable at_wini debug output
[minix3.git] / servers / inet / generic / tcp_send.c
blob7541ef819f4cfb9529e44d6589313c2e0aa881a9
1 /*
2 tcp_send.c
4 Copyright 1995 Philip Homburg
5 */
7 #include "inet.h"
8 #include "buf.h"
9 #include "clock.h"
10 #include "event.h"
11 #include "type.h"
12 #include "sr.h"
14 #include "assert.h"
15 #include "io.h"
16 #include "ip.h"
17 #include "tcp.h"
18 #include "tcp_int.h"
20 THIS_FILE
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)
27 tcp_conn_t *tcp_conn;
28 int enq; /* Writes need to be enqueued. */
30 tcp_port_t *tcp_port;
31 ev_arg_t snd_arg;
33 assert (tcp_conn->tc_flags & TCF_INUSE);
35 tcp_port= tcp_conn->tc_port;
36 if (tcp_conn->tc_flags & TCF_MORE2WRITE)
37 return;
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)
44 return;
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;
53 if (enq)
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);
62 else
63 tcp_port_write(tcp_port);
65 else
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)
73 event_t *ev;
74 ev_arg_t arg;
76 tcp_port_t *tcp_port;
78 tcp_port= arg.ev_ptr;
80 assert(ev == &tcp_port->tp_snd_event);
81 tcp_port_write(tcp_port);
84 PUBLIC void tcp_port_write(tcp_port)
85 tcp_port_t *tcp_port;
87 tcp_conn_t *tcp_conn;
88 acc_t *pack2write;
89 int r;
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);
98 for(;;)
100 if (tcp_conn->tc_frag2send)
102 pack2write= tcp_conn->tc_frag2send;
103 tcp_conn->tc_frag2send= 0;
105 else
107 tcp_conn->tc_busy++;
108 pack2write= make_pack(tcp_conn);
109 tcp_conn->tc_busy--;
110 if (!pack2write)
111 break;
113 r= ip_send(tcp_port->tp_ipfd, pack2write,
114 bf_bufsize(pack2write));
115 if (r != NW_OK)
117 if (r == NW_WOULDBLOCK)
118 break;
119 if (r == EPACKSIZE)
121 tcp_mtu_exceeded(tcp_conn);
122 continue;
124 if (r == EDSTNOTRCH)
126 tcp_notreach(tcp_conn);
127 continue;
129 if (r == EBADDEST)
130 continue;
132 assert(r == NW_OK ||
133 (printf("ip_send failed, error %d\n", r),0));
136 if (pack2write)
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));
143 if (r == NW_SUSPEND)
145 tcp_port->tp_flags |= TPF_WRITE_SP;
146 return;
148 assert(r == NW_OK);
149 tcp_port->tp_flags &= ~TPF_WRITE_IP;
150 assert(!(tcp_port->tp_flags &
151 (TPF_WRITE_IP|TPF_WRITE_SP)));
152 continue;
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;
164 tcp_hdr_t *tcp_hdr;
165 ip_hdr_t *ip_hdr;
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;
168 u16_t seg_up, mss;
169 u8_t seg_flags;
170 size_t pack_size;
171 clock_t curr_time, new_dis;
172 u8_t *optptr;
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)
180 case TCS_CLOSED:
181 case TCS_LISTEN:
182 return NULL;
183 case TCS_SYN_RECEIVED:
184 case TCS_SYN_SENT:
186 if (tcp_conn->tc_SND_TRM == tcp_conn->tc_SND_NXT &&
187 !(tcp_conn->tc_flags & TCF_SEND_ACK))
189 return 0;
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;
204 optptr[1]= 4;
205 optptr[2]= mss >> 8;
206 optptr[3]= mss & 0xFF;
208 pack2write= tcp_make_header(tcp_conn, &ip_hdr, &tcp_hdr,
209 (acc_t *)0);
211 bf_afree(tcp_conn->tc_tcpopt);
212 tcp_conn->tc_tcpopt= NULL;
214 if (!pack2write)
216 DBLOCK(1, printf("connection closed while inuse\n"));
217 return 0;
219 tot_hdr_size= bf_bufsize(pack2write);
220 seg_seq= tcp_conn->tc_SND_TRM;
221 if (tcp_conn->tc_state == TCS_SYN_SENT)
222 seg_flags= 0;
223 else
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);
247 bf_afree(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;
252 return pack2write;
254 case TCS_ESTABLISHED:
255 case TCS_CLOSING:
256 seg_seq= tcp_conn->tc_SND_TRM;
258 seg_flags= 0;
259 pack2write= 0;
260 seg_up= 0;
261 if (tcp_conn->tc_flags & TCF_SEND_ACK)
263 seg_flags= THF_ACK;
264 tcp_conn->tc_flags &= ~TCF_SEND_ACK;
266 pack2write= tcp_make_header (tcp_conn, &ip_hdr,
267 &tcp_hdr, (acc_t *)0);
268 if (!pack2write)
270 return NULL;
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)
280 DBLOCK(2,
281 printf("no data: window is closed\n"));
282 goto after_data;
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;
292 seg_hi_data= seg_hi;
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)
298 queue_lo_data--;
299 if (seg_lo_data == seg_hi_data)
300 seg_lo_data--;
301 seg_hi_data--;
304 if (!pack2write)
306 pack2write= tcp_make_header (tcp_conn,
307 &ip_hdr, &tcp_hdr, (acc_t *)0);
308 if (!pack2write)
310 return NULL;
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);
318 if (no_push)
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
325 * for a future push.
327 DBLOCK(0x20,
328 printf("no data: no push\n"));
329 if (head)
331 DBLOCK(0x1, printf(
332 "no data: setting TCF_NO_PUSH\n"));
333 tcp_conn->tc_flags |=
334 TCF_NO_PUSH;
336 goto after_data;
338 seg_hi_data--;
341 if (tot_hdr_size != IP_TCP_MIN_HDR_SIZE)
343 printf(
344 "tcp_write`make_pack: tot_hdr_size = %d\n",
345 tot_hdr_size);
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;
352 seg_hi= seg_hi_data;
353 seg_flags &= ~THF_FIN;
356 if (no_push &&
357 seg_hi_data-seg_lo_data != mss)
359 DBLOCK(0x20, printf(
360 "no data: no push for partial segment\n"));
361 more2write= (tcp_conn->tc_fd &&
362 (tcp_conn->tc_fd->tf_flags &
363 TFF_WRITE_IP));
364 DIFBLOCK(2, more2write,
365 printf(
366 "tcp_send`make_pack: more2write -> !TCF_NO_PUSH\n");
368 if (head && !more2write)
370 DBLOCK(0x1, printf(
371 "partial segment: setting TCF_NO_PUSH\n"));
372 tcp_conn->tc_flags |= TCF_NO_PUSH;
374 goto after_data;
378 if (tcp_Gmod4G(seg_hi, tcp_conn->tc_snd_cwnd))
380 seg_hi_data= tcp_conn->tc_snd_cwnd;
381 seg_hi= seg_hi_data;
382 seg_flags &= ~THF_FIN;
385 if (!head &&
386 seg_hi_data-seg_lo_data < mss)
388 if (tcp_conn->tc_flags & TCF_PUSH_NOW)
390 DBLOCK(0x20,
391 printf("push: no Nagle\n"));
393 else
395 DBLOCK(0x20,
396 printf("no data: partial packet\n"));
397 seg_flags &= ~THF_FIN;
398 goto after_data;
402 if (seg_hi-seg_seq == 0)
404 DBLOCK(0x20,
405 printf("no data: no data available\n"));
406 goto after_data;
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,
414 seg_hi_data))
416 seg_up= seg_hi_data-seg_seq;
418 else
420 seg_up= tcp_conn->tc_SND_UP-seg_seq;
422 seg_flags |= THF_URG;
423 if (!killer_inet &&
424 (tcp_conn->tc_flags & TCF_BSD_URG) &&
425 seg_up == 0)
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
436 * urgent byte.
438 seg_flags &= ~THF_URG;
441 else
442 seg_up= 0;
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;
458 tcp_conn->tc_rt_seq=
459 tcp_conn->tc_rt_threshold= seg_seq;
462 if (seg_hi_data-seg_lo_data)
464 #if DEBUG & 0
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),
472 printf(
473 " seg_hi_data= 0x%x, seg_lo_data= 0x%x, queue_lo_data= 0x%x\n",
474 seg_hi_data, seg_lo_data,
475 queue_lo_data), 0));
476 #endif
478 tmp_pack= pack2write;
479 while (tmp_pack->acc_next)
480 tmp_pack= tmp_pack->acc_next;
481 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;
489 after_data:
490 if (!(seg_flags & THF_ACK))
492 if (pack2write)
493 bf_afree(pack2write);
494 return NULL;
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);
511 bf_afree(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;
517 return pack2write;
518 default:
519 DBLOCK(1, tcp_print_conn(tcp_conn); printf("\n"));
520 ip_panic(( "Illegal state" ));
522 assert(0);
523 return NULL;
527 tcp_release_retrans
530 PUBLIC void tcp_release_retrans(tcp_conn, seg_ack, new_win)
531 tcp_conn_t *tcp_conn;
532 u32_t seg_ack;
533 u16_t new_win;
535 tcp_fd_t *tcp_fd;
536 size_t size, offset;
537 acc_t *pack;
538 clock_t retrans_time, curr_time, rtt, artt, drtt, srtt;
539 u32_t queue_lo, queue_hi;
540 u16_t mss, cthresh;
541 unsigned window;
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. */
568 else
570 srtt= retrans_time * TCP_RTT_SCALE;
572 artt= tcp_conn->tc_artt;
573 artt= ((TCP_RTT_SMOOTH-1)*artt+srtt)/TCP_RTT_SMOOTH;
575 srtt -= artt;
576 if (srtt < 0)
577 srtt= -srtt;
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)
588 #if DEBUG
589 static int warned /* = 0 */;
591 if (!warned)
593 printf(
594 "tcp_release_retrans: warning retransmission time is limited to %d ms\n",
595 TCP_RTT_MAX*1000/HZ);
596 warned= 1;
598 #endif
599 rtt= TCP_RTT_MAX;
601 DBLOCK(0x10, printf(
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,
605 rtt*1000/HZ));
607 DBLOCK(0x10, printf(
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
629 * with 1 mss.
631 window += mss;
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;
642 window= 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)
649 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;
668 DBLOCK(1, printf(
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;
674 DBLOCK(1, printf(
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)
681 queue_lo++;
683 if (tcp_conn->tc_flags & TCF_FIN_SENT)
685 if (seg_ack == queue_hi)
686 seg_ack--;
687 if (queue_lo == queue_hi)
688 queue_lo--;
689 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;
697 if (!size)
699 bf_afree(pack);
701 else
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;
715 if (tcp_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);
730 else
732 if (tcp_conn->tc_SND_UNA == tcp_conn->tc_SND_NXT)
734 assert(tcp_conn->tc_state == TCS_CLOSING);
735 DBLOCK(0x10,
736 printf("all data sent in abondoned connection\n"));
737 tcp_close_connection(tcp_conn, ENOTCONN);
738 return;
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);
760 tcp_fast_retrans
763 PUBLIC void tcp_fast_retrans(tcp_conn)
764 tcp_conn_t *tcp_conn;
766 u16_t mss, mss2;
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;
775 mss2= 2*mss;
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);
793 #if 0
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);
800 #endif
803 tcp_send_timeout
806 PRIVATE void tcp_send_timeout(conn, timer)
807 int conn;
808 struct timer *timer;
810 tcp_conn_t *tcp_conn;
811 u16_t mss, mss2;
812 u32_t snd_una, snd_nxt;
813 clock_t curr_time, rtt, stt, timeout;
814 acc_t *pkt;
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;
836 tcp_conn->tc_stt= 0;
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)
844 assert(no_push);
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.
850 return;
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;
860 DBLOCK(0x20, printf(
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,
866 tcp_send_timeout,
867 tcp_conn-tcp_conn_table);
868 return;
870 DBLOCK(0x10, printf(
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))
876 pkt= bf_memreq(1);
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.
887 tcp_conn->tc_ISS--;
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));
902 /* Fall through */
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;
912 tcp_conn->tc_stt= 0;
913 tcp_conn->tc_0wnd_to= 0;
915 DBLOCK(0x20, printf(
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);
923 return;
926 stt= tcp_conn->tc_stt;
927 if (stt == 0)
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;
941 else
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;
950 DBLOCK(0x10, printf(
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);
959 return;
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.
988 DBLOCK(1, printf(
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;
1000 mss2= 2*mss;
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);
1018 return;
1021 timeout= (curr_time-stt) >> 3;
1022 if (timeout < rtt)
1023 timeout= rtt;
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);
1034 #if 0
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;
1042 #endif
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;
1060 tcp_fd_t *tcp_fd;
1061 int urg, nourg, push;
1062 u32_t max_seq;
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)
1073 return;
1074 DBLOCK(0x10, printf("NWIOTCPSHUTDOWN\n"));
1075 if (tcp_conn->tc_state == TCS_CLOSED)
1077 tcp_reply_ioctl (tcp_fd, tcp_conn->tc_error);
1078 return;
1080 if (!(tcp_conn->tc_flags & TCF_FIN_SENT))
1082 DBLOCK(0x10, printf("calling tcp_shutdown\n"));
1083 tcp_shutdown (tcp_conn);
1085 else
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"));
1092 else
1094 DBLOCK(0x10,
1095 printf("shutdown still inprogress\n"));
1098 return;
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);
1109 else
1110 tcp_reply_write(tcp_fd, tcp_conn->tc_error);
1111 return;
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;
1121 else
1122 write_count= max_trans;
1123 if (write_count)
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))
1134 DBLOCK(0x20,
1135 printf("not sending\n"));
1136 return;
1140 data= (*tcp_fd->tf_get_userdata)
1141 (tcp_fd->tf_srfd, tcp_fd->tf_write_offset,
1142 write_count, FALSE);
1144 if (!data)
1146 if (tcp_fd->tf_write_offset)
1148 tcp_reply_write(tcp_fd,
1149 tcp_fd->tf_write_offset);
1151 else
1152 tcp_reply_write(tcp_fd, EFAULT);
1153 return;
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;
1163 if (urg)
1165 if (tcp_conn->tc_flags & TCF_BSD_URG)
1166 tcp_conn->tc_SND_UP= tcp_conn->tc_SND_NXT;
1167 else
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;
1182 tcp_fd_t *tcp_fd;
1183 int urg, nourg;
1184 u32_t max_seq;
1185 size_t max_trans;
1187 tcp_fd= tcp_conn->tc_fd;
1189 if (tcp_conn->tc_state == TCS_CLOSED)
1190 return 1;
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;
1196 if (max_trans)
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))
1207 DBLOCK(0x20,
1208 printf("not sending\n"));
1209 return 0;
1213 return 1;
1216 return 0;
1219 PUBLIC void
1220 tcp_rsel_write(tcp_conn)
1221 tcp_conn_t *tcp_conn;
1223 tcp_fd_t *tcp_fd;
1225 if (tcp_sel_write(tcp_conn) == 0)
1226 return;
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);
1232 else
1233 printf("tcp_rsel_write: no select_res\n");
1237 tcp_shutdown
1240 PUBLIC void tcp_shutdown(tcp_conn)
1241 tcp_conn_t *tcp_conn;
1243 switch (tcp_conn->tc_state)
1245 case TCS_CLOSED:
1246 case TCS_LISTEN:
1247 case TCS_SYN_SENT:
1248 case TCS_SYN_RECEIVED:
1249 tcp_close_connection(tcp_conn, ENOTCONN);
1250 return;
1253 if (tcp_conn->tc_flags & TCF_FIN_SENT)
1254 return;
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;
1272 clock_t curr_time;
1273 clock_t rtt;
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;
1299 int error;
1301 int i;
1302 tcp_port_t *tcp_port;
1303 tcp_fd_t *tcp_fd;
1304 tcp_conn_t *tc;
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)
1314 return;
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)
1324 break;
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;
1333 tcp_fd= NULL;
1335 else if (tcp_fd)
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)
1417 break;
1419 if (tc == NULL)
1421 assert(tcp_port->tp_snd_head == tcp_conn);
1422 tcp_port->tp_snd_head= tcp_conn->tc_send_link;
1424 else
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 $