Skip to content

Commit 0a30299

Browse files
committed
Merge: Bonding: add option per-port priority
MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-9/-/merge_requests/2418 Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2092194 Signed-off-by: Hangbin Liu <haliu@redhat.com> Approved-by: Xin Long <lxin@redhat.com> Approved-by: Andrea Claudi <aclaudi@redhat.com> Signed-off-by: Jan Stancek <jstancek@redhat.com>
2 parents c930ac4 + 6bee0e5 commit 0a30299

File tree

10 files changed

+362
-12
lines changed

10 files changed

+362
-12
lines changed

Documentation/networking/bonding.rst

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -781,6 +781,17 @@ peer_notif_delay
781781
value is 0 which means to match the value of the link monitor
782782
interval.
783783

784+
prio
785+
Slave priority. A higher number means higher priority.
786+
The primary slave has the highest priority. This option also
787+
follows the primary_reselect rules.
788+
789+
This option could only be configured via netlink, and is only valid
790+
for active-backup(1), balance-tlb (5) and balance-alb (6) mode.
791+
The valid value range is a signed 32 bit integer.
792+
793+
The default value is 0.
794+
784795
primary
785796

786797
A string (eth0, eth2, etc) specifying which slave is the

drivers/net/bonding/bond_main.c

Lines changed: 44 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1025,12 +1025,38 @@ static void bond_do_fail_over_mac(struct bonding *bond,
10251025

10261026
}
10271027

1028+
/**
1029+
* bond_choose_primary_or_current - select the primary or high priority slave
1030+
* @bond: our bonding struct
1031+
*
1032+
* - Check if there is a primary link. If the primary link was set and is up,
1033+
* go on and do link reselection.
1034+
*
1035+
* - If primary link is not set or down, find the highest priority link.
1036+
* If the highest priority link is not current slave, set it as primary
1037+
* link and do link reselection.
1038+
*/
10281039
static struct slave *bond_choose_primary_or_current(struct bonding *bond)
10291040
{
10301041
struct slave *prim = rtnl_dereference(bond->primary_slave);
10311042
struct slave *curr = rtnl_dereference(bond->curr_active_slave);
1043+
struct slave *slave, *hprio = NULL;
1044+
struct list_head *iter;
10321045

10331046
if (!prim || prim->link != BOND_LINK_UP) {
1047+
bond_for_each_slave(bond, slave, iter) {
1048+
if (slave->link == BOND_LINK_UP) {
1049+
hprio = hprio ?: slave;
1050+
if (slave->prio > hprio->prio)
1051+
hprio = slave;
1052+
}
1053+
}
1054+
1055+
if (hprio && hprio != curr) {
1056+
prim = hprio;
1057+
goto link_reselect;
1058+
}
1059+
10341060
if (!curr || curr->link != BOND_LINK_UP)
10351061
return NULL;
10361062
return curr;
@@ -1041,6 +1067,7 @@ static struct slave *bond_choose_primary_or_current(struct bonding *bond)
10411067
return prim;
10421068
}
10431069

1070+
link_reselect:
10441071
if (!curr || curr->link != BOND_LINK_UP)
10451072
return prim;
10461073

@@ -2626,8 +2653,11 @@ static void bond_miimon_link_change(struct bonding *bond,
26262653

26272654
static void bond_miimon_commit(struct bonding *bond)
26282655
{
2656+
struct slave *slave, *primary, *active;
2657+
bool do_failover = false;
26292658
struct list_head *iter;
2630-
struct slave *slave, *primary;
2659+
2660+
ASSERT_RTNL();
26312661

26322662
bond_for_each_slave(bond, slave, iter) {
26332663
switch (slave->link_new_state) {
@@ -2671,8 +2701,9 @@ static void bond_miimon_commit(struct bonding *bond)
26712701

26722702
bond_miimon_link_change(bond, slave, BOND_LINK_UP);
26732703

2674-
if (!bond->curr_active_slave || slave == primary)
2675-
goto do_failover;
2704+
active = rtnl_dereference(bond->curr_active_slave);
2705+
if (!active || slave == primary || slave->prio > active->prio)
2706+
do_failover = true;
26762707

26772708
continue;
26782709

@@ -2693,7 +2724,7 @@ static void bond_miimon_commit(struct bonding *bond)
26932724
bond_miimon_link_change(bond, slave, BOND_LINK_DOWN);
26942725

26952726
if (slave == rcu_access_pointer(bond->curr_active_slave))
2696-
goto do_failover;
2727+
do_failover = true;
26972728

26982729
continue;
26992730

@@ -2704,8 +2735,9 @@ static void bond_miimon_commit(struct bonding *bond)
27042735

27052736
continue;
27062737
}
2738+
}
27072739

2708-
do_failover:
2740+
if (do_failover) {
27092741
block_netpoll_tx();
27102742
bond_select_active_slave(bond);
27112743
unblock_netpoll_tx();
@@ -3503,6 +3535,7 @@ static int bond_ab_arp_inspect(struct bonding *bond)
35033535
*/
35043536
static void bond_ab_arp_commit(struct bonding *bond)
35053537
{
3538+
bool do_failover = false;
35063539
struct list_head *iter;
35073540
unsigned long last_tx;
35083541
struct slave *slave;
@@ -3532,8 +3565,9 @@ static void bond_ab_arp_commit(struct bonding *bond)
35323565
slave_info(bond->dev, slave->dev, "link status definitely up\n");
35333566

35343567
if (!rtnl_dereference(bond->curr_active_slave) ||
3535-
slave == rtnl_dereference(bond->primary_slave))
3536-
goto do_failover;
3568+
slave == rtnl_dereference(bond->primary_slave) ||
3569+
slave->prio > rtnl_dereference(bond->curr_active_slave)->prio)
3570+
do_failover = true;
35373571

35383572
}
35393573

@@ -3552,7 +3586,7 @@ static void bond_ab_arp_commit(struct bonding *bond)
35523586

35533587
if (slave == rtnl_dereference(bond->curr_active_slave)) {
35543588
RCU_INIT_POINTER(bond->current_arp_slave, NULL);
3555-
goto do_failover;
3589+
do_failover = true;
35563590
}
35573591

35583592
continue;
@@ -3576,8 +3610,9 @@ static void bond_ab_arp_commit(struct bonding *bond)
35763610
slave->link_new_state);
35773611
continue;
35783612
}
3613+
}
35793614

3580-
do_failover:
3615+
if (do_failover) {
35813616
block_netpoll_tx();
35823617
bond_select_active_slave(bond);
35833618
unblock_netpoll_tx();

drivers/net/bonding/bond_netlink.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ static size_t bond_get_slave_size(const struct net_device *bond_dev,
2727
nla_total_size(sizeof(u16)) + /* IFLA_BOND_SLAVE_AD_AGGREGATOR_ID */
2828
nla_total_size(sizeof(u8)) + /* IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE */
2929
nla_total_size(sizeof(u16)) + /* IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE */
30+
nla_total_size(sizeof(s32)) + /* IFLA_BOND_SLAVE_PRIO */
3031
0;
3132
}
3233

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

57+
if (nla_put_s32(skb, IFLA_BOND_SLAVE_PRIO, slave->prio))
58+
goto nla_put_failure;
59+
5660
if (BOND_MODE(slave->bond) == BOND_MODE_8023AD) {
5761
const struct aggregator *agg;
5862
const struct port *ad_port;
@@ -117,6 +121,7 @@ static const struct nla_policy bond_policy[IFLA_BOND_MAX + 1] = {
117121

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

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

165+
if (data[IFLA_BOND_SLAVE_PRIO]) {
166+
int prio = nla_get_s32(data[IFLA_BOND_SLAVE_PRIO]);
167+
168+
bond_opt_slave_initval(&newval, &slave_dev, prio);
169+
err = __bond_opt_set(bond, BOND_OPT_PRIO, &newval,
170+
data[IFLA_BOND_SLAVE_PRIO], extack);
171+
if (err)
172+
return err;
173+
}
174+
160175
return 0;
161176
}
162177

drivers/net/bonding/bond_options.c

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ static int bond_option_arp_validate_set(struct bonding *bond,
4040
const struct bond_opt_value *newval);
4141
static int bond_option_arp_all_targets_set(struct bonding *bond,
4242
const struct bond_opt_value *newval);
43+
static int bond_option_prio_set(struct bonding *bond,
44+
const struct bond_opt_value *newval);
4345
static int bond_option_primary_set(struct bonding *bond,
4446
const struct bond_opt_value *newval);
4547
static int bond_option_primary_reselect_set(struct bonding *bond,
@@ -365,6 +367,16 @@ static const struct bond_option bond_opts[BOND_OPT_LAST] = {
365367
.values = bond_intmax_tbl,
366368
.set = bond_option_miimon_set
367369
},
370+
[BOND_OPT_PRIO] = {
371+
.id = BOND_OPT_PRIO,
372+
.name = "prio",
373+
.desc = "Link priority for failover re-selection",
374+
.flags = BOND_OPTFLAG_RAWVAL,
375+
.unsuppmodes = BOND_MODE_ALL_EX(BIT(BOND_MODE_ACTIVEBACKUP) |
376+
BIT(BOND_MODE_TLB) |
377+
BIT(BOND_MODE_ALB)),
378+
.set = bond_option_prio_set
379+
},
368380
[BOND_OPT_PRIMARY] = {
369381
.id = BOND_OPT_PRIMARY,
370382
.name = "primary",
@@ -1306,6 +1318,27 @@ static int bond_option_missed_max_set(struct bonding *bond,
13061318
return 0;
13071319
}
13081320

1321+
static int bond_option_prio_set(struct bonding *bond,
1322+
const struct bond_opt_value *newval)
1323+
{
1324+
struct slave *slave;
1325+
1326+
slave = bond_slave_get_rtnl(newval->slave_dev);
1327+
if (!slave) {
1328+
netdev_dbg(newval->slave_dev, "%s called on NULL slave\n", __func__);
1329+
return -ENODEV;
1330+
}
1331+
slave->prio = newval->value;
1332+
1333+
if (rtnl_dereference(bond->primary_slave))
1334+
slave_warn(bond->dev, slave->dev,
1335+
"prio updated, but will not affect failover re-selection as primary slave have been set\n");
1336+
else
1337+
bond_select_active_slave(bond);
1338+
1339+
return 0;
1340+
}
1341+
13091342
static int bond_option_primary_set(struct bonding *bond,
13101343
const struct bond_opt_value *newval)
13111344
{

include/net/bond_options.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ enum {
6767
BOND_OPT_LACP_ACTIVE,
6868
BOND_OPT_MISSED_MAX,
6969
BOND_OPT_NS_TARGETS,
70+
BOND_OPT_PRIO,
7071
BOND_OPT_LAST
7172
};
7273

@@ -83,7 +84,10 @@ struct bond_opt_value {
8384
char *string;
8485
u64 value;
8586
u32 flags;
86-
char extra[BOND_OPT_EXTRA_MAXLEN];
87+
union {
88+
char extra[BOND_OPT_EXTRA_MAXLEN];
89+
struct net_device *slave_dev;
90+
};
8791
};
8892

8993
struct bonding;
@@ -133,13 +137,16 @@ static inline void __bond_opt_init(struct bond_opt_value *optval,
133137
optval->value = value;
134138
else if (string)
135139
optval->string = string;
136-
else if (extra_len <= BOND_OPT_EXTRA_MAXLEN)
140+
141+
if (extra && extra_len <= BOND_OPT_EXTRA_MAXLEN)
137142
memcpy(optval->extra, extra, extra_len);
138143
}
139144
#define bond_opt_initval(optval, value) __bond_opt_init(optval, NULL, value, NULL, 0)
140145
#define bond_opt_initstr(optval, str) __bond_opt_init(optval, str, ULLONG_MAX, NULL, 0)
141146
#define bond_opt_initextra(optval, extra, extra_len) \
142147
__bond_opt_init(optval, NULL, ULLONG_MAX, extra, extra_len)
148+
#define bond_opt_slave_initval(optval, slave_dev, value) \
149+
__bond_opt_init(optval, NULL, value, slave_dev, sizeof(struct net_device *))
143150

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

include/net/bonding.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ struct slave {
179179
u32 speed;
180180
u16 queue_id;
181181
u8 perm_hwaddr[MAX_ADDR_LEN];
182+
int prio;
182183
struct ad_slave_info *ad_info;
183184
struct tlb_slave_info tlb_info;
184185
#ifdef CONFIG_NET_POLL_CONTROLLER

include/uapi/linux/if_link.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -915,6 +915,7 @@ enum {
915915
IFLA_BOND_SLAVE_AD_AGGREGATOR_ID,
916916
IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE,
917917
IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE,
918+
IFLA_BOND_SLAVE_PRIO,
918919
__IFLA_BOND_SLAVE_MAX,
919920
};
920921

tools/include/uapi/linux/if_link.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -891,6 +891,7 @@ enum {
891891
IFLA_BOND_SLAVE_AD_AGGREGATOR_ID,
892892
IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE,
893893
IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE,
894+
IFLA_BOND_SLAVE_PRIO,
894895
__IFLA_BOND_SLAVE_MAX,
895896
};
896897

tools/testing/selftests/drivers/net/bonding/Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ TEST_PROGS := \
77
bond-lladdr-target.sh \
88
dev_addr_lists.sh \
99
mode-1-recovery-updelay.sh \
10-
mode-2-recovery-updelay.sh
10+
mode-2-recovery-updelay.sh \
11+
option_prio.sh
1112

1213
TEST_FILES := \
1314
lag_lib.sh \

0 commit comments

Comments
 (0)