madwifi: clean up wme handling, use same packet classification as mac80211
authorFelix Fietkau <nbd@openwrt.org>
Sun, 12 Jul 2009 00:01:17 +0000 (00:01 +0000)
committerFelix Fietkau <nbd@openwrt.org>
Sun, 12 Jul 2009 00:01:17 +0000 (00:01 +0000)
SVN-Revision: 16790

package/madwifi/patches/440-wme_cleanup.patch [new file with mode: 0644]

diff --git a/package/madwifi/patches/440-wme_cleanup.patch b/package/madwifi/patches/440-wme_cleanup.patch
new file mode 100644 (file)
index 0000000..d6c1b26
--- /dev/null
@@ -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) {