对于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

阅读(4638) | 评论(0) | 转发(0) |

linux .forward,linux forward的实现相关推荐

  1. [Linux转载]Linux 操作常用命令

    Linux操作命令集合 参考:http://www.cnblogs.com/rollenholt/archive/2012/09/01/2667184.html 正在运行的内核和系统信息 # unam ...

  2. OS + linux command / Linux Command / Linux command / linux Command

    写下你职业生涯中最难以忘怀的误操作.. http://www.dangkai.com/ArticlePage/Article59549.htm http://bbs.chinaunix.net/thr ...

  3. 【Linux】Linux基本指令和工具操作大集合(vim、gcc/g++、gdb、make/makefile、git)

    [Linux]Linux基本指令和工具操作大集合(vim.gcc/g++.gdb.make/makefile.git) 文章目录 [Linux]Linux基本指令和工具操作大集合(vim.gcc/g+ ...

  4. nvidia命令不可用linux,在Linux命令行下如何正确配置nVIDIA显卡

    在图形芯片领域,nVidia是一个后来者,它的历史仅相当于ATi的一半.1993年初,NVIDIA 由 Jen-Hsun Huang,,Chris Malachowsky和 Curtis Priem ...

  5. 20155301 滕树晨linux基础——linux进程间通信(IPC)机制总结

    20155301 滕树晨linux基础--linux进程间通信(IPC)机制总结 共享内存 共享内存是在多个进程之间共享内存区域的一种进程间的通信方式,由IPC为进程创建的一个特殊地址范围,它将出现在 ...

  6. 【Linux 内核】调度器 ① ( 调度器概念 | 调度器目的 | 调度器主要工作 | 调度器位置 | 进程优先级 | 抢占式调度器 | Linux 进程状态 | Linux 内核进程状态 )

    文章目录 一.调度器 0.调度器概念 1.调度器目的 2.调度器主要工作 3.调度器位置 4.进程优先级 5.抢占式调度器 二.Linux 内核进程状态 API 简介 三.Linux 进程状态 一.调 ...

  7. 在Windows里备份Linux分区,在Windows里分出Linux分区(Linux分区).pdf

    在Windows里分出Linux分区(Linux分区) ks2886v的个人空间 分区 作者:红联 分区 和大部分同学一样,我的电脑全部都是FAT32格式和NTFS格式,之前并没有考虑其他的系统,也 ...

  8. linux mint 18.3 内核,Linux Mint Linux用户可以升级到18.2 18.3”

    Linux Mint Linux用户可以升级到18.2 18.3"现在应该在造币厂"的技术 Linux Mint的升级路径--从"索尼娅".现在的操作系统是一个 ...

  9. VM之Linux:Linux的Ubuntu中,解决安装后屏幕太小的问题

    VM之Linux:Linux的Ubuntu中,解决安装后屏幕太小的问题 导读 最讨厌网上回答的啰嗦和不清晰!本人最讨厌啰嗦,直接上来,图文表达,简单明了,快速解决问题!最讨厌网上答案一大片的废话和没有 ...

  10. samba权限跟linux权限,linux之samba与linux权限

    当linux的文件夹或文件为用户或root时,则在window上共享出来的samba是不能进行修改的,当samba设置为 [share] path = /home #available = yes # ...

最新文章

  1. 再见 Python,Hello Julia!
  2. Java基础:继承、多态、抽象、接口
  3. 【作品发布】QQ2008远程自助 1.5.1.1
  4. HTML---HTML中常用的标签(标题,水平,特殊标签)
  5. java开发工具包jdk包括哪些
  6. Linux系统初始化更新(更换阿里源)(centos7mini)
  7. Rails测试《二》单元测试unit test
  8. C#基础17:匿名方法与Lambda表达式
  9. LINUX下载编译sqlite-jdbc(支持mips64el/loongarch64的jar包下载)
  10. 华硕B85M-G主板安装心得
  11. ASPICE总结2——软件详细设计与软件测试过程
  12. VB显示透明FLASH效果
  13. 二元关系的矩阵和图表示
  14. 运算放大器节点电压方程_比例运算放大器电路
  15. LDT面试:实验室开发诊断试剂监管模式(Laboratory Developed Test,LDT)
  16. java thread yield()_Java Thread yield()方法
  17. AtomicInteger类下的incrementAndGet
  18. 小米浏览器禁用java_2019-03-11 小米散招面试-Java后台实习
  19. 家用电脑设置成小程序服务器,电脑微信小程序设置全屏的方法是什么
  20. 快速了解 Git 仓库

热门文章

  1. 折弯弹性计算公式_冲压模具:影响回弹因素、回弹计算公式计算,值得收藏
  2. html右侧分为两个框架,html – 两个框架一个滚动条
  3. AndroidStudio 3.4更新了啥?(转载)
  4. linux网络包截获,用C实现截获网络数据包
  5. mysql 移植ucos_基于STM32F767的UCOSIII移植学习
  6. Windows10+Ubuntu 18.04.2+ROS 安装笔记(SSD单硬盘)上
  7. OpenCV与图像处理学习三——线段、矩形、圆、椭圆、多边形的绘制以及文字的添加
  8. 传输层(知识架构图)
  9. ActiveMQ消费者平滑关闭
  10. mysql报错 DuplicateKeyException分析与解决