Merge branch 'vendor/GDB'
[dragonfly.git] / sys / net / ifq_var.h
1 /*-
2  * Copyright (c) 2005 The DragonFly Project.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in
12  *    the documentation and/or other materials provided with the
13  *    distribution.
14  * 3. Neither the name of The DragonFly Project nor the names of its
15  *    contributors may be used to endorse or promote products derived
16  *    from this software without specific, prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
22  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
24  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
28  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  */
31 /*
32  * NOTE ON MPSAFE access.  Routines which manipulate the packet queue must
33  * be called within a critical section to interlock subsystems based on
34  * the MP lock, and must be holding the interface serializer to interlock
35  * MPSAFE subsystems.  Once all subsystems are made MPSAFE, the critical
36  * section will no longer be required.
37  */
38
39 #ifndef _NET_IFQ_VAR_H_
40 #define _NET_IFQ_VAR_H_
41
42 #ifndef _KERNEL
43
44 #error "This file should not be included by userland programs."
45
46 #else
47
48 #ifndef _SYS_SYSTM_H_
49 #include <sys/systm.h>
50 #endif
51 #ifndef _SYS_THREAD2_H_
52 #include <sys/thread2.h>
53 #endif
54 #ifndef _SYS_SERIALIZE_H_
55 #include <sys/serialize.h>
56 #endif
57 #ifndef _SYS_MBUF_H_
58 #include <sys/mbuf.h>
59 #endif
60 #ifndef _NET_IF_VAR_H_
61 #include <net/if_var.h>
62 #endif
63 #ifndef _NET_ALTQ_IF_ALTQ_H_
64 #include <net/altq/if_altq.h>
65 #endif
66
67 struct ifaltq;
68
69 /*
70  * Support for non-ALTQ interfaces.
71  */
72 int             ifq_classic_enqueue(struct ifaltq *, struct mbuf *,
73                                     struct altq_pktattr *);
74 struct mbuf     *ifq_classic_dequeue(struct ifaltq *, struct mbuf *, int);
75 int             ifq_classic_request(struct ifaltq *, int, void *);
76 void            ifq_set_classic(struct ifaltq *);
77
78 int             ifq_dispatch(struct ifnet *, struct mbuf *,
79                              struct altq_pktattr *);
80
81 #ifdef ALTQ
82 static __inline int
83 ifq_is_enabled(struct ifaltq *_ifq)
84 {
85         return(_ifq->altq_flags & ALTQF_ENABLED);
86 }
87
88 static __inline int
89 ifq_is_attached(struct ifaltq *_ifq)
90 {
91         return(_ifq->altq_disc != NULL);
92 }
93 #else
94 static __inline int
95 ifq_is_enabled(struct ifaltq *_ifq)
96 {
97         return(0);
98 }
99
100 static __inline int
101 ifq_is_attached(struct ifaltq *_ifq)
102 {
103         return(0);
104 }
105 #endif
106
107 /*
108  * WARNING: Should only be called in an MPSAFE manner.
109  */
110 static __inline int
111 ifq_is_ready(struct ifaltq *_ifq)
112 {
113         return(_ifq->altq_flags & ALTQF_READY);
114 }
115
116 /*
117  * WARNING: Should only be called in an MPSAFE manner.
118  */
119 static __inline void
120 ifq_set_ready(struct ifaltq *_ifq)
121 {
122         _ifq->altq_flags |= ALTQF_READY;
123 }
124
125 /*
126  * WARNING: Should only be called in an MPSAFE manner.
127  */
128 static __inline int
129 ifq_enqueue_locked(struct ifaltq *_ifq, struct mbuf *_m,
130                    struct altq_pktattr *_pa)
131 {
132 #ifdef ALTQ
133         if (!ifq_is_enabled(_ifq))
134                 return ifq_classic_enqueue(_ifq, _m, _pa);
135         else
136 #endif
137         return _ifq->altq_enqueue(_ifq, _m, _pa);
138 }
139
140 static __inline int
141 ifq_enqueue(struct ifaltq *_ifq, struct mbuf *_m, struct altq_pktattr *_pa)
142 {
143         int _error;
144
145         ALTQ_LOCK(_ifq);
146         _error = ifq_enqueue_locked(_ifq, _m, _pa);
147         ALTQ_UNLOCK(_ifq);
148         return _error;
149 }
150
151 /*
152  * WARNING: Should only be called in an MPSAFE manner.
153  */
154 static __inline struct mbuf *
155 ifq_dequeue(struct ifaltq *_ifq, struct mbuf *_mpolled)
156 {
157         struct mbuf *_m;
158
159         ALTQ_LOCK(_ifq);
160         if (_ifq->altq_prepended != NULL) {
161                 _m = _ifq->altq_prepended;
162                 _ifq->altq_prepended = NULL;
163                 KKASSERT(_ifq->ifq_len > 0);
164                 _ifq->ifq_len--;
165                 ALTQ_UNLOCK(_ifq);
166                 return _m;
167         }
168
169 #ifdef ALTQ
170         if (_ifq->altq_tbr != NULL)
171                 _m = tbr_dequeue(_ifq, _mpolled, ALTDQ_REMOVE);
172         else if (!ifq_is_enabled(_ifq))
173                 _m = ifq_classic_dequeue(_ifq, _mpolled, ALTDQ_REMOVE);
174         else
175 #endif
176         _m = _ifq->altq_dequeue(_ifq, _mpolled, ALTDQ_REMOVE);
177         ALTQ_UNLOCK(_ifq);
178         return _m;
179 }
180
181 /*
182  * WARNING: Should only be called in an MPSAFE manner.
183  */
184 static __inline struct mbuf *
185 ifq_poll_locked(struct ifaltq *_ifq)
186 {
187         if (_ifq->altq_prepended != NULL)
188                 return _ifq->altq_prepended;
189
190 #ifdef ALTQ
191         if (_ifq->altq_tbr != NULL)
192                 return tbr_dequeue(_ifq, NULL, ALTDQ_POLL);
193         else if (!ifq_is_enabled(_ifq))
194                 return ifq_classic_dequeue(_ifq, NULL, ALTDQ_POLL);
195         else
196 #endif
197         return _ifq->altq_dequeue(_ifq, NULL, ALTDQ_POLL);
198 }
199
200 static __inline struct mbuf *
201 ifq_poll(struct ifaltq *_ifq)
202 {
203         struct mbuf *_m;
204
205         ALTQ_LOCK(_ifq);
206         _m = ifq_poll_locked(_ifq);
207         ALTQ_UNLOCK(_ifq);
208         return _m;
209 }
210
211 /*
212  * WARNING: Should only be called in an MPSAFE manner.
213  */
214 static __inline void
215 ifq_purge_locked(struct ifaltq *_ifq)
216 {
217         if (_ifq->altq_prepended != NULL) {
218                 m_freem(_ifq->altq_prepended);
219                 _ifq->altq_prepended = NULL;
220                 KKASSERT(_ifq->ifq_len > 0);
221                 _ifq->ifq_len--;
222         }
223
224 #ifdef ALTQ
225         if (!ifq_is_enabled(_ifq))
226                 ifq_classic_request(_ifq, ALTRQ_PURGE, NULL);
227         else
228 #endif
229         _ifq->altq_request(_ifq, ALTRQ_PURGE, NULL);
230 }
231
232 static __inline void
233 ifq_purge(struct ifaltq *_ifq)
234 {
235         ALTQ_LOCK(_ifq);
236         ifq_purge_locked(_ifq);
237         ALTQ_UNLOCK(_ifq);
238 }
239
240 /*
241  * WARNING: Should only be called in an MPSAFE manner.
242  */
243 static __inline void
244 ifq_classify(struct ifaltq *_ifq, struct mbuf *_m, uint8_t _af,
245              struct altq_pktattr *_pa)
246 {
247 #ifdef ALTQ
248         ALTQ_LOCK(_ifq);
249         if (ifq_is_enabled(_ifq)) {
250                 _pa->pattr_af = _af;
251                 _pa->pattr_hdr = mtod(_m, caddr_t);
252                 if (_ifq->altq_flags & ALTQF_CLASSIFY)
253                         _ifq->altq_classify(_ifq, _m, _pa);
254         }
255         ALTQ_UNLOCK(_ifq);
256 #endif
257 }
258
259 static __inline void
260 ifq_prepend(struct ifaltq *_ifq, struct mbuf *_m)
261 {
262         ALTQ_LOCK(_ifq);
263         KASSERT(_ifq->altq_prepended == NULL, ("pending prepended mbuf"));
264         _ifq->altq_prepended = _m;
265         _ifq->ifq_len++;
266         ALTQ_UNLOCK(_ifq);
267 }
268
269 /*
270  * Hand a packet to an interface. 
271  *
272  * For subsystems protected by the MP lock, access to the queue is protected
273  * by a critical section.
274  *
275  * For MPSAFE subsystems and drivers, access to the queue is protected by
276  * the ifnet serializer.
277  */
278 static __inline int
279 ifq_handoff(struct ifnet *_ifp, struct mbuf *_m, struct altq_pktattr *_pa)
280 {
281         int _error;
282
283         ASSERT_IFNET_SERIALIZED_TX(_ifp);
284         _error = ifq_enqueue(&_ifp->if_snd, _m, _pa);
285         if (_error == 0) {
286                 _ifp->if_obytes += _m->m_pkthdr.len;
287                 if (_m->m_flags & M_MCAST)
288                         _ifp->if_omcasts++;
289                 if ((_ifp->if_flags & IFF_OACTIVE) == 0)
290                         (*_ifp->if_start)(_ifp);
291         }
292         return(_error);
293 }
294
295 static __inline int
296 ifq_is_empty(struct ifaltq *_ifq)
297 {
298         return(_ifq->ifq_len == 0);
299 }
300
301 static __inline void
302 ifq_set_maxlen(struct ifaltq *_ifq, int _len)
303 {
304         _ifq->ifq_maxlen = _len;
305 }
306
307 static __inline int
308 ifq_data_ready(struct ifaltq *_ifq)
309 {
310 #ifdef ALTQ
311         if (_ifq->altq_tbr != NULL)
312                 return (ifq_poll_locked(_ifq) != NULL);
313         else
314 #endif
315         return !ifq_is_empty(_ifq);
316 }
317
318 #endif  /* _KERNEL */
319 #endif  /* _NET_IFQ_VAR_H_ */