// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

//go:build !build_with_native_toolchain
// +build !build_with_native_toolchain

package netstack

import (
	"context"
	"errors"
	"flag"
	"fmt"
	"math"
	"net"
	"os"
	"sort"
	"syscall/zx"
	"testing"
	"time"

	"fidl/fuchsia/hardware/ethernet"
	"fidl/fuchsia/io"
	"fidl/fuchsia/logger"
	fidlnet "fidl/fuchsia/net"
	"fidl/fuchsia/net/stack"
	"fidl/fuchsia/netstack"

	"go.fuchsia.dev/fuchsia/src/connectivity/network/netstack/dhcp"
	"go.fuchsia.dev/fuchsia/src/connectivity/network/netstack/dns"
	"go.fuchsia.dev/fuchsia/src/connectivity/network/netstack/fidlconv"
	"go.fuchsia.dev/fuchsia/src/connectivity/network/netstack/link/eth/testutil"
	"go.fuchsia.dev/fuchsia/src/connectivity/network/netstack/routes"
	"go.fuchsia.dev/fuchsia/src/connectivity/network/netstack/util"
	"go.fuchsia.dev/fuchsia/src/lib/component"
	syslog "go.fuchsia.dev/fuchsia/src/lib/syslog/go"

	"github.com/google/go-cmp/cmp"
	"gvisor.dev/gvisor/pkg/tcpip"
	"gvisor.dev/gvisor/pkg/tcpip/faketime"
	"gvisor.dev/gvisor/pkg/tcpip/header"
	"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/ipv6"
	tcpipstack "gvisor.dev/gvisor/pkg/tcpip/stack"
	"gvisor.dev/gvisor/pkg/tcpip/transport/tcp"
	"gvisor.dev/gvisor/pkg/tcpip/transport/udp"
	"gvisor.dev/gvisor/pkg/waiter"
)

const (
	testTopoPath         string        = "/fake/ethernet/device"
	testV4Address        tcpip.Address = "\xc0\xa8\x2a\x10"
	testV6Address        tcpip.Address = "\xc0\xa8\x2a\x10\xc0\xa8\x2a\x10\xc0\xa8\x2a\x10\xc0\xa8\x2a\x10"
	testLinkLocalV6Addr1 tcpip.Address = "\xfe\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01"
	testLinkLocalV6Addr2 tcpip.Address = "\xfe\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02"
	dadResolutionTimeout               = dadRetransmitTimer*dadTransmits + time.Second
)

func TestMain(m *testing.M) {
	flag.Parse()
	if testing.Verbose() {
		appCtx := component.NewContextFromStartupInfo()
		req, logSink, err := logger.NewLogSinkWithCtxInterfaceRequest()
		if err != nil {
			panic(err)
		}
		appCtx.ConnectToEnvService(req)
		options := syslog.LogInitOptions{
			LogSink:                       logSink,
			LogLevel:                      syslog.TraceLevel,
			MinSeverityForFileAndLineInfo: syslog.TraceLevel,
		}
		l, err := syslog.NewLogger(options)
		if err != nil {
			panic(fmt.Sprintf("syslog.NewLogger(%#v) = %s", options, err))
		}
		syslog.SetDefaultLogger(l)

		// As of this writing we set this value to 0 in netstack/main.go.
		sniffer.LogPackets.Store(1)
	}

	os.Exit(m.Run())
}

func TestDelRouteErrors(t *testing.T) {
	ns, _ := newNetstack(t, netstackTestOptions{})

	ifs := addNoopEndpoint(t, ns, "")
	t.Cleanup(ifs.RemoveByUser)

	rt := tcpip.Route{
		Destination: header.IPv4EmptySubnet,
		Gateway:     "\x01\x02\x03\x04",
		NIC:         ifs.nicid,
	}

	// Deleting a route we never added should return no routes deleted.
	if got := ns.DelRoute(rt); len(got) != 0 {
		t.Errorf("DelRoute(%s) = %#v not empty", rt, got)
	}

	if err := ns.AddRoute(rt, metricNotSet, false); err != nil {
		t.Fatalf("AddRoute(%s, metricNotSet, false): %s", rt, err)
	}
	// Deleting a route we added should not result in an error.
	want := routes.ExtendedRoute{
		Route:                 rt,
		Prf:                   routes.MediumPreference,
		Metric:                metricNotSet,
		MetricTracksInterface: true,
	}
	if diff := cmp.Diff(ns.DelRoute(rt), []routes.ExtendedRoute{want}); diff != "" {
		t.Fatalf("DelRoute(%s): -got +want %s", rt, diff)
	}
	// Deleting a route we just deleted should result in no routes actually deleted.
	if got := ns.DelRoute(rt); len(got) != 0 {
		t.Errorf("DelRoute(%s) = %#v not empty", rt, got)
	}
}

// TestStackNICEnableDisable tests that the NIC in stack.Stack is enabled or
// disabled when the underlying link is brought up or down, respectively.
func TestStackNICEnableDisable(t *testing.T) {
	ns, _ := newNetstack(t, netstackTestOptions{})
	ifs := addNoopEndpoint(t, ns, "")
	t.Cleanup(ifs.RemoveByUser)

	// The NIC should initially be disabled in stack.Stack.
	if enabled := ns.stack.CheckNIC(ifs.nicid); enabled {
		t.Fatalf("got ns.stack.CheckNIC(%d) = true, want = false", ifs.nicid)
	}

	isUp := func() bool {
		ifs.mu.Lock()
		defer ifs.mu.Unlock()
		return ifs.IsUpLocked()
	}

	if isUp() {
		t.Fatal("got initial link state up, want down")
	}

	// Bringing the link up should enable the NIC in stack.Stack.
	if err := ifs.Up(); err != nil {
		t.Fatal("ifs.Up(): ", err)
	}
	if enabled := ns.stack.CheckNIC(ifs.nicid); !enabled {
		t.Fatalf("got ns.stack.CheckNIC(%d) = false, want = true", ifs.nicid)
	}

	if !isUp() {
		t.Fatal("got post-up link state down, want up")
	}

	// Bringing the link down should disable the NIC in stack.Stack.
	if err := ifs.Down(); err != nil {
		t.Fatal("ifs.Down(): ", err)
	}
	if enabled := ns.stack.CheckNIC(ifs.nicid); enabled {
		t.Fatalf("got ns.stack.CheckNIC(%d) = true, want = false", ifs.nicid)
	}

	if isUp() {
		t.Fatal("got post-down link state up, want down")
	}
}

var _ NICRemovedHandler = (*testNicRemovedHandler)(nil)

type testNicRemovedHandler struct {
	removedNICID tcpip.NICID
}

func (h *testNicRemovedHandler) RemovedNIC(nicID tcpip.NICID) {
	h.removedNICID = nicID
}

// TestStackNICRemove tests that the NIC in stack.Stack is removed when the
// underlying link is closed.
func TestStackNICRemove(t *testing.T) {
	nicRemovedHandler := testNicRemovedHandler{}
	ns, _ := newNetstack(t, netstackTestOptions{nicRemovedHandler: &nicRemovedHandler})
	var obs noopObserver

	ifs, err := ns.addEndpoint(
		func(tcpip.NICID) string { return t.Name() },
		&noopEndpoint{},
		&noopController{},
		&obs,
		0, /* metric */
	)
	if err != nil {
		t.Fatal(err)
	}

	// The NIC should initially be disabled in stack.Stack.
	if enabled := ns.stack.CheckNIC(ifs.nicid); enabled {
		t.Errorf("got ns.stack.CheckNIC(%d) = true, want = false", ifs.nicid)
	}
	if _, ok := ns.stack.NICInfo()[ifs.nicid]; !ok {
		t.Errorf("missing NICInfo for NIC %d", ifs.nicid)
	}
	if _, err := ns.stack.GetMainNICAddress(ifs.nicid, header.IPv6ProtocolNumber); err != nil {
		t.Errorf("GetMainNICAddress(%d, header.IPv6ProtocolNumber): %s", ifs.nicid, err)
	}

	if t.Failed() {
		t.FailNow()
	}

	// Closing the link should remove the NIC from stack.Stack.
	obs.onLinkClosed()

	if enabled := ns.stack.CheckNIC(ifs.nicid); enabled {
		t.Errorf("got ns.stack.CheckNIC(%d) = false, want = true", ifs.nicid)
	}
	if nicInfo, ok := ns.stack.NICInfo()[ifs.nicid]; ok {
		t.Errorf("unexpected NICInfo found for NIC %d = %+v", ifs.nicid, nicInfo)
	}
	{
		addr, err := ns.stack.GetMainNICAddress(ifs.nicid, header.IPv6ProtocolNumber)
		if _, ok := err.(*tcpip.ErrUnknownNICID); !ok {
			t.Errorf("got GetMainNICAddress(%d, header.IPv6ProtocolNumber) = (%s, %T), want = (_, *tcpip.ErrUnknownNICID)", ifs.nicid, addr, err)
		}
	}
	if nicRemovedHandler.removedNICID != ifs.nicid {
		t.Errorf("got nicRemovedHandler.removedNICID = %d, want = %d", nicRemovedHandler.removedNICID, ifs.nicid)
	}

	// Wait for the controller to stop and free up its resources.
	ifs.endpoint.Wait()
}

func containsRoute(rs []tcpip.Route, r tcpip.Route) bool {
	for _, i := range rs {
		if i == r {
			return true
		}
	}

	return false
}

func TestEndpoint_Close(t *testing.T) {
	ns, _ := newNetstack(t, netstackTestOptions{})
	var wq waiter.Queue
	// Avoid polluting everything with err of type tcpip.Error.
	ep := func() tcpip.Endpoint {
		ep, err := ns.stack.NewEndpoint(tcp.ProtocolNumber, ipv6.ProtocolNumber, &wq)
		if err != nil {
			t.Fatalf("NewEndpoint(tcp.ProtocolNumber, ipv6.ProtocolNumber, _) = %s", err)
		}
		return ep
	}()
	defer ep.Close()

	eps, err := newEndpointWithSocket(ep, &wq, tcp.ProtocolNumber, ipv6.ProtocolNumber, ns)
	if err != nil {
		t.Fatal(err)
	}
	defer eps.close()

	eps.mu.Lock()
	channels := []struct {
		ch   <-chan struct{}
		name string
	}{
		{ch: eps.closing, name: "closing"},
		{ch: eps.mu.loopReadDone, name: "loopReadDone"},
		{ch: eps.mu.loopWriteDone, name: "loopWriteDone"},
	}
	eps.mu.Unlock()

	// Check starting conditions.
	for _, ch := range channels {
		select {
		case <-ch.ch:
			t.Errorf("%s cleaned up prematurely", ch.name)
		default:
		}
	}

	if _, ok := eps.ns.endpoints.Load(eps.endpoint.key); !ok {
		var keys []uint64
		eps.ns.endpoints.Range(func(key uint64, _ tcpip.Endpoint) bool {
			keys = append(keys, key)
			return true
		})
		t.Errorf("got endpoints map = %d at creation, want %d", keys, eps.endpoint.key)
	}

	if t.Failed() {
		t.FailNow()
	}

	// Create a referent.
	s, err := newStreamSocket(makeStreamSocketImpl(eps))
	if err != nil {
		t.Fatalf("newStreamSocket() = %s", err)
	}
	defer func() {
		func() {
			result, err := s.Close(context.Background())
			if err, ok := err.(*zx.Error); ok && err.Status == zx.ErrPeerClosed {
				return
			}
			t.Errorf("s.Close() = (%#v, %v)", result, err)
		}()
		if err := s.Channel.Close(); err != nil {
			t.Errorf("s.Channel.Close() = %s", err)
		}
	}()

	// Create another referent.
	localC, peerC, err := zx.NewChannel(0)
	if err != nil {
		t.Fatalf("zx.NewChannel() = %s", err)
	}
	defer func() {
		// Already closed below.
		if err := localC.Close(); err != nil {
			t.Errorf("localC.Close() = %s", err)
		}

		// By-value copy already closed by the server when we closed the peer.
		err := peerC.Close()
		if err, ok := err.(*zx.Error); ok && err.Status == zx.ErrBadHandle {
			return
		}
		t.Errorf("peerC.Close() = %v", err)
	}()

	if err := s.Clone(context.Background(), 0, io.NodeWithCtxInterfaceRequest{Channel: peerC}); err != nil {
		t.Fatalf("s.Clone() = %s", err)
	}

	// Close the original referent.
	if result, err := s.Close(context.Background()); err != nil {
		t.Fatalf("s.Close() = %s", err)
	} else if result.Which() != io.Node2CloseResultResponse {
		t.Fatalf("s.Close() = %s", zx.Status(result.Err))
	}

	// There's still a referent.
	for _, ch := range channels {
		select {
		case <-ch.ch:
			t.Errorf("%s cleaned up prematurely", ch.name)
		default:
		}
	}

	if _, ok := eps.ns.endpoints.Load(eps.endpoint.key); !ok {
		var keys []uint64
		eps.ns.endpoints.Range(func(key uint64, _ tcpip.Endpoint) bool {
			keys = append(keys, key)
			return true
		})
		t.Errorf("got endpoints map prematurely = %d, want %d", keys, eps.endpoint.key)
	}

	if t.Failed() {
		t.FailNow()
	}

	// Close the last reference.
	if err := localC.Close(); err != nil {
		t.Fatalf("localC.Close() = %s", err)
	}

	// Give a generous timeout for the closed channel to be detected.
	timeout := make(chan struct{})
	time.AfterFunc(5*time.Second, func() { close(timeout) })
	for _, ch := range channels {
		if ch.ch != nil {
			select {
			case <-ch.ch:
			case <-timeout:
				t.Errorf("%s not cleaned up", ch.name)
			}
		}
	}

	for {
		if _, ok := eps.ns.endpoints.Load(eps.endpoint.key); ok {
			select {
			case <-timeout:
				var keys []uint64
				eps.ns.endpoints.Range(func(key uint64, _ tcpip.Endpoint) bool {
					keys = append(keys, key)
					return true
				})
				t.Errorf("got endpoints map = %d after closure, want *not* %d", keys, eps.endpoint.key)
			default:
				continue
			}
		}
		break
	}

	if t.Failed() {
		t.FailNow()
	}
}

// TestTCPEndpointMapAcceptAfterReset tests that an already-reset endpoint
// isn't added to the endpoints map, since such an endpoint wouldn't receive a
// hangup notification and its reference in the map would leak.
func TestTCPEndpointMapAcceptAfterReset(t *testing.T) {
	ns, _ := newNetstack(t, netstackTestOptions{})
	if err := ns.addLoopback(); err != nil {
		t.Fatalf("ns.addLoopback() = %s", err)
	}

	listener := makeStreamSocketImpl(createEP(t, ns, new(waiter.Queue)))

	if err := listener.ep.Bind(tcpip.FullAddress{}); err != nil {
		t.Fatalf("Bind({}) = %s", err)
	}
	if err := listener.ep.Listen(1); err != nil {
		t.Fatalf("Listen(1) = %s", err)
	}

	client := createEP(t, ns, new(waiter.Queue))

	// Connect and wait for the incoming connection.
	func() {
		connectAddr, err := listener.ep.GetLocalAddress()
		if err != nil {
			t.Fatalf("GetLocalAddress() = %s", err)
		}

		waitEntry, notifyCh := waiter.NewChannelEntry(waiter.EventIn)
		listener.wq.EventRegister(&waitEntry)
		defer listener.wq.EventUnregister(&waitEntry)

		switch err := client.ep.Connect(connectAddr); err.(type) {
		case *tcpip.ErrConnectStarted:
		default:
			t.Fatalf("Connect(%#v) = %s", connectAddr, err)
		}
		<-notifyCh
	}()

	// Initiate a RST of the connection sitting in the accept queue.
	client.ep.SocketOptions().SetLinger(tcpip.LingerOption{
		Enabled: true,
		Timeout: 0,
	})
	client.ep.Close()

	// Wait for the RST to be processed by the stack.
	time.Sleep(100 * time.Millisecond)

	_, _, s, err := listener.accept(false)
	if err != nil {
		t.Fatalf("ep.accept(false) = %s", err)
	}
	defer s.endpointWithSocket.close()

	// Expect the `Accept` to have removed the endpoint from the map.
	if _, ok := ns.endpoints.Load(s.endpoint.key); ok {
		t.Fatalf("got endpoints.Load(%d) = (_, true)", s.endpoint.key)
	}

	s.mu.Lock()
	channels := []struct {
		ch   <-chan struct{}
		name string
	}{
		{ch: s.closing, name: "closing"},
		{ch: s.mu.loopReadDone, name: "loopReadDone"},
		{ch: s.mu.loopWriteDone, name: "loopWriteDone"},
	}
	s.mu.Unlock()

	// Give a generous timeout for the closed channel to be detected.
	timeout := make(chan struct{})
	time.AfterFunc(5*time.Second, func() { close(timeout) })
	for _, ch := range channels {
		if ch.ch != nil {
			select {
			case <-ch.ch:
			case <-timeout:
				t.Errorf("%s not cleaned up", ch.name)
			}
		}
	}
}

func createEP(t *testing.T, ns *Netstack, wq *waiter.Queue) *endpointWithSocket {
	// Avoid polluting the scope with err of type tcpip.Error.
	ep := func() tcpip.Endpoint {
		ep, err := ns.stack.NewEndpoint(tcp.ProtocolNumber, ipv4.ProtocolNumber, wq)
		if err != nil {
			t.Fatalf("NewEndpoint(tcp.ProtocolNumber, ipv4.ProtocolNumber, _) = %s", err)
		}
		return ep
	}()
	t.Cleanup(ep.Close)
	eps, err := newEndpointWithSocket(ep, wq, tcp.ProtocolNumber, ipv4.ProtocolNumber, ns)
	if err != nil {
		t.Fatal(err)
	}
	t.Cleanup(eps.close)
	return eps
}

func TestTCPEndpointMapClose(t *testing.T) {
	ns, _ := newNetstack(t, netstackTestOptions{})
	eps := createEP(t, ns, new(waiter.Queue))

	// Closing the endpoint should remove it from the endpoints map.
	if _, ok := ns.endpoints.Load(eps.endpoint.key); !ok {
		t.Fatalf("got endpoints.Load(%d) = (_, false)", eps.endpoint.key)
	}
	eps.close()
	if _, ok := ns.endpoints.Load(eps.endpoint.key); ok {
		t.Fatalf("got endpoints.Load(%d) = (_, true)", eps.endpoint.key)
	}
}

func TestTCPEndpointMapConnect(t *testing.T) {
	ns, clock := newNetstack(t, netstackTestOptions{})

	var linkEP tcpipstack.LinkEndpoint = &noopEndpoint{
		capabilities: tcpipstack.CapabilityResolutionRequired,
	}
	if testing.Verbose() {
		linkEP = sniffer.New(linkEP)
	}
	ifs, err := ns.addEndpoint(
		func(tcpip.NICID) string { return t.Name() },
		linkEP,
		&noopController{},
		nil,
		0, /* metric */
	)
	if err != nil {
		t.Fatal(err)
	}
	if err := ns.stack.EnableNIC(ifs.nicid); err != nil {
		t.Fatal(err)
	}

	address := tcpip.Address([]byte{1, 2, 3, 4})
	destination := tcpip.FullAddress{
		Addr: address,
		Port: 1,
	}
	source := tcpip.Address([]byte{5, 6, 7, 8})
	protocolAddress := tcpip.ProtocolAddress{
		Protocol:          ipv4.ProtocolNumber,
		AddressWithPrefix: source.WithPrefix(),
	}
	if err := ns.stack.AddProtocolAddress(ifs.nicid, protocolAddress, tcpipstack.AddressProperties{}); err != nil {
		t.Fatalf("AddProtocolAddress(%d, %#v, {}) = %s", ifs.nicid, protocolAddress, err)
	}

	ns.stack.SetRouteTable([]tcpip.Route{
		{
			Destination: address.WithPrefix().Subnet(),
			NIC:         ifs.nicid,
		},
	})

	var wq waiter.Queue
	eps := createEP(t, ns, &wq)

	events := make(chan waiter.EventMask, 1)
	waitEntry := waiter.NewFunctionEntry(math.MaxUint64, func(m waiter.EventMask) {
		events <- m
	})
	wq.EventRegister(&waitEntry)
	defer wq.EventUnregister(&waitEntry)

	switch err := eps.ep.Connect(destination); err.(type) {
	case *tcpip.ErrConnectStarted:
	default:
		t.Fatalf("got Connect(%#v) = %v, want %s", destination, err, &tcpip.ErrConnectStarted{})
	}

	{
		nudConfig, err := ns.stack.NUDConfigurations(ifs.nicid, ipv4.ProtocolNumber)
		if err != nil {
			t.Fatalf("stack.NUDConfigurations(): %s", err)
		}
		clock.Advance(time.Duration(nudConfig.MaxMulticastProbes) * nudConfig.RetransmitTimer)
	}

	if got, want := <-events, waiter.ReadableEvents|waiter.WritableEvents|waiter.EventErr|waiter.EventHUp; got != want {
		t.Fatalf("got event = %b, want %b", got, want)
	}

	// The callback on HUp should have removed the endpoint from the map.
	if _, ok := ns.endpoints.Load(eps.endpoint.key); ok {
		t.Fatalf("got endpoints.Load(%d) = (_, true)", eps.endpoint.key)
	}
}

// TestTCPEndpointMapClosing validates the endpoint in a closing state like
// FIN_WAIT2 to be present in the endpoints map and is deleted when the
// endpoint transitions to CLOSED state.
func TestTCPEndpointMapClosing(t *testing.T) {
	ns, _ := newNetstack(t, netstackTestOptions{})
	if err := ns.addLoopback(); err != nil {
		t.Fatalf("ns.addLoopback() = %s", err)
	}
	listener := createEP(t, ns, new(waiter.Queue))

	if err := listener.ep.Bind(tcpip.FullAddress{}); err != nil {
		t.Fatalf("ep.Bind({}) = %s", err)
	}
	if err := listener.ep.Listen(1); err != nil {
		t.Fatalf("ep.Listen(1) = %s", err)
	}
	connectAddr, err := listener.ep.GetLocalAddress()
	if err != nil {
		t.Fatalf("ep.GetLocalAddress() = %s", err)
	}
	client := createEP(t, ns, new(waiter.Queue))

	waitEntry, inCh := waiter.NewChannelEntry(waiter.EventIn)
	listener.wq.EventRegister(&waitEntry)
	defer listener.wq.EventUnregister(&waitEntry)

	switch err := client.ep.Connect(connectAddr); err.(type) {
	case *tcpip.ErrConnectStarted:
	default:
		t.Fatalf("ep.Connect(%#v) = %s", connectAddr, err)
	}
	// Wait for the newly established connection to show up as acceptable by
	// the peer.
	<-inCh

	server, _, err := listener.ep.Accept(nil)
	if err != nil {
		t.Fatalf("ep.Accept(nil) = %s", err)
	}

	// Ensure that the client endpoint is present in our internal map.
	if _, ok := ns.endpoints.Load(client.endpoint.key); !ok {
		t.Fatalf("got endpoints.Load(%d) = (_,false)", client.endpoint.key)
	}

	// Trigger an active close from the client.
	client.close()

	// The client endpoint should not be removed from endpoints map even after
	// an endpoint close.
	if _, ok := ns.endpoints.Load(client.endpoint.key); !ok {
		t.Fatalf("got endpoints.Load(%d) = (_,false)", client.endpoint.key)
	}

	ticker := time.NewTicker(10 * time.Millisecond)
	defer ticker.Stop()
	// Wait and check for the client active close to reach FIN_WAIT2 state.
	for {
		if tcp.EndpointState(client.ep.State()) == tcp.StateFinWait2 {
			break
		}
		<-ticker.C
	}

	// Lookup for the client once more in the endpoints map, it should still not
	// be removed.
	if _, ok := ns.endpoints.Load(client.endpoint.key); !ok {
		t.Fatalf("got endpoints.Load(%d) = (_,false)", client.endpoint.key)
	}

	timeWaitOpt := tcpip.TCPTimeWaitTimeoutOption(time.Duration(0))
	if err := ns.stack.SetTransportProtocolOption(tcp.ProtocolNumber, &timeWaitOpt); err != nil {
		t.Fatalf("SetTransportProtocolOption(%d, &%T(%d)) = %s", tcp.ProtocolNumber, timeWaitOpt, timeWaitOpt, err)
	}

	// Trigger server close, so that client enters TIME_WAIT.
	server.Close()

	// gVisor stack notifies EventHUp on entering TIME_WAIT. Wait for some time
	// for the EventHUp to be processed by netstack.
	for {
		// The client endpoint would be removed from the endpoints map as a result
		// of processing EventHUp.
		if _, ok := ns.endpoints.Load(client.endpoint.key); !ok {
			break
		}
		<-ticker.C
	}
}

func TestEndpointsMapKey(t *testing.T) {
	ns, _ := newNetstack(t, netstackTestOptions{})
	if ns.endpoints.nextKey != 0 {
		t.Fatalf("got ns.endpoints.nextKey = %d, want 0", ns.endpoints.nextKey)
	}

	tcpipEP := func() (*waiter.Queue, tcpip.Endpoint) {
		var wq waiter.Queue
		ep, err := ns.stack.NewEndpoint(tcp.ProtocolNumber, ipv6.ProtocolNumber, &wq)
		if err != nil {
			t.Fatalf("NewEndpoint(tcp.ProtocolNumber, ipv6.ProtocolNumber, _) = %s", err)
		}
		t.Cleanup(ep.Close)
		return &wq, ep
	}
	// Test if we always skip key value 0 while adding to the map.
	for _, key := range []uint64{0, math.MaxUint64} {
		wq, ep := tcpipEP()

		// Set a test value to nextKey which is used to compute the endpoint key.
		ns.endpoints.nextKey = key
		eps, err := newEndpointWithSocket(ep, wq, tcp.ProtocolNumber, ipv6.ProtocolNumber, ns)
		if err != nil {
			t.Fatal(err)
		}
		t.Cleanup(eps.close)
		if ns.endpoints.nextKey != 1 {
			t.Fatalf("got ns.endpoints.nextKey = %d, want 1", ns.endpoints.nextKey)
		}
		if eps.endpoint.key != 1 {
			t.Fatalf("got eps.endpoint.key = %d, want 1", eps.endpoint.key)
		}
		if _, ok := ns.endpoints.Load(eps.endpoint.key); !ok {
			t.Fatalf("got endpoints.Load(%d) = (_,false)", eps.endpoint.key)
		}
		// Closing the endpoint should remove the endpoint with key value 1
		// from the endpoints map. This lets the subsequent iteration to reuse
		// key value 1 to add a new endpoint to the map.
		eps.close()
	}

	// Key value 0 is not expected to be removed from the map.
	_, ep := tcpipEP()
	ns.endpoints.Store(0, ep)
	if ns.onRemoveEndpoint(0) {
		t.Errorf("got ns.onRemoveEndpoint(0) = true, want false")
	}
	if _, ok := ns.endpoints.Load(0); !ok {
		t.Fatal("got endpoints.Load(0) = (_,false)")
	}
}

func TestNICName(t *testing.T) {
	ns, _ := newNetstack(t, netstackTestOptions{})

	if want, got := "unknown(NICID=0)", ns.name(0); got != want {
		t.Fatalf("got ns.name(0) = %q, want %q", got, want)
	}

	{
		ifs := addNoopEndpoint(t, ns, "")
		t.Cleanup(ifs.RemoveByUser)
		if got, want := ifs.ns.name(ifs.nicid), t.Name()+"1"; got != want {
			t.Fatalf("got ifs.mu.name = %q, want = %q", got, want)
		}
	}

	{
		const name = "VerySpecialName"
		ifs := addNoopEndpoint(t, ns, name)
		t.Cleanup(ifs.RemoveByUser)
		if got, want := ifs.ns.name(ifs.nicid), name; got != want {
			t.Fatalf("got ifs.mu.name = %q, want = %q", got, want)
		}
	}
}

func TestNotStartedByDefault(t *testing.T) {
	ns, _ := newNetstack(t, netstackTestOptions{})

	startCalled := false
	controller := noopController{
		onUp: func() { startCalled = true },
	}
	if _, err := ns.addEndpoint(
		func(tcpip.NICID) string { return t.Name() },
		&noopEndpoint{},
		&controller,
		nil, /* observer */
		0,   /* metric */
	); err != nil {
		t.Fatal(err)
	}

	if startCalled {
		t.Error("unexpected call to Controller.Up")
	}
}

type ndpDADEvent struct {
	nicID  tcpip.NICID
	addr   tcpip.Address
	result tcpipstack.DADResult
}

var _ ipv6.NDPDispatcher = (*testNDPDispatcher)(nil)

// testNDPDispatcher is a tcpip.NDPDispatcher that sends an NDP DAD event on
// dadC when OnDuplicateAddressDetectionResult gets called.
type testNDPDispatcher struct {
	dadC chan ndpDADEvent
}

// OnDuplicateAddressDetectionResult implements ipv6.NDPDispatcher.
func (n *testNDPDispatcher) OnDuplicateAddressDetectionResult(nicID tcpip.NICID, addr tcpip.Address, result tcpipstack.DADResult) {
	if c := n.dadC; c != nil {
		c <- ndpDADEvent{
			nicID:  nicID,
			addr:   addr,
			result: result,
		}
	}
}

// OnDefaultRouterDiscovered implements ipv6.NDPDispatcher.
func (*testNDPDispatcher) OnOffLinkRouteUpdated(tcpip.NICID, tcpip.Subnet, tcpip.Address, header.NDPRoutePreference) {
}

// OnDefaultRouterInvalidated implements ipv6.NDPDispatcher.
func (*testNDPDispatcher) OnOffLinkRouteInvalidated(tcpip.NICID, tcpip.Subnet, tcpip.Address) {
}

// OnOnLinkPrefixDiscovered implements ipv6.NDPDispatcher.
func (*testNDPDispatcher) OnOnLinkPrefixDiscovered(tcpip.NICID, tcpip.Subnet) {
}

// OnOnLinkPrefixInvalidated implements ipv6.NDPDispatcher.
func (*testNDPDispatcher) OnOnLinkPrefixInvalidated(tcpip.NICID, tcpip.Subnet) {
}

// OnAutoGenAddress implements ipv6.NDPDispatcher.
func (*testNDPDispatcher) OnAutoGenAddress(tcpip.NICID, tcpip.AddressWithPrefix) {
}

// OnAutoGenAddressDeprecated implements ipv6.NDPDispatcher.
func (*testNDPDispatcher) OnAutoGenAddressDeprecated(tcpip.NICID, tcpip.AddressWithPrefix) {
}

// OnAutoGenAddressInvalidated implements ipv6.NDPDispatcher.
func (*testNDPDispatcher) OnAutoGenAddressInvalidated(tcpip.NICID, tcpip.AddressWithPrefix) {
}

// OnRecursiveDNSServerOption implements ipv6.NDPDispatcher.
func (*testNDPDispatcher) OnRecursiveDNSServerOption(tcpip.NICID, []tcpip.Address, time.Duration) {
}

// OnDNSSearchListOption implements ipv6.NDPDispatcher.
func (*testNDPDispatcher) OnDNSSearchListOption(tcpip.NICID, []string, time.Duration) {
}

// OnDHCPv6Configuration implements ipv6.NDPDispatcher.
func (*testNDPDispatcher) OnDHCPv6Configuration(tcpip.NICID, ipv6.DHCPv6ConfigurationFromNDPRA) {
}

func TestIpv6LinkLocalOnLinkRoute(t *testing.T) {
	if got, want := ipv6LinkLocalOnLinkRoute(6), (tcpip.Route{Destination: header.IPv6LinkLocalPrefix.Subnet(), NIC: 6}); got != want {
		t.Fatalf("got ipv6LinkLocalOnLinkRoute(6) = %s, want = %s", got, want)
	}
}

// Test that NICs get an on-link route to the IPv6 link-local subnet when it is
// brought up.
func TestIpv6LinkLocalOnLinkRouteOnUp(t *testing.T) {
	ns, _ := newNetstack(t, netstackTestOptions{})

	ep := noopEndpoint{
		linkAddress: tcpip.LinkAddress([]byte{2, 3, 4, 5, 6, 7}),
	}
	ifs, err := ns.addEndpoint(
		func(tcpip.NICID) string { return t.Name() },
		&ep,
		&noopController{},
		nil, /* observer */
		0,   /* metric */
	)
	if err != nil {
		t.Fatal(err)
	}

	linkLocalRoute := ipv6LinkLocalOnLinkRoute(ifs.nicid)

	// Initially should not have the link-local route.
	rt := ns.stack.GetRouteTable()
	if containsRoute(rt, linkLocalRoute) {
		t.Fatalf("got GetRouteTable() = %+v, don't want = %s", rt, linkLocalRoute)
	}

	// Bringing the ethernet device up should result in the link-local
	// route being added.
	if err := ifs.Up(); err != nil {
		t.Fatalf("eth.Up(): %s", err)
	}
	rt = ns.stack.GetRouteTable()
	if !containsRoute(rt, linkLocalRoute) {
		t.Fatalf("got GetRouteTable() = %+v, want = %s", rt, linkLocalRoute)
	}

	// Bringing the ethernet device down should result in the link-local
	// route being removed.
	if err := ifs.Down(); err != nil {
		t.Fatalf("eth.Down(): %s", err)
	}
	rt = ns.stack.GetRouteTable()
	if containsRoute(rt, linkLocalRoute) {
		t.Fatalf("got GetRouteTable() = %+v, don't want = %s", rt, linkLocalRoute)
	}
}

func TestOnLinkV6Route(t *testing.T) {
	subAddr := util.Parse("abcd:1234::")
	subMask := tcpip.AddressMask(util.Parse("ffff:ffff::"))
	subnet, err := tcpip.NewSubnet(subAddr, subMask)
	if err != nil {
		t.Fatalf("NewSubnet(%s, %s): %s", subAddr, subMask, err)
	}

	if got, want := onLinkV6Route(6, subnet), (tcpip.Route{Destination: subnet, NIC: 6}); got != want {
		t.Fatalf("got onLinkV6Route(6, %s) = %s, want = %s", subnet, got, want)
	}
}

func TestMulticastPromiscuousModeEnabledByDefault(t *testing.T) {
	ns, _ := newNetstack(t, netstackTestOptions{})

	multicastPromiscuousModeEnabled := false
	eth, _ := testutil.MakeEthernetDevice(t, ethernet.Info{}, 1)
	eth.ConfigMulticastSetPromiscuousModeImpl = func(enabled bool) (int32, error) {
		multicastPromiscuousModeEnabled = enabled
		return int32(zx.ErrOk), nil
	}

	if _, err := ns.addEth(testTopoPath, netstack.InterfaceConfig{Name: t.Name()}, &eth); err != nil {
		t.Fatal(err)
	}

	if !multicastPromiscuousModeEnabled {
		t.Error("expected a call to ConfigMulticastSetPromiscuousMode(true) by addEth")
	}
}

func TestUniqueFallbackNICNames(t *testing.T) {
	ns, _ := newNetstack(t, netstackTestOptions{})

	ifs1 := addNoopEndpoint(t, ns, "")
	t.Cleanup(ifs1.RemoveByUser)
	ifs2 := addNoopEndpoint(t, ns, "")
	t.Cleanup(ifs2.RemoveByUser)

	nicInfos := ns.stack.NICInfo()

	nicInfo1, ok := nicInfos[ifs1.nicid]
	if !ok {
		t.Fatalf("stack.NICInfo()[%d] = (_, false)", ifs1.nicid)
	}
	nicInfo2, ok := nicInfos[ifs2.nicid]
	if !ok {
		t.Fatalf("stack.NICInfo()[%d]: (_, false)", ifs2.nicid)
	}

	if nicInfo1.Name == nicInfo2.Name {
		t.Fatalf("got (%+v).Name == (%+v).Name, want non-equal", nicInfo1, nicInfo2)
	}
}

func TestStaticIPConfiguration(t *testing.T) {
	ns, _ := newNetstack(t, netstackTestOptions{})

	addr := fidlconv.ToNetIpAddress(testV4Address)
	ifAddr := fidlnet.Subnet{Addr: addr, PrefixLen: 32}
	for _, test := range []struct {
		name     string
		features ethernet.Features
	}{
		{name: "default"},
		{name: "wlan", features: ethernet.FeaturesWlan},
	} {
		t.Run(test.name, func(t *testing.T) {
			d, _ := testutil.MakeEthernetDevice(t, ethernet.Info{
				Features: test.features,
				Mtu:      1400,
			}, 1)
			ifs, err := ns.addEth(testTopoPath, netstack.InterfaceConfig{Name: t.Name()}, &d)
			if err != nil {
				t.Fatal(err)
			}
			defer ifs.RemoveByUser()

			onlineChanged := make(chan bool, 1)
			ifs.observer.SetOnLinkOnlineChanged(func(linkOnline bool) {
				ifs.onLinkOnlineChanged(linkOnline)
				onlineChanged <- linkOnline
			})

			name := ifs.ns.name(ifs.nicid)
			result := ns.addInterfaceAddr(uint64(ifs.nicid), ifAddr)
			if result != stack.StackAddInterfaceAddressDeprecatedResultWithResponse(stack.StackAddInterfaceAddressDeprecatedResponse{}) {
				t.Fatalf("got ns.addInterfaceAddr(%d, %#v) = %#v, want = Response()", ifs.nicid, ifAddr, result)
			}

			if mainAddr, err := ns.stack.GetMainNICAddress(ifs.nicid, ipv4.ProtocolNumber); err != nil {
				t.Errorf("stack.GetMainNICAddress(%d, ipv4.ProtocolNumber): %s", ifs.nicid, err)
			} else if got := mainAddr.Address; got != testV4Address {
				t.Errorf("got stack.GetMainNICAddress(%d, ipv4.ProtocolNumber).Addr = %s, want = %s", ifs.nicid, got, testV4Address)
			}

			ifs.mu.Lock()
			if ifs.mu.dhcp.enabled {
				t.Error("expected dhcp state to be disabled initially")
			}
			ifs.mu.Unlock()

			if err := ifs.Down(); err != nil {
				t.Fatal(err)
			}

			ifs.mu.Lock()
			if ifs.mu.dhcp.enabled {
				t.Error("expected dhcp state to remain disabled after bringing interface down")
			}
			if ifs.mu.dhcp.running() {
				t.Error("expected dhcp state to remain stopped after bringing interface down")
			}
			ifs.mu.Unlock()

			if err := ifs.Up(); err != nil {
				t.Fatal(err)
			}
			if got, want := <-onlineChanged; got != want {
				t.Errorf("got state = %t, want %t", got, want)
			}

			ifs.mu.Lock()
			if ifs.mu.dhcp.enabled {
				t.Error("expected dhcp state to remain disabled after restarting interface")
			}
			ifs.mu.Unlock()

			ifs.setDHCPStatus(name, true)

			ifs.mu.Lock()
			if !ifs.mu.dhcp.enabled {
				t.Error("expected dhcp state to become enabled after manually enabling it")
			}
			if !ifs.mu.dhcp.running() {
				t.Error("expected dhcp state running")
			}
			ifs.mu.Unlock()
		})
	}
}

var _ NICRemovedHandler = (*noopNicRemovedHandler)(nil)

type noopNicRemovedHandler struct{}

func (*noopNicRemovedHandler) RemovedNIC(tcpip.NICID) {}

type netstackTestOptions struct {
	nicRemovedHandler  NICRemovedHandler
	ndpDisp            ipv6.NDPDispatcher
	interfaceEventChan chan<- interfaceEvent
}

func newNetstack(t *testing.T, options netstackTestOptions) (*Netstack, *faketime.ManualClock) {
	t.Helper()

	clock := faketime.NewManualClock()

	stk := tcpipstack.New(tcpipstack.Options{
		NetworkProtocols: []tcpipstack.NetworkProtocolFactory{
			arp.NewProtocol,
			ipv4.NewProtocol,
			ipv6.NewProtocolWithOptions(ipv6.Options{
				NDPDisp: options.ndpDisp,
			}),
		},
		TransportProtocols: []tcpipstack.TransportProtocolFactory{
			tcp.NewProtocol,
			udp.NewProtocol,
		},
		Clock: clock,
	})

	interfaceEventChan := options.interfaceEventChan
	if interfaceEventChan == nil {
		ch := make(chan interfaceEvent)
		go func() {
			for range ch {
			}
		}()
		interfaceEventChan = ch
	}
	ns := &Netstack{
		stack: stk,
		// Required initialization because adding/removing interfaces interacts with
		// DNS configuration.
		dnsConfig: dns.MakeServersConfig(stk.Clock()),
		nicRemovedHandlers: []NICRemovedHandler{func() NICRemovedHandler {
			if h := options.nicRemovedHandler; h != nil {
				return h
			}
			return &noopNicRemovedHandler{}

		}()},
		interfaceEventChan: interfaceEventChan,
	}
	if ndpDisp, ok := options.ndpDisp.(*ndpDispatcher); ok {
		ndpDisp.ns = ns
		ndpDisp.dynamicAddressSourceTracker.init(ns)
	}

	t.Cleanup(func() {
		for _, nic := range ns.stack.NICInfo() {
			ifs := nic.Context.(*ifState)
			ifs.RemoveByUser()
			ifs.endpoint.Wait()
		}
	})
	return ns, clock
}

func getInterfaceAddresses(t *testing.T, ni *stackImpl, nicid tcpip.NICID) []tcpip.AddressWithPrefix {
	t.Helper()
	nicInfos := ni.ns.stack.NICInfo()
	nicInfo, ok := nicInfos[nicid]
	if !ok {
		t.Fatalf("couldn't find NICID=%d in %#v", nicid, nicInfos)
	}
	addrs := make([]tcpip.AddressWithPrefix, len(nicInfo.ProtocolAddresses))
	for i := range nicInfo.ProtocolAddresses {
		addrs[i] = nicInfo.ProtocolAddresses[i].AddressWithPrefix
	}
	return addrs
}

func compareInterfaceAddresses(t *testing.T, got, want []tcpip.AddressWithPrefix) {
	t.Helper()
	sort.Slice(got, func(i, j int) bool { return got[i].Address < got[j].Address })
	sort.Slice(want, func(i, j int) bool { return want[i].Address < want[j].Address })
	if diff := cmp.Diff(got, want); diff != "" {
		t.Errorf("Interface addresses mismatch (-want +got):\n%s", diff)
	}
}

// Test adding a list of both IPV4 and IPV6 addresses and then removing them
// again one-by-one.
func TestListInterfaceAddresses(t *testing.T) {
	ndpDisp := testNDPDispatcher{
		dadC: make(chan ndpDADEvent, 1),
	}
	ns, clock := newNetstack(t, netstackTestOptions{ndpDisp: &ndpDisp})
	ni := &stackImpl{ns: ns}

	ep := noopEndpoint{
		linkAddress: tcpip.LinkAddress([]byte{2, 3, 4, 5, 6, 7}),
	}
	ifState, err := ns.addEndpoint(
		func(tcpip.NICID) string { return t.Name() },
		&ep,
		&noopController{},
		nil, /* observer */
		0,   /* metric */
	)
	if err != nil {
		t.Fatal(err)
	}
	if err := ifState.Up(); err != nil {
		t.Fatal("ifState.Up(): ", err)
	}

	// Wait for and account for any addresses added automatically.
	clock.Advance(dadResolutionTimeout)
	for {
		select {
		case d := <-ndpDisp.dadC:
			t.Logf("startup DAD event: %#v", d)
			continue
		default:
		}
		break
	}

	wantAddrs := getInterfaceAddresses(t, ni, ifState.nicid)

	testAddresses := []tcpip.AddressWithPrefix{
		{"\x01\x01\x01\x01", 32},
		{"\x02\x02\x02\x02", 24},
		{"\x03\x03\x03\x03", 16},
		{"\x04\x04\x04\x04", 8},
		{"\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01", 128},
		{"\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02", 64},
		{"\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03", 32},
		{"\x04\x04\x04\x04\x04\x04\x04\x04\x04\x04\x04\x04\x04\x04\x04\x04", 8},
	}

	t.Run("Add", func(t *testing.T) {
		for _, addr := range testAddresses {
			t.Run(addr.String(), func(t *testing.T) {
				ifAddr := fidlnet.Subnet{
					Addr:      fidlconv.ToNetIpAddress(addr.Address),
					PrefixLen: uint8(addr.PrefixLen),
				}

				result, err := ni.AddInterfaceAddressDeprecated(context.Background(), uint64(ifState.nicid), ifAddr)
				if err != nil {
					t.Fatalf("ni.AddInterfaceAddressDeprecated(%d, %#v): %s", ifState.nicid, ifAddr, err)
				}
				if result != stack.StackAddInterfaceAddressDeprecatedResultWithResponse(stack.StackAddInterfaceAddressDeprecatedResponse{}) {
					t.Fatalf("got ni.AddInterfaceAddressDeprecated(%d, %#v) = %#v, want = Response()", ifState.nicid, ifAddr, result)
				}
				expectDad := header.IsV6UnicastAddress(addr.Address)
				clock.Advance(dadResolutionTimeout)
				select {
				case d := <-ndpDisp.dadC:
					if !expectDad {
						t.Fatalf("unexpected DAD event: %#v", d)
					}
					if diff := cmp.Diff(ndpDADEvent{nicID: ifState.nicid, addr: addr.Address, result: &tcpipstack.DADSucceeded{}}, d, cmp.AllowUnexported(d)); diff != "" {
						t.Fatalf("ndp DAD event mismatch (-want +got):\n%s", diff)
					}
				default:
					if expectDad {
						t.Fatal("timed out waiting for DAD event")
					}
				}
				wantAddrs = append(wantAddrs, addr)
				gotAddrs := getInterfaceAddresses(t, ni, ifState.nicid)

				compareInterfaceAddresses(t, gotAddrs, wantAddrs)
			})
		}
	})

	t.Run("Remove", func(t *testing.T) {
		for _, addr := range testAddresses {
			t.Run(addr.String(), func(t *testing.T) {
				ifAddr := fidlnet.Subnet{
					Addr:      fidlconv.ToNetIpAddress(addr.Address),
					PrefixLen: uint8(addr.PrefixLen),
				}

				result, err := ni.DelInterfaceAddressDeprecated(context.Background(), uint64(ifState.nicid), ifAddr)
				if err != nil {
					t.Fatalf("ni.DelInterfaceAddressDeprecated(%d, %#v): %s", ifState.nicid, ifAddr, err)
				}
				if result != stack.StackDelInterfaceAddressDeprecatedResultWithResponse(stack.StackDelInterfaceAddressDeprecatedResponse{}) {
					t.Fatalf("got ni.DelInterfaceAddressDeprecated(%d, %#v) = %#v, want = Response()", ifState.nicid, ifAddr, result)
				}

				// Remove address from list.
				for i, a := range wantAddrs {
					if a == addr {
						wantAddrs = append(wantAddrs[:i], wantAddrs[i+1:]...)
						break
					}
				}
				gotAddrs := getInterfaceAddresses(t, ni, ifState.nicid)
				compareInterfaceAddresses(t, gotAddrs, wantAddrs)
			})
		}
	})
}

// Test that adding an address with one prefix and then adding the same address
// but with a different prefix will simply replace the first address.
func TestAddAddressesThenChangePrefix(t *testing.T) {
	ns, _ := newNetstack(t, netstackTestOptions{})
	ni := &stackImpl{ns: ns}
	ifState := addNoopEndpoint(t, ns, "")
	t.Cleanup(ifState.RemoveByUser)

	// The call to ns.addEndpoint() added addresses to the stack. Make sure we include
	// those in our want list.
	initialAddrs := getInterfaceAddresses(t, ni, ifState.nicid)

	// Add address.
	addr := tcpip.AddressWithPrefix{Address: "\x01\x01\x01\x01", PrefixLen: 8}
	ifAddr := fidlnet.Subnet{
		Addr:      fidlconv.ToNetIpAddress(addr.Address),
		PrefixLen: uint8(addr.PrefixLen),
	}

	result, err := ni.AddInterfaceAddressDeprecated(context.Background(), uint64(ifState.nicid), ifAddr)
	if err != nil {
		t.Fatalf("ni.AddInterfaceAddressDeprecated(%d, %#v): %s", ifState.nicid, ifAddr, err)
	}
	if result != stack.StackAddInterfaceAddressDeprecatedResultWithResponse(stack.StackAddInterfaceAddressDeprecatedResponse{}) {
		t.Fatalf("got ni.AddInterfaceAddressDeprecated(%d, %#v) = %#v, want = Response()", ifState.nicid, ifAddr, result)
	}

	wantAddrs := append(initialAddrs, addr)
	gotAddrs := getInterfaceAddresses(t, ni, ifState.nicid)
	compareInterfaceAddresses(t, gotAddrs, wantAddrs)

	// Add the same address with a different prefix.
	addr.PrefixLen *= 2
	ifAddr.PrefixLen *= 2

	result, err = ni.AddInterfaceAddressDeprecated(context.Background(), uint64(ifState.nicid), ifAddr)
	if err != nil {
		t.Fatalf("ni.AddInterfaceAddressDeprecated(%d, %#v): %s", ifState.nicid, ifAddr, err)
	}
	if result != stack.StackAddInterfaceAddressDeprecatedResultWithResponse(stack.StackAddInterfaceAddressDeprecatedResponse{}) {
		t.Fatalf("got ni.AddInterfaceAddressDeprecated(%d, %#v) = %#v, want = Response()", ifState.nicid, ifAddr, result)
	}

	wantAddrs = append(initialAddrs, addr)
	gotAddrs = getInterfaceAddresses(t, ni, ifState.nicid)

	compareInterfaceAddresses(t, gotAddrs, wantAddrs)
}

func TestAddRouteParameterValidation(t *testing.T) {
	ns, _ := newNetstack(t, netstackTestOptions{})
	addr := tcpip.ProtocolAddress{
		Protocol: ipv4.ProtocolNumber,
		AddressWithPrefix: tcpip.AddressWithPrefix{
			Address:   tcpip.Address("\xf0\xf0\xf0\xf0"),
			PrefixLen: 24,
		},
	}
	subnetLocalAddress := tcpip.Address("\xf0\xf0\xf0\xf1")
	ifState := addNoopEndpoint(t, ns, "")
	t.Cleanup(ifState.RemoveByUser)

	if ok, reason := ifState.addAddress(addr, tcpipstack.AddressProperties{}); !ok {
		t.Fatalf("ifState.addAddress(%s, {}): %s", addr.AddressWithPrefix, reason)
	}
	route := addressWithPrefixRoute(ifState.nicid, addr.AddressWithPrefix)
	if err := ns.AddRoute(route, metricNotSet /* dynamic */, false); err != nil {
		t.Fatalf("ns.AddRoute(%s, 0, false): %s", route, err)
	}

	tests := []struct {
		name    string
		route   tcpip.Route
		metric  routes.Metric
		dynamic bool
		err     error
	}{
		{
			name: "IPv4 destination no NIC invalid gateway",
			route: tcpip.Route{
				Destination: util.PointSubnet(testV4Address),
				Gateway:     testV4Address,
				NIC:         0,
			},
			metric: routes.Metric(0),
			err:    routes.ErrNoSuchNIC,
		},
		{
			name: "IPv6 destination no NIC invalid gateway",
			route: tcpip.Route{
				Destination: util.PointSubnet(testV6Address),
				Gateway:     testV6Address,
				NIC:         0,
			},
			metric: routes.Metric(0),
			err:    routes.ErrNoSuchNIC,
		},
		{
			name: "IPv4 destination no NIC valid gateway",
			route: tcpip.Route{
				Destination: util.PointSubnet(testV4Address),
				Gateway:     subnetLocalAddress,
				NIC:         0,
			},
		},
		{
			name: "zero length gateway",
			route: tcpip.Route{
				Destination: util.PointSubnet(testV4Address),
				NIC:         ifState.nicid,
			},
		},
	}

	for _, test := range tests {
		t.Run(test.name, func(t *testing.T) {
			if err := ns.AddRoute(test.route, test.metric, test.dynamic); !errors.Is(err, test.err) {
				t.Errorf("got ns.AddRoute(...) = %v, want %v", err, test.err)
			}
		})
	}
}

func TestDHCPAcquired(t *testing.T) {
	ns, _ := newNetstack(t, netstackTestOptions{})
	ifState := addNoopEndpoint(t, ns, "")
	t.Cleanup(ifState.RemoveByUser)

	addressBytes := []byte(testV4Address)
	nextAddress := func() tcpip.Address {
		addressBytes[len(addressBytes)-1]++
		return tcpip.Address(addressBytes)
	}

	serverAddress := nextAddress()
	router1Address := nextAddress()
	router2Address := nextAddress()
	multicastAddress := net.IPv4(0xe8, 0x2b, 0xd3, 0xea)
	if !multicastAddress.IsMulticast() {
		t.Fatalf("%s is not a multicast address", multicastAddress)
	}

	defaultMask := net.IP(testV4Address).DefaultMask()
	prefixLen, _ := defaultMask.Size()

	destination1, err := tcpip.NewSubnet(util.Parse("192.168.42.0"), tcpip.AddressMask(util.Parse("255.255.255.0")))
	if err != nil {
		t.Fatal(err)
	}
	destination2, err := tcpip.NewSubnet(util.Parse("0.0.0.0"), tcpip.AddressMask(util.Parse("0.0.0.0")))
	if err != nil {
		t.Fatal(err)
	}

	tests := []struct {
		name               string
		oldAddr, newAddr   tcpip.AddressWithPrefix
		config             dhcp.Config
		expectedRouteTable []routes.ExtendedRoute
	}{
		{
			name:    "subnet mask provided",
			oldAddr: tcpip.AddressWithPrefix{},
			newAddr: tcpip.AddressWithPrefix{
				Address:   testV4Address,
				PrefixLen: prefixLen,
			},
			config: dhcp.Config{
				ServerAddress: serverAddress,
				Router: []tcpip.Address{
					router1Address,
					router2Address,
					header.IPv4Any,
					header.IPv4Broadcast,
					tcpip.Address(multicastAddress),
				},
				SubnetMask: tcpip.AddressMask(defaultMask),
				DNS: []tcpip.Address{
					router1Address,
					router2Address,
				},
				LeaseLength: dhcp.Seconds(60),
			},
			expectedRouteTable: []routes.ExtendedRoute{
				{
					Route: tcpip.Route{
						Destination: destination1,
						NIC:         1,
					},
					Prf:                   routes.MediumPreference,
					Metric:                0,
					MetricTracksInterface: true,
					Dynamic:               true,
					Enabled:               false,
				},
				{
					Route: tcpip.Route{
						Destination: destination2,
						Gateway:     util.Parse("192.168.42.18"),
						NIC:         1,
					},
					Prf:                   routes.MediumPreference,
					Metric:                0,
					MetricTracksInterface: true,
					Dynamic:               true,
					Enabled:               false,
				},
				{
					Route: tcpip.Route{
						Destination: destination2,
						Gateway:     util.Parse("192.168.42.19"),
						NIC:         1,
					},
					Prf:                   routes.MediumPreference,
					Metric:                0,
					MetricTracksInterface: true,
					Dynamic:               true,
					Enabled:               false,
				},
			},
		},
		{
			name:    "no routers",
			oldAddr: tcpip.AddressWithPrefix{},
			newAddr: tcpip.AddressWithPrefix{
				Address:   testV4Address,
				PrefixLen: prefixLen,
			},
			config: dhcp.Config{},
			expectedRouteTable: []routes.ExtendedRoute{
				{
					Route: tcpip.Route{
						Destination: destination1,
						NIC:         1,
					},
					Prf:                   routes.MediumPreference,
					Metric:                0,
					MetricTracksInterface: true,
					Dynamic:               true,
					Enabled:               false,
				},
			},
		},
	}

	for _, test := range tests {
		t.Run(test.name, func(t *testing.T) {
			// save current route table for later
			originalRouteTable := ifState.ns.GetExtendedRouteTable()

			// Update the DHCP address to the given test values and verify it took
			// effect.
			ifState.dhcpAcquired(context.Background(), test.oldAddr, test.newAddr, test.config)

			if diff := cmp.Diff(ifState.dns.mu.servers, test.config.DNS); diff != "" {
				t.Errorf("ifState.mu.dnsServers mismatch (-want +got):\n%s", diff)
			}

			if diff := cmp.Diff(ifState.ns.GetExtendedRouteTable(), test.expectedRouteTable, cmp.AllowUnexported(tcpip.Subnet{})); diff != "" {
				t.Errorf("GetExtendedRouteTable() mismatch (-want +got):\n%s", diff)
			}

			infoMap := ns.stack.NICInfo()
			if info, ok := infoMap[ifState.nicid]; ok {
				found := false
				for _, address := range info.ProtocolAddresses {
					if address.Protocol == ipv4.ProtocolNumber {
						switch address.AddressWithPrefix {
						case test.oldAddr:
							t.Errorf("expired address %s was not removed from NIC addresses %v", test.oldAddr, info.ProtocolAddresses)
						case test.newAddr:
							found = true
						}
					}
				}

				if !found {
					t.Errorf("new address %s was not added to NIC addresses %v", test.newAddr, info.ProtocolAddresses)
				}
			} else {
				t.Errorf("NIC %d not found in %v", ifState.nicid, infoMap)
			}

			// Remove the address and verify everything is cleaned up correctly.
			remAddr := test.newAddr
			ifState.dhcpAcquired(context.Background(), remAddr, tcpip.AddressWithPrefix{}, dhcp.Config{})

			if diff := cmp.Diff(ifState.dns.mu.servers, ifState.dns.mu.servers[:0]); diff != "" {
				t.Errorf("ifState.mu.dnsServers mismatch (-want +got):\n%s", diff)
			}

			if diff := cmp.Diff(ifState.ns.GetExtendedRouteTable(), originalRouteTable); diff != "" {
				t.Errorf("GetExtendedRouteTable() mismatch (-want +got):\n%s", diff)
			}

			infoMap = ns.stack.NICInfo()
			if info, ok := infoMap[ifState.nicid]; ok {
				for _, address := range info.ProtocolAddresses {
					if address.Protocol == ipv4.ProtocolNumber {
						if address.AddressWithPrefix == remAddr {
							t.Errorf("address %s/%d was not removed from NIC addresses %v", remAddr.Address, remAddr.PrefixLen, info.ProtocolAddresses)
						}
					}
				}
			} else {
				t.Errorf("NIC %d not found in %v", ifState.nicid, infoMap)
			}
		})
	}
}
