--- nono/host/hostnet.cpp 2026/04/29 17:05:21 1.1.1.3 +++ nono/host/hostnet.cpp 2026/04/29 17:05:30 1.1.1.5 @@ -32,6 +32,7 @@ #if defined(HAVE_HOSTNET_TAP) #include "netdriver_tap.h" #endif +#include // コンパイル済みのドライバ名一覧を返す (MainApp から呼ばれる) /*static*/ std::vector @@ -54,11 +55,11 @@ HostNetDevice::GetDrivers() // コンストラクタ -HostNetDevice::HostNetDevice(Device *parent_, int n) +HostNetDevice::HostNetDevice(Device *parent_, uint n) : inherited(parent_, OBJ_HOSTNET(n)) { monitor.func = ToMonitorCallback(&HostNetDevice::MonitorUpdate); - monitor.SetSize(48, 21); + monitor.SetSize(48, 23); monitor.Regist(ID_MONITOR_HOSTNET(n)); } @@ -267,6 +268,14 @@ HostNetDevice::CreateAFPacket() bool HostNetDevice::Tx(const NetPacket& packet) { + // 長さ 0 のパケットは破棄する。バグでもないと通常は起きない。 + // runt frame はどうするか? + if (packet.length < 1) { + stat.txzero_pkts++; + putlog(1, "Tx: drop empty packet"); + return true; + } + // 送信キューに入れて.. if (txq.Enqueue(packet) == false) { stat.txqfull_pkts++; @@ -279,7 +288,7 @@ HostNetDevice::Tx(const NetPacket& packe stat.tx_bytes += packet.length; // ざっくりピーク値 - stat.txq_peak = std::max((int)txq.Length(), stat.txq_peak); + stat.txq_peak = std::max((uint)txq.Length(), stat.txq_peak); // パイプに通知 (値はダミー) return WritePipe(0); @@ -299,6 +308,13 @@ HostNetDevice::SetMyAddr(const macaddr_t myaddr = myaddr_; } +// マルチキャストフィルタを設定する。 +void +HostNetDevice::SetMCastFilter(uint64 filter_) +{ + multicast_filter = filter_; +} + // プロミスキャスモードを設定する。 void HostNetDevice::SetPromisc(bool promisc_) @@ -318,10 +334,10 @@ HostNetDevice::Rx(NetPacket *dst) stat.rx_pkts++; stat.rx_bytes += dst->length; if (__predict_false(loglevel >= 2)) { - putlogn("Recv %d bytes", dst->length); + putlogn("Recv %u bytes", dst->length); if (loglevel >= 3) { std::string buf; - for (int i = 0; i < dst->length; i++) { + for (uint i = 0; i < dst->length; i++) { if (i % 16 == 0) { buf += string_format("%04x:", i); } @@ -406,35 +422,49 @@ HostNetDevice::Read() // パケットフィルタリング if (__predict_true(promisc == false)) { - bool accept = true; - if (__predict_false(packet[0] & 1)) { - // マルチキャスト - // XXX いまのところ全部通す -#if 0 + static std::array bcast { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + }; + if (memcmp(&packet[0], &bcast[0], bcast.size()) == 0) { + // ブロードキャストは素通し。 + } else if (__predict_false(packet[0] & 1)) { + // マルチキャスト。 // LANCE では LADRF レジスタ、NE2000 では MAR0-7 レジスタで - // データシートを見る限りはロジックは同じものに見える... + // データシートを見る限りはロジックは同じもののようだ。 - // 宛先アドレスの CRC32 を計算する - uint32 crc = ~crc32(~0U, &packet[0], 6); - // crc 上位 6bit をとりだして検査ビット位置とする - uint bit = 1 << (crc >> 26); - // LADRF,MAR の検査ビット位置が 1 ならば受信、0 ならば破棄 + // 宛先アドレスの CRC32 を計算する。 + // イーサネットの CRC は zlib の crc32() と同じもの。 + uint32 crc = crc32(0, Z_NULL, 0); + crc = crc32(crc, &packet[0], 6); + + // crc の上位6ビットをとりだして検査ビット位置とする(=pos)。 + // multicast_filter の pos の位置のビットが 1 なら受信、 + // 0 なら破棄。 + // multicast_filter は64ビットで LSB が0番目、MSB が63番目 + // としたもの (NIC 側でこの通りに並べ替えて渡してある)。 + uint pos = (crc >> 26) & 0x3f; + uint64 bit = 1U << pos; if ((multicast_filter & bit) == 0) { - filter = true; + putlog(2, "mcast %02x:%02x:%02x:%02x:%02x:%02x pos=%d drop", + packet[0], packet[1], packet[2], + packet[3], packet[4], packet[5], pos); + stat.rxmcast_pkts++; + stat.rxmcast_bytes += packet.length; + rxq.CancelWrite(); + continue; } -#endif + putlog(2, "mcast %02x:%02x:%02x:%02x:%02x:%02x pos=%d pass", + packet[0], packet[1], packet[2], + packet[3], packet[4], packet[5], pos); } else { // ユニキャスト if (memcmp(&packet[0], &myaddr[0], 6) != 0) { - accept = false; + stat.rxnotme_pkts++; + stat.rxnotme_bytes += packet.length; + rxq.CancelWrite(); + continue; } } - if (accept == false) { - stat.rxfilter_pkts++; - stat.rxfilter_bytes += packet.length; - rxq.CancelWrite(); - continue; - } } // CRC XXX 計算すること @@ -447,7 +477,7 @@ HostNetDevice::Read() } while (left > 0); // ざっくりピーク値 - stat.rxq_peak = std::max((int)rxq.Length(), stat.rxq_peak); + stat.rxq_peak = std::max((uint)rxq.Length(), stat.rxq_peak); return queued; } @@ -465,10 +495,10 @@ HostNetDevice::Write(uint32 data) const NetPacket& packet = *p; if (__predict_false(loglevel >= 2)) { - putlogn("Send %d bytes", packet.length); + putlogn("Send %u bytes", packet.length); if (loglevel >= 3) { std::string buf; - for (int i = 0; i < packet.length; i++) { + for (uint i = 0; i < packet.length; i++) { if (i % 16 == 0) { buf += string_format("%04x:", i); } @@ -527,6 +557,9 @@ HostNetDevice::MonitorUpdate(Monitor *, screen.Print(0, y++, "%-17s%13s %17s", "Write to host", format_number(stat.write_pkts).c_str(), format_number(stat.write_bytes).c_str()); + screen.Print(0, y++, "%-17s%13s %17s", "Drop:Empty Frame", + format_number(stat.txzero_pkts).c_str(), + "0"); screen.Print(0, y++, "%-17s%13s %17s", "Drop:TxQ Full", format_number(stat.txqfull_pkts).c_str(), format_number(stat.txqfull_bytes).c_str()); @@ -548,14 +581,17 @@ HostNetDevice::MonitorUpdate(Monitor *, screen.Print(0, y++, "%-17s%13s %17s", "Drop:RxQ Full", format_number(stat.rxqfull_pkts).c_str(), format_number(stat.rxqfull_bytes).c_str()); - screen.Print(0, y++, "%-17s%13s %17s", "Drop:Addr Filter", - format_number(stat.rxfilter_pkts).c_str(), - format_number(stat.rxfilter_bytes).c_str()); + screen.Print(0, y++, "%-17s%13s %17s", "Drop:Unicast", + format_number(stat.rxnotme_pkts).c_str(), + format_number(stat.rxnotme_bytes).c_str()); + screen.Print(0, y++, "%-17s%13s %17s", "Drop:Multicast", + format_number(stat.rxmcast_pkts).c_str(), + format_number(stat.rxmcast_bytes).c_str()); y++; screen.Print(5, y++, "Capacity Peak"); - screen.Print(0, y++, "TxQ %4d/%4d %4d", - (int)txq.Length(), (int)txq.Capacity(), stat.txq_peak); - screen.Print(0, y++, "RxQ %4d/%4d %4d", - (int)rxq.Length(), (int)rxq.Capacity(), stat.rxq_peak); + screen.Print(0, y++, "TxQ %4u/%4u %4u", + (uint)txq.Length(), (uint)txq.Capacity(), stat.txq_peak); + screen.Print(0, y++, "RxQ %4u/%4u %4u", + (uint)rxq.Length(), (uint)rxq.Capacity(), stat.rxq_peak); }