白领ol嘉嘉tiffany:linux forward的实现

来源:百度文库 编辑:偶看新闻 时间:2024/04/23 14:22:29
博客首页注册建议与交流排行榜推荐投诉 搜索:帮助
CUDev
 
Hello,all like Unix Linux and CU ! ^_^
CUDev.cublog.cn管理博客
发表文章
留言
收藏夹· Linux
博客圈
音乐
相册
文章· 嵌入式Linux· 心情日记· 算法研究· 网络安全· 网络编程· Kernel and Driver· Linux深入学习· Linux应用· perl· python· QT4学习笔记· SF· Shell· 操作系统研究· 程序设计· 服务器管理
首页


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 < 0)
goto martian_source;
if (result)
flags |= RTCF_DIRECTSRC;
spec_dst = daddr;
/*设置skb->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
发表于: 2008-01-17 ,修改于: 2008-01-17 12:08,已浏览1079次,有评论0条推荐投诉


网友评论
发表评论