从上图中可以反应出接口与桥之间的关系。我们可以用brctl show指令看到当前所有的桥,以及桥里相应的接口。用ifconfig br0可以看当前桥的状态,如果细心一点可以看到,bro已经有了对应的MAC。这是怎么来的呢? 桥MAC地址的更新: 注意到在br_add_if中调用了函数br_stp_recalculate_bridge_id() 在上面的代码分析中,为了简化分析,把stp的相关流程忽略掉了,现在我们看下这个函数做了些什么 /* called under bridge lock */ void br_stp_recalculate_bridge_id(struct net_bridge *br) { const unsigned char *addr = br_mac_zero; struct net_bridge_port *p; //遍历桥中所有的端口 list_for_each_entry(p, &br->port_list, list) { //取所有接口中MAC的最少值 if (addr == br_mac_zero || memcmp(p->dev->dev_addr, addr, ETH_ALEN) addr = p->dev->dev_addr; } //如果不与现在桥的MAC相同 if (memcmp(br->bridge_id.addr, addr, ETH_ALEN)) br_stp_change_bridge_id(br, addr); } 这个函数比较简单,它就是遍历桥对应的所有接口,然后取最小的MAC。然后判断最小MAC跟现在的MAC是否相同 继续跟踪br_stp_change_bridge_id static void br_stp_change_bridge_id(struct net_bridge *br, const unsigned char *addr) { unsigned char oldaddr[6]; struct net_bridge_port *p; int wasroot; wasroot = br_is_root_bridge(br); memcpy(oldaddr, br->bridge_id.addr, ETH_ALEN); memcpy(br->bridge_id.addr, addr, ETH_ALEN); //注意到这里,呵呵,桥的MAC更新了 memcpy(br->dev->dev_addr, addr, ETH_ALEN); list_for_each_entry(p, &br->port_list, list) { if (!memcmp(p->designated_bridge.addr, oldaddr, ETH_ALEN)) memcpy(p->designated_bridge.addr, addr, ETH_ALEN); if (!memcmp(p->designated_root.addr, oldaddr, ETH_ALEN)) memcpy(p->designated_root.addr, addr, ETH_ALEN); } br_configuration_update(br); br_port_state_selection(br); if (br_is_root_bridge(br) && !wasroot) br_become_root_bridge(br); } 看到上面的注释了吧,桥的MAC就是在这里得到更新的,所以,桥的MAC地址取得是所有接口中的最小值 OK。到这里为止,网桥的配置已经讲述完了。我们来看一下网桥是怎么对数据包进行处理的 |
|
来自: enchen008 > 《kernel-v2.6》