diff options
author | William R. Otte <wotte@dre.vanderbilt.edu> | 2006-07-24 15:50:30 +0000 |
---|---|---|
committer | William R. Otte <wotte@dre.vanderbilt.edu> | 2006-07-24 15:50:30 +0000 |
commit | c44379cc7d9c7aa113989237ab0f56db12aa5219 (patch) | |
tree | 66a84b20d47f2269d8bdc6e0323f338763424d3a /ACE/ace/QoS | |
parent | 3aff90f4a822fcf5d902bbfbcc9fa931d6191a8c (diff) | |
download | ATCD-c44379cc7d9c7aa113989237ab0f56db12aa5219.tar.gz |
Repo restructuring
Diffstat (limited to 'ACE/ace/QoS')
-rw-r--r-- | ACE/ace/QoS/ACE_QoS.pc.in | 11 | ||||
-rw-r--r-- | ACE/ace/QoS/ACE_QoS_Export.h | 46 | ||||
-rw-r--r-- | ACE/ace/QoS/Makefile.am | 74 | ||||
-rw-r--r-- | ACE/ace/QoS/QoS_Decorator.cpp | 165 | ||||
-rw-r--r-- | ACE/ace/QoS/QoS_Decorator.h | 179 | ||||
-rw-r--r-- | ACE/ace/QoS/QoS_Manager.cpp | 41 | ||||
-rw-r--r-- | ACE/ace/QoS/QoS_Manager.h | 74 | ||||
-rw-r--r-- | ACE/ace/QoS/QoS_Session.h | 183 | ||||
-rw-r--r-- | ACE/ace/QoS/QoS_Session_Factory.cpp | 105 | ||||
-rw-r--r-- | ACE/ace/QoS/QoS_Session_Factory.h | 96 | ||||
-rw-r--r-- | ACE/ace/QoS/QoS_Session_Impl.cpp | 724 | ||||
-rw-r--r-- | ACE/ace/QoS/QoS_Session_Impl.h | 265 | ||||
-rw-r--r-- | ACE/ace/QoS/QoS_Session_Impl.i | 229 | ||||
-rw-r--r-- | ACE/ace/QoS/README | 55 | ||||
-rw-r--r-- | ACE/ace/QoS/SOCK_Dgram_Mcast_QoS.cpp | 258 | ||||
-rw-r--r-- | ACE/ace/QoS/SOCK_Dgram_Mcast_QoS.h | 142 | ||||
-rw-r--r-- | ACE/ace/QoS/SOCK_Dgram_Mcast_QoS.i | 57 | ||||
-rw-r--r-- | ACE/ace/QoS/qos.mpc | 16 |
18 files changed, 2720 insertions, 0 deletions
diff --git a/ACE/ace/QoS/ACE_QoS.pc.in b/ACE/ace/QoS/ACE_QoS.pc.in new file mode 100644 index 00000000000..ba6fda765b9 --- /dev/null +++ b/ACE/ace/QoS/ACE_QoS.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: ACE_QOS +Description: ACE Quality of Service Library +Requires: ACE +Version: @VERSION@ +Libs: -L${libdir} -lACE_QoS +Cflags: -I${includedir} diff --git a/ACE/ace/QoS/ACE_QoS_Export.h b/ACE/ace/QoS/ACE_QoS_Export.h new file mode 100644 index 00000000000..45790bbd24c --- /dev/null +++ b/ACE/ace/QoS/ACE_QoS_Export.h @@ -0,0 +1,46 @@ +// -*- C++ -*- +// $Id$ +// Definition for Win32 Export directives. +// This file is generated automatically by +// generate_export_file.pl +// ------------------------------ +#if !defined (ACE_QOS_EXPORT_H) +#define ACE_QOS_EXPORT_H + +#include "ace/config-all.h" + +#if defined (ACE_AS_STATIC_LIBS) +# if !defined (ACE_QoS_HAS_DLL) +# define ACE_QoS_HAS_DLL 0 +# endif /* ! ACE_QoS_HAS_DLL */ +#else +# if !defined (ACE_QoS_HAS_DLL) +# define ACE_QoS_HAS_DLL 1 +# endif /* ! ACE_QoS_HAS_DLL */ +#endif /* ACE_AS_STATIC_LIB */ + +#if defined (ACE_QoS_HAS_DLL) +# if (ACE_QoS_HAS_DLL == 1) +# if defined (ACE_QoS_BUILD_DLL) +# define ACE_QoS_Export ACE_Proper_Export_Flag +# define ACE_QoS_SINGLETON_DECLARATION(T) ACE_EXPORT_SINGLETON_DECLARATION (T) +# define ACE_QoS_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_EXPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +# else +# define ACE_QoS_Export ACE_Proper_Import_Flag +# define ACE_QoS_SINGLETON_DECLARATION(T) ACE_IMPORT_SINGLETON_DECLARATION (T) +# define ACE_QoS_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_IMPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +# endif /* ACE_QoS_BUILD_DLL */ +# else +# define ACE_QoS_Export +# define ACE_QoS_SINGLETON_DECLARATION(T) +# define ACE_QoS_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +# endif /* ! ACE_QoS_HAS_DLL == 1 */ +#else +# define ACE_QoS_Export +# define ACE_QoS_SINGLETON_DECLARATION(T) +# define ACE_QoS_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +#endif /* ACE_QoS_HAS_DLL */ + +#endif /* ACE_QOS_EXPORT_H */ + +// End of auto generated file. diff --git a/ACE/ace/QoS/Makefile.am b/ACE/ace/QoS/Makefile.am new file mode 100644 index 00000000000..70065de4481 --- /dev/null +++ b/ACE/ace/QoS/Makefile.am @@ -0,0 +1,74 @@ +## Process this file with automake to create Makefile.in +## +## $Id$ +## +## This file was generated by MPC. Any changes made directly to +## this file will be lost the next time it is generated. +## +## MPC Command: +## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu + +includedir = @includedir@/ace/QoS +pkgconfigdir = @libdir@/pkgconfig + +ACE_BUILDDIR = $(top_builddir) +ACE_ROOT = $(top_srcdir) + + +## Makefile.QoS.am + +if BUILD_QOS + +lib_LTLIBRARIES = libACE_QoS.la + +libACE_QoS_la_CPPFLAGS = \ + -I$(ACE_ROOT) \ + -I$(ACE_BUILDDIR) \ + -DACE_QoS_BUILD_DLL + +libACE_QoS_la_SOURCES = \ + QoS_Decorator.cpp \ + QoS_Manager.cpp \ + QoS_Session_Factory.cpp \ + QoS_Session_Impl.cpp \ + SOCK_Dgram_Mcast_QoS.cpp + +libACE_QoS_la_LDFLAGS = \ + -release @ACE_VERSION_NAME@ + +libACE_QoS_la_LIBADD = \ + $(ACE_BUILDDIR)/ace/libACE.la + +nobase_include_HEADERS = \ + ACE_QoS_Export.h \ + QoS_Decorator.h \ + QoS_Manager.h \ + QoS_Session.h \ + QoS_Session_Factory.h \ + QoS_Session_Impl.h \ + QoS_Session_Impl.i \ + SOCK_Dgram_Mcast_QoS.h \ + SOCK_Dgram_Mcast_QoS.i + +pkgconfig_DATA = \ + ACE_QoS.pc + +CLEANFILES = \ + ACE_QoS.pc + +ACE_QoS.pc: ${top_builddir}/config.status ${srcdir}/ACE_QoS.pc.in + ${top_builddir}/config.status --file "$@":${srcdir}/ACE_QoS.pc.in + +endif BUILD_QOS + +EXTRA_DIST = \ + ACE_QoS.pc.in + + +## Clean up template repositories, etc. +clean-local: + -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.* + -rm -f gcctemp.c gcctemp so_locations *.ics + -rm -rf cxx_repository ptrepository ti_files + -rm -rf templateregistry ir.out + -rm -rf ptrepository SunWS_cache Templates.DB diff --git a/ACE/ace/QoS/QoS_Decorator.cpp b/ACE/ace/QoS/QoS_Decorator.cpp new file mode 100644 index 00000000000..90cc748e856 --- /dev/null +++ b/ACE/ace/QoS/QoS_Decorator.cpp @@ -0,0 +1,165 @@ +// QoS_Decorator.cpp +// $Id$ + +#include "QoS_Decorator.h" + +ACE_RCSID(ace, QoS_Decorator, "$Id$") + +ACE_BEGIN_VERSIONED_NAMESPACE_DECL + +ACE_ALLOC_HOOK_DEFINE(ACE_QOS_DECORATOR) + +// Constructor. +ACE_QoS_Decorator_Base::ACE_QoS_Decorator_Base (void) +{} + +// Constructor. +ACE_QoS_Decorator_Base::ACE_QoS_Decorator_Base (ACE_Event_Handler + *event_handler) + : event_handler_ (event_handler) +{ +} + +// Destructor. +ACE_QoS_Decorator_Base::~ACE_QoS_Decorator_Base (void) +{ +} + +// Forward the call to ACE_Event_Handler component. +ACE_HANDLE +ACE_QoS_Decorator_Base::get_handle (void) const +{ + return this->event_handler_->get_handle (); +} + +// Forward the call to ACE_Event_Handler component. +int +ACE_QoS_Decorator_Base::handle_input (ACE_HANDLE fd) +{ + return this->event_handler_->handle_input (fd); +} + +// Forward the call to ACE_Event_Handler component. +int +ACE_QoS_Decorator_Base::handle_qos (ACE_HANDLE fd) +{ + return this->event_handler_->handle_qos (fd); +} + +// Constructor. +ACE_QoS_Decorator::ACE_QoS_Decorator (void) +{} + +// Constructor. +ACE_QoS_Decorator::ACE_QoS_Decorator (ACE_Event_Handler *event_handler, + ACE_QoS_Session *qos_session, + ACE_Reactor *reactor) + : qos_session_ (qos_session), + reactor_ (reactor) +{ + ACE_NEW (this->decorator_base_, + ACE_QoS_Decorator_Base (event_handler)); + + ACE_NEW (this->qos_event_handler_, + ACE_QoS_Event_Handler (this->decorator_base_)); +} + +// Destructor. +ACE_QoS_Decorator::~ACE_QoS_Decorator (void) +{ + delete this->decorator_base_; + delete this->qos_event_handler_; +} + +// Implements the undecorated functionality. This is sufficient for +// GQoS. RAPI needs additional QoS decoration. This is done by the +// ACE_QoS_Event_Handler class. +ACE_HANDLE +ACE_QoS_Decorator::get_handle (void) const +{ + return this->decorator_base_->get_handle (); +} + +// Implements the undecorated functionality. This is sufficient for +// GQoS. RAPI needs additional QoS decoration. This is done by the +// ACE_QoS_Event_Handler class. +int +ACE_QoS_Decorator::handle_input (ACE_HANDLE fd) +{ + return this->decorator_base_->handle_input (fd); +} + +// Implements the undecorated functionality. This is sufficient for +// GQoS. RAPI needs additional QoS decoration. This is done by the +// ACE_QoS_Event_Handler class. +int +ACE_QoS_Decorator::handle_qos (ACE_HANDLE fd) +{ + return this->decorator_base_->handle_qos (fd); +} + +// This method registers the RAPI QoS event handler with the reactor +// if the application is using RAPI. Note that it is a no-op for GQoS +// because an extra socket for handling QoS events is not required. +int +ACE_QoS_Decorator::init (void) +{ +#if defined (ACE_HAS_RAPI) + + // Pass the QoS session to QoS Event Handler. + this->qos_event_handler_->qos_session (this->qos_session_); + + // Register the QoS Event Handler with the Reactor. + return this->reactor_->register_handler (this->qos_event_handler_, + ACE_Event_Handler::READ_MASK); +#endif + return 0; + +} + +// Constructor. +ACE_QoS_Event_Handler::ACE_QoS_Event_Handler (void) +{ +} + +// Constructor. +ACE_QoS_Event_Handler::ACE_QoS_Event_Handler (ACE_QoS_Decorator_Base + *decorator_base) + : decorator_base_ (decorator_base) +{ +} + +// Destructor. +ACE_QoS_Event_Handler::~ACE_QoS_Event_Handler (void) +{ +} + +// Set the QoS session. +void +ACE_QoS_Event_Handler::qos_session (ACE_QoS_Session *qos_session) +{ + this->qos_session_ = qos_session; +} + +// Returns the RAPI file descriptor for listening to RAPI evnets. +ACE_HANDLE +ACE_QoS_Event_Handler::get_handle (void) const +{ + return this->qos_session_->rsvp_events_handle (); +} + +// Note, here the handle_input () calls the handle_qos () of the +// Decorator Base which then calls handle_qos () of the +// ACE_Event_Handler component within it. This helps to translate the +// normal read events into qos events in case of RAPI so the +// application using the API is oblivious to the fact that in RAPI, +// QoS events are received on a different socket. This helps to +// maintain a uniform design for the application irrespective of +// whether it is using RAPI or GQoS. +int +ACE_QoS_Event_Handler::handle_input (ACE_HANDLE fd) +{ + return this->decorator_base_->handle_qos (fd); +} + +ACE_END_VERSIONED_NAMESPACE_DECL diff --git a/ACE/ace/QoS/QoS_Decorator.h b/ACE/ace/QoS/QoS_Decorator.h new file mode 100644 index 00000000000..512912e7c3b --- /dev/null +++ b/ACE/ace/QoS/QoS_Decorator.h @@ -0,0 +1,179 @@ +// -*- C++ -*- + +//============================================================================= +/** + * @file QoS_Decorator.h + * + * $Id$ + * + * @author Vishal Kachroo <vishal@cs.wustl.edu> + */ +//============================================================================= + + +#ifndef QOS_DECORATOR_H +#define QOS_DECORATOR_H +#include /**/ "ace/pre.h" + +#include "ace/Reactor.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "ace/INET_Addr.h" +#include "ace/Event_Handler.h" +#include "SOCK_Dgram_Mcast_QoS.h" +#include "ACE_QoS_Export.h" + +ACE_BEGIN_VERSIONED_NAMESPACE_DECL + +/** + * @class ACE_QoS_Decorator_Base + * + * @brief This class is the Decorator Pattern Base class for decorating + * ACE_Event_Handler. + * + * It simply forwards the requests for get_handle (), + * handle_input () and handle_qos () to its event_handler_ + * component. Concrete decorators for ACE_Event_Handler will use + * this class to access the basic event handler functionality and + * decorate that by their own implementation. + */ +class ACE_QoS_Export ACE_QoS_Decorator_Base : public ACE_Event_Handler +{ + +public: + + // Initialization and termination methods. + /// Constructor. + ACE_QoS_Decorator_Base (void); + + /// Constructor. + ACE_QoS_Decorator_Base (ACE_Event_Handler *event_handler); + + /// Destructor. + ~ACE_QoS_Decorator_Base (void); + + /// Forwards the request to its event_handler_ component. + virtual ACE_HANDLE get_handle (void) const; + + /// Forwards the request to its event_handler_ component. + virtual int handle_input (ACE_HANDLE fd); + + /// Forwards the request to its event_handler_ component. + virtual int handle_qos (ACE_HANDLE fd); + +private: + + /// The event handler that is decorated by this class. + ACE_Event_Handler *event_handler_; + +}; + +/** + * @class ACE_QoS_Event_Handler + * + * @brief This Handler is registered with the Reactor for QoS events. + * + * Concrete QoS decorator uses this class to receive QoS events + * for RAPI. It hides the application from knowing that it is + * receiving QoS events on a different socket so the application + * doesnt have to be designed differently for RAPI and GQoS. + */ +class ACE_QoS_Export ACE_QoS_Event_Handler : public ACE_Event_Handler +{ + + /// Destructor. + ~ACE_QoS_Event_Handler (void); + + /// Returns the RAPI file descriptor for receiving QoS events. + virtual ACE_HANDLE get_handle (void) const; + + /// Calls the base class handle_input (). + virtual int handle_input (ACE_HANDLE fd); + + /// Sets the QoS session. + void qos_session (ACE_QoS_Session *qos_session); + + friend class ACE_QoS_Decorator; + +private: + + /// Constructor is private because only ACE_QoS_Decorator should + /// create this object. + ACE_QoS_Event_Handler (void); + + /// The QoS Decorator passes in its base for this handler to use. + ACE_QoS_Event_Handler (ACE_QoS_Decorator_Base *decorator_base); + + /// Used to get to the RAPI file descriptor for QoS Events. + ACE_QoS_Session *qos_session_; + + /// Requests on the class are forwarded to this base class; + ACE_QoS_Decorator_Base *decorator_base_; + +}; + +/** + * @class ACE_QoS_Decorator + * + * @brief Concrete QoS Decorator. + * + * Decorates the ACE_Event_Handler to additionally handle QoS + * events uniformly for different QoS mechanisms like RAPI and + * GQoS. + */ +class ACE_QoS_Export ACE_QoS_Decorator : public ACE_QoS_Decorator_Base +{ + +public: + + // Initialization and termination methods. + /// Constructor. + ACE_QoS_Decorator (void); + + /// Constructor. + ACE_QoS_Decorator (ACE_Event_Handler *event_handler, + ACE_QoS_Session *qos_session, + ACE_Reactor *reactor = ACE_Reactor::instance ()); + + /// Destructor. + ~ACE_QoS_Decorator (void); + + /// Calls the base class get_handle (). + virtual ACE_HANDLE get_handle (void) const; + + /// Calls the base class handle_input (). + virtual int handle_input (ACE_HANDLE fd); + + /// Calls the base class handle_qos (). + virtual int handle_qos (ACE_HANDLE fd); + + /// This method registers the QoS Event Handler with the Reactor + /// to receive RAPI events. + int init (void); + +private: + + /// Requests on the class are forwarded to this base class; + ACE_QoS_Decorator_Base *decorator_base_; + + /// Handles the QoS events and in that sense decorates the usual + /// ACE_Event_Handler. + ACE_QoS_Event_Handler *qos_event_handler_; + + /// Passed to the ACE_QoS_Event_Handler for retrieving the RAPI + /// session specific information like rapi_fd. + ACE_QoS_Session *qos_session_; + + /// If the application wants to use an instance of Reactor other + /// than the Singleton one. + ACE_Reactor *reactor_; + +}; + +ACE_END_VERSIONED_NAMESPACE_DECL + +#include /**/ "ace/post.h" +#endif /* QOS_DECORATOR_H */ diff --git a/ACE/ace/QoS/QoS_Manager.cpp b/ACE/ace/QoS/QoS_Manager.cpp new file mode 100644 index 00000000000..27fa39ab560 --- /dev/null +++ b/ACE/ace/QoS/QoS_Manager.cpp @@ -0,0 +1,41 @@ +// QoS_Manager.cpp +// $Id$ + +#include "QoS_Manager.h" +#include "ace/Log_Msg.h" + +ACE_RCSID(ace, QoS_Manager, "$Id$") + +ACE_BEGIN_VERSIONED_NAMESPACE_DECL + +ACE_ALLOC_HOOK_DEFINE(ACE_QOS_MANAGER) + +ACE_QoS_Manager::ACE_QoS_Manager (void) +{} + +ACE_QoS_Manager::~ACE_QoS_Manager (void) +{} + +// Adds the given session to the list of session objects joined by +// this socket. + +int +ACE_QoS_Manager::join_qos_session (ACE_QoS_Session *qos_session) +{ + if (this->qos_session_set ().insert (qos_session) != 0) + ACE_ERROR_RETURN ((LM_ERROR, + ACE_LIB_TEXT ("Error in adding a new session to the ") + ACE_LIB_TEXT ("socket session set\n")), + -1); + return 0; +} + +// Returns the QoS session set for this socket. + +ACE_Unbounded_Set <ACE_QoS_Session *> +ACE_QoS_Manager::qos_session_set (void) +{ + return this->qos_session_set_; +} + +ACE_END_VERSIONED_NAMESPACE_DECL diff --git a/ACE/ace/QoS/QoS_Manager.h b/ACE/ace/QoS/QoS_Manager.h new file mode 100644 index 00000000000..8a0b52c9943 --- /dev/null +++ b/ACE/ace/QoS/QoS_Manager.h @@ -0,0 +1,74 @@ +// -*- C++ -*- + +//============================================================================= +/** + * @file QoS_Manager.h + * + * $Id$ + * + * @author Vishal Kachroo + */ +//============================================================================= + + +#ifndef ACE_QOS_MANAGER_H +#define ACE_QOS_MANAGER_H +#include /**/ "ace/pre.h" + +#include "ace/Addr.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +#pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "ace/IPC_SAP.h" +#include "ace/Containers_T.h" +#include "ACE_QoS_Export.h" +#include "QoS_Session.h" + + +ACE_BEGIN_VERSIONED_NAMESPACE_DECL + +/** + * @class ACE_QoS_Manager + * + * @brief This class manages the QoS sessions associated with ACE_SOCK. + * + * This class provides functions to manage the QoS + * associated with a socket. The idea is to keep the management of + * QoS for a socket separate from the socket itself. Currently, the + * manager is used to manage the QoS session set. It will handle more + * responsibilities in the future. + */ +class ACE_QoS_Export ACE_QoS_Manager +{ + +public: + /// Default constructor. + ACE_QoS_Manager (void); + + /// Default destructor. + ~ACE_QoS_Manager (void); + + /** + * Join the given QoS session. A socket can join multiple QoS + * sessions. This call adds the given QoS session to the list of + * QoS sessions that the socket has already joined. + */ + int join_qos_session (ACE_QoS_Session *qos_session); + + typedef ACE_Unbounded_Set <ACE_QoS_Session *> ACE_QOS_SESSION_SET; + + /// Get the QoS session set. + ACE_QOS_SESSION_SET qos_session_set (void); + +private: + + /// Set of QoS sessions that this socket has joined. + ACE_QOS_SESSION_SET qos_session_set_; +}; + +ACE_END_VERSIONED_NAMESPACE_DECL + +#include /**/ "ace/post.h" +#endif /* ACE_QOS_MANAGER_H */ diff --git a/ACE/ace/QoS/QoS_Session.h b/ACE/ace/QoS/QoS_Session.h new file mode 100644 index 00000000000..3e08bbc69ce --- /dev/null +++ b/ACE/ace/QoS/QoS_Session.h @@ -0,0 +1,183 @@ +/* -*- C++ -*- */ + +//============================================================================= +/** + * @file QoS_Session.h + * + * $Id$ + * + * @author Vishal Kachroo <vishal@cs.wustl.edu> + */ +//============================================================================= + + +#ifndef ACE_QOS_SESSION_H +#define ACE_QOS_SESSION_H +#include /**/ "ace/pre.h" + +#include "ACE_QoS_Export.h" +#include "ace/INET_Addr.h" +#include "ace/OS_QoS.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +ACE_BEGIN_VERSIONED_NAMESPACE_DECL + +class ACE_SOCK; +class ACE_QoS_Manager; + +typedef int ACE_Protocol_ID; +// IPPROTO_UDP or IPPROTO_TCP. + +/** + * @class ACE_QoS_Session + * + * @brief A QoS Session object. + * + * This class defines the interface for a QoS Session. It abstracts the + * notion of QoS on different platforms and presents a simple, easy-to-use + * API. Current [RAPI,GQoS] and future implementations will conform to this + * interface. + */ +class ACE_QoS_Export ACE_QoS_Session +{ + +public: + + enum RSVP_Event_Type + { + RSVP_PATH_EVENT, + RSVP_RESV_EVENT, + RSVP_RESV_CONFIRM, + RSVP_RESV_ERROR, + RSVP_PATH_ERROR + }; + + /// A flag to indicate if this endpoint is a sender or a receiver or + /// both. + enum ACE_End_Point_Type + { + ACE_QOS_SENDER, + ACE_QOS_RECEIVER, + ACE_QOS_BOTH + }; + + + /// to shutup g++. + virtual ~ACE_QoS_Session (void) {}; + + /// Open a QoS session [dest IP, dest port, Protocol ID]. + virtual int open (ACE_INET_Addr dest_addr, + ACE_Protocol_ID protocol_id) = 0; + + /// Close the QoS Session. + virtual int close (void) = 0; + + /// Returns the QoS in the current session. + virtual ACE_QoS qos (void) const = 0; + + /// Set QoS for the current session. The qos manager is used to + /// confirm if this QoS session was subscribed to by the socket. + virtual int qos (ACE_SOCK *socket, + ACE_QoS_Manager *qos_manager, + const ACE_QoS &ace_qos) = 0; + + /** + * Sets the QoS for this session object to ace_qos. Does not + * interfere with the QoS in the underlying socket. This call is + * useful to update the QoS object when the underlying socket QoS is + * being set through a mechanism other than the previous qos () + * method e.g. inside the dgram_mcast.subscribe () where the QoS for + * the socket is set through ACE_OS::join_leaf (). + */ + virtual void qos (const ACE_QoS &ace_qos) = 0; + + /** + * This is called from handle_qos () method of the the QoS Event + * Handler. Invoking this method is an indication of a QoS event + * occurring, that may have resulted in a change of QoS for the + * underlying session. This method updates the QoS object associated + * with this session. + */ + virtual int update_qos (void) = 0; + + /// Get/Set methods for the flags_. + virtual ACE_End_Point_Type flags (void) const = 0; + virtual void flags (const ACE_End_Point_Type flags) = 0; + + /// Get the session id. + virtual int session_id (void) const = 0; + + /// Set the session id. + virtual void session_id (const int session_id) = 0; + + /// Get the file descriptor on which RSVP events will occur. + virtual ACE_HANDLE rsvp_events_handle (void) = 0; + + virtual void rsvp_event_type (RSVP_Event_Type event_type) = 0; + ///Set the RAPI event that last occured + + virtual RSVP_Event_Type rsvp_event_type (void) = 0; + ///Get the RAPI event that last occured + + + /// Get the destination address for this session. + virtual ACE_INET_Addr dest_addr (void) const = 0; + + /// Set the destination address for this session. + virtual void dest_addr (const ACE_INET_Addr &dest_addr) = 0; + + /// Get the source port for this session. + virtual u_short source_port (void) const = 0; + + /// Set the source port for this session. + virtual void source_port (const u_short &source_port) = 0; + + //Set the source host + virtual ACE_INET_Addr* source_addr (void) const = 0; + + /// Set the source port for this session. + virtual void source_addr (ACE_INET_Addr* source_addr) = 0; + + + /** + * Returns the version of the underlying RSVP implementation. Is + * meaningful only when the underlying implementation has + * versioning. + */ + virtual int version (void) = 0; + +protected: + + /// Source port if this is a Sender session. Used for rapi_sender (). + u_short source_port_; + + /// session id for the session. + int session_id_; + + /// Destination address for this session. + ACE_INET_Addr dest_addr_; + + /// Source address for this session. + ACE_INET_Addr* src_addr_; + + /// Is this a TCP or a UDP session. + ACE_Protocol_ID protocol_id_; + + /// QoS for this session. + ACE_QoS qos_; + + /// Specifies if this is a sending/receiving/both session. + ACE_End_Point_Type flags_; + + RSVP_Event_Type rsvp_event_type_; + //Has the last rsvp event that occured + +}; + +ACE_END_VERSIONED_NAMESPACE_DECL + +#include /**/ "ace/post.h" +#endif /* ACE_QOS_SESSION_H */ diff --git a/ACE/ace/QoS/QoS_Session_Factory.cpp b/ACE/ace/QoS/QoS_Session_Factory.cpp new file mode 100644 index 00000000000..89a8fbcc913 --- /dev/null +++ b/ACE/ace/QoS/QoS_Session_Factory.cpp @@ -0,0 +1,105 @@ +// QoS_Session_Factory.cpp +// $Id$ + +#include "QoS_Session_Factory.h" +#include "QoS_Session_Impl.h" +#include "ace/Log_Msg.h" + +ACE_RCSID(ace, QoS_Session_Factory, "$Id$") + +ACE_BEGIN_VERSIONED_NAMESPACE_DECL + +ACE_ALLOC_HOOK_DEFINE(ACE_QoS_Session_Factory) + +#if defined(ACE_HAS_RAPI) +const enum ACE_QoS_Session_Factory::ACE_QoS_Session_Type + ACE_QoS_Session_Factory::ACE_DEFAULT_QOS_SESSION = ACE_QoS_Session_Factory::ACE_RAPI_SESSION; +#elif defined(ACE_HAS_WINSOCK2_GQOS) + const enum ACE_QoS_Session_Factory::ACE_QoS_Session_Type + ACE_QoS_Session_Factory::ACE_DEFAULT_QOS_SESSION = ACE_QoS_Session_Factory::ACE_GQOS_SESSION; +#else +# error "QoS type not supported. Cannot build." +#endif /* ACE_HAS_RAPI */ + +ACE_QoS_Session_Factory::ACE_QoS_Session_Factory (void) +{ + ACE_TRACE ("ACE_QoS_Session_Factory::ACE_QoS_Session_Factory"); +} + +ACE_QoS_Session_Factory::~ACE_QoS_Session_Factory (void) +{ + ACE_TRACE ("ACE_QoS_Session_Factory::~ACE_QoS_Session_Factory"); +} + +// Create a QoS session of the given type (RAPI or GQoS). +ACE_QoS_Session * +ACE_QoS_Session_Factory::create_session (ACE_QoS_Session_Type qos_session_type) +{ + + ACE_QoS_Session * qos_session = 0; + +#if defined (ACE_HAS_RAPI) + if (qos_session_type == ACE_RAPI_SESSION) + ACE_NEW_RETURN (qos_session, + ACE_RAPI_Session, + 0); +#endif /* ACE_HAS_RAPI */ + + if (qos_session_type == ACE_GQOS_SESSION) + ACE_NEW_RETURN (qos_session, + ACE_GQoS_Session, + 0); + + if (this->add_session (qos_session) == -1) + { + delete qos_session; + ACE_ERROR_RETURN ((LM_ERROR, + ACE_LIB_TEXT ("Error in adding session\n")), + 0); + } + + return qos_session; +} + +// Destroy the QoS Session. +int +ACE_QoS_Session_Factory::destroy_session (ACE_QoS_Session *qos_session) +{ + + if ((qos_session != 0) && (this->remove_session (qos_session) == -1)) + ACE_ERROR_RETURN ((LM_ERROR, + ACE_LIB_TEXT ("Error in destroying session\n")), + -1); + + return 0; +} + +// Add a session to the set of sessions created by this factory. This is a +// private method called by the create_session (). +int +ACE_QoS_Session_Factory::add_session (ACE_QoS_Session *qos_session) +{ + if (this->qos_session_set_.insert (qos_session) != 0) + ACE_ERROR_RETURN ((LM_ERROR, + ACE_LIB_TEXT ("Error in adding a new session") + ACE_LIB_TEXT ("to the session set\n")), + -1); + + return 0; +} + +// Remove a session from the set of sessions created by this factory. This is +// a private method called by the destroy_session (). +int +ACE_QoS_Session_Factory::remove_session (ACE_QoS_Session *qos_session) +{ + if (this->qos_session_set_.remove (qos_session) == -1) + ACE_ERROR_RETURN ((LM_ERROR, + ACE_LIB_TEXT ("Error in removing a session") + ACE_LIB_TEXT ("from the session set\n")), + -1); + + return 0; +} + +ACE_END_VERSIONED_NAMESPACE_DECL diff --git a/ACE/ace/QoS/QoS_Session_Factory.h b/ACE/ace/QoS/QoS_Session_Factory.h new file mode 100644 index 00000000000..0559dce4220 --- /dev/null +++ b/ACE/ace/QoS/QoS_Session_Factory.h @@ -0,0 +1,96 @@ +// -*- C++ -*- + +//============================================================================= +/** + * @file QoS_Session_Factory.h + * + * $Id$ + * + * @author Vishal Kachroo <vishal@cs.wustl.edu> + */ +//============================================================================= + + +#ifndef ACE_QOS_SESSION_FACTORY_H +#define ACE_QOS_SESSION_FACTORY_H +#include /**/ "ace/pre.h" + +#include "ace/QoS/QoS_Session.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "ace/Containers_T.h" +#include "ACE_QoS_Export.h" + +ACE_BEGIN_VERSIONED_NAMESPACE_DECL + +// Forward declare this, so the factory uses only references to this. +class ACE_QoS_Session; + +/** + * @class ACE_QoS_Session_Factory + * + * @brief Concrete factory for the QoS Session objects. + * + * This class manages the life cycle of QoS Session objects. These + * objects are currently either RAPI session objects or GQoS session + * objects. It stores the sessions in an unbounded set. + */ +class ACE_QoS_Export ACE_QoS_Session_Factory +{ + +public : + + // = Initialization and termination methods. + /// Default constructor. + ACE_QoS_Session_Factory (void); + + /// Default destructor. + ~ACE_QoS_Session_Factory (void); + + + /// Types of sessions for this factory to manage. + enum ACE_QoS_Session_Type + { + /// ACE_RAPI_SESSION on Unix platforms with RAPI support + ACE_RAPI_SESSION, + + /// ACE_GQOS_SESSION on Windows platforms with GQOS support + ACE_GQOS_SESSION + }; + + /** The default QoS type supported on this platform. + * + * ACE_DEFAULT_QOS_SESSION = ACE_RAPI_SESSION on Unix platforms with RAPI support + * = ACE_GQOS_SESSION on Windows platforms with GQOS support + */ + static const enum ACE_QoS_Session_Type ACE_DEFAULT_QOS_SESSION; + + /// Create a QoS session of the given type (RAPI or GQoS). + ACE_QoS_Session * create_session (ACE_QoS_Session_Type qos_session_type = ACE_DEFAULT_QOS_SESSION ); + + /// Destroy the QoS Session. + int destroy_session (ACE_QoS_Session *qos_session); + +private: + + /// Used by the create_session () to add new sessions to the + /// set of sessions created by this factory. + int add_session (ACE_QoS_Session *qos_session); + + /// Used by the destroy_session () to remove a session from the set + /// of sessions created by this factory. + int remove_session (ACE_QoS_Session *qos_session); + + /// Unordered set of QoS Sessions. + typedef ACE_Unbounded_Set <ACE_QoS_Session *> QOS_SESSION_SET; + QOS_SESSION_SET qos_session_set_; + +}; + +ACE_END_VERSIONED_NAMESPACE_DECL + +#include /**/ "ace/post.h" +#endif /* ACE_QOS_SESSION_FACTORY_H */ diff --git a/ACE/ace/QoS/QoS_Session_Impl.cpp b/ACE/ace/QoS/QoS_Session_Impl.cpp new file mode 100644 index 00000000000..09014ae50c2 --- /dev/null +++ b/ACE/ace/QoS/QoS_Session_Impl.cpp @@ -0,0 +1,724 @@ +// QoS_Session_Impl.cpp +// $Id$ + +#include "ace/OS_NS_arpa_inet.h" +#include "ace/SOCK.h" +#include "QoS_Manager.h" +#include "QoS_Session_Impl.h" +#include "ace/Log_Msg.h" + +#if !defined (__ACE_INLINE__) +#include "QoS_Session_Impl.i" +#endif /* __ACE_INLINE__ */ + +ACE_RCSID(ace, QoS_Session_Impl, "$Id$") + +ACE_BEGIN_VERSIONED_NAMESPACE_DECL + +ACE_ALLOC_HOOK_DEFINE(ACE_QoS_Session_Impl) + +ACE_END_VERSIONED_NAMESPACE_DECL + +#if defined (ACE_HAS_RAPI) +#include "rapi_err.h" + +ACE_BEGIN_VERSIONED_NAMESPACE_DECL + +int ACE_RAPI_Session::rsvp_error = 0; + +// Call back function used by RAPI to report RSVP events. This +// function translates the RAPI QoS parameters into the more generic +// ACE_QoS parameters for the underlying RAPI session. +int +rsvp_callback (rapi_sid_t /* sid */, + rapi_eventinfo_t eventype, + int /* style_id */, + int errcode, + int errvalue, + sockaddr * errnode, + u_char /* errflags */, + int /* filter_spec_no */, + rapi_filter_t * /* filter_spec_list */, + int flow_spec_no, + rapi_flowspec_t *flow_spec_list, + int /* ad_spec_no */, + rapi_adspec_t * /* ad_spec_list */, + void *args + ) +{ + if (args == 0) + ACE_DEBUG ((LM_DEBUG, + "Argument in the call back function is null\n\n")); + + ACE_QoS_Session *qos_session = (ACE_QoS_Session *) args; + + qos_flowspecx_t *csxp = 0; + + if (!flow_spec_list) + { + ACE_DEBUG ((LM_DEBUG, + "(%N|%l) Null flow_spec_list\n")); + } + else + { + // Extended Legacy format. + csxp = &flow_spec_list->specbody_qosx; + if(!csxp) + { + ACE_ERROR_RETURN ((LM_ERROR, + "(%N|%l) Null csxp\n"), + -1); + } + } + + ACE_QoS ace_qos = qos_session->qos (); + + switch(eventype) + { + case RAPI_PATH_EVENT: + { + ACE_DEBUG ((LM_DEBUG, + "RSVP PATH Event received\n" + "No. of TSpecs received : %d %d\n", + flow_spec_no, &flow_spec_list->len)); + + ACE_Flow_Spec *receiving_fs = 0; + + if (flow_spec_no != 0) + { + + ACE_NEW_RETURN (receiving_fs, + ACE_Flow_Spec, + -1); + + ACE_NEW_RETURN (receiving_fs, + ACE_Flow_Spec ((u_long)csxp->xspec_r, + (u_long)csxp->xspec_b, + (u_long)csxp->xspec_p, + 0, + csxp->xspec_S, + 1, + csxp->xspec_M, + csxp->xspec_m, + 25, + 0), + -1); + + + ACE_DEBUG ((LM_DEBUG, + "\nTSpec :\n" + "\t Spec Type = %d\n" + "\t Rate = %f\n" + "\t Bucket = %f\n" + "\t Peak = %f\n" + "\t MPU = %d\n" + "\t MDU = %d\n" + "\t TTL = %d\n", + csxp->spec_type, + csxp->xspec_r, + csxp->xspec_b, + csxp->xspec_p, + csxp->xspec_m, + csxp->xspec_M, + 25)); + + } + // Set the sending flowspec QoS of the given session. + ace_qos.receiving_flowspec (receiving_fs); + + qos_session->rsvp_event_type (ACE_QoS_Session::RSVP_PATH_EVENT); + + } + + break; + + case RAPI_RESV_EVENT: + { + ACE_DEBUG ((LM_DEBUG, + "RSVP RESV Event received\n" + "No. of FlowSpecs received : %d\n", + flow_spec_no)); + + ACE_Flow_Spec *sending_flow = 0; + + if (flow_spec_no != 0) + { + ACE_NEW_RETURN (sending_flow, + ACE_Flow_Spec, + -1); + + // Choose based on the service type : [QOS_GUARANTEEDX/QOS_CNTR_LOAD]. + switch (csxp->spec_type) + { + case QOS_GUARANTEEDX: + // Slack term in MICROSECONDS + sending_flow->delay_variation (csxp->xspec_S); + + // @@How does the guaranteed rate parameter map to the ACE_Flow_Spec. + // Note there is no break !! + + case QOS_CNTR_LOAD: + + // qos_service_type. + sending_flow->service_type (csxp->spec_type); + // Token Bucket Average Rate (B/s) + sending_flow->token_rate ((u_long)csxp->xspec_r); + // Token Bucket Rate (B) + sending_flow->token_bucket_size ((u_long)csxp->xspec_b); + // Peak Data Rate (B/s) + sending_flow->peak_bandwidth ((u_long)csxp->xspec_p); + // Minimum Policed Unit (B) + sending_flow->minimum_policed_size (csxp->xspec_m); + // Max Packet Size (B) + sending_flow->max_sdu_size (csxp->xspec_M); + + break; + + default: + ACE_ERROR_RETURN ((LM_ERROR, + "(%N|%l) Unknown flowspec type: %u.\n", csxp->spec_type), + -1); + }; + } + ace_qos.sending_flowspec (sending_flow); + + qos_session->rsvp_event_type (ACE_QoS_Session::RSVP_RESV_EVENT); + } + break; + + case RAPI_PATH_ERROR: + { + ACE_DEBUG ((LM_DEBUG, + "PATH ERROR Event received\n" + "Code=%d Val=%d Node= %s\n", + errcode, + errvalue, + ACE_OS::inet_ntoa(((sockaddr_in *)errnode)->sin_addr))); + qos_session->rsvp_event_type (ACE_QoS_Session::RSVP_PATH_ERROR); + } + break; + + case RAPI_RESV_ERROR: + { + ACE_DEBUG ((LM_DEBUG, + "RESV ERROR Event received\n" + "Code=%d Val=%d Node= %s\n", + errcode, + errvalue, + ACE_OS::inet_ntoa(((sockaddr_in *)errnode)->sin_addr))); + qos_session->rsvp_event_type (ACE_QoS_Session::RSVP_RESV_ERROR); + } + break; + + case RAPI_RESV_CONFIRM: + { + ACE_DEBUG ((LM_DEBUG, + "RESV CONFIRM Event received\n")); + qos_session->rsvp_event_type (ACE_QoS_Session::RSVP_RESV_CONFIRM); + } + break; + + default: + ACE_DEBUG ((LM_DEBUG, + "Unknown RSVP Event Received\n")); + break; + + } + + // Set the updated ACE_QoS for the RSVP callback argument(QoS session). + qos_session->qos (ace_qos); + + // @@ what is the meaning of the return value. RAPI docs don't say anything! + return 0; +} + +// Constructor. +ACE_RAPI_Session::ACE_RAPI_Session (void) +{ + ACE_TRACE ("ACE_RAPI_Session::ACE_RAPI_Session"); + //this->source_port (DEFAULT_SOURCE_SENDER_PORT); + ACE_NEW (this->src_addr_, + ACE_INET_Addr ("0")); +} + +// Open a RAPI QoS session [dest IP, dest port, Protocol ID]. +int +ACE_RAPI_Session::open (ACE_INET_Addr dest_addr, + ACE_Protocol_ID protocol_id) +{ + char buf [BUFSIZ]; + dest_addr.addr_to_string (buf, + BUFSIZ); + ACE_DEBUG ((LM_DEBUG, + "In RAPI SESSION OPEN %s\n", + buf)); + + this->dest_addr_ = dest_addr; + this->protocol_id_ = protocol_id; + + // Open a RAPI session. Note "this" is being passed as an argument to + // the callback function. The callback function uses this argument to + // update the QoS of this session based on the RSVP event it receives. + + if ((this->session_id_ = rapi_session((struct sockaddr *) dest_addr.get_addr (), + protocol_id, + 0, + rsvp_callback, + (void *) this, + &rsvp_error)) == NULL_SID) + ACE_ERROR_RETURN ((LM_ERROR, + "rapi_session () call fails. Error\n"), + -1); + else + ACE_DEBUG ((LM_DEBUG, + "rapi_session () call succeeds. " + "Session ID = %d\n", + this->session_id_)); + + return 0; +} + +// Close the RAPI QoS Session. +int +ACE_RAPI_Session::close (void) +{ + this->rsvp_error = rapi_release(this->session_id_); + + if (rsvp_error == 0) + ACE_ERROR_RETURN ((LM_ERROR, + "Can't release RSVP session:\n\t%s\n", + rapi_errlist[rsvp_error]), + -1); + else + ACE_DEBUG ((LM_DEBUG, + "rapi session with id %d released successfully.\n", + this->session_id_)); + return 0; +} + +//Get the most recent RSVP event that occured +ACE_QoS_Session::RSVP_Event_Type +ACE_RAPI_Session::rsvp_event_type (void) +{ + return this->rsvp_event_type_; +} + +//Set the most recent RSVP event that occured +void +ACE_RAPI_Session::rsvp_event_type (ACE_QoS_Session::RSVP_Event_Type event_type) +{ + this->rsvp_event_type_ = event_type; +} + +int +ACE_RAPI_Session::qos (ACE_SOCK * /* socket */, + ACE_QoS_Manager * /* qos_manager */, + const ACE_QoS &ace_qos) +{ + + // If sender : call sending_qos () + // If receiver : call receiving_qos () + // If both : call sending_qos () and receiving_qos () + + if (this->flags_ != ACE_QOS_RECEIVER) + return this->sending_qos (ace_qos); + + if (this->flags_ != ACE_QOS_SENDER) + return this->receiving_qos (ace_qos); + + return 0; +} + +// Set sending QoS for this RAPI session. +int +ACE_RAPI_Session::sending_qos (const ACE_QoS &ace_qos) +{ + ACE_Flow_Spec *sending_flowspec = ace_qos.sending_flowspec (); + + if (sending_flowspec == 0) + { + int result = rapi_sender (this->session_id_, + 0, + 0, + NULL, + 0, + NULL, + NULL, + 25) ; + if (result != 0) + ACE_ERROR_RETURN ((LM_ERROR, + "(%N|%l) rapi_sender error %d:\n\tPATH Generation can't be started\n", + result), + -1); + else + ACE_DEBUG ((LM_DEBUG, + "rapi_sender () call succeeds with PATH Tear! \n")); + + return 0; + } + + rapi_tspec_t *t_spec = this->init_tspec_simplified (*sending_flowspec); + if (t_spec == 0) + ACE_ERROR_RETURN ((LM_ERROR, + "(%N|%l) Error in translating from ACE Flow Spec to" + " RAPI TSpec\n"), + -1); + + char buffer[BUFSIZ]; + + // This formats the t_spec in a visually intuitive char * that can + // be printed. + + (void) rapi_fmt_tspec(t_spec, buffer, sizeof(buffer)); + ACE_DEBUG ((LM_DEBUG, + "\nSender TSpec : %s\n", + buffer)); + + // Print out all the fields separately. + ACE_DEBUG ((LM_DEBUG, + "\nTSpec :\n" + "\t Spec Type = %d\n" + "\t Rate = %f\n" + "\t Bucket = %f\n" + "\t Peak = %f\n" + "\t MPU = %d\n" + "\t MDU = %d\n" + "\t TTL = %d\n", + t_spec->tspecbody_qosx.spec_type, + t_spec->tspecbody_qosx.xtspec_r, + t_spec->tspecbody_qosx.xtspec_b, + t_spec->tspecbody_qosx.xtspec_p, + t_spec->tspecbody_qosx.xtspec_m, + t_spec->tspecbody_qosx.xtspec_M, + sending_flowspec->ttl ())); + + // This the source sender port. + // ACE_INET_Addr sender_addr (this->source_port ()); + + ACE_DEBUG ((LM_DEBUG, + "Making the rapi_sender () call\n")); + + // Set the Sender TSpec for this QoS session. + + + int result = rapi_sender(this->session_id_, + 0, + (sockaddr *) this->src_addr_->get_addr (), + NULL, + t_spec, + NULL, + NULL, + sending_flowspec->ttl ()) ; + + /* + int result = rapi_sender(this->session_id_, + 0, + (sockaddr *) sender_addr.get_addr (), + NULL, + t_spec, + NULL, + NULL, + sending_flowspec->ttl ()) ; + */ + if(result!= 0) + ACE_ERROR_RETURN ((LM_ERROR, + "(%N|%l) rapi_sender error %d:\n\tPATH Generation can't be started\n", + result), + -1); + else + ACE_DEBUG ((LM_DEBUG, + "rapi_sender () call succeeds ! \n")); + return 0; +} + +// Set receiving QoS for this RAPI session. +int +ACE_RAPI_Session::receiving_qos (const ACE_QoS &ace_qos) +{ + + ACE_Flow_Spec *receiving_flowspec = ace_qos.receiving_flowspec (); + if (receiving_flowspec == 0) + { + if (rapi_reserve(this->session_id_, + 0, + // Setting the RAPI_REQ_CONFIRM flag requests confirmation + // of the resevation, by means of a confirmation upcall of + // type RAPI_RESV_CONFIRM. + // (sockaddr *)receiver_addr.get_addr (), + 0, + RAPI_RSTYLE_WILDCARD, + // This applies the flowspec to all the senders. Given this, + // @@I am passing the filter_spec to be null, hoping this will work. + NULL, + NULL, + 0, + NULL, + // The filter spec is NULL. This should work since the RSTYLE is + // WILDCARD. + 0, + 0) == -1) + ACE_ERROR_RETURN ((LM_ERROR, + "(%N|%l)rapi_reserve () error:\n\tRESV Generation can't be started\n"), + -1); + else + ACE_DEBUG ((LM_DEBUG, + "rapi_reserve () for RESV Tear call succeeds \n")); + + return 0; + } + + + rapi_flowspec_t *flow_spec = init_flowspec_simplified (*receiving_flowspec); + + if (flow_spec == 0) + ACE_ERROR_RETURN ((LM_ERROR, + "(%N|%l) Error in translating from ACE Flow Spec to" + " RAPI FlowSpec\n"), + -1); + + char buffer[BUFSIZ]; + + // This formats the flow_spec in a visually intuitive char * that can + // be printed. + (void)rapi_fmt_flowspec(flow_spec, buffer, sizeof(buffer)); + ACE_DEBUG ((LM_DEBUG, + "\nReceiver FlowSpec : %s\n", + buffer)); + + // Print out all the fields separately. + ACE_DEBUG ((LM_DEBUG, + "\nFlowSpec :\n" + "\t Spec Type = %d\n" + "\t Rate = %f\n" + "\t Bucket = %f\n" + "\t Peak = %f\n" + "\t MPU = %d\n" + "\t MDU = %d\n", + flow_spec->specbody_qosx.spec_type, + flow_spec->specbody_qosx.xspec_r, + flow_spec->specbody_qosx.xspec_b, + flow_spec->specbody_qosx.xspec_p, + flow_spec->specbody_qosx.xspec_m, + flow_spec->specbody_qosx.xspec_M)); + + sockaddr_in Receiver_host; + + Receiver_host.sin_addr.s_addr = INADDR_ANY; + + // Set the Receiver FlowSpec for this QoS session. + // @@The filter style is hardcoded to WildCard. This can be changed later. + if (rapi_reserve(this->session_id_, + RAPI_REQ_CONFIRM, + // Setting the RAPI_REQ_CONFIRM flag requests confirmation + // of the resevation, by means of a confirmation upcall of + // type RAPI_RESV_CONFIRM. + // (sockaddr *)receiver_addr.get_addr (), + (sockaddr *)&Receiver_host, + RAPI_RSTYLE_WILDCARD, + // This applies the flowspec to all the senders. Given this, + // @@I am passing the filter_spec to be null, hoping this will work. + NULL, + NULL, + 0, + NULL, + // The filter spec is NULL. This should work since the RSTYLE is + // WILDCARD. + 1, + flow_spec) == -1) + ACE_ERROR_RETURN ((LM_ERROR, + "rapi_reserve () error:\n\tRESV Generation can't be started\n"), + -1); + else + ACE_DEBUG ((LM_DEBUG, + "rapi_reserve () call succeeds \n")); + + return 0; +} + +int +ACE_RAPI_Session::update_qos (void) +{ + // Update the session QoS Parameters based on the RSVP Event Received. + if ((rsvp_error = rapi_dispatch ()) != 0) + ACE_ERROR_RETURN ((LM_ERROR, + "Error in rapi_dispatch () : %s\n", + rapi_errlist[rsvp_error]), + -1); + return 0; +} + +// Construct a simplified RAPI Sender TSpec object +// from an ACE_Flow_Spec. Note the form of the TSpec is +// simplified as against the full bodied IntServ version. + +rapi_tspec_t * +ACE_RAPI_Session::init_tspec_simplified (const ACE_Flow_Spec &flow_spec) +{ + rapi_tspec_t *t_spec; + + ACE_NEW_RETURN (t_spec, + rapi_tspec_t, + 0); + + qos_tspecx_t *ctxp = &(t_spec->tspecbody_qosx); + + // There may be some type incompatibility here. + // Note the types of the LHS are float32_t, uint32_t etc. + + ctxp->spec_type = flow_spec.service_type ();//QOS_TSPEC; + ctxp->xtspec_r = flow_spec.token_rate (); // Token Rate (B/s) + ctxp->xtspec_b = flow_spec.token_bucket_size (); // Token Bucket Depth (B) + ctxp->xtspec_p = flow_spec.peak_bandwidth (); // Peak Data Rate (B/s) + ctxp->xtspec_m = flow_spec.minimum_policed_size (); // Minimum policed unit. + ctxp->xtspec_M = flow_spec.max_sdu_size(); // Maximum SDU size. + t_spec->len = sizeof(rapi_hdr_t) + sizeof(qos_tspecx_t); + t_spec->form = RAPI_TSPECTYPE_Simplified; + + return (t_spec); +} + + +// Construct a simplified RAPI flowspec object from ACE_Flow_Spec. +// Note the form of the FlowSpec is simplified as against the +// full bodied IntServ version. + +rapi_flowspec_t * +ACE_RAPI_Session::init_flowspec_simplified(const ACE_Flow_Spec &flow_spec) +{ + rapi_flowspec_t *flowsp; + ACE_NEW_RETURN (flowsp, + rapi_flowspec_t, + 0); + + // Extended Legacy format. + qos_flowspecx_t *csxp = &flowsp->specbody_qosx; + + // Choose based on the service type : [QOS_GUARANTEEDX/QOS_CNTR_LOAD]. + + switch (flow_spec.service_type ()) + { + case QOS_GUARANTEEDX: + csxp->xspec_R = 0 ; // Guaranteed Rate B/s. @@How does this map to the + // ACE Flow Spec Parameters. + + csxp->xspec_S = flow_spec.delay_variation () ; // Slack term in MICROSECONDS + + // Note there is no break !! + + case QOS_CNTR_LOAD: + csxp->spec_type = flow_spec.service_type (); // qos_service_type + csxp->xspec_r = flow_spec.token_rate (); // Token Bucket Average Rate (B/s) + csxp->xspec_b = flow_spec.token_bucket_size (); // Token Bucket Rate (B) + csxp->xspec_p = flow_spec.peak_bandwidth (); // Peak Data Rate (B/s) + csxp->xspec_m = flow_spec.minimum_policed_size (); // Minimum Policed Unit (B) + + csxp->xspec_M = flow_spec.max_sdu_size(); // Max Packet Size (B) + + flowsp->form = RAPI_FLOWSTYPE_Simplified; + break; + + default: + ACE_ERROR_RETURN ((LM_ERROR, + "(%N|%l) Unknown flowspec type: %u\n",flow_spec.service_type () ), + 0); + } + + flowsp->len = sizeof(rapi_flowspec_t); + return flowsp; +} + +ACE_END_VERSIONED_NAMESPACE_DECL + +#endif /* ACE_HAS_RAPI */ + +ACE_BEGIN_VERSIONED_NAMESPACE_DECL + +// This is a GQoS session ID generator. +int ACE_GQoS_Session::GQoS_session_id = 0; + +// Constructor. +ACE_GQoS_Session::ACE_GQoS_Session (void) +{ + ACE_TRACE ("ACE_GQoS_Session::ACE_GQoS_Session"); +} + +// Open a GQoS session [dest IP, dest port, Protocol ID]. +int +ACE_GQoS_Session::open (ACE_INET_Addr dest_addr, + ACE_Protocol_ID protocol_id) +{ + this->dest_addr_ = dest_addr; + this->protocol_id_ = protocol_id; + + this->session_id_ = GQoS_session_id++; + + return 0; +} + +// Close the GQoS Session. +int +ACE_GQoS_Session::close (void) +{ + // TBD. + return 0; +} + +// Set the QoS for this GQoS session. +int +ACE_GQoS_Session::qos (ACE_SOCK *socket, + ACE_QoS_Manager *qos_manager, + const ACE_QoS &ace_qos) +{ + + // Confirm if the current session is one of the QoS sessions + // subscribed to by the given socket. + + if (qos_manager->qos_session_set ().find (this) == -1) + ACE_ERROR_RETURN ((LM_ERROR, + ACE_LIB_TEXT ("This QoS session was not subscribed to") + ACE_LIB_TEXT (" by the socket\n")), + -1); + + // Set the QOS according to the supplied ACE_QoS. The I/O control + // code used under the hood is SIO_SET_QOS. + + u_long ret_bytes = 0; + + ACE_QoS qos = ace_qos; + if (ACE_OS::ioctl (socket->get_handle (), + ACE_SIO_SET_QOS, + qos, + &ret_bytes) == -1) + ACE_ERROR_RETURN ((LM_ERROR, + ACE_LIB_TEXT ("Error in Qos set ACE_OS::ioctl() %d\n"), + ret_bytes), + -1); + else + ACE_DEBUG ((LM_DEBUG, + ACE_LIB_TEXT ("Setting QoS with ACE_OS::ioctl () succeeds \n"))); + + return 0; +} + +int +ACE_GQoS_Session::update_qos (void) +{ + // WSAIoctl (GET_QOS) call goes here... + return 0; +} + +//Get the most recent RSVP event that occured +ACE_QoS_Session::RSVP_Event_Type +ACE_GQoS_Session::rsvp_event_type (void) +{ + return this->rsvp_event_type_; +} + +//Set the most recent RSVP event that occured +void +ACE_GQoS_Session::rsvp_event_type (ACE_QoS_Session::RSVP_Event_Type event_type) +{ + this->rsvp_event_type_ = event_type; +} + +ACE_END_VERSIONED_NAMESPACE_DECL diff --git a/ACE/ace/QoS/QoS_Session_Impl.h b/ACE/ace/QoS/QoS_Session_Impl.h new file mode 100644 index 00000000000..193c537a74c --- /dev/null +++ b/ACE/ace/QoS/QoS_Session_Impl.h @@ -0,0 +1,265 @@ +// -*- C++ -*- + +//============================================================================= +/** + * @file QoS_Session_Impl.h + * + * $Id$ + * + * @author Vishal Kachroo <vishal@cs.wustl.edu> + */ +//============================================================================= + + +#ifndef ACE_QOS_SESSION_IMPL_H +#define ACE_QOS_SESSION_IMPL_H +#include /**/ "ace/pre.h" + +#include "ace/QoS/QoS_Session.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + + +#if defined (ACE_HAS_RAPI) +#include "rapi_lib.h" + +#define DEFAULT_SOURCE_SENDER_PORT 10001 + +ACE_BEGIN_VERSIONED_NAMESPACE_DECL + +/** + * @class ACE_RAPI_Session + * + * @brief A RAPI QoS session object. + * + * This class is a RAPI (RSVP API, an implementation of RSVP on UNIX) + * implementation of the ACE_QoS_Session interface. + */ +class ACE_QoS_Export ACE_RAPI_Session : public ACE_QoS_Session +{ + +public: + + /// Default destructor. + ~ACE_RAPI_Session (void); + + /// Error handling for RSVP callback + static int rsvp_error; + + /// Open a RAPI QoS session [dest IP, dest port, Protocol ID]. + virtual int open (ACE_INET_Addr dest_addr, + ACE_Protocol_ID protocol_id); + + /// Close the RAPI QoS Session. + virtual int close (void); + + /// Returns the QoS for this RAPI session. + virtual ACE_QoS qos (void) const; + + /// Set QoS for this RAPI session. The socket parameter is used to confirm if + /// this QoS session was subscribed to by the socket. + virtual int qos (ACE_SOCK *socket, + ACE_QoS_Manager *qos_manager, + const ACE_QoS &ace_qos); + + /** + * Sets the QoS for this session object to ace_qos. Does not interfere with the + * QoS in the underlying socket. This call is useful to update the QoS object + * when the underlying socket QoS is being set through a mechanism other than + * the previous qos () method e.g. inside the dgram_mcast.subscribe () where the + * QoS for the socket is set through ACE_OS::join_leaf (). + */ + virtual void qos (const ACE_QoS &ace_qos); + + /** + * Calls rapi_dispatch () that further triggers the call back function. + * It is a mechanism of updating the QoS for this session asynchronously, as + * RSVP events occur. + */ + virtual int update_qos (void); + + /// Get methods for the flags_. + virtual ACE_End_Point_Type flags (void) const; + + /// Set methods for the flags_. + virtual void flags (const ACE_End_Point_Type flags); + + /// Get the RAPI session id. + virtual int session_id (void) const; + + /// Set the RAPI session id. + virtual void session_id (const int session_id); + + /// Get the RAPI file descriptor for RSVP events. + virtual ACE_HANDLE rsvp_events_handle (void); + + ///Set the RAPI event that last occured + virtual void rsvp_event_type (RSVP_Event_Type event_type); + + ///Get the RAPI event that last occured + virtual RSVP_Event_Type rsvp_event_type (void); + + /// Get the destination address for this RAPI session. + virtual ACE_INET_Addr dest_addr (void) const; + + /// Set the destination address for this RAPI session. + virtual void dest_addr (const ACE_INET_Addr &dest_addr); + + /// Get the source port for this session. + virtual u_short source_port (void) const; + + /// Set the source port for this session. + virtual void source_port (const u_short &source_port); + + //Set the source host + virtual ACE_INET_Addr* source_addr (void) const; + + /// Set the source port for this session. + virtual void source_addr (ACE_INET_Addr* source_addr); + + /// RAPI version. Returned value = 100 * major-version + minor-version. + virtual int version (); + + /// The factory is a friend so it can create this object through + /// the only private constructor. + friend class ACE_QoS_Session_Factory; + +private: + + /// Default constuctor. Constructor is defined private so that only + /// the friend factory can instantiate this class. + ACE_RAPI_Session (void); + + /// Construct a simplified RAPI Sender TSpec object + /// from an ACE_Flow_Spec object. Used internally by this class. + rapi_tspec_t *init_tspec_simplified (const ACE_Flow_Spec &flow_spec); + + /// Construct a simplified RAPI Receiver FlowSpec object + /// from an ACE_Flow_Spec object. Used internally by the class. + rapi_flowspec_t *init_flowspec_simplified(const ACE_Flow_Spec &flow_spec); + + /// Set sending QoS for this RAPI session. + int sending_qos (const ACE_QoS &ace_qos); + + /// Set receiving QoS for this RAPI session. + int receiving_qos (const ACE_QoS &ace_qos); + +}; + +ACE_END_VERSIONED_NAMESPACE_DECL + +#endif /* ACE_HAS_RAPI */ + +ACE_BEGIN_VERSIONED_NAMESPACE_DECL + +/** + * @class ACE_GQoS_Session + * + * @brief A GQoS session object. + * + * This class is a GQoS (Generic QoS, an implementation of RSVP on + * Win2K) implementation of the ACE_QoS_Session interface. + */ +class ACE_QoS_Export ACE_GQoS_Session : public ACE_QoS_Session +{ + +public: + + /// Default destructor. + ~ACE_GQoS_Session (void); + + /// This is a session ID generator. It does a lot more than expected + /// from an int!. + static int GQoS_session_id; + + /// Open a GQoS session [dest IP, dest port, Protocol ID]. + virtual int open (ACE_INET_Addr dest_addr, + ACE_Protocol_ID protocol_id); + + /// Close the GQoS Session. + virtual int close (void); + + /// Returns the QoS for this GQoS session. + virtual ACE_QoS qos (void) const; + + /// Set QoS for this GQoS session. The socket parameter is used to confirm if + /// this QoS session was subscribed to by the socket. + virtual int qos (ACE_SOCK *socket, + ACE_QoS_Manager *qos_manager, + const ACE_QoS &ace_qos); + + /** + * Sets the QoS for this session object to ace_qos. Does not interfere with the + * QoS in the underlying socket. This call is useful to update the QoS object + * when the underlying socket QoS is being set through a mechanism other than + * the previous qos () method e.g. inside the dgram_mcast.subscribe () where the + * QoS for the socket is set through ACE_OS::join_leaf (). + */ + virtual void qos (const ACE_QoS &ace_qos); + + /// Calls the ioctl (ACE_SIO_GET_QOS). It is a mechanism of updating the + /// QoS for this session asynchronously, as RSVP events occur. + virtual int update_qos (void); + + /// Get/Set methods for the flags_. + virtual ACE_End_Point_Type flags (void) const; + virtual void flags (const ACE_End_Point_Type flags); + + /// Get the destination address for this GQoS session. + virtual ACE_INET_Addr dest_addr (void) const; + + /// Set the destination address for this GQoS session. + virtual void dest_addr (const ACE_INET_Addr &dest_addr); + + /// Get the source port for this session. + virtual u_short source_port (void) const; + + /// Set the source port for this session. + virtual void source_port (const u_short &source_port); + + //Set the source host + virtual ACE_INET_Addr* source_addr (void) const; + + /// Set the source port for this session. + virtual void source_addr (ACE_INET_Addr* source_addr); + + /// Get the GQoS session id. + virtual int session_id (void) const; + + /// Set the GQoS session id. + virtual void session_id (const int session_id); + + /// Get the file descriptor of the underlying socket. + virtual ACE_HANDLE rsvp_events_handle (void); + + virtual void rsvp_event_type (RSVP_Event_Type event_type); + ///Set the RAPI event that last occured + + virtual RSVP_Event_Type rsvp_event_type (void); + ///Get the RAPI event that last occured + + /// GQoS version. + virtual int version (); + + /// The factory is a friend so it can create this object through + /// the only private constructor. + friend class ACE_QoS_Session_Factory; + +private: + + /// Default constructor. Constructor is defined private so that only + /// the friend factory can instantiate this class. + ACE_GQoS_Session (void); + +}; + +ACE_END_VERSIONED_NAMESPACE_DECL + +#if defined (__ACE_INLINE__) +#include "QoS_Session_Impl.i" +#endif /* __ACE_INLINE__ */ + +#include /**/ "ace/post.h" +#endif /* ACE_QOS_SESSION_IMPL_H */ diff --git a/ACE/ace/QoS/QoS_Session_Impl.i b/ACE/ace/QoS/QoS_Session_Impl.i new file mode 100644 index 00000000000..b3971b46d52 --- /dev/null +++ b/ACE/ace/QoS/QoS_Session_Impl.i @@ -0,0 +1,229 @@ +// -*- C++ -*- +// +// $Id$ + +ACE_BEGIN_VERSIONED_NAMESPACE_DECL + +#if defined (ACE_HAS_RAPI) + +ACE_INLINE +ACE_RAPI_Session::~ACE_RAPI_Session (void) +{ + ACE_TRACE ("ACE_RAPI_Session::~ACE_RAPI_Session"); +} + +// Returns the QoS for this RAPI session. +ACE_INLINE ACE_QoS +ACE_RAPI_Session::qos (void) const +{ + return this->qos_; +} + +// Overloaded method to set the QoS for this session object. Does not +// interfere with the underlying socket QoS. +ACE_INLINE void +ACE_RAPI_Session::qos (const ACE_QoS &ace_qos) +{ + this->qos_ = ace_qos; +} + +// Get the RAPI session id. +ACE_INLINE int +ACE_RAPI_Session::session_id (void) const +{ + return this->session_id_; +} + +// Set the RAPI session id. +ACE_INLINE void +ACE_RAPI_Session::session_id (const int session_id) +{ + this->session_id_ = session_id; +} + +// Get the RAPI file desciptor for RSVP events. +ACE_INLINE ACE_HANDLE +ACE_RAPI_Session::rsvp_events_handle (void) +{ + int rapi_fd = rapi_getfd (this->session_id ()); + if (rapi_fd == -1) + { + this->close (); + ACE_ERROR_RETURN ((LM_ERROR, + "Error in rapi_getfd ()\n"), + -1); + } + + return rapi_fd; +} + +// Get the End Point Type (Sender/Receiver/Both). +ACE_INLINE ACE_QoS_Session::ACE_End_Point_Type +ACE_RAPI_Session::flags (void) const +{ + return this->flags_; +} + +// Set the End Point Type (Sender/Receiver/Both). +ACE_INLINE void +ACE_RAPI_Session::flags (const ACE_End_Point_Type flags) +{ + this->flags_ = flags; +} + + +// Get the destination address for this RAPI session. +ACE_INLINE ACE_INET_Addr +ACE_RAPI_Session::dest_addr (void) const +{ + return this->dest_addr_; +} + +// Set the destination address for this RAPI session. +ACE_INLINE void +ACE_RAPI_Session::dest_addr (const ACE_INET_Addr &dest_addr) +{ + this->dest_addr_ = dest_addr; +} + +// Get the source port for this RAPI session. +ACE_INLINE u_short +ACE_RAPI_Session::source_port (void) const +{ + return this->source_port_; +} + +// Set the source port for this RAPI session. +ACE_INLINE void +ACE_RAPI_Session::source_port (const u_short &source_port) +{ + this->source_port_ = source_port; +} + +ACE_INLINE ACE_INET_Addr* +ACE_RAPI_Session::source_addr (void) const +{ + return this->src_addr_; +} + +ACE_INLINE void +ACE_RAPI_Session::source_addr (ACE_INET_Addr* source_addr) +{ + this->src_addr_ = source_addr; +} + +// RAPI version. Returned value = 100 * major-version + minor-version. +ACE_INLINE int +ACE_RAPI_Session::version (void) +{ + return 0; +} + +#endif /* ACE_HAS_RAPI */ + +ACE_INLINE +ACE_GQoS_Session::~ACE_GQoS_Session (void) +{ + ACE_TRACE ("ACE_GQoS_Session::~ACE_GQoS_Session"); +} + +// Returns the QoS for this GQoS session. +ACE_INLINE ACE_QoS +ACE_GQoS_Session::qos (void) const +{ + return this->qos_; +} + +// Overloaded method to set the QoS for this session object. Does not +// interfere with the underlying socket QoS. +ACE_INLINE void +ACE_GQoS_Session::qos (const ACE_QoS &ace_qos) +{ + this->qos_ = ace_qos; +} + +// Get the GQoS session id. +ACE_INLINE int +ACE_GQoS_Session::session_id (void) const +{ + return this->session_id_; +} + +// Set the GQoS session id. +ACE_INLINE void +ACE_GQoS_Session::session_id (const int session_id) +{ + this->session_id_ = session_id; +} + +// Get the underlying file desciptor for RSVP events. +// Currently returns 0 because GQoS does not have a special +// descriptor for QoS events. +ACE_INLINE ACE_HANDLE +ACE_GQoS_Session::rsvp_events_handle (void) +{ + return 0; +} + +// Get the End Point Type (Sender/Receiver/Both). +ACE_INLINE ACE_QoS_Session::ACE_End_Point_Type +ACE_GQoS_Session::flags (void) const +{ + return this->flags_; +} + +// Set the End Point Type (Sender/Receiver/Both). +ACE_INLINE void +ACE_GQoS_Session::flags (const ACE_End_Point_Type flags) +{ + this->flags_ = flags; +} + +// Get the destination address for this GQoS session. +ACE_INLINE ACE_INET_Addr +ACE_GQoS_Session::dest_addr (void) const +{ + return this->dest_addr_; +} + +// Set the destination address for this GQoS session. +ACE_INLINE void +ACE_GQoS_Session::dest_addr (const ACE_INET_Addr &dest_addr) +{ + this->dest_addr_ = dest_addr; +} + +// Get the source port for this RAPI session. +ACE_INLINE u_short +ACE_GQoS_Session::source_port (void) const +{ + return this->source_port_; +} + +// Set the source port for this RAPI session. +ACE_INLINE void +ACE_GQoS_Session::source_port (const u_short &source_port) +{ + this->source_port_ = source_port; +} + +ACE_INLINE ACE_INET_Addr* +ACE_GQoS_Session::source_addr (void) const +{ + return this->src_addr_; +} + +ACE_INLINE void +ACE_GQoS_Session::source_addr (ACE_INET_Addr* source_addr) +{ + this->src_addr_ = source_addr; +} + +// GQoS version. +ACE_INLINE int +ACE_GQoS_Session::version (void) +{ + return 0; +} + +ACE_END_VERSIONED_NAMESPACE_DECL diff --git a/ACE/ace/QoS/README b/ACE/ace/QoS/README new file mode 100644 index 00000000000..4415bf1862b --- /dev/null +++ b/ACE/ace/QoS/README @@ -0,0 +1,55 @@ +$Id$ + +ACE QoS API (AQoSA) +=================== + +This directory contains the implementation for the ACE QoS API (AQoSA). + +BUILD REQUIREMENTS +================== +WIN2K : + +AQoSA makes use of the GQOS API under Windows 2000. The minimum +requirements are: + +1. June98 Platform SDK or later. +2. Link with ws2_32.lib + +More information about GQOS is available from the MSDN website: +http://msdn.microsoft.com/msdn-files/026/002/258/Search.asp + +------------------------------------------------------------------------------- + +UNIX : + +AQoSA makes use of the RSVP API (RAPI) under UNIX. +RAPI can be obtained from: ftp://ftp.isi.edu/rsvp/release/. +rsvpd.rel4.2a4-1 may require patches in order to compile +under current versions of Linux. Contact Craig Rodrigues <crodrigu@bbn.com> +to obtain these patches. + +The following lines should be added to your platform_macros.GNU file +before building AQoSA: + +PLATFORM_RAPI_CPPFLAGS += -I[path to RAPI header files] +PLATFORM_RAPI_LIBS += -lrsvp +PLATFORM_RAPI_LDFLAGS += -L[path to RAPI library files] + +1. Compile AQoSA with + + make rapi=1 + +More information about RAPI can be found at: + +http://www.opengroup.org/onlinepubs/9619099/toc.htm +http://www.cs.wustl.edu/~vishal/qos.html +http://www.sun.com/software/bandwidth/rsvp/docs/ +http://www.tru64unix.compaq.com/faqs/publications/base_doc/DOCUMENTATION/V51_HTML/ARH9UCTE/TOC.HTM#RSVPCHXX + +------------------------------------------------------------------------------- + +TEST +==== + +The test for AQoSA is located in $ACE_ROOT/examples/QOS + diff --git a/ACE/ace/QoS/SOCK_Dgram_Mcast_QoS.cpp b/ACE/ace/QoS/SOCK_Dgram_Mcast_QoS.cpp new file mode 100644 index 00000000000..548c56bef12 --- /dev/null +++ b/ACE/ace/QoS/SOCK_Dgram_Mcast_QoS.cpp @@ -0,0 +1,258 @@ +// $Id$ + +#include "SOCK_Dgram_Mcast_QoS.h" +#include "ace/Log_Msg.h" +#include "ace/OS_NS_sys_socket.h" + +#if defined (ACE_WIN32) +#include "ace/Sock_Connect.h" // needed for subscribe_ifs() +#endif /* ACE_WIN32 */ + +#if !defined (__ACE_INLINE__) +#include "SOCK_Dgram_Mcast_QoS.i" +#endif /* __ACE_INLINE__ */ + +// This is a workaround for platforms with non-standard +// definitions of the ip_mreq structure +#if ! defined (IMR_MULTIADDR) +#define IMR_MULTIADDR imr_multiaddr +#endif /* ! defined (IMR_MULTIADDR) */ + + +ACE_RCSID (QoS, + SOCK_Dgram_Mcast_QoS, + "$Id$") + +ACE_BEGIN_VERSIONED_NAMESPACE_DECL + +ACE_ALLOC_HOOK_DEFINE(ACE_SOCK_Dgram_Mcast_QoS) + +// Dummy default constructor... + +ACE_SOCK_Dgram_Mcast_QoS::ACE_SOCK_Dgram_Mcast_QoS (options opts) + : ACE_SOCK_Dgram_Mcast (opts) +{ + ACE_TRACE ("ACE_SOCK_Dgram_Mcast_QoS::ACE_SOCK_Dgram_Mcast_QoS"); +} + +int +ACE_SOCK_Dgram_Mcast_QoS::open (const ACE_INET_Addr &addr, + const ACE_QoS_Params &qos_params, + int protocol_family, + int protocol, + ACE_Protocol_Info *protocolinfo, + ACE_SOCK_GROUP g, + u_long flags, + int reuse_addr) +{ + ACE_TRACE ("ACE_SOCK_Dgram_Mcast_QoS::open"); + + ACE_UNUSED_ARG (qos_params); + + // Only perform the <open> initialization if we haven't been opened + // earlier. + if (this->get_handle () != ACE_INVALID_HANDLE) + return 0; + + ACE_DEBUG ((LM_DEBUG, + "Get Handle Returns Invalid Handle\n")); + + if (ACE_SOCK::open (SOCK_DGRAM, + protocol_family, + protocol, + protocolinfo, + g, + flags, + reuse_addr) == -1) + return -1; + + return this->open_i (addr, 0, reuse_addr); +} + + +int +ACE_SOCK_Dgram_Mcast_QoS::subscribe_ifs (const ACE_INET_Addr &mcast_addr, + const ACE_QoS_Params &qos_params, + const ACE_TCHAR *net_if, + int protocol_family, + int protocol, + int reuse_addr, + ACE_Protocol_Info *protocolinfo) +{ + ACE_TRACE ("ACE_SOCK_Dgram_Mcast_QoS::subscribe_ifs"); +#if defined (ACE_WIN32) + // Windows NT's winsock has trouble with multicast subscribes in the + // presence of multiple network interfaces when the IP address is + // given as INADDR_ANY. It will pick the first interface and only + // accept mcast there. So, to work around this, cycle through all + // of the interfaces known and subscribe to all the non-loopback + // ones. + // + // Note that this only needs to be done on NT, but there's no way to + // tell at this point if the code will be running on NT - only if it + // is compiled for NT-only or for NT/95, and that doesn't really + // help us. It doesn't hurt to do this on Win95, it's just a little + // slower than it normally would be. + // + // NOTE - <ACE_Sock_Connect::get_ip_interfaces> doesn't always get all + // of the interfaces. In particular, it may not get a PPP interface. This + // is a limitation of the way <ACE_Sock_Connect::get_ip_interfaces> works + // with MSVC. The reliable way of getting the interface list is + // available only with MSVC 5. + + if (net_if == 0) + { + ACE_INET_Addr *if_addrs = 0; + size_t if_cnt; + + if (ACE::get_ip_interfaces (if_cnt, if_addrs) != 0) + return -1; + + size_t nr_subscribed = 0; + + if (if_cnt < 2) + { + if (this->subscribe (mcast_addr, + qos_params, + reuse_addr, + ACE_LIB_TEXT ("0.0.0.0"), + protocol_family, + protocol, + protocolinfo) == 0) + ++nr_subscribed; + } + else + // Iterate through all the interfaces, figure out which ones + // offer multicast service, and subscribe to them. + while (if_cnt > 0) + { + --if_cnt; + + // Convert to 0-based for indexing, next loop check. + if (if_addrs[if_cnt].get_ip_address() == INADDR_LOOPBACK) + continue; + if (this->subscribe (mcast_addr, + qos_params, + reuse_addr, + ACE_TEXT_CHAR_TO_TCHAR + (if_addrs[if_cnt].get_host_addr()), + protocol_family, + protocol, + protocolinfo) == 0) + ++nr_subscribed; + } + + delete [] if_addrs; + + if (nr_subscribed == 0) + { + errno = ENODEV; + return -1; + } + else + // 1 indicates a "short-circuit" return. This handles the + // rather bizarre semantics of checking all the interfaces on + // NT. + return 1; + } +#else + ACE_UNUSED_ARG (mcast_addr); + ACE_UNUSED_ARG (qos_params); + ACE_UNUSED_ARG (protocol_family); + ACE_UNUSED_ARG (protocol); + ACE_UNUSED_ARG (reuse_addr); + ACE_UNUSED_ARG (protocolinfo); +#endif /* ACE_WIN32 */ + // Otherwise, do it like everyone else... + + // Create multicast request. + if (this->make_multicast_ifaddr (0, + mcast_addr, + net_if) == -1) + return -1; + else + return 0; +} + +int +ACE_SOCK_Dgram_Mcast_QoS::subscribe (const ACE_INET_Addr &mcast_addr, + const ACE_QoS_Params &qos_params, + int reuse_addr, + const ACE_TCHAR *net_if, + int protocol_family, + int protocol, + ACE_Protocol_Info *protocolinfo, + ACE_SOCK_GROUP g, + u_long flags, + ACE_QoS_Session *qos_session) +{ + ACE_TRACE ("ACE_SOCK_Dgram_Mcast_QoS::subscribe"); + + if (this->open (mcast_addr, + qos_params, + protocol_family, + protocol, + protocolinfo, + g, + flags, + reuse_addr) == -1) + return -1; + + // The following method call only applies to Win32 currently. + int result = this->subscribe_ifs (mcast_addr, + qos_params, + net_if, + protocol_family, + protocol, + reuse_addr, + protocolinfo); + // Check for the "short-circuit" return value of 1 (for NT). + if (result != 0) + return result; + + // Tell network device driver to read datagrams with a + // <mcast_request_if_> IP interface. + else + { + // Check if the mcast_addr passed into this method is the + // same as the QoS session address. + if (qos_session != 0 && mcast_addr == qos_session->dest_addr ()) + { + // Subscribe to the QoS session. + if (this->qos_manager_.join_qos_session (qos_session) == -1) + ACE_ERROR_RETURN ((LM_ERROR, + ACE_LIB_TEXT ("Unable to join QoS Session\n")), + -1); + } + else + { + if (this->close () != 0) + ACE_ERROR ((LM_ERROR, + ACE_LIB_TEXT ("Unable to close socket\n"))); + ACE_ERROR_RETURN ((LM_ERROR, + ACE_LIB_TEXT ("Dest Addr in the QoS Session does") + ACE_LIB_TEXT (" not match the address passed into") + ACE_LIB_TEXT (" subscribe\n")), + -1); + } + + ip_mreq ret_mreq; + this->make_multicast_ifaddr (&ret_mreq, mcast_addr, net_if); + + // XX This is windows stuff only. fredk + if (ACE_OS::join_leaf (this->get_handle (), + reinterpret_cast<const sockaddr *> (&ret_mreq.IMR_MULTIADDR.s_addr), + sizeof ret_mreq.IMR_MULTIADDR.s_addr, + qos_params) == ACE_INVALID_HANDLE + && errno != ENOTSUP) + return -1; + + else + if (qos_params.socket_qos () != 0 && qos_session != 0) + qos_session->qos (*(qos_params.socket_qos ())); + + return 0; + } +} + +ACE_END_VERSIONED_NAMESPACE_DECL diff --git a/ACE/ace/QoS/SOCK_Dgram_Mcast_QoS.h b/ACE/ace/QoS/SOCK_Dgram_Mcast_QoS.h new file mode 100644 index 00000000000..032bbe22f11 --- /dev/null +++ b/ACE/ace/QoS/SOCK_Dgram_Mcast_QoS.h @@ -0,0 +1,142 @@ +// -*- C++ -*- + +//============================================================================= +/** + * @file SOCK_Dgram_Mcast_QoS.h + * + * $Id$ + * + * @author Vishal Kachroo <vishal@cs.wustl.edu> + */ +//============================================================================= + + +#ifndef ACE_SOCK_DGRAM_MCAST_QOS_H +#define ACE_SOCK_DGRAM_MCAST_QOS_H +#include /**/ "ace/pre.h" + +#include "ace/SOCK_Dgram_Mcast.h" +#include "QoS_Manager.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +ACE_BEGIN_VERSIONED_NAMESPACE_DECL + +/** + * @class ACE_SOCK_Dgram_Mcast_QoS + * + * @brief Defines the member functions for the ACE QoS enabled socket + * wrapper for UDP/IP multicast. + */ +class ACE_QoS_Export ACE_SOCK_Dgram_Mcast_QoS : public ACE_SOCK_Dgram_Mcast +{ + +public: + // = Initialization routines. + /// Ctor, has same defaults as ACE_SOCK_Dgram_Mcast + ACE_SOCK_Dgram_Mcast_QoS (options opts = DEFOPTS); + + // Note that there is no public <open> method. Therefore, this + // class cannot be used unless you <subscribe> to a multicast group. + // If you just want to send (and not listen) to a multicast group, + // use <ACE_SOCK_Dgram> or <ACE_SOCK_CODgram> instead. + + /// Default dtor. + ~ACE_SOCK_Dgram_Mcast_QoS (void); + + // = Multicast group management routines. + /** + * This is a QoS-enabled method for joining a multicast group, which + * passes <qos_params> via <ACE_OS::join_leaf>. The network + * interface device driver is instructed to accept datagrams with + * <mcast_addr> multicast addresses. If the socket has already been + * opened, <subscribe> closes the socket and opens a new socket + * bound to the <mcast_addr>. The session object specifies the QoS + * session that the socket wants to subscribe to. A socket may + * subscribe to multiple QoS sessions by calling this method multiple + * times with different session objects. + * + * The <net_if> interface is hardware specific, e.g., use "netstat + * -i" to find whether your interface is, such as "le0" or something + * else. If net_if == 0, <subscribe> uses the default mcast + * interface. Returns: -1 if the call fails. + * + * Note that some platforms, such as pSoS, support only number, not + * names, for network interfaces. For these platforms, just give + * these numbers in alphanumeric form and <subscribe> will convert + * them into numbers via <ACE_OS::atoi>. + */ + int subscribe (const ACE_INET_Addr &mcast_addr, + const ACE_QoS_Params &qos_params, + int reuse_addr = 1, + const ACE_TCHAR *net_if = 0, + int protocol_family = PF_INET, + int protocol = 0, + ACE_Protocol_Info *protocolinfo = 0, + ACE_SOCK_GROUP g = 0, + u_long flags = 0, + ACE_QoS_Session *qos_session = 0); + + // = Data transfer routines. + + /// Send <buffer_count> worth of <buffers> to <addr> using overlapped + /// I/O (uses <WSASentTo>). Returns 0 on success. + ssize_t send (const iovec buffers[], + int buffer_count, + size_t &number_of_bytes_sent, + int flags, + const ACE_Addr &addr, + ACE_OVERLAPPED *overlapped, + ACE_OVERLAPPED_COMPLETION_FUNC func) const; + + /// Send an <n> byte <buf> to the datagram socket (uses <WSASentTo>). + ssize_t send (const void *buf, + size_t n, + const ACE_Addr &addr, + int flags, + ACE_OVERLAPPED *overlapped, + ACE_OVERLAPPED_COMPLETION_FUNC func) const; + + /// Returns the QoS manager for this socket. + ACE_QoS_Manager qos_manager (void); + + /// Declare the dynamic allocation hooks. + ACE_ALLOC_HOOK_DECLARE; + + int open (const ACE_INET_Addr &addr, + const ACE_QoS_Params &qos_params, + int protocol_family = PF_INET, + int protocol = 0, + ACE_Protocol_Info *protocolinfo = 0, + ACE_SOCK_GROUP g = 0, + u_long flags = 0, + int reuse_addr = 0); + +private: + // = Disable public <open> method to ensure class used properly. + + + /// Subscribe to the multicast interface using QoS-enabled semantics. + int subscribe_ifs (const ACE_INET_Addr &mcast_addr, + const ACE_QoS_Params &qos_params, + const ACE_TCHAR *net_if, + int protocol_family, + int protocol, + int reuse_addr, + ACE_Protocol_Info *protocolinfo); + + /// Manages the QoS sessions that this socket subscribes to. + ACE_QoS_Manager qos_manager_; + +}; + +ACE_END_VERSIONED_NAMESPACE_DECL + +#if defined (__ACE_INLINE__) +#include "SOCK_Dgram_Mcast_QoS.i" +#endif /* __ACE_INLINE__ */ + +#include /**/ "ace/post.h" +#endif /* ACE_SOCK_DGRAM_MCAST_QOS_H */ diff --git a/ACE/ace/QoS/SOCK_Dgram_Mcast_QoS.i b/ACE/ace/QoS/SOCK_Dgram_Mcast_QoS.i new file mode 100644 index 00000000000..9e2347669c5 --- /dev/null +++ b/ACE/ace/QoS/SOCK_Dgram_Mcast_QoS.i @@ -0,0 +1,57 @@ +// -*- C++ -*- +// +// $Id$ + +ACE_BEGIN_VERSIONED_NAMESPACE_DECL + +ACE_INLINE +ACE_SOCK_Dgram_Mcast_QoS::~ACE_SOCK_Dgram_Mcast_QoS (void) +{ +} + +ACE_INLINE ssize_t +ACE_SOCK_Dgram_Mcast_QoS::send (const iovec buffers[], + int buffer_count, + size_t &number_of_bytes_sent, + int flags, + const ACE_Addr &addr, + ACE_OVERLAPPED *overlapped, + ACE_OVERLAPPED_COMPLETION_FUNC func) const +{ + ACE_TRACE ("ACE_SOCK_Dgram_Mcast_QoS::send"); + + return ACE_SOCK_Dgram::send (buffers, + buffer_count, + number_of_bytes_sent, + flags, + addr, + overlapped, + func); + +} + +ACE_INLINE ssize_t +ACE_SOCK_Dgram_Mcast_QoS::send (const void *buf, + size_t n, + const ACE_Addr &addr, + int flags, + ACE_OVERLAPPED *overlapped, + ACE_OVERLAPPED_COMPLETION_FUNC func) const +{ + ACE_TRACE ("ACE_SOCK_Dgram_Mcast_QoS::send"); + + return ACE_SOCK_Dgram::send (buf, + n, + addr, + flags, + overlapped, + func); +} + +ACE_INLINE ACE_QoS_Manager +ACE_SOCK_Dgram_Mcast_QoS::qos_manager (void) +{ + return this->qos_manager_; +} + +ACE_END_VERSIONED_NAMESPACE_DECL diff --git a/ACE/ace/QoS/qos.mpc b/ACE/ace/QoS/qos.mpc new file mode 100644 index 00000000000..cf50f96b557 --- /dev/null +++ b/ACE/ace/QoS/qos.mpc @@ -0,0 +1,16 @@ +// -*- MPC -*- +// $Id$ + +project(QoS) : acelib, core { + requires += qos + sharedname = ACE_QoS + dynamicflags = ACE_QoS_BUILD_DLL + + specific(borland, bmake, nmake, em3, vc6, vc7, vc71, vc8) { + macros += ACE_HAS_WINSOCK2_GQOS + } + + pkgconfig_files { + ACE_QoS.pc.in + } +} |