Searching IP prefix's/aggregates is inconsistent #6328

Closed
opened 2025-12-29 19:39:29 +01:00 by adam · 3 comments
Owner

Originally created by @ghost on GitHub (Apr 10, 2022).

Originally assigned to: @DanSheps on GitHub.

NetBox version

v.3.2.0

Python version

3.8

Steps to Reproduce

Reproduced in the demo site.

  1. Go to IPAM > Prefixes

  2. Verify an existing prefix (ex. 10.112.0.0/15)

  3. Use either 'quick search' on the prefixes page, or the main search at the top to search for octets contained within this prefix (ex. 10.112)

  4. Search and/or quick search return results related to the 10.112.0.0/15 prefix along with various other prefixes containing 10.112 within the string.

  5. Create a prefix using address (ex. 24.221.112.0/24)

  6. Use either 'quick search' on the prefixes page, or the main search at the top to search for octets contained within this prefix (ex. 24.221)

  7. Search and/or quick search return zero results

Expected Behavior

The Quick Search should actually search within fields of the IP Prefix page. If you have 50 IP prefixes on a page of varying sizes (/19, /20, /24, etc.) you should be able to type 1 or more of the octets of any IP prefix and have the results filtered to display IP prefixes containing your search string.

Observed Behavior

Search and/or quick search return zero results.
Quick search within the IPAM Prefixes page is inconsistent with how Quick Search works in other areas of Netbox.

For instance, if you navigate to the 'contacts' section of netbox and use the quick search on that page it will allow you to string search any field. In the demo sites case, I can type 'dwi' and it will show me Dwight Schrute. If I quick search for 'manager' it will show me both Dwight and Michael Scott who both have 'manager' in their title.

This type of quick and easy filtering and search should be implemented for IPAM.

Originally created by @ghost on GitHub (Apr 10, 2022). Originally assigned to: @DanSheps on GitHub. ### NetBox version v.3.2.0 ### Python version 3.8 ### Steps to Reproduce Reproduced in the demo site. 1) Go to IPAM > Prefixes 2) Verify an existing prefix (ex. 10.112.0.0/15) 3) Use either 'quick search' on the prefixes page, or the main search at the top to search for octets contained within this prefix (ex. 10.112) 4) Search and/or quick search return results related to the 10.112.0.0/15 prefix along with various other prefixes containing 10.112 within the string. 5) Create a prefix using address (ex. 24.221.112.0/24) 6) Use either 'quick search' on the prefixes page, or the main search at the top to search for octets contained within this prefix (ex. 24.221) 6) Search and/or quick search return zero results ### Expected Behavior The Quick Search should actually search within fields of the IP Prefix page. If you have 50 IP prefixes on a page of varying sizes (/19, /20, /24, etc.) you should be able to type 1 or more of the octets of any IP prefix and have the results filtered to display IP prefixes containing your search string. ### Observed Behavior Search and/or quick search return zero results. Quick search within the IPAM Prefixes page is inconsistent with how Quick Search works in other areas of Netbox. For instance, if you navigate to the 'contacts' section of netbox and use the quick search on that page it will allow you to string search any field. In the demo sites case, I can type 'dwi' and it will show me Dwight Schrute. If I quick search for 'manager' it will show me both Dwight and Michael Scott who both have 'manager' in their title. This type of quick and easy filtering and search should be implemented for IPAM.
adam added the type: bugstatus: accepted labels 2025-12-29 19:39:29 +01:00
adam closed this issue 2025-12-29 19:39:29 +01:00
Author
Owner

@DanSheps commented on GitHub (Apr 11, 2022):

So, I attempted a repo on the demo site, just to see what we get.

I get the 10.112.0.0/15 prefix right off the bat, as expected.

For the 24.221 prefix, I have to search at least either:

  • 24.221.112
  • 24.221.112.0
  • 24.221.112.0/24

The following do not work:

  • < 24.221.112 (ex: 24.221.11)
  • 24.221.112.
  • 24.221.112.0/
  • 24.221.112.0/2

This is actually fairly consistent within the prefix search (the 10.112 prefixes do the same thing when doing partial matches)

@DanSheps commented on GitHub (Apr 11, 2022): So, I attempted a repo on the demo site, just to see what we get. I get the 10.112.0.0/15 prefix right off the bat, as expected. For the 24.221 prefix, I have to search at least either: * 24.221.112 * 24.221.112.0 * 24.221.112.0/24 The following do not work: * < 24.221.112 (ex: 24.221.11) * 24.221.112. * 24.221.112.0/ * 24.221.112.0/2 This is actually fairly consistent within the prefix search (the 10.112 prefixes do the same thing when doing partial matches)
Author
Owner

@DanSheps commented on GitHub (Apr 11, 2022):

Current search function uses this:

    def search(self, queryset, name, value):
        if not value.strip():
            return queryset
        qs_filter = Q(description__icontains=value)
        try:
            prefix = str(netaddr.IPNetwork(value.strip()).cidr)
            qs_filter |= Q(prefix__net_contains_or_equals=prefix)
        except (AddrFormatError, ValueError):
            pass
        return queryset.filter(qs_filter)

Results in the following SQL:

SELECT "ipam_prefix"."id", "ipam_prefix"."created", "ipam_prefix"."last_updated", "ipam_prefix"."custom_field_data", "
ipam_prefix"."prefix", "ipam_prefix"."site_id", "ipam_prefix"."vrf_id", "ipam_prefix"."tenant_id", "ipam_prefix"."vlan
_id", "ipam_prefix"."status", "ipam_prefix"."role_id", "ipam_prefix"."is_pool", "ipam_prefix"."mark_utilized", "ipam_p
refix"."description", "ipam_prefix"."_depth", "ipam_prefix"."_children" FROM "ipam_prefix" WHERE "ipam_prefix"."prefix
" >>= 24.221.0.0/32 ORDER BY "ipam_prefix"."vrf_id" ASC NULLS FIRST, "ipam_prefix"."prefix" ASC, "ipam_prefix"."id" AS
C

The >>= is a test to check and see is 24.221.0.0/32 is included in the prefix in the database. As you can see, the string '24.221' is being converted to a CIDR address.

I think if we go to:

    def search(self, queryset, name, value):
        if not value.strip():
            return queryset
        qs_filter = Q(description__icontains=value)
        try:
            prefix = str(netaddr.IPNetwork(value.strip()).cidr)
            qs_filter |= Q(prefix__net_contains_or_equals=prefix)
            qs_filter |= Q(prefix__contains=value.strip())
        except (AddrFormatError, ValueError):
            pass
        return queryset.filter(qs_filter)

Results in the following SQL:

SELECT "ipam_prefix"."id", "ipam_prefix"."created", "ipam_prefix"."last_updated", "ipam_prefix"."custom_field_data", "
ipam_prefix"."prefix", "ipam_prefix"."site_id", "ipam_prefix"."vrf_id", "ipam_prefix"."tenant_id", "ipam_prefix"."vlan
_id", "ipam_prefix"."status", "ipam_prefix"."role_id", "ipam_prefix"."is_pool", "ipam_prefix"."mark_utilized", "ipam_p
refix"."description", "ipam_prefix"."_depth", "ipam_prefix"."_children" FROM "ipam_prefix" WHERE ("ipam_prefix"."prefi
x" >>= 24.221.0.0/32 OR "ipam_prefix"."prefix"::text LIKE %24.221%) ORDER BY "ipam_prefix"."vrf_id" ASC NULLS FIRST, "
ipam_prefix"."prefix" ASC, "ipam_prefix"."id" ASC

This would fix it up, however this might have unintended consequences. Some more to think about. This has been tested

@DanSheps commented on GitHub (Apr 11, 2022): Current search function uses this: ```python def search(self, queryset, name, value): if not value.strip(): return queryset qs_filter = Q(description__icontains=value) try: prefix = str(netaddr.IPNetwork(value.strip()).cidr) qs_filter |= Q(prefix__net_contains_or_equals=prefix) except (AddrFormatError, ValueError): pass return queryset.filter(qs_filter) ``` Results in the following SQL: ```sql SELECT "ipam_prefix"."id", "ipam_prefix"."created", "ipam_prefix"."last_updated", "ipam_prefix"."custom_field_data", " ipam_prefix"."prefix", "ipam_prefix"."site_id", "ipam_prefix"."vrf_id", "ipam_prefix"."tenant_id", "ipam_prefix"."vlan _id", "ipam_prefix"."status", "ipam_prefix"."role_id", "ipam_prefix"."is_pool", "ipam_prefix"."mark_utilized", "ipam_p refix"."description", "ipam_prefix"."_depth", "ipam_prefix"."_children" FROM "ipam_prefix" WHERE "ipam_prefix"."prefix " >>= 24.221.0.0/32 ORDER BY "ipam_prefix"."vrf_id" ASC NULLS FIRST, "ipam_prefix"."prefix" ASC, "ipam_prefix"."id" AS C ``` The >>= is a test to check and see is 24.221.0.0/32 is included in the prefix in the database. As you can see, the string '24.221' is being converted to a CIDR address. I think if we go to: ```python def search(self, queryset, name, value): if not value.strip(): return queryset qs_filter = Q(description__icontains=value) try: prefix = str(netaddr.IPNetwork(value.strip()).cidr) qs_filter |= Q(prefix__net_contains_or_equals=prefix) qs_filter |= Q(prefix__contains=value.strip()) except (AddrFormatError, ValueError): pass return queryset.filter(qs_filter) ``` Results in the following SQL: ```sql SELECT "ipam_prefix"."id", "ipam_prefix"."created", "ipam_prefix"."last_updated", "ipam_prefix"."custom_field_data", " ipam_prefix"."prefix", "ipam_prefix"."site_id", "ipam_prefix"."vrf_id", "ipam_prefix"."tenant_id", "ipam_prefix"."vlan _id", "ipam_prefix"."status", "ipam_prefix"."role_id", "ipam_prefix"."is_pool", "ipam_prefix"."mark_utilized", "ipam_p refix"."description", "ipam_prefix"."_depth", "ipam_prefix"."_children" FROM "ipam_prefix" WHERE ("ipam_prefix"."prefi x" >>= 24.221.0.0/32 OR "ipam_prefix"."prefix"::text LIKE %24.221%) ORDER BY "ipam_prefix"."vrf_id" ASC NULLS FIRST, " ipam_prefix"."prefix" ASC, "ipam_prefix"."id" ASC ``` This would fix it up, however this might have unintended consequences. Some more to think about. This has been tested
Author
Owner

@t8simon commented on GitHub (May 5, 2022):

I'm also affected by this problem. This is also happening, when you have exact matching numbers in the octets. I have to search for the exact network instead of the first octets. If I remember correctly, this was working before. Taking the demo system as an example, there you have
-192.168.224.0/22
--192.168.224.0/28
--192.168.224.16/28
--192.168.224.32/27
etc

You don't find anything by searching the first two octets (192.168) even if I would expect to find all prefixes that start like that. Going on with a search for 3 octets (192.168.224) there are only appearing the first two:
-192.168.224.0/22
--192.168.224.0/28

All other networks (192.168.224.16/28 etc) are not shown.

The interesting thing is: It finds IP Addresses perfectly fine (for all IPs that start with the searched octets), so for IP Addresses the search function seems to work fine.

@t8simon commented on GitHub (May 5, 2022): I'm also affected by this problem. This is also happening, when you have exact matching numbers in the octets. I have to search for the exact network instead of the first octets. If I remember correctly, this was working before. Taking the demo system as an example, there you have -192.168.224.0/22 --192.168.224.0/28 --192.168.224.16/28 --192.168.224.32/27 etc You don't find anything by searching the first two octets (192.168) even if I would expect to find all prefixes that start like that. Going on with a search for 3 octets (192.168.224) there are only appearing the first two: -192.168.224.0/22 --192.168.224.0/28 All other networks (192.168.224.16/28 etc) are not shown. The interesting thing is: It finds IP Addresses perfectly fine (for all IPs that start with the searched octets), so for IP Addresses the search function seems to work fine.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/netbox#6328