diff options
author | Jay Vosburgh <fubar@us.ibm.com> | 2005-06-26 17:54:11 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@pobox.com> | 2005-06-26 17:54:11 -0400 |
commit | 169a3e66637c667b43dab7c319ffd5c99804cad8 (patch) | |
tree | f10f7c82ca44b871ae1391c5a3d35a65c463fc9b /drivers/net/bonding/bond_main.c | |
parent | c3ade5cad07f4d67f2e16a28f3c73d9483a55e0e (diff) |
bonding: xor/802.3ad improved slave hash
Add support for alternate slave selection algorithms to bonding
balance-xor and 802.3ad modes. Default mode (what we have now: xor of
MAC addresses) is "layer2", new choice is "layer3+4", using IP and port
information for hashing to select peer.
Originally submitted by Jason Gabler for balance-xor mode;
modified by Jay Vosburgh to additionally support 802.3ad mode. Jason's
original comment is as follows:
The attached patch to the Linux Etherchannel Bonding driver modifies the
driver's "balance-xor" mode as follows:
- alternate hashing policy support for mode 2
* Added kernel parameter "xmit_policy" to allow the specification
of different hashing policies for mode 2. The original mode 2
policy is the default, now found in xmit_hash_policy_layer2().
* Added xmit_hash_policy_layer34()
This patch was inspired by hashing policies implemented by Cisco,
Foundry and IBM, which are explained in
Foundry documentation found at:
http://www.foundrynet.com/services/documentation/sribcg/Trunking.html#112750
Signed-off-by: Jason Gabler <jygabler@lbl.gov>
Signed-off-by: Jay Vosburgh <fubar@us.ibm.com>
Diffstat (limited to 'drivers/net/bonding/bond_main.c')
-rw-r--r-- | drivers/net/bonding/bond_main.c | 107 |
1 files changed, 98 insertions, 9 deletions
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 545f6fe025a8..2c930da90a85 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c | |||
@@ -479,6 +479,14 @@ | |||
479 | * - Support for generating gratuitous ARPs in active-backup mode. | 479 | * - Support for generating gratuitous ARPs in active-backup mode. |
480 | * Includes support for VLAN tagging all bonding-generated ARPs | 480 | * Includes support for VLAN tagging all bonding-generated ARPs |
481 | * as needed. Set version to 2.6.2. | 481 | * as needed. Set version to 2.6.2. |
482 | * 2005/06/08 - Jason Gabler <jygabler at lbl dot gov> | ||
483 | * - alternate hashing policy support for mode 2 | ||
484 | * * Added kernel parameter "xmit_hash_policy" to allow the selection | ||
485 | * of different hashing policies for mode 2. The original mode 2 | ||
486 | * policy is the default, now found in xmit_hash_policy_layer2(). | ||
487 | * * Added xmit_hash_policy_layer34() | ||
488 | * - Modified by Jay Vosburgh <fubar@us.ibm.com> to also support mode 4. | ||
489 | * Set version to 2.6.3. | ||
482 | */ | 490 | */ |
483 | 491 | ||
484 | //#define BONDING_DEBUG 1 | 492 | //#define BONDING_DEBUG 1 |
@@ -493,7 +501,10 @@ | |||
493 | #include <linux/ptrace.h> | 501 | #include <linux/ptrace.h> |
494 | #include <linux/ioport.h> | 502 | #include <linux/ioport.h> |
495 | #include <linux/in.h> | 503 | #include <linux/in.h> |
504 | #include <net/ip.h> | ||
496 | #include <linux/ip.h> | 505 | #include <linux/ip.h> |
506 | #include <linux/tcp.h> | ||
507 | #include <linux/udp.h> | ||
497 | #include <linux/slab.h> | 508 | #include <linux/slab.h> |
498 | #include <linux/string.h> | 509 | #include <linux/string.h> |
499 | #include <linux/init.h> | 510 | #include <linux/init.h> |
@@ -541,6 +552,7 @@ static int use_carrier = 1; | |||
541 | static char *mode = NULL; | 552 | static char *mode = NULL; |
542 | static char *primary = NULL; | 553 | static char *primary = NULL; |
543 | static char *lacp_rate = NULL; | 554 | static char *lacp_rate = NULL; |
555 | static char *xmit_hash_policy = NULL; | ||
544 | static int arp_interval = BOND_LINK_ARP_INTERV; | 556 | static int arp_interval = BOND_LINK_ARP_INTERV; |
545 | static char *arp_ip_target[BOND_MAX_ARP_TARGETS] = { NULL, }; | 557 | static char *arp_ip_target[BOND_MAX_ARP_TARGETS] = { NULL, }; |
546 | 558 | ||
@@ -560,6 +572,8 @@ module_param(primary, charp, 0); | |||
560 | MODULE_PARM_DESC(primary, "Primary network device to use"); | 572 | MODULE_PARM_DESC(primary, "Primary network device to use"); |
561 | module_param(lacp_rate, charp, 0); | 573 | module_param(lacp_rate, charp, 0); |
562 | MODULE_PARM_DESC(lacp_rate, "LACPDU tx rate to request from 802.3ad partner (slow/fast)"); | 574 | MODULE_PARM_DESC(lacp_rate, "LACPDU tx rate to request from 802.3ad partner (slow/fast)"); |
575 | module_param(xmit_hash_policy, charp, 0); | ||
576 | MODULE_PARM_DESC(xmit_hash_policy, "XOR hashing method : 0 for layer 2 (default), 1 for layer 3+4"); | ||
563 | module_param(arp_interval, int, 0); | 577 | module_param(arp_interval, int, 0); |
564 | MODULE_PARM_DESC(arp_interval, "arp interval in milliseconds"); | 578 | MODULE_PARM_DESC(arp_interval, "arp interval in milliseconds"); |
565 | module_param_array(arp_ip_target, charp, NULL, 0); | 579 | module_param_array(arp_ip_target, charp, NULL, 0); |
@@ -579,6 +593,7 @@ static struct proc_dir_entry *bond_proc_dir = NULL; | |||
579 | static u32 arp_target[BOND_MAX_ARP_TARGETS] = { 0, } ; | 593 | static u32 arp_target[BOND_MAX_ARP_TARGETS] = { 0, } ; |
580 | static int arp_ip_count = 0; | 594 | static int arp_ip_count = 0; |
581 | static int bond_mode = BOND_MODE_ROUNDROBIN; | 595 | static int bond_mode = BOND_MODE_ROUNDROBIN; |
596 | static int xmit_hashtype= BOND_XMIT_POLICY_LAYER2; | ||
582 | static int lacp_fast = 0; | 597 | static int lacp_fast = 0; |
583 | static int app_abi_ver = 0; | 598 | static int app_abi_ver = 0; |
584 | static int orig_app_abi_ver = -1; /* This is used to save the first ABI version | 599 | static int orig_app_abi_ver = -1; /* This is used to save the first ABI version |
@@ -588,7 +603,6 @@ static int orig_app_abi_ver = -1; /* This is used to save the first ABI version | |||
588 | * command comes from an application using | 603 | * command comes from an application using |
589 | * another ABI version. | 604 | * another ABI version. |
590 | */ | 605 | */ |
591 | |||
592 | struct bond_parm_tbl { | 606 | struct bond_parm_tbl { |
593 | char *modename; | 607 | char *modename; |
594 | int mode; | 608 | int mode; |
@@ -611,9 +625,15 @@ static struct bond_parm_tbl bond_mode_tbl[] = { | |||
611 | { NULL, -1}, | 625 | { NULL, -1}, |
612 | }; | 626 | }; |
613 | 627 | ||
628 | static struct bond_parm_tbl xmit_hashtype_tbl[] = { | ||
629 | { "layer2", BOND_XMIT_POLICY_LAYER2}, | ||
630 | { "layer3+4", BOND_XMIT_POLICY_LAYER34}, | ||
631 | { NULL, -1}, | ||
632 | }; | ||
633 | |||
614 | /*-------------------------- Forward declarations ---------------------------*/ | 634 | /*-------------------------- Forward declarations ---------------------------*/ |
615 | 635 | ||
616 | static inline void bond_set_mode_ops(struct net_device *bond_dev, int mode); | 636 | static inline void bond_set_mode_ops(struct bonding *bond, int mode); |
617 | static void bond_send_gratuitous_arp(struct bonding *bond); | 637 | static void bond_send_gratuitous_arp(struct bonding *bond); |
618 | 638 | ||
619 | /*---------------------------- General routines -----------------------------*/ | 639 | /*---------------------------- General routines -----------------------------*/ |
@@ -3724,6 +3744,46 @@ static void bond_unregister_lacpdu(struct bonding *bond) | |||
3724 | dev_remove_pack(&(BOND_AD_INFO(bond).ad_pkt_type)); | 3744 | dev_remove_pack(&(BOND_AD_INFO(bond).ad_pkt_type)); |
3725 | } | 3745 | } |
3726 | 3746 | ||
3747 | /*---------------------------- Hashing Policies -----------------------------*/ | ||
3748 | |||
3749 | /* | ||
3750 | * Hash for the the output device based upon layer 3 and layer 4 data. If | ||
3751 | * the packet is a frag or not TCP or UDP, just use layer 3 data. If it is | ||
3752 | * altogether not IP, mimic bond_xmit_hash_policy_l2() | ||
3753 | */ | ||
3754 | static int bond_xmit_hash_policy_l34(struct sk_buff *skb, | ||
3755 | struct net_device *bond_dev, int count) | ||
3756 | { | ||
3757 | struct ethhdr *data = (struct ethhdr *)skb->data; | ||
3758 | struct iphdr *iph = skb->nh.iph; | ||
3759 | u16 *layer4hdr = (u16 *)((u32 *)iph + iph->ihl); | ||
3760 | int layer4_xor = 0; | ||
3761 | |||
3762 | if (skb->protocol == __constant_htons(ETH_P_IP)) { | ||
3763 | if (!(iph->frag_off & __constant_htons(IP_MF|IP_OFFSET)) && | ||
3764 | (iph->protocol == IPPROTO_TCP || | ||
3765 | iph->protocol == IPPROTO_UDP)) { | ||
3766 | layer4_xor = htons((*layer4hdr ^ *(layer4hdr + 1))); | ||
3767 | } | ||
3768 | return (layer4_xor ^ | ||
3769 | ((ntohl(iph->saddr ^ iph->daddr)) & 0xffff)) % count; | ||
3770 | |||
3771 | } | ||
3772 | |||
3773 | return (data->h_dest[5] ^ bond_dev->dev_addr[5]) % count; | ||
3774 | } | ||
3775 | |||
3776 | /* | ||
3777 | * Hash for the output device based upon layer 2 data | ||
3778 | */ | ||
3779 | static int bond_xmit_hash_policy_l2(struct sk_buff *skb, | ||
3780 | struct net_device *bond_dev, int count) | ||
3781 | { | ||
3782 | struct ethhdr *data = (struct ethhdr *)skb->data; | ||
3783 | |||
3784 | return (data->h_dest[5] ^ bond_dev->dev_addr[5]) % count; | ||
3785 | } | ||
3786 | |||
3727 | /*-------------------------- Device entry points ----------------------------*/ | 3787 | /*-------------------------- Device entry points ----------------------------*/ |
3728 | 3788 | ||
3729 | static int bond_open(struct net_device *bond_dev) | 3789 | static int bond_open(struct net_device *bond_dev) |
@@ -4310,14 +4370,13 @@ out: | |||
4310 | } | 4370 | } |
4311 | 4371 | ||
4312 | /* | 4372 | /* |
4313 | * in XOR mode, we determine the output device by performing xor on | 4373 | * In bond_xmit_xor() , we determine the output device by using a pre- |
4314 | * the source and destination hw adresses. If this device is not | 4374 | * determined xmit_hash_policy(), If the selected device is not enabled, |
4315 | * enabled, find the next slave following this xor slave. | 4375 | * find the next active slave. |
4316 | */ | 4376 | */ |
4317 | static int bond_xmit_xor(struct sk_buff *skb, struct net_device *bond_dev) | 4377 | static int bond_xmit_xor(struct sk_buff *skb, struct net_device *bond_dev) |
4318 | { | 4378 | { |
4319 | struct bonding *bond = bond_dev->priv; | 4379 | struct bonding *bond = bond_dev->priv; |
4320 | struct ethhdr *data = (struct ethhdr *)skb->data; | ||
4321 | struct slave *slave, *start_at; | 4380 | struct slave *slave, *start_at; |
4322 | int slave_no; | 4381 | int slave_no; |
4323 | int i; | 4382 | int i; |
@@ -4329,7 +4388,7 @@ static int bond_xmit_xor(struct sk_buff *skb, struct net_device *bond_dev) | |||
4329 | goto out; | 4388 | goto out; |
4330 | } | 4389 | } |
4331 | 4390 | ||
4332 | slave_no = (data->h_dest[5]^bond_dev->dev_addr[5]) % bond->slave_cnt; | 4391 | slave_no = bond->xmit_hash_policy(skb, bond_dev, bond->slave_cnt); |
4333 | 4392 | ||
4334 | bond_for_each_slave(bond, slave, i) { | 4393 | bond_for_each_slave(bond, slave, i) { |
4335 | slave_no--; | 4394 | slave_no--; |
@@ -4425,8 +4484,10 @@ out: | |||
4425 | /* | 4484 | /* |
4426 | * set bond mode specific net device operations | 4485 | * set bond mode specific net device operations |
4427 | */ | 4486 | */ |
4428 | static inline void bond_set_mode_ops(struct net_device *bond_dev, int mode) | 4487 | static inline void bond_set_mode_ops(struct bonding *bond, int mode) |
4429 | { | 4488 | { |
4489 | struct net_device *bond_dev = bond->dev; | ||
4490 | |||
4430 | switch (mode) { | 4491 | switch (mode) { |
4431 | case BOND_MODE_ROUNDROBIN: | 4492 | case BOND_MODE_ROUNDROBIN: |
4432 | bond_dev->hard_start_xmit = bond_xmit_roundrobin; | 4493 | bond_dev->hard_start_xmit = bond_xmit_roundrobin; |
@@ -4436,12 +4497,20 @@ static inline void bond_set_mode_ops(struct net_device *bond_dev, int mode) | |||
4436 | break; | 4497 | break; |
4437 | case BOND_MODE_XOR: | 4498 | case BOND_MODE_XOR: |
4438 | bond_dev->hard_start_xmit = bond_xmit_xor; | 4499 | bond_dev->hard_start_xmit = bond_xmit_xor; |
4500 | if (bond->params.xmit_policy == BOND_XMIT_POLICY_LAYER34) | ||
4501 | bond->xmit_hash_policy = bond_xmit_hash_policy_l34; | ||
4502 | else | ||
4503 | bond->xmit_hash_policy = bond_xmit_hash_policy_l2; | ||
4439 | break; | 4504 | break; |
4440 | case BOND_MODE_BROADCAST: | 4505 | case BOND_MODE_BROADCAST: |
4441 | bond_dev->hard_start_xmit = bond_xmit_broadcast; | 4506 | bond_dev->hard_start_xmit = bond_xmit_broadcast; |
4442 | break; | 4507 | break; |
4443 | case BOND_MODE_8023AD: | 4508 | case BOND_MODE_8023AD: |
4444 | bond_dev->hard_start_xmit = bond_3ad_xmit_xor; | 4509 | bond_dev->hard_start_xmit = bond_3ad_xmit_xor; |
4510 | if (bond->params.xmit_policy == BOND_XMIT_POLICY_LAYER34) | ||
4511 | bond->xmit_hash_policy = bond_xmit_hash_policy_l34; | ||
4512 | else | ||
4513 | bond->xmit_hash_policy = bond_xmit_hash_policy_l2; | ||
4445 | break; | 4514 | break; |
4446 | case BOND_MODE_TLB: | 4515 | case BOND_MODE_TLB: |
4447 | case BOND_MODE_ALB: | 4516 | case BOND_MODE_ALB: |
@@ -4490,7 +4559,7 @@ static int __init bond_init(struct net_device *bond_dev, struct bond_params *par | |||
4490 | bond_dev->change_mtu = bond_change_mtu; | 4559 | bond_dev->change_mtu = bond_change_mtu; |
4491 | bond_dev->set_mac_address = bond_set_mac_address; | 4560 | bond_dev->set_mac_address = bond_set_mac_address; |
4492 | 4561 | ||
4493 | bond_set_mode_ops(bond_dev, bond->params.mode); | 4562 | bond_set_mode_ops(bond, bond->params.mode); |
4494 | 4563 | ||
4495 | bond_dev->destructor = free_netdev; | 4564 | bond_dev->destructor = free_netdev; |
4496 | 4565 | ||
@@ -4601,6 +4670,25 @@ static int bond_check_params(struct bond_params *params) | |||
4601 | } | 4670 | } |
4602 | } | 4671 | } |
4603 | 4672 | ||
4673 | if (xmit_hash_policy) { | ||
4674 | if ((bond_mode != BOND_MODE_XOR) && | ||
4675 | (bond_mode != BOND_MODE_8023AD)) { | ||
4676 | printk(KERN_INFO DRV_NAME | ||
4677 | ": xor_mode param is irrelevant in mode %s\n", | ||
4678 | bond_mode_name(bond_mode)); | ||
4679 | } else { | ||
4680 | xmit_hashtype = bond_parse_parm(xmit_hash_policy, | ||
4681 | xmit_hashtype_tbl); | ||
4682 | if (xmit_hashtype == -1) { | ||
4683 | printk(KERN_ERR DRV_NAME | ||
4684 | ": Error: Invalid xmit_hash_policy \"%s\"\n", | ||
4685 | xmit_hash_policy == NULL ? "NULL" : | ||
4686 | xmit_hash_policy); | ||
4687 | return -EINVAL; | ||
4688 | } | ||
4689 | } | ||
4690 | } | ||
4691 | |||
4604 | if (lacp_rate) { | 4692 | if (lacp_rate) { |
4605 | if (bond_mode != BOND_MODE_8023AD) { | 4693 | if (bond_mode != BOND_MODE_8023AD) { |
4606 | printk(KERN_INFO DRV_NAME | 4694 | printk(KERN_INFO DRV_NAME |
@@ -4812,6 +4900,7 @@ static int bond_check_params(struct bond_params *params) | |||
4812 | 4900 | ||
4813 | /* fill params struct with the proper values */ | 4901 | /* fill params struct with the proper values */ |
4814 | params->mode = bond_mode; | 4902 | params->mode = bond_mode; |
4903 | params->xmit_policy = xmit_hashtype; | ||
4815 | params->miimon = miimon; | 4904 | params->miimon = miimon; |
4816 | params->arp_interval = arp_interval; | 4905 | params->arp_interval = arp_interval; |
4817 | params->updelay = updelay; | 4906 | params->updelay = updelay; |