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)相关推荐

  1. linux路由内核实现分析(四)---路由缓存机制(1)

    ------------------------------------------------------------------------------------------ 以下是我根据 li ...

  2. linux路由内核实现分析(四)---路由缓存机制(3)

    在函数ip_rt_init( )中进行了rt_hash_bucket的初始化,代码如下: rt_hash_table = (struct rt_hash_bucket *) alloc_large_s ...

  3. linux路由内核实现分析(四)---路由缓存机制(2)

    dst_entry结构   struct dst_entry { struct rcu_head             rcu_head; struct dst_entry      *child; ...

  4. linux路由内核实现分析 四,linux路由内核实现分析(二)---FIB相关数据结构(4)

    fib_info结构 struct fib_info { struct hlist_node fib_hash; struct hlist_node fib_lhash; int fib_treere ...

  5. linux路由内核实现分析(三)---路由查找过程

    ------------------------------------------------------------------------------------------ 以下是我根据 li ...

  6. linux路由内核实现分析(一)----邻居子节点(1)

    ------------------------------------------------------------------------------------------ 以下是我根据 li ...

  7. mysql 源码 缓存_MySQL源码:MYSQL存储过程/函数的分析原理及缓存机制

    前言:我个人认为,有关MYSQL存储过程/函数在MYSQL中的实现比较粗糙,可扩展性不够好,其实现的耦合性太高,所以主要讲一些它的原理方面的内容,但有可能在某些方面理解不够好或者有些不正确的地方,欢迎 ...

  8. linux路由内核实现分析(二)---FIB相关数据结构(1)

    ------------------------------------------------------------------------------------------ 以下是我根据 li ...

  9. linux路由内核实现分析(二)---FIB相关数据结构(4)

    fib_info结构 struct fib_info {struct hlist_node fib_hash;struct hlist_node fib_lhash;int fib_treeref;a ...

最新文章

  1. UIView淡入淡出动画
  2. hdu1828 线段树扫描线求矩形面积的周长
  3. Python陷阱:为什么不能用可变对象作为函数的默认参数值
  4. 监控Activity的启动等状态--- 源码级
  5. rabbitmq使用_Spring Boot中使用RabbitMQ
  6. Mysql 零距离-入门(六)数据唯一约束性
  7. 轨道病害视觉检测:背景、方法与趋势
  8. bs模式Java web,基于BS模式的即时通讯系统的设计与实现(MyEclipse)
  9. iOS 11更新第6个开发者测试版,变化最大的竟然是App Store标识
  10. 51nod 1101 换零钱 【完全背包变形/无限件可取】
  11. 删除表数据有两种方法及区别
  12. 删除苹果自带软件后果_使用adb命令删除手机软件(包括系统自带)
  13. html地址栏传值问题
  14. 数据库系统概论第五版(王珊)-系统篇(十二)
  15. Visio绘图怎么对齐连接点
  16. java 点云数据处理_点云数据处理学习笔记
  17. TP框架和Laravel框架的区别
  18. 7-3 人民币与美元汇率兑换程序 (10分)
  19. 对接中国银联刷卡支付系统架构小demo
  20. 10:1,AlphaStar横空出世,碾压星际争霸2人类职业玩家 TLO 和 MaNa

热门文章

  1. 数据分箱6——分箱结果进行WOE转化
  2. java执行命令行命令
  3. LGBM模型取消打印日志(关闭日志)
  4. python调用腾讯自然语言处理api
  5. java 一切object_javaObject类
  6. 网页制作 css样式,网页设计与制作-CSS样式.ppt
  7. 简述linux内核中,Linux内核中的文件描述符(一)——基础知识简介
  8. 48.孩子们的游戏(圆圈中最后剩下的数)
  9. Git 本地仓库与远程仓库链接
  10. 8/7-8/8-8/9 今日TF训练