// Copyright 2017 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 eth

import (
	"context"
	"fmt"
	"math"
	"sync"
	"syscall/zx"

	"gen/netstack/link/eth"

	"go.fuchsia.dev/fuchsia/src/connectivity/network/netstack/link"
	"go.fuchsia.dev/fuchsia/src/connectivity/network/netstack/link/fifo"
	syslog "go.fuchsia.dev/fuchsia/src/lib/syslog/go"

	"fidl/fuchsia/hardware/ethernet"
	"fidl/fuchsia/hardware/network"

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

// #include <zircon/device/ethernet.h>
// #include <zircon/types.h>
import "C"

const (
	tag        = "eth"
	bufferSize = 2048
)

// Buffer is a segment of memory backed by a mapped VMO.
//
// A Buffer must not outlive its VMO's mapping.
// A Buffer's head must not change (by slicing or appending).
type Buffer []byte

type IOBuffer struct {
	fifo.MappedVMO
}

func (iob *IOBuffer) BufferFromEntry(e eth.FifoEntry) Buffer {
	return iob.GetData(uint64(e.Offset()), uint64(e.Length()))
}

var _ link.Controller = (*Client)(nil)
var _ link.Observer = (*Client)(nil)

var _ stack.LinkEndpoint = (*Client)(nil)
var _ stack.GSOEndpoint = (*Client)(nil)

// Client is an ethernet client.
//
// It connects to a zircon ethernet driver using a FIFO-based protocol.
// The protocol is described in system/fidl/fuchsia-hardware-ethernet/ethernet.fidl.
type Client struct {
	dispatcher stack.NetworkDispatcher
	wg         sync.WaitGroup

	Info ethernet.Info

	device ethernet.DeviceWithCtx

	iob IOBuffer

	topopath, filepath string

	mu struct {
		sync.Mutex
		closed              bool
		onLinkClosed        func()
		onLinkOnlineChanged func(bool)
	}

	handler eth.Handler
}

// NewClient creates a new ethernet Client.
func NewClient(clientName string, topopath, filepath string, device ethernet.DeviceWithCtx) (*Client, error) {
	if status, err := device.SetClientName(context.Background(), clientName); err != nil {
		return nil, err
	} else if err := checkStatus(status, "SetClientName"); err != nil {
		return nil, err
	}
	// TODO(fxbug.dev/20540): once we support IGMP, don't automatically set multicast promisc true
	if status, err := device.ConfigMulticastSetPromiscuousMode(context.Background(), true); err != nil {
		return nil, err
	} else if err := checkStatus(status, "ConfigMulticastSetPromiscuousMode"); err != nil {
		// Some drivers - most notably virtio - don't support this setting.
		if err.(*zx.Error).Status != zx.ErrNotSupported {
			return nil, err
		}
		_ = syslog.WarnTf(tag, "%s", err)
	}
	info, err := device.GetInfo(context.Background())
	if err != nil {
		return nil, err
	}
	status, fifos, err := device.GetFifos(context.Background())
	if err != nil {
		return nil, err
	} else if err := checkStatus(status, "GetFifos"); err != nil {
		return nil, err
	}

	c := &Client{
		Info:     info,
		device:   device,
		topopath: topopath,
		filepath: filepath,
		handler: eth.Handler{
			TxDepth: fifos.TxDepth,
			RxDepth: fifos.RxDepth,
			RxFifo:  fifos.Rx,
			TxFifo:  fifos.Tx,
		},
	}

	rxStorage := int(c.handler.InitRx(uint16(fifos.RxDepth * 2)))
	txStorage := int(c.handler.InitTx(uint16(fifos.TxDepth * 2)))

	var offset uint32
	for i := 0; i < rxStorage; i++ {
		c.handler.PushInitialRx(eth.MakeFifoEntry(offset, bufferSize))
		offset += bufferSize
	}
	for i := 0; i < txStorage; i++ {
		c.handler.PushInitialTx(eth.MakeFifoEntry(offset, bufferSize))
		offset += bufferSize
	}

	{
		mappedVmo, vmo, err := fifo.NewMappedVMO(uint64(offset), fmt.Sprintf("ethernet.Device.IoBuffer: %s", topopath))
		if err != nil {
			_ = c.Close()
			return nil, fmt.Errorf("eth: NewMappedVMO: %w", err)
		}
		c.iob = IOBuffer{MappedVMO: mappedVmo}
		if status, err := device.SetIoBuffer(context.Background(), vmo); err != nil {
			_ = c.Close()
			return nil, fmt.Errorf("eth: cannot set IO VMO: %w", err)
		} else if err := checkStatus(status, "SetIoBuffer"); err != nil {
			_ = c.Close()
			return nil, fmt.Errorf("eth: cannot set IO VMO: %w", err)
		}
	}

	c.handler.Stats.Rx.FifoStats = fifo.MakeFifoStats(fifos.RxDepth)
	c.handler.Stats.Tx.FifoStats = fifo.MakeFifoStats(fifos.TxDepth)

	return c, nil
}

func (c *Client) MTU() uint32 { return c.Info.Mtu }

func (*Client) Capabilities() stack.LinkEndpointCapabilities {
	return 0
}

func (c *Client) MaxHeaderLength() uint16 {
	return 0
}

func (c *Client) LinkAddress() tcpip.LinkAddress {
	return tcpip.LinkAddress(c.Info.Mac.Octets[:])
}

func (c *Client) write(pkts stack.PacketBufferList) (int, tcpip.Error) {
	return c.handler.ProcessWrite(pkts, func(entry *eth.FifoEntry, pkt *stack.PacketBuffer) {
		entry.SetLength(bufferSize)
		b := c.iob.BufferFromEntry(*entry)
		var used int
		for _, v := range pkt.Views() {
			used += copy(b[used:], v)
		}
		entry.SetLength(uint16(used))
	})
}

func (c *Client) WritePacket(_ stack.RouteInfo, _ tcpip.NetworkProtocolNumber, pkt *stack.PacketBuffer) tcpip.Error {
	var pkts stack.PacketBufferList
	pkts.PushBack(pkt)
	_, err := c.write(pkts)
	return err
}

func (c *Client) WritePackets(_ stack.RouteInfo, pkts stack.PacketBufferList, _ tcpip.NetworkProtocolNumber) (int, tcpip.Error) {
	return c.write(pkts)
}

func (c *Client) WriteRawPacket(pkt *stack.PacketBuffer) tcpip.Error {
	var pkts stack.PacketBufferList
	pkts.PushBack(pkt)
	_, err := c.write(pkts)
	return err
}

func (c *Client) Attach(dispatcher stack.NetworkDispatcher) {
	c.dispatcher = dispatcher

	detachWithError := func(cause error) {
		c.mu.Lock()
		closed := c.mu.closed
		c.mu.Unlock()
		if closed {
			return
		}
		if err := c.Close(); err != nil {
			_ = syslog.WarnTf(tag, "error closing device on detach (caused by %s): %s", cause, err)
		} else {
			_ = syslog.WarnTf(tag, "closed device due to %s", cause)
		}
	}

	// dispatcher may be nil when the NIC in stack.Stack is being removed.
	if dispatcher == nil {
		detachWithError(fmt.Errorf("RemoveNIC"))
		return
	}

	c.wg.Add(1)
	go func() {
		defer c.wg.Done()
		if err := c.handler.TxReceiverLoop(func(entry *eth.FifoEntry) bool {
			return entry.Flags()&eth.FifoTXOK != 0
		}); err != nil {
			detachWithError(fmt.Errorf("TX read loop error: %w", err))
		}
	}()

	c.wg.Add(1)
	go func() {
		defer c.wg.Done()
		if err := c.handler.TxSenderLoop(); err != nil {
			detachWithError(fmt.Errorf("TX write loop error: %w", err))
		}
	}()

	c.wg.Add(1)
	go func() {
		defer c.wg.Done()
		if err := c.handler.RxLoop(func(entry *eth.FifoEntry) {
			// Process inbound packet.
			var emptyLinkAddress tcpip.LinkAddress
			dispatcher.DeliverNetworkPacket(emptyLinkAddress, emptyLinkAddress, 0, stack.NewPacketBuffer(stack.PacketBufferOptions{
				Data: append(buffer.View(nil), c.iob.BufferFromEntry(*entry)...).ToVectorisedView(),
			}))

			// This entry is going back to the driver; it can be reused.
			entry.SetLength(bufferSize)
		}, zx.Signals(ethernet.SignalStatus), func() {
			// Process ethernetStatusSignal.
			status, err := c.device.GetStatus(context.Background())
			if err != nil {
				_ = syslog.InfoTf(tag, "fuchsia.hardware.ethernet.Device.GetStatus() error = %s", err)
				return
			}
			_ = syslog.InfoTf(tag, "fuchsia.hardware.ethernet.Device.GetStatus() = %s", status)
			c.mu.Lock()
			fn := c.mu.onLinkOnlineChanged
			c.mu.Unlock()
			fn(status&ethernet.DeviceStatusOnline != 0)
		}); err != nil {
			detachWithError(fmt.Errorf("RX loop error: %w", err))
		}
	}()

	// Spawn a goroutine to clean up the mapped memory once all the handler
	// loops are done.
	go func() {
		c.wg.Wait()
		if err := c.iob.Close(); err != nil {
			_ = syslog.WarnTf(tag, "failed to close IO buffer: %s", err)
		}
		c.mu.Lock()
		fn := c.mu.onLinkClosed
		c.mu.Unlock()
		fn()
	}()
}

func (c *Client) IsAttached() bool {
	return c.dispatcher != nil
}

// Wait implements stack.LinkEndpoint. It blocks until an error in the dispatch
// goroutine(s) spawned in Attach occurs.
func (c *Client) Wait() {
	c.wg.Wait()
}

// ARPHardwareType implements stack.LinkEndpoint.
func (*Client) ARPHardwareType() header.ARPHardwareType {
	return header.ARPHardwareNone
}

// AddHeader implements stack.LinkEndpoint.
func (*Client) AddHeader(_, _ tcpip.LinkAddress, _ tcpip.NetworkProtocolNumber, _ *stack.PacketBuffer) {
}

// GSOMaxSize implements stack.GSOEndpoint.
func (*Client) GSOMaxSize() uint32 {
	// There's no limit on how much data we can take in a single software GSO write.
	return math.MaxUint32
}

// SupportedGSO implements stack.GSOEndpoint.
func (*Client) SupportedGSO() stack.SupportedGSO {
	return stack.SWGSOSupported
}

func checkStatus(status int32, text string) error {
	if status := zx.Status(status); status != zx.ErrOk {
		return &zx.Error{Status: status, Text: text}
	}
	return nil
}

func (c *Client) SetOnLinkClosed(f func()) {
	c.mu.Lock()
	c.mu.onLinkClosed = f
	c.mu.Unlock()
}

func (c *Client) SetOnLinkOnlineChanged(f func(bool)) {
	c.mu.Lock()
	c.mu.onLinkOnlineChanged = f
	c.mu.Unlock()
}

func (c *Client) Topopath() string {
	return c.topopath
}

func (c *Client) Filepath() string {
	return c.filepath
}

// Up enables the interface.
func (c *Client) Up() error {
	if status, err := c.device.Start(context.Background()); err != nil {
		return err
	} else if err := checkStatus(status, "Start"); err != nil {
		return err
	}
	return nil
}

// Down disables the interface.
func (c *Client) Down() error {
	return c.device.Stop(context.Background())
}

// Close closes a Client, releasing any held resources.
func (c *Client) Close() error {
	c.mu.Lock()
	closed := c.mu.closed
	c.mu.closed = true
	c.mu.Unlock()
	if closed {
		return nil
	}
	c.handler.DetachTx()
	if err := c.device.Stop(context.Background()); err != nil {
		_ = syslog.WarnTf(tag, "fuchsia.hardware.ethernet.Device.Stop() for path %q failed: %s", c.topopath, err)
	}

	if iface, ok := c.device.(*ethernet.DeviceWithCtxInterface); ok {
		if err := iface.Close(); err != nil {
			_ = syslog.WarnTf(tag, "failed to close device handle: %s", err)
		}
	} else {
		_ = syslog.WarnTf(tag, "can't close device interface of type %T", c.device)
	}

	if err := c.handler.TxFifo.Close(); err != nil {
		_ = syslog.WarnTf(tag, "failed to close tx fifo: %s", err)
	}
	if err := c.handler.RxFifo.Close(); err != nil {
		_ = syslog.WarnTf(tag, "failed to close rx fifo: %s", err)
	}

	// Additional cleanup is performed by the watcher goroutine spawned in
	// Attach once all the io loops are done.

	return nil
}

func (c *Client) SetPromiscuousMode(enabled bool) error {
	c.mu.Lock()
	defer c.mu.Unlock()

	if status, err := c.device.SetPromiscuousMode(context.Background(), enabled); err != nil {
		return err
	} else if err := checkStatus(status, "SetPromiscuousMode"); err != nil {
		return err
	}
	return nil
}

// ListenTX tells the ethernet driver to reflect all transmitted
// packets back to this ethernet client.
func (c *Client) ListenTX() error {
	if status, err := c.device.ListenStart(context.Background()); err != nil {
		return err
	} else if err := checkStatus(status, "ListenStart"); err != nil {
		return err
	}
	return nil
}

func (c *Client) DeviceClass() network.DeviceClass {
	if c.Info.Features&ethernet.FeaturesWlan != 0 {
		return network.DeviceClassWlan
	}
	return network.DeviceClassEthernet
}

func (c *Client) RxStats() *fifo.RxStats {
	return &c.handler.Stats.Rx
}

func (c *Client) TxStats() *fifo.TxStats {
	return &c.handler.Stats.Tx
}
