Chinaunix首页 | 论坛 | 博客
  • 博客访问: 458461
  • 博文数量: 64
  • 博客积分: 3271
  • 博客等级: 中校
  • 技术积分: 727
  • 用 户 组: 普通用户
  • 注册时间: 2009-07-30 18:42
文章分类

全部博文(64)

文章存档

2013年(1)

2011年(19)

2010年(42)

2009年(2)

分类: LINUX

2010-04-19 15:26:41

  

 

                                                            bridge数据流程

brigde原理相当于交换机。

1.当帧从port进入后它就认为这个port端的mac就是这个帧的源mac,并添加到地址端口表中。

2.如果帧的目的mac不在它的转发表中,它就把这个帧发到每个port。


数据它要么判断出帧为发给本地的,则交到3层协议处理。

要么是发给别个port所在的主机的,则不会经过3层。

 

 

 

 2217 int (struct  *skb)
                    2264       list_for_each_entry_rcu(ptype, &, list) {
   2265              if (ptype->dev == null_or_orig || ptype->dev == skb->dev ||
   2266                  ptype->dev == orig_dev) {
   2267                      if (pt_prev)
   2268                              ret = deliver_skb(skb, pt_prev, orig_dev);
   2269                      pt_prev = ptype;
   2270              }
   2271       }
                    2280       skb = handle_bridge(skb, &pt_prev, &ret, orig_dev);

首先把ptype_all中的raw协议交给分别注册的,然后进入hadle_bridge.

   2064 static inline struct  *(struct  *skb,
   2065                                           struct  **pt_prev, int *ret,
   2066                                           struct net_device *orig_dev)
   2067 {
   2068        struct  *;
   2069 
   2070        if (skb-> ==  ||       ////看看是不是LOOPBACK
   2071            (port = rcu_dereference(skb->dev->)) == ) ////端口为NULL
   2072                return skb;
   2073 
   2074        if (*pt_prev) {///同样是交给ETH_P_ALL类型的协议。
   2075                *ret = deliver_skb(skb, *pt_prev, orig_dev);
   2076                *pt_prev = ;
   2077        }
   2078 
   2079        return br_handle_frame_hook(port, skb);
   2080 }
   2081 #else
   2082 #define (skb, pt_prev, ret, orig_dev) (skb)
   2083 #endif

如果没有配置编译bridge,那么直接就是 skb=skb;

函数取出port

然后调用br_handle_frame_hook(port, skb)

br_init中有
    = ;
struct  *(struct  *p, struct  *)
{
       const unsigned char * = ()->;
       int (*)(struct  *);
       if (!(()->))
               goto ;
        = (, );
       if (!)
               return ;
首先检查源mac地址是否合法,然后check if buffer is shared and if so clone it
       if (((dest))) {
               /* Pause frames shouldn't be passed up by driver anyway */
               if (-> == ())
                       goto ;
               /* If STP is turned off, then forward */
               if (p->-> ==  && dest[5] == 0)
                       goto ;
               if ((, , , ->dev,
                           , ))
                       return ;   /* frame consumed by filter */
               else
                       return ;    /* continue processing */
       }
先判断是否为01:80:c2:00:00:0Xlocal multicast addressIEEE 802.1D MAC Bridge Filtered MAC Group Addresses: 01-80-C2-00-00-00 to 01-80-C2-00-00-0F; MAC frames that have a destination MAC address within this range are not relayed by MAC bridges conforming to IEEE 802.1D.

如果不是,并且如果没有配置stp,而且dest[5]=0,mac地址最后8位为0,就转发。

否则,将帧交给上层,进入NF_BR_LOCAL_IN,进入br_handle_local_finish;如果它返回0,则返回skb进一步处理,否则,返回NULL

 

:
       switch (p->) {
       case :
                = rcu_dereference();
               if ( != ) {
                       if (())
                              return ;
                       dest = ()->;
               }
               /* fall through */
       case :
               if (!(p->->dev->dev_addr, dest))
                       -> = ;
               (, , , ->dev, ,
                       );
               break;
       default:
:
               ();

 

如果是local multicast,或者满足p->-> == && dest[5] == 0,则进入forward,首先对这个端口的状态进行判断。

如果是,则调用rhook进行转发,

      (void)  中有,
 rcu_assign_pointer(, );

      函数主要任务就是做firewall,过滤用。如果ebt_broute中的规则调用返回为NF_DROP,

      即丢弃 这个帧,ebt_route返回1,那么

      会返回skb,然后在netif_receive_skb交由上层继续处理的。

然后
 先比较端口的addr,和这个数据包的mac如果相等则证明是发给本端口的包。设置skb->pkt_type=PACKET_HOST;
于是进入钩子,进入函数进一步处理 。
 

 

1.   br_handle_local_finish

static int (struct  *)
{
       struct  *p = rcu_dereference(->dev->);
       if (p)
               (p->, p, ()->);
                  mac地址与当前端口绑定,
       return 0;       /* process further */
}

 

更新当前的端口与mac的绑定即是。返回0,

会返回skb,一直返回到

   2280   skb = handle_bridge(skb, &pt_prev, &ret, orig_dev);
   2281   if (!skb)
   2282           goto ;

 

它会再调用3层协议进行进一步的处理。

2.  

对于forward的帧来说,始终会返回NULL,即帧会交到其它的端口离开,不交再上交的

int (struct  *)
{
       const unsigned char * = ()->;
       struct  *p = rcu_dereference(->dev->);
       struct  *;
       struct  *;
       struct  *;
       if (!p || p-> == )
               goto ;
       /* insert into forwarding database after filtering to avoid spoofing */
        = p->;
       (, p, ()->);

                同样更新转发表。将源mac地址与当前的port绑定。

       /* The packet skb2 goes to the local host (NULL to skip). */
        = ;
       if (->dev-> & )
                = ;
        = ;
       if ((dest)) {
               ->dev->.++;
                = ;
       } else if (( = (, dest)) && ->) {
                = ;
               /* Do not forward the packet since it's local. */
                = ;
       }

如果,桥的端口处于PROMIS状态,skb2=skb;

然后判断帧的目的地是否为multicast。如果是,则同样,skb2指向skb;

如果不是,并且通过查表得知目的地址为本地地址,skb2指向skb;skb指向NULL,即不再向外转发。

 

       if ( == )
                = (, );
       if ()
               (, );
       if () {
               if ()
                       (->, );
               else
                       (, );
       }
:
       return 0;

如果skb2=skb,则复制skb.

如果skb2不为NULL,则将它交到上层协议。

如果skb不为NULL,则如果dst即目标地址已知,则交forwarddst去。

                      否则flood到每个port.

阅读(1928) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~