来吧,路由
还记得在笔记5-IP层的处理1中ip_rcv_finish走到过一个岔口
int ip_route_input(struct sk_buff *skb, __be32 daddr, __be32 saddr,
u8 tos, struct net_device *dev)
rth = rcu_dereference(rth-> u.dst.rt_next )) {
if (((rth->fl.fl4_dst ^ daddr) | 异或 相同为0
(rth->fl.fl4_src ^ saddr) |
(rth->fl.iif ^ iif) |
rth->fl.oif |
(rth->fl.fl4_tos ^ tos)) == 0 &&
rth->fl.mark == skb->mark &&
net_eq(dev_net(rth->u.dst.dev), net) && 判断路由和报文的struct net指针地址是否相同
!rt_is_expired(rth)) { 路由项是否过期
路由是网络的核心,是linux网络协议栈的核心,我们找个入口进去看看
还记得在笔记5-IP层的处理1中ip_rcv_finish走到过一个岔口
->ip_rcv_finish()
->
ip_route_input() 查找路由信息
->if (iph->ihl > 5 && ip_rcv_options(skb))
如果IP头部大于20字节,则表示IP头部包含IP选项,需要进行选项处理.
goto drop;
goto drop;
->dst_input(skb);
dst_input实际上会调用skb->dst->input(skb).input函数会根据路由信息设置为合适的函数指针,
如果是则递交到本地的
则为ip_local_deliver,若是转发则为ip_forward
两条路径:
1)
ip_local_deliver
2) ip_forward
是什么导致路径不同呢,我们看一看
ip_route_input()
干了啥
int ip_route_input(struct sk_buff *skb, __be32 daddr, __be32 saddr,
u8 tos, struct net_device *dev)
->net = dev_net(dev);
->hash =
rt_hash(daddr, saddr, iif, rt_genid(net));
计算hash值,注意hash因子
->
既然hash值算出来了,我们就去找吧
rcu_read_lock();
for (rth = rcu_dereference(
rt_hash_table[hash].chain
); rth;
rth = rcu_dereference(rth-> u.dst.rt_next )) {
if (((rth->fl.fl4_dst ^ daddr) | 异或 相同为0
(rth->fl.fl4_src ^ saddr) |
(rth->fl.iif ^ iif) |
rth->fl.oif |
(rth->fl.fl4_tos ^ tos)) == 0 &&
rth->fl.mark == skb->mark &&
net_eq(dev_net(rth->u.dst.dev), net) && 判断路由和报文的struct net指针地址是否相同
!rt_is_expired(rth)) { 路由项是否过期
找到了
dst_use(&rth->u.dst, jiffies); 表示路由的使用时间
RT_CACHE_STAT_INC(in_hit);
rcu_read_unlock();
skb_dst_set(skb, &rth->u.dst); 设置到skb中去
return 0;
}
RT_CACHE_STAT_INC(in_hlist_search);
}
rcu_read_unlock();
static struct rt_hash_bucket *rt_hash_table __read_mostly;
dst_use(&rth->u.dst, jiffies); 表示路由的使用时间
RT_CACHE_STAT_INC(in_hit);
rcu_read_unlock();
skb_dst_set(skb, &rth->u.dst); 设置到skb中去
return 0;
}
RT_CACHE_STAT_INC(in_hlist_search);
}
rcu_read_unlock();
static struct rt_hash_bucket *rt_hash_table __read_mostly;
struct
rt_hash_bucket {
struct rtable *chain;
};
struct rtable *chain;
};
struct
rtable
{
union
{
struct dst_entry dst;
} u;
/* Cache lookup keys */
struct flowi &
{
union
{
struct dst_entry dst;
} u;
/* Cache lookup keys */
struct flowi &