2 # -*- coding: utf-8 -*-
4 from nepi.core.design import ExperimentDescription, FactoriesProvider
5 from nepi.core.execute import ExperimentController
6 from optparse import OptionParser, SUPPRESS_HELP
7 from nepi.util import proxy
8 from nepi.util.constants import DeploymentConfiguration as DC
17 -----------------------------------------------------------------------
20 | +-----+ +-----+ +-----+ +-----+ +------+ |
21 | |node1| |node2| |node3| |node4 | |server| |
22 | +-----+ +-----+ +-----+ +-----+ +------+ |
23 | 65/30 69/30 73/30 77/30 226/30 |
24 | ------- ------- ------- ------- -------- |
26 |---------------------------------------------------------------------|
28 | ------- ------- ------- ------- | |
29 | 66/30 30/30 74/30 78/30 | |
30 | +-----+ +-----+ +-----+ +-----+ | |
31 | |sta0 | |sta1 | |sta2 | |sta3 | | |
32 | +-----+ +-----+ +-----+ +-----+ | |
33 | 34/27 35/27 36/27 37/27 | |
34 | ------- -------- ------- ------- | |
35 | ((*)) ((*)) ((*)) ((*)) | |
42 | | AP | 225/30 |-------------------- |
46 -----------------------------------------------------------------------
50 class WirelessOverlay(object):
52 usage = "usage: %prog -n number_sta -m movie -u user"
53 parser = OptionParser(usage=usage)
54 parser.add_option("-u", "--user", dest="user", help="Valid linux system user (not root).", type="str")
55 parser.add_option("-m", "--movie", dest="movie", help="Path to movie file to play", type="str")
56 parser.add_option("-n", "--nsta", dest="nsta", help="Number of wifi stations", type="int")
57 parser.add_option("-a", "--base_addr", dest="base_addr", help="Base address segment for the experiment", type="str")
58 (options, args) = parser.parse_args()
60 parser.error("Missing 'movie' option.")
61 if options.user == 'root':
62 parser.error("Missing or invalid 'user' option.")
63 if options.user == 'root':
64 parser.error("Missing or invalid 'user' option.")
65 if options.nsta and options.nsta > 8:
66 parser.error("Try a number of stations under 9.")
68 self.user = options.user if options.user else os.getlogin()
69 self.movie = options.movie
70 self.nsta = options.nsta if options.nsta else 4
71 base = options.base_addr if options.base_addr else "192.168.4"
72 self.base_addr = base + ".%d"
73 self.root_dir = tempfile.mkdtemp()
75 def add_netns_tap(self, netns_desc, node):
76 tap = netns_desc.create("TapNodeInterface")
77 tap.set_attribute_value("up", True)
78 node.connector("devs").connect(tap.connector("node"))
81 def add_ns3_fdnd(self, ns3_desc, node):
82 fdnd = ns3_desc.create("ns3::FdNetDevice")
83 node.connector("devs").connect(fdnd.connector("node"))
84 fdnd.enable_trace("FdPcapTrace")
87 def add_ns3_node(self, ns3_desc):
88 node = ns3_desc.create("ns3::Node")
89 ipv4 = ns3_desc.create("ns3::Ipv4L3Protocol")
90 arp = ns3_desc.create("ns3::ArpL3Protocol")
91 icmp = ns3_desc.create("ns3::Icmpv4L4Protocol")
92 udp = ns3_desc.create("ns3::UdpL4Protocol")
93 node.connector("protos").connect(ipv4.connector("node"))
94 node.connector("protos").connect(arp.connector("node"))
95 node.connector("protos").connect(icmp.connector("node"))
96 node.connector("protos").connect(udp.connector("node"))
99 def add_ns3_wifi(self, ns3_desc, node, access_point = False):
100 wifi = ns3_desc.create("ns3::WifiNetDevice")
101 node.connector("devs").connect(wifi.connector("node"))
103 phy = ns3_desc.create("ns3::YansWifiPhy")
104 error = ns3_desc.create("ns3::NistErrorRateModel")
105 manager = ns3_desc.create("ns3::ArfWifiManager")
107 mac = ns3_desc.create("ns3::ApWifiMac")
109 mac = ns3_desc.create("ns3::StaWifiMac")
111 phy.set_attribute_value("Standard", "WIFI_PHY_STANDARD_80211a")
112 mac.set_attribute_value("Standard", "WIFI_PHY_STANDARD_80211a")
113 phy.connector("err").connect(error.connector("phy"))
114 wifi.connector("phy").connect(phy.connector("dev"))
115 wifi.connector("mac").connect(mac.connector("dev"))
116 wifi.connector("manager").connect(manager.connector("dev"))
118 phy.enable_trace("YansWifiPhyPcapTrace")
121 def add_ns3_constant_mobility(self, ns3_desc, node, x, y, z):
122 mobility = ns3_desc.create("ns3::ConstantPositionMobilityModel")
123 position = "%d:%d:%d" % (x, y, z)
124 mobility.set_attribute_value("Position", position)
125 node.connector("mobility").connect(mobility.connector("node"))
128 def add_ns3_wifi_channel(self, ns3_desc):
129 channel = ns3_desc.create("ns3::YansWifiChannel")
130 delay = ns3_desc.create("ns3::ConstantSpeedPropagationDelayModel")
131 loss = ns3_desc.create("ns3::LogDistancePropagationLossModel")
132 channel.connector("delay").connect(delay.connector("chan"))
133 channel.connector("loss").connect(loss.connector("prev"))
136 def add_ip_address(self, iface, address, netprefix):
137 ip = iface.add_address()
138 ip.set_attribute_value("Address", address)
139 ip.set_attribute_value("NetPrefix", netprefix)
141 def add_route(self, node, destination, netprefix, nexthop):
142 route = node.add_route()
143 route.set_attribute_value("Destination", destination)
144 route.set_attribute_value("NetPrefix", netprefix)
145 route.set_attribute_value("NextHop", nexthop)
148 exp_desc = ExperimentDescription()
152 ns3_provider = FactoriesProvider("ns3")
153 ns3_desc = exp_desc.add_testbed_description(ns3_provider)
154 ns3_desc.set_attribute_value("homeDirectory", self.root_dir)
155 ns3_desc.set_attribute_value("SimulatorImplementationType", "ns3::RealtimeSimulatorImpl")
156 ns3_desc.set_attribute_value("ChecksumEnabled", True)
158 ## NS3 wifi network 32/27
160 wifi_chan = self.add_ns3_wifi_channel(ns3_desc)
163 ap = self.add_ns3_node(ns3_desc)
164 self.add_ns3_constant_mobility(ns3_desc, ap, 0, 0, 0)
166 wifi_ap, phy_ap = self.add_ns3_wifi(ns3_desc, ap, access_point = True)
167 self.add_ip_address(wifi_ap, (self.base_addr%33), 27)
168 phy_ap.connector("chan").connect(wifi_chan.connector("phys"))
173 for i in xrange(0, self.nsta):
174 stai = self.add_ns3_node(ns3_desc)
175 angi = (360/self.nsta)*i
176 xi = r*math.cos(angi)
177 yi = r*math.sin(angi)
178 self.add_ns3_constant_mobility(ns3_desc, stai, xi, yi, 0)
179 wifi, phy= self.add_ns3_wifi(ns3_desc, stai, access_point = False)
180 wifi_addr = self.base_addr%(34 + i)
181 self.add_ip_address(wifi, wifi_addr, 27)
182 phy.connector("chan").connect(wifi_chan.connector("phys"))
183 sta_nodes.append((stai, wifi_addr))
187 netns_provider = FactoriesProvider("netns")
188 netns_desc = exp_desc.add_testbed_description(netns_provider)
189 netns_desc.set_attribute_value("homeDirectory", self.root_dir)
190 netns_desc.set_attribute_value(DC.DEPLOYMENT_MODE, DC.MODE_DAEMON)
191 netns_root_dir = os.path.join(self.root_dir, "netns_instance")
192 os.mkdir(netns_root_dir)
193 netns_desc.set_attribute_value(DC.ROOT_DIRECTORY, netns_root_dir)
194 netns_desc.set_attribute_value(DC.LOG_LEVEL, DC.DEBUG_LEVEL)
195 netns_desc.set_attribute_value(DC.USE_SUDO, True)
197 server = netns_desc.create("Node")
198 server.set_attribute_value("forward_X11", True)
201 #app = netns_desc.create("Application")
202 #app.set_attribute_value("command", command)
203 #app.set_attribute_value("user", self.user)
204 #app.connector("node").connect(server.connector("apps"))
206 # INTERCONNECTION NETNS/NS3
208 tap = self.add_netns_tap(netns_desc, server)
209 fdnd_ap = self.add_ns3_fdnd(ns3_desc, ap)
210 fdnd_ap.connector("->fd").connect(tap.connector("fd->"))
211 ## net NS3::fdnd/NETNS::tap 224/30
212 self.add_ip_address(fdnd_ap, (self.base_addr%225), 30)
213 self.add_ip_address(tap, (self.base_addr%226), 30)
216 self.add_route(server, (self.base_addr%32), 27, (self.base_addr%225))
221 for (stai, wifi_addr) in sta_nodes:
223 nodei = netns_desc.create("Node")
224 nodei.set_attribute_value("forward_X11", True)
225 label = "client%d" % i
226 nodei.set_attribute_value("label", label)
227 tapi = self.add_netns_tap(netns_desc, nodei)
228 fdndi = self.add_ns3_fdnd(ns3_desc, stai)
229 fdndi.connector("->fd").connect(tapi.connector("fd->"))
231 ## net NS3::fdnd/NETNS::tap subnets of 64/27
233 self.add_ip_address(tapi, (self.base_addr%(net + 1)), 30)
234 self.add_ip_address(fdndi, (self.base_addr%(net + 2)), 30)
237 self.add_route(nodei, (self.base_addr%32), 27, (self.base_addr%(net+2)))
238 self.add_route(nodei, (self.base_addr%224), 30, (self.base_addr%(net+2)))
239 self.add_route(stai, (self.base_addr%224), 30, (self.base_addr%33))
241 self.add_route(ap, (self.base_addr%net), 30, wifi_addr)
242 self.add_route(server, (self.base_addr%net), 30, (self.base_addr%225))
245 #target = "{#[%s].addr[0].[Address]#}" % label
246 target = self.base_addr%(net+1)
247 port = 5000 + net + 1
248 command = "vlc -I dummy %s --sout '#rtp{dst=%s,port=%d,mux=ts}' vlc://quit" \
249 % (self.movie, target, port)
250 vlc_server = netns_desc.create("Application")
251 vlc_server.set_attribute_value("command", command)
252 vlc_server.set_attribute_value("user", self.user)
253 vlc_server.connector("node").connect(server.connector("apps"))
254 servers.append(vlc_server.guid)
256 command = "vlc rtp://%s:%d/test.ts" % (target, port)
257 vlc_client = netns_desc.create("Application")
258 vlc_client.set_attribute_value("command", command)
259 vlc_client.set_attribute_value("user", self.user)
260 vlc_client.connector("node").connect(nodei.connector("apps"))
261 clients.append(vlc_client.guid)
265 xml = exp_desc.to_xml()
266 controller = ExperimentController(xml, self.root_dir)
273 if not controller.is_finished(guid):
277 controller.shutdown()
280 shutil.rmtree(self.root_dir)
282 if __name__ == '__main__':
283 example = WirelessOverlay()