wifi: nl80211/mac80211: clarify link ID in control port TX
Clarify the link ID behaviour in control port TX, we need it
to select the link to transmit on for both MLD and non-MLD
receivers, but select the link address as the SA only if the
receiver is not an MLD.
Fixes: 67207bab93
("wifi: cfg80211/mac80211: Support control port TX from specific link")
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
parent
dd820ed633
commit
9dd1953846
|
@ -1119,6 +1119,12 @@
|
|||
* has been received. %NL80211_ATTR_FRAME is used to specify the
|
||||
* frame contents. The frame is the raw EAPoL data, without ethernet or
|
||||
* 802.11 headers.
|
||||
* For an MLD transmitter, the %NL80211_ATTR_MLO_LINK_ID may be given and
|
||||
* its effect will depend on the destination: If the destination is known
|
||||
* to be an MLD, this will be used as a hint to select the link to transmit
|
||||
* the frame on. If the destination is not an MLD, this will select both
|
||||
* the link to transmit on and the source address will be set to the link
|
||||
* address of that link.
|
||||
* When used as an event indication %NL80211_ATTR_CONTROL_PORT_ETHERTYPE,
|
||||
* %NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT and %NL80211_ATTR_MAC are added
|
||||
* indicating the protocol type of the received frame; whether the frame
|
||||
|
|
|
@ -2896,9 +2896,35 @@ static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata,
|
|||
info->flags = info_flags;
|
||||
info->ack_frame_id = info_id;
|
||||
info->band = band;
|
||||
info->control.flags = ctrl_flags |
|
||||
u32_encode_bits(link_id,
|
||||
|
||||
if (likely(!cookie)) {
|
||||
ctrl_flags |= u32_encode_bits(link_id,
|
||||
IEEE80211_TX_CTRL_MLO_LINK);
|
||||
} else {
|
||||
unsigned int pre_conf_link_id;
|
||||
|
||||
/*
|
||||
* ctrl_flags already have been set by
|
||||
* ieee80211_tx_control_port(), here
|
||||
* we just sanity check that
|
||||
*/
|
||||
|
||||
pre_conf_link_id = u32_get_bits(ctrl_flags,
|
||||
IEEE80211_TX_CTRL_MLO_LINK);
|
||||
|
||||
if (pre_conf_link_id != link_id &&
|
||||
link_id != IEEE80211_LINK_UNSPECIFIED) {
|
||||
#ifdef CPTCFG_MAC80211_VERBOSE_DEBUG
|
||||
net_info_ratelimited("%s: dropped frame to %pM with bad link ID request (%d vs. %d)\n",
|
||||
sdata->name, hdr.addr1,
|
||||
pre_conf_link_id, link_id);
|
||||
#endif
|
||||
ret = -EINVAL;
|
||||
goto free;
|
||||
}
|
||||
}
|
||||
|
||||
info->control.flags = ctrl_flags;
|
||||
|
||||
return skb;
|
||||
free:
|
||||
|
@ -5745,11 +5771,17 @@ int ieee80211_tx_control_port(struct wiphy *wiphy, struct net_device *dev,
|
|||
ehdr = skb_push(skb, sizeof(struct ethhdr));
|
||||
memcpy(ehdr->h_dest, dest, ETH_ALEN);
|
||||
|
||||
/* we may override the SA for MLO STA later */
|
||||
if (link_id < 0) {
|
||||
ctrl_flags |= u32_encode_bits(IEEE80211_LINK_UNSPECIFIED,
|
||||
IEEE80211_TX_CTRL_MLO_LINK);
|
||||
memcpy(ehdr->h_source, sdata->vif.addr, ETH_ALEN);
|
||||
} else {
|
||||
struct ieee80211_bss_conf *link_conf;
|
||||
|
||||
ctrl_flags |= u32_encode_bits(link_id,
|
||||
IEEE80211_TX_CTRL_MLO_LINK);
|
||||
|
||||
rcu_read_lock();
|
||||
link_conf = rcu_dereference(sdata->vif.link_conf[link_id]);
|
||||
if (!link_conf) {
|
||||
|
@ -5784,6 +5816,13 @@ int ieee80211_tx_control_port(struct wiphy *wiphy, struct net_device *dev,
|
|||
|
||||
skb_set_queue_mapping(skb, queue);
|
||||
skb_get_hash(skb);
|
||||
|
||||
/*
|
||||
* for MLO STA, the SA should be the AP MLD address, but
|
||||
* the link ID has been selected already
|
||||
*/
|
||||
if (sta->sta.mlo)
|
||||
memcpy(ehdr->h_source, sdata->vif.addr, ETH_ALEN);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
|
|
Loading…
Reference in New Issue