えんでぃの技術ブログ

えんでぃの技術ブログ

ネットワークエンジニアの視点で、IT系のお役立ち情報を提供する技術ブログです。

Linuxで無線LANが繋がらない時の対処法

wifi-icon

お伝えしたいこと

NUC10を購入してFedoraをインストールしてから約半年間、長らく無線LANが使えない状況でした。
NUCはミニPCとはいえデスクトップなので、私は基本有線で使っています。
無線LANクライアントをずっと無効化したまま使っていました。

その状況が変わり、最近正しく動くようになったので、経緯を共有します。
無線LANが動かずに困っている方に役に立てば良いなと思います。

今回は無線LANの理解を深める前にあっさり直ってしまったため、内容としては薄めです。
1つのケーススタディとして見ていただければと思います。

環境

私の環境を貼っておきます。

項目 概要
PC本体 BXNUC10i5FNH
無線LANクライアント (内蔵) Intel® Wi-Fi 6 AX201 (参考元)
OS Fedora33

発生事象

GUIでの確認

トラブル発生時、GUI上で無線LANを有効化してもSSIDが全く表示されませんでした。

gui_wifi1 loading=

本来であれば、以下のように表示されるはずです。

gui_wifi2

CLIでの確認

CLIでも同様に、SSIDが表示されないことを確認しました。

1行目のコマンドで、無線LANクライアントが有効化されていることを確認しています。
無効の場合は、nmcli radio wifi onで有効化できます。

2行目のコマンドで、SSIDを一覧表示しようとしています。
しかし、どういうわけか何も表示されません。

nmcli radio wifi
# enabled

nmcli device wifi list
# IN-USE  BSSID  SSID  MODE  CHAN  RATE  SIGNAL  BARS  SECURITY

本来では、以下のように表示されるはずです。

nmcli device wifi list
# IN-USE  BSSID              SSID              MODE   CHAN  RATE        SIGNAL  BARS  SECURITY  
#         AA:BB:CC:DD:EE:FF  my-ssid1      Infra  11    405 Mbit/s  100     ▂▄▆█  WPA1 WPA2 
#         11:12:13:14:15:16  my-ssid2      Infra  64    405 Mbit/s  100     ▂▄▆█  WPA1 WPA2 
#         00:11:22:33:44:55  my-ssid3      Infra  9     270 Mbit/s  55      ▂▄__  WPA2 

無線LANが動かない原因

私のケースでは、2つの原因がありました。

  1. 無線LANのデバイスが正しく認識されていなかった
  2. 無線LAN暗号化通信をサポートするパッケージがインストールされていなかった

この2つの原因について、順を追って共有します。

(原因1) 無線LANバイスが正しく認識されない

必要なドライバが足りてなかったことで、無線LANバイスを正しく認識できていなかったようです。
以下に詳細なログを貼ります。

原因1の切り分け

dmesg (Linuxブート中のログ) を見ると、iwlwifiという無線LANクライアントのドライバが無線LANクライアントを正しく検出できず、何度かフォールバックしているように見えます。
※ちなみにiwlwifiは、Intel無線LANに関わるドライバの名称です (iwl = Intel Wireless LAN?)

特に、以下のエラーが悪影響を与えている印象でした。
Direct firmware load for iwlwifi-QuZ-a0-hr-b0-56.ucode failed with error -2
Direct firmware load for iwl-debug-yoyo.bin failed with error -2

しかし最後にAX201という正しいデバイスを認識できているようには見えます。
Detected Intel(R) Wi-Fi 6 AX201 160MHz, REV=0x354

dmesg | grep iwlwifi
# [    5.445530] iwlwifi 0000:00:14.3: enabling device (0000 -> 0002)
# [    5.447086] iwlwifi 0000:00:14.3: Direct firmware load for iwlwifi-QuZ-a0-hr-b0-56.ucode failed with error -2
# [    5.449460] iwlwifi 0000:00:14.3: api flags index 2 larger than supported by driver
# [    5.449471] iwlwifi 0000:00:14.3: TLV_FW_FSEQ_VERSION: FSEQ Version: 65.3.35.22
# [    5.449475] iwlwifi 0000:00:14.3: Found debug destination: EXTERNAL_DRAM
# [    5.449476] iwlwifi 0000:00:14.3: Found debug configuration: 0
# [    5.449698] iwlwifi 0000:00:14.3: loaded firmware version 55.d9698065.0 QuZ-a0-hr-b0-55.ucode op_mode iwlmvm
# [    5.449864] iwlwifi 0000:00:14.3: Direct firmware load for iwl-debug-yoyo.bin failed with error -2
# [    5.628261] iwlwifi 0000:00:14.3: Detected Intel(R) Wi-Fi 6 AX201 160MHz, REV=0x354
# [    5.806506] iwlwifi 0000:00:14.3: base HW address: 04:33:c2:81:04:11
# [    5.821843] iwlwifi 0000:00:14.3 wlp0s20f3: renamed from wlan0

ただ、この話には続きがあります。

lspciコマンドで、Linuxが認識しているPCIバイスを表示できます。
正しくはAX201と表示されるはずですが、なぜかIntel Corporation Wireless-AC 9462と表示されています。
単なる表示上の問題であれば良いのですが、iwlwifiが正しくデバイスを認識できていない可能性も出てきました。

sudo lspci -v | grep -A12 -i 'network controller'
# 00:14.3 Network controller: Intel Corporation Wireless-AC 9462
#   Subsystem: Intel Corporation Device 0074
#   Flags: bus master, fast devsel, latency 0, IRQ 16
#   Memory at 6023114000 (64-bit, non-prefetchable) [size=16K]
#   Capabilities: [c8] Power Management version 3
#   Capabilities: [d0] MSI: Enable- Count=1/1 Maskable- 64bit+
#   Capabilities: [40] Express Root Complex Integrated Endpoint, MSI 00
#   Capabilities: [80] MSI-X: Enable+ Count=16 Masked-
#   Capabilities: [100] Latency Tolerance Reporting
#   Capabilities: [164] Vendor Specific Information: ID=0010 Rev=0 Len=014 <?>
#   Kernel driver in use: iwlwifi
#   Kernel modules: iwlwifi

一方で、正常なときは、以下のようなログになります。

Linux起動時には特にエラーログはなく、フォールバックも発生していません。
読み込まれたファームウェアのファイル名も事象発生時と変わっており、QuZ-a0-hr-b0-59.ucodeと記載があります。
このファイルの実体は/usr/lib/firmware/iwlwifi-QuZ-a0-hr-b0-59.ucodeにあります。

dmesg | grep iwlwifi
# [    4.339129] iwlwifi 0000:00:14.3: enabling device (0000 -> 0002)
# [    4.341962] iwlwifi 0000:00:14.3: api flags index 2 larger than supported by driver
# [    4.341971] iwlwifi 0000:00:14.3: TLV_FW_FSEQ_VERSION: FSEQ Version: 65.3.35.22
# [    4.342152] iwlwifi 0000:00:14.3: loaded firmware version 59.601f3a66.0 QuZ-a0-hr-b0-59.ucode op_mode iwlmvm
# [    4.505557] iwlwifi 0000:00:14.3: Detected Intel(R) Wi-Fi 6 AX201 160MHz, REV=0x354
# [    4.688618] iwlwifi 0000:00:14.3: base HW address: 04:33:c2:81:04:11
# [    4.704444] iwlwifi 0000:00:14.3 wlp0s20f3: renamed from wlan0

Linuxが認識しているデバイス名も、AX201という正しい情報が表示されています。

sudo lspci -v | grep -A12 -i 'network controller'
# 00:14.3 Network controller: Intel Corporation Comet Lake PCH-LP CNVi WiFi
#   Subsystem: Intel Corporation Wi-Fi 6 AX201 160MHz
#   Flags: bus master, fast devsel, latency 0, IRQ 16, IOMMU group 5
#   Memory at 6023114000 (64-bit, non-prefetchable) [size=16K]
#   Capabilities: [c8] Power Management version 3
#   Capabilities: [d0] MSI: Enable- Count=1/1 Maskable- 64bit+
#   Capabilities: [40] Express Root Complex Integrated Endpoint, MSI 00
#   Capabilities: [80] MSI-X: Enable+ Count=16 Masked-
#   Capabilities: [100] Latency Tolerance Reporting
#   Capabilities: [164] Vendor Specific Information: ID=0010 Rev=0 Len=014 <?>
#   Kernel driver in use: iwlwifi
#   Kernel modules: iwlwifi

原因1の解決策

しばらくぶりにsudo dnf upgradeでパッケージを更新したら、上述の正常なログが出るようになりました。
ucodeファイルがそもそも足りていなかったか、iwlwifiがucodeファイルを正しく参照できていなかったか。
いずれにしても、iwlwifi自体に何らかの不具合か互換性不足があり、それがパッケージ更新によって解消されたようです。

時間が解決した、ということですね。

私の環境ではiwl7260-firmwareというrpmパッケージが関係あるようでした。
このパッケージの特定方法は、次のセクションに書きます。

(参考) 必要なrpmファイルの特定の仕方

iwlwifiのドライバが含まれるrpmパッケージは、以下のとおりたくさんあります。
ここでは、以下のrpmパッケージの中に自分が使っている無線LANクライアントに対応したものがあるか確認する方法を紹介します。
今回の方法はrpmを利用するRedHat系かつ、Intel無線LANクライアントを使っている場合のみ使えます。
条件に該当しない方は、適宜手順をアレンジする必要があります。

rpm -qa | grep iwl
# iwl100-firmware-39.31.5.1-119.fc33.noarch
# iwl1000-firmware-39.31.5.1-119.fc33.noarch
# iwl105-firmware-18.168.6.1-119.fc33.noarch
# iwl135-firmware-18.168.6.1-119.fc33.noarch
# iwl2000-firmware-18.168.6.1-119.fc33.noarch
# iwl2030-firmware-18.168.6.1-119.fc33.noarch
# iwl3160-firmware-25.30.13.0-119.fc33.noarch
# iwl3945-firmware-15.32.2.9-119.fc33.noarch
# iwl4965-firmware-228.61.2.24-119.fc33.noarch
# iwl5000-firmware-8.83.5.1_1-119.fc33.noarch
# iwl5150-firmware-8.24.2.2-119.fc33.noarch
# iwl6000-firmware-9.221.4.1-119.fc33.noarch
# iwl6000g2a-firmware-18.168.6.1-119.fc33.noarch
# iwl6000g2b-firmware-18.168.6.1-119.fc33.noarch
# iwl6050-firmware-41.28.5.1-119.fc33.noarch
# iwl7260-firmware-25.30.13.0-119.fc33.noarch

まず、自分が利用している製品の型番を前述のlspci -vで確認します。
lspci -vmmの方が見やすいかもしれません。
今回の場合は、AX201だとわかったとします。

この後すぐできる最も簡単な確認方法は、dnf searchコマンドで検索することです。
パッケージの説明文に型番が書いてあるので、今回はこの方法が使えます。
この結果、iwl7260-firmwareがヒットしました。

dnf search AX201
# iwl7260-firmware.noarch : Firmware for Intel(R) Wireless WiFi Link 726x/8000/9000/AX200/AX201 Series Adapters

上記方法でヒットしないケースもあります。
例えばAX210に対応するドライバも上記パッケージに本当は含まれているのですが、説明文に書いてないのでヒットしません。
そんなときは、次の方法で確認します。

Linux Wireless WikiでサポートされているIntel無線LAN機器の一覧を確認します。
このページでAX201を検索し、対応するドライバが含まれるtar.gzファイルをダウンロードして中身を確認します。
今回は、iwlwifi-Qu-48.13675109.0.tgzをダウンロードします。

すると、中にいくつかのucodeファイルが入っています。
どれでも良いので、一つのucodeファイルの名前をメモしてください。
今回は、iwlwifi-Qu-b0-hr-b0-48.ucodeにします。

続いて、dnf providesコマンドで上記ファイルを含むrpmパッケージを検索します。
dnf providesには、ファイルをフルパスで指定する必要があります。
今回は/usr/lib/firmware/iwlwifi-Qu-b0-hr-b0-48.ucodeが正しい指定方法なのですが、フルパスを知らなくてもワイルドカードで検索できます。
**は、任意の文字列かつ、任意階層分だけフォルダを下った場合もマッチするワイルドカードです。
言い換えると、**は「/を含む任意の文字列」にマッチします。

dnf provides **iwlwifi-Qu-b0-hr-b0-48.ucode
# iwl7260-firmware-1:25.30.13.0-119.fc33.noarch : Firmware for Intel(R) Wireless WiFi Link 726x/8000/9000/AX200/AX201 Series Adapters

以上の確認により、AX201に必要なrpmパッケージはiwl7260-firmwareだとわかりました。

もちろん、私の環境において必要だったQuZ-a0-hr-b0-59.ucodeも今回の検索でヒットします。

dnf provides **QuZ-a0-hr-b0-59.ucode
# iwl7260-firmware-1:25.30.13.0-119.fc33.noarch : Firmware for Intel(R) Wireless WiFi Link 726x/8000/9000/AX200/AX201 Series Adapters

本来必要なucodeファイルは、事象解消時のdmesgから読み取れます。
トラブル発生中に必要なucodeファイルを見抜く方法は、残念ながら私にはわかりませんでした。

# [    4.342152] iwlwifi 0000:00:14.3: loaded firmware version 59.601f3a66.0 QuZ-a0-hr-b0-59.ucode op_mode iwlmvm

(原因2) パッケージが足りていない

原因1を解決してもSSIDが表示されなかったので、更に調査を進めました。
その結果、wpa_supplicantというパッケージが不足していることが原因だとわかりました。

原因2の切り分け

無線LANを有効化したタイミングで、/var/log/messagesに以下のログが発生していました。
恐らく、journalctl -xeu NetworkManagerでも同様のログを確認できると思います。

NetworkManager[950]: <error> [1619738834.7337] device (wlp0s20f3): Couldn't initialize supplicant interface: Failed to D-Bus activate wpa_supplicant service

原因2の解決策

以下のコマンドでwpa_supplicantをインストールすることで直りました。

sudo dnf install wpa_supplicant

このパッケージにより、wpa_supplicant.serviceが作成されます。
このサービスは無線LANを有効化したタイミングで自動起動されるので、有効化する必要はないようです。
sudo systemctl enable --now wpa_supplicant.serviceの実行は、私の環境では不要でした。

以上の対応により原因1と原因2を解消し、無事無線が使えるようになりました。

(参考) wpa_supplicantとは?

wpa_supplicantとは、WEP、WPA、WPA2などの無線LAN暗号化技術における認証クライアントです。
言い換えれば、上述の暗号化技術を用いて無線LAN接続をするのに必要なプログラムです (参考:ArchLinux Wiki)。

初期状態のFedora33には、wpa_supplicantがインストールされていないようです。
これにより、SSIDを表示することすらできなかったようです。

(参考) 起動できないネットワークは無効化すべき

主張

今回の事象のように、無線LANが使えないなどの理由でNetworkManagerのconnectionが起動できないケースはあると思います。
基本的には、connectionが使えないときはその原因を排除して使えるようにするのが良いと思います。
しかしどうしても解決できないときは、OS起動の度にconnection起動を失敗させるのではなく、connectionを初めからdownさせておくべきです。
コマンドでいうと、nmcli radio wifi offなどです。
autoconnect offよりも更にシンプルに、デバイスレベルでwifiを無効にします。

理由

起動に失敗するconnectionを停止しておくべき理由は、OSの起動が遅くなるためです。

LinuxのOSが起動する際、様々なサービスが順番に起動します。
systemctl cat <unit>を実行するとわかりますが、サービス間には依存関係があります。
特に多くのサービスは、ネットワークに依存しています。

つまり、ネットワーク接続が完了しないと、他のサービスの起動が開始されません。

NetworkManager.service については、ネットワーク起動を待つための専用サービスがあります。
それがNetworkManager-wait-online.serviceです。
中身を見てみましょう。
description、実行コマンド、環境変数のみ抜粋しています。

systemctl cat NetworkManager-wait-online
# `nm-online -s` waits until the point when NetworkManager logs
# "startup complete". That is when startup actions are settled and
# devices and profiles reached a conclusive activated or deactivated
# state.

# ExecStart=/usr/bin/nm-online -s -q

# Environment=NM_ONLINE_TIMEOUT=30

内部的にはnm-online -s -qを実行していて、NetworkManagerがstartup completeというログを出力するまで待つようです。
NetworkManagerが30秒以内にログを出さなければ、NetworkManager-wait-onlineタイムアウトする作りです。
NetworkManager-wait-onlineは、NetworkManagerサービスの起動を最大30秒待つことで、他のネットワークに依存するサービスの起動失敗を防ぐ仕組みです。

内部的に実行しているnm-onlineのmanを見てみます。
-sオプションの説明に以下の記述がありました。
autoconnect (connectionの自動起動) に失敗すると、NetworkManagerの起動完了を遅延させるケースがあるようです。
実際、無線LAN自動起動に失敗することでLinuxの起動が遅くなることが確認できました。

For example, by setting a connection profile to autoconnect, such a profile possibly will activate during startup and thus delay startup complete being reached.

どの程度起動が遅くなるのか

では、connection自動起動の失敗により、Linuxの起動がどの程度遅くなるのか。 systemd-analyze blameコマンドで大体の検討がつきます。

systemd-analyze blameを実行すると、各サービスの起動にかかった時間を長い順に表示します。
NetworkManager-wait-onlineの数字が30秒の場合は、何かがおかしいことが多いです。

systemd-analyze blame
# 10.568s dnf-makecache.service
#  9.205s NetworkManager-wait-online.service
#  948ms systemd-udev-settle.service

ただし気をつけていただきたいのは、この表示はLinux起動時間に影響を与えた時間ではありません。
純粋に各プロセスの起動から停止までにかかった時間を表しています。
上記表示は、「NetworkManager-wait-online.serviceによりLinuxの起動が9.205秒遅延した」という意味ではありません。
...今回の場合は、起動に約9秒の影響を与えていますが。

影響を見るには、次のコマンドが適切です。
起動時間のグラフをSVGファイルとして出力します。
GUIで開くことで、画像として開くことができます。

systemd-analyze plot > tmp.svg

グラフは以下のように見えます。
NetworkManager-wait-online.serviceが完了するまで9.2秒待ち続け、その後network-online.targetが起動し、他のネットワークに依存するサービスが起動開始しています。

systemd-analyze

まとめ

Linux無線LANが動作しない原因を2パターン紹介しました。
同じような事象で困っている方の役に立てれば嬉しいです。

無線LANがうまく動作しないときは停止させておくのもぜひ実践してみてください。
Linuxの起動が更に早くなりますよ。
一方、NetworkManager-wait-onlineを無効化するのは、やめておいたほうが良いと思います。

関連記事

Linux パソコン関連の記事をまとめてあります。

endy-tech.hatenablog.jp