Linux内核分析 - 网络[三]:从netif_receive_skb()说起
在netif_receive_skb()函数中,可以看出处理的是像ARP、IP这些链路层以上的协议,那么,链路层报头是在哪里去掉的呢?答案是网卡驱动中,在调用netif_receive_skb()前,
skb->protocol = eth_type_trans(skb, bp->dev);
该函数对处理后skb>data跳过以太网报头,由mac_header指示以太网报头:
进入netif_receive_skb()函数
list_for_each_entry_rcu(ptype,&ptype_base[ntohs(type) & PTYPE_HASH_MASK], list)
按照协议类型依次由相应的协议模块进行处理,而所以的协议模块处理都会注册在ptype_base中,实际是链表结构。
net/core/dev.c
static struct list_head ptype_base __read_mostly; /* Taps */
而相应的协议模块是通过dev_add_pack()函数加入的:
void dev_add_pack(struct packet_type *pt)
{
int hash;
spin_lock_bh(&ptype_lock);
if (pt->type == htons(ETH_P_ALL))
list_add_rcu(&pt->list, &ptype_all);
else {
hash = ntohs(pt->type) & PTYPE_HASH_MASK;
list_add_rcu(&pt->list, &ptype_base[hash]);
}
spin_unlock_bh(&ptype_lock);
}
以ARP处理为例
该模块的定义,它会在arp_init()中注册进ptype_base链表中:
static struct packet_type arp_packet_type __read_mostly = {
.type = cpu_to_be16(ETH_P_ARP),
.func = arp_rcv,
};
然后在根据报文的TYPE来在ptype_base中查找相应协议模块进行处理时,实际调用arp_rcv()进行接收
arp_rcv() --> arp_process()
arp = arp_hdr(skb);
……
arp_ptr= (unsigned char *)(arp+1);
sha= arp_ptr;
arp_ptr += dev->addr_len;
memcpy(&sip, arp_ptr, 4);
arp_ptr += 4;
arp_ptr += dev->addr_len;
memcpy(&tip, arp_ptr, 4);
操作后这指针位置:
然后判断是ARP请求报文,这时先查询路由表ip_route_input()
if (arp->ar_op == htons(ARPOP_REQUEST) &&
ip_route_input(skb, tip, sip, 0, dev) == 0)
在ip_route_input()函数中,先在cache中查询是否存在相应的路由表项:
hash = rt_hash(daddr, saddr, iif, rt_genid(net));
缓存的路由项在内核中组织成hash表的形式,因此在查询时,先算出的hash值,再用该项- rt_hash_table[hash].chain即可。这里可以看到,缓存路由项包括了源IP地址、目的IP地址、网卡号。
如果在缓存中没有查到匹配项,或指定不查询cache,则查询路由表ip_route_input_slow();
进入ip_route_input_slow()函数,最终调用fib_lookup()得到查询结果fib_result
if ((err = fib_lookup(net, &fl, &res)) != 0)
如果结果fib_result合法,则需要更新路由缓存,将此次查询结果写入缓存
hash = rt_hash(daddr, saddr, fl.iif, rt_genid(net));
err = rt_intern_hash(hash, rth, NULL, skb, fl.iif);
在查找完路由表后,回到arp_process()函数,如果路由项指向本地,则应由本机接收该报文:
if (addr_type == RTN_LOCAL) {
……
if (!dont_send) {
n = neigh_event_ns(&arp_tbl, sha, &sip, dev);
if (n) {
arp_send(ARPOP_REPLY,ETH_P_ARP,sip,dev,tip,sha,dev->dev_addr,sha);
neigh_release(n);
}
}
goto out;
}
首先更新邻居表neigh_event_ns(),然后发送ARP响应 – arp_send。
至此,大致的ARP流程完成。由于ARP部分涉及到路由表以及邻居表,这都是很大的概念,在下一篇中介绍,这里直接略过了。
Linux内核分析 - 网络[三]:从netif_receive_skb()说起相关推荐
- linux内核启动分析 三,Linux内核分析 实验三:跟踪分析Linux内核的启动过程
贺邦 + 原创作品转载请注明出处 + <Linux内核分析>MOOC课程 http://mooc.study.163.com/course/USTC-1000029000 一. 实验过程 ...
- Linux内核分析(三)----初识linux内存管理子系统
原文:Linux内核分析(三)----初识linux内存管理子系统 Linux内核分析(三) 昨天我们对内核模块进行了简单的分析,今天为了让我们今后的分析没有太多障碍,我们今天先简单的分析一下linu ...
- Linux内核分析——第三周学习笔记
20135313吴子怡.北京电子科技学院 chapter1 知识点梳理 一.Linux内核源代码简介 (视频中对目录下的文件进行了简介,记录如下) arch目录 占有相当庞大的空间 arch/x86目 ...
- linux内核分析 网络九,“Linux内核分析”实验报告(九)
一 Linux内核分析博客简介及其索引 本次实验简单的分析了计算机如何进行工作,并通过简单的汇编实例进行解释分析 在本次实验中 通过听老师的视频分析,和自己的学习,初步了解了进程切换的原理.操作系统通 ...
- Linux内核分析 - 网络[十六]:TCP三次握手
内核:2.6.34 TCP是应用最广泛的传输层协议,其提供了面向连接的.可靠的字节流服务,但也正是因为这些特性,使得TCP较之UDP异常复杂,还是分两部分[创建与使用]来进行分析.这篇主要 ...
- Linux内核分析 - 网络[十]:ARP杂谈
内核版本:2.6.34 杂谈一:重复地址检测 Linux协议栈中处理重复地址检测报文的是arp_process()中的一段代码,RFC2131是DHCP的草案,相应的sip==0是DHCP服务器用来检 ...
- Linux内核分析 - 网络[四]:路由表
路由表 在内核中存在路由表fib_table_hash和路由缓存表rt_hash_table.路由缓存表主要是为了加速路由的查找,每次路由查询都会先查找路由缓存,再查找路由表.这和cache是一个道理 ...
- Linux内核分析 - 网络[九]:邻居表
内核版本:2.6.34 这部分的重点是三个核心的数据结构-邻居表.邻居缓存.代理邻居表,以及NUD状态转移图. 总的来说,要成功添加一条邻居表项,需要满足两个条件:1. 本机使用该表项:2. 对方主机 ...
- linux内核 checksum,Linux内核分析 - 网络[十三]:校验和
内核版本:2.6.34 报文的IP校验和.ICMP校验和.TCP/UDP校验和使用相同的算法,在RFC1071中定义,网上这方面的资料和例子很多,就不解释算法流程了,而是侧重于在实现的变化和技巧. T ...
最新文章
- python3 pillow使用测试
- 8,协议序列化组件NewLife.Serialization
- Apache 各启动方式的差别
- JPA J2SE 桌面应用范例
- RabbitMQ中常用的三种Exchange 类型
- 清华大学出版社,包邮送40本畅销书籍
- 如何抢占云栖大会C位?史上最强强强攻略来了
- Arm学习总结之 32位和64位寄存器
- pycharm-连接mysql设置
- Js事件对象EventUtil
- 树堆(Treap)图文详解与实现
- 毕业后,两个月,第二家公司上班第一天
- 李宏毅深度学习HW2 收入预测 (logistic regression)
- sharepoint搭建文档服务器,SharePoint Server教程
- Linux环境安装之Ant
- 009-lissajous(一)
- 纹波(ripple)--学习笔记
- 数据治理:数据质量管理策略!
- 咪咕音乐的下载音乐存储路径(MAC)
- 2015年:跑步计划
热门文章
- HTTP,TCP, socket,RPC 与gRPC都是啥?
- python pip下载本地依赖包,并在离线环境中安装,并解决报错ERROR: Could not find a version that satisfies the requirement报错
- python 读取、写入 pkl文件
- 反转dataframe
- core控制器属性注入的用处_asp.net-core – 如何使用Autofac和ASP.NET Core在控制器上启用属性注入?...
- java ldap 实例_JAVA_基本LDAP操作实例
- jQuery和react实现二维码
- Docker-创建和分享应用(3)
- 使Eclipse下支持编写HTML/JS/CSS/JSP页面的自动提示。
- How to Leak a Context: Handlers Inner Classes