int main(int argc, char **argv) { struct timeval start, end; char *mem; double t, at, mb, tbytes; int64_t megs, iter, bytes, i, j, c, adjtime = 0; uint8_t b; uint32_t x; uint64_t llx; struct bigbit bbx; volatile uint8_t *m; volatile uint32_t *lm; volatile uint64_t *llm; volatile struct bigbit *bbm; setvbuf(stdout, (char *)NULL, _IONBF, 0); if (argc < 2) { fprintf(stderr, "usage: memspeed [-a] <megs of memory to allocate>\n"); return 1; } i = 1; if (!strcmp(argv[i], "-a")) { adjtime = 1; i++; } megs = atoi(argv[i]); iter = 8192 / megs; mb = iter * megs; bytes = megs * 1024 * 1024; tbytes = (double)bytes * (double)iter; mem = malloc(bytes + 4); if (mem == NULL) { fprintf(stderr, "memspeed: memory allocation.\n"); return 1; } /* init memory to reduce cache effects for inital test */ printf("Initializing..."); memset(mem, 0, bytes); if (adjtime) { gettimeofday(&start, NULL); for (i = 0; i < iter; i++) for (m = mem, j = bytes; j; j--) m++; gettimeofday(&end, NULL); at = time2double(start, end); } printf( "\r Tests iterate over %dMB, %d times for a simulated total of " "%.0fMB\n\n", megs, iter, mb); // goto three; one: /* Test one: read bytes at a time. */ printf("Test 1: reading bytes : "); gettimeofday(&start, NULL); for (i = 0; i < iter; i++) { for (m = mem, j = bytes; j; j--) b = *m++; } gettimeofday(&end, NULL); t = time2double(start, end); if (adjtime) t -= at; printf("%5.2f seconds, %7.2f MB/s\n", t, mb / t); two: /* Test two: write bytes at a time. */ printf("Test 2: writing bytes : "); gettimeofday(&start, NULL); for (i = 0; i < iter; i++) { for (m = mem, j = bytes; j; j--) *m++ = 0; } gettimeofday(&end, NULL); t = time2double(start, end); if (adjtime) t -= at; printf("%5.2f seconds, %7.2f MB/s\n", t, mb / t); three: /* Test three: read 32 bit longs at a time. */ printf("Test 3: reading %d bit longs : ", sizeof(uint32_t) * 8); gettimeofday(&start, NULL); for (i = 0; i < iter; i++) { for (lm = (uint32_t *)mem, j = bytes / sizeof(uint32_t); j; j--) x = *lm++; } gettimeofday(&end, NULL); x++; t = time2double(start, end); if (adjtime) t -= (at / (double)sizeof(uint32_t)); printf("%5.2f seconds, %7.2f MB/s\n", t, mb / t); four: /* Test four: write 32 bit longs at a time. */ printf("Test 4: writing %d bit longs : ", sizeof(uint32_t) * 8); gettimeofday(&start, NULL); for (i = 0; i < iter; i++) { for (lm = (uint32_t *)mem, j = bytes / sizeof(uint32_t); j; j--) *lm++ = (uint32_t)0; } gettimeofday(&end, NULL); t = time2double(start, end); if (adjtime) t -= (at / (double)sizeof(uint32_t)); printf("%5.2f seconds, %7.2f MB/s\n", t, mb / t); five: /* Test five: read 64 bit longs at a time. */ printf("Test 5: reading %d bit longs : ", sizeof(uint64_t) * 8); gettimeofday(&start, NULL); for (i = 0; i < iter; i++) { for (llm = (uint64_t *)mem, j = bytes / sizeof(uint64_t); j; j--) llx = *llm++; } gettimeofday(&end, NULL); t = time2double(start, end); if (adjtime) t -= (at / (double)sizeof(uint64_t)); printf("%5.2f seconds, %7.2f MB/s\n", t, mb / t); six: /* Test six: write 64 bit longs at a time. */ printf("Test 6: writing 64 bit longs : ", sizeof(uint64_t) * 8); gettimeofday(&start, NULL); for (i = 0; i < iter; i++) { for (llm = (uint64_t *)mem, j = bytes / sizeof(uint64_t); j; j--) *llm++ = 0L; } gettimeofday(&end, NULL); t = time2double(start, end); if (adjtime) t -= (at / (double)sizeof(uint64_t)); printf("%5.2f seconds, %7.2f MB/s\n", t, mb / t); seven: /* Test seven: read 256 bit struct at a time. */ printf("Test 7: reading %d bit struct: ", sizeof(struct bigbit) * 8); gettimeofday(&start, NULL); for (i = 0; i < iter; i++) { for (bbm = (struct bigbit *)mem, j = bytes / sizeof(struct bigbit); j; j--) bbx = *bbm++; } gettimeofday(&end, NULL); t = time2double(start, end); if (adjtime) t -= (at / (double)sizeof(struct bigbit)); printf("%5.2f seconds, %7.2f MB/s\n", t, mb / t); eight: /* Test eight: write 256 bit struct at a time. */ printf("Test 8: writing %d bit struct: ", sizeof(struct bigbit) * 8); gettimeofday(&start, NULL); for (i = 0; i < iter; i++) { for (bbm = (struct bigbit *)mem, j = bytes / sizeof(struct bigbit); j; j--) *bbm++ = bbx; } gettimeofday(&end, NULL); t = time2double(start, end); if (adjtime) t -= (at / (double)sizeof(struct bigbit)); printf("%5.2f seconds, %7.2f MB/s\n", t, mb / t); nine: /* Test eight: read 256 bit struct with memcpy() */ printf("Test 9: reading with memcpy() : "); gettimeofday(&start, NULL); for (i = 0; i < iter; i++) { for (bbm = (struct bigbit *)mem, j = bytes / sizeof(struct bigbit); j; j--, bbm++) memcpy((void *)&bbx, (void *)bbm, sizeof(bbx)); } gettimeofday(&end, NULL); t = time2double(start, end); if (adjtime) t -= (at / (double)sizeof(struct bigbit)); printf("%5.2f seconds, %7.2f MB/s\n", t, mb / t); ten: /* Test nine: write with memset at a time. */ printf("Test 10: writing with memset() : "); gettimeofday(&start, NULL); for (i = 0; i < iter; i++) { memset(mem, 0, bytes); } gettimeofday(&end, NULL); t = time2double(start, end); printf("%5.2f seconds, %7.2f MB/s\n", t, mb / t); eleven: /* Test eight: copy with memcpy() */ printf("Test 11: copying with memcpy() : "); x = bytes / 2; gettimeofday(&start, NULL); for (i = 0; i < iter; i++) { memcpy(mem + x, mem, x); memcpy(mem, mem + x, x); } gettimeofday(&end, NULL); t = time2double(start, end); printf("%5.2f seconds, %7.2f MB/s\n", t, mb / t); return 0; }
/* 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); }
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++; } }
static int addseg (tcb * ptcb, quadrant * pquad, seqnum thisseg_firstbyte, seglen len, Bool * pout_order, u_short this_ip_id) { seqnum thisseg_lastbyte = thisseg_firstbyte + len - 1; segment *pseg; segment *pseg_new; int rexlen = 0; Bool split = FALSE; double recovery_time = 0; /* check each segment in the segment list */ pseg = pquad->seglist_head; /* LM - all the segments are memorized in the seglist Here has been implemented the heuristic discussed in S. Jaiswal, G.Iannaccone, C. Diot, J.F. Kurose, D.Towsley Measurement and Classification of Out-of-Sequence Packets in a Tier-1 IP Backbone INFOCOM 2003 http://www.ieee-infocom.org/2003/technical_programs.htm */ /* (optimize expected case, it just goes at the end) */ if (pquad->seglist_tail && (thisseg_firstbyte > pquad->seglist_tail->seq_lastbyte)) pseg = NULL; for (; pseg != NULL; pseg = pseg->next) { if (thisseg_firstbyte > pseg->seq_lastbyte) { /* goes beyond this one */ continue; } if (thisseg_firstbyte < pseg->seq_firstbyte) { /* starts BEFORE this recorded segment */ /* if it also FINISHES before this segment, then it's */ /* out of order (otherwise it's a resend the collapsed */ /* multiple segments into one */ if (thisseg_lastbyte < pseg->seq_lastbyte) *pout_order = TRUE; /* make a new segment record for it */ pseg_new = create_seg (thisseg_firstbyte, len, this_ip_id); insert_seg_between (pquad, pseg_new, pseg->prev, pseg); /* see if we overlap the next segment in the list */ if (thisseg_lastbyte <= pseg->seq_firstbyte) { /* we don't overlap, so we're done */ // LM start rules_test (ptcb, pseg, len, pquad, this_ip_id, FALSE, recovery_time); return (rexlen); } else { /* overlap him, split myself in 2 */ //fprintf(fp_stdout, "split %lu %lu\n", // len, pseg_new->seq_lastbyte-pseg_new->seq_firstbyte); /* adjust new piece to mate with old piece */ pseg_new->seq_lastbyte = pseg->seq_firstbyte - 1; // LM start rules_test (ptcb, pseg, pseg_new->seq_lastbyte - pseg_new->seq_firstbyte, pquad, this_ip_id, FALSE, recovery_time); /* pretend to be just the second half of this segment */ thisseg_firstbyte = pseg->seq_firstbyte; len = thisseg_lastbyte - thisseg_firstbyte + 1; /* fall through */ } } /* no ELSE, we might have fallen through */ if (thisseg_firstbyte >= pseg->seq_firstbyte) { /* starts within this recorded sequence */ ++pseg->retrans; recovery_time = time2double (current_time) - time2double (pseg->time); if (!split) rtt_retrans (ptcb, pseg); /* must be a retransmission */ if (thisseg_lastbyte <= pseg->seq_lastbyte) { /* entirely contained within this sequence */ rexlen += len; // LM start rules_test (ptcb, pseg, len, pquad, this_ip_id, TRUE, recovery_time); return (rexlen); } /* else */ /* we extend beyond this sequence, split ourself in 2 */ /* (pretend to be just the second half of this segment) */ split = TRUE; rexlen += pseg->seq_lastbyte - thisseg_firstbyte + 1; thisseg_firstbyte = pseg->seq_lastbyte + 1; // LM start rules_test (ptcb, pseg, rexlen, pquad, this_ip_id, TRUE, recovery_time); len = thisseg_lastbyte - thisseg_firstbyte + 1; } } /* if we got to the end, then it doesn't go BEFORE anybody, */ /* tack it onto the end */ pseg_new = create_seg (thisseg_firstbyte, len, this_ip_id); insert_seg_between (pquad, pseg_new, pquad->seglist_tail, NULL); /* MGM - management of the number of segments within this quadrant */ if (pquad->no_of_segments > MAX_SEG_PER_QUAD) { /* free up the first segment in this quadrant */ segment *tmp_pseg = pquad->seglist_head; /* rebuild the list */ if (tmp_pseg->next != NULL) tmp_pseg->next->prev = tmp_pseg->prev; pquad->seglist_head = tmp_pseg->next; /* recall the initial segment byte */ pquad->seglist_head->seq_firstbyte = tmp_pseg->seq_firstbyte; /* remove the segment */ segment_release (tmp_pseg); pquad->no_of_segments--; } pseg_new->type_of_segment = IN_SEQUENCE; /* LM : This is an IN_SEQUENCE segment */ if (internal_src && !internal_dst) { add_histo (tcp_anomalies_out, IN_SEQUENCE); } else if (!internal_src && internal_dst) { add_histo (tcp_anomalies_in, IN_SEQUENCE); } #ifndef LOG_UNKNOWN else if (internal_src && internal_dst) #else else #endif { add_histo (tcp_anomalies_loc, IN_SEQUENCE); } if ((&(ptcb->ptp->c2s)) == ptcb) //(dir == C2S) { add_histo (tcp_anomalies_c2s, IN_SEQUENCE); } else { add_histo (tcp_anomalies_s2c, IN_SEQUENCE); } return (rexlen); }