Chinaunix首页 | 论坛 | 博客
  • 博客访问: 795007
  • 博文数量: 264
  • 博客积分: 592
  • 博客等级: 中士
  • 技术积分: 1574
  • 用 户 组: 普通用户
  • 注册时间: 2011-10-24 22:02
文章分类

全部博文(264)

文章存档

2019年(2)

2018年(1)

2017年(1)

2016年(4)

2015年(14)

2014年(57)

2013年(88)

2012年(97)

分类: LINUX

2014-02-12 15:28:06

转:http://blog.csdn.net/nerdx/article/details/12291777
  1. //  传输配置BPDU  
  2. //  函数主要任务:  
  3. //      1.检查速率限制  
  4. //      2.填充bpdu报文  
  5. //      3.发送配置bpdu  
  6.   
  7. //  注:每个端口对bpdu的发送速率具有限制,通过net_bridge_port->hold_timer进行限制。  
  8. 1.1 void br_transmit_config(struct net_bridge_port *p)  
  9. {  
  10.     struct br_config_bpdu bpdu;//配置bpdu  
  11.     struct net_bridge *br;  
  12.   
  13.   
  14.     if (timer_pending(&p->hold_timer)) {//如果在速率限制区间内,则设置config_pending,然后返回  
  15.         p->config_pending = 1;  
  16.         return;  
  17.     }  
  18.   
  19.     br = p->br;//网桥的设备  
  20.   
  21.     bpdu.topology_change = br->topology_change;//初始化配置bpdu协议相关项  
  22.     bpdu.topology_change_ack = p->topology_change_ack;  
  23.     bpdu.root = br->designated_root;  
  24.     bpdu.root_path_cost = br->root_path_cost;  
  25.     bpdu.bridge_id = br->bridge_id;  
  26.     bpdu.port_id = p->port_id;  
  27.     if (br_is_root_bridge(br))//根网桥  
  28.         bpdu.message_age = 0;//自从根网桥生成该BPDU中包含的信息后已经过的时间  
  29.     else {  
  30.         struct net_bridge_port *root  
  31.             = br_get_port(br, br->root_port);  
  32.         bpdu.message_age = br->max_age  
  33.             - (root->message_age_timer.expires - jiffies)  
  34.             + MESSAGE_AGE_INCR;  
  35.     }  
  36.     bpdu.max_age = br->max_age;//配置BPDU的最大生存期  
  37.     bpdu.hello_time = br->hello_time;  
  38.     bpdu.forward_delay = br->forward_delay;  
  39.   
  40.     if (bpdu.message_age < br->max_age) {  
  41.         br_send_config_bpdu(p, &bpdu);//发送配置BPDU  
  42.         p->topology_change_ack = 0;  
  43.         p->config_pending = 0;  
  44.         mod_timer(&p->hold_timer, jiffies + BR_HOLD_TIME);  
  45.     }  
  46. }  
  47.   
  48. //  处理入口bpdu帧  
  49. //  调用路径netif_receive_skb->...->br_stp_handle_bpdu  
  50. //  函数主要任务:  
  51. //      1.确保sk_buff->data足够bpdu协议格式  
  52. //      2.通过报文内容,区别配置bpdu,tc-bpdu,分别处理   
  53. 2.1 int br_stp_handle_bpdu(struct sk_buff *skb)  
  54. {  
  55.     struct net_bridge_port *p = skb->dev->br_port;  
  56.     struct net_bridge *br = p->br;  
  57.     unsigned char *buf;  
  58.   
  59.     if (!pskb_may_pull(skb, sizeof(header)+1) ||//使skb->data到skb->tail的数据量足够 802 和 STP 协议最小的协议头  
  60.         memcmp(skb->data, header, sizeof(header)))//拷贝协议头到header中  
  61.         goto err;  
  62.   
  63.     buf = skb_pull(skb, sizeof(header));//skb->data向下移动n个字节,skb->len-=n  
  64.   
  65.     spin_lock_bh(&br->lock);//获取网桥的锁  
  66.     if (p->state == BR_STATE_DISABLED //skb的接收端口被关闭  
  67.         || !(br->dev->flags & IFF_UP)//网桥被关闭  
  68.         || !br->stp_enabled)//网桥没有运行stp协议  
  69.         goto out;  
  70.   
  71.     if (buf[0] == BPDU_TYPE_CONFIG) {//配置BPDU  
  72.         struct br_config_bpdu bpdu;  
  73.         //按照配置BPDU的报文格式填充结构  
  74.         if (!pskb_may_pull(skb, 32))  
  75.             goto out;  
  76.   
  77.         buf = skb->data;  
  78.         bpdu.topology_change = (buf[1] & 0x01) ? 1 : 0;//拓扑是否改变  
  79.         bpdu.topology_change_ack = (buf[1] & 0x80) ? 1 : 0;//拓扑改变BPDU的ack  
  80.         //优先级向量<根网桥id,根网桥开销,发送网桥id,发送网桥端口id>  
  81.         bpdu.root.prio[0] = buf[2];  
  82.         bpdu.root.prio[1] = buf[3];  
  83.         bpdu.root.addr[0] = buf[4];  
  84.         bpdu.root.addr[1] = buf[5];  
  85.         bpdu.root.addr[2] = buf[6];  
  86.         bpdu.root.addr[3] = buf[7];  
  87.         bpdu.root.addr[4] = buf[8];  
  88.         bpdu.root.addr[5] = buf[9];  
  89.         bpdu.root_path_cost =  
  90.             (buf[10] << 24) |  
  91.             (buf[11] << 16) |  
  92.             (buf[12] << 8) |  
  93.             buf[13];  
  94.         bpdu.bridge_id.prio[0] = buf[14];  
  95.         bpdu.bridge_id.prio[1] = buf[15];  
  96.         bpdu.bridge_id.addr[0] = buf[16];  
  97.         bpdu.bridge_id.addr[1] = buf[17];  
  98.         bpdu.bridge_id.addr[2] = buf[18];  
  99.         bpdu.bridge_id.addr[3] = buf[19];  
  100.         bpdu.bridge_id.addr[4] = buf[20];  
  101.         bpdu.bridge_id.addr[5] = buf[21];  
  102.         bpdu.port_id = (buf[22] << 8) | buf[23];  
  103.   
  104.         bpdu.message_age = br_get_ticks(buf+24);//自从根网桥生成该bpdu以来,已经过去的时间  
  105.         bpdu.max_age = br_get_ticks(buf+26);//配置bpdu的最大生存期  
  106.         bpdu.hello_time = br_get_ticks(buf+28);//hello定时器所用的时限  
  107.         bpdu.forward_delay = br_get_ticks(buf+30);//forward delay所用的时限  
  108.   
  109.         br_received_config_bpdu(p, &bpdu);//协议处理函数  
  110.     }  
  111.   
  112.     else if (buf[0] == BPDU_TYPE_TCN) {//拓扑改变bpdu  
  113.         br_received_tcn_bpdu(p);  
  114.     }  
  115.  out:  
  116.     spin_unlock_bh(&br->lock);  
  117.  err:  
  118.     kfree_skb(skb);  
  119.     return 0;  
  120. }  
  121. //  处理配置BPDU  
  122. //  调用路径br_stp_handle_bpdu->br_received_config_bpdu  
  123. //  函数主要任务:  
  124. //      1.配置bpdu的优先级向量高于当前网桥的优先级向量  
  125. //          1.1 使用配置bpdu的配置信息  
  126. //          1.2 更新网桥配置信息, 重新选择根端口,指定端口  
  127. //          1.3 网桥端口的状态选择  
  128. //          1.4 如果网桥由非根网桥变为根网桥  
  129. //              1.4.1 使用tcn_timer,周期性向网络传输设置有tc标志的配置bpdu  
  130. //      2.配置bpdu的优先级向量低于当前网桥的优先级向量  
  131. //          2.1 如果接收端口是指定端口,则向指定端口发送本网桥使用的配置信息。  
  132. 2.2 void br_received_config_bpdu(struct net_bridge_port *p, struct br_config_bpdu *bpdu)  
  133. {  
  134.     struct net_bridge *br;  
  135.     int was_root;  
  136.    
  137.     br = p->br;  
  138.     was_root = br_is_root_bridge(br);//当前网桥是否为根网桥  
  139.   
  140.     if (br_supersedes_port_info(p, bpdu)) {//配置bpdu中的优先级向量高于当前网桥的优先级向量  
  141.         br_record_config_information(p, bpdu);//更新接收到的端口优先级向量,修改message_age定时器的到期时间  
  142.         br_configuration_update(br);//更新网桥的配置信息,选择根端口,指定端口  
  143.         br_port_state_selection(br);//开启网桥端口状态的选择  
  144.   
  145.         if (!br_is_root_bridge(br) && was_root) {//由根网桥变成了非根网桥  
  146.             del_timer(&br->hello_timer);//非根网桥不需要使用hello定时器  
  147.             if (br->topology_change_detected) {//检测到拓扑的变化设置该字段  
  148.                 del_timer(&br->topology_change_timer);//根网桥检测到拓扑变化后,使用该定时器,通知其他网桥拓扑的变化  
  149.                 br_transmit_tcn(br);//从根端口发送tcn  
  150.   
  151.                 mod_timer(&br->tcn_timer,   
  152.                       jiffies + br->bridge_hello_time);//普通网桥检测到拓扑变化后,使用的定时器,等待接收到tca  
  153.             }  
  154.         }  
  155.   
  156.         if (p->port_no == br->root_port) {//当前端口为根端口  
  157.             br_record_config_timeout_values(br, bpdu);//更新br->max_age,hello_time,forward delay,topology_change。当根网桥检测的拓扑变化后,会启动topology_change_timer,并且在发送的配置bpdu中设置tc标志,当根网桥的topology_change_timer到期后,之后发送的配置bpdu,都不会再有tc标志。其他非根网桥,在每次从根端口收到配置bpdu时,都会将其中的tc标志保存在br->topology_change字段中,然后从指定端口发送的配置bpdu时,根据该字段,决定是否设置tc标志。  
  158.             br_config_bpdu_generation(br);//在每个使能的指定端口,发送配置BPDU  
  159.             if (bpdu->topology_change_ack)//此bpdu时对本机之前发送的TCN的应答,TCN从根端口发送,然后从根端口接收到TCA的配置BPDU  
  160.                 br_topology_change_acknowledged(br);//收到TCN应答  
  161.         }  
  162.     } else if (br_is_designated_port(p)) {//收到的bpdu优先级向量低于本网桥使用的优先级向量  
  163.         br_reply(p);//回复本网桥使用的配置信息        
  164.     }  
  165. }  
阅读(1319) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~