我有一个VPC,让我们说它的CIDR块是10.0.0.0/16。我在那个VPC中有几个随机子网。他们的CIDR可能类似于10.0.128.0 / 19,10.0.32.0 / 19,10.0.208.0/22。子网的CIDR块必须由VPC的CIDR块覆盖。此外,不允许子网之间的CIDR重叠。
我的问题是: 鉴于这样的VPC和子网,如何为我想要创建的新子网找到具有特定大小的良好 CIDR块(假设为/ 22)。从我的角度来看,好意味着更好地利用空间。假设我只想要一个小的CIDR块,它不应该在VPC CIDR的中间返回一个CIDR,这可以防止将来放置潜在的大CIDR块。欢迎好的其他定义。任何初始状态都不能保证。
我不知道是否有针对此类问题的标准算法。我目前正在考虑的是使用二叉树。左子项表示0,右子表示1.所有叶子表示正在使用的CIDR块。要获得新的CIDR块,问题基本上是在某个级别创建一个离开取决于所需的块大小。如何创建一个好叶子我还不知道。
顺便说一下,我正在编写Java代码。我找不到这个库。如果有现有的图书馆,请告诉我!
答案 0 :(得分:1)
二叉树是正确的结构,但它不需要下到叶级别。只在需要时将其取下。树中的每个叶子表示分配或可用块。根据定义,每个CIDR块的大小是2的幂。因此,如果一个节点/块有子节点,它只有两个。如果节点有子节点(不是叶子),则其块不可用。
所以,你的顶级块及其初始分配就像这样(为了便于绘制而从左边缘表示的树。***
标记已分配的块。[我可能在这里找到了一些东西,但是基本的想法应该是清楚的:每个/ 16有两个/ 17个孩子,每个/ 17有两个/ 18个孩子,等等,除非该节点可用,在这种情况下它没有孩子。]):
/---- 10.0.0.0/19
|
/--- 10.0.0.0/18
| |
| \---- 10.0.32.0/19***
|
/--- 10.0.0.0/17
| \
| ---- 10.0.64.0/18
|
10.0.0.0/16
|
| /---- 10.0.128.0/19***
| |
| /---- 10.0.128.0/18
| | |
| | \---- 10.0.160.0/19
| |
\--- 10.0.128.0/17
|
| /---- 10.0.192.0/20
| |
| /---- 10.0.192.0/19
| | |
| | | /---- 10.0.208.0/22***
| | | |
| | | /---- 10.0.208.0/21
| | | | |
| | | | \---- 10.0.212.0/22
| | | |
| | \---- 10.0.208.0/20
| | |
| | \---- 10.0.216.0/21
| |
\---- 10.0.192.0/18
|
\---- 10.0.224.0/19
因此,例如,要查找/ 24的块,首先遍历树(以任何顺序),查找大小为/ 24的块。如果你找到一个,你就完成了;标记它已分配并返回它。在遍历期间,跟踪您找到的最小块更大的块大于/ 24。 (显然,如果您到达树中任何小于/ 24的节点,则不需要再进行其子树遍历,因为该大小只会从那里下移。)
如果找不到一个完全为/ 24的那个,那么你会转到你保存的那个大小比/ 24大的块。然后,您将该块切成两半,将其替换为两个半尺寸块。抓住其中任何一个(任意)。如果是/ 24你已经完成了。如果没有,你可以直接裁掉两个块,依此类推。最终,你会找到一个/ 24。
假设大小比/ 24大的最小块是/ 21。通过以这种方式递归地雕刻它,你将把/ 21雕刻成:两个/ 24个(你分配一个,一个仍然可用),一个可用/ 23,一个可用/ 22。
如果一个块返回给你,你可以将它与它的伴随块组合,如果该块可用(即一个叶子而没有标记为已分配)。如果您可以将其与其伴侣结合使用,那么可能能够将其父母与父母的双胞胎结合起来。
(顺便说一下,这与@ mcdowella的答案兼容;只是添加细节。)
答案 1 :(得分:0)
我想如果你能找到Knuth对https://en.wikipedia.org/wiki/Buddy_memory_allocation的描述(在#34;计算机编程的艺术"第一卷),你会看到各种属性证明了它,并且它们可能适用于你正在考虑的那种基于树的分配器,我认为这可以归结为类似的东西。
将可用的地址范围跟踪为一组大小为2的幂的块,以2的幂的倍数对齐。如果您有两个可以合并的块来生成下一个最大尺寸的合法块,那么您应该这样做。
当询问地址空间块时,从集合中可能的最小块分配它,并分配一个大小为2的幂的块。如果在分配后剩余空间,请将其转换为两个大小块的地址对齐功率。
如果向您返回先前分配的地址空间块,请将其添加到大小为2的幂块中,如果可能,将其与其邻居块(其伙伴)合并。