Skip to content

Commit

Permalink
wifi: mac80211: fix receiving A-MSDU frames on mesh interfaces
Browse files Browse the repository at this point in the history
The current mac80211 mesh A-MSDU receive path fails to parse A-MSDU packets
on mesh interfaces, because it assumes that the Mesh Control field is always
directly after the 802.11 header.
802.11-2020 9.3.2.2.2 Figure 9-70 shows that the Mesh Control field is
actually part of the A-MSDU subframe header.
This makes more sense, since it allows packets for multiple different
destinations to be included in the same A-MSDU, as long as RA and TID are
still the same.
Another issue is the fact that the A-MSDU subframe length field was apparently
accidentally defined as little-endian in the standard.

In order to fix this, the mesh forwarding path needs happen at a different
point in the receive path.

ieee80211_data_to_8023_exthdr is changed to ignore the mesh control field
and leave it in after the ethernet header. This also affects the source/dest
MAC address fields, which now in the case of mesh point to the mesh SA/DA.

ieee80211_amsdu_to_8023s is changed to deal with the endian difference and
to add the Mesh Control length to the subframe length, since it's not covered
by the MSDU length field.

With these changes, the mac80211 will get the same packet structure for
converted regular data packets and unpacked A-MSDU subframes.

The mesh forwarding checks are now only performed after the A-MSDU decap.
For locally received packets, the Mesh Control header is stripped away.
For forwarded packets, a new 802.11 header gets added.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
Link: https://lore.kernel.org/r/20230213100855.34315-4-nbd@nbd.name
[fix fortify build error]
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
  • Loading branch information
Felix Fietkau authored and Johannes Berg committed Feb 14, 2023
1 parent 5c1e269 commit 986e43b
Show file tree
Hide file tree
Showing 4 changed files with 297 additions and 202 deletions.
2 changes: 1 addition & 1 deletion drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ static int mwifiex_11n_dispatch_amsdu_pkt(struct mwifiex_private *priv,
skb_trim(skb, le16_to_cpu(local_rx_pd->rx_pkt_length));

ieee80211_amsdu_to_8023s(skb, &list, priv->curr_addr,
priv->wdev.iftype, 0, NULL, NULL);
priv->wdev.iftype, 0, NULL, NULL, false);

while (!skb_queue_empty(&list)) {
struct rx_packet_hdr *rx_hdr;
Expand Down
27 changes: 26 additions & 1 deletion include/net/cfg80211.h
Original file line number Diff line number Diff line change
Expand Up @@ -6251,11 +6251,36 @@ static inline int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
* @extra_headroom: The hardware extra headroom for SKBs in the @list.
* @check_da: DA to check in the inner ethernet header, or NULL
* @check_sa: SA to check in the inner ethernet header, or NULL
* @mesh_control: A-MSDU subframe header includes the mesh control field
*/
void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list,
const u8 *addr, enum nl80211_iftype iftype,
const unsigned int extra_headroom,
const u8 *check_da, const u8 *check_sa);
const u8 *check_da, const u8 *check_sa,
bool mesh_control);

/**
* ieee80211_get_8023_tunnel_proto - get RFC1042 or bridge tunnel encap protocol
*
* Check for RFC1042 or bridge tunnel header and fetch the encapsulated
* protocol.
*
* @hdr: pointer to the MSDU payload
* @proto: destination pointer to store the protocol
* Return: true if encapsulation was found
*/
bool ieee80211_get_8023_tunnel_proto(const void *hdr, __be16 *proto);

/**
* ieee80211_strip_8023_mesh_hdr - strip mesh header from converted 802.3 frames
*
* Strip the mesh header, which was left in by ieee80211_data_to_8023 as part
* of the MSDU data. Also move any source/destination addresses from the mesh
* header to the ethernet header (if present).
*
* @skb: The 802.3 frame with embedded mesh header
*/
int ieee80211_strip_8023_mesh_hdr(struct sk_buff *skb);

/**
* cfg80211_classify8021d - determine the 802.1p/1d tag for a data frame
Expand Down
Loading

0 comments on commit 986e43b

Please sign in to comment.