Changeset 4c55a64 in mainline


Ignore:
Timestamp:
2011-09-19T21:01:16Z (13 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
0093ab6
Parents:
c5808b41
Message:

Implement some ACK processing and window-size update handling.

Location:
uspace/srv/net/tl/tcp
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/net/tl/tcp/conn.c

    rc5808b41 r4c55a64  
    152152        conn->irs = seg->seq;
    153153
     154
    154155        log_msg(LVL_DEBUG, "rcv_nxt=%u", conn->rcv_nxt);
    155156
     
    161162        conn->snd_nxt = conn->iss;
    162163        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;
    163173
    164174        conn->cstate = st_syn_received;
     
    201211        if ((seg->ctrl & CTL_ACK) != 0) {
    202212                conn->snd_una = seg->ack;
    203                 /* XXX process retransmission queue */
     213                tcp_tqueue_remove_acked(conn);
    204214        }
    205215
     
    240250static cproc_t tcp_conn_seg_proc_rst(tcp_conn_t *conn, tcp_segment_t *seg)
    241251{
     252        /* TODO */
    242253        return cp_continue;
    243254}
     
    245256static cproc_t tcp_conn_seg_proc_sp(tcp_conn_t *conn, tcp_segment_t *seg)
    246257{
     258        /* TODO */
    247259        return cp_continue;
    248260}
     
    250262static cproc_t tcp_conn_seg_proc_syn(tcp_conn_t *conn, tcp_segment_t *seg)
    251263{
     264        /* TODO */
    252265        return cp_continue;
    253266}
     
    259272                log_msg(LVL_WARN, "Segment ACK not acceptable, sending RST.");
    260273                tcp_reply_rst(&conn->ident, seg);
     274                tcp_segment_delete(seg);
     275                return cp_done;
    261276        }
    262277
     
    273288static cproc_t tcp_conn_seg_proc_ack_est(tcp_conn_t *conn, tcp_segment_t *seg)
    274289{
     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
    275311        return cp_continue;
    276312}
     
    278314static cproc_t tcp_conn_seg_proc_ack_fw1(tcp_conn_t *conn, tcp_segment_t *seg)
    279315{
     316        if (tcp_conn_seg_proc_ack_est(conn, seg) == cp_done)
     317                return cp_done;
     318
     319        /* TODO */
    280320        return cp_continue;
    281321}
     
    283323static cproc_t tcp_conn_seg_proc_ack_fw2(tcp_conn_t *conn, tcp_segment_t *seg)
    284324{
     325        if (tcp_conn_seg_proc_ack_est(conn, seg) == cp_done)
     326                return cp_done;
     327
     328        /* TODO */
    285329        return cp_continue;
    286330}
     
    288332static cproc_t tcp_conn_seg_proc_ack_cw(tcp_conn_t *conn, tcp_segment_t *seg)
    289333{
    290         return cp_continue;
     334        /* The same processing as in Established state */
     335        return tcp_conn_seg_proc_ack_est(conn, seg);
    291336}
    292337
    293338static cproc_t tcp_conn_seg_proc_ack_cls(tcp_conn_t *conn, tcp_segment_t *seg)
    294339{
     340        if (tcp_conn_seg_proc_ack_est(conn, seg) == cp_done)
     341                return cp_done;
     342
     343        /* TODO */
    295344        return cp_continue;
    296345}
     
    298347static cproc_t tcp_conn_seg_proc_ack_la(tcp_conn_t *conn, tcp_segment_t *seg)
    299348{
     349        if (tcp_conn_seg_proc_ack_est(conn, seg) == cp_done)
     350                return cp_done;
     351
     352        /* TODO */
    300353        return cp_continue;
    301354}
     
    303356static cproc_t tcp_conn_seg_proc_ack_tw(tcp_conn_t *conn, tcp_segment_t *seg)
    304357{
     358        /* Nothing to do */
    305359        return cp_continue;
    306360}
     
    312366        if ((seg->ctrl & CTL_ACK) == 0) {
    313367                log_msg(LVL_WARN, "Segment has no ACK. Dropping.");
    314                 /* XXX Free segment */
     368                tcp_segment_delete(seg);
    315369                return cp_done;
    316370        }
     
    349403static cproc_t tcp_conn_seg_proc_text(tcp_conn_t *conn, tcp_segment_t *seg)
    350404{
     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 */
    351425        return cp_continue;
    352426}
  • uspace/srv/net/tl/tcp/iqueue.c

    rc5808b41 r4c55a64  
    4040#include <stdlib.h>
    4141#include "iqueue.h"
     42#include "segment.h"
    4243#include "seq_no.h"
    4344#include "tcp_type.h"
     
    8586
    8687                list_remove(&iqe->link);
    87                 /* XXX free segment */
     88                tcp_segment_delete(iqe->seg);
    8889
    8990                link = list_first(&iqueue->list);
  • uspace/srv/net/tl/tcp/segment.c

    rc5808b41 r4c55a64  
    4545}
    4646
     47void tcp_segment_delete(tcp_segment_t *seg)
     48{
     49        free(seg);
     50}
     51
    4752/** Create a control segment. */
    4853tcp_segment_t *tcp_segment_make_ctrl(tcp_control_t ctrl)
  • uspace/srv/net/tl/tcp/segment.h

    rc5808b41 r4c55a64  
    3939
    4040extern tcp_segment_t *tcp_segment_new(void);
     41extern void tcp_segment_delete(tcp_segment_t *);
    4142extern tcp_segment_t *tcp_segment_make_ctrl(tcp_control_t);
    4243extern tcp_segment_t *tcp_segment_make_rst(tcp_segment_t *);
  • uspace/srv/net/tl/tcp/seq_no.c

    rc5808b41 r4c55a64  
    6868}
    6969
     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 */
     75bool 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 */
     94bool 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
    70117/** Determine if segment is ready for processing.
    71118 *
  • uspace/srv/net/tl/tcp/seq_no.h

    rc5808b41 r4c55a64  
    4040
    4141extern bool seq_no_ack_acceptable(tcp_conn_t *, uint32_t);
     42extern bool seq_no_ack_duplicate(tcp_conn_t *, uint32_t);
     43extern bool seq_no_new_wnd_update(tcp_conn_t *, tcp_segment_t *);
    4244extern bool seq_no_segment_acked(tcp_conn_t *, tcp_segment_t *, uint32_t);
    4345extern bool seq_no_syn_acked(tcp_conn_t *);
  • uspace/srv/net/tl/tcp/tcp_type.h

    rc5808b41 r4c55a64  
    148148        /** Segment length in sequence space */
    149149        uint32_t len;
     150        /** Segment window */
     151        uint32_t wnd;
    150152        /** Segment urgent pointer */
    151153        uint32_t up;
  • uspace/srv/net/tl/tcp/tqueue.c

    rc5808b41 r4c55a64  
    6464}
    6565
     66/** Remove ACKed segments from retransmission queue.
     67 *
     68 * This should be called when SND.UNA is updated due to incoming ACK.
     69 */
     70void tcp_tqueue_remove_acked(tcp_conn_t *conn)
     71{
     72        (void) conn;
     73}
     74
    6675void tcp_transmit_segment(tcp_sockpair_t *sp, tcp_segment_t *seg)
    6776{
  • uspace/srv/net/tl/tcp/tqueue.h

    rc5808b41 r4c55a64  
    4141extern void tcp_tqueue_ctrl_seg(tcp_conn_t *, tcp_control_t);
    4242extern void tcp_tqueue_seg(tcp_conn_t *, tcp_segment_t *);
     43extern void tcp_tqueue_remove_acked(tcp_conn_t *);
    4344extern void tcp_transmit_segment(tcp_sockpair_t *, tcp_segment_t *);
    4445extern void tcp_header_setup(tcp_conn_t *, tcp_segment_t *, tcp_header_t *);
Note: See TracChangeset for help on using the changeset viewer.