/* Note: all the functions here assume that there may be wraparound of TCP sequence and ack numbers */ #include #include #include #include #include #include #include "constants.h" #include "thresholds.h" #include "transaction.h" #include "packet.h" #include "packet_handler.h" #include "pcap.h" #include "conn_table.h" /* Flag needed for batch processing */ int first = TRUE; /* Transaction queue */ struct transaction* ts[MAX_TRANSACTIONS]; int nt=0; FILE* tfile; char successName[4]={'G','X','W','X'}; /* Timed statistics of goodput and throughput, to be read and cleared each second */ int Throughput = 0, Goodput = 0; /* Timed statistics of successes and failures, throughput and goodput */ int liveTransactions[MAX_SLOTS]; int failedTransactions[MAX_SLOTS]; int throughTotal[MAX_SLOTS]; int goodTotal[MAX_SLOTS]; int secs; /* In case we are doing multiple passes for various destinations */ int liveTransactionsTotal[MAX_SLOTS]; int failedTransactionsTotal[MAX_SLOTS]; double startTime = 0; double sT=0; double lastTime = 0; int successes=0; int failures=0; extern int CHECKID; extern struct hash_table* ConnTable; extern FILE* rfile; extern char Host[17]; extern int mask; extern struct appstats AppStats[NUM_APPLICATIONS]; extern int numapps, astart, aend, debug, aint; extern pcap_t* descr2; extern int format; extern int batch; struct shortAppStats sortedApps[NUM_APPLICATIONS]; char reasonName[NUM_REASON][MAX_NAME] = {"RTT-too-large ", "FTP-delay-too-large ", "No-data", "HTTP-delay-too-large ", "DNS-delay-too-large ", "Telnet-delay-too-large ", "ICMP-delay-too-large ", "Duration-too-large ", "Missing-a-reply", "One-way-delay-too-large", "Jitter-too-large", "Loss-too-large", "Mail/News-delay-too-large", "No-reason"}; char appNames[NUM_APPLICATIONS][MAX_NAME] = {"HTTP ", "DNS ", "Telnet", "FTP-Data", "FTP-Cntrl", "VoIP ", "RAudio", "Game ", "IRC ", "ICMP ", "Mail-SS", "Mail-US", "News", "FTPTelnet", "NOAPP", "FTP"}; void processThroughGood(int through, int good, double time) { Throughput += through; Goodput += good; if (time - lastTime > REPORT_INTERVAL) { double duration = time - lastTime; if (tfile) fprintf(tfile, "%lf %lf %lf\n", time-startTime, Throughput/duration, Goodput/duration); throughTotal[secs] = Throughput; goodTotal[secs] = Goodput; secs++; Throughput = 0; Goodput = 0; lastTime = time; } if (tfile) fflush(tfile); } double Max(double one, double two) { if (one>two) return one; else return two; } double Min(double one, double two) { if (oneduration = t->lastTime - t->startTime; t->throughputFrom = t->totalBytesSent/t->duration; t->throughputTo = t->totalBytesRcvd/t->duration; if (t->duration && t->totalBytesSent) t->avgThroughput = (t->totalBytesSent+t->totalBytesRcvd)/t->duration; else t->avgThroughput = 0; t->goodputFrom = t->usefulBytesSent/t->duration; t->goodputTo = t->usefulBytesRcvd/t->duration; if (t->duration && t->usefulBytesSent) t->avgGoodput = (t->usefulBytesSent+t->usefulBytesRcvd)/t->duration; else t->avgGoodput = 0; } void createTransaction(struct transaction** pt, double time, enum type ttype, enum app tapp, enum trans ttrans, unsigned int sIP, int sport, unsigned int dIP, int dport, int tid) { struct transaction *t; t = (struct transaction*)malloc(sizeof(struct transaction)); t->state = OPEN; t->startTime = t->lastTime = t->lastUsefulTime = t->lastLU = time; t->success = NOT_FOUND; t->ttype = ttype; t->tapp = tapp; t->ttrans = ttrans; t->lostpackets = 0; t->maxloss = 0; t->lastRcvdFromPeer = 0; t->numpackets = 0; t->winloss = t->winnum = 0; t->totalBytesSent = 0; t->totalBytesRcvd = 0; t->usefulBytesSent = 0; t->usefulBytesRcvd = 0; t->duration = 0; t->requestStart = t->requestEnd = t->requestBytes = 0; t->replyStart = t->replyEnd = t->replyBytes = 0; t->nc = 0; *pt = t; t->sIP = sIP; t->sport = sport; t->dIP = dIP; t->dport = dport; t->ID = 0; t->tid = tid; t->anyMaxDelay = 0; t->wholeMaxDelay = 0; t->oneWayDelay = 0; t->jitter = 0; t->maxjitter = 0; t->ds = 0; t->ws = 0; t->we = 0; t->win = 0; t->missReply = FALSE; t->reason = NOREASON; t->QoS = 0; t->dataport = t->controlport = 0; t->timeOfDeath = 0; t->maxRTT = 0; t->finstate = 0; } int detectNew(struct transaction* t, unsigned int seq) { int last; if (t->win > 0) last = (t->we - 1 + MAX_WIN)%MAX_WIN; else last = -1; if (last == -1 || seq > t->window[last].seqnum || (t->window[last].seqnum - seq > INT_MAX)) return TRUE; else return FALSE; } void decideType(struct transaction* t) { if (t->tapp == FTPTelnet || t->tapp == FTPData || t->tapp == Telnet) { int reqsize = 0, repsize = 0, i; if (t->nc == 0) { /* Too early to decide */ t->tapp = FTPData; return; } else { for(i=0; i< t->nc; i++) { reqsize += t->conversations[i].request; repsize += t->conversations[i].reply; } if (repsize && reqsize/repsize < TELNET_MAX_REQREPRTO && repsize/reqsize < TELNET_MAX_REQREPRTO) t->tapp = Telnet; else { t->tapp = FTPData; } } } } void checkTransaction(struct transaction* t, double time) { decideType(t); calculateThroughGood(t); if(t->startTime - startTime <= aend && t->lastTime - startTime > astart && t->success != FALSE) { if (t->success != IGNORE) { int old = t->success; calculateSuccess(t,&t->reason, time); if (t->success == FALSE) { double tod; struct in_addr in; char dadd[17], sadd[17]; in.s_addr = htonl(t->sIP); strcpy(sadd, inet_ntoa(in)); in.s_addr = htonl(t->dIP); strcpy(dadd, inet_ntoa(in)); if (t->timeOfDeath) tod = t->timeOfDeath - startTime; else tod = t->startTime - startTime; fprintf(rfile, "Transaction %s:%d to %s:%d failed at time %lf %lf slot %d start %lf %lf last time %lf reason %s\n", sadd, t->sport, dadd, t->dport, t->timeOfDeath, tod, (int)(tod/aint), t->startTime, t->startTime - startTime, t->lastTime - startTime, reasonName[t->reason]); fflush(rfile); failures ++; t->success = IGNORE; if (old == TRUE) successes --; } } } } /* The sequence number here should be the sequence number that will be carried in the acknowledgment, i.e. the next one to be acked */ void addTCPPacket(struct transaction* t, double time, unsigned int seq, int len, int hlen, int cindex, int syn, int fin) { int last; t->lastTime = time; /* If window is not empty */ if (t->win > 0) last = (t->we - 1 + MAX_WIN)%MAX_WIN; else last = -1; t->totalBytesSent += (hlen+len); processThroughGood(hlen+len, 0, time); /* If this is a new data packet, test for wraparound too */ if (last == -1 || seq > t->window[last].seqnum || (t->window[last].seqnum - seq > INT_MAX)) { if (len || syn) { t->window[t->we].seqnum = seq; t->window[t->we].timestamp = time; t->we = (t->we+1)%MAX_WIN; t->win ++; if (len) addQuery(t, time, TCP, len, NOT_FOUND); } } else { if (!descr2) t->lostpackets++; } t->numpackets++; checkTransaction(t, time); } void addTCPAck(struct transaction* t, double time, unsigned int peerseq, unsigned int ack, int len, int hlen, int cindex) { int i; t->lastTime = time; t->totalBytesRcvd += (hlen+len); processThroughGood(hlen+len, 0, time); /* Check if this is acking any packet in the window */ for (i=t->ws; i!=t->we;i=(i+1)%MAX_WIN) { struct packet p = t->window[i]; if (p.seqnum <= ack || p.seqnum - ack > INT_MAX) { double RTT = time - p.timestamp; p.seqnum = 0; if (RTT > t->maxRTT) { t->maxRTT = RTT; //printf("RTT1 %lf packet with timestamp %lf acked at %lf\n", // RTT, p.timestamp, time); } t->ws = (i+1)%MAX_WIN; t->win --; } } if (t->lastRcvdFromPeer < peerseq || t->lastRcvdFromPeer - peerseq > INT_MAX) { /* If this is new data sent from the other party, add its length to the running total */ { t->lastRcvdFromPeer = peerseq; if(len) addReply(t, time, len, NOT_FOUND); checkTransaction(t, time); } } } void addUDPPacket(struct transaction* t, double time, int len, int hlen, int identification) { t->lastTime = time; t->totalBytesSent += (hlen+len); processThroughGood(hlen+len, 0, time); t->numpackets++; if (len) addQuery(t, time, UDP, len, identification); checkTransaction(t, time); } void addUDPReply(struct transaction* t, double time, int len, int hlen, int identification) { t->lastTime = time; /* If this is new data sent from the other party, add its length to the running total */ t->totalBytesRcvd += (hlen+len); processThroughGood(hlen+len, 0, time); if(len) addReply(t, time, len, identification); checkTransaction(t, time); } void addICMPPacket(struct transaction* t, double time, int len, int hlen, int identification) { t->lastTime = time; t->totalBytesSent += (hlen+len); processThroughGood(hlen+len, 0, time); t->numpackets++; addQuery(t, time, ICMP, len, identification); checkTransaction(t, time); } void addICMPReply(struct transaction* t, double time, int len, int hlen, int identification) { t->lastTime = time; /* If this is new data sent from the other party, add its length to the running total */ t->totalBytesRcvd += (hlen+len); processThroughGood(hlen+len, 0, time); addReply(t, time, len, identification); checkTransaction(t, time); } /* We are sending some query, it could be DNS, ICMP, HTTP. Take the first query sent and expect a reply to this one. */ int addQuery(struct transaction* t, double time, enum trans ttrans, int len, int identification) { if (identification != NOT_FOUND && identification == t->ID && t->ID!=0) { if (!descr2) t->lostpackets++; return FALSE; } /* This is not a retransmitted query */ t->lastUsefulTime = time; t->usefulBytesSent += len; processThroughGood(0, len, time); if (identification != NOT_FOUND) { t->ID = identification; } /* If we have received any reply this is a new query */ if (t->replyStart > 0) { t->conversations[t->nc].request = t->requestBytes; t->conversations[t->nc].reply = t->replyBytes; t->conversations[t->nc].requestTime = t->requestEnd - t->requestStart; t->nc++; if (t->wholeMaxDelay < t->replyEnd - t->requestEnd) t->wholeMaxDelay = t->replyEnd - t->requestEnd; t->requestBytes = 0; t->replyBytes = 0; t->requestStart = time; t->replyStart = 0; } else if (t->requestStart == 0) t->requestStart = time; t->requestBytes += len; t->requestEnd = time; return TRUE; } /* We are receiving some reply, it could be DNS, ICMP, HTTP. Take the last reply sent, this should be the end of the long reply for HTTP but we have no way of knowing if it is the end of the page or not. */ void addReply(struct transaction* t, double time, int len, int identification) { if (identification != NOT_FOUND && identification != t->ID && t->ID!=0 && CHECKID) { if (!descr2) t->lostpackets++; return; } /* This is not a retransmitted reply */ t->lastUsefulTime = time; t->usefulBytesRcvd += len; processThroughGood(0, len, time); if (t->requestStart > 0) { t->replyBytes += len; if (t->replyStart == 0) { t->replyStart = time; if (time - t->requestEnd > t->anyMaxDelay) { t->anyMaxDelay = time - t->requestEnd; //printf("AMD1 %lf time %lf\n",t->anyMaxDelay, time); } } else if(time - t->replyEnd > t->anyMaxDelay) { t->anyMaxDelay = time - t->replyEnd; // printf("AMD2 %lf time %lf\n",t->anyMaxDelay, time); } t->replyEnd = time; } } int hasThroughput(enum app tapp) { switch(tapp) { case FTPData: return TRUE; default: return TRUE; } } int hasReply(struct transaction* t) { if (t->replyStart > 0) return TRUE; else return FALSE; } void calculateSuccess(struct transaction *t, int* reason, double time) { int i, found=NOT_FOUND, j; double loss; if (hasThroughput(t->tapp)) calculateThroughGood(t); *reason = NOREASON; /* Calculate loss */ loss = (double)(t->lostpackets - t->winloss)/(t->numpackets - t->winnum); if (time - t->lastLU > LU_PERIOD) { if (loss > t->maxloss) t->maxloss = loss; t->lastLU = time; t->winloss = t->lostpackets; t->winnum = t->numpackets; } /* If the application is ambiguous FTP/Telnet, decide whether it's one or the other looking at the avg. query/reply size */ found = findAppStats(t->tapp); /* Check if we are doing time-based failure detection */ if (t->ttrans == TCP && aint) { int i; /* See if there are any remaining packets in the window */ for(i=0;iwin;i++) { struct packet p = t->window[(i+t->ws)%MAX_WIN]; double RTT = time - p.timestamp; if (p.seqnum == 0) continue; if (RTT > t->maxRTT) { t->maxRTT = RTT; // printf("RTT2 %lf packet %u with timestamp %lf acked at %lf\n", // RTT, p.seqnum, p.timestamp, time); } } } if (followRequestReply(t->tapp) && aint) { if (t->requestStart) { if (t->replyStart == 0 && time - t->requestEnd > t->anyMaxDelay) t->anyMaxDelay = time - t->requestEnd; if (t->wholeMaxDelay < t->anyMaxDelay) t->wholeMaxDelay = t->anyMaxDelay; } } switch(t->tapp) { case VoIP: if (t->oneWayDelay > VOIP_MAX_DELAY) { t->success = FALSE; *reason = OW_DELAY; t->timeOfDeath = time; t->QoS = (VOIP_MAX_DELAY-t->oneWayDelay)/VOIP_MAX_DELAY; } else if (t->maxjitter > VOIP_MAX_JITTER) { t->success = FALSE; *reason = JITTER; t->timeOfDeath = time; t->QoS = (VOIP_MAX_JITTER-t->maxjitter)/VOIP_MAX_JITTER; } else if (t->maxloss > VOIP_MAX_LOSS) { t->success = FALSE; *reason = LOSS; t->timeOfDeath = time; t->QoS = (VOIP_MAX_LOSS-t->maxloss)/VOIP_MAX_LOSS; } else { t->success = TRUE; t->QoS = ((VOIP_MAX_DELAY-t->oneWayDelay)/VOIP_MAX_DELAY); } break; case IRC: if (t->oneWayDelay > IRC_MAX_DELAY) { t->success = FALSE; *reason = OW_DELAY; t->timeOfDeath = time; t->QoS = (IRC_MAX_DELAY-t->oneWayDelay)/IRC_MAX_DELAY; } else { t->success = TRUE; t->QoS = ((IRC_MAX_DELAY-t->oneWayDelay)/IRC_MAX_DELAY); } break; case HTTP: if (t->maxRTT > HTTP_MAX_DELAY) { t->success = FALSE; *reason = TCP_DELAY; t->timeOfDeath = time - (t->maxRTT-HTTP_MAX_DELAY); t->QoS = (HTTP_MAX_DELAY-t->maxRTT)/HTTP_MAX_DELAY; } else if (t->anyMaxDelay > HTTP_MAX_DELAY) { t->success = FALSE; *reason = HTTP_DELAY; t->timeOfDeath = time - (t->anyMaxDelay - HTTP_MAX_DELAY); t->QoS = (HTTP_MAX_DELAY-t->anyMaxDelay)/HTTP_MAX_DELAY; } else if (t->duration > HTTP_MAX_DURATION) { t->success = FALSE; *reason = DURATION; t->QoS = (HTTP_MAX_DURATION-t->duration)/HTTP_MAX_DURATION; t->timeOfDeath = time - (t->duration - HTTP_MAX_DURATION); } else { t->success = TRUE; t->QoS = ((HTTP_MAX_DELAY-t->maxRTT)/HTTP_MAX_DELAY + (HTTP_MAX_DELAY-t->anyMaxDelay)/HTTP_MAX_DELAY + (HTTP_MAX_DURATION-t->duration)/HTTP_MAX_DURATION)/3; } break; case News: case MailSS: if (t->maxRTT > MN_MAX_DELAY) { t->success = FALSE; *reason = TCP_DELAY; t->timeOfDeath = time - (t->maxRTT - MN_MAX_DELAY); t->QoS = (MN_MAX_DELAY-t->maxRTT)/MN_MAX_DELAY; } else if (t->wholeMaxDelay > MN_MAX_DELAY) { t->success = FALSE; *reason = MN_DELAY; t->timeOfDeath = time - (t->maxRTT - MN_MAX_DELAY); t->QoS = (MN_MAX_DELAY-t->anyMaxDelay)/MN_MAX_DELAY; } else { t->success = TRUE; t->QoS = ((MN_MAX_DELAY-t->maxRTT)/MN_MAX_DELAY + (MN_MAX_DELAY-t->anyMaxDelay)/MN_MAX_DELAY)/2; } break; case MailUS: if (t->maxRTT > INTERACTIVE_DELAY_THRESHOLD) { t->success = FALSE; *reason = TCP_DELAY; t->timeOfDeath = time - (t->maxRTT - INTERACTIVE_DELAY_THRESHOLD); t->QoS = (INTERACTIVE_DELAY_THRESHOLD - t->maxRTT)/INTERACTIVE_DELAY_THRESHOLD; } else if (t->anyMaxDelay > INTERACTIVE_DELAY_THRESHOLD) { t->success = FALSE; *reason = MN_DELAY; t->timeOfDeath = time - (t->anyMaxDelay - INTERACTIVE_DELAY_THRESHOLD); t->QoS = (INTERACTIVE_DELAY_THRESHOLD - t->anyMaxDelay)/INTERACTIVE_DELAY_THRESHOLD; } else if ((found != NOT_FOUND) && t->duration > INTERACTIVE_DELAY_THRESHOLD && AppStats[found].avgThroughput > 0 && t->avgThroughput*3 < AppStats[found].avgThroughput/AppStats[found].numtrans) { t->success = FALSE; *reason = DURATION; t->timeOfDeath = time - (t->duration - 3*AppStats[found].numtrans/AppStats[found].avgThroughput); t->QoS = (t->avgThroughput*3 - AppStats[found].avgThroughput/AppStats[found].numtrans)/ (AppStats[found].avgThroughput/AppStats[found].numtrans); } else { t->success = TRUE; t->QoS = ((INTERACTIVE_DELAY_THRESHOLD - t->maxRTT)/INTERACTIVE_DELAY_THRESHOLD+ (INTERACTIVE_DELAY_THRESHOLD - t->anyMaxDelay)/INTERACTIVE_DELAY_THRESHOLD+ (t->avgThroughput - AppStats[found].avgThroughput/AppStats[found].numtrans)/ (AppStats[found].avgThroughput/AppStats[found].numtrans))/3; } break; case DNS: if (t->missReply) { t->success = FALSE; t->anyMaxDelay = t->wholeMaxDelay = 2*INTERACTIVE_DELAY_THRESHOLD; t->timeOfDeath = t->lastUsefulTime + INTERACTIVE_DELAY_THRESHOLD; *reason = MISSREPLY; t->QoS = -1; } else if (t->wholeMaxDelay > INTERACTIVE_DELAY_THRESHOLD) { t->success = FALSE; *reason = DNS_DELAY; t->timeOfDeath = time - (t->wholeMaxDelay - INTERACTIVE_DELAY_THRESHOLD); t->QoS = (INTERACTIVE_DELAY_THRESHOLD-t->wholeMaxDelay)/INTERACTIVE_DELAY_THRESHOLD; } else { t->success = TRUE; t->QoS = (INTERACTIVE_DELAY_THRESHOLD-t->wholeMaxDelay)/INTERACTIVE_DELAY_THRESHOLD; } break; case FTPData: if (t->controlport) return; else { if (t->maxRTT > FTP_DELAY_THRESHOLD) { t->success = FALSE; *reason = TCP_DELAY; t->timeOfDeath = time - (t->maxRTT - FTP_DELAY_THRESHOLD); t->QoS = (FTP_DELAY_THRESHOLD - t->maxRTT)/FTP_DELAY_THRESHOLD; } else if (t->anyMaxDelay > FTP_DELAY_THRESHOLD) { t->success = FALSE; *reason = FTP_DELAY; t->timeOfDeath = time - (t->anyMaxDelay - FTP_DELAY_THRESHOLD); t->QoS = (FTP_DELAY_THRESHOLD - t->anyMaxDelay)/FTP_DELAY_THRESHOLD; } else if ((found != NOT_FOUND) && t->duration > FTP_DELAY_THRESHOLD && AppStats[found].avgThroughput > 0 && t->avgThroughput*3 < AppStats[found].avgThroughput/AppStats[found].numtrans) { t->success = FALSE; *reason = DURATION; t->timeOfDeath = time - (t->duration - 3*AppStats[found].numtrans/ AppStats[found].avgThroughput); t->QoS = (t->avgThroughput*3 - AppStats[found].avgThroughput/AppStats[found].numtrans)/ (AppStats[found].avgThroughput/AppStats[found].numtrans); } else { t->success = TRUE; t->QoS = ((FTP_DELAY_THRESHOLD - t->maxRTT)/FTP_DELAY_THRESHOLD+ (FTP_DELAY_THRESHOLD - t->anyMaxDelay)/FTP_DELAY_THRESHOLD+ (t->avgThroughput - AppStats[found].avgThroughput/AppStats[found].numtrans)/ (AppStats[found].avgThroughput/AppStats[found].numtrans))/3; } break; } case FTPControl: if (t->maxRTT > FTP_DELAY_THRESHOLD) { t->success = FALSE; *reason = TCP_DELAY; t->timeOfDeath = time - (t->maxRTT - FTP_DELAY_THRESHOLD); t->QoS = (FTP_DELAY_THRESHOLD - t->maxRTT)/FTP_DELAY_THRESHOLD; } /* No data channel established */ else if (t->dataport == 0 && (t->anyMaxDelay > FTP_DELAY_THRESHOLD || t->state == CLOSED)) { t->success = FALSE; if (t->state == CLOSED && t->dataport == 0) *reason = NO_DATA; else *reason = FTP_DELAY; t->timeOfDeath = time - (t->anyMaxDelay - FTP_DELAY_THRESHOLD); t->QoS = (FTP_DELAY_THRESHOLD - t->anyMaxDelay)/FTP_DELAY_THRESHOLD; } else if (t->dataport) { int index = find_connection(t->dIP, t->sIP, 20, t->dataport); if (index != NOT_FOUND) { struct conn_stats* data = (struct conn_stats*)ConnTable->entries[index].data; int res = setActiveTransaction(data, FTPTelnet, 0); if (res) { struct transaction * d = data->t; if (d->maxRTT > FTP_DELAY_THRESHOLD) { t->success = FALSE; *reason = TCP_DELAY; t->timeOfDeath = time - (d->maxRTT - FTP_DELAY_THRESHOLD); t->QoS = (FTP_DELAY_THRESHOLD - d->maxRTT)/FTP_DELAY_THRESHOLD; } else if (d->anyMaxDelay > FTP_DELAY_THRESHOLD) { t->success = FALSE; *reason = FTP_DELAY; t->timeOfDeath = time - (d->anyMaxDelay - FTP_DELAY_THRESHOLD); t->QoS = (FTP_DELAY_THRESHOLD - d->anyMaxDelay)/FTP_DELAY_THRESHOLD; } else { found = findAppStats(d->tapp); if ((found != NOT_FOUND) && d->duration > FTP_DELAY_THRESHOLD && AppStats[found].avgThroughput > 0 && d->avgThroughput*3 < AppStats[found].avgThroughput/AppStats[found].numtrans) { t->success = FALSE; *reason = DURATION; t->timeOfDeath = time - (d->duration - 3*AppStats[found].numtrans/ AppStats[found].avgThroughput); t->QoS = (d->avgThroughput*3 - AppStats[found].avgThroughput/AppStats[found].numtrans)/ (AppStats[found].avgThroughput/AppStats[found].numtrans); } else { t->success = TRUE; t->QoS = ((FTP_DELAY_THRESHOLD - t->maxRTT)/FTP_DELAY_THRESHOLD+ (FTP_DELAY_THRESHOLD - t->anyMaxDelay)/FTP_DELAY_THRESHOLD+ (t->avgThroughput - AppStats[found].avgThroughput/AppStats[found].numtrans)/ (AppStats[found].avgThroughput/AppStats[found].numtrans))/3; } } } } } else { t->success = TRUE; t->QoS = ((FTP_DELAY_THRESHOLD - t->maxRTT)/FTP_DELAY_THRESHOLD+ (FTP_DELAY_THRESHOLD - t->anyMaxDelay)/FTP_DELAY_THRESHOLD+ (t->avgThroughput - AppStats[found].avgThroughput/AppStats[found].numtrans)/ (AppStats[found].avgThroughput/AppStats[found].numtrans))/3; } break; case Telnet: if (t->maxRTT > TELNET_DELAY_THRESHOLD) { t->success = FALSE; *reason = TCP_DELAY; t->QoS = (TELNET_DELAY_THRESHOLD - t->maxRTT); t->timeOfDeath = time - (t->maxRTT - TELNET_DELAY_THRESHOLD); } else if (t->anyMaxDelay > TELNET_DELAY_THRESHOLD) { t->success = FALSE; *reason = TELNET_DELAY; t->QoS = (TELNET_DELAY_THRESHOLD - t->anyMaxDelay)/TELNET_DELAY_THRESHOLD; t->timeOfDeath = time - (t->anyMaxDelay - TELNET_DELAY_THRESHOLD); } else { t->success = TRUE; t->QoS = ((TELNET_DELAY_THRESHOLD - t->maxRTT)+ (TELNET_DELAY_THRESHOLD - t->anyMaxDelay))/(TELNET_DELAY_THRESHOLD)/2; } break; case ICMP: if (t->missReply) { t->success = FALSE; t->anyMaxDelay = t->wholeMaxDelay = 2*INTERACTIVE_DELAY_THRESHOLD; *reason = MISSREPLY; t->timeOfDeath = t->lastUsefulTime + INTERACTIVE_DELAY_THRESHOLD; t->QoS = -1; } else if (t->wholeMaxDelay > INTERACTIVE_DELAY_THRESHOLD) { t->success = FALSE; *reason = ICMP_DELAY; t->timeOfDeath = time - (t->wholeMaxDelay - INTERACTIVE_DELAY_THRESHOLD); t->QoS = (INTERACTIVE_DELAY_THRESHOLD - t->wholeMaxDelay)/INTERACTIVE_DELAY_THRESHOLD; } else { t->success = TRUE; t->QoS = (INTERACTIVE_DELAY_THRESHOLD - t->wholeMaxDelay)/INTERACTIVE_DELAY_THRESHOLD; } break; default: t->success = TRUE; break; } if (t->timeOfDeath < t->startTime && t->success == FALSE) printf("Something wrong, transaction %s started %lf tod %lf reason %s\n", appNames[t->tapp], t->startTime, t->timeOfDeath, reasonName[t->reason]); } void sortApps() { int i, fc=NOT_FOUND, fd=NOT_FOUND; for (i=0; itapp == FTPData && ts[i]->controlport) continue; if(ts[i]->tapp == FTPData || ts[i]->tapp == FTPControl) { if (ts[i]->success == TRUE) { AppStats[found].successes++; AppStats[found].nt++; AppStats[found].QoS += ts[i]->QoS; } else if (ts[i]->success != NOT_FOUND) { AppStats[found].failures++; AppStats[found].nt++; AppStats[found].DoS += ts[i]->QoS; } AppStats[found].service += ts[i]->QoS; } } } } int closeTransaction(struct transaction ** pt, double time) { struct transaction *t = *pt; int success, reason, i; int sslot, eslot, dslot; /* Set the state to closed */ t->state = CLOSED; /* Decide on type */ decideType(t); /* See if there is any new conversation to store */ if (t->requestStart) { t->conversations[t->nc].request = t->requestBytes; t->conversations[t->nc].reply = t->replyBytes; if (t->replyStart == 0) { /* If this is an application that follows request/reply then missing a reply is indication of failure */ if (followRequestReply(t->tapp)) { t->missReply = TRUE; if (!descr2) t->lostpackets++; t->anyMaxDelay = LARGE_DELAY; t->wholeMaxDelay = LARGE_DELAY; } } if (t->wholeMaxDelay < t->replyEnd - t->requestEnd) t->wholeMaxDelay = t->replyEnd - t->requestEnd; t->nc++; } /* See if there are any remaining packets in the window */ for(i=0;iwin;i++) { struct packet p = t->window[(i+t->ws)%MAX_WIN]; double RTT = time - p.timestamp; if (p.seqnum == 0) continue; if (RTT > t->maxRTT) { t->maxRTT = RTT; //printf("RTT3 %lf time %lf ack for %u sent at %lf\n", // RTT, time, p.seqnum, p.timestamp); } } /* Calculate duration */ t->duration = t->lastTime - t->startTime; /* If this transaction is completed before the attack, use it to calculate avg throughput */ if (t->lastTime - startTime < astart) { int j, found = NOT_FOUND; if (hasThroughput(t->tapp)) calculateThroughGood(t); found = findAppStats(t->tapp); if (found != NOT_FOUND) { AppStats[found].avgThroughput += t->avgThroughput; AppStats[found].numtrans++; } else { AppStats[numapps].numtrans = 1; AppStats[numapps].QoS = 0; AppStats[numapps].application = t->tapp; AppStats[numapps].avgThroughput = t->avgThroughput; numapps++; } } if (nt < MAX_TRANSACTIONS) { ts[nt++] = t; } *pt = 0; checkTransaction(t, time); /* Update timed measures */ if (aint) { sslot = (int)((t->startTime - startTime)/aint); if (t->timeOfDeath) eslot = (int)((t->timeOfDeath - startTime)/aint); else eslot = (int)((t->lastTime - startTime)/aint); if (t->timeOfDeath) dslot = (int)((t->timeOfDeath - startTime)/aint); else dslot = NOT_FOUND; for (i=sslot; i<=eslot && (dslot == NOT_FOUND || i < dslot);i++) liveTransactions[i]++; if (dslot != NOT_FOUND) failedTransactions[dslot]++; } return success; } void calculatePft(int start, int end, double time) { int i, j; printf("Num transactions %d aplications %d\n", nt, numapps); for(i=0;isuccess != IGNORE) // ts[i]->success = NOT_FOUND; } for(i=0;istartTime - startTime <= end && ts[i]->lastTime - startTime > start) //&& //ts[i]->success != IGNORE) { int reason; calculateSuccess(ts[i], &ts[i]->reason, time); } for (i=0;itapp); if (found == NOT_FOUND) { AppStats[numapps].numtrans = 0; AppStats[numapps].application = ts[i]->tapp; AppStats[numapps].avgThroughput = 0; AppStats[numapps].successes = 0; AppStats[numapps].failures = 0; AppStats[numapps].nt = 0; AppStats[numapps].service = 0; AppStats[numapps].QoS = 0; AppStats[numapps].DoS = 0; found = numapps; numapps++; } if (ts[i]->success == TRUE) { AppStats[found].successes++; AppStats[found].nt++; AppStats[found].QoS += ts[i]->QoS; } else if (ts[i]->success != NOT_FOUND) { AppStats[found].failures++; AppStats[found].nt++; AppStats[found].DoS += ts[i]->QoS; } AppStats[found].service += ts[i]->QoS; } sortApps(); if (format == MACHINE) { printf("%s/%d\t", Host, mask); for (i=0; isize;i++) { if(ConnTable->entries[i].state == VALID) { int j; struct conn_stats* data = (struct conn_stats*) ConnTable->entries[i].data; for(j=0;jnt;j++) { struct transaction* t = data->trans[j]; checkTransaction(t, time); } /* Close stale transactions */ for(j=0;jnt;j++) { struct transaction* t; t = data->trans[j]; if (followRequestReply(t->tapp)) { double delay = detectInactive(t->tapp); if (time - t->lastTime >= delay) { removeTransaction(data, time, t); j--; } } } } } } void printTransaction(int n, struct transaction* t, FILE* output) { int i; int sumreq=0, sumrep=0; double tod; if (t->timeOfDeath != 0) tod = t->timeOfDeath - startTime; else tod = 0; fprintf(output,"%d\t%lf\t%lf\t%lf\t%lf\t%lf\t%lf\t%lf\t%lf\t%s\t%d\t%d\t%lf\t%d\t%d\t%lf\t%d\t%d\t%lf\t%c\t%s\t%lf\t%lf\n", n, t->startTime - startTime, t->duration, t->maxloss, (double)t->lostpackets/t->numpackets, t->anyMaxDelay, t->wholeMaxDelay, t->oneWayDelay, t->maxjitter, appNames[t->tapp], t->totalBytesSent, t->totalBytesRcvd, t->avgThroughput, t->usefulBytesSent, t->usefulBytesRcvd, t->avgGoodput, t->sport, t->dport, t->maxRTT, successName[t->success+1], reasonName[t->reason], t->QoS, tod); } void printTransactions(FILE* output) { int i, j; if (nt == 0) return; fprintf(output,"ID\t start\t\t duration\t intloss \t loss\t\t anyDelay\t maxDelay\t owDelay\t jitter\t app\t sentB\t " "recB\t avgThrough\t usentB\t urecB\t avgGood\t sport\t dport\t maxRTT\t suc\t " "reason\t QoS\t timeOfDeath\n"); /* Now write them out */ for(i=0;i