diff --git a/experimental/demoprobe/main.go b/experimental/demoprobe/main.go index 773bb1ae3..a3694433f 100644 --- a/experimental/demoprobe/main.go +++ b/experimental/demoprobe/main.go @@ -84,26 +84,17 @@ func demoReport(nodeCount int) report.Report { ) // Endpoint topology - if _, ok := r.Endpoint.NodeMetadatas[srcPortID]; !ok { - r.Endpoint.NodeMetadatas[srcPortID] = report.NodeMetadata{ - Metadata: map[string]string{ - process.PID: "4000", - "name": c.srcProc, - "domain": "node-" + src, - }, - Adjacency: report.MakeIDList(dstPortID), - } - } - if _, ok := r.Endpoint.NodeMetadatas[dstPortID]; !ok { - r.Endpoint.NodeMetadatas[dstPortID] = report.NodeMetadata{ - Metadata: map[string]string{ - process.PID: "4000", - "name": c.dstProc, - "domain": "node-" + dst, - }, - Adjacency: report.MakeIDList(srcPortID), - } - } + r.Endpoint = r.Endpoint.WithNode(srcPortID, report.MakeNodeMetadata().WithMetadata(map[string]string{ + process.PID: "4000", + "name": c.srcProc, + "domain": "node-" + src, + }).WithAdjacent(dstPortID)) + r.Endpoint = r.Endpoint.WithNode(dstPortID, report.MakeNodeMetadata().WithMetadata(map[string]string{ + process.PID: "4000", + "name": c.dstProc, + "domain": "node-" + dst, + }).WithAdjacent(srcPortID)) + var ( edgeKeyEgress = report.MakeEdgeID(srcPortID, dstPortID) edgeKeyIngress = report.MakeEdgeID(dstPortID, srcPortID) @@ -116,30 +107,20 @@ func demoReport(nodeCount int) report.Report { } // Address topology - if _, ok := r.Address.NodeMetadatas[srcAddressID]; !ok { - r.Address.NodeMetadatas[srcAddressID] = report.NodeMetadata{ - Metadata: map[string]string{ - docker.Name: src, - }, - Adjacency: report.MakeIDList(dstAddressID), - } - } - if _, ok := r.Address.NodeMetadatas[dstAddressID]; !ok { - r.Address.NodeMetadatas[dstAddressID] = report.NodeMetadata{ - Metadata: map[string]string{ - docker.Name: dst, - }, - Adjacency: report.MakeIDList(srcAddressID), - } - } + r.Address = r.Address.WithNode(srcAddressID, report.MakeNodeMetadata().WithMetadata(map[string]string{ + docker.Name: src, + }).WithAdjacent(dstAddressID)) + r.Address = r.Address.WithNode(srcAddressID, report.MakeNodeMetadata().WithMetadata(map[string]string{ + docker.Name: dst, + }).WithAdjacent(srcAddressID)) // Host data - r.Host.NodeMetadatas["hostX"] = report.MakeNodeMetadataWith(map[string]string{ + r.Host = r.Host.WithNode("hostX", report.MakeNodeMetadataWith(map[string]string{ "ts": time.Now().UTC().Format(time.RFC3339Nano), "host_name": "host-x", "local_networks": localNet.String(), "os": "linux", - }) + })) } return r diff --git a/experimental/genreport/generate.go b/experimental/genreport/generate.go index 25596d0b0..f6a4f106e 100644 --- a/experimental/genreport/generate.go +++ b/experimental/genreport/generate.go @@ -64,26 +64,17 @@ func DemoReport(nodeCount int) report.Report { ) // Endpoint topology - if _, ok := r.Endpoint.NodeMetadatas[srcPortID]; !ok { - r.Endpoint.NodeMetadatas[srcPortID] = report.NodeMetadata{ - Metadata: map[string]string{ - "pid": "4000", - "name": c.srcProc, - "domain": "node-" + src, - }, - Adjacency: report.MakeIDList(dstPortID), - } - } - if _, ok := r.Endpoint.NodeMetadatas[dstPortID]; !ok { - r.Endpoint.NodeMetadatas[dstPortID] = report.NodeMetadata{ - Metadata: map[string]string{ - "pid": "4000", - "name": c.dstProc, - "domain": "node-" + dst, - }, - Adjacency: report.MakeIDList(srcPortID), - } - } + r.Endpoint = r.Endpoint.WithNode(srcPortID, report.MakeNodeMetadata().WithMetadata(map[string]string{ + "pid": "4000", + "name": c.srcProc, + "domain": "node-" + src, + }).WithAdjacent(dstPortID)) + r.Endpoint = r.Endpoint.WithNode(dstPortID, report.MakeNodeMetadata().WithMetadata(map[string]string{ + "pid": "4000", + "name": c.dstProc, + "domain": "node-" + dst, + }).WithAdjacent(srcPortID)) + var ( edgeKeyEgress = report.MakeEdgeID(srcPortID, dstPortID) edgeKeyIngress = report.MakeEdgeID(dstPortID, srcPortID) @@ -96,30 +87,20 @@ func DemoReport(nodeCount int) report.Report { } // Address topology - if _, ok := r.Address.NodeMetadatas[srcAddressID]; !ok { - r.Address.NodeMetadatas[srcAddressID] = report.NodeMetadata{ - Metadata: map[string]string{ - "name": src, - }, - Adjacency: report.MakeIDList(dstAddressID), - } - } - if _, ok := r.Address.NodeMetadatas[dstAddressID]; !ok { - r.Address.NodeMetadatas[dstAddressID] = report.NodeMetadata{ - Metadata: map[string]string{ - "name": dst, - }, - Adjacency: report.MakeIDList(srcAddressID), - } - } + r.Address = r.Address.WithNode(srcAddressID, report.MakeNodeMetadata().WithMetadata(map[string]string{ + "name": src, + }).WithAdjacent(dstAddressID)) + r.Address = r.Address.WithNode(dstAddressID, report.MakeNodeMetadata().WithMetadata(map[string]string{ + "name": dst, + }).WithAdjacent(srcAddressID)) // Host data - r.Host.NodeMetadatas["hostX"] = report.MakeNodeMetadataWith(map[string]string{ + r.Host = r.Host.WithNode("hostX", report.MakeNodeMetadataWith(map[string]string{ "ts": time.Now().UTC().Format(time.RFC3339Nano), "host_name": "host-x", "local_networks": localNet.String(), "os": "linux", - }) + })) } return r diff --git a/probe/endpoint/reporter.go b/probe/endpoint/reporter.go index 6043101d5..cc99e1ce1 100644 --- a/probe/endpoint/reporter.go +++ b/probe/endpoint/reporter.go @@ -128,12 +128,6 @@ func (r *Reporter) addConnection(rpt *report.Report, localAddr, remoteAddr strin var ( localIsClient = int(localPort) > int(remotePort) hostNodeID = report.MakeHostNodeID(r.hostID) - addNode = func(t report.Topology, nodeID string, nmd report.NodeMetadata) { - if existing, ok := t.NodeMetadatas[nodeID]; ok { - nmd = nmd.Merge(existing) - } - t.NodeMetadatas[nodeID] = nmd - } ) // Update address topology @@ -161,8 +155,8 @@ func (r *Reporter) addConnection(rpt *report.Report, localAddr, remoteAddr strin edgeID = report.MakeEdgeID(remoteAddressNodeID, localAddressNodeID) } - addNode(rpt.Address, localAddressNodeID, localNode) - addNode(rpt.Address, remoteAddressNodeID, remoteNode) + rpt.Address = rpt.Address.WithNode(localAddressNodeID, localNode) + rpt.Address = rpt.Address.WithNode(remoteAddressNodeID, remoteNode) countTCPConnection(rpt.Address.EdgeMetadatas, edgeID) } @@ -196,8 +190,8 @@ func (r *Reporter) addConnection(rpt *report.Report, localAddr, remoteAddr strin localNode.Metadata[process.PID] = strconv.FormatUint(uint64(proc.PID), 10) } - addNode(rpt.Endpoint, localEndpointNodeID, localNode) - addNode(rpt.Endpoint, remoteEndpointNodeID, remoteNode) + rpt.Endpoint = rpt.Endpoint.WithNode(localEndpointNodeID, localNode) + rpt.Endpoint = rpt.Endpoint.WithNode(remoteEndpointNodeID, remoteNode) countTCPConnection(rpt.Endpoint.EdgeMetadatas, edgeID) } } diff --git a/probe/sniff/sniffer.go b/probe/sniff/sniffer.go index e45a20507..498dd69e4 100644 --- a/probe/sniff/sniffer.go +++ b/probe/sniff/sniffer.go @@ -81,7 +81,7 @@ func (s *Sniffer) loop(src gopacket.ZeroCopyPacketDataSource, on, off time.Durat for { select { case p := <-packets: - s.Merge(p, rpt) + s.Merge(p, &rpt) case <-turnOn: atomic.StoreUint64(&process, 1) // enable packet capture @@ -217,7 +217,7 @@ func (s *Sniffer) read(src gopacket.ZeroCopyPacketDataSource, dst chan Packet, p // egress traffic on a single edge whose src is local and dst is remote. That // is, if we see a packet from the remote addr 9.8.7.6 to the local addr // 1.2.3.4, we apply it as *ingress* on the edge (1.2.3.4 -> 9.8.7.6). -func (s *Sniffer) Merge(p Packet, rpt report.Report) { +func (s *Sniffer) Merge(p Packet, rpt *report.Report) { if p.SrcIP == "" || p.DstIP == "" { return } @@ -250,17 +250,10 @@ func (s *Sniffer) Merge(p Packet, rpt report.Report) { return } - addAdjacency := func(t report.Topology, srcNodeID, dstNodeID string) { - srcNode, ok := t.NodeMetadatas[srcNodeID] - if !ok { - srcNode = report.MakeNodeMetadata() - } - srcNode.Adjacency = srcNode.Adjacency.Add(dstNodeID) - t.NodeMetadatas[srcNodeID] = srcNode - - if _, ok := t.NodeMetadatas[dstNodeID]; !ok { - t.NodeMetadatas[dstNodeID] = report.MakeNodeMetadata() - } + addAdjacency := func(t report.Topology, srcNodeID, dstNodeID string) report.Topology { + result := t.WithNode(srcNodeID, report.MakeNodeMetadata().WithAdjacent(dstNodeID)) + result = result.WithNode(dstNodeID, report.MakeNodeMetadata()) + return result } // For sure, we can add to the address topology. @@ -271,7 +264,7 @@ func (s *Sniffer) Merge(p Packet, rpt report.Report) { edgeID = report.MakeEdgeID(srcNodeID, dstNodeID) ) - addAdjacency(rpt.Address, srcNodeID, dstNodeID) + rpt.Address = addAdjacency(rpt.Address, srcNodeID, dstNodeID) emd := rpt.Address.EdgeMetadatas[edgeID] if egress { @@ -304,7 +297,7 @@ func (s *Sniffer) Merge(p Packet, rpt report.Report) { edgeID = report.MakeEdgeID(srcNodeID, dstNodeID) ) - addAdjacency(rpt.Endpoint, srcNodeID, dstNodeID) + rpt.Endpoint = addAdjacency(rpt.Endpoint, srcNodeID, dstNodeID) emd := rpt.Endpoint.EdgeMetadatas[edgeID] if egress { diff --git a/probe/sniff/sniffer_test.go b/probe/sniff/sniffer_test.go index 8d888cb58..1989b506b 100644 --- a/probe/sniff/sniffer_test.go +++ b/probe/sniff/sniffer_test.go @@ -58,7 +58,7 @@ func TestMerge(t *testing.T) { _, ipnet, _ = net.ParseCIDR(p.SrcIP + "/24") // ;) localNets = report.Networks([]*net.IPNet{ipnet}) ) - sniff.New(hostID, localNets, src, on, off).Merge(p, rpt) + sniff.New(hostID, localNets, src, on, off).Merge(p, &rpt) var ( srcEndpointNodeID = report.MakeEndpointNodeID(hostID, p.SrcIP, p.SrcPort) @@ -72,16 +72,8 @@ func TestMerge(t *testing.T) { }, }, NodeMetadatas: report.NodeMetadatas{ - srcEndpointNodeID: { - Metadata: map[string]string{}, - Counters: map[string]int{}, - Adjacency: report.MakeIDList(dstEndpointNodeID), - }, - dstEndpointNodeID: report.NodeMetadata{ - Metadata: map[string]string{}, - Counters: map[string]int{}, - Adjacency: report.MakeIDList(), - }, + srcEndpointNodeID: report.MakeNodeMetadata().WithAdjacent(dstEndpointNodeID), + dstEndpointNodeID: report.MakeNodeMetadata(), }, }), rpt.Endpoint; !reflect.DeepEqual(want, have) { t.Errorf("%s", test.Diff(want, have)) @@ -99,16 +91,8 @@ func TestMerge(t *testing.T) { }, }, NodeMetadatas: report.NodeMetadatas{ - srcAddressNodeID: report.NodeMetadata{ - Metadata: map[string]string{}, - Counters: map[string]int{}, - Adjacency: report.MakeIDList(dstAddressNodeID), - }, - dstAddressNodeID: report.NodeMetadata{ - Metadata: map[string]string{}, - Counters: map[string]int{}, - Adjacency: report.MakeIDList(), - }, + srcAddressNodeID: report.MakeNodeMetadata().WithAdjacent(dstAddressNodeID), + dstAddressNodeID: report.MakeNodeMetadata(), }, }), rpt.Address; !reflect.DeepEqual(want, have) { t.Errorf("%s", test.Diff(want, have)) diff --git a/report/topology.go b/report/topology.go index 5202c5aa7..2ea08eb5b 100644 --- a/report/topology.go +++ b/report/topology.go @@ -22,6 +22,17 @@ func MakeTopology() Topology { } } +// WithNode produces a topology from t, with nmd added under key nodeID; if a node already exists +// for this key, nmd is merged with that node. NB A fresh topology is returned. +func (t Topology) WithNode(nodeID string, nmd NodeMetadata) Topology { + if existing, ok := t.NodeMetadatas[nodeID]; ok { + nmd = nmd.Merge(existing) + } + result := t.Copy() + result.NodeMetadatas[nodeID] = nmd + return result +} + // Copy returns a value copy of the Topology. func (t Topology) Copy() Topology { return Topology{ @@ -166,6 +177,34 @@ func MakeNodeMetadataWith(m map[string]string) NodeMetadata { } } +// WithMetadata returns a fresh copy of n, with Metadata set to m +func (n NodeMetadata) WithMetadata(m map[string]string) NodeMetadata { + result := n.Copy() + result.Metadata = m + return result +} + +// WithCounters returns a fresh copy of n, with Counters set to c +func (n NodeMetadata) WithCounters(c map[string]int) NodeMetadata { + result := n.Copy() + result.Counters = c + return result +} + +// WithAdjacency returns a fresh copy of n, with Adjacency set to a +func (n NodeMetadata) WithAdjacency(a IDList) NodeMetadata { + result := n.Copy() + result.Adjacency = a + return result +} + +// WithAdjacent returns a fresh copy of n, with 'a' added to Adjacency +func (n NodeMetadata) WithAdjacent(a string) NodeMetadata { + result := n.Copy() + n.Adjacency = n.Adjacency.Add(a) + return result +} + // Copy returns a value copy of the NodeMetadata. func (n NodeMetadata) Copy() NodeMetadata { cp := MakeNodeMetadata() diff --git a/test/report_fixture.go b/test/report_fixture.go index 99a9c88a6..4c6a0e18c 100644 --- a/test/report_fixture.go +++ b/test/report_fixture.go @@ -90,79 +90,59 @@ var ( // NodeMetadata is arbitrary. We're free to put only precisely what we // care to test into the fixture. Just be sure to include the bits // that the mapping funcs extract :) - Client54001NodeID: report.NodeMetadata{ - Metadata: map[string]string{ - endpoint.Addr: ClientIP, - endpoint.Port: ClientPort54001, - process.PID: Client1PID, - report.HostNodeID: ClientHostNodeID, - }, - Adjacency: report.MakeIDList(Server80NodeID), - }, - Client54002NodeID: report.NodeMetadata{ - Metadata: map[string]string{ - endpoint.Addr: ClientIP, - endpoint.Port: ClientPort54002, - process.PID: Client2PID, - report.HostNodeID: ClientHostNodeID, - }, - Adjacency: report.MakeIDList(Server80NodeID), - }, - Server80NodeID: report.NodeMetadata{ - Metadata: map[string]string{ - endpoint.Addr: ServerIP, - endpoint.Port: ServerPort, - process.PID: ServerPID, - report.HostNodeID: ServerHostNodeID, - }, - Adjacency: report.MakeIDList(), - }, - NonContainerNodeID: report.NodeMetadata{ - Metadata: map[string]string{ - endpoint.Addr: ServerIP, - endpoint.Port: NonContainerClientPort, - process.PID: NonContainerPID, - report.HostNodeID: ServerHostNodeID, - }, - Adjacency: report.MakeIDList(GoogleEndpointNodeID), - }, + Client54001NodeID: report.MakeNodeMetadata().WithMetadata(map[string]string{ + endpoint.Addr: ClientIP, + endpoint.Port: ClientPort54001, + process.PID: Client1PID, + report.HostNodeID: ClientHostNodeID, + }).WithAdjacency(report.MakeIDList(Server80NodeID)), + + Client54002NodeID: report.MakeNodeMetadata().WithMetadata(map[string]string{ + endpoint.Addr: ClientIP, + endpoint.Port: ClientPort54002, + process.PID: Client2PID, + report.HostNodeID: ClientHostNodeID, + }).WithAdjacency(report.MakeIDList(Server80NodeID)), + + Server80NodeID: report.MakeNodeMetadata().WithMetadata(map[string]string{ + endpoint.Addr: ServerIP, + endpoint.Port: ServerPort, + process.PID: ServerPID, + report.HostNodeID: ServerHostNodeID, + }), + + NonContainerNodeID: report.MakeNodeMetadata().WithMetadata(map[string]string{ + endpoint.Addr: ServerIP, + endpoint.Port: NonContainerClientPort, + process.PID: NonContainerPID, + report.HostNodeID: ServerHostNodeID, + }).WithAdjacency(report.MakeIDList(GoogleEndpointNodeID)), // Probe pseudo nodes - UnknownClient1NodeID: report.NodeMetadata{ - Metadata: map[string]string{ - endpoint.Addr: UnknownClient1IP, - endpoint.Port: UnknownClient1Port, - }, - Adjacency: report.MakeIDList(Server80NodeID), - }, - UnknownClient2NodeID: report.NodeMetadata{ - Metadata: map[string]string{ - endpoint.Addr: UnknownClient2IP, - endpoint.Port: UnknownClient2Port, - }, - Adjacency: report.MakeIDList(Server80NodeID), - }, - UnknownClient3NodeID: report.NodeMetadata{ - Metadata: map[string]string{ - endpoint.Addr: UnknownClient3IP, - endpoint.Port: UnknownClient3Port, - }, - Adjacency: report.MakeIDList(Server80NodeID), - }, - RandomClientNodeID: report.NodeMetadata{ - Metadata: map[string]string{ - endpoint.Addr: RandomClientIP, - endpoint.Port: RandomClientPort, - }, - Adjacency: report.MakeIDList(Server80NodeID), - }, - GoogleEndpointNodeID: report.NodeMetadata{ - Metadata: map[string]string{ - endpoint.Addr: GoogleIP, - endpoint.Port: GooglePort, - }, - Adjacency: report.MakeIDList(), - }, + UnknownClient1NodeID: report.MakeNodeMetadata().WithMetadata(map[string]string{ + endpoint.Addr: UnknownClient1IP, + endpoint.Port: UnknownClient1Port, + }).WithAdjacency(report.MakeIDList(Server80NodeID)), + + UnknownClient2NodeID: report.MakeNodeMetadata().WithMetadata(map[string]string{ + endpoint.Addr: UnknownClient2IP, + endpoint.Port: UnknownClient2Port, + }).WithAdjacency(report.MakeIDList(Server80NodeID)), + + UnknownClient3NodeID: report.MakeNodeMetadata().WithMetadata(map[string]string{ + endpoint.Addr: UnknownClient3IP, + endpoint.Port: UnknownClient3Port, + }).WithAdjacency(report.MakeIDList(Server80NodeID)), + + RandomClientNodeID: report.MakeNodeMetadata().WithMetadata(map[string]string{ + endpoint.Addr: RandomClientIP, + endpoint.Port: RandomClientPort, + }).WithAdjacency(report.MakeIDList(Server80NodeID)), + + GoogleEndpointNodeID: report.MakeNodeMetadata().WithMetadata(map[string]string{ + endpoint.Addr: GoogleIP, + endpoint.Port: GooglePort, + }), }, EdgeMetadatas: report.EdgeMetadatas{ report.MakeEdgeID(Client54001NodeID, Server80NodeID): report.EdgeMetadata{ @@ -255,42 +235,31 @@ var ( }, Address: report.Topology{ NodeMetadatas: report.NodeMetadatas{ - ClientAddressNodeID: report.NodeMetadata{ - Metadata: map[string]string{ - endpoint.Addr: ClientIP, - report.HostNodeID: ClientHostNodeID, - }, - Adjacency: report.MakeIDList(ServerAddressNodeID), - }, - ServerAddressNodeID: report.MakeNodeMetadataWith(map[string]string{ + ClientAddressNodeID: report.MakeNodeMetadata().WithMetadata(map[string]string{ + endpoint.Addr: ClientIP, + report.HostNodeID: ClientHostNodeID, + }).WithAdjacency(report.MakeIDList(ServerAddressNodeID)), + + ServerAddressNodeID: report.MakeNodeMetadata().WithMetadata(map[string]string{ endpoint.Addr: ServerIP, report.HostNodeID: ServerHostNodeID, }), - UnknownAddress1NodeID: report.NodeMetadata{ - Metadata: map[string]string{ - endpoint.Addr: UnknownClient1IP, - }, - Adjacency: report.MakeIDList(ServerAddressNodeID), - }, - UnknownAddress2NodeID: report.NodeMetadata{ - Metadata: map[string]string{ - endpoint.Addr: UnknownClient2IP, - }, - Adjacency: report.MakeIDList(ServerAddressNodeID), - }, - UnknownAddress3NodeID: report.NodeMetadata{ - Metadata: map[string]string{ - endpoint.Addr: UnknownClient3IP, - }, - Adjacency: report.MakeIDList(ServerAddressNodeID), - }, - RandomAddressNodeID: report.NodeMetadata{ - Metadata: map[string]string{ - endpoint.Addr: RandomClientIP, - }, - Adjacency: report.MakeIDList(ServerAddressNodeID), - }, + UnknownAddress1NodeID: report.MakeNodeMetadata().WithMetadata(map[string]string{ + endpoint.Addr: UnknownClient1IP, + }).WithAdjacency(report.MakeIDList(ServerAddressNodeID)), + + UnknownAddress2NodeID: report.MakeNodeMetadata().WithMetadata(map[string]string{ + endpoint.Addr: UnknownClient2IP, + }).WithAdjacency(report.MakeIDList(ServerAddressNodeID)), + + UnknownAddress3NodeID: report.MakeNodeMetadata().WithMetadata(map[string]string{ + endpoint.Addr: UnknownClient3IP, + }).WithAdjacency(report.MakeIDList(ServerAddressNodeID)), + + RandomAddressNodeID: report.MakeNodeMetadata().WithMetadata(map[string]string{ + endpoint.Addr: RandomClientIP, + }).WithAdjacency(report.MakeIDList(ServerAddressNodeID)), }, EdgeMetadatas: report.EdgeMetadatas{ report.MakeEdgeID(ClientAddressNodeID, ServerAddressNodeID): report.EdgeMetadata{