-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmininet_functions.py
executable file
·128 lines (103 loc) · 5.3 KB
/
mininet_functions.py
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
import logging
import os
import re
from numpy import random
from mininet.clean import Cleanup
from mininet.net import Mininet
from mininet.link import TCLink
from mininet.log import setLogLevel
from mininet.node import CPULimitedHost
from mininet.topo import Topo
class TreeTopoGeneric(Topo):
""""Generic Tree topology."""
def __init__(self, spread, depth, bandwidth, delay, loss, fpga, fpga_bandwidth=None, fpga_delay=None,
fpga_loss=None, poisson=None):
""""Create tree topology according to given parameters."""
logger = logging.getLogger(__name__)
# Initialize topology #
Topo.__init__(self)
# Setup parameters
fpga_bandwidth = bandwidth if fpga_bandwidth is None else fpga_bandwidth
fpga_delay = delay if fpga_delay is None else halve_delay(fpga_delay)
fpga_loss = loss * 2 if fpga_loss is None else fpga_loss
if poisson:
link_opts = dict(bw=bandwidth, delay=get_poisson_delay(delay), loss=loss, use_htb=True)
fpga_link_opts = dict(bw=fpga_bandwidth, delay=get_poisson_delay(fpga_delay),
loss=fpga_loss, use_htb=True)
else:
link_opts = dict(bw=bandwidth, delay=delay, loss=loss, use_htb=True)
fpga_link_opts = dict(bw=fpga_bandwidth, delay=fpga_delay, loss=fpga_loss, use_htb=True)
cloud_link_opts = dict(bw=1000, delay='0ms', loss=0, use_htb=True)
# Add hosts and switches #
# switch naming convention:
# s[level][switch_number]
switches = [[None for _ in range(spread ** (depth - 1))] for _ in range(depth - 1)]
hosts = [None for _ in range(spread ** (depth - 1))]
for i in range(depth):
for j in range(spread ** i):
if i == (depth - 1):
hosts[j] = self.addHost('h' + str(j))
else:
sw_name = 's' + str(i) + str(j)
switches[i][j] = self.addSwitch(sw_name)
if fpga is not None and fpga == i:
# Create host to serve as FPGA in switch
# Will have one link to the relevant FPGA
# The link will have the bandwidth and loss specified by the user, and half
# the delay
# These parameters are as if they were caused by the FPGA, rather than a
# link
# As a result, latency is halved since it will essentially be doubled by the
# packet flowing in
# and out of the host
self.addHost('f{}'.format(j))
self.addLink(sw_name, 'f{}'.format(j), **fpga_link_opts)
# Add host to serve as cloud
# Will have one high bandwidth, 0 latency link to root switch
self.addHost('cloud')
self.addLink(switches[0][0], 'cloud', **cloud_link_opts)
# Add links #
for i, row in enumerate(switches):
for j, switch in enumerate(row):
if switch is None:
break
if i == (depth - 2):
for k in range(spread):
# add a link between the current switch, and all hosts
# directly beneath it.
# (spread * j) + k will get all the appropriate hosts
logger.debug("Adding standard link from switch[{}][{}] to "
"host[{}]".format(i, j, (spread * j) + k))
self.addLink(switch, hosts[(spread * j) + k], **link_opts)
else:
for k in range(spread):
# add a link between the current switch, and all
# switches directly beneath it.
# i + 1 refers to 1 level deeper in the tree, and
# (spread * j) + k will get all the appropriate child
# switches on that level.
logger.debug("Adding standard link from switch[{}][{}] to "
"switch[{}][{}]".format(i, j, i + 1, (spread * j) + k))
self.addLink(switch, switches[i + 1][(spread * j) + k], **link_opts)
def get_poisson_delay(delay):
"""Returns a Poisson distributed delay of the given delay."""
valid_time = re.compile('^([-+]?[0-9]*\.?[0-9]+)([PTGMkmunpf]?s)$')
match = valid_time.match(delay)
poisson = random.poisson(float(match.group(1)))
return "{}{}".format(poisson, match.group(2))
def halve_delay(delay):
valid_time = re.compile('^([-+]?[0-9]*\.?[0-9]+)([PTGMkmunpf]?s)$')
match = valid_time.match(delay)
half = float(match.group(1)) / 2
return "{}{}".format(half, match.group(2))
def setup_mininet(log, spread, depth, bandwidth, delay, loss, fpga, fpga_bandwidth, fpga_delay,
fpga_loss, poisson):
"""Run tasks to setup and start the mininet environment."""
Cleanup.cleanup()
setLogLevel(log)
# Create network
topo = TreeTopoGeneric(spread, depth, bandwidth, delay, loss, fpga, fpga_bandwidth, fpga_delay,
fpga_loss, poisson)
net = Mininet(topo=topo, host=CPULimitedHost, link=TCLink, autoStaticArp=True)
net.start()
return net