Academia.eduAcademia.edu

Integrating real world applications into OMNeT

2000

The discrete event simulator OMNeT++ is nowadays used for network simulations in the majority of cases. Unfortu- nately, it is not possible to easily integrate real world net- working applications into simulation models. This, however, would enable less complex and more efficient development and evaluation of real applications, especially of those that work in a distributed manner, in comparison to

Universität Karlsruhe (TH) Institut für Telematik T ELE M ATICS T ECHNICAL R EPORTS Integrating real world applications into OMNeT++ Christoph P. Mayer, Thomas Gamer {mayer,gamer}@tm.uka.de February, 27th 2008 TM-2008-2 ISSN 1613-849X http://doc.tm.uka.de/tr/ Institute of Telematics, University of Karlsruhe Zirkel 2, D-76128 Karlsruhe, Germany Integrating real world applications into OMNeT++ Christoph P. Mayer Thomas Gamer Institut für Telematik Universität Karlsruhe (TH) Germany Institut für Telematik Universität Karlsruhe (TH) Germany [email protected] [email protected] ABSTRACT The discrete event simulator OMNeT++ is nowadays used for network simulations in the majority of cases. Unfortunately, it is not possible to easily integrate real world networking applications into simulation models. This, however, would enable less complex and more efficient development and evaluation of real applications, especially of those that work in a distributed manner, in comparison to an evaluation in real world networks. We therefore present in this paper approaches to overcome the shortcoming of real world application simulation in OMNeT++ and discuss problems and solutions that arise in this context. Our preferred approach for integrating real applications into simulation models is based on an encapsulation of real applications as shared libraries that can be dynamically loaded by OMNeT++ at runtime. Categories and Subject Descriptors I.6.3 [Simulation and Modeling]: Applications General Terms Application simulation Keywords OMNeT++ integration, hardware-in-the-loop, real world simulation, application model 1. INTRODUCTION When it comes to network simulation researchers often rely on the OMNeT++ simulation environment [13]. Due to its powerful discrete event simulation engine and lots of available network protocols it is very easy to simulate and evaluate networking protocols and applications using e. g. arbitrarily large and complex network topologies [5]. The integration of existing real world applications into simulators like OMNeT++ notably simplifies evaluation and further development of these applications since topologies, traffic patterns, and other parameters can be changed easily within a simulator. This is even more important in case of distributed applications, e. g. distributed anomaly-based attack detection [6]. The detection systems in this example are sparsely distributed on nodes within the network. Specific information, e. g. statistical traffic distributions which are locally measured, is communicated between various instances in order to improve detection of adverse events like distributed denial-of-service attacks or worm propagations. Thus, such attacks can be detected efficiently and as early as possible. The behavior of such an application in large networks and under varying conditions may be more easily evaluated using a network simulator than a real network. Thus, an easy integration of real world applications into simulators should be possible without the need for redesigning or re-implementing them for the OMNeT++ environment. If networking protocols are implemented for usage with OMNeT++ protocol logic typically is integrated into so called simple modules using C++ code. By combining multiple simple modules into a compound module it is possible to implement more complex application logic, too. Thus, additional client and server applications can be integrated into the simulation model, e. g. in order to generate realistic background traffic. Integrating already existing real world applications into OMNeT++ simulations, however, is not as easy as implementing new applications specifically for OMNeT++. Problems arise, for example, if threads are used in real world applications. In addition to the complexity of actually integrating real world applications, serious simulation runtime problems may arise. These could result in time distortion, CPU scheduling issues, and process or symbol space problems. Previous work mainly focused on the integration of real world TCP/IP network stacks into OMNeT++ or other network simulators [2, 8]. The overlay network simulation framework OverSim [1] uses socket connections to connect external applications to the simulation model. We are, however, not aware of further work that details challenges and solutions of easily integrating existing real world applications into OMNeT++. The rest of the paper is organized as follows: Section 2 further motivates the need for integrating real world applications into OMNeT++. Different approaches for an integration of such applications – socket connection, source code integration, and shared library integration – are discussed and compared in section 3. We consider usage of shared libraries the best method for integrating real world applications into a simulation model. Therefore, this method is presented in more detail in section 4. Additionally, necessary adjustments that have to be made on applications as well as OMNeT++ are explained in detail. Section 5, then, details the problems that arise at compile time and runtime and describes solutions. Finally, section 6 gives a short summary and an outlook on future work. 2. WHY INTEGRATE? Evaluating real world applications – especially distributed applications – based on real networks is a challenging task. Keeping the previously described example of distributed anomaly-based attack detection in mind, a real network must achieve several requirements in order to be usable for evaluation: 1. A large network is necessary in order to get meaningful evaluation results. 2. Control over all nodes in the network is needed, e. g. to deploy the attack detection system or to execute a distributed denial-of-service attack. 3. A realistic network environment including e. g. a realistic topology and realistic background traffic is needed. These requirements apply to most distributed applications. Creating a large testbed for evaluation, however, results in high efforts for deploying necessary applications – attack detection as well as attack execution in our example – on different hosts in the network. Furthermore, building up such a large network – maybe consisting of hundreds or thousands of nodes – involves high costs for hardware. The need for different network topologies and varying network conditions additionally increases the expenses and administrative efforts. Furthermore, clients – and possibly human users – and servers have to be deployed in the network in order to create realistic background traffic. Another possibility is to use an existing large network for evaluation of real world applications, e. g. PlanetLab [9] which provides control over the nodes. This ensure that no additional hardware has to be deployed and thus, reduces costs significantly. If such a network, however, is used it must be ensured that the evaluation does not disrupt normal network operation and that failure or malfunction of the network does not bias evaluation results. Therefore, such an operational network can not be used in case of an attack detection system since attacks would disrupt normal network operation but must be generated explicitly in order to get meaningful evaluation results. All of the mentioned requirements can be easily fulfilled when deploying existing real world applications in a simulation environment like OMNeT++. Creating arbitrarily large network topologies is provided by topology generators like ReaSE [5]. They furthermore allow creation of varying network topologies. Control over the network is always given when running simulations, thus the second requirement does not impose a problem, too. In order to achieve a realistic environment self-similar network traffic [16] must be generated. Additionally, malicious nodes have to be integrated into the simulaton, e. g. based on the Tribe Flood Network [4] DDoS tool as shown in [5], which execute DDoS attacks. 3. INTEGRATION METHODS There are different approaches that can be used in order to integrate real world applications into OMNeT++ simulation models. In this section we will describe three techniques for such an integration: socket connection, source code integration, and using shared libraries. Additionally, we will evaluate the complexity and applicability of each suggested approach. The socket connection (see section 3.1) is e. g. used by the OverSim framework [1] in order to connect real world applications like SIP clients to the simulation model. Direct source code integration (see section 3.2) is the default way to integrate protocol and application logic into OMNeT++ [15]. Using dynamically loadable shared libraries (see section 3.3) to outsource application code is partially documented in [14, 15]. 3.1 Socket connection Connecting a real world application to the simulation using a socket has been implemented e. g. by OverSim and is documented in the OMNeT++ sockets sample [13]. It requires a simple module acting as proxy within OMNeT++. This proxy maintains a socket connection with the real world application. This method often does not imply any source code changes on the application and thus, is very easy to implement. Socket connections can be used if an application has no need for lower layer protocols but just needs data from application layer. Anyway it is also possible to tunnel the whole network packet including all lower layers over the socket. In most cases this requires source code adaptations on the application to support tunneling of network packets. This means that it is not possible to, e. g., transparently connect an intrusion detection system (IDS) that uses a Libpcap [7] interface for packet capture to an OMNeT++ simulation using a socket connection. Despite the fact that the integration using a socket connection is quite easy to perform, it suffers from the following problems: 1. CPU scheduling issues 2. Synchronization issues Since an OMNeT++ simulation typically runs as fast as possible it consumes as much CPU time as possible. This results in the first problem: The external application may not get enough CPU time for its own operations and therefore, does not run smoothly (1). In order to avoid this issue higher process priorities may be assigned to the real world application. This, however, may result in problems for OMNeT++ if traffic sent by the application can not be processed fast enough and thus, causes the socket connection to break. OMNeT++, on the one hand, performs a time discrete simulation in its own time domain: the simulation time. An application that is connected to a simulation using a socket connection, on the other hand, runs in its own time domain: the wall clock time which runs in real time. This causes time distortion between simulation and real world application that leads to inaccurate or even false simulation results (2). The solution that is implemented by OMNeT++ and OverSim is to use a special simulation scheduler that slows down the simulation to real time. This causes both the simulation and the external application to run in the same time domain, i. e. the wall clock time. This approach, however, results in further problems that may bias the simulation results. First of all, the approach to slow down the simulation is only possible if the simulation is able to run faster than real time. Depending on the number of modules used in the simulation and on generated traffic between the hosts in the simulated network this requirement must not taken for granted in all cases. Secondly, the external application is still not running in a time discrete manner and therefore, may not be synchronized with the simulation properly. The last drawback of slowing down the simulation is the extended simulation time: Executing a simulation that normally runs ten times faster than real time and provides ten hours of simulation time will end up running for ten hours real time instead of just one if socket connections are used for the integration. 3.2 Source code integration Integrating source code directly into a simulation is the default approach when evaluating protocols using OMNeT++. This involves writing simple modules in C++ and compiling them using the OMNeT++ build environment. This approach enables easy development of protocols and small applications. Since all code is implemented directly into OMNeT++ and scheduled by OMNeT++ no time distortion can occur. The direct source code integration technique suffers from the following problems that make it difficult to integrate existing real world applications into OMNeT++: 1. Real world applications consist of multiple source files and contain dependencies that have to be integrated into the OMNeT++ build environment. 2. The build environment for the real world application has to be reconstructed in the OMNeT++ build environment. This includes compiler and linker flags. 3. External application dependencies have to be integrated into the OMNeT++ build environment. 4. Features like timers and threads that are used in real world applications cannot be seamlessly integrated into OMNeT++. Problems (1) to (3) concern the software build environment: Reconstructing the application’s build environment within the OMNeT++ build environment involves integrating all source files and applying all compile and link time switches that are needed by the real world application. This can result in incompatibilities and unstable code: Compile time switches for character set, exception handling and threading, for example, can result in incompatibilities, break the build or produce runtime failures. Adding external dependencies into the OMNeT++ build environment (3) can further complicate the build or even make it impossible due to link time incompatibilities between the external dependencies and OMNeT++. As OMNeT++ pursues a discrete simulation model the use of threading (4) causes problems (see section 5.1). This is a general problem that is not only related to the approach of source code integration. Furthermore, timer mechanisms must be considered: Total timer functionality has to be emulated by using OMNeT++ self messages (see section 5.2). 3.3 Shared library integration Another possibility to integrate applications into OMNeT++ is to include binary code. We call this method shared library integration. It is quite similar to the integration of source code and involves most of its integration steps. As huge advantage the Shared library integration avoids the most challenging problem: project build management. Whereas the source code integration requires major adaptations to the OMNeT++ build environment the approach of using shared libraries keeps the build environment for the real world application and OMNeT++ separated in a sound way. Compile and link time switches as well as external dependencies of the application can be retained. This enables different compile and link time settings for OMNeT++ and the real world application. In the majority of cases a real world application uses compile and link settings that can not be changed without breaking the application. Thus the Shared library integration enables the application to preserve its specific settings and integrate into OMNeT++. Changing the output type of an application to shared library involves only small adaptations to the application build environment that can be implemented e. g. using command line flags for the GNU make build system [12]. This avoids costly maintenance of multiple project build environments for the application. Only one application build environment exists that can be used to build both the native application and the OMNeT++ compatible shared library. 3.4 Conclusions The solution using shared libraries includes all advantages of the direct source code integration but heavily simplifies the problems regarding management of both OMNeT++ and real application build environments. The solution based on socket connections, is the easiest one but shows synchronization problems that may bias simulation results and additionally, does only work if simulation speed is faster than real time. We hence consider the shared library approach the best choice for the integration of real world applications into OMNeT++. The rest of the paper will focus on this integration technique. Section 4 will explain in more detail how to integrate real world applications using shared libraries. Section 5 finally focuses on emerging problems and gives solutions. 4. INTEGRATION STEPS This section focuses on the integration of real world applications using the shared library approach introduced in section 3.3. Section 4.1 will detail on the required adaptations on real world application and OMNeT++. The necessary OMNeT++ NED environment will be explained in section 4.2. 4.1 Preparing the application The first step of preparing the real world application for integration into OMNeT++ involves creating a simple module using the base OMNeT++ class cSimpleModule. The functionality of the application’s regular main method has to be encapsulated into this simple module. The actual code of the main method will be split into the simple modules constructor and destructor as well as initialize and finish methods. An initialization based on multiple stages can be implemented using the simple module’s numInitStages method. Application Simple module Application logic PayloadPacket TcpPacket IpPacket Frame Network abstraction and conversion cMessage As next steo the network abstraction has to be built. Applications like intrusion detection systems or network analyzers parse all protocol layers of a packet. Most often such applications provide their own parsers to access protocol contents. These parse the binary network packet and represent the contents in a structured and easily accessible way. The intrusion detection systems Bro [11] and Snort [10], for example, employ such structured protocol parsers. OMNeT++ uses protocol classes that are transmitted within the simulation model as objects in the simulation process space. The OMNeT++/INET protocol classes, however, are different from real binary network data. It is thus not possible to use the OMNeT++ protocol objects directly for protocol parsing based on RFC-conform protocol parsers. Figure 1 compares a binary IP packet format which is RFCconform and a binary representation of an IP packet used by OMNeT++/INET. The binary representation for the OMNeT++/INET IP packet was derived from the IPDatagram message definition in the IPDatagram.msg file. It can be easily seen that the binary formats are different and that normal protocol parsers can not be used for both formats. Thus, it is not possible to transparently operate the original protocol parsers of the real world application. Integrating a real world application including the application’s original parsers is possible by using an abstraction layer for the network data. This involves converting the OMNeT++-specific protocol objects into structures that are used inside the application. There exist two different ways to achieve this: 1. Mapping the OMNeT++/INET protocol objects to application-internal protocol structures. 2. Serializing the OMNeT++/INET protocol objects to binary format and enable the application to perform the parsing. Which approach is chosen depends on the fact whether the application provides inbuilt protocol parsers or not. If the encapsulation of the OMNeT++/INET protocol parsers can be mapped to application-internal protocol parsers it is possible to develop a conversion layer that converts the OMNeT++/INET protocol objects into application-specific protocol objects (1). The architecture of such an abstraction layer is shown in figure 2. Care must be taken because OMNeT++/INET defines several constants like ICMP type and code values that are not RFC-conform. IPDatagram TCPSegment OMNeT++ Figure 2: Abstraction layer for OMNeT++/INET protocol representation and application-specific protocol representation. If the first approach can not be applied the serialization functions in OMNeT++/INET can be used to serialize the protocol objects into a binary Pcap [7] structure (2). This way a Pcap interface can be emulated that provides generic access to all network data including all protocol layers for the real world application. This approach can e. g. be used when the real world application does not employ protocol parsers but accesses protocol contents through the use of simple offsets into the binary packet data. The packet delivery model in the application may differ from the event driven approach used in OMNeT++. In an OMNeT++ simulation packets are delivered through a callback function, i. e. in a push-based manner. Network access interfaces like Pcap allow pull-based mechanisms to be used instead. If the application uses a pull-based method to access network packets additional buffers must be implemented to emulate pull-based network packet access in OMNeT++. Already integrated applications that need to communicate with other nodes in the simulation need adaptations, too. This is much easier since no protocol parsers or serializers have to be employed. To enable communication between nodes in the simulation an abstraction is needed that allows an application to transparently communicate with other nodes using e. g. sockets under a native environment and using the OMNeT++/INET facilities when running a simulation. A sound object-oriented design of the real world application makes integration into OMNeT++ rather seamless. The modular architecture allows the exchange of e. g. network access layers for the OMNeT++ environment. This results in a high level of abstraction and enables the actual application functionality to run independently of the underlying network access methods. Badly designed applications may require more integration efforts but can be integrated into OMNeT++ nonetheless using the presented method. 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 Version IHL TOS Flags Identification TTL 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 Total length Protocol Version Fragment offset IHL Source IP address Header checksum Destination IP address Source IP address Protocol Identification (1) TTL Destination IP address Identification (2) MD FF Fragment offset (2) Fragment offset (1) Diffserv Figure 1: RFC-conform binary IP format (left) and OMNeT++/INET-based IP format (right) Table 1: Flags for shared library building Type Compiler Flag -fPIC Linker -shared Linker -rdynamic Linker -o Meaning Generate position-independent code (PIC) that is needed for dynamic linking. Produce a shared object that can be used to link a shared library. Instructs the linker to add all symbols to the dynamic symbol table. This is needed if the application dynamically loads further shared libraries which use functionality from the application shared library. Specify the output filename for the shared library, e. g. libmyapp.so After adapting the source code using the simple module and building an appropriate network abstraction the application has to be built as a shared library. This applies only to the main executable component. Further shared libraries that are used by the application executable do not need to be changed. Changing the output type from executable to shared library needs adjustment of compiler and linker flags. Table 1 gives an overview of useful flags that may be necessary for compiling and linking a shared library with the GNU g++ compiler under Linux. Using a build system like GNU make [12] enables command line flags that can be used to select the runtime environment (e. g. native Linux or OMNeT++) and thus easily adapt the compiler and linker flags. 4.2 OMNeT++ NED environment After the application has been prepared as shown in section 4.1 the OMNeT++ environment has to be built. The NED and configuration files for the OMNeT++ simulation are quite similar to the default approach. First of all we adapt the omnetpp.ini file. It contains a [General] section which will be extended to command OMNeT++ load the application shared library that was built in section 4.1. In order to achieve this we add the following entry to the omnetpp.ini file: [General] ... load-libs="libmyapp" ... This instructs OMNeT++ to dynamically load the file libmyapp.so at startup. This way the simple module that was defined in section 4.1 is now available for instantiation. It has to be ensured that the shared library libmyapp.so resides in a location where it can be found for dynamic loading. The NED files that actually use the simple module look as if the source code was directly embedded, i. e. there is no difference to the default way of writing NED files. 5. CHALLENGES The procedure described in section 4 enables the integrated application to startup and run within the OMNeT++ simulation. Nonetheless only simple applications will run without problems at this point. Most often problems will emerge that require special handling. These problems will be explained in the next sections and appropriate solutions are presented. The problems and solutions discussed in this sections also partly apply to source code integration (see section 3.2) and socket connection integration (see section 3.1) technique. 5.1 Threads Threading is a direct contradiction to the discrete simulation approach followed by OMNeT++. A simulation performed by OMNeT++ is not multi-threaded and thus, implements no kind of concurrency. In real world applications threads are commonly used and receive great support by upcoming multicore processors. This results in a huge amount of software being written based on threads. In case a multi-threaded application has been integrated as previously described one or both of the following problems may occur: 1. Application threads don’t receive enough CPU time from the operating system scheduler and thus don’t run smoothly. 2. Access violations occur when a thread tries to access the OMNeT++ simulation environment. Threads that only perform little work and then finish are often not affected by too little CPU time. Such threads will run correctly and do not need any adaptation in regard to (1). Threads that e. g. wait for processing items of a queue possibly will run too slow since the OMNeT++ environment consumes all CPU resources. To resolve problem (1) threads have to be discretized and thus source code changes need to be applied. The following example will make this more clear: Consider a thread that waits for items in a queue to appear. Then it performs some work on all items until the queue is emptied. Discretizing this thread can be done by periodically calling a method that processes all items in the queue. The calling of this method can be implemented in the OMNeT++ handleMessage method of the application’s simple module. This way the thread itself is discretized and processing is triggered by OMNeT++ directly. As processing time in a simple module is not added to the simulation time no time distortion can occur. Another way to solve the CPU scheduling problem (1) is to adjust thread priorities. In case of shared library integration OMNeT++ and all application instances are treated as a single process. This means that it is not possible in this case to adjust process priorities. It is therefore necessary to adjust thread priorities. Adapting thread priorities, however, needs deep knowledge of application code and behavior as well as interaction of threads. The actual thread priority adaptations have to be performed based on the application source code. The OMNeT++ simulation environment is at any time aware of the currently active code. Therefore a context pointer is used that can be manipulated using the class cContextSwitcher. A thread in the real world application – which does not necessitate discretization and thus has not been discretized – that accesses OMNeT++ functionality, e. g. through the application’s simple module object, is not marked as active code because it has not been scheduled by OMNeT++ but by its own thread. Therefore, problems occur that result in access violations (2) because OMNeT++ is not aware of the active code. To circumvent this problem the macros Enter_Method and Enter_Method_Silent can be used before accessing simulation objects like the applications simple module. They use the class cContextSwitcher mentioned before to adjust the context pointer. This way OMNeT++ is aware of the currently active code and can handle message ownership and event scheduling correctly. 5.2 Timing issues Applications often depend on time-based information, e. g. for the following functionality: 1. Requests for the current time. 2. Request that the current thread should sleep for a defined time interval. 3. Use of timers that periodically execute a defined callback function. Each of the three features rely on time-based information. Typically, applications, on the one hand, are executed in the wall clock time domain. An OMNeT++ simulation model, on the other hand, is executed in its own time domain: the simulation time. Hence, occurrence of any feature within an application needs adaptation to run correctly in the simulation time domain. The simulation time can be requested by a simple module using the simTime method. This method returns the simulation time as floating point number with double precision in seconds. Using preprocessor macros the request for the current time (1) can be easily encapsulated and transparently used by the application: #ifdef OMNET_SIMULATION #define CUR_TIME (static_cast<unsigned long> \ (cSimpleModule::simTime()* \ 1000.0)) #else #define CUR_TIME (static_cast<unsigned long> \ (((double)clock())/ \ ((double)CLOCKS_PER_SEC))*1000.0) #endif This way the application is able to perform time requests transparently within an OMNeT++ simulation as well as a normal runtime environment like Linux. Sleeping the current thread (2) for a defined amount of time must be done in respect to the simulation time domain. As the simulation time is not increasing uniformly, sleeping can not be done using a multiplier in respect to the wall clock time domain. Thus, sleeping mechanisms must be implemented using OMNeT++ specific features. OMNeT++ provides the wait method that simulates speeping mechanisms using self-messages and can be used by a simple module. Like the request for the current time the sleeping mechanism can be encapsulated and made compile timedependent. This results in transparent usage of sleeping mechanisms for the application. Timers (3) are implemented in OMNeT++ using self messages. These are messages that are scheduled with a user defined delay and then sent to the module itself. Periodic timers can be implemented by rescheduling incoming self messages. The self message functionality can be used to implement a timer management for the application that can handle multiple timers transparently. The timer management thus is able to handle multiple timers using different identifiers in the OMNeT++ self message. 5.3 Shared libraries and symbol space As soon as the application’s shared library is dynamically loaded by OMNeT++ the runtime environment resolves all pending symbols. This is performed on a process space-wide scope. Problems can occur if the application that was loaded using the shared library in turn loads additional shared libraries (e. g. plugins). If plugins rely on functionality of the base application symbol resolution errors can occur. The reason for this is that when OMNeT++ loads the application’s shared library only symbols are mapped into the sym- Uses func1,func2 Start OMNeT++ OMNeT++/ Load Shared-library INET Insert Real world application e Us Insert Load Shared-library Application plugin e Us Func1 Func2 ... TCPSegment UDPPacket ... Process symbol space Figure 3: Shared library loading by OMNeT++ and by the integrated application. bol space that are currently needed and thus, unresolved. Symbols that are not needed at this moment are discarded and not mapped into the symbol space. A plugin that may get dynamically loaded by the application at a later time may rely on this functionality. Because the functionality has not been mapped into the symbol space at startup loading the plugin will fail. Figure 3 shows an exemplary scenario where OMNeT++ dynamically loads the real world application’s shared library. All symbols that the real world application depends on, e. g. TCPSegment, are resolved and thus, can be used by the real world application. All symbols in the real world application that are currently needed are resolved, too. All symbols that are currently not needed are not inserted into the symbol cache. This results in func1 and func2 not being inserted into the symbol cache. If the application loads a plugin that relies on func1 or func2 this functionality – which resides in the application – is not accessibly by the plugin. during runtime, e. g., when the application loads a plugin that depends on func1 or func2. The nonexistence of C++ namespaces in OMNeT++ can cause further problems that need to be considered. Every class in the real world application is compiled into a symbol. This symbol is mapped into the process space and represents the entry point for the usage of the actual functionality. Two classes having the same name compete against the symbol space entry and will swap one another. This results in the wrong class being instantiated and actually used at runtime. Function calls on the class will result in the wrong memory location being executed and fail with access violation errors. The problem can be resolved by using C++ namespaces in the real world application or taking care that no class name in OMNeT++ and the real world application clash. 5.4 Process space issues dlopen (libfname.c_str(), RTLD_NOW | RTLD_GLOBAL) When deploying several instances of the same application on the same machine using e. g. Linux, every instance resides in its own process space. Under an OMNeT++ simulation multiple instantiations of the same application’s simple module result in the fact that all instances reside in the same process space. This means that using the real world application on several nodes in the simulation network results in all application instances sharing the same process space. Every static variable or object is thus shared between all instances. Therefore, special care is needed if static variables and static objects like singletons are used. This causes all symbols in the application shared library to be mapped into the symbol space when loaded by OMNeT++. This includes symbols that are currently not needed. Thus, symbols that are needed by plugins can be resolved successfully, even at a later point of time. The shared process space, however, can also have positive effects on the simulation performance: Shared memory pools, e. g. by using the Boost Pool Library [3], or the usage of singleton objects result in smaller overall memory usage and less CPU time consumption. This may speed up simulation execution. The solution to this problem is quite easy but requires a change in the OMNeT++ code itself. The OMNeT++ code for loading shared libraries is located in the file loadlib.h at include/platdep/. The method opp_loadlibrary uses the dlopen method to load shared libraries dynamically at runtime. This method call needs to get extended using the RTLD_GLOBAL option. Thus, the resulting function call looks as follows: Based on the changes described above all symbols in our example that are available in the real world application are inserted into the symbol cache and available for later usage by plugins. This means that func1 and func2 are inserted into the symbol cache at the time the shared library of the real world application is loaded. Thus, they are available 6. CONCLUSIONS Integrating real world applications into a simulation environment like OMNeT++ enables an evaluation of their behavior in large simulated networks. Furthermore, it is possible to design and evaluate the behavior of distributed real world Table 2: Advantages and disadvantages of discussed integration techniques. Integration technique Socket connection Source code integration Shared library integration Advantages Applications like servers and clients can be integrated without changes to the application source code. No CPU or time domain issues, thus no bias. Straightforward integration method. Easy to integrate small and simple applications. All advantages of source code integration. Avoids problems of build environment and incompatibilities. applications more easily and cost-efficient than in real networks. We presented several techniques that can be used to integrate existing real world applications into OMNeT++ and discussed their pros and cons. Focusing on the approach to use shared libraries for integration we presented detailed instructions how to realize this solution. Additionally, emerging challenges are explained and solutions are provided. Table 2 gives a concluding overview of advantages and disadvantages of the different integration techniques discussed in this paper. A well designed network application can be integrated into OMNeT++ more easily than badly structured code. Anyway the integration can be time consuming and complex. It would be desirable to have better support by OMNeT++ for the integration of real world applications. Future work should focus on OMNeT++ extensions that can easily deploy existing real world applications without the need for major adaptations on the application side. 7. REFERENCES [1] I. Baumgart, B. Heep, and S. Krause. OverSim: A Flexible Overlay Network Simulation Framework. In Proceedings of 10th IEEE Global Internet Symposium (GI), pages 79–84, May 2007. [2] R. Bless and M. Doll. Integration of the FreeBSD TCP/IP Stack into the discrete event simulator OMNeT++. In Proceedings of the 2004 Winter Simulation Conference, pages 1556–1561, December 2004. [3] S. Cleary. Boost Pool Library. http://www.boost.org/libs/pool, 2000. [4] D. Dittrich. The ”Tribe Flood Network” distributed denial of service attack tool. http://staff.washington.edu/dittrich/misc/tfn.analysis, October 1999. Disadvantages CPU and timing issues make this integration technique unstable, inefficient or even impossible to perform. Need to reconstruct application build environment with OMNeT++. Applications with special compiler and linker settings can not be integrated due to incompatibilities with OMNeT++. Source code adaptations needed. Source code adaptations needed. [5] T. Gamer and M. Scharf. Realistic Simulation Environments for IP-based Networks. In Proceedings of the OMNeT++ Workshop, Marseille, France, March 2008. [6] T. Gamer, M. Scharf, and M. Schöller. Collaborative Anomaly-based Attack Detection. In Proceedings of IWSOS, pages 280–287. Springer, August 2007. [7] V. Jacobson, C. Leres, and S. McCanne. Tcpdump Pcap. http://www.tcpdump.org, 2000. [8] S. Jansen and A. McGregor. Simulation with real world network stacks. In Proceedings of the 2005 Winter Simulation Conference, pages 2454–2463, December 2005. [9] PlanetLab. PlanetLab: An open platform for developing, deploying, and accessing planetary-scale services. http://www.planet-lab.org, 2002. [10] M. Roesch. Snort. http://www.snort.org, 2001. [11] R. Sommer. Bro: An Open Source Network Intrusion Detection System. In Proceedings of the 17. DFN-Arbeitstagung über Kommunikationsnetze, pages 273–288, June 2003. [12] R. M. Stallman and R. McGrath. GNU make. http://www.gnu.org/software/make, 1988. [13] A. Varga. The OMNeT++ Discrete Event Simulation System. In Proceedings of the European Simulation Multiconference, pages 319–324, June 2001. [14] A. Varga. How to extend INET with your own C++ code. http://www.omnetpp.org, June 2005. [15] A. Varga. OMNeT++ Discrete Event Simulation System User Manual, 2005. Version 3.2. [16] W. Willinger, M. S. Taqqu, R. Sherman, and D. V. Wilson. Self-similarity through high-variability: statistical analysis of ethernet LAN traffic at the source level. In Proceedings of ACM SIGCOMM, pages 100–113, February 1995.