net/mac80211/mesh.c

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

File Facts

System
Linux kernel
Corpus path
net/mac80211/mesh.c
Extension
.c
Size
50294 bytes
Lines
1795
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

hlist_for_each_entry_safe(p, n, &rmc->bucket[i], list) {
			hlist_del(&p->list);
			kmem_cache_free(rm_cache, p);
		}
	}

	kfree(rmc);
	sdata->u.mesh.rmc = NULL;
}

/**
 * mesh_rmc_check - Check frame in recent multicast cache and add if absent.
 *
 * @sdata:	interface
 * @sa:		source address
 * @mesh_hdr:	mesh_header
 *
 * Returns: 0 if the frame is not in the cache, nonzero otherwise.
 *
 * Checks using the source address and the mesh sequence number if we have
 * received this frame lately. If the frame is not in the cache, it is added to
 * it.
 */
int mesh_rmc_check(struct ieee80211_sub_if_data *sdata,
		   const u8 *sa, struct ieee80211s_hdr *mesh_hdr)
{
	struct mesh_rmc *rmc = sdata->u.mesh.rmc;
	u32 seqnum = 0;
	int entries = 0;
	u8 idx;
	struct rmc_entry *p;
	struct hlist_node *n;

	if (!rmc)
		return -1;

	/* Don't care about endianness since only match matters */
	memcpy(&seqnum, &mesh_hdr->seqnum, sizeof(mesh_hdr->seqnum));
	idx = le32_to_cpu(mesh_hdr->seqnum) & rmc->idx_mask;
	hlist_for_each_entry_safe(p, n, &rmc->bucket[idx], list) {
		++entries;
		if (time_after(jiffies, p->exp_time) ||
		    entries == RMC_QUEUE_MAX_LEN) {
			hlist_del(&p->list);
			kmem_cache_free(rm_cache, p);
			--entries;
		} else if ((seqnum == p->seqnum) && ether_addr_equal(sa, p->sa))
			return -1;
	}

	p = kmem_cache_alloc(rm_cache, GFP_ATOMIC);
	if (!p)
		return 0;

	p->seqnum = seqnum;
	p->exp_time = jiffies + RMC_TIMEOUT;
	memcpy(p->sa, sa, ETH_ALEN);
	hlist_add_head(&p->list, &rmc->bucket[idx]);
	return 0;
}

int mesh_add_meshconf_ie(struct ieee80211_sub_if_data *sdata,
			 struct sk_buff *skb)
{
	struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
	u8 *pos, neighbors;
	u8 meshconf_len = sizeof(struct ieee80211_meshconf_ie);
	bool is_connected_to_gate = ifmsh->num_gates > 0 ||
		ifmsh->mshcfg.dot11MeshGateAnnouncementProtocol ||
		ifmsh->mshcfg.dot11MeshConnectedToMeshGate;
	bool is_connected_to_as = ifmsh->mshcfg.dot11MeshConnectedToAuthServer;

	if (skb_tailroom(skb) < 2 + meshconf_len)
		return -ENOMEM;

	pos = skb_put(skb, 2 + meshconf_len);
	*pos++ = WLAN_EID_MESH_CONFIG;
	*pos++ = meshconf_len;

	/* save a pointer for quick updates in pre-tbtt */
	ifmsh->meshconf_offset = pos - skb->data;

	/* Active path selection protocol ID */
	*pos++ = ifmsh->mesh_pp_id;
	/* Active path selection metric ID   */
	*pos++ = ifmsh->mesh_pm_id;
	/* Congestion control mode identifier */
	*pos++ = ifmsh->mesh_cc_id;
	/* Synchronization protocol identifier */
	*pos++ = ifmsh->mesh_sp_id;

Annotation

Implementation Notes