|
|
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:
1.1.1.3 ! root 113: uint64 usec = nsec_to_usec(sw.Elapsed_nsec());
1.1 root 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:
1.1.1.2 root 126: memset(buf, 0, sizeof(buf));
1.1 root 127: start_perf_func("macaddr.old");
128: while (perf_signaled == 0) {
129: volatile uint32 crc;
130: crc = EthernetDevice::CRC32(buf, sizeof(buf));
131: perf_count++;
132: u32 = crc;
133: }
134: end_perf_func();
135: }
136:
137: // ターゲット長がMACアドレスで CRC32(mac)。
138: static void
139: do_perf_mac_new()
140: {
141: union {
142: uint8 buf[6];
143: uint32 u32;
144: };
145:
1.1.1.2 root 146: memset(buf, 0, sizeof(buf));
1.1 root 147: MacAddr mac(buf);
148: start_perf_func("macaddr.new");
149: while (perf_signaled == 0) {
150: volatile uint32 crc;
151: crc = EthernetDevice::CRC32(mac);
152: perf_count++;
153: u32 = crc;
154: }
155: end_perf_func();
156: }
157:
158: // ターゲット長が1500バイトの場合。
159: static void
160: do_perf_buf()
161: {
162: union {
163: uint8 buf[1500];
164: uint32 u32;
165: };
166:
1.1.1.2 root 167: memset(buf, 0, sizeof(buf));
1.1 root 168: start_perf_func("1500bytes");
169: while (perf_signaled == 0) {
170: uint32 crc;
171: crc = EthernetDevice::CRC32(buf, sizeof(buf));
172: perf_count++;
173: u32 = crc;
174: }
175: end_perf_func();
176: }
177:
178: int
179: main(int ac, char *av[])
180: {
181: do_test(0);
182: do_test(1);
183: do_perf_buf();
184: do_perf_mac_old();
185: do_perf_mac_new();
186: return 0;
187: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.