你可以使用以下命令来检查Linux网桥当前转发表或MAC学习表。
1.$ sudo brctl showmacs <bridge-name>
该命令将显示一个学习到的MAC地址与关联端口的列表。各个条目都有一个相关的附于其上的老化计时器,因此转发条目可以在一定时间后刷新,以使MAC学习表更新到最新。
网桥接口的混杂模式取决于三个因素,一个是自身的混杂模式设置;第二是vlan过滤是否开启;最后是处于自动状态(auto_port)的子接口的数量。网桥的混杂模式管理函数br_manage_promisc如下:void br_manage_promisc(struct net_bridge *br)
{
if ((br->dev->flags &IFF_PROMISC) || !br_vlan_enabled(br))
set_all = true
list_for_each_entry(p, &br->port_list, list) {
if (set_all) {
br_port_set_promisc(p)
} else {
if (br->auto_cnt == 0 ||
(br->auto_cnt == 1 &&br_auto_port(p)))
br_port_clear_promisc(p)
else
br_port_set_promisc(p)
}
}
}
混杂模式设置
如下通过命令设置网桥br_2为混杂模式,此时,所有网桥子接口都将处于混杂模式(eth1与eth2 promiscuity mode):
ip link add br_2 type bridge
ip link set eth1 master br_2
ip link set eth2 master br_2
通过ip命令设置接口的混杂模式:
ip link set br_2 promisc on
或者ioctl系统调用设置混杂模式:
int set_bridge_promiscuity(void)
{
sockfd = socket(AF_INET, SOCK_DGRAM, 0)
strncpy(ifr.ifr_name, "br_2", IFNAMSIZ)
ioctl(sockfd, SIOCGIFFLAGS, &ifr)
ifr.ifr_flags |= IFF_PROMISC
ioctl(sockfd, SIOCSIFFLAGS, &ifr)
}
VLAN过滤
如果网桥的VLAN filtering过滤功能没有开启,即使网桥没有设置混杂模式,也需开启所有子接口的混杂模式。
/sys/devices/virtual/net/br_2/bridge/vlan_filtering
自动状态接口AUTO_PORT
内核中对自动状态接口的定义如下,即设置了学习(learning)或者单播泛洪(flood)标志的接口。
#define BR_AUTO_MASK(BR_FLOOD | BR_LEARNING)
#define br_auto_port(p) ((p)->flags &BR_AUTO_MASK)
可通过bridge或者ip命令设置网桥接口的flood/learning等标志:
bridge link set dev eth1 flood on/off
bridge link set dev eth1 learning on/off
ip link set dev eth1 type bridge_slave flood on/off
ip link set dev eth1 type bridge_slave learning on/off
网桥添加网络设备时,新接口的flags赋值为BR_LEARNING与BR_FLOOD标志,即新接口为自动状态接口。
static struct net_bridge_port *new_nbp(struct net_bridge *br, struct net_device *dev)
{
struct net_bridge_port *p
p->flags = BR_LEARNING | BR_FLOOD
}
BR_LEARNING标志,在函数br_handle_frame_finish中判断,用来决定是否使用数据包的源MAC地址更新网桥的FDB转发表。
int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
{
struct net_bridge_port *p = br_port_get_rcu(skb->dev)
struct net_bridge *br
br = p->br
if (p->flags &BR_LEARNING)
br_fdb_update(br, p, eth_hdr(skb)->h_source, vid, false)
}
BR_FLOOD标志用来控制是否在接口上泛洪单播数据包,如果没有设置此标志,不能在此接口泛洪单播包。
void br_flood(struct net_bridge *br, struct sk_buff *skb, ...)
{
struct net_bridge_port *p
list_for_each_entry_rcu(p, &br->port_list, list) {
switch (pkt_type) {
case BR_PKT_UNICAST:
if (!(p->flags &BR_FLOOD))
continue
break
}
网桥结构体中保存了自动状态接口的数量auto_cnt,在向网桥添加接口或者删除接口的时候,调用nbp_update_port_count更新自动状态接口的数量。通过遍历网桥的接口列表,获取自动接口数量。
static void nbp_update_port_count(struct net_bridge *br)
{
struct net_bridge_port *p
u32 cnt = 0
list_for_each_entry(p, &br->port_list, list) {
if (br_auto_port(p))
cnt++
}
if (br->auto_cnt != cnt) {
br->auto_cnt = cnt
br_manage_promisc(br)
}
}
所谓非自动接口,即此接口不自动学习数据包的源MAC地址,或者不泛洪单播包。对于此类接口,要正常转发报文,必须静态指定其在FDB转发表中的转发表项。由上文br_manage_promisc函数中的条件判断可知,当网桥下都是非自动接口时(auto_cnt=0),关闭混杂模式,因为此时所有接口都已经配置好了转发表项,不需要混杂模式。当只有一个接口时自动接口的时候,从这个接口接收到的数据包无非是要转发到系统剩余的其它接口,而其它接口都是非自动的,这就反向决定了此自动接口的转发路径也被确定下了,此时也不需要混杂模式。
所以当自动接口大于1时,开启混杂模式。
更多Linux信息可参考《Linux就该这么学》
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)