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..58eb6e26ce 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
+ unknownHost = 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, unknownHost), // no backlink to random
},
NodeMetadatas: NodeMetadatas{
clientIP: NodeMetadata{
@@ -104,6 +124,10 @@ var (
WithConnCountTCP: true,
MaxConnCountTCP: 3,
},
+ serverIP + IDDelim + unknownHost: EdgeMetadata{
+ WithConnCountTCP: true,
+ MaxConnCountTCP: 7,
+ },
},
},
}
@@ -140,19 +164,42 @@ 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 +232,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 +292,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))
}