import sys import time import threading from scapy.all import Ether, IP, UDP, send, sendp, Raw, sniff global initial_timestamp initial_timestamp = int(time.time() * 1000) # Simulated ACK sending function def send_ack(destination_IP, my_port, sender_port): ack_data = "" ################### # With localhost: # ack_packet = IP(dst=destination_IP) / UDP(dport=sender_port, sport=my_port) / Raw(load=str(ack_data)) # send(ack_packet, verbose=False) ################### # With netns: ack_packet = Ether(dst="64:9d:99:b1:0a:a4", src="64:9d:99:b1:0a:88") / IP(dst=destination_IP) / UDP(sport=my_port,dport=sender_port) / Raw(load=str(ack_data)) sendp(ack_packet, verbose=False) ################### print(f"Sent ACK: {ack_data}") # Process incoming packets def process_packet(pkt): ################### Save timestamps ################### if Raw in pkt: with open(save_file, "a") as f: # open as "a" for append global initial_timestamp receival_time = str(int(time.time() * 1000) - initial_timestamp) # time of arrival at receiver send_time = pkt[Raw].load # time it was sent from the sender ################### Conversion & error handling ################### try: send_time = int(send_time.decode("utf-8").split("X")[0]) # decode the payload and stop at "X" except ValueError: # For the last packet without a timestamp but "END" as payload print(f"END for {my_port}") send_ack(destination_IP, my_port, sender_port) return except Exception as e: print(f"Decoding error at {my_port}") send_ack(destination_IP, my_port, sender_port) return ################### Write data ################### aoi = int(receival_time) - send_time f.write(f"{send_time},{receival_time},{aoi}\n") send_ack(destination_IP, my_port, sender_port) # Main loop def main(destination_IP, my_port, sender_port): ################### # With localhost: # sniff(iface="lo", filter=f"udp and dst port {my_port}", prn=process_packet, store=False) ################### # With netns: sniff(iface="enp6s0f0np0", filter=f"udp and dst port {my_port}", prn=process_packet, store=False) ################### if __name__ == "__main__": if len(sys.argv) != 4: print("Usage: python receive_and_ack.py ") sys.exit(1) destination_IP = sys.argv[1] # Clear my_port = int(sys.argv[2]) # Port to listen on sender_port = int(sys.argv[3]) # Port to send acks to save_file = f"timestamps_{my_port}" main(destination_IP, my_port, sender_port)