Linux内核网络报文简单流程
转:http://blog.csdn.net/adamska0104/article/details/45397177
Linux内核网络报文简单流程2014-08-12 10:05:09
分类: Linux
linux下的网卡驱动中通常会提供类似XXX_rx的接收函数
该函数处理与具体硬件相关的寄存器操作
包括中断检查,数据状态检查,错误检查等
在确认有数据抵达后读取数据或从DMA的接收环中获取数据地址
XXX_rx函数以skb为元数据结构组织报文数据
随后调用内核接口函数netif_rx或netif_receive_skb
这里会涉及到软中断的处理,NAPI的接收方式
但是最后都会走netif_receive_skb函数
现在内核中使用了RPS机制
将报文分散到各个cpu的接收队列中进行负载均衡处理
在netif_receive_skb函数中进行了封装
真正的数据处理从__netif_receive_skb_core函数开始
现在可以将该函数视为协议栈的入口函数
首先进行skb中报文头元数据的调整
如果是vlan报文则先从数据中提取至vlan_tci字段
将vlan标签的4个字节从数据移除
即在调用deliver_skb向上层传递报文数据时不含vlan标签
ptype_all链表的处理主要用于抓包
在应用程序中注册PF_PACKET族ETH_P_ALL的socket便可以得到所有的输入报文
也可以用于实现自定义的协议类型报文收发
随后内核会丢弃无法识别的报文
也可以在内核模块中使用dev_add_pack向ptype_all注册自定义的处理函数
如果接口上配置了输入流控
则根据具体的队列和分类规则决定继续处理或丢弃报文
对于vlan数据报文
将skb记录的输入接口修改为vlan虚接口
比如使用vconfig配置的eth0.100虚接口
再重复上述处理
内核提供了netdev_rx_handler_register接口函数向接口注册rx_handler
比如为网桥下的接口注册br_handle_frame函数
为bonding接口注册bond_handle_frame函数
这相对于老式的网桥处理更灵活
有了这个机制也可以在模块中自行注册处理函数
网桥的处理包括向上层提交和转发
发往本地的报文会修改入接口为网桥虚接口如br0
调用netif_receive_skb重新进入协议栈处理
对于上层协议栈见到的只有桥虚接口
需要转发的报文根据转发表进行单播或广播发送
netfilter在网桥的处理路径中从br_handle_frame到br_dev_queue_push_xmit设置了5个hook点
根据nf_call_iptables的配置还会经过NFPROTO_IPV4的hook点等
内核注册的由br_nf_ops数组中定义
可在模块中自行向NFPROTO_BRIDGE族的几个hook点注册函数
ebtables在netfilter框架NFPROTO_BRIDGE中实现了桥二层过滤机制
配合应用程序ebtables可在桥下自定义相关规则
处理完接口上的rx_handler后便根据具体的3层协议类型在ptype_base中寻找处理函数
比如ETH_P_IP则调用ip_rcv,ETH_P_IPV6则调用ipv6_rcv
这些函数都由dev_add_pack注册
可在模块中自定义协议类型处理函数
如果重复定义相同协议的处理函数则要注意报文的修改对后续流程的影响
IP报文进入ip_rcv后进行简单的检查便进入路由选择
根据路由查找结果调用ip_local_deliver向上层提交或调用ip_forward进行转发
向上层提交前会进行IP分片的重组
在ip_local_deliver_finish中会根据报文中4层协议类型调用对应的处理函数
处理函数由接口函数inet_add_protocol注册
针对TCP或UDP进行不同处理,最后唤醒应用程序接收数据
向外发送和转发数据经由ip_output函数
包括IP的分片,ARP学习,MAC地址的修改或填充等
netfilter在从ip_rcv到ip_output间设置了5个hook点
向各个点的链表中注册处理函数或使用iptables工具自定义规则
实现报文处理的行为控制
报文的发送最后汇聚到队列发送函数dev_queue_xmit
在接口up的时候dev_activate会创建默认的队列规则
这里也涉及到接口驱动初始化的时候软件多队列与硬件多队列
配合tc工具可以在报文发送前进行流量控制等
最终报文发送到dev_hard_start_xmit调用接口注册的动作函数ndo_start_xmit
发送前会检查ptype_all链表,支持抓包处理等
如果是虚拟接口则通常调用其对应物理接口的发送函数
到这里内核对报文的控制便结束了
根据不同网卡驱动的实现,操作寄存器等由物理层将数据发送出去
整个调用链相对较长
每个点都包含大量的细节
主线都是围绕元数据结构skb的处理
Linux内核网络报文简单流程的更多相关文章
- Linux内核网络数据包处理流程
Linux内核网络数据包处理流程 from kernel-4.9: 0. Linux内核网络数据包处理流程 - 网络硬件 网卡工作在物理层和数据链路层,主要由PHY/MAC芯片.Tx/Rx FIFO. ...
- Linux内核--网络栈实现分析(一)--网络栈初始化
本文分析基于内核Linux Kernel 1.2.13 原创作品,转载请标明http://blog.csdn.net/yming0221/article/details/7488828 更多请看专栏, ...
- Linux内核--网络栈实现分析(一)--网络栈初始化--转
转载地址 http://blog.csdn.net/yming0221/article/details/7488828 作者:闫明 本文分析基于内核Linux Kernel 1.2.13 以后的系列博 ...
- Linux内核--网络栈实现分析(三)--驱动程序层+链路层(上)
本文分析基于Linux Kernel 1.2.13 原创作品,转载请标明http://blog.csdn.net/yming0221/article/details/7497260 更多请看专栏,地址 ...
- Linux内核--网络栈实现分析(二)--数据包的传递过程--转
转载地址http://blog.csdn.net/yming0221/article/details/7492423 作者:闫明 本文分析基于Linux Kernel 1.2.13 注:标题中的”(上 ...
- Linux内核--网络栈实现分析(十一)--驱动程序层(下)
本文分析基于Linux Kernel 1.2.13 原创作品,转载请标明http://blog.csdn.net/yming0221/article/details/7555870 更多请查看专栏,地 ...
- Linux内核--网络栈实现分析(七)--数据包的传递过程(下)
本文分析基于Linux Kernel 1.2.13 原创作品,转载请标明http://blog.csdn.net/yming0221/article/details/7545855 更多请查看专栏,地 ...
- Linux 内核 链表 的简单模拟(2)
接上一篇Linux 内核 链表 的简单模拟(1) 第五章:Linux内核链表的遍历 /** * list_for_each - iterate over a list * @pos: the & ...
- Linux 内核 链表 的简单模拟(1)
第零章:扯扯淡 出一个有意思的题目:用一个宏定义FIND求一个结构体struct里某个变量相对struc的编移量,如 struct student { int a; //FIND(struct stu ...
随机推荐
- Python自定义线程类简单示例
Python自定义线程类简单示例 这篇文章主要介绍了Python自定义线程类,结合简单实例形式分析Python线程的定义与调用相关操作技巧,需要的朋友可以参考下.具体如下: 一. 代码 # - ...
- 用js的方式运行c程序之webassemly
在这里就不科普webassemly的作用以及好处了,请自行百度. 那么,怎么通过js的方式在浏览器中运行c程序呢,其中原理如下: 可能另一张图会更详细: 1.安装emscripten 说明文档地址:h ...
- 机器学习笔记——模型调参利器 GridSearchCV(网格搜索)参数的说明
GridSearchCV,它存在的意义就是自动调参,只要把参数输进去,就能给出最优化的结果和参数.但是这个方法适合于小数据集,一旦数据的量级上去了,很难得出结果.这个时候就是需要动脑筋了.数据量比较大 ...
- 李宏毅 线性回归预测PM2.5
作业说明 给定训练集train.csv,要求根据前9个小时的空气监测情况预测第10个小时的PM2.5含量. 训练集介绍: (1):CSV文件,包含台湾丰原地区240天的气象观测资料(取每个月前20天的 ...
- 【VS开发】【编程开发】【C/C++开发】结构体中的数组与指针的内存分配情况说明
[VS开发][编程开发][C/C++开发]结构体中的数组与指针的内存分配情况说明 标签:[VS开发] [编程开发] 主要是疑惑在结构体定义的数组的内存空间与指针动态分配的内存空间,在地址上连续性.以及 ...
- 【ARM-Linux开发】Linux的SOCKET编程详解
Linux的SOCKET编程详解 1. 网络中进程之间如何通信 进 程通信的概念最初来源于单机系统.由于每个进程都在自己的地址范围内运行,为保证两个相互通信的进 程之间既互不干扰又协调一致工作,操作系 ...
- day18 time、datetime、calendar、sys、os、os.path模块
今日内容 时间模块 time模块 datetime模块 calendar模块 系统模块 sys模块 os模块 os.path模块 time模块: 在 time 模块中使用最多的方法有: time() ...
- 关于Oracle MAX()KEEP(DENSE_RANK LAST/FIRST ORDER BY ) 函数的使用分析
MAX()/MIN() KEEP(DENSE_RANK LAST/FIRST) 函数 解释: 1. max() 获取最大值: 2.min() 获取最小值; 3. keep 保持满足括号内条件的内容; ...
- sqlyog注释的快捷键-先收藏
在学习使用sqlyog的时候,想要多行注释SQL语句,就去网上找了相关的快捷键,与大家分享,网上有很多! Ctrl+M 创建一个新的连接Ctrl+N 使用当前设置新建连接Ctrl+F4 断开当前连接 ...
- Centos7 + nginx 托管 Django 项目
使用nginx托管django服务的原理 使用uwsgi开启django服务(通过配置文件启动) 防火墙关闭uwsgi端口(uwsgi的websocket一定要使用127.0.0.1的方式配置)) 编 ...