mirror of
				git://git.openwrt.org/openwrt/openwrt.git
				synced 2025-10-30 13:34:27 -04:00 
			
		
		
		
	
		
			
				
	
	
		
			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) {
 |