wme.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  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. static u16 ieee80211_downgrade_queue(struct ieee80211_sub_if_data *sdata,
  52. struct sk_buff *skb)
  53. {
  54. /* in case we are a client verify acm is not set for this ac */
  55. while (unlikely(sdata->wmm_acm & BIT(skb->priority))) {
  56. if (wme_downgrade_ac(skb)) {
  57. /*
  58. * This should not really happen. The AP has marked all
  59. * lower ACs to require admission control which is not
  60. * a reasonable configuration. Allow the frame to be
  61. * transmitted using AC_BK as a workaround.
  62. */
  63. break;
  64. }
  65. }
  66. /* look up which queue to use for frames with this 1d tag */
  67. return ieee802_1d_to_ac[skb->priority];
  68. }
  69. /* Indicate which queue to use for this fully formed 802.11 frame */
  70. u16 ieee80211_select_queue_80211(struct ieee80211_sub_if_data *sdata,
  71. struct sk_buff *skb,
  72. struct ieee80211_hdr *hdr)
  73. {
  74. struct ieee80211_local *local = sdata->local;
  75. u8 *p;
  76. if (local->hw.queues < IEEE80211_NUM_ACS)
  77. return 0;
  78. if (!ieee80211_is_data(hdr->frame_control)) {
  79. skb->priority = 7;
  80. return ieee802_1d_to_ac[skb->priority];
  81. }
  82. if (!ieee80211_is_data_qos(hdr->frame_control)) {
  83. skb->priority = 0;
  84. return ieee802_1d_to_ac[skb->priority];
  85. }
  86. p = ieee80211_get_qos_ctl(hdr);
  87. skb->priority = *p & IEEE80211_QOS_CTL_TAG1D_MASK;
  88. return ieee80211_downgrade_queue(sdata, skb);
  89. }
  90. /* Indicate which queue to use. */
  91. u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata,
  92. struct sk_buff *skb)
  93. {
  94. struct ieee80211_local *local = sdata->local;
  95. struct sta_info *sta = NULL;
  96. const u8 *ra = NULL;
  97. bool qos = false;
  98. struct mac80211_qos_map *qos_map;
  99. if (local->hw.queues < IEEE80211_NUM_ACS || skb->len < 6) {
  100. skb->priority = 0; /* required for correct WPA/11i MIC */
  101. return 0;
  102. }
  103. rcu_read_lock();
  104. switch (sdata->vif.type) {
  105. case NL80211_IFTYPE_AP_VLAN:
  106. sta = rcu_dereference(sdata->u.vlan.sta);
  107. if (sta) {
  108. qos = sta->sta.wme;
  109. break;
  110. }
  111. case NL80211_IFTYPE_AP:
  112. ra = skb->data;
  113. break;
  114. case NL80211_IFTYPE_WDS:
  115. ra = sdata->u.wds.remote_addr;
  116. break;
  117. #ifdef CONFIG_MAC80211_MESH
  118. case NL80211_IFTYPE_MESH_POINT:
  119. qos = true;
  120. break;
  121. #endif
  122. case NL80211_IFTYPE_STATION:
  123. ra = sdata->u.mgd.bssid;
  124. break;
  125. case NL80211_IFTYPE_ADHOC:
  126. ra = skb->data;
  127. break;
  128. default:
  129. break;
  130. }
  131. if (!sta && ra && !is_multicast_ether_addr(ra)) {
  132. sta = sta_info_get(sdata, ra);
  133. if (sta)
  134. qos = sta->sta.wme;
  135. }
  136. rcu_read_unlock();
  137. if (!qos) {
  138. skb->priority = 0; /* required for correct WPA/11i MIC */
  139. return IEEE80211_AC_BE;
  140. }
  141. if (skb->protocol == sdata->control_port_protocol) {
  142. skb->priority = 7;
  143. return ieee80211_downgrade_queue(sdata, skb);
  144. }
  145. /* use the data classifier to determine what 802.1d tag the
  146. * data frame has */
  147. rcu_read_lock();
  148. qos_map = rcu_dereference(sdata->qos_map);
  149. skb->priority = cfg80211_classify8021d(skb, qos_map ?
  150. &qos_map->qos_map : NULL);
  151. rcu_read_unlock();
  152. return ieee80211_downgrade_queue(sdata, skb);
  153. }
  154. /**
  155. * ieee80211_set_qos_hdr - Fill in the QoS header if there is one.
  156. *
  157. * @sdata: local subif
  158. * @skb: packet to be updated
  159. */
  160. void ieee80211_set_qos_hdr(struct ieee80211_sub_if_data *sdata,
  161. struct sk_buff *skb)
  162. {
  163. struct ieee80211_hdr *hdr = (void *)skb->data;
  164. struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
  165. u8 *p;
  166. u8 ack_policy, tid;
  167. if (!ieee80211_is_data_qos(hdr->frame_control))
  168. return;
  169. p = ieee80211_get_qos_ctl(hdr);
  170. tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
  171. /* preserve EOSP bit */
  172. ack_policy = *p & IEEE80211_QOS_CTL_EOSP;
  173. if (is_multicast_ether_addr(hdr->addr1) ||
  174. sdata->noack_map & BIT(tid)) {
  175. ack_policy |= IEEE80211_QOS_CTL_ACK_POLICY_NOACK;
  176. info->flags |= IEEE80211_TX_CTL_NO_ACK;
  177. }
  178. /* qos header is 2 bytes */
  179. *p++ = ack_policy | tid;
  180. if (ieee80211_vif_is_mesh(&sdata->vif)) {
  181. /* preserve RSPI and Mesh PS Level bit */
  182. *p &= ((IEEE80211_QOS_CTL_RSPI |
  183. IEEE80211_QOS_CTL_MESH_PS_LEVEL) >> 8);
  184. /* Nulls don't have a mesh header (frame body) */
  185. if (!ieee80211_is_qos_nullfunc(hdr->frame_control))
  186. *p |= (IEEE80211_QOS_CTL_MESH_CONTROL_PRESENT >> 8);
  187. } else {
  188. *p = 0;
  189. }
  190. }