blob: 2110215f3528fb0cf41c7c188de3821d171e170b [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the Free
6 * Software Foundation; either version 2 of the License, or (at your option)
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc., 59
16 * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 *
18 * The full GNU General Public License is included in this distribution in the
19 * file called LICENSE.
20 *
Linus Torvalds1da177e2005-04-16 15:20:36 -070021 */
22
Linus Torvalds1da177e2005-04-16 15:20:36 -070023#include <linux/skbuff.h>
24#include <linux/if_ether.h>
25#include <linux/netdevice.h>
26#include <linux/spinlock.h>
27#include <linux/ethtool.h>
Jay Vosburghfd989c82008-11-04 17:51:16 -080028#include <linux/etherdevice.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070029#include <linux/if_bonding.h>
30#include <linux/pkt_sched.h>
Eric W. Biedermane730c152007-09-17 11:53:39 -070031#include <net/net_namespace.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070032#include "bonding.h"
33#include "bond_3ad.h"
34
Veaceslav Falico3bf2d282014-01-08 16:46:46 +010035/* General definitions */
Linus Torvalds1da177e2005-04-16 15:20:36 -070036#define AD_SHORT_TIMEOUT 1
37#define AD_LONG_TIMEOUT 0
38#define AD_STANDBY 0x2
39#define AD_MAX_TX_IN_SECOND 3
40#define AD_COLLECTOR_MAX_DELAY 0
41
Veaceslav Falico3bf2d282014-01-08 16:46:46 +010042/* Timer definitions (43.4.4 in the 802.3ad standard) */
Linus Torvalds1da177e2005-04-16 15:20:36 -070043#define AD_FAST_PERIODIC_TIME 1
44#define AD_SLOW_PERIODIC_TIME 30
45#define AD_SHORT_TIMEOUT_TIME (3*AD_FAST_PERIODIC_TIME)
46#define AD_LONG_TIMEOUT_TIME (3*AD_SLOW_PERIODIC_TIME)
47#define AD_CHURN_DETECTION_TIME 60
48#define AD_AGGREGATE_WAIT_TIME 2
49
Veaceslav Falico3bf2d282014-01-08 16:46:46 +010050/* Port state definitions (43.4.2.2 in the 802.3ad standard) */
Linus Torvalds1da177e2005-04-16 15:20:36 -070051#define AD_STATE_LACP_ACTIVITY 0x1
52#define AD_STATE_LACP_TIMEOUT 0x2
53#define AD_STATE_AGGREGATION 0x4
54#define AD_STATE_SYNCHRONIZATION 0x8
55#define AD_STATE_COLLECTING 0x10
56#define AD_STATE_DISTRIBUTING 0x20
57#define AD_STATE_DEFAULTED 0x40
58#define AD_STATE_EXPIRED 0x80
59
Veaceslav Falico3bf2d282014-01-08 16:46:46 +010060/* Port Variables definitions used by the State Machines (43.4.7 in the
61 * 802.3ad standard)
62 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070063#define AD_PORT_BEGIN 0x1
64#define AD_PORT_LACP_ENABLED 0x2
65#define AD_PORT_ACTOR_CHURN 0x4
66#define AD_PORT_PARTNER_CHURN 0x8
67#define AD_PORT_READY 0x10
68#define AD_PORT_READY_N 0x20
69#define AD_PORT_MATCHED 0x40
70#define AD_PORT_STANDBY 0x80
71#define AD_PORT_SELECTED 0x100
72#define AD_PORT_MOVED 0x200
73
Veaceslav Falico3bf2d282014-01-08 16:46:46 +010074/* Port Key definitions
75 * key is determined according to the link speed, duplex and
76 * user key (which is yet not supported)
77 * --------------------------------------------------------------
78 * Port key : | User key | Speed | Duplex |
79 * --------------------------------------------------------------
80 * 16 6 1 0
81 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070082#define AD_DUPLEX_KEY_BITS 0x1
83#define AD_SPEED_KEY_BITS 0x3E
84#define AD_USER_KEY_BITS 0xFFC0
85
Linus Torvalds1da177e2005-04-16 15:20:36 -070086#define AD_LINK_SPEED_BITMASK_1MBPS 0x1
87#define AD_LINK_SPEED_BITMASK_10MBPS 0x2
88#define AD_LINK_SPEED_BITMASK_100MBPS 0x4
89#define AD_LINK_SPEED_BITMASK_1000MBPS 0x8
Jay Vosburgh94dbffd2006-09-22 21:52:15 -070090#define AD_LINK_SPEED_BITMASK_10000MBPS 0x10
Linus Torvalds1da177e2005-04-16 15:20:36 -070091
dingtianhong815117a2014-01-02 09:12:54 +080092/* compare MAC addresses */
93#define MAC_ADDRESS_EQUAL(A, B) \
94 ether_addr_equal_64bits((const u8 *)A, (const u8 *)B)
Linus Torvalds1da177e2005-04-16 15:20:36 -070095
Bandan Das128ea6c2010-10-16 20:19:58 +000096static struct mac_addr null_mac_addr = { { 0, 0, 0, 0, 0, 0 } };
Linus Torvalds1da177e2005-04-16 15:20:36 -070097static u16 ad_ticks_per_sec;
98static const int ad_delta_in_ticks = (AD_TIMER_INTERVAL * HZ) / 1000;
99
Holger Eitzenbergere4ac4322008-12-26 13:40:48 -0800100static const u8 lacpdu_mcast_addr[ETH_ALEN] = MULTICAST_LACPDU_ADDR;
101
Veaceslav Falico3bf2d282014-01-08 16:46:46 +0100102/* ================= main 802.3ad protocol functions ================== */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700103static int ad_lacpdu_send(struct port *port);
Mathieu Desnoyers1c3f0b82007-10-18 23:41:04 -0700104static int ad_marker_send(struct port *port, struct bond_marker *marker);
Mahesh Bandewaree637712014-10-04 17:45:01 -0700105static void ad_mux_machine(struct port *port, bool *update_slave_arr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700106static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port);
107static void ad_tx_machine(struct port *port);
108static void ad_periodic_machine(struct port *port);
Mahesh Bandewaree637712014-10-04 17:45:01 -0700109static void ad_port_selection_logic(struct port *port, bool *update_slave_arr);
110static void ad_agg_selection_logic(struct aggregator *aggregator,
111 bool *update_slave_arr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112static void ad_clear_agg(struct aggregator *aggregator);
113static void ad_initialize_agg(struct aggregator *aggregator);
114static void ad_initialize_port(struct port *port, int lacp_fast);
Mahesh Bandewaree637712014-10-04 17:45:01 -0700115static void ad_enable_collecting_distributing(struct port *port,
116 bool *update_slave_arr);
117static void ad_disable_collecting_distributing(struct port *port,
118 bool *update_slave_arr);
Veaceslav Falico3bf2d282014-01-08 16:46:46 +0100119static void ad_marker_info_received(struct bond_marker *marker_info,
120 struct port *port);
121static void ad_marker_response_received(struct bond_marker *marker,
122 struct port *port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700123
124
Veaceslav Falico3bf2d282014-01-08 16:46:46 +0100125/* ================= api to bonding and kernel code ================== */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126
127/**
128 * __get_bond_by_port - get the port's bonding struct
129 * @port: the port we're looking at
130 *
131 * Return @port's bonding struct, or %NULL if it can't be found.
132 */
133static inline struct bonding *__get_bond_by_port(struct port *port)
134{
Bandan Das7bfc4752010-10-16 20:19:59 +0000135 if (port->slave == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700136 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700137
138 return bond_get_bond_by_slave(port->slave);
139}
140
141/**
Linus Torvalds1da177e2005-04-16 15:20:36 -0700142 * __get_first_agg - get the first aggregator in the bond
143 * @bond: the bond we're looking at
144 *
145 * Return the aggregator of the first slave in @bond, or %NULL if it can't be
146 * found.
Veaceslav Falico768b9542014-01-10 11:59:44 +0100147 * The caller must hold RCU or RTNL lock.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700148 */
149static inline struct aggregator *__get_first_agg(struct port *port)
150{
151 struct bonding *bond = __get_bond_by_port(port);
nikolay@redhat.comdec1e902013-08-01 16:54:47 +0200152 struct slave *first_slave;
Veaceslav Falico768b9542014-01-10 11:59:44 +0100153 struct aggregator *agg;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700154
dingtianhongbe79bd02013-12-13 10:20:12 +0800155 /* If there's no bond for this port, or bond has no slaves */
nikolay@redhat.comdec1e902013-08-01 16:54:47 +0200156 if (bond == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700157 return NULL;
Veaceslav Falico3bf2d282014-01-08 16:46:46 +0100158
dingtianhongbe79bd02013-12-13 10:20:12 +0800159 rcu_read_lock();
160 first_slave = bond_first_slave_rcu(bond);
dingtianhong3fdddd82014-05-12 15:08:43 +0800161 agg = first_slave ? &(SLAVE_AD_INFO(first_slave)->aggregator) : NULL;
dingtianhongbe79bd02013-12-13 10:20:12 +0800162 rcu_read_unlock();
Veaceslav Falico3bf2d282014-01-08 16:46:46 +0100163
Veaceslav Falico768b9542014-01-10 11:59:44 +0100164 return agg;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700165}
166
Veaceslav Falico3bf2d282014-01-08 16:46:46 +0100167/**
168 * __agg_has_partner - see if we have a partner
169 * @agg: the agregator we're looking at
Jay Vosburghfd989c82008-11-04 17:51:16 -0800170 *
171 * Return nonzero if aggregator has a partner (denoted by a non-zero ether
Veaceslav Falico3bf2d282014-01-08 16:46:46 +0100172 * address for the partner). Return 0 if not.
Jay Vosburghfd989c82008-11-04 17:51:16 -0800173 */
174static inline int __agg_has_partner(struct aggregator *agg)
175{
176 return !is_zero_ether_addr(agg->partner_system.mac_addr_value);
177}
178
Linus Torvalds1da177e2005-04-16 15:20:36 -0700179/**
180 * __disable_port - disable the port's slave
181 * @port: the port we're looking at
Linus Torvalds1da177e2005-04-16 15:20:36 -0700182 */
183static inline void __disable_port(struct port *port)
184{
dingtianhong5e5b0662014-02-26 11:05:22 +0800185 bond_set_slave_inactive_flags(port->slave, BOND_SLAVE_NOTIFY_LATER);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700186}
187
188/**
189 * __enable_port - enable the port's slave, if it's up
190 * @port: the port we're looking at
Linus Torvalds1da177e2005-04-16 15:20:36 -0700191 */
192static inline void __enable_port(struct port *port)
193{
194 struct slave *slave = port->slave;
195
Veaceslav Falicob6adc612014-05-15 21:39:57 +0200196 if ((slave->link == BOND_LINK_UP) && bond_slave_is_up(slave))
dingtianhong5e5b0662014-02-26 11:05:22 +0800197 bond_set_slave_active_flags(slave, BOND_SLAVE_NOTIFY_LATER);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700198}
199
200/**
201 * __port_is_enabled - check if the port's slave is in active state
202 * @port: the port we're looking at
Linus Torvalds1da177e2005-04-16 15:20:36 -0700203 */
204static inline int __port_is_enabled(struct port *port)
205{
Jiri Pirkoe30bc062011-03-12 03:14:37 +0000206 return bond_is_active_slave(port->slave);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700207}
208
209/**
210 * __get_agg_selection_mode - get the aggregator selection mode
211 * @port: the port we're looking at
212 *
Jay Vosburghfd989c82008-11-04 17:51:16 -0800213 * Get the aggregator selection mode. Can be %STABLE, %BANDWIDTH or %COUNT.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700214 */
215static inline u32 __get_agg_selection_mode(struct port *port)
216{
217 struct bonding *bond = __get_bond_by_port(port);
218
Bandan Das7bfc4752010-10-16 20:19:59 +0000219 if (bond == NULL)
Jay Vosburghfd989c82008-11-04 17:51:16 -0800220 return BOND_AD_STABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700221
Peter Pan(潘卫平)1a14fbc2011-06-08 21:19:03 +0000222 return bond->params.ad_select;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700223}
224
225/**
226 * __check_agg_selection_timer - check if the selection timer has expired
227 * @port: the port we're looking at
Linus Torvalds1da177e2005-04-16 15:20:36 -0700228 */
229static inline int __check_agg_selection_timer(struct port *port)
230{
231 struct bonding *bond = __get_bond_by_port(port);
232
Bandan Das7bfc4752010-10-16 20:19:59 +0000233 if (bond == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700234 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700235
236 return BOND_AD_INFO(bond).agg_select_timer ? 1 : 0;
237}
238
239/**
Linus Torvalds1da177e2005-04-16 15:20:36 -0700240 * __get_link_speed - get a port's speed
241 * @port: the port we're looking at
242 *
243 * Return @port's speed in 802.3ad bitmask format. i.e. one of:
244 * 0,
245 * %AD_LINK_SPEED_BITMASK_10MBPS,
246 * %AD_LINK_SPEED_BITMASK_100MBPS,
Jay Vosburgh94dbffd2006-09-22 21:52:15 -0700247 * %AD_LINK_SPEED_BITMASK_1000MBPS,
248 * %AD_LINK_SPEED_BITMASK_10000MBPS
Linus Torvalds1da177e2005-04-16 15:20:36 -0700249 */
250static u16 __get_link_speed(struct port *port)
251{
252 struct slave *slave = port->slave;
253 u16 speed;
254
Veaceslav Falico3bf2d282014-01-08 16:46:46 +0100255 /* this if covers only a special case: when the configuration starts
256 * with link down, it sets the speed to 0.
257 * This is done in spite of the fact that the e100 driver reports 0
258 * to be compatible with MVT in the future.
259 */
Bandan Das7bfc4752010-10-16 20:19:59 +0000260 if (slave->link != BOND_LINK_UP)
Bandan Das128ea6c2010-10-16 20:19:58 +0000261 speed = 0;
Bandan Das7bfc4752010-10-16 20:19:59 +0000262 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700263 switch (slave->speed) {
264 case SPEED_10:
265 speed = AD_LINK_SPEED_BITMASK_10MBPS;
266 break;
267
268 case SPEED_100:
269 speed = AD_LINK_SPEED_BITMASK_100MBPS;
270 break;
271
272 case SPEED_1000:
273 speed = AD_LINK_SPEED_BITMASK_1000MBPS;
274 break;
275
Jay Vosburgh94dbffd2006-09-22 21:52:15 -0700276 case SPEED_10000:
277 speed = AD_LINK_SPEED_BITMASK_10000MBPS;
278 break;
279
Linus Torvalds1da177e2005-04-16 15:20:36 -0700280 default:
Veaceslav Falico3bf2d282014-01-08 16:46:46 +0100281 /* unknown speed value from ethtool. shouldn't happen */
282 speed = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700283 break;
284 }
285 }
286
Veaceslav Falicod4471f52014-07-15 19:36:00 +0200287 netdev_dbg(slave->bond->dev, "Port %d Received link speed %d update from adapter\n",
288 port->actor_port_number, speed);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700289 return speed;
290}
291
292/**
293 * __get_duplex - get a port's duplex
294 * @port: the port we're looking at
295 *
296 * Return @port's duplex in 802.3ad bitmask format. i.e.:
297 * 0x01 if in full duplex
298 * 0x00 otherwise
299 */
300static u8 __get_duplex(struct port *port)
301{
302 struct slave *slave = port->slave;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700303 u8 retval;
304
Veaceslav Falico3bf2d282014-01-08 16:46:46 +0100305 /* handling a special case: when the configuration starts with
306 * link down, it sets the duplex to 0.
307 */
Nikolay Aleksandrov547942c2014-09-15 17:19:34 +0200308 if (slave->link != BOND_LINK_UP) {
Bandan Das128ea6c2010-10-16 20:19:58 +0000309 retval = 0x0;
Nikolay Aleksandrov547942c2014-09-15 17:19:34 +0200310 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700311 switch (slave->duplex) {
312 case DUPLEX_FULL:
Bandan Das128ea6c2010-10-16 20:19:58 +0000313 retval = 0x1;
Veaceslav Falicod4471f52014-07-15 19:36:00 +0200314 netdev_dbg(slave->bond->dev, "Port %d Received status full duplex update from adapter\n",
315 port->actor_port_number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700316 break;
317 case DUPLEX_HALF:
318 default:
Bandan Das128ea6c2010-10-16 20:19:58 +0000319 retval = 0x0;
Veaceslav Falicod4471f52014-07-15 19:36:00 +0200320 netdev_dbg(slave->bond->dev, "Port %d Received status NOT full duplex update from adapter\n",
321 port->actor_port_number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700322 break;
323 }
324 }
325 return retval;
326}
327
Veaceslav Falico3bf2d282014-01-08 16:46:46 +0100328/* Conversions */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700329
330/**
331 * __ad_timer_to_ticks - convert a given timer type to AD module ticks
332 * @timer_type: which timer to operate
333 * @par: timer parameter. see below
334 *
335 * If @timer_type is %current_while_timer, @par indicates long/short timer.
336 * If @timer_type is %periodic_timer, @par is one of %FAST_PERIODIC_TIME,
Veaceslav Falico3bf2d282014-01-08 16:46:46 +0100337 * %SLOW_PERIODIC_TIME.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700338 */
339static u16 __ad_timer_to_ticks(u16 timer_type, u16 par)
340{
Bandan Das128ea6c2010-10-16 20:19:58 +0000341 u16 retval = 0; /* to silence the compiler */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700342
343 switch (timer_type) {
Veaceslav Falico3bf2d282014-01-08 16:46:46 +0100344 case AD_CURRENT_WHILE_TIMER: /* for rx machine usage */
Bandan Das7bfc4752010-10-16 20:19:59 +0000345 if (par)
Veaceslav Falico3bf2d282014-01-08 16:46:46 +0100346 retval = (AD_SHORT_TIMEOUT_TIME*ad_ticks_per_sec);
Bandan Das7bfc4752010-10-16 20:19:59 +0000347 else
Veaceslav Falico3bf2d282014-01-08 16:46:46 +0100348 retval = (AD_LONG_TIMEOUT_TIME*ad_ticks_per_sec);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700349 break;
Veaceslav Falico3bf2d282014-01-08 16:46:46 +0100350 case AD_ACTOR_CHURN_TIMER: /* for local churn machine */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700351 retval = (AD_CHURN_DETECTION_TIME*ad_ticks_per_sec);
352 break;
Veaceslav Falico3bf2d282014-01-08 16:46:46 +0100353 case AD_PERIODIC_TIMER: /* for periodic machine */
354 retval = (par*ad_ticks_per_sec); /* long timeout */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700355 break;
Veaceslav Falico3bf2d282014-01-08 16:46:46 +0100356 case AD_PARTNER_CHURN_TIMER: /* for remote churn machine */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700357 retval = (AD_CHURN_DETECTION_TIME*ad_ticks_per_sec);
358 break;
Veaceslav Falico3bf2d282014-01-08 16:46:46 +0100359 case AD_WAIT_WHILE_TIMER: /* for selection machine */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700360 retval = (AD_AGGREGATE_WAIT_TIME*ad_ticks_per_sec);
361 break;
362 }
Veaceslav Falico3bf2d282014-01-08 16:46:46 +0100363
Linus Torvalds1da177e2005-04-16 15:20:36 -0700364 return retval;
365}
366
367
Veaceslav Falico3bf2d282014-01-08 16:46:46 +0100368/* ================= ad_rx_machine helper functions ================== */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700369
370/**
Jay Vosburgh2d6682d2009-11-13 13:13:01 +0000371 * __choose_matched - update a port's matched variable from a received lacpdu
372 * @lacpdu: the lacpdu we've received
373 * @port: the port we're looking at
374 *
375 * Update the value of the matched variable, using parameter values from a
376 * newly received lacpdu. Parameter values for the partner carried in the
377 * received PDU are compared with the corresponding operational parameter
378 * values for the actor. Matched is set to TRUE if all of these parameters
379 * match and the PDU parameter partner_state.aggregation has the same value as
380 * actor_oper_port_state.aggregation and lacp will actively maintain the link
381 * in the aggregation. Matched is also set to TRUE if the value of
382 * actor_state.aggregation in the received PDU is set to FALSE, i.e., indicates
383 * an individual link and lacp will actively maintain the link. Otherwise,
384 * matched is set to FALSE. LACP is considered to be actively maintaining the
385 * link if either the PDU's actor_state.lacp_activity variable is TRUE or both
386 * the actor's actor_oper_port_state.lacp_activity and the PDU's
387 * partner_state.lacp_activity variables are TRUE.
388 *
389 * Note: the AD_PORT_MATCHED "variable" is not specified by 802.3ad; it is
390 * used here to implement the language from 802.3ad 43.4.9 that requires
391 * recordPDU to "match" the LACPDU parameters to the stored values.
392 */
393static void __choose_matched(struct lacpdu *lacpdu, struct port *port)
394{
dingtianhong815117a2014-01-02 09:12:54 +0800395 /* check if all parameters are alike
396 * or this is individual link(aggregation == FALSE)
397 * then update the state machine Matched variable.
398 */
Jay Vosburgh2d6682d2009-11-13 13:13:01 +0000399 if (((ntohs(lacpdu->partner_port) == port->actor_port_number) &&
400 (ntohs(lacpdu->partner_port_priority) == port->actor_port_priority) &&
dingtianhong815117a2014-01-02 09:12:54 +0800401 MAC_ADDRESS_EQUAL(&(lacpdu->partner_system), &(port->actor_system)) &&
Jay Vosburgh2d6682d2009-11-13 13:13:01 +0000402 (ntohs(lacpdu->partner_system_priority) == port->actor_system_priority) &&
403 (ntohs(lacpdu->partner_key) == port->actor_oper_port_key) &&
404 ((lacpdu->partner_state & AD_STATE_AGGREGATION) == (port->actor_oper_port_state & AD_STATE_AGGREGATION))) ||
Jay Vosburgh2d6682d2009-11-13 13:13:01 +0000405 ((lacpdu->actor_state & AD_STATE_AGGREGATION) == 0)
406 ) {
Jay Vosburgh2d6682d2009-11-13 13:13:01 +0000407 port->sm_vars |= AD_PORT_MATCHED;
408 } else {
409 port->sm_vars &= ~AD_PORT_MATCHED;
410 }
411}
412
413/**
Linus Torvalds1da177e2005-04-16 15:20:36 -0700414 * __record_pdu - record parameters from a received lacpdu
415 * @lacpdu: the lacpdu we've received
416 * @port: the port we're looking at
417 *
418 * Record the parameter values for the Actor carried in a received lacpdu as
419 * the current partner operational parameter values and sets
420 * actor_oper_port_state.defaulted to FALSE.
421 */
422static void __record_pdu(struct lacpdu *lacpdu, struct port *port)
423{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700424 if (lacpdu && port) {
Holger Eitzenbergerb99d6ba2008-12-17 19:08:14 -0800425 struct port_params *partner = &port->partner_oper;
426
Jay Vosburgh2d6682d2009-11-13 13:13:01 +0000427 __choose_matched(lacpdu, port);
Veaceslav Falico3bf2d282014-01-08 16:46:46 +0100428 /* record the new parameter values for the partner
429 * operational
430 */
Holger Eitzenbergerb99d6ba2008-12-17 19:08:14 -0800431 partner->port_number = ntohs(lacpdu->actor_port);
432 partner->port_priority = ntohs(lacpdu->actor_port_priority);
433 partner->system = lacpdu->actor_system;
434 partner->system_priority = ntohs(lacpdu->actor_system_priority);
435 partner->key = ntohs(lacpdu->actor_key);
436 partner->port_state = lacpdu->actor_state;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437
Veaceslav Falico3bf2d282014-01-08 16:46:46 +0100438 /* set actor_oper_port_state.defaulted to FALSE */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700439 port->actor_oper_port_state &= ~AD_STATE_DEFAULTED;
440
Veaceslav Falico3bf2d282014-01-08 16:46:46 +0100441 /* set the partner sync. to on if the partner is sync,
442 * and the port is matched
443 */
Bandan Das7bfc4752010-10-16 20:19:59 +0000444 if ((port->sm_vars & AD_PORT_MATCHED)
445 && (lacpdu->actor_state & AD_STATE_SYNCHRONIZATION))
Holger Eitzenbergerb99d6ba2008-12-17 19:08:14 -0800446 partner->port_state |= AD_STATE_SYNCHRONIZATION;
Bandan Das7bfc4752010-10-16 20:19:59 +0000447 else
Holger Eitzenbergerb99d6ba2008-12-17 19:08:14 -0800448 partner->port_state &= ~AD_STATE_SYNCHRONIZATION;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700449 }
450}
451
452/**
453 * __record_default - record default parameters
454 * @port: the port we're looking at
455 *
456 * This function records the default parameter values for the partner carried
457 * in the Partner Admin parameters as the current partner operational parameter
458 * values and sets actor_oper_port_state.defaulted to TRUE.
459 */
460static void __record_default(struct port *port)
461{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700462 if (port) {
Veaceslav Falico3bf2d282014-01-08 16:46:46 +0100463 /* record the partner admin parameters */
Holger Eitzenberger5eefd1a2008-12-17 19:08:46 -0800464 memcpy(&port->partner_oper, &port->partner_admin,
465 sizeof(struct port_params));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700466
Veaceslav Falico3bf2d282014-01-08 16:46:46 +0100467 /* set actor_oper_port_state.defaulted to true */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700468 port->actor_oper_port_state |= AD_STATE_DEFAULTED;
469 }
470}
471
472/**
473 * __update_selected - update a port's Selected variable from a received lacpdu
474 * @lacpdu: the lacpdu we've received
475 * @port: the port we're looking at
476 *
477 * Update the value of the selected variable, using parameter values from a
478 * newly received lacpdu. The parameter values for the Actor carried in the
479 * received PDU are compared with the corresponding operational parameter
480 * values for the ports partner. If one or more of the comparisons shows that
481 * the value(s) received in the PDU differ from the current operational values,
482 * then selected is set to FALSE and actor_oper_port_state.synchronization is
483 * set to out_of_sync. Otherwise, selected remains unchanged.
484 */
485static void __update_selected(struct lacpdu *lacpdu, struct port *port)
486{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700487 if (lacpdu && port) {
Holger Eitzenbergerce6a49a2008-12-17 19:13:07 -0800488 const struct port_params *partner = &port->partner_oper;
489
dingtianhong815117a2014-01-02 09:12:54 +0800490 /* check if any parameter is different then
491 * update the state machine selected variable.
492 */
Joe Perches8e95a202009-12-03 07:58:21 +0000493 if (ntohs(lacpdu->actor_port) != partner->port_number ||
494 ntohs(lacpdu->actor_port_priority) != partner->port_priority ||
dingtianhong815117a2014-01-02 09:12:54 +0800495 !MAC_ADDRESS_EQUAL(&lacpdu->actor_system, &partner->system) ||
Joe Perches8e95a202009-12-03 07:58:21 +0000496 ntohs(lacpdu->actor_system_priority) != partner->system_priority ||
497 ntohs(lacpdu->actor_key) != partner->key ||
498 (lacpdu->actor_state & AD_STATE_AGGREGATION) != (partner->port_state & AD_STATE_AGGREGATION)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700499 port->sm_vars &= ~AD_PORT_SELECTED;
500 }
501 }
502}
503
504/**
505 * __update_default_selected - update a port's Selected variable from Partner
506 * @port: the port we're looking at
507 *
508 * This function updates the value of the selected variable, using the partner
509 * administrative parameter values. The administrative values are compared with
510 * the corresponding operational parameter values for the partner. If one or
511 * more of the comparisons shows that the administrative value(s) differ from
512 * the current operational values, then Selected is set to FALSE and
513 * actor_oper_port_state.synchronization is set to OUT_OF_SYNC. Otherwise,
514 * Selected remains unchanged.
515 */
516static void __update_default_selected(struct port *port)
517{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700518 if (port) {
Holger Eitzenberger3c520652008-12-17 19:13:27 -0800519 const struct port_params *admin = &port->partner_admin;
520 const struct port_params *oper = &port->partner_oper;
521
dingtianhong815117a2014-01-02 09:12:54 +0800522 /* check if any parameter is different then
523 * update the state machine selected variable.
524 */
Joe Perches8e95a202009-12-03 07:58:21 +0000525 if (admin->port_number != oper->port_number ||
526 admin->port_priority != oper->port_priority ||
dingtianhong815117a2014-01-02 09:12:54 +0800527 !MAC_ADDRESS_EQUAL(&admin->system, &oper->system) ||
Joe Perches8e95a202009-12-03 07:58:21 +0000528 admin->system_priority != oper->system_priority ||
529 admin->key != oper->key ||
530 (admin->port_state & AD_STATE_AGGREGATION)
Holger Eitzenberger3c520652008-12-17 19:13:27 -0800531 != (oper->port_state & AD_STATE_AGGREGATION)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700532 port->sm_vars &= ~AD_PORT_SELECTED;
533 }
534 }
535}
536
537/**
Linus Torvalds1da177e2005-04-16 15:20:36 -0700538 * __update_ntt - update a port's ntt variable from a received lacpdu
539 * @lacpdu: the lacpdu we've received
540 * @port: the port we're looking at
541 *
542 * Updates the value of the ntt variable, using parameter values from a newly
543 * received lacpdu. The parameter values for the partner carried in the
544 * received PDU are compared with the corresponding operational parameter
545 * values for the Actor. If one or more of the comparisons shows that the
546 * value(s) received in the PDU differ from the current operational values,
547 * then ntt is set to TRUE. Otherwise, ntt remains unchanged.
548 */
549static void __update_ntt(struct lacpdu *lacpdu, struct port *port)
550{
dingtianhong815117a2014-01-02 09:12:54 +0800551 /* validate lacpdu and port */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700552 if (lacpdu && port) {
dingtianhong815117a2014-01-02 09:12:54 +0800553 /* check if any parameter is different then
554 * update the port->ntt.
555 */
Jay Vosburgh89cc76f2006-09-22 21:55:32 -0700556 if ((ntohs(lacpdu->partner_port) != port->actor_port_number) ||
557 (ntohs(lacpdu->partner_port_priority) != port->actor_port_priority) ||
dingtianhong815117a2014-01-02 09:12:54 +0800558 !MAC_ADDRESS_EQUAL(&(lacpdu->partner_system), &(port->actor_system)) ||
Jay Vosburgh89cc76f2006-09-22 21:55:32 -0700559 (ntohs(lacpdu->partner_system_priority) != port->actor_system_priority) ||
560 (ntohs(lacpdu->partner_key) != port->actor_oper_port_key) ||
Linus Torvalds1da177e2005-04-16 15:20:36 -0700561 ((lacpdu->partner_state & AD_STATE_LACP_ACTIVITY) != (port->actor_oper_port_state & AD_STATE_LACP_ACTIVITY)) ||
562 ((lacpdu->partner_state & AD_STATE_LACP_TIMEOUT) != (port->actor_oper_port_state & AD_STATE_LACP_TIMEOUT)) ||
563 ((lacpdu->partner_state & AD_STATE_SYNCHRONIZATION) != (port->actor_oper_port_state & AD_STATE_SYNCHRONIZATION)) ||
564 ((lacpdu->partner_state & AD_STATE_AGGREGATION) != (port->actor_oper_port_state & AD_STATE_AGGREGATION))
565 ) {
Holger Eitzenbergerd238d452008-12-26 11:18:15 -0800566 port->ntt = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700567 }
568 }
569}
570
571/**
Linus Torvalds1da177e2005-04-16 15:20:36 -0700572 * __agg_ports_are_ready - check if all ports in an aggregator are ready
573 * @aggregator: the aggregator we're looking at
574 *
575 */
576static int __agg_ports_are_ready(struct aggregator *aggregator)
577{
578 struct port *port;
579 int retval = 1;
580
581 if (aggregator) {
Veaceslav Falico3bf2d282014-01-08 16:46:46 +0100582 /* scan all ports in this aggregator to verfy if they are
583 * all ready.
584 */
Bandan Das128ea6c2010-10-16 20:19:58 +0000585 for (port = aggregator->lag_ports;
586 port;
587 port = port->next_port_in_aggregator) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700588 if (!(port->sm_vars & AD_PORT_READY_N)) {
589 retval = 0;
590 break;
591 }
592 }
593 }
594
595 return retval;
596}
597
598/**
599 * __set_agg_ports_ready - set value of Ready bit in all ports of an aggregator
600 * @aggregator: the aggregator we're looking at
601 * @val: Should the ports' ready bit be set on or off
602 *
603 */
604static void __set_agg_ports_ready(struct aggregator *aggregator, int val)
605{
606 struct port *port;
607
Bandan Das128ea6c2010-10-16 20:19:58 +0000608 for (port = aggregator->lag_ports; port;
609 port = port->next_port_in_aggregator) {
Bandan Das7bfc4752010-10-16 20:19:59 +0000610 if (val)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611 port->sm_vars |= AD_PORT_READY;
Bandan Das7bfc4752010-10-16 20:19:59 +0000612 else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700613 port->sm_vars &= ~AD_PORT_READY;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700614 }
615}
616
617/**
618 * __get_agg_bandwidth - get the total bandwidth of an aggregator
619 * @aggregator: the aggregator we're looking at
620 *
621 */
622static u32 __get_agg_bandwidth(struct aggregator *aggregator)
623{
Bandan Das128ea6c2010-10-16 20:19:58 +0000624 u32 bandwidth = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700625
626 if (aggregator->num_of_ports) {
David Decotigny65cce192011-04-13 15:22:30 +0000627 switch (__get_link_speed(aggregator->lag_ports)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700628 case AD_LINK_SPEED_BITMASK_1MBPS:
629 bandwidth = aggregator->num_of_ports;
630 break;
631 case AD_LINK_SPEED_BITMASK_10MBPS:
632 bandwidth = aggregator->num_of_ports * 10;
633 break;
634 case AD_LINK_SPEED_BITMASK_100MBPS:
635 bandwidth = aggregator->num_of_ports * 100;
636 break;
637 case AD_LINK_SPEED_BITMASK_1000MBPS:
638 bandwidth = aggregator->num_of_ports * 1000;
639 break;
Jay Vosburgh94dbffd2006-09-22 21:52:15 -0700640 case AD_LINK_SPEED_BITMASK_10000MBPS:
641 bandwidth = aggregator->num_of_ports * 10000;
642 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700643 default:
Veaceslav Falico3bf2d282014-01-08 16:46:46 +0100644 bandwidth = 0; /* to silence the compiler */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700645 }
646 }
647 return bandwidth;
648}
649
650/**
651 * __get_active_agg - get the current active aggregator
652 * @aggregator: the aggregator we're looking at
Veaceslav Falico49b76242014-01-10 11:59:45 +0100653 *
654 * Caller must hold RCU lock.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700655 */
656static struct aggregator *__get_active_agg(struct aggregator *aggregator)
657{
Veaceslav Falico19177e72013-09-27 16:12:00 +0200658 struct bonding *bond = aggregator->slave->bond;
659 struct list_head *iter;
660 struct slave *slave;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700661
dingtianhongbe79bd02013-12-13 10:20:12 +0800662 bond_for_each_slave_rcu(bond, slave, iter)
dingtianhong3fdddd82014-05-12 15:08:43 +0800663 if (SLAVE_AD_INFO(slave)->aggregator.is_active)
664 return &(SLAVE_AD_INFO(slave)->aggregator);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700665
Veaceslav Falico19177e72013-09-27 16:12:00 +0200666 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700667}
668
669/**
670 * __update_lacpdu_from_port - update a port's lacpdu fields
671 * @port: the port we're looking at
Linus Torvalds1da177e2005-04-16 15:20:36 -0700672 */
673static inline void __update_lacpdu_from_port(struct port *port)
674{
675 struct lacpdu *lacpdu = &port->lacpdu;
Holger Eitzenberger3b5b35d2008-12-17 19:13:53 -0800676 const struct port_params *partner = &port->partner_oper;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700677
Veaceslav Falico3bf2d282014-01-08 16:46:46 +0100678 /* update current actual Actor parameters
679 * lacpdu->subtype initialized
Linus Torvalds1da177e2005-04-16 15:20:36 -0700680 * lacpdu->version_number initialized
681 * lacpdu->tlv_type_actor_info initialized
682 * lacpdu->actor_information_length initialized
683 */
684
Al Virod3bb52b2007-08-22 20:06:58 -0400685 lacpdu->actor_system_priority = htons(port->actor_system_priority);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700686 lacpdu->actor_system = port->actor_system;
Al Virod3bb52b2007-08-22 20:06:58 -0400687 lacpdu->actor_key = htons(port->actor_oper_port_key);
688 lacpdu->actor_port_priority = htons(port->actor_port_priority);
689 lacpdu->actor_port = htons(port->actor_port_number);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700690 lacpdu->actor_state = port->actor_oper_port_state;
691
692 /* lacpdu->reserved_3_1 initialized
693 * lacpdu->tlv_type_partner_info initialized
694 * lacpdu->partner_information_length initialized
695 */
696
Holger Eitzenberger3b5b35d2008-12-17 19:13:53 -0800697 lacpdu->partner_system_priority = htons(partner->system_priority);
698 lacpdu->partner_system = partner->system;
699 lacpdu->partner_key = htons(partner->key);
700 lacpdu->partner_port_priority = htons(partner->port_priority);
701 lacpdu->partner_port = htons(partner->port_number);
702 lacpdu->partner_state = partner->port_state;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700703
704 /* lacpdu->reserved_3_2 initialized
705 * lacpdu->tlv_type_collector_info initialized
706 * lacpdu->collector_information_length initialized
707 * collector_max_delay initialized
708 * reserved_12[12] initialized
709 * tlv_type_terminator initialized
710 * terminator_length initialized
711 * reserved_50[50] initialized
712 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700713}
714
Veaceslav Falico3bf2d282014-01-08 16:46:46 +0100715/* ================= main 802.3ad protocol code ========================= */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700716
717/**
718 * ad_lacpdu_send - send out a lacpdu packet on a given port
719 * @port: the port we're looking at
720 *
721 * Returns: 0 on success
722 * < 0 on error
723 */
724static int ad_lacpdu_send(struct port *port)
725{
726 struct slave *slave = port->slave;
727 struct sk_buff *skb;
728 struct lacpdu_header *lacpdu_header;
729 int length = sizeof(struct lacpdu_header);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700730
731 skb = dev_alloc_skb(length);
Bandan Das7bfc4752010-10-16 20:19:59 +0000732 if (!skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700733 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700734
735 skb->dev = slave->dev;
Arnaldo Carvalho de Melo459a98e2007-03-19 15:30:44 -0700736 skb_reset_mac_header(skb);
Arnaldo Carvalho de Melob0e380b2007-04-10 21:21:55 -0700737 skb->network_header = skb->mac_header + ETH_HLEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700738 skb->protocol = PKT_TYPE_LACPDU;
739 skb->priority = TC_PRIO_CONTROL;
740
741 lacpdu_header = (struct lacpdu_header *)skb_put(skb, length);
742
Joe Perchesada0f862014-02-15 16:02:17 -0800743 ether_addr_copy(lacpdu_header->hdr.h_dest, lacpdu_mcast_addr);
Uwe Kleine-Königb5950762010-11-01 15:38:34 -0400744 /* Note: source address is set to be the member's PERMANENT address,
Veaceslav Falico3bf2d282014-01-08 16:46:46 +0100745 * because we use it to identify loopback lacpdus in receive.
746 */
Joe Perchesada0f862014-02-15 16:02:17 -0800747 ether_addr_copy(lacpdu_header->hdr.h_source, slave->perm_hwaddr);
Holger Eitzenbergere7271492008-12-26 13:41:53 -0800748 lacpdu_header->hdr.h_proto = PKT_TYPE_LACPDU;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700749
Veaceslav Falico3bf2d282014-01-08 16:46:46 +0100750 lacpdu_header->lacpdu = port->lacpdu;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700751
752 dev_queue_xmit(skb);
753
754 return 0;
755}
756
757/**
758 * ad_marker_send - send marker information/response on a given port
759 * @port: the port we're looking at
760 * @marker: marker data to send
761 *
762 * Returns: 0 on success
763 * < 0 on error
764 */
Mathieu Desnoyers1c3f0b82007-10-18 23:41:04 -0700765static int ad_marker_send(struct port *port, struct bond_marker *marker)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700766{
767 struct slave *slave = port->slave;
768 struct sk_buff *skb;
Mathieu Desnoyers1c3f0b82007-10-18 23:41:04 -0700769 struct bond_marker_header *marker_header;
770 int length = sizeof(struct bond_marker_header);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700771
772 skb = dev_alloc_skb(length + 16);
Bandan Das7bfc4752010-10-16 20:19:59 +0000773 if (!skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700774 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700775
776 skb_reserve(skb, 16);
777
778 skb->dev = slave->dev;
Arnaldo Carvalho de Melo459a98e2007-03-19 15:30:44 -0700779 skb_reset_mac_header(skb);
Arnaldo Carvalho de Melob0e380b2007-04-10 21:21:55 -0700780 skb->network_header = skb->mac_header + ETH_HLEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700781 skb->protocol = PKT_TYPE_LACPDU;
782
Mathieu Desnoyers1c3f0b82007-10-18 23:41:04 -0700783 marker_header = (struct bond_marker_header *)skb_put(skb, length);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700784
Joe Perchesada0f862014-02-15 16:02:17 -0800785 ether_addr_copy(marker_header->hdr.h_dest, lacpdu_mcast_addr);
Uwe Kleine-Königb5950762010-11-01 15:38:34 -0400786 /* Note: source address is set to be the member's PERMANENT address,
Veaceslav Falico3bf2d282014-01-08 16:46:46 +0100787 * because we use it to identify loopback MARKERs in receive.
788 */
Joe Perchesada0f862014-02-15 16:02:17 -0800789 ether_addr_copy(marker_header->hdr.h_source, slave->perm_hwaddr);
Holger Eitzenbergere7271492008-12-26 13:41:53 -0800790 marker_header->hdr.h_proto = PKT_TYPE_LACPDU;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700791
Veaceslav Falico3bf2d282014-01-08 16:46:46 +0100792 marker_header->marker = *marker;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700793
794 dev_queue_xmit(skb);
795
796 return 0;
797}
798
799/**
800 * ad_mux_machine - handle a port's mux state machine
801 * @port: the port we're looking at
Mahesh Bandewaree637712014-10-04 17:45:01 -0700802 * @update_slave_arr: Does slave array need update?
Linus Torvalds1da177e2005-04-16 15:20:36 -0700803 */
Mahesh Bandewaree637712014-10-04 17:45:01 -0700804static void ad_mux_machine(struct port *port, bool *update_slave_arr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700805{
806 mux_states_t last_state;
807
Veaceslav Falico3bf2d282014-01-08 16:46:46 +0100808 /* keep current State Machine state to compare later if it was
809 * changed
810 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700811 last_state = port->sm_mux_state;
812
813 if (port->sm_vars & AD_PORT_BEGIN) {
Veaceslav Falico3bf2d282014-01-08 16:46:46 +0100814 port->sm_mux_state = AD_MUX_DETACHED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700815 } else {
816 switch (port->sm_mux_state) {
817 case AD_MUX_DETACHED:
Bandan Das7bfc4752010-10-16 20:19:59 +0000818 if ((port->sm_vars & AD_PORT_SELECTED)
819 || (port->sm_vars & AD_PORT_STANDBY))
820 /* if SELECTED or STANDBY */
Veaceslav Falico3bf2d282014-01-08 16:46:46 +0100821 port->sm_mux_state = AD_MUX_WAITING;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700822 break;
823 case AD_MUX_WAITING:
Veaceslav Falico3bf2d282014-01-08 16:46:46 +0100824 /* if SELECTED == FALSE return to DETACH state */
825 if (!(port->sm_vars & AD_PORT_SELECTED)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700826 port->sm_vars &= ~AD_PORT_READY_N;
Veaceslav Falico3bf2d282014-01-08 16:46:46 +0100827 /* in order to withhold the Selection Logic to
828 * check all ports READY_N value every callback
829 * cycle to update ready variable, we check
830 * READY_N and update READY here
831 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700832 __set_agg_ports_ready(port->aggregator, __agg_ports_are_ready(port->aggregator));
Veaceslav Falico3bf2d282014-01-08 16:46:46 +0100833 port->sm_mux_state = AD_MUX_DETACHED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700834 break;
835 }
836
Veaceslav Falico3bf2d282014-01-08 16:46:46 +0100837 /* check if the wait_while_timer expired */
Bandan Das7bfc4752010-10-16 20:19:59 +0000838 if (port->sm_mux_timer_counter
839 && !(--port->sm_mux_timer_counter))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700840 port->sm_vars |= AD_PORT_READY_N;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700841
Veaceslav Falico3bf2d282014-01-08 16:46:46 +0100842 /* in order to withhold the selection logic to check
843 * all ports READY_N value every callback cycle to
844 * update ready variable, we check READY_N and update
845 * READY here
846 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700847 __set_agg_ports_ready(port->aggregator, __agg_ports_are_ready(port->aggregator));
848
Veaceslav Falico3bf2d282014-01-08 16:46:46 +0100849 /* if the wait_while_timer expired, and the port is
850 * in READY state, move to ATTACHED state
851 */
Bandan Das7bfc4752010-10-16 20:19:59 +0000852 if ((port->sm_vars & AD_PORT_READY)
853 && !port->sm_mux_timer_counter)
Veaceslav Falico3bf2d282014-01-08 16:46:46 +0100854 port->sm_mux_state = AD_MUX_ATTACHED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700855 break;
856 case AD_MUX_ATTACHED:
Veaceslav Falico3bf2d282014-01-08 16:46:46 +0100857 /* check also if agg_select_timer expired (so the
858 * edable port will take place only after this timer)
859 */
860 if ((port->sm_vars & AD_PORT_SELECTED) &&
861 (port->partner_oper.port_state & AD_STATE_SYNCHRONIZATION) &&
862 !__check_agg_selection_timer(port)) {
863 port->sm_mux_state = AD_MUX_COLLECTING_DISTRIBUTING;
864 } else if (!(port->sm_vars & AD_PORT_SELECTED) ||
865 (port->sm_vars & AD_PORT_STANDBY)) {
866 /* if UNSELECTED or STANDBY */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700867 port->sm_vars &= ~AD_PORT_READY_N;
Veaceslav Falico3bf2d282014-01-08 16:46:46 +0100868 /* in order to withhold the selection logic to
869 * check all ports READY_N value every callback
870 * cycle to update ready variable, we check
871 * READY_N and update READY here
872 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700873 __set_agg_ports_ready(port->aggregator, __agg_ports_are_ready(port->aggregator));
Veaceslav Falico3bf2d282014-01-08 16:46:46 +0100874 port->sm_mux_state = AD_MUX_DETACHED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700875 }
876 break;
877 case AD_MUX_COLLECTING_DISTRIBUTING:
Veaceslav Falico3bf2d282014-01-08 16:46:46 +0100878 if (!(port->sm_vars & AD_PORT_SELECTED) ||
879 (port->sm_vars & AD_PORT_STANDBY) ||
880 !(port->partner_oper.port_state & AD_STATE_SYNCHRONIZATION)) {
881 port->sm_mux_state = AD_MUX_ATTACHED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700882 } else {
Veaceslav Falico3bf2d282014-01-08 16:46:46 +0100883 /* if port state hasn't changed make
884 * sure that a collecting distributing
885 * port in an active aggregator is enabled
886 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700887 if (port->aggregator &&
888 port->aggregator->is_active &&
889 !__port_is_enabled(port)) {
890
891 __enable_port(port);
892 }
893 }
894 break;
Veaceslav Falico3bf2d282014-01-08 16:46:46 +0100895 default:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700896 break;
897 }
898 }
899
Veaceslav Falico3bf2d282014-01-08 16:46:46 +0100900 /* check if the state machine was changed */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700901 if (port->sm_mux_state != last_state) {
Joe Perchesa4aee5c2009-12-13 20:06:07 -0800902 pr_debug("Mux Machine: Port=%d, Last State=%d, Curr State=%d\n",
903 port->actor_port_number, last_state,
904 port->sm_mux_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700905 switch (port->sm_mux_state) {
906 case AD_MUX_DETACHED:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700907 port->actor_oper_port_state &= ~AD_STATE_SYNCHRONIZATION;
Mahesh Bandewaree637712014-10-04 17:45:01 -0700908 ad_disable_collecting_distributing(port,
909 update_slave_arr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700910 port->actor_oper_port_state &= ~AD_STATE_COLLECTING;
911 port->actor_oper_port_state &= ~AD_STATE_DISTRIBUTING;
Holger Eitzenbergerd238d452008-12-26 11:18:15 -0800912 port->ntt = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913 break;
914 case AD_MUX_WAITING:
915 port->sm_mux_timer_counter = __ad_timer_to_ticks(AD_WAIT_WHILE_TIMER, 0);
916 break;
917 case AD_MUX_ATTACHED:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700918 port->actor_oper_port_state |= AD_STATE_SYNCHRONIZATION;
919 port->actor_oper_port_state &= ~AD_STATE_COLLECTING;
920 port->actor_oper_port_state &= ~AD_STATE_DISTRIBUTING;
Mahesh Bandewaree637712014-10-04 17:45:01 -0700921 ad_disable_collecting_distributing(port,
922 update_slave_arr);
Holger Eitzenbergerd238d452008-12-26 11:18:15 -0800923 port->ntt = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700924 break;
925 case AD_MUX_COLLECTING_DISTRIBUTING:
926 port->actor_oper_port_state |= AD_STATE_COLLECTING;
927 port->actor_oper_port_state |= AD_STATE_DISTRIBUTING;
Mahesh Bandewaree637712014-10-04 17:45:01 -0700928 ad_enable_collecting_distributing(port,
929 update_slave_arr);
Holger Eitzenbergerd238d452008-12-26 11:18:15 -0800930 port->ntt = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700931 break;
Veaceslav Falico3bf2d282014-01-08 16:46:46 +0100932 default:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700933 break;
934 }
935 }
936}
937
938/**
939 * ad_rx_machine - handle a port's rx State Machine
940 * @lacpdu: the lacpdu we've received
941 * @port: the port we're looking at
942 *
943 * If lacpdu arrived, stop previous timer (if exists) and set the next state as
944 * CURRENT. If timer expired set the state machine in the proper state.
945 * In other cases, this function checks if we need to switch to other state.
946 */
947static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port)
948{
949 rx_states_t last_state;
950
Veaceslav Falico3bf2d282014-01-08 16:46:46 +0100951 /* keep current State Machine state to compare later if it was
952 * changed
953 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700954 last_state = port->sm_rx_state;
955
Veaceslav Falico3bf2d282014-01-08 16:46:46 +0100956 /* check if state machine should change state */
957
958 /* first, check if port was reinitialized */
Bandan Das7bfc4752010-10-16 20:19:59 +0000959 if (port->sm_vars & AD_PORT_BEGIN)
Bandan Das7bfc4752010-10-16 20:19:59 +0000960 port->sm_rx_state = AD_RX_INITIALIZE;
Veaceslav Falico3bf2d282014-01-08 16:46:46 +0100961 /* check if port is not enabled */
Bandan Das7bfc4752010-10-16 20:19:59 +0000962 else if (!(port->sm_vars & AD_PORT_BEGIN)
963 && !port->is_enabled && !(port->sm_vars & AD_PORT_MOVED))
Bandan Das7bfc4752010-10-16 20:19:59 +0000964 port->sm_rx_state = AD_RX_PORT_DISABLED;
Veaceslav Falico3bf2d282014-01-08 16:46:46 +0100965 /* check if new lacpdu arrived */
966 else if (lacpdu && ((port->sm_rx_state == AD_RX_EXPIRED) ||
967 (port->sm_rx_state == AD_RX_DEFAULTED) ||
968 (port->sm_rx_state == AD_RX_CURRENT))) {
969 port->sm_rx_timer_counter = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700970 port->sm_rx_state = AD_RX_CURRENT;
971 } else {
Veaceslav Falico3bf2d282014-01-08 16:46:46 +0100972 /* if timer is on, and if it is expired */
973 if (port->sm_rx_timer_counter &&
974 !(--port->sm_rx_timer_counter)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700975 switch (port->sm_rx_state) {
976 case AD_RX_EXPIRED:
Veaceslav Falico3bf2d282014-01-08 16:46:46 +0100977 port->sm_rx_state = AD_RX_DEFAULTED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700978 break;
979 case AD_RX_CURRENT:
Veaceslav Falico3bf2d282014-01-08 16:46:46 +0100980 port->sm_rx_state = AD_RX_EXPIRED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700981 break;
Veaceslav Falico3bf2d282014-01-08 16:46:46 +0100982 default:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700983 break;
984 }
985 } else {
Veaceslav Falico3bf2d282014-01-08 16:46:46 +0100986 /* if no lacpdu arrived and no timer is on */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700987 switch (port->sm_rx_state) {
988 case AD_RX_PORT_DISABLED:
Bandan Das7bfc4752010-10-16 20:19:59 +0000989 if (port->sm_vars & AD_PORT_MOVED)
Veaceslav Falico3bf2d282014-01-08 16:46:46 +0100990 port->sm_rx_state = AD_RX_INITIALIZE;
Bandan Das7bfc4752010-10-16 20:19:59 +0000991 else if (port->is_enabled
992 && (port->sm_vars
993 & AD_PORT_LACP_ENABLED))
Veaceslav Falico3bf2d282014-01-08 16:46:46 +0100994 port->sm_rx_state = AD_RX_EXPIRED;
Bandan Das7bfc4752010-10-16 20:19:59 +0000995 else if (port->is_enabled
996 && ((port->sm_vars
997 & AD_PORT_LACP_ENABLED) == 0))
Veaceslav Falico3bf2d282014-01-08 16:46:46 +0100998 port->sm_rx_state = AD_RX_LACP_DISABLED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700999 break;
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001000 default:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001001 break;
1002
1003 }
1004 }
1005 }
1006
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001007 /* check if the State machine was changed or new lacpdu arrived */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001008 if ((port->sm_rx_state != last_state) || (lacpdu)) {
Joe Perchesa4aee5c2009-12-13 20:06:07 -08001009 pr_debug("Rx Machine: Port=%d, Last State=%d, Curr State=%d\n",
1010 port->actor_port_number, last_state,
1011 port->sm_rx_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001012 switch (port->sm_rx_state) {
1013 case AD_RX_INITIALIZE:
Bandan Das7bfc4752010-10-16 20:19:59 +00001014 if (!(port->actor_oper_port_key & AD_DUPLEX_KEY_BITS))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001015 port->sm_vars &= ~AD_PORT_LACP_ENABLED;
Bandan Das7bfc4752010-10-16 20:19:59 +00001016 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001017 port->sm_vars |= AD_PORT_LACP_ENABLED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001018 port->sm_vars &= ~AD_PORT_SELECTED;
1019 __record_default(port);
1020 port->actor_oper_port_state &= ~AD_STATE_EXPIRED;
1021 port->sm_vars &= ~AD_PORT_MOVED;
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001022 port->sm_rx_state = AD_RX_PORT_DISABLED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001023
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001024 /* Fall Through */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001025 case AD_RX_PORT_DISABLED:
1026 port->sm_vars &= ~AD_PORT_MATCHED;
1027 break;
1028 case AD_RX_LACP_DISABLED:
1029 port->sm_vars &= ~AD_PORT_SELECTED;
1030 __record_default(port);
Holger Eitzenberger1055c9a2008-12-17 19:07:38 -08001031 port->partner_oper.port_state &= ~AD_STATE_AGGREGATION;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001032 port->sm_vars |= AD_PORT_MATCHED;
1033 port->actor_oper_port_state &= ~AD_STATE_EXPIRED;
1034 break;
1035 case AD_RX_EXPIRED:
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001036 /* Reset of the Synchronization flag (Standard 43.4.12)
1037 * This reset cause to disable this port in the
1038 * COLLECTING_DISTRIBUTING state of the mux machine in
1039 * case of EXPIRED even if LINK_DOWN didn't arrive for
1040 * the port.
1041 */
Holger Eitzenberger1055c9a2008-12-17 19:07:38 -08001042 port->partner_oper.port_state &= ~AD_STATE_SYNCHRONIZATION;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001043 port->sm_vars &= ~AD_PORT_MATCHED;
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001044 port->partner_oper.port_state |= AD_STATE_LACP_ACTIVITY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001045 port->sm_rx_timer_counter = __ad_timer_to_ticks(AD_CURRENT_WHILE_TIMER, (u16)(AD_SHORT_TIMEOUT));
1046 port->actor_oper_port_state |= AD_STATE_EXPIRED;
1047 break;
1048 case AD_RX_DEFAULTED:
1049 __update_default_selected(port);
1050 __record_default(port);
1051 port->sm_vars |= AD_PORT_MATCHED;
1052 port->actor_oper_port_state &= ~AD_STATE_EXPIRED;
1053 break;
1054 case AD_RX_CURRENT:
dingtianhong815117a2014-01-02 09:12:54 +08001055 /* detect loopback situation */
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001056 if (MAC_ADDRESS_EQUAL(&(lacpdu->actor_system),
1057 &(port->actor_system))) {
Veaceslav Falicod4471f52014-07-15 19:36:00 +02001058 netdev_err(port->slave->bond->dev, "An illegal loopback occurred on adapter (%s)\n"
Joe Perches90194262014-02-15 16:01:45 -08001059 "Check the configuration to verify that all adapters are connected to 802.3ad compliant switch ports\n",
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001060 port->slave->dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001061 return;
1062 }
1063 __update_selected(lacpdu, port);
1064 __update_ntt(lacpdu, port);
1065 __record_pdu(lacpdu, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001066 port->sm_rx_timer_counter = __ad_timer_to_ticks(AD_CURRENT_WHILE_TIMER, (u16)(port->actor_oper_port_state & AD_STATE_LACP_TIMEOUT));
1067 port->actor_oper_port_state &= ~AD_STATE_EXPIRED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001068 break;
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001069 default:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001070 break;
1071 }
1072 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001073}
1074
1075/**
1076 * ad_tx_machine - handle a port's tx state machine
1077 * @port: the port we're looking at
Linus Torvalds1da177e2005-04-16 15:20:36 -07001078 */
1079static void ad_tx_machine(struct port *port)
1080{
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001081 /* check if tx timer expired, to verify that we do not send more than
1082 * 3 packets per second
1083 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001084 if (port->sm_tx_timer_counter && !(--port->sm_tx_timer_counter)) {
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001085 /* check if there is something to send */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001086 if (port->ntt && (port->sm_vars & AD_PORT_LACP_ENABLED)) {
1087 __update_lacpdu_from_port(port);
Holger Eitzenbergerd238d452008-12-26 11:18:15 -08001088
Linus Torvalds1da177e2005-04-16 15:20:36 -07001089 if (ad_lacpdu_send(port) >= 0) {
Joe Perchesa4aee5c2009-12-13 20:06:07 -08001090 pr_debug("Sent LACPDU on port %d\n",
1091 port->actor_port_number);
Holger Eitzenbergerd238d452008-12-26 11:18:15 -08001092
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001093 /* mark ntt as false, so it will not be sent
1094 * again until demanded
1095 */
Holger Eitzenbergerd238d452008-12-26 11:18:15 -08001096 port->ntt = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001097 }
1098 }
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001099 /* restart tx timer(to verify that we will not exceed
1100 * AD_MAX_TX_IN_SECOND
1101 */
1102 port->sm_tx_timer_counter = ad_ticks_per_sec/AD_MAX_TX_IN_SECOND;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001103 }
1104}
1105
1106/**
1107 * ad_periodic_machine - handle a port's periodic state machine
1108 * @port: the port we're looking at
1109 *
1110 * Turn ntt flag on priodically to perform periodic transmission of lacpdu's.
1111 */
1112static void ad_periodic_machine(struct port *port)
1113{
1114 periodic_states_t last_state;
1115
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001116 /* keep current state machine state to compare later if it was changed */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001117 last_state = port->sm_periodic_state;
1118
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001119 /* check if port was reinitialized */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001120 if (((port->sm_vars & AD_PORT_BEGIN) || !(port->sm_vars & AD_PORT_LACP_ENABLED) || !port->is_enabled) ||
Holger Eitzenberger1055c9a2008-12-17 19:07:38 -08001121 (!(port->actor_oper_port_state & AD_STATE_LACP_ACTIVITY) && !(port->partner_oper.port_state & AD_STATE_LACP_ACTIVITY))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001122 ) {
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001123 port->sm_periodic_state = AD_NO_PERIODIC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001124 }
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001125 /* check if state machine should change state */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001126 else if (port->sm_periodic_timer_counter) {
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001127 /* check if periodic state machine expired */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001128 if (!(--port->sm_periodic_timer_counter)) {
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001129 /* if expired then do tx */
1130 port->sm_periodic_state = AD_PERIODIC_TX;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001131 } else {
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001132 /* If not expired, check if there is some new timeout
1133 * parameter from the partner state
1134 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001135 switch (port->sm_periodic_state) {
1136 case AD_FAST_PERIODIC:
Bandan Das7bfc4752010-10-16 20:19:59 +00001137 if (!(port->partner_oper.port_state
1138 & AD_STATE_LACP_TIMEOUT))
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001139 port->sm_periodic_state = AD_SLOW_PERIODIC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001140 break;
1141 case AD_SLOW_PERIODIC:
Holger Eitzenberger1055c9a2008-12-17 19:07:38 -08001142 if ((port->partner_oper.port_state & AD_STATE_LACP_TIMEOUT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001143 port->sm_periodic_timer_counter = 0;
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001144 port->sm_periodic_state = AD_PERIODIC_TX;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001145 }
1146 break;
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001147 default:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001148 break;
1149 }
1150 }
1151 } else {
1152 switch (port->sm_periodic_state) {
1153 case AD_NO_PERIODIC:
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001154 port->sm_periodic_state = AD_FAST_PERIODIC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001155 break;
1156 case AD_PERIODIC_TX:
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001157 if (!(port->partner_oper.port_state &
1158 AD_STATE_LACP_TIMEOUT))
1159 port->sm_periodic_state = AD_SLOW_PERIODIC;
Bandan Das7bfc4752010-10-16 20:19:59 +00001160 else
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001161 port->sm_periodic_state = AD_FAST_PERIODIC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001162 break;
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001163 default:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001164 break;
1165 }
1166 }
1167
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001168 /* check if the state machine was changed */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001169 if (port->sm_periodic_state != last_state) {
Joe Perchesa4aee5c2009-12-13 20:06:07 -08001170 pr_debug("Periodic Machine: Port=%d, Last State=%d, Curr State=%d\n",
1171 port->actor_port_number, last_state,
1172 port->sm_periodic_state);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001173 switch (port->sm_periodic_state) {
1174 case AD_NO_PERIODIC:
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001175 port->sm_periodic_timer_counter = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001176 break;
1177 case AD_FAST_PERIODIC:
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001178 /* decrement 1 tick we lost in the PERIODIC_TX cycle */
1179 port->sm_periodic_timer_counter = __ad_timer_to_ticks(AD_PERIODIC_TIMER, (u16)(AD_FAST_PERIODIC_TIME))-1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001180 break;
1181 case AD_SLOW_PERIODIC:
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001182 /* decrement 1 tick we lost in the PERIODIC_TX cycle */
1183 port->sm_periodic_timer_counter = __ad_timer_to_ticks(AD_PERIODIC_TIMER, (u16)(AD_SLOW_PERIODIC_TIME))-1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001184 break;
1185 case AD_PERIODIC_TX:
Holger Eitzenbergerd238d452008-12-26 11:18:15 -08001186 port->ntt = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001187 break;
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001188 default:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001189 break;
1190 }
1191 }
1192}
1193
1194/**
1195 * ad_port_selection_logic - select aggregation groups
1196 * @port: the port we're looking at
Mahesh Bandewaree637712014-10-04 17:45:01 -07001197 * @update_slave_arr: Does slave array need update?
Linus Torvalds1da177e2005-04-16 15:20:36 -07001198 *
1199 * Select aggregation groups, and assign each port for it's aggregetor. The
1200 * selection logic is called in the inititalization (after all the handshkes),
1201 * and after every lacpdu receive (if selected is off).
1202 */
Mahesh Bandewaree637712014-10-04 17:45:01 -07001203static void ad_port_selection_logic(struct port *port, bool *update_slave_arr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001204{
1205 struct aggregator *aggregator, *free_aggregator = NULL, *temp_aggregator;
1206 struct port *last_port = NULL, *curr_port;
Veaceslav Falico3e36bb72013-09-27 16:11:59 +02001207 struct list_head *iter;
1208 struct bonding *bond;
1209 struct slave *slave;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001210 int found = 0;
1211
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001212 /* if the port is already Selected, do nothing */
Bandan Das7bfc4752010-10-16 20:19:59 +00001213 if (port->sm_vars & AD_PORT_SELECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001214 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001215
Veaceslav Falico3e36bb72013-09-27 16:11:59 +02001216 bond = __get_bond_by_port(port);
1217
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001218 /* if the port is connected to other aggregator, detach it */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001219 if (port->aggregator) {
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001220 /* detach the port from its former aggregator */
Bandan Das128ea6c2010-10-16 20:19:58 +00001221 temp_aggregator = port->aggregator;
1222 for (curr_port = temp_aggregator->lag_ports; curr_port;
1223 last_port = curr_port,
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001224 curr_port = curr_port->next_port_in_aggregator) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001225 if (curr_port == port) {
1226 temp_aggregator->num_of_ports--;
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001227 /* if it is the first port attached to the
1228 * aggregator
1229 */
1230 if (!last_port) {
Bandan Das128ea6c2010-10-16 20:19:58 +00001231 temp_aggregator->lag_ports =
1232 port->next_port_in_aggregator;
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001233 } else {
1234 /* not the first port attached to the
1235 * aggregator
1236 */
Bandan Das128ea6c2010-10-16 20:19:58 +00001237 last_port->next_port_in_aggregator =
1238 port->next_port_in_aggregator;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001239 }
1240
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001241 /* clear the port's relations to this
1242 * aggregator
1243 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001244 port->aggregator = NULL;
Bandan Das128ea6c2010-10-16 20:19:58 +00001245 port->next_port_in_aggregator = NULL;
1246 port->actor_port_aggregator_identifier = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001247
Veaceslav Falicod4471f52014-07-15 19:36:00 +02001248 netdev_dbg(bond->dev, "Port %d left LAG %d\n",
1249 port->actor_port_number,
1250 temp_aggregator->aggregator_identifier);
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001251 /* if the aggregator is empty, clear its
1252 * parameters, and set it ready to be attached
1253 */
Bandan Das7bfc4752010-10-16 20:19:59 +00001254 if (!temp_aggregator->lag_ports)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001255 ad_clear_agg(temp_aggregator);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001256 break;
1257 }
1258 }
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001259 if (!curr_port) {
1260 /* meaning: the port was related to an aggregator
1261 * but was not on the aggregator port list
1262 */
Veaceslav Falicod4471f52014-07-15 19:36:00 +02001263 net_warn_ratelimited("%s: Warning: Port %d (on %s) was related to aggregator %d but was not on its port list\n",
1264 port->slave->bond->dev->name,
1265 port->actor_port_number,
1266 port->slave->dev->name,
1267 port->aggregator->aggregator_identifier);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001268 }
1269 }
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001270 /* search on all aggregators for a suitable aggregator for this port */
Veaceslav Falico3e36bb72013-09-27 16:11:59 +02001271 bond_for_each_slave(bond, slave, iter) {
dingtianhong3fdddd82014-05-12 15:08:43 +08001272 aggregator = &(SLAVE_AD_INFO(slave)->aggregator);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001273
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001274 /* keep a free aggregator for later use(if needed) */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001275 if (!aggregator->lag_ports) {
Bandan Das7bfc4752010-10-16 20:19:59 +00001276 if (!free_aggregator)
Bandan Das128ea6c2010-10-16 20:19:58 +00001277 free_aggregator = aggregator;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001278 continue;
1279 }
dingtianhong815117a2014-01-02 09:12:54 +08001280 /* check if current aggregator suits us */
1281 if (((aggregator->actor_oper_aggregator_key == port->actor_oper_port_key) && /* if all parameters match AND */
1282 MAC_ADDRESS_EQUAL(&(aggregator->partner_system), &(port->partner_oper.system)) &&
Holger Eitzenberger1055c9a2008-12-17 19:07:38 -08001283 (aggregator->partner_system_priority == port->partner_oper.system_priority) &&
1284 (aggregator->partner_oper_aggregator_key == port->partner_oper.key)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001285 ) &&
dingtianhong815117a2014-01-02 09:12:54 +08001286 ((!MAC_ADDRESS_EQUAL(&(port->partner_oper.system), &(null_mac_addr)) && /* partner answers */
1287 !aggregator->is_individual) /* but is not individual OR */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001288 )
1289 ) {
dingtianhong815117a2014-01-02 09:12:54 +08001290 /* attach to the founded aggregator */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001291 port->aggregator = aggregator;
Bandan Das128ea6c2010-10-16 20:19:58 +00001292 port->actor_port_aggregator_identifier =
1293 port->aggregator->aggregator_identifier;
1294 port->next_port_in_aggregator = aggregator->lag_ports;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001295 port->aggregator->num_of_ports++;
Bandan Das128ea6c2010-10-16 20:19:58 +00001296 aggregator->lag_ports = port;
Veaceslav Falicod4471f52014-07-15 19:36:00 +02001297 netdev_dbg(bond->dev, "Port %d joined LAG %d(existing LAG)\n",
1298 port->actor_port_number,
1299 port->aggregator->aggregator_identifier);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001300
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001301 /* mark this port as selected */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001302 port->sm_vars |= AD_PORT_SELECTED;
1303 found = 1;
1304 break;
1305 }
1306 }
1307
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001308 /* the port couldn't find an aggregator - attach it to a new
1309 * aggregator
1310 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001311 if (!found) {
1312 if (free_aggregator) {
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001313 /* assign port a new aggregator */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001314 port->aggregator = free_aggregator;
Bandan Das128ea6c2010-10-16 20:19:58 +00001315 port->actor_port_aggregator_identifier =
1316 port->aggregator->aggregator_identifier;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001317
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001318 /* update the new aggregator's parameters
1319 * if port was responsed from the end-user
1320 */
Bandan Das7bfc4752010-10-16 20:19:59 +00001321 if (port->actor_oper_port_key & AD_DUPLEX_KEY_BITS)
1322 /* if port is full duplex */
Holger Eitzenberger1624db72008-12-26 13:27:21 -08001323 port->aggregator->is_individual = false;
Bandan Das7bfc4752010-10-16 20:19:59 +00001324 else
Holger Eitzenberger1624db72008-12-26 13:27:21 -08001325 port->aggregator->is_individual = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001326
1327 port->aggregator->actor_admin_aggregator_key = port->actor_admin_port_key;
1328 port->aggregator->actor_oper_aggregator_key = port->actor_oper_port_key;
Bandan Das128ea6c2010-10-16 20:19:58 +00001329 port->aggregator->partner_system =
1330 port->partner_oper.system;
1331 port->aggregator->partner_system_priority =
1332 port->partner_oper.system_priority;
Holger Eitzenberger1055c9a2008-12-17 19:07:38 -08001333 port->aggregator->partner_oper_aggregator_key = port->partner_oper.key;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001334 port->aggregator->receive_state = 1;
1335 port->aggregator->transmit_state = 1;
1336 port->aggregator->lag_ports = port;
1337 port->aggregator->num_of_ports++;
1338
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001339 /* mark this port as selected */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001340 port->sm_vars |= AD_PORT_SELECTED;
1341
Veaceslav Falicod4471f52014-07-15 19:36:00 +02001342 netdev_dbg(bond->dev, "Port %d joined LAG %d(new LAG)\n",
1343 port->actor_port_number,
1344 port->aggregator->aggregator_identifier);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001345 } else {
Veaceslav Falicod4471f52014-07-15 19:36:00 +02001346 netdev_err(bond->dev, "Port %d (on %s) did not find a suitable aggregator\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001347 port->actor_port_number, port->slave->dev->name);
1348 }
1349 }
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001350 /* if all aggregator's ports are READY_N == TRUE, set ready=TRUE
1351 * in all aggregator's ports, else set ready=FALSE in all
1352 * aggregator's ports
1353 */
1354 __set_agg_ports_ready(port->aggregator,
1355 __agg_ports_are_ready(port->aggregator));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001356
Jay Vosburghfd989c82008-11-04 17:51:16 -08001357 aggregator = __get_first_agg(port);
Mahesh Bandewaree637712014-10-04 17:45:01 -07001358 ad_agg_selection_logic(aggregator, update_slave_arr);
Jay Vosburghfd989c82008-11-04 17:51:16 -08001359}
1360
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001361/* Decide if "agg" is a better choice for the new active aggregator that
Jay Vosburghfd989c82008-11-04 17:51:16 -08001362 * the current best, according to the ad_select policy.
1363 */
1364static struct aggregator *ad_agg_selection_test(struct aggregator *best,
1365 struct aggregator *curr)
1366{
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001367 /* 0. If no best, select current.
Jay Vosburghfd989c82008-11-04 17:51:16 -08001368 *
1369 * 1. If the current agg is not individual, and the best is
1370 * individual, select current.
1371 *
1372 * 2. If current agg is individual and the best is not, keep best.
1373 *
1374 * 3. Therefore, current and best are both individual or both not
1375 * individual, so:
1376 *
1377 * 3a. If current agg partner replied, and best agg partner did not,
1378 * select current.
1379 *
1380 * 3b. If current agg partner did not reply and best agg partner
1381 * did reply, keep best.
1382 *
1383 * 4. Therefore, current and best both have partner replies or
1384 * both do not, so perform selection policy:
1385 *
1386 * BOND_AD_COUNT: Select by count of ports. If count is equal,
1387 * select by bandwidth.
1388 *
1389 * BOND_AD_STABLE, BOND_AD_BANDWIDTH: Select by bandwidth.
1390 */
1391 if (!best)
1392 return curr;
1393
1394 if (!curr->is_individual && best->is_individual)
1395 return curr;
1396
1397 if (curr->is_individual && !best->is_individual)
1398 return best;
1399
1400 if (__agg_has_partner(curr) && !__agg_has_partner(best))
1401 return curr;
1402
1403 if (!__agg_has_partner(curr) && __agg_has_partner(best))
1404 return best;
1405
1406 switch (__get_agg_selection_mode(curr->lag_ports)) {
1407 case BOND_AD_COUNT:
1408 if (curr->num_of_ports > best->num_of_ports)
1409 return curr;
1410
1411 if (curr->num_of_ports < best->num_of_ports)
1412 return best;
1413
1414 /*FALLTHROUGH*/
1415 case BOND_AD_STABLE:
1416 case BOND_AD_BANDWIDTH:
1417 if (__get_agg_bandwidth(curr) > __get_agg_bandwidth(best))
1418 return curr;
1419
1420 break;
1421
1422 default:
Veaceslav Falicod4471f52014-07-15 19:36:00 +02001423 net_warn_ratelimited("%s: Impossible agg select mode %d\n",
1424 curr->slave->bond->dev->name,
1425 __get_agg_selection_mode(curr->lag_ports));
Jay Vosburghfd989c82008-11-04 17:51:16 -08001426 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001427 }
Jay Vosburghfd989c82008-11-04 17:51:16 -08001428
1429 return best;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001430}
1431
Stephen Hemminger4cd6fe12009-05-15 08:44:32 +00001432static int agg_device_up(const struct aggregator *agg)
1433{
Jiri Bohac2430af82011-04-19 02:09:55 +00001434 struct port *port = agg->lag_ports;
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001435
Jiri Bohac2430af82011-04-19 02:09:55 +00001436 if (!port)
1437 return 0;
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001438
1439 return netif_running(port->slave->dev) &&
1440 netif_carrier_ok(port->slave->dev);
Stephen Hemminger4cd6fe12009-05-15 08:44:32 +00001441}
1442
Linus Torvalds1da177e2005-04-16 15:20:36 -07001443/**
1444 * ad_agg_selection_logic - select an aggregation group for a team
1445 * @aggregator: the aggregator we're looking at
Mahesh Bandewaree637712014-10-04 17:45:01 -07001446 * @update_slave_arr: Does slave array need update?
Linus Torvalds1da177e2005-04-16 15:20:36 -07001447 *
1448 * It is assumed that only one aggregator may be selected for a team.
Jay Vosburghfd989c82008-11-04 17:51:16 -08001449 *
1450 * The logic of this function is to select the aggregator according to
1451 * the ad_select policy:
1452 *
1453 * BOND_AD_STABLE: select the aggregator with the most ports attached to
1454 * it, and to reselect the active aggregator only if the previous
1455 * aggregator has no more ports related to it.
1456 *
1457 * BOND_AD_BANDWIDTH: select the aggregator with the highest total
1458 * bandwidth, and reselect whenever a link state change takes place or the
1459 * set of slaves in the bond changes.
1460 *
1461 * BOND_AD_COUNT: select the aggregator with largest number of ports
1462 * (slaves), and reselect whenever a link state change takes place or the
1463 * set of slaves in the bond changes.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001464 *
1465 * FIXME: this function MUST be called with the first agg in the bond, or
1466 * __get_active_agg() won't work correctly. This function should be better
1467 * called with the bond itself, and retrieve the first agg from it.
1468 */
Mahesh Bandewaree637712014-10-04 17:45:01 -07001469static void ad_agg_selection_logic(struct aggregator *agg,
1470 bool *update_slave_arr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001471{
Jay Vosburghfd989c82008-11-04 17:51:16 -08001472 struct aggregator *best, *active, *origin;
Veaceslav Falicobef1fcc2013-09-27 16:12:01 +02001473 struct bonding *bond = agg->slave->bond;
1474 struct list_head *iter;
1475 struct slave *slave;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001476 struct port *port;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001477
Veaceslav Falico49b76242014-01-10 11:59:45 +01001478 rcu_read_lock();
Jay Vosburghfd989c82008-11-04 17:51:16 -08001479 origin = agg;
Jay Vosburghfd989c82008-11-04 17:51:16 -08001480 active = __get_active_agg(agg);
Stephen Hemminger4cd6fe12009-05-15 08:44:32 +00001481 best = (active && agg_device_up(active)) ? active : NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001482
dingtianhongbe79bd02013-12-13 10:20:12 +08001483 bond_for_each_slave_rcu(bond, slave, iter) {
dingtianhong3fdddd82014-05-12 15:08:43 +08001484 agg = &(SLAVE_AD_INFO(slave)->aggregator);
Veaceslav Falicobef1fcc2013-09-27 16:12:01 +02001485
Jay Vosburghfd989c82008-11-04 17:51:16 -08001486 agg->is_active = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001487
Stephen Hemminger4cd6fe12009-05-15 08:44:32 +00001488 if (agg->num_of_ports && agg_device_up(agg))
Jay Vosburghfd989c82008-11-04 17:51:16 -08001489 best = ad_agg_selection_test(best, agg);
Veaceslav Falicobef1fcc2013-09-27 16:12:01 +02001490 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001491
Jay Vosburghfd989c82008-11-04 17:51:16 -08001492 if (best &&
1493 __get_agg_selection_mode(best->lag_ports) == BOND_AD_STABLE) {
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001494 /* For the STABLE policy, don't replace the old active
Jay Vosburghfd989c82008-11-04 17:51:16 -08001495 * aggregator if it's still active (it has an answering
1496 * partner) or if both the best and active don't have an
1497 * answering partner.
1498 */
1499 if (active && active->lag_ports &&
1500 active->lag_ports->is_enabled &&
1501 (__agg_has_partner(active) ||
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001502 (!__agg_has_partner(active) &&
1503 !__agg_has_partner(best)))) {
Jay Vosburghfd989c82008-11-04 17:51:16 -08001504 if (!(!active->actor_oper_aggregator_key &&
1505 best->actor_oper_aggregator_key)) {
1506 best = NULL;
1507 active->is_active = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001508 }
1509 }
1510 }
1511
Jay Vosburghfd989c82008-11-04 17:51:16 -08001512 if (best && (best == active)) {
1513 best = NULL;
1514 active->is_active = 1;
1515 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001516
dingtianhongbe79bd02013-12-13 10:20:12 +08001517 /* if there is new best aggregator, activate it */
Jay Vosburghfd989c82008-11-04 17:51:16 -08001518 if (best) {
Veaceslav Falicod4471f52014-07-15 19:36:00 +02001519 netdev_dbg(bond->dev, "best Agg=%d; P=%d; a k=%d; p k=%d; Ind=%d; Act=%d\n",
1520 best->aggregator_identifier, best->num_of_ports,
1521 best->actor_oper_aggregator_key,
1522 best->partner_oper_aggregator_key,
1523 best->is_individual, best->is_active);
1524 netdev_dbg(bond->dev, "best ports %p slave %p %s\n",
1525 best->lag_ports, best->slave,
1526 best->slave ? best->slave->dev->name : "NULL");
Jay Vosburghfd989c82008-11-04 17:51:16 -08001527
dingtianhongbe79bd02013-12-13 10:20:12 +08001528 bond_for_each_slave_rcu(bond, slave, iter) {
dingtianhong3fdddd82014-05-12 15:08:43 +08001529 agg = &(SLAVE_AD_INFO(slave)->aggregator);
Jay Vosburghfd989c82008-11-04 17:51:16 -08001530
Veaceslav Falicod4471f52014-07-15 19:36:00 +02001531 netdev_dbg(bond->dev, "Agg=%d; P=%d; a k=%d; p k=%d; Ind=%d; Act=%d\n",
1532 agg->aggregator_identifier, agg->num_of_ports,
1533 agg->actor_oper_aggregator_key,
1534 agg->partner_oper_aggregator_key,
1535 agg->is_individual, agg->is_active);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001536 }
1537
dingtianhongbe79bd02013-12-13 10:20:12 +08001538 /* check if any partner replys */
Jay Vosburghfd989c82008-11-04 17:51:16 -08001539 if (best->is_individual) {
Veaceslav Falicod4471f52014-07-15 19:36:00 +02001540 net_warn_ratelimited("%s: Warning: No 802.3ad response from the link partner for any adapters in the bond\n",
1541 best->slave ?
1542 best->slave->bond->dev->name : "NULL");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001543 }
1544
Jay Vosburghfd989c82008-11-04 17:51:16 -08001545 best->is_active = 1;
Veaceslav Falicod4471f52014-07-15 19:36:00 +02001546 netdev_dbg(bond->dev, "LAG %d chosen as the active LAG\n",
1547 best->aggregator_identifier);
1548 netdev_dbg(bond->dev, "Agg=%d; P=%d; a k=%d; p k=%d; Ind=%d; Act=%d\n",
1549 best->aggregator_identifier, best->num_of_ports,
1550 best->actor_oper_aggregator_key,
1551 best->partner_oper_aggregator_key,
1552 best->is_individual, best->is_active);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001553
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001554 /* disable the ports that were related to the former
1555 * active_aggregator
1556 */
Jay Vosburghfd989c82008-11-04 17:51:16 -08001557 if (active) {
1558 for (port = active->lag_ports; port;
1559 port = port->next_port_in_aggregator) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001560 __disable_port(port);
1561 }
1562 }
Mahesh Bandewaree637712014-10-04 17:45:01 -07001563 /* Slave array needs update. */
1564 *update_slave_arr = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001565 }
1566
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001567 /* if the selected aggregator is of join individuals
Jay Vosburghfd989c82008-11-04 17:51:16 -08001568 * (partner_system is NULL), enable their ports
1569 */
1570 active = __get_active_agg(origin);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001571
Jay Vosburghfd989c82008-11-04 17:51:16 -08001572 if (active) {
1573 if (!__agg_has_partner(active)) {
1574 for (port = active->lag_ports; port;
1575 port = port->next_port_in_aggregator) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001576 __enable_port(port);
1577 }
1578 }
1579 }
Jay Vosburghfd989c82008-11-04 17:51:16 -08001580
dingtianhongbe79bd02013-12-13 10:20:12 +08001581 rcu_read_unlock();
1582
Veaceslav Falicobef1fcc2013-09-27 16:12:01 +02001583 bond_3ad_set_carrier(bond);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001584}
1585
1586/**
1587 * ad_clear_agg - clear a given aggregator's parameters
1588 * @aggregator: the aggregator we're looking at
Linus Torvalds1da177e2005-04-16 15:20:36 -07001589 */
1590static void ad_clear_agg(struct aggregator *aggregator)
1591{
1592 if (aggregator) {
Holger Eitzenberger1624db72008-12-26 13:27:21 -08001593 aggregator->is_individual = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001594 aggregator->actor_admin_aggregator_key = 0;
1595 aggregator->actor_oper_aggregator_key = 0;
1596 aggregator->partner_system = null_mac_addr;
1597 aggregator->partner_system_priority = 0;
1598 aggregator->partner_oper_aggregator_key = 0;
1599 aggregator->receive_state = 0;
1600 aggregator->transmit_state = 0;
1601 aggregator->lag_ports = NULL;
1602 aggregator->is_active = 0;
1603 aggregator->num_of_ports = 0;
Joe Perchesa4aee5c2009-12-13 20:06:07 -08001604 pr_debug("LAG %d was cleared\n",
1605 aggregator->aggregator_identifier);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001606 }
1607}
1608
1609/**
1610 * ad_initialize_agg - initialize a given aggregator's parameters
1611 * @aggregator: the aggregator we're looking at
Linus Torvalds1da177e2005-04-16 15:20:36 -07001612 */
1613static void ad_initialize_agg(struct aggregator *aggregator)
1614{
1615 if (aggregator) {
1616 ad_clear_agg(aggregator);
1617
1618 aggregator->aggregator_mac_address = null_mac_addr;
1619 aggregator->aggregator_identifier = 0;
1620 aggregator->slave = NULL;
1621 }
1622}
1623
1624/**
1625 * ad_initialize_port - initialize a given port's parameters
1626 * @aggregator: the aggregator we're looking at
1627 * @lacp_fast: boolean. whether fast periodic should be used
Linus Torvalds1da177e2005-04-16 15:20:36 -07001628 */
1629static void ad_initialize_port(struct port *port, int lacp_fast)
1630{
Holger Eitzenbergerc7e703d2008-12-17 19:12:07 -08001631 static const struct port_params tmpl = {
1632 .system_priority = 0xffff,
1633 .key = 1,
1634 .port_number = 1,
1635 .port_priority = 0xff,
1636 .port_state = 1,
1637 };
Holger Eitzenberger7addeef2008-12-26 13:28:33 -08001638 static const struct lacpdu lacpdu = {
1639 .subtype = 0x01,
1640 .version_number = 0x01,
1641 .tlv_type_actor_info = 0x01,
1642 .actor_information_length = 0x14,
1643 .tlv_type_partner_info = 0x02,
1644 .partner_information_length = 0x14,
1645 .tlv_type_collector_info = 0x03,
1646 .collector_information_length = 0x10,
1647 .collector_max_delay = htons(AD_COLLECTOR_MAX_DELAY),
1648 };
Holger Eitzenbergerc7e703d2008-12-17 19:12:07 -08001649
Linus Torvalds1da177e2005-04-16 15:20:36 -07001650 if (port) {
1651 port->actor_port_number = 1;
1652 port->actor_port_priority = 0xff;
1653 port->actor_system = null_mac_addr;
1654 port->actor_system_priority = 0xffff;
1655 port->actor_port_aggregator_identifier = 0;
Holger Eitzenbergerd238d452008-12-26 11:18:15 -08001656 port->ntt = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001657 port->actor_admin_port_key = 1;
1658 port->actor_oper_port_key = 1;
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001659 port->actor_admin_port_state = AD_STATE_AGGREGATION |
1660 AD_STATE_LACP_ACTIVITY;
1661 port->actor_oper_port_state = AD_STATE_AGGREGATION |
1662 AD_STATE_LACP_ACTIVITY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001663
Bandan Das7bfc4752010-10-16 20:19:59 +00001664 if (lacp_fast)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001665 port->actor_oper_port_state |= AD_STATE_LACP_TIMEOUT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001666
Holger Eitzenbergerc7e703d2008-12-17 19:12:07 -08001667 memcpy(&port->partner_admin, &tmpl, sizeof(tmpl));
1668 memcpy(&port->partner_oper, &tmpl, sizeof(tmpl));
1669
Holger Eitzenbergerf48127b2008-12-26 13:26:54 -08001670 port->is_enabled = true;
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001671 /* private parameters */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001672 port->sm_vars = 0x3;
1673 port->sm_rx_state = 0;
1674 port->sm_rx_timer_counter = 0;
1675 port->sm_periodic_state = 0;
1676 port->sm_periodic_timer_counter = 0;
1677 port->sm_mux_state = 0;
1678 port->sm_mux_timer_counter = 0;
1679 port->sm_tx_state = 0;
1680 port->sm_tx_timer_counter = 0;
1681 port->slave = NULL;
1682 port->aggregator = NULL;
1683 port->next_port_in_aggregator = NULL;
1684 port->transaction_id = 0;
1685
Holger Eitzenberger7addeef2008-12-26 13:28:33 -08001686 memcpy(&port->lacpdu, &lacpdu, sizeof(lacpdu));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001687 }
1688}
1689
1690/**
1691 * ad_enable_collecting_distributing - enable a port's transmit/receive
1692 * @port: the port we're looking at
Mahesh Bandewaree637712014-10-04 17:45:01 -07001693 * @update_slave_arr: Does slave array need update?
Linus Torvalds1da177e2005-04-16 15:20:36 -07001694 *
1695 * Enable @port if it's in an active aggregator
1696 */
Mahesh Bandewaree637712014-10-04 17:45:01 -07001697static void ad_enable_collecting_distributing(struct port *port,
1698 bool *update_slave_arr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001699{
1700 if (port->aggregator->is_active) {
Joe Perchesa4aee5c2009-12-13 20:06:07 -08001701 pr_debug("Enabling port %d(LAG %d)\n",
1702 port->actor_port_number,
1703 port->aggregator->aggregator_identifier);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001704 __enable_port(port);
Mahesh Bandewaree637712014-10-04 17:45:01 -07001705 /* Slave array needs update */
1706 *update_slave_arr = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001707 }
1708}
1709
1710/**
1711 * ad_disable_collecting_distributing - disable a port's transmit/receive
1712 * @port: the port we're looking at
Mahesh Bandewaree637712014-10-04 17:45:01 -07001713 * @update_slave_arr: Does slave array need update?
Linus Torvalds1da177e2005-04-16 15:20:36 -07001714 */
Mahesh Bandewaree637712014-10-04 17:45:01 -07001715static void ad_disable_collecting_distributing(struct port *port,
1716 bool *update_slave_arr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001717{
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001718 if (port->aggregator &&
1719 !MAC_ADDRESS_EQUAL(&(port->aggregator->partner_system),
1720 &(null_mac_addr))) {
Joe Perchesa4aee5c2009-12-13 20:06:07 -08001721 pr_debug("Disabling port %d(LAG %d)\n",
1722 port->actor_port_number,
1723 port->aggregator->aggregator_identifier);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001724 __disable_port(port);
Mahesh Bandewaree637712014-10-04 17:45:01 -07001725 /* Slave array needs an update */
1726 *update_slave_arr = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001727 }
1728}
1729
Linus Torvalds1da177e2005-04-16 15:20:36 -07001730/**
1731 * ad_marker_info_received - handle receive of a Marker information frame
1732 * @marker_info: Marker info received
1733 * @port: the port we're looking at
Linus Torvalds1da177e2005-04-16 15:20:36 -07001734 */
Mathieu Desnoyers1c3f0b82007-10-18 23:41:04 -07001735static void ad_marker_info_received(struct bond_marker *marker_info,
1736 struct port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001737{
Mathieu Desnoyers1c3f0b82007-10-18 23:41:04 -07001738 struct bond_marker marker;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001739
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001740 /* copy the received marker data to the response marker */
Mathieu Desnoyers1c3f0b82007-10-18 23:41:04 -07001741 memcpy(&marker, marker_info, sizeof(struct bond_marker));
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001742 /* change the marker subtype to marker response */
Bandan Das128ea6c2010-10-16 20:19:58 +00001743 marker.tlv_type = AD_MARKER_RESPONSE_SUBTYPE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001744
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001745 /* send the marker response */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001746 if (ad_marker_send(port, &marker) >= 0) {
Joe Perchesa4aee5c2009-12-13 20:06:07 -08001747 pr_debug("Sent Marker Response on port %d\n",
1748 port->actor_port_number);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001749 }
1750}
1751
1752/**
1753 * ad_marker_response_received - handle receive of a marker response frame
1754 * @marker: marker PDU received
1755 * @port: the port we're looking at
1756 *
1757 * This function does nothing since we decided not to implement send and handle
1758 * response for marker PDU's, in this stage, but only to respond to marker
1759 * information.
1760 */
Mathieu Desnoyers1c3f0b82007-10-18 23:41:04 -07001761static void ad_marker_response_received(struct bond_marker *marker,
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001762 struct port *port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001763{
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001764 marker = NULL;
1765 port = NULL;
1766 /* DO NOTHING, SINCE WE DECIDED NOT TO IMPLEMENT THIS FEATURE FOR NOW */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001767}
1768
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001769/* ========= AD exported functions to the main bonding code ========= */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001770
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001771/* Check aggregators status in team every T seconds */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001772#define AD_AGGREGATOR_SELECTION_TIMER 8
1773
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001774/**
1775 * bond_3ad_initiate_agg_selection - initate aggregator selection
1776 * @bond: bonding struct
Jay Vosburghfd989c82008-11-04 17:51:16 -08001777 *
1778 * Set the aggregation selection timer, to initiate an agg selection in
1779 * the very near future. Called during first initialization, and during
1780 * any down to up transitions of the bond.
1781 */
1782void bond_3ad_initiate_agg_selection(struct bonding *bond, int timeout)
1783{
1784 BOND_AD_INFO(bond).agg_select_timer = timeout;
Jay Vosburghfd989c82008-11-04 17:51:16 -08001785}
1786
Linus Torvalds1da177e2005-04-16 15:20:36 -07001787/**
1788 * bond_3ad_initialize - initialize a bond's 802.3ad parameters and structures
1789 * @bond: bonding struct to work on
1790 * @tick_resolution: tick duration (millisecond resolution)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001791 *
1792 * Can be called only after the mac address of the bond is set.
1793 */
Peter Pan(潘卫平)56d00c672011-06-08 21:19:02 +00001794void bond_3ad_initialize(struct bonding *bond, u16 tick_resolution)
Jiri Pirko3a6d54c2009-05-11 23:37:15 +00001795{
dingtianhong815117a2014-01-02 09:12:54 +08001796 /* check that the bond is not initialized yet */
1797 if (!MAC_ADDRESS_EQUAL(&(BOND_AD_INFO(bond).system.sys_mac_addr),
Jiri Pirko3a6d54c2009-05-11 23:37:15 +00001798 bond->dev->dev_addr)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001799
Jiri Bohac163c8ff2014-02-14 18:13:50 +01001800 BOND_AD_INFO(bond).aggregator_identifier = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001801
Linus Torvalds1da177e2005-04-16 15:20:36 -07001802 BOND_AD_INFO(bond).system.sys_priority = 0xFFFF;
1803 BOND_AD_INFO(bond).system.sys_mac_addr = *((struct mac_addr *)bond->dev->dev_addr);
1804
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001805 /* initialize how many times this module is called in one
1806 * second (should be about every 100ms)
1807 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001808 ad_ticks_per_sec = tick_resolution;
1809
Jay Vosburghfd989c82008-11-04 17:51:16 -08001810 bond_3ad_initiate_agg_selection(bond,
1811 AD_AGGREGATOR_SELECTION_TIMER *
1812 ad_ticks_per_sec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001813 }
1814}
1815
1816/**
1817 * bond_3ad_bind_slave - initialize a slave's port
1818 * @slave: slave struct to work on
1819 *
1820 * Returns: 0 on success
1821 * < 0 on error
1822 */
dingtianhong359632e2014-01-02 09:13:12 +08001823void bond_3ad_bind_slave(struct slave *slave)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001824{
1825 struct bonding *bond = bond_get_bond_by_slave(slave);
1826 struct port *port;
1827 struct aggregator *aggregator;
1828
dingtianhong359632e2014-01-02 09:13:12 +08001829 /* check that the slave has not been initialized yet. */
dingtianhong3fdddd82014-05-12 15:08:43 +08001830 if (SLAVE_AD_INFO(slave)->port.slave != slave) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001831
dingtianhong359632e2014-01-02 09:13:12 +08001832 /* port initialization */
dingtianhong3fdddd82014-05-12 15:08:43 +08001833 port = &(SLAVE_AD_INFO(slave)->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001834
Peter Pan(潘卫平)bf0239a2011-06-13 04:30:10 +00001835 ad_initialize_port(port, bond->params.lacp_fast);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001836
1837 port->slave = slave;
dingtianhong3fdddd82014-05-12 15:08:43 +08001838 port->actor_port_number = SLAVE_AD_INFO(slave)->id;
dingtianhong359632e2014-01-02 09:13:12 +08001839 /* key is determined according to the link speed, duplex and user key(which
1840 * is yet not supported)
dingtianhong359632e2014-01-02 09:13:12 +08001841 */
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001842 port->actor_admin_port_key = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001843 port->actor_admin_port_key |= __get_duplex(port);
1844 port->actor_admin_port_key |= (__get_link_speed(port) << 1);
1845 port->actor_oper_port_key = port->actor_admin_port_key;
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001846 /* if the port is not full duplex, then the port should be not
1847 * lacp Enabled
1848 */
Bandan Das7bfc4752010-10-16 20:19:59 +00001849 if (!(port->actor_oper_port_key & AD_DUPLEX_KEY_BITS))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001850 port->sm_vars &= ~AD_PORT_LACP_ENABLED;
dingtianhong359632e2014-01-02 09:13:12 +08001851 /* actor system is the bond's system */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001852 port->actor_system = BOND_AD_INFO(bond).system.sys_mac_addr;
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001853 /* tx timer(to verify that no more than MAX_TX_IN_SECOND
1854 * lacpdu's are sent in one second)
1855 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001856 port->sm_tx_timer_counter = ad_ticks_per_sec/AD_MAX_TX_IN_SECOND;
1857 port->aggregator = NULL;
1858 port->next_port_in_aggregator = NULL;
1859
1860 __disable_port(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001861
dingtianhong359632e2014-01-02 09:13:12 +08001862 /* aggregator initialization */
dingtianhong3fdddd82014-05-12 15:08:43 +08001863 aggregator = &(SLAVE_AD_INFO(slave)->aggregator);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001864
1865 ad_initialize_agg(aggregator);
1866
1867 aggregator->aggregator_mac_address = *((struct mac_addr *)bond->dev->dev_addr);
Jiri Bohac163c8ff2014-02-14 18:13:50 +01001868 aggregator->aggregator_identifier = ++BOND_AD_INFO(bond).aggregator_identifier;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001869 aggregator->slave = slave;
1870 aggregator->is_active = 0;
1871 aggregator->num_of_ports = 0;
1872 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001873}
1874
1875/**
1876 * bond_3ad_unbind_slave - deinitialize a slave's port
1877 * @slave: slave struct to work on
1878 *
1879 * Search for the aggregator that is related to this port, remove the
1880 * aggregator and assign another aggregator for other port related to it
1881 * (if any), and remove the port.
1882 */
1883void bond_3ad_unbind_slave(struct slave *slave)
1884{
1885 struct port *port, *prev_port, *temp_port;
1886 struct aggregator *aggregator, *new_aggregator, *temp_aggregator;
1887 int select_new_active_agg = 0;
Veaceslav Falico0b088262013-09-27 16:12:02 +02001888 struct bonding *bond = slave->bond;
1889 struct slave *slave_iter;
1890 struct list_head *iter;
Mahesh Bandewaree637712014-10-04 17:45:01 -07001891 bool dummy_slave_update; /* Ignore this value as caller updates array */
Jasper Spaansa361c832009-10-23 04:09:24 +00001892
Nikolay Aleksandrove4702592014-09-11 22:49:27 +02001893 /* Sync against bond_3ad_state_machine_handler() */
1894 spin_lock_bh(&bond->mode_lock);
dingtianhong3fdddd82014-05-12 15:08:43 +08001895 aggregator = &(SLAVE_AD_INFO(slave)->aggregator);
1896 port = &(SLAVE_AD_INFO(slave)->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001897
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001898 /* if slave is null, the whole port is not initialized */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001899 if (!port->slave) {
Veaceslav Falicod4471f52014-07-15 19:36:00 +02001900 netdev_warn(bond->dev, "Trying to unbind an uninitialized port on %s\n",
1901 slave->dev->name);
Nikolay Aleksandrove4702592014-09-11 22:49:27 +02001902 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001903 }
1904
Veaceslav Falicod4471f52014-07-15 19:36:00 +02001905 netdev_dbg(bond->dev, "Unbinding Link Aggregation Group %d\n",
1906 aggregator->aggregator_identifier);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001907
1908 /* Tell the partner that this port is not suitable for aggregation */
1909 port->actor_oper_port_state &= ~AD_STATE_AGGREGATION;
1910 __update_lacpdu_from_port(port);
1911 ad_lacpdu_send(port);
1912
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001913 /* check if this aggregator is occupied */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001914 if (aggregator->lag_ports) {
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001915 /* check if there are other ports related to this aggregator
1916 * except the port related to this slave(thats ensure us that
1917 * there is a reason to search for new aggregator, and that we
1918 * will find one
1919 */
1920 if ((aggregator->lag_ports != port) ||
1921 (aggregator->lag_ports->next_port_in_aggregator)) {
1922 /* find new aggregator for the related port(s) */
Veaceslav Falico0b088262013-09-27 16:12:02 +02001923 bond_for_each_slave(bond, slave_iter, iter) {
dingtianhong3fdddd82014-05-12 15:08:43 +08001924 new_aggregator = &(SLAVE_AD_INFO(slave_iter)->aggregator);
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001925 /* if the new aggregator is empty, or it is
1926 * connected to our port only
1927 */
1928 if (!new_aggregator->lag_ports ||
1929 ((new_aggregator->lag_ports == port) &&
1930 !new_aggregator->lag_ports->next_port_in_aggregator))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001931 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001932 }
Veaceslav Falico0b088262013-09-27 16:12:02 +02001933 if (!slave_iter)
1934 new_aggregator = NULL;
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001935
1936 /* if new aggregator found, copy the aggregator's
1937 * parameters and connect the related lag_ports to the
1938 * new aggregator
1939 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001940 if ((new_aggregator) && ((!new_aggregator->lag_ports) || ((new_aggregator->lag_ports == port) && !new_aggregator->lag_ports->next_port_in_aggregator))) {
Veaceslav Falicod4471f52014-07-15 19:36:00 +02001941 netdev_dbg(bond->dev, "Some port(s) related to LAG %d - replacing with LAG %d\n",
1942 aggregator->aggregator_identifier,
1943 new_aggregator->aggregator_identifier);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001944
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001945 if ((new_aggregator->lag_ports == port) &&
1946 new_aggregator->is_active) {
Veaceslav Falicod4471f52014-07-15 19:36:00 +02001947 netdev_info(bond->dev, "Removing an active aggregator\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001948 select_new_active_agg = 1;
1949 }
1950
1951 new_aggregator->is_individual = aggregator->is_individual;
1952 new_aggregator->actor_admin_aggregator_key = aggregator->actor_admin_aggregator_key;
1953 new_aggregator->actor_oper_aggregator_key = aggregator->actor_oper_aggregator_key;
1954 new_aggregator->partner_system = aggregator->partner_system;
1955 new_aggregator->partner_system_priority = aggregator->partner_system_priority;
1956 new_aggregator->partner_oper_aggregator_key = aggregator->partner_oper_aggregator_key;
1957 new_aggregator->receive_state = aggregator->receive_state;
1958 new_aggregator->transmit_state = aggregator->transmit_state;
1959 new_aggregator->lag_ports = aggregator->lag_ports;
1960 new_aggregator->is_active = aggregator->is_active;
1961 new_aggregator->num_of_ports = aggregator->num_of_ports;
1962
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001963 /* update the information that is written on
1964 * the ports about the aggregator
1965 */
Bandan Das128ea6c2010-10-16 20:19:58 +00001966 for (temp_port = aggregator->lag_ports; temp_port;
1967 temp_port = temp_port->next_port_in_aggregator) {
1968 temp_port->aggregator = new_aggregator;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001969 temp_port->actor_port_aggregator_identifier = new_aggregator->aggregator_identifier;
1970 }
1971
Linus Torvalds1da177e2005-04-16 15:20:36 -07001972 ad_clear_agg(aggregator);
Jasper Spaansa361c832009-10-23 04:09:24 +00001973
Bandan Das7bfc4752010-10-16 20:19:59 +00001974 if (select_new_active_agg)
Mahesh Bandewaree637712014-10-04 17:45:01 -07001975 ad_agg_selection_logic(__get_first_agg(port),
1976 &dummy_slave_update);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001977 } else {
Veaceslav Falicod4471f52014-07-15 19:36:00 +02001978 netdev_warn(bond->dev, "unbinding aggregator, and could not find a new aggregator for its ports\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001979 }
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001980 } else {
1981 /* in case that the only port related to this
1982 * aggregator is the one we want to remove
1983 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001984 select_new_active_agg = aggregator->is_active;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001985 ad_clear_agg(aggregator);
1986 if (select_new_active_agg) {
Veaceslav Falicod4471f52014-07-15 19:36:00 +02001987 netdev_info(bond->dev, "Removing an active aggregator\n");
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001988 /* select new active aggregator */
Veaceslav Falico74684492013-09-27 15:10:58 +02001989 temp_aggregator = __get_first_agg(port);
1990 if (temp_aggregator)
Mahesh Bandewaree637712014-10-04 17:45:01 -07001991 ad_agg_selection_logic(temp_aggregator,
1992 &dummy_slave_update);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001993 }
1994 }
1995 }
1996
Veaceslav Falicod4471f52014-07-15 19:36:00 +02001997 netdev_dbg(bond->dev, "Unbinding port %d\n", port->actor_port_number);
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01001998
1999 /* find the aggregator that this port is connected to */
Veaceslav Falico0b088262013-09-27 16:12:02 +02002000 bond_for_each_slave(bond, slave_iter, iter) {
dingtianhong3fdddd82014-05-12 15:08:43 +08002001 temp_aggregator = &(SLAVE_AD_INFO(slave_iter)->aggregator);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002002 prev_port = NULL;
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01002003 /* search the port in the aggregator's related ports */
Bandan Das128ea6c2010-10-16 20:19:58 +00002004 for (temp_port = temp_aggregator->lag_ports; temp_port;
2005 prev_port = temp_port,
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01002006 temp_port = temp_port->next_port_in_aggregator) {
2007 if (temp_port == port) {
2008 /* the aggregator found - detach the port from
2009 * this aggregator
2010 */
Bandan Das7bfc4752010-10-16 20:19:59 +00002011 if (prev_port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002012 prev_port->next_port_in_aggregator = temp_port->next_port_in_aggregator;
Bandan Das7bfc4752010-10-16 20:19:59 +00002013 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07002014 temp_aggregator->lag_ports = temp_port->next_port_in_aggregator;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002015 temp_aggregator->num_of_ports--;
Bandan Das128ea6c2010-10-16 20:19:58 +00002016 if (temp_aggregator->num_of_ports == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002017 select_new_active_agg = temp_aggregator->is_active;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002018 ad_clear_agg(temp_aggregator);
2019 if (select_new_active_agg) {
Veaceslav Falicod4471f52014-07-15 19:36:00 +02002020 netdev_info(bond->dev, "Removing an active aggregator\n");
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01002021 /* select new active aggregator */
Mahesh Bandewaree637712014-10-04 17:45:01 -07002022 ad_agg_selection_logic(__get_first_agg(port),
2023 &dummy_slave_update);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002024 }
2025 }
2026 break;
2027 }
2028 }
2029 }
Bandan Das128ea6c2010-10-16 20:19:58 +00002030 port->slave = NULL;
Nikolay Aleksandrove4702592014-09-11 22:49:27 +02002031
2032out:
2033 spin_unlock_bh(&bond->mode_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002034}
2035
2036/**
2037 * bond_3ad_state_machine_handler - handle state machines timeout
2038 * @bond: bonding struct to work on
2039 *
2040 * The state machine handling concept in this module is to check every tick
2041 * which state machine should operate any function. The execution order is
2042 * round robin, so when we have an interaction between state machines, the
2043 * reply of one to each other might be delayed until next tick.
2044 *
2045 * This function also complete the initialization when the agg_select_timer
2046 * times out, and it selects an aggregator for the ports that are yet not
2047 * related to any aggregator, and selects the active aggregator for a bond.
2048 */
Jay Vosburgh1b76b312007-10-17 17:37:45 -07002049void bond_3ad_state_machine_handler(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002050{
Jay Vosburgh1b76b312007-10-17 17:37:45 -07002051 struct bonding *bond = container_of(work, struct bonding,
2052 ad_work.work);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002053 struct aggregator *aggregator;
Veaceslav Falico3c4c88a2013-09-27 16:11:57 +02002054 struct list_head *iter;
2055 struct slave *slave;
2056 struct port *port;
dingtianhong5e5b0662014-02-26 11:05:22 +08002057 bool should_notify_rtnl = BOND_SLAVE_NOTIFY_LATER;
Mahesh Bandewaree637712014-10-04 17:45:01 -07002058 bool update_slave_arr = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002059
Nikolay Aleksandrove4702592014-09-11 22:49:27 +02002060 /* Lock to protect data accessed by all (e.g., port->sm_vars) and
2061 * against running with bond_3ad_unbind_slave. ad_rx_machine may run
2062 * concurrently due to incoming LACPDU as well.
2063 */
Nikolay Aleksandrovb7435622014-09-11 22:49:25 +02002064 spin_lock_bh(&bond->mode_lock);
dingtianhongbe79bd02013-12-13 10:20:12 +08002065 rcu_read_lock();
David S. Miller1f2cd842013-10-28 00:11:22 -04002066
dingtianhongbe79bd02013-12-13 10:20:12 +08002067 /* check if there are any slaves */
Veaceslav Falico0965a1f2013-09-25 09:20:21 +02002068 if (!bond_has_slaves(bond))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002069 goto re_arm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002070
dingtianhongbe79bd02013-12-13 10:20:12 +08002071 /* check if agg_select_timer timer after initialize is timed out */
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01002072 if (BOND_AD_INFO(bond).agg_select_timer &&
2073 !(--BOND_AD_INFO(bond).agg_select_timer)) {
dingtianhongbe79bd02013-12-13 10:20:12 +08002074 slave = bond_first_slave_rcu(bond);
dingtianhong3fdddd82014-05-12 15:08:43 +08002075 port = slave ? &(SLAVE_AD_INFO(slave)->port) : NULL;
Veaceslav Falicofe9323d2013-09-27 16:11:58 +02002076
dingtianhongbe79bd02013-12-13 10:20:12 +08002077 /* select the active aggregator for the bond */
Veaceslav Falicofe9323d2013-09-27 16:11:58 +02002078 if (port) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002079 if (!port->slave) {
Veaceslav Falicod4471f52014-07-15 19:36:00 +02002080 net_warn_ratelimited("%s: Warning: bond's first port is uninitialized\n",
2081 bond->dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002082 goto re_arm;
2083 }
2084
2085 aggregator = __get_first_agg(port);
Mahesh Bandewaree637712014-10-04 17:45:01 -07002086 ad_agg_selection_logic(aggregator, &update_slave_arr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002087 }
Jay Vosburghf0c76d62008-07-02 18:21:58 -07002088 bond_3ad_set_carrier(bond);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002089 }
2090
dingtianhongbe79bd02013-12-13 10:20:12 +08002091 /* for each port run the state machines */
2092 bond_for_each_slave_rcu(bond, slave, iter) {
dingtianhong3fdddd82014-05-12 15:08:43 +08002093 port = &(SLAVE_AD_INFO(slave)->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002094 if (!port->slave) {
Veaceslav Falicod4471f52014-07-15 19:36:00 +02002095 net_warn_ratelimited("%s: Warning: Found an uninitialized port\n",
Veaceslav Falico86a2b9c2014-03-16 17:55:03 +01002096 bond->dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002097 goto re_arm;
2098 }
2099
2100 ad_rx_machine(NULL, port);
2101 ad_periodic_machine(port);
Mahesh Bandewaree637712014-10-04 17:45:01 -07002102 ad_port_selection_logic(port, &update_slave_arr);
2103 ad_mux_machine(port, &update_slave_arr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002104 ad_tx_machine(port);
2105
dingtianhongbe79bd02013-12-13 10:20:12 +08002106 /* turn off the BEGIN bit, since we already handled it */
Bandan Das7bfc4752010-10-16 20:19:59 +00002107 if (port->sm_vars & AD_PORT_BEGIN)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002108 port->sm_vars &= ~AD_PORT_BEGIN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002109 }
2110
2111re_arm:
dingtianhong5e5b0662014-02-26 11:05:22 +08002112 bond_for_each_slave_rcu(bond, slave, iter) {
2113 if (slave->should_notify) {
2114 should_notify_rtnl = BOND_SLAVE_NOTIFY_NOW;
2115 break;
2116 }
2117 }
dingtianhongbe79bd02013-12-13 10:20:12 +08002118 rcu_read_unlock();
Nikolay Aleksandrovb7435622014-09-11 22:49:25 +02002119 spin_unlock_bh(&bond->mode_lock);
dingtianhong5e5b0662014-02-26 11:05:22 +08002120
Mahesh Bandewaree637712014-10-04 17:45:01 -07002121 if (update_slave_arr)
2122 bond_slave_arr_work_rearm(bond, 0);
2123
dingtianhong5e5b0662014-02-26 11:05:22 +08002124 if (should_notify_rtnl && rtnl_trylock()) {
dingtianhongb0929912014-02-26 11:05:23 +08002125 bond_slave_state_notify(bond);
dingtianhong5e5b0662014-02-26 11:05:22 +08002126 rtnl_unlock();
2127 }
dingtianhongbe79bd02013-12-13 10:20:12 +08002128 queue_delayed_work(bond->wq, &bond->ad_work, ad_delta_in_ticks);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002129}
2130
2131/**
2132 * bond_3ad_rx_indication - handle a received frame
2133 * @lacpdu: received lacpdu
2134 * @slave: slave struct to work on
2135 * @length: length of the data received
2136 *
2137 * It is assumed that frames that were sent on this NIC don't returned as new
2138 * received frames (loopback). Since only the payload is given to this
2139 * function, it check for loopback.
2140 */
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01002141static int bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave,
2142 u16 length)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002143{
2144 struct port *port;
Jiri Bohac13a8e0c2012-05-09 01:01:40 +00002145 int ret = RX_HANDLER_ANOTHER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002146
2147 if (length >= sizeof(struct lacpdu)) {
2148
dingtianhong3fdddd82014-05-12 15:08:43 +08002149 port = &(SLAVE_AD_INFO(slave)->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002150
2151 if (!port->slave) {
Veaceslav Falicod4471f52014-07-15 19:36:00 +02002152 net_warn_ratelimited("%s: Warning: port of slave %s is uninitialized\n",
2153 slave->dev->name, slave->bond->dev->name);
Jiri Bohac13a8e0c2012-05-09 01:01:40 +00002154 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002155 }
2156
2157 switch (lacpdu->subtype) {
2158 case AD_TYPE_LACPDU:
Jiri Bohac13a8e0c2012-05-09 01:01:40 +00002159 ret = RX_HANDLER_CONSUMED;
Veaceslav Falicod4471f52014-07-15 19:36:00 +02002160 netdev_dbg(slave->bond->dev, "Received LACPDU on port %d\n",
2161 port->actor_port_number);
Nils Carlson16d79d72011-03-03 22:09:11 +00002162 /* Protect against concurrent state machines */
Nikolay Aleksandrove4702592014-09-11 22:49:27 +02002163 spin_lock(&slave->bond->mode_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002164 ad_rx_machine(lacpdu, port);
Nikolay Aleksandrove4702592014-09-11 22:49:27 +02002165 spin_unlock(&slave->bond->mode_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002166 break;
2167
2168 case AD_TYPE_MARKER:
Jiri Bohac13a8e0c2012-05-09 01:01:40 +00002169 ret = RX_HANDLER_CONSUMED;
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01002170 /* No need to convert fields to Little Endian since we
2171 * don't use the marker's fields.
2172 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002173
Mathieu Desnoyers1c3f0b82007-10-18 23:41:04 -07002174 switch (((struct bond_marker *)lacpdu)->tlv_type) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002175 case AD_MARKER_INFORMATION_SUBTYPE:
Veaceslav Falicod4471f52014-07-15 19:36:00 +02002176 netdev_dbg(slave->bond->dev, "Received Marker Information on port %d\n",
2177 port->actor_port_number);
Mathieu Desnoyers1c3f0b82007-10-18 23:41:04 -07002178 ad_marker_info_received((struct bond_marker *)lacpdu, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002179 break;
2180
2181 case AD_MARKER_RESPONSE_SUBTYPE:
Veaceslav Falicod4471f52014-07-15 19:36:00 +02002182 netdev_dbg(slave->bond->dev, "Received Marker Response on port %d\n",
2183 port->actor_port_number);
Mathieu Desnoyers1c3f0b82007-10-18 23:41:04 -07002184 ad_marker_response_received((struct bond_marker *)lacpdu, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002185 break;
2186
2187 default:
Veaceslav Falicod4471f52014-07-15 19:36:00 +02002188 netdev_dbg(slave->bond->dev, "Received an unknown Marker subtype on slot %d\n",
2189 port->actor_port_number);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002190 }
2191 }
2192 }
Jiri Bohac13a8e0c2012-05-09 01:01:40 +00002193 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002194}
2195
2196/**
2197 * bond_3ad_adapter_speed_changed - handle a slave's speed change indication
2198 * @slave: slave struct to work on
2199 *
2200 * Handle reselection of aggregator (if needed) for this port.
2201 */
2202void bond_3ad_adapter_speed_changed(struct slave *slave)
2203{
2204 struct port *port;
2205
dingtianhong3fdddd82014-05-12 15:08:43 +08002206 port = &(SLAVE_AD_INFO(slave)->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002207
dingtianhong71a06c52013-12-13 17:29:19 +08002208 /* if slave is null, the whole port is not initialized */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002209 if (!port->slave) {
Veaceslav Falicod4471f52014-07-15 19:36:00 +02002210 netdev_warn(slave->bond->dev, "speed changed for uninitialized port on %s\n",
2211 slave->dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002212 return;
2213 }
2214
Nikolay Aleksandrove4702592014-09-11 22:49:27 +02002215 spin_lock_bh(&slave->bond->mode_lock);
dingtianhong71a06c52013-12-13 17:29:19 +08002216
Linus Torvalds1da177e2005-04-16 15:20:36 -07002217 port->actor_admin_port_key &= ~AD_SPEED_KEY_BITS;
Bandan Das128ea6c2010-10-16 20:19:58 +00002218 port->actor_oper_port_key = port->actor_admin_port_key |=
2219 (__get_link_speed(port) << 1);
Veaceslav Falicod4471f52014-07-15 19:36:00 +02002220 netdev_dbg(slave->bond->dev, "Port %d changed speed\n", port->actor_port_number);
dingtianhong71a06c52013-12-13 17:29:19 +08002221 /* there is no need to reselect a new aggregator, just signal the
2222 * state machines to reinitialize
2223 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002224 port->sm_vars |= AD_PORT_BEGIN;
dingtianhong71a06c52013-12-13 17:29:19 +08002225
Nikolay Aleksandrove4702592014-09-11 22:49:27 +02002226 spin_unlock_bh(&slave->bond->mode_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002227}
2228
2229/**
2230 * bond_3ad_adapter_duplex_changed - handle a slave's duplex change indication
2231 * @slave: slave struct to work on
2232 *
2233 * Handle reselection of aggregator (if needed) for this port.
2234 */
2235void bond_3ad_adapter_duplex_changed(struct slave *slave)
2236{
2237 struct port *port;
2238
dingtianhong3fdddd82014-05-12 15:08:43 +08002239 port = &(SLAVE_AD_INFO(slave)->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002240
dingtianhongbca44a72013-12-13 17:29:24 +08002241 /* if slave is null, the whole port is not initialized */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002242 if (!port->slave) {
Veaceslav Falicod4471f52014-07-15 19:36:00 +02002243 netdev_warn(slave->bond->dev, "duplex changed for uninitialized port on %s\n",
2244 slave->dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002245 return;
2246 }
2247
Nikolay Aleksandrove4702592014-09-11 22:49:27 +02002248 spin_lock_bh(&slave->bond->mode_lock);
dingtianhongbca44a72013-12-13 17:29:24 +08002249
Linus Torvalds1da177e2005-04-16 15:20:36 -07002250 port->actor_admin_port_key &= ~AD_DUPLEX_KEY_BITS;
Bandan Das128ea6c2010-10-16 20:19:58 +00002251 port->actor_oper_port_key = port->actor_admin_port_key |=
2252 __get_duplex(port);
Veaceslav Falicod4471f52014-07-15 19:36:00 +02002253 netdev_dbg(slave->bond->dev, "Port %d changed duplex\n", port->actor_port_number);
dingtianhongbca44a72013-12-13 17:29:24 +08002254 /* there is no need to reselect a new aggregator, just signal the
2255 * state machines to reinitialize
2256 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002257 port->sm_vars |= AD_PORT_BEGIN;
dingtianhongbca44a72013-12-13 17:29:24 +08002258
Nikolay Aleksandrove4702592014-09-11 22:49:27 +02002259 spin_unlock_bh(&slave->bond->mode_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002260}
2261
2262/**
2263 * bond_3ad_handle_link_change - handle a slave's link status change indication
2264 * @slave: slave struct to work on
2265 * @status: whether the link is now up or down
2266 *
2267 * Handle reselection of aggregator (if needed) for this port.
2268 */
2269void bond_3ad_handle_link_change(struct slave *slave, char link)
2270{
2271 struct port *port;
2272
dingtianhong3fdddd82014-05-12 15:08:43 +08002273 port = &(SLAVE_AD_INFO(slave)->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002274
dingtianhong108db732013-12-13 17:29:29 +08002275 /* if slave is null, the whole port is not initialized */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002276 if (!port->slave) {
Veaceslav Falicod4471f52014-07-15 19:36:00 +02002277 netdev_warn(slave->bond->dev, "link status changed for uninitialized port on %s\n",
2278 slave->dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002279 return;
2280 }
2281
Nikolay Aleksandrove4702592014-09-11 22:49:27 +02002282 spin_lock_bh(&slave->bond->mode_lock);
dingtianhong108db732013-12-13 17:29:29 +08002283 /* on link down we are zeroing duplex and speed since
2284 * some of the adaptors(ce1000.lan) report full duplex/speed
2285 * instead of N/A(duplex) / 0(speed).
2286 *
2287 * on link up we are forcing recheck on the duplex and speed since
2288 * some of he adaptors(ce1000.lan) report.
2289 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002290 if (link == BOND_LINK_UP) {
Holger Eitzenbergerf48127b2008-12-26 13:26:54 -08002291 port->is_enabled = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002292 port->actor_admin_port_key &= ~AD_DUPLEX_KEY_BITS;
Bandan Das128ea6c2010-10-16 20:19:58 +00002293 port->actor_oper_port_key = port->actor_admin_port_key |=
2294 __get_duplex(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002295 port->actor_admin_port_key &= ~AD_SPEED_KEY_BITS;
Bandan Das128ea6c2010-10-16 20:19:58 +00002296 port->actor_oper_port_key = port->actor_admin_port_key |=
2297 (__get_link_speed(port) << 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002298 } else {
2299 /* link has failed */
Holger Eitzenbergerf48127b2008-12-26 13:26:54 -08002300 port->is_enabled = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002301 port->actor_admin_port_key &= ~AD_DUPLEX_KEY_BITS;
Bandan Das128ea6c2010-10-16 20:19:58 +00002302 port->actor_oper_port_key = (port->actor_admin_port_key &=
2303 ~AD_SPEED_KEY_BITS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002304 }
Veaceslav Falicod4471f52014-07-15 19:36:00 +02002305 netdev_dbg(slave->bond->dev, "Port %d changed link status to %s\n",
2306 port->actor_port_number,
2307 link == BOND_LINK_UP ? "UP" : "DOWN");
dingtianhong108db732013-12-13 17:29:29 +08002308 /* there is no need to reselect a new aggregator, just signal the
2309 * state machines to reinitialize
2310 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002311 port->sm_vars |= AD_PORT_BEGIN;
dingtianhong108db732013-12-13 17:29:29 +08002312
Nikolay Aleksandrove4702592014-09-11 22:49:27 +02002313 spin_unlock_bh(&slave->bond->mode_lock);
Mahesh Bandewaree637712014-10-04 17:45:01 -07002314
2315 /* RTNL is held and mode_lock is released so it's safe
2316 * to update slave_array here.
2317 */
2318 bond_update_slave_arr(slave->bond, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002319}
2320
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01002321/**
2322 * bond_3ad_set_carrier - set link state for bonding master
2323 * @bond - bonding structure
2324 *
2325 * if we have an active aggregator, we're up, if not, we're down.
2326 * Presumes that we cannot have an active aggregator if there are
2327 * no slaves with link up.
Jay Vosburghff59c452006-03-27 13:27:43 -08002328 *
Jay Vosburgh031ae4d2007-06-13 22:11:34 -07002329 * This behavior complies with IEEE 802.3 section 43.3.9.
2330 *
Jay Vosburghff59c452006-03-27 13:27:43 -08002331 * Called by bond_set_carrier(). Return zero if carrier state does not
2332 * change, nonzero if it does.
2333 */
2334int bond_3ad_set_carrier(struct bonding *bond)
2335{
stephen hemminger655f8912011-06-22 09:54:39 +00002336 struct aggregator *active;
nikolay@redhat.comdec1e902013-08-01 16:54:47 +02002337 struct slave *first_slave;
Veaceslav Falicoc1bc9642014-01-10 11:59:43 +01002338 int ret = 1;
stephen hemminger655f8912011-06-22 09:54:39 +00002339
dingtianhongbe79bd02013-12-13 10:20:12 +08002340 rcu_read_lock();
2341 first_slave = bond_first_slave_rcu(bond);
Veaceslav Falicoc1bc9642014-01-10 11:59:43 +01002342 if (!first_slave) {
2343 ret = 0;
2344 goto out;
2345 }
dingtianhong3fdddd82014-05-12 15:08:43 +08002346 active = __get_active_agg(&(SLAVE_AD_INFO(first_slave)->aggregator));
stephen hemminger655f8912011-06-22 09:54:39 +00002347 if (active) {
2348 /* are enough slaves available to consider link up? */
2349 if (active->num_of_ports < bond->params.min_links) {
2350 if (netif_carrier_ok(bond->dev)) {
2351 netif_carrier_off(bond->dev);
Veaceslav Falicoc1bc9642014-01-10 11:59:43 +01002352 goto out;
stephen hemminger655f8912011-06-22 09:54:39 +00002353 }
2354 } else if (!netif_carrier_ok(bond->dev)) {
Jay Vosburghff59c452006-03-27 13:27:43 -08002355 netif_carrier_on(bond->dev);
Veaceslav Falicoc1bc9642014-01-10 11:59:43 +01002356 goto out;
Jay Vosburghff59c452006-03-27 13:27:43 -08002357 }
Veaceslav Falicoc1bc9642014-01-10 11:59:43 +01002358 } else if (netif_carrier_ok(bond->dev)) {
Jay Vosburghff59c452006-03-27 13:27:43 -08002359 netif_carrier_off(bond->dev);
Jay Vosburghff59c452006-03-27 13:27:43 -08002360 }
Veaceslav Falicoc1bc9642014-01-10 11:59:43 +01002361out:
2362 rcu_read_unlock();
2363 return ret;
Jay Vosburghff59c452006-03-27 13:27:43 -08002364}
2365
Linus Torvalds1da177e2005-04-16 15:20:36 -07002366/**
nikolay@redhat.com318debd2013-05-18 01:18:31 +00002367 * __bond_3ad_get_active_agg_info - get information of the active aggregator
Linus Torvalds1da177e2005-04-16 15:20:36 -07002368 * @bond: bonding struct to work on
2369 * @ad_info: ad_info struct to fill with the bond's info
2370 *
2371 * Returns: 0 on success
2372 * < 0 on error
2373 */
nikolay@redhat.com318debd2013-05-18 01:18:31 +00002374int __bond_3ad_get_active_agg_info(struct bonding *bond,
2375 struct ad_info *ad_info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002376{
2377 struct aggregator *aggregator = NULL;
Veaceslav Falico3c4c88a2013-09-27 16:11:57 +02002378 struct list_head *iter;
2379 struct slave *slave;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002380 struct port *port;
2381
dingtianhong47e91f562013-10-15 16:28:35 +08002382 bond_for_each_slave_rcu(bond, slave, iter) {
dingtianhong3fdddd82014-05-12 15:08:43 +08002383 port = &(SLAVE_AD_INFO(slave)->port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002384 if (port->aggregator && port->aggregator->is_active) {
2385 aggregator = port->aggregator;
2386 break;
2387 }
2388 }
2389
Joe Perches21f374c2014-02-18 09:42:47 -08002390 if (!aggregator)
2391 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002392
Joe Perches21f374c2014-02-18 09:42:47 -08002393 ad_info->aggregator_id = aggregator->aggregator_identifier;
2394 ad_info->ports = aggregator->num_of_ports;
2395 ad_info->actor_key = aggregator->actor_oper_aggregator_key;
2396 ad_info->partner_key = aggregator->partner_oper_aggregator_key;
2397 ether_addr_copy(ad_info->partner_system,
2398 aggregator->partner_system.mac_addr_value);
2399 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002400}
2401
nikolay@redhat.com318debd2013-05-18 01:18:31 +00002402int bond_3ad_get_active_agg_info(struct bonding *bond, struct ad_info *ad_info)
2403{
2404 int ret;
2405
dingtianhong47e91f562013-10-15 16:28:35 +08002406 rcu_read_lock();
nikolay@redhat.com318debd2013-05-18 01:18:31 +00002407 ret = __bond_3ad_get_active_agg_info(bond, ad_info);
dingtianhong47e91f562013-10-15 16:28:35 +08002408 rcu_read_unlock();
nikolay@redhat.com318debd2013-05-18 01:18:31 +00002409
2410 return ret;
2411}
2412
Eric Dumazetde063b72012-06-11 19:23:07 +00002413int bond_3ad_lacpdu_recv(const struct sk_buff *skb, struct bonding *bond,
2414 struct slave *slave)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002415{
Eric Dumazetde063b72012-06-11 19:23:07 +00002416 struct lacpdu *lacpdu, _lacpdu;
2417
Jiri Pirko3aba8912011-04-19 03:48:16 +00002418 if (skb->protocol != PKT_TYPE_LACPDU)
Nikolay Aleksandrov86e74982014-09-11 22:49:22 +02002419 return RX_HANDLER_ANOTHER;
Neil Hormanb3053252011-01-20 09:02:31 +00002420
Eric Dumazetde063b72012-06-11 19:23:07 +00002421 lacpdu = skb_header_pointer(skb, 0, sizeof(_lacpdu), &_lacpdu);
2422 if (!lacpdu)
Nikolay Aleksandrov86e74982014-09-11 22:49:22 +02002423 return RX_HANDLER_ANOTHER;
Andy Gospodarekab128112010-09-10 11:43:20 +00002424
Nikolay Aleksandrov86e74982014-09-11 22:49:22 +02002425 return bond_3ad_rx_indication(lacpdu, slave, skb->len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002426}
Peter Pan(潘卫平)ba824a82011-06-08 21:19:01 +00002427
Veaceslav Falico3bf2d282014-01-08 16:46:46 +01002428/**
2429 * bond_3ad_update_lacp_rate - change the lacp rate
2430 * @bond - bonding struct
2431 *
Peter Pan(潘卫平)ba824a82011-06-08 21:19:01 +00002432 * When modify lacp_rate parameter via sysfs,
2433 * update actor_oper_port_state of each port.
2434 *
Nikolay Aleksandrove4702592014-09-11 22:49:27 +02002435 * Hold bond->mode_lock,
Peter Pan(潘卫平)ba824a82011-06-08 21:19:01 +00002436 * so we can modify port->actor_oper_port_state,
2437 * no matter bond is up or down.
2438 */
2439void bond_3ad_update_lacp_rate(struct bonding *bond)
2440{
Peter Pan(潘卫平)ba824a82011-06-08 21:19:01 +00002441 struct port *port = NULL;
Veaceslav Falico9caff1e2013-09-25 09:20:14 +02002442 struct list_head *iter;
nikolay@redhat.comc5093162013-09-02 13:51:40 +02002443 struct slave *slave;
Peter Pan(潘卫平)ba824a82011-06-08 21:19:01 +00002444 int lacp_fast;
2445
Peter Pan(潘卫平)ba824a82011-06-08 21:19:01 +00002446 lacp_fast = bond->params.lacp_fast;
Nikolay Aleksandrove4702592014-09-11 22:49:27 +02002447 spin_lock_bh(&bond->mode_lock);
Veaceslav Falico9caff1e2013-09-25 09:20:14 +02002448 bond_for_each_slave(bond, slave, iter) {
dingtianhong3fdddd82014-05-12 15:08:43 +08002449 port = &(SLAVE_AD_INFO(slave)->port);
Peter Pan(潘卫平)ba824a82011-06-08 21:19:01 +00002450 if (lacp_fast)
2451 port->actor_oper_port_state |= AD_STATE_LACP_TIMEOUT;
2452 else
2453 port->actor_oper_port_state &= ~AD_STATE_LACP_TIMEOUT;
Peter Pan(潘卫平)ba824a82011-06-08 21:19:01 +00002454 }
Nikolay Aleksandrove4702592014-09-11 22:49:27 +02002455 spin_unlock_bh(&bond->mode_lock);
Peter Pan(潘卫平)ba824a82011-06-08 21:19:01 +00002456}