Skip to content

Commit 07a4dde

Browse files
vincentbernatdavem330
authored andcommitted
bonding: add an option to specify a delay between peer notifications
Currently, gratuitous ARP/ND packets are sent every `miimon' milliseconds. This commit allows a user to specify a custom delay through a new option, `peer_notif_delay'. Like for `updelay' and `downdelay', this delay should be a multiple of `miimon' to avoid managing an additional work queue. The configuration logic is copied from `updelay' and `downdelay'. However, the default value cannot be set using a module parameter: Netlink or sysfs should be used to configure this feature. When setting `miimon' to 100 and `peer_notif_delay' to 500, we can observe the 500 ms delay is respected: 20:30:19.354693 ARP, Request who-has 203.0.113.10 tell 203.0.113.10, length 28 20:30:19.874892 ARP, Request who-has 203.0.113.10 tell 203.0.113.10, length 28 20:30:20.394919 ARP, Request who-has 203.0.113.10 tell 203.0.113.10, length 28 20:30:20.914963 ARP, Request who-has 203.0.113.10 tell 203.0.113.10, length 28 In bond_mii_monitor(), I have tried to keep the lock logic readable. The change is due to the fact we cannot rely on a notification to lower the value of `bond->send_peer_notif' as `NETDEV_NOTIFY_PEERS' is only triggered once every N times, while we need to decrement the counter each time. iproute2 also needs to be updated to be able to specify this new attribute through `ip link'. Signed-off-by: Vincent Bernat <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 2368a87 commit 07a4dde

File tree

9 files changed

+98
-37
lines changed

9 files changed

+98
-37
lines changed

drivers/net/bonding/bond_main.c

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -796,6 +796,8 @@ static bool bond_should_notify_peers(struct bonding *bond)
796796
slave ? slave->dev->name : "NULL");
797797

798798
if (!slave || !bond->send_peer_notif ||
799+
bond->send_peer_notif %
800+
max(1, bond->params.peer_notif_delay) != 0 ||
799801
!netif_carrier_ok(bond->dev) ||
800802
test_bit(__LINK_STATE_LINKWATCH_PENDING, &slave->dev->state))
801803
return false;
@@ -886,15 +888,18 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active)
886888

887889
if (netif_running(bond->dev)) {
888890
bond->send_peer_notif =
889-
bond->params.num_peer_notif;
891+
bond->params.num_peer_notif *
892+
max(1, bond->params.peer_notif_delay);
890893
should_notify_peers =
891894
bond_should_notify_peers(bond);
892895
}
893896

894897
call_netdevice_notifiers(NETDEV_BONDING_FAILOVER, bond->dev);
895-
if (should_notify_peers)
898+
if (should_notify_peers) {
899+
bond->send_peer_notif--;
896900
call_netdevice_notifiers(NETDEV_NOTIFY_PEERS,
897901
bond->dev);
902+
}
898903
}
899904
}
900905

@@ -2279,6 +2284,7 @@ static void bond_mii_monitor(struct work_struct *work)
22792284
struct bonding *bond = container_of(work, struct bonding,
22802285
mii_work.work);
22812286
bool should_notify_peers = false;
2287+
bool commit;
22822288
unsigned long delay;
22832289
struct slave *slave;
22842290
struct list_head *iter;
@@ -2289,12 +2295,19 @@ static void bond_mii_monitor(struct work_struct *work)
22892295
goto re_arm;
22902296

22912297
rcu_read_lock();
2292-
22932298
should_notify_peers = bond_should_notify_peers(bond);
2294-
2295-
if (bond_miimon_inspect(bond)) {
2299+
commit = !!bond_miimon_inspect(bond);
2300+
if (bond->send_peer_notif) {
2301+
rcu_read_unlock();
2302+
if (rtnl_trylock()) {
2303+
bond->send_peer_notif--;
2304+
rtnl_unlock();
2305+
}
2306+
} else {
22962307
rcu_read_unlock();
2308+
}
22972309

2310+
if (commit) {
22982311
/* Race avoidance with bond_close cancel of workqueue */
22992312
if (!rtnl_trylock()) {
23002313
delay = 1;
@@ -2308,8 +2321,7 @@ static void bond_mii_monitor(struct work_struct *work)
23082321
bond_miimon_commit(bond);
23092322

23102323
rtnl_unlock(); /* might sleep, hold no other locks */
2311-
} else
2312-
rcu_read_unlock();
2324+
}
23132325

23142326
re_arm:
23152327
if (bond->params.miimon)
@@ -3065,10 +3077,6 @@ static int bond_master_netdev_event(unsigned long event,
30653077
case NETDEV_REGISTER:
30663078
bond_create_proc_entry(event_bond);
30673079
break;
3068-
case NETDEV_NOTIFY_PEERS:
3069-
if (event_bond->send_peer_notif)
3070-
event_bond->send_peer_notif--;
3071-
break;
30723080
default:
30733081
break;
30743082
}
@@ -4691,6 +4699,7 @@ static int bond_check_params(struct bond_params *params)
46914699
params->arp_all_targets = arp_all_targets_value;
46924700
params->updelay = updelay;
46934701
params->downdelay = downdelay;
4702+
params->peer_notif_delay = 0;
46944703
params->use_carrier = use_carrier;
46954704
params->lacp_fast = lacp_fast;
46964705
params->primary[0] = 0;

drivers/net/bonding/bond_netlink.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ static const struct nla_policy bond_policy[IFLA_BOND_MAX + 1] = {
108108
[IFLA_BOND_AD_ACTOR_SYSTEM] = { .type = NLA_BINARY,
109109
.len = ETH_ALEN },
110110
[IFLA_BOND_TLB_DYNAMIC_LB] = { .type = NLA_U8 },
111+
[IFLA_BOND_PEER_NOTIF_DELAY] = { .type = NLA_U32 },
111112
};
112113

113114
static const struct nla_policy bond_slave_policy[IFLA_BOND_SLAVE_MAX + 1] = {
@@ -215,6 +216,14 @@ static int bond_changelink(struct net_device *bond_dev, struct nlattr *tb[],
215216
if (err)
216217
return err;
217218
}
219+
if (data[IFLA_BOND_PEER_NOTIF_DELAY]) {
220+
int delay = nla_get_u32(data[IFLA_BOND_PEER_NOTIF_DELAY]);
221+
222+
bond_opt_initval(&newval, delay);
223+
err = __bond_opt_set(bond, BOND_OPT_PEER_NOTIF_DELAY, &newval);
224+
if (err)
225+
return err;
226+
}
218227
if (data[IFLA_BOND_USE_CARRIER]) {
219228
int use_carrier = nla_get_u8(data[IFLA_BOND_USE_CARRIER]);
220229

@@ -494,6 +503,7 @@ static size_t bond_get_size(const struct net_device *bond_dev)
494503
nla_total_size(sizeof(u16)) + /* IFLA_BOND_AD_USER_PORT_KEY */
495504
nla_total_size(ETH_ALEN) + /* IFLA_BOND_AD_ACTOR_SYSTEM */
496505
nla_total_size(sizeof(u8)) + /* IFLA_BOND_TLB_DYNAMIC_LB */
506+
nla_total_size(sizeof(u32)) + /* IFLA_BOND_PEER_NOTIF_DELAY */
497507
0;
498508
}
499509

@@ -536,6 +546,10 @@ static int bond_fill_info(struct sk_buff *skb,
536546
bond->params.downdelay * bond->params.miimon))
537547
goto nla_put_failure;
538548

549+
if (nla_put_u32(skb, IFLA_BOND_PEER_NOTIF_DELAY,
550+
bond->params.downdelay * bond->params.miimon))
551+
goto nla_put_failure;
552+
539553
if (nla_put_u8(skb, IFLA_BOND_USE_CARRIER, bond->params.use_carrier))
540554
goto nla_put_failure;
541555

drivers/net/bonding/bond_options.c

Lines changed: 45 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ static int bond_option_updelay_set(struct bonding *bond,
2424
const struct bond_opt_value *newval);
2525
static int bond_option_downdelay_set(struct bonding *bond,
2626
const struct bond_opt_value *newval);
27+
static int bond_option_peer_notif_delay_set(struct bonding *bond,
28+
const struct bond_opt_value *newval);
2729
static int bond_option_use_carrier_set(struct bonding *bond,
2830
const struct bond_opt_value *newval);
2931
static int bond_option_arp_interval_set(struct bonding *bond,
@@ -424,6 +426,13 @@ static const struct bond_option bond_opts[BOND_OPT_LAST] = {
424426
.desc = "Number of peer notifications to send on failover event",
425427
.values = bond_num_peer_notif_tbl,
426428
.set = bond_option_num_peer_notif_set
429+
},
430+
[BOND_OPT_PEER_NOTIF_DELAY] = {
431+
.id = BOND_OPT_PEER_NOTIF_DELAY,
432+
.name = "peer_notif_delay",
433+
.desc = "Delay between each peer notification on failover event, in milliseconds",
434+
.values = bond_intmax_tbl,
435+
.set = bond_option_peer_notif_delay_set
427436
}
428437
};
429438

@@ -841,6 +850,9 @@ static int bond_option_miimon_set(struct bonding *bond,
841850
if (bond->params.downdelay)
842851
netdev_dbg(bond->dev, "Note: Updating downdelay (to %d) since it is a multiple of the miimon value\n",
843852
bond->params.downdelay * bond->params.miimon);
853+
if (bond->params.peer_notif_delay)
854+
netdev_dbg(bond->dev, "Note: Updating peer_notif_delay (to %d) since it is a multiple of the miimon value\n",
855+
bond->params.peer_notif_delay * bond->params.miimon);
844856
if (newval->value && bond->params.arp_interval) {
845857
netdev_dbg(bond->dev, "MII monitoring cannot be used with ARP monitoring - disabling ARP monitoring...\n");
846858
bond->params.arp_interval = 0;
@@ -864,52 +876,59 @@ static int bond_option_miimon_set(struct bonding *bond,
864876
return 0;
865877
}
866878

867-
/* Set up and down delays. These must be multiples of the
868-
* MII monitoring value, and are stored internally as the multiplier.
869-
* Thus, we must translate to MS for the real world.
879+
/* Set up, down and peer notification delays. These must be multiples
880+
* of the MII monitoring value, and are stored internally as the
881+
* multiplier. Thus, we must translate to MS for the real world.
870882
*/
871-
static int bond_option_updelay_set(struct bonding *bond,
872-
const struct bond_opt_value *newval)
883+
static int _bond_option_delay_set(struct bonding *bond,
884+
const struct bond_opt_value *newval,
885+
const char *name,
886+
int *target)
873887
{
874888
int value = newval->value;
875889

876890
if (!bond->params.miimon) {
877-
netdev_err(bond->dev, "Unable to set up delay as MII monitoring is disabled\n");
891+
netdev_err(bond->dev, "Unable to set %s as MII monitoring is disabled\n",
892+
name);
878893
return -EPERM;
879894
}
880895
if ((value % bond->params.miimon) != 0) {
881-
netdev_warn(bond->dev, "up delay (%d) is not a multiple of miimon (%d), updelay rounded to %d ms\n",
896+
netdev_warn(bond->dev,
897+
"%s (%d) is not a multiple of miimon (%d), value rounded to %d ms\n",
898+
name,
882899
value, bond->params.miimon,
883900
(value / bond->params.miimon) *
884901
bond->params.miimon);
885902
}
886-
bond->params.updelay = value / bond->params.miimon;
887-
netdev_dbg(bond->dev, "Setting up delay to %d\n",
888-
bond->params.updelay * bond->params.miimon);
903+
*target = value / bond->params.miimon;
904+
netdev_dbg(bond->dev, "Setting %s to %d\n",
905+
name,
906+
*target * bond->params.miimon);
889907

890908
return 0;
891909
}
892910

911+
static int bond_option_updelay_set(struct bonding *bond,
912+
const struct bond_opt_value *newval)
913+
{
914+
return _bond_option_delay_set(bond, newval, "up delay",
915+
&bond->params.updelay);
916+
}
917+
893918
static int bond_option_downdelay_set(struct bonding *bond,
894919
const struct bond_opt_value *newval)
895920
{
896-
int value = newval->value;
897-
898-
if (!bond->params.miimon) {
899-
netdev_err(bond->dev, "Unable to set down delay as MII monitoring is disabled\n");
900-
return -EPERM;
901-
}
902-
if ((value % bond->params.miimon) != 0) {
903-
netdev_warn(bond->dev, "down delay (%d) is not a multiple of miimon (%d), delay rounded to %d ms\n",
904-
value, bond->params.miimon,
905-
(value / bond->params.miimon) *
906-
bond->params.miimon);
907-
}
908-
bond->params.downdelay = value / bond->params.miimon;
909-
netdev_dbg(bond->dev, "Setting down delay to %d\n",
910-
bond->params.downdelay * bond->params.miimon);
921+
return _bond_option_delay_set(bond, newval, "down delay",
922+
&bond->params.downdelay);
923+
}
911924

912-
return 0;
925+
static int bond_option_peer_notif_delay_set(struct bonding *bond,
926+
const struct bond_opt_value *newval)
927+
{
928+
int ret = _bond_option_delay_set(bond, newval,
929+
"peer notification delay",
930+
&bond->params.peer_notif_delay);
931+
return ret;
913932
}
914933

915934
static int bond_option_use_carrier_set(struct bonding *bond,

drivers/net/bonding/bond_procfs.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,8 @@ static void bond_info_show_master(struct seq_file *seq)
104104
bond->params.updelay * bond->params.miimon);
105105
seq_printf(seq, "Down Delay (ms): %d\n",
106106
bond->params.downdelay * bond->params.miimon);
107+
seq_printf(seq, "Peer Notification Delay (ms): %d\n",
108+
bond->params.peer_notif_delay * bond->params.miimon);
107109

108110

109111
/* ARP information */

drivers/net/bonding/bond_sysfs.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,18 @@ static ssize_t bonding_show_updelay(struct device *d,
327327
static DEVICE_ATTR(updelay, 0644,
328328
bonding_show_updelay, bonding_sysfs_store_option);
329329

330+
static ssize_t bonding_show_peer_notif_delay(struct device *d,
331+
struct device_attribute *attr,
332+
char *buf)
333+
{
334+
struct bonding *bond = to_bond(d);
335+
336+
return sprintf(buf, "%d\n",
337+
bond->params.peer_notif_delay * bond->params.miimon);
338+
}
339+
static DEVICE_ATTR(peer_notif_delay, 0644,
340+
bonding_show_peer_notif_delay, bonding_sysfs_store_option);
341+
330342
/* Show the LACP interval. */
331343
static ssize_t bonding_show_lacp(struct device *d,
332344
struct device_attribute *attr,
@@ -718,6 +730,7 @@ static struct attribute *per_bond_attrs[] = {
718730
&dev_attr_arp_ip_target.attr,
719731
&dev_attr_downdelay.attr,
720732
&dev_attr_updelay.attr,
733+
&dev_attr_peer_notif_delay.attr,
721734
&dev_attr_lacp_rate.attr,
722735
&dev_attr_ad_select.attr,
723736
&dev_attr_xmit_hash_policy.attr,

include/net/bond_options.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ enum {
6363
BOND_OPT_AD_ACTOR_SYSTEM,
6464
BOND_OPT_AD_USER_PORT_KEY,
6565
BOND_OPT_NUM_PEER_NOTIF_ALIAS,
66+
BOND_OPT_PEER_NOTIF_DELAY,
6667
BOND_OPT_LAST
6768
};
6869

include/net/bonding.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ struct bond_params {
123123
int fail_over_mac;
124124
int updelay;
125125
int downdelay;
126+
int peer_notif_delay;
126127
int lacp_fast;
127128
unsigned int min_links;
128129
int ad_select;

include/uapi/linux/if_link.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -636,6 +636,7 @@ enum {
636636
IFLA_BOND_AD_USER_PORT_KEY,
637637
IFLA_BOND_AD_ACTOR_SYSTEM,
638638
IFLA_BOND_TLB_DYNAMIC_LB,
639+
IFLA_BOND_PEER_NOTIF_DELAY,
639640
__IFLA_BOND_MAX,
640641
};
641642

tools/include/uapi/linux/if_link.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -636,6 +636,7 @@ enum {
636636
IFLA_BOND_AD_USER_PORT_KEY,
637637
IFLA_BOND_AD_ACTOR_SYSTEM,
638638
IFLA_BOND_TLB_DYNAMIC_LB,
639+
IFLA_BOND_PEER_NOTIF_DELAY,
639640
__IFLA_BOND_MAX,
640641
};
641642

0 commit comments

Comments
 (0)