linux mode4,Linux 网络bond mode 4 的xmit_hash_policy layer3+4 到底是如何hash 的

博客探讨了在Linux中使用iperf3测试4块网卡的LACP链路聚合时遇到的问题。由于xmit_hash_policy设置为layer3+4,导致在特定条件下无法充分利用所有网卡。博主分析了kernel bonding文档和源码,发现实际的端口映射算法与文档描述不同,存在丢弃最低位哈希比特的情况,以适应TCP连接端口号变化。这一改动是为了避免某些情况下所有流都映射到同一网卡,从而限制带宽。该问题在CentOS/RHEL7.3内核版本中尚未修复。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在通过iperf3 测试4 块网卡做的lacp 链路聚合时,xmit_hash_policy 选择的是layer3+4. 当iperf3 指定的线程数比较少时,总是打不满带宽。

例如在源目的IP和目的端口不变的情况下,四个线程使用连续的4个源端口10001~10004 (iperf3 参数 -P 4-B src_ip –cport 10001)测试tcp 只能打出3 个网卡的效果,从/proc/net/dev 中查看计数,以及从tcpdump 的抓包中,发现只有1,2,3 三块网卡有出流量。

其中10001 用网卡1,10002 和10003 用网卡2,10004 用网卡3,网卡四没有发包。

后续测试其他连续端口,也发现类似的情况,甚至有时候只能打出两张卡的效果。

于是去查询了kernel bonding 文档 得知其hash 方式如下:

layer3+4

This policy uses upper layer protocol information,

when available, to generate the hash. This allows for

traffic to a particular network peer to span multiple

slaves, although a single connection will not span

multiple slaves.

The formula for unfragmented TCP and UDP packets is

hash = source port, destination port (as in the header)

hash = hash XOR source IP XOR destination IP

hash = hash XOR (hash RSHIFT 16)

hash = hash XOR (hash RSHIFT 8)

And then hash is reduced modulo slave count.

If the protocol is IPv6 then the source and destination

addresses are first hashed using ipv6_addr_hash.

For fragmented TCP or UDP packets and all other IPv4 and

IPv6 protocol traffic, the source and destination port

information is omitted. For non-IP traffic, the

formula is the same as for the layer2 transmit hash

policy.

This algorithm is not fully 802.3ad compliant. A

single TCP or UDP conversation containing both

fragmented and unfragmented packets will see packets

striped across two interfaces. This may result in out

of order delivery. Most traffic types will not meet

this criteria, as TCP rarely fragments traffic, and

most UDP traffic is not involved in extended

conversations. Other implementations of 802.3ad may

or may not tolerate this noncompliance.

但按照这个算法算下来的话,10001-10004 四个端口是可以分到四块网卡的。

1

2

3

4

5

6def xmit_hash(slaves, sport, dport, sip, dip):

hash = (sport << 16) + dport

hash = hash ^ sip ^ dip

hash = hash ^ (hash >> 16)

hash = hash ^ (hash >> 8)

return (hash % slaves)

搞不定,就去翻了下源码drivers/net/bonding/bond_main.c,结果发现这玩意居然和文档里写的不一样:

1

2

3

4

5

6hash ^= (__force u32)flow_get_u32_dst(&flow) ^

(__force u32)flow_get_u32_src(&flow);

hash ^= (hash >> 16);

hash ^= (hash >> 8);

return hash >> 1;

翻译成python 大概是:

1

2

3

4

5

6def xmit_hash(slaves, sport, dport, sip, dip):

hash = (sport << 16) + dport

hash = hash ^ sip ^ dip

hash = hash ^ (hash >> 16)

hash = hash ^ (hash >> 8)

return ((hash>>1) % slaves)

这个hash >> 1 就很讲究了,这样算出来在4 网卡聚合的情况下,保持源目的地址和目的端口不变,还是上面的例子,(2n, 2n+1)的源端口号会被分配到同一块卡上,就是10001 一块卡, 10002 和10003 一块卡,10004 一块卡。用三块卡,闲置一块卡,这样的结果确实和测试吻合。

那么为什么要这么搞呢?好在git log 里有答案:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37# git log -p b5f862180d7011d9575d0499fa37f0f25b423b12

Author: Hangbin Liu

Date: Mon Nov 6 09:01:57 2017 +0800

bonding: discard lowest hash bit for 802.3ad layer3+4

After commit 07f4c90062f8 ("tcp/dccp: try to not exhaust ip_local_port_range

in connect()"), we will try to use even ports for connect(). Then if an

application (seen clearly with iperf) opens multiple streams to the same

destination IP and port, each stream will be given an even source port.

So the bonding driver's simple xmit_hash_policy based on layer3+4 addressing

will always hash all these streams to the same interface. And the total

throughput will limited to a single slave.

Change the tcp code will impact the whole tcp behavior, only for bonding

usage. Paolo Abeni suggested fix this by changing the bonding code only,

which should be more reasonable, and less impact.

Fix this by discarding the lowest hash bit because it contains little entropy.

After the fix we can re-balance between slaves.

Signed-off-by: Paolo Abeni

Signed-off-by: Hangbin Liu

Signed-off-by: David S. Miller

diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c

index c99dc59d729b..76e8054bfc4e 100644

--- a/drivers/net/bonding/bond_main.c

+++ b/drivers/net/bonding/bond_main.c

@@ -3253,7 +3253,7 @@ u32 bond_xmit_hash(struct bonding *bond, struct sk_buff *skb)

hash ^= (hash >> 16);

hash ^= (hash >> 8);

- return hash;

+ return hash >> 1;

}

看名字这位仁兄好像还是个中国人,大意是在2015 的另一个提交07f4c90062f8 改变了一些随机端口号的使用规则,现在使用iperf3 等工具时,随机的源端口号是每次+2,而不是每次+1,这样如果还是原来的xmit_hash_policy 会有一些问题,例如4 网卡的话永远都只能hash 到两个卡。所以他舍弃了hash 的最后一位来应对这个变化。

这个commit 是在2017 年提交,在CentOS/RHEL 7.3 的3.10.0-514 内核中还没有被添加进去。

对于随机端口号每次+2 这个现象,之前用python 做测试的时候也遇见过不过没有深究,现在也找到了答案,算是缘分吧。

<think>好的,用户的问题是关于在Euler OS中配置网卡bonding模式4的指南。首先,我需要确认用户提到的bond mode 4对应的模式名称。常见的bonding模式中,mode 4是IEEE 802.3ad动态链路聚合(LACP),需要交换机的支持。接下来,我需要参考提供的引用内容,特别是引用[4]和[5],它们提到了使用nmcli命令和配置文件的方法。 首先,用户可能需要确认NetworkManager服务是否正常运行,这在引用[1]和[3]中提到过。然后,创建bond接口,使用nmcli命令添加类型为bond的连接,设置模式为802.3ad(即mode4)。引用[5]中的示例命令可以用来创建bond接口,但需要调整模式参数。另外,引用[4]中的配置文件示例可能需要修改BONDING_OPTS为mode=4。 还需要注意,在配置从属接口时,确保将物理网卡(如ens1f0和ens1f1)添加到bond接口中,并修改它们的配置文件,如引用[2]和[4]所述。同时,配置LACP需要交换机端也启用相应的设置,这一点需要提醒用户。 另外,用户可能需要验证配置是否生效,使用命令如ip link show或查看/proc/net/bonding/bond0的状态。最后,生成相关问题时要考虑用户可能遇到的后续问题,比如性能优化、模式选择等。</think>### 在Euler OS中配置网卡Bonding模式4(802.3ad动态链路聚合) #### 一、配置前提 1. **确认NetworkManager服务状态** ```bash systemctl status NetworkManager # 需显示active状态[^1] ``` 2. **准备物理网卡** 通过`ip a`或`nmcli device status`确认要绑定的网卡名称(如`ens1f0`、`ens1f1`)。 3. **交换机支持LACP协议** Bonding mode 4需要交换机启用802.3ad动态链路聚合[^4]。 --- #### 二、配置步骤(通过nmcli命令) 1. **创建Bond主接口** ```bash nmcli con add type bond con-name bond0 ifname bond0 \ mode 802.3ad \ ipv4.method manual \ ipv4.addresses 192.168.1.100/24 \ ipv4.gateway 192.168.1.1 \ ipv4.dns 8.8.8.8 ``` - `mode 802.3ad`对应Bonding mode4[^5] - 若需自定义参数,可添加`bond.options "miimon=100,lacp_rate=fast"` 2. **添加从属网卡到Bond** ```bash nmcli con add type bond-slave ifname ens1f0 master bond0 nmcli con add type bond-slave ifname ens1f1 master bond0 ``` 3. **激活配置** ```bash nmcli con up bond0 nmcli con up bond-slave-ens1f0 nmcli con up bond-slave-ens1f1 ``` --- #### 三、配置文件方法(兼容传统方式) 1. **创建Bond主接口配置文件** ```bash vi /etc/sysconfig/network-scripts/ifcfg-bond0 ``` 内容示例: ```ini DEVICE=bond0 NAME=bond0 TYPE=Bond BONDING_MASTER=yes IPADDR=192.168.1.100 NETMASK=255.255.255.0 GATEWAY=192.168.1.1 ONBOOT=yes BOOTPROTO=none BONDING_OPTS="mode=4 miimon=100 lacp_rate=1"[^4] ``` 2. **配置从属网卡** 修改`ifcfg-ens1f0`和`ifcfg-ens1f1`: ```ini DEVICE=ens1f0 NAME=ens1f0 TYPE=Ethernet MASTER=bond0 SLAVE=yes ONBOOT=yes ``` --- #### 四、验证配置 1. **查看bond状态** ```bash cat /proc/net/bonding/bond0 ``` 预期输出包含: ```text Bonding Mode: IEEE 802.3ad Dynamic link aggregation LACP rate: fast ``` 2. **网络连通性测试** ```bash ping 192.168.1.1 # 测试网关可达性 ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值