Hallo alle zusammen,
ich versuche momentan mit meinem Digilent Atlys Spartan 6 FPGA (XPS
14.3) eine Ethernet-Verbindung zu einem PC aufzubauen und via UDP Daten
an diesen zu senden. Dafür benutze ich lwIP und den AXI Ethernet Lite
MAC.
Das Senden funktioniert auch ohne Probleme. Leider aber viel langsamer
als es möglich wäre.
Das Ziel dieses Testaufbaus soll es sein, in schnneller Folge Pakete mit
1400 Byte Nutzdaten über UDP zu übertragen. Ich habe 1 String-Array
(data mit 1400 Byte), der immer wieder gesendet werden soll. Dies wird
immer 1000 Mal in einer for-Schleife gemacht. Am Ende der Schleife (also
nach 1000 Paketen) kommt eine printf-Funktion, die ich zum Zählen der
Pakete bzw. zum Messen der vergangenen Zeit verwende.
Dabei kommt heraus, dass ca 3500 Pakte pro Sekunde gesendet werden, was
bei 1400 Byte insgesamt ca. 5 MByte/s (40 MBit/s) entspricht.
Beim AXI Ethernet Lite MAC sollten eigentlich 100Mbit/s möglich sein.
Habe ich wirklich schon die maximale Leistung erreicht oder lässt sich
im Code oder in den lwIP-Optionen noch eine bessere Performance
erreichen?
Die Einstellungen bei lwIP stehen alle noch beim Standard. Einzig bei
"temac_adapter_options --> "phy_link_speed" habe ich den Wert auf
"CONFIG_LINKSPEED100" gesetzt, um sicherzugehen, dass die richtige
Geschwindigkeit angepeilt wird.
Weiß jemand Rat? Jede Geschwindigkeitssteigerung ist willkommen.
Vielleicht habe ich "pbuf" oder "memcpy" bisher nicht richtig benutzt.
Ich bedanke mich im Voraus für Anregungen und Tipps!
LG
Meine main.c zu dem ganzen Aufbau findet ihr hier:
Also auf Deinem Board ist ja erstmal ein FPGA. Um Deinen C-Code laufen
zu lassen ist dort wahrscheinlich irgendeine Softcore-CPU implementiert.
Wie schnell ist die denn getaktet?
Ich hatte mal eine Faustregel gelesen "1MHz pro MBit/s". Also je
nachdem, wie schnell Deine CPU ist, sind 40 MBit/s gar nicht so
schlecht.
Ich würde auch eher einen Pin/LED togglen als printf. Letzteres kann Dir
ganz schön in die Suppe spucken, was Zeit angeht...
Ich benutze einen MicroBlaze-Prozessor mit 100 MHz Taktrate. Also
theoretisch müsste er das stemmen könnnen.
Und das mit dem printf musste ich anfangs auf sehr schmerzliche Weise
feststellen, wo ich völlig geistesabwesend nach JEDEM Paket ein printf
gesendet habe und mich gewundert habe, warum da nahezu gar nichts
passierte. Der printf-Befehl alle 1000 Pakete fällt aber nicht so stark
ins Gewicht.
Möglicherweise liegt es daran, dass du den Buffer immer wieder neue
allokierst. Behalte den einfach mal und kopiere immer nur wieder die
Daten rein, dann dürfte es schneller gehen denke ich.
Obwohl das sehr nachvollziehbar klang, hat das die Geschwindigkeit sogar
verkleinert. Auf 3,5 MByte/s (28 Mbit/s).
Folgendermaßen sah der letzte Part des Programms aus:
Aus irgendwelchen Gründen, muss der pbuf vor jedem Senden neu
angefordert und nach dem Senden wieder fallengelassen werden, damit es
schneller läuft...
Das war leider auch noch nicht die Lösung.
LG
Wir hatten damals zu Virtex PPC Zeiten damit experimentiert. Der Lwip
ist halt sehr lahm. Aif jeden Fall mussten wir das Checksum Offloading
benutzen und die Puffer ziemlich groß wahlen, erst dann haben wir mit
dem PPC und einem angepassten Stack die volle GbE Geschwindigkeit
jedenfalls in UDP erreicht. Allerdings war das FPGA dann schon voll.
Bei einem Softcore ist die Effizienz ja noch schlimmer, ohne Checksummen
Berechnung in Hardware kann das schon sein dass da nicht mehr geht.
Da lwIP eigentlich recht gut dokumentiert ist sowie häufig genutzt wird
und ich noch nicht so die großen VHDL-Erfahrungen habe, wollte ich es
erst mal auf diese Weise probieren und schauen, wie weit ich die
Performance ausreizen kann.
Wenn allerdings nicht mehr aus der Kombo "lwIP und AXI Ethernet Lite"
rauszuholen ist, müssen wohl andere Lösungen her.
Aber wer weiß; vielleicht hat ja noch jemand eine Idee. Ich versuche
mich noch mal an ein paar Puffer- und Checksummen-Einstellungen in
lwIP...
Die UDP Prüfsumme kann ja rein theoretzisch weggelassen werden (auf 0
setzen).
Musst mal gucken ob der Empfänger das Paket dann noch annimmt und ob das
schneller wird.
Die Ethernetframe CRC lässt sich durchsichtig zum AXI Modul berechnen.
Dazu einfach mal gucken wie das MII zum PHY IC funktioniert.
Hätte da auch etwas VHDL für dich übrig.
Alex W. schrieb:> Da lwIP eigentlich recht gut dokumentiert ist sowie häufig genutzt wird> und ich noch nicht so die großen VHDL-Erfahrungen habe, wollte ich es> erst mal auf diese Weise probieren und schauen, wie weit ich die> Performance ausreizen kann.
Mit dem Microblaze das MAX/UDP packet per Hand bauen und den MAC driver
selbst ansprechen. Nach dem Init mit dem Senden des ersten packets etwas
warten. Sind nur wenige Zeilen. Bekommst Du das hin?
Falls Dein lwIP an einem Windows-PC angeschlossen ist, so hat der lwIP
auch noch die vielen vom Windows-PC abgeschickten packets zu
verarbeiten.
Moin,
ich würde auch raten, den lwIP in die Ecke zu werfen und den UDP Stack
selber zu implementieren. Braucht nur noch bisschen Code für ARP und
ICMP.
Falls der Prozessor mit der Uebertragung ausgelastet ist, muss DMA her,
würde ich allerdings gleich von Anfang an machen. Mit manchen Cores
gehen sogar "Zerocopy"-Ansätze wie beim EMAC des Blackfin (kann man sich
aus der HW Referenz abgucken). Damit kriegst du dann den maximal
möglichen Durchsatz hin. Checksumme kann man später bei Bedarf in den
Core verfrachten.
Grüsse,
- Strubi
Strubi schrieb:> Braucht nur noch bisschen Code für ARP und> ICMP.
Je nach Anwendungsfall eher nicht. PC-MAC und PC-IP dem Microblaze
anders mitteilen oder PC-MAC und IP aus einem vom PC gesendeten
UDP-Packet an den richtigen Port herausziehen. (Edit: Bei Bedarf kann
man in diesem packet dem FPGA auch seine IP dynamisch mitteilen) Den
ganzen Rest ignorieren.
> Falls der Prozessor mit der Uebertragung ausgelastet ist, muss DMA her,> würde ich allerdings gleich von Anfang an machen.
Kann die MAC hier DMA-Master sein? Sonst gibt es vielleicht etwas im MAC
driver.
> Checksumme kann man später bei Bedarf in den> Core verfrachten.
Braucht es nicht. Die zwingend erforderliche Checksumme wird nur über
den Header gebildet. Da ändert sich nicht viel.
Die UDP-Prüfsumme habe ich in der Datei opt.h ausgestellt.
/**
* CHECKSUM_GEN_UDP==1: Generate checksums in software for outgoing UDP
packets.
*/
#ifndef CHECKSUM_GEN_UDP
#define CHECKSUM_GEN_UDP 0
#endif
Desweiteren habe ich die Anzahl der Buffer im pbuf-Pool verdoppelt und
die direkte Prüfsummenberechnung probiert.
/**
* LWIP_CHECKSUM_ON_COPY==1: Calculate checksum when copying data from
* application buffers to pbufs.
*/
#ifndef LWIP_CHECKSUM_ON_COPY
#define LWIP_CHECKSUM_ON_COPY 1
#endif
Das alles hat leider auch keine Veränderungen gebracht.
Lars R. schrieb :
> Mit dem Microblaze das MAX/UDP packet per Hand bauen und den MAC driver> selbst ansprechen. Nach dem Init mit dem Senden des ersten packets etwas> warten. Sind nur wenige Zeilen. Bekommst Du das hin?
Ich habe im Moment noch keine Vorstellung, wie das zu machen ist. Kannst
du mir einen Beispielcode schicken, der diese Vorgehensweise praktisch
zeigen könnte? Klingt auf jeden Fall vielversprechend.
Ansonsten ist wohl das Fazit, dass lwIP nicht die beste Leistung mit dem
Ethernet Lite IP Core hinkriegt. Mit dem lizenzpflichtigen Tri-Mode
Ethernet Media Access Controller (TEMAC) sollen wohl auch
Geschwindigkeiten von 1000 Mb/s gehen. Wenn man das (viele) Geld dafür
investieren möchte, ginge wohl auch eine bessere Performance mit lwIP.
Oder man macht den UDP-Stack halt selbst.
Gibt es empfehlenswerte Anleitungen zu diesem Thema?
Alex W. schrieb:> Ich habe im Moment noch keine Vorstellung, wie das zu machen ist.
Siehe wikipedia.
> Kannst> du mir einen Beispielcode schicken, der diese Vorgehensweise praktisch> zeigen könnte? Klingt auf jeden Fall vielversprechend.
anbei
> Oder man macht den UDP-Stack halt selbst.>> Gibt es empfehlenswerte Anleitungen zu diesem Thema?
Dass man das Nachimplementieren des lwIP, um am Ende mit gleicher oder
ähnlicher Funktionalität auch noch eine höhere Performance zu erzielen,
erst einmal können muss. Bis 100Mbit gibt es doch auch genügend andere,
FPGA-Hersteller-unabhängige Lösungen
Alex W. schrieb:> Mit dem lizenzpflichtigen Tri-Mode Ethernet Media Access Controller> (TEMAC) sollen wohl auch Geschwindigkeiten von 1000 Mb/s gehen. Wenn man> das (viele) Geld dafür investieren möchte, ginge wohl auch eine bessere> Performance mit lwIP.
Eben nicht, der lwip ist ganz gruselig ineffizient, wir haben damals
Temac und lwip sein lassen. Da war nur etwas über 100Mbit bei GbE drin.
Lars R. schrieb:> Strubi schrieb:>> Braucht nur noch bisschen Code für ARP und>> ICMP.>> Je nach Anwendungsfall eher nicht. PC-MAC und PC-IP dem Microblaze> anders mitteilen oder PC-MAC und IP aus einem vom PC gesendeten> UDP-Packet an den richtigen Port herausziehen. (Edit: Bei Bedarf kann> man in diesem packet dem FPGA auch seine IP dynamisch mitteilen) Den> ganzen Rest ignorieren.>
ARP sollte man auf jeden Fall implementieren. Sonst gibt's nur Probleme
in nem richtigen Netzwerk. Sobald ein Router dazwischen ist, geht der
Spass los. Ist keine Hexerei, ARP zu handeln.
>> Falls der Prozessor mit der Uebertragung ausgelastet ist, muss DMA her,>> würde ich allerdings gleich von Anfang an machen.>> Kann die MAC hier DMA-Master sein? Sonst gibt es vielleicht etwas im MAC> driver.>
Master ist immer der DMA-Controller. Der MAC holt sich die Daten
typischerweise aus dem FIFO (Taktdomänen-Kopplung zw. DMA und MAC) und
die DMA-Engine signalisiert in einem Status-Return per Buffer, ob das
Paket erfolgreich raus/kollidiert, usw. ist. Siehe Blackfin EMAC-Doku.
>> Checksumme kann man später bei Bedarf in den>> Core verfrachten.>> Braucht es nicht. Die zwingend erforderliche Checksumme wird nur über> den Header gebildet. Da ändert sich nicht viel.
Und dein Header ist für alle Pakete derselbe? :-)
Wie schon gesagt, kann man die Checksumme auch weglassen, der
Ethernet-Layer macht das typ. auf MAC-Ebene. Vielleicht meinst du das?
Es gibt da eine Reihe Referenzanwendungen, wie den GigE Video
UDP-transport, wo sich Pleora damals mit ihren Cores durchgesetzt hat.
Da kann man sich einiges abgucken. Nur komplett den Stack in Hardware zu
machen ist bei 100MBit eher Nonsense.
Eine andere pragmatische Lösung wäre, nen Wiznet5100 oder 5300 mit
(UDP/TCP SoC) ranzuflanschen und den ganzen lwip-Mist und weitere
Eigenentwicklungen zu vermeiden. Wenn 100 MB/s reichen...
Das Problem bei lwip ist eine fehlende saubere Buffer Queue und zuviel
Rumkopieren, gar nicht gehen dynamische mallocs, die in manchen
Implementationen per pbuf_alloc stattfinden, das geht deutlich
eleganter, schneller und robuster.
Strubi schrieb:> Lars R. schrieb:>> Strubi schrieb:>>> Braucht nur noch bisschen Code für ARP und>>> ICMP.>>>> Je nach Anwendungsfall eher nicht. PC-MAC und PC-IP dem Microblaze>> anders mitteilen oder PC-MAC und IP aus einem vom PC gesendeten>> UDP-Packet an den richtigen Port herausziehen. (Edit: Bei Bedarf kann>> man in diesem packet dem FPGA auch seine IP dynamisch mitteilen) Den>> ganzen Rest ignorieren.>>>> ARP sollte man auf jeden Fall implementieren. Sonst gibt's nur Probleme> in nem richtigen Netzwerk. Sobald ein Router dazwischen ist, geht der> Spass los. Ist keine Hexerei, ARP zu handeln.
und ICMP und DCHP und DoS-Attacken-Handling, sonst gibt es nur Probleme,
sobald es im Internet eingesetzt wird... Die Frage ist, was die Aufgabe
ist. Hierzu habe ich mich an das Posting und die Fragen des TO gehalten.
>>> Checksumme kann man später bei Bedarf in den>>> Core verfrachten.>>>> Braucht es nicht. Die zwingend erforderliche Checksumme wird nur über>> den Header gebildet. Da ändert sich nicht viel.>> Und dein Header ist für alle Pakete derselbe? :-)
Fast. Denn wenn ich nicht alles mögliche implementiere, habe ich nur
UDP-Pakete. Diese benötigen nicht zwingend eine Checksum über die
Nutzdaten.
> Wie schon gesagt, kann man die Checksumme auch weglassen, der> Ethernet-Layer macht das typ. auf MAC-Ebene. Vielleicht meinst du das?
Ich meine das, was ich geschrieben habe. Genauer: Den Inhalt des
MAC-Frames vom ersten bis zum letzten Byte.
> Das Problem bei lwip ist eine fehlende saubere Buffer Queue und zuviel> Rumkopieren, gar nicht gehen dynamische mallocs, die in manchen> Implementationen per pbuf_alloc stattfinden, das geht deutlich> eleganter, schneller und robuster.
Die Schwierigkeit ist nicht, zu dieser Erkenntnis zu erlangen, sonderen
dass scheinbar kaum etwas besseres zu vergleichbaren Kosten verfügbar
ist und dass es nicht trivial ist, einfach so etwas besseres zu
entwickeln. Sonst hätte das bereits jemand aus dem Handgelenk heraus
getan UND kostenfrei zur Verfügung gestellt oder in den lwIP einfließen
lassen.
Viele Grüße
Lars
Edit: Wird höchste Performanz benötigt, so hänge ich kein Netzwerk
dazwischen und bearbeite auch keine anderen Anfragen. Für alles andere,
das ebenfalls hohe Performanz jenseits 100MBit benötigt, ist irgend ein
Linuxgerät zum weitereichen der Daten (zB FPGA-Board mit ARM) am
Einfachsten.
Edit2: ...allein schon deshalb, weil es bisher keine langzeitverfügbaren
1Gig-Phys für die Abnahme von kleinen Stückzahlen gibt und keiner einem
den Aufwand dankt.
Lars R. schrieb:> Ich meine das, was ich geschrieben habe. Genauer: Den Inhalt des> MAC-Frames vom ersten bis zum letzten Byte.>
Stop, bitte jetzt kein Chaos machen. Nochmal zur Zusammenfassung:
a) UDP Header: Checksumme nicht zwingend nötig
b) Ethernet-Header und Paket: Checksumme erforderlich.
Alles andere sind non-standard Hacks. Sollte man gar nicht erst mit
anfangen.
>> Das Problem bei lwip ist eine fehlende saubere Buffer Queue und zuviel>> Rumkopieren, gar nicht gehen dynamische mallocs, die in manchen>> Implementationen per pbuf_alloc stattfinden, das geht deutlich>> eleganter, schneller und robuster.>> Die Schwierigkeit ist nicht, zu dieser Erkenntnis zu erlangen, sonderen> dass scheinbar kaum etwas besseres zu vergleichbaren Kosten verfügbar> ist und dass es nicht trivial ist, einfach so etwas besseres zu> entwickeln. Sonst hätte das bereits jemand aus dem Handgelenk heraus> getan UND kostenfrei zur Verfügung gestellt oder in den lwIP einfließen> lassen.
Hätte er eben nicht. Das ist ein grundsätzliches Problem der Architektur
von lwip. Zu Scatter-Gather-Konzepten gibt es eine Menge Material, und
man kann durchaus einen Stack so schreiben, dass er beides kann (been
there, done that). Aber warum sollte man das Knowhow verschenken?
Das gute an lwip ist immerhin, dass er auf fast allen MAC-Konzepten
irgendwie zum Laufen zu kriegen ist. Wer Performance will, muss in die
Tasche greifen. Fraunhofer verschenken ihren HW-TCP-Stack auch nicht.
Erst schreibst Du, dass der TO ARP und weiteres benötigt, falls er mal
in eine Situation kommt, von der im Eingangspost noch gar nichts
geschrieben hat. Dann schreibst Du, dass er für die Performanz, die er
sucht und mit dem Funktionsumfang, von dem Du sagst, dass er ihn
benötigt, etwas zahlen sollte. Und Du schreibst, dass Du über eine
solche Lösung verfügst.
Das wäre alles sehr verständlich, wenn diese Anfrage in Markt gestellt
worden wäre.
Lars, mit Verlaub, dein suggestiver Unterton ist etwas 'deja vu' und
unkonstruktiv.
Um weitere Missverständnisse zu vermeiden:
1) Ich habe eine für mich passende Lösung. Einige andere, die hier
posten, offenbar auch.
2) Ich biete sie nicht an. Grund: Sehr spezifisch zum Projekt und
Problem.
3) Selbermachen rechnet sich meist. So schrieb ich es auch.
Bitte gewöhne dich doch einfach daran, dass es legitim ist, hier Tips zu
geben ohne was verkaufen/verschenken zu wollen.
Dass von einem Opensource-Projekt wie lwip immer darauf geschlossen
wird, dass alle Verbesserungen diesbezüglich für lau sind, hat mich zu
obigem Kommentar verleitet.
In der Rubrik "Markt" wirst du auch bei frenetischem Suchen keinen
finden, der dir die universelle Highspeed-Lösung für alle möglichen
MAC-designs anbietet.
Sorry, dass ich Dich missverstanden habe. In meinem Umfeld verhält sich
ein Verkäufer oder Anbieter von Dienstleistungen nun einmal genau so,
wie Du hier.
Mir ist über das bereits oben Geschriebene hinaus überhaupt nicht klar,
warum Du dem TO empfiehlst, ARP und ICMP unbedingt zu implementieren,
wenn er bisher noch nicht einmal ein einzelnes UDP-Paket abschicken kann
das Absenden von UDP-Paketen sogar bisher das einzige ist, wonach er
gefragt hat.
Lars R. schrieb:> Sorry, dass ich Dich missverstanden habe. In meinem Umfeld verhält> sich> ein Verkäufer oder Anbieter von Dienstleistungen nun einmal genau so,> wie Du hier.>
Das dürften dann ziemlich miese Verkäufer sein :-)
Das hiesige Forum ist für mich (noch) eine Plattform für den Austausch
zwischen Entwicklern ohne (Ver)kaufsinteresse. Diejenigen mit Budget
kaufen sich typischerweise den ganzen Kuchen.
> Mir ist über das bereits oben Geschriebene hinaus überhaupt nicht klar,> warum Du dem TO empfiehlst, ARP und ICMP unbedingt zu implementieren,> wenn er bisher noch nicht einmal ein einzelnes UDP-Paket abschicken kann> das Absenden von UDP-Paketen sogar bisher das einzige ist, wonach er> gefragt hat.
ARP ist schlicht eine Minimalanforderung in einem Netzwerk, damit die IP
einer Ethernet-Adresse zugeordnet werden kann. Habe auch schon Stacks in
den Fingern gehabt, die das nicht tun, der damit auftretende
Konfigurationsoverhead macht nur das Leben schwer. Muss nicht sein.
Zudem geneerieren unbeantwortete, damit repetitive ARP-Requests nur
unnötig Verkehr. Manche Smart-Hubs deaktivieren u.U in so Fällen sogar
die Buchse.
ICMP ist schlicht nützlich, sei da
* ping
* echo
* Destination unreachable
Derjenige, der von lwip in Richtung Performance migrieren möchte, sollte
IMHO dieses Minimum implementieren, gerade wenn der Peer eine Linuxkiste
ist. Die paar zusätzlichen Paket-Handler belasten die CPU schliesslich
nicht.
Aber wollen wir uns mal nicht so an einem Nebensatz aufhaken...
Lars R. schrieb:> Mir ist über das bereits oben Geschriebene hinaus überhaupt nicht klar,> warum Du dem TO empfiehlst, ARP und ICMP unbedingt zu implementieren,> wenn er bisher noch nicht einmal ein einzelnes UDP-Paket abschicken kann> das Absenden von UDP-Paketen sogar bisher das einzige ist, wonach er> gefragt hat.
Nach meiner Erfahrung ist es wirklich hilfreich erst ARP reply, dann
ICMP reply (ping) und zum Schluß UDP zu implementieren.
Damit folgt man einfach dem Protokollstapel.
Beim Hausbau fängt man ja auch nicht mit dem Dach und dem Einbau der
Fenster an, sondern mit Keller oder Bodenplatte...
Duke