Batctl f - fragmentierung verschlechtert durchsatz um den faktor 10

wir machen gerade für wireguard ausgedehnte Tests in unserem Supernode Backbone.
Dabei kommen wir u.a. darauf das Batman mit Fragmentierung der Durchsatz um den Faktor 10 schlechter ist.
Wenn man trotz eingeschalteter Fragmentierung Pakete da rein schickt die klein genug sind (iperf -M 1300 bspw.) ist es weiterhin schnell - logisch, da dan ndie fragmentierung nicht zum Tragen kommt
jemand eine Idee woran das liegen könnte, dass mit Fragementierung so ein mieser Durchsatz zustande kommt?

# ohne Fragmentierung mtu 1332
batctl f 0
iperf3 ~ 700 MBs
# mit fragmentierung mtu 1500
batctl if 1
iperf3 ~ 60 MBs
2 Likes

Kann ich leider nur bestätigen.
Die Batman-Fragmentierung kostet überproportional viel Performance.
Daher sollte man sie in jedem Fall vermeiden.

Also mit allen Möglichkeiten, inkl. DHCP-Options, MSS clamping bereits den Client dazu bringen, nicht in Fragmentierung zu geraten, selbst wenn sie buggy sind.

1 Like

Ich fürchte, ich brauche das in -vvvvv, mindestens :frowning:

Batman erhöht selbst die MTU des WLAN auf weit über 1500, muß also bei Ethernet-Übergang i. d. R. fragmentieren.

Configuration
 
First of all, fragmentation shouldn't be needed (except for  tt-tables, see below). It is a fix for drivers/hardware that is unable to handle MTU's greater than 1528 bytes, it is slow (due to increase is packets), and is susceptible to packet loss.

It can be enabled and disabled in the sysfs file:
% echo 1 > /sys/class/net/bat0/mesh/fragmentation # enable (default)
% echo 0 > /sys/class/net/bat0/mesh/fragmentation # disable

or by using batctl:
% batctl f 1 # enable
% batctl f 0 # disable

Fragmentierung ist somit die Voreinstellung, warum das aber um Größenordnungen langsamer sein soll, erschließt sich mir nicht: batman_adv ist ein Kernel-Protokoll, die Kontext-Wechsel fallen also an sich weg. Pakete werden auch nicht auf auf maximale Paketgröße aufgebauscht, insofern gibt es keinen nachvollziehbaren Impact durch mehrere kleine Pakete?

ich kann grad nicht sagen wie der fragmentation impact sonst ist, aber auf unserem
wireguard + l2tpv3 + batman-adv-v15 konstrukt schlug sich das so nieder wie oben beschrieben. An der Stelle können wir auf Fragmentierung verzichten, da wir eh nur das rein bekommen was der fastd durchlassen wird von den knoten und das ist eh klein genug.
Grundsätzlich interessieren mich aber vor diesem Hintergrund die fragmentierung metriken insgesamt.

Hint: WLAN hat in der Regel fest 1500 mtu, das geht nur mit Schmerz und nur mit manchen Geräten anders, damit bekommst du quasi in der Regel am WLAN 1500 mtu Pakete, die werden dann in batman gepackt und haben dann eben 1528 und sind so oder so zu groß für bspw. fastd und müssen fragmentiert werden. Idealerweise passiert das nur dort, und wird nur am Empfänger wieder ausgepackt.

(und das würde mich interessieren, was passiert wenn man iperf mal mit kleineren Paketen durch den fastd jagt, ist dann auf den kleinen kisten auch schon signifikant alles besser?)

Reden wir hier davon, dass Fragmentierung auf Gateways und Clients in Batman ausgeschaltet werden muss, oder genügt es das auf den GWs zu tun?

Wenn ich das richtig verstehe, ergibt sich bei „korrekter“ MTU so oder so kein Unterschied. Nur bei inkorrekter MTU bekommt man eben mit Batman-Fragmentierung noch eine langsame Verbindung, ohne Fragmentierung jedoch gar keine. Oder verstehe ich das falsch?

AP-Client und Webserver (da wo der Client herumsurft…) müssen die MTU korrekt erkennen.
Das sollte eigenltich™ automatisch funktionieren nach Standard x, y und z.
Diversen halbdefekten Endgeräten, Anwendungen und Serverdiensten muss man aber mit dem Zaunpfahl winken. Und bei einigen funktioniert nichtmal dieses.

Fragmentierung war schon immer böse. Wohl auch ein Grund, warum das (für Router) im ipv6 nicht implementiert wurde. Deswegen:

Ich empfehle überall die MTU auf 1280 zu announcen. Im radvd bitte auch „link mtu 1280“ setzen und zusätzlich die tcp-mss für kaputte Geräte zu manipulieren.

Von was für einer MTU auf dem Tunnel (z.B. fastd) geht ihr denn hier aus?

1280 ist bei ipv6 die kleinst mögliche MTU. ipv4 kann kleiner. Wichtig ist, dass die Pakete insgesamt kleiner 1492 bleiben (1500-8 für pppoe). Davon noch den Header vom fastd (oder l2tp) tunnel abziehen, und davon dann noch den header vom batman. Man kann das klitzeklein raussuchen und exakt ausrechnen, aber mit 1280 bleibt man drunter. Wenn man es klitzeklein ausgerechnet hat, hat man vermutlich unwesentlich an Performace gewonnen.

Jemand Zeit eine Aufstellung für die einzelnen Header rauszusuchen und den maximalen Wert auszurechnen?

(Korrigiert mich, wenn ich falsch liege.)

Angenommen, mein fastd Interface hat eine MTU von 1280 Byte.
In diesen 1280 Byte werden folgende Header transportiert:

  1. TCP mit 20 Byte
  2. IPv4 mit 20 Byte
  3. Ethernet mit 14 Byte
  4. batman-adv (unicast) mit 10 Byte

Gesamt: 64 Byte Header

Ergo: Um Fragmentierung zu verhindern, müsste ich die MSS auf 1216 begrenzen. Oder?

Siehe dazu auch [B.A.T.M.A.N.] Fragmentation and padding in batman-adv und Fragmentation-technical - batman-adv - Open Mesh und Tweaking - batman-adv - Open Mesh

Hmm, dann würde v6 über den Tunnel nimmer tun, oder? AFAIK ist die minimale Paketgröße bei v6 1280 Bytes, d. h. 1280+52+14+20=1366 Bytes wären als äußere MTU minimal notwendig für fastd via v6 (vgl. fastd-Doku)?

Anders rum? Wenn das Interface, durch das Pakete zu den Knoten geleitet werden x Byte hat, dann werden y Byte vom Batman drauf kommen. Hinzu noch z Byte vom fastd oder l2tp. Wenn du dann mit x+y+z über 1500 (1492) liegst, dann wird der VPN Server schon fragmentieten müssen, wenn er es zum Ethernet raus schiebt. Selbst wenn der Server Gigabit hat und Jumbo Frames kann: irgendwo auf dem Weg zum Knoten unterstützt ein Gerät macimal 1500 und fragmentiert (vielleicht).

Die 1500 sind Ethernet netto. 1514 ist Ethernet brutto, also incl. den erwähnten 14 Byte.

nochmal langsam - bevor das hier zu einer MTU debatte ausartet (die hier vermutlich weniger zum Tragen kommt) : dazu gerne mal die Suche bemühen https://forum.freifunk.net/search?q=mtu

kurz fürs Protokoll mtu und fastd : setup fastd auf plasterouter schiebt daten zum supernode
da passiert erstmal folgendes, das fastd interface auf dem knoten hat eine MTU - das ist was fastd da real an daten reinpackt, in unserem fall 1280. Fastd hat aber headerfoo (wie jedes Protokoll) das kommt obendrauf , im extremfall 86byte . dann hängt das if noch im batman mit 28 byte und dort wird auch die Fragmentierung übernommen. (sofern batctl f 1)
Dazu auch die Beispiele im fastd ansehen http://fastd.readthedocs.io/en/v18/manual/mtu.html
siehe zur Fragmentierung auch Fragmentation-technical - batman-adv - Open Mesh
Sidenode1: das ganze ist wichtig da WLAN in der Regel auf 1500 mtu fix ist, das bedeutet, da kommen real 1500er Pakete rein, dieser wifitraffic ist was in den fastd geroutet wird, die kann man sich kleiner Wünschen, das klappt aber nicht immer, wird deswegen umschifft (weis garnicht wie groß das problem real ist „heutzutage“)
Sidenode2: 1280 ist spec limit für v6 pakete, kleiner funktioniert trotzdem - so wie das mit specs so is, fastd sagt unter 600 (edit fastd_v18 " --mtu, -M Sets the MTU; must be at least 576") is ende.
Sidenode3: alle batman nodes können defragmentieren, tun das auch wenn das auf dem if wo es weitergeht dann platz genug gibt. batctl f 1 bestimmt auschliesslich ob der knoten auch selber fragmentiert. das ist im zusammenhang mit round-robin IF gleicher güte dann spassig, weil die quali vielleicht gleich ist, aber die mtu unterschiedlich. (ins blaue geraten und hier OFFFFFFFTOPIC)

zurück zu dem Ausgangsproblem
(gehe zurück auf Los … )
Wir haben im Backbone - also zwischen den VM/Supernodes von uns sehr erfolgreich wireguard tunnel aufgemacht und darauf l2tpv3 gesetzt und darauf batman-adv
wenn wir mit iperf die Pakete künstlich klein hielten liegt der durchsatz bei ± 700 Mbs
wenn wir die optionale batman-adv fragmentierung abschalteten liegt der durchsatz ebenfalls bei ± 700 Mbs
wenn wir aber pakete die laut mtu klein genug sein müssten da durchschieben klappt alles auf 60 Mbs zusammen.
da wundert uns zum 1. der Faktor 10 verschlimmbesserung, und 2. wieso kommt batman da auf die idee zu fragmentieren, wenn doch laut if mtu eh nur 1280 (bspw.) rein konnte?

»Anders rum« macht wenig Sinn, da die nutzbare MTU je Anschluß augenscheinlich variabel ist. Sofern um ein v6-Paket zu übertragen 1280 Bytes zwingend notwendig sind, muß man doch von der Nutzlast ausgehend gucken, welche Größe der Tunnel haben muß?

MTU: Auf einem Interface mit mtu 1500 werden ausgehende Pakete die grösser als 1500 Byte sind fragmentiert, falls die fragmentiert werden dürfen. Ansonsten werden sie, mit Benachrichtigung an den Sender, verworfen.

Es können größere Pakete empfangen werden.

Wird im DHCP eine MTU von 1280 vorgegeben, hält sich das Betriebssystem in der Regel daran, auch wenn das WLAN dazwischen weiterhin 1500 und mehr in einem Paket transportieren kann.

Noch ein Mal zum Verständnis. Eure Tunnel-Interfaces (sei es nun fastd oder l2tpv3) haben eine MTU von 1280?
Zur Vereinfachung gehe ich jetzt erst Mal nur von IPv4 aus.

Ohne batman-adv: TCP muss eine MSS von 1240 beigebracht bekommen (z.B. durch MSS-Clamping), damit die Pakete inkl. TCP und IPv4 Header „durch“ das Interface „passen“.

Mit batman-adv: Durch das Interface will nicht nur ein TCP und ein IPv4 Header, sondern auch ein Ethernet (14 Byte) und ein batman-adv (unicast Paket, 10 Byte) Header. fastd soll diesen ganzen Kram (Payload + die vier geschilderten Header) dann an eine andere fastd Instanz weiterleiten, muss also seinen eigenen Header und einen IPv4 Header hinzufügen. Diese beiden Header haben erst Mal nichts mit der 1280 Byte MTU des Interfaces zu tun, sorgen aber dafür, dass am Ende über die Leitung Pakete der maximalen Größe 1280 + fastd Header + IPv4 Header laufen.

Ihr seht also vermutlich Fragmentierung, weil eure nicht-batman Pakete so groß sind, dass sie inkl. batman-header und Ethernet Header nicht „durch eine 1280 Byte MTU passen“. MSS-Clamping auf 1216 Byte könnte das Problem, dass man Fragmentierung sieht, also beheben?

Oder ich verstehe hier gerade das Problem nicht. In dem Fall: sorry :smile:

Ich verstehe das so:

|fastd   |batman     | ip  |
----------------------------
|   z    |     y     |  x  |
----------------------------

Der Payload x (IP) sollte so klein gewählt werden, dass x + y + z kleiner 1500, besser kleiner 1492 (pppoe) sind.

In Düsseldorf nutzen wir eine MTU von 1332 für die Clients.

MTU Fastd/L2TP - Overhead Batman (v15 : 32 bytes bzw v14 : 24 bytes) = Nutzbare MTU

1364 - 32 = 1332

Nun von der nutzbaren MTU 40 bytes abziehen um den MSS wert zu erhalten:

1332 - 40 = 1292

In iptables wäre der Befehl:

iptables -A FORWARD -o tun+ -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --set-mss 1292 -m comment --comment „ipv4-mss-fix“

In dhcpd benutzen wir die folgende Config:

# suppress wpad DHCPINFORM requests from MSFT devices
# See https://lists.isc.org/pipermail/dhcp-users/2013-September/017193.html
option wpad code 252 = text;
option wpad "\n\000";
class "MSFT" {
  match if substring(option vendor-class-identifier, 0, 4) = "MSFT";
  option dhcp-parameter-request-list = concat(option dhcp-parameter-request-list, fc);
}

ddns-update-style none;
option domain-name ".local";
default-lease-time 900;
max-lease-time 7200;
subnet 10.25.0.0 netmask 255.255.224.0 {
    authoritative;
    range 10.25.10.0 10.25.19.255;
    append dhcp-parameter-request-list 1,3,6,12,15,26,28,51,54;
    option domain-name-servers 10.25.0.1;
    option routers 10.25.0.1;
    option interface-mtu 1332;
}
3 Likes

@CyrusFox die iptables regel würde ich noch etwas spezifischer gestalten und „–mss 1293:1536“
vor das set einfügen damit auch nur zu große pakete angepackt werden ;o

Ansonsten kann ich nur voll und ganz zustimmen, wer auch schon mss clamping nutzt sollte
mal gucken ob er auch wie cyrus „FORWARD“ statt „POSTROUTING“ benutzt denn das
funktioniert bei nat kisten wesentlich besser :>

1 Like

Man kann noch diskutieren, ob man das auch noch für IPv6 tun möchte und nicht nur für IPv4.
Und ja, die diversen MTU-Werte (DHCP, fastd, iptables) berechnet man am besten irgendwo zentral in einem Script und die diversen anderen Configs werden daraus abgeleitet.
Ansonsten ist die Gefahr ziemlich groß, bei Änderungen irgendwo etwas zu übersehen.

 iptables -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --set-mss ${MSSMTU}
 ip6tables -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --set-mss ${MSSMTU}
1 Like