1 /* $NetBSD: if_lagg_lacp.c,v 1.43 2024/04/05 06:31:37 yamaguchi Exp $ */ 2 3 /*- 4 * SPDX-License-Identifier: BSD-2-Clause-NetBSD 5 * 6 * Copyright (c)2005 YAMAMOTO Takashi, 7 * Copyright (c)2008 Andrew Thompson <thompsa (at) FreeBSD.org> 8 * Copyright (c)2021 Internet Initiative Japan, Inc. 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 33 #include <sys/cdefs.h> 34 __KERNEL_RCSID(0, "$NetBSD: if_lagg_lacp.c,v 1.43 2024/04/05 06:31:37 yamaguchi Exp $"); 35 36 #ifdef _KERNEL_OPT 37 #include "opt_lagg.h" 38 #endif 39 40 #include <sys/param.h> 41 #include <sys/types.h> 42 43 #include <sys/evcnt.h> 44 #include <sys/kmem.h> 45 #include <sys/pcq.h> 46 #include <sys/pslist.h> 47 #include <sys/sysctl.h> 48 #include <sys/syslog.h> 49 #include <sys/workqueue.h> 50 51 #include <net/if.h> 52 #include <net/if_dl.h> 53 #include <net/if_ether.h> 54 #include <net/if_media.h> 55 56 #include <net/ether_slowprotocols.h> 57 58 #include <net/lagg/if_lagg.h> 59 #include <net/lagg/if_laggproto.h> 60 #include <net/lagg/if_lagg_lacp.h> 61 62 #define LACP_SYSTEMIDSTR_LEN 32 63 64 enum { 65 LACP_TIMER_CURRENT_WHILE = 0, 66 LACP_TIMER_PERIODIC, 67 LACP_TIMER_WAIT_WHILE, 68 LACP_NTIMER 69 }; 70 71 enum { 72 LACP_PTIMER_DISTRIBUTING = 0, 73 LACP_NPTIMER 74 }; 75 76 enum lacp_selected { 77 LACP_UNSELECTED, 78 LACP_READY, 79 LACP_STANDBY, 80 LACP_SELECTED, 81 }; 82 83 enum lacp_mux_state { 84 LACP_MUX_DETACHED, 85 LACP_MUX_WAITING, 86 LACP_MUX_STANDBY, 87 LACP_MUX_ATTACHED, 88 LACP_MUX_COLLECTING, 89 LACP_MUX_DISTRIBUTING, 90 LACP_MUX_INIT, 91 }; 92 93 struct lacp_aggregator_systemid { 94 uint16_t sid_prio; 95 uint16_t sid_key; 96 uint8_t sid_mac[LACP_MAC_LEN]; 97 }; 98 99 struct lacp_aggregator { 100 TAILQ_ENTRY(lacp_aggregator) 101 la_q; 102 LIST_HEAD(, lacp_port) 103 la_ports; 104 ssize_t la_attached_port; 105 106 struct lacp_aggregator_systemid 107 la_sid; 108 }; 109 110 struct lacp_portinfo { 111 uint8_t lpi_state; 112 uint16_t lpi_portno; 113 #define LACP_PORTNO_NONE 0 114 uint16_t lpi_portprio; 115 }; 116 117 struct lacp_port { 118 struct lagg_port *lp_laggport; 119 bool lp_added_multi; 120 int lp_timer[LACP_NTIMER]; 121 uint32_t lp_marker_xid; 122 enum lacp_selected lp_selected; 123 enum lacp_mux_state lp_mux_state; 124 125 struct lacp_portinfo lp_actor; 126 struct lacp_portinfo lp_partner; 127 struct lacp_aggregator *lp_aggregator; 128 struct lacp_aggregator_systemid 129 lp_aggregator_sidbuf; 130 uint64_t lp_linkspeed; 131 int lp_pending; 132 LIST_ENTRY(lacp_port) lp_entry_la; 133 struct timeval lp_last_lacpdu; 134 int lp_lacpdu_sent; 135 bool lp_collector; 136 137 unsigned int lp_flags; 138 #define LACP_PORT_NTT __BIT(0) 139 #define LACP_PORT_MARK __BIT(1) 140 141 struct lagg_work lp_work_smtx; 142 struct lagg_work lp_work_marker; 143 }; 144 145 struct lacp_portmap { 146 size_t pm_count; 147 struct lagg_port *pm_ports[LACP_MAX_PORTS]; 148 }; 149 150 struct lacp_softc { 151 struct lagg_softc *lsc_softc; 152 kmutex_t lsc_lock; 153 pserialize_t lsc_psz; 154 bool lsc_running; 155 bool lsc_suppress_distributing; 156 int lsc_timer[LACP_NPTIMER]; 157 uint8_t lsc_system_mac[LACP_MAC_LEN]; 158 uint16_t lsc_system_prio; 159 uint16_t lsc_key; 160 size_t lsc_max_ports; 161 size_t lsc_activemap; 162 struct lacp_portmap lsc_portmaps[2]; /* active & idle */ 163 struct lacp_aggregator *lsc_aggregator; 164 TAILQ_HEAD(, lacp_aggregator) 165 lsc_aggregators; 166 struct workqueue *lsc_workq; 167 struct lagg_work lsc_work_tick; 168 struct lagg_work lsc_work_rcvdu; 169 struct lagg_work lsc_work_linkspeed; 170 callout_t lsc_tick; 171 pcq_t *lsc_du_q; 172 173 char lsc_evgroup[32]; 174 struct evcnt lsc_mgethdr_failed; 175 struct evcnt lsc_mpullup_failed; 176 struct evcnt lsc_badlacpdu; 177 struct evcnt lsc_badmarkerdu; 178 struct evcnt lsc_norcvif; 179 struct evcnt lsc_nolaggport; 180 struct evcnt lsc_duq_nospc; 181 182 bool lsc_optimistic; 183 bool lsc_stop_lacpdu; 184 bool lsc_dump_du; 185 bool lsc_multi_linkspeed; 186 }; 187 188 /* 189 * Locking notes: 190 * - Items in struct lacp_softc are protected by 191 * lsc_lock (an adaptive mutex) 192 * - lsc_activemap is protected by pserialize (lsc_psz) 193 * - Items of struct lagg_port in lsc_portmaps are protected by 194 * protected by both pserialize (lsc_psz) and psref (lp_psref) 195 * - Updates for lsc_activemap and lsc_portmaps is serialized by 196 * sc_lock in struct lagg_softc 197 * - Other locking notes are described in if_laggproto.h 198 */ 199 200 static void lacp_dprintf(const struct lacp_softc *, 201 const struct lacp_port *, const char *, ...) 202 __attribute__((__format__(__printf__, 3, 4))); 203 204 #ifdef LACP_DEBUG 205 #define LACP_DPRINTF(a) do { lacp_dprintf a; } while (/*CONSTCOND*/ 0) 206 #define LACP_PEERINFO_IDSTR(_pi, _b, _bs) \ 207 lacp_peerinfo_idstr(_pi, _b, _bs) 208 #define LACP_STATE_STR(_s, _b, _bs) lacp_state_str(_s, _b, _bs) 209 #define LACP_AGGREGATOR_STR(_a, _b, _bs) \ 210 lacp_aggregator_str(_a, _b, _bs) 211 #define __LACPDEBUGUSED 212 #else 213 #define LACP_DPRINTF(a) __nothing 214 #define LACP_PEERINFO_IDSTR(_pi, _b, _bs) __nothing 215 #define LACP_STATE_STR(_s, _b, _bs) __nothing 216 #define LACP_AGGREGATOR_STR(_a, _b, _bs) __nothing 217 #define __LACPDEBUGUSED __unused 218 #endif 219 220 #define LACP_LOCK(_sc) mutex_enter(&(_sc)->lsc_lock) 221 #define LACP_UNLOCK(_sc) mutex_exit(&(_sc)->lsc_lock) 222 #define LACP_LOCKED(_sc) mutex_owned(&(_sc)->lsc_lock) 223 #define LACP_TIMER_ARM(_lacpp, _timer, _val) \ 224 (_lacpp)->lp_timer[(_timer)] = (_val) 225 #define LACP_TIMER_DISARM(_lacpp, _timer) \ 226 LACP_TIMER_ARM((_lacpp), (_timer), 0) 227 #define LACP_TIMER_ISARMED(_lacpp, _timer) \ 228 ((_lacpp)->lp_timer[(_timer)] > 0) 229 #define LACP_PTIMER_ARM(_sc, _timer, _val) \ 230 (_sc)->lsc_timer[(_timer)] = (_val) 231 #define LACP_PTIMER_DISARM(_sc, _timer) \ 232 LACP_PTIMER_ARM((_sc), (_timer), 0) 233 #define LACP_PTIMER_ISARMED(_sc, _timer) \ 234 ((_sc)->lsc_timer[(_timer)] > 0) 235 #define LACP_STATE_EQ(_s1, _s2, _mask) (!ISSET((_s1) ^ (_s2), (_mask))) 236 #define LACP_PORT_XNAME(_lacpp) (_lacpp != NULL) ? \ 237 (_lacpp)->lp_laggport->lp_ifp->if_xname : "(unknown)" 238 #define LACP_ISDUMPING(_sc) (_sc)->lsc_dump_du 239 #define LACP_PORTMAP_ACTIVE(_sc) \ 240 atomic_load_consume(&(_sc)->lsc_activemap) 241 #define LACP_PORTMAP_NEXT(_sc) \ 242 (((LACP_PORTMAP_ACTIVE((_sc))) ^ 0x01) &0x01) 243 #define LACP_SYS_PRI(_la) ntohs((_la)->la_sid.sid_prio) 244 #define LACP_TLV_PARSE(_du, _st, _name, _tlvlist) \ 245 tlv_parse(&(_du)->_name, \ 246 sizeof(_st) - offsetof(_st, _name), \ 247 (_tlvlist)) 248 249 static void lacp_tick(void *); 250 static void lacp_tick_work(struct lagg_work *, void *); 251 static void lacp_linkstate(struct lagg_proto_softc *, struct lagg_port *); 252 static void lacp_port_disable(struct lacp_softc *, struct lacp_port *); 253 static void lacp_port_enable(struct lacp_softc *, struct lacp_port *); 254 static void lacp_peerinfo_actor(struct lacp_softc *, struct lacp_port *, 255 struct lacpdu_peerinfo *); 256 static void lacp_peerinfo_partner(struct lacp_port *, 257 struct lacpdu_peerinfo *); 258 static struct lagg_port * 259 lacp_select_tx_port(struct lacp_softc *, struct mbuf *, 260 struct psref *); 261 static void lacp_suppress_distributing(struct lacp_softc *); 262 static void lacp_distributing_timer(struct lacp_softc *); 263 264 static void lacp_select(struct lacp_softc *, struct lacp_port *); 265 static void lacp_unselect(struct lacp_softc *, struct lacp_port *); 266 static void lacp_selected_update(struct lacp_softc *, 267 struct lacp_aggregator *); 268 static void lacp_sm_port_init(struct lacp_softc *, 269 struct lacp_port *, struct lagg_port *); 270 static int lacp_set_mux(struct lacp_softc *, 271 struct lacp_port *, enum lacp_mux_state); 272 static void lacp_sm_mux(struct lacp_softc *, struct lacp_port *); 273 static void lacp_sm_mux_timer(struct lacp_softc *, struct lacp_port *); 274 static void lacp_sm_rx(struct lacp_softc *, struct lacp_port *, 275 struct lacpdu_peerinfo *, struct lacpdu_peerinfo *); 276 static void lacp_sm_rx_set_expired(struct lacp_port *); 277 static void lacp_sm_rx_timer(struct lacp_softc *, struct lacp_port *); 278 static void lacp_sm_rx_record_default(struct lacp_softc *, 279 struct lacp_port *); 280 281 static void lacp_sm_tx(struct lacp_softc *, struct lacp_port *); 282 static void lacp_sm_tx_work(struct lagg_work *, void *); 283 static void lacp_sm_ptx_timer(struct lacp_softc *, struct lacp_port *); 284 static void lacp_sm_ptx_schedule(struct lacp_port *); 285 static void lacp_sm_ptx_update_timeout(struct lacp_port *, uint8_t); 286 287 static void lacp_rcvdu_work(struct lagg_work *, void *); 288 static void lacp_marker_work(struct lagg_work *, void *); 289 static void lacp_linkspeed_work(struct lagg_work *, void *); 290 static void lacp_dump_lacpdutlv(const struct lacpdu_peerinfo *, 291 const struct lacpdu_peerinfo *, 292 const struct lacpdu_collectorinfo *); 293 static void lacp_dump_markertlv(const struct markerdu_info *, 294 const struct markerdu_info *); 295 296 typedef void (*lacp_timer_func_t)(struct lacp_softc *, struct lacp_port *); 297 static const lacp_timer_func_t lacp_timer_funcs[] = { 298 [LACP_TIMER_CURRENT_WHILE] = lacp_sm_rx_timer, 299 [LACP_TIMER_PERIODIC] = lacp_sm_ptx_timer, 300 [LACP_TIMER_WAIT_WHILE] = lacp_sm_mux_timer, 301 }; 302 typedef void (*lacp_prototimer_func_t)(struct lacp_softc *); 303 static const lacp_prototimer_func_t lacp_ptimer_funcs[] = { 304 [LACP_PTIMER_DISTRIBUTING] = lacp_distributing_timer, 305 }; 306 307 static void 308 lacp_dprintf(const struct lacp_softc *lsc, const struct lacp_port *lacpp, 309 const char *fmt, ...) 310 { 311 struct lagg_softc *sc; 312 va_list va; 313 314 if (lsc != NULL && lsc->lsc_softc != NULL) { 315 sc = lsc->lsc_softc; 316 printf("%s", sc->sc_if.if_xname); 317 } else { 318 printf("lacp"); 319 } 320 321 if (lacpp != NULL) 322 printf("(%s)", LACP_PORT_XNAME(lacpp)); 323 324 printf(": "); 325 326 va_start(va, fmt); 327 vprintf(fmt, va); 328 va_end(va); 329 } 330 331 static inline void 332 lacp_evcnt_attach(struct lacp_softc *lsc, 333 struct evcnt *ev, const char *name) 334 { 335 336 evcnt_attach_dynamic(ev, EVCNT_TYPE_MISC, NULL, 337 lsc->lsc_evgroup, name); 338 } 339 340 static inline bool 341 lacp_iscollecting(struct lacp_port *lacpp) 342 { 343 344 return atomic_load_relaxed(&lacpp->lp_collector); 345 } 346 347 static inline bool 348 lacp_isdistributing(struct lacp_port *lacpp) 349 { 350 351 return ISSET(lacpp->lp_actor.lpi_state, LACP_STATE_DISTRIBUTING); 352 } 353 354 static inline bool 355 lacp_isactive(struct lacp_softc *lsc, struct lacp_port *lacpp) 356 { 357 358 if (lacpp->lp_selected != LACP_SELECTED) 359 return false; 360 361 if (lacpp->lp_aggregator == NULL) 362 return false; 363 364 if (lacpp->lp_aggregator != lsc->lsc_aggregator) 365 return false; 366 367 return true; 368 } 369 370 static inline void 371 lacp_mcastaddr(struct ifreq *ifr, const char *if_xname) 372 { 373 static const uint8_t addr[ETHER_ADDR_LEN] = 374 { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x02 }; 375 376 memset(ifr, 0, sizeof(*ifr)); 377 378 strlcpy(ifr->ifr_name, if_xname, 379 sizeof(ifr->ifr_name)); 380 ifr->ifr_addr.sa_len = sizeof(ifr->ifr_addr); 381 ifr->ifr_addr.sa_family = AF_UNSPEC; 382 383 CTASSERT(sizeof(ifr->ifr_addr) >= sizeof(addr)); 384 memcpy(&ifr->ifr_addr.sa_data, addr, sizeof(addr)); 385 } 386 387 static inline u_int 388 lacp_portmap_linkstate(struct lacp_portmap *pm) 389 { 390 391 if (pm->pm_count == 0) 392 return LINK_STATE_DOWN; 393 394 return LINK_STATE_UP; 395 } 396 397 static inline struct lacp_port * 398 lacp_port_priority_max(struct lacp_port *a, struct lacp_port *b) 399 { 400 uint16_t pri_a, pri_b; 401 402 pri_a = ntohs(a->lp_actor.lpi_portprio); 403 pri_b = ntohs(b->lp_actor.lpi_portprio); 404 405 if (pri_a < pri_b) 406 return a; 407 if (pri_b < pri_a) 408 return b; 409 410 pri_a = ntohs(a->lp_partner.lpi_portprio); 411 pri_b = ntohs(b->lp_partner.lpi_portprio); 412 413 if (pri_a < pri_b) 414 return a; 415 if (pri_b < pri_a) 416 return b; 417 418 if (a->lp_linkspeed > b->lp_linkspeed) 419 return a; 420 if (b->lp_linkspeed > a->lp_linkspeed) 421 return b; 422 423 return a; 424 } 425 426 static void 427 tlv_parse(void *vp, size_t len, struct tlv *list) 428 { 429 struct tlvhdr *th; 430 uint8_t *p; 431 size_t l, i; 432 433 th = (struct tlvhdr *)vp; 434 p = (uint8_t *)vp; 435 436 for (l = 0; l < len; l += th->tlv_length) { 437 th = (struct tlvhdr *)(p + l); 438 439 if (th->tlv_type == TLV_TYPE_TERMINATE) 440 break; 441 442 if (th->tlv_length <= 0) 443 break; 444 445 for (i = 0; list[i].tlv_t != TLV_TYPE_TERMINATE; i++) { 446 if (th->tlv_type != list[i].tlv_t) 447 continue; 448 449 if (th->tlv_length - sizeof(*th) != list[i].tlv_l) 450 break; 451 452 if (list[i].tlv_v == NULL) { 453 list[i].tlv_v = 454 (void *)((uint8_t *)th + sizeof(*th)); 455 } 456 457 break; 458 } 459 } 460 } 461 462 int 463 lacp_attach(struct lagg_softc *sc, struct lagg_proto_softc **lscp) 464 { 465 struct lacp_softc *lsc; 466 char xnamebuf[MAXCOMLEN]; 467 int error; 468 469 KASSERT(LAGG_LOCKED(sc)); 470 471 lsc = kmem_zalloc(sizeof(*lsc), KM_NOSLEEP); 472 if (lsc == NULL) 473 return ENOMEM; 474 475 lsc->lsc_du_q = pcq_create(LACP_RCVDU_LIMIT, KM_NOSLEEP); 476 if (lsc->lsc_du_q == NULL) { 477 error = ENOMEM; 478 goto free_lsc; 479 } 480 481 mutex_init(&lsc->lsc_lock, MUTEX_DEFAULT, IPL_SOFTNET); 482 lsc->lsc_softc = sc; 483 lsc->lsc_key = htons(if_get_index(&sc->sc_if)); 484 lsc->lsc_system_prio = htons(LACP_SYSTEM_PRIO); 485 lsc->lsc_running = false; 486 lsc->lsc_max_ports = LACP_MAX_PORTS; 487 lsc->lsc_multi_linkspeed = true; 488 TAILQ_INIT(&lsc->lsc_aggregators); 489 490 lagg_work_set(&lsc->lsc_work_tick, lacp_tick_work, lsc); 491 lagg_work_set(&lsc->lsc_work_rcvdu, lacp_rcvdu_work, lsc); 492 lagg_work_set(&lsc->lsc_work_linkspeed, 493 lacp_linkspeed_work, lsc); 494 495 snprintf(xnamebuf, sizeof(xnamebuf), "%s.lacp", 496 sc->sc_if.if_xname); 497 lsc->lsc_workq = lagg_workq_create(xnamebuf, 498 PRI_SOFTNET, IPL_SOFTNET, WQ_MPSAFE); 499 if (lsc->lsc_workq == NULL) { 500 LAGG_LOG(sc, LOG_ERR, "workqueue create failed\n"); 501 error = ENOMEM; 502 goto destroy_lock; 503 } 504 505 lsc->lsc_psz = pserialize_create(); 506 507 callout_init(&lsc->lsc_tick, CALLOUT_MPSAFE); 508 callout_setfunc(&lsc->lsc_tick, lacp_tick, lsc); 509 510 snprintf(lsc->lsc_evgroup, sizeof(lsc->lsc_evgroup), 511 "%s-lacp", sc->sc_if.if_xname); 512 lacp_evcnt_attach(lsc, &lsc->lsc_mgethdr_failed, "MGETHDR failed"); 513 lacp_evcnt_attach(lsc, &lsc->lsc_mpullup_failed, "m_pullup failed"); 514 lacp_evcnt_attach(lsc, &lsc->lsc_badlacpdu, "Bad LACPDU received"); 515 lacp_evcnt_attach(lsc, &lsc->lsc_badmarkerdu, "Bad MarkerDU received"); 516 lacp_evcnt_attach(lsc, &lsc->lsc_norcvif, "No received interface"); 517 lacp_evcnt_attach(lsc, &lsc->lsc_nolaggport, "No lagg context"); 518 lacp_evcnt_attach(lsc, &lsc->lsc_duq_nospc, "No space left on queues"); 519 520 if_link_state_change(&sc->sc_if, LINK_STATE_DOWN); 521 522 *lscp = (struct lagg_proto_softc *)lsc; 523 return 0; 524 destroy_lock: 525 mutex_destroy(&lsc->lsc_lock); 526 pcq_destroy(lsc->lsc_du_q); 527 free_lsc: 528 kmem_free(lsc, sizeof(*lsc)); 529 530 return error; 531 } 532 533 void 534 lacp_detach(struct lagg_proto_softc *xlsc) 535 { 536 struct lacp_softc *lsc = (struct lacp_softc *)xlsc; 537 struct lagg_softc *sc __diagused = lsc->lsc_softc; 538 539 KASSERT(TAILQ_EMPTY(&lsc->lsc_aggregators)); 540 KASSERT(SIMPLEQ_EMPTY(&sc->sc_ports)); 541 542 LAGG_LOCK(lsc->lsc_softc); 543 lacp_down(xlsc); 544 LAGG_UNLOCK(lsc->lsc_softc); 545 546 lagg_workq_wait(lsc->lsc_workq, &lsc->lsc_work_rcvdu); 547 lagg_workq_wait(lsc->lsc_workq, &lsc->lsc_work_tick); 548 evcnt_detach(&lsc->lsc_mgethdr_failed); 549 evcnt_detach(&lsc->lsc_mpullup_failed); 550 evcnt_detach(&lsc->lsc_badlacpdu); 551 evcnt_detach(&lsc->lsc_badmarkerdu); 552 evcnt_detach(&lsc->lsc_norcvif); 553 evcnt_detach(&lsc->lsc_nolaggport); 554 evcnt_detach(&lsc->lsc_duq_nospc); 555 lagg_workq_destroy(lsc->lsc_workq); 556 pserialize_destroy(lsc->lsc_psz); 557 mutex_destroy(&lsc->lsc_lock); 558 pcq_destroy(lsc->lsc_du_q); 559 kmem_free(lsc, sizeof(*lsc)); 560 } 561 562 int 563 lacp_up(struct lagg_proto_softc *xlsc) 564 { 565 struct lagg_softc *sc; 566 struct lagg_port *lp; 567 struct lacp_softc *lsc; 568 569 lsc = (struct lacp_softc *)xlsc; 570 sc = lsc->lsc_softc; 571 572 KASSERT(LAGG_LOCKED(sc)); 573 574 LACP_LOCK(lsc); 575 if (memcmp(lsc->lsc_system_mac, LAGG_CLLADDR(sc), 576 sizeof(lsc->lsc_system_mac)) != 0) { 577 memcpy(lsc->lsc_system_mac, LAGG_CLLADDR(sc), 578 sizeof(lsc->lsc_system_mac)); 579 } 580 lsc->lsc_running = true; 581 callout_schedule(&lsc->lsc_tick, hz); 582 LACP_UNLOCK(lsc); 583 584 LAGG_PORTS_FOREACH(sc, lp) { 585 lacp_linkstate(xlsc, lp); 586 } 587 588 LACP_DPRINTF((lsc, NULL, "lacp start\n")); 589 590 return 0; 591 } 592 593 static void 594 lacp_down_locked(struct lacp_softc *lsc) 595 { 596 struct lagg_softc *sc; 597 struct lagg_port *lp; 598 599 sc = lsc->lsc_softc; 600 601 KASSERT(LAGG_LOCKED(sc)); 602 KASSERT(LACP_LOCKED(lsc)); 603 604 lsc->lsc_running = false; 605 callout_halt(&lsc->lsc_tick, &lsc->lsc_lock); 606 607 LAGG_PORTS_FOREACH(sc, lp) { 608 lacp_port_disable(lsc, lp->lp_proto_ctx); 609 } 610 611 memset(lsc->lsc_system_mac, 0, 612 sizeof(lsc->lsc_system_mac)); 613 614 LACP_DPRINTF((lsc, NULL, "lacp stopped\n")); 615 } 616 617 void 618 lacp_down(struct lagg_proto_softc *xlsc) 619 { 620 struct lacp_softc *lsc; 621 622 lsc = (struct lacp_softc *)xlsc; 623 624 KASSERT(LAGG_LOCKED(lsc->lsc_softc)); 625 626 LACP_LOCK(lsc); 627 lacp_down_locked(lsc); 628 LACP_UNLOCK(lsc); 629 } 630 631 int 632 lacp_transmit(struct lagg_proto_softc *xlsc, struct mbuf *m) 633 { 634 struct lacp_softc *lsc; 635 struct lagg_port *lp; 636 struct ifnet *ifp; 637 struct psref psref; 638 639 lsc = (struct lacp_softc *)xlsc; 640 641 if (__predict_false(lsc->lsc_suppress_distributing)) { 642 LACP_DPRINTF((lsc, NULL, "waiting transit\n")); 643 m_freem(m); 644 return EBUSY; 645 } 646 647 lp = lacp_select_tx_port(lsc, m, &psref); 648 if (__predict_false(lp == NULL)) { 649 LACP_DPRINTF((lsc, NULL, "no distributing port\n")); 650 ifp = &lsc->lsc_softc->sc_if; 651 if_statinc(ifp, if_oerrors); 652 m_freem(m); 653 return ENOENT; 654 } 655 656 lagg_output(lsc->lsc_softc, lp, m); 657 lagg_port_putref(lp, &psref); 658 659 return 0; 660 } 661 662 int 663 lacp_allocport(struct lagg_proto_softc *xlsc, struct lagg_port *lp) 664 { 665 struct lagg_softc *sc; 666 struct lacp_softc *lsc; 667 struct lacp_port *lacpp; 668 struct ifreq ifr; 669 bool added_multi; 670 int error; 671 672 lsc = (struct lacp_softc *)xlsc; 673 sc = lsc->lsc_softc; 674 675 KASSERT(LAGG_LOCKED(sc)); 676 KASSERT(IFNET_LOCKED(lp->lp_ifp)); 677 678 lacpp = kmem_zalloc(sizeof(*lacpp), KM_NOSLEEP); 679 if (lacpp == NULL) 680 return ENOMEM; 681 682 lacp_mcastaddr(&ifr, lp->lp_ifp->if_xname); 683 error = lp->lp_ioctl(lp->lp_ifp, SIOCADDMULTI, (void *)&ifr); 684 685 switch (error) { 686 case 0: 687 added_multi = true; 688 break; 689 case EAFNOSUPPORT: 690 added_multi = false; 691 break; 692 default: 693 LAGG_LOG(sc, LOG_ERR, "SIOCADDMULTI failed on %s\n", 694 lp->lp_ifp->if_xname); 695 kmem_free(lacpp, sizeof(*lacpp)); 696 return error; 697 } 698 699 lacpp->lp_added_multi = added_multi; 700 lagg_work_set(&lacpp->lp_work_smtx, lacp_sm_tx_work, lsc); 701 lagg_work_set(&lacpp->lp_work_marker, lacp_marker_work, lsc); 702 703 LACP_LOCK(lsc); 704 lacp_sm_port_init(lsc, lacpp, lp); 705 LACP_UNLOCK(lsc); 706 707 lp->lp_proto_ctx = (void *)lacpp; 708 lp->lp_prio = ntohs(lacpp->lp_actor.lpi_portprio); 709 710 return 0; 711 } 712 713 void 714 lacp_startport(struct lagg_proto_softc *xlsc, struct lagg_port *lp) 715 { 716 struct lacp_port *lacpp; 717 uint16_t prio; 718 719 lacpp = lp->lp_proto_ctx; 720 721 prio = (uint16_t)MIN(lp->lp_prio, UINT16_MAX); 722 lacpp->lp_actor.lpi_portprio = htons(prio); 723 724 lacp_linkstate(xlsc, lp); 725 } 726 727 void 728 lacp_stopport(struct lagg_proto_softc *xlsc, struct lagg_port *lp) 729 { 730 struct lacp_softc *lsc; 731 struct lacp_port *lacpp; 732 int i; 733 734 lsc = (struct lacp_softc *)xlsc; 735 lacpp = lp->lp_proto_ctx; 736 737 KASSERT(LAGG_LOCKED(lsc->lsc_softc)); 738 739 LACP_LOCK(lsc); 740 for (i = 0; i < LACP_NTIMER; i++) { 741 LACP_TIMER_DISARM(lacpp, i); 742 } 743 744 lacp_port_disable(lsc, lacpp); 745 LACP_UNLOCK(lsc); 746 } 747 748 void 749 lacp_freeport(struct lagg_proto_softc *xlsc, struct lagg_port *lp) 750 { 751 struct lacp_softc *lsc; 752 struct lacp_port *lacpp; 753 struct ifreq ifr; 754 755 lsc = (struct lacp_softc *)xlsc; 756 lacpp = lp->lp_proto_ctx; 757 758 KASSERT(LAGG_LOCKED(lsc->lsc_softc)); 759 KASSERT(IFNET_LOCKED(lp->lp_ifp)); 760 761 lagg_workq_wait(lsc->lsc_workq, &lacpp->lp_work_smtx); 762 lagg_workq_wait(lsc->lsc_workq, &lacpp->lp_work_marker); 763 764 if (lacpp->lp_added_multi) { 765 lacp_mcastaddr(&ifr, LACP_PORT_XNAME(lacpp)); 766 767 (void)lp->lp_ioctl(lp->lp_ifp, SIOCDELMULTI, (void *)&ifr); 768 } 769 770 lp->lp_proto_ctx = NULL; 771 kmem_free(lacpp, sizeof(*lacpp)); 772 } 773 774 void 775 lacp_protostat(struct lagg_proto_softc *xlsc, struct laggreqproto *resp) 776 { 777 struct laggreq_lacp *rplacp; 778 struct lacp_softc *lsc; 779 struct lacp_aggregator *la; 780 struct lacp_aggregator_systemid *sid; 781 782 lsc = (struct lacp_softc *)xlsc; 783 784 LACP_LOCK(lsc); 785 la = lsc->lsc_aggregator; 786 rplacp = &resp->rp_lacp; 787 788 if (lsc->lsc_optimistic) 789 SET(rplacp->flags, LAGGREQLACP_OPTIMISTIC); 790 if (lsc->lsc_dump_du) 791 SET(rplacp->flags, LAGGREQLACP_DUMPDU); 792 if (lsc->lsc_stop_lacpdu) 793 SET(rplacp->flags, LAGGREQLACP_STOPDU); 794 if (lsc->lsc_multi_linkspeed) 795 SET(rplacp->flags, LAGGREQLACP_MULTILS); 796 797 rplacp->maxports = lsc->lsc_max_ports; 798 rplacp->actor_prio = ntohs(lsc->lsc_system_prio); 799 memcpy(rplacp->actor_mac, lsc->lsc_system_mac, 800 sizeof(rplacp->actor_mac)); 801 rplacp->actor_key = ntohs(lsc->lsc_key); 802 803 if (la != NULL) { 804 sid = &la->la_sid; 805 rplacp->partner_prio = ntohs(sid->sid_prio); 806 memcpy(rplacp->partner_mac, sid->sid_mac, 807 sizeof(rplacp->partner_mac)); 808 rplacp->partner_key = ntohs(sid->sid_key); 809 } 810 LACP_UNLOCK(lsc); 811 } 812 813 void 814 lacp_portstat(struct lagg_proto_softc *xlsc, struct lagg_port *lp, 815 struct laggreqport *resp) 816 { 817 struct laggreq_lacpport *llp; 818 struct lacp_softc *lsc; 819 struct lacp_port *lacpp; 820 struct lacp_aggregator *la; 821 struct lacp_aggregator_systemid *sid; 822 823 lsc = (struct lacp_softc *)xlsc; 824 lacpp = lp->lp_proto_ctx; 825 la = lacpp->lp_aggregator; 826 llp = &resp->rp_lacpport; 827 828 if (lacp_isactive(lsc, lacpp)) 829 SET(resp->rp_flags, LAGG_PORT_ACTIVE); 830 if (lacp_iscollecting(lacpp)) 831 SET(resp->rp_flags, LAGG_PORT_COLLECTING); 832 if (lacp_isdistributing(lacpp)) 833 SET(resp->rp_flags, LAGG_PORT_DISTRIBUTING); 834 if (lacpp->lp_selected == LACP_STANDBY) 835 SET(resp->rp_flags, LAGG_PORT_STANDBY); 836 837 if (la != NULL) { 838 sid = &la->la_sid; 839 llp->partner_prio = ntohs(sid->sid_prio); 840 memcpy(llp->partner_mac, sid->sid_mac, 841 sizeof(llp->partner_mac)); 842 llp->partner_key = ntohs(sid->sid_key); 843 } 844 845 llp->actor_portprio = ntohs(lacpp->lp_actor.lpi_portprio); 846 llp->actor_portno = ntohs(lacpp->lp_actor.lpi_portno); 847 llp->actor_state = lacpp->lp_actor.lpi_state; 848 849 llp->partner_portprio = ntohs(lacpp->lp_partner.lpi_portprio); 850 llp->partner_portno = ntohs(lacpp->lp_partner.lpi_portno); 851 llp->partner_state = lacpp->lp_partner.lpi_state; 852 } 853 854 void 855 lacp_linkstate_ifnet_locked(struct lagg_proto_softc *xlsc, struct lagg_port *lp) 856 { 857 struct lacp_softc *lsc; 858 struct lacp_port *lacpp; 859 struct ifmediareq ifmr; 860 struct ifnet *ifp_port; 861 uint8_t old_state; 862 uint64_t old_linkspeed, new_linkspeed; 863 int error; 864 865 KASSERT(IFNET_LOCKED(lp->lp_ifp)); 866 867 lsc = (struct lacp_softc *)xlsc; 868 869 ifp_port = lp->lp_ifp; 870 lacpp = lp->lp_proto_ctx; 871 872 memset(&ifmr, 0, sizeof(ifmr)); 873 ifmr.ifm_count = 0; 874 error = if_ioctl(ifp_port, SIOCGIFMEDIA, (void *)&ifmr); 875 if (error == 0) { 876 new_linkspeed = ifmedia_baudrate(ifmr.ifm_active); 877 #ifdef LACP_NOFDX 878 /* 879 * some driver that has no media, e.g. vioif(4), 880 * returns (IFM_ETHER | IFM_AUTO) 881 */ 882 if ((ifmr.ifm_active & ~(IFM_ETHER | IFM_AUTO)) == 0) 883 ifmr.ifm_active |= IFM_FDX; 884 #endif 885 } else if (error == ENOTTY) { 886 ifmr.ifm_active = IFM_FDX | IF_Gbps(0); 887 new_linkspeed = 0; 888 } else { 889 LACP_DPRINTF((lsc, lacpp, 890 "SIOCGIFMEDIA failed (%d)\n", error)); 891 return; 892 } 893 894 LACP_LOCK(lsc); 895 if (lsc->lsc_running) { 896 old_linkspeed = lacpp->lp_linkspeed; 897 old_state = lacpp->lp_actor.lpi_state; 898 899 if (new_linkspeed != old_linkspeed) { 900 LACP_DPRINTF((lsc, lacpp, 901 "linkspeed changed %"PRIu64" -> %"PRIu64"\n", 902 old_linkspeed, new_linkspeed)); 903 lacpp->lp_linkspeed = new_linkspeed; 904 } 905 906 if (ISSET(ifmr.ifm_active, IFM_FDX) && 907 ISSET(ifp_port->if_flags, IFF_RUNNING) && 908 ifp_port->if_link_state != LINK_STATE_DOWN) { 909 lacp_port_enable(lsc, lacpp); 910 } else { 911 LACP_DPRINTF((lsc, lacpp, 912 "FDX=%d, RUNNING=%d, link=%d\n", 913 ISSET(ifmr.ifm_active, IFM_FDX) != 0, 914 ISSET(ifp_port->if_flags, IFF_RUNNING) != 0, 915 ifp_port->if_link_state != LINK_STATE_DOWN)); 916 lacp_port_disable(lsc, lacpp); 917 } 918 919 if (old_state != lacpp->lp_actor.lpi_state || 920 old_linkspeed != new_linkspeed) { 921 LACP_DPRINTF((lsc, lacpp, 922 "state changed to UNSELECTED\n")); 923 lacpp->lp_selected = LACP_UNSELECTED; 924 } 925 } else { 926 LACP_DPRINTF((lsc, lacpp, 927 "LACP is inactive, skip linkstate\n")); 928 } 929 LACP_UNLOCK(lsc); 930 } 931 932 int 933 lacp_ioctl(struct lagg_proto_softc *xlsc, struct laggreqproto *lreq) 934 { 935 struct lacp_softc *lsc; 936 struct laggreq_lacp *rplacp; 937 struct lacp_aggregator *la; 938 int error; 939 size_t maxports; 940 bool set; 941 942 lsc = (struct lacp_softc *)xlsc; 943 rplacp = &lreq->rp_lacp; 944 error = 0; 945 946 switch (rplacp->command) { 947 case LAGGIOC_LACPSETFLAGS: 948 case LAGGIOC_LACPCLRFLAGS: 949 set = (rplacp->command == LAGGIOC_LACPSETFLAGS) ? 950 true : false; 951 952 LACP_LOCK(lsc); 953 954 if (ISSET(rplacp->flags, LAGGREQLACP_OPTIMISTIC)) 955 lsc->lsc_optimistic = set; 956 if (ISSET(rplacp->flags, LAGGREQLACP_DUMPDU)) 957 lsc->lsc_dump_du = set; 958 if (ISSET(rplacp->flags, LAGGREQLACP_STOPDU)) 959 lsc->lsc_stop_lacpdu = set; 960 961 if (ISSET(rplacp->flags, LAGGREQLACP_MULTILS) && 962 lsc->lsc_multi_linkspeed != set) { 963 lsc->lsc_multi_linkspeed = set; 964 TAILQ_FOREACH(la, &lsc->lsc_aggregators, la_q) { 965 lacp_selected_update(lsc, la); 966 } 967 } 968 969 LACP_UNLOCK(lsc); 970 break; 971 case LAGGIOC_LACPSETMAXPORTS: 972 case LAGGIOC_LACPCLRMAXPORTS: 973 maxports = (rplacp->command == LAGGIOC_LACPSETMAXPORTS) ? 974 rplacp->maxports : LACP_MAX_PORTS; 975 if (0 == maxports || LACP_MAX_PORTS < maxports) { 976 error = ERANGE; 977 break; 978 } 979 980 LACP_LOCK(lsc); 981 if (lsc->lsc_max_ports != maxports) { 982 lsc->lsc_max_ports = maxports; 983 TAILQ_FOREACH(la, &lsc->lsc_aggregators, la_q) { 984 lacp_selected_update(lsc, la); 985 } 986 } 987 LACP_UNLOCK(lsc); 988 break; 989 default: 990 error = ENOTTY; 991 } 992 993 return error; 994 } 995 996 static int 997 lacp_pdu_input(struct lacp_softc *lsc, struct lacp_port *lacpp, struct mbuf *m) 998 { 999 enum { 1000 LACP_TLV_ACTOR = 0, 1001 LACP_TLV_PARTNER, 1002 LACP_TLV_COLLECTOR, 1003 LACP_TLV_TERM, 1004 LACP_TLV_NUM 1005 }; 1006 1007 struct lacpdu *du; 1008 struct lacpdu_peerinfo *pi_actor, *pi_partner; 1009 struct lacpdu_collectorinfo *lci; 1010 struct tlv tlvlist_lacp[LACP_TLV_NUM] = { 1011 [LACP_TLV_ACTOR] = { 1012 .tlv_t = LACP_TYPE_ACTORINFO, 1013 .tlv_l = sizeof(*pi_actor)}, 1014 [LACP_TLV_PARTNER] = { 1015 .tlv_t = LACP_TYPE_PARTNERINFO, 1016 .tlv_l = sizeof(*pi_partner)}, 1017 [LACP_TLV_COLLECTOR] = { 1018 .tlv_t = LACP_TYPE_COLLECTORINFO, 1019 .tlv_l = sizeof(*lci)}, 1020 [LACP_TLV_TERM] = { 1021 .tlv_t = TLV_TYPE_TERMINATE, 1022 .tlv_l = 0}, 1023 }; 1024 1025 if (m->m_pkthdr.len != sizeof(*du)) 1026 goto bad; 1027 1028 if (m->m_len < (int)sizeof(*du)) { 1029 m = m_pullup(m, sizeof(*du)); 1030 if (m == NULL) { 1031 lsc->lsc_mpullup_failed.ev_count++; 1032 return ENOMEM; 1033 } 1034 } 1035 1036 du = mtod(m, struct lacpdu *); 1037 1038 if (memcmp(&du->ldu_eh.ether_dhost, 1039 ethermulticastaddr_slowprotocols, ETHER_ADDR_LEN) != 0) 1040 goto bad; 1041 1042 LACP_TLV_PARSE(du, struct lacpdu, ldu_tlv_actor, 1043 tlvlist_lacp); 1044 1045 pi_actor = tlvlist_lacp[LACP_TLV_ACTOR].tlv_v; 1046 pi_partner = tlvlist_lacp[LACP_TLV_PARTNER].tlv_v; 1047 lci = tlvlist_lacp[LACP_TLV_COLLECTOR].tlv_v; 1048 1049 if (pi_actor == NULL || pi_partner == NULL) 1050 goto bad; 1051 1052 if (LACP_ISDUMPING(lsc)) { 1053 lacp_dprintf(lsc, lacpp, "lacpdu received\n"); 1054 lacp_dump_lacpdutlv(pi_actor, pi_partner, lci); 1055 } 1056 1057 LACP_LOCK(lsc); 1058 lacp_sm_rx(lsc, lacpp, pi_partner, pi_actor); 1059 LACP_UNLOCK(lsc); 1060 1061 m_freem(m); 1062 return 0; 1063 bad: 1064 lsc->lsc_badlacpdu.ev_count++; 1065 m_freem(m); 1066 return EINVAL; 1067 } 1068 1069 static int 1070 marker_cmp(struct markerdu_info *mi, 1071 struct lacp_softc *lsc, struct lacp_port *lacpp) 1072 { 1073 1074 KASSERT(LACP_LOCKED(lsc)); 1075 1076 if (mi->mi_rq_port != lacpp->lp_actor.lpi_portno) 1077 return -1; 1078 1079 if (ntohl(mi->mi_rq_xid) != lacpp->lp_marker_xid) 1080 return -1; 1081 1082 return memcmp(mi->mi_rq_system, lsc->lsc_system_mac, 1083 LACP_MAC_LEN); 1084 } 1085 1086 static void 1087 lacp_marker_reply(struct lacp_softc *lsc, struct lacp_port *lacpp, 1088 struct mbuf *m_info) 1089 { 1090 struct lagg_port *lp; 1091 struct markerdu *mdu; 1092 struct ifnet *ifp_port; 1093 struct psref psref; 1094 1095 LACP_LOCK(lsc); 1096 lp = lacpp->lp_laggport; 1097 lagg_port_getref(lp, &psref); 1098 LACP_UNLOCK(lsc); 1099 1100 ifp_port = lp->lp_ifp; 1101 mdu = mtod(m_info, struct markerdu *); 1102 1103 mdu->mdu_tlv_info.tlv_type = MARKER_TYPE_RESPONSE; 1104 /* ether_dhost is already ethermulticastaddr_slowprotocols */ 1105 m_info->m_flags |= M_MCAST; 1106 memcpy(mdu->mdu_eh.ether_shost, 1107 CLLADDR(ifp_port->if_sadl), ETHER_ADDR_LEN); 1108 1109 if (LACP_ISDUMPING(lsc)) { 1110 lacp_dprintf(lsc, lacpp, "markerdu reply\n"); 1111 lacp_dump_markertlv(NULL, &mdu->mdu_info); 1112 } 1113 1114 lagg_port_xmit(lp, m_info); 1115 lagg_port_putref(lp, &psref); 1116 } 1117 1118 static int 1119 lacp_marker_recv_response(struct lacp_softc *lsc, struct lacp_port *lacpp, 1120 struct markerdu_info *mi_res) 1121 { 1122 struct lagg_softc *sc; 1123 struct lagg_port *lp0; 1124 struct lacp_port *lacpp0; 1125 bool pending; 1126 1127 sc = lsc->lsc_softc; 1128 1129 LACP_LOCK(lsc); 1130 if (marker_cmp(mi_res, lsc, lacpp) != 0) { 1131 LACP_UNLOCK(lsc); 1132 return -1; 1133 } 1134 CLR(lacpp->lp_flags, LACP_PORT_MARK); 1135 LACP_UNLOCK(lsc); 1136 1137 LAGG_LOCK(sc); 1138 LACP_LOCK(lsc); 1139 1140 if (lsc->lsc_suppress_distributing) { 1141 pending = false; 1142 LAGG_PORTS_FOREACH(sc, lp0) { 1143 lacpp0 = lp0->lp_proto_ctx; 1144 if (ISSET(lacpp0->lp_flags, LACP_PORT_MARK)) { 1145 pending = true; 1146 break; 1147 } 1148 } 1149 1150 if (!pending) { 1151 LACP_DPRINTF((lsc, NULL, "queue flush complete\n")); 1152 LACP_PTIMER_DISARM(lsc, LACP_PTIMER_DISTRIBUTING); 1153 lsc->lsc_suppress_distributing = false; 1154 } 1155 } 1156 1157 LACP_UNLOCK(lsc); 1158 LAGG_UNLOCK(sc); 1159 1160 return 0; 1161 } 1162 1163 static int 1164 lacp_marker_input(struct lacp_softc *lsc, struct lacp_port *lacpp, 1165 struct mbuf *m) 1166 { 1167 enum { 1168 MARKER_TLV_INFO = 0, 1169 MARKER_TLV_RESPONSE, 1170 MARKER_TLV_TERM, 1171 MARKER_TLV_NUM 1172 }; 1173 1174 struct markerdu *mdu; 1175 struct markerdu_info *mi_info, *mi_res; 1176 int error; 1177 struct tlv tlvlist_marker[MARKER_TLV_NUM] = { 1178 [MARKER_TLV_INFO] = { 1179 .tlv_t = MARKER_TYPE_INFO, 1180 .tlv_l = sizeof(*mi_info)}, 1181 [MARKER_TLV_RESPONSE] = { 1182 .tlv_t = MARKER_TYPE_RESPONSE, 1183 .tlv_l = sizeof(*mi_res)}, 1184 [MARKER_TLV_TERM] = { 1185 .tlv_t = TLV_TYPE_TERMINATE, 1186 .tlv_l = 0}, 1187 }; 1188 1189 if (m->m_pkthdr.len != sizeof(*mdu)) 1190 goto bad; 1191 1192 if (m->m_len < (int)sizeof(*mdu)) { 1193 m = m_pullup(m, sizeof(*mdu)); 1194 if (m == NULL) { 1195 lsc->lsc_mpullup_failed.ev_count++; 1196 return ENOMEM; 1197 } 1198 } 1199 1200 mdu = mtod(m, struct markerdu *); 1201 1202 if (memcmp(mdu->mdu_eh.ether_dhost, 1203 ethermulticastaddr_slowprotocols, ETHER_ADDR_LEN) != 0) 1204 goto bad; 1205 1206 LACP_TLV_PARSE(mdu, struct markerdu, mdu_tlv_info, 1207 tlvlist_marker); 1208 1209 mi_info = tlvlist_marker[MARKER_TLV_INFO].tlv_v; 1210 mi_res = tlvlist_marker[MARKER_TLV_RESPONSE].tlv_v; 1211 1212 if (LACP_ISDUMPING(lsc)) { 1213 lacp_dprintf(lsc, lacpp, "markerdu received\n"); 1214 lacp_dump_markertlv(mi_info, mi_res); 1215 } 1216 1217 if (mi_info != NULL && mi_res == NULL) { 1218 lacp_marker_reply(lsc, lacpp, m); 1219 } else if (mi_info == NULL && mi_res != NULL) { 1220 error = lacp_marker_recv_response(lsc, lacpp, 1221 mi_res); 1222 if (error != 0) { 1223 goto bad; 1224 } else { 1225 m_freem(m); 1226 } 1227 } else { 1228 goto bad; 1229 } 1230 1231 return 0; 1232 bad: 1233 lsc->lsc_badmarkerdu.ev_count++; 1234 m_freem(m); 1235 return EINVAL; 1236 } 1237 1238 struct mbuf * 1239 lacp_input(struct lagg_proto_softc *xlsc, struct lagg_port *lp, struct mbuf *m) 1240 { 1241 struct ifnet *ifp; 1242 struct lacp_softc *lsc; 1243 struct lacp_port *lacpp; 1244 struct ether_header *eh; 1245 uint8_t subtype; 1246 1247 eh = mtod(m, struct ether_header *); 1248 lsc = (struct lacp_softc *)xlsc; 1249 ifp = &lsc->lsc_softc->sc_if; 1250 lacpp = lp->lp_proto_ctx; 1251 1252 if (!vlan_has_tag(m) && 1253 eh->ether_type == htons(ETHERTYPE_SLOWPROTOCOLS)) { 1254 if (m->m_pkthdr.len < (int)(sizeof(*eh) + sizeof(subtype))) { 1255 m_freem(m); 1256 return NULL; 1257 } 1258 1259 m_copydata(m, sizeof(struct ether_header), 1260 sizeof(subtype), &subtype); 1261 1262 switch (subtype) { 1263 case SLOWPROTOCOLS_SUBTYPE_LACP: 1264 case SLOWPROTOCOLS_SUBTYPE_MARKER: 1265 if (pcq_put(lsc->lsc_du_q, (void *)m)) { 1266 lagg_workq_add(lsc->lsc_workq, 1267 &lsc->lsc_work_rcvdu); 1268 } else { 1269 m_freem(m); 1270 lsc->lsc_duq_nospc.ev_count++; 1271 } 1272 return NULL; 1273 } 1274 } 1275 1276 if (!lacp_iscollecting(lacpp) || !lacp_isactive(lsc, lacpp)) { 1277 if_statinc(ifp, if_ierrors); 1278 m_freem(m); 1279 return NULL; 1280 } 1281 1282 return m; 1283 } 1284 1285 static void 1286 lacp_rcvdu_work(struct lagg_work *lw __unused, void *xlsc) 1287 { 1288 struct lacp_softc *lsc = (struct lacp_softc *)xlsc; 1289 struct ifnet *ifp; 1290 struct psref psref_lp; 1291 struct lagg_port *lp; 1292 struct mbuf *m; 1293 uint8_t subtype; 1294 int bound, s0, s1; 1295 1296 bound = curlwp_bind(); 1297 1298 for (;;) { 1299 m = pcq_get(lsc->lsc_du_q); 1300 if (m == NULL) 1301 break; 1302 1303 ifp = m_get_rcvif(m, &s0); 1304 if (ifp == NULL) { 1305 m_freem(m); 1306 lsc->lsc_norcvif.ev_count++; 1307 continue; 1308 } 1309 1310 s1 = pserialize_read_enter(); 1311 lp = atomic_load_consume(&ifp->if_lagg); 1312 if (lp == NULL) { 1313 pserialize_read_exit(s1); 1314 m_put_rcvif(ifp, &s0); 1315 m_freem(m); 1316 lsc->lsc_norcvif.ev_count++; 1317 continue; 1318 } 1319 1320 lagg_port_getref(lp, &psref_lp); 1321 pserialize_read_exit(s1); 1322 m_put_rcvif(ifp, &s0); 1323 1324 m_copydata(m, sizeof(struct ether_header), 1325 sizeof(subtype), &subtype); 1326 1327 switch (subtype) { 1328 case SLOWPROTOCOLS_SUBTYPE_LACP: 1329 (void)lacp_pdu_input(lsc, 1330 lp->lp_proto_ctx, m); 1331 break; 1332 case SLOWPROTOCOLS_SUBTYPE_MARKER: 1333 (void)lacp_marker_input(lsc, 1334 lp->lp_proto_ctx, m); 1335 break; 1336 } 1337 1338 lagg_port_putref(lp, &psref_lp); 1339 } 1340 1341 curlwp_bindx(bound); 1342 } 1343 1344 static bool 1345 lacp_port_need_to_tell(struct lacp_port *lacpp) 1346 { 1347 1348 if (!ISSET(lacpp->lp_actor.lpi_state, 1349 LACP_STATE_AGGREGATION)) { 1350 return false; 1351 } 1352 1353 if (!ISSET(lacpp->lp_actor.lpi_state, 1354 LACP_STATE_ACTIVITY) 1355 && !ISSET(lacpp->lp_partner.lpi_state, 1356 LACP_STATE_ACTIVITY)) { 1357 return false; 1358 } 1359 1360 if (!ISSET(lacpp->lp_flags, LACP_PORT_NTT)) 1361 return false; 1362 1363 return true; 1364 } 1365 1366 static void 1367 lacp_sm_assert_ntt(struct lacp_port *lacpp) 1368 { 1369 1370 SET(lacpp->lp_flags, LACP_PORT_NTT); 1371 } 1372 1373 static void 1374 lacp_sm_negate_ntt(struct lacp_port *lacpp) 1375 { 1376 1377 CLR(lacpp->lp_flags, LACP_PORT_NTT); 1378 } 1379 1380 static struct mbuf * 1381 lacp_lacpdu_mbuf(struct lacp_softc *lsc, struct lacp_port *lacpp) 1382 { 1383 struct ifnet *ifp_port; 1384 struct mbuf *m; 1385 struct lacpdu *du; 1386 1387 KASSERT(LACP_LOCKED(lsc)); 1388 1389 ifp_port = lacpp->lp_laggport->lp_ifp; 1390 1391 MGETHDR(m, M_DONTWAIT, MT_DATA); 1392 if (m == NULL) { 1393 lsc->lsc_mgethdr_failed.ev_count++; 1394 return NULL; 1395 } 1396 1397 m->m_pkthdr.len = m->m_len = sizeof(*du); 1398 m_reset_rcvif(m); 1399 1400 du = mtod(m, struct lacpdu *); 1401 memset(du, 0, sizeof(*du)); 1402 1403 m->m_flags |= M_MCAST; 1404 memcpy(du->ldu_eh.ether_dhost, ethermulticastaddr_slowprotocols, 1405 ETHER_ADDR_LEN); 1406 memcpy(du->ldu_eh.ether_shost, CLLADDR(ifp_port->if_sadl), 1407 ETHER_ADDR_LEN); 1408 du->ldu_eh.ether_type = htons(ETHERTYPE_SLOWPROTOCOLS); 1409 du->ldu_sph.sph_subtype = SLOWPROTOCOLS_SUBTYPE_LACP; 1410 du->ldu_sph.sph_version = 1; 1411 1412 tlv_set(&du->ldu_tlv_actor, LACP_TYPE_ACTORINFO, 1413 sizeof(du->ldu_actor)); 1414 lacp_peerinfo_actor(lsc, lacpp, &du->ldu_actor); 1415 1416 tlv_set(&du->ldu_tlv_partner, LACP_TYPE_PARTNERINFO, 1417 sizeof(du->ldu_partner)); 1418 lacp_peerinfo_partner(lacpp, &du->ldu_partner); 1419 1420 tlv_set(&du->ldu_tlv_collector, LACP_TYPE_COLLECTORINFO, 1421 sizeof(du->ldu_collector)); 1422 du->ldu_collector.lci_maxdelay = 0; 1423 1424 du->ldu_tlv_term.tlv_type = LACP_TYPE_TERMINATE; 1425 du->ldu_tlv_term.tlv_length = 0; 1426 1427 return m; 1428 } 1429 1430 static void 1431 lacp_sm_tx_work(struct lagg_work *lw, void *xlsc) 1432 { 1433 struct lacp_softc *lsc; 1434 struct lacp_port *lacpp; 1435 struct lagg_port *lp; 1436 struct lacpdu *du; 1437 struct mbuf *m; 1438 struct psref psref; 1439 int bound; 1440 1441 lsc = xlsc; 1442 lacpp = container_of(lw, struct lacp_port, lp_work_smtx); 1443 1444 LACP_LOCK(lsc); 1445 1446 if (lsc->lsc_stop_lacpdu) { 1447 LACP_UNLOCK(lsc); 1448 return; 1449 } 1450 1451 m = lacp_lacpdu_mbuf(lsc, lacpp); 1452 if (m == NULL) { 1453 LACP_UNLOCK(lsc); 1454 return; 1455 } 1456 lacp_sm_negate_ntt(lacpp); 1457 lp = lacpp->lp_laggport; 1458 bound = curlwp_bind(); 1459 lagg_port_getref(lp, &psref); 1460 LACP_UNLOCK(lsc); 1461 1462 if (LACP_ISDUMPING(lsc)) { 1463 lacp_dprintf(lsc, lacpp, "lacpdu transmit\n"); 1464 du = mtod(m, struct lacpdu *); 1465 lacp_dump_lacpdutlv(&du->ldu_actor, 1466 &du->ldu_partner, &du->ldu_collector); 1467 } 1468 1469 lagg_port_xmit(lp, m); 1470 lagg_port_putref(lp, &psref); 1471 curlwp_bindx(bound); 1472 } 1473 1474 static void 1475 lacp_sm_tx(struct lacp_softc *lsc, struct lacp_port *lacpp) 1476 { 1477 1478 if (!lacp_port_need_to_tell(lacpp)) 1479 return; 1480 1481 lagg_workq_add(lsc->lsc_workq, &lacpp->lp_work_smtx); 1482 } 1483 1484 static void 1485 lacp_tick(void *xlsc) 1486 { 1487 struct lacp_softc *lsc; 1488 1489 lsc = xlsc; 1490 1491 LACP_LOCK(lsc); 1492 1493 if (!lsc->lsc_running) { 1494 LACP_UNLOCK(lsc); 1495 return; 1496 } 1497 1498 lagg_workq_add(lsc->lsc_workq, &lsc->lsc_work_tick); 1499 callout_schedule(&lsc->lsc_tick, hz); 1500 1501 LACP_UNLOCK(lsc); 1502 } 1503 1504 static void 1505 lacp_run_timers(struct lacp_softc *lsc, struct lacp_port *lacpp) 1506 { 1507 size_t i; 1508 1509 KASSERT(LACP_LOCKED(lsc)); 1510 1511 for (i = 0; i < LACP_NTIMER; i++) { 1512 KASSERT(lacpp->lp_timer[i] >= 0); 1513 1514 if (lacpp->lp_timer[i] == 0) 1515 continue; 1516 if (--lacpp->lp_timer[i] > 0) 1517 continue; 1518 1519 KASSERT(lacp_timer_funcs[i] != NULL); 1520 lacp_timer_funcs[i](lsc, lacpp); 1521 } 1522 } 1523 1524 static void 1525 lacp_run_prototimers(struct lacp_softc *lsc) 1526 { 1527 size_t i; 1528 1529 for (i = 0; i < LACP_NPTIMER; i++) { 1530 KASSERT(lsc->lsc_timer[i] >= 0); 1531 1532 if (lsc->lsc_timer[i] == 0) 1533 continue; 1534 if (--lsc->lsc_timer[i] > 0) 1535 continue; 1536 1537 KASSERT(lacp_ptimer_funcs[i] != NULL); 1538 lacp_ptimer_funcs[i](lsc); 1539 } 1540 } 1541 1542 static void 1543 lacp_tick_work(struct lagg_work *lw __unused, void *xlsc) 1544 { 1545 struct lacp_softc *lsc; 1546 struct lacp_port *lacpp; 1547 struct lagg_softc *sc; 1548 struct lagg_port *lp; 1549 1550 lsc = xlsc; 1551 sc = lsc->lsc_softc; 1552 1553 LACP_LOCK(lsc); 1554 if (!lsc->lsc_running) { 1555 LACP_UNLOCK(lsc); 1556 return; 1557 } 1558 1559 lacp_run_prototimers(lsc); 1560 LACP_UNLOCK(lsc); 1561 1562 LAGG_LOCK(sc); 1563 LACP_LOCK(lsc); 1564 LAGG_PORTS_FOREACH(sc, lp) { 1565 lacpp = lp->lp_proto_ctx; 1566 if (!ISSET(lacpp->lp_actor.lpi_state, 1567 LACP_STATE_AGGREGATION)) { 1568 continue; 1569 } 1570 1571 lacp_run_timers(lsc, lacpp); 1572 lacp_select(lsc, lacpp); 1573 lacp_sm_mux(lsc, lacpp); 1574 lacp_sm_tx(lsc, lacpp); 1575 lacp_sm_ptx_schedule(lacpp); 1576 } 1577 1578 LACP_UNLOCK(lsc); 1579 LAGG_UNLOCK(sc); 1580 } 1581 1582 static void 1583 lacp_systemid_str(char *buf, size_t buflen, 1584 uint16_t prio, const uint8_t *mac, uint16_t key) 1585 { 1586 1587 snprintf(buf, buflen, 1588 "%04X," 1589 "%02X-%02X-%02X-%02X-%02X-%02X," 1590 "%04X", 1591 (unsigned int)ntohs(prio), 1592 (int)mac[0], (int)mac[1], (int)mac[2], 1593 (int)mac[3], (int)mac[4], (int)mac[5], 1594 (unsigned int)htons(key)); 1595 1596 } 1597 1598 __LACPDEBUGUSED static void 1599 lacp_aggregator_str(struct lacp_aggregator *la, char *buf, size_t buflen) 1600 { 1601 1602 lacp_systemid_str(buf, buflen, la->la_sid.sid_prio, 1603 la->la_sid.sid_mac, la->la_sid.sid_key); 1604 } 1605 1606 static void 1607 lacp_peerinfo_idstr(const struct lacpdu_peerinfo *pi, 1608 char *buf, size_t buflen) 1609 { 1610 1611 lacp_systemid_str(buf, buflen, pi->lpi_system_prio, 1612 pi->lpi_system_mac, pi->lpi_key); 1613 } 1614 1615 static void 1616 lacp_state_str(uint8_t state, char *buf, size_t buflen) 1617 { 1618 1619 snprintb(buf, buflen, LACP_STATE_BITS, state); 1620 } 1621 1622 static struct lagg_port * 1623 lacp_select_tx_port(struct lacp_softc *lsc, struct mbuf *m, 1624 struct psref *psref) 1625 { 1626 struct lacp_portmap *pm; 1627 struct lagg_port *lp; 1628 uint32_t hash; 1629 size_t act; 1630 int s; 1631 1632 hash = lagg_hashmbuf(lsc->lsc_softc, m); 1633 1634 s = pserialize_read_enter(); 1635 act = LACP_PORTMAP_ACTIVE(lsc); 1636 pm = &lsc->lsc_portmaps[act]; 1637 1638 if (pm->pm_count == 0) { 1639 pserialize_read_exit(s); 1640 return NULL; 1641 } 1642 1643 hash %= pm->pm_count; 1644 lp = pm->pm_ports[hash]; 1645 lagg_port_getref(lp, psref); 1646 1647 pserialize_read_exit(s); 1648 1649 return lp; 1650 } 1651 1652 static void 1653 lacp_peerinfo_actor(struct lacp_softc *lsc, struct lacp_port *lacpp, 1654 struct lacpdu_peerinfo *dst) 1655 { 1656 1657 memcpy(dst->lpi_system_mac, lsc->lsc_system_mac, LACP_MAC_LEN); 1658 dst->lpi_system_prio = lsc->lsc_system_prio; 1659 dst->lpi_key = lsc->lsc_key; 1660 dst->lpi_port_no = lacpp->lp_actor.lpi_portno; 1661 dst->lpi_port_prio = lacpp->lp_actor.lpi_portprio; 1662 dst->lpi_state = lacpp->lp_actor.lpi_state; 1663 } 1664 1665 static void 1666 lacp_peerinfo_partner(struct lacp_port *lacpp, struct lacpdu_peerinfo *dst) 1667 { 1668 struct lacp_aggregator *la; 1669 1670 la = lacpp->lp_aggregator; 1671 1672 if (la != NULL) { 1673 memcpy(dst->lpi_system_mac, la->la_sid.sid_mac, LACP_MAC_LEN); 1674 dst->lpi_system_prio = la->la_sid.sid_prio; 1675 dst->lpi_key = la->la_sid.sid_key; 1676 } else { 1677 memset(dst->lpi_system_mac, 0, LACP_MAC_LEN); 1678 dst->lpi_system_prio = 0; 1679 dst->lpi_key = 0; 1680 } 1681 dst->lpi_port_no = lacpp->lp_partner.lpi_portno; 1682 dst->lpi_port_prio = lacpp->lp_partner.lpi_portprio; 1683 dst->lpi_state = lacpp->lp_partner.lpi_state; 1684 } 1685 1686 static int 1687 lacp_compare_peerinfo(struct lacpdu_peerinfo *a, struct lacpdu_peerinfo *b) 1688 { 1689 1690 return memcmp(a, b, offsetof(struct lacpdu_peerinfo, lpi_state)); 1691 } 1692 1693 static void 1694 lacp_sm_rx_record_default(struct lacp_softc *lsc, struct lacp_port *lacpp) 1695 { 1696 uint8_t oldpstate; 1697 struct lacp_portinfo *pi; 1698 char buf[LACP_STATESTR_LEN] __LACPDEBUGUSED; 1699 1700 pi = &lacpp->lp_partner; 1701 1702 oldpstate = pi->lpi_state; 1703 pi->lpi_portno = htons(LACP_PORTNO_NONE); 1704 pi->lpi_portprio = htons(0xffff); 1705 1706 if (lsc->lsc_optimistic) 1707 pi->lpi_state = LACP_PARTNER_ADMIN_OPTIMISTIC; 1708 else 1709 pi->lpi_state = LACP_PARTNER_ADMIN_STRICT; 1710 1711 SET(lacpp->lp_actor.lpi_state, LACP_STATE_DEFAULTED); 1712 1713 if (oldpstate != pi->lpi_state) { 1714 LACP_STATE_STR(oldpstate, buf, sizeof(buf)); 1715 LACP_DPRINTF((lsc, lacpp, "oldpstate %s\n", buf)); 1716 1717 LACP_STATE_STR(pi->lpi_state, buf, sizeof(buf)); 1718 LACP_DPRINTF((lsc, lacpp, "newpstate %s\n", buf)); 1719 } 1720 1721 lacp_sm_ptx_update_timeout(lacpp, oldpstate); 1722 } 1723 1724 static inline bool 1725 lacp_port_is_synced(struct lacp_softc *lsc, struct lacp_port *lacpp, 1726 struct lacpdu_peerinfo *my_pi, struct lacpdu_peerinfo *peer_pi) 1727 { 1728 struct lacpdu_peerinfo actor; 1729 1730 if (!ISSET(peer_pi->lpi_state, LACP_STATE_ACTIVITY) && 1731 (!ISSET(my_pi->lpi_state, LACP_STATE_ACTIVITY) || 1732 !ISSET(lacpp->lp_actor.lpi_state, LACP_STATE_ACTIVITY))) 1733 return false; 1734 1735 if (!ISSET(peer_pi->lpi_state, LACP_STATE_AGGREGATION)) 1736 return false; 1737 1738 lacp_peerinfo_actor(lsc, lacpp, &actor); 1739 if (lacp_compare_peerinfo(&actor, my_pi) != 0) 1740 return false; 1741 1742 if (!LACP_STATE_EQ(actor.lpi_state, my_pi->lpi_state, 1743 LACP_STATE_AGGREGATION)) { 1744 return false; 1745 } 1746 1747 return true; 1748 } 1749 1750 static void 1751 lacp_sm_rx_record_peerinfo(struct lacp_softc *lsc, struct lacp_port *lacpp, 1752 struct lacpdu_peerinfo *my_pi, struct lacpdu_peerinfo *peer_pi) 1753 { 1754 char buf[LACP_STATESTR_LEN] __LACPDEBUGUSED; 1755 uint8_t oldpstate; 1756 struct lacp_portinfo *pi; 1757 struct lacp_aggregator_systemid *sid; 1758 1759 pi = &lacpp->lp_partner; 1760 sid = &lacpp->lp_aggregator_sidbuf; 1761 1762 oldpstate = lacpp->lp_partner.lpi_state; 1763 1764 sid->sid_prio = peer_pi->lpi_system_prio; 1765 sid->sid_key = peer_pi->lpi_key; 1766 memcpy(sid->sid_mac, peer_pi->lpi_system_mac, 1767 sizeof(sid->sid_mac)); 1768 1769 pi->lpi_portno = peer_pi->lpi_port_no; 1770 pi->lpi_portprio = peer_pi->lpi_port_prio; 1771 pi->lpi_state = peer_pi->lpi_state; 1772 1773 if (lacp_port_is_synced(lsc, lacpp, my_pi, peer_pi)) { 1774 if (lsc->lsc_optimistic) 1775 SET(lacpp->lp_partner.lpi_state, LACP_STATE_SYNC); 1776 } else { 1777 CLR(lacpp->lp_partner.lpi_state, LACP_STATE_SYNC); 1778 } 1779 1780 CLR(lacpp->lp_actor.lpi_state, LACP_STATE_DEFAULTED); 1781 1782 if (oldpstate != lacpp->lp_partner.lpi_state) { 1783 LACP_STATE_STR(oldpstate, buf, sizeof(buf)); 1784 LACP_DPRINTF((lsc, lacpp, "oldpstate %s\n", buf)); 1785 1786 LACP_STATE_STR(lacpp->lp_partner.lpi_state, 1787 buf, sizeof(buf)); 1788 LACP_DPRINTF((lsc, lacpp, "newpstate %s\n", buf)); 1789 } 1790 1791 lacp_sm_ptx_update_timeout(lacpp, oldpstate); 1792 } 1793 1794 static void 1795 lacp_sm_rx_set_expired(struct lacp_port *lacpp) 1796 { 1797 uint8_t oldpstate; 1798 1799 oldpstate = lacpp->lp_partner.lpi_state; 1800 1801 CLR(lacpp->lp_partner.lpi_state, LACP_STATE_SYNC); 1802 SET(lacpp->lp_partner.lpi_state, LACP_STATE_TIMEOUT); 1803 LACP_TIMER_ARM(lacpp, LACP_TIMER_CURRENT_WHILE, 1804 LACP_SHORT_TIMEOUT_TIME); 1805 SET(lacpp->lp_actor.lpi_state, LACP_STATE_EXPIRED); 1806 1807 lacp_sm_ptx_update_timeout(lacpp, oldpstate); 1808 } 1809 1810 static void 1811 lacp_sm_port_init(struct lacp_softc *lsc, struct lacp_port *lacpp, 1812 struct lagg_port *lp) 1813 { 1814 1815 KASSERT(LACP_LOCKED(lsc)); 1816 1817 lacpp->lp_laggport = lp; 1818 lacpp->lp_actor.lpi_state = LACP_STATE_ACTIVITY; 1819 lacpp->lp_actor.lpi_portno = htons(if_get_index(lp->lp_ifp)); 1820 lacpp->lp_actor.lpi_portprio = htons(LACP_PORT_PRIO); 1821 lacpp->lp_partner.lpi_state = LACP_STATE_TIMEOUT; 1822 lacpp->lp_aggregator = NULL; 1823 lacpp->lp_marker_xid = 0; 1824 lacpp->lp_mux_state = LACP_MUX_INIT; 1825 1826 lacp_set_mux(lsc, lacpp, LACP_MUX_DETACHED); 1827 lacp_sm_rx_record_default(lsc, lacpp); 1828 } 1829 1830 static void 1831 lacp_port_disable(struct lacp_softc *lsc, struct lacp_port *lacpp) 1832 { 1833 1834 KASSERT(LACP_LOCKED(lsc)); 1835 1836 if (ISSET(lacpp->lp_actor.lpi_state, LACP_STATE_AGGREGATION)) 1837 LACP_DPRINTF((lsc, lacpp, "enable -> disable\n")); 1838 1839 lacp_set_mux(lsc, lacpp, LACP_MUX_DETACHED); 1840 lacp_sm_rx_record_default(lsc, lacpp); 1841 CLR(lacpp->lp_actor.lpi_state, 1842 LACP_STATE_AGGREGATION | LACP_STATE_EXPIRED); 1843 CLR(lacpp->lp_partner.lpi_state, LACP_STATE_AGGREGATION); 1844 } 1845 1846 static void 1847 lacp_port_enable(struct lacp_softc *lsc __LACPDEBUGUSED, 1848 struct lacp_port *lacpp) 1849 { 1850 1851 KASSERT(LACP_LOCKED(lsc)); 1852 1853 if (!ISSET(lacpp->lp_actor.lpi_state, LACP_STATE_AGGREGATION)) 1854 LACP_DPRINTF((lsc, lacpp, "disable -> enable\n")); 1855 1856 SET(lacpp->lp_actor.lpi_state, LACP_STATE_AGGREGATION); 1857 lacp_sm_rx_set_expired(lacpp); 1858 } 1859 1860 static void 1861 lacp_sm_rx_timer(struct lacp_softc *lsc, struct lacp_port *lacpp) 1862 { 1863 1864 KASSERT(LACP_LOCKED(lsc)); 1865 1866 if (!ISSET(lacpp->lp_actor.lpi_state, LACP_STATE_EXPIRED)) { 1867 /* CURRENT -> EXPIRED */ 1868 LACP_DPRINTF((lsc, lacpp, "CURRENT -> EXPIRED\n")); 1869 lacp_sm_rx_set_expired(lacpp); 1870 } else { 1871 LACP_DPRINTF((lsc, lacpp, "EXPIRED -> DEFAULTED\n")); 1872 lacp_set_mux(lsc, lacpp, LACP_MUX_DETACHED); 1873 lacp_sm_rx_record_default(lsc, lacpp); 1874 } 1875 } 1876 1877 static void 1878 lacp_sm_ptx_timer(struct lacp_softc *lsc __unused, struct lacp_port *lacpp) 1879 { 1880 1881 KASSERT(LACP_LOCKED(lsc)); 1882 lacp_sm_assert_ntt(lacpp); 1883 } 1884 1885 static void 1886 lacp_sm_ptx_schedule(struct lacp_port *lacpp) 1887 { 1888 int timeout; 1889 1890 /* no periodic */ 1891 if (!ISSET(lacpp->lp_actor.lpi_state, LACP_STATE_ACTIVITY) && 1892 !ISSET(lacpp->lp_partner.lpi_state, LACP_STATE_ACTIVITY)) { 1893 LACP_TIMER_DISARM(lacpp, LACP_TIMER_PERIODIC); 1894 return; 1895 } 1896 1897 if (LACP_TIMER_ISARMED(lacpp, LACP_TIMER_PERIODIC)) 1898 return; 1899 1900 timeout = ISSET(lacpp->lp_partner.lpi_state, LACP_STATE_TIMEOUT) ? 1901 LACP_FAST_PERIODIC_TIME : LACP_SLOW_PERIODIC_TIME; 1902 1903 LACP_TIMER_ARM(lacpp, LACP_TIMER_PERIODIC, timeout); 1904 } 1905 1906 static void 1907 lacp_sm_ptx_update_timeout(struct lacp_port *lacpp, uint8_t oldpstate) 1908 { 1909 1910 if (LACP_STATE_EQ(oldpstate, lacpp->lp_partner.lpi_state, 1911 LACP_STATE_TIMEOUT)) 1912 return; 1913 1914 LACP_DPRINTF((NULL, lacpp, "partner timeout changed\n")); 1915 1916 LACP_TIMER_DISARM(lacpp, LACP_TIMER_PERIODIC); 1917 1918 /* if timeout has been shorted, assert NTT */ 1919 if (ISSET(lacpp->lp_partner.lpi_state, LACP_STATE_TIMEOUT)) 1920 lacp_sm_assert_ntt(lacpp); 1921 } 1922 1923 static void 1924 lacp_sm_mux_timer(struct lacp_softc *lsc __LACPDEBUGUSED, 1925 struct lacp_port *lacpp) 1926 { 1927 char buf[LACP_SYSTEMIDSTR_LEN] __LACPDEBUGUSED; 1928 1929 KASSERT(LACP_LOCKED(lsc)); 1930 KASSERT(lacpp->lp_pending > 0); 1931 1932 LACP_AGGREGATOR_STR(lacpp->lp_aggregator, buf, sizeof(buf)); 1933 LACP_DPRINTF((lsc, lacpp, "aggregator %s, pending %d -> %d\n", 1934 buf, lacpp->lp_pending, lacpp->lp_pending -1)); 1935 1936 lacpp->lp_pending--; 1937 } 1938 1939 static void 1940 lacp_sm_rx_update_selected(struct lacp_softc *lsc, struct lacp_port *lacpp, 1941 struct lacpdu_peerinfo *peer_pi) 1942 { 1943 struct lacpdu_peerinfo partner; 1944 char str0[LACP_SYSTEMIDSTR_LEN] __LACPDEBUGUSED; 1945 char str1[LACP_SYSTEMIDSTR_LEN] __LACPDEBUGUSED; 1946 1947 if (lacpp->lp_aggregator == NULL) 1948 return; 1949 1950 lacp_peerinfo_partner(lacpp, &partner); 1951 if (lacp_compare_peerinfo(peer_pi, &partner) != 0) { 1952 LACP_PEERINFO_IDSTR(&partner, str0, sizeof(str0)); 1953 LACP_PEERINFO_IDSTR(peer_pi, str1, sizeof(str1)); 1954 LACP_DPRINTF((lsc, lacpp, 1955 "different peerinfo, %s vs %s\n", str0, str1)); 1956 goto do_unselect; 1957 } 1958 1959 if (!LACP_STATE_EQ(lacpp->lp_partner.lpi_state, 1960 peer_pi->lpi_state, LACP_STATE_AGGREGATION)) { 1961 LACP_DPRINTF((lsc, lacpp, 1962 "STATE_AGGREGATION changed %d -> %d\n", 1963 ISSET(lacpp->lp_partner.lpi_state, 1964 LACP_STATE_AGGREGATION) != 0, 1965 ISSET(peer_pi->lpi_state, LACP_STATE_AGGREGATION) != 0)); 1966 goto do_unselect; 1967 } 1968 1969 return; 1970 1971 do_unselect: 1972 lacpp->lp_selected = LACP_UNSELECTED; 1973 /* lacpp->lp_aggregator will be released at lacp_set_mux() */ 1974 } 1975 1976 static void 1977 lacp_sm_rx_update_ntt(struct lacp_softc *lsc, struct lacp_port *lacpp, 1978 struct lacpdu_peerinfo *my_pi) 1979 { 1980 struct lacpdu_peerinfo actor; 1981 1982 lacp_peerinfo_actor(lsc, lacpp, &actor); 1983 1984 if (lacp_compare_peerinfo(&actor, my_pi) != 0 || 1985 !LACP_STATE_EQ(lacpp->lp_actor.lpi_state, my_pi->lpi_state, 1986 LACP_STATE_ACTIVITY | LACP_STATE_SYNC | LACP_STATE_AGGREGATION)) { 1987 if (ppsratecheck(&lacpp->lp_last_lacpdu, &lacpp->lp_lacpdu_sent, 1988 (LACP_SENDDU_PPS / LACP_FAST_PERIODIC_TIME)) == 0) { 1989 LACP_DPRINTF((lsc, lacpp, 1990 "skip ntt due to rate limit")); 1991 } else { 1992 LACP_DPRINTF((lsc, lacpp, "assert ntt\n")); 1993 lacp_sm_assert_ntt(lacpp); 1994 } 1995 } 1996 } 1997 1998 static void 1999 lacp_sm_rx(struct lacp_softc *lsc, struct lacp_port *lacpp, 2000 struct lacpdu_peerinfo *my_pi, struct lacpdu_peerinfo *peer_pi) 2001 { 2002 int timeout; 2003 2004 KASSERT(LACP_LOCKED(lsc)); 2005 2006 /* check LACP disabled first */ 2007 if (!ISSET(lacpp->lp_actor.lpi_state, LACP_STATE_AGGREGATION)) 2008 return; 2009 2010 /* check loopback condition */ 2011 if (memcmp(lsc->lsc_system_mac, peer_pi->lpi_system_mac, 2012 LACP_MAC_LEN) == 0 && 2013 lsc->lsc_system_prio == peer_pi->lpi_system_prio) 2014 return; 2015 2016 lacp_sm_rx_update_selected(lsc, lacpp, peer_pi); 2017 lacp_sm_rx_update_ntt(lsc, lacpp, my_pi); 2018 lacp_sm_rx_record_peerinfo(lsc, lacpp, my_pi, peer_pi); 2019 2020 timeout = ISSET(lacpp->lp_actor.lpi_state, LACP_STATE_TIMEOUT) ? 2021 LACP_SHORT_TIMEOUT_TIME : LACP_LONG_TIMEOUT_TIME; 2022 LACP_TIMER_ARM(lacpp, LACP_TIMER_CURRENT_WHILE, timeout); 2023 2024 CLR(lacpp->lp_actor.lpi_state, LACP_STATE_EXPIRED); 2025 2026 /* kick transmit machine without timeout. */ 2027 lacp_sm_tx(lsc, lacpp); 2028 } 2029 2030 static void 2031 lacp_disable_collecting(struct lacp_port *lacpp) 2032 { 2033 2034 LACP_DPRINTF((NULL, lacpp, "collecting disabled\n")); 2035 CLR(lacpp->lp_actor.lpi_state, LACP_STATE_COLLECTING); 2036 atomic_store_relaxed(&lacpp->lp_collector, false); 2037 } 2038 2039 static void 2040 lacp_enable_collecting(struct lacp_port *lacpp) 2041 { 2042 LACP_DPRINTF((NULL, lacpp, "collecting enabled\n")); 2043 SET(lacpp->lp_actor.lpi_state, LACP_STATE_COLLECTING); 2044 atomic_store_relaxed(&lacpp->lp_collector, true); 2045 } 2046 2047 static void 2048 lacp_update_portmap(struct lacp_softc *lsc) 2049 { 2050 struct lagg_softc *sc; 2051 struct lacp_aggregator *la; 2052 struct lacp_portmap *pm_act, *pm_next; 2053 struct lacp_port *lacpp; 2054 size_t pmap, n; 2055 u_int link; 2056 2057 KASSERT(LACP_LOCKED(lsc)); 2058 2059 la = lsc->lsc_aggregator; 2060 2061 pmap = LACP_PORTMAP_ACTIVE(lsc); 2062 pm_act = &lsc->lsc_portmaps[pmap]; 2063 2064 pmap = LACP_PORTMAP_NEXT(lsc); 2065 pm_next = &lsc->lsc_portmaps[pmap]; 2066 2067 n = 0; 2068 if (la != NULL) { 2069 LIST_FOREACH(lacpp, &la->la_ports, lp_entry_la) { 2070 if (!ISSET(lacpp->lp_actor.lpi_state, 2071 LACP_STATE_DISTRIBUTING)) { 2072 continue; 2073 } 2074 2075 pm_next->pm_ports[n] = lacpp->lp_laggport; 2076 n++; 2077 2078 if (n >= LACP_MAX_PORTS) 2079 break; 2080 } 2081 } 2082 pm_next->pm_count = n; 2083 2084 atomic_store_release(&lsc->lsc_activemap, pmap); 2085 pserialize_perform(lsc->lsc_psz); 2086 2087 LACP_DPRINTF((lsc, NULL, "portmap count updated (%zu -> %zu)\n", 2088 pm_act->pm_count, pm_next->pm_count)); 2089 2090 link = lacp_portmap_linkstate(pm_next); 2091 if (link != lacp_portmap_linkstate(pm_act)) { 2092 sc = lsc->lsc_softc; 2093 if_link_state_change(&sc->sc_if, link); 2094 } 2095 2096 lagg_workq_add(lsc->lsc_workq, &lsc->lsc_work_linkspeed); 2097 2098 /* cleanup */ 2099 pm_act->pm_count = 0; 2100 memset(pm_act->pm_ports, 0, sizeof(pm_act->pm_ports)); 2101 } 2102 2103 static void 2104 lacp_disable_distributing(struct lacp_softc *lsc, struct lacp_port *lacpp) 2105 { 2106 struct lacp_portmap *pm; 2107 bool do_update; 2108 size_t act, i; 2109 int s; 2110 2111 KASSERT(LACP_LOCKED(lsc)); 2112 2113 if (ISSET(lacpp->lp_actor.lpi_state, LACP_STATE_DISTRIBUTING)) { 2114 LAGG_LOG(lsc->lsc_softc, LOG_INFO, 2115 "disable distributing on %s\n", LACP_PORT_XNAME(lacpp)); 2116 CLR(lacpp->lp_actor.lpi_state, LACP_STATE_DISTRIBUTING); 2117 } 2118 2119 s = pserialize_read_enter(); 2120 act = LACP_PORTMAP_ACTIVE(lsc); 2121 pm = &lsc->lsc_portmaps[act]; 2122 2123 do_update = false; 2124 for (i = 0; i < pm->pm_count; i++) { 2125 if (pm->pm_ports[i] == lacpp->lp_laggport) { 2126 do_update = true; 2127 break; 2128 } 2129 } 2130 pserialize_read_exit(s); 2131 2132 if (do_update) 2133 lacp_update_portmap(lsc); 2134 } 2135 2136 static void 2137 lacp_enable_distributing(struct lacp_softc *lsc, struct lacp_port *lacpp) 2138 { 2139 2140 KASSERT(LACP_LOCKED(lsc)); 2141 2142 KASSERT(lacp_isactive(lsc, lacpp)); 2143 2144 LAGG_LOG(lsc->lsc_softc, LOG_INFO, 2145 "enable distributing on %s\n", LACP_PORT_XNAME(lacpp)); 2146 SET(lacpp->lp_actor.lpi_state, LACP_STATE_DISTRIBUTING); 2147 lacp_suppress_distributing(lsc); 2148 lacp_update_portmap(lsc); 2149 } 2150 2151 static void 2152 lacp_select_active_aggregator(struct lacp_softc *lsc) 2153 { 2154 struct lacp_aggregator *la, *best_la; 2155 char str[LACP_SYSTEMIDSTR_LEN] __LACPDEBUGUSED; 2156 2157 KASSERT(LACP_LOCKED(lsc)); 2158 2159 la = lsc->lsc_aggregator; 2160 if (la != NULL && la->la_attached_port > 0) { 2161 best_la = la; 2162 } else { 2163 best_la = NULL; 2164 } 2165 2166 TAILQ_FOREACH(la, &lsc->lsc_aggregators, la_q) { 2167 if (la->la_attached_port <= 0) 2168 continue; 2169 2170 if (best_la == NULL || 2171 LACP_SYS_PRI(la) < LACP_SYS_PRI(best_la)) 2172 best_la = la; 2173 } 2174 2175 if (best_la != lsc->lsc_aggregator) { 2176 LACP_DPRINTF((lsc, NULL, "active aggregator changed\n")); 2177 2178 if (lsc->lsc_aggregator != NULL) { 2179 LACP_AGGREGATOR_STR(lsc->lsc_aggregator, 2180 str, sizeof(str)); 2181 } else { 2182 snprintf(str, sizeof(str), "(null)"); 2183 } 2184 LACP_DPRINTF((lsc, NULL, "old aggregator=%s\n", str)); 2185 2186 if (best_la != NULL) { 2187 LACP_AGGREGATOR_STR(best_la, str, sizeof(str)); 2188 } else { 2189 snprintf(str, sizeof(str), "(null)"); 2190 } 2191 LACP_DPRINTF((lsc, NULL, "new aggregator=%s\n", str)); 2192 2193 lsc->lsc_aggregator = best_la; 2194 } 2195 } 2196 2197 static void 2198 lacp_port_attached(struct lacp_softc *lsc, struct lacp_port *lacpp) 2199 { 2200 struct lacp_aggregator *la; 2201 2202 KASSERT(LACP_LOCKED(lsc)); 2203 2204 if (ISSET(lacpp->lp_actor.lpi_state, LACP_STATE_SYNC)) 2205 return; 2206 2207 la = lacpp->lp_aggregator; 2208 KASSERT(la != NULL); 2209 KASSERT(la->la_attached_port >= 0); 2210 2211 SET(lacpp->lp_actor.lpi_state, LACP_STATE_SYNC); 2212 la->la_attached_port++; 2213 lacp_select_active_aggregator(lsc); 2214 } 2215 2216 static void 2217 lacp_port_detached(struct lacp_softc *lsc, struct lacp_port *lacpp) 2218 { 2219 struct lacp_aggregator *la; 2220 2221 KASSERT(LACP_LOCKED(lsc)); 2222 2223 if (!ISSET(lacpp->lp_actor.lpi_state, LACP_STATE_SYNC)) 2224 return; 2225 2226 la = lacpp->lp_aggregator; 2227 KASSERT(la != NULL); 2228 KASSERT(la->la_attached_port > 0); 2229 2230 CLR(lacpp->lp_actor.lpi_state, LACP_STATE_SYNC); 2231 la->la_attached_port--; 2232 lacp_select_active_aggregator(lsc); 2233 } 2234 2235 static int 2236 lacp_set_mux(struct lacp_softc *lsc, struct lacp_port *lacpp, 2237 enum lacp_mux_state new_state) 2238 { 2239 struct lagg_softc *sc; 2240 struct ifnet *ifp; 2241 2242 KASSERT(LACP_LOCKED(lsc)); 2243 2244 sc = lacpp->lp_laggport->lp_softc; 2245 ifp = &sc->sc_if; 2246 2247 if (lacpp->lp_mux_state == new_state) 2248 return -1; 2249 2250 switch (new_state) { 2251 case LACP_MUX_DETACHED: 2252 lacp_port_detached(lsc, lacpp); 2253 lacp_disable_distributing(lsc, lacpp); 2254 lacp_disable_collecting(lacpp); 2255 lacp_sm_assert_ntt(lacpp); 2256 /* cancel timer */ 2257 if (LACP_TIMER_ISARMED(lacpp, LACP_TIMER_WAIT_WHILE)) { 2258 KASSERT(lacpp->lp_pending > 0); 2259 lacpp->lp_pending--; 2260 LACP_TIMER_DISARM(lacpp, LACP_TIMER_WAIT_WHILE); 2261 } 2262 lacp_unselect(lsc, lacpp); 2263 break; 2264 case LACP_MUX_WAITING: 2265 LACP_TIMER_ARM(lacpp, LACP_TIMER_WAIT_WHILE, 2266 LACP_AGGREGATE_WAIT_TIME); 2267 lacpp->lp_pending++; 2268 break; 2269 case LACP_MUX_STANDBY: 2270 #ifdef LACP_STANDBY_SYNCED 2271 lacp_port_attached(lsc, lacpp); 2272 lacp_disable_collecting(lacpp); 2273 lacp_sm_assert_ntt(lacpp); 2274 #endif 2275 break; 2276 case LACP_MUX_ATTACHED: 2277 lacp_port_attached(lsc, lacpp); 2278 lacp_disable_collecting(lacpp); 2279 lacp_sm_assert_ntt(lacpp); 2280 break; 2281 case LACP_MUX_COLLECTING: 2282 lacp_enable_collecting(lacpp); 2283 lacp_disable_distributing(lsc, lacpp); 2284 lacp_sm_assert_ntt(lacpp); 2285 break; 2286 case LACP_MUX_DISTRIBUTING: 2287 lacp_enable_distributing(lsc, lacpp); 2288 break; 2289 case LACP_MUX_INIT: 2290 default: 2291 panic("%s: unknown state", ifp->if_xname); 2292 } 2293 2294 LACP_DPRINTF((lsc, lacpp, "mux_state %d -> %d\n", 2295 lacpp->lp_mux_state, new_state)); 2296 2297 lacpp->lp_mux_state = new_state; 2298 return 0; 2299 } 2300 2301 static void 2302 lacp_sm_mux(struct lacp_softc *lsc, struct lacp_port *lacpp) 2303 { 2304 struct lacp_aggregator *la __diagused; 2305 enum lacp_mux_state next_state; 2306 enum lacp_selected selected; 2307 bool p_sync, p_collecting; 2308 2309 p_sync = ISSET(lacpp->lp_partner.lpi_state, LACP_STATE_SYNC); 2310 p_collecting = ISSET(lacpp->lp_partner.lpi_state, 2311 LACP_STATE_COLLECTING); 2312 2313 do { 2314 next_state = lacpp->lp_mux_state; 2315 la = lacpp->lp_aggregator; 2316 selected = lacpp->lp_selected; 2317 KASSERT(la != NULL || 2318 lacpp->lp_mux_state == LACP_MUX_DETACHED); 2319 2320 switch (lacpp->lp_mux_state) { 2321 case LACP_MUX_DETACHED: 2322 if (selected != LACP_UNSELECTED) 2323 next_state = LACP_MUX_WAITING; 2324 break; 2325 case LACP_MUX_WAITING: 2326 KASSERTMSG((lacpp->lp_pending > 0 || 2327 !LACP_TIMER_ISARMED(lacpp, LACP_TIMER_WAIT_WHILE)), 2328 "lp_pending=%d, timer=%d", lacpp->lp_pending, 2329 !LACP_TIMER_ISARMED(lacpp, LACP_TIMER_WAIT_WHILE)); 2330 2331 if (selected == LACP_UNSELECTED) { 2332 next_state = LACP_MUX_DETACHED; 2333 } else if (lacpp->lp_pending == 0) { 2334 if (selected == LACP_SELECTED) { 2335 next_state = LACP_MUX_ATTACHED; 2336 } else if (selected == LACP_STANDBY) { 2337 next_state = LACP_MUX_STANDBY; 2338 } else { 2339 next_state = LACP_MUX_DETACHED; 2340 } 2341 } 2342 break; 2343 case LACP_MUX_STANDBY: 2344 if (selected == LACP_SELECTED) { 2345 next_state = LACP_MUX_ATTACHED; 2346 } else if (selected != LACP_STANDBY) { 2347 next_state = LACP_MUX_DETACHED; 2348 } 2349 break; 2350 case LACP_MUX_ATTACHED: 2351 if (selected != LACP_SELECTED) { 2352 if (selected == LACP_STANDBY) 2353 LAGG_LOG(lsc->lsc_softc, LOG_INFO, 2354 "detaching %s\n", 2355 LACP_PORT_XNAME(lacpp)); 2356 next_state = LACP_MUX_DETACHED; 2357 } else if (lacp_isactive(lsc, lacpp) && p_sync) { 2358 next_state = LACP_MUX_COLLECTING; 2359 } 2360 break; 2361 case LACP_MUX_COLLECTING: 2362 if (selected != LACP_SELECTED || 2363 !lacp_isactive(lsc, lacpp) 2364 || !p_sync) { 2365 next_state = LACP_MUX_ATTACHED; 2366 } else if (p_collecting) { 2367 next_state = LACP_MUX_DISTRIBUTING; 2368 } 2369 break; 2370 case LACP_MUX_DISTRIBUTING: 2371 if (selected != LACP_SELECTED || 2372 !lacp_isactive(lsc, lacpp) 2373 || !p_sync || !p_collecting) { 2374 next_state = LACP_MUX_COLLECTING; 2375 LACP_DPRINTF((lsc, lacpp, 2376 "Interface stopped DISTRIBUTING," 2377 " possible flapping\n")); 2378 } 2379 break; 2380 case LACP_MUX_INIT: 2381 default: 2382 panic("%s: unknown state", 2383 lsc->lsc_softc->sc_if.if_xname); 2384 } 2385 } while (lacp_set_mux(lsc, lacpp, next_state) == 0); 2386 } 2387 2388 static bool 2389 lacp_aggregator_is_match(struct lacp_aggregator_systemid *a, 2390 struct lacp_aggregator_systemid *b) 2391 { 2392 2393 if (a->sid_prio != b->sid_prio) 2394 return false; 2395 2396 if (a->sid_key != b->sid_key) 2397 return false; 2398 2399 if (memcmp(a->sid_mac, b->sid_mac, sizeof(a->sid_mac)) != 0) 2400 return false; 2401 2402 return true; 2403 } 2404 2405 static void 2406 lacp_selected_update(struct lacp_softc *lsc, struct lacp_aggregator *la) 2407 { 2408 struct lacp_port *lacpp; 2409 enum lacp_selected next_selected; 2410 const char *msg; 2411 size_t nselected; 2412 uint64_t linkspeed; 2413 2414 KASSERT(LACP_LOCKED(lsc)); 2415 2416 lacpp = LIST_FIRST(&la->la_ports); 2417 if (lacpp == NULL) 2418 return; 2419 2420 linkspeed = lacpp->lp_linkspeed; 2421 nselected = 0; 2422 LIST_FOREACH(lacpp, &la->la_ports, lp_entry_la) { 2423 if (lacpp->lp_selected == LACP_UNSELECTED) 2424 continue; 2425 2426 next_selected = LACP_SELECTED; 2427 msg = " is selected"; 2428 2429 if (nselected >= lsc->lsc_max_ports) { 2430 next_selected = LACP_STANDBY; 2431 msg = " is standby because of too many active ports"; 2432 } 2433 2434 if (!lsc->lsc_multi_linkspeed && 2435 linkspeed != lacpp->lp_linkspeed) { 2436 next_selected = LACP_STANDBY; 2437 msg = " is standby because of link speed mismatch"; 2438 } 2439 2440 if (lacpp->lp_selected != next_selected) { 2441 lacpp->lp_selected = next_selected; 2442 LAGG_LOG(lsc->lsc_softc, LOG_INFO, 2443 "%s%s\n", LACP_PORT_XNAME(lacpp), msg); 2444 } 2445 2446 if (lacpp->lp_selected == LACP_SELECTED) 2447 nselected++; 2448 } 2449 } 2450 2451 static void 2452 lacp_select(struct lacp_softc *lsc, struct lacp_port *lacpp) 2453 { 2454 struct lacp_aggregator *la; 2455 struct lacp_aggregator_systemid *sid; 2456 struct lacp_port *lacpp0; 2457 char buf[LACP_SYSTEMIDSTR_LEN] __LACPDEBUGUSED; 2458 2459 if (lacpp->lp_aggregator != NULL) 2460 return; 2461 2462 /* If we haven't heard from our peer, skip this step. */ 2463 if (ISSET(lacpp->lp_actor.lpi_state, LACP_STATE_DEFAULTED)) 2464 return 2465 2466 KASSERT(!LACP_TIMER_ISARMED(lacpp, LACP_TIMER_WAIT_WHILE)); 2467 2468 sid = &lacpp->lp_aggregator_sidbuf; 2469 2470 TAILQ_FOREACH(la, &lsc->lsc_aggregators, la_q) { 2471 if (lacp_aggregator_is_match(&la->la_sid, sid)) 2472 break; 2473 } 2474 2475 if (la == NULL) { 2476 la = kmem_zalloc(sizeof(*la), KM_NOSLEEP); 2477 if (la == NULL) { 2478 LACP_DPRINTF((lsc, lacpp, 2479 "couldn't allocate aggregator\n")); 2480 /* will retry the next tick. */ 2481 return; 2482 } 2483 LIST_INIT(&la->la_ports); 2484 2485 la->la_sid = *sid; 2486 TAILQ_INSERT_TAIL(&lsc->lsc_aggregators, la, la_q); 2487 LACP_DPRINTF((lsc, lacpp, "a new aggregator created\n")); 2488 } else { 2489 LACP_DPRINTF((lsc, lacpp, "aggregator found\n")); 2490 } 2491 2492 KASSERT(la != NULL); 2493 LACP_AGGREGATOR_STR(la, buf, sizeof(buf)); 2494 LACP_DPRINTF((lsc, lacpp, "aggregator lagid=%s\n", buf)); 2495 2496 lacpp->lp_aggregator = la; 2497 lacpp->lp_selected = LACP_READY; 2498 2499 LIST_FOREACH(lacpp0, &la->la_ports, lp_entry_la) { 2500 if (lacp_port_priority_max(lacpp0, lacpp) == lacpp) { 2501 LIST_INSERT_BEFORE(lacpp0, lacpp, lp_entry_la); 2502 break; 2503 } 2504 2505 if (LIST_NEXT(lacpp0, lp_entry_la) == NULL) { 2506 LIST_INSERT_AFTER(lacpp0, lacpp, lp_entry_la); 2507 break; 2508 } 2509 } 2510 2511 if (lacpp0 == NULL) 2512 LIST_INSERT_HEAD(&la->la_ports, lacpp, lp_entry_la); 2513 2514 lacp_selected_update(lsc, la); 2515 } 2516 2517 static void 2518 lacp_unselect(struct lacp_softc *lsc, struct lacp_port *lacpp) 2519 { 2520 struct lacp_aggregator *la; 2521 char buf[LACP_SYSTEMIDSTR_LEN] __LACPDEBUGUSED; 2522 bool remove_actaggr; 2523 2524 KASSERT(LACP_LOCKED(lsc)); 2525 KASSERT(!LACP_TIMER_ISARMED(lacpp, LACP_TIMER_WAIT_WHILE)); 2526 2527 la = lacpp->lp_aggregator; 2528 lacpp->lp_selected = LACP_UNSELECTED; 2529 2530 if (la == NULL) 2531 return; 2532 2533 KASSERT(!LIST_EMPTY(&la->la_ports)); 2534 2535 LACP_AGGREGATOR_STR(la, buf, sizeof(buf)); 2536 LACP_DPRINTF((lsc, lacpp, "unselect aggregator lagid=%s\n", buf)); 2537 2538 LIST_REMOVE(lacpp, lp_entry_la); 2539 lacpp->lp_aggregator = NULL; 2540 2541 if (LIST_EMPTY(&la->la_ports)) { 2542 remove_actaggr = false; 2543 2544 if (la == lsc->lsc_aggregator) { 2545 LACP_DPRINTF((lsc, NULL, "remove active aggregator\n")); 2546 lsc->lsc_aggregator = NULL; 2547 remove_actaggr = true; 2548 } 2549 2550 TAILQ_REMOVE(&lsc->lsc_aggregators, la, la_q); 2551 kmem_free(la, sizeof(*la)); 2552 2553 if (remove_actaggr) 2554 lacp_select_active_aggregator(lsc); 2555 } else { 2556 lacp_selected_update(lsc, la); 2557 } 2558 } 2559 2560 static void 2561 lacp_suppress_distributing(struct lacp_softc *lsc) 2562 { 2563 struct lacp_aggregator *la; 2564 struct lacp_port *lacpp; 2565 bool marker_scheduled; 2566 2567 KASSERT(LACP_LOCKED(lsc)); 2568 2569 la = lsc->lsc_aggregator; 2570 marker_scheduled = false; 2571 2572 LIST_FOREACH(lacpp, &la->la_ports, lp_entry_la) { 2573 if (ISSET(lacpp->lp_actor.lpi_state, 2574 LACP_STATE_DISTRIBUTING)) { 2575 lagg_workq_add(lsc->lsc_workq, 2576 &lacpp->lp_work_marker); 2577 marker_scheduled = true; 2578 } 2579 } 2580 2581 lsc->lsc_suppress_distributing = marker_scheduled; 2582 LACP_PTIMER_ARM(lsc, LACP_PTIMER_DISTRIBUTING, 2583 LACP_TRANSIT_DELAY); 2584 } 2585 2586 static void 2587 lacp_distributing_timer(struct lacp_softc *lsc) 2588 { 2589 2590 KASSERT(LACP_LOCKED(lsc)); 2591 2592 if (lsc->lsc_suppress_distributing) { 2593 LACP_DPRINTF((lsc, NULL, 2594 "disable suppress distributing\n")); 2595 lsc->lsc_suppress_distributing = false; 2596 } 2597 } 2598 2599 static struct mbuf * 2600 lacp_markerdu_mbuf(struct lacp_softc *lsc, struct lacp_port *lacpp) 2601 { 2602 struct ifnet *ifp_port; 2603 struct mbuf *m; 2604 struct markerdu *mdu; 2605 struct markerdu_info *mi; 2606 2607 KASSERT(LACP_LOCKED(lsc)); 2608 2609 ifp_port = lacpp->lp_laggport->lp_ifp; 2610 2611 MGETHDR(m, M_DONTWAIT, MT_DATA); 2612 if (m == NULL) { 2613 lsc->lsc_mgethdr_failed.ev_count++; 2614 return NULL; 2615 } 2616 2617 m->m_pkthdr.len = m->m_len = sizeof(*mdu); 2618 m_reset_rcvif(m); 2619 2620 mdu = mtod(m, struct markerdu *); 2621 2622 memset(mdu, 0, sizeof(*mdu)); 2623 2624 m->m_flags |= M_MCAST; 2625 memcpy(mdu->mdu_eh.ether_dhost, ethermulticastaddr_slowprotocols, 2626 ETHER_ADDR_LEN); 2627 memcpy(mdu->mdu_eh.ether_shost, CLLADDR(ifp_port->if_sadl), 2628 ETHER_ADDR_LEN); 2629 mdu->mdu_eh.ether_type = ntohs(ETHERTYPE_SLOWPROTOCOLS); 2630 mdu->mdu_sph.sph_subtype = SLOWPROTOCOLS_SUBTYPE_MARKER; 2631 mdu->mdu_sph.sph_version = 1; 2632 2633 mi = &mdu->mdu_info; 2634 tlv_set(&mdu->mdu_tlv_info, MARKER_TYPE_INFO, 2635 sizeof(*mi)); 2636 mi->mi_rq_port = lacpp->lp_actor.lpi_portno; 2637 mi->mi_rq_xid = htonl(lacpp->lp_marker_xid); 2638 memcpy(mi->mi_rq_system, lsc->lsc_system_mac, LACP_MAC_LEN); 2639 2640 mdu->mdu_tlv_term.tlv_type = MARKER_TYPE_TERMINATE; 2641 mdu->mdu_tlv_term.tlv_length = 0; 2642 2643 return m; 2644 } 2645 2646 static void 2647 lacp_marker_work(struct lagg_work *lw, void *xlsc) 2648 { 2649 struct lacp_softc *lsc; 2650 struct lacp_port *lacpp; 2651 struct lagg_port *lp; 2652 struct markerdu *mdu; 2653 struct mbuf *m; 2654 struct psref psref; 2655 int bound; 2656 2657 lsc = xlsc; 2658 lacpp = container_of(lw, struct lacp_port, lp_work_marker); 2659 2660 LACP_LOCK(lsc); 2661 lacpp->lp_marker_xid++; 2662 m = lacp_markerdu_mbuf(lsc, lacpp); 2663 if (m == NULL) { 2664 LACP_UNLOCK(lsc); 2665 return; 2666 } 2667 SET(lacpp->lp_flags, LACP_PORT_MARK); 2668 lp = lacpp->lp_laggport; 2669 bound = curlwp_bind(); 2670 lagg_port_getref(lp, &psref); 2671 LACP_UNLOCK(lsc); 2672 2673 if (LACP_ISDUMPING(lsc)) { 2674 lacp_dprintf(lsc, lacpp, "markerdu transmit\n"); 2675 mdu = mtod(m, struct markerdu *); 2676 lacp_dump_markertlv(&mdu->mdu_info, NULL); 2677 } 2678 2679 lagg_port_xmit(lp, m); 2680 lagg_port_putref(lp, &psref); 2681 curlwp_bindx(bound); 2682 } 2683 2684 static void 2685 lacp_dump_lacpdutlv(const struct lacpdu_peerinfo *pi_actor, 2686 const struct lacpdu_peerinfo *pi_partner, 2687 const struct lacpdu_collectorinfo *lci) 2688 { 2689 char str[LACP_STATESTR_LEN]; 2690 2691 if (pi_actor != NULL) { 2692 lacp_peerinfo_idstr(pi_actor, str, sizeof(str)); 2693 printf("actor=%s\n", str); 2694 lacp_state_str(pi_actor->lpi_state, 2695 str, sizeof(str)); 2696 printf("actor.state=%s portno=%d portprio=0x%04x\n", 2697 str, 2698 ntohs(pi_actor->lpi_port_no), 2699 ntohs(pi_actor->lpi_port_prio)); 2700 } else { 2701 printf("no actor info\n"); 2702 } 2703 2704 if (pi_partner != NULL) { 2705 lacp_peerinfo_idstr(pi_partner, str, sizeof(str)); 2706 printf("partner=%s\n", str); 2707 lacp_state_str(pi_partner->lpi_state, 2708 str, sizeof(str)); 2709 printf("partner.state=%s portno=%d portprio=0x%04x\n", 2710 str, 2711 ntohs(pi_partner->lpi_port_no), 2712 ntohs(pi_partner->lpi_port_prio)); 2713 } else { 2714 printf("no partner info\n"); 2715 } 2716 2717 if (lci != NULL) { 2718 printf("maxdelay=%d\n", ntohs(lci->lci_maxdelay)); 2719 } else { 2720 printf("no collector info\n"); 2721 } 2722 } 2723 2724 static void 2725 lacp_dump_markertlv(const struct markerdu_info *mi_info, 2726 const struct markerdu_info *mi_res) 2727 { 2728 2729 if (mi_info != NULL) { 2730 printf("marker info: port=%d, sys=%s, id=%u\n", 2731 ntohs(mi_info->mi_rq_port), 2732 ether_sprintf(mi_info->mi_rq_system), 2733 ntohl(mi_info->mi_rq_xid)); 2734 } 2735 2736 if (mi_res != NULL) { 2737 printf("marker resp: port=%d, sys=%s, id=%u\n", 2738 ntohs(mi_res->mi_rq_port), 2739 ether_sprintf(mi_res->mi_rq_system), 2740 ntohl(mi_res->mi_rq_xid)); 2741 } 2742 } 2743 2744 /* 2745 * lacp_linkstate: 2746 * callback on link state changed. 2747 * enable, disable or reset LACP processing on the physical port. 2748 */ 2749 2750 static void 2751 lacp_linkstate(struct lagg_proto_softc *xlsc, struct lagg_port *lp) 2752 { 2753 2754 IFNET_ASSERT_UNLOCKED(lp->lp_ifp); 2755 2756 IFNET_LOCK(lp->lp_ifp); 2757 lacp_linkstate_ifnet_locked(xlsc, lp); 2758 IFNET_UNLOCK(lp->lp_ifp); 2759 } 2760 2761 static void 2762 lacp_linkspeed_work(struct lagg_work *lw __unused, void *xlsc) 2763 { 2764 struct lacp_softc *lsc = (struct lacp_softc *)xlsc; 2765 struct lagg_softc *sc = lsc->lsc_softc; 2766 struct lacp_portmap *pm; 2767 struct lagg_port *lp; 2768 struct lacp_port *lacpp; 2769 uint64_t linkspeed; 2770 size_t act, i; 2771 2772 linkspeed = 0; 2773 2774 LACP_LOCK(lsc); 2775 act = LACP_PORTMAP_ACTIVE(lsc); 2776 pm = &lsc->lsc_portmaps[act]; 2777 for (i = 0; i < pm->pm_count; i++) { 2778 lp = pm->pm_ports[i]; 2779 lacpp = lp->lp_proto_ctx; 2780 linkspeed = MAX(linkspeed, lacpp->lp_linkspeed); 2781 } 2782 LACP_UNLOCK(lsc); 2783 2784 LAGG_LOCK(sc); 2785 lagg_set_linkspeed(sc, linkspeed); 2786 LAGG_UNLOCK(sc); 2787 } 2788