func (s *Stack) AddProtocolAddress(id tcpip.NICID, protocolAddress tcpip.ProtocolAddress) *tcpip.Error {
	return s.AddProtocolAddressWithOptions(id, protocolAddress, CanBePrimaryEndpoint)
}
AddProtocolAddress adds a new network-layer protocol address to the
specified NIC.
package stack
import (
	"encoding/binary"
	"sync"
	"sync/atomic"
	"time"
	"github.com/google/netstack/rand"
	"github.com/google/netstack/sleep"
	"github.com/google/netstack/tcpip"
	"github.com/google/netstack/tcpip/buffer"
	"github.com/google/netstack/tcpip/header"
	"github.com/google/netstack/tcpip/iptables"
	"github.com/google/netstack/tcpip/ports"
	"github.com/google/netstack/tcpip/seqnum"
	"github.com/google/netstack/waiter"
	"golang.org/x/time/rate"
)
const (
	ageLimit = 1 * time.Minute
	resolutionTimeout = 1 * time.Second
	resolutionAttempts = 3
	DefaultTOS = 0
)
type transportProtocolState struct {
	proto          TransportProtocol
	defaultHandler func(r *Route, id TransportEndpointID, pkt tcpip.PacketBuffer) bool
}
type TCPProbeFunc func(s TCPEndpointState)
type TCPCubicState struct {
	WLastMax                float64
	WMax                    float64
	T                       time.Time
	TimeSinceLastCongestion time.Duration
	C                       float64
	K                       float64
	Beta                    float64
	WC                      float64
	WEst                    float64
}
type TCPEndpointID struct {
	LocalPort uint16
	LocalAddress tcpip.Address
	RemotePort uint16
	RemoteAddress tcpip.Address
}
type TCPFastRecoveryState struct {
	Active bool
	First seqnum.Value
	Last seqnum.Value
	MaxCwnd int
	HighRxt seqnum.Value
	RescueRxt seqnum.Value
}
type TCPReceiverState struct {
	RcvNxt seqnum.Value
	RcvAcc seqnum.Value
	RcvWndScale uint8
	PendingBufUsed seqnum.Size
	PendingBufSize seqnum.Size
}
type TCPSenderState struct {
	LastSendTime time.Time
	DupAckCount int
	SndCwnd int
	Ssthresh int
	SndCAAckCount int
	Outstanding int
	SndWnd seqnum.Size
	SndUna seqnum.Value
	SndNxt seqnum.Value
	RTTMeasureSeqNum seqnum.Value
	RTTMeasureTime time.Time
	Closed bool
	SRTT time.Duration
	RTO time.Duration
	RTTVar time.Duration
	SRTTInited bool
	MaxPayloadSize int
	SndWndScale uint8
	MaxSentAck seqnum.Value
	FastRecovery TCPFastRecoveryState
	Cubic TCPCubicState
}
type TCPSACKInfo struct {
	Blocks []header.SACKBlock
	ReceivedBlocks []header.SACKBlock
	MaxSACKED seqnum.Value
}
type RcvBufAutoTuneParams struct {
	MeasureTime time.Time
	CopiedBytes int
	PrevCopiedBytes int
	RcvBufSize int
	RTT time.Duration
	RTTVar time.Duration
	RTTMeasureSeqNumber seqnum.Value
	RTTMeasureTime time.Time
	Disabled bool
}
type TCPEndpointState struct {
	ID TCPEndpointID
	SegTime time.Time
	RcvBufSize int
	RcvBufUsed int
	RcvAutoParams RcvBufAutoTuneParams
	RcvClosed bool
	SendTSOk bool
	RecentTS uint32
	TSOffset uint32
	SACKPermitted bool
	SACK TCPSACKInfo
	SndBufSize int
	SndBufUsed int
	SndClosed bool
	SndBufInQueue seqnum.Size
	PacketTooBigCount int
	SndMTU int
	Receiver TCPReceiverState
	Sender TCPSenderState
}
type ResumableEndpoint interface {
	Resume(*Stack)
}
type uniqueIDGenerator uint64
func (u *uniqueIDGenerator) UniqueID() uint64 {
	return atomic.AddUint64((*uint64)(u), 1)
}
type Stack struct {
	transportProtocols map[tcpip.TransportProtocolNumber]*transportProtocolState
	networkProtocols   map[tcpip.NetworkProtocolNumber]NetworkProtocol
	linkAddrResolvers  map[tcpip.NetworkProtocolNumber]LinkAddressResolver
	rawFactory RawFactory
	demux *transportDemuxer
	stats tcpip.Stats
	linkAddrCache *linkAddrCache
	mu               sync.RWMutex
	nics             map[tcpip.NICID]*NIC
	forwarding       bool
	cleanupEndpoints map[TransportEndpoint]struct{}
	routeTable []tcpip.Route
	*ports.PortManager
	tcpProbeFunc TCPProbeFunc
	clock tcpip.Clock
	handleLocal bool
	tables iptables.IPTables
	resumableEndpoints []ResumableEndpoint
	icmpRateLimiter *ICMPRateLimiter
	seed uint32
	ndpConfigs NDPConfigurations
	autoGenIPv6LinkLocal bool
	ndpDisp NDPDispatcher
	uniqueIDGenerator UniqueID
}
type UniqueID interface {
	UniqueID() uint64
}
type Options struct {
	NetworkProtocols []NetworkProtocol
	TransportProtocols []TransportProtocol
	Clock tcpip.Clock
	Stats tcpip.Stats
	HandleLocal bool
	UniqueID UniqueID
	NDPConfigs NDPConfigurations
	AutoGenIPv6LinkLocal bool
	NDPDisp NDPDispatcher
	RawFactory RawFactory
}
type TransportEndpointInfo struct {
	NetProto   tcpip.NetworkProtocolNumber
	TransProto tcpip.TransportProtocolNumber
	ID TransportEndpointID
	BindNICID tcpip.NICID
	BindAddr  tcpip.Address
	RegisterNICID tcpip.NICID
}
func (*TransportEndpointInfo) IsEndpointInfo() {}
func New(opts Options) *Stack {
	clock := opts.Clock
	if clock == nil {
		clock = &tcpip.StdClock{}
	}
	if opts.UniqueID == nil {
		opts.UniqueID = new(uniqueIDGenerator)
	}
	opts.NDPConfigs.validate()
	s := &Stack{
		transportProtocols:   make(map[tcpip.TransportProtocolNumber]*transportProtocolState),
		networkProtocols:     make(map[tcpip.NetworkProtocolNumber]NetworkProtocol),
		linkAddrResolvers:    make(map[tcpip.NetworkProtocolNumber]LinkAddressResolver),
		nics:                 make(map[tcpip.NICID]*NIC),
		cleanupEndpoints:     make(map[TransportEndpoint]struct{}),
		linkAddrCache:        newLinkAddrCache(ageLimit, resolutionTimeout, resolutionAttempts),
		PortManager:          ports.NewPortManager(),
		clock:                clock,
		stats:                opts.Stats.FillIn(),
		handleLocal:          opts.HandleLocal,
		icmpRateLimiter:      NewICMPRateLimiter(),
		seed:                 generateRandUint32(),
		ndpConfigs:           opts.NDPConfigs,
		autoGenIPv6LinkLocal: opts.AutoGenIPv6LinkLocal,
		uniqueIDGenerator:    opts.UniqueID,
		ndpDisp:              opts.NDPDisp,
	}
	for _, netProto := range opts.NetworkProtocols {
		s.networkProtocols[netProto.Number()] = netProto
		if r, ok := netProto.(LinkAddressResolver); ok {
			s.linkAddrResolvers[r.LinkAddressProtocol()] = r
		}
	}
	for _, transProto := range opts.TransportProtocols {
		s.transportProtocols[transProto.Number()] = &transportProtocolState{
			proto: transProto,
		}
	}
	s.rawFactory = opts.RawFactory
	s.demux = newTransportDemuxer(s)
	return s
}
func (s *Stack) UniqueID() uint64 {
	return s.uniqueIDGenerator.UniqueID()
}
func (s *Stack) SetNetworkProtocolOption(network tcpip.NetworkProtocolNumber, option interface{}) *tcpip.Error {
	netProto, ok := s.networkProtocols[network]
	if !ok {
		return tcpip.ErrUnknownProtocol
	}
	return netProto.SetOption(option)
}
func (s *Stack) NetworkProtocolOption(network tcpip.NetworkProtocolNumber, option interface{}) *tcpip.Error {
	netProto, ok := s.networkProtocols[network]
	if !ok {
		return tcpip.ErrUnknownProtocol
	}
	return netProto.Option(option)
}
func (s *Stack) SetTransportProtocolOption(transport tcpip.TransportProtocolNumber, option interface{}) *tcpip.Error {
	transProtoState, ok := s.transportProtocols[transport]
	if !ok {
		return tcpip.ErrUnknownProtocol
	}
	return transProtoState.proto.SetOption(option)
}
func (s *Stack) TransportProtocolOption(transport tcpip.TransportProtocolNumber, option interface{}) *tcpip.Error {
	transProtoState, ok := s.transportProtocols[transport]
	if !ok {
		return tcpip.ErrUnknownProtocol
	}
	return transProtoState.proto.Option(option)
}
func (s *Stack) SetTransportProtocolHandler(p tcpip.TransportProtocolNumber, h func(*Route, TransportEndpointID, tcpip.PacketBuffer) bool) {
	state := s.transportProtocols[p]
	if state != nil {
		state.defaultHandler = h
	}
}
func (s *Stack) NowNanoseconds() int64 {
	return s.clock.NowNanoseconds()
}
func (s *Stack) Stats() tcpip.Stats {
	return s.stats
}
func (s *Stack) SetForwarding(enable bool) {
	s.mu.Lock()
	s.forwarding = enable
	s.mu.Unlock()
}
func (s *Stack) Forwarding() bool {
	s.mu.RLock()
	defer s.mu.RUnlock()
	return s.forwarding
}
func (s *Stack) SetRouteTable(table []tcpip.Route) {
	s.mu.Lock()
	defer s.mu.Unlock()
	s.routeTable = table
}
func (s *Stack) GetRouteTable() []tcpip.Route {
	s.mu.Lock()
	defer s.mu.Unlock()
	return append([]tcpip.Route(nil), s.routeTable...)
}
func (s *Stack) NewEndpoint(transport tcpip.TransportProtocolNumber, network tcpip.NetworkProtocolNumber, waiterQueue *waiter.Queue) (tcpip.Endpoint, *tcpip.Error) {
	t, ok := s.transportProtocols[transport]
	if !ok {
		return nil, tcpip.ErrUnknownProtocol
	}
	return t.proto.NewEndpoint(s, network, waiterQueue)
}
func (s *Stack) NewRawEndpoint(transport tcpip.TransportProtocolNumber, network tcpip.NetworkProtocolNumber, waiterQueue *waiter.Queue, associated bool) (tcpip.Endpoint, *tcpip.Error) {
	if s.rawFactory == nil {
		return nil, tcpip.ErrNotPermitted
	}
	if !associated {
		return s.rawFactory.NewUnassociatedEndpoint(s, network, transport, waiterQueue)
	}
	t, ok := s.transportProtocols[transport]
	if !ok {
		return nil, tcpip.ErrUnknownProtocol
	}
	return t.proto.NewRawEndpoint(s, network, waiterQueue)
}
func (s *Stack) NewPacketEndpoint(cooked bool, netProto tcpip.NetworkProtocolNumber, waiterQueue *waiter.Queue) (tcpip.Endpoint, *tcpip.Error) {
	if s.rawFactory == nil {
		return nil, tcpip.ErrNotPermitted
	}
	return s.rawFactory.NewPacketEndpoint(s, cooked, netProto, waiterQueue)
}
func (s *Stack) createNIC(id tcpip.NICID, name string, ep LinkEndpoint, enabled, loopback bool) *tcpip.Error {
	s.mu.Lock()
	defer s.mu.Unlock()
	if _, ok := s.nics[id]; ok {
		return tcpip.ErrDuplicateNICID
	}
	n := newNIC(s, id, name, ep, loopback)
	s.nics[id] = n
	if enabled {
		return n.enable()
	}
	return nil
}
func (s *Stack) CreateNIC(id tcpip.NICID, ep LinkEndpoint) *tcpip.Error {
	return s.createNIC(id, "", ep, true, false)
}
func (s *Stack) CreateNamedNIC(id tcpip.NICID, name string, ep LinkEndpoint) *tcpip.Error {
	return s.createNIC(id, name, ep, true, false)
}
func (s *Stack) CreateNamedLoopbackNIC(id tcpip.NICID, name string, ep LinkEndpoint) *tcpip.Error {
	return s.createNIC(id, name, ep, true, true)
}
func (s *Stack) CreateDisabledNIC(id tcpip.NICID, ep LinkEndpoint) *tcpip.Error {
	return s.createNIC(id, "", ep, false, false)
}
func (s *Stack) CreateDisabledNamedNIC(id tcpip.NICID, name string, ep LinkEndpoint) *tcpip.Error {
	return s.createNIC(id, name, ep, false, false)
}
func (s *Stack) EnableNIC(id tcpip.NICID) *tcpip.Error {
	s.mu.RLock()
	defer s.mu.RUnlock()
	nic := s.nics[id]
	if nic == nil {
		return tcpip.ErrUnknownNICID
	}
	return nic.enable()
}
func (s *Stack) CheckNIC(id tcpip.NICID) bool {
	s.mu.RLock()
	nic, ok := s.nics[id]
	s.mu.RUnlock()
	if ok {
		return nic.linkEP.IsAttached()
	}
	return false
}
func (s *Stack) NICAddressRanges() map[tcpip.NICID][]tcpip.Subnet {
	s.mu.RLock()
	defer s.mu.RUnlock()
	nics := map[tcpip.NICID][]tcpip.Subnet{}
	for id, nic := range s.nics {
		nics[id] = append(nics[id], nic.AddressRanges()...)
	}
	return nics
}
type NICInfo struct {
	Name              string
	LinkAddress       tcpip.LinkAddress
	ProtocolAddresses []tcpip.ProtocolAddress
	Flags NICStateFlags
	MTU uint32
	Stats NICStats
}
func (s *Stack) NICInfo() map[tcpip.NICID]NICInfo {
	s.mu.RLock()
	defer s.mu.RUnlock()
	nics := make(map[tcpip.NICID]NICInfo)
	for id, nic := range s.nics {
		flags := NICStateFlags{
			Up:          true,  
			Running:     nic.linkEP.IsAttached(),
			Promiscuous: nic.isPromiscuousMode(),
			Loopback:    nic.linkEP.Capabilities()&CapabilityLoopback != 0,
		}
		nics[id] = NICInfo{
			Name:              nic.name,
			LinkAddress:       nic.linkEP.LinkAddress(),
			ProtocolAddresses: nic.PrimaryAddresses(),
			Flags:             flags,
			MTU:               nic.linkEP.MTU(),
			Stats:             nic.stats,
		}
	}
	return nics
}
type NICStateFlags struct {
	Up bool
	Running bool
	Promiscuous bool
	Loopback bool
}
func (s *Stack) AddAddress(id tcpip.NICID, protocol tcpip.NetworkProtocolNumber, addr tcpip.Address) *tcpip.Error {
	return s.AddAddressWithOptions(id, protocol, addr, CanBePrimaryEndpoint)
}