Enable custom interface naturalization functions #904

Open
opened 2026-04-05 18:41:27 +02:00 by MrUnknownDE · 0 comments
Owner

Originally created by @PieterL75 on 11/7/2025

NetBox version

v4.3.7

Feature type

New functionality

Proposed functionality

Interfaces are sorted according a specific interface naturalization function

cf0ef92268/netbox/utilities/ordering.py (L51)
This function suits very well for Cisco branded devices, but does not always work for other vendors.

There has been few proposals (can only find this one https://github.com/netbox-community/netbox/issues/9368 ) to address this, but for now non has been accepted. FR #20335 proposed several options, and the discussion thread ended with this proposal:

  • provide different sorting mechanisms, which can be applied per Platform type
  • also allow plugins to extend these sorting mechanisms

Proposed sorting algoritms

  • Default: (current one) Similar in nature to naturalize(), but takes into account a particular naming format adapted from the old InterfaceManager
  • Alphanumeric: Take an alphanumeric string and prepend all integers to integer_places places to ensure the strings are ordered naturally. (Arista)
  • Numeric: Take an alphanumeric string and prepend all integers to integer_places places to ensure the strings are ordered naturally, while ignoring the alpa part. (NetApp, JunOS, Arista)

Add new functions with a plugin or in configuration.py

 FIELD_CHOICES = {
     'dcim.Platform.interfacesorting+': (
         ('naturalsort' , 'Natural Interface Sorting', netbox_plugin.ordering.naturalsort),
     )
}

Other sorting option that could be implemented

  • Numeric, but with mgmt_only interfaces first

A PoC can be found here, but that needs further coding before it can become a PR
https://github.com/PieterL75/netbox/tree/customize-naturlization

As a side effect, an extra option was implemented to the ChoiceSetMeta, adding the possibility to prevent a ChoiceSet to be replaced or extended. This probably need to go to a separate FR.

Use case

A recent poll in #netbox shows that there is a need for this: https://netdev-community.slack.com/archives/C01P0FRSXRV/p1757313471550629?thread_ts=1757065483.482359&cid=C01P0FRSXRV

Platform OS Current Desired
Arista EOS Ethernet48/1 Ethernet1
Ethernet48/2 Ethernet2
Ethernet49/1 Ethernet48/1
Ethernet49/2 Ethernet48/2
Ethernet1 Ethernet49/1
Ethernet2 Ethernet49/2
Juniper JUNOS ge-0/0/0 ge-0/0/0
ge-0/0/3 xe-0/0/1
xe-0/0/1 xe-0/0/2
xe-0/0/2 ge-0/0/3
Netapp 10a e9a
10b e9e
e9a 10a
e9e 10b
e11a e11
e11e e11

Database changes

Extra field on 'Platform'

            model_name='platform',
            name='interface_sorting',
            field=models.CharField(default='default', max_length=100)

External dependencies

No response

*Originally created by @PieterL75 on 11/7/2025* ### NetBox version v4.3.7 ### Feature type New functionality ### Proposed functionality Interfaces are sorted according a specific interface naturalization function https://github.com/netbox-community/netbox/blob/cf0ef9226866223be6b54e791ea157ef849a340f/netbox/utilities/ordering.py#L51 This function suits very well for Cisco branded devices, but does not always work for other vendors. There has been few proposals (can only find this one https://github.com/netbox-community/netbox/issues/9368 ) to address this, but for now non has been accepted. FR #20335 proposed several options, and the discussion thread ended with this proposal: * provide different sorting mechanisms, which can be applied per Platform type * also allow plugins to extend these sorting mechanisms Proposed sorting algoritms - Default: (current one) Similar in nature to naturalize(), but takes into account a particular naming format adapted from the old InterfaceManager - Alphanumeric: Take an alphanumeric string and prepend all integers to `integer_places` places to ensure the strings are ordered naturally. (Arista) - Numeric: Take an alphanumeric string and prepend all integers to `integer_places` places to ensure the strings are ordered naturally, while ignoring the alpa part. (NetApp, JunOS, Arista) Add new functions with a plugin or in configuration.py ```python FIELD_CHOICES = { 'dcim.Platform.interfacesorting+': ( ('naturalsort' , 'Natural Interface Sorting', netbox_plugin.ordering.naturalsort), ) } ``` Other sorting option that could be implemented - Numeric, but with mgmt_only interfaces first A PoC can be found here, but that needs further coding before it can become a PR https://github.com/PieterL75/netbox/tree/customize-naturlization As a side effect, an extra option was implemented to the ChoiceSetMeta, adding the possibility to prevent a ChoiceSet to be replaced or extended. This probably need to go to a separate FR. ### Use case A recent poll in #netbox shows that there is a need for this: https://netdev-community.slack.com/archives/C01P0FRSXRV/p1757313471550629?thread_ts=1757065483.482359&cid=C01P0FRSXRV | Platform OS | Current | Desired | | ------------- | ------------ | ------------ | | Arista EOS | Ethernet48/1 | Ethernet1 | | | Ethernet48/2 | Ethernet2 | | | Ethernet49/1 | Ethernet48/1 | | | Ethernet49/2 | Ethernet48/2 | | | Ethernet1 | Ethernet49/1 | | | Ethernet2 | Ethernet49/2 | | Juniper JUNOS | ge-0/0/0 | ge-0/0/0 | | | ge-0/0/3 | xe-0/0/1 | | | xe-0/0/1 | xe-0/0/2 | | | xe-0/0/2 | ge-0/0/3 | | Netapp | 10a | e9a | | | 10b | e9e | | | e9a | 10a | | | e9e | 10b | | | e11a | e11 | | | e11e | e11 | ### Database changes Extra field on 'Platform' ``` model_name='platform', name='interface_sorting', field=models.CharField(default='default', max_length=100) ``` ### External dependencies _No response_
MrUnknownDE added the netboxtype: featurestatus: backlogcomplexity: highnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxnetboxtype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featuretype: featurestatus: backlogstatus: backlogstatus: backlogstatus: backlogstatus: backlogstatus: backlogstatus: backlogstatus: backlogstatus: backlogstatus: backlogstatus: backlogstatus: backlogstatus: backlogstatus: backlogstatus: backlogstatus: backlogstatus: backlogstatus: backlogstatus: backlogstatus: backlogstatus: backlogstatus: backlogstatus: backlogstatus: backlogstatus: backlogstatus: backlogstatus: backlogstatus: backlogstatus: backlogstatus: backlogstatus: backlogcomplexity: highcomplexity: highcomplexity: highcomplexity: highcomplexity: highcomplexity: highcomplexity: highcomplexity: highcomplexity: highcomplexity: highcomplexity: highcomplexity: highcomplexity: high labels 2026-04-05 18:42:22 +02:00
Sign in to join this conversation.
No Label complexity: high complexity: high complexity: high complexity: high complexity: high complexity: high complexity: high complexity: high complexity: high complexity: high complexity: high complexity: high complexity: high complexity: high netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox netbox status: backlog status: backlog status: backlog status: backlog status: backlog status: backlog status: backlog status: backlog status: backlog status: backlog status: backlog status: backlog status: backlog status: backlog status: backlog status: backlog status: backlog status: backlog status: backlog status: backlog status: backlog status: backlog status: backlog status: backlog status: backlog status: backlog status: backlog status: backlog status: backlog status: backlog status: backlog status: backlog type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature type: feature
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github/netbox#904