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

#include <fuchsia/netstack/cpp/fidl_test_base.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <lib/trace-provider/provider.h>
#include <zircon/device/ethernet.h>

#include <virtio/net.h>

#include "src/virtualization/bin/vmm/device/test_with_device.h"
#include "src/virtualization/bin/vmm/device/virtio_queue_fake.h"

static constexpr char kVirtioNetUrl[] = "fuchsia-pkg://fuchsia.com/virtio_net#meta/virtio_net.cmx";
static constexpr size_t kNumQueues = 2;
static constexpr uint16_t kQueueSize = 16;
static constexpr size_t kVmoSize = 1024;
static constexpr uint16_t kFakeInterfaceId = 0;

class VirtioNetTest : public TestWithDevice, public fuchsia::netstack::testing::Netstack_TestBase {
 protected:
  VirtioNetTest()
      : rx_queue_(phys_mem_, PAGE_SIZE * kNumQueues, kQueueSize),
        tx_queue_(phys_mem_, rx_queue_.end(), kQueueSize) {}

  void SetUp() override {
    auto env_services = CreateServices();

    // Add our fake netstack service.
    ASSERT_EQ(ZX_OK, env_services->AddService(bindings_.GetHandler(this)));

    // Launch device process.
    fuchsia::virtualization::hardware::StartInfo start_info;
    zx_status_t status =
        LaunchDevice(kVirtioNetUrl, tx_queue_.end(), &start_info, std::move(env_services));
    ASSERT_EQ(ZX_OK, status);

    // Start device execution.
    services_->Connect(net_.NewRequest());
    RunLoopUntilIdle();

    fuchsia::hardware::ethernet::MacAddress mac_address = {
        .octets = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
    };

    // Start the device, waiting for it to complete before attempting to use it.
    bool started = false;
    net_->Start(std::move(start_info), mac_address, true /* enable_bridge */,
                [&started] { started = true; });
    RunLoopUntil([&] { return started; });

    // Get fifos.
    eth_device_->GetFifos(
        [this](zx_status_t status, std::unique_ptr<fuchsia::hardware::ethernet::Fifos> fifos) {
          ASSERT_EQ(status, ZX_OK);
          rx_ = std::move(fifos->rx);
          tx_ = std::move(fifos->tx);
        });
    ASSERT_TRUE(RunLoopWithTimeoutOrUntil([this] { return (rx_ && tx_); }, zx::sec(5)));

    size_t vmo_size = kVmoSize;
    status = zx::vmo::create(vmo_size, 0, &vmo_);
    ASSERT_EQ(status, ZX_OK);

    zx::vmo vmo_dup;
    status = vmo_.duplicate(ZX_RIGHTS_IO | ZX_RIGHT_MAP | ZX_RIGHT_TRANSFER, &vmo_dup);
    ASSERT_EQ(status, ZX_OK);

    eth_device_->SetIOBuffer(std::move(vmo_dup), [](zx_status_t status) {
      ASSERT_EQ(status, ZX_OK) << "Failed to set IO buffer";
    });

    // Configure device queues.
    VirtioQueueFake* queues[kNumQueues] = {&rx_queue_, &tx_queue_};
    for (size_t i = 0; i < kNumQueues; i++) {
      auto q = queues[i];
      q->Configure(PAGE_SIZE * i, PAGE_SIZE);
      net_->ConfigureQueue(i, q->size(), q->desc(), q->avail(), q->used(), [] {});
    }

    bool eth_started = false;
    eth_device_->Start([&eth_started](zx_status_t status) {
      ASSERT_EQ(ZX_OK, status);
      eth_started = true;
    });
    RunLoopUntil([&] { return eth_started; });
  }

  // Fake |fuchsia.netstack.Netstack| implementation.
  void AddEthernetDevice(std::string topological_path,
                         fuchsia::netstack::InterfaceConfig interfaceConfig,
                         fidl::InterfaceHandle<::fuchsia::hardware::ethernet::Device> device,
                         AddEthernetDeviceCallback callback) override {
    eth_device_ = device.Bind();
    callback(fuchsia::netstack::Netstack_AddEthernetDevice_Result::WithResponse(
        fuchsia::netstack::Netstack_AddEthernetDevice_Response{kFakeInterfaceId}));
  }

  // Fake |fuchsia.netstack.Netstack| implementation.
  void GetInterfaces(GetInterfacesCallback callback) override {
    // Return a single fake interface.
    std::vector<fuchsia::netstack::NetInterface> interfaces;
    interfaces.push_back({
        .id = 0,
        .flags = fuchsia::netstack::Flags::UP,
        .addr = fuchsia::net::IpAddress::WithIpv4(fuchsia::net::Ipv4Address()),
        .netmask = fuchsia::net::IpAddress::WithIpv4(fuchsia::net::Ipv4Address()),
        .broadaddr = fuchsia::net::IpAddress::WithIpv4(fuchsia::net::Ipv4Address()),
    });
    callback(std::move(interfaces));
  }

  // Fake |fuchsia.netstack.Netstack| implementation.
  void BridgeInterfaces(std::vector<uint32_t> nicids, BridgeInterfacesCallback callback) override {
    callback(fuchsia::netstack::NetErr{.status = fuchsia::netstack::Status::OK}, /*nicid=*/0);
  }

  void NotImplemented_(const std::string& name) override {
    printf("Not implemented: Netstack::%s\n", name.data());
  }

  // Note: use of sync can be problematic here if the test environment needs to handle
  // some incoming FIDL requests.
  fuchsia::virtualization::hardware::VirtioNetPtr net_;
  VirtioQueueFake rx_queue_;
  VirtioQueueFake tx_queue_;
  fidl::BindingSet<fuchsia::netstack::Netstack> bindings_;
  fuchsia::hardware::ethernet::DevicePtr eth_device_;

  zx::fifo rx_;
  zx::fifo tx_;
  zx::vmo vmo_;
};

TEST_F(VirtioNetTest, SendToGuest) {
  const size_t packet_size = 10;
  uint8_t* data;
  zx_status_t status = DescriptorChainBuilder(rx_queue_)
                           .AppendWritableDescriptor(&data, sizeof(virtio_net_hdr_t) + packet_size)
                           .Build();
  ASSERT_EQ(status, ZX_OK);

  const uint8_t expected_packet[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
  ASSERT_EQ(packet_size, sizeof(expected_packet));
  vmo_.write(static_cast<const void*>(&expected_packet), 0, sizeof(expected_packet));

  eth_fifo_entry_t entry{
      .offset = 0,
      .length = packet_size,
      .flags = 0,
      .cookie = 0xdeadbeef,
  };

  zx_signals_t pending = 0;
  status = tx_.wait_one(ZX_FIFO_WRITABLE | ZX_FIFO_PEER_CLOSED, zx::deadline_after(zx::sec(5)),
                        &pending);
  ASSERT_EQ(status, ZX_OK);

  status = tx_.write(sizeof(entry), static_cast<void*>(&entry), 1, nullptr);
  ASSERT_EQ(status, ZX_OK);

  net_->NotifyQueue(0);

  RunLoopUntilIdle();

  status = tx_.wait_one(ZX_FIFO_READABLE | ZX_FIFO_PEER_CLOSED, zx::deadline_after(zx::sec(5)),
                        &pending);
  ASSERT_EQ(status, ZX_OK);

  status = tx_.read(sizeof(entry), static_cast<void*>(&entry), 1, nullptr);
  ASSERT_EQ(status, ZX_OK);

  status = WaitOnInterrupt();
  ASSERT_EQ(status, ZX_OK);

  virtio_net_hdr_t* hdr = reinterpret_cast<virtio_net_hdr_t*>(data);
  EXPECT_EQ(hdr->num_buffers, 1);
  EXPECT_EQ(hdr->gso_type, VIRTIO_NET_HDR_GSO_NONE);
  EXPECT_EQ(hdr->flags, 0);

  data += sizeof(virtio_net_hdr_t);
  for (size_t i = 0; i != packet_size; ++i) {
    EXPECT_EQ(data[i], expected_packet[i]);
  }

  EXPECT_EQ(entry.offset, 0u);
  EXPECT_EQ(entry.length, packet_size);
  EXPECT_EQ(entry.flags, ETH_FIFO_TX_OK);
  EXPECT_EQ(entry.cookie, 0xdeadbeef);
}

TEST_F(VirtioNetTest, ReceiveFromGuest) {
  const size_t packet_size = 10;
  uint8_t data[packet_size + sizeof(virtio_net_hdr_t)];
  zx_status_t status = DescriptorChainBuilder(tx_queue_)
                           .AppendReadableDescriptor(&data, sizeof(virtio_net_hdr_t) + packet_size)
                           .Build();
  ASSERT_EQ(status, ZX_OK);

  eth_fifo_entry_t entry{
      .offset = 0,
      .length = packet_size,
      .flags = 0,
      .cookie = 0xdeadbeef,
  };

  zx_signals_t pending = 0;
  status = rx_.wait_one(ZX_FIFO_WRITABLE | ZX_FIFO_PEER_CLOSED, zx::deadline_after(zx::sec(5)),
                        &pending);
  ASSERT_EQ(status, ZX_OK);

  status = rx_.write(sizeof(entry), static_cast<void*>(&entry), 1, nullptr);
  ASSERT_EQ(status, ZX_OK);

  RunLoopUntilIdle();

  net_->NotifyQueue(1);

  RunLoopUntilIdle();

  status = rx_.wait_one(ZX_FIFO_READABLE | ZX_FIFO_PEER_CLOSED, zx::deadline_after(zx::sec(5)),
                        &pending);
  ASSERT_EQ(status, ZX_OK);

  status = rx_.read(sizeof(entry), static_cast<void*>(&entry), 1, nullptr);
  ASSERT_EQ(status, ZX_OK);

  status = WaitOnInterrupt();
  ASSERT_EQ(status, ZX_OK);

  EXPECT_EQ(entry.offset, 0u);
  EXPECT_EQ(entry.length, packet_size);
  EXPECT_EQ(entry.flags, ETH_FIFO_RX_OK);
  EXPECT_EQ(entry.cookie, 0xdeadbeef);
}

TEST_F(VirtioNetTest, ResumesReceiveFromGuest) {
  // Build two descriptors.
  const size_t packet_size = 10;
  uint8_t data1[packet_size + sizeof(virtio_net_hdr_t)];
  uint8_t data2[packet_size + sizeof(virtio_net_hdr_t)];

  zx_status_t status = DescriptorChainBuilder(tx_queue_)
                           .AppendReadableDescriptor(&data1, sizeof(virtio_net_hdr_t) + packet_size)
                           .Build();
  ASSERT_EQ(status, ZX_OK);

  status = DescriptorChainBuilder(tx_queue_)
               .AppendReadableDescriptor(&data2, sizeof(virtio_net_hdr_t) + packet_size)
               .Build();
  ASSERT_EQ(status, ZX_OK);

  // Notify the device of the two descriptors we built.
  net_->NotifyQueue(1);
  RunLoopUntilIdle();

  // Write one entry into the rx fifo.
  eth_fifo_entry_t entry = {
      .offset = 0,
      .length = packet_size,
      .flags = 0,
      .cookie = 0xdeadbeef,
  };
  zx_signals_t pending = 0;
  status = rx_.wait_one(ZX_FIFO_WRITABLE | ZX_FIFO_PEER_CLOSED, zx::deadline_after(zx::sec(5)),
                        &pending);
  ASSERT_EQ(status, ZX_OK);
  status = rx_.write(sizeof(entry), static_cast<void*>(&entry), 1, nullptr);
  ASSERT_EQ(status, ZX_OK);

  RunLoopUntilIdle();

  // Attempt to ready two entries from the fifo. Since we only gave the device one entry, it should
  // only return one to us.
  status = rx_.wait_one(ZX_FIFO_READABLE | ZX_FIFO_PEER_CLOSED, zx::deadline_after(zx::sec(5)),
                        &pending);
  ASSERT_EQ(status, ZX_OK);
  size_t actual;
  eth_fifo_entry_t entries[2];
  status = rx_.read(sizeof(entries[0]), static_cast<void*>(&entries), 2, &actual);
  ASSERT_EQ(status, ZX_OK);
  ASSERT_EQ(actual, 1u);

  status = WaitOnInterrupt();
  ASSERT_EQ(status, ZX_OK);

  EXPECT_EQ(entries[0].offset, 0u);
  EXPECT_EQ(entries[0].length, packet_size);
  EXPECT_EQ(entries[0].flags, ETH_FIFO_RX_OK);
  EXPECT_EQ(entries[0].cookie, 0xdeadbeef);

  // Now write another entry into the fifo and the device should process the descriptor without
  // being notified by the guest (i.e. without a call to NotifyQueue).
  entry = {
      .offset = 100,
      .length = packet_size,
      .flags = 0,
      .cookie = 0x1337cafe,
  };
  status = rx_.wait_one(ZX_FIFO_WRITABLE | ZX_FIFO_PEER_CLOSED, zx::deadline_after(zx::sec(5)),
                        &pending);
  ASSERT_EQ(status, ZX_OK);
  status = rx_.write(sizeof(entry), static_cast<void*>(&entry), 1, nullptr);
  ASSERT_EQ(status, ZX_OK);

  RunLoopUntilIdle();

  status = rx_.wait_one(ZX_FIFO_READABLE | ZX_FIFO_PEER_CLOSED, zx::deadline_after(zx::sec(5)),
                        &pending);
  ASSERT_EQ(status, ZX_OK);
  status = rx_.read(sizeof(entries[0]), static_cast<void*>(&entries), 2, &actual);
  ASSERT_EQ(status, ZX_OK);
  ASSERT_EQ(actual, 1u);

  status = WaitOnInterrupt();
  ASSERT_EQ(status, ZX_OK);

  EXPECT_EQ(entries[0].offset, 100u);
  EXPECT_EQ(entries[0].length, packet_size);
  EXPECT_EQ(entries[0].flags, ETH_FIFO_RX_OK);
  EXPECT_EQ(entries[0].cookie, 0x1337cafeu);
}
