1 /* $NetBSD: ieee8023ad_lacp.c,v 1.3 2005/12/11 12:24:54 christos Exp $ */ 2 3 /*- 4 * Copyright (c)2005 YAMAMOTO Takashi, 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #include <sys/cdefs.h> 30 __FBSDID("$FreeBSD$"); 31 32 #include <sys/param.h> 33 #include <sys/callout.h> 34 #include <sys/mbuf.h> 35 #include <sys/systm.h> 36 #include <sys/malloc.h> 37 #include <sys/kernel.h> /* hz */ 38 #include <sys/socket.h> /* for net/if.h */ 39 #include <sys/sockio.h> 40 #include <machine/stdarg.h> 41 #include <sys/lock.h> 42 #include <sys/rwlock.h> 43 #include <sys/taskqueue.h> 44 45 #include <net/if.h> 46 #include <net/if_dl.h> 47 #include <net/ethernet.h> 48 #include <net/if_media.h> 49 #include <net/if_types.h> 50 51 #include <net/if_lagg.h> 52 #include <net/ieee8023ad_lacp.h> 53 54 /* 55 * actor system priority and port priority. 56 * XXX should be configurable. 57 */ 58 59 #define LACP_SYSTEM_PRIO 0x8000 60 #define LACP_PORT_PRIO 0x8000 61 62 const uint8_t ethermulticastaddr_slowprotocols[ETHER_ADDR_LEN] = 63 { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x02 }; 64 65 static const struct tlv_template lacp_info_tlv_template[] = { 66 { LACP_TYPE_ACTORINFO, 67 sizeof(struct tlvhdr) + sizeof(struct lacp_peerinfo) }, 68 { LACP_TYPE_PARTNERINFO, 69 sizeof(struct tlvhdr) + sizeof(struct lacp_peerinfo) }, 70 { LACP_TYPE_COLLECTORINFO, 71 sizeof(struct tlvhdr) + sizeof(struct lacp_collectorinfo) }, 72 { 0, 0 }, 73 }; 74 75 typedef void (*lacp_timer_func_t)(struct lacp_port *); 76 77 static const struct tlv_template marker_info_tlv_template[] = { 78 { MARKER_TYPE_INFO, 79 sizeof(struct tlvhdr) + sizeof(struct lacp_markerinfo) }, 80 { 0, 0 }, 81 }; 82 83 static const struct tlv_template marker_response_tlv_template[] = { 84 { MARKER_TYPE_RESPONSE, 85 sizeof(struct tlvhdr) + sizeof(struct lacp_markerinfo) }, 86 { 0, 0 }, 87 }; 88 89 static void lacp_fill_actorinfo(struct lacp_port *, struct lacp_peerinfo *); 90 static void lacp_fill_markerinfo(struct lacp_port *, 91 struct lacp_markerinfo *); 92 93 static uint64_t lacp_aggregator_bandwidth(struct lacp_aggregator *); 94 static void lacp_suppress_distributing(struct lacp_softc *, 95 struct lacp_aggregator *); 96 static void lacp_transit_expire(void *); 97 static void lacp_select_active_aggregator(struct lacp_softc *); 98 static uint16_t lacp_compose_key(struct lacp_port *); 99 static int tlv_check(const void *, size_t, const struct tlvhdr *, 100 const struct tlv_template *, boolean_t); 101 static void lacp_tick(void *); 102 103 static void lacp_fill_aggregator_id(struct lacp_aggregator *, 104 const struct lacp_port *); 105 static void lacp_fill_aggregator_id_peer(struct lacp_peerinfo *, 106 const struct lacp_peerinfo *); 107 static int lacp_aggregator_is_compatible(const struct lacp_aggregator *, 108 const struct lacp_port *); 109 static int lacp_peerinfo_is_compatible(const struct lacp_peerinfo *, 110 const struct lacp_peerinfo *); 111 112 static struct lacp_aggregator *lacp_aggregator_get(struct lacp_softc *, 113 struct lacp_port *); 114 static void lacp_aggregator_addref(struct lacp_softc *, 115 struct lacp_aggregator *); 116 static void lacp_aggregator_delref(struct lacp_softc *, 117 struct lacp_aggregator *); 118 119 /* receive machine */ 120 121 static void lacp_dequeue(void *, int); 122 static int lacp_pdu_input(struct lagg_port *, struct mbuf *); 123 static int lacp_marker_input(struct lagg_port *, struct mbuf *); 124 static void lacp_sm_rx(struct lacp_port *, const struct lacpdu *); 125 static void lacp_sm_rx_timer(struct lacp_port *); 126 static void lacp_sm_rx_set_expired(struct lacp_port *); 127 static void lacp_sm_rx_update_ntt(struct lacp_port *, 128 const struct lacpdu *); 129 static void lacp_sm_rx_record_pdu(struct lacp_port *, 130 const struct lacpdu *); 131 static void lacp_sm_rx_update_selected(struct lacp_port *, 132 const struct lacpdu *); 133 static void lacp_sm_rx_record_default(struct lacp_port *); 134 static void lacp_sm_rx_update_default_selected(struct lacp_port *); 135 static void lacp_sm_rx_update_selected_from_peerinfo(struct lacp_port *, 136 const struct lacp_peerinfo *); 137 138 /* mux machine */ 139 140 static void lacp_sm_mux(struct lacp_port *); 141 static void lacp_set_mux(struct lacp_port *, enum lacp_mux_state); 142 static void lacp_sm_mux_timer(struct lacp_port *); 143 144 /* periodic transmit machine */ 145 146 static void lacp_sm_ptx_update_timeout(struct lacp_port *, uint8_t); 147 static void lacp_sm_ptx_tx_schedule(struct lacp_port *); 148 static void lacp_sm_ptx_timer(struct lacp_port *); 149 150 /* transmit machine */ 151 152 static void lacp_sm_tx(struct lacp_port *); 153 static void lacp_sm_assert_ntt(struct lacp_port *); 154 155 static void lacp_run_timers(struct lacp_port *); 156 static int lacp_compare_peerinfo(const struct lacp_peerinfo *, 157 const struct lacp_peerinfo *); 158 static int lacp_compare_systemid(const struct lacp_systemid *, 159 const struct lacp_systemid *); 160 static void lacp_port_enable(struct lacp_port *); 161 static void lacp_port_disable(struct lacp_port *); 162 static void lacp_select(struct lacp_port *); 163 static void lacp_unselect(struct lacp_port *); 164 static void lacp_disable_collecting(struct lacp_port *); 165 static void lacp_enable_collecting(struct lacp_port *); 166 static void lacp_disable_distributing(struct lacp_port *); 167 static void lacp_enable_distributing(struct lacp_port *); 168 static int lacp_xmit_lacpdu(struct lacp_port *); 169 static int lacp_xmit_marker(struct lacp_port *); 170 171 #if defined(LACP_DEBUG) 172 static void lacp_dump_lacpdu(const struct lacpdu *); 173 static const char *lacp_format_partner(const struct lacp_peerinfo *, char *, 174 size_t); 175 static const char *lacp_format_lagid(const struct lacp_peerinfo *, 176 const struct lacp_peerinfo *, char *, size_t); 177 static const char *lacp_format_lagid_aggregator(const struct lacp_aggregator *, 178 char *, size_t); 179 static const char *lacp_format_state(uint8_t, char *, size_t); 180 static const char *lacp_format_mac(const uint8_t *, char *, size_t); 181 static const char *lacp_format_systemid(const struct lacp_systemid *, char *, 182 size_t); 183 static const char *lacp_format_portid(const struct lacp_portid *, char *, 184 size_t); 185 static void lacp_dprintf(const struct lacp_port *, const char *, ...) 186 __attribute__((__format__(__printf__, 2, 3))); 187 #define LACP_DPRINTF(a) lacp_dprintf a 188 #else 189 #define LACP_DPRINTF(a) /* nothing */ 190 #endif 191 192 /* 193 * partner administration variables. 194 * XXX should be configurable. 195 */ 196 197 static const struct lacp_peerinfo lacp_partner_admin = { 198 .lip_systemid = { .lsi_prio = 0xffff }, 199 .lip_portid = { .lpi_prio = 0xffff }, 200 #if 1 201 /* optimistic */ 202 .lip_state = LACP_STATE_SYNC | LACP_STATE_AGGREGATION | 203 LACP_STATE_COLLECTING | LACP_STATE_DISTRIBUTING, 204 #else 205 /* pessimistic */ 206 .lip_state = 0, 207 #endif 208 }; 209 210 static const lacp_timer_func_t lacp_timer_funcs[LACP_NTIMER] = { 211 [LACP_TIMER_CURRENT_WHILE] = lacp_sm_rx_timer, 212 [LACP_TIMER_PERIODIC] = lacp_sm_ptx_timer, 213 [LACP_TIMER_WAIT_WHILE] = lacp_sm_mux_timer, 214 }; 215 216 struct mbuf * 217 lacp_input(struct lagg_port *lgp, struct mbuf *m) 218 { 219 struct lagg_softc *sc = lgp->lp_softc; 220 struct lacp_softc *lsc = LACP_SOFTC(sc); 221 uint8_t subtype; 222 223 if (m->m_pkthdr.len < sizeof(struct ether_header) + sizeof(subtype)) { 224 m_freem(m); 225 return (NULL); 226 } 227 228 m_copydata(m, sizeof(struct ether_header), sizeof(subtype), &subtype); 229 switch (subtype) { 230 case SLOWPROTOCOLS_SUBTYPE_LACP: 231 IF_HANDOFF(&lsc->lsc_queue, m, NULL); 232 taskqueue_enqueue(taskqueue_swi, &lsc->lsc_qtask); 233 break; 234 235 case SLOWPROTOCOLS_SUBTYPE_MARKER: 236 lacp_marker_input(lgp, m); 237 break; 238 239 default: 240 /* Not a subtype we are interested in */ 241 return (m); 242 } 243 return (NULL); 244 } 245 246 static void 247 lacp_dequeue(void *arg, int pending) 248 { 249 struct lacp_softc *lsc = (struct lacp_softc *)arg; 250 struct lagg_softc *sc = lsc->lsc_softc; 251 struct lagg_port *lgp; 252 struct mbuf *m; 253 254 LAGG_WLOCK(sc); 255 for (;;) { 256 IF_DEQUEUE(&lsc->lsc_queue, m); 257 if (m == NULL) 258 break; 259 lgp = m->m_pkthdr.rcvif->if_lagg; 260 lacp_pdu_input(lgp, m); 261 } 262 LAGG_WUNLOCK(sc); 263 } 264 265 /* 266 * lacp_pdu_input: process lacpdu 267 */ 268 static int 269 lacp_pdu_input(struct lagg_port *lgp, struct mbuf *m) 270 { 271 struct lacp_port *lp = LACP_PORT(lgp); 272 struct lacpdu *du; 273 int error = 0; 274 275 LAGG_WLOCK_ASSERT(lgp->lp_softc); 276 277 if (m->m_pkthdr.len != sizeof(*du)) { 278 goto bad; 279 } 280 281 if ((m->m_flags & M_MCAST) == 0) { 282 goto bad; 283 } 284 285 if (m->m_len < sizeof(*du)) { 286 m = m_pullup(m, sizeof(*du)); 287 if (m == NULL) { 288 return (ENOMEM); 289 } 290 } 291 292 du = mtod(m, struct lacpdu *); 293 294 if (memcmp(&du->ldu_eh.ether_dhost, 295 ðermulticastaddr_slowprotocols, ETHER_ADDR_LEN)) { 296 goto bad; 297 } 298 299 /* 300 * ignore the version for compatibility with 301 * the future protocol revisions. 302 */ 303 #if 0 304 if (du->ldu_sph.sph_version != 1) { 305 goto bad; 306 } 307 #endif 308 309 /* 310 * ignore tlv types for compatibility with 311 * the future protocol revisions. 312 */ 313 if (tlv_check(du, sizeof(*du), &du->ldu_tlv_actor, 314 lacp_info_tlv_template, FALSE)) { 315 goto bad; 316 } 317 318 #if defined(LACP_DEBUG) 319 LACP_DPRINTF((lp, "lacpdu receive\n")); 320 lacp_dump_lacpdu(du); 321 #endif /* defined(LACP_DEBUG) */ 322 lacp_sm_rx(lp, du); 323 324 m_freem(m); 325 326 return (error); 327 328 bad: 329 m_freem(m); 330 return (EINVAL); 331 } 332 333 static void 334 lacp_fill_actorinfo(struct lacp_port *lp, struct lacp_peerinfo *info) 335 { 336 struct lagg_port *lgp = lp->lp_lagg; 337 struct lagg_softc *sc = lgp->lp_softc; 338 339 info->lip_systemid.lsi_prio = htons(LACP_SYSTEM_PRIO); 340 memcpy(&info->lip_systemid.lsi_mac, 341 IF_LLADDR(sc->sc_ifp), ETHER_ADDR_LEN); 342 info->lip_portid.lpi_prio = htons(LACP_PORT_PRIO); 343 info->lip_portid.lpi_portno = htons(lp->lp_ifp->if_index); 344 info->lip_state = lp->lp_state; 345 } 346 347 static void 348 lacp_fill_markerinfo(struct lacp_port *lp, struct lacp_markerinfo *info) 349 { 350 struct ifnet *ifp = lp->lp_ifp; 351 352 /* Fill in the port index and system id (encoded as the MAC) */ 353 info->mi_rq_port = htons(ifp->if_index); 354 memcpy(&info->mi_rq_system, lp->lp_systemid.lsi_mac, ETHER_ADDR_LEN); 355 info->mi_rq_xid = htonl(0); 356 } 357 358 static int 359 lacp_xmit_lacpdu(struct lacp_port *lp) 360 { 361 struct lagg_port *lgp = lp->lp_lagg; 362 struct mbuf *m; 363 struct lacpdu *du; 364 int error; 365 366 LAGG_WLOCK_ASSERT(lgp->lp_softc); 367 368 m = m_gethdr(M_DONTWAIT, MT_DATA); 369 if (m == NULL) { 370 return (ENOMEM); 371 } 372 m->m_len = m->m_pkthdr.len = sizeof(*du); 373 374 du = mtod(m, struct lacpdu *); 375 memset(du, 0, sizeof(*du)); 376 377 memcpy(&du->ldu_eh.ether_dhost, ethermulticastaddr_slowprotocols, 378 ETHER_ADDR_LEN); 379 memcpy(&du->ldu_eh.ether_shost, lgp->lp_lladdr, ETHER_ADDR_LEN); 380 du->ldu_eh.ether_type = htons(ETHERTYPE_SLOW); 381 382 du->ldu_sph.sph_subtype = SLOWPROTOCOLS_SUBTYPE_LACP; 383 du->ldu_sph.sph_version = 1; 384 385 TLV_SET(&du->ldu_tlv_actor, LACP_TYPE_ACTORINFO, sizeof(du->ldu_actor)); 386 du->ldu_actor = lp->lp_actor; 387 388 TLV_SET(&du->ldu_tlv_partner, LACP_TYPE_PARTNERINFO, 389 sizeof(du->ldu_partner)); 390 du->ldu_partner = lp->lp_partner; 391 392 TLV_SET(&du->ldu_tlv_collector, LACP_TYPE_COLLECTORINFO, 393 sizeof(du->ldu_collector)); 394 du->ldu_collector.lci_maxdelay = 0; 395 396 #if defined(LACP_DEBUG) 397 LACP_DPRINTF((lp, "lacpdu transmit\n")); 398 lacp_dump_lacpdu(du); 399 #endif /* defined(LACP_DEBUG) */ 400 401 m->m_flags |= M_MCAST; 402 403 /* 404 * XXX should use higher priority queue. 405 * otherwise network congestion can break aggregation. 406 */ 407 408 error = lagg_enqueue(lp->lp_ifp, m); 409 return (error); 410 } 411 412 static int 413 lacp_xmit_marker(struct lacp_port *lp) 414 { 415 struct lagg_port *lgp = lp->lp_lagg; 416 struct mbuf *m; 417 struct markerdu *mdu; 418 int error; 419 420 LAGG_WLOCK_ASSERT(lgp->lp_softc); 421 422 m = m_gethdr(M_DONTWAIT, MT_DATA); 423 if (m == NULL) { 424 return (ENOMEM); 425 } 426 m->m_len = m->m_pkthdr.len = sizeof(*mdu); 427 428 mdu = mtod(m, struct markerdu *); 429 memset(mdu, 0, sizeof(*mdu)); 430 431 memcpy(&mdu->mdu_eh.ether_dhost, ethermulticastaddr_slowprotocols, 432 ETHER_ADDR_LEN); 433 memcpy(&mdu->mdu_eh.ether_shost, lgp->lp_lladdr, ETHER_ADDR_LEN); 434 mdu->mdu_eh.ether_type = htons(ETHERTYPE_SLOW); 435 436 mdu->mdu_sph.sph_subtype = SLOWPROTOCOLS_SUBTYPE_MARKER; 437 mdu->mdu_sph.sph_version = 1; 438 439 /* Bump the transaction id and copy over the marker info */ 440 lp->lp_marker.mi_rq_xid = htonl(ntohl(lp->lp_marker.mi_rq_xid) + 1); 441 TLV_SET(&mdu->mdu_tlv, MARKER_TYPE_INFO, sizeof(mdu->mdu_info)); 442 mdu->mdu_info = lp->lp_marker; 443 444 LACP_DPRINTF((lp, "marker transmit, port=%u, sys=%6D, id=%u\n", 445 ntohs(mdu->mdu_info.mi_rq_port), mdu->mdu_info.mi_rq_system, ":", 446 ntohl(mdu->mdu_info.mi_rq_xid))); 447 448 m->m_flags |= M_MCAST; 449 error = lagg_enqueue(lp->lp_ifp, m); 450 return (error); 451 } 452 void 453 lacp_linkstate(struct lagg_port *lgp) 454 { 455 struct lacp_port *lp = LACP_PORT(lgp); 456 struct ifnet *ifp = lgp->lp_ifp; 457 struct ifmediareq ifmr; 458 int error = 0; 459 u_int media; 460 uint8_t old_state; 461 uint16_t old_key; 462 463 LAGG_WLOCK_ASSERT(lgp->lp_softc); 464 465 bzero((char *)&ifmr, sizeof(ifmr)); 466 error = (*ifp->if_ioctl)(ifp, SIOCGIFMEDIA, (caddr_t)&ifmr); 467 if (error != 0) 468 return; 469 470 media = ifmr.ifm_active; 471 LACP_DPRINTF((lp, "media changed 0x%x -> 0x%x, ether = %d, fdx = %d, " 472 "link = %d\n", lp->lp_media, media, IFM_TYPE(media) == IFM_ETHER, 473 (media & IFM_FDX) != 0, ifp->if_link_state == LINK_STATE_UP)); 474 old_state = lp->lp_state; 475 old_key = lp->lp_key; 476 477 lp->lp_media = media; 478 /* 479 * If the port is not an active full duplex Ethernet link then it can 480 * not be aggregated. 481 */ 482 if (IFM_TYPE(media) != IFM_ETHER || (media & IFM_FDX) == 0 || 483 ifp->if_link_state != LINK_STATE_UP) { 484 lacp_port_disable(lp); 485 } else { 486 lacp_port_enable(lp); 487 } 488 lp->lp_key = lacp_compose_key(lp); 489 490 if (old_state != lp->lp_state || old_key != lp->lp_key) { 491 LACP_DPRINTF((lp, "-> UNSELECTED\n")); 492 lp->lp_selected = LACP_UNSELECTED; 493 } 494 } 495 496 static void 497 lacp_tick(void *arg) 498 { 499 struct lacp_softc *lsc = arg; 500 struct lacp_port *lp; 501 502 LIST_FOREACH(lp, &lsc->lsc_ports, lp_next) { 503 if ((lp->lp_state & LACP_STATE_AGGREGATION) == 0) 504 continue; 505 506 lacp_run_timers(lp); 507 508 lacp_select(lp); 509 lacp_sm_mux(lp); 510 lacp_sm_tx(lp); 511 lacp_sm_ptx_tx_schedule(lp); 512 } 513 callout_reset(&lsc->lsc_callout, hz, lacp_tick, lsc); 514 } 515 516 int 517 lacp_port_create(struct lagg_port *lgp) 518 { 519 struct lagg_softc *sc = lgp->lp_softc; 520 struct lacp_softc *lsc = LACP_SOFTC(sc); 521 struct lacp_port *lp; 522 struct ifnet *ifp = lgp->lp_ifp; 523 struct sockaddr_dl sdl; 524 struct ifmultiaddr *rifma = NULL; 525 int error; 526 527 boolean_t active = TRUE; /* XXX should be configurable */ 528 boolean_t fast = FALSE; /* XXX should be configurable */ 529 530 LAGG_WLOCK_ASSERT(sc); 531 532 bzero((char *)&sdl, sizeof(sdl)); 533 sdl.sdl_len = sizeof(sdl); 534 sdl.sdl_family = AF_LINK; 535 sdl.sdl_index = ifp->if_index; 536 sdl.sdl_type = IFT_ETHER; 537 sdl.sdl_alen = ETHER_ADDR_LEN; 538 539 bcopy(ðermulticastaddr_slowprotocols, 540 LLADDR(&sdl), ETHER_ADDR_LEN); 541 error = if_addmulti(ifp, (struct sockaddr *)&sdl, &rifma); 542 if (error) { 543 printf("%s: ADDMULTI failed on %s\n", __func__, lgp->lp_ifname); 544 return (error); 545 } 546 547 lp = malloc(sizeof(struct lacp_port), 548 M_DEVBUF, M_NOWAIT|M_ZERO); 549 if (lp == NULL) 550 return (ENOMEM); 551 552 lgp->lp_psc = (caddr_t)lp; 553 lp->lp_ifp = ifp; 554 lp->lp_lagg = lgp; 555 lp->lp_lsc = lsc; 556 lp->lp_ifma = rifma; 557 558 LIST_INSERT_HEAD(&lsc->lsc_ports, lp, lp_next); 559 560 lacp_fill_actorinfo(lp, &lp->lp_actor); 561 lacp_fill_markerinfo(lp, &lp->lp_marker); 562 lp->lp_state = 563 (active ? LACP_STATE_ACTIVITY : 0) | 564 (fast ? LACP_STATE_TIMEOUT : 0); 565 lp->lp_aggregator = NULL; 566 lacp_linkstate(lgp); 567 lacp_sm_rx_set_expired(lp); 568 569 return (0); 570 } 571 572 void 573 lacp_port_destroy(struct lagg_port *lgp) 574 { 575 struct lacp_port *lp = LACP_PORT(lgp); 576 int i; 577 578 LAGG_WLOCK_ASSERT(lgp->lp_softc); 579 580 for (i = 0; i < LACP_NTIMER; i++) { 581 LACP_TIMER_DISARM(lp, i); 582 } 583 584 lacp_disable_collecting(lp); 585 lacp_disable_distributing(lp); 586 lacp_unselect(lp); 587 lgp->lp_flags &= ~LAGG_PORT_DISABLED; 588 589 /* The address may have already been removed by if_purgemaddrs() */ 590 if (!lgp->lp_detaching) 591 if_delmulti_ifma(lp->lp_ifma); 592 593 LIST_REMOVE(lp, lp_next); 594 free(lp, M_DEVBUF); 595 } 596 597 int 598 lacp_port_isactive(struct lagg_port *lgp) 599 { 600 struct lacp_port *lp = LACP_PORT(lgp); 601 struct lacp_softc *lsc = lp->lp_lsc; 602 struct lacp_aggregator *la = lp->lp_aggregator; 603 604 /* This port is joined to the active aggregator */ 605 if (la != NULL && la == lsc->lsc_active_aggregator) 606 return (1); 607 608 return (0); 609 } 610 611 void 612 lacp_req(struct lagg_softc *sc, caddr_t data) 613 { 614 struct lacp_opreq *req = (struct lacp_opreq *)data; 615 struct lacp_softc *lsc = LACP_SOFTC(sc); 616 struct lacp_aggregator *la = lsc->lsc_active_aggregator; 617 618 bzero(req, sizeof(struct lacp_opreq)); 619 if (la != NULL) { 620 req->actor_prio = ntohs(la->la_actor.lip_systemid.lsi_prio); 621 memcpy(&req->actor_mac, &la->la_actor.lip_systemid.lsi_mac, 622 ETHER_ADDR_LEN); 623 req->actor_key = ntohs(la->la_actor.lip_key); 624 req->actor_portprio = ntohs(la->la_actor.lip_portid.lpi_prio); 625 req->actor_portno = ntohs(la->la_actor.lip_portid.lpi_portno); 626 req->actor_state = la->la_actor.lip_state; 627 628 req->partner_prio = ntohs(la->la_partner.lip_systemid.lsi_prio); 629 memcpy(&req->partner_mac, &la->la_partner.lip_systemid.lsi_mac, 630 ETHER_ADDR_LEN); 631 req->partner_key = ntohs(la->la_partner.lip_key); 632 req->partner_portprio = ntohs(la->la_partner.lip_portid.lpi_prio); 633 req->partner_portno = ntohs(la->la_partner.lip_portid.lpi_portno); 634 req->partner_state = la->la_partner.lip_state; 635 } 636 } 637 638 void 639 lacp_portreq(struct lagg_port *lgp, caddr_t data) 640 { 641 struct lacp_opreq *req = (struct lacp_opreq *)data; 642 struct lacp_port *lp = LACP_PORT(lgp); 643 644 req->actor_prio = ntohs(lp->lp_actor.lip_systemid.lsi_prio); 645 memcpy(&req->actor_mac, &lp->lp_actor.lip_systemid.lsi_mac, 646 ETHER_ADDR_LEN); 647 req->actor_key = ntohs(lp->lp_actor.lip_key); 648 req->actor_portprio = ntohs(lp->lp_actor.lip_portid.lpi_prio); 649 req->actor_portno = ntohs(lp->lp_actor.lip_portid.lpi_portno); 650 req->actor_state = lp->lp_actor.lip_state; 651 652 req->partner_prio = ntohs(lp->lp_partner.lip_systemid.lsi_prio); 653 memcpy(&req->partner_mac, &lp->lp_partner.lip_systemid.lsi_mac, 654 ETHER_ADDR_LEN); 655 req->partner_key = ntohs(lp->lp_partner.lip_key); 656 req->partner_portprio = ntohs(lp->lp_partner.lip_portid.lpi_prio); 657 req->partner_portno = ntohs(lp->lp_partner.lip_portid.lpi_portno); 658 req->partner_state = lp->lp_partner.lip_state; 659 } 660 661 static void 662 lacp_disable_collecting(struct lacp_port *lp) 663 { 664 struct lagg_port *lgp = lp->lp_lagg; 665 666 LACP_DPRINTF((lp, "collecting disabled\n")); 667 668 lp->lp_state &= ~LACP_STATE_COLLECTING; 669 lgp->lp_flags &= ~LAGG_PORT_COLLECTING; 670 } 671 672 static void 673 lacp_enable_collecting(struct lacp_port *lp) 674 { 675 struct lagg_port *lgp = lp->lp_lagg; 676 677 LACP_DPRINTF((lp, "collecting enabled\n")); 678 679 lp->lp_state |= LACP_STATE_COLLECTING; 680 lgp->lp_flags |= LAGG_PORT_COLLECTING; 681 } 682 683 static void 684 lacp_disable_distributing(struct lacp_port *lp) 685 { 686 struct lacp_aggregator *la = lp->lp_aggregator; 687 struct lacp_softc *lsc = lp->lp_lsc; 688 struct lagg_port *lgp = lp->lp_lagg; 689 #if defined(LACP_DEBUG) 690 char buf[LACP_LAGIDSTR_MAX+1]; 691 #endif /* defined(LACP_DEBUG) */ 692 693 LAGG_WLOCK_ASSERT(lgp->lp_softc); 694 695 if (la == NULL || (lp->lp_state & LACP_STATE_DISTRIBUTING) == 0) { 696 return; 697 } 698 699 KASSERT(!TAILQ_EMPTY(&la->la_ports), ("no aggregator ports")); 700 KASSERT(la->la_nports > 0, ("nports invalid (%d)", la->la_nports)); 701 KASSERT(la->la_refcnt >= la->la_nports, ("aggregator refcnt invalid")); 702 703 LACP_DPRINTF((lp, "disable distributing on aggregator %s, " 704 "nports %d -> %d\n", 705 lacp_format_lagid_aggregator(la, buf, sizeof(buf)), 706 la->la_nports, la->la_nports - 1)); 707 708 TAILQ_REMOVE(&la->la_ports, lp, lp_dist_q); 709 la->la_nports--; 710 711 lacp_suppress_distributing(lsc, la); 712 713 lp->lp_state &= ~LACP_STATE_DISTRIBUTING; 714 lgp->lp_flags &= ~LAGG_PORT_DISTRIBUTING; 715 716 if (lsc->lsc_active_aggregator == la) { 717 lacp_select_active_aggregator(lsc); 718 } 719 } 720 721 static void 722 lacp_enable_distributing(struct lacp_port *lp) 723 { 724 struct lacp_aggregator *la = lp->lp_aggregator; 725 struct lacp_softc *lsc = lp->lp_lsc; 726 struct lagg_port *lgp = lp->lp_lagg; 727 #if defined(LACP_DEBUG) 728 char buf[LACP_LAGIDSTR_MAX+1]; 729 #endif /* defined(LACP_DEBUG) */ 730 731 LAGG_WLOCK_ASSERT(lgp->lp_softc); 732 733 if ((lp->lp_state & LACP_STATE_DISTRIBUTING) != 0) { 734 return; 735 } 736 737 LACP_DPRINTF((lp, "enable distributing on aggregator %s, " 738 "nports %d -> %d\n", 739 lacp_format_lagid_aggregator(la, buf, sizeof(buf)), 740 la->la_nports, la->la_nports + 1)); 741 742 KASSERT(la->la_refcnt > la->la_nports, ("aggregator refcnt invalid")); 743 TAILQ_INSERT_HEAD(&la->la_ports, lp, lp_dist_q); 744 la->la_nports++; 745 746 lacp_suppress_distributing(lsc, la); 747 748 lp->lp_state |= LACP_STATE_DISTRIBUTING; 749 lgp->lp_flags |= LAGG_PORT_DISTRIBUTING; 750 751 if (lsc->lsc_active_aggregator != la) { 752 lacp_select_active_aggregator(lsc); 753 } 754 } 755 756 static void 757 lacp_transit_expire(void *vp) 758 { 759 struct lacp_softc *lsc = vp; 760 761 LACP_DPRINTF((NULL, "%s\n", __func__)); 762 lsc->lsc_suppress_distributing = FALSE; 763 } 764 765 int 766 lacp_attach(struct lagg_softc *sc) 767 { 768 struct lacp_softc *lsc; 769 770 LAGG_WLOCK_ASSERT(sc); 771 772 lsc = malloc(sizeof(struct lacp_softc), 773 M_DEVBUF, M_NOWAIT|M_ZERO); 774 if (lsc == NULL) 775 return (ENOMEM); 776 777 sc->sc_psc = (caddr_t)lsc; 778 lsc->lsc_softc = sc; 779 780 lsc->lsc_hashkey = arc4random(); 781 lsc->lsc_active_aggregator = NULL; 782 TAILQ_INIT(&lsc->lsc_aggregators); 783 LIST_INIT(&lsc->lsc_ports); 784 785 TASK_INIT(&lsc->lsc_qtask, 0, lacp_dequeue, lsc); 786 mtx_init(&lsc->lsc_queue.ifq_mtx, "lacp queue", NULL, MTX_DEF); 787 lsc->lsc_queue.ifq_maxlen = ifqmaxlen; 788 789 callout_init_rw(&lsc->lsc_transit_callout, &sc->sc_mtx, 0); 790 callout_init_rw(&lsc->lsc_callout, &sc->sc_mtx, 0); 791 792 /* if the lagg is already up then do the same */ 793 if (sc->sc_ifp->if_drv_flags & IFF_DRV_RUNNING) 794 lacp_init(sc); 795 796 return (0); 797 } 798 799 int 800 lacp_detach(struct lagg_softc *sc) 801 { 802 struct lacp_softc *lsc = LACP_SOFTC(sc); 803 804 KASSERT(TAILQ_EMPTY(&lsc->lsc_aggregators), 805 ("aggregators still active")); 806 KASSERT(lsc->lsc_active_aggregator == NULL, 807 ("aggregator still attached")); 808 809 sc->sc_psc = NULL; 810 callout_drain(&lsc->lsc_transit_callout); 811 callout_drain(&lsc->lsc_callout); 812 taskqueue_drain(taskqueue_swi, &lsc->lsc_qtask); 813 IF_DRAIN(&lsc->lsc_queue); 814 mtx_destroy(&lsc->lsc_queue.ifq_mtx); 815 816 free(lsc, M_DEVBUF); 817 return (0); 818 } 819 820 void 821 lacp_init(struct lagg_softc *sc) 822 { 823 struct lacp_softc *lsc = LACP_SOFTC(sc); 824 825 callout_reset(&lsc->lsc_callout, hz, lacp_tick, lsc); 826 } 827 828 void 829 lacp_stop(struct lagg_softc *sc) 830 { 831 struct lacp_softc *lsc = LACP_SOFTC(sc); 832 833 callout_stop(&lsc->lsc_transit_callout); 834 callout_stop(&lsc->lsc_callout); 835 } 836 837 struct lagg_port * 838 lacp_select_tx_port(struct lagg_softc *sc, struct mbuf *m) 839 { 840 struct lacp_softc *lsc = LACP_SOFTC(sc); 841 struct lacp_aggregator *la; 842 struct lacp_port *lp; 843 uint32_t hash; 844 int nports; 845 846 LAGG_RLOCK_ASSERT(sc); 847 848 if (__predict_false(lsc->lsc_suppress_distributing)) { 849 LACP_DPRINTF((NULL, "%s: waiting transit\n", __func__)); 850 return (NULL); 851 } 852 853 la = lsc->lsc_active_aggregator; 854 if (__predict_false(la == NULL)) { 855 LACP_DPRINTF((NULL, "%s: no active aggregator\n", __func__)); 856 return (NULL); 857 } 858 859 nports = la->la_nports; 860 KASSERT(nports > 0, ("no ports available")); 861 862 hash = lagg_hashmbuf(m, lsc->lsc_hashkey); 863 hash %= nports; 864 lp = TAILQ_FIRST(&la->la_ports); 865 while (hash--) { 866 lp = TAILQ_NEXT(lp, lp_dist_q); 867 } 868 869 KASSERT((lp->lp_state & LACP_STATE_DISTRIBUTING) != 0, 870 ("aggregated port is not distributing")); 871 872 return (lp->lp_lagg); 873 } 874 /* 875 * lacp_suppress_distributing: drop transmit packets for a while 876 * to preserve packet ordering. 877 */ 878 879 static void 880 lacp_suppress_distributing(struct lacp_softc *lsc, struct lacp_aggregator *la) 881 { 882 struct lacp_port *lp; 883 884 if (lsc->lsc_active_aggregator != la) { 885 return; 886 } 887 888 LACP_DPRINTF((NULL, "%s\n", __func__)); 889 lsc->lsc_suppress_distributing = TRUE; 890 891 /* send a marker frame down each port to verify the queues are empty */ 892 LIST_FOREACH(lp, &lsc->lsc_ports, lp_next) { 893 lp->lp_flags |= LACP_PORT_MARK; 894 lacp_xmit_marker(lp); 895 } 896 897 /* set a timeout for the marker frames */ 898 callout_reset(&lsc->lsc_transit_callout, 899 LACP_TRANSIT_DELAY * hz / 1000, lacp_transit_expire, lsc); 900 } 901 902 static int 903 lacp_compare_peerinfo(const struct lacp_peerinfo *a, 904 const struct lacp_peerinfo *b) 905 { 906 return (memcmp(a, b, offsetof(struct lacp_peerinfo, lip_state))); 907 } 908 909 static int 910 lacp_compare_systemid(const struct lacp_systemid *a, 911 const struct lacp_systemid *b) 912 { 913 return (memcmp(a, b, sizeof(*a))); 914 } 915 916 #if 0 /* unused */ 917 static int 918 lacp_compare_portid(const struct lacp_portid *a, 919 const struct lacp_portid *b) 920 { 921 return (memcmp(a, b, sizeof(*a))); 922 } 923 #endif 924 925 static uint64_t 926 lacp_aggregator_bandwidth(struct lacp_aggregator *la) 927 { 928 struct lacp_port *lp; 929 uint64_t speed; 930 931 lp = TAILQ_FIRST(&la->la_ports); 932 if (lp == NULL) { 933 return (0); 934 } 935 936 speed = ifmedia_baudrate(lp->lp_media); 937 speed *= la->la_nports; 938 if (speed == 0) { 939 LACP_DPRINTF((lp, "speed 0? media=0x%x nports=%d\n", 940 lp->lp_media, la->la_nports)); 941 } 942 943 return (speed); 944 } 945 946 /* 947 * lacp_select_active_aggregator: select an aggregator to be used to transmit 948 * packets from lagg(4) interface. 949 */ 950 951 static void 952 lacp_select_active_aggregator(struct lacp_softc *lsc) 953 { 954 struct lacp_aggregator *la; 955 struct lacp_aggregator *best_la = NULL; 956 uint64_t best_speed = 0; 957 #if defined(LACP_DEBUG) 958 char buf[LACP_LAGIDSTR_MAX+1]; 959 #endif /* defined(LACP_DEBUG) */ 960 961 LACP_DPRINTF((NULL, "%s:\n", __func__)); 962 963 TAILQ_FOREACH(la, &lsc->lsc_aggregators, la_q) { 964 uint64_t speed; 965 966 if (la->la_nports == 0) { 967 continue; 968 } 969 970 speed = lacp_aggregator_bandwidth(la); 971 LACP_DPRINTF((NULL, "%s, speed=%jd, nports=%d\n", 972 lacp_format_lagid_aggregator(la, buf, sizeof(buf)), 973 speed, la->la_nports)); 974 975 /* This aggregator is chosen if 976 * the partner has a better system priority 977 * or, the total aggregated speed is higher 978 * or, it is already the chosen aggregator 979 */ 980 if ((best_la != NULL && LACP_SYS_PRI(la->la_partner) < 981 LACP_SYS_PRI(best_la->la_partner)) || 982 speed > best_speed || 983 (speed == best_speed && 984 la == lsc->lsc_active_aggregator)) { 985 best_la = la; 986 best_speed = speed; 987 } 988 } 989 990 KASSERT(best_la == NULL || best_la->la_nports > 0, 991 ("invalid aggregator refcnt")); 992 KASSERT(best_la == NULL || !TAILQ_EMPTY(&best_la->la_ports), 993 ("invalid aggregator list")); 994 995 #if defined(LACP_DEBUG) 996 if (lsc->lsc_active_aggregator != best_la) { 997 LACP_DPRINTF((NULL, "active aggregator changed\n")); 998 LACP_DPRINTF((NULL, "old %s\n", 999 lacp_format_lagid_aggregator(lsc->lsc_active_aggregator, 1000 buf, sizeof(buf)))); 1001 } else { 1002 LACP_DPRINTF((NULL, "active aggregator not changed\n")); 1003 } 1004 LACP_DPRINTF((NULL, "new %s\n", 1005 lacp_format_lagid_aggregator(best_la, buf, sizeof(buf)))); 1006 #endif /* defined(LACP_DEBUG) */ 1007 1008 if (lsc->lsc_active_aggregator != best_la) { 1009 lsc->lsc_active_aggregator = best_la; 1010 if (best_la) { 1011 lacp_suppress_distributing(lsc, best_la); 1012 } 1013 } 1014 } 1015 1016 static uint16_t 1017 lacp_compose_key(struct lacp_port *lp) 1018 { 1019 struct lagg_port *lgp = lp->lp_lagg; 1020 struct lagg_softc *sc = lgp->lp_softc; 1021 u_int media = lp->lp_media; 1022 uint16_t key; 1023 1024 if ((lp->lp_state & LACP_STATE_AGGREGATION) == 0) { 1025 1026 /* 1027 * non-aggregatable links should have unique keys. 1028 * 1029 * XXX this isn't really unique as if_index is 16 bit. 1030 */ 1031 1032 /* bit 0..14: (some bits of) if_index of this port */ 1033 key = lp->lp_ifp->if_index; 1034 /* bit 15: 1 */ 1035 key |= 0x8000; 1036 } else { 1037 u_int subtype = IFM_SUBTYPE(media); 1038 1039 KASSERT(IFM_TYPE(media) == IFM_ETHER, ("invalid media type")); 1040 KASSERT((media & IFM_FDX) != 0, ("aggregating HDX interface")); 1041 1042 /* bit 0..4: IFM_SUBTYPE */ 1043 key = subtype; 1044 /* bit 5..14: (some bits of) if_index of lagg device */ 1045 key |= 0x7fe0 & ((sc->sc_ifp->if_index) << 5); 1046 /* bit 15: 0 */ 1047 } 1048 return (htons(key)); 1049 } 1050 1051 static void 1052 lacp_aggregator_addref(struct lacp_softc *lsc, struct lacp_aggregator *la) 1053 { 1054 #if defined(LACP_DEBUG) 1055 char buf[LACP_LAGIDSTR_MAX+1]; 1056 #endif 1057 1058 LACP_DPRINTF((NULL, "%s: lagid=%s, refcnt %d -> %d\n", 1059 __func__, 1060 lacp_format_lagid(&la->la_actor, &la->la_partner, 1061 buf, sizeof(buf)), 1062 la->la_refcnt, la->la_refcnt + 1)); 1063 1064 KASSERT(la->la_refcnt > 0, ("refcount <= 0")); 1065 la->la_refcnt++; 1066 KASSERT(la->la_refcnt > la->la_nports, ("invalid refcount")); 1067 } 1068 1069 static void 1070 lacp_aggregator_delref(struct lacp_softc *lsc, struct lacp_aggregator *la) 1071 { 1072 #if defined(LACP_DEBUG) 1073 char buf[LACP_LAGIDSTR_MAX+1]; 1074 #endif 1075 1076 LACP_DPRINTF((NULL, "%s: lagid=%s, refcnt %d -> %d\n", 1077 __func__, 1078 lacp_format_lagid(&la->la_actor, &la->la_partner, 1079 buf, sizeof(buf)), 1080 la->la_refcnt, la->la_refcnt - 1)); 1081 1082 KASSERT(la->la_refcnt > la->la_nports, ("invalid refcnt")); 1083 la->la_refcnt--; 1084 if (la->la_refcnt > 0) { 1085 return; 1086 } 1087 1088 KASSERT(la->la_refcnt == 0, ("refcount not zero")); 1089 KASSERT(lsc->lsc_active_aggregator != la, ("aggregator active")); 1090 1091 TAILQ_REMOVE(&lsc->lsc_aggregators, la, la_q); 1092 1093 free(la, M_DEVBUF); 1094 } 1095 1096 /* 1097 * lacp_aggregator_get: allocate an aggregator. 1098 */ 1099 1100 static struct lacp_aggregator * 1101 lacp_aggregator_get(struct lacp_softc *lsc, struct lacp_port *lp) 1102 { 1103 struct lacp_aggregator *la; 1104 1105 la = malloc(sizeof(*la), M_DEVBUF, M_NOWAIT); 1106 if (la) { 1107 la->la_refcnt = 1; 1108 la->la_nports = 0; 1109 TAILQ_INIT(&la->la_ports); 1110 la->la_pending = 0; 1111 TAILQ_INSERT_TAIL(&lsc->lsc_aggregators, la, la_q); 1112 } 1113 1114 return (la); 1115 } 1116 1117 /* 1118 * lacp_fill_aggregator_id: setup a newly allocated aggregator from a port. 1119 */ 1120 1121 static void 1122 lacp_fill_aggregator_id(struct lacp_aggregator *la, const struct lacp_port *lp) 1123 { 1124 lacp_fill_aggregator_id_peer(&la->la_partner, &lp->lp_partner); 1125 lacp_fill_aggregator_id_peer(&la->la_actor, &lp->lp_actor); 1126 1127 la->la_actor.lip_state = lp->lp_state & LACP_STATE_AGGREGATION; 1128 } 1129 1130 static void 1131 lacp_fill_aggregator_id_peer(struct lacp_peerinfo *lpi_aggr, 1132 const struct lacp_peerinfo *lpi_port) 1133 { 1134 memset(lpi_aggr, 0, sizeof(*lpi_aggr)); 1135 lpi_aggr->lip_systemid = lpi_port->lip_systemid; 1136 lpi_aggr->lip_key = lpi_port->lip_key; 1137 } 1138 1139 /* 1140 * lacp_aggregator_is_compatible: check if a port can join to an aggregator. 1141 */ 1142 1143 static int 1144 lacp_aggregator_is_compatible(const struct lacp_aggregator *la, 1145 const struct lacp_port *lp) 1146 { 1147 if (!(lp->lp_state & LACP_STATE_AGGREGATION) || 1148 !(lp->lp_partner.lip_state & LACP_STATE_AGGREGATION)) { 1149 return (0); 1150 } 1151 1152 if (!(la->la_actor.lip_state & LACP_STATE_AGGREGATION)) { 1153 return (0); 1154 } 1155 1156 if (!lacp_peerinfo_is_compatible(&la->la_partner, &lp->lp_partner)) { 1157 return (0); 1158 } 1159 1160 if (!lacp_peerinfo_is_compatible(&la->la_actor, &lp->lp_actor)) { 1161 return (0); 1162 } 1163 1164 return (1); 1165 } 1166 1167 static int 1168 lacp_peerinfo_is_compatible(const struct lacp_peerinfo *a, 1169 const struct lacp_peerinfo *b) 1170 { 1171 if (memcmp(&a->lip_systemid, &b->lip_systemid, 1172 sizeof(a->lip_systemid))) { 1173 return (0); 1174 } 1175 1176 if (memcmp(&a->lip_key, &b->lip_key, sizeof(a->lip_key))) { 1177 return (0); 1178 } 1179 1180 return (1); 1181 } 1182 1183 static void 1184 lacp_port_enable(struct lacp_port *lp) 1185 { 1186 struct lagg_port *lgp = lp->lp_lagg; 1187 1188 lp->lp_state |= LACP_STATE_AGGREGATION; 1189 lgp->lp_flags &= ~LAGG_PORT_DISABLED; 1190 } 1191 1192 static void 1193 lacp_port_disable(struct lacp_port *lp) 1194 { 1195 struct lagg_port *lgp = lp->lp_lagg; 1196 1197 lacp_set_mux(lp, LACP_MUX_DETACHED); 1198 1199 lp->lp_state &= ~LACP_STATE_AGGREGATION; 1200 lp->lp_selected = LACP_UNSELECTED; 1201 lacp_sm_rx_record_default(lp); 1202 lp->lp_partner.lip_state &= ~LACP_STATE_AGGREGATION; 1203 lp->lp_state &= ~LACP_STATE_EXPIRED; 1204 lgp->lp_flags |= LAGG_PORT_DISABLED; 1205 } 1206 1207 /* 1208 * lacp_select: select an aggregator. create one if necessary. 1209 */ 1210 static void 1211 lacp_select(struct lacp_port *lp) 1212 { 1213 struct lacp_softc *lsc = lp->lp_lsc; 1214 struct lacp_aggregator *la; 1215 #if defined(LACP_DEBUG) 1216 char buf[LACP_LAGIDSTR_MAX+1]; 1217 #endif 1218 1219 if (lp->lp_aggregator) { 1220 return; 1221 } 1222 1223 KASSERT(!LACP_TIMER_ISARMED(lp, LACP_TIMER_WAIT_WHILE), 1224 ("timer_wait_while still active")); 1225 1226 LACP_DPRINTF((lp, "port lagid=%s\n", 1227 lacp_format_lagid(&lp->lp_actor, &lp->lp_partner, 1228 buf, sizeof(buf)))); 1229 1230 TAILQ_FOREACH(la, &lsc->lsc_aggregators, la_q) { 1231 if (lacp_aggregator_is_compatible(la, lp)) { 1232 break; 1233 } 1234 } 1235 1236 if (la == NULL) { 1237 la = lacp_aggregator_get(lsc, lp); 1238 if (la == NULL) { 1239 LACP_DPRINTF((lp, "aggregator creation failed\n")); 1240 1241 /* 1242 * will retry on the next tick. 1243 */ 1244 1245 return; 1246 } 1247 lacp_fill_aggregator_id(la, lp); 1248 LACP_DPRINTF((lp, "aggregator created\n")); 1249 } else { 1250 LACP_DPRINTF((lp, "compatible aggregator found\n")); 1251 lacp_aggregator_addref(lsc, la); 1252 } 1253 1254 LACP_DPRINTF((lp, "aggregator lagid=%s\n", 1255 lacp_format_lagid(&la->la_actor, &la->la_partner, 1256 buf, sizeof(buf)))); 1257 1258 lp->lp_aggregator = la; 1259 lp->lp_selected = LACP_SELECTED; 1260 } 1261 1262 /* 1263 * lacp_unselect: finish unselect/detach process. 1264 */ 1265 1266 static void 1267 lacp_unselect(struct lacp_port *lp) 1268 { 1269 struct lacp_softc *lsc = lp->lp_lsc; 1270 struct lacp_aggregator *la = lp->lp_aggregator; 1271 1272 KASSERT(!LACP_TIMER_ISARMED(lp, LACP_TIMER_WAIT_WHILE), 1273 ("timer_wait_while still active")); 1274 1275 if (la == NULL) { 1276 return; 1277 } 1278 1279 lp->lp_aggregator = NULL; 1280 lacp_aggregator_delref(lsc, la); 1281 } 1282 1283 /* mux machine */ 1284 1285 static void 1286 lacp_sm_mux(struct lacp_port *lp) 1287 { 1288 enum lacp_mux_state new_state; 1289 boolean_t p_sync = 1290 (lp->lp_partner.lip_state & LACP_STATE_SYNC) != 0; 1291 boolean_t p_collecting = 1292 (lp->lp_partner.lip_state & LACP_STATE_COLLECTING) != 0; 1293 enum lacp_selected selected = lp->lp_selected; 1294 struct lacp_aggregator *la; 1295 1296 /* LACP_DPRINTF((lp, "%s: state %d\n", __func__, lp->lp_mux_state)); */ 1297 1298 re_eval: 1299 la = lp->lp_aggregator; 1300 KASSERT(lp->lp_mux_state == LACP_MUX_DETACHED || la != NULL, 1301 ("MUX not detached")); 1302 new_state = lp->lp_mux_state; 1303 switch (lp->lp_mux_state) { 1304 case LACP_MUX_DETACHED: 1305 if (selected != LACP_UNSELECTED) { 1306 new_state = LACP_MUX_WAITING; 1307 } 1308 break; 1309 case LACP_MUX_WAITING: 1310 KASSERT(la->la_pending > 0 || 1311 !LACP_TIMER_ISARMED(lp, LACP_TIMER_WAIT_WHILE), 1312 ("timer_wait_while still active")); 1313 if (selected == LACP_SELECTED && la->la_pending == 0) { 1314 new_state = LACP_MUX_ATTACHED; 1315 } else if (selected == LACP_UNSELECTED) { 1316 new_state = LACP_MUX_DETACHED; 1317 } 1318 break; 1319 case LACP_MUX_ATTACHED: 1320 if (selected == LACP_SELECTED && p_sync) { 1321 new_state = LACP_MUX_COLLECTING; 1322 } else if (selected != LACP_SELECTED) { 1323 new_state = LACP_MUX_DETACHED; 1324 } 1325 break; 1326 case LACP_MUX_COLLECTING: 1327 if (selected == LACP_SELECTED && p_sync && p_collecting) { 1328 new_state = LACP_MUX_DISTRIBUTING; 1329 } else if (selected != LACP_SELECTED || !p_sync) { 1330 new_state = LACP_MUX_ATTACHED; 1331 } 1332 break; 1333 case LACP_MUX_DISTRIBUTING: 1334 if (selected != LACP_SELECTED || !p_sync || !p_collecting) { 1335 new_state = LACP_MUX_COLLECTING; 1336 } 1337 break; 1338 default: 1339 panic("%s: unknown state", __func__); 1340 } 1341 1342 if (lp->lp_mux_state == new_state) { 1343 return; 1344 } 1345 1346 lacp_set_mux(lp, new_state); 1347 goto re_eval; 1348 } 1349 1350 static void 1351 lacp_set_mux(struct lacp_port *lp, enum lacp_mux_state new_state) 1352 { 1353 struct lacp_aggregator *la = lp->lp_aggregator; 1354 1355 if (lp->lp_mux_state == new_state) { 1356 return; 1357 } 1358 1359 switch (new_state) { 1360 case LACP_MUX_DETACHED: 1361 lp->lp_state &= ~LACP_STATE_SYNC; 1362 lacp_disable_distributing(lp); 1363 lacp_disable_collecting(lp); 1364 lacp_sm_assert_ntt(lp); 1365 /* cancel timer */ 1366 if (LACP_TIMER_ISARMED(lp, LACP_TIMER_WAIT_WHILE)) { 1367 KASSERT(la->la_pending > 0, 1368 ("timer_wait_while not active")); 1369 la->la_pending--; 1370 } 1371 LACP_TIMER_DISARM(lp, LACP_TIMER_WAIT_WHILE); 1372 lacp_unselect(lp); 1373 break; 1374 case LACP_MUX_WAITING: 1375 LACP_TIMER_ARM(lp, LACP_TIMER_WAIT_WHILE, 1376 LACP_AGGREGATE_WAIT_TIME); 1377 la->la_pending++; 1378 break; 1379 case LACP_MUX_ATTACHED: 1380 lp->lp_state |= LACP_STATE_SYNC; 1381 lacp_disable_collecting(lp); 1382 lacp_sm_assert_ntt(lp); 1383 break; 1384 case LACP_MUX_COLLECTING: 1385 lacp_enable_collecting(lp); 1386 lacp_disable_distributing(lp); 1387 lacp_sm_assert_ntt(lp); 1388 break; 1389 case LACP_MUX_DISTRIBUTING: 1390 lacp_enable_distributing(lp); 1391 break; 1392 default: 1393 panic("%s: unknown state", __func__); 1394 } 1395 1396 LACP_DPRINTF((lp, "mux_state %d -> %d\n", lp->lp_mux_state, new_state)); 1397 1398 lp->lp_mux_state = new_state; 1399 } 1400 1401 static void 1402 lacp_sm_mux_timer(struct lacp_port *lp) 1403 { 1404 struct lacp_aggregator *la = lp->lp_aggregator; 1405 #if defined(LACP_DEBUG) 1406 char buf[LACP_LAGIDSTR_MAX+1]; 1407 #endif 1408 1409 KASSERT(la->la_pending > 0, ("no pending event")); 1410 1411 LACP_DPRINTF((lp, "%s: aggregator %s, pending %d -> %d\n", __func__, 1412 lacp_format_lagid(&la->la_actor, &la->la_partner, 1413 buf, sizeof(buf)), 1414 la->la_pending, la->la_pending - 1)); 1415 1416 la->la_pending--; 1417 } 1418 1419 /* periodic transmit machine */ 1420 1421 static void 1422 lacp_sm_ptx_update_timeout(struct lacp_port *lp, uint8_t oldpstate) 1423 { 1424 if (LACP_STATE_EQ(oldpstate, lp->lp_partner.lip_state, 1425 LACP_STATE_TIMEOUT)) { 1426 return; 1427 } 1428 1429 LACP_DPRINTF((lp, "partner timeout changed\n")); 1430 1431 /* 1432 * FAST_PERIODIC -> SLOW_PERIODIC 1433 * or 1434 * SLOW_PERIODIC (-> PERIODIC_TX) -> FAST_PERIODIC 1435 * 1436 * let lacp_sm_ptx_tx_schedule to update timeout. 1437 */ 1438 1439 LACP_TIMER_DISARM(lp, LACP_TIMER_PERIODIC); 1440 1441 /* 1442 * if timeout has been shortened, assert NTT. 1443 */ 1444 1445 if ((lp->lp_partner.lip_state & LACP_STATE_TIMEOUT)) { 1446 lacp_sm_assert_ntt(lp); 1447 } 1448 } 1449 1450 static void 1451 lacp_sm_ptx_tx_schedule(struct lacp_port *lp) 1452 { 1453 int timeout; 1454 1455 if (!(lp->lp_state & LACP_STATE_ACTIVITY) && 1456 !(lp->lp_partner.lip_state & LACP_STATE_ACTIVITY)) { 1457 1458 /* 1459 * NO_PERIODIC 1460 */ 1461 1462 LACP_TIMER_DISARM(lp, LACP_TIMER_PERIODIC); 1463 return; 1464 } 1465 1466 if (LACP_TIMER_ISARMED(lp, LACP_TIMER_PERIODIC)) { 1467 return; 1468 } 1469 1470 timeout = (lp->lp_partner.lip_state & LACP_STATE_TIMEOUT) ? 1471 LACP_FAST_PERIODIC_TIME : LACP_SLOW_PERIODIC_TIME; 1472 1473 LACP_TIMER_ARM(lp, LACP_TIMER_PERIODIC, timeout); 1474 } 1475 1476 static void 1477 lacp_sm_ptx_timer(struct lacp_port *lp) 1478 { 1479 lacp_sm_assert_ntt(lp); 1480 } 1481 1482 static void 1483 lacp_sm_rx(struct lacp_port *lp, const struct lacpdu *du) 1484 { 1485 int timeout; 1486 1487 /* 1488 * check LACP_DISABLED first 1489 */ 1490 1491 if (!(lp->lp_state & LACP_STATE_AGGREGATION)) { 1492 return; 1493 } 1494 1495 /* 1496 * check loopback condition. 1497 */ 1498 1499 if (!lacp_compare_systemid(&du->ldu_actor.lip_systemid, 1500 &lp->lp_actor.lip_systemid)) { 1501 return; 1502 } 1503 1504 /* 1505 * EXPIRED, DEFAULTED, CURRENT -> CURRENT 1506 */ 1507 1508 lacp_sm_rx_update_selected(lp, du); 1509 lacp_sm_rx_update_ntt(lp, du); 1510 lacp_sm_rx_record_pdu(lp, du); 1511 1512 timeout = (lp->lp_state & LACP_STATE_TIMEOUT) ? 1513 LACP_SHORT_TIMEOUT_TIME : LACP_LONG_TIMEOUT_TIME; 1514 LACP_TIMER_ARM(lp, LACP_TIMER_CURRENT_WHILE, timeout); 1515 1516 lp->lp_state &= ~LACP_STATE_EXPIRED; 1517 1518 /* 1519 * kick transmit machine without waiting the next tick. 1520 */ 1521 1522 lacp_sm_tx(lp); 1523 } 1524 1525 static void 1526 lacp_sm_rx_set_expired(struct lacp_port *lp) 1527 { 1528 lp->lp_partner.lip_state &= ~LACP_STATE_SYNC; 1529 lp->lp_partner.lip_state |= LACP_STATE_TIMEOUT; 1530 LACP_TIMER_ARM(lp, LACP_TIMER_CURRENT_WHILE, LACP_SHORT_TIMEOUT_TIME); 1531 lp->lp_state |= LACP_STATE_EXPIRED; 1532 } 1533 1534 static void 1535 lacp_sm_rx_timer(struct lacp_port *lp) 1536 { 1537 if ((lp->lp_state & LACP_STATE_EXPIRED) == 0) { 1538 /* CURRENT -> EXPIRED */ 1539 LACP_DPRINTF((lp, "%s: CURRENT -> EXPIRED\n", __func__)); 1540 lacp_sm_rx_set_expired(lp); 1541 } else { 1542 /* EXPIRED -> DEFAULTED */ 1543 LACP_DPRINTF((lp, "%s: EXPIRED -> DEFAULTED\n", __func__)); 1544 lacp_sm_rx_update_default_selected(lp); 1545 lacp_sm_rx_record_default(lp); 1546 lp->lp_state &= ~LACP_STATE_EXPIRED; 1547 } 1548 } 1549 1550 static void 1551 lacp_sm_rx_record_pdu(struct lacp_port *lp, const struct lacpdu *du) 1552 { 1553 boolean_t active; 1554 uint8_t oldpstate; 1555 #if defined(LACP_DEBUG) 1556 char buf[LACP_STATESTR_MAX+1]; 1557 #endif 1558 1559 /* LACP_DPRINTF((lp, "%s\n", __func__)); */ 1560 1561 oldpstate = lp->lp_partner.lip_state; 1562 1563 active = (du->ldu_actor.lip_state & LACP_STATE_ACTIVITY) 1564 || ((lp->lp_state & LACP_STATE_ACTIVITY) && 1565 (du->ldu_partner.lip_state & LACP_STATE_ACTIVITY)); 1566 1567 lp->lp_partner = du->ldu_actor; 1568 if (active && 1569 ((LACP_STATE_EQ(lp->lp_state, du->ldu_partner.lip_state, 1570 LACP_STATE_AGGREGATION) && 1571 !lacp_compare_peerinfo(&lp->lp_actor, &du->ldu_partner)) 1572 || (du->ldu_partner.lip_state & LACP_STATE_AGGREGATION) == 0)) { 1573 /* XXX nothing? */ 1574 } else { 1575 lp->lp_partner.lip_state &= ~LACP_STATE_SYNC; 1576 } 1577 1578 lp->lp_state &= ~LACP_STATE_DEFAULTED; 1579 1580 if (oldpstate != lp->lp_partner.lip_state) { 1581 LACP_DPRINTF((lp, "old pstate %s\n", 1582 lacp_format_state(oldpstate, buf, sizeof(buf)))); 1583 LACP_DPRINTF((lp, "new pstate %s\n", 1584 lacp_format_state(lp->lp_partner.lip_state, buf, 1585 sizeof(buf)))); 1586 } 1587 1588 lacp_sm_ptx_update_timeout(lp, oldpstate); 1589 } 1590 1591 static void 1592 lacp_sm_rx_update_ntt(struct lacp_port *lp, const struct lacpdu *du) 1593 { 1594 /* LACP_DPRINTF((lp, "%s\n", __func__)); */ 1595 1596 if (lacp_compare_peerinfo(&lp->lp_actor, &du->ldu_partner) || 1597 !LACP_STATE_EQ(lp->lp_state, du->ldu_partner.lip_state, 1598 LACP_STATE_ACTIVITY | LACP_STATE_SYNC | LACP_STATE_AGGREGATION)) { 1599 LACP_DPRINTF((lp, "%s: assert ntt\n", __func__)); 1600 lacp_sm_assert_ntt(lp); 1601 } 1602 } 1603 1604 static void 1605 lacp_sm_rx_record_default(struct lacp_port *lp) 1606 { 1607 uint8_t oldpstate; 1608 1609 /* LACP_DPRINTF((lp, "%s\n", __func__)); */ 1610 1611 oldpstate = lp->lp_partner.lip_state; 1612 lp->lp_partner = lacp_partner_admin; 1613 lp->lp_state |= LACP_STATE_DEFAULTED; 1614 lacp_sm_ptx_update_timeout(lp, oldpstate); 1615 } 1616 1617 static void 1618 lacp_sm_rx_update_selected_from_peerinfo(struct lacp_port *lp, 1619 const struct lacp_peerinfo *info) 1620 { 1621 /* LACP_DPRINTF((lp, "%s\n", __func__)); */ 1622 1623 if (lacp_compare_peerinfo(&lp->lp_partner, info) || 1624 !LACP_STATE_EQ(lp->lp_partner.lip_state, info->lip_state, 1625 LACP_STATE_AGGREGATION)) { 1626 lp->lp_selected = LACP_UNSELECTED; 1627 /* mux machine will clean up lp->lp_aggregator */ 1628 } 1629 } 1630 1631 static void 1632 lacp_sm_rx_update_selected(struct lacp_port *lp, const struct lacpdu *du) 1633 { 1634 /* LACP_DPRINTF((lp, "%s\n", __func__)); */ 1635 1636 lacp_sm_rx_update_selected_from_peerinfo(lp, &du->ldu_actor); 1637 } 1638 1639 static void 1640 lacp_sm_rx_update_default_selected(struct lacp_port *lp) 1641 { 1642 /* LACP_DPRINTF((lp, "%s\n", __func__)); */ 1643 1644 lacp_sm_rx_update_selected_from_peerinfo(lp, &lacp_partner_admin); 1645 } 1646 1647 /* transmit machine */ 1648 1649 static void 1650 lacp_sm_tx(struct lacp_port *lp) 1651 { 1652 int error; 1653 1654 if (!(lp->lp_state & LACP_STATE_AGGREGATION) 1655 #if 1 1656 || (!(lp->lp_state & LACP_STATE_ACTIVITY) 1657 && !(lp->lp_partner.lip_state & LACP_STATE_ACTIVITY)) 1658 #endif 1659 ) { 1660 lp->lp_flags &= ~LACP_PORT_NTT; 1661 } 1662 1663 if (!(lp->lp_flags & LACP_PORT_NTT)) { 1664 return; 1665 } 1666 1667 /* Rate limit to 3 PDUs per LACP_FAST_PERIODIC_TIME */ 1668 if (ppsratecheck(&lp->lp_last_lacpdu, &lp->lp_lacpdu_sent, 1669 (3 / LACP_FAST_PERIODIC_TIME)) == 0) { 1670 LACP_DPRINTF((lp, "rate limited pdu\n")); 1671 return; 1672 } 1673 1674 error = lacp_xmit_lacpdu(lp); 1675 1676 if (error == 0) { 1677 lp->lp_flags &= ~LACP_PORT_NTT; 1678 } else { 1679 LACP_DPRINTF((lp, "lacpdu transmit failure, error %d\n", 1680 error)); 1681 } 1682 } 1683 1684 static void 1685 lacp_sm_assert_ntt(struct lacp_port *lp) 1686 { 1687 1688 lp->lp_flags |= LACP_PORT_NTT; 1689 } 1690 1691 static void 1692 lacp_run_timers(struct lacp_port *lp) 1693 { 1694 int i; 1695 1696 for (i = 0; i < LACP_NTIMER; i++) { 1697 KASSERT(lp->lp_timer[i] >= 0, 1698 ("invalid timer value %d", lp->lp_timer[i])); 1699 if (lp->lp_timer[i] == 0) { 1700 continue; 1701 } else if (--lp->lp_timer[i] <= 0) { 1702 if (lacp_timer_funcs[i]) { 1703 (*lacp_timer_funcs[i])(lp); 1704 } 1705 } 1706 } 1707 } 1708 1709 int 1710 lacp_marker_input(struct lagg_port *lgp, struct mbuf *m) 1711 { 1712 struct lacp_port *lp = LACP_PORT(lgp); 1713 struct lacp_port *lp2; 1714 struct lacp_softc *lsc = lp->lp_lsc; 1715 struct markerdu *mdu; 1716 int error = 0; 1717 int pending = 0; 1718 1719 LAGG_RLOCK_ASSERT(lgp->lp_softc); 1720 1721 if (m->m_pkthdr.len != sizeof(*mdu)) { 1722 goto bad; 1723 } 1724 1725 if ((m->m_flags & M_MCAST) == 0) { 1726 goto bad; 1727 } 1728 1729 if (m->m_len < sizeof(*mdu)) { 1730 m = m_pullup(m, sizeof(*mdu)); 1731 if (m == NULL) { 1732 return (ENOMEM); 1733 } 1734 } 1735 1736 mdu = mtod(m, struct markerdu *); 1737 1738 if (memcmp(&mdu->mdu_eh.ether_dhost, 1739 ðermulticastaddr_slowprotocols, ETHER_ADDR_LEN)) { 1740 goto bad; 1741 } 1742 1743 if (mdu->mdu_sph.sph_version != 1) { 1744 goto bad; 1745 } 1746 1747 switch (mdu->mdu_tlv.tlv_type) { 1748 case MARKER_TYPE_INFO: 1749 if (tlv_check(mdu, sizeof(*mdu), &mdu->mdu_tlv, 1750 marker_info_tlv_template, TRUE)) { 1751 goto bad; 1752 } 1753 mdu->mdu_tlv.tlv_type = MARKER_TYPE_RESPONSE; 1754 memcpy(&mdu->mdu_eh.ether_dhost, 1755 ðermulticastaddr_slowprotocols, ETHER_ADDR_LEN); 1756 memcpy(&mdu->mdu_eh.ether_shost, 1757 lgp->lp_lladdr, ETHER_ADDR_LEN); 1758 error = lagg_enqueue(lp->lp_ifp, m); 1759 break; 1760 1761 case MARKER_TYPE_RESPONSE: 1762 if (tlv_check(mdu, sizeof(*mdu), &mdu->mdu_tlv, 1763 marker_response_tlv_template, TRUE)) { 1764 goto bad; 1765 } 1766 LACP_DPRINTF((lp, "marker response, port=%u, sys=%6D, id=%u\n", 1767 ntohs(mdu->mdu_info.mi_rq_port), mdu->mdu_info.mi_rq_system, 1768 ":", ntohl(mdu->mdu_info.mi_rq_xid))); 1769 1770 /* Verify that it is the last marker we sent out */ 1771 if (memcmp(&mdu->mdu_info, &lp->lp_marker, 1772 sizeof(struct lacp_markerinfo))) 1773 goto bad; 1774 1775 lp->lp_flags &= ~LACP_PORT_MARK; 1776 1777 if (lsc->lsc_suppress_distributing) { 1778 /* Check if any ports are waiting for a response */ 1779 LIST_FOREACH(lp2, &lsc->lsc_ports, lp_next) { 1780 if (lp2->lp_flags & LACP_PORT_MARK) { 1781 pending = 1; 1782 break; 1783 } 1784 } 1785 1786 if (pending == 0) { 1787 /* All interface queues are clear */ 1788 LACP_DPRINTF((NULL, "queue flush complete\n")); 1789 lsc->lsc_suppress_distributing = FALSE; 1790 } 1791 } 1792 1793 m_freem(m); 1794 break; 1795 1796 default: 1797 goto bad; 1798 } 1799 1800 return (error); 1801 1802 bad: 1803 LACP_DPRINTF((lp, "bad marker frame\n")); 1804 m_freem(m); 1805 return (EINVAL); 1806 } 1807 1808 static int 1809 tlv_check(const void *p, size_t size, const struct tlvhdr *tlv, 1810 const struct tlv_template *tmpl, boolean_t check_type) 1811 { 1812 while (/* CONSTCOND */ 1) { 1813 if ((const char *)tlv - (const char *)p + sizeof(*tlv) > size) { 1814 return (EINVAL); 1815 } 1816 if ((check_type && tlv->tlv_type != tmpl->tmpl_type) || 1817 tlv->tlv_length != tmpl->tmpl_length) { 1818 return (EINVAL); 1819 } 1820 if (tmpl->tmpl_type == 0) { 1821 break; 1822 } 1823 tlv = (const struct tlvhdr *) 1824 ((const char *)tlv + tlv->tlv_length); 1825 tmpl++; 1826 } 1827 1828 return (0); 1829 } 1830 1831 #if defined(LACP_DEBUG) 1832 const char * 1833 lacp_format_mac(const uint8_t *mac, char *buf, size_t buflen) 1834 { 1835 snprintf(buf, buflen, "%02X-%02X-%02X-%02X-%02X-%02X", 1836 (int)mac[0], 1837 (int)mac[1], 1838 (int)mac[2], 1839 (int)mac[3], 1840 (int)mac[4], 1841 (int)mac[5]); 1842 1843 return (buf); 1844 } 1845 1846 const char * 1847 lacp_format_systemid(const struct lacp_systemid *sysid, 1848 char *buf, size_t buflen) 1849 { 1850 char macbuf[LACP_MACSTR_MAX+1]; 1851 1852 snprintf(buf, buflen, "%04X,%s", 1853 ntohs(sysid->lsi_prio), 1854 lacp_format_mac(sysid->lsi_mac, macbuf, sizeof(macbuf))); 1855 1856 return (buf); 1857 } 1858 1859 const char * 1860 lacp_format_portid(const struct lacp_portid *portid, char *buf, size_t buflen) 1861 { 1862 snprintf(buf, buflen, "%04X,%04X", 1863 ntohs(portid->lpi_prio), 1864 ntohs(portid->lpi_portno)); 1865 1866 return (buf); 1867 } 1868 1869 const char * 1870 lacp_format_partner(const struct lacp_peerinfo *peer, char *buf, size_t buflen) 1871 { 1872 char sysid[LACP_SYSTEMIDSTR_MAX+1]; 1873 char portid[LACP_PORTIDSTR_MAX+1]; 1874 1875 snprintf(buf, buflen, "(%s,%04X,%s)", 1876 lacp_format_systemid(&peer->lip_systemid, sysid, sizeof(sysid)), 1877 ntohs(peer->lip_key), 1878 lacp_format_portid(&peer->lip_portid, portid, sizeof(portid))); 1879 1880 return (buf); 1881 } 1882 1883 const char * 1884 lacp_format_lagid(const struct lacp_peerinfo *a, 1885 const struct lacp_peerinfo *b, char *buf, size_t buflen) 1886 { 1887 char astr[LACP_PARTNERSTR_MAX+1]; 1888 char bstr[LACP_PARTNERSTR_MAX+1]; 1889 1890 #if 0 1891 /* 1892 * there's a convention to display small numbered peer 1893 * in the left. 1894 */ 1895 1896 if (lacp_compare_peerinfo(a, b) > 0) { 1897 const struct lacp_peerinfo *t; 1898 1899 t = a; 1900 a = b; 1901 b = t; 1902 } 1903 #endif 1904 1905 snprintf(buf, buflen, "[%s,%s]", 1906 lacp_format_partner(a, astr, sizeof(astr)), 1907 lacp_format_partner(b, bstr, sizeof(bstr))); 1908 1909 return (buf); 1910 } 1911 1912 const char * 1913 lacp_format_lagid_aggregator(const struct lacp_aggregator *la, 1914 char *buf, size_t buflen) 1915 { 1916 if (la == NULL) { 1917 return ("(none)"); 1918 } 1919 1920 return (lacp_format_lagid(&la->la_actor, &la->la_partner, buf, buflen)); 1921 } 1922 1923 const char * 1924 lacp_format_state(uint8_t state, char *buf, size_t buflen) 1925 { 1926 snprintf(buf, buflen, "%b", state, LACP_STATE_BITS); 1927 return (buf); 1928 } 1929 1930 static void 1931 lacp_dump_lacpdu(const struct lacpdu *du) 1932 { 1933 char buf[LACP_PARTNERSTR_MAX+1]; 1934 char buf2[LACP_STATESTR_MAX+1]; 1935 1936 printf("actor=%s\n", 1937 lacp_format_partner(&du->ldu_actor, buf, sizeof(buf))); 1938 printf("actor.state=%s\n", 1939 lacp_format_state(du->ldu_actor.lip_state, buf2, sizeof(buf2))); 1940 printf("partner=%s\n", 1941 lacp_format_partner(&du->ldu_partner, buf, sizeof(buf))); 1942 printf("partner.state=%s\n", 1943 lacp_format_state(du->ldu_partner.lip_state, buf2, sizeof(buf2))); 1944 1945 printf("maxdelay=%d\n", ntohs(du->ldu_collector.lci_maxdelay)); 1946 } 1947 1948 static void 1949 lacp_dprintf(const struct lacp_port *lp, const char *fmt, ...) 1950 { 1951 va_list va; 1952 1953 if (lp) { 1954 printf("%s: ", lp->lp_ifp->if_xname); 1955 } 1956 1957 va_start(va, fmt); 1958 vprintf(fmt, va); 1959 va_end(va); 1960 } 1961 #endif 1962