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