免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 3810 | 回复: 11
打印 上一主题 下一主题

[网络子系统] fib_del_ifaddr函数的一个问题 [复制链接]

论坛徽章:
1
IT运维版块每日发帖之星
日期:2015-11-17 06:20:00
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2015-04-23 21:40 |只看该作者 |倒序浏览
最近在复习以前阅读的linux网络内核源码笔记,发现了一个以前忽略的问题,下面我列出我有疑问的代码

   872 static void fib_del_ifaddr(struct in_ifaddr *ifa)
   873 {
             ...
   942     if (!(ok&LOCAL_OK)) {
   943         fib_magic(RTM_DELROUTE, RTN_LOCAL, ifa->ifa_local, 32, prim);
   944
   945         /* Check, that this local address finally disappeared. */
   946         if (inet_addr_type(ifa->ifa_local) != RTN_LOCAL) {
   947             /* And the last, but not the least thing.
   948                We must flush stray FIB entries.
   949
   950                First of all, we scan fib_info list searching
   951                for stray nexthop entries, then ignite fib_flush.
   952             */
   953             if (fib_sync_down(ifa->ifa_local, NULL, 0))
   954                 fib_flush();
   955         }
   956     }
             ...
   961 }

如上红色字体所示代码,通过inet_addr_type函数判断当前被删除的地址ifa对应的路由是否为RTN_LOCAL,如果不是则调用下面的fib_sync_down,我这里的问题是,什么样的地址具有这样的非RTN_LOCAL特征?作为对比,在fib_add_ifaddr函数中我们可以给linux添加一个ip,而该添加函数中我反复阅读了下,都找不到能在这里满足此红色字体语句的那样的ifa,这到底是怎么回事?以前阅读这段代码时没有想到这个细节,望各位能给予解答!

论坛徽章:
1
IT运维版块每日发帖之星
日期:2015-11-17 06:20:00
2 [报告]
发表于 2015-04-23 22:37 |只看该作者
本帖最后由 jiufei19 于 2015-04-27 12:01 编辑

刚才我描述问题时,遗漏了一个相关内容,即inet_addr_type函数,如下
   162 unsigned inet_addr_type(__be32 addr)
   163 {
   164     struct flowi        fl = { .nl_u = { .ip4_u = { .daddr = addr } } };
   165     struct fib_result   res;
   166     unsigned ret = RTN_BROADCAST;
   167            
   168     if (ZERONET(addr) || BADCLASS(addr))
   169       return RTN_BROADCAST;
   170     if (MULTICAST(addr))
   171       return RTN_MULTICAST;
   172
   173 #ifdef CONFIG_IP_MULTIPLE_TABLES
   174     res.r = NULL;
   175 #endif
   176
   177     if (ip_fib_local_table) {
   178         ret = RTN_UNICAST;
   179         if (!ip_fib_local_table->tb_lookup(ip_fib_local_table,
   180                            &fl, &res)) {
   181             ret = res.type;
   182             fib_res_put(&res);
   183         }
   184     }
   185     return ret;
   186 }

显然,在inet_addr_type函数有上述兰色字体表示了该ifa有可能为非RTN_LOCAL的情况,但是我之前的疑问并非指这两种特殊情况,也即除了这2种情况外,还有其他非RTN_LOCAL的情况吗?

接着描述我的困惑:

假设这个被删除的ifa既不是multicast,也不是ZERONET或BADCLASS,那么inet_addr_type函数中从177行开始的判断到底是为什么而进行的呢?根据Understanding Linux Network Internals一书中所说,有一种特殊的地址添加情况,即:
# ip addr add dev eth0 192.168.0.1/24
# ip addr add dev eth0 192.168.0.1/16

此时同一个地址配置了两个掩码,于是当删除其中一个地址时,将不能简单就去掉到此地址的路由,因为还有另外一个地址和掩码存在着,但是这样的话,LOCAL_OK标记就不成立了,代码也就不会继续执行后面的inet_addr_type判断了。显然,当一个唯一性的local地址被删除后,才会引发后续的inet_addr_type的判断,而这个判断对于这种唯一性的地址似乎没有任何意义呢?

论坛徽章:
1
IT运维版块每日发帖之星
日期:2015-11-17 06:20:00
3 [报告]
发表于 2015-04-24 17:44 |只看该作者
本帖最后由 jiufei19 于 2015-04-24 17:52 编辑

为了找到问题,作为对比,今天又把fib_add_ifaddr函数仔细看了一遍,发现仍然无法理解我这里提出的问题。

void fib_add_ifaddr(struct in_ifaddr *ifa)
{
   ...
   fib_magic(RTM_NEWROUTE, RTN_LOCAL, addr, 32, prim);
   ...
}

这里显然被添加的ip对应的路由都是RTN_LOCAL,那么在fib_del_ifaddr函数中似乎永远也不会出现 if (inet_addr_type(ifa->ifa_local) != RTN_LOCAL) 的情况了(除了我前面的帖子中指明的那两个特殊的类型以外),这到底是怎么一回事呢?只能是我对地址和路由的概念有地方理解错了,请大家指正!


PS:

忽然想到一个问题,即inet_addr_type函数的调用点有好几个地方,或许是在fib_del_ifaddr这个调用场景下,被删除的地址只能是组播、badclass、zeronet三种形式!

论坛徽章:
20
程序设计版块每日发帖之星
日期:2015-08-17 06:20:00程序设计版块每日发帖之星
日期:2016-07-16 06:20:00程序设计版块每日发帖之星
日期:2016-07-18 06:20:00每日论坛发贴之星
日期:2016-07-18 06:20:00黑曼巴
日期:2016-12-26 16:00:3215-16赛季CBA联赛之江苏
日期:2017-06-26 11:05:5615-16赛季CBA联赛之上海
日期:2017-07-21 18:12:5015-16赛季CBA联赛之青岛
日期:2017-09-04 17:32:0515-16赛季CBA联赛之吉林
日期:2018-03-26 10:02:16程序设计版块每日发帖之星
日期:2016-07-15 06:20:0015-16赛季CBA联赛之江苏
日期:2016-07-07 18:37:512015亚冠之萨济拖拉机
日期:2015-08-17 12:21:08
4 [报告]
发表于 2015-04-24 19:35 |只看该作者
本帖最后由 nswcfd 于 2015-04-24 19:50 编辑

没有那么复杂吧?

inet_addr_type(946行)前面的fib_magic(943)已经把local表中路由删除了,
那么inet_addr_type查找local表多半会失败的,失败就返回RTN_UNICAST,不就命中了这个分支?

========================================
以上纯属猜测,待会儿加上Printk测试一下。

论坛徽章:
20
程序设计版块每日发帖之星
日期:2015-08-17 06:20:00程序设计版块每日发帖之星
日期:2016-07-16 06:20:00程序设计版块每日发帖之星
日期:2016-07-18 06:20:00每日论坛发贴之星
日期:2016-07-18 06:20:00黑曼巴
日期:2016-12-26 16:00:3215-16赛季CBA联赛之江苏
日期:2017-06-26 11:05:5615-16赛季CBA联赛之上海
日期:2017-07-21 18:12:5015-16赛季CBA联赛之青岛
日期:2017-09-04 17:32:0515-16赛季CBA联赛之吉林
日期:2018-03-26 10:02:16程序设计版块每日发帖之星
日期:2016-07-15 06:20:0015-16赛季CBA联赛之江苏
日期:2016-07-07 18:37:512015亚冠之萨济拖拉机
日期:2015-08-17 12:21:08
5 [报告]
发表于 2015-04-24 20:22 |只看该作者
本帖最后由 nswcfd 于 2015-04-24 20:22 编辑

通过printk观察,貌似是这样的。

正在努力思考问题的反方面:

什么情况下,在local表中删除了ifa_local对应的路由,而inet_addr_type仍然会返回RTN_LOCAL(即表中还有ifa_local对应的路由)?

论坛徽章:
20
程序设计版块每日发帖之星
日期:2015-08-17 06:20:00程序设计版块每日发帖之星
日期:2016-07-16 06:20:00程序设计版块每日发帖之星
日期:2016-07-18 06:20:00每日论坛发贴之星
日期:2016-07-18 06:20:00黑曼巴
日期:2016-12-26 16:00:3215-16赛季CBA联赛之江苏
日期:2017-06-26 11:05:5615-16赛季CBA联赛之上海
日期:2017-07-21 18:12:5015-16赛季CBA联赛之青岛
日期:2017-09-04 17:32:0515-16赛季CBA联赛之吉林
日期:2018-03-26 10:02:16程序设计版块每日发帖之星
日期:2016-07-15 06:20:0015-16赛季CBA联赛之江苏
日期:2016-07-07 18:37:512015亚冠之萨济拖拉机
日期:2015-08-17 12:21:08
6 [报告]
发表于 2015-04-24 21:12 |只看该作者
一种可能性是人为的在local路由表中加入了匹配某接口IP的非32掩码的路由条目(非kernel自动生成的)……

论坛徽章:
1
IT运维版块每日发帖之星
日期:2015-11-17 06:20:00
7 [报告]
发表于 2015-04-26 21:51 |只看该作者
本帖最后由 jiufei19 于 2015-04-27 11:51 编辑

回复 4# nswcfd


    感谢nswcfd的回答。对于nswcfd的如下说明:
-------------------------------------------------------------
inet_addr_type(946行)前面的fib_magic(943)已经把local表中路由删除了,
那么inet_addr_type查找local表多半会失败的,失败就返回RTN_UNICAST,不就命中了这个分支?
--------------------------------------------------------------

我的问题就是这里,这样做的原因到底是什么?因为似乎inet_addr_type的查找local表一定会失败的,多此一举的目的是什么呢?

论坛徽章:
1
IT运维版块每日发帖之星
日期:2015-11-17 06:20:00
8 [报告]
发表于 2015-04-27 10:11 |只看该作者
本帖最后由 jiufei19 于 2015-04-27 11:48 编辑

回复 5# nswcfd


根据代码可知,当被删除的一个ip具有唯一性时,其一定是RTN_LOCAL类型,于是有:
-----------------------------------------------------------------------------------------
if (!(ok&LOCAL_OK)) {// 地址列表中已无此地址,可删除之
           fib_magic(RTM_DELROUTE, RTN_LOCAL, ifa->ifa_local, 32,
                              prim);

           if (inet_addr_type(ifa->ifa_local) != RTN_LOCAL) {
-----------------------------------------------------------------------------------------
而此时这个被删除的ifa通过inet_addr_type判断时一定会返回RTN_UNICAST类型,从而命中了!=RTN_LOCAL分支,这正是我对fib_del_ifaddr感到疑惑的地方,为啥要这样做?

论坛徽章:
20
程序设计版块每日发帖之星
日期:2015-08-17 06:20:00程序设计版块每日发帖之星
日期:2016-07-16 06:20:00程序设计版块每日发帖之星
日期:2016-07-18 06:20:00每日论坛发贴之星
日期:2016-07-18 06:20:00黑曼巴
日期:2016-12-26 16:00:3215-16赛季CBA联赛之江苏
日期:2017-06-26 11:05:5615-16赛季CBA联赛之上海
日期:2017-07-21 18:12:5015-16赛季CBA联赛之青岛
日期:2017-09-04 17:32:0515-16赛季CBA联赛之吉林
日期:2018-03-26 10:02:16程序设计版块每日发帖之星
日期:2016-07-15 06:20:0015-16赛季CBA联赛之江苏
日期:2016-07-07 18:37:512015亚冠之萨济拖拉机
日期:2015-08-17 12:21:08
9 [报告]
发表于 2015-04-27 13:05 |只看该作者
个人理解:

ip和路由条目之间没有必然联系(自动添加和删除的条目除外),完全可以人为的在local route table里面增加路由,导致最后一个ip被删除之后,local route table查找依然命中。

另外,对于loopback类型的接口,fib_add_ifaddr自动添加内核路由的时候,并不是往main表中添加的,而是往local表中添加的。
所以,如果添加了
ip addr add dev lo 1.1.1.1/16
ip addr add dev lo 1.1.1.2/24
local表中会有 1.1.0.0/16 和 1.1.1.0/24 两个非广播路由

当删除1.1.1.2/24的时候,!OK&LOCAL_OK仍然成立,1.1.1.0/24被删除,但是1.1.0.0/16仍然存在,所以还会返回RTN_LOCAL

论坛徽章:
1
IT运维版块每日发帖之星
日期:2015-11-17 06:20:00
10 [报告]
发表于 2015-04-27 21:54 |只看该作者
本帖最后由 jiufei19 于 2015-04-27 21:59 编辑
nswcfd 发表于 2015-04-27 13:05
个人理解:

ip和路由条目之间没有必然联系(自动添加和删除的条目除外),完全可以人为的在local route  ...


虽然我目前仍然无法理解fib_del_ifaddr函数在这个问题上的处理逻辑究竟是什么,不过似乎可以看成是这样一种基调:
------------------------------------------------------------------------------------------------------------
关于这里为啥要调用inet_addr_type进行继续判断的理由,目前可以暂时这样认为:当删除了某个local地址后,对应的RTN_LOCAL路由也被fib_magic函数在local表中所删除,于是系统需要进一步再通过inet_addr_type在local路由表中再次搜索是否真的再也没有这样的RTN_LOCAL路由了,如果是,则!=RTN_LOCAL成立,于是可以进一步去删除其他相关信息(fib_info和fib_nh),否则表示在local表中仍然可以找到对应此被删除ip的RTN_LOCAL路由存在,则不能进一步删除其他相关信息(fib_info和fib_nh)

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP