net/mac80211/iface.c

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

File Facts

System
Linux kernel
Corpus path
net/mac80211/iface.c
Extension
.c
Size
69616 bytes
Lines
2563
Domain
Networking Core
Bucket
Sockets, Protocols, Packet Path, And Network Policy
Inferred role
Networking Core: operation-table or driver-model contract
Status
pattern 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

static const struct net_device_ops ieee80211_dataif_ops = {
	.ndo_open		= ieee80211_open,
	.ndo_stop		= ieee80211_stop,
	.ndo_uninit		= ieee80211_uninit,
	.ndo_start_xmit		= ieee80211_subif_start_xmit,
	.ndo_set_rx_mode	= ieee80211_set_multicast_list,
	.ndo_set_mac_address 	= ieee80211_change_mac,
	.ndo_setup_tc		= ieee80211_netdev_setup_tc,
};

static u16 ieee80211_monitor_select_queue(struct net_device *dev,
					  struct sk_buff *skb,
					  struct net_device *sb_dev)
{
	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
	struct ieee80211_local *local = sdata->local;
	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
	struct ieee80211_hdr *hdr;
	int len_rthdr;

	if (local->hw.queues < IEEE80211_NUM_ACS)
		return 0;

	/* reset flags and info before parsing radiotap header */
	memset(info, 0, sizeof(*info));

	if (!ieee80211_parse_tx_radiotap(skb, dev))
		return 0; /* doesn't matter, frame will be dropped */

	len_rthdr = ieee80211_get_radiotap_len(skb->data);
	hdr = (struct ieee80211_hdr *)(skb->data + len_rthdr);
	if (skb->len < len_rthdr + 2 ||
	    skb->len < len_rthdr + ieee80211_hdrlen(hdr->frame_control))
		return 0; /* doesn't matter, frame will be dropped */

	return ieee80211_select_queue_80211(sdata, skb, hdr);
}

static const struct net_device_ops ieee80211_monitorif_ops = {
	.ndo_open		= ieee80211_open,
	.ndo_stop		= ieee80211_stop,
	.ndo_uninit		= ieee80211_uninit,
	.ndo_start_xmit		= ieee80211_monitor_start_xmit,
	.ndo_set_rx_mode	= ieee80211_set_multicast_list,
	.ndo_set_mac_address 	= ieee80211_change_mac,
	.ndo_select_queue	= ieee80211_monitor_select_queue,
};

static int ieee80211_netdev_fill_forward_path(struct net_device_path_ctx *ctx,
					      struct net_device_path *path)
{
	struct ieee80211_sub_if_data *sdata;
	struct ieee80211_local *local;
	struct sta_info *sta;
	int ret = -ENOENT;

	sdata = IEEE80211_DEV_TO_SUB_IF(ctx->dev);
	local = sdata->local;

	if (!local->ops->net_fill_forward_path)
		return -EOPNOTSUPP;

	rcu_read_lock();
	switch (sdata->vif.type) {
	case NL80211_IFTYPE_AP_VLAN:
		sta = rcu_dereference(sdata->u.vlan.sta);
		if (sta)
			break;
		if (sdata->wdev.use_4addr)
			goto out;
		if (is_multicast_ether_addr(ctx->daddr))
			goto out;
		sta = sta_info_get_bss(sdata, ctx->daddr);
		break;
	case NL80211_IFTYPE_AP:
		if (is_multicast_ether_addr(ctx->daddr))
			goto out;
		sta = sta_info_get(sdata, ctx->daddr);
		break;
	case NL80211_IFTYPE_STATION:
		if (sdata->wdev.wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS) {
			sta = sta_info_get(sdata, ctx->daddr);
			if (sta && test_sta_flag(sta, WLAN_STA_TDLS_PEER)) {
				if (!test_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH))
					goto out;

				break;
			}
		}

Annotation

Implementation Notes