예제 #1
0
 def _new_ip_allocator(self, recycling_interval):
     """
     Creates and sets up an IPAllocator with the given recycling interval.
     """
     store = MobilityStore(fakeredis.FakeStrictRedis())
     ip_allocator = IpAllocatorPool(store)
     ip_allocator_static = IPAllocatorStaticWrapper(
         store,
         MockedSubscriberDBStub(),
         ip_allocator,
     )
     ipv4_allocator = IPAllocatorMultiAPNWrapper(
         store,
         subscriberdb_rpc_stub=MockedSubscriberDBStub(),
         ip_allocator=ip_allocator_static,
     )
     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)
예제 #2
0
    def setUp(self):
        self._br = "t_up_br0"

        setup_dhcp_server = SCRIPT_PATH + "scripts/setup-test-dhcp-srv.sh"
        subprocess.check_call([setup_dhcp_server, "t0"])

        setup_uplink_br = [
            SCRIPT_PATH + "scripts/setup-uplink-br.sh",
            self._br,
            "t0uplink_p0",
            "t0_dhcp1",
        ]
        subprocess.check_call(setup_uplink_br)

        store = MobilityStore(fakeredis.FakeStrictRedis())
        ipv4_allocator = IPAllocatorDHCP(
            store,
            iface='t0uplink_p0',
            retry_limit=50,
        )
        ipv6_allocator = IPv6AllocatorPool(
            store,
            session_prefix_alloc_mode='RANDOM',
        )
        self._dhcp_allocator = IPAddressManager(
            ipv4_allocator,
            ipv6_allocator,
            store,
            recycling_interval=2,
        )
예제 #3
0
 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)
     store.dhcp_gw_info.read_default_gw()
     ip_allocator = IpAllocatorPool(store)
     ipv6_allocator = IPv6AllocatorPool(store,
                                        session_prefix_alloc_mode='RANDOM')
     self._allocator = IPAddressManager(ip_allocator, ipv6_allocator, store,
                                        recycling_interval)
     self._allocator.add_ip_block(self._block)
예제 #4
0
 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.
     persist_to_redis = False
     self._allocator = IPAddressManager(
         recycling_interval=recycling_interval,
         persist_to_redis=persist_to_redis,
         redis_port=6379)
     self._allocator.add_ip_block(self._block)
예제 #5
0
    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)
예제 #6
0
    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)
예제 #7
0
 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)
예제 #8
0
 def _new_ip_allocator(self, recycling_interval):
     """
     Creates and sets up an IPAllocator with the given recycling interval.
     """
     store = MobilityStore(fakeredis.FakeStrictRedis())
     store.dhcp_gw_info.read_default_gw()
     ip_allocator = IpAllocatorPool(store)
     ipv6_allocator = IPv6AllocatorPool(
         store,
         session_prefix_alloc_mode='RANDOM',
     )
     self._allocator = IPAddressManager(
         ip_allocator,
         ipv6_allocator,
         store,
         recycling_interval,
     )
     self._allocator.add_ip_block(self._block)
예제 #9
0
    def setUp(self):
        # Bind the rpc server to a free port
        thread_pool = futures.ThreadPoolExecutor(max_workers=10)
        self._rpc_server = grpc.server(thread_pool)
        port = self._rpc_server.add_insecure_port('0.0.0.0:0')

        store = MobilityStore(get_default_client(), False, 3980)
        store.dhcp_gw_info.read_default_gw()
        ip_allocator = IpAllocatorPool(store)
        ipv6_allocator = IPv6AllocatorPool(
            store,
            session_prefix_alloc_mode='RANDOM',
        )
        self._allocator = IPAddressManager(
            ip_allocator,
            ipv6_allocator,
            store,
        )

        # Add the servicer
        self._servicer = MobilityServiceRpcServicer(self._allocator, False)
        self._servicer.add_to_server(self._rpc_server)
        self._rpc_server.start()

        # Create a rpc stub
        channel = grpc.insecure_channel('0.0.0.0:{}'.format(port))
        self._stub = MobilityServiceStub(channel)

        # variables shared across tests
        self._netaddr = '192.168.0.0'
        self._prefix_len = 28
        ip_bytes = bytes(map(int, self._netaddr.split('.')))
        self._block_msg = IPBlock(
            version=IPBlock.IPV4,
            net_address=ip_bytes,
            prefix_len=self._prefix_len,
        )
        self._ipv6_block = ipaddress.ip_network('fdee:5:6c::/48')
        self._ipv6_netaddr = self._ipv6_block.network_address.packed
        self._ipv6_block_msg = IPBlock(
            version=IPBlock.IPV6,
            net_address=self._ipv6_netaddr,
            prefix_len=self._ipv6_block.prefixlen,
        )
        self._block = ipaddress.ip_network(
            "%s/%s" % (self._netaddr, self._prefix_len),
        )
        self._sid0 = SIDUtils.to_pb('IMSI0')
        self._sid1 = SIDUtils.to_pb('IMSI1')
        self._sid2 = SIDUtils.to_pb('IMSI2')
        self._apn0 = 'Internet'
        self._apn1 = 'IMS'
예제 #10
0
    def setUp(self):
        self._br = "t_up_br0"

        setup_dhcp_server = SCRIPT_PATH + "scripts/setup-test-dhcp-srv.sh"
        subprocess.check_call([setup_dhcp_server, "t0"])

        setup_uplink_br = [
            SCRIPT_PATH + "scripts/setup-uplink-br.sh", self._br,
            "t0uplink_p0", "8A:00:00:00:00:01"
        ]
        subprocess.check_call(setup_uplink_br)

        config = {
            'dhcp_iface': 't_dhcp0',
            'retry_limit': 50,
            'allocator_type': 'dhcp',
            'persist_to_redis': False,
        }
        self._dhcp_allocator = IPAddressManager(recycling_interval=2,
                                                allocator_type=MobilityD.DHCP,
                                                config=config)
        print("dhcp allocator created")
예제 #11
0
    def setUp(self):
        self._br = "t_up_br0"

        setup_dhcp_server = SCRIPT_PATH + "scripts/setup-test-dhcp-srv.sh"
        subprocess.check_call([setup_dhcp_server, "t0"])

        setup_uplink_br = [
            SCRIPT_PATH + "scripts/setup-uplink-br.sh", self._br,
            "t0uplink_p0", "t0_dhcp1"
        ]
        subprocess.check_call(setup_uplink_br)

        config = {
            'dhcp_iface': 't0uplink_p0',
            'retry_limit': 50,
            'persist_to_redis': False,
        }
        mconfig = MobilityD(ip_allocator_type=MobilityD.DHCP,
                            static_ip_enabled=False)

        self._dhcp_allocator = IPAddressManager(recycling_interval=2,
                                                config=config,
                                                mconfig=mconfig)
예제 #12
0
파일: main.py 프로젝트: shilawat/magma
def main():
    """ main() for MobilityD """
    service = MagmaService('mobilityd', mconfigs_pb2.MobilityD())

    # 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', 300)

    # 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', 6380))

    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_allocation_type = config['ipv6_ip_allocator_type']
    ipv6_allocator = IPv6AllocatorPool(
        store=store, session_prefix_alloc_mode=ipv6_allocation_type)

    # Load IPAddressManager
    ip_address_man = IPAddressManager(ipv4_allocator, ipv6_allocator, store)

    # Add all servicers to the server
    mobility_service_servicer = MobilityServiceRpcServicer(
        ip_address_man, mconfig.ip_block, config.get('ipv6_prefix_block'))
    mobility_service_servicer.add_to_server(service.rpc_server)

    # Run the service loop
    service.run()

    # Cleanup the service
    service.close()
예제 #13
0
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)
예제 #14
0
class DhcpIPAllocEndToEndTest(unittest.TestCase):
    def setUp(self):
        self._br = "t_up_br0"

        setup_dhcp_server = SCRIPT_PATH + "scripts/setup-test-dhcp-srv.sh"
        subprocess.check_call([setup_dhcp_server, "t0"])

        setup_uplink_br = [
            SCRIPT_PATH + "scripts/setup-uplink-br.sh",
            self._br,
            "t0uplink_p0",
            "t0_dhcp1",
        ]
        subprocess.check_call(setup_uplink_br)

        store = MobilityStore(fakeredis.FakeStrictRedis())
        ipv4_allocator = IPAllocatorDHCP(
            store,
            iface='t0uplink_p0',
            retry_limit=50,
        )
        ipv6_allocator = IPv6AllocatorPool(
            store,
            session_prefix_alloc_mode='RANDOM',
        )
        self._dhcp_allocator = IPAddressManager(
            ipv4_allocator,
            ipv6_allocator,
            store,
            recycling_interval=2,
        )

    def tearDown(self):
        self._dhcp_allocator.ip_allocator.stop_dhcp_sniffer()
        BridgeTools.destroy_bridge(self._br)

    @unittest.skipIf(os.getuid(), reason="needs root user")
    def test_ip_alloc(self):
        sid1 = "IMSI02917"
        ip1, _ = self._dhcp_allocator.alloc_ip_address(sid1)
        threading.Event().wait(2)
        dhcp_gw_info = self._dhcp_allocator._store.dhcp_gw_info
        dhcp_store = self._dhcp_allocator._store.dhcp_store

        self.assertEqual(str(dhcp_gw_info.get_gw_ip()), "192.168.128.211")
        self._dhcp_allocator.release_ip_address(sid1, ip1)

        # wait for DHCP release
        threading.Event().wait(7)
        mac1 = create_mac_from_sid(sid1)
        dhcp_state1 = dhcp_store.get(mac1.as_redis_key(None))

        self.assertEqual(dhcp_state1, None)

        ip1_1, _ = self._dhcp_allocator.alloc_ip_address(sid1)
        threading.Event().wait(2)
        self.assertEqual(str(ip1), str(ip1_1))

        self._dhcp_allocator.release_ip_address(sid1, ip1_1)
        threading.Event().wait(5)
        self.assertEqual(self._dhcp_allocator.list_added_ip_blocks(), [])

        ip1, _ = self._dhcp_allocator.alloc_ip_address("IMSI02918")
        self.assertEqual(str(ip1), "192.168.128.146")
        self.assertEqual(
            self._dhcp_allocator.list_added_ip_blocks(),
            [ip_network('192.168.128.0/24')],
        )

        ip2, _ = self._dhcp_allocator.alloc_ip_address("IMSI029192")
        self.assertNotEqual(ip1, ip2)

        ip3, _ = self._dhcp_allocator.alloc_ip_address("IMSI0432")
        self.assertNotEqual(ip1, ip3)
        self.assertNotEqual(ip2, ip3)
        # release unallocated IP of SID
        ip_unallocated = IPDesc(
            ip=ip3,
            state=IPState.ALLOCATED,
            sid="IMSI033",
            ip_block=ip_network("1.1.1.0/24"),
            ip_type=IPType.DHCP,
        )
        self._dhcp_allocator.ip_allocator.release_ip(ip_unallocated)
        self.assertEqual(
            self._dhcp_allocator.list_added_ip_blocks(),
            [ip_network('192.168.128.0/24')],
        )

        sid4 = "IMSI54321"
        ip4, _ = self._dhcp_allocator.alloc_ip_address(sid4)
        threading.Event().wait(1)
        self._dhcp_allocator.release_ip_address(sid4, ip4)
        self.assertEqual(
            self._dhcp_allocator.list_added_ip_blocks(),
            [ip_network('192.168.128.0/24')],
        )

        # wait for DHCP release
        threading.Event().wait(7)
        mac4 = create_mac_from_sid(sid4)
        dhcp_state = dhcp_store.get(mac4.as_redis_key(None))

        self.assertEqual(dhcp_state, None)
        ip4_2, _ = self._dhcp_allocator.alloc_ip_address(sid4)
        self.assertEqual(ip4, ip4_2)

        try:
            self._dhcp_allocator.release_ip_address(sid1, ip1)
            self.assertEqual("should not", "reach here")
        except MappingNotFoundError:
            pass
예제 #15
0
def main():
    """ main() for MobilityD """
    service = MagmaService('mobilityd', mconfigs_pb2.MobilityD())

    # 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', 300)

    # 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', 6380))

    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_prefix_allocation_type = mconfig.ipv6_prefix_allocation_type or \
                                  DEFAULT_IPV6_PREFIX_ALLOC_MODE
    ipv6_allocator = IPv6AllocatorPool(
        store=store, session_prefix_alloc_mode=ipv6_prefix_allocation_type)

    # Load IPAddressManager
    ip_address_man = IPAddressManager(ipv4_allocator, ipv6_allocator, store)

    # 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)

    # Load IPv4 and IPv6 blocks from the configurable mconfig file
    # No dynamic reloading support for now, assume restart after updates
    logging.info('Adding IPv4 block')
    ipv4_block = _get_ip_block(mconfig.ip_block)
    if ipv4_block is not None:
        try:
            mobility_service_servicer.add_ip_block(ipv4_block)
        except OverlappedIPBlocksError:
            logging.warning("Overlapped IPv4 block: %s", ipv4_block)

    logging.info('Adding IPv6 block')
    ipv6_block = _get_ip_block(mconfig.ipv6_block)
    if ipv6_block is not None:
        try:
            mobility_service_servicer.add_ip_block(ipv6_block)
        except OverlappedIPBlocksError:
            logging.warning("Overlapped IPv6 block: %s", ipv6_block)

    # Run the service loop
    service.run()

    # Cleanup the service
    service.close()
예제 #16
0
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))
예제 #17
0
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)
예제 #18
0
class DhcpIPAllocEndToEndTest(unittest.TestCase):
    @mock.patch("redis.Redis", MockRedis)
    def setUp(self):
        self._br = "t_up_br0"

        subprocess.check_call(["redis-cli", "flushall"])

        setup_dhcp_server = SCRIPT_PATH + "scripts/setup-test-dhcp-srv.sh"
        subprocess.check_call([setup_dhcp_server, "t0"])

        setup_uplink_br = [
            SCRIPT_PATH + "scripts/setup-uplink-br.sh", self._br,
            "t0uplink_p0", "8A:00:00:00:00:01"
        ]
        subprocess.check_call(setup_uplink_br)

        config = {
            'dhcp_iface': 't_dhcp0',
            'retry_limit': 50,
            'allocator_type': 'dhcp',
            'persist_to_redis': False,
        }
        self._dhcp_allocator = IPAddressManager(recycling_interval=2,
                                                config=config)
        print("dhcp allocator created")

    def tearDown(self):
        self._dhcp_allocator.ip_allocator.stop_dhcp_sniffer()
        BridgeTools.destroy_bridge(self._br)

    @unittest.skipIf(os.getuid(), reason="needs root user")
    def test_ip_alloc(self):
        sid1 = "IMSI02917"
        ip1 = self._dhcp_allocator.alloc_ip_address(sid1)

        threading.Event().wait(2)
        self._dhcp_allocator.release_ip_address(sid1, ip1)
        threading.Event().wait(2)
        ip1_1 = self._dhcp_allocator.alloc_ip_address(sid1)
        threading.Event().wait(2)
        self.assertEqual(str(ip1), str(ip1_1))

        self._dhcp_allocator.release_ip_address(sid1, ip1_1)
        threading.Event().wait(5)
        self.assertEqual(self._dhcp_allocator.list_added_ip_blocks(), [])

        ip1 = self._dhcp_allocator.alloc_ip_address("IMSI02918")
        self.assertEqual(str(ip1), "192.168.128.146")
        self.assertEqual(self._dhcp_allocator.list_added_ip_blocks(),
                         [ip_network('192.168.128.0/24')])

        ip2 = self._dhcp_allocator.alloc_ip_address("IMSI029192")
        self.assertNotEqual(ip1, ip2)

        ip3 = self._dhcp_allocator.alloc_ip_address("IMSI0432")
        self.assertNotEqual(ip1, ip3)
        self.assertNotEqual(ip2, ip3)
        # release unallocated IP of SID
        self._dhcp_allocator.ip_allocator.release_ip("IMSI033", ip3,
                                                     ip_network("1.1.1.0/24"))
        self.assertEqual(self._dhcp_allocator.list_added_ip_blocks(),
                         [ip_network('192.168.128.0/24')])

        sid4 = "IMSI54321"
        ip4 = self._dhcp_allocator.alloc_ip_address(sid4)
        threading.Event().wait(1)
        self._dhcp_allocator.release_ip_address(sid4, ip4)
        self.assertEqual(self._dhcp_allocator.list_added_ip_blocks(),
                         [ip_network('192.168.128.0/24')])

        # wait for DHCP release
        threading.Event().wait(20)
        ip4_2 = self._dhcp_allocator.alloc_ip_address(sid4)
        self.assertEqual(ip4, ip4_2)

        try:
            self._dhcp_allocator.release_ip_address(sid1, ip1)
            self.assertEqual("should not", "reach here")
        except MappingNotFoundError:
            pass
예제 #19
0
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()
예제 #20
0
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)
예제 #21
0
class DhcpIPAllocEndToEndTest(unittest.TestCase):
    def setUp(self):
        self._br = "t_up_br0"

        setup_dhcp_server = SCRIPT_PATH + "scripts/setup-test-dhcp-srv.sh"
        subprocess.check_call([setup_dhcp_server, "t0"])

        setup_uplink_br = [
            SCRIPT_PATH + "scripts/setup-uplink-br.sh", self._br,
            "t0uplink_p0", "t0_dhcp1"
        ]
        subprocess.check_call(setup_uplink_br)

        config = {
            'dhcp_iface': 't0uplink_p0',
            'retry_limit': 50,
            'persist_to_redis': False,
        }
        mconfig = MobilityD(ip_allocator_type=MobilityD.DHCP,
                            static_ip_enabled=False)

        self._dhcp_allocator = IPAddressManager(recycling_interval=2,
                                                config=config,
                                                mconfig=mconfig)

    def tearDown(self):
        self._dhcp_allocator.ip_allocator.stop_dhcp_sniffer()
        BridgeTools.destroy_bridge(self._br)

    @unittest.skipIf(os.getuid(), reason="needs root user")
    def test_ip_alloc(self):
        sid1 = "IMSI02917"
        ip1 = self._dhcp_allocator.alloc_ip_address(sid1)
        threading.Event().wait(2)
        dhcp_gw_info = self._dhcp_allocator._dhcp_gw_info
        dhcp_store = self._dhcp_allocator._dhcp_store

        self.assertEqual(str(dhcp_gw_info.getIP()), "192.168.128.211")
        self._dhcp_allocator.release_ip_address(sid1, ip1)

        # wait for DHCP release
        threading.Event().wait(7)
        mac1 = create_mac_from_sid(sid1)
        dhcp_state1 = dhcp_store.get(mac1.as_redis_key())

        self.assertEqual(dhcp_state1.state_requested, DHCPState.RELEASE)

        ip1_1 = self._dhcp_allocator.alloc_ip_address(sid1)
        threading.Event().wait(2)
        self.assertEqual(str(ip1), str(ip1_1))

        self._dhcp_allocator.release_ip_address(sid1, ip1_1)
        threading.Event().wait(5)
        self.assertEqual(self._dhcp_allocator.list_added_ip_blocks(), [])

        ip1 = self._dhcp_allocator.alloc_ip_address("IMSI02918")
        self.assertEqual(str(ip1), "192.168.128.146")
        self.assertEqual(self._dhcp_allocator.list_added_ip_blocks(),
                         [ip_network('192.168.128.0/24')])

        ip2 = self._dhcp_allocator.alloc_ip_address("IMSI029192")
        self.assertNotEqual(ip1, ip2)

        ip3 = self._dhcp_allocator.alloc_ip_address("IMSI0432")
        self.assertNotEqual(ip1, ip3)
        self.assertNotEqual(ip2, ip3)
        # release unallocated IP of SID
        ip_unallocated = IPDesc(ip=ip3,
                                state=IPState.ALLOCATED,
                                sid="IMSI033",
                                ip_block=ip_network("1.1.1.0/24"),
                                ip_type=IPType.DHCP)
        self._dhcp_allocator.ip_allocator.release_ip(ip_unallocated)
        self.assertEqual(self._dhcp_allocator.list_added_ip_blocks(),
                         [ip_network('192.168.128.0/24')])

        sid4 = "IMSI54321"
        ip4 = self._dhcp_allocator.alloc_ip_address(sid4)
        threading.Event().wait(1)
        self._dhcp_allocator.release_ip_address(sid4, ip4)
        self.assertEqual(self._dhcp_allocator.list_added_ip_blocks(),
                         [ip_network('192.168.128.0/24')])

        # wait for DHCP release
        threading.Event().wait(7)
        mac4 = create_mac_from_sid(sid4)
        dhcp_state = dhcp_store.get(mac4.as_redis_key())

        self.assertEqual(dhcp_state.state_requested, DHCPState.RELEASE)
        ip4_2 = self._dhcp_allocator.alloc_ip_address(sid4)
        self.assertEqual(ip4, ip4_2)

        try:
            self._dhcp_allocator.release_ip_address(sid1, ip1)
            self.assertEqual("should not", "reach here")
        except MappingNotFoundError:
            pass
예제 #22
0
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)