Featured image of post Linuxでネットが落ちる問題

Linuxでネットが落ちる問題

目次

背景

  • ReazonSpeech のデータセットを Hugging Face から DL すると、高確率でネットワークが落ちてしまう
  • データ自体は 4TB あり、最初は Hugging Face 側の問題かと思っていた
  • しかし実際には、ローカルの Linux PC 側のネットワークが切れている問題だった
  • WiFi 自体は落ちていないので、単純に自分の Linux PC の問題だと判断した

事前に入れるコマンド

1
sudo apt install iw
  • iw は Linux で WiFi デバイスの状態確認や設定変更を行うためのコマンド
  • 今回の場合は、WiFi の省電力設定を確認したり、無効化したりするために使う

現状チェック

外部ドメインに疎通できるか確認する

1
2
ping google.com
...
  • ping google.com は、ドメイン名を使って外部に疎通できるかを確認するコマンド
  • この確認には、以下の2つが含まれる
    • DNS で google.com を IP アドレスに名前解決できるか
    • 名前解決後、その IP アドレスまで実際に通信できるか
  • そのため、ここで失敗しただけでは DNS の問題なのか、ネットワーク経路の問題なのかはまだ分からない

DNS を使わず IP アドレスに直接 ping する

1
2
3
4
5
6
7
8
ping 1.1.1.1
PING 1.1.1.1 (1.1.1.1) 56(84) bytes of data.
From 192.168.3.8 icmp_seq=1 Destination Host Unreachable
From 192.168.3.8 icmp_seq=2 Destination Host Unreachable
From 192.168.3.8 icmp_seq=3 Destination Host Unreachable
From 192.168.3.8 icmp_seq=4 Destination Host Unreachable
From 192.168.3.8 icmp_seq=5 Destination Host Unreachable
From 192.168.3.8 icmp_seq=6 Destination Host Unreachable
  • 1.1.1.1 は Cloudflare の DNS サーバー
  • ドメイン名ではなく IP アドレスに直接 ping しているので、この確認では DNS を経由しない
  • ここで Destination Host Unreachable になっているため、少なくとも DNS の問題ではなさそうだと分かる
  • また、エラーの送信元が 192.168.3.8、つまり自分の Linux PC になっている。これは、PC 自身が「宛先に到達できない」と判断している状態

IPv4 アドレスが付与されているか確認する

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
ip -4 a

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
3: wlo1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    altname wlp0s20f3
    inet 192.168.3.8/24 metric 600 brd 192.168.3.255 scope global dynamic wlo1
       valid_lft 18793sec preferred_lft 18793sec
4: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
5: br-xxxxx: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
    inet 172.18.0.1/16 brd 172.18.255.255 scope global br-xxxx
       valid_lft forever preferred_lft forever
  • ip -4 a は、各ネットワークインターフェースに付与されている IPv4 アドレスを確認するコマンド
  • ここでは WiFi インターフェースである wlo1192.168.3.8/24 が付与されている
  • つまり、DHCP による IP アドレス取得自体は成功している
  • この時点で、少なくとも「IP アドレスがないから通信できない」という状態ではない

ルーティングテーブルを確認する

1
2
3
4
5
6
7
ip route

default via 192.168.3.1 dev wlo1 proto dhcp src 192.168.3.8 metric 600 
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1 linkdown 
172.18.0.0/16 dev br-d3b6513508a9 proto kernel scope link src 172.18.0.1 linkdown 
192.168.3.0/24 dev wlo1 proto kernel scope link src 192.168.3.8 metric 600 
192.168.3.1 dev wlo1 proto dhcp scope link src 192.168.3.8 metric 600 

ip route は、通信先ごとにどのネットワークインターフェースを使うかを確認するコマンド。

重要なのは以下の行。

1
default via 192.168.3.1 dev wlo1 proto dhcp src 192.168.3.8 metric 600
  • これは、通常のインターネット向け通信は 192.168.3.1 をゲートウェイとして、wlo1 から出ていくという意味
  • つまり、default route も存在している
  • この時点で、以下は確認できた
    • wlo1 に IP アドレスはある
    • default route もある
    • それでも外部に通信できない

デフォルトゲートウェイを取り出す

1
2
ip route | awk '/default/ {print $3; exit}'
192.168.3.1
  • このコマンドは、ip route の出力から default 行を探し、その3列目を表示している
  • 今回の出力では、デフォルトゲートウェイは 192.168.3.1

デフォルトゲートウェイに ping する

bash の場合は、以下のように変数に入れて確認する。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
GW=$(ip route | awk '/default/ {print $3; exit}')

echo "$GW"
192.168.3.1

ping -c 5 "$GW"
PING 192.168.3.1 (192.168.3.1) 56(84) bytes of data.
From 192.168.3.8 icmp_seq=1 Destination Host Unreachable
From 192.168.3.8 icmp_seq=2 Destination Host Unreachable
From 192.168.3.8 icmp_seq=3 Destination Host Unreachable
From 192.168.3.8 icmp_seq=4 Destination Host Unreachable
From 192.168.3.8 icmp_seq=5 Destination Host Unreachable

--- 192.168.3.1 ping statistics ---
5 packets transmitted, 0 received, +5 errors, 100% packet loss, time 4078ms
pipe 4
  • ping -c 5 "$GW" は、デフォルトゲートウェイに5回 ping を送るコマンド
  • ここで Destination Host Unreachable になっている
  • つまり、インターネットに出られないだけではなく、同じ LAN 内にいるはずのルーター 192.168.3.1 にも到達できていない
  • この時点で、問題は DNS や Hugging Face 側ではなく、かなりローカル側に寄っている

ARP の状態を確認する

1
2
3
4
5
ip neigh show dev wlo1 

192.168.3.1 INCOMPLETE 
fe80::da0f:99ff:fed9:ac8d lladdr d8:0f:99:d9:ac:8d router STALE 
2400:2412:3360:4d00:1111:1111:1111:1111 router FAILED 
  • ip neigh show dev wlo1 は、wlo1 から見た近隣ホストの状態を確認するコマンド
  • ARPとは「IPアドレスからMACアドレスを調べる仕組み」
  • 以下のような流れ
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    
      Linux PC
      192.168.3.1 に送りたい
      でも 192.168.3.1 のMACアドレスが分からない
      ARPで「192.168.3.1 のMACアドレスを教えて」と聞く
      ルーターがMACアドレスを返す
      そのMACアドレス宛に通信する
    
  • IPv4 では主に ARP の状態を見るために使う

今回重要なのは以下。

1
192.168.3.1 INCOMPLETE
  • INCOMPLETE は、ARP 解決に失敗している状態
  • つまり、PC は 192.168.3.1 というルーターの IP アドレスは知っているが、その IP アドレスに対応する MAC アドレスを取得できていない
  • 同じ LAN 内で通信するには、IP アドレスだけではなく MAC アドレスも必要になる
  • そのため、ARP が失敗していると、ルーターにすらパケットを届けられない

NetworkManager から見たデバイス状態を確認する

1
2
3
4
5
6
7
8
nmcli dev status

DEVICE           TYPE      STATE      CONNECTION 
br-d3b6513508a9  bridge    unmanaged  --         
docker0          bridge    unmanaged  --         
enp2s0           ethernet  unmanaged  --         
lo               loopback  unmanaged  --         
wlo1             wifi      unmanaged  --         
  • nmcli dev status は、NetworkManager から見たネットワークデバイスの状態を確認するコマンド
  • ここでは wlo1 が WiFi デバイスとして見えているが、STATEunmanaged になっている
  • この表示だけで今回の原因だと断定はできないが、NetworkManager の管理状態を確認する上では見ておく価値がある

復旧方法

NetworkManager の再起動だけでは復旧しなかった。

1
sudo systemctl restart NetworkManager
  • sudo systemctl restart NetworkManager は、Linux のネットワーク管理サービスである NetworkManager を再起動するコマンド
  • ただし今回の症状では、これだけでは復旧しなかった
  • その後、WiFi の無線機能を一度オフにしてからオンにした
1
2
nmcli radio wifi off
nmcli radio wifi on
  • nmcli radio wifi off は WiFi をソフトウェア的に無効化するコマンド
  • nmcli radio wifi on は WiFi を再度有効化するコマンド
  • 今回のように、IP アドレスや route は残っているが ARP が壊れている状態では、WiFi を一度落として再接続させることで復旧することがある

考察

  • wlo1 に IP アドレスは付与されており、default route も存在していた
  • しかし、Destination Host Unreachable になっていた
1
ping 192.168.3.1
  • そのため、DNS や Hugging Face 側ではなく、PC とルーター間の L2 通信が壊れている状態だったと考えられる
  • 特に以下が重要だった
1
2
ip neigh show dev wlo1
192.168.3.1 INCOMPLETE
  • INCOMPLETE は ARP 解決に失敗している状態で、ルーターの MAC アドレスを取得できていない
  • つまり、今回の状態は以下だった
    • WiFi 接続自体は見えている
    • IP アドレスもある
    • route もある
    • しかし ARP が失敗して通信できない
  • WiFi はつながっているように見えるが、実際には同じネットワーク内のルーターにフレームを届けられない状態になっていた

切り分け

今回確認した内容を整理すると、以下になった。

確認項目状態
WiFi 接続OK
DHCPIP 取得済み
default route正常
DNS関係なし
インターネット到達不可
ルーター疎通不可
ARP失敗

そのため問題箇所は下の区間となる。

1
Linux PC ←→ WiFi AP / ルーター

次発生したら試すコマンド

WiFi 省電力を無効化

まず、現在の WiFi 省電力設定を確認する。

1
iw dev wlo1 get power_save
  • iw dev wlo1 get power_save は、wlo1 の WiFi 省電力設定が有効かどうかを確認するコマンド
  • 省電力が有効になっている場合は、以下で無効化する
1
sudo iw dev wlo1 set power_save off
  • sudo iw dev wlo1 set power_save off は、wlo1 の WiFi 省電力機能を無効化するコマンド
  • 大きなデータセットを長時間ダウンロードするようなケースでは、WiFi の省電力機能が悪さをして通信が不安定になる可能性がある

WiFi 省電力設定を永続化する

  • 一時的に iw で無効化しても、再起動後に設定が戻ることがある
  • 永続化する場合は、NetworkManager の設定ファイルを作成する
1
2
sudo mkdir -p /etc/NetworkManager/conf.d
sudo vim /etc/NetworkManager/conf.d/wifi-powersave.conf
  • sudo mkdir -p /etc/NetworkManager/conf.d は、NetworkManager の追加設定を置くディレクトリを作成するコマンド
  • sudo vim /etc/NetworkManager/conf.d/wifi-powersave.conf は、省電力設定用の設定ファイルを編集するコマンド

ファイルの中身は以下にする。

1
2
[connection]
wifi.powersave = 2
  • wifi.powersave = 2 は、WiFi の省電力を無効化する設定
  • 設定を反映するには、NetworkManager を再起動する
1
sudo systemctl restart NetworkManager

ドライバ確認

1
lspci -nnk | grep -A4 -i network
  • lspci は PCI デバイスを一覧表示するコマンド
  • grep -A4 -i network は、network という文字列を大文字小文字を無視して探し、その後ろ4行も表示する指定
  • これにより、WiFi デバイスのチップセットや、使用中のカーネルドライバを確認できる
  • Intel 系なら iwlwifi が使われていることが多い
  • ドライバ名が分かると、同じ症状の既知問題を調べやすくなる

ログ確認

切断時に NetworkManager のログを見る。

1
journalctl -u NetworkManager -b
  • journalctl は systemd のログを見るコマンド
  • -u NetworkManager は NetworkManager サービスのログだけに絞る指定
  • -b は現在の起動以降のログだけを見る指定

次に、カーネル側のログも見る。

1
dmesg | grep -iE 'wifi|wlan|iwlwifi'
  • dmesg はカーネルログを表示するコマンド
  • grep -iE 'wifi|wlan|iwlwifi' は、wifiwlaniwlwifi を大文字小文字を無視して検索する指定
  • 切断時刻の周辺にエラーが出ていれば、WiFi ドライバやファームウェア側の問題を疑える

まとめ

  • WiFi が見えていても、通信できるとは限らない
  • IP アドレスと default route があっても、ARP が失敗するとルーターにすら届かない
  • ping 1.1.1.1 が失敗したら、DNS 以外の問題を疑う
  • ping <default gateway> が失敗したら、PC とルーター間の問題を疑う
  • ip neigh show dev wlo1INCOMPLETE が出ていたら、ARP 解決に失敗している
  • 今回は nmcli radio wifi offnmcli radio wifi on で復旧した
  • 次に起きたら、WiFi 省電力設定、ドライバ、NetworkManager ログ、カーネルログを確認する
  • Linux のネットワーク周りは、見た目上つながっているのに実際には通信できないことがある
  • 今回も「WiFi は落ちていない」「IP もある」「route もある」のに、ARP が死んでいて通信できないという状態だった

参考文献

Built with Hugo
テーマ StackJimmy によって設計されています。