mirror of
git://git.openwrt.org/openwrt/openwrt.git
synced 2024-12-14 19:04:39 +00:00
5eef1e4f29
SVN-Revision: 23971
137 lines
3.4 KiB
Diff
137 lines
3.4 KiB
Diff
--- 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) {
|