Add support for generating 16-bit ASn
Change-Id: I8b1508361fdc7541c0fc231e7e816651626596b7
This commit is contained in:
parent
a9ac7dc88b
commit
a34640e10e
40
provides.py
40
provides.py
|
@ -54,7 +54,40 @@ class BGPEndpoint(reactive.Endpoint):
|
|||
|
||||
return asn
|
||||
|
||||
def publish_info(self, asn=None, passive=False, bindings=None):
|
||||
def generate_asn_16(self):
|
||||
"""
|
||||
Generate unique 16-bit Private Use [RFC6996] ASn.
|
||||
|
||||
This is useful to automate configuration of BGP routers that is part
|
||||
of a Clos Network Topology with a Layer 3-Only routed design. [RFC7938]
|
||||
|
||||
Assumption:
|
||||
- Unit has a IPv4 address and it is unique to the deployment.
|
||||
|
||||
Implementation:
|
||||
- A private 16-bit ASn has a range of 64512 - 65534
|
||||
which leaves us with 1022 possible endpoints.
|
||||
- The 16-bit ASn space is limited and this implementation
|
||||
will give you unique ASns for a /23
|
||||
|
||||
Note:
|
||||
- This implementation generates ASn in the following range:
|
||||
65023 - 65534
|
||||
- Leaving the following range for any static configuration needs:
|
||||
64512 - 65022
|
||||
"""
|
||||
asn_base = 65023
|
||||
mask = netaddr.IPAddress('0.0.1.255')
|
||||
unit_ip = netaddr.IPAddress(
|
||||
ch_core.hookenv.unit_get('private-address'))
|
||||
masked_ip = unit_ip & mask
|
||||
|
||||
asn = asn_base + int(masked_ip)
|
||||
|
||||
return asn
|
||||
|
||||
def publish_info(self, asn=None, passive=False, bindings=None,
|
||||
use_16bit_asn=False):
|
||||
"""
|
||||
Publish the AS Number and IP address of any extra-bindings of this
|
||||
BGP Endpoint over the relationship.
|
||||
|
@ -70,7 +103,10 @@ class BGPEndpoint(reactive.Endpoint):
|
|||
if asn:
|
||||
myasn = asn
|
||||
else:
|
||||
myasn = self.generate_asn()
|
||||
if use_16bit_asn:
|
||||
myasn = self.generate_asn_16()
|
||||
else:
|
||||
myasn = self.generate_asn()
|
||||
|
||||
# network_get will return addresses for bindings regardless of them
|
||||
# being bound to a network space. detect actual space bindings by
|
||||
|
|
|
@ -33,6 +33,40 @@ class TestBGPProvides(ut_utils.BaseTestCase):
|
|||
asn = endpoint.generate_asn()
|
||||
self.assertEqual(asn, 4294967294)
|
||||
|
||||
def test_generate_asn_16_min(self):
|
||||
self.patch_object(provides, 'ch_core')
|
||||
self.ch_core.hookenv.unit_get.return_value = '0.0.0.0'
|
||||
endpoint = provides.BGPEndpoint('bgpserver')
|
||||
asn = endpoint.generate_asn_16()
|
||||
self.assertEqual(asn, 65023)
|
||||
|
||||
def test_generate_asn_16_collission(self):
|
||||
self.patch_object(provides, 'ch_core')
|
||||
self.ch_core.hookenv.unit_get.return_value = '0.0.0.0'
|
||||
endpoint = provides.BGPEndpoint('bgpserver')
|
||||
self.ch_core.hookenv.unit_get.return_value = '10.0.0.0'
|
||||
asn0 = endpoint.generate_asn_16()
|
||||
self.ch_core.hookenv.unit_get.return_value = '10.0.0.255'
|
||||
asn0_255 = endpoint.generate_asn_16()
|
||||
self.ch_core.hookenv.unit_get.return_value = '10.0.1.0'
|
||||
asn1 = endpoint.generate_asn_16()
|
||||
self.ch_core.hookenv.unit_get.return_value = '10.0.1.255'
|
||||
asn1_255 = endpoint.generate_asn_16()
|
||||
self.ch_core.hookenv.unit_get.return_value = '10.0.2.0'
|
||||
asn2 = endpoint.generate_asn_16()
|
||||
self.assertNotEqual(asn0, asn0_255)
|
||||
self.assertNotEqual(asn0, asn1)
|
||||
self.assertNotEqual(asn0_255, asn1_255)
|
||||
self.assertNotEqual(asn1, asn1_255)
|
||||
self.assertEqual(asn0, asn2)
|
||||
|
||||
def test_generate_asn_16_max(self):
|
||||
self.patch_object(provides, 'ch_core')
|
||||
self.ch_core.hookenv.unit_get.return_value = '255.255.255.255'
|
||||
endpoint = provides.BGPEndpoint('bgpserver')
|
||||
asn = endpoint.generate_asn_16()
|
||||
self.assertEqual(asn, 65534)
|
||||
|
||||
_network_get_side_effect = [
|
||||
yaml.load('''
|
||||
bind-addresses:
|
||||
|
@ -154,6 +188,50 @@ ingress-addresses:
|
|||
}
|
||||
)
|
||||
|
||||
def test_publish_info_16bit_asn(self):
|
||||
self.maxDiff = None
|
||||
self.patch_object(provides, 'ch_core')
|
||||
self.ch_core.hookenv.unit_get.return_value = '172.16.122.251'
|
||||
self.ch_core.hookenv.network_get.side_effect = \
|
||||
self._network_get_side_effect
|
||||
endpoint = provides.BGPEndpoint('bgpserver')
|
||||
endpoint._relations = [self._relation]
|
||||
endpoint.publish_info(bindings=['ptp0', 'ptp1', 'ptp2', 'ptp3',
|
||||
'lan0'], use_16bit_asn=True)
|
||||
self.assertEqual(
|
||||
endpoint.relations[0].to_publish,
|
||||
{
|
||||
'asn': 65274,
|
||||
'bindings': [
|
||||
{
|
||||
'address': '172.16.100.1',
|
||||
'cidr': '172.16.100.0/30'
|
||||
},
|
||||
{
|
||||
'address': '2001:db8:100::1:0:0',
|
||||
'cidr': '2001:db8:100::/64'
|
||||
},
|
||||
{
|
||||
'address': '172.16.110.1',
|
||||
'cidr': '172.16.110.0/30'
|
||||
},
|
||||
{
|
||||
'address': '2001:db8:110::1:0:0',
|
||||
'cidr': '2001:db8:110::/64'
|
||||
},
|
||||
{
|
||||
'address': '172.16.120.1',
|
||||
'cidr': '172.16.120.0/30'
|
||||
},
|
||||
{
|
||||
'address': '2001:db8:120::1:0:0',
|
||||
'cidr': '2001:db8:120::/64'
|
||||
},
|
||||
],
|
||||
'passive': False,
|
||||
}
|
||||
)
|
||||
|
||||
def test_get_received_info(self):
|
||||
self.maxDiff = None
|
||||
self.patch_object(provides, 'ch_core')
|
||||
|
|
Loading…
Reference in New Issue