Просмотр исходного кода

Do not allocate subnet router anycast in certain IPv6 prefixes

Sean M. Collins 3 лет назад
Родитель
Сommit
b5613a2cc6
2 измененных файлов с 24 добавлено и 8 удалено
  1. 12 8
      netbox/ipam/models/ip.py
  2. 12 0
      netbox/ipam/tests/test_models.py

+ 12 - 8
netbox/ipam/models/ip.py

@@ -507,16 +507,20 @@ class Prefix(GetAvailablePrefixesMixin, NetBoxModel):
             child_ranges.add(iprange.range)
         available_ips = prefix - child_ips - child_ranges
 
-        # IPv6, pool, or IPv4 /31-/32 sets are fully usable
-        if self.family == 6 or self.is_pool or (self.family == 4 and self.prefix.prefixlen >= 31):
+        # IPv6 /127's, pool, or IPv4 /31-/32 sets are fully usable
+        if (self.family == 6 and self.prefix.prefixlen >= 127) or self.is_pool or (self.family == 4 and self.prefix.prefixlen >= 31):
             return available_ips
 
-        # For "normal" IPv4 prefixes, omit first and last addresses
-        available_ips -= netaddr.IPSet([
-            netaddr.IPAddress(self.prefix.first),
-            netaddr.IPAddress(self.prefix.last),
-        ])
-
+        if self.family == 4:
+            # For "normal" IPv4 prefixes, omit first and last addresses
+            available_ips -= netaddr.IPSet([
+                netaddr.IPAddress(self.prefix.first),
+                netaddr.IPAddress(self.prefix.last),
+            ])
+        else:
+            # For IPv6 prefixes, omit the Subnet-Router anycast address
+            # per RFC 4291
+            available_ips -= netaddr.IPSet([netaddr.IPAddress(self.prefix.first)])
         return available_ips
 
     def get_first_available_ip(self):

+ 12 - 0
netbox/ipam/tests/test_models.py

@@ -185,6 +185,18 @@ class TestPrefix(TestCase):
         IPAddress.objects.create(address=IPNetwork('10.0.0.4/24'))
         self.assertEqual(parent_prefix.get_first_available_ip(), '10.0.0.5/24')
 
+    def test_get_first_available_ip_ipv6(self):
+        parent_prefix = Prefix.objects.create(prefix=IPNetwork('2001:db8:500::/64'))
+        self.assertEqual(parent_prefix.get_first_available_ip(), '2001:db8:500::1/64')
+
+    def test_get_first_available_ip_ipv6_rfc3627(self):
+        parent_prefix = Prefix.objects.create(prefix=IPNetwork('2001:db8:500:4::/126'))
+        self.assertEqual(parent_prefix.get_first_available_ip(), '2001:db8:500:4::1/126')
+
+    def test_get_first_available_ip_ipv6_rfc6164(self):
+        parent_prefix = Prefix.objects.create(prefix=IPNetwork('2001:db8:500:5::/127'))
+        self.assertEqual(parent_prefix.get_first_available_ip(), '2001:db8:500:5::/127')
+
     def test_get_utilization_container(self):
         prefixes = (
             Prefix(prefix=IPNetwork('10.0.0.0/24'), status=PrefixStatusChoices.STATUS_CONTAINER),