Commit b414ac9a authored by David S. Miller's avatar David S. Miller

Merge branch 'bonding_option_api'

Nikolay Aleksandrov says:

====================
bonding: introduce new option API

This patchset's goal is to introduce a new option API which should be used
to properly describe the bonding options with their mode dependcies and
requirements. With this patchset applied we get centralized option
manipulation, automatic RTNL acquire per option setting, automatic option
range checking, mode dependcy checking and other various flags which are
described in detail in patch 01's commit message and comments.
Also the parameter passing is changed to use a specialized structure which
is initialized to a value depending on the needs.
The main exported functions are:
 __bond_opt_set() - set an option (RTNL should be acquired prior)
 bond_opt_init(val|str) - init a bond_opt_value struct for value or string
                          parameter passing
 bond_opt_tryset_rtnl() - function which tries to acquire rtnl, mainly used
                          for sysfs
 bond_opt_parse - used to parse or check for valid values
 bond_opt_get - retrieve a pointer to bond_option struct for some option
 bond_opt_get_val - retrieve a pointer to a bond_opt_value struct for
                    some value

The same functions are used to set an option via sysfs and netlink, just
the parameter that's passed is usually initialized in a different way.
The converted options have multiple style fixes, there're some longer
lines but they looked either ugly or were strings/pr_warnings, if you
think some line would be better broken just let me know :-) there're
also a few sscanf false-positive warnings.
I decided to keep the "unsuppmodes" way of mode dep checking since it's
straight forward, if we make a more general way for checking dependencies
it'll be easy to change it.

Future plans for this work include:
 - Automatic sysfs generation from the bond_opts[].
 - Use of the API in bond_check_params() and thus cleaning it up (this has
   actually started, I'll take care of the rest in a separate patch)
 - Clean up all option-unrelated files of option definitions and functions

I've tried to leave as much documentation as possible, if there's anything
unclear please let me know. One more thing, I haven't moved all
option-related functions from bonding.h to the new bond_options.h, this
will be done in a separate patch, it's in my todo list.

This patchset has been tested by setting each converted option via sysfs
and netlink to a couple of wrong values, a couple of correct values and
some random values, also for the opts that have flags they have been
tested as well.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 374d1125 0e2e5b66
This diff is collapsed.
......@@ -98,6 +98,7 @@ static int bond_changelink(struct net_device *bond_dev,
struct nlattr *tb[], struct nlattr *data[])
{
struct bonding *bond = netdev_priv(bond_dev);
struct bond_opt_value newval;
int miimon = 0;
int err;
......@@ -107,51 +108,57 @@ static int bond_changelink(struct net_device *bond_dev,
if (data[IFLA_BOND_MODE]) {
int mode = nla_get_u8(data[IFLA_BOND_MODE]);
err = bond_option_mode_set(bond, mode);
bond_opt_initval(&newval, mode);
err = __bond_opt_set(bond, BOND_OPT_MODE, &newval);
if (err)
return err;
}
if (data[IFLA_BOND_ACTIVE_SLAVE]) {
int ifindex = nla_get_u32(data[IFLA_BOND_ACTIVE_SLAVE]);
struct net_device *slave_dev;
char *active_slave = "";
if (ifindex == 0) {
slave_dev = NULL;
} else {
if (ifindex != 0) {
slave_dev = __dev_get_by_index(dev_net(bond_dev),
ifindex);
if (!slave_dev)
return -ENODEV;
active_slave = slave_dev->name;
}
err = bond_option_active_slave_set(bond, slave_dev);
bond_opt_initstr(&newval, active_slave);
err = __bond_opt_set(bond, BOND_OPT_ACTIVE_SLAVE, &newval);
if (err)
return err;
}
if (data[IFLA_BOND_MIIMON]) {
miimon = nla_get_u32(data[IFLA_BOND_MIIMON]);
err = bond_option_miimon_set(bond, miimon);
bond_opt_initval(&newval, miimon);
err = __bond_opt_set(bond, BOND_OPT_MIIMON, &newval);
if (err)
return err;
}
if (data[IFLA_BOND_UPDELAY]) {
int updelay = nla_get_u32(data[IFLA_BOND_UPDELAY]);
err = bond_option_updelay_set(bond, updelay);
bond_opt_initval(&newval, updelay);
err = __bond_opt_set(bond, BOND_OPT_UPDELAY, &newval);
if (err)
return err;
}
if (data[IFLA_BOND_DOWNDELAY]) {
int downdelay = nla_get_u32(data[IFLA_BOND_DOWNDELAY]);
err = bond_option_downdelay_set(bond, downdelay);
bond_opt_initval(&newval, downdelay);
err = __bond_opt_set(bond, BOND_OPT_DOWNDELAY, &newval);
if (err)
return err;
}
if (data[IFLA_BOND_USE_CARRIER]) {
int use_carrier = nla_get_u8(data[IFLA_BOND_USE_CARRIER]);
err = bond_option_use_carrier_set(bond, use_carrier);
bond_opt_initval(&newval, use_carrier);
err = __bond_opt_set(bond, BOND_OPT_USE_CARRIER, &newval);
if (err)
return err;
}
......@@ -164,21 +171,29 @@ static int bond_changelink(struct net_device *bond_dev,
return -EINVAL;
}
err = bond_option_arp_interval_set(bond, arp_interval);
bond_opt_initval(&newval, arp_interval);
err = __bond_opt_set(bond, BOND_OPT_ARP_INTERVAL, &newval);
if (err)
return err;
}
if (data[IFLA_BOND_ARP_IP_TARGET]) {
__be32 targets[BOND_MAX_ARP_TARGETS] = { 0, };
struct nlattr *attr;
int i = 0, rem;
bond_option_arp_ip_targets_clear(bond);
nla_for_each_nested(attr, data[IFLA_BOND_ARP_IP_TARGET], rem) {
__be32 target = nla_get_be32(attr);
targets[i++] = target;
}
err = bond_option_arp_ip_targets_set(bond, targets, i);
bond_opt_initval(&newval, target);
err = __bond_opt_set(bond, BOND_OPT_ARP_TARGETS,
&newval);
if (err)
break;
i++;
}
if (i == 0 && bond->params.arp_interval)
pr_warn("%s: removing last arp target with arp_interval on\n",
bond->dev->name);
if (err)
return err;
}
......@@ -191,7 +206,8 @@ static int bond_changelink(struct net_device *bond_dev,
return -EINVAL;
}
err = bond_option_arp_validate_set(bond, arp_validate);
bond_opt_initval(&newval, arp_validate);
err = __bond_opt_set(bond, BOND_OPT_ARP_VALIDATE, &newval);
if (err)
return err;
}
......@@ -199,7 +215,8 @@ static int bond_changelink(struct net_device *bond_dev,
int arp_all_targets =
nla_get_u32(data[IFLA_BOND_ARP_ALL_TARGETS]);
err = bond_option_arp_all_targets_set(bond, arp_all_targets);
bond_opt_initval(&newval, arp_all_targets);
err = __bond_opt_set(bond, BOND_OPT_ARP_ALL_TARGETS, &newval);
if (err)
return err;
}
......@@ -212,7 +229,8 @@ static int bond_changelink(struct net_device *bond_dev,
if (dev)
primary = dev->name;
err = bond_option_primary_set(bond, primary);
bond_opt_initstr(&newval, primary);
err = __bond_opt_set(bond, BOND_OPT_PRIMARY, &newval);
if (err)
return err;
}
......@@ -220,7 +238,8 @@ static int bond_changelink(struct net_device *bond_dev,
int primary_reselect =
nla_get_u8(data[IFLA_BOND_PRIMARY_RESELECT]);
err = bond_option_primary_reselect_set(bond, primary_reselect);
bond_opt_initval(&newval, primary_reselect);
err = __bond_opt_set(bond, BOND_OPT_PRIMARY_RESELECT, &newval);
if (err)
return err;
}
......@@ -228,7 +247,8 @@ static int bond_changelink(struct net_device *bond_dev,
int fail_over_mac =
nla_get_u8(data[IFLA_BOND_FAIL_OVER_MAC]);
err = bond_option_fail_over_mac_set(bond, fail_over_mac);
bond_opt_initval(&newval, fail_over_mac);
err = __bond_opt_set(bond, BOND_OPT_FAIL_OVER_MAC, &newval);
if (err)
return err;
}
......@@ -236,7 +256,8 @@ static int bond_changelink(struct net_device *bond_dev,
int xmit_hash_policy =
nla_get_u8(data[IFLA_BOND_XMIT_HASH_POLICY]);
err = bond_option_xmit_hash_policy_set(bond, xmit_hash_policy);
bond_opt_initval(&newval, xmit_hash_policy);
err = __bond_opt_set(bond, BOND_OPT_XMIT_HASH, &newval);
if (err)
return err;
}
......@@ -244,7 +265,8 @@ static int bond_changelink(struct net_device *bond_dev,
int resend_igmp =
nla_get_u32(data[IFLA_BOND_RESEND_IGMP]);
err = bond_option_resend_igmp_set(bond, resend_igmp);
bond_opt_initval(&newval, resend_igmp);
err = __bond_opt_set(bond, BOND_OPT_RESEND_IGMP, &newval);
if (err)
return err;
}
......@@ -252,7 +274,8 @@ static int bond_changelink(struct net_device *bond_dev,
int num_peer_notif =
nla_get_u8(data[IFLA_BOND_NUM_PEER_NOTIF]);
err = bond_option_num_peer_notif_set(bond, num_peer_notif);
bond_opt_initval(&newval, num_peer_notif);
err = __bond_opt_set(bond, BOND_OPT_NUM_PEER_NOTIF, &newval);
if (err)
return err;
}
......@@ -260,8 +283,8 @@ static int bond_changelink(struct net_device *bond_dev,
int all_slaves_active =
nla_get_u8(data[IFLA_BOND_ALL_SLAVES_ACTIVE]);
err = bond_option_all_slaves_active_set(bond,
all_slaves_active);
bond_opt_initval(&newval, all_slaves_active);
err = __bond_opt_set(bond, BOND_OPT_ALL_SLAVES_ACTIVE, &newval);
if (err)
return err;
}
......@@ -269,7 +292,8 @@ static int bond_changelink(struct net_device *bond_dev,
int min_links =
nla_get_u32(data[IFLA_BOND_MIN_LINKS]);
err = bond_option_min_links_set(bond, min_links);
bond_opt_initval(&newval, min_links);
err = __bond_opt_set(bond, BOND_OPT_MINLINKS, &newval);
if (err)
return err;
}
......@@ -277,7 +301,8 @@ static int bond_changelink(struct net_device *bond_dev,
int lp_interval =
nla_get_u32(data[IFLA_BOND_LP_INTERVAL]);
err = bond_option_lp_interval_set(bond, lp_interval);
bond_opt_initval(&newval, lp_interval);
err = __bond_opt_set(bond, BOND_OPT_LP_INTERVAL, &newval);
if (err)
return err;
}
......@@ -285,8 +310,8 @@ static int bond_changelink(struct net_device *bond_dev,
int packets_per_slave =
nla_get_u32(data[IFLA_BOND_PACKETS_PER_SLAVE]);
err = bond_option_packets_per_slave_set(bond,
packets_per_slave);
bond_opt_initval(&newval, packets_per_slave);
err = __bond_opt_set(bond, BOND_OPT_PACKETS_PER_SLAVE, &newval);
if (err)
return err;
}
......@@ -294,7 +319,8 @@ static int bond_changelink(struct net_device *bond_dev,
int lacp_rate =
nla_get_u8(data[IFLA_BOND_AD_LACP_RATE]);
err = bond_option_lacp_rate_set(bond, lacp_rate);
bond_opt_initval(&newval, lacp_rate);
err = __bond_opt_set(bond, BOND_OPT_LACP_RATE, &newval);
if (err)
return err;
}
......@@ -302,7 +328,8 @@ static int bond_changelink(struct net_device *bond_dev,
int ad_select =
nla_get_u8(data[IFLA_BOND_AD_SELECT]);
err = bond_option_ad_select_set(bond, ad_select);
bond_opt_initval(&newval, ad_select);
err = __bond_opt_set(bond, BOND_OPT_AD_SELECT, &newval);
if (err)
return err;
}
......
This diff is collapsed.
/*
* drivers/net/bond/bond_options.h - bonding options
* Copyright (c) 2013 Nikolay Aleksandrov <nikolay@redhat.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#ifndef _BOND_OPTIONS_H
#define _BOND_OPTIONS_H
#define BOND_OPT_MAX_NAMELEN 32
#define BOND_OPT_VALID(opt) ((opt) < BOND_OPT_LAST)
#define BOND_MODE_ALL_EX(x) (~(x))
/* Option flags:
* BOND_OPTFLAG_NOSLAVES - check if the bond device is empty before setting
* BOND_OPTFLAG_IFDOWN - check if the bond device is down before setting
* BOND_OPTFLAG_RAWVAL - the option parses the value itself
*/
enum {
BOND_OPTFLAG_NOSLAVES = BIT(0),
BOND_OPTFLAG_IFDOWN = BIT(1),
BOND_OPTFLAG_RAWVAL = BIT(2)
};
/* Value type flags:
* BOND_VALFLAG_DEFAULT - mark the value as default
* BOND_VALFLAG_(MIN|MAX) - mark the value as min/max
*/
enum {
BOND_VALFLAG_DEFAULT = BIT(0),
BOND_VALFLAG_MIN = BIT(1),
BOND_VALFLAG_MAX = BIT(2)
};
/* Option IDs, their bit positions correspond to their IDs */
enum {
BOND_OPT_MODE,
BOND_OPT_PACKETS_PER_SLAVE,
BOND_OPT_XMIT_HASH,
BOND_OPT_ARP_VALIDATE,
BOND_OPT_ARP_ALL_TARGETS,
BOND_OPT_FAIL_OVER_MAC,
BOND_OPT_ARP_INTERVAL,
BOND_OPT_ARP_TARGETS,
BOND_OPT_DOWNDELAY,
BOND_OPT_UPDELAY,
BOND_OPT_LACP_RATE,
BOND_OPT_MINLINKS,
BOND_OPT_AD_SELECT,
BOND_OPT_NUM_PEER_NOTIF,
BOND_OPT_MIIMON,
BOND_OPT_PRIMARY,
BOND_OPT_PRIMARY_RESELECT,
BOND_OPT_USE_CARRIER,
BOND_OPT_ACTIVE_SLAVE,
BOND_OPT_QUEUE_ID,
BOND_OPT_ALL_SLAVES_ACTIVE,
BOND_OPT_RESEND_IGMP,
BOND_OPT_LP_INTERVAL,
BOND_OPT_SLAVES,
BOND_OPT_LAST
};
/* This structure is used for storing option values and for passing option
* values when changing an option. The logic when used as an arg is as follows:
* - if string != NULL -> parse it, if the opt is RAW type then return it, else
* return the parse result
* - if string == NULL -> parse value
*/
struct bond_opt_value {
char *string;
u64 value;
u32 flags;
};
struct bonding;
struct bond_option {
int id;
char *name;
char *desc;
u32 flags;
/* unsuppmodes is used to denote modes in which the option isn't
* supported.
*/
unsigned long unsuppmodes;
/* supported values which this option can have, can be a subset of
* BOND_OPTVAL_RANGE's value range
*/
struct bond_opt_value *values;
int (*set)(struct bonding *bond, struct bond_opt_value *val);
};
int __bond_opt_set(struct bonding *bond, unsigned int option,
struct bond_opt_value *val);
int bond_opt_tryset_rtnl(struct bonding *bond, unsigned int option, char *buf);
struct bond_opt_value *bond_opt_parse(const struct bond_option *opt,
struct bond_opt_value *val);
struct bond_option *bond_opt_get(unsigned int option);
struct bond_opt_value *bond_opt_get_val(unsigned int option, u64 val);
/* This helper is used to initialize a bond_opt_value structure for parameter
* passing. There should be either a valid string or value, but not both.
* When value is ULLONG_MAX then string will be used.
*/
static inline void __bond_opt_init(struct bond_opt_value *optval,
char *string, u64 value)
{
memset(optval, 0, sizeof(*optval));
optval->value = ULLONG_MAX;
if (value == ULLONG_MAX)
optval->string = string;
else
optval->value = value;
}
#define bond_opt_initval(optval, value) __bond_opt_init(optval, NULL, value)
#define bond_opt_initstr(optval, str) __bond_opt_init(optval, str, ULLONG_MAX)
int bond_option_mode_set(struct bonding *bond, struct bond_opt_value *newval);
int bond_option_pps_set(struct bonding *bond, struct bond_opt_value *newval);
int bond_option_xmit_hash_policy_set(struct bonding *bond,
struct bond_opt_value *newval);
int bond_option_arp_validate_set(struct bonding *bond,
struct bond_opt_value *newval);
int bond_option_arp_all_targets_set(struct bonding *bond,
struct bond_opt_value *newval);
int bond_option_fail_over_mac_set(struct bonding *bond,
struct bond_opt_value *newval);
int bond_option_arp_interval_set(struct bonding *bond,
struct bond_opt_value *newval);
int bond_option_arp_ip_targets_set(struct bonding *bond,
struct bond_opt_value *newval);
void bond_option_arp_ip_targets_clear(struct bonding *bond);
int bond_option_downdelay_set(struct bonding *bond,
struct bond_opt_value *newval);
int bond_option_updelay_set(struct bonding *bond,
struct bond_opt_value *newval);
int bond_option_lacp_rate_set(struct bonding *bond,
struct bond_opt_value *newval);
int bond_option_min_links_set(struct bonding *bond,
struct bond_opt_value *newval);
int bond_option_ad_select_set(struct bonding *bond,
struct bond_opt_value *newval);
int bond_option_num_peer_notif_set(struct bonding *bond,
struct bond_opt_value *newval);
int bond_option_miimon_set(struct bonding *bond, struct bond_opt_value *newval);
int bond_option_primary_set(struct bonding *bond,
struct bond_opt_value *newval);
int bond_option_primary_reselect_set(struct bonding *bond,
struct bond_opt_value *newval);
int bond_option_use_carrier_set(struct bonding *bond,
struct bond_opt_value *newval);
int bond_option_active_slave_set(struct bonding *bond,
struct bond_opt_value *newval);
int bond_option_queue_id_set(struct bonding *bond,
struct bond_opt_value *newval);
int bond_option_all_slaves_active_set(struct bonding *bond,
struct bond_opt_value *newval);
int bond_option_resend_igmp_set(struct bonding *bond,
struct bond_opt_value *newval);
int bond_option_lp_interval_set(struct bonding *bond,
struct bond_opt_value *newval);
int bond_option_slaves_set(struct bonding *bond, struct bond_opt_value *newval);
#endif /* _BOND_OPTIONS_H */
......@@ -65,6 +65,7 @@ static void bond_info_seq_stop(struct seq_file *seq, void *v)
static void bond_info_show_master(struct seq_file *seq)
{
struct bonding *bond = seq->private;
struct bond_opt_value *optval;
struct slave *curr;
int i;
......@@ -76,26 +77,32 @@ static void bond_info_show_master(struct seq_file *seq)
bond_mode_name(bond->params.mode));
if (bond->params.mode == BOND_MODE_ACTIVEBACKUP &&
bond->params.fail_over_mac)
seq_printf(seq, " (fail_over_mac %s)",
fail_over_mac_tbl[bond->params.fail_over_mac].modename);
bond->params.fail_over_mac) {
optval = bond_opt_get_val(BOND_OPT_FAIL_OVER_MAC,
bond->params.fail_over_mac);
seq_printf(seq, " (fail_over_mac %s)", optval->string);
}
seq_printf(seq, "\n");
if (bond->params.mode == BOND_MODE_XOR ||
bond->params.mode == BOND_MODE_8023AD) {
optval = bond_opt_get_val(BOND_OPT_XMIT_HASH,
bond->params.xmit_policy);
seq_printf(seq, "Transmit Hash Policy: %s (%d)\n",
xmit_hashtype_tbl[bond->params.xmit_policy].modename,
bond->params.xmit_policy);
optval->string, bond->params.xmit_policy);
}
if (USES_PRIMARY(bond->params.mode)) {
seq_printf(seq, "Primary Slave: %s",
(bond->primary_slave) ?
bond->primary_slave->dev->name : "None");
if (bond->primary_slave)
if (bond->primary_slave) {
optval = bond_opt_get_val(BOND_OPT_PRIMARY_RESELECT,
bond->params.primary_reselect);
seq_printf(seq, " (primary_reselect %s)",
pri_reselect_tbl[bond->params.primary_reselect].modename);
optval->string);
}
seq_printf(seq, "\nCurrently Active Slave: %s\n",
(curr) ? curr->dev->name : "None");
......@@ -136,8 +143,10 @@ static void bond_info_show_master(struct seq_file *seq)
seq_printf(seq, "LACP rate: %s\n",
(bond->params.lacp_fast) ? "fast" : "slow");
seq_printf(seq, "Min links: %d\n", bond->params.min_links);
optval = bond_opt_get_val(BOND_OPT_AD_SELECT,
bond->params.ad_select);
seq_printf(seq, "Aggregator selection policy (ad_select): %s\n",
ad_select_tbl[bond->params.ad_select].modename);
optval->string);
if (__bond_3ad_get_active_agg_info(bond, &ad_info)) {
seq_printf(seq, "bond %s has no active aggregator\n",
......
This diff is collapsed.
......@@ -27,6 +27,7 @@
#include "bond_3ad.h"
#include "bond_alb.h"
#include "bond_options.h"
#define DRV_VERSION "3.7.1"
#define DRV_RELDATE "April 27, 2011"
......@@ -451,35 +452,8 @@ void bond_setup(struct net_device *bond_dev);
unsigned int bond_get_num_tx_queues(void);
int bond_netlink_init(void);
void bond_netlink_fini(void);
int bond_option_mode_set(struct bonding *bond, int mode);
int bond_option_active_slave_set(struct bonding *bond, struct net_device *slave_dev);
int bond_option_miimon_set(struct bonding *bond, int miimon);
int bond_option_updelay_set(struct bonding *bond, int updelay);
int bond_option_downdelay_set(struct bonding *bond, int downdelay);
int bond_option_use_carrier_set(struct bonding *bond, int use_carrier);
int bond_option_arp_interval_set(struct bonding *bond, int arp_interval);
int bond_option_arp_ip_targets_set(struct bonding *bond, __be32 *targets,
int count);
int bond_option_arp_ip_target_add(struct bonding *bond, __be32 target);
int bond_option_arp_ip_target_rem(struct bonding *bond, __be32 target);
int bond_option_arp_validate_set(struct bonding *bond, int arp_validate);
int bond_option_arp_all_targets_set(struct bonding *bond, int arp_all_targets);
int bond_option_primary_set(struct bonding *bond, const char *primary);
int bond_option_primary_reselect_set(struct bonding *bond,
int primary_reselect);
int bond_option_fail_over_mac_set(struct bonding *bond, int fail_over_mac);
int bond_option_xmit_hash_policy_set(struct bonding *bond,
int xmit_hash_policy);
int bond_option_resend_igmp_set(struct bonding *bond, int resend_igmp);
int bond_option_num_peer_notif_set(struct bonding *bond, int num_peer_notif);
int bond_option_all_slaves_active_set(struct bonding *bond,
int all_slaves_active);
int bond_option_min_links_set(struct bonding *bond, int min_links);
int bond_option_lp_interval_set(struct bonding *bond, int min_links);
int bond_option_packets_per_slave_set(struct bonding *bond,
int packets_per_slave);
int bond_option_lacp_rate_set(struct bonding *bond, int lacp_rate);
int bond_option_ad_select_set(struct bonding *bond, int ad_select);
struct net_device *bond_option_active_slave_get_rcu(struct bonding *bond);
struct net_device *bond_option_active_slave_get(struct bonding *bond);
const char *bond_slave_link_status(s8 link);
......@@ -562,7 +536,6 @@ static inline int bond_get_targets_ip(__be32 *targets, __be32 ip)
/* exported from bond_main.c */
extern int bond_net_id;
extern const struct bond_parm_tbl bond_lacp_tbl[];
extern const struct bond_parm_tbl bond_mode_tbl[];
extern const struct bond_parm_tbl xmit_hashtype_tbl[];
extern const struct bond_parm_tbl arp_validate_tbl[];
extern const struct bond_parm_tbl arp_all_targets_tbl[];
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment