// 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.

#ifndef GARNET_BIN_GUEST_VMM_VIRTIO_NET_LEGACY_H_
#define GARNET_BIN_GUEST_VMM_VIRTIO_NET_LEGACY_H_

#include <atomic>
#include <vector>

#include <fbl/unique_fd.h>
#include <fuchsia/hardware/ethernet/c/fidl.h>
#include <lib/async/cpp/wait.h>
#include <lib/zx/channel.h>
#include <trace-engine/types.h>
#include <virtio/net.h>
#include <virtio/virtio_ids.h>

#include "garnet/bin/guest/vmm/virtio_device.h"
#include "garnet/bin/guest/vmm/virtio_queue_waiter.h"

static constexpr uint16_t kVirtioNetLegacyNumQueues = 2;
static_assert(kVirtioNetLegacyNumQueues % 2 == 0,
              "There must be a queue for both RX and TX");

static constexpr uint16_t kVirtioNetLegacyRxQueueIndex = 0;
static constexpr uint16_t kVirtioNetLegacyTxQueueIndex = 1;
static_assert(kVirtioNetLegacyRxQueueIndex != kVirtioNetLegacyTxQueueIndex,
              "RX and TX queues must be distinct");

// Implements a Virtio Ethernet device.
class VirtioNetLegacy
    : public VirtioInprocessDevice<VIRTIO_ID_NET, kVirtioNetLegacyNumQueues,
                                   virtio_net_config_t> {
 public:
  VirtioNetLegacy(const PhysMem& phys_mem, async_dispatcher_t* dispatcher);
  ~VirtioNetLegacy() override;

  // Starts the Virtio Ethernet device based on the path provided.
  zx_status_t Start(const char* path);

  VirtioQueue* rx_queue() { return queue(kVirtioNetLegacyRxQueueIndex); }
  VirtioQueue* tx_queue() { return queue(kVirtioNetLegacyTxQueueIndex); }

 protected:
  // Helper function to initialize the IO bufs structure that gets shared with
  // the ethdriver. This is protected to allow for a mock VirtioNet to be easily
  // constructed for testing without needing a fully mocked ethernet driver.
  zx_status_t InitIoBuffer(size_t count, size_t elem_size);
  zx_status_t WaitOnFifos(const fuchsia_hardware_ethernet_Fifos& fifos);

 private:
  // Ethernet control plane.
  fuchsia_hardware_ethernet_Fifos fifos_ = {};
  // Connection to the Ethernet device.
  zx::channel net_svc_;

  std::atomic<trace_async_id_t>* rx_trace_flow_id() {
    return trace_flow_id(kVirtioNetLegacyRxQueueIndex);
  }
  std::atomic<trace_async_id_t>* tx_trace_flow_id() {
    return trace_flow_id(kVirtioNetLegacyTxQueueIndex);
  }

  class IoBuffer {
   public:
    IoBuffer() {}

    zx::vmo& vmo() { return vmo_; }

    zx_status_t Init(size_t count, size_t elem_size);
    zx_status_t Allocate(uintptr_t* offset);
    void Free(uintptr_t offset);

   private:
    std::vector<uint16_t> free_list_;
    size_t elem_size_;
    zx::vmo vmo_;
  };

  // A single data stream (either RX or TX).
  class Stream {
   public:
    Stream(const PhysMem& phys_mem, async_dispatcher_t* dispatcher,
           VirtioQueue* queue, std::atomic<trace_async_id_t>* trace_flow_id,
           IoBuffer* iobufs);
    zx_status_t Start(zx_handle_t fifo, size_t fifo_num_entries, bool rx);

   private:
    // Move buffers from VirtioQueue -> FIFO.
    zx_status_t WaitOnQueue();
    void OnQueueReady(zx_status_t status, uint16_t index);
    zx_status_t WaitOnFifoWritable();
    void OnFifoWritable(async_dispatcher_t* dispatcher, async::WaitBase* wait,
                        zx_status_t status, const zx_packet_signal_t* signal);

    // Return buffers from FIFO to VirtioQueue.
    zx_status_t WaitOnFifoReadable();
    void OnFifoReadable(async_dispatcher_t* dispatcher, async::WaitBase* wait,
                        zx_status_t status, const zx_packet_signal_t* signal);

    virtio_net_hdr_t* ReadPacketInfo(uint16_t index, uintptr_t* offset,
                                     uintptr_t* length);

    const PhysMem& phys_mem_;
    async_dispatcher_t* dispatcher_;
    VirtioQueue* queue_;
    std::atomic<trace_async_id_t>* trace_flow_id_;
    zx_handle_t fifo_ = ZX_HANDLE_INVALID;
    bool rx_ = false;
    IoBuffer* io_buf_;

    std::vector<fuchsia_hardware_ethernet_FifoEntry> fifo_entries_;
    // Number of entries in |fifo_entries_| that have not yet been written
    // to the fifo.
    size_t fifo_num_entries_ = 0;
    // In the case of a short write to the fifo, we'll need to resume writing
    // from the middle of |fifo_entries_|. This is the index of the first item
    // to be written.
    size_t fifo_entries_write_index_ = 0;

    VirtioQueueWaiter queue_wait_;
    async::WaitMethod<Stream, &Stream::OnFifoWritable> fifo_writable_wait_{
        this};
    async::WaitMethod<Stream, &Stream::OnFifoReadable> fifo_readable_wait_{
        this};
  };

  Stream rx_stream_;
  Stream tx_stream_;

  IoBuffer io_buf_;
};

#endif  // GARNET_BIN_GUEST_VMM_VIRTIO_NET_LEGACY_H_
