示例#1
0
void
host_htc_eptx_comp(void *context, wbuf_t skb, HTC_ENDPOINT_ID epid)
{

	/* for HTC, since we don't have the "real" tx-status, we do them here. */
    struct ath_softc_net80211 	*scn = (struct ath_softc_net80211 *)context;
	ath_dev_t  				 	sc_dev = scn->sc_dev;
	struct ath_softc 			*sc = ATH_DEV_TO_SC(sc_dev);
	u_int16_t 					min_len_req_by_stats = sizeof(ath_data_hdr_t)+sizeof(struct ieee80211_frame);

	if( wbuf_get_pktlen(skb)> min_len_req_by_stats &&
		wbuf_get_tid(skb) < ATH_HTC_WME_NUM_TID &&(
		epid == sc->sc_data_BE_ep ||
		epid == sc->sc_data_BK_ep ||
		epid == sc->sc_data_VI_ep ||
		epid == sc->sc_data_VO_ep	)){
		
		struct ieee80211_node 		*ni = wbuf_get_node(skb);
		struct ieee80211vap 		*vap = ni->ni_vap;
		struct ieee80211_frame 		*wh;
		struct ieee80211_tx_status 	ts;
		struct ieee80211_mac_stats 	*mac_stats;
		u_int8_t 					type, subtype;
		u_int8_t 					is_mcast;
				
		wh = (struct ieee80211_frame *)(wbuf_header(skb)+sizeof(ath_data_hdr_t));
		type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
		subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
		/* we fake ts becuase we don't have ts in HTC tx */
		ts.ts_flags = 0;                                    
    	ts.ts_retries = 0;  

		ieee80211_update_stats(vap, skb, wh, type, subtype, &ts);
		
		/* patch: HTC tx only ath_data_hdr length */
		is_mcast = IEEE80211_IS_MULTICAST(wh->i_addr1) ? 1 : 0;
		mac_stats = is_mcast ? &vap->iv_multicast_stats : &vap->iv_unicast_stats;
		mac_stats->ims_tx_bytes -= sizeof(ath_data_hdr_t);

 	}
	
    ieee80211_free_node(wbuf_get_node(skb));
}
示例#2
0
文件: pktlog.c 项目: KHATEEBNSIT/AP
/*
 * Searches for the presence of a protocol header and returns protocol type.
 * proto_len and proto_log are modified to return length (in bytes) and
 * contents of header (in host byte order), if one is found.
 */ 
static int 
pktlog_proto(struct ath_softc *sc, u_int32_t proto_log[PKTLOG_MAX_PROTO_WORDS],
             void *log_data, pktlog_proto_desc_t ds_type, int *proto_len, HAL_BOOL *isSack)
{
#define IPHDRLEN     20
    struct llc *llc = NULL;
    struct log_tx *tx_log;
    struct log_rx *rx_log;
    wbuf_t wbuf = NULL;
    static const int pktlog_proto_min_hlen = sizeof(struct ieee80211_frame) + 
                                             sizeof(struct llc) + IPHDRLEN;

    switch (ds_type) {
        case PKTLOG_PROTO_TX_DESC:
            tx_log = (struct log_tx *)log_data;
            wbuf = (wbuf_t)(tx_log->bf->bf_mpdu);
            if (wbuf_get_pktlen((wbuf_t)(tx_log->bf->bf_mpdu)) < pktlog_proto_min_hlen) {
                return PKTLOG_PROTO_NONE;
            }
            
            llc = (struct llc *)sc->sc_ieee_ops->parse_frm(sc->sc_ieee,
                                                           wbuf,
                                                           wbuf_get_node((wbuf_t)(tx_log->bf->bf_mpdu)),
                                                           tx_log->bf->bf_vdata,
                                                           0);
            break;
            
        case PKTLOG_PROTO_RX_DESC:
            rx_log = (struct log_rx *)log_data;
            if (rx_log->status->rs_datalen < pktlog_proto_min_hlen) {
                return PKTLOG_PROTO_NONE;
            }

            llc = (struct llc *)sc->sc_ieee_ops->parse_frm(sc->sc_ieee,
                                                           NULL, NULL,
                                                           rx_log->bf->bf_vdata,
                                                           rx_log->status->rs_keyix);
            break;
            
        default:
            return PKTLOG_PROTO_NONE;
    }

    if(!llc) {
        return PKTLOG_PROTO_NONE;
    }
    
    return pktlog_tcpip(sc, wbuf, llc, proto_log, proto_len, isSack);
#undef IPHDRLEN
}
示例#3
0
/*
 * This routine picks an AMSDU buffer, calls the platform specific 802.11 layer for
 * WLAN encapsulation and then dispatches it to hardware for transmit.
 */
void
ath_amsdu_stageq_flush(struct ath_softc_net80211 *scn, struct ath_amsdu_tx *amsdutx)
{
    struct ieee80211_node *ni;
    struct ieee80211com *ic;
    wbuf_t wbuf;
    ATH_AMSDU_TXQ_LOCK(scn);
    wbuf = amsdutx->amsdu_tx_buf;
    if (!wbuf) {
        ATH_AMSDU_TXQ_UNLOCK(scn);
        return;
    }
    amsdutx->amsdu_tx_buf = NULL;
    ATH_AMSDU_TXQ_UNLOCK(scn);
    ni = wbuf_get_node(wbuf);
    ic = ni->ni_ic;
    /*
     * Encapsulate the packet for transmission
     */
    wbuf = ieee80211_encap(ni, wbuf);
    if (wbuf == NULL) {
        printk("%s[%d] : ERROR: ieee80211_encap ret NULL\n", __func__, __LINE__);
        return;
    }
    /* There is only one wbuf to send */
    if (wbuf != NULL) {
        int error = 0;

        ATH_DEFINE_TXCTL(txctl, wbuf);
        HTC_WBUF_TX_DELCARE
        /* prepare this frame */
        if (ath_tx_prepare(scn, wbuf, 0, txctl) != 0) {
            goto bad;
        }

        HTC_WBUF_TX_DATA_PREPARE(ic, scn);
        
        if (error == 0) {
            /* send this frame to hardware */
            txctl->an = (ATH_NODE_NET80211(ni))->an_sta;
            if (scn->sc_ops->tx(scn->sc_dev, wbuf, txctl) != 0)
            {
                goto bad;
            } else {
                HTC_WBUF_TX_DATA_COMPLETE_STATUS(ic);
            }
        }
    }
示例#4
0
/*
 * callback hadlers: Action frames TX Complete.
 */
void
ath_action_tx_event(void *Context, int8_t tx_status)
{
    struct ath_softc_net80211 *scn = (struct ath_softc_net80211 *)Context;
    struct ath_usb_p2p_action_queue *p2p_action_wbuf;

    IEEE80211_STATE_P2P_ACTION_LOCK_IRQ(scn);
    if (scn->sc_p2p_action_queue_head) {
        ieee80211_vap_complete_buf_handler handler;
        void *arg;
        wbuf_t wbuf;

        p2p_action_wbuf = scn->sc_p2p_action_queue_head;
        if (scn->sc_p2p_action_queue_head == scn->sc_p2p_action_queue_tail) {
            scn->sc_p2p_action_queue_head = scn->sc_p2p_action_queue_tail = NULL;
        } else {
            scn->sc_p2p_action_queue_head = scn->sc_p2p_action_queue_head->next;
        }

        wbuf = p2p_action_wbuf->wbuf;
        if (!p2p_action_wbuf->deleted) {
            wbuf_get_complete_handler(wbuf,(void **)&handler, &arg);
            if (handler) {
                struct ieee80211_node *ni = wbuf_get_node(wbuf);
                struct ieee80211_frame *wh = (struct ieee80211_frame *)wbuf_header(wbuf);
                wlan_if_t vap = ni->ni_vap;
                struct ieee80211_tx_status ts;

                ts.ts_flags = tx_status;
                ts.ts_retries = 0;
                handler(vap, wbuf, arg, wh->i_addr1, wh->i_addr2, wh->i_addr3, &ts);
            }
        } else {
#ifndef MAGPIE_HIF_GMAC 
            printk("### action frame %p marked as deleted\n", wbuf);
#endif        
        }
        wbuf_release(scn->sc_osdev, p2p_action_wbuf->wbuf);
        OS_FREE(p2p_action_wbuf);

        //printk("### %s (%d) : Action TX EVENT DONE...\n", __FUNCTION__, __LINE__);
    }
    IEEE80211_STATE_P2P_ACTION_UNLOCK_IRQ(scn);
}
示例#5
0
u_int8_t ath_htc_find_tgt_node_index(wbuf_t wbuf)
{
    struct ieee80211_node *ni = wbuf_get_node(wbuf);

    return ath_find_tgt_node_index(ni);
}
示例#6
0
/*
 * Add privacy headers appropriate for the specified key.
 */
static int
ccmp_encap(struct ieee80211_key *k, wbuf_t wbuf, u_int8_t keyid)
{
    struct ccmp_ctx *ctx = k->wk_private;
    struct ieee80211com *ic = ctx->cc_ic;
    u_int8_t *ivp;
    int hdrlen;
    int is4addr, isqos, owl_wdswar;
    struct ieee80211_frame *wh;
    struct ieee80211_node *ni = wbuf_get_node(wbuf);

    wh = (struct ieee80211_frame *)wbuf_header(wbuf);
    is4addr = ((wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) == IEEE80211_FC1_DIR_DSTODS) ? 1 : 0;
    isqos = IEEE80211_QOS_HAS_SEQ(wh);
    owl_wdswar = (ni->ni_flags & IEEE80211_NODE_OWL_WDSWAR);

    hdrlen = ieee80211_hdrspace(ic, wbuf_header(wbuf));

    /*
     * Copy down 802.11 header and add the IV, KeyID, and ExtIV.
     */
#ifndef __CARRIER_PLATFORM__
    ivp = (u_int8_t *)wbuf_push(wbuf, ccmp.ic_header);

    /* 
     * refresh the wh pointer,
     * wbuf header  pointer is changed with wbuf_push.
     */
    wh = (struct ieee80211_frame *) wbuf_header(wbuf); /* recompute wh */

    memmove(ivp, ivp + ccmp.ic_header, hdrlen);
#else
    if (wbuf_is_encap_done(wbuf)) {
        ivp = (u_int8_t *)wbuf_header(wbuf);
    }
    else { 
        ivp = (u_int8_t *)wbuf_push(wbuf, ccmp.ic_header);
        memmove(ivp, ivp + ccmp.ic_header, hdrlen);
        /* 
         * refresh the wh pointer,
         * wbuf header  pointer is changed with wbuf_push.
         */
        wh = (struct ieee80211_frame *) wbuf_header(wbuf); /* recompute wh */
    }
#endif
    ivp += hdrlen;

    /*
     * Due to OWL specific HW bug, increment key tsc by 16, since
     * we're copying the TID into bits [3:0] of IV0.
     * XXX: Need logic to not implement workaround for SOWL or greater.
     */
    if (is4addr && isqos && owl_wdswar)
        k->wk_keytsc += 16;
    else
        k->wk_keytsc++;		/* XXX wrap at 48 bits */

    ivp[0] = k->wk_keytsc >> 0;		/* PN0 */
    ivp[1] = k->wk_keytsc >> 8;		/* PN1 */
    ivp[2] = 0;				/* Reserved */
    ivp[3] = keyid | IEEE80211_WEP_EXTIV;	/* KeyID | ExtID */
    ivp[4] = k->wk_keytsc >> 16;		/* PN2 */
    ivp[5] = k->wk_keytsc >> 24;		/* PN3 */
    ivp[6] = k->wk_keytsc >> 32;		/* PN4 */
    ivp[7] = k->wk_keytsc >> 40;		/* PN5 */

    /*
     * Finally, do software encrypt if neeed.
     */
    if (k->wk_flags & IEEE80211_KEY_SWCRYPT) {
        if (!ccmp_encrypt(k, wbuf, hdrlen, 0)) {
            return 0;
        }
    }
    if ((k->wk_flags & IEEE80211_KEY_MFP) && IEEE80211_IS_MFP_FRAME(wh)) {
        if (ic->ic_get_mfpsupport(ic) != IEEE80211_MFP_HW_CRYPTO) {
            /* HW MFP is not enabled - do software encrypt */
            if (!ccmp_encrypt(k, wbuf, hdrlen, 1)) {
                return 0;
            }
        }
    }
    return 1;
}