Annotation of nono/vm/ethernet.cpp, revision 1.1.1.5

1.1       root        1: //
                      2: // nono
1.1.1.3   root        3: // Copyright (C) 2020 nono project
                      4: // Licensed under nono-license.txt
1.1       root        5: //
                      6: 
                      7: #include "ethernet.h"
1.1.1.3   root        8: #include "config.h"
1.1.1.5 ! root        9: #include "netdriver_selector.h"
1.1       root       10: #include <random>
                     11: 
1.1.1.2   root       12: std::unique_ptr<EthernetDevice> gEthernet;
1.1       root       13: 
                     14: // コンストラクタ
1.1.1.5 ! root       15: EthernetDevice::EthernetDevice(const std::string& objname_)
        !            16:        : inherited(objname_)
1.1       root       17: {
                     18: }
                     19: 
                     20: // デストラクタ
                     21: EthernetDevice::~EthernetDevice()
                     22: {
                     23: }
                     24: 
                     25: // 動的なコンストラクション
                     26: bool
                     27: EthernetDevice::Create()
                     28: {
1.1.1.5 ! root       29:        try {
        !            30:                // ホストドライバをこのデバイスと紐付ける。
        !            31:                gNetDriverSelector.reset(new NetDriverSelector(this));
        !            32:                return true;
        !            33:        } catch (...) {
1.1       root       34:        }
1.1.1.5 ! root       35:        return false;
1.1       root       36: }
                     37: 
                     38: // MAC アドレスをてきとーに生成する。
                     39: // 02:00:01 はローカルだし割り当てもされてなさそうなので使っちゃえ。
                     40: // 下3バイトは乱数。
                     41: /*static*/ void
                     42: EthernetDevice::GenerateMacAddr(macaddr_t *addrp)
                     43: {
                     44:        std::random_device rnd;
                     45:        uint32 x = rnd();
                     46: 
                     47:        macaddr_t& addr = *addrp;
                     48:        addr[0] = 0x02;
                     49:        addr[1] = 0x00;
                     50:        addr[2] = 0x01;
                     51:        addr[3] = (x >> 16) & 0xff;
                     52:        addr[4] = (x >>  8) & 0xff;
                     53:        addr[5] = x & 0xff;
                     54: }
                     55: 
                     56: // MAC アドレス文字列をバイナリに変換して返す。
                     57: // "HH:HH:HH:HH:HH:HH" 形式のみ。
                     58: // 成功すれば true を返す。
                     59: /*static*/ bool
                     60: EthernetDevice::ParseMacAddr(macaddr_t& dst, const std::string& src)
                     61: {
                     62:        const char *p;
                     63:        char *e;
                     64: 
                     65:        p = src.data();
                     66:        for (int i = 0; ; ) {
                     67:                unsigned long val = strtoul(p, &e, 16);
                     68: 
                     69:                if (p == e) {
                     70:                        return false;
                     71:                }
                     72:                if (val > 0xff) {
                     73:                        return false;
                     74:                }
                     75:                dst[i++] = val;
                     76:                p = e;
                     77: 
                     78:                // 最後だけ ':' をチェックしないので
                     79:                if (i == 6) {
                     80:                        break;
                     81:                }
                     82: 
                     83:                if (*p++ != ':') {
                     84:                        return false;
                     85:                }
                     86:        }
                     87:        if (*p != '\0') {
                     88:                return false;
                     89:        }
                     90:        return true;
                     91: }
                     92: 
                     93: // パケットを送信する (VM から呼ばれる)
                     94: bool
                     95: EthernetDevice::SendPacket(const std::vector<uint8>& buf)
                     96: {
1.1.1.5 ! root       97:        tx_pkts++;
1.1       root       98:        return gNetDriver->SendPacket(buf);
                     99: }
1.1.1.5 ! root      100: 
        !           101: // パケット受信。
        !           102: // NetDriver スレッドから呼ばれる。
        !           103: // ロックは中で取るので、ロック解除状態で呼ぶこと。
        !           104: // XXX: 戻り値はなんだろう
        !           105: bool
        !           106: EthernetDevice::RecvPacket(RXPacket packet)
        !           107: {
        !           108:        std::lock_guard<std::mutex> lock(mtx);
        !           109: 
        !           110:        if (RecvEnabled == false) {
        !           111:                // 受信禁止状態
        !           112:                putlog(2, "%s: receive disabled", __func__);
        !           113:                return true;
        !           114:        }
        !           115: 
        !           116:        // イーサネットフレームより長いパケットはゲスト OS が期待していない。
        !           117:        // ここでドロップしてみる。
        !           118:        // これによりゲストでの dropping chained buffer が出なくなる。
        !           119:        // 1518(EthernetII) にするか 1522(802.1Q) にするかは未定。
        !           120:        if (packet->size() > 1518) {
        !           121:                // TODO: 統計とりたい
        !           122:                putlog(1, "%s: drop long packet(%zd)", __func__, packet->size());
        !           123:                return true;
        !           124:        }
        !           125: 
        !           126:        // XXX とりあえず 16 パケットをキューする。
        !           127:        // 入り切らないときは捨てる。
        !           128:        if (rxq.size() > 16) {
        !           129:                // 前のパケットをまだ処理中なので、このパケットは捨てる
        !           130:                putlog(1, "%s: discard %zd bytes, pending %zd packets", __func__,
        !           131:                        packet->size(), rxq.size());
        !           132:                return true;
        !           133:        }
        !           134:        putlog(1, "%s: enqueue %zd bytes, pending %zd packets", __func__,
        !           135:                packet->size(), rxq.size());
        !           136: 
        !           137:        // キューへ投入
        !           138:        rxq.push(std::move(packet));
        !           139:        rx_pkts++;
        !           140: 
        !           141:        // 継承クラスに通知
        !           142:        NotifyRecvPacket();
        !           143: 
        !           144:        return true;
        !           145: }

unix.superglobalmegacorp.com

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