32 import netifaces
as ni
38 from tc_utils
import *
41 def tcp_rx_loop(clientSock, serverSock, size, ip_da, tcp_dp, count, verbose=False):
42 """TCP Rx Single-Thread Ramp.
43 Requests the FPGA to open a new active port and expects to receive 'count' segments
44 of 'size' bytes. Each segment is made of the following repetitive pattern
45 '48692066726f6d200x464d4b553630210a' which decodes into the string "Hi from FMKU60\n".
46 :param clientSock The socket to send to.
47 :param serverSock The socket to receive from.
48 :param size The size of the expected segment.
49 :param ip_da The destination address of the host.
50 :param tcp_dp The active destination port number that the FPGA is requested to open.
51 :param count The number of segments to receive.
52 :param verbose Enables verbosity.
55 print(
"[INFO] Requesting the FPGA to send %d segments of %d bytes on TCP port number %d." % (count, size, tcp_dp))
58 totalReceivedBytes = 0
62 clientSock.settimeout(5)
63 clientSock.setblocking(
False)
64 serverSock.settimeout(5)
65 serverSock.setblocking(
False)
70 reqMsgAsBytes = struct.pack(
">IHH", ip_da, tcp_dp, size)
72 print(
"[DEBUG] >>> reqMsgAsBytes = %s" % reqMsgAsBytes)
74 startTime = datetime.datetime.now()
79 clientSock.sendall(reqMsgAsBytes)
80 except socket.error
as exception:
82 print(
"[EXCEPTION] Socket error while transmitting :: %s" % exception)
90 while currRxByteCnt < size:
92 data = serverSock.recv(MTU)
98 if e.errno != errno.EAGAIN
and e.errno != errno.EWOULDBLOCK:
99 print(
'[ERROR] Socket reading error: {}'.format(
str(e)))
103 print(
"[DEBUG] So far we received %d bytes out of %d." % (currRxByteCnt, size))
105 except socket.error
as exc:
107 print(
"[EXCEPTION] Socket error while receiving :: %s" % exc)
110 currRxByteCnt += len(data)
112 print(
"[INFO] Loop=%d | RxBytes=%d | RxData=%s\n" % (loop, len(data), data))
116 totalReceivedBytes += currRxByteCnt;
118 endTime = datetime.datetime.now()
119 elapseTime = endTime - startTime
121 if totalReceivedBytes < 1000000:
122 print(
"[INFO] Received a total of %d bytes." % totalReceivedBytes)
123 elif totalReceivedBytes < 1000000000:
124 megaBytes = (totalReceivedBytes * 1.0) / (1024 * 1024 * 1.0)
125 print(
"[INFO] Received a total of %.1f MB." % megaBytes)
127 gigaBytes = (totalReceivedBytes * 1.0) / (1024 * 1024 * 1024 * 1.0)
128 print(
"[INFO] Transferred a total of %.1f GB." % gigaBytes)
130 bandwidth = (totalReceivedBytes * 8 * 1.0) / (elapseTime.total_seconds() * 1024 * 1024)
131 print(
"#####################################################")
133 print(
"#### TCP Rx DONE with bandwidth = %6.1f Mb/s ####" % bandwidth)
135 bandwidth = bandwidth / 1000
136 print(
"#### TCP Rx DONE with bandwidth = %2.1f Gb/s ####" % bandwidth)
137 if (totalReceivedBytes != (size * count)):
138 print(
"#### [WARNING] TCP data loss = %.1f%%" % (1 - (totalReceivedBytes) / (size * count)))
139 print(
"#####################################################")
151 parser = argparse.ArgumentParser(description=
'A script to receive TCP data from an FPGA module.')
152 parser.add_argument(
'-fi',
'--fpga_ipv4', type=str, default=
'',
153 help=
'The IPv4 address of the FPGA (a.k.a image_ip / e.g. 10.12.200.163)')
154 parser.add_argument(
'-ii',
'--inst_id', type=int, default=0,
155 help=
'The instance ID assigned by the cloudFPGA Resource Manager (e.g. 42)')
156 parser.add_argument(
'-lc',
'--loop_count', type=int, default=10,
157 help=
'The number of test runs (default is 10)')
158 parser.add_argument(
'-mi',
'--mngr_ipv4', type=str, default=
'10.12.0.132',
159 help=
'The IPv4 address of the cloudFPGA Resource Manager (default is 10.12.0.132)')
160 parser.add_argument(
'-mp',
'--mngr_port', type=int, default=8080,
161 help=
'The TCP port of the cloudFPGA Resource Manager (default is 8080)')
162 parser.add_argument(
'-sd',
'--seed', type=int, default=-1,
163 help=
'The initial number to seed the pseudorandom number generator.')
164 parser.add_argument(
'-sz',
'--size', type=int, default=-1,
165 help=
'The size of the datagram to receive.')
166 parser.add_argument(
'-un',
'--user_name', type=str, default=
'',
167 help=
'A user-name as used to log in ZYC2 (.e.g \'fab\')')
168 parser.add_argument(
'-up',
'--user_passwd', type=str, default=
'',
169 help=
'The ZYC2 password attached to the user-name')
170 parser.add_argument(
'-v',
'--verbose', action=
"store_true",
171 help=
'Enable verbosity')
173 args = parser.parse_args()
175 if args.user_name ==
'' or args.user_passwd ==
'':
176 print(
"\n[WARNING] You must provide a ZYC2 user name and the corresponding password for this script to execute.\n")
193 portFpgaServer = XMIT_MODE_LSN_PORT
201 restartApp(instId, ipResMngr, portResMngr, args.user_name, args.user_passwd)
209 fpgaServerAssociation = (
str(ipFpga), portFpgaServer)
214 tcpClientSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
215 except Exception
as exc:
216 print(
"[EXCEPTION] %s" % exc)
222 tcpClientSock.connect(fpgaServerAssociation)
223 print(
"[INFO] Connecting host client to FPGA server socket ", fpgaServerAssociation)
224 except Exception
as exc:
225 print(
"[EXCEPTION] %s" % exc)
228 print(
"[INFO] \tStatus --> Successful connection.")
232 hostname = socket.gethostname()
233 ipHostStr = socket.gethostbyname(hostname)
234 if ipHostStr.startswith(
'9.4.'):
236 ipHostStr = ni.ifaddresses(
'tun0')[2][0][
'addr']
237 ipHost =
int(ipaddress.IPv4Address(ipHostStr))
239 print(
"[INFO] Hostname = %s | IP is %s (0x%8.8X)" % (hostname, ipHostStr, ipHost))
241 hostListenAssociation = (
str(ipHostStr), dpHost)
246 tcpListenSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
247 except Exception
as exc:
248 print(
"[EXCEPTION] %s" % exc)
250 tcpListenSock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
257 tcpListenSock.bind(hostListenAssociation)
258 print(
"[INFO] Binding and start listening on host socket ", hostListenAssociation)
259 except Exception
as exc:
260 print(
"[EXCEPTION] %s" % exc)
262 tcpListenSock.listen(1)
268 ipHost =
int(ipaddress.IPv4Address(ipHostStr))
269 reqMsgAsBytes = struct.pack(
">IHH", ipHost, dpHost, 0)
270 print(
"[INFO] Requesting the remote FPGA client to open a connection with the host")
271 print(
"[DEBUG] With message = reqMsgAsBytes = %s" % reqMsgAsBytes)
273 tcpClientSock.sendall(reqMsgAsBytes)
274 except socket.error
as exception:
276 print(
"[EXCEPTION] Socket error while transmitting :: %s" % exception)
283 print(
"[INFO] Waiting for a connection from remote FPGA")
284 tcpServerSock, fpgaClientAssociation = tcpListenSock.accept()
285 print(
"[INFO] Received a connection from FPGA socket address ", fpgaClientAssociation)
290 print(
"[INFO] Testcase `%s` is run with:" % (os.path.basename(__file__)))
294 seed = random.randint(0, 100000)
296 print(
"\t\t seed = %d" % seed)
300 size = random.randint(1, 0xFFFF)
303 print(
"[ERROR] This test limits the size of the received segments to %d bytes.\n" % 0xFFFF)
305 print(
"\t\t size = %d" % size)
307 count = args.loop_count
308 print(
"\t\t loop = %d" % count)
310 verbose = args.verbose
314 print(
"[INFO] This run is executed in single-threading mode.\n")
315 tcp_rx_loop(tcpClientSock, tcpServerSock, size, ipHost, dpHost, count, args.verbose)
319 tcpClientSock.close()
320 tcpServerSock.close()
321 tcpListenSock.close()
def tcp_rx_loop(clientSock, serverSock, size, ip_da, tcp_dp, count, verbose=False)
def restartApp(instId, ipResMngr, portResMngr, user_name, user_passwd)
def getResourceManagerIpv4(args)
def getResourceManagerPort(args)