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

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

unix.superglobalmegacorp.com

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