The cnet network simulator - event driven programming
Keywords: network simulator simulation protocol undergraduate teaching

### The event driven programming style

cnet employs an event-driven style of programming similar, though not identical, to the data-link layer protocols presented in Tanenbaum [Prentice-Hall,1988]. Execution proceeds when cnet informs protocols that an event of interest has occurred. Protocols are expected to respond to these events.

Events occur when a node reboots, the Application Layer has a message for delivery, the Physical Layer receives a frame on a link, a timer event expires, a debugging button (under Tcl/Tk) is selected, and a node is (politely) shutdown. No event is delivered if a node pauses, crashes or suffers a hardware failure. These last few events only occur in simulations designed to address the higher layers of the OSI model (say, the Session Layer).

NOTE: cnet employs an event-driven style of programming, not an interrupt-driven style. In particular, while an event handler is executing it will not be interrupted by the arrival of another event. In support of this, there are no facilities to specify non-interruptable, high-priority handlers nor to ``wrap'' data structures in semaphores or monitors (you won't need them!).

Event-handling functions must first be registered to receive incoming events with a call to `CNET_set_handler`. Event-handling functions will be later called by cnet with three parameters. The first is the type of event (the reason the handler is being called), one of the `CnetEvent` enumerated values. The second parameter is a unique timer (described later) and the third, some user-specified data.

Each node is initially rebooted by calling its `reboot_node` function. This is the only function that you must provide and is assumed to have the name `reboot_node()` unless overridden with either the -R option or the `rebootnode` node attribute. The purpose of calling `reboot_node` is to give protocols a chance to allocate any necessary dynamic memory, initialize variables, inform cnet in which events protocols are interested, and which handlers that cnet should call when these events occur.

### An example of cnet's event handlers

Consider the following protocol skeleton. Like all cnet protocol files, the standard cnet header file is first included. This contains all definitions and function prototypes necessary for protocols. The `reboot_node` function first informs cnet that when the Application Layer has a message for delivery to another host (because `EV_APPLICATIONREADY` occurs) cnet should call the function `new_message` which reads the new message from the Application Layer to commence the delivery process. The function `frame_arrived` will similarly be called when the `EV_PHYSICALREADY` event occurs.

    #include <cnet.h>

    void new_message(CnetEvent ev, CnetTimer timer, CnetData data)
    {
      ...
      success = CNET_read_application( ... );
      ...
    }

    void frame_arrived(CnetEvent ev, CnetTimer timer, CnetData data)
    {
      ...
      success = CNET_read_physical( ... );
      ...
    }

    void reboot_node(CnetEvent ev, CnetTimer timer, CnetData data)
    {
      ...
      success = CNET_set_handler(EV_APPLICATIONREADY, new_message, 0);
      success = CNET_set_handler(EV_PHYSICALREADY,    frame_arrived, 0);
      ...
    }

A user-defined data value must be initially provided as the third parameter to `CNET_set_handler`. When the handler's event eventually occurs, the same value is passed as the third parameter to the handler. Within more complex protocols, you will typically want to pass an integer or, with care, a pointer, via this third parameter. The user-defined data value for timeout handlers (for `EV_TIMER1..EV_TIMER10`) must also be provided as the third parameter to `CNET_start_timer`.

IMPORTANT:
  Event-handling functions must execute to their completion - they must perform their actions and then simply return. cnet does not employ pre-emptive scheduling - once an event handling function is being executed, it will not be interrupted by the arrival of another event. Event-handling functions are of type `void` - that is, they do not return a value. If event-handling functions do not return, the whole simulation, including all windowing, will block and cnet must be interrupted via the invoking xterm.

### Timers

cnet supports 10 timer event queues providing a call-back mechanism for the protocol code. For example, the event `EV_TIMER1` may be requested to be ``raised'' in `5000ms`, and cnet will call the `EV_TIMER1` event-handler in `5` seconds time. Timers are referenced via unique values. For example:

        timer1 = CNET_start_timer(EV_TIMER1, 5000, 0);

The timer has significance for functions handling timer events; all other handlers will simply receive the special `NULLTIMER`. Notice that timers do not reflect the current time; they specify which timer has expired. When a timer expires, the event-handler for the corresponding event is invoked with the event and the unique timer as parameters. Timers may be cancelled prematurely with `CNET_stop_timer` to prevent them expiring, for example:

        (void)CNET_stop_timer(timer1);

though they are automatically cancelled as a result of their handler being invoked.

cnet was written and is maintained by Chris McDonald (chris@cs.uwa.edu.au)