[sim-env][sim-ap][iwlwifi] Create sim-ap

Change our overall approach to sim-env. Rather than including AP
support inside of sim-env, define a virtual interface used by all
stations, including our simulated AP and our simulated hardware
(firmware) stations. This will allow us to develop a generic
event-driven simulated environment with numerous heterogeneous
clients.

TEST: These changes are part of the overall test framework, but
      they were verified by running the iwlwifi tests, which are
      currently the only client using it.
Change-Id: If4223844fad1df5616b959165d4ceca0d2eea169
diff --git a/src/connectivity/wlan/drivers/testing/lib/sim-env/BUILD.gn b/src/connectivity/wlan/drivers/testing/lib/sim-env/BUILD.gn
index 6c15ea3..7f89b04 100644
--- a/src/connectivity/wlan/drivers/testing/lib/sim-env/BUILD.gn
+++ b/src/connectivity/wlan/drivers/testing/lib/sim-env/BUILD.gn
@@ -5,6 +5,7 @@
 static_library("simenv") {
   sources = [
     "sim-env.h",
+    "sim-sta-ifc.h",
   ]
 
   deps = [
diff --git a/src/connectivity/wlan/drivers/testing/lib/sim-env/sim-env.h b/src/connectivity/wlan/drivers/testing/lib/sim-env/sim-env.h
index 5bd2d06..a8e02326 100644
--- a/src/connectivity/wlan/drivers/testing/lib/sim-env/sim-env.h
+++ b/src/connectivity/wlan/drivers/testing/lib/sim-env/sim-env.h
@@ -29,84 +29,65 @@
 #ifndef SRC_CONNECTIVITY_WLAN_DRIVERS_TESTING_LIB_SIM_ENV_SIM_ENV_H_
 #define SRC_CONNECTIVITY_WLAN_DRIVERS_TESTING_LIB_SIM_ENV_SIM_ENV_H_
 
+#include <netinet/if_ether.h>
 #include <stdint.h>
-#include <wlan/protocol/ieee80211.h>
-#include <wlan/protocol/info.h>
+#include <zircon/time.h>
+#include <zircon/types.h>
 
 #include <list>
 
-#include "netinet/if_ether.h"
-#include "zircon/types.h"
+#include <wlan/protocol/ieee80211.h>
+#include <wlan/protocol/info.h>
+
+#include "sim-sta-ifc.h"
 
 namespace wlan {
-namespace testing {
-
-// To simulate an AP. Only keep minimum information for sim-fw to generate
-// response for driver.
-//
-class SimulatedAp {
- public:
-  struct SimulatedSecurity {
-    enum ieee80211_cipher_suite cipher_suite;
-    size_t key_len;
-    uint8_t key[32];
-  };
-
-  SimulatedAp(const uint8_t bssid[ETH_ALEN], const uint8_t* ssid, const size_t ssid_len,
-              uint8_t chan)
-      : chan_(chan) {
-    memcpy(bssid_, bssid, sizeof(bssid_));
-
-    ssid_.len = std::min(ssid_len, static_cast<size_t>(WLAN_MAX_SSID_LEN));
-    memcpy(ssid_.ssid, ssid, ssid_.len);
-
-    memset(&security_, 0, sizeof(security_));
-    security_.cipher_suite = IEEE80211_CIPHER_SUITE_NONE;
-  }
-  ~SimulatedAp() {}
-
-  // When this is not called, the default is open network.
-  void SetSecurity(const struct SimulatedSecurity sec);
-
- private:
-  uint8_t chan_;
-  uint8_t bssid_[ETH_ALEN];
-  wlan_ssid_t ssid_;
-  struct SimulatedSecurity security_;
-};
+namespace simulation {
 
 // To simulate the physical environment.
 //
-class SimulatedEnvironment {
+class Environment {
  public:
-  SimulatedEnvironment() {}
-  ~SimulatedEnvironment() {}
+  Environment() = default;
+  ~Environment() = default;
 
-  // Add an AP into the environment. This can be called by unit test and sim-fw.
-  void AddAp(SimulatedAp* ap) { aps_.push_back(ap); }
+  // Add a station into the environment.
+  void AddStation(StationIfc* sta) { stations_.push_back(sta); }
 
-  // getter function for sim-fw to generate the scan response.
-  std::list<SimulatedAp*> aps() { return aps_; }
+  // Remove a station from the environment.
+  void RemoveStation(StationIfc* sta) { stations_.remove(sta); }
+
+  // Begin simulation. Simulation will end when there are no more events pending.
+  void Start();
+
+  // Send a packet into the simulated environment.
+  void Tx();
+
+  // Send a beacon. Note that this will (likely) someday be deprecated in favor of Tx().
+  void TxBeacon();
+
+  // Ask for a future notification. Specify sender so we can omit them from the Rx notifications.
+  zx_status_t RequestNotification(StationIfc* sta, uint64_t msec);
 
  private:
-  std::list<SimulatedAp*> aps_;
+  struct EnvironmentEvent {
+    zx_time_t msec;  // The absolute time to fire
+    enum EnvironmentEventType type;
+    StationIfc* requester;
+    void* payload;
+  };
+
+  // All registered stations
+  std::list<StationIfc*> stations_;
+
+  // Current time
+  zx_time_t msec_;
+
+  // Future events, sorted by time
+  std::list<std::unique_ptr<EnvironmentEvent>> events_;
 };
 
-//
-// The driver-specific simulated firmware must inherit this class.
-//
-class SimulatedFirmware {
- public:
-  // |env| is passed into the simulated firmware so that the firmware can
-  // interact with the simulated environment.
-  SimulatedFirmware(SimulatedEnvironment* env) : env_(env) {}
-  ~SimulatedFirmware() {}
-
- protected:
-  SimulatedEnvironment* env_;
-};
-
-}  // namespace testing
+}  // namespace simulation
 }  // namespace wlan
 
 #endif  // SRC_CONNECTIVITY_WLAN_DRIVERS_TESTING_LIB_SIM_ENV_SIM_ENV_H_
diff --git a/src/connectivity/wlan/drivers/testing/lib/sim-env/sim-sta-ifc.h b/src/connectivity/wlan/drivers/testing/lib/sim-env/sim-sta-ifc.h
new file mode 100644
index 0000000..2c507f3
--- /dev/null
+++ b/src/connectivity/wlan/drivers/testing/lib/sim-env/sim-sta-ifc.h
@@ -0,0 +1,31 @@
+// 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.
+
+#ifndef SRC_CONNECTIVITY_WLAN_DRIVERS_TESTING_LIB_SIM_ENV_SIM_STA_IFC_H_
+#define SRC_CONNECTIVITY_WLAN_DRIVERS_TESTING_LIB_SIM_ENV_SIM_STA_IFC_H_
+
+#include <wlan/protocol/info.h>
+
+namespace wlan::simulation {
+
+enum EnvironmentEventType {
+  kEventDone,    // Simulation has ended -- no more events
+  kEventStaReq,  // Station-requested event
+};
+
+class StationIfc {
+ public:
+  // Placeholder for eventual packet-level packet handler
+  virtual void Rx(void* pkt) = 0;
+
+  // Simplified beacon handler, eventually to be incorporated into Rx() functionality
+  virtual void RxBeacon(wlan_channel_t* channel, wlan_ssid_t* ssid) = 0;
+
+  // Receive notification of a simulation event
+  virtual void ReceiveNotification(enum EnvironmentEventType notification_type, void* payload) = 0;
+};
+
+}  // namespace wlan::simulation
+
+#endif  // SRC_CONNECTIVITY_WLAN_DRIVERS_TESTING_LIB_SIM_ENV_SIM_STA_IFC_H_
diff --git a/src/connectivity/wlan/drivers/testing/lib/sim-fake-ap/BUILD.gn b/src/connectivity/wlan/drivers/testing/lib/sim-fake-ap/BUILD.gn
new file mode 100644
index 0000000..0cdd75b
--- /dev/null
+++ b/src/connectivity/wlan/drivers/testing/lib/sim-fake-ap/BUILD.gn
@@ -0,0 +1,20 @@
+# 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.
+
+static_library("sim-fake-ap") {
+  sources = [
+    "sim-fake-ap.h",
+  ]
+
+  deps = [
+    "//zircon/public/lib/ddk",
+  ]
+
+  public_deps = [
+    "//garnet/lib/wlan/protocol:protocol",
+    "//src/connectivity/wlan/drivers/testing/lib/sim-env:simenv",
+    "//zircon/public/banjo/ddk.hw.wlan.ieee80211",
+    "//zircon/public/banjo/ddk.hw.wlan.wlaninfo",
+  ]
+}
diff --git a/src/connectivity/wlan/drivers/testing/lib/sim-fake-ap/sim-fake-ap.h b/src/connectivity/wlan/drivers/testing/lib/sim-fake-ap/sim-fake-ap.h
new file mode 100644
index 0000000..ea2f01d
--- /dev/null
+++ b/src/connectivity/wlan/drivers/testing/lib/sim-fake-ap/sim-fake-ap.h
@@ -0,0 +1,62 @@
+// 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.
+
+#ifndef SRC_CONNECTIVITY_WLAN_DRIVERS_TESTING_LIB_SIM_FAKE_AP_SIM_FAKE_AP_H_
+#define SRC_CONNECTIVITY_WLAN_DRIVERS_TESTING_LIB_SIM_FAKE_AP_SIM_FAKE_AP_H_
+
+#include <stdint.h>
+
+#include <array>
+#include <list>
+
+#include <wlan/protocol/ieee80211.h>
+#include <wlan/protocol/info.h>
+
+#include "netinet/if_ether.h"
+#include "src/connectivity/wlan/drivers/testing/lib/sim-env/sim-sta-ifc.h"
+#include "zircon/types.h"
+
+namespace wlan::simulation {
+
+// To simulate an AP. Only keep minimum information for sim-fw to generate
+// response for driver.
+//
+class FakeAp : public StationIfc {
+ public:
+  struct Security {
+    enum ieee80211_cipher_suite cipher_suite;
+
+    static constexpr size_t kMaxKeyLen = 32;
+    size_t key_len;
+    std::array<uint8_t, kMaxKeyLen> key;
+  };
+
+  typedef std::array<uint8_t, ETH_ALEN> Bssid;
+
+  FakeAp(const Bssid bssid, const wlan_ssid_t ssid, const wlan_channel_t chan)
+      : chan_(chan),
+        bssid_(bssid),
+        ssid_(ssid),
+        security_{.cipher_suite = IEEE80211_CIPHER_SUITE_NONE} {}
+  ~FakeAp() = default;
+
+  // When this is not called, the default is open network.
+  void SetSecurity(struct Security sec);
+
+  // StationIfc operations - these are the functions that allow the simulated AP to be used
+  // inside of a sim-env environment.
+  void Rx(void* pkt) override {}
+  void RxBeacon(wlan_channel_t* channel, wlan_ssid_t* ssid) override {}
+  void ReceiveNotification(enum EnvironmentEventType notification_type, void* payload) override {}
+
+ private:
+  wlan_channel_t chan_;
+  Bssid bssid_;
+  wlan_ssid_t ssid_;
+  struct Security security_;
+};
+
+}  // namespace wlan::simulation
+
+#endif  // SRC_CONNECTIVITY_WLAN_DRIVERS_TESTING_LIB_SIM_FAKE_AP_SIM_FAKE_AP_H_
diff --git a/src/connectivity/wlan/drivers/third_party/intel/iwlwifi/test/BUILD.gn b/src/connectivity/wlan/drivers/third_party/intel/iwlwifi/test/BUILD.gn
index f585104..de00313 100644
--- a/src/connectivity/wlan/drivers/third_party/intel/iwlwifi/test/BUILD.gn
+++ b/src/connectivity/wlan/drivers/third_party/intel/iwlwifi/test/BUILD.gn
@@ -33,6 +33,7 @@
 
   public_deps = [
     "//src/connectivity/wlan/drivers/testing/lib/sim-env:simenv",
+    "//src/connectivity/wlan/drivers/testing/lib/sim-fake-ap",
     "//src/connectivity/wlan/drivers/third_party/intel/iwlwifi:core",
   ]
 }
diff --git a/src/connectivity/wlan/drivers/third_party/intel/iwlwifi/test/dummy_test.cc b/src/connectivity/wlan/drivers/third_party/intel/iwlwifi/test/dummy_test.cc
index 298da9f2..1807b59 100644
--- a/src/connectivity/wlan/drivers/third_party/intel/iwlwifi/test/dummy_test.cc
+++ b/src/connectivity/wlan/drivers/third_party/intel/iwlwifi/test/dummy_test.cc
@@ -14,8 +14,7 @@
 
 #include "src/connectivity/wlan/drivers/third_party/intel/iwlwifi/test/single-ap-test.h"
 
-namespace wlan {
-namespace testing {
+namespace wlan::testing {
 namespace {
 
 // To test helper functions only.
@@ -46,5 +45,4 @@
 TEST_F(MvmTest, MvmTestFunction) { EXPECT_EQ(trans_.Init(), ZX_OK); }
 
 }  // namespace
-}  // namespace testing
-}  // namespace wlan
+}  // namespace wlan::testing
diff --git a/src/connectivity/wlan/drivers/third_party/intel/iwlwifi/test/sim-mvm.h b/src/connectivity/wlan/drivers/third_party/intel/iwlwifi/test/sim-mvm.h
index a1dba01..6dacd266 100644
--- a/src/connectivity/wlan/drivers/third_party/intel/iwlwifi/test/sim-mvm.h
+++ b/src/connectivity/wlan/drivers/third_party/intel/iwlwifi/test/sim-mvm.h
@@ -6,6 +6,7 @@
 #define SRC_CONNECTIVITY_WLAN_DRIVERS_THIRD_PARTY_INTEL_IWLWIFI_TEST_SIM_MVM_H_
 
 #include "src/connectivity/wlan/drivers/testing/lib/sim-env/sim-env.h"
+#include "src/connectivity/wlan/drivers/testing/lib/sim-env/sim-sta-ifc.h"
 
 extern "C" {
 #include "src/connectivity/wlan/drivers/third_party/intel/iwlwifi/iwl-trans.h"
@@ -14,12 +15,25 @@
 namespace wlan {
 namespace testing {
 
-class SimMvm : public SimulatedFirmware {
+class SimMvm : public ::wlan::simulation::StationIfc {
  public:
-  SimMvm(SimulatedEnvironment* env) : SimulatedFirmware(env) {}
-  ~SimMvm() {}
+  explicit SimMvm(::wlan::simulation::Environment* env) : env_(env) { env->AddStation(this); }
+  ~SimMvm() {
+    if (env_ != nullptr) {
+      env_->RemoveStation(this);
+    }
+  }
 
   zx_status_t SendCmd(struct iwl_host_cmd* cmd);
+
+  // StationIfc operations
+  void Rx(void* pkt) override {}
+  void RxBeacon(wlan_channel_t* channel, wlan_ssid_t* ssid) override {}
+  void ReceiveNotification(enum ::wlan::simulation::EnvironmentEventType notification_type,
+                           void* payload) override {}
+
+ private:
+  ::wlan::simulation::Environment* env_;
 };
 
 }  // namespace testing
diff --git a/src/connectivity/wlan/drivers/third_party/intel/iwlwifi/test/single-ap-test.h b/src/connectivity/wlan/drivers/third_party/intel/iwlwifi/test/single-ap-test.h
index bba2e4e..e1eadfb 100644
--- a/src/connectivity/wlan/drivers/third_party/intel/iwlwifi/test/single-ap-test.h
+++ b/src/connectivity/wlan/drivers/third_party/intel/iwlwifi/test/single-ap-test.h
@@ -10,36 +10,34 @@
 
 #include "gtest/gtest.h"
 #include "src/connectivity/wlan/drivers/testing/lib/sim-env/sim-env.h"
+#include "src/connectivity/wlan/drivers/testing/lib/sim-fake-ap/sim-fake-ap.h"
 #include "src/connectivity/wlan/drivers/third_party/intel/iwlwifi/test/trans-sim.h"
 
-namespace wlan {
-namespace testing {
+namespace wlan::testing {
 
 // Helper class for unit test code to inherit in order to create an environment
 // with one virtual AP ready to scan/connect.
 //
 class SingleApTest : public ::testing::Test {
  public:
-  SingleApTest() : ap_(kApAddr, kSsid, kSsidLen, kChannel), trans_(&env_) {
+  SingleApTest() : ap_(kApAddr, kSsid, kChannel), trans_(&env_) {
     zx_status_t status = trans_.Init();
     ZX_ASSERT_MSG(ZX_OK == status, "Transportation initialization failed: %s",
                   zx_status_get_string(status));
-    env_.AddAp(&ap_);
+    env_.AddStation(&ap_);
   }
   ~SingleApTest() {}
 
  protected:
-  static constexpr uint8_t kApAddr[ETH_ALEN] = {0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc};
-  static constexpr uint8_t kSsid[] = "MySSID";
-  static constexpr size_t kSsidLen = 6;  // The length of 'ssid' above.
-  static constexpr uint8_t kChannel = 11;
+  static constexpr std::array<uint8_t, ETH_ALEN> kApAddr = {0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc};
+  static constexpr wlan_ssid_t kSsid = {.ssid = "MySSID", .len = 6 /* strlen("MySSID") */};
+  static constexpr wlan_channel_t kChannel = {.primary = 11, .cbw = CBW20};
 
-  SimulatedEnvironment env_;
-  SimulatedAp ap_;
+  ::wlan::simulation::Environment env_;
+  ::wlan::simulation::FakeAp ap_;
   TransportSim trans_;
 };
 
-}  // namespace testing
-}  // namespace wlan
+}  // namespace wlan::testing
 
 #endif  // SRC_CONNECTIVITY_WLAN_DRIVERS_THIRD_PARTY_INTEL_IWLWIFI_TEST_SINGLE_AP_TEST_H_
diff --git a/src/connectivity/wlan/drivers/third_party/intel/iwlwifi/test/trans-sim.h b/src/connectivity/wlan/drivers/third_party/intel/iwlwifi/test/trans-sim.h
index 1f3f671..bc776ed 100644
--- a/src/connectivity/wlan/drivers/third_party/intel/iwlwifi/test/trans-sim.h
+++ b/src/connectivity/wlan/drivers/third_party/intel/iwlwifi/test/trans-sim.h
@@ -19,7 +19,7 @@
 
 class TransportSim : public SimMvm {
  public:
-  TransportSim(SimulatedEnvironment* env) : SimMvm(env) {}
+  explicit TransportSim(::wlan::simulation::Environment* env) : SimMvm(env) {}
   ~TransportSim() {}
 
   // This function must be called before starting using other functions.