Wer hat schon mal einen Ethernet-Treiber mit IOKit programmiert...

  • Wer hat schon mal einen Ethernet-Treiber mit IOKit programmiert...

    Ich habe einen (GPL-Treiber) für ein Ethernet-Device und versuche einen Fehler beim Sleep des Macs zu beheben.

    Und zwar passiert folgendes:
    wenn ich einen ping auf das Device laufen lasse ist alles prima. Sobald ein Powerbook in den Ruhezustand geht und wieder aufwacht, meldet der ping relativ zufällig:
    ping: sendto: Host is down
    ping: sendto: Network is down
    ping: sendto: No route to host

    Allerdings wird outputPacket() weiterhin korrekt aufgerufen.

    Wenn ich das Device abstecke und wieder anstecke, läuft der Treiber weiter und der ping geht wieder.

    Was ich suche ist ein vertieftes Verständnis, über welchen Mechanismus der ping seine Meinung zu Host is down/Network is down/No route to host bezieht.

    Ausserdem versuche ich herauszufinden, wie man in einem Treiber mitbekommt, dass das Powerbook aus dem Sleep Mode aufgewacht ist (um ggf. den Treiber wieder in einen definierten Zustand zu versetzen).

    Kennt jemand dazu Antworten oder zumindest ein Forum wo man das diskutieren kann?

    Besten Dank.
    -- hns
  • RE: Wer hat schon mal einen Ethernet-Treiber mit IOKit programmiert...

    Ein paar Fragen, um das Problem besser einzukreisen:

    • Hängt das Device direkt per Kabel am Ethernet des Powerbooks oder über einen Hub/Switch?
    • Hast Du die Geschwindigkeit des Ethernets beim Powerbook auf "autoselect" stehen oder fest eingestellt?
    • Ist nach dem Aufwachen des Powerbooks die MAC-Adresse des Devices noch im Cache (arp -a)?
    • Ist DHCP im Einsatz oder sind die Adressen des Devices und des Powerbooks manuell konfiguriert?
    • Hast Du schonmal angeschaut, was tcpdump nach dem Aufwachen sagt?


    Die Fehlermeldungen beim ping kommen entweder daher, dass gar keine Antwort vom Device kommt oder aber eine negative ICMP-Response von einer dazwischenliegenden Komponente (Router).

    Wenn das Device direkt am Powerbook hängt, vermute ich mal, dass das Powerbook nach dem Aufwachen versucht, die aktuelle Geschwindigkeit des Ethernets per autonegotiation rauszubekommen, aber weder das Device noch ein Hub/Switch (falls vorhanden) dazwischen das unterstützt und damit die Geräte auf einer unterschiedlichen Geschwindigkeit senden. Ich weiss nicht, was der aktuelle Fallback-Wert für OS X ist, wenn eine Negotiation schiefgeht - zu Zeiten von 10.1 war es 10 MBit half duplex - das hat mich einige Nerven mit unserem ersten Xserve gekostet, da 10.1 nur autonegotiation konnte und das Rechenzentrum die an unseren Switches abgeschaltet hatte. Damals half nur Treiber umschreiben...

    Was macht der Treiber denn? Kann man sich den (weil GPL) mal anschaun?

    (edit) Was mich noch wundert - warum braucht ein über Ethernet angeschlossenes Device einen IOKit-Treiber - oder hab ich das falsch verstanden und das Gerät ist ein (z.B. über USB oder PCMCIA angeschlossener) Ethernet-Controller am Powerbook direkt und Du pingst irgendeinen anderen Rechner im Netz an?

    Einige Mailinglisten zum Thema Device Driver sind hier aufgelistet:
    developer.apple.com/devicedrivers/

    Ich vermute, auf der Darwin Driver-Liste hat Dein Problem am ehesten eine Chance.
  • RE: Wer hat schon mal einen Ethernet-Treiber mit IOKit programmiert...

    Original von cuby
    Ein paar Fragen, um das Problem besser einzukreisen:

    • Hängt das Device direkt per Kabel am Ethernet des Powerbooks oder über einen Hub/Switch?
    • Hast Du die Geschwindigkeit des Ethernets beim Powerbook auf "autoselect" stehen oder fest eingestellt?
    • Ist nach dem Aufwachen des Powerbooks die MAC-Adresse des Devices noch im Cache (arp -a)?
    • Ist DHCP im Einsatz oder sind die Adressen des Devices und des Powerbooks manuell konfiguriert?
    • Hast Du schonmal angeschaut, was tcpdump nach dem Aufwachen sagt?


    Die Fehlermeldungen beim ping kommen entweder daher, dass gar keine Antwort vom Device kommt oder aber eine negative ICMP-Response von einer dazwischenliegenden Komponente (Router).

    Wenn das Device direkt am Powerbook hängt, vermute ich mal, dass das Powerbook nach dem Aufwachen versucht, die aktuelle Geschwindigkeit des Ethernets per autonegotiation rauszubekommen, aber weder das Device noch ein Hub/Switch (falls vorhanden) dazwischen das unterstützt und damit die Geräte auf einer unterschiedlichen Geschwindigkeit senden. Ich weiss nicht, was der aktuelle Fallback-Wert für OS X ist, wenn eine Negotiation schiefgeht - zu Zeiten von 10.1 war es 10 MBit half duplex - das hat mich einige Nerven mit unserem ersten Xserve gekostet, da 10.1 nur autonegotiation konnte und das Rechenzentrum die an unseren Switches abgeschaltet hatte. Damals half nur Treiber umschreiben...

    Was macht der Treiber denn? Kann man sich den (weil GPL) mal anschaun?
    (edit) Was mich noch wundert - warum braucht ein über Ethernet angeschlossenes Device einen IOKit-Treiber - oder hab ich das falsch verstanden und das Gerät ist ein (z.B. über USB oder PCMCIA angeschlossener) Ethernet-Controller am Powerbook direkt und Du pingst irgendeinen anderen Rechner im Netz an?


    1. es handelt sich um einen IP over USB-Treiber, d.h. er ist als Ethernet-Treiber (subclass von IOEthernetController) registriert, und sendet/empfängt über USB vom angeschlossenen Device (Sharp Zaurus). Source ist enthalten in: dsitri.de/download/AJZaurusUSB-0.3.0.tgz
    2. kein Hub/Router etc. dazwischen
    3. das angepingte Device antwortet normalerweise
    4. der (nicht abgebrochene!) ping-prozess meldet sich wieder mit der normalen Roundtrip-Time sobald man das Device kurz aus und wieder anschaltet - die dadurch ausgelösten Befehle bringen es wieder in Ordnung...
    5. "negative ICMP-Response" - das wäre eine Möglichkeit. aber Kabel abstecken macht nichts anders als aus/an des angeschlossenen Devices:

    So sieht der Ping aus (nach icmp_seq=6 habe ich Powerbook in den Sleep geschickt)
    - dann wieder aufgeweckt (-> no route/host down)
    - dann Kabel ab und wieder angesteckt (löst message(), initDevice(), enable() des Treibers aus)

    Quellcode

    1. 64 bytes from 192.168.129.201: icmp_seq=3 ttl=64 time=1.284 ms
    2. 64 bytes from 192.168.129.201: icmp_seq=4 ttl=64 time=1.034 ms
    3. 64 bytes from 192.168.129.201: icmp_seq=5 ttl=64 time=1.751 ms
    4. 64 bytes from 192.168.129.201: icmp_seq=6 ttl=64 time=1.551 ms
    5. ping: sendto: No route to host
    6. ping: sendto: Host is down
    7. ping: sendto: Host is down
    8. ping: sendto: Host is down
    9. ping: sendto: Host is down
    10. ping: sendto: Host is down
    11. 64 bytes from 192.168.129.201: icmp_seq=31 ttl=64 time=2.015 ms
    12. 64 bytes from 192.168.129.201: icmp_seq=32 ttl=64 time=1.793 ms
    13. 64 bytes from 192.168.129.201: icmp_seq=33 ttl=64 time=1.533 ms
    Alles anzeigen

    Nun zu arp
    Es meldet nach dem Aufwachen:

    $ arp -a
    ? (192.168.0.1) at 0:40:5:49:76:65 on en1 [ethernet]
    ? (192.168.129.201) at (incomplete) on en3 [ethernet]

    Und das erklärt es eigentlich schon. Der ARP-Cache wird beim Sleep irgendwie zurückgesetzt. Und wird erst durch das aus/an wieder korrigiert. Das müsste ich im Treiber nach dem Aufwachen aus dem Sleep auslösen - wenn ich nur wüßte wie...

    Hier noch ein ifconfig des Devices (bleibt unverändert):

    en3: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
    inet6 fe80::3630:30ff:fe30:3000%en3 prefixlen 64 scopeid 0x7
    inet 192.168.129.1 netmask 0xffffff00 broadcast 192.168.129.255
    ether 34:30:30:30:30:00
    media: autoselect (10baseT/UTP <full-duplex>) status: active
    supported media: none autoselect 10baseT/UTP <half-duplex> 10baseT/UTP <full-duplex> 100baseTX <half-duplex> 100baseTX <full-duplex>


    -- hns
  • RE: Wer hat schon mal einen Ethernet-Treiber mit IOKit programmiert...

    OK, jetzt versteh ich das Problem besser. Hast Du einfach mal testweise versucht, die ARP-Adresse mit arp -s permanent zu setzen?

    Zum Powermanagement (hab noch nie was mit gemacht...) hab ich das hier gefunden:

    developer.apple.com/documentat…OPMLib/CompositePage.html

    Mit IORegisterForSystemPower kann man sich wohl für Power-Management-Events registrieren. Allerdings frage ich mich, ob man die Funktion jetzt auch direkt aus einem anderen IOKit-Treiber (oder nur aus einer Applikation heraus) aufrufen kann. Die Technote hier

    developer.apple.com/qa/qa2004/qa1340.html

    schreibt nur was über Applikationen. Da müsste ich mich auch mal genauer einlesen - wenn man die Funktionalität benutzt, könnte man evtl. die ARP-Adresse grade von einem kleinen Userspace-Daemon neu setzen lassen, das wäre IMHO aber eher ein Hack als ne Lösung.

    Hier findet sich noch was, das nach Power Management in Treibern aussieht:

    developer.apple.com/documentat…/chapter_4_section_5.html
    und ein kurzes Tutorial hier:
    developer.apple.com/technotes/tn2002/tn2076.html

    Das ist wohl eher das Richtige.

    Hmm, ich hab noch irgendwo einen 3Com USB-Ethernet-Adapter, für den es noch keinen OS X-Treiber gibt ;).

    Michael
  • RE: Wer hat schon mal einen Ethernet-Treiber mit IOKit programmiert...

    Du kannst den Treiber gerne als Skelett für den 3Com nehmen...

    Soweit ich das IORegisterForSystemPower verstanden habe geht es in der Tat erst mal nur um Powermanagement für Applications (d.h. dass sie z.B. den Sleep-Mode unterdrücken können) und nicht Treiber (die Header oder die Methoden gibt es nicht so direkt...).

    Und das andere Thema "Power Management" habe ich erst mal so verstanden, dass es darum geht, den Energieverbrauch von verwalteten Treibern zu steuern (also Device abschalten wenn man es nicht braucht: but unless your driver serves as a policy maker or as the power controller for your device, you will probably not need to implement or call any of them.).

    Vielleicht muss man das Device "virtuell" ausschalten, also einfach auf das Anschalten-Event reagieren (und nichts physikalisch machen)?

    Beste Grüße,
    hns
  • RE: Wer hat schon mal einen Ethernet-Treiber mit IOKit programmiert...

    Kleiner Update: die TN2076 war genau der richtige Hinweis um den Treiber so zu erweitern, dass er zumindest Power down/up des Powerbooks mitbekommt.

    Jetzt fehlt "nur" noch die richtige Aktion im Treiber um das ARP-System zurückzusetzen...

    -- hns
  • RE: Wer hat schon mal einen Ethernet-Treiber mit IOKit programmiert...

    Einfach die initDevice- und enable-Methode des Treibers nochmal aufrufen dürfte das IOKit vermutlich zu sehr verwirren (oder garnicht helfen, weil der Kernel noch irgendetwas anderes macht, um das Interface wieder zu konfigurieren)?

    Für sowas wünscht man sich dann doch dtrace im Darwin-Kernel. Würde hier eigentlich das Kernel-Debugging mit zwei Rechnern funktionieren - sprich, überlebt der remote gdb den Sleep-Zustand des Powerbooks?

    Hmm, wenn ich den komischen Windows C++-Code hier fertig habe, muss ich mal intensiv basteln ;).

    Grüße,
    Michael
  • RE: Wer hat schon mal einen Ethernet-Treiber mit IOKit programmiert...

    Michael,
    ich habe gerade diesen Link gefunden: episteme.arstechnica.com/6/ubb…f=8300945231&m=7480952764

    Ich glaube das wird die Lösung bringen - denn Device abschalten und anschalten ruft in einer bestimmten Reihenfolge irgendwelche Aktionen auf und es geht wieder. Und die entscheidenede müsste sich ja isolieren lassen und dann aufrufen wenn Power wieder angeschaltet werden soll.

    -- hns
  • RE: Wer hat schon mal einen Ethernet-Treiber mit IOKit programmiert...

    Whow, da war jemand fleißig im ars-Forum. Ich hab's nur überflogen, aber alle Achtung. Das ist was, das ich allgemein zu OS X gerne sehen würde - ein "Internals"-Buch analog zum "Design and Implementation of the FreeBSD 5.2 OS", ergänzt mit Tutorials zur Programmierung aller relevanter Teile von Mach bis IOKit.

    Ein gutes Stück in die Richtung wird sicher Amit Singhs Buch kernelthread.com/ gehen - bin schon sehr gespannt.

    Für meinen 3Com USB-Ethernet-Adapter (3C19250 mit Kawasaki LSI KU5KUSB101B-Chipsatz) gibt es in Net- und FreeBSD einen Treiber (kue), dann könnte ich meinem Mac Mini ja mal wirklich ein zweites Netzinterface spendieren...

    Michael