ns-3 meeting notes, April 12-13, 2007 Attendees: Raj Bhattarchjea, Craig Dowell, Tom Henderson, Mathieu Lacage, George Riley 1. Summary The core ns-3 development team met at Georgia Tech for two days to progress the core software architecture for ns-3. The team made significant conceptual progress on a number of system issues including configuration of the simulator, interface-based replacable component system, and a system-wide memory management policy. The team will focus on proof-of-concept of the resulting agreements by the end of April, and additional functionality for a new code release at the end of May. As an object-based system, it was observed that the project needed a clear architecture for the following aspects: i) Configuration ii) Object creation iii) Object genericity (reusable code via replaceable components) iv) Object destruction (memory management) The meeting discussion focused on the above four topics. 2. Configuration The current ns-3 code does not have a systematic way for configuring defaults for member variables or class substitution. In ns-2, this is accomplished with ns-default.tcl, for example. In other simulators, there are often static global variables and they can be sometimes hooked into command-line argument passing facility. The meeting continued some mail discussion of how to do this in ns-3. The goal expressed were: - specify default class types for virtual constructors - allow overridding of default values for class member variables - do both of the above in a localized manner (e.g., with a simple "Bind ()" function like in the ns-2 C++/OTcl code) - allow it to tie into the command-line argument parsing facility Mathieu shared some prototype code based on a global "database" (list) of default values that has the following properties: i) contains a "Bind" function whose two arguments are of type std::string. This Bind function can parse the input strings and assign corresponding values to class instances of type DefaultValueBase. There are a number of subclasses of this base class to handle multiple types of user value types: - BooleanDefaultValue: one "bool" variable - IntegerDefaultValue: any variable of type basic integer - EnumStringDefaultValue : any variable made of an enumeration of distinct string values. - EnumDefaultValue: any variable which is a C++ enum. ii) contains a command-line parsing library which allows users to add their own values but also handles by default all the variables used by Bind. So, one can set with the command-line every variable which is exported to Bind. The group agreed that this was a sensible approach and Mathieu sent Raj some initial code to consider integrating into ns-3-dev. 3. System architecture for replaceable components This topic covered the aspects of object creation, genericity, and destruction. 3.1 Background The current ns-3 codebase includes the fundamental objects of a Node, NetDevice, and Channel. There is not a systematic way for creating such objects (creation); the current code shows a mix of the Prototype design pattern (create a prototype object and clone it via a deep copy) and use of operator new. Another competing approach has been the explicit factory pattern. Object genericity is a problem that is seen in many simulators including ns-2. The problem is that users want to reuse common code constructs but substitute components. An example is someone who wants to substitute a different TCP or Queue implementation. The typical approach to this has been the use of polymorphic classes with base class pointers; that is, the use of a Queue pointer to point to a subclass (e.g., RED) implementation. A problem with this approach is that if the interface to the object changes via subclassing, either the client code has to change or else the base class interface has to be extended. Sometimes the base class interface cannot be extended in a way that makes sense for all subclasses, and the base class tends to depend on lots of subclasses and must be recompiled; this has been called "base class fragility". A third problem we discussed is the current lack of system-wide policy for memory management, ensuring that simulations do not leak, while having clear policies of object destruction for users and developers. 3.2 COM-like system A system for replaceable components called the Component Object Model (COM) has been in wide use in the commercial world. COM provides a component-oriented approach to programming. COM has been used for large scale C++ simulators as well, such as the Athena simulator. More details can be found at Wikipedia, among other places. The following aspects of COM are applicable to the problems that ns-3 has been facing: - encapsulation (interface-oriented programming) allows for separation of interface and implementation - system-wide (unique) class and instance IDs that allow for class type information to be passed as an object in the system and used at run-time to create the right objects - component manager for object creation based on factories - system-wide memory management policy and implementation based on reference counting - aggregation of multiple interfaces to a single implementation at runtime Craig Dowell provided an overview of his port of the ns-3-dev code to a COM-like system. He walked through a sample program that showed how interface aggregation, run-time loading of libraries, and separation of interface and implementation would work. The group felt that this COM-like approach would indeed solve many of the system wide issues in flux in the simulator. There was concern that the syntax, programming concepts, and verbosity of the implementation might present a challenge to use of the system. On the other hand, COM is a well-established, well-documented programming system, and it was observed that the low-level COM aspects could be masked or simplified for users of higher-level code. 3.3 Alternative system Mathieu Lacage and George Riley both observed that providing a query interface was the main motivation for exploration of the COM space, and that perhaps only that concept might be borrowed from COM, with the caveat that other issues (such as memory management) need to be separately dealt with. The group sketched out an alternate design focusing on a type-safe query interface, a factory based approach for object construction, and a memory management policy largely based on the policy of "if you new or factory-create an object, you either delete it or you explicitly delegate ownership to another object. The resultant design bore some similarity to COM concepts, including a queryable interface, a separation of interface from implementation (including a base Interface class analogous to the IUnknown class), a base QueriableInterface object analogous to per-object component manager, and a templated object factory. The memory management was different because the concept of reference counting was found to be challenged by the lack of symmetry between object implementations and their underlying objects (unlike in COM). Another key difference was the lack of a COM-like global component manager. The group then explored the implications of general topology code and found that it was basically built similarly regardless of the design pattern. It was observed that we might be at risk of reinventing COM once we were done with the alternate design. It was also observed that COM-like class IDs might help with the topologies (to allow class types to be passed as objects into the topology code, for later construction). There was some concern expressed that the alternative system was not fully fleshed out system-wide to the extent that (other) COM systems have been, and that by picking and choosing some COM features selectively, the soundness of the end-to-end system might be compromised downstream in an unforseen way. This introduced perhaps slightly more risk to this approach. 3.4 Outcome It was unclear to the group whether one or the other approach offered a stronger solution, with the COM system potentially providing a steeper learning curve for new users/developers (i.e., perhaps being more heavyweight than strictly needed) or else more work to simplify it at higher programming layers, but with the alternative system evolving in many aspects towards a COM-lite with different naming. However, the alternative system represented less of a departure from the current system design. The group agreed that COM would be a solution to the ns-3 design problem, although there was not strong agreement or disagreement with the COM-based approach (i.e., there was not a clear cut or strong argument for or against). Since the alternative being sketched out seemed to be arriving back at a COM-like design in many aspects, Tom recommended that the project try to more fully prototype the COM approach and go forward with it unless the syntax/verbosity was found to be too cumbersome. Craig volunteered to document and prototype some basic use cases and to start a more active progression of the system towards a COM-based framework. Mathieu agreed to assist by looking at migrating the current code base and simplifying the design where possible. The group agreed to review the use cases and implementation by the end of next week. The use cases were: - subclass existing protocol - add new protocol - add new node type - add new object to node - aggregate interfaces on objects 4. Other topics 4.1 Topologies The group looked at various ways to implement topology helper functions. A case study was how to define a point to point link with two different a Queue types within the current AddDuplexLink topology function. (this is not currently a capability of the topology object). Some options were: - use inversion of control to allow pieces of the topology to be subclassed, and allow client to subclass the part of code that dealt with the NetDevice queue - pass the queue type as an argument (class ID or factory) to the topology - build the topology and later get a queue handle to change the value - use the configuration system and provide a callout to reset (rebind) the queue configuration Craig Dowell is going to consider developing some of these approaches further in the next month or two. 4.2 Build system Gustavo Carneiro suggested that the project try out the WAF build system, since WAF can be distributed self-contained and may have advantages in user interface and speed. Mathieu agreed to follow up with Gustavo on this point. 4.3 Python bindings Gustavo suggested Py++ to generate Boost::Python code to help with C++/Python bindings. Mathieu reported that Boost::Python code was potentially difficult to maintain. Craig volunteered to sketch a prototype design and to follow-up with Gustavo. 4.4 Signals Gustavo suggested an ns-3-signals module to allow for a chain of callbacks to be added by any code, for application of node position location and packet traversal hooks. Mathieu agreed to follow up with Gustavo but there was not yet consensus that this needed to be an added feature at this time. 5. Revised roadmap - end of April: new architecture document and prototype code release - end of May: new code release with focus on static routing, TCP, and 802.11.