From b7ab5771111fdca5166949d2298af5c357979c5a Mon Sep 17 00:00:00 2001 From: Govind Singh Date: Thu, 8 Oct 2015 16:38:37 +0530 Subject: [PATCH] qcacld-3.0: IPv6 packets classification support Enable classification of IPv6 frames based on the traffic class field in the IPv6 header. Change-Id: I4114cb972f61b75da35a225c07f7628d748a744c CRs-Fixed: 921955 --- core/hdd/inc/wlan_hdd_cfg.h | 6 - core/hdd/src/wlan_hdd_cfg.c | 9 -- core/hdd/src/wlan_hdd_wmm.c | 254 +++++++++++++++--------------------- 3 files changed, 102 insertions(+), 167 deletions(-) diff --git a/core/hdd/inc/wlan_hdd_cfg.h b/core/hdd/inc/wlan_hdd_cfg.h index 198a5a0e3675..f25b9131962e 100644 --- a/core/hdd/inc/wlan_hdd_cfg.h +++ b/core/hdd/inc/wlan_hdd_cfg.h @@ -684,11 +684,6 @@ typedef enum { #define CFG_ROAM_SCAN_OFFLOAD_ENABLED_MAX (1) #define CFG_ROAM_SCAN_OFFLOAD_ENABLED_DEFAULT (1) -#define CFG_QOS_WMM_PKT_CLASSIFY_BASIS_NAME "PktClassificationBasis" /* DSCP or 802.1Q */ -#define CFG_QOS_WMM_PKT_CLASSIFY_BASIS_MIN (0) -#define CFG_QOS_WMM_PKT_CLASSIFY_BASIS_MAX (1) -#define CFG_QOS_WMM_PKT_CLASSIFY_BASIS_DEFAULT (0) /* DSCP */ - /* default TSPEC parameters for AC_VO */ #define CFG_QOS_WMM_INFRA_DIR_AC_VO_NAME "InfraDirAcVo" #define CFG_QOS_WMM_INFRA_DIR_AC_VO_MIN (0) @@ -2918,7 +2913,6 @@ struct hdd_config { bool isOkcIniFeatureEnabled; #endif bool isRoamOffloadScanEnabled; - hdd_wmm_classification_t PktClassificationBasis; /* DSCP or 802.1Q */ bool bImplicitQosEnabled; /* default TSPEC parameters for AC_VO */ diff --git a/core/hdd/src/wlan_hdd_cfg.c b/core/hdd/src/wlan_hdd_cfg.c index da08ff7e621e..e31103f60a03 100644 --- a/core/hdd/src/wlan_hdd_cfg.c +++ b/core/hdd/src/wlan_hdd_cfg.c @@ -1095,12 +1095,6 @@ REG_TABLE_ENTRY g_registry_table[] = { CFG_ROAM_SCAN_OFFLOAD_ENABLED_MIN, CFG_ROAM_SCAN_OFFLOAD_ENABLED_MAX, cb_notify_update_roam_scan_offload_enabled, 0), - REG_VARIABLE(CFG_QOS_WMM_PKT_CLASSIFY_BASIS_NAME, WLAN_PARAM_Integer, - struct hdd_config, PktClassificationBasis, - VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, - CFG_QOS_WMM_PKT_CLASSIFY_BASIS_DEFAULT, - CFG_QOS_WMM_PKT_CLASSIFY_BASIS_MIN, - CFG_QOS_WMM_PKT_CLASSIFY_BASIS_MAX), REG_VARIABLE(CFG_QOS_WMM_INFRA_DIR_AC_VO_NAME, WLAN_PARAM_Integer, struct hdd_config, InfraDirAcVo, @@ -4472,9 +4466,6 @@ void hdd_cfg_print(hdd_context_t *pHddCtx) CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, "Name = [UapsdMask] Value = [0x%x] ", pHddCtx->config->UapsdMask); - CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, - "Name = [PktClassificationBasis] Value = [%u] ", - pHddCtx->config->PktClassificationBasis); CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_INFO_HIGH, "Name = [ImplicitQosIsEnabled] Value = [%u]", (int)pHddCtx->config->bImplicitQosEnabled); diff --git a/core/hdd/src/wlan_hdd_wmm.c b/core/hdd/src/wlan_hdd_wmm.c index d25a71849eae..f2699f1ab4e3 100644 --- a/core/hdd/src/wlan_hdd_wmm.c +++ b/core/hdd/src/wlan_hdd_wmm.c @@ -54,6 +54,7 @@ #include #include #include +#include #include #include #include @@ -1548,29 +1549,27 @@ CDF_STATUS hdd_wmm_adapter_close(hdd_adapter_t *pAdapter) /** * hdd_wmm_classify_pkt() - Function which will classify an OS packet - * into a WMM AC based on either 802.1Q or DSCP + * into a WMM AC based on DSCP * - * @pAdapter: [in] adapter upon which the packet is being transmitted - * @skb: [in] the actual OS packet (sk_buff) being transmitted - * @pAcType: [out] WMM AC type of the OS packet - * @pUserPri: [out] User Priority of the OS packet + * @adapter: adapter upon which the packet is being transmitted + * @skb: pointer to network buffer + * @user_pri: user priority of the OS packet + * @is_eapol: eapol packet flag * * Return: None */ static -void hdd_wmm_classify_pkt(hdd_adapter_t *pAdapter, +void hdd_wmm_classify_pkt(hdd_adapter_t *adapter, struct sk_buff *skb, - sme_ac_enum_type *pAcType, - sme_QosWmmUpType *pUserPri, + sme_QosWmmUpType *user_pri, bool *is_eapol) { - unsigned char *pPkt; - union generic_ethhdr *pHdr; - struct iphdr *pIpHdr; - unsigned char tos; unsigned char dscp; - sme_QosWmmUpType userPri; - sme_ac_enum_type acType; + unsigned char tos; + union generic_ethhdr *eth_hdr; + struct iphdr *ip_hdr; + struct ipv6hdr *ipv6hdr; + unsigned char *pkt; /* this code is executed for every packet therefore * all debug code is kept conditional @@ -1581,158 +1580,118 @@ void hdd_wmm_classify_pkt(hdd_adapter_t *pAdapter, "%s: Entered", __func__); #endif /* HDD_WMM_DEBUG */ - pPkt = skb->data; - pHdr = (union generic_ethhdr *)pPkt; + pkt = skb->data; + eth_hdr = (union generic_ethhdr *)pkt; #ifdef HDD_WMM_DEBUG CDF_TRACE(CDF_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW, - "%s: proto/length is 0x%04x", __func__, pHdr->eth_II.h_proto); + "%s: proto is 0x%04x", __func__, skb->protocol); #endif /* HDD_WMM_DEBUG */ - if (HDD_WMM_CLASSIFICATION_DSCP == - (WLAN_HDD_GET_CTX(pAdapter))->config->PktClassificationBasis) { - if (pHdr->eth_II.h_proto == htons(ETH_P_IP)) { - /* case 1: Ethernet II IP packet */ - pIpHdr = (struct iphdr *)&pPkt[sizeof(pHdr->eth_II)]; - tos = pIpHdr->tos; + if (eth_hdr->eth_II.h_proto == htons(ETH_P_IP)) { + /* case 1: Ethernet II IP packet */ + ip_hdr = (struct iphdr *)&pkt[sizeof(eth_hdr->eth_II)]; + tos = ip_hdr->tos; #ifdef HDD_WMM_DEBUG - CDF_TRACE(CDF_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW, - "%s: Ethernet II IP Packet, tos is %d", - __func__, tos); + CDF_TRACE(CDF_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW, + "%s: Ethernet II IP Packet, tos is %d", + __func__, tos); #endif /* HDD_WMM_DEBUG */ - } else if ((ntohs(pHdr->eth_II.h_proto) < WLAN_MIN_PROTO) && - (pHdr->eth_8023.h_snap.dsap == WLAN_SNAP_DSAP) && - (pHdr->eth_8023.h_snap.ssap == WLAN_SNAP_SSAP) && - (pHdr->eth_8023.h_snap.ctrl == WLAN_SNAP_CTRL) && - (pHdr->eth_8023.h_proto == htons(ETH_P_IP))) { - /* case 2: 802.3 LLC/SNAP IP packet */ - pIpHdr = (struct iphdr *)&pPkt[sizeof(pHdr->eth_8023)]; - tos = pIpHdr->tos; + } else if (eth_hdr->eth_II.h_proto == htons(ETH_P_IPV6)) { + ipv6hdr = ipv6_hdr(skb); + tos = ntohs(*(const __be16 *)ipv6hdr) >> 4; #ifdef HDD_WMM_DEBUG - CDF_TRACE(CDF_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW, - "%s: 802.3 LLC/SNAP IP Packet, tos is %d", - __func__, tos); + CDF_TRACE(CDF_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW, + "%s: Ethernet II IPv6 Packet, tos is %d", + __func__, tos); #endif /* HDD_WMM_DEBUG */ - } else if (pHdr->eth_II.h_proto == htons(ETH_P_8021Q)) { - /* VLAN tagged */ + } else if ((ntohs(eth_hdr->eth_II.h_proto) < WLAN_MIN_PROTO) && + (eth_hdr->eth_8023.h_snap.dsap == WLAN_SNAP_DSAP) && + (eth_hdr->eth_8023.h_snap.ssap == WLAN_SNAP_SSAP) && + (eth_hdr->eth_8023.h_snap.ctrl == WLAN_SNAP_CTRL) && + (eth_hdr->eth_8023.h_proto == htons(ETH_P_IP))) { + /* case 2: 802.3 LLC/SNAP IP packet */ + ip_hdr = (struct iphdr *)&pkt[sizeof(eth_hdr->eth_8023)]; + tos = ip_hdr->tos; +#ifdef HDD_WMM_DEBUG + CDF_TRACE(CDF_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO_LOW, + "%s: 802.3 LLC/SNAP IP Packet, tos is %d", + __func__, tos); +#endif /* HDD_WMM_DEBUG */ + } else if (eth_hdr->eth_II.h_proto == htons(ETH_P_8021Q)) { + /* VLAN tagged */ - if (pHdr->eth_IIv.h_vlan_encapsulated_proto == - htons(ETH_P_IP)) { - /* case 3: Ethernet II vlan-tagged IP packet */ - pIpHdr = - (struct iphdr *) - &pPkt[sizeof(pHdr->eth_IIv)]; - tos = pIpHdr->tos; + if (eth_hdr->eth_IIv.h_vlan_encapsulated_proto == + htons(ETH_P_IP)) { + /* case 3: Ethernet II vlan-tagged IP packet */ + ip_hdr = + (struct iphdr *) + &pkt[sizeof(eth_hdr->eth_IIv)]; + tos = ip_hdr->tos; #ifdef HDD_WMM_DEBUG - CDF_TRACE(CDF_MODULE_ID_HDD, - WMM_TRACE_LEVEL_INFO_LOW, - "%s: Ethernet II VLAN tagged IP Packet, tos is %d", - __func__, tos); + CDF_TRACE(CDF_MODULE_ID_HDD, + WMM_TRACE_LEVEL_INFO_LOW, + "%s: Ethernet II VLAN tagged IP Packet, tos is %d", + __func__, tos); #endif /* HDD_WMM_DEBUG */ - } else - if ((ntohs(pHdr->eth_IIv.h_vlan_encapsulated_proto) - < WLAN_MIN_PROTO) - && (pHdr->eth_8023v.h_snap.dsap == - WLAN_SNAP_DSAP) - && (pHdr->eth_8023v.h_snap.ssap == - WLAN_SNAP_SSAP) - && (pHdr->eth_8023v.h_snap.ctrl == - WLAN_SNAP_CTRL) - && (pHdr->eth_8023v.h_proto == - htons(ETH_P_IP))) { - /* case 4: 802.3 LLC/SNAP vlan-tagged IP packet */ - pIpHdr = - (struct iphdr *) - &pPkt[sizeof(pHdr->eth_8023v)]; - tos = pIpHdr->tos; + } else + if ((ntohs(eth_hdr->eth_IIv.h_vlan_encapsulated_proto) + < WLAN_MIN_PROTO) + && (eth_hdr->eth_8023v.h_snap.dsap == + WLAN_SNAP_DSAP) + && (eth_hdr->eth_8023v.h_snap.ssap == + WLAN_SNAP_SSAP) + && (eth_hdr->eth_8023v.h_snap.ctrl == + WLAN_SNAP_CTRL) + && (eth_hdr->eth_8023v.h_proto == + htons(ETH_P_IP))) { + /* case 4: 802.3 LLC/SNAP vlan-tagged IP packet */ + ip_hdr = + (struct iphdr *) + &pkt[sizeof(eth_hdr->eth_8023v)]; + tos = ip_hdr->tos; #ifdef HDD_WMM_DEBUG - CDF_TRACE(CDF_MODULE_ID_HDD, - WMM_TRACE_LEVEL_INFO_LOW, - "%s: 802.3 LLC/SNAP VLAN tagged IP Packet, tos is %d", - __func__, tos); + CDF_TRACE(CDF_MODULE_ID_HDD, + WMM_TRACE_LEVEL_INFO_LOW, + "%s: 802.3 LLC/SNAP VLAN tagged IP Packet, tos is %d", + __func__, tos); #endif /* HDD_WMM_DEBUG */ - } else { - /* default */ -#ifdef HDD_WMM_DEBUG - CDF_TRACE(CDF_MODULE_ID_HDD, - WMM_TRACE_LEVEL_WARN, - "%s: VLAN tagged Unhandled Protocol, using default tos", - __func__); -#endif /* HDD_WMM_DEBUG */ - tos = 0; - } } else { /* default */ #ifdef HDD_WMM_DEBUG - CDF_TRACE(CDF_MODULE_ID_HDD, WMM_TRACE_LEVEL_WARN, - "%s: Unhandled Protocol, using default tos", - __func__); + CDF_TRACE(CDF_MODULE_ID_HDD, + WMM_TRACE_LEVEL_WARN, + "%s: VLAN tagged Unhandled Protocol, using default tos", + __func__); #endif /* HDD_WMM_DEBUG */ - /* Give the highest priority to 802.1x packet */ - if (pHdr->eth_II.h_proto == - htons(HDD_ETHERTYPE_802_1_X)) { - tos = 0xC0; - *is_eapol = true; - } else - tos = 0; - } - - dscp = (tos >> 2) & 0x3f; - userPri = pAdapter->hddWmmDscpToUpMap[dscp]; - -#ifdef HDD_WMM_DEBUG - CDF_TRACE(CDF_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO, - "%s: tos is %d, dscp is %d, up is %d", - __func__, tos, dscp, userPri); -#endif /* HDD_WMM_DEBUG */ - - } else if (HDD_WMM_CLASSIFICATION_802_1Q == - (WLAN_HDD_GET_CTX(pAdapter))->config-> - PktClassificationBasis) { - if (pHdr->eth_IIv.h_vlan_proto == htons(ETH_P_8021Q)) { - /* VLAN tagged */ - userPri = (ntohs(pHdr->eth_IIv.h_vlan_TCI) >> 13) & 0x7; -#ifdef HDD_WMM_DEBUG - CDF_TRACE(CDF_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO, - "%s: Tagged frame, UP is %d", - __func__, userPri); -#endif /* HDD_WMM_DEBUG */ - } else { - /* not VLAN tagged, use default */ -#ifdef HDD_WMM_DEBUG - CDF_TRACE(CDF_MODULE_ID_HDD, WMM_TRACE_LEVEL_WARN, - "%s: Untagged frame, using default UP", - __func__); -#endif /* HDD_WMM_DEBUG */ - /* Give the highest priority to 802.1x packet */ - if (pHdr->eth_II.h_proto == - htons(HDD_ETHERTYPE_802_1_X)) { - userPri = SME_QOS_WMM_UP_VO; - *is_eapol = true; - } else - userPri = SME_QOS_WMM_UP_BE; + tos = 0; } } else { /* default */ #ifdef HDD_WMM_DEBUG - CDF_TRACE(CDF_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR, - "%s: Unknown classification scheme, using default UP", - __func__); + CDF_TRACE(CDF_MODULE_ID_HDD, WMM_TRACE_LEVEL_WARN, + "%s: Unhandled Protocol, using default tos", + __func__); #endif /* HDD_WMM_DEBUG */ - userPri = SME_QOS_WMM_UP_BE; + /* Give the highest priority to 802.1x packet */ + if (eth_hdr->eth_II.h_proto == + htons(HDD_ETHERTYPE_802_1_X)) { + tos = 0xC0; + *is_eapol = true; + } else + tos = 0; } - acType = hdd_wmm_up_to_ac_map[userPri]; + dscp = (tos >> 2) & 0x3f; + *user_pri = adapter->hddWmmDscpToUpMap[dscp]; #ifdef HDD_WMM_DEBUG CDF_TRACE(CDF_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO, - "%s: UP is %d, AC is %d", __func__, userPri, acType); + "%s: tos is %d, dscp is %d, up is %d", + __func__, tos, dscp, *user_pri); #endif /* HDD_WMM_DEBUG */ - *pUserPri = userPri; - *pAcType = acType; - return; } @@ -1780,25 +1739,21 @@ uint16_t hdd_hostapd_select_queue(struct net_device *dev, struct sk_buff *skb ) { - sme_ac_enum_type ac; sme_QosWmmUpType up = SME_QOS_WMM_UP_BE; uint16_t queueIndex; - hdd_adapter_t *pAdapter = (hdd_adapter_t *) netdev_priv(dev); - hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + hdd_adapter_t *adapter = (hdd_adapter_t *) netdev_priv(dev); + hdd_context_t *hddctx = WLAN_HDD_GET_CTX(adapter); bool is_eapol = false; int status = 0; - status = wlan_hdd_validate_context(pHddCtx); + status = wlan_hdd_validate_context(hddctx); if (status != 0) { skb->priority = SME_QOS_WMM_UP_BE; return HDD_LINUX_AC_BE; } - if (HDD_WMM_USER_MODE_NO_QOS != pHddCtx->config->WmmMode) { - /* Get the user priority from IP header & corresponding AC */ - hdd_wmm_classify_pkt(pAdapter, skb, &ac, &up, &is_eapol); - } - + /* Get the user priority from IP header */ + hdd_wmm_classify_pkt(adapter, skb, &up, &is_eapol); skb->priority = up; queueIndex = hdd_get_queue_index(skb->priority, is_eapol); @@ -1816,7 +1771,6 @@ uint16_t hdd_hostapd_select_queue(struct net_device *dev, struct sk_buff *skb */ uint16_t hdd_wmm_select_queue(struct net_device *dev, struct sk_buff *skb) { - sme_ac_enum_type ac; sme_QosWmmUpType up = SME_QOS_WMM_UP_BE; uint16_t queueIndex; hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); @@ -1830,15 +1784,11 @@ uint16_t hdd_wmm_select_queue(struct net_device *dev, struct sk_buff *skb) return HDD_LINUX_AC_BE; } - /* if we don't want QoS or the AP doesn't support Qos */ - /* All traffic will get equal opportuniy to transmit data frames. */ - if (hdd_wmm_is_active(pAdapter)) { - /* Get the user priority from IP header & corresponding AC */ - hdd_wmm_classify_pkt(pAdapter, skb, &ac, &up, &is_eapol); - } - + /* Get the user priority from IP header */ + hdd_wmm_classify_pkt(pAdapter, skb, &up, &is_eapol); skb->priority = up; queueIndex = hdd_get_queue_index(skb->priority, is_eapol); + return queueIndex; }