Wed Jan 12 08:23:53 2022 UTC ()
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.


(yamaguchi)
diff -r1.29 -r1.30 src/sys/net/lagg/if_lagg.c
diff -r1.11 -r1.12 src/sys/net/lagg/if_lagg_lacp.c
diff -r1.9 -r1.10 src/sys/net/lagg/if_laggproto.h

cvs diff -r1.29 -r1.30 src/sys/net/lagg/if_lagg.c (expand / switch to unified diff)

--- 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
1485static void 1485static void
1486lagg_proto_linkstate(struct lagg_softc *sc, struct lagg_port *lp) 1486lagg_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
2682static int 2684static int
2683lagg_port_ioctl(struct ifnet *ifp, u_long cmd, void *data) 2685lagg_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
2825void 2832void
2826lagg_port_getref(struct lagg_port *lp, struct psref *psref) 2833lagg_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
2832void 2839void
2833lagg_port_putref(struct lagg_port *lp, struct psref *psref) 2840lagg_port_putref(struct lagg_port *lp, struct psref *psref)

cvs diff -r1.11 -r1.12 src/sys/net/lagg/if_lagg_lacp.c (expand / switch to unified diff)

--- 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
243static void lacp_tick(void *); 241static void lacp_tick(void *);
244static void lacp_tick_work(struct lagg_work *, void *); 242static void lacp_tick_work(struct lagg_work *, void *);
 243static void lacp_linkstate(struct lagg_proto_softc *, struct lagg_port *);
245static uint32_t lacp_ifmedia2lacpmedia(u_int); 244static uint32_t lacp_ifmedia2lacpmedia(u_int);
246static void lacp_port_disable(struct lacp_softc *, struct lacp_port *); 245static void lacp_port_disable(struct lacp_softc *, struct lacp_port *);
247static void lacp_port_enable(struct lacp_softc *, struct lacp_port *); 246static void lacp_port_enable(struct lacp_softc *, struct lacp_port *);
248static void lacp_peerinfo_actor(struct lacp_softc *, struct lacp_port *, 247static void lacp_peerinfo_actor(struct lacp_softc *, struct lacp_port *,
249 struct lacpdu_peerinfo *); 248 struct lacpdu_peerinfo *);
250static void lacp_peerinfo_partner(struct lacp_port *, 249static void lacp_peerinfo_partner(struct lacp_port *,
251 struct lacpdu_peerinfo *); 250 struct lacpdu_peerinfo *);
252static struct lagg_port * 251static 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 *);
255static void lacp_suppress_distributing(struct lacp_softc *); 254static void lacp_suppress_distributing(struct lacp_softc *);
256static void lacp_distributing_timer(struct lacp_softc *); 255static 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
681void 680void
682lacp_startport(struct lagg_proto_softc *xlsc, struct lagg_port *lp) 681lacp_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
695void 694void
696lacp_stopport(struct lagg_proto_softc *xlsc, struct lagg_port *lp) 695lacp_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
823void 822void
824lacp_linkstate(struct lagg_proto_softc *xlsc, struct lagg_port *lp) 823lacp_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
 2647static void
 2648lacp_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}

cvs diff -r1.9 -r1.10 src/sys/net/lagg/if_laggproto.h (expand / switch to unified diff)

--- 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
310int lacp_up(struct lagg_proto_softc *); 310int lacp_up(struct lagg_proto_softc *);
311void lacp_down(struct lagg_proto_softc *); 311void lacp_down(struct lagg_proto_softc *);
312int lacp_transmit(struct lagg_proto_softc *, struct mbuf *); 312int lacp_transmit(struct lagg_proto_softc *, struct mbuf *);
313struct mbuf * lacp_input(struct lagg_proto_softc *, struct lagg_port *, 313struct mbuf * lacp_input(struct lagg_proto_softc *, struct lagg_port *,
314 struct mbuf *); 314 struct mbuf *);
315int lacp_allocport(struct lagg_proto_softc *, struct lagg_port *); 315int lacp_allocport(struct lagg_proto_softc *, struct lagg_port *);
316void lacp_freeport(struct lagg_proto_softc *, struct lagg_port *); 316void lacp_freeport(struct lagg_proto_softc *, struct lagg_port *);
317void lacp_startport(struct lagg_proto_softc *, struct lagg_port *); 317void lacp_startport(struct lagg_proto_softc *, struct lagg_port *);
318void lacp_stopport(struct lagg_proto_softc *, struct lagg_port *); 318void lacp_stopport(struct lagg_proto_softc *, struct lagg_port *);
319void lacp_protostat(struct lagg_proto_softc *, 319void lacp_protostat(struct lagg_proto_softc *,
320 struct laggreqproto *); 320 struct laggreqproto *);
321void lacp_portstat(struct lagg_proto_softc *, struct lagg_port *, 321void lacp_portstat(struct lagg_proto_softc *, struct lagg_port *,
322 struct laggreqport *); 322 struct laggreqport *);
323void lacp_linkstate(struct lagg_proto_softc *, struct lagg_port *); 323void lacp_linkstate_ifnet_locked(struct lagg_proto_softc *, struct lagg_port *);
324int lacp_ioctl(struct lagg_proto_softc *, struct laggreqproto *); 324int lacp_ioctl(struct lagg_proto_softc *, struct laggreqproto *);
325#endif 325#endif