wme.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. /*
  2. * Copyright 2004, Instant802 Networks, Inc.
  3. * Copyright 2013-2014 Intel Mobile Communications GmbH
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License version 2 as
  7. * published by the Free Software Foundation.
  8. */
  9. #include <linux/netdevice.h>
  10. #include <linux/skbuff.h>
  11. #include <linux/module.h>
  12. #include <linux/if_arp.h>
  13. #include <linux/types.h>
  14. #include <net/ip.h>
  15. #include <net/pkt_sched.h>
  16. #include <net/mac80211.h>
  17. #include "ieee80211_i.h"
  18. #include "wme.h"
  19. /* Default mapping in classifier to work with default
  20. * queue setup.
  21. */
  22. const int ieee802_1d_to_ac[8] = {
  23. IEEE80211_AC_BE,
  24. IEEE80211_AC_BK,
  25. IEEE80211_AC_BK,
  26. IEEE80211_AC_BE,
  27. IEEE80211_AC_VI,
  28. IEEE80211_AC_VI,
  29. IEEE80211_AC_VO,
  30. IEEE80211_AC_VO
  31. };
  32. static int wme_downgrade_ac(struct sk_buff *skb)
  33. {
  34. switch (skb->priority) {
  35. case 6:
  36. case 7:
  37. skb->priority = 5; /* VO -> VI */
  38. return 0;
  39. case 4:
  40. case 5:
  41. skb->priority = 3; /* VI -> BE */
  42. return 0;
  43. case 0:
  44. case 3:
  45. skb->priority = 2; /* BE -> BK */
  46. return 0;
  47. default:
  48. return -1;
  49. }
  50. }
  51. /**
  52. * ieee80211_fix_reserved_tid - return the TID to use if this one is reserved
  53. * @tid: the assumed-reserved TID
  54. *
  55. * Returns: the alternative TID to use, or 0 on error
  56. */
  57. static inline u8 ieee80211_fix_reserved_tid(u8 tid)
  58. {
  59. switch (tid) {
  60. case 0:
  61. return 3;
  62. case 1:
  63. return 2;
  64. case 2:
  65. return 1;
  66. case 3:
  67. return 0;
  68. case 4:
  69. return 5;
  70. case 5:
  71. return 4;
  72. case 6:
  73. return 7;
  74. case 7:
  75. return 6;
  76. }
  77. return 0;
  78. }
  79. static u16 ieee80211_downgrade_queue(struct ieee80211_sub_if_data *sdata,
  80. struct sta_info *sta, struct sk_buff *skb)
  81. {
  82. struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
  83. /* in case we are a client verify acm is not set for this ac */
  84. while (sdata->wmm_acm & BIT(skb->priority)) {
  85. int ac = ieee802_1d_to_ac[skb->priority];
  86. if (ifmgd->tx_tspec[ac].admitted_time &&
  87. skb->priority == ifmgd->tx_tspec[ac].up)
  88. return ac;
  89. if (wme_downgrade_ac(skb)) {
  90. /*
  91. * This should not really happen. The AP has marked all
  92. * lower ACs to require admission control which is not
  93. * a reasonable configuration. Allow the frame to be
  94. * transmitted using AC_BK as a workaround.
  95. */
  96. break;
  97. }
  98. }
  99. /* Check to see if this is a reserved TID */
  100. if (sta && sta->reserved_tid == skb->priority)
  101. skb->priority = ieee80211_fix_reserved_tid(skb->priority);
  102. /* look up which queue to use for frames with this 1d tag */
  103. return ieee802_1d_to_ac[skb->priority];
  104. }
  105. /* Indicate which queue to use for this fully formed 802.11 frame */
  106. u16 ieee80211_select_queue_80211(struct ieee80211_sub_if_data *sdata,
  107. struct sk_buff *skb,
  108. struct ieee80211_hdr *hdr)
  109. {
  110. struct ieee80211_local *local = sdata->local;
  111. u8 *p;
  112. if (local->hw.queues < IEEE80211_NUM_ACS)
  113. return 0;
  114. if (!ieee80211_is_data(hdr->frame_control)) {
  115. skb->priority = 7;
  116. return ieee802_1d_to_ac[skb->priority];
  117. }
  118. if (!ieee80211_is_data_qos(hdr->frame_control)) {
  119. skb->priority = 0;
  120. return ieee802_1d_to_ac[skb->priority];
  121. }
  122. p = ieee80211_get_qos_ctl(hdr);
  123. skb->priority = *p & IEEE80211_QOS_CTL_TAG1D_MASK;
  124. return ieee80211_downgrade_queue(sdata, NULL, skb);
  125. }
  126. /* Indicate which queue to use. */
  127. u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata,
  128. struct sk_buff *skb)
  129. {
  130. struct ieee80211_local *local = sdata->local;
  131. struct sta_info *sta = NULL;
  132. const u8 *ra = NULL;
  133. bool qos = false;
  134. struct mac80211_qos_map *qos_map;
  135. u16 ret;
  136. if (local->hw.queues < IEEE80211_NUM_ACS || skb->len < 6) {
  137. skb->priority = 0; /* required for correct WPA/11i MIC */
  138. return 0;
  139. }
  140. rcu_read_lock();
  141. switch (sdata->vif.type) {
  142. case NL80211_IFTYPE_AP_VLAN:
  143. sta = rcu_dereference(sdata->u.vlan.sta);
  144. if (sta) {
  145. qos = sta->sta.wme;
  146. break;
  147. }
  148. case NL80211_IFTYPE_AP:
  149. ra = skb->data;
  150. break;
  151. case NL80211_IFTYPE_WDS:
  152. ra = sdata->u.wds.remote_addr;
  153. break;
  154. #ifdef CONFIG_MAC80211_MESH
  155. case NL80211_IFTYPE_MESH_POINT:
  156. qos = true;
  157. break;
  158. #endif
  159. case NL80211_IFTYPE_STATION:
  160. /* might be a TDLS station */
  161. sta = sta_info_get(sdata, skb->data);
  162. if (sta)
  163. qos = sta->sta.wme;
  164. ra = sdata->u.mgd.bssid;
  165. break;
  166. case NL80211_IFTYPE_ADHOC:
  167. ra = skb->data;
  168. break;
  169. case NL80211_IFTYPE_OCB:
  170. /* all stations are required to support WME */
  171. qos = true;
  172. break;
  173. default:
  174. break;
  175. }
  176. if (!sta && ra && !is_multicast_ether_addr(ra)) {
  177. sta = sta_info_get(sdata, ra);
  178. if (sta)
  179. qos = sta->sta.wme;
  180. }
  181. if (!qos) {
  182. skb->priority = 0; /* required for correct WPA/11i MIC */
  183. ret = IEEE80211_AC_BE;
  184. goto out;
  185. }
  186. if (skb->protocol == sdata->control_port_protocol) {
  187. skb->priority = 7;
  188. goto downgrade;
  189. }
  190. /* use the data classifier to determine what 802.1d tag the
  191. * data frame has */
  192. qos_map = rcu_dereference(sdata->qos_map);
  193. skb->priority = cfg80211_classify8021d(skb, qos_map ?
  194. &qos_map->qos_map : NULL);
  195. downgrade:
  196. ret = ieee80211_downgrade_queue(sdata, sta, skb);
  197. out:
  198. rcu_read_unlock();
  199. return ret;
  200. }
  201. /**
  202. * ieee80211_set_qos_hdr - Fill in the QoS header if there is one.
  203. *
  204. * @sdata: local subif
  205. * @skb: packet to be updated
  206. */
  207. void ieee80211_set_qos_hdr(struct ieee80211_sub_if_data *sdata,
  208. struct sk_buff *skb)
  209. {
  210. struct ieee80211_hdr *hdr = (void *)skb->data;
  211. struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
  212. u8 *p;
  213. u8 ack_policy, tid;
  214. if (!ieee80211_is_data_qos(hdr->frame_control))
  215. return;
  216. p = ieee80211_get_qos_ctl(hdr);
  217. tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
  218. /* preserve EOSP bit */
  219. ack_policy = *p & IEEE80211_QOS_CTL_EOSP;
  220. if (is_multicast_ether_addr(hdr->addr1) ||
  221. sdata->noack_map & BIT(tid)) {
  222. ack_policy |= IEEE80211_QOS_CTL_ACK_POLICY_NOACK;
  223. info->flags |= IEEE80211_TX_CTL_NO_ACK;
  224. }
  225. /* qos header is 2 bytes */
  226. *p++ = ack_policy | tid;
  227. if (ieee80211_vif_is_mesh(&sdata->vif)) {
  228. /* preserve RSPI and Mesh PS Level bit */
  229. *p &= ((IEEE80211_QOS_CTL_RSPI |
  230. IEEE80211_QOS_CTL_MESH_PS_LEVEL) >> 8);
  231. /* Nulls don't have a mesh header (frame body) */
  232. if (!ieee80211_is_qos_nullfunc(hdr->frame_control))
  233. *p |= (IEEE80211_QOS_CTL_MESH_CONTROL_PRESENT >> 8);
  234. } else {
  235. *p = 0;
  236. }
  237. }