Skip to content

Commit

Permalink
mac80211: add rx decapsulation offload support
Browse files Browse the repository at this point in the history
This allows drivers to pass 802.3 frames to mac80211, with some restrictions:

- the skb must be passed with a valid sta
- fast-rx needs to be active for the sta
- monitor mode needs to be disabled

mac80211 will tell the driver when it is safe to enable rx decap offload for
a particular station.

In order to implement support, a driver must:

- call ieee80211_hw_set(hw, SUPPORTS_RX_DECAP_OFFLOAD)
- implement ops->sta_set_decap_offload
- mark 802.3 frames with RX_FLAG_8023

If it doesn't want to enable offload for some vif types, it can mask out
IEEE80211_OFFLOAD_DECAP_ENABLED in vif->offload_flags from within the
.add_interface or .update_vif_offload driver ops

Signed-off-by: Felix Fietkau <nbd@nbd.name>
Link: https://lore.kernel.org/r/20201218184718.93650-6-nbd@nbd.name
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
  • Loading branch information
nbd168 authored and jmberg-intel committed Jan 21, 2021
1 parent d7b6492 commit 80a915e
Show file tree
Hide file tree
Showing 8 changed files with 225 additions and 89 deletions.
16 changes: 16 additions & 0 deletions include/net/mac80211.h
Original file line number Diff line number Diff line change
Expand Up @@ -1296,6 +1296,8 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info)
* the "0-length PSDU" field included there. The value for it is
* in &struct ieee80211_rx_status. Note that if this value isn't
* known the frame shouldn't be reported.
* @RX_FLAG_8023: the frame has an 802.3 header (decap offload performed by
* hardware or driver)
*/
enum mac80211_rx_flags {
RX_FLAG_MMIC_ERROR = BIT(0),
Expand Down Expand Up @@ -1328,6 +1330,7 @@ enum mac80211_rx_flags {
RX_FLAG_RADIOTAP_HE_MU = BIT(27),
RX_FLAG_RADIOTAP_LSIG = BIT(28),
RX_FLAG_NO_PSDU = BIT(29),
RX_FLAG_8023 = BIT(30),
};

/**
Expand Down Expand Up @@ -1649,11 +1652,15 @@ enum ieee80211_vif_flags {
* The driver supports sending frames passed as 802.3 frames by mac80211.
* It must also support sending 802.11 packets for the same interface.
* @IEEE80211_OFFLOAD_ENCAP_4ADDR: support 4-address mode encapsulation offload
* @IEEE80211_OFFLOAD_DECAP_ENABLED: rx encapsulation offload is enabled
* The driver supports passing received 802.11 frames as 802.3 frames to
* mac80211.
*/

enum ieee80211_offload_flags {
IEEE80211_OFFLOAD_ENCAP_ENABLED = BIT(0),
IEEE80211_OFFLOAD_ENCAP_4ADDR = BIT(1),
IEEE80211_OFFLOAD_DECAP_ENABLED = BIT(2),
};

/**
Expand Down Expand Up @@ -2389,6 +2396,9 @@ struct ieee80211_txq {
* @IEEE80211_HW_SUPPORTS_TX_ENCAP_OFFLOAD: Hardware supports tx encapsulation
* offload
*
* @IEEE80211_HW_SUPPORTS_RX_DECAP_OFFLOAD: Hardware supports rx decapsulation
* offload
*
* @NUM_IEEE80211_HW_FLAGS: number of hardware flags, used for sizing arrays
*/
enum ieee80211_hw_flags {
Expand Down Expand Up @@ -2442,6 +2452,7 @@ enum ieee80211_hw_flags {
IEEE80211_HW_SUPPORTS_ONLY_HE_MULTI_BSSID,
IEEE80211_HW_AMPDU_KEYBORDER_SUPPORT,
IEEE80211_HW_SUPPORTS_TX_ENCAP_OFFLOAD,
IEEE80211_HW_SUPPORTS_RX_DECAP_OFFLOAD,

/* keep last, obviously */
NUM_IEEE80211_HW_FLAGS
Expand Down Expand Up @@ -3881,6 +3892,8 @@ enum ieee80211_reconfig_type {
* @sta_set_4addr: Called to notify the driver when a station starts/stops using
* 4-address mode
* @set_sar_specs: Update the SAR (TX power) settings.
* @sta_set_decap_offload: Called to notify the driver when a station is allowed
* to use rx decapsulation offload
*/
struct ieee80211_ops {
void (*tx)(struct ieee80211_hw *hw,
Expand Down Expand Up @@ -4198,6 +4211,9 @@ struct ieee80211_ops {
struct ieee80211_sta *sta, bool enabled);
int (*set_sar_specs)(struct ieee80211_hw *hw,
const struct cfg80211_sar_specs *sar);
void (*sta_set_decap_offload)(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta, bool enabled);
};

/**
Expand Down
1 change: 1 addition & 0 deletions net/mac80211/debugfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,7 @@ static const char *hw_flag_names[] = {
FLAG(SUPPORTS_ONLY_HE_MULTI_BSSID),
FLAG(AMPDU_KEYBORDER_SUPPORT),
FLAG(SUPPORTS_TX_ENCAP_OFFLOAD),
FLAG(SUPPORTS_RX_DECAP_OFFLOAD),
#undef FLAG
};

Expand Down
1 change: 1 addition & 0 deletions net/mac80211/debugfs_sta.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ static const char * const sta_flag_names[] = {
FLAG(MPSP_RECIPIENT),
FLAG(PS_DELIVER),
FLAG(USES_ENCRYPTION),
FLAG(DECAP_OFFLOAD),
#undef FLAG
};

Expand Down
16 changes: 16 additions & 0 deletions net/mac80211/driver-ops.h
Original file line number Diff line number Diff line change
Expand Up @@ -1413,4 +1413,20 @@ static inline void drv_sta_set_4addr(struct ieee80211_local *local,
trace_drv_return_void(local);
}

static inline void drv_sta_set_decap_offload(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata,
struct ieee80211_sta *sta,
bool enabled)
{
sdata = get_bss_sdata(sdata);
if (!check_sdata_in_driver(sdata))
return;

trace_drv_sta_set_decap_offload(local, sdata, sta, enabled);
if (local->ops->sta_set_decap_offload)
local->ops->sta_set_decap_offload(&local->hw, &sdata->vif, sta,
enabled);
trace_drv_return_void(local);
}

#endif /* __MAC80211_DRIVER_OPS */
17 changes: 14 additions & 3 deletions net/mac80211/iface.c
Original file line number Diff line number Diff line change
Expand Up @@ -765,7 +765,7 @@ static const struct net_device_ops ieee80211_dataif_8023_ops = {
.ndo_get_stats64 = ieee80211_get_stats64,
};

static bool ieee80211_iftype_supports_encap_offload(enum nl80211_iftype iftype)
static bool ieee80211_iftype_supports_hdr_offload(enum nl80211_iftype iftype)
{
switch (iftype) {
/* P2P GO and client are mapped to AP/STATION types */
Expand All @@ -785,7 +785,7 @@ static bool ieee80211_set_sdata_offload_flags(struct ieee80211_sub_if_data *sdat
flags = sdata->vif.offload_flags;

if (ieee80211_hw_check(&local->hw, SUPPORTS_TX_ENCAP_OFFLOAD) &&
ieee80211_iftype_supports_encap_offload(sdata->vif.type)) {
ieee80211_iftype_supports_hdr_offload(sdata->vif.type)) {
flags |= IEEE80211_OFFLOAD_ENCAP_ENABLED;

if (!ieee80211_hw_check(&local->hw, SUPPORTS_TX_FRAG) &&
Expand All @@ -798,10 +798,21 @@ static bool ieee80211_set_sdata_offload_flags(struct ieee80211_sub_if_data *sdat
flags &= ~IEEE80211_OFFLOAD_ENCAP_ENABLED;
}

if (ieee80211_hw_check(&local->hw, SUPPORTS_RX_DECAP_OFFLOAD) &&
ieee80211_iftype_supports_hdr_offload(sdata->vif.type)) {
flags |= IEEE80211_OFFLOAD_DECAP_ENABLED;

if (local->monitors)
flags &= ~IEEE80211_OFFLOAD_DECAP_ENABLED;
} else {
flags &= ~IEEE80211_OFFLOAD_DECAP_ENABLED;
}

if (sdata->vif.offload_flags == flags)
return false;

sdata->vif.offload_flags = flags;
ieee80211_check_fast_rx_iface(sdata);
return true;
}

Expand All @@ -819,7 +830,7 @@ static void ieee80211_set_vif_encap_ops(struct ieee80211_sub_if_data *sdata)
}

if (!ieee80211_hw_check(&local->hw, SUPPORTS_TX_ENCAP_OFFLOAD) ||
!ieee80211_iftype_supports_encap_offload(bss->vif.type))
!ieee80211_iftype_supports_hdr_offload(bss->vif.type))
return;

enabled = bss->vif.offload_flags & IEEE80211_OFFLOAD_ENCAP_ENABLED;
Expand Down

0 comments on commit 80a915e

Please sign in to comment.