cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

s1g.c (5659B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * S1G handling
      4 * Copyright(c) 2020 Adapt-IP
      5 */
      6#include <linux/ieee80211.h>
      7#include <net/mac80211.h>
      8#include "ieee80211_i.h"
      9#include "driver-ops.h"
     10
     11void ieee80211_s1g_sta_rate_init(struct sta_info *sta)
     12{
     13	/* avoid indicating legacy bitrates for S1G STAs */
     14	sta->deflink.tx_stats.last_rate.flags |= IEEE80211_TX_RC_S1G_MCS;
     15	sta->deflink.rx_stats.last_rate =
     16			STA_STATS_FIELD(TYPE, STA_STATS_RATE_TYPE_S1G);
     17}
     18
     19bool ieee80211_s1g_is_twt_setup(struct sk_buff *skb)
     20{
     21	struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
     22
     23	if (likely(!ieee80211_is_action(mgmt->frame_control)))
     24		return false;
     25
     26	if (likely(mgmt->u.action.category != WLAN_CATEGORY_S1G))
     27		return false;
     28
     29	return mgmt->u.action.u.s1g.action_code == WLAN_S1G_TWT_SETUP;
     30}
     31
     32static void
     33ieee80211_s1g_send_twt_setup(struct ieee80211_sub_if_data *sdata, const u8 *da,
     34			     const u8 *bssid, struct ieee80211_twt_setup *twt)
     35{
     36	int len = IEEE80211_MIN_ACTION_SIZE + 4 + twt->length;
     37	struct ieee80211_local *local = sdata->local;
     38	struct ieee80211_mgmt *mgmt;
     39	struct sk_buff *skb;
     40
     41	skb = dev_alloc_skb(local->hw.extra_tx_headroom + len);
     42	if (!skb)
     43		return;
     44
     45	skb_reserve(skb, local->hw.extra_tx_headroom);
     46	mgmt = skb_put_zero(skb, len);
     47	mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
     48					  IEEE80211_STYPE_ACTION);
     49	memcpy(mgmt->da, da, ETH_ALEN);
     50	memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
     51	memcpy(mgmt->bssid, bssid, ETH_ALEN);
     52
     53	mgmt->u.action.category = WLAN_CATEGORY_S1G;
     54	mgmt->u.action.u.s1g.action_code = WLAN_S1G_TWT_SETUP;
     55	memcpy(mgmt->u.action.u.s1g.variable, twt, 3 + twt->length);
     56
     57	IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT |
     58					IEEE80211_TX_INTFL_MLME_CONN_TX |
     59					IEEE80211_TX_CTL_REQ_TX_STATUS;
     60	ieee80211_tx_skb(sdata, skb);
     61}
     62
     63static void
     64ieee80211_s1g_send_twt_teardown(struct ieee80211_sub_if_data *sdata,
     65				const u8 *da, const u8 *bssid, u8 flowid)
     66{
     67	struct ieee80211_local *local = sdata->local;
     68	struct ieee80211_mgmt *mgmt;
     69	struct sk_buff *skb;
     70	u8 *id;
     71
     72	skb = dev_alloc_skb(local->hw.extra_tx_headroom +
     73			    IEEE80211_MIN_ACTION_SIZE + 2);
     74	if (!skb)
     75		return;
     76
     77	skb_reserve(skb, local->hw.extra_tx_headroom);
     78	mgmt = skb_put_zero(skb, IEEE80211_MIN_ACTION_SIZE + 2);
     79	mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
     80					  IEEE80211_STYPE_ACTION);
     81	memcpy(mgmt->da, da, ETH_ALEN);
     82	memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
     83	memcpy(mgmt->bssid, bssid, ETH_ALEN);
     84
     85	mgmt->u.action.category = WLAN_CATEGORY_S1G;
     86	mgmt->u.action.u.s1g.action_code = WLAN_S1G_TWT_TEARDOWN;
     87	id = (u8 *)mgmt->u.action.u.s1g.variable;
     88	*id = flowid;
     89
     90	IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT |
     91					IEEE80211_TX_CTL_REQ_TX_STATUS;
     92	ieee80211_tx_skb(sdata, skb);
     93}
     94
     95static void
     96ieee80211_s1g_rx_twt_setup(struct ieee80211_sub_if_data *sdata,
     97			   struct sta_info *sta, struct sk_buff *skb)
     98{
     99	struct ieee80211_mgmt *mgmt = (void *)skb->data;
    100	struct ieee80211_twt_setup *twt = (void *)mgmt->u.action.u.s1g.variable;
    101	struct ieee80211_twt_params *twt_agrt = (void *)twt->params;
    102
    103	twt_agrt->req_type &= cpu_to_le16(~IEEE80211_TWT_REQTYPE_REQUEST);
    104
    105	/* broadcast TWT not supported yet */
    106	if (twt->control & IEEE80211_TWT_CONTROL_NEG_TYPE_BROADCAST) {
    107		twt_agrt->req_type &=
    108			~cpu_to_le16(IEEE80211_TWT_REQTYPE_SETUP_CMD);
    109		twt_agrt->req_type |=
    110			le16_encode_bits(TWT_SETUP_CMD_REJECT,
    111					 IEEE80211_TWT_REQTYPE_SETUP_CMD);
    112		goto out;
    113	}
    114
    115	drv_add_twt_setup(sdata->local, sdata, &sta->sta, twt);
    116out:
    117	ieee80211_s1g_send_twt_setup(sdata, mgmt->sa, sdata->vif.addr, twt);
    118}
    119
    120static void
    121ieee80211_s1g_rx_twt_teardown(struct ieee80211_sub_if_data *sdata,
    122			      struct sta_info *sta, struct sk_buff *skb)
    123{
    124	struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
    125
    126	drv_twt_teardown_request(sdata->local, sdata, &sta->sta,
    127				 mgmt->u.action.u.s1g.variable[0]);
    128}
    129
    130static void
    131ieee80211_s1g_tx_twt_setup_fail(struct ieee80211_sub_if_data *sdata,
    132				struct sta_info *sta, struct sk_buff *skb)
    133{
    134	struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
    135	struct ieee80211_twt_setup *twt = (void *)mgmt->u.action.u.s1g.variable;
    136	struct ieee80211_twt_params *twt_agrt = (void *)twt->params;
    137	u8 flowid = le16_get_bits(twt_agrt->req_type,
    138				  IEEE80211_TWT_REQTYPE_FLOWID);
    139
    140	drv_twt_teardown_request(sdata->local, sdata, &sta->sta, flowid);
    141
    142	ieee80211_s1g_send_twt_teardown(sdata, mgmt->sa, sdata->vif.addr,
    143					flowid);
    144}
    145
    146void ieee80211_s1g_rx_twt_action(struct ieee80211_sub_if_data *sdata,
    147				 struct sk_buff *skb)
    148{
    149	struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
    150	struct ieee80211_local *local = sdata->local;
    151	struct sta_info *sta;
    152
    153	mutex_lock(&local->sta_mtx);
    154
    155	sta = sta_info_get_bss(sdata, mgmt->sa);
    156	if (!sta)
    157		goto out;
    158
    159	switch (mgmt->u.action.u.s1g.action_code) {
    160	case WLAN_S1G_TWT_SETUP:
    161		ieee80211_s1g_rx_twt_setup(sdata, sta, skb);
    162		break;
    163	case WLAN_S1G_TWT_TEARDOWN:
    164		ieee80211_s1g_rx_twt_teardown(sdata, sta, skb);
    165		break;
    166	default:
    167		break;
    168	}
    169
    170out:
    171	mutex_unlock(&local->sta_mtx);
    172}
    173
    174void ieee80211_s1g_status_twt_action(struct ieee80211_sub_if_data *sdata,
    175				     struct sk_buff *skb)
    176{
    177	struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
    178	struct ieee80211_local *local = sdata->local;
    179	struct sta_info *sta;
    180
    181	mutex_lock(&local->sta_mtx);
    182
    183	sta = sta_info_get_bss(sdata, mgmt->da);
    184	if (!sta)
    185		goto out;
    186
    187	switch (mgmt->u.action.u.s1g.action_code) {
    188	case WLAN_S1G_TWT_SETUP:
    189		/* process failed twt setup frames */
    190		ieee80211_s1g_tx_twt_setup_fail(sdata, sta, skb);
    191		break;
    192	default:
    193		break;
    194	}
    195
    196out:
    197	mutex_unlock(&local->sta_mtx);
    198}