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