GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Kein Pufferspeicherplatz beim Verbinden verfügbar

Nun, ich weiß nicht genau, was das Problem ist, aber ich werde versuchen, die richtige Richtung zu finden, um es zu lösen.

Der ENOBUFS Code wird zurückgegeben, wenn entweder sk_alloc() oder dst_alloc() Ist fehlgeschlagen. Ich kann keine anderen Vorkommen von ENOBUFS finden im Quellcode bezogen auf die Sockets.

Auch kann ich keine Pfade von SYSCALL_DEFINE3(connect) finden bis sk_alloc() , und ich denke, der Socket sollte während connect() nicht zugewiesen werden anrufen wo man den fehler bekommt, daher halte ich es für unwahrscheinlich das die sk_alloc() das Problem verursacht hat.

Die dst_alloc() wird wahrscheinlich zum Überprüfen von Routen während der connect() verwendet , ich kann den genauen Pfad nicht finden, er muss irgendwo darin sein:SYSCALL_DEFINE3(connect) -> .connect() -> ip4_datagram_connect() -> ip_route_connect()

Die dst_alloc() weist einen Eintrag in einem entsprechenden SLAB-Cache zu, und es kann tatsächlich fehlschlagen, wenn der Cache voll ist. Eigentlich sollten alte Einträge gelöscht werden, wenn das passiert, aber vielleicht gibt es Fälle, in denen es immer noch einen Fehler zurückgibt.

Ich denke also, dass Sie in diese Richtung gehen können. Die dst-Cache-Größe kann sich durch /proc/sys/net/ipv4/route/max_size ändern . Überprüfen Sie zunächst, ob die Einstellung (oder andere Einstellungen in sys.net.ipv4.route ) wird durch "zufällige TCP-Optimierungen, die bei Google angezeigt werden" geändert.


In den Kerneln vor 3.6 könnten Sie von ENOBUFS für den regulären IPv4/v6-Verkehr getroffen worden sein, wenn das net.ipv4.route.max_size- oder net.ipv6.route.max_size-Limit entsprechend erschöpft war.

Ab Kernel 3.6 wurde der Routing-Cache entfernt und net.ipv4.route.max_size verlor seinen Einfluss auf die Anzahl der dst-Einträge. Das wäre also im Allgemeinen nicht mehr möglich.

Sie können jedoch immer noch auf diesen Fehler stoßen, wenn Sie IPSec verwenden. Nach einer bestimmten Anzahl von erstellten IPSec-Tunneln konnte ich den Remote-Host nicht anpingen:

# ping 10.100.0.1
connect: No buffer space available

ping von iputils erstellt einen Testdateideskriptor und verwendet connect() darauf, um die dst-IP zu binden. Wenn dies passiert, wird der dst-Cache-Eintrag für das angegebene AF vom Kernel erstellt, und das xfrm4-Limit für dst-Cache-Einträge war in meinem Fall bereits erschöpft. Diese Grenze wird durch die sysctl-Einstellung gesteuert:

xfrm4_gc_thresh - INTEGER
    The threshold at which we will start garbage collecting for IPv4
    destination cache entries.  At twice this value the system will
    refuse new allocations.

Ich bin mit Kernel 3.10.59 darauf gestoßen, wo das Standardlimit sehr niedrig ist - 1024. Ab Kernel 3.10.83 wurde dieses Limit auf 32768 erhöht und wäre viel schwerer zu erreichen.

Also habe ich ausgegeben:

# sysctl net.ipv4.xfrm4_gc_thresh=32768

und es hat das Ding für mich getan.

Ungefährer Pfad im Kernel für meinen Fall mit IPSec:

ip4_datagram_connect() -> ip_route_connect() -> ip_route_output_flow() ->
xfrm_lookup() -> xfrm_resolve_and_create_bundle() ->
... -> xfrm_alloc_dst() -> dst_alloc() with xfrm4_dst_ops, where gc is set.

Linux
  1. Was ist mit dem freien Speicherplatz passiert?

  2. Kann das Farbthema an einen Puffer gebunden werden?

  3. Mit Domainuser zu Webdav (https) verbinden?

  4. Tauschen Sie Speicherplatz auf Cloud-Servern aus

  5. Wie portabel ist mmap?

So löschen Sie den RAM-Speicher-Cache, den Puffer und den Swap-Speicher unter Linux

So überprüfen Sie den Auslagerungsbereich unter Linux

Ubuntu 18.04 Bionic Beaver zum Download verfügbar

Fedora 30-Hintergründe zum Herunterladen verfügbar

Ubuntu 21.10 „Impish Indri“ zum Download verfügbar

Top 10 Linux-Distributionen