免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: new_learner
打印 上一主题 下一主题

[bridge]加入到bridge中的interface能直接与ip层通信吗? [复制链接]

论坛徽章:
0
51 [报告]
发表于 2009-03-23 22:25 |只看该作者
原帖由 kevert 于 2009-3-22 17:42 发表
之所以ICMP报文没有发送出去应该是跟ARP有关系的。
ip neigh ls 看看结果。
基本流程是这样子的:
ping报文到了网关,MAC地址是网关自己,因此br0收到这个报文,从而交给上层也就是IP层处理,IP层处理之后,找路由找到eth0,创建路由缓存,但是此时并没有对应WAN侧设备的ARP信息,因此创建一个邻居节点,将这个邻居节点和这条路由缓存关联起来,但是没有获取到ARP,所以,发送 ARP请求出去,也就是通过eth0发送ARP请求出去,这个请求的响应被网关eth0收到,本来这个请求的skb->dev指向的是eth0的,结果因为eth0又被加到桥里面去了,因此,使得这个请求被桥处理之后skb->dev变成了br0了,然后送给上层处理,此时,因为ARP请求是从eth0发出去的,但是结果回应却在ARP层看来是从br0收到的,而实际上内核创建一个邻居节点的时候需要两个条件: dev 以及 MAC地址,因此这样skb->dev变成了br0,从而导致匹配不上,从而导致ARP从eth0发送出去之后没有dev匹配不上,而导致没有响应,认为目的不可达,也就是eth0并没有学到WAN侧设备的MAC地址,而是认为可以通过br0到达,所以,你最终看到结果是学习到了ARP,但是是 br0学习到的,而不是eth0学习到的,使用 ip neigh ls 就可以很清楚的知道, arp -a 显示出来内容不够细致。

说了这么多,自己都觉得有点罗嗦了,不知道解决了你的疑问么。

不好意思回复晚了,今天公司网络有点问题。

非常感谢这位兄弟的帮忙,这个问题也正如你说的这样,与arp相关。
我试过在缓存里加入静态arp,网络就通了;如果把这条arp删掉,ping包就出不去。
分析流程也正如你描述的这样,非常准确,再次感谢你:)

当然也谢谢LS各位帮忙分析问题的兄弟!

论坛徽章:
36
IT运维版块每日发帖之星
日期:2016-04-10 06:20:00IT运维版块每日发帖之星
日期:2016-04-16 06:20:0015-16赛季CBA联赛之广东
日期:2016-04-16 19:59:32IT运维版块每日发帖之星
日期:2016-04-18 06:20:00IT运维版块每日发帖之星
日期:2016-04-19 06:20:00每日论坛发贴之星
日期:2016-04-19 06:20:00IT运维版块每日发帖之星
日期:2016-04-25 06:20:00IT运维版块每日发帖之星
日期:2016-05-06 06:20:00IT运维版块每日发帖之星
日期:2016-05-08 06:20:00IT运维版块每日发帖之星
日期:2016-05-13 06:20:00IT运维版块每日发帖之星
日期:2016-05-28 06:20:00每日论坛发贴之星
日期:2016-05-28 06:20:00
52 [报告]
发表于 2009-03-23 23:13 |只看该作者

回复 #51 new_learner 的帖子

偶也又仔细的看了kevert 兄的分析,解释的很具体啊。系统学到ARP并不代表某个端口学到了ARP。也可能是别的端口学到的。

受益匪浅。

论坛徽章:
0
53 [报告]
发表于 2009-03-25 12:47 |只看该作者
原帖由 Godbach 于 2009-3-20 21:33 发表

作为一个桥,至少得有两个物理接口接到这个桥里面吧


一个也可以

论坛徽章:
36
IT运维版块每日发帖之星
日期:2016-04-10 06:20:00IT运维版块每日发帖之星
日期:2016-04-16 06:20:0015-16赛季CBA联赛之广东
日期:2016-04-16 19:59:32IT运维版块每日发帖之星
日期:2016-04-18 06:20:00IT运维版块每日发帖之星
日期:2016-04-19 06:20:00每日论坛发贴之星
日期:2016-04-19 06:20:00IT运维版块每日发帖之星
日期:2016-04-25 06:20:00IT运维版块每日发帖之星
日期:2016-05-06 06:20:00IT运维版块每日发帖之星
日期:2016-05-08 06:20:00IT运维版块每日发帖之星
日期:2016-05-13 06:20:00IT运维版块每日发帖之星
日期:2016-05-28 06:20:00每日论坛发贴之星
日期:2016-05-28 06:20:00
54 [报告]
发表于 2009-03-25 12:50 |只看该作者

回复 #53 liyaoshi 的帖子

一个的时候怎么做转发呢?

论坛徽章:
0
55 [报告]
发表于 2009-03-27 23:20 |只看该作者
原帖由 kevert 于 2009-3-22 17:42 发表
之所以ICMP报文没有发送出去应该是跟ARP有关系的。
ip neigh ls 看看结果。
基本流程是这样子的:
ping报文到了网关,MAC地址是网关自己,因此br0收到这个报文,从而交给上层也就是IP层处理,IP层处理之后,找路由找到eth0,创建路由缓存,但是此时并没有对应WAN侧设备的ARP信息,因此创建一个邻居节点,将这个邻居节点和这条路由缓存关联起来,但是没有获取到ARP,所以,发送 ARP请求出去,也就是通过eth0发送ARP请求出去,这个请求的响应被网关eth0收到,本来这个请求的skb->dev指向的是eth0的,结果因为eth0又被加到桥里面去了,因此,使得这个请求被桥处理之后skb->dev变成了br0了,然后送给上层处理,此时,因为ARP请求是从eth0发出去的,但是结果回应却在ARP层看来是从br0收到的,而实际上内核创建一个邻居节点的时候需要两个条件: dev 以及 MAC地址,因此这样skb->dev变成了br0,从而导致匹配不上,从而导致ARP从eth0发送出去之后没有dev匹配不上,而导致没有响应,认为目的不可达,也就是eth0并没有学到WAN侧设备的MAC地址,而是认为可以通过br0到达,所以,你最终看到结果是学习到了ARP,但是是 br0学习到的,而不是eth0学习到的,使用 ip neigh ls 就可以很清楚的知道, arp -a 显示出来内容不够细致。

说了这么多,自己都觉得有点罗嗦了,不知道解决了你的疑问么。


这两天又看了一下代码,kevert兄是不是认为在ip_finish_output2()中,skb实际上是没有发送出去的,直接在这个函数里被free了?
见下面代码:

  1. static inline int ip_finish_output2(struct sk_buff *skb)
  2. {

  3.         。。。。。。

  4.         if (hh)
  5.         {
  6.                 int hh_alen;

  7.                 read_lock_bh(&hh->hh_lock);
  8.                 hh_alen = HH_DATA_ALIGN(hh->hh_len);
  9.                   memcpy(skb->data - hh_alen, hh->hh_data, hh_alen);  /*填充ethernet header*/
  10.                 read_unlock_bh(&hh->hh_lock);
  11.                 skb_push(skb, hh->hh_len);
  12.                 return hh->hh_output(skb);   /*dev_queue_xmit()*/
  13.         }
  14.         else if (dst->neighbour)
  15.                 return dst->neighbour->output(skb); /*neigh_resolve_output()*/

  16.         /**************** 1 ***********/
  17.         if (net_ratelimit())
  18.                 printk(KERN_DEBUG "ip_finish_output2: No header cache and no neighbour!\n");
  19.         kfree_skb(skb);
  20.         return -EINVAL;
  21. }
复制代码

你的意思是不是代码运行了到了/**************** 1 ***********/处,所以skb被free掉了?

另外,根据你提到的:
IP层处理之后,找路由找到eth0,创建路由缓存,但是此时并没有对应WAN侧设备的ARP信息,因此创建一个邻居节点,将这个邻居节点和这条路由缓存关联起来,但是没有获取到ARP,所以,发送 ARP请求出去,

请问一下这个"因此创建一个邻居节点"的代码是在哪里呢?
我跟到了这个函数调用路径:

  1. ip_route_input_slow()-->rt_intern_hash()-->arp_bind_neighbour()-->__neigh_lookup_errno()-->neigh_create()
复制代码

但好像还是没看到哪里在发送arp request packet?
请kevert兄指点一下迷津。。。。谢谢~

论坛徽章:
0
56 [报告]
发表于 2009-03-28 00:05 |只看该作者
原帖由 new_learner 于 2009-3-27 23:20 发表


你的意思是不是代码运行了到了/**************** 1 ***********/处,所以skb被free掉了?


可能我理解错了,代码应该没有运行到/**************** 1 ***********/这里
而是运行到了

  1. else if (dst->neighbour)
  2.                 return dst->neighbour->output(skb); /*neigh_resolve_output()*/
复制代码

只是dst->neighbour->output()没有运行成功。

论坛徽章:
36
IT运维版块每日发帖之星
日期:2016-04-10 06:20:00IT运维版块每日发帖之星
日期:2016-04-16 06:20:0015-16赛季CBA联赛之广东
日期:2016-04-16 19:59:32IT运维版块每日发帖之星
日期:2016-04-18 06:20:00IT运维版块每日发帖之星
日期:2016-04-19 06:20:00每日论坛发贴之星
日期:2016-04-19 06:20:00IT运维版块每日发帖之星
日期:2016-04-25 06:20:00IT运维版块每日发帖之星
日期:2016-05-06 06:20:00IT运维版块每日发帖之星
日期:2016-05-08 06:20:00IT运维版块每日发帖之星
日期:2016-05-13 06:20:00IT运维版块每日发帖之星
日期:2016-05-28 06:20:00每日论坛发贴之星
日期:2016-05-28 06:20:00
57 [报告]
发表于 2009-03-28 12:44 |只看该作者

回复 #56 new_learner 的帖子

new_learner兄的问题还没有完全解决吗?

论坛徽章:
0
58 [报告]
发表于 2009-03-29 10:38 |只看该作者
大概应该是这样子:
如果没有学习到ARP,那么就会将路由层发过来的报文先存储在该邻居节点的一个缓存队列上,当ARP尝试几次之后没有学到之后,就会认为该邻居不可达,从而设置该邻居的状态为NUD_FAILED,然后邻居子系统有两个定时器函数来进行定时回收,一个是全局的,一个是邻居项自己的(一个表包括很多个邻居项),在这两个定时器中会根据状态来做些事情,应该就是在这两个定时器中将数据包kfree掉的。全局的为:neigh_periodic_timer,主要是用来释放邻居节点,回收内存,数据包的释放是在 neigh_timer_handler 这个定时器中。
大概流程应该就是这样了,具体细节你可以跟进去看看。可能描述有点误差也不一定,因为很久没有接触这块了,你还是一切以代码为准吧。

论坛徽章:
0
59 [报告]
发表于 2009-03-31 17:49 |只看该作者
原帖由 kevert 于 2009-3-29 10:38 发表
大概应该是这样子:
如果没有学习到ARP,那么就会将路由层发过来的报文先存储在该邻居节点的一个缓存队列上,当ARP尝试几次之后没有学到之后,就会认为该邻居不可达,从而设置该邻居的状态为NUD_FAILED,然后邻 ...

谢谢kevert的讲解。
我想最后arp reply没有与arp request对应起来的根本原因在这段代码:

  1. arp_rcv()-->arp_process()-->__neigh_lookup()-->neigh_lookup()

  2. struct neighbour *neigh_lookup(struct neigh_table *tbl, const void *pkey,
  3.                                struct net_device *dev)
  4. {
  5.         struct neighbour *n;
  6.         int key_len = tbl->key_len;
  7.         u32 hash_val = tbl->hash(pkey, dev) & tbl->hash_mask;   /*¼ÆËã³öhashÖµ*/
  8.        
  9.         NEIGH_CACHE_STAT_INC(tbl, lookups);

  10.         read_lock_bh(&tbl->lock);
  11.         for (n = tbl->hash_buckets[hash_val]; n; n = n->next)
  12.         {   
  13.                                 /*从这里可以看出,要匹配到tbl->hash_buckets里的元素,需要pkey和dev同时满足。
  14.                      但由于对arp的处理在bridge之后(可以参看netif_receive_skb()),在tbl->hash_buckets的n->dev
  15.                                是eth0,但接受进来的arp reply的dev却是br0,所以这里无法做到匹配,导致arp_process()中没有运行到
  16.                      neigh_update()这个函数里*/
  17.                 if (dev == n->dev && !memcmp(n->primary_key, pkey, key_len))
  18.                 {
  19.                         neigh_hold(n);
  20.                         NEIGH_CACHE_STAT_INC(tbl, hits);
  21.                         break;
  22.                 }
  23.         }
  24.         read_unlock_bh(&tbl->lock);
  25.         return n;   
  26. }
复制代码

论坛徽章:
0
60 [报告]
发表于 2009-03-31 22:25 |只看该作者
原帖由 new_learner 于 2009-3-31 17:49 发表

谢谢kevert的讲解。
我想最后arp reply没有与arp request对应起来的根本原因在这段代码:

arp_rcv()-->arp_process()-->__neigh_lookup()-->neigh_lookup()

struct neighbour *neigh_lookup(struct ne ...



是的,正解。因为找不到,所以导致ARP认为通过eth0无法到达该WAN设备。从而使得不通。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP