Ignore:
File:
1 edited

Legend:

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

    rdc12262 r3e2291a9  
    4444#include <stdlib.h>
    4545#include "conn.h"
     46#include "inet.h"
    4647#include "iqueue.h"
     48#include "pdu.h"
     49#include "rqueue.h"
    4750#include "segment.h"
    4851#include "seq_no.h"
     
    5760#define TIME_WAIT_TIMEOUT       (2*MAX_SEGMENT_LIFETIME)
    5861
     62/** List of all allocated connections */
    5963static LIST_INITIALIZE(conn_list);
    6064/** Taken after tcp_conn_t lock */
    6165static FIBRIL_MUTEX_INITIALIZE(conn_list_lock);
     66/** Connection association map */
    6267static amap_t *amap;
    63 
    64 static void tcp_conn_seg_process(tcp_conn_t *conn, tcp_segment_t *seg);
    65 static void tcp_conn_tw_timer_set(tcp_conn_t *conn);
    66 static void tcp_conn_tw_timer_clear(tcp_conn_t *conn);
     68/** Taken after tcp_conn_t lock */
     69static FIBRIL_MUTEX_INITIALIZE(amap_lock);
     70
     71/** Internal loopback configuration */
     72tcp_lb_t tcp_conn_lb = tcp_lb_none;
     73
     74static void tcp_conn_seg_process(tcp_conn_t *, tcp_segment_t *);
     75static void tcp_conn_tw_timer_set(tcp_conn_t *);
     76static void tcp_conn_tw_timer_clear(tcp_conn_t *);
     77static void tcp_transmit_segment(inet_ep2_t *, tcp_segment_t *);
     78static void tcp_conn_trim_seg_to_wnd(tcp_conn_t *, tcp_segment_t *);
     79static void tcp_reply_rst(inet_ep2_t *, tcp_segment_t *);
     80
     81static tcp_tqueue_cb_t tcp_conn_tqueue_cb = {
     82        .transmit_seg = tcp_transmit_segment
     83};
    6784
    6885/** Initialize connections. */
     
    7895
    7996        return EOK;
     97}
     98
     99/** Finalize connections. */
     100void tcp_conns_fini(void)
     101{
     102        assert(list_empty(&conn_list));
     103
     104        amap_destroy(amap);
     105        amap = NULL;
    80106}
    81107
     
    130156
    131157        /* Initialize retransmission queue */
    132         if (tcp_tqueue_init(&conn->retransmit, conn) != EOK)
     158        if (tcp_tqueue_init(&conn->retransmit, conn, &tcp_conn_tqueue_cb)
     159            != EOK) {
    133160                goto error;
     161        }
    134162
    135163        tqueue_inited = true;
     
    147175        if (epp != NULL)
    148176                conn->ident = *epp;
     177
     178        fibril_mutex_lock(&conn_list_lock);
     179        list_append(&conn->link, &conn_list);
     180        fibril_mutex_unlock(&conn_list_lock);
    149181
    150182        return conn;
     
    181213{
    182214        log_msg(LOG_DEFAULT, LVL_DEBUG, "%s: tcp_conn_free(%p)", conn->name, conn);
     215
     216        assert(conn->mapped == false);
    183217        tcp_tqueue_fini(&conn->retransmit);
     218
     219        fibril_mutex_lock(&conn_list_lock);
     220        list_remove(&conn->link);
     221        fibril_mutex_unlock(&conn_list_lock);
    184222
    185223        if (conn->rcv_buf != NULL)
     
    271309
    272310        tcp_conn_addref(conn);
    273         fibril_mutex_lock(&conn_list_lock);
     311        fibril_mutex_lock(&amap_lock);
    274312
    275313        log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_add: conn=%p", conn);
     
    278316        if (rc != EOK) {
    279317                tcp_conn_delref(conn);
    280                 fibril_mutex_unlock(&conn_list_lock);
     318                fibril_mutex_unlock(&amap_lock);
    281319                return rc;
    282320        }
    283321
    284322        conn->ident = aepp;
    285         list_append(&conn->link, &conn_list);
    286         fibril_mutex_unlock(&conn_list_lock);
     323        conn->mapped = true;
     324        fibril_mutex_unlock(&amap_lock);
    287325
    288326        return EOK;
     
    293331 * Remove connection from the connection map.
    294332 */
    295 void tcp_conn_remove(tcp_conn_t *conn)
    296 {
    297         fibril_mutex_lock(&conn_list_lock);
     333static void tcp_conn_remove(tcp_conn_t *conn)
     334{
     335        if (!conn->mapped)
     336                return;
     337
     338        fibril_mutex_lock(&amap_lock);
    298339        amap_remove(amap, &conn->ident);
    299         list_remove(&conn->link);
    300         fibril_mutex_unlock(&conn_list_lock);
     340        conn->mapped = false;
     341        fibril_mutex_unlock(&amap_lock);
    301342        tcp_conn_delref(conn);
    302343}
     
    335376void tcp_conn_sync(tcp_conn_t *conn)
    336377{
     378        assert(fibril_mutex_is_locked(&conn->lock));
     379
    337380        /* XXX select ISS */
    338381        conn->iss = 1;
     
    388431        log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_find_ref(%p)", epp);
    389432
    390         fibril_mutex_lock(&conn_list_lock);
     433        fibril_mutex_lock(&amap_lock);
    391434
    392435        rc = amap_find_match(amap, epp, &arg);
    393436        if (rc != EOK) {
    394437                assert(rc == ENOENT);
    395                 fibril_mutex_unlock(&conn_list_lock);
     438                fibril_mutex_unlock(&amap_lock);
    396439                return NULL;
    397440        }
     
    400443        tcp_conn_addref(conn);
    401444
    402         fibril_mutex_unlock(&conn_list_lock);
     445        fibril_mutex_unlock(&amap_lock);
    403446        log_msg(LOG_DEFAULT, LVL_DEBUG, "tcp_conn_find_ref: got conn=%p",
    404447            conn);
     
    412455void tcp_conn_reset(tcp_conn_t *conn)
    413456{
     457        assert(fibril_mutex_is_locked(&conn->lock));
     458
    414459        log_msg(LOG_DEFAULT, LVL_DEBUG, "%s: tcp_conn_reset()", conn->name);
     460
     461        if (conn->cstate == st_closed)
     462                return;
     463
    415464        conn->reset = true;
    416465        tcp_conn_state_set(conn, st_closed);
     
    865914                return cp_done;
    866915
    867         /* TODO */
     916        if (conn->fin_is_acked) {
     917                log_msg(LOG_DEFAULT, LVL_DEBUG, "%s: FIN acked -> Time-Wait",
     918                    conn->name);
     919                tcp_conn_state_set(conn, st_time_wait);
     920        }
     921
    868922        return cp_continue;
    869923}
     
    10621116                log_msg(LOG_DEFAULT, LVL_DEBUG, " - FIN found in segment.");
    10631117
     1118                conn->rcv_nxt++;
     1119                conn->rcv_wnd--;
     1120
    10641121                /* Send ACK */
    10651122                tcp_tqueue_ctrl_seg(conn, CTL_ACK);
    1066 
    1067                 conn->rcv_nxt++;
    1068                 conn->rcv_wnd--;
    10691123
    10701124                /* Change connection state */
     
    12111265
    12121266                /* Need to remove and re-insert connection with new identity */
    1213                 fibril_mutex_lock(&conn_list_lock);
     1267                fibril_mutex_lock(&amap_lock);
    12141268
    12151269                if (inet_addr_is_any(&conn->ident.remote.addr))
     
    12271281                        assert(rc == ENOMEM);
    12281282                        log_msg(LOG_DEFAULT, LVL_ERROR, "Out of memory.");
    1229                         fibril_mutex_unlock(&conn_list_lock);
     1283                        fibril_mutex_unlock(&amap_lock);
    12301284                        tcp_conn_unlock(conn);
    12311285                        return;
     
    12331287
    12341288                amap_remove(amap, &oldepp);
    1235                 fibril_mutex_unlock(&conn_list_lock);
     1289                fibril_mutex_unlock(&amap_lock);
    12361290
    12371291                conn->name = (char *) "a";
     
    13221376 * @param seg           Segment
    13231377 */
    1324 void tcp_conn_trim_seg_to_wnd(tcp_conn_t *conn, tcp_segment_t *seg)
     1378static void tcp_conn_trim_seg_to_wnd(tcp_conn_t *conn, tcp_segment_t *seg)
    13251379{
    13261380        uint32_t left, right;
     
    13461400}
    13471401
     1402/** Transmit segment over network.
     1403 *
     1404 * @param epp Endpoint pair with source and destination information
     1405 * @param seg Segment (ownership retained by caller)
     1406 */
     1407static void tcp_transmit_segment(inet_ep2_t *epp, tcp_segment_t *seg)
     1408{
     1409        tcp_pdu_t *pdu;
     1410        tcp_segment_t *dseg;
     1411        inet_ep2_t rident;
     1412
     1413        log_msg(LOG_DEFAULT, LVL_DEBUG,
     1414            "tcp_transmit_segment(l:(%u),f:(%u), %p)",
     1415            epp->local.port, epp->remote.port, seg);
     1416
     1417        log_msg(LOG_DEFAULT, LVL_DEBUG, "SEG.SEQ=%" PRIu32 ", SEG.WND=%" PRIu32,
     1418            seg->seq, seg->wnd);
     1419
     1420        tcp_segment_dump(seg);
     1421
     1422        if (tcp_conn_lb == tcp_lb_segment) {
     1423                /* Loop back segment */
     1424//              tcp_ncsim_bounce_seg(sp, seg);
     1425
     1426                /* Reverse the identification */
     1427                tcp_ep2_flipped(epp, &rident);
     1428
     1429                /* Insert segment back into rqueue */
     1430                dseg = tcp_segment_dup(seg);
     1431                tcp_rqueue_insert_seg(&rident, dseg);
     1432                return;
     1433        }
     1434
     1435        if (tcp_pdu_encode(epp, seg, &pdu) != EOK) {
     1436                log_msg(LOG_DEFAULT, LVL_WARN, "Not enough memory. Segment dropped.");
     1437                return;
     1438        }
     1439
     1440        if (tcp_conn_lb == tcp_lb_pdu) {
     1441                /* Loop back PDU */
     1442                if (tcp_pdu_decode(pdu, &rident, &dseg) != EOK) {
     1443                        log_msg(LOG_DEFAULT, LVL_WARN, "Not enough memory. Segment dropped.");
     1444                        tcp_pdu_delete(pdu);
     1445                        return;
     1446                }
     1447
     1448                tcp_pdu_delete(pdu);
     1449
     1450                /* Insert decoded segment into rqueue */
     1451                tcp_rqueue_insert_seg(&rident, dseg);
     1452                return;
     1453        }
     1454
     1455        tcp_transmit_pdu(pdu);
     1456        tcp_pdu_delete(pdu);
     1457}
     1458
    13481459/** Compute flipped endpoint pair for response.
    13491460 *
     
    13641475 * @param seg           Incoming segment
    13651476 */
    1366 void tcp_reply_rst(inet_ep2_t *epp, tcp_segment_t *seg)
     1477static void tcp_reply_rst(inet_ep2_t *epp, tcp_segment_t *seg)
    13671478{
    13681479        tcp_segment_t *rseg;
Note: See TracChangeset for help on using the changeset viewer.