Move a lot of the network logic to net.cpp

This commit is contained in:
Sijmen 2020-12-11 01:09:29 +01:00
parent cff82bbad3
commit 18c5bbd29d
Signed by: vijfhoek
GPG key ID: DAF7821E067D9C48
6 changed files with 196 additions and 86 deletions

View file

@ -1943,7 +1943,6 @@ extern "C"
const auto ipAddress = 0x0A00000B; const auto ipAddress = 0x0A00000B;
uint8_t ipBuffer[USPI_FRAME_BUFFER_SIZE]; uint8_t ipBuffer[USPI_FRAME_BUFFER_SIZE];
std::unordered_map<std::uint32_t, std::array<std::uint8_t, 6>> arpTable;
if (USPiEthernetAvailable()) { if (USPiEthernetAvailable()) {
std::array<std::uint8_t, 6> macAddress; std::array<std::uint8_t, 6> macAddress;
@ -1952,24 +1951,8 @@ extern "C"
snprintf(tempBuffer, tempBufferSize, "Ethernet found"); snprintf(tempBuffer, tempBufferSize, "Ethernet found");
screen.PrintText(false, 0, y_pos+=16, tempBuffer, COLOUR_WHITE, COLOUR_BLACK); screen.PrintText(false, 0, y_pos+=16, tempBuffer, COLOUR_WHITE, COLOUR_BLACK);
// Send an ARP announcement // Send an ARP announcement
{ SendArpAnnouncement(macAddress, ipAddress);
Ipv4ArpPacket arp(ARP_OPERATION_REPLY);
arp.senderMac = macAddress;
arp.senderIp = ipAddress;
arp.targetMac.fill(0);
arp.targetIp = ipAddress;
EthernetFrame<decltype(arp)> frame(ETHERTYPE_ARP, arp);
frame.header.macDestination.fill(0xFF); // Broadcast
frame.header.macSource = macAddress;
size_t size = frame.Serialize(ipBuffer);
USPiSendFrame(ipBuffer, size);
}
while (true) while (true)
{ {
@ -1977,41 +1960,17 @@ extern "C"
if (!USPiReceiveFrame(ipBuffer, &size)) if (!USPiReceiveFrame(ipBuffer, &size))
{ {
const auto targetIp = 0x0A00000A; const auto targetIp = 0x0A00000A;
const auto targetMacIter = arpTable.find(targetIp); const auto targetMacIter = ArpTable.find(targetIp);
if (targetMacIter != arpTable.end()) if (targetMacIter != ArpTable.end())
{ {
const auto targetMac = targetMacIter->second; const auto targetMac = targetMacIter->second;
SendIcmpEchoRequest(targetMac, targetIp);
int value = 1337;
IcmpEchoRequest<int> ping(value);
IcmpPacket<decltype(ping)> icmp(8, 0, ping);
Ipv4Packet<decltype(icmp)> ip(1, ipAddress, targetIp, icmp);
EthernetFrame<decltype(ip)> frame(ETHERTYPE_IPV4, ip);
frame.header.macDestination = targetMac;
frame.header.macSource = macAddress;
size_t size = frame.Serialize(ipBuffer);
USPiSendFrame(ipBuffer, size);
} }
else else
{ {
// Send ARP request // Send an ARP request to find the MAC address belonging to this IP.
Ipv4ArpPacket arp(ARP_OPERATION_REQUEST); SendArpRequest(MacBroadcast, macAddress, targetIp, ipAddress);
arp.senderMac = macAddress;
arp.senderIp = ipAddress;
arp.targetMac.fill(0);
arp.targetIp = 0x0A00000A;
EthernetFrame<decltype(arp)> frame(ETHERTYPE_ARP, arp);
frame.header.macDestination.fill(0xFF); // Broadcast
frame.header.macSource = macAddress;
size_t size = frame.Serialize(ipBuffer);
USPiSendFrame(ipBuffer, size);
} }
MsDelay(1000); MsDelay(1000);
@ -2030,36 +1989,7 @@ extern "C"
if (header.type == ETHERTYPE_ARP) if (header.type == ETHERTYPE_ARP)
{ {
auto frame = EthernetFrame<Ipv4ArpPacket>::Deserialize(ipBuffer); HandleArpFrame(ipBuffer);
const auto arp = frame.payload;
if (arp.hardwareType == 1 &&
arp.protocolType == ETHERTYPE_IPV4 &&
arp.operation == ARP_OPERATION_REQUEST &&
arp.targetIp == ipAddress)
{
Ipv4ArpPacket arpReply(ARP_OPERATION_REPLY);
arpReply.targetMac = arp.senderMac;
arpReply.senderMac = macAddress;
arpReply.targetIp = arp.senderIp;
arpReply.senderIp = ipAddress;
EthernetFrame<decltype(arpReply)> frame(ETHERTYPE_ARP, arpReply);
frame.header.macSource = macAddress;
size_t size = frame.Serialize(ipBuffer);
USPiSendFrame(ipBuffer, size);
}
else if (arp.hardwareType == 1 &&
arp.protocolType == ETHERTYPE_IPV4 &&
arp.operation == ARP_OPERATION_REPLY &&
arp.targetIp == ipAddress &&
arp.targetMac == macAddress)
{
arpTable.insert(std::make_pair(arp.senderIp, arp.senderMac));
}
} }
} }
} }

View file

@ -69,7 +69,7 @@ struct EthernetFrame
buffer[i++] = 0; buffer[i++] = 0;
} }
crc = crc32(buffer, i); crc = Crc32(buffer, i);
buffer[i++] = crc; buffer[i++] = crc;
buffer[i++] = crc >> 8; buffer[i++] = crc >> 8;

View file

@ -42,7 +42,7 @@ struct IcmpPacket
i += header.Serialize(buffer); i += header.Serialize(buffer);
i += payload.Serialize(buffer + i); i += payload.Serialize(buffer + i);
uint16_t checksum = internetChecksum(buffer, i); uint16_t checksum = InternetChecksum(buffer, i);
buffer[2] = checksum; buffer[2] = checksum;
buffer[3] = checksum >> 8; buffer[3] = checksum >> 8;

View file

@ -64,7 +64,7 @@ struct Ipv4Header
buffer[i++] = destinationIp >> 8; buffer[i++] = destinationIp >> 8;
buffer[i++] = destinationIp; buffer[i++] = destinationIp;
headerChecksum = internetChecksum(buffer, i); headerChecksum = InternetChecksum(buffer, i);
buffer[10] = headerChecksum; buffer[10] = headerChecksum;
buffer[11] = headerChecksum >> 8; buffer[11] = headerChecksum >> 8;

View file

@ -1,5 +1,102 @@
#include "net.h" #include "net.h"
#include <unordered_map> #include "net-ethernet.h"
#include "net-ipv4.h"
#include "net-arp.h"
#include "net-icmp.h"
#include "types.h"
#include <uspi.h>
const uint32_t Ipv4Address = 0x0A00000B;
//
// ARP
//
void SendArpPacket(ArpOperation operation,
MacAddress targetMac,
MacAddress senderMac,
uint32_t targetIp,
uint32_t senderIp)
{
Ipv4ArpPacket arp(operation);
arp.targetMac = targetMac;
arp.senderMac = senderMac;
arp.targetIp = targetIp;
arp.senderIp = senderIp;
EthernetFrame<decltype(arp)> frame(ETHERTYPE_ARP, arp);
frame.header.macDestination = targetMac;
frame.header.macSource = senderMac;
uint8_t buffer[USPI_FRAME_BUFFER_SIZE];
const auto size = frame.Serialize(buffer);
USPiSendFrame(buffer, size);
}
void SendArpRequest(MacAddress targetMac,
MacAddress senderMac,
uint32_t targetIp,
uint32_t senderIp)
{
SendArpPacket(ARP_OPERATION_REQUEST, targetMac, senderMac, targetIp, senderIp);
}
void SendArpReply(MacAddress targetMac,
MacAddress senderMac,
uint32_t targetIp,
uint32_t senderIp)
{
SendArpPacket(ARP_OPERATION_REPLY, targetMac, senderMac, targetIp, senderIp);
}
void SendArpAnnouncement(MacAddress mac, uint32_t ip)
{
SendArpReply(MacBroadcast, mac, ip, ip);
}
void HandleArpFrame(uint8_t* buffer)
{
const auto macAddress = GetMacAddress();
const auto ipAddress = 0x0A00000B;
const auto frame = EthernetFrame<Ipv4ArpPacket>::Deserialize(buffer);
const auto arp = frame.payload;
if (arp.hardwareType == 1 &&
arp.protocolType == ETHERTYPE_IPV4 &&
arp.operation == ARP_OPERATION_REQUEST &&
arp.targetIp == ipAddress)
{
SendArpReply(arp.senderMac, macAddress, arp.senderIp, ipAddress);
}
else if (arp.hardwareType == 1 &&
arp.protocolType == ETHERTYPE_IPV4 &&
arp.operation == ARP_OPERATION_REPLY &&
arp.targetIp == ipAddress &&
arp.targetMac == macAddress)
{
ArpTable.insert(std::make_pair(arp.senderIp, arp.senderMac));
}
}
//
// ICMP
//
void SendIcmpEchoRequest(MacAddress mac, uint32_t ip)
{
IcmpEchoRequest<int> pingPacket(0);
IcmpPacket<decltype(pingPacket)> icmpPacket(8, 0, pingPacket);
Ipv4Packet<decltype(icmpPacket)> ipv4Packet(1, Ipv4Address, ip, icmpPacket);
EthernetFrame<decltype(ipv4Packet)> frame(ETHERTYPE_IPV4, ipv4Packet);
frame.header.macDestination = mac;
frame.header.macSource = GetMacAddress();
uint8_t buffer[USPI_FRAME_BUFFER_SIZE];
size_t size = frame.Serialize(buffer);
USPiSendFrame(buffer, size);
}
// //
// Helpers // Helpers
@ -71,7 +168,7 @@ static const std::uint32_t crcTab32[256] = {
0xB40BBE37ul, 0xC30C8EA1ul, 0x5A05DF1Bul, 0x2D02EF8Dul 0xB40BBE37ul, 0xC30C8EA1ul, 0x5A05DF1Bul, 0x2D02EF8Dul
}; };
std::uint32_t crc32(const std::uint8_t *buffer, std::size_t size) { std::uint32_t Crc32(const std::uint8_t *buffer, std::size_t size) {
std::uint32_t crc = 0xFFFFFFFFul; std::uint32_t crc = 0xFFFFFFFFul;
for (std::size_t a = 0; a < size; a++) for (std::size_t a = 0; a < size; a++)
@ -83,7 +180,7 @@ std::uint32_t crc32(const std::uint8_t *buffer, std::size_t size) {
return crc ^ 0xFFFFFFFFul; return crc ^ 0xFFFFFFFFul;
} }
std::uint16_t internetChecksum(const void* data, std::size_t size) std::uint16_t InternetChecksum(const void* data, std::size_t size)
{ {
std::uint32_t sum = 0; std::uint32_t sum = 0;
while (size > 1) { while (size > 1) {
@ -103,3 +200,18 @@ std::uint16_t internetChecksum(const void* data, std::size_t size)
return ~sum; return ~sum;
} }
MacAddress GetMacAddress()
{
static MacAddress macAddress{0};
if (macAddress == MacAddress{0})
{
USPiGetMACAddress(macAddress.data());
}
return macAddress;
}
MacAddress MacBroadcast{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
std::unordered_map<std::uint32_t, MacAddress> ArpTable;

View file

@ -3,6 +3,7 @@
#include <cstring> #include <cstring>
#include <algorithm> #include <algorithm>
#include <array> #include <array>
#include <unordered_map>
enum EtherType { enum EtherType {
ETHERTYPE_IPV4 = 0x0800, ETHERTYPE_IPV4 = 0x0800,
@ -16,8 +17,31 @@ enum ArpOperation {
typedef std::array<std::uint8_t, 6> MacAddress; typedef std::array<std::uint8_t, 6> MacAddress;
std::uint32_t crc32(const std::uint8_t* buffer, std::size_t size);
std::uint16_t internetChecksum(const void* data, std::size_t size); void HandleArpFrame(std::uint8_t* buffer);
void SendArpPacket(ArpOperation operation,
MacAddress targetMac,
MacAddress senderMac,
uint32_t senderIp,
uint32_t targetIp);
void SendArpRequest(MacAddress targetMac,
MacAddress senderMac,
uint32_t senderIp,
uint32_t targetIp);
void SendArpReply(MacAddress targetMac,
MacAddress senderMac,
uint32_t senderIp,
uint32_t targetIp);
void SendArpAnnouncement(MacAddress mac, uint32_t ip);
void SendIcmpEchoRequest(MacAddress mac, uint32_t ip);
std::uint32_t Crc32(const std::uint8_t* buffer, std::size_t size);
std::uint16_t InternetChecksum(const void* data, std::size_t size);
MacAddress GetMacAddress();
extern MacAddress MacBroadcast;
extern std::unordered_map<std::uint32_t, MacAddress> ArpTable;
struct UdpDatagramHeader struct UdpDatagramHeader
{ {
@ -25,4 +49,48 @@ struct UdpDatagramHeader
std::uint16_t destinationPort; std::uint16_t destinationPort;
std::uint16_t length; std::uint16_t length;
std::uint16_t checksum; std::uint16_t checksum;
UdpDatagramHeader() {}
UdpDatagramHeader(uint16_t sourcePort, uint16_t destinationPort, uint16_t length) :
sourcePort(sourcePort), destinationPort(destinationPort), length(length)
{}
size_t Serialize(uint8_t* buffer)
{
size_t i = 0;
buffer[i++] = sourcePort >> 8;
buffer[i++] = sourcePort;
buffer[i++] = destinationPort >> 8;
buffer[i++] = destinationPort;
buffer[i++] = length >> 8;
buffer[i++] = length;
buffer[i++] = checksum >> 8;
buffer[i++] = checksum;
return i;
}
UdpDatagramHeader Deserialize(const uint8_t* buffer)
{
UdpDatagramHeader self;
self.sourcePort = buffer[0] << 8 | buffer[1];
self.destinationPort = buffer[2] << 8 | buffer[3];
self.length = buffer[4] << 8 | buffer[5];
self.checksum = buffer[6] << 8 | buffer[7];
return self;
}
};
template <class T>
struct UdpDatagram
{
UdpDatagramHeader header;
T payload;
UdpDatagram() {}
UdpDatagram(uint16_t sourcePort, uint16_t destinationPort, T payload) :
header(sourcePort, destinationPort, sizeof(UdpDatagram<T>)),
payload(payload)
{}
}; };