コード例 #1
0
ファイル: qofseq.c プロジェクト: britram/qof
static int qfSeqGapValidate(qfSeq_t *qs) {
    int i;
    char *err = NULL;

    for (i = 0; i < QF_SEQGAP_CT; i++) {
        if (qs->gaps[i].a && qs->gaps[i].b) {
            if (qfWrapCompare(qs->gaps[i].b, qs->gaps[i].a) < 1) {
                err = "invalid";
                break;
            }
            if (i && (qfWrapCompare(qs->gaps[i].a, qs->gaps[i-1].b) >= 0)) {
                err = "inverted";
                break;
            }
        }
    }
    
    if (!err) return 1;
    
    fprintf(stderr, "%8s gap at %u in %p (nsn %u):\n", err, i, qs, qs->nsn);
    
    for (i = 0; i < QF_SEQGAP_CT; i++) {
        fprintf(stderr, "\t%u-%u (%u) (%d)\n",
                qs->gaps[i].a,  qs->gaps[i].b,
                qs->gaps[i].b - qs->gaps[i].a,
                i ? (qs->gaps[i-1].b - qs->gaps[i].a) : 0);
    }

    return 0;
}
コード例 #2
0
ファイル: qofack.c プロジェクト: constcast/qof
void qfAckSegment(qfAck_t *qa,
                  uint32_t ack,
                  uint32_t sack,
                  uint32_t oct,
                  uint32_t ms)
{
    if (!qa->fan || qfWrapCompare(ack, qa->fan) > 0) {
        qa->fan = ack;
        qa->fanlms = ms;
    } else if (!oct) {
        qa->dup_ct++;
    }
    
    if (sack && qfWrapCompare(sack, ack) > 0) {
        qa->sel_ct++;
    }
}
コード例 #3
0
ファイル: qofrtt.c プロジェクト: britram/qof
void qfRttSegment(qfRtt_t           *rtt,
                  uint32_t          seq,
                  uint32_t          ack,
                  uint32_t          tsval,
                  uint32_t          tsecr,
                  uint32_t          ms,
                  uint8_t           tcpflags,
                  unsigned          reverse)
{
    qfRttDir_t    *fdir, *rdir;
#if QOF_RTT_DEBUG
    char          *dirname;
#endif
    
    /* select which side we're looking at */
    if (reverse) {
        fdir = &rtt->rev;
        rdir = &rtt->fwd;
#if QOF_RTT_DEBUG
        dirname = "rev";
#endif
    } else {
        fdir = &rtt->fwd;
        rdir = &rtt->rev;
#if QOF_RTT_DEBUG
        dirname = "fwd";
#endif
    }

    if (fdir->ackwait && (tcpflags & YF_TF_ACK) &&
        qfWrapCompare(ack, fdir->tsack) >= 0)
    {
        /* got an ACK we were waiting for */
        fdir->obs_ms = ms - fdir->lms;
        if (qfRttSample(rtt)) {
#if QOF_RTT_DEBUG
            fprintf(stderr, "\ton %3s ack %u for seq %u (%u)\n", dirname,
                    ack, fdir->tsack, ack - fdir->tsack);
#endif
        }
        fdir->ackwait = 0;
        if (tsval) {
            qfRttSetEcrWait(rdir, tsval, ms);
        }
            
    } else if (fdir->ecrwait && qfWrapCompare(tsecr, fdir->tsack) >= 0) {
        /* got a TSECR we were waiting for */
        if ((ms - fdir->lms) > fdir->obs_ms) {
            /* Minimize measured RTT on TSECR samples */
            fdir->obs_ms = ms - fdir->lms;
            if (qfRttSample(rtt)) {
#if QOF_RTT_DEBUG
                fprintf(stderr, "\ton %s ecr %u for val %u (%u)\n", dirname,
                        tsecr, fdir->tsack, tsecr - fdir->tsack);
#endif
            }
        }
        fdir->ecrwait = 0;
        qfRttSetAckWait(rdir, seq, ms);
    } else if (!rdir->ackwait && !rdir->ecrwait) {
        qfRttSetAckWait(rdir, seq, ms);
    }
}
コード例 #4
0
ファイル: qofseq.c プロジェクト: britram/qof
static int qfSeqGapFill(qfSeq_t *qs, uint32_t a, uint32_t b) {
    int i;
    uint32_t rtxoct = 0, nexa, nexb;

    /* Segment might fill multiple gaps, so iterate until
       we've distributed the entire segment */
    while (qfWrapCompare(b, a) > 0) {
        
        /* Seek to the next applicable gap */
        i = 0;
        while ((i < QF_SEQGAP_CT) && !qfSeqGapEmpty(qs->gaps, i) &&
               (qfWrapCompare(a, qs->gaps[i].a)) < 0) i++;
        
        /* If we're off the edge of the gapstack, this is pure RTX. */
        if (i == QF_SEQGAP_CT || qfSeqGapEmpty(qs->gaps, i)) {
            rtxoct += b - a;
            break;
        }
        
        /* Everything greater than the gap is also RTX */
        if (qfWrapCompare(b, qs->gaps[i].b) > 0) {
            if (qfWrapCompare(a, qs->gaps[i].b) > 0) {
                rtxoct += b - a;
                break;
            } else {
                rtxoct += b - qs->gaps[i].b;
                b = qs->gaps[i].b;
            }
        }

        /* Check to see if we'll need to iterate */
        if (qfWrapCompare(a, qs->gaps[i].a) < 0) {
            /* A is less than the gap; prepare to iterate */
            nexa = a;
            nexb = b;
            a = qs->gaps[i].a;
        } else {
            /* A and B within or on gap edge; terminate iteration */
            nexa = 0;
            nexb = 0;
        }

        /* Check for overlap within gap and fill */
        if ((a == qs->gaps[i].a) && (b == qs->gaps[i].b)) {
            /* Completely fill gap */
            qfSeqGapShift(qs->gaps, i);
            break;
        } else if (b == qs->gaps[i].b) {
            /* A within gap, B on edge; fill on the high side */
            qs->gaps[i].b = a;
            break;
        } else if (a == qs->gaps[i].a) {
            /* B within gap, A on edge; fill on the high side */
            qs->gaps[i].a = b;
            break;
        } else {
            /* A and B within gap; split the gap */
            qs->seqlost += qfSeqGapUnshift(qs->gaps, i);
            qs->gaps[i].a = b;
            qs->gaps[i+1].b = a;
        }
        
        /* Modify segment and iterate */
        a = nexa;
        b = nexb;
    }
    
    /* Done. Count retransmit */
    if (rtxoct) {
        qs->rtx++;
        return 1;
    } else {
        return 0;
    }
    
}
コード例 #5
0
ファイル: qofseq.c プロジェクト: britram/qof
int qfSeqSegment(qfSeq_t *qs, qfRtt_t *rtt, uint16_t mss,
                 uint8_t flags, uint32_t seq, uint32_t oct,
                 uint32_t ms, uint32_t tsval,
                 gboolean do_ts, gboolean do_iat) {

    uint32_t lastms = 0;
    
    /* Empty segments don't count */
    if (!oct) return 0;
    
    if (qfWrapCompare(seq, qs->nsn) < 0) {
        /* Sequence less than NSN: fill */
        if (seq - qs->nsn > qs->maxooo) {
            qs->maxooo = seq - qs->nsn;
        }
        if (qfSeqGapFill(qs, seq, seq + oct)) {
            qfCountLoss(qs, rtt, ms);
        }
    } else {
        /* Sequence beyond NSN: push */
        if (seq != qs->nsn) {
            qfSeqGapPush(qs, qs->nsn, seq, mss);

            /* signal loss for burst tracking */
            qfCountLoss(qs, rtt, ms);
            
            /* track max out of order */
            if (seq - qs->nsn > qs->maxooo) {
                qs->maxooo = seq - qs->nsn;
            }
        }
        
        /* Detect wrap */
        if (seq + oct < qs->nsn) {
            qs->wrapct++;
        }
        
        /* Determine next sequence number */
        qs->nsn = seq + oct;
        
        /* track timestamp frequency */
        if (do_ts && tsval) {
            /* increment wrap counters if necessary */
            if (tsval < qs->advtsval) {
                qs->tsvalwrap++;
            }
            if (ms < qs->advlms) {
                qs->lmswrap++;
            }

            /* save current value */
            qs->advtsval = tsval;
        }

        /* and advance time */
        lastms = qs->advlms;
        qs->advlms = ms;

        /* calculate interarrival/interdeparture time of advancing segments */
        if (do_iat) {
            uint32_t iat = 0, idt = 0, hz = 0;
            
            iat = ms - lastms;
            sstMeanAdd(&qs->seg_iat, iat);
            if (do_ts && tsval && (hz = qfTimestampHz(qs))) {
                idt = (1000 * (tsval - qs->advtsval)) / hz;
                sstMeanAdd(&qs->seg_variat, iat - idt);
            }
        }
        
        return 1;
    }
    
    /* if we're here, we didn't advance */
    return 0;
}