|
Thomas Bogendoerfer |
450565 |
From: Jie Wang <wangjie125@huawei.com>
|
|
Thomas Bogendoerfer |
450565 |
Date: Wed, 12 Jan 2022 20:54:18 +0800
|
|
Thomas Bogendoerfer |
450565 |
Subject: net: bonding: fix bond_xmit_broadcast return value error bug
|
|
Thomas Bogendoerfer |
450565 |
Patch-mainline: v5.17-rc1
|
|
Thomas Bogendoerfer |
450565 |
Git-commit: 4e5bd03ae34652cd932ab4c91c71c511793df75c
|
|
Thomas Bogendoerfer |
450565 |
References: git-fixes
|
|
Thomas Bogendoerfer |
450565 |
|
|
Thomas Bogendoerfer |
450565 |
In Linux bonding scenario, one packet is copied to several copies and sent
|
|
Thomas Bogendoerfer |
450565 |
by all slave device of bond0 in mode 3(broadcast mode). The mode 3 xmit
|
|
Thomas Bogendoerfer |
450565 |
function bond_xmit_broadcast() only ueses the last slave device's tx result
|
|
Thomas Bogendoerfer |
450565 |
as the final result. In this case, if the last slave device is down, then
|
|
Thomas Bogendoerfer |
450565 |
it always return NET_XMIT_DROP, even though the other slave devices xmit
|
|
Thomas Bogendoerfer |
450565 |
success. It may cause the tx statistics error, and cause the application
|
|
Thomas Bogendoerfer |
450565 |
(e.g. scp) consider the network is unreachable.
|
|
Thomas Bogendoerfer |
450565 |
|
|
Thomas Bogendoerfer |
450565 |
For example, use the following command to configure server A.
|
|
Thomas Bogendoerfer |
450565 |
|
|
Thomas Bogendoerfer |
450565 |
echo 3 > /sys/class/net/bond0/bonding/mode
|
|
Thomas Bogendoerfer |
450565 |
ifconfig bond0 up
|
|
Thomas Bogendoerfer |
450565 |
ifenslave bond0 eth0 eth1
|
|
Thomas Bogendoerfer |
450565 |
ifconfig bond0 192.168.1.125
|
|
Thomas Bogendoerfer |
450565 |
ifconfig eth0 up
|
|
Thomas Bogendoerfer |
450565 |
ifconfig eth1 down
|
|
Thomas Bogendoerfer |
450565 |
The slave device eth0 and eth1 are connected to server B(192.168.1.107).
|
|
Thomas Bogendoerfer |
450565 |
Run the ping 192.168.1.107 -c 3 -i 0.2 command, the following information
|
|
Thomas Bogendoerfer |
450565 |
is displayed.
|
|
Thomas Bogendoerfer |
450565 |
|
|
Thomas Bogendoerfer |
450565 |
PING 192.168.1.107 (192.168.1.107) 56(84) bytes of data.
|
|
Thomas Bogendoerfer |
450565 |
64 bytes from 192.168.1.107: icmp_seq=1 ttl=64 time=0.077 ms
|
|
Thomas Bogendoerfer |
450565 |
64 bytes from 192.168.1.107: icmp_seq=2 ttl=64 time=0.056 ms
|
|
Thomas Bogendoerfer |
450565 |
64 bytes from 192.168.1.107: icmp_seq=3 ttl=64 time=0.051 ms
|
|
Thomas Bogendoerfer |
450565 |
|
|
Thomas Bogendoerfer |
450565 |
192.168.1.107 ping statistics
|
|
Thomas Bogendoerfer |
450565 |
0 packets transmitted, 3 received
|
|
Thomas Bogendoerfer |
450565 |
|
|
Thomas Bogendoerfer |
450565 |
Actually, the slave device eth0 of the bond successfully sends three
|
|
Thomas Bogendoerfer |
450565 |
ICMP packets, but the result shows that 0 packets are transmitted.
|
|
Thomas Bogendoerfer |
450565 |
|
|
Thomas Bogendoerfer |
450565 |
Also if we use scp command to get remote files, the command end with the
|
|
Thomas Bogendoerfer |
450565 |
following printings.
|
|
Thomas Bogendoerfer |
450565 |
|
|
Thomas Bogendoerfer |
450565 |
ssh_exchange_identification: read: Connection timed out
|
|
Thomas Bogendoerfer |
450565 |
|
|
Thomas Bogendoerfer |
450565 |
So this patch modifies the bond_xmit_broadcast to return NET_XMIT_SUCCESS
|
|
Thomas Bogendoerfer |
450565 |
if one slave device in the bond sends packets successfully. If all slave
|
|
Thomas Bogendoerfer |
450565 |
devices send packets fail, the discarded packets stats is increased. The
|
|
Thomas Bogendoerfer |
450565 |
skb is released when there is no slave device in the bond or the last slave
|
|
Thomas Bogendoerfer |
450565 |
device is down.
|
|
Thomas Bogendoerfer |
450565 |
|
|
Thomas Bogendoerfer |
450565 |
Fixes: ae46f184bc1f ("bonding: propagate transmit status")
|
|
Thomas Bogendoerfer |
450565 |
Signed-off-by: Jie Wang <wangjie125@huawei.com>
|
|
Thomas Bogendoerfer |
450565 |
Signed-off-by: Guangbin Huang <huangguangbin2@huawei.com>
|
|
Thomas Bogendoerfer |
450565 |
Signed-off-by: David S. Miller <davem@davemloft.net>
|
|
Thomas Bogendoerfer |
450565 |
Acked-by: Thomas Bogendoerfer <tbogendoerfer@suse.de>
|
|
Thomas Bogendoerfer |
450565 |
---
|
|
Thomas Bogendoerfer |
450565 |
drivers/net/bonding/bond_main.c | 30 ++++++++++++++++++++++--------
|
|
Thomas Bogendoerfer |
450565 |
1 file changed, 22 insertions(+), 8 deletions(-)
|
|
Thomas Bogendoerfer |
450565 |
|
|
Thomas Bogendoerfer |
450565 |
--- a/drivers/net/bonding/bond_main.c
|
|
Thomas Bogendoerfer |
450565 |
+++ b/drivers/net/bonding/bond_main.c
|
|
Thomas Bogendoerfer |
450565 |
@@ -4631,25 +4631,39 @@ static netdev_tx_t bond_xmit_broadcast(s
|
|
Thomas Bogendoerfer |
450565 |
struct bonding *bond = netdev_priv(bond_dev);
|
|
Thomas Bogendoerfer |
450565 |
struct slave *slave = NULL;
|
|
Thomas Bogendoerfer |
450565 |
struct list_head *iter;
|
|
Thomas Bogendoerfer |
450565 |
+ bool xmit_suc = false;
|
|
Thomas Bogendoerfer |
450565 |
+ bool skb_used = false;
|
|
Thomas Bogendoerfer |
450565 |
|
|
Thomas Bogendoerfer |
450565 |
bond_for_each_slave_rcu(bond, slave, iter) {
|
|
Thomas Bogendoerfer |
450565 |
- if (bond_is_last_slave(bond, slave))
|
|
Thomas Bogendoerfer |
450565 |
- break;
|
|
Thomas Bogendoerfer |
450565 |
- if (bond_slave_is_up(slave) && slave->link == BOND_LINK_UP) {
|
|
Thomas Bogendoerfer |
450565 |
- struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
|
|
Thomas Bogendoerfer |
450565 |
+ struct sk_buff *skb2;
|
|
Thomas Bogendoerfer |
450565 |
|
|
Thomas Bogendoerfer |
450565 |
+ if (!(bond_slave_is_up(slave) && slave->link == BOND_LINK_UP))
|
|
Thomas Bogendoerfer |
450565 |
+ continue;
|
|
Thomas Bogendoerfer |
450565 |
+
|
|
Thomas Bogendoerfer |
450565 |
+ if (bond_is_last_slave(bond, slave)) {
|
|
Thomas Bogendoerfer |
450565 |
+ skb2 = skb;
|
|
Thomas Bogendoerfer |
450565 |
+ skb_used = true;
|
|
Thomas Bogendoerfer |
450565 |
+ } else {
|
|
Thomas Bogendoerfer |
450565 |
+ skb2 = skb_clone(skb, GFP_ATOMIC);
|
|
Thomas Bogendoerfer |
450565 |
if (!skb2) {
|
|
Thomas Bogendoerfer |
450565 |
net_err_ratelimited("%s: Error: %s: skb_clone() failed\n",
|
|
Thomas Bogendoerfer |
450565 |
bond_dev->name, __func__);
|
|
Thomas Bogendoerfer |
450565 |
continue;
|
|
Thomas Bogendoerfer |
450565 |
}
|
|
Thomas Bogendoerfer |
450565 |
- bond_dev_queue_xmit(bond, skb2, slave->dev);
|
|
Thomas Bogendoerfer |
450565 |
}
|
|
Thomas Bogendoerfer |
450565 |
+
|
|
Thomas Bogendoerfer |
450565 |
+ if (bond_dev_queue_xmit(bond, skb2, slave->dev) == NETDEV_TX_OK)
|
|
Thomas Bogendoerfer |
450565 |
+ xmit_suc = true;
|
|
Thomas Bogendoerfer |
450565 |
}
|
|
Thomas Bogendoerfer |
450565 |
- if (slave && bond_slave_is_up(slave) && slave->link == BOND_LINK_UP)
|
|
Thomas Bogendoerfer |
450565 |
- return bond_dev_queue_xmit(bond, skb, slave->dev);
|
|
Thomas Bogendoerfer |
450565 |
|
|
Thomas Bogendoerfer |
450565 |
- return bond_tx_drop(bond_dev, skb);
|
|
Thomas Bogendoerfer |
450565 |
+ if (!skb_used)
|
|
Thomas Bogendoerfer |
450565 |
+ dev_kfree_skb_any(skb);
|
|
Thomas Bogendoerfer |
450565 |
+
|
|
Thomas Bogendoerfer |
450565 |
+ if (xmit_suc)
|
|
Thomas Bogendoerfer |
450565 |
+ return NETDEV_TX_OK;
|
|
Thomas Bogendoerfer |
450565 |
+
|
|
Thomas Bogendoerfer |
450565 |
+ atomic_long_inc(&bond_dev->tx_dropped);
|
|
Thomas Bogendoerfer |
450565 |
+ return NET_XMIT_DROP;
|
|
Thomas Bogendoerfer |
450565 |
}
|
|
Thomas Bogendoerfer |
450565 |
|
|
Thomas Bogendoerfer |
450565 |
/*------------------------- Device initialization ---------------------------*/
|