博所搬至http://xiaogr.com
全部博文(79)
分类: LINUX
2007-10-25 18:44:00
这样,就往桥中添加了一个接口,从上图中可以反应出接口与桥之间的关系。我们可以用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) < 0)
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。到这里为止,网桥的配置已经讲述完了。我们来看一下网桥是怎么对数据包进行处理的