--- nono/host/netdriver.h 2026/04/29 17:04:30 1.1.1.2 +++ nono/host/netdriver.h 2026/04/29 17:05:47 1.1.1.11 @@ -1,84 +1,51 @@ // // nono -// Copyright (C) 2019 isaki@NetBSD.org +// Copyright (C) 2020 nono project +// Licensed under nono-license.txt +// + +// +// ホストネットワークのドライバ (基本クラス) // #pragma once -#include "object.h" -#include "ethernet.h" -#include -#include +#include "driver.h" +#include "autofd.h" -class NetDriver : public Object +class NetPacket; + +class NetDriver : public Driver { - public: - // コンストラクタ - NetDriver(const char *name, EthernetDevice *parent, - std::mutex *m, std::condition_variable *c); - - // デストラクタ。 - virtual ~NetDriver(); - - // 初期化 & オープン。 - // EthernetDevice::Init() から呼ばれる。諸制約については device.h 参照。 - // 必要なオープン処理や、必要なら受信スレッドの作成を行う。 - // 成功すれば true、失敗すれば warn()/warnx() でメッセージを出力して - // false を返すこと。 - // また、クローズ相当の動作はなくデストラクタで行う。 - virtual bool Init() = 0; - - virtual bool MonitorUpdate(); - - // パケットを送信する。正常に送信できれば 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 を更新すること。 - virtual void ThreadRun() = 0; + using inherited = Driver; protected: - // オープンされていれば true を返す。 - bool IsOpen() const { return fd != -1; } + NetDriver(HostDevice *hostdev_, const char *drivername_); + public: + ~NetDriver() override; - // 受信スレッドを起動する (必要なら継承クラス側が呼ぶ) - bool InitRecvThread(); + // パケットを外部から受信する。 + // VM に送り込むパケットがなければ負数(NODATA)を返す。 + // VM に送り込むパケットがあれば p に書き戻して、ドライバ側のバッファに + // 残っているパケット数 (といっても 0 か 1以上) を返す。 + virtual int Read(NetPacket *p) = 0; - const char *drivername = NULL; // ドライバ名 - EthernetDevice *parent = NULL; // 親 + // パケットを外部に送信する。 + virtual void Write(const void *buf, int buflen) = 0; - std::string devpath; // デバイスファイルパス - std::string ifname; // 作成したインタフェース名 + protected: + // ifup/ifdown スクリプト実行 + bool Run_ifup(); + bool Run_ifdown(); + + std::string ifname {}; // (あれば)作成したインタフェース名 // デバイスディスクリプタ。 // ディスクリプタを持つというのは共通なのでディスクリプタはここに置くが // これを Open(), Close() するのはあくまで継承側の仕事で、こちらでは - // 初期化と IsOpen() だけ受け持つ。ちょっと責任分解点が気持ち悪いけど。 - int fd = 0; - - // 親(Ethernet)デバイスの mutex と condvar - std::mutex *mtx; - std::condition_variable *cv; - - // 統計情報 - uint64 tx_pkts = 0; - uint64 rx_pkts = 0; - uint64 tx_bytes = 0; - uint64 rx_bytes = 0; - - // ifup/ifdown スクリプト実行 - bool Run_ifup(); - bool Run_ifdown(); + // 初期化と IsOpen() だけ受け持つ。ちょっと責任分界点が気持ち悪いけど。 + autofd fd {}; private: bool RunScript(const char *filename); }; - -extern std::unique_ptr gNetDriver;