我在计算网络中可用子网(或主机)的数量时遇到了以下问题。例如,主子网是/ 24(255.255.255.0),其中包含两个/ 25(255.255.255.128)或四个/ 26(255.255.255.192)。
因此,如果一个节点已经被使用,那么将只有一个/ 25个或只有3个/ 26个。那么我应该如何计算可用子网的数量。换句话说,如何获得剩余的数量和类型。 我想在PHP中执行此算法。
答案 0 :(得分:1)
我使用python来解决这个问题(所有代码都附加了,最后是整个脚本),但我确信PHP的解决方案存在类似的库。由于这是旧的并且没有发布解决方案,我猜测任何解决方案(在这种情况下,Python解决方案)都比没有解决方案更好。
该脚本由两个函数组成,一个计算" main"中的可用子网。使用BFS的子网,另一个使用graphviz创建pdf绘图。
我使用的算法是一个非常简单的BFS。它基本上从顶部子网(" main",/ 24)开始,并查明是否有任何使用过的("采用的")子网与它重叠/匹配。如果他们中的任何一个做了,那么算法会将它排在队列中,并且#34;孩子们会#34; (/ 25)在同一过程中检查。如果算法击中没有"采取的子网"儿童被标记为"可用"。如果它击中的子网与"采取的"完全匹配它标记为"采取"。在任何其他情况下,迭代继续。
可视化的绘制过程是相同的。
这是脚本描述(argparse-generated):
usage: script.py [-h] -m M -t TAKEN [TAKEN ...] -o OUTPUT
optional arguments:
-h, --help show this help message and exit
-m M, --m M main subnet to check
-t TAKEN [TAKEN ...], --taken TAKEN [TAKEN ...]
taken subnets
-o OUTPUT, --output OUTPUT
graphviz output file name (.pdf)
使用您的参数运行脚本:
subnet_script.py -m 255.255.255.0/24 -t 255.255.255.192/26 -o test
给出了这些结果:
做一些更有趣的事情,如:
script.py -m 255.255.255.0/24 -t 255.255.255.192/26 255.255.255.128/30 -o test
给出了这些结果:
我已经使用了ipaddress,queue和graphviz(用于python)模块,以及argparse来使脚本更好用。< / p>
第一个功能:
def get_available_subnets_set(main, taken):
# we assume no subnets are available intially
available = []
q = queue.Queue()
# add first node for expansion in the BFS process
q.put(main)
while q.qsize() > 0:
subnet = q.get()
for taken_subnet in taken:
if taken_subnet.compare_networks(subnet) == 0:
# found matching subnet in taken, stop expanding
print("similar: %s and %s" % (subnet, taken_subnet))
break
if taken_subnet.overlaps(subnet):
# still has overlaps somewhere in children, keep expanding
print("overlaps: %s and %s" % (subnet, taken_subnet))
for sub_subnet in subnet.subnets():
q.put(sub_subnet)
break
else:
# no overlaps with taken - this subnet is entirely available
available.append(subnet)
return set(available)
第二个函数以类似的方式使用graphviz绘制结果:
def make_subnet_graph(main, taken_subnets, available_subnets, filename):
g = graphviz.Graph()
q = queue.Queue()
q.put(main)
g.node(str(main))
while q.qsize() > 0:
subnet = q.get()
for sub_subnet in subnet.subnets():
if sub_subnet in available_subnets:
# draw as available (green)
g.node(str(sub_subnet), _attributes={"color": "green"})
g.edge(str(sub_subnet), str(subnet))
continue
if sub_subnet in taken_subnets:
# draw as taken (red)
g.node(str(sub_subnet), _attributes={"color": "red"})
g.edge(str(sub_subnet), str(subnet))
continue
# has mixed type subnets (taken / available) - go deeper
g.node(str(sub_subnet))
g.edge(str(sub_subnet), str(subnet))
q.put(sub_subnet)
# write file
g.render(filename)
与argparse一起整个事情:
#!/usr/bin/env python3.4
import ipaddress
import argparse
import queue
import graphviz
def get_available_subnets(main, taken):
# we assume no subnets are available intially
available = []
q = queue.Queue()
# add first node for expansion in the BFS process
q.put(main)
while q.qsize() > 0:
subnet = q.get()
for taken_subnet in taken:
if taken_subnet.compare_networks(subnet) == 0:
# found matching subnet in taken, stop expanding
print("similar: %s and %s" % (subnet, taken_subnet))
break
if taken_subnet.overlaps(subnet):
# still has overlaps somewhere in children, keep expanding
print("overlaps: %s and %s" % (subnet, taken_subnet))
for sub_subnet in subnet.subnets():
q.put(sub_subnet)
break
else:
# no overlaps with taken - this subnet is entirely available
available.append(subnet)
return available
def make_subnet_graph(main, taken_subnets, available_subnets, filename):
g = graphviz.Graph()
q = queue.Queue()
q.put(main)
g.node(str(main))
while q.qsize() > 0:
subnet = q.get()
for sub_subnet in subnet.subnets():
if sub_subnet in available_subnets:
# draw as available (green)
g.node(str(sub_subnet), _attributes={"color": "green"})
g.edge(str(sub_subnet), str(subnet))
continue
if sub_subnet in taken_subnets:
# draw as taken (red)
g.node(str(sub_subnet), _attributes={"color": "red"})
g.edge(str(sub_subnet), str(subnet))
continue
# has mixed type subnets (taken / available) - go deeper
g.node(str(sub_subnet))
g.edge(str(sub_subnet), str(subnet))
q.put(sub_subnet)
# write file
g.render(filename)
if "__main__" == __name__:
parser = argparse.ArgumentParser()
parser.add_argument('-m', '--m', help='main subnet to check', required=True)
parser.add_argument('-t', '--taken', nargs='+', help='taken subnets', required=True)
parser.add_argument('-o', '--output', help='graphviz output file name (.pdf)', required=True)
args = parser.parse_args()
taken = [ipaddress.IPv4Network(subnet) for subnet in args.taken]
main = ipaddress.IPv4Network(args.m)
available = get_available_subnets_set(main, taken)
make_subnet_graph(main, taken, available, args.output)