有关速率获取的问题
通过上面的代码分析,我们认为在madwifi情况下,r0就是实际的速率,因此,需要在应用层能够获得r0的指,经过跟踪,发现当调用iwconfig命令,来获取速率的值的时候,会调用
ieee80211_ioctl_giwrate(struct net_device *dev, struct iw_request_info *info,
struct iw_param *rrq, char *extra)
{
struct ieee80211vap *vap = dev->priv;
现在当使用auto的自适应速率时候,自动返回-1,因此,获得速率值为0. 因此,需要修改这个函数,调用ARMARF自适应速率的ath_rate_findrate函数. 通过上面的分析,我们认为实际上使用的发送速率就是r0,那么如何获取呢?
速率控制的驱动中有一个函数:
void
ath_rate_findrate(struct ath_softc *sc, struct ath_node *an, int shortPreamble, size_t frameLen, u_int8_t *rix, int *try0, u_int8_t *txrate)
{
struct onoe_node *on = ATH_NODE_ONOE(an);
*rix = on->on_tx_rix0;
*try0 = on->on_tx_try0;
if (shortPreamble)
*txrate = on->on_tx_rate0sp;
else
*txrate = on->on_tx_rate0;
}
返回的txrate就是实际上使用的on->on_tx_rate0,r0 该函数为实际上只有struct ath_node *an参数是需要传递的,ieee80211_ioctl_giwrate输入的参数为net_device *dev,因此,需要将该输入参数转换得到struct ath_node *an参数:因此,我们需要关注三个结构体:
struct net_device *dev结构体包含了ieee80211vap *vap结构体:
ieee80211vap *vap = dev->priv;
an = ATH_NODE(ni);
struct ath_softc {
struct ieee80211com sc_ic; /* NB: must be first */
struct net_device *sc_dev;
struct semaphore sc_lock; /* dev-level lock */
struct ath_node {
struct ieee80211_node an_node; /* base class */
u_int16_t an_decomp_index; /* decompression mask index */
u_int32_t an_avgrssi; /* average rssi over all rx frames */
u_int8_t an_prevdatarix; /* rate ix of last data frame */
u_int16_t an_minffrate; /* mimum rate in kbps for ff to aggragate */
HAL_NODE_STATS an_halstats; /* rssi statistics used by hal */
struct ath_buf *an_tx_ffbuf[WME_NUM_AC]; /* ff staging area */
ath_bufhead an_uapsd_q; /* U-APSD delivery queue */
int an_uapsd_qdepth; /* U-APSD delivery queue depth */
ath_bufhead an_uapsd_overflowq; /* U-APSD overflow queue (for > MaxSp frames) */
int an_uapsd_overflowqdepth; /* U-APSD overflow queue depth */
spinlock_t an_uapsd_lock; /* U-APSD deleivery queue lock */
/* variable-length rate control state follows */
};
struct ieee80211_node {
struct ieee80211vap *ni_vap;
struct ieee80211com *ni_ic;
struct ieee80211_node_table *ni_table;
…………..
struct ieee80211vap {
struct net_device *iv_dev; /* associated device */
struct net_device_stats iv_devstats; /* interface statistics */
struct ifmedia iv_media; /* interface media config */
#ifdef CONFIG_NET_WIRELESS
struct iw_statistics iv_iwstats; /* wireless statistics block */
#endif
…………
struct ieee80211com *iv_ic; /* back ptr to common state */
……………
下面三个结构体的包含关系为:
ath_node-> ieee80211_node-> ieee80211vap
并且由于首地址是一样的,因此,只要获得任意一个结构体,可以使用指针强制转换为另外两个结构体,例如已知ieee80211_node结构体,可以获得ath_node,在if_ath.c 的ath_tx_start函数中,使用
an = ATH_NODE(ni)命令获得,
#define ATH_NODE(_n) ((struct ath_node *)(_n))
struct ath_softc *sc = dev->priv;
struct ieee80211com *an = dev->priv;
ath_rate_findrate(sc, an, shortPreamble, skb->len, &rix, &try0, &txrate);
调试中发现,始终不能正确的传递参数,经过调试,发现ieee80211.c和if_ath.c代码的struct net_device变量是不一样的,两者的参数名字分别为ath0和wifi0,也就是两个网络设备的名字,因此,没有办法传递参数。
下面还是分析iwconfig中的参数是如何传递的,以ieee80211_ioctl_siwpower函数为例,设置发送功率。
ieee80211_ioctl_siwpower(struct net_device *dev, struct iw_request_info *info,
struct iw_param *wrq, char *extra)
{
struct ieee80211vap *vap = dev->priv;
struct ieee80211com *ic = vap->iv_ic;
……………..
return IS_UP(ic->ic_dev) ? ic->ic_reset(ic->ic_dev) : 0; 如果设备已经UP,那么以新的参数对设备设置。这里面调用了一个函数指针,ic->ic_reset,经过检查,只有 if_ath.c文件调用了,
if_ath.c(692): ic->ic_reset = ath_reset;
ath_attach(u_int16_t devid, struct net_device *dev)
{
struct ath_softc *sc = dev->priv;
struct ieee80211com *ic = &sc->sc_ic;
struct ath_hal *ah;
………….
ic->ic_reset = ath_reset;
ath_reset(struct net_device *dev)
{
struct ath_softc *sc = dev->priv;
struct ieee80211com *ic = &sc->sc_ic;
struct ath_hal *ah = sc->sc_ah;
struct ieee80211_channel *c;
HAL_STATUS status;
iwconfig命令会最终调用ieee80211_wireless.c中的
各种参数设置和控制命令,查看代码,发现ieee80211_wireless中本身定义了很多的参数变量,如果需要设置,再调用底层的函数将参数写入网
卡芯片,如果读参数,就直接读自己已经保存好的参数,而并不是读真正的物理层的参数!
ieee80211_ioctl_siwpower代码最终会调用ath_reset,这两个函数的输入参数都是struct net_device *dev,他是如何进行参数转换的呢?将ath0变为wifi0?
Iwconfig中,首先由输入参数ath0(struct net_device *dev)获得vap struct ieee80211vap *vap = dev->priv;
该结构体定义为:
struct ieee80211vap {
struct net_device *iv_dev; /* associated device */
struct ieee80211com *iv_ic; /* back ptr to common state */
……………
然后由vap获得ic,struct ieee80211com *ic = vap->iv_ic;
而该结构体定义为:
struct ieee80211com {
struct net_device *ic_dev; /* associated device */
又关联了一个net_device设备,这个设备正是wifi0,因此,调用ic_reset的时候,并不是直接将
ieee80211_ioctl_siwpower的输出参数dev放进去,而是转了两个弯,ic->ic_reset(ic->ic_dev)。再次回到获取速率的函数,调用下面的函数获得速率,
ath_rate_findrate(sc, an, shortPreamble, skb->len, &rix, &try0, &txrate);
这里,sc以前直接定义为:ieee80211_ioctl_siwpower输入参数的dev,
struct ath_softc *sc = dev->priv;
需要将其定义为wifi0,因此,需要定义为:
struct ieee80211vap *vap = dev->priv; 由ath0 device获得vap
struct ieee80211com *ic = vap->iv_ic;
struct net_device *wifi= ic->ic_dev; 再次获得wifi device
struct ath_softc *sc = wifi ->priv; 获得sc
如果调用findrate函数,第二个参数ath_node需要传递过来,发现这比较困难,因此,暂时不使用这个方法,而是自己在ieee80211com结构体中定义一个变量,利用该变量传递参数。
ath_rate_findrate(struct ath_softc *sc, struct ath_node *an, int shortPreamble, size_t frameLen, u_int8_t *rix, int *try0, u_int8_t *txrate)
» 本文来自:橙叶WLAN » 《madwifi底层驱动速率的获取》
No comments:
Post a Comment