summaryrefslogtreecommitdiffhomepage
path: root/pkg/tcpip/network/arp/arp.go
diff options
context:
space:
mode:
authorArthur Sfez <asfez@google.com>2021-01-25 16:50:14 -0800
committergVisor bot <gvisor-bot@google.com>2021-01-25 16:52:05 -0800
commit39db3b93554ea74611602ad4c20dfa5c08e748f2 (patch)
tree406dbe1877169627a2449ce95a3372d479a96590 /pkg/tcpip/network/arp/arp.go
parentb4665aef8717d00f2f3320616ae4ef0914f9a1b4 (diff)
Add per endpoint ARP statistics
The ARP stat NetworkUnreachable was removed, and was replaced by InterfaceHasNoLocalAddress. No stats are recorded when dealing with an missing endpoint (ErrNotConnected) (because if there is no endpoint, there is no valid per-endpoint stats). PiperOrigin-RevId: 353759462
Diffstat (limited to 'pkg/tcpip/network/arp/arp.go')
-rw-r--r--pkg/tcpip/network/arp/arp.go90
1 files changed, 63 insertions, 27 deletions
diff --git a/pkg/tcpip/network/arp/arp.go b/pkg/tcpip/network/arp/arp.go
index 0616b10aa..6bc8c5c02 100644
--- a/pkg/tcpip/network/arp/arp.go
+++ b/pkg/tcpip/network/arp/arp.go
@@ -19,8 +19,10 @@ package arp
import (
"fmt"
+ "reflect"
"sync/atomic"
+ "gvisor.dev/gvisor/pkg/sync"
"gvisor.dev/gvisor/pkg/tcpip"
"gvisor.dev/gvisor/pkg/tcpip/buffer"
"gvisor.dev/gvisor/pkg/tcpip/header"
@@ -50,6 +52,7 @@ type endpoint struct {
nic stack.NetworkInterface
linkAddrCache stack.LinkAddressCache
nud stack.NUDHandler
+ stats sharedStats
}
func (e *endpoint) Enable() *tcpip.Error {
@@ -98,7 +101,9 @@ func (e *endpoint) MaxHeaderLength() uint16 {
return e.nic.MaxHeaderLength() + header.ARPSize
}
-func (*endpoint) Close() {}
+func (e *endpoint) Close() {
+ e.protocol.forgetEndpoint(e.nic.ID())
+}
func (*endpoint) WritePacket(*stack.Route, *stack.GSO, stack.NetworkHeaderParams, *stack.PacketBuffer) *tcpip.Error {
return tcpip.ErrNotSupported
@@ -119,27 +124,27 @@ func (*endpoint) WriteHeaderIncludedPacket(*stack.Route, *stack.PacketBuffer) *t
}
func (e *endpoint) HandlePacket(pkt *stack.PacketBuffer) {
- stats := e.protocol.stack.Stats().ARP
- stats.PacketsReceived.Increment()
+ stats := e.stats.arp
+ stats.packetsReceived.Increment()
if !e.isEnabled() {
- stats.DisabledPacketsReceived.Increment()
+ stats.disabledPacketsReceived.Increment()
return
}
h := header.ARP(pkt.NetworkHeader().View())
if !h.IsValid() {
- stats.MalformedPacketsReceived.Increment()
+ stats.malformedPacketsReceived.Increment()
return
}
switch h.Op() {
case header.ARPRequest:
- stats.RequestsReceived.Increment()
+ stats.requestsReceived.Increment()
localAddr := tcpip.Address(h.ProtocolAddressTarget())
if e.protocol.stack.CheckLocalAddress(e.nic.ID(), header.IPv4ProtocolNumber, localAddr) == 0 {
- stats.RequestsReceivedUnknownTargetAddress.Increment()
+ stats.requestsReceivedUnknownTargetAddress.Increment()
return // we have no useful answer, ignore the request
}
@@ -180,13 +185,13 @@ func (e *endpoint) HandlePacket(pkt *stack.PacketBuffer) {
// Send the packet to the (new) target hardware address on the same
// hardware on which the request was received.
if err := e.nic.WritePacketToRemote(tcpip.LinkAddress(origSender), nil /* gso */, ProtocolNumber, respPkt); err != nil {
- stats.OutgoingRepliesDropped.Increment()
+ stats.outgoingRepliesDropped.Increment()
} else {
- stats.OutgoingRepliesSent.Increment()
+ stats.outgoingRepliesSent.Increment()
}
case header.ARPReply:
- stats.RepliesReceived.Increment()
+ stats.repliesReceived.Increment()
addr := tcpip.Address(h.ProtocolAddressSender())
linkAddr := tcpip.LinkAddress(h.HardwareAddressSender())
@@ -212,21 +217,23 @@ func (e *endpoint) HandlePacket(pkt *stack.PacketBuffer) {
// Stats implements stack.NetworkEndpoint.
func (e *endpoint) Stats() stack.NetworkEndpointStats {
- // TODO(gvisor.dev/issues/4963): Record statistics for ARP.
- return &Stats{}
+ return &e.stats.localStats
}
-var _ stack.NetworkEndpointStats = (*Stats)(nil)
-
-// Stats holds ARP statistics.
-type Stats struct{}
-
-// IsNetworkEndpointStats implements stack.NetworkEndpointStats.
-func (*Stats) IsNetworkEndpointStats() {}
+var _ stack.NetworkProtocol = (*protocol)(nil)
+var _ stack.LinkAddressResolver = (*protocol)(nil)
// protocol implements stack.NetworkProtocol and stack.LinkAddressResolver.
type protocol struct {
stack *stack.Stack
+
+ mu struct {
+ sync.RWMutex
+
+ // eps is keyed by NICID to allow protocol methods to retrieve the correct
+ // endpoint depending on the NIC.
+ eps map[tcpip.NICID]*endpoint
+ }
}
func (p *protocol) Number() tcpip.NetworkProtocolNumber { return ProtocolNumber }
@@ -244,9 +251,25 @@ func (p *protocol) NewEndpoint(nic stack.NetworkInterface, linkAddrCache stack.L
linkAddrCache: linkAddrCache,
nud: nud,
}
+
+ tcpip.InitStatCounters(reflect.ValueOf(&e.stats.localStats).Elem())
+
+ stackStats := p.stack.Stats()
+ e.stats.arp.init(&e.stats.localStats.ARP, &stackStats.ARP)
+
+ p.mu.Lock()
+ p.mu.eps[nic.ID()] = e
+ p.mu.Unlock()
+
return e
}
+func (p *protocol) forgetEndpoint(nicID tcpip.NICID) {
+ p.mu.Lock()
+ defer p.mu.Unlock()
+ delete(p.mu.eps, nicID)
+}
+
// LinkAddressProtocol implements stack.LinkAddressResolver.LinkAddressProtocol.
func (*protocol) LinkAddressProtocol() tcpip.NetworkProtocolNumber {
return header.IPv4ProtocolNumber
@@ -254,28 +277,35 @@ func (*protocol) LinkAddressProtocol() tcpip.NetworkProtocolNumber {
// LinkAddressRequest implements stack.LinkAddressResolver.LinkAddressRequest.
func (p *protocol) LinkAddressRequest(targetAddr, localAddr tcpip.Address, remoteLinkAddr tcpip.LinkAddress, nic stack.NetworkInterface) *tcpip.Error {
- stats := p.stack.Stats().ARP
+ nicID := nic.ID()
+
+ p.mu.Lock()
+ netEP, ok := p.mu.eps[nicID]
+ p.mu.Unlock()
+ if !ok {
+ return tcpip.ErrNotConnected
+ }
+
+ stats := netEP.stats.arp
if len(remoteLinkAddr) == 0 {
remoteLinkAddr = header.EthernetBroadcastAddress
}
- nicID := nic.ID()
if len(localAddr) == 0 {
addr, ok := p.stack.GetMainNICAddress(nicID, header.IPv4ProtocolNumber)
if !ok {
- stats.OutgoingRequestInterfaceHasNoLocalAddressErrors.Increment()
return tcpip.ErrUnknownNICID
}
if len(addr.Address) == 0 {
- stats.OutgoingRequestNetworkUnreachableErrors.Increment()
+ stats.outgoingRequestInterfaceHasNoLocalAddressErrors.Increment()
return tcpip.ErrNetworkUnreachable
}
localAddr = addr.Address
} else if p.stack.CheckLocalAddress(nicID, header.IPv4ProtocolNumber, localAddr) == 0 {
- stats.OutgoingRequestBadLocalAddressErrors.Increment()
+ stats.outgoingRequestBadLocalAddressErrors.Increment()
return tcpip.ErrBadLocalAddress
}
@@ -296,10 +326,10 @@ func (p *protocol) LinkAddressRequest(targetAddr, localAddr tcpip.Address, remot
panic(fmt.Sprintf("copied %d bytes, expected %d bytes", n, header.IPv4AddressSize))
}
if err := nic.WritePacketToRemote(remoteLinkAddr, nil /* gso */, ProtocolNumber, pkt); err != nil {
- stats.OutgoingRequestsDropped.Increment()
+ stats.outgoingRequestsDropped.Increment()
return err
}
- stats.OutgoingRequestsSent.Increment()
+ stats.outgoingRequestsSent.Increment()
return nil
}
@@ -337,5 +367,11 @@ func (*protocol) Parse(pkt *stack.PacketBuffer) (proto tcpip.TransportProtocolNu
// NewProtocol returns an ARP network protocol.
func NewProtocol(s *stack.Stack) stack.NetworkProtocol {
- return &protocol{stack: s}
+ return &protocol{
+ stack: s,
+ mu: struct {
+ sync.RWMutex
+ eps map[tcpip.NICID]*endpoint
+ }{eps: make(map[tcpip.NICID]*endpoint)},
+ }
}