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_ */ 320