cloudFPGA (cF) API  1.0
The documentation of the source code of cloudFPGA (cF)
SimIcmpPacket.hpp
Go to the documentation of this file.
1 /*
2  * Copyright 2016 -- 2021 IBM Corporation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 
30 #ifndef _SIM_ICMP_PACKET_
31 #define _SIM_ICMP_PACKET_
32 
33 #include "nts.hpp"
34 #include "nts_utils.hpp"
35 
36 
37 
50 
51  private:
52  int len; // In bytes
53  std::deque<AxisIcmp> pktQ; // A double-ended queue to store ICMP chunks
54  const char *myName;
55 
56  // Set the length of this ICMP packet (in bytes)
57  void setLen(int pktLen) {
58  this->len = pktLen;
59  }
60  // GSet the length of this ICMP packet (in bytes)
61  int getLen() {
62  return this->len;
63  }
64 
65  // Clear the content of the ICMP packet queue
66  void clear() {
67  this->pktQ.clear();
68  this->len = 0;
69  }
70  // Return the front chunk element of the ICMP packet but do not remove it from the queue
71  AxisIcmp front() {
72  return this->pktQ.front();
73  }
74  // Remove the first chunk element of the ICMP packet queue
75  void pop_front() {
76  this->pktQ.pop_front();
77  }
78  // Add an element at the end of the ICMP packet queue
79  void push_back(AxisIcmp icmpChunk) {
80  this->pktQ.push_back(icmpChunk);
81  }
82 
83  public:
84 
85  // Default Constructor: Constructs a packet of 'pktLen' bytes.
86  SimIcmpPacket(int pktLen) {
87  this->myName = "SimIcmpPacket";
88  setLen(0);
89  if (pktLen > 0 && pktLen <= MTU) {
90  int noBytes = pktLen;
91  while(noBytes > 8) {
92  pushChunk(AxisIcmp(0x0000000000000000, 0xFF, 0));
93  noBytes -= 8;
94  }
95  pushChunk(AxisIcmp(0x0000000000000000, lenToLE_tKeep(noBytes), TLAST));
96  }
97  }
99  this->myName = "SimIcmpPacket";
100  this->len = 0;
101  }
102 
103  // Add a chunk of bytes at the end of the double-ended queue
104  void pushChunk(AxisIcmp icmpChunk) {
105  if (this->size() > 0) {
106  // Always clear 'TLAST' bit of previous chunck
107  this->pktQ[this->size()-1].setLE_TLast(0);
108  }
109  this->pktQ.push_back(icmpChunk);
110  setLen(this->getLen() + icmpChunk.getLen());
111  }
112 
113  // Return the chunk of bytes at the front of the queue and remove that chunk from the queue
115  AxisIcmp headingChunk = this->front();
116  this->pop_front();
117  setLen(getLen() - headingChunk.getLen());
118  return headingChunk;
119  }
120 
121  // Return the length of the ICMP packet (in bytes)
122  int length() { return this->len; }
123 
124  // Return the number of chunk element in the ICMP packet
125  int size() { return this->pktQ.size(); }
126 
127  // Set-Get the Message Type field
128  void setIcmpType(IcmpType type) { pktQ[0].setIcmpType(type); }
129  IcmpType getIcmpType() { return pktQ[0].getIcmpType(); }
130 
131  // Set-Get the Message Code field
132  void setIcmpCode(IcmpCode code) { pktQ[0].setIcmpCode(code); }
133  IcmpCode getCode() { return pktQ[0].getIcmpCode(); }
134 
135  // Set-Get the Message Checksum field
136  void setIcmpChecksum(IcmpCsum csum) { pktQ[0].setIcmpCsum(csum); }
137  IcmpCsum getIcmpChecksum() { return pktQ[0].getIcmpCsum(); }
138 
139  // Set-Get the Identifier field
140  void setIcmpIdent(IcmpIdent id) { pktQ[0].setIcmpIdent(id); }
141  IcmpIdent getIcmpIdent() { return pktQ[0].getIcmpIdent(); }
142 
143  // Set-Get the Sequence Number field
144  void setIcmpSeqNum(IcmpSeqNum num) { pktQ[0].setIcmpSeqNum(num); }
145  IcmpSeqNum getIcmpSeqNum() { return pktQ[0].getIcmpSeqNum(); }
146 
147  // Append data payload to an ICMP header
148  void addIcmpPayload(string pldStr) {
149  if (this->getLen() != ICMP_HEADER_LEN) {
150  printFatal("IcmpPacket", "Empty packet is expected to be of length %d bytes (was found to be %d bytes).\n",
151  ICMP_HEADER_LEN, this->getLen());
152  }
153  int hdrLen = this->getLen(); // in bytes
154  int pldLen = pldStr.size();
155  int q = (hdrLen / 8);
156  int b = (hdrLen % 8);
157  int i = 0;
158  // At this point we are aligned on an 8-byte data chunk since all
159  // ICMP packets have an 8-byte header.
160  while (i < pldLen) {
161  unsigned long leQword = 0x0000000000000000; // in LE order
162  unsigned char leKeep = 0x00;
163  bool leLast = false;
164  while (b < 8) {
165  unsigned char datByte = pldStr[i];
166  leQword = leQword | (datByte << b*8);
167  leKeep = leKeep | (1 << b);
168  i++;
169  b++;
170  if (i == pldLen) {
171  leLast = true;
172  break;
173  }
174  }
175  b = 0;
176  pushChunk(AxisIcmp(leQword, leKeep, leLast));
177  }
178  } // End-of: addIcmpPayload
179 
180  // Calculate the ICMP checksum of the packet.
182  ap_uint<32> csum = 0;
183  for (uint8_t i=0;i<this->size();++i) {
184  ap_uint<64> tempInput = 0x0000000000000000;
185  if (pktQ[i].getLE_TKeep() & 0x01)
186  tempInput.range( 7, 0) = (pktQ[i].getLE_TData().range( 7, 0));
187  if (pktQ[i].getLE_TKeep() & 0x02)
188  tempInput.range(15, 8) = (pktQ[i].getLE_TData().range(15, 8));
189  if (pktQ[i].getLE_TKeep() & 0x04)
190  tempInput.range(23,16) = (pktQ[i].getLE_TData().range(23,16));
191  if (pktQ[i].getLE_TKeep() & 0x08)
192  tempInput.range(31,24) = (pktQ[i].getLE_TData().range(31,24));
193  if (pktQ[i].getLE_TKeep() & 0x10)
194  tempInput.range(39,32) = (pktQ[i].getLE_TData().range(39,32));
195  if (pktQ[i].getLE_TKeep() & 0x20)
196  tempInput.range(47,40) = (pktQ[i].getLE_TData().range(47,40));
197  if (pktQ[i].getLE_TKeep() & 0x40)
198  tempInput.range(55,48) = (pktQ[i].getLE_TData().range(55,48));
199  if (pktQ[i].getLE_TKeep() & 0x80)
200  tempInput.range(63,56) = (pktQ[i].getLE_TData().range(63,56));
201  csum = ((((csum +
202  tempInput.range(63, 48)) + tempInput.range(47, 32)) +
203  tempInput.range(31, 16)) + tempInput.range(15, 0));
204  csum = (csum & 0xFFFF) + (csum >> 16);
205  }
206  // Reverse the bits of the result
207  IcmpCsum icmpCsum = csum;
208  icmpCsum = ~icmpCsum;
209  return byteSwap16(icmpCsum);
210  }
211 
212 
221  this->setIcmpChecksum(0x0000);
222  IcmpCsum newIcmpCsum = calculateIcmpChecksum();
223  // Overwrite the former ICMP checksum
224  this->setIcmpChecksum(newIcmpCsum);
225  return (newIcmpCsum);
226  }
227 
228 }; // End-of: SimIcmpPacket
229 
230 #endif
231 
int getLen() const
Definition: AxisRaw.hpp:411
Class ICMP Packet for simulation.
void setIcmpCode(IcmpCode code)
IcmpType getIcmpType()
SimIcmpPacket(int pktLen)
void pushChunk(AxisIcmp icmpChunk)
IcmpIdent getIcmpIdent()
IcmpCode getCode()
IcmpCsum calculateIcmpChecksum()
IcmpCsum reCalculateIcmpChecksum()
Recalculate the ICMP checksum of a packet.
void setIcmpIdent(IcmpIdent id)
void setIcmpType(IcmpType type)
void addIcmpPayload(string pldStr)
void setIcmpChecksum(IcmpCsum csum)
AxisIcmp pullChunk()
IcmpSeqNum getIcmpSeqNum()
void setIcmpSeqNum(IcmpSeqNum num)
IcmpCsum getIcmpChecksum()
ap_uint< 16 > IcmpIdent
Definition: AxisIcmp.hpp:94
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< 16 > IcmpSeqNum
Definition: AxisIcmp.hpp:95
#define ICMP_HEADER_LEN
Definition: AxisIcmp.hpp:78
ap_uint< 16 > IcmpCsum
Definition: AxisIcmp.hpp:93
ap_uint< 8 > IcmpCode
Definition: AxisIcmp.hpp:92
#define printFatal(callerName, format,...)
A macro to print a fatal error message and exit.
Definition: nts_utils.hpp:208
#define TLAST
Definition: AxisRaw.hpp:116
ap_uint< 8 > IcmpType
Definition: AxisIcmp.hpp:91
: Definition of the Network Transport Stack (NTS) component as if it was an HLS IP core.
: Utilities and helpers for the Network-Transport-Stack (NTS) components.
ap_uint< 16 > byteSwap16(ap_uint< 16 > inputVector)
Definition: udp.cpp:82
#define MTU
Definition: udp.hpp:71