[netstack] Move eth.Controller to the link package

The link package is currently empty, and the bridge package's dependency
on the eth package makes it not possible to run the bridge tests as a
host test.

In addition, there's nothing ethernet-specific about these lifecycle
methods or states - "link.Controller" and "link.State" are better names
for these anyway.

Tested: CQ
Change-Id: I3b2d31fe8391a717d11a5525360c8e1e121c3039
diff --git a/go/src/netstack/fuchsia_net_stack.go b/go/src/netstack/fuchsia_net_stack.go
index 6b35875..287849e 100644
--- a/go/src/netstack/fuchsia_net_stack.go
+++ b/go/src/netstack/fuchsia_net_stack.go
@@ -9,7 +9,7 @@
 	"sort"
 
 	"netstack/fidlconv"
-	"netstack/link/eth"
+	"netstack/link"
 
 	"fidl/fuchsia/hardware/ethernet"
 	"fidl/fuchsia/net"
@@ -41,7 +41,7 @@
 	// TODO(tkilbourn): distinguish between enabled and link up
 	enablementStatus := stack.EnablementStatusDisabled
 	physicalStatus := stack.PhysicalStatusDown
-	if ifs.mu.state == eth.StateStarted {
+	if ifs.mu.state == link.StateStarted {
 		enablementStatus = stack.EnablementStatusEnabled
 		physicalStatus = stack.PhysicalStatusUp
 	}
diff --git a/go/src/netstack/link/bridge/bridge.go b/go/src/netstack/link/bridge/bridge.go
index e4f196f..a584dc1 100644
--- a/go/src/netstack/link/bridge/bridge.go
+++ b/go/src/netstack/link/bridge/bridge.go
@@ -8,7 +8,7 @@
 	"strings"
 	"sync"
 
-	"netstack/link/eth"
+	"netstack/link"
 
 	"github.com/google/netstack/tcpip"
 	"github.com/google/netstack/tcpip/buffer"
@@ -17,7 +17,7 @@
 
 var _ stack.LinkEndpoint = (*Endpoint)(nil)
 var _ stack.NetworkDispatcher = (*Endpoint)(nil)
-var _ eth.Controller = (*Endpoint)(nil)
+var _ link.Controller = (*Endpoint)(nil)
 
 type Endpoint struct {
 	links           map[tcpip.LinkAddress]*BridgeableEndpoint
@@ -28,7 +28,7 @@
 	linkAddress     tcpip.LinkAddress
 	mu              struct {
 		sync.Mutex
-		onStateChange func(eth.State)
+		onStateChange func(link.State)
 	}
 }
 
@@ -89,7 +89,7 @@
 	ep.mu.Unlock()
 
 	if onStateChange != nil {
-		onStateChange(eth.StateStarted)
+		onStateChange(link.StateStarted)
 	}
 
 	return nil
@@ -102,7 +102,7 @@
 // implementation directly.
 //
 // Down and Close are the same, except they call the OnStateChange callback
-// with eth.StateDown and eth.StateClose respectively.
+// with link.StateDown and link.StateClose respectively.
 func (ep *Endpoint) Down() error {
 	for _, l := range ep.links {
 		l.SetBridge(nil)
@@ -113,7 +113,7 @@
 	ep.mu.Unlock()
 
 	if onStateChange != nil {
-		onStateChange(eth.StateDown)
+		onStateChange(link.StateDown)
 	}
 
 	return nil
@@ -126,7 +126,7 @@
 // implementation directly.
 //
 // Down and Close are the same, except they call the OnStateChange callback
-// with eth.StateDown and eth.StateClose respectively.
+// with link.StateDown and link.StateClose respectively.
 func (ep *Endpoint) Close() error {
 	for _, l := range ep.links {
 		l.SetBridge(nil)
@@ -137,13 +137,13 @@
 	ep.mu.Unlock()
 
 	if onStateChange != nil {
-		onStateChange(eth.StateClosed)
+		onStateChange(link.StateClosed)
 	}
 
 	return nil
 }
 
-func (ep *Endpoint) SetOnStateChange(f func(eth.State)) {
+func (ep *Endpoint) SetOnStateChange(f func(link.State)) {
 	ep.mu.Lock()
 	defer ep.mu.Unlock()
 
diff --git a/go/src/netstack/link/controller.go b/go/src/netstack/link/controller.go
new file mode 100644
index 0000000..47715da
--- /dev/null
+++ b/go/src/netstack/link/controller.go
@@ -0,0 +1,46 @@
+// Copyright 2019 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.
+
+package link
+
+import (
+  "fmt"
+)
+
+type State int
+
+const (
+	StateUnknown State = iota
+	StateStarted
+	StateDown
+	StateClosed
+)
+
+type Controller interface {
+	Up() error
+	Down() error
+	Close() error
+	SetOnStateChange(func(State))
+
+	// TODO(stijlist): remove all callers of this method;
+	// not all interfaces are backed by a topological path
+	// (e.g. loopback, bridge).
+	Path() string
+	SetPromiscuousMode(bool) error
+}
+
+func (s State) String() string {
+	switch s {
+	case StateUnknown:
+		return "link unknown state"
+	case StateStarted:
+		return "link started"
+	case StateDown:
+		return "link down"
+	case StateClosed:
+		return "link stopped"
+	default:
+		return fmt.Sprintf("link bad state (%d)", s)
+	}
+}
diff --git a/go/src/netstack/link/eth/client.go b/go/src/netstack/link/eth/client.go
index 55c67a4..902e407 100644
--- a/go/src/netstack/link/eth/client.go
+++ b/go/src/netstack/link/eth/client.go
@@ -49,6 +49,7 @@
 	"syscall/zx/zxwait"
 	"unsafe"
 
+	"netstack/link"
 	"netstack/trace"
 
 	"fidl/fuchsia/hardware/ethernet"
@@ -56,7 +57,7 @@
 
 const ZXSIO_ETH_SIGNAL_STATUS = zx.SignalUser0
 
-var _ Controller = (*Client)(nil)
+var _ link.Controller = (*Client)(nil)
 
 // A Client is an ethernet client.
 // It connects to a zircon ethernet driver using a FIFO-based protocol.
@@ -69,8 +70,8 @@
 	path   string
 
 	mu        sync.Mutex
-	state     State
-	stateFunc func(State)
+	state     link.State
+	stateFunc func(link.State)
 	arena     *Arena
 	tmpbuf    []ethernet.FifoEntry // used to fill rx and drain tx
 	recvbuf   []ethernet.FifoEntry // packets received
@@ -148,7 +149,7 @@
 	return c, nil
 }
 
-func (c *Client) SetOnStateChange(f func(State)) {
+func (c *Client) SetOnStateChange(f func(link.State)) {
 	c.mu.Lock()
 	defer c.mu.Unlock()
 	c.stateFunc = f
@@ -158,7 +159,7 @@
 	return c.path
 }
 
-func (c *Client) changeStateLocked(s State) {
+func (c *Client) changeStateLocked(s link.State) {
 	c.state = s
 	if fn := c.stateFunc; fn != nil {
 		fn(s)
@@ -169,13 +170,13 @@
 func (c *Client) Up() error {
 	c.mu.Lock()
 	defer c.mu.Unlock()
-	if c.state != StateStarted {
+	if c.state != link.StateStarted {
 		if status, err := c.device.Start(); err != nil {
 			return err
 		} else if err := checkStatus(status, "Start"); err != nil {
 			return err
 		}
-		c.changeStateLocked(StateStarted)
+		c.changeStateLocked(link.StateStarted)
 	}
 
 	return nil
@@ -185,11 +186,11 @@
 func (c *Client) Down() error {
 	c.mu.Lock()
 	defer c.mu.Unlock()
-	if c.state != StateDown {
+	if c.state != link.StateDown {
 		if err := c.device.Stop(); err != nil {
 			return err
 		}
-		c.changeStateLocked(StateDown)
+		c.changeStateLocked(link.StateDown)
 	}
 	return nil
 }
@@ -202,7 +203,7 @@
 }
 
 func (c *Client) closeLocked() error {
-	if c.state == StateClosed {
+	if c.state == link.StateClosed {
 		return nil
 	}
 	err := c.device.Stop()
@@ -216,7 +217,7 @@
 	c.recvbuf = c.recvbuf[:0]
 	c.sendbuf = c.sendbuf[:0]
 	c.arena.freeAll(c)
-	c.changeStateLocked(StateClosed)
+	c.changeStateLocked(link.StateClosed)
 
 	return err
 }
@@ -413,9 +414,9 @@
 				c.mu.Lock()
 				switch status {
 				case LinkDown:
-					c.changeStateLocked(StateDown)
+					c.changeStateLocked(link.StateDown)
 				case LinkUp:
-					c.changeStateLocked(StateStarted)
+					c.changeStateLocked(link.StateStarted)
 				}
 				c.mu.Unlock()
 
@@ -450,27 +451,3 @@
 	status, err := c.device.GetStatus()
 	return LinkStatus(status & ethernet.DeviceStatusOnline), err
 }
-
-type State int
-
-const (
-	StateUnknown State = iota
-	StateStarted
-	StateDown
-	StateClosed
-)
-
-func (s State) String() string {
-	switch s {
-	case StateUnknown:
-		return "eth unknown state"
-	case StateStarted:
-		return "eth started"
-	case StateDown:
-		return "eth down"
-	case StateClosed:
-		return "eth stopped"
-	default:
-		return fmt.Sprintf("eth bad state (%d)", s)
-	}
-}
diff --git a/go/src/netstack/link/eth/controller.go b/go/src/netstack/link/eth/controller.go
deleted file mode 100644
index 6a6317c..0000000
--- a/go/src/netstack/link/eth/controller.go
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 2019 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.
-
-package eth
-
-type Controller interface {
-	Up() error
-	Down() error
-	Close() error
-	SetOnStateChange(func(State))
-
-	// TODO(stijlist): remove all callers of this method;
-	// not all interfaces are backed by a topological path
-	// (e.g. loopback, bridge).
-	Path() string
-	SetPromiscuousMode(bool) error
-}
diff --git a/go/src/netstack/netstack.go b/go/src/netstack/netstack.go
index 04e5fc9..000eb1b 100644
--- a/go/src/netstack/netstack.go
+++ b/go/src/netstack/netstack.go
@@ -15,6 +15,7 @@
 	"netstack/dns"
 	"netstack/fidlconv"
 	"netstack/filter"
+	"netstack/link"
 	"netstack/link/bridge"
 	"netstack/link/eth"
 	"netstack/link/stats"
@@ -75,10 +76,10 @@
 // Each ifState tracks the state of a network interface.
 type ifState struct {
 	ns  *Netstack
-	eth eth.Controller
+	eth link.Controller
 	mu  struct {
 		sync.Mutex
-		state eth.State
+		state link.State
 		// TODO(NET-1223): remove and replace with refs to stack via ns
 		nic *netiface.NIC
 		dhcpState
@@ -270,14 +271,14 @@
 	d.enabled = enabled
 }
 
-func (ifs *ifState) stateChange(s eth.State) {
+func (ifs *ifState) stateChange(s link.State) {
 	ifs.ns.mu.Lock()
 	ifs.mu.Lock()
 	switch s {
-	case eth.StateClosed:
+	case link.StateClosed:
 		delete(ifs.ns.mu.ifStates, ifs.mu.nic.ID)
 		fallthrough
-	case eth.StateDown:
+	case link.StateDown:
 		log.Printf("NIC %s: stopped", ifs.mu.nic.Name)
 		if ifs.cancel != nil {
 			ifs.cancel()
@@ -296,9 +297,9 @@
 		ifs.mu.nic.Addr = "\x00\x00\x00\x00"
 		ifs.mu.nic.DNSServers = nil
 
-	case eth.StateStarted:
+	case link.StateStarted:
 		// Only call `restarted` if we are not in the initial state (which means we're still starting).
-		if ifs.mu.state != eth.StateUnknown {
+		if ifs.mu.state != link.StateUnknown {
 			log.Printf("NIC %s: restarting", ifs.mu.nic.Name)
 			ifs.ctx, ifs.cancel = context.WithCancel(context.Background())
 			ifs.mu.nic.Routes = defaultRouteTable(ifs.mu.nic.ID, "")
@@ -438,7 +439,7 @@
 		cancel: cancel,
 	}
 
-	ifs.mu.state = eth.StateStarted
+	ifs.mu.state = link.StateStarted
 	ifs.mu.nic = nic
 
 	ns.mu.Lock()
@@ -540,7 +541,7 @@
 		ctx:    ctx,
 		cancel: cancel,
 	}
-	ifs.mu.state = eth.StateUnknown
+	ifs.mu.state = link.StateUnknown
 	ifs.mu.nic = &netiface.NIC{
 		Addr:    "\x00\x00\x00\x00",
 		Netmask: "\xff\xff\xff\xff",
diff --git a/go/src/netstack/netstack_service.go b/go/src/netstack/netstack_service.go
index 4d37b48..c9785bd 100644
--- a/go/src/netstack/netstack_service.go
+++ b/go/src/netstack/netstack_service.go
@@ -13,7 +13,7 @@
 	"syscall/zx/zxwait"
 
 	"netstack/fidlconv"
-	"netstack/link/eth"
+	"netstack/link"
 
 	"fidl/fuchsia/hardware/ethernet"
 	"fidl/fuchsia/net"
@@ -64,7 +64,7 @@
 	}
 
 	var flags uint32
-	if ifs.mu.state == eth.StateStarted {
+	if ifs.mu.state == link.StateStarted {
 		flags |= netstack.NetInterfaceFlagUp
 	}
 	if ifs.mu.dhcpState.enabled {