如何计算IP子网之间的差距?

时间:2017-11-20 10:59:28

标签: algorithm math networking logarithm subnet

计算输入IP子网之间所有间隙的最有效算法是什么?

示例输入

192.168.1.24 / 29
192.168.1.40 / 30
192.168.1.64 / 28

示例输出

192.168.1.0 / 28   <--- auto-created
192.168.1.16 / 29  <--- auto-created
192.168.1.24 / 29  <--- INPUT
192.168.1.32 / 29  <--- auto-created
192.168.1.40 / 30  <--- INPUT
192.168.1.44 / 30  <--- auto-created
192.168.1.48 / 28  <--- auto-created
192.168.1.64 / 28  <--- INPUT
192.168.1.80 / 28  <--- auto-created
192.168.1.96 / 27  <--- auto-created
192.168.1.128 / 25 <--- auto-created

迄今为止的研究:

步骤1.对于输入对:192.168.1.0 / 28,192.168.1.24 / 29

让我们计算IP子网的数字表示之间的差异:

diff = 3232235800 - 3232235776 = 24

然后计算基数2中的对数:

log2 = log2(24) = 4.58

然后我们可以计算CIDR和子网长度:

cidr = 32 - 4 = 28
ipStart = 3232235776 
ipEnd = 3232235776 + 2^4 - 1 = 3232235776 + 15 = 3232235791

所以我们添加到列表中:

192.168.1.0/28

但是仍然存在差距:

diff = 3232235800 - 3232235792 = 8
log2 = log2(8) = 3
cidr = 32-3=29
ipStart = 3232235792
ipEnd = 3232235799

所以我们添加第二个:

192.168.1.16/29

等等。但是,有没有更有效的方法来找到差距并生成子网?

1 个答案:

答案 0 :(得分:0)

假设子网按升序列出。我们考虑32位二进制字符串s以及相应子网掩码的长度n。

考虑长度为n的s的前缀。通过在此前缀表示的数字上加1,我们获得下一个子网中第一个地址的前缀。要想看到这一点,想象用1s填充前缀右侧的所有内容;这是s子网中可能的最大地址,因此下一个地址必须位于下一个子网中。将1添加到子网掩码中的地址部分,因此我们可以直接考虑这一点。

这为我们提供了我们需要的位字符串,但它并没有告诉我们相应子网掩码的长度n。当然,n必须至少足够长,以包括我们获得的字符串的所有非零数字。否则,可以显示我们将在当前子网中包含地址。但是,我们可能需要更多的0来避免与列表中的下一个子网重叠。我们还必须确保保留足够的零,以便我们的新子网与列表中的下一个子网至少有一个数字不同:下一个地址中的最后一个非零数字。

以下是您问题的一个示例:

192.168.1.24 / 29
192.168.1.40 / 30
192.168.1.64 / 28

我们将这些视为

11000000 10101000 00000001 00011000 / 29
11000000 10101000 00000001 00101000 / 30
11000000 10101000 00000001 01000000 / 28

现在,考虑第一个

11000000 10101000 00000001 00011000 / 29

我们考虑长度为29的前缀:

11000000 10101000 00000001 00011

添加一个:

11000000 10101000 00000001 00100

我们的n必须至少为27.要查看是否需要更长时间,请考虑列表中的下一个子网:

11000000 10101000 00000001 00101000 / 30
11000000 10101000 00000001 00100
                               ^

我们的子网与第29个位置的下一个子网不同,后者也是下一个子网中最右边的非零位置。因此,n = 29;我们创建了一个新的子网:

11000000 10101000 00000001 00100000 / 29

如果我们对刚刚创建的子网应用相同的过程,我们会发现我们生成的完全相同的前缀与原始列表中的下一个子网相对应。我们可以检测到这一点,并认识到这意味着这里不再有填补空白,继续前进。

下一个子网是

11000000 10101000 00000001 00101000 / 30

长度为30的前缀是

11000000 10101000 00000001 001010

添加一个:

11000000 10101000 00000001 001011

与下一个子网比较:

11000000 10101000 00000001 01000000 / 28
11000000 10101000 00000001 001011

我们必须至少选择n = 30,所以我们得到子网:

11000000 10101000 00000001 00101100 / 30

考虑长度为30的前缀并添加一个:

11000000 10101000 00000001 001011
+                               1
=================================
11000000 10101000 00000001 001100

与下一个比较:

11000000 10101000 00000001 01000000 / 28
11000000 10101000 00000001 001100

我们必须有n至少28,所以我们得到

11000000 10101000 00000001 00110000 / 28

考虑长度为28的子字符串,添加一个,我们得到的属性字符串与原始列表中的下一个子网相同。我们认识到这意味着我们填补了空白,因此我们继续前进。

我们正在查看最后一个原始输入,因此无需填写任何内容。完成。我们的子网:

11000000 10101000 00000001 00011000 / 29
11000000 10101000 00000001 00100000 / 29 <<<
11000000 10101000 00000001 00101000 / 30
11000000 10101000 00000001 00101100 / 30 <<<
11000000 10101000 00000001 00110000 / 28 <<<
11000000 10101000 00000001 01000000 / 28

请注意,这不会在提供的输入之外创建子网范围。如果要这样做,您的算法可以在列表中添加最小子网,并将最大子网附加到列表中。让最小子网为0.0.0.0/1,最小子网为255.255.255.255/32作为最大子网:

00000000 00000000 00000000 00000000 / 1
0
+1
=1
 11000000 10101000 00000001 00011000 / 29
  ^
 => n = 2
 => 10000000 00000000 00000000 00000000 / 2    <<<<<<<<<

10000000 00000000 00000000 00000000 / 2
10
+1
=11
 11000000 10101000 00000001 00011000 / 29
          ^
=> n = 9
=> 11000000 00000000 00000000 00000000 / 9    <<<<<<<<<

11000000 00000000 00000000 00000000 / 9
11000000 0
+1
= 11000000 1
  11000000 10101000 00000001 00011000 / 29
             ^
=> n = 11
=> 11000000 10000000 00000000 00000000 / 11    <<<<<<<<<

11000000 10000000 00000000 00000000 / 11
11000000 100
+1
= 11000000 101
  11000000 10101000 00000001 00011000 / 29
               ^
=> n = 13
=> 11000000 10100000 00000000 00000000 / 13    <<<<<<<<<

11000000 10100000 00000000 00000000 / 13
11000000 10100
+1
= 11000000 10101
  11000000 10101000 00000001 00011000 / 29
                           ^
=> n = 24
=> 11000000 10101000 00000000 00000000 / 24    <<<<<<<<<

11000000 10101000 00000000 00000000 / 24
11000000 10101000 00000000
+1
= 11000000 10101000 00000001
  11000000 10101000 00000001 00011000 / 29
                                ^
=> n = 28
=> 11000000 10101000 00000001 00000000 / 28    <<<<<<<<<

11000000 10101000 00000001 00000000 / 28
11000000 10101000 00000001 0000
+1
= 11000000 10101000 00000001 0001
  11000000 10101000 00000001 00011000 / 29
                                 ^
=> n = 29
=> 11000000 10101000 00000001 00010000 / 29    <<<<<<<<<

下一个将为我们提供第一个真正的输入子网。子网现在是:

00000000 00000000 00000000 00000000 / 1  <<<
10000000 00000000 00000000 00000000 / 2  <<<
11000000 00000000 00000000 00000000 / 9  <<<
11000000 10000000 00000000 00000000 / 11 <<<
11000000 10100000 00000000 00000000 / 13 <<<
11000000 10101000 00000000 00000000 / 24 <<<
11000000 10101000 00000001 00000000 / 28 <<<
11000000 10101000 00000001 00010000 / 29 <<<

11000000 10101000 00000001 00011000 / 29
11000000 10101000 00000001 00100000 / 29 <<<
11000000 10101000 00000001 00101000 / 30
11000000 10101000 00000001 00101100 / 30 <<<
11000000 10101000 00000001 00110000 / 28 <<<
11000000 10101000 00000001 01000000 / 28

我们可以在另一端重复练习:

11000000 10101000 00000001 01000000 / 28
11000000 10101000 00000001 0100
+1
= 11000000 10101000 00000001 0101
  11111111 11111111 11111111 11111111
                                ^
=> n = 28 (must include rightmost 1 of s + 1)
=> 11000000 10101000 00000001 01010000 / 28    <<<<<<<

11000000 10101000 00000001 01010000 / 28
11000000 10101000 00000001 0101
+1
= 11000000 10101000 00000001 0110
  11111111 11111111 11111111 11111111
                               ^
=> n = 27
=> 11000000 10101000 00000001 01100000 / 27    <<<<<<<

11000000 10101000 00000001 01100000 / 27
11000000 10101000 00000001 011
+1
= 11000000 10101000 00000001 100
  11111111 11111111 11111111 11111111
                             ^
=> n = 25
=> 11000000 10101000 00000001 10000000 / 25    <<<<<<<

11000000 10101000 00000001 10000000 / 25
11000000 10101000 00000001 1
+1
= 11000000 10101000 00000010 0
  11111111 11111111 11111111 11111111
                           ^
=> n = 23
=> 11000000 10101000 00000010 00000000 / 23    <<<<<<<

不是列出所有的术语,因为它会变得单调,我们可以注意到当我们有0个字符串时,我们将把n减少一个并向左移动最右边的一个空格。所以,我们跳过:

=> 11000000 10101000 00000100 00000000 / 22    <<<<<<<
=> 11000000 10101000 00001000 00000000 / 21    <<<<<<<
=> 11000000 10101000 00010000 00000000 / 20    <<<<<<<
=> 11000000 10101000 00100000 00000000 / 19    <<<<<<<
=> 11000000 10101000 01000000 00000000 / 18    <<<<<<<
=> 11000000 10101000 10000000 00000000 / 17    <<<<<<<
=> 11000000 10101001 00000000 00000000 / 16    <<<<<<<
=> 11000000 10101010 00000000 00000000 / 15    <<<<<<<
=> 11000000 10101100 00000000 00000000 / 14    <<<<<<<

我们注意到01 ^ k变为10 ^ k,n减少了k;所以我们再次跳过添加

=> 11000000 10110000 00000000 00000000 / 12    <<<<<<<
=> 11000000 11000000 00000000 00000000 / 10    <<<<<<<
=> 11000001 00000000 00000000 00000000 / 8     <<<<<<<

回到规则#1:

=> 11000010 00000000 00000000 00000000 / 7     <<<<<<<
=> 11000100 00000000 00000000 00000000 / 6     <<<<<<<
=> 11001000 00000000 00000000 00000000 / 5     <<<<<<<
=> 11010000 00000000 00000000 00000000 / 4     <<<<<<<

下一步,我们得到一个与我们范围的末尾相匹配的子网,因此我们必须包含一个额外的零,以使其不同:

=> 11100000 00000000 00000000 00000000 / 4     <<<<<<<

如果我们真的关心255.255.255.255子网,正确的方法是通过每次增加n和1的数量来继续这个,以获得更多的27个子网。但是,如果我们只是想填补空白,我们可以认识到我们目前的状况并添加:

=> 11110000 00000000 00000000 00000000 / 4     <<<<<<<<

这涵盖了范围的其余部分,包括 255.255.255.255,因此它不是解决增强问题本身的问题,但它确实解决了填补空白的原始问题。我们的完整清单如下:

00000000 00000000 00000000 00000000 / 1  <<<
10000000 00000000 00000000 00000000 / 2  <<<
11000000 00000000 00000000 00000000 / 9  <<<
11000000 10000000 00000000 00000000 / 11 <<<
11000000 10100000 00000000 00000000 / 13 <<<
11000000 10101000 00000000 00000000 / 24 <<<
11000000 10101000 00000001 00000000 / 28 <<<
11000000 10101000 00000001 00010000 / 29 <<<

11000000 10101000 00000001 00011000 / 29
11000000 10101000 00000001 00100000 / 29 <<<
11000000 10101000 00000001 00101000 / 30
11000000 10101000 00000001 00101100 / 30 <<<
11000000 10101000 00000001 00110000 / 28 <<<
11000000 10101000 00000001 01000000 / 28

11000000 10101000 00000001 01010000 / 28 <<<
11000000 10101000 00000001 01100000 / 27 <<<
11000000 10101000 00000001 10000000 / 25 <<<
11000000 10101000 00000010 00000000 / 23 <<<
11000000 10101000 00000100 00000000 / 22 <<<
11000000 10101000 00001000 00000000 / 21 <<<
11000000 10101000 00010000 00000000 / 20 <<<
11000000 10101000 00100000 00000000 / 19 <<<
11000000 10101000 01000000 00000000 / 18 <<<
11000000 10101000 10000000 00000000 / 17 <<<
11000000 10101001 00000000 00000000 / 16 <<<
11000000 10101010 00000000 00000000 / 15 <<<
11000000 10101100 00000000 00000000 / 14 <<<
11000000 10110000 00000000 00000000 / 12 <<<
11000000 11000000 00000000 00000000 / 10 <<<
11000001 00000000 00000000 00000000 / 8  <<<
11000010 00000000 00000000 00000000 / 7  <<<
11000100 00000000 00000000 00000000 / 6  <<<
11001000 00000000 00000000 00000000 / 5  <<<
11010000 00000000 00000000 00000000 / 4  <<<
11100000 00000000 00000000 00000000 / 3  <<<

如上所述,我没有两个/ 4个子网,而是将一个/ 3子网放在此列表中,因为它是等效的。