drivers/net/wireguard/peerlookup.c

Source file repositories/reference/linux-study-clean/drivers/net/wireguard/peerlookup.c

File Facts

System
Linux kernel
Corpus path
drivers/net/wireguard/peerlookup.c
Extension
.c
Size
6405 bytes
Lines
227
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: implementation source
Status
source 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

if (existing_entry->index == entry->index) {
			spin_unlock_bh(&table->lock);
			/* If it was stolen, we start over. */
			goto search_unused_slot;
		}
	}
	/* Otherwise, we know we have it exclusively (since we're locked),
	 * so we insert.
	 */
	hlist_add_head_rcu(&entry->index_hash,
			   index_bucket(table, entry->index));
	spin_unlock_bh(&table->lock);

	rcu_read_unlock_bh();

	return entry->index;
}

bool wg_index_hashtable_replace(struct index_hashtable *table,
				struct index_hashtable_entry *old,
				struct index_hashtable_entry *new)
{
	bool ret;

	spin_lock_bh(&table->lock);
	ret = !hlist_unhashed(&old->index_hash);
	if (unlikely(!ret))
		goto out;

	new->index = old->index;
	hlist_replace_rcu(&old->index_hash, &new->index_hash);

	/* Calling init here NULLs out index_hash, and in fact after this
	 * function returns, it's theoretically possible for this to get
	 * reinserted elsewhere. That means the RCU lookup below might either
	 * terminate early or jump between buckets, in which case the packet
	 * simply gets dropped, which isn't terrible.
	 */
	INIT_HLIST_NODE(&old->index_hash);
out:
	spin_unlock_bh(&table->lock);
	return ret;
}

void wg_index_hashtable_remove(struct index_hashtable *table,
			       struct index_hashtable_entry *entry)
{
	spin_lock_bh(&table->lock);
	hlist_del_init_rcu(&entry->index_hash);
	spin_unlock_bh(&table->lock);
}

/* Returns a strong reference to a entry->peer */
struct index_hashtable_entry *
wg_index_hashtable_lookup(struct index_hashtable *table,
			  const enum index_hashtable_type type_mask,
			  const __le32 index, struct wg_peer **peer)
{
	struct index_hashtable_entry *iter_entry, *entry = NULL;

	rcu_read_lock_bh();
	hlist_for_each_entry_rcu_bh(iter_entry, index_bucket(table, index),
				    index_hash) {
		if (iter_entry->index == index) {
			if (likely(iter_entry->type & type_mask))
				entry = iter_entry;
			break;
		}
	}
	if (likely(entry)) {
		entry->peer = wg_peer_get_maybe_zero(entry->peer);
		if (likely(entry->peer))
			*peer = entry->peer;
		else
			entry = NULL;
	}
	rcu_read_unlock_bh();
	return entry;
}

Annotation

Implementation Notes