Changeset 4c55a64 in mainline
- Timestamp:
- 2011-09-19T21:01:16Z (13 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 0093ab6
- Parents:
- c5808b41
- Location:
- uspace/srv/net/tl/tcp
- Files:
-
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/net/tl/tcp/conn.c
rc5808b41 r4c55a64 152 152 conn->irs = seg->seq; 153 153 154 154 155 log_msg(LVL_DEBUG, "rcv_nxt=%u", conn->rcv_nxt); 155 156 … … 161 162 conn->snd_nxt = conn->iss; 162 163 conn->snd_una = conn->iss; 164 165 /* 166 * Surprisingly the spec does not deal with initial window setting. 167 * Set SND.WND = SEG.WND and set SND.WL1 so that next segment 168 * will always be accepted as new window setting. 169 */ 170 conn->snd_wnd = seg->wnd; 171 conn->snd_wl1 = seg->seq; 172 conn->snd_wl2 = seg->seq; 163 173 164 174 conn->cstate = st_syn_received; … … 201 211 if ((seg->ctrl & CTL_ACK) != 0) { 202 212 conn->snd_una = seg->ack; 203 /* XXX process retransmission queue */213 tcp_tqueue_remove_acked(conn); 204 214 } 205 215 … … 240 250 static cproc_t tcp_conn_seg_proc_rst(tcp_conn_t *conn, tcp_segment_t *seg) 241 251 { 252 /* TODO */ 242 253 return cp_continue; 243 254 } … … 245 256 static cproc_t tcp_conn_seg_proc_sp(tcp_conn_t *conn, tcp_segment_t *seg) 246 257 { 258 /* TODO */ 247 259 return cp_continue; 248 260 } … … 250 262 static cproc_t tcp_conn_seg_proc_syn(tcp_conn_t *conn, tcp_segment_t *seg) 251 263 { 264 /* TODO */ 252 265 return cp_continue; 253 266 } … … 259 272 log_msg(LVL_WARN, "Segment ACK not acceptable, sending RST."); 260 273 tcp_reply_rst(&conn->ident, seg); 274 tcp_segment_delete(seg); 275 return cp_done; 261 276 } 262 277 … … 273 288 static cproc_t tcp_conn_seg_proc_ack_est(tcp_conn_t *conn, tcp_segment_t *seg) 274 289 { 290 if (!seq_no_ack_acceptable(conn, seg->ack)) { 291 if (!seq_no_ack_duplicate(conn, seg->ack)) { 292 /* Not acceptable, not duplicate. Send ACK and drop. */ 293 tcp_tqueue_ctrl_seg(conn, CTL_ACK); 294 tcp_segment_delete(seg); 295 return cp_done; 296 } 297 } else { 298 /* Update SND.UNA */ 299 conn->snd_una = seg->ack; 300 301 /* Prune acked segments from retransmission queue */ 302 tcp_tqueue_remove_acked(conn); 303 } 304 305 if (seq_no_new_wnd_update(conn, seg)) { 306 conn->snd_wnd = seg->wnd; 307 conn->snd_wl1 = seg->seq; 308 conn->snd_wl2 = seg->ack; 309 } 310 275 311 return cp_continue; 276 312 } … … 278 314 static cproc_t tcp_conn_seg_proc_ack_fw1(tcp_conn_t *conn, tcp_segment_t *seg) 279 315 { 316 if (tcp_conn_seg_proc_ack_est(conn, seg) == cp_done) 317 return cp_done; 318 319 /* TODO */ 280 320 return cp_continue; 281 321 } … … 283 323 static cproc_t tcp_conn_seg_proc_ack_fw2(tcp_conn_t *conn, tcp_segment_t *seg) 284 324 { 325 if (tcp_conn_seg_proc_ack_est(conn, seg) == cp_done) 326 return cp_done; 327 328 /* TODO */ 285 329 return cp_continue; 286 330 } … … 288 332 static cproc_t tcp_conn_seg_proc_ack_cw(tcp_conn_t *conn, tcp_segment_t *seg) 289 333 { 290 return cp_continue; 334 /* The same processing as in Established state */ 335 return tcp_conn_seg_proc_ack_est(conn, seg); 291 336 } 292 337 293 338 static cproc_t tcp_conn_seg_proc_ack_cls(tcp_conn_t *conn, tcp_segment_t *seg) 294 339 { 340 if (tcp_conn_seg_proc_ack_est(conn, seg) == cp_done) 341 return cp_done; 342 343 /* TODO */ 295 344 return cp_continue; 296 345 } … … 298 347 static cproc_t tcp_conn_seg_proc_ack_la(tcp_conn_t *conn, tcp_segment_t *seg) 299 348 { 349 if (tcp_conn_seg_proc_ack_est(conn, seg) == cp_done) 350 return cp_done; 351 352 /* TODO */ 300 353 return cp_continue; 301 354 } … … 303 356 static cproc_t tcp_conn_seg_proc_ack_tw(tcp_conn_t *conn, tcp_segment_t *seg) 304 357 { 358 /* Nothing to do */ 305 359 return cp_continue; 306 360 } … … 312 366 if ((seg->ctrl & CTL_ACK) == 0) { 313 367 log_msg(LVL_WARN, "Segment has no ACK. Dropping."); 314 /* XXX Free segment */368 tcp_segment_delete(seg); 315 369 return cp_done; 316 370 } … … 349 403 static cproc_t tcp_conn_seg_proc_text(tcp_conn_t *conn, tcp_segment_t *seg) 350 404 { 405 switch (conn->cstate) { 406 case st_established: 407 case st_fin_wait_1: 408 case st_fin_wait_2: 409 /* OK */ 410 break; 411 case st_close_wait: 412 case st_closing: 413 case st_last_ack: 414 case st_time_wait: 415 /* Invalid since FIN has been received. Ignore text. */ 416 return cp_continue; 417 case st_listen: 418 case st_syn_sent: 419 case st_syn_received: 420 case st_closed: 421 assert(false); 422 } 423 424 /* TODO Process segment text */ 351 425 return cp_continue; 352 426 } -
uspace/srv/net/tl/tcp/iqueue.c
rc5808b41 r4c55a64 40 40 #include <stdlib.h> 41 41 #include "iqueue.h" 42 #include "segment.h" 42 43 #include "seq_no.h" 43 44 #include "tcp_type.h" … … 85 86 86 87 list_remove(&iqe->link); 87 /* XXX free segment */88 tcp_segment_delete(iqe->seg); 88 89 89 90 link = list_first(&iqueue->list); -
uspace/srv/net/tl/tcp/segment.c
rc5808b41 r4c55a64 45 45 } 46 46 47 void tcp_segment_delete(tcp_segment_t *seg) 48 { 49 free(seg); 50 } 51 47 52 /** Create a control segment. */ 48 53 tcp_segment_t *tcp_segment_make_ctrl(tcp_control_t ctrl) -
uspace/srv/net/tl/tcp/segment.h
rc5808b41 r4c55a64 39 39 40 40 extern tcp_segment_t *tcp_segment_new(void); 41 extern void tcp_segment_delete(tcp_segment_t *); 41 42 extern tcp_segment_t *tcp_segment_make_ctrl(tcp_control_t); 42 43 extern tcp_segment_t *tcp_segment_make_rst(tcp_segment_t *); -
uspace/srv/net/tl/tcp/seq_no.c
rc5808b41 r4c55a64 68 68 } 69 69 70 /** Determine wheter ack is duplicate. 71 * 72 * ACK is duplicate if it refers to a sequence number that has 73 * aleady been acked (SEG.ACK < SND.UNA). 74 */ 75 bool seq_no_ack_duplicate(tcp_conn_t *conn, uint32_t seg_ack) 76 { 77 uint32_t diff; 78 79 /* 80 * There does not seem to be a three-point comparison 81 * equivalent of SEG.ACK < SND.UNA. Thus we do it 82 * on a best-effort basis, based on the difference. 83 * [-2^31, 0) means less-than, [0, 2^31) means greater-than. 84 */ 85 diff = seg_ack - conn->snd_una; 86 return (diff & (0x1 << 31)) != 0; 87 } 88 89 /** Determine segment has new window update. 90 * 91 * Window update is new if either SND.WL1 < SEG.SEQ or 92 * (SND.WL1 = SEG.SEQ and SND.WL2 <= SEG.ACK). 93 */ 94 bool seq_no_new_wnd_update(tcp_conn_t *conn, tcp_segment_t *seg) 95 { 96 bool n_seq, n_ack; 97 98 assert(seq_no_segment_acceptable(conn, seg)); 99 100 /* 101 * We make use of the fact that the peer should not ACK anything 102 * beyond our send window (we surely haven't sent that yet) 103 * as we should have filtered those acks out. 104 * We use SND.UNA+SND.WND as the third point of comparison. 105 */ 106 107 n_seq = seq_no_lt_le(conn->snd_wl1, seg->seq, 108 conn->snd_una + conn->snd_wnd); 109 110 n_ack = conn->snd_wl1 == seg->seq && 111 seq_no_le_lt(conn->snd_wl2, seg->ack, 112 conn->snd_una + conn->snd_wnd + 1); 113 114 return n_seq || n_ack; 115 } 116 70 117 /** Determine if segment is ready for processing. 71 118 * -
uspace/srv/net/tl/tcp/seq_no.h
rc5808b41 r4c55a64 40 40 41 41 extern bool seq_no_ack_acceptable(tcp_conn_t *, uint32_t); 42 extern bool seq_no_ack_duplicate(tcp_conn_t *, uint32_t); 43 extern bool seq_no_new_wnd_update(tcp_conn_t *, tcp_segment_t *); 42 44 extern bool seq_no_segment_acked(tcp_conn_t *, tcp_segment_t *, uint32_t); 43 45 extern bool seq_no_syn_acked(tcp_conn_t *); -
uspace/srv/net/tl/tcp/tcp_type.h
rc5808b41 r4c55a64 148 148 /** Segment length in sequence space */ 149 149 uint32_t len; 150 /** Segment window */ 151 uint32_t wnd; 150 152 /** Segment urgent pointer */ 151 153 uint32_t up; -
uspace/srv/net/tl/tcp/tqueue.c
rc5808b41 r4c55a64 64 64 } 65 65 66 /** Remove ACKed segments from retransmission queue. 67 * 68 * This should be called when SND.UNA is updated due to incoming ACK. 69 */ 70 void tcp_tqueue_remove_acked(tcp_conn_t *conn) 71 { 72 (void) conn; 73 } 74 66 75 void tcp_transmit_segment(tcp_sockpair_t *sp, tcp_segment_t *seg) 67 76 { -
uspace/srv/net/tl/tcp/tqueue.h
rc5808b41 r4c55a64 41 41 extern void tcp_tqueue_ctrl_seg(tcp_conn_t *, tcp_control_t); 42 42 extern void tcp_tqueue_seg(tcp_conn_t *, tcp_segment_t *); 43 extern void tcp_tqueue_remove_acked(tcp_conn_t *); 43 44 extern void tcp_transmit_segment(tcp_sockpair_t *, tcp_segment_t *); 44 45 extern void tcp_header_setup(tcp_conn_t *, tcp_segment_t *, tcp_header_t *);
Note:
See TracChangeset
for help on using the changeset viewer.