summaryrefslogtreecommitdiffhomepage
path: root/pkg/tcpip/stack/stack_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/tcpip/stack/stack_test.go')
-rw-r--r--pkg/tcpip/stack/stack_test.go1151
1 files changed, 0 insertions, 1151 deletions
diff --git a/pkg/tcpip/stack/stack_test.go b/pkg/tcpip/stack/stack_test.go
deleted file mode 100644
index 959071dbe..000000000
--- a/pkg/tcpip/stack/stack_test.go
+++ /dev/null
@@ -1,1151 +0,0 @@
-// Copyright 2018 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 stack_test contains tests for the stack. It is in its own package so
-// that the tests can also validate that all definitions needed to implement
-// transport and network protocols are properly exported by the stack package.
-package stack_test
-
-import (
- "bytes"
- "fmt"
- "math"
- "strings"
- "testing"
-
- "gvisor.dev/gvisor/pkg/tcpip"
- "gvisor.dev/gvisor/pkg/tcpip/buffer"
- "gvisor.dev/gvisor/pkg/tcpip/header"
- "gvisor.dev/gvisor/pkg/tcpip/link/channel"
- "gvisor.dev/gvisor/pkg/tcpip/stack"
-)
-
-const (
- fakeNetNumber tcpip.NetworkProtocolNumber = math.MaxUint32
- fakeNetHeaderLen = 12
-
- // fakeControlProtocol is used for control packets that represent
- // destination port unreachable.
- fakeControlProtocol tcpip.TransportProtocolNumber = 2
-
- // defaultMTU is the MTU, in bytes, used throughout the tests, except
- // where another value is explicitly used. It is chosen to match the MTU
- // of loopback interfaces on linux systems.
- defaultMTU = 65536
-)
-
-// fakeNetworkEndpoint is a network-layer protocol endpoint. It counts sent and
-// received packets; the counts of all endpoints are aggregated in the protocol
-// descriptor.
-//
-// Headers of this protocol are fakeNetHeaderLen bytes, but we currently only
-// use the first three: destination address, source address, and transport
-// protocol. They're all one byte fields to simplify parsing.
-type fakeNetworkEndpoint struct {
- nicid tcpip.NICID
- id stack.NetworkEndpointID
- proto *fakeNetworkProtocol
- dispatcher stack.TransportDispatcher
- linkEP stack.LinkEndpoint
-}
-
-func (f *fakeNetworkEndpoint) MTU() uint32 {
- return f.linkEP.MTU() - uint32(f.MaxHeaderLength())
-}
-
-func (f *fakeNetworkEndpoint) NICID() tcpip.NICID {
- return f.nicid
-}
-
-func (*fakeNetworkEndpoint) DefaultTTL() uint8 {
- return 123
-}
-
-func (f *fakeNetworkEndpoint) ID() *stack.NetworkEndpointID {
- return &f.id
-}
-
-func (f *fakeNetworkEndpoint) HandlePacket(r *stack.Route, vv buffer.VectorisedView) {
- // Increment the received packet count in the protocol descriptor.
- f.proto.packetCount[int(f.id.LocalAddress[0])%len(f.proto.packetCount)]++
-
- // Consume the network header.
- b := vv.First()
- vv.TrimFront(fakeNetHeaderLen)
-
- // Handle control packets.
- if b[2] == uint8(fakeControlProtocol) {
- nb := vv.First()
- if len(nb) < fakeNetHeaderLen {
- return
- }
-
- vv.TrimFront(fakeNetHeaderLen)
- f.dispatcher.DeliverTransportControlPacket(tcpip.Address(nb[1:2]), tcpip.Address(nb[0:1]), fakeNetNumber, tcpip.TransportProtocolNumber(nb[2]), stack.ControlPortUnreachable, 0, vv)
- return
- }
-
- // Dispatch the packet to the transport protocol.
- f.dispatcher.DeliverTransportPacket(r, tcpip.TransportProtocolNumber(b[2]), buffer.View([]byte{}), vv)
-}
-
-func (f *fakeNetworkEndpoint) MaxHeaderLength() uint16 {
- return f.linkEP.MaxHeaderLength() + fakeNetHeaderLen
-}
-
-func (f *fakeNetworkEndpoint) PseudoHeaderChecksum(protocol tcpip.TransportProtocolNumber, dstAddr tcpip.Address) uint16 {
- return 0
-}
-
-func (f *fakeNetworkEndpoint) Capabilities() stack.LinkEndpointCapabilities {
- return f.linkEP.Capabilities()
-}
-
-func (f *fakeNetworkEndpoint) WritePacket(r *stack.Route, gso *stack.GSO, hdr buffer.Prependable, payload buffer.VectorisedView, protocol tcpip.TransportProtocolNumber, _ uint8, loop stack.PacketLooping) *tcpip.Error {
- // Increment the sent packet count in the protocol descriptor.
- f.proto.sendPacketCount[int(r.RemoteAddress[0])%len(f.proto.sendPacketCount)]++
-
- // Add the protocol's header to the packet and send it to the link
- // endpoint.
- b := hdr.Prepend(fakeNetHeaderLen)
- b[0] = r.RemoteAddress[0]
- b[1] = f.id.LocalAddress[0]
- b[2] = byte(protocol)
-
- if loop&stack.PacketLoop != 0 {
- views := make([]buffer.View, 1, 1+len(payload.Views()))
- views[0] = hdr.View()
- views = append(views, payload.Views()...)
- vv := buffer.NewVectorisedView(len(views[0])+payload.Size(), views)
- f.HandlePacket(r, vv)
- }
- if loop&stack.PacketOut == 0 {
- return nil
- }
-
- return f.linkEP.WritePacket(r, gso, hdr, payload, fakeNetNumber)
-}
-
-func (*fakeNetworkEndpoint) WriteHeaderIncludedPacket(r *stack.Route, payload buffer.VectorisedView, loop stack.PacketLooping) *tcpip.Error {
- return tcpip.ErrNotSupported
-}
-
-func (*fakeNetworkEndpoint) Close() {}
-
-type fakeNetGoodOption bool
-
-type fakeNetBadOption bool
-
-type fakeNetInvalidValueOption int
-
-type fakeNetOptions struct {
- good bool
-}
-
-// fakeNetworkProtocol is a network-layer protocol descriptor. It aggregates the
-// number of packets sent and received via endpoints of this protocol. The index
-// where packets are added is given by the packet's destination address MOD 10.
-type fakeNetworkProtocol struct {
- packetCount [10]int
- sendPacketCount [10]int
- opts fakeNetOptions
-}
-
-func (f *fakeNetworkProtocol) Number() tcpip.NetworkProtocolNumber {
- return fakeNetNumber
-}
-
-func (f *fakeNetworkProtocol) MinimumPacketSize() int {
- return fakeNetHeaderLen
-}
-
-func (*fakeNetworkProtocol) ParseAddresses(v buffer.View) (src, dst tcpip.Address) {
- return tcpip.Address(v[1:2]), tcpip.Address(v[0:1])
-}
-
-func (f *fakeNetworkProtocol) NewEndpoint(nicid tcpip.NICID, addr tcpip.Address, linkAddrCache stack.LinkAddressCache, dispatcher stack.TransportDispatcher, linkEP stack.LinkEndpoint) (stack.NetworkEndpoint, *tcpip.Error) {
- return &fakeNetworkEndpoint{
- nicid: nicid,
- id: stack.NetworkEndpointID{addr},
- proto: f,
- dispatcher: dispatcher,
- linkEP: linkEP,
- }, nil
-}
-
-func (f *fakeNetworkProtocol) SetOption(option interface{}) *tcpip.Error {
- switch v := option.(type) {
- case fakeNetGoodOption:
- f.opts.good = bool(v)
- return nil
- case fakeNetInvalidValueOption:
- return tcpip.ErrInvalidOptionValue
- default:
- return tcpip.ErrUnknownProtocolOption
- }
-}
-
-func (f *fakeNetworkProtocol) Option(option interface{}) *tcpip.Error {
- switch v := option.(type) {
- case *fakeNetGoodOption:
- *v = fakeNetGoodOption(f.opts.good)
- return nil
- default:
- return tcpip.ErrUnknownProtocolOption
- }
-}
-
-func TestNetworkReceive(t *testing.T) {
- // Create a stack with the fake network protocol, one nic, and two
- // addresses attached to it: 1 & 2.
- id, linkEP := channel.New(10, defaultMTU, "")
- s := stack.New([]string{"fakeNet"}, nil, stack.Options{})
- if err := s.CreateNIC(1, id); err != nil {
- t.Fatalf("CreateNIC failed: %v", err)
- }
-
- if err := s.AddAddress(1, fakeNetNumber, "\x01"); err != nil {
- t.Fatalf("AddAddress failed: %v", err)
- }
-
- if err := s.AddAddress(1, fakeNetNumber, "\x02"); err != nil {
- t.Fatalf("AddAddress failed: %v", err)
- }
-
- fakeNet := s.NetworkProtocolInstance(fakeNetNumber).(*fakeNetworkProtocol)
-
- buf := buffer.NewView(30)
-
- // Make sure packet with wrong address is not delivered.
- buf[0] = 3
- linkEP.Inject(fakeNetNumber, buf.ToVectorisedView())
- if fakeNet.packetCount[1] != 0 {
- t.Errorf("packetCount[1] = %d, want %d", fakeNet.packetCount[1], 0)
- }
- if fakeNet.packetCount[2] != 0 {
- t.Errorf("packetCount[2] = %d, want %d", fakeNet.packetCount[2], 0)
- }
-
- // Make sure packet is delivered to first endpoint.
- buf[0] = 1
- linkEP.Inject(fakeNetNumber, buf.ToVectorisedView())
- if fakeNet.packetCount[1] != 1 {
- t.Errorf("packetCount[1] = %d, want %d", fakeNet.packetCount[1], 1)
- }
- if fakeNet.packetCount[2] != 0 {
- t.Errorf("packetCount[2] = %d, want %d", fakeNet.packetCount[2], 0)
- }
-
- // Make sure packet is delivered to second endpoint.
- buf[0] = 2
- linkEP.Inject(fakeNetNumber, buf.ToVectorisedView())
- if fakeNet.packetCount[1] != 1 {
- t.Errorf("packetCount[1] = %d, want %d", fakeNet.packetCount[1], 1)
- }
- if fakeNet.packetCount[2] != 1 {
- t.Errorf("packetCount[2] = %d, want %d", fakeNet.packetCount[2], 1)
- }
-
- // Make sure packet is not delivered if protocol number is wrong.
- linkEP.Inject(fakeNetNumber-1, buf.ToVectorisedView())
- if fakeNet.packetCount[1] != 1 {
- t.Errorf("packetCount[1] = %d, want %d", fakeNet.packetCount[1], 1)
- }
- if fakeNet.packetCount[2] != 1 {
- t.Errorf("packetCount[2] = %d, want %d", fakeNet.packetCount[2], 1)
- }
-
- // Make sure packet that is too small is dropped.
- buf.CapLength(2)
- linkEP.Inject(fakeNetNumber, buf.ToVectorisedView())
- if fakeNet.packetCount[1] != 1 {
- t.Errorf("packetCount[1] = %d, want %d", fakeNet.packetCount[1], 1)
- }
- if fakeNet.packetCount[2] != 1 {
- t.Errorf("packetCount[2] = %d, want %d", fakeNet.packetCount[2], 1)
- }
-}
-
-func sendTo(t *testing.T, s *stack.Stack, addr tcpip.Address, payload buffer.View) {
- r, err := s.FindRoute(0, "", addr, fakeNetNumber, false /* multicastLoop */)
- if err != nil {
- t.Fatalf("FindRoute failed: %v", err)
- }
- defer r.Release()
-
- hdr := buffer.NewPrependable(int(r.MaxHeaderLength()))
- if err := r.WritePacket(nil /* gso */, hdr, payload.ToVectorisedView(), fakeTransNumber, 123); err != nil {
- t.Errorf("WritePacket failed: %v", err)
- }
-}
-
-func TestNetworkSend(t *testing.T) {
- // Create a stack with the fake network protocol, one nic, and one
- // address: 1. The route table sends all packets through the only
- // existing nic.
- id, linkEP := channel.New(10, defaultMTU, "")
- s := stack.New([]string{"fakeNet"}, nil, stack.Options{})
- if err := s.CreateNIC(1, id); err != nil {
- t.Fatalf("NewNIC failed: %v", err)
- }
-
- s.SetRouteTable([]tcpip.Route{{"\x00", "\x00", "\x00", 1}})
-
- if err := s.AddAddress(1, fakeNetNumber, "\x01"); err != nil {
- t.Fatalf("AddAddress failed: %v", err)
- }
-
- // Make sure that the link-layer endpoint received the outbound packet.
- sendTo(t, s, "\x03", nil)
- if c := linkEP.Drain(); c != 1 {
- t.Errorf("packetCount = %d, want %d", c, 1)
- }
-}
-
-func TestNetworkSendMultiRoute(t *testing.T) {
- // Create a stack with the fake network protocol, two nics, and two
- // addresses per nic, the first nic has odd address, the second one has
- // even addresses.
- s := stack.New([]string{"fakeNet"}, nil, stack.Options{})
-
- id1, linkEP1 := channel.New(10, defaultMTU, "")
- if err := s.CreateNIC(1, id1); err != nil {
- t.Fatalf("CreateNIC failed: %v", err)
- }
-
- if err := s.AddAddress(1, fakeNetNumber, "\x01"); err != nil {
- t.Fatalf("AddAddress failed: %v", err)
- }
-
- if err := s.AddAddress(1, fakeNetNumber, "\x03"); err != nil {
- t.Fatalf("AddAddress failed: %v", err)
- }
-
- id2, linkEP2 := channel.New(10, defaultMTU, "")
- if err := s.CreateNIC(2, id2); err != nil {
- t.Fatalf("CreateNIC failed: %v", err)
- }
-
- if err := s.AddAddress(2, fakeNetNumber, "\x02"); err != nil {
- t.Fatalf("AddAddress failed: %v", err)
- }
-
- if err := s.AddAddress(2, fakeNetNumber, "\x04"); err != nil {
- t.Fatalf("AddAddress failed: %v", err)
- }
-
- // Set a route table that sends all packets with odd destination
- // addresses through the first NIC, and all even destination address
- // through the second one.
- s.SetRouteTable([]tcpip.Route{
- {"\x01", "\x01", "\x00", 1},
- {"\x00", "\x01", "\x00", 2},
- })
-
- // Send a packet to an odd destination.
- sendTo(t, s, "\x05", nil)
-
- if c := linkEP1.Drain(); c != 1 {
- t.Errorf("packetCount = %d, want %d", c, 1)
- }
-
- // Send a packet to an even destination.
- sendTo(t, s, "\x06", nil)
-
- if c := linkEP2.Drain(); c != 1 {
- t.Errorf("packetCount = %d, want %d", c, 1)
- }
-}
-
-func testRoute(t *testing.T, s *stack.Stack, nic tcpip.NICID, srcAddr, dstAddr, expectedSrcAddr tcpip.Address) {
- r, err := s.FindRoute(nic, srcAddr, dstAddr, fakeNetNumber, false /* multicastLoop */)
- if err != nil {
- t.Fatalf("FindRoute failed: %v", err)
- }
-
- defer r.Release()
-
- if r.LocalAddress != expectedSrcAddr {
- t.Fatalf("Bad source address: expected %v, got %v", expectedSrcAddr, r.LocalAddress)
- }
-
- if r.RemoteAddress != dstAddr {
- t.Fatalf("Bad destination address: expected %v, got %v", dstAddr, r.RemoteAddress)
- }
-}
-
-func testNoRoute(t *testing.T, s *stack.Stack, nic tcpip.NICID, srcAddr, dstAddr tcpip.Address) {
- _, err := s.FindRoute(nic, srcAddr, dstAddr, fakeNetNumber, false /* multicastLoop */)
- if err != tcpip.ErrNoRoute {
- t.Fatalf("FindRoute returned unexpected error, expected tcpip.ErrNoRoute, got %v", err)
- }
-}
-
-func TestRoutes(t *testing.T) {
- // Create a stack with the fake network protocol, two nics, and two
- // addresses per nic, the first nic has odd address, the second one has
- // even addresses.
- s := stack.New([]string{"fakeNet"}, nil, stack.Options{})
-
- id1, _ := channel.New(10, defaultMTU, "")
- if err := s.CreateNIC(1, id1); err != nil {
- t.Fatalf("CreateNIC failed: %v", err)
- }
-
- if err := s.AddAddress(1, fakeNetNumber, "\x01"); err != nil {
- t.Fatalf("AddAddress failed: %v", err)
- }
-
- if err := s.AddAddress(1, fakeNetNumber, "\x03"); err != nil {
- t.Fatalf("AddAddress failed: %v", err)
- }
-
- id2, _ := channel.New(10, defaultMTU, "")
- if err := s.CreateNIC(2, id2); err != nil {
- t.Fatalf("CreateNIC failed: %v", err)
- }
-
- if err := s.AddAddress(2, fakeNetNumber, "\x02"); err != nil {
- t.Fatalf("AddAddress failed: %v", err)
- }
-
- if err := s.AddAddress(2, fakeNetNumber, "\x04"); err != nil {
- t.Fatalf("AddAddress failed: %v", err)
- }
-
- // Set a route table that sends all packets with odd destination
- // addresses through the first NIC, and all even destination address
- // through the second one.
- s.SetRouteTable([]tcpip.Route{
- {"\x01", "\x01", "\x00", 1},
- {"\x00", "\x01", "\x00", 2},
- })
-
- // Test routes to odd address.
- testRoute(t, s, 0, "", "\x05", "\x01")
- testRoute(t, s, 0, "\x01", "\x05", "\x01")
- testRoute(t, s, 1, "\x01", "\x05", "\x01")
- testRoute(t, s, 0, "\x03", "\x05", "\x03")
- testRoute(t, s, 1, "\x03", "\x05", "\x03")
-
- // Test routes to even address.
- testRoute(t, s, 0, "", "\x06", "\x02")
- testRoute(t, s, 0, "\x02", "\x06", "\x02")
- testRoute(t, s, 2, "\x02", "\x06", "\x02")
- testRoute(t, s, 0, "\x04", "\x06", "\x04")
- testRoute(t, s, 2, "\x04", "\x06", "\x04")
-
- // Try to send to odd numbered address from even numbered ones, then
- // vice-versa.
- testNoRoute(t, s, 0, "\x02", "\x05")
- testNoRoute(t, s, 2, "\x02", "\x05")
- testNoRoute(t, s, 0, "\x04", "\x05")
- testNoRoute(t, s, 2, "\x04", "\x05")
-
- testNoRoute(t, s, 0, "\x01", "\x06")
- testNoRoute(t, s, 1, "\x01", "\x06")
- testNoRoute(t, s, 0, "\x03", "\x06")
- testNoRoute(t, s, 1, "\x03", "\x06")
-}
-
-func TestAddressRemoval(t *testing.T) {
- s := stack.New([]string{"fakeNet"}, nil, stack.Options{})
-
- id, linkEP := channel.New(10, defaultMTU, "")
- if err := s.CreateNIC(1, id); err != nil {
- t.Fatalf("CreateNIC failed: %v", err)
- }
-
- if err := s.AddAddress(1, fakeNetNumber, "\x01"); err != nil {
- t.Fatalf("AddAddress failed: %v", err)
- }
-
- fakeNet := s.NetworkProtocolInstance(fakeNetNumber).(*fakeNetworkProtocol)
-
- buf := buffer.NewView(30)
-
- // Write a packet, and check that it gets delivered.
- fakeNet.packetCount[1] = 0
- buf[0] = 1
- linkEP.Inject(fakeNetNumber, buf.ToVectorisedView())
- if fakeNet.packetCount[1] != 1 {
- t.Errorf("packetCount[1] = %d, want %d", fakeNet.packetCount[1], 1)
- }
-
- // Remove the address, then check that packet doesn't get delivered
- // anymore.
- if err := s.RemoveAddress(1, "\x01"); err != nil {
- t.Fatalf("RemoveAddress failed: %v", err)
- }
-
- linkEP.Inject(fakeNetNumber, buf.ToVectorisedView())
- if fakeNet.packetCount[1] != 1 {
- t.Errorf("packetCount[1] = %d, want %d", fakeNet.packetCount[1], 1)
- }
-
- // Check that removing the same address fails.
- if err := s.RemoveAddress(1, "\x01"); err != tcpip.ErrBadLocalAddress {
- t.Fatalf("RemoveAddress failed: %v", err)
- }
-}
-
-func TestDelayedRemovalDueToRoute(t *testing.T) {
- s := stack.New([]string{"fakeNet"}, nil, stack.Options{})
-
- id, linkEP := channel.New(10, defaultMTU, "")
- if err := s.CreateNIC(1, id); err != nil {
- t.Fatalf("CreateNIC failed: %v", err)
- }
-
- if err := s.AddAddress(1, fakeNetNumber, "\x01"); err != nil {
- t.Fatalf("AddAddress failed: %v", err)
- }
-
- s.SetRouteTable([]tcpip.Route{
- {"\x00", "\x00", "\x00", 1},
- })
-
- fakeNet := s.NetworkProtocolInstance(fakeNetNumber).(*fakeNetworkProtocol)
-
- buf := buffer.NewView(30)
-
- // Write a packet, and check that it gets delivered.
- fakeNet.packetCount[1] = 0
- buf[0] = 1
- linkEP.Inject(fakeNetNumber, buf.ToVectorisedView())
- if fakeNet.packetCount[1] != 1 {
- t.Errorf("packetCount[1] = %d, want %d", fakeNet.packetCount[1], 1)
- }
-
- // Get a route, check that packet is still deliverable.
- r, err := s.FindRoute(0, "", "\x02", fakeNetNumber, false /* multicastLoop */)
- if err != nil {
- t.Fatalf("FindRoute failed: %v", err)
- }
-
- linkEP.Inject(fakeNetNumber, buf.ToVectorisedView())
- if fakeNet.packetCount[1] != 2 {
- t.Errorf("packetCount[1] = %d, want %d", fakeNet.packetCount[1], 2)
- }
-
- // Remove the address, then check that packet is still deliverable
- // because the route is keeping the address alive.
- if err := s.RemoveAddress(1, "\x01"); err != nil {
- t.Fatalf("RemoveAddress failed: %v", err)
- }
-
- linkEP.Inject(fakeNetNumber, buf.ToVectorisedView())
- if fakeNet.packetCount[1] != 3 {
- t.Errorf("packetCount[1] = %d, want %d", fakeNet.packetCount[1], 3)
- }
-
- // Check that removing the same address fails.
- if err := s.RemoveAddress(1, "\x01"); err != tcpip.ErrBadLocalAddress {
- t.Fatalf("RemoveAddress failed: %v", err)
- }
-
- // Release the route, then check that packet is not deliverable anymore.
- r.Release()
- linkEP.Inject(fakeNetNumber, buf.ToVectorisedView())
- if fakeNet.packetCount[1] != 3 {
- t.Errorf("packetCount[1] = %d, want %d", fakeNet.packetCount[1], 3)
- }
-}
-
-func TestPromiscuousMode(t *testing.T) {
- s := stack.New([]string{"fakeNet"}, nil, stack.Options{})
-
- id, linkEP := channel.New(10, defaultMTU, "")
- if err := s.CreateNIC(1, id); err != nil {
- t.Fatalf("CreateNIC failed: %v", err)
- }
-
- s.SetRouteTable([]tcpip.Route{
- {"\x00", "\x00", "\x00", 1},
- })
-
- fakeNet := s.NetworkProtocolInstance(fakeNetNumber).(*fakeNetworkProtocol)
-
- buf := buffer.NewView(30)
-
- // Write a packet, and check that it doesn't get delivered as we don't
- // have a matching endpoint.
- fakeNet.packetCount[1] = 0
- buf[0] = 1
- linkEP.Inject(fakeNetNumber, buf.ToVectorisedView())
- if fakeNet.packetCount[1] != 0 {
- t.Errorf("packetCount[1] = %d, want %d", fakeNet.packetCount[1], 0)
- }
-
- // Set promiscuous mode, then check that packet is delivered.
- if err := s.SetPromiscuousMode(1, true); err != nil {
- t.Fatalf("SetPromiscuousMode failed: %v", err)
- }
-
- linkEP.Inject(fakeNetNumber, buf.ToVectorisedView())
- if fakeNet.packetCount[1] != 1 {
- t.Errorf("packetCount[1] = %d, want %d", fakeNet.packetCount[1], 1)
- }
-
- // Check that we can't get a route as there is no local address.
- _, err := s.FindRoute(0, "", "\x02", fakeNetNumber, false /* multicastLoop */)
- if err != tcpip.ErrNoRoute {
- t.Fatalf("FindRoute returned unexpected status: expected %v, got %v", tcpip.ErrNoRoute, err)
- }
-
- // Set promiscuous mode to false, then check that packet can't be
- // delivered anymore.
- if err := s.SetPromiscuousMode(1, false); err != nil {
- t.Fatalf("SetPromiscuousMode failed: %v", err)
- }
-
- linkEP.Inject(fakeNetNumber, buf.ToVectorisedView())
- if fakeNet.packetCount[1] != 1 {
- t.Errorf("packetCount[1] = %d, want %d", fakeNet.packetCount[1], 1)
- }
-}
-
-func TestAddressSpoofing(t *testing.T) {
- srcAddr := tcpip.Address("\x01")
- dstAddr := tcpip.Address("\x02")
-
- s := stack.New([]string{"fakeNet"}, nil, stack.Options{})
-
- id, _ := channel.New(10, defaultMTU, "")
- if err := s.CreateNIC(1, id); err != nil {
- t.Fatalf("CreateNIC failed: %v", err)
- }
-
- if err := s.AddAddress(1, fakeNetNumber, dstAddr); err != nil {
- t.Fatalf("AddAddress failed: %v", err)
- }
-
- s.SetRouteTable([]tcpip.Route{
- {"\x00", "\x00", "\x00", 1},
- })
-
- // With address spoofing disabled, FindRoute does not permit an address
- // that was not added to the NIC to be used as the source.
- r, err := s.FindRoute(0, srcAddr, dstAddr, fakeNetNumber, false /* multicastLoop */)
- if err == nil {
- t.Errorf("FindRoute succeeded with route %+v when it should have failed", r)
- }
-
- // With address spoofing enabled, FindRoute permits any address to be used
- // as the source.
- if err := s.SetSpoofing(1, true); err != nil {
- t.Fatalf("SetSpoofing failed: %v", err)
- }
- r, err = s.FindRoute(0, srcAddr, dstAddr, fakeNetNumber, false /* multicastLoop */)
- if err != nil {
- t.Fatalf("FindRoute failed: %v", err)
- }
- if r.LocalAddress != srcAddr {
- t.Errorf("Route has wrong local address: got %v, wanted %v", r.LocalAddress, srcAddr)
- }
- if r.RemoteAddress != dstAddr {
- t.Errorf("Route has wrong remote address: got %v, wanted %v", r.RemoteAddress, dstAddr)
- }
-}
-
-func TestBroadcastNeedsNoRoute(t *testing.T) {
- s := stack.New([]string{"fakeNet"}, nil, stack.Options{})
-
- id, _ := channel.New(10, defaultMTU, "")
- if err := s.CreateNIC(1, id); err != nil {
- t.Fatalf("CreateNIC failed: %v", err)
- }
- s.SetRouteTable([]tcpip.Route{})
-
- // If there is no endpoint, it won't work.
- if _, err := s.FindRoute(1, header.IPv4Any, header.IPv4Broadcast, fakeNetNumber, false /* multicastLoop */); err != tcpip.ErrNetworkUnreachable {
- t.Fatalf("got FindRoute(1, %v, %v, %v) = %v, want = %v", header.IPv4Any, header.IPv4Broadcast, fakeNetNumber, err, tcpip.ErrNetworkUnreachable)
- }
-
- if err := s.AddAddress(1, fakeNetNumber, header.IPv4Any); err != nil {
- t.Fatalf("AddAddress(%v, %v) failed: %v", fakeNetNumber, header.IPv4Any, err)
- }
- r, err := s.FindRoute(1, header.IPv4Any, header.IPv4Broadcast, fakeNetNumber, false /* multicastLoop */)
- if err != nil {
- t.Fatalf("FindRoute(1, %v, %v, %v) failed: %v", header.IPv4Any, header.IPv4Broadcast, fakeNetNumber, err)
- }
-
- if r.LocalAddress != header.IPv4Any {
- t.Errorf("Bad local address: got %v, want = %v", r.LocalAddress, header.IPv4Any)
- }
-
- if r.RemoteAddress != header.IPv4Broadcast {
- t.Errorf("Bad remote address: got %v, want = %v", r.RemoteAddress, header.IPv4Broadcast)
- }
-
- // If the NIC doesn't exist, it won't work.
- if _, err := s.FindRoute(2, header.IPv4Any, header.IPv4Broadcast, fakeNetNumber, false /* multicastLoop */); err != tcpip.ErrNetworkUnreachable {
- t.Fatalf("got FindRoute(2, %v, %v, %v) = %v want = %v", header.IPv4Any, header.IPv4Broadcast, fakeNetNumber, err, tcpip.ErrNetworkUnreachable)
- }
-}
-
-func TestMulticastOrIPv6LinkLocalNeedsNoRoute(t *testing.T) {
- for _, tc := range []struct {
- name string
- routeNeeded bool
- address tcpip.Address
- }{
- // IPv4 multicast address range: 224.0.0.0 - 239.255.255.255
- // <=> 0xe0.0x00.0x00.0x00 - 0xef.0xff.0xff.0xff
- {"IPv4 Multicast 1", false, "\xe0\x00\x00\x00"},
- {"IPv4 Multicast 2", false, "\xef\xff\xff\xff"},
- {"IPv4 Unicast 1", true, "\xdf\xff\xff\xff"},
- {"IPv4 Unicast 2", true, "\xf0\x00\x00\x00"},
- {"IPv4 Unicast 3", true, "\x00\x00\x00\x00"},
-
- // IPv6 multicast address is 0xff[8] + flags[4] + scope[4] + groupId[112]
- {"IPv6 Multicast 1", false, "\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"},
- {"IPv6 Multicast 2", false, "\xff\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"},
- {"IPv6 Multicast 3", false, "\xff\x0f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"},
-
- // IPv6 link-local address starts with fe80::/10.
- {"IPv6 Unicast Link-Local 1", false, "\xfe\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"},
- {"IPv6 Unicast Link-Local 2", false, "\xfe\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01"},
- {"IPv6 Unicast Link-Local 3", false, "\xfe\x80\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff"},
- {"IPv6 Unicast Link-Local 4", false, "\xfe\xbf\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"},
- {"IPv6 Unicast Link-Local 5", false, "\xfe\xbf\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"},
-
- // IPv6 addresses that are neither multicast nor link-local.
- {"IPv6 Unicast Not Link-Local 1", true, "\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"},
- {"IPv6 Unicast Not Link-Local 2", true, "\xf0\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"},
- {"IPv6 Unicast Not Link-local 3", true, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"},
- {"IPv6 Unicast Not Link-Local 4", true, "\xfe\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"},
- {"IPv6 Unicast Not Link-Local 5", true, "\xfe\xdf\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"},
- {"IPv6 Unicast Not Link-Local 6", true, "\xfd\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"},
- {"IPv6 Unicast Not Link-Local 7", true, "\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"},
- } {
- t.Run(tc.name, func(t *testing.T) {
- s := stack.New([]string{"fakeNet"}, nil, stack.Options{})
-
- id, _ := channel.New(10, defaultMTU, "")
- if err := s.CreateNIC(1, id); err != nil {
- t.Fatalf("CreateNIC failed: %v", err)
- }
-
- s.SetRouteTable([]tcpip.Route{})
-
- var anyAddr tcpip.Address
- if len(tc.address) == header.IPv4AddressSize {
- anyAddr = header.IPv4Any
- } else {
- anyAddr = header.IPv6Any
- }
-
- want := tcpip.ErrNetworkUnreachable
- if tc.routeNeeded {
- want = tcpip.ErrNoRoute
- }
-
- // If there is no endpoint, it won't work.
- if _, err := s.FindRoute(1, anyAddr, tc.address, fakeNetNumber, false /* multicastLoop */); err != want {
- t.Fatalf("got FindRoute(1, %v, %v, %v) = %v, want = %v", anyAddr, tc.address, fakeNetNumber, err, want)
- }
-
- if err := s.AddAddress(1, fakeNetNumber, anyAddr); err != nil {
- t.Fatalf("AddAddress(%v, %v) failed: %v", fakeNetNumber, anyAddr, err)
- }
-
- if r, err := s.FindRoute(1, anyAddr, tc.address, fakeNetNumber, false /* multicastLoop */); tc.routeNeeded {
- // Route table is empty but we need a route, this should cause an error.
- if err != tcpip.ErrNoRoute {
- t.Fatalf("got FindRoute(1, %v, %v, %v) = %v, want = %v", anyAddr, tc.address, fakeNetNumber, err, tcpip.ErrNoRoute)
- }
- } else {
- if err != nil {
- t.Fatalf("FindRoute(1, %v, %v, %v) failed: %v", anyAddr, tc.address, fakeNetNumber, err)
- }
- if r.LocalAddress != anyAddr {
- t.Errorf("Bad local address: got %v, want = %v", r.LocalAddress, anyAddr)
- }
- if r.RemoteAddress != tc.address {
- t.Errorf("Bad remote address: got %v, want = %v", r.RemoteAddress, tc.address)
- }
- }
- // If the NIC doesn't exist, it won't work.
- if _, err := s.FindRoute(2, anyAddr, tc.address, fakeNetNumber, false /* multicastLoop */); err != want {
- t.Fatalf("got FindRoute(2, %v, %v, %v) = %v want = %v", anyAddr, tc.address, fakeNetNumber, err, want)
- }
- })
- }
-}
-
-// Set the subnet, then check that packet is delivered.
-func TestSubnetAcceptsMatchingPacket(t *testing.T) {
- s := stack.New([]string{"fakeNet"}, nil, stack.Options{})
-
- id, linkEP := channel.New(10, defaultMTU, "")
- if err := s.CreateNIC(1, id); err != nil {
- t.Fatalf("CreateNIC failed: %v", err)
- }
-
- s.SetRouteTable([]tcpip.Route{
- {"\x00", "\x00", "\x00", 1},
- })
-
- fakeNet := s.NetworkProtocolInstance(fakeNetNumber).(*fakeNetworkProtocol)
-
- buf := buffer.NewView(30)
-
- buf[0] = 1
- fakeNet.packetCount[1] = 0
- subnet, err := tcpip.NewSubnet(tcpip.Address("\x00"), tcpip.AddressMask("\xF0"))
- if err != nil {
- t.Fatalf("NewSubnet failed: %v", err)
- }
- if err := s.AddSubnet(1, fakeNetNumber, subnet); err != nil {
- t.Fatalf("AddSubnet failed: %v", err)
- }
-
- linkEP.Inject(fakeNetNumber, buf.ToVectorisedView())
- if fakeNet.packetCount[1] != 1 {
- t.Errorf("packetCount[1] = %d, want %d", fakeNet.packetCount[1], 1)
- }
-}
-
-// Set destination outside the subnet, then check it doesn't get delivered.
-func TestSubnetRejectsNonmatchingPacket(t *testing.T) {
- s := stack.New([]string{"fakeNet"}, nil, stack.Options{})
-
- id, linkEP := channel.New(10, defaultMTU, "")
- if err := s.CreateNIC(1, id); err != nil {
- t.Fatalf("CreateNIC failed: %v", err)
- }
-
- s.SetRouteTable([]tcpip.Route{
- {"\x00", "\x00", "\x00", 1},
- })
-
- fakeNet := s.NetworkProtocolInstance(fakeNetNumber).(*fakeNetworkProtocol)
-
- buf := buffer.NewView(30)
-
- buf[0] = 1
- fakeNet.packetCount[1] = 0
- subnet, err := tcpip.NewSubnet(tcpip.Address("\x10"), tcpip.AddressMask("\xF0"))
- if err != nil {
- t.Fatalf("NewSubnet failed: %v", err)
- }
- if err := s.AddSubnet(1, fakeNetNumber, subnet); err != nil {
- t.Fatalf("AddSubnet failed: %v", err)
- }
- linkEP.Inject(fakeNetNumber, buf.ToVectorisedView())
- if fakeNet.packetCount[1] != 0 {
- t.Errorf("packetCount[1] = %d, want %d", fakeNet.packetCount[1], 0)
- }
-}
-
-func TestNetworkOptions(t *testing.T) {
- s := stack.New([]string{"fakeNet"}, []string{}, stack.Options{})
-
- // Try an unsupported network protocol.
- if err := s.SetNetworkProtocolOption(tcpip.NetworkProtocolNumber(99999), fakeNetGoodOption(false)); err != tcpip.ErrUnknownProtocol {
- t.Fatalf("SetNetworkProtocolOption(fakeNet2, blah, false) = %v, want = tcpip.ErrUnknownProtocol", err)
- }
-
- testCases := []struct {
- option interface{}
- wantErr *tcpip.Error
- verifier func(t *testing.T, p stack.NetworkProtocol)
- }{
- {fakeNetGoodOption(true), nil, func(t *testing.T, p stack.NetworkProtocol) {
- t.Helper()
- fakeNet := p.(*fakeNetworkProtocol)
- if fakeNet.opts.good != true {
- t.Fatalf("fakeNet.opts.good = false, want = true")
- }
- var v fakeNetGoodOption
- if err := s.NetworkProtocolOption(fakeNetNumber, &v); err != nil {
- t.Fatalf("s.NetworkProtocolOption(fakeNetNumber, &v) = %v, want = nil, where v is option %T", v, err)
- }
- if v != true {
- t.Fatalf("s.NetworkProtocolOption(fakeNetNumber, &v) returned v = %v, want = true", v)
- }
- }},
- {fakeNetBadOption(true), tcpip.ErrUnknownProtocolOption, nil},
- {fakeNetInvalidValueOption(1), tcpip.ErrInvalidOptionValue, nil},
- }
- for _, tc := range testCases {
- if got := s.SetNetworkProtocolOption(fakeNetNumber, tc.option); got != tc.wantErr {
- t.Errorf("s.SetNetworkProtocolOption(fakeNet, %v) = %v, want = %v", tc.option, got, tc.wantErr)
- }
- if tc.verifier != nil {
- tc.verifier(t, s.NetworkProtocolInstance(fakeNetNumber))
- }
- }
-}
-
-func TestSubnetAddRemove(t *testing.T) {
- s := stack.New([]string{"fakeNet"}, nil, stack.Options{})
- id, _ := channel.New(10, defaultMTU, "")
- if err := s.CreateNIC(1, id); err != nil {
- t.Fatalf("CreateNIC failed: %v", err)
- }
-
- addr := tcpip.Address("\x01\x01\x01\x01")
- mask := tcpip.AddressMask(strings.Repeat("\xff", len(addr)))
- subnet, err := tcpip.NewSubnet(addr, mask)
- if err != nil {
- t.Fatalf("NewSubnet failed: %v", err)
- }
-
- if contained, err := s.ContainsSubnet(1, subnet); err != nil {
- t.Fatalf("ContainsSubnet failed: %v", err)
- } else if contained {
- t.Fatal("got s.ContainsSubnet(...) = true, want = false")
- }
-
- if err := s.AddSubnet(1, fakeNetNumber, subnet); err != nil {
- t.Fatalf("AddSubnet failed: %v", err)
- }
-
- if contained, err := s.ContainsSubnet(1, subnet); err != nil {
- t.Fatalf("ContainsSubnet failed: %v", err)
- } else if !contained {
- t.Fatal("got s.ContainsSubnet(...) = false, want = true")
- }
-
- if err := s.RemoveSubnet(1, subnet); err != nil {
- t.Fatalf("RemoveSubnet failed: %v", err)
- }
-
- if contained, err := s.ContainsSubnet(1, subnet); err != nil {
- t.Fatalf("ContainsSubnet failed: %v", err)
- } else if contained {
- t.Fatal("got s.ContainsSubnet(...) = true, want = false")
- }
-}
-
-func TestGetMainNICAddressAddPrimaryNonPrimary(t *testing.T) {
- for _, addrLen := range []int{4, 16} {
- t.Run(fmt.Sprintf("addrLen=%d", addrLen), func(t *testing.T) {
- for canBe := 0; canBe < 3; canBe++ {
- t.Run(fmt.Sprintf("canBe=%d", canBe), func(t *testing.T) {
- for never := 0; never < 3; never++ {
- t.Run(fmt.Sprintf("never=%d", never), func(t *testing.T) {
- s := stack.New([]string{"fakeNet"}, nil, stack.Options{})
- id, _ := channel.New(10, defaultMTU, "")
- if err := s.CreateNIC(1, id); err != nil {
- t.Fatalf("CreateNIC failed: %v", err)
- }
- // Insert <canBe> primary and <never> never-primary addresses.
- // Each one will add a network endpoint to the NIC.
- primaryAddrAdded := make(map[tcpip.Address]tcpip.Subnet)
- for i := 0; i < canBe+never; i++ {
- var behavior stack.PrimaryEndpointBehavior
- if i < canBe {
- behavior = stack.CanBePrimaryEndpoint
- } else {
- behavior = stack.NeverPrimaryEndpoint
- }
- // Add an address and in case of a primary one also add a
- // subnet.
- address := tcpip.Address(bytes.Repeat([]byte{byte(i)}, addrLen))
- if err := s.AddAddressWithOptions(1, fakeNetNumber, address, behavior); err != nil {
- t.Fatalf("AddAddressWithOptions failed: %v", err)
- }
- if behavior == stack.CanBePrimaryEndpoint {
- mask := tcpip.AddressMask(strings.Repeat("\xff", len(address)))
- subnet, err := tcpip.NewSubnet(address, mask)
- if err != nil {
- t.Fatalf("NewSubnet failed: %v", err)
- }
- if err := s.AddSubnet(1, fakeNetNumber, subnet); err != nil {
- t.Fatalf("AddSubnet failed: %v", err)
- }
- // Remember the address/subnet.
- primaryAddrAdded[address] = subnet
- }
- }
- // Check that GetMainNICAddress returns an address if at least
- // one primary address was added. In that case make sure the
- // address/subnet matches what we added.
- if len(primaryAddrAdded) == 0 {
- // No primary addresses present, expect an error.
- if _, _, err := s.GetMainNICAddress(1, fakeNetNumber); err != tcpip.ErrNoLinkAddress {
- t.Fatalf("got s.GetMainNICAddress(...) = %v, wanted = %v", err, tcpip.ErrNoLinkAddress)
- }
- } else {
- // At least one primary address was added, expect a valid
- // address and subnet.
- gotAddress, gotSubnet, err := s.GetMainNICAddress(1, fakeNetNumber)
- if err != nil {
- t.Fatalf("GetMainNICAddress failed: %v", err)
- }
- expectedSubnet, ok := primaryAddrAdded[gotAddress]
- if !ok {
- t.Fatalf("GetMainNICAddress: got address = %v, wanted any in {%v}", gotAddress, primaryAddrAdded)
- }
- if gotSubnet != expectedSubnet {
- t.Fatalf("GetMainNICAddress: got subnet = %v, wanted %v", gotSubnet, expectedSubnet)
- }
- }
- })
- }
- })
- }
- })
- }
-}
-
-func TestGetMainNICAddressAddRemove(t *testing.T) {
- s := stack.New([]string{"fakeNet"}, nil, stack.Options{})
- id, _ := channel.New(10, defaultMTU, "")
- if err := s.CreateNIC(1, id); err != nil {
- t.Fatalf("CreateNIC failed: %v", err)
- }
-
- for _, tc := range []struct {
- name string
- address tcpip.Address
- }{
- {"IPv4", "\x01\x01\x01\x01"},
- {"IPv6", "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01"},
- } {
- t.Run(tc.name, func(t *testing.T) {
- address := tc.address
- mask := tcpip.AddressMask(strings.Repeat("\xff", len(address)))
- subnet, err := tcpip.NewSubnet(address, mask)
- if err != nil {
- t.Fatalf("NewSubnet failed: %v", err)
- }
-
- if err := s.AddAddress(1, fakeNetNumber, address); err != nil {
- t.Fatalf("AddAddress failed: %v", err)
- }
-
- if err := s.AddSubnet(1, fakeNetNumber, subnet); err != nil {
- t.Fatalf("AddSubnet failed: %v", err)
- }
-
- // Check that we get the right initial address and subnet.
- if gotAddress, gotSubnet, err := s.GetMainNICAddress(1, fakeNetNumber); err != nil {
- t.Fatalf("GetMainNICAddress failed: %v", err)
- } else if gotAddress != address {
- t.Fatalf("got GetMainNICAddress = (%v, ...), want = (%v, ...)", gotAddress, address)
- } else if gotSubnet != subnet {
- t.Fatalf("got GetMainNICAddress = (..., %v), want = (..., %v)", gotSubnet, subnet)
- }
-
- if err := s.RemoveSubnet(1, subnet); err != nil {
- t.Fatalf("RemoveSubnet failed: %v", err)
- }
-
- if err := s.RemoveAddress(1, address); err != nil {
- t.Fatalf("RemoveAddress failed: %v", err)
- }
-
- // Check that we get an error after removal.
- if _, _, err := s.GetMainNICAddress(1, fakeNetNumber); err != tcpip.ErrNoLinkAddress {
- t.Fatalf("got s.GetMainNICAddress(...) = %v, want = %v", err, tcpip.ErrNoLinkAddress)
- }
- })
- }
-}
-
-func TestNICStats(t *testing.T) {
- s := stack.New([]string{"fakeNet"}, nil, stack.Options{})
- id1, linkEP1 := channel.New(10, defaultMTU, "")
- if err := s.CreateNIC(1, id1); err != nil {
- t.Fatalf("CreateNIC failed: %v", err)
- }
- if err := s.AddAddress(1, fakeNetNumber, "\x01"); err != nil {
- t.Fatalf("AddAddress failed: %v", err)
- }
- // Route all packets for address \x01 to NIC 1.
- s.SetRouteTable([]tcpip.Route{
- {"\x01", "\xff", "\x00", 1},
- })
-
- // Send a packet to address 1.
- buf := buffer.NewView(30)
- linkEP1.Inject(fakeNetNumber, buf.ToVectorisedView())
- if got, want := s.NICInfo()[1].Stats.Rx.Packets.Value(), uint64(1); got != want {
- t.Errorf("got Rx.Packets.Value() = %d, want = %d", got, want)
- }
-
- if got, want := s.NICInfo()[1].Stats.Rx.Bytes.Value(), uint64(len(buf)); got != want {
- t.Errorf("got Rx.Bytes.Value() = %d, want = %d", got, want)
- }
-
- payload := buffer.NewView(10)
- // Write a packet out via the address for NIC 1
- sendTo(t, s, "\x01", payload)
- want := uint64(linkEP1.Drain())
- if got := s.NICInfo()[1].Stats.Tx.Packets.Value(); got != want {
- t.Errorf("got Tx.Packets.Value() = %d, linkEP1.Drain() = %d", got, want)
- }
-
- if got, want := s.NICInfo()[1].Stats.Tx.Bytes.Value(), uint64(len(payload)); got != want {
- t.Errorf("got Tx.Bytes.Value() = %d, want = %d", got, want)
- }
-}
-
-func TestNICForwarding(t *testing.T) {
- // Create a stack with the fake network protocol, two NICs, each with
- // an address.
- s := stack.New([]string{"fakeNet"}, nil, stack.Options{})
- s.SetForwarding(true)
-
- id1, linkEP1 := channel.New(10, defaultMTU, "")
- if err := s.CreateNIC(1, id1); err != nil {
- t.Fatalf("CreateNIC #1 failed: %v", err)
- }
- if err := s.AddAddress(1, fakeNetNumber, "\x01"); err != nil {
- t.Fatalf("AddAddress #1 failed: %v", err)
- }
-
- id2, linkEP2 := channel.New(10, defaultMTU, "")
- if err := s.CreateNIC(2, id2); err != nil {
- t.Fatalf("CreateNIC #2 failed: %v", err)
- }
- if err := s.AddAddress(2, fakeNetNumber, "\x02"); err != nil {
- t.Fatalf("AddAddress #2 failed: %v", err)
- }
-
- // Route all packets to address 3 to NIC 2.
- s.SetRouteTable([]tcpip.Route{
- {"\x03", "\xff", "\x00", 2},
- })
-
- // Send a packet to address 3.
- buf := buffer.NewView(30)
- buf[0] = 3
- linkEP1.Inject(fakeNetNumber, buf.ToVectorisedView())
-
- select {
- case <-linkEP2.C:
- default:
- t.Fatal("Packet not forwarded")
- }
-
- // Test that forwarding increments Tx stats correctly.
- if got, want := s.NICInfo()[2].Stats.Tx.Packets.Value(), uint64(1); got != want {
- t.Errorf("got Tx.Packets.Value() = %d, want = %d", got, want)
- }
-
- if got, want := s.NICInfo()[2].Stats.Tx.Bytes.Value(), uint64(len(buf)); got != want {
- t.Errorf("got Tx.Bytes.Value() = %d, want = %d", got, want)
- }
-}
-
-func init() {
- stack.RegisterNetworkProtocolFactory("fakeNet", func() stack.NetworkProtocol {
- return &fakeNetworkProtocol{}
- })
-}