Automated rollback of changelist 336304024

PiperOrigin-RevId: 336339194
This commit is contained in:
Ghanan Gowripalan
2020-10-09 12:09:12 -07:00
committed by gVisor bot
parent 33d6622172
commit 257703c050
34 changed files with 1635 additions and 429 deletions
+1
View File
@@ -17,6 +17,7 @@ go_library(
"//pkg/sentry/vfs",
"//pkg/syserror",
"//pkg/tcpip/link/tun",
"//pkg/tcpip/network/arp",
"//pkg/usermem",
"//pkg/waiter",
],
+13 -1
View File
@@ -16,6 +16,8 @@
package tundev
import (
"fmt"
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
"gvisor.dev/gvisor/pkg/sentry/arch"
@@ -26,6 +28,7 @@ import (
"gvisor.dev/gvisor/pkg/sentry/vfs"
"gvisor.dev/gvisor/pkg/syserror"
"gvisor.dev/gvisor/pkg/tcpip/link/tun"
"gvisor.dev/gvisor/pkg/tcpip/network/arp"
"gvisor.dev/gvisor/pkg/usermem"
"gvisor.dev/gvisor/pkg/waiter"
)
@@ -84,7 +87,16 @@ func (fd *tunFD) Ioctl(ctx context.Context, uio usermem.IO, args arch.SyscallArg
return 0, err
}
flags := usermem.ByteOrder.Uint16(req.Data[:])
return 0, fd.device.SetIff(stack.Stack, req.Name(), flags)
created, err := fd.device.SetIff(stack.Stack, req.Name(), flags)
if err == nil && created {
// Always start with an ARP address for interfaces so they can handle ARP
// packets.
nicID := fd.device.NICID()
if err := stack.Stack.AddAddress(nicID, arp.ProtocolNumber, arp.ProtocolAddress); err != nil {
panic(fmt.Sprintf("failed to add ARP address after creating new TUN/TAP interface with ID = %d", nicID))
}
}
return 0, err
case linux.TUNGETIFF:
var req linux.IFReq
+1
View File
@@ -34,6 +34,7 @@ go_library(
"//pkg/sentry/socket/netstack",
"//pkg/syserror",
"//pkg/tcpip/link/tun",
"//pkg/tcpip/network/arp",
"//pkg/usermem",
"//pkg/waiter",
],
+32 -20
View File
@@ -15,6 +15,8 @@
package dev
import (
"fmt"
"gvisor.dev/gvisor/pkg/abi/linux"
"gvisor.dev/gvisor/pkg/context"
"gvisor.dev/gvisor/pkg/sentry/arch"
@@ -25,6 +27,7 @@ import (
"gvisor.dev/gvisor/pkg/sentry/socket/netstack"
"gvisor.dev/gvisor/pkg/syserror"
"gvisor.dev/gvisor/pkg/tcpip/link/tun"
"gvisor.dev/gvisor/pkg/tcpip/network/arp"
"gvisor.dev/gvisor/pkg/usermem"
"gvisor.dev/gvisor/pkg/waiter"
)
@@ -60,7 +63,7 @@ func newNetTunDevice(ctx context.Context, owner fs.FileOwner, mode linux.FileMod
}
// GetFile implements fs.InodeOperations.GetFile.
func (iops *netTunInodeOperations) GetFile(ctx context.Context, d *fs.Dirent, flags fs.FileFlags) (*fs.File, error) {
func (*netTunInodeOperations) GetFile(ctx context.Context, d *fs.Dirent, flags fs.FileFlags) (*fs.File, error) {
return fs.NewFile(ctx, d, flags, &netTunFileOperations{}), nil
}
@@ -80,12 +83,12 @@ type netTunFileOperations struct {
var _ fs.FileOperations = (*netTunFileOperations)(nil)
// Release implements fs.FileOperations.Release.
func (fops *netTunFileOperations) Release(ctx context.Context) {
fops.device.Release(ctx)
func (n *netTunFileOperations) Release(ctx context.Context) {
n.device.Release(ctx)
}
// Ioctl implements fs.FileOperations.Ioctl.
func (fops *netTunFileOperations) Ioctl(ctx context.Context, file *fs.File, io usermem.IO, args arch.SyscallArguments) (uintptr, error) {
func (n *netTunFileOperations) Ioctl(ctx context.Context, file *fs.File, io usermem.IO, args arch.SyscallArguments) (uintptr, error) {
request := args[1].Uint()
data := args[2].Pointer()
@@ -109,16 +112,25 @@ func (fops *netTunFileOperations) Ioctl(ctx context.Context, file *fs.File, io u
return 0, err
}
flags := usermem.ByteOrder.Uint16(req.Data[:])
return 0, fops.device.SetIff(stack.Stack, req.Name(), flags)
created, err := n.device.SetIff(stack.Stack, req.Name(), flags)
if err == nil && created {
// Always start with an ARP address for interfaces so they can handle ARP
// packets.
nicID := n.device.NICID()
if err := stack.Stack.AddAddress(nicID, arp.ProtocolNumber, arp.ProtocolAddress); err != nil {
panic(fmt.Sprintf("failed to add ARP address after creating new TUN/TAP interface with ID = %d", nicID))
}
}
return 0, err
case linux.TUNGETIFF:
var req linux.IFReq
copy(req.IFName[:], fops.device.Name())
copy(req.IFName[:], n.device.Name())
// Linux adds IFF_NOFILTER (the same value as IFF_NO_PI unfortunately) when
// there is no sk_filter. See __tun_chr_ioctl() in net/drivers/tun.c.
flags := fops.device.Flags() | linux.IFF_NOFILTER
flags := n.device.Flags() | linux.IFF_NOFILTER
usermem.ByteOrder.PutUint16(req.Data[:], flags)
_, err := req.CopyOut(t, data)
@@ -130,41 +142,41 @@ func (fops *netTunFileOperations) Ioctl(ctx context.Context, file *fs.File, io u
}
// Write implements fs.FileOperations.Write.
func (fops *netTunFileOperations) Write(ctx context.Context, file *fs.File, src usermem.IOSequence, offset int64) (int64, error) {
func (n *netTunFileOperations) Write(ctx context.Context, file *fs.File, src usermem.IOSequence, offset int64) (int64, error) {
data := make([]byte, src.NumBytes())
if _, err := src.CopyIn(ctx, data); err != nil {
return 0, err
}
return fops.device.Write(data)
return n.device.Write(data)
}
// Read implements fs.FileOperations.Read.
func (fops *netTunFileOperations) Read(ctx context.Context, file *fs.File, dst usermem.IOSequence, offset int64) (int64, error) {
data, err := fops.device.Read()
func (n *netTunFileOperations) Read(ctx context.Context, file *fs.File, dst usermem.IOSequence, offset int64) (int64, error) {
data, err := n.device.Read()
if err != nil {
return 0, err
}
n, err := dst.CopyOut(ctx, data)
if n > 0 && n < len(data) {
bytesCopied, err := dst.CopyOut(ctx, data)
if bytesCopied > 0 && bytesCopied < len(data) {
// Not an error for partial copying. Packet truncated.
err = nil
}
return int64(n), err
return int64(bytesCopied), err
}
// Readiness implements watier.Waitable.Readiness.
func (fops *netTunFileOperations) Readiness(mask waiter.EventMask) waiter.EventMask {
return fops.device.Readiness(mask)
func (n *netTunFileOperations) Readiness(mask waiter.EventMask) waiter.EventMask {
return n.device.Readiness(mask)
}
// EventRegister implements watier.Waitable.EventRegister.
func (fops *netTunFileOperations) EventRegister(e *waiter.Entry, mask waiter.EventMask) {
fops.device.EventRegister(e, mask)
func (n *netTunFileOperations) EventRegister(e *waiter.Entry, mask waiter.EventMask) {
n.device.EventRegister(e, mask)
}
// EventUnregister implements watier.Waitable.EventUnregister.
func (fops *netTunFileOperations) EventUnregister(e *waiter.Entry) {
fops.device.EventUnregister(e)
func (n *netTunFileOperations) EventUnregister(e *waiter.Entry) {
n.device.EventUnregister(e)
}
// isNetTunSupported returns whether /dev/net/tun device is supported for s.
+11 -5
View File
@@ -117,25 +117,31 @@ func (b Ethernet) Encode(e *EthernetFields) {
copy(b[dstMAC:][:EthernetAddressSize], e.DstAddr)
}
// IsValidUnicastEthernetAddress returns true if addr is a valid unicast
// IsMulticastEthernetAddress returns true if the address is a multicast
// ethernet address.
func IsMulticastEthernetAddress(addr tcpip.LinkAddress) bool {
if len(addr) != EthernetAddressSize {
return false
}
return addr[unicastMulticastFlagByteIdx]&unicastMulticastFlagMask != 0
}
// IsValidUnicastEthernetAddress returns true if the address is a unicast
// ethernet address.
func IsValidUnicastEthernetAddress(addr tcpip.LinkAddress) bool {
// Must be of the right length.
if len(addr) != EthernetAddressSize {
return false
}
// Must not be unspecified.
if addr == unspecifiedEthernetAddress {
return false
}
// Must not be a multicast.
if addr[unicastMulticastFlagByteIdx]&unicastMulticastFlagMask != 0 {
return false
}
// addr is a valid unicast ethernet address.
return true
}
+47
View File
@@ -67,6 +67,53 @@ func TestIsValidUnicastEthernetAddress(t *testing.T) {
}
}
func TestIsMulticastEthernetAddress(t *testing.T) {
tests := []struct {
name string
addr tcpip.LinkAddress
expected bool
}{
{
"Nil",
tcpip.LinkAddress([]byte(nil)),
false,
},
{
"Empty",
tcpip.LinkAddress(""),
false,
},
{
"InvalidLength",
tcpip.LinkAddress("\x01\x02\x03"),
false,
},
{
"Unspecified",
unspecifiedEthernetAddress,
false,
},
{
"Multicast",
tcpip.LinkAddress("\x01\x02\x03\x04\x05\x06"),
true,
},
{
"Unicast",
tcpip.LinkAddress("\x02\x02\x03\x04\x05\x06"),
false,
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
if got := IsMulticastEthernetAddress(test.addr); got != test.expected {
t.Fatalf("got IsMulticastEthernetAddress = %t, want = %t", got, test.expected)
}
})
}
}
func TestEthernetAddressFromMulticastIPv4Address(t *testing.T) {
tests := []struct {
name string
+15
View File
@@ -0,0 +1,15 @@
load("//tools:defs.bzl", "go_library")
package(licenses = ["notice"])
go_library(
name = "pipe",
srcs = ["pipe.go"],
visibility = ["//visibility:public"],
deps = [
"//pkg/tcpip",
"//pkg/tcpip/buffer",
"//pkg/tcpip/header",
"//pkg/tcpip/stack",
],
)
+124
View File
@@ -0,0 +1,124 @@
// 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 pipe provides the implementation of pipe-like data-link layer
// endpoints. Such endpoints allow packets to be sent between two interfaces.
package pipe
import (
"gvisor.dev/gvisor/pkg/tcpip"
"gvisor.dev/gvisor/pkg/tcpip/buffer"
"gvisor.dev/gvisor/pkg/tcpip/header"
"gvisor.dev/gvisor/pkg/tcpip/stack"
)
var _ stack.LinkEndpoint = (*Endpoint)(nil)
// New returns both ends of a new pipe.
func New(linkAddr1, linkAddr2 tcpip.LinkAddress, capabilities stack.LinkEndpointCapabilities) (*Endpoint, *Endpoint) {
ep1 := &Endpoint{
linkAddr: linkAddr1,
capabilities: capabilities,
}
ep2 := &Endpoint{
linkAddr: linkAddr2,
linked: ep1,
capabilities: capabilities,
}
ep1.linked = ep2
return ep1, ep2
}
// Endpoint is one end of a pipe.
type Endpoint struct {
capabilities stack.LinkEndpointCapabilities
linkAddr tcpip.LinkAddress
dispatcher stack.NetworkDispatcher
linked *Endpoint
onWritePacket func(*stack.PacketBuffer)
}
// WritePacket implements stack.LinkEndpoint.
func (e *Endpoint) WritePacket(r *stack.Route, _ *stack.GSO, proto tcpip.NetworkProtocolNumber, pkt *stack.PacketBuffer) *tcpip.Error {
if !e.linked.IsAttached() {
return nil
}
// The pipe endpoint will accept all multicast/broadcast link traffic and only
// unicast traffic destined to itself.
if len(e.linked.linkAddr) != 0 &&
r.RemoteLinkAddress != e.linked.linkAddr &&
r.RemoteLinkAddress != header.EthernetBroadcastAddress &&
!header.IsMulticastEthernetAddress(r.RemoteLinkAddress) {
return nil
}
e.linked.dispatcher.DeliverNetworkPacket(e.linkAddr, r.RemoteLinkAddress, proto, stack.NewPacketBuffer(stack.PacketBufferOptions{
Data: buffer.NewVectorisedView(pkt.Size(), pkt.Views()),
}))
return nil
}
// WritePackets implements stack.LinkEndpoint.
func (*Endpoint) WritePackets(*stack.Route, *stack.GSO, stack.PacketBufferList, tcpip.NetworkProtocolNumber) (int, *tcpip.Error) {
panic("not implemented")
}
// WriteRawPacket implements stack.LinkEndpoint.
func (*Endpoint) WriteRawPacket(buffer.VectorisedView) *tcpip.Error {
panic("not implemented")
}
// Attach implements stack.LinkEndpoint.
func (e *Endpoint) Attach(dispatcher stack.NetworkDispatcher) {
e.dispatcher = dispatcher
}
// IsAttached implements stack.LinkEndpoint.
func (e *Endpoint) IsAttached() bool {
return e.dispatcher != nil
}
// Wait implements stack.LinkEndpoint.
func (*Endpoint) Wait() {}
// MTU implements stack.LinkEndpoint.
func (*Endpoint) MTU() uint32 {
return header.IPv6MinimumMTU
}
// Capabilities implements stack.LinkEndpoint.
func (e *Endpoint) Capabilities() stack.LinkEndpointCapabilities {
return e.capabilities
}
// MaxHeaderLength implements stack.LinkEndpoint.
func (*Endpoint) MaxHeaderLength() uint16 {
return 0
}
// LinkAddress implements stack.LinkEndpoint.
func (e *Endpoint) LinkAddress() tcpip.LinkAddress {
return e.linkAddr
}
// ARPHardwareType implements stack.LinkEndpoint.
func (*Endpoint) ARPHardwareType() header.ARPHardwareType {
return header.ARPHardwareEther
}
// AddHeader implements stack.LinkEndpoint.
func (*Endpoint) AddHeader(_, _ tcpip.LinkAddress, _ tcpip.NetworkProtocolNumber, _ *stack.PacketBuffer) {
}
+29 -13
View File
@@ -76,13 +76,29 @@ func (d *Device) Release(ctx context.Context) {
}
}
// NICID returns the NIC ID of the device.
//
// Must only be called after the device has been attached to an endpoint.
func (d *Device) NICID() tcpip.NICID {
d.mu.RLock()
defer d.mu.RUnlock()
if d.endpoint == nil {
panic("called NICID on a device that has not been attached")
}
return d.endpoint.nicID
}
// SetIff services TUNSETIFF ioctl(2) request.
func (d *Device) SetIff(s *stack.Stack, name string, flags uint16) error {
//
// Returns true if a new NIC was created; false if an existing one was attached.
func (d *Device) SetIff(s *stack.Stack, name string, flags uint16) (bool, error) {
d.mu.Lock()
defer d.mu.Unlock()
if d.endpoint != nil {
return syserror.EINVAL
return false, syserror.EINVAL
}
// Input validations.
@@ -90,7 +106,7 @@ func (d *Device) SetIff(s *stack.Stack, name string, flags uint16) error {
isTap := flags&linux.IFF_TAP != 0
supportedFlags := uint16(linux.IFF_TUN | linux.IFF_TAP | linux.IFF_NO_PI)
if isTap && isTun || !isTap && !isTun || flags&^supportedFlags != 0 {
return syserror.EINVAL
return false, syserror.EINVAL
}
prefix := "tun"
@@ -103,32 +119,32 @@ func (d *Device) SetIff(s *stack.Stack, name string, flags uint16) error {
linkCaps |= stack.CapabilityResolutionRequired
}
endpoint, err := attachOrCreateNIC(s, name, prefix, linkCaps)
endpoint, created, err := attachOrCreateNIC(s, name, prefix, linkCaps)
if err != nil {
return syserror.EINVAL
return false, syserror.EINVAL
}
d.endpoint = endpoint
d.notifyHandle = d.endpoint.AddNotify(d)
d.flags = flags
return nil
return created, nil
}
func attachOrCreateNIC(s *stack.Stack, name, prefix string, linkCaps stack.LinkEndpointCapabilities) (*tunEndpoint, error) {
func attachOrCreateNIC(s *stack.Stack, name, prefix string, linkCaps stack.LinkEndpointCapabilities) (*tunEndpoint, bool, error) {
for {
// 1. Try to attach to an existing NIC.
if name != "" {
if nic, found := s.GetNICByName(name); found {
endpoint, ok := nic.LinkEndpoint().(*tunEndpoint)
if linkEP := s.GetLinkEndpointByName(name); linkEP != nil {
endpoint, ok := linkEP.(*tunEndpoint)
if !ok {
// Not a NIC created by tun device.
return nil, syserror.EOPNOTSUPP
return nil, false, syserror.EOPNOTSUPP
}
if !endpoint.TryIncRef() {
// Race detected: NIC got deleted in between.
continue
}
return endpoint, nil
return endpoint, false, nil
}
}
@@ -151,12 +167,12 @@ func attachOrCreateNIC(s *stack.Stack, name, prefix string, linkCaps stack.LinkE
})
switch err {
case nil:
return endpoint, nil
return endpoint, true, nil
case tcpip.ErrDuplicateNICID:
// Race detected: A NIC has been created in between.
continue
default:
return nil, syserror.EINVAL
return nil, false, syserror.EINVAL
}
}
}
+16 -9
View File
@@ -49,7 +49,6 @@ type endpoint struct {
enabled uint32
nic stack.NetworkInterface
linkEP stack.LinkEndpoint
linkAddrCache stack.LinkAddressCache
nud stack.NUDHandler
}
@@ -92,12 +91,12 @@ func (e *endpoint) DefaultTTL() uint8 {
}
func (e *endpoint) MTU() uint32 {
lmtu := e.linkEP.MTU()
lmtu := e.nic.MTU()
return lmtu - uint32(e.MaxHeaderLength())
}
func (e *endpoint) MaxHeaderLength() uint16 {
return e.linkEP.MaxHeaderLength() + header.ARPSize
return e.nic.MaxHeaderLength() + header.ARPSize
}
func (e *endpoint) Close() {
@@ -154,17 +153,25 @@ func (e *endpoint) HandlePacket(r *stack.Route, pkt *stack.PacketBuffer) {
e.nud.HandleProbe(remoteAddr, localAddr, ProtocolNumber, remoteLinkAddr, e.protocol)
}
pkt := stack.NewPacketBuffer(stack.PacketBufferOptions{
ReserveHeaderBytes: int(e.linkEP.MaxHeaderLength()) + header.ARPSize,
// As per RFC 826, under Packet Reception:
// Swap hardware and protocol fields, putting the local hardware and
// protocol addresses in the sender fields.
//
// Send the packet to the (new) target hardware address on the same
// hardware on which the request was received.
origSender := h.HardwareAddressSender()
r.RemoteLinkAddress = tcpip.LinkAddress(origSender)
respPkt := stack.NewPacketBuffer(stack.PacketBufferOptions{
ReserveHeaderBytes: int(e.nic.MaxHeaderLength()) + header.ARPSize,
})
packet := header.ARP(pkt.NetworkHeader().Push(header.ARPSize))
packet := header.ARP(respPkt.NetworkHeader().Push(header.ARPSize))
packet.SetIPv4OverEthernet()
packet.SetOp(header.ARPReply)
copy(packet.HardwareAddressSender(), r.LocalLinkAddress[:])
copy(packet.ProtocolAddressSender(), h.ProtocolAddressTarget())
copy(packet.HardwareAddressTarget(), h.HardwareAddressSender())
copy(packet.HardwareAddressTarget(), origSender)
copy(packet.ProtocolAddressTarget(), h.ProtocolAddressSender())
_ = e.linkEP.WritePacket(r, nil /* gso */, ProtocolNumber, pkt)
_ = e.nic.WritePacket(r, nil /* gso */, ProtocolNumber, respPkt)
case header.ARPReply:
addr := tcpip.Address(h.ProtocolAddressSender())
@@ -207,7 +214,6 @@ func (p *protocol) NewEndpoint(nic stack.NetworkInterface, linkAddrCache stack.L
e := &endpoint{
protocol: p,
nic: nic,
linkEP: nic.LinkEndpoint(),
linkAddrCache: linkAddrCache,
nud: nud,
}
@@ -223,6 +229,7 @@ func (*protocol) LinkAddressProtocol() tcpip.NetworkProtocolNumber {
// LinkAddressRequest implements stack.LinkAddressResolver.LinkAddressRequest.
func (*protocol) LinkAddressRequest(addr, localAddr tcpip.Address, remoteLinkAddr tcpip.LinkAddress, linkEP stack.LinkEndpoint) *tcpip.Error {
r := &stack.Route{
NetProto: ProtocolNumber,
RemoteLinkAddress: remoteLinkAddr,
}
if len(r.RemoteLinkAddress) == 0 {
+57 -61
View File
@@ -270,7 +270,7 @@ func buildDummyStack(t *testing.T) *stack.Stack {
var _ stack.NetworkInterface = (*testInterface)(nil)
type testInterface struct {
tester testObject
testObject
mu struct {
sync.RWMutex
@@ -302,10 +302,6 @@ func (t *testInterface) setEnabled(v bool) {
t.mu.disabled = !v
}
func (t *testInterface) LinkEndpoint() stack.LinkEndpoint {
return &t.tester
}
func TestSourceAddressValidation(t *testing.T) {
rxIPv4ICMP := func(e *channel.Endpoint, src tcpip.Address) {
totalLen := header.IPv4MinimumSize + header.ICMPv4MinimumSize
@@ -517,7 +513,7 @@ func TestIPv4Send(t *testing.T) {
s := buildDummyStack(t)
proto := s.NetworkProtocolInstance(ipv4.ProtocolNumber)
nic := testInterface{
tester: testObject{
testObject: testObject{
t: t,
v4: true,
},
@@ -538,10 +534,10 @@ func TestIPv4Send(t *testing.T) {
})
// Issue the write.
nic.tester.protocol = 123
nic.tester.srcAddr = localIPv4Addr
nic.tester.dstAddr = remoteIPv4Addr
nic.tester.contents = payload
nic.testObject.protocol = 123
nic.testObject.srcAddr = localIPv4Addr
nic.testObject.dstAddr = remoteIPv4Addr
nic.testObject.contents = payload
r, err := buildIPv4Route(localIPv4Addr, remoteIPv4Addr)
if err != nil {
@@ -560,12 +556,12 @@ func TestIPv4Receive(t *testing.T) {
s := buildDummyStack(t)
proto := s.NetworkProtocolInstance(ipv4.ProtocolNumber)
nic := testInterface{
tester: testObject{
testObject: testObject{
t: t,
v4: true,
},
}
ep := proto.NewEndpoint(&nic, nil, nil, &nic.tester)
ep := proto.NewEndpoint(&nic, nil, nil, &nic.testObject)
defer ep.Close()
if err := ep.Enable(); err != nil {
@@ -590,10 +586,10 @@ func TestIPv4Receive(t *testing.T) {
}
// Give packet to ipv4 endpoint, dispatcher will validate that it's ok.
nic.tester.protocol = 10
nic.tester.srcAddr = remoteIPv4Addr
nic.tester.dstAddr = localIPv4Addr
nic.tester.contents = view[header.IPv4MinimumSize:totalLen]
nic.testObject.protocol = 10
nic.testObject.srcAddr = remoteIPv4Addr
nic.testObject.dstAddr = localIPv4Addr
nic.testObject.contents = view[header.IPv4MinimumSize:totalLen]
r, err := buildIPv4Route(localIPv4Addr, remoteIPv4Addr)
if err != nil {
@@ -606,8 +602,8 @@ func TestIPv4Receive(t *testing.T) {
t.Fatalf("failed to parse packet: %x", pkt.Data.ToView())
}
ep.HandlePacket(&r, pkt)
if nic.tester.dataCalls != 1 {
t.Fatalf("Bad number of data calls: got %x, want 1", nic.tester.dataCalls)
if nic.testObject.dataCalls != 1 {
t.Fatalf("Bad number of data calls: got %x, want 1", nic.testObject.dataCalls)
}
}
@@ -640,11 +636,11 @@ func TestIPv4ReceiveControl(t *testing.T) {
s := buildDummyStack(t)
proto := s.NetworkProtocolInstance(ipv4.ProtocolNumber)
nic := testInterface{
tester: testObject{
testObject: testObject{
t: t,
},
}
ep := proto.NewEndpoint(&nic, nil, nil, &nic.tester)
ep := proto.NewEndpoint(&nic, nil, nil, &nic.testObject)
defer ep.Close()
if err := ep.Enable(); err != nil {
@@ -691,16 +687,16 @@ func TestIPv4ReceiveControl(t *testing.T) {
// Give packet to IPv4 endpoint, dispatcher will validate that
// it's ok.
nic.tester.protocol = 10
nic.tester.srcAddr = remoteIPv4Addr
nic.tester.dstAddr = localIPv4Addr
nic.tester.contents = view[dataOffset:]
nic.tester.typ = c.expectedTyp
nic.tester.extra = c.expectedExtra
nic.testObject.protocol = 10
nic.testObject.srcAddr = remoteIPv4Addr
nic.testObject.dstAddr = localIPv4Addr
nic.testObject.contents = view[dataOffset:]
nic.testObject.typ = c.expectedTyp
nic.testObject.extra = c.expectedExtra
ep.HandlePacket(&r, truncatedPacket(view, c.trunc, header.IPv4MinimumSize))
if want := c.expectedCount; nic.tester.controlCalls != want {
t.Fatalf("Bad number of control calls for %q case: got %v, want %v", c.name, nic.tester.controlCalls, want)
if want := c.expectedCount; nic.testObject.controlCalls != want {
t.Fatalf("Bad number of control calls for %q case: got %v, want %v", c.name, nic.testObject.controlCalls, want)
}
})
}
@@ -710,12 +706,12 @@ func TestIPv4FragmentationReceive(t *testing.T) {
s := buildDummyStack(t)
proto := s.NetworkProtocolInstance(ipv4.ProtocolNumber)
nic := testInterface{
tester: testObject{
testObject: testObject{
t: t,
v4: true,
},
}
ep := proto.NewEndpoint(&nic, nil, nil, &nic.tester)
ep := proto.NewEndpoint(&nic, nil, nil, &nic.testObject)
defer ep.Close()
if err := ep.Enable(); err != nil {
@@ -758,10 +754,10 @@ func TestIPv4FragmentationReceive(t *testing.T) {
}
// Give packet to ipv4 endpoint, dispatcher will validate that it's ok.
nic.tester.protocol = 10
nic.tester.srcAddr = remoteIPv4Addr
nic.tester.dstAddr = localIPv4Addr
nic.tester.contents = append(frag1[header.IPv4MinimumSize:totalLen], frag2[header.IPv4MinimumSize:totalLen]...)
nic.testObject.protocol = 10
nic.testObject.srcAddr = remoteIPv4Addr
nic.testObject.dstAddr = localIPv4Addr
nic.testObject.contents = append(frag1[header.IPv4MinimumSize:totalLen], frag2[header.IPv4MinimumSize:totalLen]...)
r, err := buildIPv4Route(localIPv4Addr, remoteIPv4Addr)
if err != nil {
@@ -776,8 +772,8 @@ func TestIPv4FragmentationReceive(t *testing.T) {
t.Fatalf("failed to parse packet: %x", pkt.Data.ToView())
}
ep.HandlePacket(&r, pkt)
if nic.tester.dataCalls != 0 {
t.Fatalf("Bad number of data calls: got %x, want 0", nic.tester.dataCalls)
if nic.testObject.dataCalls != 0 {
t.Fatalf("Bad number of data calls: got %x, want 0", nic.testObject.dataCalls)
}
// Send second segment.
@@ -788,8 +784,8 @@ func TestIPv4FragmentationReceive(t *testing.T) {
t.Fatalf("failed to parse packet: %x", pkt.Data.ToView())
}
ep.HandlePacket(&r, pkt)
if nic.tester.dataCalls != 1 {
t.Fatalf("Bad number of data calls: got %x, want 1", nic.tester.dataCalls)
if nic.testObject.dataCalls != 1 {
t.Fatalf("Bad number of data calls: got %x, want 1", nic.testObject.dataCalls)
}
}
@@ -797,7 +793,7 @@ func TestIPv6Send(t *testing.T) {
s := buildDummyStack(t)
proto := s.NetworkProtocolInstance(ipv6.ProtocolNumber)
nic := testInterface{
tester: testObject{
testObject: testObject{
t: t,
},
}
@@ -821,10 +817,10 @@ func TestIPv6Send(t *testing.T) {
})
// Issue the write.
nic.tester.protocol = 123
nic.tester.srcAddr = localIPv6Addr
nic.tester.dstAddr = remoteIPv6Addr
nic.tester.contents = payload
nic.testObject.protocol = 123
nic.testObject.srcAddr = localIPv6Addr
nic.testObject.dstAddr = remoteIPv6Addr
nic.testObject.contents = payload
r, err := buildIPv6Route(localIPv6Addr, remoteIPv6Addr)
if err != nil {
@@ -843,11 +839,11 @@ func TestIPv6Receive(t *testing.T) {
s := buildDummyStack(t)
proto := s.NetworkProtocolInstance(ipv6.ProtocolNumber)
nic := testInterface{
tester: testObject{
testObject: testObject{
t: t,
},
}
ep := proto.NewEndpoint(&nic, nil, nil, &nic.tester)
ep := proto.NewEndpoint(&nic, nil, nil, &nic.testObject)
defer ep.Close()
if err := ep.Enable(); err != nil {
@@ -871,10 +867,10 @@ func TestIPv6Receive(t *testing.T) {
}
// Give packet to ipv6 endpoint, dispatcher will validate that it's ok.
nic.tester.protocol = 10
nic.tester.srcAddr = remoteIPv6Addr
nic.tester.dstAddr = localIPv6Addr
nic.tester.contents = view[header.IPv6MinimumSize:totalLen]
nic.testObject.protocol = 10
nic.testObject.srcAddr = remoteIPv6Addr
nic.testObject.dstAddr = localIPv6Addr
nic.testObject.contents = view[header.IPv6MinimumSize:totalLen]
r, err := buildIPv6Route(localIPv6Addr, remoteIPv6Addr)
if err != nil {
@@ -888,8 +884,8 @@ func TestIPv6Receive(t *testing.T) {
t.Fatalf("failed to parse packet: %x", pkt.Data.ToView())
}
ep.HandlePacket(&r, pkt)
if nic.tester.dataCalls != 1 {
t.Fatalf("Bad number of data calls: got %x, want 1", nic.tester.dataCalls)
if nic.testObject.dataCalls != 1 {
t.Fatalf("Bad number of data calls: got %x, want 1", nic.testObject.dataCalls)
}
}
@@ -931,11 +927,11 @@ func TestIPv6ReceiveControl(t *testing.T) {
s := buildDummyStack(t)
proto := s.NetworkProtocolInstance(ipv6.ProtocolNumber)
nic := testInterface{
tester: testObject{
testObject: testObject{
t: t,
},
}
ep := proto.NewEndpoint(&nic, nil, nil, &nic.tester)
ep := proto.NewEndpoint(&nic, nil, nil, &nic.testObject)
defer ep.Close()
if err := ep.Enable(); err != nil {
@@ -994,19 +990,19 @@ func TestIPv6ReceiveControl(t *testing.T) {
// Give packet to IPv6 endpoint, dispatcher will validate that
// it's ok.
nic.tester.protocol = 10
nic.tester.srcAddr = remoteIPv6Addr
nic.tester.dstAddr = localIPv6Addr
nic.tester.contents = view[dataOffset:]
nic.tester.typ = c.expectedTyp
nic.tester.extra = c.expectedExtra
nic.testObject.protocol = 10
nic.testObject.srcAddr = remoteIPv6Addr
nic.testObject.dstAddr = localIPv6Addr
nic.testObject.contents = view[dataOffset:]
nic.testObject.typ = c.expectedTyp
nic.testObject.extra = c.expectedExtra
// Set ICMPv6 checksum.
icmp.SetChecksum(header.ICMPv6Checksum(icmp, outerSrcAddr, localIPv6Addr, buffer.VectorisedView{}))
ep.HandlePacket(&r, truncatedPacket(view, c.trunc, header.IPv6MinimumSize))
if want := c.expectedCount; nic.tester.controlCalls != want {
t.Fatalf("Bad number of control calls for %q case: got %v, want %v", c.name, nic.tester.controlCalls, want)
if want := c.expectedCount; nic.testObject.controlCalls != want {
t.Fatalf("Bad number of control calls for %q case: got %v, want %v", c.name, nic.testObject.controlCalls, want)
}
})
}
+1
View File
@@ -32,6 +32,7 @@ go_test(
"//pkg/tcpip/header",
"//pkg/tcpip/link/channel",
"//pkg/tcpip/link/sniffer",
"//pkg/tcpip/network/arp",
"//pkg/tcpip/network/ipv4",
"//pkg/tcpip/network/testutil",
"//pkg/tcpip/stack",
+24 -16
View File
@@ -102,8 +102,6 @@ func (e *endpoint) handleICMP(r *stack.Route, pkt *stack.PacketBuffer) {
e.dispatcher.DeliverTransportPacket(r, header.ICMPv4ProtocolNumber, pkt)
remoteLinkAddr := r.RemoteLinkAddress
// As per RFC 1122 section 3.2.1.3, when a host sends any datagram, the IP
// source address MUST be one of its own IP addresses (but not a broadcast
// or multicast address).
@@ -119,9 +117,6 @@ func (e *endpoint) handleICMP(r *stack.Route, pkt *stack.PacketBuffer) {
}
defer r.Release()
// Use the remote link address from the incoming packet.
r.ResolveWith(remoteLinkAddr)
// TODO(gvisor.dev/issue/3810:) When adding protocol numbers into the
// header information, we may have to change this code to handle the
// ICMP header no longer being in the data buffer.
@@ -244,13 +239,7 @@ func (*icmpReasonProtoUnreachable) isICMPReason() {}
// the problematic packet. It incorporates as much of that packet as
// possible as well as any error metadata as is available. returnError
// expects pkt to hold a valid IPv4 packet as per the wire format.
func returnError(r *stack.Route, reason icmpReason, pkt *stack.PacketBuffer) *tcpip.Error {
sent := r.Stats().ICMP.V4PacketsSent
if !r.Stack().AllowICMPMessage() {
sent.RateLimited.Increment()
return nil
}
func (p *protocol) returnError(r *stack.Route, reason icmpReason, pkt *stack.PacketBuffer) *tcpip.Error {
// We check we are responding only when we are allowed to.
// See RFC 1812 section 4.3.2.7 (shown below).
//
@@ -279,6 +268,25 @@ func returnError(r *stack.Route, reason icmpReason, pkt *stack.PacketBuffer) *tc
return nil
}
// Even if we were able to receive a packet from some remote, we may not have
// a route to it - the remote may be blocked via routing rules. We must always
// consult our routing table and find a route to the remote before sending any
// packet.
route, err := p.stack.FindRoute(r.NICID(), r.LocalAddress, r.RemoteAddress, ProtocolNumber, false /* multicastLoop */)
if err != nil {
return err
}
defer route.Release()
// From this point on, the incoming route should no longer be used; route
// must be used to send the ICMP error.
r = nil
sent := p.stack.Stats().ICMP.V4PacketsSent
if !p.stack.AllowICMPMessage() {
sent.RateLimited.Increment()
return nil
}
networkHeader := pkt.NetworkHeader().View()
transportHeader := pkt.TransportHeader().View()
@@ -329,11 +337,11 @@ func returnError(r *stack.Route, reason icmpReason, pkt *stack.PacketBuffer) *tc
// least 8 bytes of the payload must be included. Today linux and other
// systems implement the RFC 1812 definition and not the original
// requirement. We treat 8 bytes as the minimum but will try send more.
mtu := int(r.MTU())
mtu := int(route.MTU())
if mtu > header.IPv4MinimumProcessableDatagramSize {
mtu = header.IPv4MinimumProcessableDatagramSize
}
headerLen := int(r.MaxHeaderLength()) + header.ICMPv4MinimumSize
headerLen := int(route.MaxHeaderLength()) + header.ICMPv4MinimumSize
available := int(mtu) - headerLen
if available < header.IPv4MinimumSize+header.ICMPv4MinimumErrorPayloadSize {
@@ -378,11 +386,11 @@ func returnError(r *stack.Route, reason icmpReason, pkt *stack.PacketBuffer) *tc
icmpHdr.SetChecksum(header.ICMPv4Checksum(icmpHdr, icmpPkt.Data))
counter := sent.DstUnreachable
if err := r.WritePacket(
if err := route.WritePacket(
nil, /* gso */
stack.NetworkHeaderParams{
Protocol: header.ICMPv4ProtocolNumber,
TTL: r.DefaultTTL(),
TTL: route.DefaultTTL(),
TOS: stack.DefaultTOS,
},
icmpPkt,
+11 -21
View File
@@ -66,7 +66,6 @@ var _ stack.NetworkEndpoint = (*endpoint)(nil)
type endpoint struct {
nic stack.NetworkInterface
linkEP stack.LinkEndpoint
dispatcher stack.TransportDispatcher
protocol *protocol
@@ -87,7 +86,6 @@ type endpoint struct {
func (p *protocol) NewEndpoint(nic stack.NetworkInterface, _ stack.LinkAddressCache, _ stack.NUDHandler, dispatcher stack.TransportDispatcher) stack.NetworkEndpoint {
e := &endpoint{
nic: nic,
linkEP: nic.LinkEndpoint(),
dispatcher: dispatcher,
protocol: p,
}
@@ -178,21 +176,13 @@ func (e *endpoint) DefaultTTL() uint8 {
// MTU implements stack.NetworkEndpoint.MTU. It returns the link-layer MTU minus
// the network layer max header length.
func (e *endpoint) MTU() uint32 {
return calculateMTU(e.linkEP.MTU())
return calculateMTU(e.nic.MTU())
}
// MaxHeaderLength returns the maximum length needed by ipv4 headers (and
// underlying protocols).
func (e *endpoint) MaxHeaderLength() uint16 {
return e.linkEP.MaxHeaderLength() + header.IPv4MaximumHeaderSize
}
// GSOMaxSize returns the maximum GSO packet size.
func (e *endpoint) GSOMaxSize() uint32 {
if gso, ok := e.linkEP.(stack.GSOEndpoint); ok {
return gso.GSOMaxSize()
}
return 0
return e.nic.MaxHeaderLength() + header.IPv4MaximumHeaderSize
}
// NetworkProtocolNumber implements stack.NetworkEndpoint.NetworkProtocolNumber.
@@ -210,7 +200,7 @@ func (e *endpoint) writePacketFragments(r *stack.Route, gso *stack.GSO, mtu uint
for {
fragPkt, more := buildNextFragment(&pf, networkHeader)
if err := e.linkEP.WritePacket(r, gso, ProtocolNumber, fragPkt); err != nil {
if err := e.nic.WritePacket(r, gso, ProtocolNumber, fragPkt); err != nil {
r.Stats().IP.OutgoingPacketErrors.IncrementBy(uint64(pf.RemainingFragmentCount() + 1))
return err
}
@@ -283,10 +273,10 @@ func (e *endpoint) WritePacket(r *stack.Route, gso *stack.GSO, params stack.Netw
if r.Loop&stack.PacketOut == 0 {
return nil
}
if pkt.Size() > int(e.linkEP.MTU()) && (gso == nil || gso.Type == stack.GSONone) {
return e.writePacketFragments(r, gso, e.linkEP.MTU(), pkt)
if pkt.Size() > int(e.nic.MTU()) && (gso == nil || gso.Type == stack.GSONone) {
return e.writePacketFragments(r, gso, e.nic.MTU(), pkt)
}
if err := e.linkEP.WritePacket(r, gso, ProtocolNumber, pkt); err != nil {
if err := e.nic.WritePacket(r, gso, ProtocolNumber, pkt); err != nil {
r.Stats().IP.OutgoingPacketErrors.Increment()
return err
}
@@ -316,7 +306,7 @@ func (e *endpoint) WritePackets(r *stack.Route, gso *stack.GSO, pkts stack.Packe
if len(dropped) == 0 && len(natPkts) == 0 {
// Fast path: If no packets are to be dropped then we can just invoke the
// faster WritePackets API directly.
n, err := e.linkEP.WritePackets(r, gso, pkts, ProtocolNumber)
n, err := e.nic.WritePackets(r, gso, pkts, ProtocolNumber)
r.Stats().IP.PacketsSent.IncrementBy(uint64(n))
if err != nil {
r.Stats().IP.OutgoingPacketErrors.IncrementBy(uint64(pkts.Len() - n))
@@ -343,7 +333,7 @@ func (e *endpoint) WritePackets(r *stack.Route, gso *stack.GSO, pkts stack.Packe
continue
}
}
if err := e.linkEP.WritePacket(r, gso, ProtocolNumber, pkt); err != nil {
if err := e.nic.WritePacket(r, gso, ProtocolNumber, pkt); err != nil {
r.Stats().IP.PacketsSent.IncrementBy(uint64(n))
r.Stats().IP.OutgoingPacketErrors.IncrementBy(uint64(pkts.Len() - n - len(dropped)))
// Dropped packets aren't errors, so include them in
@@ -404,7 +394,7 @@ func (e *endpoint) WriteHeaderIncludedPacket(r *stack.Route, pkt *stack.PacketBu
return nil
}
if err := e.linkEP.WritePacket(r, nil /* gso */, ProtocolNumber, pkt); err != nil {
if err := e.nic.WritePacket(r, nil /* gso */, ProtocolNumber, pkt); err != nil {
r.Stats().IP.OutgoingPacketErrors.Increment()
return err
}
@@ -512,13 +502,13 @@ func (e *endpoint) HandlePacket(r *stack.Route, pkt *stack.PacketBuffer) {
// 3 (Port Unreachable), when the designated transport protocol
// (e.g., UDP) is unable to demultiplex the datagram but has no
// protocol mechanism to inform the sender.
_ = returnError(r, &icmpReasonPortUnreachable{}, pkt)
_ = e.protocol.returnError(r, &icmpReasonPortUnreachable{}, pkt)
case stack.TransportPacketProtocolUnreachable:
// As per RFC: 1122 Section 3.2.2.1
// A host SHOULD generate Destination Unreachable messages with code:
// 2 (Protocol Unreachable), when the designated transport protocol
// is not supported
_ = returnError(r, &icmpReasonProtoUnreachable{}, pkt)
_ = e.protocol.returnError(r, &icmpReasonProtoUnreachable{}, pkt)
default:
panic(fmt.Sprintf("unrecognized result from DeliverTransportPacket = %d", res))
}
+203
View File
@@ -16,6 +16,7 @@ package ipv4_test
import (
"bytes"
"context"
"encoding/hex"
"math"
"net"
@@ -28,6 +29,7 @@ import (
"gvisor.dev/gvisor/pkg/tcpip/header"
"gvisor.dev/gvisor/pkg/tcpip/link/channel"
"gvisor.dev/gvisor/pkg/tcpip/link/sniffer"
"gvisor.dev/gvisor/pkg/tcpip/network/arp"
"gvisor.dev/gvisor/pkg/tcpip/network/ipv4"
"gvisor.dev/gvisor/pkg/tcpip/network/testutil"
"gvisor.dev/gvisor/pkg/tcpip/stack"
@@ -1492,3 +1494,204 @@ func (lm *limitedMatcher) Match(stack.Hook, *stack.PacketBuffer, string) (bool,
lm.limit--
return false, false
}
func TestPacketQueing(t *testing.T) {
const nicID = 1
var (
host1NICLinkAddr = tcpip.LinkAddress("\x02\x03\x03\x04\x05\x06")
host2NICLinkAddr = tcpip.LinkAddress("\x02\x03\x03\x04\x05\x09")
host1IPv4Addr = tcpip.ProtocolAddress{
Protocol: ipv4.ProtocolNumber,
AddressWithPrefix: tcpip.AddressWithPrefix{
Address: tcpip.Address(net.ParseIP("192.168.0.1").To4()),
PrefixLen: 24,
},
}
host2IPv4Addr = tcpip.ProtocolAddress{
Protocol: ipv4.ProtocolNumber,
AddressWithPrefix: tcpip.AddressWithPrefix{
Address: tcpip.Address(net.ParseIP("192.168.0.2").To4()),
PrefixLen: 8,
},
}
)
tests := []struct {
name string
rxPkt func(*channel.Endpoint)
checkResp func(*testing.T, *channel.Endpoint)
}{
{
name: "ICMP Error",
rxPkt: func(e *channel.Endpoint) {
hdr := buffer.NewPrependable(header.IPv4MinimumSize + header.UDPMinimumSize)
u := header.UDP(hdr.Prepend(header.UDPMinimumSize))
u.Encode(&header.UDPFields{
SrcPort: 5555,
DstPort: 80,
Length: header.UDPMinimumSize,
})
sum := header.PseudoHeaderChecksum(udp.ProtocolNumber, host2IPv4Addr.AddressWithPrefix.Address, host1IPv4Addr.AddressWithPrefix.Address, header.UDPMinimumSize)
sum = header.Checksum(header.UDP([]byte{}), sum)
u.SetChecksum(^u.CalculateChecksum(sum))
ip := header.IPv4(hdr.Prepend(header.IPv4MinimumSize))
ip.Encode(&header.IPv4Fields{
IHL: header.IPv4MinimumSize,
TotalLength: header.IPv4MinimumSize + header.UDPMinimumSize,
TTL: ipv4.DefaultTTL,
Protocol: uint8(udp.ProtocolNumber),
SrcAddr: host2IPv4Addr.AddressWithPrefix.Address,
DstAddr: host1IPv4Addr.AddressWithPrefix.Address,
})
e.InjectInbound(ipv4.ProtocolNumber, stack.NewPacketBuffer(stack.PacketBufferOptions{
Data: hdr.View().ToVectorisedView(),
}))
},
checkResp: func(t *testing.T, e *channel.Endpoint) {
p, ok := e.ReadContext(context.Background())
if !ok {
t.Fatalf("timed out waiting for packet")
}
if p.Proto != header.IPv4ProtocolNumber {
t.Errorf("got p.Proto = %d, want = %d", p.Proto, header.IPv4ProtocolNumber)
}
if p.Route.RemoteLinkAddress != host2NICLinkAddr {
t.Errorf("got p.Route.RemoteLinkAddress = %s, want = %s", p.Route.RemoteLinkAddress, host2NICLinkAddr)
}
checker.IPv4(t, stack.PayloadSince(p.Pkt.NetworkHeader()),
checker.SrcAddr(host1IPv4Addr.AddressWithPrefix.Address),
checker.DstAddr(host2IPv4Addr.AddressWithPrefix.Address),
checker.ICMPv4(
checker.ICMPv4Type(header.ICMPv4DstUnreachable),
checker.ICMPv4Code(header.ICMPv4PortUnreachable)))
},
},
{
name: "Ping",
rxPkt: func(e *channel.Endpoint) {
totalLen := header.IPv4MinimumSize + header.ICMPv4MinimumSize
hdr := buffer.NewPrependable(totalLen)
pkt := header.ICMPv4(hdr.Prepend(header.ICMPv4MinimumSize))
pkt.SetType(header.ICMPv4Echo)
pkt.SetCode(0)
pkt.SetChecksum(0)
pkt.SetChecksum(^header.Checksum(pkt, 0))
ip := header.IPv4(hdr.Prepend(header.IPv4MinimumSize))
ip.Encode(&header.IPv4Fields{
IHL: header.IPv4MinimumSize,
TotalLength: uint16(totalLen),
Protocol: uint8(icmp.ProtocolNumber4),
TTL: ipv4.DefaultTTL,
SrcAddr: host2IPv4Addr.AddressWithPrefix.Address,
DstAddr: host1IPv4Addr.AddressWithPrefix.Address,
})
e.InjectInbound(header.IPv4ProtocolNumber, stack.NewPacketBuffer(stack.PacketBufferOptions{
Data: hdr.View().ToVectorisedView(),
}))
},
checkResp: func(t *testing.T, e *channel.Endpoint) {
p, ok := e.ReadContext(context.Background())
if !ok {
t.Fatalf("timed out waiting for packet")
}
if p.Proto != header.IPv4ProtocolNumber {
t.Errorf("got p.Proto = %d, want = %d", p.Proto, header.IPv4ProtocolNumber)
}
if p.Route.RemoteLinkAddress != host2NICLinkAddr {
t.Errorf("got p.Route.RemoteLinkAddress = %s, want = %s", p.Route.RemoteLinkAddress, host2NICLinkAddr)
}
checker.IPv4(t, stack.PayloadSince(p.Pkt.NetworkHeader()),
checker.SrcAddr(host1IPv4Addr.AddressWithPrefix.Address),
checker.DstAddr(host2IPv4Addr.AddressWithPrefix.Address),
checker.ICMPv4(
checker.ICMPv4Type(header.ICMPv4EchoReply),
checker.ICMPv4Code(header.ICMPv4UnusedCode)))
},
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
e := channel.New(1, header.IPv6MinimumMTU, host1NICLinkAddr)
e.LinkEPCapabilities |= stack.CapabilityResolutionRequired
s := stack.New(stack.Options{
NetworkProtocols: []stack.NetworkProtocolFactory{arp.NewProtocol, ipv4.NewProtocol},
TransportProtocols: []stack.TransportProtocolFactory{udp.NewProtocol},
})
if err := s.CreateNIC(nicID, e); err != nil {
t.Fatalf("s.CreateNIC(%d, _): %s", nicID, err)
}
if err := s.AddAddress(nicID, arp.ProtocolNumber, arp.ProtocolAddress); err != nil {
t.Fatalf("s.AddAddress(%d, %d, %s): %s", nicID, arp.ProtocolNumber, arp.ProtocolAddress, err)
}
if err := s.AddProtocolAddress(nicID, host1IPv4Addr); err != nil {
t.Fatalf("s.AddProtocolAddress(%d, %#v): %s", nicID, host1IPv4Addr, err)
}
s.SetRouteTable([]tcpip.Route{
tcpip.Route{
Destination: host1IPv4Addr.AddressWithPrefix.Subnet(),
NIC: nicID,
},
})
// Receive a packet to trigger link resolution before a response is sent.
test.rxPkt(e)
// Wait for a ARP request since link address resolution should be
// performed.
{
p, ok := e.ReadContext(context.Background())
if !ok {
t.Fatalf("timed out waiting for packet")
}
if p.Proto != arp.ProtocolNumber {
t.Errorf("got p.Proto = %d, want = %d", p.Proto, arp.ProtocolNumber)
}
if p.Route.RemoteLinkAddress != header.EthernetBroadcastAddress {
t.Errorf("got p.Route.RemoteLinkAddress = %s, want = %s", p.Route.RemoteLinkAddress, header.EthernetBroadcastAddress)
}
rep := header.ARP(p.Pkt.NetworkHeader().View())
if got := rep.Op(); got != header.ARPRequest {
t.Errorf("got Op() = %d, want = %d", got, header.ARPRequest)
}
if got := tcpip.LinkAddress(rep.HardwareAddressSender()); got != host1NICLinkAddr {
t.Errorf("got HardwareAddressSender = %s, want = %s", got, host1NICLinkAddr)
}
if got := tcpip.Address(rep.ProtocolAddressSender()); got != host1IPv4Addr.AddressWithPrefix.Address {
t.Errorf("got ProtocolAddressSender = %s, want = %s", got, host1IPv4Addr.AddressWithPrefix.Address)
}
if got := tcpip.Address(rep.ProtocolAddressTarget()); got != host2IPv4Addr.AddressWithPrefix.Address {
t.Errorf("got ProtocolAddressTarget = %s, want = %s", got, host2IPv4Addr.AddressWithPrefix.Address)
}
}
// Send an ARP reply to complete link address resolution.
{
hdr := buffer.View(make([]byte, header.ARPSize))
packet := header.ARP(hdr)
packet.SetIPv4OverEthernet()
packet.SetOp(header.ARPReply)
copy(packet.HardwareAddressSender(), host2NICLinkAddr)
copy(packet.ProtocolAddressSender(), host2IPv4Addr.AddressWithPrefix.Address)
copy(packet.HardwareAddressTarget(), host1NICLinkAddr)
copy(packet.ProtocolAddressTarget(), host1IPv4Addr.AddressWithPrefix.Address)
e.InjectInbound(arp.ProtocolNumber, stack.NewPacketBuffer(stack.PacketBufferOptions{
Data: hdr.ToVectorisedView(),
}))
}
// Expect the response now that the link address has resolved.
test.checkResp(t, e)
// Since link resolution was already performed, it shouldn't be performed
// again.
test.rxPkt(e)
test.checkResp(t, e)
})
}
}
+33 -18
View File
@@ -440,8 +440,6 @@ func (e *endpoint) handleICMP(r *stack.Route, pkt *stack.PacketBuffer, hasFragme
return
}
remoteLinkAddr := r.RemoteLinkAddress
// As per RFC 4291 section 2.7, multicast addresses must not be used as
// source addresses in IPv6 packets.
localAddr := r.LocalAddress
@@ -456,9 +454,6 @@ func (e *endpoint) handleICMP(r *stack.Route, pkt *stack.PacketBuffer, hasFragme
}
defer r.Release()
// Use the link address from the source of the original packet.
r.ResolveWith(remoteLinkAddr)
replyPkt := stack.NewPacketBuffer(stack.PacketBufferOptions{
ReserveHeaderBytes: int(r.MaxHeaderLength()) + header.ICMPv6EchoMinimumSize,
Data: pkt.Data,
@@ -742,14 +737,7 @@ func (*icmpReasonPortUnreachable) isICMPReason() {}
// returnError takes an error descriptor and generates the appropriate ICMP
// error packet for IPv6 and sends it.
func returnError(r *stack.Route, reason icmpReason, pkt *stack.PacketBuffer) *tcpip.Error {
stats := r.Stats().ICMP
sent := stats.V6PacketsSent
if !r.Stack().AllowICMPMessage() {
sent.RateLimited.Increment()
return nil
}
func (p *protocol) returnError(r *stack.Route, reason icmpReason, pkt *stack.PacketBuffer) *tcpip.Error {
// Only send ICMP error if the address is not a multicast v6
// address and the source is not the unspecified address.
//
@@ -780,6 +768,26 @@ func returnError(r *stack.Route, reason icmpReason, pkt *stack.PacketBuffer) *tc
return nil
}
// Even if we were able to receive a packet from some remote, we may not have
// a route to it - the remote may be blocked via routing rules. We must always
// consult our routing table and find a route to the remote before sending any
// packet.
route, err := p.stack.FindRoute(r.NICID(), r.LocalAddress, r.RemoteAddress, ProtocolNumber, false /* multicastLoop */)
if err != nil {
return err
}
defer route.Release()
// From this point on, the incoming route should no longer be used; route
// must be used to send the ICMP error.
r = nil
stats := p.stack.Stats().ICMP
sent := stats.V6PacketsSent
if !p.stack.AllowICMPMessage() {
sent.RateLimited.Increment()
return nil
}
network, transport := pkt.NetworkHeader().View(), pkt.TransportHeader().View()
if pkt.TransportProtocolNumber == header.ICMPv6ProtocolNumber {
@@ -806,11 +814,11 @@ func returnError(r *stack.Route, reason icmpReason, pkt *stack.PacketBuffer) *tc
// packet that caused the error) as possible without making
// the error message packet exceed the minimum IPv6 MTU
// [IPv6].
mtu := int(r.MTU())
mtu := int(route.MTU())
if mtu > header.IPv6MinimumMTU {
mtu = header.IPv6MinimumMTU
}
headerLen := int(r.MaxHeaderLength()) + header.ICMPv6ErrorHeaderSize
headerLen := int(route.MaxHeaderLength()) + header.ICMPv6ErrorHeaderSize
available := int(mtu) - headerLen
if available < header.IPv6MinimumSize {
return nil
@@ -843,9 +851,16 @@ func returnError(r *stack.Route, reason icmpReason, pkt *stack.PacketBuffer) *tc
default:
panic(fmt.Sprintf("unsupported ICMP type %T", reason))
}
icmpHdr.SetChecksum(header.ICMPv6Checksum(icmpHdr, r.LocalAddress, r.RemoteAddress, newPkt.Data))
err := r.WritePacket(nil /* gso */, stack.NetworkHeaderParams{Protocol: header.ICMPv6ProtocolNumber, TTL: r.DefaultTTL(), TOS: stack.DefaultTOS}, newPkt)
if err != nil {
icmpHdr.SetChecksum(header.ICMPv6Checksum(icmpHdr, route.LocalAddress, route.RemoteAddress, newPkt.Data))
if err := route.WritePacket(
nil, /* gso */
stack.NetworkHeaderParams{
Protocol: header.ICMPv6ProtocolNumber,
TTL: route.DefaultTTL(),
TOS: stack.DefaultTOS,
},
newPkt,
); err != nil {
sent.Dropped.Increment()
return err
}
+216 -5
View File
@@ -16,9 +16,11 @@ package ipv6
import (
"context"
"net"
"reflect"
"strings"
"testing"
"time"
"gvisor.dev/gvisor/pkg/tcpip"
"gvisor.dev/gvisor/pkg/tcpip/buffer"
@@ -28,6 +30,7 @@ import (
"gvisor.dev/gvisor/pkg/tcpip/link/sniffer"
"gvisor.dev/gvisor/pkg/tcpip/stack"
"gvisor.dev/gvisor/pkg/tcpip/transport/icmp"
"gvisor.dev/gvisor/pkg/tcpip/transport/udp"
"gvisor.dev/gvisor/pkg/waiter"
)
@@ -40,6 +43,9 @@ const (
defaultChannelSize = 1
defaultMTU = 65536
// Extra time to use when waiting for an async event to occur.
defaultAsyncPositiveEventTimeout = 30 * time.Second
)
var (
@@ -110,7 +116,9 @@ func (*stubNUDHandler) HandleUpperLevelConfirmation(addr tcpip.Address) {
var _ stack.NetworkInterface = (*testInterface)(nil)
type testInterface struct{}
type testInterface struct {
stack.NetworkLinkEndpoint
}
func (*testInterface) ID() tcpip.NICID {
return 0
@@ -128,10 +136,6 @@ func (*testInterface) Enabled() bool {
return true
}
func (*testInterface) LinkEndpoint() stack.LinkEndpoint {
return nil
}
func TestICMPCounts(t *testing.T) {
tests := []struct {
name string
@@ -1281,3 +1285,210 @@ func TestLinkAddressRequest(t *testing.T) {
))
}
}
func TestPacketQueing(t *testing.T) {
const nicID = 1
var (
host1NICLinkAddr = tcpip.LinkAddress("\x02\x03\x03\x04\x05\x06")
host2NICLinkAddr = tcpip.LinkAddress("\x02\x03\x03\x04\x05\x09")
host1IPv6Addr = tcpip.ProtocolAddress{
Protocol: ProtocolNumber,
AddressWithPrefix: tcpip.AddressWithPrefix{
Address: tcpip.Address(net.ParseIP("a::1").To16()),
PrefixLen: 64,
},
}
host2IPv6Addr = tcpip.ProtocolAddress{
Protocol: ProtocolNumber,
AddressWithPrefix: tcpip.AddressWithPrefix{
Address: tcpip.Address(net.ParseIP("a::2").To16()),
PrefixLen: 64,
},
}
)
tests := []struct {
name string
rxPkt func(*channel.Endpoint)
checkResp func(*testing.T, *channel.Endpoint)
}{
{
name: "ICMP Error",
rxPkt: func(e *channel.Endpoint) {
hdr := buffer.NewPrependable(header.IPv6MinimumSize + header.UDPMinimumSize)
u := header.UDP(hdr.Prepend(header.UDPMinimumSize))
u.Encode(&header.UDPFields{
SrcPort: 5555,
DstPort: 80,
Length: header.UDPMinimumSize,
})
sum := header.PseudoHeaderChecksum(udp.ProtocolNumber, host2IPv6Addr.AddressWithPrefix.Address, host1IPv6Addr.AddressWithPrefix.Address, header.UDPMinimumSize)
sum = header.Checksum(header.UDP([]byte{}), sum)
u.SetChecksum(^u.CalculateChecksum(sum))
payloadLength := hdr.UsedLength()
ip := header.IPv6(hdr.Prepend(header.IPv6MinimumSize))
ip.Encode(&header.IPv6Fields{
PayloadLength: uint16(payloadLength),
NextHeader: uint8(udp.ProtocolNumber),
HopLimit: DefaultTTL,
SrcAddr: host2IPv6Addr.AddressWithPrefix.Address,
DstAddr: host1IPv6Addr.AddressWithPrefix.Address,
})
e.InjectInbound(ProtocolNumber, stack.NewPacketBuffer(stack.PacketBufferOptions{
Data: hdr.View().ToVectorisedView(),
}))
},
checkResp: func(t *testing.T, e *channel.Endpoint) {
p, ok := e.ReadContext(context.Background())
if !ok {
t.Fatalf("timed out waiting for packet")
}
if p.Proto != ProtocolNumber {
t.Errorf("got p.Proto = %d, want = %d", p.Proto, ProtocolNumber)
}
if p.Route.RemoteLinkAddress != host2NICLinkAddr {
t.Errorf("got p.Route.RemoteLinkAddress = %s, want = %s", p.Route.RemoteLinkAddress, host2NICLinkAddr)
}
checker.IPv6(t, stack.PayloadSince(p.Pkt.NetworkHeader()),
checker.SrcAddr(host1IPv6Addr.AddressWithPrefix.Address),
checker.DstAddr(host2IPv6Addr.AddressWithPrefix.Address),
checker.ICMPv6(
checker.ICMPv6Type(header.ICMPv6DstUnreachable),
checker.ICMPv6Code(header.ICMPv6PortUnreachable)))
},
},
{
name: "Ping",
rxPkt: func(e *channel.Endpoint) {
totalLen := header.IPv6MinimumSize + header.ICMPv6MinimumSize
hdr := buffer.NewPrependable(totalLen)
pkt := header.ICMPv6(hdr.Prepend(header.ICMPv6MinimumSize))
pkt.SetType(header.ICMPv6EchoRequest)
pkt.SetCode(0)
pkt.SetChecksum(0)
pkt.SetChecksum(header.ICMPv6Checksum(pkt, host2IPv6Addr.AddressWithPrefix.Address, host1IPv6Addr.AddressWithPrefix.Address, buffer.VectorisedView{}))
ip := header.IPv6(hdr.Prepend(header.IPv6MinimumSize))
ip.Encode(&header.IPv6Fields{
PayloadLength: header.ICMPv6MinimumSize,
NextHeader: uint8(icmp.ProtocolNumber6),
HopLimit: DefaultTTL,
SrcAddr: host2IPv6Addr.AddressWithPrefix.Address,
DstAddr: host1IPv6Addr.AddressWithPrefix.Address,
})
e.InjectInbound(header.IPv6ProtocolNumber, stack.NewPacketBuffer(stack.PacketBufferOptions{
Data: hdr.View().ToVectorisedView(),
}))
},
checkResp: func(t *testing.T, e *channel.Endpoint) {
p, ok := e.ReadContext(context.Background())
if !ok {
t.Fatalf("timed out waiting for packet")
}
if p.Proto != ProtocolNumber {
t.Errorf("got p.Proto = %d, want = %d", p.Proto, ProtocolNumber)
}
if p.Route.RemoteLinkAddress != host2NICLinkAddr {
t.Errorf("got p.Route.RemoteLinkAddress = %s, want = %s", p.Route.RemoteLinkAddress, host2NICLinkAddr)
}
checker.IPv6(t, stack.PayloadSince(p.Pkt.NetworkHeader()),
checker.SrcAddr(host1IPv6Addr.AddressWithPrefix.Address),
checker.DstAddr(host2IPv6Addr.AddressWithPrefix.Address),
checker.ICMPv6(
checker.ICMPv6Type(header.ICMPv6EchoReply),
checker.ICMPv6Code(header.ICMPv6UnusedCode)))
},
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
e := channel.New(1, header.IPv6MinimumMTU, host1NICLinkAddr)
e.LinkEPCapabilities |= stack.CapabilityResolutionRequired
s := stack.New(stack.Options{
NetworkProtocols: []stack.NetworkProtocolFactory{NewProtocol},
TransportProtocols: []stack.TransportProtocolFactory{udp.NewProtocol},
})
if err := s.CreateNIC(nicID, e); err != nil {
t.Fatalf("s.CreateNIC(%d, _): %s", nicID, err)
}
if err := s.AddProtocolAddress(nicID, host1IPv6Addr); err != nil {
t.Fatalf("s.AddProtocolAddress(%d, %#v): %s", nicID, host1IPv6Addr, err)
}
s.SetRouteTable([]tcpip.Route{
tcpip.Route{
Destination: host1IPv6Addr.AddressWithPrefix.Subnet(),
NIC: nicID,
},
})
// Receive a packet to trigger link resolution before a response is sent.
test.rxPkt(e)
// Wait for a neighbor solicitation since link address resolution should
// be performed.
{
p, ok := e.ReadContext(context.Background())
if !ok {
t.Fatalf("timed out waiting for packet")
}
if p.Proto != ProtocolNumber {
t.Errorf("got Proto = %d, want = %d", p.Proto, ProtocolNumber)
}
snmc := header.SolicitedNodeAddr(host2IPv6Addr.AddressWithPrefix.Address)
if want := header.EthernetAddressFromMulticastIPv6Address(snmc); p.Route.RemoteLinkAddress != want {
t.Errorf("got p.Route.RemoteLinkAddress = %s, want = %s", p.Route.RemoteLinkAddress, want)
}
checker.IPv6(t, stack.PayloadSince(p.Pkt.NetworkHeader()),
checker.SrcAddr(host1IPv6Addr.AddressWithPrefix.Address),
checker.DstAddr(snmc),
checker.TTL(header.NDPHopLimit),
checker.NDPNS(
checker.NDPNSTargetAddress(host2IPv6Addr.AddressWithPrefix.Address),
checker.NDPNSOptions([]header.NDPOption{header.NDPSourceLinkLayerAddressOption(host1NICLinkAddr)}),
))
}
// Send a neighbor advertisement to complete link address resolution.
{
naSize := header.ICMPv6NeighborAdvertMinimumSize + header.NDPLinkLayerAddressSize
hdr := buffer.NewPrependable(header.IPv6MinimumSize + naSize)
pkt := header.ICMPv6(hdr.Prepend(naSize))
pkt.SetType(header.ICMPv6NeighborAdvert)
na := header.NDPNeighborAdvert(pkt.NDPPayload())
na.SetSolicitedFlag(true)
na.SetOverrideFlag(true)
na.SetTargetAddress(host2IPv6Addr.AddressWithPrefix.Address)
na.Options().Serialize(header.NDPOptionsSerializer{
header.NDPTargetLinkLayerAddressOption(host2NICLinkAddr),
})
pkt.SetChecksum(header.ICMPv6Checksum(pkt, host2IPv6Addr.AddressWithPrefix.Address, host1IPv6Addr.AddressWithPrefix.Address, buffer.VectorisedView{}))
payloadLength := hdr.UsedLength()
ip := header.IPv6(hdr.Prepend(header.IPv6MinimumSize))
ip.Encode(&header.IPv6Fields{
PayloadLength: uint16(payloadLength),
NextHeader: uint8(icmp.ProtocolNumber6),
HopLimit: header.NDPHopLimit,
SrcAddr: host2IPv6Addr.AddressWithPrefix.Address,
DstAddr: host1IPv6Addr.AddressWithPrefix.Address,
})
e.InjectInbound(ProtocolNumber, stack.NewPacketBuffer(stack.PacketBufferOptions{
Data: hdr.View().ToVectorisedView(),
}))
}
// Expect the response now that the link address has resolved.
test.checkResp(t, e)
// Since link resolution was already performed, it shouldn't be performed
// again.
test.rxPkt(e)
test.checkResp(t, e)
})
}
}
+16 -26
View File
@@ -66,7 +66,6 @@ var _ NDPEndpoint = (*endpoint)(nil)
type endpoint struct {
nic stack.NetworkInterface
linkEP stack.LinkEndpoint
linkAddrCache stack.LinkAddressCache
nud stack.NUDHandler
dispatcher stack.TransportDispatcher
@@ -364,21 +363,13 @@ func (e *endpoint) DefaultTTL() uint8 {
// MTU implements stack.NetworkEndpoint.MTU. It returns the link-layer MTU minus
// the network layer max header length.
func (e *endpoint) MTU() uint32 {
return calculateMTU(e.linkEP.MTU())
return calculateMTU(e.nic.MTU())
}
// MaxHeaderLength returns the maximum length needed by ipv6 headers (and
// underlying protocols).
func (e *endpoint) MaxHeaderLength() uint16 {
return e.linkEP.MaxHeaderLength() + header.IPv6MinimumSize
}
// GSOMaxSize returns the maximum GSO packet size.
func (e *endpoint) GSOMaxSize() uint32 {
if gso, ok := e.linkEP.(stack.GSOEndpoint); ok {
return gso.GSOMaxSize()
}
return 0
return e.nic.MaxHeaderLength() + header.IPv6MinimumSize
}
func (e *endpoint) addIPHeader(r *stack.Route, pkt *stack.PacketBuffer, params stack.NetworkHeaderParams) {
@@ -396,7 +387,7 @@ func (e *endpoint) addIPHeader(r *stack.Route, pkt *stack.PacketBuffer, params s
}
func (e *endpoint) packetMustBeFragmented(pkt *stack.PacketBuffer, gso *stack.GSO) bool {
return pkt.Size() > int(e.linkEP.MTU()) && (gso == nil || gso.Type == stack.GSONone)
return pkt.Size() > int(e.nic.MTU()) && (gso == nil || gso.Type == stack.GSONone)
}
// handleFragments fragments pkt and calls the handler function on each
@@ -477,19 +468,19 @@ func (e *endpoint) WritePacket(r *stack.Route, gso *stack.GSO, params stack.Netw
}
if e.packetMustBeFragmented(pkt, gso) {
sent, remain, err := e.handleFragments(r, gso, e.linkEP.MTU(), pkt, params.Protocol, func(fragPkt *stack.PacketBuffer) *tcpip.Error {
sent, remain, err := e.handleFragments(r, gso, e.nic.MTU(), pkt, params.Protocol, func(fragPkt *stack.PacketBuffer) *tcpip.Error {
// TODO(gvisor.dev/issue/3884): Evaluate whether we want to send each
// fragment one by one using WritePacket() (current strategy) or if we
// want to create a PacketBufferList from the fragments and feed it to
// WritePackets(). It'll be faster but cost more memory.
return e.linkEP.WritePacket(r, gso, ProtocolNumber, fragPkt)
return e.nic.WritePacket(r, gso, ProtocolNumber, fragPkt)
})
r.Stats().IP.PacketsSent.IncrementBy(uint64(sent))
r.Stats().IP.OutgoingPacketErrors.IncrementBy(uint64(remain))
return err
}
if err := e.linkEP.WritePacket(r, gso, ProtocolNumber, pkt); err != nil {
if err := e.nic.WritePacket(r, gso, ProtocolNumber, pkt); err != nil {
r.Stats().IP.OutgoingPacketErrors.Increment()
return err
}
@@ -511,7 +502,7 @@ func (e *endpoint) WritePackets(r *stack.Route, gso *stack.GSO, pkts stack.Packe
e.addIPHeader(r, pb, params)
if e.packetMustBeFragmented(pb, gso) {
current := pb
_, _, err := e.handleFragments(r, gso, e.linkEP.MTU(), pb, params.Protocol, func(fragPkt *stack.PacketBuffer) *tcpip.Error {
_, _, err := e.handleFragments(r, gso, e.nic.MTU(), pb, params.Protocol, func(fragPkt *stack.PacketBuffer) *tcpip.Error {
// Modify the packet list in place with the new fragments.
pkts.InsertAfter(current, fragPkt)
current = current.Next()
@@ -536,7 +527,7 @@ func (e *endpoint) WritePackets(r *stack.Route, gso *stack.GSO, pkts stack.Packe
if len(dropped) == 0 && len(natPkts) == 0 {
// Fast path: If no packets are to be dropped then we can just invoke the
// faster WritePackets API directly.
n, err := e.linkEP.WritePackets(r, gso, pkts, ProtocolNumber)
n, err := e.nic.WritePackets(r, gso, pkts, ProtocolNumber)
r.Stats().IP.PacketsSent.IncrementBy(uint64(n))
if err != nil {
r.Stats().IP.OutgoingPacketErrors.IncrementBy(uint64(pkts.Len() - n))
@@ -563,7 +554,7 @@ func (e *endpoint) WritePackets(r *stack.Route, gso *stack.GSO, pkts stack.Packe
continue
}
}
if err := e.linkEP.WritePacket(r, gso, ProtocolNumber, pkt); err != nil {
if err := e.nic.WritePacket(r, gso, ProtocolNumber, pkt); err != nil {
r.Stats().IP.PacketsSent.IncrementBy(uint64(n))
r.Stats().IP.OutgoingPacketErrors.IncrementBy(uint64(pkts.Len() - n + len(dropped)))
// Dropped packets aren't errors, so include them in
@@ -643,7 +634,7 @@ func (e *endpoint) HandlePacket(r *stack.Route, pkt *stack.PacketBuffer) {
// As per RFC 8200 section 4.1, the Hop By Hop extension header is
// restricted to appear immediately after an IPv6 fixed header.
if previousHeaderStart != 0 {
_ = returnError(r, &icmpReasonParameterProblem{
_ = e.protocol.returnError(r, &icmpReasonParameterProblem{
code: header.ICMPv6UnknownHeader,
pointer: previousHeaderStart,
}, pkt)
@@ -682,7 +673,7 @@ func (e *endpoint) HandlePacket(r *stack.Route, pkt *stack.PacketBuffer) {
// ICMP Parameter Problem, Code 2, message to the packet's
// Source Address, pointing to the unrecognized Option Type.
//
_ = returnError(r, &icmpReasonParameterProblem{
_ = e.protocol.returnError(r, &icmpReasonParameterProblem{
code: header.ICMPv6UnknownOption,
pointer: it.ParseOffset() + optsIt.OptionOffset(),
respondToMulticast: true,
@@ -707,7 +698,7 @@ func (e *endpoint) HandlePacket(r *stack.Route, pkt *stack.PacketBuffer) {
// header, so we just make sure Segments Left is zero before processing
// the next extension header.
if extHdr.SegmentsLeft() != 0 {
_ = returnError(r, &icmpReasonParameterProblem{
_ = e.protocol.returnError(r, &icmpReasonParameterProblem{
code: header.ICMPv6ErroneousHeader,
pointer: it.ParseOffset(),
}, pkt)
@@ -859,7 +850,7 @@ func (e *endpoint) HandlePacket(r *stack.Route, pkt *stack.PacketBuffer) {
// ICMP Parameter Problem, Code 2, message to the packet's
// Source Address, pointing to the unrecognized Option Type.
//
_ = returnError(r, &icmpReasonParameterProblem{
_ = e.protocol.returnError(r, &icmpReasonParameterProblem{
code: header.ICMPv6UnknownOption,
pointer: it.ParseOffset() + optsIt.OptionOffset(),
respondToMulticast: true,
@@ -896,7 +887,7 @@ func (e *endpoint) HandlePacket(r *stack.Route, pkt *stack.PacketBuffer) {
// message with Code 4 in response to a packet for which the
// transport protocol (e.g., UDP) has no listener, if that transport
// protocol has no alternative means to inform the sender.
_ = returnError(r, &icmpReasonPortUnreachable{}, pkt)
_ = e.protocol.returnError(r, &icmpReasonPortUnreachable{}, pkt)
case stack.TransportPacketProtocolUnreachable:
// As per RFC 8200 section 4. (page 7):
// Extension headers are numbered from IANA IP Protocol Numbers
@@ -917,7 +908,7 @@ func (e *endpoint) HandlePacket(r *stack.Route, pkt *stack.PacketBuffer) {
//
// Which when taken together indicate that an unknown protocol should
// be treated as an unrecognized next header value.
_ = returnError(r, &icmpReasonParameterProblem{
_ = e.protocol.returnError(r, &icmpReasonParameterProblem{
code: header.ICMPv6UnknownHeader,
pointer: it.ParseOffset(),
}, pkt)
@@ -927,7 +918,7 @@ func (e *endpoint) HandlePacket(r *stack.Route, pkt *stack.PacketBuffer) {
}
default:
_ = returnError(r, &icmpReasonParameterProblem{
_ = e.protocol.returnError(r, &icmpReasonParameterProblem{
code: header.ICMPv6UnknownHeader,
pointer: it.ParseOffset(),
}, pkt)
@@ -1302,7 +1293,6 @@ func (*protocol) ParseAddresses(v buffer.View) (src, dst tcpip.Address) {
func (p *protocol) NewEndpoint(nic stack.NetworkInterface, linkAddrCache stack.LinkAddressCache, nud stack.NUDHandler, dispatcher stack.TransportDispatcher) stack.NetworkEndpoint {
e := &endpoint{
nic: nic,
linkEP: nic.LinkEndpoint(),
linkAddrCache: linkAddrCache,
nud: nud,
dispatcher: dispatcher,
+1 -1
View File
@@ -1289,7 +1289,7 @@ func (ndp *ndpState) generateSLAACAddr(prefix tcpip.Subnet, state *slaacPrefixSt
//
// TODO(b/141011931): Validate a LinkEndpoint's link address (provided by
// LinkEndpoint.LinkAddress) before reaching this point.
linkAddr := ndp.ep.linkEP.LinkAddress()
linkAddr := ndp.ep.nic.LinkAddress()
if !header.IsValidUnicastEthernetAddress(linkAddr) {
return false
}
+2 -3
View File
@@ -56,7 +56,6 @@ go_library(
srcs = [
"addressable_endpoint_state.go",
"conntrack.go",
"forwarder.go",
"headertype_string.go",
"icmp_rate_limit.go",
"iptables.go",
@@ -73,6 +72,7 @@ go_library(
"nud.go",
"packet_buffer.go",
"packet_buffer_list.go",
"pending_packets.go",
"rand.go",
"registration.go",
"route.go",
@@ -123,7 +123,6 @@ go_test(
"//pkg/tcpip/header",
"//pkg/tcpip/link/channel",
"//pkg/tcpip/link/loopback",
"//pkg/tcpip/network/arp",
"//pkg/tcpip/network/ipv4",
"//pkg/tcpip/network/ipv6",
"//pkg/tcpip/ports",
@@ -139,7 +138,7 @@ go_test(
name = "stack_test",
size = "small",
srcs = [
"forwarder_test.go",
"forwarding_test.go",
"linkaddrcache_test.go",
"neighbor_cache_test.go",
"neighbor_entry_test.go",

Some files were not shown because too many files have changed in this diff Show More