pkg/skoop/netstack/neigh.go (79 lines of code) (raw):

package netstack import ( "fmt" "net" "golang.org/x/sys/unix" ) // Neighbor Cache Entry States. const ( NudNone = 0x00 NudIncomplete = 0x01 NudReachable = 0x02 NudStale = 0x04 NudDelay = 0x08 NudProbe = 0x10 NudFailed = 0x20 NudNoarp = 0x40 NudPermanent = 0x80 ) type NeighResult struct { State int LLAddr net.HardwareAddr // for vxlan usage DST net.IP } type Neighbour struct { interfaces []Interface } func NewNeigh(interfaces []Interface) *Neighbour { return &Neighbour{ interfaces: interfaces, } } func (n *Neighbour) ProbeNeigh(ip net.IP, linkIndex int) (*NeighResult, error) { var in *Interface for _, inf := range n.interfaces { if inf.Index == linkIndex { in = &inf break } } if in == nil { return nil, fmt.Errorf("cannot found link: %v", linkIndex) } var ( matchNeigh *Neigh ) result := &NeighResult{} for _, neigh := range in.NeighInfo { if neigh.LinkIndex == linkIndex && neigh.IP.Equal(ip) { matchNeigh = &neigh break } } // no cache for neigh if matchNeigh == nil { return nil, nil } result.LLAddr = matchNeigh.HardwareAddr result.State = matchNeigh.State if result.State == NudPermanent { for _, fdb := range in.FdbInfo { if fdb.HardwareAddr.String() == matchNeigh.HardwareAddr.String() { result.DST = fdb.IP } } } return result, nil } func (n *Neighbour) ProbeRouteNeigh(route *Route, dst net.IP) (*Neigh, error) { for _, ni := range n.interfaces { if ni.Name == route.OifName { for _, neigh := range ni.NeighInfo { if neigh.Family == unix.AF_INET && (route.Gw == nil && neigh.IP.Equal(dst)) || (route.Gw != nil && neigh.IP.Equal(route.Gw)) { return &neigh, nil } } } } return nil, nil }