--- nono/host/hostnet.cpp 2026/04/29 17:05:39 1.1.1.7 +++ nono/host/hostnet.cpp 2026/04/29 17:05:47 1.1.1.9 @@ -81,6 +81,7 @@ #if defined(HAVE_HOSTNET_TAP) #include "netdriver_tap.h" #endif +#include "uimessage.h" #include #include #include @@ -110,8 +111,9 @@ HostNetDevice::GetDrivers() // コンストラクタ -HostNetDevice::HostNetDevice(Device *parent_, uint n) - : inherited(parent_, OBJ_HOSTNET(n)) +HostNetDevice::HostNetDevice(Device *parent_, uint n, + const std::string& portname_) + : inherited(parent_, OBJ_HOSTNET(n), portname_) { ihwaddrfilter = dynamic_cast(parent); assert(ihwaddrfilter); @@ -119,6 +121,17 @@ HostNetDevice::HostNetDevice(Device *par monitor = gMonitorManager->Regist(ID_MONITOR_HOSTNET(n), this); monitor->func = ToMonitorCallback(&HostNetDevice::MonitorUpdate); monitor->SetSize(48, 24); + +#if defined(HAVE_HOSTNET_SLIRP) + // SLIRP モニタは usermode を使う時のみ必要だが、現状モニタは + // 起動時に1回登録しなければならない (以後増減できない) という制約が + // あるのでここで登録だけしておく。うーんこの…。 + // usermode は現状高々1つなので、登録されてない時だけ登録する。 + Monitor *mon = gMonitorManager->Find(ID_MONITOR_SLIRP); + if (mon == NULL) { + gMonitorManager->Regist(ID_MONITOR_SLIRP, NULL); + } +#endif } // デストラクタ @@ -132,6 +145,7 @@ HostNetDevice::SetLogLevel(int loglevel_ { inherited::SetLogLevel(loglevel_); + std::lock_guard guard(driverlock); if ((bool)driver) { driver->SetLogLevel(loglevel_); } @@ -145,25 +159,39 @@ HostNetDevice::Create2() return false; } - if (SelectDriver() == false) { + // hostnet*-fallback は使わなくなったので、 + // 初期値から変更されていれば警告だけ出す。 + std::string key = GetConfigKey(); + const std::string fallback_key = key + "-fallback"; + const ConfigItem& fallback_item = gConfig->Find(fallback_key); + if (fallback_item.GetFrom() != ConfigItem::FromInitial) { + warnx("Warning: option '%s' has been obsoleted.", + fallback_key.c_str()); + } + + if (SelectDriver(true) == false) { return false; } return true; } -// ドライバ(再)選択 +// ドライバ(再)選択。 +// エラーが起きた場合、 +// 起動時なら、warn() 等で表示して false を返す(終了する)。 +// 実行中なら、warn() 等で表示してもいいが、必ず None にフォールバックして +// true を返すこと。 bool -HostNetDevice::SelectDriver() +HostNetDevice::SelectDriver(bool startup) { - int n = GetId() - OBJ_HOSTNET0; - const std::string key_driver = string_format("hostnet%d-driver", n); - const std::string key_fallback = string_format("hostnet%d-fallback", n); - const ConfigItem& item = gConfig->Find(key_driver); - std::string type = item.AsString(); - bool fallback = gConfig->Find(key_fallback).AsInt(); + std::lock_guard guard(driverlock); driver.reset(); + errmsg.clear(); + + std::string key = GetConfigKey(); + const ConfigItem& item = gConfig->Find(key + "-driver"); + std::string type = item.AsString(); // auto は usermode か none と同義にする。 if (type == "auto") { @@ -174,57 +202,75 @@ HostNetDevice::SelectDriver() #endif } - if (type != "none") { - if (type == "usermode") { + enum { + ERR_CONFIG, // 設定でのエラー + ERR_INVALID, // 知らないドライバ + ERR_NOTSUPP, // コンパイルされてない + } reason = ERR_CONFIG; + + if (type == "none") { + CreateNone(); + + } else if (type == "usermode") { #if defined(HAVE_HOSTNET_SLIRP) - CreateSlirp(); + CreateSlirp(startup); #else - item.Err("Hostnet driver %s not compiled", type.c_str()); + reason = ERR_NOTSUPP; #endif - } else if (type == "tap") { + } else if (type == "tap") { #if defined(HAVE_HOSTNET_TAP) - CreateTap(); + CreateTap(); #else - item.Err("Hostnet driver %s not compiled", type.c_str()); + reason = ERR_NOTSUPP; #endif - } else if (type == "bpf") { + } else if (type == "bpf") { #if defined(HAVE_HOSTNET_BPF) - CreateBPF(); + CreateBPF(); #else - item.Err("Hostnet driver %s not compiled", type.c_str()); + reason = ERR_NOTSUPP; #endif - } else if (type == "afpacket") { + } else if (type == "afpacket") { #if defined(HAVE_HOSTNET_AFPACKET) - CreateAFPacket(); + CreateAFPacket(); #else - item.Err("Hostnet driver %s not compiled", type.c_str()); + reason = ERR_NOTSUPP; #endif - } else { - // 知らないドライバ種別 - item.Err(); - } - - if ((bool)driver == false) { - putmsg(1, "hostnet-fallback=%d", fallback ? 1 : 0); - - if (fallback == false) { - // フォールバックしないならエラー終了 - errmsg = "No host network driver found"; - putmsg(1, "%s", errmsg.c_str()); - warnx("%s (See details with options -C -Lhostnet=1)", - errmsg.c_str()); - - return false; - } - } + } else { + // 知らないドライバ種別 + reason = ERR_INVALID; } if ((bool)driver == false) { - CreateNone(); + // 指定のドライバが使えなかった場合、 + // o 起動時ならエラー終了する。 + // o 実行中なら none にフォールバックする。 + if (startup) { + switch (reason) { + case ERR_INVALID: + item.Err("Invalid driver name"); + break; + case ERR_CONFIG: + item.Err("Could not configure the driver"); + warnx("(See details with option -C -L%s=1)", key.c_str()); + break; + case ERR_NOTSUPP: + item.Err("Hostnet driver %s not compiled", type.c_str()); + break; + default: + assert(false); + } + return false; + } else { + // UI に通知してフォールバック。 + int n = GetId() - OBJ_HOSTNET0; + UIMessage::Post(UIMessage::HOSTNET_FAILED, n); + + CreateNone(); + } } assert((bool)driver); @@ -235,42 +281,47 @@ HostNetDevice::SelectDriver() return true; } -// None ドライバを生成する -bool +// None ドライバを生成する。 +// 戻り値はなく、成否は (bool)driver で判断する。 +void HostNetDevice::CreateNone() { - driver.reset(new NetDriverNone(this)); + try { + driver.reset(new NetDriverNone(this)); + } catch (...) { } if ((bool)driver) { if (driver->InitDriver()) { // 成功 - return true; + return; } errmsg = driver->errmsg; driver.reset(); } - return false; } -// Slirp ドライバを生成する -bool -HostNetDevice::CreateSlirp() +// Slirp ドライバを生成する。 +// 戻り値はなく、成否は (bool)driver で判断する。 +void +HostNetDevice::CreateSlirp(bool startup) { #if defined(HAVE_HOSTNET_SLIRP) - driver.reset(new NetDriverSlirp(this)); + try { + driver.reset(new NetDriverSlirp(this)); + } catch (...) { } if ((bool)driver) { - if (driver->InitDriver()) { + if (driver->InitDriver(startup)) { // 成功 - return true; + return; } errmsg = driver->errmsg; driver.reset(); } #endif - return false; } -// Tap ドライバを生成する -bool +// Tap ドライバを生成する。 +// 戻り値はなく、成否は (bool)driver で判断する。 +void HostNetDevice::CreateTap() { #if defined(HAVE_HOSTNET_TAP) @@ -279,21 +330,23 @@ HostNetDevice::CreateTap() const ConfigItem& item = gConfig->Find(keyname); const std::string& devpath = item.AsString(); - driver.reset(new NetDriverTap(this, devpath)); + try { + driver.reset(new NetDriverTap(this, devpath)); + } catch (...) { } if ((bool)driver) { if (driver->InitDriver()) { // 成功 - return true; + return; } errmsg = driver->errmsg; driver.reset(); } #endif - return false; } -// bpf ドライバを生成する -bool +// bpf ドライバを生成する。 +// 戻り値はなく、成否は (bool)driver で判断する。 +void HostNetDevice::CreateBPF() { #if defined(HAVE_HOSTNET_BPF) @@ -302,21 +355,23 @@ HostNetDevice::CreateBPF() const ConfigItem& item = gConfig->Find(keyname); const std::string& ifname = item.AsString(); - driver.reset(new NetDriverBPF(this, ifname)); + try { + driver.reset(new NetDriverBPF(this, ifname)); + } catch (...) { } if ((bool)driver) { if (driver->InitDriver()) { // 成功 - return true; + return; } errmsg = driver->errmsg; driver.reset(); } #endif - return false; } -// AFPacket ドライバを生成する -bool +// AFPacket ドライバを生成する。 +// 戻り値はなく、成否は (bool)driver で判断する。 +void HostNetDevice::CreateAFPacket() { #if defined(HAVE_HOSTNET_AFPACKET) @@ -325,17 +380,18 @@ HostNetDevice::CreateAFPacket() const ConfigItem& item = gConfig->Find(keyname); const std::string& ifname = item.AsString(); - driver.reset(new NetDriverAFPacket(this, ifname)); + try { + driver.reset(new NetDriverAFPacket(this, ifname)); + } catch (...) { } if ((bool)driver) { if (driver->InitDriver()) { // 成功 - return true; + return; } errmsg = driver->errmsg; driver.reset(); } #endif - return false; } // VM からの送信 (VM スレッドで呼ばれる) @@ -364,8 +420,8 @@ HostNetDevice::Tx(const NetPacket& packe // ざっくりピーク値 stat.txq_peak = std::max((uint)txq.Length(), stat.txq_peak); - // パイプに通知 (値はダミー) - return WritePipe(0); + // パイプで通知。 + return WritePipe(PIPE_TX); } // rxq への投入を行う場合は true。 @@ -431,6 +487,7 @@ HostNetDevice::Read() int queued = 0; int left = 0; + std::lock_guard guard(driverlock); assert((bool)driver); do { @@ -524,10 +581,11 @@ HostNetDevice::Read() // 外部への書き出し(パケットを送信) void -HostNetDevice::Write(uint32 data) +HostNetDevice::Write() { const NetPacket *p; + std::lock_guard guard(driverlock); assert((bool)driver); // 送信キューから取り出す @@ -565,8 +623,9 @@ HostNetDevice::Write(uint32 data) // ドライバ名を返す const std::string -HostNetDevice::GetDriverName() const +HostNetDevice::GetDriverName() { + std::lock_guard guard(driverlock); assert((bool)driver); return driver->GetDriverName(); } @@ -587,10 +646,13 @@ HostNetDevice::MonitorUpdate(Monitor *, { screen.Clear(); - screen.Print(0, 0, "Parent Device : %s", parent->GetName().c_str()); - screen.Print(0, 1, "HostNet Driver: %s", driver->GetDriverName()); - // 次の2行はドライバ依存情報 - driver->MonitorUpdateMD(screen, 2); + screen.Print(0, 0, "Device(Port) : %s", GetPortName().c_str()); + { + std::lock_guard guard(driverlock); + screen.Print(0, 1, "HostNet Driver: %s", driver->GetDriverName()); + // 次の2行はドライバ依存情報 + driver->MonitorUpdateMD(screen, 2); + } // 01234567890123456 // Write to host