Unverified Commit cf303cf3 authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!1434 [sync] PR-346: anolis: bond: broadcast ARP or ND messages to all slaves

Merge Pull Request from: @openeuler-sync-bot 
 

Origin pull request: 
https://gitee.com/openeuler/kernel/pulls/346 
 
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. 
 
Link:https://gitee.com/openeuler/kernel/pulls/1434

 

Reviewed-by: default avatarYue Haibing <yuehaibing@huawei.com>
Signed-off-by: default avatarJialin Zhang <zhangjialin11@huawei.com>
parents 80e7361a 337eb92c
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -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
+1 −1
Original line number Diff line number Diff line
@@ -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)
+40 −0
Original line number Diff line number Diff line
@@ -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);
+32 −0
Original line number Diff line number Diff line
// 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);
}
+4 −0
Original line number Diff line number Diff line
@@ -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);