net/mac80211/s1g.c

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

File Facts

System
Linux kernel
Corpus path
net/mac80211/s1g.c
Extension
.c
Size
6736 bytes
Lines
231
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

// SPDX-License-Identifier: GPL-2.0
/*
 * S1G handling
 * Copyright(c) 2020 Adapt-IP
 * Copyright (C) 2023, 2026 Intel Corporation
 */
#include <linux/ieee80211.h>
#include <net/mac80211.h>
#include "ieee80211_i.h"
#include "driver-ops.h"

void ieee80211_s1g_sta_rate_init(struct sta_info *sta)
{
	/* avoid indicating legacy bitrates for S1G STAs */
	sta->deflink.tx_stats.last_rate.flags |= IEEE80211_TX_RC_S1G_MCS;
	sta->deflink.rx_stats.last_rate =
			STA_STATS_FIELD(TYPE, STA_STATS_RATE_TYPE_S1G);
}

bool ieee80211_s1g_is_twt_setup(struct sk_buff *skb)
{
	struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;

	if (likely(!ieee80211_is_action(mgmt->frame_control)))
		return false;

	if (likely(mgmt->u.action.category != WLAN_CATEGORY_S1G))
		return false;

	return mgmt->u.action.action_code == WLAN_S1G_TWT_SETUP;
}

static void
ieee80211_s1g_send_twt_setup(struct ieee80211_sub_if_data *sdata, const u8 *da,
			     const u8 *bssid, struct ieee80211_twt_setup *twt)
{
	int len = IEEE80211_MIN_ACTION_SIZE(s1g) + 3 + twt->length;
	struct ieee80211_local *local = sdata->local;
	struct ieee80211_mgmt *mgmt;
	struct sk_buff *skb;

	skb = dev_alloc_skb(local->hw.extra_tx_headroom + len);
	if (!skb)
		return;

	skb_reserve(skb, local->hw.extra_tx_headroom);
	mgmt = skb_put_zero(skb, len);
	mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
					  IEEE80211_STYPE_ACTION);
	memcpy(mgmt->da, da, ETH_ALEN);
	memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
	memcpy(mgmt->bssid, bssid, ETH_ALEN);

	mgmt->u.action.category = WLAN_CATEGORY_S1G;
	mgmt->u.action.action_code = WLAN_S1G_TWT_SETUP;
	memcpy(mgmt->u.action.s1g.variable, twt, 3 + twt->length);

	IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT |
					IEEE80211_TX_INTFL_MLME_CONN_TX |
					IEEE80211_TX_CTL_REQ_TX_STATUS;
	ieee80211_tx_skb(sdata, skb);
}

static void
ieee80211_s1g_send_twt_teardown(struct ieee80211_sub_if_data *sdata,
				const u8 *da, const u8 *bssid, u8 flowid)
{
	struct ieee80211_local *local = sdata->local;
	struct ieee80211_mgmt *mgmt;
	struct sk_buff *skb;
	u8 *id;

	skb = dev_alloc_skb(local->hw.extra_tx_headroom +
			    IEEE80211_MIN_ACTION_SIZE(s1g) + 1);
	if (!skb)
		return;

	skb_reserve(skb, local->hw.extra_tx_headroom);
	mgmt = skb_put_zero(skb, IEEE80211_MIN_ACTION_SIZE(s1g) + 1);
	mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
					  IEEE80211_STYPE_ACTION);
	memcpy(mgmt->da, da, ETH_ALEN);
	memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
	memcpy(mgmt->bssid, bssid, ETH_ALEN);

	mgmt->u.action.category = WLAN_CATEGORY_S1G;
	mgmt->u.action.action_code = WLAN_S1G_TWT_TEARDOWN;
	id = (u8 *)mgmt->u.action.s1g.variable;
	*id = flowid;

Annotation

Implementation Notes