wifi: mac80211: use link ID for MLO in queued frames
authorJohannes Berg <johannes.berg@intel.com>
Wed, 17 Aug 2022 19:57:19 +0000 (21:57 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Thu, 25 Aug 2022 08:41:18 +0000 (10:41 +0200)
When queuing frames to an interface store the link ID we
determined (which possibly came from the driver in the
RX status in the first place) in the RX status, and use
it in the MLME code to send probe responses, beacons and
CSA frames to the right link.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
net/mac80211/mlme.c
net/mac80211/rx.c

index 04d35cd398898fe96681152678cb7a8c4387b365..385d51e9990c161f909420a77ae4db1f97a36057 100644 (file)
@@ -5671,6 +5671,13 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
 
        sdata_lock(sdata);
 
+       if (rx_status->link_valid) {
+               link = sdata_dereference(sdata->link[rx_status->link_id],
+                                        sdata);
+               if (!link)
+                       goto out;
+       }
+
        switch (fc & IEEE80211_FCTL_STYPE) {
        case IEEE80211_STYPE_BEACON:
                ieee80211_rx_mgmt_beacon(link, (void *)mgmt,
@@ -5747,6 +5754,7 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
                }
                break;
        }
+out:
        sdata_unlock(sdata);
 }
 
index d4df2dc5844fa72974f8e76a963aac3baaebb398..cc139fe5fb7864bfe90b1b69c749dee68cdfac25 100644 (file)
@@ -215,9 +215,19 @@ ieee80211_rx_radiotap_hdrlen(struct ieee80211_local *local,
 }
 
 static void __ieee80211_queue_skb_to_iface(struct ieee80211_sub_if_data *sdata,
+                                          int link_id,
                                           struct sta_info *sta,
                                           struct sk_buff *skb)
 {
+       struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
+
+       if (link_id >= 0) {
+               status->link_valid = 1;
+               status->link_id = link_id;
+       } else {
+               status->link_valid = 0;
+       }
+
        skb_queue_tail(&sdata->skb_queue, skb);
        ieee80211_queue_work(&sdata->local->hw, &sdata->work);
        if (sta)
@@ -225,11 +235,12 @@ static void __ieee80211_queue_skb_to_iface(struct ieee80211_sub_if_data *sdata,
 }
 
 static void ieee80211_queue_skb_to_iface(struct ieee80211_sub_if_data *sdata,
+                                        int link_id,
                                         struct sta_info *sta,
                                         struct sk_buff *skb)
 {
        skb->protocol = 0;
-       __ieee80211_queue_skb_to_iface(sdata, sta, skb);
+       __ieee80211_queue_skb_to_iface(sdata, link_id, sta, skb);
 }
 
 static void ieee80211_handle_mu_mimo_mon(struct ieee80211_sub_if_data *sdata,
@@ -272,7 +283,7 @@ static void ieee80211_handle_mu_mimo_mon(struct ieee80211_sub_if_data *sdata,
        if (!skb)
                return;
 
-       ieee80211_queue_skb_to_iface(sdata, NULL, skb);
+       ieee80211_queue_skb_to_iface(sdata, -1, NULL, skb);
 }
 
 /*
@@ -1394,7 +1405,7 @@ static void ieee80211_rx_reorder_ampdu(struct ieee80211_rx_data *rx,
        /* if this mpdu is fragmented - terminate rx aggregation session */
        sc = le16_to_cpu(hdr->seq_ctrl);
        if (sc & IEEE80211_SCTL_FRAG) {
-               ieee80211_queue_skb_to_iface(rx->sdata, NULL, skb);
+               ieee80211_queue_skb_to_iface(rx->sdata, rx->link_id, NULL, skb);
                return;
        }
 
@@ -3044,7 +3055,8 @@ ieee80211_rx_h_data(struct ieee80211_rx_data *rx)
                    (tf->action_code == WLAN_TDLS_CHANNEL_SWITCH_REQUEST ||
                     tf->action_code == WLAN_TDLS_CHANNEL_SWITCH_RESPONSE)) {
                        rx->skb->protocol = cpu_to_be16(ETH_P_TDLS);
-                       __ieee80211_queue_skb_to_iface(sdata, rx->sta, rx->skb);
+                       __ieee80211_queue_skb_to_iface(sdata, rx->link_id,
+                                                      rx->sta, rx->skb);
                        return RX_QUEUED;
                }
        }
@@ -3634,7 +3646,7 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
        return RX_QUEUED;
 
  queue:
-       ieee80211_queue_skb_to_iface(sdata, rx->sta, rx->skb);
+       ieee80211_queue_skb_to_iface(sdata, rx->link_id, rx->sta, rx->skb);
        return RX_QUEUED;
 }
 
@@ -3792,7 +3804,7 @@ ieee80211_rx_h_ext(struct ieee80211_rx_data *rx)
                return RX_DROP_MONITOR;
 
        /* for now only beacons are ext, so queue them */
-       ieee80211_queue_skb_to_iface(sdata, rx->sta, rx->skb);
+       ieee80211_queue_skb_to_iface(sdata, rx->link_id, rx->sta, rx->skb);
 
        return RX_QUEUED;
 }
@@ -3849,7 +3861,7 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx)
                return RX_DROP_MONITOR;
        }
 
-       ieee80211_queue_skb_to_iface(sdata, rx->sta, rx->skb);
+       ieee80211_queue_skb_to_iface(sdata, rx->link_id, rx->sta, rx->skb);
 
        return RX_QUEUED;
 }