Skip to content

Commit

Permalink
make some formatting changes
Browse files Browse the repository at this point in the history
  • Loading branch information
pfandzelter committed Apr 17, 2024
1 parent 03e4431 commit 1fcbfcd
Show file tree
Hide file tree
Showing 13 changed files with 141 additions and 158 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
*.img
*.bin

test.sh

~$*

# Created by https://www.toptal.com/developers/gitignore/api/python,macos,windows,git
Expand Down
29 changes: 25 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,37 @@
all: client.img server.img tracker.img alt-tracker.img

client.img: client/client.sh client/client-base.sh client/workload.csv client/ultra_ping
@docker run --rm -v $(PWD)/client/client.sh:/app.sh -v $(PWD)/client/client-base.sh:/base.sh -v $(PWD)/client/workload.csv:/files/workload.csv -v $(PWD)/client/ultra_ping:/files/ultra_ping -v $(PWD)/client:/opt/code --privileged rootfsbuilder $@
@docker run --rm \
-v $(PWD)/client/client.sh:/app.sh \
-v $(PWD)/client/client-base.sh:/base.sh \
-v $(PWD)/client/workload.csv:/files/workload.csv \
-v $(PWD)/client/ultra_ping:/files/ultra_ping \
-v $(PWD)/client:/opt/code \
--privileged rootfsbuilder $@

alt-tracker.img: tracker/tracker.bin tracker/alt-tracker.sh
@docker run --rm -v $(PWD)/tracker/alt-tracker.sh:/app.sh -v $(PWD)/tracker/tracker-base.sh:/base.sh -v $(PWD)/tracker/tracker.bin:/files/tracker.bin -v $(PWD)/tracker:/opt/code --privileged rootfsbuilder $@
@docker run --rm \
-v $(PWD)/tracker/alt-tracker.sh:/app.sh \
-v $(PWD)/tracker/tracker-base.sh:/base.sh \
-v $(PWD)/tracker/tracker.bin:/files/tracker.bin \
-v $(PWD)/tracker:/opt/code \
--privileged rootfsbuilder $@

tracker.img: tracker/tracker.bin tracker/tracker.sh
@docker run --rm -v $(PWD)/tracker/tracker.sh:/app.sh -v $(PWD)/tracker/tracker-base.sh:/base.sh -v $(PWD)/tracker/tracker.bin:/files/tracker.bin -v $(PWD)/tracker:/opt/code --privileged rootfsbuilder $@
@docker run --rm \
-v $(PWD)/tracker/tracker.sh:/app.sh \
-v $(PWD)/tracker/tracker-base.sh:/base.sh \
-v $(PWD)/tracker/tracker.bin:/files/tracker.bin \
-v $(PWD)/tracker:/opt/code \
--privileged rootfsbuilder $@

tracker/tracker.bin: tracker/cmd/tracker tracker/go.mod
@cd tracker ; GOOS=linux GOARCH=amd64 go build -o tracker.bin ./cmd/tracker

server.img: server/server.sh server/multiply.nft server/server-base.sh
@docker run --rm -v $(PWD)/server/server.sh:/app.sh -v $(PWD)/server/server-base.sh:/base.sh -v $(PWD)/server/multiply.nft:/files/multiply.nft -v $(PWD)/server:/opt/code --privileged rootfsbuilder $@
@docker run --rm \
-v $(PWD)/server/server.sh:/app.sh \
-v $(PWD)/server/server-base.sh:/base.sh \
-v $(PWD)/server/multiply.nft:/files/multiply.nft
-v $(PWD)/server:/opt/code \
--privileged rootfsbuilder $@
6 changes: 1 addition & 5 deletions client/client-base.sh
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,4 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#

apk update
apk add -u chrony
echo "refclock PHC /dev/ptp0 poll -2 dpoll -2 offset 0 trust prefer" > /etc/chrony/chrony.conf
apk add python3 curl
apk add python3 curl
24 changes: 1 addition & 23 deletions client/client.sh
Original file line number Diff line number Diff line change
Expand Up @@ -18,31 +18,9 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#

rc-service chronyd start

IP=$(/sbin/ip route | awk '/default/ { print $3 }')

echo nameserver "$IP" > /etc/resolv.conf

chronyc tracking

chronyc -a makestep

sleep 10

chronyc tracking

chronyc -a makestep

chronyc tracking

sleep 10

chronyc tracking

echo "STARTING CLIENT"

NAME=$(curl -s "$IP"/self | python3 -c 'import sys, json; print(json.load(sys.stdin)["name"])')
NAME=$(curl -s info.celestial/self | python3 -c 'import sys, json; print(json.load(sys.stdin)["name"])')

echo "$NAME"
cd ultra_ping || exit
Expand Down
110 changes: 76 additions & 34 deletions client/ultra_ping/onewaymeasurement.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@
from __future__ import division
import socket
import time
import socket
import time
import pickle
import typing
import http.server
Expand All @@ -19,13 +17,13 @@

target_address_pipe_in, target_address_pipe_out = mp.Pipe()

class Handler(http.server.BaseHTTPRequestHandler):

class Handler(http.server.BaseHTTPRequestHandler):
def do_POST(self) -> None:
form = cgi.FieldStorage(
fp=self.rfile,
headers=self.headers, # type: ignore
environ={"REQUEST_METHOD": "POST"}
headers=self.headers, # type: ignore
environ={"REQUEST_METHOD": "POST"},
)

s = form.getvalue("server")
Expand All @@ -36,8 +34,8 @@ def do_POST(self) -> None:
self.end_headers()
self.wfile.write(b"OK\n")

class OneWayMeasurement():

class OneWayMeasurement:
description = """Measure one-way UDP packet latency time.
On your server host, run:
$ ./quack2.py --server
Expand All @@ -56,7 +54,10 @@ def update_target(self, target_address_pipe: MultiprocessingConnection) -> None:
while True:
target_address = target_address_pipe.recv()
if self.target_port is not None:
print("Updating target address to %s:%d" % (target_address, self.target_port))
print(
"Updating target address to %s:%d"
% (target_address, self.target_port)
)
if self.target_address != target_address:
self.target_address = None

Expand All @@ -72,12 +73,12 @@ def send_packets(self, id: int, n_packets: int) -> None:
send_rate_kbytes_per_s.
"""

#send_rate_bytes_per_s = send_rate_kbytes_per_s * 1000
# send_rate_bytes_per_s = send_rate_kbytes_per_s * 1000
n_bytes = 0
#packet_rate = send_rate_bytes_per_s / packet_len
#packet_interval = 1 / packet_rate
# packet_rate = send_rate_bytes_per_s / packet_len
# packet_interval = 1 / packet_rate

#print("Sending %d %d-byte packets at about %d kB/s..." %(n_packets, packet_len, send_rate_kbytes_per_s))
# print("Sending %d %d-byte packets at about %d kB/s..." %(n_packets, packet_len, send_rate_kbytes_per_s))

print("Waiting for a target address...")

Expand All @@ -86,12 +87,10 @@ def send_packets(self, id: int, n_packets: int) -> None:

print("Got a target address...")


send_start_seconds = time.time()
#inter_packet_sleep_times_ms = []
# inter_packet_sleep_times_ms = []

for packet_n in range(n_packets):

while self.target_address == None:
pass

Expand All @@ -115,8 +114,10 @@ def send_packets(self, id: int, n_packets: int) -> None:
# I don't know why, but this still doesn't yield exactly the desired
# send rate. But eh, it's good enough.
tx_time_seconds = tx_end_seconds - tx_start_seconds
sleep_time_seconds = self.workload_deltas[packet_n % self.workload_length] - tx_time_seconds
#inter_packet_sleep_times_ms.append("%.3f" % (sleep_time_seconds * 1000))
sleep_time_seconds = (
self.workload_deltas[packet_n % self.workload_length] - tx_time_seconds
)
# inter_packet_sleep_times_ms.append("%.3f" % (sleep_time_seconds * 1000))
if sleep_time_seconds > 0:
time.sleep(sleep_time_seconds)
send_end_seconds = time.time()
Expand All @@ -125,30 +126,53 @@ def send_packets(self, id: int, n_packets: int) -> None:

total_send_duration_seconds = send_end_seconds - send_start_seconds
bytes_per_second = n_bytes / total_send_duration_seconds
print("(Actually sent packets at %d kB/s: %d bytes for %.1f seconds)" % (bytes_per_second / 1e3, n_bytes, total_send_duration_seconds))
print(
"(Actually sent packets at %d kB/s: %d bytes for %.1f seconds)"
% (bytes_per_second / 1e3, n_bytes, total_send_duration_seconds)
)

self.sock_out.close()

@staticmethod
def save_packet_latencies(packetn_latency_tuples: typing.Tuple[typing.List[int],typing.List[int],typing.List[int],typing.List[float],typing.List[float],typing.List[float]], n_packets_expected: int, output_filename: str) -> None:
def save_packet_latencies(
packetn_latency_tuples: typing.Tuple[
typing.List[int],
typing.List[int],
typing.List[int],
typing.List[float],
typing.List[float],
typing.List[float],
],
n_packets_expected: int,
output_filename: str,
) -> None:
"""
Save latencies of received packets to a file, along with the total
number of packets send in the first place.
"""
with open(output_filename, "w") as out_file:
#out_file.write("%d\n" % n_packets_expected)
# out_file.write("%d\n" % n_packets_expected)
out_file.write("id,packet_n,packet_len,latency,send_time,recv_time\n")
for i in range(len(packetn_latency_tuples[0])):
id = packetn_latency_tuples[0][i]
packet_n = packetn_latency_tuples[1][i]
packet_len = packetn_latency_tuples[2][i]
latency = packetn_latency_tuples[3][i]
send_time = (packetn_latency_tuples[4][i] * 1e9)
recv_time = (packetn_latency_tuples[5][i] * 1e9)
out_file.write("%d,%d,%d,%.2f,%.0f,%.0f\n" % (id, packet_n, packet_len,latency, send_time, recv_time))

def run_client(self, id: int, listen_port: int, http_port: int, n_packets: int, workload_file: str) -> None:

send_time = packetn_latency_tuples[4][i] * 1e9
recv_time = packetn_latency_tuples[5][i] * 1e9
out_file.write(
"%d,%d,%d,%.2f,%.0f,%.0f\n"
% (id, packet_n, packet_len, latency, send_time, recv_time)
)

def run_client(
self,
id: int,
listen_port: int,
http_port: int,
n_packets: int,
workload_file: str,
) -> None:
total_packet_len = 0
total_workload_duration = 0.0

Expand Down Expand Up @@ -186,7 +210,9 @@ def run_client(self, id: int, listen_port: int, http_port: int, n_packets: int,

print("Started HTTP server on :%d" % (http_port))

controlThread = td.Thread(target=self.update_target, args=[target_address_pipe_out])
controlThread = td.Thread(
target=self.update_target, args=[target_address_pipe_out]
)
controlThread.start()

print("Started control thread...")
Expand All @@ -208,14 +234,19 @@ def get_packet_payload(self, id: int, packet_n: int) -> bytes:
payload = pickle.dumps((id, packet_n, send_time_seconds))
return payload

def run_server(self, n_packets_expected: int, server_listen_port: int, payload_len: int, timeout: int=15) -> None:
def run_server(
self,
n_packets_expected: int,
server_listen_port: int,
payload_len: int,
timeout: int = 15,
) -> None:
"""
Receive packets sent from the client. Calculate the latency for each
packet by comparing the counter value from the packet (the counter value
at time of transmission) to the current counter value.
"""
sock_in = \
socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
sock_in = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
sock_in.bind(("0.0.0.0", server_listen_port))

print("UDP server running...")
Expand All @@ -242,13 +273,13 @@ def run_server(self, n_packets_expected: int, server_listen_port: int, payload_l
payload = data.rstrip(a)
(ids[packet_c], packet_ns[packet_c], send_time) = pickle.loads(payload)
latency_mss[packet_c] = (recv_time - send_time) * 1e3
#packets[packet_c] = (id, packet_n, packet_len, latency_ms, send_time, recv_time)
send_times[packet_c] = send_time
recv_times[packet_c] = recv_time
# packets[packet_c] = (id, packet_n, packet_len, latency_ms, send_time, recv_time)
send_times[packet_c] = send_time
recv_times[packet_c] = recv_time

packet_c += 1

#if packet_c % 2000 == 0:
# if packet_c % 2000 == 0:
# print("%d packets received so far" % packet_c)

except socket.timeout:
Expand All @@ -261,4 +292,15 @@ def run_server(self, n_packets_expected: int, server_listen_port: int, payload_l

print("Received %d packets" % packet_c)

self.save_packet_latencies((ids[:packet_c], packet_ns[:packet_c], packet_lens[:packet_c], latency_mss[:packet_c], send_times[:packet_c], recv_times[:packet_c]), n_packets_expected, self.test_output_filename)
self.save_packet_latencies(
(
ids[:packet_c],
packet_ns[:packet_c],
packet_lens[:packet_c],
latency_mss[:packet_c],
send_times[:packet_c],
recv_times[:packet_c],
),
n_packets_expected,
self.test_output_filename,
)
35 changes: 23 additions & 12 deletions client/ultra_ping/quack.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

SERVER_RECV_BUFFER_SIZE = 2048


def start(Measurement: typing.Type[OneWayMeasurement]) -> None:
"""
Process arguments and run the appropriate functions depending on whether
Expand All @@ -22,38 +23,48 @@ def start(Measurement: typing.Type[OneWayMeasurement]) -> None:
args = parse_args(Measurement.description)

if args.payload_len > SERVER_RECV_BUFFER_SIZE:
print("Warning: payload_len (%d) is greater than "
"SERVER_RECV_BUFFER_SIZE (%d)" % (args.payload_len,
SERVER_RECV_BUFFER_SIZE))
print(
"Warning: payload_len (%d) is greater than "
"SERVER_RECV_BUFFER_SIZE (%d)" % (args.payload_len, SERVER_RECV_BUFFER_SIZE)
)

tester = Measurement(args.output_filename)
if args.server:
tester.run_server(args.n_packets, args.listen_port, SERVER_RECV_BUFFER_SIZE, args.timeout)
tester.run_server(
args.n_packets, args.listen_port, SERVER_RECV_BUFFER_SIZE, args.timeout
)
elif args.client:
tester.run_client(args.id, args.listen_port, args.http_port, args.n_packets, args.workload_file)
tester.run_client(
args.id,
args.listen_port,
args.http_port,
args.n_packets,
args.workload_file,
)


def parse_args(description: str) -> argparse.Namespace:
"""
Parse arguments.
"""

parser = argparse.ArgumentParser(
description=description, formatter_class=argparse.RawTextHelpFormatter)
description=description, formatter_class=argparse.RawTextHelpFormatter
)
group = parser.add_mutually_exclusive_group(required=True)
group.add_argument('--server', action='store_true')
group.add_argument('--client', action='store_true' )
group.add_argument("--server", action="store_true")
group.add_argument("--client", action="store_true")
parser.add_argument("--n_packets", type=int, default=700000)
parser.add_argument("--payload_len", type=int, default=1227)
parser.add_argument("--send_rate_kBps", type=int, default=1400)
parser.add_argument("--timeout", type=int, default=15)
parser.add_argument("--id", type=int, default=random.randint(0,100))
parser.add_argument(
"--output_filename", default='udp_packetn_latency_pairs')
parser.add_argument("--id", type=int, default=random.randint(0, 100))
parser.add_argument("--output_filename", default="udp_packetn_latency_pairs")
parser.add_argument("--listen_port", type=int, default=8888)
parser.add_argument("--http_port", type=int, default=8000)
parser.add_argument("--workload_file", type=str, default="./workload.csv")
args = parser.parse_args()
return args


start(OneWayMeasurement)
start(OneWayMeasurement)
Loading

0 comments on commit 1fcbfcd

Please sign in to comment.