Gentoo Linux在MacBook Pro配置Wifi

备注

broadcom-sta 私有驱动非常难以安装,对内核互斥选项很多,实际上 ebuild 的维护者也说这个驱动已经不再维护,建议直接购买内核 brcmfmac 驱动支持的兼容无线网卡 BCM943602CS ,在二手市场上只需要20美金。

  • 我准备最后再折腾一下 broadcom-sta 私有驱动安装 最终通过回退 wpa_supplicant 版本2.8 解决无线网卡无流量问题 非常 ugly ,我准备改为采用兼容无线网卡避免新版本内核的退化

    • 目前最有希望的方案是参考 Broadcom Wireless Drivers ,该文档是最新的 5.16.11 内核实践,提供了很多修复异常报错的方法

    • 我目前实在没有精力来折腾,所以准备购买Linux兼容的无线网卡来绕过这个问题 为了使用闭源broadcom-sta导致很多新内核特性无法使用实在觉得得不偿失 ,这个闭源驱动从2015年以后就没有更新,所以在最新的内核中需要很多hack才能使用,代价很大

  • MacBook Pro 15" Late 2013 我在淘宝上花50元换一块 BCM943602CS蓝牙无线模块 省的以后再折腾这种私有驱动了

  • MacBook Air 13" Early 2014 找不到内置兼容的无线网卡模块,太古老低端设备,我通过购买外接USB无线网卡来解决

Broadcom WiFi

早期MacBook Air 11" 2011版

我曾经使用过MacBook Air 11" 2011版,这款笔记本使用的是Broadcom B43xx系列,是可以使用 b43-firmware 驱动的,装 b43 驱动即可:

MacBook Air 11" 2011版可以使用 b43 驱动
echo "sys-firmware/b43-firmware" >> /etc/portage/package.accept_keywords
echo "sys-firmware/b43-firmware Broadcom" >> /etc/portage/package.license
emerge --ask b43-firmware

Broadcom BCM4360

MacBook Pro 15" Late 2013 以及我另外一台 MacBook Air 13" Early 2014 ,采用是 Broadcom BCM4360 。这款无线芯片对开源支持不佳,参考 Linux wireless b43文档 可以看到 b43 驱动不支持BCM4360,建议使用 wl 驱动 broadcom-sta

也就是需要使用闭源的Broadcom驱动( Apple Macbook Pro Retina - Closed source Broadcom driver )

lspci -k 输出硬件信息
# lspci -k
...
03:00.0 Network controller: Broadcom Inc. and subsidiaries BCM4360 802.11ac Wireless Network Adapter (rev 03)
	Subsystem: Apple Inc. BCM4360 802.11ac Wireless Network Adapter
	Kernel driver in use: bcma-pci-bridge
	Kernel modules: bcma
...

内核

IEEE 802.11

至少需要激活 cfg80211 (CONFIG_CFG80211) 和 mac80211 (CONFIG_MAC80211)

内核激活 cfg80211 (CONFIG_CFG80211) 和 mac80211 (CONFIG_MAC80211)
[*] Networking support  --->
    [*] Wireless  --->
        <M>   cfg80211 - wireless configuration API
        [ ]     nl80211 testmode command
        [ ]     enable developer warnings
        [ ]     cfg80211 certification onus
        [*]     enable powersave by default
        [*]     cfg80211 DebugFS entries # 文档没有要求,我选择激活
        [ ]     support CRDA
        [ ]     cfg80211 wireless extensions compatibility
        <M>   Generic IEEE 802.11 Networking Stack (mac80211)
        [*]   Minstrel
        [*]     Minstrel 802.11n support
        [ ]       Minstrel 802.11ac support
              Default rate control algorithm (Minstrel)  --->
        [*]   Enable mac80211 mesh networking support # 文档没有要求,但我这个功能有时候有用
        -*-   Enable LED triggers
        -*-   Export mac80211 internals in DebugFS
        [ ]   Trace all mac80211 debug messages
        [ ]   Select mac80211 debugging features  ----

备注

由于需要加载firmware,所以 wireless configuration API (CONFIG_CFG80211) 需要配置成模块方式而不是直接buildin

备注

对于私有驱动, 似乎 需要关闭 mac80211 (CONFIG_MAC80211)

WEXT

cfg80211 wireless extensions compatibility 选项( WEXT )可以支持传统的 wireless-toolsiwconfig :

内核激活 cfg80211 wireless extensions compatibility 选项( WEXT )
[*] Networking support  --->
    [*] Wireless  --->
        [*]     cfg80211 wireless extensions compatibility

备注

我在 Kernel 6.1.12 未找到这个配置项

设备驱动

注意,建议将驱动编译为内核模块,因为WiFi驱动通常需要firmware,只有作为模块加载时才能使用firmware:

内核激活相应的驱动内核模块
Device Drivers  --->
    [*] Network device support  --->
        [*] Wireless LAN  --->
 
            Select the driver for your Wifi network device, e.g.:
            <M> Broadcom 43xx wireless support (mac80211 stack) (b43)
            [M]    Support for 802.11n (N-PHY) devices
            [M]    Support for low-power (LP-PHY) devices
            [M]    Support for HT-PHY (high throughput) devices
            <M> Intel Wireless WiFi Next Gen AGN - Wireless-N/Advanced-N/Ultimate-N (iwlwifi)
            <M>    Intel Wireless WiFi DVM Firmware support                             
            <M>    Intel Wireless WiFi MVM Firmware support
            <M> Intel Wireless WiFi 4965AGN (iwl4965)
            <M> Intel PRO/Wireless 3945ABG/BG Network Connection (iwl3945)
            <M> Ralink driver support  --->
                <M>   Ralink rt27xx/rt28xx/rt30xx (USB) support (rt2800usb)
 
-*- Cryptographic API --->
    Accelerated Cryptographic Algorithms for CPU (x86)  --->
       <*> Ciphers: AES, modes: ECB, CBC, CTS, CTR, XTR, XTS, GCM (AES-NI)

备注

b43 可以在内核源码中激活模块方式编译,但是Broadcom4360需要私有驱动 net-wireless/broadcom-sta 没有编译选项

对于安装私有驱动,上述设备驱动我全关闭了

但是参考 Closed source Broadcom driver 采用激活Intel PRO/Wireless 2100网卡驱动来输出内核的 LIB80211

Device Drivers
   -> Network device support
      -> Wireless LAN
         -> <*>   Intel PRO/Wireless 2100 Network Connection

LED支持

笔记本内置WiFi没有LED,可忽略

内核WiFi的LED支持(数据包收发LED triggers)
Device Drivers  --->
    [*] LED Support  --->
        <*>   LED Class Support
 
[*] Networking support  --->
    [*] Wireless  --->
        [*] Enable LED triggers

Firmware

根据 gentoo linux wiki: WiFi 文档,除了内核模块编译支持之外,WiFi芯片还需要对应firmware:

Broadcom无线网卡驱动及firmware

WiFi设备

驱动

Firmware

说明

Broadcom 43xx 无线芯片

b43 / b43legacy

sys-firmware/b43-firmware

可用于 Aircrack-ng ,如果bcm43xx设备被该驱动支持则通常是最好的选择

Broadcom PCIe和SDIO/USB设备

brcmsmac / brcmfmac

sys-kernel/linux-firmware

缺乏节能,LED支持以及一些其他功能

Broadcom 43xx 无线芯片

wl

net-wireless/broadcom-sta

私有驱动,没有AP或监控模式,可以支持 b43 不支持的芯片,如4360

快速起步: Broadcom BCM4360驱动和Firmware

备注

上文的絮絮叨叨,实际上你要快速解决问题的话,只有一个步骤: 见这里

综上所述,对于 Broadcom BCM4360 实际上就只有安装私有驱动和firmware了,几乎连内核驱动模块都省了:

  • 安装 wl 驱动和firmware:

安装Broadcom BCM4360的私有驱动和firmware
emerge --ask net-wireless/broadcom-sta

备注

net-wireless/broadcom-sta 同时包含了驱动和firmware

broadcom-sta 编译时会检查当前内核编译配置,如果有冲突选项会提示,按提示调整内核编译配置,例如我遇到以下内核配置需要关闭:

X86_INTEL_LPSS  #位于 "Processor type and features ==> Intel Low Power Subsystem Support"
PREEMPT_RCU 不能设置为 Preemptible Kernel  Preemption Model  #位于General setup ==> RCU Subsystem

经验总结

  • 实际上最好的内核参数校验(是否满足 wl 正常运行)就是安装 net-wireless/broadcom-sta 输出信息

  • 将输出信息项和 /usr/src/linux/.config 进行对比就知道内核配置有哪些不能满足闭源 wl 驱动的运行条件

genkernel 内核安装 broadcom-sta

  • 安装 wl 驱动和firmware:

安装Broadcom BCM4360的私有驱动和firmware
emerge --ask net-wireless/broadcom-sta
  • 提示错误显示 net-wireless/broadcom-sta 已经被 masked :

安装 net-wireless/broadcom-sta 提示被 masked
!!! All ebuilds that could satisfy "net-wireless/broadcom-sta" have been masked.
!!! One of the following masked packages is required to complete your request:
- net-wireless/broadcom-sta-6.30.223.271-r7::gentoo (masked by: ~amd64 keyword)

这里软件被屏蔽的原因是 ~amd64 关键字,有两种方式解决,

方法一: 在 Gentoo make.conf 中配置接受测试版本:

/etc/portage/make.conf 配置接受测试阶段的AMD64架构软件包
ACCEPT_KEYWORDS="~amd64"

方法二(建议): 在 /etc/portage/package.accept_keywords 中添加你想安装的被mask的关键字:

创建 /etc/portage/package.accept_keywords 包含接受的软件包关键字
#直接使用 /etc/portage/package.accept_keywords
#echo "net-wireless/broadcom-sta" >> /etc/portage/package.accept_keywords

#或者 /etc/portage/package.accept_keywords 目录下分别配置针对不同应用的配置
#这里举例为fcitx5配置 /etc/portage/package.accept_keywords/fcitx5
app-i18n/fcitx ~amd64
x11-libs/xcb-imdkit ~amd64
app-i18n/fcitx-chinese-addons ~amd64
app-i18n/fcitx-rime ~amd64
app-i18n/rime-data ~amd64
app-i18n/libime ~amd64
app-i18n/fcitx-qt ~amd64
app-i18n/fcitx-gtk ~amd64
app-i18n/fcitx-configtool ~amd64
dev-qt/qtcore ~amd64
# dev-libs/boost-1.84.0 required by fcitx-chinese-addons (~amd64)
dev-libs/boost ~amd64

当初次完成 在MacBook Pro上安装Gentoo Linux 采用通用发行版内核时,会提示如下信息:

在通用内核的Gentoo上安装 net-wireless/broadcom-sta 提示信息
 * Messages for package net-wireless/broadcom-sta-6.30.223.271-r7:

 *   B43: If you insist on building this, you must blacklist it!
 *   BCMA: If you insist on building this, you must blacklist it!
 *   SSB: If you insist on building this, you must blacklist it!
 *   X86_INTEL_LPSS: Please disable it. The module does not work with it enabled.
 *   MAC80211: If you insist on building this, you must blacklist it!
 *   LIB80211_CRYPT_TKIP: You will need this for WPA.
 *   PREEMPT_RCU: Please do not set the Preemption Model to "Preemptible Kernel"; choose something else.

按照提示,需要配置 blocklist 屏蔽冲突内核模块 也就是配置 /etc/modprobe.d/blacklist.conf 如下:

针对安装 net-wireless/broadcom-sta 需要屏蔽地内核模块配置文件 /etc/modprobe.d/blacklist.conf
blacklist b43
blacklist bcma
blacklist sbb
blacklist mac80211

警告

必须在操作系统启动时屏蔽掉上述冲突的内核模块,否则即使加载了 wl 模块,也看不到对应的网卡

  • 移除冲突内核模块,加载 wl 内核模块:

移除冲突内核模块后加载 wl 内核模块
depmod –a
rmmod b43
rmmod ssb
rmmod wl
modprobe wl
  • 需要重新编译内核(并且每次升级内核都需要重新安装一次 net-wireless/broadcom-sta 并重新编译内核):

重新编译内核, all 参数将包括firmware
genkernel all
  • 重启系统后,如果正确加载了 wl 内核模块,那么可以看到一块新出现的无线网卡 wlp3s0

PREEMPT_RCU 冲突

我在最新的 6.1.12 内核安装 broadcom-sta 遇到报错:

PREEMPT_RCU: Please do not set the Preemption Model to "Preemptible Kernel"; choose something else.

这个问题在 emerge broadcom-sta fails (6.1.12 kernel) due to PREEMPT_RCU 有解决建议:

  • PREEMPT_RCU 不能直接修改(确实,我在配置选项中没有找到)

  • General setup 中 当选择以下 preemption modelsPREEMPT_RCU 会自动选择:

    • Preemptible Kernel (Low-Latency Desktop) # 位于 General setup => Preemption Model

    • Fully Preemptible Kernel (Real-Time) (this might not be available on all CPU architectures)

  • General setup 中如果激活 PREEMPT_DYNAMIC 就会自动选择

果然,原来我选择激活了 Gneeral setup => Preemption behaviour defined on boot ,这个选项就是 PREEMPT_DYNAMIC=y ,就是这个选项导致。真是这个选项激活导致了 PREEMPT_RCU 出现,我取消这个配置就可以了

配置 使用wpa_supplicant连接无线网络

Ubuntu Linux 配置 使用wpa_supplicant连接无线网络 或者 arch linux使用wpa_supplicant连接无线网络 类似,采用 wpa_supplicant 可以轻松配置无线连接:

  • 检查无线网络:

使用 rfkill list 检查网卡设备是否被block
rfkill list

输出显示当前状态,可以看到无线网络没有屏蔽:

rfkill list 显示我的主机无线网卡没有被软件block
0: hci0: Bluetooth
        Soft blocked: no
        Hard blocked: no
1: phy0: Wireless LAN
        Soft blocked: no
        Hard blocked: no
2: brcmwl-0: Wireless LAN
        Soft blocked: no
        Hard blocked: no
  • 创建初始配置:

使用 wpa_passphrase 初始化一个简单配置
wpa_passphrase your-ESSID your-passphrase | sudo tee /etc/wpa_supplicant/wpa_supplicant.conf
sudo chmod 600 /etc/wpa_supplicant/wpa_supplicant.conf
  • 通过 OpenRC 启动 wpa_supplicant 服务:

设置 openrc 启动 wpa_supplicant 服务
rc-update add wpa_supplicant default
rc-service wpa_supplicant start

异常排查

警告

我折腾了很久 wlp3s0 无线网卡无数据流量的问题,最初以为是内核编译问题,但是实际上最终解决的方法是将 wpa_supplicant 回退到旧版本 2.8 解决。非常坑

  • wlp3s0 无线网卡没有任何数据包进出(观察 ifconfig 输出显示 RX/TX 包都是0)

通过前台执行命令 wpa_supplicant -c /etc/wpa_supplicant/wpa_supplicant.conf -i wlp3s0 可以看到输出了错误信息:

wpa_supplicant 显示无线网卡扫描错误
Successfully initialized wpa_supplicant
wlp3s0: CTRL-EVENT-SCAN-FAILED ret=-22 retry=1
wlp3s0: CTRL-EVENT-SCAN-FAILED ret=-22 retry=1
...

参考 gentoo linux wiki: WiFi 提到,当操作系统启动时, dmesgjournalctl 中应该有对应的firmware probe,则我现在检查 dmesg -T | grep -i firmware 输出:

dmesg -T 输出过滤找不到无线网卡的firmware信息
[Sat Dec 30 20:14:24 2023] Spectre V2 : Enabling Restricted Speculation for firmware calls
[Sat Dec 30 20:14:24 2023] ACPI: [Firmware Bug]: BIOS _OSI(Linux) query ignored
[Sat Dec 30 20:14:24 2023] acpi PNP0A08:00: [Firmware Info]: MMCONFIG for domain 0000 [bus 00-9b] only partially covers this bridge
[Sat Dec 30 20:14:30 2023] Loading firmware: regulatory.db
[Sat Dec 30 20:14:30 2023] Loading firmware: regulatory.db.p7s

IPW2100

参考 Apple Macbook Pro Retina (early 2013)#Wireless 其中提到闭源Broadcom驱动需要内核中输出 LIB80211 ,这个配置是通过将 Intel PRO/Wireless 2100 Network Connection 直接编译进内核(不是模块)来实现的。不过,需要注意这个 Intel Pro/Wireless 2100 Network Connection 默认是编译为模块,因为它依赖的内核部分是模块形式导致,需要仔细调整,强制为直接编译进内核:

Intel PRO/Wireless 2100 Network Connection 需要编译进内核以激活 LIB80211
Device Drivers
   -> Network device support
      -> Wireless LAN
         -> <*>   Intel PRO/Wireless 2100 Network Connection

这里有一个模块依赖关系:

IPW2100 (m) => CFG80211 (m) => RFKILL (m)
设置 IPW2100 buildin 内核的配置方法
Networking support  --->
  Wireless  --->
    <*>   cfg80211 - wireless configuration API
    < >   Generic IEEE 802.11 Networking Stack (mac80211)
  RF switch subsystem support  --->
    <*>   GPIO RFKILL driver
Device Drivers  --->
  Network device support  --->
     Wireless LAN  --->
       [*]   Intel devices
       <*>   Intel PRO/Wireless 2100 Network Connection

最终解决方法是前文的 经验总结 : 对比 net-wireless/broadcom-sta 安装后的输出信息 和 /usr/src/linux/.config ,调整内核配置。 也就是 grep XXX /usr/src/linux/.config ,我发现我的错误在于依然包含了冲突配置:

CONFIG_SSB=m
CONFIG_X86_INTEL_LPSS=y   <= Intel Low Power Subsystem Support
CONFIG_PREEMPT_RCU=y

PREEMPT_RCU

备注

Broadcom Wireless Drivers 文档提到 ERROR: PREEMPT_RCU 可以忽略,原因不明

这个 PREEMPT_RCU 非常难找,在 make menuconfig 中,通过 /PREEMPT_RCU 找不到入口。参考 How to disable CONFIG_PREEMPT_RCU in 5.14 kernel ,这个配置在 3.14 内核没有激活,到 5.14 内核默认激活

根据 make menuconfig 搜索 /PREEMPT_RCU 可以看到提示这个选项在 kernel/rcu/Kconfig:19 提供: 所以查看源码中 /usr/src/linux/kernel/rcu/Kconfig

根据 Kconfig : PREEMPTION 选择 PREEMPT_RCU 就会触发 PREEMPT_RCU=y
# SPDX-License-Identifier: GPL-2.0-only
#
# RCU-related configuration options
#

menu "RCU Subsystem"

config TREE_RCU
	bool
	default y if SMP
	# Dynticks-idle tracking
	select CONTEXT_TRACKING_IDLE
	help
	  This option selects the RCU implementation that is
	  designed for very large SMP system with hundreds or
	  thousands of CPUs.  It also scales down nicely to
	  smaller systems.

config PREEMPT_RCU
	bool
	default y if PREEMPTION
	select TREE_RCU
	help
	  This option selects the RCU implementation that is
	  designed for very large SMP systems with hundreds or
	  thousands of CPUs, but for which real-time response
	  is also required.  It also scales down nicely to
	  smaller systems.

	  Select this option if you are unsure.

上述 Kconfig 可以看出选择的链路:

  • SMP 选择了 CONTEXT_TRACKING_IDLE 导致 TREE_RCUY

  • TREE_RCU 选择之后就会导致 PREEMPT_RCUY

但是,我还是没有找到可以调整的入口,看起来在最新的Kernel 这个配置是固化的?

警告

太折腾了,我最终还是没有解决在最新的 Kernel 6.1.67 上支持 BCM4360 网卡的私有驱动 broadcom-sta (wl)的安装,太累了,放弃... 突然找到了解决方案,最后再试一下

我理解关闭内核 RCU PREEMPT_RCU 对性能是有影响的,无法充分发挥最新内核的特性。加上实在太折腾了,我放弃继续安装 broadcom-sta ,准备更换无线网卡硬件,采用内核原生开源驱动。

或许早期内核版本能够使用这个网卡驱动?

备注

我学习和整理了内核的 RCU概览 知识点,算是为这次无线网卡折腾画个句号。

最终的解决方法

根据 Broadcom Wireless Drivers 文档经验,原来最新版本的 wpa_supplicant 是无法配合 broadcom-sta 驱动工作的,需要回退到 2019 年的 wpa_supplicant-2.8 版本

由于兼容性问题,需要回滚 wpa_supplicant 2.8 版本才能和 broadcom-sta 一起工作
mkdir ~/compile
cd compile
wget https://w1.fi/releases/wpa_supplicant-2.8.tar.gz
tar -xvf wpa_supplicant-2.8.tar.gz
cd wpa_supplicant-2.8

需要修订 wpa_supplicant 编译配置,所以修改源代码 ./wpa_supplicant/.config 如下:

修改 ./wpa_supplicant/.config 配置
CONFIG_BACKEND=file
CONFIG_CTRL_IFACE=y
CONFIG_DEBUG_FILE=y
CONFIG_DEBUG_SYSLOG=y
CONFIG_DEBUG_SYSLOG_FACILITY=LOG_DAEMON
CONFIG_DRIVER_NL80211=y
CONFIG_DRIVER_WEXT=y
CONFIG_DRIVER_WIRED=y
CONFIG_EAP_GTC=y
CONFIG_EAP_LEAP=y
CONFIG_EAP_MD5=y
CONFIG_EAP_MSCHAPV2=y
CONFIG_EAP_OTP=y
CONFIG_EAP_PEAP=y
CONFIG_EAP_TLS=y
CONFIG_EAP_TTLS=y
CONFIG_IEEE8021X_EAPOL=y
CONFIG_IPV6=y
CONFIG_LIBNL32=y
CONFIG_PEERKEY=y
CONFIG_PKCS12=y
CONFIG_READLINE=y
CONFIG_SMARTCARD=y
CONFIG_WPS=y
CFLAGS += -I/usr/include/libnl3
  • 删除掉系统已经安装的 wpa_supplicant 并清理:

删除并清理系统已经安装的 wpa_supplicant
sudo emerge --deselect net-wireless/wpa_supplicant
sudo emerge --depclean
  • 最后完成编译安装:

编译安装旧版本 wpa_supplicant
cd wpa_supplicant
make
sudo make install

果然, 使用旧版wpa_supplicant 就能够正常发起通讯,此时无线网卡已经显示有数据流量。

接下来 wpa_supplicant 和上文相同,不再重复

其他问题

旧版 wpa_supplicant 在连接 802.1x和EAP 报错:

旧版 wpa_supplicant 连接 802.1x和EAP 无线网络报错,显示不支持TLS
...
wlp3s0: CTRL-EVENT-EAP-PEER-ALT depth=0 EMAIL: XXXX
OpenSSL: EVP_DigestInit_ex failed: error:0308010C:digital envelope routines::unsupported
...

这个报错 error:0308010C:digital envelope routines::unsupportedNode.js Atlas version 17 中常见,原因是不支持 TLS 导致。我感觉我回退到旧版本的 wpa_supplicant 应该也是存在这个异常问题的,不过我没有再折腾解决这个问题。(参考 Error: error:0308010c:digital envelope routines::unsupported [Node Error Solved] )

参考