38 from tc_utils
import *
41 gEchoRxPath =
'./echoRx.dat'
42 gEchoTxPath =
'./echoTx.dat'
44 def tcp_tx(sock, message, count, verbose=False):
46 :param sock, the socket to send to.
47 :param message, the random string to sent.
48 :param count, the number of segments to send.
49 :param verbose, enables verbosity.
52 print(
"The following message of %d bytes will be sent out %d times:\n Message=%s\n" %
53 (len(message), count, message.decode(
'ascii')))
56 echoTxFile = open(gEchoTxPath,
'w')
60 echoTxFile.write(message.decode(
'ascii'))
65 startTime = datetime.datetime.now()
72 endTime = datetime.datetime.now()
73 elapseTime = endTime - startTime;
74 bandwidth = len(message) * 8 * count * 1.0 / (elapseTime.total_seconds() * 1024 * 1024)
75 print(
"##################################################")
76 print(
"#### TCP TX DONE with bandwidth = %6.1f Mb/s ####" % bandwidth)
77 print(
"##################################################")
89 def tcp_rx(sock, message, count, verbose):
91 :param sock, the socket to receive from.
92 :param message, the expected string message to be received.
93 :param count, the number of segment to receive.
94 :param verbose, enables verbosity.
98 echoRxFile = open(gEchoRxPath,
'w')
103 expectedBytes = count*len(message)
104 startTime = datetime.datetime.now()
105 while rxBytes < expectedBytes:
107 data = sock.recv(expectedBytes - rxBytes)
110 echoRxFile.write(data.decode(
'ascii'))
111 except socket.error
as exc:
112 print(
"[EXCEPTION] Socket error while receiving :: %s" % exc)
115 print(
"Loop=%d | RxBytes=%d" % (loop, rxBytes))
117 endTime = datetime.datetime.now()
118 elapseTime = endTime - startTime
119 bandwidth = len(message) * 8 * count * 1.0 / (elapseTime.total_seconds() * 1024 * 1024)
120 print(
"##################################################")
121 print(
"#### TCP RX DONE with bandwidth = %6.1f Mb/s ####" % bandwidth)
122 print(
"##################################################")
130 """Check and wait until the a socket pair can be reused.
131 [INFO] When a client or a server initiates an active close, then the same destination socket
132 (i.e. the same IP address / TCP port number) cannot be re-used immediately because
133 of security issues. Therefore, a closed connection must linger in a 'TIME_WAIT' or
134 'FIN_WAIT' state for as long as 2xMSL (Maximum Segment Lifetime), which corresponds
135 to twice the time a TCP segment might exist in the internet system. The MSL is
136 arbitrarily defined to be 2 minutes long.
137 :param ipFpga: the IP address of FPGA.
138 :param portFpga: the TCP port of the FPGA.
143 cmdStr =
"netstat | grep \'" +
str(ipFpga) +
":" +
str(portFpga) +
"\' | grep \'TIME_WAIT\|FIN_WAIT\' "
145 rc = os.system(cmdStr)
147 print(
"[INFO] Cannot reuse this socket as long as it is in the \'TIME_WAIT\' or \'FIN_WAIT\' state.")
148 print(
" Let's sleep for 5 sec...")
154 """TCP Tx-Rx Single-Thread Loop.
155 :param sock The socket to send/receive to/from.
156 :param message The message string to sent.
157 :param count The number of segments send.
158 :param verbose Enables verbosity.
161 print(
"[INFO] The following message of %d bytes will be sent out %d times:\n Message=%s\n" %
162 (len(message), count, message.decode(
'ascii')))
171 for i
in range(count):
172 txStream = txStream + message.decode(
'ascii')
174 startTime = datetime.datetime.now()
176 while rxByteCnt < (count * len(message)):
177 if txMssgCnt < count:
181 tcpSock.sendall(message)
189 data = tcpSock.recv(len(message))
190 rxByteCnt += len(data)
193 print(
"%d:%s" % (rxMssgCnt, data.decode(
'ascii')))
200 if e.errno != errno.EAGAIN
and e.errno != errno.EWOULDBLOCK:
201 print(
'[ERROR] Socket reading error: {}'.format(
str(e)))
205 except socket.error
as exc:
207 print(
"[EXCEPTION] Socket error while receiving :: %s" % exc)
211 rxStream = rxStream + data.decode(
'ascii')
213 endTime = datetime.datetime.now()
219 if rxStream != txStream:
220 print(
" KO | Received stream = %s" % data.decode(
'ascii'))
221 print(
" | Expected stream = %s" % rxStream)
224 print(
" OK | Received %d bytes in %d messages." % (rxByteCnt, rxMssgCnt))
226 elapseTime = endTime - startTime;
227 bandwidth = len(message) * 8 * count * 1.0 / (elapseTime.total_seconds() * 1024 * 1024)
228 print(
"[INFO] Transferred a total of %d bytes." % rxByteCnt)
229 print(
"#####################################################")
230 print(
"#### TCP Tx/Rx DONE with bandwidth = %6.1f Mb/s ####" % bandwidth)
231 print(
"#####################################################")
235 """TCP Tx-Rx Single-Thread Ramp.
236 :param sock The socket to send/receive to/from.
237 :param message The message string to sent.
238 :param count The number of segments to send.
239 :param verbose Enables verbosity.
242 print(
"[INFO] The following message of %d bytes will be sent out incrementally %d times:\n Message=%s\n" %
243 (len(message), count, message.decode(
'ascii')))
247 startTime = datetime.datetime.now()
250 while i <= len(message):
251 subMsg = message[0:i]
255 tcpSock.sendall(subMsg)
261 data = tcpSock.recv(len(subMsg))
262 rxByteCnt += len(data)
265 print(
"Loop=%d | RxBytes=%d" % (loop, len(data)))
267 print(
"Loop=%d | RxBytes=%d" % (loop, len(data)))
268 print(
" KO | Received Message=%s" % data.decode(
'ascii'))
269 print(
" | Expecting Message=%s" % subMsg)
276 if e.errno != errno.EAGAIN
and e.errno != errno.EWOULDBLOCK:
277 print(
'[ERROR] Socket reading error: {}'.format(
str(e)))
281 except socket.error
as exc:
283 print(
"[EXCEPTION] Socket error while receiving :: %s" % exc)
289 endTime = datetime.datetime.now()
290 elapseTime = endTime - startTime
291 bandwidth = (rxByteCnt * 8 * count * 1.0) / (elapseTime.total_seconds() * 1024 * 1024)
292 megaBytes = (rxByteCnt * 1.0) / (1024 * 1024 * 1.0)
293 print(
"[INFO] Transferred a total of %.1f MB." % megaBytes)
294 print(
"#####################################################")
295 print(
"#### TCP Tx/Rx DONE with bandwidth = %6.1f Mb/s ####" % bandwidth)
296 print(
"#####################################################")
309 parser = argparse.ArgumentParser(description=
'A script to send/receive TCP data to/from an FPGA module.')
310 parser.add_argument(
'-fi',
'--fpga_ipv4', type=str, default=
'',
311 help=
'The destination IPv4 address of the FPGA (a.k.a image_ip / e.g. 10.12.200.163)')
312 parser.add_argument(
'-fp',
'--fpga_port', type=int, default=8803,
313 help=
'The TCP destination port of the FPGA (default is 8803)')
314 parser.add_argument(
'-ii',
'--inst_id', type=int, default=0,
315 help=
'The instance ID assigned by the cloudFPGA Resource Manager (range is 1-32)')
316 parser.add_argument(
'-lc',
'--loop_count', type=int, default=10,
317 help=
'The number of times to run run the test (default is 10)')
318 parser.add_argument(
'-mi',
'--mngr_ipv4', type=str, default=
'10.12.0.132',
319 help=
'The IP address of the cloudFPGA Resource Manager (default is 10.12.0.132)')
320 parser.add_argument(
'-mp',
'--mngr_port', type=int, default=8080,
321 help=
'The TCP port of the cloudFPGA Resource Manager (default is 8080)')
322 parser.add_argument(
'-mt',
'--multi_threading', action=
"store_true",
323 help=
'Enable multi_threading')
324 parser.add_argument(
'-sd',
'--seed', type=int, default=-1,
325 help=
'The initial number to seed the pseudo-random number generator.')
326 parser.add_argument(
'-sz',
'--size', type=int, default=-1,
327 help=
'The size of the segment to generate.')
328 parser.add_argument(
'-un',
'--user_name', type=str, default=
'',
329 help=
'A user name as used to log in ZYC2 (.e.g \'fab\')')
330 parser.add_argument(
'-up',
'--user_passwd', type=str, default=
'',
331 help=
'The ZYC2 password attached to the user name')
332 parser.add_argument(
'-v',
'--verbose', action=
"store_true",
333 help=
'Enable verbosity')
335 args = parser.parse_args()
337 if args.user_name ==
'' or args.user_passwd ==
'':
338 print(
"\nWARNING: You must provide a ZYC2 user name and the corresponding password for this script to execute.\n")
368 restartApp(instId, ipResMngr, portResMngr, args.user_name, args.user_passwd)
377 fpgaAssociation = (
str(ipFpga), tcpDP)
388 tcpSP = tcpDP + 49152
389 hostAssociation = (ipSaStr, tcpSP)
399 tcpSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
400 except Exception
as exc:
401 print(
"[EXCEPTION] %s" % exc)
406 tcpSock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
407 tcpSock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY,
True)
415 tcpSock.bind(hostAssociation)
416 print(
'Binding the socket address of the HOST to {%s, %d}' % hostAssociation)
417 except Exception
as exc:
418 print(
"[EXCEPTION] %s" % exc)
424 tcpSock.connect(fpgaAssociation)
425 except Exception
as exc:
426 print(
"[EXCEPTION] %s" % exc)
429 print(
'\nSuccessful connection with socket address of FPGA at {%s, %d} \n' % fpgaAssociation)
433 print(
"[INFO] Testcase `%s` is run with:" % (os.path.basename(__file__)))
436 seed = random.randint(0, 100000)
438 print(
"\t\t seed = %d" % seed)
442 size = random.randint(1, ZYC2_MSS)
443 elif size > ZYC2_MSS:
445 print(
"[ERROR] This test-case expects the transfer of segment which are less or equal to MSS (.i.e %d bytes).\n" % ZYC2_MSS)
447 print(
"\t\t size = %d" % size)
449 count = args.loop_count
450 print(
"\t\t loop = %d" % count)
457 verbose = args.verbose
459 print(
"[INFO] This testcase is sending traffic from HOST-to-FPGA and back from FPGA-to-HOST.")
460 if args.multi_threading:
461 print(
"[INFO] This run is executed in multi-threading mode.\n")
464 tx_thread = threading.Thread(target=tcp_tx, args=(tcpSock, message, count, args.verbose))
465 rx_thread = threading.Thread(target=tcp_rx, args=(tcpSock, message, count, args.verbose))
476 result = filecmp.cmp(gEchoTxPath, gEchoRxPath, shallow=
False)
478 print(
"\n[ERROR] Rx file \'%s\' differs from Tx file \'%s\'.\n" % (gEchoRxPath, gEchoTxPath))
481 os.remove(gEchoRxPath)
482 os.remove(gEchoTxPath)
484 print(
"[INFO] The run is executed in single-threading mode.\n")
487 tcpSock.setblocking(
False)
488 tcpSock.settimeout(5)
def tcp_txrx_loop(sock, message, count, verbose=False)
def tcp_rx(sock, message, count, verbose)
def tcp_tx(sock, message, count, verbose=False)
def tcp_txrx_ramp(sock, message, count, verbose=False)
def waitUntilSocketPairCanBeReused(ipFpga, portFpga)
def restartApp(instId, ipResMngr, portResMngr, user_name, user_passwd)
def getResourceManagerIpv4(args)
def getResourceManagerPort(args)