S1005403_RisCC/test_server_packets.py

219 lines
7.3 KiB
Python

#!/usr/bin/env python3
"""
Script di test per verificare se il server SFP sta inviando pacchetti
e per analizzare il contenuto dei messaggi ricevuti.
"""
import socket
import time
import sys
import ctypes
from datetime import datetime
# Struttura SFP Header (32 bytes)
class SFPHeader(ctypes.Structure):
_pack_ = 1
_fields_ = [
("SFP_MARKER", ctypes.c_uint8),
("SFP_DIRECTION", ctypes.c_uint8),
("SFP_PROT_VER", ctypes.c_uint8),
("SFP_PT_SPARE", ctypes.c_uint8),
("SFP_TAG", ctypes.c_uint8),
("SFP_SRC", ctypes.c_uint8),
("SFP_FLOW", ctypes.c_uint8),
("SFP_TID", ctypes.c_uint8),
("SFP_FLAGS", ctypes.c_uint8),
("SFP_WIN", ctypes.c_uint8),
("SFP_ERR", ctypes.c_uint8),
("SFP_ERR_INFO", ctypes.c_uint8),
("SFP_TOTFRGAS", ctypes.c_uint16),
("SFP_FRAG", ctypes.c_uint16),
("SFP_RECTYPE", ctypes.c_uint8),
("SFP_RECSPARE", ctypes.c_uint8),
("SFP_PLDAP", ctypes.c_uint8),
("SFP_PLEXT", ctypes.c_uint8),
("SFP_RECCOUNTER", ctypes.c_uint16),
("SFP_PLSIZE", ctypes.c_uint16),
("SFP_TOTSIZE", ctypes.c_uint32),
("SFP_PLOFFSET", ctypes.c_uint32),
]
# DataTag (8 bytes)
class DataTag(ctypes.Structure):
_pack_ = 1
_fields_ = [
("ID", ctypes.c_uint8 * 2),
("VALID", ctypes.c_uint8),
("VERSION", ctypes.c_uint8),
("SIZE", ctypes.c_uint32),
]
def main():
# Configurazione
LOCAL_IP = "0.0.0.0"
LOCAL_PORT = 60012
SERVER_IP = "127.0.0.1"
SERVER_PORT = 60013
print("=" * 70)
print("TEST SERVER SFP - Verifica ricezione pacchetti")
print("=" * 70)
print(f"Locale: {LOCAL_IP}:{LOCAL_PORT}")
print(f"Server: {SERVER_IP}:{SERVER_PORT}")
print("=" * 70)
# Crea socket UDP
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# Aumenta il buffer di ricezione
sock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 8388608)
sock.bind((LOCAL_IP, LOCAL_PORT))
sock.settimeout(5.0) # Timeout di 5 secondi
print(f"[OK] Socket creato e bound su {LOCAL_IP}:{LOCAL_PORT}")
print(
f"[INFO] Buffer size: {sock.getsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF)} bytes"
)
print()
except Exception as e:
print(f"[ERROR] Impossibile creare socket: {e}")
return 1
print("In ascolto per pacchetti dal server...")
print("(Premi Ctrl+C per terminare)")
print()
packet_count = 0
start_time = time.time()
last_report_time = start_time
flow_stats = {}
try:
while True:
try:
data, addr = sock.recvfrom(65535)
packet_count += 1
current_time = time.time()
# Analizza l'header SFP
if len(data) < 32:
print(f"[WARN] Pacchetto troppo corto: {len(data)} bytes da {addr}")
continue
try:
header = SFPHeader.from_buffer_copy(data)
flow_char = (
chr(header.SFP_FLOW)
if 32 <= header.SFP_FLOW <= 126
else f"0x{header.SFP_FLOW:02X}"
)
direction = (
chr(header.SFP_DIRECTION)
if 32 <= header.SFP_DIRECTION <= 126
else f"0x{header.SFP_DIRECTION:02X}"
)
# Aggiorna statistiche per flow
if flow_char not in flow_stats:
flow_stats[flow_char] = 0
flow_stats[flow_char] += 1
# Timestamp leggibile
ts = datetime.now().strftime("%H:%M:%S.%f")[:-3]
# Analizza il payload (primi bytes dopo l'header)
payload = data[32:]
tag_info = ""
if len(payload) >= 8:
try:
tag = DataTag.from_buffer_copy(payload)
tag_str = (
f"{chr(tag.ID[0]) if 32 <= tag.ID[0] <= 126 else tag.ID[0]:02X}"
f"{chr(tag.ID[1]) if 32 <= tag.ID[1] <= 126 else tag.ID[1]:02X}"
)
tag_info = f" | Tag: {tag_str} (valid={tag.VALID}, size={tag.SIZE})"
except:
pass
# Mostra preview dei primi bytes del payload
preview = (
payload[:16].hex() if len(payload) >= 16 else payload.hex()
)
print(
f"[{ts}] Pkt #{packet_count:04d} | From: {addr[0]}:{addr[1]} | "
f"Flow: {flow_char} | Dir: {direction} | TID: {header.SFP_TID:03d} | "
f"Size: {len(data):5d} bytes | Payload: {header.SFP_PLSIZE:5d} bytes{tag_info}"
)
if packet_count <= 3:
print(f" Payload preview: {preview}")
print()
except Exception as e:
print(f"[ERROR] Impossibile parsare header: {e}")
print(f" Raw bytes (primi 32): {data[:32].hex()}")
# Report periodico ogni 5 secondi
if current_time - last_report_time >= 5.0:
elapsed = current_time - start_time
rate = packet_count / elapsed if elapsed > 0 else 0
print()
print("-" * 70)
print(
f"[STATS] Tempo: {elapsed:.1f}s | Pacchetti: {packet_count} | "
f"Rate: {rate:.1f} pkt/s"
)
print(f"[STATS] Distribuzione per Flow: {flow_stats}")
print("-" * 70)
print()
last_report_time = current_time
except socket.timeout:
print(f"[WARN] Nessun pacchetto ricevuto negli ultimi 5 secondi")
print(
f" Verifica che il server sia in esecuzione su {SERVER_IP}:{SERVER_PORT}"
)
print()
except KeyboardInterrupt:
print()
print("=" * 70)
print("Test terminato dall'utente")
finally:
sock.close()
elapsed = time.time() - start_time
rate = packet_count / elapsed if elapsed > 0 else 0
print("=" * 70)
print("STATISTICHE FINALI:")
print(f" Durata: {elapsed:.1f} secondi")
print(f" Pacchetti ricevuti: {packet_count}")
print(f" Rate medio: {rate:.1f} pkt/s")
print(f" Distribuzione Flow: {flow_stats}")
print("=" * 70)
if packet_count == 0:
print()
print("[ATTENZIONE] Nessun pacchetto ricevuto!")
print("Possibili cause:")
print(" 1. Il server non è in esecuzione")
print(" 2. Il server non sta trasmettendo sulla porta corretta")
print(" 3. Firewall sta bloccando i pacchetti")
print(" 4. Problema di network/routing")
return 1
return 0
if __name__ == "__main__":
sys.exit(main())