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