func (u *NetLinkProbe) handleIntfIsBond(intf *graph.Node, link netlink.Link) { if link.Type() != "bond" { return } bond := link.(*netlink.Bond) u.Graph.AddMetadata(intf, "BondMode", bond.Mode.String()) // TODO(safchain) Add more info there like xmit_hash_policy }
func (u *NetLinkProbe) handleIntfIsVeth(intf *graph.Node, link netlink.Link) { if link.Type() != "veth" { return } stats, err := ethtool.Stats(link.Attrs().Name) if err != nil { logging.GetLogger().Errorf("Unable get stats from ethtool: %s", err.Error()) return } if index, ok := stats["peer_ifindex"]; ok { peerResolver := func() bool { // re get the interface from the graph since the interface could have been deleted if u.Graph.GetNode(intf.ID) == nil { return false } // got more than 1 peer, unable to find the right one, wait for the other to discover peer := u.Graph.LookupFirstNode(graph.Metadata{"IfIndex": int64(index), "Type": "veth"}) if peer != nil && !u.Graph.AreLinked(peer, intf) { u.Graph.Link(peer, intf, graph.Metadata{"RelationType": "layer2", "Type": "veth"}) return true } return false } if int64(index) > intf.Metadata()["IfIndex"].(int64) { ok := peerResolver() if !ok { // retry few seconds later since the right peer can be insert later go func() { ok := false try := 0 for { if ok || try > 10 { return } time.Sleep(time.Millisecond * 200) u.Graph.Lock() ok = peerResolver() u.Graph.Unlock() try++ } }() } } } }
func vxlanLinksIncompat(l1, l2 netlink.Link) string { if l1.Type() != l2.Type() { return fmt.Sprintf("link type: %v vs %v", l1.Type(), l2.Type()) } v1 := l1.(*netlink.Vxlan) v2 := l2.(*netlink.Vxlan) if v1.VxlanId != v2.VxlanId { return fmt.Sprintf("vni: %v vs %v", v1.VxlanId, v2.VxlanId) } if v1.VtepDevIndex > 0 && v2.VtepDevIndex > 0 && v1.VtepDevIndex != v2.VtepDevIndex { return fmt.Sprintf("vtep (external) interface: %v vs %v", v1.VtepDevIndex, v2.VtepDevIndex) } if len(v1.SrcAddr) > 0 && len(v2.SrcAddr) > 0 && !v1.SrcAddr.Equal(v2.SrcAddr) { return fmt.Sprintf("vtep (external) IP: %v vs %v", v1.SrcAddr, v2.SrcAddr) } if len(v1.Group) > 0 && len(v2.Group) > 0 && !v1.Group.Equal(v2.Group) { return fmt.Sprintf("group address: %v vs %v", v1.Group, v2.Group) } if v1.L2miss != v2.L2miss { return fmt.Sprintf("l2miss: %v vs %v", v1.L2miss, v2.L2miss) } if v1.Port > 0 && v2.Port > 0 && v1.Port != v2.Port { return fmt.Sprintf("port: %v vs %v", v1.Port, v2.Port) } return "" }
func (u *NetLinkProbe) handleIntfIsVeth(intf *graph.Node, link netlink.Link) { if link.Type() != "veth" { return } if index, ok := intf.Metadata()["PeerIfIndex"]; ok { peerResolver := func() error { // re get the interface from the graph since the interface could have been deleted if u.Graph.GetNode(intf.ID) == nil { return errors.New("Node not found") } // got more than 1 peer, unable to find the right one, wait for the other to discover peer := u.Graph.LookupFirstNode(graph.Metadata{"IfIndex": index.(int64), "Type": "veth"}) if peer != nil && !u.Graph.AreLinked(peer, intf) { u.Graph.Link(peer, intf, graph.Metadata{"RelationType": "layer2", "Type": "veth"}) return nil } return errors.New("Nodes not linked") } if index.(int64) > intf.Metadata()["IfIndex"].(int64) { if err := peerResolver(); err != nil { retryFnc := func() error { if u.isRunning() == false { return nil } u.Graph.Lock() defer u.Graph.Unlock() return peerResolver() } go common.Retry(retryFnc, 10, 200*time.Millisecond) } } } }
func (u *NetLinkProbe) addLinkToTopology(link netlink.Link) { logging.GetLogger().Debugf("Link \"%s(%d)\" added", link.Attrs().Name, link.Attrs().Index) u.Graph.Lock() defer u.Graph.Unlock() driver, _ := ethtool.DriverName(link.Attrs().Name) if driver == "" && link.Type() == "bridge" { driver = "bridge" } metadata := graph.Metadata{ "Name": link.Attrs().Name, "Type": link.Type(), "IfIndex": int64(link.Attrs().Index), "MAC": link.Attrs().HardwareAddr.String(), "MTU": int64(link.Attrs().MTU), "Driver": driver, } /*ipv4 := u.getLinkIPV4Addr(link) if len(ipv4) > 0 { metadata["IPV4"] = ipv4 }*/ if vlan, ok := link.(*netlink.Vlan); ok { metadata["Vlan"] = vlan.VlanId } if (link.Attrs().Flags & net.FlagUp) > 0 { metadata["State"] = "UP" } else { metadata["State"] = "DOWN" } var intf *graph.Node switch driver { case "bridge": intf = u.addBridgeLinkToTopology(link, metadata) case "openvswitch": intf = u.addOvsLinkToTopology(link, metadata) // always prefer Type from ovs metadata["Type"] = intf.Metadata()["Type"] default: intf = u.addGenericLinkToTopology(link, metadata) } // merge metadata if the interface returned is not a new one if intf != nil { m := intf.Metadata() updated := false for k, nv := range metadata { if ov, ok := m[k]; ok && nv == ov { continue } m[k] = nv updated = true } if updated { u.Graph.SetMetadata(intf, m) } } }