Perform factor reduction as a modular step
[lttv.git] / lttv / lttv / sync / data_structures.c
CommitLineData
70407e86 1/* This file is part of the Linux Trace Toolkit viewer
277e5b53 2 * Copyright (C) 2009, 2010 Benjamin Poirier <benjamin.poirier@polymtl.ca>
70407e86 3 *
277e5b53
BP
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License as published by
6 * the Free Software Foundation, either version 2.1 of the License, or (at
7 * your option) any later version.
70407e86 8 *
277e5b53
BP
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
12 * License for more details.
70407e86 13 *
277e5b53
BP
14 * You should have received a copy of the GNU Lesser General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
70407e86
BP
16 */
17
18#ifdef HAVE_CONFIG_H
19#include <config.h>
20#endif
21
22#include <arpa/inet.h>
23#include <glib.h>
24#include <stdint.h>
25#include <stdio.h>
26#include <stdlib.h>
27#include <string.h>
28
08365995
BP
29#include <unistd.h>
30
70407e86
BP
31#include "lookup3.h"
32
10341d26 33#include "data_structures.h"
70407e86
BP
34
35
70407e86
BP
36// TCP sequence numbers use clock arithmetic, these comparison functions take
37// that into account
38#define SEQ_LT(a,b) ((int32_t)((a)-(b)) < 0)
39#define SEQ_LEQ(a,b) ((int32_t)((a)-(b)) <= 0)
40#define SEQ_GT(a,b) ((int32_t)((a)-(b)) > 0)
41#define SEQ_GEQ(a,b) ((int32_t)((a)-(b)) >= 0)
42
0a87ec9a
BP
43const char* const approxNames[]= {
44 [EXACT]= "Exact",
45 [ACCURATE]= "Accurate",
46 [APPROXIMATE]= "Approximate",
47 [INCOMPLETE]= "Incomplete",
48 [ABSENT]= "Absent",
49 [SCREWED]= "Screwed",
50};
51
70407e86
BP
52
53/*
54 * Compare two ConnectionKey structures
55 *
56 * Returns:
57 * true if each field of the structure is equal
58 * false otherwise
59 */
60bool connectionKeyEqual(const ConnectionKey* const a, const
61 ConnectionKey* const b)
62{
63 if (a->saddr == b->saddr && a->daddr == b->daddr && a->source == b->source
64 && a->dest == b->dest)
65 {
66 return true;
67 }
68 else
69 {
70 return false;
71 }
72}
73
74
75/*
76 * Check if a packet is an acknowledge of another packet.
77 *
78 * Args:
10341d26
BP
79 * ackSegment packet that is the confirmation
80 * ackedSegment packet that contains the original data, both packets have to
81 * come from the same direction of the same connection. Both
82 * messages have to contain TCP events.
70407e86 83 */
10341d26
BP
84bool isAcking(const Message* const ackSegment, const Message* const
85 ackedSegment)
70407e86 86{
10341d26
BP
87 g_assert(ackSegment->inE->type == TCP);
88 g_assert(ackSegment->outE->type == TCP);
89
90 if (SEQ_GT(ackSegment->inE->event.tcpEvent->segmentKey->ack_seq,
91 ackedSegment->inE->event.tcpEvent->segmentKey->seq))
70407e86
BP
92 {
93 return true;
94 }
95 else
96 {
97 return false;
98 }
99}
100
101
102/*
103 * Convert an IP address from 32 bit form to dotted quad
104 *
105 * Args:
d4721e1a 106 * str: A preallocated string of length >= 16
70407e86
BP
107 * addr: Address
108 */
109void convertIP(char* const str, const uint32_t addr)
110{
d4721e1a 111 strcpy(str, inet_ntoa((struct in_addr) {.s_addr= addr}));
70407e86
BP
112}
113
114
115/*
10341d26 116 * Print the content of a TCP Message structure
70407e86 117 */
10341d26 118void printTCPSegment(const Message* const segment)
70407e86 119{
d4721e1a 120 char saddr[16], daddr[16];
10341d26
BP
121 SegmentKey* segmentKey;
122
123 g_assert(segment->inE->type == TCP);
124 g_assert(segment->inE->event.tcpEvent->segmentKey ==
125 segment->outE->event.tcpEvent->segmentKey);
70407e86 126
10341d26 127 segmentKey= segment->inE->event.tcpEvent->segmentKey;
70407e86 128
10341d26
BP
129 convertIP(saddr, segmentKey->connectionKey.saddr);
130 convertIP(daddr, segmentKey->connectionKey.daddr);
70407e86
BP
131 g_debug("%s:%u to %s:%u tot_len: %u ihl: %u seq: %u ack_seq: %u doff: %u "
132 "ack: %u rst: %u syn: %u fin: %u", saddr,
10341d26
BP
133 segmentKey->connectionKey.source, daddr, segmentKey->connectionKey.dest,
134 segmentKey->tot_len, segmentKey->ihl, segmentKey->seq,
135 segmentKey->ack_seq, segmentKey->doff, segmentKey->ack, segmentKey->rst,
136 segmentKey->syn, segmentKey->fin);
70407e86
BP
137}
138
139
140/*
141 * A GHashFunc for g_hash_table_new()
142 *
10341d26
BP
143 * This function is for indexing TCPEvents in unMatched lists. All fields of
144 * the corresponding SegmentKey must match for two keys to be equal.
70407e86
BP
145 *
146 * Args:
10341d26
BP
147 * key SegmentKey*
148 *
149 * Returns:
150 * A hash of all fields in the SegmentKey
70407e86 151 */
10341d26 152guint ghfSegmentKeyHash(gconstpointer key)
70407e86 153{
10341d26 154 const SegmentKey* p;
70407e86
BP
155 uint32_t a, b, c;
156
10341d26 157 p= (SegmentKey*) key;
70407e86
BP
158
159 a= p->connectionKey.source + (p->connectionKey.dest << 16);
160 b= p->connectionKey.saddr;
161 c= p->connectionKey.daddr;
162 mix(a, b, c);
163
164 a+= p->ihl + (p->tot_len << 8) + (p->doff << 24);
165 b+= p->seq;
166 c+= p->ack_seq;
167 mix(a, b, c);
168
169 a+= p->ack + (p->rst << 8) + (p->syn << 16) + (p->fin << 24);
170 final(a, b, c);
171
10341d26
BP
172 g_debug("segment key hash %p: %u", p, c);
173
70407e86
BP
174 return c;
175}
176
177
178/*
179 * A GEqualFunc for g_hash_table_new()
180 *
10341d26
BP
181 * This function is for indexing TCPEvents in unMatched lists. All fields of
182 * the corresponding SegmentKey must match for two keys to be equal.
70407e86
BP
183 *
184 * Args:
10341d26 185 * a, b SegmentKey*
70407e86
BP
186 *
187 * Returns:
188 * TRUE if both values are equal
189 */
10341d26 190gboolean gefSegmentKeyEqual(gconstpointer a, gconstpointer b)
70407e86 191{
10341d26
BP
192 const SegmentKey* sA, * sB;
193
194 sA= (SegmentKey*) a;
195 sB= (SegmentKey*) b;
196
197 if (connectionKeyEqual(&sA->connectionKey, &sB->connectionKey) &&
198 sA->ihl == sB->ihl &&
199 sA->tot_len == sB->tot_len &&
200 sA->seq == sB->seq &&
201 sA->ack_seq == sB->ack_seq &&
202 sA->doff == sB->doff &&
203 sA->ack == sB->ack &&
204 sA->rst == sB->rst &&
205 sA->syn == sB->syn &&
206 sA->fin == sB->fin)
70407e86 207 {
10341d26 208 g_debug("segment key equal %p %p: TRUE", sA, sB);
70407e86
BP
209 return TRUE;
210 }
211 else
212 {
10341d26 213 g_debug("segment key equal %p %p: FALSE", sA, sB);
70407e86
BP
214 return FALSE;
215 }
216}
217
218
219/*
220 * A GDestroyNotify function for g_hash_table_new_full()
221 *
222 * Args:
10341d26 223 * data: Event*
70407e86 224 */
10341d26 225void gdnDestroyEvent(gpointer data)
70407e86 226{
10341d26
BP
227 Event* event= data;
228
229 event->destroy(event);
70407e86
BP
230}
231
232
233/*
234 * A GDestroyNotify function for g_hash_table_new_full()
235 *
236 * Args:
237 * data: GQueue* list[Packet]
238 */
10341d26 239void gdnTCPSegmentListDestroy(gpointer data)
70407e86
BP
240{
241 GQueue* list;
242
243 list= (GQueue*) data;
244
10341d26 245 g_queue_foreach(list, &gfTCPSegmentDestroy, NULL);
70407e86
BP
246 g_queue_free(list);
247}
248
249
250/*
251 * A GFunc for g_queue_foreach()
252 *
253 * Args:
10341d26 254 * data Message*, TCP message to destroy
70407e86
BP
255 * user_data NULL
256 */
10341d26 257void gfTCPSegmentDestroy(gpointer data, gpointer user_data)
70407e86 258{
10341d26 259 destroyTCPSegment((Message*) data);
70407e86
BP
260}
261
262
263/*
10341d26 264 * Free the memory used by a TCP Message and the memory of all its associated
70407e86 265 * resources
10341d26
BP
266 *
267 * Args:
268 * segment TCP Message to destroy
70407e86 269 */
10341d26 270void destroyTCPSegment(Message* const segment)
70407e86 271{
10341d26
BP
272 TCPEvent* inE, *outE;
273
10341d26 274 segment->print(segment);
70407e86 275
10341d26
BP
276 g_assert(segment->inE != NULL && segment->outE != NULL);
277 g_assert(segment->inE->type == TCP && segment->outE->type == TCP);
278 inE= segment->inE->event.tcpEvent;
279 outE= segment->outE->event.tcpEvent;
280 g_assert(inE->segmentKey == outE->segmentKey);
70407e86 281
10341d26 282 outE->segmentKey= NULL;
70407e86 283
10341d26
BP
284 destroyTCPEvent(segment->inE);
285 destroyTCPEvent(segment->outE);
70407e86 286
10341d26
BP
287 free(segment);
288}
289
290
291/*
292 * Free the memory used by a TCP Exchange and the memory of SOME of its
293 * associated resources. The message is not destroyed. Use destroyTCPSegment()
294 * to free it.
295 *
296 * Args:
297 * exchange TCP Exchange to destroy. The .message must be NULL
298 */
299void destroyTCPExchange(Exchange* const exchange)
300{
301 g_assert(exchange->message == NULL);
302
303 if (exchange->acks != NULL)
70407e86 304 {
10341d26
BP
305 g_queue_foreach(exchange->acks, &gfTCPSegmentDestroy, NULL);
306 g_queue_free(exchange->acks);
70407e86
BP
307 }
308
10341d26 309 free(exchange);
70407e86
BP
310}
311
312
313/*
10341d26 314 * Free the memory used by a TCP Event and its associated resources
70407e86 315 */
10341d26 316void destroyTCPEvent(Event* const event)
70407e86 317{
10341d26 318 g_assert(event->type == TCP);
70407e86 319
10341d26 320 if (event->event.tcpEvent->segmentKey != NULL)
70407e86 321 {
10341d26 322 free(event->event.tcpEvent->segmentKey);
70407e86 323 }
10341d26
BP
324 free(event->event.tcpEvent);
325 event->event.tcpEvent= NULL;
326 destroyEvent(event);
327}
328
d4721e1a 329
10341d26
BP
330/*
331 * Free the memory used by a base Event
332 */
333void destroyEvent(Event* const event)
334{
335 g_assert(event->event.tcpEvent == NULL);
336
70407e86
BP
337 free(event);
338}
339
340
10341d26
BP
341/*
342 * Free the memory used by a UDP Event and its associated resources
343 */
344void destroyUDPEvent(Event* const event)
345{
346 g_assert(event->type == UDP);
347
348 if (event->event.udpEvent->datagramKey != NULL)
349 {
350 free(event->event.udpEvent->datagramKey);
351 }
352 free(event->event.udpEvent);
353 event->event.udpEvent= NULL;
354 destroyEvent(event);
355}
356
357
70407e86
BP
358/*
359 * A GCompareFunc for g_queue_find_custom()
360 *
361 * Args:
10341d26
BP
362 * a Message* acked packet
363 * b Message* ack packet
70407e86
BP
364 *
365 * Returns:
366 * 0 if b acks a
367 */
10341d26 368gint gcfTCPSegmentAckCompare(gconstpointer a, gconstpointer b)
70407e86 369{
10341d26 370 if (isAcking((const Message*) b, (const Message*) a))
70407e86
BP
371 {
372 return 0;
373 }
374 else
375 {
376 return 1;
377 }
378}
379
380
381/*
382 * A GHashFunc for g_hash_table_new()
383 *
384 * Hash TCP connection keys. Here are a few possible implementations:
385 *
386 * 2.4 kernels used tcp_hashfn()
387 *
388 * I've seen something about an XOR hash:
389 * http://tservice.net.ru/~s0mbre/blog/2006/05/14#2006_05_14:
390 * unsigned int h = (laddr ^ lport) ^ (faddr ^ fport);
391 * h ^= h >> 16;
392 * h ^= h >> 8;
393 * return h;
394 *
395 * In 2.6 kernels, inet_ehashfn() handles connection hashing with the help of
396 * Jenkins hashing, jhash.h
397 *
398 * This function uses jenkins hashing. The hash is not the same for packets in
399 * opposite directions of the same connection. (Hence the name
400 * connection*key*hash)
401 *
402 * Args:
403 * key ConnectionKey*
404 */
405guint ghfConnectionKeyHash(gconstpointer key)
406{
407 ConnectionKey* connectionKey;
408 uint32_t a, b, c;
409
410 connectionKey= (ConnectionKey*) key;
411
412 a= connectionKey->source + (connectionKey->dest << 16);
413 b= connectionKey->saddr;
414 c= connectionKey->daddr;
415 final(a, b, c);
416
417 return c;
418}
419
420
421/*
422 * A GEqualFunc for g_hash_table_new()
423 *
424 * Args:
425 * a, b ConnectionKey*
426 *
427 * Returns:
428 * TRUE if both values are equal
429 */
430gboolean gefConnectionKeyEqual(gconstpointer a, gconstpointer b)
431{
432 // Two packets in the same direction
433 if (connectionKeyEqual((const ConnectionKey*) a, (const ConnectionKey*) b))
434 {
435 return TRUE;
436 }
437 else
438 {
439 return FALSE;
440 }
441}
442
443
444/*
445 * A GDestroyNotify function for g_hash_table_new_full()
446 *
447 * Args:
448 * data: ConnectionKey*
449 */
450void gdnConnectionKeyDestroy(gpointer data)
451{
452 free((ConnectionKey*) data);
453}
f6691532
BP
454
455
456/*
457 * A GHashFunc for g_hash_table_new()
458 *
459 * Args:
460 * key DatagramKey*
461 */
462guint ghfDatagramKeyHash(gconstpointer key)
463{
464 DatagramKey* datagramKey;
1d3e6a04
BP
465 union {
466 uint8_t byteKey[8];
467 uint32_t hashableKey[2];
468 } dataKey;
f6691532
BP
469 uint32_t a, b, c;
470
471 datagramKey= (DatagramKey*) key;
1d3e6a04 472 memcpy(dataKey.byteKey, datagramKey->dataKey, sizeof(dataKey.byteKey));
f6691532
BP
473
474 a= datagramKey->saddr;
475 b= datagramKey->daddr;
476 c= datagramKey->source + (datagramKey->dest << 16);
477 mix(a, b, c);
478
479 a+= datagramKey->ulen; // 16 bits left here
1d3e6a04
BP
480 b+= dataKey.hashableKey[0];
481 c+= dataKey.hashableKey[1];
f6691532
BP
482 final(a, b, c);
483
484 return c;
485}
486
487
488/*
489 * A GEqualFunc for g_hash_table_new()
490 *
491 * Args:
492 * a, b DatagramKey*
493 *
494 * Returns:
495 * TRUE if both values are equal
496 */
497gboolean gefDatagramKeyEqual(gconstpointer a, gconstpointer b)
498{
499 const DatagramKey* dA, * dB;
500
501 dA= (DatagramKey*) a;
502 dB= (DatagramKey*) b;
503
504 if (dA->saddr == dB->saddr && dA->daddr == dB->daddr &&
505 dA->source == dB->source && dA->dest == dB->dest &&
506 dA->ulen == dB->ulen &&
507 memcmp(dA->dataKey, dB->dataKey, sizeof(dA->dataKey)) == 0)
508 {
509 return TRUE;
510 }
511 else
512 {
513 return FALSE;
514 }
515}
516
517
518/*
519 * A GDestroyNotify function for g_hash_table_new_full()
520 *
521 * Args:
522 * data: DatagramKey*
523 */
524void gdnDestroyDatagramKey(gpointer data)
525{
526 free((DatagramKey*) data);
527}
528
529
530/*
531 * A GDestroyNotify function for g_hash_table_new_full()
532 *
533 * Args:
534 * data: Broadcast*
535 */
536void gdnDestroyBroadcast(gpointer data)
537{
538 destroyBroadcast((Broadcast*) data);
539}
540
541
542/*
543 * Free a Broadcast struct and its associated ressources
544 *
545 * Args:
546 * broadcast: Broadcast*
547 */
548void destroyBroadcast(Broadcast* const broadcast)
549{
550 g_queue_foreach(broadcast->events, &gfDestroyEvent, NULL);
d4721e1a 551 g_queue_free(broadcast->events);
f6691532
BP
552 free(broadcast);
553}
554
555
556/*
557 * A GFunc for g_queue_foreach()
558 *
559 * Args:
560 * data Event*
561 * user_data NULL
562 */
563void gfDestroyEvent(gpointer data, gpointer user_data)
564{
565 Event* event= data;
566
567 event->destroy(event);
568}
76be6fc2
BP
569
570
571/* Subtract two WallTime structs
572 *
573 * Args:
574 * tA, tB: WallTime
575 *
576 * Returns:
577 * The result of tA - tB, as a double. This may incur a loss of
578 * precision.
579 */
580double wallTimeSub(const WallTime const* tA, const WallTime const* tB)
581{
d4721e1a
BP
582 return (double) tA->seconds - tB->seconds + ((double) tA->nanosec - tB->nanosec) / 1e9;
583}
584
585
586/*
587 * Allocate and copy a base event
588 *
589 * Args:
590 * newEvent: new event, pointer will be updated
591 * event: event to copy
592 */
593void copyEvent(const Event* const event, Event** const newEvent)
594{
595 g_assert(event->event.tcpEvent == NULL);
596
597 *newEvent= malloc(sizeof(Event));
598 memcpy(*newEvent, event, sizeof(Event));
599}
600
601
602/*
603 * Allocate and copy a TCP event
604 *
605 * Args:
606 * newEvent: new event, pointer will be updated
607 * event: event to copy
608 */
609void copyTCPEvent(const Event* const event, Event** const newEvent)
610{
611 g_assert(event->type == TCP);
612
613 *newEvent= malloc(sizeof(Event));
614 memcpy(*newEvent, event, sizeof(Event));
615
616 (*newEvent)->event.tcpEvent= malloc(sizeof(TCPEvent));
617 memcpy((*newEvent)->event.tcpEvent, event->event.tcpEvent,
618 sizeof(TCPEvent));
619
620 (*newEvent)->event.tcpEvent->segmentKey= malloc(sizeof(SegmentKey));
621 memcpy((*newEvent)->event.tcpEvent->segmentKey,
622 event->event.tcpEvent->segmentKey, sizeof(SegmentKey));
623}
624
625
626/*
627 * Allocate and copy a UDP event
628 *
629 * Args:
630 * newEvent: new event, pointer will be updated
631 * event: event to copy
632 */
633void copyUDPEvent(const Event* const event, Event** const newEvent)
634{
635 g_assert(event->type == UDP);
636
637 *newEvent= malloc(sizeof(Event));
638 memcpy(*newEvent, event, sizeof(Event));
639
640 (*newEvent)->event.udpEvent= malloc(sizeof(UDPEvent));
641 memcpy((*newEvent)->event.udpEvent, event->event.udpEvent,
642 sizeof(UDPEvent));
643
644 (*newEvent)->event.udpEvent->datagramKey= malloc(sizeof(DatagramKey));
645 memcpy((*newEvent)->event.udpEvent->datagramKey,
646 event->event.udpEvent->datagramKey, sizeof(DatagramKey));
76be6fc2 647}
66eaf2eb
BP
648
649
650/*
651 * A GFunc for g_queue_foreach()
652 *
653 * Args:
654 * data Event*, event to add
655 * user_data GArray*, array to add to
656 */
657void gfAddEventToArray(gpointer data, gpointer user_data)
658{
659 g_array_append_val((GArray*) user_data, data);
660}
0a87ec9a
BP
661
662
663/*
664 * Free a PairFactors
665 *
666 * Args:
667 * factorsCHull: container of Factors
668 */
669void destroyPairFactors(PairFactors* pairFactors)
670{
671 if (pairFactors->min != NULL)
672 {
673 free(pairFactors->min);
674 }
675 if (pairFactors->max != NULL)
676 {
677 free(pairFactors->max);
678 }
679 if (pairFactors->approx != NULL)
680 {
681 free(pairFactors->approx);
682 }
683}
684
685
686/*
687 * Create and initialize a container of PairFactors
688 *
689 * Args:
690 * traceNb: number of traces
691 *
692 * Returns:
693 * A new array, which can be freed with freeAllFactors()
694 */
695AllFactors* createAllFactors(const unsigned int traceNb)
696{
697 AllFactors* allFactors;
698 PairFactors** factorsArray;
699 unsigned int i, j;
700
701 allFactors= malloc(sizeof(AllFactors));
0a87ec9a
BP
702 allFactors->refCount= 1;
703 allFactors->pairFactors= malloc(traceNb * sizeof(PairFactors*));
704 factorsArray=allFactors->pairFactors;
705 for (i= 0; i < traceNb; i++)
706 {
707 factorsArray[i]= calloc(traceNb, sizeof(PairFactors));
708
709 for (j= 0; j < traceNb; j++)
710 {
711 if (i == j)
712 {
713 factorsArray[i][i].type= EXACT;
714 factorsArray[i][i].approx= malloc(sizeof(Factors));
715 factorsArray[i][i].approx->drift= 1.;
716 factorsArray[i][i].approx->offset= 0.;
717 }
718 else
719 {
720 factorsArray[i][j].type= ABSENT;
721 }
722 }
723 }
724
725 return allFactors;
726}
727
728
729/*
730 * Free a container of PairFactors
731 *
732 * Args:
0a87ec9a 733 * allFactors: container of PairFactors
b2da0724 734 * traceNb: number of traces
0a87ec9a 735 */
b2da0724 736void freeAllFactors(AllFactors* const allFactors, const unsigned int traceNb)
0a87ec9a
BP
737{
738 unsigned int i, j;
0a87ec9a
BP
739
740 allFactors->refCount--;
741
742 if (allFactors->refCount == 0)
743 {
744 for (i= 0; i < traceNb; i++)
745 {
746 for (j= 0; j < traceNb; j++)
747 {
748 destroyPairFactors(&allFactors->pairFactors[i][j]);
749 }
750 free(allFactors->pairFactors[i]);
751 }
752 free(allFactors->pairFactors);
753 free(allFactors);
754 }
755}
This page took 0.056959 seconds and 4 git commands to generate.