forked from scoutsaachi/poxStartup
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathnewGraphGen.py
205 lines (165 loc) · 6.47 KB
/
newGraphGen.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
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
import networkx
import random
import Queue
import pickle
explore = False
debug = False
bestTotalPort = 10
bestSwitchPort = 8
for totalPortSelect in range(6, 20):
for switchPortSelect in range(4, totalPortSelect):
if not explore:
if totalPortSelect != bestTotalPort or switchPortSelect != bestSwitchPort:
continue
if (totalPortSelect == switchPortSelect):
continue
numPorts = totalPortSelect # k in the paper
toSwitchPorts = switchPortSelect # r in the paper, also implicitly the degree
degree = toSwitchPorts
toServerPorts = numPorts - toSwitchPorts # k-r in the paper, also the number of servers per switch
numServers = 686
numSwitches = numServers / toServerPorts
if numServers % toServerPorts != 0:
numSwitches += 1
if (degree * numSwitches) % 2 != 0:
continue
kShortest = 8
sourceServers = [i for i in range(numServers)]
targetServers = [-1 for i in range(numServers)]
serversToSwitches = {}
for server in range(numServers):
serversToSwitches[server] = server / toServerPorts
kShortestCounts = {}
ECMP8Counts = {}
ECMP64Counts = {}
redo = False
first = True
def BFS(sourceSwitch, targetSwitch):
source = sourceSwitch
target = targetSwitch
topK = []
candidates = []
candidates.append([source])
doneWithECMP = False
while (len(topK) < kShortest or not doneWithECMP) and len(candidates) > 0 and len(candidates) < 20000:
current = candidates.pop(0)
if len(topK) >= kShortest and len(current) + 1 > len(topK[0]):
return topK
neighbors = list(graph[current[len(current) - 1]].keys())
random.shuffle(neighbors)
# Skip neighbors already in the partial path to avoid loops
for i in range(len(neighbors)):
if neighbors[i] in current:
continue
new_current = list(current)
new_current.append(neighbors[i])
if neighbors[i] == target:
topK.append(new_current)
if len(new_current) > len(topK[0]) or len(topK) >= 64:
doneWithECMP = True
else:
candidates.append(new_current)
return topK
# Generate the random traffic permutation
print "Generating random traffic permutation"
while first or redo:
unused = set(sourceServers)
first = False
for source in range(len(sourceServers)):
target = source
while target == source:
target = random.sample(unused, 1)[0]
if target == source and len(unused) == 1:
break
if (target == source):
redo = True
if debug:
print "Had to restart the graph gen"
break;
else:
targetServers[source] = target
unused.remove(target)
# Generate the degree regular random graph
graph = networkx.random_regular_graph(degree, numSwitches)
# Initialize the link counts
for edge in graph.edges():
kShortestCounts[tuple([edge[0], edge[1]])] = 0
kShortestCounts[tuple([edge[1], edge[0]])] = 0
ECMP8Counts[tuple([edge[0], edge[1]])] = 0
ECMP8Counts[tuple([edge[1], edge[0]])] = 0
ECMP64Counts[tuple([edge[0], edge[1]])] = 0
ECMP64Counts[tuple([edge[1], edge[0]])] = 0
# Start computing the shortest paths
print "Computing shortest paths for k = " + str(totalPortSelect) + " and r = " + str(switchPortSelect) + "..."
for sourceServer in range(len(sourceServers)):
if sourceServer % 100 == 0:
print "Computing path for server " + str(sourceServer)
source = serversToSwitches[sourceServer]
targetServer = targetServers[sourceServer]
target = serversToSwitches[targetServer]
if source == target:
if debug:
print "Sending to a server on the same rack"
continue
if debug:
print "Starting k shortest for path " + str(source)
paths = BFS(source, target)
if debug:
print "Length of path vector is " + str(len(paths))
if len(paths) == 0:
print "Graph is not fully connected"
continue
minLen = len(paths[0])
kShortestUpperBound = min(kShortest, len(paths))
for i in range(0, kShortestUpperBound):
currentPath = paths[i]
for j in range(len(currentPath) - 1):
link = tuple([currentPath[j], currentPath[j+1]])
kShortestCounts[link] += 1
if debug:
if kShortestCounts[link] > 100:
print "Link " + link + " is greater than 100"
if len(currentPath) == minLen:
ECMP8Counts[link] += 1
ECMP64Counts[link] += 1
if len(paths) > kShortest:
for i in range(kShortest, len(paths)):
currentPath = paths[i]
if len(currentPath) > minLen:
break
for j in range(len(currentPath) - 1):
link = tuple([currentPath[j], currentPath[j+1]])
ECMP64Counts[link] += 1
print "Done computing shortest paths"
kShortestBuckets = [0 for i in range(1000)]
ECMP8Buckets = [0 for i in range(1000)]
ECMP64Buckets = [0 for i in range(1000)]
for key, value in kShortestCounts.items() :
kShortestBuckets[value] += 1
for key, value in ECMP8Counts.items() :
ECMP8Buckets[value] += 1
for key, value in ECMP64Counts.items() :
ECMP64Buckets[value] += 1
for i in range(len(kShortestBuckets)):
if kShortestBuckets[i] == 0:
continue
print "k-Shortest: Num on " + str(i) + " paths: " + str(kShortestBuckets[i])
if debug:
if i > 80:
print "Testing"
for key, value in kShortestCounts.items():
if value == i:
print "Link in question was " + str(key)
print "\n"
for i in range(len(ECMP8Buckets)):
if ECMP8Buckets[i] == 0:
continue
print "ECMP-8: Num on " + str(i) + " paths: " + str(ECMP8Buckets[i])
print "\n"
for i in range(len(ECMP64Buckets)):
if ECMP64Buckets[i] == 0:
continue
print "ECMP-64: Num on " + str(i) + " paths: " + str(ECMP64Buckets[i])
buckets = [kShortestBuckets, ECMP8Buckets, ECMP64Buckets]
with open('k' + str(totalPortSelect) + 'r' + str(switchPortSelect) + '.pickle', 'wb') as handle:
pickle.dump(buckets, handle, protocol=pickle.HIGHEST_PROTOCOL)