Linux仮想マシンでプロセスが「接続」を呼び出すと、「利用可能なバッファスペースがありません」というエラーメッセージが表示されます。原因の追跡に問題があります-誰かが助けてくれることを願っています!
私は以下をチェックしました:
(1)ファイルハンドル:
cat /proc/sys/fs/file-nr
4672 0 810707
私はこれを(割り当て済み、未使用、使用可能)と読んでいるので、問題ありません。
(2)ソケットまたはTCPメモリ:
cat /proc/sys/net/ipv4/tcp_mem
191889 255854 383778
cat /proc/net/sockstat
sockets: used 579
TCP: inuse 169 Orphan 0 tw 245 alloc 187 mem 5
UDP: inuse 31 mem 4
UDPLITE: inuse 0
RAW: inuse 0
FRAG: inuse 0 memory 0
これを使用している合計579のソケットとして読むと、ページの合計は最大値をはるかに下回ります。
たくさんのランダムTCP微調整がGoogleに表示されています-回答で期待しているのは、(1)不足しているリソース、(2)現在のリソースを特定する方法です。値と(3)天井の調整方法。私が見つけたほとんどのページには、(3)以外のすべてが欠けています!
**アップデート#1 **
Flupの提案で、(pingを使用して)発生したときにsystraceを実行しました。
socket(PF_INET, SOCK_DGRAM, IPPROTO_IP) = 4
connect(4, {sa_family=AF_INET, sin_port=htons(1025), sin_addr=inet_addr("10.140.0.65")}, 16) = -1 ENOBUFS (No buffer space available)
**アップデート#2 **
Linuxカーネルソースについてはあまり知りませんが、Digを使用していて、connect()パスの中でENOBUFSを確認できる唯一の場所はここにあります http://lxr.free-electrons.com /source/net/ipv4/af_inet.c?v=3.11#L35
これはkmem_cache_alloc
とsecurity_sk_alloc
...を使用してカーネルに割り当てているようです。
3.6より前のカーネルでは、net.ipv4.route.max_sizeまたはnet.ipv6.route.max_size 制限時に、通常のIPv4/v6トラフィックでENOBUFSの影響を受ける可能性がありました。それに応じて減少しました 。
カーネル3.6以降、 ルーティングキャッシュが削除され 、net.ipv4.route.max_sizeが失われ、dstエントリの量への影響がなくなりました。したがって、一般的には、それはもはや不可能です。
ただし、IPSecを使用している場合でも、私のようにこのエラーが発生する可能性があります。一定量のIPSecトンネルを作成した後、リモートホストにpingできませんでした。
# ping 10.100.0.1
connect: No buffer space available
iputilsからのpingは、テストファイル記述子を作成し、その上でconnect()を使用して、dst ipをバインドします。その場合、指定されたAFのdstキャッシュエントリはカーネルによって作成され、xfrm4 dstキャッシュエントリの制限は私の場合すでに枯渇しています。この制限は、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.
私はカーネル3.10.59を使用してこれに遭遇しました。デフォルトの制限は非常に低い-1024です。カーネル3.10.83から、この制限は32768に増加し、 ヒットするのがはるかに困難になります 。
だから、私は発行しました:
# sysctl net.ipv4.xfrm4_gc_thresh=32768
そしてそれは私のために事をしました。
私の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.
まあ、正確には何が問題なのかはわかりませんが、問題を解決するための正しい方向を見つけようと思います。
sk_alloc()
またはdst_alloc()
のいずれかが失敗すると、ENOBUFS
コードが返されます。ソケットに関連するソースコードでENOBUFS
の他の出現箇所を見つけることができません。
また、SYSCALL_DEFINE3(connect)
からsk_alloc()
へのパスを見つけることができず、エラーが発生するconnect()
の呼び出し中にソケットを割り当てることはできないため、sk_alloc()
が問題の原因である可能性は低いと思います。
dst_alloc()
は、connect()
の間にルートをチェックするために使用される可能性があります。正確なパスが見つかりません。どこかにある必要があります: SYSCALL_DEFINE3(connect)
-> .connect()
-> ip4_datagram_connect()
-> ip_route_connect()
dst_alloc()
は、対応するSLABキャッシュにエントリを割り当てます。キャッシュがいっぱいの場合、実際には失敗する可能性があります。その場合、実際には古いエントリを削除する必要がありますが、それでもエラーが返される場合があります。
ですから、この方向に進むことができると思います。 dstキャッシュサイズは/proc/sys/net/ipv4/route/max_size
。最初に、設定(またはsys.net.ipv4.route
)は、「ランダムにTCP Googleに表示される微調整」によって変更されます。