Пример #1
0
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))
}
Пример #2
0
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()
				}()
			}
		}
	}
}
Пример #3
0
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)
		}
	}
}