Skip to content

Commit

Permalink
Stop forwarding trace when loop is found
Browse files Browse the repository at this point in the history
  • Loading branch information
michielbdejong committed Apr 19, 2024
1 parent 5c34bbb commit 65f4986
Show file tree
Hide file tree
Showing 7 changed files with 17,415 additions and 1,333 deletions.
16,897 changes: 15,682 additions & 1,215 deletions __tests__/fixtures/batched-giraffe-hourglass.json

Large diffs are not rendered by default.

1,748 changes: 1,662 additions & 86 deletions __tests__/fixtures/batched-giraffe-hourglass.puml

Large diffs are not rendered by default.

21 changes: 17 additions & 4 deletions __tests__/fixtures/batched-giraffe-triangle.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
"[Bob]->[Charlie] okay-to-send-probes",
"[Bob]->[Alice] trace genRanHex0 genRanHex1 genRanHex2",
"[---]->[---] ---",
"[Alice]->[Charlie] trace genRanHex0 genRanHex1 genRanHex2",
"[---]->[---] ---",
"[---]->[---] ---"
],
"probes": {
Expand Down Expand Up @@ -62,11 +64,17 @@
"[Node#receiveMessage] Alice receives message from Charlie",
"[TraceEngine] handling trace message from Charlie: trace genRanHex0 genRanHex1 genRanHex3",
"[Node#lookup-probe] Alice is looking up probe genRanHex0",
"[TraceEngine] in the context of trace message from Charlie: trace genRanHex0 genRanHex1 genRanHex3, we found these upstreams: [], and otherLeg undefined",
"[TraceEngine] forwarding a counter-probe-wise trace message from Charlie: trace genRanHex0 genRanHex1 genRanHex3",
"Looking for other leg genRanHex0 genRanHex1 genRanHex3 in {\"Charlie\":\"genRanHex3\"}",
"[TraceEngine] in the context of trace message from Charlie: trace genRanHex0 genRanHex1 genRanHex3, we found these counter-probe-wise next hops: [], and otherLeg undefined",
"[Node#receiveMessage] Alice receives message from Bob",
"[TraceEngine] handling trace message from Bob: trace genRanHex0 genRanHex1 genRanHex2",
"[Node#lookup-probe] Alice is looking up probe genRanHex0",
"[TraceEngine] in the context of trace message from Bob: trace genRanHex0 genRanHex1 genRanHex2, we found these upstreams: [], and otherLeg undefined"
"[TraceEngine] forwarding a counter-probe-wise trace message from Bob: trace genRanHex0 genRanHex1 genRanHex2",
"Looking for other leg genRanHex0 genRanHex1 genRanHex2 in {\"Charlie\":\"genRanHex3\",\"Bob\":\"genRanHex2\"}",
"[TraceEngine] in the context of trace message from Bob: trace genRanHex0 genRanHex1 genRanHex2, we found these counter-probe-wise next hops: [], and otherLeg Charlie",
"[TracesEngine] found otherLeg Charlie for trace genRanHex1 of probe genRanHex0",
"[Node#sendTraceMessage] Alice sends trace message to Charlie: trace genRanHex0 genRanHex1 genRanHex2"
],
"loopsFound": []
},
Expand Down Expand Up @@ -94,7 +102,9 @@
"[Node#receiveMessage] Bob receives message from Charlie",
"[TraceEngine] handling trace message from Charlie: trace genRanHex0 genRanHex1 genRanHex2",
"[Node#lookup-probe] Bob is looking up probe genRanHex0",
"[TraceEngine] in the context of trace message from Charlie: trace genRanHex0 genRanHex1 genRanHex2, we found these upstreams: [Alice], and otherLeg undefined",
"[TraceEngine] forwarding a counter-probe-wise trace message from Charlie: trace genRanHex0 genRanHex1 genRanHex2",
"Looking for other leg genRanHex0 genRanHex1 genRanHex2 in {\"Charlie\":\"genRanHex2\"}",
"[TraceEngine] in the context of trace message from Charlie: trace genRanHex0 genRanHex1 genRanHex2, we found these counter-probe-wise next hops: [Alice], and otherLeg undefined",
"[TracesEngine] sending message to Alice: trace genRanHex0 genRanHex1 genRanHex2",
"[Node#sendTraceMessage] Bob sends trace message to Alice: trace genRanHex0 genRanHex1 genRanHex2"
],
Expand Down Expand Up @@ -126,7 +136,10 @@
"[Node#receiveMessage] Charlie receives message from Alice",
"Charlie receives okay-to-send-probes from Alice",
"[Node#receiveMessage] Charlie receives message from Bob",
"Charlie receives okay-to-send-probes from Bob"
"Charlie receives okay-to-send-probes from Bob",
"[Node#receiveMessage] Charlie receives message from Alice",
"[TraceEngine] handling trace message from Alice: trace genRanHex0 genRanHex1 genRanHex2",
"loop-found genRanHex0 genRanHex1"
],
"loopsFound": []
}
Expand Down
1 change: 1 addition & 0 deletions __tests__/fixtures/batched-giraffe-triangle.puml
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ Alice -[#green]-> Charlie: probe genRanHex0
Charlie -[#green]-> Bob: trace genRanHex0 genRanHex1 genRanHex2
Charlie -[#green]-> Alice: trace genRanHex0 genRanHex1 genRanHex3
Bob -[#green]-> Alice: trace genRanHex0 genRanHex1 genRanHex2
Alice -[#green]-> Charlie: trace genRanHex0 genRanHex1 genRanHex2
@enduml
2 changes: 1 addition & 1 deletion __tests__/self-mending-for-giraffe-hourglass.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import { jest } from '@jest/globals';
import { readFileSync, writeFileSync } from 'fs';

const NUM_ROUNDS = 10;
const NUM_ROUNDS = 1000;
const TEST_NAME = 'batched-giraffe-hourglass';
const JSON_FILE = `__tests__/fixtures/${TEST_NAME}.json`;
const PUML_FILE = `__tests__/fixtures/${TEST_NAME}.puml`;
Expand Down
74 changes: 49 additions & 25 deletions src/engine/tracesengine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,45 +4,69 @@ import { genRanHex } from "../genRanHex.js";
export class TracesEngine extends EventEmitter {
tracesCreated = {};
tracesForwarded = {};
getLegs(probeId: string, traceId: string): { [to: string]: string } | undefined {
if (typeof this.tracesForwarded[probeId] === 'undefined') {
return undefined;
}
return this.tracesForwarded[probeId][traceId];
getLegsForwarded(probeId: string, traceId: string): { [to: string]: string } | undefined {
return this.tracesForwarded[probeId]?.[traceId];
}
getLegsCreated(probeId: string, traceId: string): { [to: string]: string } | undefined {
return this.tracesCreated[probeId]?.[traceId];
}
wasCreatedByUs(probeId: string, traceId: string): boolean {
return typeof this.getLegsCreated(probeId, traceId) !== 'undefined';
}
getOtherLeg(probeId: string, traceId: string, thisLegId: string): string | undefined {
const legs = this.getLegs(probeId, traceId);
const legs = this.getLegsForwarded(probeId, traceId);
this.emit('debug', `Looking for other leg ${probeId} ${traceId} ${thisLegId} in ${JSON.stringify(legs)}`);
if (typeof legs === 'undefined') {
return undefined;
}
return Object.keys(legs).find((to) => legs[to] !== thisLegId);
}
logTraceMessage(sender: string, probeId: string, traceId: string, legId: string): void {
if (typeof this.tracesForwarded[probeId] === 'undefined') {
this.tracesForwarded[probeId] = {};
}
if (typeof this.tracesForwarded[probeId][traceId] === 'undefined') {
this.tracesForwarded[probeId][traceId] = {};
}
this.tracesForwarded[probeId][traceId][sender] = legId;
}
forwardTraceMessage(probeId: string, traceId: string, legId: string, nextHops: string[]): void {
nextHops.forEach((from) => {
this.emit('debug', `[TracesEngine] sending message to ${from}: trace ${probeId} ${traceId} ${legId}`);
this.emit('message', from, `trace ${probeId} ${traceId} ${legId}`);
});
}
handleTraceMessage(sender: string, message: string): void {
this.emit('debug', `[TraceEngine] handling trace message from ${sender}: ${message}`);
const [messageType, probeId, traceId, legId] = message.split(' ');
if (this.wasCreatedByUs(probeId, traceId)) {
this.emit('debug', `loop-found ${probeId} ${traceId}`);
this.emit('loop-found', probeId, traceId);
return;
}
if (messageType !== 'trace') {
throw new Error(`expected trace message but got ${messageType}`);
}
this.emit('lookup-probe', probeId, (probeFrom: string[]) => {
const otherLeg = this.getOtherLeg(probeId, traceId, legId);
this.emit('debug', `[TraceEngine] in the context of trace message from ${sender}: ${message}, we found these upstreams: [${probeFrom.join(', ')}], and otherLeg ${otherLeg}`);
if (typeof otherLeg === 'undefined') {
const legs = {};
probeFrom.forEach((from) => {
legs[from] = legId;
this.emit('debug', `[TracesEngine] sending message to ${from}: trace ${probeId} ${traceId} ${legId}`);
this.emit('message', from, `trace ${probeId} ${traceId} ${legId}`);
});
if (typeof this.tracesForwarded[probeId] === 'undefined') {
this.tracesForwarded[probeId] = {};
this.logTraceMessage(sender,probeId, traceId, legId);
this.emit('lookup-probe', probeId, (probeFrom: string[], probeTo: string[]) => {
if (probeFrom.includes(sender)) {
this.emit('debug', `[TraceEngine] forwarding a probe-wise trace message from ${sender}: ${message}`);
this.forwardTraceMessage(probeId, traceId, legId, probeTo);
} else if (probeTo.includes(sender)) {
this.emit('debug', `[TraceEngine] forwarding a counter-probe-wise trace message from ${sender}: ${message}`);
const otherLeg = this.getOtherLeg(probeId, traceId, legId);
this.emit('debug', `[TraceEngine] in the context of trace message from ${sender}: ${message}, we found these counter-probe-wise next hops: [${probeFrom.join(', ')}], and otherLeg ${otherLeg}`);
if (typeof otherLeg === 'undefined') {
this.forwardTraceMessage(probeId, traceId, legId, probeFrom);
} else {
this.emit('debug', `[TracesEngine] found otherLeg ${otherLeg} for trace ${traceId} of probe ${probeId}`);
if (otherLeg === sender) {
this.emit('debug', `UNEXPECTED: Received two different legs from the same node`);
}
this.emit('message', otherLeg, `trace ${probeId} ${traceId} ${legId}`)
}
this.tracesForwarded[probeId][traceId] = legs;
} else {
this.emit('debug', `[TracesEngine] found otherLeg ${otherLeg} for trace ${traceId} of probe ${probeId}`);
if (otherLeg === sender) {
this.emit('debug', `UNEXPECTED: Received two different legs from the same node`);
}
// this.emit('message', otherLeg, `trace ${probeId} ${traceId} ${legId}`)
throw new Error(`received trace message '${message}' from unexpected sender ${sender}`);
}
});
}
Expand All @@ -59,7 +83,7 @@ export class TracesEngine extends EventEmitter {
if (typeof this.tracesCreated[probeId] === 'undefined') {
this.tracesCreated[probeId] = {};
}
this.tracesCreated[probeId][traceId] = legs;
this.tracesCreated[probeId][traceId] = legs;
});
}
}
Expand Down
5 changes: 3 additions & 2 deletions src/giraffe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,10 @@ export class Giraffe extends EventEmitter implements NetworkNode {
tracesengine.on('debug', (message: string) => {
this.debugLog.push(message);
});
tracesengine.on('lookup-probe', (probeId: string, callback: (probeFrom: string[]) => void) => {
tracesengine.on('lookup-probe', (probeId: string, callback: (probeFrom: string[], probeTo: string[]) => void) => {
this.debugLog.push(`[Node#lookup-probe] ${this.name} is looking up probe ${probeId}`);
callback(probesengine.get(probeId).getFrom());
const probe = probesengine.get(probeId);
callback(probe.getFrom(), probe.getTo());
});
tracesengine.on('message', (to: string, message: string) => {
this.debugLog.push(`[Node#sendTraceMessage] ${this.name} sends trace message to ${to}: ${message}`);
Expand Down

0 comments on commit 65f4986

Please sign in to comment.