Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright 2004, Instant802 Networks, Inc.
0004  * Copyright 2013-2014  Intel Mobile Communications GmbH
0005  * Copyright (C) 2022 Intel Corporation
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 /* Default mapping in classifier to work with default
0021  * queue setup.
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; /* VO -> VI */
0040         return 0;
0041     case 4:
0042     case 5:
0043         skb->priority = 3; /* VI -> BE */
0044         return 0;
0045     case 0:
0046     case 3:
0047         skb->priority = 2; /* BE -> BK */
0048         return 0;
0049     default:
0050         return -1;
0051     }
0052 }
0053 
0054 /**
0055  * ieee80211_fix_reserved_tid - return the TID to use if this one is reserved
0056  * @tid: the assumed-reserved TID
0057  *
0058  * Returns: the alternative TID to use, or 0 on error
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     /* in case we are a client verify acm is not set for this ac */
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              * This should not really happen. The AP has marked all
0100              * lower ACs to require admission control which is not
0101              * a reasonable configuration. Allow the frame to be
0102              * transmitted using AC_BK as a workaround.
0103              */
0104             break;
0105         }
0106     }
0107 
0108     /* Check to see if this is a reserved TID */
0109     if (sta && sta->reserved_tid == skb->priority)
0110         skb->priority = ieee80211_fix_reserved_tid(skb->priority);
0111 
0112     /* look up which queue to use for frames with this 1d tag */
0113     return ieee802_1d_to_ac[skb->priority];
0114 }
0115 
0116 /* Indicate which queue to use for this fully formed 802.11 frame */
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     /* all mesh/ocb stations are required to support WME */
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; /* required for correct WPA/11i MIC */
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     /* use the data classifier to determine what 802.1d tag the
0170      * data frame has */
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 /* Indicate which queue to use. */
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     /* when using iTXQ, we can do this later */
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; /* required for correct WPA/11i MIC */
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         /* might be a TDLS station */
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  * ieee80211_set_qos_hdr - Fill in the QoS header if there is one.
0234  *
0235  * @sdata: local subif
0236  * @skb: packet to be updated
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     /* don't overwrite the QoS field of injected frames */
0253     if (info->flags & IEEE80211_TX_CTL_INJECTED) {
0254         /* do take into account Ack policy of injected frames */
0255         if (*p & IEEE80211_QOS_CTL_ACK_POLICY_NOACK)
0256             info->flags |= IEEE80211_TX_CTL_NO_ACK;
0257         return;
0258     }
0259 
0260     /* set up the first byte */
0261 
0262     /*
0263      * preserve everything but the TID and ACK policy
0264      * (which we both write here)
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     /* set up the second byte */
0278     p++;
0279 
0280     if (ieee80211_vif_is_mesh(&sdata->vif)) {
0281         /* preserve RSPI and Mesh PS Level bit */
0282         *p &= ((IEEE80211_QOS_CTL_RSPI |
0283             IEEE80211_QOS_CTL_MESH_PS_LEVEL) >> 8);
0284 
0285         /* Nulls don't have a mesh header (frame body) */
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 }