1/* 2 * Copyright (c) 1998-2008 Apple Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * The contents of this file constitute Original Code as defined in and 7 * are subject to the Apple Public Source License Version 1.1 (the 8 * "License"). You may not use this file except in compliance with the 9 * License. Please obtain a copy of the License at 10 * http://www.apple.com/publicsource and read it before using this file. 11 * 12 * This Original Code and all software distributed under the License are 13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER 14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the 17 * License for the specific language governing rights and limitations 18 * under the License. 19 * 20 * @APPLE_LICENSE_HEADER_END@ 21 */ 22 23#ifndef _IOBASICOUTPUTQUEUE_H 24#define _IOBASICOUTPUTQUEUE_H 25 26#include <IOKit/IOLocks.h> 27#include <IOKit/network/IOOutputQueue.h> 28#include <IOKit/network/IOPacketQueue.h> 29 30struct IOMbufQueue; 31 32/*! @class IOBasicOutputQueue 33 @abstract A concrete implementation of an IOOutputQueue. 34 @discussion This object uses a mutex to protect the packet queue from 35 multiple producers. 36 A single producer is promoted to become a consumer when the queue is 37 not active. Otherwise, the producer will simply queue the packet and 38 return without blocking. 39 40 The flow of packets from the queue to its target can be controlled 41 by calling methods such as start(), stop(), or service(). The target 42 is expected to call those methods from a single threaded context, 43 i.e. the work loop context in a network driver. In addition, the 44 target must also return a status for every packet delivered by the 45 consumer thread. This return value is the only mechanism that the 46 target can use to manage the queue when it is running on the 47 consumer thread. 48*/ 49 50class IOBasicOutputQueue : public IOOutputQueue 51{ 52 OSDeclareDefaultStructors( IOBasicOutputQueue ) 53 54private: 55 static IOReturn dispatchNetworkDataNotification(void * target, 56 void * param, 57 IONetworkData * data, 58 UInt32 type); 59 60 void dequeue(); 61 62protected: 63 OSObject * _target; 64 IOOutputAction _action; 65 UInt32 _priorities; 66 IOOutputQueueStats * _stats; 67 IONetworkData * _statsData; 68 IOLock * _queueLock; 69 IOMbufQueue * _inQueues; 70 IOMbufQueue * _primaryQueues; 71 IOMbufQueue * _shadowQueues; 72 volatile bool _waitDequeueDone; 73 volatile UInt32 _state; 74 volatile UInt32 _serviceCount; 75 76/*! @function serviceThread 77 @abstract Provides an implementation for the serviceThread() method 78 defined in IOOutputQueue. 79 @discussion This method is called by the scheduled service thread when it 80 starts to run. The service thread is scheduled by service() 81 to restart a stalled queue when the kServiceAsync option is given. 82 @param param A parameter that was given to scheduleServiceThread(). 83 This parameter is not used. 84*/ 85 86 virtual void serviceThread(void * param); 87 88/*! @function output 89 @abstract Transfers all packets in the mbuf queue to the target. 90 @param queue A queue of output packets. 91 @param state Returns a state bit defined by IOBasicOutputQueue that 92 declares the new state of the queue following this method call. 93 A kStateStalled is returned if the queue should stall, otherwise 0 94 is returned. 95*/ 96 97 virtual void output(IOMbufQueue * queue, UInt32 * state); 98 99/*! @function free 100 @abstract Frees the IOBasicOutputQueue object. 101 @discussion This function releases allocated resources, then call super::free(). 102*/ 103 104 virtual void free(); 105 106/*! @function handleNetworkDataAccess 107 @abstract Handles an external access to the IONetworkData object 108 returned by getStatisticsData(). 109 @param data The IONetworkData object being accessed. 110 @param type Description of the type of access being performed. 111 @param param An optional parameter for the handler. 112 @result Returns kIOReturnSuccess on success, or an error code otherwise. 113*/ 114 115 virtual IOReturn handleNetworkDataAccess(IONetworkData * data, 116 UInt32 type, 117 void * param); 118 119public: 120 121/*! @function init 122 @abstract Initializes an IOBasicOutputQueue object. 123 @param target The object that will handle packets removed from the 124 queue, which is usually a subclass of IONetworkController. 125 @param action The function that will handle packets removed from the 126 queue. 127 @param capacity The initial capacity of the output queue. 128 @result Returns true if initialized successfully, false otherwise. 129*/ 130 131 virtual bool init(OSObject * target, 132 IOOutputAction action, 133 UInt32 capacity = 0, 134 UInt32 priorities = 1); 135 136/*! @function withTarget 137 @abstract Factory method that constructs and initializes an 138 IOBasicOutputQueue object. 139 @param target An IONetworkController object that will handle packets 140 removed from the queue. 141 @param capacity The initial capacity of the output queue. 142 @result Returns an IOBasicOutputQueue object on success, or 0 otherwise. 143*/ 144 145 static IOBasicOutputQueue * withTarget(IONetworkController * target, 146 UInt32 capacity = 0); 147 148 /*! @function withTarget 149 @abstract Factory method that constructs and initializes an 150 IOBasicOutputQueue object. 151 @param target An IONetworkController object that will handle packets 152 removed from the queue. 153 @param capacity The initial capacity of the output queue. 154 @param priorities The number of traffic priorities supported 155 @result Returns an IOBasicOutputQueue object on success, or 0 otherwise. 156 */ 157 158 static IOBasicOutputQueue * withTarget(IONetworkController * target, 159 UInt32 capacity, 160 UInt32 priorities); 161 162/*! @function withTarget 163 @abstract Factory method that constructs and initializes an 164 IOBasicOutputQueue object. 165 @param target The object that will handle packets removed from the 166 queue. 167 @param action The function that will handle packets removed from the 168 queue. 169 @param capacity The initial capacity of the output queue. 170 @result Returns an IOBasicOutputQueue object on success, or 0 otherwise. 171*/ 172 173 static IOBasicOutputQueue * withTarget(OSObject * target, 174 IOOutputAction action, 175 UInt32 capacity = 0); 176 177 /*! @function withTarget 178 @abstract Factory method that constructs and initializes an 179 IOBasicOutputQueue object. 180 @param target The object that will handle packets removed from the 181 queue. 182 @param action The function that will handle packets removed from the 183 queue. 184 @param capacity The initial capacity of the output queue. 185 @param priorities The number of traffic priorities supported 186 @result Returns an IOBasicOutputQueue object on success, or 0 otherwise. 187 */ 188 189 static IOBasicOutputQueue * withTarget(OSObject * target, 190 IOOutputAction action, 191 UInt32 capacity, 192 UInt32 priorities); 193 194/*! @function enqueue 195 @abstract Adds a packet, or a chain of packets, 196 to the queue. 197 @discussion This method is called by a client to add a packet, or a chain of packets, 198 to the queue. A packet is described by an mbuf chain, while a chain 199 of packets is constructed by linking multiple mbuf chains via the 200 m_nextpkt field. This method can be called by multiple client 201 threads. 202 @param m A single packet, or a chain of packets. 203 @param param A parameter provided by the caller. 204 @result Always returns 0. 205*/ 206 207 virtual UInt32 enqueue(mbuf_t m, void * param); 208 209/*! @function start 210 @abstract Starts up the packet flow between the queue and its target. 211 @discussion Called by the target to start the queue. This will allow 212 packets to be removed from the queue, and then delivered to the target. 213 @result Returns true if the queue was started successfully, false otherwise. */ 214 215 virtual bool start(); 216 217/*! @function stop 218 @abstract Stops the packet flow between the queue and its target. 219 @discussion This method stops the queue and prevents it from sending packets to its 220 target. This call is synchronous and it may block. After this method 221 returns, the queue will no longer call the registered target/action, 222 even as new packets are added to the queue. The queue will continue to 223 absorb new packets until the size of the queue reaches its capacity. 224 The registered action must never call stop(), or a deadlock will occur. 225 @result Returns the previous running state of the queue, 226 true if the queue was running, false if the queue was already stopped. 227*/ 228 229 virtual bool stop(); 230 231/*! @enum ServiceAsync 232 @abstract The option bits recognized by service(). 233 @constant kServiceAsync Set this option to service the queue in 234 an asynchronous manner. The service() call will not block, but a 235 scheduling latency will be introduced before the queue is serviced. 236*/ 237 238 enum { 239 kServiceAsync = 0x1 240 }; 241 242/*! @function service 243 @abstract Services a queue that was stalled by the target. 244 @discussion A target that stalls the queue must call service() when 245 it becomes ready to accept more packets. Calling this method when the 246 queue is not stalled is harmless. 247 @result Returns true if the queue was stalled and there were packets sitting in 248 the queue awaiting delivery, false otherwise. 249*/ 250 251 virtual bool service(IOOptionBits options = 0); 252 253/*! @function flush 254 @abstract Drops and frees all packets currently held by the queue. 255 @discussion To ensure that all packets are removed from the queue, 256 stop() should be called prior to flush(), to make sure there are 257 no packets in-flight and being delivered to the target. 258 @result Returns the number of packets that were dropped and freed. 259*/ 260 261 virtual UInt32 flush(); 262 263/*! @function setCapacity 264 @abstract Changes the number of packets that the queue can hold 265 before it begins to drop excess packets. 266 @param capacity The new desired capacity. 267 @result Returns true if the new capacity was accepted, false otherwise. 268*/ 269 270 virtual bool setCapacity(UInt32 capacity); 271 272/*! @function getCapacity 273 @abstract Gets the number of packets that the queue can hold. 274 @discussion The queue will begin to drop incoming packets when the 275 size of the queue reaches its capacity. 276 @result Returns the current queue capacity. 277*/ 278 279 virtual UInt32 getCapacity() const; 280 281/*! @function getSize 282 @abstract Gets the number of packets currently held in the queue. 283 @result Returns the size of the queue. 284*/ 285 286 virtual UInt32 getSize() const; 287 288/*! @function getDropCount 289 @abstract Gets the number of packets dropped by the queue. 290 @result Returns the number of packets dropped due to over-capacity, or by 291 external calls to the flush() method. 292*/ 293 294 virtual UInt32 getDropCount(); 295 296/*! @function getOutputCount 297 @abstract Gets the number of packets accepted by the target. 298 @result Returns the number of times that kIOOutputStatusAccepted is returned by 299 the target. 300*/ 301 302 virtual UInt32 getOutputCount(); 303 304/*! @function getRetryCount 305 @abstract Gets the number of instances when the target has refused to 306 accept the packet provided. 307 @result Returns the number of times that kIOOutputStatusRetry is returned by the 308 target. 309*/ 310 311 virtual UInt32 getRetryCount(); 312 313/*! @function getStallCount 314 @abstract Gets the number of instances when the target has stalled the 315 queue. 316 @result Returns the number of times that kIOOutputCommandStall is returned by the 317 target. 318*/ 319 320 virtual UInt32 getStallCount(); 321 322/*! @enum GetStateBits 323 @abstract The bits in the value returned by getState(). 324 @constant kStateRunning Set when the queue is running. Calling start() 325 and stop() will set or clear this bit. 326 @constant kStateStalled Set when the queue is stalled by the target. 327 @constant kStateActive Set when a consumer thread is actively removing 328 packets from the queue and passing them to the target. 329*/ 330 331 enum { 332 kStateRunning = 0x1, 333 kStateOutputStalled = 0x2, 334 kStateOutputActive = 0x4, 335 kStateOutputServiceMask = 0xff00 336 }; 337 338/*! @function getState 339 @abstract Gets the state of the queue object. 340 @result Returns the current state of the queue object. 341*/ 342 343 virtual UInt32 getState() const; 344 345/*! @function getStatisticsData 346 @abstract Returns an IONetworkData object containing statistics counters 347 updated by the queue. 348 @result Returns an IONetworkData object. 349*/ 350 351 virtual IONetworkData * getStatisticsData() const; 352}; 353 354#endif /* !_IOBASICOUTPUTQUEUE_H */ 355