1

I have a set that contains mixture of ip4 addresses and ip4 networks.

Simple short example:

{'127.0.0.1', '138.56.76.02', '192.4.2.0/24', '29.24.48.80', etc, etc, etc}

Real size is a few thousands items.

Question is – what is the fastest way to check whether specific ip address 'xxx.yyy.zzz.lll' is contained in all these mixture of ip addresses and ip networks without iterating through them one by one?

With plain ips set it is obvious but with presence of ip networks not so, as network might contain this ip as well.

It is also possible to have same set but with ips and networks inside wrapped in IPv4Address and IPv4Network objects from ipaddress package.

Perhaps it is possible to combine all these in one pseudo-network somehow???

Thanks...

Aleksei Khatkevich
  • 1,923
  • 2
  • 10
  • 27
  • 1
    You could make a set of single IPs and check if yours is one of them in O(1). For the subnets part, you could have a look at https://stackoverflow.com/questions/44262437/how-to-efficiently-check-if-a-given-ip-address-belong-to-an-ip-subnetwork-in-pyt – Thierry Lathuille Aug 24 '20 at 12:09

2 Answers2

1

One way would be to use the ipaddress module to build a set of IPv4Address instances:

>>> from ipaddress import *
>>> from itertools import *
>>>
>>> p = {'127.0.0.1', '138.56.76.02', '192.4.2.0/24', '29.24.48.80', ...}
>>>
>>> all_hosts = set(chain.from_iterable(IPv4Network(n) for n in p))
>>>
>>> IPv4Address('192.4.2.4') in all_hosts
True
>>> IPv4Address('29.24.48.80') in all_hosts
True
>>> IPv4Address('29.24.48.81') in all_hosts
False

This takes advantage of the fact that constructing an IPv4Network from just an address (with no mask) creates a network with just that address in it. It also uses the feature that iterating an IPv4Network gives you each host in turn.

The all_hosts set will be slow to build and large in memory if p is large or the netmasks contain many hosts. However, after that, checking if an IP address is in the set is fast (O(1) on average).

All this still works if p already contains IPv4Network and IPv4Address instances.

Wander Nauta
  • 18,832
  • 1
  • 45
  • 62
  • Thank you for the answer. I thought about something similiar. But don't you think that creating instance of IPv4Address after creating IPv4Network for each object in set would be slow? Mybe it is better to filter out networks from sets (10 to 90% more or less) and then expand networks to list of individyal ips without converting them to IPv4Network and IPv4Address ? – Aleksei Khatkevich Aug 24 '20 at 12:42
  • The only way to know for sure would be to measure. You can use the [timeit module](https://docs.python.org/3.8/library/timeit.html) or just a stopwatch to see which way of building `all_hosts` is faster, and then think about how often you rebuild `all_sets` in your program and decide whether the difference is large enough to be worth the extra complexity. – Wander Nauta Aug 24 '20 at 12:55
-1

I would suggest to work with lists and do this:

if "xxx.yyy.zzz.ttt" in ip_list:
    print("IP IN LIST")

Regards.

Daniziz
  • 88
  • 7