X-Git-Url: http://git.liburcu.org/?a=blobdiff_plain;f=lttv%2Flttv%2Fsync%2Fevent_matching_tcp.c;h=0202380ccb6f2dca652c6cbe6702d9cba5bee65a;hb=d6ee500355b870e83d5cdbc431629999ec97794e;hp=892dc7af127ab1fa40c0dfcc94f03a12618cf968;hpb=70407e861d8430dbe06cc52e6fe4ed5c9cd0872a;p=lttv.git diff --git a/lttv/lttv/sync/event_matching_tcp.c b/lttv/lttv/sync/event_matching_tcp.c index 892dc7af..0202380c 100644 --- a/lttv/lttv/sync/event_matching_tcp.c +++ b/lttv/lttv/sync/event_matching_tcp.c @@ -20,8 +20,10 @@ #include #endif +#include #include #include +#include #include "event_analysis.h" #include "sync_chain.h" @@ -38,33 +40,42 @@ static void initMatchingTCP(SyncState* const syncState); static void destroyMatchingTCP(SyncState* const syncState); -static void matchEventTCP(SyncState* const syncState, NetEvent* const event, - EventType eventType); +static void matchEventTCP(SyncState* const syncState, Event* const event); static GArray* finalizeMatchingTCP(SyncState* const syncState); static void printMatchingStatsTCP(SyncState* const syncState); +static void writeMatchingGraphsPlotsTCP(FILE* stream, SyncState* const + syncState, const unsigned int i, const unsigned int j); // Functions specific to this module static void registerMatchingTCP() __attribute__((constructor (101))); -static void matchEvents(SyncState* const syncState, NetEvent* const event, +static void matchEvents(SyncState* const syncState, Event* const event, GHashTable* const unMatchedList, GHashTable* const unMatchedOppositeList, const size_t fieldOffset, const size_t oppositeFieldOffset); static void partialDestroyMatchingTCP(SyncState* const syncState); -static bool isAck(const Packet* const packet); -static bool needsAck(const Packet* const packet); +static bool isAck(const Message* const message); +static bool needsAck(const Message* const message); static void buildReversedConnectionKey(ConnectionKey* const reversedConnectionKey, const ConnectionKey* const connectionKey); +static void openGraphDataFiles(SyncState* const syncState); +static void closeGraphDataFiles(SyncState* const syncState); +static void writeMessagePoint(FILE* stream, const Message* const message); + static MatchingModule matchingModuleTCP = { .name= "TCP", + .canMatch[TCP]= true, + .canMatch[UDP]= false, .initMatching= &initMatchingTCP, .destroyMatching= &destroyMatchingTCP, .matchEvent= &matchEventTCP, .finalizeMatching= &finalizeMatchingTCP, .printMatchingStats= &printMatchingStatsTCP, + .writeMatchingGraphsPlots= &writeMatchingGraphsPlotsTCP, + .writeMatchingGraphsOptions= NULL, }; @@ -100,22 +111,40 @@ static void initMatchingTCP(SyncState* const syncState) matchingData= malloc(sizeof(MatchingDataTCP)); syncState->matchingData= matchingData; - matchingData->unMatchedInE= g_hash_table_new_full(&ghfPacketKeyHash, - &gefPacketKeyEqual, NULL, &gdnDestroyNetEvent); - matchingData->unMatchedOutE= g_hash_table_new_full(&ghfPacketKeyHash, - &gefPacketKeyEqual, NULL, &gdnDestroyNetEvent); + matchingData->unMatchedInE= g_hash_table_new_full(&ghfSegmentKeyHash, + &gefSegmentKeyEqual, NULL, &gdnDestroyEvent); + matchingData->unMatchedOutE= g_hash_table_new_full(&ghfSegmentKeyHash, + &gefSegmentKeyEqual, NULL, &gdnDestroyEvent); matchingData->unAcked= g_hash_table_new_full(&ghfConnectionKeyHash, &gefConnectionKeyEqual, &gdnConnectionKeyDestroy, - &gdnPacketListDestroy); + &gdnTCPSegmentListDestroy); if (syncState->stats) { + unsigned int i; + matchingData->stats= calloc(1, sizeof(MatchingStatsTCP)); + matchingData->stats->totMessageArray= malloc(syncState->traceNb * + sizeof(unsigned int*)); + for (i= 0; i < syncState->traceNb; i++) + { + matchingData->stats->totMessageArray[i]= + calloc(syncState->traceNb, sizeof(unsigned int)); + } } else { matchingData->stats= NULL; } + + if (syncState->graphs) + { + openGraphDataFiles(syncState); + } + else + { + matchingData->messagePoints= NULL; + } } @@ -144,6 +173,13 @@ static void destroyMatchingTCP(SyncState* const syncState) if (syncState->stats) { + unsigned int i; + + for (i= 0; i < syncState->traceNb; i++) + { + free(matchingData->stats->totMessageArray[i]); + } + free(matchingData->stats->totMessageArray); free(matchingData->stats); } @@ -176,13 +212,15 @@ static void partialDestroyMatchingTCP(SyncState* const syncState) return; } - g_debug("Cleaning up unMatchedInE list\n"); g_hash_table_destroy(matchingData->unMatchedInE); matchingData->unMatchedInE= NULL; - g_debug("Cleaning up unMatchedOutE list\n"); g_hash_table_destroy(matchingData->unMatchedOutE); - g_debug("Cleaning up unAcked list\n"); g_hash_table_destroy(matchingData->unAcked); + + if (syncState->graphs && matchingData->messagePoints) + { + closeGraphDataFiles(syncState); + } } @@ -193,25 +231,26 @@ static void partialDestroyMatchingTCP(SyncState* const syncState) * Args: * syncState container for synchronization data. * event new event to match - * eventType type of event to match */ -static void matchEventTCP(SyncState* const syncState, NetEvent* const event, EventType eventType) +static void matchEventTCP(SyncState* const syncState, Event* const event) { MatchingDataTCP* matchingData; + g_assert(event->type == TCP); + matchingData= (MatchingDataTCP*) syncState->matchingData; - if (eventType == IN) + if (event->event.tcpEvent->direction == IN) { matchEvents(syncState, event, matchingData->unMatchedInE, - matchingData->unMatchedOutE, offsetof(Packet, inE), - offsetof(Packet, outE)); + matchingData->unMatchedOutE, offsetof(Message, inE), + offsetof(Message, outE)); } else { matchEvents(syncState, event, matchingData->unMatchedOutE, - matchingData->unMatchedInE, offsetof(Packet, outE), - offsetof(Packet, inE)); + matchingData->unMatchedInE, offsetof(Message, outE), + offsetof(Message, inE)); } } @@ -234,14 +273,15 @@ static GArray* finalizeMatchingTCP(SyncState* const syncState) /* - * Print statistics related to matching and downstream modules. Must be - * called after finalizeMatching. + * Print statistics related to matching. Must be called after + * finalizeMatching. * * Args: * syncState container for synchronization data. */ static void printMatchingStatsTCP(SyncState* const syncState) { + unsigned int i, j; MatchingDataTCP* matchingData; if (!syncState->stats) @@ -252,18 +292,29 @@ static void printMatchingStatsTCP(SyncState* const syncState) matchingData= (MatchingDataTCP*) syncState->matchingData; printf("TCP matching stats:\n"); - printf("\ttotal input and output events matched together to form a packet: %d\n", + printf("\ttotal input and output events matched together to form a packet: %u\n", matchingData->stats->totPacket); - printf("\ttotal packets identified needing an acknowledge: %d\n", - matchingData->stats->totPacketNeedAck); - printf("\ttotal exchanges (four events matched together): %d\n", - matchingData->stats->totExchangeEffective); - printf("\ttotal synchronization exchanges: %d\n", - matchingData->stats->totExchangeSync); - - if (syncState->analysisModule->printAnalysisStats != NULL) + + printf("\tMessage traffic:\n"); + + for (i= 0; i < syncState->traceNb; i++) + { + for (j= i + 1; j < syncState->traceNb; j++) + { + printf("\t\t%3d - %-3d: sent %-10u received %-10u\n", i, j, + matchingData->stats->totMessageArray[j][i], + matchingData->stats->totMessageArray[i][j]); + } + } + + if (syncState->analysisModule->analyzeExchange != NULL) { - syncState->analysisModule->printAnalysisStats(syncState); + printf("\ttotal packets identified needing an acknowledge: %u\n", + matchingData->stats->totPacketNeedAck); + printf("\ttotal exchanges (four events matched together): %u\n", + matchingData->stats->totExchangeEffective); + printf("\ttotal synchronization exchanges: %u\n", + matchingData->stats->totExchangeSync); } } @@ -272,64 +323,71 @@ static void printMatchingStatsTCP(SyncState* const syncState) * Implementation of a packet matching algorithm for TCP * * Args: - * netEvent: new event to match + * event: new event to match * unMatchedList: list of unmatched events of the same type (send or - * receive) as netEvent + * receive) as event * unMatchedOppositeList: list of unmatched events of the opposite type of - * netEvent - * fieldOffset: offset of the NetEvent field in the Packet struct for the - * field of the type of netEvent - * oppositeFieldOffset: offset of the NetEvent field in the Packet struct - * for the field of the opposite type of netEvent + * event + * fieldOffset: offset of the Event field in the Message struct for the + * field of the type of event + * oppositeFieldOffset: offset of the Event field in the Message struct + * for the field of the opposite type of event */ -static void matchEvents(SyncState* const syncState, NetEvent* const event, +static void matchEvents(SyncState* const syncState, Event* const event, GHashTable* const unMatchedList, GHashTable* const unMatchedOppositeList, const size_t fieldOffset, const size_t oppositeFieldOffset) { - NetEvent* companionEvent; - Packet* packet; + Event* companionEvent; + Message* packet; MatchingDataTCP* matchingData; GQueue* conUnAcked; matchingData= (MatchingDataTCP*) syncState->matchingData; - companionEvent= g_hash_table_lookup(unMatchedOppositeList, event->packetKey); + companionEvent= g_hash_table_lookup(unMatchedOppositeList, event->event.tcpEvent->segmentKey); if (companionEvent != NULL) { g_debug("Found matching companion event, "); + // If it's there, remove it and create a Message + g_hash_table_steal(unMatchedOppositeList, event->event.tcpEvent->segmentKey); + packet= malloc(sizeof(Message)); + *((Event**) ((void*) packet + fieldOffset))= event; + *((Event**) ((void*) packet + oppositeFieldOffset))= companionEvent; + packet->print= &printTCPSegment; + // Both events can now share the same segmentKey + free(packet->outE->event.tcpEvent->segmentKey); + packet->outE->event.tcpEvent->segmentKey= packet->inE->event.tcpEvent->segmentKey; + if (syncState->stats) { matchingData->stats->totPacket++; + matchingData->stats->totMessageArray[packet->inE->traceNum][packet->outE->traceNum]++; } - // If it's there, remove it and create a Packet - g_hash_table_steal(unMatchedOppositeList, event->packetKey); - packet= malloc(sizeof(Packet)); - *((NetEvent**) ((void*) packet + fieldOffset))= event; - *((NetEvent**) ((void*) packet + oppositeFieldOffset))= companionEvent; - // Both events can now share the same packetKey - free(packet->outE->packetKey); - packet->outE->packetKey= packet->inE->packetKey; - packet->acks= NULL; - // Discard loopback traffic if (packet->inE->traceNum == packet->outE->traceNum) { - destroyPacket(packet); + destroyTCPSegment(packet); return; } - if (syncState->analysisModule->analyzePacket) + if (syncState->graphs) { - syncState->analysisModule->analyzePacket(syncState, packet); + writeMessagePoint(matchingData->messagePoints[packet->inE->traceNum][packet->outE->traceNum], + packet); + } + + if (syncState->analysisModule->analyzeMessage != NULL) + { + syncState->analysisModule->analyzeMessage(syncState, packet); } // We can skip the rest of the algorithm if the analysis module is not // interested in exchanges - if (!syncState->analysisModule->analyzeExchange) + if (syncState->analysisModule->analyzeExchange == NULL) { - destroyPacket(packet); + destroyTCPSegment(packet); return; } @@ -339,15 +397,18 @@ static void matchEvents(SyncState* const syncState, NetEvent* const event, ConnectionKey oppositeConnectionKey; buildReversedConnectionKey(&oppositeConnectionKey, - &event->packetKey->connectionKey); + &event->event.tcpEvent->segmentKey->connectionKey); conUnAcked= g_hash_table_lookup(matchingData->unAcked, &oppositeConnectionKey); if (conUnAcked != NULL) { - Packet* ackedPacket; + Message* ackedPacket; GList* result; + Exchange* exchange; + + exchange= NULL; - result= g_queue_find_custom(conUnAcked, packet, &gcfPacketAckCompare); + result= g_queue_find_custom(conUnAcked, packet, &gcfTCPSegmentAckCompare); while (result != NULL) { @@ -355,7 +416,7 @@ static void matchEvents(SyncState* const syncState, NetEvent* const event, // and keep it for later offset calculations g_debug("Found matching unAcked packet, "); - ackedPacket= (Packet*) result->data; + ackedPacket= (Message*) result->data; g_queue_delete_link(conUnAcked, result); if (syncState->stats) @@ -363,28 +424,30 @@ static void matchEvents(SyncState* const syncState, NetEvent* const event, matchingData->stats->totExchangeEffective++; } - if (packet->acks == NULL) + if (exchange == NULL) { - packet->acks= g_queue_new(); + exchange= malloc(sizeof(Exchange)); + exchange->message= packet; + exchange->acks= g_queue_new(); } - g_queue_push_tail(packet->acks, ackedPacket); + g_queue_push_tail(exchange->acks, ackedPacket); result= g_queue_find_custom(conUnAcked, packet, - &gcfPacketAckCompare); + &gcfTCPSegmentAckCompare); } // It might be possible to do an offset calculation - if (packet->acks != NULL) + if (exchange != NULL) { - ackedPacket= g_queue_peek_tail(packet->acks); + ackedPacket= g_queue_peek_tail(exchange->acks); if (ackedPacket->outE->traceNum != packet->inE->traceNum || ackedPacket->inE->traceNum != packet->outE->traceNum || packet->inE->traceNum == packet->outE->traceNum) { - printPacket(ackedPacket); - printPacket(packet); + ackedPacket->print(ackedPacket); + packet->print(packet); g_error("Disorganized exchange encountered during " "synchronization"); } @@ -396,8 +459,11 @@ static void matchEvents(SyncState* const syncState, NetEvent* const event, } syncState->analysisModule->analyzeExchange(syncState, - packet); + exchange); } + + exchange->message= NULL; + destroyTCPExchange(exchange); } } } @@ -412,13 +478,13 @@ static void matchEvents(SyncState* const syncState, NetEvent* const event, // If this packet will generate an ack, add it to the unAcked list g_debug("Adding to unAcked, "); conUnAcked= g_hash_table_lookup(matchingData->unAcked, - &event->packetKey->connectionKey); + &event->event.tcpEvent->segmentKey->connectionKey); if (conUnAcked == NULL) { ConnectionKey* connectionKey; connectionKey= malloc(sizeof(ConnectionKey)); - memcpy(connectionKey, &event->packetKey->connectionKey, + memcpy(connectionKey, &event->event.tcpEvent->segmentKey->connectionKey, sizeof(ConnectionKey)); g_hash_table_insert(matchingData->unAcked, connectionKey, conUnAcked= g_queue_new()); @@ -427,7 +493,7 @@ static void matchEvents(SyncState* const syncState, NetEvent* const event, } else { - destroyPacket(packet); + destroyTCPSegment(packet); } } else @@ -435,7 +501,7 @@ static void matchEvents(SyncState* const syncState, NetEvent* const event, // If there's no corresponding event, add the event to the unmatched // list for this type of event g_debug("Adding to unmatched event list, "); - g_hash_table_replace(unMatchedList, event->packetKey, event); + g_hash_table_replace(unMatchedList, event->event.tcpEvent->segmentKey, event); } } @@ -443,13 +509,16 @@ static void matchEvents(SyncState* const syncState, NetEvent* const event, /* * Check if a packet is an acknowledge * + * Args: + * packet TCP Message + * * Returns: * true if it is, * false otherwise */ -static bool isAck(const Packet* const packet) +static bool isAck(const Message* const packet) { - if (packet->inE->packetKey->ack == 1) + if (packet->inE->event.tcpEvent->segmentKey->ack == 1) { return true; } @@ -464,15 +533,18 @@ static bool isAck(const Packet* const packet) * Check if a packet will increment the sequence number, thus needing an * acknowledge * + * Args: + * packet TCP Message + * * Returns: * true if the packet will need an acknowledge * false otherwise */ -static bool needsAck(const Packet* const packet) +static bool needsAck(const Message* const packet) { - if (packet->inE->packetKey->syn || packet->inE->packetKey->fin || - packet->inE->packetKey->tot_len - packet->inE->packetKey->ihl * 4 - - packet->inE->packetKey->doff * 4 > 0) + if (packet->inE->event.tcpEvent->segmentKey->syn || packet->inE->event.tcpEvent->segmentKey->fin || + packet->inE->event.tcpEvent->segmentKey->tot_len - packet->inE->event.tcpEvent->segmentKey->ihl * 4 - + packet->inE->event.tcpEvent->segmentKey->doff * 4 > 0) { return true; } @@ -499,3 +571,146 @@ static void buildReversedConnectionKey(ConnectionKey* const reversedConnectionKey->source= connectionKey->dest; reversedConnectionKey->dest= connectionKey->source; } + + +/* + * Create and open files used to store message points to genereate + * graphs. Allocate and populate array to store file pointers. + * + * Args: + * syncState: container for synchronization data + */ +static void openGraphDataFiles(SyncState* const syncState) +{ + unsigned int i, j; + int retval; + char* cwd; + char name[29]; + MatchingDataTCP* matchingData; + + matchingData= (MatchingDataTCP*) syncState->matchingData; + + cwd= changeToGraphDir(syncState->graphs); + + matchingData->messagePoints= malloc(syncState->traceNb * sizeof(FILE**)); + for (i= 0; i < syncState->traceNb; i++) + { + matchingData->messagePoints[i]= malloc(syncState->traceNb * + sizeof(FILE*)); + for (j= 0; j < syncState->traceNb; j++) + { + if (i != j) + { + retval= snprintf(name, sizeof(name), + "matching_tcp-%03u_to_%03u.data", j, i); + if (retval > sizeof(name) - 1) + { + name[sizeof(name) - 1]= '\0'; + } + if ((matchingData->messagePoints[i][j]= fopen(name, "w")) == + NULL) + { + g_error(strerror(errno)); + } + } + } + } + + retval= chdir(cwd); + if (retval == -1) + { + g_error(strerror(errno)); + } + free(cwd); +} + + +/* + * Write a message point to a file used to generate graphs + * + * Args: + * stream: FILE*, file pointer where to write the point + * message: message for which to write the point + */ +static void writeMessagePoint(FILE* stream, const Message* const message) +{ + LttCycleCount x, y; + + if (message->inE->traceNum < message->outE->traceNum) + { + // CA is inE->traceNum + x= message->inE->cpuTime; + y= message->outE->cpuTime; + } + else + { + // CA is outE->traceNum + x= message->outE->cpuTime; + y= message->inE->cpuTime; + } + + fprintf(stream, "%20llu %20llu\n", x, y); +} + + +/* + * Close files used to store convex hull points to genereate graphs. + * Deallocate array to store file pointers. + * + * Args: + * syncState: container for synchronization data + */ +static void closeGraphDataFiles(SyncState* const syncState) +{ + unsigned int i, j; + MatchingDataTCP* matchingData; + int retval; + + matchingData= (MatchingDataTCP*) syncState->matchingData; + + if (matchingData->messagePoints == NULL) + { + return; + } + + for (i= 0; i < syncState->traceNb; i++) + { + for (j= 0; j < syncState->traceNb; j++) + { + if (i != j) + { + retval= fclose(matchingData->messagePoints[i][j]); + if (retval != 0) + { + g_error(strerror(errno)); + } + } + } + free(matchingData->messagePoints[i]); + } + free(matchingData->messagePoints); + + matchingData->messagePoints= NULL; +} + + +/* + * Write the matching-specific graph lines in the gnuplot script. + * + * Args: + * stream: stream where to write the data + * syncState: container for synchronization data + * i: first trace number + * j: second trace number, garanteed to be larger than i + */ +static void writeMatchingGraphsPlotsTCP(FILE* stream, SyncState* const + syncState, const unsigned int i, const unsigned int j) +{ + fprintf(stream, + "\t\"matching_tcp-%1$03d_to_%2$03d.data\" " + "title \"Sent messages\" with points linetype 4 " + "linecolor rgb \"#98fc66\" pointtype 9 pointsize 2, \\\n" + "\t\"matching_tcp-%2$03d_to_%1$03d.data\" " + "title \"Received messages\" with points linetype 4 " + "linecolor rgb \"#6699cc\" pointtype 11 pointsize 2, \\\n", i, j); +}