Linux Wireless架构总结
来源:互联网 发布:打车软件对比分析 编辑:程序博客网 时间:2024/05/16 04:43
1、无线网络驱动(ath9k_htc)
- static struct usb_driver ath9k_hif_usb_driver = {
- .name = KBUILD_MODNAME,
- .probe = ath9k_hif_usb_probe,
- .disconnect = ath9k_hif_usb_disconnect,
- #ifdef CONFIG_PM
- .suspend = ath9k_hif_usb_suspend,
- .resume = ath9k_hif_usb_resume,
- .reset_resume = ath9k_hif_usb_resume,
- #endif
- .id_table = ath9k_hif_usb_ids,
- .soft_unbind = 1,
- };
static struct usb_driver ath9k_hif_usb_driver = { .name = KBUILD_MODNAME, .probe = ath9k_hif_usb_probe, .disconnect = ath9k_hif_usb_disconnect,
ifdef CONFIG_PM
.suspend = ath9k_hif_usb_suspend, .resume = ath9k_hif_usb_resume, .reset_resume = ath9k_hif_usb_resume,
endif
.id_table = ath9k_hif_usb_ids, .soft_unbind = 1,
};
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的调用。
- struct ieee80211_ops ath9k_htc_ops = {
- .tx = ath9k_htc_tx, // 发送mac80211要求发送的帧
- .start = ath9k_htc_start, // 第一个被attach到此硬件的net_device被enable之前被调用,之后,可以接收帧数据
- .stop = ath9k_htc_stop, // 最后一个被attach到此硬件的net_device被disable之后被调用,之后,不可以接收帧数据
- .add_interface = ath9k_htc_add_interface, // 当一个被attach到此硬件的net_device被enable时被调用
- .remove_interface = ath9k_htc_remove_interface, // 通知driver一个接口将要going down
- .config = ath9k_htc_config, // mac802.11调用它修改硬件配置
- .configure_filter = ath9k_htc_configure_filter, // 配置设备的接收过滤器
- .sta_add = ath9k_htc_sta_add,
- .sta_remove = ath9k_htc_sta_remove,
- .conf_tx = ath9k_htc_conf_tx,
- .bss_info_changed = ath9k_htc_bss_info_changed,
- .set_key = ath9k_htc_set_key,
- .get_tsf = ath9k_htc_get_tsf,
- .set_tsf = ath9k_htc_set_tsf,
- .reset_tsf = ath9k_htc_reset_tsf,
- .ampdu_action = ath9k_htc_ampdu_action,
- .sw_scan_start = ath9k_htc_sw_scan_start,
- .sw_scan_complete = ath9k_htc_sw_scan_complete,
- .set_rts_threshold = ath9k_htc_set_rts_threshold,
- .rfkill_poll = ath9k_htc_rfkill_poll_state,
- .set_coverage_class = ath9k_htc_set_coverage_class,
- .set_bitrate_mask = ath9k_htc_set_bitrate_mask,
- };
struct ieee80211_ops ath9k_htc_ops = { .tx = ath9k_htc_tx, // 发送mac80211要求发送的帧 .start = ath9k_htc_start, // 第一个被attach到此硬件的net_device被enable之前被调用,之后,可以接收帧数据 .stop = ath9k_htc_stop, // 最后一个被attach到此硬件的net_device被disable之后被调用,之后,不可以接收帧数据 .add_interface = ath9k_htc_add_interface, // 当一个被attach到此硬件的net_device被enable时被调用 .remove_interface = ath9k_htc_remove_interface, // 通知driver一个接口将要going down .config = ath9k_htc_config, // mac802.11调用它修改硬件配置 .configure_filter = ath9k_htc_configure_filter, // 配置设备的接收过滤器 .sta_add = ath9k_htc_sta_add, .sta_remove = ath9k_htc_sta_remove, .conf_tx = ath9k_htc_conf_tx, .bss_info_changed = ath9k_htc_bss_info_changed, .set_key = ath9k_htc_set_key, .get_tsf = ath9k_htc_get_tsf, .set_tsf = ath9k_htc_set_tsf, .reset_tsf = ath9k_htc_reset_tsf, .ampdu_action = ath9k_htc_ampdu_action, .sw_scan_start = ath9k_htc_sw_scan_start, .sw_scan_complete = ath9k_htc_sw_scan_complete, .set_rts_threshold = ath9k_htc_set_rts_threshold, .rfkill_poll = ath9k_htc_rfkill_poll_state, .set_coverage_class = ath9k_htc_set_coverage_class, .set_bitrate_mask = ath9k_htc_set_bitrate_mask, };
3.2 struct cfg80211_ops 实例 mac80211_config_ops(mac80211实现)
cfg80211_ops定义了无线配置的操作,在它的增加虚拟接口(ieee80211_add_iface)中,它将创建并注册net_device。在mac80211中,其定义如下所示:
- struct cfg80211_ops mac80211_config_ops = {
- .add_virtual_intf = ieee80211_add_iface, //使用给定的名字创建一个”虚拟接口”,在wiphy的命名空间中创建net_device并返回
- .del_virtual_intf = ieee80211_del_iface, //删除由ifindex指定的”虚拟接口”
- .change_virtual_intf = ieee80211_change_iface,
- .add_key = ieee80211_add_key,
- .del_key = ieee80211_del_key,
- .get_key = ieee80211_get_key,
- .set_default_key = ieee80211_config_default_key,
- .set_default_mgmt_key = ieee80211_config_default_mgmt_key,
- .add_beacon = ieee80211_add_beacon,
- .set_beacon = ieee80211_set_beacon,
- .del_beacon = ieee80211_del_beacon,
- .add_station = ieee80211_add_station,
- .del_station = ieee80211_del_station,
- .change_station = ieee80211_change_station,
- .get_station = ieee80211_get_station,
- .dump_station = ieee80211_dump_station,
- .dump_survey = ieee80211_dump_survey,
- #ifdef CONFIG_MAC80211_MESH
- .add_mpath = ieee80211_add_mpath,
- .del_mpath = ieee80211_del_mpath,
- .change_mpath = ieee80211_change_mpath,
- .get_mpath = ieee80211_get_mpath,
- .dump_mpath = ieee80211_dump_mpath,
- .update_mesh_config = ieee80211_update_mesh_config,
- .get_mesh_config = ieee80211_get_mesh_config,
- .join_mesh = ieee80211_join_mesh,
- .leave_mesh = ieee80211_leave_mesh,
- #endif
- .change_bss = ieee80211_change_bss,
- .set_txq_params = ieee80211_set_txq_params,
- .set_channel = ieee80211_set_channel,
- .suspend = ieee80211_suspend,
- .resume = ieee80211_resume,
- .scan = ieee80211_scan,
- .sched_scan_start = ieee80211_sched_scan_start,
- .sched_scan_stop = ieee80211_sched_scan_stop,
- .auth = ieee80211_auth,
- .assoc = ieee80211_assoc,
- .deauth = ieee80211_deauth,
- .disassoc = ieee80211_disassoc,
- .join_ibss = ieee80211_join_ibss,
- .leave_ibss = ieee80211_leave_ibss,
- .set_wiphy_params = ieee80211_set_wiphy_params,
- .set_tx_power = ieee80211_set_tx_power,
- .get_tx_power = ieee80211_get_tx_power,
- .set_wds_peer = ieee80211_set_wds_peer,
- .rfkill_poll = ieee80211_rfkill_poll,
- CFG80211_TESTMODE_CMD(ieee80211_testmode_cmd)
- .set_power_mgmt = ieee80211_set_power_mgmt,
- .set_bitrate_mask = ieee80211_set_bitrate_mask,
- .remain_on_channel = ieee80211_remain_on_channel,
- .cancel_remain_on_channel = ieee80211_cancel_remain_on_channel,
- .mgmt_tx = ieee80211_mgmt_tx,
- .mgmt_tx_cancel_wait = ieee80211_mgmt_tx_cancel_wait,
- .set_cqm_rssi_config = ieee80211_set_cqm_rssi_config,
- .mgmt_frame_register = ieee80211_mgmt_frame_register,
- .set_antenna = ieee80211_set_antenna,
- .get_antenna = ieee80211_get_antenna,
- .set_ringparam = ieee80211_set_ringparam,
- .get_ringparam = ieee80211_get_ringparam,
- }
struct cfg80211_ops mac80211_config_ops = { .add_virtual_intf = ieee80211_add_iface, //使用给定的名字创建一个"虚拟接口",在wiphy的命名空间中创建net_device并返回 .del_virtual_intf = ieee80211_del_iface, //删除由ifindex指定的"虚拟接口" .change_virtual_intf = ieee80211_change_iface, .add_key = ieee80211_add_key, .del_key = ieee80211_del_key, .get_key = ieee80211_get_key, .set_default_key = ieee80211_config_default_key, .set_default_mgmt_key = ieee80211_config_default_mgmt_key, .add_beacon = ieee80211_add_beacon, .set_beacon = ieee80211_set_beacon, .del_beacon = ieee80211_del_beacon, .add_station = ieee80211_add_station, .del_station = ieee80211_del_station, .change_station = ieee80211_change_station, .get_station = ieee80211_get_station, .dump_station = ieee80211_dump_station, .dump_survey = ieee80211_dump_survey,#ifdef CONFIG_MAC80211_MESH .add_mpath = ieee80211_add_mpath, .del_mpath = ieee80211_del_mpath, .change_mpath = ieee80211_change_mpath, .get_mpath = ieee80211_get_mpath, .dump_mpath = ieee80211_dump_mpath, .update_mesh_config = ieee80211_update_mesh_config, .get_mesh_config = ieee80211_get_mesh_config, .join_mesh = ieee80211_join_mesh, .leave_mesh = ieee80211_leave_mesh, #endif .change_bss = ieee80211_change_bss, .set_txq_params = ieee80211_set_txq_params, .set_channel = ieee80211_set_channel, .suspend = ieee80211_suspend, .resume = ieee80211_resume, .scan = ieee80211_scan, .sched_scan_start = ieee80211_sched_scan_start, .sched_scan_stop = ieee80211_sched_scan_stop, .auth = ieee80211_auth, .assoc = ieee80211_assoc, .deauth = ieee80211_deauth, .disassoc = ieee80211_disassoc, .join_ibss = ieee80211_join_ibss, .leave_ibss = ieee80211_leave_ibss, .set_wiphy_params = ieee80211_set_wiphy_params, .set_tx_power = ieee80211_set_tx_power, .get_tx_power = ieee80211_get_tx_power, .set_wds_peer = ieee80211_set_wds_peer, .rfkill_poll = ieee80211_rfkill_poll, CFG80211_TESTMODE_CMD(ieee80211_testmode_cmd) .set_power_mgmt = ieee80211_set_power_mgmt, .set_bitrate_mask = ieee80211_set_bitrate_mask, .remain_on_channel = ieee80211_remain_on_channel, .cancel_remain_on_channel = ieee80211_cancel_remain_on_channel, .mgmt_tx = ieee80211_mgmt_tx, .mgmt_tx_cancel_wait = ieee80211_mgmt_tx_cancel_wait, .set_cqm_rssi_config = ieee80211_set_cqm_rssi_config, .mgmt_frame_register = ieee80211_mgmt_frame_register, .set_antenna = ieee80211_set_antenna, .get_antenna = ieee80211_get_antenna, .set_ringparam = ieee80211_set_ringparam, .get_ringparam = ieee80211_get_ringparam, }
cfg80211_wext_handler实现了wext要求的ioctl操作,将通过net_device->wireless_handlers->standard[ioctl cmd- SIOCIWFIRST]来进行调用。在net/wireless/wext-compat.c中的定义如下所示:
- tatic const iw_handler cfg80211_handlers[] = {
- [IW_IOCTL_IDX(SIOCGIWNAME)] = (iw_handler) cfg80211_wext_giwname,
- [IW_IOCTL_IDX(SIOCSIWFREQ)] = (iw_handler) cfg80211_wext_siwfreq,
- [IW_IOCTL_IDX(SIOCGIWFREQ)] = (iw_handler) cfg80211_wext_giwfreq,
- [IW_IOCTL_IDX(SIOCSIWMODE)] = (iw_handler) cfg80211_wext_siwmode,
- [IW_IOCTL_IDX(SIOCGIWMODE)] = (iw_handler) cfg80211_wext_giwmode,
- [IW_IOCTL_IDX(SIOCGIWRANGE)] = (iw_handler) cfg80211_wext_giwrange,
- [IW_IOCTL_IDX(SIOCSIWAP)] = (iw_handler) cfg80211_wext_siwap,
- [IW_IOCTL_IDX(SIOCGIWAP)] = (iw_handler) cfg80211_wext_giwap,
- [IW_IOCTL_IDX(SIOCSIWMLME)] = (iw_handler) cfg80211_wext_siwmlme,
- [IW_IOCTL_IDX(SIOCSIWSCAN)] = (iw_handler) cfg80211_wext_siwscan,
- [IW_IOCTL_IDX(SIOCGIWSCAN)] = (iw_handler) cfg80211_wext_giwscan,
- [IW_IOCTL_IDX(SIOCSIWESSID)] = (iw_handler) cfg80211_wext_siwessid,
- [IW_IOCTL_IDX(SIOCGIWESSID)] = (iw_handler) cfg80211_wext_giwessid,
- [IW_IOCTL_IDX(SIOCSIWRATE)] = (iw_handler) cfg80211_wext_siwrate,
- [IW_IOCTL_IDX(SIOCGIWRATE)] = (iw_handler) cfg80211_wext_giwrate,
- [IW_IOCTL_IDX(SIOCSIWRTS)] = (iw_handler) cfg80211_wext_siwrts,
- [IW_IOCTL_IDX(SIOCGIWRTS)] = (iw_handler) cfg80211_wext_giwrts,
- [IW_IOCTL_IDX(SIOCSIWFRAG)] = (iw_handler) cfg80211_wext_siwfrag,
- [IW_IOCTL_IDX(SIOCGIWFRAG)] = (iw_handler) cfg80211_wext_giwfrag,
- [IW_IOCTL_IDX(SIOCSIWTXPOW)] = (iw_handler) cfg80211_wext_siwtxpower,
- [IW_IOCTL_IDX(SIOCGIWTXPOW)] = (iw_handler) cfg80211_wext_giwtxpower,
- [IW_IOCTL_IDX(SIOCSIWRETRY)] = (iw_handler) cfg80211_wext_siwretry,
- [IW_IOCTL_IDX(SIOCGIWRETRY)] = (iw_handler) cfg80211_wext_giwretry,
- [IW_IOCTL_IDX(SIOCSIWENCODE)] = (iw_handler) cfg80211_wext_siwencode,
- [IW_IOCTL_IDX(SIOCGIWENCODE)] = (iw_handler) cfg80211_wext_giwencode,
- [IW_IOCTL_IDX(SIOCSIWPOWER)] = (iw_handler) cfg80211_wext_siwpower,
- [IW_IOCTL_IDX(SIOCGIWPOWER)] = (iw_handler) cfg80211_wext_giwpower,
- [IW_IOCTL_IDX(SIOCSIWGENIE)] = (iw_handler) cfg80211_wext_siwgenie,
- [IW_IOCTL_IDX(SIOCSIWAUTH)] = (iw_handler) cfg80211_wext_siwauth,
- [IW_IOCTL_IDX(SIOCGIWAUTH)] = (iw_handler) cfg80211_wext_giwauth,
- [IW_IOCTL_IDX(SIOCSIWENCODEEXT)]= (iw_handler) cfg80211_wext_siwencodeext,
- [IW_IOCTL_IDX(SIOCSIWPMKSA)] = (iw_handler) cfg80211_wext_siwpmksa,
- [IW_IOCTL_IDX(SIOCSIWPRIV)] = (iw_handler)cfg80211_wext_setpriv
- };
- const struct iw_handler_def cfg80211_wext_handler = {
- .num_standard = ARRAY_SIZE(cfg80211_handlers),
- .standard = cfg80211_handlers,
- .get_wireless_stats = cfg80211_wireless_stats,
tatic const iw_handler cfg80211_handlers[] = { [IW_IOCTL_IDX(SIOCGIWNAME)] = (iw_handler) cfg80211_wext_giwname, [IW_IOCTL_IDX(SIOCSIWFREQ)] = (iw_handler) cfg80211_wext_siwfreq, [IW_IOCTL_IDX(SIOCGIWFREQ)] = (iw_handler) cfg80211_wext_giwfreq, [IW_IOCTL_IDX(SIOCSIWMODE)] = (iw_handler) cfg80211_wext_siwmode, [IW_IOCTL_IDX(SIOCGIWMODE)] = (iw_handler) cfg80211_wext_giwmode, [IW_IOCTL_IDX(SIOCGIWRANGE)] = (iw_handler) cfg80211_wext_giwrange, [IW_IOCTL_IDX(SIOCSIWAP)] = (iw_handler) cfg80211_wext_siwap, [IW_IOCTL_IDX(SIOCGIWAP)] = (iw_handler) cfg80211_wext_giwap, [IW_IOCTL_IDX(SIOCSIWMLME)] = (iw_handler) cfg80211_wext_siwmlme, [IW_IOCTL_IDX(SIOCSIWSCAN)] = (iw_handler) cfg80211_wext_siwscan, [IW_IOCTL_IDX(SIOCGIWSCAN)] = (iw_handler) cfg80211_wext_giwscan, [IW_IOCTL_IDX(SIOCSIWESSID)] = (iw_handler) cfg80211_wext_siwessid, [IW_IOCTL_IDX(SIOCGIWESSID)] = (iw_handler) cfg80211_wext_giwessid, [IW_IOCTL_IDX(SIOCSIWRATE)] = (iw_handler) cfg80211_wext_siwrate, [IW_IOCTL_IDX(SIOCGIWRATE)] = (iw_handler) cfg80211_wext_giwrate, [IW_IOCTL_IDX(SIOCSIWRTS)] = (iw_handler) cfg80211_wext_siwrts, [IW_IOCTL_IDX(SIOCGIWRTS)] = (iw_handler) cfg80211_wext_giwrts, [IW_IOCTL_IDX(SIOCSIWFRAG)] = (iw_handler) cfg80211_wext_siwfrag, [IW_IOCTL_IDX(SIOCGIWFRAG)] = (iw_handler) cfg80211_wext_giwfrag, [IW_IOCTL_IDX(SIOCSIWTXPOW)] = (iw_handler) cfg80211_wext_siwtxpower, [IW_IOCTL_IDX(SIOCGIWTXPOW)] = (iw_handler) cfg80211_wext_giwtxpower, [IW_IOCTL_IDX(SIOCSIWRETRY)] = (iw_handler) cfg80211_wext_siwretry, [IW_IOCTL_IDX(SIOCGIWRETRY)] = (iw_handler) cfg80211_wext_giwretry, [IW_IOCTL_IDX(SIOCSIWENCODE)] = (iw_handler) cfg80211_wext_siwencode, [IW_IOCTL_IDX(SIOCGIWENCODE)] = (iw_handler) cfg80211_wext_giwencode, [IW_IOCTL_IDX(SIOCSIWPOWER)] = (iw_handler) cfg80211_wext_siwpower, [IW_IOCTL_IDX(SIOCGIWPOWER)] = (iw_handler) cfg80211_wext_giwpower, [IW_IOCTL_IDX(SIOCSIWGENIE)] = (iw_handler) cfg80211_wext_siwgenie, [IW_IOCTL_IDX(SIOCSIWAUTH)] = (iw_handler) cfg80211_wext_siwauth, [IW_IOCTL_IDX(SIOCGIWAUTH)] = (iw_handler) cfg80211_wext_giwauth, [IW_IOCTL_IDX(SIOCSIWENCODEEXT)]= (iw_handler) cfg80211_wext_siwencodeext, [IW_IOCTL_IDX(SIOCSIWPMKSA)] = (iw_handler) cfg80211_wext_siwpmksa, [IW_IOCTL_IDX(SIOCSIWPRIV)] = (iw_handler)cfg80211_wext_setpriv }; const struct iw_handler_def cfg80211_wext_handler = { .num_standard = ARRAY_SIZE(cfg80211_handlers), .standard = cfg80211_handlers, .get_wireless_stats = cfg80211_wireless_stats,
当执行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参数。其具体定义如下:
- static const struct net_device_ops ieee80211_dataif_ops = {
- .ndo_open = ieee80211_open, // net_device变换到 UP 时被调用
- .ndo_stop = ieee80211_stop, // net_device变换到 Down 时被调用
- .ndo_uninit = ieee80211_teardown_sdata, // 取消注册或注册失败时调用
- .ndo_start_xmit = ieee80211_subif_start_xmit, // 需要发送包时被调用
- .ndo_set_multicast_list = ieee80211_set_multicast_list,// 多播地址列表变化时被调用
- .ndo_change_mtu = ieee80211_change_mtu, // 当用户想改变一个设备的MTU时被调用
- .ndo_set_mac_address = ieee80211_change_mac, // mac地址需要改变时被调用
- .ndo_select_queue = ieee80211_netdev_select_queue, //当net_device支持多个发送队列时,用来决定使用哪个队列
- };
static const struct net_device_ops ieee80211_dataif_ops = { .ndo_open = ieee80211_open, // net_device变换到 UP 时被调用 .ndo_stop = ieee80211_stop, // net_device变换到 Down 时被调用 .ndo_uninit = ieee80211_teardown_sdata, // 取消注册或注册失败时调用 .ndo_start_xmit = ieee80211_subif_start_xmit, // 需要发送包时被调用 .ndo_set_multicast_list = ieee80211_set_multicast_list,// 多播地址列表变化时被调用 .ndo_change_mtu = ieee80211_change_mtu, // 当用户想改变一个设备的MTU时被调用 .ndo_set_mac_address = ieee80211_change_mac, // mac地址需要改变时被调用 .ndo_select_queue = ieee80211_netdev_select_queue, //当net_device支持多个发送队列时,用来决定使用哪个队列 };
mac80211中初始化net_device->netdev_ops:
- static void ieee80211_if_setup(struct net_device *dev)
- {
- ether_setup(dev);
- dev->priv_flags &= ~IFF_TX_SKB_SHARING;
- dev->netdev_ops = &ieee80211_dataif_ops;
- dev->destructor = free_netdev;
- }
static void ieee80211_if_setup(struct net_device *dev) { ether_setup(dev); dev->priv_flags &= ~IFF_TX_SKB_SHARING; dev->netdev_ops = &ieee80211_dataif_ops; dev->destructor = free_netdev; }
5. 数据接收(Data RX)流程
数据接收流程如下图所示:
IP层与TCP/UDP层接口定义如下:
- static const struct net_protocol tcp_protocol = {
- .handler = tcp_v4_rcv,
- .err_handler = tcp_v4_err,
- .gso_send_check = tcp_v4_gso_send_check,
- .gso_segment = tcp_tso_segment,
- .gro_receive = tcp4_gro_receive,
- .gro_complete = tcp4_gro_complete,
- .no_policy = 1,
- .netns_ok = 1,
- };
- static const struct net_protocol udp_protocol = {
- .handler = udp_rcv,
- .err_handler = udp_err,
- .gso_send_check = udp4_ufo_send_check,
- .gso_segment = udp4_ufo_fragment,
- .no_policy = 1,
- .netns_ok = 1,
- };
- static const struct net_protocol icmp_protocol = {
- .handler = icmp_rcv,
- .err_handler = ping_err,
- .no_policy = 1,
- .netns_ok = 1,
- };
static const struct net_protocol tcp_protocol = { .handler = tcp_v4_rcv, .err_handler = tcp_v4_err, .gso_send_check = tcp_v4_gso_send_check, .gso_segment = tcp_tso_segment, .gro_receive = tcp4_gro_receive, .gro_complete = tcp4_gro_complete, .no_policy = 1, .netns_ok = 1, }; static const struct net_protocol udp_protocol = { .handler = udp_rcv, .err_handler = udp_err, .gso_send_check = udp4_ufo_send_check, .gso_segment = udp4_ufo_fragment, .no_policy = 1, .netns_ok = 1, }; static const struct net_protocol icmp_protocol = { .handler = icmp_rcv, .err_handler = ping_err, .no_policy = 1, .netns_ok = 1, };
IP层与net/core层接口定义如下
- static struct packet_type ip_packet_type __read_mostly = {
- .type = cpu_to_be16(ETH_P_IP),
- .func = ip_rcv,
- .gso_send_check = inet_gso_send_check,
- .gso_segment = inet_gso_segment,
- .gro_receive = inet_gro_receive,
- .gro_complete = inet_gro_complete,
- };
static struct packet_type ip_packet_type __read_mostly = { .type = cpu_to_be16(ETH_P_IP), .func = ip_rcv, .gso_send_check = inet_gso_send_check, .gso_segment = inet_gso_segment, .gro_receive = inet_gro_receive, .gro_complete = inet_gro_complete, };
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
- static int __init inet_init(void)
- {
- struct sk_buff *dummy_skb;
- struct inet_protosw *q;
- struct list_head *r;
- int rc = -EINVAL;
- BUILD_BUG_ON(sizeof(struct inet_skb_parm) > sizeof(dummy_skb->cb));
- sysctl_local_reserved_ports = kzalloc(65536 / 8, GFP_KERNEL);
- if (!sysctl_local_reserved_ports)
- goto out;
- rc = proto_register(&tcp_prot, 1);
- if (rc)
- goto out_free_reserved_ports;
- rc = proto_register(&udp_prot, 1);
- if (rc)
- goto out_unregister_tcp_proto;
- rc = proto_register(&raw_prot, 1);
- if (rc)
- goto out_unregister_udp_proto;
- rc = proto_register(&ping_prot, 1);
- if (rc)
- goto out_unregister_raw_proto;
- /*
- * Tell SOCKET that we are alive…
- */
- (void)sock_register(&inet_family_ops);
- #ifdef CONFIG_SYSCTL
- ip_static_sysctl_init();
- #endif
- /*
- * Add all the base protocols.
- */
- if (inet_add_protocol(&icmp_protocol, IPPROTO_ICMP) < 0)
- printk(KERN_CRIT ”inet_init: Cannot add ICMP protocol\n”);
- if (inet_add_protocol(&udp_protocol, IPPROTO_UDP) < 0)
- printk(KERN_CRIT ”inet_init: Cannot add UDP protocol\n”);
- if (inet_add_protocol(&tcp_protocol, IPPROTO_TCP) < 0)
- printk(KERN_CRIT ”inet_init: Cannot add TCP protocol\n”);
- #ifdef CONFIG_IP_MULTICAST
- if (inet_add_protocol(&igmp_protocol, IPPROTO_IGMP) < 0)
- printk(KERN_CRIT ”inet_init: Cannot add IGMP protocol\n”);
- #endif
- /* Register the socket-side information for inet_create. */
- for (r = &inetsw[0]; r < &inetsw[SOCK_MAX]; ++r)
- INIT_LIST_HEAD(r);
- for (q = inetsw_array; q < &inetsw_array[INETSW_ARRAY_LEN]; ++q)
- inet_register_protosw(q);
- /*
- * Set the ARP module up
- */
- arp_init();
- /*
- * Set the IP module up
- */
- ip_init();
- tcp_v4_init();
- /* Setup TCP slab cache for open requests. */
- tcp_init();
- /* Setup UDP memory threshold */
- udp_init();
- /* Add UDP-Lite (RFC 3828) */
- udplite4_register();
- ping_init();
- /*
- * Set the ICMP layer up
- */
- if (icmp_init() < 0)
- panic(”Failed to create the ICMP control socket.\n”);
- /*
- * Initialise the multicast router
- */
- #if defined(CONFIG_IP_MROUTE)
- if (ip_mr_init())
- printk(KERN_CRIT ”inet_init: Cannot init ipv4 mroute\n”);
- #endif
- /*
- * Initialise per-cpu ipv4 mibs
- */
- if (init_ipv4_mibs())
- printk(KERN_CRIT ”inet_init: Cannot init ipv4 mibs\n”);
- ipv4_proc_init();
- ipfrag_init();
- dev_add_pack(&ip_packet_type);
- rc = 0;
- out:
- return rc;
- out_unregister_raw_proto:
- proto_unregister(&raw_prot);
- out_unregister_udp_proto:
- proto_unregister(&udp_prot);
- out_unregister_tcp_proto:
- proto_unregister(&tcp_prot);
- out_free_reserved_ports:
- kfree(sysctl_local_reserved_ports);
- goto out;
- }
static int __init inet_init(void) { struct sk_buff *dummy_skb; struct inet_protosw *q; struct list_head *r; int rc = -EINVAL; BUILD_BUG_ON(sizeof(struct inet_skb_parm) > sizeof(dummy_skb->cb)); sysctl_local_reserved_ports = kzalloc(65536 / 8, GFP_KERNEL); if (!sysctl_local_reserved_ports) goto out; rc = proto_register(&tcp_prot, 1); if (rc) goto out_free_reserved_ports; rc = proto_register(&udp_prot, 1); if (rc) goto out_unregister_tcp_proto; rc = proto_register(&raw_prot, 1); if (rc) goto out_unregister_udp_proto; rc = proto_register(&ping_prot, 1); if (rc) goto out_unregister_raw_proto; /* * Tell SOCKET that we are alive... */ (void)sock_register(&inet_family_ops);
ifdef CONFIG_SYSCTL
ip_static_sysctl_init();
endif
/* * Add all the base protocols. */ if (inet_add_protocol(&icmp_protocol, IPPROTO_ICMP) < 0) printk(KERN_CRIT "inet_init: Cannot add ICMP protocol\n"); if (inet_add_protocol(&udp_protocol, IPPROTO_UDP) < 0) printk(KERN_CRIT "inet_init: Cannot add UDP protocol\n"); if (inet_add_protocol(&tcp_protocol, IPPROTO_TCP) < 0) printk(KERN_CRIT "inet_init: Cannot add TCP protocol\n");
ifdef CONFIG_IP_MULTICAST
if (inet_add_protocol(&igmp_protocol, IPPROTO_IGMP) < 0) printk(KERN_CRIT "inet_init: Cannot add IGMP protocol\n");
endif
/* Register the socket-side information for inet_create. */ for (r = &inetsw[0]; r < &inetsw[SOCK_MAX]; ++r) INIT_LIST_HEAD(r); for (q = inetsw_array; q < &inetsw_array[INETSW_ARRAY_LEN]; ++q) inet_register_protosw(q); /* * Set the ARP module up */ arp_init(); /* * Set the IP module up */ ip_init(); tcp_v4_init(); /* Setup TCP slab cache for open requests. */ tcp_init(); /* Setup UDP memory threshold */ udp_init(); /* Add UDP-Lite (RFC 3828) */ udplite4_register(); ping_init(); /* * Set the ICMP layer up */ if (icmp_init() < 0) panic("Failed to create the ICMP control socket.\n"); /* * Initialise the multicast router */
if defined(CONFIG_IP_MROUTE)
if (ip_mr_init()) printk(KERN_CRIT "inet_init: Cannot init ipv4 mroute\n");
endif
/* * Initialise per-cpu ipv4 mibs */ if (init_ipv4_mibs()) printk(KERN_CRIT "inet_init: Cannot init ipv4 mibs\n"); ipv4_proc_init(); ipfrag_init(); dev_add_pack(&ip_packet_type); rc = 0;
out:
return rc;
out_unregister_raw_proto:
proto_unregister(&raw_prot);
out_unregister_udp_proto:
proto_unregister(&udp_prot);
out_unregister_tcp_proto:
proto_unregister(&tcp_prot);
out_free_reserved_ports:
kfree(sysctl_local_reserved_ports);
goto out;
}
- Linux Wireless架构总结
- Linux Wireless架构总结
- Linux Wireless架构总结
- Linux Wireless架构总结
- Linux Wireless架构总结
- Linux Wireless架构总结
- Linux Wireless架构总结
- Linux Wireless架构总结
- Linux Wireless架构总结
- Linux Wireless架构总结
- Linux Wireless架构总结
- Linux Wireless架构总结--wifi的数据通路
- 「转 MyArrow 」Linux Wireless架构总结
- linux wireless
- linux无线架构总结
- Useful Linux Wireless Commands
- official Linux Wireless wiki
- Wireless Tools for Linux
- Swift 自定义转场动画 (没有封装)
- ios 数据存储常用方式
- RabbitMQ从入门到精通----编码与模式
- qemu如何实现面向对象模型QOM(代码讲解)
- lintcode,最长公共前缀
- Linux Wireless架构总结
- 移动端兼容性
- Android业务组件化之URL Scheme使用
- 相参、相参积累和相参雷达
- 输入输出流
- Android校招复习资料整理
- pthread_attr_init线程属性
- FloatingActionButton的使用
- 【POJ】 3982 序列