viernes, 21 de agosto de 2009

Proyecto SCTP-H264

El proyecto completo se baja del SVN con el comando:

$ svn co svn+ssh://218.45.218.150/SCTP-H264/trunk SCTP-H264

- freebsd.makefile es el makefile para FreeBSD, se usa "$ make -f freebsd.makefile"
- include es el directorio con todos los .h llamados por los programas de la carpeta src
- Makefile es para Linux
- scripts es un directorio con herramientas muy utiles al momento de hacer 1 millon de tests, tiene scripts en ruby y shell
- SCTP-H264.conf es un archivo de configuracion para ciertos programas en src
- suj incluye archivos de la libreria libsuj hecha por Horacio y externa al proyecto

En los Makefile's es posible ver todos los ejecutables del proyecto. Ahora lo tengo para que los ejecutables obtenidos queden siempre en la carpeta raiz (SCTP-H264).
La carpeta scripts incluye:
- common.rb: varias clases y funciones que uso en otros scripts de la carpeta
- info.rb: tira informacion de un archivo .h64
- netem.sh: permite hacer la setting de netem simplemente haciendo "sudo netem.sh 50 6" para simular 50ms de RTT y 6% packet loss rate. En suj-uchile51 puse un link simbolico de /sbin/netem a dicho script que permite ahorrarse el .sh al final del comando.
- plot_globecom1.rb: programa en ruby que genera los graficos usados en el primer paper enviado a Globecom usando mi parser
- plot_ieice.rb: idem para el paper de IEICE
- plot.rb: grafica 1 o mas tracefiles usando mi parser
- process.rb: hecho por Horacio para hacer los graficos del primer paper mandado a Globecom
- sctpdump.sh: igual que netem.sh para obtener los .cap o trace files con tcpdump. Filtra todo lo de sctp haciendo "$ sudo sctpdump archivo.cap"
- test_buffer.rb: lo hice en su momento para obtener la diferencia entre la llamada a sctp_send y cuando efectivamente el mensaje salia a la red
- test_rtx.rb: para dejar corriendo muchos test para testear PR con RTX
- test_rtx2.rb: lo usaba despues del anterior para graficar la data obtenida de muchos tests
- test_sender.rb con este parseaba datos de la parte sender
- test_ttl.rb: analogo a test_rtx.rb pero con TTL
- test_ttl2.rb: analogo a test_rtx2.rb pero con TTL

De todos estos scripts, los mas utiles son netem.sh sctpdump.sh y plot.rb. Todos los programas en Ruby mios se puden ejecutar como comando, es decir "$ ./plot.rb" en vez de "$ ruby plot.rb"

En la carpeta include es relevante:
- const.h donde se especifican constantes para las apps, incluyendo el path del archivo de configuracion.
- connection.h es importante porque se especifica la estructura connection_t usada constantemente.
- nal.h: se especifica la estructura NALUnit usada constantemente y ademas es la que se usa para reproducir video, o sea en el player hecho por Felipe.

Ahora describo la carpeta src, que es donde estan todos los programas:

- annexb.c: hecho por Horacio
- buffer.c: maneja lectura y escritura de archivos, hecho por Felipe Lalanne
- config_file.c: hecho por mi, incluye solo la funcion read_config_file() para leer el archivo de configuracion
- connection.c: uno de los mas importantes del proyecto, hecho por todo el grupo. Maneja el envio y recepcion de datos, ademas de las policies de SCTP. Originalmente fue hecho por Felipe como una capa que manejaba la parte de red, asi que maneja tambien UDP y deberia tambien manejar TCP (no lo hace pero lo implementare en Chile).
- h264-parser.c: hecho por Felipe para obteners las NALs de un archivo H.264 raw.
- idrlist.c: pedido por Luis para listar los frames IDR (suponiendo 1 NAL por frame y descartando los SPS y PPS como frames). Es muy simple, la pega real la hacen los parsers de archivos. Es ejecutable (tiene main()).
- logging.c: hecho por Felipe para tirar a salida estandar mensajes de informacion (INFO: ...) y debugging (DEBUG: ...). Ademas estos mensajes quedan siembre en un archivo .log que usualmente tiene el mismo nombre que el ejecutable
- nal.c: ciertas funciones para NALs hecho por Felipe
- nal-queue.c: hecho por Felipe para el player
- packet-queue.c: hecho por Felipe para el player
- parse_file.c: lo hice para parsear un archivo H.264 pero esta medio deprecado
- parse_sctp.c: llamese a este MI parser. Hecho por mi y odiado por Horacio ;)
es para parsear los trace files y tira el resultado a salida estandar, lo cual es leido por algun programa en ruby para graficar. Come mucha memoria y es lento con archivos grandes, pero al parecer funciona. Es ejecutable
- parse_sender.c: hecho por mi, parecido al anterior pero orientado a sacar informacion de un trace file obtenido en la parte sender. Es ejecutable.
- parse_tcp.c: para parsear trace files usando TCP, no usar por el momento, creo que no esta ni terminado. Es ejecutable.
- parse_udp.c: idem para UDP, pero no obtiene informacion de NALs, sino que lo hice para analizar los trace files de FSO de Christian.
- player.c: hecho por Felipe. Reproduce archivos H.264
- receive_file.c: hecho por mi. Un cliente SCTP que recive NALs y las guarda en un archivo que luego es reproducible
- receive_play.c: igual que el anterior pero en vez de guardar en un archivo, reproduce el video. Este es el player de Felipe. Funciona bien la mayoria de las veces y es tolerante a perdida de NALs pues usa las librerias de FFMPEG
- sctp_dump.c: hecho por Horacio
- sctp_play.c:hecho por Horacio
- sctp_send.c: hecho por Horacio
- test_pcap.c: el parser de Horacio. Lo mismo que parse_sctp.c. Es ejecutable.
- test_pqueue.c: lo hice en su momento para testear la libreria de pqueue's de Horacio. Es ejecutable.
- test_receive.c: es el cliente SCTP, el que uso constantemente. Recibe mensajes SCTP y los descarta inmediatamente. Idealmente se usa junto con tcpdump. Escucha en el puerto 30000 siempre pero esto es modificable en el archivo de configuracion. Es ejecutable.
- test_send.c: el enviador que uso constantemente. Todos los parametros los lee del archivo de configuracion, pero es posible especificar la policy por ej: $ test_send --profile="rtx 0.06". Es ejecutable
- udpclient.c: hecho por mi para testear si la perdida especificada con netem era efectivamente esa. Es ejecutable.
- utils.c: un par de funciones miscelaneas usadas en varios programas
- video-decoder.c: hecho por Felipe para parsear y reproducir archivos H.264
- sctp_dump.rb: Hecho por Horacio en Ruby.

miércoles, 19 de agosto de 2009

Actualización del Kernel de FreeBSD 8 desde el source usando csup

El método que uso para actualizar el kernel de FreeBSD es el oficial, usando una herramienta llamada "csup", que al parecer es una versión moderna de otro comando llamado "cvsup".

Lo que hacemos es bajar de algun servidor CVS oficial el código del kernel + aplicaciones. Recomiendan no actualizar solamente el kernel, sino todo el sistema. Luego recompilamos todo.
Este método es medio delicado, no siempre funcionan las cosas. Lo que describo ahora es lo que me ha resultado sin problemas, basado en la documentación que he encontrado.

Primero que nada, nos logueamos como root (con sudo también se puede) en un PC con acceso a internet (implica cambiar la configuración de red de suj-uchile52 que no tiene acceso a los servidores CVS):
$ su
$ cd /usr/src

Con el siguiente comando se aplican las últimas actualizaciones desde el CVS:
$ csup /etc/supfile

donde /etc/supfile es nuestro archivo de configuración para csup. Así lo uso ahora:

*default host=cvsup.jp.freebsd.org
*default base=/var/db
*default prefix=/usr
*default release=cvs tag=.
*default delete use-rel-suffix
*default compress
src-all
ports-all tag=.
doc-all tag=.

en el directorio que dejamos como "base" (/var/db) hay un archivo de menor importancia, /var/db/sup/refuse, que indica que NO queremos bajar. Yo lo tengo con los idiomas distintos al inglés:

doc/bn_*
doc/da_*
doc/de_*
doc/el_*
doc/es_*
doc/fr_*
doc/hu_*
doc/it_*
doc/ja_*
doc/mn_*
doc/nl_*
doc/no_*
doc/pl_*
doc/pt_*
doc/ru_*
doc/sr_*
doc/tr_*
doc/zh_*

Cuando baja los sources, Randall recomienda hacer lo siguiente:

What I normally do if I want to run HEAD/9.0 on a machine that I want to
"be more stable" and make performance measurements is:

1) Go in to the GENERIC file of the machine type and comment out
the 2 lines that mention INVARIANT and the 2 lines that mention
WITNESS.

2) Go to the file head/lib/libc/stdlib/malloc.c and uncomment the
#define that says MALLOC_PRODUCTION

3) Then do all my builds.. kernel and buildworld/installworld.


This then assures me that I do NOT get:

a) Debugging panics
b) Bogged down with unnecessary performance drags that are for
the normal kernel development.

Lo que uso desde ahora es lo que aparece en /usr/src/UPDATING, que es el método oficial.
Esto compila todo o "el mundo"

$ env -i make buildworld

en /usr/src/UPDATING recomiendan poner "env -i" antes de todos los make, así que eso es lo que hago. Una vez olvidé poner env -i y me tiró un error al compilar.

Este proceso se demora harto rato, más que compilar sólo el kernel.

Cuando vuelves del café (con piernas) y todo compiló bien, compilamos el kernel:

$ env -i make kernel KERNCONF=GENERIC

donde GENERIC es el nombre de nuestra configuración. Esto se demora unos 25 minutos.

Si todo salio bien rebooteamos en modo "single user". Esto se hace rebooteando y cuando aparece el menú feo de inicio de FreeBSD elegimos el modo "single user" presionando el 4.

# mount -a
# cd /usr/src
# mergemaster -pa

# make installworld

esto demora 1 ó 2 minutos

# make delete-old

Otra vez, las opciones por default deberían estar OK.

# mergemaster -a

De nuevo, las opciones por default deberían estar OK. Finalmente:

# reboot

Rebootea normalmente y el sistema queda "a punto", con todas las últimas modificaciones. Ojo que para actualizar los ports es otra historia.

jueves, 30 de abril de 2009

Parches SCTP para FreeBSD 7.1

En teraperu/share/FreeBSD7.1_patches están los tar.gz correspondientes a los parches de FreeBSD 7.1 en orden. No son realmente parches (no se debe hacer patch), está el código completo, para no enredarse con las versiones. Randall Stewart también los envía de la misma manera, pero siempre se utilizaban de maneras distintas o los archivos estaban corruptos (había que cambiar la extensión o descomprimir 2 veces).

  • netinet0.tar.gz es la versión original, la que se tiene al instalar con el disco
  • netinet1.tar.gz lo anterior más el único parche oficial de www.sctp.org
  • netinet2.tar.gz lo anterior más el primer parche enviado por Randall Stewart (todavía bien buggy en PR-SCTP)
  • netinet3.tar.gz la última versión (parche de Randall que es correcto pero peor para nosotros, no tengo la versión anterior)
También están los archivos que mandó Randall pero de forma no ordenada, sin nombres significativos.

Para aplicar éstos u otros tar.gz hay que fijarse en que parte de /usr/src hay que descomprimirlo. Éstos se descomprimen en /usr/src/sys, incluyen las carpetas netinet y netinet6 completas:

suj-uchile52:~$ sudo cp netinet3.tar.gz /usr/src/sys
suj-uchile52:~$ cd /usr/src/sys
suj-uchile52:~$ tar xvzf netinet3.tar.gz

Es conveniente también copiar los headers files al /usr/include:
suj-uchile52:~$ sudo cp /usr/src/sys/netinet/*.h /usr/include/netinet
suj-uchile52:~$ sudo cp /usr/src/sys/netinet6/*.h /usr/include/netinet6

Ahora se recompila el kernel FreeBSD:
suj-uchile52:~$ cd /usr/src
suj-uchile52:~$ sudo make clean
suj-uchile52:~$ sudo make buildkernel KERNCONF=CUSTOM
Acá hay que esperar como 20 minutos mientras compila. "CUSTOM" es el archivo de configuración, puede ser "GENERIC", "MYKERNEL" o el que hallamos especificado.
Al final:
suj-uchile52:~$ sudo make installkernel KERNCONF=CUSTOM

Reiniciar y ya está.

Ojo que todavía hay bugs de menor importancia. No he podido activar las notificaciones SCTP si no quiero que FreeBSD se reinicie solo. Aparecen ABORT's frecuentemente (no deberian aparecer).

Simulación con tc/netem en Linux

Esta configuración tiene 3 PC's: los extremos suj-uchile52, suj-uchile53 y el bridge suj-uchile51 (con 2 tarjetas de red eth0 y eth1).
Asegurarse que cada extremo esté conectado al bridge con un cable cruzado.
Cada extremo puede utilizarse con Linux o FreeBSD, el bridge sólo lo tengo habilitado con Ubuntu server 8.10 (netem sólo funciona en Linux). Las IP's son:

suj-uchile51: 192.168.4.51
suj-uchile52: 192.168.4.52
suj-uchile53: 192.168.4.53

Comandos tc


Se utiliza tc para todo. tc es el Traffic Control. Todo se debe ejecutar con sudo o como root. Lo otro que se utiliza mucho son los qdisc's (queuing discipline) que son algo así como un objeto de simulación.

Algo que yo hago mucho es:

suj-uchile51:~$ tc qdisc show
qdisc pfifo_fast 0: dev eth1 root bands 3 priomap 1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1
qdisc pfifo_fast 0: dev eth0 root bands 3 priomap 1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1

Esto muestra los qdisc's. La salida que aparece no tengo bien claro qué es, pero aparece cuando no hay qdiscs configurados.

Para crear un qdisc con pérdida 0.1% se hace:

suj-uchile51:~$ sudo tc qdisc add dev eth0 root netem drop 0.1%

Lo que importa de este comando es sólo la última parte netem drop 0.1%. El resto del comando dice que se quiere añadir (add) un qdisc en el dispositivo (dev) eth0 como raíz (root) del sistema de clases. Este sistema de clases es complejo y no es necesario comprenderlo por ahora. En Packet Shaping HOWTO aparece una explicación más extensa.

Si ahora se consulta por los qdisc's existentes:
suj-uchile51:~$ tc qdisc show
qdisc pfifo_fast 0: dev eth1 root bands 3 priomap 1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1
qdisc netem 8001: dev eth0 root limit 1000 loss 0.1%

aparece el último qdisc creado.

Para simular delay (200ms) se hace:
suj-uchile51:~$ sudo tc qdisc change dev eth0 root netem delay 200ms

Ojo que ahora pusimos change en vez de add, porque cambiamos el qdisc en vez de crearlo.

Para combinar delay y pérdida:
suj-uchile51:~$ sudo tc qdisc change dev eth0 root netem drop 0.1% delay 200ms
suj-uchile51:~$ tc qdisc show
qdisc pfifo_fast 0: dev eth1 root bands 3 priomap 1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1
qdisc netem 8001: dev eth0 root limit 1000 delay 200.0ms loss 0.1%

(con netem "drop" es sinónimo de "loss")

Es importante notar que el qdisc asignado a eth0 afectará sólo el tráfico que salga por eth0 y no el entrante. Por ej. con la siguiente configuración:

El tráfico desde suj-uchile52 a suj-uchile53 no será afectado, pero sí el de suj-uchile53 a suj-uchile52 con los parámetros especificados.

Por eso lo que hemos estado haciendo es simular un canal con P% pérdida y D ms de delay asignando P% pérdida a cada interfaz y D/2 en cada una.

Por ej. para simular un canal con 6.7% pérdida y 268ms delay hacemos:

suj-uchile51:~$ sudo tc qdisc change dev eth0 root netem delay 134ms drop 6.7%
suj-uchile51:~$ sudo tc qdisc add dev eth1 root netem delay 134ms drop 6.7%
suj-uchile51:~$ tc qdisc show
qdisc netem 8002: dev eth1 root limit 1000 delay 134.0ms loss 6.7%
qdisc netem 8001: dev eth0 root limit 1000 delay 134.0ms loss 6.7%

Para borrar qdisc hacemos:
suj-uchile51:~$ sudo tc qdisc delete dev eth0 root
suj-uchile51:~$ sudo tc qdisc delete dev eth1 root

En el SVN uchile está el script netem.sh:

#!/bin/sh

user=`whoami`
if [ $user != "root" ]
then
echo "You have to be root, you are $user"
exit 1
fi

if test $# != 2
then
echo "Use ./netem "
exit 1
fi
delay=`echo "scale=1 ; $1 / 2" | bc`
if `tc qdisc add dev eth0 root netem delay ${delay}ms drop $2`
then
tc qdisc add dev eth1 root netem delay ${delay}ms drop $2
else
tc qdisc change dev eth0 root netem delay ${delay}ms drop $2
tc qdisc change dev eth1 root netem delay ${delay}ms drop $2
fi
tc qdisc show

Si queremos simular lo mismo (268ms delay y 6.7% pérdida) con este script:
suj-uchile51:~$ sudo netem 268 6.7
qdisc netem 8004: dev eth1 root limit 1000 delay 134.0ms loss 6.7%
qdisc netem 8003: dev eth0 root limit 1000 delay 134.0ms loss 6.7%

Token Buffer Filter


Ya cachamos que un porcentaje de pérdida constante independiente del bandwitdh enviado no es realista y deja la escoba al tener congestion control. Así que la siguiente etapa es utilizar este algoritmo Token Buffer Filter (tbf), que simula los routers botando paquetes dado un ancho de banda.
Además del ancho de banda, se debe especificar otros 2 parámetros (no sé todavía qué función cumplen en el algoritmo):
  • latency: favorable para el bandwidth, poner 200ms
  • burst: favorable para el bandwidth, poner 256k
El período del sawtooth del cwnd con TCP reno es creciente con ambos parámetros, pero al parecer este aumento es más lineal con el burst y más cuadrático con la latency.

Después de varias pruebas, lo que caché que funciona más parecido a la conexión entre Tokio y Santiago es poner el rate en 9mbit, latency 200ms, burst 256k

Los qdisc's de tbf son distintos a los con netem. Para emular la conexión con Chile se debe además configurar con netem un delay de 268ms.

Los siguientes comandos están basados en Network Simulation with NetEm. Haciendo copy/paste con mis propios parámetros. Además de los qdisc's se agrega un filter al final para que sólo se afecte el tráfico que se quiere:

suj-uchile51:~$ sudo tc qdisc add dev eth0 root handle 1: prio
suj-uchile51:~$ sudo tc qdisc add dev eth0 parent 1:3 handle 30: netem delay 268ms
suj-uchile51:~$ sudo tc qdisc add dev eth0 parent 30:1 tbf rate 9mbit latency 200ms burst 256k
suj-uchile51:~$ sudo tc filter add dev eth0 protocol ip parent 1:0 prio 3 u32 match ip dst 192.168.4.52/24 flowid 10:3
suj-uchile51:~$ tc qdisc show
qdisc pfifo_fast 0: dev eth1 root bands 3 priomap 1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1
qdisc prio 1: dev eth0 root bands 3 priomap 1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1
qdisc netem 30: dev eth0 parent 1:3 limit 1000 delay 268.0ms
qdisc tbf 8005: dev eth0 parent 30:1 rate 9000Kbit burst 256Kb lat 200.0ms

Del filter no estoy muy seguro. Con esto el tráfico desde suj-uchile52 hasta suj-uchile53 tendrá 268ms de delay y se botarán paquetes de acuerdo al tbf configurado. Ojo que por completitud también debería configurarse el sentido inverso (la interfaz eth1).

lunes, 20 de abril de 2009

Deep Purple + Yngwie Malmsteen Live Tokyo 15 Abril 2009

Ok. No podía llevar camara al concierto asi que escribo esta reseña. Y las fotos que se ven son las pocas que pude sacar (afuera del concierto obviamente).

Primero que nada, un concierto aca en Tokio es muuuuuuuuuuuuuy distinto a un galpón lleno de chascones sudando mientras saltan como estoy acostumbrado en Chile. Aca un show es un show, independientemente del tipo de musica del concierto. Al parecer aca el metal no es musica solo de delincuentes como en Chile. Habia gente de todas las edades, adelante mio habia una senora de unos 60 anos con atuendo tradicional japones. Es como ir al cine con la familia. El acomodador que me llevo a mi asiento se agachaba para no tapar el espectaculo a los otros espectadores.
El asunto fue en el Tokyo International Forum, un edificio a todo recto con excelente sonido para rock. Llegue justo antes de que Yngwie abriera con "Death Dealer", el primer track de su ultimo disco "Perpetual Flame".

Yngwie como siempre moviendose caleta, creo que esta mas flaco porque dejo de chupar y fumar parece. Ripper Owens al microfono tiene una voz muuy intensa, ideal para cosas como Judas Priest pero matiza aun menos que Yngwie y le aplica todo el metaleo al mismo nivel el 100% de las canciones, hasta baladas. Me dio la impresion de que le falta un poquito de aperramiento escenografico. Por algo Halford volvio a Judas Priest, wequito y todo ...

Habia escuchado hartas cosas del publico japones, pero cache que se mueven poquiito, a lo mas se pararon cuando empezo y se mantuvieron todo el concierto parados. Igual bacilaban pero poquito, nadie cantaba (excepto yo obviamente jaja). Notable cuando Ripper Owens dijo "Tokyo, scream with me! Yngwie ..." y todos debiamos gritar "Malmsteen" pero se escucharon solo grillos.

Misa Yngwieana

Apesar del publico fome, Yngwie hizo algo que nunca lo habia visto hacer en Chile. Nuestro Señor dedos todopoderosos San Yngwie Malmsteen empezo una misa metalera, como me gusta llamarla jaja. Mientras el Sacerdote "Destripador" Ow ens ejecutaba gritos constantes metaleros y el resto de la banda seguia tocando, el Mesias Metalero Yngwie procedia a sacrificar una guitarra, primero le arranco las cuerdas despues empezo a azotar la strato contra el piso hasta hacer pedazos el cue llo, el cuerpo lo azotaba una y otra vez contra uno de los retornos hasta que rompio la guitarra en 3 y tiro las partes al publico. Igual fue emocionante para nuestra sed metalera yea h! jaja

Deep Purple

Despues de un receso de como 20 minutos aparecio Deep Purple, que aunque me duela decirlo, en vivo es muy superior que Yngwie. Abrieron con "Highway Star" y aca el publico vacilaba un poco mas. Habia una mina delante mio que se movia caleta y cantaba, pero creo que estaba drogada. Ian Gillian esta viejito, parec e Frak Sinat ra, pero igual sigue aperrand o como en los 60's la cago! Puta que era bueno Steve Morse, con mucha mas clase que Yngwie, era un poco un descanso para tan refuerte y monotono que toca Yngwie (otra vez, aunque me duela). Por algo Steve Morse fue elegido "Overall Best Guitarist" por una revista o algo así.


Deep Purple es una banda que aunque toque toda la noche no alcanza a tocar todos los clásicos que tienen.

El ultimo tema fue su clasico mas clasico "Smoke on the Water" tan conocido que es el que tenia que tararear aca en Amarillilandia cuando me preguntaban quien recto era Deep P urple. Aca fue bacan, ya que se subio Jon Lord, el tecla dista que habia jubilado y Ma lmsteen volvió al escenario. Encontre en youtube este video del notable momento:


Trate de cachar otros gaijines para sociabilizar pero habia pocazos, creo que un par de al emanes eran los unicos extranjeros. En conclusion, excelente experiencia especialmente por que nunca habia visto a Deep Purp le en vivo, me sorprendi eron muy gratamente. Y para cachar lo distinto que es un concierto en Santiago o en Tokio.