func (u *NetLinkProbe) onLinkDeleted(index int) { logging.GetLogger().Debug("Link %d deleted", index) u.Graph.Lock() defer u.Graph.Unlock() var intf *graph.Node intfs := u.Graph.LookupNodes(graph.Metadatas{"IfIndex": int64(index)}) switch l := len(intfs); { case l == 1: intf = intfs[0] case l > 1: Loop: for _, i := range intfs { parents := u.Graph.LookupParentNodes(i, nil) for _, parent := range parents { if parent.ID == u.Root.ID { intf = i break Loop } } } } // case of removing the interface from a bridge if intf != nil { parents := u.Graph.LookupParentNodes(intf, graph.Metadatas{"Type": "bridge"}) for _, parent := range parents { u.Graph.Unlink(parent, intf) } } // check wheter the interface has been deleted or not // we get a delete event when an interace is removed from a bridge _, err := netlink.LinkByIndex(index) if err != nil && intf != nil { if driver, ok := intf.Metadatas()["Driver"]; ok { // if openvswitch do not remove let's do the job by ovs piece of code if driver == "openvswitch" { u.Graph.Unlink(u.Root, intf) } else { u.Graph.DelNode(intf) } } } delete(u.indexTointfsQueue, int64(index)) }
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().Error("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.Metadatas{"IfIndex": int64(index), "Type": "veth"}) if peer != nil && !u.Graph.AreLinked(peer, intf) { u.Graph.NewEdge(graph.GenID(), peer, intf, graph.Metadatas{"Type": "veth"}) return true } return false } if int64(index) > intf.Metadatas()["IfIndex"].(int64) { ok := peerResolver() if !ok { // retry few second later since the right peer can be insert later go func() { time.Sleep(2 * time.Second) u.Graph.Lock() defer u.Graph.Unlock() peerResolver() }() } } } }
func (u *NetLinkProbe) addLinkToTopology(link netlink.Link) { logging.GetLogger().Debug("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" } metadatas := graph.Metadatas{ "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 { metadatas["IPV4"] = ipv4 }*/ if vlan, ok := link.(*netlink.Vlan); ok { metadatas["Vlan"] = vlan.VlanId } if (link.Attrs().Flags & net.FlagUp) > 0 { metadatas["State"] = "UP" } else { metadatas["State"] = "DOWN" } var intf *graph.Node switch driver { case "bridge": intf = u.addBridgeLinkToTopology(link, metadatas) case "openvswitch": intf = u.addOvsLinkToTopology(link, metadatas) default: intf = u.addGenericLinkToTopology(link, metadatas) } // merge metadatas if the interface returned is not a new one if intf != nil { m := intf.Metadatas() updated := false for k, nv := range metadatas { if ov, ok := m[k]; ok && nv == ov { continue } m[k] = nv updated = true } if updated { u.Graph.SetMetadatas(intf, m) } } }