wme.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright 2004, Instant802 Networks, Inc.
  4. * Copyright 2013-2014 Intel Mobile Communications GmbH
  5. * Copyright (C) 2022 Intel Corporation
  6. */
  7. #include <linux/netdevice.h>
  8. #include <linux/skbuff.h>
  9. #include <linux/module.h>
  10. #include <linux/if_arp.h>
  11. #include <linux/types.h>
  12. #include <net/ip.h>
  13. #include <net/pkt_sched.h>
  14. #include <net/mac80211.h>
  15. #include "ieee80211_i.h"
  16. #include "wme.h"
  17. /* Default mapping in classifier to work with default
  18. * queue setup.
  19. */
  20. const int ieee802_1d_to_ac[8] = {
  21. IEEE80211_AC_BE,
  22. IEEE80211_AC_BK,
  23. IEEE80211_AC_BK,
  24. IEEE80211_AC_BE,
  25. IEEE80211_AC_VI,
  26. IEEE80211_AC_VI,
  27. IEEE80211_AC_VO,
  28. IEEE80211_AC_VO
  29. };
  30. static int wme_downgrade_ac(struct sk_buff *skb)
  31. {
  32. switch (skb->priority) {
  33. case 6:
  34. case 7:
  35. skb->priority = 5; /* VO -> VI */
  36. return 0;
  37. case 4:
  38. case 5:
  39. skb->priority = 3; /* VI -> BE */
  40. return 0;
  41. case 0:
  42. case 3:
  43. skb->priority = 2; /* BE -> BK */
  44. return 0;
  45. default:
  46. return -1;
  47. }
  48. }
  49. /**
  50. * ieee80211_fix_reserved_tid - return the TID to use if this one is reserved
  51. * @tid: the assumed-reserved TID
  52. *
  53. * Returns: the alternative TID to use, or 0 on error
  54. */
  55. static inline u8 ieee80211_fix_reserved_tid(u8 tid)
  56. {
  57. switch (tid) {
  58. case 0:
  59. return 3;
  60. case 1:
  61. return 2;
  62. case 2:
  63. return 1;
  64. case 3:
  65. return 0;
  66. case 4:
  67. return 5;
  68. case 5:
  69. return 4;
  70. case 6:
  71. return 7;
  72. case 7:
  73. return 6;
  74. }
  75. return 0;
  76. }
  77. static u16 ieee80211_downgrade_queue(struct ieee80211_sub_if_data *sdata,
  78. struct sta_info *sta, struct sk_buff *skb)
  79. {
  80. struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
  81. /* in case we are a client verify acm is not set for this ac */
  82. while (sdata->wmm_acm & BIT(skb->priority)) {
  83. int ac = ieee802_1d_to_ac[skb->priority];
  84. if (ifmgd->tx_tspec[ac].admitted_time &&
  85. skb->priority == ifmgd->tx_tspec[ac].up)
  86. return ac;
  87. if (wme_downgrade_ac(skb)) {
  88. /*
  89. * This should not really happen. The AP has marked all
  90. * lower ACs to require admission control which is not
  91. * a reasonable configuration. Allow the frame to be
  92. * transmitted using AC_BK as a workaround.
  93. */
  94. break;
  95. }
  96. }
  97. /* Check to see if this is a reserved TID */
  98. if (sta && sta->reserved_tid == skb->priority)
  99. skb->priority = ieee80211_fix_reserved_tid(skb->priority);
  100. /* look up which queue to use for frames with this 1d tag */
  101. return ieee802_1d_to_ac[skb->priority];
  102. }
  103. /* Indicate which queue to use for this fully formed 802.11 frame */
  104. u16 ieee80211_select_queue_80211(struct ieee80211_sub_if_data *sdata,
  105. struct sk_buff *skb,
  106. struct ieee80211_hdr *hdr)
  107. {
  108. struct ieee80211_local *local = sdata->local;
  109. struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
  110. u8 *p;
  111. /* Ensure hash is set prior to potential SW encryption */
  112. skb_get_hash(skb);
  113. if ((info->control.flags & IEEE80211_TX_CTRL_DONT_REORDER) ||
  114. local->hw.queues < IEEE80211_NUM_ACS)
  115. return 0;
  116. if (!ieee80211_is_data(hdr->frame_control)) {
  117. skb->priority = 7;
  118. return ieee802_1d_to_ac[skb->priority];
  119. }
  120. if (!ieee80211_is_data_qos(hdr->frame_control)) {
  121. skb->priority = 0;
  122. return ieee802_1d_to_ac[skb->priority];
  123. }
  124. p = ieee80211_get_qos_ctl(hdr);
  125. skb->priority = *p & IEEE80211_QOS_CTL_TAG1D_MASK;
  126. return ieee80211_downgrade_queue(sdata, NULL, skb);
  127. }
  128. u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata,
  129. struct sta_info *sta, struct sk_buff *skb)
  130. {
  131. const struct ethhdr *eth = (void *)skb->data;
  132. struct mac80211_qos_map *qos_map;
  133. bool qos;
  134. /* Ensure hash is set prior to potential SW encryption */
  135. skb_get_hash(skb);
  136. /* all mesh/ocb stations are required to support WME */
  137. if ((sdata->vif.type == NL80211_IFTYPE_MESH_POINT &&
  138. !is_multicast_ether_addr(eth->h_dest)) ||
  139. (sdata->vif.type == NL80211_IFTYPE_OCB && sta))
  140. qos = true;
  141. else if (sta)
  142. qos = sta->sta.wme;
  143. else
  144. qos = false;
  145. if (!qos) {
  146. skb->priority = 0; /* required for correct WPA/11i MIC */
  147. return IEEE80211_AC_BE;
  148. }
  149. if (skb->protocol == sdata->control_port_protocol) {
  150. skb->priority = 7;
  151. goto downgrade;
  152. }
  153. /* use the data classifier to determine what 802.1d tag the
  154. * data frame has */
  155. qos_map = rcu_dereference(sdata->qos_map);
  156. skb->priority = cfg80211_classify8021d(skb, qos_map ?
  157. &qos_map->qos_map : NULL);
  158. downgrade:
  159. return ieee80211_downgrade_queue(sdata, sta, skb);
  160. }
  161. /**
  162. * ieee80211_set_qos_hdr - Fill in the QoS header if there is one.
  163. *
  164. * @sdata: local subif
  165. * @skb: packet to be updated
  166. */
  167. void ieee80211_set_qos_hdr(struct ieee80211_sub_if_data *sdata,
  168. struct sk_buff *skb)
  169. {
  170. struct ieee80211_hdr *hdr = (void *)skb->data;
  171. struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
  172. u8 tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
  173. u8 flags;
  174. u8 *p;
  175. if (!ieee80211_is_data_qos(hdr->frame_control))
  176. return;
  177. p = ieee80211_get_qos_ctl(hdr);
  178. /* don't overwrite the QoS field of injected frames */
  179. if (info->flags & IEEE80211_TX_CTL_INJECTED) {
  180. /* do take into account Ack policy of injected frames */
  181. if (*p & IEEE80211_QOS_CTL_ACK_POLICY_NOACK)
  182. info->flags |= IEEE80211_TX_CTL_NO_ACK;
  183. return;
  184. }
  185. /* set up the first byte */
  186. /*
  187. * preserve everything but the TID and ACK policy
  188. * (which we both write here)
  189. */
  190. flags = *p & ~(IEEE80211_QOS_CTL_TID_MASK |
  191. IEEE80211_QOS_CTL_ACK_POLICY_MASK);
  192. if (is_multicast_ether_addr(hdr->addr1) ||
  193. sdata->noack_map & BIT(tid)) {
  194. flags |= IEEE80211_QOS_CTL_ACK_POLICY_NOACK;
  195. info->flags |= IEEE80211_TX_CTL_NO_ACK;
  196. }
  197. *p = flags | tid;
  198. /* set up the second byte */
  199. p++;
  200. if (ieee80211_vif_is_mesh(&sdata->vif)) {
  201. /* preserve RSPI and Mesh PS Level bit */
  202. *p &= ((IEEE80211_QOS_CTL_RSPI |
  203. IEEE80211_QOS_CTL_MESH_PS_LEVEL) >> 8);
  204. /* Nulls don't have a mesh header (frame body) */
  205. if (!ieee80211_is_qos_nullfunc(hdr->frame_control))
  206. *p |= (IEEE80211_QOS_CTL_MESH_CONTROL_PRESENT >> 8);
  207. } else {
  208. *p = 0;
  209. }
  210. }