QOS and Winsock

In the previous section, we discussed the various components required for the success of an end-to-end QOS network. Now we'll turn our attention to Winsock 2, which is the API you use to programmatically access QOS from an application. First we'll take a look at the top-level QOS structures needed by the majority of Winsock calls. Next we'll cover the Winsock functions capable of invoking QOS on a socket, as well as how to terminate QOS once it has been enabled on a socket. The last thing we'll do is cover the provider-specific objects that can be used to affect the behavior of—or return information from—the QOS service provider.

It might seem a bit out of order to jump from a discussion of the major QOS structures to QOS functions and then back to provider-specific structures. However, we want to give a thorough, high-level overview of how the major structures interact with the Winsock API calls before delving into the gory details of the provider-specific options.

QOS Structures

The central structure in QOS programming is the QOS structure. This structure consists of

  • A FLOWSPEC structure used to describe the QOS levels that your application will use for sending data
  • A FLOWSPEC structure used to describe the QOS levels that your application will use to receive data
  • A service provider-specific buffer to allow the specification of provider-specific QOS characteristics (We will discuss these characteristics in the provider-specific section.)

QOS

The QOS structure specifies the QOS parameters for both sending and receiving traffic. It is defined as

 typedef struct _QualityOfService { FLOWSPEC SendingFlowspec; FLOWSPEC ReceivingFlowspec; WSABUF ProviderSpecific; } QOS, FAR * LPQOS; 

The FLOWSPEC structures define the traffic characteristics and requirements for each traffic direction, while the ProviderSpecific field is used to return information and to change the behavior of QOS. These provider-specific options are covered in detail a little later in this chapter.

FLOWSPEC

FLOWSPEC is the basic structure that describes a single flow. Remember that a flow describes data traveling in a single direction. The structure is defined as

 typedef struct _flowspec { ULONG TokenRate; ULONG TokenBucketSize; ULONG PeakBandwidth; ULONG Latency; ULONG DelayVariation; SERVICETYPE ServiceType; ULONG MaxSduSize; ULONG MinimumPolicedSize; } FLOWSPEC, *PFLOWSPEC, FAR *LPFLOWSPEC; 

Let's take a look at the meaning of each of the FLOWSPEC structure fields.

TokenRate

The TokenRate field specifies the rate of transmission for data that is given in bytes per second. An application can transmit data at this rate, but if for some reason it transmits data at a lower rate, the application can accrue extra tokens so that more data can be transmitted later. However, the number of tokens that an application can accrue is bound by PeakBandwidth. This accumulation of token credits itself is limited by the TokenBucketSize field. By limiting the total number of tokens, we avoid a situation of inactive flows that have accrued many tokens, which could lead to flooding the available bandwidth. Because flows can accrue transmission credits over time (at their TokenRate value) only up to the maximum of their TokenBucketSize, and because they are limited in "burst transmissions" to their PeakBandwidth, traffic control and network-device resource integrity are maintained. Traffic control is maintained because flows cannot send too much data at once, and network-device resource integrity is maintained because such devices are spared high-traffic bursts.

Because of these limitations, an application can transmit only when sufficient credits have accrued. If the required number of credits are not available, the application must either wait until sufficient credits have accrued to send the data or discard the data altogether. The Traffic Control module determines what happens to data queued too long without being sent. Therefore, applications should take care to base their TokenRate requests on reasonable amounts.

If an application does not require scheduling of transmission rates, this field can be set to QOS_NOT_SPECIFIED (-1).

TokenBucketSize

As we discussed earlier, the TokenBucketSize field limits the number of credits that can accrue for a given flow. For example, video applications would set this field to the frame size being transmitted since it is desirable to have single video frames being transmitted at a time. Applications requiring a constant data rate should set this field to allow for some variation. Like the TokenRate field, TokenBucketSize is expressed in bytes per second.

PeakBandwidth

PeakBandwidth specifies the maximum amount of data transmitted in a given period of time. In effect, this value specifies the maximum amount of burst data. This is an important value because it prevents applications that have accrued a significant number of transmission tokens from flooding the network all at once. PeakBandwidth is expressed in bytes per second.

Latency

The Latency field specifies the maximum acceptable delay between the transmission of a bit and its receipt by the intended recipient or recipients. How this value is actually interpreted depends on the level of service requested in the ServiceType field. Latency is expressed in microseconds.

DelayVariation

DelayVariation specifies the difference between the minimum and maximum delay that a packet can experience. Typically an application uses this value to determine the amount of buffer space required to receive the data and still maintain the original data transmission pattern. DelayVariation is expressed in microseconds.

ServiceType

The ServiceType field specifies the level of service required by the data flow. The following service types can be specified:

  • SERVICETYPE_NOTRAFFIC indicates that no data is being transmitted in this direction.
  • SERVICETYPE_BESTEFFORT indicates that the parameters specified in FLOWSPEC are guidelines and that the system will make a reasonable effort to maintain that service level; however, there are no guarantees of packet delivery.
  • SERVICETYPE_CONTROLLEDLOAD indicates that data transmission will closely approximate transmission quality provided by best-effort service on a network with nonloaded traffic conditions. This really breaks down into two conditions. First, packet loss will approximate the normal error rate of the transmission medium; and second, transmission delay will not greatly exceed the minimum delay experienced by delivered packets.
  • SERVICETYPE_GUARANTEED guarantees data transmission at the rate specified by the TokenRate field over the lifetime of the connection. However, if the actual data transmission rate exceeds TokenRate, data might be delayed or discarded (depending on how Traffic Control is configured). Additionally, if TokenRate is not exceeded, Latency is also guaranteed.

In addition to these four service types, several other flags provide information that can be returned to an application. These informational flags can be ORed with any valid ServiceType flag. Table 12-1 lists these information flags.

Table 12-1. Service type modifier flags

Value Meaning
SERVICETYPE_NETWORK_UNAVAILABLE Indicates a loss of service in either the sending or the receiving direction.
SERVICETYPE_GENERAL_INFORMATION Indicates that all service types are supported for a flow.
SERVICETYPE_NOCHANGE Indicates that there is no change in the requested QOS service level. This flag can be returned from a Winsock call or an application can specify this flag when renegotiating QOS to indicate no change in the QOS levels for the given direction.
SERVICE_IMMEDIATE_TRAFFIC_CONTROL An application can use this flag to indicate to the system to immediately invoke Traffic Control instead of sending best effort until a RESV message arrives.
SERVICE_NO_TRAFFIC_CONTROL This flag can be ORed with other ServiceType flags to disable traffic control altogether.
SERVICE_NO_QOS_SIGNALING This flag can be used with the immediate traffic control flag above to prevent any RSVP signaling messages from being sent. Local traffic control will be invoked, but no RSVP Path messages will be sent. This flag can also be used in conjunction with a receiving FLOWSPEC structure to suppress the automatic generation of a RESV message. The application receives notification that a PATH message has arrived and then needs to alter the QOS by issuing WSAIoctl(SIO_SET_QOS) to unset this flag and thereby cause RESV messages to go out.

MaxSduSize

The MaxSduSize field indicates the maximum packet size for data transmitted in the given flow. MaxSduSize is expressed in bytes.

MinimumPolicedSize

The MinimumPolicedSize field indicates the minimum packet size that can be transmitted in the given flow. MinimumPolicedSize is expressed in bytes.

QOS-Invoking Functions

Let's say you want your application to make a request on the network for certain bandwidth requirements. Four functions initiate the process. Once an RSVP session has begun, an application can register for FD_QOS events. QOS status information and error codes are conveyed to applications as FD_QOS events. Applications can register to receive these events in the usual way: by including the FD_QOS flag in the event field of either the WSAAsyncSelect or the WSAEventSelect function.

The FD_QOS notification is especially relevant if a connection is established with FLOWSPEC structures that specify default values (QOS_NOT_SPECIFIED). Once the application has made the request for QOS, the underlying provider will periodically update the FLOWSPEC structure to indicate current network conditions and will notify the application by posting an FD_QOS event. With this information, applications can request or modify QOS levels to reflect the amount of available bandwidth. Keep in mind that the updated information is an indication of only the locally available bandwidth and does not necessarily indicate the end-to-end bandwidth.

Once a flow is established, available network bandwidth might change or a single party taking part in an established flow might decide to change the requested QOS service level. A renegotiation of allocated resources causes an FD_QOS event to be generated to indicate the change to the application. At this point, the application should call SIO_GET_QOS to obtain the new resource levels. We'll revisit QOS event signaling and status information in the section on programming QOS later in this chapter.

WSAConnect

A client uses the WSAConnect function to initiate a unicast QOS connection to a server. The requested QOS values are passed as the lpSQOS parameters. Currently group QOS is not supported or implemented; a null value should be passed for lpGQOS.

 int WSAConnect ( SOCKET s, const struct sockaddr FAR *name, int namelen, LPWSABUF lpCallerData, LPWSABUF lpCalleeData, LPQOS lpSQOS, LPQOS lpGQOS ); 

The WSAConnect call can be used with connection-oriented or connectionless sockets. With a connection-oriented socket, this function establishes the connection and also generates the appropriate PATH and/or RESV messages. For connectionless sockets, you must associate an endpoint's address with the socket so that the service provider knows where to send PATH and RESV messages. The caveat with using WSAConnect on a connectionless socket is that only data sent to that destination address will be shaped by the system according to the QOS levels associated with that socket. In other words, if WSAConnect is used to associate an endpoint on a connectionless socket, data can be transferred only between those two endpoints for the lifetime of the socket. If you need to send data with QOS guarantees to multiple endpoints, use WSAIoctl and SIO_SET_QOS to specify each new endpoint.

WSAAccept

The WSAAccept function accepts a client connection that can be QOS-enabled. The prototype for the function is as follows:

 SOCKET WSAAccept( SOCKET s, struct sockaddr FAR *addr, LPINT addrlen, LPCONDITIONPROC lpfnCondition, DWORD dwCallbackData ); 

If you want to supply a conditional function, you must prototype it as

 int CALLBACK ConditionalFunc( LPWSABUF lpCallerId, LPWSABUF lpCallerData, LPQOS lpSQOS, LPQOS lpGQOS, LPWSABUF lpCalleeId, LPWSABUF lpCalleeData, GROUP FAR *g, DWORD dwCallbackData ); 

The unfortunate drawback is that the QOS service provider does not guarantee to return the actual QOS values that the client is requesting as the lpSQOS parameter, which means that to enable QOS on the client socket, WSAIoctl with SIO_SET_QOS must be called before or after WSAAccept. If QOS is set on the listening socket, those values will be copied over to the client socket by default.

In actuality, the condition function is not useful at all. With TCP, you cannot reject a client connection per se because by the time the conditional function has been called, the connection has already been established on the TCP level. Additionally, the QOS service provider will not pass valid QOS parameters into the conditional function even if a PATH message has already arrived. Basically, don't use the WSAAccept condition function.

NOTE
There is one issue to be aware of when using WSAAccept on Windows 98. If you do use a conditional function with WSAAccept and the lpSQOS parameter is not null, you must set QOS (using SIO_SET_QOS), or WSAAccept will fail.

WSAJoinLeaf

WSAJoinLeaf is used for multipoint communications. Chapter 11 discusses multicasting in great detail. The function is defined as

 SOCKET WSAJoinLeaf( SOCKET s, const struct sockaddr FAR *name, int namelen, LPWSABUF lpCallerData, LPWSABUF lpCalleeData, LPQOS lpSQOS, LPQOS lpGQOS, DWORD dwFlags ); 

For an application to join a multicast session, it must create a socket with the appropriate flags (WSA_FLAG_MULTIPOINT_C_ROOT, WSA_FLAG_MULTIPOINT_C_LEAF, WSA_FLAG_MULTIPOINT_D_ROOT, and WSA_FLAG_MULTIPOINT_D_LEAF). When the application sets up multipoint communications, it specifies QOS parameters in the lpSQOS parameter.

When you use WSAJoinLeaf to join IP multicast groups, the operation of joining a multicast group is separate from the QOS RSVP session setup. In fact, joining a multicast group is likely to succeed. The function returns without the reservation request completing. At some later time, you will receive an FD_QOS event that will notify you of either a success or a failure in allocating the requested resources.

Keep in mind the time-to-live (TTL) set on multicast data. If you plan on setting the TTL with either SIO_MULTICAST_SCOPE or IP_MULTICAST_TTL, the TTL must be set prior to calling WSAJoinLeaf or calling the SIO_SET_QOS ioctl command to set QOS on the socket. If the scope is set after the QOS is already set, the TTL will not take effect until QOS is renegotiated through SIO_SET_QOS. The TTL value set will also be carried by the RSVP request.

Setting the TTL before setting QOS on a socket is important because the multicast TTL set on the socket also affects the TTL of the RSVP messages, directly affecting how many networks your resource reservation request is propagated to. For example, if you want to set up several endpoints in an IP multicast group that spans 3 networks, you ideally would set the TTL to 3 so that the network traffic you generate is not propagated to networks beyond those interested in the data. If the TTL isn't set before WSAJoinLeaf is called, RSVP messages are sent out with a default TTL of 63, which results in the host attempting to reserve resources on far too many networks.

WSAIoctl

The WSAIoctl function with the ioctl option SIO_SET_QOS can be used either to request QOS for the first time on either a connected or an unconnected socket or to renegotiate QOS requirements after an initial QOS request. The one advantage to using WSAIoctl is that if the QOS request fails, more detailed error information is returned via the provider-specific information. Chapter 9 covers the WSAIoctl function and how it is called, along with SIO_SET_QOS and SIO_GET_QOS.

The SIO_SET_QOS option is used to set or modify QOS parameters on a socket. One feature of using WSAIoctl with SIO_SET_QOS is the ability to specify provider-specific objects to further refine the behavior of QOS. The next section is dedicated to covering all the provider-specific objects. In particular, an application using connectionless sockets that does not want to use WSAConnect can call WSAIoctl with SIO_SET_QOS and specify the destination address object in the provider-specific buffer to associate an endpoint so that an RSVP session can be established. When setting QOS parameters, pass the QOS structure as lpvInBuffer, with cbInBuffer indicating the amount of bytes passed in.

The SIO_GET_QOS option is used upon receipt of an FD_QOS event. When an application receives this event notification, a call to WSAIoctl with SIO_GET_QOS should be made to investigate the reason for the event. As we mentioned earlier, the FD_QOS event can be generated because of a change in the available bandwidth on the network or by renegotiation by the peer. To obtain the QOS values for a socket, pass a sufficiently large buffer as lpvOutBuffer, with cbOutBuffer indicating the size. The input parameters can be NULL and 0. The one tricky thing when calling SIO_GET_QOS is passing a buffer large enough to hold the QOS structure, including the provider-specific objects. The ProviderSpecific field—a WASBUF structure—is within the QOS structure. If the len field is set to QUERY_PS_SIZE and the buf field is null, len will be updated with the necessary size upon return from WSAIoctl. Additionally, if the call fails because the buffer is too small, the len field will be updated with the correct size. Querying for the buffer size is supported only on Windows 2000. For Windows 98, you must always supply a large enough buffer—simply pick a large buffer size and stick with it.

Another ioctl command can be used with WSAIoctl: SIO_CHK_QOS. This command can be used to query for the six values described in Table 12-2. When you call this command, the lpvInBuffer parameter points to a DWORD that is set to one of the three flags. The lpvOutBuffer parameter should also point to a DWORD, and upon return, the value requested is returned. The most commonly used flag is ALLOWED_TO_SEND_DATA. This flag is used by senders who have initiated a PATH message but have not received any RESV messages indicating successful allocation of the QOS level. When senders use the SIO_CHK_QOS ioctl command with the ALLOWED_TO_SEND_DATA flag, the network is queried to see whether the best-effort traffic currently available is sufficient for sending the kind of data described in the QOS structure passed to a QOS-invoking function. For more details, take a look at the entry for this ioctl command in Chapter 9.

Table 12-2. SIO_CHK_QOS flags

SIO_CHK_QOS Flag Description Return Value
ALLOW_TO_SEND_DATA Indicates whether sending data can begin immediately or whether the application should wait for a RESV message BOOL
ABLE_TO_RECV_RSVP Indicates to senders whether its interface is RSVP-enabled BOOL
LINE_RATE Returns the bandwidth capacity of the interface DWORD
LOCAL_TRAFFIC_CONTROL Returns whether Traffic Control is installed and available for use BOOL
LOCAL_QOSABILITY Returns whether QOS is available BOOL
END_TO_END_QOSABILITY Determines whether end-to-end QOS is available on the network BOOL

The options listed in Table 12-2 that return BOOL values actually return 1 or 0 to indicate a yes or a no answer respectively. The last four options in the table can return the constant INFO_NOT_AVAILABLE if the system cannot currently obtain the answer.



Network Programming for Microsoft Windows
Linux Server Hacks, Volume Two: Tips & Tools for Connecting, Monitoring, and Troubleshooting
ISBN: 735615799
EAN: 2147483647
Year: 1998
Pages: 159

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net