|
|
1.1 root 1: //
2: // nono
3: // Copyright (C) 2020 nono project
4: // Licensed under nono-license.txt
5: //
6:
7: //
8: // ネットワークのホストデバイス
9: //
10:
11: #pragma once
12:
13: #include "hostdevice.h"
14: #include "macaddr.h"
15: #include "netdriver.h"
16: #include "spscqueue.h"
17:
1.1.1.9 ! root 18: // パケット。
! 19: class NetPacket
1.1 root 20: {
21: public:
1.1.1.2 root 22: NetPacket() {
23: Clear();
24: }
25:
1.1 root 26: // バッファをクリアする
1.1.1.2 root 27: void Clear() {
28: length = 0;
1.1.1.9 ! root 29: readpos = 0;
1.1.1.2 root 30: }
1.1 root 31:
1.1.1.9 ! root 32: // このパケットの内容を置き換える。
! 33: void Assign(const void *src, uint srclen);
! 34:
! 35: // バッファサイズ (パケット長) を変更する。
! 36: void Resize(uint newlength);
! 37:
1.1 root 38: // パケットに1バイト追加する
1.1.1.9 ! root 39: void Append(uint8 data);
1.1 root 40:
1.1.1.2 root 41: // 読み出し開始位置を設定
1.1.1.9 ! root 42: void Seek(size_t readpos_) { readpos = readpos_; }
! 43:
! 44: // バッファの先頭を返す。
! 45: uint8 *Data() { return buf.data(); }
! 46: const uint8 *Data() const { return buf.data(); }
! 47:
! 48: // パケットサイズを取得。
! 49: // NetDriver で受信してから HostNet で破棄されるまでの間だけ
! 50: // Length() が buf.size() を上回ることを許容する。
! 51: // データは buf に収まる分だけ書いておくが、実際には Length バイトの
! 52: // パケットだったことを示す。どのみち捨てられるのでデータが尻切れなことは
! 53: // 気にしない。あわよくばモニタ上で長いパケットだと示唆できるかも知れない
! 54: // という程度。
! 55: uint Length() const { return length; }
1.1.1.2 root 56:
57: // 読み出しの残りバイト数を返す
1.1.1.9 ! root 58: uint GetRemain() const { return Length() - readpos; }
1.1.1.2 root 59:
60: // 1バイト読み出す。EOP なら -1 を返す
61: uint32 Read() {
1.1.1.9 ! root 62: if (readpos < Length()) {
! 63: return buf[readpos++];
1.1.1.2 root 64: } else {
65: return (uint32)-1;
66: }
67: }
1.1.1.5 root 68:
1.1.1.9 ! root 69: // ポインタを進めず指定の位置のデータを読み出す。
! 70: // pos が不正なら -1 を返す。
! 71: uint32 Peek(uint pos) const {
! 72: if (pos < Length()) {
! 73: return buf[pos];
! 74: } else {
! 75: return (uint32)-1;
! 76: }
! 77: }
1.1.1.5 root 78:
1.1.1.9 ! root 79: private:
! 80: // 有効長
! 81: uint length {};
1.1.1.5 root 82: // 現在の読み出し位置
1.1.1.9 ! root 83: uint readpos {};
! 84:
! 85: std::array<uint8, 1536> buf {};
1.1 root 86: };
87:
1.1.1.6 root 88: // MAC アドレスフィルタ。
89: // VM 側デバイスはこれを多重継承して実装すること。
90: class IHWAddrFilter
91: {
92: // インタフェース風にするため、メンバ変数を持たせないこと。
93: public:
94: enum {
95: HPF_PASS = 0, // このフレームを受信する。
96: HPF_DROP_UNICAST, // このユニキャストフレームを破棄する。
97: HPF_DROP_MULTICAST, // このマルチキャストフレームを破棄する。
98: };
99:
100: public:
101: virtual ~IHWAddrFilter();
102:
103: // デバイスがこの dstaddr 宛のフレームを受け付けるかどうかを返す。
104: // デバイスは、自分宛て、ブロードキャスト、マルチキャスト
105: // (おそらくハッシュ)、プロミスキャスなどの状態を考慮すること。
106: virtual int HWAddrFilter(const MacAddr& dstaddr) const = 0;
107: };
108:
1.1 root 109: class HostNetDevice : public HostDevice
110: {
111: using inherited = HostDevice;
112: using NetTxQueue = SPSCQueue<NetPacket, 32>;
113: using NetRxQueue = SPSCQueue<NetPacket, 64>;
114:
115: // 統計情報
116: struct stat_t {
117: uint64 tx_pkts;
118: uint64 tx_bytes;
119: uint64 rx_pkts;
120: uint64 rx_bytes;
121: uint64 read_pkts;
122: uint64 read_bytes;
123: uint64 write_pkts;
124: uint64 write_bytes;
1.1.1.4 root 125: uint64 txzero_pkts; // 送信長0で破棄したパケット数
1.1.1.6 root 126: uint64 txunsupp_pkts; // 送信先が未対応で破棄したパケット数
127: uint64 txunsupp_bytes; // 送信先が未対応で破棄したバイト数
1.1.1.3 root 128: uint64 txqfull_pkts; // キューが一杯だった回数
1.1 root 129: uint64 txqfull_bytes; // キューに入れられなかったバイト数
130: uint64 rxdisable_pkts; // 上位層が受信無効
131: uint64 rxdisable_bytes; // 上位層が受信無効
132: uint64 rxjumbo_pkts; // 受信したジャンボパケット数
133: uint64 rxjumbo_bytes; // 受信したジャンボパケットのバイト数
1.1.1.3 root 134: uint64 rxqfull_pkts; // キューが一杯だった回数
1.1 root 135: uint64 rxqfull_bytes; // キューに入れられなかったバイト数
1.1.1.3 root 136: uint64 rxnotme_pkts; // ユニキャストで破棄したパケット数
137: uint64 rxnotme_bytes; // フィルタされたバイト数
138: uint64 rxmcast_pkts; // マルチキャストで破棄したパケット数
139: uint64 rxmcast_bytes; // フィルタされたバイト数
1.1 root 140:
1.1.1.4 root 141: uint txq_peak; // キューのおおよその最大使用量
142: uint rxq_peak; // キューのおおよその最大使用量
1.1 root 143: };
144:
145: public:
1.1.1.7 root 146: HostNetDevice(Device *parent_, uint n, const std::string& portname_);
1.1 root 147: ~HostNetDevice() override;
148:
149: void SetLogLevel(int loglevel_) override;
1.1.1.6 root 150: bool Create2() override;
1.1 root 151:
152: // パケットを送信する。
153: // data はプリアンブルを含まず、イーサネットフレームヘッダ(14バイト)、
154: // データ(46-1500バイト) からなる。FCS(CRC) (4バイト) は含まない。
155: // 送信キューに追加できれば true、出来なければ false を返す。
156: bool Tx(const NetPacket& packet);
157:
158: // パケットを引き取るために VM から呼ばれる。
159: // パケットが受信キューにあるときは packet にコピーして true を返す。
160: // キューが空なら false を返す。
161: bool Rx(NetPacket *packet);
162:
163: // 受信キューへの投入を許可/禁止する。
164: void EnableRx(bool enable);
165:
1.1.1.3 root 166: // マルチキャストフィルタを設定する。
167: void SetMCastFilter(uint64 filter);
168:
1.1.1.7 root 169: // ドライバ名を返す。
1.1.1.8 root 170: const std::string& GetDriverName();
1.1 root 171:
172: // 統計情報を返す (ステータスパネルから呼ばれる)
173: uint64 GetTXPkts() const { return stat.tx_pkts; }
174: uint64 GetRXPkts() const { return stat.rx_pkts; }
175:
1.1.1.6 root 176: // 統計情報に1パケット分加算する (これだけ SLIRP の裏スレッドから呼ばれる)
177: void CountTXUnsupp(size_t bytes);
178:
1.1 root 179: // コンパイル済みのドライバ名一覧を返す
180: static std::vector<std::string> GetDrivers();
181:
1.1.1.8 root 182: // libslirp のバージョン文字列を返す
183: static const char *GetSlirpVersion();
184:
1.1.1.6 root 185: // デバッグ用。
186: static std::vector<std::string> DumpHex(const void *, size_t);
187: static std::vector<std::string> DumpFrame(const void *, size_t);
188:
1.1 root 189: private:
1.1.1.7 root 190: bool SelectDriver(bool startup) override;
191: void CreateNone();
192: void CreateSlirp(bool startup);
193: void CreateTap();
194: void CreateBPF();
195: void CreateAFPacket();
1.1 root 196:
197: int Read() override;
198:
199: // 外部への書き出し(パケットを送信)
1.1.1.7 root 200: void Write() override;
1.1 root 201:
1.1.1.9 ! root 202: DECLARE_MONITOR_SCREEN(MonitorScreen);
1.1 root 203:
1.1.1.6 root 204: // デバッグ用 (下請け)
205: static std::vector<std::string> DumpARP(const void *, size_t);
206: static std::vector<std::string> DumpIPv4(const void *, size_t);
207: static std::vector<std::string> DumpICMPv4(const char *, const char *,
208: const void *, size_t);
209: static std::vector<std::string> DumpTCPv4(const char *, const char *,
210: const void *, size_t);
211: static std::vector<std::string> DumpUDPv4(const char *, const char *,
212: const void *, size_t);
213: static std::vector<std::string> DumpDHCP(const void *, size_t);
214: static std::vector<std::string> DumpIPv6(const void *, size_t);
215: static std::vector<std::string> DumpICMPv6(const char *, const char *,
216: const void *, size_t);
217: static std::string DumpDHCPAddrList(const uint8 *, size_t);
218: static std::string GetServByPort(uint16 port_be, const char *protoname);
219:
1.1 root 220: std::unique_ptr<NetDriver> driver {};
221:
222: bool rx_enable {};
1.1.1.3 root 223:
1.1 root 224: // キュー
225: NetTxQueue txq {};
226: NetRxQueue rxq {};
227:
228: // 統計情報
229: struct stat_t stat {};
230:
1.1.1.5 root 231: Monitor *monitor {};
1.1.1.6 root 232:
233: IHWAddrFilter *ihwaddrfilter {};
1.1 root 234: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.