我是靠谱客的博主 坚强篮球,最近开发中收集的这篇文章主要介绍Linux Wireless架构总结,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

1.  无线网络驱动(ath9k_htc)

     ath9k_htc是一个基于USB接口的SoftMAC无线网络适配器。为了其驱动能正常工作,首先必须调用usb_register来注册驱动定义的usb_driver,以借助USB Core的力量来处理与USB协议相关的事件。其代码如下:

 

 
  1. static struct usb_driver ath9k_hif_usb_driver = {

  2. .name = KBUILD_MODNAME,

  3. .probe = ath9k_hif_usb_probe,

  4. .disconnect = ath9k_hif_usb_disconnect,

  5. #ifdef CONFIG_PM

  6. .suspend = ath9k_hif_usb_suspend,

  7. .resume = ath9k_hif_usb_resume,

  8. .reset_resume = ath9k_hif_usb_resume,

  9. #endif

  10. .id_table = ath9k_hif_usb_ids,

  11. .soft_unbind = 1,

  12. };

 

2. 关键数据结构

1) struct ieee80211_hw: 它包含802.11 PHY的配置硬件信息。

 

2.1 各层间关键数据接口

 

 

 

3. USB无线适配器枚举过程 

     当此基于USB接口的无线网络适配器被枚举时,ath9k_hif_usb_probe将被调用。其调用流程如下图所示:

 

3.1 struct ieee80211_ops 实例 ath9k_htc_ops(驱动实现)

       ath9k_htc_ops: mac80211通过这些回调函数回调driver的处理函数。ath9k_htc为了接受mac80211的管理,它必须首先向mac80211注册,以申明自己的存在,从而可以接受mac80211的调用。

 

 
  1. struct ieee80211_ops ath9k_htc_ops = {

  2. .tx = ath9k_htc_tx, // 发送mac80211要求发送的帧

  3. .start = ath9k_htc_start, // 第一个被attach到此硬件的net_device被enable之前被调用,之后,可以接收帧数据

  4. .stop = ath9k_htc_stop, // 最后一个被attach到此硬件的net_device被disable之后被调用,之后,不可以接收帧数据

  5. .add_interface = ath9k_htc_add_interface, // 当一个被attach到此硬件的net_device被enable时被调用

  6. .remove_interface = ath9k_htc_remove_interface, // 通知driver一个接口将要going down

  7. .config = ath9k_htc_config, // mac802.11调用它修改硬件配置

  8. .configure_filter = ath9k_htc_configure_filter, // 配置设备的接收过滤器

  9. .sta_add = ath9k_htc_sta_add,

  10. .sta_remove = ath9k_htc_sta_remove,

  11. .conf_tx = ath9k_htc_conf_tx,

  12. .bss_info_changed = ath9k_htc_bss_info_changed,

  13. .set_key = ath9k_htc_set_key,

  14. .get_tsf = ath9k_htc_get_tsf,

  15. .set_tsf = ath9k_htc_set_tsf,

  16. .reset_tsf = ath9k_htc_reset_tsf,

  17. .ampdu_action = ath9k_htc_ampdu_action,

  18. .sw_scan_start = ath9k_htc_sw_scan_start,

  19. .sw_scan_complete = ath9k_htc_sw_scan_complete,

  20. .set_rts_threshold = ath9k_htc_set_rts_threshold,

  21. .rfkill_poll = ath9k_htc_rfkill_poll_state,

  22. .set_coverage_class = ath9k_htc_set_coverage_class,

  23. .set_bitrate_mask = ath9k_htc_set_bitrate_mask,

  24. };

 

3.2 struct cfg80211_ops 实例 mac80211_config_ops(mac80211实现)  

   cfg80211_ops定义了无线配置的操作,在它的增加虚拟接口(ieee80211_add_iface)中,它将创建并注册net_device。在mac80211中,其定义如下所示:

 

 

 
  1. struct cfg80211_ops mac80211_config_ops = {

  2. .add_virtual_intf = ieee80211_add_iface, //使用给定的名字创建一个"虚拟接口",在wiphy的命名空间中创建net_device并返回

  3. .del_virtual_intf = ieee80211_del_iface, //删除由ifindex指定的"虚拟接口"

  4. .change_virtual_intf = ieee80211_change_iface,

  5. .add_key = ieee80211_add_key,

  6. .del_key = ieee80211_del_key,

  7. .get_key = ieee80211_get_key,

  8. .set_default_key = ieee80211_config_default_key,

  9. .set_default_mgmt_key = ieee80211_config_default_mgmt_key,

  10. .add_beacon = ieee80211_add_beacon,

  11. .set_beacon = ieee80211_set_beacon,

  12. .del_beacon = ieee80211_del_beacon,

  13. .add_station = ieee80211_add_station,

  14. .del_station = ieee80211_del_station,

  15. .change_station = ieee80211_change_station,

  16. .get_station = ieee80211_get_station,

  17. .dump_station = ieee80211_dump_station,

  18. .dump_survey = ieee80211_dump_survey,

  19. #ifdef CONFIG_MAC80211_MESH

  20. .add_mpath = ieee80211_add_mpath,

  21. .del_mpath = ieee80211_del_mpath,

  22. .change_mpath = ieee80211_change_mpath,

  23. .get_mpath = ieee80211_get_mpath,

  24. .dump_mpath = ieee80211_dump_mpath,

  25. .update_mesh_config = ieee80211_update_mesh_config,

  26. .get_mesh_config = ieee80211_get_mesh_config,

  27. .join_mesh = ieee80211_join_mesh,

  28. .leave_mesh = ieee80211_leave_mesh,

  29. #endif

  30. .change_bss = ieee80211_change_bss,

  31. .set_txq_params = ieee80211_set_txq_params,

  32. .set_channel = ieee80211_set_channel,

  33. .suspend = ieee80211_suspend,

  34. .resume = ieee80211_resume,

  35. .scan = ieee80211_scan,

  36. .sched_scan_start = ieee80211_sched_scan_start,

  37. .sched_scan_stop = ieee80211_sched_scan_stop,

  38. .auth = ieee80211_auth,

  39. .assoc = ieee80211_assoc,

  40. .deauth = ieee80211_deauth,

  41. .disassoc = ieee80211_disassoc,

  42. .join_ibss = ieee80211_join_ibss,

  43. .leave_ibss = ieee80211_leave_ibss,

  44. .set_wiphy_params = ieee80211_set_wiphy_params,

  45. .set_tx_power = ieee80211_set_tx_power,

  46. .get_tx_power = ieee80211_get_tx_power,

  47. .set_wds_peer = ieee80211_set_wds_peer,

  48. .rfkill_poll = ieee80211_rfkill_poll,

  49. CFG80211_TESTMODE_CMD(ieee80211_testmode_cmd)

  50. .set_power_mgmt = ieee80211_set_power_mgmt,

  51. .set_bitrate_mask = ieee80211_set_bitrate_mask,

  52. .remain_on_channel = ieee80211_remain_on_channel,

  53. .cancel_remain_on_channel = ieee80211_cancel_remain_on_channel,

  54. .mgmt_tx = ieee80211_mgmt_tx,

  55. .mgmt_tx_cancel_wait = ieee80211_mgmt_tx_cancel_wait,

  56. .set_cqm_rssi_config = ieee80211_set_cqm_rssi_config,

  57. .mgmt_frame_register = ieee80211_mgmt_frame_register,

  58. .set_antenna = ieee80211_set_antenna,

  59. .get_antenna = ieee80211_get_antenna,

  60. .set_ringparam = ieee80211_set_ringparam,

  61. .get_ringparam = ieee80211_get_ringparam,

  62. }

 

3.3 struct iw_handler_def  实例 cfg80211_wext_handler(wireless实现)

      cfg80211_wext_handler实现了wext要求的ioctl操作,将通过net_device->wireless_handlers->standard[ioctl cmd- SIOCIWFIRST]来进行调用。在net/wireless/wext-compat.c中的定义如下所示:

 

 
  1. static const iw_handler cfg80211_handlers[] = {

  2. [IW_IOCTL_IDX(SIOCGIWNAME)] = (iw_handler) cfg80211_wext_giwname,

  3. [IW_IOCTL_IDX(SIOCSIWFREQ)] = (iw_handler) cfg80211_wext_siwfreq,

  4. [IW_IOCTL_IDX(SIOCGIWFREQ)] = (iw_handler) cfg80211_wext_giwfreq,

  5. [IW_IOCTL_IDX(SIOCSIWMODE)] = (iw_handler) cfg80211_wext_siwmode,

  6. [IW_IOCTL_IDX(SIOCGIWMODE)] = (iw_handler) cfg80211_wext_giwmode,

  7. [IW_IOCTL_IDX(SIOCGIWRANGE)] = (iw_handler) cfg80211_wext_giwrange,

  8. [IW_IOCTL_IDX(SIOCSIWAP)] = (iw_handler) cfg80211_wext_siwap,

  9. [IW_IOCTL_IDX(SIOCGIWAP)] = (iw_handler) cfg80211_wext_giwap,

  10. [IW_IOCTL_IDX(SIOCSIWMLME)] = (iw_handler) cfg80211_wext_siwmlme,

  11. [IW_IOCTL_IDX(SIOCSIWSCAN)] = (iw_handler) cfg80211_wext_siwscan,

  12. [IW_IOCTL_IDX(SIOCGIWSCAN)] = (iw_handler) cfg80211_wext_giwscan,

  13. [IW_IOCTL_IDX(SIOCSIWESSID)] = (iw_handler) cfg80211_wext_siwessid,

  14. [IW_IOCTL_IDX(SIOCGIWESSID)] = (iw_handler) cfg80211_wext_giwessid,

  15. [IW_IOCTL_IDX(SIOCSIWRATE)] = (iw_handler) cfg80211_wext_siwrate,

  16. [IW_IOCTL_IDX(SIOCGIWRATE)] = (iw_handler) cfg80211_wext_giwrate,

  17. [IW_IOCTL_IDX(SIOCSIWRTS)] = (iw_handler) cfg80211_wext_siwrts,

  18. [IW_IOCTL_IDX(SIOCGIWRTS)] = (iw_handler) cfg80211_wext_giwrts,

  19. [IW_IOCTL_IDX(SIOCSIWFRAG)] = (iw_handler) cfg80211_wext_siwfrag,

  20. [IW_IOCTL_IDX(SIOCGIWFRAG)] = (iw_handler) cfg80211_wext_giwfrag,

  21. [IW_IOCTL_IDX(SIOCSIWTXPOW)] = (iw_handler) cfg80211_wext_siwtxpower,

  22. [IW_IOCTL_IDX(SIOCGIWTXPOW)] = (iw_handler) cfg80211_wext_giwtxpower,

  23. [IW_IOCTL_IDX(SIOCSIWRETRY)] = (iw_handler) cfg80211_wext_siwretry,

  24. [IW_IOCTL_IDX(SIOCGIWRETRY)] = (iw_handler) cfg80211_wext_giwretry,

  25. [IW_IOCTL_IDX(SIOCSIWENCODE)] = (iw_handler) cfg80211_wext_siwencode,

  26. [IW_IOCTL_IDX(SIOCGIWENCODE)] = (iw_handler) cfg80211_wext_giwencode,

  27. [IW_IOCTL_IDX(SIOCSIWPOWER)] = (iw_handler) cfg80211_wext_siwpower,

  28. [IW_IOCTL_IDX(SIOCGIWPOWER)] = (iw_handler) cfg80211_wext_giwpower,

  29. [IW_IOCTL_IDX(SIOCSIWGENIE)] = (iw_handler) cfg80211_wext_siwgenie,

  30. [IW_IOCTL_IDX(SIOCSIWAUTH)] = (iw_handler) cfg80211_wext_siwauth,

  31. [IW_IOCTL_IDX(SIOCGIWAUTH)] = (iw_handler) cfg80211_wext_giwauth,

  32. [IW_IOCTL_IDX(SIOCSIWENCODEEXT)]= (iw_handler) cfg80211_wext_siwencodeext,

  33. [IW_IOCTL_IDX(SIOCSIWPMKSA)] = (iw_handler) cfg80211_wext_siwpmksa,

  34. [IW_IOCTL_IDX(SIOCSIWPRIV)] = (iw_handler)cfg80211_wext_setpriv

  35. };

  36.  
  37. const struct iw_handler_def cfg80211_wext_handler = {

  38. .num_standard = ARRAY_SIZE(cfg80211_handlers),

  39. .standard = cfg80211_handlers,

  40. .get_wireless_stats = cfg80211_wireless_stats,

  41. }


 

 

4. 创建并注册net_device

             当执行mac80211_config_ops-> ieee80211_add_iface时,它将创建net_device和对应的ieee80211_sub_if_data, 然后主要做了以下几件事:

        1) 把net_device对应的名字增加到/sys/class/net/目录下   

        2) 把新创建的net_device插入到init_net->dev_base_head中

        3) 通知上层协议,有一个新的net_device出现了,大家可以使用它了

        4) 把新创建的ieee80211_sub_if_data增加到ieee80211_local的interfaces列表中        

        其流程如下图所示:

 

        mac80211中定义的net_device_ops ieee80211_dataif_ops,以下这些方法,都有一个struct net_device参数。其具体定义如下:   

 

 
  1. static const struct net_device_ops ieee80211_dataif_ops = {

  2. .ndo_open = ieee80211_open, // net_device变换到 UP 时被调用

  3. .ndo_stop = ieee80211_stop, // net_device变换到 Down 时被调用

  4. .ndo_uninit = ieee80211_teardown_sdata, // 取消注册或注册失败时调用

  5. .ndo_start_xmit = ieee80211_subif_start_xmit, // 需要发送包时被调用

  6. .ndo_set_multicast_list = ieee80211_set_multicast_list,// 多播地址列表变化时被调用

  7. .ndo_change_mtu = ieee80211_change_mtu, // 当用户想改变一个设备的MTU时被调用

  8. .ndo_set_mac_address = ieee80211_change_mac, // mac地址需要改变时被调用

  9. .ndo_select_queue = ieee80211_netdev_select_queue, //当net_device支持多个发送队列时,用来决定使用哪个队列

  10. };


  mac80211中初始化net_device->netdev_ops:

 

 

 
  1. static void ieee80211_if_setup(struct net_device *dev)

  2. {

  3. ether_setup(dev);

  4. dev->priv_flags &= ~IFF_TX_SKB_SHARING;

  5. dev->netdev_ops = &ieee80211_dataif_ops;

  6. dev->destructor = free_netdev;

  7. }

 

5. 数据接收(Data RX)流程

   数据接收流程如下图所示:

IP层与TCP/UDP层接口定义如下:

 

 
  1. static const struct net_protocol tcp_protocol = {

  2. .handler = tcp_v4_rcv,

  3. .err_handler = tcp_v4_err,

  4. .gso_send_check = tcp_v4_gso_send_check,

  5. .gso_segment = tcp_tso_segment,

  6. .gro_receive = tcp4_gro_receive,

  7. .gro_complete = tcp4_gro_complete,

  8. .no_policy = 1,

  9. .netns_ok = 1,

  10. };

  11.  
  12. static const struct net_protocol udp_protocol = {

  13. .handler = udp_rcv,

  14. .err_handler = udp_err,

  15. .gso_send_check = udp4_ufo_send_check,

  16. .gso_segment = udp4_ufo_fragment,

  17. .no_policy = 1,

  18. .netns_ok = 1,

  19. };

  20.  
  21. static const struct net_protocol icmp_protocol = {

  22. .handler = icmp_rcv,

  23. .err_handler = ping_err,

  24. .no_policy = 1,

  25. .netns_ok = 1,

  26. };


IP层与net/core层接口定义如下:

 

 

 
  1. static struct packet_type ip_packet_type __read_mostly = {

  2. .type = cpu_to_be16(ETH_P_IP),

  3. .func = ip_rcv,

  4. .gso_send_check = inet_gso_send_check,

  5. .gso_segment = inet_gso_segment,

  6. .gro_receive = inet_gro_receive,

  7. .gro_complete = inet_gro_complete,

  8. };


 

 

 

接收下半部stack如下所示:

 

 
  1. [ 336.646628] [<c07d8b24>] (tcp_rcv_established+0x648/0x9b0) from [<c07e04cc>] (tcp_v4_do_rcv+0x74/0x2a8)

  2. [ 336.646661] [<c07e04cc>] (tcp_v4_do_rcv+0x74/0x2a8) from [<c07e0c40>] (tcp_v4_rcv+0x540/0x908)

  3. [ 336.646678] [<c07e0c40>] (tcp_v4_rcv+0x540/0x908) from [<c07c23d4>] (ip_local_deliver_finish+0x158/0x318)

  4. [ 336.646694] [<c07c23d4>] (ip_local_deliver_finish+0x158/0x318) from [<c07c1e44>] (ip_rcv_finish+0x420/0x440)

  5. [ 336.646715] [<c07c1e44>] (ip_rcv_finish+0x420/0x440) from [<c0772dcc>] (__netif_receive_skb+0x4d0/0x534)

  6. [ 336.646730] [<c0772dcc>] (__netif_receive_skb+0x4d0/0x534) from [<c0774434>] (netif_receive_skb+0x9c/0xb4)

  7. [ 336.646752] [<c0774434>] (netif_receive_skb+0x9c/0xb4) from [<c08b8e6c>] (ieee80211_deliver_skb+0x134/0x164)

  8. [ 336.646769] [<c08b8e6c>] (ieee80211_deliver_skb+0x134/0x164) from [<c08b9ed8>] (ieee80211_rx_handlers+0x103c/0x1978)

  9. [ 336.646785] [<c08b9ed8>] (ieee80211_rx_handlers+0x103c/0x1978) from [<c08baf10>] (ieee80211_prepare_and_rx_handle+0x6fc/0x788)

  10. [ 336.646802] [<c08baf10>] (ieee80211_prepare_and_rx_handle+0x6fc/0x788) from [<c08bb920>] (ieee80211_rx+0x908/0x988)

  11. [ 336.646819] [<c08bb920>] (ieee80211_rx+0x908/0x988) from [<c068a578>] (ath9k_rx_tasklet+0x4e4/0x54c)

  12. [ 336.646835] [<c068a578>] (ath9k_rx_tasklet+0x4e4/0x54c) from [<c0467d98>] (tasklet_action+0xa8/0x14c)

  13. [ 336.646850] [<c0467d98>] (tasklet_action+0xa8/0x14c) from [<c0468144>] (__do_softirq+0x88/0x158)

  14. [ 336.646863] [<c0468144>] (__do_softirq+0x88/0x158) from [<c0468414>] (irq_exit+0x48/0xac)

  15. [ 336.646882] [<c0468414>] (irq_exit+0x48/0xac) from [<c04313c0>] (do_local_timer+0x50/0x80)

  16. [ 336.646898] [<c04313c0>] (do_local_timer+0x50/0x80) from [<c0436708>] (__irq_svc+0x48/0xe0)


 

 

6. 数据发送(Data TX)流珵

   数据发送流程如下图所示:

上半部分涉及到的相关代码如下所示(以上流程主要通过dump_stack获取):

     net/socket.c
     net/ipv4/af_net.c
     net/ipv4/tcp.c
     net/ipv4/tcp_output.c
     net/ipv4/ip_output.c
     net/core/neighbour.c
     net/core/dev.c

 

7. INET初始化

    INET为Linux OS实现了TCP/IP协议集,它使用BSD Socket接口作为与User通讯的方式。其初始化代码如下所示:

    代码位于:net/ipv4/af_inet.c。

 

 
  1. static int __init inet_init(void)

  2. {

  3. struct sk_buff *dummy_skb;

  4. struct inet_protosw *q;

  5. struct list_head *r;

  6. int rc = -EINVAL;

  7.  
  8. BUILD_BUG_ON(sizeof(struct inet_skb_parm) > sizeof(dummy_skb->cb));

  9.  
  10. sysctl_local_reserved_ports = kzalloc(65536 / 8, GFP_KERNEL);

  11. if (!sysctl_local_reserved_ports)

  12. goto out;

  13.  
  14. rc = proto_register(&tcp_prot, 1);

  15. if (rc)

  16. goto out_free_reserved_ports;

  17.  
  18. rc = proto_register(&udp_prot, 1);

  19. if (rc)

  20. goto out_unregister_tcp_proto;

  21.  
  22. rc = proto_register(&raw_prot, 1);

  23. if (rc)

  24. goto out_unregister_udp_proto;

  25.  
  26. rc = proto_register(&ping_prot, 1);

  27. if (rc)

  28. goto out_unregister_raw_proto;

  29.  
  30. /*

  31. * Tell SOCKET that we are alive...

  32. */

  33.  
  34. (void)sock_register(&inet_family_ops);

  35.  
  36. #ifdef CONFIG_SYSCTL

  37. ip_static_sysctl_init();

  38. #endif

  39.  
  40. /*

  41. * Add all the base protocols.

  42. */

  43.  
  44. if (inet_add_protocol(&icmp_protocol, IPPROTO_ICMP) < 0)

  45. printk(KERN_CRIT "inet_init: Cannot add ICMP protocoln");

  46. if (inet_add_protocol(&udp_protocol, IPPROTO_UDP) < 0)

  47. printk(KERN_CRIT "inet_init: Cannot add UDP protocoln");

  48. if (inet_add_protocol(&tcp_protocol, IPPROTO_TCP) < 0)

  49. printk(KERN_CRIT "inet_init: Cannot add TCP protocoln");

  50. #ifdef CONFIG_IP_MULTICAST

  51. if (inet_add_protocol(&igmp_protocol, IPPROTO_IGMP) < 0)

  52. printk(KERN_CRIT "inet_init: Cannot add IGMP protocoln");

  53. #endif

  54.  
  55. /* Register the socket-side information for inet_create. */

  56. for (r = &inetsw[0]; r < &inetsw[SOCK_MAX]; ++r)

  57. INIT_LIST_HEAD(r);

  58.  
  59. for (q = inetsw_array; q < &inetsw_array[INETSW_ARRAY_LEN]; ++q)

  60. inet_register_protosw(q);

  61.  
  62. /*

  63. * Set the ARP module up

  64. */

  65.  
  66. arp_init();

  67.  
  68. /*

  69. * Set the IP module up

  70. */

  71.  
  72. ip_init();

  73.  
  74. tcp_v4_init();

  75.  
  76. /* Setup TCP slab cache for open requests. */

  77. tcp_init();

  78.  
  79. /* Setup UDP memory threshold */

  80. udp_init();

  81.  
  82. /* Add UDP-Lite (RFC 3828) */

  83. udplite4_register();

  84.  
  85. ping_init();

  86.  
  87. /*

  88. * Set the ICMP layer up

  89. */

  90.  
  91. if (icmp_init() < 0)

  92. panic("Failed to create the ICMP control socket.n");

  93.  
  94. /*

  95. * Initialise the multicast router

  96. */

  97. #if defined(CONFIG_IP_MROUTE)

  98. if (ip_mr_init())

  99. printk(KERN_CRIT "inet_init: Cannot init ipv4 mrouten");

  100. #endif

  101. /*

  102. * Initialise per-cpu ipv4 mibs

  103. */

  104.  
  105. if (init_ipv4_mibs())

  106. printk(KERN_CRIT "inet_init: Cannot init ipv4 mibsn");

  107.  
  108. ipv4_proc_init();

  109.  
  110. ipfrag_init();

  111.  
  112. dev_add_pack(&ip_packet_type);

  113.  
  114. rc = 0;

  115. out:

  116. return rc;

  117. out_unregister_raw_proto:

  118. proto_unregister(&raw_prot);

  119. out_unregister_udp_proto:

  120. proto_unregister(&udp_prot);

  121. out_unregister_tcp_proto:

  122. proto_unregister(&tcp_prot);

  123. out_free_reserved_ports:

  124. kfree(sysctl_local_reserved_ports);

  125. goto out;

  126. }


 

 

 

 

 

 

最后

以上就是坚强篮球为你收集整理的Linux Wireless架构总结的全部内容,希望文章能够帮你解决Linux Wireless架构总结所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(55)

评论列表共有 0 条评论

立即
投稿
返回
顶部