func (e *endpoint) MTU() uint32 {
	return e.mtu - header.EthernetMinimumSize
}
MTU implements stack.LinkEndpoint.MTU. It returns the value initialized
during construction.
package sharedmem
import (
	"sync"
	"sync/atomic"
	"syscall"
	"github.com/google/netstack/tcpip"
	"github.com/google/netstack/tcpip/buffer"
	"github.com/google/netstack/tcpip/header"
	"github.com/google/netstack/tcpip/link/sharedmem/queue"
	"github.com/google/netstack/tcpip/stack"
	"log"
)
type QueueConfig struct {
	DataFD int
	EventFD int
	TxPipeFD int
	RxPipeFD int
	SharedDataFD int
}
type endpoint struct {
	mtu uint32
	bufferSize uint32
	addr tcpip.LinkAddress
	rx rx
	stopRequested uint32
	completed sync.WaitGroup
	mu sync.Mutex
	tx tx
	workerStarted bool
}
func New(mtu, bufferSize uint32, addr tcpip.LinkAddress, tx, rx QueueConfig) (stack.LinkEndpoint, error) {
	e := &endpoint{
		mtu:        mtu,
		bufferSize: bufferSize,
		addr:       addr,
	}
	if err := e.tx.init(bufferSize, &tx); err != nil {
		return nil, err
	}
	if err := e.rx.init(bufferSize, &rx); err != nil {
		e.tx.cleanup()
		return nil, err
	}
	return e, nil
}
func (e *endpoint) Close() {
	atomic.StoreUint32(&e.stopRequested, 1)
	syscall.Write(e.rx.eventFD, []byte{1, 0, 0, 0, 0, 0, 0, 0})
	e.mu.Lock()
	workerPresent := e.workerStarted
	e.mu.Unlock()
	if !workerPresent {
		e.tx.cleanup()
		e.rx.cleanup()
	}
}
func (e *endpoint) Wait() {
	e.completed.Wait()
}
func (e *endpoint) Attach(dispatcher stack.NetworkDispatcher) {
	e.mu.Lock()
	if !e.workerStarted && atomic.LoadUint32(&e.stopRequested) == 0 {
		e.workerStarted = true
		e.completed.Add(1)
		go e.dispatchLoop(dispatcher)
	}
	e.mu.Unlock()
}
func (e *endpoint) IsAttached() bool {
	e.mu.Lock()
	defer e.mu.Unlock()
	return e.workerStarted
}