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 void 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; 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 /* Unknown LACP packet type */ 241 m_freem(m); 242 break; 243 } 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 lagg_softc *sc = lsc->lsc_softc; 501 struct lacp_port *lp; 502 503 LAGG_WLOCK(sc); 504 LIST_FOREACH(lp, &lsc->lsc_ports, lp_next) { 505 if ((lp->lp_state & LACP_STATE_AGGREGATION) == 0) 506 continue; 507 508 lacp_run_timers(lp); 509 510 lacp_select(lp); 511 lacp_sm_mux(lp); 512 lacp_sm_tx(lp); 513 lacp_sm_ptx_tx_schedule(lp); 514 } 515 LAGG_WUNLOCK(sc); 516 callout_reset(&lsc->lsc_callout, hz, lacp_tick, lsc); 517 } 518 519 int 520 lacp_port_create(struct lagg_port *lgp) 521 { 522 struct lagg_softc *sc = lgp->lp_softc; 523 struct lacp_softc *lsc = LACP_SOFTC(sc); 524 struct lacp_port *lp; 525 struct ifnet *ifp = lgp->lp_ifp; 526 struct sockaddr_dl sdl; 527 struct ifmultiaddr *rifma = NULL; 528 int error; 529 530 boolean_t active = TRUE; /* XXX should be configurable */ 531 boolean_t fast = FALSE; /* XXX should be configurable */ 532 533 LAGG_WLOCK_ASSERT(sc); 534 535 bzero((char *)&sdl, sizeof(sdl)); 536 sdl.sdl_len = sizeof(sdl); 537 sdl.sdl_family = AF_LINK; 538 sdl.sdl_index = ifp->if_index; 539 sdl.sdl_type = IFT_ETHER; 540 sdl.sdl_alen = ETHER_ADDR_LEN; 541 542 bcopy(ðermulticastaddr_slowprotocols, 543 LLADDR(&sdl), ETHER_ADDR_LEN); 544 error = if_addmulti(ifp, (struct sockaddr *)&sdl, &rifma); 545 if (error) { 546 printf("%s: ADDMULTI failed on %s\n", __func__, lgp->lp_ifname); 547 return (error); 548 } 549 550 lp = malloc(sizeof(struct lacp_port), 551 M_DEVBUF, M_NOWAIT|M_ZERO); 552 if (lp == NULL) 553 return (ENOMEM); 554 555 lgp->lp_psc = (caddr_t)lp; 556 lp->lp_ifp = ifp; 557 lp->lp_lagg = lgp; 558 lp->lp_lsc = lsc; 559 lp->lp_ifma = rifma; 560 561 LIST_INSERT_HEAD(&lsc->lsc_ports, lp, lp_next); 562 563 lacp_fill_actorinfo(lp, &lp->lp_actor); 564 lacp_fill_markerinfo(lp, &lp->lp_marker); 565 lp->lp_state = 566 (active ? LACP_STATE_ACTIVITY : 0) | 567 (fast ? LACP_STATE_TIMEOUT : 0); 568 lp->lp_aggregator = NULL; 569 lacp_linkstate(lgp); 570 lacp_sm_rx_set_expired(lp); 571 572 return (0); 573 } 574 575 void 576 lacp_port_destroy(struct lagg_port *lgp) 577 { 578 struct lacp_port *lp = LACP_PORT(lgp); 579 int i; 580 581 LAGG_WLOCK_ASSERT(lgp->lp_softc); 582 583 for (i = 0; i < LACP_NTIMER; i++) { 584 LACP_TIMER_DISARM(lp, i); 585 } 586 587 lacp_disable_collecting(lp); 588 lacp_disable_distributing(lp); 589 lacp_unselect(lp); 590 lgp->lp_flags &= ~LAGG_PORT_DISABLED; 591 592 /* The address may have already been removed by if_purgemaddrs() */ 593 if (!lgp->lp_detaching) 594 if_delmulti_ifma(lp->lp_ifma); 595 596 LIST_REMOVE(lp, lp_next); 597 free(lp, M_DEVBUF); 598 } 599 600 int 601 lacp_port_isactive(struct lagg_port *lgp) 602 { 603 struct lacp_port *lp = LACP_PORT(lgp); 604 struct lacp_softc *lsc = lp->lp_lsc; 605 struct lacp_aggregator *la = lp->lp_aggregator; 606 607 /* This port is joined to the active aggregator */ 608 if (la != NULL && la == lsc->lsc_active_aggregator) 609 return (1); 610 611 return (0); 612 } 613 614 void 615 lacp_req(struct lagg_softc *sc, caddr_t data) 616 { 617 struct lacp_opreq *req = (struct lacp_opreq *)data; 618 struct lacp_softc *lsc = LACP_SOFTC(sc); 619 struct lacp_aggregator *la = lsc->lsc_active_aggregator; 620 621 bzero(req, sizeof(struct lacp_opreq)); 622 if (la != NULL) { 623 req->actor_prio = ntohs(la->la_actor.lip_systemid.lsi_prio); 624 memcpy(&req->actor_mac, &la->la_actor.lip_systemid.lsi_mac, 625 ETHER_ADDR_LEN); 626 req->actor_key = ntohs(la->la_actor.lip_key); 627 req->actor_portprio = ntohs(la->la_actor.lip_portid.lpi_prio); 628 req->actor_portno = ntohs(la->la_actor.lip_portid.lpi_portno); 629 req->actor_state = la->la_actor.lip_state; 630 631 req->partner_prio = ntohs(la->la_partner.lip_systemid.lsi_prio); 632 memcpy(&req->partner_mac, &la->la_partner.lip_systemid.lsi_mac, 633 ETHER_ADDR_LEN); 634 req->partner_key = ntohs(la->la_partner.lip_key); 635 req->partner_portprio = ntohs(la->la_partner.lip_portid.lpi_prio); 636 req->partner_portno = ntohs(la->la_partner.lip_portid.lpi_portno); 637 req->partner_state = la->la_partner.lip_state; 638 } 639 } 640 641 void 642 lacp_portreq(struct lagg_port *lgp, caddr_t data) 643 { 644 struct lacp_opreq *req = (struct lacp_opreq *)data; 645 struct lacp_port *lp = LACP_PORT(lgp); 646 647 req->actor_prio = ntohs(lp->lp_actor.lip_systemid.lsi_prio); 648 memcpy(&req->actor_mac, &lp->lp_actor.lip_systemid.lsi_mac, 649 ETHER_ADDR_LEN); 650 req->actor_key = ntohs(lp->lp_actor.lip_key); 651 req->actor_portprio = ntohs(lp->lp_actor.lip_portid.lpi_prio); 652 req->actor_portno = ntohs(lp->lp_actor.lip_portid.lpi_portno); 653 req->actor_state = lp->lp_actor.lip_state; 654 655 req->partner_prio = ntohs(lp->lp_partner.lip_systemid.lsi_prio); 656 memcpy(&req->partner_mac, &lp->lp_partner.lip_systemid.lsi_mac, 657 ETHER_ADDR_LEN); 658 req->partner_key = ntohs(lp->lp_partner.lip_key); 659 req->partner_portprio = ntohs(lp->lp_partner.lip_portid.lpi_prio); 660 req->partner_portno = ntohs(lp->lp_partner.lip_portid.lpi_portno); 661 req->partner_state = lp->lp_partner.lip_state; 662 } 663 664 static void 665 lacp_disable_collecting(struct lacp_port *lp) 666 { 667 struct lagg_port *lgp = lp->lp_lagg; 668 669 LACP_DPRINTF((lp, "collecting disabled\n")); 670 671 lp->lp_state &= ~LACP_STATE_COLLECTING; 672 lgp->lp_flags &= ~LAGG_PORT_COLLECTING; 673 } 674 675 static void 676 lacp_enable_collecting(struct lacp_port *lp) 677 { 678 struct lagg_port *lgp = lp->lp_lagg; 679 680 LACP_DPRINTF((lp, "collecting enabled\n")); 681 682 lp->lp_state |= LACP_STATE_COLLECTING; 683 lgp->lp_flags |= LAGG_PORT_COLLECTING; 684 } 685 686 static void 687 lacp_disable_distributing(struct lacp_port *lp) 688 { 689 struct lacp_aggregator *la = lp->lp_aggregator; 690 struct lacp_softc *lsc = lp->lp_lsc; 691 struct lagg_port *lgp = lp->lp_lagg; 692 #if defined(LACP_DEBUG) 693 char buf[LACP_LAGIDSTR_MAX+1]; 694 #endif /* defined(LACP_DEBUG) */ 695 696 LAGG_WLOCK_ASSERT(lgp->lp_softc); 697 698 if (la == NULL || (lp->lp_state & LACP_STATE_DISTRIBUTING) == 0) { 699 return; 700 } 701 702 KASSERT(!TAILQ_EMPTY(&la->la_ports), ("no aggregator ports")); 703 KASSERT(la->la_nports > 0, ("nports invalid (%d)", la->la_nports)); 704 KASSERT(la->la_refcnt >= la->la_nports, ("aggregator refcnt invalid")); 705 706 LACP_DPRINTF((lp, "disable distributing on aggregator %s, " 707 "nports %d -> %d\n", 708 lacp_format_lagid_aggregator(la, buf, sizeof(buf)), 709 la->la_nports, la->la_nports - 1)); 710 711 TAILQ_REMOVE(&la->la_ports, lp, lp_dist_q); 712 la->la_nports--; 713 714 lacp_suppress_distributing(lsc, la); 715 716 lp->lp_state &= ~LACP_STATE_DISTRIBUTING; 717 lgp->lp_flags &= ~LAGG_PORT_DISTRIBUTING; 718 719 if (lsc->lsc_active_aggregator == la) { 720 lacp_select_active_aggregator(lsc); 721 } 722 } 723 724 static void 725 lacp_enable_distributing(struct lacp_port *lp) 726 { 727 struct lacp_aggregator *la = lp->lp_aggregator; 728 struct lacp_softc *lsc = lp->lp_lsc; 729 struct lagg_port *lgp = lp->lp_lagg; 730 #if defined(LACP_DEBUG) 731 char buf[LACP_LAGIDSTR_MAX+1]; 732 #endif /* defined(LACP_DEBUG) */ 733 734 LAGG_WLOCK_ASSERT(lgp->lp_softc); 735 736 if ((lp->lp_state & LACP_STATE_DISTRIBUTING) != 0) { 737 return; 738 } 739 740 LACP_DPRINTF((lp, "enable distributing on aggregator %s, " 741 "nports %d -> %d\n", 742 lacp_format_lagid_aggregator(la, buf, sizeof(buf)), 743 la->la_nports, la->la_nports + 1)); 744 745 KASSERT(la->la_refcnt > la->la_nports, ("aggregator refcnt invalid")); 746 TAILQ_INSERT_HEAD(&la->la_ports, lp, lp_dist_q); 747 la->la_nports++; 748 749 lacp_suppress_distributing(lsc, la); 750 751 lp->lp_state |= LACP_STATE_DISTRIBUTING; 752 lgp->lp_flags |= LAGG_PORT_DISTRIBUTING; 753 754 if (lsc->lsc_active_aggregator != la) { 755 lacp_select_active_aggregator(lsc); 756 } 757 } 758 759 static void 760 lacp_transit_expire(void *vp) 761 { 762 struct lacp_softc *lsc = vp; 763 764 LACP_DPRINTF((NULL, "%s\n", __func__)); 765 lsc->lsc_suppress_distributing = FALSE; 766 } 767 768 int 769 lacp_attach(struct lagg_softc *sc) 770 { 771 struct lacp_softc *lsc; 772 773 LAGG_WLOCK_ASSERT(sc); 774 775 lsc = malloc(sizeof(struct lacp_softc), 776 M_DEVBUF, M_NOWAIT|M_ZERO); 777 if (lsc == NULL) 778 return (ENOMEM); 779 780 sc->sc_psc = (caddr_t)lsc; 781 lsc->lsc_softc = sc; 782 783 lsc->lsc_hashkey = arc4random(); 784 lsc->lsc_active_aggregator = NULL; 785 TAILQ_INIT(&lsc->lsc_aggregators); 786 LIST_INIT(&lsc->lsc_ports); 787 788 TASK_INIT(&lsc->lsc_qtask, 0, lacp_dequeue, lsc); 789 mtx_init(&lsc->lsc_queue.ifq_mtx, "lacp queue", NULL, MTX_DEF); 790 lsc->lsc_queue.ifq_maxlen = ifqmaxlen; 791 792 callout_init(&lsc->lsc_transit_callout, CALLOUT_MPSAFE); 793 callout_init(&lsc->lsc_callout, CALLOUT_MPSAFE); 794 795 /* if the lagg is already up then do the same */ 796 if (sc->sc_ifp->if_drv_flags & IFF_DRV_RUNNING) 797 lacp_init(sc); 798 799 return (0); 800 } 801 802 int 803 lacp_detach(struct lagg_softc *sc) 804 { 805 struct lacp_softc *lsc = LACP_SOFTC(sc); 806 807 KASSERT(TAILQ_EMPTY(&lsc->lsc_aggregators), 808 ("aggregators still active")); 809 KASSERT(lsc->lsc_active_aggregator == NULL, 810 ("aggregator still attached")); 811 812 sc->sc_psc = NULL; 813 callout_drain(&lsc->lsc_transit_callout); 814 callout_drain(&lsc->lsc_callout); 815 taskqueue_drain(taskqueue_swi, &lsc->lsc_qtask); 816 IF_DRAIN(&lsc->lsc_queue); 817 mtx_destroy(&lsc->lsc_queue.ifq_mtx); 818 819 free(lsc, M_DEVBUF); 820 return (0); 821 } 822 823 void 824 lacp_init(struct lagg_softc *sc) 825 { 826 struct lacp_softc *lsc = LACP_SOFTC(sc); 827 828 callout_reset(&lsc->lsc_callout, hz, lacp_tick, lsc); 829 } 830 831 void 832 lacp_stop(struct lagg_softc *sc) 833 { 834 struct lacp_softc *lsc = LACP_SOFTC(sc); 835 836 callout_stop(&lsc->lsc_transit_callout); 837 callout_stop(&lsc->lsc_callout); 838 } 839 840 struct lagg_port * 841 lacp_select_tx_port(struct lagg_softc *sc, struct mbuf *m) 842 { 843 struct lacp_softc *lsc = LACP_SOFTC(sc); 844 struct lacp_aggregator *la; 845 struct lacp_port *lp; 846 uint32_t hash; 847 int nports; 848 849 LAGG_RLOCK_ASSERT(sc); 850 851 if (__predict_false(lsc->lsc_suppress_distributing)) { 852 LACP_DPRINTF((NULL, "%s: waiting transit\n", __func__)); 853 return (NULL); 854 } 855 856 la = lsc->lsc_active_aggregator; 857 if (__predict_false(la == NULL)) { 858 LACP_DPRINTF((NULL, "%s: no active aggregator\n", __func__)); 859 return (NULL); 860 } 861 862 nports = la->la_nports; 863 KASSERT(nports > 0, ("no ports available")); 864 865 hash = lagg_hashmbuf(m, lsc->lsc_hashkey); 866 hash %= nports; 867 lp = TAILQ_FIRST(&la->la_ports); 868 while (hash--) { 869 lp = TAILQ_NEXT(lp, lp_dist_q); 870 } 871 872 KASSERT((lp->lp_state & LACP_STATE_DISTRIBUTING) != 0, 873 ("aggregated port is not distributing")); 874 875 return (lp->lp_lagg); 876 } 877 /* 878 * lacp_suppress_distributing: drop transmit packets for a while 879 * to preserve packet ordering. 880 */ 881 882 static void 883 lacp_suppress_distributing(struct lacp_softc *lsc, struct lacp_aggregator *la) 884 { 885 struct lacp_port *lp; 886 887 if (lsc->lsc_active_aggregator != la) { 888 return; 889 } 890 891 LACP_DPRINTF((NULL, "%s\n", __func__)); 892 lsc->lsc_suppress_distributing = TRUE; 893 894 /* send a marker frame down each port to verify the queues are empty */ 895 LIST_FOREACH(lp, &lsc->lsc_ports, lp_next) { 896 lp->lp_flags |= LACP_PORT_MARK; 897 lacp_xmit_marker(lp); 898 } 899 900 /* set a timeout for the marker frames */ 901 callout_reset(&lsc->lsc_transit_callout, 902 LACP_TRANSIT_DELAY * hz / 1000, lacp_transit_expire, lsc); 903 } 904 905 static int 906 lacp_compare_peerinfo(const struct lacp_peerinfo *a, 907 const struct lacp_peerinfo *b) 908 { 909 return (memcmp(a, b, offsetof(struct lacp_peerinfo, lip_state))); 910 } 911 912 static int 913 lacp_compare_systemid(const struct lacp_systemid *a, 914 const struct lacp_systemid *b) 915 { 916 return (memcmp(a, b, sizeof(*a))); 917 } 918 919 #if 0 /* unused */ 920 static int 921 lacp_compare_portid(const struct lacp_portid *a, 922 const struct lacp_portid *b) 923 { 924 return (memcmp(a, b, sizeof(*a))); 925 } 926 #endif 927 928 static uint64_t 929 lacp_aggregator_bandwidth(struct lacp_aggregator *la) 930 { 931 struct lacp_port *lp; 932 uint64_t speed; 933 934 lp = TAILQ_FIRST(&la->la_ports); 935 if (lp == NULL) { 936 return (0); 937 } 938 939 speed = ifmedia_baudrate(lp->lp_media); 940 speed *= la->la_nports; 941 if (speed == 0) { 942 LACP_DPRINTF((lp, "speed 0? media=0x%x nports=%d\n", 943 lp->lp_media, la->la_nports)); 944 } 945 946 return (speed); 947 } 948 949 /* 950 * lacp_select_active_aggregator: select an aggregator to be used to transmit 951 * packets from lagg(4) interface. 952 */ 953 954 static void 955 lacp_select_active_aggregator(struct lacp_softc *lsc) 956 { 957 struct lacp_aggregator *la; 958 struct lacp_aggregator *best_la = NULL; 959 uint64_t best_speed = 0; 960 #if defined(LACP_DEBUG) 961 char buf[LACP_LAGIDSTR_MAX+1]; 962 #endif /* defined(LACP_DEBUG) */ 963 964 LACP_DPRINTF((NULL, "%s:\n", __func__)); 965 966 TAILQ_FOREACH(la, &lsc->lsc_aggregators, la_q) { 967 uint64_t speed; 968 969 if (la->la_nports == 0) { 970 continue; 971 } 972 973 speed = lacp_aggregator_bandwidth(la); 974 LACP_DPRINTF((NULL, "%s, speed=%jd, nports=%d\n", 975 lacp_format_lagid_aggregator(la, buf, sizeof(buf)), 976 speed, la->la_nports)); 977 978 /* This aggregator is chosen if 979 * the partner has a better system priority 980 * or, the total aggregated speed is higher 981 * or, it is already the chosen aggregator 982 */ 983 if ((best_la != NULL && LACP_SYS_PRI(la->la_partner) < 984 LACP_SYS_PRI(best_la->la_partner)) || 985 speed > best_speed || 986 (speed == best_speed && 987 la == lsc->lsc_active_aggregator)) { 988 best_la = la; 989 best_speed = speed; 990 } 991 } 992 993 KASSERT(best_la == NULL || best_la->la_nports > 0, 994 ("invalid aggregator refcnt")); 995 KASSERT(best_la == NULL || !TAILQ_EMPTY(&best_la->la_ports), 996 ("invalid aggregator list")); 997 998 #if defined(LACP_DEBUG) 999 if (lsc->lsc_active_aggregator != best_la) { 1000 LACP_DPRINTF((NULL, "active aggregator changed\n")); 1001 LACP_DPRINTF((NULL, "old %s\n", 1002 lacp_format_lagid_aggregator(lsc->lsc_active_aggregator, 1003 buf, sizeof(buf)))); 1004 } else { 1005 LACP_DPRINTF((NULL, "active aggregator not changed\n")); 1006 } 1007 LACP_DPRINTF((NULL, "new %s\n", 1008 lacp_format_lagid_aggregator(best_la, buf, sizeof(buf)))); 1009 #endif /* defined(LACP_DEBUG) */ 1010 1011 if (lsc->lsc_active_aggregator != best_la) { 1012 lsc->lsc_active_aggregator = best_la; 1013 if (best_la) { 1014 lacp_suppress_distributing(lsc, best_la); 1015 } 1016 } 1017 } 1018 1019 static uint16_t 1020 lacp_compose_key(struct lacp_port *lp) 1021 { 1022 struct lagg_port *lgp = lp->lp_lagg; 1023 struct lagg_softc *sc = lgp->lp_softc; 1024 u_int media = lp->lp_media; 1025 uint16_t key; 1026 1027 if ((lp->lp_state & LACP_STATE_AGGREGATION) == 0) { 1028 1029 /* 1030 * non-aggregatable links should have unique keys. 1031 * 1032 * XXX this isn't really unique as if_index is 16 bit. 1033 */ 1034 1035 /* bit 0..14: (some bits of) if_index of this port */ 1036 key = lp->lp_ifp->if_index; 1037 /* bit 15: 1 */ 1038 key |= 0x8000; 1039 } else { 1040 u_int subtype = IFM_SUBTYPE(media); 1041 1042 KASSERT(IFM_TYPE(media) == IFM_ETHER, ("invalid media type")); 1043 KASSERT((media & IFM_FDX) != 0, ("aggregating HDX interface")); 1044 1045 /* bit 0..4: IFM_SUBTYPE */ 1046 key = subtype; 1047 /* bit 5..14: (some bits of) if_index of lagg device */ 1048 key |= 0x7fe0 & ((sc->sc_ifp->if_index) << 5); 1049 /* bit 15: 0 */ 1050 } 1051 return (htons(key)); 1052 } 1053 1054 static void 1055 lacp_aggregator_addref(struct lacp_softc *lsc, struct lacp_aggregator *la) 1056 { 1057 #if defined(LACP_DEBUG) 1058 char buf[LACP_LAGIDSTR_MAX+1]; 1059 #endif 1060 1061 LACP_DPRINTF((NULL, "%s: lagid=%s, refcnt %d -> %d\n", 1062 __func__, 1063 lacp_format_lagid(&la->la_actor, &la->la_partner, 1064 buf, sizeof(buf)), 1065 la->la_refcnt, la->la_refcnt + 1)); 1066 1067 KASSERT(la->la_refcnt > 0, ("refcount <= 0")); 1068 la->la_refcnt++; 1069 KASSERT(la->la_refcnt > la->la_nports, ("invalid refcount")); 1070 } 1071 1072 static void 1073 lacp_aggregator_delref(struct lacp_softc *lsc, struct lacp_aggregator *la) 1074 { 1075 #if defined(LACP_DEBUG) 1076 char buf[LACP_LAGIDSTR_MAX+1]; 1077 #endif 1078 1079 LACP_DPRINTF((NULL, "%s: lagid=%s, refcnt %d -> %d\n", 1080 __func__, 1081 lacp_format_lagid(&la->la_actor, &la->la_partner, 1082 buf, sizeof(buf)), 1083 la->la_refcnt, la->la_refcnt - 1)); 1084 1085 KASSERT(la->la_refcnt > la->la_nports, ("invalid refcnt")); 1086 la->la_refcnt--; 1087 if (la->la_refcnt > 0) { 1088 return; 1089 } 1090 1091 KASSERT(la->la_refcnt == 0, ("refcount not zero")); 1092 KASSERT(lsc->lsc_active_aggregator != la, ("aggregator active")); 1093 1094 TAILQ_REMOVE(&lsc->lsc_aggregators, la, la_q); 1095 1096 free(la, M_DEVBUF); 1097 } 1098 1099 /* 1100 * lacp_aggregator_get: allocate an aggregator. 1101 */ 1102 1103 static struct lacp_aggregator * 1104 lacp_aggregator_get(struct lacp_softc *lsc, struct lacp_port *lp) 1105 { 1106 struct lacp_aggregator *la; 1107 1108 la = malloc(sizeof(*la), M_DEVBUF, M_NOWAIT); 1109 if (la) { 1110 la->la_refcnt = 1; 1111 la->la_nports = 0; 1112 TAILQ_INIT(&la->la_ports); 1113 la->la_pending = 0; 1114 TAILQ_INSERT_TAIL(&lsc->lsc_aggregators, la, la_q); 1115 } 1116 1117 return (la); 1118 } 1119 1120 /* 1121 * lacp_fill_aggregator_id: setup a newly allocated aggregator from a port. 1122 */ 1123 1124 static void 1125 lacp_fill_aggregator_id(struct lacp_aggregator *la, const struct lacp_port *lp) 1126 { 1127 lacp_fill_aggregator_id_peer(&la->la_partner, &lp->lp_partner); 1128 lacp_fill_aggregator_id_peer(&la->la_actor, &lp->lp_actor); 1129 1130 la->la_actor.lip_state = lp->lp_state & LACP_STATE_AGGREGATION; 1131 } 1132 1133 static void 1134 lacp_fill_aggregator_id_peer(struct lacp_peerinfo *lpi_aggr, 1135 const struct lacp_peerinfo *lpi_port) 1136 { 1137 memset(lpi_aggr, 0, sizeof(*lpi_aggr)); 1138 lpi_aggr->lip_systemid = lpi_port->lip_systemid; 1139 lpi_aggr->lip_key = lpi_port->lip_key; 1140 } 1141 1142 /* 1143 * lacp_aggregator_is_compatible: check if a port can join to an aggregator. 1144 */ 1145 1146 static int 1147 lacp_aggregator_is_compatible(const struct lacp_aggregator *la, 1148 const struct lacp_port *lp) 1149 { 1150 if (!(lp->lp_state & LACP_STATE_AGGREGATION) || 1151 !(lp->lp_partner.lip_state & LACP_STATE_AGGREGATION)) { 1152 return (0); 1153 } 1154 1155 if (!(la->la_actor.lip_state & LACP_STATE_AGGREGATION)) { 1156 return (0); 1157 } 1158 1159 if (!lacp_peerinfo_is_compatible(&la->la_partner, &lp->lp_partner)) { 1160 return (0); 1161 } 1162 1163 if (!lacp_peerinfo_is_compatible(&la->la_actor, &lp->lp_actor)) { 1164 return (0); 1165 } 1166 1167 return (1); 1168 } 1169 1170 static int 1171 lacp_peerinfo_is_compatible(const struct lacp_peerinfo *a, 1172 const struct lacp_peerinfo *b) 1173 { 1174 if (memcmp(&a->lip_systemid, &b->lip_systemid, 1175 sizeof(a->lip_systemid))) { 1176 return (0); 1177 } 1178 1179 if (memcmp(&a->lip_key, &b->lip_key, sizeof(a->lip_key))) { 1180 return (0); 1181 } 1182 1183 return (1); 1184 } 1185 1186 static void 1187 lacp_port_enable(struct lacp_port *lp) 1188 { 1189 struct lagg_port *lgp = lp->lp_lagg; 1190 1191 lp->lp_state |= LACP_STATE_AGGREGATION; 1192 lgp->lp_flags &= ~LAGG_PORT_DISABLED; 1193 } 1194 1195 static void 1196 lacp_port_disable(struct lacp_port *lp) 1197 { 1198 struct lagg_port *lgp = lp->lp_lagg; 1199 1200 lacp_set_mux(lp, LACP_MUX_DETACHED); 1201 1202 lp->lp_state &= ~LACP_STATE_AGGREGATION; 1203 lp->lp_selected = LACP_UNSELECTED; 1204 lacp_sm_rx_record_default(lp); 1205 lp->lp_partner.lip_state &= ~LACP_STATE_AGGREGATION; 1206 lp->lp_state &= ~LACP_STATE_EXPIRED; 1207 lgp->lp_flags |= LAGG_PORT_DISABLED; 1208 } 1209 1210 /* 1211 * lacp_select: select an aggregator. create one if necessary. 1212 */ 1213 static void 1214 lacp_select(struct lacp_port *lp) 1215 { 1216 struct lacp_softc *lsc = lp->lp_lsc; 1217 struct lacp_aggregator *la; 1218 #if defined(LACP_DEBUG) 1219 char buf[LACP_LAGIDSTR_MAX+1]; 1220 #endif 1221 1222 if (lp->lp_aggregator) { 1223 return; 1224 } 1225 1226 KASSERT(!LACP_TIMER_ISARMED(lp, LACP_TIMER_WAIT_WHILE), 1227 ("timer_wait_while still active")); 1228 1229 LACP_DPRINTF((lp, "port lagid=%s\n", 1230 lacp_format_lagid(&lp->lp_actor, &lp->lp_partner, 1231 buf, sizeof(buf)))); 1232 1233 TAILQ_FOREACH(la, &lsc->lsc_aggregators, la_q) { 1234 if (lacp_aggregator_is_compatible(la, lp)) { 1235 break; 1236 } 1237 } 1238 1239 if (la == NULL) { 1240 la = lacp_aggregator_get(lsc, lp); 1241 if (la == NULL) { 1242 LACP_DPRINTF((lp, "aggregator creation failed\n")); 1243 1244 /* 1245 * will retry on the next tick. 1246 */ 1247 1248 return; 1249 } 1250 lacp_fill_aggregator_id(la, lp); 1251 LACP_DPRINTF((lp, "aggregator created\n")); 1252 } else { 1253 LACP_DPRINTF((lp, "compatible aggregator found\n")); 1254 lacp_aggregator_addref(lsc, la); 1255 } 1256 1257 LACP_DPRINTF((lp, "aggregator lagid=%s\n", 1258 lacp_format_lagid(&la->la_actor, &la->la_partner, 1259 buf, sizeof(buf)))); 1260 1261 lp->lp_aggregator = la; 1262 lp->lp_selected = LACP_SELECTED; 1263 } 1264 1265 /* 1266 * lacp_unselect: finish unselect/detach process. 1267 */ 1268 1269 static void 1270 lacp_unselect(struct lacp_port *lp) 1271 { 1272 struct lacp_softc *lsc = lp->lp_lsc; 1273 struct lacp_aggregator *la = lp->lp_aggregator; 1274 1275 KASSERT(!LACP_TIMER_ISARMED(lp, LACP_TIMER_WAIT_WHILE), 1276 ("timer_wait_while still active")); 1277 1278 if (la == NULL) { 1279 return; 1280 } 1281 1282 lp->lp_aggregator = NULL; 1283 lacp_aggregator_delref(lsc, la); 1284 } 1285 1286 /* mux machine */ 1287 1288 static void 1289 lacp_sm_mux(struct lacp_port *lp) 1290 { 1291 enum lacp_mux_state new_state; 1292 boolean_t p_sync = 1293 (lp->lp_partner.lip_state & LACP_STATE_SYNC) != 0; 1294 boolean_t p_collecting = 1295 (lp->lp_partner.lip_state & LACP_STATE_COLLECTING) != 0; 1296 enum lacp_selected selected = lp->lp_selected; 1297 struct lacp_aggregator *la; 1298 1299 /* LACP_DPRINTF((lp, "%s: state %d\n", __func__, lp->lp_mux_state)); */ 1300 1301 re_eval: 1302 la = lp->lp_aggregator; 1303 KASSERT(lp->lp_mux_state == LACP_MUX_DETACHED || la != NULL, 1304 ("MUX not detached")); 1305 new_state = lp->lp_mux_state; 1306 switch (lp->lp_mux_state) { 1307 case LACP_MUX_DETACHED: 1308 if (selected != LACP_UNSELECTED) { 1309 new_state = LACP_MUX_WAITING; 1310 } 1311 break; 1312 case LACP_MUX_WAITING: 1313 KASSERT(la->la_pending > 0 || 1314 !LACP_TIMER_ISARMED(lp, LACP_TIMER_WAIT_WHILE), 1315 ("timer_wait_while still active")); 1316 if (selected == LACP_SELECTED && la->la_pending == 0) { 1317 new_state = LACP_MUX_ATTACHED; 1318 } else if (selected == LACP_UNSELECTED) { 1319 new_state = LACP_MUX_DETACHED; 1320 } 1321 break; 1322 case LACP_MUX_ATTACHED: 1323 if (selected == LACP_SELECTED && p_sync) { 1324 new_state = LACP_MUX_COLLECTING; 1325 } else if (selected != LACP_SELECTED) { 1326 new_state = LACP_MUX_DETACHED; 1327 } 1328 break; 1329 case LACP_MUX_COLLECTING: 1330 if (selected == LACP_SELECTED && p_sync && p_collecting) { 1331 new_state = LACP_MUX_DISTRIBUTING; 1332 } else if (selected != LACP_SELECTED || !p_sync) { 1333 new_state = LACP_MUX_ATTACHED; 1334 } 1335 break; 1336 case LACP_MUX_DISTRIBUTING: 1337 if (selected != LACP_SELECTED || !p_sync || !p_collecting) { 1338 new_state = LACP_MUX_COLLECTING; 1339 } 1340 break; 1341 default: 1342 panic("%s: unknown state", __func__); 1343 } 1344 1345 if (lp->lp_mux_state == new_state) { 1346 return; 1347 } 1348 1349 lacp_set_mux(lp, new_state); 1350 goto re_eval; 1351 } 1352 1353 static void 1354 lacp_set_mux(struct lacp_port *lp, enum lacp_mux_state new_state) 1355 { 1356 struct lacp_aggregator *la = lp->lp_aggregator; 1357 1358 if (lp->lp_mux_state == new_state) { 1359 return; 1360 } 1361 1362 switch (new_state) { 1363 case LACP_MUX_DETACHED: 1364 lp->lp_state &= ~LACP_STATE_SYNC; 1365 lacp_disable_distributing(lp); 1366 lacp_disable_collecting(lp); 1367 lacp_sm_assert_ntt(lp); 1368 /* cancel timer */ 1369 if (LACP_TIMER_ISARMED(lp, LACP_TIMER_WAIT_WHILE)) { 1370 KASSERT(la->la_pending > 0, 1371 ("timer_wait_while not active")); 1372 la->la_pending--; 1373 } 1374 LACP_TIMER_DISARM(lp, LACP_TIMER_WAIT_WHILE); 1375 lacp_unselect(lp); 1376 break; 1377 case LACP_MUX_WAITING: 1378 LACP_TIMER_ARM(lp, LACP_TIMER_WAIT_WHILE, 1379 LACP_AGGREGATE_WAIT_TIME); 1380 la->la_pending++; 1381 break; 1382 case LACP_MUX_ATTACHED: 1383 lp->lp_state |= LACP_STATE_SYNC; 1384 lacp_disable_collecting(lp); 1385 lacp_sm_assert_ntt(lp); 1386 break; 1387 case LACP_MUX_COLLECTING: 1388 lacp_enable_collecting(lp); 1389 lacp_disable_distributing(lp); 1390 lacp_sm_assert_ntt(lp); 1391 break; 1392 case LACP_MUX_DISTRIBUTING: 1393 lacp_enable_distributing(lp); 1394 break; 1395 default: 1396 panic("%s: unknown state", __func__); 1397 } 1398 1399 LACP_DPRINTF((lp, "mux_state %d -> %d\n", lp->lp_mux_state, new_state)); 1400 1401 lp->lp_mux_state = new_state; 1402 } 1403 1404 static void 1405 lacp_sm_mux_timer(struct lacp_port *lp) 1406 { 1407 struct lacp_aggregator *la = lp->lp_aggregator; 1408 #if defined(LACP_DEBUG) 1409 char buf[LACP_LAGIDSTR_MAX+1]; 1410 #endif 1411 1412 KASSERT(la->la_pending > 0, ("no pending event")); 1413 1414 LACP_DPRINTF((lp, "%s: aggregator %s, pending %d -> %d\n", __func__, 1415 lacp_format_lagid(&la->la_actor, &la->la_partner, 1416 buf, sizeof(buf)), 1417 la->la_pending, la->la_pending - 1)); 1418 1419 la->la_pending--; 1420 } 1421 1422 /* periodic transmit machine */ 1423 1424 static void 1425 lacp_sm_ptx_update_timeout(struct lacp_port *lp, uint8_t oldpstate) 1426 { 1427 if (LACP_STATE_EQ(oldpstate, lp->lp_partner.lip_state, 1428 LACP_STATE_TIMEOUT)) { 1429 return; 1430 } 1431 1432 LACP_DPRINTF((lp, "partner timeout changed\n")); 1433 1434 /* 1435 * FAST_PERIODIC -> SLOW_PERIODIC 1436 * or 1437 * SLOW_PERIODIC (-> PERIODIC_TX) -> FAST_PERIODIC 1438 * 1439 * let lacp_sm_ptx_tx_schedule to update timeout. 1440 */ 1441 1442 LACP_TIMER_DISARM(lp, LACP_TIMER_PERIODIC); 1443 1444 /* 1445 * if timeout has been shortened, assert NTT. 1446 */ 1447 1448 if ((lp->lp_partner.lip_state & LACP_STATE_TIMEOUT)) { 1449 lacp_sm_assert_ntt(lp); 1450 } 1451 } 1452 1453 static void 1454 lacp_sm_ptx_tx_schedule(struct lacp_port *lp) 1455 { 1456 int timeout; 1457 1458 if (!(lp->lp_state & LACP_STATE_ACTIVITY) && 1459 !(lp->lp_partner.lip_state & LACP_STATE_ACTIVITY)) { 1460 1461 /* 1462 * NO_PERIODIC 1463 */ 1464 1465 LACP_TIMER_DISARM(lp, LACP_TIMER_PERIODIC); 1466 return; 1467 } 1468 1469 if (LACP_TIMER_ISARMED(lp, LACP_TIMER_PERIODIC)) { 1470 return; 1471 } 1472 1473 timeout = (lp->lp_partner.lip_state & LACP_STATE_TIMEOUT) ? 1474 LACP_FAST_PERIODIC_TIME : LACP_SLOW_PERIODIC_TIME; 1475 1476 LACP_TIMER_ARM(lp, LACP_TIMER_PERIODIC, timeout); 1477 } 1478 1479 static void 1480 lacp_sm_ptx_timer(struct lacp_port *lp) 1481 { 1482 lacp_sm_assert_ntt(lp); 1483 } 1484 1485 static void 1486 lacp_sm_rx(struct lacp_port *lp, const struct lacpdu *du) 1487 { 1488 int timeout; 1489 1490 /* 1491 * check LACP_DISABLED first 1492 */ 1493 1494 if (!(lp->lp_state & LACP_STATE_AGGREGATION)) { 1495 return; 1496 } 1497 1498 /* 1499 * check loopback condition. 1500 */ 1501 1502 if (!lacp_compare_systemid(&du->ldu_actor.lip_systemid, 1503 &lp->lp_actor.lip_systemid)) { 1504 return; 1505 } 1506 1507 /* 1508 * EXPIRED, DEFAULTED, CURRENT -> CURRENT 1509 */ 1510 1511 lacp_sm_rx_update_selected(lp, du); 1512 lacp_sm_rx_update_ntt(lp, du); 1513 lacp_sm_rx_record_pdu(lp, du); 1514 1515 timeout = (lp->lp_state & LACP_STATE_TIMEOUT) ? 1516 LACP_SHORT_TIMEOUT_TIME : LACP_LONG_TIMEOUT_TIME; 1517 LACP_TIMER_ARM(lp, LACP_TIMER_CURRENT_WHILE, timeout); 1518 1519 lp->lp_state &= ~LACP_STATE_EXPIRED; 1520 1521 /* 1522 * kick transmit machine without waiting the next tick. 1523 */ 1524 1525 lacp_sm_tx(lp); 1526 } 1527 1528 static void 1529 lacp_sm_rx_set_expired(struct lacp_port *lp) 1530 { 1531 lp->lp_partner.lip_state &= ~LACP_STATE_SYNC; 1532 lp->lp_partner.lip_state |= LACP_STATE_TIMEOUT; 1533 LACP_TIMER_ARM(lp, LACP_TIMER_CURRENT_WHILE, LACP_SHORT_TIMEOUT_TIME); 1534 lp->lp_state |= LACP_STATE_EXPIRED; 1535 } 1536 1537 static void 1538 lacp_sm_rx_timer(struct lacp_port *lp) 1539 { 1540 if ((lp->lp_state & LACP_STATE_EXPIRED) == 0) { 1541 /* CURRENT -> EXPIRED */ 1542 LACP_DPRINTF((lp, "%s: CURRENT -> EXPIRED\n", __func__)); 1543 lacp_sm_rx_set_expired(lp); 1544 } else { 1545 /* EXPIRED -> DEFAULTED */ 1546 LACP_DPRINTF((lp, "%s: EXPIRED -> DEFAULTED\n", __func__)); 1547 lacp_sm_rx_update_default_selected(lp); 1548 lacp_sm_rx_record_default(lp); 1549 lp->lp_state &= ~LACP_STATE_EXPIRED; 1550 } 1551 } 1552 1553 static void 1554 lacp_sm_rx_record_pdu(struct lacp_port *lp, const struct lacpdu *du) 1555 { 1556 boolean_t active; 1557 uint8_t oldpstate; 1558 #if defined(LACP_DEBUG) 1559 char buf[LACP_STATESTR_MAX+1]; 1560 #endif 1561 1562 /* LACP_DPRINTF((lp, "%s\n", __func__)); */ 1563 1564 oldpstate = lp->lp_partner.lip_state; 1565 1566 active = (du->ldu_actor.lip_state & LACP_STATE_ACTIVITY) 1567 || ((lp->lp_state & LACP_STATE_ACTIVITY) && 1568 (du->ldu_partner.lip_state & LACP_STATE_ACTIVITY)); 1569 1570 lp->lp_partner = du->ldu_actor; 1571 if (active && 1572 ((LACP_STATE_EQ(lp->lp_state, du->ldu_partner.lip_state, 1573 LACP_STATE_AGGREGATION) && 1574 !lacp_compare_peerinfo(&lp->lp_actor, &du->ldu_partner)) 1575 || (du->ldu_partner.lip_state & LACP_STATE_AGGREGATION) == 0)) { 1576 /* XXX nothing? */ 1577 } else { 1578 lp->lp_partner.lip_state &= ~LACP_STATE_SYNC; 1579 } 1580 1581 lp->lp_state &= ~LACP_STATE_DEFAULTED; 1582 1583 if (oldpstate != lp->lp_partner.lip_state) { 1584 LACP_DPRINTF((lp, "old pstate %s\n", 1585 lacp_format_state(oldpstate, buf, sizeof(buf)))); 1586 LACP_DPRINTF((lp, "new pstate %s\n", 1587 lacp_format_state(lp->lp_partner.lip_state, buf, 1588 sizeof(buf)))); 1589 } 1590 1591 lacp_sm_ptx_update_timeout(lp, oldpstate); 1592 } 1593 1594 static void 1595 lacp_sm_rx_update_ntt(struct lacp_port *lp, const struct lacpdu *du) 1596 { 1597 /* LACP_DPRINTF((lp, "%s\n", __func__)); */ 1598 1599 if (lacp_compare_peerinfo(&lp->lp_actor, &du->ldu_partner) || 1600 !LACP_STATE_EQ(lp->lp_state, du->ldu_partner.lip_state, 1601 LACP_STATE_ACTIVITY | LACP_STATE_SYNC | LACP_STATE_AGGREGATION)) { 1602 LACP_DPRINTF((lp, "%s: assert ntt\n", __func__)); 1603 lacp_sm_assert_ntt(lp); 1604 } 1605 } 1606 1607 static void 1608 lacp_sm_rx_record_default(struct lacp_port *lp) 1609 { 1610 uint8_t oldpstate; 1611 1612 /* LACP_DPRINTF((lp, "%s\n", __func__)); */ 1613 1614 oldpstate = lp->lp_partner.lip_state; 1615 lp->lp_partner = lacp_partner_admin; 1616 lp->lp_state |= LACP_STATE_DEFAULTED; 1617 lacp_sm_ptx_update_timeout(lp, oldpstate); 1618 } 1619 1620 static void 1621 lacp_sm_rx_update_selected_from_peerinfo(struct lacp_port *lp, 1622 const struct lacp_peerinfo *info) 1623 { 1624 /* LACP_DPRINTF((lp, "%s\n", __func__)); */ 1625 1626 if (lacp_compare_peerinfo(&lp->lp_partner, info) || 1627 !LACP_STATE_EQ(lp->lp_partner.lip_state, info->lip_state, 1628 LACP_STATE_AGGREGATION)) { 1629 lp->lp_selected = LACP_UNSELECTED; 1630 /* mux machine will clean up lp->lp_aggregator */ 1631 } 1632 } 1633 1634 static void 1635 lacp_sm_rx_update_selected(struct lacp_port *lp, const struct lacpdu *du) 1636 { 1637 /* LACP_DPRINTF((lp, "%s\n", __func__)); */ 1638 1639 lacp_sm_rx_update_selected_from_peerinfo(lp, &du->ldu_actor); 1640 } 1641 1642 static void 1643 lacp_sm_rx_update_default_selected(struct lacp_port *lp) 1644 { 1645 /* LACP_DPRINTF((lp, "%s\n", __func__)); */ 1646 1647 lacp_sm_rx_update_selected_from_peerinfo(lp, &lacp_partner_admin); 1648 } 1649 1650 /* transmit machine */ 1651 1652 static void 1653 lacp_sm_tx(struct lacp_port *lp) 1654 { 1655 int error; 1656 1657 if (!(lp->lp_state & LACP_STATE_AGGREGATION) 1658 #if 1 1659 || (!(lp->lp_state & LACP_STATE_ACTIVITY) 1660 && !(lp->lp_partner.lip_state & LACP_STATE_ACTIVITY)) 1661 #endif 1662 ) { 1663 lp->lp_flags &= ~LACP_PORT_NTT; 1664 } 1665 1666 if (!(lp->lp_flags & LACP_PORT_NTT)) { 1667 return; 1668 } 1669 1670 /* Rate limit to 3 PDUs per LACP_FAST_PERIODIC_TIME */ 1671 if (ppsratecheck(&lp->lp_last_lacpdu, &lp->lp_lacpdu_sent, 1672 (3 / LACP_FAST_PERIODIC_TIME)) == 0) { 1673 LACP_DPRINTF((lp, "rate limited pdu\n")); 1674 return; 1675 } 1676 1677 error = lacp_xmit_lacpdu(lp); 1678 1679 if (error == 0) { 1680 lp->lp_flags &= ~LACP_PORT_NTT; 1681 } else { 1682 LACP_DPRINTF((lp, "lacpdu transmit failure, error %d\n", 1683 error)); 1684 } 1685 } 1686 1687 static void 1688 lacp_sm_assert_ntt(struct lacp_port *lp) 1689 { 1690 1691 lp->lp_flags |= LACP_PORT_NTT; 1692 } 1693 1694 static void 1695 lacp_run_timers(struct lacp_port *lp) 1696 { 1697 int i; 1698 1699 for (i = 0; i < LACP_NTIMER; i++) { 1700 KASSERT(lp->lp_timer[i] >= 0, 1701 ("invalid timer value %d", lp->lp_timer[i])); 1702 if (lp->lp_timer[i] == 0) { 1703 continue; 1704 } else if (--lp->lp_timer[i] <= 0) { 1705 if (lacp_timer_funcs[i]) { 1706 (*lacp_timer_funcs[i])(lp); 1707 } 1708 } 1709 } 1710 } 1711 1712 int 1713 lacp_marker_input(struct lagg_port *lgp, struct mbuf *m) 1714 { 1715 struct lacp_port *lp = LACP_PORT(lgp); 1716 struct lacp_port *lp2; 1717 struct lacp_softc *lsc = lp->lp_lsc; 1718 struct markerdu *mdu; 1719 int error = 0; 1720 int pending = 0; 1721 1722 LAGG_RLOCK_ASSERT(lgp->lp_softc); 1723 1724 if (m->m_pkthdr.len != sizeof(*mdu)) { 1725 goto bad; 1726 } 1727 1728 if ((m->m_flags & M_MCAST) == 0) { 1729 goto bad; 1730 } 1731 1732 if (m->m_len < sizeof(*mdu)) { 1733 m = m_pullup(m, sizeof(*mdu)); 1734 if (m == NULL) { 1735 return (ENOMEM); 1736 } 1737 } 1738 1739 mdu = mtod(m, struct markerdu *); 1740 1741 if (memcmp(&mdu->mdu_eh.ether_dhost, 1742 ðermulticastaddr_slowprotocols, ETHER_ADDR_LEN)) { 1743 goto bad; 1744 } 1745 1746 if (mdu->mdu_sph.sph_version != 1) { 1747 goto bad; 1748 } 1749 1750 switch (mdu->mdu_tlv.tlv_type) { 1751 case MARKER_TYPE_INFO: 1752 if (tlv_check(mdu, sizeof(*mdu), &mdu->mdu_tlv, 1753 marker_info_tlv_template, TRUE)) { 1754 goto bad; 1755 } 1756 mdu->mdu_tlv.tlv_type = MARKER_TYPE_RESPONSE; 1757 memcpy(&mdu->mdu_eh.ether_dhost, 1758 ðermulticastaddr_slowprotocols, ETHER_ADDR_LEN); 1759 memcpy(&mdu->mdu_eh.ether_shost, 1760 lgp->lp_lladdr, ETHER_ADDR_LEN); 1761 error = lagg_enqueue(lp->lp_ifp, m); 1762 break; 1763 1764 case MARKER_TYPE_RESPONSE: 1765 if (tlv_check(mdu, sizeof(*mdu), &mdu->mdu_tlv, 1766 marker_response_tlv_template, TRUE)) { 1767 goto bad; 1768 } 1769 LACP_DPRINTF((lp, "marker response, port=%u, sys=%6D, id=%u\n", 1770 ntohs(mdu->mdu_info.mi_rq_port), mdu->mdu_info.mi_rq_system, 1771 ":", ntohl(mdu->mdu_info.mi_rq_xid))); 1772 1773 /* Verify that it is the last marker we sent out */ 1774 if (memcmp(&mdu->mdu_info, &lp->lp_marker, 1775 sizeof(struct lacp_markerinfo))) 1776 goto bad; 1777 1778 lp->lp_flags &= ~LACP_PORT_MARK; 1779 1780 if (lsc->lsc_suppress_distributing) { 1781 /* Check if any ports are waiting for a response */ 1782 LIST_FOREACH(lp2, &lsc->lsc_ports, lp_next) { 1783 if (lp2->lp_flags & LACP_PORT_MARK) { 1784 pending = 1; 1785 break; 1786 } 1787 } 1788 1789 if (pending == 0) { 1790 /* All interface queues are clear */ 1791 LACP_DPRINTF((NULL, "queue flush complete\n")); 1792 lsc->lsc_suppress_distributing = FALSE; 1793 } 1794 } 1795 1796 m_freem(m); 1797 break; 1798 1799 default: 1800 goto bad; 1801 } 1802 1803 return (error); 1804 1805 bad: 1806 LACP_DPRINTF((lp, "bad marker frame\n")); 1807 m_freem(m); 1808 return (EINVAL); 1809 } 1810 1811 static int 1812 tlv_check(const void *p, size_t size, const struct tlvhdr *tlv, 1813 const struct tlv_template *tmpl, boolean_t check_type) 1814 { 1815 while (/* CONSTCOND */ 1) { 1816 if ((const char *)tlv - (const char *)p + sizeof(*tlv) > size) { 1817 return (EINVAL); 1818 } 1819 if ((check_type && tlv->tlv_type != tmpl->tmpl_type) || 1820 tlv->tlv_length != tmpl->tmpl_length) { 1821 return (EINVAL); 1822 } 1823 if (tmpl->tmpl_type == 0) { 1824 break; 1825 } 1826 tlv = (const struct tlvhdr *) 1827 ((const char *)tlv + tlv->tlv_length); 1828 tmpl++; 1829 } 1830 1831 return (0); 1832 } 1833 1834 #if defined(LACP_DEBUG) 1835 const char * 1836 lacp_format_mac(const uint8_t *mac, char *buf, size_t buflen) 1837 { 1838 snprintf(buf, buflen, "%02X-%02X-%02X-%02X-%02X-%02X", 1839 (int)mac[0], 1840 (int)mac[1], 1841 (int)mac[2], 1842 (int)mac[3], 1843 (int)mac[4], 1844 (int)mac[5]); 1845 1846 return (buf); 1847 } 1848 1849 const char * 1850 lacp_format_systemid(const struct lacp_systemid *sysid, 1851 char *buf, size_t buflen) 1852 { 1853 char macbuf[LACP_MACSTR_MAX+1]; 1854 1855 snprintf(buf, buflen, "%04X,%s", 1856 ntohs(sysid->lsi_prio), 1857 lacp_format_mac(sysid->lsi_mac, macbuf, sizeof(macbuf))); 1858 1859 return (buf); 1860 } 1861 1862 const char * 1863 lacp_format_portid(const struct lacp_portid *portid, char *buf, size_t buflen) 1864 { 1865 snprintf(buf, buflen, "%04X,%04X", 1866 ntohs(portid->lpi_prio), 1867 ntohs(portid->lpi_portno)); 1868 1869 return (buf); 1870 } 1871 1872 const char * 1873 lacp_format_partner(const struct lacp_peerinfo *peer, char *buf, size_t buflen) 1874 { 1875 char sysid[LACP_SYSTEMIDSTR_MAX+1]; 1876 char portid[LACP_PORTIDSTR_MAX+1]; 1877 1878 snprintf(buf, buflen, "(%s,%04X,%s)", 1879 lacp_format_systemid(&peer->lip_systemid, sysid, sizeof(sysid)), 1880 ntohs(peer->lip_key), 1881 lacp_format_portid(&peer->lip_portid, portid, sizeof(portid))); 1882 1883 return (buf); 1884 } 1885 1886 const char * 1887 lacp_format_lagid(const struct lacp_peerinfo *a, 1888 const struct lacp_peerinfo *b, char *buf, size_t buflen) 1889 { 1890 char astr[LACP_PARTNERSTR_MAX+1]; 1891 char bstr[LACP_PARTNERSTR_MAX+1]; 1892 1893 #if 0 1894 /* 1895 * there's a convention to display small numbered peer 1896 * in the left. 1897 */ 1898 1899 if (lacp_compare_peerinfo(a, b) > 0) { 1900 const struct lacp_peerinfo *t; 1901 1902 t = a; 1903 a = b; 1904 b = t; 1905 } 1906 #endif 1907 1908 snprintf(buf, buflen, "[%s,%s]", 1909 lacp_format_partner(a, astr, sizeof(astr)), 1910 lacp_format_partner(b, bstr, sizeof(bstr))); 1911 1912 return (buf); 1913 } 1914 1915 const char * 1916 lacp_format_lagid_aggregator(const struct lacp_aggregator *la, 1917 char *buf, size_t buflen) 1918 { 1919 if (la == NULL) { 1920 return ("(none)"); 1921 } 1922 1923 return (lacp_format_lagid(&la->la_actor, &la->la_partner, buf, buflen)); 1924 } 1925 1926 const char * 1927 lacp_format_state(uint8_t state, char *buf, size_t buflen) 1928 { 1929 snprintf(buf, buflen, "%b", state, LACP_STATE_BITS); 1930 return (buf); 1931 } 1932 1933 static void 1934 lacp_dump_lacpdu(const struct lacpdu *du) 1935 { 1936 char buf[LACP_PARTNERSTR_MAX+1]; 1937 char buf2[LACP_STATESTR_MAX+1]; 1938 1939 printf("actor=%s\n", 1940 lacp_format_partner(&du->ldu_actor, buf, sizeof(buf))); 1941 printf("actor.state=%s\n", 1942 lacp_format_state(du->ldu_actor.lip_state, buf2, sizeof(buf2))); 1943 printf("partner=%s\n", 1944 lacp_format_partner(&du->ldu_partner, buf, sizeof(buf))); 1945 printf("partner.state=%s\n", 1946 lacp_format_state(du->ldu_partner.lip_state, buf2, sizeof(buf2))); 1947 1948 printf("maxdelay=%d\n", ntohs(du->ldu_collector.lci_maxdelay)); 1949 } 1950 1951 static void 1952 lacp_dprintf(const struct lacp_port *lp, const char *fmt, ...) 1953 { 1954 va_list va; 1955 1956 if (lp) { 1957 printf("%s: ", lp->lp_ifp->if_xname); 1958 } 1959 1960 va_start(va, fmt); 1961 vprintf(fmt, va); 1962 va_end(va); 1963 } 1964 #endif 1965