blob: c7b7b29b359f744d0c6c1682ce9a819cc36b57a2 [file]
//
// Copyright (C) 2019 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "host/commands/run_cvd/launch/launch.h"
#include "host/commands/run_cvd/launch/wmediumd_server.h"
#include <string>
#include <unordered_set>
#include <utility>
#include <vector>
#include <android-base/logging.h>
#include <fruit/fruit.h>
#include "common/libs/utils/files.h"
#include "common/libs/utils/network.h"
#include "common/libs/utils/result.h"
#include "host/libs/config/command_source.h"
#include "host/libs/config/known_paths.h"
#include "host/libs/config/openwrt_args.h"
#include "host/libs/vm_manager/crosvm_builder.h"
#include "host/libs/vm_manager/crosvm_manager.h"
namespace cuttlefish {
namespace {
using APBootFlow = CuttlefishConfig::InstanceSpecific::APBootFlow;
// TODO(b/288987294) Remove dependency to InstanceSpecific config when moving
// to run_env is completed.
class OpenWrt : public CommandSource {
public:
INJECT(OpenWrt(const CuttlefishConfig& config,
const CuttlefishConfig::EnvironmentSpecific& environment,
const CuttlefishConfig::InstanceSpecific& instance,
LogTeeCreator& log_tee, WmediumdServer& wmediumd_server))
: config_(config),
environment_(environment),
instance_(instance),
log_tee_(log_tee),
wmediumd_server_(wmediumd_server) {}
// CommandSource
Result<std::vector<MonitorCommand>> Commands() override {
constexpr auto crosvm_for_ap_socket = "ap_control.sock";
CrosvmBuilder ap_cmd;
ap_cmd.Cmd().AddPrerequisite([this]() -> Result<void> {
return wmediumd_server_.WaitForAvailability();
});
/* TODO(b/305102099): Due to hostapd issue of OpenWRT 22.03.X versions,
* OpenWRT instance should be rebooted.
*/
LOG(DEBUG) << "Restart OpenWRT due to hostapd issue";
ap_cmd.ApplyProcessRestarter(instance_.crosvm_binary(),
/*first_time_argument=*/"",
kOpenwrtVmResetExitCode);
ap_cmd.Cmd().AddParameter("run");
ap_cmd.AddControlSocket(
instance_.PerInstanceInternalUdsPath(crosvm_for_ap_socket),
instance_.crosvm_binary());
ap_cmd.Cmd().AddParameter("--no-usb");
ap_cmd.Cmd().AddParameter("--core-scheduling=false");
if (!environment_.vhost_user_mac80211_hwsim().empty()) {
ap_cmd.Cmd().AddParameter("--vhost-user-mac80211-hwsim=",
environment_.vhost_user_mac80211_hwsim());
}
SharedFD wifi_tap;
if (environment_.enable_wifi()) {
wifi_tap = ap_cmd.AddTap(instance_.wifi_tap_name());
}
const std::string snapshot_dir = config_.snapshot_path();
if (!snapshot_dir.empty()) {
CF_EXPECT(ap_cmd.SetToRestoreFromSnapshot(snapshot_dir, instance_.id(),
"_openwrt"));
}
/* TODO(kwstephenkim): delete this code when Minidroid completely disables
* the AP VM itself
*/
if (!instance_.crosvm_use_balloon()) {
ap_cmd.Cmd().AddParameter("--no-balloon");
}
/* TODO(kwstephenkim): delete this code when Minidroid completely disables
* the AP VM itself
*/
if (!instance_.crosvm_use_rng()) {
ap_cmd.Cmd().AddParameter("--no-rng");
}
if (instance_.enable_sandbox()) {
ap_cmd.Cmd().AddParameter("--seccomp-policy-dir=",
instance_.seccomp_policy_dir());
} else {
ap_cmd.Cmd().AddParameter("--disable-sandbox");
}
ap_cmd.AddReadWriteDisk(instance_.PerInstancePath("ap_overlay.img"));
auto boot_logs_path =
instance_.PerInstanceLogPath("crosvm_openwrt_boot.log");
auto logs_path = instance_.PerInstanceLogPath("crosvm_openwrt.log");
ap_cmd.AddSerialConsoleReadOnly(boot_logs_path);
ap_cmd.AddHvcReadOnly(logs_path);
auto openwrt_args = OpenwrtArgsFromConfig(instance_);
switch (instance_.ap_boot_flow()) {
case APBootFlow::Grub:
if (config_.vm_manager() == "qemu_cli") {
ap_cmd.AddReadWriteDisk(
instance_.persistent_ap_composite_overlay_path());
} else {
ap_cmd.AddReadWriteDisk(
instance_.persistent_ap_composite_disk_path());
}
ap_cmd.Cmd().AddParameter("--bios=", instance_.bootloader());
break;
case APBootFlow::LegacyDirect:
ap_cmd.Cmd().AddParameter("--params=\"root=/dev/vda1\"");
for (auto& openwrt_arg : openwrt_args) {
ap_cmd.Cmd().AddParameter("--params=" + openwrt_arg.first + "=" +
openwrt_arg.second);
}
ap_cmd.Cmd().AddParameter(config_.ap_kernel_image());
break;
default:
// must not be happened
break;
}
std::vector<MonitorCommand> commands;
commands.emplace_back(
CF_EXPECT(log_tee_.CreateLogTee(ap_cmd.Cmd(), "openwrt")));
commands.emplace_back(std::move(ap_cmd.Cmd()));
return commands;
}
// SetupFeature
std::string Name() const override { return "OpenWrt"; }
bool Enabled() const override {
return instance_.ap_boot_flow() != APBootFlow::None &&
config_.vm_manager() == vm_manager::CrosvmManager::name();
}
private:
std::unordered_set<SetupFeature*> Dependencies() const override { return {}; }
Result<void> ResultSetup() override { return {}; }
const CuttlefishConfig& config_;
const CuttlefishConfig::EnvironmentSpecific& environment_;
const CuttlefishConfig::InstanceSpecific& instance_;
LogTeeCreator& log_tee_;
WmediumdServer& wmediumd_server_;
static constexpr int kOpenwrtVmResetExitCode = 32;
};
} // namespace
fruit::Component<fruit::Required<
const CuttlefishConfig, const CuttlefishConfig::EnvironmentSpecific,
const CuttlefishConfig::InstanceSpecific, LogTeeCreator, WmediumdServer>>
OpenWrtComponent() {
return fruit::createComponent()
.addMultibinding<CommandSource, OpenWrt>()
.addMultibinding<SetupFeature, OpenWrt>();
}
} // namespace cuttlefish