xref: /illumos-gate/usr/src/uts/common/io/aggr/aggr_lacp.c (revision 5435d801)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 /*
30  * IEEE 802.3ad Link Aggregation - LACP & Marker Protocol processing.
31  */
32 
33 #include <sys/types.h>
34 #include <sys/sysmacros.h>
35 #include <sys/conf.h>
36 #include <sys/cmn_err.h>
37 #include <sys/list.h>
38 #include <sys/ksynch.h>
39 #include <sys/kmem.h>
40 #include <sys/stream.h>
41 #include <sys/modctl.h>
42 #include <sys/ddi.h>
43 #include <sys/sunddi.h>
44 #include <sys/atomic.h>
45 #include <sys/stat.h>
46 #include <sys/byteorder.h>
47 #include <sys/strsun.h>
48 #include <sys/isa_defs.h>
49 
50 #include <sys/aggr.h>
51 #include <sys/aggr_impl.h>
52 
53 static struct ether_addr	etherzeroaddr = {
54 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00
55 };
56 
57 /*
58  * Slow_Protocol_Multicast address, as per IEEE 802.3ad spec.
59  */
60 static struct ether_addr   slow_multicast_addr = {
61 	0x01, 0x80, 0xc2, 0x00, 0x00, 0x02
62 };
63 
64 #ifdef DEBUG
65 /* LACP state machine debugging support */
66 static uint32_t aggr_lacp_debug = 0;
67 #define	AGGR_LACP_DBG(x)	if (aggr_lacp_debug) { (void) printf x; }
68 #else
69 #define	AGGR_LACP_DBG(x)	{}
70 #endif /* DEBUG */
71 
72 #define	NSECS_PER_SEC   1000000000ll
73 
74 /* used by lacp_misconfig_walker() */
75 typedef struct lacp_misconfig_check_state_s {
76 	aggr_port_t *cs_portp;
77 	boolean_t cs_found;
78 } lacp_misconfig_check_state_t;
79 
80 static const char *lacp_receive_str[] = LACP_RECEIVE_STATE_STRINGS;
81 static const char *lacp_periodic_str[] = LACP_PERIODIC_STRINGS;
82 static const char *lacp_mux_str[] = LACP_MUX_STRINGS;
83 
84 static uint16_t lacp_port_priority = 0x1000;
85 static uint16_t lacp_system_priority = 0x1000;
86 
87 static void periodic_timer_pop_locked(aggr_port_t *);
88 static void periodic_timer_pop(void *);
89 static void lacp_xmit_sm(aggr_port_t *);
90 static void lacp_periodic_sm(aggr_port_t *);
91 static void fill_lacp_pdu(aggr_port_t *, lacp_t *);
92 static void fill_lacp_ether(aggr_port_t *, struct ether_header *);
93 static void lacp_on(aggr_port_t *);
94 static void lacp_off(aggr_port_t *);
95 static boolean_t valid_lacp_pdu(aggr_port_t *, lacp_t *);
96 static void lacp_receive_sm(aggr_port_t *, lacp_t *);
97 static void aggr_set_coll_dist(aggr_port_t *, boolean_t);
98 static void aggr_set_coll_dist_locked(aggr_port_t *, boolean_t);
99 static void start_wait_while_timer(aggr_port_t *);
100 static void stop_wait_while_timer(aggr_port_t *);
101 static void lacp_reset_port(aggr_port_t *);
102 static void stop_current_while_timer(aggr_port_t *);
103 static void current_while_timer_pop(void *);
104 static void update_default_selected(aggr_port_t *);
105 static boolean_t update_selected(aggr_port_t *, lacp_t *);
106 
107 static int
108 inst_num(char *devname)
109 {
110 	int inst = 0;
111 	int fact = 1;
112 	char *p = &devname[strlen(devname)-1];
113 
114 	while (*p >= '0' && *p <= '9' && p >= devname) {
115 		inst += (*p - '0') * fact;
116 		fact *= 10;
117 		p--;
118 	}
119 
120 	return (inst);
121 }
122 
123 /*
124  * Initialize group specific LACP state and parameters.
125  */
126 void
127 aggr_lacp_init_grp(aggr_grp_t *aggrp)
128 {
129 	aggrp->aggr.PeriodicTimer = AGGR_LACP_TIMER_SHORT;
130 	aggrp->aggr.ActorSystemPriority = (uint16_t)lacp_system_priority;
131 	aggrp->aggr.CollectorMaxDelay = 10;
132 	aggrp->lg_lacp_mode = AGGR_LACP_OFF;
133 	aggrp->aggr.ready = B_FALSE;
134 }
135 
136 /*
137  * Complete LACP info initialization at port creation time.
138  */
139 void
140 aggr_lacp_init_port(aggr_port_t *portp)
141 {
142 	aggr_grp_t *aggrp = portp->lp_grp;
143 	aggr_lacp_port_t *pl = &portp->lp_lacp;
144 	uint16_t offset;
145 	uint32_t instance;
146 
147 	ASSERT(AGGR_LACP_LOCK_HELD(aggrp));
148 	ASSERT(RW_WRITE_HELD(&aggrp->lg_lock) || RW_READ_HELD(&aggrp->lg_lock));
149 	ASSERT(RW_WRITE_HELD(&portp->lp_lock) || RW_READ_HELD(&portp->lp_lock));
150 
151 	/*
152 	 * Port numbers must be unique. For now, we encode the first two
153 	 * characters into the top byte of the port number. This will work
154 	 * with multiple types of NICs provided that the first two
155 	 * characters are unique.
156 	 */
157 	offset = ((portp->lp_devname[0] + portp->lp_devname[1]) << 8);
158 	instance = inst_num(portp->lp_devname);
159 	/* actor port # */
160 	pl->ActorPortNumber = offset + instance + portp->lp_port;
161 	AGGR_LACP_DBG(("aggr_lacp_init_port(%s/%d): "
162 	    "ActorPortNumber = 0x%x\n", portp->lp_devname,
163 	    portp->lp_port, pl->ActorPortNumber));
164 
165 	pl->ActorPortPriority = (uint16_t)lacp_port_priority;
166 	pl->ActorPortAggrId = 0;	/* aggregator id - not used */
167 	pl->NTT = B_FALSE;			/* need to transmit */
168 
169 	pl->ActorAdminPortKey = aggrp->lg_key;
170 	pl->ActorOperPortKey = pl->ActorAdminPortKey;
171 	AGGR_LACP_DBG(("aggr_lacp_init_port(%s/%d) "
172 	    "ActorAdminPortKey = 0x%x, ActorAdminPortKey = 0x%x\n",
173 	    portp->lp_devname, portp->lp_port, pl->ActorAdminPortKey,
174 	    pl->ActorOperPortKey));
175 
176 	/* Actor admin. port state */
177 	pl->ActorAdminPortState.bit.activity = B_FALSE;
178 	pl->ActorAdminPortState.bit.timeout = B_TRUE;
179 	pl->ActorAdminPortState.bit.aggregation = B_TRUE;
180 	pl->ActorAdminPortState.bit.sync = B_FALSE;
181 	pl->ActorAdminPortState.bit.collecting = B_FALSE;
182 	pl->ActorAdminPortState.bit.distributing = B_FALSE;
183 	pl->ActorAdminPortState.bit.defaulted = B_FALSE;
184 	pl->ActorAdminPortState.bit.expired = B_FALSE;
185 	pl->ActorOperPortState = pl->ActorAdminPortState;
186 
187 	/*
188 	 * Partner Administrative Information
189 	 * (All initialized to zero except for the following)
190 	 * Fast Timeouts.
191 	 */
192 	pl->PartnerAdminPortState.bit.timeout =
193 	    pl->PartnerOperPortState.bit.timeout = B_TRUE;
194 
195 	pl->PartnerCollectorMaxDelay = 0; /* tens of microseconds */
196 
197 	/*
198 	 * State machine information.
199 	 */
200 	pl->sm.lacp_on = B_FALSE;		/* LACP Off default */
201 	pl->sm.begin = B_TRUE;		/* Prevents transmissions */
202 	pl->sm.lacp_enabled = B_FALSE;
203 	pl->sm.port_enabled = B_FALSE;		/* Link Down */
204 	pl->sm.actor_churn = B_FALSE;
205 	pl->sm.partner_churn = B_FALSE;
206 	pl->sm.ready_n = B_FALSE;
207 	pl->sm.selected = AGGR_UNSELECTED;
208 	pl->sm.port_moved = B_FALSE;
209 
210 	pl->sm.periodic_state = LACP_NO_PERIODIC;
211 	pl->sm.receive_state = LACP_INITIALIZE;
212 	pl->sm.mux_state = LACP_DETACHED;
213 	pl->sm.churn_state = LACP_NO_ACTOR_CHURN;
214 
215 	/*
216 	 * Timer information.
217 	 */
218 	pl->current_while_timer.id = 0;
219 	pl->current_while_timer.val = SHORT_TIMEOUT_TIME;
220 
221 	pl->periodic_timer.id = 0;
222 	pl->periodic_timer.val = FAST_PERIODIC_TIME;
223 
224 	pl->wait_while_timer.id = 0;
225 	pl->wait_while_timer.val = AGGREGATE_WAIT_TIME;
226 }
227 
228 /*
229  * Port initialization when we need to
230  * turn LACP on/off, etc. Not everything is
231  * reset like in the above routine.
232  *		Do NOT modify things like link status.
233  */
234 static void
235 lacp_reset_port(aggr_port_t *portp)
236 {
237 	aggr_lacp_port_t *pl = &portp->lp_lacp;
238 
239 	ASSERT(AGGR_LACP_LOCK_HELD(portp->lp_grp));
240 
241 	pl->NTT = B_FALSE;			/* need to transmit */
242 
243 	/* reset operational port state */
244 	pl->ActorOperPortState.bit.timeout =
245 		pl->ActorAdminPortState.bit.timeout;
246 
247 	pl->ActorOperPortState.bit.sync = B_FALSE;
248 	pl->ActorOperPortState.bit.collecting = B_FALSE;
249 	pl->ActorOperPortState.bit.distributing = B_FALSE;
250 	pl->ActorOperPortState.bit.defaulted = B_TRUE;
251 	pl->ActorOperPortState.bit.expired = B_FALSE;
252 
253 	pl->PartnerOperPortState.bit.timeout = B_TRUE;	/* fast t/o */
254 	pl->PartnerCollectorMaxDelay = 0; /* tens of microseconds */
255 
256 	/*
257 	 * State machine information.
258 	 */
259 	pl->sm.begin = B_TRUE;		/* Prevents transmissions */
260 	pl->sm.actor_churn = B_FALSE;
261 	pl->sm.partner_churn = B_FALSE;
262 	pl->sm.ready_n = B_FALSE;
263 	pl->sm.selected = AGGR_UNSELECTED;
264 
265 	pl->sm.periodic_state = LACP_NO_PERIODIC;
266 	pl->sm.receive_state = LACP_INITIALIZE;
267 	pl->sm.mux_state = LACP_DETACHED;
268 	pl->sm.churn_state = LACP_NO_ACTOR_CHURN;
269 
270 	/*
271 	 * Timer information.
272 	 */
273 	pl->current_while_timer.val = SHORT_TIMEOUT_TIME;
274 	pl->periodic_timer.val = FAST_PERIODIC_TIME;
275 }
276 
277 static void
278 aggr_lacp_mcast_on(aggr_port_t *port)
279 {
280 	ASSERT(AGGR_LACP_LOCK_HELD(port->lp_grp));
281 	ASSERT(RW_WRITE_HELD(&port->lp_lock));
282 
283 	if (port->lp_state != AGGR_PORT_STATE_ATTACHED)
284 		return;
285 
286 	(void) aggr_port_multicst(port, B_TRUE,
287 	    (uchar_t *)&slow_multicast_addr);
288 }
289 
290 static void
291 aggr_lacp_mcast_off(aggr_port_t *port)
292 {
293 	ASSERT(AGGR_LACP_LOCK_HELD(port->lp_grp));
294 	ASSERT(RW_WRITE_HELD(&port->lp_lock));
295 
296 	if (port->lp_state != AGGR_PORT_STATE_ATTACHED)
297 		return;
298 
299 	(void) aggr_port_multicst(port, B_FALSE,
300 	    (uchar_t *)&slow_multicast_addr);
301 }
302 
303 static void
304 start_periodic_timer(aggr_port_t *portp)
305 {
306 	ASSERT(AGGR_LACP_LOCK_HELD(portp->lp_grp));
307 
308 	if (portp->lp_lacp.periodic_timer.id == 0) {
309 		portp->lp_lacp.periodic_timer.id =
310 		    timeout(periodic_timer_pop, portp,
311 		    drv_usectohz(1000000 * portp->lp_lacp.periodic_timer.val));
312 	}
313 }
314 
315 static void
316 stop_periodic_timer(aggr_port_t *portp)
317 {
318 	ASSERT(AGGR_LACP_LOCK_HELD(portp->lp_grp));
319 
320 	if (portp->lp_lacp.periodic_timer.id != 0) {
321 		AGGR_LACP_UNLOCK(portp->lp_grp);
322 		(void) untimeout(portp->lp_lacp.periodic_timer.id);
323 		AGGR_LACP_LOCK(portp->lp_grp);
324 		portp->lp_lacp.periodic_timer.id = 0;
325 	}
326 }
327 
328 /*
329  * When the timer pops, we arrive here to
330  * clear out LACPDU count as well as transmit an
331  * LACPDU. We then set the periodic state and let
332  * the periodic state machine restart the timer.
333  */
334 
335 static void
336 periodic_timer_pop_locked(aggr_port_t *portp)
337 {
338 	ASSERT(AGGR_LACP_LOCK_HELD(portp->lp_grp));
339 
340 	portp->lp_lacp.periodic_timer.id = NULL;
341 	portp->lp_lacp_stats.LACPDUsTx = 0;
342 
343 	/* current timestamp */
344 	portp->lp_lacp.time = gethrtime();
345 	portp->lp_lacp.NTT = B_TRUE;
346 	lacp_xmit_sm(portp);
347 
348 	/*
349 	 * Set Periodic State machine state based on the
350 	 * value of the Partner Operation Port State timeout
351 	 * bit.
352 	 */
353 	if (portp->lp_lacp.PartnerOperPortState.bit.timeout) {
354 		portp->lp_lacp.periodic_timer.val = FAST_PERIODIC_TIME;
355 		portp->lp_lacp.sm.periodic_state = LACP_FAST_PERIODIC;
356 	} else {
357 		portp->lp_lacp.periodic_timer.val = SLOW_PERIODIC_TIME;
358 		portp->lp_lacp.sm.periodic_state = LACP_SLOW_PERIODIC;
359 	}
360 
361 	lacp_periodic_sm(portp);
362 }
363 
364 static void
365 periodic_timer_pop(void *data)
366 {
367 	aggr_port_t *portp = data;
368 
369 	if (portp->lp_closing)
370 		return;
371 
372 	AGGR_LACP_LOCK(portp->lp_grp);
373 	periodic_timer_pop_locked(portp);
374 	AGGR_LACP_UNLOCK(portp->lp_grp);
375 }
376 
377 /*
378  * Invoked from:
379  *	- startup upon aggregation
380  *	- when the periodic timer pops
381  *	- when the periodic timer value is changed
382  *	- when the port is attached or detached
383  *	- when LACP mode is changed.
384  */
385 static void
386 lacp_periodic_sm(aggr_port_t *portp)
387 {
388 	lacp_periodic_state_t oldstate = portp->lp_lacp.sm.periodic_state;
389 	aggr_lacp_port_t *pl = &portp->lp_lacp;
390 
391 	ASSERT(AGGR_LACP_LOCK_HELD(portp->lp_grp));
392 
393 	/* LACP_OFF state not in specification so check here.  */
394 	if (!pl->sm.lacp_on) {
395 		/* Stop timer whether it is running or not */
396 		stop_periodic_timer(portp);
397 		pl->sm.periodic_state = LACP_NO_PERIODIC;
398 		pl->NTT = B_FALSE;
399 		AGGR_LACP_DBG(("lacp_periodic_sm(%s/%d):NO LACP "
400 		    "%s--->%s\n", portp->lp_devname, portp->lp_port,
401 		    lacp_periodic_str[oldstate],
402 		    lacp_periodic_str[pl->sm.periodic_state]));
403 		return;
404 	}
405 
406 	if (pl->sm.begin || !pl->sm.lacp_enabled ||
407 	    !pl->sm.port_enabled ||
408 	    !pl->ActorOperPortState.bit.activity &&
409 	    !pl->PartnerOperPortState.bit.activity) {
410 
411 		/* Stop timer whether it is running or not */
412 		stop_periodic_timer(portp);
413 		pl->sm.periodic_state = LACP_NO_PERIODIC;
414 		pl->NTT = B_FALSE;
415 		AGGR_LACP_DBG(("lacp_periodic_sm(%s/%d):STOP %s--->%s\n",
416 		    portp->lp_devname, portp->lp_port,
417 		    lacp_periodic_str[oldstate],
418 		    lacp_periodic_str[pl->sm.periodic_state]));
419 		return;
420 	}
421 
422 	/*
423 	 * Startup with FAST_PERIODIC_TIME if no previous LACPDU
424 	 * has been received. Then after we timeout, then it is
425 	 * possible to go to SLOW_PERIODIC_TIME.
426 	 */
427 	if (pl->sm.periodic_state == LACP_NO_PERIODIC) {
428 		pl->periodic_timer.val = FAST_PERIODIC_TIME;
429 		pl->sm.periodic_state = LACP_FAST_PERIODIC;
430 	} else if ((pl->sm.periodic_state == LACP_SLOW_PERIODIC) &&
431 	    pl->PartnerOperPortState.bit.timeout) {
432 		/*
433 		 * If we receive a bit indicating we are going to
434 		 * fast periodic from slow periodic, stop the timer
435 		 * and let the periodic_timer_pop routine deal
436 		 * with reseting the periodic state and transmitting
437 		 * a LACPDU.
438 		 */
439 		stop_periodic_timer(portp);
440 		periodic_timer_pop_locked(portp);
441 	}
442 
443 	/* Rearm timer with value provided by partner */
444 	start_periodic_timer(portp);
445 }
446 
447 /*
448  * This routine transmits an LACPDU if lacp_enabled
449  * is TRUE and if NTT is set.
450  */
451 static void
452 lacp_xmit_sm(aggr_port_t *portp)
453 {
454 	aggr_lacp_port_t *pl = &portp->lp_lacp;
455 	size_t	len;
456 	mblk_t  *mp;
457 	hrtime_t now, elapsed;
458 	const mac_txinfo_t *mtp;
459 
460 	ASSERT(AGGR_LACP_LOCK_HELD(portp->lp_grp));
461 
462 	/* LACP_OFF state not in specification so check here.  */
463 	if (!pl->sm.lacp_on || !pl->NTT || !portp->lp_started)
464 		return;
465 
466 	/*
467 	 * Do nothing if LACP has been turned off or if the
468 	 * periodic state machine is not enabled.
469 	 */
470 	if ((pl->sm.periodic_state == LACP_NO_PERIODIC) ||
471 	    !pl->sm.lacp_enabled || pl->sm.begin) {
472 		pl->NTT = B_FALSE;
473 		return;
474 	}
475 
476 	/*
477 	 * If we have sent 5 Slow packets in the last second, avoid
478 	 * sending any more here. No more than three LACPDUs may be transmitted
479 	 * in any Fast_Periodic_Time interval.
480 	 */
481 	if (portp->lp_lacp_stats.LACPDUsTx >= 3) {
482 		/*
483 		 * Grab the current time value and see if
484 		 * more than 1 second has passed. If so,
485 		 * reset the timestamp and clear the count.
486 		 */
487 		now = gethrtime();
488 		elapsed = now - pl->time;
489 		if (elapsed > NSECS_PER_SEC) {
490 			portp->lp_lacp_stats.LACPDUsTx = 0;
491 			pl->time = now;
492 		} else {
493 			return;
494 		}
495 	}
496 
497 	len = sizeof (lacp_t) + sizeof (struct ether_header);
498 	mp = allocb(len, BPRI_MED);
499 	if (mp == NULL)
500 		return;
501 
502 	mp->b_wptr = mp->b_rptr + len;
503 	bzero(mp->b_rptr, len);
504 
505 	fill_lacp_ether(portp, (struct ether_header *)mp->b_rptr);
506 	fill_lacp_pdu(portp,
507 	    (lacp_t *)(mp->b_rptr + sizeof (struct ether_header)));
508 
509 	/*
510 	 * Store the transmit info pointer locally in case it changes between
511 	 * loading mt_fn and mt_arg.
512 	 */
513 	mtp = portp->lp_txinfo;
514 	mtp->mt_fn(mtp->mt_arg, mp);
515 
516 	pl->NTT = B_FALSE;
517 	portp->lp_lacp_stats.LACPDUsTx++;
518 }
519 
520 /*
521  * Initialize the ethernet header of a LACP packet sent from the specified
522  * port.
523  */
524 static void
525 fill_lacp_ether(aggr_port_t *port, struct ether_header *ether)
526 {
527 	bcopy(port->lp_addr, (uint8_t *)&(ether->ether_shost), ETHERADDRL);
528 	bcopy(&slow_multicast_addr, (uint8_t *)&(ether->ether_dhost),
529 	    ETHERADDRL);
530 	ether->ether_type = htons(ETHERTYPE_SLOW);
531 }
532 
533 static void
534 fill_lacp_pdu(aggr_port_t *portp, lacp_t *lacp)
535 {
536 	aggr_lacp_port_t *pl = &portp->lp_lacp;
537 	aggr_grp_t *aggrp = portp->lp_grp;
538 
539 	ASSERT(AGGR_LACP_LOCK_HELD(portp->lp_grp));
540 
541 	lacp->subtype = LACP_SUBTYPE;
542 	lacp->version = LACP_VERSION;
543 
544 	rw_enter(&aggrp->lg_lock, RW_READER);
545 	rw_enter(&portp->lp_lock, RW_READER);
546 
547 	/*
548 	 * Actor Information
549 	 */
550 	lacp->actor_info.tlv_type = ACTOR_TLV;
551 	lacp->actor_info.information_len = sizeof (link_info_t);
552 	lacp->actor_info.system_priority =
553 	    htons(aggrp->aggr.ActorSystemPriority);
554 	bcopy(aggrp->lg_addr, (uchar_t *)&lacp->actor_info.system_id,
555 	    ETHERADDRL);
556 	lacp->actor_info.key = htons(pl->ActorOperPortKey);
557 	lacp->actor_info.port_priority = htons(pl->ActorPortPriority);
558 	lacp->actor_info.port = htons(pl->ActorPortNumber);
559 	lacp->actor_info.state.state = pl->ActorOperPortState.state;
560 
561 	/*
562 	 * Partner Information
563 	 */
564 	lacp->partner_info.tlv_type = PARTNER_TLV;
565 	lacp->partner_info.information_len = sizeof (link_info_t);
566 	lacp->partner_info.system_priority =
567 	    htons(pl->PartnerOperSysPriority);
568 	lacp->partner_info.system_id = pl->PartnerOperSystem;
569 	lacp->partner_info.key = htons(pl->PartnerOperKey);
570 	lacp->partner_info.port_priority =
571 	    htons(pl->PartnerOperPortPriority);
572 	lacp->partner_info.port = htons(pl->PartnerOperPortNum);
573 	lacp->partner_info.state.state = pl->PartnerOperPortState.state;
574 
575 	/* Collector Information */
576 	lacp->tlv_collector = COLLECTOR_TLV;
577 	lacp->collector_len = 0x10;
578 	lacp->collector_max_delay = htons(aggrp->aggr.CollectorMaxDelay);
579 
580 	/* Termination Information */
581 	lacp->tlv_terminator = TERMINATOR_TLV;
582 	lacp->terminator_len = 0x0;
583 
584 	rw_exit(&portp->lp_lock);
585 	rw_exit(&aggrp->lg_lock);
586 }
587 
588 /*
589  * lacp_mux_sm - LACP mux state machine
590  *		This state machine is invoked from:
591  *			- startup upon aggregation
592  *			- from the Selection logic
593  *			- when the wait_while_timer pops
594  *			- when the aggregation MAC address is changed
595  *			- when receiving DL_NOTE_LINK_UP/DOWN
596  *			- when receiving DL_NOTE_AGGR_AVAIL/UNAVAIL
597  *			- when LACP mode is changed.
598  *			- when a DL_NOTE_SPEED is received
599  */
600 static void
601 lacp_mux_sm(aggr_port_t *portp)
602 {
603 	aggr_grp_t *aggrp = portp->lp_grp;
604 	boolean_t NTT_updated = B_FALSE;
605 	aggr_lacp_port_t *pl = &portp->lp_lacp;
606 	lacp_mux_state_t oldstate = pl->sm.mux_state;
607 
608 	ASSERT(AGGR_LACP_LOCK_HELD(aggrp));
609 
610 	/* LACP_OFF state not in specification so check here.  */
611 	if (!pl->sm.lacp_on) {
612 		pl->sm.mux_state = LACP_DETACHED;
613 		pl->ActorOperPortState.bit.sync = B_FALSE;
614 
615 		if (pl->ActorOperPortState.bit.collecting ||
616 		    pl->ActorOperPortState.bit.distributing) {
617 			AGGR_LACP_DBG(("trunk link: (%s/%d): "
618 			    "Collector_Distributor Disabled.\n",
619 			    portp->lp_devname, portp->lp_port));
620 		}
621 
622 		pl->ActorOperPortState.bit.collecting =
623 		    pl->ActorOperPortState.bit.distributing = B_FALSE;
624 		return;
625 	}
626 
627 	if (pl->sm.begin || !pl->sm.lacp_enabled)
628 		pl->sm.mux_state = LACP_DETACHED;
629 
630 	/* determine next state, or return if state unchanged */
631 	switch (pl->sm.mux_state) {
632 	case LACP_DETACHED:
633 		if (pl->sm.begin) {
634 			break;
635 		}
636 
637 		if ((pl->sm.selected == AGGR_SELECTED) ||
638 		    (pl->sm.selected == AGGR_STANDBY)) {
639 			pl->sm.mux_state = LACP_WAITING;
640 			break;
641 		}
642 		return;
643 
644 	case LACP_WAITING:
645 		if (pl->sm.selected == AGGR_UNSELECTED) {
646 			pl->sm.mux_state = LACP_DETACHED;
647 			break;
648 		}
649 
650 		if ((pl->sm.selected == AGGR_SELECTED) && aggrp->aggr.ready) {
651 			pl->sm.mux_state = LACP_ATTACHED;
652 			break;
653 		}
654 		return;
655 
656 	case LACP_ATTACHED:
657 		if ((pl->sm.selected == AGGR_UNSELECTED) ||
658 		    (pl->sm.selected == AGGR_STANDBY)) {
659 			pl->sm.mux_state = LACP_DETACHED;
660 			break;
661 		}
662 
663 		if ((pl->sm.selected == AGGR_SELECTED) &&
664 		    pl->PartnerOperPortState.bit.sync) {
665 			pl->sm.mux_state = LACP_COLLECTING_DISTRIBUTING;
666 			break;
667 		}
668 		return;
669 
670 	case LACP_COLLECTING_DISTRIBUTING:
671 		if ((pl->sm.selected == AGGR_UNSELECTED) ||
672 		    (pl->sm.selected == AGGR_STANDBY) ||
673 		    !pl->PartnerOperPortState.bit.sync) {
674 			pl->sm.mux_state = LACP_ATTACHED;
675 			break;
676 		}
677 		return;
678 	}
679 
680 	AGGR_LACP_DBG(("lacp_mux_sm(%s/%d):%s--->%s\n",
681 	    portp->lp_devname, portp->lp_port, lacp_mux_str[oldstate],
682 	    lacp_mux_str[pl->sm.mux_state]));
683 
684 	/* perform actions on entering a new state */
685 	switch (pl->sm.mux_state) {
686 	case LACP_DETACHED:
687 		if (pl->ActorOperPortState.bit.collecting ||
688 		    pl->ActorOperPortState.bit.distributing) {
689 			AGGR_LACP_DBG(("trunk link: (%s/%d): "
690 			    "Collector_Distributor Disabled.\n",
691 			    portp->lp_devname, portp->lp_port));
692 		}
693 
694 		pl->ActorOperPortState.bit.sync =
695 		    pl->ActorOperPortState.bit.collecting = B_FALSE;
696 
697 		/* Turn OFF Collector_Distributor */
698 		aggr_set_coll_dist(portp, B_FALSE);
699 
700 		pl->ActorOperPortState.bit.distributing = B_FALSE;
701 		NTT_updated = B_TRUE;
702 		break;
703 
704 	case LACP_WAITING:
705 		start_wait_while_timer(portp);
706 		break;
707 
708 	case LACP_ATTACHED:
709 		if (pl->ActorOperPortState.bit.collecting ||
710 		    pl->ActorOperPortState.bit.distributing) {
711 			AGGR_LACP_DBG(("trunk link: (%s%d): "
712 			    "Collector_Distributor Disabled.\n",
713 			    portp->lp_devname, portp->lp_port));
714 		}
715 
716 		pl->ActorOperPortState.bit.sync = B_TRUE;
717 		pl->ActorOperPortState.bit.collecting = B_FALSE;
718 
719 		/* Turn OFF Collector_Distributor */
720 		aggr_set_coll_dist(portp, B_FALSE);
721 
722 		pl->ActorOperPortState.bit.distributing = B_FALSE;
723 		NTT_updated = B_TRUE;
724 		break;
725 
726 	case LACP_COLLECTING_DISTRIBUTING:
727 		if (!pl->ActorOperPortState.bit.collecting &&
728 		    !pl->ActorOperPortState.bit.distributing) {
729 			AGGR_LACP_DBG(("trunk link: (%s/%d): "
730 			    "Collector_Distributor Enabled.\n",
731 			    portp->lp_devname, portp->lp_port));
732 		}
733 		pl->ActorOperPortState.bit.distributing = B_TRUE;
734 
735 		/* Turn Collector_Distributor back ON */
736 		aggr_set_coll_dist(portp, B_TRUE);
737 
738 		pl->ActorOperPortState.bit.collecting = B_TRUE;
739 		NTT_updated = B_TRUE;
740 		break;
741 	}
742 
743 	/*
744 	 * If we updated the state of the NTT variable, then
745 	 * initiate a LACPDU transmission.
746 	 */
747 	if (NTT_updated) {
748 		pl->NTT = B_TRUE;
749 		lacp_xmit_sm(portp);
750 	}
751 } /* lacp_mux_sm */
752 
753 
754 static void
755 receive_marker_pdu(aggr_port_t *portp, mblk_t *mp)
756 {
757 	marker_pdu_t		*markerp = (marker_pdu_t *)mp->b_rptr;
758 	const mac_txinfo_t	*mtp;
759 
760 	AGGR_LACP_LOCK(portp->lp_grp);
761 
762 	AGGR_LACP_DBG(("trunk link: (%s/%d): MARKER PDU received:\n",
763 	    portp->lp_devname, portp->lp_port));
764 
765 	/* LACP_OFF state not in specification so check here.  */
766 	if (!portp->lp_lacp.sm.lacp_on)
767 		goto bail;
768 
769 	if (MBLKL(mp) < sizeof (marker_pdu_t))
770 		goto bail;
771 
772 	if (markerp->version != MARKER_VERSION) {
773 		AGGR_LACP_DBG(("trunk link (%s/%d): Malformed MARKER PDU: "
774 		    "version = %d does not match s/w version %d\n",
775 		    portp->lp_devname, portp->lp_port,
776 		    markerp->version, MARKER_VERSION));
777 		goto bail;
778 	}
779 
780 	if (markerp->tlv_marker == MARKER_RESPONSE_TLV) {
781 		/* We do not yet send out MARKER info PDUs */
782 		AGGR_LACP_DBG(("trunk link (%s/%d): MARKER RESPONSE PDU: "
783 		    " MARKER TLV = %d - We don't send out info type!\n",
784 		    portp->lp_devname, portp->lp_port,
785 		    markerp->tlv_marker));
786 		goto bail;
787 	}
788 
789 	if (markerp->tlv_marker != MARKER_INFO_TLV) {
790 		AGGR_LACP_DBG(("trunk link (%s/%d): Malformed MARKER PDU: "
791 		    " MARKER TLV = %d \n", portp->lp_devname, portp->lp_port,
792 		    markerp->tlv_marker));
793 		goto bail;
794 	}
795 
796 	if (markerp->marker_len != MARKER_INFO_RESPONSE_LENGTH) {
797 		AGGR_LACP_DBG(("trunk link (%s/%d): Malformed MARKER PDU: "
798 		    " MARKER length = %d \n", portp->lp_devname, portp->lp_port,
799 		    markerp->marker_len));
800 		goto bail;
801 	}
802 
803 	if (markerp->requestor_port != portp->lp_lacp.PartnerOperPortNum) {
804 		AGGR_LACP_DBG(("trunk link (%s/%d): MARKER PDU: "
805 		    " MARKER Port %d not equal to Partner port %d\n",
806 		    portp->lp_devname, portp->lp_port,
807 		    markerp->requestor_port,
808 		    portp->lp_lacp.PartnerOperPortNum));
809 		goto bail;
810 	}
811 
812 	if (ether_cmp(&markerp->system_id,
813 	    &portp->lp_lacp.PartnerOperSystem) != 0) {
814 		AGGR_LACP_DBG(("trunk link (%s/%d): MARKER PDU: "
815 		    " MARKER MAC not equal to Partner MAC\n",
816 		    portp->lp_devname, portp->lp_port));
817 		goto bail;
818 	}
819 
820 	/*
821 	 * Turn into Marker Response PDU
822 	 * and return mblk to sending system
823 	 */
824 	markerp->tlv_marker = MARKER_RESPONSE_TLV;
825 
826 	/* reuse the space that was used by received ethernet header */
827 	ASSERT(MBLKHEAD(mp) >= sizeof (struct ether_header));
828 	mp->b_rptr -= sizeof (struct ether_header);
829 	fill_lacp_ether(portp, (struct ether_header *)mp->b_rptr);
830 	AGGR_LACP_UNLOCK(portp->lp_grp);
831 
832 	/*
833 	 * Store the transmit info pointer locally in case it changes between
834 	 * loading mt_fn and mt_arg.
835 	 */
836 	mtp = portp->lp_txinfo;
837 	mtp->mt_fn(mtp->mt_arg, mp);
838 	return;
839 
840 bail:
841 	AGGR_LACP_UNLOCK(portp->lp_grp);
842 	freemsg(mp);
843 }
844 
845 
846 /*
847  * Update the LACP mode (off, active, or passive) of the specified group.
848  */
849 void
850 aggr_lacp_update_mode(aggr_grp_t *grp, aggr_lacp_mode_t mode)
851 {
852 	aggr_lacp_mode_t old_mode = grp->lg_lacp_mode;
853 	aggr_port_t *port;
854 
855 	ASSERT(AGGR_LACP_LOCK_HELD(grp));
856 	ASSERT(RW_WRITE_HELD(&grp->lg_lock));
857 
858 	if (mode == old_mode)
859 		return;
860 
861 	grp->lg_lacp_mode = mode;
862 
863 	for (port = grp->lg_ports; port != NULL; port = port->lp_next) {
864 		port->lp_lacp.ActorAdminPortState.bit.activity =
865 		    port->lp_lacp.ActorOperPortState.bit.activity =
866 		    (mode == AGGR_LACP_ACTIVE);
867 
868 		if (old_mode == AGGR_LACP_OFF) {
869 			/* OFF -> {PASSIVE,ACTIVE} */
870 			/* turn OFF Collector_Distributor */
871 			aggr_set_coll_dist(port, B_FALSE);
872 			rw_enter(&port->lp_lock, RW_WRITER);
873 			lacp_on(port);
874 			if (port->lp_state == AGGR_PORT_STATE_ATTACHED)
875 				aggr_lacp_port_attached(port);
876 			rw_exit(&port->lp_lock);
877 		} else if (mode == AGGR_LACP_OFF) {
878 			/* {PASSIVE,ACTIVE} -> OFF */
879 			rw_enter(&port->lp_lock, RW_WRITER);
880 			lacp_off(port);
881 			rw_exit(&port->lp_lock);
882 			if (!grp->lg_closing) {
883 				/* Turn ON Collector_Distributor */
884 				aggr_set_coll_dist(port, B_TRUE);
885 			}
886 		} else {
887 			/* PASSIVE->ACTIVE or ACTIVE->PASSIVE */
888 			port->lp_lacp.sm.begin = B_TRUE;
889 			lacp_mux_sm(port);
890 			lacp_periodic_sm(port);
891 
892 			/* kick off state machines */
893 			lacp_receive_sm(port, NULL);
894 			lacp_mux_sm(port);
895 		}
896 
897 		if (grp->lg_closing)
898 			break;
899 	}
900 }
901 
902 
903 /*
904  * Update the LACP timer (short or long) of the specified group.
905  */
906 void
907 aggr_lacp_update_timer(aggr_grp_t *grp, aggr_lacp_timer_t timer)
908 {
909 	aggr_port_t *port;
910 
911 	ASSERT(AGGR_LACP_LOCK_HELD(grp));
912 	ASSERT(RW_WRITE_HELD(&grp->lg_lock));
913 
914 	if (timer == grp->aggr.PeriodicTimer)
915 		return;
916 
917 	grp->aggr.PeriodicTimer = timer;
918 
919 	for (port = grp->lg_ports; port != NULL; port = port->lp_next) {
920 		port->lp_lacp.ActorAdminPortState.bit.timeout =
921 		    port->lp_lacp.ActorOperPortState.bit.timeout =
922 		    (timer == AGGR_LACP_TIMER_SHORT);
923 	}
924 }
925 
926 
927 /*
928  * Sets the initial LACP mode (off, active, passive) and LACP timer
929  * (short, long) of the specified group.
930  */
931 void
932 aggr_lacp_set_mode(aggr_grp_t *grp, aggr_lacp_mode_t mode,
933     aggr_lacp_timer_t timer)
934 {
935 	aggr_port_t *port;
936 
937 	ASSERT(AGGR_LACP_LOCK_HELD(grp));
938 	ASSERT(RW_WRITE_HELD(&grp->lg_lock));
939 
940 	grp->lg_lacp_mode = mode;
941 	grp->aggr.PeriodicTimer = timer;
942 
943 	for (port = grp->lg_ports; port != NULL; port = port->lp_next) {
944 		port->lp_lacp.ActorAdminPortState.bit.activity =
945 		    port->lp_lacp.ActorOperPortState.bit.activity =
946 		    (mode == AGGR_LACP_ACTIVE);
947 
948 		port->lp_lacp.ActorAdminPortState.bit.timeout =
949 			port->lp_lacp.ActorOperPortState.bit.timeout =
950 			(timer == AGGR_LACP_TIMER_SHORT);
951 
952 		if (grp->lg_lacp_mode == AGGR_LACP_OFF) {
953 			/* Turn ON Collector_Distributor */
954 			aggr_set_coll_dist(port, B_TRUE);
955 		} else { /* LACP_ACTIVE/PASSIVE */
956 			rw_enter(&port->lp_lock, RW_WRITER);
957 			lacp_on(port);
958 			rw_exit(&port->lp_lock);
959 		}
960 	}
961 }
962 
963 static void
964 lacp_misconfig_walker(aggr_grp_t *grp, void *arg)
965 {
966 	lacp_misconfig_check_state_t *state = arg;
967 	aggr_port_t *port = state->cs_portp;
968 	aggr_port_t *cport;
969 
970 	if (state->cs_found)
971 		return;
972 
973 	if (grp == state->cs_portp->lp_grp)
974 		return;
975 
976 	AGGR_LACP_LOCK(grp);
977 	rw_enter(&grp->lg_lock, RW_READER);
978 
979 	for (cport = grp->lg_ports; cport != NULL; cport = cport->lp_next) {
980 		if ((ether_cmp(&port->lp_lacp.PartnerOperSystem,
981 		    &grp->aggr.PartnerSystem) == 0) &&
982 		    (port->lp_lacp.PartnerOperKey ==
983 		    grp->aggr.PartnerOperAggrKey)) {
984 			/*
985 			 * The Partner port information is already in use
986 			 * by ports in another aggregation so disable this
987 			 * port.
988 			 */
989 			port->lp_lacp.sm.selected = AGGR_UNSELECTED;
990 			cmn_err(CE_NOTE, "aggr: (%s/%d): Port Partner "
991 			    "MAC and key (%d) in use on aggregation "
992 			    "key (%d)\n",
993 			    port->lp_devname, port->lp_port,
994 			    port->lp_lacp.PartnerOperKey,
995 			    grp->aggr.PartnerOperAggrKey);
996 			state->cs_found = B_TRUE;
997 			break;
998 		}
999 	}
1000 
1001 	rw_exit(&grp->lg_lock);
1002 	AGGR_LACP_UNLOCK(grp);
1003 }
1004 
1005 /*
1006  * Verify that the Partner MAC and Key recorded by the specified
1007  * port are not found in other ports that are not part of our
1008  * aggregation. Returns B_TRUE if such a port is found, B_FALSE
1009  * otherwise.
1010  */
1011 static boolean_t
1012 lacp_misconfig_check(aggr_port_t *portp)
1013 {
1014 	lacp_misconfig_check_state_t state;
1015 
1016 	ASSERT(AGGR_LACP_LOCK_HELD(portp->lp_grp));
1017 
1018 	state.cs_portp = portp;
1019 	state.cs_found = B_FALSE;
1020 
1021 	aggr_grp_walk(lacp_misconfig_walker, &state);
1022 
1023 	return (state.cs_found);
1024 }
1025 
1026 
1027 /*
1028  * lacp_selection_logic - LACP selection logic
1029  *		Sets the selected variable on a per port basis
1030  *		and sets Ready when all waiting ports are ready
1031  *		to go online.
1032  *
1033  * parameters:
1034  *      - portp - instance this applies to.
1035  *
1036  * invoked:
1037  *    - when initialization is needed
1038  *    - when UNSELECTED is set from the lacp_receive_sm() in LACP_CURRENT state
1039  *    - When the lacp_receive_sm goes to the LACP_DEFAULTED state
1040  *    - every time the wait_while_timer pops
1041  *    - everytime we turn LACP on/off
1042  */
1043 static void
1044 lacp_selection_logic(aggr_port_t *portp)
1045 {
1046 	aggr_port_t *tpp;
1047 	aggr_grp_t *aggrp = portp->lp_grp;
1048 	int ports_waiting;
1049 	boolean_t reset_mac = B_FALSE;
1050 	aggr_lacp_port_t *pl = &portp->lp_lacp;
1051 
1052 	ASSERT(AGGR_LACP_LOCK_HELD(aggrp));
1053 
1054 	/* LACP_OFF state not in specification so check here.  */
1055 	if (!pl->sm.lacp_on) {
1056 		pl->sm.selected = AGGR_UNSELECTED;
1057 		aggrp->aggr.ready = B_FALSE;
1058 		lacp_mux_sm(portp);
1059 		return;
1060 	}
1061 
1062 	if (pl->sm.begin || !pl->sm.lacp_enabled ||
1063 	    (portp->lp_state != AGGR_PORT_STATE_ATTACHED)) {
1064 
1065 		AGGR_LACP_DBG(("lacp_selection_logic:(%s/%d): "
1066 		    "selected %d-->%d (begin=%d, lacp_enabled = %d, "
1067 		    "lp_state=%d)\n", portp->lp_devname, portp->lp_port,
1068 		    pl->sm.selected, AGGR_UNSELECTED,
1069 		    pl->sm.begin, pl->sm.lacp_enabled,
1070 		    portp->lp_state));
1071 
1072 		pl->sm.selected = AGGR_UNSELECTED;
1073 		aggrp->aggr.ready = B_FALSE;
1074 		lacp_mux_sm(portp);
1075 		return;
1076 	}
1077 
1078 	/*
1079 	 * If LACP is not enabled then selected is never set.
1080 	 */
1081 	if (!pl->sm.lacp_enabled) {
1082 		AGGR_LACP_DBG(("lacp_selection_logic:(%s/%d): "
1083 		    "selected %d-->%d\n", portp->lp_devname, portp->lp_port,
1084 		    pl->sm.selected, AGGR_UNSELECTED));
1085 
1086 		pl->sm.selected = AGGR_UNSELECTED;
1087 		lacp_mux_sm(portp);
1088 		return;
1089 	}
1090 
1091 	/*
1092 	 * Check if the Partner MAC or Key are zero. If so, we have
1093 	 * not received any LACP info or it has expired and the
1094 	 * receive machine is in the LACP_DEFAULTED state.
1095 	 */
1096 	if (ether_cmp(&pl->PartnerOperSystem, &etherzeroaddr) == 0 ||
1097 	    (pl->PartnerOperKey == 0)) {
1098 
1099 		for (tpp = aggrp->lg_ports; tpp; tpp = tpp->lp_next) {
1100 			if (ether_cmp(&tpp->lp_lacp.PartnerOperSystem,
1101 			    &etherzeroaddr) != 0 &&
1102 			    (tpp->lp_lacp.PartnerOperKey != 0))
1103 				break;
1104 		}
1105 
1106 		/*
1107 		 * If all ports have no key or aggregation address,
1108 		 * then clear the negotiated Partner MAC and key.
1109 		 */
1110 		if (tpp == NULL) {
1111 			/* Clear the aggregation Partner MAC and key */
1112 			aggrp->aggr.PartnerSystem = etherzeroaddr;
1113 			aggrp->aggr.PartnerOperAggrKey = 0;
1114 		}
1115 
1116 		return;
1117 	}
1118 
1119 	/*
1120 	 * Insure that at least one port in the aggregation
1121 	 * matches the Partner aggregation MAC and key. If not,
1122 	 * then clear the aggregation MAC and key. Later we will
1123 	 * set the Partner aggregation MAC and key to that of the
1124 	 * current port's Partner MAC and key.
1125 	 */
1126 	if (ether_cmp(&pl->PartnerOperSystem,
1127 	    &aggrp->aggr.PartnerSystem) != 0 ||
1128 	    (pl->PartnerOperKey != aggrp->aggr.PartnerOperAggrKey)) {
1129 
1130 		for (tpp = aggrp->lg_ports; tpp; tpp = tpp->lp_next) {
1131 			if (ether_cmp(&tpp->lp_lacp.PartnerOperSystem,
1132 			    &aggrp->aggr.PartnerSystem) == 0 &&
1133 			    (tpp->lp_lacp.PartnerOperKey ==
1134 			    aggrp->aggr.PartnerOperAggrKey))
1135 				break;
1136 		}
1137 
1138 		if (tpp == NULL) {
1139 			/* Clear the aggregation Partner MAC and key */
1140 			aggrp->aggr.PartnerSystem = etherzeroaddr;
1141 			aggrp->aggr.PartnerOperAggrKey = 0;
1142 			reset_mac = B_TRUE;
1143 		}
1144 	}
1145 
1146 	/*
1147 	 * If our Actor MAC is found in the Partner MAC
1148 	 * on this port then we have a loopback misconfiguration.
1149 	 */
1150 	if (ether_cmp(&pl->PartnerOperSystem,
1151 	    (struct ether_addr *)&aggrp->lg_addr) == 0) {
1152 		pl->sm.selected = AGGR_UNSELECTED;
1153 		cmn_err(CE_NOTE, "trunk link: (%s/%d): Loopback condition.\n",
1154 		    portp->lp_devname, portp->lp_port);
1155 
1156 		lacp_mux_sm(portp);
1157 		return;
1158 	}
1159 
1160 	/*
1161 	 * If our Partner MAC and Key are found on any other
1162 	 * ports that are not in our aggregation, we have
1163 	 * a misconfiguration.
1164 	 */
1165 	if (lacp_misconfig_check(portp)) {
1166 		lacp_mux_sm(portp);
1167 		return;
1168 	}
1169 
1170 	/*
1171 	 * If the Aggregation Partner MAC and Key have not been
1172 	 * set, then this is either the first port or the aggregation
1173 	 * MAC and key have been reset. In either case we must set
1174 	 * the values of the Partner MAC and key.
1175 	 */
1176 	if (ether_cmp(&aggrp->aggr.PartnerSystem, &etherzeroaddr) == 0 &&
1177 	    (aggrp->aggr.PartnerOperAggrKey == 0)) {
1178 		/* Set aggregation Partner MAC and key */
1179 		aggrp->aggr.PartnerSystem = pl->PartnerOperSystem;
1180 		aggrp->aggr.PartnerOperAggrKey = pl->PartnerOperKey;
1181 
1182 		/*
1183 		 * If we reset Partner aggregation MAC, then restart
1184 		 * selection_logic on ports that match new MAC address.
1185 		 */
1186 		if (reset_mac) {
1187 			for (tpp = aggrp->lg_ports; tpp; tpp =
1188 			    tpp->lp_next) {
1189 				if (tpp == portp)
1190 					continue;
1191 				if (ether_cmp(&tpp->lp_lacp.PartnerOperSystem,
1192 				    &aggrp->aggr.PartnerSystem) == 0 &&
1193 				    (tpp->lp_lacp.PartnerOperKey ==
1194 				    aggrp->aggr.PartnerOperAggrKey))
1195 					lacp_selection_logic(tpp);
1196 			}
1197 		}
1198 	} else if (ether_cmp(&pl->PartnerOperSystem,
1199 	    &aggrp->aggr.PartnerSystem) != 0 ||
1200 	    (pl->PartnerOperKey != aggrp->aggr.PartnerOperAggrKey)) {
1201 		/*
1202 		 * The Partner port information does not match
1203 		 * that of the other ports in the aggregation
1204 		 * so disable this port.
1205 		 */
1206 		pl->sm.selected = AGGR_UNSELECTED;
1207 		cmn_err(CE_NOTE, "trunk link: (%s/%d): Port Partner MAC or"
1208 		    " key (%d) incompatible with Aggregation Partner "
1209 		    "MAC or key (%d)\n",
1210 		    portp->lp_devname, portp->lp_port,
1211 		    pl->PartnerOperKey, aggrp->aggr.PartnerOperAggrKey);
1212 
1213 		lacp_mux_sm(portp);
1214 		return;
1215 	}
1216 
1217 	/* If we get to here, automatically set selected */
1218 	if (pl->sm.selected != AGGR_SELECTED) {
1219 		AGGR_LACP_DBG(("lacp_selection_logic:(%s/%d): "
1220 		    "selected %d-->%d\n", portp->lp_devname, portp->lp_port,
1221 		    pl->sm.selected, AGGR_SELECTED));
1222 
1223 		pl->sm.selected = AGGR_SELECTED;
1224 		lacp_mux_sm(portp);
1225 	}
1226 
1227 	/*
1228 	 * From this point onward we have selected the port
1229 	 * and are simply checking if the Ready flag should
1230 	 * be set.
1231 	 */
1232 
1233 	/*
1234 	 * If at least two ports are waiting to aggregate
1235 	 * and ready_n is set on all ports waiting to aggregate
1236 	 * then set READY for the aggregation.
1237 	 */
1238 
1239 	ports_waiting = 0;
1240 
1241 	if (!aggrp->aggr.ready) {
1242 		/*
1243 		 * If all ports in the aggregation have received compatible
1244 		 * partner information and they match up correctly with the
1245 		 * switch, there is no need to wait for all the
1246 		 * wait_while_timers to pop.
1247 		 */
1248 		for (tpp = aggrp->lg_ports; tpp; tpp = tpp->lp_next) {
1249 			if (((tpp->lp_lacp.sm.mux_state == LACP_WAITING) ||
1250 			    tpp->lp_lacp.sm.begin) &&
1251 			    !pl->PartnerOperPortState.bit.sync) {
1252 				/* Add up ports uninitialized or waiting */
1253 				ports_waiting++;
1254 				if (!tpp->lp_lacp.sm.ready_n)
1255 					return;
1256 			}
1257 		}
1258 	}
1259 
1260 	if (aggrp->aggr.ready) {
1261 		AGGR_LACP_DBG(("lacp_selection_logic:(%s/%d): "
1262 		    "aggr.ready already set\n", portp->lp_devname,
1263 		    portp->lp_port));
1264 		lacp_mux_sm(portp);
1265 	} else {
1266 		AGGR_LACP_DBG(("lacp_selection_logic:(%s/%d): Ready %d-->%d\n",
1267 		    portp->lp_devname, portp->lp_port, aggrp->aggr.ready,
1268 		    B_TRUE));
1269 		aggrp->aggr.ready = B_TRUE;
1270 
1271 		for (tpp = aggrp->lg_ports; tpp; tpp = tpp->lp_next)
1272 			lacp_mux_sm(tpp);
1273 	}
1274 
1275 }
1276 
1277 /*
1278  * wait_while_timer_pop - When the timer pops, we arrive here to
1279  *			set ready_n and trigger the selection logic.
1280  */
1281 static void
1282 wait_while_timer_pop(void *data)
1283 {
1284 	aggr_port_t *portp = data;
1285 
1286 	if (portp->lp_closing)
1287 		return;
1288 
1289 	AGGR_LACP_LOCK(portp->lp_grp);
1290 
1291 	AGGR_LACP_DBG(("trunk link:(%s/%d): wait_while_timer pop \n",
1292 	    portp->lp_devname, portp->lp_port));
1293 	portp->lp_lacp.wait_while_timer.id = 0;
1294 	portp->lp_lacp.sm.ready_n = B_TRUE;
1295 
1296 	lacp_selection_logic(portp);
1297 	AGGR_LACP_UNLOCK(portp->lp_grp);
1298 }
1299 
1300 static void
1301 start_wait_while_timer(aggr_port_t *portp)
1302 {
1303 	ASSERT(AGGR_LACP_LOCK_HELD(portp->lp_grp));
1304 
1305 	if (portp->lp_lacp.wait_while_timer.id == 0) {
1306 		portp->lp_lacp.wait_while_timer.id =
1307 		    timeout(wait_while_timer_pop, portp,
1308 		    drv_usectohz(1000000 *
1309 		    portp->lp_lacp.wait_while_timer.val));
1310 	}
1311 }
1312 
1313 
1314 static void
1315 stop_wait_while_timer(portp)
1316 aggr_port_t *portp;
1317 {
1318 	ASSERT(AGGR_LACP_LOCK_HELD(portp->lp_grp));
1319 
1320 	if (portp->lp_lacp.wait_while_timer.id != 0) {
1321 		AGGR_LACP_UNLOCK(portp->lp_grp);
1322 		(void) untimeout(portp->lp_lacp.wait_while_timer.id);
1323 		AGGR_LACP_LOCK(portp->lp_grp);
1324 		portp->lp_lacp.wait_while_timer.id = 0;
1325 	}
1326 }
1327 
1328 /*
1329  * Invoked when a port has been attached to a group.
1330  * Complete the processing that couldn't be finished from lacp_on()
1331  * because the port was not started. We know that the link is full
1332  * duplex and ON, otherwise it wouldn't be attached.
1333  */
1334 void
1335 aggr_lacp_port_attached(aggr_port_t *portp)
1336 {
1337 	aggr_grp_t *grp = portp->lp_grp;
1338 	aggr_lacp_port_t *pl = &portp->lp_lacp;
1339 
1340 	ASSERT(AGGR_LACP_LOCK_HELD(grp));
1341 	ASSERT(portp->lp_state == AGGR_PORT_STATE_ATTACHED);
1342 	ASSERT(RW_WRITE_HELD(&portp->lp_lock));
1343 
1344 	AGGR_LACP_DBG(("aggr_lacp_port_attached: "
1345 	    "port %s/%d\n", portp->lp_devname, portp->lp_port));
1346 
1347 	portp->lp_lacp.sm.port_enabled = B_TRUE;	/* link on */
1348 
1349 	if (grp->lg_lacp_mode == AGGR_LACP_OFF) {
1350 		pl->ActorAdminPortState.bit.activity =
1351 		    pl->ActorOperPortState.bit.activity = B_FALSE;
1352 
1353 		/* Turn ON Collector_Distributor */
1354 		aggr_set_coll_dist_locked(portp, B_TRUE);
1355 
1356 		return;
1357 	}
1358 
1359 	pl->ActorAdminPortState.bit.activity =
1360 	    pl->ActorOperPortState.bit.activity =
1361 	    (grp->lg_lacp_mode == AGGR_LACP_ACTIVE);
1362 
1363 	pl->ActorAdminPortState.bit.timeout =
1364 	    pl->ActorOperPortState.bit.timeout =
1365 	    (grp->aggr.PeriodicTimer == AGGR_LACP_TIMER_SHORT);
1366 
1367 	pl->sm.lacp_enabled = B_TRUE;
1368 	pl->ActorOperPortState.bit.aggregation = B_TRUE;
1369 	pl->sm.begin = B_TRUE;
1370 
1371 	if (!pl->sm.lacp_on) {
1372 		/* Turn OFF Collector_Distributor */
1373 		aggr_set_coll_dist_locked(portp, B_FALSE);
1374 
1375 		lacp_on(portp);
1376 	} else {
1377 		lacp_receive_sm(portp, NULL);
1378 		lacp_mux_sm(portp);
1379 
1380 		/* Enable Multicast Slow Protocol address */
1381 		aggr_lacp_mcast_on(portp);
1382 
1383 		/* periodic_sm is started up from the receive machine */
1384 		lacp_selection_logic(portp);
1385 	}
1386 }
1387 
1388 /*
1389  * Invoked when a port has been detached from a group. Turn off
1390  * LACP processing if it was enabled.
1391  */
1392 void
1393 aggr_lacp_port_detached(aggr_port_t *portp)
1394 {
1395 	aggr_grp_t *grp = portp->lp_grp;
1396 
1397 	ASSERT(AGGR_LACP_LOCK_HELD(grp));
1398 	ASSERT(RW_WRITE_HELD(&portp->lp_lock));
1399 
1400 	AGGR_LACP_DBG(("aggr_lacp_port_detached: port %s/%d\n",
1401 	    portp->lp_devname, portp->lp_port));
1402 
1403 	portp->lp_lacp.sm.port_enabled = B_FALSE;
1404 
1405 	if (grp->lg_lacp_mode == AGGR_LACP_OFF)
1406 		return;
1407 
1408 	/* Disable Slow Protocol PDUs */
1409 	lacp_off(portp);
1410 }
1411 
1412 
1413 /*
1414  * Invoked after the outbound port selection policy has been changed.
1415  */
1416 void
1417 aggr_lacp_policy_changed(aggr_grp_t *grp)
1418 {
1419 	ASSERT(AGGR_LACP_LOCK_HELD(grp));
1420 	ASSERT(RW_WRITE_HELD(&grp->lg_lock));
1421 
1422 	/* suspend transmission for CollectorMaxDelay time */
1423 	delay(grp->aggr.CollectorMaxDelay * 10);
1424 }
1425 
1426 
1427 /*
1428  * Enable Slow Protocol LACP and Marker PDUs.
1429  */
1430 static void
1431 lacp_on(aggr_port_t *portp)
1432 {
1433 	ASSERT(AGGR_LACP_LOCK_HELD(portp->lp_grp));
1434 	ASSERT(RW_WRITE_HELD(&portp->lp_grp->lg_lock));
1435 	ASSERT(RW_WRITE_HELD(&portp->lp_lock));
1436 
1437 	/*
1438 	 * Reset the state machines and Partner operational
1439 	 * information. Careful to not reset things like
1440 	 * our link state.
1441 	 */
1442 	lacp_reset_port(portp);
1443 	portp->lp_lacp.sm.lacp_on = B_TRUE;
1444 
1445 	AGGR_LACP_DBG(("lacp_on:(%s/%d): \n", portp->lp_devname,
1446 	    portp->lp_port));
1447 
1448 	lacp_receive_sm(portp, NULL);
1449 	lacp_mux_sm(portp);
1450 
1451 	if (portp->lp_state != AGGR_PORT_STATE_ATTACHED)
1452 		return;
1453 
1454 	/* Enable Multicast Slow Protocol address */
1455 	aggr_lacp_mcast_on(portp);
1456 
1457 	/* periodic_sm is started up from the receive machine */
1458 	lacp_selection_logic(portp);
1459 } /* lacp_on */
1460 
1461 
1462 /* Disable Slow Protocol LACP and Marker PDUs */
1463 static void
1464 lacp_off(aggr_port_t *portp)
1465 {
1466 	aggr_grp_t *grp = portp->lp_grp;
1467 
1468 	ASSERT(AGGR_LACP_LOCK_HELD(portp->lp_grp));
1469 	ASSERT(RW_WRITE_HELD(&grp->lg_lock));
1470 	ASSERT(RW_WRITE_HELD(&portp->lp_lock));
1471 
1472 	portp->lp_lacp.sm.lacp_on = B_FALSE;
1473 
1474 	AGGR_LACP_DBG(("lacp_off:(%s/%d): \n", portp->lp_devname,
1475 	    portp->lp_port));
1476 
1477 	/*
1478 	 * Disable Slow Protocol Timers. We must temporarely release
1479 	 * the group and port locks in order to avod deadlocks. Make
1480 	 * sure that the port nor the group are closing after re-acquiring
1481 	 * their locks.
1482 	 */
1483 	rw_exit(&portp->lp_lock);
1484 	rw_exit(&grp->lg_lock);
1485 
1486 	stop_periodic_timer(portp);
1487 	stop_current_while_timer(portp);
1488 	stop_wait_while_timer(portp);
1489 
1490 	rw_enter(&grp->lg_lock, RW_WRITER);
1491 	rw_enter(&portp->lp_lock, RW_WRITER);
1492 
1493 	if (!portp->lp_closing && !grp->lg_closing) {
1494 		lacp_mux_sm(portp);
1495 		lacp_periodic_sm(portp);
1496 		lacp_selection_logic(portp);
1497 	}
1498 
1499 	/* Turn OFF Collector_Distributor */
1500 	aggr_set_coll_dist_locked(portp, B_FALSE);
1501 
1502 	/* Disable Multicast Slow Protocol address */
1503 	aggr_lacp_mcast_off(portp);
1504 
1505 	lacp_reset_port(portp);
1506 }
1507 
1508 
1509 static boolean_t
1510 valid_lacp_pdu(aggr_port_t *portp, lacp_t *lacp)
1511 {
1512 	/*
1513 	 * 43.4.12 - "a Receive machine shall not validate
1514 	 * the Version Number, TLV_type, or Reserved fields in received
1515 	 * LACPDUs."
1516 	 * ... "a Receive machine may validate the Actor_Information_Length,
1517 	 * Partner_Information_Length, Collector_Information_Length,
1518 	 * or Terminator_Length fields."
1519 	 */
1520 	if ((lacp->actor_info.information_len != sizeof (link_info_t)) ||
1521 	    (lacp->partner_info.information_len != sizeof (link_info_t)) ||
1522 	    (lacp->collector_len != LACP_COLLECTOR_INFO_LEN) ||
1523 	    (lacp->terminator_len != LACP_TERMINATOR_INFO_LEN)) {
1524 		AGGR_LACP_DBG(("trunk link (%s/%d): Malformed LACPDU: "
1525 		    " Terminator Length = %d \n", portp->lp_devname,
1526 		    portp->lp_port, lacp->terminator_len));
1527 		return (B_FALSE);
1528 	}
1529 
1530 	return (B_TRUE);
1531 }
1532 
1533 
1534 static void
1535 start_current_while_timer(aggr_port_t *portp, uint_t time)
1536 {
1537 	ASSERT(AGGR_LACP_LOCK_HELD(portp->lp_grp));
1538 
1539 	if (portp->lp_lacp.current_while_timer.id == 0) {
1540 		if (time > 0) {
1541 			portp->lp_lacp.current_while_timer.val = time;
1542 		} else if (portp->lp_lacp.ActorOperPortState.bit.timeout) {
1543 			portp->lp_lacp.current_while_timer.val =
1544 			    SHORT_TIMEOUT_TIME;
1545 		} else {
1546 			portp->lp_lacp.current_while_timer.val =
1547 			    LONG_TIMEOUT_TIME;
1548 		}
1549 
1550 		portp->lp_lacp.current_while_timer.id =
1551 		    timeout(current_while_timer_pop, portp,
1552 		    drv_usectohz((clock_t)1000000 *
1553 		    (clock_t)portp->lp_lacp.current_while_timer.val));
1554 	}
1555 }
1556 
1557 
1558 static void
1559 stop_current_while_timer(aggr_port_t *portp)
1560 {
1561 	ASSERT(AGGR_LACP_LOCK_HELD(portp->lp_grp));
1562 
1563 	if (portp->lp_lacp.current_while_timer.id != 0) {
1564 		AGGR_LACP_UNLOCK(portp->lp_grp);
1565 		(void) untimeout(portp->lp_lacp.current_while_timer.id);
1566 		AGGR_LACP_LOCK(portp->lp_grp);
1567 		portp->lp_lacp.current_while_timer.id = 0;
1568 	}
1569 }
1570 
1571 
1572 static void
1573 current_while_timer_pop(void *data)
1574 {
1575 	aggr_port_t *portp = (aggr_port_t *)data;
1576 
1577 	if (portp->lp_closing)
1578 		return;
1579 
1580 	AGGR_LACP_LOCK(portp->lp_grp);
1581 
1582 	AGGR_LACP_DBG(("trunk link:(%s/%d): current_while_timer "
1583 	    "pop id=%p\n", portp->lp_devname, portp->lp_port,
1584 	    portp->lp_lacp.current_while_timer.id));
1585 
1586 	portp->lp_lacp.current_while_timer.id = 0;
1587 	lacp_receive_sm(portp, NULL);
1588 	AGGR_LACP_UNLOCK(portp->lp_grp);
1589 }
1590 
1591 
1592 /*
1593  * record_Default - Simply copies over administrative values
1594  * to the partner operational values, and sets our state to indicate we
1595  * are using defaulted values.
1596  */
1597 static void
1598 record_Default(aggr_port_t *portp)
1599 {
1600 	aggr_lacp_port_t *pl = &portp->lp_lacp;
1601 
1602 	ASSERT(AGGR_LACP_LOCK_HELD(portp->lp_grp));
1603 
1604 	pl->PartnerOperPortNum = pl->PartnerAdminPortNum;
1605 	pl->PartnerOperPortPriority = pl->PartnerAdminPortPriority;
1606 	pl->PartnerOperSystem = pl->PartnerAdminSystem;
1607 	pl->PartnerOperSysPriority = pl->PartnerAdminSysPriority;
1608 	pl->PartnerOperKey = pl->PartnerAdminKey;
1609 	pl->PartnerOperPortState.state = pl->PartnerAdminPortState.state;
1610 
1611 	pl->ActorOperPortState.bit.defaulted = B_TRUE;
1612 }
1613 
1614 
1615 /* Returns B_TRUE on sync value changing */
1616 static boolean_t
1617 record_PDU(aggr_port_t *portp, lacp_t *lacp)
1618 {
1619 	aggr_grp_t *aggrp = portp->lp_grp;
1620 	aggr_lacp_port_t *pl = &portp->lp_lacp;
1621 	uint8_t save_sync;
1622 
1623 	ASSERT(AGGR_LACP_LOCK_HELD(portp->lp_grp));
1624 
1625 	/*
1626 	 * Partner Information
1627 	 */
1628 	pl->PartnerOperPortNum = ntohs(lacp->actor_info.port);
1629 	pl->PartnerOperPortPriority =
1630 	    ntohs(lacp->actor_info.port_priority);
1631 	pl->PartnerOperSystem = lacp->actor_info.system_id;
1632 	pl->PartnerOperSysPriority =
1633 	    htons(lacp->actor_info.system_priority);
1634 	pl->PartnerOperKey = ntohs(lacp->actor_info.key);
1635 
1636 	/* All state info except for Synchronization */
1637 	save_sync = pl->PartnerOperPortState.bit.sync;
1638 	pl->PartnerOperPortState.state = lacp->actor_info.state.state;
1639 
1640 	/* Defaulted set to FALSE */
1641 	pl->ActorOperPortState.bit.defaulted = B_FALSE;
1642 
1643 	/*
1644 	 * 43.4.9 - (Partner_Port, Partner_Port_Priority, Partner_system,
1645 	 *		Partner_System_Priority, Partner_Key, and
1646 	 *		Partner_State.Aggregation) are compared to the
1647 	 *		corresponding operations paramters values for
1648 	 *		the Actor. If these are equal, or if this is
1649 	 *		an individual link, we are synchronized.
1650 	 */
1651 	if (((ntohs(lacp->partner_info.port) == pl->ActorPortNumber) &&
1652 	    (ntohs(lacp->partner_info.port_priority) ==
1653 	    pl->ActorPortPriority) &&
1654 	    (ether_cmp(&lacp->partner_info.system_id,
1655 		(struct ether_addr *)&aggrp->lg_addr) == 0) &&
1656 	    (ntohs(lacp->partner_info.system_priority) ==
1657 	    aggrp->aggr.ActorSystemPriority) &&
1658 	    (ntohs(lacp->partner_info.key) == pl->ActorOperPortKey) &&
1659 	    (lacp->partner_info.state.bit.aggregation ==
1660 	    pl->ActorOperPortState.bit.aggregation)) ||
1661 	    (!lacp->actor_info.state.bit.aggregation)) {
1662 
1663 		pl->PartnerOperPortState.bit.sync =
1664 		    lacp->actor_info.state.bit.sync;
1665 	} else {
1666 		pl->PartnerOperPortState.bit.sync = B_FALSE;
1667 	}
1668 
1669 	if (save_sync != pl->PartnerOperPortState.bit.sync) {
1670 		AGGR_LACP_DBG(("record_PDU:(%s/%d): partner sync "
1671 		    "%d -->%d\n", portp->lp_devname, portp->lp_port,
1672 		    save_sync, pl->PartnerOperPortState.bit.sync));
1673 		return (B_TRUE);
1674 	} else {
1675 		return (B_FALSE);
1676 	}
1677 }
1678 
1679 
1680 /*
1681  * update_selected - If any of the Partner parameters has
1682  *			changed from a previous value, then
1683  *			unselect the link from the aggregator.
1684  */
1685 static boolean_t
1686 update_selected(aggr_port_t *portp, lacp_t *lacp)
1687 {
1688 	aggr_lacp_port_t *pl = &portp->lp_lacp;
1689 
1690 	ASSERT(AGGR_LACP_LOCK_HELD(portp->lp_grp));
1691 
1692 	if ((pl->PartnerOperPortNum != ntohs(lacp->actor_info.port)) ||
1693 	    (pl->PartnerOperPortPriority !=
1694 	    ntohs(lacp->actor_info.port_priority)) ||
1695 	    (ether_cmp(&pl->PartnerOperSystem,
1696 	    &lacp->actor_info.system_id) != 0) ||
1697 	    (pl->PartnerOperSysPriority !=
1698 	    ntohs(lacp->actor_info.system_priority)) ||
1699 	    (pl->PartnerOperKey != ntohs(lacp->actor_info.key)) ||
1700 	    (pl->PartnerOperPortState.bit.aggregation !=
1701 	    lacp->actor_info.state.bit.aggregation)) {
1702 		AGGR_LACP_DBG(("update_selected:(%s/%d): "
1703 		    "selected  %d-->%d\n", portp->lp_devname, portp->lp_port,
1704 		    pl->sm.selected, AGGR_UNSELECTED));
1705 
1706 		pl->sm.selected = AGGR_UNSELECTED;
1707 		return (B_TRUE);
1708 	} else {
1709 		return (B_FALSE);
1710 	}
1711 }
1712 
1713 
1714 /*
1715  * update_default_selected - If any of the operational Partner parameters
1716  *			is different than that of the administrative values
1717  *			then unselect the link from the aggregator.
1718  */
1719 static void
1720 update_default_selected(aggr_port_t *portp)
1721 {
1722 	aggr_lacp_port_t *pl = &portp->lp_lacp;
1723 
1724 	ASSERT(AGGR_LACP_LOCK_HELD(portp->lp_grp));
1725 
1726 	if ((pl->PartnerAdminPortNum != pl->PartnerOperPortNum) ||
1727 	    (pl->PartnerOperPortPriority != pl->PartnerAdminPortPriority) ||
1728 	    (ether_cmp(&pl->PartnerOperSystem, &pl->PartnerAdminSystem) != 0) ||
1729 	    (pl->PartnerOperSysPriority != pl->PartnerAdminSysPriority) ||
1730 	    (pl->PartnerOperKey != pl->PartnerAdminKey) ||
1731 	    (pl->PartnerOperPortState.bit.aggregation !=
1732 	    pl->PartnerAdminPortState.bit.aggregation)) {
1733 
1734 		AGGR_LACP_DBG(("update_default_selected:(%s/%d): "
1735 		    "selected  %d-->%d\n", portp->lp_devname, portp->lp_port,
1736 		    pl->sm.selected, AGGR_UNSELECTED));
1737 		pl->sm.selected = AGGR_UNSELECTED;
1738 	}
1739 }
1740 
1741 
1742 /*
1743  * update_NTT - If any of the Partner values in the received LACPDU
1744  *			are different than that of the Actor operational
1745  *			values then set NTT to true.
1746  */
1747 static void
1748 update_NTT(aggr_port_t *portp, lacp_t *lacp)
1749 {
1750 	aggr_grp_t *aggrp = portp->lp_grp;
1751 	aggr_lacp_port_t *pl = &portp->lp_lacp;
1752 
1753 	ASSERT(AGGR_LACP_LOCK_HELD(portp->lp_grp));
1754 
1755 	if ((pl->ActorPortNumber != ntohs(lacp->partner_info.port)) ||
1756 	    (pl->ActorPortPriority !=
1757 	    ntohs(lacp->partner_info.port_priority)) ||
1758 	    (ether_cmp(&aggrp->lg_addr,
1759 	    &lacp->partner_info.system_id) != 0) ||
1760 	    (aggrp->aggr.ActorSystemPriority !=
1761 	    ntohs(lacp->partner_info.system_priority)) ||
1762 	    (pl->ActorOperPortKey != ntohs(lacp->partner_info.key)) ||
1763 	    (pl->ActorOperPortState.bit.activity !=
1764 	    lacp->partner_info.state.bit.activity) ||
1765 	    (pl->ActorOperPortState.bit.timeout !=
1766 	    lacp->partner_info.state.bit.timeout) ||
1767 	    (pl->ActorOperPortState.bit.sync !=
1768 	    lacp->partner_info.state.bit.sync) ||
1769 	    (pl->ActorOperPortState.bit.aggregation !=
1770 	    lacp->partner_info.state.bit.aggregation)) {
1771 
1772 		AGGR_LACP_DBG(("update_NTT:(%s/%d): NTT  %d-->%d\n",
1773 		    portp->lp_devname, portp->lp_port, pl->NTT,
1774 		    B_TRUE));
1775 
1776 		pl->NTT = B_TRUE;
1777 	}
1778 }
1779 
1780 /*
1781  * lacp_receive_sm - LACP receive state machine
1782  *
1783  * parameters:
1784  *      - portp - instance this applies to.
1785  *      - lacp - pointer in the case of a received LACPDU.
1786  *                This value is NULL if there is no LACPDU.
1787  *
1788  * invoked:
1789  *    - when initialization is needed
1790  *    - upon reception of an LACPDU. This is the common case.
1791  *    - every time the current_while_timer pops
1792  */
1793 static void
1794 lacp_receive_sm(aggr_port_t *portp, lacp_t *lacp)
1795 {
1796 	boolean_t sync_updated, selected_updated, save_activity;
1797 	aggr_lacp_port_t *pl = &portp->lp_lacp;
1798 	lacp_receive_state_t oldstate = pl->sm.receive_state;
1799 
1800 	ASSERT(AGGR_LACP_LOCK_HELD(portp->lp_grp));
1801 
1802 	/* LACP_OFF state not in specification so check here.  */
1803 	if (!pl->sm.lacp_on)
1804 		return;
1805 
1806 	/* figure next state */
1807 	if (pl->sm.begin || pl->sm.port_moved) {
1808 		pl->sm.receive_state = LACP_INITIALIZE;
1809 	} else if (!pl->sm.port_enabled) {	/* DL_NOTE_LINK_DOWN */
1810 		pl->sm.receive_state = LACP_PORT_DISABLED;
1811 	} else if (!pl->sm.lacp_enabled) { /* DL_NOTE_AGGR_UNAVAIL */
1812 		pl->sm.receive_state =
1813 		    (pl->sm.receive_state == LACP_PORT_DISABLED) ?
1814 		    LACP_DISABLED : LACP_PORT_DISABLED;
1815 	} else if (lacp != NULL) {
1816 		if ((pl->sm.receive_state == LACP_EXPIRED) ||
1817 		    (pl->sm.receive_state == LACP_DEFAULTED)) {
1818 			pl->sm.receive_state = LACP_CURRENT;
1819 		}
1820 	} else if ((pl->sm.receive_state == LACP_CURRENT) &&
1821 	    (pl->current_while_timer.id == 0)) {
1822 		pl->sm.receive_state = LACP_EXPIRED;
1823 	} else if ((pl->sm.receive_state == LACP_EXPIRED) &&
1824 	    (pl->current_while_timer.id == 0)) {
1825 		pl->sm.receive_state = LACP_DEFAULTED;
1826 	}
1827 
1828 
1829 	if (!((lacp && (oldstate == LACP_CURRENT) &&
1830 	    (pl->sm.receive_state == LACP_CURRENT)))) {
1831 		AGGR_LACP_DBG(("lacp_receive_sm(%s/%d):%s--->%s\n",
1832 		    portp->lp_devname, portp->lp_port,
1833 		    lacp_receive_str[oldstate],
1834 		    lacp_receive_str[pl->sm.receive_state]));
1835 	}
1836 
1837 	switch (pl->sm.receive_state) {
1838 	case LACP_INITIALIZE:
1839 		pl->sm.selected = AGGR_UNSELECTED;
1840 		record_Default(portp);
1841 		pl->ActorOperPortState.bit.expired = B_FALSE;
1842 		pl->sm.port_moved = B_FALSE;
1843 		pl->sm.receive_state = LACP_PORT_DISABLED;
1844 		pl->sm.begin = B_FALSE;
1845 		lacp_receive_sm(portp, NULL);
1846 		break;
1847 
1848 	case LACP_PORT_DISABLED:
1849 		pl->PartnerOperPortState.bit.sync = B_FALSE;
1850 		/*
1851 		 * Stop current_while_timer in case
1852 		 * we got here from link down
1853 		 */
1854 		stop_current_while_timer(portp);
1855 
1856 		if (pl->sm.port_enabled && !pl->sm.lacp_enabled) {
1857 			pl->sm.receive_state = LACP_DISABLED;
1858 			lacp_receive_sm(portp, lacp);
1859 			/* We goto LACP_DISABLED state */
1860 			break;
1861 		} else if (pl->sm.port_enabled && pl->sm.lacp_enabled) {
1862 			pl->sm.receive_state = LACP_EXPIRED;
1863 			/*
1864 			 * FALL THROUGH TO LACP_EXPIRED CASE:
1865 			 * We have no way of knowing if we get into
1866 			 * lacp_receive_sm() from a  current_while_timer
1867 			 * expiring as it has never been kicked off yet!
1868 			 */
1869 		} else {
1870 			/* We stay in LACP_PORT_DISABLED state */
1871 			break;
1872 		}
1873 		/* LACP_PORT_DISABLED -> LACP_EXPIRED */
1874 		/* FALLTHROUGH */
1875 
1876 	case LACP_EXPIRED:
1877 		/*
1878 		 * Arrives here from LACP_PORT_DISABLED state as well as
1879 		 * as well as current_while_timer expiring.
1880 		 */
1881 		pl->PartnerOperPortState.bit.sync = B_FALSE;
1882 		pl->PartnerOperPortState.bit.timeout = B_TRUE;
1883 
1884 		pl->ActorOperPortState.bit.expired = B_TRUE;
1885 		start_current_while_timer(portp, SHORT_TIMEOUT_TIME);
1886 		lacp_periodic_sm(portp);
1887 		break;
1888 
1889 	case LACP_DISABLED:
1890 		/*
1891 		 * This is the normal state for recv_sm when LACP_OFF
1892 		 * is set or the NIC is in half duplex mode.
1893 		 */
1894 		pl->sm.selected = AGGR_UNSELECTED;
1895 		record_Default(portp);
1896 		pl->PartnerOperPortState.bit.aggregation = B_FALSE;
1897 		pl->ActorOperPortState.bit.expired = B_FALSE;
1898 		break;
1899 
1900 	case LACP_DEFAULTED:
1901 		/*
1902 		 * Current_while_timer expired a second time.
1903 		 */
1904 		update_default_selected(portp);
1905 		record_Default(portp);	/* overwrite Partner Oper val */
1906 		pl->ActorOperPortState.bit.expired = B_FALSE;
1907 		pl->PartnerOperPortState.bit.sync = B_TRUE;
1908 
1909 		lacp_selection_logic(portp);
1910 		lacp_mux_sm(portp);
1911 		break;
1912 
1913 	case LACP_CURRENT:
1914 		/*
1915 		 * Reception of LACPDU
1916 		 */
1917 
1918 		if (!lacp) /* no LACPDU so current_while_timer popped */
1919 			break;
1920 
1921 		AGGR_LACP_DBG(("lacp_receive_sm: (%s/%d): "
1922 		    "LACPDU received:\n", portp->lp_devname, portp->lp_port));
1923 
1924 		/*
1925 		 * Validate Actor_Information_Length,
1926 		 * Partner_Information_Length, Collector_Information_Length,
1927 		 * and Terminator_Length fields.
1928 		 */
1929 		if (!valid_lacp_pdu(portp, lacp)) {
1930 			AGGR_LACP_DBG(("lacp_receive_sm (%s/%d): "
1931 			    "Invalid LACPDU received\n",
1932 			    portp->lp_devname, portp->lp_port));
1933 			break;
1934 		}
1935 
1936 		save_activity = pl->PartnerOperPortState.bit.activity;
1937 		selected_updated = update_selected(portp, lacp);
1938 		update_NTT(portp, lacp);
1939 		sync_updated = record_PDU(portp, lacp);
1940 
1941 		pl->ActorOperPortState.bit.expired = B_FALSE;
1942 
1943 		if (selected_updated) {
1944 			lacp_selection_logic(portp);
1945 			lacp_mux_sm(portp);
1946 		} else if (sync_updated) {
1947 			lacp_mux_sm(portp);
1948 		}
1949 
1950 		/*
1951 		 * If the periodic timer value bit has been modified
1952 		 * or the partner activity bit has been changed then
1953 		 * we need to respectively:
1954 		 *  - restart the timer with the proper timeout value.
1955 		 *  - possibly enable/disable transmission of LACPDUs.
1956 		 */
1957 		if ((pl->PartnerOperPortState.bit.timeout &&
1958 		    (pl->periodic_timer.val != FAST_PERIODIC_TIME)) ||
1959 		    (!pl->PartnerOperPortState.bit.timeout &&
1960 		    (pl->periodic_timer.val != SLOW_PERIODIC_TIME)) ||
1961 		    (pl->PartnerOperPortState.bit.activity !=
1962 		    save_activity)) {
1963 			lacp_periodic_sm(portp);
1964 		}
1965 
1966 		stop_current_while_timer(portp);
1967 		/* Check if we need to transmit an LACPDU */
1968 		if (pl->NTT)
1969 			lacp_xmit_sm(portp);
1970 		start_current_while_timer(portp, 0);
1971 
1972 		break;
1973 	}
1974 }
1975 
1976 static void
1977 aggr_set_coll_dist(aggr_port_t *portp, boolean_t enable)
1978 {
1979 	rw_enter(&portp->lp_lock, RW_WRITER);
1980 	aggr_set_coll_dist_locked(portp, enable);
1981 	rw_exit(&portp->lp_lock);
1982 }
1983 
1984 static void
1985 aggr_set_coll_dist_locked(aggr_port_t *portp, boolean_t enable)
1986 {
1987 	ASSERT(RW_WRITE_HELD(&portp->lp_lock));
1988 
1989 	AGGR_LACP_DBG(("AGGR_SET_COLL_DIST_TYPE: (%s/%d) %s\n",
1990 	    portp->lp_devname, portp->lp_port,
1991 	    enable ? "ENABLED" : "DISABLED"));
1992 
1993 	if (!enable) {
1994 		/*
1995 		 * Turn OFF Collector_Distributor.
1996 		 */
1997 		portp->lp_collector_enabled = B_FALSE;
1998 		aggr_send_port_disable(portp);
1999 		return;
2000 	}
2001 
2002 	/*
2003 	 * Turn ON Collector_Distributor.
2004 	 */
2005 
2006 	if (!portp->lp_lacp.sm.lacp_on || (portp->lp_lacp.sm.lacp_on &&
2007 	    (portp->lp_lacp.sm.mux_state == LACP_COLLECTING_DISTRIBUTING))) {
2008 		/* Port is compatible and can be aggregated */
2009 		portp->lp_collector_enabled = B_TRUE;
2010 		aggr_send_port_enable(portp);
2011 	}
2012 }
2013 
2014 /*
2015  * Process a received Marker or LACPDU.
2016  */
2017 void
2018 aggr_lacp_rx(aggr_port_t *portp, mblk_t *dmp)
2019 {
2020 	lacp_t	*lacp;
2021 
2022 	dmp->b_rptr += sizeof (struct ether_header);
2023 
2024 	if (MBLKL(dmp) < sizeof (lacp_t)) {
2025 		freemsg(dmp);
2026 		return;
2027 	}
2028 
2029 	lacp = (lacp_t *)dmp->b_rptr;
2030 
2031 	switch (lacp->subtype) {
2032 	case LACP_SUBTYPE:
2033 		AGGR_LACP_DBG(("aggr_lacp_rx:(%s/%d): "
2034 		    "LACPDU received.\n", portp->lp_devname, portp->lp_port));
2035 
2036 		AGGR_LACP_LOCK(portp->lp_grp);
2037 		if (!portp->lp_lacp.sm.lacp_on) {
2038 			AGGR_LACP_UNLOCK(portp->lp_grp);
2039 			break;
2040 		}
2041 		lacp_receive_sm(portp, lacp);
2042 		AGGR_LACP_UNLOCK(portp->lp_grp);
2043 		break;
2044 
2045 	case MARKER_SUBTYPE:
2046 		AGGR_LACP_DBG(("aggr_lacp_rx:(%s%d): "
2047 		    "Marker Packet received.\n",
2048 		    portp->lp_devname, portp->lp_port));
2049 
2050 		(void) receive_marker_pdu(portp, dmp);
2051 		break;
2052 
2053 	default:
2054 		AGGR_LACP_DBG(("aggr_lacp_rx: (%s%d): "
2055 		    "Unknown Slow Protocol type %d\n",
2056 		    portp->lp_devname, portp->lp_port, lacp->subtype));
2057 		break;
2058 	}
2059 
2060 	freemsg(dmp);
2061 }
2062