snapshot: sagernet/gvisor v0.0.0-20250811.0-sing-box-mod.1

Содержимое пина, зафиксированного в go.mod sing-box-lx, одним коммитом
без истории. Полная история SagerNet/gvisor — 1.45 ГБ и клонируется в
каждой CI-джобе; наша дельта — одна вставка в одну функцию, история для
неё не нужна.

Module path github.com/sagernet/gvisor сохранён намеренно: на него
опирается replace-директива суперпроекта.

Патч поверх — отдельным коммитом, чтобы дельта читалась одним git show
и переносилась на новый пин копированием.

SPECS/TASKS/048-GVISOR_HANDSHAKE_NIL_CRASH
This commit is contained in:
Leadaxe 2026-08-04 15:50:08 +03:00
commit 2c4ae3b0a4
712 changed files with 185689 additions and 0 deletions

View file

@ -0,0 +1,304 @@
// Copyright 2021 The gVisor Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Package ip holds IPv4/IPv6 common utilities.
package ip
import (
"bytes"
"fmt"
"io"
"github.com/sagernet/gvisor/pkg/sync"
"github.com/sagernet/gvisor/pkg/tcpip"
"github.com/sagernet/gvisor/pkg/tcpip/stack"
)
type extendRequest int
const (
notRequested extendRequest = iota
requested
extended
)
// +stateify savable
type dadState struct {
nonce []byte
extendRequest extendRequest
done *bool
timer tcpip.Timer
completionHandlers []stack.DADCompletionHandler
}
// DADProtocol is a protocol whose core state machine can be represented by DAD.
type DADProtocol interface {
// SendDADMessage attempts to send a DAD probe message.
SendDADMessage(tcpip.Address, []byte) tcpip.Error
}
// DADOptions holds options for DAD.
//
// +stateify savable
type DADOptions struct {
Clock tcpip.Clock
// TODO(b/341946753): Restore when netstack is savable.
SecureRNG io.Reader `state:"nosave"`
NonceSize uint8
ExtendDADTransmits uint8
Protocol DADProtocol
NICID tcpip.NICID
}
// DAD performs duplicate address detection for addresses.
//
// +stateify savable
type DAD struct {
opts DADOptions
configs stack.DADConfigurations
protocolMU sync.Locker `state:"nosave"`
addresses map[tcpip.Address]dadState
}
// Init initializes the DAD state.
//
// Must only be called once for the lifetime of d; Init will panic if it is
// called twice.
//
// The lock will only be taken when timers fire.
func (d *DAD) Init(protocolMU sync.Locker, configs stack.DADConfigurations, opts DADOptions) {
if d.addresses != nil {
panic("attempted to initialize DAD state twice")
}
if opts.NonceSize != 0 && opts.ExtendDADTransmits == 0 {
panic(fmt.Sprintf("given a non-zero value for NonceSize (%d) but zero for ExtendDADTransmits", opts.NonceSize))
}
configs.Validate()
*d = DAD{
opts: opts,
configs: configs,
protocolMU: protocolMU,
addresses: make(map[tcpip.Address]dadState),
}
}
// CheckDuplicateAddressLocked performs DAD for an address, calling the
// completion handler once DAD resolves.
//
// If DAD is already performing for the provided address, h will be called when
// the currently running process completes.
//
// Precondition: d.protocolMU must be locked.
func (d *DAD) CheckDuplicateAddressLocked(addr tcpip.Address, h stack.DADCompletionHandler) stack.DADCheckAddressDisposition {
if d.configs.DupAddrDetectTransmits == 0 {
return stack.DADDisabled
}
ret := stack.DADAlreadyRunning
s, ok := d.addresses[addr]
if !ok {
ret = stack.DADStarting
remaining := d.configs.DupAddrDetectTransmits
// Protected by d.protocolMU.
done := false
s = dadState{
done: &done,
timer: d.opts.Clock.AfterFunc(0, func() {
dadDone := remaining == 0
nonce, earlyReturn := func() ([]byte, bool) {
d.protocolMU.Lock()
defer d.protocolMU.Unlock()
if done {
return nil, true
}
s, ok := d.addresses[addr]
if !ok {
panic(fmt.Sprintf("dad: timer fired but missing state for %s on NIC(%d)", addr, d.opts.NICID))
}
// As per RFC 7527 section 4
//
// If any probe is looped back within RetransTimer milliseconds
// after having sent DupAddrDetectTransmits NS(DAD) messages, the
// interface continues with another MAX_MULTICAST_SOLICIT number of
// NS(DAD) messages transmitted RetransTimer milliseconds apart.
if dadDone && s.extendRequest == requested {
dadDone = false
remaining = d.opts.ExtendDADTransmits
s.extendRequest = extended
}
if !dadDone && d.opts.NonceSize != 0 {
if s.nonce == nil {
s.nonce = make([]byte, d.opts.NonceSize)
}
if n, err := io.ReadFull(d.opts.SecureRNG, s.nonce); err != nil {
panic(fmt.Sprintf("SecureRNG.Read(...): %s", err))
} else if n != len(s.nonce) {
panic(fmt.Sprintf("expected to read %d bytes from secure RNG, only read %d bytes", len(s.nonce), n))
}
}
d.addresses[addr] = s
return s.nonce, false
}()
if earlyReturn {
return
}
var err tcpip.Error
if !dadDone {
err = d.opts.Protocol.SendDADMessage(addr, nonce)
}
d.protocolMU.Lock()
defer d.protocolMU.Unlock()
if done {
return
}
s, ok := d.addresses[addr]
if !ok {
panic(fmt.Sprintf("dad: timer fired but missing state for %s on NIC(%d)", addr, d.opts.NICID))
}
if !dadDone && err == nil {
remaining--
s.timer.Reset(d.configs.RetransmitTimer)
return
}
// At this point we know that either DAD has resolved or we hit an error
// sending the last DAD message. Either way, clear the DAD state.
done = false
s.timer.Stop()
delete(d.addresses, addr)
var res stack.DADResult = &stack.DADSucceeded{}
if err != nil {
res = &stack.DADError{Err: err}
}
for _, h := range s.completionHandlers {
h(res)
}
}),
}
}
s.completionHandlers = append(s.completionHandlers, h)
d.addresses[addr] = s
return ret
}
// ExtendIfNonceEqualLockedDisposition enumerates the possible results from
// ExtendIfNonceEqualLocked.
type ExtendIfNonceEqualLockedDisposition int
const (
// Extended indicates that the DAD process was extended.
Extended ExtendIfNonceEqualLockedDisposition = iota
// AlreadyExtended indicates that the DAD process was already extended.
AlreadyExtended
// NoDADStateFound indicates that DAD state was not found for the address.
NoDADStateFound
// NonceDisabled indicates that nonce values are not sent with DAD messages.
NonceDisabled
// NonceNotEqual indicates that the nonce value passed and the nonce in the
// last send DAD message are not equal.
NonceNotEqual
)
// ExtendIfNonceEqualLocked extends the DAD process if the provided nonce is the
// same as the nonce sent in the last DAD message.
//
// Precondition: d.protocolMU must be locked.
func (d *DAD) ExtendIfNonceEqualLocked(addr tcpip.Address, nonce []byte) ExtendIfNonceEqualLockedDisposition {
s, ok := d.addresses[addr]
if !ok {
return NoDADStateFound
}
if d.opts.NonceSize == 0 {
return NonceDisabled
}
if s.extendRequest != notRequested {
return AlreadyExtended
}
// As per RFC 7527 section 4
//
// If any probe is looped back within RetransTimer milliseconds after having
// sent DupAddrDetectTransmits NS(DAD) messages, the interface continues
// with another MAX_MULTICAST_SOLICIT number of NS(DAD) messages transmitted
// RetransTimer milliseconds apart.
//
// If a DAD message has already been sent and the nonce value we observed is
// the same as the nonce value we last sent, then we assume our probe was
// looped back and request an extension to the DAD process.
//
// Note, the first DAD message is sent asynchronously so we need to make sure
// that we sent a DAD message by checking if we have a nonce value set.
if s.nonce != nil && bytes.Equal(s.nonce, nonce) {
s.extendRequest = requested
d.addresses[addr] = s
return Extended
}
return NonceNotEqual
}
// StopLocked stops a currently running DAD process.
//
// Precondition: d.protocolMU must be locked.
func (d *DAD) StopLocked(addr tcpip.Address, reason stack.DADResult) {
s, ok := d.addresses[addr]
if !ok {
return
}
*s.done = true
s.timer.Stop()
delete(d.addresses, addr)
for _, h := range s.completionHandlers {
h(reason)
}
}
// SetConfigsLocked sets the DAD configurations.
//
// Precondition: d.protocolMU must be locked.
func (d *DAD) SetConfigsLocked(c stack.DADConfigurations) {
c.Validate()
d.configs = c
}

View file

@ -0,0 +1,129 @@
// Copyright 2021 The gVisor Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package ip
import (
"fmt"
"github.com/sagernet/gvisor/pkg/tcpip"
)
// ForwardingError represents an error that occurred while trying to forward
// a packet.
type ForwardingError interface {
isForwardingError()
fmt.Stringer
}
// ErrTTLExceeded indicates that the received packet's TTL has been exceeded.
type ErrTTLExceeded struct{}
func (*ErrTTLExceeded) isForwardingError() {}
func (*ErrTTLExceeded) String() string { return "ttl exceeded" }
// ErrOutgoingDeviceNoBufferSpace indicates that the outgoing device does not
// have enough space to hold a buffer.
type ErrOutgoingDeviceNoBufferSpace struct{}
func (*ErrOutgoingDeviceNoBufferSpace) isForwardingError() {}
func (*ErrOutgoingDeviceNoBufferSpace) String() string { return "no device buffer space" }
// ErrParameterProblem indicates the received packet had a problem with an IP
// parameter.
type ErrParameterProblem struct{}
func (*ErrParameterProblem) isForwardingError() {}
func (*ErrParameterProblem) String() string { return "parameter problem" }
// ErrInitializingSourceAddress indicates the received packet had a source
// address that may only be used on the local network as part of initialization
// work.
type ErrInitializingSourceAddress struct{}
func (*ErrInitializingSourceAddress) isForwardingError() {}
func (*ErrInitializingSourceAddress) String() string { return "initializing source address" }
// ErrLinkLocalSourceAddress indicates the received packet had a link-local
// source address.
type ErrLinkLocalSourceAddress struct{}
func (*ErrLinkLocalSourceAddress) isForwardingError() {}
func (*ErrLinkLocalSourceAddress) String() string { return "link local source address" }
// ErrLinkLocalDestinationAddress indicates the received packet had a link-local
// destination address.
type ErrLinkLocalDestinationAddress struct{}
func (*ErrLinkLocalDestinationAddress) isForwardingError() {}
func (*ErrLinkLocalDestinationAddress) String() string { return "link local destination address" }
// ErrHostUnreachable indicates that the destination host could not be reached.
type ErrHostUnreachable struct{}
func (*ErrHostUnreachable) isForwardingError() {}
func (*ErrHostUnreachable) String() string { return "no route to host" }
// ErrMessageTooLong indicates the packet was too big for the outgoing MTU.
//
// +stateify savable
type ErrMessageTooLong struct{}
func (*ErrMessageTooLong) isForwardingError() {}
func (*ErrMessageTooLong) String() string { return "message too long" }
// ErrNoMulticastPendingQueueBufferSpace indicates that a multicast packet
// could not be added to the pending packet queue due to insufficient buffer
// space.
//
// +stateify savable
type ErrNoMulticastPendingQueueBufferSpace struct{}
func (*ErrNoMulticastPendingQueueBufferSpace) isForwardingError() {}
func (*ErrNoMulticastPendingQueueBufferSpace) String() string { return "no buffer space" }
// ErrUnexpectedMulticastInputInterface indicates that the interface that the
// packet arrived on did not match the routes expected input interface.
type ErrUnexpectedMulticastInputInterface struct{}
func (*ErrUnexpectedMulticastInputInterface) isForwardingError() {}
func (*ErrUnexpectedMulticastInputInterface) String() string { return "unexpected input interface" }
// ErrUnknownOutputEndpoint indicates that the output endpoint associated with
// a route could not be found.
type ErrUnknownOutputEndpoint struct{}
func (*ErrUnknownOutputEndpoint) isForwardingError() {}
func (*ErrUnknownOutputEndpoint) String() string { return "unknown endpoint" }
// ErrOther indicates the packet coould not be forwarded for a reason
// captured by the contained error.
type ErrOther struct {
Err tcpip.Error
}
func (*ErrOther) isForwardingError() {}
func (e *ErrOther) String() string { return fmt.Sprintf("other tcpip error: %s", e.Err) }

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,435 @@
// automatically generated by stateify.
package ip
import (
"context"
"github.com/sagernet/gvisor/pkg/state"
)
func (d *dadState) StateTypeName() string {
return "pkg/tcpip/network/internal/ip.dadState"
}
func (d *dadState) StateFields() []string {
return []string{
"nonce",
"extendRequest",
"done",
"timer",
"completionHandlers",
}
}
func (d *dadState) beforeSave() {}
// +checklocksignore
func (d *dadState) StateSave(stateSinkObject state.Sink) {
d.beforeSave()
stateSinkObject.Save(0, &d.nonce)
stateSinkObject.Save(1, &d.extendRequest)
stateSinkObject.Save(2, &d.done)
stateSinkObject.Save(3, &d.timer)
stateSinkObject.Save(4, &d.completionHandlers)
}
func (d *dadState) afterLoad(context.Context) {}
// +checklocksignore
func (d *dadState) StateLoad(ctx context.Context, stateSourceObject state.Source) {
stateSourceObject.Load(0, &d.nonce)
stateSourceObject.Load(1, &d.extendRequest)
stateSourceObject.Load(2, &d.done)
stateSourceObject.Load(3, &d.timer)
stateSourceObject.Load(4, &d.completionHandlers)
}
func (d *DADOptions) StateTypeName() string {
return "pkg/tcpip/network/internal/ip.DADOptions"
}
func (d *DADOptions) StateFields() []string {
return []string{
"Clock",
"NonceSize",
"ExtendDADTransmits",
"Protocol",
"NICID",
}
}
func (d *DADOptions) beforeSave() {}
// +checklocksignore
func (d *DADOptions) StateSave(stateSinkObject state.Sink) {
d.beforeSave()
stateSinkObject.Save(0, &d.Clock)
stateSinkObject.Save(1, &d.NonceSize)
stateSinkObject.Save(2, &d.ExtendDADTransmits)
stateSinkObject.Save(3, &d.Protocol)
stateSinkObject.Save(4, &d.NICID)
}
func (d *DADOptions) afterLoad(context.Context) {}
// +checklocksignore
func (d *DADOptions) StateLoad(ctx context.Context, stateSourceObject state.Source) {
stateSourceObject.Load(0, &d.Clock)
stateSourceObject.Load(1, &d.NonceSize)
stateSourceObject.Load(2, &d.ExtendDADTransmits)
stateSourceObject.Load(3, &d.Protocol)
stateSourceObject.Load(4, &d.NICID)
}
func (d *DAD) StateTypeName() string {
return "pkg/tcpip/network/internal/ip.DAD"
}
func (d *DAD) StateFields() []string {
return []string{
"opts",
"configs",
"addresses",
}
}
func (d *DAD) beforeSave() {}
// +checklocksignore
func (d *DAD) StateSave(stateSinkObject state.Sink) {
d.beforeSave()
stateSinkObject.Save(0, &d.opts)
stateSinkObject.Save(1, &d.configs)
stateSinkObject.Save(2, &d.addresses)
}
func (d *DAD) afterLoad(context.Context) {}
// +checklocksignore
func (d *DAD) StateLoad(ctx context.Context, stateSourceObject state.Source) {
stateSourceObject.Load(0, &d.opts)
stateSourceObject.Load(1, &d.configs)
stateSourceObject.Load(2, &d.addresses)
}
func (e *ErrMessageTooLong) StateTypeName() string {
return "pkg/tcpip/network/internal/ip.ErrMessageTooLong"
}
func (e *ErrMessageTooLong) StateFields() []string {
return []string{}
}
func (e *ErrMessageTooLong) beforeSave() {}
// +checklocksignore
func (e *ErrMessageTooLong) StateSave(stateSinkObject state.Sink) {
e.beforeSave()
}
func (e *ErrMessageTooLong) afterLoad(context.Context) {}
// +checklocksignore
func (e *ErrMessageTooLong) StateLoad(ctx context.Context, stateSourceObject state.Source) {
}
func (e *ErrNoMulticastPendingQueueBufferSpace) StateTypeName() string {
return "pkg/tcpip/network/internal/ip.ErrNoMulticastPendingQueueBufferSpace"
}
func (e *ErrNoMulticastPendingQueueBufferSpace) StateFields() []string {
return []string{}
}
func (e *ErrNoMulticastPendingQueueBufferSpace) beforeSave() {}
// +checklocksignore
func (e *ErrNoMulticastPendingQueueBufferSpace) StateSave(stateSinkObject state.Sink) {
e.beforeSave()
}
func (e *ErrNoMulticastPendingQueueBufferSpace) afterLoad(context.Context) {}
// +checklocksignore
func (e *ErrNoMulticastPendingQueueBufferSpace) StateLoad(ctx context.Context, stateSourceObject state.Source) {
}
func (m *multicastGroupState) StateTypeName() string {
return "pkg/tcpip/network/internal/ip.multicastGroupState"
}
func (m *multicastGroupState) StateFields() []string {
return []string{
"joins",
"transmissionLeft",
"lastToSendReport",
"delayedReportJob",
"queriedIncludeSources",
"deleteScheduled",
}
}
func (m *multicastGroupState) beforeSave() {}
// +checklocksignore
func (m *multicastGroupState) StateSave(stateSinkObject state.Sink) {
m.beforeSave()
stateSinkObject.Save(0, &m.joins)
stateSinkObject.Save(1, &m.transmissionLeft)
stateSinkObject.Save(2, &m.lastToSendReport)
stateSinkObject.Save(3, &m.delayedReportJob)
stateSinkObject.Save(4, &m.queriedIncludeSources)
stateSinkObject.Save(5, &m.deleteScheduled)
}
func (m *multicastGroupState) afterLoad(context.Context) {}
// +checklocksignore
func (m *multicastGroupState) StateLoad(ctx context.Context, stateSourceObject state.Source) {
stateSourceObject.Load(0, &m.joins)
stateSourceObject.Load(1, &m.transmissionLeft)
stateSourceObject.Load(2, &m.lastToSendReport)
stateSourceObject.Load(3, &m.delayedReportJob)
stateSourceObject.Load(4, &m.queriedIncludeSources)
stateSourceObject.Load(5, &m.deleteScheduled)
}
func (g *GenericMulticastProtocolOptions) StateTypeName() string {
return "pkg/tcpip/network/internal/ip.GenericMulticastProtocolOptions"
}
func (g *GenericMulticastProtocolOptions) StateFields() []string {
return []string{
"Clock",
"Protocol",
"MaxUnsolicitedReportDelay",
}
}
func (g *GenericMulticastProtocolOptions) beforeSave() {}
// +checklocksignore
func (g *GenericMulticastProtocolOptions) StateSave(stateSinkObject state.Sink) {
g.beforeSave()
stateSinkObject.Save(0, &g.Clock)
stateSinkObject.Save(1, &g.Protocol)
stateSinkObject.Save(2, &g.MaxUnsolicitedReportDelay)
}
func (g *GenericMulticastProtocolOptions) afterLoad(context.Context) {}
// +checklocksignore
func (g *GenericMulticastProtocolOptions) StateLoad(ctx context.Context, stateSourceObject state.Source) {
stateSourceObject.Load(0, &g.Clock)
stateSourceObject.Load(1, &g.Protocol)
stateSourceObject.Load(2, &g.MaxUnsolicitedReportDelay)
}
func (g *GenericMulticastProtocolState) StateTypeName() string {
return "pkg/tcpip/network/internal/ip.GenericMulticastProtocolState"
}
func (g *GenericMulticastProtocolState) StateFields() []string {
return []string{
"opts",
"memberships",
"robustnessVariable",
"queryInterval",
"mode",
"modeTimer",
"generalQueryV2Timer",
"stateChangedReportV2Timer",
"stateChangedReportV2TimerSet",
}
}
func (g *GenericMulticastProtocolState) beforeSave() {}
// +checklocksignore
func (g *GenericMulticastProtocolState) StateSave(stateSinkObject state.Sink) {
g.beforeSave()
stateSinkObject.Save(0, &g.opts)
stateSinkObject.Save(1, &g.memberships)
stateSinkObject.Save(2, &g.robustnessVariable)
stateSinkObject.Save(3, &g.queryInterval)
stateSinkObject.Save(4, &g.mode)
stateSinkObject.Save(5, &g.modeTimer)
stateSinkObject.Save(6, &g.generalQueryV2Timer)
stateSinkObject.Save(7, &g.stateChangedReportV2Timer)
stateSinkObject.Save(8, &g.stateChangedReportV2TimerSet)
}
func (g *GenericMulticastProtocolState) afterLoad(context.Context) {}
// +checklocksignore
func (g *GenericMulticastProtocolState) StateLoad(ctx context.Context, stateSourceObject state.Source) {
stateSourceObject.Load(0, &g.opts)
stateSourceObject.Load(1, &g.memberships)
stateSourceObject.Load(2, &g.robustnessVariable)
stateSourceObject.Load(3, &g.queryInterval)
stateSourceObject.Load(4, &g.mode)
stateSourceObject.Load(5, &g.modeTimer)
stateSourceObject.Load(6, &g.generalQueryV2Timer)
stateSourceObject.Load(7, &g.stateChangedReportV2Timer)
stateSourceObject.Load(8, &g.stateChangedReportV2TimerSet)
}
func (m *MultiCounterIPForwardingStats) StateTypeName() string {
return "pkg/tcpip/network/internal/ip.MultiCounterIPForwardingStats"
}
func (m *MultiCounterIPForwardingStats) StateFields() []string {
return []string{
"Unrouteable",
"ExhaustedTTL",
"InitializingSource",
"LinkLocalSource",
"LinkLocalDestination",
"PacketTooBig",
"HostUnreachable",
"ExtensionHeaderProblem",
"UnexpectedMulticastInputInterface",
"UnknownOutputEndpoint",
"NoMulticastPendingQueueBufferSpace",
"OutgoingDeviceNoBufferSpace",
"Errors",
"OutgoingDeviceClosedForSend",
}
}
func (m *MultiCounterIPForwardingStats) beforeSave() {}
// +checklocksignore
func (m *MultiCounterIPForwardingStats) StateSave(stateSinkObject state.Sink) {
m.beforeSave()
stateSinkObject.Save(0, &m.Unrouteable)
stateSinkObject.Save(1, &m.ExhaustedTTL)
stateSinkObject.Save(2, &m.InitializingSource)
stateSinkObject.Save(3, &m.LinkLocalSource)
stateSinkObject.Save(4, &m.LinkLocalDestination)
stateSinkObject.Save(5, &m.PacketTooBig)
stateSinkObject.Save(6, &m.HostUnreachable)
stateSinkObject.Save(7, &m.ExtensionHeaderProblem)
stateSinkObject.Save(8, &m.UnexpectedMulticastInputInterface)
stateSinkObject.Save(9, &m.UnknownOutputEndpoint)
stateSinkObject.Save(10, &m.NoMulticastPendingQueueBufferSpace)
stateSinkObject.Save(11, &m.OutgoingDeviceNoBufferSpace)
stateSinkObject.Save(12, &m.Errors)
stateSinkObject.Save(13, &m.OutgoingDeviceClosedForSend)
}
func (m *MultiCounterIPForwardingStats) afterLoad(context.Context) {}
// +checklocksignore
func (m *MultiCounterIPForwardingStats) StateLoad(ctx context.Context, stateSourceObject state.Source) {
stateSourceObject.Load(0, &m.Unrouteable)
stateSourceObject.Load(1, &m.ExhaustedTTL)
stateSourceObject.Load(2, &m.InitializingSource)
stateSourceObject.Load(3, &m.LinkLocalSource)
stateSourceObject.Load(4, &m.LinkLocalDestination)
stateSourceObject.Load(5, &m.PacketTooBig)
stateSourceObject.Load(6, &m.HostUnreachable)
stateSourceObject.Load(7, &m.ExtensionHeaderProblem)
stateSourceObject.Load(8, &m.UnexpectedMulticastInputInterface)
stateSourceObject.Load(9, &m.UnknownOutputEndpoint)
stateSourceObject.Load(10, &m.NoMulticastPendingQueueBufferSpace)
stateSourceObject.Load(11, &m.OutgoingDeviceNoBufferSpace)
stateSourceObject.Load(12, &m.Errors)
stateSourceObject.Load(13, &m.OutgoingDeviceClosedForSend)
}
func (m *MultiCounterIPStats) StateTypeName() string {
return "pkg/tcpip/network/internal/ip.MultiCounterIPStats"
}
func (m *MultiCounterIPStats) StateFields() []string {
return []string{
"PacketsReceived",
"ValidPacketsReceived",
"DisabledPacketsReceived",
"InvalidDestinationAddressesReceived",
"InvalidSourceAddressesReceived",
"PacketsDelivered",
"PacketsSent",
"OutgoingPacketErrors",
"MalformedPacketsReceived",
"MalformedFragmentsReceived",
"IPTablesPreroutingDropped",
"IPTablesInputDropped",
"IPTablesForwardDropped",
"IPTablesOutputDropped",
"IPTablesPostroutingDropped",
"OptionTimestampReceived",
"OptionRecordRouteReceived",
"OptionRouterAlertReceived",
"OptionUnknownReceived",
"Forwarding",
}
}
func (m *MultiCounterIPStats) beforeSave() {}
// +checklocksignore
func (m *MultiCounterIPStats) StateSave(stateSinkObject state.Sink) {
m.beforeSave()
stateSinkObject.Save(0, &m.PacketsReceived)
stateSinkObject.Save(1, &m.ValidPacketsReceived)
stateSinkObject.Save(2, &m.DisabledPacketsReceived)
stateSinkObject.Save(3, &m.InvalidDestinationAddressesReceived)
stateSinkObject.Save(4, &m.InvalidSourceAddressesReceived)
stateSinkObject.Save(5, &m.PacketsDelivered)
stateSinkObject.Save(6, &m.PacketsSent)
stateSinkObject.Save(7, &m.OutgoingPacketErrors)
stateSinkObject.Save(8, &m.MalformedPacketsReceived)
stateSinkObject.Save(9, &m.MalformedFragmentsReceived)
stateSinkObject.Save(10, &m.IPTablesPreroutingDropped)
stateSinkObject.Save(11, &m.IPTablesInputDropped)
stateSinkObject.Save(12, &m.IPTablesForwardDropped)
stateSinkObject.Save(13, &m.IPTablesOutputDropped)
stateSinkObject.Save(14, &m.IPTablesPostroutingDropped)
stateSinkObject.Save(15, &m.OptionTimestampReceived)
stateSinkObject.Save(16, &m.OptionRecordRouteReceived)
stateSinkObject.Save(17, &m.OptionRouterAlertReceived)
stateSinkObject.Save(18, &m.OptionUnknownReceived)
stateSinkObject.Save(19, &m.Forwarding)
}
func (m *MultiCounterIPStats) afterLoad(context.Context) {}
// +checklocksignore
func (m *MultiCounterIPStats) StateLoad(ctx context.Context, stateSourceObject state.Source) {
stateSourceObject.Load(0, &m.PacketsReceived)
stateSourceObject.Load(1, &m.ValidPacketsReceived)
stateSourceObject.Load(2, &m.DisabledPacketsReceived)
stateSourceObject.Load(3, &m.InvalidDestinationAddressesReceived)
stateSourceObject.Load(4, &m.InvalidSourceAddressesReceived)
stateSourceObject.Load(5, &m.PacketsDelivered)
stateSourceObject.Load(6, &m.PacketsSent)
stateSourceObject.Load(7, &m.OutgoingPacketErrors)
stateSourceObject.Load(8, &m.MalformedPacketsReceived)
stateSourceObject.Load(9, &m.MalformedFragmentsReceived)
stateSourceObject.Load(10, &m.IPTablesPreroutingDropped)
stateSourceObject.Load(11, &m.IPTablesInputDropped)
stateSourceObject.Load(12, &m.IPTablesForwardDropped)
stateSourceObject.Load(13, &m.IPTablesOutputDropped)
stateSourceObject.Load(14, &m.IPTablesPostroutingDropped)
stateSourceObject.Load(15, &m.OptionTimestampReceived)
stateSourceObject.Load(16, &m.OptionRecordRouteReceived)
stateSourceObject.Load(17, &m.OptionRouterAlertReceived)
stateSourceObject.Load(18, &m.OptionUnknownReceived)
stateSourceObject.Load(19, &m.Forwarding)
}
func init() {
state.Register((*dadState)(nil))
state.Register((*DADOptions)(nil))
state.Register((*DAD)(nil))
state.Register((*ErrMessageTooLong)(nil))
state.Register((*ErrNoMulticastPendingQueueBufferSpace)(nil))
state.Register((*multicastGroupState)(nil))
state.Register((*GenericMulticastProtocolOptions)(nil))
state.Register((*GenericMulticastProtocolState)(nil))
state.Register((*MultiCounterIPForwardingStats)(nil))
state.Register((*MultiCounterIPStats)(nil))
}

View file

@ -0,0 +1,219 @@
// Copyright 2020 The gVisor Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package ip
import "github.com/sagernet/gvisor/pkg/tcpip"
// LINT.IfChange(MultiCounterIPForwardingStats)
// MultiCounterIPForwardingStats holds IP forwarding statistics. Each counter
// may have several versions.
//
// +stateify savable
type MultiCounterIPForwardingStats struct {
// Unrouteable is the number of IP packets received which were dropped
// because the netstack could not construct a route to their
// destination.
Unrouteable tcpip.MultiCounterStat
// ExhaustedTTL is the number of IP packets received which were dropped
// because their TTL was exhausted.
ExhaustedTTL tcpip.MultiCounterStat
// InitializingSource is the number of IP packets which were dropped
// because they contained a source address that may only be used on the local
// network as part of initialization work.
InitializingSource tcpip.MultiCounterStat
// LinkLocalSource is the number of IP packets which were dropped
// because they contained a link-local source address.
LinkLocalSource tcpip.MultiCounterStat
// LinkLocalDestination is the number of IP packets which were dropped
// because they contained a link-local destination address.
LinkLocalDestination tcpip.MultiCounterStat
// PacketTooBig is the number of IP packets which were dropped because they
// were too big for the outgoing MTU.
PacketTooBig tcpip.MultiCounterStat
// HostUnreachable is the number of IP packets received which could not be
// successfully forwarded due to an unresolvable next hop.
HostUnreachable tcpip.MultiCounterStat
// ExtensionHeaderProblem is the number of IP packets which were dropped
// because of a problem encountered when processing an IPv6 extension
// header.
ExtensionHeaderProblem tcpip.MultiCounterStat
// UnexpectedMulticastInputInterface is the number of multicast packets that
// were received on an interface that did not match the corresponding route's
// expected input interface.
UnexpectedMulticastInputInterface tcpip.MultiCounterStat
// UnknownOutputEndpoint is the number of packets that could not be forwarded
// because the output endpoint could not be found.
UnknownOutputEndpoint tcpip.MultiCounterStat
// NoMulticastPendingQueueBufferSpace is the number of multicast packets that
// were dropped due to insufficient buffer space in the pending packet queue.
NoMulticastPendingQueueBufferSpace tcpip.MultiCounterStat
// OutgoingDeviceNoBufferSpace is the number of packets that were dropped due
// to insufficient space in the outgoing device.
OutgoingDeviceNoBufferSpace tcpip.MultiCounterStat
// Errors is the number of IP packets received which could not be
// successfully forwarded.
Errors tcpip.MultiCounterStat
// OutgoingDeviceClosedForSend is the number of packets that were dropped due
// to the outgoing device being closed for send.
OutgoingDeviceClosedForSend tcpip.MultiCounterStat
}
// Init sets internal counters to track a and b counters.
func (m *MultiCounterIPForwardingStats) Init(a, b *tcpip.IPForwardingStats) {
m.Unrouteable.Init(a.Unrouteable, b.Unrouteable)
m.Errors.Init(a.Errors, b.Errors)
m.InitializingSource.Init(a.InitializingSource, b.InitializingSource)
m.LinkLocalSource.Init(a.LinkLocalSource, b.LinkLocalSource)
m.LinkLocalDestination.Init(a.LinkLocalDestination, b.LinkLocalDestination)
m.ExtensionHeaderProblem.Init(a.ExtensionHeaderProblem, b.ExtensionHeaderProblem)
m.PacketTooBig.Init(a.PacketTooBig, b.PacketTooBig)
m.ExhaustedTTL.Init(a.ExhaustedTTL, b.ExhaustedTTL)
m.HostUnreachable.Init(a.HostUnreachable, b.HostUnreachable)
m.UnexpectedMulticastInputInterface.Init(a.UnexpectedMulticastInputInterface, b.UnexpectedMulticastInputInterface)
m.UnknownOutputEndpoint.Init(a.UnknownOutputEndpoint, b.UnknownOutputEndpoint)
m.NoMulticastPendingQueueBufferSpace.Init(a.NoMulticastPendingQueueBufferSpace, b.NoMulticastPendingQueueBufferSpace)
m.OutgoingDeviceNoBufferSpace.Init(a.OutgoingDeviceNoBufferSpace, b.OutgoingDeviceNoBufferSpace)
m.OutgoingDeviceClosedForSend.Init(a.OutgoingDeviceClosedForSend, b.OutgoingDeviceClosedForSend)
}
// LINT.ThenChange(../../../tcpip.go:IPForwardingStats)
// LINT.IfChange(MultiCounterIPStats)
// MultiCounterIPStats holds IP statistics, each counter may have several
// versions.
//
// +stateify savable
type MultiCounterIPStats struct {
// PacketsReceived is the number of IP packets received from the link
// layer.
PacketsReceived tcpip.MultiCounterStat
// ValidPacketsReceived is the number of valid IP packets that reached the IP
// layer.
ValidPacketsReceived tcpip.MultiCounterStat
// DisabledPacketsReceived is the number of IP packets received from
// the link layer when the IP layer is disabled.
DisabledPacketsReceived tcpip.MultiCounterStat
// InvalidDestinationAddressesReceived is the number of IP packets
// received with an unknown or invalid destination address.
InvalidDestinationAddressesReceived tcpip.MultiCounterStat
// InvalidSourceAddressesReceived is the number of IP packets received
// with a source address that should never have been received on the
// wire.
InvalidSourceAddressesReceived tcpip.MultiCounterStat
// PacketsDelivered is the number of incoming IP packets successfully
// delivered to the transport layer.
PacketsDelivered tcpip.MultiCounterStat
// PacketsSent is the number of IP packets sent via WritePacket.
PacketsSent tcpip.MultiCounterStat
// OutgoingPacketErrors is the number of IP packets which failed to
// write to a link-layer endpoint.
OutgoingPacketErrors tcpip.MultiCounterStat
// MalformedPacketsReceived is the number of IP Packets that were
// dropped due to the IP packet header failing validation checks.
MalformedPacketsReceived tcpip.MultiCounterStat
// MalformedFragmentsReceived is the number of IP Fragments that were
// dropped due to the fragment failing validation checks.
MalformedFragmentsReceived tcpip.MultiCounterStat
// IPTablesPreroutingDropped is the number of IP packets dropped in the
// Prerouting chain.
IPTablesPreroutingDropped tcpip.MultiCounterStat
// IPTablesInputDropped is the number of IP packets dropped in the
// Input chain.
IPTablesInputDropped tcpip.MultiCounterStat
// IPTablesForwardDropped is the number of IP packets dropped in the
// Forward chain.
IPTablesForwardDropped tcpip.MultiCounterStat
// IPTablesOutputDropped is the number of IP packets dropped in the
// Output chain.
IPTablesOutputDropped tcpip.MultiCounterStat
// IPTablesPostroutingDropped is the number of IP packets dropped in
// the Postrouting chain.
IPTablesPostroutingDropped tcpip.MultiCounterStat
// TODO(https://gvisor.dev/issues/5529): Move the IPv4-only option
// stats out of IPStats.
// OptionTimestampReceived is the number of Timestamp options seen.
OptionTimestampReceived tcpip.MultiCounterStat
// OptionRecordRouteReceived is the number of Record Route options
// seen.
OptionRecordRouteReceived tcpip.MultiCounterStat
// OptionRouterAlertReceived is the number of Router Alert options
// seen.
OptionRouterAlertReceived tcpip.MultiCounterStat
// OptionUnknownReceived is the number of unknown IP options seen.
OptionUnknownReceived tcpip.MultiCounterStat
// Forwarding collects stats related to IP forwarding.
Forwarding MultiCounterIPForwardingStats
}
// Init sets internal counters to track a and b counters.
func (m *MultiCounterIPStats) Init(a, b *tcpip.IPStats) {
m.PacketsReceived.Init(a.PacketsReceived, b.PacketsReceived)
m.ValidPacketsReceived.Init(a.ValidPacketsReceived, b.ValidPacketsReceived)
m.DisabledPacketsReceived.Init(a.DisabledPacketsReceived, b.DisabledPacketsReceived)
m.InvalidDestinationAddressesReceived.Init(a.InvalidDestinationAddressesReceived, b.InvalidDestinationAddressesReceived)
m.InvalidSourceAddressesReceived.Init(a.InvalidSourceAddressesReceived, b.InvalidSourceAddressesReceived)
m.PacketsDelivered.Init(a.PacketsDelivered, b.PacketsDelivered)
m.PacketsSent.Init(a.PacketsSent, b.PacketsSent)
m.OutgoingPacketErrors.Init(a.OutgoingPacketErrors, b.OutgoingPacketErrors)
m.MalformedPacketsReceived.Init(a.MalformedPacketsReceived, b.MalformedPacketsReceived)
m.MalformedFragmentsReceived.Init(a.MalformedFragmentsReceived, b.MalformedFragmentsReceived)
m.IPTablesPreroutingDropped.Init(a.IPTablesPreroutingDropped, b.IPTablesPreroutingDropped)
m.IPTablesInputDropped.Init(a.IPTablesInputDropped, b.IPTablesInputDropped)
m.IPTablesForwardDropped.Init(a.IPTablesForwardDropped, b.IPTablesForwardDropped)
m.IPTablesOutputDropped.Init(a.IPTablesOutputDropped, b.IPTablesOutputDropped)
m.IPTablesPostroutingDropped.Init(a.IPTablesPostroutingDropped, b.IPTablesPostroutingDropped)
m.OptionTimestampReceived.Init(a.OptionTimestampReceived, b.OptionTimestampReceived)
m.OptionRecordRouteReceived.Init(a.OptionRecordRouteReceived, b.OptionRecordRouteReceived)
m.OptionRouterAlertReceived.Init(a.OptionRouterAlertReceived, b.OptionRouterAlertReceived)
m.OptionUnknownReceived.Init(a.OptionUnknownReceived, b.OptionUnknownReceived)
m.Forwarding.Init(&a.Forwarding, &b.Forwarding)
}
// LINT.ThenChange(../../../tcpip.go:IPStats)