diff options
author | Nikolay Aleksandrov <nikolay@redhat.com> | 2013-11-05 07:51:41 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-11-07 15:10:21 -0500 |
commit | 73958329ea1fe0dc149b51e5d8703015f65a03e0 (patch) | |
tree | 149b655cfa917f9239f68dfe0ad3bb55d7ad8a90 /drivers | |
parent | 6fb392b1a63ae36c31f62bc3fc8630b49d602b62 (diff) |
bonding: extend round-robin mode with packets_per_slave
This patch aims to extend round-robin mode with a new option called
packets_per_slave which can have the following values and effects:
0 - choose a random slave
1 (default) - standard round-robin, 1 packet per slave
>1 - round-robin when >1 packets have been transmitted per slave
The allowed values are between 0 and 65535.
This patch also fixes the comment style in bond_xmit_roundrobin().
Signed-off-by: Nikolay Aleksandrov <nikolay@redhat.com>
Acked-by: Veaceslav Falico <vfalico@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/bonding/bond_main.c | 55 | ||||
-rw-r--r-- | drivers/net/bonding/bond_sysfs.c | 49 | ||||
-rw-r--r-- | drivers/net/bonding/bonding.h | 3 |
3 files changed, 101 insertions, 6 deletions
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index a141f406cb98..4dd5ee2a34cc 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c | |||
@@ -79,6 +79,7 @@ | |||
79 | #include <net/pkt_sched.h> | 79 | #include <net/pkt_sched.h> |
80 | #include <linux/rculist.h> | 80 | #include <linux/rculist.h> |
81 | #include <net/flow_keys.h> | 81 | #include <net/flow_keys.h> |
82 | #include <linux/reciprocal_div.h> | ||
82 | #include "bonding.h" | 83 | #include "bonding.h" |
83 | #include "bond_3ad.h" | 84 | #include "bond_3ad.h" |
84 | #include "bond_alb.h" | 85 | #include "bond_alb.h" |
@@ -111,6 +112,7 @@ static char *fail_over_mac; | |||
111 | static int all_slaves_active; | 112 | static int all_slaves_active; |
112 | static struct bond_params bonding_defaults; | 113 | static struct bond_params bonding_defaults; |
113 | static int resend_igmp = BOND_DEFAULT_RESEND_IGMP; | 114 | static int resend_igmp = BOND_DEFAULT_RESEND_IGMP; |
115 | static int packets_per_slave = 1; | ||
114 | 116 | ||
115 | module_param(max_bonds, int, 0); | 117 | module_param(max_bonds, int, 0); |
116 | MODULE_PARM_DESC(max_bonds, "Max number of bonded devices"); | 118 | MODULE_PARM_DESC(max_bonds, "Max number of bonded devices"); |
@@ -183,6 +185,10 @@ MODULE_PARM_DESC(all_slaves_active, "Keep all frames received on an interface" | |||
183 | module_param(resend_igmp, int, 0); | 185 | module_param(resend_igmp, int, 0); |
184 | MODULE_PARM_DESC(resend_igmp, "Number of IGMP membership reports to send on " | 186 | MODULE_PARM_DESC(resend_igmp, "Number of IGMP membership reports to send on " |
185 | "link failure"); | 187 | "link failure"); |
188 | module_param(packets_per_slave, int, 0); | ||
189 | MODULE_PARM_DESC(packets_per_slave, "Packets to send per slave in balance-rr " | ||
190 | "mode; 0 for a random slave, 1 packet per " | ||
191 | "slave (default), >1 packets per slave."); | ||
186 | 192 | ||
187 | /*----------------------------- Global variables ----------------------------*/ | 193 | /*----------------------------- Global variables ----------------------------*/ |
188 | 194 | ||
@@ -3574,14 +3580,44 @@ void bond_xmit_slave_id(struct bonding *bond, struct sk_buff *skb, int slave_id) | |||
3574 | kfree_skb(skb); | 3580 | kfree_skb(skb); |
3575 | } | 3581 | } |
3576 | 3582 | ||
3583 | /** | ||
3584 | * bond_rr_gen_slave_id - generate slave id based on packets_per_slave | ||
3585 | * @bond: bonding device to use | ||
3586 | * | ||
3587 | * Based on the value of the bonding device's packets_per_slave parameter | ||
3588 | * this function generates a slave id, which is usually used as the next | ||
3589 | * slave to transmit through. | ||
3590 | */ | ||
3591 | static u32 bond_rr_gen_slave_id(struct bonding *bond) | ||
3592 | { | ||
3593 | int packets_per_slave = bond->params.packets_per_slave; | ||
3594 | u32 slave_id; | ||
3595 | |||
3596 | switch (packets_per_slave) { | ||
3597 | case 0: | ||
3598 | slave_id = prandom_u32(); | ||
3599 | break; | ||
3600 | case 1: | ||
3601 | slave_id = bond->rr_tx_counter; | ||
3602 | break; | ||
3603 | default: | ||
3604 | slave_id = reciprocal_divide(bond->rr_tx_counter, | ||
3605 | packets_per_slave); | ||
3606 | break; | ||
3607 | } | ||
3608 | bond->rr_tx_counter++; | ||
3609 | |||
3610 | return slave_id; | ||
3611 | } | ||
3612 | |||
3577 | static int bond_xmit_roundrobin(struct sk_buff *skb, struct net_device *bond_dev) | 3613 | static int bond_xmit_roundrobin(struct sk_buff *skb, struct net_device *bond_dev) |
3578 | { | 3614 | { |
3579 | struct bonding *bond = netdev_priv(bond_dev); | 3615 | struct bonding *bond = netdev_priv(bond_dev); |
3580 | struct iphdr *iph = ip_hdr(skb); | 3616 | struct iphdr *iph = ip_hdr(skb); |
3581 | struct slave *slave; | 3617 | struct slave *slave; |
3618 | u32 slave_id; | ||
3582 | 3619 | ||
3583 | /* | 3620 | /* Start with the curr_active_slave that joined the bond as the |
3584 | * Start with the curr_active_slave that joined the bond as the | ||
3585 | * default for sending IGMP traffic. For failover purposes one | 3621 | * default for sending IGMP traffic. For failover purposes one |
3586 | * needs to maintain some consistency for the interface that will | 3622 | * needs to maintain some consistency for the interface that will |
3587 | * send the join/membership reports. The curr_active_slave found | 3623 | * send the join/membership reports. The curr_active_slave found |
@@ -3594,8 +3630,8 @@ static int bond_xmit_roundrobin(struct sk_buff *skb, struct net_device *bond_dev | |||
3594 | else | 3630 | else |
3595 | bond_xmit_slave_id(bond, skb, 0); | 3631 | bond_xmit_slave_id(bond, skb, 0); |
3596 | } else { | 3632 | } else { |
3597 | bond_xmit_slave_id(bond, skb, | 3633 | slave_id = bond_rr_gen_slave_id(bond); |
3598 | bond->rr_tx_counter++ % bond->slave_cnt); | 3634 | bond_xmit_slave_id(bond, skb, slave_id % bond->slave_cnt); |
3599 | } | 3635 | } |
3600 | 3636 | ||
3601 | return NETDEV_TX_OK; | 3637 | return NETDEV_TX_OK; |
@@ -4099,6 +4135,12 @@ static int bond_check_params(struct bond_params *params) | |||
4099 | resend_igmp = BOND_DEFAULT_RESEND_IGMP; | 4135 | resend_igmp = BOND_DEFAULT_RESEND_IGMP; |
4100 | } | 4136 | } |
4101 | 4137 | ||
4138 | if (packets_per_slave < 0 || packets_per_slave > USHRT_MAX) { | ||
4139 | pr_warn("Warning: packets_per_slave (%d) should be between 0 and %u resetting to 1\n", | ||
4140 | packets_per_slave, USHRT_MAX); | ||
4141 | packets_per_slave = 1; | ||
4142 | } | ||
4143 | |||
4102 | /* reset values for TLB/ALB */ | 4144 | /* reset values for TLB/ALB */ |
4103 | if ((bond_mode == BOND_MODE_TLB) || | 4145 | if ((bond_mode == BOND_MODE_TLB) || |
4104 | (bond_mode == BOND_MODE_ALB)) { | 4146 | (bond_mode == BOND_MODE_ALB)) { |
@@ -4288,7 +4330,10 @@ static int bond_check_params(struct bond_params *params) | |||
4288 | params->resend_igmp = resend_igmp; | 4330 | params->resend_igmp = resend_igmp; |
4289 | params->min_links = min_links; | 4331 | params->min_links = min_links; |
4290 | params->lp_interval = BOND_ALB_DEFAULT_LP_INTERVAL; | 4332 | params->lp_interval = BOND_ALB_DEFAULT_LP_INTERVAL; |
4291 | 4333 | if (packets_per_slave > 1) | |
4334 | params->packets_per_slave = reciprocal_value(packets_per_slave); | ||
4335 | else | ||
4336 | params->packets_per_slave = packets_per_slave; | ||
4292 | if (primary) { | 4337 | if (primary) { |
4293 | strncpy(params->primary, primary, IFNAMSIZ); | 4338 | strncpy(params->primary, primary, IFNAMSIZ); |
4294 | params->primary[IFNAMSIZ - 1] = 0; | 4339 | params->primary[IFNAMSIZ - 1] = 0; |
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c index 47749c970a01..75dc4d0efb34 100644 --- a/drivers/net/bonding/bond_sysfs.c +++ b/drivers/net/bonding/bond_sysfs.c | |||
@@ -40,6 +40,7 @@ | |||
40 | #include <net/net_namespace.h> | 40 | #include <net/net_namespace.h> |
41 | #include <net/netns/generic.h> | 41 | #include <net/netns/generic.h> |
42 | #include <linux/nsproxy.h> | 42 | #include <linux/nsproxy.h> |
43 | #include <linux/reciprocal_div.h> | ||
43 | 44 | ||
44 | #include "bonding.h" | 45 | #include "bonding.h" |
45 | 46 | ||
@@ -1640,6 +1641,53 @@ out: | |||
1640 | static DEVICE_ATTR(lp_interval, S_IRUGO | S_IWUSR, | 1641 | static DEVICE_ATTR(lp_interval, S_IRUGO | S_IWUSR, |
1641 | bonding_show_lp_interval, bonding_store_lp_interval); | 1642 | bonding_show_lp_interval, bonding_store_lp_interval); |
1642 | 1643 | ||
1644 | static ssize_t bonding_show_packets_per_slave(struct device *d, | ||
1645 | struct device_attribute *attr, | ||
1646 | char *buf) | ||
1647 | { | ||
1648 | struct bonding *bond = to_bond(d); | ||
1649 | int packets_per_slave = bond->params.packets_per_slave; | ||
1650 | |||
1651 | if (packets_per_slave > 1) | ||
1652 | packets_per_slave = reciprocal_value(packets_per_slave); | ||
1653 | |||
1654 | return sprintf(buf, "%d\n", packets_per_slave); | ||
1655 | } | ||
1656 | |||
1657 | static ssize_t bonding_store_packets_per_slave(struct device *d, | ||
1658 | struct device_attribute *attr, | ||
1659 | const char *buf, size_t count) | ||
1660 | { | ||
1661 | struct bonding *bond = to_bond(d); | ||
1662 | int new_value, ret = count; | ||
1663 | |||
1664 | if (sscanf(buf, "%d", &new_value) != 1) { | ||
1665 | pr_err("%s: no packets_per_slave value specified.\n", | ||
1666 | bond->dev->name); | ||
1667 | ret = -EINVAL; | ||
1668 | goto out; | ||
1669 | } | ||
1670 | if (new_value < 0 || new_value > USHRT_MAX) { | ||
1671 | pr_err("%s: packets_per_slave must be between 0 and %u\n", | ||
1672 | bond->dev->name, USHRT_MAX); | ||
1673 | ret = -EINVAL; | ||
1674 | goto out; | ||
1675 | } | ||
1676 | if (bond->params.mode != BOND_MODE_ROUNDROBIN) | ||
1677 | pr_warn("%s: Warning: packets_per_slave has effect only in balance-rr mode\n", | ||
1678 | bond->dev->name); | ||
1679 | if (new_value > 1) | ||
1680 | bond->params.packets_per_slave = reciprocal_value(new_value); | ||
1681 | else | ||
1682 | bond->params.packets_per_slave = new_value; | ||
1683 | out: | ||
1684 | return ret; | ||
1685 | } | ||
1686 | |||
1687 | static DEVICE_ATTR(packets_per_slave, S_IRUGO | S_IWUSR, | ||
1688 | bonding_show_packets_per_slave, | ||
1689 | bonding_store_packets_per_slave); | ||
1690 | |||
1643 | static struct attribute *per_bond_attrs[] = { | 1691 | static struct attribute *per_bond_attrs[] = { |
1644 | &dev_attr_slaves.attr, | 1692 | &dev_attr_slaves.attr, |
1645 | &dev_attr_mode.attr, | 1693 | &dev_attr_mode.attr, |
@@ -1671,6 +1719,7 @@ static struct attribute *per_bond_attrs[] = { | |||
1671 | &dev_attr_resend_igmp.attr, | 1719 | &dev_attr_resend_igmp.attr, |
1672 | &dev_attr_min_links.attr, | 1720 | &dev_attr_min_links.attr, |
1673 | &dev_attr_lp_interval.attr, | 1721 | &dev_attr_lp_interval.attr, |
1722 | &dev_attr_packets_per_slave.attr, | ||
1674 | NULL, | 1723 | NULL, |
1675 | }; | 1724 | }; |
1676 | 1725 | ||
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h index 046a60535e04..77a07a12e77f 100644 --- a/drivers/net/bonding/bonding.h +++ b/drivers/net/bonding/bonding.h | |||
@@ -156,6 +156,7 @@ struct bond_params { | |||
156 | int all_slaves_active; | 156 | int all_slaves_active; |
157 | int resend_igmp; | 157 | int resend_igmp; |
158 | int lp_interval; | 158 | int lp_interval; |
159 | int packets_per_slave; | ||
159 | }; | 160 | }; |
160 | 161 | ||
161 | struct bond_parm_tbl { | 162 | struct bond_parm_tbl { |
@@ -222,7 +223,7 @@ struct bonding { | |||
222 | char proc_file_name[IFNAMSIZ]; | 223 | char proc_file_name[IFNAMSIZ]; |
223 | #endif /* CONFIG_PROC_FS */ | 224 | #endif /* CONFIG_PROC_FS */ |
224 | struct list_head bond_list; | 225 | struct list_head bond_list; |
225 | u16 rr_tx_counter; | 226 | u32 rr_tx_counter; |
226 | struct ad_bond_info ad_info; | 227 | struct ad_bond_info ad_info; |
227 | struct alb_bond_info alb_info; | 228 | struct alb_bond_info alb_info; |
228 | struct bond_params params; | 229 | struct bond_params params; |