2014-07-15 72 views
4

在計算網絡中可用子網(或主機)的數量時,存在以下問題。例如,主子網是/ 24(255.255.255.0),其中包含兩個/ 25(255.255.255.128)或四個/ 26(255.255.255.192)。計算給定網絡中可用子網的數量

所以,如果一個節點已被使用,將只有一個/ 25或只有3次/ 26。那麼我應該如何計算可用子網的數量。換句話說,如何獲得剩餘數量和類型。 我想在PHP中執行此算法。 enter image description here

回答

1

我用python解決了這個問題(所有的代碼都附加了,整個腳本到最後),但是我確定PHP的解決方案存在類似的庫。由於這是舊的,沒有解決方案發布,我猜任何解決方案(在這種情況下,Python解決方案)比沒有解決方案好。

該腳本由兩個功能組成,一個使用BFS計算「主」子網內的可用子網,另一個使用graphviz創建pdf圖形。

我使用的算法是一個非常簡單的BFS。它基本上從頂級子網(「main」,/ 24)開始,並查明是否有任何已使用(「已採納」)的子網與其重疊/匹配。如果它們中的任何一個都存在,則該算法排隊它的「孩子」(/ 25)以在相同的過程中被檢查。如果算法遇到沒有「被採納」子的子網,它將被標記爲「可用」。如果它擊中與「採取」完全匹配的子網,則將其標記爲「採取」。在任何其他情況下,迭代繼續。

可視化的繪製過程是相同的。

這裏是腳本描述(argparse生成):

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 

給出了這些結果:

results

做有點像更有趣的事:

script.py -m 255.255.255.0/24 -t 255.255.255.192/26 255.255.255.128/30 -o test 

給出了這些結果:

a bit more interesting results

我用過的ipaddressqueuegraphviz(對於Python)模塊,以及argparse使腳本更好用。

第一功能:

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) 

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繪製結果