Signals in OMNeT++ András Varga OMNeT++ Workshop March 19, 2010 Malaga, Spain Motivation Problems to solve: • Need more flexible statistics recording • Ideally, module should just produce the values, and we want to be able to decide per-run basis what to record and how (vector, mean/stddev, histogram, etc.) • Existing models: they need to calculate and output “everything”, and actual recording may be disabled via configuration options • Support for global statistics processing modules • Example: watch for the total #drops in the network to raise over a limit, and tune model parameters accordingly • Currently not possible without changing participating modules 2 Motivation / 2 In the INET Framework: • Support for exposing pcap traces • We need to be able to record packet traces easily, without obtrusive changes to existing models: • without inserting an extra submodule deep inside StandardHost • without adding fwrite() calls and “string pcapFileName” parameters into L2 modules • Support for creating global log files • E.g. “nam” traces, whose contents should come from all over the simulation • Model change notification • Certain model components need to get informed about runtime topology changes • For example, the PPP module needs to update internal cached channel pointer when it gets reconnected 3 Idea Recurrent element: • Producer of information needs to be decoupled from consumer. Why not build a publish-subscribe mechanism into OMNeT++ itself? Note: there is MF’s Blackboard and INET’s NotificationBoard, but they are not suitable for many of these tasks (e.g. statistics, model change notification) 4 The Signals API Component (module or channel) class: • • • • • emit(signal, emit(signal, emit(signal, emit(signal, emit(signal, long) double) simtime_t) const char *) cObject *) for everything else Listener (cIListener class): • • • • • • receiveSignal(sourceComponent, receiveSignal(sourceComponent, receiveSignal(sourceComponent, receiveSignal(sourceComponent, receiveSignal(sourceComponent, +1: finish(component, signal) signal, long) signal, double) signal, simtime_t) signal, const char *) signal, cObject *) mostly for result recording 5 Adding Listeners Component (module or channel) class: • subscribe(signal, cIListener *) • unsubscribe(signal, cIListener *) • hasListeners(signal) Listener (cIListener): • subscribedTo(component, signal) • unsubscribedFrom(component, signal) 6 Signal Propagation Signals propagate up the module tree: – You can subscribe at the module, or at any ancestor – Listeners subscribed at the root are catch-alls – Optimization: no listener – no notification overhead! Practical examples: – INET’s NotificationBoard can be substituted by adding listeners to the host compound module – Facilitates collecting global or aggregated statistics • if statistics are exposed as signals, aggregation can be done by adding listeners at the root module 7 Identifying Signals • Signals are identified by name (a string) • During simulation: simsignal_t – dynamically assigned numeric identifier, used for efficiency reasons; “signal ID” – Obtaining the signal ID from signal name: cComponent::registerSignal(“signalname”); • Signal names and signal IDs are global – Different modules “registering” (looking up) the same name get the same signal ID 8 NotificationBoard Signals as replacement for INET’s NotificationBoard • How? – Modules emit notifications as (local) signals – Listeners subscribe at the host/router compound module • Why? – Efficiency: signal allow emitting only when needed • Notification information may be costly to produce, and maybe no one is listening! Signals have an efficient hasListeners() method. – Uniformity: • Signals emitted this way may be used for other purposes as well, e.g. for statistics recording (e.g. “number of routing table changes during simulation”) 9 Signals Currently signals are ready to be used for: • Model change notifications • Statistics recording • Model-specific use (e.g. as NotificationBoard) Planned: • pcap trace recording, nam trace recording • As input for custom animations • To be used by a future animation framework. Examples: wireless transmission effects; visualize routes discovered by routing protocols 10 Model Change Notifications • Two predefined signals: – PRE_MODEL_CHANGE, POST_MODEL_CHANGE • Notifications are emitted as objects – subclassed from cModelChangeNotification – contain the details about the change 11 Model Change Notifications Notification details data classes: cPreModuleAddNotification cPreModuleDeleteNotification cPreModuleReparentNotification cPreGateAddNotification cPreGateDeleteNotification cPreGateVectorResizeNotification cPreGateConnectNotification cPreGateDisconnectNotification cPrePathCreateNotification cPrePathCutNotification cPreParameterChangeNotification cPreDisplayStringChangeNotification cPostModuleAddNotification cPostModuleDeleteNotification cPostModuleReparentNotification cPostGateAddNotification cPostGateDeleteNotification cPostGateVectorResizeNotification cPostGateConnectNotification cPostGateDisconnectNotification cPostPathCreateNotification cPostPathCutNotification cPostParameterChangeNotification cPostDisplayStringChangeNotification 12 Model Change Notifications Example notification details classes: class cPostGateVectorResizeNotification : ... { cModule *module; const char *gateName; int oldSize; }; class cPostGateConnectNotification : … { cGate *gate; }; class cPre/PostPathCreateNotification : … { same for xxxPathCutNotification cGate *pathStartGate; cGate *pathEndGate; cGate *changedGate; the gate that got connected or disconnected 13 Planned: Packet Trace Recording Recording pcap traces: – Modules emit packets as signal value (cPacket*) – The simulation framework may subscribe to the signal – Listener converts packets to byte arrays and records them into a pcap file – Crucial: pcap-recording listener should be extensible – Tkenv support (“Save pcap trace…” menu item) 14 Statistics Recording Statistics recording using signals: • Data are emitted as signals from modules/channels – emit(signalID, x) • Statistics are declared in the NED files – @statistic property – may define: name, title, interpolation mode, unit, default recording mode (as vector, as histogram, etc) • Configurability: – amount of information to be recorded can be changed from omnetpp.ini • Compatibility: – This is just a layer above existing vectors/scalars 15 Statistics Basic syntax: @statistic[name](attr1=value1;attr2=value2;…); – Statistic name is also the signal name (by default) – Attributes get recorded to the result files – Some attribute names: • title: text for chart legend • unit: unit of measurement (for display on charts) • interpolationmode: linear, sample-hold, backward-sample-hold, none (affects chart drawing) 16 Statistics: An Example NED example: simple Fifo { parameters: volatile double serviceTime @unit(s); @statistic[queueLen](title="queue length”; interpolationmode=sample-hold); @statistic[busy](interpolationmode=sample-hold); @statistic[queueingTime](unit=s); gates: input in; output out; } 17 Statistics • Recording mode: – @statistic[qlen](record=vector,max,timeavg); • Available recorders: – last, mean, timeavg, min, max, sum, count, histogram, vector – new ones can be defined • Recording mode can be modified from omnetpp.ini: – **.qlen.result-recoding-mode = +count,-vector 18 Statistics When statistic name and signal name differ: – @statistic[queueLength](source=qlen; record=vector,max,timeavg); Object-to-number transformations: – @statistic[numTxPks](source=“count(txStart)”; record=vector,last); – @statistic[txBytes](source=“pkBytes(txStart)”; record=vector,histogram); Expressions: – @statistic[txBits](source=“8*pkBytes(txStart)”; record=vector,histogram); 19 Statistics Recording with timestamp: • Must be emitted as object (cObject*) • Helper class: cTimestampedValue – contains a timestamp and a value • Usage: cTimestampedValue tmp(timestamp, value); emit(signalID, &tmp); 20 Statistics: Extensibility Defining new result filters and result recorders • To list existing ones: $ ./mysim -h resultfilters $ ./mysim -h resultrecorders • To add existing ones: • Implement ResultFilter / ResultRecorder (from src/envir) • Register them with the Register_ResultFilter() and Register_ResultRecorder() macros 21 Statistics: Example Recorder class MeanRecorder : public NumericResultRecorder { protected: long count; double sum; protected: virtual void collect(double value) {count++; sum += value;} virtual void collect(simtime_t t, double value) {count++; sum += value;} public: MeanRecorder() {count = 0; sum = 0;} virtual void finish(ResultFilter *prev) { opp_string_map attributes = getStatisticAttributes(); ev.recordScalar(getComponent(), getResultName().c_str(), sum/count, &attributes); } }; 22 Conclusion • A new Signals framework has been introduced in OMNeT++ • Purposes: – Publish-subscribe communication in the model – Statistics collection and recording – Model change notification – Trace file writing (pcap, nam) – Other 23 Signals Questions, comments? Discussion 24