|
|
nono 1.7.0
//
// nono
// Copyright (C) 2020 nono project
// Licensed under nono-license.txt
//
// EthernetDevice::CRC32() のテスト。
#include "header.h"
#include "bitops.h"
#include "macaddr.h"
#include "stopwatch.h"
#include <signal.h>
#include <sys/time.h>
// パフォーマンステストの秒数
#define PERF_SEC (2)
class EthernetDevice
{
public:
static uint32 CRC32(const uint8 *buf, size_t buflen);
static uint32 CRC32(const MacAddr& mac);
};
#define SELFTEST
#include "ethernet.cpp"
// testnum は 0 が通常の CRC、1 が MAC アドレス用 CRC。
static void
do_test(int testnum)
{
struct {
uint8 src[6];
uint32 expected;
} table[] = {
{ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, 0x3a7abc72 },
{ { 0x33, 0x33, 0x00, 0x00, 0x00, 0x01 }, 0xf99baaba },
};
int failed = 0;
if (testnum == 0) {
printf("Test(buf)");
} else {
printf("Test(mac)");
}
for (size_t i = 0; i < countof(table); i++) {
const uint8 *src = table[i].src;
uint32 expected = table[i].expected;
uint32 actual;
if (testnum == 0) {
actual = EthernetDevice::CRC32(src, 6);
} else {
MacAddr mac(src);
actual = EthernetDevice::CRC32(mac);
}
if (actual != expected) {
if (failed == 0) {
printf("\n");
}
printf("FAILED: %02x%02x%02x%02x%02x%02x expects %08x but got %08x",
src[0], src[1], src[2], src[3], src[4], src[5],
expected, actual);
// 念のため反転して一致するか。
uint32 revact = bitrev32(actual);
if (revact == expected) {
printf(" (bit-reversed)");
}
printf(" !\n");
failed++;
}
}
if (failed == 0) {
printf("..OK\n");
}
}
static volatile uint32 perf_signaled;
static uint64 perf_count;
static Stopwatch sw;
static void
signal_alarm(int signo)
{
perf_signaled = 1;
}
static void
start_perf_func(const char *name)
{
printf("%s\t... ", name);
fflush(stdout);
perf_count = 0;
perf_signaled = 0;
signal(SIGALRM, signal_alarm);
struct itimerval it = {};
it.it_value.tv_sec = PERF_SEC;
sw.Restart();
setitimer(ITIMER_REAL, &it, NULL);
}
static void
end_perf_func()
{
sw.Stop();
uint64 usec = nsec_to_usec(sw.Elapsed_nsec());
printf("%6.2f times/usec\n", (double)perf_count / usec);
}
// ターゲット長がMACアドレスで従来の CRC32(buf)。
static void
do_perf_mac_old()
{
union {
uint8 buf[6];
uint32 u32;
};
memset(buf, 0, sizeof(buf));
start_perf_func("macaddr.old");
while (perf_signaled == 0) {
volatile uint32 crc;
crc = EthernetDevice::CRC32(buf, sizeof(buf));
perf_count++;
u32 = crc;
}
end_perf_func();
}
// ターゲット長がMACアドレスで CRC32(mac)。
static void
do_perf_mac_new()
{
union {
uint8 buf[6];
uint32 u32;
};
memset(buf, 0, sizeof(buf));
MacAddr mac(buf);
start_perf_func("macaddr.new");
while (perf_signaled == 0) {
volatile uint32 crc;
crc = EthernetDevice::CRC32(mac);
perf_count++;
u32 = crc;
}
end_perf_func();
}
// ターゲット長が1500バイトの場合。
static void
do_perf_buf()
{
union {
uint8 buf[1500];
uint32 u32;
};
memset(buf, 0, sizeof(buf));
start_perf_func("1500bytes");
while (perf_signaled == 0) {
uint32 crc;
crc = EthernetDevice::CRC32(buf, sizeof(buf));
perf_count++;
u32 = crc;
}
end_perf_func();
}
int
main(int ac, char *av[])
{
do_test(0);
do_test(1);
do_perf_buf();
do_perf_mac_old();
do_perf_mac_new();
return 0;
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.