wme.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  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. /* fall through */
  149. case NL80211_IFTYPE_AP:
  150. ra = skb->data;
  151. break;
  152. case NL80211_IFTYPE_WDS:
  153. ra = sdata->u.wds.remote_addr;
  154. break;
  155. #ifdef CONFIG_MAC80211_MESH
  156. case NL80211_IFTYPE_MESH_POINT:
  157. qos = true;
  158. break;
  159. #endif
  160. case NL80211_IFTYPE_STATION:
  161. /* might be a TDLS station */
  162. sta = sta_info_get(sdata, skb->data);
  163. if (sta)
  164. qos = sta->sta.wme;
  165. ra = sdata->u.mgd.bssid;
  166. break;
  167. case NL80211_IFTYPE_ADHOC:
  168. ra = skb->data;
  169. break;
  170. case NL80211_IFTYPE_OCB:
  171. /* all stations are required to support WME */
  172. qos = true;
  173. break;
  174. default:
  175. break;
  176. }
  177. if (!sta && ra && !is_multicast_ether_addr(ra)) {
  178. sta = sta_info_get(sdata, ra);
  179. if (sta)
  180. qos = sta->sta.wme;
  181. }
  182. if (!qos) {
  183. skb->priority = 0; /* required for correct WPA/11i MIC */
  184. ret = IEEE80211_AC_BE;
  185. goto out;
  186. }
  187. if (skb->protocol == sdata->control_port_protocol) {
  188. skb->priority = 7;
  189. goto downgrade;
  190. }
  191. /* use the data classifier to determine what 802.1d tag the
  192. * data frame has */
  193. qos_map = rcu_dereference(sdata->qos_map);
  194. skb->priority = cfg80211_classify8021d(skb, qos_map ?
  195. &qos_map->qos_map : NULL);
  196. downgrade:
  197. ret = ieee80211_downgrade_queue(sdata, sta, skb);
  198. out:
  199. rcu_read_unlock();
  200. return ret;
  201. }
  202. /**
  203. * ieee80211_set_qos_hdr - Fill in the QoS header if there is one.
  204. *
  205. * @sdata: local subif
  206. * @skb: packet to be updated
  207. */
  208. void ieee80211_set_qos_hdr(struct ieee80211_sub_if_data *sdata,
  209. struct sk_buff *skb)
  210. {
  211. struct ieee80211_hdr *hdr = (void *)skb->data;
  212. struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
  213. u8 tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
  214. u8 flags;
  215. u8 *p;
  216. if (!ieee80211_is_data_qos(hdr->frame_control))
  217. return;
  218. p = ieee80211_get_qos_ctl(hdr);
  219. /* set up the first byte */
  220. /*
  221. * preserve everything but the TID and ACK policy
  222. * (which we both write here)
  223. */
  224. flags = *p & ~(IEEE80211_QOS_CTL_TID_MASK |
  225. IEEE80211_QOS_CTL_ACK_POLICY_MASK);
  226. if (is_multicast_ether_addr(hdr->addr1) ||
  227. sdata->noack_map & BIT(tid)) {
  228. flags |= IEEE80211_QOS_CTL_ACK_POLICY_NOACK;
  229. info->flags |= IEEE80211_TX_CTL_NO_ACK;
  230. }
  231. *p = flags | tid;
  232. /* set up the second byte */
  233. p++;
  234. if (ieee80211_vif_is_mesh(&sdata->vif)) {
  235. /* preserve RSPI and Mesh PS Level bit */
  236. *p &= ((IEEE80211_QOS_CTL_RSPI |
  237. IEEE80211_QOS_CTL_MESH_PS_LEVEL) >> 8);
  238. /* Nulls don't have a mesh header (frame body) */
  239. if (!ieee80211_is_qos_nullfunc(hdr->frame_control))
  240. *p |= (IEEE80211_QOS_CTL_MESH_CONTROL_PRESENT >> 8);
  241. } else {
  242. *p = 0;
  243. }
  244. }