diff --git a/netbox/ipam/fields.py b/netbox/ipam/fields.py index c5930d8399f..a1fbdf0975f 100644 --- a/netbox/ipam/fields.py +++ b/netbox/ipam/fields.py @@ -16,6 +16,7 @@ # BGP ASN bounds BGP_ASN_MIN = 1 BGP_ASN_MAX = 2**32 - 1 +BGP_ASN_ASDOT_BASE = 2**16 class BaseIPField(models.Field): @@ -126,3 +127,16 @@ def formfield(self, **kwargs): } defaults.update(**kwargs) return super().formfield(**defaults) + + @staticmethod + def to_asdot(value) -> str: + """ + Return ASDOT notation for AS numbers greater than 16 bits. + """ + if value is None: + return '' + + if value >= BGP_ASN_ASDOT_BASE: + hi, lo = divmod(value, BGP_ASN_ASDOT_BASE) + return f'{hi}.{lo}' + return str(value) diff --git a/netbox/ipam/models/asns.py b/netbox/ipam/models/asns.py index ee1a5416ece..1b445992125 100644 --- a/netbox/ipam/models/asns.py +++ b/netbox/ipam/models/asns.py @@ -55,13 +55,6 @@ class Meta: def __str__(self): return f'{self.name} ({self.range_as_string()})' - @property - def range(self): - return range(self.start, self.end + 1) - - def range_as_string(self): - return f'{self.start}-{self.end}' - def clean(self): super().clean() @@ -72,7 +65,45 @@ def clean(self): ) ) + @property + def range(self): + """ + Return a range of integers representing the ASN range. + """ + return range(self.start, self.end + 1) + + @property + def start_asdot(self): + """ + Return ASDOT notation for AS numbers greater than 16 bits. + """ + return ASNField.to_asdot(self.start) + + @property + def end_asdot(self): + """ + Return ASDOT notation for AS numbers greater than 16 bits. + """ + return ASNField.to_asdot(self.end) + + def range_as_string(self): + """ + Return a string representation of the ASN range. + """ + return f'{self.start}-{self.end}' + + def range_as_string_with_asdot(self): + """ + Return a string representation of the ASN range, including ASDOT notation. + """ + if self.end >= 65536: + return f'{self.range_as_string()} ({self.start_asdot}-{self.end_asdot})' + return self.range_as_string() + def get_child_asns(self): + """ + Return all child ASNs (ASNs within the range). + """ return ASN.objects.filter( asn__gte=self.start, asn__lte=self.end @@ -131,20 +162,20 @@ def asn_asdot(self): """ Return ASDOT notation for AS numbers greater than 16 bits. """ - if self.asn > 65535: - return f'{self.asn // 65536}.{self.asn % 65536}' - return self.asn + return ASNField.to_asdot(self.asn) @property def asn_with_asdot(self): """ Return both plain and ASDOT notation, where applicable. """ - if self.asn > 65535: - return f'{self.asn} ({self.asn // 65536}.{self.asn % 65536})' - else: - return self.asn + if self.asn >= 65536: + return f'{self.asn} ({self.asn_asdot})' + return str(self.asn) @property def prefixed_name(self): + """ + Return the ASN with ASDOT notation prefixed with "AS". + """ return f'AS{self.asn_with_asdot}' diff --git a/netbox/ipam/tables/asn.py b/netbox/ipam/tables/asn.py index bfbbdd1505c..2d1ce988291 100644 --- a/netbox/ipam/tables/asn.py +++ b/netbox/ipam/tables/asn.py @@ -20,6 +20,16 @@ class ASNRangeTable(TenancyColumnsMixin, NetBoxTable): verbose_name=_('RIR'), linkify=True ) + start_asdot = tables.Column( + accessor=tables.A('start_asdot'), + order_by=tables.A('start'), + verbose_name=_('Start ASDOT') + ) + end_asdot = tables.Column( + accessor=tables.A('end_asdot'), + order_by=tables.A('end'), + verbose_name=_('End ASDOT') + ) tags = columns.TagColumn( url_name='ipam:asnrange_list' ) @@ -30,8 +40,8 @@ class ASNRangeTable(TenancyColumnsMixin, NetBoxTable): class Meta(NetBoxTable.Meta): model = ASNRange fields = ( - 'pk', 'name', 'slug', 'rir', 'start', 'end', 'asn_count', 'tenant', 'tenant_group', 'description', 'tags', - 'created', 'last_updated', 'actions', + 'pk', 'name', 'slug', 'rir', 'start', 'start_asdot', 'end', 'end_asdot', 'asn_count', 'tenant', + 'tenant_group', 'description', 'tags', 'created', 'last_updated', 'actions', ) default_columns = ('pk', 'name', 'rir', 'start', 'end', 'tenant', 'asn_count', 'description') diff --git a/netbox/templates/ipam/asnrange.html b/netbox/templates/ipam/asnrange.html index b5405cfda97..0b3ae9c5e85 100644 --- a/netbox/templates/ipam/asnrange.html +++ b/netbox/templates/ipam/asnrange.html @@ -23,7 +23,7 @@