if_lagg.c (169340) | if_lagg.c (169569) |
---|---|
1/* $OpenBSD: if_trunk.c,v 1.30 2007/01/31 06:20:19 reyk Exp $ */ 2 3/* 4 * Copyright (c) 2005, 2006 Reyk Floeter <reyk@openbsd.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19#include <sys/cdefs.h> | 1/* $OpenBSD: if_trunk.c,v 1.30 2007/01/31 06:20:19 reyk Exp $ */ 2 3/* 4 * Copyright (c) 2005, 2006 Reyk Floeter <reyk@openbsd.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19#include <sys/cdefs.h> |
20__FBSDID("$FreeBSD: head/sys/net/if_lagg.c 169340 2007-05-07 09:53:02Z thompsa $"); | 20__FBSDID("$FreeBSD: head/sys/net/if_lagg.c 169569 2007-05-15 07:41:46Z thompsa $"); |
21 22#include "opt_inet.h" 23#include "opt_inet6.h" 24 25#include <sys/param.h> 26#include <sys/kernel.h> 27#include <sys/malloc.h> 28#include <sys/mbuf.h> 29#include <sys/queue.h> 30#include <sys/socket.h> 31#include <sys/sockio.h> 32#include <sys/sysctl.h> 33#include <sys/module.h> 34#include <sys/priv.h> 35#include <sys/systm.h> 36#include <sys/proc.h> 37#include <sys/hash.h> | 21 22#include "opt_inet.h" 23#include "opt_inet6.h" 24 25#include <sys/param.h> 26#include <sys/kernel.h> 27#include <sys/malloc.h> 28#include <sys/mbuf.h> 29#include <sys/queue.h> 30#include <sys/socket.h> 31#include <sys/sockio.h> 32#include <sys/sysctl.h> 33#include <sys/module.h> 34#include <sys/priv.h> 35#include <sys/systm.h> 36#include <sys/proc.h> 37#include <sys/hash.h> |
38#include <sys/lock.h> 39#include <sys/rwlock.h> |
|
38#include <sys/taskqueue.h> 39 40#include <net/ethernet.h> 41#include <net/if.h> 42#include <net/if_clone.h> 43#include <net/if_arp.h> 44#include <net/if_dl.h> 45#include <net/if_llc.h> --- 211 unchanged lines hidden (view full) --- 257} 258 259static void 260lagg_clone_destroy(struct ifnet *ifp) 261{ 262 struct lagg_softc *sc = (struct lagg_softc *)ifp->if_softc; 263 struct lagg_port *lp; 264 | 40#include <sys/taskqueue.h> 41 42#include <net/ethernet.h> 43#include <net/if.h> 44#include <net/if_clone.h> 45#include <net/if_arp.h> 46#include <net/if_dl.h> 47#include <net/if_llc.h> --- 211 unchanged lines hidden (view full) --- 259} 260 261static void 262lagg_clone_destroy(struct ifnet *ifp) 263{ 264 struct lagg_softc *sc = (struct lagg_softc *)ifp->if_softc; 265 struct lagg_port *lp; 266 |
265 LAGG_LOCK(sc); | 267 LAGG_WLOCK(sc); |
266 267 lagg_stop(sc); 268 ifp->if_flags &= ~IFF_UP; 269 270 /* Shutdown and remove lagg ports */ 271 while ((lp = SLIST_FIRST(&sc->sc_ports)) != NULL) 272 lagg_port_destroy(lp, 1); 273 /* Unhook the aggregation protocol */ 274 if (sc->sc_detach != NULL) 275 (*sc->sc_detach)(sc); 276 | 268 269 lagg_stop(sc); 270 ifp->if_flags &= ~IFF_UP; 271 272 /* Shutdown and remove lagg ports */ 273 while ((lp = SLIST_FIRST(&sc->sc_ports)) != NULL) 274 lagg_port_destroy(lp, 1); 275 /* Unhook the aggregation protocol */ 276 if (sc->sc_detach != NULL) 277 (*sc->sc_detach)(sc); 278 |
277 LAGG_UNLOCK(sc); | 279 LAGG_WUNLOCK(sc); |
278 279 ifmedia_removeall(&sc->sc_media); 280 ether_ifdetach(ifp); 281 if_free_type(ifp, IFT_ETHER); 282 283 mtx_lock(&lagg_list_mtx); 284 SLIST_REMOVE(&lagg_list, sc, lagg_softc, sc_entries); 285 mtx_unlock(&lagg_list_mtx); --- 18 unchanged lines hidden (view full) --- 304} 305 306static int 307lagg_capabilities(struct lagg_softc *sc) 308{ 309 struct lagg_port *lp; 310 int cap = ~0, priv; 311 | 280 281 ifmedia_removeall(&sc->sc_media); 282 ether_ifdetach(ifp); 283 if_free_type(ifp, IFT_ETHER); 284 285 mtx_lock(&lagg_list_mtx); 286 SLIST_REMOVE(&lagg_list, sc, lagg_softc, sc_entries); 287 mtx_unlock(&lagg_list_mtx); --- 18 unchanged lines hidden (view full) --- 306} 307 308static int 309lagg_capabilities(struct lagg_softc *sc) 310{ 311 struct lagg_port *lp; 312 int cap = ~0, priv; 313 |
312 LAGG_LOCK_ASSERT(sc); | 314 LAGG_WLOCK_ASSERT(sc); |
313 314 /* Preserve private capabilities */ 315 priv = sc->sc_capabilities & IFCAP_LAGG_MASK; 316 317 /* Get capabilities from the lagg ports */ 318 SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) 319 cap &= lp->lp_capabilities; 320 --- 8 unchanged lines hidden (view full) --- 329static void 330lagg_port_lladdr(struct lagg_port *lp, uint8_t *lladdr) 331{ 332 struct lagg_softc *sc = lp->lp_lagg; 333 struct ifnet *ifp = lp->lp_ifp; 334 struct lagg_llq *llq; 335 int pending = 0; 336 | 315 316 /* Preserve private capabilities */ 317 priv = sc->sc_capabilities & IFCAP_LAGG_MASK; 318 319 /* Get capabilities from the lagg ports */ 320 SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) 321 cap &= lp->lp_capabilities; 322 --- 8 unchanged lines hidden (view full) --- 331static void 332lagg_port_lladdr(struct lagg_port *lp, uint8_t *lladdr) 333{ 334 struct lagg_softc *sc = lp->lp_lagg; 335 struct ifnet *ifp = lp->lp_ifp; 336 struct lagg_llq *llq; 337 int pending = 0; 338 |
337 LAGG_LOCK_ASSERT(sc); | 339 LAGG_WLOCK_ASSERT(sc); |
338 339 if (lp->lp_detaching || 340 memcmp(lladdr, IF_LLADDR(ifp), ETHER_ADDR_LEN) == 0) 341 return; 342 343 /* Check to make sure its not already queued to be changed */ 344 SLIST_FOREACH(llq, &sc->sc_llq_head, llq_entries) { 345 if (llq->llq_ifp == ifp) { --- 25 unchanged lines hidden (view full) --- 371lagg_port_setlladdr(void *arg, int pending) 372{ 373 struct lagg_softc *sc = (struct lagg_softc *)arg; 374 struct lagg_llq *llq, *head; 375 struct ifnet *ifp; 376 int error; 377 378 /* Grab a local reference of the queue and remove it from the softc */ | 340 341 if (lp->lp_detaching || 342 memcmp(lladdr, IF_LLADDR(ifp), ETHER_ADDR_LEN) == 0) 343 return; 344 345 /* Check to make sure its not already queued to be changed */ 346 SLIST_FOREACH(llq, &sc->sc_llq_head, llq_entries) { 347 if (llq->llq_ifp == ifp) { --- 25 unchanged lines hidden (view full) --- 373lagg_port_setlladdr(void *arg, int pending) 374{ 375 struct lagg_softc *sc = (struct lagg_softc *)arg; 376 struct lagg_llq *llq, *head; 377 struct ifnet *ifp; 378 int error; 379 380 /* Grab a local reference of the queue and remove it from the softc */ |
379 LAGG_LOCK(sc); | 381 LAGG_WLOCK(sc); |
380 head = SLIST_FIRST(&sc->sc_llq_head); 381 SLIST_FIRST(&sc->sc_llq_head) = NULL; | 382 head = SLIST_FIRST(&sc->sc_llq_head); 383 SLIST_FIRST(&sc->sc_llq_head) = NULL; |
382 LAGG_UNLOCK(sc); | 384 LAGG_WUNLOCK(sc); |
383 384 /* 385 * Traverse the queue and set the lladdr on each ifp. It is safe to do 386 * unlocked as we have the only reference to it. 387 */ 388 for (llq = head; llq != NULL; llq = head) { 389 ifp = llq->llq_ifp; 390 --- 10 unchanged lines hidden (view full) --- 401 402static int 403lagg_port_create(struct lagg_softc *sc, struct ifnet *ifp) 404{ 405 struct lagg_softc *sc_ptr; 406 struct lagg_port *lp; 407 int error = 0; 408 | 385 386 /* 387 * Traverse the queue and set the lladdr on each ifp. It is safe to do 388 * unlocked as we have the only reference to it. 389 */ 390 for (llq = head; llq != NULL; llq = head) { 391 ifp = llq->llq_ifp; 392 --- 10 unchanged lines hidden (view full) --- 403 404static int 405lagg_port_create(struct lagg_softc *sc, struct ifnet *ifp) 406{ 407 struct lagg_softc *sc_ptr; 408 struct lagg_port *lp; 409 int error = 0; 410 |
409 LAGG_LOCK_ASSERT(sc); | 411 LAGG_WLOCK_ASSERT(sc); |
410 411 /* Limit the maximal number of lagg ports */ 412 if (sc->sc_count >= LAGG_MAX_PORTS) 413 return (ENOSPC); 414 415 /* New lagg port has to be in an idle state */ 416 if (ifp->if_drv_flags & IFF_DRV_OACTIVE) 417 return (EBUSY); --- 77 unchanged lines hidden (view full) --- 495 496static int 497lagg_port_checkstacking(struct lagg_softc *sc) 498{ 499 struct lagg_softc *sc_ptr; 500 struct lagg_port *lp; 501 int m = 0; 502 | 412 413 /* Limit the maximal number of lagg ports */ 414 if (sc->sc_count >= LAGG_MAX_PORTS) 415 return (ENOSPC); 416 417 /* New lagg port has to be in an idle state */ 418 if (ifp->if_drv_flags & IFF_DRV_OACTIVE) 419 return (EBUSY); --- 77 unchanged lines hidden (view full) --- 497 498static int 499lagg_port_checkstacking(struct lagg_softc *sc) 500{ 501 struct lagg_softc *sc_ptr; 502 struct lagg_port *lp; 503 int m = 0; 504 |
503 LAGG_LOCK_ASSERT(sc); | 505 LAGG_WLOCK_ASSERT(sc); |
504 505 SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) { 506 if (lp->lp_flags & LAGG_PORT_STACK) { 507 sc_ptr = (struct lagg_softc *)lp->lp_ifp->if_softc; 508 m = MAX(m, lagg_port_checkstacking(sc_ptr)); 509 } 510 } 511 512 return (m + 1); 513} 514 515static int 516lagg_port_destroy(struct lagg_port *lp, int runpd) 517{ 518 struct lagg_softc *sc = lp->lp_lagg; 519 struct lagg_port *lp_ptr; 520 struct lagg_llq *llq; 521 struct ifnet *ifp = lp->lp_ifp; 522 | 506 507 SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) { 508 if (lp->lp_flags & LAGG_PORT_STACK) { 509 sc_ptr = (struct lagg_softc *)lp->lp_ifp->if_softc; 510 m = MAX(m, lagg_port_checkstacking(sc_ptr)); 511 } 512 } 513 514 return (m + 1); 515} 516 517static int 518lagg_port_destroy(struct lagg_port *lp, int runpd) 519{ 520 struct lagg_softc *sc = lp->lp_lagg; 521 struct lagg_port *lp_ptr; 522 struct lagg_llq *llq; 523 struct ifnet *ifp = lp->lp_ifp; 524 |
523 LAGG_LOCK_ASSERT(sc); | 525 LAGG_WLOCK_ASSERT(sc); |
524 525 if (runpd && sc->sc_port_destroy != NULL) 526 (*sc->sc_port_destroy)(lp); 527 528 /* 529 * Remove multicast addresses and interface flags from this port and 530 * reset the MAC address, skip if the interface is being detached. 531 */ --- 64 unchanged lines hidden (view full) --- 596 597 /* Should be checked by the caller */ 598 if (ifp->if_type != IFT_IEEE8023ADLAG || 599 (lp = ifp->if_lagg) == NULL || (sc = lp->lp_lagg) == NULL) 600 goto fallback; 601 602 switch (cmd) { 603 case SIOCGLAGGPORT: | 526 527 if (runpd && sc->sc_port_destroy != NULL) 528 (*sc->sc_port_destroy)(lp); 529 530 /* 531 * Remove multicast addresses and interface flags from this port and 532 * reset the MAC address, skip if the interface is being detached. 533 */ --- 64 unchanged lines hidden (view full) --- 598 599 /* Should be checked by the caller */ 600 if (ifp->if_type != IFT_IEEE8023ADLAG || 601 (lp = ifp->if_lagg) == NULL || (sc = lp->lp_lagg) == NULL) 602 goto fallback; 603 604 switch (cmd) { 605 case SIOCGLAGGPORT: |
604 LAGG_LOCK(sc); | 606 LAGG_RLOCK(sc); |
605 if (rp->rp_portname[0] == '\0' || 606 ifunit(rp->rp_portname) != ifp) { 607 error = EINVAL; 608 break; 609 } 610 611 if (lp->lp_lagg != sc) { 612 error = ENOENT; 613 break; 614 } 615 616 lagg_port2req(lp, rp); | 607 if (rp->rp_portname[0] == '\0' || 608 ifunit(rp->rp_portname) != ifp) { 609 error = EINVAL; 610 break; 611 } 612 613 if (lp->lp_lagg != sc) { 614 error = ENOENT; 615 break; 616 } 617 618 lagg_port2req(lp, rp); |
617 LAGG_UNLOCK(sc); | 619 LAGG_RUNLOCK(sc); |
618 break; 619 default: 620 goto fallback; 621 } 622 623 return (error); 624 625fallback: --- 39 unchanged lines hidden (view full) --- 665 struct lagg_port *lp; 666 struct lagg_softc *sc; 667 668 if ((lp = ifp->if_lagg) == NULL) 669 return; 670 671 sc = lp->lp_lagg; 672 | 620 break; 621 default: 622 goto fallback; 623 } 624 625 return (error); 626 627fallback: --- 39 unchanged lines hidden (view full) --- 667 struct lagg_port *lp; 668 struct lagg_softc *sc; 669 670 if ((lp = ifp->if_lagg) == NULL) 671 return; 672 673 sc = lp->lp_lagg; 674 |
673 LAGG_LOCK(sc); | 675 LAGG_WLOCK(sc); |
674 lp->lp_detaching = 1; 675 lagg_port_destroy(lp, 1); | 676 lp->lp_detaching = 1; 677 lagg_port_destroy(lp, 1); |
676 LAGG_UNLOCK(sc); | 678 LAGG_WUNLOCK(sc); |
677} 678 679static void 680lagg_port2req(struct lagg_port *lp, struct lagg_reqport *rp) 681{ 682 struct lagg_softc *sc = lp->lp_lagg; 683 strlcpy(rp->rp_ifname, sc->sc_ifname, sizeof(rp->rp_ifname)); 684 strlcpy(rp->rp_portname, lp->lp_ifp->if_xname, sizeof(rp->rp_portname)); --- 27 unchanged lines hidden (view full) --- 712{ 713 struct lagg_softc *sc = (struct lagg_softc *)xsc; 714 struct lagg_port *lp; 715 struct ifnet *ifp = sc->sc_ifp; 716 717 if (ifp->if_drv_flags & IFF_DRV_RUNNING) 718 return; 719 | 679} 680 681static void 682lagg_port2req(struct lagg_port *lp, struct lagg_reqport *rp) 683{ 684 struct lagg_softc *sc = lp->lp_lagg; 685 strlcpy(rp->rp_ifname, sc->sc_ifname, sizeof(rp->rp_ifname)); 686 strlcpy(rp->rp_portname, lp->lp_ifp->if_xname, sizeof(rp->rp_portname)); --- 27 unchanged lines hidden (view full) --- 714{ 715 struct lagg_softc *sc = (struct lagg_softc *)xsc; 716 struct lagg_port *lp; 717 struct ifnet *ifp = sc->sc_ifp; 718 719 if (ifp->if_drv_flags & IFF_DRV_RUNNING) 720 return; 721 |
720 LAGG_LOCK(sc); | 722 LAGG_WLOCK(sc); |
721 722 ifp->if_drv_flags |= IFF_DRV_RUNNING; 723 /* Update the port lladdrs */ 724 SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) 725 lagg_port_lladdr(lp, IF_LLADDR(ifp)); 726 727 if (sc->sc_init != NULL) 728 (*sc->sc_init)(sc); 729 | 723 724 ifp->if_drv_flags |= IFF_DRV_RUNNING; 725 /* Update the port lladdrs */ 726 SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) 727 lagg_port_lladdr(lp, IF_LLADDR(ifp)); 728 729 if (sc->sc_init != NULL) 730 (*sc->sc_init)(sc); 731 |
730 LAGG_UNLOCK(sc); | 732 LAGG_WUNLOCK(sc); |
731} 732 733static void 734lagg_stop(struct lagg_softc *sc) 735{ 736 struct ifnet *ifp = sc->sc_ifp; 737 | 733} 734 735static void 736lagg_stop(struct lagg_softc *sc) 737{ 738 struct ifnet *ifp = sc->sc_ifp; 739 |
738 LAGG_LOCK_ASSERT(sc); | 740 LAGG_WLOCK_ASSERT(sc); |
739 740 if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) 741 return; 742 743 ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 744 745 if (sc->sc_stop != NULL) 746 (*sc->sc_stop)(sc); --- 6 unchanged lines hidden (view full) --- 753 struct lagg_reqall *ra = (struct lagg_reqall *)data; 754 struct lagg_reqport *rp = (struct lagg_reqport *)data, rpbuf; 755 struct ifreq *ifr = (struct ifreq *)data; 756 struct lagg_port *lp; 757 struct ifnet *tpif; 758 struct thread *td = curthread; 759 int i, error = 0, unlock = 1; 760 | 741 742 if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) 743 return; 744 745 ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 746 747 if (sc->sc_stop != NULL) 748 (*sc->sc_stop)(sc); --- 6 unchanged lines hidden (view full) --- 755 struct lagg_reqall *ra = (struct lagg_reqall *)data; 756 struct lagg_reqport *rp = (struct lagg_reqport *)data, rpbuf; 757 struct ifreq *ifr = (struct ifreq *)data; 758 struct lagg_port *lp; 759 struct ifnet *tpif; 760 struct thread *td = curthread; 761 int i, error = 0, unlock = 1; 762 |
761 LAGG_LOCK(sc); | 763 LAGG_WLOCK(sc); |
762 763 bzero(&rpbuf, sizeof(rpbuf)); 764 765 switch (cmd) { 766 case SIOCGLAGG: 767 ra->ra_proto = sc->sc_proto; 768 ra->ra_ports = i = 0; 769 lp = SLIST_FIRST(&sc->sc_ports); --- 106 unchanged lines hidden (view full) --- 876 */ 877 lagg_stop(sc); 878 } else if ((ifp->if_flags & IFF_UP) && 879 !(ifp->if_drv_flags & IFF_DRV_RUNNING)) { 880 /* 881 * If interface is marked up and it is stopped, then 882 * start it. 883 */ | 764 765 bzero(&rpbuf, sizeof(rpbuf)); 766 767 switch (cmd) { 768 case SIOCGLAGG: 769 ra->ra_proto = sc->sc_proto; 770 ra->ra_ports = i = 0; 771 lp = SLIST_FIRST(&sc->sc_ports); --- 106 unchanged lines hidden (view full) --- 878 */ 879 lagg_stop(sc); 880 } else if ((ifp->if_flags & IFF_UP) && 881 !(ifp->if_drv_flags & IFF_DRV_RUNNING)) { 882 /* 883 * If interface is marked up and it is stopped, then 884 * start it. 885 */ |
884 LAGG_UNLOCK(sc); | 886 LAGG_WUNLOCK(sc); |
885 unlock = 0; 886 (*ifp->if_init)(sc); 887 } 888 break; 889 case SIOCADDMULTI: 890 case SIOCDELMULTI: 891 error = lagg_ether_setmulti(sc); 892 break; 893 case SIOCSIFMEDIA: 894 case SIOCGIFMEDIA: | 887 unlock = 0; 888 (*ifp->if_init)(sc); 889 } 890 break; 891 case SIOCADDMULTI: 892 case SIOCDELMULTI: 893 error = lagg_ether_setmulti(sc); 894 break; 895 case SIOCSIFMEDIA: 896 case SIOCGIFMEDIA: |
895 LAGG_UNLOCK(sc); | 897 LAGG_WUNLOCK(sc); |
896 unlock = 0; 897 error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd); 898 break; 899 default: | 898 unlock = 0; 899 error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd); 900 break; 901 default: |
900 LAGG_UNLOCK(sc); | 902 LAGG_WUNLOCK(sc); |
901 unlock = 0; 902 error = ether_ioctl(ifp, cmd, data); 903 break; 904 } 905 906out: 907 if (unlock) | 903 unlock = 0; 904 error = ether_ioctl(ifp, cmd, data); 905 break; 906 } 907 908out: 909 if (unlock) |
908 LAGG_UNLOCK(sc); | 910 LAGG_WUNLOCK(sc); |
909 return (error); 910} 911 912static int 913lagg_ether_setmulti(struct lagg_softc *sc) 914{ 915 struct lagg_port *lp; 916 | 911 return (error); 912} 913 914static int 915lagg_ether_setmulti(struct lagg_softc *sc) 916{ 917 struct lagg_port *lp; 918 |
917 LAGG_LOCK_ASSERT(sc); | 919 LAGG_WLOCK_ASSERT(sc); |
918 919 SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) { 920 /* First, remove any existing filter entries. */ 921 lagg_ether_cmdmulti(lp, 0); 922 /* copy all addresses from the lagg interface to the port */ 923 lagg_ether_cmdmulti(lp, 1); 924 } 925 return (0); --- 5 unchanged lines hidden (view full) --- 931 struct lagg_softc *sc = lp->lp_lagg; 932 struct ifnet *ifp = lp->lp_ifp; 933 struct ifnet *trifp = sc->sc_ifp; 934 struct lagg_mc *mc; 935 struct ifmultiaddr *ifma, *rifma = NULL; 936 struct sockaddr_dl sdl; 937 int error; 938 | 920 921 SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) { 922 /* First, remove any existing filter entries. */ 923 lagg_ether_cmdmulti(lp, 0); 924 /* copy all addresses from the lagg interface to the port */ 925 lagg_ether_cmdmulti(lp, 1); 926 } 927 return (0); --- 5 unchanged lines hidden (view full) --- 933 struct lagg_softc *sc = lp->lp_lagg; 934 struct ifnet *ifp = lp->lp_ifp; 935 struct ifnet *trifp = sc->sc_ifp; 936 struct lagg_mc *mc; 937 struct ifmultiaddr *ifma, *rifma = NULL; 938 struct sockaddr_dl sdl; 939 int error; 940 |
939 LAGG_LOCK_ASSERT(sc); | 941 LAGG_WLOCK_ASSERT(sc); |
940 941 bzero((char *)&sdl, sizeof(sdl)); 942 sdl.sdl_len = sizeof(sdl); 943 sdl.sdl_family = AF_LINK; 944 sdl.sdl_type = IFT_ETHER; 945 sdl.sdl_alen = ETHER_ADDR_LEN; 946 sdl.sdl_index = ifp->if_index; 947 --- 28 unchanged lines hidden (view full) --- 976lagg_setflag(struct lagg_port *lp, int flag, int status, 977 int (*func)(struct ifnet *, int)) 978{ 979 struct lagg_softc *sc = lp->lp_lagg; 980 struct ifnet *trifp = sc->sc_ifp; 981 struct ifnet *ifp = lp->lp_ifp; 982 int error; 983 | 942 943 bzero((char *)&sdl, sizeof(sdl)); 944 sdl.sdl_len = sizeof(sdl); 945 sdl.sdl_family = AF_LINK; 946 sdl.sdl_type = IFT_ETHER; 947 sdl.sdl_alen = ETHER_ADDR_LEN; 948 sdl.sdl_index = ifp->if_index; 949 --- 28 unchanged lines hidden (view full) --- 978lagg_setflag(struct lagg_port *lp, int flag, int status, 979 int (*func)(struct ifnet *, int)) 980{ 981 struct lagg_softc *sc = lp->lp_lagg; 982 struct ifnet *trifp = sc->sc_ifp; 983 struct ifnet *ifp = lp->lp_ifp; 984 int error; 985 |
984 LAGG_LOCK_ASSERT(sc); | 986 LAGG_WLOCK_ASSERT(sc); |
985 986 status = status ? (trifp->if_flags & flag) : 0; 987 /* Now "status" contains the flag value or 0 */ 988 989 /* 990 * See if recorded ports status is different from what 991 * we want it to be. If it is, flip it. We record ports 992 * status in lp_ifflags so that we won't clear ports flag --- 33 unchanged lines hidden (view full) --- 1026 1027static void 1028lagg_start(struct ifnet *ifp) 1029{ 1030 struct lagg_softc *sc = (struct lagg_softc *)ifp->if_softc; 1031 struct mbuf *m; 1032 int error = 0; 1033 | 987 988 status = status ? (trifp->if_flags & flag) : 0; 989 /* Now "status" contains the flag value or 0 */ 990 991 /* 992 * See if recorded ports status is different from what 993 * we want it to be. If it is, flip it. We record ports 994 * status in lp_ifflags so that we won't clear ports flag --- 33 unchanged lines hidden (view full) --- 1028 1029static void 1030lagg_start(struct ifnet *ifp) 1031{ 1032 struct lagg_softc *sc = (struct lagg_softc *)ifp->if_softc; 1033 struct mbuf *m; 1034 int error = 0; 1035 |
1036 LAGG_RLOCK(sc); |
|
1034 for (;; error = 0) { 1035 IFQ_DEQUEUE(&ifp->if_snd, m); 1036 if (m == NULL) 1037 break; 1038 1039 BPF_MTAP(ifp, m); 1040 | 1037 for (;; error = 0) { 1038 IFQ_DEQUEUE(&ifp->if_snd, m); 1039 if (m == NULL) 1040 break; 1041 1042 BPF_MTAP(ifp, m); 1043 |
1041 if (sc->sc_proto != LAGG_PROTO_NONE) { 1042 LAGG_LOCK(sc); | 1044 if (sc->sc_proto != LAGG_PROTO_NONE) |
1043 error = (*sc->sc_start)(sc, m); | 1045 error = (*sc->sc_start)(sc, m); |
1044 LAGG_UNLOCK(sc); 1045 } else | 1046 else |
1046 m_free(m); 1047 1048 if (error == 0) 1049 ifp->if_opackets++; 1050 else 1051 ifp->if_oerrors++; 1052 } | 1047 m_free(m); 1048 1049 if (error == 0) 1050 ifp->if_opackets++; 1051 else 1052 ifp->if_oerrors++; 1053 } |
1054 LAGG_RUNLOCK(sc); |
|
1053 1054 return; 1055} 1056 1057static struct mbuf * 1058lagg_input(struct ifnet *ifp, struct mbuf *m) 1059{ 1060 struct lagg_port *lp = ifp->if_lagg; 1061 struct lagg_softc *sc = lp->lp_lagg; 1062 struct ifnet *trifp = sc->sc_ifp; 1063 1064 if ((trifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || 1065 (lp->lp_flags & LAGG_PORT_DISABLED) || 1066 sc->sc_proto == LAGG_PROTO_NONE) { 1067 m_freem(m); 1068 return (NULL); 1069 } 1070 | 1055 1056 return; 1057} 1058 1059static struct mbuf * 1060lagg_input(struct ifnet *ifp, struct mbuf *m) 1061{ 1062 struct lagg_port *lp = ifp->if_lagg; 1063 struct lagg_softc *sc = lp->lp_lagg; 1064 struct ifnet *trifp = sc->sc_ifp; 1065 1066 if ((trifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || 1067 (lp->lp_flags & LAGG_PORT_DISABLED) || 1068 sc->sc_proto == LAGG_PROTO_NONE) { 1069 m_freem(m); 1070 return (NULL); 1071 } 1072 |
1071 LAGG_LOCK(sc); | 1073 LAGG_RLOCK(sc); |
1072 BPF_MTAP(trifp, m); 1073 1074 m = (*sc->sc_input)(sc, lp, m); 1075 1076 if (m != NULL) { 1077 ifp->if_ipackets++; 1078 ifp->if_ibytes += m->m_pkthdr.len; 1079 trifp->if_ipackets++; 1080 trifp->if_ibytes += m->m_pkthdr.len; 1081 } 1082 | 1074 BPF_MTAP(trifp, m); 1075 1076 m = (*sc->sc_input)(sc, lp, m); 1077 1078 if (m != NULL) { 1079 ifp->if_ipackets++; 1080 ifp->if_ibytes += m->m_pkthdr.len; 1081 trifp->if_ipackets++; 1082 trifp->if_ibytes += m->m_pkthdr.len; 1083 } 1084 |
1083 LAGG_UNLOCK(sc); | 1085 LAGG_RUNLOCK(sc); |
1084 return (m); 1085} 1086 1087static int 1088lagg_media_change(struct ifnet *ifp) 1089{ 1090 struct lagg_softc *sc = (struct lagg_softc *)ifp->if_softc; 1091 --- 8 unchanged lines hidden (view full) --- 1100lagg_media_status(struct ifnet *ifp, struct ifmediareq *imr) 1101{ 1102 struct lagg_softc *sc = (struct lagg_softc *)ifp->if_softc; 1103 struct lagg_port *lp; 1104 1105 imr->ifm_status = IFM_AVALID; 1106 imr->ifm_active = IFM_ETHER | IFM_AUTO; 1107 | 1086 return (m); 1087} 1088 1089static int 1090lagg_media_change(struct ifnet *ifp) 1091{ 1092 struct lagg_softc *sc = (struct lagg_softc *)ifp->if_softc; 1093 --- 8 unchanged lines hidden (view full) --- 1102lagg_media_status(struct ifnet *ifp, struct ifmediareq *imr) 1103{ 1104 struct lagg_softc *sc = (struct lagg_softc *)ifp->if_softc; 1105 struct lagg_port *lp; 1106 1107 imr->ifm_status = IFM_AVALID; 1108 imr->ifm_active = IFM_ETHER | IFM_AUTO; 1109 |
1108 LAGG_LOCK(sc); | 1110 LAGG_RLOCK(sc); |
1109 SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) { 1110 if (LAGG_PORTACTIVE(lp)) 1111 imr->ifm_status |= IFM_ACTIVE; 1112 } | 1111 SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) { 1112 if (LAGG_PORTACTIVE(lp)) 1113 imr->ifm_status |= IFM_ACTIVE; 1114 } |
1113 LAGG_UNLOCK(sc); | 1115 LAGG_RUNLOCK(sc); |
1114} 1115 1116static void 1117lagg_port_state(struct ifnet *ifp, int state) 1118{ 1119 struct lagg_port *lp = (struct lagg_port *)ifp->if_lagg; 1120 struct lagg_softc *sc = NULL; 1121 1122 if (lp != NULL) 1123 sc = lp->lp_lagg; 1124 if (sc == NULL) 1125 return; 1126 | 1116} 1117 1118static void 1119lagg_port_state(struct ifnet *ifp, int state) 1120{ 1121 struct lagg_port *lp = (struct lagg_port *)ifp->if_lagg; 1122 struct lagg_softc *sc = NULL; 1123 1124 if (lp != NULL) 1125 sc = lp->lp_lagg; 1126 if (sc == NULL) 1127 return; 1128 |
1127 LAGG_LOCK(sc); | 1129 LAGG_WLOCK(sc); |
1128 if (sc->sc_linkstate != NULL) 1129 (*sc->sc_linkstate)(lp); | 1130 if (sc->sc_linkstate != NULL) 1131 (*sc->sc_linkstate)(lp); |
1130 LAGG_UNLOCK(sc); | 1132 LAGG_WUNLOCK(sc); |
1131} 1132 1133struct lagg_port * 1134lagg_link_active(struct lagg_softc *sc, struct lagg_port *lp) 1135{ 1136 struct lagg_port *lp_next, *rval = NULL; 1137 // int new_link = LINK_STATE_DOWN; 1138 | 1133} 1134 1135struct lagg_port * 1136lagg_link_active(struct lagg_softc *sc, struct lagg_port *lp) 1137{ 1138 struct lagg_port *lp_next, *rval = NULL; 1139 // int new_link = LINK_STATE_DOWN; 1140 |
1139 LAGG_LOCK_ASSERT(sc); | 1141 LAGG_WLOCK_ASSERT(sc); |
1140 /* 1141 * Search a port which reports an active link state. 1142 */ 1143 1144 if (lp == NULL) 1145 goto search; 1146 if (LAGG_PORTACTIVE(lp)) { 1147 rval = lp; --- 405 unchanged lines hidden (view full) --- 1553{ 1554 struct lagg_port *lp; 1555 int error; 1556 1557 SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) 1558 lacp_port_destroy(lp); 1559 1560 /* unlocking is safe here */ | 1142 /* 1143 * Search a port which reports an active link state. 1144 */ 1145 1146 if (lp == NULL) 1147 goto search; 1148 if (LAGG_PORTACTIVE(lp)) { 1149 rval = lp; --- 405 unchanged lines hidden (view full) --- 1555{ 1556 struct lagg_port *lp; 1557 int error; 1558 1559 SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) 1560 lacp_port_destroy(lp); 1561 1562 /* unlocking is safe here */ |
1561 LAGG_UNLOCK(sc); | 1563 LAGG_WUNLOCK(sc); |
1562 error = lacp_detach(sc); | 1564 error = lacp_detach(sc); |
1563 LAGG_LOCK(sc); | 1565 LAGG_WLOCK(sc); |
1564 1565 return (error); 1566} 1567 1568static void 1569lagg_lacp_lladdr(struct lagg_softc *sc) 1570{ 1571 struct lagg_port *lp; --- 21 unchanged lines hidden (view full) --- 1593} 1594 1595static struct mbuf * 1596lagg_lacp_input(struct lagg_softc *sc, struct lagg_port *lp, struct mbuf *m) 1597{ 1598 struct ifnet *ifp = sc->sc_ifp; 1599 struct ether_header *eh; 1600 u_short etype; | 1566 1567 return (error); 1568} 1569 1570static void 1571lagg_lacp_lladdr(struct lagg_softc *sc) 1572{ 1573 struct lagg_port *lp; --- 21 unchanged lines hidden (view full) --- 1595} 1596 1597static struct mbuf * 1598lagg_lacp_input(struct lagg_softc *sc, struct lagg_port *lp, struct mbuf *m) 1599{ 1600 struct ifnet *ifp = sc->sc_ifp; 1601 struct ether_header *eh; 1602 u_short etype; |
1601 uint8_t subtype; | |
1602 1603 eh = mtod(m, struct ether_header *); 1604 etype = ntohs(eh->ether_type); 1605 1606 /* Tap off LACP control messages */ 1607 if (etype == ETHERTYPE_SLOW) { | 1603 1604 eh = mtod(m, struct ether_header *); 1605 etype = ntohs(eh->ether_type); 1606 1607 /* Tap off LACP control messages */ 1608 if (etype == ETHERTYPE_SLOW) { |
1608 if (m->m_pkthdr.len < sizeof(*eh) + sizeof(subtype)) { 1609 m_freem(m); 1610 return (NULL); 1611 } 1612 1613 m_copydata(m, sizeof(*eh), sizeof(subtype), &subtype); 1614 switch (subtype) { 1615 case SLOWPROTOCOLS_SUBTYPE_LACP: 1616 lacp_input(lp, m); 1617 break; 1618 1619 case SLOWPROTOCOLS_SUBTYPE_MARKER: 1620 lacp_marker_input(lp, m); 1621 break; 1622 1623 default: 1624 /* Unknown LACP packet type */ 1625 m_freem(m); 1626 break; 1627 } | 1609 lacp_input(lp, m); |
1628 return (NULL); 1629 } 1630 1631 /* 1632 * If the port is not collecting or not in the active aggregator then 1633 * free and return. 1634 */ 1635 if ((lp->lp_flags & LAGG_PORT_COLLECTING) == 0 || 1636 lacp_port_isactive(lp) == 0) { 1637 m_freem(m); 1638 return (NULL); 1639 } 1640 1641 m->m_pkthdr.rcvif = ifp; 1642 return (m); 1643} | 1610 return (NULL); 1611 } 1612 1613 /* 1614 * If the port is not collecting or not in the active aggregator then 1615 * free and return. 1616 */ 1617 if ((lp->lp_flags & LAGG_PORT_COLLECTING) == 0 || 1618 lacp_port_isactive(lp) == 0) { 1619 m_freem(m); 1620 return (NULL); 1621 } 1622 1623 m->m_pkthdr.rcvif = ifp; 1624 return (m); 1625} |