//-------------------------------------------------------------------- void Stat(Double *p, Int n, Statistics *s) { // Statistics: min, max, ave, var s->ave = Mean(p,n); s->dev = Stdev(p,n); //qsort((void*)p, n, sizeof(Double),(int(*)(void*,void*))Cmp_Double); qsort((void*)p, n, sizeof(Double), Cmp_Double); s->min = p[0]; s->max = p[n-1]; } // end Statistics
void PrintTrace( tcp_pair *ptp) { double etime; u_long etime_secs; u_long etime_usecs; double etime_data1; double etime_data2; tcb *pab = &ptp->a2b; tcb *pba = &ptp->b2a; char *host1 = pab->host_letter; char *host2 = pba->host_letter; char bufl[40],bufr[40]; /* counters to use for seq. space wrap around calculations */ u_llong stream_length_pab=0, stream_length_pba=0; u_long pab_last, pba_last; /* Reset the counter for each connection */ sv_print_count = 1; /* The first field (conn_#) gets printed in trace.c */ /* calculate elapsed time */ etime = elapsed(ptp->first_time,ptp->last_time); etime_secs = etime / 1000000.0; etime_usecs = 1000000 * (etime/1000000.0 - (double)etime_secs); /* Check if comma-separated-values or tab-separated-values * has been requested. */ if(csv || tsv || (sv != NULL)) { fprintf(stdout,"%s%s%s%s%s%s%s%s", ptp->a_hostname, sp, ptp->b_hostname, sp, ptp->a_portname, sp, ptp->b_portname, sp); sv_print_count += 4; /* Print the start and end times. In other words, * print the time of the first and the last packet */ fprintf(stdout,"%ld.%ld %s %ld.%ld %s", (long)ptp->first_time.tv_sec, (long)ptp->first_time.tv_usec, sp, (long)ptp->last_time.tv_sec, (long)ptp->last_time.tv_usec, sp); sv_print_count += 2; } else { fprintf(stdout,"\thost %-4s %s\n", (snprintf(bufl,sizeof(bufl),"%s:", host1),bufl), ptp->a_endpoint); fprintf(stdout,"\thost %-4s %s\n", (snprintf(bufl,sizeof(bufl),"%s:", host2),bufl), ptp->b_endpoint); fprintf(stdout,"\tcomplete conn: %s", ConnReset(ptp)?"RESET":( ConnComplete(ptp)?"yes":"no")); if (ConnComplete(ptp)) fprintf(stdout,"\n"); else fprintf(stdout,"\t(SYNs: %u) (FINs: %u)\n", SynCount(ptp), FinCount(ptp)); fprintf(stdout,"\tfirst packet: %s\n", ts2ascii(&ptp->first_time)); fprintf(stdout,"\tlast packet: %s\n", ts2ascii(&ptp->last_time)); fprintf(stdout,"\telapsed time: %s\n", elapsed2str(etime)); fprintf(stdout,"\ttotal packets: %" FS_ULL "\n", ptp->packets); fprintf(stdout,"\tfilename: %s\n", ptp->filename); fprintf(stdout," %s->%s: %s->%s:\n", host1,host2,host2,host1); } StatLineI("total packets","", pab->packets, pba->packets); if (pab->reset_count || pba->reset_count || csv || tsv || (sv != NULL)) StatLineI("resets sent","", pab->reset_count, pba->reset_count); StatLineI("ack pkts sent","", pab->ack_pkts, pba->ack_pkts); StatLineI("pure acks sent","", pab->pureack_pkts, pba->pureack_pkts); StatLineI("sack pkts sent","", pab->num_sacks, pba->num_sacks); StatLineI("dsack pkts sent","", pab->num_dsacks, pba->num_dsacks); StatLineI("max sack blks/ack","", pab->max_sack_blocks, pba->max_sack_blocks); StatLineI("unique bytes sent","", pab->unique_bytes, pba->unique_bytes); StatLineI("actual data pkts","", pab->data_pkts, pba->data_pkts); StatLineI("actual data bytes","", pab->data_bytes, pba->data_bytes); StatLineI("rexmt data pkts","", pab->rexmit_pkts, pba->rexmit_pkts); StatLineI("rexmt data bytes","", pab->rexmit_bytes, pba->rexmit_bytes); StatLineI("zwnd probe pkts","", pab->num_zwnd_probes, pba->num_zwnd_probes); StatLineI("zwnd probe bytes","", pab->zwnd_probe_bytes, pba->zwnd_probe_bytes); StatLineI("outoforder pkts","", pab->out_order_pkts, pba->out_order_pkts); StatLineI("pushed data pkts","", pab->data_pkts_push, pba->data_pkts_push); StatLineP("SYN/FIN pkts sent","","%s", (snprintf(bufl,sizeof(bufl),"%d/%d", pab->syn_count, pab->fin_count),bufl), (snprintf(bufr,sizeof(bufr),"%d/%d", pba->syn_count, pba->fin_count),bufr)); if (pab->f1323_ws || pba->f1323_ws || pab->f1323_ts || pba->f1323_ts || csv || tsv || (sv != NULL)) { StatLineP("req 1323 ws/ts","","%s", (snprintf(bufl,sizeof(bufl),"%c/%c", pab->f1323_ws?'Y':'N',pab->f1323_ts?'Y':'N'),bufl), (snprintf(bufr,sizeof(bufr),"%c/%c", pba->f1323_ws?'Y':'N',pba->f1323_ts?'Y':'N'),bufr)); } if (pab->f1323_ws || pba->f1323_ws || csv || tsv || (sv != NULL)) { StatLineI("adv wind scale","", (u_long)pab->window_scale, (u_long)pba->window_scale); } if (pab->fsack_req || pba->fsack_req || csv || tsv || (sv != NULL)) { StatLineP("req sack","","%s", pab->fsack_req?"Y":"N", pba->fsack_req?"Y":"N"); StatLineI("sacks sent","", pab->sacks_sent, pba->sacks_sent); } StatLineI("urgent data pkts", "pkts", pab->urg_data_pkts, pba->urg_data_pkts); StatLineI("urgent data bytes", "bytes", pab->urg_data_bytes, pba->urg_data_bytes); StatLineI("mss requested","bytes", pab->mss, pba->mss); StatLineI("max segm size","bytes", pab->max_seg_size, pba->max_seg_size); StatLineI("min segm size","bytes", pab->min_seg_size, pba->min_seg_size); StatLineI("avg segm size","bytes", (int)((double)pab->data_bytes / ((double)pab->data_pkts+.001)), (int)((double)pba->data_bytes / ((double)pba->data_pkts+.001))); StatLineI("max win adv","bytes", pab->win_max, pba->win_max); StatLineI("min win adv","bytes", pab->win_min, pba->win_min); StatLineI("zero win adv","times", pab->win_zero_ct, pba->win_zero_ct); // Average window advertisement is calculated only for window scaled pkts // if we have seen this connection using window scaling. // Otherwise, it is just the regular way of dividing the sum of // all window advertisements by the total number of packets. if (pab->window_stats_updated_for_scaling && pba->window_stats_updated_for_scaling) StatLineI("avg win adv","bytes", pab->win_scaled_pkts==0?0: (pab->win_tot/pab->win_scaled_pkts), pba->win_scaled_pkts==0?0: (pba->win_tot/pba->win_scaled_pkts)); else StatLineI("avg win adv","bytes", pab->packets==0?0:pab->win_tot/pab->packets, pba->packets==0?0:pba->win_tot/pba->packets); if (print_owin) { StatLineI("max owin","bytes", pab->owin_max, pba->owin_max); StatLineI("min non-zero owin","bytes", pab->owin_min, pba->owin_min); StatLineI("avg owin","bytes", pab->owin_count==0?0:pab->owin_tot/pab->owin_count, pba->owin_count==0?0:pba->owin_tot/pba->owin_count); if (etime == 0.0) { StatLineP("wavg owin", "", "%s", "NA", "NA"); } else { StatLineI("wavg owin","bytes", (u_llong)(pab->owin_wavg/((double)etime/1000000)), (u_llong)(pba->owin_wavg/((double)etime/1000000))); } } StatLineI("initial window","bytes", pab->initialwin_bytes, pba->initialwin_bytes); StatLineI("initial window","pkts", pab->initialwin_segs, pba->initialwin_segs); /* compare to theoretical length of the stream (not just what we saw) using the SYN and FIN * Seq. Space wrap around calculations: * Calculate stream length using last_seq_num seen, first_seq_num * seen and wrap_count. * first_seq_num = syn * If reset_set, last_seq_num = latest_seq * else last_seq_num = fin */ pab_last = (pab->reset_count>0)?pab->latest_seq:pab->fin; pba_last = (pba->reset_count>0)?pba->latest_seq:pba->fin; /* calculating stream length for direction pab */ if ((pab->syn_count > 0) && (pab->fin_count > 0)) { if (pab->seq_wrap_count > 0) { if (pab_last > pab->syn) { stream_length_pab = pab_last + (MAX_32 * pab->seq_wrap_count) - pab->syn - 1; } else { stream_length_pab = pab_last + (MAX_32 * (pab->seq_wrap_count+1)) - pab->syn - 1; } } else { if (pab_last > pab->syn) { stream_length_pab = pab_last - pab->syn - 1; } else { stream_length_pab = MAX_32 + pab_last - pab->syn - 1; } } } /* calculating stream length for direction pba */ if ((pba->syn_count > 0) && (pba->fin_count > 0)) { if (pba->seq_wrap_count > 0) { if (pba_last > pba->syn) { stream_length_pba = pba_last + (MAX_32 * pba->seq_wrap_count) - pba->syn - 1; } else { stream_length_pba = pba_last + (MAX_32 * (pba->seq_wrap_count+1)) - pba->syn - 1; } } else { if (pba_last > pba->syn) { stream_length_pba = pba_last - pba->syn - 1; } else { stream_length_pba = MAX_32 + pba_last - pba->syn - 1; } } } /* print out values */ if ((pab->fin_count > 0) && (pab->syn_count > 0)) { char *format = "%8" FS_ULL; StatLineFieldL("ttl stream length", "bytes", format, stream_length_pab, 0); } else { StatLineField("ttl stream length", "", "%s", (u_long)"NA", 0); } if ((pba->fin_count > 0) && (pba->syn_count > 0)) { char *format = "%8" FS_ULL; StatLineFieldL("ttl stream length", "bytes", format, stream_length_pba, 1); } else { StatLineField("ttl stream length", "", "%s", (u_long)"NA", 1); } if ((pab->fin_count > 0) && (pab->syn_count > 0)) { char *format = "%8" FS_ULL; StatLineFieldL("missed data", "bytes", format, (stream_length_pab - pab->unique_bytes), 0); } else { StatLineField("missed data", "", "%s", (u_long)"NA", 0); } if ((pba->fin_count > 0) && (pba->syn_count > 0)) { char *format = "%8" FS_ULL; StatLineFieldL("missed data", "bytes", format, (stream_length_pba - pba->unique_bytes), 1); } else { StatLineField("missed data", "", "%s", (u_long)"NA", 1); } /* tell how much data was NOT captured in the files */ StatLineI("truncated data","bytes", pab->trunc_bytes, pba->trunc_bytes); StatLineI("truncated packets","pkts", pab->trunc_segs, pba->trunc_segs); /* stats on just the data */ etime_data1 = elapsed(pab->first_data_time, pab->last_data_time); /* in usecs */ etime_data2 = elapsed(pba->first_data_time, pba->last_data_time); /* in usecs */ /* fix from Rob Austein */ StatLineF("data xmit time","secs","%7.3f", etime_data1 / 1000000.0, etime_data2 / 1000000.0); StatLineP("idletime max","ms","%s", ZERO_TIME(&pab->last_time)?"NA": (snprintf(bufl,sizeof(bufl),"%8.1f",(double)pab->idle_max/1000.0),bufl), ZERO_TIME(&pba->last_time)?"NA": (snprintf(bufr,sizeof(bufr),"%8.1f",(double)pba->idle_max/1000.0),bufr)); if ((pab->num_hardware_dups != 0) || (pba->num_hardware_dups != 0) || csv || tsv || (sv != NULL)) { StatLineI("hardware dups","segs", pab->num_hardware_dups, pba->num_hardware_dups); if(!(csv || tsv || (sv != NULL))) fprintf(stdout, " ** WARNING: presence of hardware duplicates makes these figures suspect!\n"); } /* do the throughput calcs */ etime /= 1000000.0; /* convert to seconds */ if (etime == 0.0) StatLineP("throughput","","%s","NA","NA"); else StatLineF("throughput","Bps","%8.0f", (double) (pab->unique_bytes) / etime, (double) (pba->unique_bytes) / etime); if (print_rtt) { if(!(csv || tsv || (sv != NULL))) fprintf(stdout,"\n"); StatLineI("RTT samples","", pab->rtt_count, pba->rtt_count); StatLineF("RTT min","ms","%8.1f", (double)pab->rtt_min/1000.0, (double)pba->rtt_min/1000.0); StatLineF("RTT max","ms","%8.1f", (double)pab->rtt_max/1000.0, (double)pba->rtt_max/1000.0); StatLineF("RTT avg","ms","%8.1f", Average(pab->rtt_sum, pab->rtt_count) / 1000.0, Average(pba->rtt_sum, pba->rtt_count) / 1000.0); StatLineF("RTT stdev","ms","%8.1f", Stdev(pab->rtt_sum, pab->rtt_sum2, pab->rtt_count) / 1000.0, Stdev(pba->rtt_sum, pba->rtt_sum2, pba->rtt_count) / 1000.0); if(!(csv || tsv || (sv != NULL))) fprintf(stdout,"\n"); StatLineF("RTT from 3WHS","ms","%8.1f", (double)pab->rtt_3WHS/1000.0, (double)pba->rtt_3WHS/1000.0); if(!(csv || tsv || (sv != NULL))) fprintf(stdout,"\n"); StatLineI("RTT full_sz smpls","", pab->rtt_full_count, pba->rtt_full_count); StatLineF("RTT full_sz min","ms","%8.1f", (double)pab->rtt_full_min/1000.0, (double)pba->rtt_full_min/1000.0); StatLineF("RTT full_sz max","ms","%8.1f", (double)pab->rtt_full_max/1000.0, (double)pba->rtt_full_max/1000.0); StatLineF("RTT full_sz avg","ms","%8.1f", Average(pab->rtt_full_sum, pab->rtt_full_count) / 1000.0, Average(pba->rtt_full_sum, pba->rtt_full_count) / 1000.0); StatLineF("RTT full_sz stdev","ms","%8.1f", Stdev(pab->rtt_full_sum, pab->rtt_full_sum2, pab->rtt_full_count) / 1000.0, Stdev(pba->rtt_full_sum, pba->rtt_full_sum2, pba->rtt_full_count) / 1000.0); if(!(csv || tsv || (sv != NULL))) fprintf(stdout,"\n"); StatLineI("post-loss acks","", pab->rtt_nosample, pba->rtt_nosample); if (pab->rtt_amback || pba->rtt_amback || csv || tsv || (sv != NULL)) { if(!(csv || tsv || (sv != NULL))) fprintf(stdout, "\ \t For the following 5 RTT statistics, only ACKs for\n\ \t multiply-transmitted segments (ambiguous ACKs) were\n\ \t considered. Times are taken from the last instance\n\ \t of a segment.\n\ "); StatLineI("ambiguous acks","", pab->rtt_amback, pba->rtt_amback); StatLineF("RTT min (last)","ms","%8.1f", (double)pab->rtt_min_last/1000.0, (double)pba->rtt_min_last/1000.0); StatLineF("RTT max (last)","ms","%8.1f", (double)pab->rtt_max_last/1000.0, (double)pba->rtt_max_last/1000.0); StatLineF("RTT avg (last)","ms","%8.1f", Average(pab->rtt_sum_last, pab->rtt_count_last) / 1000.0, Average(pba->rtt_sum_last, pba->rtt_count_last) / 1000.0); StatLineF("RTT sdv (last)","ms","%8.1f", Stdev(pab->rtt_sum_last, pab->rtt_sum2_last, pab->rtt_count_last) / 1000.0, Stdev(pba->rtt_sum_last, pba->rtt_sum2_last, pba->rtt_count_last) / 1000.0); } StatLineI("segs cum acked","", pab->rtt_cumack, pba->rtt_cumack); StatLineI("duplicate acks","", pab->rtt_dupack, pba->rtt_dupack); StatLineI("triple dupacks","", pab->rtt_triple_dupack, pba->rtt_triple_dupack); if (debug) StatLineI("unknown acks:","", pab->rtt_unkack, pba->rtt_unkack); StatLineI("max # retrans","", pab->retr_max, pba->retr_max); StatLineF("min retr time","ms","%8.1f", (double)((double)pab->retr_min_tm/1000.0), (double)((double)pba->retr_min_tm/1000.0)); StatLineF("max retr time","ms","%8.1f", (double)((double)pab->retr_max_tm/1000.0), (double)((double)pba->retr_max_tm/1000.0)); StatLineF("avg retr time","ms","%8.1f", Average(pab->retr_tm_sum, pab->retr_tm_count) / 1000.0, Average(pba->retr_tm_sum, pba->retr_tm_count) / 1000.0); StatLineF("sdv retr time","ms","%8.1f", Stdev(pab->retr_tm_sum, pab->retr_tm_sum2, pab->retr_tm_count) / 1000.0, Stdev(pba->retr_tm_sum, pba->retr_tm_sum2, pba->retr_tm_count) / 1000.0); } if(csv || tsv || (sv != NULL)) { printf("\n"); /* Error checking: print an error message if the count of printed fields * doesn't correspond to the actual fields expected. */ if(sv_print_count != sv_expected_count) { fprintf(stderr, "output.c: Count of printed fields does not correspond to count of header fields for long output with comma/tab/<SP>-separated values.\n"); fprintf(stderr,"sv_print_count=%u, sv_expected_count=%u\n", sv_print_count, sv_expected_count); exit(-1); } } }
void rules_test (tcb * thisdir, segment * pseg, seglen len, quadrant * pquad, u_short this_ip_id, Bool pkt_already_seen, double recovery_time) { double DeltaT2, RTO, Mean_RTT, RTT_min; char type_of_segment = real_rules_test (thisdir, pseg, len, pquad, this_ip_id, pkt_already_seen, &recovery_time); tcb *otherdir; int dir, num_acked; #ifdef LOG_OOO extern FILE *fp_dup_ooo_log; #endif if (pkt_already_seen) { pseg->type_of_segment = type_of_segment; num_acked = (pseg->prev != NULL) ? pseg->prev->acked : 0; } else { pseg->prev->type_of_segment = type_of_segment; num_acked = (pseg->prev->prev != NULL) ? pseg->prev->prev->acked : 0; } /* LM added */ dir = (&(thisdir->ptp->c2s)) == thisdir; otherdir = (dir == C2S) ? &(thisdir->ptp->s2c) : &(thisdir->ptp->c2s); DeltaT2 = time2double (current_time) - time2double (pquad->seglist_tail->time); Mean_RTT = Average (thisdir->rtt_sum, thisdir->rtt_count) + Average (otherdir->rtt_sum, otherdir->rtt_count); RTO = Mean_RTT + 4 * (Stdev (thisdir->rtt_sum + otherdir->rtt_sum, thisdir->rtt_sum2 + otherdir->rtt_sum2, thisdir->rtt_count + otherdir->rtt_count)); RTT_min = (double) (thisdir->rtt_min + otherdir->rtt_min); #ifdef LOG_OOO if (type_of_segment != 0) { wfprintf (fp_dup_ooo_log, "T: %f ", (elapsed (first_packet, current_time) / 1000.0)); if (dir == C2S) { wfprintf (fp_dup_ooo_log, "%s %s ", HostName (thisdir->ptp->addr_pair.a_address), ServiceName (thisdir->ptp->addr_pair.a_port)); wfprintf (fp_dup_ooo_log, "%s %s ", HostName (thisdir->ptp->addr_pair.b_address), ServiceName (thisdir->ptp->addr_pair.b_port)); } else { wfprintf (fp_dup_ooo_log, "%s %s ", HostName (thisdir->ptp->addr_pair.b_address), ServiceName (thisdir->ptp->addr_pair.b_port)); wfprintf (fp_dup_ooo_log, "%s %s ", HostName (thisdir->ptp->addr_pair.a_address), ServiceName (thisdir->ptp->addr_pair.a_port)); } wfprintf (fp_dup_ooo_log, "%lu %lu %d %d %u %d %u %d %lf %lf %lu %lf %lf %lf %d", thisdir->data_pkts, thisdir->data_bytes, (type_of_segment & 15), thisdir->fsack_req && otherdir->fsack_req, thisdir->mss, (dir == C2S), (internal_dst), thisdir->initialwin_bytes, recovery_time / 1000.0, DeltaT2 / 1000.0, len, RTO / 1000.0, RTT_min / 1000.0, Mean_RTT / 1000.0, num_acked); wfprintf (fp_dup_ooo_log, " %f %f %f %f\n", thisdir->srtt / 1000.0, thisdir->rttvar / 1000.0, otherdir->srtt / 1000.0, otherdir->rttvar / 1000.0); } #endif if (internal_src && !internal_dst) { add_histo (tcp_anomalies_out, aggregateType (type_of_segment)); } else if (!internal_src && internal_dst) { add_histo (tcp_anomalies_in, aggregateType (type_of_segment)); } #ifndef LOG_UNKNOWN else if (internal_src && internal_dst) #else else #endif { add_histo (tcp_anomalies_loc, aggregateType (type_of_segment)); } if (dir == C2S) { add_histo (tcp_anomalies_c2s, aggregateType (type_of_segment)); } else { add_histo (tcp_anomalies_s2c, aggregateType (type_of_segment)); } /* just keep the main classification and discard bit larger than BATCH_CLASSIFICATION*/ switch (type_of_segment & (BATCH_CLASSIFICATION - 1)) { case IN_SEQUENCE: /* just ignore them */ break; case RETRANSMISSION_RTO: thisdir->rtx_RTO++; break; case RETRANSMISSION_FR: thisdir->rtx_FR++; break; case REORDERING: thisdir->reordering++; break; case NETWORK_DUPLICATE: thisdir->net_dup++; break; case FLOW_CONTROL: thisdir->flow_control++; break; case UNNECESSARY_RETRANSMISSION_FR: thisdir->unnecessary_rtx_FR++; break; case UNNECESSARY_RETRANSMISSION_RTO: thisdir->unnecessary_rtx_RTO++; break; default: thisdir->unknown++; } }
/* LM start - Rule number one ** R1.a IP_id_new not equal to IP_id_old ** R1.b this_seg_time-prev_seg_time > ** R1.c number of acks > 3 (or max number permitted) ** DeltaT1: Time between current segment and the last segment before a ooo ** DeltaT2: Time between current segment and the received segment with the maximum sequence number */ char real_rules_test (tcb * thisdir, segment * pseg, seglen len, quadrant * pquad, u_short this_ip_id, Bool pkt_already_seen, double *recovery_time) { double RTO, RTT, Mean_RTT; int Rule1a, Rule1b, Rule1d; int Rule2b, Rule2c; int RuleProbing; tcb *otherdir; char prev_tos; int validRTT; int dir = (&(thisdir->ptp->c2s) == thisdir); otherdir = (dir == C2S) ? &(thisdir->ptp->s2c) : &(thisdir->ptp->c2s); Mean_RTT = Average (thisdir->rtt_sum, thisdir->rtt_count) + Average (otherdir->rtt_sum, otherdir->rtt_count); RTO = Mean_RTT + 4 * (Stdev (thisdir->rtt_sum + otherdir->rtt_sum, thisdir->rtt_sum2 + otherdir->rtt_sum2, thisdir->rtt_count + otherdir->rtt_count)); RTT = (double) (thisdir->rtt_min + otherdir->rtt_min); validRTT = (thisdir->rtt_count != 0 && otherdir->rtt_count != 0); if (RTO < RTO_MIN) RTO = RTO_MIN; if (RTT < RTT_MIN) RTT = RTT_MIN; if (!pkt_already_seen) /* if pkt_already_seen then *recovery_time is passed otherwise it is set below */ *recovery_time = (pseg->prev->prev != NULL) ? time2double (current_time) - time2double (pseg->prev->prev->time) : -1.0; /* take the previous packet classification */ if (pseg->prev != NULL) { if (pkt_already_seen) prev_tos = pseg->prev->type_of_segment; else prev_tos = (pseg->prev->prev != NULL) ? pseg->prev->prev->type_of_segment : IN_SEQUENCE; } else prev_tos = IN_SEQUENCE; if (!validRTT) { RTT = INITIAL_RTT_MIN; RTO = INITIAL_RTO; /* if *recovery_time is -1 then this is the first packet and use next segment as recovery time */ if (*recovery_time == -1.0) *recovery_time = time2double (current_time) - time2double (pseg->time); } Rule1a = (pseg->ip_id != this_ip_id); Rule1b = (*recovery_time > RTO); Rule1d = (*recovery_time < Mean_RTT); if (pkt_already_seen) Rule2b = (pseg->prev != NULL) ? (pseg->prev->acked > 3 && *recovery_time < RTO) : 0; else Rule2b = (pseg->prev->prev != NULL) ? (pseg->prev->prev->acked > 3 && *recovery_time < RTO) : 0; Rule2c = (time2double (current_time) - time2double (pseg->time) < RTT); RuleProbing = ((len == 1) && (otherdir->win_curr == 0) && (thisdir->syn_count != 0) && (otherdir->syn_count != 0)); if (RuleProbing) return FLOW_CONTROL; if (Rule1d && prev_tos != IN_SEQUENCE) return (prev_tos | BATCH_CLASSIFICATION); /* Old Classification with the first bit is 1 */ if (!pseg->acked) { if (pkt_already_seen) { if (!Rule1a) return CLASSIFICATION (NETWORK_DUPLICATE); if (Rule1a && (Rule1b || Rule2b)) return CLASSIFICATION (Rule2b ? RETRANSMISSION_FR : RETRANSMISSION_RTO); if (Rule1d) return CLASSIFICATION (DUPLICATE_WITH_RC_LESS_THAN_RTT_NOT_3DUP_ACK); if (!Rule1b) return CLASSIFICATION (DUPLICATE_WITH_RC_LESS_THAN_RTO_AND_GREATER_THAN_RTT_NOT_3DUP_ACK); return CLASSIFICATION (UNKNOWN); } if (Rule1b || Rule2b) return CLASSIFICATION (Rule2b ? RETRANSMISSION_FR : RETRANSMISSION_RTO); if (Rule2c) return CLASSIFICATION (REORDERING); if (Rule1d) return CLASSIFICATION (OOO_WITH_RC_LESS_THAN_RTT_NOT_3DUP_ACK); if (!Rule1b) return CLASSIFICATION (OOO_WITH_RC_LESS_THAN_RTO_AND_GREATER_THAN_RTT_NOT_3DUP_ACK); return CLASSIFICATION (UNKNOWN); } if (!Rule1a) return CLASSIFICATION (NETWORK_DUPLICATE); if ((Rule1b || Rule2b)) return CLASSIFICATION (Rule2b ? UNNECESSARY_RETRANSMISSION_FR : UNNECESSARY_RETRANSMISSION_RTO); if (Rule1d) return CLASSIFICATION (UNNECESSARY_RETRANSMISSION_WITH_RC_LESS_THAN_RTT_NOT_3DUP_ACK); if (!Rule1b) return CLASSIFICATION (UNNECESSARY_RETRANSMISSION_WITH_RC_LESS_THAN_RTO_AND_GREATER_THAN_RTT_NOT_3DUP_ACK); return CLASSIFICATION (UNKNOWN); }