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