Test di velocità simultaneo su più modem LTE

Durante la quarantena mi è stato proposto di partecipare allo sviluppo di un dispositivo per misurare la velocità dei modem LTE per diversi operatori di telefonia mobile.

Test di velocità simultaneo su più modem LTE

Il cliente voleva valutare la velocità di vari operatori di telefonia in diversi punti geografici, per capire quale operatore fosse più adatto all'installazione di attrezzature che utilizzano una connessione LTE, ad esempio per le dirette streaming. La sfida doveva essere risolta nel modo più semplice ed economico possibile, senza attrezzature costose.

Dico subito che la sfida non è stata delle più semplici e richiede molto lavoro; parlerò delle problematiche che ho incontrato e di come le ho affrontate. Quindi, iniziamo.

Nota

Misurare la velocità di una connessione LTE è un compito piuttosto complesso: è necessario scegliere correttamente l'attrezzatura e la metodologia di misura, oltre a comprendere bene la topologia e il funzionamento della rete cellulare. Inoltre, la velocità può essere influenzata da diversi fattori: il numero di utenti sulla cella, le condizioni meteorologiche, e anche da cella a cella la velocità può variare notevolmente a causa della topologia della rete. In generale, questa è una sfida con un gran numero di variabili sconosciute, e solo un operatore di telefonia è in grado di risolverla correttamente.

Inizialmente, il cliente voleva semplicemente far correre un corriere con i telefoni degli operatori, eseguendo misurazioni direttamente sui telefoni e registrando poi i risultati su un quaderno. La mia soluzione per misurare la velocità delle reti LTE, sebbene non sia perfetta, raggiunge l'obiettivo prefissato.

A causa della mancanza di tempo, ho preso decisioni che non favorivano la comodità o la praticità, ma la rapidità di sviluppo. Ad esempio, per l'accesso remoto ho impostato un SSH inverso, invece di una VPN più pratica, per risparmiare tempo nella configurazione del server e di ogni singolo client.

Capitolato tecnico

Come riportato nell'articolo Senza specifiche: perché il cliente non le vuole: Non lavorare senza specifiche! Mai, da nessuna parte!

Le specifiche tecniche erano piuttosto semplici, le espanderò un po' per la comprensione dell'utente finale. La scelta delle soluzioni tecniche e dell'attrezzatura è stata dettata dal cliente. Dunque, le specifiche finali, dopo tutte le approvazioni:

Su base di un computer a scheda singola vim2 creare un tester di velocità per la connessione LTE tramite modem Huawei e3372h — 153 diversi operatori di telecomunicazioni (da uno a n). È anche necessario ottenere le coordinate da un ricevitore GPS collegato tramite UART. Non utilizzare il servizio per misurare la velocità www.speedtest.net e raccoglierli in una tabella del tipo:

Test di velocità simultaneo su più modem LTE

Tabella in formato csv. Dopodiché inviare questa tabella tramite email ogni 6 ore. In caso di errori, lampeggiare un LED collegato al GPIO.

Ho descritto il progetto in modo libero, dopo molte approvazioni. Ma il senso del compito è già chiaro. Il termine per tutto era di una settimana. Ma in realtà si è prolungato per tre settimane. Questo considerando che l'ho fatto solo dopo il lavoro principale e nei fine settimana.

Voglio sottolineare ancora una volta che è stato concordato in anticipo con il committente l'uso del servizio di misurazione della velocità e dell'hardware, il che ha limitato notevolmente le mie possibilità. Anche il budget era limitato, quindi non sono stati acquistati particolari elementi. Quindi, ho dovuto seguire queste regole.

Architettura e sviluppo

Lo schema è semplice e ovvio. Pertanto, lo lascerò senza particolari commenti.

Test di velocità simultaneo su più modem LTE

Ho deciso di realizzare l'intero progetto in python, nonostante non avessi alcuna esperienza nello sviluppo in questo linguaggio. L'ho scelto perché c'erano molti esempi e soluzioni pronte che potevano accelerare lo sviluppo. Quindi, chiedo a tutti i programmatori professionisti di non criticare la mia prima esperienza di sviluppo in python e sono sempre felice di ricevere critiche costruttive per migliorare le mie abilità.

Ho anche scoperto che python ha due versioni principali, 2 e 3, e alla fine ho scelto la terza.

Unità hardware

Scheda a una scheda vim2

Come macchina principale mi è stata fornita una scheda a una scheda vim2

Test di velocità simultaneo su più modem LTE

Ottimo, potente media combiner per smart home e SMART-TV, ma raramente adatto per questo compito, o diciamo pure, scarsamente appropriato. Ad esempio, il suo sistema operativo principale è Android, mentre Linux è un sistema operativo secondario, e di conseguenza nessuno garantisce un buon funzionamento di tutti i nodi e driver sotto Linux. E presumo che parte dei problemi fosse legata ai driver USB di questa piattaforma, quindi i modem non funzionavano su questa scheda come previsto. Ha anche una documentazione molto scadente e disgiunta, quindi ogni operazione richiedeva molto tempo per cercare nei documenti. Anche un lavoro banale con GPIO ha richiesto molto impegno. Ad esempio, per impostare il funzionamento con un LED, ho impiegato diverse ore. Tuttavia, per essere obiettivo, non era fondamentale quale single-board computer fosse, l'importante era che funzionasse e avesse porte USB.

Per iniziare, ho bisogno di installare Linux su questa scheda. Per non dover cercare a caso nella documentazione, e anche per chi si cimenterà con questo single-board, scrivo questo capitolo.

Ci sono due opzioni per installare Linux: su una scheda SD esterna o su MMC interna. Ho passato un'intera serata con la scheda e non sono riuscito a farla funzionare, quindi ho deciso di installare su MMC, anche se senza dubbio con la scheda esterna sarebbe stato molto più semplice lavorare.

Su come eseguire il flashing è descritto in modo impreciso qui. Traduco da un linguaggio strano al russo. Per eseguire il flashing della scheda, ho bisogno di connettere un UART hardware. L'ho connesso nel seguente modo.

  • Tool Pin GND: Pin17 del GPIO di VIM
  • Tool Pin TXD: Pin18 del GPIO di VIM (Linux_Rx)
  • Tool Pin RXD: Pin19 del GPIO di VIM (Linux_Tx)
  • Tool Pin VCC: Pin20 del GPIO di VIM

Test di velocità simultaneo su più modem LTE

Dopo di che, ho scaricato il firmware da qui. La versione specifica del firmware VIM1_Ubuntu-server-bionic_Linux-4.9_arm64_EMMC_V20191231.

Per caricare questo firmware, ho bisogno di alcune utility. Maggiori dettagli sono forniti qui. Non ho provato a eseguire il flashing sotto Windows, ma devo dire qualche parola sul flashing sotto Linux. Prima di tutto, installerò le utility seguendo le istruzioni.

git clone https://github.com/khadas/utils
cd /path/to/utils
sudo ./INSTALL

E... niente funziona. Ho speso un paio d'ore a modificare gli script di installazione affinché si installassero correttamente. Non ricordo esattamente cosa ho fatto, ma è stato un vero circo. Quindi siate cauti. Ma senza queste utility non ha senso continuare a lavorare con vim2. Meglio non averci a che fare!

Dopo sette cerchi dell'inferno, configurazioni degli script e installazioni ho ottenuto un pacchetto di utility funzionanti. Ho collegato la scheda tramite USB al mio computer Linux, e ho anche collegato l'UART secondo lo schema sopra.
Sto configurando il mio terminale preferito minicom a una velocità di 115200, senza controllo degli errori hardware o software. E iniziamo.

Test di velocità simultaneo su più modem LTE

All'avvio di VIM2 nel terminale UART premo un qualsiasi tasto, ad esempio la barra spaziatrice, per fermare il caricamento. Dopo che appare la riga

kvim2# 

Inserisco il comando:

kvim2# run update

Sull'host da cui stiamo caricando, eseguo:

burn-tool -v aml -b VIM2 -i VIM2_Ubuntu-server-bionic_Linux-4.9_arm64_EMMC_V20191231.img

Tutto, uff. Ho flashato, sulla scheda c'è Linux. Login/password khadas:khadas.

Dopo ciò, alcune piccole impostazioni iniziali. Per un utilizzo successivo disabilito la password per sudo (sì, non è sicuro, ma è comodo).

sudo visudo

Modifico la riga fino a questo formato e salviamo

# Allow members of group sudo to execute any command
%sudo ALL=(ALL:ALL) NOPASSWD: ALL

Dopodiché cambio la località attuale, affinché l'orario sia quello di Mosca, altrimenti sarà quello di Greenwich.

sudo timedatectl set-timezone Europe/Moscow

oppure

ln -s /usr/share/zoneinfo/Europe/Moscow /etc/localtime

Se ti sembra complicato, allora non utilizzare questa scheda, meglio un Raspberry Pi. Onestamente.

Modem Huawei e3372h — 153

Questo modem mi ha dato un bel po' di problemi, e in effetti è diventato il collo di bottiglia dell'intero progetto. In realtà, il termine 'modem' per questi dispositivi non riflette affatto la loro funzionalità: si tratta di un potente combinatore, questo dispositivo ha un'unità composta, che si finge CD-ROM per installare i driver, e poi passa in modalità scheda di rete.

Architettonicamente, dal punto di vista dell'utente Linux dopo tutte le impostazioni, appare così: dopo aver collegato il modem, mi appare l'interfaccia di rete eth*, che tramite DHCP riceve l'indirizzo IP 192.168.8.100, e il gateway predefinito 192.168.8.1.

E il punto principale! Questo modello di modem non sa funzionare in modalità modem, controllato dai comandi AT.. Sarebbe stato molto più semplice creare connessioni PPP per ogni modem e poi operare con esse. Ma nel mio caso il 'può' (piuttosto i driver Linux secondo le regole udev) crea un'interfaccia eth e per DHCP le assegna un indirizzo IP.

Per non confonderci ulteriormente, propongo di dimenticare la parola 'modem' e parlare di scheda di rete e gateway, perché in effetti, è come collegare una nuova scheda di rete con un gateway.
Quando c'è un solo modem, non ci sono problemi particolari, ma quando ce ne sono più di uno, vale a dire n pezzi, si presenta il seguente quadro di rete.

Test di velocità simultaneo su più modem LTE

Cioè n schede di rete, con un solo indirizzo IP, con lo stesso gateway predefinito per ognuna. Ma di fatto, ognuna di esse è collegata al proprio operatore.

Inizialmente avevo una soluzione semplice: utilizzare il comando ifconfig o ip per disattivare tutte le interfacce e accenderle una alla volta per testarle. La soluzione andava bene, ma durante i passaggi non avevo la possibilità di connettermi al dispositivo. E poiché i passaggi erano frequenti e rapidi, in effetti non riuscivo a connettermi affatto.

Pertanto ho scelto di cambiare gli indirizzi IP dei modem "manualmente" e poi instradare il traffico tramite le impostazioni di routing.

Test di velocità simultaneo su più modem LTE

Così i miei problemi con i modem non sono finiti: in caso di problemi di alimentazione, si scollegavano, era necessaria una buona alimentazione stabile per l'hub USB. Ho risolto questo problema saldando l'alimentazione direttamente all'hub. Un altro problema che ho affrontato e che ha rovinato l'intero progetto è stato che dopo un riavvio o un avvio a freddo non venivano riconosciuti tutti i modem, e non sempre, e non sono riuscito a capire perché e secondo quale algoritmo ciò accadesse. Ma andiamo con ordine.

Per un corretto funzionamento del modem, ho installato il pacchetto usb-modeswitch.

sudo apt update
sudo apt install -y usb-modeswitch

Dopo di che, il modem verrà correttamente riconosciuto e configurato dal sottosistema udev. Controllo semplicemente collegando il modem e assicurandomi che la rete sia apparsa.
Un altro problema che non sono riuscito a risolvere: come ottenere il nome dell'operatore dal modem con cui lavoriamo? Il nome dell'operatore è presente nell'interfaccia web del modem all'indirizzo 192.168.8.1. Si tratta di una pagina web dinamica che ottiene i dati tramite richieste ajax, quindi non è possibile semplicemente usare wget per scaricare la pagina e analizzare il nome. Così ho iniziato a esplorare come gestire la pagina web ecc., e ho capito che stavo facendo qualcosa di assurdo. Alla fine ho desistito e ho iniziato a ottenere il nome dell'operatore tramite l'API di Speedtest.

Molte cose sarebbero state più semplici se il modem avesse avuto accesso tramite comandi AT. Si sarebbe potuto riconfigurare, creare una connessione ppp, assegnare un IP, ottenere il nome dell'operatore, ecc. Ma purtroppo, lavoro con quello che mi è stato dato.

GPS

Il ricevitore GPS che mi è stato fornito aveva un'interfaccia UART e alimentazione. Non era la soluzione migliore, ma comunque funzionante e semplice. Il ricevitore aveva un aspetto simile a questo.

Test di velocità simultaneo su più modem LTE

A dire il vero, è la prima volta che lavoro con un ricevitore GPS, ma come immaginavo, hanno già pensato a tutto per noi. Quindi, utilizziamo semplicemente soluzioni pronte.

Per cominciare, attivo uart_AO_B (UART_RX_AO_B, UART_TX_AO_B) per collegare il GPS.

khadas@Khadas:~$ sudo fdtput -t s /dtb.img /serial@c81004e0 status okay

Dopo verifico il successo dell'operazione.

khadas@Khadas:~$ fdtget /dtb.img /serial@c81004e0 status
okay

Questo comando, a quanto pare, modifica il devtree al volo, il che è molto comodo.

Dopo il successo di questa operazione, riavviamo e installiamo il demone GPS.

khadas@Khadas:~$ sudo reboot

Installazione del demone GPS. Installo tutto e lo spengo immediatamente per una configurazione successiva.

sudo apt install gpsd gpsd-clients -y
sudo killall gpsd
 
/* Fermare/disabilitare il demone GPS */
sudo systemctl stop gpsd.socket
sudo systemctl disable gpsd.socket

Modifico il file di configurazione.

sudo vim /etc/default/gpsd

Imposto la UART su cui sarà collegato il GPS.

DEVICES="/dev/ttyS4"

E poi accendiamo tutto e avviamo.

/* GPS daemon enable/start */
sudo systemctl enable gpsd.socket
sudo systemctl start gpsd.socket

Successivamente, collego il GPS.

Test di velocità simultaneo su più modem LTE

Nelle mani ho il cavo GPS, sotto le dita si vedono i fili UART del debugger.

Riavvio e controllo il funzionamento del GPS utilizzando il programma gpsmon.

Test di velocità simultaneo su più modem LTE

In questo screenshot non ci sono satelliti visibili, ma è evidente la comunicazione con il ricevitore GPS, e questo indica che tutto va bene.

Ho testato molte opzioni per lavorare con questo demone in Python, ma mi sono fermato su quella che funzionava correttamente con Python 3.

Installo la libreria necessaria.

sudo -H pip3 install gps3 

E scrivo il codice di funzionamento.

from gps3.agps3threaded import AGPS3mechanism
...
def getPositionData(agps_thread):
	counter = 0;
	while True:
		longitude = agps_thread.data_stream.lon
		latitude = agps_thread.data_stream.lat
		if latitude != 'n/a' and longitude != 'n/a':
			return '{}' .format(longitude), '{}' .format(latitude)
		counter = counter + 1
		print ("Aspetta gps contatore = %d" % counter)
		if counter == 10:
			ErrorMessage("Errore del ricevitore GPS!!!")
			return "NA", "NA"
		time.sleep(1.0)
...
f __name__ == '__main__':
...	#gps
	agps_thread = AGPS3mechanism()  # Instanzia i meccanismi AGPS3
	agps_thread.stream_data()  # Da localhost (), o altri host, ad esempio, (host='gps.ddns.net')
	agps_thread.run_thread()  # Tempo di throttling per dormire dopo un lookup vuoto, di default '()' 0.2 due decimi di secondo

Se ho bisogno di ottenere le coordinate, lo faccio con la seguente chiamata:

longitude, latitude = getPositionData(agps_thread)

E in 1-10 secondi riceverò o le coordinate o non le riceverò. Sì, ho fatto dieci tentativi per ottenere le coordinate. Non è ottimale, è un po' impreciso, ma funziona. Ho deciso di procedere in questo modo perché il GPS può ricevere male e non ottenere sempre i dati. Se aspettassi di ricevere i dati, in caso di lavoro in un ambiente chiuso, il programma si bloccherebbe in quel punto. Per questo ho implementato una soluzione non elegante.

In linea di principio, se avessi avuto più tempo, avrei potuto ricevere i dati dal GPS direttamente tramite UART, analizzarli in un thread separato e lavorarci. Ma non avevo tempo del tutto, ecco perché il codice è brutto e complicato. E sì, non mi vergogno.

LED

Collegare il LED è stato semplice ma complicato allo stesso tempo. La difficoltà principale è che il numero del pin nel sistema non corrisponde al numero del pin sulla scheda e perché la documentazione è scritta in modo incomprensibile. Per abbinare il numero del pin hardware e il numero del pin nel sistema operativo, è necessario eseguire il comando:

gpio readall

Verrà visualizzata una tabella di corrispondenza tra il pin nel sistema e sulla scheda. Dopo di che posso già lavorare con il pin nel sistema operativo. Nel mio caso, il LED è collegato a GPIOH_5.

Test di velocità simultaneo su più modem LTE

Imposto il pin GPIO in modalità uscita.

gpio -g mode 421 out

Scrivo zero.

gpio -g write 421 0

Scrivo uno.

gpio -g write 421 1

Test di velocità simultaneo su più modem LTE
Tutto si accende dopo aver scritto '1'.

#gpio subsistem
def gpio_init():
	os.system("gpio -g mode 421 out")
	os.system("gpio -g write 421 1")

def gpio_set(val):
	os.system("gpio -g write 421 %d" % val)
	
def error_blink():
	gpio_set(0)
	time.sleep(0.1)
	gpio_set(1)
	time.sleep(0.1)
	gpio_set(0)
	time.sleep(0.1)
	gpio_set(1)
	time.sleep(0.1)
	gpio_set(0)
	time.sleep(1.0)
	gpio_set(1)

def good_blink():
	gpio_set(1)

Ora, in caso di errori, chiamo error_blink() e il LED lampeggia in modo carino.

Moduli software

API Speedtest

È una grande gioia che il servizio speedtest.net abbia una sua propria API python, che può essere consultata su Github.

Il bello è che ci sono i codici sorgente che possono essere consultati. Come lavorare con questa API (esempi semplici) può essere visto nella sezione corrispondente.

Installo la libreria python con il seguente comando.

sudo -H pip3 install speedtest-cli

Per esempio, puoi anche installare Speedtest in Ubuntu direttamente dai repository. È la stessa applicazione python, che poi può essere eseguita direttamente dalla console.

sudo apt install speedtest-cli -y

E misurare la velocità della tua connessione.

speedtest-cli
Recupero della configurazione di speedtest.net...
Test in corso da B***** (*.*.*.*)...
Recupero dell'elenco dei server speedtest.net...
Selezione del miglior server in base al ping...
Ospitato da MTS (Mosca) [0.12 km]: 11.8 ms
Test della velocità di download................................................................................
Download: 7.10 Mbit/s
Test della velocità di upload......................................................................................................
Upload: 3.86 Mbit/s

Di conseguenza, come l'ho fatto io. Ho dovuto entrare nei codici sorgente di questo Speedtest per integrarli meglio nel mio progetto. Una delle principali sfide è raccogliere anche il nome dell'operatore telefonico, per inserirlo nella tabella.

import speedtest
from datetime import datetime
...
# Indica un server specifico per il test
#6053) MaximaTelecom (Mosca, Federazione Russa)
servers = ["6053"]
# Se vuoi utilizzare un test a thread singolo
threads = None
s = speedtest.Speedtest()
# otteniamo il nome dell'operatore di telefonia mobile
opos = '%(isp)s' % s.config['client']
s.get_servers(servers)
# otteniamo una stringa testuale con i parametri del server
testserver = '%(sponsor)s (%(name)s) [%(d)0.2f km]: %(latency)s ms' % s.results.server
# test di download
s.download(threads=threads)
# test di upload
s.upload(threads=threads)
# otteniamo i risultati
s.results.share()

# Dopodiché si forma una stringa per la registrazione in un file csv.
# otteniamo la posizione GPS
longitude, latitude = getPositionData(agps_thread)
# ora e data
curdata = datetime.now().strftime('%d.%m.%Y')
curtime = datetime.now().strftime('%H:%M:%S')
delimiter = ';'
result_string = opos + delimiter + str(curpos) + delimiter + 
	curdata + delimiter + curtime + delimiter + longitude + ', ' + latitude + delimiter + 
	str(s.results.download/1000.0/1000.0) + delimiter + str(s.results.upload / 1000.0 / 1000.0) + 
	delimiter + str(s.results.ping) + delimiter + testserver + "n"
# qui si procede con la scrittura nel file di log

Qui si è rivelato tutto meno semplice del previsto, anche se, sembrerebbe, potrebbe essere più semplice. Inizialmente il parametro servers era impostato su [], ovvero scegli il server migliore. Di conseguenza, avevo server casuali e, come è facile immaginare, una velocità fluttuante. È un tema piuttosto complesso, usare un server fisso, se sì, allora statico o dinamico, richiede una certa ricerca. Ma ecco un esempio di grafici delle misurazioni della velocità dell'operatore Beeline con scelta dinamica del server di test e uno staticamente fissato.

Test di velocità simultaneo su più modem LTE
Risultato della misurazione della velocità con selezione di un server dinamico.

Test di velocità simultaneo su più modem LTE
Risultato del test di velocità, con un server scelto rigorosamente.

La "povere" durante i test è presente sia lì che là, e deve essere rimossa con metodi matematici. Ma con un server fisso ce n'è un po' meno e l'ampiezza è più stabile.
In realtà, questo è un campo di grandi ricerche. E io avrei condotto misurazioni della velocità verso il mio server utilizzando l'utility iperf. Ma noi seguiamo le specifiche.

Invio di posta e errori

Per l'invio di posta ho provato diverse decine di opzioni, ma alla fine mi sono fermato su quella seguente. Ho registrato un'email su yandex e poi ho preso questo esempio di invio di posta. L'ho testato e implementato nel programma. In questo esempio si analizzano diverse opzioni, inclusa l'invio da gmail, ecc. Non avevo voglia di mettermi a gestire il mio server di posta e non avevo tempo per questo, ma si è rivelato essere uno spreco di tempo.

Ho inviato i log tramite il pianificatore, in presenza di connessione, ogni 6 ore: alle 00, 06, 12 e 18. Inviavo nel seguente modo.

from send_email import *
...
message_log = "Log di test della scheda n. 1"
EmailForSend = ["dlinyj@trololo.ru", "pupkin@trololo.ru"]
files = ["/home/khadas/modems_speedtest/csv"]
...
def sendLogs():
	global EmailForSend
	curdata = datetime.now().strftime('%d.%m.%Y')
	сurtime = datetime.now().strftime('%H:%M:%S')
	try:
		for addr_to in EmailForSend:
			send_email(addr_to, message_log, "Log per " + curdata + " " + сurtime, files)
	except:
		print("Problema di rete durante l'invio dell'email")
		return False
	return True

Gli errori venivano inizialmente inviati. Inizialmente si accumulavano in una lista, e poi li inviavo anche tramite il pianificatore, in presenza di connessione. Tuttavia, in seguito si sono presentati problemi con il fatto che yandex ha una limitazione sul numero di messaggi inviati al giorno (è un dolore, un dispiacere e una vergogna). Poiché gli errori potevano essere numerosi anche in un solo minuto, ho dovuto rinunciare all'invio degli errori via email. Quindi tieni presente che, durante l'invio automatico tramite i servizi di yandex, esiste questo problema.

Server di feedback

Per avere accesso all'hardware remoto e poterlo riconfigurare e ristrutturare, avevo bisogno di un server esterno. In effetti, per essere giusti, sarebbe stato corretto inviare tutti i dati a un server e costruire tutte le belle grafiche nell'interfaccia web. Ma non si può avere tutto subito.

Come VPS ho scelto ruvds.com. Si sarebbe potuto prendere un server molto semplice. In generale, per i miei scopi sarebbe stato più che sufficiente. Ma poiché pagavo il server non di tasca mia, ho deciso di prenderne uno con un piccolo margine, per essere coperti nel caso avessimo sviluppato un'interfaccia web, un proprio server SMTP, VPN, ecc. Inoltre, avere la possibilità di configurare un bot Telegram e non avere problemi con le sue restrizioni. Perciò ho scelto Amsterdam e i seguenti parametri.

Test di velocità simultaneo su più modem LTE

Come metodo di connessione con l'hardware vim2, ho scelto una connessione SSH inversa e, come ha dimostrato la pratica, non è stata la migliore. In caso di interruzione della connessione, il server mantiene la porta e non è possibile connettersi per un certo periodo. Quindi, è comunque meglio utilizzare altri metodi di connessione, come la VPN. In futuro, volevo passare alla VPN, ma non ci sono riuscito.

Non entrerò nei dettagli della configurazione del firewall, delle limitazioni dei diritti, della disattivazione della connessione ssh per root e altre banalità nella configurazione di un VPS. Spero che sappiate già tutto. Per la connessione remota, creo un nuovo utente sul server.

adduser vimssh

Generando le chiavi di connessione ssh sulla nostra macchina.

ssh-keygen

E le copio sul nostro server.

ssh-copy-id vimssh@host.com

Sulla nostra macchina creo una connessione automatica back ssh all'avvio.

[Unit]
Descrizione=Auto Reverse SSH
Richiede=systemd-networkd-wait-online.service
Dopo=systemd-networkd-wait-online.service
[Service]
Utente=khadas
ExecStart=/usr/bin/ssh -NT -o ExitOnForwardFailure=yes -o ServerAliveInterval=60 -CD 8080 -R 8083:localhost:22 vimssh@host.com
RestartSec=5
Restart=always
[Install]
WantedBy=multi-user.target

Fate attenzione alla porta 8083: è quella che determina la porta per la connessione tramite back ssh. Aggiungiamo all'avvio automatico e partiamo.

sudo systemctl enable autossh.service
sudo systemctl start autossh.service

Possiamo anche controllare lo stato:

sudo systemctl status autossh.service

Ora, sul nostro server VPS, se eseguiamo:

ssh -p 8083 khadas@localhost

Vengo indirizzato alla mia macchina di test. E da lì posso anche inviare registri e qualsiasi dato via ssh al mio server, il che è molto comodo.

Mettiamo tutto insieme

Test di velocità simultaneo su più modem LTE
Inizio, procediamo con lo sviluppo e il debug

Uff, bene, sembra che abbia descritto tutti i nodi. Ora è il momento di raccogliere tutto in un'unica soluzione. Puoi visualizzare il codice qui.

Un aspetto importante del codice: questo progetto potrebbe non avviarsi così «com'è», poiché è stato progettato per uno specifico compito, in una specifica architettura. Anche se fornisco i sorgenti, comunque il più prezioso lo discuterò qui, nel testo, altrimenti risulterebbe completamente incomprensibile.

All'inizio vanno l'inizializzazione gps, gpio e l'avvio di un thread separato per il pianificatore.

#запуск потока планировщика
pShedulerThread = threading.Thread(target=ShedulerThread, args=(1,))
pShedulerThread.start()

Il pianificatore è piuttosto semplice: controlla se è il momento di inviare i messaggi e qual è lo stato attuale degli errori. Se c'è un flag di errore, lampeggiamo il LED.

#sheduler
def ShedulerThread(name):
	global ready_to_send
	while True:
		d = datetime.today()
		time_x = d.strftime('%H:%M')
		if time_x in time_send_csv:
			ready_to_send = True
		if error_status:
			error_blink()
		else:
			good_blink()
		time.sleep(1)

Il momento più complesso di questo progetto è mantenere la connessione ssh inversa attiva ad ogni test. In ogni test, si configura nuovamente il gateway predefinito e il server dns. Poiché tanto nessuno legge, sappiate che il treno non corre su rotaie di legno. Chi troverà l'uovo di Pasqua, avrà una caramella.

Per questo creo una tabella di routing separata —set-mark 0x2 e una regola per il reindirizzamento del traffico.

def InitRouteForSSH():
	cmd_run("sudo iptables -t mangle -A OUTPUT -p tcp -m tcp --dport 22 -j MARK --set-mark 0x2")
	cmd_run("sudo ip rule add fwmark 0x2/0x2 lookup 102")

Per ulteriori dettagli su come funziona, puoi leggere questo articolo.

Dopo di che, passo a un ciclo infinito, dove ogni volta otteniamo un elenco dei modem connessi (per sapere se la configurazione della rete è cambiata).

network_list = getNetworklist()

Ottenere l'elenco delle interfacce di rete è abbastanza semplice.

def getNetworklist():
	full_networklist = os.listdir('/sys/class/net/')
	network_list = [x for x in full_networklist if "eth" in x and x != "eth0"]
	return network_list

Dopo aver ottenuto l'elenco, assegno gli indirizzi IP a tutte le interfacce, come mostrato nell'immagine del capitolo sul modem.

SetIpAllNetwork(network_list)

def SetIpAllNetwork(network_list):
	for iface in network_list:
		lastip = "%d" % (3 + network_list.index(iface))
		cmd_run ("sudo ifconfig " + iface + " 192.168.8." + lastip + " up")

Poi semplicemente, in un ciclo, attraversiamo ogni interfaccia. E configuriamo ogni interfaccia.

	for iface in network_list:
		ConfigNetwork(iface)

def ConfigNetwork(iface):
#ripristiniamo tutte le impostazioni
		cmd_run("sudo ip route flush all")
#Assegniamo il gateway predefinito
		cmd_run("sudo route add default gw 192.168.8.1 " + iface)
#impostiamo il server DNS (questo è necessario per il funzionamento di speedtest)
		cmd_run ("sudo bash -c 'echo nameserver 8.8.8.8 > /etc/resolv.conf'")

Controllo l'interfaccia per verificarne il funzionamento; se non c'è rete, genero errori. Se la rete è presente, è tempo di agire!

Qui configuro il routing ssh per questa interfaccia (se non è stato fatto), invio errori al server, se il momento è arrivato, invio i log e alla fine eseguo speedtest e salvo i log in un file csv.

if not NetworkAvalible():
....
#Qui generiamo errori
....
else: #C'è rete, evviva, lavoriamo!
#Se abbiamo un'interfaccia problematica su cui è presente ssh, la cambiamo
  if (sshint == lastbanint or sshint == "free"):
    print("********** Setup SSH ********************")
    if sshint != "free":
      cmd_run("sudo ip route del default via 192.168.8.1 dev " + sshint + " table 102")
    SetupReverseSSH(iface)
    sshint = iface
#Poiché la rete funziona, spediamo tutto il prima possibile!!!
    if ready_to_send:
      print ("**** Pronto per inviare!!!")
        if sendLogs():
          ready_to_send = False
        if error_status:
          SendErrors()
#e poi testiamo la velocità e salviamo i log. 

Si può dire qualcosa sulla funzione di configurazione del reverse ssh.

def SetupReverseSSH(iface):
	cmd_run("sudo systemctl stop autossh.service")
	cmd_run("sudo ip route add default via 192.168.8.1 dev " + iface + " table 102")
	cmd_run("sudo systemctl start autossh.service")

E ovviamente, è necessario aggiungere tutta questa bellezza all'avvio automatico. Per questo creo un file:

sudo vim /etc/systemd/system/modems_speedtest.service

E ci scrivo dentro:

[Unit]
Descrizione=Test di Velocità del Modem
Richiede=systemd-networkd-wait-online.service
Dopo=systemd-networkd-wait-online.service
[Service]
Utente=khadas
ExecStart=\/usr\/bin\/python3.6 \/home\/khadas\/modems_speedtest\/networks.py
RestartSec=5
Restart=always
[Install]
WantedBy=multi-user.target

Attivo l'avvio automatico e lo avvio!

sudo systemctl enable modems_speedtest.service
sudo systemctl start modems_speedtest.service

Ora posso controllare i log di quello che succede con il comando:

journalctl -u modems_speedtest.service --no-pager -f

Risultati

Beh, ora la cosa più importante: cosa è risultato alla fine? Presento alcuni grafici che sono riuscito a catturare durante il processo di sviluppo e debug. I grafici sono stati realizzati con gnuplot usando il seguente script.

#! /usr/bin/gnuplot -persist
set terminal postscript eps enhanced color solid
set output "Rostelecom.ps"
 
#set terminal png size 1024, 768
#set output "Rostelecom.png"
 
set datafile separator ';'
set grid xtics ytics
set xdata time
set ylabel "Speed Mb/s"
set xlabel 'Time'
set timefmt '%d.%m.%Y;%H:%M:%S'
set title "Rostelecom Speed"

plot "Rostelecom.csv" using 3:6 with lines title "Download", '' using 3:7 with lines title "Upload"
 
set title "Rostelecom 2 Ping"
set ylabel "Ping ms"
plot "Rostelecom.csv" using 3:8 with lines title "Ping"

La prima esperienza è stata con l'operatore Tele2, che ho condotto per diversi giorni.

Test di velocità simultaneo su più modem LTE

Qui ho utilizzato un server di misurazione dinamico. Le misurazioni della velocità funzionano, ma variano molto, tuttavia è visibile una certa media, che può essere ottenuta filtrando i dati, ad esempio usando la media mobile.

In seguito ho creato altri grafici per altri operatori di telecomunicazioni. In questo caso, il server di test era unico e anche i risultati sono molto interessanti.

Test di velocità simultaneo su più modem LTE

Test di velocità simultaneo su più modem LTE

Test di velocità simultaneo su più modem LTE

Test di velocità simultaneo su più modem LTE

Come si può vedere, l'argomento è molto ampio per ricerche e per l'elaborazione di questi dati, e chiaramente non possiamo pensare che bastino un paio di settimane di lavoro. Ma...

Risultato del lavoro

Il lavoro è stato bruscamente interrotto per motivi indipendenti dalla mia volontà. Una delle debolezze di questo progetto, dal mio punto di vista, era il modem, che non voleva funzionare bene insieme ad altri modem, e ad ogni avvio mostrava questi problemi. Per queste esigenze ci sono molte altre modelli di modem, che di solito hanno un formato Mini PCI-e e vengono installati all'interno del dispositivo, ed è molto più semplice configurarli. Ma questa è un'altra storia. Il progetto era interessante e sono stato molto felice di aver avuto l'opportunità di partecipare.

Test di velocità simultaneo su più modem LTE

Fonte: habr.com

Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server 🔥 Acquista hosting affidabile per siti web con protezione DDoS, VPS VDS server | ProHoster