aboutsummaryrefslogtreecommitdiffstats
path: root/package/madwifi/patches/440-wme_cleanup.patch
diff options
context:
space:
mode:
Diffstat (limited to 'package/madwifi/patches/440-wme_cleanup.patch')
-rw-r--r--package/madwifi/patches/440-wme_cleanup.patch136
1 files changed, 136 insertions, 0 deletions
diff --git a/package/madwifi/patches/440-wme_cleanup.patch b/package/madwifi/patches/440-wme_cleanup.patch
new file mode 100644
index 000000000..bb81ac7f8
--- /dev/null
+++ b/package/madwifi/patches/440-wme_cleanup.patch
@@ -0,0 +1,136 @@
+--- a/net80211/ieee80211_output.c
++++ b/net80211/ieee80211_output.c
+@@ -73,6 +73,29 @@ doprint(struct ieee80211vap *vap, int su
+ }
+ #endif
+
++static const int ieee802_1d_to_ac[8] = {
++ WME_AC_BE, WME_AC_BK, WME_AC_BK, WME_AC_BE,
++ WME_AC_VI, WME_AC_VI, WME_AC_VO, WME_AC_VO
++};
++
++/* Given a data frame determine the 802.1p/1d tag to use. */
++static unsigned int ieee80211_classify_ip(struct sk_buff *skb)
++{
++ const struct ether_header *eh = (struct ether_header *) skb->data;
++ const struct iphdr *ip = (struct iphdr *)
++ (skb->data + sizeof (struct ether_header));
++ unsigned int dscp;
++
++ switch (skb->protocol) {
++ case __constant_htons(ETH_P_IP):
++ dscp = ip->tos & 0xfc;
++ break;
++ default:
++ return 0;
++ }
++
++ return dscp >> 5;
++}
+
+ /*
+ * Determine the priority based on VLAN and/or IP TOS. Priority is
+@@ -83,90 +106,24 @@ static int
+ ieee80211_classify(struct ieee80211_node *ni, struct sk_buff *skb)
+ {
+ struct ieee80211vap *vap = ni->ni_vap;
+- struct ether_header *eh = (struct ether_header *) skb->data;
+- int v_wme_ac = 0, d_wme_ac = 0;
+
+- /* default priority */
+- skb->priority = WME_AC_BE;
+-
+- if (!(ni->ni_flags & IEEE80211_NODE_QOS))
+- return 0;
+-
+- /*
+- * If node has a vlan tag then all traffic
+- * to it must have a matching vlan id.
++ /* skb->priority values from 256->263 are magic values to
++ * directly indicate a specific 802.1d priority. This is used
++ * to allow 802.1d priority to be passed directly in from VLAN
++ * tags, etc.
+ */
+- if (ni->ni_vlan != 0 && vlan_tx_tag_present(skb)) {
+- u_int32_t tag=0;
+- int v_pri;
+-
+- if (vap->iv_vlgrp == NULL) {
+- IEEE80211_NODE_STAT(ni, tx_novlantag);
+- ni->ni_stats.ns_tx_novlantag++;
+- return 1;
+- }
+- if (((tag = vlan_tx_tag_get(skb)) & VLAN_VID_MASK) !=
+- (ni->ni_vlan & VLAN_VID_MASK)) {
+- IEEE80211_NODE_STAT(ni, tx_vlanmismatch);
+- ni->ni_stats.ns_tx_vlanmismatch++;
+- return 1;
+- }
+- if (ni->ni_flags & IEEE80211_NODE_QOS) {
+- v_pri = (tag >> VLAN_PRI_SHIFT) & VLAN_PRI_MASK;
+- switch (v_pri) {
+- case 1:
+- case 2: /* Background (BK) */
+- v_wme_ac = WME_AC_BK;
+- break;
+- case 0:
+- case 3: /* Best Effort (BE) */
+- v_wme_ac = WME_AC_BE;
+- break;
+- case 4:
+- case 5: /* Video (VI) */
+- v_wme_ac = WME_AC_VI;
+- break;
+- case 6:
+- case 7: /* Voice (VO) */
+- v_wme_ac = WME_AC_VO;
+- break;
+- }
+- }
++ if (skb->priority >= 256 && skb->priority <= 263) {
++ skb->priority = ieee802_1d_to_ac[skb->priority - 256];
++ return 0;
+ }
+
+- if (eh->ether_type == __constant_htons(ETHERTYPE_IP)) {
+- const struct iphdr *ip = (struct iphdr *)
+- (skb->data + sizeof (struct ether_header));
+- /*
+- * IP frame, map the TOS field.
+- *
+- * XXX: fill out these mappings???
+- */
+- switch (ip->tos) {
+- case 0x08: /* Background */
+- case 0x20:
+- d_wme_ac = WME_AC_BK;
+- break;
+- case 0x28: /* Video */
+- case 0xa0:
+- d_wme_ac = WME_AC_VI;
+- break;
+- case 0x30: /* Voice */
+- case 0xe0:
+- case 0x88: /* XXX UPSD */
+- case 0xb8:
+- d_wme_ac = WME_AC_VO;
+- break;
+- default: /* All others */
+- d_wme_ac = WME_AC_BE;
+- break;
+- }
+- } else {
+- d_wme_ac = WME_AC_BE;
++ if (!(ni->ni_flags & IEEE80211_NODE_QOS)) {
++ /* default priority */
++ skb->priority = WME_AC_BE;
++ return 0;
+ }
+- skb->priority = d_wme_ac;
+- if (v_wme_ac > d_wme_ac)
+- skb->priority = v_wme_ac;
++
++ skb->priority = ieee802_1d_to_ac[ieee80211_classify_ip(skb)];
+
+ /* Applying ACM policy */
+ if (vap->iv_opmode == IEEE80211_M_STA) {