|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.