// discover reads reports from a collector and republishes them on the // publisher, while scanning the reports for IPs to connect to. Only addresses // in the network topology of the report are considered. IPs listed in fixed // are always skipped. func discover(c collector, p publisher, fixed []string) { lastSeen := map[string]time.Time{} avoid := makeAvoid(fixed) for r := range c.Reports() { // log.Printf("got a report") p.Publish(r) var ( now = time.Now() localNets = render.LocalNetworks(r) ) for _, adjacent := range r.Address.Adjacency { for _, a := range adjacent { ip := report.AddressIDAddresser(a) // address id -> IP if ip == nil { continue } addr := ip.String() if _, ok := avoid[addr]; ok { continue } // log.Printf("potential address: %v (via %s)", addr, src) if _, ok := lastSeen[addr]; !ok { if interestingAddress(localNets, addr) { log.Printf("discovery %v: potential probe address", addr) c.Add(addressToDial(addr)) } else { log.Printf("discovery %v: non-probe address", addr) } } // We always add addr to lastSeen[], even if it's a non-local // address. This way they are part of the normal timeout logic, // and we won't analyze the address again until it re-appears // after a timeout. lastSeen[addr] = now } } for addr, last := range lastSeen { if now.Sub(last) > trafficTimeout { // Timeout can be for a non-local address, which we didn't // connect to. In that case the RemoveAddress() call won't do // anything. log.Printf("discovery %v: traffic timeout", addr) delete(lastSeen, addr) c.Remove(addressToDial(addr)) } } } }
func TestReportLocalNetworks(t *testing.T) { r := report.MakeReport() r.Merge(report.Report{Host: report.Topology{NodeMetadatas: report.NodeMetadatas{ "nonets": report.NewNodeMetadata(map[string]string{}), "foo": report.NewNodeMetadata(map[string]string{host.LocalNetworks: "10.0.0.1/8 192.168.1.1/24 10.0.0.1/8 badnet/33"}), }}}) want := report.Networks([]*net.IPNet{ mustParseCIDR("10.0.0.1/8"), mustParseCIDR("192.168.1.1/24"), }) have := render.LocalNetworks(r) if !reflect.DeepEqual(want, have) { t.Errorf("%s", test.Diff(want, have)) } }
func TestReportLocalNetworks(t *testing.T) { r := report.MakeReport().Merge(report.Report{ Host: report.Topology{ Nodes: report.Nodes{ "nonets": report.MakeNode(), "foo": report.MakeNode().WithSets(report.Sets{ host.LocalNetworks: report.MakeStringSet( "10.0.0.1/8", "192.168.1.1/24", "10.0.0.1/8", "badnet/33"), }), }, }, }) want := report.Networks([]*net.IPNet{ mustParseCIDR("10.0.0.1/8"), mustParseCIDR("192.168.1.1/24"), }) have := render.LocalNetworks(r) if !reflect.DeepEqual(want, have) { t.Errorf("%s", test.Diff(want, have)) } }