提交 fdb27c18 编写于 作者: T Tony Lu 提交者: openeuler-sync-bot

anolis: bond: broadcast ARP or ND messages to all slaves

anolis inclusion
from devel-5.10-v5.10.134-12
commit b90e28f7170e1ae40c572f9f80a50bbdc8f8b99f
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I697AN
CVE: NA

Reference: https://gitee.com/anolis/cloud-kernel/commit/b90e28f7170e1ae40c572f9f80a50bbdc8f8b99f

---------------------------

OpenAnolis Bug Tracker:0000282

This is achieved by broadcasting ARP or ND packets to all of its slave
devices on transmit side. The switch will take further actions based on
proper configuration.

A new sysctl knob "net.bonding.broadcast_arp_or_nd" is introduced which
controls the behaviour of broadcasting.

Signed-off-by: Tony Lu <tonylu(a)linux.alibaba.com>
Acked-by: Dust Li <dust.li(a)linux.alibaba.com>
Signed-off-by: Qiao Ma <mqaio(a)linux.alibaba.com>
Reviewed-by: Shile Zhang <shile.zhang(a)linux.alibaba.com>
Acked-by: Dust Li <dust.li(a)linux.alibaba.com>
Signed-off-by: Wang Yufen <wangyufen(a)huawei.com>
(cherry picked from commit 7c902772)
上级 92ae7769
......@@ -2665,3 +2665,14 @@ max_dgram_qlen - INTEGER
Default: 10
``/proc/sys/net/bonding/*``
========================
broadcast_arp_or_nd - INTEGER
Control broadcasting ARP or ND messages to all slaves
0: Not broadcasting
1: Broadcasting
Default: 0
......@@ -5,7 +5,7 @@
obj-$(CONFIG_BONDING) += bonding.o
bonding-objs := bond_main.o bond_3ad.o bond_alb.o bond_sysfs.o bond_sysfs_slave.o bond_debugfs.o bond_netlink.o bond_options.o
bonding-objs := bond_main.o bond_3ad.o bond_alb.o bond_sysfs.o bond_sysfs_slave.o bond_debugfs.o bond_netlink.o bond_options.o bond_sysctl.o
proc-$(CONFIG_PROC_FS) += bond_procfs.o
bonding-objs += $(proc-y)
......
......@@ -4559,6 +4559,39 @@ int bond_update_slave_arr(struct bonding *bond, struct slave *skipslave)
return ret;
}
/* Check whether the skb is arp or nd msg */
static inline bool skb_is_arp_or_nd(struct sk_buff *skb)
{
switch (ntohs(skb->protocol)) {
case ETH_P_ARP:
return true;
case ETH_P_IPV6:
if (pskb_may_pull(skb, sizeof(struct ipv6hdr) +
sizeof(struct nd_msg))) {
struct ipv6hdr *hdr = ipv6_hdr(skb);
u8 nexthdr = hdr->nexthdr;
struct icmp6hdr *icmp6;
if (nexthdr == IPPROTO_ICMPV6) {
icmp6 = icmp6_hdr(skb);
if ((icmp6->icmp6_type ==
NDISC_NEIGHBOUR_SOLICITATION ||
icmp6->icmp6_type ==
NDISC_NEIGHBOUR_ADVERTISEMENT) &&
icmp6->icmp6_code == 0) {
return true;
}
}
}
}
return false;
}
static netdev_tx_t bond_xmit_broadcast(struct sk_buff *skb,
struct net_device *bond_dev);
static struct slave *bond_xmit_3ad_xor_slave_get(struct bonding *bond,
struct sk_buff *skb,
struct bond_up_slave *slaves)
......@@ -4587,6 +4620,10 @@ static netdev_tx_t bond_3ad_xor_xmit(struct sk_buff *skb,
struct bond_up_slave *slaves;
struct slave *slave;
/* Broadcast to all slaves. */
if (sysctl_bond_broadcast_arp_or_nd && skb_is_arp_or_nd(skb))
return bond_xmit_broadcast(skb, dev);
slaves = rcu_dereference(bond->usable_slaves);
slave = bond_xmit_3ad_xor_slave_get(bond, skb, slaves);
if (likely(slave))
......@@ -5503,6 +5540,7 @@ static int __init bonding_init(void)
goto err_link;
bond_create_debugfs();
bond_create_sysctl();
for (i = 0; i < max_bonds; i++) {
res = bond_create(&init_net, NULL);
......@@ -5519,6 +5557,7 @@ static int __init bonding_init(void)
return res;
err:
bond_destroy_debugfs();
bond_destroy_sysctl();
bond_netlink_fini();
err_link:
unregister_pernet_subsys(&bond_net_ops);
......@@ -5531,6 +5570,7 @@ static void __exit bonding_exit(void)
unregister_netdevice_notifier(&bond_netdev_notifier);
bond_destroy_debugfs();
bond_destroy_sysctl();
bond_netlink_fini();
unregister_pernet_subsys(&bond_net_ops);
......
// SPDX-License-Identifier: GPL-2.0
#include <net/net_namespace.h>
#include <linux/sysctl.h>
#include <net/bonding.h>
int sysctl_bond_broadcast_arp_or_nd __read_mostly;
EXPORT_SYMBOL(sysctl_bond_broadcast_arp_or_nd);
struct ctl_table_header *bond_broadcast_arp_or_nd_table_header;
static struct ctl_table bond_broadcast_arp_or_nd_table[] = {
{
.procname = "broadcast_arp_or_nd",
.data = &sysctl_bond_broadcast_arp_or_nd,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = proc_dointvec,
},
{}
};
void bond_create_sysctl(void)
{
bond_broadcast_arp_or_nd_table_header =
register_net_sysctl(&init_net, "net/bonding",
bond_broadcast_arp_or_nd_table);
}
void bond_destroy_sysctl(void)
{
unregister_net_sysctl_table(bond_broadcast_arp_or_nd_table_header);
}
......@@ -114,6 +114,8 @@ static inline int is_netpoll_tx_blocked(struct net_device *dev)
#define is_netpoll_tx_blocked(dev) (0)
#endif
extern int sysctl_bond_broadcast_arp_or_nd;
struct bond_params {
int mode;
int xmit_policy;
......@@ -659,6 +661,8 @@ struct bond_vlan_tag *bond_verify_device_path(struct net_device *start_dev,
int bond_update_slave_arr(struct bonding *bond, struct slave *skipslave);
void bond_slave_arr_work_rearm(struct bonding *bond, unsigned long delay);
void bond_work_init_all(struct bonding *bond);
void bond_create_sysctl(void);
void bond_destroy_sysctl(void);
#ifdef CONFIG_PROC_FS
void bond_create_proc_entry(struct bonding *bond);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册