net/mac80211/agg-rx.c

Source file repositories/reference/linux-study-clean/net/mac80211/agg-rx.c

File Facts

System
Linux kernel
Corpus path
net/mac80211/agg-rx.c
Extension
.c
Size
16238 bytes
Lines
542
Domain
Networking Core
Bucket
Sockets, Protocols, Packet Path, And Network Policy
Inferred role
Networking Core: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Networking stack implementation surface: socket APIs, protocol dispatch, packet flow, routing, filtering, and network namespaces.

Dependency Surface

Detected Declarations

Annotated Snippet

if (sta->ampdu_mlme.tid_rx_token[tid] == dialog_token) {
			struct tid_ampdu_rx *tid_rx;

			ht_dbg_ratelimited(sta->sdata,
					   "updated AddBA Req from %pM on tid %u\n",
					   sta->sta.addr, tid);
			/* We have no API to update the timeout value in the
			 * driver so reject the timeout update if the timeout
			 * changed. If it did not change, i.e., no real update,
			 * just reply with success.
			 */
			rcu_read_lock();
			tid_rx = rcu_dereference(sta->ampdu_mlme.tid_rx[tid]);
			if (tid_rx && tid_rx->timeout == timeout)
				status = WLAN_STATUS_SUCCESS;
			else
				status = WLAN_STATUS_REQUEST_DECLINED;
			rcu_read_unlock();
			goto end;
		}

		ht_dbg_ratelimited(sta->sdata,
				   "unexpected AddBA Req from %pM on tid %u\n",
				   sta->sta.addr, tid);

		/* delete existing Rx BA session on the same tid */
		__ieee80211_stop_rx_ba_session(sta, tid, WLAN_BACK_RECIPIENT,
					       WLAN_STATUS_UNSPECIFIED_QOS,
					       false);
	}

	if (ieee80211_hw_check(&local->hw, SUPPORTS_REORDERING_BUFFER)) {
		ret = drv_ampdu_action(local, sta->sdata, &params);
		ht_dbg(sta->sdata,
		       "Rx A-MPDU request on %pM tid %d result %d\n",
		       sta->sta.addr, tid, ret);
		if (!ret)
			status = WLAN_STATUS_SUCCESS;
		goto end;
	}

	/* prepare A-MPDU MLME for Rx aggregation */
	tid_agg_rx = kzalloc_flex(*tid_agg_rx, reorder, buf_size);
	if (!tid_agg_rx)
		goto end;

	spin_lock_init(&tid_agg_rx->reorder_lock);

	/* rx timer */
	timer_setup(&tid_agg_rx->session_timer,
		    sta_rx_agg_session_timer_expired, TIMER_DEFERRABLE);

	/* rx reorder timer */
	timer_setup(&tid_agg_rx->reorder_timer,
		    sta_rx_agg_reorder_timer_expired, 0);

	for (i = 0; i < buf_size; i++)
		__skb_queue_head_init(&tid_agg_rx->reorder[i].buf);

	ret = drv_ampdu_action(local, sta->sdata, &params);
	ht_dbg(sta->sdata, "Rx A-MPDU request on %pM tid %d result %d\n",
	       sta->sta.addr, tid, ret);
	if (ret) {
		kfree(tid_agg_rx);
		goto end;
	}

	/* update data */
	tid_agg_rx->ssn = start_seq_num;
	tid_agg_rx->head_seq_num = start_seq_num;
	tid_agg_rx->buf_size = buf_size;
	tid_agg_rx->timeout = timeout;
	tid_agg_rx->stored_mpdu_num = 0;
	tid_agg_rx->auto_seq = auto_seq;
	tid_agg_rx->started = false;
	tid_agg_rx->reorder_buf_filtered = 0;
	tid_agg_rx->tid = tid;
	tid_agg_rx->sta = sta;
	status = WLAN_STATUS_SUCCESS;

	/* activate it for RX */
	rcu_assign_pointer(sta->ampdu_mlme.tid_rx[tid], tid_agg_rx);

	if (timeout) {
		mod_timer(&tid_agg_rx->session_timer, TU_TO_EXP_TIME(timeout));
		tid_agg_rx->last_rx = jiffies;
	}

end:
	if (status == WLAN_STATUS_SUCCESS) {

Annotation

Implementation Notes