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