320-v4.17-mac80211-support-A-MSDU-in-fast-rx.patch 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. From: Felix Fietkau <[email protected]>
  2. Date: Mon, 26 Feb 2018 22:09:29 +0100
  3. Subject: [PATCH] mac80211: support A-MSDU in fast-rx
  4. Only works if the IV was stripped from packets. Create a smaller
  5. variant of ieee80211_rx_h_amsdu, which bypasses checks already done
  6. within the fast-rx context.
  7. Signed-off-by: Felix Fietkau <[email protected]>
  8. ---
  9. --- a/net/mac80211/rx.c
  10. +++ b/net/mac80211/rx.c
  11. @@ -2358,39 +2358,17 @@ ieee80211_deliver_skb(struct ieee80211_r
  12. }
  13. static ieee80211_rx_result debug_noinline
  14. -ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx)
  15. +__ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx, u8 data_offset)
  16. {
  17. struct net_device *dev = rx->sdata->dev;
  18. struct sk_buff *skb = rx->skb;
  19. struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
  20. __le16 fc = hdr->frame_control;
  21. struct sk_buff_head frame_list;
  22. - struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
  23. struct ethhdr ethhdr;
  24. const u8 *check_da = ethhdr.h_dest, *check_sa = ethhdr.h_source;
  25. - if (unlikely(!ieee80211_is_data(fc)))
  26. - return RX_CONTINUE;
  27. -
  28. - if (unlikely(!ieee80211_is_data_present(fc)))
  29. - return RX_DROP_MONITOR;
  30. -
  31. - if (!(status->rx_flags & IEEE80211_RX_AMSDU))
  32. - return RX_CONTINUE;
  33. -
  34. if (unlikely(ieee80211_has_a4(hdr->frame_control))) {
  35. - switch (rx->sdata->vif.type) {
  36. - case NL80211_IFTYPE_AP_VLAN:
  37. - if (!rx->sdata->u.vlan.sta)
  38. - return RX_DROP_UNUSABLE;
  39. - break;
  40. - case NL80211_IFTYPE_STATION:
  41. - if (!rx->sdata->u.mgd.use_4addr)
  42. - return RX_DROP_UNUSABLE;
  43. - break;
  44. - default:
  45. - return RX_DROP_UNUSABLE;
  46. - }
  47. check_da = NULL;
  48. check_sa = NULL;
  49. } else switch (rx->sdata->vif.type) {
  50. @@ -2410,15 +2388,13 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx
  51. break;
  52. }
  53. - if (is_multicast_ether_addr(hdr->addr1))
  54. - return RX_DROP_UNUSABLE;
  55. -
  56. skb->dev = dev;
  57. __skb_queue_head_init(&frame_list);
  58. if (ieee80211_data_to_8023_exthdr(skb, &ethhdr,
  59. rx->sdata->vif.addr,
  60. - rx->sdata->vif.type))
  61. + rx->sdata->vif.type,
  62. + data_offset))
  63. return RX_DROP_UNUSABLE;
  64. ieee80211_amsdu_to_8023s(skb, &frame_list, dev->dev_addr,
  65. @@ -2440,6 +2416,44 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx
  66. return RX_QUEUED;
  67. }
  68. +static ieee80211_rx_result debug_noinline
  69. +ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx)
  70. +{
  71. + struct sk_buff *skb = rx->skb;
  72. + struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
  73. + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
  74. + __le16 fc = hdr->frame_control;
  75. +
  76. + if (!(status->rx_flags & IEEE80211_RX_AMSDU))
  77. + return RX_CONTINUE;
  78. +
  79. + if (unlikely(!ieee80211_is_data(fc)))
  80. + return RX_CONTINUE;
  81. +
  82. + if (unlikely(!ieee80211_is_data_present(fc)))
  83. + return RX_DROP_MONITOR;
  84. +
  85. + if (unlikely(ieee80211_has_a4(hdr->frame_control))) {
  86. + switch (rx->sdata->vif.type) {
  87. + case NL80211_IFTYPE_AP_VLAN:
  88. + if (!rx->sdata->u.vlan.sta)
  89. + return RX_DROP_UNUSABLE;
  90. + break;
  91. + case NL80211_IFTYPE_STATION:
  92. + if (!rx->sdata->u.mgd.use_4addr)
  93. + return RX_DROP_UNUSABLE;
  94. + break;
  95. + default:
  96. + return RX_DROP_UNUSABLE;
  97. + }
  98. + }
  99. +
  100. + if (is_multicast_ether_addr(hdr->addr1))
  101. + return RX_DROP_UNUSABLE;
  102. +
  103. + return __ieee80211_rx_h_amsdu(rx, 0);
  104. +}
  105. +
  106. #ifdef CPTCFG_MAC80211_MESH
  107. static ieee80211_rx_result
  108. ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
  109. @@ -3889,7 +3903,8 @@ static bool ieee80211_invoke_fast_rx(str
  110. struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
  111. struct sta_info *sta = rx->sta;
  112. int orig_len = skb->len;
  113. - int snap_offs = ieee80211_hdrlen(hdr->frame_control);
  114. + int hdrlen = ieee80211_hdrlen(hdr->frame_control);
  115. + int snap_offs = hdrlen;
  116. struct {
  117. u8 snap[sizeof(rfc1042_header)];
  118. __be16 proto;
  119. @@ -3920,10 +3935,6 @@ static bool ieee80211_invoke_fast_rx(str
  120. (status->flag & FAST_RX_CRYPT_FLAGS) != FAST_RX_CRYPT_FLAGS)
  121. return false;
  122. - /* we don't deal with A-MSDU deaggregation here */
  123. - if (status->rx_flags & IEEE80211_RX_AMSDU)
  124. - return false;
  125. -
  126. if (unlikely(!ieee80211_is_data_present(hdr->frame_control)))
  127. return false;
  128. @@ -3955,21 +3966,24 @@ static bool ieee80211_invoke_fast_rx(str
  129. snap_offs += IEEE80211_CCMP_HDR_LEN;
  130. }
  131. - if (!pskb_may_pull(skb, snap_offs + sizeof(*payload)))
  132. - goto drop;
  133. - payload = (void *)(skb->data + snap_offs);
  134. + if (!(status->rx_flags & IEEE80211_RX_AMSDU)) {
  135. + if (!pskb_may_pull(skb, snap_offs + sizeof(*payload)))
  136. + goto drop;
  137. - if (!ether_addr_equal(payload->snap, fast_rx->rfc1042_hdr))
  138. - return false;
  139. + payload = (void *)(skb->data + snap_offs);
  140. - /* Don't handle these here since they require special code.
  141. - * Accept AARP and IPX even though they should come with a
  142. - * bridge-tunnel header - but if we get them this way then
  143. - * there's little point in discarding them.
  144. - */
  145. - if (unlikely(payload->proto == cpu_to_be16(ETH_P_TDLS) ||
  146. - payload->proto == fast_rx->control_port_protocol))
  147. - return false;
  148. + if (!ether_addr_equal(payload->snap, fast_rx->rfc1042_hdr))
  149. + return false;
  150. +
  151. + /* Don't handle these here since they require special code.
  152. + * Accept AARP and IPX even though they should come with a
  153. + * bridge-tunnel header - but if we get them this way then
  154. + * there's little point in discarding them.
  155. + */
  156. + if (unlikely(payload->proto == cpu_to_be16(ETH_P_TDLS) ||
  157. + payload->proto == fast_rx->control_port_protocol))
  158. + return false;
  159. + }
  160. /* after this point, don't punt to the slowpath! */
  161. @@ -3983,12 +3997,6 @@ static bool ieee80211_invoke_fast_rx(str
  162. }
  163. /* statistics part of ieee80211_rx_h_sta_process() */
  164. - stats->last_rx = jiffies;
  165. - stats->last_rate = sta_stats_encode_rate(status);
  166. -
  167. - stats->fragments++;
  168. - stats->packets++;
  169. -
  170. if (!(status->flag & RX_FLAG_NO_SIGNAL_VAL)) {
  171. stats->last_signal = status->signal;
  172. if (!fast_rx->uses_rss)
  173. @@ -4017,6 +4025,20 @@ static bool ieee80211_invoke_fast_rx(str
  174. if (rx->key && !ieee80211_has_protected(hdr->frame_control))
  175. goto drop;
  176. + if (status->rx_flags & IEEE80211_RX_AMSDU) {
  177. + if (__ieee80211_rx_h_amsdu(rx, snap_offs - hdrlen) !=
  178. + RX_QUEUED)
  179. + goto drop;
  180. +
  181. + return true;
  182. + }
  183. +
  184. + stats->last_rx = jiffies;
  185. + stats->last_rate = sta_stats_encode_rate(status);
  186. +
  187. + stats->fragments++;
  188. + stats->packets++;
  189. +
  190. /* do the header conversion - first grab the addresses */
  191. ether_addr_copy(addrs.da, skb->data + fast_rx->da_offs);
  192. ether_addr_copy(addrs.sa, skb->data + fast_rx->sa_offs);
  193. --- a/include/net/cfg80211.h
  194. +++ b/include/net/cfg80211.h
  195. @@ -4331,10 +4331,12 @@ unsigned int ieee80211_get_mesh_hdrlen(s
  196. * of it being pushed into the SKB
  197. * @addr: the device MAC address
  198. * @iftype: the virtual interface type
  199. + * @data_offset: offset of payload after the 802.11 header
  200. * Return: 0 on success. Non-zero on error.
  201. */
  202. int ieee80211_data_to_8023_exthdr(struct sk_buff *skb, struct ethhdr *ehdr,
  203. - const u8 *addr, enum nl80211_iftype iftype);
  204. + const u8 *addr, enum nl80211_iftype iftype,
  205. + u8 data_offset);
  206. /**
  207. * ieee80211_data_to_8023 - convert an 802.11 data frame to 802.3
  208. @@ -4346,7 +4348,7 @@ int ieee80211_data_to_8023_exthdr(struct
  209. static inline int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
  210. enum nl80211_iftype iftype)
  211. {
  212. - return ieee80211_data_to_8023_exthdr(skb, NULL, addr, iftype);
  213. + return ieee80211_data_to_8023_exthdr(skb, NULL, addr, iftype, 0);
  214. }
  215. /**
  216. --- a/net/wireless/util.c
  217. +++ b/net/wireless/util.c
  218. @@ -419,7 +419,8 @@ unsigned int ieee80211_get_mesh_hdrlen(s
  219. EXPORT_SYMBOL(ieee80211_get_mesh_hdrlen);
  220. int ieee80211_data_to_8023_exthdr(struct sk_buff *skb, struct ethhdr *ehdr,
  221. - const u8 *addr, enum nl80211_iftype iftype)
  222. + const u8 *addr, enum nl80211_iftype iftype,
  223. + u8 data_offset)
  224. {
  225. struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
  226. struct {
  227. @@ -433,7 +434,7 @@ int ieee80211_data_to_8023_exthdr(struct
  228. if (unlikely(!ieee80211_is_data_present(hdr->frame_control)))
  229. return -1;
  230. - hdrlen = ieee80211_hdrlen(hdr->frame_control);
  231. + hdrlen = ieee80211_hdrlen(hdr->frame_control) + data_offset;
  232. if (skb->len < hdrlen + 8)
  233. return -1;