"Search" for prefixes does not find all matching prefixes #4681

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

Originally created by @candlerb on GitHub (Mar 19, 2021).

NetBox version

v2.10.6

Python version

3.6

Steps to Reproduce

Create a bunch of /29 prefixes under 10.9.1: 10.9.1.0/29, 10.9.1.8/29, 10.9.1.16/29 ... 10.9.1.48/29

Then search for "10.9.1" or "10.9.1." in either global search, or the top search box under IPAM > Prefixes

Expected Behavior

All prefixes beginning 10.9.1 to be shown

Observed Behavior

If you search for "10.9.1" - only the first prefix (10.9.1.0/29) is found
If you search for "10.9.1." - no prefixes are found

Search box:

image

Results:

image

Note 1: an IP address search for "10.9.1" or "10.9.1." does work as expected, showing all IP addresses beginning 10.9.1. It's only prefixes which appear to have this problem.

Note 2: the "search within parent prefix" functionality works fine, and this was the only way I could discover the apparently missing prefixes:

image

Results:

image

However this doesn't work from global search. First you have to navigate to IPAM > prefixes, and then have to construct a suitable parent prefix to search within.

EDIT: in a regular search, the positive finding of the 10.9.1.0/29 prefix suggests strongly to the user that there are no other matching prefixes (when in fact there are).

Originally created by @candlerb on GitHub (Mar 19, 2021). ### NetBox version v2.10.6 ### Python version 3.6 ### Steps to Reproduce Create a bunch of /29 prefixes under 10.9.1: 10.9.1.0/29, 10.9.1.8/29, 10.9.1.16/29 ... 10.9.1.48/29 Then search for "10.9.1" or "10.9.1." in either global search, or the top search box under IPAM > Prefixes ### Expected Behavior All prefixes beginning 10.9.1 to be shown ### Observed Behavior If you search for "10.9.1" - only the first prefix (10.9.1.0/29) is found If you search for "10.9.1." - no prefixes are found Search box: ![image](https://user-images.githubusercontent.com/44789/111763527-290d2300-889a-11eb-9ec3-fccd390d7cea.png) Results: ![image](https://user-images.githubusercontent.com/44789/111763680-50fc8680-889a-11eb-901c-ce1cffa08083.png) Note 1: an *IP address* search for "10.9.1" or "10.9.1." does work as expected, showing all IP addresses beginning 10.9.1. It's only *prefixes* which appear to have this problem. Note 2: the "search within parent prefix" functionality works fine, and this was the only way I could discover the apparently missing prefixes: ![image](https://user-images.githubusercontent.com/44789/111763808-738e9f80-889a-11eb-969e-2f7aceda39b2.png) Results: ![image](https://user-images.githubusercontent.com/44789/111763877-843f1580-889a-11eb-90df-3225ab691729.png) However this doesn't work from global search. First you have to navigate to IPAM > prefixes, and then have to construct a suitable parent prefix to search within. EDIT: in a regular search, the positive finding of the 10.9.1.0/29 prefix suggests strongly to the user that there are no other matching prefixes (when in fact there are).
adam added the type: bug label 2025-12-29 19:19:27 +01:00
adam closed this issue 2025-12-29 19:19:27 +01:00
Author
Owner

@jeremystretch commented on GitHub (Mar 19, 2021):

If you search for "10.9.1" - only the first prefix (10.9.1.0/29) is found

This is expected. The string is cast to a prefix using netaddr, which evaluates it as 10.9.1.0. This returns the matching prefix, 10.9.1.0. Note that NetBox does not support wildcard matching because it is extremely ineffective for IP addresses (as has been discussed previously).

To search for all prefixes within a prefix, use the within or within_include filter (the "search within" field on the prefixes list search box).

@jeremystretch commented on GitHub (Mar 19, 2021): > If you search for "10.9.1" - only the first prefix (10.9.1.0/29) is found This is expected. The string is cast to a prefix using `netaddr`, which evaluates it as 10.9.1.0. This returns the matching prefix, 10.9.1.0. Note that NetBox does not support wildcard matching because it is extremely ineffective for IP addresses (as has been discussed previously). To search for all prefixes _within_ a prefix, use the `within` or `within_include` filter (the "search within" field on the prefixes list search box).
Author
Owner

@candlerb commented on GitHub (Mar 19, 2021):

Note that NetBox does not support wildcard matching because it is extremely ineffective for IP addresses (as has been discussed previously).

That's odd, because as far as I can see, it is used for IP addresses. From netbox/ipam/filters.py:

class IPAddressFilterSet(BaseFilterSet, TenancyFilterSet, CustomFieldModelFilterSet, CreatedUpdatedFilterSet):
...
    def search(self, queryset, name, value):
        if not value.strip():
            return queryset
        qs_filter = (
            Q(dns_name__icontains=value) |
            Q(description__icontains=value) |
            Q(address__istartswith=value)    <<<<<< HERE
        )

(This means that for example, searching for "192.1" matches addresses that start 192.168 - confirmed by testing)

Whereas prefixes are handled differently, as you say:

class PrefixFilterSet(BaseFilterSet, TenancyFilterSet, CustomFieldModelFilterSet, CreatedUpdatedFilterSet):
...
    def search(self, queryset, name, value):
...
        try:
            prefix = str(netaddr.IPNetwork(value.strip()).cidr)
            qs_filter |= Q(prefix__net_contains_or_equals=prefix)    <<<<<< HERE

From a user's point of view, it would be much better if it were consistent.

One way would be to use prefix__istartswith=value in the prefix search - which you just rejected. However ISTM that in general, the number of prefixes in a system is much less than the number of IP addresses, so this is bound to be better than IP Address searching.

The other way would be to flip IP address searching to match in a similar way. e.g.

  • For IP address search, if user types "10.9.1" then treat this as "10.9.1.0/24" and search for IP addresses within that block
  • For prefix search, if user types "10.9.1" then search for all prefixes contained within "10.9.1.0/24" as well as all prefixes containing "10.9.1.0/32"

This would need to be slightly more intelligent than the current search, by realising that 3 octets implies /24, rather than /32:

>>> str(netaddr.IPNetwork("10.9.1".strip()).cidr)
'10.9.1.0/32'

But it wouldn't be hard to implement, and I think it would be more logical, because then searching for "192.1" would only turn up IP addresses within 192.1.0.0/16

@candlerb commented on GitHub (Mar 19, 2021): > Note that NetBox does not support wildcard matching because it is extremely ineffective for IP addresses (as has been discussed previously). That's odd, because as far as I can see, it *is* used for IP addresses. From [netbox/ipam/filters.py](https://github.com/netbox-community/netbox/blob/develop/netbox/ipam/filters.py): ``` class IPAddressFilterSet(BaseFilterSet, TenancyFilterSet, CustomFieldModelFilterSet, CreatedUpdatedFilterSet): ... def search(self, queryset, name, value): if not value.strip(): return queryset qs_filter = ( Q(dns_name__icontains=value) | Q(description__icontains=value) | Q(address__istartswith=value) <<<<<< HERE ) ``` (This means that for example, searching for "192.1" matches addresses that start `192.168` - confirmed by testing) Whereas prefixes are handled differently, as you say: ``` class PrefixFilterSet(BaseFilterSet, TenancyFilterSet, CustomFieldModelFilterSet, CreatedUpdatedFilterSet): ... def search(self, queryset, name, value): ... try: prefix = str(netaddr.IPNetwork(value.strip()).cidr) qs_filter |= Q(prefix__net_contains_or_equals=prefix) <<<<<< HERE ``` From a user's point of view, it would be much better if it were consistent. One way would be to use `prefix__istartswith=value` in the prefix search - which you just rejected. However ISTM that in general, the number of prefixes in a system is much less than the number of IP addresses, so this is bound to be better than IP Address searching. The other way would be to flip IP address searching to match in a similar way. e.g. * For IP address search, if user types "10.9.1" then treat this as "10.9.1.0/24" and search for IP addresses _within_ that block * For prefix search, if user types "10.9.1" then search for all prefixes _contained within_ "10.9.1.0/24" as well as all prefixes _containing_ "10.9.1.0/32" This would need to be slightly more intelligent than the current search, by realising that 3 octets implies /24, rather than /32: ``` >>> str(netaddr.IPNetwork("10.9.1".strip()).cidr) '10.9.1.0/32' ``` But it wouldn't be hard to implement, and I think it would be more logical, because then searching for "192.1" would only turn up IP addresses within `192.1.0.0/16`
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/netbox#4681