-
Notifications
You must be signed in to change notification settings - Fork 0
/
MIGRATION
349 lines (282 loc) · 16.1 KB
/
MIGRATION
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
MIGRATING SIMULATION MODELS FROM OMNeT++ 3.x TO 4.0
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Simulation models written for OMNeT++ 3.x cannot be used directly with
OMNeT++ 4.0 or later, due to changes in the C++ API, NED, ini and msg
files. This readme provides a brief overview of the porting process.
This is just a QUICK GUIDE -- for more background and details
see the Migration Document under doc/Migration.pdf!
You would port your simulation model in two stages: (1) get it working
with 4.1; then (2) improve it by making use of new OMNeT++ features.
Getting your simulation model working.
PREREQUISITES: Have OMNeT++ 4.1 installed and working, and familiarize
yourself with the IDE.
1. Make a backup of your simulation model. Be prepared to have to start
over with the migration process several times, until you get it right.
2. Change into the directory of your simulation model, and run
all scripts in the <omnetpp>/migrate subdirectory from there.
$ cd MyModel
$ ../omnetpp-4.0/migrate/migratened
$ ../omnetpp-4.0/migrate/migrateini
$ ../omnetpp-4.0/migrate/migratemsg
$ ../omnetpp-4.0/migrate/migratecpp | tee migratecpp.out
The scripts convert NED, ini, msg and C++ files to 4.x format.
The result will need some manual post-processing, because not
everything can be converted automatically. The scripts will print
some hints on what you'll need to do manually -- please make note
of these printouts. Especially, migratecpp is going to print a
number of notes, warnings and hints -- read them carefully.
3. If your simulation model is based on the INET Framework, have the
new INET installed, and similarly run the scripts in the migrate/
subdirectory of INET. They will update your source files according
to changes in the INET Framework.
$ cd MyModel
$ ../INET/migrate/migratened
$ ../INET/migrate/migrateini
$ ../INET/migrate/migratemsg
$ ../INET/migrate/migratecpp | tee migratecpp.out
4. You can do the rest of the migration either on the command line,
or in the OMNeT++ IDE. We recommend the latter. To use the IDE,
you need to create a project for your simulation model. Select
File | New | OMNeT++ Project...
from the menu. A wizard comes up. On the first page, uncheck
"Use default location" and specify the name and the directory
of your simulation model, then go through the other wizard pages
and hit Finish at the end. You should see the new project appear
in the Project Explorer (left), and it should contain your files.
If something goes wrong, remove the project by selecting it and
hitting DEL. It will ask whether you also want to delete the
files from the disk -- answer NO! Then start over with project
creation.
4a. If your project is based on INET (or any other project), you can set
up the project as one that depends on the INET project. To do that,
make sure the INET project is imported and open, then open the
Properties dialog for your project (select the project, right-click
it, then choose Properties from the context menu), and check INET
on the Project References page. This makes the NED types of INET
available in your project, and also puts INET directories on the
C++ include path. Make sure the INET project builds a (static/shared)
library, not an executable, so your project can link with it -- you
can check that by opening INET's Project Properties dialog, and going
to the C/C++ Build / Makemake page.
5. NED in 4.x has a package system, similar to Java. If your model
contains NED files in several subdirectories, these subdirectories
now mean packages, and the NED files will need package declarations
and imports to be added. This can be done automatically in the IDE.
Have your project created and open in the IDE (see previous step),
then choose
Navigate | Clean up NED files...
from the menu. Select your project and click OK. The IDE will then fix
all package declarations and imports in your NED files.
You may want to add a package.ned file to define the root package --
see later.
6. Revise NED files. A brief checklist:
(1) Revise "volatile" parameters if they really need to be volatile.
As a rule of thumb, a parameter needs to be volatile if it is
being read *during* simulation, not only in the initialization
phase. If it is only read from initialize(), remove the volatile
keyword.
(2) Revise "double" parameters if they should rather be "int".
Before, NED only supported a "numeric" type, and the migration
script, for lack of a better heuristics, turns all such parameters
into "double". You need to check each, and change it to "int" if
needed.
(3) "somepar = input;" lines became just "somepar;" -- you probably
want to remove them, as they are completely redundant.
(4) Remove superfluous network declarations. Background: a 3.x-style
network declaration denotes a compound module as network. In 4.x,
a compound module may be directly declared to be a network, so that
extra step is not needed. Example: the 3.x network declaration
network cqn : CQN
endmodule
is converted by the migration script into an inheritance:
network cqn extends CQN {
}
However, you can remove that altogether, if you change the CQN
module's declaration to use the "network" keyword (like:
network CQN {...}), and replace network=cqn with network=CQN
in the ini files.
(5) "like" module types should be changed into interfaces, and actual
types declared to be "like" them. For example, if you have a
submodule
app: <appType> like App;
then App should be turned into a module interface (and its name
prepended with "I" to conform naming convention), like this:
moduleinterface IApp {
gates: input in; output out;
}
and the concrete types should be modified to comply with IApp:
simple BurstyApp like IApp { ... }
simple AnotherApp like IApp { ... }
7. Compile your simulation model (right-click on the project and
select Build from the context menu, or close all other projects
and hit Ctrl+B.) The most frequent compile errors and their fixes:
"Cannot convert SimTime to double"
simtime_t now maps to the int64-based SimTime class and not double.
Wherever a simtime_t is assigned to a variable of type double,
consider changing that variable to simtime_t as well.
Where still needed, use SIMTIME_DBL(t) to convert a simtime_t to
double. In printf's, use "%s" and SIMTIME_STR(t). The advantage of
using these macros instead of SimTime methods is that your model will
also compile with simtime_t=double (a compatibility mode).
"No such method setBitLength/getBitLength/encapsulate/decapsulate"
Length and encapsulation have been moved to cPacket, a subclass of
cMessage. You likely need to change the "message" keyword in
.msg files to "packet", which will cause the generated class
to have cPacket as base class.
message ABCPacket {...} ==> packet ABCPacket {...}
Inside handleMessage() and other functions, cast the cMessage*
pointer to cPacket:
cPacket *pkt = check_and_cast<cPacket *>(msg);
"Cannot open file csimul.h" (or any other header)
Only <omnetpp.h> is public API. Other OMNeT++ header files should
not be included directly, as they may be renamed or removed in
any future version.
"sendDirect() does not take 3 (or 4) arguments"
sendDirect()'s signature has changed. It used to take a delay
as second argument; now it has two variants, one which takes
no delay argument (i.e. if you have 0.0 in your simulation,
just remove it), and another one that takes a propagation delay
and a transmission duration. If you use the second one,
you'll probably want to call setDeliverOnReceptionStart(true)
on the receiver gate in the target module's initialize() method
as well.
8. Run your simulation model. The most frequent runtime errors and
their fixes:
"Cannot convert unit 'none' to 'seconds'"
Physical units now have to be written out in expressions, so you
need to change 5 into 5s, and exponential(1) into exponential(1s).
"Cannot convert unit 'none' to 'bps'"
The datarate channel parameter now has unit bps (bit/sec), and
this unit must be written out. Kbps, Mbps, Gbps are also accepted.
"No such module type 'X'"
If your model creates modules dynamically, module types need to be
looked up by fully qualified name (like "some.package.X").
Making use of new OMNeT++ features.
1. NED files
(1) default icons: add a line like this into the parameters section
of simple modules: @display("i=block/fork");
(2) default values: they may be specified in NED files where the
parameter is declared, or in any sub-type. The syntax is the
following:
double interval = default(exponential(1));
(3) annotate parameters with physical units, using the @unit property.
This will enforce units to be given in ini files as well.
An example:
double interval @unit(s) = default(exponential(1s));
(4) use inout gates and bi-directional connections where appropriate.
The gate type keyword is "inout", and the connection syntax uses
"<-->" arrows. Examples:
inout port;
and
node1.port <--> node2.port;
(5) define the root package for your NED files. To do that, put a
package.ned file into the toplevel NED source folder (i.e.
a directory that's listed on the OMNeT++/NED Source Folders page
of the Project Properties dialog of your project). The package
declaration in that package.ned file determines the package of that
directory and all directories underneath. For example, if the
file's contents is
package org.myproject;
then the NED packages will be org.myproject, org.myproject.subdir1,
org.myproject.subdir2, etc.
(6) use inner types: specialized channels (like 100Mbps, 1Gbps etc)
no longer need to pollute the global namespace, you can move them
inside the compound module where they are actually needed:
module Network {
types:
channel C extends ned.DatarateChannel {
datarate = 100Mbps
}
...
host1.p++ <--> C <--> host2.p++;
}
(7) use inheritance to specialize a module or channel, or to factor out
the common part of several compound modules into a base type
(because a derived compound module may add new submodules and
connections in addition to new parameters and gates)
(8) mark gates that are supposed to receive messages via sendDirect()
as such:
input in @directIn; // or: input in @loose;
The effect of @loose or @directIn is that NED won't complain about
the gate being unconnected, and you can remove the "allowunconnected"
(formerly "nocheck") keyword from "connections:".
(9) possibly make use of @properties as "marker interfaces", like @node,
@host(true)
2. ini files
(1) Give meaningful names to sections. The ini migration tool changes
[Run n] to [Config confign], but you can surely come up with better
names.
(2) Remove redundant parameter settings. If a module parameter now has
a default value and the ini file explicitly sets that value,
that line can be removed from the ini file.
Hint: if you open the file in the IDE, it will annotate the lines
that can possibly be removed with a blue "i" mark.
(3) Make use of section inheritance, if applicable. Common settings
may be factored out into a based config that other configs extend
(syntax: add an extend=BaseConfig line).
(4) Make use of the iteration syntax (${...}). If you had many runs
that simulated the same network with different parameter value,
they can be merged into a single config that contains an iteration.
For example, if you had
[Run 1]
**.numClients = 2
[Run 2]
**.numClients = 5
[Run 3]
**.numClients = 10
Then you can now merge them into a single config:
[Config MyExperiment]
**.numClients = ${N=2,5,10}
There can be several iterations within a section (nested loops),
you can specify an additional constraint to get a subset of the
Cartesian product (constraint=), and you can repeat each one
several times with different seeds (repeat=).
3. C++ code
(1) You can add metadata to the output vectors to enhance the
visualization. Use the setInterpolationMode(), setEnum() etc.
methods of cOutVector.
(2) If possible take advantage of inout gates a bidirectional
connections. use gate("gatename$i") or gate("gatename$o")
to access the two direction separately (note: gate("gatename")
will not work).
(3) Use cMessage or cPacket depending on your needs. The length,
bit error flag and encapsulated message cMessage fields got
factored out from cMessage, into the cPacket class.
(4) If you have a complex channel model, now you can extend cChannel
and register your new class. Override the deliver(...) method.
There are three new built-in channels you can use as a starting
point: cIdealChannel, cDelayChannel, cDatarateChannel
(5) If a message is transmitted on a finite-datarate channel, call
setDeliverOnReceptionStart(true) on a simple module's input gate
to deliver the message to the receiver module at the start of
the reception (instead of the default, which delivers at the end).
In 3.x, the only way to receive the packet at the beginning of
the reception was to set the channel datarate to zero and
calculate the duration manually -- this workaround is no longer
needed.
(6) In wireless models, the handling of transmission duration needs
to be refactored. In 3.x, the receiver side usually calculated
the frame duration independent of the sender. In 4.x, the duration
calculated by the sender should be specified in the sendDirect()
call, which writes it into the packet (setDuration()). The receiver
module should have the input gate configured for
deliverOnReceptionStart=true, i.e. it is supposed to call
setDeliverOnReceptionStart(true) on the gate in the initialize
phase. The receiver module should obtain the duration from the
packet (pkt->getDuration()) instead of recalculating it.
(7) You can use the getProperties() method of cComponent to access
model metadata. Properties can be attached to a module or channel
in a NED file with the @propname(key1=val1,val2;key2=valA,valB)
syntax. You can use properties as a markers (e.g. @host), or
to provide additional information about the model.
Other sources of information
doc/migration.pdf
include/ChangeLog
src/*/ChangeLog
doc/API-changes
doc/api
doc/manual
opp_run -h all
If you get stuck anywhere, please post the problem on the mailing list, and
we'll rush to your help!
The OMNeT++ team