Wed Nov 15 02:19:00 2023 UTC ()
Protect the ALTQ state that's exposed to the ifqueue if the ifq->ifq_lock.
This requires exposing some implementation details to ALTQ, which is guarded
by an __IFQ_PRIVATE define.


(thorpej)
diff -r1.22.6.1 -r1.22.6.1.2.1 src/sys/altq/altq_cdnr.c
diff -r1.33.46.1 -r1.33.46.1.2.1 src/sys/altq/altq_subr.c
diff -r1.529.2.1.2.2 -r1.529.2.1.2.3 src/sys/net/if.c
diff -r1.305.2.1.2.2 -r1.305.2.1.2.3 src/sys/net/if.h

cvs diff -r1.22.6.1 -r1.22.6.1.2.1 src/sys/altq/altq_cdnr.c (expand / switch to unified diff)

--- src/sys/altq/altq_cdnr.c 2023/11/11 13:16:30 1.22.6.1
+++ src/sys/altq/altq_cdnr.c 2023/11/15 02:19:00 1.22.6.1.2.1
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: altq_cdnr.c,v 1.22.6.1 2023/11/11 13:16:30 thorpej Exp $ */ 1/* $NetBSD: altq_cdnr.c,v 1.22.6.1.2.1 2023/11/15 02:19:00 thorpej Exp $ */
2/* $KAME: altq_cdnr.c,v 1.15 2005/04/13 03:44:24 suz Exp $ */ 2/* $KAME: altq_cdnr.c,v 1.15 2005/04/13 03:44:24 suz Exp $ */
3 3
4/* 4/*
5 * Copyright (C) 1999-2002 5 * Copyright (C) 1999-2002
6 * Sony Computer Science Laboratories Inc. All rights reserved. 6 * Sony Computer Science Laboratories Inc. All rights reserved.
7 * 7 *
8 * Redistribution and use in source and binary forms, with or without 8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions 9 * modification, are permitted provided that the following conditions
10 * are met: 10 * are met:
11 * 1. Redistributions of source code must retain the above copyright 11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer. 12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright 13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the 14 * notice, this list of conditions and the following disclaimer in the
@@ -18,27 +18,27 @@ @@ -18,27 +18,27 @@
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL SONY CSL OR CONTRIBUTORS BE LIABLE 20 * ARE DISCLAIMED. IN NO EVENT SHALL SONY CSL OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE. 27 * SUCH DAMAGE.
28 */ 28 */
29 29
30#include <sys/cdefs.h> 30#include <sys/cdefs.h>
31__KERNEL_RCSID(0, "$NetBSD: altq_cdnr.c,v 1.22.6.1 2023/11/11 13:16:30 thorpej Exp $"); 31__KERNEL_RCSID(0, "$NetBSD: altq_cdnr.c,v 1.22.6.1.2.1 2023/11/15 02:19:00 thorpej Exp $");
32 32
33#ifdef _KERNEL_OPT 33#ifdef _KERNEL_OPT
34#include "opt_altq.h" 34#include "opt_altq.h"
35#include "opt_inet.h" 35#include "opt_inet.h"
36#endif 36#endif
37 37
38#include <sys/param.h> 38#include <sys/param.h>
39#include <sys/malloc.h> 39#include <sys/malloc.h>
40#include <sys/mbuf.h> 40#include <sys/mbuf.h>
41#include <sys/socket.h> 41#include <sys/socket.h>
42#include <sys/sockio.h> 42#include <sys/sockio.h>
43#include <sys/systm.h> 43#include <sys/systm.h>
44#include <sys/proc.h> 44#include <sys/proc.h>
@@ -128,31 +128,36 @@ altqdev_decl(cdnr); @@ -128,31 +128,36 @@ altqdev_decl(cdnr);
128/* 128/*
129 * top level input function called from ip_input. 129 * top level input function called from ip_input.
130 * should be called before converting header fields to host-byte-order. 130 * should be called before converting header fields to host-byte-order.
131 */ 131 */
132int 132int
133altq_cdnr_input(struct mbuf *m, int af) 133altq_cdnr_input(struct mbuf *m, int af)
134{ 134{
135 struct ifnet *ifp; 135 struct ifnet *ifp;
136 struct ip *ip; 136 struct ip *ip;
137 struct top_cdnr *top; 137 struct top_cdnr *top;
138 struct tc_action *tca; 138 struct tc_action *tca;
139 struct cdnr_block *cb; 139 struct cdnr_block *cb;
140 struct cdnr_pktinfo pktinfo; 140 struct cdnr_pktinfo pktinfo;
 141 bool is_cnding = false;
141 142
142 ifp = m_get_rcvif_NOMPSAFE(m); 143 ifp = m_get_rcvif_NOMPSAFE(m);
143 if (!ALTQ_IS_CNDTNING(&ifp->if_snd)) 144 mutex_enter(ifp->if_snd.ifq_lock);
 145 is_cnding = ALTQ_IS_CNDTNING(&ifp->if_snd);
 146 mutex_exit(ifp->if_snd.ifq_lock);
 147 if (!is_cnding) {
144 /* traffic conditioner is not enabled on this interface */ 148 /* traffic conditioner is not enabled on this interface */
145 return (1); 149 return (1);
 150 }
146 151
147 top = ifp->if_snd.ifq_altq->altq_cdnr; 152 top = ifp->if_snd.ifq_altq->altq_cdnr;
148 153
149 ip = mtod(m, struct ip *); 154 ip = mtod(m, struct ip *);
150#ifdef INET6 155#ifdef INET6
151 if (af == AF_INET6) { 156 if (af == AF_INET6) {
152 u_int32_t flowlabel; 157 u_int32_t flowlabel;
153 158
154 flowlabel = ((struct ip6_hdr *)ip)->ip6_flow; 159 flowlabel = ((struct ip6_hdr *)ip)->ip6_flow;
155 pktinfo.pkt_dscp = (ntohl(flowlabel) >> 20) & DSCP_MASK; 160 pktinfo.pkt_dscp = (ntohl(flowlabel) >> 20) & DSCP_MASK;
156 } else 161 } else
157#endif 162#endif
158 pktinfo.pkt_dscp = ip->ip_tos & DSCP_MASK; 163 pktinfo.pkt_dscp = ip->ip_tos & DSCP_MASK;
@@ -418,50 +423,59 @@ top_create(struct ifaltq *ifq) @@ -418,50 +423,59 @@ top_create(struct ifaltq *ifq)
418 423
419 LIST_INSERT_HEAD(&tcb_list, top, tc_next); 424 LIST_INSERT_HEAD(&tcb_list, top, tc_next);
420 425
421 ifq->altq_cdnr = top; 426 ifq->altq_cdnr = top;
422 427
423 return (top); 428 return (top);
424} 429}
425 430
426static int 431static int
427top_destroy(struct top_cdnr *top) 432top_destroy(struct top_cdnr *top)
428{ 433{
429 struct cdnr_block *cb; 434 struct cdnr_block *cb;
430 435
 436 mutex_enter(top->tc_ifq->altq_ifq->ifq_lock);
431 if (ALTQ_IS_CNDTNING(top->tc_ifq)) 437 if (ALTQ_IS_CNDTNING(top->tc_ifq))
432 ALTQ_CLEAR_CNDTNING(top->tc_ifq); 438 ALTQ_CLEAR_CNDTNING(top->tc_ifq);
433 top->tc_ifq->altq_cdnr = NULL; 439 top->tc_ifq->altq_cdnr = NULL;
 440 mutex_exit(top->tc_ifq->altq_ifq->ifq_lock);
434 441
435 /* 442 /*
436 * destroy all the conditioner elements belonging to this interface 443 * destroy all the conditioner elements belonging to this interface
437 */ 444 */
438 while ((cb = LIST_FIRST(&top->tc_elements)) != NULL) { 445 while ((cb = LIST_FIRST(&top->tc_elements)) != NULL) {
439 while (cb != NULL && cb->cb_ref > 0) 446 while (cb != NULL && cb->cb_ref > 0)
440 cb = LIST_NEXT(cb, cb_next); 447 cb = LIST_NEXT(cb, cb_next);
441 if (cb != NULL) 448 if (cb != NULL)
442 generic_element_destroy(cb); 449 generic_element_destroy(cb);
443 } 450 }
444 451
445 LIST_REMOVE(top, tc_next); 452 LIST_REMOVE(top, tc_next);
446 453
447 cdnr_cbdestroy(top); 454 cdnr_cbdestroy(top);
448 455
449 /* if there is no active conditioner, remove the input hook */ 456 /* if there is no active conditioner, remove the input hook */
450 if (altq_input != NULL) { 457 if (altq_input != NULL) {
451 LIST_FOREACH(top, &tcb_list, tc_next) 458 bool is_cnding = false;
 459
 460 LIST_FOREACH(top, &tcb_list, tc_next) {
 461 mutex_enter(top->tc_ifq->altq_ifq->ifq_lock);
452 if (ALTQ_IS_CNDTNING(top->tc_ifq)) 462 if (ALTQ_IS_CNDTNING(top->tc_ifq))
 463 is_cnding = true;
 464 mutex_exit(top->tc_ifq->altq_ifq->ifq_lock);
 465 if (is_cnding)
453 break; 466 break;
454 if (top == NULL) 467 }
 468 if (!is_cnding)
455 altq_input = NULL; 469 altq_input = NULL;
456 } 470 }
457 471
458 return (0); 472 return (0);
459} 473}
460 474
461/* 475/*
462 * simple tc elements without input function (e.g., dropper and makers). 476 * simple tc elements without input function (e.g., dropper and makers).
463 */ 477 */
464static struct cdnr_block * 478static struct cdnr_block *
465element_create(struct top_cdnr *top, struct tc_action *action) 479element_create(struct top_cdnr *top, struct tc_action *action)
466{ 480{
467 struct cdnr_block *cb; 481 struct cdnr_block *cb;
@@ -1210,39 +1224,50 @@ cdnrioctl(dev_t dev, ioctlcmd_t cmd, voi @@ -1210,39 +1224,50 @@ cdnrioctl(dev_t dev, ioctlcmd_t cmd, voi
1210 break; 1224 break;
1211 1225
1212 case CDNR_ENABLE: 1226 case CDNR_ENABLE:
1213 case CDNR_DISABLE: 1227 case CDNR_DISABLE:
1214 ifacep = (struct cdnr_interface *)addr; 1228 ifacep = (struct cdnr_interface *)addr;
1215 if ((top = tcb_lookup(ifacep->cdnr_ifname)) == NULL) { 1229 if ((top = tcb_lookup(ifacep->cdnr_ifname)) == NULL) {
1216 error = EBADF; 1230 error = EBADF;
1217 break; 1231 break;
1218 } 1232 }
1219 1233
1220 switch (cmd) { 1234 switch (cmd) {
1221 1235
1222 case CDNR_ENABLE: 1236 case CDNR_ENABLE:
 1237 mutex_enter(top->tc_ifq->altq_ifq->ifq_lock);
1223 ALTQ_SET_CNDTNING(top->tc_ifq); 1238 ALTQ_SET_CNDTNING(top->tc_ifq);
 1239 mutex_exit(top->tc_ifq->altq_ifq->ifq_lock);
1224 if (altq_input == NULL) 1240 if (altq_input == NULL)
1225 altq_input = altq_cdnr_input; 1241 altq_input = altq_cdnr_input;
1226 break; 1242 break;
1227 1243
1228 case CDNR_DISABLE: 1244 case CDNR_DISABLE: {
 1245 bool is_cnding = false;
 1246 mutex_enter(top->tc_ifq->altq_ifq->ifq_lock);
1229 ALTQ_CLEAR_CNDTNING(top->tc_ifq); 1247 ALTQ_CLEAR_CNDTNING(top->tc_ifq);
1230 LIST_FOREACH(top, &tcb_list, tc_next) 1248 mutex_exit(top->tc_ifq->altq_ifq->ifq_lock);
 1249 LIST_FOREACH(top, &tcb_list, tc_next) {
 1250 mutex_enter(top->tc_ifq->altq_ifq->ifq_lock);
1231 if (ALTQ_IS_CNDTNING(top->tc_ifq)) 1251 if (ALTQ_IS_CNDTNING(top->tc_ifq))
 1252 is_cnding = true;
 1253 mutex_exit(top->tc_ifq->altq_ifq->ifq_lock);
 1254 if (is_cnding)
1232 break; 1255 break;
1233 if (top == NULL) 1256 }
 1257 if (!is_cnding)
1234 altq_input = NULL; 1258 altq_input = NULL;
1235 break; 1259 break;
 1260 }
1236 } 1261 }
1237 break; 1262 break;
1238 1263
1239 case CDNR_ADD_ELEM: 1264 case CDNR_ADD_ELEM:
1240 error = cdnrcmd_add_element((struct cdnr_add_element *)addr); 1265 error = cdnrcmd_add_element((struct cdnr_add_element *)addr);
1241 break; 1266 break;
1242 1267
1243 case CDNR_DEL_ELEM: 1268 case CDNR_DEL_ELEM:
1244 error = cdnrcmd_delete_element((struct cdnr_delete_element *)addr); 1269 error = cdnrcmd_delete_element((struct cdnr_delete_element *)addr);
1245 break; 1270 break;
1246 1271
1247 case CDNR_ADD_TBM: 1272 case CDNR_ADD_TBM:
1248 error = cdnrcmd_add_tbm((struct cdnr_add_tbmeter *)addr); 1273 error = cdnrcmd_add_tbm((struct cdnr_add_tbmeter *)addr);

cvs diff -r1.33.46.1 -r1.33.46.1.2.1 src/sys/altq/altq_subr.c (expand / switch to unified diff)

--- src/sys/altq/altq_subr.c 2023/11/11 13:16:30 1.33.46.1
+++ src/sys/altq/altq_subr.c 2023/11/15 02:19:00 1.33.46.1.2.1
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: altq_subr.c,v 1.33.46.1 2023/11/11 13:16:30 thorpej Exp $ */ 1/* $NetBSD: altq_subr.c,v 1.33.46.1.2.1 2023/11/15 02:19:00 thorpej Exp $ */
2/* $KAME: altq_subr.c,v 1.24 2005/04/13 03:44:25 suz Exp $ */ 2/* $KAME: altq_subr.c,v 1.24 2005/04/13 03:44:25 suz Exp $ */
3 3
4/* 4/*
5 * Copyright (C) 1997-2003 5 * Copyright (C) 1997-2003
6 * Sony Computer Science Laboratories Inc. All rights reserved. 6 * Sony Computer Science Laboratories Inc. All rights reserved.
7 * 7 *
8 * Redistribution and use in source and binary forms, with or without 8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions 9 * modification, are permitted provided that the following conditions
10 * are met: 10 * are met:
11 * 1. Redistributions of source code must retain the above copyright 11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer. 12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright 13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the 14 * notice, this list of conditions and the following disclaimer in the
@@ -18,34 +18,36 @@ @@ -18,34 +18,36 @@
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL SONY CSL OR CONTRIBUTORS BE LIABLE 20 * ARE DISCLAIMED. IN NO EVENT SHALL SONY CSL OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE. 27 * SUCH DAMAGE.
28 */ 28 */
29 29
30#include <sys/cdefs.h> 30#include <sys/cdefs.h>
31__KERNEL_RCSID(0, "$NetBSD: altq_subr.c,v 1.33.46.1 2023/11/11 13:16:30 thorpej Exp $"); 31__KERNEL_RCSID(0, "$NetBSD: altq_subr.c,v 1.33.46.1.2.1 2023/11/15 02:19:00 thorpej Exp $");
32 32
33#ifdef _KERNEL_OPT 33#ifdef _KERNEL_OPT
34#include "opt_altq.h" 34#include "opt_altq.h"
35#include "opt_inet.h" 35#include "opt_inet.h"
36#include "pf.h" 36#include "pf.h"
37#endif 37#endif
38 38
 39#define __IFQ_PRIVATE
 40
39#include <sys/param.h> 41#include <sys/param.h>
40#include <sys/malloc.h> 42#include <sys/malloc.h>
41#include <sys/mbuf.h> 43#include <sys/mbuf.h>
42#include <sys/systm.h> 44#include <sys/systm.h>
43#include <sys/proc.h> 45#include <sys/proc.h>
44#include <sys/socket.h> 46#include <sys/socket.h>
45#include <sys/socketvar.h> 47#include <sys/socketvar.h>
46#include <sys/kernel.h> 48#include <sys/kernel.h>
47#include <sys/kmem.h> 49#include <sys/kmem.h>
48#include <sys/errno.h> 50#include <sys/errno.h>
49#include <sys/syslog.h> 51#include <sys/syslog.h>
50#include <sys/sysctl.h> 52#include <sys/sysctl.h>
51#include <sys/queue.h> 53#include <sys/queue.h>
@@ -130,156 +132,205 @@ altq_alloc(struct ifqueue *ifq, struct i @@ -130,156 +132,205 @@ altq_alloc(struct ifqueue *ifq, struct i
130 } 132 }
131 if (ifp != NULL) { 133 if (ifp != NULL) {
132 ifq->ifq_altq->altq_ifp = ifp; 134 ifq->ifq_altq->altq_ifp = ifp;
133 } 135 }
134} 136}
135 137
136/* 138/*
137 * Free the ifaltq structure associated with an ifqueue. 139 * Free the ifaltq structure associated with an ifqueue.
138 */ 140 */
139void 141void
140altq_free(struct ifqueue *ifq) 142altq_free(struct ifqueue *ifq)
141{ 143{
142 if (ifq->ifq_altq != NULL) { 144 if (ifq->ifq_altq != NULL) {
 145 /*
 146 * No need to pre-flight these calls; both can handle
 147 * the not-enabled / not-attached scenarios.
 148 */
 149 altq_disable(ifq->ifq_altq);
 150 altq_detach(ifq->ifq_altq);
 151
143 ifq->ifq_altq->altq_ifp = NULL; 152 ifq->ifq_altq->altq_ifp = NULL;
144 kmem_free(ifq->ifq_altq, sizeof(*ifq->ifq_altq)); 153 kmem_free(ifq->ifq_altq, sizeof(*ifq->ifq_altq));
145 ifq->ifq_altq = NULL; 154 ifq->ifq_altq = NULL;
146 } 155 }
147} 156}
148 157
149/* 158/*
150 * Mark's a device's send queue as being ready for (as in 159 * Mark's a device's send queue as being ready for (as in
151 * "knowledgeable about") ALTQ processing. 160 * "knowledgeable about") ALTQ processing.
152 */ 161 */
153void 162void
154altq_set_ready(struct ifqueue *ifq) 163altq_set_ready(struct ifqueue *ifq)
155{ 164{
156 altq_alloc(ifq, NULL); 165 altq_alloc(ifq, NULL);
157 ifq->ifq_altq->altq_flags = ALTQF_READY; 166 ifq->ifq_altq->altq_flags |= ALTQF_READY;
158} 167}
159 168
160/* look up the queue state by the interface name and the queueing type. */ 169/* look up the queue state by the interface name and the queueing type. */
161void * 170void *
162altq_lookup(char *name, int type) 171altq_lookup(char *name, int type)
163{ 172{
164 struct ifnet *ifp; 173 struct ifnet *ifp;
165 174
166 if ((ifp = ifunit(name)) != NULL) { 175 if ((ifp = ifunit(name)) != NULL) {
167 struct ifaltq *altq = ifp->if_snd.ifq_altq; 176 struct ifaltq *altq = ifp->if_snd.ifq_altq;
168 if (type != ALTQT_NONE && altq->altq_type == type) 177 if (type != ALTQT_NONE && altq->altq_type == type)
169 return (altq->altq_disc); 178 return (altq->altq_disc);
170 } 179 }
171 180
172 return NULL; 181 return NULL;
173} 182}
174 183
175int 184int
176altq_attach(struct ifaltq *ifq, int type, void *discipline, 185altq_attach(struct ifaltq *altq, int type, void *discipline,
177 int (*enqueue)(struct ifaltq *, struct mbuf *), 186 int (*enqueue)(struct ifaltq *, struct mbuf *),
178 struct mbuf *(*dequeue)(struct ifaltq *, int), 187 struct mbuf *(*dequeue)(struct ifaltq *, int),
179 int (*request)(struct ifaltq *, int, void *), 188 int (*request)(struct ifaltq *, int, void *),
180 void *clfier, void *(*classify)(void *, struct mbuf *, int)) 189 void *clfier, void *(*classify)(void *, struct mbuf *, int))
181{ 190{
182 if (!ALTQ_IS_READY(ifq)) 191 struct ifqueue *ifq = altq->altq_ifq;
183 return ENXIO; 192 int error = 0;
 193
 194 mutex_enter(ifq->ifq_lock);
 195
 196 if (!ALTQ_IS_READY(ifq)) {
 197 error = ENXIO;
 198 goto out;
 199 }
184 200
185#ifdef ALTQ3_COMPAT 201#ifdef ALTQ3_COMPAT
186 /* 202 /*
187 * pfaltq can override the existing discipline, but altq3 cannot. 203 * pfaltq can override the existing discipline, but altq3 cannot.
188 * check these if clfier is not NULL (which implies altq3). 204 * check these if clfier is not NULL (which implies altq3).
189 */ 205 */
190 if (clfier != NULL) { 206 if (clfier != NULL) {
191 if (ALTQ_IS_ENABLED(ifq)) 207 if (ALTQ_IS_ENABLED(ifq)) {
192 return EBUSY; 208 error = EBUSY;
193 if (ALTQ_IS_ATTACHED(ifq)) 209 goto out;
194 return EEXIST; 210 }
 211 if (ALTQ_IS_ATTACHED(ifq)) {
 212 error = EEXIST;
 213 goto out;
 214 }
195 } 215 }
196#endif 216#endif
197 ifq->altq_type = type; 217 altq->altq_type = type;
198 ifq->altq_disc = discipline; 218 altq->altq_disc = discipline;
199 ifq->altq_enqueue = enqueue; 219 altq->altq_enqueue = enqueue;
200 ifq->altq_dequeue = dequeue; 220 altq->altq_dequeue = dequeue;
201 ifq->altq_request = request; 221 altq->altq_request = request;
202 ifq->altq_clfier = clfier; 222 altq->altq_clfier = clfier;
203 ifq->altq_classify = classify; 223 altq->altq_classify = classify;
204 ifq->altq_flags &= (ALTQF_CANTCHANGE|ALTQF_ENABLED); 224 altq->altq_flags &= (ALTQF_CANTCHANGE|ALTQF_ENABLED);
205#ifdef ALTQ3_COMPAT 225#ifdef ALTQ3_COMPAT
206#ifdef ALTQ_KLD 226#ifdef ALTQ_KLD
207 altq_module_incref(type); 227 altq_module_incref(type);
208#endif 228#endif
209#endif 229#endif
210 return 0; 230 out:
 231 mutex_exit(ifq->ifq_lock);
 232 return error;
211} 233}
212 234
213int 235int
214altq_detach(struct ifaltq *ifq) 236altq_detach(struct ifaltq *altq)
215{ 237{
216 if (!ALTQ_IS_READY(ifq)) 238 struct ifqueue *ifq = altq->altq_ifq;
217 return ENXIO; 239 int error = 0;
218 if (ALTQ_IS_ENABLED(ifq)) 240
219 return EBUSY; 241 mutex_enter(ifq->ifq_lock);
220 if (!ALTQ_IS_ATTACHED(ifq)) 242
221 return (0); 243 if (!ALTQ_IS_READY(ifq)) {
 244 error = ENXIO;
 245 goto out;
 246 }
 247 if (ALTQ_IS_ENABLED(ifq)) {
 248 error = EBUSY;
 249 goto out;
 250 }
 251 if (!ALTQ_IS_ATTACHED(ifq)) {
 252 goto out;
 253 }
 254
222#ifdef ALTQ3_COMPAT 255#ifdef ALTQ3_COMPAT
223#ifdef ALTQ_KLD 256#ifdef ALTQ_KLD
224 altq_module_declref(ifq->altq_type); 257 altq_module_declref(ifq->altq_type);
225#endif 258#endif
226#endif 259#endif
227 260
228 ifq->altq_type = ALTQT_NONE; 261 altq->altq_type = ALTQT_NONE;
229 ifq->altq_disc = NULL; 262 altq->altq_disc = NULL;
230 ifq->altq_enqueue = NULL; 263 altq->altq_enqueue = NULL;
231 ifq->altq_dequeue = NULL; 264 altq->altq_dequeue = NULL;
232 ifq->altq_request = NULL; 265 altq->altq_request = NULL;
233 ifq->altq_clfier = NULL; 266 altq->altq_clfier = NULL;
234 ifq->altq_classify = NULL; 267 altq->altq_classify = NULL;
235 ifq->altq_flags &= ALTQF_CANTCHANGE; 268 altq->altq_flags &= ALTQF_CANTCHANGE;
236 return 0; 269 out:
 270 mutex_exit(ifq->ifq_lock);
 271 return error;
237} 272}
238 273
239int 274int
240altq_enable(struct ifaltq *ifq) 275altq_enable(struct ifaltq *altq)
241{ 276{
242 int s; 277 struct ifqueue *ifq = altq->altq_ifq;
 278 struct mbuf *m = NULL;
 279 int error = 0;
243 280
244 if (!ALTQ_IS_READY(ifq)) 281 mutex_enter(ifq->ifq_lock);
245 return ENXIO; 
246 if (ALTQ_IS_ENABLED(ifq)) 
247 return 0; 
248 282
249 s = splnet(); 283 if (!ALTQ_IS_READY(ifq)) {
250 IFQ_PURGE(ifq->altq_ifq); 284 error = ENXIO;
251 ASSERT(ALTQ_GET_LEN(ifq) == 0); 285 goto out;
252 ifq->altq_flags |= ALTQF_ENABLED; 286 }
253 if (ifq->altq_clfier != NULL) 287 if (ALTQ_IS_ENABLED(ifq)) {
254 ifq->altq_flags |= ALTQF_CLASSIFY; 288 goto out;
255 splx(s); 289 }
256 290
257 return 0; 291 m = ifq_purge_locked(ifq);
 292 ASSERT(ALTQ_GET_LEN(altq) == 0);
 293 altq->altq_flags |= ALTQF_ENABLED;
 294 if (altq->altq_clfier != NULL)
 295 altq->altq_flags |= ALTQF_CLASSIFY;
 296 out:
 297 mutex_exit(ifq->ifq_lock);
 298 if (m != NULL) {
 299 ifq_purge_free(m);
 300 }
 301 return error;
258} 302}
259 303
260int 304int
261altq_disable(struct ifaltq *ifq) 305altq_disable(struct ifaltq *altq)
262{ 306{
263 int s; 307 struct ifqueue *ifq = altq->altq_ifq;
 308 struct mbuf *m = NULL;
264 309
265 if (!ALTQ_IS_ENABLED(ifq)) 310 mutex_enter(ifq->ifq_lock);
266 return 0; 
267 311
268 s = splnet(); 312 if (!ALTQ_IS_ENABLED(ifq)) {
269 IFQ_PURGE(ifq->altq_ifq); 313 goto out;
270 ASSERT(ALTQ_GET_LEN(ifq) == 0); 314 }
271 ifq->altq_flags &= ~(ALTQF_ENABLED|ALTQF_CLASSIFY); 315
272 splx(s); 316 m = ifq_purge_locked(ifq);
 317 ASSERT(ALTQ_GET_LEN(altq) == 0);
 318 altq->altq_flags &= ~(ALTQF_ENABLED|ALTQF_CLASSIFY);
 319 out:
 320 mutex_exit(ifq->ifq_lock);
 321 if (m != NULL) {
 322 ifq_purge_free(m);
 323 }
273 return 0; 324 return 0;
274} 325}
275 326
276#ifdef ALTQ_DEBUG 327#ifdef ALTQ_DEBUG
277void 328void
278altq_assert(const char *file, int line, const char *failedexpr) 329altq_assert(const char *file, int line, const char *failedexpr)
279{ 330{
280 (void)printf("altq assertion \"%s\" failed: file \"%s\", line %d\n", 331 (void)printf("altq assertion \"%s\" failed: file \"%s\", line %d\n",
281 failedexpr, file, line); 332 failedexpr, file, line);
282 panic("altq assertion"); 333 panic("altq assertion");
283 /* NOTREACHED */ 334 /* NOTREACHED */
284} 335}
285#endif 336#endif

cvs diff -r1.529.2.1.2.2 -r1.529.2.1.2.3 src/sys/net/if.c (expand / switch to unified diff)

--- src/sys/net/if.c 2023/11/15 02:08:33 1.529.2.1.2.2
+++ src/sys/net/if.c 2023/11/15 02:19:00 1.529.2.1.2.3
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: if.c,v 1.529.2.1.2.2 2023/11/15 02:08:33 thorpej Exp $ */ 1/* $NetBSD: if.c,v 1.529.2.1.2.3 2023/11/15 02:19:00 thorpej Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 1999, 2000, 2001, 2008, 2023 The NetBSD Foundation, Inc. 4 * Copyright (c) 1999, 2000, 2001, 2008, 2023 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by William Studenmund and Jason R. Thorpe. 8 * by William Studenmund and Jason R. Thorpe.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -80,37 +80,39 @@ @@ -80,37 +80,39 @@
80 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 80 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
81 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 81 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
82 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 82 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
83 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 83 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
84 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 84 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
85 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 85 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
86 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 86 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
87 * SUCH DAMAGE. 87 * SUCH DAMAGE.
88 * 88 *
89 * @(#)if.c 8.5 (Berkeley) 1/9/95 89 * @(#)if.c 8.5 (Berkeley) 1/9/95
90 */ 90 */
91 91
92#include <sys/cdefs.h> 92#include <sys/cdefs.h>
93__KERNEL_RCSID(0, "$NetBSD: if.c,v 1.529.2.1.2.2 2023/11/15 02:08:33 thorpej Exp $"); 93__KERNEL_RCSID(0, "$NetBSD: if.c,v 1.529.2.1.2.3 2023/11/15 02:19:00 thorpej Exp $");
94 94
95#if defined(_KERNEL_OPT) 95#if defined(_KERNEL_OPT)
96#include "opt_inet.h" 96#include "opt_inet.h"
97#include "opt_ipsec.h" 97#include "opt_ipsec.h"
98#include "opt_atalk.h" 98#include "opt_atalk.h"
99#include "opt_wlan.h" 99#include "opt_wlan.h"
100#include "opt_net_mpsafe.h" 100#include "opt_net_mpsafe.h"
101#include "opt_mrouting.h" 101#include "opt_mrouting.h"
102#endif 102#endif
103 103
 104#define __IFQ_PRIVATE
 105
104#include <sys/param.h> 106#include <sys/param.h>
105#include <sys/mbuf.h> 107#include <sys/mbuf.h>
106#include <sys/systm.h> 108#include <sys/systm.h>
107#include <sys/callout.h> 109#include <sys/callout.h>
108#include <sys/condvar.h> 110#include <sys/condvar.h>
109#include <sys/proc.h> 111#include <sys/proc.h>
110#include <sys/socket.h> 112#include <sys/socket.h>
111#include <sys/socketvar.h> 113#include <sys/socketvar.h>
112#include <sys/domain.h> 114#include <sys/domain.h>
113#include <sys/protosw.h> 115#include <sys/protosw.h>
114#include <sys/kernel.h> 116#include <sys/kernel.h>
115#include <sys/ioctl.h> 117#include <sys/ioctl.h>
116#include <sys/sysctl.h> 118#include <sys/sysctl.h>
@@ -1377,30 +1379,26 @@ if_detach(struct ifnet *ifp) @@ -1377,30 +1379,26 @@ if_detach(struct ifnet *ifp)
1377 kmem_free(isd, sizeof(*isd)); 1379 kmem_free(isd, sizeof(*isd));
1378 1380
1379 ifp->if_slowtimo_data = NULL; /* paraonia */ 1381 ifp->if_slowtimo_data = NULL; /* paraonia */
1380 ifp->if_slowtimo = NULL; /* paranoia */ 1382 ifp->if_slowtimo = NULL; /* paranoia */
1381 } 1383 }
1382 if_deferred_start_destroy(ifp); 1384 if_deferred_start_destroy(ifp);
1383 1385
1384 /* 1386 /*
1385 * Do an if_down() to give protocols a chance to do something. 1387 * Do an if_down() to give protocols a chance to do something.
1386 */ 1388 */
1387 if_down_deactivated(ifp); 1389 if_down_deactivated(ifp);
1388 1390
1389#ifdef ALTQ 1391#ifdef ALTQ
1390 if (ALTQ_IS_ENABLED(&ifp->if_snd)) 
1391 altq_disable(ifp->if_snd.ifq_altq); 
1392 if (ALTQ_IS_ATTACHED(&ifp->if_snd)) 
1393 altq_detach(ifp->if_snd.ifq_altq); 
1394 altq_free(&ifp->if_snd); 1392 altq_free(&ifp->if_snd);
1395#endif 1393#endif
1396 1394
1397#if NCARP > 0 1395#if NCARP > 0
1398 /* Remove the interface from any carp group it is a part of. */ 1396 /* Remove the interface from any carp group it is a part of. */
1399 if (ifp->if_carp != NULL && ifp->if_type != IFT_CARP) 1397 if (ifp->if_carp != NULL && ifp->if_type != IFT_CARP)
1400 carp_ifdetach(ifp); 1398 carp_ifdetach(ifp);
1401#endif 1399#endif
1402 1400
1403 /* 1401 /*
1404 * Ensure that all packets on protocol input pktqueues have been 1402 * Ensure that all packets on protocol input pktqueues have been
1405 * processed, or, at least, removed from the queues. 1403 * processed, or, at least, removed from the queues.
1406 * 1404 *
@@ -4332,59 +4330,75 @@ ifq_purge_slow(struct ifqueue * const if @@ -4332,59 +4330,75 @@ ifq_purge_slow(struct ifqueue * const if
4332 ifq->ifq_len = 0; 4330 ifq->ifq_len = 0;
4333 } 4331 }
4334 KERNEL_UNLOCK_ONE(NULL); 4332 KERNEL_UNLOCK_ONE(NULL);
4335 4333
4336 return m; 4334 return m;
4337} 4335}
4338#endif /* ALTQ */ 4336#endif /* ALTQ */
4339 4337
4340/* 4338/*
4341 * ifq_purge -- 4339 * ifq_purge --
4342 * 4340 *
4343 * Purge all of the packets from the specified interface queue. 4341 * Purge all of the packets from the specified interface queue.
4344 */ 4342 */
4345void 4343struct mbuf *
4346ifq_purge(struct ifqueue * const ifq) 4344ifq_purge_locked(struct ifqueue * const ifq)
4347{ 4345{
4348 struct mbuf *m, *nextm; 4346 struct mbuf *m;
4349 
4350 mutex_enter(ifq->ifq_lock); 
4351 4347
4352#ifdef ALTQ 4348#ifdef ALTQ
4353 if (__predict_false(ALTQ_IS_ENABLED(ifq))) 4349 if (__predict_false(ALTQ_IS_ENABLED(ifq)))
4354 m = ifq_purge_slow(ifq); 4350 m = ifq_purge_slow(ifq);
4355 else 4351 else
4356#endif /* ALTQ */ 4352#endif /* ALTQ */
4357 { 4353 {
4358 m = ifq->ifq_head; 4354 m = ifq->ifq_head;
4359 ifq->ifq_head = ifq->ifq_tail = NULL; 4355 ifq->ifq_head = ifq->ifq_tail = NULL;
4360 ifq->ifq_len = 0; 4356 ifq->ifq_len = 0;
4361 } 4357 }
4362 4358
4363 if (ifq->ifq_staged != NULL) { 4359 if (ifq->ifq_staged != NULL) {
4364 ifq->ifq_staged->m_nextpkt = m; 4360 ifq->ifq_staged->m_nextpkt = m;
4365 m = ifq->ifq_staged; 4361 m = ifq->ifq_staged;
4366 ifq->ifq_staged = NULL; 4362 ifq->ifq_staged = NULL;
4367 } 4363 }
4368 4364
4369 mutex_exit(ifq->ifq_lock); 4365 return m;
 4366}
 4367
 4368void
 4369ifq_purge_free(struct mbuf *m)
 4370{
 4371 struct mbuf *nextm;
4370 4372
4371 for (; m != NULL; m = nextm) { 4373 for (; m != NULL; m = nextm) {
4372 nextm = m->m_nextpkt; 4374 nextm = m->m_nextpkt;
4373 m->m_nextpkt = NULL; 4375 m->m_nextpkt = NULL;
4374 m_freem(m); 4376 m_freem(m);
4375 } 4377 }
4376} 4378}
4377 4379
 4380void
 4381ifq_purge(struct ifqueue * const ifq)
 4382{
 4383 struct mbuf *m;
 4384
 4385 mutex_enter(ifq->ifq_lock);
 4386 m = ifq_purge_locked(ifq);
 4387 mutex_exit(ifq->ifq_lock);
 4388
 4389 ifq_purge_free(m);
 4390}
 4391
4378/* 4392/*
4379 * ifq_classify_packet -- 4393 * ifq_classify_packet --
4380 * 4394 *
4381 * Decorate a packet with classificaiton information per the 4395 * Decorate a packet with classificaiton information per the
4382 * queue's queueing discipline. 4396 * queue's queueing discipline.
4383 * 4397 *
4384 * XXX This should be a private function. It's unfortunate that 4398 * XXX This should be a private function. It's unfortunate that
4385 * XXX it's called from where it's called. 4399 * XXX it's called from where it's called.
4386 */ 4400 */
4387void 4401void
4388ifq_classify_packet(struct ifqueue * const ifq, struct mbuf * const m, 4402ifq_classify_packet(struct ifqueue * const ifq, struct mbuf * const m,
4389 sa_family_t af) 4403 sa_family_t af)
4390{ 4404{

cvs diff -r1.305.2.1.2.2 -r1.305.2.1.2.3 src/sys/net/if.h (expand / switch to unified diff)

--- src/sys/net/if.h 2023/11/15 02:08:34 1.305.2.1.2.2
+++ src/sys/net/if.h 2023/11/15 02:19:00 1.305.2.1.2.3
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: if.h,v 1.305.2.1.2.2 2023/11/15 02:08:34 thorpej Exp $ */ 1/* $NetBSD: if.h,v 1.305.2.1.2.3 2023/11/15 02:19:00 thorpej Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 1999, 2000, 2001, 2023 The NetBSD Foundation, Inc. 4 * Copyright (c) 1999, 2000, 2001, 2023 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by William Studenmund and Jason R. Thorpe. 8 * by William Studenmund and Jason R. Thorpe.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -1260,26 +1260,31 @@ void ifq_set_maxlen(struct ifqueue *, u @@ -1260,26 +1260,31 @@ void ifq_set_maxlen(struct ifqueue *, u
1260unsigned int ifq_maxlen(struct ifqueue *); 1260unsigned int ifq_maxlen(struct ifqueue *);
1261uint64_t ifq_drops(struct ifqueue *); 1261uint64_t ifq_drops(struct ifqueue *);
1262struct mbuf * ifq_get(struct ifqueue *); 1262struct mbuf * ifq_get(struct ifqueue *);
1263struct mbuf * ifq_stage(struct ifqueue *); 1263struct mbuf * ifq_stage(struct ifqueue *);
1264int ifq_put(struct ifqueue *, struct mbuf *); 1264int ifq_put(struct ifqueue *, struct mbuf *);
1265void ifq_restage(struct ifqueue *, struct mbuf *, struct mbuf *); 1265void ifq_restage(struct ifqueue *, struct mbuf *, struct mbuf *);
1266void ifq_commit(struct ifqueue *, struct mbuf *); 1266void ifq_commit(struct ifqueue *, struct mbuf *);
1267void ifq_abort(struct ifqueue *, struct mbuf *); 1267void ifq_abort(struct ifqueue *, struct mbuf *);
1268bool ifq_continue(struct ifqueue *); 1268bool ifq_continue(struct ifqueue *);
1269void ifq_purge(struct ifqueue *); 1269void ifq_purge(struct ifqueue *);
1270void ifq_classify_packet(struct ifqueue *, struct mbuf *, 1270void ifq_classify_packet(struct ifqueue *, struct mbuf *,
1271 sa_family_t); 1271 sa_family_t);
1272 1272
 1273#ifdef __IFQ_PRIVATE
 1274struct mbuf * ifq_purge_locked(struct ifqueue *);
 1275void ifq_purge_free(struct mbuf *);
 1276#endif /* __IFQ_PRIVATE */
 1277
1273int if_tunnel_check_nesting(struct ifnet *, struct mbuf *, int); 1278int if_tunnel_check_nesting(struct ifnet *, struct mbuf *, int);
1274percpu_t *if_tunnel_alloc_ro_percpu(void); 1279percpu_t *if_tunnel_alloc_ro_percpu(void);
1275void if_tunnel_free_ro_percpu(percpu_t *); 1280void if_tunnel_free_ro_percpu(percpu_t *);
1276void if_tunnel_ro_percpu_rtcache_free(percpu_t *); 1281void if_tunnel_ro_percpu_rtcache_free(percpu_t *);
1277 1282
1278struct tunnel_ro { 1283struct tunnel_ro {
1279 struct route *tr_ro; 1284 struct route *tr_ro;
1280 kmutex_t *tr_lock; 1285 kmutex_t *tr_lock;
1281}; 1286};
1282 1287
1283static inline void 1288static inline void
1284if_tunnel_get_ro(percpu_t *ro_percpu, struct route **ro, kmutex_t **lock) 1289if_tunnel_get_ro(percpu_t *ro_percpu, struct route **ro, kmutex_t **lock)
1285{ 1290{