18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * Bond several ethernet interfaces into a Cisco, running 'Etherchannel'.
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * Portions are (c) Copyright 1995 Simon "Guru Aleph-Null" Janes
58c2ecf20Sopenharmony_ci * NCM: Network and Communications Management, Inc.
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci * BUT, I'm the one who modified it for ethernet, so:
88c2ecf20Sopenharmony_ci * (c) Copyright 1999, Thomas Davis, tadavis@lbl.gov
98c2ecf20Sopenharmony_ci *
108c2ecf20Sopenharmony_ci *	This software may be used and distributed according to the terms
118c2ecf20Sopenharmony_ci *	of the GNU Public License, incorporated herein by reference.
128c2ecf20Sopenharmony_ci *
138c2ecf20Sopenharmony_ci */
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_ci#ifndef _NET_BONDING_H
168c2ecf20Sopenharmony_ci#define _NET_BONDING_H
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci#include <linux/timer.h>
198c2ecf20Sopenharmony_ci#include <linux/proc_fs.h>
208c2ecf20Sopenharmony_ci#include <linux/if_bonding.h>
218c2ecf20Sopenharmony_ci#include <linux/cpumask.h>
228c2ecf20Sopenharmony_ci#include <linux/in6.h>
238c2ecf20Sopenharmony_ci#include <linux/netpoll.h>
248c2ecf20Sopenharmony_ci#include <linux/inetdevice.h>
258c2ecf20Sopenharmony_ci#include <linux/etherdevice.h>
268c2ecf20Sopenharmony_ci#include <linux/reciprocal_div.h>
278c2ecf20Sopenharmony_ci#include <linux/if_link.h>
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_ci#include <net/bond_3ad.h>
308c2ecf20Sopenharmony_ci#include <net/bond_alb.h>
318c2ecf20Sopenharmony_ci#include <net/bond_options.h>
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci#define BOND_MAX_ARP_TARGETS	16
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci#define BOND_DEFAULT_MIIMON	100
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_ci#ifndef __long_aligned
388c2ecf20Sopenharmony_ci#define __long_aligned __attribute__((aligned((sizeof(long)))))
398c2ecf20Sopenharmony_ci#endif
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_ci#define slave_info(bond_dev, slave_dev, fmt, ...) \
428c2ecf20Sopenharmony_ci	netdev_info(bond_dev, "(slave %s): " fmt, (slave_dev)->name, ##__VA_ARGS__)
438c2ecf20Sopenharmony_ci#define slave_warn(bond_dev, slave_dev, fmt, ...) \
448c2ecf20Sopenharmony_ci	netdev_warn(bond_dev, "(slave %s): " fmt, (slave_dev)->name, ##__VA_ARGS__)
458c2ecf20Sopenharmony_ci#define slave_dbg(bond_dev, slave_dev, fmt, ...) \
468c2ecf20Sopenharmony_ci	netdev_dbg(bond_dev, "(slave %s): " fmt, (slave_dev)->name, ##__VA_ARGS__)
478c2ecf20Sopenharmony_ci#define slave_err(bond_dev, slave_dev, fmt, ...) \
488c2ecf20Sopenharmony_ci	netdev_err(bond_dev, "(slave %s): " fmt, (slave_dev)->name, ##__VA_ARGS__)
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ci#define BOND_MODE(bond) ((bond)->params.mode)
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_ci/* slave list primitives */
538c2ecf20Sopenharmony_ci#define bond_slave_list(bond) (&(bond)->dev->adj_list.lower)
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ci#define bond_has_slaves(bond) !list_empty(bond_slave_list(bond))
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_ci/* IMPORTANT: bond_first/last_slave can return NULL in case of an empty list */
588c2ecf20Sopenharmony_ci#define bond_first_slave(bond) \
598c2ecf20Sopenharmony_ci	(bond_has_slaves(bond) ? \
608c2ecf20Sopenharmony_ci		netdev_adjacent_get_private(bond_slave_list(bond)->next) : \
618c2ecf20Sopenharmony_ci		NULL)
628c2ecf20Sopenharmony_ci#define bond_last_slave(bond) \
638c2ecf20Sopenharmony_ci	(bond_has_slaves(bond) ? \
648c2ecf20Sopenharmony_ci		netdev_adjacent_get_private(bond_slave_list(bond)->prev) : \
658c2ecf20Sopenharmony_ci		NULL)
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_ci/* Caller must have rcu_read_lock */
688c2ecf20Sopenharmony_ci#define bond_first_slave_rcu(bond) \
698c2ecf20Sopenharmony_ci	netdev_lower_get_first_private_rcu(bond->dev)
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_ci#define bond_is_first_slave(bond, pos) (pos == bond_first_slave(bond))
728c2ecf20Sopenharmony_ci#define bond_is_last_slave(bond, pos) (pos == bond_last_slave(bond))
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ci/**
758c2ecf20Sopenharmony_ci * bond_for_each_slave - iterate over all slaves
768c2ecf20Sopenharmony_ci * @bond:	the bond holding this list
778c2ecf20Sopenharmony_ci * @pos:	current slave
788c2ecf20Sopenharmony_ci * @iter:	list_head * iterator
798c2ecf20Sopenharmony_ci *
808c2ecf20Sopenharmony_ci * Caller must hold RTNL
818c2ecf20Sopenharmony_ci */
828c2ecf20Sopenharmony_ci#define bond_for_each_slave(bond, pos, iter) \
838c2ecf20Sopenharmony_ci	netdev_for_each_lower_private((bond)->dev, pos, iter)
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_ci/* Caller must have rcu_read_lock */
868c2ecf20Sopenharmony_ci#define bond_for_each_slave_rcu(bond, pos, iter) \
878c2ecf20Sopenharmony_ci	netdev_for_each_lower_private_rcu((bond)->dev, pos, iter)
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_ci#define BOND_XFRM_FEATURES (NETIF_F_HW_ESP | NETIF_F_HW_ESP_TX_CSUM | \
908c2ecf20Sopenharmony_ci			    NETIF_F_GSO_ESP)
918c2ecf20Sopenharmony_ci
928c2ecf20Sopenharmony_ci#ifdef CONFIG_NET_POLL_CONTROLLER
938c2ecf20Sopenharmony_ciextern atomic_t netpoll_block_tx;
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_cistatic inline void block_netpoll_tx(void)
968c2ecf20Sopenharmony_ci{
978c2ecf20Sopenharmony_ci	atomic_inc(&netpoll_block_tx);
988c2ecf20Sopenharmony_ci}
998c2ecf20Sopenharmony_ci
1008c2ecf20Sopenharmony_cistatic inline void unblock_netpoll_tx(void)
1018c2ecf20Sopenharmony_ci{
1028c2ecf20Sopenharmony_ci	atomic_dec(&netpoll_block_tx);
1038c2ecf20Sopenharmony_ci}
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_cistatic inline int is_netpoll_tx_blocked(struct net_device *dev)
1068c2ecf20Sopenharmony_ci{
1078c2ecf20Sopenharmony_ci	if (unlikely(netpoll_tx_running(dev)))
1088c2ecf20Sopenharmony_ci		return atomic_read(&netpoll_block_tx);
1098c2ecf20Sopenharmony_ci	return 0;
1108c2ecf20Sopenharmony_ci}
1118c2ecf20Sopenharmony_ci#else
1128c2ecf20Sopenharmony_ci#define block_netpoll_tx()
1138c2ecf20Sopenharmony_ci#define unblock_netpoll_tx()
1148c2ecf20Sopenharmony_ci#define is_netpoll_tx_blocked(dev) (0)
1158c2ecf20Sopenharmony_ci#endif
1168c2ecf20Sopenharmony_ci
1178c2ecf20Sopenharmony_cistruct bond_params {
1188c2ecf20Sopenharmony_ci	int mode;
1198c2ecf20Sopenharmony_ci	int xmit_policy;
1208c2ecf20Sopenharmony_ci	int miimon;
1218c2ecf20Sopenharmony_ci	u8 num_peer_notif;
1228c2ecf20Sopenharmony_ci	int arp_interval;
1238c2ecf20Sopenharmony_ci	int arp_validate;
1248c2ecf20Sopenharmony_ci	int arp_all_targets;
1258c2ecf20Sopenharmony_ci	int use_carrier;
1268c2ecf20Sopenharmony_ci	int fail_over_mac;
1278c2ecf20Sopenharmony_ci	int updelay;
1288c2ecf20Sopenharmony_ci	int downdelay;
1298c2ecf20Sopenharmony_ci	int peer_notif_delay;
1308c2ecf20Sopenharmony_ci	int lacp_fast;
1318c2ecf20Sopenharmony_ci	unsigned int min_links;
1328c2ecf20Sopenharmony_ci	int ad_select;
1338c2ecf20Sopenharmony_ci	char primary[IFNAMSIZ];
1348c2ecf20Sopenharmony_ci	int primary_reselect;
1358c2ecf20Sopenharmony_ci	__be32 arp_targets[BOND_MAX_ARP_TARGETS];
1368c2ecf20Sopenharmony_ci	int tx_queues;
1378c2ecf20Sopenharmony_ci	int all_slaves_active;
1388c2ecf20Sopenharmony_ci	int resend_igmp;
1398c2ecf20Sopenharmony_ci	int lp_interval;
1408c2ecf20Sopenharmony_ci	int packets_per_slave;
1418c2ecf20Sopenharmony_ci	int tlb_dynamic_lb;
1428c2ecf20Sopenharmony_ci	struct reciprocal_value reciprocal_packets_per_slave;
1438c2ecf20Sopenharmony_ci	u16 ad_actor_sys_prio;
1448c2ecf20Sopenharmony_ci	u16 ad_user_port_key;
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_ci	/* 2 bytes of padding : see ether_addr_equal_64bits() */
1478c2ecf20Sopenharmony_ci	u8 ad_actor_system[ETH_ALEN + 2];
1488c2ecf20Sopenharmony_ci};
1498c2ecf20Sopenharmony_ci
1508c2ecf20Sopenharmony_cistruct bond_parm_tbl {
1518c2ecf20Sopenharmony_ci	char *modename;
1528c2ecf20Sopenharmony_ci	int mode;
1538c2ecf20Sopenharmony_ci};
1548c2ecf20Sopenharmony_ci
1558c2ecf20Sopenharmony_cistruct slave {
1568c2ecf20Sopenharmony_ci	struct net_device *dev; /* first - useful for panic debug */
1578c2ecf20Sopenharmony_ci	struct bonding *bond; /* our master */
1588c2ecf20Sopenharmony_ci	int    delay;
1598c2ecf20Sopenharmony_ci	/* all three in jiffies */
1608c2ecf20Sopenharmony_ci	unsigned long last_link_up;
1618c2ecf20Sopenharmony_ci	unsigned long last_rx;
1628c2ecf20Sopenharmony_ci	unsigned long target_last_arp_rx[BOND_MAX_ARP_TARGETS];
1638c2ecf20Sopenharmony_ci	s8     link;		/* one of BOND_LINK_XXXX */
1648c2ecf20Sopenharmony_ci	s8     link_new_state;	/* one of BOND_LINK_XXXX */
1658c2ecf20Sopenharmony_ci	u8     backup:1,   /* indicates backup slave. Value corresponds with
1668c2ecf20Sopenharmony_ci			      BOND_STATE_ACTIVE and BOND_STATE_BACKUP */
1678c2ecf20Sopenharmony_ci	       inactive:1, /* indicates inactive slave */
1688c2ecf20Sopenharmony_ci	       should_notify:1, /* indicates whether the state changed */
1698c2ecf20Sopenharmony_ci	       should_notify_link:1; /* indicates whether the link changed */
1708c2ecf20Sopenharmony_ci	u8     duplex;
1718c2ecf20Sopenharmony_ci	u32    original_mtu;
1728c2ecf20Sopenharmony_ci	u32    link_failure_count;
1738c2ecf20Sopenharmony_ci	u32    speed;
1748c2ecf20Sopenharmony_ci	u16    queue_id;
1758c2ecf20Sopenharmony_ci	u8     perm_hwaddr[MAX_ADDR_LEN];
1768c2ecf20Sopenharmony_ci	struct ad_slave_info *ad_info;
1778c2ecf20Sopenharmony_ci	struct tlb_slave_info tlb_info;
1788c2ecf20Sopenharmony_ci#ifdef CONFIG_NET_POLL_CONTROLLER
1798c2ecf20Sopenharmony_ci	struct netpoll *np;
1808c2ecf20Sopenharmony_ci#endif
1818c2ecf20Sopenharmony_ci	struct delayed_work notify_work;
1828c2ecf20Sopenharmony_ci	struct kobject kobj;
1838c2ecf20Sopenharmony_ci	struct rtnl_link_stats64 slave_stats;
1848c2ecf20Sopenharmony_ci};
1858c2ecf20Sopenharmony_ci
1868c2ecf20Sopenharmony_cistatic inline struct slave *to_slave(struct kobject *kobj)
1878c2ecf20Sopenharmony_ci{
1888c2ecf20Sopenharmony_ci	return container_of(kobj, struct slave, kobj);
1898c2ecf20Sopenharmony_ci}
1908c2ecf20Sopenharmony_ci
1918c2ecf20Sopenharmony_cistruct bond_up_slave {
1928c2ecf20Sopenharmony_ci	unsigned int	count;
1938c2ecf20Sopenharmony_ci	struct rcu_head rcu;
1948c2ecf20Sopenharmony_ci	struct slave	*arr[];
1958c2ecf20Sopenharmony_ci};
1968c2ecf20Sopenharmony_ci
1978c2ecf20Sopenharmony_ci/*
1988c2ecf20Sopenharmony_ci * Link pseudo-state only used internally by monitors
1998c2ecf20Sopenharmony_ci */
2008c2ecf20Sopenharmony_ci#define BOND_LINK_NOCHANGE -1
2018c2ecf20Sopenharmony_ci
2028c2ecf20Sopenharmony_cistruct bond_ipsec {
2038c2ecf20Sopenharmony_ci	struct list_head list;
2048c2ecf20Sopenharmony_ci	struct xfrm_state *xs;
2058c2ecf20Sopenharmony_ci};
2068c2ecf20Sopenharmony_ci
2078c2ecf20Sopenharmony_ci/*
2088c2ecf20Sopenharmony_ci * Here are the locking policies for the two bonding locks:
2098c2ecf20Sopenharmony_ci * Get rcu_read_lock when reading or RTNL when writing slave list.
2108c2ecf20Sopenharmony_ci */
2118c2ecf20Sopenharmony_cistruct bonding {
2128c2ecf20Sopenharmony_ci	struct   net_device *dev; /* first - useful for panic debug */
2138c2ecf20Sopenharmony_ci	struct   slave __rcu *curr_active_slave;
2148c2ecf20Sopenharmony_ci	struct   slave __rcu *current_arp_slave;
2158c2ecf20Sopenharmony_ci	struct   slave __rcu *primary_slave;
2168c2ecf20Sopenharmony_ci	struct   bond_up_slave __rcu *usable_slaves;
2178c2ecf20Sopenharmony_ci	struct   bond_up_slave __rcu *all_slaves;
2188c2ecf20Sopenharmony_ci	bool     force_primary;
2198c2ecf20Sopenharmony_ci	bool     notifier_ctx;
2208c2ecf20Sopenharmony_ci	s32      slave_cnt; /* never change this value outside the attach/detach wrappers */
2218c2ecf20Sopenharmony_ci	int     (*recv_probe)(const struct sk_buff *, struct bonding *,
2228c2ecf20Sopenharmony_ci			      struct slave *);
2238c2ecf20Sopenharmony_ci	/* mode_lock is used for mode-specific locking needs, currently used by:
2248c2ecf20Sopenharmony_ci	 * 3ad mode (4) - protect against running bond_3ad_unbind_slave() and
2258c2ecf20Sopenharmony_ci	 *                bond_3ad_state_machine_handler() concurrently and also
2268c2ecf20Sopenharmony_ci	 *                the access to the state machine shared variables.
2278c2ecf20Sopenharmony_ci	 * TLB mode (5) - to sync the use and modifications of its hash table
2288c2ecf20Sopenharmony_ci	 * ALB mode (6) - to sync the use and modifications of its hash table
2298c2ecf20Sopenharmony_ci	 */
2308c2ecf20Sopenharmony_ci	spinlock_t mode_lock;
2318c2ecf20Sopenharmony_ci	spinlock_t stats_lock;
2328c2ecf20Sopenharmony_ci	u8	 send_peer_notif;
2338c2ecf20Sopenharmony_ci	u8       igmp_retrans;
2348c2ecf20Sopenharmony_ci#ifdef CONFIG_PROC_FS
2358c2ecf20Sopenharmony_ci	struct   proc_dir_entry *proc_entry;
2368c2ecf20Sopenharmony_ci	char     proc_file_name[IFNAMSIZ];
2378c2ecf20Sopenharmony_ci#endif /* CONFIG_PROC_FS */
2388c2ecf20Sopenharmony_ci	struct   list_head bond_list;
2398c2ecf20Sopenharmony_ci	u32      rr_tx_counter;
2408c2ecf20Sopenharmony_ci	struct   ad_bond_info ad_info;
2418c2ecf20Sopenharmony_ci	struct   alb_bond_info alb_info;
2428c2ecf20Sopenharmony_ci	struct   bond_params params;
2438c2ecf20Sopenharmony_ci	struct   workqueue_struct *wq;
2448c2ecf20Sopenharmony_ci	struct   delayed_work mii_work;
2458c2ecf20Sopenharmony_ci	struct   delayed_work arp_work;
2468c2ecf20Sopenharmony_ci	struct   delayed_work alb_work;
2478c2ecf20Sopenharmony_ci	struct   delayed_work ad_work;
2488c2ecf20Sopenharmony_ci	struct   delayed_work mcast_work;
2498c2ecf20Sopenharmony_ci	struct   delayed_work slave_arr_work;
2508c2ecf20Sopenharmony_ci#ifdef CONFIG_DEBUG_FS
2518c2ecf20Sopenharmony_ci	/* debugging support via debugfs */
2528c2ecf20Sopenharmony_ci	struct	 dentry *debug_dir;
2538c2ecf20Sopenharmony_ci#endif /* CONFIG_DEBUG_FS */
2548c2ecf20Sopenharmony_ci	struct rtnl_link_stats64 bond_stats;
2558c2ecf20Sopenharmony_ci#ifdef CONFIG_XFRM_OFFLOAD
2568c2ecf20Sopenharmony_ci	struct list_head ipsec_list;
2578c2ecf20Sopenharmony_ci	/* protecting ipsec_list */
2588c2ecf20Sopenharmony_ci	spinlock_t ipsec_lock;
2598c2ecf20Sopenharmony_ci#endif /* CONFIG_XFRM_OFFLOAD */
2608c2ecf20Sopenharmony_ci};
2618c2ecf20Sopenharmony_ci
2628c2ecf20Sopenharmony_ci#define bond_slave_get_rcu(dev) \
2638c2ecf20Sopenharmony_ci	((struct slave *) rcu_dereference(dev->rx_handler_data))
2648c2ecf20Sopenharmony_ci
2658c2ecf20Sopenharmony_ci#define bond_slave_get_rtnl(dev) \
2668c2ecf20Sopenharmony_ci	((struct slave *) rtnl_dereference(dev->rx_handler_data))
2678c2ecf20Sopenharmony_ci
2688c2ecf20Sopenharmony_civoid bond_queue_slave_event(struct slave *slave);
2698c2ecf20Sopenharmony_civoid bond_lower_state_changed(struct slave *slave);
2708c2ecf20Sopenharmony_ci
2718c2ecf20Sopenharmony_cistruct bond_vlan_tag {
2728c2ecf20Sopenharmony_ci	__be16		vlan_proto;
2738c2ecf20Sopenharmony_ci	unsigned short	vlan_id;
2748c2ecf20Sopenharmony_ci};
2758c2ecf20Sopenharmony_ci
2768c2ecf20Sopenharmony_ci/**
2778c2ecf20Sopenharmony_ci * Returns NULL if the net_device does not belong to any of the bond's slaves
2788c2ecf20Sopenharmony_ci *
2798c2ecf20Sopenharmony_ci * Caller must hold bond lock for read
2808c2ecf20Sopenharmony_ci */
2818c2ecf20Sopenharmony_cistatic inline struct slave *bond_get_slave_by_dev(struct bonding *bond,
2828c2ecf20Sopenharmony_ci						  struct net_device *slave_dev)
2838c2ecf20Sopenharmony_ci{
2848c2ecf20Sopenharmony_ci	return netdev_lower_dev_get_private(bond->dev, slave_dev);
2858c2ecf20Sopenharmony_ci}
2868c2ecf20Sopenharmony_ci
2878c2ecf20Sopenharmony_cistatic inline struct bonding *bond_get_bond_by_slave(struct slave *slave)
2888c2ecf20Sopenharmony_ci{
2898c2ecf20Sopenharmony_ci	return slave->bond;
2908c2ecf20Sopenharmony_ci}
2918c2ecf20Sopenharmony_ci
2928c2ecf20Sopenharmony_cistatic inline bool bond_should_override_tx_queue(struct bonding *bond)
2938c2ecf20Sopenharmony_ci{
2948c2ecf20Sopenharmony_ci	return BOND_MODE(bond) == BOND_MODE_ACTIVEBACKUP ||
2958c2ecf20Sopenharmony_ci	       BOND_MODE(bond) == BOND_MODE_ROUNDROBIN;
2968c2ecf20Sopenharmony_ci}
2978c2ecf20Sopenharmony_ci
2988c2ecf20Sopenharmony_cistatic inline bool bond_is_lb(const struct bonding *bond)
2998c2ecf20Sopenharmony_ci{
3008c2ecf20Sopenharmony_ci	return BOND_MODE(bond) == BOND_MODE_TLB ||
3018c2ecf20Sopenharmony_ci	       BOND_MODE(bond) == BOND_MODE_ALB;
3028c2ecf20Sopenharmony_ci}
3038c2ecf20Sopenharmony_ci
3048c2ecf20Sopenharmony_cistatic inline bool bond_needs_speed_duplex(const struct bonding *bond)
3058c2ecf20Sopenharmony_ci{
3068c2ecf20Sopenharmony_ci	return BOND_MODE(bond) == BOND_MODE_8023AD || bond_is_lb(bond);
3078c2ecf20Sopenharmony_ci}
3088c2ecf20Sopenharmony_ci
3098c2ecf20Sopenharmony_cistatic inline bool bond_is_nondyn_tlb(const struct bonding *bond)
3108c2ecf20Sopenharmony_ci{
3118c2ecf20Sopenharmony_ci	return (bond_is_lb(bond) && bond->params.tlb_dynamic_lb == 0);
3128c2ecf20Sopenharmony_ci}
3138c2ecf20Sopenharmony_ci
3148c2ecf20Sopenharmony_cistatic inline bool bond_mode_can_use_xmit_hash(const struct bonding *bond)
3158c2ecf20Sopenharmony_ci{
3168c2ecf20Sopenharmony_ci	return (BOND_MODE(bond) == BOND_MODE_8023AD ||
3178c2ecf20Sopenharmony_ci		BOND_MODE(bond) == BOND_MODE_XOR ||
3188c2ecf20Sopenharmony_ci		BOND_MODE(bond) == BOND_MODE_TLB ||
3198c2ecf20Sopenharmony_ci		BOND_MODE(bond) == BOND_MODE_ALB);
3208c2ecf20Sopenharmony_ci}
3218c2ecf20Sopenharmony_ci
3228c2ecf20Sopenharmony_cistatic inline bool bond_mode_uses_xmit_hash(const struct bonding *bond)
3238c2ecf20Sopenharmony_ci{
3248c2ecf20Sopenharmony_ci	return (BOND_MODE(bond) == BOND_MODE_8023AD ||
3258c2ecf20Sopenharmony_ci		BOND_MODE(bond) == BOND_MODE_XOR ||
3268c2ecf20Sopenharmony_ci		bond_is_nondyn_tlb(bond));
3278c2ecf20Sopenharmony_ci}
3288c2ecf20Sopenharmony_ci
3298c2ecf20Sopenharmony_cistatic inline bool bond_mode_uses_arp(int mode)
3308c2ecf20Sopenharmony_ci{
3318c2ecf20Sopenharmony_ci	return mode != BOND_MODE_8023AD && mode != BOND_MODE_TLB &&
3328c2ecf20Sopenharmony_ci	       mode != BOND_MODE_ALB;
3338c2ecf20Sopenharmony_ci}
3348c2ecf20Sopenharmony_ci
3358c2ecf20Sopenharmony_cistatic inline bool bond_mode_uses_primary(int mode)
3368c2ecf20Sopenharmony_ci{
3378c2ecf20Sopenharmony_ci	return mode == BOND_MODE_ACTIVEBACKUP || mode == BOND_MODE_TLB ||
3388c2ecf20Sopenharmony_ci	       mode == BOND_MODE_ALB;
3398c2ecf20Sopenharmony_ci}
3408c2ecf20Sopenharmony_ci
3418c2ecf20Sopenharmony_cistatic inline bool bond_uses_primary(struct bonding *bond)
3428c2ecf20Sopenharmony_ci{
3438c2ecf20Sopenharmony_ci	return bond_mode_uses_primary(BOND_MODE(bond));
3448c2ecf20Sopenharmony_ci}
3458c2ecf20Sopenharmony_ci
3468c2ecf20Sopenharmony_cistatic inline struct net_device *bond_option_active_slave_get_rcu(struct bonding *bond)
3478c2ecf20Sopenharmony_ci{
3488c2ecf20Sopenharmony_ci	struct slave *slave = rcu_dereference(bond->curr_active_slave);
3498c2ecf20Sopenharmony_ci
3508c2ecf20Sopenharmony_ci	return bond_uses_primary(bond) && slave ? slave->dev : NULL;
3518c2ecf20Sopenharmony_ci}
3528c2ecf20Sopenharmony_ci
3538c2ecf20Sopenharmony_cistatic inline bool bond_slave_is_up(struct slave *slave)
3548c2ecf20Sopenharmony_ci{
3558c2ecf20Sopenharmony_ci	return netif_running(slave->dev) && netif_carrier_ok(slave->dev);
3568c2ecf20Sopenharmony_ci}
3578c2ecf20Sopenharmony_ci
3588c2ecf20Sopenharmony_cistatic inline void bond_set_active_slave(struct slave *slave)
3598c2ecf20Sopenharmony_ci{
3608c2ecf20Sopenharmony_ci	if (slave->backup) {
3618c2ecf20Sopenharmony_ci		slave->backup = 0;
3628c2ecf20Sopenharmony_ci		bond_queue_slave_event(slave);
3638c2ecf20Sopenharmony_ci		bond_lower_state_changed(slave);
3648c2ecf20Sopenharmony_ci	}
3658c2ecf20Sopenharmony_ci}
3668c2ecf20Sopenharmony_ci
3678c2ecf20Sopenharmony_cistatic inline void bond_set_backup_slave(struct slave *slave)
3688c2ecf20Sopenharmony_ci{
3698c2ecf20Sopenharmony_ci	if (!slave->backup) {
3708c2ecf20Sopenharmony_ci		slave->backup = 1;
3718c2ecf20Sopenharmony_ci		bond_queue_slave_event(slave);
3728c2ecf20Sopenharmony_ci		bond_lower_state_changed(slave);
3738c2ecf20Sopenharmony_ci	}
3748c2ecf20Sopenharmony_ci}
3758c2ecf20Sopenharmony_ci
3768c2ecf20Sopenharmony_cistatic inline void bond_set_slave_state(struct slave *slave,
3778c2ecf20Sopenharmony_ci					int slave_state, bool notify)
3788c2ecf20Sopenharmony_ci{
3798c2ecf20Sopenharmony_ci	if (slave->backup == slave_state)
3808c2ecf20Sopenharmony_ci		return;
3818c2ecf20Sopenharmony_ci
3828c2ecf20Sopenharmony_ci	slave->backup = slave_state;
3838c2ecf20Sopenharmony_ci	if (notify) {
3848c2ecf20Sopenharmony_ci		bond_lower_state_changed(slave);
3858c2ecf20Sopenharmony_ci		bond_queue_slave_event(slave);
3868c2ecf20Sopenharmony_ci		slave->should_notify = 0;
3878c2ecf20Sopenharmony_ci	} else {
3888c2ecf20Sopenharmony_ci		if (slave->should_notify)
3898c2ecf20Sopenharmony_ci			slave->should_notify = 0;
3908c2ecf20Sopenharmony_ci		else
3918c2ecf20Sopenharmony_ci			slave->should_notify = 1;
3928c2ecf20Sopenharmony_ci	}
3938c2ecf20Sopenharmony_ci}
3948c2ecf20Sopenharmony_ci
3958c2ecf20Sopenharmony_cistatic inline void bond_slave_state_change(struct bonding *bond)
3968c2ecf20Sopenharmony_ci{
3978c2ecf20Sopenharmony_ci	struct list_head *iter;
3988c2ecf20Sopenharmony_ci	struct slave *tmp;
3998c2ecf20Sopenharmony_ci
4008c2ecf20Sopenharmony_ci	bond_for_each_slave(bond, tmp, iter) {
4018c2ecf20Sopenharmony_ci		if (tmp->link == BOND_LINK_UP)
4028c2ecf20Sopenharmony_ci			bond_set_active_slave(tmp);
4038c2ecf20Sopenharmony_ci		else if (tmp->link == BOND_LINK_DOWN)
4048c2ecf20Sopenharmony_ci			bond_set_backup_slave(tmp);
4058c2ecf20Sopenharmony_ci	}
4068c2ecf20Sopenharmony_ci}
4078c2ecf20Sopenharmony_ci
4088c2ecf20Sopenharmony_cistatic inline void bond_slave_state_notify(struct bonding *bond)
4098c2ecf20Sopenharmony_ci{
4108c2ecf20Sopenharmony_ci	struct list_head *iter;
4118c2ecf20Sopenharmony_ci	struct slave *tmp;
4128c2ecf20Sopenharmony_ci
4138c2ecf20Sopenharmony_ci	bond_for_each_slave(bond, tmp, iter) {
4148c2ecf20Sopenharmony_ci		if (tmp->should_notify) {
4158c2ecf20Sopenharmony_ci			bond_lower_state_changed(tmp);
4168c2ecf20Sopenharmony_ci			tmp->should_notify = 0;
4178c2ecf20Sopenharmony_ci		}
4188c2ecf20Sopenharmony_ci	}
4198c2ecf20Sopenharmony_ci}
4208c2ecf20Sopenharmony_ci
4218c2ecf20Sopenharmony_cistatic inline int bond_slave_state(struct slave *slave)
4228c2ecf20Sopenharmony_ci{
4238c2ecf20Sopenharmony_ci	return slave->backup;
4248c2ecf20Sopenharmony_ci}
4258c2ecf20Sopenharmony_ci
4268c2ecf20Sopenharmony_cistatic inline bool bond_is_active_slave(struct slave *slave)
4278c2ecf20Sopenharmony_ci{
4288c2ecf20Sopenharmony_ci	return !bond_slave_state(slave);
4298c2ecf20Sopenharmony_ci}
4308c2ecf20Sopenharmony_ci
4318c2ecf20Sopenharmony_cistatic inline bool bond_slave_can_tx(struct slave *slave)
4328c2ecf20Sopenharmony_ci{
4338c2ecf20Sopenharmony_ci	return bond_slave_is_up(slave) && slave->link == BOND_LINK_UP &&
4348c2ecf20Sopenharmony_ci	       bond_is_active_slave(slave);
4358c2ecf20Sopenharmony_ci}
4368c2ecf20Sopenharmony_ci
4378c2ecf20Sopenharmony_cistatic inline bool bond_is_active_slave_dev(const struct net_device *slave_dev)
4388c2ecf20Sopenharmony_ci{
4398c2ecf20Sopenharmony_ci	struct slave *slave;
4408c2ecf20Sopenharmony_ci	bool active;
4418c2ecf20Sopenharmony_ci
4428c2ecf20Sopenharmony_ci	rcu_read_lock();
4438c2ecf20Sopenharmony_ci	slave = bond_slave_get_rcu(slave_dev);
4448c2ecf20Sopenharmony_ci	active = bond_is_active_slave(slave);
4458c2ecf20Sopenharmony_ci	rcu_read_unlock();
4468c2ecf20Sopenharmony_ci
4478c2ecf20Sopenharmony_ci	return active;
4488c2ecf20Sopenharmony_ci}
4498c2ecf20Sopenharmony_ci
4508c2ecf20Sopenharmony_cistatic inline void bond_hw_addr_copy(u8 *dst, const u8 *src, unsigned int len)
4518c2ecf20Sopenharmony_ci{
4528c2ecf20Sopenharmony_ci	if (len == ETH_ALEN) {
4538c2ecf20Sopenharmony_ci		ether_addr_copy(dst, src);
4548c2ecf20Sopenharmony_ci		return;
4558c2ecf20Sopenharmony_ci	}
4568c2ecf20Sopenharmony_ci
4578c2ecf20Sopenharmony_ci	memcpy(dst, src, len);
4588c2ecf20Sopenharmony_ci}
4598c2ecf20Sopenharmony_ci
4608c2ecf20Sopenharmony_ci#define BOND_PRI_RESELECT_ALWAYS	0
4618c2ecf20Sopenharmony_ci#define BOND_PRI_RESELECT_BETTER	1
4628c2ecf20Sopenharmony_ci#define BOND_PRI_RESELECT_FAILURE	2
4638c2ecf20Sopenharmony_ci
4648c2ecf20Sopenharmony_ci#define BOND_FOM_NONE			0
4658c2ecf20Sopenharmony_ci#define BOND_FOM_ACTIVE			1
4668c2ecf20Sopenharmony_ci#define BOND_FOM_FOLLOW			2
4678c2ecf20Sopenharmony_ci
4688c2ecf20Sopenharmony_ci#define BOND_ARP_TARGETS_ANY		0
4698c2ecf20Sopenharmony_ci#define BOND_ARP_TARGETS_ALL		1
4708c2ecf20Sopenharmony_ci
4718c2ecf20Sopenharmony_ci#define BOND_ARP_VALIDATE_NONE		0
4728c2ecf20Sopenharmony_ci#define BOND_ARP_VALIDATE_ACTIVE	(1 << BOND_STATE_ACTIVE)
4738c2ecf20Sopenharmony_ci#define BOND_ARP_VALIDATE_BACKUP	(1 << BOND_STATE_BACKUP)
4748c2ecf20Sopenharmony_ci#define BOND_ARP_VALIDATE_ALL		(BOND_ARP_VALIDATE_ACTIVE | \
4758c2ecf20Sopenharmony_ci					 BOND_ARP_VALIDATE_BACKUP)
4768c2ecf20Sopenharmony_ci#define BOND_ARP_FILTER			(BOND_ARP_VALIDATE_ALL + 1)
4778c2ecf20Sopenharmony_ci#define BOND_ARP_FILTER_ACTIVE		(BOND_ARP_VALIDATE_ACTIVE | \
4788c2ecf20Sopenharmony_ci					 BOND_ARP_FILTER)
4798c2ecf20Sopenharmony_ci#define BOND_ARP_FILTER_BACKUP		(BOND_ARP_VALIDATE_BACKUP | \
4808c2ecf20Sopenharmony_ci					 BOND_ARP_FILTER)
4818c2ecf20Sopenharmony_ci
4828c2ecf20Sopenharmony_ci#define BOND_SLAVE_NOTIFY_NOW		true
4838c2ecf20Sopenharmony_ci#define BOND_SLAVE_NOTIFY_LATER		false
4848c2ecf20Sopenharmony_ci
4858c2ecf20Sopenharmony_cistatic inline int slave_do_arp_validate(struct bonding *bond,
4868c2ecf20Sopenharmony_ci					struct slave *slave)
4878c2ecf20Sopenharmony_ci{
4888c2ecf20Sopenharmony_ci	return bond->params.arp_validate & (1 << bond_slave_state(slave));
4898c2ecf20Sopenharmony_ci}
4908c2ecf20Sopenharmony_ci
4918c2ecf20Sopenharmony_cistatic inline int slave_do_arp_validate_only(struct bonding *bond)
4928c2ecf20Sopenharmony_ci{
4938c2ecf20Sopenharmony_ci	return bond->params.arp_validate & BOND_ARP_FILTER;
4948c2ecf20Sopenharmony_ci}
4958c2ecf20Sopenharmony_ci
4968c2ecf20Sopenharmony_cistatic inline int bond_is_ip_target_ok(__be32 addr)
4978c2ecf20Sopenharmony_ci{
4988c2ecf20Sopenharmony_ci	return !ipv4_is_lbcast(addr) && !ipv4_is_zeronet(addr);
4998c2ecf20Sopenharmony_ci}
5008c2ecf20Sopenharmony_ci
5018c2ecf20Sopenharmony_ci/* Get the oldest arp which we've received on this slave for bond's
5028c2ecf20Sopenharmony_ci * arp_targets.
5038c2ecf20Sopenharmony_ci */
5048c2ecf20Sopenharmony_cistatic inline unsigned long slave_oldest_target_arp_rx(struct bonding *bond,
5058c2ecf20Sopenharmony_ci						       struct slave *slave)
5068c2ecf20Sopenharmony_ci{
5078c2ecf20Sopenharmony_ci	int i = 1;
5088c2ecf20Sopenharmony_ci	unsigned long ret = slave->target_last_arp_rx[0];
5098c2ecf20Sopenharmony_ci
5108c2ecf20Sopenharmony_ci	for (; (i < BOND_MAX_ARP_TARGETS) && bond->params.arp_targets[i]; i++)
5118c2ecf20Sopenharmony_ci		if (time_before(slave->target_last_arp_rx[i], ret))
5128c2ecf20Sopenharmony_ci			ret = slave->target_last_arp_rx[i];
5138c2ecf20Sopenharmony_ci
5148c2ecf20Sopenharmony_ci	return ret;
5158c2ecf20Sopenharmony_ci}
5168c2ecf20Sopenharmony_ci
5178c2ecf20Sopenharmony_cistatic inline unsigned long slave_last_rx(struct bonding *bond,
5188c2ecf20Sopenharmony_ci					struct slave *slave)
5198c2ecf20Sopenharmony_ci{
5208c2ecf20Sopenharmony_ci	if (bond->params.arp_all_targets == BOND_ARP_TARGETS_ALL)
5218c2ecf20Sopenharmony_ci		return slave_oldest_target_arp_rx(bond, slave);
5228c2ecf20Sopenharmony_ci
5238c2ecf20Sopenharmony_ci	return slave->last_rx;
5248c2ecf20Sopenharmony_ci}
5258c2ecf20Sopenharmony_ci
5268c2ecf20Sopenharmony_ci#ifdef CONFIG_NET_POLL_CONTROLLER
5278c2ecf20Sopenharmony_cistatic inline netdev_tx_t bond_netpoll_send_skb(const struct slave *slave,
5288c2ecf20Sopenharmony_ci					 struct sk_buff *skb)
5298c2ecf20Sopenharmony_ci{
5308c2ecf20Sopenharmony_ci	return netpoll_send_skb(slave->np, skb);
5318c2ecf20Sopenharmony_ci}
5328c2ecf20Sopenharmony_ci#else
5338c2ecf20Sopenharmony_cistatic inline netdev_tx_t bond_netpoll_send_skb(const struct slave *slave,
5348c2ecf20Sopenharmony_ci					 struct sk_buff *skb)
5358c2ecf20Sopenharmony_ci{
5368c2ecf20Sopenharmony_ci	BUG();
5378c2ecf20Sopenharmony_ci	return NETDEV_TX_OK;
5388c2ecf20Sopenharmony_ci}
5398c2ecf20Sopenharmony_ci#endif
5408c2ecf20Sopenharmony_ci
5418c2ecf20Sopenharmony_cistatic inline void bond_set_slave_inactive_flags(struct slave *slave,
5428c2ecf20Sopenharmony_ci						 bool notify)
5438c2ecf20Sopenharmony_ci{
5448c2ecf20Sopenharmony_ci	if (!bond_is_lb(slave->bond))
5458c2ecf20Sopenharmony_ci		bond_set_slave_state(slave, BOND_STATE_BACKUP, notify);
5468c2ecf20Sopenharmony_ci	if (!slave->bond->params.all_slaves_active)
5478c2ecf20Sopenharmony_ci		slave->inactive = 1;
5488c2ecf20Sopenharmony_ci}
5498c2ecf20Sopenharmony_ci
5508c2ecf20Sopenharmony_cistatic inline void bond_set_slave_active_flags(struct slave *slave,
5518c2ecf20Sopenharmony_ci					       bool notify)
5528c2ecf20Sopenharmony_ci{
5538c2ecf20Sopenharmony_ci	bond_set_slave_state(slave, BOND_STATE_ACTIVE, notify);
5548c2ecf20Sopenharmony_ci	slave->inactive = 0;
5558c2ecf20Sopenharmony_ci}
5568c2ecf20Sopenharmony_ci
5578c2ecf20Sopenharmony_cistatic inline bool bond_is_slave_inactive(struct slave *slave)
5588c2ecf20Sopenharmony_ci{
5598c2ecf20Sopenharmony_ci	return slave->inactive;
5608c2ecf20Sopenharmony_ci}
5618c2ecf20Sopenharmony_ci
5628c2ecf20Sopenharmony_cistatic inline void bond_propose_link_state(struct slave *slave, int state)
5638c2ecf20Sopenharmony_ci{
5648c2ecf20Sopenharmony_ci	slave->link_new_state = state;
5658c2ecf20Sopenharmony_ci}
5668c2ecf20Sopenharmony_ci
5678c2ecf20Sopenharmony_cistatic inline void bond_commit_link_state(struct slave *slave, bool notify)
5688c2ecf20Sopenharmony_ci{
5698c2ecf20Sopenharmony_ci	if (slave->link_new_state == BOND_LINK_NOCHANGE)
5708c2ecf20Sopenharmony_ci		return;
5718c2ecf20Sopenharmony_ci
5728c2ecf20Sopenharmony_ci	slave->link = slave->link_new_state;
5738c2ecf20Sopenharmony_ci	if (notify) {
5748c2ecf20Sopenharmony_ci		bond_queue_slave_event(slave);
5758c2ecf20Sopenharmony_ci		bond_lower_state_changed(slave);
5768c2ecf20Sopenharmony_ci		slave->should_notify_link = 0;
5778c2ecf20Sopenharmony_ci	} else {
5788c2ecf20Sopenharmony_ci		if (slave->should_notify_link)
5798c2ecf20Sopenharmony_ci			slave->should_notify_link = 0;
5808c2ecf20Sopenharmony_ci		else
5818c2ecf20Sopenharmony_ci			slave->should_notify_link = 1;
5828c2ecf20Sopenharmony_ci	}
5838c2ecf20Sopenharmony_ci}
5848c2ecf20Sopenharmony_ci
5858c2ecf20Sopenharmony_cistatic inline void bond_set_slave_link_state(struct slave *slave, int state,
5868c2ecf20Sopenharmony_ci					     bool notify)
5878c2ecf20Sopenharmony_ci{
5888c2ecf20Sopenharmony_ci	bond_propose_link_state(slave, state);
5898c2ecf20Sopenharmony_ci	bond_commit_link_state(slave, notify);
5908c2ecf20Sopenharmony_ci}
5918c2ecf20Sopenharmony_ci
5928c2ecf20Sopenharmony_cistatic inline void bond_slave_link_notify(struct bonding *bond)
5938c2ecf20Sopenharmony_ci{
5948c2ecf20Sopenharmony_ci	struct list_head *iter;
5958c2ecf20Sopenharmony_ci	struct slave *tmp;
5968c2ecf20Sopenharmony_ci
5978c2ecf20Sopenharmony_ci	bond_for_each_slave(bond, tmp, iter) {
5988c2ecf20Sopenharmony_ci		if (tmp->should_notify_link) {
5998c2ecf20Sopenharmony_ci			bond_queue_slave_event(tmp);
6008c2ecf20Sopenharmony_ci			bond_lower_state_changed(tmp);
6018c2ecf20Sopenharmony_ci			tmp->should_notify_link = 0;
6028c2ecf20Sopenharmony_ci		}
6038c2ecf20Sopenharmony_ci	}
6048c2ecf20Sopenharmony_ci}
6058c2ecf20Sopenharmony_ci
6068c2ecf20Sopenharmony_cistatic inline __be32 bond_confirm_addr(struct net_device *dev, __be32 dst, __be32 local)
6078c2ecf20Sopenharmony_ci{
6088c2ecf20Sopenharmony_ci	struct in_device *in_dev;
6098c2ecf20Sopenharmony_ci	__be32 addr = 0;
6108c2ecf20Sopenharmony_ci
6118c2ecf20Sopenharmony_ci	rcu_read_lock();
6128c2ecf20Sopenharmony_ci	in_dev = __in_dev_get_rcu(dev);
6138c2ecf20Sopenharmony_ci
6148c2ecf20Sopenharmony_ci	if (in_dev)
6158c2ecf20Sopenharmony_ci		addr = inet_confirm_addr(dev_net(dev), in_dev, dst, local,
6168c2ecf20Sopenharmony_ci					 RT_SCOPE_HOST);
6178c2ecf20Sopenharmony_ci	rcu_read_unlock();
6188c2ecf20Sopenharmony_ci	return addr;
6198c2ecf20Sopenharmony_ci}
6208c2ecf20Sopenharmony_ci
6218c2ecf20Sopenharmony_cistruct bond_net {
6228c2ecf20Sopenharmony_ci	struct net		*net;	/* Associated network namespace */
6238c2ecf20Sopenharmony_ci	struct list_head	dev_list;
6248c2ecf20Sopenharmony_ci#ifdef CONFIG_PROC_FS
6258c2ecf20Sopenharmony_ci	struct proc_dir_entry	*proc_dir;
6268c2ecf20Sopenharmony_ci#endif
6278c2ecf20Sopenharmony_ci	struct class_attribute	class_attr_bonding_masters;
6288c2ecf20Sopenharmony_ci};
6298c2ecf20Sopenharmony_ci
6308c2ecf20Sopenharmony_ciint bond_arp_rcv(const struct sk_buff *skb, struct bonding *bond, struct slave *slave);
6318c2ecf20Sopenharmony_cinetdev_tx_t bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, struct net_device *slave_dev);
6328c2ecf20Sopenharmony_ciint bond_create(struct net *net, const char *name);
6338c2ecf20Sopenharmony_ciint bond_create_sysfs(struct bond_net *net);
6348c2ecf20Sopenharmony_civoid bond_destroy_sysfs(struct bond_net *net);
6358c2ecf20Sopenharmony_civoid bond_prepare_sysfs_group(struct bonding *bond);
6368c2ecf20Sopenharmony_ciint bond_sysfs_slave_add(struct slave *slave);
6378c2ecf20Sopenharmony_civoid bond_sysfs_slave_del(struct slave *slave);
6388c2ecf20Sopenharmony_ciint bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev,
6398c2ecf20Sopenharmony_ci		 struct netlink_ext_ack *extack);
6408c2ecf20Sopenharmony_ciint bond_release(struct net_device *bond_dev, struct net_device *slave_dev);
6418c2ecf20Sopenharmony_ciu32 bond_xmit_hash(struct bonding *bond, struct sk_buff *skb);
6428c2ecf20Sopenharmony_ciint bond_set_carrier(struct bonding *bond);
6438c2ecf20Sopenharmony_civoid bond_select_active_slave(struct bonding *bond);
6448c2ecf20Sopenharmony_civoid bond_change_active_slave(struct bonding *bond, struct slave *new_active);
6458c2ecf20Sopenharmony_civoid bond_create_debugfs(void);
6468c2ecf20Sopenharmony_civoid bond_destroy_debugfs(void);
6478c2ecf20Sopenharmony_civoid bond_debug_register(struct bonding *bond);
6488c2ecf20Sopenharmony_civoid bond_debug_unregister(struct bonding *bond);
6498c2ecf20Sopenharmony_civoid bond_debug_reregister(struct bonding *bond);
6508c2ecf20Sopenharmony_ciconst char *bond_mode_name(int mode);
6518c2ecf20Sopenharmony_civoid bond_setup(struct net_device *bond_dev);
6528c2ecf20Sopenharmony_ciunsigned int bond_get_num_tx_queues(void);
6538c2ecf20Sopenharmony_ciint bond_netlink_init(void);
6548c2ecf20Sopenharmony_civoid bond_netlink_fini(void);
6558c2ecf20Sopenharmony_cistruct net_device *bond_option_active_slave_get_rcu(struct bonding *bond);
6568c2ecf20Sopenharmony_ciconst char *bond_slave_link_status(s8 link);
6578c2ecf20Sopenharmony_cistruct bond_vlan_tag *bond_verify_device_path(struct net_device *start_dev,
6588c2ecf20Sopenharmony_ci					      struct net_device *end_dev,
6598c2ecf20Sopenharmony_ci					      int level);
6608c2ecf20Sopenharmony_ciint bond_update_slave_arr(struct bonding *bond, struct slave *skipslave);
6618c2ecf20Sopenharmony_civoid bond_slave_arr_work_rearm(struct bonding *bond, unsigned long delay);
6628c2ecf20Sopenharmony_civoid bond_work_init_all(struct bonding *bond);
6638c2ecf20Sopenharmony_ci
6648c2ecf20Sopenharmony_ci#ifdef CONFIG_PROC_FS
6658c2ecf20Sopenharmony_civoid bond_create_proc_entry(struct bonding *bond);
6668c2ecf20Sopenharmony_civoid bond_remove_proc_entry(struct bonding *bond);
6678c2ecf20Sopenharmony_civoid bond_create_proc_dir(struct bond_net *bn);
6688c2ecf20Sopenharmony_civoid bond_destroy_proc_dir(struct bond_net *bn);
6698c2ecf20Sopenharmony_ci#else
6708c2ecf20Sopenharmony_cistatic inline void bond_create_proc_entry(struct bonding *bond)
6718c2ecf20Sopenharmony_ci{
6728c2ecf20Sopenharmony_ci}
6738c2ecf20Sopenharmony_ci
6748c2ecf20Sopenharmony_cistatic inline void bond_remove_proc_entry(struct bonding *bond)
6758c2ecf20Sopenharmony_ci{
6768c2ecf20Sopenharmony_ci}
6778c2ecf20Sopenharmony_ci
6788c2ecf20Sopenharmony_cistatic inline void bond_create_proc_dir(struct bond_net *bn)
6798c2ecf20Sopenharmony_ci{
6808c2ecf20Sopenharmony_ci}
6818c2ecf20Sopenharmony_ci
6828c2ecf20Sopenharmony_cistatic inline void bond_destroy_proc_dir(struct bond_net *bn)
6838c2ecf20Sopenharmony_ci{
6848c2ecf20Sopenharmony_ci}
6858c2ecf20Sopenharmony_ci#endif
6868c2ecf20Sopenharmony_ci
6878c2ecf20Sopenharmony_cistatic inline struct slave *bond_slave_has_mac(struct bonding *bond,
6888c2ecf20Sopenharmony_ci					       const u8 *mac)
6898c2ecf20Sopenharmony_ci{
6908c2ecf20Sopenharmony_ci	struct list_head *iter;
6918c2ecf20Sopenharmony_ci	struct slave *tmp;
6928c2ecf20Sopenharmony_ci
6938c2ecf20Sopenharmony_ci	bond_for_each_slave(bond, tmp, iter)
6948c2ecf20Sopenharmony_ci		if (ether_addr_equal_64bits(mac, tmp->dev->dev_addr))
6958c2ecf20Sopenharmony_ci			return tmp;
6968c2ecf20Sopenharmony_ci
6978c2ecf20Sopenharmony_ci	return NULL;
6988c2ecf20Sopenharmony_ci}
6998c2ecf20Sopenharmony_ci
7008c2ecf20Sopenharmony_ci/* Caller must hold rcu_read_lock() for read */
7018c2ecf20Sopenharmony_cistatic inline bool bond_slave_has_mac_rcu(struct bonding *bond, const u8 *mac)
7028c2ecf20Sopenharmony_ci{
7038c2ecf20Sopenharmony_ci	struct list_head *iter;
7048c2ecf20Sopenharmony_ci	struct slave *tmp;
7058c2ecf20Sopenharmony_ci
7068c2ecf20Sopenharmony_ci	bond_for_each_slave_rcu(bond, tmp, iter)
7078c2ecf20Sopenharmony_ci		if (ether_addr_equal_64bits(mac, tmp->dev->dev_addr))
7088c2ecf20Sopenharmony_ci			return true;
7098c2ecf20Sopenharmony_ci	return false;
7108c2ecf20Sopenharmony_ci}
7118c2ecf20Sopenharmony_ci
7128c2ecf20Sopenharmony_ci/* Check if the ip is present in arp ip list, or first free slot if ip == 0
7138c2ecf20Sopenharmony_ci * Returns -1 if not found, index if found
7148c2ecf20Sopenharmony_ci */
7158c2ecf20Sopenharmony_cistatic inline int bond_get_targets_ip(__be32 *targets, __be32 ip)
7168c2ecf20Sopenharmony_ci{
7178c2ecf20Sopenharmony_ci	int i;
7188c2ecf20Sopenharmony_ci
7198c2ecf20Sopenharmony_ci	for (i = 0; i < BOND_MAX_ARP_TARGETS; i++)
7208c2ecf20Sopenharmony_ci		if (targets[i] == ip)
7218c2ecf20Sopenharmony_ci			return i;
7228c2ecf20Sopenharmony_ci		else if (targets[i] == 0)
7238c2ecf20Sopenharmony_ci			break;
7248c2ecf20Sopenharmony_ci
7258c2ecf20Sopenharmony_ci	return -1;
7268c2ecf20Sopenharmony_ci}
7278c2ecf20Sopenharmony_ci
7288c2ecf20Sopenharmony_ci/* exported from bond_main.c */
7298c2ecf20Sopenharmony_ciextern unsigned int bond_net_id;
7308c2ecf20Sopenharmony_ciextern const struct bond_parm_tbl bond_lacp_tbl[];
7318c2ecf20Sopenharmony_ciextern const struct bond_parm_tbl xmit_hashtype_tbl[];
7328c2ecf20Sopenharmony_ciextern const struct bond_parm_tbl arp_validate_tbl[];
7338c2ecf20Sopenharmony_ciextern const struct bond_parm_tbl arp_all_targets_tbl[];
7348c2ecf20Sopenharmony_ciextern const struct bond_parm_tbl fail_over_mac_tbl[];
7358c2ecf20Sopenharmony_ciextern const struct bond_parm_tbl pri_reselect_tbl[];
7368c2ecf20Sopenharmony_ciextern struct bond_parm_tbl ad_select_tbl[];
7378c2ecf20Sopenharmony_ci
7388c2ecf20Sopenharmony_ci/* exported from bond_netlink.c */
7398c2ecf20Sopenharmony_ciextern struct rtnl_link_ops bond_link_ops;
7408c2ecf20Sopenharmony_ci
7418c2ecf20Sopenharmony_ci/* exported from bond_sysfs_slave.c */
7428c2ecf20Sopenharmony_ciextern const struct sysfs_ops slave_sysfs_ops;
7438c2ecf20Sopenharmony_ci
7448c2ecf20Sopenharmony_ci/* exported from bond_3ad.c */
7458c2ecf20Sopenharmony_ciextern const u8 lacpdu_mcast_addr[];
7468c2ecf20Sopenharmony_ci
7478c2ecf20Sopenharmony_cistatic inline netdev_tx_t bond_tx_drop(struct net_device *dev, struct sk_buff *skb)
7488c2ecf20Sopenharmony_ci{
7498c2ecf20Sopenharmony_ci	atomic_long_inc(&dev->tx_dropped);
7508c2ecf20Sopenharmony_ci	dev_kfree_skb_any(skb);
7518c2ecf20Sopenharmony_ci	return NET_XMIT_DROP;
7528c2ecf20Sopenharmony_ci}
7538c2ecf20Sopenharmony_ci
7548c2ecf20Sopenharmony_ci#endif /* _NET_BONDING_H */
755