drivers/net/wireless/intel/iwlwifi/mld/rx.c

Source file repositories/reference/linux-study-clean/drivers/net/wireless/intel/iwlwifi/mld/rx.c

File Facts

System
Linux kernel
Corpus path
drivers/net/wireless/intel/iwlwifi/mld/rx.c
Extension
.c
Size
77314 bytes
Lines
2422
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct iwl_mld_rx_phy_data {
	struct iwl_rx_phy_air_sniffer_ntfy *ntfy;
	bool first_subframe;
	bool with_data;
	u32 rate_n_flags;
	u32 gp2_on_air_rise;
	/* phy_info is only valid when we have a frame, i.e. with_data=true */
	u16 phy_info;
	u8 energy_a, energy_b;
};

static void
iwl_mld_fill_phy_data_from_mpdu(struct iwl_mld *mld,
				struct iwl_rx_mpdu_desc *desc,
				struct iwl_mld_rx_phy_data *phy_data)
{
	if (unlikely(mld->monitor.phy.valid)) {
		mld->monitor.phy.used = true;
		phy_data->ntfy = &mld->monitor.phy.data;
	}

	phy_data->phy_info = le16_to_cpu(desc->phy_info);
	phy_data->rate_n_flags = le32_to_cpu(desc->v3.rate_n_flags);
	phy_data->gp2_on_air_rise = le32_to_cpu(desc->v3.gp2_on_air_rise);
	phy_data->energy_a = desc->v3.energy_a;
	phy_data->energy_b = desc->v3.energy_b;
	phy_data->with_data = true;
}

static inline int iwl_mld_check_pn(struct iwl_mld *mld, struct sk_buff *skb,
				   int queue, struct ieee80211_sta *sta)
{
	struct ieee80211_hdr *hdr = (void *)skb_mac_header(skb);
	struct ieee80211_rx_status *stats = IEEE80211_SKB_RXCB(skb);
	struct iwl_mld_sta *mld_sta;
	struct iwl_mld_ptk_pn *ptk_pn;
	int res;
	u8 tid, keyidx;
	u8 pn[IEEE80211_CCMP_PN_LEN];
	u8 *extiv;

	/* multicast and non-data only arrives on default queue; avoid checking
	 * for default queue - we don't want to replicate all the logic that's
	 * necessary for checking the PN on fragmented frames, leave that
	 * to mac80211
	 */
	if (queue == 0 || !ieee80211_is_data(hdr->frame_control) ||
	    is_multicast_ether_addr(hdr->addr1))
		return 0;

	if (!(stats->flag & RX_FLAG_DECRYPTED))
		return 0;

	/* if we are here - this for sure is either CCMP or GCMP */
	if (!sta) {
		IWL_DEBUG_DROP(mld,
			       "expected hw-decrypted unicast frame for station\n");
		return -1;
	}

	mld_sta = iwl_mld_sta_from_mac80211(sta);

	extiv = (u8 *)hdr + ieee80211_hdrlen(hdr->frame_control);
	keyidx = extiv[3] >> 6;

	ptk_pn = rcu_dereference(mld_sta->ptk_pn[keyidx]);
	if (!ptk_pn)
		return -1;

	if (ieee80211_is_data_qos(hdr->frame_control))
		tid = ieee80211_get_tid(hdr);
	else
		tid = 0;

	/* we don't use HCCA/802.11 QoS TSPECs, so drop such frames */
	if (tid >= IWL_MAX_TID_COUNT)
		return -1;

	/* load pn */
	pn[0] = extiv[7];
	pn[1] = extiv[6];
	pn[2] = extiv[5];
	pn[3] = extiv[4];
	pn[4] = extiv[1];
	pn[5] = extiv[0];

	res = memcmp(pn, ptk_pn->q[queue].pn[tid], IEEE80211_CCMP_PN_LEN);
	if (res < 0)
		return -1;
	if (!res && !(stats->flag & RX_FLAG_ALLOW_SAME_PN))

Annotation

Implementation Notes