adding ns3 testbed: ongoing development! tests DON'T run OK!
[nepi.git] / src / nepi / testbeds / ns3 / metadata_v3.9.RC3.py
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3
4 from constants import TESTBED_ID
5 from nepi.core import metadata
6 from nepi.core.attributes import Attribute
7 from nepi.util import validation
8 from nepi.util.constants import AF_INET, STATUS_NOT_STARTED, STATUS_RUNNING, \
9         STATUS_FINISHED
10
11 wifi_standards = dict({
12     "WIFI_PHY_STANDARD_holland": 5,
13     "WIFI_PHY_STANDARD_80211p_SCH": 7,
14     "WIFI_PHY_STANDARD_80211_5Mhz": 4,
15     "WIFI_PHY_UNKNOWN": 8,
16     "WIFI_PHY_STANDARD_80211_10Mhz": 3,
17     "WIFI_PHY_STANDARD_80211g": 2,
18     "WIFI_PHY_STANDARD_80211p_CCH": 6,
19     "WIFI_PHY_STANDARD_80211a": 0,
20     "WIFI_PHY_STANDARD_80211b": 1
21 })
22
23 ### Connection functions ####
24
25 def connect_node_device(testbed_instance, node, device):
26     node.AddDevice(device)
27
28 def connect_queue_device(testbed_instance, queue, device):
29     device.SetQueue(queue)
30
31 def connect_manager_device(testbed_instance, manager, device):
32     device.SetRemoteStationManager(manager)
33
34 def connect_phy_device(testbed_instance, phy, device):
35     device.SetPhy(phy)
36     phy.SetDevice(device)
37     # search for the node asociated with the device
38     node_guid = testbed_instance.get_connected(guid, "node", "devs")
39     if len(node_guid) == 0:
40         raise RuntimeError("Can't instantiate interface %d outside netns \
41                 node" % guid)
42     node = testbed_instance.elements[node_guid[0]]
43     phy.SetMobility(node)
44
45 def connect_mac_device(testbed_instance, mac, device):
46     device.SetMac(mac)
47
48 def connect_errormodel_device(testbed_instance, model, device):
49     device.SetReceiveErrorModel(model)
50
51 def connect_errormodel_phy(testbed_instance, err, phy):
52     phy.SetErrorRateModel(err)
53
54 def connect_channel_device(testbed_instance, channel, device):
55     device.Attach(channel)
56
57 def connect_simple_channel_device(testbed_instance, channel, device):
58     device.SetChannel(channel)
59
60 def connect_loss_channel(testbed_instance, loss, channel):
61     channel.SetPropagationLossModel(loss)
62
63 def connect_next_loss(testbed_instance, prev, next):
64     prev.SetNext(next)
65
66 def connect_delay_channel(testbed_instance, delay, channel):
67     channel.SetPropagationDelayModel(delay)
68
69 def connect_node_application(testbed_instance, node, application):
70     node.AddApplication(application)
71 # works for ArpL3Protocol, Ipv4L3Protocol, UdpL4Protocol, TcpL4Protocol,
72 # NscTcpL4Protocol, MobilityModel (every subclass), 
73 # RoutingProtocol (every subclass)
74
75 def connect_node_other(tesbed_instance, node, other):
76     node.AggregateObject(other)
77  
78 ### Creation functions ###
79
80 def create_element(testbed_instance, guid, parameters, factory_parameters):
81     element_factory = testbed_instance.ns3.ObjectFactory()
82     factory_id = testbed_instance._create[guid]
83     element_factory.SetTypeId(factory_id) 
84     for name, value in factory_parameters.iteritems():
85         testbed_instance._set(element_factory, factory_id, name, value)
86     element = element_factory.Create()
87     testbed_instance._elements[guid] = element
88
89 def create_node(testbed_instance, guid, parameters, factory_parameters):
90     create_element(testbed_instance, guid, parameters, factory_parameters)
91     element = testbed_instance._elements[guid]
92     element.AggregateObject(testbed_instance.PacketSocketFactory())
93
94 def create_dev(testbed_instance, guid, parameters, factory_parameters):
95     create_element(testbed_instance, guid, parameters, factory_parameters)
96     element = testbed_instance._elements[guid]
97     if "macAddress" in parameters:
98         address = parameters["macAddress"]
99         macaddr = testbed_instance.ns3.Mac48Address(address)
100     else:
101         macaddr = testbed_instance.ns3.Mac48Address.Allocate()
102     element.SetAddress(macaddr)
103
104 def create_wifi_standard_model(testbed_instance, guid, parameters, 
105         factory_parameters):
106     create_element(testbed_instance, guid, parameters, factory_parameters)
107     element = testbed_instance._elements[guid]
108     if "standard" in parameters:
109         standard = parameters["standard"]
110         if standard:
111             elements.ConfigureStandard(wifi_standards[standard])
112
113 def create_ipv4stack(testbed_instance, guid, parameters, factory_parameters):
114     create_element(testbed_instance, guid, parameters, factory_parameters)
115     element = testbed_instance._elements[guid]
116     list_routing = testbed_instance.ns3.Ipv4ListRouting()
117     element.SetRoutingProtocol(list_routing)
118     static_routing = testbed_instance.ns3.Ipv4StaticRouting()
119     list_routing.AddRoutingProtocol(static_routing, 1)
120
121 ### Start/Stop functions ###
122
123 def start_application(testbed_instance, guid, parameters, traces):
124     element = testbed_instance.elements[guid]
125     element.Start()
126
127 def stop_application(testbed_instance, guid, parameters, traces):
128     element = testbed_instance.elements[guid]
129     element.Stop()
130
131 ### Status functions ###
132
133 def status_application(testbed_instance, guid, parameters, traces):
134     if guid not in testbed_instance.elements.keys():
135         return STATUS_NOT_STARTED
136     app = testbed_instance.elements[guid]
137     if "stopTime" in parameters:
138         stop = parameters["stopTime"]
139         if stop:
140             simTime = testbed_instance.ns3.Simulator.Now()
141             if simTime.Compare(stopTime) > 0:
142                 return STATUS_RUNNING
143     return STATUS_FINISHED
144
145 ### Factory information ###
146
147 connector_types = dict({
148     "node": dict({
149                 "help": "Connector to a ns3::Node object (mandatory)",
150                 "name": "node",
151                 "max": 1,
152                 "min": 1
153             }),
154     "devs": dict({
155                 "help": "Connector to network interfaces",
156                 "name": "devs",
157                 "max": -1,
158                 "min": 0
159             }),
160     "dev2": dict({
161                 "help": "Connector to exactly two network interfaces (mandatory)",
162                 "name": "dev2",
163                 "max": 2,
164                 "min": 2
165             }),
166     "dev": dict({
167                 "help": "Connector to exactly one network interface (mandatory)",
168                 "name": "dev",
169                 "max": 1,
170                 "min": 1
171             }),
172     "apps": dict({
173                 "help": "Connector to applications", 
174                 "name": "apps",
175                 "max": -1,
176                 "min": 0
177             }),
178     "protos": dict({
179                 "help": "Connector to network stacks and protocols", 
180                 "name": "protos",
181                 "max": -1,
182                 "min": 0
183             }),
184     "chan": dict({
185                 "help": "Connector to a channel for the device (mandatory)", 
186                 "name": "chan",
187                 "max": 1,
188                 "min": 1
189             }),
190     "queue": dict({
191                 "help": "Connector to a queueing discipline (mandatory)", 
192                 "name": "queue",
193                 "max": 1,
194                 "min": 1
195             }),
196     "err": dict({
197                 "help": "Connector to an error model for the device", 
198                 "name": "err",
199                 "max": 1,
200                 "min": 0
201             }),
202     "fd": dict({
203                 "help": "Connector to interconnect devices with file descriptors",
204                 "name": "fd",
205                 "max": 1,
206                 "min": 0
207             }),
208     "phy": dict({
209                 "help": "Connector to interconnect elements with a PHY wifi model", 
210                 "name": "phy",
211                 "max": 1,
212                 "min": 0
213             }),
214     "phys": dict({
215                 "help": "Connector to interconnect a wifi channel with PHY wifi models", 
216                 "name": "phys",
217                 "max": -1,
218                 "min": 0
219             }),
220     "mac": dict({
221                 "help": "Connector to interconnect a device with a MAC wifi model", 
222                 "name": "mac",
223                 "max": 1,
224                 "min": 0
225             }),
226     "manager": dict({
227                 "help": "Connector to interconnect a wifi device with a wifi manager", 
228                 "name": "manager",
229                 "max": 1,
230                 "min": 0
231             }),
232     "delay": dict({
233                 "help": "Connector to a delay model", 
234                 "name": "delay",
235                 "max": 1,
236                 "min": 0
237             }),
238     "loss": dict({
239                 "help": "Connector to a loss model", 
240                 "name": "loss",
241                 "max": 1,
242                 "min": 0
243             }),
244     "prev": dict({
245                 "help": "Connector to the previous loss model", 
246                 "name": "prev",
247                 "max": 1,
248                 "min": 0
249             }),
250     "next": dict({
251                 "help": "Connector to the next loss model", 
252                 "name": "next",
253                 "max": 1,
254                 "min": 0
255             }),
256     "mobility": dict({
257                 "help": "Connector to a mobility model for the node", 
258                 "name": "mobility",
259                 "max": 1,
260                 "min": 0
261             }),
262     })
263
264 connections = [
265     dict({
266             "from": ( "ns3", "ns3::Node", "devs" ),
267             "to":   ( "ns3", "ns3::BridgeNetDevice", "node" ),
268             "code": connect_node_device,
269             "can_cross": False
270     }),
271     dict({
272             "from": ( "ns3", "ns3::Node", "devs" ),
273             "to":   ( "ns3", "ns3::CsmaNetDevice", "node" ),
274             "code": connect_node_device,
275             "can_cross": False
276     }),
277     dict({
278             "from": ( "ns3", "ns3::Node", "devs" ),
279             "to":   ( "ns3", "ns3::EmuNetDevice", "node" ),
280             "code": connect_node_device,
281             "can_cross": False
282     }),
283     dict({
284             "from": ( "ns3", "ns3::Node", "devs" ),
285             "to":   ( "ns3", "ns3::PointToPointNetDevice", "node" ),
286             "code": connect_node_device,
287             "can_cross": False
288     }),
289     dict({
290             "from": ( "ns3", "ns3::Node", "devs" ),
291             "to":   ( "ns3", "ns3::SimpleNetDevice", "node" ),
292             "code": connect_node_device,
293             "can_cross": False
294     }),
295     dict({
296             "from": ( "ns3", "ns3::Node", "devs" ),
297             "to":   ( "ns3", "ns3::FileDescriptorNetDevice", "node" ),
298             "code": connect_node_device,
299             "can_cross": False
300     }),
301     dict({
302             "from": ( "ns3", "ns3::Node", "devs" ),
303             "to":   ( "ns3", "ns3::WifiNetDevice", "node" ),
304             "code": connect_node_device,   
305             "can_cross": False
306     }),
307     dict({
308             "from": ( "ns3", "ns3::DropTailQueue", "dev" ),
309             "to":   ( "ns3", "ns3::CsmaNetDevice", "queue" ),
310             "code": connect_queue_device,
311             "can_cross": False
312     }),
313     dict({
314             "from": ( "ns3", "ns3::DropTailQueue", "dev" ),
315             "to":   ( "ns3", "ns3::EmuNetDevice", "queue" ),
316             "code": connect_queue_device,
317             "can_cross": False
318     }),
319     dict({
320             "from": ( "ns3", "ns3::DropTailQueue", "dev" ),
321             "to":   ( "ns3", "ns3::PointToPointNetDevice", "queue" ),
322             "code": connect_queue_device,
323             "can_cross": False
324     }),
325     dict({
326             "from": ( "ns3", "ns3::ArfWifiManager", "dev" ),
327             "to":   ( "ns3", "ns3::WifiNetDevice", "manager" ),  
328             "code": connect_manager_device,
329             "can_cross": False
330     }),
331     dict({
332             "from": ( "ns3", "ns3::ConstantRateWifiManager", "dev" ),
333             "to":   ( "ns3", "ns3::WifiNetDevice", "manager" ),  
334             "code": connect_manager_device,
335             "can_cross": False
336     }),
337     dict({
338             "from": ( "ns3", "ns3::YansWifiPhy", "dev" ),
339             "to":   ( "ns3", "ns3::WifiNetDevice", "phy" ),  
340             "code": connect_phy_device,
341             "can_cross": False
342     }),
343     dict({
344             "from": ( "ns3", "ns3::QapWifiMac", "dev" ),
345             "to":   ( "ns3", "ns3::WifiNetDevice", "mac" ),
346             "code": connect_mac_device,
347             "can_cross": False
348     }),
349     dict({
350             "from": ( "ns3", "ns3::QstaWifiMac", "dev" ),
351             "to":   ( "ns3", "ns3::WifiNetDevice", "mac" ),
352             "code": connect_mac_device,
353             "can_cross": False
354     }),
355     dict({
356             "from": ( "ns3", "ns3::RateErrorModel", "dev" ),
357             "to":   ( "ns3", "ns3::CsmaNetDevice", "err" ),
358             "code": connect_errormodel_device,
359             "can_cross": False
360     }),
361     dict({
362             "from": ( "ns3", "ns3::RateErrorModel", "dev" ),
363             "to":   ( "ns3", "ns3::PointToPointNetDevice", "err" ),
364             "code": connect_errormodel_device,
365             "can_cross": False
366     }),
367     dict({
368             "from": ( "ns3", "ns3::ListErrorModel", "dev" ),
369             "to":   ( "ns3", "ns3::CsmaNetDevice", "err" ),
370             "code": connect_errormodel_device,
371             "can_cross": False
372     }),
373     dict({
374             "from": ( "ns3", "ns3::ListErrorModel", "dev" ),
375             "to":   ( "ns3", "ns3::PointToPointNetDevice", "err" ),
376             "code": connect_errormodel_device,
377             "can_cross": False
378     }),
379     dict({
380         "from": ( "ns3", "ns3::NistErrorRateModel", "phy" ),        
381         "to":   ( "ns3", "ns3::YansWifiPhy", "err" ),
382         "code": connect_errormodel_phy,
383         "can_cross": False
384     }),
385     dict({
386         "from": ( "ns3", "ns3::CsmaChannel", "devs" ),
387         "to":   ( "ns3", "ns3::CsmaNetDevice", "chan" ),
388         "code": connect_channel_device,
389         "can_cross": False
390     }),
391     dict({
392         "from": ( "ns3", "ns3::PointToPointChannel", "dev2" ),
393         "to":   ( "ns3", "ns3::PointToPointNetDevice", "chan" ),
394         "code": connect_channel_device,
395         "can_cross": False
396     }),
397     dict({
398         "from": ( "ns3", "ns3::SimpleChannel", "devs" ),
399         "to":   ( "ns3", "ns3::SimpleNetDevice", "chan" ),
400         "code": connect_simple_channel_device,
401         "can_cross": False
402     }),
403     dict({
404         "from": ( "ns3", "ns3::YansWifiChannel", "phys" ),
405         "to":   ( "ns3", "ns3::YansWifiPhy", "chan" ),  
406         "code": connect_simple_channel_device,
407         "can_cross": False
408     }),
409     dict({
410         "from": ( "ns3", "ns3::LogDistancePropagationLossModel", "prev" ),
411         "to":   ( "ns3", "ns3::YansWifiChannel", "loss" ),  
412         "code": connect_loss_channel,
413         "can_cross": False
414     }),
415     dict({
416         "from": ( "ns3", "ns3::LogDistancePropagationLossModel", "prev" ),
417         "to":   ( "ns3", "ns3::LogDistancePropagationLossModel", "next" ),  
418         "code": connect_next_loss,
419         "can_cross": False
420     }),
421     dict({
422         "from": ( "ns3", "ns3::ConstantSpeedPropagationDelayModel", "chan" ),
423         "to":   ( "ns3", "ns3::YansWifiChannel", "delay" ),  
424         "code": connect_delay_channel,
425         "can_cross": False
426     }),
427     dict({
428         "from": ( "ns3", "ns3::Node", "apps" ),
429         "to":   ( "ns3", "ns3::OnOffApplication", "node" ),
430         "code": connect_node_application,
431         "can_cross": False
432     }),
433     dict({
434         "from": ( "ns3", "ns3::Node", "apps" ),
435         "to":   ( "ns3", "ns3::PacketSink", "node" ),
436         "code": connect_node_application,
437         "can_cross": False
438     }),
439     dict({
440         "from": ( "ns3", "ns3::Node", "apps" ),
441         "to":   ( "ns3", "ns3::UdpEchoClient", "node" ),
442         "code": connect_node_application,
443         "can_cross": False
444     }),
445     dict({
446         "from": ( "ns3", "ns3::Node", "apps" ),
447         "to":   ( "ns3", "ns3::UdpEchoServer", "node" ),
448         "code": connect_node_application,
449         "can_cross": False
450     }),
451     dict({
452         "from": ( "ns3", "ns3::Node", "apps" ),
453         "to":   ( "ns3", "ns3::V4Ping", "node" ),
454         "code": connect_node_application,
455         "can_cross": False
456     }),
457     dict({
458         "from": ( "ns3", "ns3::Node", "protos" ),
459         "to":   ( "ns3", "ns3::ArpL3Protocol", "node" ),
460         "code": connect_node_other,
461         "can_cross": False
462     }),
463     dict({
464         "from": ( "ns3", "ns3::Node", "protos" ),
465         "to":   ( "ns3", "ns3::Icmpv4L4Protocol", "node" ),
466         "code": connect_node_other,
467         "can_cross": False
468     }),
469     dict({
470         "from": ( "ns3", "ns3::Node", "protos" ),
471         "to":   ( "ns3", "ns3::Ipv4L3Protocol", "node" ),
472         "code": connect_node_other,
473         "can_cross": False
474     }),
475     dict({
476         "from": ( "ns3", "ns3::Node", "protos" ),
477         "to":   ( "ns3", "ns3::UdpL4Protocol", "node" ),
478         "code": connect_node_other,
479         "can_cross": False
480     }),
481     dict({
482         "from": ( "ns3", "ns3::Node", "protos" ),
483         "to":   ( "ns3", "ns3::TcpL4Protocol", "node" ),
484         "code": connect_node_other,
485         "can_cross": False
486     }),
487     dict({
488         "from": ( "ns3", "ns3::Node", "mobility" ),
489         "to":   ( "ns3", "ns3::ConstantAccelerationMobilityModel", "node" ),
490         "code": connect_node_other,
491         "can_cross": False
492     }),
493     dict({
494         "from": ( "ns3", "ns3::Node", "mobility" ),
495         "to":   ( "ns3", "ns3::ConstantPositionMobilityModel", "node" ),
496         "code": connect_node_other,
497         "can_cross": False
498     }),
499     dict({
500         "from": ( "ns3", "ns3::Node", "mobility" ),
501         "to":   ( "ns3", "ns3::ConstantVelocityMobilityModel", "node" ),
502         "code": connect_node_other,
503         "can_cross": False
504     }),
505     dict({
506         "from": ( "ns3", "ns3::Node", "mobility" ),
507         "to":   ( "ns3", "ns3::HierarchicalMobilityModel", "node" ),
508         "code": connect_node_other,
509         "can_cross": False
510     }),
511     dict({
512         "from": ( "ns3", "ns3::Node", "mobility" ),
513         "to":   ( "ns3", "ns3::RandomDirection2dMobilityModel", "node" ),
514         "code": connect_node_other,
515         "can_cross": False
516     }),
517     dict({
518         "from": ( "ns3", "ns3::Node", "mobility" ),
519         "to":   ( "ns3", "ns3::RandomWalk2dMobilityModel", "node" ),
520         "code": connect_node_other,
521         "can_cross": False
522     }),
523     dict({
524         "from": ( "ns3", "ns3::Node", "mobility" ),
525         "to":   ( "ns3", "ns3::RandomWaypointMobilityModel", "node" ),
526         "code": connect_node_other,
527         "can_cross": False
528     })
529 ]
530
531 # TODO!
532 attributes = dict({
533     "forward_X11": dict({      
534                 "name": "forward_X11",
535                 "help": "Forward x11 from main namespace to the node",
536                 "type": Attribute.BOOL, 
537                 "value": False,
538                 "range": None,
539                 "allowed": None,
540                 "flags": Attribute.DesignOnly,
541                 "validation_function": validation.is_bool
542             }),
543     })
544
545 # TODO!
546 traces = dict({
547     "stdout": dict({
548                 "name": "stdout",
549                 "help": "Standard output stream"
550               }),
551     })
552
553 # TODO!
554 factories_order = [ NODE, P2PIFACE, NODEIFACE, TAPIFACE, SWITCH,
555         APPLICATION ]
556
557 # TODO!
558 factories_info = dict({
559     NODE: dict({
560             "allow_routes": True,
561             "help": "Emulated Node with virtualized network stack",
562             "category": "topology",
563             "create_function": create_node,
564             "start_function": None,
565             "stop_function": None,
566             "status_function": None,
567             "box_attributes": ["forward_X11"],
568             "connector_types": ["devs", "apps"]
569        }),
570  })
571
572 testbed_attributes = dict({
573         "ns3_bindings": dict({
574                 "name": "ns3Bindings",
575                 "help": "Location of the ns-3 python binding",
576                 "type": Attribute.STRING,
577                 "value": None,
578                 "range": None,
579                 "allowed": None,
580                 "flags": Attribute.DesignOnly,
581                 "validation_function": validation.is_string # TODO: validation.is_path
582             }),
583          "ns3_library": dict({
584                 "name": "ns3Library",
585                 "help": "Location of the ns-3 library .so file",
586                 "type": Attribute.STRING,
587                 "value": None,
588                 "range": None,
589                 "allowed": None,
590                 "flags": Attribute.DesignOnly,
591                 "validation_function": validation.is_string # TODO: validation.is_path
592             }),
593          "simu_impl_type": dict({
594                 "name": "SimulatorImplementationType",
595                 "help": "The object class to use as the simulator implementation",
596                 "type": Attribute.STRING,
597                 "value": None,
598                 "range": None,
599                 "allowed": None,
600                 "flags": Attribute.DesignOnly,
601                 "validation_function": validation.is_string
602             }),
603           "checksum": dict({
604                 "name": "ChecksumEnabled",
605                 "help": "A global switch to enable all checksums for all protocols",
606                 "type": Attribute.BOOL,
607                 "value": False,
608                 "range": None,
609                 "allowed": None,
610                 "flags": Attribute.DesignOnly,
611                 "validation_function": validation.is_bool
612             })
613  })
614
615 class VersionedMetadataInfo(metadata.VersionedMetadataInfo):
616     @property
617     def connections_types(self):
618         return connection_types
619
620     @property
621     def connections(self):
622         return connections
623
624     @property
625     def attributes(self):
626         return attributes
627
628     @property
629     def traces(self):
630         return traces
631
632     @property
633     def factories_order(self):
634         return factories_order
635
636     @property
637     def factories_info(self):
638         return factories_info
639
640     @property
641     def testbed_attributes(self):
642         return testbed_attributes
643