linuxforward的实现(ip_rcv__iprcv_slow_ip_route_input
来源:互联网 发布:邪恶吧下载软件 编辑:程序博客网 时间:2024/04/30 10:33
http://os.chinaunix.net/a2008/0407/978/000000978808.shtml
linux forward的实现
对于linux的数据包流向,大家应该是比较了解,如果还不是很了解,可以参考《OReilly.Understanding.Linux.Network.Internals.Dec.2005》,其中有一个图非常清楚的描述了数据包的流向。
ip的数据包接收函数是ip_rcv()==>ip_rcv_finish()
在ip_rcv_finish()中:
if (skb->dst == NULL) {
int err = ip_route_input(skb, iph->daddr, iph->saddr, iph->tos,
skb->dev);
刚接收到的数据包,skb->dst项是空的,因此会调用ip_route_input()函数,我们来追踪ip_route_input函数:
ip_route_input()==>ip_route_input_slow()
在ip_route_input_slow()中:
if ((err = fib_lookup(&fl, &res)) != 0) {
if (!IN_DEV_FORWARD(in_dev))
goto e_hostunreach;
goto no_route;
}
调用fib_lookup()函数用来在fib中查询路由信息,将路由查询结果保存在fib_result结构的res中。
接下来:
if (res.type == RTN_LOCAL) {
int result;
result = fib_validate_source(saddr, daddr, tos,
loopback_dev.ifindex,
dev, &spec_dst, &itag);
if (result dst->input=ip_local_deliver*/
goto local_input;
}
如果查询的结果显示,路由类型RTN_LOCAL的话,跳转到local_input段,设置skb->dst->input = ip_local_deliver
接下来,路由类型是RTN_LOCAL的已经跳转到下面去了,剩下的就是非LCOAL的,也就是Forward的:
if (!IN_DEV_FORWARD(in_dev))
goto e_hostunreach;
if (res.type != RTN_UNICAST)
goto martian_destination;
/*设置skb->dst->input=ip_forward*/
err = ip_mkroute_input(skb, &res, &fl, in_dev, daddr, saddr, tos);
调用IN_DEV_FORWARD宏来判断网络设备是否处于FORWARD状态;调用ip_mkroute_input()函数来设置skb->dst->input=ip_forward
我们来分析一下IN_DEV_FORWARD这个宏:
#define IN_DEV_FORWARD(in_dev) ((in_dev)->cnf.forwarding)
在ipv4_sysctl_forward()函数中调用inet_forward_change()函数:
在inet_forward_change()函数中:
int on = ipv4_devconf.forwarding;
in_dev->cnf.forwarding = on;
在sysctl_net_ipv4.c中
{
.ctl_name = NET_IPV4_FORWARD,
.procname = "ip_forward",
.data = &ipv4_devconf.forwarding,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &ipv4_sysctl_forward,
.strategy = &ipv4_sysctl_forward_strategy
},
这样,我们通过
echo 1 > /proc/sys/net/ipv4/ip_forward
来打开forward功能,实际上就调用了
ipv4_sysctl_forward()==>inet_forward_change()
设置了in_dev->cnf.forwarding = 1;
这样IN_DEV_FORWARD(in_dev)返回为1,当forward的数据包到来的时候,能够调用ip_mkroute_input()函数,设置skb->dst->input=ip_forward。
==========
再回到ip_rcv_finish()中,最后函数调用了dst_input函数,我们来追踪一下dst_input()函数:
dst_input()==>skb->dst->input
对于LOCAL的数据包来说调用的是:ip_local_deliver()函数
对于FORWARD的数据包来说调用的是:ip_forward()函数
对于fib_lookup的细节,可以参考:
http://blog.chinaunix.net/u/28366/showart_215922.html
- linuxforward的实现(ip_rcv__iprcv_slow_ip_route_input
- 三子棋的实现的实现的实现
- JAVA实现的时钟实现
- 模态框的的实现
- 杀毒软件的简单实现的简单实现
- android的实现电话号码的实现
- 音频的实现音乐声音的实现
- malloc的实现、内存池的实现
- 异形窗体的实现
- 个性化的分页实现
- ASP数据库连接的实现
- Struts单选框的实现
- 梅西迭代算法的实现
- 翻页功能的实现
- Struts,MVC 的实现
- 实现JavaScript的继承
- 接口的显示实现
- TTerm的实现( 一)
- 嵌入式系统MAC地址(新增内容)烧写方法(未完)
- ASP.NET MVC3 概要
- StringBuffer与StringBuilder区别
- 一天一linux命令(16) cut sort wc uniq tee split 较常用命令
- opengl纹理相关知识
- linuxforward的实现(ip_rcv__iprcv_slow_ip_route_input
- do...while(0)的妙用
- 黑马程序员——初识String类:String类的知识点总结
- 战争迷雾效果 第05章 项目源码下载
- 特效
- JSTL 表达式与 EL 语言
- 广州传智播客4月份最新开班信息
- maven安装与使用
- 在线备份系统的简明操作