Prueba de velocidad simultánea en varios módems LTE

Durante la cuarentena, me ofrecieron participar en el desarrollo de un dispositivo para medir la velocidad de los módems LTE para varios operadores de telefonía móvil.

Prueba de velocidad simultánea en varios módems LTE

El cliente quería evaluar la velocidad de varios operadores de telecomunicaciones en diferentes ubicaciones geográficas para poder entender qué operador celular era el más óptimo para él al instalar equipos que utilizan una conexión LTE, por ejemplo, para transmisiones de video. Al mismo tiempo, el problema debía resolverse de la forma más sencilla y económica posible, sin necesidad de equipos costosos.

Diré de inmediato que la tarea no es la más simple ni la que requiere más conocimientos, les diré qué problemas encontré y cómo los resolví. Entonces vamos.

Nota

Medir la velocidad de una conexión LTE es una cuestión muy compleja: es necesario elegir el equipo y la técnica de medición adecuados, así como tener un buen conocimiento de la topología y el funcionamiento de la red celular. Además, la velocidad puede verse influenciada por varios factores: el número de suscriptores en un celular, las condiciones climáticas, incluso de un celular a otro la velocidad puede variar dramáticamente debido a la topología de la red. En general, se trata de un problema con una gran cantidad de incógnitas y sólo un operador de telecomunicaciones puede resolverlo correctamente.

Al principio, el cliente sólo quería conducir el mensajero con los teléfonos de los operadores, tomar medidas directamente en el teléfono y luego anotar los resultados de la medición de velocidad en una libreta. Mi solución para medir la velocidad de las redes LTE, aunque no es ideal, resuelve el problema.

Por falta de tiempo, tomé decisiones no por conveniencia o practicidad, sino por la velocidad de desarrollo. Por ejemplo, se utilizó ssh inverso para el acceso remoto, en lugar de la más práctica VPN, para ahorrar tiempo en la configuración del servidor y de cada cliente individual.

Términos de referencia

Como dice el articulo Sin especificaciones técnicas: por qué el cliente no lo quiere: ¡No trabajes sin especificaciones técnicas! ¡Nunca, en ningún lado!

La tarea técnica fue bastante sencilla, la ampliaré un poco para la comprensión del usuario final. La elección de las soluciones técnicas y del equipamiento fue dictada por el cliente. Entonces, la especificación técnica en sí, después de todas las aprobaciones:

Basado en una computadora de placa única vim2 hacer un probador de velocidad para conexiones lte a través de módems HHuawei e3372h - 153 varios operadores de telecomunicaciones (de uno a n). También es necesario recibir coordenadas de un receptor GPS conectado vía UART. Realice mediciones de velocidad utilizando el servicio. www.speedtest.net y ponerlos en una mesa como:

Prueba de velocidad simultánea en varios módems LTE

Tabla en formato csv. Luego envíe este cartel por correo electrónico cada 6 horas. En caso de errores, haga parpadear el LED que está conectado al GPIO.

Describí las especificaciones técnicas de forma libre, después de muchas aprobaciones. Pero el significado de la tarea ya es visible. Se dio una semana para todo. Pero en realidad duró tres semanas. Esto teniendo en cuenta el hecho de que lo hacía sólo después de mi trabajo principal y los fines de semana.

Aquí quiero llamar la atención una vez más sobre el hecho de que el cliente acordó de antemano el uso del servicio y el hardware de medición de velocidad, lo que limitó en gran medida mis capacidades. El presupuesto también era limitado, por lo que no se compró nada especial. Así que teníamos que seguir estas reglas.

Arquitectura y desarrollo

El esquema es simple y obvio. Por tanto, lo dejaré sin ningún comentario especial.

Prueba de velocidad simultánea en varios módems LTE

Decidí implementar todo el proyecto en Python, a pesar de que no tenía ninguna experiencia desarrollando en este lenguaje. Lo elegí porque había muchos ejemplos y soluciones ya preparados que podrían acelerar el desarrollo. Por lo tanto, pido a todos los programadores profesionales que no regañen mi primera experiencia de desarrollo en Python, y siempre me alegra escuchar críticas constructivas para mejorar mis habilidades.

También en el proceso descubrí que Python tiene dos versiones en ejecución, 2 y 3, como resultado me decidí por la tercera.

Nodos de hardware

vim2 de placa única

Me dieron una computadora de placa única como mi máquina principal. vim2

Prueba de velocidad simultánea en varios módems LTE

Un excelente y potente procesador multimedia para hogares inteligentes y SMART-TV, pero extremadamente inadecuado para esta tarea o, digamos, poco adecuado. Por ejemplo, su sistema operativo principal es Android y Linux es un sistema operativo secundario y, en consecuencia, nadie garantiza el funcionamiento de alta calidad de todos los nodos y controladores en Linux. Y supongo que algunos de los problemas estaban relacionados con los controladores USB de esta plataforma, por lo que los módems no funcionaron como se esperaba en esta placa. Además tiene documentación muy pobre y dispersa, por lo que cada operación requirió mucho tiempo excavando en los muelles. Incluso el trabajo normal con GPIO requirió mucha sangre. Por ejemplo, me llevó varias horas configurar el LED. Pero, para ser objetivo, en principio no importaba qué tipo de placa única fuera, lo principal era que funcionara y que hubiera puertos USB.

Primero, necesito instalar Linux en esta placa. Para no buscar documentación para todos, y también para aquellos que se ocuparán de este sistema de placa única, estoy escribiendo este capítulo.

Hay dos opciones para instalar Linux: en una tarjeta SD externa o en una MMC interna. Estuve una tarde intentando descubrir cómo hacer que funcionara con la tarjeta, así que decidí instalarla en la MMC, aunque sin duda sería mucho más fácil trabajar con una tarjeta externa.

Acerca del firmware dicho torcidamente aquí. Traduzco del extraño al ruso. Para flashear la placa, necesito conectar el hardware UART. Lo conecté como sigue.

  • Pin de herramienta GND: <—> Pin17 del GPIO de VIM
  • Pin de herramienta TXD: <—> Pin18 del GPIO de VIM (Linux_Rx)
  • Pin de herramienta RXD: <—> Pin19 del GPIO de VIM (Linux_Tx)
  • Pin de herramienta VCC: <—> Pin20 del GPIO de VIM

Prueba de velocidad simultánea en varios módems LTE

Después de lo cual, descargué el firmware. por lo tanto. Versión de firmware específica VIM1_Ubuntu-server-bionic_Linux-4.9_arm64_EMMC_V20191231.

Para cargar este firmware, necesito utilidades. Más detalles sobre esto aquí. No he intentado actualizarlo en Windows, pero necesito contarles algunas palabras sobre el firmware en Linux. Primero, instalaré las utilidades según las instrucciones.

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

Y... Nada funciona. Pasé un par de horas editando los scripts de instalación para que todo se instalara correctamente. No recuerdo qué hice allí, pero también estaba ese circo con caballos. Así que ten cuidado. Pero sin estas utilidades no tiene sentido torturar más a vim2. ¡Es mejor no meterse con él en absoluto!

Después de siete círculos del infierno, configuración e instalación del script, recibí un paquete de utilidades que funcionan. Conecté la placa vía USB a mi computadora Linux y también conecté el UART de acuerdo con el diagrama anterior.
Estoy configurando mi terminal minicom favorito para una velocidad de 115200, sin control de errores de hardware ni software. Y comencemos.

Prueba de velocidad simultánea en varios módems LTE

Al cargar VIM2 en la terminal UART, presiono una tecla, como la barra espaciadora, para detener la carga. Después de que aparezca la línea

kvim2# 

Ingreso el comando:

kvim2# run update

En el host desde el que estamos cargando ejecuto:

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

Eso es todo, uf. Lo comprobé, hay Linux en la placa. Inicio de sesión/contraseña khadas:khadas.

Después de eso, algunas configuraciones iniciales menores. Para seguir trabajando, desactivo la contraseña de sudo (sí, no es segura, pero sí conveniente).

sudo visudo

Edito la línea al formulario y guardo.

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

Luego cambio la ubicación actual para que la hora sea en Moscú; de lo contrario, será en Greenwich.

sudo timedatectl set-timezone Europe/Moscow

o

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

Si te resulta difícil, no utilices esta placa; Raspberry Pi es mejor. Honestamente.

Módem Huawei e3372h – 153

Este módem fue una importante fuente de sangre para mí y, de hecho, se convirtió en el cuello de botella de todo el proyecto. En general, el nombre "módem" para estos dispositivos no refleja en absoluto la esencia del trabajo: se trata de una cosechadora potente, esta pieza de hardware tiene un dispositivo compuesto que se hace pasar por un CD-ROM para instalar los controladores, y luego cambia al modo de tarjeta de red.

Arquitectónicamente, desde el punto de vista de un usuario de Linux, después de todas las configuraciones, se ve así: después de conectar el módem, tengo una interfaz de red eth*, que a través de dhcp recibe la dirección IP 192.168.8.100 y la puerta de enlace predeterminada es 192.168.8.1.

¡Y el momento más importante! Este modelo de módem no puede funcionar en modo módem, que está controlado por comandos AT. Todo sería mucho más sencillo, crear conexiones PPP para cada módem y luego operar con ellas. Pero en mi caso, "él mismo" (más precisamente, un buzo de Linux según las reglas de udev), crea una interfaz eth y le asigna una dirección IP a través de dhcp.

Para evitar mayor confusión, sugiero olvidar la palabra “módem” y decir tarjeta de red y puerta de enlace, porque en esencia, es como conectar una nueva tarjeta de red con una puerta de enlace.
Cuando hay un módem, esto no causa ningún problema especial, pero cuando hay más de uno, es decir, n piezas, surge la siguiente imagen de red.

Prueba de velocidad simultánea en varios módems LTE

Es decir, n tarjetas de red, con la misma dirección IP, cada una con la misma puerta de enlace predeterminada. Pero, de hecho, cada uno de ellos está conectado a su propio operador.

Inicialmente, tenía una solución simple: usando el comando ifconfig o ip, apague todas las interfaces y simplemente encienda una por turno y pruébela. La solución fue buena para todos, excepto que durante los momentos de cambio no pude conectarme al dispositivo. Y como el cambio es frecuente y rápido, en realidad no tuve ninguna oportunidad de conectarme.

Por lo tanto, elegí la opción de cambiar manualmente las direcciones IP de los módems y luego dirigir el tráfico usando la configuración de enrutamiento.

Prueba de velocidad simultánea en varios módems LTE

Este no fue el final de mis problemas con los módems: en caso de problemas de energía, se caían y se necesitaba una fuente de alimentación buena y estable para el concentrador USB. Resolví este problema soldando la alimentación directamente al concentrador. Otro problema que encontré y que arruinó todo el proyecto: después de reiniciar o arrancar en frío el dispositivo, no se detectaron todos los módems ni siempre, y no pude determinar por qué sucedió esto y mediante qué algoritmo. Pero primero lo primero.

Para que el módem funcione correctamente, instalé el paquete usb-modeswitch.

sudo apt update
sudo apt install -y usb-modeswitch

Después de lo cual, después de conectarse, el subsistema udev detectará y configurará correctamente el módem. Lo compruebo simplemente conectando el módem y asegurándome de que aparece la red.
Otro problema que no pude solucionar: ¿cómo puedo obtener el nombre del operador con el que estamos trabajando desde este módem? El nombre del operador está contenido en la interfaz web del módem en 192.168.8.1. Esta es una página web dinámica que recibe datos a través de solicitudes Ajax, por lo que simplemente crear la página y analizar el nombre no funcionará. Entonces comencé a buscar cómo desarrollar una página web, etc., y me di cuenta de que estaba haciendo una especie de tontería. Como resultado, escupió y el operador comenzó a recibir utilizando la propia API Speedtest.

Sería mucho más fácil si el módem tuviera acceso mediante comandos AT. Sería posible reconfigurarlo, crear una conexión ppp, asignar una IP, conseguir un operador de telecomunicaciones, etc. Pero, por desgracia, estoy trabajando con lo que me han dado.

GPS

El receptor GPS que me dieron tenía una interfaz UART y alimentación. No era la mejor solución, pero aun así era viable y sencilla. El receptor se parecía a esto.

Prueba de velocidad simultánea en varios módems LTE

Para ser honesto, esta fue la primera vez que trabajo con un receptor GPS, pero como esperaba, todo fue pensado para nosotros hace mucho tiempo. Así que simplemente utilizamos soluciones ya preparadas.

Primero, habilito uart_AO_B (UART_RX_AO_B, UART_TX_AO_B) para conectar el GPS.

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

Después compruebo el éxito de la operación.

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

Este comando aparentemente edita el árbol de desarrollo sobre la marcha, lo cual es muy conveniente.

Después del éxito de esta operación, reinicie e instale el demonio GPS.

khadas@Khadas:~$ sudo reboot

Instalación del demonio GPS. Instalo todo y lo corto inmediatamente para realizar más configuraciones.

sudo apt install gpsd gpsd-clients -y
sudo killall gpsd
 
/* GPS daemon stop/disable */
sudo systemctl stop gpsd.socket
sudo systemctl disable gpsd.socket

Editando el archivo de configuración.

sudo vim /etc/default/gpsd

Estoy instalando un UART en el que se colgará el GPS.

DEVICES="/dev/ttyS4"

Y luego encendemos todo y comenzamos.

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

Después de eso, conecto el GPS.

Prueba de velocidad simultánea en varios módems LTE

El cable del GPS está en mis manos, los cables del depurador UART son visibles bajo mis dedos.

Reinicio y verifico el funcionamiento del GPS usando el programa gpsmon.

Prueba de velocidad simultánea en varios módems LTE

No puedes ver los satélites en esta captura de pantalla, pero puedes ver la comunicación con el receptor GPS, y esto significa que todo está bien.

En Python, probé muchas opciones para trabajar con este demonio, pero me decidí por la que funcionaba correctamente con Python 3.

Instalo la biblioteca necesaria.

sudo -H pip3 install gps3 

Y esculpo el código de trabajo.

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 ("Wait gps counter = %d" % counter)
		if counter == 10:
			ErrorMessage("Ошибка GPS приемника!!!")
			return "NA", "NA"
		time.sleep(1.0)
...
f __name__ == '__main__':
...
	#gps
	agps_thread = AGPS3mechanism()  # Instantiate AGPS3 Mechanisms
	agps_thread.stream_data()  # From localhost (), or other hosts, by example, (host='gps.ddns.net')
	agps_thread.run_thread()  # Throttle time to sleep after an empty lookup, default '()' 0.2 two tenths of a second

Si necesito obtener coordenadas, esto se hace con la siguiente llamada:

longitude, latitude = getPositionData(agps_thread)

Y dentro de 1 a 10 segundos obtendré la coordenada o no. Sí, tuve diez intentos de obtener coordenadas. No es óptimo, está torcido y torcido, pero funciona. Decidí hacer esto porque el GPS puede tener mala recepción y no siempre recibir datos. Si espera recibir datos, si trabaja en una habitación remota, el programa se congelará en este lugar. Por eso, implementé esta opción poco elegante.

En principio, si hubiera más tiempo, sería posible recibir datos del GPS directamente a través de UART, analizarlos en un hilo separado y trabajar con ellos. Pero no hubo tiempo en absoluto, de ahí el código brutalmente feo. Y sí, no me avergüenzo.

LED

Conectar el LED fue sencillo y difícil al mismo tiempo. La principal dificultad es que el número de pin del sistema no se corresponde con el número de pin de la pizarra y porque la documentación está escrita con la mano izquierda. Para comparar el número de pin del hardware y el número de pin en el sistema operativo, debe ejecutar el comando:

gpio readall

Se mostrará una tabla de correspondencia de pines en el sistema y en el tablero. Después de lo cual ya puedo operar el pin en el propio sistema operativo. En mi caso el LED está conectado a GPIOH_5.

Prueba de velocidad simultánea en varios módems LTE

Cambio el pin GPIO al modo de salida.

gpio -g mode 421 out

Escribo cero.

gpio -g write 421 0

Escribo uno.

gpio -g write 421 1

Prueba de velocidad simultánea en varios módems LTE
Todo se enciende, después de escribir “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)

Ahora, en caso de errores, llamo a error_blink() y el LED parpadeará maravillosamente.

Nodos de software

API de prueba de velocidad

Es una gran alegría que el servicio speedtest.net tenga su propia API de Python, puedes verlo Github.

Lo bueno es que hay códigos fuente que también se pueden visualizar. Cómo trabajar con esta API (ejemplos simples) se puede encontrar en sección relevante.

Instalo la biblioteca de Python con el siguiente comando.

sudo -H pip3 install speedtest-cli

Por ejemplo, incluso puedes instalar un probador de velocidad en Ubuntu directamente desde el software. Esta es la misma aplicación de Python, que luego se puede iniciar directamente desde la consola.

sudo apt install speedtest-cli -y

Y mide tu velocidad de Internet.

speedtest-cli
Retrieving speedtest.net configuration...
Testing from B***** (*.*.*.*)...
Retrieving speedtest.net server list...
Selecting best server based on ping...
Hosted by MTS (Moscow) [0.12 km]: 11.8 ms
Testing download speed................................................................................
Download: 7.10 Mbit/s
Testing upload speed......................................................................................................
Upload: 3.86 Mbit/s

Como resultado, tal como lo hice yo. Tuve que profundizar en los códigos fuente de esta prueba de velocidad para poder implementarlos más completamente en mi proyecto. Una de las tareas más importantes es obtener el nombre del operador de telecomunicaciones para poder sustituirlo en la placa.

import speedtest
from datetime import datetime
...
#Указываем конкретный сервер для теста
#6053) MaximaTelecom (Moscow, Russian Federation)
servers = ["6053"]
# If you want to use a single threaded test
threads = None
s = speedtest.Speedtest()
#получаем имя оператора сотовой связи
opos = '%(isp)s' % s.config['client']
s.get_servers(servers)
#получаем текстовую строку с параметрами сервера
testserver = '%(sponsor)s (%(name)s) [%(d)0.2f km]: %(latency)s ms' % s.results.server
#тест загрузки
s.download(threads=threads)
#тест выгрузки
s.upload(threads=threads)
#получаем результаты
s.results.share()

#После чего формируется строка для записи в csv-файл.
#получаем позицию GPS
longitude, latitude = getPositionData(agps_thread)
#время и дата
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"
#тут идет запись в файл логов

Aquí tampoco todo resultó tan sencillo, aunque parecería mucho más sencillo. Inicialmente, el parámetro de los servidores era igual a [], dicen, elige el mejor servidor. Como resultado, tenía servidores aleatorios y, como puedes imaginar, velocidad variable. Este es un tema bastante complejo, el uso de un servidor fijo, si es estático o dinámico, requiere investigación. Pero aquí hay un ejemplo de gráficos de medición de velocidad para un operador de Beeline cuando selecciona dinámicamente un servidor de prueba y uno fijo estáticamente.

Prueba de velocidad simultánea en varios módems LTE
El resultado de medir la velocidad a la hora de elegir un servidor dinámico.

Prueba de velocidad simultánea en varios módems LTE
El resultado de las pruebas de velocidad, con un servidor estrictamente seleccionado.

Durante la prueba, hay "pelaje" en ambos lugares y es necesario eliminarlo mediante métodos matemáticos. Pero con un servidor fijo es un poco menor y la amplitud es más estable.
En general, este es un lugar de gran investigación. Y mediría la velocidad de mi servidor usando la utilidad iperf. Pero nos atenemos a las especificaciones técnicas.

Envío de correo y errores

Para enviar correo, probé varias docenas de opciones diferentes, pero al final me decidí por la siguiente. Registré un buzón en Yandex y luego tomé Este es un ejemplo de envío de correo.. Lo verifiqué y lo implementé en el programa. Este ejemplo examina varias opciones, incluido el envío desde Gmail, etc. No quería molestarme en configurar mi servidor de correo y no tuve tiempo para ello, pero como resultó más tarde, también fue en vano.

Los registros se enviaron según el planificador, si hay una conexión, cada 6 horas: a las 00 h, 06 h, 12 h y 18 h. Lo envió de la siguiente manera.

from send_email import *
...
message_log = "Логи тестирования платы №1"
EmailForSend = ["[email protected]", "[email protected]"]
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, "Логи за " + curdata + " " + сurtime, files)
	except:
		print("Network problem for send mail")
		return False
	return True

Inicialmente también se enviaron errores. Para empezar, se acumulaban en la lista y luego se enviaban también mediante el programador, si había una conexión. Sin embargo, luego surgieron problemas con el hecho de que Yandex tiene un límite en la cantidad de mensajes enviados por día (esto es dolor, tristeza y humillación). Como podía haber una gran cantidad de errores incluso por minuto, tuvimos que abandonar el envío de errores por correo. Así que tenga en cuenta al enviar automáticamente información sobre un problema de este tipo a través de los servicios de Yandex.

Servidor de comentarios

Para tener acceso a una pieza de hardware remota y poder personalizarla y reconfigurarla, necesitaba un servidor externo. En general, para ser justos, sería correcto enviar todos los datos al servidor y crear todos los gráficos hermosos en la interfaz web. Pero no todos a la vez.

Para VPS elegí ruvds.com. Podrías elegir el servidor más simple. Y en general, para mis propósitos esto sería suficiente. Pero como no pagué el servidor de mi bolsillo, decidí comprarlo con una pequeña reserva para que fuera suficiente si tuviéramos que implementar una interfaz web, nuestro propio servidor SMTP, VPN, etc. Además, poder configurar un bot de Telegram y no tener problemas con que lo bloqueen. Por eso, elegí Amsterdam y los siguientes parámetros.

Prueba de velocidad simultánea en varios módems LTE

Como método de comunicación con el hardware, vim2 eligió una conexión ssh inversa y, como ha demostrado la práctica, no es la mejor. Si se pierde la conexión, el servidor retiene el puerto y es imposible conectarse a través de él durante algún tiempo. Por lo tanto, es mejor utilizar otros métodos de comunicación, por ejemplo VPN. En el futuro quise cambiarme a VPN, pero no tuve tiempo.

No entraré en detalles sobre cómo configurar un firewall, restringir derechos, deshabilitar las conexiones ssh raíz y otras perogrulladas sobre la configuración de un VPS. Me gustaría creer que ya lo sabes todo. Para una conexión remota, creo un nuevo usuario en el servidor.

adduser vimssh

Genero claves de conexión ssh en nuestro hardware.

ssh-keygen

Y los copio a nuestro servidor.

ssh-copy-id [email protected]

En nuestro hardware, creo una conexión ssh inversa automática en cada arranque.

[Unit] Description=Auto Reverse SSH
Requires=systemd-networkd-wait-online.service
After=systemd-networkd-wait-online.service
[Service] User=khadas
ExecStart=/usr/bin/ssh -NT -o ExitOnForwardFailure=yes -o ServerAliveInterval=60 -CD 8080 -R 8083:localhost:22 [email protected]
RestartSec=5
Restart=always
[Install] WantedBy=multi-user.target

Preste atención al puerto 8083: determina qué puerto usaré para conectarme mediante ssh inverso. Agréguelo al inicio y comience.

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

Incluso puedes ver el estado:

sudo systemctl status autossh.service

Ahora, en nuestro servidor VPS, si ejecutamos:

ssh -p 8083 khadas@localhost

Luego llego a mi pieza de hardware de prueba. Y desde el hardware también puedo enviar registros y cualquier dato vía ssh a mi servidor, lo cual es muy conveniente.

Poniendo todo junto

Prueba de velocidad simultánea en varios módems LTE
Encendido, comencemos el desarrollo y la depuración.

Uf, bueno, eso es todo, describí todos los nodos. Ahora es el momento de juntarlo todo. Puedes ver el código. aquí.

Un punto importante con el código: es posible que este proyecto no comience así, porque fue diseñado para una tarea específica, de una arquitectura específica. Aunque estoy dando el código fuente, explicaré las cosas más valiosas aquí, directamente en el texto, de lo contrario es completamente incomprensible.

Al principio, inicializo gps, gpio y lanzo un hilo de programación separado.

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

El programador es bastante simple: mira para ver si ha llegado el momento de enviar mensajes y cuál es el estado de error actual. Si hay un indicador de error, hacemos parpadear el 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)

La parte más difícil de este proyecto es mantener la conexión ssh inversa para cada prueba. Cada prueba implica reconfigurar la puerta de enlace predeterminada y el servidor DNS. Como de todos modos nadie lee, sepa que el tren no viaja sobre rieles de madera. Quien encuentre el huevo de Pascua recibirá unos dulces.

Para hacer esto, creo una tabla de enrutamiento separada -set-mark 0x2 y una regla para redirigir el tráfico.

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")

Puedes aprender más sobre cómo funciona. leer en este artículo.

Después de lo cual entro en un bucle sin fin, donde cada vez obtenemos una lista de módems conectados (para saber si la configuración de la red ha cambiado repentinamente).

network_list = getNetworklist()

Obtener una lista de interfaces de red es bastante sencillo.

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

Después de recibir la lista, configuro las direcciones IP para todas las interfaces, como mostré en la imagen del capítulo sobre el módem.

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")

Luego simplemente reviso cada interfaz en un bucle. Y configuro cada interfaz.

	for iface in network_list:
		ConfigNetwork(iface)

def ConfigNetwork(iface):
#сбрасываем все настройки
		cmd_run("sudo ip route flush all")
#Назначаем шлюз по умолчанию
		cmd_run("sudo route add default gw 192.168.8.1 " + iface)
#задаем dns-сервер (это нужно для работы speedtest)
		cmd_run ("sudo bash -c 'echo nameserver 8.8.8.8 > /etc/resolv.conf'")

Verifico la funcionalidad de la interfaz, si no hay red, genero errores. Si existe una red, ¡es hora de actuar!

Aquí configuro el enrutamiento ssh a esta interfaz (si no se ha hecho), envío errores al servidor si ha llegado el momento, envío registros y finalmente ejecuto una prueba de velocidad y guardo los registros en un archivo csv.

if not NetworkAvalible():
....
#Здесь мы формируем ошибки
....
else: #Есть сеть, ура, работаем!
#Если у нас проблемный интерфейс, на котором ssh, то меняем его
  if (sshint == lastbanint or sshint =="free"):
    print("********** Setup SSH ********************")
    if sshint !="free":
      сmd_run("sudo ip route del default via 192.168.8.1 dev " + sshint +" table 102")
    SetupReverseSSH(iface)
    sshint = iface
#раз сетка работает, то давай срочно все отправим!!!
    if ready_to_send:
      print ("**** Ready to send!!!")
        if sendLogs():
          ready_to_send = False
        if error_status:
          SendErrors()
#и далее тестируем скорость и сохраняем логи. 

Vale la pena mencionar la función de configurar ssh inverso.

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")

Y, por supuesto, debes agregar toda esta belleza al inicio. Para hacer esto creo un archivo:

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

Y escribo en él:

[Unit] Description=Modem Speed Test
Requires=systemd-networkd-wait-online.service
After=systemd-networkd-wait-online.service
[Service] User=khadas
ExecStart=/usr/bin/python3.6 /home/khadas/modems_speedtest/networks.py
RestartSec=5
Restart=always
[Install] WantedBy=multi-user.target

¡Activo la carga automática y empiezo!

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

Ahora puedo ver registros de lo que está sucediendo usando el comando:

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

resultados

Bueno, ahora lo más importante es, ¿qué pasó como resultado? Aquí hay algunos gráficos que logré capturar durante el proceso de desarrollo y depuración. Los gráficos se construyeron usando gnuplot con el siguiente 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 primera experiencia fue con el operador Tele2, que realicé durante varios días.

Prueba de velocidad simultánea en varios módems LTE

Aquí utilicé un servidor de medición dinámica. Las mediciones de velocidad funcionan, pero fluctúan mucho, pero todavía se ve algún valor promedio, y esto se puede obtener filtrando los datos, por ejemplo, con una media móvil.

Posteriormente construí varios gráficos para otros operadores de telecomunicaciones. En este caso ya existía un servidor de pruebas y los resultados también fueron muy interesantes.

Prueba de velocidad simultánea en varios módems LTE

Prueba de velocidad simultánea en varios módems LTE

Prueba de velocidad simultánea en varios módems LTE

Prueba de velocidad simultánea en varios módems LTE

Como puede ver, el tema es muy extenso para la investigación y el procesamiento de estos datos, y claramente no dura ni un par de semanas de trabajo. Pero…

El resultado del trabajo.

El trabajo se completó abruptamente debido a circunstancias fuera de mi control. Una de las debilidades de este proyecto, en mi opinión subjetiva, fue el módem, que realmente no quería funcionar simultáneamente con otros módems y hacía tales trucos cada vez que se cargaba. Para estos fines, existe una gran cantidad de otros modelos de módems, generalmente ya están en formato Mini PCI-e, se instalan dentro del dispositivo y son mucho más fáciles de configurar. Pero esa es una historia completamente diferente. El proyecto fue interesante y me alegré mucho de poder participar en él.

Prueba de velocidad simultánea en varios módems LTE

Fuente: habr.com

Añadir un comentario