Commit 5d99ec3a authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'bonding-per-port-priorities'



Hangbin Liu says:

====================
Bonding: add per-port priority support

This patch set add per-port priority for bonding failover re-selection.

The first patch add a new filed for bond_opt_value so we can set slave
value easier. I will update the bond_option_queue_id_set() setting
in later patch.

The second patch add the per-port priority for bonding. I defined
it as s32 to compatible with team prio option, which also use a s32
value.

v3: store slave_dev in bond_opt_value directly to simplify setting
    values for slave.

v2: using the extant bonding options management stuff instead setting
    slave prio in bond_slave_changelink() directly.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 7747de17 0a2ff7cc
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -780,6 +780,17 @@ peer_notif_delay
	value is 0 which means to match the value of the link monitor
	interval.

prio
	Slave priority. A higher number means higher priority.
	The primary slave has the highest priority. This option also
	follows the primary_reselect rules.

	This option could only be configured via netlink, and is only valid
	for active-backup(1), balance-tlb (5) and balance-alb (6) mode.
	The valid value range is a signed 32 bit integer.

	The default value is 0.

primary

	A string (eth0, eth2, etc) specifying which slave is the
+27 −0
Original line number Diff line number Diff line
@@ -1026,12 +1026,38 @@ static void bond_do_fail_over_mac(struct bonding *bond,

}

/**
 * bond_choose_primary_or_current - select the primary or high priority slave
 * @bond: our bonding struct
 *
 * - Check if there is a primary link. If the primary link was set and is up,
 *   go on and do link reselection.
 *
 * - If primary link is not set or down, find the highest priority link.
 *   If the highest priority link is not current slave, set it as primary
 *   link and do link reselection.
 */
static struct slave *bond_choose_primary_or_current(struct bonding *bond)
{
	struct slave *prim = rtnl_dereference(bond->primary_slave);
	struct slave *curr = rtnl_dereference(bond->curr_active_slave);
	struct slave *slave, *hprio = NULL;
	struct list_head *iter;

	if (!prim || prim->link != BOND_LINK_UP) {
		bond_for_each_slave(bond, slave, iter) {
			if (slave->link == BOND_LINK_UP) {
				hprio = hprio ?: slave;
				if (slave->prio > hprio->prio)
					hprio = slave;
			}
		}

		if (hprio && hprio != curr) {
			prim = hprio;
			goto link_reselect;
		}

		if (!curr || curr->link != BOND_LINK_UP)
			return NULL;
		return curr;
@@ -1042,6 +1068,7 @@ static struct slave *bond_choose_primary_or_current(struct bonding *bond)
		return prim;
	}

link_reselect:
	if (!curr || curr->link != BOND_LINK_UP)
		return prim;

+15 −0
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ static size_t bond_get_slave_size(const struct net_device *bond_dev,
		nla_total_size(sizeof(u16)) +	/* IFLA_BOND_SLAVE_AD_AGGREGATOR_ID */
		nla_total_size(sizeof(u8)) +	/* IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE */
		nla_total_size(sizeof(u16)) +	/* IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE */
		nla_total_size(sizeof(s32)) +	/* IFLA_BOND_SLAVE_PRIO */
		0;
}

@@ -53,6 +54,9 @@ static int bond_fill_slave_info(struct sk_buff *skb,
	if (nla_put_u16(skb, IFLA_BOND_SLAVE_QUEUE_ID, slave->queue_id))
		goto nla_put_failure;

	if (nla_put_s32(skb, IFLA_BOND_SLAVE_PRIO, slave->prio))
		goto nla_put_failure;

	if (BOND_MODE(slave->bond) == BOND_MODE_8023AD) {
		const struct aggregator *agg;
		const struct port *ad_port;
@@ -117,6 +121,7 @@ static const struct nla_policy bond_policy[IFLA_BOND_MAX + 1] = {

static const struct nla_policy bond_slave_policy[IFLA_BOND_SLAVE_MAX + 1] = {
	[IFLA_BOND_SLAVE_QUEUE_ID]	= { .type = NLA_U16 },
	[IFLA_BOND_SLAVE_PRIO]		= { .type = NLA_S32 },
};

static int bond_validate(struct nlattr *tb[], struct nlattr *data[],
@@ -157,6 +162,16 @@ static int bond_slave_changelink(struct net_device *bond_dev,
			return err;
	}

	if (data[IFLA_BOND_SLAVE_PRIO]) {
		int prio = nla_get_s32(data[IFLA_BOND_SLAVE_PRIO]);

		bond_opt_slave_initval(&newval, &slave_dev, prio);
		err = __bond_opt_set(bond, BOND_OPT_PRIO, &newval,
				     data[IFLA_BOND_SLAVE_PRIO], extack);
		if (err)
			return err;
	}

	return 0;
}

+33 −0
Original line number Diff line number Diff line
@@ -40,6 +40,8 @@ static int bond_option_arp_validate_set(struct bonding *bond,
					const struct bond_opt_value *newval);
static int bond_option_arp_all_targets_set(struct bonding *bond,
					   const struct bond_opt_value *newval);
static int bond_option_prio_set(struct bonding *bond,
				const struct bond_opt_value *newval);
static int bond_option_primary_set(struct bonding *bond,
				   const struct bond_opt_value *newval);
static int bond_option_primary_reselect_set(struct bonding *bond,
@@ -365,6 +367,16 @@ static const struct bond_option bond_opts[BOND_OPT_LAST] = {
		.values = bond_intmax_tbl,
		.set = bond_option_miimon_set
	},
	[BOND_OPT_PRIO] = {
		.id = BOND_OPT_PRIO,
		.name = "prio",
		.desc = "Link priority for failover re-selection",
		.flags = BOND_OPTFLAG_RAWVAL,
		.unsuppmodes = BOND_MODE_ALL_EX(BIT(BOND_MODE_ACTIVEBACKUP) |
						BIT(BOND_MODE_TLB) |
						BIT(BOND_MODE_ALB)),
		.set = bond_option_prio_set
	},
	[BOND_OPT_PRIMARY] = {
		.id = BOND_OPT_PRIMARY,
		.name = "primary",
@@ -1306,6 +1318,27 @@ static int bond_option_missed_max_set(struct bonding *bond,
	return 0;
}

static int bond_option_prio_set(struct bonding *bond,
				const struct bond_opt_value *newval)
{
	struct slave *slave;

	slave = bond_slave_get_rtnl(newval->slave_dev);
	if (!slave) {
		netdev_dbg(newval->slave_dev, "%s called on NULL slave\n", __func__);
		return -ENODEV;
	}
	slave->prio = newval->value;

	if (rtnl_dereference(bond->primary_slave))
		slave_warn(bond->dev, slave->dev,
			   "prio updated, but will not affect failover re-selection as primary slave have been set\n");
	else
		bond_select_active_slave(bond);

	return 0;
}

static int bond_option_primary_set(struct bonding *bond,
				   const struct bond_opt_value *newval)
{
+9 −2
Original line number Diff line number Diff line
@@ -67,6 +67,7 @@ enum {
	BOND_OPT_LACP_ACTIVE,
	BOND_OPT_MISSED_MAX,
	BOND_OPT_NS_TARGETS,
	BOND_OPT_PRIO,
	BOND_OPT_LAST
};

@@ -83,7 +84,10 @@ struct bond_opt_value {
	char *string;
	u64 value;
	u32 flags;
	union {
		char extra[BOND_OPT_EXTRA_MAXLEN];
		struct net_device *slave_dev;
	};
};

struct bonding;
@@ -133,13 +137,16 @@ static inline void __bond_opt_init(struct bond_opt_value *optval,
		optval->value = value;
	else if (string)
		optval->string = string;
	else if (extra_len <= BOND_OPT_EXTRA_MAXLEN)

	if (extra && extra_len <= BOND_OPT_EXTRA_MAXLEN)
		memcpy(optval->extra, extra, extra_len);
}
#define bond_opt_initval(optval, value) __bond_opt_init(optval, NULL, value, NULL, 0)
#define bond_opt_initstr(optval, str) __bond_opt_init(optval, str, ULLONG_MAX, NULL, 0)
#define bond_opt_initextra(optval, extra, extra_len) \
	__bond_opt_init(optval, NULL, ULLONG_MAX, extra, extra_len)
#define bond_opt_slave_initval(optval, slave_dev, value) \
	__bond_opt_init(optval, NULL, value, slave_dev, sizeof(struct net_device *))

void bond_option_arp_ip_targets_clear(struct bonding *bond);
#if IS_ENABLED(CONFIG_IPV6)
Loading