|
|
1.1 root 1: //
2: // nono
3: // Copyright (C) 2020 nono project
4: // Licensed under nono-license.txt
5: //
6:
7: // EthernetDevice::CRC32() のテスト。
8:
9: #include "header.h"
10: #include "bitops.h"
11: #include "macaddr.h"
12: #include "stopwatch.h"
13: #include <signal.h>
14: #include <sys/time.h>
15:
16: // パフォーマンステストの秒数
17: #define PERF_SEC (2)
18:
19: class EthernetDevice
20: {
21: public:
22: static uint32 CRC32(const uint8 *buf, size_t buflen);
23: static uint32 CRC32(const MacAddr& mac);
24: };
25:
26: #define SELFTEST
27: #include "ethernet.cpp"
28:
29: // testnum は 0 が通常の CRC、1 が MAC アドレス用 CRC。
30: static void
31: do_test(int testnum)
32: {
33: struct {
34: uint8 src[6];
35: uint32 expected;
36: } table[] = {
37: { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 0x3a7abc72 },
38: { { 0x33, 0x33, 0x00, 0x00, 0x00, 0x01 }, 0xf99baaba },
39: };
40: int failed = 0;
41:
42: if (testnum == 0) {
43: printf("Test(buf)");
44: } else {
45: printf("Test(mac)");
46: }
47:
48: for (size_t i = 0; i < countof(table); i++) {
49: const uint8 *src = table[i].src;
50: uint32 expected = table[i].expected;
51: uint32 actual;
52: if (testnum == 0) {
53: actual = EthernetDevice::CRC32(src, 6);
54: } else {
55: MacAddr mac(src);
56: actual = EthernetDevice::CRC32(mac);
57: }
58:
59: if (actual != expected) {
60: if (failed == 0) {
61: printf("\n");
62: }
63: printf("FAILED: %02x%02x%02x%02x%02x%02x expects %08x but got %08x",
64: src[0], src[1], src[2], src[3], src[4], src[5],
65: expected, actual);
66:
67: // 念のため反転して一致するか。
68: uint32 revact = bitrev32(actual);
69: if (revact == expected) {
70: printf(" (bit-reversed)");
71: }
72:
73: printf(" !\n");
74: failed++;
75: }
76: }
77: if (failed == 0) {
78: printf("..OK\n");
79: }
80: }
81:
82: static volatile uint32 perf_signaled;
83: static uint64 perf_count;
84: static Stopwatch sw;
85:
86: static void
87: signal_alarm(int signo)
88: {
89: perf_signaled = 1;
90: }
91:
92: static void
93: start_perf_func(const char *name)
94: {
95: printf("%s\t... ", name);
96: fflush(stdout);
97:
98: perf_count = 0;
99: perf_signaled = 0;
100: signal(SIGALRM, signal_alarm);
101: struct itimerval it = {};
102: it.it_value.tv_sec = PERF_SEC;
103:
104: sw.Restart();
105: setitimer(ITIMER_REAL, &it, NULL);
106: }
107:
108: static void
109: end_perf_func()
110: {
111: sw.Stop();
112:
113: uint64 usec = sw.Elapsed() / 1000;
114: printf("%6.2f times/usec\n", (double)perf_count / usec);
115: }
116:
117: // ターゲット長がMACアドレスで従来の CRC32(buf)。
118: static void
119: do_perf_mac_old()
120: {
121: union {
122: uint8 buf[6];
123: uint32 u32;
124: };
125:
126: memset(&buf, 0, sizeof(buf));
127: MacAddr mac(buf);
128: start_perf_func("macaddr.old");
129: while (perf_signaled == 0) {
130: volatile uint32 crc;
131: crc = EthernetDevice::CRC32(buf, sizeof(buf));
132: perf_count++;
133: u32 = crc;
134: }
135: end_perf_func();
136: }
137:
138: // ターゲット長がMACアドレスで CRC32(mac)。
139: static void
140: do_perf_mac_new()
141: {
142: union {
143: uint8 buf[6];
144: uint32 u32;
145: };
146:
147: memset(&buf, 0, sizeof(buf));
148: MacAddr mac(buf);
149: start_perf_func("macaddr.new");
150: while (perf_signaled == 0) {
151: volatile uint32 crc;
152: crc = EthernetDevice::CRC32(mac);
153: perf_count++;
154: u32 = crc;
155: }
156: end_perf_func();
157: }
158:
159: // ターゲット長が1500バイトの場合。
160: static void
161: do_perf_buf()
162: {
163: union {
164: uint8 buf[1500];
165: uint32 u32;
166: };
167:
168: memset(&buf, 0, sizeof(buf));
169: start_perf_func("1500bytes");
170: while (perf_signaled == 0) {
171: uint32 crc;
172: crc = EthernetDevice::CRC32(buf, sizeof(buf));
173: perf_count++;
174: u32 = crc;
175: }
176: end_perf_func();
177: }
178:
179: int
180: main(int ac, char *av[])
181: {
182: do_test(0);
183: do_test(1);
184: do_perf_buf();
185: do_perf_mac_old();
186: do_perf_mac_new();
187: return 0;
188: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.