Annotation of nono/host/hostnet.cpp, revision 1.1.1.2

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: // ログ名
                     12: //       Ethernet    HostDevice       NetDriver
                     13: //         |          |                |
                     14: //         v          v                v
                     15: //        Lance   -> HostNetDevice -> NetDriver***
                     16: // 表示名 (Lance)    (HostNet)       (HostNet.***)
                     17: // 識別名 "lance"    "hostnet"       "hostnet"
                     18: //
                     19: // HostNet は 1VM あたり高々1つなので COMDriver のように同じインスタンス間で
                     20: // 互いを区別する必要がないのと、NetDriver 派生クラス選択時はフォールバックも
                     21: // 含めて、どれが選択されるか複雑なこともあるのでログ表示名に自分のドライバ名
                     22: // も表示したい。
                     23: 
                     24: #include "hostnet.h"
                     25: #include "config.h"
                     26: #include "netdriver_none.h"
                     27: #if defined(HAVE_HOSTNET_AFPACKET)
                     28: #include "netdriver_afpacket.h"
                     29: #endif
                     30: #if defined(HAVE_HOSTNET_BPF)
                     31: #include "netdriver_bpf.h"
                     32: #endif
                     33: #if defined(HAVE_HOSTNET_TAP)
                     34: #include "netdriver_tap.h"
                     35: #endif
                     36: 
                     37: // コンパイル済みのドライバ名一覧を返す (MainApp から呼ばれる)
                     38: /*static*/ std::vector<std::string>
                     39: HostNetDevice::GetDrivers()
                     40: {
                     41:        std::vector<std::string> list;
                     42: 
                     43: #if defined(HAVE_HOSTNET_AFPACKET)
                     44:        list.emplace_back("afpacket");
                     45: #endif
                     46: #if defined(HAVE_HOSTNET_BPF)
                     47:        list.emplace_back("bpf");
                     48: #endif
                     49: #if defined(HAVE_HOSTNET_TAP)
                     50:        list.emplace_back("tap");
                     51: #endif
                     52: 
                     53:        return list;
                     54: }
                     55: 
                     56: 
                     57: // コンストラクタ
                     58: HostNetDevice::HostNetDevice()
1.1.1.2 ! root       59:        : inherited(OBJ_HOSTNET)
1.1       root       60: {
                     61:        monitor.func = ToMonitorCallback(&HostNetDevice::MonitorUpdate);
                     62:        monitor.SetSize(48, 20);
                     63:        monitor.Regist(ID_MONITOR_HOSTNET);
                     64: }
                     65: 
                     66: // デストラクタ
                     67: HostNetDevice::~HostNetDevice()
                     68: {
                     69: }
                     70: 
                     71: // ログレベル設定
                     72: void
                     73: HostNetDevice::SetLogLevel(int loglevel_)
                     74: {
                     75:        inherited::SetLogLevel(loglevel_);
                     76: 
                     77:        if ((bool)driver) {
                     78:                driver->SetLogLevel(loglevel_);
                     79:        }
                     80: }
                     81: 
                     82: // 初期化
                     83: bool
                     84: HostNetDevice::Init()
                     85: {
                     86:        if (inherited::Init() == false) {
                     87:                return false;
                     88:        }
                     89: 
                     90:        if (SelectDriver() == false) {
                     91:                return false;
                     92:        }
                     93: 
                     94:        return true;
                     95: }
                     96: 
                     97: // ドライバ(再)選択
                     98: bool
                     99: HostNetDevice::SelectDriver()
                    100: {
                    101:        const ConfigItem& item = gConfig->Find("hostnet-driver");
                    102:        const std::string& type = item.AsString();
                    103:        bool fallback = gConfig->Find("hostnet-fallback").AsInt();
                    104: 
                    105:        driver.reset();
                    106: 
                    107:        if (type != "none") {
                    108:                if (type == "tap") {
                    109: #if defined(HAVE_HOSTNET_TAP)
                    110:                        CreateTap();
                    111: #else
1.1.1.2 ! root      112:                        item.Err("Hostnet driver %s not compiled", type.c_str());
1.1       root      113: #endif
                    114: 
                    115:                } else if (type == "bpf") {
                    116: #if defined(HAVE_HOSTNET_BPF)
                    117:                        CreateBPF();
                    118: #else
1.1.1.2 ! root      119:                        item.Err("Hostnet driver %s not compiled", type.c_str());
1.1       root      120: #endif
                    121: 
                    122:                } else if (type == "afpacket") {
                    123: #if defined(HAVE_HOSTNET_AFPACKET)
                    124:                        CreateAFPacket();
                    125: #else
1.1.1.2 ! root      126:                        item.Err("Hostnet driver %s not compiled", type.c_str());
1.1       root      127: #endif
                    128: 
                    129:                } else if (type == "auto") {
                    130:                        // auto なら Tap -> { BPF, AFPacket } の順で試す。
                    131:                        //
                    132:                        // Tap は事前の準備が面倒だが制約がない。
                    133:                        // BPF, AFPacket (この2つは OS の違いだけでほぼ同じもの) は
                    134:                        // 準備に手間がかからないが自ホストと通信できない制約がある。
                    135:                        // そのためどの環境でも Tap が使えれば Tap を、そうでなければ
                    136:                        // BPF, AFPacket を使う、という順にしておく。
                    137:                        bool r;
                    138: 
                    139:                        r = CreateTap();
                    140:                        if (r == false) {
                    141:                                r = CreateAFPacket();
                    142:                        }
                    143:                        if (r == false) {
                    144:                                r = CreateBPF();
                    145:                        }
                    146: 
                    147:                } else {
                    148:                        // 知らないドライバ種別
                    149:                        item.Err();
                    150:                }
                    151: 
                    152:                if ((bool)driver == false) {
                    153:                        putmsg(1, "hostnet-fallback=%d", fallback ? 1 : 0);
                    154: 
                    155:                        if (fallback == false) {
                    156:                                // フォールバックしないならエラー終了
                    157:                                errmsg = "No host network driver found";
                    158:                                putmsg(1, "%s", errmsg.c_str());
                    159:                                warnx("%s (See details with options -C -Lhostnet=1)",
                    160:                                        errmsg.c_str());
                    161: 
                    162:                                return false;
                    163:                        }
                    164:                }
                    165:        }
                    166: 
                    167:        if ((bool)driver == false) {
                    168:                CreateNone();
                    169:        }
                    170:        assert((bool)driver);
                    171: 
                    172:        // ドライバ名は Capitalize だがログはほぼ小文字なので雰囲気を揃える…
                    173:        putmsg(1, "selected host driver: %s",
                    174:                string_tolower(driver->GetDriverName()).c_str());
                    175: 
                    176:        return true;
                    177: }
                    178: 
                    179: // None ドライバを生成する
                    180: bool
                    181: HostNetDevice::CreateNone()
                    182: {
                    183:        driver.reset(new NetDriverNone(this));
                    184:        if ((bool)driver) {
                    185:                if (driver->InitDriver()) {
                    186:                        // 成功
                    187:                        return true;
                    188:                }
                    189:                errmsg = driver->errmsg;
                    190:                driver.reset();
                    191:        }
                    192:        return false;
                    193: }
                    194: 
                    195: // Tap ドライバを生成する
                    196: bool
                    197: HostNetDevice::CreateTap()
                    198: {
                    199: #if defined(HAVE_HOSTNET_TAP)
                    200:        const ConfigItem& item = gConfig->Find("hostnet-tap-devpath");
                    201:        const std::string& devpath = item.AsString();
                    202: 
                    203:        driver.reset(new NetDriverTap(this, devpath));
                    204:        if ((bool)driver) {
                    205:                if (driver->InitDriver()) {
                    206:                        // 成功
                    207:                        return true;
                    208:                }
                    209:                errmsg = driver->errmsg;
                    210:                driver.reset();
                    211:        }
                    212: #endif
                    213:        return false;
                    214: }
                    215: 
                    216: // bpf ドライバを生成する
                    217: bool
                    218: HostNetDevice::CreateBPF()
                    219: {
                    220: #if defined(HAVE_HOSTNET_BPF)
                    221:        const ConfigItem& item = gConfig->Find("hostnet-bpf-ifname");
                    222:        const std::string& ifname = item.AsString();
                    223: 
                    224:        driver.reset(new NetDriverBPF(this, ifname));
                    225:        if ((bool)driver) {
                    226:                if (driver->InitDriver()) {
                    227:                        // 成功
                    228:                        return true;
                    229:                }
                    230:                errmsg = driver->errmsg;
                    231:                driver.reset();
                    232:        }
                    233: #endif
                    234:        return false;
                    235: }
                    236: 
                    237: // AFPacket ドライバを生成する
                    238: bool
                    239: HostNetDevice::CreateAFPacket()
                    240: {
                    241: #if defined(HAVE_HOSTNET_AFPACKET)
                    242:        const ConfigItem& item = gConfig->Find("hostnet-afpacket-ifname");
                    243:        const std::string& ifname = item.AsString();
                    244: 
                    245:        driver.reset(new NetDriverAFPacket(this, ifname));
                    246:        if ((bool)driver) {
                    247:                if (driver->InitDriver()) {
                    248:                        // 成功
                    249:                        return true;
                    250:                }
                    251:                errmsg = driver->errmsg;
                    252:                driver.reset();
                    253:        }
                    254: #endif
                    255:        return false;
                    256: }
                    257: 
                    258: // VM からの送信 (VM スレッドで呼ばれる)
                    259: bool
                    260: HostNetDevice::Tx(const NetPacket& packet)
                    261: {
                    262:        // 送信キューに入れて..
                    263:        if (txq.Enqueue(packet) == false) {
                    264:                stat.txqfull_pkts++;
                    265:                stat.txqfull_bytes += packet.length;
                    266:                putlog(2, "txq exhausted");
                    267:                return false;
                    268:        }
                    269: 
                    270:        stat.tx_pkts++;
                    271:        stat.tx_bytes += packet.length;
                    272: 
                    273:        // ざっくりピーク値
                    274:        stat.txq_peak = std::max((int)txq.Length(), stat.txq_peak);
                    275: 
                    276:        // パイプに通知 (値はダミー)
                    277:        return WritePipe(0);
                    278: }
                    279: 
                    280: // rxq への投入を行う場合は true
                    281: void
                    282: HostNetDevice::EnableRx(bool enable)
                    283: {
                    284:        rx_enable = enable;
                    285: }
                    286: 
                    287: // 自身の MAC アドレスを設定する。
                    288: void
                    289: HostNetDevice::SetMyAddr(const macaddr_t& myaddr_)
                    290: {
                    291:        myaddr = myaddr_;
                    292: }
                    293: 
                    294: // プロミスキャスモードを設定する。
                    295: void
                    296: HostNetDevice::SetPromisc(bool promisc_)
                    297: {
                    298:        promisc = promisc_;
                    299: }
                    300: 
                    301: // パケットをキューから取り出す。
                    302: // VM 側から呼ばれる。
                    303: bool
                    304: HostNetDevice::Rx(NetPacket *dst)
                    305: {
                    306:        if (rxq.Dequeue(dst) == false) {
                    307:                // キューが空
                    308:                return false;
                    309:        }
                    310:        stat.rx_pkts++;
                    311:        stat.rx_bytes += dst->length;
                    312:        putlog(2, "Recv %d bytes", dst->length);
                    313: 
                    314:        return true;
                    315: }
                    316: 
                    317: // 外部からの読み込み (パケットを受信)。
                    318: // 戻り値はキューに投入したパケット数。
                    319: int
                    320: HostNetDevice::Read()
                    321: {
                    322:        int queued = 0;
                    323:        int left = 0;
                    324: 
                    325:        assert((bool)driver);
                    326: 
                    327:        do {
                    328:                NetPacket *p;
                    329: 
                    330:                p = rxq.BeginWrite();
                    331:                if (p == NULL) {
                    332:                        NetPacket discard;
                    333:                        left = driver->Read(&discard);
                    334:                        if (left < 0) {
                    335:                                break;
                    336:                        }
                    337:                        stat.rxqfull_pkts++;
                    338:                        stat.rxqfull_bytes += discard.length;
                    339:                        continue;
                    340:                }
                    341: 
                    342:                // driver->Read() は VM に投入すべきパケットがなければ負数を返す。
                    343:                // パケットがあれば p に書き戻して、driver 側のバッファに残っている
                    344:                // パケット数 (といっても 0 か 1以上) を返してくる。
                    345:                left = driver->Read(p);
                    346:                if (left < 0) {
                    347:                        rxq.CancelWrite();
                    348:                        break;
                    349:                }
                    350: 
                    351:                NetPacket& packet = *p;
                    352: 
                    353:                stat.read_pkts++;
                    354:                stat.read_bytes += packet.length;
                    355: 
                    356:                if (rx_enable == false) {
                    357:                        rxq.CancelWrite();
                    358:                        stat.rxdisable_pkts++;
                    359:                        stat.rxdisable_bytes += packet.length;
                    360:                        continue;
                    361:                }
                    362: 
                    363:                // イーサネットフレームより長いパケットはゲスト OS が期待していない。
                    364:                // ここでドロップしてみる。
                    365:                // これによりゲストでの dropping chained buffer が出なくなる。
                    366:                if (packet.length > 1518) {
                    367:                        rxq.CancelWrite();
                    368:                        stat.rxjumbo_pkts++;
                    369:                        stat.rxjumbo_bytes += packet.length;
                    370:                        continue;
                    371:                }
                    372: 
                    373:                // ホストカーネルから直接着信したパケット(というかフレームか)は
                    374:                // 60バイトパディングされないまま読み出せるので、ここでパディングする。
                    375:                while (packet.length < 60) {
                    376:                        packet.Append(0x00);
                    377:                }
                    378: 
                    379:                // パケットフィルタリング
                    380:                if (__predict_true(promisc == false)) {
                    381:                        bool filter = false;
                    382:                        if (__predict_false(packet[0] & 1)) {
                    383:                                // マルチキャスト
                    384:                                // XXX いまのところ全部通す
                    385: #if 0
                    386:                                // LANCE では LADRF レジスタ、NE2000 では MAR0-7 レジスタで
                    387:                                // データシートを見る限りはロジックは同じものに見える...
                    388: 
                    389:                                // 宛先アドレスの CRC32 を計算する
                    390:                                uint32 crc = ~crc32(~0U, &packet[0], 6);
                    391:                                // crc 上位 6bit をとりだして検査ビット位置とする
                    392:                                uint bit = 1 << (crc >> 26);
                    393:                                // LADRF,MAR の検査ビット位置が 1 ならば受信、0 ならば破棄
                    394:                                if ((multicast_filter & bit) == 0) {
                    395:                                        filter = true;
                    396:                                }
                    397: #endif
                    398:                        } else {
                    399:                                // ユニキャスト
                    400:                                if (memcmp(&packet[0], &myaddr[0], 6) != 0) {
                    401:                                        filter = true;
                    402:                                }
                    403:                        }
                    404:                        if (filter) {
                    405:                                stat.rxfilter_pkts++;
                    406:                                stat.rxfilter_bytes += packet.length;
                    407:                                rxq.CancelWrite();
                    408:                                continue;
                    409:                        }
                    410:                }
                    411: 
                    412:                // CRC XXX 計算すること
                    413:                for (int i = 0; i < 4; i++) {
                    414:                        packet.Append(0x00);
                    415:                }
                    416: 
                    417:                rxq.EndWrite();
                    418:                queued++;
                    419:        } while (left > 0);
                    420: 
                    421:        // ざっくりピーク値
                    422:        stat.rxq_peak = std::max((int)rxq.Length(), stat.rxq_peak);
                    423: 
                    424:        return queued;
                    425: }
                    426: 
                    427: // 外部への書き出し(パケットを送信)
                    428: void
                    429: HostNetDevice::Write(uint32 data)
                    430: {
                    431:        const NetPacket *p;
                    432: 
                    433:        assert((bool)driver);
                    434: 
                    435:        // 送信キューから取り出す
                    436:        while ((p = txq.BeginRead()) != NULL) {
                    437:                const NetPacket& packet = *p;
                    438: 
                    439:                putlog(2, "Send %d bytes", packet.length);
                    440:                stat.write_pkts++;
                    441:                stat.write_bytes += packet.length;
                    442: 
                    443:                driver->Write(packet.data(), packet.length);
                    444:                txq.EndRead();
                    445:        }
                    446: }
                    447: 
                    448: // ドライバ名を返す
                    449: const std::string
                    450: HostNetDevice::GetDriverName() const
                    451: {
                    452:        assert((bool)driver);
                    453:        return driver->GetDriverName();
                    454: }
                    455: 
                    456: // モニタ
                    457: void
                    458: HostNetDevice::MonitorUpdate(Monitor *, TextScreen& screen)
                    459: {
                    460:        screen.Clear();
                    461: 
                    462:        screen.Print(0, 0, "HostNet Driver: %s", driver->GetDriverName());
                    463:        // 次の2行はドライバ依存情報
                    464:        driver->MonitorUpdateMD(screen);
                    465: 
                    466:        // 01234567890123456
                    467:        // Write to host
                    468:        // Drop:TxQ Full
                    469:        // Drop:Rx Disabled
                    470:        // Drop:Jumbo Frame
                    471:        // Drop:Addr Filter
                    472: 
                    473:        int y = 4;
                    474:        screen.Print(0, y++, "%-17s%13s %17s", "<Tx>", "Packets", "Bytes");
                    475:        screen.Print(0, y++, "%-17s%13s %17s", "VM sends",
                    476:                format_number(stat.tx_pkts).c_str(),
                    477:                format_number(stat.tx_bytes).c_str());
                    478:        screen.Print(0, y++, "%-17s%13s %17s", "Write to host",
                    479:                format_number(stat.write_pkts).c_str(),
                    480:                format_number(stat.write_bytes).c_str());
                    481:        screen.Print(0, y++, "%-17s%13s %17s", "Drop:TxQ Full",
                    482:                format_number(stat.txqfull_pkts).c_str(),
                    483:                format_number(stat.txqfull_bytes).c_str());
                    484:        y++;
                    485: 
                    486:        screen.Print(0, y++, "%-17s%13s %17s", "<Rx>", "Packets", "Bytes");
                    487:        screen.Print(0, y++, "%-17s%13s %17s", "Read from host",
                    488:                format_number(stat.read_pkts).c_str(),
                    489:                format_number(stat.read_bytes).c_str());
                    490:        screen.Print(0, y++, "%-17s%13s %17s", "VM receives",
                    491:                format_number(stat.rx_pkts).c_str(),
                    492:                format_number(stat.rx_bytes).c_str());
                    493:        screen.Print(0, y++, "%-17s%13s %17s", "Drop:Rx Disabled",
                    494:                format_number(stat.rxdisable_pkts).c_str(),
                    495:                format_number(stat.rxdisable_bytes).c_str());
                    496:        screen.Print(0, y++, "%-17s%13s %17s", "Drop:Jumbo Frame",
                    497:                format_number(stat.rxjumbo_pkts).c_str(),
                    498:                format_number(stat.rxjumbo_bytes).c_str());
                    499:        screen.Print(0, y++, "%-17s%13s %17s", "Drop:RxQ Full",
                    500:                format_number(stat.rxqfull_pkts).c_str(),
                    501:                format_number(stat.rxqfull_bytes).c_str());
                    502:        screen.Print(0, y++, "%-17s%13s %17s", "Drop:Addr Filter",
                    503:                format_number(stat.rxfilter_pkts).c_str(),
                    504:                format_number(stat.rxfilter_bytes).c_str());
                    505:        y++;
                    506: 
                    507:        screen.Print(5, y++, "Capacity Peak");
                    508:        screen.Print(0, y++, "TxQ %4d/%4d %4d",
                    509:                (int)txq.Length(), (int)txq.Capacity(), stat.txq_peak);
                    510:        screen.Print(0, y++, "RxQ %4d/%4d %4d",
                    511:                (int)rxq.Length(), (int)rxq.Capacity(), stat.rxq_peak);
                    512: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.