如何显示Linux网桥的MAC学习表

如何显示Linux网桥的MAC学习表,第1张

 Linux网桥是网桥的软件实现,这是Linux内核的内核部分。与硬件网桥相类似,Linux网桥维护了一个2层转发表(也称为MAC学习表,转发数据库,或者仅仅称为FDB),它跟踪记录了MAC地址与端口的对应关系。当一个网桥在端口N收到一个包时(源MAC地址为X),它在FDB中记录为MAC地址X可以从端口N到达。这样的话,以后当网桥需要转发一个包到地址X时,它就可以从FDB查询知道转发到哪里。构建一个FDB常常称之为“MAC学习”或仅仅称为“学习”过程。

你可以使用以下命令来检查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就该这么学》


欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/yw/7305745.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-04
下一篇 2023-04-04

发表评论

登录后才能评论

评论列表(0条)

保存