Example #1
0
void ath_ald_update_frame_stats(struct ath_softc *sc, struct ath_buf *bf, struct ath_tx_status *ts)
{
    struct ieee80211_frame *wh;
    int type;
    int bfUsed = 0;
    u_int32_t ptime = 0;
    u_int32_t airtime = 0;
    int i;
    void *ds = bf->bf_lastbf->bf_desc;

    wh = (struct ieee80211_frame *)wbuf_header(bf->bf_mpdu);
    type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
    if((type == IEEE80211_FC0_TYPE_DATA) &&
        (!IEEE80211_IS_MULTICAST(wh->i_addr1)) &&
        (!IEEE80211_IS_BROADCAST(wh->i_addr1))){
        for(i=0; i < HAL_NUM_TX_QUEUES; i++) {
            if (ATH_TXQ_SETUP(sc, i)) {
                bfUsed += sc->sc_txq[i].axq_num_buf_used;
            }
        }
        ptime = sc->sc_ald.sc_ald_txairtime;
        airtime = ath_hal_txcalcairtime(sc->sc_ah, ds, ts, AH_FALSE, 1, 1);
        sc->sc_ald.sc_ald_txairtime += airtime;
        if (ptime > sc->sc_ald.sc_ald_txairtime) {
            sc->sc_ald.sc_ald_txairtime = airtime;
            sc->sc_ald.sc_ald_pktnum = 0;
        }
        if (airtime) {
            sc->sc_ald.sc_ald_pktlen += (bf->bf_isaggr ? bf->bf_al : bf->bf_frmlen);
            sc->sc_ald.sc_ald_pktnum += bf->bf_nframes;
            sc->sc_ald.sc_ald_bfused += bfUsed;
            sc->sc_ald.sc_ald_counter += 1;
        }
    }
}
Example #2
0
void android_ar6k_check_wow_status(AR_SOFTC_T *ar, struct sk_buff *skb, A_BOOL isEvent)
{
#ifdef CONFIG_HAS_WAKELOCK
    unsigned long wake_timeout = HZ; /* 1 second for normal window's ping test */
#endif
    AR_SOFTC_DEV_T *arPriv;
    A_UINT8  i; 
    A_BOOL needWake = FALSE;
    for(i = 0; i < num_device; i++) 
    {
        arPriv = ar->arDev[i];
        if (
#ifdef CONFIG_HAS_EARLYSUSPEND
            screen_is_off && 
#endif
                skb && arPriv->arConnected) {
            if (isEvent) {
                if (A_NETBUF_LEN(skb) >= sizeof(A_UINT16)) {
                    A_UINT16 cmd = *(const A_UINT16 *)A_NETBUF_DATA(skb);
                    switch (cmd) {
                    case WMI_CONNECT_EVENTID:
#ifdef CONFIG_HAS_WAKELOCK
                         wake_timeout = 3*HZ;
#endif
                         needWake = TRUE;
                         break;
                    default:
                        /* dont wake lock the system for other event */
                         break;
                    }
                }
            } else if (A_NETBUF_LEN(skb) >= sizeof(ATH_MAC_HDR)) {
                ATH_MAC_HDR *datap = (ATH_MAC_HDR *)A_NETBUF_DATA(skb);
                if (!IEEE80211_IS_MULTICAST(datap->dstMac)) {
                    switch (A_BE2CPU16(datap->typeOrLen)) {
                    case 0x0800: /* IP */
                        if (A_NETBUF_LEN(skb)>=24 &&
                            *((A_UCHAR*)A_NETBUF_DATA(skb)+23)==0x11) {
                            A_UCHAR *udpPkt = (A_UCHAR*)A_NETBUF_DATA(skb)+14;
                            A_UINT8 ihl = (*udpPkt & 0x0f) * sizeof(A_UINT32);
                            const A_UCHAR ipsec_keepalive[] = { 
                                0x11, 0x94, 0x11, 0x94, 0x00, 0x09, 0x00, 0x00, 0xff
                            };
                            udpPkt += ihl;
                            if (A_NETBUF_LEN(skb)>=14+ihl+sizeof(ipsec_keepalive) &&
                                    !memcmp(udpPkt, ipsec_keepalive, sizeof(ipsec_keepalive)-3) &&
                                    udpPkt[8]==0xff) {
                                /* 
                                 * RFC 3948 UDP Encapsulation of IPsec ESP Packets
                                 * Source and Destination port must be 4500
                                 * Receivers MUST NOT depend upon the UDP checksum being zero 
                                 * Sender must use 1 byte payload with 0xff
                                 * Receiver SHOULD ignore a received NAT-keepalive packet
                                 *
                                 * IPSec over UDP NAT keepalive packet. Just ignore
                                 */
                                break;
                            }
                        }
                    case 0x888e: /* EAPOL */
                    case 0x88c7: /* RSN_PREAUTH */
                    case 0x88b4: /* WAPI */
                         needWake = TRUE;
                         break;
                    case 0x0806: /* ARP is not important to hold wake lock */
                        needWake = (arPriv->arNetworkType==AP_NETWORK);
                        break;
                    default:
                         break;
                    }
                } else if ( !IEEE80211_IS_BROADCAST(datap->dstMac) ) {
                    if (A_NETBUF_LEN(skb)>=14+20 ) {
					    /* check if it is mDNS packets */
                        A_UINT8 *dstIpAddr = (A_UINT8*)(A_NETBUF_DATA(skb)+14+20-4);                    
                        struct net_device *ndev = arPriv->arNetDev;
                        needWake = ((dstIpAddr[3] & 0xf8) == 0xf8) &&
                                (arPriv->arNetworkType==AP_NETWORK || 
                                (ndev->flags & IFF_ALLMULTI || ndev->flags & IFF_MULTICAST));
                    }
                }else if (arPriv->arNetworkType==AP_NETWORK) {
                    switch (A_BE2CPU16(datap->typeOrLen)) {
                    case 0x0800: /* IP */
                        if (A_NETBUF_LEN(skb)>=14+20+2) {
                            A_UINT16 dstPort = *(A_UINT16*)(A_NETBUF_DATA(skb)+14+20);
                            dstPort = A_BE2CPU16(dstPort);
                            needWake = (dstPort == 0x43); /* dhcp request */
                        }
                        break;
                    case 0x0806: 
                        needWake = TRUE;
                    default:
                        break;
                    }
                }
             }
         }
    }
    if (needWake) {
#ifdef CONFIG_HAS_WAKELOCK
        /* keep host wake up if there is any event and packate comming in*/
        wake_lock_timeout(&ar6k_wow_wake_lock, wake_timeout);
#endif
        if (wowledon) {
            char buf[32];
            int len = sprintf(buf, "on");
            android_readwrite_file("/sys/power/state", NULL, buf, len);

            len = sprintf(buf, "%d", 127);
            android_readwrite_file("/sys/class/leds/lcd-backlight/brightness",
                                   NULL, buf,len);
        }
    }
}
void android_ar6k_check_wow_status(AR_SOFTC_T *ar, struct sk_buff *skb, A_BOOL isEvent)
{
    AR_SOFTC_DEV_T *arPriv;
    A_UINT8  i; 
    A_BOOL needWake = FALSE;
    for(i = 0; i < num_device; i++) 
    {
        arPriv = ar->arDev[i];
        if (
#ifdef CONFIG_HAS_EARLYSUSPEND
            screen_is_off && 
#endif
                skb && arPriv->arConnected) {
            if (isEvent) {
                if (A_NETBUF_LEN(skb) >= sizeof(A_UINT16)) {
                    A_UINT16 cmd = *(const A_UINT16 *)A_NETBUF_DATA(skb);
                    switch (cmd) {
                    case WMI_CONNECT_EVENTID:
                    case WMI_DISCONNECT_EVENTID:
                         needWake = TRUE;
                         break;
                    default:
                        /* dont wake lock the system for other event */
                         break;
                    }
                }
            } else if (A_NETBUF_LEN(skb) >= sizeof(ATH_MAC_HDR)) {
                ATH_MAC_HDR *datap = (ATH_MAC_HDR *)A_NETBUF_DATA(skb);
                if (!IEEE80211_IS_MULTICAST(datap->dstMac)) {
                    switch (A_BE2CPU16(datap->typeOrLen)) {
                    case 0x0800: /* IP */
                    case 0x888e: /* EAPOL */
                    case 0x88c7: /* RSN_PREAUTH */
                    case 0x88b4: /* WAPI */
                         needWake = TRUE;
                         break;
                    case 0x0806: /* ARP is not important to hold wake lock */
                        needWake = (arPriv->arNetworkType==AP_NETWORK);
                        break;
                    default:
                         break;
                    }
                } else if ( !IEEE80211_IS_BROADCAST(datap->dstMac) ) {
                    if (A_NETBUF_LEN(skb)>=14+20 ) {
					    /* check if it is mDNS packets */
                        A_UINT8 *dstIpAddr = (A_UINT8*)(A_NETBUF_DATA(skb)+14+20-4);                    
                        struct net_device *ndev = arPriv->arNetDev;
                        needWake = ((dstIpAddr[3] & 0xf8) == 0xf8) &&
                                (arPriv->arNetworkType==AP_NETWORK || 
                                (ndev->flags & IFF_ALLMULTI || ndev->flags & IFF_MULTICAST));
                    }
                }else if (arPriv->arNetworkType==AP_NETWORK) {
                    switch (A_BE2CPU16(datap->typeOrLen)) {
                    case 0x0800: /* IP */
                        if (A_NETBUF_LEN(skb)>=14+20+2) {
                            A_UINT16 dstPort = *(A_UINT16*)(A_NETBUF_DATA(skb)+14+20);
                            dstPort = A_BE2CPU16(dstPort);
                            needWake = (dstPort == 0x43); /* dhcp request */
                        }
                        break;
                    case 0x0806: 
                        needWake = TRUE;
                    default:
                        break;
                    }
                }
             }
         }
    }
    if (needWake) {
#ifdef CONFIG_HAS_WAKELOCK
        /* keep host wake up if there is any event and packate comming in*/
        wake_lock_timeout(&ar6k_wow_wake_lock, 3*HZ);
#endif
        if (wowledon) {
            char buf[32];
            int len = sprintf(buf, "on");
            android_readwrite_file("/sys/power/state", NULL, buf, len);

            len = sprintf(buf, "%d", 127);
            android_readwrite_file("/sys/class/leds/lcd-backlight/brightness",
                                   NULL, buf,len);
        }
    }
}
Example #4
0
 /*
  * processes data frames.
  * ieee80211_wow_magic_parser parses the wbuf to check if match magic packet.
  */
void 
ieee80211_wow_magic_parser(struct ieee80211_node *ni, wbuf_t wbuf)
{
    struct ieee80211vap *vap = ni->ni_vap;
    a_uint8_t    i_addr[IEEE80211_ADDR_LEN];
    a_int32_t    left_len = wbuf_get_pktlen(wbuf);
    a_uint8_t    *cur_ptr;
    a_uint32_t   dup_cnt, is_match = FALSE, is_bcast = FALSE;

    //wow_dump_pkt(wbuf->data, wbuf->len);

    if (left_len < IEEE80211_WOW_MAGIC_PKTLEN)
        return;
        
    cur_ptr = wbuf_header(wbuf);
    IEEE80211_ADDR_COPY(i_addr, vap->iv_myaddr);

    /* parse whole pkt */
    while (cur_ptr && (left_len>0) && (!is_match)) {
        
        /* left len is less than magic pkt size, give up */
        if (left_len < IEEE80211_WOW_MAGIC_PKTLEN)
            break;

        /* to skip continuous 0xFF and to match last 6 bytes of 0xFF */
        while (IEEE80211_IS_BROADCAST(cur_ptr) && (left_len>=IEEE80211_WOW_MAGIC_PKTLEN)) {
            is_bcast = TRUE;
            cur_ptr += IEEE80211_ADDR_LEN;
            left_len -= IEEE80211_ADDR_LEN;
        }

        /* 6 bytes of 0xFF matched, to check if 16 duplications of the IEEE address */
        if (is_bcast) {
            
            dup_cnt = 0;
            
            /* if 0xFF exists at head, skip it */
            while ((cur_ptr[0]==0xFF) && (left_len>=IEEE80211_WOW_MAGIC_DUPLEN)) {
                cur_ptr++;
                left_len--;
            }

            /* left len is less than duplication size, give up */
            if (left_len < IEEE80211_WOW_MAGIC_DUPLEN)
                break;
            
            /* to check if 16 duplications of the IEEE address */
            while (cur_ptr && (left_len>=IEEE80211_ADDR_LEN) && IEEE80211_ADDR_EQ(cur_ptr, i_addr)) {
                cur_ptr += IEEE80211_ADDR_LEN;
                left_len -= IEEE80211_ADDR_LEN;
                dup_cnt++;
                
                if (dup_cnt >= IEEE80211_WOW_MAGIC_DUPCNT) {
                    is_match = TRUE;
                    break;
                }
            }

            /* not match magic pkt, keep parsing */
            is_bcast = FALSE;

        } else {
            cur_ptr++;
            left_len--;
        }        
    }
    
    if (is_match) {
        adf_os_print("Magic packet received...\n");
        ieee80211_wow_set_gpio(vap);
    }
}
int
ieee80211_recv_probereq(struct ieee80211_node *ni, wbuf_t wbuf, int subtype)
{
    struct ieee80211com *ic = ni->ni_ic;
    struct ieee80211vap *vap = ni->ni_vap;
    struct ieee80211_frame *wh;
    u_int8_t *frm, *efrm;
    u_int8_t *ssid, *rates, *ven;

#if ATH_SUPPORT_AP_WDS_COMBO
    if (vap->iv_opmode == IEEE80211_M_STA || !ieee80211_vap_ready_is_set(vap) || vap->iv_no_beacon) {
#else
    if (vap->iv_opmode == IEEE80211_M_STA || !ieee80211_vap_ready_is_set(vap)) {
#endif
        vap->iv_stats.is_rx_mgtdiscard++;   /* XXX stat */
        return -EINVAL;
    }

    wh = (struct ieee80211_frame *) wbuf_header(wbuf);
    frm = (u_int8_t *)&wh[1];
    efrm = wbuf_header(wbuf) + wbuf_get_pktlen(wbuf);

	/*zhaoyang1 add start for  probe request REQUIREMENTS-340*/
	if (vap->iv_probe_request) {
		switch (vap->iv_probe_request) {
			case IEEE80211_BROADCAST_PROBE:
				if (IEEE80211_IS_BROADCAST(wh->i_addr1)) {
					vap->iv_stats.is_rx_mgtdiscard++;   /* XXX stat */
			        return -EINVAL;
				}
				break;
			case IEEE80211_ALL_PROBE:
				vap->iv_stats.is_rx_mgtdiscard++;   /* XXX stat */
	    		return -EINVAL;
			default:
				printk("Probe_req value is wrong, iv_probe_request = %d\n", vap->iv_probe_request);
				break;
		}
	}
	/*zhaoyang1 add end*/
	if (IEEE80211_IS_MULTICAST(wh->i_addr2)) {
        /* frame must be directed */
        vap->iv_stats.is_rx_mgtdiscard++;   /* XXX stat */
        return -EINVAL;
    }

    /*
     * prreq frame format
     *  [tlv] ssid
     *  [tlv] supported rates
     *  [tlv] extended supported rates
     *  [tlv] Atheros Advanced Capabilities
     */
    ssid = rates = NULL;
    while (((frm+1) < efrm) && (frm + frm[1] + 1 < efrm)) {
        switch (*frm) {
        case IEEE80211_ELEMID_SSID:
            ssid = frm;
            break;
        case IEEE80211_ELEMID_RATES:
            rates = frm;
            break;
        case IEEE80211_ELEMID_VENDOR:
            if (vap->iv_venie && vap->iv_venie->ven_oui_set) {            
                ven = frm;
                if (ven[2] == vap->iv_venie->ven_oui[0] && 
                    ven[3] == vap->iv_venie->ven_oui[1] && 
                    ven[4] == vap->iv_venie->ven_oui[2]) {
                    vap->iv_venie->ven_ie_len = MIN(ven[1] + 2, IEEE80211_MAX_IE_LEN);
                    OS_MEMCPY(vap->iv_venie->ven_ie, ven, vap->iv_venie->ven_ie_len);
                }
            }
            break;
        }
        frm += frm[1] + 2;
    }

    if (frm > efrm) {
        return -EINVAL;
    }

    IEEE80211_VERIFY_ELEMENT(rates, IEEE80211_RATE_MAXSIZE);
    IEEE80211_VERIFY_ELEMENT(ssid, IEEE80211_NWID_LEN);
    IEEE80211_VERIFY_SSID(vap->iv_bss, ssid);

    if (IEEE80211_VAP_IS_HIDESSID_ENABLED(vap) && (ssid[1] == 0)) {
        IEEE80211_DISCARD(vap, IEEE80211_MSG_INPUT,
                          wh, ieee80211_mgt_subtype_name[
                              subtype >> IEEE80211_FC0_SUBTYPE_SHIFT],
                          "%s", "no ssid with ssid suppression enabled");
        vap->iv_stats.is_rx_ssidmismatch++; /*XXX*/
        return -EINVAL;
    }

    /*
     * Skip Probe Requests received while the scan algorithm is setting a new 
     * channel, or while in a foreign channel.
     * Trying to transmit a frame (Probe Response) during a channel change 
     * (which includes a channel reset) can cause a NMI due to invalid HW 
     * addresses. 
     * Trying to transmit the Probe Response while in a foreign channel 
     * wouldn't do us any good either.
     */
    if (ieee80211_scan_can_transmit(ic->ic_scanner))
        ieee80211_send_proberesp(ni, wh->i_addr2, NULL,0);
    
    return 0;
}