~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/net/mac80211/s1g.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php