aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMahesh Bandewar <maheshb@google.com>2015-05-09 03:01:57 -0400
committerDavid S. Miller <davem@davemloft.net>2015-05-11 10:59:32 -0400
commitd22a5fc0c32edcf5c3bb973ee8c9a2606ba500a8 (patch)
tree8984e73fb65aa74638b517129d35b94891b7e9f6
parent74514957552edd4661a4608618121f3c71d4e891 (diff)
bonding: Implement user key part of port_key in an AD system.
The port key has three components - user-key, speed-part, and duplex-part. The LSBit is for the duplex-part, next 5 bits are for the speed while the remaining 10 bits are the user defined key bits. Get these 10 bits from the user-space (through the SysFs interface) and use it to form the admin port-key. Allowed range for the user-key is 0 - 1023 (10 bits). If it is not provided then use zero for the user-key-bits (default). It can set using following example code - # modprobe bonding mode=4 # usr_port_key=$(( RANDOM & 0x3FF )) # echo $usr_port_key > /sys/class/net/bond0/bonding/ad_user_port_key # echo +eth1 > /sys/class/net/bond0/bonding/slaves ... # ip link set bond0 up Signed-off-by: Mahesh Bandewar <maheshb@google.com> Reviewed-by: Nikolay Aleksandrov <nikolay@redhat.com> [jt: * fixed up style issues reported by checkpatch * fixed up context from change in ad_actor_sys_prio patch] Signed-off-by: Jonathan Toppins <jtoppins@cumulusnetworks.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--Documentation/networking/bonding.txt63
-rw-r--r--drivers/net/bonding/bond_3ad.c14
-rw-r--r--drivers/net/bonding/bond_main.c10
-rw-r--r--drivers/net/bonding/bond_options.c26
-rw-r--r--drivers/net/bonding/bond_sysfs.c15
-rw-r--r--include/net/bond_options.h1
-rw-r--r--include/net/bonding.h1
7 files changed, 123 insertions, 7 deletions
diff --git a/Documentation/networking/bonding.txt b/Documentation/networking/bonding.txt
index 2c197b68baf0..334b49ef02d1 100644
--- a/Documentation/networking/bonding.txt
+++ b/Documentation/networking/bonding.txt
@@ -51,6 +51,7 @@ Table of Contents
513.4 Configuring Bonding Manually via Sysfs 513.4 Configuring Bonding Manually via Sysfs
523.5 Configuration with Interfaces Support 523.5 Configuration with Interfaces Support
533.6 Overriding Configuration for Special Cases 533.6 Overriding Configuration for Special Cases
543.7 Configuring LACP for 802.3ad mode in a more secure way
54 55
554. Querying Bonding Configuration 564. Querying Bonding Configuration
564.1 Bonding Configuration 574.1 Bonding Configuration
@@ -241,6 +242,21 @@ ad_select
241 242
242 This option was added in bonding version 3.4.0. 243 This option was added in bonding version 3.4.0.
243 244
245ad_user_port_key
246
247 In an AD system, the port-key has three parts as shown below -
248
249 Bits Use
250 00 Duplex
251 01-05 Speed
252 06-15 User-defined
253
254 This defines the upper 10 bits of the port key. The values can be
255 from 0 - 1023. If not given, the system defaults to 0.
256
257 This parameter has effect only in 802.3ad mode and is available through
258 SysFs interface.
259
244all_slaves_active 260all_slaves_active
245 261
246 Specifies that duplicate frames (received on inactive ports) should be 262 Specifies that duplicate frames (received on inactive ports) should be
@@ -1643,6 +1659,53 @@ output port selection.
1643This feature first appeared in bonding driver version 3.7.0 and support for 1659This feature first appeared in bonding driver version 3.7.0 and support for
1644output slave selection was limited to round-robin and active-backup modes. 1660output slave selection was limited to round-robin and active-backup modes.
1645 1661
16623.7 Configuring LACP for 802.3ad mode in a more secure way
1663----------------------------------------------------------
1664
1665When using 802.3ad bonding mode, the Actor (host) and Partner (switch)
1666exchange LACPDUs. These LACPDUs cannot be sniffed, because they are
1667destined to link local mac addresses (which switches/bridges are not
1668supposed to forward). However, most of the values are easily predictable
1669or are simply the machine's MAC address (which is trivially known to all
1670other hosts in the same L2). This implies that other machines in the L2
1671domain can spoof LACPDU packets from other hosts to the switch and potentially
1672cause mayhem by joining (from the point of view of the switch) another
1673machine's aggregate, thus receiving a portion of that hosts incoming
1674traffic and / or spoofing traffic from that machine themselves (potentially
1675even successfully terminating some portion of flows). Though this is not
1676a likely scenario, one could avoid this possibility by simply configuring
1677few bonding parameters:
1678
1679 (a) ad_actor_system : You can set a random mac-address that can be used for
1680 these LACPDU exchanges. The value can not be either NULL or Multicast.
1681 Also it's preferable to set the local-admin bit. Following shell code
1682 generates a random mac-address as described above.
1683
1684 # sys_mac_addr=$(printf '%02x:%02x:%02x:%02x:%02x:%02x' \
1685 $(( (RANDOM & 0xFE) | 0x02 )) \
1686 $(( RANDOM & 0xFF )) \
1687 $(( RANDOM & 0xFF )) \
1688 $(( RANDOM & 0xFF )) \
1689 $(( RANDOM & 0xFF )) \
1690 $(( RANDOM & 0xFF )))
1691 # echo $sys_mac_addr > /sys/class/net/bond0/bonding/ad_actor_system
1692
1693 (b) ad_actor_sys_prio : Randomize the system priority. The default value
1694 is 65535, but system can take the value from 1 - 65535. Following shell
1695 code generates random priority and sets it.
1696
1697 # sys_prio=$(( 1 + RANDOM + RANDOM ))
1698 # echo $sys_prio > /sys/class/net/bond0/bonding/ad_actor_sys_prio
1699
1700 (c) ad_user_port_key : Use the user portion of the port-key. The default
1701 keeps this empty. These are the upper 10 bits of the port-key and value
1702 ranges from 0 - 1023. Following shell code generates these 10 bits and
1703 sets it.
1704
1705 # usr_port_key=$(( RANDOM & 0x3FF ))
1706 # echo $usr_port_key > /sys/class/net/bond0/bonding/ad_user_port_key
1707
1708
16464 Querying Bonding Configuration 17094 Querying Bonding Configuration
1647================================= 1710=================================
1648 1711
diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c
index 012f7bc22d91..7fde4d5c2b28 100644
--- a/drivers/net/bonding/bond_3ad.c
+++ b/drivers/net/bonding/bond_3ad.c
@@ -75,10 +75,10 @@
75/* Port Key definitions 75/* Port Key definitions
76 * key is determined according to the link speed, duplex and 76 * key is determined according to the link speed, duplex and
77 * user key (which is yet not supported) 77 * user key (which is yet not supported)
78 * -------------------------------------------------------------- 78 * --------------------------------------------------------------
79 * Port key : | User key | Speed | Duplex | 79 * Port key | User key (10 bits) | Speed (5 bits) | Duplex|
80 * -------------------------------------------------------------- 80 * --------------------------------------------------------------
81 * 16 6 1 0 81 * |15 6|5 1|0
82 */ 82 */
83#define AD_DUPLEX_KEY_MASKS 0x1 83#define AD_DUPLEX_KEY_MASKS 0x1
84#define AD_SPEED_KEY_MASKS 0x3E 84#define AD_SPEED_KEY_MASKS 0x3E
@@ -1951,10 +1951,10 @@ void bond_3ad_bind_slave(struct slave *slave)
1951 1951
1952 port->slave = slave; 1952 port->slave = slave;
1953 port->actor_port_number = SLAVE_AD_INFO(slave)->id; 1953 port->actor_port_number = SLAVE_AD_INFO(slave)->id;
1954 /* key is determined according to the link speed, duplex and user key(which 1954 /* key is determined according to the link speed, duplex and
1955 * is yet not supported) 1955 * user key
1956 */ 1956 */
1957 port->actor_admin_port_key = 0; 1957 port->actor_admin_port_key = bond->params.ad_user_port_key << 6;
1958 port->actor_admin_port_key |= __get_duplex(port); 1958 port->actor_admin_port_key |= __get_duplex(port);
1959 port->actor_admin_port_key |= (__get_link_speed(port) << 1); 1959 port->actor_admin_port_key |= (__get_link_speed(port) << 1);
1960 port->actor_oper_port_key = port->actor_admin_port_key; 1960 port->actor_oper_port_key = port->actor_admin_port_key;
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index a4e2f27ef683..2ee13be7551b 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -4141,6 +4141,7 @@ static int bond_check_params(struct bond_params *params)
4141 const struct bond_opt_value *valptr; 4141 const struct bond_opt_value *valptr;
4142 int arp_all_targets_value; 4142 int arp_all_targets_value;
4143 u16 ad_actor_sys_prio = 0; 4143 u16 ad_actor_sys_prio = 0;
4144 u16 ad_user_port_key = 0;
4144 4145
4145 /* Convert string parameters. */ 4146 /* Convert string parameters. */
4146 if (mode) { 4147 if (mode) {
@@ -4445,6 +4446,14 @@ static int bond_check_params(struct bond_params *params)
4445 } 4446 }
4446 ad_actor_sys_prio = valptr->value; 4447 ad_actor_sys_prio = valptr->value;
4447 4448
4449 valptr = bond_opt_parse(bond_opt_get(BOND_OPT_AD_USER_PORT_KEY),
4450 &newval);
4451 if (!valptr) {
4452 pr_err("Error: No ad_user_port_key default value");
4453 return -EINVAL;
4454 }
4455 ad_user_port_key = valptr->value;
4456
4448 if (lp_interval == 0) { 4457 if (lp_interval == 0) {
4449 pr_warn("Warning: ip_interval must be between 1 and %d, so it was reset to %d\n", 4458 pr_warn("Warning: ip_interval must be between 1 and %d, so it was reset to %d\n",
4450 INT_MAX, BOND_ALB_DEFAULT_LP_INTERVAL); 4459 INT_MAX, BOND_ALB_DEFAULT_LP_INTERVAL);
@@ -4475,6 +4484,7 @@ static int bond_check_params(struct bond_params *params)
4475 params->tlb_dynamic_lb = 1; /* Default value */ 4484 params->tlb_dynamic_lb = 1; /* Default value */
4476 params->ad_actor_sys_prio = ad_actor_sys_prio; 4485 params->ad_actor_sys_prio = ad_actor_sys_prio;
4477 eth_zero_addr(params->ad_actor_system); 4486 eth_zero_addr(params->ad_actor_system);
4487 params->ad_user_port_key = ad_user_port_key;
4478 if (packets_per_slave > 0) { 4488 if (packets_per_slave > 0) {
4479 params->reciprocal_packets_per_slave = 4489 params->reciprocal_packets_per_slave =
4480 reciprocal_value(packets_per_slave); 4490 reciprocal_value(packets_per_slave);
diff --git a/drivers/net/bonding/bond_options.c b/drivers/net/bonding/bond_options.c
index cdcef217ac84..c85da05721e6 100644
--- a/drivers/net/bonding/bond_options.c
+++ b/drivers/net/bonding/bond_options.c
@@ -74,6 +74,8 @@ static int bond_option_ad_actor_sys_prio_set(struct bonding *bond,
74 const struct bond_opt_value *newval); 74 const struct bond_opt_value *newval);
75static int bond_option_ad_actor_system_set(struct bonding *bond, 75static int bond_option_ad_actor_system_set(struct bonding *bond,
76 const struct bond_opt_value *newval); 76 const struct bond_opt_value *newval);
77static int bond_option_ad_user_port_key_set(struct bonding *bond,
78 const struct bond_opt_value *newval);
77 79
78 80
79static const struct bond_opt_value bond_mode_tbl[] = { 81static const struct bond_opt_value bond_mode_tbl[] = {
@@ -196,6 +198,12 @@ static const struct bond_opt_value bond_ad_actor_sys_prio_tbl[] = {
196 { NULL, -1, 0}, 198 { NULL, -1, 0},
197}; 199};
198 200
201static const struct bond_opt_value bond_ad_user_port_key_tbl[] = {
202 { "minval", 0, BOND_VALFLAG_MIN | BOND_VALFLAG_DEFAULT},
203 { "maxval", 1023, BOND_VALFLAG_MAX},
204 { NULL, -1, 0},
205};
206
199static const struct bond_option bond_opts[BOND_OPT_LAST] = { 207static const struct bond_option bond_opts[BOND_OPT_LAST] = {
200 [BOND_OPT_MODE] = { 208 [BOND_OPT_MODE] = {
201 .id = BOND_OPT_MODE, 209 .id = BOND_OPT_MODE,
@@ -405,6 +413,14 @@ static const struct bond_option bond_opts[BOND_OPT_LAST] = {
405 .flags = BOND_OPTFLAG_RAWVAL | BOND_OPTFLAG_IFDOWN, 413 .flags = BOND_OPTFLAG_RAWVAL | BOND_OPTFLAG_IFDOWN,
406 .set = bond_option_ad_actor_system_set, 414 .set = bond_option_ad_actor_system_set,
407 }, 415 },
416 [BOND_OPT_AD_USER_PORT_KEY] = {
417 .id = BOND_OPT_AD_USER_PORT_KEY,
418 .name = "ad_user_port_key",
419 .unsuppmodes = BOND_MODE_ALL_EX(BIT(BOND_MODE_8023AD)),
420 .flags = BOND_OPTFLAG_IFDOWN,
421 .values = bond_ad_user_port_key_tbl,
422 .set = bond_option_ad_user_port_key_set,
423 }
408}; 424};
409 425
410/* Searches for an option by name */ 426/* Searches for an option by name */
@@ -1402,3 +1418,13 @@ static int bond_option_ad_actor_system_set(struct bonding *bond,
1402 ether_addr_copy(bond->params.ad_actor_system, macaddr); 1418 ether_addr_copy(bond->params.ad_actor_system, macaddr);
1403 return 0; 1419 return 0;
1404} 1420}
1421
1422static int bond_option_ad_user_port_key_set(struct bonding *bond,
1423 const struct bond_opt_value *newval)
1424{
1425 netdev_info(bond->dev, "Setting ad_user_port_key to (%llu)\n",
1426 newval->value);
1427
1428 bond->params.ad_user_port_key = newval->value;
1429 return 0;
1430}
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c
index 09fefa50d055..143a2abd1c1c 100644
--- a/drivers/net/bonding/bond_sysfs.c
+++ b/drivers/net/bonding/bond_sysfs.c
@@ -721,6 +721,20 @@ static ssize_t bonding_show_ad_actor_system(struct device *d,
721static DEVICE_ATTR(ad_actor_system, S_IRUGO | S_IWUSR, 721static DEVICE_ATTR(ad_actor_system, S_IRUGO | S_IWUSR,
722 bonding_show_ad_actor_system, bonding_sysfs_store_option); 722 bonding_show_ad_actor_system, bonding_sysfs_store_option);
723 723
724static ssize_t bonding_show_ad_user_port_key(struct device *d,
725 struct device_attribute *attr,
726 char *buf)
727{
728 struct bonding *bond = to_bond(d);
729
730 if (BOND_MODE(bond) == BOND_MODE_8023AD)
731 return sprintf(buf, "%hu\n", bond->params.ad_user_port_key);
732
733 return 0;
734}
735static DEVICE_ATTR(ad_user_port_key, S_IRUGO | S_IWUSR,
736 bonding_show_ad_user_port_key, bonding_sysfs_store_option);
737
724static struct attribute *per_bond_attrs[] = { 738static struct attribute *per_bond_attrs[] = {
725 &dev_attr_slaves.attr, 739 &dev_attr_slaves.attr,
726 &dev_attr_mode.attr, 740 &dev_attr_mode.attr,
@@ -756,6 +770,7 @@ static struct attribute *per_bond_attrs[] = {
756 &dev_attr_tlb_dynamic_lb.attr, 770 &dev_attr_tlb_dynamic_lb.attr,
757 &dev_attr_ad_actor_sys_prio.attr, 771 &dev_attr_ad_actor_sys_prio.attr,
758 &dev_attr_ad_actor_system.attr, 772 &dev_attr_ad_actor_system.attr,
773 &dev_attr_ad_user_port_key.attr,
759 NULL, 774 NULL,
760}; 775};
761 776
diff --git a/include/net/bond_options.h b/include/net/bond_options.h
index eeeefa1d3cd8..c28aca25320e 100644
--- a/include/net/bond_options.h
+++ b/include/net/bond_options.h
@@ -65,6 +65,7 @@ enum {
65 BOND_OPT_TLB_DYNAMIC_LB, 65 BOND_OPT_TLB_DYNAMIC_LB,
66 BOND_OPT_AD_ACTOR_SYS_PRIO, 66 BOND_OPT_AD_ACTOR_SYS_PRIO,
67 BOND_OPT_AD_ACTOR_SYSTEM, 67 BOND_OPT_AD_ACTOR_SYSTEM,
68 BOND_OPT_AD_USER_PORT_KEY,
68 BOND_OPT_LAST 69 BOND_OPT_LAST
69}; 70};
70 71
diff --git a/include/net/bonding.h b/include/net/bonding.h
index 650f38693956..20defc0353d1 100644
--- a/include/net/bonding.h
+++ b/include/net/bonding.h
@@ -137,6 +137,7 @@ struct bond_params {
137 int tlb_dynamic_lb; 137 int tlb_dynamic_lb;
138 struct reciprocal_value reciprocal_packets_per_slave; 138 struct reciprocal_value reciprocal_packets_per_slave;
139 u16 ad_actor_sys_prio; 139 u16 ad_actor_sys_prio;
140 u16 ad_user_port_key;
140 u8 ad_actor_system[ETH_ALEN]; 141 u8 ad_actor_system[ETH_ALEN];
141}; 142};
142 143