diff options
Diffstat (limited to 'drivers/net/bonding/bond_main.c')
-rw-r--r-- | drivers/net/bonding/bond_main.c | 55 |
1 files changed, 50 insertions, 5 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; |