Öffnen und Schließen

Unser Treiber kann eine Schnittstelle beim Laden des Moduls oder beim Hochfahren des Kernels suchen. Bevor die Schnittstelle Pakete transportieren kann, muß der Kernel sie aber öffnen und ihr eine Adresse zuweisen. Dies geschieht als Reaktion auf einen ifconfig-Aufruf.

Wenn ifconfig verwendet wird, um einer Schnittstelle eine Adresse zuzuweisen, erledigt es zwei Aufgaben. Zunächst weist es die Adresse der Schnittstelle mit Hilfe des ioctl-Befehls SIOCSIFADDR (Socket I/O Control Set Interface ADDRess) zu und dann setzt es das IFF_UP-Bit in dev->flag durch den ioctl-Befehl SIOCSIFFLAGS (Socket I/O Control Set Interface FLAGS), um die Schnittstelle zu aktivieren.

Was das Gerät angeht, macht ioctl(SIOCSIFADDR) nichts. Es wird keine Treiberfunktion aufgerufen — die Aufgabe ist geräteunabhängig und wird vom Kernel erledigt. Der zweite ioctl-Befehl (SIOCSIFFLAGS) ruft dann allerdings die open-Methode für das Gerät auf.

Entsprechend ruft ifconfig beim Herunterfahren einer Schnittstelle ioctl(SIOCSIFFLAGS) auf, um das Flag IFF_UP zu löschen. Anschließend wird die stop-Methode aufgerufen.

Beide Gerätemethoden geben im Erfolgsfall 0 und den üblichen negativen Wert bei Fehlern zurück.

Was den eigentlichen Code angeht, muß der Treiber in vielerlei Hinsicht das gleiche machen, wie auch bei Zeichen- und Block-Treibern. open fordert alle benötigten Systemressourcen an und teilt der Schnittstelle mit, jetzt aktiv zu sein; stop fährt die Schnittstelle herunter und gibt die Systemressourcen frei. Es sind allerdings noch eine Reihe weiterer Schritte durchzuführen.

Zunächst muß die Hardware-Adresse aus dem Hardware-Gerät nach dev->dev_addr kopiert werden, bevor die Schnittstelle mit der Außenwelt kommunizieren kann. Die Hardware-Adresse kann je nach Geschmack des Treibers beim Suchen nach dem Gerät oder beim Öffnen zugewiesen werden. Die Software-Schnittstelle snull macht das in open; hier wird einfach eine Hardware-Nummer vorgetäuscht, indem ein ASCII-String der Länge ETH_ALEN verwendet wird (also der Länge von Ethernet-Hardware-Adressen).

Die Methode open sollte auch die Übertragungswarteschlange der Schnittstelle starten (und damit Pakete zur Übertragung akzeptieren), sobald die Schnittstelle zum Senden von Daten bereit ist. Der Kernel stellt dafür eine Funktion bereit:


void netif_start_queue(struct net_device *dev);

Der Code von open in snull sieht so aus:


int snull_open(struct net_device *dev)
{
    MOD_INC_USE_COUNT;

    /* request_region(), request_irq(), .... (wie fops->open) */

    /*
     * Die Hardware-Adresse der Karte zuweisen: Wir verwenden
     * "\0SNULx", wobei x 0 oder 1 ist. Das erste Byte ist '\0', um
     * Multicast-Adressen zu vermeiden (das erste Byte in
     * Multicast-Adressen ist ungerade).
     */
    memcpy(dev->dev_addr, "\0SNUL0", ETH_ALEN);
    dev->dev_addr[ETH_ALEN-1] += (dev - snull_devs); /* die Nummer */

    netif_start_queue(dev);
    return 0;
}

Wie Sie sehen, muß man bei Abwesenheit echter Hardware in der open-Methode nur wenig tun. Das gleiche gilt auch für die stop-Methode; diese macht nur die Operationen von open rückgängig. Aus diesem Grund wird die Funktion, die stop implementiert, oft close oder release genannt.


int snull_release(struct net_device *dev)
{
    /* Ports, IRQ usw. freigeben -- wie fops->close */

    netif_stop_queue(dev); /* keine Uebertragung mehr moeglich */
    MOD_DEC_USE_COUNT;
    return 0;
}

Die Funktion


void netif_stop_queue(struct net_device *dev);

ist das Gegenstück zu netif_start_queue; sie markiert das Gerät als nicht mehr übertragungsfähig. Diese Funktion muß aufgerufen werden, wenn die Schnittstelle geschlossen wird (was in der Methode stop geschieht), kann aber auch dazu verwendet werden, die Übertragung vorübergehend anzuhalten, was im nächsten Abschnitt erläutert wird.