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, ðerzeroaddr) == 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 ðerzeroaddr) != 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, ðerzeroaddr) == 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