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