转: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内核网络报文简单流程的更多相关文章

  1. Linux内核网络数据包处理流程

    Linux内核网络数据包处理流程 from kernel-4.9: 0. Linux内核网络数据包处理流程 - 网络硬件 网卡工作在物理层和数据链路层,主要由PHY/MAC芯片.Tx/Rx FIFO. ...

  2. Linux内核--网络栈实现分析(一)--网络栈初始化

    本文分析基于内核Linux Kernel 1.2.13 原创作品,转载请标明http://blog.csdn.net/yming0221/article/details/7488828 更多请看专栏, ...

  3. Linux内核--网络栈实现分析(一)--网络栈初始化--转

    转载地址 http://blog.csdn.net/yming0221/article/details/7488828 作者:闫明 本文分析基于内核Linux Kernel 1.2.13 以后的系列博 ...

  4. Linux内核--网络栈实现分析(三)--驱动程序层+链路层(上)

    本文分析基于Linux Kernel 1.2.13 原创作品,转载请标明http://blog.csdn.net/yming0221/article/details/7497260 更多请看专栏,地址 ...

  5. Linux内核--网络栈实现分析(二)--数据包的传递过程--转

    转载地址http://blog.csdn.net/yming0221/article/details/7492423 作者:闫明 本文分析基于Linux Kernel 1.2.13 注:标题中的”(上 ...

  6. Linux内核--网络栈实现分析(十一)--驱动程序层(下)

    本文分析基于Linux Kernel 1.2.13 原创作品,转载请标明http://blog.csdn.net/yming0221/article/details/7555870 更多请查看专栏,地 ...

  7. Linux内核--网络栈实现分析(七)--数据包的传递过程(下)

    本文分析基于Linux Kernel 1.2.13 原创作品,转载请标明http://blog.csdn.net/yming0221/article/details/7545855 更多请查看专栏,地 ...

  8. Linux 内核 链表 的简单模拟(2)

    接上一篇Linux 内核 链表 的简单模拟(1) 第五章:Linux内核链表的遍历 /** * list_for_each - iterate over a list * @pos: the & ...

  9. Linux 内核 链表 的简单模拟(1)

    第零章:扯扯淡 出一个有意思的题目:用一个宏定义FIND求一个结构体struct里某个变量相对struc的编移量,如 struct student { int a; //FIND(struct stu ...

随机推荐

  1. SQL Server 时间戳与时间格式互相转换

    时间戳(Unix timestamp) 是一种时间表示方式,定义为从格林威治时间1970年01月01日00时00分00秒起至现在的总秒数. Unix时间戳不仅被使用在Unix系统.类Unix系统中,也 ...

  2. flask(2.0)

    目录 一. Flask基础(一) 1.Flask启动 2.路由 3.Response 4.Request 5.Jinja2 6.session 二.Flask基础(二) 1.路由配置 (1)metho ...

  3. spring-boot集成8:集成shiro,jwt

    Shrio是一个轻量级的,基于AOP 和 Servlet 过滤器的安全框架.它提供全面的安全性解决方案,同时在 Web 请求级和方法调用级处理身份确认和授权. JWT(JSON Web Token)是 ...

  4. Springboot--关于使用webapp目录

    前我在学习springBoot集成springMVC的时候发现webapp目录, 1. 直接右键运行,访问不到页面,原来并不是不支持啊,只是默认没有把它放在编译路径里面. 我们可以在项目的packag ...

  5. Unity Shader的形式

    (1)表面着色器 表面着色器是Unity自身的一种着色器代码类型.它需要的代码量很少,Unity在背后做了很多工作,但渲染的代价比较大.但Unity在背后仍旧把表面着色器转换成对应的顶点/片元着色器. ...

  6. sqlalchemy 的操作

    使用PyMySQL的前提: 1. 先建好表 2. 自己动手需要手动去写多条SQL语句 改进: 类 ------>  表 实例化 -> 数据 这种思想叫:ORM(Object Relatio ...

  7. 阿里P8架构师谈:Restful、SOAP、RPC、SOA、微服务之间的区别(转载)

    转载来源:https://youzhixueyuan.com/the-difference-between-restful-soap-rpc-soa-and-micro-service.html 内容 ...

  8. NDK学习笔记-JNI数据类型和属性方法的访问

    JNI实现了C/C++与Java的相互访问,那么这篇文章就从C/C++访问Java开始说起 native函数说明 每个native函数,都至少有两个参数(JNIEnv *和jclass或jobject ...

  9. 性能排查--CPU占用高

    排查思路: 1.先找到占用CPU高的进程PID    top命令 2.top -H -p <PID>  查看哪个占用CPU高的线程TID 3.jstack <PID>  /ho ...

  10. Excel小技巧(随机点名)

    如图,想要做一个随机点名的表格,同样可以石头剪刀布的场合,随机选人. 如何做呢? 第一步,填好想要的数据 第二步,在空的位置输入=INDIRECT("A"&RANDBETW ...