Encapsulate netstack metrics
PiperOrigin-RevId: 209943212 Change-Id: I96dcbc7c2ab2426e510b94a564436505256c5c79
This commit is contained in:
parent
a78df1d874
commit
abe7764928
|
@ -282,12 +282,12 @@ func (n *NIC) RemoveAddress(addr tcpip.Address) *tcpip.Error {
|
||||||
func (n *NIC) DeliverNetworkPacket(linkEP LinkEndpoint, remoteLinkAddr tcpip.LinkAddress, protocol tcpip.NetworkProtocolNumber, vv *buffer.VectorisedView) {
|
func (n *NIC) DeliverNetworkPacket(linkEP LinkEndpoint, remoteLinkAddr tcpip.LinkAddress, protocol tcpip.NetworkProtocolNumber, vv *buffer.VectorisedView) {
|
||||||
netProto, ok := n.stack.networkProtocols[protocol]
|
netProto, ok := n.stack.networkProtocols[protocol]
|
||||||
if !ok {
|
if !ok {
|
||||||
atomic.AddUint64(&n.stack.stats.UnknownProtocolRcvdPackets, 1)
|
n.stack.stats.UnknownProtocolRcvdPackets.Increment()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(vv.First()) < netProto.MinimumPacketSize() {
|
if len(vv.First()) < netProto.MinimumPacketSize() {
|
||||||
atomic.AddUint64(&n.stack.stats.MalformedRcvdPackets, 1)
|
n.stack.stats.MalformedRcvdPackets.Increment()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -330,7 +330,7 @@ func (n *NIC) DeliverNetworkPacket(linkEP LinkEndpoint, remoteLinkAddr tcpip.Lin
|
||||||
}
|
}
|
||||||
|
|
||||||
if ref == nil {
|
if ref == nil {
|
||||||
atomic.AddUint64(&n.stack.stats.UnknownNetworkEndpointRcvdPackets, 1)
|
n.stack.stats.UnknownNetworkEndpointRcvdPackets.Increment()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -345,19 +345,19 @@ func (n *NIC) DeliverNetworkPacket(linkEP LinkEndpoint, remoteLinkAddr tcpip.Lin
|
||||||
func (n *NIC) DeliverTransportPacket(r *Route, protocol tcpip.TransportProtocolNumber, vv *buffer.VectorisedView) {
|
func (n *NIC) DeliverTransportPacket(r *Route, protocol tcpip.TransportProtocolNumber, vv *buffer.VectorisedView) {
|
||||||
state, ok := n.stack.transportProtocols[protocol]
|
state, ok := n.stack.transportProtocols[protocol]
|
||||||
if !ok {
|
if !ok {
|
||||||
atomic.AddUint64(&n.stack.stats.UnknownProtocolRcvdPackets, 1)
|
n.stack.stats.UnknownProtocolRcvdPackets.Increment()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
transProto := state.proto
|
transProto := state.proto
|
||||||
if len(vv.First()) < transProto.MinimumPacketSize() {
|
if len(vv.First()) < transProto.MinimumPacketSize() {
|
||||||
atomic.AddUint64(&n.stack.stats.MalformedRcvdPackets, 1)
|
n.stack.stats.MalformedRcvdPackets.Increment()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
srcPort, dstPort, err := transProto.ParsePorts(vv.First())
|
srcPort, dstPort, err := transProto.ParsePorts(vv.First())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
atomic.AddUint64(&n.stack.stats.MalformedRcvdPackets, 1)
|
n.stack.stats.MalformedRcvdPackets.Increment()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -379,7 +379,7 @@ func (n *NIC) DeliverTransportPacket(r *Route, protocol tcpip.TransportProtocolN
|
||||||
// We could not find an appropriate destination for this packet, so
|
// We could not find an appropriate destination for this packet, so
|
||||||
// deliver it to the global handler.
|
// deliver it to the global handler.
|
||||||
if !transProto.HandleUnknownDestinationPacket(r, id, vv) {
|
if !transProto.HandleUnknownDestinationPacket(r, id, vv) {
|
||||||
atomic.AddUint64(&n.stack.stats.MalformedRcvdPackets, 1)
|
n.stack.stats.MalformedRcvdPackets.Increment()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,6 @@ package stack
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"gvisor.googlesource.com/gvisor/pkg/sleep"
|
"gvisor.googlesource.com/gvisor/pkg/sleep"
|
||||||
|
@ -308,6 +307,9 @@ type Options struct {
|
||||||
//
|
//
|
||||||
// If no Clock is specified, the clock source will be time.Now.
|
// If no Clock is specified, the clock source will be time.Now.
|
||||||
Clock tcpip.Clock
|
Clock tcpip.Clock
|
||||||
|
|
||||||
|
// Stats are optional statistic counters.
|
||||||
|
Stats tcpip.Stats
|
||||||
}
|
}
|
||||||
|
|
||||||
// New allocates a new networking stack with only the requested networking and
|
// New allocates a new networking stack with only the requested networking and
|
||||||
|
@ -331,6 +333,7 @@ func New(network []string, transport []string, opts Options) *Stack {
|
||||||
linkAddrCache: newLinkAddrCache(ageLimit, resolutionTimeout, resolutionAttempts),
|
linkAddrCache: newLinkAddrCache(ageLimit, resolutionTimeout, resolutionAttempts),
|
||||||
PortManager: ports.NewPortManager(),
|
PortManager: ports.NewPortManager(),
|
||||||
clock: clock,
|
clock: clock,
|
||||||
|
stats: opts.Stats.FillIn(),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add specified network protocols.
|
// Add specified network protocols.
|
||||||
|
@ -437,27 +440,12 @@ func (s *Stack) NowNanoseconds() int64 {
|
||||||
return s.clock.NowNanoseconds()
|
return s.clock.NowNanoseconds()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stats returns a snapshot of the current stats.
|
// Stats returns a mutable copy of the current stats.
|
||||||
//
|
|
||||||
// NOTE: The underlying stats are updated using atomic instructions as a result
|
|
||||||
// the snapshot returned does not represent the value of all the stats at any
|
|
||||||
// single given point of time.
|
|
||||||
// TODO: Make stats available in sentry for debugging/diag.
|
|
||||||
func (s *Stack) Stats() tcpip.Stats {
|
|
||||||
return tcpip.Stats{
|
|
||||||
UnknownProtocolRcvdPackets: atomic.LoadUint64(&s.stats.UnknownProtocolRcvdPackets),
|
|
||||||
UnknownNetworkEndpointRcvdPackets: atomic.LoadUint64(&s.stats.UnknownNetworkEndpointRcvdPackets),
|
|
||||||
MalformedRcvdPackets: atomic.LoadUint64(&s.stats.MalformedRcvdPackets),
|
|
||||||
DroppedPackets: atomic.LoadUint64(&s.stats.DroppedPackets),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// MutableStats returns a mutable copy of the current stats.
|
|
||||||
//
|
//
|
||||||
// This is not generally exported via the public interface, but is available
|
// This is not generally exported via the public interface, but is available
|
||||||
// internally.
|
// internally.
|
||||||
func (s *Stack) MutableStats() *tcpip.Stats {
|
func (s *Stack) Stats() tcpip.Stats {
|
||||||
return &s.stats
|
return s.stats
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetRouteTable assigns the route table to be used by this stack. It
|
// SetRouteTable assigns the route table to be used by this stack. It
|
||||||
|
|
|
@ -34,6 +34,7 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"gvisor.googlesource.com/gvisor/pkg/tcpip/buffer"
|
"gvisor.googlesource.com/gvisor/pkg/tcpip/buffer"
|
||||||
|
@ -465,23 +466,62 @@ type TransportProtocolNumber uint32
|
||||||
// NetworkProtocolNumber is the number of a network protocol.
|
// NetworkProtocolNumber is the number of a network protocol.
|
||||||
type NetworkProtocolNumber uint32
|
type NetworkProtocolNumber uint32
|
||||||
|
|
||||||
|
// A StatCounter keeps track of a statistic.
|
||||||
|
type StatCounter struct {
|
||||||
|
count uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
// Increment adds one to the counter.
|
||||||
|
func (s *StatCounter) Increment() {
|
||||||
|
atomic.AddUint64(&s.count, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Value returns the current value of the counter.
|
||||||
|
func (s *StatCounter) Value() uint64 {
|
||||||
|
return atomic.LoadUint64(&s.count)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IncrementBy increments the counter by v.
|
||||||
|
func (s *StatCounter) IncrementBy(v uint64) {
|
||||||
|
atomic.AddUint64(&s.count, v)
|
||||||
|
}
|
||||||
|
|
||||||
// Stats holds statistics about the networking stack.
|
// Stats holds statistics about the networking stack.
|
||||||
|
//
|
||||||
|
// All fields are optional.
|
||||||
type Stats struct {
|
type Stats struct {
|
||||||
// UnknownProtocolRcvdPackets is the number of packets received by the
|
// UnknownProtocolRcvdPackets is the number of packets received by the
|
||||||
// stack that were for an unknown or unsupported protocol.
|
// stack that were for an unknown or unsupported protocol.
|
||||||
UnknownProtocolRcvdPackets uint64
|
UnknownProtocolRcvdPackets *StatCounter
|
||||||
|
|
||||||
// UnknownNetworkEndpointRcvdPackets is the number of packets received
|
// UnknownNetworkEndpointRcvdPackets is the number of packets received
|
||||||
// by the stack that were for a supported network protocol, but whose
|
// by the stack that were for a supported network protocol, but whose
|
||||||
// destination address didn't having a matching endpoint.
|
// destination address didn't having a matching endpoint.
|
||||||
UnknownNetworkEndpointRcvdPackets uint64
|
UnknownNetworkEndpointRcvdPackets *StatCounter
|
||||||
|
|
||||||
// MalformedRcvPackets is the number of packets received by the stack
|
// MalformedRcvPackets is the number of packets received by the stack
|
||||||
// that were deemed malformed.
|
// that were deemed malformed.
|
||||||
MalformedRcvdPackets uint64
|
MalformedRcvdPackets *StatCounter
|
||||||
|
|
||||||
// DroppedPackets is the number of packets dropped due to full queues.
|
// DroppedPackets is the number of packets dropped due to full queues.
|
||||||
DroppedPackets uint64
|
DroppedPackets *StatCounter
|
||||||
|
}
|
||||||
|
|
||||||
|
// FillIn returns a copy of s with nil fields initialized to new StatCounters.
|
||||||
|
func (s Stats) FillIn() Stats {
|
||||||
|
if s.UnknownProtocolRcvdPackets == nil {
|
||||||
|
s.UnknownProtocolRcvdPackets = &StatCounter{}
|
||||||
|
}
|
||||||
|
if s.UnknownNetworkEndpointRcvdPackets == nil {
|
||||||
|
s.UnknownNetworkEndpointRcvdPackets = &StatCounter{}
|
||||||
|
}
|
||||||
|
if s.MalformedRcvdPackets == nil {
|
||||||
|
s.MalformedRcvdPackets = &StatCounter{}
|
||||||
|
}
|
||||||
|
if s.DroppedPackets == nil {
|
||||||
|
s.DroppedPackets = &StatCounter{}
|
||||||
|
}
|
||||||
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
// String implements the fmt.Stringer interface.
|
// String implements the fmt.Stringer interface.
|
||||||
|
|
|
@ -16,7 +16,6 @@ package tcp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"gvisor.googlesource.com/gvisor/pkg/rand"
|
"gvisor.googlesource.com/gvisor/pkg/rand"
|
||||||
|
@ -292,7 +291,7 @@ func (h *handshake) synRcvdState(s *segment) *tcpip.Error {
|
||||||
// not carry a timestamp option then the segment must be dropped
|
// not carry a timestamp option then the segment must be dropped
|
||||||
// as per https://tools.ietf.org/html/rfc7323#section-3.2.
|
// as per https://tools.ietf.org/html/rfc7323#section-3.2.
|
||||||
if h.ep.sendTSOk && !s.parsedOptions.TS {
|
if h.ep.sendTSOk && !s.parsedOptions.TS {
|
||||||
atomic.AddUint64(&h.ep.stack.MutableStats().DroppedPackets, 1)
|
h.ep.stack.Stats().DroppedPackets.Increment()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -793,7 +792,7 @@ func (e *endpoint) handleSegments() *tcpip.Error {
|
||||||
// must be dropped as per
|
// must be dropped as per
|
||||||
// https://tools.ietf.org/html/rfc7323#section-3.2.
|
// https://tools.ietf.org/html/rfc7323#section-3.2.
|
||||||
if e.sendTSOk && !s.parsedOptions.TS {
|
if e.sendTSOk && !s.parsedOptions.TS {
|
||||||
atomic.AddUint64(&e.stack.MutableStats().DroppedPackets, 1)
|
e.stack.Stats().DroppedPackets.Increment()
|
||||||
s.decRef()
|
s.decRef()
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
|
@ -1225,7 +1225,7 @@ func (e *endpoint) GetRemoteAddress() (tcpip.FullAddress, *tcpip.Error) {
|
||||||
func (e *endpoint) HandlePacket(r *stack.Route, id stack.TransportEndpointID, vv *buffer.VectorisedView) {
|
func (e *endpoint) HandlePacket(r *stack.Route, id stack.TransportEndpointID, vv *buffer.VectorisedView) {
|
||||||
s := newSegment(r, id, vv)
|
s := newSegment(r, id, vv)
|
||||||
if !s.parse() {
|
if !s.parse() {
|
||||||
atomic.AddUint64(&e.stack.MutableStats().MalformedRcvdPackets, 1)
|
e.stack.Stats().MalformedRcvdPackets.Increment()
|
||||||
s.decRef()
|
s.decRef()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -1235,7 +1235,7 @@ func (e *endpoint) HandlePacket(r *stack.Route, id stack.TransportEndpointID, vv
|
||||||
e.newSegmentWaker.Assert()
|
e.newSegmentWaker.Assert()
|
||||||
} else {
|
} else {
|
||||||
// The queue is full, so we drop the segment.
|
// The queue is full, so we drop the segment.
|
||||||
atomic.AddUint64(&e.stack.MutableStats().DroppedPackets, 1)
|
e.stack.Stats().DroppedPackets.Increment()
|
||||||
s.decRef()
|
s.decRef()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -268,7 +268,8 @@ func TestSegmentDropWhenTimestampMissing(t *testing.T) {
|
||||||
defer c.WQ.EventUnregister(&we)
|
defer c.WQ.EventUnregister(&we)
|
||||||
|
|
||||||
stk := c.Stack()
|
stk := c.Stack()
|
||||||
droppedPackets := stk.Stats().DroppedPackets
|
droppedPacketsStat := stk.Stats().DroppedPackets
|
||||||
|
droppedPackets := droppedPacketsStat.Value()
|
||||||
data := []byte{1, 2, 3}
|
data := []byte{1, 2, 3}
|
||||||
// Save the sequence number as we will reset it later down
|
// Save the sequence number as we will reset it later down
|
||||||
// in the test.
|
// in the test.
|
||||||
|
@ -283,11 +284,11 @@ func TestSegmentDropWhenTimestampMissing(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Assert that DroppedPackets was incremented by 1.
|
// Assert that DroppedPackets was incremented by 1.
|
||||||
if got, want := stk.Stats().DroppedPackets, droppedPackets+1; got != want {
|
if got, want := droppedPacketsStat.Value(), droppedPackets+1; got != want {
|
||||||
t.Fatalf("incorrect number of dropped packets, got: %v, want: %v", got, want)
|
t.Fatalf("incorrect number of dropped packets, got: %v, want: %v", got, want)
|
||||||
}
|
}
|
||||||
|
|
||||||
droppedPackets = stk.Stats().DroppedPackets
|
droppedPackets = droppedPacketsStat.Value()
|
||||||
// Reset the sequence number so that the other endpoint accepts
|
// Reset the sequence number so that the other endpoint accepts
|
||||||
// this segment and does not treat it like an out of order delivery.
|
// this segment and does not treat it like an out of order delivery.
|
||||||
rep.NextSeqNum = savedSeqNum
|
rep.NextSeqNum = savedSeqNum
|
||||||
|
@ -301,7 +302,7 @@ func TestSegmentDropWhenTimestampMissing(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Assert that DroppedPackets was not incremented by 1.
|
// Assert that DroppedPackets was not incremented by 1.
|
||||||
if got, want := stk.Stats().DroppedPackets, droppedPackets; got != want {
|
if got, want := droppedPacketsStat.Value(), droppedPackets; got != want {
|
||||||
t.Fatalf("incorrect number of dropped packets, got: %v, want: %v", got, want)
|
t.Fatalf("incorrect number of dropped packets, got: %v, want: %v", got, want)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue