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))))
}
RxqSetup allocates and sets up a receive queue for an Ethernet
device.

The function allocates a contiguous block of memory for nDesc
receive descriptors from a memory zone associated with *socket_id*
and initializes each receive descriptor with a network buffer
allocated from the memory pool *mb_pool*.

qid is the index of the receive queue to set up. The value must be
in the range [0, nb_rx_queue - 1] previously supplied to
rte_eth_dev_configure().

nDesc is the number of receive descriptors to allocate for the
receive ring.

mp is the pointer to the memory pool from which to allocate
*rte_mbuf* network memory buffers to populate each descriptor of
the receive ring.

opts specifies the configuration data to be used for the receive
queue.  The *rx_conf* structure contains an *rx_thresh* structure
with the values of the Prefetch, Host, and Write-Back threshold
registers of the receive ring.  In addition it contains the
hardware offloads features to activate using the DEV_RX_OFFLOAD_*
flags.  If an offloading set in rx_conf->offloads hasn't been set
in the input argument eth_conf->rxmode.offloads to
rte_eth_dev_configure(), it is a new added offloading, it must be
per-queue type and it is enabled for the queue.  No need to repeat
any bit in rx_conf->offloads which has already been enabled in
rte_eth_dev_configure() at port level. An offloading enabled at
port level can't be disabled at queue level.

Return codes:

- 0: Success, receive queue correctly set up.

- -EIO: if device is removed.

- -EINVAL: The memory pool pointer is null or the size of network
buffers which can be allocated from this memory pool does not
fit the various buffer sizes allowed by the device controller.

- -ENOMEM: Unable to allocate the receive ring descriptors or to
allocate network memory buffers from the memory pool when
initializing receive descriptors.
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)
	}}
}