func (link *EthLink) Duplex() bool {
	return link.link_duplex > 0
}
Duplex returns true if the port is in full-duplex, otherwise it's
in half-duplex.
package ethdev
import "C"
import (
	"net"
	"reflect"
	"unsafe"
	"github.com/yerden/go-dpdk/common"
	"github.com/yerden/go-dpdk/mempool"
)
const (
	RxOffloadVlanStrip      uint64 = C.DEV_RX_OFFLOAD_VLAN_STRIP
	RxOffloadIpv4Cksum             = C.DEV_RX_OFFLOAD_IPV4_CKSUM
	RxOffloadUDPCksum              = C.DEV_RX_OFFLOAD_UDP_CKSUM
	RxOffloadTCPCksum              = C.DEV_RX_OFFLOAD_TCP_CKSUM
	RxOffloadTCPLro                = C.DEV_RX_OFFLOAD_TCP_LRO
	RxOffloadQinqStrip             = C.DEV_RX_OFFLOAD_QINQ_STRIP
	RxOffloadOuterIpv4Cksum        = C.DEV_RX_OFFLOAD_OUTER_IPV4_CKSUM
	RxOffloadMacsecStrip           = C.DEV_RX_OFFLOAD_MACSEC_STRIP
	RxOffloadHeaderSplit           = C.DEV_RX_OFFLOAD_HEADER_SPLIT
	RxOffloadVlanFilter            = C.DEV_RX_OFFLOAD_VLAN_FILTER
	RxOffloadVlanExtend            = C.DEV_RX_OFFLOAD_VLAN_EXTEND
	RxOffloadJumboFrame            = C.DEV_RX_OFFLOAD_JUMBO_FRAME
	RxOffloadScatter               = C.DEV_RX_OFFLOAD_SCATTER
	RxOffloadTimestamp             = C.DEV_RX_OFFLOAD_TIMESTAMP
	RxOffloadSecurity              = C.DEV_RX_OFFLOAD_SECURITY
	RxOffloadChecksum = (RxOffloadIpv4Cksum |
		RxOffloadUDPCksum |
		RxOffloadTCPCksum)
	RxOffloadVlan = (RxOffloadVlanStrip |
		RxOffloadVlanFilter |
		RxOffloadVlanExtend)
)
const (
	TxOffloadVlanInsert     uint64 = C.DEV_TX_OFFLOAD_VLAN_INSERT
	TxOffloadIpv4Cksum             = C.DEV_TX_OFFLOAD_IPV4_CKSUM
	TxOffloadUDPCksum              = C.DEV_TX_OFFLOAD_UDP_CKSUM
	TxOffloadTCPCksum              = C.DEV_TX_OFFLOAD_TCP_CKSUM
	TxOffloadSCTPCksum             = C.DEV_TX_OFFLOAD_SCTP_CKSUM
	TxOffloadTCPTso                = C.DEV_TX_OFFLOAD_TCP_TSO
	TxOffloadUDPTso                = C.DEV_TX_OFFLOAD_UDP_TSO
	TxOffloadOuterIpv4Cksum        = C.DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM
	TxOffloadQinqInsert            = C.DEV_TX_OFFLOAD_QINQ_INSERT
	TxOffloadVxlanTnlTso           = C.DEV_TX_OFFLOAD_VXLAN_TNL_TSO
	TxOffloadGreTnlTso             = C.DEV_TX_OFFLOAD_GRE_TNL_TSO
	TxOffloadIpipTnlTso            = C.DEV_TX_OFFLOAD_IPIP_TNL_TSO
	TxOffloadGeneveTnlTso          = C.DEV_TX_OFFLOAD_GENEVE_TNL_TSO
	TxOffloadMacsecInsert          = C.DEV_TX_OFFLOAD_MACSEC_INSERT
	TxOffloadMtLockfree            = C.DEV_TX_OFFLOAD_MT_LOCKFREE
	TxOffloadMultiSegs             = C.DEV_TX_OFFLOAD_MULTI_SEGS
	TxOffloadMbufFastFree          = C.DEV_TX_OFFLOAD_MBUF_FAST_FREE
	TxOffloadSecurity              = C.DEV_TX_OFFLOAD_SECURITY
)
const (
	LinkSpeedAutoneg uint = C.ETH_LINK_SPEED_AUTONEG  
	LinkSpeedFixed        = C.ETH_LINK_SPEED_FIXED    
	LinkSpeed10mHd        = C.ETH_LINK_SPEED_10M_HD   
	LinkSpeed10m          = C.ETH_LINK_SPEED_10M      
	LinkSpeed100mHd       = C.ETH_LINK_SPEED_100M_HD  
	LinkSpeed100m         = C.ETH_LINK_SPEED_100M     
	LinkSpeed1g           = C.ETH_LINK_SPEED_1G       
	LinkSpeed2_5g         = C.ETH_LINK_SPEED_2_5G     
	LinkSpeed5g           = C.ETH_LINK_SPEED_5G       
	LinkSpeed10g          = C.ETH_LINK_SPEED_10G      
	LinkSpeed20g          = C.ETH_LINK_SPEED_20G      
	LinkSpeed25g          = C.ETH_LINK_SPEED_25G      
	LinkSpeed40g          = C.ETH_LINK_SPEED_40G      
	LinkSpeed50g          = C.ETH_LINK_SPEED_50G      
	LinkSpeed56g          = C.ETH_LINK_SPEED_56G      
	LinkSpeed100g         = C.ETH_LINK_SPEED_100G     
)
const (
	MqRxNone       uint = C.ETH_MQ_RX_NONE          
	MqRxRss             = C.ETH_MQ_RX_RSS           
	MqRxDcb             = C.ETH_MQ_RX_DCB           
	MqRxDcbRss          = C.ETH_MQ_RX_DCB_RSS       
	MqRxVmdqOnly        = C.ETH_MQ_RX_VMDQ_ONLY     
	MqRxVmdqRss         = C.ETH_MQ_RX_VMDQ_RSS      
	MqRxVmdqDcb         = C.ETH_MQ_RX_VMDQ_DCB      
	MqRxVmdqDcbRss      = C.ETH_MQ_RX_VMDQ_DCB_RSS  
)
const (
	MqTxNone     uint = C.ETH_MQ_TX_NONE       
	MqTxDcb           = C.ETH_MQ_TX_DCB        
	MqTxVmdqDcb       = C.ETH_MQ_TX_VMDQ_DCB   
	MqTxVmdqOnly      = C.ETH_MQ_TX_VMDQ_ONLY  
)
type Option struct {
	f func(*ethConf)
}
type qConf struct {
	socket C.int
	rx     C.struct_rte_eth_rxconf
	tx     C.struct_rte_eth_txconf
}
type QueueOption struct {
	f func(*qConf)
}
type RxMode struct {
	MqMode uint
	MaxRxPktLen uint32
	SplitHdrSize uint16
	Offloads uint64
}
type TxMode struct {
	MqMode uint
	Offloads uint64
	Pvid uint16
	HwVlanRejectTagged bool
	HwVlanRejectUntagged bool
	HwVlanInsertPvid bool
}
type RssConf struct {
	Key []byte
	Hf uint64
}
type MACAddr C.struct_rte_ether_addr
func (pid Port) MACAddrGet(addr *MACAddr) error {
	return errget(C.rte_eth_macaddr_get(C.ushort(pid), (*C.struct_rte_ether_addr)(addr)))
}
func (addr *MACAddr) HardwareAddr() net.HardwareAddr {
	p := &addr.addr_bytes
	return (*[unsafe.Sizeof(*p)]byte)(unsafe.Pointer(&p[0]))[:]
}
func (addr *MACAddr) String() string {
	return addr.HardwareAddr().String()
}
func (pid Port) RssHashConfGet(conf *RssConf) error {
	var rssConf C.struct_rte_eth_rss_conf
	rc := C.rte_eth_dev_rss_hash_conf_get(C.ushort(pid), &rssConf)
	sh := (*reflect.SliceHeader)(unsafe.Pointer(&conf.Key))
	sh.Data = uintptr(unsafe.Pointer(rssConf.rss_key))
	sh.Len = int(rssConf.rss_key_len)
	sh.Cap = sh.Len
	conf.Hf = uint64(rssConf.rss_hf)
	return errget(rc)
}
type RssRetaEntry64 C.struct_rte_eth_rss_reta_entry64
func (conf *RssRetaEntry64) Reta() (reta []uint16) {
	sh := (*reflect.SliceHeader)(unsafe.Pointer(&reta))
	sh.Len = len(conf.reta)
	sh.Cap = len(conf.reta)
	sh.Data = uintptr(unsafe.Pointer(&conf.reta))
	return
}
func (conf *RssRetaEntry64) Mask() *uint64 {
	return (*uint64)(&conf.mask)
}
func (pid Port) RssRetaUpdate(conf []RssRetaEntry64, retaSize uint16) error {
	p := (*C.struct_rte_eth_rss_reta_entry64)(nil)
	if len(conf) > 0 {
		p = (*C.struct_rte_eth_rss_reta_entry64)(&conf[0])
	}
	return errget(C.rte_eth_dev_rss_reta_update(C.ushort(pid), p, C.ushort(retaSize)))
}
func (pid Port) RssRetaQuery(conf []RssRetaEntry64, retaSize uint16) error {
	p := (*C.struct_rte_eth_rss_reta_entry64)(nil)
	if len(conf) > 0 {
		p = (*C.struct_rte_eth_rss_reta_entry64)(&conf[0])
	}
	return errget(C.rte_eth_dev_rss_reta_query(C.ushort(pid), p, C.ushort(retaSize)))
}
type Thresh struct {
	PThresh uint8
	HThresh uint8
	WThresh uint8
}
type RxqConf struct {
	Thresh
	FreeThresh uint16
	DropEn uint8
	DeferredStart uint8
	Offloads uint64
}
type TxqConf struct {
	Thresh
	RsThresh uint16
	FreeThresh uint16
	DeferredStart uint8
	Offloads uint64
}
type Port uint16
func errget(n ...interface{}) error {
	if len(n) == 0 {
		return common.RteErrno()
	}
	return common.IntToErr(n[0])
}
func (t *Thresh) cThresh() (out C.struct_rte_eth_thresh) {
	out.pthresh = C.uchar(t.PThresh)
	out.hthresh = C.uchar(t.HThresh)
	out.wthresh = C.uchar(t.WThresh)
	return
}
func OptLinkSpeeds(speeds uint) Option {
	return Option{func(c *ethConf) {
		c.conf.link_speeds = C.uint(speeds)
	}}
}
func OptRxMode(conf RxMode) Option {
	return Option{func(c *ethConf) {
		c.conf.rxmode = C.struct_rte_eth_rxmode{
			mq_mode:        uint32(conf.MqMode),
			max_rx_pkt_len: C.uint(conf.MaxRxPktLen),
			split_hdr_size: C.ushort(conf.SplitHdrSize),
			offloads:       C.ulong(conf.Offloads),
		}
	}}
}
type ethConf struct {
	conf  C.struct_rte_eth_conf
	cptrs []unsafe.Pointer  
}
func (c *ethConf) free() {
	for _, p := range c.cptrs {
		C.free(p)
	}
}
func OptTxMode(conf TxMode) Option {
	return Option{func(c *ethConf) {
		c.conf.txmode = C.struct_rte_eth_txmode{
			mq_mode:  uint32(conf.MqMode),
			offloads: C.ulong(conf.Offloads),
			pvid:     C.ushort(conf.Pvid),
		}
		if conf.HwVlanRejectTagged {
			C.set_tx_reject_tagged(&c.conf.txmode)
		}
		if conf.HwVlanRejectUntagged {
			C.set_tx_reject_untagged(&c.conf.txmode)
		}
		if conf.HwVlanInsertPvid {
			C.set_tx_insert_pvid(&c.conf.txmode)
		}
	}}
}
func OptLoopbackMode(mode uint32) Option {
	return Option{func(c *ethConf) {
		c.conf.lpbk_mode = C.uint(mode)
	}}
}
func OptRss(conf RssConf) Option {
	return Option{func(c *ethConf) {
		rssConf := &c.conf.rx_adv_conf.rss_conf
		rssConf.rss_key_len = C.uchar(len(conf.Key))
		rssConf.rss_hf = C.ulong(conf.Hf)
		if conf.Key != nil && len(conf.Key) > 0 {
			p := C.CBytes(conf.Key)
			rssConf.rss_key = (*C.uchar)(p)
			c.cptrs = append(c.cptrs, p)
		}
	}}
}
func (pid Port) DevConfigure(nrxq, ntxq uint16, opts ...Option) error {
	ec := &ethConf{}
	for i := range opts {
		opts[i].f(ec)
	}
	defer ec.free()
	return errget(C.rte_eth_dev_configure(C.ushort(pid), C.ushort(nrxq),
		C.ushort(ntxq), &ec.conf))
}
func OptRxqConf(conf RxqConf) QueueOption {
	return QueueOption{func(q *qConf) {
		q.rx = C.struct_rte_eth_rxconf{
			rx_thresh:         conf.Thresh.cThresh(),
			rx_free_thresh:    C.ushort(conf.FreeThresh),
			rx_drop_en:        C.uchar(conf.DropEn),
			rx_deferred_start: C.uchar(conf.DeferredStart),
			offloads:          C.ulong(conf.Offloads),
		}
	}}
}
func OptTxqConf(conf TxqConf) QueueOption {
	return QueueOption{func(q *qConf) {
		q.tx = C.struct_rte_eth_txconf{
			tx_thresh:         conf.Thresh.cThresh(),
			tx_rs_thresh:      C.ushort(conf.RsThresh),
			tx_free_thresh:    C.ushort(conf.FreeThresh),
			tx_deferred_start: C.uchar(conf.DeferredStart),
			offloads:          C.ulong(conf.Offloads),
		}
	}}
}
func OptSocket(socket int) QueueOption {
	return QueueOption{func(q *qConf) {
		q.socket = C.int(socket)
	}}
}
func (pid Port) RxqSetup(qid, nDesc uint16, mp *mempool.Mempool, opts ...QueueOption) error {
	conf := &qConf{socket: C.SOCKET_ID_ANY}
	for i := range opts {
		opts[i].f(conf)
	}
	return errget(C.rte_eth_rx_queue_setup(C.ushort(pid), C.ushort(qid),
		C.ushort(nDesc), C.uint(conf.socket), &conf.rx,
		(*C.struct_rte_mempool)(unsafe.Pointer(mp))))
}
func (pid Port) TxqSetup(qid, nDesc uint16, opts ...QueueOption) error {
	conf := &qConf{socket: C.SOCKET_ID_ANY}
	for i := range opts {
		opts[i].f(conf)
	}
	return errget(C.rte_eth_tx_queue_setup(C.ushort(pid), C.ushort(qid),
		C.ushort(nDesc), C.uint(conf.socket), &conf.tx))
}
func (pid Port) Reset() error {
	return errget(C.rte_eth_dev_reset(C.ushort(pid)))
}
func (pid Port) Start() error {
	return errget(C.rte_eth_dev_start(C.ushort(pid)))
}
func (pid Port) Stop() {
	C.rte_eth_dev_stop(C.ushort(pid))
}
func (pid Port) Close() {
	C.rte_eth_dev_close(C.ushort(pid))
}
func (pid Port) PromiscEnable() error {
	return errget(C.rte_eth_promiscuous_enable(C.ushort(pid)))
}
func (pid Port) PromiscDisable() error {
	return errget(C.rte_eth_promiscuous_disable(C.ushort(pid)))
}
func (pid Port) SetLinkUp() error {
	return errget(C.rte_eth_dev_set_link_up(C.ushort(pid)))
}
func (pid Port) SetLinkDown() error {
	return errget(C.rte_eth_dev_set_link_down(C.ushort(pid)))
}
func (pid Port) SocketID() int {
	return int(C.rte_eth_dev_socket_id(C.ushort(pid)))
}
type DevInfo C.struct_rte_eth_dev_info
func (info *DevInfo) DriverName() string {
	return C.GoString((*C.struct_rte_eth_dev_info)(info).driver_name)
}
func (info *DevInfo) InterfaceName() string {
	var buf [C.IF_NAMESIZE]C.char
	return C.GoString(C.if_indextoname(info.if_index, &buf[0]))
}
func (info *DevInfo) RetaSize() uint16 {
	return uint16(info.reta_size)
}
func (pid Port) InfoGet(info *DevInfo) error {
	return errget(C.rte_eth_dev_info_get(C.ushort(pid), (*C.struct_rte_eth_dev_info)(info)))
}
func (info *DevInfo) NbRxQueues() uint16 {
	return uint16(info.nb_rx_queues)
}
func (info *DevInfo) NbTxQueues() uint16 {
	return uint16(info.nb_tx_queues)
}
func (pid Port) IsValid() bool {
	return C.rte_eth_dev_is_valid_port(C.ushort(pid)) != 0
}
func CountAvail() int {
	return int(C.rte_eth_dev_count_avail())
}
func CountTotal() int {
	return int(C.rte_eth_dev_count_total())
}
type EthLink C.struct_go_rte_eth_link
func (link *EthLink) Speed() uint32 {
	return uint32(link.link_speed)
}