--- nono/host/netdriver.h 2026/04/29 17:04:54 1.1.1.8 +++ nono/host/netdriver.h 2026/04/29 17:05:11 1.1.1.9 @@ -4,83 +4,48 @@ // Licensed under nono-license.txt // +// +// ホストネットワークのドライバ (基本クラス) +// + #pragma once -#include "device.h" -#include "ethernet.h" -#include "monitor.h" -#include -#include +#include "driver.h" +#include "autofd.h" -class NetDriver : public Device +class NetPacket; + +class NetDriver : public Driver { - using inherited = Device; - protected: - // コンストラクタ - NetDriver(const char *name, EthernetDevice *parent, int loglevel_); + using inherited = Driver; + protected: + NetDriver(HostDevice *hostdev_, const char *drivername_); public: - // デストラクタ。 virtual ~NetDriver() override; - // デバイス初期化 & オープン。 - // NetDriverSelector::InitDriver() から呼ばれる。 - // この中ではログ出力が可能。まずどれが呼ばれたかを putmsg(1) で表示し - // 必要なオープン処理を行う。 - // 成功すれば true、失敗すれば warn()/warnx() でメッセージを出力して - // false を返すこと。 - // また、これに対応するクローズ相当の動作はなくデストラクタで行う。 - virtual bool InitDriver() = 0; - - // こっちは Device クラス由来の Init()。VM::Init() から呼ばれる。 - // ここで受信スレッドを起動する。 - bool Init() override; - - // パケットを送信する。正常に送信できれば true を返す。 - // EthernetDevice::SendPacket() が呼ばれると常に呼び出される。 - // その上で、ドライバが有効かどうか(オープンされているかどうかなど) は - // すべてこちら(NetDriver)側の責任。 - // data はプリアンブルを含まず、イーサネットフレームヘッダ(14バイト)、 - // データ(46-1500バイト) からなる。FCS(CRC) (4バイト) は含まない。 - // VM から引き取ったパケットについて tx_pkts, tx_bytes を更新すること - // false が返った場合の規定が不明。 - virtual bool SendPacket(const std::vector& data) = 0; - - // 受信スレッド。 - // VM に引き渡せたパケットについて rx_pkts, rx_bytes を更新すること。 - void ThreadRun(); + // パケットを外部から受信する。 + // VM に送り込むパケットがなければ負数(NODATA)を返す。 + // VM に送り込むパケットがあれば p に書き戻して、ドライバ側のバッファに + // 残っているパケット数 (といっても 0 か 1以上) を返す。 + virtual int Read(NetPacket *p) = 0; - // オープンされていれば true を返す。 - bool IsOpen() const { return fd != -1; } - - // ドライバ名を返す。 - const char *GetDriverName() const { return drivername; } + // パケットを外部に送信する。 + virtual void Write(const void *buf, int buflen) = 0; // InitDriver() 中の(主に最後の)エラーメッセージ。 // NetDriver は複数を順番に試す場合もあるし、全部エラーになっても終了する // かどうかは設定によるので、各ドライバはエラーが発生しても各自で warnx に // よる表示はせず、ここにエラーメッセージをセットする。必要になった時点で - // NetDriverSelector が最後の一つを warnx() で表示する。 + // HostNetDevice が最後の一つを warnx() で表示する。 // なお、おそらくそれだけでは大抵何も分からないのでこれとは別に // ログレベル 1 で putmsg() は充実させておくこと。 std::string errmsg {}; protected: - // 受信パケットキューにパケットを一つ追加する - void RecvEnqueue(uint8 *buf, size_t len); - - // パケットを受信する。read(2) と同じように値を返す。 - virtual ssize_t RecvPacket() = 0; - - // モニタのうちドライバ依存部分の情報を書き出す。 - // screen のうち (0から数えて) 1行目と2行目のみがドライバ依存部分なので - // ここだけ書き出すこと。不要なら書き出さなくてよい。Clear() しないこと。 - virtual void MonitorUpdateMD(TextScreen& screen) = 0; - - DECLARE_MONITOR_CALLBACK(MonitorUpdate); - - const char *drivername {}; // ドライバ名 - EthernetDevice *parent {}; // 親 + // ifup/ifdown スクリプト実行 + bool Run_ifup(); + bool Run_ifdown(); std::string ifname {}; // (あれば)作成したインタフェース名 @@ -88,22 +53,8 @@ class NetDriver : public Device // ディスクリプタを持つというのは共通なのでディスクリプタはここに置くが // これを Open(), Close() するのはあくまで継承側の仕事で、こちらでは // 初期化と IsOpen() だけ受け持つ。ちょっと責任分解点が気持ち悪いけど。 - int fd {}; - - // 統計情報 - uint64 tx_pkts = 0; - uint64 rx_pkts = 0; - uint64 tx_bytes = 0; - uint64 rx_bytes = 0; - - // ifup/ifdown スクリプト実行 - bool Run_ifup(); - bool Run_ifdown(); + autofd fd {}; private: bool RunScript(const char *filename); - - Monitor monitor { this }; }; - -extern std::unique_ptr gNetDriver;