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 * $DragonFly: src/sys/net/ifq_var.h,v 1.10 2008/05/14 11:59:23 sephe Exp $ 32 */ 33 /* 34 * NOTE ON MPSAFE access. Routines which manipulate the packet queue must 35 * be called within a critical section to interlock subsystems based on 36 * the MP lock, and must be holding the interface serializer to interlock 37 * MPSAFE subsystems. Once all subsystems are made MPSAFE, the critical 38 * section will no longer be required. 39 */ 40 41 #ifndef _NET_IFQ_VAR_H_ 42 #define _NET_IFQ_VAR_H_ 43 44 #ifndef _KERNEL 45 46 #error "This file should not be included by userland programs." 47 48 #else 49 50 #ifndef _SYS_SYSTM_H_ 51 #include <sys/systm.h> 52 #endif 53 #ifndef _SYS_THREAD2_H_ 54 #include <sys/thread2.h> 55 #endif 56 #ifndef _SYS_SERIALIZE_H_ 57 #include <sys/serialize.h> 58 #endif 59 #ifndef _SYS_MBUF_H_ 60 #include <sys/mbuf.h> 61 #endif 62 #ifndef _NET_IF_VAR_H_ 63 #include <net/if_var.h> 64 #endif 65 #ifndef _NET_ALTQ_IF_ALTQ_H_ 66 #include <net/altq/if_altq.h> 67 #endif 68 69 struct ifaltq; 70 71 /* 72 * Support for non-ALTQ interfaces. 73 */ 74 int ifq_classic_enqueue(struct ifaltq *, struct mbuf *, 75 struct altq_pktattr *); 76 struct mbuf *ifq_classic_dequeue(struct ifaltq *, struct mbuf *, int); 77 int ifq_classic_request(struct ifaltq *, int, void *); 78 void ifq_set_classic(struct ifaltq *); 79 80 int ifq_dispatch(struct ifnet *, struct mbuf *, 81 struct altq_pktattr *); 82 83 #ifdef ALTQ 84 static __inline int 85 ifq_is_enabled(struct ifaltq *_ifq) 86 { 87 return(_ifq->altq_flags & ALTQF_ENABLED); 88 } 89 90 static __inline int 91 ifq_is_attached(struct ifaltq *_ifq) 92 { 93 return(_ifq->altq_disc != NULL); 94 } 95 #else 96 static __inline int 97 ifq_is_enabled(struct ifaltq *_ifq) 98 { 99 return(0); 100 } 101 102 static __inline int 103 ifq_is_attached(struct ifaltq *_ifq) 104 { 105 return(0); 106 } 107 #endif 108 109 /* 110 * WARNING: Should only be called in an MPSAFE manner. 111 */ 112 static __inline int 113 ifq_is_ready(struct ifaltq *_ifq) 114 { 115 return(_ifq->altq_flags & ALTQF_READY); 116 } 117 118 /* 119 * WARNING: Should only be called in an MPSAFE manner. 120 */ 121 static __inline void 122 ifq_set_ready(struct ifaltq *_ifq) 123 { 124 _ifq->altq_flags |= ALTQF_READY; 125 } 126 127 /* 128 * WARNING: Should only be called in an MPSAFE manner. 129 */ 130 static __inline int 131 ifq_enqueue_locked(struct ifaltq *_ifq, struct mbuf *_m, 132 struct altq_pktattr *_pa) 133 { 134 #ifdef ALTQ 135 if (!ifq_is_enabled(_ifq)) 136 return ifq_classic_enqueue(_ifq, _m, _pa); 137 else 138 #endif 139 return _ifq->altq_enqueue(_ifq, _m, _pa); 140 } 141 142 static __inline int 143 ifq_enqueue(struct ifaltq *_ifq, struct mbuf *_m, struct altq_pktattr *_pa) 144 { 145 int _error; 146 147 ALTQ_LOCK(_ifq); 148 _error = ifq_enqueue_locked(_ifq, _m, _pa); 149 ALTQ_UNLOCK(_ifq); 150 return _error; 151 } 152 153 /* 154 * WARNING: Should only be called in an MPSAFE manner. 155 */ 156 static __inline struct mbuf * 157 ifq_dequeue(struct ifaltq *_ifq, struct mbuf *_mpolled) 158 { 159 struct mbuf *_m; 160 161 ALTQ_LOCK(_ifq); 162 if (_ifq->altq_prepended != NULL) { 163 _m = _ifq->altq_prepended; 164 _ifq->altq_prepended = NULL; 165 KKASSERT(_ifq->ifq_len > 0); 166 _ifq->ifq_len--; 167 ALTQ_UNLOCK(_ifq); 168 return _m; 169 } 170 171 #ifdef ALTQ 172 if (_ifq->altq_tbr != NULL) 173 _m = tbr_dequeue(_ifq, _mpolled, ALTDQ_REMOVE); 174 else if (!ifq_is_enabled(_ifq)) 175 _m = ifq_classic_dequeue(_ifq, _mpolled, ALTDQ_REMOVE); 176 else 177 #endif 178 _m = _ifq->altq_dequeue(_ifq, _mpolled, ALTDQ_REMOVE); 179 ALTQ_UNLOCK(_ifq); 180 return _m; 181 } 182 183 /* 184 * WARNING: Should only be called in an MPSAFE manner. 185 */ 186 static __inline struct mbuf * 187 ifq_poll_locked(struct ifaltq *_ifq) 188 { 189 if (_ifq->altq_prepended != NULL) 190 return _ifq->altq_prepended; 191 192 #ifdef ALTQ 193 if (_ifq->altq_tbr != NULL) 194 return tbr_dequeue(_ifq, NULL, ALTDQ_POLL); 195 else if (!ifq_is_enabled(_ifq)) 196 return ifq_classic_dequeue(_ifq, NULL, ALTDQ_POLL); 197 else 198 #endif 199 return _ifq->altq_dequeue(_ifq, NULL, ALTDQ_POLL); 200 } 201 202 static __inline struct mbuf * 203 ifq_poll(struct ifaltq *_ifq) 204 { 205 struct mbuf *_m; 206 207 ALTQ_LOCK(_ifq); 208 _m = ifq_poll_locked(_ifq); 209 ALTQ_UNLOCK(_ifq); 210 return _m; 211 } 212 213 /* 214 * WARNING: Should only be called in an MPSAFE manner. 215 */ 216 static __inline void 217 ifq_purge_locked(struct ifaltq *_ifq) 218 { 219 if (_ifq->altq_prepended != NULL) { 220 m_freem(_ifq->altq_prepended); 221 _ifq->altq_prepended = NULL; 222 KKASSERT(_ifq->ifq_len > 0); 223 _ifq->ifq_len--; 224 } 225 226 #ifdef ALTQ 227 if (!ifq_is_enabled(_ifq)) 228 ifq_classic_request(_ifq, ALTRQ_PURGE, NULL); 229 else 230 #endif 231 _ifq->altq_request(_ifq, ALTRQ_PURGE, NULL); 232 } 233 234 static __inline void 235 ifq_purge(struct ifaltq *_ifq) 236 { 237 ALTQ_LOCK(_ifq); 238 ifq_purge_locked(_ifq); 239 ALTQ_UNLOCK(_ifq); 240 } 241 242 /* 243 * WARNING: Should only be called in an MPSAFE manner. 244 */ 245 static __inline void 246 ifq_classify(struct ifaltq *_ifq, struct mbuf *_m, uint8_t _af, 247 struct altq_pktattr *_pa) 248 { 249 #ifdef ALTQ 250 ALTQ_LOCK(_ifq); 251 if (ifq_is_enabled(_ifq)) { 252 _pa->pattr_af = _af; 253 _pa->pattr_hdr = mtod(_m, caddr_t); 254 if (_ifq->altq_flags & ALTQF_CLASSIFY) 255 _ifq->altq_classify(_ifq, _m, _pa); 256 } 257 ALTQ_UNLOCK(_ifq); 258 #endif 259 } 260 261 static __inline void 262 ifq_prepend(struct ifaltq *_ifq, struct mbuf *_m) 263 { 264 ALTQ_LOCK(_ifq); 265 KASSERT(_ifq->altq_prepended == NULL, ("pending prepended mbuf\n")); 266 _ifq->altq_prepended = _m; 267 _ifq->ifq_len++; 268 ALTQ_UNLOCK(_ifq); 269 } 270 271 /* 272 * Hand a packet to an interface. 273 * 274 * For subsystems protected by the MP lock, access to the queue is protected 275 * by a critical section. 276 * 277 * For MPSAFE subsystems and drivers, access to the queue is protected by 278 * the ifnet serializer. 279 */ 280 static __inline int 281 ifq_handoff(struct ifnet *_ifp, struct mbuf *_m, struct altq_pktattr *_pa) 282 { 283 int _error; 284 285 ASSERT_SERIALIZED(_ifp->if_serializer); 286 _error = ifq_enqueue(&_ifp->if_snd, _m, _pa); 287 if (_error == 0) { 288 _ifp->if_obytes += _m->m_pkthdr.len; 289 if (_m->m_flags & M_MCAST) 290 _ifp->if_omcasts++; 291 if ((_ifp->if_flags & IFF_OACTIVE) == 0) 292 (*_ifp->if_start)(_ifp); 293 } 294 return(_error); 295 } 296 297 static __inline int 298 ifq_is_empty(struct ifaltq *_ifq) 299 { 300 return(_ifq->ifq_len == 0); 301 } 302 303 static __inline void 304 ifq_set_maxlen(struct ifaltq *_ifq, int _len) 305 { 306 _ifq->ifq_maxlen = _len; 307 } 308 309 static __inline int 310 ifq_data_ready(struct ifaltq *_ifq) 311 { 312 #ifdef ALTQ 313 if (_ifq->altq_tbr != NULL) 314 return (ifq_poll_locked(_ifq) != NULL); 315 else 316 #endif 317 return !ifq_is_empty(_ifq); 318 } 319 320 #endif /* _KERNEL */ 321 #endif /* _NET_IFQ_VAR_H_ */ 322