tdaq-develop-2025-02-12
ddcp_sw_emulator.cpp
1 #include <arpa/inet.h>
28 #include <errno.h>
29 #include <netdb.h>
30 #include <netinet/in.h>
31 #include <stdint.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <sys/socket.h>
36 #include <sys/types.h>
37 #include <unistd.h>
38 #include <iostream>
39 
40 #define HWPORT "65000" // the port of the front end (hardware) target
41 #define MAXBUFLEN 1492
42 
43 #define __COUT__ std::cout
44 #define __E__ std::endl
45 
47 void* get_in_addr(struct sockaddr* sa)
48 {
49  if(sa->sa_family == AF_INET)
50  {
51  return &(((struct sockaddr_in*)sa)->sin_addr);
52  }
53 
54  return &(((struct sockaddr_in6*)sa)->sin6_addr);
55 }
56 
57 int makeSocket(char* ip, int /*port*/)
58 {
59  int sockfd;
60  struct addrinfo hints, *servinfo, *p;
61  int rv;
62  // int numbytes;
63  // struct sockaddr_storage their_addr;
64  // socklen_t addr_len;
65  // char s[INET6_ADDRSTRLEN];
66 
67  memset(&hints, 0, sizeof hints);
68  hints.ai_family = AF_UNSPEC;
69  hints.ai_socktype = SOCK_DGRAM;
70 
71  if((rv = getaddrinfo(ip, HWPORT, &hints, &servinfo)) != 0)
72  {
73  fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
74  return 1;
75  }
76 
77  // loop through all the results and make a socket
78  for(p = servinfo; p != NULL; p = p->ai_next)
79  {
80  if((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1)
81  {
82  perror("sw: socket");
83  continue;
84  }
85 
86  break;
87  }
88 
89  if(p == NULL)
90  {
91  fprintf(stderr, "sw: failed to create socket\n");
92  return 2;
93  }
94 
95  freeaddrinfo(servinfo);
96 
97  return sockfd;
98 }
99 
100 int main(int argc, char* argv[])
101 {
102  // 2 types of tests defined:
103  // 1. write and read
104  // 2. burst data read test
105 
106  int sockfd;
107  struct addrinfo hints, *servinfo, *p;
108  int rv;
109  int numbytes;
110  struct sockaddr_storage their_addr;
111  socklen_t addr_len;
112  char s[INET6_ADDRSTRLEN];
113 
114  if(argc != 4)
115  {
116  fprintf(stderr, "usage: ./sw <hostname/ip> <type-of-test> <debug>\n");
117  exit(1);
118  }
119 
120  memset(&hints, 0, sizeof hints);
121  hints.ai_family = AF_UNSPEC;
122  hints.ai_socktype = SOCK_DGRAM;
123 
124  if((rv = getaddrinfo(argv[1], HWPORT, &hints, &servinfo)) != 0)
125  {
126  fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
127  return 1;
128  }
129 
130  // loop through all the results and make a socket
131  for(p = servinfo; p != NULL; p = p->ai_next)
132  {
133  if((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1)
134  {
135  perror("sw: socket");
136  continue;
137  }
138 
139  break;
140  }
141 
142  if(p == NULL)
143  {
144  fprintf(stderr, "sw: failed to create socket\n");
145  return 2;
146  }
147 
148  freeaddrinfo(servinfo);
149 
153 
154  char buff[MAXBUFLEN];
155  unsigned int packetSz;
156  bool debug = false;
157  std::cout << "sw: Line " << __LINE__ << ":::"
158  << "Type of Test: " << type << " debug=" << debug << std::endl;
159 
160  int type = atoi(argv[2]);
161 
162  uint64_t addr = 0; // stoul(argv[3],0,16);
163  sscanf(argv[3], "0x%llX", &addr);
164  uint64_t val = 0;
165 
166  const unsigned int RX_ADDR_OFFSET = 2;
167  const unsigned int RX_DATA_OFFSET = 10;
168  const unsigned int TX_DATA_OFFSET = 2;
169 
170  switch(type)
171  {
172  case 1: // write
173  case 10: // long write
174 
175  sscanf(argv[4], "0x%llX", &val);
176  cout << "====== WRITE "
177  << "| addr: 0x" << hex << setw(12) << addr << " %d " << dec << setw(10)
178  << addr << " \t| write-val: 0x" << hex << setw(12) << val << " %d " << dec
179  << setw(10) << val << endl;
180 
181  // setup write packet ///////////////////////////////////////////////////////////
182  // Read of 2000000 16MB requst :
183  // 0004 000f 0100 0002
184  // 0000 0000 0000 0000
185  // 0000 0000 0000 0000
186  // 0000 0000 001e 8480
187  // 0000 0000 0000 0000
188  // Flipped byte order
189  // 0200 0001 0f00 0400
190  // 0000 0000 0000 0000
191  // 0000 0000 0000 0000
192  // 8084 1e00 0000 0000
193  // 0000 0000 0000 0000
194 
195  packetSz = 0;
196  addr = 0x040000010f000400;
197  memcpy((void*)&buff[packetSz], (void*)&addr, 8);
198  packetSz += 8;
199  addr = 0x0000000000000000;
200  memcpy((void*)&buff[packetSz], (void*)&addr, 8);
201  packetSz += 8;
202  addr = 0x0000000000000000;
203  memcpy((void*)&buff[packetSz], (void*)&addr, 8);
204  packetSz += 8;
205  addr = 0x0100000000000000; // size //0x80841e0000000000;
206  memcpy((void*)&buff[packetSz], (void*)&addr, 8);
207  packetSz += 8;
208  addr = 0x0400000000000000; // payload is 4 bytes
209  memcpy((void*)&buff[packetSz], (void*)&addr, 8);
210  packetSz += 8;
211  memcpy((void*)&buff[packetSz], (void*)&val, 4);
212  packetSz += 4;
213  {
214  int sz = 1; // 2000000/179/2 + 1; // /2 when 32-bit change, get from read in
215  // TYPE 1
216  std::cout << "sw: Line " << __LINE__ << ":::"
217  << "Number of packets expecting: " << sz << std::endl;
218 
219  unsigned long long qwords = 0;
220  if((numbytes =
221  sendto(sockfd, buff, packetSz, 0, p->ai_addr, p->ai_addrlen)) == -1)
222  {
223  perror("sw: sendto");
224  exit(1);
225  }
226 
227  // read data packets
228  // ///////////////////////////////////////////////////////////
229 
230  for(int i = 0; i < sz; ++i)
231  {
232  if(debug)
233  std::cout << "sw: Line " << __LINE__ << ":::"
234  << "Received " << qwords
235  << " qwords. Waiting for data packet: " << i << " of " << sz
236  << std::endl;
237 
238  // read response
239  // ///////////////////////////////////////////////////////////
240  if((numbytes = recvfrom(sockfd,
241  buff,
242  MAXBUFLEN - 1,
243  0,
244  (struct sockaddr*)&their_addr,
245  &addr_len)) == -1)
246  {
247  perror("recvfrom");
248  exit(1);
249  }
250  qwords += (numbytes - 40) / 8;
251 
252  continue;
253  printf("sw: got read response from %s\n",
254  inet_ntop(their_addr.ss_family,
255  get_in_addr((struct sockaddr*)&their_addr),
256  s,
257  sizeof s));
258  printf("sw: packet is %d bytes long\n", numbytes);
259  printf("recv packet contents: ");
260 
261  for(int i = 0; i < numbytes; ++i)
262  {
263  printf("%2.2X", (unsigned char)buff[i]);
264  if(i % 8 == 7)
265  printf("\n");
266  }
267  printf("\n");
268 
269  memcpy((void*)&val, (void*)&buff[TX_DATA_OFFSET], 8);
270  std::cout << "sw: Line " << __LINE__ << ":::"
271  << "Value read: " << val << std::endl;
272  }
273  __COUT__ << "Got all " << sz << " packet(s)." << __E__;
274  }
275 
276  break;
277  case 2:
278  // burst data read test
279 
280  // set socket huge
281  {
282  unsigned int defaultSocketReceiveSize_ = 0x10000; // in bytes
283  unsigned int socketReceiveBufferSize = 1 << 26; // in bytes
284 
285  __COUT__ << "Setting socket receive buffer size = " << socketReceiveBufferSize
286  << " 0x" << std::hex << socketReceiveBufferSize << std::dec << __E__;
287  if(setsockopt(sockfd,
288  SOL_SOCKET,
289  SO_RCVBUF,
290  (char*)&socketReceiveBufferSize,
291  sizeof(socketReceiveBufferSize)) < 0)
292  {
293  __COUT__ << "Failed to set socket receive size to "
294  << socketReceiveBufferSize
295  << ". Attempting to revert to default." << std::endl;
296 
297  socketReceiveBufferSize = defaultSocketReceiveSize_;
298 
299  __COUT__ << "Setting socket receive buffer size = "
300  << socketReceiveBufferSize << " 0x" << std::hex
301  << socketReceiveBufferSize << std::dec << __E__;
302  if(setsockopt(sockfd,
303  SOL_SOCKET,
304  SO_RCVBUF,
305  (char*)&socketReceiveBufferSize,
306  sizeof(socketReceiveBufferSize)) < 0)
307  {
308  __COUT__ << "Failed to set socket receive size to "
309  << socketReceiveBufferSize
310  << ". Attempting to revert to default." << std::endl;
311  }
312  }
313  }
314  // Read of 2000000 16MB requst :
315  // 0004 000f 0100 0002
316  // 0000 0000 0000 0000
317  // 0000 0000 0000 0000
318  // 0000 0000 001e 8480
319  // 0000 0000 0000 0000
320  // Flipped byte order
321  // 0200 0001 0f00 0400
322  // 0000 0000 0000 0000
323  // 0000 0000 0000 0000
324  // 8084 1e00 0000 0000
325  // 0000 0000 0000 0000
326  // setup read packet ///////////////////////////////////////////////////////////
327 
328  packetSz = 0;
329  addr = 0x020000010f000400;
330  memcpy((void*)&buff[packetSz], (void*)&addr, 8);
331  packetSz += 8;
332  addr = 0x0000000000000000;
333  memcpy((void*)&buff[packetSz], (void*)&addr, 8);
334  packetSz += 8;
335  addr = 0x0000000000000000;
336  memcpy((void*)&buff[packetSz], (void*)&addr, 8);
337  packetSz += 8;
338  addr = 0x80841e0000000000;
339  memcpy((void*)&buff[packetSz], (void*)&addr, 8);
340  packetSz += 8;
341  addr = 0x0000000000000000;
342  memcpy((void*)&buff[packetSz], (void*)&addr, 8);
343  packetSz += 8;
344  {
345  int sz =
346  2000000 / 179 / 2 + 1; // /2 when 32-bit change, get from read in TYPE 1
347  std::cout << "sw: Line " << __LINE__ << ":::"
348  << "Number of packets expecting: " << sz << std::endl;
349 
350  unsigned long long qwords = 0;
351  if((numbytes =
352  sendto(sockfd, buff, packetSz, 0, p->ai_addr, p->ai_addrlen)) == -1)
353  {
354  perror("sw: sendto");
355  exit(1);
356  }
357  // printf("sw: sent %d bytes to %s\n", numbytes, argv[1]);
358 
359  // read data packets
360  // ///////////////////////////////////////////////////////////
361 
362  for(int i = 0; i < sz; ++i)
363  {
364  if(debug)
365  std::cout << "sw: Line " << __LINE__ << ":::"
366  << "Received " << qwords
367  << " qwords. Waiting for data packet: " << i << " of " << sz
368  << std::endl;
369 
370  // read response
371  // ///////////////////////////////////////////////////////////
372  if((numbytes = recvfrom(sockfd,
373  buff,
374  MAXBUFLEN - 1,
375  0,
376  (struct sockaddr*)&their_addr,
377  &addr_len)) == -1)
378  {
379  perror("recvfrom");
380  exit(1);
381  }
382  qwords += (numbytes - 40) / 8;
383 
384  continue;
385  printf("sw: got read response from %s\n",
386  inet_ntop(their_addr.ss_family,
387  get_in_addr((struct sockaddr*)&their_addr),
388  s,
389  sizeof s));
390  printf("sw: packet is %d bytes long\n", numbytes);
391  printf("recv packet contents: ");
392 
393  for(int i = 0; i < numbytes; ++i)
394  {
395  printf("%2.2X", (unsigned char)buff[i]);
396  if(i % 8 == 7)
397  printf("\n");
398  }
399  printf("\n");
400 
401  memcpy((void*)&val, (void*)&buff[TX_DATA_OFFSET], 8);
402  std::cout << "sw: Line " << __LINE__ << ":::"
403  << "Value read: " << val << std::endl;
404  }
405  __COUT__ << "Got all " << sz << " packet(s)." << __E__;
406  }
407 
408  break;
409  default:
410  std::cout << "sw: Line " << __LINE__ << ":::"
411  << "INVALID Type of Test: " << type << std::endl;
412  }
413 
414  close(sockfd);
415 
416  return 0;
417 }