History

bonding: Add independent control state machine

Add support for the independent control state machine per IEEE 802.1AX-2008 5.4.15 in addition to the existing implementation of the coupled control state machine. Introduces two new states, AD_MUX_COLLECTING and AD_MUX_DISTRIBUTING in the LACP MUX state machine for separated handling of an initial Collecting state before the Collecting and Distributing state. This enables a port to be in a state where it can receive incoming packets while not still distributing. This is useful for reducing packet loss when a port begins distributing before its partner is able to collect. Added new functions such as bond_set_slave_tx_disabled_flags and bond_set_slave_rx_enabled_flags to precisely manage the port's collecting and distributing states. Previously, there was no dedicated method to disable TX while keeping RX enabled, which this patch addresses. Note that the regular flow process in the kernel's bonding driver remains unaffected by this patch. The extension requires explicit opt-in by the user (in order to ensure no disruptions for existing setups) via netlink support using the new bonding parameter coupled_control. The default value for coupled_control is set to 1 so as to preserve existing behaviour.

Aahil Awatramani committed 2 years ago

Commit 240fd401 parent 040067310 files · +234 −8Browse files

Unified · Split

10 files
  1. Documentation/networking/bonding.rst +12 −0
  2. drivers/net/bonding/bond_3ad.c +150 −7
  3. drivers/net/bonding/bond_main.c +1 −0
  4. drivers/net/bonding/bond_netlink.c +16 −0
  5. drivers/net/bonding/bond_options.c +27 −1
  6. include/net/bond_3ad.h +2 −0
  7. include/net/bond_options.h +1 −0
  8. include/net/bonding.h +23 −0
  9. include/uapi/linux/if_link.h +1 −0
  10. tools/include/uapi/linux/if_link.h +1 −0
Documentation/networking/bonding.rst+12−0
@@ -444,6 +444,18 @@ arp_missed_max · 443 unmodified lines
444 444
445 The default value is 2, and the allowable range is 1 - 255.445 The default value is 2, and the allowable range is 1 - 255.
446 446
447coupled_control
448
449 Specifies whether the LACP state machine's MUX in the 802.3ad mode
450 should have separate Collecting and Distributing states.
451
452 This is by implementing the independent control state machine per
453 IEEE 802.1AX-2008 5.4.15 in addition to the existing coupled control
454 state machine.
455
456 The default value is 1. This setting does not separate the Collecting
457 and Distributing states, maintaining the bond in coupled control.
458
447downdelay459downdelay
448 460
449 Specifies the time, in milliseconds, to wait before disabling461 Specifies the time, in milliseconds, to wait before disabling
drivers/net/bonding/bond_3ad.c+150−7
@@ -106,6 +106,9 @@ static void ad_agg_selection_logic(struct aggregator *aggregator, · 105 unmodified lines
106static void ad_clear_agg(struct aggregator *aggregator);106static void ad_clear_agg(struct aggregator *aggregator);
107static void ad_initialize_agg(struct aggregator *aggregator);107static void ad_initialize_agg(struct aggregator *aggregator);
108static void ad_initialize_port(struct port *port, int lacp_fast);108static void ad_initialize_port(struct port *port, int lacp_fast);
109static void ad_enable_collecting(struct port *port);
110static void ad_disable_distributing(struct port *port,
111 bool *update_slave_arr);
109static void ad_enable_collecting_distributing(struct port *port,112static void ad_enable_collecting_distributing(struct port *port,
110 bool *update_slave_arr);113 bool *update_slave_arr);
111static void ad_disable_collecting_distributing(struct port *port,114static void ad_disable_collecting_distributing(struct port *port,
@@ -171,9 +174,38 @@ static inline int __agg_has_partner(struct aggregator *agg) · 59 unmodified lines
171 return !is_zero_ether_addr(agg->partner_system.mac_addr_value);174 return !is_zero_ether_addr(agg->partner_system.mac_addr_value);
172}175}
173 176
177/**
178 * __disable_distributing_port - disable the port's slave for distributing.
179 * Port will still be able to collect.
180 * @port: the port we're looking at
181 *
182 * This will disable only distributing on the port's slave.
183 */
184static void __disable_distributing_port(struct port *port)
185{
186 bond_set_slave_tx_disabled_flags(port->slave, BOND_SLAVE_NOTIFY_LATER);
187}
188
189/**
190 * __enable_collecting_port - enable the port's slave for collecting,
191 * if it's up
192 * @port: the port we're looking at
193 *
194 * This will enable only collecting on the port's slave.
195 */
196static void __enable_collecting_port(struct port *port)
197{
198 struct slave *slave = port->slave;
199
200 if (slave->link == BOND_LINK_UP && bond_slave_is_up(slave))
201 bond_set_slave_rx_enabled_flags(slave, BOND_SLAVE_NOTIFY_LATER);
202}
203
174/**204/**
175 * __disable_port - disable the port's slave205 * __disable_port - disable the port's slave
176 * @port: the port we're looking at206 * @port: the port we're looking at
207 *
208 * This will disable both collecting and distributing on the port's slave.
177 */209 */
178static inline void __disable_port(struct port *port)210static inline void __disable_port(struct port *port)
179{211{
@@ -183,6 +215,8 @@ static inline void __disable_port(struct port *port) · 3 unmodified lines
183/**215/**
184 * __enable_port - enable the port's slave, if it's up216 * __enable_port - enable the port's slave, if it's up
185 * @port: the port we're looking at217 * @port: the port we're looking at
218 *
219 * This will enable both collecting and distributing on the port's slave.
186 */220 */
187static inline void __enable_port(struct port *port)221static inline void __enable_port(struct port *port)
188{222{
@@ -193,10 +227,27 @@ static inline void __enable_port(struct port *port) · 4 unmodified lines
193}227}
194 228
195/**229/**
196 * __port_is_enabled - check if the port's slave is in active state230 * __port_move_to_attached_state - check if port should transition back to attached
231 * state.
232 * @port: the port we're looking at
233 */
234static bool __port_move_to_attached_state(struct port *port)
235{
236 if (!(port->sm_vars & AD_PORT_SELECTED) ||
237 (port->sm_vars & AD_PORT_STANDBY) ||
238 !(port->partner_oper.port_state & LACP_STATE_SYNCHRONIZATION) ||
239 !(port->actor_oper_port_state & LACP_STATE_SYNCHRONIZATION))
240 port->sm_mux_state = AD_MUX_ATTACHED;
241
242 return port->sm_mux_state == AD_MUX_ATTACHED;
243}
244
245/**
246 * __port_is_collecting_distributing - check if the port's slave is in the
247 * combined collecting/distributing state
197 * @port: the port we're looking at248 * @port: the port we're looking at
198 */249 */
199static inline int __port_is_enabled(struct port *port)250static int __port_is_collecting_distributing(struct port *port)
200{251{
201 return bond_is_active_slave(port->slave);252 return bond_is_active_slave(port->slave);
202}253}
@@ -942,6 +993,7 @@ static int ad_marker_send(struct port *port, struct bond_marker *marker) · 739 unmodified lines
942 */993 */
943static void ad_mux_machine(struct port *port, bool *update_slave_arr)994static void ad_mux_machine(struct port *port, bool *update_slave_arr)
944{995{
996 struct bonding *bond = __get_bond_by_port(port);
945 mux_states_t last_state;997 mux_states_t last_state;
946 998
947 /* keep current State Machine state to compare later if it was999 /* keep current State Machine state to compare later if it was
@@ -999,9 +1051,13 @@ static void ad_mux_machine(struct port *port, bool *update_slave_arr) · 51 unmodified lines
999 if ((port->sm_vars & AD_PORT_SELECTED) &&1051 if ((port->sm_vars & AD_PORT_SELECTED) &&
1000 (port->partner_oper.port_state & LACP_STATE_SYNCHRONIZATION) &&1052 (port->partner_oper.port_state & LACP_STATE_SYNCHRONIZATION) &&
1001 !__check_agg_selection_timer(port)) {1053 !__check_agg_selection_timer(port)) {
1002 if (port->aggregator->is_active)1054 if (port->aggregator->is_active) {
1003 port->sm_mux_state =1055 int state = AD_MUX_COLLECTING_DISTRIBUTING;
1004 AD_MUX_COLLECTING_DISTRIBUTING;1056
1057 if (!bond->params.coupled_control)
1058 state = AD_MUX_COLLECTING;
1059 port->sm_mux_state = state;
1060 }
1005 } else if (!(port->sm_vars & AD_PORT_SELECTED) ||1061 } else if (!(port->sm_vars & AD_PORT_SELECTED) ||
1006 (port->sm_vars & AD_PORT_STANDBY)) {1062 (port->sm_vars & AD_PORT_STANDBY)) {
1007 /* if UNSELECTED or STANDBY */1063 /* if UNSELECTED or STANDBY */
@@ -1019,11 +1075,45 @@ static void ad_mux_machine(struct port *port, bool *update_slave_arr) · 11 unmodified lines
1019 }1075 }
1020 break;1076 break;
1021 case AD_MUX_COLLECTING_DISTRIBUTING:1077 case AD_MUX_COLLECTING_DISTRIBUTING:
1078 if (!__port_move_to_attached_state(port)) {
1079 /* if port state hasn't changed make
1080 * sure that a collecting distributing
1081 * port in an active aggregator is enabled
1082 */
1083 if (port->aggregator->is_active &&
1084 !__port_is_collecting_distributing(port)) {
1085 __enable_port(port);
1086 *update_slave_arr = true;
1087 }
1088 }
1089 break;
1090 case AD_MUX_COLLECTING:
1091 if (!__port_move_to_attached_state(port)) {
1092 if ((port->sm_vars & AD_PORT_SELECTED) &&
1093 (port->partner_oper.port_state & LACP_STATE_SYNCHRONIZATION) &&
1094 (port->partner_oper.port_state & LACP_STATE_COLLECTING)) {
1095 port->sm_mux_state = AD_MUX_DISTRIBUTING;
1096 } else {
1097 /* If port state hasn't changed, make sure that a collecting
1098 * port is enabled for an active aggregator.
1099 */
1100 struct slave *slave = port->slave;
1101
1102 if (port->aggregator->is_active &&
1103 bond_is_slave_rx_disabled(slave)) {
1104 ad_enable_collecting(port);
1105 *update_slave_arr = true;
1106 }
1107 }
1108 }
1109 break;
1110 case AD_MUX_DISTRIBUTING:
1022 if (!(port->sm_vars & AD_PORT_SELECTED) ||1111 if (!(port->sm_vars & AD_PORT_SELECTED) ||
1023 (port->sm_vars & AD_PORT_STANDBY) ||1112 (port->sm_vars & AD_PORT_STANDBY) ||
1113 !(port->partner_oper.port_state & LACP_STATE_COLLECTING) ||
1024 !(port->partner_oper.port_state & LACP_STATE_SYNCHRONIZATION) ||1114 !(port->partner_oper.port_state & LACP_STATE_SYNCHRONIZATION) ||
1025 !(port->actor_oper_port_state & LACP_STATE_SYNCHRONIZATION)) {1115 !(port->actor_oper_port_state & LACP_STATE_SYNCHRONIZATION)) {
1026 port->sm_mux_state = AD_MUX_ATTACHED;1116 port->sm_mux_state = AD_MUX_COLLECTING;
1027 } else {1117 } else {
1028 /* if port state hasn't changed make1118 /* if port state hasn't changed make
1029 * sure that a collecting distributing1119 * sure that a collecting distributing
@@ -1031,7 +1121,7 @@ static void ad_mux_machine(struct port *port, bool *update_slave_arr) · 1 unmodified line
1031 */1121 */
1032 if (port->aggregator &&1122 if (port->aggregator &&
1033 port->aggregator->is_active &&1123 port->aggregator->is_active &&
1034 !__port_is_enabled(port)) {1124 !__port_is_collecting_distributing(port)) {
1035 __enable_port(port);1125 __enable_port(port);
1036 *update_slave_arr = true;1126 *update_slave_arr = true;
1037 }1127 }
@@ -1082,6 +1172,20 @@ static void ad_mux_machine(struct port *port, bool *update_slave_arr) · 44 unmodified lines
1082 update_slave_arr);1172 update_slave_arr);
1083 port->ntt = true;1173 port->ntt = true;
1084 break;1174 break;
1175 case AD_MUX_COLLECTING:
1176 port->actor_oper_port_state |= LACP_STATE_COLLECTING;
1177 port->actor_oper_port_state &= ~LACP_STATE_DISTRIBUTING;
1178 port->actor_oper_port_state |= LACP_STATE_SYNCHRONIZATION;
1179 ad_enable_collecting(port);
1180 ad_disable_distributing(port, update_slave_arr);
1181 port->ntt = true;
1182 break;
1183 case AD_MUX_DISTRIBUTING:
1184 port->actor_oper_port_state |= LACP_STATE_DISTRIBUTING;
1185 port->actor_oper_port_state |= LACP_STATE_SYNCHRONIZATION;
1186 ad_enable_collecting_distributing(port,
1187 update_slave_arr);
1188 break;
1085 default:1189 default:
1086 break;1190 break;
1087 }1191 }
@@ -1906,6 +2010,45 @@ static void ad_initialize_port(struct port *port, int lacp_fast) · 818 unmodified lines
1906 }2010 }
1907}2011}
1908 2012
2013/**
2014 * ad_enable_collecting - enable a port's receive
2015 * @port: the port we're looking at
2016 *
2017 * Enable @port if it's in an active aggregator
2018 */
2019static void ad_enable_collecting(struct port *port)
2020{
2021 if (port->aggregator->is_active) {
2022 struct slave *slave = port->slave;
2023
2024 slave_dbg(slave->bond->dev, slave->dev,
2025 "Enabling collecting on port %d (LAG %d)\n",
2026 port->actor_port_number,
2027 port->aggregator->aggregator_identifier);
2028 __enable_collecting_port(port);
2029 }
2030}
2031
2032/**
2033 * ad_disable_distributing - disable a port's transmit
2034 * @port: the port we're looking at
2035 * @update_slave_arr: Does slave array need update?
2036 */
2037static void ad_disable_distributing(struct port *port, bool *update_slave_arr)
2038{
2039 if (port->aggregator &&
2040 !MAC_ADDRESS_EQUAL(&port->aggregator->partner_system,
2041 &(null_mac_addr))) {
2042 slave_dbg(port->slave->bond->dev, port->slave->dev,
2043 "Disabling distributing on port %d (LAG %d)\n",
2044 port->actor_port_number,
2045 port->aggregator->aggregator_identifier);
2046 __disable_distributing_port(port);
2047 /* Slave array needs an update */
2048 *update_slave_arr = true;
2049 }
2050}
2051
1909/**2052/**
1910 * ad_enable_collecting_distributing - enable a port's transmit/receive2053 * ad_enable_collecting_distributing - enable a port's transmit/receive
1911 * @port: the port we're looking at2054 * @port: the port we're looking at
drivers/net/bonding/bond_main.c+1−0
@@ -6306,6 +6306,7 @@ static int __init bond_check_params(struct bond_params *params) · 6305 unmodified lines
6306 params->ad_actor_sys_prio = ad_actor_sys_prio;6306 params->ad_actor_sys_prio = ad_actor_sys_prio;
6307 eth_zero_addr(params->ad_actor_system);6307 eth_zero_addr(params->ad_actor_system);
6308 params->ad_user_port_key = ad_user_port_key;6308 params->ad_user_port_key = ad_user_port_key;
6309 params->coupled_control = 1;
6309 if (packets_per_slave > 0) {6310 if (packets_per_slave > 0) {
6310 params->reciprocal_packets_per_slave =6311 params->reciprocal_packets_per_slave =
6311 reciprocal_value(packets_per_slave);6312 reciprocal_value(packets_per_slave);
drivers/net/bonding/bond_netlink.c+16−0
@@ -122,6 +122,7 @@ static const struct nla_policy bond_policy[IFLA_BOND_MAX + 1] = { · 121 unmodified lines
122 [IFLA_BOND_PEER_NOTIF_DELAY] = NLA_POLICY_FULL_RANGE(NLA_U32, &delay_range),122 [IFLA_BOND_PEER_NOTIF_DELAY] = NLA_POLICY_FULL_RANGE(NLA_U32, &delay_range),
123 [IFLA_BOND_MISSED_MAX] = { .type = NLA_U8 },123 [IFLA_BOND_MISSED_MAX] = { .type = NLA_U8 },
124 [IFLA_BOND_NS_IP6_TARGET] = { .type = NLA_NESTED },124 [IFLA_BOND_NS_IP6_TARGET] = { .type = NLA_NESTED },
125 [IFLA_BOND_COUPLED_CONTROL] = { .type = NLA_U8 },
125};126};
126 127
127static const struct nla_policy bond_slave_policy[IFLA_BOND_SLAVE_MAX + 1] = {128static const struct nla_policy bond_slave_policy[IFLA_BOND_SLAVE_MAX + 1] = {
@@ -549,6 +550,16 @@ static int bond_changelink(struct net_device *bond_dev, struct nlattr *tb[], · 421 unmodified lines
549 return err;550 return err;
550 }551 }
551 552
553 if (data[IFLA_BOND_COUPLED_CONTROL]) {
554 int coupled_control = nla_get_u8(data[IFLA_BOND_COUPLED_CONTROL]);
555
556 bond_opt_initval(&newval, coupled_control);
557 err = __bond_opt_set(bond, BOND_OPT_COUPLED_CONTROL, &newval,
558 data[IFLA_BOND_COUPLED_CONTROL], extack);
559 if (err)
560 return err;
561 }
562
552 return 0;563 return 0;
553}564}
554 565
@@ -615,6 +626,7 @@ static size_t bond_get_size(const struct net_device *bond_dev) · 60 unmodified lines
615 /* IFLA_BOND_NS_IP6_TARGET */626 /* IFLA_BOND_NS_IP6_TARGET */
616 nla_total_size(sizeof(struct nlattr)) +627 nla_total_size(sizeof(struct nlattr)) +
617 nla_total_size(sizeof(struct in6_addr)) * BOND_MAX_NS_TARGETS +628 nla_total_size(sizeof(struct in6_addr)) * BOND_MAX_NS_TARGETS +
629 nla_total_size(sizeof(u8)) + /* IFLA_BOND_COUPLED_CONTROL */
618 0;630 0;
619}631}
620 632
@@ -774,6 +786,10 @@ static int bond_fill_info(struct sk_buff *skb, · 153 unmodified lines
774 bond->params.missed_max))786 bond->params.missed_max))
775 goto nla_put_failure;787 goto nla_put_failure;
776 788
789 if (nla_put_u8(skb, IFLA_BOND_COUPLED_CONTROL,
790 bond->params.coupled_control))
791 goto nla_put_failure;
792
777 if (BOND_MODE(bond) == BOND_MODE_8023AD) {793 if (BOND_MODE(bond) == BOND_MODE_8023AD) {
778 struct ad_info info;794 struct ad_info info;
779 795
drivers/net/bonding/bond_options.c+27−1
@@ -84,7 +84,8 @@ static int bond_option_ad_user_port_key_set(struct bonding *bond, · 83 unmodified lines
84 const struct bond_opt_value *newval);84 const struct bond_opt_value *newval);
85static int bond_option_missed_max_set(struct bonding *bond,85static int bond_option_missed_max_set(struct bonding *bond,
86 const struct bond_opt_value *newval);86 const struct bond_opt_value *newval);
87 87static int bond_option_coupled_control_set(struct bonding *bond,
88 const struct bond_opt_value *newval);
88 89
89static const struct bond_opt_value bond_mode_tbl[] = {90static const struct bond_opt_value bond_mode_tbl[] = {
90 { "balance-rr", BOND_MODE_ROUNDROBIN, BOND_VALFLAG_DEFAULT},91 { "balance-rr", BOND_MODE_ROUNDROBIN, BOND_VALFLAG_DEFAULT},
@@ -232,6 +233,12 @@ static const struct bond_opt_value bond_missed_max_tbl[] = { · 141 unmodified lines
232 { NULL, -1, 0},233 { NULL, -1, 0},
233};234};
234 235
236static const struct bond_opt_value bond_coupled_control_tbl[] = {
237 { "on", 1, BOND_VALFLAG_DEFAULT},
238 { "off", 0, 0},
239 { NULL, -1, 0},
240};
241
235static const struct bond_option bond_opts[BOND_OPT_LAST] = {242static const struct bond_option bond_opts[BOND_OPT_LAST] = {
236 [BOND_OPT_MODE] = {243 [BOND_OPT_MODE] = {
237 .id = BOND_OPT_MODE,244 .id = BOND_OPT_MODE,
@@ -496,6 +503,15 @@ static const struct bond_option bond_opts[BOND_OPT_LAST] = { · 258 unmodified lines
496 .desc = "Delay between each peer notification on failover event, in milliseconds",503 .desc = "Delay between each peer notification on failover event, in milliseconds",
497 .values = bond_peer_notif_delay_tbl,504 .values = bond_peer_notif_delay_tbl,
498 .set = bond_option_peer_notif_delay_set505 .set = bond_option_peer_notif_delay_set
506 },
507 [BOND_OPT_COUPLED_CONTROL] = {
508 .id = BOND_OPT_COUPLED_CONTROL,
509 .name = "coupled_control",
510 .desc = "Opt into using coupled control MUX for LACP states",
511 .unsuppmodes = BOND_MODE_ALL_EX(BIT(BOND_MODE_8023AD)),
512 .flags = BOND_OPTFLAG_IFDOWN,
513 .values = bond_coupled_control_tbl,
514 .set = bond_option_coupled_control_set,
499 }515 }
500};516};
501 517
@@ -1692,3 +1708,13 @@ static int bond_option_ad_user_port_key_set(struct bonding *bond, · 1190 unmodified lines
1692 bond->params.ad_user_port_key = newval->value;1708 bond->params.ad_user_port_key = newval->value;
1693 return 0;1709 return 0;
1694}1710}
1711
1712static int bond_option_coupled_control_set(struct bonding *bond,
1713 const struct bond_opt_value *newval)
1714{
1715 netdev_info(bond->dev, "Setting coupled_control to %s (%llu)\n",
1716 newval->string, newval->value);
1717
1718 bond->params.coupled_control = newval->value;
1719 return 0;
1720}
include/net/bond_3ad.h+2−0
@@ -54,6 +54,8 @@ typedef enum { · 53 unmodified lines
54 AD_MUX_DETACHED, /* mux machine */54 AD_MUX_DETACHED, /* mux machine */
55 AD_MUX_WAITING, /* mux machine */55 AD_MUX_WAITING, /* mux machine */
56 AD_MUX_ATTACHED, /* mux machine */56 AD_MUX_ATTACHED, /* mux machine */
57 AD_MUX_COLLECTING, /* mux machine */
58 AD_MUX_DISTRIBUTING, /* mux machine */
57 AD_MUX_COLLECTING_DISTRIBUTING /* mux machine */59 AD_MUX_COLLECTING_DISTRIBUTING /* mux machine */
58} mux_states_t;60} mux_states_t;
59 61
include/net/bond_options.h+1−0
@@ -76,6 +76,7 @@ enum { · 75 unmodified lines
76 BOND_OPT_MISSED_MAX,76 BOND_OPT_MISSED_MAX,
77 BOND_OPT_NS_TARGETS,77 BOND_OPT_NS_TARGETS,
78 BOND_OPT_PRIO,78 BOND_OPT_PRIO,
79 BOND_OPT_COUPLED_CONTROL,
79 BOND_OPT_LAST80 BOND_OPT_LAST
80};81};
81 82
include/net/bonding.h+23−0
@@ -148,6 +148,7 @@ struct bond_params { · 147 unmodified lines
148#if IS_ENABLED(CONFIG_IPV6)148#if IS_ENABLED(CONFIG_IPV6)
149 struct in6_addr ns_targets[BOND_MAX_NS_TARGETS];149 struct in6_addr ns_targets[BOND_MAX_NS_TARGETS];
150#endif150#endif
151 int coupled_control;
151 152
152 /* 2 bytes of padding : see ether_addr_equal_64bits() */153 /* 2 bytes of padding : see ether_addr_equal_64bits() */
153 u8 ad_actor_system[ETH_ALEN + 2];154 u8 ad_actor_system[ETH_ALEN + 2];
@@ -167,6 +168,7 @@ struct slave { · 13 unmodified lines
167 u8 backup:1, /* indicates backup slave. Value corresponds with168 u8 backup:1, /* indicates backup slave. Value corresponds with
168 BOND_STATE_ACTIVE and BOND_STATE_BACKUP */169 BOND_STATE_ACTIVE and BOND_STATE_BACKUP */
169 inactive:1, /* indicates inactive slave */170 inactive:1, /* indicates inactive slave */
171 rx_disabled:1, /* indicates whether slave's Rx is disabled */
170 should_notify:1, /* indicates whether the state changed */172 should_notify:1, /* indicates whether the state changed */
171 should_notify_link:1; /* indicates whether the link changed */173 should_notify_link:1; /* indicates whether the link changed */
172 u8 duplex;174 u8 duplex;
@@ -568,6 +570,14 @@ static inline void bond_set_slave_inactive_flags(struct slave *slave, · 395 unmodified lines
568 bond_set_slave_state(slave, BOND_STATE_BACKUP, notify);570 bond_set_slave_state(slave, BOND_STATE_BACKUP, notify);
569 if (!slave->bond->params.all_slaves_active)571 if (!slave->bond->params.all_slaves_active)
570 slave->inactive = 1;572 slave->inactive = 1;
573 if (BOND_MODE(slave->bond) == BOND_MODE_8023AD)
574 slave->rx_disabled = 1;
575}
576
577static inline void bond_set_slave_tx_disabled_flags(struct slave *slave,
578 bool notify)
579{
580 bond_set_slave_state(slave, BOND_STATE_BACKUP, notify);
571}581}
572 582
573static inline void bond_set_slave_active_flags(struct slave *slave,583static inline void bond_set_slave_active_flags(struct slave *slave,
@@ -575,6 +585,14 @@ static inline void bond_set_slave_active_flags(struct slave *slave, · 1 unmodified line
575{585{
576 bond_set_slave_state(slave, BOND_STATE_ACTIVE, notify);586 bond_set_slave_state(slave, BOND_STATE_ACTIVE, notify);
577 slave->inactive = 0;587 slave->inactive = 0;
588 if (BOND_MODE(slave->bond) == BOND_MODE_8023AD)
589 slave->rx_disabled = 0;
590}
591
592static inline void bond_set_slave_rx_enabled_flags(struct slave *slave,
593 bool notify)
594{
595 slave->rx_disabled = 0;
578}596}
579 597
580static inline bool bond_is_slave_inactive(struct slave *slave)598static inline bool bond_is_slave_inactive(struct slave *slave)
@@ -582,6 +600,11 @@ static inline bool bond_is_slave_inactive(struct slave *slave) · 1 unmodified line
582 return slave->inactive;600 return slave->inactive;
583}601}
584 602
603static inline bool bond_is_slave_rx_disabled(struct slave *slave)
604{
605 return slave->rx_disabled;
606}
607
585static inline void bond_propose_link_state(struct slave *slave, int state)608static inline void bond_propose_link_state(struct slave *slave, int state)
586{609{
587 slave->link_new_state = state;610 slave->link_new_state = state;
include/uapi/linux/if_link.h+1−0
@@ -1505,6 +1505,7 @@ enum { · 1504 unmodified lines
1505 IFLA_BOND_AD_LACP_ACTIVE,1505 IFLA_BOND_AD_LACP_ACTIVE,
1506 IFLA_BOND_MISSED_MAX,1506 IFLA_BOND_MISSED_MAX,
1507 IFLA_BOND_NS_IP6_TARGET,1507 IFLA_BOND_NS_IP6_TARGET,
1508 IFLA_BOND_COUPLED_CONTROL,
1508 __IFLA_BOND_MAX,1509 __IFLA_BOND_MAX,
1509};1510};
1510 1511
tools/include/uapi/linux/if_link.h+1−0
@@ -974,6 +974,7 @@ enum { · 973 unmodified lines
974 IFLA_BOND_AD_LACP_ACTIVE,974 IFLA_BOND_AD_LACP_ACTIVE,
975 IFLA_BOND_MISSED_MAX,975 IFLA_BOND_MISSED_MAX,
976 IFLA_BOND_NS_IP6_TARGET,976 IFLA_BOND_NS_IP6_TARGET,
977 IFLA_BOND_COUPLED_CONTROL,
977 __IFLA_BOND_MAX,978 __IFLA_BOND_MAX,
978};979};
979 980