Split net stack into eth/arp/ipv4/icmp, deferred handler responses, ping tests
This commit is contained in:
41
firmware/lib/arp.cpp
Normal file
41
firmware/lib/arp.cpp
Normal file
@@ -0,0 +1,41 @@
|
||||
#include "arp.h"
|
||||
|
||||
namespace arp {
|
||||
|
||||
static constexpr uint16_t ARP_HTYPE_ETH = __builtin_bswap16(1);
|
||||
static constexpr uint16_t ARP_PTYPE_IPV4 = __builtin_bswap16(0x0800);
|
||||
static constexpr uint16_t ARP_OP_REQUEST = __builtin_bswap16(1);
|
||||
static constexpr uint16_t ARP_OP_REPLY = __builtin_bswap16(2);
|
||||
|
||||
void handle(std::span<const uint8_t> frame, span_writer& tx,
|
||||
eth::mac_addr our_mac, ipv4::ip4_addr our_ip,
|
||||
std::function<void(std::span<const uint8_t>)> send_raw) {
|
||||
if (frame.size() < sizeof(packet)) return;
|
||||
auto& pkt = *reinterpret_cast<const packet*>(frame.data());
|
||||
|
||||
if (pkt.htype != ARP_HTYPE_ETH) return;
|
||||
if (pkt.ptype != ARP_PTYPE_IPV4) return;
|
||||
if (pkt.hlen != 6 || pkt.plen != 4) return;
|
||||
if (pkt.oper != ARP_OP_REQUEST) return;
|
||||
if (pkt.tpa != our_ip) return;
|
||||
if (sizeof(packet) > tx.capacity()) return;
|
||||
|
||||
auto& reply = *reinterpret_cast<packet*>(tx.data());
|
||||
reply = {};
|
||||
reply.eth.dst = pkt.eth.src;
|
||||
reply.eth.src = our_mac;
|
||||
reply.eth.ethertype = eth::ETH_ARP;
|
||||
reply.htype = ARP_HTYPE_ETH;
|
||||
reply.ptype = ARP_PTYPE_IPV4;
|
||||
reply.hlen = 6;
|
||||
reply.plen = 4;
|
||||
reply.oper = ARP_OP_REPLY;
|
||||
reply.sha = our_mac;
|
||||
reply.spa = our_ip;
|
||||
reply.tha = pkt.sha;
|
||||
reply.tpa = pkt.spa;
|
||||
|
||||
send_raw({tx.data(), sizeof(packet)});
|
||||
}
|
||||
|
||||
} // namespace arp
|
||||
Reference in New Issue
Block a user