Add support for a subnet prefix length on interface network addresses

This allows the user code to add a network address with a subnet prefix length.
The prefix length value is stored in the network endpoint and provided back to
the user in the ProtocolAddress type.

PiperOrigin-RevId: 259807693
This commit is contained in:
Chris Kuiper 2019-07-24 13:40:52 -07:00 committed by gVisor bot
parent 7e38d64333
commit 40e682759f
12 changed files with 396 additions and 191 deletions

View File

@ -75,8 +75,8 @@ func (s *Stack) InterfaceAddrs() map[int32][]inet.InterfaceAddr {
addrs = append(addrs, inet.InterfaceAddr{
Family: family,
PrefixLen: uint8(len(a.Address) * 8),
Addr: []byte(a.Address),
PrefixLen: uint8(a.AddressWithPrefix.PrefixLen),
Addr: []byte(a.AddressWithPrefix.Address),
// TODO(b/68878065): Other fields.
})
}

View File

@ -46,7 +46,6 @@ const (
// endpoint implements stack.NetworkEndpoint.
type endpoint struct {
nicid tcpip.NICID
addr tcpip.Address
linkEP stack.LinkEndpoint
linkAddrCache stack.LinkAddressCache
}
@ -73,6 +72,10 @@ func (e *endpoint) ID() *stack.NetworkEndpointID {
return &stack.NetworkEndpointID{ProtocolAddress}
}
func (e *endpoint) PrefixLen() int {
return 0
}
func (e *endpoint) MaxHeaderLength() uint16 {
return e.linkEP.MaxHeaderLength() + header.ARPSize
}
@ -122,19 +125,19 @@ type protocol struct {
func (p *protocol) Number() tcpip.NetworkProtocolNumber { return ProtocolNumber }
func (p *protocol) MinimumPacketSize() int { return header.ARPSize }
func (p *protocol) DefaultPrefixLen() int { return 0 }
func (*protocol) ParseAddresses(v buffer.View) (src, dst tcpip.Address) {
h := header.ARP(v)
return tcpip.Address(h.ProtocolAddressSender()), ProtocolAddress
}
func (p *protocol) NewEndpoint(nicid tcpip.NICID, addr tcpip.Address, linkAddrCache stack.LinkAddressCache, dispatcher stack.TransportDispatcher, sender stack.LinkEndpoint) (stack.NetworkEndpoint, *tcpip.Error) {
if addr != ProtocolAddress {
func (p *protocol) NewEndpoint(nicid tcpip.NICID, addrWithPrefix tcpip.AddressWithPrefix, linkAddrCache stack.LinkAddressCache, dispatcher stack.TransportDispatcher, sender stack.LinkEndpoint) (stack.NetworkEndpoint, *tcpip.Error) {
if addrWithPrefix.Address != ProtocolAddress {
return nil, tcpip.ErrBadLocalAddress
}
return &endpoint{
nicid: nicid,
addr: addr,
linkEP: sender,
linkAddrCache: linkAddrCache,
}, nil

View File

@ -29,16 +29,18 @@ import (
)
const (
localIpv4Addr = "\x0a\x00\x00\x01"
remoteIpv4Addr = "\x0a\x00\x00\x02"
ipv4SubnetAddr = "\x0a\x00\x00\x00"
ipv4SubnetMask = "\xff\xff\xff\x00"
ipv4Gateway = "\x0a\x00\x00\x03"
localIpv6Addr = "\x0a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01"
remoteIpv6Addr = "\x0a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02"
ipv6SubnetAddr = "\x0a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
ipv6SubnetMask = "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00"
ipv6Gateway = "\x0a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03"
localIpv4Addr = "\x0a\x00\x00\x01"
localIpv4PrefixLen = 24
remoteIpv4Addr = "\x0a\x00\x00\x02"
ipv4SubnetAddr = "\x0a\x00\x00\x00"
ipv4SubnetMask = "\xff\xff\xff\x00"
ipv4Gateway = "\x0a\x00\x00\x03"
localIpv6Addr = "\x0a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01"
localIpv6PrefixLen = 120
remoteIpv6Addr = "\x0a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02"
ipv6SubnetAddr = "\x0a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
ipv6SubnetMask = "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00"
ipv6Gateway = "\x0a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03"
)
// testObject implements two interfaces: LinkEndpoint and TransportDispatcher.
@ -197,7 +199,7 @@ func buildIPv6Route(local, remote tcpip.Address) (stack.Route, *tcpip.Error) {
func TestIPv4Send(t *testing.T) {
o := testObject{t: t, v4: true}
proto := ipv4.NewProtocol()
ep, err := proto.NewEndpoint(1, localIpv4Addr, nil, nil, &o)
ep, err := proto.NewEndpoint(1, tcpip.AddressWithPrefix{localIpv4Addr, localIpv4PrefixLen}, nil, nil, &o)
if err != nil {
t.Fatalf("NewEndpoint failed: %v", err)
}
@ -229,7 +231,7 @@ func TestIPv4Send(t *testing.T) {
func TestIPv4Receive(t *testing.T) {
o := testObject{t: t, v4: true}
proto := ipv4.NewProtocol()
ep, err := proto.NewEndpoint(1, localIpv4Addr, nil, &o, nil)
ep, err := proto.NewEndpoint(1, tcpip.AddressWithPrefix{localIpv4Addr, localIpv4PrefixLen}, nil, &o, nil)
if err != nil {
t.Fatalf("NewEndpoint failed: %v", err)
}
@ -295,7 +297,7 @@ func TestIPv4ReceiveControl(t *testing.T) {
t.Run(c.name, func(t *testing.T) {
o := testObject{t: t}
proto := ipv4.NewProtocol()
ep, err := proto.NewEndpoint(1, localIpv4Addr, nil, &o, nil)
ep, err := proto.NewEndpoint(1, tcpip.AddressWithPrefix{localIpv4Addr, localIpv4PrefixLen}, nil, &o, nil)
if err != nil {
t.Fatalf("NewEndpoint failed: %v", err)
}
@ -359,7 +361,7 @@ func TestIPv4ReceiveControl(t *testing.T) {
func TestIPv4FragmentationReceive(t *testing.T) {
o := testObject{t: t, v4: true}
proto := ipv4.NewProtocol()
ep, err := proto.NewEndpoint(1, localIpv4Addr, nil, &o, nil)
ep, err := proto.NewEndpoint(1, tcpip.AddressWithPrefix{localIpv4Addr, localIpv4PrefixLen}, nil, &o, nil)
if err != nil {
t.Fatalf("NewEndpoint failed: %v", err)
}
@ -426,7 +428,7 @@ func TestIPv4FragmentationReceive(t *testing.T) {
func TestIPv6Send(t *testing.T) {
o := testObject{t: t}
proto := ipv6.NewProtocol()
ep, err := proto.NewEndpoint(1, localIpv6Addr, nil, nil, &o)
ep, err := proto.NewEndpoint(1, tcpip.AddressWithPrefix{localIpv6Addr, localIpv6PrefixLen}, nil, nil, &o)
if err != nil {
t.Fatalf("NewEndpoint failed: %v", err)
}
@ -458,7 +460,7 @@ func TestIPv6Send(t *testing.T) {
func TestIPv6Receive(t *testing.T) {
o := testObject{t: t}
proto := ipv6.NewProtocol()
ep, err := proto.NewEndpoint(1, localIpv6Addr, nil, &o, nil)
ep, err := proto.NewEndpoint(1, tcpip.AddressWithPrefix{localIpv6Addr, localIpv6PrefixLen}, nil, &o, nil)
if err != nil {
t.Fatalf("NewEndpoint failed: %v", err)
}
@ -532,7 +534,7 @@ func TestIPv6ReceiveControl(t *testing.T) {
t.Run(c.name, func(t *testing.T) {
o := testObject{t: t}
proto := ipv6.NewProtocol()
ep, err := proto.NewEndpoint(1, localIpv6Addr, nil, &o, nil)
ep, err := proto.NewEndpoint(1, tcpip.AddressWithPrefix{localIpv6Addr, localIpv6PrefixLen}, nil, &o, nil)
if err != nil {
t.Fatalf("NewEndpoint failed: %v", err)
}

View File

@ -49,16 +49,18 @@ const (
type endpoint struct {
nicid tcpip.NICID
id stack.NetworkEndpointID
prefixLen int
linkEP stack.LinkEndpoint
dispatcher stack.TransportDispatcher
fragmentation *fragmentation.Fragmentation
}
// NewEndpoint creates a new ipv4 endpoint.
func (p *protocol) NewEndpoint(nicid tcpip.NICID, addr tcpip.Address, linkAddrCache stack.LinkAddressCache, dispatcher stack.TransportDispatcher, linkEP stack.LinkEndpoint) (stack.NetworkEndpoint, *tcpip.Error) {
func (p *protocol) NewEndpoint(nicid tcpip.NICID, addrWithPrefix tcpip.AddressWithPrefix, linkAddrCache stack.LinkAddressCache, dispatcher stack.TransportDispatcher, linkEP stack.LinkEndpoint) (stack.NetworkEndpoint, *tcpip.Error) {
e := &endpoint{
nicid: nicid,
id: stack.NetworkEndpointID{LocalAddress: addr},
id: stack.NetworkEndpointID{LocalAddress: addrWithPrefix.Address},
prefixLen: addrWithPrefix.PrefixLen,
linkEP: linkEP,
dispatcher: dispatcher,
fragmentation: fragmentation.NewFragmentation(fragmentation.HighFragThreshold, fragmentation.LowFragThreshold, fragmentation.DefaultReassembleTimeout),
@ -93,6 +95,11 @@ func (e *endpoint) ID() *stack.NetworkEndpointID {
return &e.id
}
// PrefixLen returns the ipv4 endpoint subnet prefix length in bits.
func (e *endpoint) PrefixLen() int {
return e.prefixLen
}
// MaxHeaderLength returns the maximum length needed by ipv4 headers (and
// underlying protocols).
func (e *endpoint) MaxHeaderLength() uint16 {
@ -338,6 +345,11 @@ func (p *protocol) MinimumPacketSize() int {
return header.IPv4MinimumSize
}
// DefaultPrefixLen returns the IPv4 default prefix length.
func (p *protocol) DefaultPrefixLen() int {
return header.IPv4AddressSize * 8
}
// ParseAddresses implements NetworkProtocol.ParseAddresses.
func (*protocol) ParseAddresses(v buffer.View) (src, dst tcpip.Address) {
h := header.IPv4(v)

View File

@ -99,7 +99,11 @@ func TestICMPCounts(t *testing.T) {
}},
)
ep, err := s.NetworkProtocolInstance(ProtocolNumber).NewEndpoint(0, lladdr1, &stubLinkAddressCache{}, &stubDispatcher{}, nil)
netProto := s.NetworkProtocolInstance(ProtocolNumber)
if netProto == nil {
t.Fatalf("cannot find protocol instance for network protocol %d", ProtocolNumber)
}
ep, err := netProto.NewEndpoint(0, tcpip.AddressWithPrefix{lladdr1, netProto.DefaultPrefixLen()}, &stubLinkAddressCache{}, &stubDispatcher{}, nil)
if err != nil {
t.Fatalf("NewEndpoint(_) = _, %s, want = _, nil", err)
}

View File

@ -46,6 +46,7 @@ const (
type endpoint struct {
nicid tcpip.NICID
id stack.NetworkEndpointID
prefixLen int
linkEP stack.LinkEndpoint
linkAddrCache stack.LinkAddressCache
dispatcher stack.TransportDispatcher
@ -72,6 +73,11 @@ func (e *endpoint) ID() *stack.NetworkEndpointID {
return &e.id
}
// PrefixLen returns the ipv6 endpoint subnet prefix length in bits.
func (e *endpoint) PrefixLen() int {
return e.prefixLen
}
// Capabilities implements stack.NetworkEndpoint.Capabilities.
func (e *endpoint) Capabilities() stack.LinkEndpointCapabilities {
return e.linkEP.Capabilities()
@ -172,6 +178,11 @@ func (p *protocol) MinimumPacketSize() int {
return header.IPv6MinimumSize
}
// DefaultPrefixLen returns the IPv6 default prefix length.
func (p *protocol) DefaultPrefixLen() int {
return header.IPv6AddressSize * 8
}
// ParseAddresses implements NetworkProtocol.ParseAddresses.
func (*protocol) ParseAddresses(v buffer.View) (src, dst tcpip.Address) {
h := header.IPv6(v)
@ -179,10 +190,11 @@ func (*protocol) ParseAddresses(v buffer.View) (src, dst tcpip.Address) {
}
// NewEndpoint creates a new ipv6 endpoint.
func (p *protocol) NewEndpoint(nicid tcpip.NICID, addr tcpip.Address, linkAddrCache stack.LinkAddressCache, dispatcher stack.TransportDispatcher, linkEP stack.LinkEndpoint) (stack.NetworkEndpoint, *tcpip.Error) {
func (p *protocol) NewEndpoint(nicid tcpip.NICID, addrWithPrefix tcpip.AddressWithPrefix, linkAddrCache stack.LinkAddressCache, dispatcher stack.TransportDispatcher, linkEP stack.LinkEndpoint) (stack.NetworkEndpoint, *tcpip.Error) {
return &endpoint{
nicid: nicid,
id: stack.NetworkEndpointID{LocalAddress: addr},
id: stack.NetworkEndpointID{LocalAddress: addrWithPrefix.Address},
prefixLen: addrWithPrefix.PrefixLen,
linkEP: linkEP,
linkAddrCache: linkAddrCache,
dispatcher: dispatcher,

View File

@ -129,7 +129,7 @@ func (n *NIC) setSpoofing(enable bool) {
n.mu.Unlock()
}
func (n *NIC) getMainNICAddress(protocol tcpip.NetworkProtocolNumber) (tcpip.Address, tcpip.Subnet, *tcpip.Error) {
func (n *NIC) getMainNICAddress(protocol tcpip.NetworkProtocolNumber) (tcpip.AddressWithPrefix, *tcpip.Error) {
n.mu.RLock()
defer n.mu.RUnlock()
@ -148,21 +148,16 @@ func (n *NIC) getMainNICAddress(protocol tcpip.NetworkProtocolNumber) (tcpip.Add
}
if r == nil {
return "", tcpip.Subnet{}, tcpip.ErrNoLinkAddress
return tcpip.AddressWithPrefix{}, tcpip.ErrNoLinkAddress
}
address := r.ep.ID().LocalAddress
addressWithPrefix := tcpip.AddressWithPrefix{
Address: r.ep.ID().LocalAddress,
PrefixLen: r.ep.PrefixLen(),
}
r.decRef()
// Find the least-constrained matching subnet for the address, if one
// exists, and return it.
var subnet tcpip.Subnet
for _, s := range n.subnets {
if s.Contains(address) && !subnet.Contains(s.ID()) {
subnet = s
}
}
return address, subnet, nil
return addressWithPrefix, nil
}
// primaryEndpoint returns the primary endpoint of n for the given network
@ -213,23 +208,26 @@ func (n *NIC) findEndpoint(protocol tcpip.NetworkProtocolNumber, address tcpip.A
n.mu.Lock()
ref = n.endpoints[id]
if ref == nil || !ref.tryIncRef() {
ref, _ = n.addAddressLocked(protocol, address, peb, true)
if ref != nil {
ref.holdsInsertRef = false
if netProto, ok := n.stack.networkProtocols[protocol]; ok {
addrWithPrefix := tcpip.AddressWithPrefix{address, netProto.DefaultPrefixLen()}
ref, _ = n.addAddressLocked(protocol, addrWithPrefix, peb, true)
if ref != nil {
ref.holdsInsertRef = false
}
}
}
n.mu.Unlock()
return ref
}
func (n *NIC) addAddressLocked(protocol tcpip.NetworkProtocolNumber, addr tcpip.Address, peb PrimaryEndpointBehavior, replace bool) (*referencedNetworkEndpoint, *tcpip.Error) {
func (n *NIC) addAddressLocked(protocol tcpip.NetworkProtocolNumber, addrWithPrefix tcpip.AddressWithPrefix, peb PrimaryEndpointBehavior, replace bool) (*referencedNetworkEndpoint, *tcpip.Error) {
netProto, ok := n.stack.networkProtocols[protocol]
if !ok {
return nil, tcpip.ErrUnknownProtocol
}
// Create the new network endpoint.
ep, err := netProto.NewEndpoint(n.id, addr, n.stack, n, n.linkEP)
ep, err := netProto.NewEndpoint(n.id, addrWithPrefix, n.stack, n, n.linkEP)
if err != nil {
return nil, err
}
@ -278,16 +276,10 @@ func (n *NIC) addAddressLocked(protocol tcpip.NetworkProtocolNumber, addr tcpip.
// AddAddress adds a new address to n, so that it starts accepting packets
// targeted at the given address (and network protocol).
func (n *NIC) AddAddress(protocol tcpip.NetworkProtocolNumber, addr tcpip.Address) *tcpip.Error {
return n.AddAddressWithOptions(protocol, addr, CanBePrimaryEndpoint)
}
// AddAddressWithOptions is the same as AddAddress, but allows you to specify
// whether the new endpoint can be primary or not.
func (n *NIC) AddAddressWithOptions(protocol tcpip.NetworkProtocolNumber, addr tcpip.Address, peb PrimaryEndpointBehavior) *tcpip.Error {
func (n *NIC) AddAddress(protocol tcpip.NetworkProtocolNumber, addrWithPrefix tcpip.AddressWithPrefix, peb PrimaryEndpointBehavior) *tcpip.Error {
// Add the endpoint.
n.mu.Lock()
_, err := n.addAddressLocked(protocol, addr, peb, false)
_, err := n.addAddressLocked(protocol, addrWithPrefix, peb, false)
n.mu.Unlock()
return err
@ -298,10 +290,13 @@ func (n *NIC) Addresses() []tcpip.ProtocolAddress {
n.mu.RLock()
defer n.mu.RUnlock()
addrs := make([]tcpip.ProtocolAddress, 0, len(n.endpoints))
for nid, ep := range n.endpoints {
for nid, ref := range n.endpoints {
addrs = append(addrs, tcpip.ProtocolAddress{
Protocol: ep.protocol,
Address: nid.LocalAddress,
Protocol: ref.protocol,
AddressWithPrefix: tcpip.AddressWithPrefix{
Address: nid.LocalAddress,
PrefixLen: ref.ep.PrefixLen(),
},
})
}
return addrs
@ -415,7 +410,12 @@ func (n *NIC) joinGroup(protocol tcpip.NetworkProtocolNumber, addr tcpip.Address
id := NetworkEndpointID{addr}
joins := n.mcastJoins[id]
if joins == 0 {
if _, err := n.addAddressLocked(protocol, addr, NeverPrimaryEndpoint, false); err != nil {
netProto, ok := n.stack.networkProtocols[protocol]
if !ok {
return tcpip.ErrUnknownProtocol
}
addrWithPrefix := tcpip.AddressWithPrefix{addr, netProto.DefaultPrefixLen()}
if _, err := n.addAddressLocked(protocol, addrWithPrefix, NeverPrimaryEndpoint, false); err != nil {
return err
}
}
@ -572,7 +572,13 @@ func (n *NIC) getRef(protocol tcpip.NetworkProtocolNumber, dst tcpip.Address) *r
n.mu.Unlock()
return ref
}
ref, err := n.addAddressLocked(protocol, dst, CanBePrimaryEndpoint, true)
netProto, ok := n.stack.networkProtocols[protocol]
if !ok {
n.mu.Unlock()
return nil
}
addrWithPrefix := tcpip.AddressWithPrefix{dst, netProto.DefaultPrefixLen()}
ref, err := n.addAddressLocked(protocol, addrWithPrefix, CanBePrimaryEndpoint, true)
n.mu.Unlock()
if err == nil {
ref.holdsInsertRef = false

View File

@ -181,6 +181,9 @@ type NetworkEndpoint interface {
// ID returns the network protocol endpoint ID.
ID() *NetworkEndpointID
// PrefixLen returns the network endpoint's subnet prefix length in bits.
PrefixLen() int
// NICID returns the id of the NIC this endpoint belongs to.
NICID() tcpip.NICID
@ -203,12 +206,15 @@ type NetworkProtocol interface {
// than this targeted at this protocol.
MinimumPacketSize() int
// DefaultPrefixLen returns the protocol's default prefix length.
DefaultPrefixLen() int
// ParsePorts returns the source and destination addresses stored in a
// packet of this protocol.
ParseAddresses(v buffer.View) (src, dst tcpip.Address)
// NewEndpoint creates a new endpoint of this protocol.
NewEndpoint(nicid tcpip.NICID, addr tcpip.Address, linkAddrCache LinkAddressCache, dispatcher TransportDispatcher, sender LinkEndpoint) (NetworkEndpoint, *tcpip.Error)
NewEndpoint(nicid tcpip.NICID, addrWithPrefix tcpip.AddressWithPrefix, linkAddrCache LinkAddressCache, dispatcher TransportDispatcher, sender LinkEndpoint) (NetworkEndpoint, *tcpip.Error)
// SetOption allows enabling/disabling protocol specific features.
// SetOption returns an error if the option is not supported or the

View File

@ -751,9 +751,26 @@ func (s *Stack) AddAddress(id tcpip.NICID, protocol tcpip.NetworkProtocolNumber,
return s.AddAddressWithOptions(id, protocol, addr, CanBePrimaryEndpoint)
}
// AddAddressWithPrefix adds a new network-layer address/prefixLen to the
// specified NIC.
func (s *Stack) AddAddressWithPrefix(id tcpip.NICID, protocol tcpip.NetworkProtocolNumber, addrWithPrefix tcpip.AddressWithPrefix) *tcpip.Error {
return s.AddAddressWithPrefixAndOptions(id, protocol, addrWithPrefix, CanBePrimaryEndpoint)
}
// AddAddressWithOptions is the same as AddAddress, but allows you to specify
// whether the new endpoint can be primary or not.
func (s *Stack) AddAddressWithOptions(id tcpip.NICID, protocol tcpip.NetworkProtocolNumber, addr tcpip.Address, peb PrimaryEndpointBehavior) *tcpip.Error {
netProto, ok := s.networkProtocols[protocol]
if !ok {
return tcpip.ErrUnknownProtocol
}
addrWithPrefix := tcpip.AddressWithPrefix{addr, netProto.DefaultPrefixLen()}
return s.AddAddressWithPrefixAndOptions(id, protocol, addrWithPrefix, peb)
}
// AddAddressWithPrefixAndOptions is the same as AddAddressWithPrefixLen,
// but allows you to specify whether the new endpoint can be primary or not.
func (s *Stack) AddAddressWithPrefixAndOptions(id tcpip.NICID, protocol tcpip.NetworkProtocolNumber, addrWithPrefix tcpip.AddressWithPrefix, peb PrimaryEndpointBehavior) *tcpip.Error {
s.mu.RLock()
defer s.mu.RUnlock()
@ -762,7 +779,7 @@ func (s *Stack) AddAddressWithOptions(id tcpip.NICID, protocol tcpip.NetworkProt
return tcpip.ErrUnknownNICID
}
return nic.AddAddressWithOptions(protocol, addr, peb)
return nic.AddAddress(protocol, addrWithPrefix, peb)
}
// AddSubnet adds a subnet range to the specified NIC.
@ -821,7 +838,7 @@ func (s *Stack) RemoveAddress(id tcpip.NICID, addr tcpip.Address) *tcpip.Error {
// contains it) for the given NIC and protocol. Returns an arbitrary endpoint's
// address if no primary addresses exist. Returns an error if the NIC doesn't
// exist or has no endpoints.
func (s *Stack) GetMainNICAddress(id tcpip.NICID, protocol tcpip.NetworkProtocolNumber) (tcpip.Address, tcpip.Subnet, *tcpip.Error) {
func (s *Stack) GetMainNICAddress(id tcpip.NICID, protocol tcpip.NetworkProtocolNumber) (tcpip.AddressWithPrefix, *tcpip.Error) {
s.mu.RLock()
defer s.mu.RUnlock()
@ -829,7 +846,7 @@ func (s *Stack) GetMainNICAddress(id tcpip.NICID, protocol tcpip.NetworkProtocol
return nic.getMainNICAddress(protocol)
}
return "", tcpip.Subnet{}, tcpip.ErrUnknownNICID
return tcpip.AddressWithPrefix{}, tcpip.ErrUnknownNICID
}
func (s *Stack) getRefEP(nic *NIC, localAddr tcpip.Address, netProto tcpip.NetworkProtocolNumber) (ref *referencedNetworkEndpoint) {

View File

@ -21,6 +21,7 @@ import (
"bytes"
"fmt"
"math"
"sort"
"strings"
"testing"
@ -32,8 +33,9 @@ import (
)
const (
fakeNetNumber tcpip.NetworkProtocolNumber = math.MaxUint32
fakeNetHeaderLen = 12
fakeNetNumber tcpip.NetworkProtocolNumber = math.MaxUint32
fakeNetHeaderLen = 12
fakeDefaultPrefixLen = 8
// fakeControlProtocol is used for control packets that represent
// destination port unreachable.
@ -55,6 +57,7 @@ const (
type fakeNetworkEndpoint struct {
nicid tcpip.NICID
id stack.NetworkEndpointID
prefixLen int
proto *fakeNetworkProtocol
dispatcher stack.TransportDispatcher
linkEP stack.LinkEndpoint
@ -68,6 +71,10 @@ func (f *fakeNetworkEndpoint) NICID() tcpip.NICID {
return f.nicid
}
func (f *fakeNetworkEndpoint) PrefixLen() int {
return f.prefixLen
}
func (*fakeNetworkEndpoint) DefaultTTL() uint8 {
return 123
}
@ -170,14 +177,19 @@ func (f *fakeNetworkProtocol) MinimumPacketSize() int {
return fakeNetHeaderLen
}
func (f *fakeNetworkProtocol) DefaultPrefixLen() int {
return fakeDefaultPrefixLen
}
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) {
func (f *fakeNetworkProtocol) NewEndpoint(nicid tcpip.NICID, addrWithPrefix tcpip.AddressWithPrefix, linkAddrCache stack.LinkAddressCache, dispatcher stack.TransportDispatcher, linkEP stack.LinkEndpoint) (stack.NetworkEndpoint, *tcpip.Error) {
return &fakeNetworkEndpoint{
nicid: nicid,
id: stack.NetworkEndpointID{addr},
id: stack.NetworkEndpointID{addrWithPrefix.Address},
prefixLen: addrWithPrefix.PrefixLen,
proto: f,
dispatcher: dispatcher,
linkEP: linkEP,
@ -212,15 +224,15 @@ func TestNetworkReceive(t *testing.T) {
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)
t.Fatal("CreateNIC failed:", err)
}
if err := s.AddAddress(1, fakeNetNumber, "\x01"); err != nil {
t.Fatalf("AddAddress failed: %v", err)
t.Fatal("AddAddress failed:", err)
}
if err := s.AddAddress(1, fakeNetNumber, "\x02"); err != nil {
t.Fatalf("AddAddress failed: %v", err)
t.Fatal("AddAddress failed:", err)
}
fakeNet := s.NetworkProtocolInstance(fakeNetNumber).(*fakeNetworkProtocol)
@ -280,13 +292,13 @@ func TestNetworkReceive(t *testing.T) {
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)
t.Fatal("FindRoute failed:", 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)
t.Error("WritePacket failed:", err)
}
}
@ -297,13 +309,13 @@ func TestNetworkSend(t *testing.T) {
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)
t.Fatal("NewNIC failed:", err)
}
s.SetRouteTable([]tcpip.Route{{"\x00", "\x00", "\x00", 1}})
if err := s.AddAddress(1, fakeNetNumber, "\x01"); err != nil {
t.Fatalf("AddAddress failed: %v", err)
t.Fatal("AddAddress failed:", err)
}
// Make sure that the link-layer endpoint received the outbound packet.
@ -321,28 +333,28 @@ func TestNetworkSendMultiRoute(t *testing.T) {
id1, linkEP1 := channel.New(10, defaultMTU, "")
if err := s.CreateNIC(1, id1); err != nil {
t.Fatalf("CreateNIC failed: %v", err)
t.Fatal("CreateNIC failed:", err)
}
if err := s.AddAddress(1, fakeNetNumber, "\x01"); err != nil {
t.Fatalf("AddAddress failed: %v", err)
t.Fatal("AddAddress failed:", err)
}
if err := s.AddAddress(1, fakeNetNumber, "\x03"); err != nil {
t.Fatalf("AddAddress failed: %v", err)
t.Fatal("AddAddress failed:", err)
}
id2, linkEP2 := channel.New(10, defaultMTU, "")
if err := s.CreateNIC(2, id2); err != nil {
t.Fatalf("CreateNIC failed: %v", err)
t.Fatal("CreateNIC failed:", err)
}
if err := s.AddAddress(2, fakeNetNumber, "\x02"); err != nil {
t.Fatalf("AddAddress failed: %v", err)
t.Fatal("AddAddress failed:", err)
}
if err := s.AddAddress(2, fakeNetNumber, "\x04"); err != nil {
t.Fatalf("AddAddress failed: %v", err)
t.Fatal("AddAddress failed:", err)
}
// Set a route table that sends all packets with odd destination
@ -371,7 +383,7 @@ func TestNetworkSendMultiRoute(t *testing.T) {
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)
t.Fatal("FindRoute failed:", err)
}
defer r.Release()
@ -388,7 +400,7 @@ func testRoute(t *testing.T, s *stack.Stack, nic tcpip.NICID, srcAddr, dstAddr,
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)
t.Fatalf("FindRoute returned unexpected error, got = %v, want = %s", err, tcpip.ErrNoRoute)
}
}
@ -400,28 +412,28 @@ func TestRoutes(t *testing.T) {
id1, _ := channel.New(10, defaultMTU, "")
if err := s.CreateNIC(1, id1); err != nil {
t.Fatalf("CreateNIC failed: %v", err)
t.Fatal("CreateNIC failed:", err)
}
if err := s.AddAddress(1, fakeNetNumber, "\x01"); err != nil {
t.Fatalf("AddAddress failed: %v", err)
t.Fatal("AddAddress failed:", err)
}
if err := s.AddAddress(1, fakeNetNumber, "\x03"); err != nil {
t.Fatalf("AddAddress failed: %v", err)
t.Fatal("AddAddress failed:", err)
}
id2, _ := channel.New(10, defaultMTU, "")
if err := s.CreateNIC(2, id2); err != nil {
t.Fatalf("CreateNIC failed: %v", err)
t.Fatal("CreateNIC failed:", err)
}
if err := s.AddAddress(2, fakeNetNumber, "\x02"); err != nil {
t.Fatalf("AddAddress failed: %v", err)
t.Fatal("AddAddress failed:", err)
}
if err := s.AddAddress(2, fakeNetNumber, "\x04"); err != nil {
t.Fatalf("AddAddress failed: %v", err)
t.Fatal("AddAddress failed:", err)
}
// Set a route table that sends all packets with odd destination
@ -464,11 +476,11 @@ func TestAddressRemoval(t *testing.T) {
id, linkEP := channel.New(10, defaultMTU, "")
if err := s.CreateNIC(1, id); err != nil {
t.Fatalf("CreateNIC failed: %v", err)
t.Fatal("CreateNIC failed:", err)
}
if err := s.AddAddress(1, fakeNetNumber, "\x01"); err != nil {
t.Fatalf("AddAddress failed: %v", err)
t.Fatal("AddAddress failed:", err)
}
fakeNet := s.NetworkProtocolInstance(fakeNetNumber).(*fakeNetworkProtocol)
@ -486,7 +498,7 @@ func TestAddressRemoval(t *testing.T) {
// 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)
t.Fatal("RemoveAddress failed:", err)
}
linkEP.Inject(fakeNetNumber, buf.ToVectorisedView())
@ -496,7 +508,7 @@ func TestAddressRemoval(t *testing.T) {
// Check that removing the same address fails.
if err := s.RemoveAddress(1, "\x01"); err != tcpip.ErrBadLocalAddress {
t.Fatalf("RemoveAddress failed: %v", err)
t.Fatalf("RemoveAddress returned unexpected error, got = %v, want = %s", err, tcpip.ErrBadLocalAddress)
}
}
@ -505,11 +517,11 @@ func TestDelayedRemovalDueToRoute(t *testing.T) {
id, linkEP := channel.New(10, defaultMTU, "")
if err := s.CreateNIC(1, id); err != nil {
t.Fatalf("CreateNIC failed: %v", err)
t.Fatal("CreateNIC failed:", err)
}
if err := s.AddAddress(1, fakeNetNumber, "\x01"); err != nil {
t.Fatalf("AddAddress failed: %v", err)
t.Fatal("AddAddress failed:", err)
}
s.SetRouteTable([]tcpip.Route{
@ -531,7 +543,7 @@ func TestDelayedRemovalDueToRoute(t *testing.T) {
// 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)
t.Fatal("FindRoute failed:", err)
}
linkEP.Inject(fakeNetNumber, buf.ToVectorisedView())
@ -542,7 +554,7 @@ func TestDelayedRemovalDueToRoute(t *testing.T) {
// 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)
t.Fatal("RemoveAddress failed:", err)
}
linkEP.Inject(fakeNetNumber, buf.ToVectorisedView())
@ -552,7 +564,7 @@ func TestDelayedRemovalDueToRoute(t *testing.T) {
// Check that removing the same address fails.
if err := s.RemoveAddress(1, "\x01"); err != tcpip.ErrBadLocalAddress {
t.Fatalf("RemoveAddress failed: %v", err)
t.Fatalf("RemoveAddress returned unexpected error, got = %v, want = %s", err, tcpip.ErrBadLocalAddress)
}
// Release the route, then check that packet is not deliverable anymore.
@ -568,7 +580,7 @@ func TestPromiscuousMode(t *testing.T) {
id, linkEP := channel.New(10, defaultMTU, "")
if err := s.CreateNIC(1, id); err != nil {
t.Fatalf("CreateNIC failed: %v", err)
t.Fatal("CreateNIC failed:", err)
}
s.SetRouteTable([]tcpip.Route{
@ -590,7 +602,7 @@ func TestPromiscuousMode(t *testing.T) {
// Set promiscuous mode, then check that packet is delivered.
if err := s.SetPromiscuousMode(1, true); err != nil {
t.Fatalf("SetPromiscuousMode failed: %v", err)
t.Fatal("SetPromiscuousMode failed:", err)
}
linkEP.Inject(fakeNetNumber, buf.ToVectorisedView())
@ -601,13 +613,13 @@ func TestPromiscuousMode(t *testing.T) {
// 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)
t.Fatalf("FindRoute returned unexpected error: got = %v, want = %s", err, tcpip.ErrNoRoute)
}
// 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)
t.Fatal("SetPromiscuousMode failed:", err)
}
linkEP.Inject(fakeNetNumber, buf.ToVectorisedView())
@ -624,11 +636,11 @@ func TestAddressSpoofing(t *testing.T) {
id, _ := channel.New(10, defaultMTU, "")
if err := s.CreateNIC(1, id); err != nil {
t.Fatalf("CreateNIC failed: %v", err)
t.Fatal("CreateNIC failed:", err)
}
if err := s.AddAddress(1, fakeNetNumber, dstAddr); err != nil {
t.Fatalf("AddAddress failed: %v", err)
t.Fatal("AddAddress failed:", err)
}
s.SetRouteTable([]tcpip.Route{
@ -645,11 +657,11 @@ func TestAddressSpoofing(t *testing.T) {
// 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)
t.Fatal("SetSpoofing failed:", err)
}
r, err = s.FindRoute(0, srcAddr, dstAddr, fakeNetNumber, false /* multicastLoop */)
if err != nil {
t.Fatalf("FindRoute failed: %v", err)
t.Fatal("FindRoute failed:", err)
}
if r.LocalAddress != srcAddr {
t.Errorf("Route has wrong local address: got %v, wanted %v", r.LocalAddress, srcAddr)
@ -664,17 +676,17 @@ func TestBroadcastNeedsNoRoute(t *testing.T) {
id, _ := channel.New(10, defaultMTU, "")
if err := s.CreateNIC(1, id); err != nil {
t.Fatalf("CreateNIC failed: %v", err)
t.Fatal("CreateNIC failed:", 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)
t.Fatalf("got FindRoute(1, %v, %v, %v) = %v, want = %s", 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)
t.Fatalf("AddAddress(%v, %v) failed: %s", fakeNetNumber, header.IPv4Any, err)
}
r, err := s.FindRoute(1, header.IPv4Any, header.IPv4Broadcast, fakeNetNumber, false /* multicastLoop */)
if err != nil {
@ -735,7 +747,7 @@ func TestMulticastOrIPv6LinkLocalNeedsNoRoute(t *testing.T) {
id, _ := channel.New(10, defaultMTU, "")
if err := s.CreateNIC(1, id); err != nil {
t.Fatalf("CreateNIC failed: %v", err)
t.Fatal("CreateNIC failed:", err)
}
s.SetRouteTable([]tcpip.Route{})
@ -791,7 +803,7 @@ func TestSubnetAcceptsMatchingPacket(t *testing.T) {
id, linkEP := channel.New(10, defaultMTU, "")
if err := s.CreateNIC(1, id); err != nil {
t.Fatalf("CreateNIC failed: %v", err)
t.Fatal("CreateNIC failed:", err)
}
s.SetRouteTable([]tcpip.Route{
@ -806,10 +818,10 @@ func TestSubnetAcceptsMatchingPacket(t *testing.T) {
fakeNet.packetCount[1] = 0
subnet, err := tcpip.NewSubnet(tcpip.Address("\x00"), tcpip.AddressMask("\xF0"))
if err != nil {
t.Fatalf("NewSubnet failed: %v", err)
t.Fatal("NewSubnet failed:", err)
}
if err := s.AddSubnet(1, fakeNetNumber, subnet); err != nil {
t.Fatalf("AddSubnet failed: %v", err)
t.Fatal("AddSubnet failed:", err)
}
linkEP.Inject(fakeNetNumber, buf.ToVectorisedView())
@ -824,7 +836,7 @@ func TestSubnetRejectsNonmatchingPacket(t *testing.T) {
id, linkEP := channel.New(10, defaultMTU, "")
if err := s.CreateNIC(1, id); err != nil {
t.Fatalf("CreateNIC failed: %v", err)
t.Fatal("CreateNIC failed:", err)
}
s.SetRouteTable([]tcpip.Route{
@ -839,10 +851,10 @@ func TestSubnetRejectsNonmatchingPacket(t *testing.T) {
fakeNet.packetCount[1] = 0
subnet, err := tcpip.NewSubnet(tcpip.Address("\x10"), tcpip.AddressMask("\xF0"))
if err != nil {
t.Fatalf("NewSubnet failed: %v", err)
t.Fatal("NewSubnet failed:", err)
}
if err := s.AddSubnet(1, fakeNetNumber, subnet); err != nil {
t.Fatalf("AddSubnet failed: %v", err)
t.Fatal("AddSubnet failed:", err)
}
linkEP.Inject(fakeNetNumber, buf.ToVectorisedView())
if fakeNet.packetCount[1] != 0 {
@ -894,38 +906,38 @@ 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)
t.Fatal("CreateNIC failed:", 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)
t.Fatal("NewSubnet failed:", err)
}
if contained, err := s.ContainsSubnet(1, subnet); err != nil {
t.Fatalf("ContainsSubnet failed: %v", err)
t.Fatal("ContainsSubnet failed:", 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)
t.Fatal("AddSubnet failed:", err)
}
if contained, err := s.ContainsSubnet(1, subnet); err != nil {
t.Fatalf("ContainsSubnet failed: %v", err)
t.Fatal("ContainsSubnet failed:", 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)
t.Fatal("RemoveSubnet failed:", err)
}
if contained, err := s.ContainsSubnet(1, subnet); err != nil {
t.Fatalf("ContainsSubnet failed: %v", err)
t.Fatal("ContainsSubnet failed:", err)
} else if contained {
t.Fatal("got s.ContainsSubnet(...) = true, want = false")
}
@ -941,11 +953,11 @@ func TestGetMainNICAddressAddPrimaryNonPrimary(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)
t.Fatal("CreateNIC failed:", 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)
primaryAddrAdded := make(map[tcpip.AddressWithPrefix]struct{})
for i := 0; i < canBe+never; i++ {
var behavior stack.PrimaryEndpointBehavior
if i < canBe {
@ -953,46 +965,39 @@ func TestGetMainNICAddressAddPrimaryNonPrimary(t *testing.T) {
} else {
behavior = stack.NeverPrimaryEndpoint
}
// Add an address and in case of a primary one also add a
// subnet.
// Add an address and in case of a primary one include a
// prefixLen.
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)
addressWithPrefix := tcpip.AddressWithPrefix{address, addrLen * 8}
if err := s.AddAddressWithPrefixAndOptions(1, fakeNetNumber, addressWithPrefix, behavior); err != nil {
t.Fatal("AddAddressWithPrefixAndOptions failed:", err)
}
if err := s.AddSubnet(1, fakeNetNumber, subnet); err != nil {
t.Fatalf("AddSubnet failed: %v", err)
// Remember the address/prefix.
primaryAddrAdded[addressWithPrefix] = struct{}{}
} else {
if err := s.AddAddressWithOptions(1, fakeNetNumber, address, behavior); err != nil {
t.Fatal("AddAddressWithOptions failed:", 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.
// address/prefixLen 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)
if _, err := s.GetMainNICAddress(1, fakeNetNumber); err != tcpip.ErrNoLinkAddress {
t.Fatalf("got s.GetMainNICAddress(...) = %v, wanted = %s", err, tcpip.ErrNoLinkAddress)
}
} else {
// At least one primary address was added, expect a valid
// address and subnet.
gotAddress, gotSubnet, err := s.GetMainNICAddress(1, fakeNetNumber)
// address and prefixLen.
gotAddressWithPefix, err := s.GetMainNICAddress(1, fakeNetNumber)
if err != nil {
t.Fatalf("GetMainNICAddress failed: %v", err)
t.Fatal("GetMainNICAddress failed:", 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)
if _, ok := primaryAddrAdded[gotAddressWithPefix]; !ok {
t.Fatalf("GetMainNICAddress: got addressWithPrefix = %v, wanted any in {%v}", gotAddressWithPefix, primaryAddrAdded)
}
}
})
@ -1007,65 +1012,194 @@ 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)
t.Fatal("CreateNIC failed:", err)
}
for _, tc := range []struct {
name string
address tcpip.Address
name string
address tcpip.Address
prefixLen int
}{
{"IPv4", "\x01\x01\x01\x01"},
{"IPv6", "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01"},
{"IPv4", "\x01\x01\x01\x01", 24},
{"IPv6", "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01", 116},
} {
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)
addressWithPrefix := tcpip.AddressWithPrefix{tc.address, tc.prefixLen}
if err := s.AddAddressWithPrefix(1, fakeNetNumber, addressWithPrefix); err != nil {
t.Fatal("AddAddressWithPrefix failed:", err)
}
if err := s.AddAddress(1, fakeNetNumber, address); err != nil {
t.Fatalf("AddAddress failed: %v", err)
// Check that we get the right initial address and prefix length.
if gotAddressWithPrefix, err := s.GetMainNICAddress(1, fakeNetNumber); err != nil {
t.Fatal("GetMainNICAddress failed:", err)
} else if gotAddressWithPrefix != addressWithPrefix {
t.Fatalf("got GetMainNICAddress = %+v, want = %+v", gotAddressWithPrefix, addressWithPrefix)
}
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)
if err := s.RemoveAddress(1, addressWithPrefix.Address); err != nil {
t.Fatal("RemoveAddress failed:", 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)
if _, err := s.GetMainNICAddress(1, fakeNetNumber); err != tcpip.ErrNoLinkAddress {
t.Fatalf("got s.GetMainNICAddress(...) = %v, want = %s", err, tcpip.ErrNoLinkAddress)
}
})
}
}
// Simple network address generator. Good for 255 addresses.
type addressGenerator struct{ cnt byte }
func (g *addressGenerator) next(addrLen int) tcpip.Address {
g.cnt++
return tcpip.Address(bytes.Repeat([]byte{g.cnt}, addrLen))
}
func verifyAddresses(t *testing.T, expectedAddresses, gotAddresses []tcpip.ProtocolAddress) {
if len(gotAddresses) != len(expectedAddresses) {
t.Fatalf("got len(addresses) = %d, wanted = %d", len(gotAddresses), len(expectedAddresses))
}
sort.Slice(gotAddresses, func(i, j int) bool {
return gotAddresses[i].AddressWithPrefix.Address < gotAddresses[j].AddressWithPrefix.Address
})
sort.Slice(expectedAddresses, func(i, j int) bool {
return expectedAddresses[i].AddressWithPrefix.Address < expectedAddresses[j].AddressWithPrefix.Address
})
for i, gotAddr := range gotAddresses {
expectedAddr := expectedAddresses[i]
if gotAddr != expectedAddr {
t.Errorf("got address = %+v, wanted = %+v", gotAddr, expectedAddr)
}
}
}
func TestAddAddress(t *testing.T) {
const nicid = 1
s := stack.New([]string{"fakeNet"}, nil, stack.Options{})
id, _ := channel.New(10, defaultMTU, "")
if err := s.CreateNIC(nicid, id); err != nil {
t.Fatal("CreateNIC failed:", err)
}
var addrGen addressGenerator
expectedAddresses := make([]tcpip.ProtocolAddress, 0, 2)
for _, addrLen := range []int{4, 16} {
address := addrGen.next(addrLen)
if err := s.AddAddress(nicid, fakeNetNumber, address); err != nil {
t.Fatalf("AddAddress(address=%s) failed: %s", address, err)
}
expectedAddresses = append(expectedAddresses, tcpip.ProtocolAddress{
Protocol: fakeNetNumber,
AddressWithPrefix: tcpip.AddressWithPrefix{address, fakeDefaultPrefixLen},
})
}
gotAddresses := s.NICInfo()[nicid].ProtocolAddresses
verifyAddresses(t, expectedAddresses, gotAddresses)
}
func TestAddAddressWithPrefix(t *testing.T) {
const nicid = 1
s := stack.New([]string{"fakeNet"}, nil, stack.Options{})
id, _ := channel.New(10, defaultMTU, "")
if err := s.CreateNIC(nicid, id); err != nil {
t.Fatal("CreateNIC failed:", err)
}
var addrGen addressGenerator
addrLenRange := []int{4, 16}
prefixLenRange := []int{8, 13, 20, 32}
expectedAddresses := make([]tcpip.ProtocolAddress, 0, len(addrLenRange)*len(prefixLenRange))
for _, addrLen := range addrLenRange {
for _, prefixLen := range prefixLenRange {
address := addrGen.next(addrLen)
if err := s.AddAddressWithPrefix(nicid, fakeNetNumber, tcpip.AddressWithPrefix{address, prefixLen}); err != nil {
t.Errorf("AddAddressWithPrefix(address=%s, prefixLen=%d) failed: %s", address, prefixLen, err)
}
expectedAddresses = append(expectedAddresses, tcpip.ProtocolAddress{
Protocol: fakeNetNumber,
AddressWithPrefix: tcpip.AddressWithPrefix{address, prefixLen},
})
}
}
gotAddresses := s.NICInfo()[nicid].ProtocolAddresses
verifyAddresses(t, expectedAddresses, gotAddresses)
}
func TestAddAddressWithOptions(t *testing.T) {
const nicid = 1
s := stack.New([]string{"fakeNet"}, nil, stack.Options{})
id, _ := channel.New(10, defaultMTU, "")
if err := s.CreateNIC(nicid, id); err != nil {
t.Fatal("CreateNIC failed:", err)
}
addrLenRange := []int{4, 16}
behaviorRange := []stack.PrimaryEndpointBehavior{stack.CanBePrimaryEndpoint, stack.FirstPrimaryEndpoint, stack.NeverPrimaryEndpoint}
expectedAddresses := make([]tcpip.ProtocolAddress, 0, len(addrLenRange)*len(behaviorRange))
var addrGen addressGenerator
for _, addrLen := range addrLenRange {
for _, behavior := range behaviorRange {
address := addrGen.next(addrLen)
if err := s.AddAddressWithOptions(nicid, fakeNetNumber, address, behavior); err != nil {
t.Fatalf("AddAddressWithOptions(address=%s, behavior=%d) failed: %s", address, behavior, err)
}
expectedAddresses = append(expectedAddresses, tcpip.ProtocolAddress{
Protocol: fakeNetNumber,
AddressWithPrefix: tcpip.AddressWithPrefix{address, fakeDefaultPrefixLen},
})
}
}
gotAddresses := s.NICInfo()[nicid].ProtocolAddresses
verifyAddresses(t, expectedAddresses, gotAddresses)
}
func TestAddAddressWithPrefixAndOptions(t *testing.T) {
const nicid = 1
s := stack.New([]string{"fakeNet"}, nil, stack.Options{})
id, _ := channel.New(10, defaultMTU, "")
if err := s.CreateNIC(nicid, id); err != nil {
t.Fatal("CreateNIC failed:", err)
}
addrLenRange := []int{4, 16}
prefixLenRange := []int{8, 13, 20, 32}
behaviorRange := []stack.PrimaryEndpointBehavior{stack.CanBePrimaryEndpoint, stack.FirstPrimaryEndpoint, stack.NeverPrimaryEndpoint}
expectedAddresses := make([]tcpip.ProtocolAddress, 0, len(addrLenRange)*len(prefixLenRange)*len(behaviorRange))
var addrGen addressGenerator
for _, addrLen := range addrLenRange {
for _, prefixLen := range prefixLenRange {
for _, behavior := range behaviorRange {
address := addrGen.next(addrLen)
if err := s.AddAddressWithPrefixAndOptions(nicid, fakeNetNumber, tcpip.AddressWithPrefix{address, prefixLen}, behavior); err != nil {
t.Fatalf("AddAddressWithPrefixAndOptions(address=%s, prefixLen=%d, behavior=%d) failed: %s", address, prefixLen, behavior, err)
}
expectedAddresses = append(expectedAddresses, tcpip.ProtocolAddress{
Protocol: fakeNetNumber,
AddressWithPrefix: tcpip.AddressWithPrefix{address, prefixLen},
})
}
}
}
gotAddresses := s.NICInfo()[nicid].ProtocolAddresses
verifyAddresses(t, expectedAddresses, gotAddresses)
}
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)
t.Fatal("CreateNIC failed:", err)
}
if err := s.AddAddress(1, fakeNetNumber, "\x01"); err != nil {
t.Fatalf("AddAddress failed: %v", err)
t.Fatal("AddAddress failed:", err)
}
// Route all packets for address \x01 to NIC 1.
s.SetRouteTable([]tcpip.Route{
@ -1104,18 +1238,18 @@ func TestNICForwarding(t *testing.T) {
id1, linkEP1 := channel.New(10, defaultMTU, "")
if err := s.CreateNIC(1, id1); err != nil {
t.Fatalf("CreateNIC #1 failed: %v", err)
t.Fatal("CreateNIC #1 failed:", err)
}
if err := s.AddAddress(1, fakeNetNumber, "\x01"); err != nil {
t.Fatalf("AddAddress #1 failed: %v", err)
t.Fatal("AddAddress #1 failed:", err)
}
id2, linkEP2 := channel.New(10, defaultMTU, "")
if err := s.CreateNIC(2, id2); err != nil {
t.Fatalf("CreateNIC #2 failed: %v", err)
t.Fatal("CreateNIC #2 failed:", err)
}
if err := s.AddAddress(2, fakeNetNumber, "\x02"); err != nil {
t.Fatalf("AddAddress #2 failed: %v", err)
t.Fatal("AddAddress #2 failed:", err)
}
// Route all packets to address 3 to NIC 2.

View File

@ -1059,14 +1059,23 @@ func ParseMACAddress(s string) (LinkAddress, error) {
return LinkAddress(addr), nil
}
// AddressWithPrefix is an address with its subnet prefix length.
type AddressWithPrefix struct {
// Address is a network address.
Address Address
// PrefixLen is the subnet prefix length.
PrefixLen int
}
// ProtocolAddress is an address and the network protocol it is associated
// with.
type ProtocolAddress struct {
// Protocol is the protocol of the address.
Protocol NetworkProtocolNumber
// Address is a network address.
Address Address
// AddressWithPrefix is a network address with its subnet prefix length.
AddressWithPrefix AddressWithPrefix
}
// danglingEndpointsMu protects access to danglingEndpoints.

View File

@ -967,14 +967,14 @@ func TestTTL(t *testing.T) {
multicast = false
switch variant {
case "v4", "mapped":
ep, err := ipv4.NewProtocol().NewEndpoint(0, "", nil, nil, nil)
ep, err := ipv4.NewProtocol().NewEndpoint(0, tcpip.AddressWithPrefix{}, nil, nil, nil)
if err != nil {
t.Fatal(err)
}
wantTTL = ep.DefaultTTL()
ep.Close()
case "v6":
ep, err := ipv6.NewProtocol().NewEndpoint(0, "", nil, nil, nil)
ep, err := ipv6.NewProtocol().NewEndpoint(0, tcpip.AddressWithPrefix{}, nil, nil, nil)
if err != nil {
t.Fatal(err)
}