Changeset 7cf7ded in mainline for uspace/srv/net/tl/tcp/tqueue.c


Ignore:
Timestamp:
2011-11-15T23:50:57Z (12 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
4f3f6285
Parents:
8218b6b
Message:

TCP retransmission (WIP). Allow setting timer in timer handler.
Simulate packet drop. Fixes.

File:
1 edited

Legend:

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

    r8218b6b r7cf7ded  
    3636
    3737#include <adt/list.h>
     38#include <errno.h>
     39#include <fibril_synch.h>
    3840#include <byteorder.h>
    3941#include <io/log.h>
     
    5052#include "tcp_type.h"
    5153
    52 void tcp_tqueue_init(tcp_tqueue_t *tqueue, tcp_conn_t *conn)
     54#define RETRANSMIT_TIMEOUT      (2*1000*1000)
     55
     56static void retransmit_timeout_func(void *arg);
     57static void tcp_tqueue_timer_set(tcp_conn_t *conn);
     58static void tcp_tqueue_timer_clear(tcp_conn_t *conn);
     59
     60int tcp_tqueue_init(tcp_tqueue_t *tqueue, tcp_conn_t *conn)
    5361{
    5462        tqueue->conn = conn;
     63        tqueue->timer = fibril_timer_create();
     64        if (tqueue->timer == NULL)
     65                return ENOMEM;
     66
    5567        list_initialize(&tqueue->list);
     68
     69        return EOK;
     70}
     71
     72void tcp_tqueue_fini(tcp_tqueue_t *tqueue)
     73{
     74        if (tqueue->timer != NULL) {
     75                fibril_timer_destroy(tqueue->timer);
     76                tqueue->timer = NULL;
     77        }
    5678}
    5779
     
    92114                }
    93115
     116                tqe->conn = conn;
    94117                tqe->seg = rt_seg;
    95118                list_append(&tqe->link, &conn->retransmit.list);
    96         }
    97 
     119
     120                /* Set retransmission timer */
     121                tcp_tqueue_timer_set(conn);
     122        }
     123
     124        tcp_prepare_transmit_segment(conn, seg);
     125}
     126
     127void tcp_prepare_transmit_segment(tcp_conn_t *conn, tcp_segment_t *seg)
     128{
    98129        /*
    99130         * Always send ACK once we have received SYN, except for RST segments.
     
    105136
    106137        seg->seq = conn->snd_nxt;
    107         seg->wnd = conn->rcv_wnd;
    108 
    109         log_msg(LVL_DEBUG, "SEG.SEQ=%" PRIu32 ", SEG.WND=%" PRIu32,
    110             seg->seq, seg->wnd);
    111 
    112         if ((seg->ctrl & CTL_ACK) != 0)
    113                 seg->ack = conn->rcv_nxt;
    114         else
    115                 seg->ack = 0;
    116 
    117138        conn->snd_nxt += seg->len;
    118139
     
    204225                        tcp_segment_delete(tqe->seg);
    205226                        free(tqe);
     227
     228                        /* Reset retransmission timer */
     229                        tcp_tqueue_timer_set(conn);
    206230                }
    207231
    208232                cur = next;
    209233        }
     234
     235        /* Clear retransmission timer if the queue is empty. */
     236        if (list_empty(&conn->retransmit.list))
     237                tcp_tqueue_timer_clear(conn);
    210238
    211239        /* Possibly transmit more data */
     
    213241}
    214242
     243void tcp_conn_transmit_segment(tcp_conn_t *conn, tcp_segment_t *seg)
     244{
     245        log_msg(LVL_DEBUG, "tcp_conn_transmit_segment(%p, %p)", conn, seg);
     246
     247        seg->wnd = conn->rcv_wnd;
     248
     249        if ((seg->ctrl & CTL_ACK) != 0)
     250                seg->ack = conn->rcv_nxt;
     251        else
     252                seg->ack = 0;
     253
     254        tcp_transmit_segment(&conn->ident, seg);
     255}
     256
    215257void tcp_transmit_segment(tcp_sockpair_t *sp, tcp_segment_t *seg)
    216258{
    217259        log_msg(LVL_DEBUG, "tcp_transmit_segment(%p, %p)", sp, seg);
     260
     261        log_msg(LVL_DEBUG, "SEG.SEQ=%" PRIu32 ", SEG.WND=%" PRIu32,
     262            seg->seq, seg->wnd);
    218263/*
    219264        tcp_pdu_prepare(conn, seg, &data, &len);
    220265        tcp_pdu_transmit(data, len);
    221266*/
    222         //tcp_rqueue_bounce_seg(sp, seg);
    223         tcp_ncsim_bounce_seg(sp, seg);
     267        tcp_rqueue_bounce_seg(sp, seg);
     268//      tcp_ncsim_bounce_seg(sp, seg);
     269}
     270
     271static void retransmit_timeout_func(void *arg)
     272{
     273        tcp_conn_t *conn = (tcp_conn_t *) arg;
     274        tcp_tqueue_entry_t *tqe;
     275        tcp_segment_t *rt_seg;
     276        link_t *link;
     277
     278        log_msg(LVL_DEBUG, "### %s: retransmit_timeout_func(%p)", conn->name, conn);
     279        link = list_first(&conn->retransmit.list);
     280        if (link == NULL) {
     281                log_msg(LVL_DEBUG, "Nothing to retransmit");
     282                return;
     283        }
     284
     285        tqe = list_get_instance(link, tcp_tqueue_entry_t, link);
     286
     287        rt_seg = tcp_segment_dup(tqe->seg);
     288        if (rt_seg == NULL) {
     289                log_msg(LVL_ERROR, "Memory allocation failed.");
     290                /* XXX Handle properly */
     291                return;
     292        }
     293
     294        log_msg(LVL_DEBUG, "### %s: retransmitting segment", conn->name);
     295        tcp_conn_transmit_segment(tqe->conn, rt_seg);
     296
     297        /* Reset retransmission timer */
     298        tcp_tqueue_timer_set(tqe->conn);
     299}
     300
     301/** Set or re-set retransmission timer */
     302static void tcp_tqueue_timer_set(tcp_conn_t *conn)
     303{
     304        log_msg(LVL_DEBUG, "### %s: tcp_tqueue_timer_set()", conn->name);
     305
     306        (void) retransmit_timeout_func;
     307        fibril_timer_set(conn->retransmit.timer, RETRANSMIT_TIMEOUT,
     308            retransmit_timeout_func, (void *) conn);
     309}
     310
     311/** Clear retransmission timer */
     312static void tcp_tqueue_timer_clear(tcp_conn_t *conn)
     313{
     314        log_msg(LVL_DEBUG, "### %s: tcp_tqueue_timer_clear()", conn->name);
     315
     316        fibril_timer_clear(conn->retransmit.timer);
    224317}
    225318
Note: See TracChangeset for help on using the changeset viewer.