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="00:00:00:00:00:04", src="00:00:00:00:00:01") / IP(dst="127.0.0.1") / UDP(dport=5551) / 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="ns-g", 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)