]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
wifi: mac80211: Add counter for all monitor interfaces
authorAlexander Wetzel <Alexander@wetzel-home.de>
Thu, 20 Feb 2025 09:41:39 +0000 (10:41 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 29 May 2025 09:13:49 +0000 (11:13 +0200)
[ Upstream commit 129860044c611008be37f49d04cf41874e3659e6 ]

Count open monitor interfaces regardless of the monitor interface type.
The new counter virt_monitors takes over counting interfaces depending
on the virtual monitor interface while monitors is used for all active
monitor interfaces.

This fixes monitor packet mirroring when using MONITOR_FLAG_ACTIVE or
NO_VIRTUAL_MONITOR interfaces.

Fixes: 286e69677065 ("wifi: mac80211: Drop cooked monitor support")
Reported-by: Karthikeyan Periyasamy <quic_periyasa@quicinc.com>
Closes: https://lore.kernel.org/r/cc715114-4e3b-619a-49dc-a4878075e1dc@quicinc.com
Signed-off-by: Alexander Wetzel <Alexander@wetzel-home.de>
Tested-by: Karthikeyan Periyasamy <quic_periyasa@quicinc.com>
Link: https://patch.msgid.link/20250220094139.61459-1-Alexander@wetzel-home.de
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
net/mac80211/cfg.c
net/mac80211/ethtool.c
net/mac80211/ieee80211_i.h
net/mac80211/iface.c
net/mac80211/util.c

index 1ec246133d2441c2de84c7b132f5951765d6f1db..a7aeb37254bbfbef21fa3bed22f0c15cb24e9009 100644 (file)
@@ -4370,9 +4370,8 @@ static int ieee80211_cfg_get_channel(struct wiphy *wiphy,
        if (chanctx_conf) {
                *chandef = link->conf->chanreq.oper;
                ret = 0;
-       } else if (!ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR) &&
-                  local->open_count > 0 &&
-                  local->open_count == local->monitors &&
+       } else if (local->open_count > 0 &&
+                  local->open_count == local->virt_monitors &&
                   sdata->vif.type == NL80211_IFTYPE_MONITOR) {
                *chandef = local->monitor_chanreq.oper;
                ret = 0;
index 42f7ee142ce3f4dd5a4d50dcf59acb783fd7aaa7..0397755a3bd1c70e3af96a28dae8c4d31b85d142 100644 (file)
@@ -158,7 +158,7 @@ do_survey:
        if (chanctx_conf)
                channel = chanctx_conf->def.chan;
        else if (local->open_count > 0 &&
-                local->open_count == local->monitors &&
+                local->open_count == local->virt_monitors &&
                 sdata->vif.type == NL80211_IFTYPE_MONITOR)
                channel = local->monitor_chanreq.oper.chan;
        else
index afc6fda6b606bc702eb0a74c78b09793dcd1053c..3d7304ce23e23d2a4366d2a053281800c36a561d 100644 (file)
@@ -1378,7 +1378,7 @@ struct ieee80211_local {
        spinlock_t queue_stop_reason_lock;
 
        int open_count;
-       int monitors, tx_mntrs;
+       int monitors, virt_monitors, tx_mntrs;
        /* number of interfaces with corresponding FIF_ flags */
        int fif_fcsfail, fif_plcpfail, fif_control, fif_other_bss, fif_pspoll,
            fif_probe_req;
index 5616c0adbe093b7fcc1bb01501ceecab84c1fe4a..768d774d7d1f9b52f2e2712c41c00d764fcab960 100644 (file)
@@ -582,11 +582,13 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, bool going_do
                /* no need to tell driver */
                break;
        case NL80211_IFTYPE_MONITOR:
+               local->monitors--;
+
                if (!(sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE) &&
                    !ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR)) {
 
-                       local->monitors--;
-                       if (local->monitors == 0) {
+                       local->virt_monitors--;
+                       if (local->virt_monitors == 0) {
                                local->hw.conf.flags &= ~IEEE80211_CONF_MONITOR;
                                hw_reconf_flags |= IEEE80211_CONF_CHANGE_MONITOR;
                        }
@@ -686,7 +688,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, bool going_do
        case NL80211_IFTYPE_AP_VLAN:
                break;
        case NL80211_IFTYPE_MONITOR:
-               if (local->monitors == 0)
+               if (local->virt_monitors == 0)
                        ieee80211_del_virtual_monitor(local);
 
                ieee80211_recalc_idle(local);
@@ -723,7 +725,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, bool going_do
        ieee80211_configure_filter(local);
        ieee80211_hw_config(local, hw_reconf_flags);
 
-       if (local->monitors == local->open_count)
+       if (local->virt_monitors == local->open_count)
                ieee80211_add_virtual_monitor(local);
 }
 
@@ -982,7 +984,7 @@ static bool ieee80211_set_sdata_offload_flags(struct ieee80211_sub_if_data *sdat
                    local->hw.wiphy->frag_threshold != (u32)-1)
                        flags &= ~IEEE80211_OFFLOAD_ENCAP_ENABLED;
 
-               if (local->monitors)
+               if (local->virt_monitors)
                        flags &= ~IEEE80211_OFFLOAD_ENCAP_ENABLED;
        } else {
                flags &= ~IEEE80211_OFFLOAD_ENCAP_ENABLED;
@@ -992,7 +994,7 @@ static bool ieee80211_set_sdata_offload_flags(struct ieee80211_sub_if_data *sdat
            ieee80211_iftype_supports_hdr_offload(sdata->vif.type)) {
                flags |= IEEE80211_OFFLOAD_DECAP_ENABLED;
 
-               if (local->monitors &&
+               if (local->virt_monitors &&
                    !ieee80211_hw_check(&local->hw, SUPPORTS_CONC_MON_RX_DECAP))
                        flags &= ~IEEE80211_OFFLOAD_DECAP_ENABLED;
        } else {
@@ -1336,20 +1338,22 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
                        if (res)
                                goto err_stop;
                } else {
-                       if (local->monitors == 0 && local->open_count == 0) {
+                       if (local->virt_monitors == 0 && local->open_count == 0) {
                                res = ieee80211_add_virtual_monitor(local);
                                if (res)
                                        goto err_stop;
                        }
-                       local->monitors++;
+                       local->virt_monitors++;
 
                        /* must be before the call to ieee80211_configure_filter */
-                       if (local->monitors == 1) {
+                       if (local->virt_monitors == 1) {
                                local->hw.conf.flags |= IEEE80211_CONF_MONITOR;
                                hw_reconf_flags |= IEEE80211_CONF_CHANGE_MONITOR;
                        }
                }
 
+               local->monitors++;
+
                ieee80211_adjust_monitor_flags(sdata, 1);
                ieee80211_configure_filter(local);
                ieee80211_recalc_offload(local);
index fdda14c08e2b116b45176d06eb4c538cb5c99f84..dec6e16b8c7d28c758af64f1d4c8fd3f551c0147 100644 (file)
@@ -2156,7 +2156,8 @@ int ieee80211_reconfig(struct ieee80211_local *local)
 
  wake_up:
 
-       if (local->monitors == local->open_count && local->monitors > 0)
+       if (local->virt_monitors > 0 &&
+           local->virt_monitors == local->open_count)
                ieee80211_add_virtual_monitor(local);
 
        /*