1 /* $NetBSD: if_lagg.c,v 1.74 2025/07/30 02:16:54 ozaki-r Exp $ */ 2 3 /* 4 * Copyright (c) 2005, 2006 Reyk Floeter <reyk (at) openbsd.org> 5 * Copyright (c) 2007 Andrew Thompson <thompsa (at) FreeBSD.org> 6 * Copyright (c) 2014, 2016 Marcelo Araujo <araujo (at) FreeBSD.org> 7 * Copyright (c) 2021, Internet Initiative Japan Inc. 8 * 9 * Permission to use, copy, modify, and distribute this software for any 10 * purpose with or without fee is hereby granted, provided that the above 11 * copyright notice and this permission notice appear in all copies. 12 * 13 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 19 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 20 */ 21 22 #include <sys/cdefs.h> 23 __KERNEL_RCSID(0, "$NetBSD: if_lagg.c,v 1.74 2025/07/30 02:16:54 ozaki-r Exp $"); 24 25 #ifdef _KERNEL_OPT 26 #include "opt_inet.h" 27 #include "opt_lagg.h" 28 #endif 29 30 #include <sys/param.h> 31 #include <sys/types.h> 32 33 #include <sys/cprng.h> 34 #include <sys/cpu.h> 35 #include <sys/device.h> 36 #include <sys/evcnt.h> 37 #include <sys/hash.h> 38 #include <sys/kmem.h> 39 #include <sys/module.h> 40 #include <sys/pserialize.h> 41 #include <sys/pslist.h> 42 #include <sys/psref.h> 43 #include <sys/sysctl.h> 44 #include <sys/syslog.h> 45 #include <sys/workqueue.h> 46 47 #include <net/bpf.h> 48 #include <net/if.h> 49 #include <net/if_dl.h> 50 #include <net/if_ether.h> 51 #include <net/if_media.h> 52 #include <net/if_types.h> 53 #include <net/if_vlanvar.h> 54 #include <netinet/ip.h> 55 #include <netinet/ip6.h> 56 #include <netinet/tcp.h> 57 #include <netinet/udp.h> 58 59 #if defined(INET) || defined(INET6) 60 #include <netinet/in.h> 61 #endif 62 63 #ifdef INET6 64 #include <netinet6/in6_ifattach.h> 65 #include <netinet6/in6_var.h> 66 #endif 67 68 #include <net/lagg/if_lagg.h> 69 #include <net/lagg/if_laggproto.h> 70 71 #include "ioconf.h" 72 73 enum lagg_portctrl { 74 LAGG_PORTCTRL_ALLOC, 75 LAGG_PORTCTRL_FREE, 76 LAGG_PORTCTRL_START, 77 LAGG_PORTCTRL_STOP 78 }; 79 80 enum lagg_iftypes { 81 LAGG_IF_TYPE_ETHERNET, 82 }; 83 84 static const struct lagg_proto lagg_protos[] = { 85 [LAGG_PROTO_NONE] = { 86 .pr_num = LAGG_PROTO_NONE, 87 .pr_attach = lagg_none_attach, 88 }, 89 [LAGG_PROTO_LACP] = { 90 .pr_num = LAGG_PROTO_LACP, 91 .pr_attach = lacp_attach, 92 .pr_detach = lacp_detach, 93 .pr_up = lacp_up, 94 .pr_down = lacp_down, 95 .pr_transmit = lacp_transmit, 96 .pr_input = lacp_input, 97 .pr_allocport = lacp_allocport, 98 .pr_freeport = lacp_freeport, 99 .pr_startport = lacp_startport, 100 .pr_stopport = lacp_stopport, 101 .pr_protostat = lacp_protostat, 102 .pr_portstat = lacp_portstat, 103 .pr_linkstate = lacp_linkstate_ifnet_locked, 104 .pr_ioctl = lacp_ioctl, 105 }, 106 [LAGG_PROTO_FAILOVER] = { 107 .pr_num = LAGG_PROTO_FAILOVER, 108 .pr_attach = lagg_fail_attach, 109 .pr_detach = lagg_common_detach, 110 .pr_transmit = lagg_fail_transmit, 111 .pr_input = lagg_fail_input, 112 .pr_allocport = lagg_common_allocport, 113 .pr_freeport = lagg_common_freeport, 114 .pr_startport = lagg_common_startport, 115 .pr_stopport = lagg_common_stopport, 116 .pr_portstat = lagg_fail_portstat, 117 .pr_linkstate = lagg_common_linkstate_ifnet_locked, 118 .pr_ioctl = lagg_fail_ioctl, 119 }, 120 [LAGG_PROTO_LOADBALANCE] = { 121 .pr_num = LAGG_PROTO_LOADBALANCE, 122 .pr_attach = lagg_lb_attach, 123 .pr_detach = lagg_common_detach, 124 .pr_transmit = lagg_lb_transmit, 125 .pr_input = lagg_lb_input, 126 .pr_allocport = lagg_common_allocport, 127 .pr_freeport = lagg_common_freeport, 128 .pr_startport = lagg_lb_startport, 129 .pr_stopport = lagg_lb_stopport, 130 .pr_portstat = lagg_lb_portstat, 131 .pr_linkstate = lagg_common_linkstate_ifnet_locked, 132 }, 133 }; 134 135 static int lagg_chg_sadl(struct ifnet *, const uint8_t *, size_t); 136 static void lagg_input_ethernet(struct ifnet *, struct mbuf *); 137 static int lagg_clone_create(struct if_clone *, int); 138 static int lagg_clone_destroy(struct ifnet *); 139 static int lagg_init(struct ifnet *); 140 static int lagg_init_locked(struct lagg_softc *); 141 static void lagg_stop(struct ifnet *, int); 142 static void lagg_stop_locked(struct lagg_softc *); 143 static int lagg_ioctl(struct ifnet *, u_long, void *); 144 static int lagg_transmit(struct ifnet *, struct mbuf *); 145 static void lagg_start(struct ifnet *); 146 static int lagg_media_change(struct ifnet *); 147 static void lagg_media_status(struct ifnet *, struct ifmediareq *); 148 static int lagg_vlan_cb(struct ethercom *, uint16_t, bool); 149 static void lagg_linkstate_changed(void *); 150 static void lagg_ifdetach(void *); 151 static struct lagg_softc * 152 lagg_softc_alloc(enum lagg_iftypes); 153 static void lagg_softc_free(struct lagg_softc *); 154 static int lagg_setup_sysctls(struct lagg_softc *); 155 static void lagg_teardown_sysctls(struct lagg_softc *); 156 static int lagg_proto_attach(struct lagg_softc *, lagg_proto, 157 struct lagg_proto_softc **); 158 static void lagg_proto_detach(struct lagg_variant *); 159 static int lagg_proto_up(struct lagg_softc *); 160 static void lagg_proto_down(struct lagg_softc *); 161 static int lagg_proto_allocport(struct lagg_softc *, struct lagg_port *); 162 static void lagg_proto_freeport(struct lagg_softc *, struct lagg_port *); 163 static void lagg_proto_startport(struct lagg_softc *, 164 struct lagg_port *); 165 static void lagg_proto_stopport(struct lagg_softc *, 166 struct lagg_port *); 167 static struct mbuf * 168 lagg_proto_input(struct lagg_softc *, struct lagg_port *, 169 struct mbuf *); 170 static void lagg_proto_linkstate(struct lagg_softc *, struct lagg_port *); 171 static int lagg_proto_ioctl(struct lagg_softc *, struct lagg_req *); 172 static int lagg_get_stats(struct lagg_softc *, struct lagg_req *, size_t); 173 static int lagg_pr_attach(struct lagg_softc *, lagg_proto); 174 static void lagg_pr_detach(struct lagg_softc *); 175 static int lagg_addport(struct lagg_softc *, struct ifnet *); 176 static int lagg_delport(struct lagg_softc *, struct ifnet *); 177 static int lagg_delport_all(struct lagg_softc *); 178 static int lagg_port_ioctl(struct ifnet *, u_long, void *); 179 static int lagg_port_output(struct ifnet *, struct mbuf *, 180 const struct sockaddr *, const struct rtentry *); 181 static void lagg_config_promisc(struct lagg_softc *, struct lagg_port *); 182 static void lagg_unconfig_promisc(struct lagg_softc *, struct lagg_port *); 183 static struct lagg_variant * 184 lagg_variant_getref(struct lagg_softc *, struct psref *); 185 static void lagg_variant_putref(struct lagg_variant *, struct psref *); 186 static int lagg_ether_addmulti(struct lagg_softc *, struct ifreq *); 187 static int lagg_ether_delmulti(struct lagg_softc *, struct ifreq *); 188 static void lagg_port_syncmulti(struct lagg_softc *, struct lagg_port *); 189 static void lagg_port_purgemulti(struct lagg_softc *, struct lagg_port *); 190 static int lagg_port_setup(struct lagg_softc *, struct lagg_port *, 191 struct ifnet *); 192 static void lagg_port_teardown(struct lagg_softc *, struct lagg_port *, 193 bool); 194 static void lagg_port_syncvlan(struct lagg_softc *, struct lagg_port *); 195 static void lagg_port_purgevlan(struct lagg_softc *, struct lagg_port *); 196 static void lagg_capabilities_update(struct lagg_softc *); 197 static void lagg_sync_ifcaps(struct lagg_softc *); 198 static void lagg_sync_ethcaps(struct lagg_softc *); 199 static void lagg_sync_sadl(struct lagg_softc *); 200 201 static struct if_clone lagg_cloner = 202 IF_CLONE_INITIALIZER("lagg", lagg_clone_create, lagg_clone_destroy); 203 static unsigned int lagg_count; 204 static struct psref_class 205 *lagg_psref_class __read_mostly; 206 static struct psref_class 207 *lagg_port_psref_class __read_mostly; 208 209 static enum lagg_iftypes 210 lagg_iftype = LAGG_IF_TYPE_ETHERNET; 211 212 #ifdef LAGG_DEBUG 213 #define __LAGGDEBUGUSED 214 #define LAGG_DPRINTF(_sc, _fmt, _args...) do { \ 215 printf("%s: " _fmt, (_sc) != NULL ? \ 216 (_sc)->sc_if.if_xname : "lagg", ##_args); \ 217 } while (0) 218 #else 219 #define __LAGGDEBUGUSED __unused 220 #define LAGG_DPRINTF(_sc, _fmt, _args...) __nothing 221 #endif 222 223 #ifndef LAGG_SETCAPS_RETRY 224 #define LAGG_SETCAPS_RETRY (LAGG_MAX_PORTS * 2) 225 #endif 226 227 static size_t 228 lagg_sizeof_softc(enum lagg_iftypes ift) 229 { 230 struct lagg_softc *_dummy = NULL; 231 size_t s; 232 233 s = sizeof(*_dummy) - sizeof(_dummy->sc_if); 234 235 switch (ift) { 236 case LAGG_IF_TYPE_ETHERNET: 237 s += sizeof(struct ethercom); 238 break; 239 default: 240 s += sizeof(struct ifnet); 241 break; 242 } 243 244 return s; 245 } 246 247 static void 248 lagg_evcnt_attach(struct lagg_softc *sc, 249 struct evcnt *ev, const char *name) 250 { 251 252 evcnt_attach_dynamic(ev, EVCNT_TYPE_MISC, NULL, 253 sc->sc_evgroup, name); 254 } 255 256 static void 257 lagg_in6_ifattach(struct ifnet *ifp) 258 { 259 260 #ifdef INET6 261 KERNEL_LOCK_UNLESS_NET_MPSAFE(); 262 if (in6_present) { 263 if (ISSET(ifp->if_flags, IFF_UP)) 264 in6_ifattach(ifp, NULL); 265 } 266 KERNEL_UNLOCK_UNLESS_NET_MPSAFE(); 267 #endif 268 } 269 270 static void 271 lagg_in6_ifdetach(struct ifnet *ifp) 272 { 273 274 #ifdef INET6 275 KERNEL_LOCK_UNLESS_NET_MPSAFE(); 276 if (in6_present) 277 in6_ifdetach(ifp); 278 KERNEL_UNLOCK_UNLESS_NET_MPSAFE(); 279 #endif 280 } 281 282 static int 283 lagg_lp_ioctl(struct lagg_port *lp, u_long cmd, void *data) 284 { 285 struct ifnet *ifp_port; 286 int error; 287 288 if (lp->lp_ioctl == NULL) 289 return EINVAL; 290 291 ifp_port = lp->lp_ifp; 292 IFNET_LOCK(ifp_port); 293 error = lp->lp_ioctl(ifp_port, cmd, data); 294 IFNET_UNLOCK(ifp_port); 295 296 return error; 297 } 298 299 static bool 300 lagg_lladdr_equal(const uint8_t *a, const uint8_t *b) 301 { 302 303 if (memcmp(a, b, ETHER_ADDR_LEN) == 0) 304 return true; 305 306 return false; 307 } 308 309 static void 310 lagg_lladdr_cpy(uint8_t *dst, const uint8_t *src) 311 { 312 313 memcpy(dst, src, ETHER_ADDR_LEN); 314 } 315 316 void 317 laggattach(int n) 318 { 319 320 /* 321 * Nothing to do here, initialization is handled by the 322 * module initialization code in lagginit() below). 323 */ 324 } 325 326 static void 327 lagginit(void) 328 { 329 size_t i; 330 331 lagg_psref_class = psref_class_create("laggvariant", IPL_SOFTNET); 332 lagg_port_psref_class = psref_class_create("laggport", IPL_SOFTNET); 333 334 for (i = 0; i < LAGG_PROTO_MAX; i++) { 335 if (lagg_protos[i].pr_init != NULL) 336 lagg_protos[i].pr_init(); 337 } 338 339 if_clone_attach(&lagg_cloner); 340 } 341 342 static int 343 laggdetach(void) 344 { 345 size_t i; 346 347 if (lagg_count > 0) 348 return EBUSY; 349 350 if_clone_detach(&lagg_cloner); 351 352 for (i = 0; i < LAGG_PROTO_MAX; i++) { 353 if (lagg_protos[i].pr_fini != NULL) 354 lagg_protos[i].pr_fini(); 355 } 356 357 psref_class_destroy(lagg_port_psref_class); 358 psref_class_destroy(lagg_psref_class); 359 360 return 0; 361 } 362 363 static int 364 lagg_clone_create(struct if_clone *ifc, int unit) 365 { 366 struct lagg_softc *sc; 367 struct ifnet *ifp; 368 struct ethercom *ec; 369 int error; 370 371 sc = lagg_softc_alloc(lagg_iftype); 372 ifp = &sc->sc_if; 373 374 mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_SOFTNET); 375 sc->sc_psz = pserialize_create(); 376 SIMPLEQ_INIT(&sc->sc_ports); 377 LIST_INIT(&sc->sc_mclist); 378 TAILQ_INIT(&sc->sc_vtags); 379 sc->sc_hash_mac = true; 380 sc->sc_hash_ipaddr = true; 381 sc->sc_hash_ip6addr = true; 382 sc->sc_hash_tcp = true; 383 sc->sc_hash_udp = true; 384 385 if_initname(ifp, ifc->ifc_name, unit); 386 ifp->if_softc = sc; 387 ifp->if_init = lagg_init; 388 ifp->if_stop = lagg_stop; 389 ifp->if_ioctl = lagg_ioctl; 390 ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST; 391 ifp->if_extflags = IFEF_MPSAFE; 392 ifp->if_transmit = lagg_transmit; 393 ifp->if_start = lagg_start; 394 IFQ_SET_READY(&ifp->if_snd); 395 396 error = lagg_setup_sysctls(sc); 397 if (error != 0) 398 goto destroy_psz; 399 400 /*XXX dependent on ethernet */ 401 ifmedia_init_with_lock(&sc->sc_media, 0, lagg_media_change, 402 lagg_media_status, &sc->sc_lock); 403 ifmedia_add(&sc->sc_media, IFM_ETHER | IFM_AUTO, 0, NULL); 404 ifmedia_set(&sc->sc_media, IFM_ETHER | IFM_AUTO); 405 406 if_initialize(ifp); 407 408 switch (lagg_iftype) { 409 case LAGG_IF_TYPE_ETHERNET: 410 ec = (struct ethercom *)ifp; 411 cprng_fast(sc->sc_lladdr_rand, sizeof(sc->sc_lladdr_rand)); 412 sc->sc_lladdr_rand[0] &= 0xFE; /* clear I/G bit */ 413 sc->sc_lladdr_rand[0] |= 0x02; /* set G/L bit */ 414 lagg_lladdr_cpy(sc->sc_lladdr, sc->sc_lladdr_rand); 415 ether_set_vlan_cb(ec, lagg_vlan_cb); 416 417 /* 418 * notify ETHERCAP_VLAN_HWTAGGING to ether_ifattach 419 * to handle VLAN tag, stripped by hardware, in bpf(4) 420 */ 421 ec->ec_capabilities = ETHERCAP_VLAN_HWTAGGING; 422 423 ether_ifattach(ifp, sc->sc_lladdr_rand); 424 break; 425 default: 426 panic("unknown if type"); 427 } 428 429 snprintf(sc->sc_evgroup, sizeof(sc->sc_evgroup), 430 "%s", ifp->if_xname); 431 lagg_evcnt_attach(sc, &sc->sc_novar, "no lagg variant"); 432 if_link_state_change(&sc->sc_if, LINK_STATE_DOWN); 433 lagg_setup_sysctls(sc); 434 (void)lagg_pr_attach(sc, LAGG_PROTO_NONE); 435 if_register(ifp); 436 lagg_count++; 437 438 return 0; 439 440 destroy_psz: 441 pserialize_destroy(sc->sc_psz); 442 mutex_destroy(&sc->sc_lock); 443 lagg_softc_free(sc); 444 445 return error; 446 } 447 448 static int 449 lagg_clone_destroy(struct ifnet *ifp) 450 { 451 struct lagg_softc *sc = (struct lagg_softc *)ifp->if_softc; 452 struct lagg_port *lp; 453 454 lagg_stop(ifp, 1); 455 456 IFNET_LOCK(ifp); 457 LAGG_LOCK(sc); 458 while ((lp = LAGG_PORTS_FIRST(sc)) != NULL) { 459 lagg_port_teardown(sc, lp, false); 460 } 461 LAGG_UNLOCK(sc); 462 IFNET_UNLOCK(ifp); 463 464 switch (ifp->if_type) { 465 case IFT_ETHER: 466 ether_ifdetach(ifp); 467 KASSERT(TAILQ_EMPTY(&sc->sc_vtags)); 468 break; 469 } 470 471 if_detach(ifp); 472 ifmedia_fini(&sc->sc_media); 473 lagg_pr_detach(sc); 474 evcnt_detach(&sc->sc_novar); 475 lagg_teardown_sysctls(sc); 476 477 pserialize_destroy(sc->sc_psz); 478 mutex_destroy(&sc->sc_lock); 479 lagg_softc_free(sc); 480 481 if (lagg_count > 0) 482 lagg_count--; 483 484 return 0; 485 } 486 487 static int 488 lagg_init(struct ifnet *ifp) 489 { 490 struct lagg_softc *sc; 491 int rv; 492 493 sc = ifp->if_softc; 494 LAGG_LOCK(sc); 495 rv = lagg_init_locked(sc); 496 LAGG_UNLOCK(sc); 497 498 return rv; 499 } 500 501 static int 502 lagg_init_locked(struct lagg_softc *sc) 503 { 504 struct ifnet *ifp = &sc->sc_if; 505 int rv; 506 507 KASSERT(LAGG_LOCKED(sc)); 508 509 if (ISSET(ifp->if_flags, IFF_RUNNING)) 510 lagg_stop_locked(sc); 511 512 lagg_sync_sadl(sc); 513 514 SET(ifp->if_flags, IFF_RUNNING); 515 516 rv = lagg_proto_up(sc); 517 if (rv != 0) 518 lagg_stop_locked(sc); 519 520 return rv; 521 } 522 523 static void 524 lagg_stop(struct ifnet *ifp, int disable __unused) 525 { 526 struct lagg_softc *sc; 527 528 sc = ifp->if_softc; 529 LAGG_LOCK(sc); 530 lagg_stop_locked(sc); 531 LAGG_UNLOCK(sc); 532 } 533 534 static void 535 lagg_stop_locked(struct lagg_softc *sc) 536 { 537 struct ifnet *ifp = &sc->sc_if; 538 539 KASSERT(LAGG_LOCKED(sc)); 540 541 if (!ISSET(ifp->if_flags, IFF_RUNNING)) 542 return; 543 544 CLR(ifp->if_flags, IFF_RUNNING); 545 lagg_proto_down(sc); 546 547 } 548 549 static int 550 lagg_config(struct lagg_softc *sc, struct lagg_req *lrq) 551 { 552 struct ifnet *ifp_port; 553 struct laggreqport *rp; 554 struct lagg_port *lp; 555 struct psref psref; 556 size_t i; 557 int error, bound; 558 559 error = 0; 560 bound = curlwp_bind(); 561 562 switch (lrq->lrq_ioctl) { 563 case LAGGIOC_SETPROTO: 564 if (lrq->lrq_proto >= LAGG_PROTO_MAX) { 565 error = EPROTONOSUPPORT; 566 break; 567 } 568 569 error = lagg_delport_all(sc); 570 if (error != 0) 571 break; 572 error = lagg_pr_attach(sc, lrq->lrq_proto); 573 if (error != 0) 574 break; 575 576 for (i = 0; i < lrq->lrq_nports; i++) { 577 rp = &lrq->lrq_reqports[i]; 578 ifp_port = if_get(rp->rp_portname, &psref); 579 if (ifp_port == NULL) { 580 error = ENOENT; 581 break; /* break for */ 582 } 583 584 error = lagg_addport(sc, ifp_port); 585 if_put(ifp_port, &psref); 586 587 if (error != 0) 588 break; /* break for */ 589 } 590 break; /* break switch */ 591 case LAGGIOC_ADDPORT: 592 rp = &lrq->lrq_reqports[0]; 593 ifp_port = if_get(rp->rp_portname, &psref); 594 if (ifp_port == NULL) { 595 error = ENOENT; 596 break; 597 } 598 599 error = lagg_addport(sc, ifp_port); 600 if_put(ifp_port, &psref); 601 break; 602 case LAGGIOC_DELPORT: 603 rp = &lrq->lrq_reqports[0]; 604 ifp_port = if_get(rp->rp_portname, &psref); 605 if (ifp_port == NULL) { 606 error = ENOENT; 607 break; 608 } 609 610 error = lagg_delport(sc, ifp_port); 611 if_put(ifp_port, &psref); 612 break; 613 case LAGGIOC_SETPORTPRI: 614 rp = &lrq->lrq_reqports[0]; 615 ifp_port = if_get(rp->rp_portname, &psref); 616 if (ifp_port == NULL) { 617 error = ENOENT; 618 break; 619 } 620 621 lp = ifp_port->if_lagg; 622 if (lp == NULL || lp->lp_softc != sc) { 623 if_put(ifp_port, &psref); 624 error = ENOENT; 625 break; 626 } 627 628 lp->lp_prio = rp->rp_prio; 629 630 /* restart protocol */ 631 LAGG_LOCK(sc); 632 lagg_proto_stopport(sc, lp); 633 lagg_proto_startport(sc, lp); 634 LAGG_UNLOCK(sc); 635 if_put(ifp_port, &psref); 636 break; 637 case LAGGIOC_SETPROTOOPT: 638 error = lagg_proto_ioctl(sc, lrq); 639 break; 640 default: 641 error = ENOTTY; 642 } 643 644 curlwp_bindx(bound); 645 return error; 646 } 647 648 static int 649 lagg_ioctl(struct ifnet *ifp, u_long cmd, void *data) 650 { 651 struct lagg_softc *sc; 652 struct ifreq *ifr = (struct ifreq *)data; 653 struct lagg_req laggreq, *laggresp; 654 struct lagg_port *lp; 655 size_t allocsiz, outlen, nports; 656 char *outbuf; 657 void *buf; 658 int error = 0, rv; 659 660 sc = ifp->if_softc; 661 662 switch (cmd) { 663 case SIOCGLAGG: 664 error = copyin(ifr->ifr_data, &laggreq, sizeof(laggreq)); 665 if (error != 0) 666 break; 667 668 nports = sc->sc_nports; 669 nports = MIN(nports, laggreq.lrq_nports); 670 671 allocsiz = sizeof(*laggresp) 672 + sizeof(laggresp->lrq_reqports[0]) * nports; 673 laggresp = kmem_zalloc(allocsiz, KM_SLEEP); 674 675 rv = lagg_get_stats(sc, laggresp, nports); 676 677 outbuf = (char *)laggresp; 678 679 nports = MIN(laggresp->lrq_nports, nports); 680 outlen = sizeof(*laggresp) 681 + sizeof(laggresp->lrq_reqports[0]) * nports; 682 683 error = copyout(outbuf, ifr->ifr_data, outlen); 684 kmem_free(outbuf, allocsiz); 685 686 if (error == 0 && rv != 0) 687 error = rv; 688 689 break; 690 case SIOCSLAGG: 691 error = copyin(ifr->ifr_data, &laggreq, sizeof(laggreq)); 692 if (error != 0) 693 break; 694 695 nports = laggreq.lrq_nports; 696 if (nports > LAGG_MAX_PORTS) { 697 error = ENOMEM; 698 break; 699 } else if (nports > 0) { 700 allocsiz = sizeof(struct lagg_req) 701 + sizeof(struct laggreqport) * nports; 702 buf = kmem_alloc(allocsiz, KM_SLEEP); 703 704 error = copyin(ifr->ifr_data, buf, allocsiz); 705 if (error != 0) { 706 kmem_free(buf, allocsiz); 707 break; 708 } 709 } else { 710 buf = (void *)&laggreq; 711 allocsiz = 0; 712 } 713 714 error = lagg_config(sc, buf); 715 if (allocsiz > 0) 716 kmem_free(buf, allocsiz); 717 break; 718 case SIOCSIFFLAGS: 719 error = ifioctl_common(ifp, cmd, data); 720 if (error != 0) 721 break; 722 723 switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) { 724 case IFF_RUNNING: 725 if_stop(ifp, 1); 726 break; 727 case IFF_UP: 728 error = if_init(ifp); 729 break; 730 } 731 732 if (error != 0) 733 break; 734 735 /* Set flags on ports too */ 736 LAGG_LOCK(sc); 737 LAGG_PORTS_FOREACH(sc, lp) { 738 (void)lagg_config_promisc(sc, lp); 739 } 740 LAGG_UNLOCK(sc); 741 break; 742 case SIOCSIFMTU: 743 /* set the MTU to each port */ 744 LAGG_LOCK(sc); 745 LAGG_PORTS_FOREACH(sc, lp) { 746 error = lagg_lp_ioctl(lp, cmd, (void *)ifr); 747 748 if (error != 0) { 749 LAGG_LOG(sc, LOG_ERR, 750 "failed to change MTU to %d on port %s, " 751 "reverting all ports to original " 752 "MTU(%" PRIu64 ")\n", 753 ifr->ifr_mtu, lp->lp_ifp->if_xname, 754 ifp->if_mtu); 755 break; 756 } 757 } 758 LAGG_UNLOCK(sc); 759 760 /* set the MTU to the lagg interface */ 761 if (error == 0) 762 error = ether_ioctl(ifp, cmd, data); 763 764 if (error != 0) { 765 /* undo the changed MTU */ 766 ifr->ifr_mtu = ifp->if_mtu; 767 768 LAGG_LOCK(sc); 769 LAGG_PORTS_FOREACH(sc, lp) { 770 if (lp->lp_ioctl != NULL) 771 lagg_lp_ioctl(lp, cmd, (void *)ifr); 772 } 773 LAGG_UNLOCK(sc); 774 } 775 break; 776 case SIOCADDMULTI: 777 if (sc->sc_if.if_type == IFT_ETHER) { 778 error = lagg_ether_addmulti(sc, ifr); 779 } else { 780 error = EPROTONOSUPPORT; 781 } 782 break; 783 case SIOCDELMULTI: 784 if (sc->sc_if.if_type == IFT_ETHER) { 785 error = lagg_ether_delmulti(sc, ifr); 786 } else { 787 error = EPROTONOSUPPORT; 788 } 789 break; 790 case SIOCSIFCAP: 791 error = ether_ioctl(ifp, cmd, data); 792 if (error == 0) 793 lagg_sync_ifcaps(sc); 794 break; 795 case SIOCSETHERCAP: 796 error = ether_ioctl(ifp, cmd, data); 797 if (error == 0) 798 lagg_sync_ethcaps(sc); 799 break; 800 default: 801 error = ether_ioctl(ifp, cmd, data); 802 } 803 return error; 804 } 805 806 static int 807 lagg_setup_sysctls(struct lagg_softc *sc) 808 { 809 struct sysctllog **slog; 810 const struct sysctlnode **rnode, *hashnode; 811 const char *ifname; 812 int error; 813 814 slog = &sc->sc_sysctllog; 815 rnode = &sc->sc_sysctlnode; 816 ifname = sc->sc_if.if_xname; 817 818 error = sysctl_createv(slog, 0, NULL, rnode, 819 CTLFLAG_PERMANENT, CTLTYPE_NODE, ifname, 820 SYSCTL_DESCR("lagg information and settings"), 821 NULL, 0, NULL, 0, CTL_NET, CTL_CREATE, CTL_EOL); 822 if (error != 0) 823 goto done; 824 825 error = sysctl_createv(slog, 0, rnode, &hashnode, 826 CTLFLAG_PERMANENT, CTLTYPE_NODE, "hash", 827 SYSCTL_DESCR("hash calculation settings"), 828 NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL); 829 if (error != 0) 830 goto done; 831 832 error = sysctl_createv(slog, 0, &hashnode, NULL, 833 CTLFLAG_READWRITE, CTLTYPE_BOOL, "macaddr", 834 SYSCTL_DESCR("use src/dst mac addresses"), 835 NULL, 0, &sc->sc_hash_mac, 0, CTL_CREATE, CTL_EOL); 836 if (error != 0) 837 goto done; 838 839 error = sysctl_createv(slog, 0, &hashnode, NULL, 840 CTLFLAG_READWRITE, CTLTYPE_BOOL, "ipaddr", 841 SYSCTL_DESCR("use src/dst IPv4 addresses"), 842 NULL, 0, &sc->sc_hash_ipaddr, 0, CTL_CREATE, CTL_EOL); 843 if (error != 0) 844 goto done; 845 846 error = sysctl_createv(slog, 0, &hashnode, NULL, 847 CTLFLAG_READWRITE, CTLTYPE_BOOL, "ip6addr", 848 SYSCTL_DESCR("use src/dst IPv6 addresses"), 849 NULL, 0, &sc->sc_hash_ip6addr, 0, CTL_CREATE, CTL_EOL); 850 if (error != 0) 851 goto done; 852 853 error = sysctl_createv(slog, 0, &hashnode, NULL, 854 CTLFLAG_READWRITE, CTLTYPE_BOOL, "tcp", 855 SYSCTL_DESCR("use TCP src/dst port"), 856 NULL, 0, &sc->sc_hash_tcp, 0, CTL_CREATE, CTL_EOL); 857 if (error != 0) 858 goto done; 859 860 error = sysctl_createv(slog, 0, &hashnode, NULL, 861 CTLFLAG_READWRITE, CTLTYPE_BOOL, "udp", 862 SYSCTL_DESCR("use UDP src/dst port"), 863 NULL, 0, &sc->sc_hash_udp, 0, CTL_CREATE, CTL_EOL); 864 done: 865 if (error != 0) { 866 LAGG_LOG(sc, LOG_ERR, "unable to create sysctl node\n"); 867 sysctl_teardown(slog); 868 } 869 870 return error; 871 } 872 873 static void 874 lagg_teardown_sysctls(struct lagg_softc *sc) 875 { 876 877 sc->sc_sysctlnode = NULL; 878 sysctl_teardown(&sc->sc_sysctllog); 879 } 880 881 uint32_t 882 lagg_hashmbuf(struct lagg_softc *sc, struct mbuf *m) 883 { 884 union { 885 struct ether_header _eh; 886 struct ether_vlan_header _evl; 887 struct ip _ip; 888 struct ip6_hdr _ip6; 889 struct tcphdr _th; 890 struct udphdr _uh; 891 } buf; 892 const struct ether_header *eh; 893 const struct ether_vlan_header *evl; 894 const struct ip *ip; 895 const struct ip6_hdr *ip6; 896 const struct tcphdr *th; 897 const struct udphdr *uh; 898 uint32_t hash, hash_src, hash_dst; 899 uint32_t flowlabel; 900 uint16_t etype, vlantag; 901 uint8_t proto; 902 size_t off; 903 904 KASSERT(ISSET(m->m_flags, M_PKTHDR)); 905 906 hash = HASH32_BUF_INIT; 907 hash_src = HASH32_BUF_INIT; 908 hash_dst = HASH32_BUF_INIT; 909 910 #define LAGG_HASH_ADD(hp, v) do { \ 911 *(hp) = hash32_buf(&(v), sizeof(v), *(hp)); \ 912 } while(0) 913 914 eh = lagg_m_extract(m, 0, sizeof(*eh), __alignof(*eh), &buf); 915 if (eh == NULL) 916 goto out; 917 918 off = ETHER_HDR_LEN; 919 etype = ntohs(eh->ether_type); 920 921 if (etype == ETHERTYPE_VLAN) { 922 evl = lagg_m_extract(m, 0, sizeof(*evl), __alignof(*evl), 923 &buf); 924 if (evl == NULL) 925 goto out; 926 927 vlantag = ntohs(evl->evl_tag); 928 etype = ntohs(evl->evl_proto); 929 off += ETHER_VLAN_ENCAP_LEN; 930 } else if (vlan_has_tag(m)) { 931 vlantag = vlan_get_tag(m); 932 } else { 933 vlantag = 0; 934 } 935 936 if (sc->sc_hash_mac) { 937 LAGG_HASH_ADD(&hash_dst, eh->ether_dhost); 938 LAGG_HASH_ADD(&hash_src, eh->ether_shost); 939 LAGG_HASH_ADD(&hash, vlantag); 940 } 941 942 switch (etype) { 943 case ETHERTYPE_IP: 944 ip = lagg_m_extract(m, off, sizeof(*ip), __alignof(*ip), &buf); 945 if (ip == NULL) 946 goto out; 947 948 if (sc->sc_hash_ipaddr) { 949 LAGG_HASH_ADD(&hash_src, ip->ip_src); 950 LAGG_HASH_ADD(&hash_dst, ip->ip_dst); 951 LAGG_HASH_ADD(&hash, ip->ip_p); 952 } 953 off += ip->ip_hl << 2; 954 proto = ip->ip_p; 955 break; 956 case ETHERTYPE_IPV6: 957 ip6 = lagg_m_extract(m, off, sizeof(*ip6), __alignof(*ip6), 958 &buf); 959 if (ip6 == NULL) 960 goto out; 961 962 if (sc->sc_hash_ip6addr) { 963 LAGG_HASH_ADD(&hash_src, ip6->ip6_src); 964 LAGG_HASH_ADD(&hash_dst, ip6->ip6_dst); 965 flowlabel = ip6->ip6_flow & IPV6_FLOWLABEL_MASK; 966 LAGG_HASH_ADD(&hash, flowlabel); 967 } 968 proto = ip6->ip6_nxt; 969 off += sizeof(*ip6); 970 break; 971 972 default: 973 return hash; 974 } 975 976 switch (proto) { 977 case IPPROTO_TCP: 978 th = lagg_m_extract(m, off, sizeof(*th), __alignof(*th), &buf); 979 if (th == NULL) 980 goto out; 981 982 if (sc->sc_hash_tcp) { 983 LAGG_HASH_ADD(&hash_src, th->th_sport); 984 LAGG_HASH_ADD(&hash_dst, th->th_dport); 985 } 986 break; 987 case IPPROTO_UDP: 988 uh = lagg_m_extract(m, off, sizeof(*uh), __alignof(*uh), &buf); 989 if (uh == NULL) 990 goto out; 991 992 if (sc->sc_hash_udp) { 993 LAGG_HASH_ADD(&hash_src, uh->uh_sport); 994 LAGG_HASH_ADD(&hash_dst, uh->uh_dport); 995 } 996 break; 997 } 998 999 out: 1000 hash_src ^= hash_dst; 1001 LAGG_HASH_ADD(&hash, hash_src); 1002 #undef LAGG_HASH_ADD 1003 1004 return hash; 1005 } 1006 1007 static int 1008 lagg_tx_common(struct ifnet *ifp, struct mbuf *m) 1009 { 1010 struct lagg_variant *var; 1011 lagg_proto pr; 1012 struct psref psref; 1013 int error; 1014 1015 var = lagg_variant_getref(ifp->if_softc, &psref); 1016 1017 if (__predict_false(var == NULL)) { 1018 m_freem(m); 1019 if_statinc(ifp, if_oerrors); 1020 return ENOENT; 1021 } 1022 1023 pr = var->lv_proto; 1024 if (__predict_true(lagg_protos[pr].pr_transmit != NULL)) { 1025 error = lagg_protos[pr].pr_transmit(var->lv_psc, m); 1026 /* mbuf is already freed */ 1027 } else { 1028 m_freem(m); 1029 if_statinc(ifp, if_oerrors); 1030 error = EIO; 1031 } 1032 1033 lagg_variant_putref(var, &psref); 1034 1035 return error; 1036 } 1037 1038 static int 1039 lagg_transmit(struct ifnet *ifp, struct mbuf *m) 1040 { 1041 1042 return lagg_tx_common(ifp, m); 1043 } 1044 1045 static void 1046 lagg_start(struct ifnet *ifp) 1047 { 1048 struct mbuf *m; 1049 1050 for (;;) { 1051 IFQ_DEQUEUE(&ifp->if_snd, m); 1052 if (m == NULL) 1053 break; 1054 1055 (void)lagg_tx_common(ifp, m); 1056 } 1057 } 1058 1059 void 1060 lagg_output(struct lagg_softc *sc, struct lagg_port *lp, struct mbuf *m) 1061 { 1062 struct ifnet *ifp; 1063 int len, error; 1064 short mflags; 1065 1066 ifp = &sc->sc_if; 1067 len = m->m_pkthdr.len; 1068 mflags = m->m_flags; 1069 1070 error = pfil_run_hooks(ifp->if_pfil, &m, ifp, PFIL_OUT); 1071 if (error != 0) { 1072 m_freem(m); 1073 return; 1074 } 1075 bpf_mtap(ifp, m, BPF_D_OUT); 1076 1077 error = lagg_port_xmit(lp, m); 1078 if (error) { 1079 /* mbuf is already freed */ 1080 if_statinc(ifp, if_oerrors); 1081 } else { 1082 net_stat_ref_t nsr = IF_STAT_GETREF(ifp); 1083 if_statinc_ref(ifp, nsr, if_opackets); 1084 if_statadd_ref(ifp, nsr, if_obytes, len); 1085 if (mflags & M_MCAST) 1086 if_statinc_ref(ifp, nsr, if_omcasts); 1087 IF_STAT_PUTREF(ifp); 1088 } 1089 } 1090 1091 static struct mbuf * 1092 lagg_proto_input(struct lagg_softc *sc, struct lagg_port *lp, struct mbuf *m) 1093 { 1094 struct psref psref; 1095 struct lagg_variant *var; 1096 lagg_proto pr; 1097 1098 var = lagg_variant_getref(sc, &psref); 1099 1100 if (var == NULL) { 1101 sc->sc_novar.ev_count++; 1102 m_freem(m); 1103 return NULL; 1104 } 1105 1106 pr = var->lv_proto; 1107 1108 if (lagg_protos[pr].pr_input != NULL) { 1109 m = lagg_protos[pr].pr_input(var->lv_psc, lp, m); 1110 } else { 1111 m_freem(m); 1112 m = NULL; 1113 } 1114 1115 lagg_variant_putref(var, &psref); 1116 1117 return m; 1118 } 1119 1120 static void 1121 lagg_input_ethernet(struct ifnet *ifp_port, struct mbuf *m) 1122 { 1123 struct ifnet *ifp; 1124 struct psref psref; 1125 struct lagg_port *lp; 1126 struct ether_header *eh; 1127 int s; 1128 1129 /* sanity check */ 1130 s = pserialize_read_enter(); 1131 lp = atomic_load_consume(&ifp_port->if_lagg); 1132 if (lp == NULL) { 1133 /* This interface is not a member of lagg */ 1134 pserialize_read_exit(s); 1135 m_freem(m); 1136 if_statinc(ifp_port, if_ierrors); 1137 return; 1138 } 1139 lagg_port_getref(lp, &psref); 1140 pserialize_read_exit(s); 1141 1142 ifp = &lp->lp_softc->sc_if; 1143 1144 if (__predict_false(m->m_len < (int)sizeof(*eh))) { 1145 if ((m = m_pullup(m, sizeof(*eh))) == NULL) { 1146 if_statinc(ifp, if_ierrors); 1147 goto out; 1148 } 1149 } 1150 1151 eh = mtod(m, struct ether_header *); 1152 1153 if (ETHER_IS_MULTICAST(eh->ether_dhost)) { 1154 /* 1155 * If this is not a simplex interface, drop the packet 1156 * if it came from us. 1157 */ 1158 if ((ifp->if_flags & IFF_SIMPLEX) == 0 && 1159 memcmp(CLLADDR(ifp->if_sadl), eh->ether_shost, 1160 ETHER_ADDR_LEN) == 0) { 1161 goto drop; 1162 } 1163 1164 if_statinc(ifp_port, if_imcasts); 1165 } else { 1166 /* 1167 * Drop promiscuously received packets 1168 * if we are not in promiscuous mode. 1169 */ 1170 if ((ifp->if_flags & IFF_PROMISC) == 0 && 1171 (ifp_port->if_flags & IFF_PROMISC) != 0 && 1172 memcmp(CLLADDR(ifp->if_sadl), eh->ether_dhost, 1173 ETHER_ADDR_LEN) != 0) 1174 goto drop; 1175 } 1176 1177 if_statadd(ifp_port, if_ibytes, m->m_pkthdr.len); 1178 1179 if (pfil_run_hooks(ifp_port->if_pfil, &m, 1180 ifp_port, PFIL_IN) != 0) { 1181 m_freem(m); 1182 m = NULL; 1183 goto out; 1184 } 1185 1186 m = lagg_proto_input(lp->lp_softc, lp, m); 1187 if (m != NULL) { 1188 m_set_rcvif(m, ifp); 1189 m->m_flags &= ~M_PROMISC; 1190 if_input(ifp, m); 1191 } 1192 1193 out: 1194 lagg_port_putref(lp, &psref); 1195 return; 1196 1197 drop: 1198 lagg_port_putref(lp, &psref); 1199 m_freem(m); 1200 if_statinc(ifp_port, if_iqdrops); 1201 return; 1202 } 1203 1204 static int 1205 lagg_media_change(struct ifnet *ifp) 1206 { 1207 1208 if (ISSET(ifp->if_flags, IFF_DEBUG)) 1209 printf("%s: ignore media change\n", ifp->if_xname); 1210 1211 return 0; 1212 } 1213 1214 static void 1215 lagg_media_status(struct ifnet *ifp, struct ifmediareq *imr) 1216 { 1217 struct lagg_softc *sc; 1218 struct lagg_port *lp; 1219 1220 sc = ifp->if_softc; 1221 1222 imr->ifm_status = IFM_AVALID; 1223 imr->ifm_active = IFM_ETHER | IFM_AUTO; 1224 1225 LAGG_LOCK(sc); 1226 1227 imr->ifm_active |= sc->sc_media_active; 1228 1229 LAGG_PORTS_FOREACH(sc, lp) { 1230 if (lagg_portactive(lp)) 1231 imr->ifm_status |= IFM_ACTIVE; 1232 } 1233 LAGG_UNLOCK(sc); 1234 } 1235 1236 static uint64_t 1237 lagg_search_media_type(uint64_t linkspeed) 1238 { 1239 1240 if (linkspeed == IF_Gbps(40)) 1241 return IFM_40G_T | IFM_FDX; 1242 1243 if (linkspeed == IF_Gbps(25)) 1244 return IFM_25G_T | IFM_FDX; 1245 1246 if (linkspeed == IF_Gbps(10)) 1247 return IFM_10G_T | IFM_FDX; 1248 1249 if (linkspeed == IF_Gbps(5)) 1250 return IFM_5000_T | IFM_FDX; 1251 1252 if (linkspeed == IF_Mbps(2500)) 1253 return IFM_2500_T | IFM_FDX; 1254 1255 if (linkspeed == IF_Gbps(1)) 1256 return IFM_1000_T | IFM_FDX; 1257 1258 if (linkspeed == IF_Mbps(100)) 1259 return IFM_100_TX | IFM_FDX; 1260 1261 if (linkspeed == IF_Mbps(10)) 1262 return IFM_10_T | IFM_FDX; 1263 1264 return 0; 1265 } 1266 1267 void 1268 lagg_set_linkspeed(struct lagg_softc *sc, uint64_t linkspeed) 1269 { 1270 struct ifnet *ifp; 1271 1272 ifp = &sc->sc_if; 1273 1274 KASSERT(LAGG_LOCKED(sc)); 1275 1276 ifp->if_baudrate = linkspeed; 1277 1278 sc->sc_media_active = 1279 lagg_search_media_type(linkspeed); 1280 } 1281 1282 static int 1283 lagg_port_vlan_cb(struct lagg_port *lp, 1284 struct lagg_vlantag *lvt, bool set) 1285 { 1286 struct ifnet *ifp_port; 1287 int error; 1288 1289 if (lp->lp_iftype != IFT_ETHER) 1290 return 0; 1291 1292 error = 0; 1293 ifp_port = lp->lp_ifp; 1294 1295 if (set) { 1296 error = ether_add_vlantag(ifp_port, 1297 lvt->lvt_vtag, NULL); 1298 } else { 1299 error = ether_del_vlantag(ifp_port, 1300 lvt->lvt_vtag); 1301 } 1302 1303 return error; 1304 } 1305 1306 static int 1307 lagg_vlan_cb(struct ethercom *ec, uint16_t vtag, bool set) 1308 { 1309 struct ifnet *ifp; 1310 struct lagg_softc *sc; 1311 struct lagg_vlantag *lvt, *lvt0; 1312 struct lagg_port *lp; 1313 int error; 1314 1315 ifp = (struct ifnet *)ec; 1316 sc = ifp->if_softc; 1317 1318 if (set) { 1319 lvt = kmem_zalloc(sizeof(*lvt), KM_SLEEP); 1320 lvt->lvt_vtag = vtag; 1321 TAILQ_INSERT_TAIL(&sc->sc_vtags, lvt, lvt_entry); 1322 } else { 1323 TAILQ_FOREACH_SAFE(lvt, &sc->sc_vtags, lvt_entry, lvt0) { 1324 if (lvt->lvt_vtag == vtag) { 1325 TAILQ_REMOVE(&sc->sc_vtags, lvt, lvt_entry); 1326 break; 1327 } 1328 } 1329 1330 if (lvt == NULL) 1331 return ENOENT; 1332 } 1333 1334 KASSERT(lvt != NULL); 1335 LAGG_PORTS_FOREACH(sc, lp) { 1336 error = lagg_port_vlan_cb(lp, lvt, set); 1337 if (error != 0) { 1338 LAGG_LOG(sc, LOG_WARNING, 1339 "%s failed to configure vlan on %d\n", 1340 lp->lp_ifp->if_xname, error); 1341 } 1342 } 1343 1344 return 0; 1345 } 1346 1347 static struct lagg_softc * 1348 lagg_softc_alloc(enum lagg_iftypes ift) 1349 { 1350 struct lagg_softc *sc; 1351 size_t s; 1352 1353 s = lagg_sizeof_softc(ift); 1354 KASSERT(s > 0); 1355 1356 sc = kmem_zalloc(s, KM_SLEEP); 1357 KASSERT(sc != NULL); 1358 1359 return sc; 1360 } 1361 1362 static void 1363 lagg_softc_free(struct lagg_softc *sc) 1364 { 1365 1366 kmem_free(sc, 1367 lagg_sizeof_softc(sc->sc_iftype)); 1368 } 1369 1370 static void 1371 lagg_variant_update(struct lagg_softc *sc, struct lagg_variant *newvar) 1372 { 1373 struct lagg_variant *oldvar; 1374 1375 KASSERT(LAGG_LOCKED(sc)); 1376 1377 psref_target_init(&newvar->lv_psref, lagg_psref_class); 1378 1379 oldvar = sc->sc_var; 1380 atomic_store_release(&sc->sc_var, newvar); 1381 pserialize_perform(sc->sc_psz); 1382 1383 if (__predict_true(oldvar != NULL)) 1384 psref_target_destroy(&oldvar->lv_psref, lagg_psref_class); 1385 } 1386 1387 static struct lagg_variant * 1388 lagg_variant_getref(struct lagg_softc *sc, struct psref *psref) 1389 { 1390 struct lagg_variant *var; 1391 int s; 1392 1393 s = pserialize_read_enter(); 1394 var = atomic_load_consume(&sc->sc_var); 1395 if (var == NULL) { 1396 pserialize_read_exit(s); 1397 return NULL; 1398 } 1399 1400 psref_acquire(psref, &var->lv_psref, lagg_psref_class); 1401 pserialize_read_exit(s); 1402 1403 return var; 1404 } 1405 1406 static void 1407 lagg_variant_putref(struct lagg_variant *var, struct psref *psref) 1408 { 1409 1410 if (__predict_false(var == NULL)) 1411 return; 1412 psref_release(psref, &var->lv_psref, lagg_psref_class); 1413 } 1414 1415 static int 1416 lagg_proto_attach(struct lagg_softc *sc, lagg_proto pr, 1417 struct lagg_proto_softc **psc) 1418 { 1419 1420 KASSERT(lagg_protos[pr].pr_attach != NULL); 1421 return lagg_protos[pr].pr_attach(sc, psc); 1422 } 1423 1424 static void 1425 lagg_proto_detach(struct lagg_variant *oldvar) 1426 { 1427 lagg_proto pr; 1428 1429 pr = oldvar->lv_proto; 1430 1431 if (lagg_protos[pr].pr_detach == NULL) 1432 return; 1433 1434 lagg_protos[pr].pr_detach(oldvar->lv_psc); 1435 } 1436 1437 static int 1438 lagg_proto_updown(struct lagg_softc *sc, bool is_up) 1439 { 1440 struct lagg_variant *var; 1441 struct psref psref; 1442 lagg_proto pr; 1443 int error, bound; 1444 1445 error = 0; 1446 bound = curlwp_bind(); 1447 1448 var = lagg_variant_getref(sc, &psref); 1449 if (var == NULL) { 1450 curlwp_bindx(bound); 1451 return ENXIO; 1452 } 1453 1454 pr = var->lv_proto; 1455 1456 if (is_up && lagg_protos[pr].pr_up != NULL) { 1457 error = lagg_protos[pr].pr_up(var->lv_psc); 1458 } else if (!is_up && lagg_protos[pr].pr_down != NULL) { 1459 lagg_protos[pr].pr_down(var->lv_psc); 1460 } 1461 1462 lagg_variant_putref(var, &psref); 1463 curlwp_bindx(bound); 1464 1465 return error; 1466 } 1467 1468 static int 1469 lagg_proto_up(struct lagg_softc *sc) 1470 { 1471 1472 return lagg_proto_updown(sc, true); 1473 } 1474 1475 static void 1476 lagg_proto_down(struct lagg_softc *sc) 1477 { 1478 1479 (void)lagg_proto_updown(sc, false); 1480 } 1481 1482 static int 1483 lagg_proto_portctrl(struct lagg_softc *sc, struct lagg_port *lp, 1484 enum lagg_portctrl ctrl) 1485 { 1486 struct lagg_variant *var; 1487 struct psref psref; 1488 lagg_proto pr; 1489 int error, bound; 1490 1491 error = 0; 1492 bound = curlwp_bind(); 1493 1494 var = lagg_variant_getref(sc, &psref); 1495 if (var == NULL) { 1496 curlwp_bindx(bound); 1497 return ENXIO; 1498 } 1499 1500 pr = var->lv_proto; 1501 1502 switch (ctrl) { 1503 case LAGG_PORTCTRL_ALLOC: 1504 if (lagg_protos[pr].pr_allocport == NULL) { 1505 goto nosupport; 1506 } 1507 error = lagg_protos[pr].pr_allocport(var->lv_psc, lp); 1508 break; 1509 case LAGG_PORTCTRL_FREE: 1510 if (lagg_protos[pr].pr_freeport == NULL) { 1511 goto nosupport; 1512 } 1513 lagg_protos[pr].pr_freeport(var->lv_psc, lp); 1514 break; 1515 case LAGG_PORTCTRL_START: 1516 if (lagg_protos[pr].pr_startport == NULL) { 1517 goto nosupport; 1518 } 1519 lagg_protos[pr].pr_startport(var->lv_psc, lp); 1520 break; 1521 case LAGG_PORTCTRL_STOP: 1522 if (lagg_protos[pr].pr_stopport == NULL) { 1523 goto nosupport; 1524 } 1525 lagg_protos[pr].pr_stopport(var->lv_psc, lp); 1526 break; 1527 default: 1528 goto nosupport; 1529 } 1530 1531 lagg_variant_putref(var, &psref); 1532 curlwp_bindx(bound); 1533 return error; 1534 1535 nosupport: 1536 lagg_variant_putref(var, &psref); 1537 curlwp_bindx(bound); 1538 return EPROTONOSUPPORT; 1539 } 1540 1541 static int 1542 lagg_proto_allocport(struct lagg_softc *sc, struct lagg_port *lp) 1543 { 1544 1545 return lagg_proto_portctrl(sc, lp, LAGG_PORTCTRL_ALLOC); 1546 } 1547 1548 static void 1549 lagg_proto_freeport(struct lagg_softc *sc, struct lagg_port *lp) 1550 { 1551 1552 lagg_proto_portctrl(sc, lp, LAGG_PORTCTRL_FREE); 1553 } 1554 1555 static void 1556 lagg_proto_startport(struct lagg_softc *sc, struct lagg_port *lp) 1557 { 1558 1559 lagg_proto_portctrl(sc, lp, LAGG_PORTCTRL_START); 1560 } 1561 1562 static void 1563 lagg_proto_stopport(struct lagg_softc *sc, struct lagg_port *lp) 1564 { 1565 1566 lagg_proto_portctrl(sc, lp, LAGG_PORTCTRL_STOP); 1567 } 1568 1569 static void 1570 lagg_proto_linkstate(struct lagg_softc *sc, struct lagg_port *lp) 1571 { 1572 struct lagg_variant *var; 1573 struct psref psref; 1574 lagg_proto pr; 1575 int bound; 1576 1577 KASSERT(IFNET_LOCKED(lp->lp_ifp)); 1578 1579 bound = curlwp_bind(); 1580 var = lagg_variant_getref(sc, &psref); 1581 1582 if (var == NULL) { 1583 curlwp_bindx(bound); 1584 return; 1585 } 1586 1587 pr = var->lv_proto; 1588 1589 if (lagg_protos[pr].pr_linkstate) 1590 lagg_protos[pr].pr_linkstate(var->lv_psc, lp); 1591 1592 lagg_variant_putref(var, &psref); 1593 curlwp_bindx(bound); 1594 } 1595 1596 static void 1597 lagg_proto_stat(struct lagg_variant *var, struct laggreqproto *resp) 1598 { 1599 lagg_proto pr; 1600 1601 pr = var->lv_proto; 1602 1603 if (lagg_protos[pr].pr_protostat != NULL) 1604 lagg_protos[pr].pr_protostat(var->lv_psc, resp); 1605 } 1606 1607 static void 1608 lagg_proto_portstat(struct lagg_variant *var, struct lagg_port *lp, 1609 struct laggreqport *resp) 1610 { 1611 lagg_proto pr; 1612 1613 pr = var->lv_proto; 1614 1615 if (lagg_protos[pr].pr_portstat != NULL) 1616 lagg_protos[pr].pr_portstat(var->lv_psc, lp, resp); 1617 } 1618 1619 static int 1620 lagg_proto_ioctl(struct lagg_softc *sc, struct lagg_req *lreq) 1621 { 1622 struct lagg_variant *var; 1623 struct psref psref; 1624 lagg_proto pr; 1625 int bound, error; 1626 1627 error = ENOTTY; 1628 bound = curlwp_bind(); 1629 var = lagg_variant_getref(sc, &psref); 1630 1631 if (var == NULL) { 1632 error = ENXIO; 1633 goto done; 1634 } 1635 1636 pr = var->lv_proto; 1637 if (pr != lreq->lrq_proto) { 1638 error = EBUSY; 1639 goto done; 1640 } 1641 1642 if (lagg_protos[pr].pr_ioctl != NULL) { 1643 error = lagg_protos[pr].pr_ioctl(var->lv_psc, 1644 &lreq->lrq_reqproto); 1645 } 1646 1647 done: 1648 if (var != NULL) 1649 lagg_variant_putref(var, &psref); 1650 curlwp_bindx(bound); 1651 return error; 1652 } 1653 1654 static int 1655 lagg_pr_attach(struct lagg_softc *sc, lagg_proto pr) 1656 { 1657 struct lagg_variant *newvar, *oldvar; 1658 struct lagg_proto_softc *psc; 1659 int error; 1660 1661 error = 0; 1662 newvar = kmem_alloc(sizeof(*newvar), KM_SLEEP); 1663 1664 LAGG_LOCK(sc); 1665 oldvar = sc->sc_var; 1666 1667 if (oldvar != NULL && oldvar->lv_proto == pr) { 1668 error = 0; 1669 goto failed; 1670 } 1671 1672 error = lagg_proto_attach(sc, pr, &psc); 1673 if (error != 0) 1674 goto failed; 1675 1676 newvar->lv_proto = pr; 1677 newvar->lv_psc = psc; 1678 lagg_variant_update(sc, newvar); 1679 lagg_set_linkspeed(sc, 0); 1680 LAGG_UNLOCK(sc); 1681 1682 if (oldvar != NULL) { 1683 lagg_proto_detach(oldvar); 1684 kmem_free(oldvar, sizeof(*oldvar)); 1685 } 1686 1687 return 0; 1688 1689 failed: 1690 LAGG_UNLOCK(sc); 1691 kmem_free(newvar, sizeof(*newvar)); 1692 1693 return error; 1694 } 1695 1696 static void 1697 lagg_pr_detach(struct lagg_softc *sc) 1698 { 1699 struct lagg_variant *var; 1700 1701 LAGG_LOCK(sc); 1702 var = sc->sc_var; 1703 atomic_store_release(&sc->sc_var, NULL); 1704 LAGG_UNLOCK(sc); 1705 pserialize_perform(sc->sc_psz); 1706 1707 if (var != NULL) 1708 lagg_proto_detach(var); 1709 1710 1711 if (var != NULL) 1712 kmem_free(var, sizeof(*var)); 1713 } 1714 1715 static int 1716 lagg_ether_addmulti(struct lagg_softc *sc, struct ifreq *ifr) 1717 { 1718 struct lagg_port *lp; 1719 struct lagg_mc_entry *mc; 1720 struct ethercom *ec; 1721 const struct sockaddr *sa; 1722 uint8_t addrlo[ETHER_ADDR_LEN], addrhi[ETHER_ADDR_LEN]; 1723 int error; 1724 1725 if (sc->sc_if.if_type != IFT_ETHER) 1726 return EPROTONOSUPPORT; 1727 1728 ec = (struct ethercom *)&sc->sc_if; 1729 sa = ifreq_getaddr(SIOCADDMULTI, ifr); 1730 1731 error = ether_addmulti(sa, ec); 1732 if (error != ENETRESET) 1733 return error; 1734 1735 error = ether_multiaddr(sa, addrlo, addrhi); 1736 KASSERT(error == 0); 1737 1738 mc = kmem_zalloc(sizeof(*mc), KM_SLEEP); 1739 1740 ETHER_LOCK(ec); 1741 mc->mc_enm = ether_lookup_multi(addrlo, addrhi, ec); 1742 ETHER_UNLOCK(ec); 1743 1744 KASSERT(mc->mc_enm != NULL); 1745 1746 LAGG_LOCK(sc); 1747 LAGG_PORTS_FOREACH(sc, lp) { 1748 (void)lagg_lp_ioctl(lp, SIOCADDMULTI, (void *)ifr); 1749 } 1750 LAGG_UNLOCK(sc); 1751 1752 KASSERT(sa->sa_len <= sizeof(mc->mc_addr)); 1753 memcpy(&mc->mc_addr, sa, sa->sa_len); 1754 LIST_INSERT_HEAD(&sc->sc_mclist, mc, mc_entry); 1755 1756 return 0; 1757 } 1758 1759 static int 1760 lagg_ether_delmulti(struct lagg_softc *sc, struct ifreq *ifr) 1761 { 1762 struct lagg_port *lp; 1763 struct lagg_mc_entry *mc; 1764 const struct sockaddr *sa; 1765 struct ethercom *ec; 1766 struct ether_multi *enm; 1767 uint8_t addrlo[ETHER_ADDR_LEN], addrhi[ETHER_ADDR_LEN]; 1768 int error; 1769 1770 ec = (struct ethercom *)&sc->sc_if; 1771 sa = ifreq_getaddr(SIOCDELMULTI, ifr); 1772 error = ether_multiaddr(sa, addrlo, addrhi); 1773 if (error != 0) 1774 return error; 1775 1776 ETHER_LOCK(ec); 1777 enm = ether_lookup_multi(addrlo, addrhi, ec); 1778 ETHER_UNLOCK(ec); 1779 1780 if (enm == NULL) 1781 return ENOENT; 1782 1783 LIST_FOREACH(mc, &sc->sc_mclist, mc_entry) { 1784 if (mc->mc_enm == enm) 1785 break; 1786 } 1787 1788 if (mc == NULL) 1789 return ENOENT; 1790 1791 error = ether_delmulti(sa, ec); 1792 if (error != ENETRESET) 1793 return error; 1794 1795 LAGG_LOCK(sc); 1796 LAGG_PORTS_FOREACH(sc, lp) { 1797 (void)lagg_lp_ioctl(lp, SIOCDELMULTI, (void *)ifr); 1798 } 1799 LAGG_UNLOCK(sc); 1800 1801 LIST_REMOVE(mc, mc_entry); 1802 kmem_free(mc, sizeof(*mc)); 1803 1804 return 0; 1805 } 1806 1807 static void 1808 lagg_port_multi(struct lagg_softc *sc, struct lagg_port *lp, 1809 u_long cmd) 1810 { 1811 struct lagg_mc_entry *mc; 1812 struct ifreq ifr; 1813 struct ifnet *ifp_port; 1814 const struct sockaddr *sa; 1815 1816 ifp_port = lp->lp_ifp; 1817 1818 memset(&ifr, 0, sizeof(ifr)); 1819 strlcpy(ifr.ifr_name, ifp_port->if_xname, sizeof(ifr.ifr_name)); 1820 1821 LIST_FOREACH(mc, &sc->sc_mclist, mc_entry) { 1822 sa = (struct sockaddr *)&mc->mc_addr; 1823 KASSERT(sizeof(ifr.ifr_space) >= sa->sa_len); 1824 memcpy(&ifr.ifr_addr, sa, sa->sa_len); 1825 (void)lagg_lp_ioctl(lp, cmd, (void *)&ifr); 1826 } 1827 1828 } 1829 1830 static void 1831 lagg_port_syncmulti(struct lagg_softc *sc, struct lagg_port *lp) 1832 { 1833 1834 lagg_port_multi(sc, lp, SIOCADDMULTI); 1835 } 1836 1837 static void 1838 lagg_port_purgemulti(struct lagg_softc *sc, struct lagg_port *lp) 1839 { 1840 1841 lagg_port_multi(sc, lp, SIOCDELMULTI); 1842 } 1843 1844 static void 1845 lagg_port_vlan(struct lagg_softc *sc, struct lagg_port *lp, 1846 bool set) 1847 { 1848 struct lagg_vlantag *lvt; 1849 int error; 1850 1851 TAILQ_FOREACH(lvt, &sc->sc_vtags, lvt_entry) { 1852 error = lagg_port_vlan_cb(lp, lvt, set); 1853 if (error != 0) { 1854 LAGG_LOG(sc, LOG_WARNING, 1855 "%s failed to configure vlan on %d\n", 1856 lp->lp_ifp->if_xname, error); 1857 } 1858 } 1859 } 1860 1861 static void 1862 lagg_port_syncvlan(struct lagg_softc *sc, struct lagg_port *lp) 1863 1864 { 1865 lagg_port_vlan(sc, lp, true); 1866 } 1867 1868 static void 1869 lagg_port_purgevlan(struct lagg_softc *sc, struct lagg_port *lp) 1870 { 1871 1872 lagg_port_vlan(sc, lp, false); 1873 } 1874 1875 static int 1876 lagg_setifcaps(struct lagg_port *lp, uint64_t cap) 1877 { 1878 struct ifcapreq ifcr; 1879 int error; 1880 1881 if (lp->lp_ifp->if_capenable == cap) 1882 return 0; 1883 1884 memset(&ifcr, 0, sizeof(ifcr)); 1885 ifcr.ifcr_capenable = cap; 1886 1887 IFNET_LOCK(lp->lp_ifp); 1888 error = LAGG_PORT_IOCTL(lp, SIOCSIFCAP, &ifcr); 1889 IFNET_UNLOCK(lp->lp_ifp); 1890 1891 return error; 1892 } 1893 1894 static void 1895 lagg_sync_ifcaps(struct lagg_softc *sc) 1896 { 1897 struct lagg_port *lp; 1898 struct ifnet *ifp; 1899 int error = 0; 1900 1901 ifp = (struct ifnet *)&sc->sc_if; 1902 1903 LAGG_LOCK(sc); 1904 LAGG_PORTS_FOREACH(sc, lp) { 1905 error = lagg_setifcaps(lp, ifp->if_capenable); 1906 1907 if (error != 0) { 1908 LAGG_LOG(sc, LOG_WARNING, 1909 "failed to update capabilities " 1910 "of %s, error=%d\n", 1911 lp->lp_ifp->if_xname, error); 1912 } 1913 } 1914 LAGG_UNLOCK(sc); 1915 } 1916 1917 static int 1918 lagg_setethcaps(struct lagg_port *lp, int cap) 1919 { 1920 struct ethercom *ec; 1921 struct eccapreq eccr; 1922 int error; 1923 1924 KASSERT(lp->lp_iftype == IFT_ETHER); 1925 ec = (struct ethercom *)lp->lp_ifp; 1926 1927 if (ec->ec_capenable == cap) 1928 return 0; 1929 1930 memset(&eccr, 0, sizeof(eccr)); 1931 eccr.eccr_capenable = cap; 1932 1933 IFNET_LOCK(lp->lp_ifp); 1934 error = LAGG_PORT_IOCTL(lp, SIOCSETHERCAP, &eccr); 1935 IFNET_UNLOCK(lp->lp_ifp); 1936 1937 return error; 1938 } 1939 1940 static void 1941 lagg_sync_ethcaps(struct lagg_softc *sc) 1942 { 1943 struct ethercom *ec; 1944 struct lagg_port *lp; 1945 int error; 1946 1947 ec = (struct ethercom *)&sc->sc_if; 1948 1949 LAGG_LOCK(sc); 1950 LAGG_PORTS_FOREACH(sc, lp) { 1951 if (lp->lp_iftype != IFT_ETHER) 1952 continue; 1953 1954 error = lagg_setethcaps(lp, ec->ec_capenable); 1955 if (error != 0) { 1956 LAGG_LOG(sc, LOG_WARNING, 1957 "failed to update ether " 1958 "capabilities"" of %s, error=%d\n", 1959 lp->lp_ifp->if_xname, error); 1960 } 1961 1962 } 1963 LAGG_UNLOCK(sc); 1964 } 1965 1966 static void 1967 lagg_ifcap_update(struct lagg_softc *sc) 1968 { 1969 struct ifnet *ifp; 1970 struct lagg_port *lp; 1971 uint64_t cap, ena, pena; 1972 size_t i; 1973 1974 KASSERT(LAGG_LOCKED(sc)); 1975 1976 /* Get common capabilities for the lagg ports */ 1977 ena = ~(uint64_t)0; 1978 cap = ~(uint64_t)0; 1979 LAGG_PORTS_FOREACH(sc, lp) { 1980 ena &= lp->lp_ifp->if_capenable; 1981 cap &= lp->lp_ifp->if_capabilities; 1982 } 1983 1984 if (ena == ~(uint64_t)0) 1985 ena = 0; 1986 if (cap == ~(uint64_t)0) 1987 cap = 0; 1988 1989 /* 1990 * Apply common enabled capabilities back to the lagg ports. 1991 * May require several iterations if they are dependent. 1992 */ 1993 for (i = 0; i < LAGG_SETCAPS_RETRY; i++) { 1994 pena = ena; 1995 LAGG_PORTS_FOREACH(sc, lp) { 1996 lagg_setifcaps(lp, ena); 1997 ena &= lp->lp_ifp->if_capenable; 1998 } 1999 2000 if (pena == ena) 2001 break; 2002 } 2003 2004 if (pena != ena) { 2005 LAGG_LOG(sc, LOG_DEBUG, "couldn't set " 2006 "capabilities 0x%08"PRIx64"\n", pena); 2007 } 2008 2009 ifp = &sc->sc_if; 2010 2011 if (ifp->if_capabilities != cap || 2012 ifp->if_capenable != ena) { 2013 ifp->if_capabilities = cap; 2014 ifp->if_capenable = ena; 2015 2016 LAGG_LOG(sc, LOG_DEBUG,"capabilities " 2017 "0x%08"PRIx64" enabled 0x%08"PRIx64"\n", 2018 cap, ena); 2019 } 2020 } 2021 2022 static void 2023 lagg_ethercap_update(struct lagg_softc *sc) 2024 { 2025 struct ethercom *ec; 2026 struct lagg_port *lp; 2027 int cap, ena, pena; 2028 size_t i; 2029 2030 KASSERT(LAGG_LOCKED(sc)); 2031 2032 if (sc->sc_if.if_type != IFT_ETHER) 2033 return; 2034 2035 if (SIMPLEQ_EMPTY(&sc->sc_ports)) { 2036 ena = 0; 2037 cap = ETHERCAP_VLAN_HWTAGGING; 2038 } else { 2039 /* Get common enabled capabilities for the lagg ports */ 2040 ena = ~0; 2041 cap = ~0; 2042 LAGG_PORTS_FOREACH(sc, lp) { 2043 switch (lp->lp_iftype) { 2044 case IFT_ETHER: 2045 ec = (struct ethercom *)lp->lp_ifp; 2046 ena &= ec->ec_capenable; 2047 cap &= ec->ec_capabilities; 2048 break; 2049 case IFT_L2TP: 2050 ena &= (ETHERCAP_VLAN_MTU | ETHERCAP_JUMBO_MTU); 2051 cap &= (ETHERCAP_VLAN_MTU | ETHERCAP_JUMBO_MTU); 2052 break; 2053 default: 2054 ena = 0; 2055 cap = 0; 2056 } 2057 } 2058 } 2059 2060 /* 2061 * Apply common enabled capabilities back to the lagg ports. 2062 * May require several iterations if they are dependent. 2063 */ 2064 for (i = 0; i < LAGG_SETCAPS_RETRY; i++) { 2065 pena = ena; 2066 LAGG_PORTS_FOREACH(sc, lp) { 2067 if (lp->lp_iftype != IFT_ETHER) 2068 continue; 2069 2070 ec = (struct ethercom *)lp->lp_ifp; 2071 lagg_setethcaps(lp, ena); 2072 ena &= ec->ec_capenable; 2073 } 2074 2075 if (pena == ena) 2076 break; 2077 } 2078 2079 if (pena != ena) { 2080 LAGG_LOG(sc, LOG_DEBUG, "couldn't set " 2081 "ether capabilities 0x%08x\n", pena); 2082 } 2083 2084 ec = (struct ethercom *)&sc->sc_if; 2085 2086 if (ec->ec_capabilities != cap || 2087 ec->ec_capenable != ena) { 2088 ec->ec_capabilities = cap; 2089 ec->ec_capenable = ena; 2090 2091 LAGG_LOG(sc, LOG_DEBUG, 2092 "ether capabilities 0x%08x" 2093 " enabled 0x%08x\n", cap, ena); 2094 } 2095 } 2096 2097 static void 2098 lagg_capabilities_update(struct lagg_softc *sc) 2099 { 2100 2101 lagg_ifcap_update(sc); 2102 lagg_ethercap_update(sc); 2103 } 2104 2105 static int 2106 lagg_setmtu(struct ifnet *ifp, uint64_t mtu) 2107 { 2108 struct lagg_softc *sc __LAGGDEBUGUSED; 2109 struct lagg_port *lp; 2110 struct ifreq ifr; 2111 int error; 2112 2113 KASSERT(IFNET_LOCKED(ifp)); 2114 2115 memset(&ifr, 0, sizeof(ifr)); 2116 ifr.ifr_mtu = mtu; 2117 lp = ifp->if_lagg; 2118 2119 if (lp != NULL) { 2120 /* ioctl for port interface */ 2121 error = lp->lp_ioctl(ifp, SIOCSIFMTU, &ifr); 2122 sc = lp->lp_softc; 2123 } else { 2124 /* ioctl for lagg interface */ 2125 error = ether_ioctl(ifp, SIOCSIFMTU, &ifr); 2126 sc = ifp->if_softc; 2127 } 2128 2129 if (error != 0) { 2130 LAGG_DPRINTF(sc, 2131 "couldn't change MTU for %s\n", 2132 ifp->if_xname); 2133 } 2134 2135 return error; 2136 } 2137 2138 static void 2139 lagg_port_setsadl(struct lagg_port *lp, const uint8_t *lladdr) 2140 { 2141 struct ifnet *ifp_port; 2142 int error; 2143 2144 ifp_port = lp->lp_ifp; 2145 2146 KASSERT(LAGG_LOCKED(lp->lp_softc)); 2147 KASSERT(IFNET_LOCKED(ifp_port)); 2148 2149 switch (lp->lp_iftype) { 2150 case IFT_ETHER: 2151 if (lladdr == NULL) { 2152 lladdr = lp->lp_lladdr; 2153 } else { 2154 if (lagg_lladdr_equal(lladdr, 2155 CLLADDR(ifp_port->if_sadl))) 2156 break; 2157 } 2158 2159 lagg_chg_sadl(ifp_port, 2160 lladdr, ETHER_ADDR_LEN); 2161 2162 if (ifp_port->if_init != NULL) { 2163 error = 0; 2164 /* Apply updated ifp_port->if_sadl to the device */ 2165 if (ISSET(ifp_port->if_flags, IFF_RUNNING)) 2166 error = if_init(ifp_port); 2167 2168 if (error != 0) { 2169 LAGG_LOG(lp->lp_softc, LOG_WARNING, 2170 "%s failed to if_init() on %d\n", 2171 ifp_port->if_xname, error); 2172 } 2173 } 2174 break; 2175 default: 2176 if_alloc_sadl(ifp_port); 2177 break; 2178 } 2179 } 2180 2181 static void 2182 lagg_if_setsadl(struct lagg_softc *sc, uint8_t *lladdr) 2183 { 2184 struct ifnet *ifp; 2185 2186 KASSERT(LAGG_LOCKED(sc)); 2187 2188 ifp = &sc->sc_if; 2189 2190 if (lagg_lladdr_equal(CLLADDR(ifp->if_sadl), lladdr)) 2191 return; 2192 2193 lagg_chg_sadl(ifp, lladdr, ETHER_ADDR_LEN); 2194 2195 LAGG_UNLOCK(sc); 2196 lagg_in6_ifdetach(ifp); 2197 lagg_in6_ifattach(ifp); 2198 LAGG_LOCK(sc); 2199 2200 lagg_sync_sadl(sc); 2201 } 2202 2203 static void 2204 lagg_sync_sadl(struct lagg_softc *sc) 2205 { 2206 struct ifnet *ifp; 2207 struct lagg_port *lp; 2208 const uint8_t *lla; 2209 2210 ifp = &sc->sc_if; 2211 KASSERT(IFNET_LOCKED(ifp)); 2212 2213 lla = CLLADDR(ifp->if_sadl); 2214 if (lagg_lladdr_equal(lla, sc->sc_lladdr)) 2215 return; 2216 2217 lagg_lladdr_cpy(sc->sc_lladdr, lla); 2218 2219 LAGG_PORTS_FOREACH(sc, lp) { 2220 IFNET_LOCK(lp->lp_ifp); 2221 lagg_port_setsadl(lp, lla); 2222 IFNET_UNLOCK(lp->lp_ifp); 2223 } 2224 } 2225 2226 static int 2227 lagg_port_setup(struct lagg_softc *sc, 2228 struct lagg_port *lp, struct ifnet *ifp_port) 2229 { 2230 struct ifnet *ifp; 2231 u_char if_type; 2232 int error; 2233 bool stopped, use_lagg_sadl; 2234 2235 KASSERT(LAGG_LOCKED(sc)); 2236 IFNET_ASSERT_UNLOCKED(ifp_port); 2237 2238 ifp = &sc->sc_if; 2239 2240 use_lagg_sadl = true; 2241 if (SIMPLEQ_EMPTY(&sc->sc_ports) && 2242 ifp_port->if_type == IFT_ETHER) { 2243 if (lagg_lladdr_equal(CLLADDR(ifp->if_sadl), 2244 sc->sc_lladdr_rand)) 2245 use_lagg_sadl = false; 2246 } 2247 2248 if (&sc->sc_if == ifp_port) { 2249 LAGG_DPRINTF(sc, "cannot add a lagg to itself as a port\n"); 2250 return EINVAL; 2251 } 2252 2253 if (sc->sc_nports > LAGG_MAX_PORTS) 2254 return ENOSPC; 2255 2256 if (ifp_port->if_lagg != NULL) { 2257 lp = (struct lagg_port *)ifp_port->if_lagg; 2258 if (lp->lp_softc == sc) 2259 return EEXIST; 2260 return EBUSY; 2261 } 2262 2263 switch (ifp_port->if_type) { 2264 case IFT_ETHER: 2265 case IFT_L2TP: 2266 if (VLAN_ATTACHED((struct ethercom *)ifp_port)) 2267 return EBUSY; 2268 2269 if_type = IFT_IEEE8023ADLAG; 2270 break; 2271 default: 2272 return ENOTSUP; 2273 } 2274 2275 error = 0; 2276 stopped = false; 2277 lp->lp_softc = sc; 2278 lp->lp_prio = LAGG_PORT_PRIO; 2279 lp->lp_linkstate_hook = if_linkstate_change_establish(ifp_port, 2280 lagg_linkstate_changed, ifp_port); 2281 lp->lp_ifdetach_hook = ether_ifdetachhook_establish(ifp_port, 2282 lagg_ifdetach, ifp_port); 2283 psref_target_init(&lp->lp_psref, lagg_port_psref_class); 2284 2285 IFNET_LOCK(ifp_port); 2286 /* stop packet processing */ 2287 if (ISSET(ifp_port->if_flags, IFF_RUNNING) && 2288 ifp_port->if_init != NULL) { 2289 if_stop(ifp_port, 0); 2290 stopped = true; 2291 } 2292 2293 /* to delete ipv6 link local address */ 2294 lagg_in6_ifdetach(ifp_port); 2295 2296 /* backup members */ 2297 lp->lp_iftype = ifp_port->if_type; 2298 lp->lp_ioctl = ifp_port->if_ioctl; 2299 lp->lp_input = ifp_port->_if_input; 2300 lp->lp_output = ifp_port->if_output; 2301 lp->lp_ifcapenable = ifp_port->if_capenable; 2302 lp->lp_mtu = ifp_port->if_mtu; 2303 if (lp->lp_iftype == IFT_ETHER) { 2304 struct ethercom *ec; 2305 ec = (struct ethercom *)ifp_port; 2306 2307 lagg_lladdr_cpy(lp->lp_lladdr, CLLADDR(ifp_port->if_sadl)); 2308 lp->lp_eccapenable = ec->ec_capenable; 2309 } 2310 2311 /* change callbacks and others */ 2312 atomic_store_release(&ifp_port->if_lagg, (void *)lp); 2313 ifp_port->if_type = if_type; 2314 ifp_port->if_ioctl = lagg_port_ioctl; 2315 ifp_port->_if_input = lagg_input_ethernet; 2316 ifp_port->if_output = lagg_port_output; 2317 2318 /* update Link address */ 2319 if (use_lagg_sadl) { 2320 lagg_port_setsadl(lp, CLLADDR(ifp->if_sadl)); 2321 } else { 2322 /* update if_type in if_sadl */ 2323 if (lp->lp_iftype != ifp_port->if_type) 2324 lagg_port_setsadl(lp, NULL); 2325 } 2326 2327 error = lagg_setmtu(ifp_port, ifp->if_mtu); 2328 if (error != 0) 2329 goto restore_sadl; 2330 2331 error = lagg_proto_allocport(sc, lp); 2332 if (error != 0) 2333 goto restore_mtu; 2334 2335 /* restart packet processing */ 2336 if (stopped) { 2337 error = if_init(ifp_port); 2338 if (error != 0) 2339 goto free_port; 2340 } 2341 2342 /* setup of ifp_port is complete */ 2343 IFNET_UNLOCK(ifp_port); 2344 2345 /* copy sadl from added port to lagg */ 2346 if (!use_lagg_sadl) 2347 lagg_if_setsadl(sc, lp->lp_lladdr); 2348 2349 SIMPLEQ_INSERT_TAIL(&sc->sc_ports, lp, lp_entry); 2350 sc->sc_nports++; 2351 2352 lagg_capabilities_update(sc); 2353 lagg_port_syncmulti(sc, lp); 2354 lagg_port_syncvlan(sc, lp); 2355 lagg_config_promisc(sc, lp); 2356 2357 lagg_proto_startport(sc, lp); 2358 2359 return 0; 2360 2361 free_port: 2362 KASSERT(IFNET_LOCKED(ifp_port)); 2363 lagg_proto_freeport(sc, lp); 2364 restore_mtu: 2365 KASSERT(IFNET_LOCKED(ifp_port)); 2366 if (ifp_port->if_mtu != lp->lp_mtu) 2367 lagg_setmtu(ifp_port, lp->lp_mtu); 2368 restore_sadl: 2369 KASSERT(IFNET_LOCKED(ifp_port)); 2370 2371 /* restore if_type before changing sadl */ 2372 if_type = ifp_port->if_type; 2373 ifp_port->if_type = lp->lp_iftype; 2374 2375 if (!SIMPLEQ_EMPTY(&sc->sc_ports)) { 2376 lagg_port_setsadl(lp, lp->lp_lladdr); 2377 } else { 2378 if (ifp_port->if_type != if_type) 2379 lagg_port_setsadl(lp, NULL); 2380 } 2381 2382 lagg_in6_ifattach(ifp_port); 2383 if (stopped) { 2384 if (if_init(ifp_port) != 0) { 2385 LAGG_LOG(sc, LOG_WARNING, 2386 "couldn't re-start port %s\n", 2387 ifp_port->if_xname); 2388 } 2389 } 2390 2391 ifp_port->if_ioctl = lp->lp_ioctl; 2392 ifp_port->_if_input = lp->lp_input; 2393 ifp_port->if_output = lp->lp_output; 2394 atomic_store_release(&ifp_port->if_lagg, NULL); 2395 IFNET_UNLOCK(ifp_port); 2396 2397 psref_target_destroy(&lp->lp_psref, lagg_port_psref_class); 2398 if_linkstate_change_disestablish(ifp_port, 2399 lp->lp_linkstate_hook, NULL); 2400 ether_ifdetachhook_disestablish(ifp_port, 2401 lp->lp_ifdetach_hook, &sc->sc_lock); 2402 2403 return error; 2404 } 2405 2406 static void 2407 lagg_port_teardown(struct lagg_softc *sc, struct lagg_port *lp, 2408 bool is_ifdetach) 2409 { 2410 struct ifnet *ifp, *ifp_port; 2411 bool stopped, is_1st_port, iftype_changed; 2412 2413 KASSERT(LAGG_LOCKED(sc)); 2414 2415 ifp = &sc->sc_if; 2416 ifp_port = lp->lp_ifp; 2417 stopped = false; 2418 is_1st_port = 2419 SIMPLEQ_FIRST(&sc->sc_ports) == lp ? true : false; 2420 2421 ether_ifdetachhook_disestablish(ifp_port, 2422 lp->lp_ifdetach_hook, &sc->sc_lock); 2423 2424 if (ifp_port->if_lagg == NULL) { 2425 /* already done in lagg_ifdetach() */ 2426 return; 2427 } 2428 2429 if_linkstate_change_disestablish(ifp_port, 2430 lp->lp_linkstate_hook, NULL); 2431 2432 lagg_proto_stopport(sc, lp); 2433 2434 lagg_port_purgemulti(sc, lp); 2435 lagg_port_purgevlan(sc, lp); 2436 if (is_ifdetach == false) { 2437 lagg_unconfig_promisc(sc, lp); 2438 lagg_setifcaps(lp, lp->lp_ifcapenable); 2439 if (lp->lp_iftype == IFT_ETHER) 2440 lagg_setethcaps(lp, lp->lp_eccapenable); 2441 } 2442 2443 SIMPLEQ_REMOVE(&sc->sc_ports, lp, lagg_port, lp_entry); 2444 sc->sc_nports--; 2445 2446 if (is_1st_port) { 2447 if (lp->lp_iftype == IFT_ETHER && 2448 lagg_lladdr_equal(lp->lp_lladdr, 2449 CLLADDR(ifp->if_sadl))) { 2450 struct lagg_port *lp0; 2451 uint8_t *lla; 2452 2453 lp0 = SIMPLEQ_FIRST(&sc->sc_ports); 2454 if (lp0 != NULL && 2455 lp0->lp_iftype == IFT_ETHER) { 2456 lla = lp0->lp_lladdr; 2457 } else { 2458 lla = sc->sc_lladdr_rand; 2459 } 2460 2461 lagg_if_setsadl(sc, lla); 2462 } 2463 } 2464 2465 IFNET_LOCK(ifp_port); 2466 /* stop packet processing */ 2467 if (ISSET(ifp_port->if_flags, IFF_RUNNING) && 2468 ifp_port->if_init != NULL) { 2469 if_stop(ifp_port, 0); 2470 stopped = true; 2471 } 2472 2473 lagg_proto_freeport(sc, lp); 2474 2475 /* change if_type before set sadl */ 2476 iftype_changed = ifp_port->if_type != lp->lp_iftype ? 2477 true : false; 2478 ifp_port->if_type = lp->lp_iftype; 2479 2480 if (is_ifdetach == false) { 2481 if (iftype_changed && 2482 lagg_lladdr_equal(CLLADDR(ifp_port->if_sadl), 2483 lp->lp_lladdr)) { 2484 lagg_port_setsadl(lp, NULL); 2485 } 2486 lagg_port_setsadl(lp, lp->lp_lladdr); 2487 lagg_in6_ifattach(ifp_port); 2488 (void)lagg_setmtu(ifp_port, lp->lp_mtu); 2489 } 2490 2491 ifp_port->_if_input = lp->lp_input; 2492 ifp_port->if_output = lp->lp_output; 2493 if (ifp_port->if_ioctl == lagg_port_ioctl) 2494 ifp_port->if_ioctl = lp->lp_ioctl; 2495 atomic_store_release(&ifp_port->if_lagg, NULL); 2496 pserialize_perform(sc->sc_psz); 2497 2498 /* to assign ipv6 link local address */ 2499 if (is_ifdetach == false) { 2500 lagg_in6_ifattach(ifp_port); 2501 } 2502 2503 /* restart packet processing */ 2504 if (stopped) { 2505 int error; 2506 error = if_init(ifp_port); 2507 if (error != 0) { 2508 LAGG_LOG(sc, LOG_WARNING, 2509 "%s failed to if_init() on %d\n", 2510 ifp_port->if_xname, error); 2511 } 2512 } 2513 IFNET_UNLOCK(ifp_port); 2514 2515 psref_target_destroy(&lp->lp_psref, lagg_port_psref_class); 2516 kmem_free(lp, sizeof(*lp)); 2517 } 2518 2519 static int 2520 lagg_addport(struct lagg_softc *sc, struct ifnet *ifp_port) 2521 { 2522 struct lagg_port *lp; 2523 int error; 2524 2525 lp = kmem_zalloc(sizeof(*lp), KM_SLEEP); 2526 lp->lp_ifp = ifp_port; 2527 2528 LAGG_LOCK(sc); 2529 error = lagg_port_setup(sc, lp, ifp_port); 2530 LAGG_UNLOCK(sc); 2531 2532 if (error != 0) 2533 kmem_free(lp, sizeof(*lp)); 2534 2535 return error; 2536 } 2537 2538 static int 2539 lagg_delport(struct lagg_softc *sc, struct ifnet *ifp_port) 2540 { 2541 struct lagg_port *lp; 2542 int error; 2543 2544 KASSERT(IFNET_LOCKED(&sc->sc_if)); 2545 2546 error = 0; 2547 LAGG_LOCK(sc); 2548 lp = ifp_port->if_lagg; 2549 if (lp == NULL || lp->lp_softc != sc) { 2550 error = ENOENT; 2551 goto out; 2552 } 2553 2554 if (lp->lp_ifdetaching) { 2555 error = EBUSY; 2556 goto out; 2557 } 2558 2559 lagg_port_teardown(sc, lp, false); 2560 2561 out: 2562 LAGG_UNLOCK(sc); 2563 2564 return error; 2565 } 2566 2567 static int 2568 lagg_delport_all(struct lagg_softc *sc) 2569 { 2570 struct lagg_port *lp; 2571 int error; 2572 2573 KASSERT(IFNET_LOCKED(&sc->sc_if)); 2574 2575 error = 0; 2576 2577 LAGG_LOCK(sc); 2578 while ((lp = LAGG_PORTS_FIRST(sc)) != NULL) { 2579 if (lp->lp_ifdetaching) { 2580 error = EBUSY; 2581 continue; 2582 } 2583 2584 lagg_port_teardown(sc, lp, false); 2585 } 2586 2587 LAGG_UNLOCK(sc); 2588 2589 return error; 2590 } 2591 2592 static int 2593 lagg_get_stats(struct lagg_softc *sc, struct lagg_req *resp, 2594 size_t nports) 2595 { 2596 struct lagg_variant *var; 2597 struct lagg_port *lp; 2598 struct laggreqport *port; 2599 struct psref psref; 2600 struct ifnet *ifp; 2601 int bound; 2602 size_t n; 2603 2604 bound = curlwp_bind(); 2605 var = lagg_variant_getref(sc, &psref); 2606 if (var == NULL) { 2607 curlwp_bindx(bound); 2608 return ENOENT; 2609 } 2610 2611 resp->lrq_proto = var->lv_proto; 2612 2613 lagg_proto_stat(var, &resp->lrq_reqproto); 2614 2615 n = 0; 2616 LAGG_LOCK(sc); 2617 LAGG_PORTS_FOREACH(sc, lp) { 2618 if (n < nports) { 2619 port = &resp->lrq_reqports[n]; 2620 2621 ifp = lp->lp_ifp; 2622 strlcpy(port->rp_portname, ifp->if_xname, 2623 sizeof(port->rp_portname)); 2624 2625 port->rp_prio = lp->lp_prio; 2626 port->rp_flags = lp->lp_flags; 2627 lagg_proto_portstat(var, lp, port); 2628 } 2629 n++; 2630 } 2631 LAGG_UNLOCK(sc); 2632 2633 resp->lrq_nports = n; 2634 2635 lagg_variant_putref(var, &psref); 2636 curlwp_bindx(bound); 2637 2638 if (resp->lrq_nports > nports) { 2639 return ENOBUFS; 2640 } 2641 return 0; 2642 } 2643 2644 static void 2645 lagg_config_promisc(struct lagg_softc *sc, struct lagg_port *lp) 2646 { 2647 struct ifnet *ifp, *ifp_port; 2648 int error; 2649 bool promisc; 2650 2651 KASSERT(LAGG_LOCKED(sc)); 2652 2653 ifp = &sc->sc_if; 2654 ifp_port = lp->lp_ifp; 2655 2656 if (lp->lp_iftype == IFT_ETHER) { 2657 promisc = ISSET(ifp->if_flags, IFF_PROMISC) ? 2658 true : false; 2659 } else { 2660 promisc = true; 2661 } 2662 2663 if (lp->lp_promisc == promisc) 2664 return; 2665 2666 error = ifpromisc(ifp_port, promisc ? 1 : 0); 2667 if (error == ENETRESET) { 2668 error = ifp_port->if_init(ifp_port); 2669 } 2670 2671 if (error == 0) { 2672 lp->lp_promisc = promisc; 2673 } else { 2674 LAGG_LOG(sc, LOG_WARNING, 2675 "couldn't %s promisc on %s\n", 2676 promisc ? "set" : "unset", 2677 ifp_port->if_xname); 2678 } 2679 } 2680 2681 static void 2682 lagg_unconfig_promisc(struct lagg_softc *sc, struct lagg_port *lp) 2683 { 2684 struct ifnet *ifp_port; 2685 int error; 2686 2687 KASSERT(LAGG_LOCKED(sc)); 2688 2689 ifp_port = lp->lp_ifp; 2690 2691 if (lp->lp_promisc == false) 2692 return; 2693 2694 error = ifpromisc(ifp_port, 0); 2695 if (error == ENETRESET) { 2696 error = ifp_port->if_init(ifp_port); 2697 } 2698 2699 if (error != 0) { 2700 LAGG_LOG(sc, LOG_WARNING, 2701 "couldn't unset promisc on %s\n", 2702 ifp_port->if_xname); 2703 } 2704 } 2705 2706 static int 2707 lagg_port_ioctl(struct ifnet *ifp, u_long cmd, void *data) 2708 { 2709 struct lagg_softc *sc; 2710 struct lagg_port *lp; 2711 int error = 0; 2712 u_int ifflags; 2713 2714 if ((lp = ifp->if_lagg) == NULL) 2715 goto fallback; 2716 2717 sc = lp->lp_softc; 2718 KASSERT(sc != NULL); 2719 2720 KASSERT(IFNET_LOCKED(lp->lp_ifp)); 2721 2722 switch (cmd) { 2723 case SIOCSIFCAP: 2724 case SIOCSIFMTU: 2725 case SIOCSETHERCAP: 2726 /* Do not allow the setting to be changed once joined */ 2727 error = EINVAL; 2728 break; 2729 case SIOCSIFFLAGS: 2730 ifflags = ifp->if_flags; 2731 error = LAGG_PORT_IOCTL(lp, cmd, data); 2732 ifflags ^= ifp->if_flags; 2733 2734 if ((ifflags & (IFF_UP | IFF_RUNNING)) != 0) 2735 lagg_proto_linkstate(sc, lp); 2736 break; 2737 default: 2738 goto fallback; 2739 } 2740 2741 return error; 2742 fallback: 2743 if (lp != NULL) { 2744 error = LAGG_PORT_IOCTL(lp, cmd, data); 2745 } else { 2746 error = ENOTTY; 2747 } 2748 2749 return error; 2750 } 2751 2752 static int 2753 lagg_port_output(struct ifnet *ifp, struct mbuf *m, 2754 const struct sockaddr *dst, const struct rtentry *rt) 2755 { 2756 struct lagg_port *lp = ifp->if_lagg; 2757 int error = 0; 2758 2759 switch (dst->sa_family) { 2760 case pseudo_AF_HDRCMPLT: 2761 case AF_UNSPEC: 2762 if (lp != NULL) 2763 error = lp->lp_output(ifp, m, dst, rt); 2764 else 2765 error = ENETDOWN; 2766 break; 2767 default: 2768 m_freem(m); 2769 error = ENETDOWN; 2770 } 2771 2772 return error; 2773 } 2774 2775 void 2776 lagg_ifdetach(void *xifp_port) 2777 { 2778 struct ifnet *ifp_port = xifp_port; 2779 struct lagg_port *lp; 2780 struct lagg_softc *sc; 2781 int s; 2782 2783 IFNET_ASSERT_UNLOCKED(ifp_port); 2784 2785 s = pserialize_read_enter(); 2786 lp = atomic_load_consume(&ifp_port->if_lagg); 2787 if (lp == NULL) { 2788 pserialize_read_exit(s); 2789 return; 2790 } else { 2791 sc = lp->lp_softc; 2792 KASSERT(sc != NULL); 2793 } 2794 pserialize_read_exit(s); 2795 2796 LAGG_LOCK(sc); 2797 lp = ifp_port->if_lagg; 2798 if (lp == NULL) { 2799 LAGG_UNLOCK(sc); 2800 return; 2801 } 2802 2803 /* 2804 * mark as a detaching to prevent other 2805 * lagg_port_teardown() processings with IFNET_LOCK() held 2806 */ 2807 lp->lp_ifdetaching = true; 2808 2809 LAGG_UNLOCK(sc); 2810 2811 IFNET_LOCK(&sc->sc_if); 2812 LAGG_LOCK(sc); 2813 lp = ifp_port->if_lagg; 2814 if (lp != NULL) { 2815 lagg_port_teardown(sc, lp, true); 2816 } 2817 LAGG_UNLOCK(sc); 2818 IFNET_UNLOCK(&sc->sc_if); 2819 } 2820 2821 void 2822 lagg_linkstate_changed(void *xifp) 2823 { 2824 struct ifnet *ifp = xifp; 2825 struct lagg_port *lp; 2826 struct psref psref; 2827 int s, bound; 2828 2829 s = pserialize_read_enter(); 2830 lp = atomic_load_consume(&ifp->if_lagg); 2831 if (lp != NULL) { 2832 bound = curlwp_bind(); 2833 lagg_port_getref(lp, &psref); 2834 } else { 2835 pserialize_read_exit(s); 2836 return; 2837 } 2838 pserialize_read_exit(s); 2839 2840 KASSERT(IFNET_LOCKED(lp->lp_ifp)); 2841 2842 lagg_proto_linkstate(lp->lp_softc, lp); 2843 2844 lagg_port_putref(lp, &psref); 2845 curlwp_bindx(bound); 2846 } 2847 2848 void 2849 lagg_port_getref(struct lagg_port *lp, struct psref *psref) 2850 { 2851 2852 psref_acquire(psref, &lp->lp_psref, lagg_port_psref_class); 2853 } 2854 2855 void 2856 lagg_port_putref(struct lagg_port *lp, struct psref *psref) 2857 { 2858 2859 psref_release(psref, &lp->lp_psref, lagg_port_psref_class); 2860 } 2861 2862 static void 2863 lagg_workq_work(struct work *wk, void *context) 2864 { 2865 struct lagg_work *lw; 2866 2867 lw = container_of(wk, struct lagg_work, lw_cookie); 2868 2869 atomic_cas_uint(&lw->lw_state, LAGG_WORK_ENQUEUED, LAGG_WORK_IDLE); 2870 lw->lw_func(lw, lw->lw_arg); 2871 } 2872 2873 struct workqueue * 2874 lagg_workq_create(const char *name, pri_t prio, int ipl, int flags) 2875 { 2876 struct workqueue *wq; 2877 int error; 2878 2879 error = workqueue_create(&wq, name, lagg_workq_work, 2880 NULL, prio, ipl, flags); 2881 2882 if (error) 2883 return NULL; 2884 2885 return wq; 2886 } 2887 2888 void 2889 lagg_workq_destroy(struct workqueue *wq) 2890 { 2891 2892 workqueue_destroy(wq); 2893 } 2894 2895 void 2896 lagg_workq_add(struct workqueue *wq, struct lagg_work *lw) 2897 { 2898 2899 if (atomic_cas_uint(&lw->lw_state, LAGG_WORK_IDLE, 2900 LAGG_WORK_ENQUEUED) != LAGG_WORK_IDLE) 2901 return; 2902 2903 KASSERT(lw->lw_func != NULL); 2904 kpreempt_disable(); 2905 workqueue_enqueue(wq, &lw->lw_cookie, NULL); 2906 kpreempt_enable(); 2907 } 2908 2909 void 2910 lagg_workq_wait(struct workqueue *wq, struct lagg_work *lw) 2911 { 2912 2913 atomic_swap_uint(&lw->lw_state, LAGG_WORK_STOPPING); 2914 workqueue_wait(wq, &lw->lw_cookie); 2915 } 2916 2917 static int 2918 lagg_chg_sadl(struct ifnet *ifp, const uint8_t *lla, size_t lla_len) 2919 { 2920 struct psref psref_cur, psref_next; 2921 struct ifaddr *ifa_cur, *ifa_next, *ifa_lla; 2922 const struct sockaddr_dl *sdl, *nsdl; 2923 int s, error; 2924 2925 KASSERT(!cpu_intr_p() && !cpu_softintr_p()); 2926 KASSERT(IFNET_LOCKED(ifp)); 2927 KASSERT(ifp->if_addrlen == lla_len); 2928 2929 error = 0; 2930 ifa_lla = NULL; 2931 2932 /* Renew all AF_LINK address to update sdl_type */ 2933 while (1) { 2934 /* find a Link-Level address that has the previous sdl_type */ 2935 s = pserialize_read_enter(); 2936 IFADDR_READER_FOREACH(ifa_cur, ifp) { 2937 sdl = satocsdl(ifa_cur->ifa_addr); 2938 if (sdl->sdl_family != AF_LINK) 2939 continue; 2940 2941 if (sdl->sdl_type != ifp->if_type) { 2942 ifa_acquire(ifa_cur, &psref_cur); 2943 break; 2944 } 2945 } 2946 pserialize_read_exit(s); 2947 2948 if (ifa_cur == NULL) 2949 break; 2950 /* 2951 * create a new address that has new sdl_type, 2952 * and copy address from the previous. 2953 */ 2954 ifa_next = if_dl_create(ifp, &nsdl); 2955 if (ifa_next == NULL) { 2956 error = ENOMEM; 2957 ifa_release(ifa_cur, &psref_cur); 2958 goto done; 2959 } 2960 ifa_acquire(ifa_next, &psref_next); 2961 (void)sockaddr_dl_setaddr(__UNCONST(nsdl), nsdl->sdl_len, 2962 CLLADDR(sdl), ifp->if_addrlen); 2963 ifa_insert(ifp, ifa_next); 2964 2965 /* the next Link-Level address is already set */ 2966 if (ifa_lla == NULL && 2967 memcmp(CLLADDR(sdl), lla, lla_len) == 0) { 2968 ifa_lla = ifa_next; 2969 ifaref(ifa_lla); 2970 } 2971 2972 if (ifa_cur == ifp->if_dl) 2973 if_activate_sadl(ifp, ifa_next, nsdl); 2974 2975 if (ifa_cur == ifp->if_hwdl) { 2976 ifp->if_hwdl = ifa_next; 2977 ifaref(ifa_next); 2978 ifafree(ifa_cur); 2979 } 2980 2981 /* remove the old address */ 2982 ifaref(ifa_cur); 2983 ifa_release(ifa_cur, &psref_cur); 2984 ifa_remove(ifp, ifa_cur); 2985 KASSERTMSG(ifa_cur->ifa_refcnt == 1, 2986 "ifa_refcnt=%d", ifa_cur->ifa_refcnt); 2987 ifafree(ifa_cur); 2988 ifa_release(ifa_next, &psref_next); 2989 } 2990 2991 /* acquire or create the next Link-Level address */ 2992 if (ifa_lla != NULL) { 2993 ifa_next = ifa_lla; 2994 2995 ifa_acquire(ifa_next, &psref_next); 2996 ifafree(ifa_lla); 2997 2998 nsdl = satocsdl(ifa_next->ifa_addr); 2999 } else { 3000 ifa_next = if_dl_create(ifp, &nsdl); 3001 if (ifa_next == NULL) { 3002 error = ENOMEM; 3003 goto done; 3004 } 3005 ifa_acquire(ifa_next, &psref_next); 3006 (void)sockaddr_dl_setaddr(__UNCONST(nsdl), 3007 nsdl->sdl_len, lla, ifp->if_addrlen); 3008 ifa_insert(ifp, ifa_next); 3009 } 3010 3011 /* Activate the next Link-Level address */ 3012 if (__predict_true(ifa_next != ifp->if_dl)) { 3013 /* save the current address */ 3014 ifa_cur = ifp->if_dl; 3015 if (ifa_cur != NULL) 3016 ifa_acquire(ifa_cur, &psref_cur); 3017 3018 if_activate_sadl(ifp, ifa_next, nsdl); 3019 3020 /* 3021 * free the saved address after switching, 3022 * if the address is not if_hwdl. 3023 */ 3024 if (ifa_cur != NULL) { 3025 if (ifa_cur != ifp->if_hwdl) { 3026 ifaref(ifa_cur); 3027 ifa_release(ifa_cur, &psref_cur); 3028 ifa_remove(ifp, ifa_cur); 3029 KASSERTMSG(ifa_cur->ifa_refcnt == 1, 3030 "ifa_refcnt=%d", 3031 ifa_cur->ifa_refcnt); 3032 ifafree(ifa_cur); 3033 } else { 3034 ifa_release(ifa_cur, &psref_cur); 3035 } 3036 } 3037 } 3038 3039 ifa_release(ifa_next, &psref_next); 3040 3041 done: 3042 return error; 3043 } 3044 3045 /* 3046 * Module infrastructure 3047 */ 3048 #include <net/if_module.h> 3049 3050 IF_MODULE(MODULE_CLASS_DRIVER, lagg, NULL) 3051