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

#include <lib/async-loop/cpp/loop.h>
#include <lib/fpromise/bridge.h>
#include <lib/fpromise/promise.h>
#include <lib/fpromise/single_threaded_executor.h>
#include <lib/syslog/cpp/macros.h>
#include <sys/socket.h>

#include <future>
#include <optional>

#include <fbl/unique_fd.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>

#include "src/lib/fxl/strings/string_printf.h"
#include "src/lib/fxl/strings/trim.h"
#include "src/virtualization/tests/lib/enclosed_guest.h"
#include "src/virtualization/tests/lib/guest_test.h"

using ::testing::HasSubstr;

static constexpr char kVirtioNetUtil[] = "virtio_net_test_util";
static constexpr size_t kTestPacketSize = 1000;

// Includes ethernet + IPv4 + UDP headers.
static constexpr size_t kHeadersSize = 42;

static constexpr fuchsia::net::MacAddress kDefaultMacAddress = {
    .octets = {0x02, 0x1a, 0x11, 0x00, 0x01, 0x00},
};
static constexpr fuchsia::net::MacAddress kSecondNicMacAddress = {
    .octets = {0x02, 0x1a, 0x11, 0x00, 0x01, 0x01},
};
static constexpr fuchsia::virtualization::NetSpec kSecondNicNetSpec = {
    .mac_address = kSecondNicMacAddress,
    .enable_bridge = true,
};
static constexpr char kDefaultMacString[] = "02:1a:11:00:01:00";
static constexpr char kSecondNicMacString[] = "02:1a:11:00:01:01";
[[maybe_unused]] static constexpr char kHostMacString[] = "02:1a:11:00:00:00";

// Run the two promises, returning the result of the first that completes.
//
// TODO(https://fxbug.dev/42139156): When a library version becomes available, use that
// instead.
template <typename V, typename E>
fpromise::promise<V, E> SelectPromise(fpromise::promise<V, E>& a, fpromise::promise<V, E>& b) {
  return fpromise::make_promise(
      [&a, &b](fpromise::context& context) mutable -> fpromise::result<V, E> {
        fpromise::result<V, E> a_result = a(context);
        if (!a_result.is_pending()) {
          return std::move(a_result);
        }
        fpromise::result<V, E> b_result = b(context);
        if (!b_result.is_pending()) {
          return std::move(b_result);
        }
        return fpromise::pending();
      });
}
static void TestThread(fuchsia::net::MacAddress mac_addr, FakeNetstack* netstack,
                       uint8_t receive_byte, uint8_t send_byte, bool rotate_bytes,
                       bool use_raw_packets, fpromise::consumer<void, void> consumer) {
  async::Loop loop(&kAsyncLoopConfigAttachToCurrentThread);

  // This thread will loop indefinitely until it receives the correct packet.
  // The test will time out via RunUtil in the test fixture if we fail to
  // receive the correct packet.

  using Promise = fpromise::promise<std::optional<std::vector<uint8_t>>, zx_status_t>;
  using PromiseResult = fpromise::result<std::optional<std::vector<uint8_t>>, zx_status_t>;
  Promise consumer_promise =
      consumer.promise().then([](fpromise::result<void, void>&) -> PromiseResult {
        return fpromise::ok(std::optional<std::vector<uint8_t>>());
      });

  while (true) {
    Promise netstack_promise =
        netstack->ReceivePacket(mac_addr).and_then([](std::vector<uint8_t>& v) {
          return fpromise::ok(std::optional<std::vector<uint8_t>>(std::move(v)));
        });
    auto result = fpromise::run_single_threaded(SelectPromise(netstack_promise, consumer_promise));
    ASSERT_TRUE(result.is_ok());
    std::optional opt_value = result.take_value();
    if (!opt_value.has_value()) {
      // The consumer promise has completed, so we can break from the while loop here.
      break;
    }
    std::vector<uint8_t> packet = std::move(opt_value.value());

    bool match_test_packet = false;
    size_t headers_size = use_raw_packets ? 0 : kHeadersSize;
    if (packet.size() == headers_size + kTestPacketSize) {
      match_test_packet = true;
      for (size_t i = headers_size; i != packet.size(); ++i) {
        if (packet[i] != receive_byte) {
          match_test_packet = false;
          break;
        }
      }
    }
    if (!match_test_packet) {
      // The packet is incorrect, don't echo it back to the target
      continue;
    }
    std::vector<uint8_t> send_packet(kTestPacketSize);
    memset(send_packet.data(), send_byte, kTestPacketSize);
    if (rotate_bytes) {
      receive_byte++;
      send_byte++;
    }

    fpromise::promise<void, zx_status_t> promise;
    if (use_raw_packets) {
      promise = netstack->SendPacket(mac_addr, std::move(send_packet));
    } else {
      promise = netstack->SendUdpPacket(mac_addr, std::move(send_packet));
    }
    auto send_result = fpromise::run_single_threaded(std::move(promise));
    ASSERT_TRUE(send_result.is_ok());
  }
}

class VirtioNetMultipleInterfacesZirconGuest : public ZirconEnclosedGuest {
 public:
  VirtioNetMultipleInterfacesZirconGuest(async_dispatcher_t* dispatcher,
                                         RunLoopUntilFunc run_loop_until)
      : ZirconEnclosedGuest(dispatcher, std::move(run_loop_until)) {}

  zx_status_t BuildLaunchInfo(GuestLaunchInfo* launch_info) override {
    zx_status_t status = ZirconEnclosedGuest::BuildLaunchInfo(launch_info);
    if (status != ZX_OK) {
      return status;
    }
    launch_info->config.set_virtio_gpu(false);
    launch_info->config.mutable_net_devices()->emplace_back(kSecondNicNetSpec);
    return ZX_OK;
  }
};

using VirtioNetMultipleInterfacesZirconGuestTest =
    GuestTest<VirtioNetMultipleInterfacesZirconGuest>;

TEST_F(VirtioNetMultipleInterfacesZirconGuestTest, ReceiveAndSend) {
  // Both the value and error are void here, as we're only using the bridge as a signal.
  fpromise::bridge<void, void> bridge;

  // Loop back some data over the default network interface to verify that it is functional.
  auto handle = std::async(std::launch::async, [this, &bridge] {
    FakeNetstack* netstack = this->GetEnclosedGuest().GetNetstack();
    // Pass the consumer into the test thread here.
    TestThread(kDefaultMacAddress, netstack, 0xab, 0xba, /*rotate_bytes=*/false,
               /*use_raw_packets=*/true, std::move(bridge.consumer));
  });

  std::string result;
  EXPECT_EQ(this->RunUtil(kVirtioNetUtil,
                          {fxl::StringPrintf("%u", 0xab), fxl::StringPrintf("%u", 0xba),
                           fxl::StringPrintf("%zu", kTestPacketSize), kDefaultMacString},
                          &result),
            ZX_OK);
  EXPECT_THAT(result, HasSubstr("PASS"));
  bridge.completer.complete_ok();

  handle.wait();

  bridge = fpromise::bridge<void, void>();
  // Ensure that the guest's second NIC works as well.
  handle = std::async(std::launch::async, [this, &bridge] {
    FakeNetstack* netstack = this->GetEnclosedGuest().GetNetstack();
    TestThread(kSecondNicMacAddress, netstack, 0xcd, 0xdc, /*rotate_bytes=*/false,
               /*use_raw_packets=*/true, std::move(bridge.consumer));
  });

  EXPECT_EQ(this->RunUtil(kVirtioNetUtil,
                          {fxl::StringPrintf("%u", 0xcd), fxl::StringPrintf("%u", 0xdc),
                           fxl::StringPrintf("%zu", kTestPacketSize), kSecondNicMacString},
                          &result),
            ZX_OK);
  EXPECT_THAT(result, HasSubstr("PASS"));
  bridge.completer.complete_ok();

  handle.wait();
}

#if __x86_64__
class VirtioNetMultipleInterfacesDebianGuest : public DebianEnclosedGuest {
 public:
  VirtioNetMultipleInterfacesDebianGuest(async_dispatcher_t* dispatcher,
                                         RunLoopUntilFunc run_loop_until)
      : DebianEnclosedGuest(dispatcher, std::move(run_loop_until)) {}

  zx_status_t BuildLaunchInfo(struct GuestLaunchInfo* launch_info) override {
    zx_status_t status = DebianEnclosedGuest::BuildLaunchInfo(launch_info);
    if (status != ZX_OK) {
      return status;
    }
    launch_info->config.set_virtio_gpu(false);
    launch_info->config.mutable_net_devices()->emplace_back(kSecondNicNetSpec);
    return ZX_OK;
  }
};

using VirtioNetMultipleInterfacesDebianGuestTest =
    GuestTest<VirtioNetMultipleInterfacesDebianGuest>;

TEST_F(VirtioNetMultipleInterfacesDebianGuestTest, ReceiveAndEchoMultiple) {
  fpromise::bridge<void, void> bridge;
  auto handle = std::async(std::launch::async, [this, &bridge] {
    FakeNetstack* netstack = this->GetEnclosedGuest().GetNetstack();
    TestThread(kDefaultMacAddress, netstack, 0xab, 0xab, /*rotate_bytes=*/true,
               /*use_raw_packets=*/false, std::move(bridge.consumer));
  });

  // The NetworkManager service tries to detect whether there is a working network, and as we
  // simply drop all unexpected packets this times out and fails during longer running tests.
  // We can just disable this since we don't actually want our networks managed, but longer term
  // we need to improve the fake network logic.
  //
  // TODO(https://fxbug.dev/42065907): Improve fake network to reply to NetworkManager.
  EXPECT_EQ(this->Execute({"sudo", "systemctl", "mask", "NetworkManager.service"}), ZX_OK);
  EXPECT_EQ(this->Execute({"sudo", "systemctl", "stop", "NetworkManager.service"}), ZX_OK);

  // Find the network interface corresponding to the guest's first ethernet device MAC address.
  std::string network_interface;
  ASSERT_EQ(this->RunUtil(kVirtioNetUtil,
                          {
                              "Find",
                              kDefaultMacString,
                          },
                          &network_interface),
            ZX_OK);
  network_interface = std::string(fxl::TrimString(network_interface, "\n"));
  ASSERT_FALSE(network_interface.empty());

  // Configure the guest IPv4 address.
  EXPECT_EQ(this->Execute({"ifconfig", network_interface, "192.168.0.10"}), ZX_OK);

  // Manually add a route to the host.
  EXPECT_EQ(this->Execute({"arp", "-s", "192.168.0.1", kHostMacString}), ZX_OK);

  std::string result;
  EXPECT_EQ(this->RunUtil(kVirtioNetUtil,
                          {
                              "RotatingTransfer",
                              fxl::StringPrintf("%u", 0xab),
                              fxl::StringPrintf("%u", 50000),  // Roughly 50MB of data.
                              fxl::StringPrintf("%zu", kTestPacketSize),
                          },
                          &result),
            ZX_OK);
  EXPECT_THAT(result, HasSubstr("PASS"));

  bridge.completer.complete_ok();
  handle.wait();
}

TEST_F(VirtioNetMultipleInterfacesDebianGuestTest, ReceiveAndSend) {
  fpromise::bridge<void, void> bridge;
  auto handle = std::async(std::launch::async, [this, &bridge] {
    FakeNetstack* netstack = this->GetEnclosedGuest().GetNetstack();
    TestThread(kDefaultMacAddress, netstack, 0xab, 0xba, /*rotate_bytes=*/false,
               /*use_raw_packets=*/false, std::move(bridge.consumer));
  });

  // Find the network interface corresponding to the guest's first ethernet device MAC address.
  std::string network_interface;
  ASSERT_EQ(this->RunUtil(kVirtioNetUtil,
                          {
                              "Find",
                              kDefaultMacString,
                          },
                          &network_interface),
            ZX_OK);
  network_interface = std::string(fxl::TrimString(network_interface, "\n"));
  ASSERT_FALSE(network_interface.empty());

  // Configure the guest IPv4 address.
  EXPECT_EQ(this->Execute({"ifconfig", network_interface, "192.168.0.10"}), ZX_OK);

  // Manually add a route to the host.
  EXPECT_EQ(this->Execute({"arp", "-s", "192.168.0.1", kHostMacString}), ZX_OK);

  std::string result;
  EXPECT_EQ(this->RunUtil(kVirtioNetUtil,
                          {
                              "Transfer",
                              fxl::StringPrintf("%u", 0xab),
                              fxl::StringPrintf("%u", 0xba),
                              fxl::StringPrintf("%zu", kTestPacketSize),
                          },
                          &result),
            ZX_OK);
  EXPECT_THAT(result, HasSubstr("PASS"));
  bridge.completer.complete_ok();

  handle.wait();

  bridge = fpromise::bridge<void, void>();
  // Bring down the first interface
  EXPECT_EQ(this->Execute({"ifconfig", network_interface, "down"}), ZX_OK);

  // Find the network interface corresponding to the guest's second ethernet device MAC address.
  ASSERT_EQ(this->RunUtil(kVirtioNetUtil,
                          {
                              "Find",
                              kSecondNicMacString,
                          },
                          &network_interface),
            ZX_OK);
  network_interface = std::string(fxl::TrimString(network_interface, "\n"));
  ASSERT_FALSE(network_interface.empty());

  // Configure the guest's second interface with the same settings as the first interface.
  EXPECT_EQ(this->Execute({"ifconfig", network_interface, "192.168.0.10"}), ZX_OK);
  EXPECT_EQ(this->Execute({"arp", "-s", "192.168.0.1", kHostMacString}), ZX_OK);

  // Start a new handler thread to validate the data sent over the second NIC.
  handle = std::async(std::launch::async, [this, &bridge] {
    FakeNetstack* netstack = this->GetEnclosedGuest().GetNetstack();
    TestThread(kSecondNicMacAddress, netstack, 0xcd, 0xdc, /*rotate_bytes=*/false,
               /*use_raw_packets=*/false, std::move(bridge.consumer));
  });

  // Run the net util to generate and validate the data
  EXPECT_EQ(this->RunUtil(kVirtioNetUtil,
                          {
                              "Transfer",
                              fxl::StringPrintf("%u", 0xcd),
                              fxl::StringPrintf("%u", 0xdc),
                              fxl::StringPrintf("%zu", kTestPacketSize),
                          },
                          &result),
            ZX_OK);
  EXPECT_THAT(result, HasSubstr("PASS"));
  bridge.completer.complete_ok();
  handle.wait();
}

#endif  // __x86_64__
