102 lines
4.3 KiB
C++
102 lines
4.3 KiB
C++
// SPDX-FileCopyrightText: 2024 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
|
|
// SPDX-License-Identifier: CERN-OHL-S-2.0
|
|
|
|
|
|
#include "hls_jfjoch.h"
|
|
|
|
static const uint64_t arp_refresh = 5 * 200L*1000L*1000L; // Every 5 s @ 200 MHz
|
|
|
|
static const ap_uint<16> ARP_REQUEST = 0x0100;
|
|
static const ap_uint<16> ARP_REPLY = 0x0200;
|
|
static const ap_uint<16> ARP_HW_ETH = 0x0100;
|
|
static const ap_uint<16> ARP_PR_IP = 0x0008;
|
|
|
|
static const ap_uint<32> arp_sha_pos = eth_payload_pos + 8 * 8;
|
|
static const ap_uint<32> arp_spa_pos = arp_sha_pos + 6 * 8;
|
|
static const ap_uint<32> arp_tha_pos = arp_spa_pos + 4 * 8;
|
|
static const ap_uint<32> arp_tpa_pos = arp_tha_pos + 6 * 8;
|
|
|
|
inline void compose_arp_packet(packet_512_t &packet_out,
|
|
ap_uint<48> fpga_mac_addr,
|
|
ap_uint<32> fpga_ipv4_addr,
|
|
ap_uint<48> arp_src_mac_addr,
|
|
ap_uint<32> arp_src_ipv4_addr,
|
|
ap_uint<16> arp_operation) {
|
|
#pragma HLS INLINE
|
|
packet_out.data = 0;
|
|
packet_out.data(47, 0) = arp_src_mac_addr;
|
|
packet_out.data(48 + 47, 48) = fpga_mac_addr;
|
|
|
|
packet_out.data(96 + 16, 96) = 0x0608; // 0x0806
|
|
packet_out.data(eth_payload_pos + 15, eth_payload_pos) = ARP_HW_ETH; // ETH = 0x0001
|
|
packet_out.data(eth_payload_pos + 31, eth_payload_pos + 16) = ARP_PR_IP; // IPv4 = 0x0800
|
|
packet_out.data(eth_payload_pos + 39, eth_payload_pos + 32) = 0x6;
|
|
packet_out.data(eth_payload_pos + 47, eth_payload_pos + 40) = 0x4;
|
|
packet_out.data(eth_payload_pos + 63, eth_payload_pos + 48) = arp_operation; // 2 = reply
|
|
|
|
packet_out.data(arp_sha_pos + 47, arp_sha_pos) = fpga_mac_addr;
|
|
packet_out.data(arp_spa_pos + 31, arp_spa_pos) = fpga_ipv4_addr;
|
|
packet_out.data(arp_tha_pos + 47, arp_tha_pos) = arp_src_mac_addr;
|
|
packet_out.data(arp_tpa_pos + 31, arp_tpa_pos) = arp_src_ipv4_addr;
|
|
|
|
packet_out.dest = 0;
|
|
packet_out.last = 1;
|
|
packet_out.keep = UINT64_MAX; // 64 bytes
|
|
packet_out.user = 0;
|
|
|
|
}
|
|
|
|
void arp(AXI_STREAM &arp_in,
|
|
AXI_STREAM ð_out,
|
|
ap_uint<48> fpga_mac_addr,
|
|
ap_uint<32> fpga_ipv4_addr,
|
|
ap_uint<1> enable) {
|
|
#pragma HLS INTERFACE ap_ctrl_none port=return
|
|
#pragma HLS PIPELINE II=1 style=flp
|
|
#pragma HLS INTERFACE ap_none register port=fpga_mac_addr
|
|
#pragma HLS INTERFACE ap_none register port=fpga_ipv4_addr
|
|
#pragma HLS INTERFACE ap_none register port=enable
|
|
|
|
#pragma HLS INTERFACE axis register both port=arp_in
|
|
#pragma HLS INTERFACE axis register both port=eth_out
|
|
|
|
packet_512_t packet_in, packet_out;
|
|
static ap_uint<36> counter = 0; // 2^36 cycles @ 200 MHz = 343 seconds
|
|
|
|
if (enable && (counter == 0) && (fpga_mac_addr != 0) && (fpga_ipv4_addr != 0)) {
|
|
compose_arp_packet(packet_out, fpga_mac_addr, fpga_ipv4_addr,
|
|
MAC_BROADCAST, fpga_ipv4_addr,
|
|
ARP_REQUEST);
|
|
eth_out.write(packet_out);
|
|
} else if (!arp_in.empty()) {
|
|
arp_in.read(packet_in);
|
|
|
|
if ((fpga_mac_addr != 0) && (fpga_ipv4_addr != 0)) {
|
|
|
|
ap_uint<16> arp_hw_type = packet_in.data(eth_payload_pos + 15, eth_payload_pos);
|
|
ap_uint<16> arp_protocol_type = packet_in.data(eth_payload_pos + 31, eth_payload_pos + 16);
|
|
ap_uint<16> arp_operation = packet_in.data(eth_payload_pos + 63, eth_payload_pos + 48);
|
|
ap_uint<48> arp_src_hw_addr = packet_in.data(arp_sha_pos + 47, arp_sha_pos);
|
|
ap_uint<32> arp_src_ip_addr = packet_in.data(arp_spa_pos + 31, arp_spa_pos);
|
|
ap_uint<32> arp_dst_ip_addr = packet_in.data(arp_tpa_pos + 31, arp_tpa_pos);
|
|
|
|
if ((arp_hw_type == ARP_HW_ETH)
|
|
&& (arp_operation == ARP_REQUEST)
|
|
&& (arp_protocol_type == ARP_PR_IP)
|
|
&& (arp_src_ip_addr != fpga_ipv4_addr) // Don't reply on own gratuitous ARP
|
|
&& (arp_dst_ip_addr == fpga_ipv4_addr)) {
|
|
|
|
compose_arp_packet(packet_out, fpga_mac_addr, fpga_ipv4_addr,
|
|
arp_src_hw_addr, arp_src_ip_addr,
|
|
ARP_REPLY);
|
|
eth_out.write(packet_out);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (enable && (counter < arp_refresh) && (fpga_mac_addr != 0) && (fpga_ipv4_addr != 0))
|
|
counter++;
|
|
else
|
|
counter = 0;
|
|
}
|