网桥接口非混杂模式下数据包转发

网桥接口处在非混杂模式下,只能接收目的MAC地址为自身的数据包,也就是说如果数据包的目的MAC为其它地址,将会被丢弃掉。对于单网口的设备这样没有问题,但是对于存在多个网卡的交换设备,如果从一个网口接收到的数据包为需要转发的数据包,其去往另外一个接口,由于目的mac不等于接收网卡的MAC地址就会被丢弃导调导致网络不通。

Linux内核为了处理这一问题,采取了为一个非混杂模式的接口,添加多个硬件单播MAC地址的方法,即一个接口对应多个MAC地址(MAC地址列表)。

struct net_device {
     struct netdev_hw_addr_list  uc;    /* Unicast mac addresses */
}

网桥代码中函数br_port_clear_promisc负责处理混杂模式的关闭, 如果网桥的子接口不支持单播过滤功能(网卡驱动不支持IFF_UNICAST_FLT),即其混杂模式不能关闭,不用再做处理。


static void br_port_clear_promisc(struct net_bridge_port *p)
{
    if (!br_promisc_port(p) || !(p->dev->priv_flags & IFF_UNICAST_FLT))
        return;

    err = br_fdb_sync_static(p->br, p);

    dev_set_promiscuity(p->dev, -1);
    p->flags &= ~BR_PROMISC;
}


当网卡设备支持单播过滤时,在关闭接口混杂模式之前,需要先同步好FDB表内相关的静态转发表项,以防关闭混杂模式后导致数据流中断。br_fdb_sync_static函数负责将fdb表中的静态表项同步到网卡设备的单播地址列表中(uc),这样,当关闭混杂模式时,目的地址只要在dev->uc列表中的数据包,还可以继续正常转发。dev_uc_add函数会将这些地址同步到网卡硬件的过滤列表中。


int br_fdb_sync_static(struct net_bridge *br, struct net_bridge_port *p)
{
    for (i = 0; i < BR_HASH_SIZE; i++) {
        hlist_for_each_entry(fdb, &br->hash[i], hlist) {
            if (!fdb->is_static)
                continue;
            err = dev_uc_add(p->dev, fdb->addr.addr);
        }
    }
}
int dev_uc_add(struct net_device *dev, const unsigned char *addr)
{
    err = __hw_addr_add(&dev->uc, addr, dev->addr_len, NETDEV_HW_ADDR_T_UNICAST);
    if (!err) __dev_set_rx_mode(dev);
}


最后看一下FDB表中都由哪些静态表项。首先是网桥接口自身的MAC地址生成的表项(毫无疑问目的mac为网桥自身的数据包,子接口必须接收上来);第二是网桥增加子接口时,由子接口的MAC地址生成的表项;然后就是用户配置的静态转发表项。

ip link add br_test type bridge
ip link set eth0 master br_test
bridge fdb add 00:01:02:03:04:05 dev eth0 master static


内核版本

linux-4.15


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值