Fix to call lacp_linkstate with IFNET_LOCK held Network stack calls lacp_linkstate through lagg_port_ioctl when doing "ifconfig up" or "ifconfig down" to an interface that is a member of lagg(4). And IFNET_LOCK in the member interface is held while the ioctl. Therefore, lacp_linkstate is renamed to lacp_linkstate_ifnet_locked, and always called with IFNET_LOCK held. It avoids locking agains myself.diff -r1.29 -r1.30 src/sys/net/lagg/if_lagg.c
(yamaguchi)
--- src/sys/net/lagg/if_lagg.c 2022/01/12 01:21:36 1.29
+++ src/sys/net/lagg/if_lagg.c 2022/01/12 08:23:53 1.30
@@ -1,36 +1,36 @@ | @@ -1,36 +1,36 @@ | |||
1 | /* $NetBSD: if_lagg.c,v 1.29 2022/01/12 01:21:36 riastradh Exp $ */ | 1 | /* $NetBSD: if_lagg.c,v 1.30 2022/01/12 08:23:53 yamaguchi Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright (c) 2005, 2006 Reyk Floeter <reyk@openbsd.org> | 4 | * Copyright (c) 2005, 2006 Reyk Floeter <reyk@openbsd.org> | |
5 | * Copyright (c) 2007 Andrew Thompson <thompsa@FreeBSD.org> | 5 | * Copyright (c) 2007 Andrew Thompson <thompsa@FreeBSD.org> | |
6 | * Copyright (c) 2014, 2016 Marcelo Araujo <araujo@FreeBSD.org> | 6 | * Copyright (c) 2014, 2016 Marcelo Araujo <araujo@FreeBSD.org> | |
7 | * Copyright (c) 2021, Internet Initiative Japan Inc. | 7 | * Copyright (c) 2021, Internet Initiative Japan Inc. | |
8 | * | 8 | * | |
9 | * Permission to use, copy, modify, and distribute this software for any | 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 | 10 | * purpose with or without fee is hereby granted, provided that the above | |
11 | * copyright notice and this permission notice appear in all copies. | 11 | * copyright notice and this permission notice appear in all copies. | |
12 | * | 12 | * | |
13 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | 13 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |
14 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | 14 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
15 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | 15 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |
16 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | 16 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
17 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | 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 | 18 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |
19 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 19 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
20 | */ | 20 | */ | |
21 | 21 | |||
22 | #include <sys/cdefs.h> | 22 | #include <sys/cdefs.h> | |
23 | __KERNEL_RCSID(0, "$NetBSD: if_lagg.c,v 1.29 2022/01/12 01:21:36 riastradh Exp $"); | 23 | __KERNEL_RCSID(0, "$NetBSD: if_lagg.c,v 1.30 2022/01/12 08:23:53 yamaguchi Exp $"); | |
24 | 24 | |||
25 | #ifdef _KERNEL_OPT | 25 | #ifdef _KERNEL_OPT | |
26 | #include "opt_inet.h" | 26 | #include "opt_inet.h" | |
27 | #include "opt_lagg.h" | 27 | #include "opt_lagg.h" | |
28 | #endif | 28 | #endif | |
29 | 29 | |||
30 | #include <sys/param.h> | 30 | #include <sys/param.h> | |
31 | #include <sys/types.h> | 31 | #include <sys/types.h> | |
32 | 32 | |||
33 | #include <sys/cprng.h> | 33 | #include <sys/cprng.h> | |
34 | #include <sys/cpu.h> | 34 | #include <sys/cpu.h> | |
35 | #include <sys/device.h> | 35 | #include <sys/device.h> | |
36 | #include <sys/evcnt.h> | 36 | #include <sys/evcnt.h> | |
@@ -92,27 +92,27 @@ static const struct lagg_proto lagg_prot | @@ -92,27 +92,27 @@ static const struct lagg_proto lagg_prot | |||
92 | .pr_num = LAGG_PROTO_LACP, | 92 | .pr_num = LAGG_PROTO_LACP, | |
93 | .pr_attach = lacp_attach, | 93 | .pr_attach = lacp_attach, | |
94 | .pr_detach = lacp_detach, | 94 | .pr_detach = lacp_detach, | |
95 | .pr_up = lacp_up, | 95 | .pr_up = lacp_up, | |
96 | .pr_down = lacp_down, | 96 | .pr_down = lacp_down, | |
97 | .pr_transmit = lacp_transmit, | 97 | .pr_transmit = lacp_transmit, | |
98 | .pr_input = lacp_input, | 98 | .pr_input = lacp_input, | |
99 | .pr_allocport = lacp_allocport, | 99 | .pr_allocport = lacp_allocport, | |
100 | .pr_freeport = lacp_freeport, | 100 | .pr_freeport = lacp_freeport, | |
101 | .pr_startport = lacp_startport, | 101 | .pr_startport = lacp_startport, | |
102 | .pr_stopport = lacp_stopport, | 102 | .pr_stopport = lacp_stopport, | |
103 | .pr_protostat = lacp_protostat, | 103 | .pr_protostat = lacp_protostat, | |
104 | .pr_portstat = lacp_portstat, | 104 | .pr_portstat = lacp_portstat, | |
105 | .pr_linkstate = lacp_linkstate, | 105 | .pr_linkstate = lacp_linkstate_ifnet_locked, | |
106 | .pr_ioctl = lacp_ioctl, | 106 | .pr_ioctl = lacp_ioctl, | |
107 | }, | 107 | }, | |
108 | [LAGG_PROTO_FAILOVER] = { | 108 | [LAGG_PROTO_FAILOVER] = { | |
109 | .pr_num = LAGG_PROTO_FAILOVER, | 109 | .pr_num = LAGG_PROTO_FAILOVER, | |
110 | .pr_attach = lagg_fail_attach, | 110 | .pr_attach = lagg_fail_attach, | |
111 | .pr_detach = lagg_common_detach, | 111 | .pr_detach = lagg_common_detach, | |
112 | .pr_transmit = lagg_fail_transmit, | 112 | .pr_transmit = lagg_fail_transmit, | |
113 | .pr_input = lagg_fail_input, | 113 | .pr_input = lagg_fail_input, | |
114 | .pr_allocport = lagg_common_allocport, | 114 | .pr_allocport = lagg_common_allocport, | |
115 | .pr_freeport = lagg_common_freeport, | 115 | .pr_freeport = lagg_common_freeport, | |
116 | .pr_startport = lagg_common_startport, | 116 | .pr_startport = lagg_common_startport, | |
117 | .pr_stopport = lagg_common_stopport, | 117 | .pr_stopport = lagg_common_stopport, | |
118 | .pr_portstat = lagg_fail_portstat, | 118 | .pr_portstat = lagg_fail_portstat, | |
@@ -1480,26 +1480,28 @@ lagg_proto_stopport(struct lagg_softc *s | @@ -1480,26 +1480,28 @@ lagg_proto_stopport(struct lagg_softc *s | |||
1480 | { | 1480 | { | |
1481 | 1481 | |||
1482 | lagg_proto_portctrl(sc, lp, LAGG_PORTCTRL_STOP); | 1482 | lagg_proto_portctrl(sc, lp, LAGG_PORTCTRL_STOP); | |
1483 | } | 1483 | } | |
1484 | 1484 | |||
1485 | static void | 1485 | static void | |
1486 | lagg_proto_linkstate(struct lagg_softc *sc, struct lagg_port *lp) | 1486 | lagg_proto_linkstate(struct lagg_softc *sc, struct lagg_port *lp) | |
1487 | { | 1487 | { | |
1488 | struct lagg_variant *var; | 1488 | struct lagg_variant *var; | |
1489 | struct psref psref; | 1489 | struct psref psref; | |
1490 | lagg_proto pr; | 1490 | lagg_proto pr; | |
1491 | int bound; | 1491 | int bound; | |
1492 | 1492 | |||
1493 | KASSERT(IFNET_LOCKED(lp->lp_ifp)); | |||
1494 | ||||
1493 | bound = curlwp_bind(); | 1495 | bound = curlwp_bind(); | |
1494 | var = lagg_variant_getref(sc, &psref); | 1496 | var = lagg_variant_getref(sc, &psref); | |
1495 | 1497 | |||
1496 | if (var == NULL) { | 1498 | if (var == NULL) { | |
1497 | curlwp_bindx(bound); | 1499 | curlwp_bindx(bound); | |
1498 | return; | 1500 | return; | |
1499 | } | 1501 | } | |
1500 | 1502 | |||
1501 | pr = var->lv_proto; | 1503 | pr = var->lv_proto; | |
1502 | 1504 | |||
1503 | if (lagg_protos[pr].pr_linkstate) | 1505 | if (lagg_protos[pr].pr_linkstate) | |
1504 | lagg_protos[pr].pr_linkstate(var->lv_psc, lp); | 1506 | lagg_protos[pr].pr_linkstate(var->lv_psc, lp); | |
1505 | 1507 | |||
@@ -2682,26 +2684,28 @@ lagg_unconfig_promisc(struct lagg_softc | @@ -2682,26 +2684,28 @@ lagg_unconfig_promisc(struct lagg_softc | |||
2682 | static int | 2684 | static int | |
2683 | lagg_port_ioctl(struct ifnet *ifp, u_long cmd, void *data) | 2685 | lagg_port_ioctl(struct ifnet *ifp, u_long cmd, void *data) | |
2684 | { | 2686 | { | |
2685 | struct lagg_softc *sc; | 2687 | struct lagg_softc *sc; | |
2686 | struct lagg_port *lp; | 2688 | struct lagg_port *lp; | |
2687 | int error = 0; | 2689 | int error = 0; | |
2688 | u_int ifflags; | 2690 | u_int ifflags; | |
2689 | 2691 | |||
2690 | if ((lp = ifp->if_lagg) == NULL || | 2692 | if ((lp = ifp->if_lagg) == NULL || | |
2691 | (sc = lp->lp_softc) == NULL) { | 2693 | (sc = lp->lp_softc) == NULL) { | |
2692 | goto fallback; | 2694 | goto fallback; | |
2693 | } | 2695 | } | |
2694 | 2696 | |||
2697 | KASSERT(IFNET_LOCKED(lp->lp_ifp)); | |||
2698 | ||||
2695 | switch (cmd) { | 2699 | switch (cmd) { | |
2696 | case SIOCSIFCAP: | 2700 | case SIOCSIFCAP: | |
2697 | case SIOCSIFMTU: | 2701 | case SIOCSIFMTU: | |
2698 | case SIOCSETHERCAP: | 2702 | case SIOCSETHERCAP: | |
2699 | /* Do not allow the setting to be cahanged once joined */ | 2703 | /* Do not allow the setting to be cahanged once joined */ | |
2700 | error = EINVAL; | 2704 | error = EINVAL; | |
2701 | break; | 2705 | break; | |
2702 | case SIOCSIFFLAGS: | 2706 | case SIOCSIFFLAGS: | |
2703 | ifflags = ifp->if_flags; | 2707 | ifflags = ifp->if_flags; | |
2704 | error = LAGG_PORT_IOCTL(lp, cmd, data); | 2708 | error = LAGG_PORT_IOCTL(lp, cmd, data); | |
2705 | ifflags ^= ifp->if_flags; | 2709 | ifflags ^= ifp->if_flags; | |
2706 | 2710 | |||
2707 | if ((ifflags & (IFF_UP | IFF_RUNNING)) != 0) { | 2711 | if ((ifflags & (IFF_UP | IFF_RUNNING)) != 0) { | |
@@ -2807,27 +2811,30 @@ lagg_linkstate_changed(void *xifp) | @@ -2807,27 +2811,30 @@ lagg_linkstate_changed(void *xifp) | |||
2807 | int s, bound; | 2811 | int s, bound; | |
2808 | 2812 | |||
2809 | s = pserialize_read_enter(); | 2813 | s = pserialize_read_enter(); | |
2810 | lp = atomic_load_consume(&ifp->if_lagg); | 2814 | lp = atomic_load_consume(&ifp->if_lagg); | |
2811 | if (lp != NULL) { | 2815 | if (lp != NULL) { | |
2812 | bound = curlwp_bind(); | 2816 | bound = curlwp_bind(); | |
2813 | lagg_port_getref(lp, &psref); | 2817 | lagg_port_getref(lp, &psref); | |
2814 | } else { | 2818 | } else { | |
2815 | pserialize_read_exit(s); | 2819 | pserialize_read_exit(s); | |
2816 | return; | 2820 | return; | |
2817 | } | 2821 | } | |
2818 | pserialize_read_exit(s); | 2822 | pserialize_read_exit(s); | |
2819 | 2823 | |||
2824 | IFNET_LOCK(lp->lp_ifp); | |||
2820 | lagg_proto_linkstate(lp->lp_softc, lp); | 2825 | lagg_proto_linkstate(lp->lp_softc, lp); | |
2826 | IFNET_UNLOCK(lp->lp_ifp); | |||
2827 | ||||
2821 | lagg_port_putref(lp, &psref); | 2828 | lagg_port_putref(lp, &psref); | |
2822 | curlwp_bindx(bound); | 2829 | curlwp_bindx(bound); | |
2823 | } | 2830 | } | |
2824 | 2831 | |||
2825 | void | 2832 | void | |
2826 | lagg_port_getref(struct lagg_port *lp, struct psref *psref) | 2833 | lagg_port_getref(struct lagg_port *lp, struct psref *psref) | |
2827 | { | 2834 | { | |
2828 | 2835 | |||
2829 | psref_acquire(psref, &lp->lp_psref, lagg_port_psref_class); | 2836 | psref_acquire(psref, &lp->lp_psref, lagg_port_psref_class); | |
2830 | } | 2837 | } | |
2831 | 2838 | |||
2832 | void | 2839 | void | |
2833 | lagg_port_putref(struct lagg_port *lp, struct psref *psref) | 2840 | lagg_port_putref(struct lagg_port *lp, struct psref *psref) |
--- src/sys/net/lagg/if_lagg_lacp.c 2022/01/06 12:09:42 1.11
+++ src/sys/net/lagg/if_lagg_lacp.c 2022/01/12 08:23:53 1.12
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: if_lagg_lacp.c,v 1.11 2022/01/06 12:09:42 riastradh Exp $ */ | 1 | /* $NetBSD: if_lagg_lacp.c,v 1.12 2022/01/12 08:23:53 yamaguchi Exp $ */ | |
2 | 2 | |||
3 | /*- | 3 | /*- | |
4 | * SPDX-License-Identifier: BSD-2-Clause-NetBSD | 4 | * SPDX-License-Identifier: BSD-2-Clause-NetBSD | |
5 | * | 5 | * | |
6 | * Copyright (c)2005 YAMAMOTO Takashi, | 6 | * Copyright (c)2005 YAMAMOTO Takashi, | |
7 | * Copyright (c)2008 Andrew Thompson <thompsa@FreeBSD.org> | 7 | * Copyright (c)2008 Andrew Thompson <thompsa@FreeBSD.org> | |
8 | * Copyright (c)2021 Internet Initiative Japan, Inc. | 8 | * Copyright (c)2021 Internet Initiative Japan, Inc. | |
9 | * All rights reserved. | 9 | * All rights reserved. | |
10 | * | 10 | * | |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without | |
12 | * modification, are permitted provided that the following conditions | 12 | * modification, are permitted provided that the following conditions | |
13 | * are met: | 13 | * are met: | |
14 | * 1. Redistributions of source code must retain the above copyright | 14 | * 1. Redistributions of source code must retain the above copyright | |
@@ -21,27 +21,27 @@ | @@ -21,27 +21,27 @@ | |||
21 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 21 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | 22 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | 23 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | |
24 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | 24 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
25 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | 25 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
26 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | 26 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
27 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | 27 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
28 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | 28 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
29 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | 29 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
30 | * SUCH DAMAGE. | 30 | * SUCH DAMAGE. | |
31 | */ | 31 | */ | |
32 | 32 | |||
33 | #include <sys/cdefs.h> | 33 | #include <sys/cdefs.h> | |
34 | __KERNEL_RCSID(0, "$NetBSD: if_lagg_lacp.c,v 1.11 2022/01/06 12:09:42 riastradh Exp $"); | 34 | __KERNEL_RCSID(0, "$NetBSD: if_lagg_lacp.c,v 1.12 2022/01/12 08:23:53 yamaguchi Exp $"); | |
35 | 35 | |||
36 | #ifdef _KERNEL_OPT | 36 | #ifdef _KERNEL_OPT | |
37 | #include "opt_lagg.h" | 37 | #include "opt_lagg.h" | |
38 | #endif | 38 | #endif | |
39 | 39 | |||
40 | #include <sys/param.h> | 40 | #include <sys/param.h> | |
41 | #include <sys/types.h> | 41 | #include <sys/types.h> | |
42 | 42 | |||
43 | #include <sys/evcnt.h> | 43 | #include <sys/evcnt.h> | |
44 | #include <sys/kmem.h> | 44 | #include <sys/kmem.h> | |
45 | #include <sys/pslist.h> | 45 | #include <sys/pslist.h> | |
46 | #include <sys/sysctl.h> | 46 | #include <sys/sysctl.h> | |
47 | #include <sys/syslog.h> | 47 | #include <sys/syslog.h> | |
@@ -202,28 +202,26 @@ static void lacp_dprintf(const struct la | @@ -202,28 +202,26 @@ static void lacp_dprintf(const struct la | |||
202 | lacp_aggregator_str(_a, _b, _bs) | 202 | lacp_aggregator_str(_a, _b, _bs) | |
203 | #define __LACPDEBUGUSED | 203 | #define __LACPDEBUGUSED | |
204 | #else | 204 | #else | |
205 | #define LACP_DPRINTF(a) __nothing | 205 | #define LACP_DPRINTF(a) __nothing | |
206 | #define LACP_PEERINFO_IDSTR(_pi, _b, _bs) __nothing | 206 | #define LACP_PEERINFO_IDSTR(_pi, _b, _bs) __nothing | |
207 | #define LACP_STATE_STR(_s, _b, _bs) __nothing | 207 | #define LACP_STATE_STR(_s, _b, _bs) __nothing | |
208 | #define LACP_AGGREGATOR_STR(_a, _b, _bs) __nothing | 208 | #define LACP_AGGREGATOR_STR(_a, _b, _bs) __nothing | |
209 | #define __LACPDEBUGUSED __unused | 209 | #define __LACPDEBUGUSED __unused | |
210 | #endif | 210 | #endif | |
211 | 211 | |||
212 | #define LACP_LOCK(_sc) mutex_enter(&(_sc)->lsc_lock) | 212 | #define LACP_LOCK(_sc) mutex_enter(&(_sc)->lsc_lock) | |
213 | #define LACP_UNLOCK(_sc) mutex_exit(&(_sc)->lsc_lock) | 213 | #define LACP_UNLOCK(_sc) mutex_exit(&(_sc)->lsc_lock) | |
214 | #define LACP_LOCKED(_sc) mutex_owned(&(_sc)->lsc_lock) | 214 | #define LACP_LOCKED(_sc) mutex_owned(&(_sc)->lsc_lock) | |
215 | #define LACP_LINKSTATE(_sc, _lp) \ | |||
216 | lacp_linkstate((struct lagg_proto_softc *)(_sc), (_lp)) | |||
217 | #define LACP_TIMER_ARM(_lacpp, _timer, _val) \ | 215 | #define LACP_TIMER_ARM(_lacpp, _timer, _val) \ | |
218 | (_lacpp)->lp_timer[(_timer)] = (_val) | 216 | (_lacpp)->lp_timer[(_timer)] = (_val) | |
219 | #define LACP_TIMER_DISARM(_lacpp, _timer) \ | 217 | #define LACP_TIMER_DISARM(_lacpp, _timer) \ | |
220 | LACP_TIMER_ARM((_lacpp), (_timer), 0) | 218 | LACP_TIMER_ARM((_lacpp), (_timer), 0) | |
221 | #define LACP_TIMER_ISARMED(_lacpp, _timer) \ | 219 | #define LACP_TIMER_ISARMED(_lacpp, _timer) \ | |
222 | ((_lacpp)->lp_timer[(_timer)] > 0) | 220 | ((_lacpp)->lp_timer[(_timer)] > 0) | |
223 | #define LACP_PTIMER_ARM(_sc, _timer, _val) \ | 221 | #define LACP_PTIMER_ARM(_sc, _timer, _val) \ | |
224 | (_sc)->lsc_timer[(_timer)] = (_val) | 222 | (_sc)->lsc_timer[(_timer)] = (_val) | |
225 | #define LACP_PTIMER_DISARM(_sc, _timer) \ | 223 | #define LACP_PTIMER_DISARM(_sc, _timer) \ | |
226 | LACP_PTIMER_ARM((_sc), (_timer), 0) | 224 | LACP_PTIMER_ARM((_sc), (_timer), 0) | |
227 | #define LACP_PTIMER_ISARMED(_sc, _timer) \ | 225 | #define LACP_PTIMER_ISARMED(_sc, _timer) \ | |
228 | ((_sc)->lsc_timer[(_timer)] > 0) | 226 | ((_sc)->lsc_timer[(_timer)] > 0) | |
229 | #define LACP_STATE_EQ(_s1, _s2, _mask) (!ISSET((_s1) ^ (_s2), (_mask))) | 227 | #define LACP_STATE_EQ(_s1, _s2, _mask) (!ISSET((_s1) ^ (_s2), (_mask))) | |
@@ -232,26 +230,27 @@ static void lacp_dprintf(const struct la | @@ -232,26 +230,27 @@ static void lacp_dprintf(const struct la | |||
232 | #define LACP_ISDUMPING(_sc) (_sc)->lsc_dump_du | 230 | #define LACP_ISDUMPING(_sc) (_sc)->lsc_dump_du | |
233 | #define LACP_PORTMAP_ACTIVE(_sc) \ | 231 | #define LACP_PORTMAP_ACTIVE(_sc) \ | |
234 | atomic_load_consume(&(_sc)->lsc_activemap) | 232 | atomic_load_consume(&(_sc)->lsc_activemap) | |
235 | #define LACP_PORTMAP_NEXT(_sc) \ | 233 | #define LACP_PORTMAP_NEXT(_sc) \ | |
236 | (((LACP_PORTMAP_ACTIVE((_sc))) ^ 0x01) &0x01) | 234 | (((LACP_PORTMAP_ACTIVE((_sc))) ^ 0x01) &0x01) | |
237 | #define LACP_SYS_PRI(_la) ntohs((_la)->la_sid.sid_prio) | 235 | #define LACP_SYS_PRI(_la) ntohs((_la)->la_sid.sid_prio) | |
238 | #define LACP_TLV_PARSE(_du, _st, _name, _tlvlist) \ | 236 | #define LACP_TLV_PARSE(_du, _st, _name, _tlvlist) \ | |
239 | tlv_parse(&(_du)->_name, \ | 237 | tlv_parse(&(_du)->_name, \ | |
240 | sizeof(_st) - offsetof(_st, _name), \ | 238 | sizeof(_st) - offsetof(_st, _name), \ | |
241 | (_tlvlist)) | 239 | (_tlvlist)) | |
242 | 240 | |||
243 | static void lacp_tick(void *); | 241 | static void lacp_tick(void *); | |
244 | static void lacp_tick_work(struct lagg_work *, void *); | 242 | static void lacp_tick_work(struct lagg_work *, void *); | |
243 | static void lacp_linkstate(struct lagg_proto_softc *, struct lagg_port *); | |||
245 | static uint32_t lacp_ifmedia2lacpmedia(u_int); | 244 | static uint32_t lacp_ifmedia2lacpmedia(u_int); | |
246 | static void lacp_port_disable(struct lacp_softc *, struct lacp_port *); | 245 | static void lacp_port_disable(struct lacp_softc *, struct lacp_port *); | |
247 | static void lacp_port_enable(struct lacp_softc *, struct lacp_port *); | 246 | static void lacp_port_enable(struct lacp_softc *, struct lacp_port *); | |
248 | static void lacp_peerinfo_actor(struct lacp_softc *, struct lacp_port *, | 247 | static void lacp_peerinfo_actor(struct lacp_softc *, struct lacp_port *, | |
249 | struct lacpdu_peerinfo *); | 248 | struct lacpdu_peerinfo *); | |
250 | static void lacp_peerinfo_partner(struct lacp_port *, | 249 | static void lacp_peerinfo_partner(struct lacp_port *, | |
251 | struct lacpdu_peerinfo *); | 250 | struct lacpdu_peerinfo *); | |
252 | static struct lagg_port * | 251 | static struct lagg_port * | |
253 | lacp_select_tx_port(struct lacp_softc *, struct mbuf *, | 252 | lacp_select_tx_port(struct lacp_softc *, struct mbuf *, | |
254 | struct psref *); | 253 | struct psref *); | |
255 | static void lacp_suppress_distributing(struct lacp_softc *); | 254 | static void lacp_suppress_distributing(struct lacp_softc *); | |
256 | static void lacp_distributing_timer(struct lacp_softc *); | 255 | static void lacp_distributing_timer(struct lacp_softc *); | |
257 | 256 | |||
@@ -663,43 +662,43 @@ lacp_allocport(struct lagg_proto_softc * | @@ -663,43 +662,43 @@ lacp_allocport(struct lagg_proto_softc * | |||
663 | if (lacpp == NULL) | 662 | if (lacpp == NULL) | |
664 | return ENOMEM; | 663 | return ENOMEM; | |
665 | 664 | |||
666 | lacpp->lp_added_multi = added_multi; | 665 | lacpp->lp_added_multi = added_multi; | |
667 | lagg_work_set(&lacpp->lp_work_smtx, lacp_sm_tx_work, lsc); | 666 | lagg_work_set(&lacpp->lp_work_smtx, lacp_sm_tx_work, lsc); | |
668 | lagg_work_set(&lacpp->lp_work_marker, lacp_marker_work, lsc); | 667 | lagg_work_set(&lacpp->lp_work_marker, lacp_marker_work, lsc); | |
669 | 668 | |||
670 | LACP_LOCK(lsc); | 669 | LACP_LOCK(lsc); | |
671 | lacp_sm_port_init(lsc, lacpp, lp); | 670 | lacp_sm_port_init(lsc, lacpp, lp); | |
672 | LACP_UNLOCK(lsc); | 671 | LACP_UNLOCK(lsc); | |
673 | 672 | |||
674 | lp->lp_proto_ctx = (void *)lacpp; | 673 | lp->lp_proto_ctx = (void *)lacpp; | |
675 | lp->lp_prio = ntohs(lacpp->lp_actor.lpi_portprio); | 674 | lp->lp_prio = ntohs(lacpp->lp_actor.lpi_portprio); | |
676 | LACP_LINKSTATE(lsc, lp); | 675 | lacp_linkstate(xlsc, lp); | |
677 | 676 | |||
678 | return 0; | 677 | return 0; | |
679 | } | 678 | } | |
680 | 679 | |||
681 | void | 680 | void | |
682 | lacp_startport(struct lagg_proto_softc *xlsc, struct lagg_port *lp) | 681 | lacp_startport(struct lagg_proto_softc *xlsc, struct lagg_port *lp) | |
683 | { | 682 | { | |
684 | struct lacp_port *lacpp; | 683 | struct lacp_port *lacpp; | |
685 | uint16_t prio; | 684 | uint16_t prio; | |
686 | 685 | |||
687 | lacpp = lp->lp_proto_ctx; | 686 | lacpp = lp->lp_proto_ctx; | |
688 | 687 | |||
689 | prio = (uint16_t)MIN(lp->lp_prio, UINT16_MAX); | 688 | prio = (uint16_t)MIN(lp->lp_prio, UINT16_MAX); | |
690 | lacpp->lp_actor.lpi_portprio = htons(prio); | 689 | lacpp->lp_actor.lpi_portprio = htons(prio); | |
691 | 690 | |||
692 | LACP_LINKSTATE((struct lacp_softc *)xlsc, lp); | 691 | lacp_linkstate(xlsc, lp); | |
693 | } | 692 | } | |
694 | 693 | |||
695 | void | 694 | void | |
696 | lacp_stopport(struct lagg_proto_softc *xlsc, struct lagg_port *lp) | 695 | lacp_stopport(struct lagg_proto_softc *xlsc, struct lagg_port *lp) | |
697 | { | 696 | { | |
698 | struct lacp_softc *lsc; | 697 | struct lacp_softc *lsc; | |
699 | struct lacp_port *lacpp; | 698 | struct lacp_port *lacpp; | |
700 | int i; | 699 | int i; | |
701 | 700 | |||
702 | lsc = (struct lacp_softc *)xlsc; | 701 | lsc = (struct lacp_softc *)xlsc; | |
703 | lacpp = lp->lp_proto_ctx; | 702 | lacpp = lp->lp_proto_ctx; | |
704 | 703 | |||
705 | KASSERT(LAGG_LOCKED(lsc->lsc_softc)); | 704 | KASSERT(LAGG_LOCKED(lsc->lsc_softc)); | |
@@ -811,47 +810,47 @@ lacp_portstat(struct lagg_proto_softc *x | @@ -811,47 +810,47 @@ lacp_portstat(struct lagg_proto_softc *x | |||
811 | llp->partner_key = ntohs(sid->sid_key); | 810 | llp->partner_key = ntohs(sid->sid_key); | |
812 | } | 811 | } | |
813 | 812 | |||
814 | llp->actor_portprio = ntohs(lacpp->lp_actor.lpi_portprio); | 813 | llp->actor_portprio = ntohs(lacpp->lp_actor.lpi_portprio); | |
815 | llp->actor_portno = ntohs(lacpp->lp_actor.lpi_portno); | 814 | llp->actor_portno = ntohs(lacpp->lp_actor.lpi_portno); | |
816 | llp->actor_state = lacpp->lp_actor.lpi_state; | 815 | llp->actor_state = lacpp->lp_actor.lpi_state; | |
817 | 816 | |||
818 | llp->partner_portprio = ntohs(lacpp->lp_partner.lpi_portprio); | 817 | llp->partner_portprio = ntohs(lacpp->lp_partner.lpi_portprio); | |
819 | llp->partner_portno = ntohs(lacpp->lp_partner.lpi_portno); | 818 | llp->partner_portno = ntohs(lacpp->lp_partner.lpi_portno); | |
820 | llp->partner_state = lacpp->lp_partner.lpi_state; | 819 | llp->partner_state = lacpp->lp_partner.lpi_state; | |
821 | } | 820 | } | |
822 | 821 | |||
823 | void | 822 | void | |
824 | lacp_linkstate(struct lagg_proto_softc *xlsc, struct lagg_port *lp) | 823 | lacp_linkstate_ifnet_locked(struct lagg_proto_softc *xlsc, struct lagg_port *lp) | |
825 | { | 824 | { | |
826 | struct lacp_softc *lsc; | 825 | struct lacp_softc *lsc; | |
827 | struct lacp_port *lacpp; | 826 | struct lacp_port *lacpp; | |
828 | struct ifmediareq ifmr; | 827 | struct ifmediareq ifmr; | |
829 | struct ifnet *ifp_port; | 828 | struct ifnet *ifp_port; | |
830 | uint8_t old_state; | 829 | uint8_t old_state; | |
831 | uint32_t media, old_media; | 830 | uint32_t media, old_media; | |
832 | int error; | 831 | int error; | |
833 | 832 | |||
833 | KASSERT(IFNET_LOCKED(lp->lp_ifp)); | |||
834 | ||||
834 | lsc = (struct lacp_softc *)xlsc; | 835 | lsc = (struct lacp_softc *)xlsc; | |
835 | 836 | |||
836 | ifp_port = lp->lp_ifp; | 837 | ifp_port = lp->lp_ifp; | |
837 | lacpp = lp->lp_proto_ctx; | 838 | lacpp = lp->lp_proto_ctx; | |
838 | media = LACP_MEDIA_DEFAULT; | 839 | media = LACP_MEDIA_DEFAULT; | |
839 | 840 | |||
840 | memset(&ifmr, 0, sizeof(ifmr)); | 841 | memset(&ifmr, 0, sizeof(ifmr)); | |
841 | ifmr.ifm_count = 0; | 842 | ifmr.ifm_count = 0; | |
842 | IFNET_LOCK(ifp_port); | |||
843 | error = if_ioctl(ifp_port, SIOCGIFMEDIA, (void *)&ifmr); | 843 | error = if_ioctl(ifp_port, SIOCGIFMEDIA, (void *)&ifmr); | |
844 | IFNET_UNLOCK(ifp_port); | |||
845 | if (error == 0) { | 844 | if (error == 0) { | |
846 | media = lacp_ifmedia2lacpmedia(ifmr.ifm_active); | 845 | media = lacp_ifmedia2lacpmedia(ifmr.ifm_active); | |
847 | } else if (error != ENOTTY){ | 846 | } else if (error != ENOTTY){ | |
848 | LACP_DPRINTF((lsc, lacpp, | 847 | LACP_DPRINTF((lsc, lacpp, | |
849 | "SIOCGIFMEDIA failed (%d)\n", error)); | 848 | "SIOCGIFMEDIA failed (%d)\n", error)); | |
850 | return; | 849 | return; | |
851 | } | 850 | } | |
852 | 851 | |||
853 | LACP_LOCK(lsc); | 852 | LACP_LOCK(lsc); | |
854 | if (lsc->lsc_running) { | 853 | if (lsc->lsc_running) { | |
855 | old_media = lacpp->lp_media; | 854 | old_media = lacpp->lp_media; | |
856 | old_state = lacpp->lp_actor.lpi_state; | 855 | old_state = lacpp->lp_actor.lpi_state; | |
857 | 856 | |||
@@ -2634,13 +2633,24 @@ lacp_ifmedia2lacpmedia(u_int ifmedia) | @@ -2634,13 +2633,24 @@ lacp_ifmedia2lacpmedia(u_int ifmedia) | |||
2634 | rv = LACP_LINKSPEED_10G; | 2633 | rv = LACP_LINKSPEED_10G; | |
2635 | break; | 2634 | break; | |
2636 | default: | 2635 | default: | |
2637 | rv = LACP_LINKSPEED_UNKNOWN; | 2636 | rv = LACP_LINKSPEED_UNKNOWN; | |
2638 | } | 2637 | } | |
2639 | 2638 | |||
2640 | if (IFM_TYPE(ifmedia) == IFM_ETHER) | 2639 | if (IFM_TYPE(ifmedia) == IFM_ETHER) | |
2641 | SET(rv, LACP_MEDIA_ETHER); | 2640 | SET(rv, LACP_MEDIA_ETHER); | |
2642 | if ((ifmedia & IFM_FDX) != 0) | 2641 | if ((ifmedia & IFM_FDX) != 0) | |
2643 | SET(rv, LACP_MEDIA_FDX); | 2642 | SET(rv, LACP_MEDIA_FDX); | |
2644 | 2643 | |||
2645 | return rv; | 2644 | return rv; | |
2646 | } | 2645 | } | |
2646 | ||||
2647 | static void | |||
2648 | lacp_linkstate(struct lagg_proto_softc *xlsc, struct lagg_port *lp) | |||
2649 | { | |||
2650 | ||||
2651 | IFNET_ASSERT_UNLOCKED(lp->lp_ifp); | |||
2652 | ||||
2653 | IFNET_LOCK(lp->lp_ifp); | |||
2654 | lacp_linkstate_ifnet_locked(xlsc, lp); | |||
2655 | IFNET_UNLOCK(lp->lp_ifp); | |||
2656 | } |
--- src/sys/net/lagg/if_laggproto.h 2021/10/19 07:52:33 1.9
+++ src/sys/net/lagg/if_laggproto.h 2022/01/12 08:23:53 1.10
@@ -1,14 +1,14 @@ | @@ -1,14 +1,14 @@ | |||
1 | /* $NetBSD: if_laggproto.h,v 1.9 2021/10/19 07:52:33 yamaguchi Exp $ */ | 1 | /* $NetBSD: if_laggproto.h,v 1.10 2022/01/12 08:23:53 yamaguchi Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright (c) 2021 Internet Initiative Japan Inc. | 4 | * Copyright (c) 2021 Internet Initiative Japan Inc. | |
5 | * All rights reserved. | 5 | * All rights reserved. | |
6 | * | 6 | * | |
7 | * Redistribution and use in source and binary forms, with or without | 7 | * Redistribution and use in source and binary forms, with or without | |
8 | * modification, are permitted provided that the following conditions | 8 | * modification, are permitted provided that the following conditions | |
9 | * are met: | 9 | * are met: | |
10 | * 1. Redistributions of source code must retain the above copyright | 10 | * 1. Redistributions of source code must retain the above copyright | |
11 | * notice, this list of conditions and the following disclaimer. | 11 | * notice, this list of conditions and the following disclaimer. | |
12 | * 2. Redistributions in binary form must reproduce the above copyright | 12 | * 2. Redistributions in binary form must reproduce the above copyright | |
13 | * notice, this list of conditions and the following disclaimer in the | 13 | * notice, this list of conditions and the following disclaimer in the | |
14 | * documentation and/or other materials provided with the distribution. | 14 | * documentation and/or other materials provided with the distribution. | |
@@ -189,28 +189,28 @@ struct lagg_softc { | @@ -189,28 +189,28 @@ struct lagg_softc { | |||
189 | * - sc_var is protected by both pselialize (sc_psz) and psref (lv_psref) | 189 | * - sc_var is protected by both pselialize (sc_psz) and psref (lv_psref) | |
190 | * - Updates of sc_var is serialized by sc_lock | 190 | * - Updates of sc_var is serialized by sc_lock | |
191 | * - Items in sc_ports is protected by both psref (lp_psref) and | 191 | * - Items in sc_ports is protected by both psref (lp_psref) and | |
192 | * pserialize contained in struct lagg_proto_softc | 192 | * pserialize contained in struct lagg_proto_softc | |
193 | * - details are discribed in if_laggport.c and if_lagg_lacp.c | 193 | * - details are discribed in if_laggport.c and if_lagg_lacp.c | |
194 | * - Updates of items in sc_ports are serialized by sc_lock | 194 | * - Updates of items in sc_ports are serialized by sc_lock | |
195 | * - an instance referenced by lp_proto_ctx in struct lagg_port is | 195 | * - an instance referenced by lp_proto_ctx in struct lagg_port is | |
196 | * protected by a lock in struct lagg_proto_softc | 196 | * protected by a lock in struct lagg_proto_softc | |
197 | * | 197 | * | |
198 | * Locking order: | 198 | * Locking order: | |
199 | * - IFNET_LOCK(sc_if) -> LAGG_LOCK -> ETHER_LOCK(sc_if) -> a lock in | 199 | * - IFNET_LOCK(sc_if) -> LAGG_LOCK -> ETHER_LOCK(sc_if) -> a lock in | |
200 | * struct lagg_port_softc | 200 | * struct lagg_port_softc | |
201 | * - IFNET_LOCK(sc_if) -> LAGG_LOCK -> IFNET_LOCK(lp_ifp) | 201 | * - IFNET_LOCK(sc_if) -> LAGG_LOCK -> IFNET_LOCK(lp_ifp) | |
202 | * - IFNET_LOCK(lp_ifp) -> a lock in struct lagg_proto_softc | |||
202 | * - Currently, there is no combination of following locks | 203 | * - Currently, there is no combination of following locks | |
203 | * - IFNET_LOCK(lp_ifp) and a lock in struct lagg_proto_softc | |||
204 | * - IFNET_LOCK(lp_ifp) and ETHER_LOCK(sc_if) | 204 | * - IFNET_LOCK(lp_ifp) and ETHER_LOCK(sc_if) | |
205 | */ | 205 | */ | |
206 | #define LAGG_LOCK(_sc) mutex_enter(&(_sc)->sc_lock) | 206 | #define LAGG_LOCK(_sc) mutex_enter(&(_sc)->sc_lock) | |
207 | #define LAGG_UNLOCK(_sc) mutex_exit(&(_sc)->sc_lock) | 207 | #define LAGG_UNLOCK(_sc) mutex_exit(&(_sc)->sc_lock) | |
208 | #define LAGG_LOCKED(_sc) mutex_owned(&(_sc)->sc_lock) | 208 | #define LAGG_LOCKED(_sc) mutex_owned(&(_sc)->sc_lock) | |
209 | #define LAGG_CLLADDR(_sc) CLLADDR((_sc)->sc_if.if_sadl) | 209 | #define LAGG_CLLADDR(_sc) CLLADDR((_sc)->sc_if.if_sadl) | |
210 | 210 | |||
211 | #define LAGG_PORTS_FOREACH(_sc, _lp) \ | 211 | #define LAGG_PORTS_FOREACH(_sc, _lp) \ | |
212 | SIMPLEQ_FOREACH((_lp), &(_sc)->sc_ports, lp_entry) | 212 | SIMPLEQ_FOREACH((_lp), &(_sc)->sc_ports, lp_entry) | |
213 | #define LAGG_PORTS_FIRST(_sc) SIMPLEQ_FIRST(&(_sc)->sc_ports) | 213 | #define LAGG_PORTS_FIRST(_sc) SIMPLEQ_FIRST(&(_sc)->sc_ports) | |
214 | #define LAGG_PORTS_EMPTY(_sc) SIMPLEQ_EMPTY(&(_sc)->sc_ports) | 214 | #define LAGG_PORTS_EMPTY(_sc) SIMPLEQ_EMPTY(&(_sc)->sc_ports) | |
215 | #define LAGG_PORT_IOCTL(_lp, _cmd, _data) \ | 215 | #define LAGG_PORT_IOCTL(_lp, _cmd, _data) \ | |
216 | (_lp)->lp_ioctl == NULL ? ENOTTY : \ | 216 | (_lp)->lp_ioctl == NULL ? ENOTTY : \ | |
@@ -310,16 +310,16 @@ void lacp_detach(struct lagg_proto_soft | @@ -310,16 +310,16 @@ void lacp_detach(struct lagg_proto_soft | |||
310 | int lacp_up(struct lagg_proto_softc *); | 310 | int lacp_up(struct lagg_proto_softc *); | |
311 | void lacp_down(struct lagg_proto_softc *); | 311 | void lacp_down(struct lagg_proto_softc *); | |
312 | int lacp_transmit(struct lagg_proto_softc *, struct mbuf *); | 312 | int lacp_transmit(struct lagg_proto_softc *, struct mbuf *); | |
313 | struct mbuf * lacp_input(struct lagg_proto_softc *, struct lagg_port *, | 313 | struct mbuf * lacp_input(struct lagg_proto_softc *, struct lagg_port *, | |
314 | struct mbuf *); | 314 | struct mbuf *); | |
315 | int lacp_allocport(struct lagg_proto_softc *, struct lagg_port *); | 315 | int lacp_allocport(struct lagg_proto_softc *, struct lagg_port *); | |
316 | void lacp_freeport(struct lagg_proto_softc *, struct lagg_port *); | 316 | void lacp_freeport(struct lagg_proto_softc *, struct lagg_port *); | |
317 | void lacp_startport(struct lagg_proto_softc *, struct lagg_port *); | 317 | void lacp_startport(struct lagg_proto_softc *, struct lagg_port *); | |
318 | void lacp_stopport(struct lagg_proto_softc *, struct lagg_port *); | 318 | void lacp_stopport(struct lagg_proto_softc *, struct lagg_port *); | |
319 | void lacp_protostat(struct lagg_proto_softc *, | 319 | void lacp_protostat(struct lagg_proto_softc *, | |
320 | struct laggreqproto *); | 320 | struct laggreqproto *); | |
321 | void lacp_portstat(struct lagg_proto_softc *, struct lagg_port *, | 321 | void lacp_portstat(struct lagg_proto_softc *, struct lagg_port *, | |
322 | struct laggreqport *); | 322 | struct laggreqport *); | |
323 | void lacp_linkstate(struct lagg_proto_softc *, struct lagg_port *); | 323 | void lacp_linkstate_ifnet_locked(struct lagg_proto_softc *, struct lagg_port *); | |
324 | int lacp_ioctl(struct lagg_proto_softc *, struct laggreqproto *); | 324 | int lacp_ioctl(struct lagg_proto_softc *, struct laggreqproto *); | |
325 | #endif | 325 | #endif |