cloudFPGA (cF) API  1.0
The documentation of the source code of cloudFPGA (cF)
udp.cpp
Go to the documentation of this file.
1 
17 
43 
56 #include "udp.hpp"
57 
58 #define packetSize 16
59 
60 ap_uint<4> countBits(ap_uint<8> bitVector) {
61  ap_uint<4> bitCounter = 0;
62  for (uint8_t i=0;i<8;++i) {
63  if (bitVector.bit(i) == 1)
64  bitCounter++;
65  }
66  return bitCounter;
67 }
68 
69 ap_uint<8> length2keep_mapping(ap_uint<4> lengthValue) {
70  ap_uint<8> keep = 0;
71  for (uint8_t i=0;i<8;++i) {
72  if (i < lengthValue)
73  keep.bit(i) = 1;
74  }
75  return keep;
76 }
77 
78 ap_uint<32> byteSwap32(ap_uint<32> inputVector) {
79  return (inputVector.range(7,0), inputVector(15, 8), inputVector(23, 16), inputVector(31, 24));
80 }
81 
82 ap_uint<16> byteSwap16(ap_uint<16> inputVector) {
83  return (inputVector.range(7,0), inputVector(15, 8));
84 }
85 
86 using namespace hls;
87 
88 void portTable(stream<ap_uint<16> >& rxEng2portTable_check_req, // Input stream, which queries the port table to determine if the provided port is open
89  stream<ap_uint<16> >& app2portTable_port_req, // Input stream, which allows the application to specify which port's state to toggle
90  stream<ap_uint<16> >& app2portTable_port_rel, // Input stream, which allows the application to release a port upon completing its use
91  stream<bool>& portTable2app_port_assign, // Output stream, over which the port table returns an assigned port to the application
92  stream<bool>& portTable2rxEng_check_rsp) { // Output stream, returning true or false to the Rx path depending on if the queried port is open or not
93 #pragma HLS pipeline II=1 enable_flush
94 
95  static bool portTable[65536];
96  #pragma HLS RESOURCE variable=portTable core=RAM_T2P_BRAM
97  #pragma HLS DEPENDENCE variable=portTable inter false
98 
99  if (!rxEng2portTable_check_req.empty()) { // This part handles querying the state of a port when a packet is received on the Rx side.
100  ap_uint<16> currPort = rxEng2portTable_check_req.read();
101  portTable2rxEng_check_rsp.write(portTable[currPort]);
102  }
103  else if (!app2portTable_port_req.empty()) {
104  ap_uint<16> portToOpen = app2portTable_port_req.read();
105  if (!portTable[portToOpen])
106  portTable2app_port_assign.write(true);
107  else
108  portTable2app_port_assign.write(false);
109  portTable[portToOpen] = true;
110  }
111  else if (!app2portTable_port_rel.empty()) {
112  ap_uint<16> releasedPort = app2portTable_port_rel.read();
113  portTable[releasedPort] = false;
114  }
115 }
116 
117 void inputPathRxEngine(stream<axiWord> &inputPathInputData, stream<ipTuple> &incomingIPaddresses, stream<axiWord> &inputPathIPheader, stream<ap_uint<16> >& rxEng2portTable_check_req,
118  stream<bool>& portTable2rxEng_assign, stream<bool> &rxChecksum2rxEngine, stream<axiWord> &inputPathOutputData,
119  stream<metadata> &inputPathOutputMetadata, stream<axiWord> &inputPathPortUnreachable) {
120  #pragma HLS INLINE off
121  #pragma HLS pipeline II=1 enable_flush
122 
123  static enum iState{IP_IDLE = 0, IP_WAIT, IP_STREAMFIRST, IP_STREAMIP, IP_STREAMREST, IP_DROP, IP_PORT_UNREACHABLE_IP_FIRST, IP_PORT_UNREACHABLE_IP, IP_PORT_UNREACHABLE_UDP, IP_PORT_UNREACHABLE_RESIDUE, IP_DRAIN} inputPathState;
124 
125  static metadata rxPathMetadata = metadata(sockaddr_in(0, 0), sockaddr_in(0, 0));
126  static axiWord bufferWord = axiWord(0, 0, 0);
127  static axiWord ipHdrWord = axiWord(0, 0, 0);
128  static ap_uint<4> rxEngIpHdrWordCount = 0;
129  static ap_uint<1> rxEngNoPayloadFlag = 0;
130 
131  switch(inputPathState) {
132  case IP_IDLE:
133  if (!inputPathInputData.empty() && !incomingIPaddresses.empty() && !inputPathIPheader.empty() && !rxEng2portTable_check_req.full()) {
134  ipTuple ipAddressBuffer = incomingIPaddresses.read();
135  //axiWord inputWord = {0, 0xFF, 0};
136  ipHdrWord = inputPathIPheader.read();
137  rxEngIpHdrWordCount = ipHdrWord.data.range(3,0) - 2;
138  bufferWord = inputPathInputData.read(); // Assumes that the input stream is byte-aligned and has been stripped from the IP header. Hence the first word will be the IDP header
139  (byteSwap16(bufferWord.data.range(47, 32)) > 8) ? rxEngNoPayloadFlag = 0 : rxEngNoPayloadFlag = 1;
140  rxEng2portTable_check_req.write(byteSwap16(bufferWord.data.range(31, 16))); // Send the port state query to the port table
141  rxPathMetadata = metadata(sockaddr_in(byteSwap16(bufferWord.data.range(15, 0)), ipAddressBuffer.sourceIP), sockaddr_in(byteSwap16(bufferWord.data.range(31, 16)), ipAddressBuffer.destinationIP));
142  inputPathState = IP_WAIT;
143  }
144  break;
145  case IP_WAIT:
146  if (!portTable2rxEng_assign.empty() && !rxChecksum2rxEngine.empty()) {
147  bool checksumResult = rxChecksum2rxEngine.read();
148  bool portResult = portTable2rxEng_assign.read();
149  if(portResult && checksumResult && rxEngNoPayloadFlag == 0)
150  inputPathState = IP_STREAMFIRST;
151  else if (!checksumResult || rxEngNoPayloadFlag == 1)
152  inputPathState = IP_DROP;
153  else
154  inputPathState = IP_PORT_UNREACHABLE_IP_FIRST;
155  }
156  break;
157  case IP_STREAMFIRST:
158  if (!inputPathInputData.empty() && !inputPathOutputData.full() && !inputPathOutputMetadata.full()) {
159  axiWord inputWord = inputPathInputData.read();
160  inputPathOutputData.write(inputWord);
161  inputPathOutputMetadata.write(rxPathMetadata);
162  if (inputWord.last == 1)
163  inputPathState = IP_DRAIN;
164  else
165  inputPathState = IP_STREAMIP;
166  }
167  break;
168  case IP_STREAMIP:
169  if (!inputPathInputData.empty() && !inputPathIPheader.empty() && !inputPathOutputData.full() && !inputPathOutputMetadata.full()) {
170  axiWord inputWord = inputPathInputData.read();
171  inputPathIPheader.read();
172  inputPathOutputData.write(inputWord);
173  if (inputWord.last == 1) {
174  if (rxEngIpHdrWordCount <= 2)
175  inputPathState = IP_IDLE;
176  else
177  inputPathState = IP_DRAIN;
178  }
179  else {
180  if (rxEngIpHdrWordCount <= 2)
181  inputPathState = IP_STREAMREST;
182  }
183  rxEngIpHdrWordCount -= 2;
184  }
185  break;
186  case IP_STREAMREST:
187  if (!inputPathInputData.empty() && !inputPathOutputData.full()) {
188  axiWord inputWord = inputPathInputData.read();
189  inputPathOutputData.write(inputWord);
190  if (inputWord.last == 1) {
191  inputPathState = IP_IDLE;
192  }
193  }
194  break;
195  case IP_DROP:
196  if (!inputPathInputData.empty()) {
197  axiWord inputWord = inputPathInputData.read();
198  if (rxEngIpHdrWordCount > 0) {
199  inputPathIPheader.read();
200  rxEngIpHdrWordCount > 2 ? rxEngIpHdrWordCount -= 2 : rxEngIpHdrWordCount = 0;
201  }
202  if (inputWord.last == 1) {
203  if (rxEngIpHdrWordCount == 0 )
204  inputPathState = IP_IDLE;
205  else
206  inputPathState = IP_DRAIN;
207  }
208  }
209  break;
210  case IP_PORT_UNREACHABLE_IP_FIRST:
211  if (!inputPathPortUnreachable.full()) {
212  inputPathPortUnreachable.write(ipHdrWord);
213  inputPathState = IP_PORT_UNREACHABLE_IP;
214  }
215  break;
216  case IP_PORT_UNREACHABLE_IP:
217  if (!inputPathIPheader.empty() && !inputPathPortUnreachable.full()) {
218  axiWord inputWord = inputPathIPheader.read();
219  if (inputWord.last == 1) {
220  inputWord = axiWord(inputWord.data, 0xFF, 0);
221  inputWord.data.range(63, 32) = bufferWord.data.range(31, 0);
222  inputPathState = IP_PORT_UNREACHABLE_UDP;
223  }
224  inputPathPortUnreachable.write(inputWord);
225  }
226  break;
227  case IP_PORT_UNREACHABLE_UDP:
228  if (!inputPathInputData.empty() && !inputPathPortUnreachable.full()) {
229  axiWord inputWord = inputPathInputData.read();
230  bufferWord.data = (inputWord.data.range(31, 0), bufferWord.data.range(63, 32));
231  if (inputWord.last == 1) {
232  if (inputWord.keep.range(7, 4) == 0x0) { // If there's no residue
233  bufferWord.keep.range(7, 4) = inputWord.keep.range(3, 0);
234  bufferWord.last = 1;
235  inputPathState = IP_IDLE;
236  }
237  else {
238  bufferWord.last = 0;
239  inputPathState = IP_PORT_UNREACHABLE_RESIDUE;
240  }
241  inputPathPortUnreachable.write(bufferWord);
242  }
243  else
244  inputPathPortUnreachable.write(bufferWord);
245  bufferWord.data = inputWord.data;
246  }
247  break;
248  case IP_PORT_UNREACHABLE_RESIDUE:
249  if (!inputPathPortUnreachable.full()) {
250  bufferWord = axiWord(0, 0, 1);
251  bufferWord.data.range(31, 0) = bufferWord.data.range(63, 32);
252  bufferWord.keep.range(3, 0) = bufferWord.keep.range(7, 4);
253  inputPathPortUnreachable.write(bufferWord);
254  inputPathState = IP_IDLE;
255  }
256  break;
257  case IP_DRAIN:
258  if (!inputPathIPheader.empty()) {
259  inputPathIPheader.read();
260  if (rxEngIpHdrWordCount > 2)
261  rxEngIpHdrWordCount -= 2;
262  else
263  inputPathState = IP_IDLE;
264  }
265  break;
266  }
267 }
268 
269 void stripIpHeader(stream<axiWord> &inputPathInData, stream<axiWord> &strip2inputPath_data, stream<axiWord> &strip2inputPath_IpHeader, stream<ipTuple> &strip2inputPath_IP, stream<axiWord> &strip2rxChecksum) {
270  #pragma HLS INLINE off
271  #pragma HLS pipeline II=1 enable_flush
272 
273  static enum sState{STRIP_IDLE = 0, STRIP_IP, STRIP_SKIPOPTIONS, STRIP_IP2, STRIP_FORWARD, STRIP_FORWARDALIGNED, STRIP_FORWARD_CS, STRIP_FORWARDCSALIGNED, STRIP_RESIDUE, STRIP_CS_RESIDUE, STRIP_CS_RESIDUEALIGNNED} stripState;
274  static axiWord outputWord = axiWord(0, 0, 0);
275  static ipTuple stripIpTuple = ipTuple(0, 0);
276  static ap_uint<16> udpLength = 0;
277  static ap_uint<4> ipHeaderLength = 0;
278  static ap_uint<4> bitCounter = 0; // Used to count the number of bytes which are valid in the last data word
279  static ap_uint<3> ipHdrWordCount = 0;
280 
281  switch(stripState) {
282  case STRIP_IDLE:
283  if (!inputPathInData.empty() && !strip2inputPath_IpHeader.full()) {
284  bitCounter = 0;
285  ipHdrWordCount = 0;
286  outputWord = inputPathInData.read();
287  udpLength = (outputWord.data.range(23, 16), outputWord.data.range(31, 24)); // Store the IP packet length
288  ipHeaderLength = outputWord.data.range(3, 0); // Store the IP header length in 32-bit words
289  udpLength = udpLength - (ipHeaderLength * 4);
290  strip2inputPath_IpHeader.write(outputWord);
291  stripState = STRIP_IP;
292  }
293  break;
294  case STRIP_IP:
295  if (!inputPathInData.empty() && !strip2inputPath_IpHeader.full()) {
296  outputWord = inputPathInData.read();
297  stripIpTuple.sourceIP = byteSwap32(outputWord.data.range(63, 32));
298  strip2inputPath_IpHeader.write(outputWord);
299  ipHdrWordCount = 1;
300  ipHeaderLength -= 2;
301  if (ipHeaderLength == 3) // Check the remaining IP Hdr legth ad determine if there are options that need to be ignored or if the next word contains UDP Header
302  stripState = STRIP_IP2;
303  else if (ipHeaderLength > 3)
304  stripState = STRIP_SKIPOPTIONS;
305  }
306  break;
307  case STRIP_SKIPOPTIONS:
308  if (!inputPathInData.empty() && !strip2inputPath_IpHeader.full() && !strip2inputPath_IP.full()) {
309  outputWord = inputPathInData.read();
310  if (ipHdrWordCount == 1) {
311  stripIpTuple.destinationIP = byteSwap32(outputWord.data.range(31, 0));
312  strip2inputPath_IP.write(stripIpTuple);
313  axiWord checksumWord = axiWord(0, 0xFF, 0);
314  checksumWord.data = (byteSwap32(stripIpTuple.destinationIP), byteSwap32(stripIpTuple.sourceIP));
315  strip2rxChecksum.write(checksumWord);
316  }
317  strip2inputPath_IpHeader.write(outputWord);
318  ipHeaderLength -= 2;
319  ipHdrWordCount++;
320  if (ipHeaderLength == 2)
321  stripState = STRIP_FORWARDALIGNED;
322  else if (ipHeaderLength == 3)
323  stripState = STRIP_IP2;
324  else if (ipHeaderLength > 3)
325  stripState = STRIP_SKIPOPTIONS;
326  }
327  break;
328  case STRIP_IP2:
329  if (!inputPathInData.empty() && !strip2rxChecksum.full() && !strip2inputPath_IP.full()) {
330  outputWord = inputPathInData.read();
331  if (ipHdrWordCount == 1) {
332  stripIpTuple.destinationIP = byteSwap32(outputWord.data.range(31, 0));
333  strip2inputPath_IP.write(stripIpTuple);
334  axiWord checksumWord = axiWord((byteSwap32(stripIpTuple.destinationIP), byteSwap32(stripIpTuple.sourceIP)), 0xFF, 0);
335  strip2rxChecksum.write(checksumWord);
336  }
337  strip2inputPath_IpHeader.write(axiWord(outputWord.data.range(31, 0), 0x0F, 1));
338  stripState = STRIP_FORWARD;
339  }
340  break;
341  case STRIP_FORWARDALIGNED:
342  if (!inputPathInData.empty() && !strip2rxChecksum.full() && !strip2inputPath_data.full()) {
343  outputWord = inputPathInData.read();
344  axiWord checksumWord = axiWord(0x1100, 0xFF, 0);
345  checksumWord.data.range(31, 16) = byteSwap16(udpLength.range(15, 0)); // Same for the UDP length.
346  checksumWord.data.range(63, 32) = outputWord.data.range(31, 0);
347  strip2rxChecksum.write(checksumWord);
348  strip2inputPath_data.write(outputWord);
349  stripState = STRIP_FORWARDCSALIGNED;
350  }
351  break;
352  case STRIP_FORWARD:
353  if (!inputPathInData.empty() && !strip2rxChecksum.full() && !strip2inputPath_data.full()) {
354  axiWord checksumWord = axiWord(0x1100, 0xFF, 0); // Inject Protocol length in the pseudo header
355  checksumWord.data.range(31, 16) = byteSwap16(udpLength.range(15, 0)); // Same for the UDP length.
356  checksumWord.data.range(63, 32) = outputWord.data.range(63, 32);
357  strip2rxChecksum.write(checksumWord);
358  axiWord tempWord = axiWord(0, 0x0F, 0);
359  tempWord.data.range(31, 0) = outputWord.data.range(63, 32);
360  outputWord = inputPathInData.read();
361  tempWord.data.range(63, 32) = outputWord.data.range(31, 0);
362  tempWord.keep.range(7, 4) = outputWord.keep.range(3, 0);
363  strip2inputPath_data.write(tempWord);
364  if (outputWord.last == 1) {
365  bitCounter = countBits(outputWord.keep);
366  stripState = STRIP_RESIDUE;
367  }
368  else
369  stripState = STRIP_FORWARD_CS;
370  }
371  break;
372  case STRIP_FORWARDCSALIGNED:
373  if (!inputPathInData.empty() && !strip2rxChecksum.full() && !strip2inputPath_data.full()) {
374  axiWord checksumWord = axiWord(0, 0xFF, 0);
375  checksumWord.data.range(31, 0) = outputWord.data.range(63, 32);
376  outputWord = inputPathInData.read();
377  checksumWord.data.range(63, 32) = outputWord.data.range(31, 0);
378  strip2rxChecksum.write(checksumWord);
379  strip2inputPath_data.write(outputWord);
380  if (outputWord.last == 1) {
381  if (outputWord.keep.range(7, 4) > 0)
382  stripState = STRIP_CS_RESIDUEALIGNNED;
383  else
384  stripState = STRIP_IDLE;
385  }
386  }
387  break;
388  case STRIP_FORWARD_CS:
389  if (!inputPathInData.empty() && !strip2rxChecksum.full() && !strip2inputPath_data.full()) {
390  strip2rxChecksum.write(outputWord);
391  //std::cerr << std::hex << outputWord.data << std::endl;
392  axiWord tempWord = axiWord(0, 0x0F, 0);
393  tempWord.data.range(31, 0) = outputWord.data.range(63, 32);
394  outputWord = inputPathInData.read();
395  tempWord.data.range(63, 32) = outputWord.data.range(31, 0);
396  tempWord.keep.range(7, 4) = outputWord.keep.range(3, 0);
397  if (outputWord.last == 1) {
398  bitCounter = countBits(outputWord.keep);
399  if (outputWord.keep.range(7, 4) != 0)
400  stripState = STRIP_RESIDUE;
401  else {
402  tempWord.keep.range(7,4) = outputWord.keep.range(3, 0);
403  tempWord.last = 1;
404  stripState = STRIP_CS_RESIDUE;
405  }
406  }
407  strip2inputPath_data.write(tempWord);
408  }
409  break;
410  case STRIP_RESIDUE:
411  if (!strip2rxChecksum.full() && !strip2inputPath_data.full()) {
412  axiWord tempWord = axiWord(0, 0, 1);
413  axiWord csWord = axiWord(0, outputWord.keep, 1);
414  csWord.data.range((bitCounter.to_int() * 8) - 1, 0) = outputWord.data.range((bitCounter.to_int() * 8) - 1, 0);
415  strip2rxChecksum.write(csWord);
417  tempWord.data.range(31, 0) = outputWord.data.range(63, 32);
418  tempWord.keep.range(3, 0) = outputWord.keep.range(7, 4);
419  //std::cerr << std::hex << tempWord.data << std::endl;
420  strip2inputPath_data.write(tempWord);
421  stripState = STRIP_IDLE;
422  }
423  break;
424  case STRIP_CS_RESIDUE:
425  if (!strip2rxChecksum.full()) {
426  axiWord csWord = axiWord(0, outputWord.keep, 1);
427  csWord.data.range((bitCounter.to_int() * 8) - 1, 0) = outputWord.data.range((bitCounter.to_int() * 8) - 1, 0);
428  strip2rxChecksum.write(csWord);
429  stripState = STRIP_IDLE;
430  }
431  break;
432  case STRIP_CS_RESIDUEALIGNNED:
433  if (!strip2rxChecksum.full()) {
434  //axiWord csWord = {outputWord.data.range(31, 0), outputWord.keep.range(7, 4), 1};
435  //strip2rxChecksum.write(csWord);
436  strip2rxChecksum.write(axiWord(outputWord.data.range(63, 32), outputWord.keep.range(7, 4), 1));
437  stripState = STRIP_IDLE;
438  }
439  break;
440  }
441 }
442 
443 void rxEngineUdpChecksumVerification(stream<axiWord> &dataIn,
444  stream<bool> &udpChecksumOut) {
445 #pragma HLS INLINE off
446 #pragma HLS pipeline II=1 enable_flush
447 
448  static ap_uint<32> udpChecksum = 0;
449  static ap_uint<16> receivedChecksum = 0;
450  static ap_uint<10> wordCounter = 0;
451 
452  if (!dataIn.empty()) {
453  wordCounter++;
454  axiWord inputWord = dataIn.read();
455  if(wordCounter == 3)
456  receivedChecksum = (inputWord.data.range(23, 16), inputWord.data.range(31, 24));
457  udpChecksum = ((((udpChecksum + inputWord.data.range(63, 48)) + inputWord.data.range(47, 32)) + inputWord.data.range(31, 16)) + inputWord.data.range(15, 0));
458  if (inputWord.last) {
459  wordCounter = 0;
460  udpChecksum = (udpChecksum & 0xFFFF) + (udpChecksum >> 16);
461  udpChecksum = (udpChecksum & 0xFFFF) + (udpChecksum >> 16);
462  udpChecksum = ~udpChecksum; // Reverse the bits of the result
463  ap_uint<16> tempChecksum = udpChecksum.range(15, 0);
464  udpChecksumOut.write(tempChecksum == 0 || receivedChecksum == 0);
465  udpChecksum = 0;
466  }
467  }
468 }
469 
470 
471 /* @brief { Brief description (1-2 lines) }
472  * @ingroup (<groupname> [<groupname> <groupname>])
473  *
474  * @param [(dir)] <parameter-name> { parameter description }
475  * @param[in] _inArg1 Description of first function argument.
476  * @param[out] _outArg2 Description of second function argument.
477  * @param[in,out] _inoutArg3 Description of third function argument.
478  *
479  * @return { description of the return value }.
480  *****************************************************************************/
481 void rxEngine(
482  stream<axiWord> &inputPathInData,
483  stream<ap_uint<16> > &app2portTable_port_req,
484  stream<ap_uint<16> > &app2portTable_port_rel,
485  stream<bool> &portTable2app_port_assign,
486  stream<axiWord> &inputPathOutData,
487  stream<metadata> &inputPathOutputMetadata,
488  stream<axiWord> &inputPathPortUnreachable) {
489 
490 #pragma HLS INLINE
491  static stream<ap_uint<16> > rxEng2portTable_check_req("rxEng2portTable_check_req");
492  static stream<bool> portTable2rxEng_assign("portTable2rxEng_assign");
493  static stream<axiWord> strip2inputPath_data("strip2inputPath_data");
494  static stream<ipTuple> strip2inputPath_IP("strip2inputPath_IP");
495  static stream<axiWord> strip2rxChecksum("strip2rxChecksum");
496  static stream<bool> rxChecksum2rxEngine("rxChecksum2rxEngine");
497  static stream<axiWord> strip2inputPath_IPheader("strip2inputPath_IPheader");
498 
499  #pragma HLS STREAM variable=strip2inputPath_data depth=4096
500  #pragma HLS STREAM variable=strip2inputPath_IPheader depth=32
501  #pragma HLS STREAM variable=strip2inputPath_IP depth=8
502  #pragma HLS STREAM variable=strip2rxChecksum depth=8
503  #pragma HLS STREAM variable=rxChecksum2rxEngine depth=4
504 
505  stripIpHeader(inputPathInData, strip2inputPath_data, strip2inputPath_IPheader, strip2inputPath_IP, strip2rxChecksum);
506  rxEngineUdpChecksumVerification(strip2rxChecksum, rxChecksum2rxEngine);
507  inputPathRxEngine(strip2inputPath_data, strip2inputPath_IP, strip2inputPath_IPheader, rxEng2portTable_check_req, portTable2rxEng_assign, rxChecksum2rxEngine, inputPathOutData, inputPathOutputMetadata, inputPathPortUnreachable);
508  portTable(rxEng2portTable_check_req, app2portTable_port_req, app2portTable_port_rel, portTable2app_port_assign, portTable2rxEng_assign);
509 }
510 
511 void outputPathWriteFunction(stream<axiWord> &outputPathInData, stream<metadata> &outputPathInMetadata, stream<ap_uint<16> > &outputpathInLength,
512  stream<ap_uint<64> > &packetData, stream<ap_uint<16> > &packetLength, stream<metadata> &udpMetadata,
513  stream<ioWord> &outputPathWriteFunction2checksumCalculation) {
514  #pragma HLS INLINE off
515  #pragma HLS pipeline II=1 enable_flush
516 
517  static enum opwfState{OW_IDLE = 0, OW_PSEUDOHEADER, OW_MIX, OW_STREAM, OW_RESIDUE, OW_SWCS, OW_ONLYPACKETRESIDUE} outputPathWriteFunctionState;
518  static axiWord outputPathInputWord = axiWord(0, 0, 0); // Temporary buffer for the input data word
519  static ap_uint<16> outputPathPacketLength = 0; // Temporary buffer for the packet data length
520  static metadata tempMetadata = metadata(sockaddr_in(0, 0), sockaddr_in(0, 0)); // Temporary buffer for the destination & source IP addresses & ports
521 
522  switch(outputPathWriteFunctionState) {
523  case OW_IDLE:
524  if (!outputPathInMetadata.empty() && !outputPathWriteFunction2checksumCalculation.full()) {
525  tempMetadata = outputPathInMetadata.read(); // Read in the metadata
526  udpMetadata.write(tempMetadata); // Write the metadata in the buffer for the next stage
527  ioWord checksumOutput = {0, 0}; // Temporary variable for the checksum calculation data word
528  checksumOutput.data = (byteSwap32(tempMetadata.destinationSocket.addr), byteSwap32(tempMetadata.sourceSocket.addr)); // Create the first checksum calc. data word. Byte swap the addresses
529  outputPathWriteFunction2checksumCalculation.write(checksumOutput); // Write the data word into the output
530  outputPathWriteFunctionState = OW_PSEUDOHEADER; // Move into the next state
531  }
532  break;
533  case OW_PSEUDOHEADER:
534  if (!outputpathInLength.empty() && !outputPathWriteFunction2checksumCalculation.full()) {
535  outputPathPacketLength = outputpathInLength.read(); // Read in the payload length
536  outputPathPacketLength += 8; // Increase the length to take the UDP header into account.
537  packetLength.write(outputPathPacketLength); // Write length into the buffer for the next stage
538  ioWord checksumOutput = {0x1100, 0}; // Create the 2nd checksum word. 0x1100 is the protocol used
539  checksumOutput.data.range(63, 16) = (byteSwap16(tempMetadata.destinationSocket.port), byteSwap16(tempMetadata.sourceSocket.port), byteSwap16(outputPathPacketLength)); // Add destination & source port & packet length info for the checksum calculation
540  //std::cerr << std::hex << checksumOutput << std::endl;
541  outputPathWriteFunction2checksumCalculation.write(checksumOutput); // Write the checksum word into the output
542  outputPathWriteFunctionState = OW_MIX; // Move to the next state
543  }
544  break;
545  case OW_MIX:
546  if (!outputPathInData.empty() && !outputPathWriteFunction2checksumCalculation.full()) {
547  outputPathInputWord = outputPathInData.read(); // Read in the first payload length
548  ioWord checksumOutput = {0, 0}; // First payload length
549  checksumOutput.data.range(15, 0) = (outputPathPacketLength.range(7, 0), outputPathPacketLength.range(15, 8)); // Packet length for the checksum calculation data
550  checksumOutput.data.range(63, 32) = outputPathInputWord.data.range(31, 0); // Payload data copy to the checksum calculation
551  if (outputPathInputWord.last == 1) { // When the last data word is read
552  packetData.write(outputPathInputWord.data);
553  if (outputPathInputWord.keep.range(7, 4) == 0) {
554  outputPathWriteFunctionState = OW_IDLE; // Move to the residue state and output any remaining data.
555  checksumOutput.eop = 1;
556  }
557  else
558  outputPathWriteFunctionState = OW_SWCS;
559  }
560  else
561  outputPathWriteFunctionState = OW_STREAM; // Go into next state
562  outputPathWriteFunction2checksumCalculation.write(checksumOutput); // Write checksum calculation data word
563  }
564  break;
565  case OW_STREAM: // This state streams all the payload data into both the checksum calculation stage and the next stage, reformatting them as required
566  if (!outputPathInData.empty() && !packetData.full() && !outputPathWriteFunction2checksumCalculation.full()) {
567  packetData.write(outputPathInputWord.data); // Write the realignned data word to the next stage
568  ioWord checksumOutput = {0, 0};
569  checksumOutput.data.range(31,0) = outputPathInputWord.data.range(63, 32); // Realign the output data word for the next stage
570  outputPathInputWord = outputPathInData.read(); // Read the next data word
571  checksumOutput.data.range(63, 32) = outputPathInputWord.data.range(31, 0);
572  if (outputPathInputWord.last == 1) {
573  if (outputPathInputWord.keep.bit(4) == 1) // When the last data word is read
574  outputPathWriteFunctionState = OW_RESIDUE; // Move to the residue state and output any remaining data.
575  else {
576  outputPathWriteFunctionState = OW_ONLYPACKETRESIDUE;
577  checksumOutput.eop = 1;
578  }
579  }
580  outputPathWriteFunction2checksumCalculation.write(checksumOutput); // Write the checksum calculation data word
581  }
582  break;
583  case OW_ONLYPACKETRESIDUE:
584  if (!packetData.full()) {
585  packetData.write(outputPathInputWord.data);
586  outputPathWriteFunctionState = OW_IDLE;
587  }
588  break;
589  case OW_SWCS:
590  if (!outputPathWriteFunction2checksumCalculation.full()) {
591  ioWord checksumOutput = {0, 1};
592  checksumOutput.data.range(31, 0) = outputPathInputWord.data.range(63, 32);
593  outputPathWriteFunction2checksumCalculation.write(checksumOutput);
594  outputPathWriteFunctionState = OW_IDLE;
595  }
596  break;
597  case OW_RESIDUE:
598  if (!packetData.full() && !outputPathWriteFunction2checksumCalculation.full()) {
599  ioWord checksumOutput = {0, 1};
600  checksumOutput.data.range(31, 0) = outputPathInputWord.data.range(63, 32);
601  outputPathWriteFunction2checksumCalculation.write(checksumOutput);
602  packetData.write(outputPathInputWord.data);
603  outputPathWriteFunctionState = OW_IDLE;
604  }
605  break;
606  }
607 }
608 
609 void udpChecksumCalculation(stream<ioWord>& dataIn,
610  stream<ap_uint<16> >& udpChecksumOut) {
611 #pragma HLS INLINE off
612 #pragma HLS pipeline II=1 enable_flush
613 
614  static ap_uint<32> udpChecksum = 0;
615 
616  if (!dataIn.empty()) {
617  ioWord inputWord = dataIn.read();
618  udpChecksum = ((((udpChecksum + inputWord.data.range(63, 48)) + inputWord.data.range(47, 32)) + inputWord.data.range(31, 16)) + inputWord.data.range(15, 0));
619  if (inputWord.eop) {
620  udpChecksum = (udpChecksum & 0xFFFF) + (udpChecksum >> 16);
621  udpChecksum = (udpChecksum & 0xFFFF) + (udpChecksum >> 16);
622  udpChecksum = ~udpChecksum; // Reverse the bits of the result
623  udpChecksumOut.write(udpChecksum.range(15, 0)); // and write it into the output
624  udpChecksum = 0;
625  }
626  }
627 }
628 
629 void outputPathReadFunction(stream<ap_uint<64> > &packetData, stream<ap_uint<16> > &packetLength, stream<metadata> &udpMetadata, stream<ap_uint<16> > &udpChecksum,
630  stream<axiWord> &outputPathOutData, stream<ipTuple> &outIPaddresses, stream<ap_uint<16> > &outputPathReadFunction2addIpHeader_length) {
631 
632  #pragma HLS INLINE off
633  #pragma HLS pipeline II=1 enable_flush
634 
635  static enum oprfState{OR_IDLE = 0, OR_STREAM} outputPathReadFunctionState;
636  static ap_uint<16> readFunctionOutputPathPacketLength;
637  static uint32_t myPacketCounter = 0;
638 
639  switch(outputPathReadFunctionState) {
640  case OR_IDLE:
641  if (!packetLength.empty() && !udpMetadata.empty() && !udpChecksum.empty() ) {
642  //std::cerr << myPacketCounter << std::endl;
643  myPacketCounter++;
644 
645  packetLength.read(readFunctionOutputPathPacketLength); // Read the packet length
646  ap_uint<16> interimLength = readFunctionOutputPathPacketLength; // Add the length of the UDP header
647  readFunctionOutputPathPacketLength -= 8;
648  outputPathReadFunction2addIpHeader_length.write(interimLength);
649  metadata tempMetadata = udpMetadata.read();
650  axiWord outputWord = axiWord(0, 0xFF, 0);
651  outputWord.data.range(15, 0) = byteSwap16(tempMetadata.sourceSocket.port);
652  outputWord.data.range(31, 16) = byteSwap16(tempMetadata.destinationSocket.port);
653  outputWord.data.range(47, 32) = byteSwap16(interimLength);
654  outputWord.data.range(63, 48) = udpChecksum.read();
655  //std::cerr << std::hex << outputWord.data << std::endl;
656  outputPathOutData.write(outputWord);
657  ipTuple tempIPaddresses = ipTuple(tempMetadata.sourceSocket.addr, tempMetadata.destinationSocket.addr);
658  outIPaddresses.write(tempIPaddresses);
659  outputPathReadFunctionState = OR_STREAM;
660  }
661  break;
662  case OR_STREAM:
663  if (!packetData.empty()) {
664  ap_uint<64> inputWord = packetData.read();
665  axiWord outputWord = axiWord(inputWord, 0xFF, 0);
666  //std::cerr << std::hex << outputWord.data << std::endl;
667  if (readFunctionOutputPathPacketLength > 8)
668  readFunctionOutputPathPacketLength -= 8;
669  else {
670  outputWord.last = 1;
671  outputWord.keep = length2keep_mapping(static_cast <uint16_t>(readFunctionOutputPathPacketLength));
672  readFunctionOutputPathPacketLength = 0;
673  outputPathReadFunctionState = OR_IDLE;
674  }
675  outputPathOutData.write(outputWord);
676  }
677  break;
678  }
679 }
680 
681 void addIpHeader(stream<axiWord> &outputPathRead2addIpHeader_data, stream<ipTuple> &outputPathRead2addIpHeader_ipAddress,
682  stream<axiWord> &outputPathOutData, stream<ap_uint<16> > &outputPathReadFunction2addIpHeader_length) {
683 
684 #pragma HLS pipeline II=1 enable_flush
685 
686  static enum iState {IPH_IDLE, IPH_IP1, IPH_IP2, IPH_FORWARD, IPH_RESIDUE} iphState;
687  static ipTuple ipHeaderTuple = ipTuple(0, 0);
688  static axiWord outputWord = axiWord(0, 0, 0);
689 
690  switch(iphState) {
691  case IPH_IDLE:
692  if(!outputPathRead2addIpHeader_data.empty() && !outputPathRead2addIpHeader_ipAddress.empty() &&!outputPathReadFunction2addIpHeader_length.empty() && !outputPathOutData.full()) {
693  ap_uint<16> tempLength = outputPathReadFunction2addIpHeader_length.read();
694  tempLength += 20;
695  axiWord tempWord = axiWord(0x0000000034000045, 0xFF, 0);
696  tempWord.data.range(31, 16) = byteSwap16(tempLength);
697  //tempWord.data.range(31, 16) = (tempLength.range(7, 0), tempLength.range(15, 0));
698  outputPathOutData.write(tempWord);
699  iphState = IPH_IP1;
700  }
701  break;
702  case IPH_IP1:
703  if(!outputPathRead2addIpHeader_data.empty() && !outputPathRead2addIpHeader_ipAddress.empty() && !outputPathOutData.full()) {
704  axiWord tempWord = axiWord(0x0, 0xFF, 0);
705  ipHeaderTuple = outputPathRead2addIpHeader_ipAddress.read();
706  tempWord.data.range(31, 0) = 0x000011FF;
707  tempWord.data.range(63, 32) = byteSwap32(ipHeaderTuple.sourceIP);
708  outputPathOutData.write(tempWord);
709  iphState = IPH_IP2;
710  }
711  break;
712  case IPH_IP2:
713  if(!outputPathRead2addIpHeader_data.empty() && !outputPathOutData.full()) {
714  axiWord tempWord = axiWord(0x0, 0xFF, 0);
715  outputWord = outputPathRead2addIpHeader_data.read();
716  tempWord.data.range(31, 0) = byteSwap32(ipHeaderTuple.destinationIP);
717  tempWord.data.range(63, 32) = outputWord.data.range(31, 0);
718  outputPathOutData.write(tempWord);
719  iphState = IPH_FORWARD;
720  }
721  break;
722  case IPH_FORWARD:
723  if(!outputPathRead2addIpHeader_data.empty() && !outputPathOutData.full()) {
724  axiWord tempWord = axiWord(0x0, 0x0F, 0);
725  tempWord.data.range(31, 0) = outputWord.data.range(63, 32);
726  outputWord = outputPathRead2addIpHeader_data.read();
727  tempWord.data.range(63, 32) = outputWord.data.range(31, 0);
728  if(outputWord.last) {
729  if (outputWord.keep.range(7, 4) != 0) {
730  tempWord.keep.range(7, 4) = 0xF;
731  iphState = IPH_RESIDUE;
732  }
733  else {
734  tempWord.keep.range(7, 4) = outputWord.keep.range(3, 0);
735  tempWord.last = 1;
736  iphState = IPH_IDLE;
737  }
738  }
739  else
740  tempWord.keep.range(7, 4) = 0xF;
741  outputPathOutData.write(tempWord);
742  }
743  break;
744  case IPH_RESIDUE:
745  if (!outputPathOutData.full()) {
746  axiWord tempWord = axiWord(outputWord.data.range(63, 32), outputWord.keep.range(7, 4), 1);
747  outputPathOutData.write(tempWord);
748  iphState = IPH_IDLE;
749  }
750  break;
751  }
752 }
753 
754 
755 /* @brief { Brief description (1-2 lines) }
756  * @ingroup (<groupname> [<groupname> <groupname>])
757  *
758  * @param [(dir)] <parameter-name> { parameter description }
759  * @param[in] _inArg1 Description of first function argument.
760  * @param[out] _outArg2 Description of second function argument.
761  * @param[in,out] _inoutArg3 Description of third function argument.
762  *
763  * @return { description of the return value }.
764  *****************************************************************************/
765 void txEngine(
766  stream<axiWord> &outputPathInData,
767  stream<metadata> &outputPathInMetadata,
768  stream<ap_uint<16> > &outputpathInLength,
769  stream<axiWord> &outputPathOutData) {
770 
771 #pragma HLS INLINE
772 
773  // Declare intermediate streams for inter-function communication
774  static stream<ap_uint<64> > packetData("packetData");
775  static stream<ap_uint<16> > packetLength("packetLength");
776  static stream<metadata> udpMetadata("udpMetadata");
777  static stream<ap_uint<16> > checksumCalculation2outputPathReadFunction("checksumCalculation2outputPathReadFunction");
778  static stream<ioWord> outputPathWriteFunction2checksumCalculation("outputPathWriteFunction2checksumCalculation");
779  static stream<axiWord> outputPathRead2addIpHeader_data("outputPathRead2addIpHeader_data");
780  static stream<ipTuple> outputPathRead2addIpHeader_ipAddress("outputPathRead2addIpHeader_ipAddress");
781  static stream<ap_uint<16> > outputPathReadFunction2addIpHeader_length("outputPathReadFunction2addIpHeader_length");
782 
783  #pragma HLS DATA_PACK variable=udpMetadata
784  #pragma HLS DATA_PACK variable=outputPathRead2addIpHeader_ipAddress
785 
786  #pragma HLS STREAM variable=packetData depth=4096
787  #pragma HLS STREAM variable=packetLength depth=8
788  #pragma HLS STREAM variable=udpMetadata depth=8
789  #pragma HLS STREAM variable=outputPathWriteFunction2checksumCalculation depth=32
790 
791  outputPathWriteFunction(outputPathInData, outputPathInMetadata, outputpathInLength, packetData, packetLength, udpMetadata,
792  outputPathWriteFunction2checksumCalculation); // This function receives the data from the user logic, creates the pseudo-header for UDP checksum calculation and send it on to the read stage.
793  udpChecksumCalculation(outputPathWriteFunction2checksumCalculation, checksumCalculation2outputPathReadFunction); // Calculates the UDP checksum value
794  outputPathReadFunction(packetData, packetLength, udpMetadata, checksumCalculation2outputPathReadFunction, outputPathRead2addIpHeader_data, outputPathRead2addIpHeader_ipAddress, outputPathReadFunction2addIpHeader_length); // Reads the checksum value and composes the UDP packet
795  addIpHeader(outputPathRead2addIpHeader_data, outputPathRead2addIpHeader_ipAddress, outputPathOutData, outputPathReadFunction2addIpHeader_length); // Adds the IP header on top of the UDP one.
796 }
797 
798 
799 
800 /* @brief Main process - UDP offload engine.
801  * @ingroup udp
802  *
803  * @param [(dir)] <parameter-name> { parameter description } [TODO]
804  * @param[in] _inArg1 Description of first function argument. [TODO]
805  * @param[out] _outArg2 Description of second function argument. [TODO]
806  * @param[in,out] _inoutArg3 Description of third function argument. [TODO]
807  *
808  * @return { description of the return value }.
809  *****************************************************************************/
810 void udp(
811 
812  //------------------------------------------------------
813  //-- UDMX / This / Open-Port Interfaces
814  //------------------------------------------------------
815  stream<ap_uint<16> > &openPort,
816  stream<bool> &confirmPortStatus,
817 
818 
819 
820  stream<axiWord> &inputPathInData,
821  stream<axiWord> &inputpathOutData,
822 
823 
824  stream<metadata> &inputPathOutputMetadata,
825  stream<ap_uint<16> > &portRelease, // Input Path Streams
826  stream<axiWord> &outputPathInData,
827  stream<axiWord> &outputPathOutData,
828  stream<metadata> &outputPathInMetadata,
829  stream<ap_uint<16> > &outputpathInLength,
830  stream<axiWord> &inputPathPortUnreachable) { // Output Path Streams
831 
832  #pragma HLS INTERFACE ap_ctrl_none port=return // The block-level interface protocol is removed.
833  #pragma HLS DATAFLOW interval=1
834 
835  #pragma HLS DATA_PACK variable=inputPathOutputMetadata
836  #pragma HLS DATA_PACK variable=outputPathInMetadata
837 
838  // Set all of the interfaces as AXI4Stream
839  #pragma HLS resource core=AXI4Stream variable=inputPathInData metadata="-bus_bundle inputPathInData"
840  #pragma HLS resource core=AXI4Stream variable=inputpathOutData metadata="-bus_bundle inputpathOutData"
841  #pragma HLS resource core=AXI4Stream variable=openPort metadata="-bus_bundle openPort"
842  #pragma HLS resource core=AXI4Stream variable=confirmPortStatus metadata="-bus_bundle confirmPortStatus"
843  #pragma HLS resource core=AXI4Stream variable=inputPathOutputMetadata metadata="-bus_bundle inputPathOutputMetadata"
844  #pragma HLS resource core=AXI4Stream variable=portRelease metadata="-bus_bundle portRelease"
845  #pragma HLS resource core=AXI4Stream variable=outputPathInData metadata="-bus_bundle outputPathInData"
846  #pragma HLS resource core=AXI4Stream variable=outputPathOutData metadata="-bus_bundle outputPathOutData"
847  #pragma HLS resource core=AXI4Stream variable=outputPathInMetadata metadata="-bus_bundle outputPathInMetadata"
848  #pragma HLS resource core=AXI4Stream variable=inputPathPortUnreachable metadata="-bus_bundle inputPathPortUnreachable"
849  #pragma HLS resource core=AXI4Stream variable=outputpathInLength metadata="-bus_bundle outputpathInLength"
850 
851  // Data pack all of the interfaces that consist of structs (except the axiWord ones, which are to be mapped to the AXI4S I/F fields)
852 
853  rxEngine(inputPathInData, openPort, portRelease, confirmPortStatus, inputpathOutData, inputPathOutputMetadata, inputPathPortUnreachable); // Rx path
854  txEngine(outputPathInData, outputPathInMetadata, outputpathInLength, outputPathOutData); // Tx path
855 }
ap_uint< 8 > keep
Definition: tcp_ip.hpp:41
ap_uint< 64 > data
Definition: tcp_ip.hpp:40
ap_uint< 1 > last
Definition: tcp_ip.hpp:42
Definition: udp.hpp:99
ap_uint< 1 > eop
Definition: udp.hpp:101
ap_uint< 64 > data
Definition: udp.hpp:100
Definition: udp.hpp:91
ap_uint< 32 > sourceIP
Definition: udp.hpp:92
ap_uint< 32 > destinationIP
Definition: udp.hpp:93
Definition: udp.hpp:83
sockaddr_in destinationSocket
Definition: udp.hpp:85
sockaddr_in sourceSocket
Definition: udp.hpp:84
ap_uint< 32 > addr
Definition: udp.hpp:77
ap_uint< 16 > port
Definition: udp.hpp:76
void outputPathWriteFunction(stream< axiWord > &outputPathInData, stream< metadata > &outputPathInMetadata, stream< ap_uint< 16 > > &outputpathInLength, stream< ap_uint< 64 > > &packetData, stream< ap_uint< 16 > > &packetLength, stream< metadata > &udpMetadata, stream< ioWord > &outputPathWriteFunction2checksumCalculation)
Definition: udp.cpp:511
void rxEngine(stream< axiWord > &inputPathInData, stream< ap_uint< 16 > > &app2portTable_port_req, stream< ap_uint< 16 > > &app2portTable_port_rel, stream< bool > &portTable2app_port_assign, stream< axiWord > &inputPathOutData, stream< metadata > &inputPathOutputMetadata, stream< axiWord > &inputPathPortUnreachable)
Definition: udp.cpp:481
void addIpHeader(stream< axiWord > &outputPathRead2addIpHeader_data, stream< ipTuple > &outputPathRead2addIpHeader_ipAddress, stream< axiWord > &outputPathOutData, stream< ap_uint< 16 > > &outputPathReadFunction2addIpHeader_length)
Definition: udp.cpp:681
void stripIpHeader(stream< axiWord > &inputPathInData, stream< axiWord > &strip2inputPath_data, stream< axiWord > &strip2inputPath_IpHeader, stream< ipTuple > &strip2inputPath_IP, stream< axiWord > &strip2rxChecksum)
Definition: udp.cpp:269
ap_uint< 8 > length2keep_mapping(ap_uint< 4 > lengthValue)
Definition: udp.cpp:69
void rxEngineUdpChecksumVerification(stream< axiWord > &dataIn, stream< bool > &udpChecksumOut)
Definition: udp.cpp:443
void txEngine(stream< axiWord > &outputPathInData, stream< metadata > &outputPathInMetadata, stream< ap_uint< 16 > > &outputpathInLength, stream< axiWord > &outputPathOutData)
Definition: udp.cpp:765
void outputPathReadFunction(stream< ap_uint< 64 > > &packetData, stream< ap_uint< 16 > > &packetLength, stream< metadata > &udpMetadata, stream< ap_uint< 16 > > &udpChecksum, stream< axiWord > &outputPathOutData, stream< ipTuple > &outIPaddresses, stream< ap_uint< 16 > > &outputPathReadFunction2addIpHeader_length)
Definition: udp.cpp:629
void udp(stream< ap_uint< 16 > > &openPort, stream< bool > &confirmPortStatus, stream< axiWord > &inputPathInData, stream< axiWord > &inputpathOutData, stream< metadata > &inputPathOutputMetadata, stream< ap_uint< 16 > > &portRelease, stream< axiWord > &outputPathInData, stream< axiWord > &outputPathOutData, stream< metadata > &outputPathInMetadata, stream< ap_uint< 16 > > &outputpathInLength, stream< axiWord > &inputPathPortUnreachable)
Definition: udp.cpp:810
void udpChecksumCalculation(stream< ioWord > &dataIn, stream< ap_uint< 16 > > &udpChecksumOut)
Definition: udp.cpp:609
ap_uint< 4 > countBits(ap_uint< 8 > bitVector)
Definition: udp.cpp:60
void inputPathRxEngine(stream< axiWord > &inputPathInputData, stream< ipTuple > &incomingIPaddresses, stream< axiWord > &inputPathIPheader, stream< ap_uint< 16 > > &rxEng2portTable_check_req, stream< bool > &portTable2rxEng_assign, stream< bool > &rxChecksum2rxEngine, stream< axiWord > &inputPathOutputData, stream< metadata > &inputPathOutputMetadata, stream< axiWord > &inputPathPortUnreachable)
Definition: udp.cpp:117
void portTable(stream< ap_uint< 16 > > &rxEng2portTable_check_req, stream< ap_uint< 16 > > &app2portTable_port_req, stream< ap_uint< 16 > > &app2portTable_port_rel, stream< bool > &portTable2app_port_assign, stream< bool > &portTable2rxEng_check_rsp)
Definition: udp.cpp:88
ap_uint< 32 > byteSwap32(ap_uint< 32 > inputVector)
Definition: udp.cpp:78
ap_uint< 16 > byteSwap16(ap_uint< 16 > inputVector)
Definition: udp.cpp:82
: UDP offload engine.