diff options
author | Mahesh Bandewar <maheshb@google.com> | 2015-05-09 03:01:57 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-05-11 10:59:32 -0400 |
commit | d22a5fc0c32edcf5c3bb973ee8c9a2606ba500a8 (patch) | |
tree | 8984e73fb65aa74638b517129d35b94891b7e9f6 | |
parent | 74514957552edd4661a4608618121f3c71d4e891 (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.txt | 63 | ||||
-rw-r--r-- | drivers/net/bonding/bond_3ad.c | 14 | ||||
-rw-r--r-- | drivers/net/bonding/bond_main.c | 10 | ||||
-rw-r--r-- | drivers/net/bonding/bond_options.c | 26 | ||||
-rw-r--r-- | drivers/net/bonding/bond_sysfs.c | 15 | ||||
-rw-r--r-- | include/net/bond_options.h | 1 | ||||
-rw-r--r-- | include/net/bonding.h | 1 |
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 | |||
51 | 3.4 Configuring Bonding Manually via Sysfs | 51 | 3.4 Configuring Bonding Manually via Sysfs |
52 | 3.5 Configuration with Interfaces Support | 52 | 3.5 Configuration with Interfaces Support |
53 | 3.6 Overriding Configuration for Special Cases | 53 | 3.6 Overriding Configuration for Special Cases |
54 | 3.7 Configuring LACP for 802.3ad mode in a more secure way | ||
54 | 55 | ||
55 | 4. Querying Bonding Configuration | 56 | 4. Querying Bonding Configuration |
56 | 4.1 Bonding Configuration | 57 | 4.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 | ||
245 | ad_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 | |||
244 | all_slaves_active | 260 | all_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. | |||
1643 | This feature first appeared in bonding driver version 3.7.0 and support for | 1659 | This feature first appeared in bonding driver version 3.7.0 and support for |
1644 | output slave selection was limited to round-robin and active-backup modes. | 1660 | output slave selection was limited to round-robin and active-backup modes. |
1645 | 1661 | ||
1662 | 3.7 Configuring LACP for 802.3ad mode in a more secure way | ||
1663 | ---------------------------------------------------------- | ||
1664 | |||
1665 | When using 802.3ad bonding mode, the Actor (host) and Partner (switch) | ||
1666 | exchange LACPDUs. These LACPDUs cannot be sniffed, because they are | ||
1667 | destined to link local mac addresses (which switches/bridges are not | ||
1668 | supposed to forward). However, most of the values are easily predictable | ||
1669 | or are simply the machine's MAC address (which is trivially known to all | ||
1670 | other hosts in the same L2). This implies that other machines in the L2 | ||
1671 | domain can spoof LACPDU packets from other hosts to the switch and potentially | ||
1672 | cause mayhem by joining (from the point of view of the switch) another | ||
1673 | machine's aggregate, thus receiving a portion of that hosts incoming | ||
1674 | traffic and / or spoofing traffic from that machine themselves (potentially | ||
1675 | even successfully terminating some portion of flows). Though this is not | ||
1676 | a likely scenario, one could avoid this possibility by simply configuring | ||
1677 | few 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 | |||
1646 | 4 Querying Bonding Configuration | 1709 | 4 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); |
75 | static int bond_option_ad_actor_system_set(struct bonding *bond, | 75 | static int bond_option_ad_actor_system_set(struct bonding *bond, |
76 | const struct bond_opt_value *newval); | 76 | const struct bond_opt_value *newval); |
77 | static int bond_option_ad_user_port_key_set(struct bonding *bond, | ||
78 | const struct bond_opt_value *newval); | ||
77 | 79 | ||
78 | 80 | ||
79 | static const struct bond_opt_value bond_mode_tbl[] = { | 81 | static 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 | ||
201 | static 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 | |||
199 | static const struct bond_option bond_opts[BOND_OPT_LAST] = { | 207 | static 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 | |||
1422 | static 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, | |||
721 | static DEVICE_ATTR(ad_actor_system, S_IRUGO | S_IWUSR, | 721 | static 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 | ||
724 | static 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 | } | ||
735 | static DEVICE_ATTR(ad_user_port_key, S_IRUGO | S_IWUSR, | ||
736 | bonding_show_ad_user_port_key, bonding_sysfs_store_option); | ||
737 | |||
724 | static struct attribute *per_bond_attrs[] = { | 738 | static 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 | ||