cloudFPGA (cF) API  1.0
The documentation of the source code of cloudFPGA (cF)
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
iprx.cpp
Go to the documentation of this file.
1 
17 
43 
56 #include "iprx.hpp"
57 
58 using namespace hls;
59 
60 
64 #ifndef __SYNTHESIS__
65  extern bool gTraceEvent;
66 #endif
67 #define THIS_NAME "IPRX"
68 
69 #define TRACE_OFF 0x0000
70 #define TRACE_IBUF 1 << 1
71 #define TRACE_MPD 1 << 2
72 #define TRACE_ILC 1 << 3
73 #define TRACE_ICA 1 << 4
74 #define TRACE_ICC 1 << 5
75 #define TRACE_IID 1 << 6
76 #define TRACE_ICL 1 << 7
77 #define TRACE_IPR 1 << 8
78 #define TRACE_ALL 0xFFFF
79 
80 #define DEBUG_LEVEL (TRACE_OFF)
81 
82 
83 
95  stream<AxisEth> &siETH_Data,
96  stream<AxisEth> &soMPd_Data)
97 {
98  //-- DIRECTIVES FOR THIS PROCESS -------------------------------------------
99  #pragma HLS INLINE off
100  #pragma HLS PIPELINE II=1 enable_flush
101 
102  const char *myName = concat3(THIS_NAME, "/", "IBuf");
103 
104  if (!siETH_Data.empty() && !soMPd_Data.full()) {
105  AxisEth axisEth;
106  siETH_Data.read(axisEth);
107  if (not axisEth.isValid()) {
108  if (DEBUG_LEVEL & TRACE_IBUF) {
109  printWarn(myName, "Received an AxisChunk with an unexpected \'tkeep\' or \'tlast\' value.\n");
110  printAxisRaw(myName, "Aborting the frame after: ", AxisRaw(axisEth.getLE_TData(), axisEth.getLE_TKeep(), axisEth.getLE_TLast()));
111  }
112  soMPd_Data.write(AxisEth(axisEth.getLE_TData(), 0x00, 1));
113  }
114  else {
115  soMPd_Data.write(axisEth);
116  }
117  }
118 }
119 
120 
134  EthAddr piMMIO_MacAddr,
135  stream<AxisEth> &siIBuf_Data,
136  stream<AxisArp> &soARP_Data,
137  stream<AxisEth> &soILc_Data)
138 {
139  //-- DIRECTIVES FOR THIS PROCESS -------------------------------------------
140  #pragma HLS INLINE off
141  #pragma HLS PIPELINE II=1 enable_flush
142 
143  const char *myName = concat3(THIS_NAME, "/", "MPd");
144 
145  //-- STATIC CONTROL VARIABLES (with RESET) ---------------------------------
146  static enum FsmStates { S0=0, S1 } mpd_fsmState=S0;
147  #pragma HLS RESET variable=mpd_fsmState
148  static ap_uint<2> mpd_chunkCount=0;
149  #pragma HLS RESET variable=mpd_chunkCount
150 
151  //-- STATIC DATAFLOW VARIABLES ---------------------------------------------
152  static EtherType mpd_etherType;
153  static AxisEth mpd_prevChunk;
154 
155  //-- DYNAMIC VARIABLES -----------------------------------------------------
156  AxisEth currChunk;
157 
158  switch (mpd_fsmState) {
159  case S0:
160  if (!siIBuf_Data.empty() && !soARP_Data.full() && !soILc_Data.full()) {
161  siIBuf_Data.read(currChunk);
162  switch (mpd_chunkCount) {
163  case 0:
164  // Compare MAC_DA with our MMIO_MacAddress and with BROADCAST
165  // [TODO - Is this really needed given ARP ?]
166  if (currChunk.getEthDstAddr() != piMMIO_MacAddr &&
167  currChunk.getEthDstAddr() != 0xFFFFFFFFFFFF) {
168  mpd_etherType = CMD_DROP;
169  printInfo(myName, "Requesting current frame with MAC destination address = 0x%16.16lX (0x%16.16lX) to be dropped\n",
170  currChunk.getEthDstAddr().to_long(), currChunk.getLE_EthDstAddr().to_long());
171  }
172  else {
173  mpd_etherType = CMD_KEEP;
174  }
175  mpd_chunkCount++;
176  break;
177  default:
178  if (mpd_chunkCount == 1) {
179  if (mpd_etherType != CMD_DROP) {
180  mpd_etherType = currChunk.getEtherType();
181  }
182  mpd_chunkCount++;
183  }
184  if (mpd_etherType == ETH_ETHERTYPE_ARP) {
185  soARP_Data.write(mpd_prevChunk);
186  }
187  else if (mpd_etherType == ETH_ETHERTYPE_IP4) {
188  soILc_Data.write(mpd_prevChunk);
189  }
190  break;
191  }
192  mpd_prevChunk = currChunk;
193  if (currChunk.getLE_TLast()) {
194  mpd_chunkCount = 0;
195  mpd_fsmState = S1;
196  }
197  }
198  break;
199  case S1:
200  if( !soARP_Data.full() && !soILc_Data.full()){
201  if (mpd_etherType == ETH_ETHERTYPE_ARP) {
202  soARP_Data.write(mpd_prevChunk);
203  }
204  else if (mpd_etherType == ETH_ETHERTYPE_IP4) {
205  soILc_Data.write(mpd_prevChunk);
206  }
207  mpd_fsmState = S0;
208  }
209  break;
210 
211  } // End of: switch
212 }
213 
214 
227  stream<AxisEth> &siMPd_Data,
228  stream<AxisEth> &soICa_Data)
229 {
230  //-- DIRECTIVES FOR THIS PROCESS -------------------------------------------
231  #pragma HLS INLINE off
232  #pragma HLS PIPELINE II=1 enable_flush
233 
234  const char *myName = concat3(THIS_NAME, "/", "ILc");
235 
236  //-- STATIC CONTROL VARIABLES (with RESET) ---------------------------------
237  static ap_uint<2> ilc_leftToWrite=0;
238  #pragma HLS RESET variable=ilc_leftToWrite
239  static enum FsmStates {FSM_IDLE=0, FSM_SIZECHECK, FSM_STREAM} ilc_fsmState=FSM_IDLE;
240  #pragma HLS RESET variable=ilc_fsmState
241  static ap_uint<2> ilc_chunkCount=0;
242  #pragma HLS RESET variable=ilc_chunkCount
243  static ap_uint<1> ilc_filterPacket=0;
244  #pragma HLS RESET variable=ilc_filterPacket
245 
246  //-- STATIC DATAFLOW VARIABLES ---------------------------------------------
247  static ap_shift_reg<AxisEth, 2> chunkBuffer; // A shift reg. holding 2 AxisChunks
248 
249  //-- DYNAMIC VARIABLES -----------------------------------------------------
250  AxisEth tempChunk;
251  Ip4TotalLen ip4TotLen;
252 
253  if (ilc_leftToWrite == 0) {
254  if (!siMPd_Data.empty() && !soICa_Data.full()) {
255  AxisEth currChunk = siMPd_Data.read();
256  switch (ilc_fsmState) {
257  case FSM_IDLE:
258  // Read head of shift reg, shift up one, and load current chunk into location 0
259  chunkBuffer.shift(currChunk);
260  if (ilc_chunkCount == 1) {
261  ilc_fsmState = FSM_SIZECHECK;
262  }
263  ilc_chunkCount++;
264  break;
265  case FSM_SIZECHECK:
266  // Check the IPv4/TotalLength field ([FIXME - Consider removing.])
267  ip4TotLen = currChunk.getIp4TotalLen();
268  if (ip4TotLen > MaxDatagramSize) {
269  ilc_filterPacket = 1;
270  printWarn(myName, "Current frame will be discarded because frame is too long!\n");
271  }
272  else {
273  ilc_filterPacket = 0;
274  if (DEBUG_LEVEL & TRACE_ILC) {
275  printInfo(myName, "Start of IPv4 packet - Total length = %d bytes.\n", ip4TotLen.to_int());
276  }
277  }
278  // Read head of shift reg, shift up one, and load current chunk into location 0
279  tempChunk = chunkBuffer.shift(currChunk);
280  if (ilc_filterPacket == 0) {
281  soICa_Data.write(tempChunk);
282  }
283  ilc_fsmState = FSM_STREAM;
284  break;
285  case FSM_STREAM:
286  tempChunk = chunkBuffer.shift(currChunk);
287  if (ilc_filterPacket == 0) {
288  soICa_Data.write(tempChunk);
289  }
290  break;
291  } // End of: switch
292 
293  if (currChunk.getLE_TLast()) {
294  ilc_chunkCount = 0;
295  ilc_leftToWrite = 2;
296  ilc_fsmState = FSM_IDLE;
297  }
298  }
299  }
300  else if (ilc_leftToWrite != 0 && !soICa_Data.full() ) {
301  tempChunk = chunkBuffer.shift(AxisEth(0, 0, 0));
302  if (ilc_filterPacket == 0) {
303  soICa_Data.write(tempChunk);
304  }
305  ilc_leftToWrite--;
306  }
307 }
308 
309 
324  Ip4Addr piMMIO_Ip4Address,
325  stream<AxisEth> &siILc_Data,
326  stream<AxisIp4> &soIId_Data,
327  stream<Ip4Version> &soIId_IpVer,
328  stream<CmdBit> &soIId_DropCmd,
329  stream<SubSums> &soICc_SubSums)
330 {
331  //-- DIRECTIVES FOR THIS PROCESS -------------------------------------------
332  #pragma HLS INLINE off
333  #pragma HLS PIPELINE II=1 enable_flush
334 
335  const char *myName = concat3(THIS_NAME, "/", "ICa");
336 
337  //-- STATIC CONTROL VARIABLES (with RESET) ---------------------------------
338  static bool ica_wasLastChunk=false;
339  #pragma HLS RESET variable=ica_wasLastChunk
340  static ap_uint<3> ica_chunkCount=0;
341  #pragma HLS RESET variable=ica_chunkCount
342 
343  //-- STATIC DATAFLOW VARIABLES --------------------------------------------
344  static ap_uint<17> ica_ipHdrSums[4];
345  static ap_uint<8> ica_ipHdrLen;
346  static LE_Ip4Addr ica_dstIpAddress;
347  static AxisEth ica_prevChunk;
348 
349  //-- DYNAMIC VARIABLES -----------------------------------------------------
350  AxisEth currChunk;
351  AxisIp4 sendChunk;
352  ap_uint<16> ip4FlagsAndFragOff;
353  bool ipAddrMatch;
354 
355  currChunk.setLE_TLast(0);
356  if (!siILc_Data.empty() && !ica_wasLastChunk && !soIId_IpVer.full() &&
357  !soIId_DropCmd.full() && !soICc_SubSums.full() && !soIId_Data.full()) {
358  siILc_Data.read(currChunk);
359 
360  switch (ica_chunkCount) {
361  case 0:
362  // Skip because chunk contains MAC_SA[1:0] | MAC_DA[5:0]
363  for (int i=0; i<4 ;++i) {
364  ica_ipHdrSums[i] = 0;
365  }
366  ica_chunkCount++;
367  break;
368  case 1:
369  // Retrieve the IP version field
370  soIId_IpVer.write(currChunk.getIp4Version());
371  // Retrieve the Internet Header Length
372  ica_ipHdrLen = currChunk.getIp4HdrLen();
373  // Retrieve the first two bytes of the IPv4 header
374  ica_ipHdrSums[3].range(15,12) = currChunk.getIp4Version();
375  ica_ipHdrSums[3].range(11, 8) = currChunk.getIp4HdrLen();
376  ica_ipHdrSums[3].range( 7, 0) = currChunk.getIp4ToS();
377  ica_chunkCount++;
378  break;
379  case 2:
380  // Check for fragmentation in this cycle. Need to check the MF flag.
381  // If set, then drop. If not set, then check the fragment offset and
382  // if it is non-zero then drop.
383  ip4FlagsAndFragOff = byteSwap16(currChunk.getLE_TData().range(47, 32));
384  if (ip4FlagsAndFragOff.range(12, 0) != 0 || ip4FlagsAndFragOff.bit(13) != 0) {
385  soIId_DropCmd.write(CMD_DROP);
386  if (ip4FlagsAndFragOff.bit(13) != 0) {
387  printWarn(myName, "The More Fragments (MF) is set but IP fragmentation is not supported (yet).\n");
388  }
389  if (ip4FlagsAndFragOff.range(12, 0) != 0) {
390  printWarn(myName, "Fragment offset is set but not supported (yet) !!!\n");
391  }
392  }
393  else {
394  soIId_DropCmd.write(CMD_KEEP);
395  }
396  for (int i = 0; i < 4; i++) {
397  #pragma HLS unroll
398  ica_ipHdrSums[i] += byteSwap16(currChunk.getLE_TData().range(i*16+15, i*16));
399  ica_ipHdrSums[i] = (ica_ipHdrSums[i] + (ica_ipHdrSums[i] >> 16)) & 0xFFFF;
400  }
401  ica_ipHdrLen -= 2;
402  ica_chunkCount++;
403  break;
404  case 3:
405  ica_dstIpAddress.range(31, 16) = currChunk.getIp4DstAddrHi();
406  for (int i = 0; i < 4; i++) {
407  #pragma HLS unroll
408  ica_ipHdrSums[i] += byteSwap16(currChunk.getLE_TData().range(i*16+15, i*16));
409  ica_ipHdrSums[i] = (ica_ipHdrSums[i] + (ica_ipHdrSums[i] >> 16)) & 0xFFFF;
410  }
411  ica_ipHdrLen -= 2;
412  ica_chunkCount++;
413  break;
414 
415  default:
416  if (ica_chunkCount == 4) {
417  ica_dstIpAddress(15, 0) = currChunk.getIp4DstAddrLo();
418  }
419  switch (ica_ipHdrLen) {
420  case 0:
421  break;
422  case 1:
423  // Sum up part0
424  ica_ipHdrSums[0] += currChunk.getIp4DstAddrLo();
425  ica_ipHdrSums[0] = (ica_ipHdrSums[0] + (ica_ipHdrSums[0] >> 16)) & 0xFFFF;
426  ica_ipHdrLen = 0;
427  // Assess destination IP address (FYI - IP Broadcast addresses are dropped)
428  if (ica_dstIpAddress == piMMIO_Ip4Address) {
429  ipAddrMatch = true;
430  }
431  else {
432  ipAddrMatch = false;
433  }
434  soICc_SubSums.write(SubSums(ica_ipHdrSums, ipAddrMatch));
435  break;
436  case 2:
437  // Sum up parts 0-2
438  for (int i = 0; i < 4; i++) {
439  #pragma HLS unroll
440  ica_ipHdrSums[i] += byteSwap16(currChunk.getLE_TData().range(i*16+15, i*16));
441  ica_ipHdrSums[i] = (ica_ipHdrSums[i] + (ica_ipHdrSums[i] >> 16)) & 0xFFFF;
442  }
443  ica_ipHdrLen = 0;
444  // Assess destination IP address (FYI - IP Broadcast addresses are dropped)
445  if (ica_dstIpAddress == piMMIO_Ip4Address) {
446  // || ica_dstIpAddress == 0xFFFFFFFF) {
447  ipAddrMatch = true;
448  }
449  else {
450  ipAddrMatch = false;
451  }
452  soICc_SubSums.write(SubSums(ica_ipHdrSums, ipAddrMatch));
453  break;
454  default:
455  // Sum up everything
456  for (int i = 0; i < 4; i++) {
457  #pragma HLS unroll
458  ica_ipHdrSums[i] += byteSwap16(currChunk.getLE_TData().range(i*16+15, i*16));
459  ica_ipHdrSums[i] = (ica_ipHdrSums[i] + (ica_ipHdrSums[i] >> 16)) & 0xFFFF;
460  }
461  ica_ipHdrLen -= 2;
462  break;
463  }
464  break;
465  } // End of: switch(ica_chunkCount)f
466 
467  if (ica_chunkCount > 2) {
468  // Send AxisIp4 chunks while re-aligning the outgoing chunks
469  sendChunk = AxisIp4((currChunk.getLE_TData().range(47, 0), ica_prevChunk.getLE_TData().range(63, 48)),
470  (currChunk.getLE_TKeep().range( 5, 0), ica_prevChunk.getLE_TKeep().range( 7, 6)),
471  (currChunk.getLE_TKeep()[6] == 0));
472  soIId_Data.write(sendChunk);
473  }
474  ica_prevChunk = currChunk;
475  if (currChunk.getLE_TLast()) {
476  ica_chunkCount = 0;
477  ica_wasLastChunk = !sendChunk.getLE_TLast();
478  }
479  }
480  else if(ica_wasLastChunk && !soIId_Data.full()) {
481  // Send remaining Chunk;
482  sendChunk = AxisIp4(ica_prevChunk.getLE_TData().range(63, 48),
483  ica_prevChunk.getLE_TKeep().range( 7, 6),
484  TLAST);
485  soIId_Data.write(sendChunk);
486  ica_wasLastChunk = false;
487  }
488 }
489 
490 
505  stream<AxisIp4> &siICa_Data,
506  stream<Ip4Version> &siICa_IpVer,
507  stream<ValBit> &siICa_DropFrag,
508  stream<ValBit> &siICc_CsumValid,
509  stream<AxisIp4> &soICl_Data)
510 {
511  //-- DIRECTIVES FOR THIS PROCESS -------------------------------------------
512  #pragma HLS INLINE off
513  #pragma HLS PIPELINE II=1 enable_flush
514 
515  const char *myName = concat3(THIS_NAME, "/", "IId");
516 
517  //-- STATIC CONTROL VARIABLES (with RESET) ---------------------------------
518  static enum FsmStates {FSM_IDLE=0, FSM_FWD, FSM_DROP} iid_fsmState=FSM_IDLE;
519  #pragma HLS RESET variable=iid_fsmState
520 
521  //-- DYNAMIC VARIABLES -----------------------------------------------------
522  AxisIp4 currChunk = AxisIp4(0, 0, 0);
523 
524  switch(iid_fsmState) {
525  case FSM_IDLE:
526  if (!siICc_CsumValid.empty() && !siICa_IpVer.empty() && !siICa_DropFrag.empty() &&
527  !siICa_Data.empty() && !soICl_Data.full()) {
528  siICa_Data.read(currChunk);
529  // Assess validity of the current IPv4 packet
530  ValBit csumValid = (siICc_CsumValid.read() == 1); // CSUM is valid
531  ValBit isIpv4Pkt = (siICa_IpVer.read() == 4); // IP Version is 4
532  ValBit doKeepPkt = (siICa_DropFrag.read() == CMD_KEEP); // Do not drop
533  ap_uint<2> valid = (csumValid + isIpv4Pkt + doKeepPkt);
534  if (valid != 3) {
535  iid_fsmState = FSM_DROP;
536  printWarn(myName, "The current IP packet will be dropped because:\n");
537  printWarn(myName, " csumValid=%d | isIpv4Pkt=%d | doKeepPkt=%d\n",
538  csumValid.to_int(), isIpv4Pkt.to_int(), doKeepPkt.to_int());
539  }
540  else {
541  soICl_Data.write(currChunk);
542  iid_fsmState = FSM_FWD;
543  }
544  }
545  break;
546  case FSM_FWD:
547  if(!siICa_Data.empty() && !soICl_Data.full()) {
548  siICa_Data.read(currChunk);
549  soICl_Data.write(currChunk);
550  if (currChunk.getLE_TLast()) {
551  iid_fsmState = FSM_IDLE;
552  }
553  }
554  break;
555  case FSM_DROP:
556  if(!siICa_Data.empty()){
557  siICa_Data.read(currChunk);
558  if (currChunk.getLE_TLast()) {
559  iid_fsmState = FSM_IDLE;
560  }
561  }
562  break;
563  }
564 }
565 
566 
577  stream<AxisIp4> &siIId_Data,
578  stream<AxisIp4> &soIPr_Data)
579 {
580  //-- DIRECTIVES FOR THIS PROCESS -------------------------------------------
581  #pragma HLS INLINE off
582  #pragma HLS PIPELINE II=1 enable_flush
583 
584  const char *myName = concat3(THIS_NAME, "/", "ICl");
585 
586  //-- STATIC CONTROL VARIABLES (with RESET) ---------------------------------
587  static enum FsmStates {FSM_FWD=0, FSM_DROP} icl_fsmState=FSM_FWD;
588  #pragma HLS RESET variable=icl_fsmState
589  static ap_uint<13> icl_chunkCount=0; // Ip4TotalLen/8
590  #pragma HLS RESET variable=icl_chunkCount
591 
592  //-- STATIC DATAFLOW VARIABLES ---------------------------------------------
593  static Ip4TotalLen icl_ip4TotalLength;
594 
595  switch(icl_fsmState){
596  case FSM_FWD:
597  if (!siIId_Data.empty() && !soIPr_Data.full()) {
598  AxisIp4 currChunk = siIId_Data.read();
599  switch (icl_chunkCount) {
600  case 0:
601  icl_ip4TotalLength = currChunk.getIp4TotalLen();
602  break;
603  default:
604  if (((icl_chunkCount+1)*8) >= icl_ip4TotalLength) {
605  if (currChunk.getLE_TLast() == 0) {
606  icl_fsmState = FSM_DROP;
607  }
608  currChunk.setLE_TLast(TLAST);
609  ap_uint<4> leftLength = icl_ip4TotalLength - (icl_chunkCount*8);
610  currChunk.setLE_TKeep(lenToLE_tKeep(leftLength));
611  }
612  break;
613  } // End of: switch(icl_chunkCount)
614  soIPr_Data.write(currChunk);
615  icl_chunkCount++;
616  if (currChunk.getLE_TLast()) {
617  icl_chunkCount = 0;
618  }
619  }
620  break;
621  case FSM_DROP:
622  if (!siIId_Data.empty()) {
623  AxisIp4 currChunk = siIId_Data.read();
624  if (currChunk.getLE_TLast()) {
625  icl_fsmState = FSM_FWD;
626  }
627  }
628  break;
629 
630  } // End of: switch(icl_fsmState)
631 }
632 
633 
644  stream<SubSums> &siICa_SubSums,
645  stream<ValBit> &soIId_CsumValid)
646 {
647  //-- DIRECTIVES FOR THIS PROCESS -------------------------------------------
648  #pragma HlS INLINE off
649  #pragma HLS PIPELINE II=1 enable_flush
650 
651  const char *myName = concat3(THIS_NAME, "/", "ICc");
652 
653  if (!siICa_SubSums.empty() && !soIId_CsumValid.full()) {
654  SubSums ipHdrSums = siICa_SubSums.read();
655 
656  ipHdrSums.sum0 += ipHdrSums.sum2;
657  ipHdrSums.sum1 += ipHdrSums.sum3;
658  ipHdrSums.sum0 = (ipHdrSums.sum0 + (ipHdrSums.sum0 >> 16)) & 0xFFFF;
659  ipHdrSums.sum1 = (ipHdrSums.sum1 + (ipHdrSums.sum1 >> 16)) & 0xFFFF;
660  ipHdrSums.sum0 += ipHdrSums.sum1;
661  ipHdrSums.sum0 = (ipHdrSums.sum0 + (ipHdrSums.sum0 >> 16)) & 0xFFFF;
662  ipHdrSums.sum0 = ~ipHdrSums.sum0;
663  if (ipHdrSums.sum0(15, 0) != 0x0000) {
664  printError(myName, "Bad IP header checksum: Expected 0x0000 - Computed 0x%4.4X\n", ipHdrSums.sum0(15, 0).to_int());
665  }
666  soIId_CsumValid.write((ipHdrSums.sum0(15, 0) == 0x0000) && ipHdrSums.ipMatch);
667  }
668 }
669 
670 
690  stream<AxisIp4> &siICl_Data,
691  stream<AxisIp4> &soICMP_Data,
692  stream<AxisIp4> &soICMP_Derr,
693  stream<AxisIp4> &soUOE_Data,
694  stream<AxisIp4> &soTOE_Data)
695 {
696  //-- DIRECTIVES FOR THIS PROCESS -------------------------------------------
697  #pragma HLS INLINE off
698  #pragma HLS PIPELINE II=1 enable_flush
699 
700  const char *myName = concat3(THIS_NAME, "/", "IPr");
701 
702  //-- STATIC CONTROL VARIABLES (with RESET) ---------------------------------
703  static enum FsmStates { FSM_IDLE=0, FSM_LAST} ipr_fsmState=FSM_IDLE;
704  #pragma HLS RESET variable=ipr_fsmState
705  static ap_uint<2> ipr_chunkCount=0;
706  #pragma HLS RESET variable=ipr_chunkCount
707  static bool ipr_leftToWrite=false;
708  #pragma HLS RESET variable=ipr_leftToWrite
709 
710  //-- STATIC DATAFLOW VARIABLES ---------------------------------------------
711  static StsBit ipr_ttlExpired;
712  static Ip4Prot ipr_ipProtocol;
713  static AxisIp4 ipr_prevChunk;
714 
715  //-- DYNAMIC VARIABLES -----------------------------------------------------
716  AxisIp4 currChunk;
717 
718  switch (ipr_fsmState) {
719  case FSM_IDLE:
720  if (!siICl_Data.empty() &&
721  !soICMP_Derr.full() && !soICMP_Data.full() &&
722  !soUOE_Data.full() && !soTOE_Data.full()) {
723  siICl_Data.read(currChunk);
724  switch (ipr_chunkCount) {
725  case 0:
726  ipr_chunkCount++;
727  break;
728  default:
729  if (ipr_chunkCount == 1) {
730  if (currChunk.getIp4TtL() == 1) {
731  ipr_ttlExpired = 1;
732  }
733  else {
734  ipr_ttlExpired = 0;
735  }
736  ipr_ipProtocol = currChunk.getIp4Prot();
737  ipr_chunkCount++;
738  }
739  if (ipr_ttlExpired == 1) {
740  // Forward the current IP packet to ICMP for building the error message
741  soICMP_Derr.write(ipr_prevChunk);
742  }
743  else {
744  switch (ipr_ipProtocol) {
745  // FYI - There is no default case. If the current packet
746  // does not match any case, it is automatically dropped.
747  case IP4_PROT_ICMP:
748  soICMP_Data.write(ipr_prevChunk);
749  break;
750  case IP4_PROT_UDP:
751  soUOE_Data.write(ipr_prevChunk);
752  break;
753  case IP4_PROT_TCP:
754  soTOE_Data.write(ipr_prevChunk);
755  break;
756  }
757  }
758  break;
759  }
760  ipr_prevChunk = currChunk;
761  if (currChunk.getLE_TLast()) {
762  ipr_chunkCount = 0;
763  ipr_leftToWrite = true;
764  ipr_fsmState = FSM_LAST;
765  }
766  }
767  break;
768  case FSM_LAST:
769  if (!soICMP_Derr.full() &&
770  !soICMP_Data.full() && !soUOE_Data.full() && !soTOE_Data.full() ) {
771  ap_uint<log2Ceil<8>::val> bitCounter = 0;
772  bitCounter = ipr_prevChunk.getLen();
773  if (ipr_prevChunk.getLE_TKeep() != 0xFF) {
774  ipr_prevChunk.setLE_TData(0, 63, 64-((8-bitCounter.to_int())*8));
775  }
776  if (ipr_ttlExpired == 1) {
777  soICMP_Derr.write(ipr_prevChunk);
778  }
779  else {
780  switch (ipr_ipProtocol) {
781  case IP4_PROT_ICMP:
782  soICMP_Data.write(ipr_prevChunk);
783  break;
784  case IP4_PROT_UDP:
785  soUOE_Data.write(ipr_prevChunk);
786  break;
787  case IP4_PROT_TCP:
788  soTOE_Data.write(ipr_prevChunk);
789  break;
790  }
791  }
792  ipr_leftToWrite = false;
793  ipr_fsmState = FSM_IDLE;
794  }
795  break;
796  }
797 }
798 
799 
800 
826 void iprx(
827  //------------------------------------------------------
828  //-- MMIO Interfaces
829  //------------------------------------------------------
830  EthAddr piMMIO_MacAddress,
831  Ip4Addr piMMIO_Ip4Address,
832  //------------------------------------------------------
833  //-- ETHernet MAC Layer Interface
834  //------------------------------------------------------
835  stream<AxisEth> &siETH_Data,
836  //------------------------------------------------------
837  //-- ARP Interface
838  //------------------------------------------------------
839  stream<AxisArp> &soARP_Data,
840  //------------------------------------------------------
841  //-- ICMP Interfaces
842  //------------------------------------------------------
843  stream<AxisIp4> &soICMP_Data,
844  stream<AxisIp4> &soICMP_Derr,
845  //------------------------------------------------------
846  //-- UOE Interface
847  //------------------------------------------------------
848  stream<AxisIp4> &soUOE_Data,
849  //------------------------------------------------------
850  //-- TOE Interface
851  //------------------------------------------------------
852  stream<AxisIp4> &soTOE_Data)
853 {
854  //-- DIRECTIVES FOR THIS PROCESS -------------------------------------------
855  #pragma HLS DATAFLOW
856  #pragma HLS INLINE
857  #pragma HLS INTERFACE ap_ctrl_none port=return
858 
859  //--------------------------------------------------------------------------
860  //-- LOCAL STREAMS (Sorted by the name of the modules which generate them)
861  //--------------------------------------------------------------------------
862 
863  //-- Input Buffer (IBuf)
864  static stream<AxisEth> ssIBufToMPd_Data ("ssIBufToMPd_Data");
865  #pragma HLS STREAM variable=ssIBufToMPd_Data depth=8192
866 
867  //-- MAC Protocol Detector (MPd)
868  static stream<AxisEth> ssMPdToILc_Data ("ssMPdToILc_Data");
869  #pragma HLS STREAM variable=ssMPdToILc_Data depth=32
870 
871  //-- IPv4 Length Checker (ILc)
872  static stream<AxisEth> ssILcToICa_Data ("ssILcToICa_Data");
873  #pragma HLS STREAM variable=ssILcToICa_Data depth=32
874 
875  //-- IPv4 Checksum Accumulator (ICa)
876  static stream<AxisIp4> ssICaToIId_Data ("ssICaToIId_Data");
877  #pragma HLS STREAM variable=ssICaToIId_Data depth=1024 // Must hold IP header for checksum checking
878  static stream<Ip4Version> ssICaToIId_IpVer ("ssICaToIId_IpVer");
879  #pragma HLS STREAM variable=ssICaToIId_IpVer depth=32
880  static stream<CmdBit> ssICaToIId_DropFrag ("ssICaToIId_DropFrag");
881  #pragma HLS STREAM variable=ssICaToIId_DropFrag depth=32
882  static stream<SubSums> ssICaToICc_SubSums ("ssICaToICc_SubSums");
883  #pragma HLS DATA_PACK variable=ssICaToICc_SubSums
884  #pragma HLS STREAM variable=ssICaToICc_SubSums depth=32
885 
886  //-- IPv4 Invalid Dropper (IId)
887  static stream<AxisIp4> ssIIdToICl_Data ("ssIIdToICl_Data");
888  #pragma HLS DATA_PACK variable=ssIIdToICl_Data
889  #pragma HLS STREAM variable=ssIIdToICl_Data depth=32
890 
891  //-- IPv4 Cut Length (ICl)
892  static stream<AxisIp4> ssIClToIPr_Data ("ssIClToIPr_Data");
893  #pragma HLS DATA_PACK variable=ssIClToIPr_Data
894  #pragma HLS STREAM variable=ssIClToIPr_Data depth=32
895 
896  //-- IPv4 Checksum Checker
897  static stream<ValBit> ssICcToIId_CsumVal ("ssICcToIId_CsumVal");
898  #pragma HLS STREAM variable=ssICcToIId_CsumVal depth=32
899 
900  //-- PROCESS FUNCTIONS -----------------------------------------------------
901 
902  pInputBuffer(
903  siETH_Data,
904  ssIBufToMPd_Data);
905 
907  piMMIO_MacAddress,
908  ssIBufToMPd_Data,
909  soARP_Data,
910  ssMPdToILc_Data);
911 
913  ssMPdToILc_Data,
914  ssILcToICa_Data);
915 
917  piMMIO_Ip4Address,
918  ssILcToICa_Data,
919  ssICaToIId_Data,
920  ssICaToIId_IpVer,
921  ssICaToIId_DropFrag,
922  ssICaToICc_SubSums);
923 
925  ssICaToICc_SubSums,
926  ssICcToIId_CsumVal);
927 
929  ssICaToIId_Data,
930  ssICaToIId_IpVer,
931  ssICaToIId_DropFrag,
932  ssICcToIId_CsumVal,
933  ssIIdToICl_Data);
934 
935  pIpCutLength(
936  ssIIdToICl_Data,
937  ssIClToIPr_Data);
938 
940  ssIClToIPr_Data,
941  soICMP_Data,
942  soICMP_Derr,
943  soUOE_Data,
944  soTOE_Data);
945 
946 }
947 
948 
961 #if HLS_VERSION == 2017
962  void iprx_top(
963  //------------------------------------------------------
964  //-- MMIO Interfaces
965  //------------------------------------------------------
966  EthAddr piMMIO_MacAddress,
967  Ip4Addr piMMIO_Ip4Address,
968  //------------------------------------------------------
969  //-- ETHernet MAC Layer Interface
970  //------------------------------------------------------
971  stream<AxisEth> &siETH_Data,
972  //------------------------------------------------------
973  //-- ARP Interface
974  //------------------------------------------------------
975  stream<AxisArp> &soARP_Data,
976  //------------------------------------------------------
977  //-- ICMP Interfaces
978  //------------------------------------------------------
979  stream<AxisIp4> &soICMP_Data,
980  stream<AxisIp4> &soICMP_Derr,
981  //------------------------------------------------------
982  //-- UOE Interface
983  //------------------------------------------------------
984  stream<AxisIp4> &soUOE_Data,
985  //------------------------------------------------------
986  //-- TOE Interface
987  //------------------------------------------------------
988  stream<AxisIp4> &soTOE_Data)
989 {
990  //-- DIRECTIVES FOR THE INTERFACES -----------------------------------------
991  #pragma HLS INTERFACE ap_ctrl_none port=return
992 
993 
994 
995 
996 
997  #pragma HLS INTERFACE ap_stable register port=piMMIO_MacAddress
998  #pragma HLS INTERFACE ap_stable register port=piMMIO_Ip4Address
999 
1000  #pragma HLS RESOURCE core=AXI4Stream variable=siETH_Data metadata="-bus_bundle siETH_Data"
1001 
1002  #pragma HLS RESOURCE core=AXI4Stream variable=soARP_Data metadata="-bus_bundle soARP_Data"
1003 
1004  #pragma HLS RESOURCE core=AXI4Stream variable=soICMP_Data metadata="-bus_bundle soICMP_Data"
1005  #pragma HLS RESOURCE core=AXI4Stream variable=soICMP_Derr metadata="-bus_bundle soICMP_Derr"
1006 
1007  #pragma HLS RESOURCE core=AXI4Stream variable=soUOE_Data metadata="-bus_bundle soUOE_Data"
1008  #pragma HLS RESOURCE core=AXI4Stream variable=soTOE_Data metadata="-bus_bundle soTOE_Data"
1009 
1010  //-- DIRECTIVES FOR THIS PROCESS -------------------------------------------
1011  #pragma HLS DATAFLOW
1012 
1013  //-- MAIN IPRX PROCESS -----------------------------------------------------
1014  iprx(
1015  //-- MMIO Interfaces
1016  piMMIO_MacAddress,
1017  piMMIO_Ip4Address,
1018  //-- ETHernet MAC Layer Interface
1019  siETH_Data,
1020  //-- ARP Interface
1021  soARP_Data,
1022  //-- ICMP Interfaces
1023  soICMP_Data,
1024  soICMP_Derr,
1025  //-- UDP Interface
1026  soUOE_Data,
1027  //-- TOE Interface
1028  soTOE_Data);
1029 
1030 }
1031 #else
1032  void iprx_top(
1033  //------------------------------------------------------
1034  //-- MMIO Interfaces
1035  //------------------------------------------------------
1036  EthAddr piMMIO_MacAddress,
1037  Ip4Addr piMMIO_Ip4Address,
1038  //------------------------------------------------------
1039  //-- ETHernet MAC Layer Interface
1040  //------------------------------------------------------
1041  stream<AxisRaw> &siETH_Data,
1042  //------------------------------------------------------
1043  //-- ARP Interface
1044  //------------------------------------------------------
1045  stream<AxisRaw> &soARP_Data,
1046  //------------------------------------------------------
1047  //-- ICMP Interfaces
1048  //------------------------------------------------------
1049  stream<AxisRaw> &soICMP_Data,
1050  stream<AxisRaw> &soICMP_Derr,
1051  //------------------------------------------------------
1052  //-- UOE Interface
1053  //------------------------------------------------------
1054  stream<AxisRaw> &soUOE_Data,
1055  //------------------------------------------------------
1056  //-- TOE Interface
1057  //------------------------------------------------------
1058  stream<AxisRaw> &soTOE_Data)
1059 {
1060 
1061  //-- DIRECTIVES FOR THE INTERFACES -----------------------------------------
1062  #pragma HLS INTERFACE ap_ctrl_none port=return
1063 
1064  #pragma HLS INTERFACE ap_stable port=piMMIO_MacAddress name=piMMIO_MacAddress
1065  #pragma HLS INTERFACE ap_stable port=piMMIO_Ip4Address name=piMMIO_Ip4Address
1066 
1067  #pragma HLS INTERFACE axis off port=siETH_Data name=siETH_Data
1068 
1069  #pragma HLS INTERFACE axis off port=soARP_Data name=soARP_Data
1070 
1071  #pragma HLS INTERFACE axis off port=soICMP_Data name=soICMP_Data
1072  #pragma HLS INTERFACE axis off port=soICMP_Derr name=soICMP_Derr
1073 
1074  #pragma HLS INTERFACE axis off port=soUOE_Data name=soUOE_Data
1075  #pragma HLS INTERFACE axis off port=soTOE_Data name=soTOE_Data
1076 
1077  //-- DIRECTIVES FOR THIS PROCESS -------------------------------------------
1078  #pragma HLS DATAFLOW disable_start_propagation
1079 
1080  //-- LOCAL INPUT and OUTPUT STREAMS ----------------------------------------
1081  static stream<AxisEth> ssiETH_Data;
1082  static stream<AxisArp> ssoARP_Data;
1083  static stream<AxisIp4> ssoICMP_Data;
1084  static stream<AxisIp4> ssoICMP_Derr;
1085  static stream<AxisIp4> ssoUOE_Data;
1086  static stream<AxisIp4> ssoTOE_Data;
1087 
1088  //-- INPUT STREAM CASTING --------------------------------------------------
1089  pAxisRawCast(siETH_Data, ssiETH_Data);
1090 
1091  //-- MAIN IPRX PROCESS -----------------------------------------------------
1092  iprx(
1093  //-- MMIO Interfaces
1094  piMMIO_MacAddress,
1095  piMMIO_Ip4Address,
1096  //-- ETHernet MAC Layer Interface
1097  ssiETH_Data,
1098  //-- ARP Interface
1099  ssoARP_Data,
1100  //-- ICMP Interfaces
1101  ssoICMP_Data,
1102  ssoICMP_Derr,
1103  //-- UDP Interface
1104  ssoUOE_Data,
1105  //-- TOE Interface
1106  ssoTOE_Data);
1107 
1108  //-- OUTPUT STREAM CASTING -------------------------------------------------
1109  pAxisRawCast(ssoARP_Data, soARP_Data);
1110  pAxisRawCast(ssoICMP_Data, soICMP_Data);
1111  pAxisRawCast(ssoICMP_Derr, soICMP_Derr);
1112  pAxisRawCast(ssoUOE_Data, soUOE_Data);
1113  pAxisRawCast(ssoTOE_Data, soTOE_Data);
1114 
1115 }
1116 #endif // HLS_VERSION
1117 
Ip4HdrLen getIp4HdrLen()
Definition: AxisEth.hpp:237
Ip4DstAddrHi getIp4DstAddrHi()
Definition: AxisEth.hpp:268
EtherType getEtherType()
Definition: AxisEth.hpp:172
Ip4Version getIp4Version()
Definition: AxisEth.hpp:234
Ip4DstAddrLo getIp4DstAddrLo()
Definition: AxisEth.hpp:270
LE_EthAddr getLE_EthDstAddr()
Definition: AxisEth.hpp:176
Ip4TotalLen getIp4TotalLen()
Definition: AxisEth.hpp:243
EthAddr getEthDstAddr()
Definition: AxisEth.hpp:161
Ip4ToS getIp4ToS()
Definition: AxisEth.hpp:240
Ip4TtL getIp4TtL()
Definition: AxisIp4.hpp:218
Ip4TotalLen getIp4TotalLen()
Definition: AxisIp4.hpp:205
Ip4Prot getIp4Prot()
Definition: AxisIp4.hpp:221
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_TData(LE_tData data, int leHi=64 -1, int leLo=0)
Definition: AxisRaw.hpp:272
int getLen() const
Definition: AxisRaw.hpp:411
void setLE_TKeep(LE_tKeep keep, int leHi=64/8-1, int leLo=0)
Definition: AxisRaw.hpp:276
bool isValid() const
Definition: AxisRaw.hpp:434
LE_tLast getLE_TLast() const
Definition: AxisRaw.hpp:268
Definition: iprx.hpp:73
ap_uint< 17 > sum1
Definition: iprx.hpp:76
ap_uint< 17 > sum0
Definition: iprx.hpp:75
bool ipMatch
Definition: iprx.hpp:79
ap_uint< 17 > sum2
Definition: iprx.hpp:77
ap_uint< 17 > sum3
Definition: iprx.hpp:78
#define FSM_IDLE
Definition: harris.hpp:79
void pIpCutLength(stream< AxisIp4 > &siIId_Data, stream< AxisIp4 > &soIPr_Data)
Definition: iprx.cpp:576
#define TRACE_IBUF
Definition: iprx.cpp:70
void pIpLengthChecker(stream< AxisEth > &siMPd_Data, stream< AxisEth > &soICa_Data)
Definition: iprx.cpp:226
const UdpLen MaxDatagramSize
Definition: iprx.hpp:68
void pIpInvalidDropper(stream< AxisIp4 > &siICa_Data, stream< Ip4Version > &siICa_IpVer, stream< ValBit > &siICa_DropFrag, stream< ValBit > &siICc_CsumValid, stream< AxisIp4 > &soICl_Data)
Definition: iprx.cpp:504
void iprx(EthAddr piMMIO_MacAddress, Ip4Addr piMMIO_Ip4Address, stream< AxisEth > &siETH_Data, stream< AxisArp > &soARP_Data, stream< AxisIp4 > &soICMP_Data, stream< AxisIp4 > &soICMP_Derr, stream< AxisIp4 > &soUOE_Data, stream< AxisIp4 > &soTOE_Data)
Main process of the IP Receive handler (IPRX).
Definition: iprx.cpp:826
#define TRACE_ILC
Definition: iprx.cpp:72
bool gTraceEvent
Definition: tb_nal.cpp:151
void iprx_top(EthAddr piMMIO_MacAddress, Ip4Addr piMMIO_Ip4Address, stream< AxisRaw > &siETH_Data, stream< AxisRaw > &soARP_Data, stream< AxisRaw > &soICMP_Data, stream< AxisRaw > &soICMP_Derr, stream< AxisRaw > &soUOE_Data, stream< AxisRaw > &soTOE_Data)
Top of IP Receive handler (IPRX)
Definition: iprx.cpp:1032
void pInputBuffer(stream< AxisEth > &siETH_Data, stream< AxisEth > &soMPd_Data)
Definition: iprx.cpp:94
#define THIS_NAME
Definition: iprx.cpp:67
void pMacProtocolDetector(EthAddr piMMIO_MacAddr, stream< AxisEth > &siIBuf_Data, stream< AxisArp > &soARP_Data, stream< AxisEth > &soILc_Data)
Definition: iprx.cpp:133
void pIpChecksumChecker(stream< SubSums > &siICa_SubSums, stream< ValBit > &soIId_CsumValid)
Definition: iprx.cpp:643
void pIpPacketRouter(stream< AxisIp4 > &siICl_Data, stream< AxisIp4 > &soICMP_Data, stream< AxisIp4 > &soICMP_Derr, stream< AxisIp4 > &soUOE_Data, stream< AxisIp4 > &soTOE_Data)
Definition: iprx.cpp:689
#define DEBUG_LEVEL
Definition: iprx.cpp:80
void pIpChecksumAccumulator(Ip4Addr piMMIO_Ip4Address, stream< AxisEth > &siILc_Data, stream< AxisIp4 > &soIId_Data, stream< Ip4Version > &soIId_IpVer, stream< CmdBit > &soIId_DropCmd, stream< SubSums > &soICc_SubSums)
Definition: iprx.cpp:323
#define IP4_PROT_ICMP
Definition: nts_types.hpp:183
ap_uint< 8 > Ip4Prot
Definition: AxisIp4.hpp:164
ap_uint< 48 > EthAddr
Definition: AxisEth.hpp:120
#define printError(callerName, format,...)
A macro to print an error message.
Definition: nts_utils.hpp:195
ap_uint< 32 > LE_Ip4Addr
Definition: AxisIp4.hpp:149
LE_tKeep lenToLE_tKeep(ap_uint< 4 > noValidBytes)
A function to set a number of '1' in an 8-bit field. It is used here to set the number of valid bytes...
Definition: nts_utils.cpp:307
ap_uint< 1 > StsBit
Definition: nts_types.hpp:116
#define IP4_PROT_UDP
Definition: nts_types.hpp:185
void printAxisRaw(const char *callerName, AxisRaw chunk)
Prints an Axis raw data chunk (used for debugging).
Definition: nts_utils.cpp:46
ap_uint< 32 > Ip4Addr
Definition: AxisIp4.hpp:169
ap_uint< 1 > ValBit
Definition: nts_types.hpp:117
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
#define CMD_DROP
Definition: nts_types.hpp:61
#define IP4_PROT_TCP
Definition: nts_types.hpp:184
#define ETH_ETHERTYPE_ARP
Definition: nts_types.hpp:156
#define CMD_KEEP
Definition: nts_types.hpp:62
#define printInfo(callerName, format,...)
A macro to print an information message.
Definition: nts_utils.hpp:169
ap_uint< 16 > Ip4TotalLen
Definition: AxisIp4.hpp:159
#define printWarn(callerName, format,...)
A macro to print a warning message.
Definition: nts_utils.hpp:182
#define concat3(firstCharConst, secondCharConst, thirdCharConst)
Definition: nts_utils.hpp:161
#define ETH_ETHERTYPE_IP4
Definition: nts_types.hpp:155
#define TLAST
Definition: AxisRaw.hpp:116
ap_uint< 16 > EtherType
Definition: AxisEth.hpp:122
: IP Receiver packet handler (IPRX).
ap_uint< 16 > byteSwap16(ap_uint< 16 > inputVector)
Definition: udp.cpp:82