2015-07-21 22 views
5

Ich führe iperf Messungen zwischen zwei Servern, verbunden durch 10Gbit-Link. Ich versuche, die maximale Fenstergröße, die ich beobachte, mit den Systemkonfigurationsparametern zu korrelieren.TCP-Empfangsfenstergröße höher als net.core.rmem_max

Insbesondere habe ich beobachtet, dass die maximale Fenstergröße 3 MiB ist. Ich kann jedoch die entsprechenden Werte in den Systemdateien nicht finden.

von sysctl -a läuft ich die folgenden Werte erhalten:

net.ipv4.tcp_rmem = 4096  87380 6291456 
net.core.rmem_max = 212992 

Der erste Wert sagt uns, dass die maximale Empfangsfenstergröße 6 MiB ist. Allerdings tendiert TCP dazu, die doppelte Größe der angeforderten Größe zuzuweisen, so dass die maximale Empfängerfenstergröße 3 MiB betragen sollte, genau wie ich es gemessen habe. Von man tcp:

Beachten Sie, dass TCP ordnet tatsächlich zweimal die Größe des Puffers in der setsockopt angefordert (2) Ruf, und so ein nachfolgendes getsockopt (2) Anruf wird die gleiche Größe des Puffers nicht zurück, wie in dem angeforderten setsockopt (2) Anruf. TCP verwendet den zusätzlichen Speicherplatz für administrative Zwecke und interne Kernelstrukturen, und die Werte der Datei/proc enthalten die größeren Größen im Vergleich zu den tatsächlichen TCP-Fenstern.

Der zweite Wert, net.core.rmem_max, besagt jedoch, dass die maximale Empfängerfenstergröße nicht mehr als 208 KiB betragen kann. Und das soll die harte Grenze sein, nach man tcp:

tcp_rmem max: die maximale Größe des Puffers von jedem TCP-Socket verwendet erhalten. Dieser Wert überschreibt nicht das globale net.core.rmem_max. Dies wird nicht verwendet, um die Größe des Empfangspuffers zu begrenzen, der mit SO_RCVBUF für einen Socket deklariert wird.

Also, wie kommt und ich beobachte eine maximale Fenstergröße größer als die in net.core.rmem_max angegebene?

Hinweis: Ich habe auch das Bandbreiten-Latenz-Produkt berechnet: window_size = Bandwidth x RTT das ist etwa 3 MiB (10 Gbps @ 2 ms RTT), so dass meine Verkehrserfassung zu überprüfen.

Antwort

1

net.ipv4.tcp_rmem hat Vorrang net.core.rmem_max nach https://serverfault.com/questions/734920/difference-between-net-core-rmem-max-and-net-ipv4-tcp-rmem:

Es scheint, dass die TCP-Einstellung precendence über den gemeinsamen max Einstellung


nehmen Aber ich stimme mit dem, was Sie sagen, das scheint mit dem zu kollidieren, was in man tcp geschrieben ist, und ich kann Ihre Ergebnisse reproduzieren. Vielleicht ist die Dokumentation falsch? Bitte herausfinden und kommentieren!

+1

ich eine Prämie begonnen haben, um herauszufinden, ob 'Mann tcp' ist wirklich falsch. – nh2

4

Eine schnelle Suche aufgedreht:

https://github.com/torvalds/linux/blob/4e5448a31d73d0e944b7adb9049438a09bc332cb/net/ipv4/tcp_output.c

in void tcp_select_initial_window()

if (wscale_ok) { 
    /* Set window scaling on max possible window 
    * See RFC1323 for an explanation of the limit to 14 
    */ 
    space = max_t(u32, sysctl_tcp_rmem[2], sysctl_rmem_max); 
    space = min_t(u32, space, *window_clamp); 
    while (space > 65535 && (*rcv_wscale) < 14) { 
     space >>= 1; 
     (*rcv_wscale)++; 
    } 
} 

max_t nimmt den höheren Wert der Argumente. Der größere Wert hat also Vorrang.

Eine weitere Referenz auf sysctl_rmem_max wird gemacht, wo es verwendet wird, um das Argument auf SO_RCVBUF (in net/core/sock.c) zu begrenzen.

Alle anderen TCP-Code bezieht sich nur auf sysctl_tcp_rmem.

Also ohne den Code suchen tiefer in Sie zu dem Schluss, dass eine größere net.ipv4.tcp_rmemnet.core.rmem_max in allen Fällen, außer außer Kraft gesetzt wird, wenn SO_RCVBUF (deren Prüfung kann mit SO_RCVBUFFORCE umgangen werden) einstellen

+0

'... Sie können daraus schließen, dass ein größeres net.ipv4.tcp_rmem in allen Fällen net.core.rmem_max außer beim Setzen von SO_RCVBUF überschreiben wird - es ist mir noch nicht klar, ob das in allen Fällen geschieht: In der von Ihnen geposteten Funktion , 'max_t (u32, sysctl_tcp_rmem [2], sysctl_rmem_max)' bestimmt 'rcv_wscale', das dann zum Festlegen der Fenstergrößen verwendet wird. Daher sollte das Maximum der beiden Werte verwendet werden. Ich kann jedoch nicht experimentell bestätigen, dass: Wenn "net.core.rmem_max" sehr groß eingestellt ist, wird die Fenstergröße nicht größer als 'tcp_rmem's max. – nh2

+0

Ich habe nicht gesagt, dass die Umkehrung wahr ist (!), Ich würde eher erwarten, dass eine große 'net.core.rmem_max' nicht viel Einfluss hat, wie Sie gesehen haben, weil der gesamte Code nur auf net.ipv4 verweist .tcp_rmem'; Der Verweis auf 'net.core.rmem_max' erfolgt * nur einmal * in einer Routine namens' tcp_select_initial_window'. Aber ich habe nicht in alle Interna geschaut, um zu sehen, was mit 'rcv_wscale' gemacht wurde, nachdem das erste Fenster ausgewählt wurde. Alles, was ich aus einem oberflächlichen Code-Scan schließen kann, ist, dass "net.ipv4.tcp_rmem" in allen Fällen der effektive Wert ist, wenn er größer ist als "net.core.rmem_max". – mvds

+0

Sie haben recht, viele Orte wie [this] (https://github.com/torvalds/linux/blob/34229b277480f46c1e9a19f027f30b074512e68b/net/ipv4/tcp_input.c#L455) und [hier] (https: // github. com/torvalds/linux/blob/34229b277480f46c1e9a19f027f30b074512e68b/net/ipv4/tcp_input.C# L607) verweisen direkt auf 'sysctl_tcp_rmem [2]' anstelle von 'rcv_wscale'. Da es für uns beide intransparent ist, ob 'rcv_wscale' irgendwo anders verwendet wird, habe ich gerade eine E-Mail an' linux-man @ vger.kernel.org' geschickt und um Klärung der man-Seite gebeten. (Weiter im nächsten Kommentar; auf jeden Fall trifft deine Antwort definitiv mein Kopfgeld, thx!) – nh2