mac80211学习

最近一直在为文章做实验,其中涉及mac层调度算法,所以一直在读和修改ath5k和mac80211的代码。也学习了一些东西,本来一直记载笔记上面,但是怕这些知识会被自己慢慢地淡忘,所以选择书写一些博客来记录下自己学习的脚步。

上面这张图片来自与Daniel Camps Mur 的linux Wi-Fi Open Source Driver -mac80211, ath9k/ath5k演讲的ppt。这张图代表了数据从内核传送给无线网卡,在经过无线网卡传送出去的过程。如果结合netfilter的思路,那么就是数据进入内核之后,netfilter/iptable判断这些数据是不是传送给本机的还是通过本机转发的,如果是通过本机转发的,那么就通过内核传送给网卡。

1. ieee_80211_subif_start_xmit

kernel将所要传输的数据放在skb中,ieee_80211_subif_start_xmit(struct sk_buff *skb,  struct net_device *dev),可以看出这个函数有两个参数,第一个是包含数据的skb,第二个是数据的来源网络接口,在我的配置中(数据通过有线接口eth0进入,然后通过wlan0传送给客户端)应该是wlan0(printk输出参数显示,该接口就是wlan0)。然后这个函数调用_ieee_80211_subif_xmit函数,这个函数的参数是刚才的skb和网络接口类型,还有一个0,在此对skb进行创建80211头操作:

skb = ieee80211_build_hdr(sdata, skb, info_flags);

其中sdata为:

struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);(这个数据结构比较复杂,需要进一步了解)

在创建完80211头之后,发送到master接口,

dev->stats.tx_packets++;
dev->stats.tx_bytes += skb->len;
dev->trans_start = jiffies; //最近传送数据包的时间   
ieee80211_xmit(sdata, skb);

其中dev->stats中的stats是一个数据结构,其结构如下:

struct net_device_stats
    {
        unsigned long rx_packets;
        unsigned long tx_packets;
        unsigned long rx_bytes;
        unsigned long tx_bytes;
        unsigned long rx_errors;
        unsigned long tx_errors;
        unsigned long rx_dropped;
        unsigned long tx_dropped;
        unsigned long multicast;
        unsigned long   collisions;

       
        unsigned long rx_length_errors;
        unsigned long rx_over_errors;
        unsigned long rx_crc_errors;
        unsigned long rx_frame_errors;
        unsigned long rx_fifo_errors;
        unsigned long rx_missed_errors;

   
    unsigned long   tx_aborted_errors;
    unsigned long   tx_carrier_errors;
    unsigned long   tx_fifo_errors;
    unsigned long   tx_heartbeat_errors;
    unsigned long   tx_window_errors;

   
    unsigned long   rx_compressed;
    unsigned long   tx_compressed;
};

它是一个用来保存发送数据状态的数据结构。

最后__ieee80211_subif_start_xmit调用ieee80211_xmit(sdata, skb);

小结:在这个函数中,最主要的工作还是为skb创建ieee80211 header,其次是设置发送数据加一和记录最近的发送时间。

2. ieee80211_xmit(sdata,skb)

这个函数主要有三个作用:

1. 为加密分配headroom

2.ieee80211_set_qos_hdr在包头中设置QoS参数,

void ieee80211_set_qos_hdr(struct ieee80211_sub_if_data *sdata,

  struct sk_buff *skb)
{
struct ieee80211_hdr *hdr = (void *)skb->data;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
u8 *p;
u8 ack_policy, tid;
if (!ieee80211_is_data_qos(hdr->frame_control))
return;
p = ieee80211_get_qos_ctl(hdr);//这里是用来获取IP包里面的TOS域内容。
tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
/* preserve EOSP bit */
ack_policy = *p & IEEE80211_QOS_CTL_EOSP;
if (is_multicast_ether_addr(hdr->addr1) ||
   sdata->noack_map & BIT(tid)) {
ack_policy |= IEEE80211_QOS_CTL_ACK_POLICY_NOACK;
info->flags |= IEEE80211_TX_CTL_NO_ACK;
}
/* qos header is 2 bytes */
*p++ = ack_policy | tid;
if (ieee80211_vif_is_mesh(&sdata->vif)) {
/* preserve RSPI and Mesh PS Level bit */
*p &= ((IEEE80211_QOS_CTL_RSPI |
IEEE80211_QOS_CTL_MESH_PS_LEVEL) >> 8);
/* Nulls don't have a mesh header (frame body) */
if (!ieee80211_is_qos_nullfunc(hdr->frame_control))
*p |= (IEEE80211_QOS_CTL_MESH_CONTROL_PRESENT >> 8);
} else {
*p = 0;
}
}

这个函数应该就是为了修改P也就是ip包中的TOS域的内容。

3.调用ieee80211_tx(sdata,skb,false,band)

ieee80211_tx(sdata,skb,false,band)

         dnsmasq-25107 [002] 98228.755607: funcgraph_entry:                   |  ieee80211_subif_start_xmit() {
         dnsmasq-25107 [002] 98228.755619: funcgraph_entry:                   |    __ieee80211_subif_start_xmit() {
         dnsmasq-25107 [002] 98228.755632: funcgraph_entry:        1.726 us   |      ieee80211_build_hdr();
         dnsmasq-25107 [002] 98228.755634: funcgraph_entry:                   |      ieee80211_xmit() {
         dnsmasq-25107 [002] 98228.755635: funcgraph_entry:        0.356 us   |        ieee80211_set_qos_hdr();
         dnsmasq-25107 [002] 98228.755636: funcgraph_entry:                   |        ieee80211_tx() {
         dnsmasq-25107 [002] 98228.755637: funcgraph_entry:        0.491 us   |          ieee80211_tx_prepare();
         dnsmasq-25107 [002] 98228.755639: funcgraph_entry:        0.834 us   |          ieee80211_tx_h_select_key();
         dnsmasq-25107 [002] 98228.755643: funcgraph_entry:        0.198 us   |          ieee80211_tx_h_michael_mic_add();
         dnsmasq-25107 [002] 98228.755645: funcgraph_entry:        0.120 us   |          ieee80211_tx_set_protected();
         dnsmasq-25107 [002] 98228.755647: funcgraph_entry:        8.724 us   |          __ieee80211_tx();
         dnsmasq-25107 [002] 98228.755669: funcgraph_exit:       + 32.257 us  |        }
         dnsmasq-25107 [002] 98228.755675: funcgraph_exit:       + 40.463 us  |      }
         dnsmasq-25107 [002] 98228.755676: funcgraph_exit:       + 56.223 us  |    }
         dnsmasq-25107 [002] 98228.755676: funcgraph_exit:       + 57.636 us  |  }
          <idle>-0     [002] 98228.758095: funcgraph_entry:                   |  ieee80211_tx_status() {
          <idle>-0     [002] 98228.758106: funcgraph_entry:        0.286 us   |    ieee80211_tx_get_rates.isra.14();
          <idle>-0     [002] 98228.758117: funcgraph_exit:       + 11.453 us  |  }

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值