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