34 import netifaces
as ni
37 from netifaces
import AF_INET
40 from tc_utils
import *
43 def udp_rx_loop(clientSock, serverSock, size, ip_da, udp_dp, count, verbose=False):
44 """UDP Rx Single-Thread Ramp.
45 Requests the FPGA to open a new active port and expects to receive 'count' datagrams
46 of 'size' bytes. Each datagram is made of the following repetitive pattern
47 '48692066726f6d200x464d4b553630210a' which decodes into the string "Hi from FMKU60\n".
48 :param clientSock The socket to send to.
49 :param serverSock The socket to receive from.
50 :param size The size of the expected segment.
51 :param ip_da The destination address of the host.
52 :param udp_dp The active destination port number that the FPGA is requested to open.
53 :param count The number of datagrams to receive.
54 :param verbose Enables verbosity.
57 print(
"[INFO] Requesting the FPGA to send %d datagrams of %d bytes.\n" % (count, size))
60 totalReceivedBytes = 0
64 serverSock.setblocking(
False)
65 serverSock.settimeout(5)
71 reqMsgAsBytes = struct.pack(
">IHH", ip_da, udp_dp, size)
73 print(
"\n\n[DEBUG] reqMsgAsBytes = %s" % reqMsgAsBytes)
75 startTime = datetime.datetime.now()
80 clientSock.sendall(reqMsgAsBytes)
81 except socket.error
as exc:
83 print(
"[EXCEPTION] Socket error while transmitting :: %s" % exc)
91 while currRxByteCnt < size:
93 data = serverSock.recv(MTU)
99 if e.errno != errno.EAGAIN
and e.errno != errno.EWOULDBLOCK:
100 print(
"[ERROR] Socket reading error: {}".format(
str(e)))
102 print(
"\t[INFO] 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(
"#### UDP Rx DONE with bandwidth = %6.1f Mb/s " % bandwidth)
135 bandwidth = bandwidth / 1000
136 print(
"#### UDP Rx DONE with bandwidth = %2.1f Gb/s " % bandwidth)
137 if (totalReceivedBytes != (size * count)):
138 print(
"#### [WARNING] UDP data loss = %.1f%%" % (1-(totalReceivedBytes)/(size*count)))
139 print(
"#####################################################")
151 parser = argparse.ArgumentParser(description=
'A script to receive UDP 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 fpgaClientAssociation = (
str(ipFpga), dpHost)
219 udpClientSock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
220 except Exception
as exc:
221 print(
"[EXCEPTION] %s" % exc)
228 udpServerSock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
229 except Exception
as exc:
230 print(
"[EXCEPTION] %s" % exc)
232 udpServerSock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 100*1024)
240 udpClientSock.bind(hostClientAssociation)
241 print(
'[INFO] Binding the socket address of the HOST to {%s, %d}' % hostClientAssociation)
242 except Exception
as exc:
243 print(
"[EXCEPTION] %s" % exc)
249 hostname = socket.gethostname()
250 ipHostStr = socket.gethostbyname(hostname)
251 if ipHostStr.startswith(
'9.4.'):
253 for itf
in ni.interfaces():
255 if itf.startswith(
'tun'):
256 ip4Str = ni.ifaddresses(itf)[AF_INET][0][
'addr']
257 if ip4Str.startswith(
'10.2.'):
263 print(
"[ERROR] Could not find IPv4 address of the tunnel associated with the user-VPN.\n")
265 ipHost =
int(ipaddress.IPv4Address(ipHostStr))
267 print(
"[INFO] Hostname = %s | IP is %s (0x%8.8X) \n" % (hostname, ipHostStr, ipHost))
270 udpServerSock.bind((ipHostStr, dpHost))
271 print(
'[INFO] Binding the socket address of the HOST to {%s, %d}' % (ipHostStr, dpHost))
272 except Exception
as exc:
273 print(
"[EXCEPTION] %s" % exc)
282 udpClientSock.connect(fpgaServerAssociation)
283 except Exception
as exc:
284 print(
"[EXCEPTION] %s" % exc)
287 print(
'[INFO] Successful connection with socket address of FPGA at {%s, %d}' % fpgaServerAssociation)
291 print(
'[INFO] Host server ready to start listening on socket address {%s, %d}' % fpgaClientAssociation)
295 print(
"[INFO] Testcase `%s` is run with:" % (os.path.basename(__file__)))
298 seed = random.randint(0, 100000)
300 print(
"\t\t seed = %d" % seed)
304 size = random.randint(1, 0xFFFF)
307 print(
"[ERROR] This test limits the size of the received datagram to %d bytes.\n" % 0xFFFF)
309 print(
"\t\t size = %d" % size)
311 count = args.loop_count
312 print(
"\t\t loop = %d" % count)
316 print(
"[INFO] This testcase is sending traffic from FPGA-to-HOST.")
317 print(
"[INFO] This run is executed in single-threading mode.\n")
318 udp_rx_loop(udpClientSock, udpServerSock, size, ipHost, dpHost, count, args.verbose)
323 udpClientSock.close()
324 udpServerSock.close()
def udp_rx_loop(clientSock, serverSock, size, ip_da, udp_dp, count, verbose=False)
def restartApp(instId, ipResMngr, portResMngr, user_name, user_passwd)
def getResourceManagerIpv4(args)
def getResourceManagerPort(args)