ICP  1
Qxtrm_driver.cpp
Go to the documentation of this file.
1 // Qxtrm_driver.cpp : Defines the exported functions for the DLL application.
2 //
3 
4 #include "stdafx.h"
5 
6 class WinsockException : public std::runtime_error
7 {
8 public:
9  explicit WinsockException(const std::string& message) : std::runtime_error(win32_message(message, WSAGetLastError())) { }
10  explicit WinsockException(const std::string& message, DWORD code) : std::runtime_error(win32_message(message, code)) { }
11 private:
12  static std::string win32_message(const std::string& message, DWORD code)
13  {
14  std::string s(message);
15  s.append(": ");
16  LPTSTR errMsg;
17  FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
18  | FORMAT_MESSAGE_FROM_SYSTEM
19  | FORMAT_MESSAGE_IGNORE_INSERTS,
20  NULL,
21  code,
22  MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
23  (LPTSTR) &errMsg,
24  0,
25  NULL);
26  s.append(errMsg);
27  LocalFree((LPVOID)errMsg);
28  return s;
29  }
30 };
31 
32 #include "qxtrm.h"
33 #include "Qxtrm_driver.h"
34 
35 #include "Poco/String.h"
36 #include "Poco/Environment.h"
37 #include "Poco/Format.h"
38 
39 Qxtrm_channel::Qxtrm_channel(Poco::SharedPtr<Quixtream> qx, const std::string& chan_name) : ISIS::Base("Qxtrm_channel"), m_qx(qx), m_chan_name(chan_name), m_chan_id(INVALID_QXTRM_CHANNEL)
40 {
41  setLoggerName("Qxtrm_channel");
42  LOGSTR_INFORMATION("Creating channel \"" << chan_name << "\"");
43  m_chan_id = qx->GetChannel(const_cast<char*>(m_chan_name.c_str()));
45  {
46  throw qxtrmException(std::string("Qxtrm_channel: error mapping channel ") + m_chan_name);
47  }
48 }
49 
51 {
52 }
53 
54 void Qxtrm_channel::RDMARead(void* buffer, unsigned int len, unsigned int remote_address)
55 {
56  int timeout = 5 * 1000; /* QXTRM_WAIT_FOREVER */
57  LOGSTR_INFORMATION("RDMARead channel \"" << m_chan_name << "\" address " << std::hex << "0x" << remote_address << std::dec << " count " << len);
58  qxtrmStatus status = m_qx->RDMARead(m_chan_id, static_cast<char*>(buffer), len, remote_address, qxtrmTransferSync, timeout);
59  if (qxtrmStatusOK != status)
60  {
61  throw qxtrmException(status, "Qxtrm_channel::RDMARead failed", m_qx, m_chan_id);
62  }
63 }
64 
65 void Qxtrm_channel::RDMAWrite(const void* buffer, unsigned int len, unsigned int remote_address)
66 {
67  int timeout = 5 * 1000; /* QXTRM_WAIT_FOREVER */
68  LOGSTR_INFORMATION("RDMAWrite channel \"" << m_chan_name << "\" address " << std::hex << "0x" << remote_address << std::dec << " count " << len);
69  qxtrmStatus status = m_qx->RDMAWrite(m_chan_id, static_cast<char*>(const_cast<void*>(buffer)), len, remote_address, qxtrmTransferSync, timeout);
70  if (qxtrmStatusOK != status)
71  {
72  throw qxtrmException(status, "Qxtrm_channel::RDMAWrite failed", m_qx, m_chan_id);
73  }
74 }
75 
76 
77 std::string Qxtrm_channel::channelStatus() const
78 {
79  qxtrmChannelStatus chan_stat;
80  qxtrmStatus status = (const_cast<Poco::SharedPtr<Quixtream>&>(m_qx))->GetTransferStats(m_chan_id, qxtrmTransStatsCmdLastStatus, &chan_stat);
81  if (qxtrmStatusOK == status)
82  {
84  }
85  else
86  {
87 // throw qxtrmException(status, "Qxtrm_channel::channelStatus failed");
88  return Qxtrm_driver::qxtrmStatusMessage(status);
89  }
90 }
91 
92 void Qxtrm_channel::channelStatsHelper(int chan, qxtrmTransStatsCmd cmd, const char* mess, std::ostream& os) const
93 {
94  unsigned int n = 0;
95  qxtrmStatus status = (const_cast<Poco::SharedPtr<Quixtream>&>(m_qx))->GetTransferStats(chan, cmd, &n);
96  if (qxtrmStatusOK == status)
97  {
98  os << mess << ": " << n << "\n";
99  }
100  else
101  {
102  os << mess << ": unknown (" << Qxtrm_driver::qxtrmStatusMessage(status) << ")\n";
103  }
104 }
105 
106 std::ostream& Qxtrm_channel::channelTransferStats(std::ostream& os) const
107 {
108  os << "--- Transfer stats for channel \"" << m_chan_name << "\" (id=" << m_chan_id << ") ---\n";
109  channelStatsHelper(m_chan_id, qxtrmTransStatsCmdLastBytesTrans, "Bytes transferred for last completed transfer", os);
110  channelStatsHelper(m_chan_id, qxtrmTransStatsCmdTotalBytesTrans, "Bytes transferred for all cumulative transfers", os);
111  channelStatsHelper(m_chan_id, qxtrmTransStatsCmdLastDataErrors, "Data frame errors for last completed transfer", os);
112  channelStatsHelper(m_chan_id, qxtrmTransStatsCmdTotalDataErrors, "Data frame errors for all cumulative transfers", os);
113  channelStatsHelper(m_chan_id, qxtrmTransStatsCmdLastAckErrors, "Acknowledgement frame errors for last completed transfer", os);
114  channelStatsHelper(m_chan_id, qxtrmTransStatsCmdTotalAckErrors, "Acknowledgement frame errors for all cumulative transfers", os);
115  return os;
116 }
117 
118 std::ostream& Qxtrm_channel::channelStatus(std::ostream& os) const
119 {
120  os << "Channel \"" << m_chan_name << "\" (id=" << m_chan_id << "): " << channelStatus();
121  return os;
122 }
123 
124 
125 void Qxtrm_channel::blockSend(const void* buffer, unsigned int len)
126 {
127  LOGSTR_INFORMATION("blockSend channel \"" << m_chan_name << "\" count " << len);
128  int timeout = 5 * 1000; /* QXTRM_WAIT_FOREVER */
129  qxtrmStatus status = m_qx->BlockSend(m_chan_id, static_cast<char*>(const_cast<void*>(buffer)), len, qxtrmTransferSync, timeout);
130  if (status != qxtrmStatusOK)
131  {
132  throw qxtrmException(status, "Qxtrm_channel::blockSend failed", m_qx, m_chan_id);
133  }
134 }
135 
136 void Qxtrm_channel::blockReceive(void* buffer, unsigned int len)
137 {
138  LOGSTR_INFORMATION("blockReceive channel \"" << m_chan_name << "\" count " << len);
139  int timeout = 5 * 1000; /* QXTRM_WAIT_FOREVER */
140  qxtrmStatus status = m_qx->BlockRecv(m_chan_id, static_cast<char*>(buffer), len, qxtrmTransferSync, timeout);
141  if (status != qxtrmStatusOK)
142  {
143  throw qxtrmException(status, "Qxtrm_channel::blockReceive failed", m_qx, m_chan_id);
144  }
145 }
146 
147 
148 void Qxtrm_channel::streamSend(const void* buffer, unsigned int len)
149 {
150  int timeout = 5 * 1000; /* QXTRM_WAIT_FOREVER */
151  char* pDataBuffer = NULL;
152  LOGSTR_INFORMATION("streamSend channel \"" << m_chan_name << "\" count " << len);
153  qxtrmStatus status = m_qx->StreamSend(m_chan_id, &pDataBuffer, timeout); // acquire segment buffer
154  if (status != qxtrmStatusOK)
155  {
156  throw qxtrmException(status, "Qxtrm_channel::streamSend(1) failed", m_qx, m_chan_id);
157  }
158  memcpy(pDataBuffer, buffer, len);
159  status = m_qx->StreamSend(m_chan_id, len, true); // send data and signal end of segment
160  if (status != qxtrmStatusOK)
161  {
162  throw qxtrmException(status, "Qxtrm_channel::streamSend(2) failed", m_qx, m_chan_id);
163  }
164 }
165 
168 {
169  int timeout = QXTRM_WAIT_FOREVER;
170  char *pData = NULL;
171  unsigned int newDataAvail = 0;
172  unsigned int oldDataAvail = 0;
173  bool endOfSeg = false;
174  LOGSTR_INFORMATION("streamReceive channel \"" << m_chan_name);
175  qxtrmStatus status;
176  while(!endOfSeg)
177  {
178  status = m_qx->StreamRecv(m_chan_id, &pData, &newDataAvail, &endOfSeg, qxtrmTransferAsync, timeout);
179  if (status != qxtrmStatusOK && status != qxtrmStatusNoStreamDataWaiting)
180  {
181  throw qxtrmException(status, "Qxtrm_channel::streamReceive(StreamRecv) failed", m_qx, m_chan_id);
182  }
183  if (newDataAvail > oldDataAvail)
184  {
185  outputStreamDataCallback(pData, newDataAvail, endOfSeg);
186  oldDataAvail = newDataAvail;
187  }
188  else
189  {
190  std::cerr << "Qxtrm_channel::streamReceive(StreamRecv) waiting for more data, sofar " << oldDataAvail << std::endl;
191  Sleep(1000);
192  }
193  }
194  status = m_qx->TransferSync(m_chan_id);
195  if (status != qxtrmStatusOK)
196  {
197  throw qxtrmException(status, "Qxtrm_channel::streamReceive(TransferSync) failed", m_qx, m_chan_id);
198  }
199  status = m_qx->StreamReleaseSegment(m_chan_id);
200  if (status != qxtrmStatusOK)
201  {
202 // std::cerr << "Qxtrm_channel::streamReceive(StreamReleaseSegment) failed: " << Qxtrm_driver::qxtrmStatusMessage(status, m_qx, m_chan_id) << std::endl;
203  throw qxtrmException(status, "Qxtrm_channel::streamReceive(StreamReleaseSegment) failed", m_qx, m_chan_id);
204  }
205  oldDataAvail = 0;
206 }
207 
208 
210 void Qxtrm_channel::streamReceive(qxtrmStreamCallbackFunc pCallback, unsigned int interval)
211 {
212  int timeout = 5 * 1000; /* QXTRM_WAIT_FOREVER */
213  LOGSTR_INFORMATION("streamReceive channel \"" << m_chan_name << "\" interval " << interval);
214  qxtrmStatus status;
215  while( (status = m_qx->StreamRecv(m_chan_id, pCallback, interval, qxtrmTransferSync, timeout)) == qxtrmStatusTransferTimeout )
216  {
217  std::cerr << "Qxtrm_channel::streamReceive(StreamRecv) timeout, retrying" << std::endl;
218  }
219  if (status != qxtrmStatusOK)
220  {
221  throw qxtrmException(status, "Qxtrm_channel::streamReceive(StreamRecv) failed", m_qx, m_chan_id);
222  }
223  std::cerr << "releasing stream" << std::endl;
224  status = m_qx->StreamReleaseSegment(m_chan_id);
225  if (status != qxtrmStatusOK)
226  {
227 // std::cerr << "Qxtrm_channel::streamReceive(StreamReleaseSegment) failed: " << Qxtrm_driver::qxtrmStatusMessage(status, m_qx, m_chan_id) << std::endl;
228  throw qxtrmException(status, "Qxtrm_channel::streamReceive(StreamReleaseSegment) failed", m_qx, m_chan_id);
229  }
230 }
231 
232 void Qxtrm_channel::outputStreamDataCallback(char* pDataBuffer, unsigned int callbackSize, bool segmentEnd)
233 {
234  static int oldData = 0; // amount of data read so far
235  char* pNewData;
236  int newData, word_size = m_outstream_word_size;
237  union
238  {
239  unsigned int u;
240  char c[4];
241  } word;
242  FILE* outstream = (m_outstream != NULL ? m_outstream : stdout);
243  pNewData = pDataBuffer + oldData;
244  newData = callbackSize - oldData;
245  if (!segmentEnd)
246  {
247  newData = word_size * (newData / word_size); // if we are not segment end, round to a multiple of word size
248  }
249  std::cerr << "outputStreamDataCallback: callbackSize=" << callbackSize << " oldData=" << oldData << " newData=" << newData << " segmentEnd=" << segmentEnd << std::endl;
250  word.u = 0;
251  for(int i = 0; i < newData; ++i)
252  {
253  word.c[i%word_size] = pNewData[i]; // little endian specific filing of union
254  ++oldData;
255  if ( (i+1) % word_size == 0 )
256  {
257  fprintf(outstream, "0x%0*x%s", 2*word_size, word.u, ((oldData % (word_size * m_outstream_columns) == 0) ? "\n" : " ")); // words per line
258  }
259  }
260  if (segmentEnd)
261  {
262  std::cerr << "outputStreamDataCallback: finished segment total size=" << callbackSize << std::endl;
263  if (oldData != callbackSize)
264  {
265  std::cerr << "outputStreamDataCallback: ERROR: callbackSize=" << callbackSize << " oldData=" << oldData << std::endl;
266  }
267  oldData = 0;
268  fprintf(outstream, "\n");
269  }
270 }
271 
272 
273 void Qxtrm_channel::RDMARegisterMemory(void* local_address, unsigned int len, unsigned int rdmaAddr)
274 {
275  qxtrmStatus status = m_qx->RDMARegisterMemory(m_chan_id, static_cast<char*>(local_address), len, rdmaAddr);
276  if (qxtrmStatusOK != status)
277  {
278  throw qxtrmException(status, "Qxtrm_channel::RDMARegisterMemory failed", m_qx, m_chan_id);
279  }
280 }
281 
282 void Qxtrm_channel::RDMAUnregisterMemory(unsigned int rdmaAddr)
283 {
284  qxtrmStatus status = m_qx->RDMAUnregisterMemory(m_chan_id, rdmaAddr);
285  if (qxtrmStatusOK != status)
286  {
287  throw qxtrmException(status, "Qxtrm_channel::RDMAUnregisterMemory failed", m_qx, m_chan_id);
288  }
289 }
290 
291 std::ostream& Qxtrm_driver::channelStatus(std::ostream& os) const
292 {
293  for(chan_map_t::const_iterator it = m_chans.begin(); it != m_chans.end(); ++it)
294  {
295  it->second->channelStatus(os);
296  }
297  return os;
298 }
299 
300 std::ostream& Qxtrm_driver::channelTransferStats(std::ostream& os) const
301 {
302  for(chan_map_t::const_iterator it = m_chans.begin(); it != m_chans.end(); ++it)
303  {
304  it->second->channelTransferStats(os);
305  }
306  return os;
307 }
308 
309 void Qxtrm_driver::getNetworkDetails(const std::string& ip_prefix, std::string& ip_addr, std::string& mac_addr)
310 {
311  ULONG outBufLen = 0;
312  DWORD dwRetVal = 0;
313  char mac_buffer[32];
314  ip_addr = mac_addr = "";
315  IP_ADAPTER_INFO* pAdapterInfos = (IP_ADAPTER_INFO*) malloc(sizeof(IP_ADAPTER_INFO));
316 
317  // retry up to 5 times, to get the adapter infos needed
318  for( int i = 0; i < 5 && (dwRetVal == ERROR_BUFFER_OVERFLOW || dwRetVal == NO_ERROR); ++i )
319  {
320  dwRetVal = GetAdaptersInfo(pAdapterInfos, &outBufLen);
321  if( dwRetVal == NO_ERROR )
322  {
323  break;
324  }
325  else if( dwRetVal == ERROR_BUFFER_OVERFLOW )
326  {
327  free(pAdapterInfos);
328  pAdapterInfos = (IP_ADAPTER_INFO*) malloc(outBufLen);
329  }
330  else
331  {
332  pAdapterInfos = 0;
333  break;
334  }
335  }
336  if( dwRetVal == NO_ERROR )
337  {
338  IP_ADAPTER_INFO* pAdapterInfo = pAdapterInfos;
339  while( pAdapterInfo )
340  {
341  IP_ADDR_STRING* pIpAddress = &(pAdapterInfo->IpAddressList);
342  while( pIpAddress != 0 )
343  {
344  if ( !strncmp(pIpAddress->IpAddress.String, ip_prefix.c_str(), ip_prefix.size()) )
345  {
346  ip_addr = pIpAddress->IpAddress.String;
347  sprintf(mac_buffer, "%02X-%02X-%02X-%02X-%02X-%02X", pAdapterInfo->Address[0], pAdapterInfo->Address[1], pAdapterInfo->Address[2],
348  pAdapterInfo->Address[3], pAdapterInfo->Address[4], pAdapterInfo->Address[5]);
349  mac_addr = mac_buffer;
350  }
351  pIpAddress = pIpAddress->Next;
352  }
353  pAdapterInfo = pAdapterInfo->Next;
354  }
355  }
356  free(pAdapterInfos);
357 }
358 
359 void Qxtrm_driver::loadConfigData(const std::string& config_file, int ethernet_id, bool do_remote_config, std::string& config_data)
360 {
361  std::stringstream config_stream;
362  std::string ip_prefix = "192.168.1."; // must end with a "."
363  std::string card_ip, card_mac;
364  std::fstream fs(config_file, std::ios::in);
365  config_stream << fs.rdbuf();
366  fs.close();
367  config_data = config_stream.str();
368  std::string ip_addr, mac_addr;
369  getNetworkDetails(ip_prefix, ip_addr, mac_addr);
370  if ( ip_addr.size() == 0 )
371  {
372  ip_prefix = "192.168.0."; // This is Kelvin's NDW834 machine
373  getNetworkDetails(ip_prefix, ip_addr, mac_addr);
374  }
375  if ( ip_addr.size() == 0 )
376  {
377  ip_prefix = "130.246.49.";
378  getNetworkDetails(ip_prefix, ip_addr, mac_addr);
379  }
380  switch(ethernet_id)
381  {
382  case 0:
383  card_ip = Poco::format("%s%d", ip_prefix, 1);
384  card_mac = "00-0A-35-00-00-00";
385  break;
386 
387  case 1:
388  card_ip = Poco::format("%s%d", ip_prefix, 2);
389  card_mac = "00-0A-35-00-00-02";
390  break;
391 
392  case 2:
393  card_ip = Poco::format("%s%d", ip_prefix, 3);
394  card_mac = "00-0A-35-00-00-03";
395  break;
396 
397  default:
398  throw(std::runtime_error("invalid card ethernet id"));
399  break;
400  }
401  struct sockaddr_in addr;
402  SOCKET sfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
403  if (sfd < 0)
404  {
405  throw WinsockException("socket");
406  }
407  memset(&addr, 0, sizeof(struct sockaddr_in));
408  addr.sin_family = AF_INET;
409  addr.sin_port = htons(0); // ask to be allocated a port
410  addr.sin_addr.S_un.S_addr = inet_addr(ip_addr.c_str());
411  if (::bind(sfd, (struct sockaddr*)&addr, sizeof(struct sockaddr_in)) < 0)
412  {
413  throw WinsockException("bind");
414  }
415  int namelen = sizeof(struct sockaddr_in);
416  if (getsockname(sfd, (struct sockaddr*)&addr, &namelen) < 0)
417  {
418  throw WinsockException("getsockname");
419  }
420  char port_string[10];
421  closesocket(sfd);
422 // sprintf(port_string, "0x%x", addr.sin_port);
423  sprintf(port_string, "0x%x", 0xfe02 + 8 * ethernet_id);
424  std::cerr << "Using HOST IP " << ip_addr << " Mac " << mac_addr << " Port " << port_string << std::endl;
425  LOGSTR_INFORMATION("Using HOST IP " << ip_addr << " Mac " << mac_addr << " Port " << port_string);
426  LOGSTR_INFORMATION("Using FPGA IP " << card_ip << " Mac " << card_mac);
427  Poco::replaceInPlace(config_data, "##HOST_IP##", ip_addr.c_str());
428  Poco::replaceInPlace(config_data, "##HOST_MAC##", mac_addr.c_str()); // e.g. "00-25-64-B5-92-21"
429  Poco::replaceInPlace(config_data, "##HOST_PORT_BASE##", port_string);
430  Poco::replaceInPlace(config_data, "##PACKET_SIZE##", "1452"); // 1452 on standard network, 7944 on jumbo frames network
431  Poco::replaceInPlace(config_data, "##DAE_CARD##", "DAE_CARD_FPGA");
432  Poco::replaceInPlace(config_data, "##DAE_CARD_IP##", card_ip.c_str());
433  Poco::replaceInPlace(config_data, "##DAE_CARD_MAC##", card_mac.c_str()); // e.g. "00-0A-35-00-00-00"
434  Poco::replaceInPlace(config_data, "##DAE_CARD_PORT_BASE##", "0xfe22");
435  Poco::replaceInPlace(config_data, "##ACK_TIMEOUT##", "1000"); // milliseconds
436  Poco::replaceInPlace(config_data, "##DATA_TIMEOUT##", "1000"); // milliseconds
437  Poco::replaceInPlace(config_data, "##ACK_MODE##", "on"); // On or Off
438  if (do_remote_config)
439  {
440  Poco::replaceInPlace(config_data, "##REMOTE_CONFIG##", "<RemoteConfig remoteinterface=\"Eth0\" remoteprocess=\"process1\" remotenode=\"host\"/>");
441  }
442  else
443  {
444  Poco::replaceInPlace(config_data, "##REMOTE_CONFIG##", "");
445  }
446  Poco::replaceInPlace(config_data, "##ACK_MODE##", "on"); // On or Off
447 }
448 
449 Poco::SharedPtr<Qxtrm_channel> Qxtrm_driver::createChannel(const std::string& chan_name)
450 {
451  Poco::SharedPtr<Qxtrm_channel> chan = new Qxtrm_channel(m_qx, chan_name);
452  m_chans[chan_name] = chan;
453  return chan;
454 }
455 
456 
460 std::string Qxtrm_driver::qxtrmStatusMessage(int qxtrm_status, Quixtream* qx, int chan)
461 {
462  std::string message;
463  switch(qxtrm_status)
464  {
465  case qxtrmStatusOK:
466  message = "The command completed successfully with no errors.";
467  break;
468 
469  case qxtrmStatusInvalidChannelHandle:
470  message = "The supplied channel handle is not valid. ";
471  break;
472 
473  case qxtrmStatusInvalidTransferForChannel:
474  message = "The requested transfer type is not supported by this channel instance. ";
475  break;
476 
477  case qxtrmStatusChannelTerminated:
478  message = "The channels transfer thread is not running. ";
479  break;
480 
481  case qxtrmStatusTransferInProgress:
482  message = "The channel instance already has a transfer in progress, or has an unsynced completed transfer. ";
483  break;
484 
485  case qxtrmStatusInvalidTransferArguments:
486  message = "The transfer arguments are invalid, i.e. the sizes may not be aligned, etc. ";
487  break;
488 
489  case qxtrmStatusTransferTimeout:
490  message = "The timeout period on this channel expired before the transfer commenced. ";
491  break;
492 
493  case qxtrmStatusTransferErrors:
494  message = "The last transfer on this channel completed with errors. Use GetTransferStats() to see the nature of the errors. ";
495  break;
496 
497  case qxtrmStatusTransferNotInProgress:
498  message = "The channel instance does not have an outstanding transfer which require syncing. ";
499  break;
500 
501  case qxtrmStatusNoStreamDataWaiting:
502  message = "There is no streaming data waiting to be received on the stream channel. Stream data must be available for an async call. ";
503  break;
504 
505  case qxtrmStatusNoStreamBuffersFree:
506  message = "No free Stream buffers available to write into. ";
507  break;
508 
509  case qxtrmStatusStreamNotInitialised:
510  message = "The Stream send has not been initialised yet. ";
511  break;
512 
513  case qxtrmStatusRDMARegionOverlap:
514  message = "The specified RDMA region overlaps with an existing region. ";
515  break;
516 
517  case qxtrmStatusTooManyRDMARegions:
518  message = "Too many RDMA memory regions already specified. ";
519  break;
520 
521  case qxtrmStatusError:
522  message = "General error. ";
523  break;
524 
525  default:
526  message = Poco::format("Unknown qxtrmStatus error code %d. ", qxtrm_status);
527  break;
528  }
529  if (NULL != qx && INVALID_QXTRM_CHANNEL != chan)
530  {
531  message += qxtrmChannelStatusMessage(qx, chan);
532  }
533  return message;
534 }
535 
536 std::string Qxtrm_driver::qxtrmChannelStatusMessage(Quixtream* qx, int chan)
537 {
538  qxtrmChannelStatus chan_stat;
539  qxtrmStatus status = qx->GetTransferStats(chan, qxtrmTransStatsCmdLastStatus, &chan_stat);
540  if (qxtrmStatusOK == status)
541  {
542  return "Channel status: " + qxtrmChannelStatusMessage(chan_stat);
543  }
544  else
545  {
546  return "GetTransferStats() failed: " + qxtrmStatusMessage(status);
547  }
548 }
549 
551 std::string Qxtrm_driver::qxtrmChannelStatusMessage(int qxtrm_channel_status)
552 {
553  std::string message;
554  switch(qxtrm_channel_status)
555  {
556  case qxtrmChanStatusOK:
557  message = "Transfer completed OK. ";
558  break;
559 
560  case qxtrmChanStatusInitialPSNMismatch:
561  message = "Transfer completed OK, but the initial packet sequence number was not what we expected. This may indicate a sync loss or a whole previous packet loss. ";
562  break;
563 
564  case qxtrmChanStatusTooMuchData:
565  message = "Transfer completed OK. Too much data received compared to the amount expected. ";
566  break;
567 
568  case qxtrmChanStatusTooLittleData:
569  message = "Transfer completed OK. Too little data received compared to the amount expected. ";
570  break;
571 
572  case qxtrmChanStatusLostDataPackets:
573  message = "Transfer failed. Packet seqnece numbers within the message where inconsistent. One or more packets where not received. ";
574  break;
575 
576  case qxtrmChanStatusLostACKPackets:
577  message = "Transfer failed. Packet seqnece numbers within the acknowledgment packets where inconsistent. One or more ACK packets where not received. ";
578  break;
579 
580  case qxtrmChanStatusACKRecvTimeout:
581  message = "Transfer failed. Acknowledgment packet not received before timeout. ";
582  break;
583 
584  case qxtrmChanStatusDataRecvTimeout:
585  message = "Transfer failed. Data packet not received before timeout. ";
586  break;
587 
588  case qxtrmChanStatusInvalidRDMAAddr:
589  message = "Transfer failed. The specified RDMA region was invalid. ";
590  break;
591 
592  case qxtrmChanStatusTransportFailure:
593  message = "Transfer failed. Send or receive command failed. ";
594  break;
595 
596  default:
597  message = Poco::format("Unknown qxtrmChannelStatus error code %d. ", qxtrm_channel_status);
598  break;
599  }
600  return message;
601 }
602 
603 Qxtrm_driver::Qxtrm_driver(const std::string& config_file, const std::string& node_name, int ethernet_id, int process_number, bool do_remote_config) : ISIS::Base("Qxtrm_driver"), m_qx(NULL)
604 {
605  setLoggerName("Qxtrm_driver");
606  LOGSTR_INFORMATION("Creating Qxtrm driver from \"" << config_file << "\" node \"" << node_name << "\" process \"process" << process_number << "\"");
607  int timeout = 30 * 1000; // in milliseconds, or QXTRM_WAIT_FOREVER
608  std::string config_data;
609  std::string process_name = Poco::format("process%d", process_number);
610  loadConfigData(config_file, ethernet_id, do_remote_config, config_data);
611  m_qx = new Quixtream(const_cast<char*>(node_name.c_str()), const_cast<char*>(process_name.c_str()),
612  const_cast<char*>(config_data.c_str()), false, timeout);
613 }
614 
616 {
617 }
618 
619 FILE* Qxtrm_channel::m_outstream = NULL;
622 
Poco::SharedPtr< Qxtrm_channel > createChannel(const std::string &chan_name)
chan_map_t m_chans
Definition: Qxtrm_driver.h:59
WinsockException(const std::string &message, DWORD code)
void RDMAUnregisterMemory(unsigned int rdmaAddr)
static FILE * m_outstream
Definition: Qxtrm_driver.h:48
std::string m_chan_name
Definition: Qxtrm_driver.h:28
void RDMARegisterMemory(void *local_address, unsigned int len, unsigned int rdmaAddr)
static std::string qxtrmChannelStatusMessage(int qxtrm_channel_status)
Poco::SharedPtr< Quixtream > m_qx
Definition: Qxtrm_driver.h:57
std::string channelStatus() const
static const int INVALID_QXTRM_CHANNEL
Definition: Qxtrm_driver.h:20
virtual ~Qxtrm_driver()
void blockSend(const void *buffer, unsigned int len)
std::ostream & channelTransferStats(std::ostream &os) const
static void getNetworkDetails(const std::string &ip_prefix, std::string &ip_addr, std::string &mac_addr)
void RDMAWrite(uint32_t value, unsigned int remote_address)
Definition: Qxtrm_driver.h:33
static std::string win32_message(const std::string &message, DWORD code)
Definition: icputils.h:74
std::ostream & channelTransferStats(std::ostream &os) const
void streamSend(const void *buffer, unsigned int len)
void channelStatsHelper(int chan, qxtrmTransStatsCmd cmd, const char *mess, std::ostream &oss) const
std::ostream & channelStatus(std::ostream &os) const
void loadConfigData(const std::string &config_file, int ethernet_id, bool do_remote_config, std::string &config_data)
#define LOGSTR_INFORMATION(__arg)
Definition: IsisBase.h:78
Poco::SharedPtr< Quixtream > m_qx
Definition: Qxtrm_driver.h:26
#define SOCKET
void RDMARead(uint32_t &value, unsigned int remote_address)
Definition: Qxtrm_driver.h:34
void streamReceive()
receives one segment
Qxtrm_driver(const std::string &config_file, const std::string &node_name, int ethernet_id, int process_number, bool do_remote_config)
#define closesocket
static std::string qxtrmStatusMessage(int qxtrm_status, Quixtream *qx=NULL, int chan=INVALID_QXTRM_CHANNEL)
static int m_outstream_word_size
Definition: Qxtrm_driver.h:49
void setLoggerName(const std::string &logger_name)
Definition: IsisBase.h:17
WinsockException(const std::string &message)
Definition: Qxtrm_driver.cpp:9
Exception class recording an error raised by a Quixtream API function.
Definition: Qxtrm_driver.h:75
static void outputStreamDataCallback(char *pDataBuffer, unsigned int callbackSize, bool segmentEnd)
static int m_outstream_columns
Definition: Qxtrm_driver.h:50
void blockReceive(void *buffer, unsigned int len)
virtual ~Qxtrm_channel()
Qxtrm_channel(Poco::SharedPtr< Quixtream > qx, const std::string &chan_name)