Skip to content

Instantly share code, notes, and snippets.

@agoose77
Last active September 19, 2026 15:47
Show Gist options
  • Select an option

  • Save agoose77/4336ddeaafbca45f3e5d1fc9f5ebf63c to your computer and use it in GitHub Desktop.

Select an option

Save agoose77/4336ddeaafbca45f3e5d1fc9f5ebf63c to your computer and use it in GitHub Desktop.
Build an OpenWRT image with kernel-patches from a release
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 6dfc61a9a..76291c489 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -511,7 +511,15 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
key->conf.flags |= IEEE80211_KEY_FLAG_NO_AUTO_TX;
if (mac_addr) {
+ bool defer_hw_upload;
+
sta = sta_info_get_bss(sdata, mac_addr);
+ defer_hw_upload =
+ sta && pairwise &&
+ !test_sta_flag(sta, WLAN_STA_ASSOC) &&
+ (sdata->vif.type == NL80211_IFTYPE_AP ||
+ sdata->vif.type == NL80211_IFTYPE_AP_VLAN) &&
+ !ieee80211_hw_check(&local->hw, SW_CRYPTO_CONTROL);
/*
* The ASSOC test makes sure the driver is ready to
* receive the key. When wpa_supplicant has roamed
@@ -519,10 +527,15 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
* association has completed, this rejects that attempt
* so it will set the key again after association.
*
- * TODO: accept the key if we have a station entry and
- * add it to the device after the station.
+ * AP-side FT may also install a pairwise key before the
+ * station is associated. If automatic software fallback is
+ * allowed, keep it in mac80211 and upload it after the station
+ * reaches ASSOC. Drivers with SW_CRYPTO_CONTROL cannot use this
+ * path since only their set_key() return value can permit
+ * software crypto.
*/
- if (!sta || !test_sta_flag(sta, WLAN_STA_ASSOC)) {
+ if (!sta || (!test_sta_flag(sta, WLAN_STA_ASSOC) &&
+ !defer_hw_upload)) {
ieee80211_key_free_unused(key);
return -ENOENT;
}
diff --git a/net/mac80211/key.c b/net/mac80211/key.c
index 67ecfea22..cf0002846 100644
--- a/net/mac80211/key.c
+++ b/net/mac80211/key.c
@@ -143,7 +143,13 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE;
return -EINVAL;
}
-
+ if (key->flags & KEY_FLAG_DEFERRED_HW_UPLOAD) {
+ /*
+ * Deferred keys allow automatic software fallback. Keep ret at
+ * -EOPNOTSUPP until the station is ready for hardware upload.
+ */
+ goto out_unsupported;
+ }
if (!key->local->ops->set_key)
goto out_unsupported;
@@ -987,6 +993,41 @@ void ieee80211_reenable_keys(struct ieee80211_sub_if_data *sdata)
}
}
+void ieee80211_upload_deferred_sta_keys(struct sta_info *sta)
+{
+ struct ieee80211_local *local = sta->local;
+ struct ieee80211_key *key;
+ u16 flags;
+ int i, ret;
+
+ lockdep_assert_wiphy(local->hw.wiphy);
+
+ for (i = 0; i < ARRAY_SIZE(sta->ptk); i++) {
+ key = wiphy_dereference(local->hw.wiphy, sta->ptk[i]);
+ if (!key || !(key->flags & KEY_FLAG_DEFERRED_HW_UPLOAD))
+ continue;
+
+ /*
+ * Capabilities may have changed since key installation.
+ * Avoid exposing temporarily cleared flags to RX/TX.
+ */
+ flags = key->conf.flags & ~(IEEE80211_KEY_FLAG_RX_MGMT |
+ IEEE80211_KEY_FLAG_SPP_AMSDU);
+ if (test_sta_flag(sta, WLAN_STA_MFP))
+ flags |= IEEE80211_KEY_FLAG_RX_MGMT;
+ if (sta->sta.spp_amsdu)
+ flags |= IEEE80211_KEY_FLAG_SPP_AMSDU;
+ WRITE_ONCE(key->conf.flags, flags);
+
+ key->flags &= ~KEY_FLAG_DEFERRED_HW_UPLOAD;
+ ret = ieee80211_key_enable_hw_accel(key);
+ if (ret)
+ sdata_err(key->sdata,
+ "failed to enable deferred key (%d, %pM): %d\n",
+ key->conf.keyidx, sta->sta.addr, ret);
+ }
+}
+
static void
ieee80211_key_iter(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
diff --git a/net/mac80211/key.h b/net/mac80211/key.h
index 1fa0f4f78..691268ce2 100644
--- a/net/mac80211/key.h
+++ b/net/mac80211/key.h
@@ -35,6 +35,7 @@ struct sta_info;
enum ieee80211_internal_key_flags {
KEY_FLAG_UPLOADED_TO_HARDWARE = BIT(0),
KEY_FLAG_TAINTED = BIT(1),
+ KEY_FLAG_DEFERRED_HW_UPLOAD = BIT(2),
};
enum ieee80211_internal_tkip_state {
@@ -165,6 +166,7 @@ void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata,
void ieee80211_free_sta_keys(struct ieee80211_local *local,
struct sta_info *sta);
void ieee80211_reenable_keys(struct ieee80211_sub_if_data *sdata);
+void ieee80211_upload_deferred_sta_keys(struct sta_info *sta);
int ieee80211_key_switch_links(struct ieee80211_sub_if_data *sdata,
unsigned long del_links_mask,
unsigned long add_links_mask);
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index aa22f09e6..e82215ae3 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -1348,6 +1348,7 @@ static int _sta_info_move_state(struct sta_info *sta,
case IEEE80211_STA_ASSOC:
if (sta->sta_state == IEEE80211_STA_AUTH) {
set_bit(WLAN_STA_ASSOC, &sta->_flags);
+ ieee80211_upload_deferred_sta_keys(sta);
sta->assoc_at = ktime_get_boottime_ns();
if (recalc) {
ieee80211_recalc_min_chandef(sta->sdata, -1);
FROM debian:bookworm
# Add old Debian repository for python2.7 package.
# Needed for OpenWrt 19.07.10
RUN echo "deb http://archive.debian.org/debian/ stretch contrib main non-free" >> /etc/apt/sources.list
RUN apt-get update && \
apt-get install -y \
sudo time git-core subversion build-essential g++ bash make \
libssl-dev patch libncurses5 libncurses5-dev zlib1g-dev gawk \
flex gettext wget unzip xz-utils python3 python3-distutils-extra \
python3-distutils-extra python3-setuptools swig rsync curl \
libsnmp-dev liblzma-dev libpam0g-dev cpio rsync gcc-multilib qemu-utils \
python2.7 quilt && \
apt-get clean && \
useradd -m user && \
echo 'user ALL=NOPASSWD: ALL' > /etc/sudoers.d/user
# set system wide dummy git config
RUN git config --system user.name "user" && git config --system user.email "user@example.com"
USER user
COPY openwrt.sh /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
WORKDIR /home/user
#/usr/bin/env bash
set -eu
release="${1:?Need kernel release version}"
test -d src || git clone https://github.com/openwrt/openwrt src
cd src
cp /mac80211-patches/* package/kernel/mac80211/patches/subsys/998-fix-wifi-roaming.patch
curl https://downloads.openwrt.org/releases/${release}/targets/mediatek/filogic/feeds.buildinfo -o feeds.conf
./scripts/feeds update
./scripts/feeds install -a
version=$(curl -s https://downloads.openwrt.org/releases/${release}/targets/mediatek/filogic/version.buildinfo | grep -E '[^-]+$' -o)
git checkout "${version}"
curl https://downloads.openwrt.org/releases/${release}/targets/mediatek/filogic/config.buildinfo -o .config
echo '
CONFIG_COLLECT_KERNEL_DEBUG=n
CONFIG_IB=n
CONFIG_SDK=n
CONFIG_MAKE_TOOLCHAIN=n
CONFIG_TARGET_mediatek_filogic_DEVICE_glinet_gl-mt6000=y
CONFIG_TARGET_PROFILE="DEVICE_glinet_gl-mt6000"
CONFIG_PACKAGE_u-boot-mt7986_glinet_gl-mt6000=y
'>>.config
make -j$(nproc) defconfig
make -j$(nproc) download
#ionice -c 3 chrt --idle 0 nice -n19 make -j$(nproc)
make -j$(nproc)
@agoose77

Copy link
Copy Markdown
Author

This should be generalised to do things like specify device config more generically. I am just sharing what I'm using locally on my Flint 2.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment