Commit 67625910 authored by Johannes Berg's avatar Johannes Berg

wifi: mac80211: implement MLO multicast deduplication

If the vif is an MLD then it may receive multicast from
different links, and should drop those frames according
to the SN. Implement that.

Link: https://msgid.link/20240129200456.693b77d14b44.I491846f2bea0058c14eab6422962c10bfae9b675@changeidSigned-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent b1344b13
...@@ -191,6 +191,11 @@ static inline bool ieee80211_sn_less(u16 sn1, u16 sn2) ...@@ -191,6 +191,11 @@ static inline bool ieee80211_sn_less(u16 sn1, u16 sn2)
return ((sn1 - sn2) & IEEE80211_SN_MASK) > (IEEE80211_SN_MODULO >> 1); return ((sn1 - sn2) & IEEE80211_SN_MASK) > (IEEE80211_SN_MODULO >> 1);
} }
static inline bool ieee80211_sn_less_eq(u16 sn1, u16 sn2)
{
return ((sn2 - sn1) & IEEE80211_SN_MASK) <= (IEEE80211_SN_MODULO >> 1);
}
static inline u16 ieee80211_sn_add(u16 sn1, u16 sn2) static inline u16 ieee80211_sn_add(u16 sn1, u16 sn2)
{ {
return (sn1 + sn2) & IEEE80211_SN_MASK; return (sn1 + sn2) & IEEE80211_SN_MASK;
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
* Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
* Copyright 2007-2010 Johannes Berg <johannes@sipsolutions.net> * Copyright 2007-2010 Johannes Berg <johannes@sipsolutions.net>
* Copyright 2013-2015 Intel Mobile Communications GmbH * Copyright 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2018-2022 Intel Corporation * Copyright (C) 2018-2024 Intel Corporation
*/ */
#ifndef IEEE80211_I_H #ifndef IEEE80211_I_H
...@@ -523,6 +523,8 @@ struct ieee80211_if_managed { ...@@ -523,6 +523,8 @@ struct ieee80211_if_managed {
unsigned int flags; unsigned int flags;
u16 mcast_seq_last;
bool status_acked; bool status_acked;
bool status_received; bool status_received;
__le16 status_fc; __le16 status_fc;
......
...@@ -3351,6 +3351,8 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, ...@@ -3351,6 +3351,8 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
wiphy_delayed_work_cancel(sdata->local->hw.wiphy, wiphy_delayed_work_cancel(sdata->local->hw.wiphy,
&ifmgd->neg_ttlm_timeout_work); &ifmgd->neg_ttlm_timeout_work);
ieee80211_vif_set_links(sdata, 0, 0); ieee80211_vif_set_links(sdata, 0, 0);
ifmgd->mcast_seq_last = IEEE80211_SN_MODULO;
} }
static void ieee80211_reset_ap_probe(struct ieee80211_sub_if_data *sdata) static void ieee80211_reset_ap_probe(struct ieee80211_sub_if_data *sdata)
...@@ -7512,6 +7514,7 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata) ...@@ -7512,6 +7514,7 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata)
spin_lock_init(&ifmgd->teardown_lock); spin_lock_init(&ifmgd->teardown_lock);
ifmgd->teardown_skb = NULL; ifmgd->teardown_skb = NULL;
ifmgd->orig_teardown_skb = NULL; ifmgd->orig_teardown_skb = NULL;
ifmgd->mcast_seq_last = IEEE80211_SN_MODULO;
} }
static void ieee80211_recalc_smps_work(struct wiphy *wiphy, static void ieee80211_recalc_smps_work(struct wiphy *wiphy,
......
...@@ -1434,13 +1434,31 @@ ieee80211_rx_h_check_dup(struct ieee80211_rx_data *rx) ...@@ -1434,13 +1434,31 @@ ieee80211_rx_h_check_dup(struct ieee80211_rx_data *rx)
return RX_CONTINUE; return RX_CONTINUE;
if (ieee80211_is_ctl(hdr->frame_control) || if (ieee80211_is_ctl(hdr->frame_control) ||
ieee80211_is_any_nullfunc(hdr->frame_control) || ieee80211_is_any_nullfunc(hdr->frame_control))
is_multicast_ether_addr(hdr->addr1))
return RX_CONTINUE; return RX_CONTINUE;
if (!rx->sta) if (!rx->sta)
return RX_CONTINUE; return RX_CONTINUE;
if (unlikely(is_multicast_ether_addr(hdr->addr1))) {
struct ieee80211_sub_if_data *sdata = rx->sdata;
u16 sn = ieee80211_get_sn(hdr);
if (!ieee80211_is_data_present(hdr->frame_control))
return RX_CONTINUE;
if (!ieee80211_vif_is_mld(&sdata->vif) ||
sdata->vif.type != NL80211_IFTYPE_STATION)
return RX_CONTINUE;
if (sdata->u.mgd.mcast_seq_last != IEEE80211_SN_MODULO &&
ieee80211_sn_less_eq(sn, sdata->u.mgd.mcast_seq_last))
return RX_DROP_U_DUP;
sdata->u.mgd.mcast_seq_last = sn;
return RX_CONTINUE;
}
if (unlikely(ieee80211_has_retry(hdr->frame_control) && if (unlikely(ieee80211_has_retry(hdr->frame_control) &&
rx->sta->last_seq_ctrl[rx->seqno_idx] == hdr->seq_ctrl)) { rx->sta->last_seq_ctrl[rx->seqno_idx] == hdr->seq_ctrl)) {
I802_DEBUG_INC(rx->local->dot11FrameDuplicateCount); I802_DEBUG_INC(rx->local->dot11FrameDuplicateCount);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment