VirtualBox

Changeset 14275 in vbox for trunk/src/VBox/Devices/Network


Ignore:
Timestamp:
Nov 18, 2008 3:44:28 AM (16 years ago)
Author:
vboxsync
Message:

TCP reassembling (compilable, but not working version)

Location:
trunk/src/VBox/Devices/Network/slirp
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Network/slirp/slirp.h

    r14232 r14275  
    349349
    350350/* tcp_input.c */
     351#ifndef VBOX_WITH_BSD_TCP_REASS
    351352int tcp_reass _P((PNATState, register struct tcpcb *, register struct tcpiphdr *, struct mbuf *));
     353#else /* !VBOX_WITH_BSD_TCP_REASS */
     354int tcp_reass _P((PNATState, struct tcpcb *, struct tcphdr *, int *, struct mbuf *));
     355#endif /* VBOX_WITH_BSD_TCP_REASS */
    352356void tcp_input _P((PNATState, register struct mbuf *, int, struct socket *));
    353357void tcp_dooptions _P((PNATState, struct tcpcb *, u_char *, int, struct tcpiphdr *));
  • trunk/src/VBox/Devices/Network/slirp/slirp_state.h

    r14232 r14275  
    116116    struct tcpstat_t tcpstat;
    117117    uint32_t tcp_now;
     118#ifdef VBOX_WITH_BSD_TCP_REASS
     119    int tcp_reass_qsize;
     120    int tcp_reass_maxqlen;
     121    int tcp_reass_maxseg;
     122    int tcp_reass_overflows;
     123#endif /* VBOX_WITH_BSD_TCP_REASS */
    118124    /* Stuff from tftp.c */
    119125    struct tftp_session tftp_sessions[TFTP_SESSIONS_MAX];
     
    237243#endif /* VBOX_WITH_BSD_REASS */
    238244
     245#ifdef VBOX_WITH_BSD_TCP_REASS
     246#define tcp_reass_qsize pData->tcp_reass_qsize
     247#define tcp_reass_maxqlen pData->tcp_reass_maxqlen
     248#define tcp_reass_maxseg pData->tcp_reass_maxseg
     249#define tcp_reass_overflows pData->tcp_reass_overflows
     250#endif /* VBOX_WITH_BSD_TCP_REASS */
    239251
    240252#if SIZEOF_CHAR_P != 4
  • trunk/src/VBox/Devices/Network/slirp/tcp_input.c

    r14252 r14275  
    5353#define TSTMP_GEQ(a,b)  ((int)((a)-(b)) >= 0)
    5454
     55#ifndef VBOX_WITH_BSD_TCP_REASS
    5556/*
    5657 * Insert segment ti into reassembly queue of tcp with
     
    220221}
    221222
     223#else /* !VBOX_WITH_BSD_TCP_REASS */
     224
     225#ifndef TCP_ACK_HACK
     226#define DELAY_ACK(tp, ti)                           \
     227               if (ti->ti_flags & TH_PUSH)          \
     228                       tp->t_flags |= TF_ACKNOW;    \
     229               else                                 \
     230                       tp->t_flags |= TF_DELACK;
     231#else /* !TCP_ACK_HACK */
     232#define DELAY_ACK(tp, ign)                          \
     233                tp->t_flags |= TF_DELACK;
     234#endif /* TCP_ACK_HACK */
     235
     236
     237/*
     238 * deps: netinet/tcp_reass.c
     239 *          tcp_reass_maxqlen = 48 (deafault)
     240 *          tcp_reass_maxseg  = nmbclusters/16 (nmbclusters = 1024 + maxusers * 64 from kern/kern_mbuf.c let's say 256)
     241 */
     242int
     243tcp_reass(PNATState pData, struct tcpcb *tp, struct tcphdr *th, int *tlenp, struct mbuf *m)
     244{
     245        struct tseg_qent *q;
     246        struct tseg_qent *p = NULL;
     247        struct tseg_qent *nq;
     248        struct tseg_qent *te = NULL;
     249        struct socket *so = tp->t_socket;
     250        int flags;
     251
     252        /*
     253         * XXX: tcp_reass() is rather inefficient with its data structures
     254         * and should be rewritten (see NetBSD for optimizations).  While
     255         * doing that it should move to its own file tcp_reass.c.
     256         */
     257
     258        /*
     259         * Call with th==NULL after become established to
     260         * force pre-ESTABLISHED data up to user socket.
     261         */
     262        if (th == NULL)
     263                goto present;
     264
     265        /*
     266         * Limit the number of segments in the reassembly queue to prevent
     267         * holding on to too many segments (and thus running out of mbufs).
     268         * Make sure to let the missing segment through which caused this
     269         * queue.  Always keep one global queue entry spare to be able to
     270         * process the missing segment.
     271         */
     272        if (th->th_seq != tp->rcv_nxt &&
     273            (tcp_reass_qsize + 1 >= tcp_reass_maxseg ||
     274             tp->t_segqlen >= tcp_reass_maxqlen)) {
     275                tcp_reass_overflows++;
     276                tcpstat.tcps_rcvmemdrop++;
     277                m_freem(pData, m);
     278                *tlenp = 0;
     279                return (0);
     280        }
     281
     282        /*
     283         * Allocate a new queue entry. If we can't, or hit the zone limit
     284         * just drop the pkt.
     285         */
     286        te = malloc(sizeof(struct tseg_qent));
     287        if (te == NULL) {
     288                tcpstat.tcps_rcvmemdrop++;
     289                m_freem(pData, m);
     290                *tlenp = 0;
     291                return (0);
     292        }
     293        tp->t_segqlen++;
     294        tcp_reass_qsize++;
     295
     296        /*
     297         * Find a segment which begins after this one does.
     298         */
     299        LIST_FOREACH(q, &tp->t_segq, tqe_q) {
     300                if (SEQ_GT(q->tqe_th->th_seq, th->th_seq))
     301                        break;
     302                p = q;
     303        }
     304
     305        /*
     306         * If there is a preceding segment, it may provide some of
     307         * our data already.  If so, drop the data from the incoming
     308         * segment.  If it provides all of our data, drop us.
     309         */
     310        if (p != NULL) {
     311                int i;
     312                /* conversion to int (in i) handles seq wraparound */
     313                i = p->tqe_th->th_seq + p->tqe_len - th->th_seq;
     314                if (i > 0) {
     315                        if (i >= *tlenp) {
     316                                tcpstat.tcps_rcvduppack++;
     317                                tcpstat.tcps_rcvdupbyte += *tlenp;
     318                                m_freem(pData, m);
     319                                free(te);
     320                                tp->t_segqlen--;
     321                                tcp_reass_qsize--;
     322                                /*
     323                                 * Try to present any queued data
     324                                 * at the left window edge to the user.
     325                                 * This is needed after the 3-WHS
     326                                 * completes.
     327                                 */
     328                                goto present;   /* ??? */
     329                        }
     330                        m_adj(m, i);
     331                        *tlenp -= i;
     332                        th->th_seq += i;
     333                }
     334        }
     335        tcpstat.tcps_rcvoopack++;
     336        tcpstat.tcps_rcvoobyte += *tlenp;
     337
     338        /*
     339         * While we overlap succeeding segments trim them or,
     340         * if they are completely covered, dequeue them.
     341         */
     342        while (q) {
     343                int i = (th->th_seq + *tlenp) - q->tqe_th->th_seq;
     344                if (i <= 0)
     345                        break;
     346                if (i < q->tqe_len) {
     347                        q->tqe_th->th_seq += i;
     348                        q->tqe_len -= i;
     349                        m_adj(q->tqe_m, i);
     350                        break;
     351                }
     352
     353                nq = LIST_NEXT(q, tqe_q);
     354                LIST_REMOVE(q, tqe_q);
     355                m_freem(pData, q->tqe_m);
     356                free(q);
     357                tp->t_segqlen--;
     358                tcp_reass_qsize--;
     359                q = nq;
     360        }
     361
     362        /* Insert the new segment queue entry into place. */
     363        te->tqe_m = m;
     364        te->tqe_th = th;
     365        te->tqe_len = *tlenp;
     366
     367        if (p == NULL) {
     368                LIST_INSERT_HEAD(&tp->t_segq, te, tqe_q);
     369        } else {
     370                LIST_INSERT_AFTER(p, te, tqe_q);
     371        }
     372
     373present:
     374        /*
     375         * Present data to user, advancing rcv_nxt through
     376         * completed sequence space.
     377         */
     378        if (!TCPS_HAVEESTABLISHED(tp->t_state))
     379                return (0);
     380        q = LIST_FIRST(&tp->t_segq);
     381        if (!q || q->tqe_th->th_seq != tp->rcv_nxt)
     382                return (0);
     383        do {
     384                tp->rcv_nxt += q->tqe_len;
     385                flags = q->tqe_th->th_flags & TH_FIN;
     386                nq = LIST_NEXT(q, tqe_q);
     387                LIST_REMOVE(q, tqe_q);
     388                /* XXX: This place should be checked for the same code in
     389                 * original BSD code for Slirp and current BSD used SS_FCANTRCVMORE
     390                 */
     391                if (so->so_state & SS_FCANTSENDMORE)
     392                        m_freem(pData, q->tqe_m);
     393                else
     394                        sbappend(pData, so, q->tqe_m);
     395                free(q);
     396                tp->t_segqlen--;
     397                tcp_reass_qsize--;
     398                q = nq;
     399        } while (q && q->tqe_th->th_seq == tp->rcv_nxt);
     400        return (flags);
     401}
     402#endif /* VBOX_WITH_BSD_TCP_REASS */
     403
    222404/*
    223405 * TCP input routine, follows pages 65-76 of the
     
    545727                        }
    546728                } else if (ti->ti_ack == tp->snd_una &&
     729#ifndef VBOX_WITH_BSD_TCP_REASS
    547730                    u32_to_ptr(pData, tp->seg_next, struct tcpcb *) == tp &&
     731#else /* !VBOX_WITH_BSD_TCP_REASS */
     732                    LIST_NEXT(tp, t_list) == tp &&
     733#endif /* VBOX_WITH_BSD_TCP_REASS */
    548734                    ti->ti_len <= sbspace(&so->so_rcv)) {
    549735                        /*
     
    774960 *                      }
    775961 */
     962#ifndef VBOX_WITH_BSD_TCP_REASS
    776963                        (void) tcp_reass(pData, tp, (struct tcpiphdr *)0,
    777964                                (struct mbuf *)0);
     965#else /* !VBOX_WITH_BSD_TCP_REASS */
     966                        (void) tcp_reass(pData, tp, (struct tcphdr *)0, NULL, (struct mbuf *)0);
     967#endif /* VBOX_WITH_BSD_TCP_REASS */
    778968                        /*
    779969                         * if we didn't have to retransmit the SYN,
     
    10441234 *              }
    10451235 */
     1236#ifndef VBOX_WITH_BSD_TCP_REASS
    10461237                (void) tcp_reass(pData, tp, (struct tcpiphdr *)0, (struct mbuf *)0);
     1238#else /* !VBOX_WITH_BSD_TCP_REASS */
     1239                (void) tcp_reass(pData, tp, (struct tcpiphdr *)0, (int *)0, (struct mbuf *)0);
     1240#endif /*VBOX_WITH_BSD_TCP_REASS*/
    10471241                tp->snd_wl1 = ti->ti_seq - 1;
    10481242                /* Avoid ack processing; snd_una==ti_ack  =>  dup ack */
     
    13461540        if ((ti->ti_len || (tiflags&TH_FIN)) &&
    13471541            TCPS_HAVERCVDFIN(tp->t_state) == 0) {
     1542#ifndef VBOX_WITH_BSD_TCP_REASS
    13481543                TCP_REASS(pData, tp, ti, m, so, tiflags);
     1544#else /* !VBOX_WITH_BSD_TCP_REASS */
     1545                DELAY_ACK(tp, ti); /* little bit different from BSD declaration see netinet/tcp_input.c */
     1546                tp->rcv_nxt += tlen;
     1547                tiflags = ti->ti_t.th_flags & TH_FIN;
     1548                tcpstat.tcps_rcvpack++;
     1549                tcpstat.tcps_rcvbyte += tlen;
     1550                if (so->so_state & SS_FCANTRCVMORE)
     1551                        m_freem(pData, m);
     1552                else
     1553                        sbappend(pData, so, m);
     1554                /* NB: sorwakeup_locked() does an implicit unlock. */
     1555                sorwakeup(so);
     1556#endif /* VBOX_WITH_BSD_TCP_REASS */
    13491557                /*
    13501558                 * Note the amount of data that peer has sent into
  • trunk/src/VBox/Devices/Network/slirp/tcp_subr.c

    r14180 r14275  
    189189
    190190        memset((char *) tp, 0, sizeof(struct tcpcb));
     191#ifndef VBOX_WITH_BSD_TCP_REASS
    191192        tp->seg_next = tp->seg_prev = ptr_to_u32(pData, (struct tcpiphdr *)tp);
     193#else /* !VBOX_WITH_BSD_TCP_REASS */
     194        /*XXX: inject initialization here*/
     195#endif /* VBOX_WITH_BSD_TCP_REASS */
    192196        tp->t_maxseg = tcp_mssdflt;
    193197
     
    263267        DEBUG_ARG("tp = %lx", (long )tp);
    264268
     269#ifndef VBOX_WITH_BSD_TCP_REASS
    265270        /* free the reassembly queue, if any */
    266271        t = u32_to_ptr(pData, tp->seg_next, struct tcpiphdr *);
     
    271276                m_freem(pData, m);
    272277        }
     278#else /* !VBOX_WITH_BSD_TCP_REASS */
     279        /*XXX: freeing the reassembly queue */
     280#endif /* VBOX_WITH_BSD_TCP_REASS */
    273281        /* It's static */
    274282/*      if (tp->t_template)
  • trunk/src/VBox/Devices/Network/slirp/tcp_var.h

    r1076 r14275  
    3838#define _TCP_VAR_H_
    3939
     40#ifdef VBOX_WITH_BSD_TCP_REASS
     41#include <sys/queue.h>
     42#endif /* VBOX_WITH_BSD_TCP_REASS */
     43
    4044#include "tcpip.h"
    4145#include "tcp_timer.h"
     
    5761#endif
    5862
     63#ifdef VBOX_WITH_BSD_TCP_REASS
     64/* TCP segment queue entry */
     65struct tseg_qent {
     66        LIST_ENTRY(tseg_qent) tqe_q;
     67        int     tqe_len;                /* TCP segment data length */
     68        struct  tcphdr *tqe_th;         /* a pointer to tcp header */
     69        struct  mbuf    *tqe_m;         /* mbuf contains packet */
     70};
     71LIST_HEAD(tsegqe_head, tseg_qent);
     72#endif
     73
    5974/*
    6075 * Tcp control block, one per tcp; fields:
    6176 */
    6277struct tcpcb {
     78#ifndef VBOX_WITH_BSD_TCP_REASS
    6379        tcpiphdrp_32 seg_next;  /* sequencing queue */
    6480        tcpiphdrp_32 seg_prev;
     81#else /* !VBOX_WITH_BSD_TCP_REASS */
     82        LIST_ENTRY(tcpcb) t_list;
     83        struct  tsegqe_head t_segq;     /* segment reassembly queue */
     84        int     t_segqlen;              /* segment reassembly queue length */
     85#endif /* VBOX_WITH_BSD_TCP_REASS */
    6586        short   t_state;                /* state of this connection */
    6687        short   t_timer[TCPT_NTIMERS];  /* tcp timers */
     
    148169
    149170};
     171
     172#ifdef VBOX_WITH_BSD_TCP_REASS
     173LIST_HEAD(tcpcbhead, tcpcb);
     174#endif /*VBOX_WITH_BSD_TCP_REASS*/
    150175
    151176#define sototcpcb(so)   ((so)->so_tcpcb)
     
    261286        u_long  tcps_socachemiss;       /* tcp_last_so misses */
    262287        u_long  tcps_didnuttin;         /* Times tcp_output didn't do anything XXX */
     288#ifdef VBOX_WITH_BSD_TCP_REASS
     289        u_long tcps_rcvmemdrop;
     290#endif /* VBOX_WITH_BSD_TCP_REASS */
    263291};
    264292
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette