Beispiel #1
0
func (self NamedPort) Stats() (PortStats, error) {
	ifinfo := (*[syscall.SizeofIfInfomsg]byte)(unsafe.Pointer(&syscall.IfInfomsg{
		Index: int32(self.ifIndex),
	}))[:]
	if hub, err := nlgo.NewRtHub(); err != nil {
		return PortStats{}, err
	} else {
		defer hub.Close()
		if res, err := hub.Request(syscall.RTM_GETLINK, syscall.NLM_F_DUMP, ifinfo, nil); err != nil {
			return PortStats{}, err
		} else {
			for _, r := range res {
				rIfinfo := (*syscall.IfInfomsg)(unsafe.Pointer(&r.Message.Data[0]))
				if rIfinfo.Index != int32(self.ifIndex) {
					continue
				}
				switch r.Message.Header.Type {
				case syscall.RTM_NEWLINK:
					if attrs, err := nlgo.RouteLinkPolicy.Parse(r.Message.Data[nlgo.NLMSG_ALIGN(syscall.SizeofIfInfomsg):]); err != nil {
						return PortStats{}, err
					} else if blk := attrs.(nlgo.AttrMap).Get(nlgo.IFLA_STATS64); blk != nil {
						stat := []byte(blk.(nlgo.Binary))
						s := (*nlgo.RtnlLinkStats64)(unsafe.Pointer(&stat[0]))
						ret := PortStats{
							RxPackets: s.RxPackets,
							TxPackets: s.TxPackets,
							RxBytes:   s.RxBytes,
							TxBytes:   s.TxBytes,
							RxDropped: s.RxDropped,
							TxDropped: s.TxDropped,
							RxErrors:  s.RxErrors,
							TxErrors:  s.TxErrors,
						}
						if self.hatype == syscall.ARPHRD_ETHER {
							ret.Ethernet = &PortStatsEthernet{
								RxFrameErr: s.RxFrameErrors,
								RxOverErr:  s.RxOverErrors,
								RxCrcErr:   s.RxCrcErrors,
								Collisions: s.Collisions,
							}
						}
						return ret, nil
					}
				}
			}
		}
	}
	return PortStats{}, fmt.Errorf("rtnetlink query failed")
}
Beispiel #2
0
func parse_attributes(data []byte) map[int]Attr {
	attrs := make(map[int]Attr, 0)

	for len(data) != 0 {

		attr_len := binary.LittleEndian.Uint16(data[0:2])

		attr_type := binary.LittleEndian.Uint16(data[2:4])

		attrs[int(attr_type)] = Attr{
			int(attr_type),
			data[4:attr_len],
		}

		data = data[nlgo.NLMSG_ALIGN(int(attr_len)):]
	}
	return attrs
}
Beispiel #3
0
func (self NamedPort) get6lowpanMac(addr net.IP) net.HardwareAddr {
	if msgs, err := self.rhub.Request(
		syscall.RTM_GETROUTE,
		syscall.NLM_F_REQUEST,
		(*[syscall.SizeofRtMsg]byte)(unsafe.Pointer(&syscall.RtMsg{
			Family: syscall.AF_INET6,
		}))[:],
		nlgo.AttrSlice{
			nlgo.Attr{
				Header: syscall.NlAttr{
					Type: syscall.RTA_DST,
				},
				Value: nlgo.Binary(addr.To16()),
			},
		},
	); err != nil {
		return nil
	} else {
		for _, msg := range msgs {
			if msg.Error != nil {
				continue
			}
			switch msg.Message.Header.Type {
			case syscall.RTM_NEWROUTE:
				if attr, err := nlgo.RoutePolicy.Parse(msg.Message.Data[nlgo.NLMSG_ALIGN(syscall.SizeofRtMsg):]); err != nil {
					return nil
				} else if gw := attr.(nlgo.AttrMap).Get(nlgo.RTA_GATEWAY); gw != nil {
					if mac := v6toMac(net.IP(gw.(nlgo.Binary))); mac != nil {
						return mac
					}
				}
			}
		}
	}
	if mac := v6toMac(addr); mac != nil {
		return mac
	}
	return nil
}
Beispiel #4
0
func (self *NamedPortManager) RtListen(ev nlgo.RtMessage) {
	mtype := ev.Message.Header.Type
	if mtype != syscall.RTM_NEWLINK && mtype != syscall.RTM_DELLINK {
		return // no concern
	}

	ifinfo := (*syscall.IfInfomsg)(unsafe.Pointer(&ev.Message.Data[0]))
	evPort := &NamedPort{
		ifIndex: uint32(ifinfo.Index),
		flags:   ifinfo.Flags,
		fd:      -1,
		lock:    &sync.Mutex{},
		rhub:    self.rhub,
	}
	if attrs, err := nlgo.RouteLinkPolicy.Parse(ev.Message.Data[nlgo.NLMSG_ALIGN(syscall.SizeofIfInfomsg):]); err != nil {
		log.Print(err)
	} else if amap, ok := attrs.(nlgo.AttrMap); !ok {
		log.Print("route link policy did not return attr map")
	} else {
		if t := amap.Get(nlgo.IFLA_IFNAME); t != nil {
			evPort.name = string(t.(nlgo.NulString))
		}
		if t := amap.Get(nlgo.IFLA_MTU); t != nil {
			evPort.mtu = uint32(t.(nlgo.U32))
		}
		if t := amap.Get(nlgo.IFLA_ADDRESS); t != nil {
			evPort.mac = []byte(t.(nlgo.Binary))
		}
	}

	switch mtype {
	case syscall.RTM_NEWLINK:
		if port := self.ports[evPort.ifIndex]; port != nil {
			port.flags = ifinfo.Flags
			if len(evPort.name) > 0 {
				port.name = evPort.name
			}
			if evPort.mtu != 0 {
				port.mtu = evPort.mtu
			}
			if len(evPort.mac) != 0 {
				port.mac = evPort.mac
			}
			port.monitor <- true
			if err := port.Up(); err != nil { // maybe ready for up
				log.Print(err)
			}
			return
		}
		// query wiphy
		if res, err := self.ghub.Request("nl80211", 1, nlgo.NL80211_CMD_GET_INTERFACE, syscall.NLM_F_DUMP, nil, nlgo.AttrSlice{
			nlgo.Attr{
				Header: syscall.NlAttr{
					Type: nlgo.NL80211_ATTR_IFINDEX,
				},
				Value: nlgo.U32(ifinfo.Index),
			},
		}); err != nil {
			log.Print(err)
		} else {
			for _, r := range res {
				if r.Error != nil {
					log.Print(r.Error)
				}
				if r.Family != "nl80211" {
					continue
				}
				if attrs, err := nlgo.Nl80211Policy.Parse(r.Payload); err != nil {
					log.Print(err)
				} else if amap, ok := attrs.(nlgo.AttrMap); !ok {
					log.Print("nl80211 attr policy error")
				} else {
					if evPort.ifIndex == uint32(amap.Get(nlgo.NL80211_ATTR_IFINDEX).(nlgo.U32)) {
						evPort.hasWiphy = true
						evPort.wiphy = uint32(amap.Get(nlgo.NL80211_ATTR_WIPHY).(nlgo.U32))
					}
				}
			}
		}
		tracking := func(port *NamedPort) bool {
			for _, name := range self.trackingNames {
				if port.name == name {
					return true
				}
			}
			if port.hasWiphy {
				for _, wiphy := range self.trackingWiphy {
					if port.wiphy == wiphy {
						return true
					}
				}
			}
			for idx, _ := range self.ports {
				if idx == port.ifIndex {
					return true
				}
			}
			return false
		}
		if tracking(evPort) {
			port := evPort
			port.ingress = make(chan Frame)
			port.monitor = make(chan bool)
			self.ports[uint32(ifinfo.Index)] = port
			func() {
				if port.hasWiphy {
					for _, wiphy := range self.trackingWiphy {
						if wiphy == port.wiphy {
							return
						}
					}
					self.trackingWiphy = append(self.trackingWiphy, port.wiphy)
				}
			}()
			self.datapath.AddPort(port)
			port.monitor <- true
			if err := port.Up(); err != nil { // maybe ready for up
				log.Print(err)
			}
		}
	case syscall.RTM_DELLINK:
		if port, ok := self.ports[evPort.ifIndex]; ok && port != nil {
			port.Down()
			port.Close()
			delete(self.ports, evPort.ifIndex)
		}
		// for wiphy unplug
		if res, err := self.ghub.Request("nl80211", 1, nlgo.NL80211_CMD_GET_WIPHY, syscall.NLM_F_DUMP, nil, nil); err != nil {
			log.Print(err)
		} else {
			var activeWiphy []uint32
			for _, r := range res {
				if r.Family != "nl80211" {
					continue
				}
				if attrs, err := nlgo.Nl80211Policy.Parse(r.Payload); err != nil {
					log.Print(err)
				} else {
					activeWiphy = append(activeWiphy, uint32(attrs.(nlgo.AttrMap).Get(nlgo.NL80211_ATTR_WIPHY).(nlgo.U32)))
				}
			}
			var trackingWiphy []uint32
			for _, wiphy := range self.trackingWiphy {
				for _, active := range activeWiphy {
					if wiphy == active {
						trackingWiphy = append(trackingWiphy, wiphy)
					}
				}
			}
			self.trackingWiphy = trackingWiphy
		}
	}
}