Premiamo il PTT.
Parliamo nel microfono.
Il nostro hotspot riceve il segnale e pochi istanti dopo la nostra voce viene ascoltata da radioamatori che si trovano a centinaia o migliaia di chilometri di distanza.
In mezzo a tutto questo spesso compare una parola:
reflector.
Ma che cos’è realmente?
Un reflector non è semplicemente “un server al quale si collegano le radio”.
È un sistema che mantiene informazioni sui client collegati, riceve flussi digital voice, interpreta il protocollo, decide dove debbano essere inoltrati e distribuisce i pacchetti alle destinazioni appropriate.
A seconda del software può inoltre gestire moduli, gateway, keepalive, dashboard, interlink, autenticazione o validazione, logging e perfino transcoding.
Progetti reali mostrano bene quanto il concetto possa diventare sofisticato: mrefd, per esempio, è un reflector open source M17 che gestisce Stream e Packet Mode e fino a 26 moduli; URF estende invece il concetto a diversi protocolli digital voice e può essere abbinato a un transcoder.
Vediamo quindi cosa accade realmente dentro un reflector.
Prima distinzione: repeater, gateway e reflector
Sono tre componenti differenti.
Ripetitore
Il ripetitore lavora principalmente sul lato RF:
RADIO
↓ RF
RIPETITORE
↓ RF
ALTRE RADIO
Può naturalmente essere collegato alla rete, ma la sua funzione fondamentale rimane quella di ricevere e ritrasmettere RF.
Gateway
Il gateway collega il mondo RF o un sistema locale alla rete.
Per esempio:
RADIO
↓
HOTSPOT / RIPETITORE
↓
GATEWAY
↓
INTERNET
Il software M17Gateway, per esempio, permette a un sistema M17 di collegarsi ai reflector e gestisce comandi quali collegamento, scollegamento, echo e informazioni sullo stato del link.
Reflector
Il reflector sta dall’altra parte.
Riceve connessioni da:
Gateway A
Gateway B
Gateway C
Hotspot D
Ripetitore E
...
e crea un punto comune nel quale i flussi vengono distribuiti.
Possiamo immaginarlo come una grande sala virtuale.
Una metafora utile: la conferenza telefonica
Immaginiamo dieci persone in una conference call.
Quando parla A:
A
↓
SERVER
├── B
├── C
├── D
├── E
└── ...
Il server non deve necessariamente trasformare la voce.
Può semplicemente ricevere il flusso dati e replicarlo verso gli altri partecipanti.
Il reflector digitale segue spesso una filosofia simile.
Primo passo: collegamento del client
Supponiamo di avere:
HOTSPOT IZ1ABC
che vuole collegarsi:
REFLECTOR XYZ
MODULO A
Il gateway conosce normalmente:
- hostname o IP;
- porta;
- protocollo;
- identificativo/callsign;
- modulo desiderato.
Nel mondo M17, per esempio, un reflector può possedere moduli distinti indicati da lettere; mrefd supporta fino a 26 canali/moduli, mentre gli host file utilizzati nell’ecosistema possono includere callsign del reflector, indirizzi IPv4/IPv6, moduli configurati e porta UDP.
Che cos’è un modulo?
Possiamo immaginare:
REFLECTOR D2ALP
│
├── MODULO A
├── MODULO B
├── MODULO C
└── MODULO D
Ogni modulo rappresenta una sala logica separata.
Client collegati ad A ascoltano normalmente il traffico di A.
Client collegati a B ascoltano B.
Non abbiamo necessariamente quattro server.
Abbiamo quattro gruppi logici gestiti dallo stesso processo reflector.
La tabella dei client
Il reflector deve sapere chi è collegato.
Concettualmente potrebbe mantenere una struttura simile:
CALLSIGN IP PORTA MODULO LAST SEEN
IZ1AAA 1.2.3.4 17000 A 10:21:03
IZ1BBB 5.6.7.8 23001 A 10:21:04
IW1CCC 9.8.7.6 41000 B 10:21:02
Non è necessariamente la struttura interna esatta di ogni software, ma rappresenta bene ciò che un reflector deve conoscere:
a quali endpoint deve inviare i pacchetti?
mrefd è esplicitamente progettato come reflector M17 con più moduli e gestione dei client Stream/Packet; applicazioni come M17Web dimostrano inoltre che il traffico di un reflector può essere osservato da software esterno via UDP e successivamente elaborato.
Perché spesso viene usato UDP?
Nelle applicazioni digital voice in tempo reale incontriamo frequentemente UDP.
Il motivo concettuale è semplice:
la voce ha bisogno soprattutto di arrivare in tempo.
Immaginiamo un pacchetto vocale appartenente alla parola:
buongiorno
che viene perso.
Dopo 500 ms non sarebbe molto utile ritrasmetterlo quando la conversazione è già andata avanti.
In sistemi real-time si preferisce spesso accettare una piccola perdita e proseguire.
M17Web, ad esempio, documenta esplicitamente un’architettura nella quale il sistema ascolta traffico UDP proveniente dai reflector M17, lo inoltra attraverso un proxy e decodifica l’audio nel browser. Anche implementazioni M17 relay descrivono esplicitamente connessioni e interlink gestiti tramite UDP.
Questo non significa che ogni protocollo digital voice utilizzi esclusivamente UDP: dipende dal sistema.
Premiamo il PTT
A questo punto iniziamo una trasmissione.
La catena potrebbe essere:
MICROFONO
↓
RADIO
↓ RF
MMDVM
↓
GATEWAY
↓ IP
REFLECTOR
La voce è già stata trasformata in dati digitali prima di raggiungere il reflector.
Questo punto è essenziale.
Il reflector normalmente non riceve “audio WAV”
Riceve frame del protocollo.
Concettualmente potremmo avere qualcosa del tipo:
HEADER
SOURCE
DESTINATION
STREAM ID
SEQUENCE
VOICE DATA
CONTROL
La struttura reale dipende dal protocollo.
Il server deve quindi analizzare i campi necessari per capire:
- chi trasmette;
- a quale flusso appartiene il pacchetto;
- quale modulo è interessato;
- dove deve essere inoltrato.
Lo Stream ID
Immaginiamo che due stazioni inizino trasmissioni quasi contemporaneamente.
Il reflector deve distinguere:
STREAM 0x1234
da:
STREAM 0xABCD
Un identificatore di flusso permette al software di associare pacchetti successivi alla stessa trasmissione.
Il concetto è analogo a mettere un’etichetta su ogni pacchetto:
“Io appartengo alla trasmissione di IZ1ABC iniziata poco fa.”
I pacchetti arrivano in sequenza
La voce viene suddivisa in piccoli blocchi.
Possiamo rappresentarla così:
P1
P2
P3
P4
P5
P6
...
Il network li trasporta attraverso Internet.
Idealmente arrivano:
1 2 3 4 5 6
ma una rete IP reale può produrre:
1 2 4 3 5 6
oppure:
1 2 X 4 5 6
dove X rappresenta un pacchetto perso.
È qui che diventano importanti:
- sequence number;
- buffering;
- jitter management;
- gestione delle perdite.
Il reflector riceve il primo frame
Supponiamo:
SOURCE = IZ1ABC
MODULE = A
STREAM = 1234
Il reflector verifica il contesto della connessione e determina:
questa trasmissione appartiene al modulo A.
A questo punto consulta l’elenco dei client associati ad A.
Fan-out: una copia diventa cento copie
Supponiamo che sul modulo A ci siano:
100 client
Il reflector riceve:
1 pacchetto
e deve distribuirlo ai client interessati.
Concettualmente:
┌→ CLIENT 1
├→ CLIENT 2
├→ CLIENT 3
PACCHETTO → REF ├→ CLIENT 4
├→ ...
└→ CLIENT 100
Questo processo può essere chiamato fan-out.
Il reflector diventa quindi un moltiplicatore di traffico.
Un semplice conto
Supponiamo, solo come esempio didattico, che il flusso IP complessivo di una trasmissione sia:
10 kbit/s
con 100 destinatari.
In ingresso il server riceve circa:
10 kbit/s
in uscita potrebbe dover inviare, nell’ordine di grandezza:
10 × 100 = 1000 kbit/s
cioè circa 1 Mbit/s, trascurando overhead e traffico di controllo.
Con:
500 client
il traffico cresce ulteriormente.
Per questo un reflector molto frequentato necessita non tanto di enormi capacità CPU quanto di:
- rete affidabile;
- banda;
- packet processing efficiente;
- kernel/network stack ben configurato.
Il server deve decodificare la voce?
Non necessariamente.
Questa è probabilmente la parte più importante dell’articolo.
Se:
CLIENT A → codec X
CLIENT B → codec X
il reflector può spesso distribuire direttamente il frame codificato.
CODEC X DATA
↓
REFLECTOR
↓
CODEC X DATA
Non serve:
decode → PCM → encode
Il server non deve quindi necessariamente sapere “cosa stiamo dicendo”.
Deve sapere dove deve mandare quei dati.
Routing non significa transcoding
Ecco la differenza fondamentale.
Routing/reflecting
AMBE
↓
AMBE
oppure:
Codec2
↓
Codec2
Il payload vocale resta essenzialmente nello stesso formato.
Transcoding
AMBE
↓
DECODER
↓
PCM
↓
ENCODER
↓
CODEC2
Qui il server deve realmente convertire l’audio.
Un progetto come URF chiarisce bene la distinzione: può supportare diversi protocolli, ma senza il componente transcoder gli utenti che impiegano codec differenti possono ascoltare soltanto gli altri client compatibili con il proprio codec.
Reflector multiprotocollo
Qui la faccenda diventa molto più interessante.
Supponiamo:
DMR
\
YSF ---- REFLECTOR
/
D-STAR
Il server deve comprendere diversi protocolli di rete.
Non significa però automaticamente che sappia convertire anche i codec.
Possiamo avere:
PROTOCOL TRANSLATION
senza:
VOICE TRANSCODING
Sono due operazioni differenti.
Prendiamo XLX come esempio concettuale
Software della famiglia XLX sono nati come reflector/gateway multiprotocollo per reti digital voice.
DMRGateway, per esempio, può collegare un sistema MMDVM fino a più reti DMR e prevede specificamente una rete XLX tra quelle configurabili.
Questo dimostra come nel mondo digital voice i ruoli possano concatenarsi:
MMDVM
↓
DMRGateway
↓
XLX
↓
altri gateway/client
Il transcoder
Se due lati utilizzano codifiche vocali incompatibili occorre aggiungere:
TRANSCODER
L’architettura può diventare:
PROTOCOLLO A
↓
REFLECTOR
↓
TRANSCODER
↓
PROTOCOLLO B
Esistono implementazioni multiprotocollo che utilizzano proprio un componente transcoder separato. URF, ad esempio, supporta la possibilità di transcoding locale o remoto mediante un componente dedicato.
Perché il transcoder è separato?
Perché svolge un lavoro completamente differente.
Il reflector deve principalmente:
ricevere
identificare
decidere
replicare
trasmettere
Il transcoder deve:
decodificare codec A
↓
produrre audio intermedio
↓
codificare codec B
Può quindi richiedere:
- maggiore CPU;
- hardware vocoder;
- software aggiuntivo;
- buffering;
- gestione della latenza.
Separare le due funzioni permette di scalare il sistema meglio.
La latenza si accumula
Seguiamo una QSO:
RADIO
↓
RF
↓
HOTSPOT
↓
INTERNET
↓
REFLECTOR
↓
TRANSCODER
↓
INTERNET
↓
HOTSPOT
↓
RF
↓
RADIO
Ogni freccia richiede tempo.
Abbiamo:
- codifica;
- buffering;
- RF;
- gateway;
- uplink Internet;
- routing;
- reflector;
- eventuale transcoding;
- downlink;
- decodifica.
È così che due radio poste a pochi metri l’una dall’altra possono avere centinaia di millisecondi di ritardo se stanno comunicando attraverso un server a migliaia di chilometri.
Perché a volte due persone si parlano sopra?
Immaginiamo:
IZ1AAA termina di parlare
ma il pacchetto finale deve ancora attraversare:
Internet → reflector → Internet → hotspot
Il secondo operatore sente la fine della trasmissione leggermente dopo.
Se risponde istantaneamente, la rete potrebbe ancora avere code o stati di stream in fase di chiusura.
Ecco perché nelle reti digitali è buona pratica lasciare una piccola pausa tra un passaggio e l’altro.
Non serve aspettare cinque secondi.
Ma neppure schiacciare il PTT nello stesso istante in cui scompare l’audio.
Keepalive: “sei ancora lì?”
Il reflector deve anche capire se un client è ancora collegato.
Supponiamo che un hotspot venga spento senza inviare correttamente un messaggio di disconnessione.
Il server potrebbe continuare a considerarlo online.
Per questo molti protocolli utilizzano meccanismi di:
PING
PONG
KEEPALIVE
TIMEOUT
Concettualmente:
REFLECTOR → sei vivo?
CLIENT → sì
REFLECTOR → sei vivo?
CLIENT → sì
REFLECTOR → sei vivo?
CLIENT → ...
timeout
CLIENT RIMOSSO
Questo mantiene pulita la tabella delle connessioni.
NAT: perché complica tutto
Molti hotspot si trovano dietro:
router domestico
NAT
CGNAT
firewall
Il reflector non può necessariamente aprire spontaneamente una connessione verso quel dispositivo.
È quindi il client che generalmente avvia la comunicazione verso il server.
HOTSPOT
│
└────────→ REFLECTOR
Una volta creata la mappatura NAT, i pacchetti di risposta possono tornare verso il client finché quella associazione rimane valida.
Anche questo spiega l’utilità dei keepalive.
La dashboard non è il reflector
Altro errore comune.
Apriamo:
https://reflector.example
e vediamo:
- last heard;
- client;
- moduli;
- callsign;
- uptime.
Quella pagina non è necessariamente il reflector stesso.
È una dashboard.
Il backend reflector può essere:
processo C/C++
↓
log/XML/database/stato
↓
dashboard PHP/Go/web
↓
browser
Il progetto ufficiale ref-dash di M17, per esempio, è esplicitamente una dashboard separata progettata per essere utilizzata insieme a mrefd.
Last Heard
Quando arriva una trasmissione il reflector può aggiornare informazioni come:
CALLSIGN
MODULO
ORA
SORGENTE
La dashboard legge questi dati e costruisce il classico:
LAST HEARD
Il Last Heard è quindi principalmente un sistema di reporting.
Non è ciò che trasporta la voce.
Il reflector può anche registrare statistiche
Un Sysop può voler sapere:
quanti client?
quanti stream?
quale modulo?
quanta banda?
quanti pacchetti?
quali errori?
uptime?
Queste informazioni possono essere esportate verso:
- dashboard;
- log;
- Prometheus;
- Grafana;
- sistemi di alert.
A quel punto possiamo trasformare un reflector in un servizio realmente monitorato.
Interlink tra reflector
Supponiamo ora di avere:
REFLECTOR A
e:
REFLECTOR B
Possiamo collegarli.
CLIENT
↓
REF A
↓
INTERLINK
↓
REF B
↓
CLIENT
Il server A diventa, dal punto di vista di B, una sorta di ulteriore endpoint o relay.
Progetti moderni di relay M17 prevedono espressamente gestione sia dei client sia degli interlink tra relay.
Attenzione ai loop
Il problema diventa evidente.
A → B
B → C
C → A
Un pacchetto potrebbe iniziare a circolare.
Serve quindi una logica capace di impedire:
- duplicazioni;
- loop;
- riverberi;
- stream replicati più volte.
Più una rete multiprotocollo diventa grande, più la progettazione del routing diventa importante.
Ecco perché i bridge possono diventare pericolosi
Immaginiamo:
DMR TG 123
↓
YSF ROOM A
↓
M17 MODULE B
↓
DMR TG 123
Abbiamo creato potenzialmente un percorso circolare.
Da qui possono nascere:
- loop audio;
- stream bloccati;
- PTT continuo;
- duplicazioni;
- enorme traffico inutile.
Il Sysop deve quindi disegnare la rete prima di collegare tutto con tutto.
Una buona topologia
Molto meglio:
MASTER/HUB
/ | \
/ | \
DMR M17 YSF
con regole chiare di conversione.
Piuttosto che:
DMR ↔ YSF
↕ ↕
M17 ↔ DSTAR
↖_____↗
senza sapere più chi genera cosa.
Il reflector può avere più processi
In una struttura più complessa potremmo avere:
NGINX / WEB
│
DASHBOARD
│
┌─────┴─────┐
│ REFLECTOR │
└─────┬─────┘
│
TRANSCODER
│
DATABASE/LOG
│
MONITORING
Non è obbligatorio che tutto sia un unico programma.
Anzi, separare le funzioni spesso rende l’infrastruttura più facile da mantenere.
Quanto potente deve essere il server?
Per un piccolo reflector senza transcoding non è necessariamente necessaria una macchina potentissima.
Il lavoro principale consiste infatti spesso nel:
- ricevere pacchetti;
- analizzare piccoli header;
- mantenere stati;
- replicare pacchetti.
Quando introduciamo:
- molti utenti;
- numerosi moduli;
- transcoding;
- dashboard;
- database;
- bridge multiprotocollo;
le esigenze aumentano.
Spesso però il vero requisito critico rimane la qualità della connettività.
Cosa preferire?
Per un reflector serio cercherei:
datacenter affidabile
IP pubblico
buon peering
latenza contenuta
packet loss minimo
banda sufficiente
monitoring
backup
piuttosto che:
64 core CPU
+
connessione instabile
Un digital voice reflector vive di pacchetti.
Se quei pacchetti arrivano male, una CPU enorme non risolve il problema.
Un esempio completo
Seguiamo IZ1ABC.
Premiamo il PTT.
1. IZ1ABC parla
↓
2. La radio codifica la voce
↓
3. Trasmette RF
↓
4. Hotspot/MMDVM riceve
↓
5. Gateway crea i pacchetti di rete
↓
6. Internet trasporta UDP/IP
↓
7. Reflector identifica:
source
stream
module
↓
8. Cerca tutti i client del modulo
↓
9. Replica il frame
↓
10. Ogni gateway riceve la copia
↓
11. Il payload torna verso RF
↓
12. Ogni radio decodifica la voce
Tutto questo avviene in una frazione di secondo.
Se c’è un altro codec
Aggiungiamo:
13. Il client B usa codec differente
allora può entrare in gioco:
TRANSCODER
e il percorso diventa:
codec A
↓
decode
↓
PCM
↓
encode
↓
codec B
È esattamente per questo che dobbiamo distinguere sempre:
reflector
da
transcoder.
Reflector o master server?
Sono concetti che possono sovrapporsi in alcuni ecosistemi ma non sono necessariamente sinonimi.
Un reflector viene tipicamente pensato come una risorsa alla quale più nodi si collegano per condividere un flusso o un modulo.
Un master DMR, per esempio, può implementare logiche più ampie:
- autenticazione;
- routing Talkgroup;
- policy;
- gestione ripetitori;
- networking con altri server.
Il principio della distribuzione dei pacchetti rimane simile, ma l’architettura complessiva può essere molto più sofisticata.
Reflector e Talkgroup non sono la stessa cosa
Anche qui attenzione.
Un:
MODULO A
di un reflector e un:
TG 22215
DMR possono produrre un’esperienza apparentemente simile:
“parlo e tutti quelli collegati mi sentono.”
Ma dal punto di vista tecnico sono concetti appartenenti ad architetture differenti.
Un bridge può associare:
TG 22215
↕
Modulo A
ma quell’associazione è una decisione del gateway/bridge.
Non significa che modulo e Talkgroup siano nativamente la stessa entità.
Un reflector open source è una scuola di networking
Ed è forse questo l’aspetto più bello.
Installare e studiare un reflector permette di imparare contemporaneamente:
- Linux;
- UDP;
- socket;
- NAT;
- DNS;
- firewall;
- protocolli digital voice;
- C/C++;
- routing;
- monitoring;
- cybersecurity.
Progetti come mrefd, M17Gateway, URF e gli strumenti G4KLX sono disponibili come sorgenti e rappresentano un laboratorio formidabile per chi voglia comprendere davvero cosa accade dietro una rete digital voice.
Conclusioni
Quando premiamo il PTT su un hotspot collegato a un reflector, dietro la nostra voce non c’è magia.
C’è una sequenza estremamente precisa:
VOCE
↓
VOCODER
↓
RF
↓
GATEWAY
↓
PACCHETTI IP
↓
REFLECTOR
↓
ROUTING / FAN-OUT
↓
PACCHETTI IP
↓
GATEWAY
↓
RF
↓
VOCODER
↓
VOCE
E solo quando vogliamo mettere in comunicazione sistemi incompatibili aggiungiamo eventualmente:
TRANSCODER
Il reflector quindi non è semplicemente “un server che ripete l’audio”.
È un router specializzato per flussi digital voice, capace di mantenere lo stato dei client e distribuire rapidamente piccoli pacchetti verso decine, centinaia o migliaia di endpoint.
Capire questo significa anche capire perché:
- la latenza conta;
- il packet loss conta;
- il jitter conta;
- una buona connessione conta;
- i loop nei bridge sono pericolosi;
- il transcoding degrada potenzialmente l’audio;
- un server ben progettato può gestire moltissimo traffico con risorse relativamente modeste.
La prossima volta che colleghiamo un hotspot a un reflector possiamo quindi immaginare il vero percorso della nostra voce:
non una voce che attraversa Internet, ma migliaia di piccoli pacchetti che il reflector riceve, riconosce, instrada e moltiplica in tempo reale.
