cloudFPGA (cF) API  1.0
The documentation of the source code of cloudFPGA (cF)
ICMP

Internet Control Message Protocol server (ICMP) of the Network Transport Stack (NTS). More...

Collaboration diagram for ICMP:

Modules

 ICMP_TEST
 Testbench for the Internet Control Message Protocol server (ICMP) of the Network Transport Stack (NTS).
 

Files

file  test_icmp.cpp
 : Testbench for the Internet Control Message Protocol (ICMP) server.
 
file  test_icmp.cpp
 : Testbench for the Internet Control Message Protocol (ICMP) server.
 

Macros

#define THIS_NAME   "ICMP"
 
#define TRACE_OFF   0x0000
 
#define TRACE_CMB   1 << 1
 
#define TRACE_ICC   1 << 2
 
#define TRACE_ICI   1 << 3
 
#define TRACE_IHA   1 << 4
 
#define TRACE_IPD   1 << 5
 
#define TRACE_ALL   0xFFFF
 
#define DEBUG_LEVEL   (TRACE_OFF)
 

Typedefs

typedef ap_uint< 17 > Sum17
 
typedef ap_uint< 17 > LE_Sum17
 

Functions

void pIcmpChecksumChecker (stream< AxisIp4 > &siIPRX_Data, stream< AxisIp4 > &soIPd_Data, stream< ValBool > &soIPd_DropCmd, stream< IcmpCsum > &soICi_Csum)
 
void pControlMessageBuilder (stream< AxisIcmp > &siUOE_Data, stream< AxisIp4 > &siIPRX_Derr, stream< AxisIcmp > &soIHa_Data, stream< AxisIp4 > &soIHa_IpHdr, stream< IcmpCsum > &soICi_Csum)
 
void pIpHeaderAppender (Ip4Addr piMMIO_Ip4Address, stream< AxisIcmp > &siCMb_Data, stream< AxisIp4 > &siIHa_IpHdr, stream< AxisIp4 > &soICi_Data)
 
void pInvalidPacketDropper (stream< AxisIp4 > &siICc_Data, stream< ValBool > &siICc_DropCmd, stream< AxisIp4 > &soICi_Data)
 
void pIcmpChecksumInserter (stream< AxisIp4 > siXYz_Data[2], stream< IcmpCsum > siUVw_Csum[2], stream< AxisIp4 > &soIPTX_Data)
 
void icmp (Ip4Addr piMMIO_Ip4Address, stream< AxisIp4 > &siIPRX_Data, stream< AxisIp4 > &siIPRX_Derr, stream< AxisIcmp > &siUOE_Data, stream< AxisIp4 > &soIPTX_Data)
 Main process of the Internet Control Message Protocol (ICMP) Server. More...
 
void icmp_top (Ip4Addr piMMIO_Ip4Address, stream< AxisRaw > &siIPRX_Data, stream< AxisRaw > &siIPRX_Derr, stream< AxisRaw > &siUOE_Data, stream< AxisRaw > &soIPTX_Data)
 Top of the Internet Control Message Protocol (ICMP) Server. More...
 

Variables

bool gTraceEvent
 
const IcmpType ICMP_ECHO_REPLY = 0x00
 
const IcmpType ICMP_DESTINATION_UNREACHABLE = 0x03
 
const IcmpType ICMP_ECHO_REQUEST = 0x08
 
const IcmpType ICMP_TIME_EXCEEDED = 0x0B
 
const IcmpCode ICMP_TTL_EXPIRED_IN_TRANSIT = 0x00
 
const IcmpCode ICMP_DESTINATION_PORT_UNREACHABLE = 0x03
 
const Ip4Prot ICMP_PROTOCOL = 0x01
 

Detailed Description

Internet Control Message Protocol server (ICMP) of the Network Transport Stack (NTS).

Macro Definition Documentation

◆ DEBUG_LEVEL

#define DEBUG_LEVEL   (TRACE_OFF)

Definition at line 77 of file icmp.cpp.

◆ THIS_NAME

#define THIS_NAME   "ICMP"

Definition at line 67 of file icmp.cpp.

◆ TRACE_ALL

#define TRACE_ALL   0xFFFF

Definition at line 75 of file icmp.cpp.

◆ TRACE_CMB

#define TRACE_CMB   1 << 1

Definition at line 70 of file icmp.cpp.

◆ TRACE_ICC

#define TRACE_ICC   1 << 2

Definition at line 71 of file icmp.cpp.

◆ TRACE_ICI

#define TRACE_ICI   1 << 3

Definition at line 72 of file icmp.cpp.

◆ TRACE_IHA

#define TRACE_IHA   1 << 4

Definition at line 73 of file icmp.cpp.

◆ TRACE_IPD

#define TRACE_IPD   1 << 5

Definition at line 74 of file icmp.cpp.

◆ TRACE_OFF

#define TRACE_OFF   0x0000

Definition at line 69 of file icmp.cpp.

Typedef Documentation

◆ LE_Sum17

typedef ap_uint<17> LE_Sum17

Definition at line 76 of file icmp.hpp.

◆ Sum17

typedef ap_uint<17> Sum17

Definition at line 75 of file icmp.hpp.

Function Documentation

◆ icmp()

void icmp ( Ip4Addr  piMMIO_Ip4Address,
stream< AxisIp4 > &  siIPRX_Data,
stream< AxisIp4 > &  siIPRX_Derr,
stream< AxisIcmp > &  siUOE_Data,
stream< AxisIp4 > &  soIPTX_Data 
)

Main process of the Internet Control Message Protocol (ICMP) Server.

Parameters
[in]piMMIO_MacAddressThe MAC address from MMIO (in network order).
[in]siIPRX_DataThe data stream from the IP Rx handler (IPRX).
[in]siIPRX_DerrErroneous IP data stream from [IPRX].
[in]siUOE_DataA copy of the first IPv4 bytes that caused the error.
[out]soIPTX_DataThe data stream to the IpTxHandler (IPTX).

This process is in charge of building and sending control and error messages back to the IP address that initiated the control request or that caused an error in the first place. The process performs the 3 following main tasks: 1) It implements the ICMP Echo Reply message used by the ping command. 2) It creates an error message of type "Time Exceeded" upon reception of an IPv4 packet which TTL has expired. 3) It creates an error message of type 'Destination Port Unreachable' if an UDP datagram is received for a port that is not opened in listening mode.

Definition at line 686 of file icmp.cpp.

708 {
709  //-- DIRECTIVES FOR THIS PROCESS -------------------------------------------
710  #pragma HLS DATAFLOW
711  #pragma HLS INLINE
712  #pragma HLS INTERFACE ap_ctrl_none port=return
713 
714  //--------------------------------------------------------------------------
715  //-- LOCAL STREAMS (Sorted by the name of the modules which generate them)
716  //--------------------------------------------------------------------------
717 
718  //-- IP Checksum Checker (ICc)
719  static stream<AxisIp4> ssICcToIPd_Data ("ssICcToIPd_Data");
720  #pragma HLS stream variable=ssICcToIPd_Data depth=64
721  #pragma HLS DATA_PACK variable=ssICcToIPd_Data
722 
723  static stream<ValBool> ssICcToIPd_DropCmd ("ssICcToIPd_DropCmd");
724  #pragma HLS stream variable=ssICcToIPd_DropCmd depth=8
725 
726  //-- Control Message Builder (CMb)
727  static stream<AxisIcmp> ssCMbToIHa_Data ("ssCMbToIHa_Data");
728  #pragma HLS stream variable=ssCMbToIHa_Data depth=192
729  static stream<AxisIp4> ssCMbToIHa_IpHdr ("ssCMbToIHa_IpHdr");
730  #pragma HLS stream variable=ssCMbToIHa_IpHdr depth=64
731 
732  //-- XYz = [InvalidPacketDropper (IPd)| IpHeaderAppender (IHa)]
733  static stream<AxisIp4> ssXYzToICi_Data[2];
734  #pragma HLS STREAM variable=ssXYzToICi_Data depth=16
735 
736  //-- UVw = [ICc|CMb]
737  static stream<IcmpCsum> ssUVwToICi_Csum[2];
738  #pragma HLS STREAM variable=ssUVwToICi_Csum depth=16
739 
740  //-- PROCESS FUNCTIONS ----------------------------------------------------
742  siIPRX_Data,
743  ssICcToIPd_Data,
744  ssICcToIPd_DropCmd,
745  ssUVwToICi_Csum[0]);
746 
748  ssICcToIPd_Data,
749  ssICcToIPd_DropCmd,
750  ssXYzToICi_Data[0]);
751 
753  siUOE_Data,
754  siIPRX_Derr,
755  ssCMbToIHa_Data,
756  ssCMbToIHa_IpHdr,
757  ssUVwToICi_Csum[1]);
758 
760  piMMIO_Ip4Address,
761  ssCMbToIHa_Data,
762  ssCMbToIHa_IpHdr,
763  ssXYzToICi_Data[1]);
764 
766  ssXYzToICi_Data,
767  ssUVwToICi_Csum,
768  soIPTX_Data);
769 
770 }
void pInvalidPacketDropper(stream< AxisIp4 > &siICc_Data, stream< ValBool > &siICc_DropCmd, stream< AxisIp4 > &soICi_Data)
Definition: icmp.cpp:542
void pControlMessageBuilder(stream< AxisIcmp > &siUOE_Data, stream< AxisIp4 > &siIPRX_Derr, stream< AxisIcmp > &soIHa_Data, stream< AxisIp4 > &soIHa_IpHdr, stream< IcmpCsum > &soICi_Csum)
Definition: icmp.cpp:316
void pIpHeaderAppender(Ip4Addr piMMIO_Ip4Address, stream< AxisIcmp > &siCMb_Data, stream< AxisIp4 > &siIHa_IpHdr, stream< AxisIp4 > &soICi_Data)
Definition: icmp.cpp:436
void pIcmpChecksumInserter(stream< AxisIp4 > siXYz_Data[2], stream< IcmpCsum > siUVw_Csum[2], stream< AxisIp4 > &soIPTX_Data)
Definition: icmp.cpp:602
void pIcmpChecksumChecker(stream< AxisIp4 > &siIPRX_Data, stream< AxisIp4 > &soIPd_Data, stream< ValBool > &soIPd_DropCmd, stream< IcmpCsum > &soICi_Csum)
Definition: icmp.cpp:117
Here is the call graph for this function:
Here is the caller graph for this function:

◆ icmp_top()

void icmp_top ( Ip4Addr  piMMIO_Ip4Address,
stream< AxisRaw > &  siIPRX_Data,
stream< AxisRaw > &  siIPRX_Derr,
stream< AxisRaw > &  siUOE_Data,
stream< AxisRaw > &  soIPTX_Data 
)

Top of the Internet Control Message Protocol (ICMP) Server.

Parameters
[in]piMMIO_MacAddressThe MAC address from MMIO (in network order).
[in]siIPRX_DataThe data stream from the IP Rx handler (IPRX).
[in]siIPRX_DerrErroneous IP data stream from [IPRX].
[in]siUOE_DataA copy of the first IPv4 bytes that caused the error.
[out]soIPTX_DataThe data stream to the IpTxHandler (IPTX).

ENTITY - INTERNET CONTROL MESSAGE PROTOCOL (ICMP) SERVER

Definition at line 832 of file icmp.cpp.

850 {
851  //-- DIRECTIVES FOR THE INTERFACES ----------------------------------------
852  #pragma HLS INTERFACE ap_ctrl_none port=return
853 
854  #pragma HLS INTERFACE ap_stable port=piMMIO_Ip4Address
855 
856  #pragma HLS INTERFACE axis off port=siIPRX_Data
857  #pragma HLS INTERFACE axis off port=siIPRX_Derr
858  #pragma HLS INTERFACE axis off port=siUOE_Data
859  #pragma HLS INTERFACE axis register both port=soIPTX_Data
860 
861  //-- DIRECTIVES FOR THIS PROCESS -------------------------------------------
862  #pragma HLS DATAFLOW disable_start_propagation
863 
864  //-- LOCAL INPUT and OUTPUT STREAMS ----------------------------------------
865  static stream<AxisIp4> ssiIPRX_Data ("ssiIPRX_Data");
866  #pragma HLS STREAM variable=ssiIPRX_Data depth=32
867  static stream<AxisIp4> ssiIPRX_Derr ("ssiIPRX_Derr");
868  static stream<AxisIcmp> ssiUOE_Data ("ssiUOE_Data");
869  static stream<AxisIp4> ssoIPTX_Data ("ssoIPTX_Data");
870 
871  //-- INPUT STREAM CASTING --------------------------------------------------
872  pAxisRawCast(siIPRX_Data, ssiIPRX_Data);
873  pAxisRawCast(siIPRX_Derr, ssiIPRX_Derr);
874  pAxisRawCast(siUOE_Data, ssiUOE_Data);
875 
876  //-- MAIN ICMP PROCESS -----------------------------------------------------
877  icmp(
878  //-- MMIO Interfaces
879  piMMIO_Ip4Address,
880  //-- IPRX Interfaces
881  ssiIPRX_Data,
882  ssiIPRX_Derr,
883  //-- UOE Interface
884  ssiUOE_Data,
885  //-- IPTX Interface
886  ssoIPTX_Data);
887 
888  //-- OUTPUT STREAM CASTING -------------------------------------------------
889  pAxisRawCast(ssoIPTX_Data, soIPTX_Data);
890 
891 }
void icmp(Ip4Addr piMMIO_Ip4Address, stream< AxisIp4 > &siIPRX_Data, stream< AxisIp4 > &siIPRX_Derr, stream< AxisIcmp > &siUOE_Data, stream< AxisIp4 > &soIPTX_Data)
Main process of the Internet Control Message Protocol (ICMP) Server.
Definition: icmp.cpp:686
void pAxisRawCast(hls::stream< TypeIn > &si, hls::stream< TypeOut > &so)
AxisRaw cast - Casts an AxisRaw stream to/from an AxisRaw derived class.
Definition: AxisRaw.hpp:148
Here is the call graph for this function:
Here is the caller graph for this function:

◆ pControlMessageBuilder()

void pControlMessageBuilder ( stream< AxisIcmp > &  siUOE_Data,
stream< AxisIp4 > &  siIPRX_Derr,
stream< AxisIcmp > &  soIHa_Data,
stream< AxisIp4 > &  soIHa_IpHdr,
stream< IcmpCsum > &  soICi_Csum 
)

Control Message Builder (CMb)

Parameters
[in]siUOE_DataThe data stream from the UDP offload engine (UDP).
[in]siIPRX_DerrErroneous IP data stream from IpRxHandler (IPRX).
[out]soIHa_DataData stream to IpHeaderAppender (IHa).
[out]soIHa_HdrHeader data stream to IpHeaderAppender (IHa).
[out]soICi_CsumICMP checksum to ICi.

This process is dedicated to the building of 2 types of error messages: 1) It creates an error message of type "Time Exceeded" upon reception of an IPv4 packet which TTL has expired. 2) It creates an error message of type 'Destination Port Unreachable' if an UDP datagram is received for a port that is not opened in listening mode.

Definition at line 316 of file icmp.cpp.

322 {
323  //-- DIRECTIVES FOR THIS PROCESS -------------------------------------------
324  #pragma HLS INLINE off
325  #pragma HLS pipeline II=1
326 
327  const char *myName = concat3(THIS_NAME, "/", "CMb");
328 
329  //-- STATIC CONTROL VARIABLES (with RESET) ---------------------------------
330  static enum FsmStates { BCM_IDLE, BCM_IP, \
331  BCM_STREAM, BCM_CS } bcm_fsmState=BCM_IDLE;
332  #pragma HLS reset variable=bcm_fsmState
333 
334  //-- STATIC DATAFLOW VARIABLES ---------------------------------------------
335  static ap_uint<3> ipChunkCounter; // Up to 64-bytes IP packet
336  static ap_uint<20> checksumAcc;
337 
338  static ap_uint<1> streamSource = 0; // 0 is UDP, 1 is IP Handler (Destination unreachable & TTL exceeded respectively)
339 
340  //-- DYNAMIC VARIABLES -----------------------------------------------------
341  StsBit udpInEmpty;
342  StsBit iprxInEmpty;
343 
344  udpInEmpty = siUOE_Data.empty();
345  iprxInEmpty = siIPRX_Derr.empty();
346 
347  switch(bcm_fsmState) {
348  case BCM_IDLE:
349  //-- Assemble an ICMP header = [Type | Code | Checksum]
350  if ((udpInEmpty == 0 || iprxInEmpty == 0) && !soIHa_Data.full()) {
351  // Data are available in at lease one of the input queue(s).
352  // Don't read them yet but start assembling a ICMP header
353  ipChunkCounter = 0;
354  AxisIcmp axisIcmp(0, 0xFF, 0);
355  if (udpInEmpty == 0) {
356  axisIcmp.setIcmpType(ICMP_DESTINATION_UNREACHABLE);
357  axisIcmp.setIcmpCode(ICMP_DESTINATION_PORT_UNREACHABLE);
358  streamSource = 0;
359  }
360  else if (iprxInEmpty == 0) {
361  axisIcmp.setIcmpType(ICMP_TIME_EXCEEDED);
362  axisIcmp.setIcmpCode(ICMP_TTL_EXPIRED_IN_TRANSIT);
363  streamSource = 1;
364  }
365  checksumAcc = (((axisIcmp.getLE_TData(63, 48) + axisIcmp.getLE_TData(47, 32)) +
366  axisIcmp.getLE_TData(31, 16)) + axisIcmp.getLE_TData(15, 0));
367  soIHa_Data.write(axisIcmp);
368  bcm_fsmState = BCM_IP;
369  }
370  break;
371  case BCM_IP:
372  //-- Forward the IP header to [IHa]
373  if (((streamSource == 0 && udpInEmpty == 0) || (streamSource == 1 && iprxInEmpty == 0)) &&
374  !soIHa_Data.full() && !soIHa_IpHdr.full()) {
375  // Start reading data from one of the input queues.
376  AxisIcmp axisIcmp(0, 0, 0);
377  if (streamSource == 0) {
378  axisIcmp = siUOE_Data.read();
379  }
380  else if (streamSource == 1) {
381  axisIcmp = siIPRX_Derr.read();
382  }
383  checksumAcc = (checksumAcc +
384  ((axisIcmp.getLE_TData(63, 48) + axisIcmp.getLE_TData(47, 32)) +
385  axisIcmp.getLE_TData(31, 16) + axisIcmp.getLE_TData(15, 0)));
386  soIHa_Data.write(axisIcmp);
387  soIHa_IpHdr.write(axisIcmp);
388  if (ipChunkCounter == 2) {
389  bcm_fsmState = BCM_STREAM;
390  }
391  else {
392  ipChunkCounter++;
393  }
394  }
395  break;
396  case BCM_STREAM:
397  if (((streamSource == 0 && udpInEmpty == 0) || (streamSource == 1 && iprxInEmpty == 0)) && !soIHa_Data.full()) { // If there are data in the queue start reading them
398  AxisIcmp axisIcmp(0, 0, 0);
399  if (streamSource == 0) {
400  axisIcmp = siUOE_Data.read();
401  }
402  else if (streamSource == 1) {
403  axisIcmp = siIPRX_Derr.read();
404  }
405  checksumAcc = (checksumAcc +
406  ((axisIcmp.getLE_TData(63, 48) + axisIcmp.getLE_TData(47, 32)) +
407  axisIcmp.getLE_TData(31, 16) + axisIcmp.getLE_TData(15, 0)));
408  soIHa_Data.write(axisIcmp);
409  if (axisIcmp.getLE_TLast()) {
410  bcm_fsmState = BCM_CS;
411  }
412  }
413  break;
414  case BCM_CS:
415  if (!soICi_Csum.full()) {
416  checksumAcc = (checksumAcc & 0xFFFF) + (checksumAcc >> 16);
417  checksumAcc = (checksumAcc & 0xFFFF) + (checksumAcc >> 16);
418  // Reverse the bits and forward to [ICi]
419  checksumAcc = ~checksumAcc;
420  soICi_Csum.write(checksumAcc.range(15, 0));
421  bcm_fsmState = BCM_IDLE;
422  }
423  break;
424  }
425 }
const IcmpType ICMP_TIME_EXCEEDED
Definition: icmp.hpp:68
const IcmpCode ICMP_DESTINATION_PORT_UNREACHABLE
Definition: icmp.hpp:71
const IcmpCode ICMP_TTL_EXPIRED_IN_TRANSIT
Definition: icmp.hpp:70
#define THIS_NAME
Definition: icmp.cpp:67
const IcmpType ICMP_DESTINATION_UNREACHABLE
Definition: icmp.hpp:66
ap_uint< 1 > StsBit
Definition: nts_types.hpp:116
#define concat3(firstCharConst, secondCharConst, thirdCharConst)
Definition: nts_utils.hpp:161
Here is the call graph for this function:
Here is the caller graph for this function:

◆ pIcmpChecksumChecker()

void pIcmpChecksumChecker ( stream< AxisIp4 > &  siIPRX_Data,
stream< AxisIp4 > &  soIPd_Data,
stream< ValBool > &  soIPd_DropCmd,
stream< IcmpCsum > &  soICi_Csum 
)

ICMP header Checksum accumulator and Checker (ICc)

Parameters
[in]siIPRX_DataThe data stream from the IP Rx handler (IPRX).
[out]soIPd_DataThe data stream to IcmpPacketDropper (IPd)
[out]soIPd_DropCmdTHe drop command information for [IPd].
[out]soICi_CsumICMP checksum to IcmpChecksumInserter (ICi).

This process handles the incoming data stream from the IPRX. It assesses the validity of the ICMP checksum while forwarding the data stream to the InvalidPacketDropper (IPd). If the incoming packet is an ICMP_REQUEST, the packet forwarded to [IPd] is turned into an ICMP_REPLY by overwriting the 'Type' field. To avoid the recomputing of the entire ICMP checksum, an incremental checksum update is performed as described in RFC-1624. The resulting new header checksum is then forwarded to the IcmpChecksumInserter (ICi).

Warning
It is expected that the IP header does not have any option.

The format of the incoming ICMP message embedded into an IPv4 packet is as follows: 6 5 4 3 2 1 0 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Frag Ofst (L) |Flags| FO(H) | Identification | Total Length |Type of Service|Version| IHL | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Source Address | Header Checksum | Protocol | Time to Live | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Checksum | Code | Type | Destination Address | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Rest of Header (content varies based on the ICMP Type and Code) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Data | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Definition at line 117 of file icmp.cpp.

122 {
123  //-- DIRECTIVES FOR THIS PROCESS ------------------------------------------
124  #pragma HLS INLINE off
125  #pragma HLS PIPELINE II=1 enable_flush
126 
127  const char *myName = concat3(THIS_NAME, "/", "ICc");
128 
129  //-- STATIC CONTROL VARIABLES (with RESET) --------------------------------
130  static bool icc_writeLastOne=false;
131  #pragma HLS RESET variable=icc_writeLastOne
132  static bool icc_computeCs=false;
133  #pragma HLS RESET variable=icc_computeCs
134  static ap_uint<7> icc_chunkCount=0; // The max len of ICMP messages is 576 bytes
135  #pragma HLS RESET variable=icc_chunkCount
136  static enum FsmStates { S0=0, S1, S2, S3 } icc_csumState=S0;
137  #pragma HLS RESET variable=icc_csumState
138 
139  //-- STATIC DATAFLOW VARIABLES --------------------------------------------
140  static AxisIp4 icc_prevChunk;
141  static Sum17 icc_subSums[4];
142  static IcmpCsum icc_oldHCsum;
143  static Sum17 icc_newHCsum;
144  static IcmpType icc_icmpType;
145  static IcmpCode icc_icmpCode;
146 
147  //-- DYNAMIC VARIABLES ----------------------------------------------------
148  AxisIp4 currChunk;
149  AxisIp4 sendChunk;
150 
151  enum { CHUNK_0=0, CHUNK_1, CHUNK_2, CHUNK_3, CHUNK_4, CHUNK_5 };
152 
153  currChunk.setLE_TLast(0);
154 
155  if (icc_writeLastOne) {
156  // Forward the very last AxisChunk
157  soIPd_Data.write(icc_prevChunk);
158  icc_writeLastOne = false;
159  }
160  else if (icc_computeCs) {
161  switch (icc_csumState) {
162  case S0:
163  icc_subSums[0] += icc_subSums[2];
164  icc_subSums[0] = (icc_subSums[0] + (icc_subSums[0] >> 16)) & 0xFFFF;
165  icc_subSums[1] += icc_subSums[3];
166  icc_subSums[1] = (icc_subSums[1] + (icc_subSums[1] >> 16)) & 0xFFFF;
167  //-- [RFC-1624] --> HC' = ~(~HC + ~m + m')
168  icc_newHCsum = ~icc_oldHCsum & 0xFFFF;
169  icc_csumState = S1;
170  break;
171  case S1:
172  icc_subSums[0] += icc_subSums[1];
173  icc_subSums[0] = (icc_subSums[0] + (icc_subSums[0] >> 16)) & 0xFFFF;
174  if ((icc_icmpType == ICMP_ECHO_REQUEST) && (icc_icmpCode == 0)) {
175  // Message is a PING -> Perform incremental update of chechsum
176  //-- [RFC-1624] --> HC' = ~(~HC + ~m + m')
177  icc_newHCsum = icc_newHCsum + (~0x0800 & 0xFFFF) + 0x0000;
178  icc_newHCsum = (icc_newHCsum + (icc_newHCsum >> 16)) & 0xFFFF;
179  }
180  icc_csumState = S2;
181  break;
182  case S2:
183  icc_subSums[0] = ~icc_subSums[0];
184  //-- [RFC-1624] --> HC' = ~(~HC + ~m + m')
185  icc_newHCsum = ~icc_newHCsum & 0xFFFF;
186  icc_csumState = S3;
187  break;
188  case S3:
189  if (icc_subSums[0](15, 0) == 0) {
190  if (DEBUG_LEVEL & TRACE_ICC) {
191  printInfo(myName, "\tThe checksum is valid.\n");
192  }
193  if ((icc_icmpType == ICMP_ECHO_REQUEST) && (icc_icmpCode == 0)) {
194  soICi_Csum.write(icc_newHCsum.range(15, 0));
195  soIPd_DropCmd.write(CMD_KEEP);
196  if (DEBUG_LEVEL & TRACE_ICC) {
197  printInfo(myName, "\tThe control message is ECHO-REQUEST (.i.e Ping).\n");
198  printInfo(myName, "\t\tThe computed new checksum for ECHO-REPLY is 0x%4.4X.\n",
199  icc_newHCsum.range(15, 0).to_uint());
200  }
201  }
202  else {
203  soIPd_DropCmd.write(CMD_DROP);
204  if (DEBUG_LEVEL & TRACE_ICC) {
205  printWarn(myName, "\tThis control message is not supported.\n");
206  printInfo(myName, "\t\tThe message-type is %d and message-code is %d.\n",
207  icc_icmpType.to_int(), icc_icmpCode.to_int());
208  }
209  }
210  }
211  else {
212  soIPd_DropCmd.write(CMD_DROP);
213  if (DEBUG_LEVEL & TRACE_ICC) {
214  printWarn(myName, "\tThe checksum is invalid.\n");
215  }
216  }
217  icc_csumState = S0;
218  icc_computeCs = false;
219  break;
220  }
221  }
222  else if (!siIPRX_Data.empty()) {
223  siIPRX_Data.read(currChunk);
224  switch (icc_chunkCount) {
225  case CHUNK_0: // The current chunk contains [ FO | Id | TotLen | ToS | IHL ]
226  icc_subSums[0] = 0;
227  icc_subSums[1] = 0;
228  icc_subSums[2] = 0;
229  icc_subSums[3] = 0;
230  break;
231  case CHUNK_1: // The current chunk contains [ SA | HdCsum | Prot | TTL ]
232  sendChunk = icc_prevChunk;
233  soIPd_Data.write(sendChunk);
234  break;
235  case CHUNK_2: // The current chunk contains [ Csum | Code | Type | DA ]
236  // Save ICMP Type, Code and Checksum
237  icc_icmpType = currChunk.getIcmpType();
238  icc_icmpCode = currChunk.getIcmpCode();
239  icc_oldHCsum = currChunk.getIcmpCsum();
240  // Forward data stream while swapping IP_SA & IP_DA
241  sendChunk.setIp4TtL(icc_prevChunk.getIp4TtL());
242  sendChunk.setIp4Prot(icc_prevChunk.getIp4Prot());
243  sendChunk.setIp4HdrCsum(icc_prevChunk.getIp4HdrCsum());
244  sendChunk.setIp4SrcAddr(currChunk.getIp4DstAddr());
245  sendChunk.setLE_TKeep(0xFF);
246  sendChunk.setLE_TLast(0);
247  soIPd_Data.write(sendChunk);
248  // Accumulate [ Csum | Code | Type ]
249  for (int i=2; i<4; i++) {
250  #pragma HLS UNROLL
251  ap_uint<16> temp;
252  temp( 7, 0) = currChunk.getLE_TData(i*16+15, i*16+8);
253  temp(15, 8) = currChunk.getLE_TData(i*16+ 7, i*16+0);
254  icc_subSums[i] += temp;
255  icc_subSums[i] = (icc_subSums[i] + (icc_subSums[i] >> 16)) & 0xFFFF;
256  }
257  // Replace the IP_DA field with IP_SA
258  currChunk.setIp4DstAddr(icc_prevChunk.getIp4SrcAddr());
259  // Replace ECHO_REQUEST field with ECHO_REPLY
260  currChunk.setIcmpType(ICMP_ECHO_REPLY);
261  break;
262  default:
263  // Accumulate quadword
264  for (int i=0; i<4; i++) {
265  #pragma HLS UNROLL
266  ap_uint<16> temp;
267  if (currChunk.getLE_TKeep(i*2+1, i*2) == 0x3) {
268  temp( 7, 0) = currChunk.getLE_TData(i*16+15, i*16+8);
269  temp(15, 8) = currChunk.getLE_TData(i*16+ 7, i*16+0);
270  icc_subSums[i] += temp;
271  icc_subSums[i] = (icc_subSums[i] + (icc_subSums[i] >> 16)) & 0xFFFF;
272  }
273  else if (currChunk.getLE_TKeep()[i*2] == 0x1) {
274  temp( 7, 0) = 0;
275  temp(15, 8) = currChunk.getLE_TData(i*16+7, i*16);
276  icc_subSums[i] += temp;
277  icc_subSums[i] = (icc_subSums[i] + (icc_subSums[i] >> 16)) & 0xFFFF;
278  }
279  }
280  sendChunk = icc_prevChunk;
281  soIPd_Data.write(sendChunk);
282  break;
283  } // End-of: switch (icc_chunkCount)
284 
285  icc_prevChunk = currChunk;
286  icc_chunkCount++;
287 
288  if (currChunk.getLE_TLast()) {
289  icc_chunkCount = 0;
290  icc_writeLastOne = true;
291  icc_computeCs = true;
292  if (DEBUG_LEVEL & TRACE_ICC) {
293  printInfo(myName, "Received a new message (checksum=0x%4.4X)\n",
294  icc_oldHCsum.to_uint());
295  }
296  }
297  }
298 }
Ip4TtL getIp4TtL()
Definition: AxisIp4.hpp:218
void setIcmpType(IcmpType type)
Definition: AxisIp4.hpp:310
IcmpType getIcmpType()
Definition: AxisIp4.hpp:311
void setIp4Prot(Ip4Prot prot)
Definition: AxisIp4.hpp:220
Ip4Addr getIp4DstAddr()
Definition: AxisIp4.hpp:230
void setIp4HdrCsum(Ip4HdrCsum csum)
Definition: AxisIp4.hpp:223
void setIp4DstAddr(Ip4Addr addr)
Definition: AxisIp4.hpp:229
IcmpCsum getIcmpCsum()
Definition: AxisIp4.hpp:317
Ip4Prot getIp4Prot()
Definition: AxisIp4.hpp:221
Ip4Addr getIp4SrcAddr()
Definition: AxisIp4.hpp:227
IcmpCode getIcmpCode()
Definition: AxisIp4.hpp:314
void setIp4SrcAddr(Ip4Addr addr)
Definition: AxisIp4.hpp:226
void setIp4TtL(Ip4TtL ttl)
Definition: AxisIp4.hpp:217
Ip4HdrCsum getIp4HdrCsum()
Definition: AxisIp4.hpp:224
LE_tKeep getLE_TKeep(int leHi=64/8-1, int leLo=0) const
Definition: AxisRaw.hpp:264
LE_tData getLE_TData(int leHi=64 -1, int leLo=0) const
Definition: AxisRaw.hpp:260
void setLE_TLast(LE_tLast last)
Definition: AxisRaw.hpp:280
void setLE_TKeep(LE_tKeep keep, int leHi=64/8-1, int leLo=0)
Definition: AxisRaw.hpp:276
LE_tLast getLE_TLast() const
Definition: AxisRaw.hpp:268
const IcmpType ICMP_ECHO_REPLY
Definition: icmp.hpp:65
const IcmpType ICMP_ECHO_REQUEST
Definition: icmp.hpp:67
ap_uint< 17 > Sum17
Definition: icmp.hpp:75
#define DEBUG_LEVEL
Definition: icmp.cpp:77
#define TRACE_ICC
Definition: icmp.cpp:71
@ CHUNK_2
Definition: toe.hpp:244
@ CHUNK_1
Definition: toe.hpp:244
@ CHUNK_4
Definition: toe.hpp:244
@ CHUNK_5
Definition: toe.hpp:244
@ CHUNK_3
Definition: toe.hpp:244
@ CHUNK_0
Definition: toe.hpp:244
ap_uint< 16 > IcmpCsum
Definition: AxisIcmp.hpp:93
ap_uint< 8 > IcmpCode
Definition: AxisIcmp.hpp:92
#define CMD_DROP
Definition: nts_types.hpp:61
#define CMD_KEEP
Definition: nts_types.hpp:62
#define printInfo(callerName, format,...)
A macro to print an information message.
Definition: nts_utils.hpp:169
#define printWarn(callerName, format,...)
A macro to print a warning message.
Definition: nts_utils.hpp:182
ap_uint< 8 > IcmpType
Definition: AxisIcmp.hpp:91
Here is the call graph for this function:
Here is the caller graph for this function:

◆ pIcmpChecksumInserter()

void pIcmpChecksumInserter ( stream< AxisIp4 siXYz_Data[2],
stream< IcmpCsum siUVw_Csum[2],
stream< AxisIp4 > &  soIPTX_Data 
)

IP Checksum Inserter (ICi)

Parameters
[in]siXYz_DataData stream array from IPd and IHa.
[in]siUVw_CsumICMP checksum array from ICc and CMb.
[out]soIPTX_DataThe data stream to the IpTxHandler (IPTX).

This process inserts both the IP header checksum and the ICMP checksum into the outgoing packet.

Definition at line 602 of file icmp.cpp.

606 {
607  //-- DIRECTIVES FOR THIS PROCESS ------------------------------------------
608  #pragma HLS INLINE off
609  #pragma HLS pipeline II=1
610 
611  const char *myName = concat3(THIS_NAME, "/", "ICi");
612 
613  //-- STATIC CONTROL VARIABLES (with RESET) --------------------------------
614  static ap_uint<7> ici_chunkCount=0; // The max len of ICMP messages is 576 bytes
615  #pragma HLS RESET variable=ici_chunkCount
616 
617  //-- STATIC DATAFLOW VARIABLES --------------------------------------------
618  static ap_uint<1> ici_dataStreamSource; // siIPd_Data or siIHa_Data
619 
620  //-- DYNAMIC VARIABLES ----------------------------------------------------
621  AxisIp4 inputChunk(0, 0, 0);
622  LE_IcmpCsum icmpChecksum;
623 
624  switch(ici_chunkCount) {
625  case 0:
626  bool streamEmptyStatus[2]; // Status of the input data streams
627  for (int i=0; i<2; ++i) {
628  streamEmptyStatus[i] = siXYz_Data[i].empty();
629  }
630  for (int i=0; i<2; ++i) {
631  if(!streamEmptyStatus[i]) {
632  ici_dataStreamSource = i;
633  inputChunk = siXYz_Data[i].read();
634  soIPTX_Data.write(inputChunk);
635  ici_chunkCount++;
636  break;
637  }
638  }
639  break;
640  case 2:
641  if (!siXYz_Data[ici_dataStreamSource].empty() &&
642  !siUVw_Csum[ici_dataStreamSource].empty()) {
643  siXYz_Data[ici_dataStreamSource].read(inputChunk);
644  icmpChecksum = siUVw_Csum[ici_dataStreamSource].read();
645  inputChunk.setIcmpCsum(icmpChecksum);
646  soIPTX_Data.write(inputChunk);
647  ici_chunkCount++;
648  }
649  break;
650  default:
651  if (!siXYz_Data[ici_dataStreamSource].empty()) {
652  siXYz_Data[ici_dataStreamSource].read(inputChunk);
653  soIPTX_Data.write(inputChunk);
654  if (inputChunk.getLE_TLast()) {
655  ici_chunkCount = 0;
656  }
657  else {
658  ici_chunkCount++;
659  }
660  }
661  break;
662  }
663 }
ap_uint< 16 > LE_IcmpCsum
Definition: AxisIcmp.hpp:85
Here is the call graph for this function:
Here is the caller graph for this function:

◆ pInvalidPacketDropper()

void pInvalidPacketDropper ( stream< AxisIp4 > &  siICc_Data,
stream< ValBool > &  siICc_DropCmd,
stream< AxisIp4 > &  soICi_Data 
)

Invalid Packet Dropper (IPd)

Parameters
[in]siICc_DataData stream from IcmpChecksumChecker (ICc).
[in]siICc_DropCmdThe drop command information from [ICc].
[out]soICi_DataData stream to IcmpChecksumInserter (ICi).

This process drops the messages which arrive with a bad checksum. All the other ICMP messages are forwarded to the IcmpChecksumInserter (ICi).

Definition at line 542 of file icmp.cpp.

546 {
547  //-- STATIC CONTROL VARIABLES (with RESET) --------------------------------
548  static bool ipd_isFirstChunk=true;
549  #pragma HLS RESET variable=ipd_isFirstChunk
550 
551  //-- STATIC DATAFLOW VARIABLES --------------------------------------------
552  static bool ipd_drop;
553 
554  //-- DYNAMIC VARIABLES ----------------------------------------------------
555  bool dropCmd;
556 
557  //-- DYNAMIC VARIABLES ----------------------------------------------------
558  AxisIp4 currChunk;
559 
560  if (!siICc_Data.empty()) {
561  if(ipd_isFirstChunk) {
562  if (!siICc_DropCmd.empty()) {
563  siICc_Data.read(currChunk);
564  siICc_DropCmd.read(dropCmd);
565  if(dropCmd == CMD_KEEP) {
566  soICi_Data.write(currChunk);
567  }
568  else {
569  ipd_drop = true;
570  }
571  ipd_isFirstChunk = false;
572  }
573  }
574  else if (ipd_drop) {
575  // Drain and drop current packet
576  siICc_Data.read(currChunk);
577  }
578  else {
579  // Forward packet
580  siICc_Data.read(currChunk);
581  soICi_Data.write(currChunk);
582  }
583  if (currChunk.getLE_TLast()) {
584  ipd_drop = false;
585  ipd_isFirstChunk = true;
586  }
587  }
588 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ pIpHeaderAppender()

void pIpHeaderAppender ( Ip4Addr  piMMIO_Ip4Address,
stream< AxisIcmp > &  siCMb_Data,
stream< AxisIp4 > &  siIHa_IpHdr,
stream< AxisIp4 > &  soICi_Data 
)

IP Header Appender (IHa)

Parameters
[in]piMMIO_Ip4AddressThe IPv4 address from MMIO (in network order).
[in]siCMb_DataData stream from ControlMessageBuilder (CMb).
[in]siIHa_IpHdrThe IP header part of a data stream.
[out]soICi_DataData stream to IcmpChecksumInserter (ICi).

Definition at line 436 of file icmp.cpp.

441 {
442  //-- DIRECTIVES FOR THIS PROCESS ------------------------------------------
443  #pragma HLS INLINE off
444  #pragma HLS pipeline II=1
445 
446  //-- STATIC CONTROL VARIABLES (with RESET) --------------------------------
447  static enum FsmStates { AIH_IDLE=0, AIH_IP, AIH_MERGE, \
448  AIH_STREAM, AIH_RESIDUE } aih_fsmState=AIH_IDLE;
449  #pragma HLS RESET variable=aih_fsmState
450 
451  //-- STATIC DATAFLOW VARIABLES --------------------------------------------
452  static AxisIcmp iha_icmpData(0, 0, 0);
453  static AxisIp4 iha_ipHdrChunk(0, 0, 0);
454  static Ip4Addr iha_remoteIpHostAddr;
455 
456  switch(aih_fsmState) {
457  case AIH_IDLE:
458  if (!siIHa_IpHdr.empty() && !soICi_Data.full()) {
459  //-- Forward the 1st IP header chunk
460  siIHa_IpHdr.read(iha_ipHdrChunk);
461  Ip4TotalLen ip4TotLen = iha_ipHdrChunk.getIp4TotalLen() + 28;
462  iha_ipHdrChunk.setIp4TotalLen(ip4TotLen);
463  iha_ipHdrChunk.setLE_TKeep(0xFF);
464  iha_ipHdrChunk.setLE_TLast(0);
465  soICi_Data.write(iha_ipHdrChunk);
466  aih_fsmState = AIH_IP;
467  }
468  break;
469  case AIH_IP:
470  if (!siIHa_IpHdr.empty() && !soICi_Data.full()) {
471  //-- Forward the 2nd IP header chunk
472  siIHa_IpHdr.read(iha_ipHdrChunk);
473  iha_ipHdrChunk.setIp4TtL(0x80);
474  iha_ipHdrChunk.setIp4Prot(ICMP_PROTOCOL);
475  // Save the remote host address and set the new IP_SA
476  iha_remoteIpHostAddr = iha_ipHdrChunk.getIp4SrcAddr();
477  iha_ipHdrChunk.setIp4SrcAddr(piMMIO_Ip4Address);
478  iha_ipHdrChunk.setLE_TKeep(0xFF);
479  iha_ipHdrChunk.setLE_TLast(0);
480  soICi_Data.write(iha_ipHdrChunk);
481  aih_fsmState = AIH_MERGE;
482  }
483  break;
484  case AIH_MERGE:
485  if (!siIHa_IpHdr.empty() && !siCMb_Data.empty() &&
486  !soICi_Data.full()) {
487  siIHa_IpHdr.read(); // Drain and drop this chunk
488  //-- Merge 3rd IP header chunk with 1st ICMP datagram
489  iha_icmpData = siCMb_Data.read();
490  AxisIp4 thirdChunk(0, 0xFF, 0);
491  thirdChunk.setIp4DstAddr(iha_remoteIpHostAddr);
492  thirdChunk.setIcmpType(iha_icmpData.getIcmpType());
493  thirdChunk.setIcmpCode(iha_icmpData.getIcmpCode());
494  thirdChunk.setIcmpCsum(iha_icmpData.getIcmpCsum());
495  soICi_Data.write(thirdChunk);
496  aih_fsmState = AIH_STREAM;
497  }
498  break;
499  case AIH_STREAM:
500  if (!siCMb_Data.empty() && !soICi_Data.full()) {
501  AxisIp4 outputChunk(0, 0xFF, 0);
502  outputChunk.setLE_TData(iha_icmpData.getLE_TData(63, 32), 31, 0);
503  iha_icmpData = siCMb_Data.read();
504  outputChunk.setLE_TData(iha_icmpData.getLE_TData(31, 0), 63, 32);
505  if (iha_icmpData.getLE_TLast()) {
506  if (iha_icmpData.getLE_TKeep(7, 4) == 0) {
507  outputChunk.setLE_TLast(TLAST);
508  outputChunk.setLE_TKeep(iha_icmpData.getLE_TKeep(3,0), 7, 4);
509  aih_fsmState = AIH_IDLE;
510  }
511  else {
512  aih_fsmState = AIH_RESIDUE;
513  }
514  }
515  soICi_Data.write(outputChunk);
516  }
517  break;
518  case AIH_RESIDUE:
519  if (!soICi_Data.full()) {
520  AxisIp4 outputChunk(0, 0, 1);
521  outputChunk.setLE_TData(iha_icmpData.getLE_TData(63, 32), 31, 0);
522  outputChunk.setLE_TKeep(iha_icmpData.getLE_TKeep( 7, 4), 3, 0);
523  soICi_Data.write(outputChunk);
524  aih_fsmState = AIH_IDLE;
525  }
526  break;
527  }
528 }
const Ip4Prot ICMP_PROTOCOL
Definition: icmp.hpp:73
ap_uint< 32 > Ip4Addr
Definition: AxisIp4.hpp:169
ap_uint< 16 > Ip4TotalLen
Definition: AxisIp4.hpp:159
#define TLAST
Definition: AxisRaw.hpp:116
Here is the call graph for this function:
Here is the caller graph for this function:

Variable Documentation

◆ gTraceEvent

bool gTraceEvent
extern

HELPERS FOR THE DEBUGGING TRACES .e.g: DEBUG_LEVEL = (TRACE_MPd | TRACE_IBUF)

HELPERS FOR THE DEBUGGING TRACES .e.g: DEBUG_LEVEL = (MDL_TRACE | IPS_TRACE)

Definition at line 151 of file tb_nal.cpp.

◆ ICMP_DESTINATION_PORT_UNREACHABLE

const IcmpCode ICMP_DESTINATION_PORT_UNREACHABLE = 0x03

Definition at line 71 of file icmp.hpp.

◆ ICMP_DESTINATION_UNREACHABLE

const IcmpType ICMP_DESTINATION_UNREACHABLE = 0x03

Definition at line 66 of file icmp.hpp.

◆ ICMP_ECHO_REPLY

const IcmpType ICMP_ECHO_REPLY = 0x00

Definition at line 65 of file icmp.hpp.

◆ ICMP_ECHO_REQUEST

const IcmpType ICMP_ECHO_REQUEST = 0x08

Definition at line 67 of file icmp.hpp.

◆ ICMP_PROTOCOL

const Ip4Prot ICMP_PROTOCOL = 0x01

Definition at line 73 of file icmp.hpp.

◆ ICMP_TIME_EXCEEDED

const IcmpType ICMP_TIME_EXCEEDED = 0x0B

Definition at line 68 of file icmp.hpp.

◆ ICMP_TTL_EXPIRED_IN_TRANSIT

const IcmpCode ICMP_TTL_EXPIRED_IN_TRANSIT = 0x00

Definition at line 70 of file icmp.hpp.