func (m *idManager) remove(i uint64) *queue.TxBuffer {
	if i >= uint64(len(m.ids)) {
		return nil
	}
	desc := &m.ids[i]
	b := desc.buf
	if b == nil {
		return nil
	}
	desc.buf = nil
	desc.nextFree = m.freeList
	m.freeList = i
	return b
}
remove retrieves the tx buffer associated with the given ID, and removes the
ID from the assigned table so that it can be reused in the future.
package sharedmem
import (
	"math"
	"syscall"
	"github.com/google/netstack/tcpip/link/sharedmem/queue"
)
const (
	nilID = math.MaxUint64
)
type tx struct {
	data []byte
	q    queue.Tx
	ids  idManager
	bufs bufferManager
}
func (t *tx) init(mtu uint32, c *QueueConfig) error {
	txPipe, err := getBuffer(c.TxPipeFD)
	if err != nil {
		return err
	}
	rxPipe, err := getBuffer(c.RxPipeFD)
	if err != nil {
		syscall.Munmap(txPipe)
		return err
	}
	data, err := getBuffer(c.DataFD)
	if err != nil {
		syscall.Munmap(txPipe)
		syscall.Munmap(rxPipe)
		return err
	}
	t.q.Init(txPipe, rxPipe)
	t.ids.init()
	t.bufs.init(0, len(data), int(mtu))
	t.data = data
	return nil
}
func (t *tx) cleanup() {
	a, b := t.q.Bytes()
	syscall.Munmap(a)
	syscall.Munmap(b)
	syscall.Munmap(t.data)
}
func (t *tx) transmit(a, b []byte) bool {
	for {
		id, ok := t.q.CompletedPacket()
		if !ok {
			break
		}
		if buf := t.ids.remove(id); buf != nil {
			t.bufs.free(buf)
		}
	}
	bSize := t.bufs.entrySize
	total := uint32(len(a) + len(b))
	bufCount := (total + bSize - 1) / bSize
	var buf *queue.TxBuffer
	for i := bufCount; i != 0; i-- {
		b := t.bufs.alloc()
		if b == nil {
			if buf != nil {
				t.bufs.free(buf)
			}
			return false
		}
		b.Next = buf
		buf = b
	}
	nBuf := buf
	var dBuf []byte
	for _, data := range [][]byte{a, b} {
		for len(data) > 0 {
			if len(dBuf) == 0 {
				dBuf = t.data[nBuf.Offset:][:nBuf.Size]
				nBuf = nBuf.Next
			}
			n := copy(dBuf, data)
			data = data[n:]
			dBuf = dBuf[n:]
		}
	}
	id := t.ids.add(buf)
	if !t.q.Enqueue(id, total, bufCount, buf) {
		t.ids.remove(id)
		t.bufs.free(buf)
		return false
	}
	return true
}
func getBuffer(fd int) ([]byte, error) {
	var s syscall.Stat_t
	if err := syscall.Fstat(fd, &s); err != nil {
		return nil, err
	}
	if s.Size > int64(^uint(0)>>1) {
		return nil, syscall.EDOM
	}
	return syscall.Mmap(fd, 0, int(s.Size), syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_SHARED|syscall.MAP_FILE)
}
type idDescriptor struct {
	buf      *queue.TxBuffer
	nextFree uint64
}
type idManager struct {
	ids []idDescriptor
	freeList uint64
}
func (m *idManager) init() {
	m.freeList = nilID
}
func (m *idManager) add(b *queue.TxBuffer) uint64 {
	if i := m.freeList; i != nilID {
		m.ids[i].buf = b
		m.freeList = m.ids[i].nextFree
		return i
	}
	m.ids = append(m.ids, idDescriptor{buf: b})
	return uint64(len(m.ids) - 1)
}