diff options
author | Arthur Sfez <asfez@google.com> | 2021-01-25 16:50:14 -0800 |
---|---|---|
committer | gVisor bot <gvisor-bot@google.com> | 2021-01-25 16:52:05 -0800 |
commit | 39db3b93554ea74611602ad4c20dfa5c08e748f2 (patch) | |
tree | 406dbe1877169627a2449ce95a3372d479a96590 /pkg/tcpip/network/arp/arp.go | |
parent | b4665aef8717d00f2f3320616ae4ef0914f9a1b4 (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.go | 90 |
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)}, + } } |