// NewTPacket returns a new TPacket object for reading packets off the wire. // Its behavior may be modified by passing in any/all of afpacket.Opt* to this // function. // If this function succeeds, the user should be sure to Close the returned // TPacket when finished with it. func NewTPacket(opts ...interface{}) (h *TPacket, err error) { h = &TPacket{} if h.opts, err = parseOptions(opts...); err != nil { return nil, err } fd, err := C.socket(C.AF_PACKET, C.int(h.opts.socktype), C.int(C.htons(C.ETH_P_ALL))) if err != nil { return nil, err } h.fd = fd if h.opts.iface != "" { if err = h.bindToInterface(h.opts.iface); err != nil { goto errlbl } } if err = h.setRequestedTPacketVersion(); err != nil { goto errlbl } if err = h.setUpRing(); err != nil { goto errlbl } // Clear stat counter from socket if err = h.InitSocketStats(); err != nil { goto errlbl } runtime.SetFinalizer(h, (*TPacket).Close) return h, nil errlbl: h.Close() return nil, err }
func (self NamedPort) Ethernet() (PortEthernetProperty, error) { switch self.hatype { case 0: return PortEthernetProperty{}, nil case syscall.ARPHRD_ETHER: // pass default: return PortEthernetProperty{}, fmt.Errorf("%s not an ether", self.name) } cname := C.CString(self.name) defer C.free(unsafe.Pointer(cname)) fd := C.socket(C.AF_INET, C.SOCK_DGRAM, 0) defer C.close(fd) state := PortEthernetProperty{} ecmd := C.struct_ethtool_cmd{cmd: C.ETHTOOL_GSET} if r, err := C.ethtool_cmd_call(fd, cname, &ecmd); err != nil { return state, fmt.Errorf("ethtool for %s: %s", self.name, err.Error()) } else if r != 0 { return state, fmt.Errorf("ethtool_cmd_call error") } else { for k, v := range supportedSpeed { if ecmd.supported&k != 0 && v > state.MaxSpeed { state.MaxSpeed = v } } state.Supported = 0 for k, v := range supportedConvert { if ecmd.supported&k != 0 { state.Supported |= v } } state.Advertised = 0 state.Peer = 0 for k, v := range advertisedConvert { if ecmd.advertising&k != 0 { state.Advertised |= v } if ecmd.lp_advertising&k != 0 { state.Peer |= v } } var curr uint32 switch C.ethtool_cmd_speed(&ecmd) { case C.SPEED_10: state.CurrSpeed = 10000 switch ecmd.duplex { case C.DUPLEX_HALF: curr |= ofp4.OFPPF_10MB_HD case C.DUPLEX_FULL: curr |= ofp4.OFPPF_10MB_FD default: curr |= ofp4.OFPPF_OTHER } case C.SPEED_100: state.CurrSpeed = 100000 switch ecmd.duplex { case C.DUPLEX_HALF: curr |= ofp4.OFPPF_100MB_HD case C.DUPLEX_FULL: curr |= ofp4.OFPPF_100MB_FD default: curr |= ofp4.OFPPF_OTHER } case C.SPEED_1000: state.CurrSpeed = 1000000 switch ecmd.duplex { case C.DUPLEX_HALF: curr |= ofp4.OFPPF_1GB_HD case C.DUPLEX_FULL: curr |= ofp4.OFPPF_1GB_FD default: curr |= ofp4.OFPPF_OTHER } case C.SPEED_10000: state.CurrSpeed = 1000000 switch ecmd.duplex { case C.DUPLEX_FULL: curr |= ofp4.OFPPF_10GB_FD default: curr |= ofp4.OFPPF_OTHER } default: curr |= ofp4.OFPPF_OTHER } switch ecmd.port { case C.PORT_TP: curr |= ofp4.OFPPF_COPPER case C.PORT_FIBRE: curr |= ofp4.OFPPF_FIBER } if ecmd.autoneg != C.AUTONEG_DISABLE { curr |= ofp4.OFPPF_AUTONEG } state.Curr = curr } return state, nil }