class StaticIPAllocationTests(unittest.TestCase): """ Test class for the Mobilityd Static IP Allocator """ RECYCLING_INTERVAL_SECONDS = 1 @mock.patch("redis.Redis", MockRedis) def _new_ip_allocator(self, recycling_interval): """ Creates and sets up an IPAllocator with the given recycling interval. """ store = MobilityStore(get_default_client(), False, 3980) ip_allocator = IpAllocatorPool(store) ipv4_allocator = IPAllocatorStaticWrapper( store, subscriberdb_rpc_stub=MockedSubscriberDBStub(), ip_allocator=ip_allocator) ipv6_allocator = IPv6AllocatorPool(store, session_prefix_alloc_mode='RANDOM') self._allocator = IPAddressManager(ipv4_allocator, ipv6_allocator, store, recycling_interval) self._allocator.add_ip_block(self._block) def setUp(self): self._block = ipaddress.ip_network('192.168.0.0/24') self._new_ip_allocator(self.RECYCLING_INTERVAL_SECONDS) def tearDown(self): MockedSubscriberDBStub.clear_subs() def check_type(self, sid: str, type: IPType): ip_desc = self._allocator._store.sid_ips_map[sid] self.assertEqual(ip_desc.type, type) if type == IPType.IP_POOL: ip_block = self._block else: ip_block = ipaddress.ip_network(ip_desc.ip) self.assertEqual(ip_desc.ip_block, ip_block) def check_gw_info(self, vlan: Optional[int], gw_ip: str, gw_mac: Optional[str]): gw_info_ip = self._allocator._store.dhcp_gw_info.get_gw_ip(vlan) self.assertEqual(gw_info_ip, gw_ip) gw_info_mac = self._allocator._store.dhcp_gw_info.get_gw_mac(vlan) self.assertEqual(gw_info_mac, gw_mac) def test_get_ip_for_subscriber(self): """ test get_ip_for_sid without any assignment """ sid = 'IMSI11' with self.assertRaises(SubscriberDBStaticIPValueError): ip0, _ = self._allocator.alloc_ip_address(sid) def test_get_ip_for_subscriber_with_apn(self): """ test get_ip_for_sid with static IP """ apn = 'magma' imsi = 'IMSI110' sid = imsi + '.' + apn + ",ipv4" assigned_ip = '1.2.3.4' MockedSubscriberDBStub.add_sub(sid=imsi, apn=apn, ip=assigned_ip) ip0, _ = self._allocator.alloc_ip_address(sid) ip0_returned = self._allocator.get_ip_for_sid(sid) # check if retrieved ip is the same as the one allocated self.assertEqual(ip0, ip0_returned) self.assertEqual(ip0, ipaddress.ip_address(assigned_ip)) self.check_type(sid, IPType.STATIC) def test_get_ip_for_subscriber_with_different_apn(self): """ test get_ip_for_sid with different APN assigned ip""" apn = 'magma' imsi = 'IMSI110' sid = imsi + '.' + apn + ",ipv4" assigned_ip = '1.2.3.4' MockedSubscriberDBStub.add_sub(sid=imsi, apn="xyz", ip=assigned_ip) ip0, _ = self._allocator.alloc_ip_address(sid) ip0_returned = self._allocator.get_ip_for_sid(sid) # check if retrieved ip is the same as the one allocated self.assertEqual(ip0, ip0_returned) self.assertNotEqual(ip0, ipaddress.ip_address(assigned_ip)) self.check_type(sid, IPType.IP_POOL) def test_get_ip_for_subscriber_with_wildcard_apn(self): """ test wildcard apn""" apn = 'magma' imsi = 'IMSI110' sid = imsi + '.' + apn + ",ipv4" assigned_ip = '1.2.3.4' MockedSubscriberDBStub.add_sub(sid=imsi, apn="*", ip=assigned_ip) ip0, _ = self._allocator.alloc_ip_address(sid) ip0_returned = self._allocator.get_ip_for_sid(sid) # check if retrieved ip is the same as the one allocated self.assertEqual(ip0, ip0_returned) self.assertEqual(ip0, ipaddress.ip_address(assigned_ip)) self.check_type(sid, IPType.STATIC) def test_get_ip_for_subscriber_with_wildcard_and_exact_apn(self): """ test IP assignement from multiple APNs""" apn = 'magma' imsi = 'IMSI110' sid = imsi + '.' + apn + ",ipv4" assigned_ip = '1.2.3.4' assigned_ip_wild = '22.22.22.22' MockedSubscriberDBStub.add_sub(sid=imsi, apn="*", ip=assigned_ip_wild) MockedSubscriberDBStub.add_sub_ip(sid=imsi, apn=apn, ip=assigned_ip) ip0, _ = self._allocator.alloc_ip_address(sid) ip0_returned = self._allocator.get_ip_for_sid(sid) # check if retrieved ip is the same as the one allocated self.assertEqual(ip0, ip0_returned) self.assertEqual(ip0, ipaddress.ip_address(assigned_ip)) self.check_type(sid, IPType.STATIC) def test_get_ip_for_subscriber_with_invalid_ip(self): """ test invalid data from DB """ apn = 'magma' imsi = 'IMSI110' sid = imsi + '.' + apn + ",ipv4" assigned_ip = '1.2.3.hh' MockedSubscriberDBStub.add_sub(sid=imsi, apn=apn, ip=assigned_ip) ip0, _ = self._allocator.alloc_ip_address(sid) ip0_returned = self._allocator.get_ip_for_sid(sid) # check if retrieved ip is the same as the one allocated self.assertEqual(ip0, ip0_returned) self.assertNotEqual(str(ip0), assigned_ip) self.check_type(sid, IPType.IP_POOL) def test_get_ip_for_subscriber_with_multi_apn_but_no_match(self): """ test IP assignment from multiple APNs""" apn = 'magma' imsi = 'IMSI110' sid = imsi + '.' + apn + ",ipv4" assigned_ip = '1.2.3.4' assigned_ip_wild = '22.22.22.22' MockedSubscriberDBStub.add_sub(sid=imsi, apn="abc", ip=assigned_ip_wild) MockedSubscriberDBStub.add_sub_ip(sid=imsi, apn="xyz", ip=assigned_ip) ip0, _ = self._allocator.alloc_ip_address(sid) ip0_returned = self._allocator.get_ip_for_sid(sid) # check if retrieved ip is the same as the one allocated self.assertEqual(ip0, ip0_returned) self.assertNotEqual(ip0, ipaddress.ip_address(assigned_ip)) self.check_type(sid, IPType.IP_POOL) def test_get_ip_for_subscriber_with_incomplete_sub(self): """ test IP assignment from subscriber without non_3gpp config""" apn = 'magma' imsi = 'IMSI110' sid = imsi + '.' + apn + ",ipv4" MockedSubscriberDBStub.add_incomplete_sub(sid=imsi) ip0, _ = self._allocator.alloc_ip_address(sid) ip0_returned = self._allocator.get_ip_for_sid(sid) # check if retrieved ip is the same as the one allocated self.assertEqual(ip0, ip0_returned) self.check_type(sid, IPType.IP_POOL) def test_get_ip_for_subscriber_with_wildcard_no_apn(self): """ test wildcard apn""" imsi = 'IMSI110' sid = imsi + ",ipv4" assigned_ip = '1.2.3.4' MockedSubscriberDBStub.add_sub(sid=imsi, apn="*", ip=assigned_ip) ip0, _ = self._allocator.alloc_ip_address(sid) ip0_returned = self._allocator.get_ip_for_sid(sid) # check if retrieved ip is the same as the one allocated self.assertEqual(ip0, ip0_returned) self.assertEqual(ip0, ipaddress.ip_address(assigned_ip)) self.check_type(sid, IPType.STATIC) def test_get_ip_for_subscriber_with_apn_dot(self): """ test get_ip_for_sid with static IP """ apn = 'magma.ipv4' imsi = 'IMSI110' sid = imsi + '.' + apn + ",ipv4" assigned_ip = '1.2.3.4' MockedSubscriberDBStub.add_sub(sid=imsi, apn=apn, ip=assigned_ip) ip0, _ = self._allocator.alloc_ip_address(sid) ip0_returned = self._allocator.get_ip_for_sid(sid) # check if retrieved ip is the same as the one allocated self.assertEqual(ip0, ip0_returned) self.assertEqual(ip0, ipaddress.ip_address(assigned_ip)) self.check_type(sid, IPType.STATIC) def test_get_ip_for_subscriber_with_wildcard_and_no_exact_apn(self): """ test IP assignement from multiple APNs""" apn = 'magma' imsi = 'IMSI110' sid = imsi + '.' + apn + ",ipv4" assigned_ip = '1.2.3.4' assigned_ip_wild = '22.22.22.22' MockedSubscriberDBStub.add_sub(sid=imsi, apn="*", ip=assigned_ip_wild) MockedSubscriberDBStub.add_sub_ip(sid=imsi, apn="xyz", ip=assigned_ip) ip0, _ = self._allocator.alloc_ip_address(sid) ip0_returned = self._allocator.get_ip_for_sid(sid) # check if retrieved ip is the same as the one allocated self.assertEqual(ip0, ip0_returned) self.assertEqual(ip0, ipaddress.ip_address(assigned_ip_wild)) self.check_type(sid, IPType.STATIC) def test_get_ip_for_subscriber_with_wildcard_and_exact_apn_no_ip(self): """ test IP assignement from multiple APNs""" apn = 'magma' imsi = 'IMSI110' sid = imsi + '.' + apn + ",ipv4" assigned_ip_wild = '22.22.22.22' MockedSubscriberDBStub.add_sub(sid=imsi, apn="*", ip=assigned_ip_wild) MockedSubscriberDBStub.add_sub_ip(sid=imsi, apn=apn, ip=None) ip0, _ = self._allocator.alloc_ip_address(sid) ip0_returned = self._allocator.get_ip_for_sid(sid) # check if retrieved ip is the same as the one allocated self.assertEqual(ip0, ip0_returned) self.assertNotEqual(ip0, ipaddress.ip_address(assigned_ip_wild)) self.check_type(sid, IPType.IP_POOL) def test_get_ip_for_subscriber_with_apn_with_gw(self): """ test get_ip_for_sid with static IP """ apn = 'magma' imsi = 'IMSI110' sid = imsi + '.' + apn + ",ipv4" assigned_ip = '1.2.3.4' gw_ip = "1.2.3.1" gw_mac = "11:22:33:11:77:28" MockedSubscriberDBStub.add_sub(sid=imsi, apn=apn, ip=assigned_ip, gw_ip=gw_ip, gw_mac=gw_mac) ip0, _ = self._allocator.alloc_ip_address(sid) ip0_returned = self._allocator.get_ip_for_sid(sid) # check if retrieved ip is the same as the one allocated self.assertEqual(ip0, ip0_returned) self.assertEqual(ip0, ipaddress.ip_address(assigned_ip)) self.check_type(sid, IPType.STATIC) self.check_gw_info(None, gw_ip, gw_mac) def test_get_ip_for_subscriber_with_only_wildcard_apn_gw(self): """ test wildcard apn""" apn = 'magma' imsi = 'IMSI110' sid = imsi + '.' + apn + ",ipv4" assigned_ip = '1.2.3.4' gw_ip = "1.2.3.100" gw_mac = "11:22:33:11:77:81" MockedSubscriberDBStub.add_sub(sid=imsi, apn="*", ip=assigned_ip, gw_ip=gw_ip, gw_mac=gw_mac) ip0, _ = self._allocator.alloc_ip_address(sid) ip0_returned = self._allocator.get_ip_for_sid(sid) # check if retrieved ip is the same as the one allocated self.assertEqual(ip0, ip0_returned) self.assertEqual(ip0, ipaddress.ip_address(assigned_ip)) self.check_type(sid, IPType.STATIC) def test_get_ip_for_subscriber_with_apn_with_gw_vlan(self): """ test get_ip_for_sid with static IP """ apn = 'magma' imsi = 'IMSI110' sid = imsi + '.' + apn + ",ipv4" assigned_ip = '1.2.3.4' gw_ip = "1.2.3.1" gw_mac = "11:22:33:11:77:44" vlan = "200" MockedSubscriberDBStub.add_sub(sid=imsi, apn=apn, ip=assigned_ip, gw_ip=gw_ip, gw_mac=gw_mac, vlan=vlan) ip0, _ = self._allocator.alloc_ip_address(sid) ip0_returned = self._allocator.get_ip_for_sid(sid) # check if retrieved ip is the same as the one allocated self.assertEqual(ip0, ip0_returned) self.assertEqual(ip0, ipaddress.ip_address(assigned_ip)) self.check_type(sid, IPType.STATIC) self.check_gw_info(vlan, gw_ip, gw_mac) def test_get_ip_for_subscriber_with_apn_with_gw_invalid_ip(self): """ test get_ip_for_sid with static IP """ apn = 'magma' imsi = 'IMSI110' sid = imsi + '.' + apn + ",ipv4" assigned_ip = '1.2.3.4' gw_ip = "1.2.3.1333" gw_mac = "11:22:33:11:77:76" vlan = "200" MockedSubscriberDBStub.add_sub(sid=imsi, apn=apn, ip=assigned_ip, gw_ip=gw_ip, gw_mac=gw_mac, vlan=vlan) ip0, _ = self._allocator.alloc_ip_address(sid) ip0_returned = self._allocator.get_ip_for_sid(sid) # check if retrieved ip is the same as the one allocated self.assertEqual(ip0, ip0_returned) self.assertEqual(ip0, ipaddress.ip_address(assigned_ip)) self.check_type(sid, IPType.STATIC) self.check_gw_info(vlan, None, None) def test_get_ip_for_subscriber_with_apn_with_gw_nul_ip(self): """ test get_ip_for_sid with static IP """ apn = 'magma' imsi = 'IMSI110' sid = imsi + '.' + apn + ",ipv4" assigned_ip = '1.2.3.4' gw_ip = "" gw_mac = "11:22:33:11:77:45" vlan = "200" MockedSubscriberDBStub.add_sub(sid=imsi, apn=apn, ip=assigned_ip, gw_ip=gw_ip, gw_mac=gw_mac, vlan=vlan) ip0, _ = self._allocator.alloc_ip_address(sid) ip0_returned = self._allocator.get_ip_for_sid(sid) # check if retrieved ip is the same as the one allocated self.assertEqual(ip0, ip0_returned) self.assertEqual(ip0, ipaddress.ip_address(assigned_ip)) self.check_type(sid, IPType.STATIC) self.check_gw_info(vlan, None, None) def test_get_ip_for_subscriber_with_apn_with_gw_nul_mac(self): """ test get_ip_for_sid with static IP """ apn = 'magma' imsi = 'IMSI110' sid = imsi + '.' + apn + ",ipv4" assigned_ip = '1.2.3.24' gw_ip = "1.2.3.55" gw_mac = None vlan = "200" MockedSubscriberDBStub.add_sub(sid=imsi, apn=apn, ip=assigned_ip, gw_ip=gw_ip, gw_mac=gw_mac, vlan=vlan) ip0, _ = self._allocator.alloc_ip_address(sid) ip0_returned = self._allocator.get_ip_for_sid(sid) # check if retrieved ip is the same as the one allocated self.assertEqual(ip0, ip0_returned) self.assertEqual(ip0, ipaddress.ip_address(assigned_ip)) self.check_type(sid, IPType.STATIC) self.check_gw_info(vlan, gw_ip, "") def test_get_ip_for_subscriber_with_wildcard_apn_gw(self): """ test wildcard apn""" apn = 'magma' imsi = 'IMSI110' sid = imsi + '.' + apn + ",ipv4" assigned_ip = '1.2.3.4' gw_ip = "1.2.3.100" gw_mac = "11:22:33:11:77:81" vlan = "300" MockedSubscriberDBStub.add_sub(sid=imsi, apn=apn, ip=assigned_ip, gw_ip=gw_ip, gw_mac=gw_mac, vlan=vlan) wildcard_assigned_ip = "20.20.20.20" wildcard_gw_ip = "1.2.7.7" wildcard_gw_mac = "11:22:33:88:77:99" wildcard_vlan = "400" MockedSubscriberDBStub.add_sub_ip(sid=imsi, apn="*", ip=wildcard_assigned_ip, gw_ip=wildcard_gw_ip, gw_mac=wildcard_gw_mac, vlan=wildcard_vlan) ip0, _ = self._allocator.alloc_ip_address(sid) ip0_returned = self._allocator.get_ip_for_sid(sid) # check if retrieved ip is the same as the one allocated self.assertEqual(ip0, ip0_returned) self.assertEqual(ip0, ipaddress.ip_address(assigned_ip)) self.check_type(sid, IPType.STATIC) self.check_gw_info(vlan, gw_ip, gw_mac) self.check_gw_info(wildcard_vlan, None, None) def test_get_ip_for_subscriber_with_apn_with_gw_invalid_vlan(self): """ test get_ip_for_sid with static IP """ apn = 'magma' imsi = 'IMSI110' sid = imsi + '.' + apn + ",ipv4" assigned_ip = '1.2.3.4' gw_ip = "1.2.3.1" gw_mac = "11:22:33:11:77:44" vlan = "20000" MockedSubscriberDBStub.add_sub(sid=imsi, apn=apn, ip=assigned_ip, gw_ip=gw_ip, gw_mac=gw_mac, vlan=vlan) with self.assertRaises(InvalidVlanId): ip0, _ = self._allocator.alloc_ip_address(sid) def test_get_ip_for_subscriber_with_apn_dup_assignment(self): """ test duplicate static IPs """ apn = 'magma' imsi = 'IMSI110' sid = imsi + '.' + apn + ",ipv4" assigned_ip = '1.2.3.4' MockedSubscriberDBStub.add_sub(sid=imsi, apn=apn, ip=assigned_ip) ip0, _ = self._allocator.alloc_ip_address(sid) ip0_returned = self._allocator.get_ip_for_sid(sid) # check if retrieved ip is the same as the one allocated self.assertEqual(ip0, ip0_returned) self.assertEqual(ip0, ipaddress.ip_address(assigned_ip)) self.check_type(sid, IPType.STATIC) apn = 'magma' imsi = 'IMSI999' sid = imsi + '.' + apn + ",ipv4" MockedSubscriberDBStub.add_sub(sid=imsi, apn=apn, ip=assigned_ip) with self.assertRaises(DuplicateIPAssignmentError): ip0, _ = self._allocator.alloc_ip_address(sid) def test_get_ip_for_2_subscribers_with_apn(self): """ test duplicate static IPs """ apn = 'magma' imsi = 'IMSI110' sid = imsi + '.' + apn + ",ipv4" assigned_ip = '1.2.3.4' MockedSubscriberDBStub.add_sub(sid=imsi, apn=apn, ip=assigned_ip) ip0, _ = self._allocator.alloc_ip_address(sid) ip0_returned = self._allocator.get_ip_for_sid(sid) # check if retrieved ip is the same as the one allocated self.assertEqual(ip0, ip0_returned) self.assertEqual(ip0, ipaddress.ip_address(assigned_ip)) self.check_type(sid, IPType.STATIC) apn1 = 'magma' imsi1 = 'IMSI999' assigned_ip1 = '1.2.3.5' sid1 = imsi1 + '.' + apn1 + ",ipv4" MockedSubscriberDBStub.add_sub(sid=imsi1, apn=apn1, ip=assigned_ip1) ip1, _ = self._allocator.alloc_ip_address(sid1) ip1_returned = self._allocator.get_ip_for_sid(sid1) # check if retrieved ip is the same as the one allocated self.assertEqual(ip1, ip1_returned) self.assertEqual(ip1, ipaddress.ip_address(assigned_ip1)) self.check_type(sid, IPType.STATIC) def test_get_ip_for_subscriber_with_apn_overlap_ip_pool(self): """ test get_ip_for_sid with static IP """ apn = 'magma' imsi = 'IMSI110' sid = imsi + '.' + apn + ",ipv4" assigned_ip = '192.168.0.10' MockedSubscriberDBStub.add_sub(sid=imsi, apn=apn, ip=assigned_ip) with self.assertRaises(DuplicateIPAssignmentError): ip0, _ = self._allocator.alloc_ip_address(sid)
class MultiAPNIPAllocationTests(unittest.TestCase): """ Test class for the Mobilityd Multi APN Allocator """ RECYCLING_INTERVAL_SECONDS = 1 def _new_ip_allocator(self, recycling_interval): """ Creates and sets up an IPAllocator with the given recycling interval. """ config = { 'recycling_interval': recycling_interval, 'persist_to_redis': False, 'redis_port': 6379, 'multi_apn': True, } mconfig = MobilityD(ip_allocator_type=MobilityD.IP_POOL, static_ip_enabled=True) self._allocator = IPAddressManager( recycling_interval=recycling_interval, subscriberdb_rpc_stub=MockedSubscriberDBStub(), config=config, mconfig=mconfig) self._allocator.add_ip_block(self._block) def setUp(self): self._block = ipaddress.ip_network('192.168.0.0/28') self._new_ip_allocator(self.RECYCLING_INTERVAL_SECONDS) def tearDown(self): MockedSubscriberDBStub.clear_subs() def check_type(self, sid: str, type1: IPType): ip_desc = self._allocator.sid_ips_map[sid] self.assertEqual(ip_desc.type, type1) def check_vlan(self, sid: str, vlan: str): ip_desc = self._allocator.sid_ips_map[sid] logging.info("type ip_desc.vlan_id %s vlan %s", type(ip_desc.vlan_id), type(vlan)) self.assertEqual(ip_desc.vlan_id, vlan) def check_gw_info(self, vlan: Optional[int], gw_ip: str, gw_mac: Optional[str]): gw_info_ip = self._allocator._dhcp_gw_info.get_gw_ip(vlan) self.assertEqual(gw_info_ip, gw_ip) gw_info_mac = self._allocator._dhcp_gw_info.get_gw_mac(vlan) self.assertEqual(gw_info_mac, gw_mac) def test_get_ip_vlan_for_subscriber(self): """ test get_ip_for_sid without any assignment """ sid = 'IMSI11' ip0, _ = self._allocator.alloc_ip_address(sid) ip0_returned = self._allocator.get_ip_for_sid(sid) # check if retrieved ip is the same as the one allocated self.assertEqual(ip0, ip0_returned) self.check_type(sid, IPType.IP_POOL) def test_get_ip_vlan_for_subscriber_with_apn(self): """ test get_ip_for_sid with static IP """ apn = 'magma' imsi = 'IMSI110' sid = imsi + '.' + apn assigned_ip = '1.2.3.4' vlan = 132 MockedSubscriberDBStub.add_sub(sid=imsi, apn=apn, ip=assigned_ip, vlan=vlan) ip0, _ = self._allocator.alloc_ip_address(sid) ip0_returned = self._allocator.get_ip_for_sid(sid) # check if retrieved ip is the same as the one allocated self.assertEqual(ip0, ip0_returned) self.assertEqual(ip0, ipaddress.ip_address(assigned_ip)) self.check_type(sid, IPType.STATIC) self.check_vlan(sid, vlan) self.check_gw_info(vlan, None, None) def test_get_ip_vlan_for_subscriber_with_different_apn(self): """ test get_ip_for_sid with different APN assigned ip""" apn = 'magma' imsi = 'IMSI110' sid = imsi + '.' + apn assigned_ip = '1.2.3.4' vlan = 188 MockedSubscriberDBStub.add_sub(sid=imsi, apn="xyz", ip=assigned_ip, vlan=vlan) ip0, _ = self._allocator.alloc_ip_address(sid) ip0_returned = self._allocator.get_ip_for_sid(sid) # check if retrieved ip is the same as the one allocated self.assertEqual(ip0, ip0_returned) self.assertNotEqual(ip0, ipaddress.ip_address(assigned_ip)) self.check_type(sid, IPType.IP_POOL) self.check_vlan(sid, 0) self.check_gw_info(vlan, None, None) def test_get_ip_vlan_for_subscriber_with_wildcard_apn(self): """ test wildcard apn""" apn = 'magma' imsi = 'IMSI110' sid = imsi + '.' + apn assigned_ip = '1.2.3.4' vlan = 166 MockedSubscriberDBStub.add_sub(sid=imsi, apn="*", ip=assigned_ip, vlan=vlan) ip0, _ = self._allocator.alloc_ip_address(sid) ip0_returned = self._allocator.get_ip_for_sid(sid) # check if retrieved ip is the same as the one allocated self.assertEqual(ip0, ip0_returned) self.assertEqual(ip0, ipaddress.ip_address(assigned_ip)) self.check_type(sid, IPType.STATIC) self.check_vlan(sid, vlan) self.check_gw_info(vlan, None, None) def test_get_ip_vlan_for_subscriber_with_wildcard_and_exact_apn(self): """ test IP assignement from multiple APNs""" apn = 'magma' imsi = 'IMSI110' sid = imsi + '.' + apn assigned_ip = '1.2.3.4' wild_assigned_ip = '44.2.3.11' vlan = 44 vlan_wild = 66 MockedSubscriberDBStub.add_sub(sid=imsi, apn="*", ip=wild_assigned_ip, vlan=vlan_wild) MockedSubscriberDBStub.add_sub_ip(sid=imsi, apn=apn, ip=assigned_ip, vlan=vlan) ip0, _ = self._allocator.alloc_ip_address(sid) ip0_returned = self._allocator.get_ip_for_sid(sid) # check if retrieved ip is the same as the one allocated self.assertEqual(ip0, ip0_returned) self.assertEqual(ip0, ipaddress.ip_address(assigned_ip)) self.check_type(sid, IPType.STATIC) self.check_vlan(sid, vlan) self.check_gw_info(vlan, None, None) def test_get_ip_vlan_for_subscriber_with_invalid_ip(self): """ test invalid data from DB """ apn = 'magma' imsi = 'IMSI110' sid = imsi + '.' + apn assigned_ip = '1.2.3.hh' vlan = 111 MockedSubscriberDBStub.add_sub(sid=imsi, apn=apn, ip=assigned_ip, vlan=vlan) ip0, _ = self._allocator.alloc_ip_address(sid) ip0_returned = self._allocator.get_ip_for_sid(sid) # check if retrieved ip is the same as the one allocated self.assertEqual(ip0, ip0_returned) self.assertNotEqual(str(ip0), assigned_ip) self.check_type(sid, IPType.IP_POOL) self.check_vlan(sid, 0) self.check_gw_info(vlan, None, None) def test_get_ip_vlan_for_subscriber_with_multi_apn_but_no_match(self): """ test IP assignment from multiple APNs""" apn = 'magma' imsi = 'IMSI110' sid = imsi + '.' + apn assigned_ip = '1.2.3.4' vlan = 31 vlan_wild = 552 MockedSubscriberDBStub.add_sub(sid=imsi, apn="abc", ip=assigned_ip, vlan=vlan_wild) MockedSubscriberDBStub.add_sub_ip(sid=imsi, apn="xyz", ip=assigned_ip, vlan=vlan) ip0, _ = self._allocator.alloc_ip_address(sid) ip0_returned = self._allocator.get_ip_for_sid(sid) # check if retrieved ip is the same as the one allocated self.assertEqual(ip0, ip0_returned) self.assertNotEqual(ip0, ipaddress.ip_address(assigned_ip)) self.check_type(sid, IPType.IP_POOL) self.check_vlan(sid, 0) self.check_gw_info(vlan, None, None) def test_get_ip_vlan_for_subscriber_with_incomplete_sub(self): """ test IP assignment from subscriber without non_3gpp config""" apn = 'magma' imsi = 'IMSI110' sid = imsi + '.' + apn MockedSubscriberDBStub.add_incomplete_sub(sid=imsi) ip0, _ = self._allocator.alloc_ip_address(sid) ip0_returned = self._allocator.get_ip_for_sid(sid) # check if retrieved ip is the same as the one allocated self.assertEqual(ip0, ip0_returned) self.check_type(sid, IPType.IP_POOL) self.check_vlan(sid, 0) def test_get_ip_vlan_for_subscriber_with_wildcard_no_apn(self): """ test wildcard apn""" imsi = 'IMSI110' sid = imsi assigned_ip = '1.2.3.4' vlan = 122 MockedSubscriberDBStub.add_sub(sid=imsi, apn="*", ip=assigned_ip, vlan=vlan) ip0, _ = self._allocator.alloc_ip_address(sid) ip0_returned = self._allocator.get_ip_for_sid(sid) # check if retrieved ip is the same as the one allocated self.assertEqual(ip0, ip0_returned) self.assertEqual(ip0, ipaddress.ip_address(assigned_ip)) self.check_type(sid, IPType.STATIC) self.check_vlan(sid, vlan) self.check_gw_info(vlan, None, None) def test_get_ip_vlan_for_subscriber_with_apn_dot(self): """ test get_ip_for_sid with static IP """ apn = 'magma.ipv4' imsi = 'IMSI110' sid = imsi + '.' + apn assigned_ip = '1.2.3.4' vlan = 165 MockedSubscriberDBStub.add_sub(sid=imsi, apn=apn, ip=assigned_ip, vlan=vlan) ip0, _ = self._allocator.alloc_ip_address(sid) ip0_returned = self._allocator.get_ip_for_sid(sid) # check if retrieved ip is the same as the one allocated self.assertEqual(ip0, ip0_returned) self.assertEqual(ip0, ipaddress.ip_address(assigned_ip)) self.check_type(sid, IPType.STATIC) self.check_vlan(sid, vlan) self.check_gw_info(vlan, None, None) def test_get_ip_vlan_for_subscriber_with_wildcard_and_no_exact_apn(self): """ test IP assignement from multiple APNs""" apn = 'dsddf' imsi = 'IMSI110' sid = imsi + '.' + apn assigned_ip = '1.2.3.4' wild_assigned_ip = '44.2.3.11' vlan = 0 vlan_wild = 66 MockedSubscriberDBStub.add_sub(sid=imsi, apn="*", ip=wild_assigned_ip, vlan=vlan_wild) MockedSubscriberDBStub.add_sub_ip(sid=imsi, apn="xyz", ip=assigned_ip, vlan=vlan) ip0, _ = self._allocator.alloc_ip_address(sid) ip0_returned = self._allocator.get_ip_for_sid(sid) # check if retrieved ip is the same as the one allocated self.assertEqual(ip0, ip0_returned) self.assertEqual(ip0, ipaddress.ip_address(wild_assigned_ip)) self.check_type(sid, IPType.STATIC) self.check_vlan(sid, vlan_wild) self.check_gw_info(vlan, None, None) def test_get_ip_vlan_for_subscriber_with_wildcard_and_exact_apn_no_ip( self): """ test IP assignement from multiple APNs""" apn = 'magma' imsi = 'IMSI110' sid = imsi + '.' + apn wild_assigned_ip = '44.2.3.11' vlan = 44 vlan_wild = 66 MockedSubscriberDBStub.add_sub(sid=imsi, apn="*", ip=wild_assigned_ip, vlan=vlan_wild) MockedSubscriberDBStub.add_sub_ip(sid=imsi, apn=apn, ip=None, vlan=vlan) ip0, _ = self._allocator.alloc_ip_address(sid) ip0_returned = self._allocator.get_ip_for_sid(sid) # check if retrieved ip is the same as the one allocated self.assertEqual(ip0, ip0_returned) self.assertEqual(ip0, ipaddress.ip_address(wild_assigned_ip)) self.check_type(sid, IPType.STATIC) self.check_vlan(sid, vlan_wild) self.check_gw_info(vlan, None, None)
class IPAllocatorTests(unittest.TestCase): """ Test class for the Mobilityd IP Allocator """ RECYCLING_INTERVAL_SECONDS = 1 def _new_ip_allocator(self, recycling_interval): """ Creates and sets up an IPAllocator with the given recycling interval. """ # NOTE: change below to True to run IP allocator tests locally. We # don't persist to Redis during normal unit tests since they are run # in Sandcastle. config = { 'recycling_interval': recycling_interval, 'persist_to_redis': False, 'redis_port': 6379, } self._allocator = IPAddressManager( recycling_interval=recycling_interval, allocator_type=MobilityD.IP_POOL, config=config) self._allocator.add_ip_block(self._block) def setUp(self): # need to allocate at least 4 bits, as 13 addresses # are either preallocated or not valid for hosts self._block = ipaddress.ip_network('192.168.0.0/28') # 192.168.0.0 is not valid host IP # 192.168.0.1 to 192.168.0.11 are preallocated self._ip0 = ipaddress.ip_address('192.168.0.12') self._ip1 = ipaddress.ip_address('192.168.0.13') self._ip2 = ipaddress.ip_address('192.168.0.14') self._new_ip_allocator(self.RECYCLING_INTERVAL_SECONDS) def test_list_added_ip_blocks(self): """ test list assigned IP blocks """ ip_block_list = self._allocator.list_added_ip_blocks() self.assertEqual(ip_block_list, [self._block]) def test_list_empty_ip_block(self): """ test list empty ip block """ ip_list = self._allocator.list_allocated_ips(self._block) self.assertEqual(len(ip_list), 0) def test_list_unknown_ip_block(self): """ test list unknown ip block """ block = ipaddress.ip_network('10.0.0.0/28') with self.assertRaises(IPBlockNotFoundError): self._allocator.list_allocated_ips(block) def test_alloc_ip_address(self): """ test alloc_ip_address """ ip0 = self._allocator.alloc_ip_address('SID0') self.assertTrue(ip0 in [self._ip0, self._ip1, self._ip2]) self.assertTrue(ip0 in self._allocator.list_allocated_ips(self._block)) self.assertEqual(self._allocator.get_sid_ip_table(), [('SID0', ip0)]) ip1 = self._allocator.alloc_ip_address('SID1') self.assertTrue(ip1 in [self._ip0, self._ip1, self._ip2]) self.assertNotEqual(ip1, ip0) self.assertEqual({ip0, ip1}, set(self._allocator.list_allocated_ips(self._block))) self.assertEqual(set(self._allocator.get_sid_ip_table()), {('SID0', ip0), ('SID1', ip1)}) ip2 = self._allocator.alloc_ip_address('SID2') self.assertTrue(ip2 in [self._ip0, self._ip1, self._ip2]) self.assertNotEqual(ip2, ip0) self.assertNotEqual(ip2, ip1) self.assertEqual({ip0, ip1, ip2}, set(self._allocator.list_allocated_ips(self._block))) self.assertEqual(set(self._allocator.get_sid_ip_table()), {('SID0', ip0), ('SID1', ip1), ('SID2', ip2)}) # allocate from empty free set with self.assertRaises(NoAvailableIPError): self._allocator.alloc_ip_address('SID3') def test_release_ip_address(self): """ test release_ip_address """ ip0 = self._allocator.alloc_ip_address('SID0') ip1 = self._allocator.alloc_ip_address('SID1') ip2 = self._allocator.alloc_ip_address('SID2') # release ip self._allocator.release_ip_address('SID0', ip0) self.assertFalse( ip0 in self._allocator.list_allocated_ips(self._block)) # check not recyled self.assertEqual(set(self._allocator.get_sid_ip_table()), {('SID0', ip0), ('SID1', ip1), ('SID2', ip2)}) with self.assertRaises(NoAvailableIPError): self._allocator.alloc_ip_address('SID3') # double release with self.assertRaises(IPNotInUseError): self._allocator.release_ip_address('SID0', ip0) # ip does not exist with self.assertRaises(MappingNotFoundError): non_existing_ip = ipaddress.ip_address('192.168.1.16') self._allocator.release_ip_address('SID0', non_existing_ip) def test_get_ip_for_subscriber(self): """ test get_ip_for_sid """ ip0 = self._allocator.alloc_ip_address('SID0') ip1 = self._allocator.alloc_ip_address('SID1') ip0_returned = self._allocator.get_ip_for_sid('SID0') ip1_returned = self._allocator.get_ip_for_sid('SID1') # check if retrieved ip is the same as the one allocated self.assertEqual(ip0, ip0_returned) self.assertEqual(ip1, ip1_returned) def test_get_ip_for_unknown_subscriber(self): """ Getting ip for non existent subscriber should return None """ self.assertIsNone(self._allocator.get_ip_for_sid('SID0')) def test_get_sid_for_ip(self): """ test get_sid_for_ip """ ip0 = self._allocator.alloc_ip_address('SID0') ip1 = self._allocator.alloc_ip_address('SID1') sid0_returned = self._allocator.get_sid_for_ip(ip0) sid1_returned = self._allocator.get_sid_for_ip(ip1) self.assertEqual('SID0', sid0_returned) self.assertEqual('SID1', sid1_returned) def test_get_sid_for_unknown_ip(self): """ Getting sid for non allocated ip address should return None """ self.assertIsNone( self._allocator.get_sid_for_ip(ipaddress.ip_address('1.1.1.1'))) def test_allocate_allocate(self): """ Duplicated IP requests for the same UE returns same IP """ ip0 = self._allocator.alloc_ip_address('SID0') ip1 = self._allocator.alloc_ip_address('SID0') self.assertEqual(ip0, ip1) def test_allocated_release_allocate(self): """ Immediate allocation after releasing get the same IP """ ip0 = self._allocator.alloc_ip_address('SID0') self._allocator.release_ip_address('SID0', ip0) ip2 = self._allocator.alloc_ip_address('SID0') self.assertEqual(ip0, ip2) def test_allocate_release_recycle_allocate(self): """ Allocation after recycling should get different IPs """ ip0 = self._allocator.alloc_ip_address('SID0') self._allocator.release_ip_address('SID0', ip0) # Wait for auto-recycler to kick in time.sleep(1.2 * self.RECYCLING_INTERVAL_SECONDS) ip1 = self._allocator.alloc_ip_address('SID1') ip2 = self._allocator.alloc_ip_address('SID0') self.assertNotEqual(ip1, ip2) def test_recycle_tombstone_ip_on_timer(self): """ test recycle tombstone IP on interval loop """ ip0 = self._allocator.alloc_ip_address('SID0') ip1 = self._allocator.alloc_ip_address('SID1') ip2 = self._allocator.alloc_ip_address('SID2') self._allocator.release_ip_address('SID0', ip0) # Wait for auto-recycler to kick in time.sleep(2 * self.RECYCLING_INTERVAL_SECONDS) ip3 = self._allocator.alloc_ip_address('SID3') self.assertEqual(ip0, ip3) self._allocator.release_ip_address('SID1', ip1) # Wait for auto-recycler to kick in time.sleep(2 * self.RECYCLING_INTERVAL_SECONDS) ip4 = self._allocator.alloc_ip_address('SID4') self.assertEqual(ip1, ip4) self._allocator.release_ip_address('SID2', ip2) # Wait for auto-recycler to kick in time.sleep(2 * self.RECYCLING_INTERVAL_SECONDS) ip5 = self._allocator.alloc_ip_address('SID5') self.assertEqual(ip2, ip5) def test_allocate_unrecycled_IP(self): """ Allocation should fail before IP recycling """ ip0 = self._allocator.alloc_ip_address('SID0') self._allocator.alloc_ip_address('SID1') self._allocator.alloc_ip_address('SID2') self._allocator.release_ip_address('SID0', ip0) with self.assertRaises(NoAvailableIPError): self._allocator.alloc_ip_address('SID3') def test_recycle_tombstone_ip(self): """ test recycle tombstone IP """ self._new_ip_allocator(0) ip0 = self._allocator.alloc_ip_address('SID0') ip1 = self._allocator.alloc_ip_address('SID1') ip2 = self._allocator.alloc_ip_address('SID2') self._allocator.release_ip_address('SID0', ip0) ip3 = self._allocator.alloc_ip_address('SID3') self.assertEqual(ip0, ip3) self._allocator.release_ip_address('SID1', ip1) ip4 = self._allocator.alloc_ip_address('SID4') self.assertEqual(ip1, ip4) self._allocator.release_ip_address('SID2', ip2) ip5 = self._allocator.alloc_ip_address('SID5') self.assertEqual(ip2, ip5) def test_remove_unallocated_block(self): """ test removing the allocator for an unallocated block """ self.assertEqual({self._block}, self._allocator.remove_ip_blocks(self._block)) def test_remove_allocated_block_without_force(self): """ test removing the allocator for an allocated block unforcibly """ self._allocator.alloc_ip_address('SID0') self.assertEqual( set(), self._allocator.remove_ip_blocks(self._block, force=False)) def test_remove_unforcible_is_default_behavior(self): """ test that removing by default is unforcible remove """ self._allocator.alloc_ip_address('SID0') self.assertEqual(set(), self._allocator.remove_ip_blocks(self._block)) def test_remove_allocated_block_with_force(self): """ test removing the allocator for an allocated block forcibly """ self._allocator.alloc_ip_address('SID0') self.assertEqual({self._block}, self._allocator.remove_ip_blocks(self._block, force=True)) def test_remove_after_releasing_all_addresses(self): """ removing after releasing all allocated addresses """ self._new_ip_allocator(0) # Immediately recycle ip0 = self._allocator.alloc_ip_address('SID0') ip1 = self._allocator.alloc_ip_address('SID1') self.assertEqual( set(), self._allocator.remove_ip_blocks(self._block, force=False)) self._allocator.release_ip_address('SID0', ip0) self._allocator.release_ip_address('SID1', ip1) self.assertEqual({self._block}, self._allocator.remove_ip_blocks(self._block, force=False)) def test_remove_after_releasing_some_addresses(self): """ removing after releasing all allocated addresses """ self._new_ip_allocator(0) # Immediately recycle ip0 = self._allocator.alloc_ip_address('SID0') ip1 = self._allocator.alloc_ip_address('SID1') self.assertEqual( set(), self._allocator.remove_ip_blocks(self._block, force=False)) self._allocator.release_ip_address('SID0', ip0) self.assertEqual( set(), self._allocator.remove_ip_blocks(self._block, force=False)) self.assertTrue( ip0 not in self._allocator.list_allocated_ips(self._block)) self.assertTrue(ip1 in self._allocator.list_allocated_ips(self._block)) def test_reap_after_forced_remove(self): """ test reaping after a forced remove and readding the reaped ips doesn't free them """ recycling_interval_seconds = 1 # plenty of time to set up self._new_ip_allocator(recycling_interval_seconds) ip0 = self._allocator.alloc_ip_address('SID0') ip1 = self._allocator.alloc_ip_address('SID1') self._allocator.release_ip_address('SID0', ip0) self.assertEqual({self._block}, self._allocator.remove_ip_blocks(self._block, force=True)) self._allocator.add_ip_block(self._block) ip0 = self._allocator.alloc_ip_address('SID0') ip1 = self._allocator.alloc_ip_address('SID1') # Wait for auto-recycler to kick in time.sleep(recycling_interval_seconds) # Ensure that released-then-allocated address doesn't get reaped self.assertTrue(ip0 in self._allocator.list_allocated_ips(self._block)) self.assertTrue(ip1 in self._allocator.list_allocated_ips(self._block))
def main(): """Start mobilityd""" service = MagmaService('mobilityd', mconfigs_pb2.MobilityD()) # Optionally pipe errors to Sentry sentry_init(service_name=service.name) # Load service configs and mconfig config = service.config mconfig = service.mconfig multi_apn = config.get('multi_apn', mconfig.multi_apn_ip_alloc) static_ip_enabled = config.get('static_ip', mconfig.static_ip_enabled) allocator_type = mconfig.ip_allocator_type dhcp_iface = config.get('dhcp_iface', 'dhcp0') dhcp_retry_limit = config.get('retry_limit', RETRY_LIMIT) # TODO: consider adding gateway mconfig to decide whether to # persist to Redis client = get_default_client() store = MobilityStore( client, config.get('persist_to_redis', False), config.get('redis_port', DEFAULT_REDIS_PORT), ) chan = ServiceRegistry.get_rpc_channel( 'subscriberdb', ServiceRegistry.LOCAL, ) ipv4_allocator = _get_ipv4_allocator( store, allocator_type, static_ip_enabled, multi_apn, dhcp_iface, dhcp_retry_limit, SubscriberDBStub(chan), ) # Init IPv6 allocator, for now only IP_POOL mode is supported for IPv6 ipv6_allocator = IPv6AllocatorPool( store=store, session_prefix_alloc_mode=_get_value_or_default( mconfig.ipv6_prefix_allocation_type, DEFAULT_IPV6_PREFIX_ALLOC_MODE, ), ) # Load IPAddressManager ip_address_man = IPAddressManager(ipv4_allocator, ipv6_allocator, store) # Load IPv4 and IPv6 blocks from the configurable mconfig file # No dynamic reloading support for now, assume restart after updates ipv4_block = _get_ip_block(mconfig.ip_block, "IPv4") if ipv4_block is not None: logging.info('Adding IPv4 block') try: allocated_ip_blocks = ip_address_man.list_added_ip_blocks() if ipv4_block not in allocated_ip_blocks: # Cleanup previously allocated IP blocks ip_address_man.remove_ip_blocks(*allocated_ip_blocks, force=True) ip_address_man.add_ip_block(ipv4_block) except OverlappedIPBlocksError: logging.warning("Overlapped IPv4 block: %s", ipv4_block) ipv6_block = _get_ip_block(mconfig.ipv6_block, "IPv6") if ipv6_block is not None: logging.info('Adding IPv6 block') try: allocated_ipv6_block = ip_address_man.get_assigned_ipv6_block() if ipv6_block != allocated_ipv6_block: ip_address_man.add_ip_block(ipv6_block) except OverlappedIPBlocksError: logging.warning("Overlapped IPv6 block: %s", ipv6_block) # Add all servicers to the server mobility_service_servicer = MobilityServiceRpcServicer( ip_address_man, config.get('print_grpc_payload', False), ) mobility_service_servicer.add_to_server(service.rpc_server) service.run() # Cleanup the service service.close()
class StaticIPAllocationTests(unittest.TestCase): """ Test class for the Mobilityd Static IP Allocator """ RECYCLING_INTERVAL_SECONDS = 1 def _new_ip_allocator(self, recycling_interval): """ Creates and sets up an IPAllocator with the given recycling interval. """ config = { 'recycling_interval': recycling_interval, 'persist_to_redis': False, 'redis_port': 6379, } mconfig = MobilityD(ip_allocator_type=MobilityD.IP_POOL, static_ip_enabled=True) self._allocator = IPAddressManager( recycling_interval=recycling_interval, subscriberdb_rpc_stub=MockedSubscriberDBStub(), config=config, mconfig=mconfig) self._allocator.add_ip_block(self._block) def setUp(self): self._block = ipaddress.ip_network('192.168.0.0/28') self._new_ip_allocator(self.RECYCLING_INTERVAL_SECONDS) def tearDown(self): MockedSubscriberDBStub.clear_subs() def check_type(self, sid: str, type: IPType): ip_desc = self._allocator.sid_ips_map[sid] self.assertEqual(ip_desc.type, type) def test_get_ip_for_subscriber(self): """ test get_ip_for_sid without any assignment """ sid = 'IMSI11' ip0 = self._allocator.alloc_ip_address(sid) ip0_returned = self._allocator.get_ip_for_sid(sid) # check if retrieved ip is the same as the one allocated self.assertEqual(ip0, ip0_returned) self.check_type(sid, IPType.IP_POOL) def test_get_ip_for_subscriber_with_apn(self): """ test get_ip_for_sid with static IP """ apn = 'magma' imsi = 'IMSI110' sid = imsi + '.' + apn assigned_ip = '1.2.3.4' MockedSubscriberDBStub.add_sub(sid=imsi, apn=apn, ip=assigned_ip) ip0 = self._allocator.alloc_ip_address(sid) ip0_returned = self._allocator.get_ip_for_sid(sid) # check if retrieved ip is the same as the one allocated self.assertEqual(ip0, ip0_returned) self.assertEqual(ip0, ipaddress.ip_address(assigned_ip)) self.check_type(sid, IPType.STATIC) def test_get_ip_for_subscriber_with_different_apn(self): """ test get_ip_for_sid with different APN assigned ip""" apn = 'magma' imsi = 'IMSI110' sid = imsi + '.' + apn assigned_ip = '1.2.3.4' MockedSubscriberDBStub.add_sub(sid=imsi, apn="xyz", ip=assigned_ip) ip0 = self._allocator.alloc_ip_address(sid) ip0_returned = self._allocator.get_ip_for_sid(sid) # check if retrieved ip is the same as the one allocated self.assertEqual(ip0, ip0_returned) self.assertNotEqual(ip0, ipaddress.ip_address(assigned_ip)) self.check_type(sid, IPType.IP_POOL) def test_get_ip_for_subscriber_with_wildcard_apn(self): """ test wildcard apn""" apn = 'magma' imsi = 'IMSI110' sid = imsi + '.' + apn assigned_ip = '1.2.3.4' MockedSubscriberDBStub.add_sub(sid=imsi, apn="*", ip=assigned_ip) ip0 = self._allocator.alloc_ip_address(sid) ip0_returned = self._allocator.get_ip_for_sid(sid) # check if retrieved ip is the same as the one allocated self.assertEqual(ip0, ip0_returned) self.assertEqual(ip0, ipaddress.ip_address(assigned_ip)) self.check_type(sid, IPType.STATIC) def test_get_ip_for_subscriber_with_wildcard_and_exact_apn(self): """ test IP assignement from multiple APNs""" apn = 'magma' imsi = 'IMSI110' sid = imsi + '.' + apn assigned_ip = '1.2.3.4' assigned_ip_wild = '22.22.22.22' MockedSubscriberDBStub.add_sub(sid=imsi, apn="*", ip=assigned_ip_wild) MockedSubscriberDBStub.add_sub_ip(sid=imsi, apn=apn, ip=assigned_ip) ip0 = self._allocator.alloc_ip_address(sid) ip0_returned = self._allocator.get_ip_for_sid(sid) # check if retrieved ip is the same as the one allocated self.assertEqual(ip0, ip0_returned) self.assertEqual(ip0, ipaddress.ip_address(assigned_ip)) self.check_type(sid, IPType.STATIC) def test_get_ip_for_subscriber_with_invalid_ip(self): """ test invalid data from DB """ apn = 'magma' imsi = 'IMSI110' sid = imsi + '.' + apn assigned_ip = '1.2.3.hh' MockedSubscriberDBStub.add_sub(sid=imsi, apn=apn, ip=assigned_ip) ip0 = self._allocator.alloc_ip_address(sid) ip0_returned = self._allocator.get_ip_for_sid(sid) # check if retrieved ip is the same as the one allocated self.assertEqual(ip0, ip0_returned) self.assertNotEqual(str(ip0), assigned_ip) self.check_type(sid, IPType.IP_POOL) def test_get_ip_for_subscriber_with_multi_apn_but_no_match(self): """ test IP assignment from multiple APNs""" apn = 'magma' imsi = 'IMSI110' sid = imsi + '.' + apn assigned_ip = '1.2.3.4' assigned_ip_wild = '22.22.22.22' MockedSubscriberDBStub.add_sub(sid=imsi, apn="abc", ip=assigned_ip_wild) MockedSubscriberDBStub.add_sub_ip(sid=imsi, apn="xyz", ip=assigned_ip) ip0 = self._allocator.alloc_ip_address(sid) ip0_returned = self._allocator.get_ip_for_sid(sid) # check if retrieved ip is the same as the one allocated self.assertEqual(ip0, ip0_returned) self.assertNotEqual(ip0, ipaddress.ip_address(assigned_ip)) self.check_type(sid, IPType.IP_POOL) def test_get_ip_for_subscriber_with_incomplete_sub(self): """ test IP assignment from subscriber without non_3gpp config""" apn = 'magma' imsi = 'IMSI110' sid = imsi + '.' + apn MockedSubscriberDBStub.add_incomplete_sub(sid=imsi) ip0 = self._allocator.alloc_ip_address(sid) ip0_returned = self._allocator.get_ip_for_sid(sid) # check if retrieved ip is the same as the one allocated self.assertEqual(ip0, ip0_returned) self.check_type(sid, IPType.IP_POOL) def test_get_ip_for_subscriber_with_wildcard_no_apn(self): """ test wildcard apn""" imsi = 'IMSI110' sid = imsi assigned_ip = '1.2.3.4' MockedSubscriberDBStub.add_sub(sid=imsi, apn="*", ip=assigned_ip) ip0 = self._allocator.alloc_ip_address(sid) ip0_returned = self._allocator.get_ip_for_sid(sid) # check if retrieved ip is the same as the one allocated self.assertEqual(ip0, ip0_returned) self.assertEqual(ip0, ipaddress.ip_address(assigned_ip)) self.check_type(sid, IPType.STATIC) def test_get_ip_for_subscriber_with_apn_dot(self): """ test get_ip_for_sid with static IP """ apn = 'magma.ipv4' imsi = 'IMSI110' sid = imsi + '.' + apn assigned_ip = '1.2.3.4' MockedSubscriberDBStub.add_sub(sid=imsi, apn=apn, ip=assigned_ip) ip0 = self._allocator.alloc_ip_address(sid) ip0_returned = self._allocator.get_ip_for_sid(sid) # check if retrieved ip is the same as the one allocated self.assertEqual(ip0, ip0_returned) self.assertEqual(ip0, ipaddress.ip_address(assigned_ip)) self.check_type(sid, IPType.STATIC)
class StaticIPAllocationTests(unittest.TestCase): """ Test class for the Mobilityd Static IP Allocator """ RECYCLING_INTERVAL_SECONDS = 1 def _new_ip_allocator(self, recycling_interval): """ Creates and sets up an IPAllocator with the given recycling interval. """ config = { 'recycling_interval': recycling_interval, 'persist_to_redis': False, 'redis_port': 6379, } mconfig = MobilityD(ip_allocator_type=MobilityD.IP_POOL, static_ip_enabled=True) self._allocator = IPAddressManager( recycling_interval=recycling_interval, subscriberdb_rpc_stub=MockedSubscriberDBStub(), config=config, mconfig=mconfig) self._allocator.add_ip_block(self._block) def setUp(self): self._block = ipaddress.ip_network('192.168.0.0/28') self._new_ip_allocator(self.RECYCLING_INTERVAL_SECONDS) def tearDown(self): MockedSubscriberDBStub.clear_subs() def check_type(self, sid: str, type: IPType): ip_desc = self._allocator.sid_ips_map[sid] self.assertEqual(ip_desc.type, type) def check_gw_info(self, vlan: Optional[int], gw_ip: str, gw_mac: Optional[str]): gw_info_ip = self._allocator._dhcp_gw_info.get_gw_ip(vlan) self.assertEqual(gw_info_ip, gw_ip) gw_info_mac = self._allocator._dhcp_gw_info.get_gw_mac(vlan) self.assertEqual(gw_info_mac, gw_mac) def test_get_ip_for_subscriber(self): """ test get_ip_for_sid without any assignment """ sid = 'IMSI11' ip0, _ = self._allocator.alloc_ip_address(sid) ip0_returned = self._allocator.get_ip_for_sid(sid) # check if retrieved ip is the same as the one allocated self.assertEqual(ip0, ip0_returned) self.check_type(sid, IPType.IP_POOL) def test_get_ip_for_subscriber_with_apn(self): """ test get_ip_for_sid with static IP """ apn = 'magma' imsi = 'IMSI110' sid = imsi + '.' + apn assigned_ip = '1.2.3.4' MockedSubscriberDBStub.add_sub(sid=imsi, apn=apn, ip=assigned_ip) ip0, _ = self._allocator.alloc_ip_address(sid) ip0_returned = self._allocator.get_ip_for_sid(sid) # check if retrieved ip is the same as the one allocated self.assertEqual(ip0, ip0_returned) self.assertEqual(ip0, ipaddress.ip_address(assigned_ip)) self.check_type(sid, IPType.STATIC) def test_get_ip_for_subscriber_with_different_apn(self): """ test get_ip_for_sid with different APN assigned ip""" apn = 'magma' imsi = 'IMSI110' sid = imsi + '.' + apn assigned_ip = '1.2.3.4' MockedSubscriberDBStub.add_sub(sid=imsi, apn="xyz", ip=assigned_ip) ip0, _ = self._allocator.alloc_ip_address(sid) ip0_returned = self._allocator.get_ip_for_sid(sid) # check if retrieved ip is the same as the one allocated self.assertEqual(ip0, ip0_returned) self.assertNotEqual(ip0, ipaddress.ip_address(assigned_ip)) self.check_type(sid, IPType.IP_POOL) def test_get_ip_for_subscriber_with_wildcard_apn(self): """ test wildcard apn""" apn = 'magma' imsi = 'IMSI110' sid = imsi + '.' + apn assigned_ip = '1.2.3.4' MockedSubscriberDBStub.add_sub(sid=imsi, apn="*", ip=assigned_ip) ip0, _ = self._allocator.alloc_ip_address(sid) ip0_returned = self._allocator.get_ip_for_sid(sid) # check if retrieved ip is the same as the one allocated self.assertEqual(ip0, ip0_returned) self.assertEqual(ip0, ipaddress.ip_address(assigned_ip)) self.check_type(sid, IPType.STATIC) def test_get_ip_for_subscriber_with_wildcard_and_exact_apn(self): """ test IP assignement from multiple APNs""" apn = 'magma' imsi = 'IMSI110' sid = imsi + '.' + apn assigned_ip = '1.2.3.4' assigned_ip_wild = '22.22.22.22' MockedSubscriberDBStub.add_sub(sid=imsi, apn="*", ip=assigned_ip_wild) MockedSubscriberDBStub.add_sub_ip(sid=imsi, apn=apn, ip=assigned_ip) ip0, _ = self._allocator.alloc_ip_address(sid) ip0_returned = self._allocator.get_ip_for_sid(sid) # check if retrieved ip is the same as the one allocated self.assertEqual(ip0, ip0_returned) self.assertEqual(ip0, ipaddress.ip_address(assigned_ip)) self.check_type(sid, IPType.STATIC) def test_get_ip_for_subscriber_with_invalid_ip(self): """ test invalid data from DB """ apn = 'magma' imsi = 'IMSI110' sid = imsi + '.' + apn assigned_ip = '1.2.3.hh' MockedSubscriberDBStub.add_sub(sid=imsi, apn=apn, ip=assigned_ip) ip0, _ = self._allocator.alloc_ip_address(sid) ip0_returned = self._allocator.get_ip_for_sid(sid) # check if retrieved ip is the same as the one allocated self.assertEqual(ip0, ip0_returned) self.assertNotEqual(str(ip0), assigned_ip) self.check_type(sid, IPType.IP_POOL) def test_get_ip_for_subscriber_with_multi_apn_but_no_match(self): """ test IP assignment from multiple APNs""" apn = 'magma' imsi = 'IMSI110' sid = imsi + '.' + apn assigned_ip = '1.2.3.4' assigned_ip_wild = '22.22.22.22' MockedSubscriberDBStub.add_sub(sid=imsi, apn="abc", ip=assigned_ip_wild) MockedSubscriberDBStub.add_sub_ip(sid=imsi, apn="xyz", ip=assigned_ip) ip0, _ = self._allocator.alloc_ip_address(sid) ip0_returned = self._allocator.get_ip_for_sid(sid) # check if retrieved ip is the same as the one allocated self.assertEqual(ip0, ip0_returned) self.assertNotEqual(ip0, ipaddress.ip_address(assigned_ip)) self.check_type(sid, IPType.IP_POOL) def test_get_ip_for_subscriber_with_incomplete_sub(self): """ test IP assignment from subscriber without non_3gpp config""" apn = 'magma' imsi = 'IMSI110' sid = imsi + '.' + apn MockedSubscriberDBStub.add_incomplete_sub(sid=imsi) ip0, _ = self._allocator.alloc_ip_address(sid) ip0_returned = self._allocator.get_ip_for_sid(sid) # check if retrieved ip is the same as the one allocated self.assertEqual(ip0, ip0_returned) self.check_type(sid, IPType.IP_POOL) def test_get_ip_for_subscriber_with_wildcard_no_apn(self): """ test wildcard apn""" imsi = 'IMSI110' sid = imsi assigned_ip = '1.2.3.4' MockedSubscriberDBStub.add_sub(sid=imsi, apn="*", ip=assigned_ip) ip0, _ = self._allocator.alloc_ip_address(sid) ip0_returned = self._allocator.get_ip_for_sid(sid) # check if retrieved ip is the same as the one allocated self.assertEqual(ip0, ip0_returned) self.assertEqual(ip0, ipaddress.ip_address(assigned_ip)) self.check_type(sid, IPType.STATIC) def test_get_ip_for_subscriber_with_apn_dot(self): """ test get_ip_for_sid with static IP """ apn = 'magma.ipv4' imsi = 'IMSI110' sid = imsi + '.' + apn assigned_ip = '1.2.3.4' MockedSubscriberDBStub.add_sub(sid=imsi, apn=apn, ip=assigned_ip) ip0, _ = self._allocator.alloc_ip_address(sid) ip0_returned = self._allocator.get_ip_for_sid(sid) # check if retrieved ip is the same as the one allocated self.assertEqual(ip0, ip0_returned) self.assertEqual(ip0, ipaddress.ip_address(assigned_ip)) self.check_type(sid, IPType.STATIC) def test_get_ip_for_subscriber_with_wildcard_and_no_exact_apn(self): """ test IP assignement from multiple APNs""" apn = 'magma' imsi = 'IMSI110' sid = imsi + '.' + apn assigned_ip = '1.2.3.4' assigned_ip_wild = '22.22.22.22' MockedSubscriberDBStub.add_sub(sid=imsi, apn="*", ip=assigned_ip_wild) MockedSubscriberDBStub.add_sub_ip(sid=imsi, apn="xyz", ip=assigned_ip) ip0, _ = self._allocator.alloc_ip_address(sid) ip0_returned = self._allocator.get_ip_for_sid(sid) # check if retrieved ip is the same as the one allocated self.assertEqual(ip0, ip0_returned) self.assertEqual(ip0, ipaddress.ip_address(assigned_ip_wild)) self.check_type(sid, IPType.STATIC) def test_get_ip_for_subscriber_with_wildcard_and_exact_apn_no_ip(self): """ test IP assignement from multiple APNs""" apn = 'magma' imsi = 'IMSI110' sid = imsi + '.' + apn assigned_ip_wild = '22.22.22.22' MockedSubscriberDBStub.add_sub(sid=imsi, apn="*", ip=assigned_ip_wild) MockedSubscriberDBStub.add_sub_ip(sid=imsi, apn=apn, ip=None) ip0, _ = self._allocator.alloc_ip_address(sid) ip0_returned = self._allocator.get_ip_for_sid(sid) # check if retrieved ip is the same as the one allocated self.assertEqual(ip0, ip0_returned) self.assertEqual(ip0, ipaddress.ip_address(assigned_ip_wild)) self.check_type(sid, IPType.STATIC) def test_get_ip_for_subscriber_with_apn_with_gw(self): """ test get_ip_for_sid with static IP """ apn = 'magma' imsi = 'IMSI110' sid = imsi + '.' + apn assigned_ip = '1.2.3.4' gw_ip = "1.2.3.1" gw_mac = "11:22:33:11:77:28" MockedSubscriberDBStub.add_sub(sid=imsi, apn=apn, ip=assigned_ip, gw_ip=gw_ip, gw_mac=gw_mac) ip0, _ = self._allocator.alloc_ip_address(sid) ip0_returned = self._allocator.get_ip_for_sid(sid) # check if retrieved ip is the same as the one allocated self.assertEqual(ip0, ip0_returned) self.assertEqual(ip0, ipaddress.ip_address(assigned_ip)) self.check_type(sid, IPType.STATIC) self.check_gw_info(None, gw_ip, gw_mac) def test_get_ip_for_subscriber_with_only_wildcard_apn_gw(self): """ test wildcard apn""" apn = 'magma' imsi = 'IMSI110' sid = imsi + '.' + apn assigned_ip = '1.2.3.4' gw_ip = "1.2.3.100" gw_mac = "11:22:33:11:77:81" MockedSubscriberDBStub.add_sub(sid=imsi, apn="*", ip=assigned_ip, gw_ip=gw_ip, gw_mac=gw_mac) ip0, _ = self._allocator.alloc_ip_address(sid) ip0_returned = self._allocator.get_ip_for_sid(sid) # check if retrieved ip is the same as the one allocated self.assertEqual(ip0, ip0_returned) self.assertEqual(ip0, ipaddress.ip_address(assigned_ip)) self.check_type(sid, IPType.STATIC) def test_get_ip_for_subscriber_with_apn_with_gw_vlan(self): """ test get_ip_for_sid with static IP """ apn = 'magma' imsi = 'IMSI110' sid = imsi + '.' + apn assigned_ip = '1.2.3.4' gw_ip = "1.2.3.1" gw_mac = "11:22:33:11:77:44" vlan = "200" MockedSubscriberDBStub.add_sub(sid=imsi, apn=apn, ip=assigned_ip, gw_ip=gw_ip, gw_mac=gw_mac, vlan=vlan) ip0, _ = self._allocator.alloc_ip_address(sid) ip0_returned = self._allocator.get_ip_for_sid(sid) # check if retrieved ip is the same as the one allocated self.assertEqual(ip0, ip0_returned) self.assertEqual(ip0, ipaddress.ip_address(assigned_ip)) self.check_type(sid, IPType.STATIC) self.check_gw_info(vlan, gw_ip, gw_mac) def test_get_ip_for_subscriber_with_apn_with_gw_invalid_ip(self): """ test get_ip_for_sid with static IP """ apn = 'magma' imsi = 'IMSI110' sid = imsi + '.' + apn assigned_ip = '1.2.3.4' gw_ip = "1.2.3.1333" gw_mac = "11:22:33:11:77:76" vlan = "200" MockedSubscriberDBStub.add_sub(sid=imsi, apn=apn, ip=assigned_ip, gw_ip=gw_ip, gw_mac=gw_mac, vlan=vlan) ip0, _ = self._allocator.alloc_ip_address(sid) ip0_returned = self._allocator.get_ip_for_sid(sid) # check if retrieved ip is the same as the one allocated self.assertEqual(ip0, ip0_returned) self.assertEqual(ip0, ipaddress.ip_address(assigned_ip)) self.check_type(sid, IPType.STATIC) self.check_gw_info(vlan, None, None) def test_get_ip_for_subscriber_with_apn_with_gw_nul_ip(self): """ test get_ip_for_sid with static IP """ apn = 'magma' imsi = 'IMSI110' sid = imsi + '.' + apn assigned_ip = '1.2.3.4' gw_ip = "" gw_mac = "11:22:33:11:77:45" vlan = "200" MockedSubscriberDBStub.add_sub(sid=imsi, apn=apn, ip=assigned_ip, gw_ip=gw_ip, gw_mac=gw_mac, vlan=vlan) ip0, _ = self._allocator.alloc_ip_address(sid) ip0_returned = self._allocator.get_ip_for_sid(sid) # check if retrieved ip is the same as the one allocated self.assertEqual(ip0, ip0_returned) self.assertEqual(ip0, ipaddress.ip_address(assigned_ip)) self.check_type(sid, IPType.STATIC) self.check_gw_info(vlan, None, None) def test_get_ip_for_subscriber_with_apn_with_gw_nul_mac(self): """ test get_ip_for_sid with static IP """ apn = 'magma' imsi = 'IMSI110' sid = imsi + '.' + apn assigned_ip = '1.2.3.24' gw_ip = "1.2.3.55" gw_mac = None vlan = "200" MockedSubscriberDBStub.add_sub(sid=imsi, apn=apn, ip=assigned_ip, gw_ip=gw_ip, gw_mac=gw_mac, vlan=vlan) ip0, _ = self._allocator.alloc_ip_address(sid) ip0_returned = self._allocator.get_ip_for_sid(sid) # check if retrieved ip is the same as the one allocated self.assertEqual(ip0, ip0_returned) self.assertEqual(ip0, ipaddress.ip_address(assigned_ip)) self.check_type(sid, IPType.STATIC) self.check_gw_info(vlan, gw_ip, "") def test_get_ip_for_subscriber_with_wildcard_apn_gw(self): """ test wildcard apn""" apn = 'magma' imsi = 'IMSI110' sid = imsi + '.' + apn assigned_ip = '1.2.3.4' gw_ip = "1.2.3.100" gw_mac = "11:22:33:11:77:81" vlan = "300" MockedSubscriberDBStub.add_sub(sid=imsi, apn=apn, ip=assigned_ip, gw_ip=gw_ip, gw_mac=gw_mac, vlan=vlan) wildcard_assigned_ip = "20.20.20.20" wildcard_gw_ip = "1.2.7.7" wildcard_gw_mac = "11:22:33:88:77:99" wildcard_vlan = "400" MockedSubscriberDBStub.add_sub_ip(sid=imsi, apn="*", ip=wildcard_assigned_ip, gw_ip=wildcard_gw_ip, gw_mac=wildcard_gw_mac, vlan=wildcard_vlan) ip0, _ = self._allocator.alloc_ip_address(sid) ip0_returned = self._allocator.get_ip_for_sid(sid) # check if retrieved ip is the same as the one allocated self.assertEqual(ip0, ip0_returned) self.assertEqual(ip0, ipaddress.ip_address(assigned_ip)) self.check_type(sid, IPType.STATIC) self.check_gw_info(vlan, gw_ip, gw_mac) self.check_gw_info(wildcard_vlan, None, None) def test_get_ip_for_subscriber_with_apn_with_gw_invalid_vlan(self): """ test get_ip_for_sid with static IP """ apn = 'magma' imsi = 'IMSI110' sid = imsi + '.' + apn assigned_ip = '1.2.3.4' gw_ip = "1.2.3.1" gw_mac = "11:22:33:11:77:44" vlan = "20000" MockedSubscriberDBStub.add_sub(sid=imsi, apn=apn, ip=assigned_ip, gw_ip=gw_ip, gw_mac=gw_mac, vlan=vlan) with self.assertRaises(InvalidVlanId): ip0, _ = self._allocator.alloc_ip_address(sid)