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