linux路由内核实现分析(四)---路由缓存机制(4)
ip_route_input函数
int ip_route_input(struct sk_buff *skb, __be32 daddr, __be32 saddr,
u8 tos, struct net_device *dev)
{
struct rtable * rth;
unsigned hash;
int iif = dev->ifindex;
tos &= IPTOS_RT_MASK;
//根据源地址,目的地址,还有网卡的index来生成哈希值,如果
//是2.4.x的内核,还需要加上tos.
hash = rt_hash(daddr, saddr, iif);
rcu_read_lock();
//通过相应的哈希值,调用rcu_dereference得到RCU保护的临界指针指向一个
//rt_hash_buck中的rtable,进行遍历查找,一直到rtable链表尾部
for (rth = rcu_dereference(rt_hash_table[hash].chain); rth;
rth = rcu_dereference(rth->u.dst.rt_next)) {
if (rth->fl.fl4_dst == daddr &&
rth->fl.fl4_src == saddr &&
rth->fl.iif == iif &&
rth->fl.oif == 0 &&
rth->fl.mark == skb->mark &&
rth->fl.fl4_tos == tos) {
rth->u.dst.lastuse = jiffies;
dst_hold(&rth->u.dst);
rth->u.dst.__use++;
RT_CACHE_STAT_INC(in_hit);
rcu_read_unlock();
skb->dst = (struct dst_entry*)rth;
return 0;
//找到相匹配的路由信息,将skb->dst赋值为找到的dst_entry,然后
//直接return
}
RT_CACHE_STAT_INC(in_hlist_search);
}
rcu_read_unlock();
if (MULTICAST(daddr)) {
struct in_device *in_dev;
rcu_read_lock();
if ((in_dev = __in_dev_get_rcu(dev)) != NULL) {
int our = ip_check_mc(in_dev, daddr, saddr,
ip_hdr(skb)->protocol);
if (our
#ifdef CONFIG_IP_MROUTE
|| (!LOCAL_MCAST(daddr) && IN_DEV_MFORWARD(in_dev))
#endif
) {
rcu_read_unlock();
return ip_route_input_mc(skb, daddr, saddr,
tos, dev, our);
}
}
rcu_read_unlock();
return -EINVAL;
}
//如果没有查找到相对应的路由信息,就使用这个函数
//进行路由查找,这个函数将调用fib_lookup来查找相对应
//的FIB
return ip_route_input_slow(skb, daddr, saddr, tos, dev);
}
ip_route_input_slow函数
static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr,
u8 tos, struct net_device *dev)
{
………………………………………………………..
………………………………………………………..
调用fib_lookup查找路由项目,将结果放在res中
if ((err = fib_lookup(&fl, &res)) != 0) {
if (!IN_DEV_FORWARD(in_dev))
goto e_hostunreach;
goto no_route;
}
free_res = 1;
RT_CACHE_STAT_INC(in_slow_tot);
//如果是广播路由
if (res.type == RTN_BROADCAST)
goto brd_input;
//如果是本地路由
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;
goto local_input;
}
//如果当前系统并不处于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);
if (err == -ENOBUFS)
goto e_nobufs;
if (err == -EINVAL)
goto e_inval;
done:
in_dev_put(in_dev);
if (free_res)
fib_res_put(&res);
out: return err;
brd_input:
if (skb->protocol != htons(ETH_P_IP))
goto e_inval;
if (ZERONET(saddr))
spec_dst = inet_select_addr(dev, 0, RT_SCOPE_LINK);
else {
err = fib_validate_source(saddr, 0, tos, 0, dev, &spec_dst,
&itag);
if (err < 0)
goto martian_source;
if (err)
flags |= RTCF_DIRECTSRC;
}
flags |= RTCF_BROADCAST;
res.type = RTN_BROADCAST;
RT_CACHE_STAT_INC(in_brd);
local_input:
//生成一条新的rtable信息,用于下次路由缓存
rth = dst_alloc(&ipv4_dst_ops);
……………………………………………………………………………………..
……………………………………………………………………………………..
}
linux路由内核实现分析(四)---路由缓存机制(4)相关推荐
- linux路由内核实现分析(四)---路由缓存机制(1)
------------------------------------------------------------------------------------------ 以下是我根据 li ...
- linux路由内核实现分析(四)---路由缓存机制(3)
在函数ip_rt_init( )中进行了rt_hash_bucket的初始化,代码如下: rt_hash_table = (struct rt_hash_bucket *) alloc_large_s ...
- linux路由内核实现分析(四)---路由缓存机制(2)
dst_entry结构 struct dst_entry { struct rcu_head rcu_head; struct dst_entry *child; ...
- linux路由内核实现分析 四,linux路由内核实现分析(二)---FIB相关数据结构(4)
fib_info结构 struct fib_info { struct hlist_node fib_hash; struct hlist_node fib_lhash; int fib_treere ...
- linux路由内核实现分析(三)---路由查找过程
------------------------------------------------------------------------------------------ 以下是我根据 li ...
- linux路由内核实现分析(一)----邻居子节点(1)
------------------------------------------------------------------------------------------ 以下是我根据 li ...
- mysql 源码 缓存_MySQL源码:MYSQL存储过程/函数的分析原理及缓存机制
前言:我个人认为,有关MYSQL存储过程/函数在MYSQL中的实现比较粗糙,可扩展性不够好,其实现的耦合性太高,所以主要讲一些它的原理方面的内容,但有可能在某些方面理解不够好或者有些不正确的地方,欢迎 ...
- linux路由内核实现分析(二)---FIB相关数据结构(1)
------------------------------------------------------------------------------------------ 以下是我根据 li ...
- linux路由内核实现分析(二)---FIB相关数据结构(4)
fib_info结构 struct fib_info {struct hlist_node fib_hash;struct hlist_node fib_lhash;int fib_treeref;a ...
最新文章
- UIView淡入淡出动画
- hdu1828 线段树扫描线求矩形面积的周长
- Python陷阱:为什么不能用可变对象作为函数的默认参数值
- 监控Activity的启动等状态--- 源码级
- rabbitmq使用_Spring Boot中使用RabbitMQ
- Mysql 零距离-入门(六)数据唯一约束性
- 轨道病害视觉检测:背景、方法与趋势
- bs模式Java web,基于BS模式的即时通讯系统的设计与实现(MyEclipse)
- iOS 11更新第6个开发者测试版,变化最大的竟然是App Store标识
- 51nod 1101 换零钱 【完全背包变形/无限件可取】
- 删除表数据有两种方法及区别
- 删除苹果自带软件后果_使用adb命令删除手机软件(包括系统自带)
- html地址栏传值问题
- 数据库系统概论第五版(王珊)-系统篇(十二)
- Visio绘图怎么对齐连接点
- java 点云数据处理_点云数据处理学习笔记
- TP框架和Laravel框架的区别
- 7-3 人民币与美元汇率兑换程序 (10分)
- 对接中国银联刷卡支付系统架构小demo
- 10:1,AlphaStar横空出世,碾压星际争霸2人类职业玩家 TLO 和 MaNa