0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/netdevice.h>
0009 #include <linux/skbuff.h>
0010 #include <linux/module.h>
0011 #include <linux/if_arp.h>
0012 #include <linux/types.h>
0013 #include <net/ip.h>
0014 #include <net/pkt_sched.h>
0015
0016 #include <net/mac80211.h>
0017 #include "ieee80211_i.h"
0018 #include "wme.h"
0019
0020
0021
0022
0023 const int ieee802_1d_to_ac[8] = {
0024 IEEE80211_AC_BE,
0025 IEEE80211_AC_BK,
0026 IEEE80211_AC_BK,
0027 IEEE80211_AC_BE,
0028 IEEE80211_AC_VI,
0029 IEEE80211_AC_VI,
0030 IEEE80211_AC_VO,
0031 IEEE80211_AC_VO
0032 };
0033
0034 static int wme_downgrade_ac(struct sk_buff *skb)
0035 {
0036 switch (skb->priority) {
0037 case 6:
0038 case 7:
0039 skb->priority = 5;
0040 return 0;
0041 case 4:
0042 case 5:
0043 skb->priority = 3;
0044 return 0;
0045 case 0:
0046 case 3:
0047 skb->priority = 2;
0048 return 0;
0049 default:
0050 return -1;
0051 }
0052 }
0053
0054
0055
0056
0057
0058
0059
0060 static inline u8 ieee80211_fix_reserved_tid(u8 tid)
0061 {
0062 switch (tid) {
0063 case 0:
0064 return 3;
0065 case 1:
0066 return 2;
0067 case 2:
0068 return 1;
0069 case 3:
0070 return 0;
0071 case 4:
0072 return 5;
0073 case 5:
0074 return 4;
0075 case 6:
0076 return 7;
0077 case 7:
0078 return 6;
0079 }
0080
0081 return 0;
0082 }
0083
0084 static u16 ieee80211_downgrade_queue(struct ieee80211_sub_if_data *sdata,
0085 struct sta_info *sta, struct sk_buff *skb)
0086 {
0087 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
0088
0089
0090 while (sdata->wmm_acm & BIT(skb->priority)) {
0091 int ac = ieee802_1d_to_ac[skb->priority];
0092
0093 if (ifmgd->tx_tspec[ac].admitted_time &&
0094 skb->priority == ifmgd->tx_tspec[ac].up)
0095 return ac;
0096
0097 if (wme_downgrade_ac(skb)) {
0098
0099
0100
0101
0102
0103
0104 break;
0105 }
0106 }
0107
0108
0109 if (sta && sta->reserved_tid == skb->priority)
0110 skb->priority = ieee80211_fix_reserved_tid(skb->priority);
0111
0112
0113 return ieee802_1d_to_ac[skb->priority];
0114 }
0115
0116
0117 u16 ieee80211_select_queue_80211(struct ieee80211_sub_if_data *sdata,
0118 struct sk_buff *skb,
0119 struct ieee80211_hdr *hdr)
0120 {
0121 struct ieee80211_local *local = sdata->local;
0122 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
0123 u8 *p;
0124
0125 if ((info->control.flags & IEEE80211_TX_CTRL_DONT_REORDER) ||
0126 local->hw.queues < IEEE80211_NUM_ACS)
0127 return 0;
0128
0129 if (!ieee80211_is_data(hdr->frame_control)) {
0130 skb->priority = 7;
0131 return ieee802_1d_to_ac[skb->priority];
0132 }
0133 if (!ieee80211_is_data_qos(hdr->frame_control)) {
0134 skb->priority = 0;
0135 return ieee802_1d_to_ac[skb->priority];
0136 }
0137
0138 p = ieee80211_get_qos_ctl(hdr);
0139 skb->priority = *p & IEEE80211_QOS_CTL_TAG1D_MASK;
0140
0141 return ieee80211_downgrade_queue(sdata, NULL, skb);
0142 }
0143
0144 u16 __ieee80211_select_queue(struct ieee80211_sub_if_data *sdata,
0145 struct sta_info *sta, struct sk_buff *skb)
0146 {
0147 struct mac80211_qos_map *qos_map;
0148 bool qos;
0149
0150
0151 if (sta && (sdata->vif.type == NL80211_IFTYPE_MESH_POINT ||
0152 sdata->vif.type == NL80211_IFTYPE_OCB))
0153 qos = true;
0154 else if (sta)
0155 qos = sta->sta.wme;
0156 else
0157 qos = false;
0158
0159 if (!qos) {
0160 skb->priority = 0;
0161 return IEEE80211_AC_BE;
0162 }
0163
0164 if (skb->protocol == sdata->control_port_protocol) {
0165 skb->priority = 7;
0166 goto downgrade;
0167 }
0168
0169
0170
0171 qos_map = rcu_dereference(sdata->qos_map);
0172 skb->priority = cfg80211_classify8021d(skb, qos_map ?
0173 &qos_map->qos_map : NULL);
0174
0175 downgrade:
0176 return ieee80211_downgrade_queue(sdata, sta, skb);
0177 }
0178
0179
0180
0181 u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata,
0182 struct sk_buff *skb)
0183 {
0184 struct ieee80211_local *local = sdata->local;
0185 struct sta_info *sta = NULL;
0186 const u8 *ra = NULL;
0187 u16 ret;
0188
0189
0190 if (local->ops->wake_tx_queue)
0191 return 0;
0192
0193 if (local->hw.queues < IEEE80211_NUM_ACS || skb->len < 6) {
0194 skb->priority = 0;
0195 return 0;
0196 }
0197
0198 rcu_read_lock();
0199 switch (sdata->vif.type) {
0200 case NL80211_IFTYPE_AP_VLAN:
0201 sta = rcu_dereference(sdata->u.vlan.sta);
0202 if (sta)
0203 break;
0204 fallthrough;
0205 case NL80211_IFTYPE_AP:
0206 ra = skb->data;
0207 break;
0208 case NL80211_IFTYPE_STATION:
0209
0210 sta = sta_info_get(sdata, skb->data);
0211 if (sta)
0212 break;
0213
0214 ra = sdata->deflink.u.mgd.bssid;
0215 break;
0216 case NL80211_IFTYPE_ADHOC:
0217 ra = skb->data;
0218 break;
0219 default:
0220 break;
0221 }
0222
0223 if (!sta && ra && !is_multicast_ether_addr(ra))
0224 sta = sta_info_get(sdata, ra);
0225
0226 ret = __ieee80211_select_queue(sdata, sta, skb);
0227
0228 rcu_read_unlock();
0229 return ret;
0230 }
0231
0232
0233
0234
0235
0236
0237
0238 void ieee80211_set_qos_hdr(struct ieee80211_sub_if_data *sdata,
0239 struct sk_buff *skb)
0240 {
0241 struct ieee80211_hdr *hdr = (void *)skb->data;
0242 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
0243 u8 tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
0244 u8 flags;
0245 u8 *p;
0246
0247 if (!ieee80211_is_data_qos(hdr->frame_control))
0248 return;
0249
0250 p = ieee80211_get_qos_ctl(hdr);
0251
0252
0253 if (info->flags & IEEE80211_TX_CTL_INJECTED) {
0254
0255 if (*p & IEEE80211_QOS_CTL_ACK_POLICY_NOACK)
0256 info->flags |= IEEE80211_TX_CTL_NO_ACK;
0257 return;
0258 }
0259
0260
0261
0262
0263
0264
0265
0266 flags = *p & ~(IEEE80211_QOS_CTL_TID_MASK |
0267 IEEE80211_QOS_CTL_ACK_POLICY_MASK);
0268
0269 if (is_multicast_ether_addr(hdr->addr1) ||
0270 sdata->noack_map & BIT(tid)) {
0271 flags |= IEEE80211_QOS_CTL_ACK_POLICY_NOACK;
0272 info->flags |= IEEE80211_TX_CTL_NO_ACK;
0273 }
0274
0275 *p = flags | tid;
0276
0277
0278 p++;
0279
0280 if (ieee80211_vif_is_mesh(&sdata->vif)) {
0281
0282 *p &= ((IEEE80211_QOS_CTL_RSPI |
0283 IEEE80211_QOS_CTL_MESH_PS_LEVEL) >> 8);
0284
0285
0286 if (!ieee80211_is_qos_nullfunc(hdr->frame_control))
0287 *p |= (IEEE80211_QOS_CTL_MESH_CONTROL_PRESENT >> 8);
0288 } else {
0289 *p = 0;
0290 }
0291 }