diff --git a/report/topology.go b/report/topology.go index 1c7e1bbe4c..d4215bef1e 100644 --- a/report/topology.go +++ b/report/topology.go @@ -123,15 +123,21 @@ func (t Topology) RenderBy(f MapFunc, grouped bool) map[string]RenderableNode { dstRenderableID = localUnknown maj, min = "", "" } else { - dstRenderableID = "pseudo:" + dstNodeAddress - maj, min = formatLabel(dstNodeAddress) + // Rule for non-internet psuedo nodes; emit 1 new node for each + // dstNodeAddr, srcNodeAddr, srcNodePort. + srcNodeAddr, srcNodePort := trySplitAddr(srcNodeAddress) + dstNodeAddr, _ := trySplitAddr(dstNodeAddress) + + // We don't care about dst remote port, just src local. + dstRenderableID = strings.Join([]string{"pseudo:", dstNodeAddr, srcNodeAddr, srcNodePort}, ScopeDelim) + maj, min = dstNodeAddr, "" } nodes[dstRenderableID] = RenderableNode{ ID: dstRenderableID, LabelMajor: maj, LabelMinor: min, Pseudo: true, - Metadata: AggregateMetadata{}, // populated below + Metadata: AggregateMetadata{}, // populated below - or not? } address2mapped[dstNodeAddress] = dstRenderableID } @@ -151,6 +157,14 @@ func (t Topology) RenderBy(f MapFunc, grouped bool) map[string]RenderableNode { return nodes } +func trySplitAddr(addr string) (string, string) { + fields := strings.SplitN(addr, ScopeDelim, 3) + if len(fields) == 3 { + return fields[1], fields[2] + } + return fields[1], "" +} + // EdgeMetadata gives the metadata of an edge from the perspective of the // srcRenderableID. Since an edgeID can have multiple edges on the address // level, it uses the supplied mapping function to translate address IDs to diff --git a/report/topology_test.go b/report/topology_test.go index b0e0d35544..260b8b46bc 100644 --- a/report/topology_test.go +++ b/report/topology_test.go @@ -14,13 +14,17 @@ func init() { } const ( - client54001 = ScopeDelim + "10.10.10.20" + ScopeDelim + "54001" // curl (1) - client54002 = ScopeDelim + "10.10.10.20" + ScopeDelim + "54002" // curl (2) - server80 = ScopeDelim + "192.168.1.1" + ScopeDelim + "80" // apache + client54001 = ScopeDelim + "10.10.10.20" + ScopeDelim + "54001" // curl (1) + client54002 = ScopeDelim + "10.10.10.20" + ScopeDelim + "54002" // curl (2) + unknownClient1 = ScopeDelim + "10.10.10.10" + ScopeDelim + "54010" // we want to ensure two unknown clients, connnected + unknownClient2 = ScopeDelim + "10.10.10.10" + ScopeDelim + "54020" // to the same server, are deduped. + unknownClient3 = ScopeDelim + "10.10.10.11" + ScopeDelim + "54020" // Check this one isn't deduped + server80 = ScopeDelim + "192.168.1.1" + ScopeDelim + "80" // apache - clientIP = ScopeDelim + "10.10.10.20" - serverIP = ScopeDelim + "192.168.1.1" - randomIP = ScopeDelim + "172.16.11.9" // only in Network topology + clientIP = ScopeDelim + "10.10.10.20" + serverIP = ScopeDelim + "192.168.1.1" + randomIP = ScopeDelim + "172.16.11.9" // only in Network topology + unknownIP = ScopeDelim + "10.10.10.10" ) var ( @@ -29,7 +33,7 @@ var ( Adjacency: Adjacency{ "client.hostname.com" + IDDelim + client54001: NewIDList(server80), "client.hostname.com" + IDDelim + client54002: NewIDList(server80), - "server.hostname.com" + IDDelim + server80: NewIDList(client54001, client54002), + "server.hostname.com" + IDDelim + server80: NewIDList(client54001, client54002, unknownClient1, unknownClient2, unknownClient3), }, NodeMetadatas: NodeMetadatas{ // NodeMetadata is arbitrary. We're free to put only precisely what we @@ -62,6 +66,7 @@ var ( BytesIngress: 200, BytesEgress: 20, }, + server80 + IDDelim + client54001: EdgeMetadata{ WithBytes: true, BytesIngress: 10, @@ -72,13 +77,28 @@ var ( BytesIngress: 20, BytesEgress: 200, }, + server80 + IDDelim + unknownClient1: EdgeMetadata{ + WithBytes: true, + BytesIngress: 30, + BytesEgress: 300, + }, + server80 + IDDelim + unknownClient2: EdgeMetadata{ + WithBytes: true, + BytesIngress: 40, + BytesEgress: 400, + }, + server80 + IDDelim + unknownClient3: EdgeMetadata{ + WithBytes: true, + BytesIngress: 50, + BytesEgress: 500, + }, }, }, Network: Topology{ Adjacency: Adjacency{ "client.hostname.com" + IDDelim + clientIP: NewIDList(serverIP), "random.hostname.com" + IDDelim + randomIP: NewIDList(serverIP), - "server.hostname.com" + IDDelim + serverIP: NewIDList(clientIP), // no backlink to random + "server.hostname.com" + IDDelim + serverIP: NewIDList(clientIP, unknownIP), // no backlink to random }, NodeMetadatas: NodeMetadatas{ clientIP: NodeMetadata{ @@ -104,6 +124,10 @@ var ( WithConnCountTCP: true, MaxConnCountTCP: 3, }, + serverIP + IDDelim + unknownIP: EdgeMetadata{ + WithConnCountTCP: true, + MaxConnCountTCP: 7, + }, }, }, } @@ -140,19 +164,46 @@ func TestRenderByProcessPID(t *testing.T) { }, }, "pid:server-80-domain:215": { - ID: "pid:server-80-domain:215", - LabelMajor: "apache", - LabelMinor: "server-80-domain (215)", - Rank: "215", - Pseudo: false, - Adjacency: NewIDList("pid:client-54001-domain:10001", "pid:client-54002-domain:10001"), + ID: "pid:server-80-domain:215", + LabelMajor: "apache", + LabelMinor: "server-80-domain (215)", + Rank: "215", + Pseudo: false, + Adjacency: NewIDList( + "pid:client-54001-domain:10001", + "pid:client-54002-domain:10001", + "pseudo:;10.10.10.10;192.168.1.1;80", + "pseudo:;10.10.10.11;192.168.1.1;80", + ), OriginHosts: NewIDList("server.hostname.com"), OriginNodes: NewIDList(";192.168.1.1;80"), Metadata: AggregateMetadata{ - KeyBytesIngress: 30, - KeyBytesEgress: 300, + KeyBytesIngress: 150, + KeyBytesEgress: 1500, }, }, + "pseudo:;10.10.10.10;192.168.1.1;80": { + ID: "pseudo:;10.10.10.10;192.168.1.1;80", + LabelMajor: "10.10.10.10", + LabelMinor: "", + Rank: "", + Pseudo: true, + Adjacency: nil, + OriginHosts: nil, + OriginNodes: nil, + Metadata: AggregateMetadata{}, + }, + "pseudo:;10.10.10.11;192.168.1.1;80": { + ID: "pseudo:;10.10.10.11;192.168.1.1;80", + LabelMajor: "10.10.10.11", + LabelMinor: "", + Rank: "", + Pseudo: true, + Adjacency: nil, + OriginHosts: nil, + OriginNodes: nil, + Metadata: AggregateMetadata{}, + }, } have := report.Process.RenderBy(ProcessPID, false) if !reflect.DeepEqual(want, have) { @@ -185,14 +236,25 @@ func TestRenderByProcessPIDGrouped(t *testing.T) { LabelMinor: "", Rank: "215", Pseudo: false, - Adjacency: NewIDList("curl"), + Adjacency: NewIDList("curl", "localUnknown"), OriginHosts: NewIDList("server.hostname.com"), OriginNodes: NewIDList(";192.168.1.1;80"), Metadata: AggregateMetadata{ - KeyBytesIngress: 30, - KeyBytesEgress: 300, + KeyBytesIngress: 150, + KeyBytesEgress: 1500, }, }, + "localUnknown": { + ID: "localUnknown", + LabelMajor: "", + LabelMinor: "", + Rank: "", + Pseudo: true, + Adjacency: nil, + OriginHosts: nil, + OriginNodes: nil, + Metadata: AggregateMetadata{}, + }, } have := report.Process.RenderBy(ProcessPID, true) if !reflect.DeepEqual(want, have) { @@ -234,15 +296,26 @@ func TestRenderByNetworkHostname(t *testing.T) { LabelMinor: "hostname.com", // after first . Rank: "server", Pseudo: false, - Adjacency: NewIDList("host:client.hostname.com"), + Adjacency: NewIDList("host:client.hostname.com", "pseudo:;10.10.10.10;192.168.1.1;"), OriginHosts: NewIDList("server.hostname.com"), OriginNodes: NewIDList(";192.168.1.1"), Metadata: AggregateMetadata{ - KeyMaxConnCountTCP: 3, + KeyMaxConnCountTCP: 10, }, }, + "pseudo:;10.10.10.10;192.168.1.1;": { + ID: "pseudo:;10.10.10.10;192.168.1.1;", + LabelMajor: "10.10.10.10", + LabelMinor: "", // after first . + Rank: "", + Pseudo: true, + Adjacency: nil, + OriginHosts: nil, + OriginNodes: nil, + Metadata: AggregateMetadata{}, + }, } - have := report.Network.RenderBy(NetworkHostname, true) + have := report.Network.RenderBy(NetworkHostname, false) if !reflect.DeepEqual(want, have) { t.Error("\n" + diff(want, have)) }