예제 #1
0
void
ath_rate_tx_complete(struct ath_softc *sc, struct ath_node *an,
	const struct ath_rc_series *rc, const struct ath_tx_status *ts,
	int frame_size, int nframes, int nbad)
{
	struct ifnet *ifp = sc->sc_ifp;
	struct ieee80211com *ic = ifp->if_l2com;
	struct sample_node *sn = ATH_NODE_SAMPLE(an);
	int final_rix, short_tries, long_tries;
	const HAL_RATE_TABLE *rt = sc->sc_currates;
	int status = ts->ts_status;
	int mrr;

	final_rix = rt->rateCodeToIndex[ts->ts_rate];
	short_tries = ts->ts_shortretry;
	long_tries = ts->ts_longretry + 1;

	if (frame_size == 0)		    /* NB: should not happen */
		frame_size = 1500;

	if (sn->ratemask == 0) {
		IEEE80211_NOTE(an->an_node.ni_vap, IEEE80211_MSG_RATECTL,
		    &an->an_node,
		    "%s: size %d %s rate/try %d/%d no rates yet", 
		    __func__,
		    bin_to_size(size_to_bin(frame_size)),
		    status ? "FAIL" : "OK",
		    short_tries, long_tries);
		return;
	}
	mrr = sc->sc_mrretry && !(ic->ic_flags & IEEE80211_F_USEPROT);
	if (!mrr || ts->ts_finaltsi == 0) {
		if (!IS_RATE_DEFINED(sn, final_rix)) {
			badrate(ifp, 0, ts->ts_rate, long_tries, status);
			return;
		}
		/*
		 * Only one rate was used; optimize work.
		 */
		IEEE80211_NOTE(an->an_node.ni_vap, IEEE80211_MSG_RATECTL,
		     &an->an_node, "%s: size %d (%d bytes) %s rate/try %d %s/%d/%d nframes/nbad [%d/%d]",
		     __func__,
		     bin_to_size(size_to_bin(frame_size)),
		     frame_size,
		     status ? "FAIL" : "OK",
		     dot11rate(rt, final_rix), dot11rate_label(rt, final_rix),
		     short_tries, long_tries, nframes, nbad);
		update_stats(sc, an, frame_size, 
			     final_rix, long_tries,
			     0, 0,
			     0, 0,
			     0, 0,
			     short_tries, long_tries, status,
			     nframes, nbad);
		update_ewma_stats(sc, an, frame_size, 
			     final_rix, long_tries,
			     0, 0,
			     0, 0,
			     0, 0,
			     short_tries, long_tries, status,
			     nframes, nbad);

	} else {
		int finalTSIdx = ts->ts_finaltsi;
		int i;

		/*
		 * Process intermediate rates that failed.
		 */

		IEEE80211_NOTE(an->an_node.ni_vap, IEEE80211_MSG_RATECTL,
		    &an->an_node,
"%s: size %d (%d bytes) finaltsidx %d tries %d %s rate/try [%d %s/%d %d %s/%d %d %s/%d %d %s/%d] nframes/nbad [%d/%d]", 
		     __func__,
		     bin_to_size(size_to_bin(frame_size)),
		     frame_size,
		     finalTSIdx,
		     long_tries,
		     status ? "FAIL" : "OK",
		     dot11rate(rt, rc[0].rix),
		      dot11rate_label(rt, rc[0].rix), rc[0].tries,
		     dot11rate(rt, rc[1].rix),
		      dot11rate_label(rt, rc[1].rix), rc[1].tries,
		     dot11rate(rt, rc[2].rix),
		      dot11rate_label(rt, rc[2].rix), rc[2].tries,
		     dot11rate(rt, rc[3].rix),
		      dot11rate_label(rt, rc[3].rix), rc[3].tries,
		     nframes, nbad);

		for (i = 0; i < 4; i++) {
			if (rc[i].tries && !IS_RATE_DEFINED(sn, rc[i].rix))
				badrate(ifp, 0, rc[i].ratecode, rc[i].tries,
				    status);
		}

		/*
		 * NB: series > 0 are not penalized for failure
		 * based on the try counts under the assumption
		 * that losses are often bursty and since we
		 * sample higher rates 1 try at a time doing so
		 * may unfairly penalize them.
		 */
		if (rc[0].tries) {
			update_stats(sc, an, frame_size,
				     rc[0].rix, rc[0].tries,
				     rc[1].rix, rc[1].tries,
				     rc[2].rix, rc[2].tries,
				     rc[3].rix, rc[3].tries,
				     short_tries, long_tries,
				     long_tries > rc[0].tries,
				     nframes, nbad);
			long_tries -= rc[0].tries;
		}
		
		if (rc[1].tries && finalTSIdx > 0) {
			update_stats(sc, an, frame_size,
				     rc[1].rix, rc[1].tries,
				     rc[2].rix, rc[2].tries,
				     rc[3].rix, rc[3].tries,
				     0, 0,
				     short_tries, long_tries,
				     status,
				     nframes, nbad);
			long_tries -= rc[1].tries;
		}

		if (rc[2].tries && finalTSIdx > 1) {
			update_stats(sc, an, frame_size,
				     rc[2].rix, rc[2].tries,
				     rc[3].rix, rc[3].tries,
				     0, 0,
				     0, 0,
				     short_tries, long_tries,
				     status,
				     nframes, nbad);
			long_tries -= rc[2].tries;
		}

		if (rc[3].tries && finalTSIdx > 2) {
			update_stats(sc, an, frame_size,
				     rc[3].rix, rc[3].tries,
				     0, 0,
				     0, 0,
				     0, 0,
				     short_tries, long_tries,
				     status,
				     nframes, nbad);
		}

		update_ewma_stats(sc, an, frame_size,
			     rc[0].rix, rc[0].tries,
			     rc[1].rix, rc[1].tries,
			     rc[2].rix, rc[2].tries,
			     rc[3].rix, rc[3].tries,
			     short_tries, long_tries,
			     long_tries > rc[0].tries,
			     nframes, nbad);

	}
}
예제 #2
0
void
ath_rate_tx_complete(struct ath_softc *sc, struct ath_node *an,
	const struct ath_buf *bf)
{
	struct ifnet *ifp = sc->sc_ifp;
	struct ieee80211com *ic = ifp->if_l2com;
	struct sample_node *sn = ATH_NODE_SAMPLE(an);
	const struct ath_tx_status *ts = &bf->bf_status.ds_txstat;
	const struct ath_desc *ds0 = &bf->bf_desc[0];
	int final_rix, short_tries, long_tries, frame_size;
	const HAL_RATE_TABLE *rt = sc->sc_currates;
	int mrr;

	final_rix = rt->rateCodeToIndex[ts->ts_rate];
	short_tries = ts->ts_shortretry;
	long_tries = ts->ts_longretry + 1;
	frame_size = ds0->ds_ctl0 & 0x0fff; /* low-order 12 bits of ds_ctl0 */
	if (frame_size == 0)		    /* NB: should not happen */
		frame_size = 1500;

	if (sn->ratemask == 0) {
		IEEE80211_NOTE(an->an_node.ni_vap, IEEE80211_MSG_RATECTL,
		    &an->an_node,
		    "%s: size %d %s rate/try %d/%d no rates yet", 
		    __func__,
		    bin_to_size(size_to_bin(frame_size)),
		    ts->ts_status ? "FAIL" : "OK",
		    short_tries, long_tries);
		return;
	}
	mrr = sc->sc_mrretry && !(ic->ic_flags & IEEE80211_F_USEPROT);
	if (!mrr || ts->ts_finaltsi == 0) {
		if (!IS_RATE_DEFINED(sn, final_rix)) {
			badrate(ifp, 0, ts->ts_rate, long_tries, ts->ts_status);
			return;
		}
		/*
		 * Only one rate was used; optimize work.
		 */
		IEEE80211_NOTE(an->an_node.ni_vap, IEEE80211_MSG_RATECTL,
		     &an->an_node, "%s: size %d %s rate/try %d/%d/%d",
		     __func__,
		     bin_to_size(size_to_bin(frame_size)),
		     ts->ts_status ? "FAIL" : "OK",
		     final_rix, short_tries, long_tries);
		update_stats(sc, an, frame_size, 
			     final_rix, long_tries,
			     0, 0,
			     0, 0,
			     0, 0,
			     short_tries, long_tries, ts->ts_status);
	} else {
		int hwrate0, rix0, tries0;
		int hwrate1, rix1, tries1;
		int hwrate2, rix2, tries2;
		int hwrate3, rix3, tries3;
		int finalTSIdx = ts->ts_finaltsi;

		/*
		 * Process intermediate rates that failed.
		 */
		if (sc->sc_ah->ah_magic != 0x20065416) {
			hwrate0 = MS(ds0->ds_ctl3, AR_XmitRate0);
			hwrate1 = MS(ds0->ds_ctl3, AR_XmitRate1);
			hwrate2 = MS(ds0->ds_ctl3, AR_XmitRate2);
			hwrate3 = MS(ds0->ds_ctl3, AR_XmitRate3);
		} else {
			hwrate0 = MS(ds0->ds_ctl3, AR5416_XmitRate0);
			hwrate1 = MS(ds0->ds_ctl3, AR5416_XmitRate1);
			hwrate2 = MS(ds0->ds_ctl3, AR5416_XmitRate2);
			hwrate3 = MS(ds0->ds_ctl3, AR5416_XmitRate3);
		}

		rix0 = rt->rateCodeToIndex[hwrate0];
		tries0 = MS(ds0->ds_ctl2, AR_XmitDataTries0);

		rix1 = rt->rateCodeToIndex[hwrate1];
		tries1 = MS(ds0->ds_ctl2, AR_XmitDataTries1);

		rix2 = rt->rateCodeToIndex[hwrate2];
		tries2 = MS(ds0->ds_ctl2, AR_XmitDataTries2);

		rix3 = rt->rateCodeToIndex[hwrate3];
		tries3 = MS(ds0->ds_ctl2, AR_XmitDataTries3);

		IEEE80211_NOTE(an->an_node.ni_vap, IEEE80211_MSG_RATECTL,
		    &an->an_node,
"%s: size %d finaltsidx %d tries %d %s rate/try [%d/%d %d/%d %d/%d %d/%d]", 
		     __func__,
		     bin_to_size(size_to_bin(frame_size)),
		     finalTSIdx,
		     long_tries, 
		     ts->ts_status ? "FAIL" : "OK",
		     rix0, tries0,
		     rix1, tries1,
		     rix2, tries2,
		     rix3, tries3);

		if (tries0 && !IS_RATE_DEFINED(sn, rix0))
			badrate(ifp, 0, hwrate0, tries0, ts->ts_status);
		if (tries1 && !IS_RATE_DEFINED(sn, rix1))
			badrate(ifp, 1, hwrate1, tries1, ts->ts_status);
		if (tries2 && !IS_RATE_DEFINED(sn, rix2))
			badrate(ifp, 2, hwrate2, tries2, ts->ts_status);
		if (tries3 && !IS_RATE_DEFINED(sn, rix3))
			badrate(ifp, 3, hwrate3, tries3, ts->ts_status);

		/*
		 * NB: series > 0 are not penalized for failure
		 * based on the try counts under the assumption
		 * that losses are often bursty and since we
		 * sample higher rates 1 try at a time doing so
		 * may unfairly penalize them.
		 */
		if (tries0) {
			update_stats(sc, an, frame_size, 
				     rix0, tries0, 
				     rix1, tries1, 
				     rix2, tries2, 
				     rix3, tries3, 
				     short_tries, long_tries, 
				     long_tries > tries0);
			long_tries -= tries0;
		}
		
		if (tries1 && finalTSIdx > 0) {
			update_stats(sc, an, frame_size, 
				     rix1, tries1, 
				     rix2, tries2, 
				     rix3, tries3, 
				     0, 0, 
				     short_tries, long_tries, 
				     ts->ts_status);
			long_tries -= tries1;
		}

		if (tries2 && finalTSIdx > 1) {
			update_stats(sc, an, frame_size, 
				     rix2, tries2, 
				     rix3, tries3, 
				     0, 0,
				     0, 0,
				     short_tries, long_tries, 
				     ts->ts_status);
			long_tries -= tries2;
		}

		if (tries3 && finalTSIdx > 2) {
			update_stats(sc, an, frame_size, 
				     rix3, tries3, 
				     0, 0,
				     0, 0,
				     0, 0,
				     short_tries, long_tries, 
				     ts->ts_status);
		}
	}
}