[英]How can I remove two or more subnet from a network?
from ipaddress
class, I know the address_exclude
method.从ipaddress
class,我知道address_exclude
方法。 below is an example from the documentation:以下是文档中的示例:
>>> n1 = ip_network('192.0.2.0/28')
>>> n2 = ip_network('192.0.2.1/32')
>>> list(n1.address_exclude(n2))
[IPv4Network('192.0.2.8/29'), IPv4Network('192.0.2.4/30'),
IPv4Network('192.0.2.2/31'), IPv4Network('192.0.2.0/32')]
but what about if I want to remove two or more subnets from a network?但是如果我想从网络中删除两个或更多子网怎么办? for example, how can I delete from the 192.168.10.0/26 his subnets 192.168.10.24/29 and 192.168.10.48/28?例如,如何从 192.168.10.0/26 中删除他的子网 192.168.10.24/29 和 192.168.10.48/28? the result should be 192.168.10.0/28, 192.168.10.16/29 and 192.168.10.32/28.结果应该是 192.168.10.0/28、192.168.10.16/29 和 192.168.10.32/28。
I'm trying to find a way to write the algoritm that I use in my mind using the address_exclude
method but I can't.我正在尝试找到一种方法来使用address_exclude
方法编写我在脑海中使用的算法,但我做不到。 is there a simple way to implement what I just explained?有没有一种简单的方法来实现我刚才解释的内容?
When you exclude one network from another, the result can be multiple networks (original one got split) - so, for the rest of the networks to exclude, you need to first find which part they would fit into before excluding them as well.当您从另一个网络中排除一个网络时,结果可能是多个网络(原始网络被拆分) - 因此,对于要排除的网络的 rest,您需要先找到它们适合的部分,然后再排除它们。
Here's one possible solution:这是一种可能的解决方案:
from ipaddress import ip_network, collapse_addresses
complete = ip_network('192.168.10.0/26')
# I chose the larger subnet for exclusion first, can be automated with network comparison
subnets = list(complete.address_exclude(ip_network('192.168.10.48/28')))
# other network to exclude
other_exclude = ip_network('192.168.10.24/29')
result = []
# Find which subnet the other exclusion will happen in
for sub in subnets:
# If found, exclude & add the result
if other_exclude.subnet_of(sub):
result.extend(list(sub.address_exclude(other_exclude)))
else:
# Other subnets can be added directly
result.append(sub)
# Collapse in case of overlaps
print(list(collapse_addresses(result)))
Output: Output:
[IPv4Network('192.168.10.0/28'), IPv4Network('192.168.10.16/29'), IPv4Network('192.168.10.32/28')]
Expanding on my brain wave posted on @rdas's response, posting my solution.扩展我在@rdas 的回复上发布的脑电波,发布我的解决方案。
It seems better to split the initial network into the smallest chunks you are asking, and do this for all ranges to be removed.将初始网络拆分为您要求的最小块似乎更好,并为要删除的所有范围执行此操作。 Then exclude them from the list and return result.然后将它们从列表中排除并返回结果。
from ipaddress import ip_network, collapse_addresses
def remove_ranges(mynetwork,l_of_ranges):
# find smallest chunk
l_chunk = sorted(list(set([x.split('/')[1] for x in l_of_ranges])))
l_mynetwork = list(ip_network(mynetwork).subnets(new_prefix=int(l_chunk[-1])))
l_chunked_ranges = [ ]
for nw in l_of_ranges:
l_chunked_ranges.extend(list(ip_network(nw).subnets(new_prefix=int(l_chunk[-1]))))
l_removed_networks = [ ]
for mynw in l_mynetwork:
if not mynw in l_chunked_ranges:
l_removed_networks.append(mynw)
result = list(collapse_addresses(l_removed_networks))
return [str(r) for r in result]
if __name__ == '__main__':
mynetwork = "10.110.0.0/16"
l_of_ranges = ["10.110.0.0/18","10.110.72.0/21","10.110.80.0/21","10.110.96.0/21"]
print(f"My network: {mynetwork}, Existing: {l_of_ranges} ")
a = remove_ranges(mynetwork,l_of_ranges)
print(f"Remaining: {a}")
With the result:结果:
My network: 10.110.0.0/16, Existing: ['10.110.0.0/18', '10.110.72.0/21', '10.110.80.0/21', '10.110.96.0/21']
Remaining: ['10.110.64.0/21', '10.110.88.0/21', '10.110.104.0/21', '10.110.112.0/20', '10.110.128.0/17']
Which seems to be valid.这似乎是有效的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.