--- nono/host/hostnet.cpp 2026/04/29 17:05:21 1.1.1.3 +++ nono/host/hostnet.cpp 2026/04/29 17:05:26 1.1.1.4 @@ -32,6 +32,7 @@ #if defined(HAVE_HOSTNET_TAP) #include "netdriver_tap.h" #endif +#include // コンパイル済みのドライバ名一覧を返す (MainApp から呼ばれる) /*static*/ std::vector @@ -58,7 +59,7 @@ HostNetDevice::HostNetDevice(Device *par : inherited(parent_, OBJ_HOSTNET(n)) { monitor.func = ToMonitorCallback(&HostNetDevice::MonitorUpdate); - monitor.SetSize(48, 21); + monitor.SetSize(48, 22); monitor.Regist(ID_MONITOR_HOSTNET(n)); } @@ -299,6 +300,13 @@ HostNetDevice::SetMyAddr(const macaddr_t myaddr = myaddr_; } +// マルチキャストフィルタを設定する。 +void +HostNetDevice::SetMCastFilter(uint64 filter_) +{ + multicast_filter = filter_; +} + // プロミスキャスモードを設定する。 void HostNetDevice::SetPromisc(bool promisc_) @@ -406,35 +414,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() と同じもの。 + ulong 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 計算すること @@ -548,9 +570,12 @@ 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");