Monday, October 10, 2011

madwifi底层驱动速率的获取

有关速率获取的问题

通过上面的代码分析,我们认为在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.cif_ath.c代码的struct net_device变量是不一样的,两者的参数名字分别为ath0wifi0,也就是两个网络设备的名字,因此,没有办法传递参数。

下面还是分析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)

No comments:

Post a Comment