--- nono/host/hostnet.cpp 2026/04/29 17:05:43 1.1.1.8 +++ nono/host/hostnet.cpp 2026/04/29 17:05:55 1.1.1.11 @@ -77,10 +77,12 @@ #endif #if defined(HAVE_HOSTNET_SLIRP) #include "netdriver_slirp.h" +#include #endif #if defined(HAVE_HOSTNET_TAP) #include "netdriver_tap.h" #endif +#include "uimessage.h" #include #include #include @@ -108,10 +110,23 @@ HostNetDevice::GetDrivers() return list; } +// libslirp のバージョン文字列を返す。 +// libslirp が有効でなければ NULL を返す。 +/*static*/ const char * +HostNetDevice::GetSlirpVersion() +{ +#if defined(SLIRP_VERSION_STRING) + return SLIRP_VERSION_STRING; +#else + return NULL; +#endif +} + // コンストラクタ -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 +134,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 +158,7 @@ HostNetDevice::SetLogLevel(int loglevel_ { inherited::SetLogLevel(loglevel_); + RWLockGuard_Read guard(driverlock); if ((bool)driver) { driver->SetLogLevel(loglevel_); } @@ -145,25 +172,29 @@ HostNetDevice::Create2() return false; } - if (SelectDriver() == false) { + 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(); + RWLockGuard_Write 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 +205,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; + gMainApp.GetUIMessage()->Post(UIMessage::HOSTNET_FAILED, n); + + CreateNone(); + } } assert((bool)driver); @@ -235,8 +284,9 @@ HostNetDevice::SelectDriver() return true; } -// None ドライバを生成する -bool +// None ドライバを生成する。 +// 戻り値はなく、成否は (bool)driver で判断する。 +void HostNetDevice::CreateNone() { try { @@ -245,36 +295,36 @@ HostNetDevice::CreateNone() 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) 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) @@ -289,17 +339,17 @@ HostNetDevice::CreateTap() 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) @@ -314,17 +364,17 @@ HostNetDevice::CreateBPF() 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) @@ -339,13 +389,12 @@ HostNetDevice::CreateAFPacket() if ((bool)driver) { if (driver->InitDriver()) { // 成功 - return true; + return; } errmsg = driver->errmsg; driver.reset(); } #endif - return false; } // VM からの送信 (VM スレッドで呼ばれる) @@ -374,8 +423,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。 @@ -441,6 +490,7 @@ HostNetDevice::Read() int queued = 0; int left = 0; + RWLockGuard_Read guard(driverlock); assert((bool)driver); do { @@ -534,10 +584,11 @@ HostNetDevice::Read() // 外部への書き出し(パケットを送信) void -HostNetDevice::Write(uint32 data) +HostNetDevice::Write() { const NetPacket *p; + RWLockGuard_Read guard(driverlock); assert((bool)driver); // 送信キューから取り出す @@ -574,9 +625,10 @@ HostNetDevice::Write(uint32 data) } // ドライバ名を返す -const std::string -HostNetDevice::GetDriverName() const +const std::string& +HostNetDevice::GetDriverName() { + RWLockGuard_Read guard(driverlock); assert((bool)driver); return driver->GetDriverName(); } @@ -597,10 +649,14 @@ 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()); + { + RWLockGuard_Read guard(driverlock); + screen.Print(0, 1, "HostNet Driver: %s", + driver->GetDriverName().c_str()); + // 次の2行はドライバ依存情報 + driver->MonitorUpdateMD(screen, 2); + } // 01234567890123456 // Write to host