Posted & filed under Valencià.

Quan féiem la prova de configurar la pila amb ifupdown durant l'arrencada ens trobàvem amb dos problemes. D'una banda, el sistema fallava a l'intentar trobar la interfície de loopback per atorgar-li una adreça, i d'altra banda, el client DHCP no aconseguia obtindre l'adreça MAC de la interfície que estava intentant configurar. Per a realitzar aquestes dues accions, ifupdown fa servir la interfície iioctl. A hores d'ara, ja estan implementades totes les operacions ioctl que implementa pfinet, això és, totes les que declara la interfície iioctl excepte SIOCSIFMETRIC i SIOCDIFADDR. Un cop en funcionament, era l'hora de tornar a provar com reaccionava el servidor LwIP a les accions del sistema ifupdown.

Comencem per la interfície loopback. Bàsicament, a LwIP hi ha dues maneres d'activar aquesta funcionalitat: una és afegint realment una nova interfície configurada de manera que atenga el trànsit de la xarxa 127.0.0.0/8 i l'altra és indicant-li a la pila que es comporte en tot moment com si aquesta interfície existira, però sense crear-la realment i emprant les altres interfícies existents per tractar el trànsit. En un principi, jo havia triat la segona opció, bàsicament perquè la primera complicava la gestió d'fsysopts. Tanmateix, després de comprovar que ifupdown enviava peticions ioctl destinades a la interfície "lo" vaig haver d'emprar la primera opció i configurar LwIP per a que creara efectivament aquesta interfície.

Pel que fa al client DHCP, un cop amb les operacions iioctl en marxa ja no donava l'error obtenint l'adreça MAC, en canvi, el client simplement es quedava penjat. Fent les proves amb el depurador i el Wireshark vaig veure que el client enviava el missatge DHCPDISCOVER però aquest mai arribava al cable. Després d'una mica d'investigació vaig trobar dos problemes, el primer, que la pila no podia enviar paquets amb adreça IP d'origen 0.0.0.0; i el segon, que tampoc podia enviar trames amb destinació 255.255.255.255.

Quan al primer error, cal remarcar que no és el mateix l'adreça que te assignada la interfície que la que té assignada el socket. Al socket se li pot assignar l'adreça 0.0.0.0 per a indicar que es vol rebre missatges des de qualsevol interfície disponible, però lògicament quan s'empra el mateix socket per a enviar, l'adreça 0.0.0.0 es substitueix per a de la interfície per la qual està eixint el paquet. D'altra banda, la raó per la qual la pila no deixava sortir paquets amb destinació 255.255.255.255 era perquè la interfície no tenia adreça configurada, i com que INADDR_BROADCAST == INADDR_NONE, la pila es pensava que la destinació del paquet era la mateixa interfície i la ficava a la cua loopback.

En els dos casos, ho he arreglat afegint les excepcions necessàries a les clàusules if pertinents per a permetre la sortida del missatge DHCPDISCOVER. Concretament, ara es permet enviar paquets amb origen 0.0.0.0, però només UDP i només quan la interfície no té cap adreça configurada. De la mateixa manera, s'evita ficar a la cua de loopback un missatge destinat a l'adreça de difusió. Atenent a les proves que jo he fet sembla que tot funciona correctament, però podria ser que aquestes excepcions portaren a la pila a comportar-se malament en algunes altres situacions particulars, de manera que caldrà estar atent per si aquests canvis provoquen problemes més endavant.

Un dels assumptes que més temps m'ha ocupat aquesta setmana ha sigut aconseguir depurar el servidor LwIP mentre arrencava el sistema. Per fer-ho, vaig intentar posar en marxa un subhurd. Vaig trigar un dos dies en aconseguir-ho, però al final em vaig bassar en aquesta guia i ho vaig fer de la següent manera:

  1. Descarregant la imatge d'un sistema net i afegint-la com un disc dur virtual de qemu.

    En el meu cas, la partició amb el sistema es accessible des de /dev/hd2s5.

  2. Arrancant amb la comanda:

    boot --kernel-command-line="fastboot root=pseudo-root" -f hd0=/dev/hd2 -f hd0s1=/dev/hd2s1 -f hd0s5=/dev/hd2s5 -f eth0=/dev/eth1 -T typed device:hd2s5
  3. Modificant el fitxer /etc/fstab del subhurd i canviant la primera línia per la següent:

    /dev/pseudo-root	/	ext2	defaults	0	1
  4. A partir d'aquí ja es pot arrancar amb la comanda:

    boot -f hd0=/dev/hd2 -f hd0s1=/dev/hd2s1 -f hd0s5=/dev/hd2s5 -f eth0=/dev/eth1 -T typed device:hd2s5

L'opció més interessant de la comanda boot és la -d, que pausa el subhurd en alguns moments de l'arrencada per a poder connectar-hi un depurador. Tanmateix, en el meu cas l'opció -d només pausa el subhurd una vegada abans de començar l'arrencada i ja no el torna a aturar més, de manera que l'objectiu inicial de depurar el servidor durant l'arrencada no l'he aconseguit, però he pogut reiniciar el servei networking i depurar el servidor en eixe moment, suficient per tirar endavant.

Canviant de tema, la setmana anterior vaig parlar sobre un problema que tenia amb l'operació device_get_status(), que sempre retornava el valor 0x00000041 per als indicadors del dispositiu quan es cridava amb l'opció NET_STATUS, sense importar quins eren els indicadors activats realment. Aquesta setmana li he fet una ullada al tema per veure què podia estar passant, i he descobert que és un problema del controlador e1000, perquè amb el controlador rtl8139 sí que funciona correctament. Per això, al final he decidit mantenir l'opció NET_STATUS atès que també és reconeguda per eth-multiplexer.