94 lines
3.2 KiB
C++
94 lines
3.2 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"
|
|
|
|
void ethernet(AXI_STREAM ð_in,
|
|
AXI_STREAM &ip_out,
|
|
AXI_STREAM &arp_out,
|
|
AXI_STREAM &ptp_out,
|
|
ap_uint<48> fpga_mac_addr,
|
|
ap_uint<1> enable,
|
|
ap_uint<1> direct,
|
|
uint64_t& counter,
|
|
volatile ap_uint<1> &in_clear_counters) {
|
|
// direct - don't enforce MAC address
|
|
// enable - allows packets to go through
|
|
|
|
#pragma HLS INTERFACE ap_ctrl_none port=return
|
|
#pragma HLS INTERFACE axis register both port=eth_in
|
|
#pragma HLS INTERFACE axis register both port=ip_out
|
|
#pragma HLS INTERFACE axis register both port=arp_out
|
|
#pragma HLS INTERFACE axis register both port=ptp_out
|
|
|
|
#pragma HLS INTERFACE ap_none register port=fpga_mac_addr
|
|
#pragma HLS INTERFACE ap_none register port=direct
|
|
#pragma HLS INTERFACE ap_none register port=enable
|
|
#pragma HLS INTERFACE ap_vld register port=counter
|
|
#pragma HLS INTERFACE ap_none register port=in_clear_counters
|
|
|
|
#pragma HLS PIPELINE II=1 style=flp
|
|
enum eth_dest {DEST_IP = 0, DEST_ARP = 1, DEST_IGNORE = 2, DEST_PTP = 3};
|
|
enum eth_state {INSPECT_HEADER, FORWARD, DISCARD};
|
|
static eth_state state = INSPECT_HEADER;
|
|
static eth_dest dest;
|
|
static uint64_t internal_counter = 0;
|
|
|
|
ap_uint<1> tmp = in_clear_counters;
|
|
if (tmp)
|
|
internal_counter = 0;
|
|
|
|
#pragma HLS RESET variable=state
|
|
#pragma HLS RESET variable=internal_counter
|
|
|
|
packet_512_t packet_in;
|
|
if (eth_in.read_nb(packet_in)) {
|
|
|
|
if (state == INSPECT_HEADER) {
|
|
dest = DEST_IGNORE;
|
|
if (enable) {
|
|
ap_uint<48> dest_mac = packet_in.data(47, 0);
|
|
ap_uint<48> src_mac = packet_in.data(95, 48);
|
|
ap_uint<16> ether_type = get_header_field_16(packet_in.data, 12 * 8);
|
|
bool multicast = (dest_mac(47, 40) == 0x01 && dest_mac(39, 32) == 0x00 && dest_mac(31, 24) == 0x5e);
|
|
|
|
if (((dest_mac == fpga_mac_addr) || (dest_mac == MAC_BROADCAST) || multicast || direct)
|
|
&& (ether_type == ETHER_PTP)) {
|
|
state = FORWARD;
|
|
dest = DEST_PTP;
|
|
} else if (((dest_mac == fpga_mac_addr) || (dest_mac == MAC_BROADCAST) || multicast || direct)
|
|
&& (ether_type == ETHER_IP)) {
|
|
state = FORWARD;
|
|
dest = DEST_IP;
|
|
internal_counter++;
|
|
} else if ((dest_mac == MAC_BROADCAST)
|
|
&& (ether_type == ETHER_ARP)
|
|
&& (packet_in.last)) {
|
|
state = FORWARD;
|
|
dest = DEST_ARP;
|
|
}
|
|
}
|
|
}
|
|
|
|
switch (dest) {
|
|
case DEST_IP:
|
|
ip_out.write(packet_in);
|
|
break;
|
|
case DEST_ARP:
|
|
arp_out.write(packet_in);
|
|
break;
|
|
case DEST_PTP:
|
|
ptp_out.write(packet_in);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (packet_in.last) {
|
|
state = INSPECT_HEADER;
|
|
}
|
|
}
|
|
|
|
counter = internal_counter;
|
|
}
|