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