mirror of
https://github.com/akuker/RASCSI.git
synced 2026-10-25 12:02:59 +00:00
Restore the SCBR device as an X68000 Host Bridge, including the Human68k-compatible host file-system service and the bridge-specific SCSI message handlers. Back its Ethernet path with the TAP driver, derive a stable locally administered MAC address, preserve the driver minimum-frame/FCS expectations, and restrict received traffic to its own unicast frames and broadcasts. Match the RASCTL/RASETHER/RASDRV bridge protocol that originated in the parent RaSCSI project: dispatch its non-standard message format on READ(10)/WRITE(10) (0x28/0x2a), with type, function, phase, and a three-byte byte count carried in the CDB. Advertise the legacy control channel required by RASCTL, translate its list and device-management commands to PiSCSI operations, and defer stop or system-shutdown requests until after the response is sent, while gating this insecure interface behind a new '-c disabled|media|full' runtime option. Preserve the type-1 Ethernet exchange used by RASETHER and the type-2, phased filesystem exchange used by RASDRV. Register the device in the factory, protobuf API, controller transfer path, command-line tooling, device listings, and web UI. Share the explicit bridge and proxy-ARP topology workflow with DaynaPort so both adapters validate and use the same mode/interface pair. Add build support for iconv where needed, extend unit coverage for device creation, RAS* protocol handling, CLI parsing, web attachment, and topology selection, and update the man pages and network-profile documentation for Host Bridge operation and its networking limits.
89 lines
3.0 KiB
C++
89 lines
3.0 KiB
C++
//---------------------------------------------------------------------------
|
|
//
|
|
// SCSI Target Emulator PiSCSI
|
|
// for Raspberry Pi
|
|
//
|
|
// Copyright (C) 2022-2023 Uwe Seimet
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
#include "mocks.h"
|
|
#include <net/ethernet.h>
|
|
#include "devices/ctapdriver.h"
|
|
|
|
using namespace network_util;
|
|
|
|
TEST(CTapDriverTest, GetDefaultParams)
|
|
{
|
|
CTapDriver driver;
|
|
const auto params = driver.GetDefaultParams();
|
|
EXPECT_EQ(2, params.size());
|
|
EXPECT_EQ("piscsi_bridge", params.at("interface"));
|
|
EXPECT_EQ("bridge", params.at("mode"));
|
|
EXPECT_FALSE(params.contains("inet"));
|
|
}
|
|
|
|
TEST(CTapDriverTest, ValidateProfiles)
|
|
{
|
|
const network_interface_map interfaces = {
|
|
{ "piscsi_bridge", { "piscsi_bridge", NetworkInterfaceType::BRIDGE, true } },
|
|
{ "wlan0", { "wlan0", NetworkInterfaceType::WIFI, true } },
|
|
{ "eth0", { "eth0", NetworkInterfaceType::ETHERNET, true } },
|
|
{ "wlan1", { "wlan1", NetworkInterfaceType::WIFI, false } },
|
|
};
|
|
|
|
EXPECT_TRUE(CTapDriver::GetProfileValidationError("bridge", "piscsi_bridge", interfaces).empty());
|
|
EXPECT_TRUE(CTapDriver::GetProfileValidationError("proxyarp", "wlan0", interfaces).empty());
|
|
EXPECT_THAT(CTapDriver::GetProfileValidationError("", "piscsi_bridge", interfaces), HasSubstr("Unsupported"));
|
|
EXPECT_THAT(CTapDriver::GetProfileValidationError("bridge", "eth0", interfaces), HasSubstr("requires"));
|
|
EXPECT_THAT(CTapDriver::GetProfileValidationError("proxyarp", "eth0", interfaces), HasSubstr("Wi-Fi"));
|
|
EXPECT_THAT(CTapDriver::GetProfileValidationError("proxyarp", "wlan1", interfaces), HasSubstr("down"));
|
|
EXPECT_THAT(CTapDriver::GetProfileValidationError("proxyarp", "wlan0,eth0", interfaces), HasSubstr("Invalid"));
|
|
|
|
auto conflicting_interfaces = interfaces;
|
|
conflicting_interfaces.emplace("piscsi0", NetworkInterfaceInfo { "piscsi0", NetworkInterfaceType::TAP, true });
|
|
EXPECT_THAT(CTapDriver::GetProfileValidationError("proxyarp", "wlan0", conflicting_interfaces), HasSubstr("in use"));
|
|
}
|
|
|
|
TEST(CTapDriverTest, CleanupAndMacAreSafeWithoutATap)
|
|
{
|
|
CTapDriver driver;
|
|
array<uint8_t, 6> mac;
|
|
mac.fill(0xff);
|
|
driver.GetUplinkMacAddr(mac.data());
|
|
EXPECT_THAT(mac, Each(0));
|
|
|
|
driver.CleanUp();
|
|
driver.CleanUp();
|
|
}
|
|
|
|
TEST(CTapDriverTest, Crc32)
|
|
{
|
|
array<uint8_t, ETH_FRAME_LEN> buf;
|
|
|
|
buf.fill(0x00);
|
|
EXPECT_EQ(0xe3d887bb, CTapDriver::Crc32(span(buf.data(), ETH_FRAME_LEN)));
|
|
|
|
buf.fill(0xff);
|
|
EXPECT_EQ(0x814765f4, CTapDriver::Crc32(span(buf.data(), ETH_FRAME_LEN)));
|
|
|
|
buf.fill(0x10);
|
|
EXPECT_EQ(0xb7288Cd3, CTapDriver::Crc32(span(buf.data(), ETH_FRAME_LEN)));
|
|
|
|
buf.fill(0x7f);
|
|
EXPECT_EQ(0x4b543477, CTapDriver::Crc32(span(buf.data(), ETH_FRAME_LEN)));
|
|
|
|
buf.fill(0x80);
|
|
EXPECT_EQ(0x29cbd638, CTapDriver::Crc32(span(buf.data(), ETH_FRAME_LEN)));
|
|
|
|
for (size_t i = 0; i < buf.size(); i++) {
|
|
buf[i] = (uint8_t)i;
|
|
}
|
|
EXPECT_EQ(0xe7870705, CTapDriver::Crc32(span(buf.data(), ETH_FRAME_LEN)));
|
|
|
|
for (size_t i = buf.size() - 1; i > 0; i--) {
|
|
buf[i] = (uint8_t)i;
|
|
}
|
|
EXPECT_EQ(0xe7870705, CTapDriver::Crc32(span(buf.data(), ETH_FRAME_LEN)));
|
|
}
|