1. leaf-spine tree
主要过程就是构造一个树字典,随机构成一个receiver和多个sender,然后根据生成的sender和receiver就可以知道leaf的位置,然后构成sender_host->sender_leaf->spine->recv_leaf->receiver_host的过程。
如果在同一个leaf下,只需要sender_host->sender_leaf->receiver_host。
def gen_leaf_spine_tree(spine_num, leaf_num, host_num_per_leaf, sender_num):
host_num = host_num_per_leaf * leaf_num # 总用户数
hosts = random.sample(range(host_num), sender_num + 1) # 所需用户数
recv_host = random.choice(hosts) # 选择一个receiver
recv_leaf = 'L{0}'.format(recv_host // host_num_per_leaf)
tree = {recv_leaf: set(['H{0}'.format(recv_host), ])} # receiver叶子指向receiver主机
sender_host = [n for n in hosts if n != recv_host] # 剩余都为发送者
sender_leaf_nodes = set()
for i in sender_host: # 为每一个发送主机指向对应叶子
leaf_s = 'L{0}'.format(i // host_num_per_leaf)
tree.setdefault('H{0}'.format(i), set()).add(leaf_s)
sender_leaf_nodes.add(leaf_s)
sender_leaf_nodes.discard(recv_leaf)
if len(sender_leaf_nodes) > 0: # 为每一个发送叶子分配spine
for ls in sender_leaf_nodes:
spine = 'S{0}'.format(random.randint(0, spine_num - 1))
tree.setdefault(ls, set()).add(spine)
tree.setdefault(spine, set()).add(recv_leaf)
for key in tree.keys():
tree[key] = list(tree[key])
return tree
2. fat tree
从论文中,每个交换机最大连接数是k,共有(k/2)2个core switch,每个pod中有k/2个aggregation switch和edge switch,因此除去与edge switch的端口连接,aggregation switch还有k/2个端口与core switch相连。因此,k/2个aggregation switch的( k / 2 )*( k / 2 )个端口正好与(k/2)2个core switch相连。
那么,在某个pod中的aggregation switch的序号为 aggre_seq = core_s // aggre_num。
还要在考虑edge和pod的关系,其实就是pod_seq = edge // edge_per_pod
def gen_fat_tree(k, sender_num):
pod_num = k
core_num = int((k / 2) ** 2)
aggre_per_pod = edge_per_pod = host_per_edge = int(k / 2)
# print(type(aggre_per_pod), type(core_num))
host_num = int(pod_num * edge_per_pod * host_per_edge)
hosts = random.sample(range(host_num), sender_num + 1) # 所需用户数
recv_host = random.choice(hosts) # 选择一个receiver
recv_edge = recv_host // host_per_edge
recv_pod_seq = recv_edge // edge_per_pod
tree = {'E{0}'.format(recv_edge): set(['H{0}'.format(recv_host), ])}
sender_host = [n for n in hosts if n != recv_host] # 剩余都为发送者
sender_edge_nodes = set()
for i in sender_host: # 为每一个发送主机指向对应edge
edge_s = i // host_per_edge
tree.setdefault('H{0}'.format(i), set()).add('E{0}'.format(edge_s))
sender_edge_nodes.add(edge_s)
sender_edge_nodes.discard(recv_edge) # 只给在不是接收edge下的edge分配core
if (len(sender_edge_nodes) > 0):
for se in sender_edge_nodes:
core_s = random.randint(0, core_num - 1) # 随机得到core层的switch序号
aggre_seq = core_s // aggre_per_pod
sender_pod_seq = se // edge_per_pod
sender_aggre_seq = sender_pod_seq * aggre_per_pod + aggre_seq # 计算发送端aggre层的switch序号
recv_aggre_seq = recv_pod_seq * aggre_per_pod + aggre_seq # 计算接收端aggre层的switch序号
if (recv_pod_seq == sender_pod_seq):
# 直接连接E->A->E,不需要C
tree.setdefault('E{0}'.format(se), set()).add('A{0}'.format(sender_aggre_seq))
tree.setdefault('A{0}'.format(sender_aggre_seq), set()).add('E{0}'.format(recv_edge))
else:
# 连接发送端E->A->C
tree.setdefault('E{0}'.format(se), set()).add('A{0}'.format(sender_aggre_seq))
tree.setdefault('A{0}'.format(sender_aggre_seq), set()).add('C{0}'.format(core_s))
# 连接接收端C->A->E
tree.setdefault('C{0}'.format(core_s), set()).add('A{0}'.format(recv_aggre_seq))
tree.setdefault('A{0}'.format(recv_aggre_seq), set()).add('E{0}'.format(recv_edge))
for key in tree.keys():
tree[key] = list(tree[key])
return tree