GNU/Linux >> Znalost Linux >  >> Linux

Při připojení není k dispozici vyrovnávací paměť

No, nevím, v čem přesně je problém, ale pokusím se najít správný směr jeho řešení.

ENOBUFS kód je vrácen, když je buď sk_alloc() nebo dst_alloc() selhal. Nemohu najít žádné další výskyty ENOBUFS ve zdrojovém kódu souvisejícím se sokety.

Také nemohu najít žádné cesty z SYSCALL_DEFINE3(connect)sk_alloc() , a myslím, že soket by neměl být alokován během connect() zavolejte, kde se zobrazí chyba, takže si myslím, že není pravděpodobné, že sk_alloc() způsobil problém.

dst_alloc() se pravděpodobně používá pro kontrolu tras během connect() , nemohu k němu najít přesnou cestu, musí to být někde uvnitř:SYSCALL_DEFINE3(connect) -> .connect() -> ip4_datagram_connect() -> ip_route_connect()

dst_alloc() přiděluje položku v odpovídající mezipaměti SLAB a může ve skutečnosti selhat, pokud je mezipaměť plná. Pokud k tomu dojde, staré záznamy by měly být vyčištěny, ale možná existují případy, kdy stále vrací chybu.

Takže si myslím, že můžete přejít tímto směrem. Velikost mezipaměti dst se může změnit až do /proc/sys/net/ipv4/route/max_size . Nejprve zkontrolujte, zda nastavení (nebo jakékoli jiné nastavení v sys.net.ipv4.route ) je změněno „náhodnými vylepšeními TCP zobrazenými na Googlu“.


V jádrech před 3.6 jste mohli být zasaženi ENOBUFS pro běžný provoz IPv4/v6, když byl odpovídajícím způsobem vyčerpán limit net.ipv4.route.max_size nebo net.ipv6.route.max_size.

Počínaje jádrem 3.6 byla směrovací mezipaměť odstraněna a net.ipv4.route.max_size ztratil svůj vliv na množství položek dst. Takže obecně by to již nebylo možné.

Stále však můžete narazit na tuto chybu jako já při používání IPSec. Po určitém počtu vytvořených IPSec tunelů se mi nepodařilo pingnout vzdáleného hostitele:

# ping 10.100.0.1
connect: No buffer space available

ping z iputils vytvoří deskriptor testovacího souboru a použije na něj connect() k navázání dst ip. Když se to stane, dst cache entry pro daný AF je vytvořen jádrem a limit dst cache entries xfrm4 byl v mém případě již vyčerpán. Tento limit je řízen nastavením sysctl:

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.

Narazil jsem na to pomocí jádra 3.10.59, kde je výchozí limit velmi nízký - 1024. Počínaje jádrem 3.10.83 byl tento limit zvýšen na 32768 a bylo by mnohem těžší ho dosáhnout.

Takže jsem vydal:

# sysctl net.ipv4.xfrm4_gc_thresh=32768

a udělal to pro mě.

Přibližná cesta v jádře pro můj případ s 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. VPN Kill Switch pro OpenVPN Connect nyní k dispozici

  2. Co se stalo s volným prostorem?

  3. Výměna místa na cloudových serverech

  1. Jak přenosný je mmap?

  2. V zařízení nezbývá místo

  3. git gc:na zařízení nezbývá místo, i když jsou k dispozici 3 GB a tmp_pack pouze 16 MB

  1. Může se barevný motiv vázat na vyrovnávací paměť?

  2. Připojit k Webdav (https) s uživatelem domény?

  3. Připojte se ke cloudovému serveru