// Copyright 2020 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

package netstack

import (
	"context"
	"fmt"
	"strings"
	"sync/atomic"
	"syscall/zx"
	"syscall/zx/fidl"

	"go.fuchsia.dev/fuchsia/src/connectivity/network/netstack/fidlconv"
	"go.fuchsia.dev/fuchsia/src/connectivity/network/netstack/routes"
	"go.fuchsia.dev/fuchsia/src/connectivity/network/netstack/routetypes"
	"go.fuchsia.dev/fuchsia/src/connectivity/network/netstack/sync"
	"go.fuchsia.dev/fuchsia/src/lib/component"
	syslog "go.fuchsia.dev/fuchsia/src/lib/syslog/go"

	"fidl/fuchsia/net"
	fnetRoutes "fidl/fuchsia/net/routes"

	"gvisor.dev/gvisor/pkg/tcpip"
	"gvisor.dev/gvisor/pkg/tcpip/stack"
)

const routesFidlName = "fuchsia.net.routes"
const watcherV4ProtocolName = "fuchsia.net.routes.WatcherV4"
const watcherV6ProtocolName = "fuchsia.net.routes.WatcherV6"

var _ fnetRoutes.StateWithCtx = (*resolveImpl)(nil)

// resolveImpl provides an implementation for fuchsia.net.routes/State.
type resolveImpl struct {
	stack *stack.Stack
}

var _ fnetRoutes.StateV4WithCtx = (*getWatcherImpl)(nil)
var _ fnetRoutes.StateV6WithCtx = (*getWatcherImpl)(nil)

// getWatcherImpl provides implementations for fuchsia.net.routes/StateV4 and
// fuchsia.net.routes/State.V6.
type getWatcherImpl struct {
	interruptChan chan<- routeInterrupt
}

func (r *resolveImpl) Resolve(ctx fidl.Context, destination net.IpAddress) (fnetRoutes.StateResolveResult, error) {
	const unspecifiedNIC = tcpip.NICID(0)
	var unspecifiedLocalAddress tcpip.Address

	remote, proto := fidlconv.ToTCPIPAddressAndProtocolNumber(destination)
	netProtoName := strings.TrimPrefix(networkProtocolToString(proto), "IP")
	var flags string
	syslogFn := syslog.DebugTf
	if remote.Unspecified() {
		flags = "U"
		syslogFn = syslog.InfoTf
	}
	logFn := func(suffix string, err tcpip.Error) {
		_ = syslogFn(
			routesFidlName, "stack.FindRoute(%s (%s|%s))%s = (_, %s)",
			remote,
			netProtoName,
			flags,
			suffix,
			err,
		)
	}

	route, err := r.stack.FindRoute(unspecifiedNIC, unspecifiedLocalAddress, remote, proto, false /* multicastLoop */)
	if err != nil {
		logFn("", err)
		return fnetRoutes.StateResolveResultWithErr(int32(WrapTcpIpError(err).ToZxStatus())), nil
	}
	defer route.Release()

	return func() fnetRoutes.StateResolveResult {
		ch := make(chan stack.ResolvedFieldsResult, 1)
		err := route.ResolvedFields(func(result stack.ResolvedFieldsResult) {
			ch <- result
		})
		switch err.(type) {
		case nil, *tcpip.ErrWouldBlock:
			select {
			case result := <-ch:
				if result.Err == nil {
					// Build our response with the resolved route.
					nicID := route.NICID()
					route := result.RouteInfo

					var node fnetRoutes.Destination
					node.SetSourceAddress(fidlconv.ToNetIpAddress(route.LocalAddress))
					// If the remote link address is unspecified, then the outgoing link
					// does not support MAC addressing.
					if linkAddr := route.RemoteLinkAddress; len(linkAddr) != 0 {
						node.SetMac(fidlconv.ToNetMacAddress(linkAddr))
					}
					node.SetInterfaceId(uint64(nicID))

					var response fnetRoutes.StateResolveResponse
					if route.NextHop.Len() != 0 {
						node.SetAddress(fidlconv.ToNetIpAddress(route.NextHop))
						response.Result.SetGateway(node)
					} else {
						node.SetAddress(fidlconv.ToNetIpAddress(route.RemoteAddress))
						response.Result.SetDirect(node)
					}
					return fnetRoutes.StateResolveResultWithResponse(response)
				}
				err = result.Err
			case <-ctx.Done():
				switch ctx.Err() {
				case context.Canceled:
					return fnetRoutes.StateResolveResultWithErr(int32(zx.ErrCanceled))
				case context.DeadlineExceeded:
					return fnetRoutes.StateResolveResultWithErr(int32(zx.ErrTimedOut))
				}
			}
		}
		logFn(".ResolvedFields(...)", err)
		return fnetRoutes.StateResolveResultWithErr(int32(zx.ErrAddressUnreachable))
	}(), nil
}

// GetRouteTableName implements fuchsia.net.routes/State.GetRouteTableName.
func (r *resolveImpl) GetRouteTableName(ctx_ fidl.Context, tableId uint32) (fnetRoutes.StateGetRouteTableNameResult, error) {
	panic("TODO(https://fxbug.dev/336205291): Implement for main table")
}

// GetWatcherV4 implements fuchsia.net.routes/StateV4.GetWatcherV4.
func (r *getWatcherImpl) GetWatcherV4(
	_ fidl.Context,
	watcher fnetRoutes.WatcherV4WithCtxInterfaceRequest,
	options fnetRoutes.WatcherOptionsV4,
) error {
	r.interruptChan <- &getWatcherV4Request{
		req:     watcher,
		options: options,
	}
	return nil
}

// GetRuleWatcherV4 implements fuchsia.net.routes/StateV4.GetRuleWatcherV4.
func (r *getWatcherImpl) GetRuleWatcherV4(
	_ fidl.Context,
	watcher fnetRoutes.RuleWatcherV4WithCtxInterfaceRequest,
	options fnetRoutes.RuleWatcherOptionsV4,
) error {
	panic("TODO(https://fxbug.dev/336204757): Implement rules watcher")
}

// GetWatcherV6 implements fuchsia.net.routes/StateV6.GetWatcherV6.
func (r *getWatcherImpl) GetWatcherV6(
	_ fidl.Context,
	watcher fnetRoutes.WatcherV6WithCtxInterfaceRequest,
	options fnetRoutes.WatcherOptionsV6,
) error {
	r.interruptChan <- &getWatcherV6Request{
		req:     watcher,
		options: options,
	}
	return nil
}

// GetRuleWatcherV6 implements fuchsia.net.routes/StateV6.GetRuleWatcherV6.
func (r *getWatcherImpl) GetRuleWatcherV6(
	_ fidl.Context,
	watcher fnetRoutes.RuleWatcherV6WithCtxInterfaceRequest,
	options fnetRoutes.RuleWatcherOptionsV6,
) error {
	panic("TODO(https://fxbug.dev/336204757): Implement rules watcher")
}

// routesGetWatcherRequest is an interface for GetWatcher requests, abstracting
// over the V4 & V6 variants.
type routesGetWatcherRequest interface {
	// serve serves the GetWatcher request by instantiating a Watcher client.
	serve(
		ctx context.Context,
		cancel context.CancelFunc,
		existingRoutes map[installedRouteComparisonKey]struct{},
		eventsChan chan eventUnion,
		onClose chan<- routeInterrupt,
		metrics *fidlRoutesWatcherMetrics,
	) *routesWatcherImplInner
}

var _ routesGetWatcherRequest = (*getWatcherV4Request)(nil)
var _ routesGetWatcherRequest = (*getWatcherV6Request)(nil)

// getWatcherV4Request is an implementation of the routesGetWatcherRequest
// interface for IPv4.
type getWatcherV4Request struct {
	req     fnetRoutes.WatcherV4WithCtxInterfaceRequest
	options fnetRoutes.WatcherOptionsV4
}

// getWatcherV6Request is an implementation of the routesGetWatcherRequest
// interface for IPv6.
type getWatcherV6Request struct {
	req     fnetRoutes.WatcherV6WithCtxInterfaceRequest
	options fnetRoutes.WatcherOptionsV6
}

// serve implements routesGetWatcherRequest.
func (r *getWatcherV4Request) serve(
	ctx context.Context,
	cancel context.CancelFunc,
	existingRoutes map[installedRouteComparisonKey]struct{},
	eventsChan chan eventUnion,
	onClose chan<- routeInterrupt,
	metrics *fidlRoutesWatcherMetrics,
) *routesWatcherImplInner {
	impl := routesWatcherV4Impl{
		inner: makeRoutesWatcherImplInner(
			cancel,
			eventsChan,
			// Filter out all Non-IPv4 events.
			func(e *eventUnion) bool {
				return e.version == routetypes.IPv4
			},
			existingRoutes,
			eventUnion{
				version:    routetypes.IPv4,
				ipv4_event: fnetRoutes.EventV4WithIdle(fnetRoutes.Empty{}),
			},
		),
	}

	go func() {
		defer func() {
			metrics.count_v4.Add(-1)
			cancel()
			onClose <- &(impl.inner)
		}()
		metrics.count_v4.Add(1)
		component.Serve(
			ctx,
			&fnetRoutes.WatcherV4WithCtxStub{Impl: &impl},
			r.req.Channel,
			component.ServeOptions{
				Concurrent: true,
				OnError: func(err error) {
					_ = syslog.WarnTf(watcherV4ProtocolName, "%s", err)
				},
			})
	}()

	return &(impl.inner)
}

// serve implements routesGetWatcherRequest.
func (r *getWatcherV6Request) serve(
	ctx context.Context,
	cancel context.CancelFunc,
	existingRoutes map[installedRouteComparisonKey]struct{},
	eventsChan chan eventUnion,
	onClose chan<- routeInterrupt,
	metrics *fidlRoutesWatcherMetrics,
) *routesWatcherImplInner {
	impl := routesWatcherV6Impl{
		inner: makeRoutesWatcherImplInner(
			cancel,
			eventsChan,
			// Filter out all Non-IPv6 events.
			func(e *eventUnion) bool {
				return e.version == routetypes.IPv6
			},
			existingRoutes,
			eventUnion{
				version:    routetypes.IPv6,
				ipv6_event: fnetRoutes.EventV6WithIdle(fnetRoutes.Empty{}),
			},
		),
	}

	go func() {
		defer func() {
			metrics.count_v6.Add(-1)
			cancel()
			onClose <- &(impl.inner)
		}()
		metrics.count_v6.Add(1)
		component.Serve(
			ctx,
			&fnetRoutes.WatcherV6WithCtxStub{Impl: &impl},
			r.req.Channel,
			component.ServeOptions{
				Concurrent: true,
				OnError: func(err error) {
					_ = syslog.WarnTf(watcherV6ProtocolName, "%s", err)
				},
			})
	}()

	return &(impl.inner)
}

// isRouteInterrupt implements routeInterrupt.
func (*getWatcherV4Request) isRouteInterrupt() {}

// isRouteInterrupt implements routeInterrupt.
func (*getWatcherV6Request) isRouteInterrupt() {}

// routesWatcherImplInner is the implementation of a routes Watcher protocol.
type routesWatcherImplInner struct {
	// cancel is the function to call to cancel the watcher.
	cancel context.CancelFunc
	// eventsChan is the channel of events that should be sent to this watcher's
	// client.
	eventsChan chan eventUnion
	// existingEvents are the routes that existed at the time this watcher
	// client was instantiated, followed by the idle sentinel. Note that
	// existing routes are stored out of band from eventsChan, because the
	// number of existing routes may exceed the size of the eventsChan.
	existingEvents []eventUnion
	// filter is the predicate applied to events before they are pushed into
	// eventsChan.
	filter func(*eventUnion) bool
	mu     struct {
		sync.Mutex
		// isHanging is True while a Watch request is in progress. E.g.
		// "hanging" in the Hanging-Get design pattern.
		isHanging bool
	}
}

// makeRoutesWatcherImplInner constructs a new routesWatcherImplInner.
func makeRoutesWatcherImplInner(
	cancel context.CancelFunc,
	eventsChan chan eventUnion,
	filter func(*eventUnion) bool,
	existingRoutes map[installedRouteComparisonKey]struct{},
	idleEvent eventUnion,
) routesWatcherImplInner {
	// Create the existing events.
	var existingEvents []eventUnion
	for key := range existingRoutes {
		installedRoute, err := fromInstalledRouteComparisonKey(key)
		if err != nil {
			panic(fmt.Sprintf("observed error while attempting to construct route from comparison key %#v: %s", key, err))
		}
		event := toEvent(existingEvent, installedRoute)
		if filter(&event) {
			existingEvents = append(existingEvents, event)
		}
	}
	existingEvents = append(existingEvents, idleEvent)
	return routesWatcherImplInner{
		cancel:         cancel,
		eventsChan:     eventsChan,
		filter:         filter,
		existingEvents: existingEvents,
	}
}

// pushEvent pushes the given event into the watcher's event channel, if it
// passes the watcher's filter. If the push would block (indicating the client
// isn't keeping up with the flow of events), the client is canceled.
func (w *routesWatcherImplInner) pushEvent(e eventUnion) {
	if !w.filter(&e) {
		return
	}
	select {
	case w.eventsChan <- e:
		// The event was successfully dispatched without blocking.
	default:
		_ = syslog.WarnTf(
			routesFidlName,
			"too many unconsumed events "+
				"(the client may not be calling Watch frequently enough): %d",
			maxPendingEventsPerClient,
		)
		w.cancel()
	}
}

// pullEvents pulls events from the underlying eventsChan. This call blocks if
// there are no available events. Otherwise, this call pulls all available
// events from the underlying channel (up to fnetRoutes.MaxEvents) and returns
// immediately.
func (w *routesWatcherImplInner) pullEvents(fidlCtx fidl.Context) ([]eventUnion, error) {
	var events []eventUnion
	for len(events) < int(fnetRoutes.MaxEvents) {
		if len(w.existingEvents) > 0 {
			// First drain the existing routes, before pulling from the channel.
			var existing eventUnion
			existing, w.existingEvents = w.existingEvents[0], w.existingEvents[1:]
			events = append(events, existing)
		} else if len(events) != 0 {
			// Poll the channel in a non-blocking fashion if we've already
			// accumulated some events.
			select {
			case <-fidlCtx.Done():
				return nil, fmt.Errorf("cancelled: %w", fidlCtx.Err())
			case event := <-w.eventsChan:
				events = append(events, event)
			default:
				return events, nil
			}
		} else {
			// Poll the channel and block until an event is available.
			select {
			case <-fidlCtx.Done():
				return nil, fmt.Errorf("cancelled: %w", fidlCtx.Err())
			case event := <-w.eventsChan:
				events = append(events, event)
			}
		}
	}
	return events, nil
}

// watch services a single call to Watch. This function returns an error if
// there was already a pending call to Watch or if it was canceled while waiting
// for available events.
func (w *routesWatcherImplInner) watch(fidlCtx fidl.Context) ([]eventUnion, error) {
	{
		w.mu.Lock()
		if w.mu.isHanging {
			w.cancel()
			w.mu.Unlock()
			return nil, fmt.Errorf("Watch called while a prior call is still pending")
		}
		w.mu.isHanging = true
		w.mu.Unlock()
	}

	// Fetch Events, blocking if none are available.
	events, err := w.pullEvents(fidlCtx)

	if err != nil {
		w.cancel()
	}

	{
		w.mu.Lock()
		w.mu.isHanging = false
		w.mu.Unlock()
	}

	return events, err
}

// isRouteInterrupt implements routeInterrupt.
func (*routesWatcherImplInner) isRouteInterrupt() {}

// routesWatcherV4Impl and routesWatcherV6Impl wrap routesWatcherImplInner to
// implement WatcherV4 and WatcherV6, respectively. Note that this layer of
// indirection is necessary because both WatcherV4 and WatcherV6 expose a Watch
// method with an identical signature. Trying to to implement the protocols
// directly leads to conflicting implementations (e.g. Watch func defined
// multiple times).

var _ fnetRoutes.WatcherV4WithCtx = (*routesWatcherV4Impl)(nil)

type routesWatcherV4Impl struct {
	inner routesWatcherImplInner
}

var _ fnetRoutes.WatcherV6WithCtx = (*routesWatcherV6Impl)(nil)

type routesWatcherV6Impl struct {
	inner routesWatcherImplInner
}

// Watch implements fuchsia.net.routes/WatcherV4.Watch.
func (w4 *routesWatcherV4Impl) Watch(ctx fidl.Context) ([]fnetRoutes.EventV4, error) {
	events, err := w4.inner.watch(ctx)
	if err != nil {
		return nil, err
	}

	eventsV4 := make([]fnetRoutes.EventV4, 0, len(events))
	for _, event := range events {
		switch event.version {
		case routetypes.IPv4:
			eventsV4 = append(eventsV4, event.ipv4_event)
		case routetypes.IPv6:
			// Unreachable because of the filter installed by GetWatcherV4.
			panic(fmt.Sprintf(
				"Internal Error. %s received an IPv6 event: %s",
				watcherV4ProtocolName,
				intoLogString(event),
			))
		default:
			panic(fmt.Sprintf("Event with invalid IP protocol :%d", event.version))
		}
	}
	return eventsV4, nil
}

// Watch implements fuchsia.net.routes/WatcherV6.Watch.
func (w6 *routesWatcherV6Impl) Watch(ctx fidl.Context) ([]fnetRoutes.EventV6, error) {
	events, err := w6.inner.watch(ctx)
	if err != nil {
		return nil, err
	}

	eventsV6 := make([]fnetRoutes.EventV6, 0, len(events))
	for _, event := range events {
		switch event.version {
		case routetypes.IPv4:
			// Unreachable because of the filter installed by GetWatcherV4.
			panic(fmt.Sprintf(
				"Internal Error. %s received an IPv4 event: %s",
				watcherV6ProtocolName,
				intoLogString(event),
			))
		case routetypes.IPv6:
			eventsV6 = append(eventsV6, event.ipv6_event)
		default:
			panic(fmt.Sprintf("Event with invalid IP protocol :%d", event.version))
		}
	}
	return eventsV6, nil
}

// fidlRoutesWatcherMetrics defines metrics for the
// fuchsia.net.routes Watcher protocols.
type fidlRoutesWatcherMetrics struct {
	count_v4 atomic.Int64
	count_v6 atomic.Int64
}

// eventUnion is a union type abstracting over IPv4 and IPv6 events.
// ipv4_event will be set iif version == IPv4 (and vice-versa for ipv6_event).
type eventUnion struct {
	version    routetypes.IpProtoTag
	ipv4_event fnetRoutes.EventV4
	ipv6_event fnetRoutes.EventV6
}

// maxPendingEventsPerClient is the maximum number of events queued for a single
// Watcher client. The value should be large enough to give clients some leeway
// when processing entries, but small enough to not waste memory. Clients are
// responsible for pulling events from the queue, thus it may back up.
const maxPendingEventsPerClient = 5 * fnetRoutes.MaxEvents

// maxPendingInterrupts is the maximum number of interrupts that have not yet
// been handled by the routesWatcherEventLoop. The value is somewhat arbitrary,
// because the changes are "drained" by the routesWatcherEventLoop immediately;
// however, larger values may reduce contention between goroutines.
const maxPendingInterrupts = 100

// routeInterrupt is a marker interface used to improve type safety in
// routesWatcherEventLoop.
type routeInterrupt interface {
	isRouteInterrupt()
}

// routingTableChanged wraps routes.RoutingTableChanged so that it can implement
// routeEvent.
type routingTableChange struct {
	routes.RoutingTableChange
}

// isRouteInterrupt implements routeInterrupt.
func (*routingTableChange) isRouteInterrupt() {}

// routesWatcherEventLoop is the main event loop servicing clients of the
// fuchsia.net.routes Watcher protocols.
func routesWatcherEventLoop(
	ctx context.Context,
	interruptChan chan routeInterrupt,
	metrics *fidlRoutesWatcherMetrics,
) {
	// Keep track of the current routing table state as changes are received.
	// This allows us to push existing events to new watcher clients without
	// having to call into the system Routing table, which may introduce race
	// conditions.
	currentRoutes := make(map[installedRouteComparisonKey]struct{})

	// Keep track of the active Watcher implementations
	currentWatchers := make(map[*routesWatcherImplInner]struct{})

	for {
		select {
		case <-ctx.Done():
			_ = syslog.WarnTf(routesFidlName, "stopping routes watcher event loop")
			// Wait for all watchers to close.
			for len(currentWatchers) > 0 {
				switch interrupt := (<-interruptChan).(type) {
				case *routesWatcherImplInner:
					delete(currentWatchers, interrupt)
				case *routingTableChange, *getWatcherV4Request, *getWatcherV6Request:
					// Ignore all other interrupts when canceled.
				default:
					panic(fmt.Sprintf("unknown interrupt: %T", interrupt))
				}
			}
			return
		case interrupt := <-interruptChan:
			switch interrupt := interrupt.(type) {
			case *routingTableChange:
				route := fidlconv.ToInstalledRoute(interrupt.Route)
				key, err := toInstalledRouteComparisonKey(route)
				if err != nil {
					panic(fmt.Sprintf("observed error while attempting to compute comparison key for %#v: %s", route, err))
				}
				var eventType eventTag
				// Updates routes based on the received change.
				switch interrupt.Change {
				case routetypes.RouteAdded:
					if _, present := currentRoutes[key]; present {
						panic(fmt.Sprintf(
							"received duplicate add event for route: %+v",
							interrupt.Route,
						))
					}
					currentRoutes[key] = struct{}{}
					eventType = addedEvent
				case routetypes.RouteRemoved:
					if _, present := currentRoutes[key]; !present {
						panic(fmt.Sprintf(
							"received remove event for non-existent route: %+v",
							interrupt.Route,
						))
					}
					delete(currentRoutes, key)
					eventType = removedEvent
				default:
					panic(fmt.Sprintf(
						"observed unexpected routing table change :%+v",
						interrupt.Route,
					))
				}
				// Notify the watchers of change
				event := toEvent(eventType, route)
				for watcherImpl := range currentWatchers {
					watcherImpl.pushEvent(event)
				}
			case *getWatcherV4Request, *getWatcherV6Request:
				// NB: because we're using a case-list, Golang will keep
				// interrupt as an routeInterrupt, instead of rebinding it to a
				// more specific type.
				var watcher routesGetWatcherRequest
				var ok bool
				if watcher, ok = interrupt.(routesGetWatcherRequest); !ok {
					panic(fmt.Sprintf(
						"interrupt was impossibly not a routesGetWatcherRequest: %T",
						interrupt,
					))
				}
				// Serve the new watcher client.
				eventsChan := make(chan eventUnion, maxPendingEventsPerClient)
				watcherCtx, cancel := context.WithCancel(ctx)
				impl := watcher.serve(
					watcherCtx, cancel, currentRoutes, eventsChan, interruptChan, metrics,
				)
				currentWatchers[impl] = struct{}{}
			case *routesWatcherImplInner:
				delete(currentWatchers, interrupt)
			default:
				panic(fmt.Sprintf("unknown interrupt: %T", interrupt))
			}
		}
	}
}

type eventTag uint32

const (
	_ eventTag = iota
	existingEvent
	addedEvent
	removedEvent
)

// toEvent converts the given route into an event based on the provided
// eventTag.
func toEvent(eventType eventTag, route fidlconv.InstalledRoute) eventUnion {
	switch route.Version {
	case routetypes.IPv4:
		var event fnetRoutes.EventV4
		switch eventType {
		case existingEvent:
			event.SetExisting(route.V4)
		case addedEvent:
			event.SetAdded(route.V4)
		case removedEvent:
			event.SetRemoved(route.V4)
		default:
			panic(fmt.Sprintf("invalid eventTag: %d", eventType))
		}
		return eventUnion{
			version:    routetypes.IPv4,
			ipv4_event: event,
		}
	case routetypes.IPv6:
		var event fnetRoutes.EventV6
		switch eventType {
		case existingEvent:
			event.SetExisting(route.V6)
		case addedEvent:
			event.SetAdded(route.V6)
		case removedEvent:
			event.SetRemoved(route.V6)
		default:
			panic(fmt.Sprintf("invalid eventTag: %d", eventType))
		}
		return eventUnion{
			version:    routetypes.IPv6,
			ipv6_event: event,
		}
	default:
		panic(fmt.Sprintf("Route with invalid IP protocol :%d", route.Version))
	}
}

// intoLogString converts the given eventUnion into a string suitable for logs.
// It's important not to log the FIDL type directly, as it's address format
// prevents PII redaction.
func intoLogString(e eventUnion) string {
	fmtInstalledRouteV4 := func(r fnetRoutes.InstalledRouteV4) string {
		dst := fidlconv.ToTCPIPSubnet(net.Subnet{
			Addr:      net.IpAddressWithIpv4(r.Route.Destination.Addr),
			PrefixLen: r.Route.Destination.PrefixLen,
		})
		return fmt.Sprintf(
			"InstalledRoute: %T{ EffectiveProperties: %#v, Route: %T{ Destination: %s, %s, Properties: %#v } }",
			r,
			r.EffectiveProperties,
			r.Route,
			dst,
			func() string {
				return fmt.Sprintf(
					"Action: %T{ I_routeActionV4Tag: %d, Forward: %s }",
					r.Route.Action,
					r.Route.Action.I_routeActionV4Tag,
					func() string {
						switch r.Route.Action.I_routeActionV4Tag {
						case fnetRoutes.RouteActionV4Forward:
							return fmt.Sprintf(
								"%T{ OutboundInterface: %d, NextHop: %s } }",
								r.Route.Action,
								r.Route.Action.I_routeActionV4Tag,
								func() string {
									if r.Route.Action.Forward.NextHop == nil {
										return "nil"
									} else {
										return tcpip.AddrFrom4Slice(
											r.Route.Action.Forward.NextHop.Addr[:]).String()
									}
								}())
						default:
							return fmt.Sprintf("%#v", r.Route.Action.Forward)
						}
					}())
			}(),
			r.Route.Properties)
	}

	fmtInstalledRouteV6 := func(r fnetRoutes.InstalledRouteV6) string {
		dst := fidlconv.ToTCPIPSubnet(net.Subnet{
			Addr:      net.IpAddressWithIpv6(r.Route.Destination.Addr),
			PrefixLen: r.Route.Destination.PrefixLen,
		})
		return fmt.Sprintf(
			"InstalledRoute: %T{ EffectiveProperties: %#v, Route: %T{ Destination: %s, %s, Properties: %#v } }",
			r,
			r.EffectiveProperties,
			r.Route,
			dst,
			func() string {
				return fmt.Sprintf(
					"Action: %T{ I_routeActionV6Tag: %d, Forward: %s }",
					r.Route.Action,
					r.Route.Action.I_routeActionV6Tag,
					func() string {
						switch r.Route.Action.I_routeActionV6Tag {
						case fnetRoutes.RouteActionV6Forward:
							return fmt.Sprintf(
								"%T{ OutboundInterface: %d, NextHop: %s } }",
								r.Route.Action,
								r.Route.Action.I_routeActionV6Tag,
								func() string {
									if r.Route.Action.Forward.NextHop == nil {
										return "nil"
									} else {
										return tcpip.AddrFrom16Slice(
											r.Route.Action.Forward.NextHop.Addr[:]).String()
									}
								}())
						default:
							return fmt.Sprintf("%#v", r.Route.Action.Forward)
						}
					}())
			}(),
			r.Route.Properties)
	}

	return fmt.Sprintf(
		"%T{ version: %d ipv4_event: %s, ipv6_event: %s}",
		e,
		e.version,
		func() string {
			switch e.version {
			case routetypes.IPv4:
				return fmt.Sprintf("%T{ I_eventV4Tag: %d, %s }",
					e.ipv4_event, e.ipv4_event.I_eventV4Tag, func() string {
						switch e.ipv4_event.I_eventV4Tag {
						case fnetRoutes.EventV4Idle:
							return "Idle: {}{}"
						case fnetRoutes.EventV4Existing:
							return fmt.Sprintf("Existing: %s",
								fmtInstalledRouteV4(e.ipv4_event.Existing))
						case fnetRoutes.EventV4Added:
							return fmt.Sprintf("Added: %s",
								fmtInstalledRouteV4(e.ipv4_event.Added))
						case fnetRoutes.EventV4Removed:
							return fmt.Sprintf("Removed: %s",
								fmtInstalledRouteV4(e.ipv4_event.Removed))
						default:
							return "Unknown"
						}
					}())

			default:
				return "<unset>"
			}
		}(),
		func() string {
			switch e.version {
			case routetypes.IPv6:
				return fmt.Sprintf("%T{ I_eventV6Tag: %d, %s }",
					e.ipv6_event, e.ipv6_event.I_eventV6Tag, func() string {
						switch e.ipv6_event.I_eventV6Tag {
						case fnetRoutes.EventV6Idle:
							return "Idle: {}{}"
						case fnetRoutes.EventV6Existing:
							return fmt.Sprintf("Existing: %s",
								fmtInstalledRouteV6(e.ipv6_event.Existing))
						case fnetRoutes.EventV6Added:
							return fmt.Sprintf("Added: %s",
								fmtInstalledRouteV6(e.ipv6_event.Added))
						case fnetRoutes.EventV6Removed:
							return fmt.Sprintf("Removed: %s",
								fmtInstalledRouteV6(e.ipv6_event.Removed))
						default:
							return "Unknown"
						}
					}())

			default:
				return "<unset>"
			}
		}(),
	)
}

// installedRouteComparisonKey is an alternative to InstalledRoute whose boxed members
// are defined out-of-band at the top level. Two installedRouteComparisonKeys can be
// checked for equality, whereas two InstalledRoutes cannot (since their boxed
// members are behind a pointer, leading to address comparisons, not value
// comparisons).
type installedRouteComparisonKey struct {
	fidlconv.RouteComparisonKey
	Version                         routetypes.IpProtoTag
	EffectiveRoutePropertiesPresent bool
	EffectiveRouteProperties        fnetRoutes.EffectiveRouteProperties
}

// toInstalledRouteComparisonKey converts an InstalledRoute to an installedRouteComparisonKey.
func toInstalledRouteComparisonKey(r fidlconv.InstalledRoute) (installedRouteComparisonKey, error) {
	key, err := r.ToRouteComparisonKey()
	if err != nil {
		return installedRouteComparisonKey{}, err
	}

	present, props := func() (bool, fnetRoutes.EffectiveRouteProperties) {
		switch r.Version {
		case routetypes.IPv4:
			return r.V4.EffectivePropertiesPresent, r.V4.EffectiveProperties
		case routetypes.IPv6:
			return r.V6.EffectivePropertiesPresent, r.V6.EffectiveProperties
		default:
			panic(fmt.Sprintf("unknown IP Version tag %d", r.Version))
		}
	}()

	return installedRouteComparisonKey{
		RouteComparisonKey:              key,
		Version:                         r.Version,
		EffectiveRoutePropertiesPresent: present,
		EffectiveRouteProperties:        props,
	}, nil
}

// fromInstalledRouteComparisonKey converts an installedRouteComparisonKey to an InstalledRoute.
func fromInstalledRouteComparisonKey(r installedRouteComparisonKey) (fidlconv.InstalledRoute, error) {
	var result fidlconv.InstalledRoute
	result.Version = r.Version

	switch r.Version {
	case routetypes.IPv4:
		route, err := fidlconv.ToFidlRouteV4(r.V4)
		if err != nil {
			return result, err
		}
		result.V4.SetRoute(route)
		result.V4.EffectivePropertiesPresent = r.EffectiveRoutePropertiesPresent
		result.V4.EffectiveProperties = r.EffectiveRouteProperties
	case routetypes.IPv6:
		route, err := fidlconv.ToFidlRouteV6(r.V6)
		if err != nil {
			return result, err
		}
		result.V6.SetRoute(route)
		result.V6.EffectivePropertiesPresent = r.EffectiveRoutePropertiesPresent
		result.V6.EffectiveProperties = r.EffectiveRouteProperties
	default:
		panic(fmt.Sprintf("unknown IP Version tag %d", r.Version))
	}
	return result, nil
}
