net/mac80211/mesh_pathtbl.c

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

File Facts

System
Linux kernel
Corpus path
net/mac80211/mesh_pathtbl.c
Extension
.c
Size
30258 bytes
Lines
1101
Domain
Networking Core
Bucket
Sockets, Protocols, Packet Path, And Network Policy
Inferred role
Networking Core: implementation source
Status
source 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

mpath_expired(entry->mpath)) {
		spin_lock_bh(&cache->walk_lock);
		entry = rhashtable_lookup(&cache->rht, key, fast_tx_rht_params);
		if (entry)
		    mesh_fast_tx_entry_free(cache, entry);
		spin_unlock_bh(&cache->walk_lock);
		return NULL;
	}

	mesh_path_refresh(sdata, entry->mpath, NULL);
	if (entry->mppath)
		entry->mppath->exp_time = jiffies;
	entry->timestamp = jiffies;

	return entry;
}

void mesh_fast_tx_cache(struct ieee80211_sub_if_data *sdata,
			struct sk_buff *skb, struct mesh_path *mpath)
{
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
	struct ieee80211_mesh_fast_tx *entry, *prev;
	struct ieee80211_mesh_fast_tx build = {};
	struct ieee80211s_hdr *meshhdr;
	struct mesh_tx_cache *cache;
	struct ieee80211_key *key;
	struct mesh_path *mppath;
	struct sta_info *sta;
	u8 *qc;

	if (sdata->noack_map ||
	    !ieee80211_is_data_qos(hdr->frame_control))
		return;

	build.fast_tx.hdr_len = ieee80211_hdrlen(hdr->frame_control);
	meshhdr = (struct ieee80211s_hdr *)(skb->data + build.fast_tx.hdr_len);
	build.hdrlen = ieee80211_get_mesh_hdrlen(meshhdr);

	cache = &sdata->u.mesh.tx_cache;
	if (atomic_read(&cache->rht.nelems) >= MESH_FAST_TX_CACHE_MAX_SIZE)
		return;

	sta = rcu_dereference(mpath->next_hop);
	if (!sta)
		return;

	build.key.type = MESH_FAST_TX_TYPE_LOCAL;
	if ((meshhdr->flags & MESH_FLAGS_AE) == MESH_FLAGS_AE_A5_A6) {
		/* This is required to keep the mppath alive */
		mppath = mpp_path_lookup(sdata, meshhdr->eaddr1);
		if (!mppath)
			return;
		build.mppath = mppath;
		if (!ether_addr_equal(meshhdr->eaddr2, sdata->vif.addr))
			build.key.type = MESH_FAST_TX_TYPE_PROXIED;
	} else if (ieee80211_has_a4(hdr->frame_control)) {
		mppath = mpath;
	} else {
		return;
	}

	if (!ether_addr_equal(hdr->addr4, sdata->vif.addr))
		build.key.type = MESH_FAST_TX_TYPE_FORWARDED;

	/* rate limit, in case fast xmit can't be enabled */
	if (mppath->fast_tx_check == jiffies)
		return;

	mppath->fast_tx_check = jiffies;

	/*
	 * Same use of the sta lock as in ieee80211_check_fast_xmit, in order
	 * to protect against concurrent sta key updates.
	 */
	spin_lock_bh(&sta->lock);
	key = rcu_access_pointer(sta->ptk[sta->ptk_idx]);
	if (!key)
		key = rcu_access_pointer(sdata->default_unicast_key);
	build.fast_tx.key = key;

	if (key) {
		bool gen_iv, iv_spc;

		gen_iv = key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV;
		iv_spc = key->conf.flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE;

		if (!(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) ||
		    (key->flags & KEY_FLAG_TAINTED))
			goto unlock_sta;

Annotation

Implementation Notes