Uthernet II: implement getMACAddress for libslirp.
Signed-off-by: Andrea Odetti <mariofutire@gmail.com>
This commit is contained in:
parent
b5ec2343fb
commit
a4bdf7ec53
4 changed files with 38 additions and 15 deletions
|
@ -77,15 +77,13 @@ namespace
|
||||||
return sum;
|
return sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t checksum(const void *addr, int count, int start_sum)
|
uint16_t checksum(const void *addr, int count)
|
||||||
{
|
{
|
||||||
/* Compute Internet Checksum for "count" bytes
|
/* Compute Internet Checksum for "count" bytes
|
||||||
* beginning at location "addr".
|
* beginning at location "addr".
|
||||||
* Taken from https://tools.ietf.org/html/rfc1071
|
* Taken from https://tools.ietf.org/html/rfc1071
|
||||||
*/
|
*/
|
||||||
uint32_t sum = start_sum;
|
uint32_t sum = sum_every_16bits(addr, count);
|
||||||
|
|
||||||
sum += sum_every_16bits(addr, count);
|
|
||||||
|
|
||||||
/* Fold 32-bit sum to 16 bits */
|
/* Fold 32-bit sum to 16 bits */
|
||||||
while (sum >> 16)
|
while (sum >> 16)
|
||||||
|
@ -97,7 +95,7 @@ namespace
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<uint8_t> createETH2Frame(const std::vector<uint8_t> &data,
|
std::vector<uint8_t> createETH2Frame(const std::vector<uint8_t> &data,
|
||||||
const MACAddress * sourceMac, const MACAddress *destinationMac,
|
const MACAddress *sourceMac, const MACAddress *destinationMac,
|
||||||
const uint8_t ttl, const uint8_t tos, const uint8_t protocol,
|
const uint8_t ttl, const uint8_t tos, const uint8_t protocol,
|
||||||
const uint32_t sourceAddress, const uint32_t destinationAddress)
|
const uint32_t sourceAddress, const uint32_t destinationAddress)
|
||||||
{
|
{
|
||||||
|
@ -119,7 +117,7 @@ std::vector<uint8_t> createETH2Frame(const std::vector<uint8_t> &data,
|
||||||
ip4header->proto = protocol;
|
ip4header->proto = protocol;
|
||||||
ip4header->sourceAddress = sourceAddress;
|
ip4header->sourceAddress = sourceAddress;
|
||||||
ip4header->destinationAddress = destinationAddress;
|
ip4header->destinationAddress = destinationAddress;
|
||||||
ip4header->checksum = checksum(ip4header, sizeof(IP4Header), 0);
|
ip4header->checksum = checksum(ip4header, sizeof(IP4Header));
|
||||||
|
|
||||||
memcpy(frame.data() + sizeof(ETH2Frame) + sizeof(IP4Header), data.data(), data.size());
|
memcpy(frame.data() + sizeof(ETH2Frame) + sizeof(IP4Header), data.data(), data.size());
|
||||||
|
|
||||||
|
|
|
@ -677,7 +677,7 @@ void Uthernet2::sendDataIPRaw(const size_t i, std::vector<uint8_t> &payload)
|
||||||
|
|
||||||
const MACAddress * sourceMac = reinterpret_cast<const MACAddress *>(myMemory.data() + W5100_SHAR0);
|
const MACAddress * sourceMac = reinterpret_cast<const MACAddress *>(myMemory.data() + W5100_SHAR0);
|
||||||
const MACAddress * destinationMac;
|
const MACAddress * destinationMac;
|
||||||
GetMACAddress(destination, destinationMac);
|
getMACAddress(destination, destinationMac);
|
||||||
|
|
||||||
std::vector<uint8_t> packet = createETH2Frame(payload, sourceMac, destinationMac, ttl, tos, protocol, source, destination);
|
std::vector<uint8_t> packet = createETH2Frame(payload, sourceMac, destinationMac, ttl, tos, protocol, source, destination);
|
||||||
|
|
||||||
|
@ -1293,7 +1293,7 @@ void Uthernet2::InitializeIO(LPBYTE pCxRomPeripheral)
|
||||||
RegisterIoHandler(m_slot, u2_C0, u2_C0, nullptr, nullptr, this, nullptr);
|
RegisterIoHandler(m_slot, u2_C0, u2_C0, nullptr, nullptr, this, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Uthernet2::GetMACAddress(const uint32_t address, const MACAddress * & mac)
|
void Uthernet2::getMACAddress(const uint32_t address, const MACAddress * & mac)
|
||||||
{
|
{
|
||||||
const auto it = myARPTable.find(address);
|
const auto it = myARPTable.find(address);
|
||||||
if (it != myARPTable.end())
|
if (it != myARPTable.end())
|
||||||
|
@ -1303,12 +1303,31 @@ void Uthernet2::GetMACAddress(const uint32_t address, const MACAddress * & mac)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
MACAddress & macAddr = myARPTable[address];
|
MACAddress & macAddr = myARPTable[address];
|
||||||
memset(macAddr.address, 0xFF, sizeof(macAddr.address));
|
const uint32_t source = readAddress(myMemory.data() + W5100_SIPR0);
|
||||||
|
|
||||||
// need to handle the case of the W5100 self address unknown to Windows
|
if (address == source)
|
||||||
if (address != INADDR_BROADCAST)
|
|
||||||
{
|
{
|
||||||
myNetworkBackend->getMACAddress(address, macAddr);
|
const uint8_t * sourceMac = myMemory.data() + W5100_SHAR0;
|
||||||
|
memcpy(macAddr.address, sourceMac, sizeof(macAddr.address));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memset(macAddr.address, 0xFF, sizeof(macAddr.address)); // fallback to broadcast
|
||||||
|
if (address != INADDR_BROADCAST)
|
||||||
|
{
|
||||||
|
const uint32_t subnet = readAddress(myMemory.data() + W5100_SUBR0);
|
||||||
|
if ((address & subnet) == (source & subnet))
|
||||||
|
{
|
||||||
|
// same network: send ARP request
|
||||||
|
myNetworkBackend->getMACAddress(address, macAddr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const uint32_t gateway = readAddress(myMemory.data() + W5100_GAR0);
|
||||||
|
// different network: go via gateway
|
||||||
|
myNetworkBackend->getMACAddress(gateway, macAddr);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
mac = &macAddr;
|
mac = &macAddr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,7 +81,7 @@ private:
|
||||||
|
|
||||||
std::map<uint32_t, MACAddress> myARPTable;
|
std::map<uint32_t, MACAddress> myARPTable;
|
||||||
|
|
||||||
void GetMACAddress(const uint32_t address, const MACAddress * & mac);
|
void getMACAddress(const uint32_t address, const MACAddress * & mac);
|
||||||
|
|
||||||
void setSocketModeRegister(const size_t i, const uint16_t address, const uint8_t value);
|
void setSocketModeRegister(const size_t i, const uint16_t address, const uint8_t value);
|
||||||
void setTXSizes(const uint16_t address, uint8_t value);
|
void setTXSizes(const uint16_t address, uint8_t value);
|
||||||
|
|
|
@ -202,9 +202,15 @@ bool SlirpBackend::isValid()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SlirpBackend::getMACAddress(const uint32_t /* address */, MACAddress & /* mac */)
|
void SlirpBackend::getMACAddress(const uint32_t address, MACAddress & mac)
|
||||||
{
|
{
|
||||||
// not needed for libslirp
|
// a bit of a hack, I've found out that slirp uses
|
||||||
|
/* emulated hosts use the MAC addr 52:55:IP:IP:IP:IP */
|
||||||
|
// https://gitlab.freedesktop.org/slirp/libslirp/-/blob/bf917b89d64f57d9302aba4b2f027ea68fb78c13/src/slirp.c#L78
|
||||||
|
mac.address[0] = 0x52;
|
||||||
|
mac.address[1] = 0x55;
|
||||||
|
uint32_t * ptr = reinterpret_cast<uint32_t *>(mac.address + 2);
|
||||||
|
*ptr = address;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Add table
Reference in a new issue