def test_per_sub_digests(self): """ Test if per-sub digest gets & updates work as expected """ self.assertEqual(self._store.get_current_per_sub_digests(), []) digests1 = [ SubscriberDigestWithID( sid=SIDUtils.to_pb('IMSI11111'), digest=Digest(md5_base64_digest='digest_apple'), ), SubscriberDigestWithID( sid=SIDUtils.to_pb('IMSI22222'), digest=Digest(md5_base64_digest='digest_cherry'), ), ] self._store.update_per_sub_digests(digests1) self.assertEqual(self._store.get_current_per_sub_digests(), digests1) digests2 = [ SubscriberDigestWithID( sid=SIDUtils.to_pb('IMSI11111'), digest=Digest(md5_base64_digest='digest_apple'), ), SubscriberDigestWithID( sid=SIDUtils.to_pb('IMSI33333'), digest=Digest(md5_base64_digest='digest_banana'), ), SubscriberDigestWithID( sid=SIDUtils.to_pb('IMSI44444'), digest=Digest(md5_base64_digest='digest_orange'), ), ] self._store.update_per_sub_digests(digests2) self.assertEqual(self._store.get_current_per_sub_digests(), digests2)
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') # Create a mock "mconfig" for the servicer to use mconfig = unittest.mock.Mock() mconfig.ip_block = None # Add the servicer config = {'persist_to_redis': False, 'redis_port': None} self._servicer = MobilityServiceRpcServicer(mconfig, config) 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._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'
def test_ue_mac_restart(self, _): """ Verify that default flows are properly installed with empty setup Verify that ue mac flows are properly restored """ imsi1 = 'IMSI111111111111111' imsi2 = 'IMSI222222222222222' mac1 = '5e:cc:cc:b1:aa:aa' mac2 = 'b2:6a:f3:b3:2f:4c' ap_mac_addr1 = '11:22:33:44:55:66' ap_mac_addr2 = '12:12:13:24:25:26' fake_cwf_setup(ue_mac_controller=self.ue_mac_controller) snapshot_verifier = SnapshotVerifier(self, self.BRIDGE, self.service_manager, 'default_flows', include_stats=False) with snapshot_verifier: pass setup_ue_mac_request = SetupUEMacRequest( requests=[ UEMacFlowRequest( sid=SIDUtils.to_pb(imsi1), mac_addr=mac1, msisdn='123456', ap_mac_addr=ap_mac_addr1, ap_name='magma', pdp_start_time=1, ), UEMacFlowRequest( sid=SIDUtils.to_pb(imsi2), mac_addr=mac2, msisdn='654321', ap_mac_addr=ap_mac_addr2, ap_name='amgam', pdp_start_time=9, ), ], epoch=global_epoch, ) fake_cwf_setup(ue_mac_controller=self.ue_mac_controller, setup_ue_mac_request=setup_ue_mac_request) snapshot_verifier = SnapshotVerifier(self, self.BRIDGE, self.service_manager, 'recovery_flows', include_stats=False) with snapshot_verifier: pass
def setUp(self): # Create sqlite3 database for testing self._tmpfile = tempfile.TemporaryDirectory() store = SqliteStore(self._tmpfile.name + '/') op = 16 * b'\x11' amf = b'\x80\x00' self._sub_profiles = { 'superfast': SubscriberDB.SubscriptionProfile(max_ul_bit_rate=100000, max_dl_bit_rate=50000) } self._default_sub_profile = SubscriberDB.SubscriptionProfile( max_ul_bit_rate=10000, max_dl_bit_rate=5000) self._processor = processor.Processor(store, self._default_sub_profile, self._sub_profiles, op, amf) # Add some test users (rand, sres, gsm_key) = _dummy_auth_tuple() gsm = GSMSubscription(state=GSMSubscription.ACTIVE, auth_tuples=[rand + sres + gsm_key]) lte_key = 16 * b'\x00' lte = LTESubscription(state=LTESubscription.ACTIVE, auth_key=lte_key) lte_opc = LTESubscription(state=LTESubscription.ACTIVE, auth_key=lte_key, auth_opc=Milenage.generate_opc(lte_key, op)) lte_opc_short = LTESubscription(state=LTESubscription.ACTIVE, auth_key=lte_key, auth_opc=b'\x00') state = SubscriberState(lte_auth_next_seq=1) sub1 = SubscriberData(sid=SIDUtils.to_pb('IMSI11111'), gsm=gsm, lte=lte, state=state, sub_profile='superfast') sub2 = SubscriberData( sid=SIDUtils.to_pb('IMSI22222'), # No auth keys gsm=GSMSubscription(state=GSMSubscription.ACTIVE), lte=LTESubscription(state=LTESubscription.ACTIVE)) sub3 = SubscriberData( sid=SIDUtils.to_pb('IMSI33333')) # No subscribtion sub4 = SubscriberData(sid=SIDUtils.to_pb('IMSI44444'), lte=lte_opc, state=state) sub5 = SubscriberData(sid=SIDUtils.to_pb('IMSI55555'), lte=lte_opc_short, state=state) store.add_subscriber(sub1) store.add_subscriber(sub2) store.add_subscriber(sub3) store.add_subscriber(sub4) store.add_subscriber(sub5)
async def test(): # noqa: WPS430 get_grpc_mock.return_value = self.channel # resync is True if the changeset is too big resync = (await self.subscriberdb_cloud_client._sync_subscribers()) self.assertEqual(True, resync) self.subscriberdb_cloud_client._store.update_per_sub_digests([ SubscriberDigestWithID( sid=SIDUtils.to_pb('IMSI11111'), digest=Digest(md5_base64_digest="digest_apple"), ), SubscriberDigestWithID( sid=SIDUtils.to_pb('IMSI00000'), digest=Digest(md5_base64_digest="digest_zebra"), ), ]) self.subscriberdb_cloud_client._store.add_subscriber( subscriber_data_by_id('IMSI00000'), ) self.subscriberdb_cloud_client._store.add_subscriber( subscriber_data_by_id('IMSI11111'), ) # the client subscriber db and per-subscriber digest db are updated # when resync is False expected_per_sub_digests = [ SubscriberDigestWithID( sid=SIDUtils.to_pb('IMSI11111'), digest=Digest(md5_base64_digest="digest_apple"), ), SubscriberDigestWithID( sid=SIDUtils.to_pb('IMSI22222'), digest=Digest(md5_base64_digest="digest_banana"), ), SubscriberDigestWithID( sid=SIDUtils.to_pb('IMSI33333'), digest=Digest(md5_base64_digest="digest_cherry"), ), ] resync = (await self.subscriberdb_cloud_client._sync_subscribers()) self.assertEqual(False, resync) self.assertEqual( "flat_digest_apple", self.subscriberdb_cloud_client._store.get_current_digest(), ) self.assertEqual( ['IMSI11111', 'IMSI22222', 'IMSI33333'], self.subscriberdb_cloud_client._store.list_subscribers(), ) self.assertEqual( expected_per_sub_digests, self.subscriberdb_cloud_client._store. get_current_per_sub_digests(), )
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'
def SyncSubscribers(self, request, context): """ Mock to trigger SyncSubscribers-related test cases Args: request: SyncSubscribersRequest context: request context Returns: SyncSubscribersResponse """ per_sub_digests = [ SubscriberDigestWithID( sid=SIDUtils.to_pb('IMSI11111'), digest=Digest(md5_base64_digest="digest_apple"), ), SubscriberDigestWithID( sid=SIDUtils.to_pb('IMSI22222'), digest=Digest(md5_base64_digest="digest_banana"), ), SubscriberDigestWithID( sid=SIDUtils.to_pb('IMSI33333'), digest=Digest(md5_base64_digest="digest_cherry"), ), ] client_per_sub_digest_ids = [ SIDUtils.to_str(digest.sid) for digest in request.per_sub_digests ] to_renew = [] deleted = [] if 'IMSI11111' not in client_per_sub_digest_ids: to_renew.append(subscriber_data_by_id('IMSI11111')) if 'IMSI22222' not in client_per_sub_digest_ids: to_renew.append(subscriber_data_by_id('IMSI22222')) if 'IMSI33333' not in client_per_sub_digest_ids: to_renew.append(subscriber_data_by_id('IMSI33333')) if 'IMSI00000' in client_per_sub_digest_ids: deleted.append('IMSI00000') resync = len(to_renew) >= 3 return SyncSubscribersResponse( resync=resync, flat_digest=Digest(md5_base64_digest="flat_digest_apple"), per_sub_digests=per_sub_digests, to_renew=to_renew, deleted=deleted, )
def create_bearer(self, imsi, lbi): """ Sends a CreateBearer Request to SPGW service """ print('Sending CreateBearer request to spgw service') req = CreateBearerRequest( sid=SIDUtils.to_pb(imsi), link_bearer_id=lbi, policy_rules=[ PolicyRule( qos=FlowQos( qci=1, gbr_ul=10000000, gbr_dl=10000000, max_req_bw_ul=10000000, max_req_bw_dl=10000000, arp=QosArp( priority_level=1, pre_capability=1, pre_vulnerability=0, ) ) ) ] ) self._stub.CreateBearer(req)
def _activate_subscriber_rules(self): try_grpc_call_with_retries( lambda: self._pipelined_stub.ActivateFlows( ActivateFlowsRequest(sid=SIDUtils.to_pb(self.cfg.imsi), rule_ids=self._static_rule_names, dynamic_rules=self._dynamic_rules)) )
def _cleanup_subs(): client = SubscriberDBStub( ServiceRegistry.get_rpc_channel('subscriberdb', ServiceRegistry.LOCAL), ) for sid in client.ListSubscribers(Void()).sids: client.DeleteSubscriber(SIDUtils.to_pb('IMSI%s' % sid.id))
def release_ip_handler(client, args): try: sid_msg = SIDUtils.to_pb(args.sid) except ValueError: print("Error: invalid SubscriberID format: %s" % args.sid) return try: ip = ipaddress.ip_address(args.ip) except ValueError: print("Error: invalid IP format: %s" % args.ip) return ip_msg = IPAddress() if ip.version == 4: ip_msg.version = IPAddress.IPV4 elif ip.version == 6: ip_msg.version = IPAddress.IPV6 else: print("Error: unknown IP version") return ip_msg.address = ip.packed request = ReleaseIPRequest() request.sid.CopyFrom(sid_msg) request.ip.CopyFrom(ip_msg) client.ReleaseIPAddress(request)
def update_quota(client, args): request = SubscriberQuotaUpdate(sid=SIDUtils.to_pb(args.imsi), mac_addr=args.mac, update_type=args.update_type) res = client.UpdateSubscriberQuotaState(request) if res is None: print("Error updating check quota flows")
def update_subscriber(client, args): update = SubscriberUpdate() update.data.sid.CopyFrom(SIDUtils.to_pb(args.sid)) gsm = update.data.gsm lte = update.data.lte fields = update.mask.paths if len(args.gsm_auth_tuple) != 0: gsm.state = GSMSubscription.ACTIVE for auth_tuple in args.gsm_auth_tuple: gsm.auth_tuples.append(bytes.fromhex(auth_tuple)) fields.append('gsm.state') fields.append('gsm.auth_tuples') if args.lte_auth_key is not None: lte.state = LTESubscription.ACTIVE lte.auth_key = bytes.fromhex(args.lte_auth_key) fields.append('lte.state') fields.append('lte.auth_key') if args.lte_auth_next_seq is not None: update.data.state.lte_auth_next_seq = args.lte_auth_next_seq fields.append('state.lte_auth_next_seq') if args.lte_auth_opc is not None: lte.auth_opc = bytes.fromhex(args.lte_auth_opc) fields.append('lte.state') fields.append('lte.auth_opc') client.UpdateSubscriber(update)
def allocate_ip_handler(client, args): try: sid_msg = SIDUtils.to_pb(args.sid) except ValueError: print("Invalid SubscriberID format: %s" % args.sid) return request = AllocateIPRequest() if int(args.version) == 4: request.version = AllocateIPRequest.IPV4 elif int(args.version) == 6: request.version = AllocateIPRequest.IPV6 else: print("Error: IP version %d is not supported yet" % args.version) return request.sid.CopyFrom(sid_msg) request.apn = args.apn response = client.AllocateIPAddress(request) ip_list_msg = response.ip_list for ip_msg in ip_list_msg: if ip_msg.version == IPAddress.IPV4: ip = ipaddress.IPv4Address(ip_msg.address) print("IPv4 address allocated: %s" % ip) elif ip_msg.version == IPAddress.IPV6: ip = ipaddress.IPv6Address(ip_msg.address) print("IPv6 address allocated: %s" % ip) else: print("Error: unknown IP version")
def add_subscriber(client, args): gsm = GSMSubscription() lte = LTESubscription() state = SubscriberState() if len(args.gsm_auth_tuple) != 0: gsm.state = GSMSubscription.ACTIVE for auth_tuple in args.gsm_auth_tuple: gsm.auth_tuples.append(bytes.fromhex(auth_tuple)) if args.lte_auth_key is not None: lte.state = LTESubscription.ACTIVE lte.auth_key = bytes.fromhex(args.lte_auth_key) if args.lte_auth_next_seq is not None: state.lte_auth_next_seq = args.lte_auth_next_seq if args.lte_auth_opc is not None: lte.auth_opc = bytes.fromhex(args.lte_auth_opc) data = SubscriberData( sid=SIDUtils.to_pb(args.sid), gsm=gsm, lte=lte, state=state, ) client.AddSubscriber(data)
def activate_flows(client, args): request = ActivateFlowsRequest( sid=SIDUtils.to_pb(args.imsi), rule_ids=args.rule_ids.split(','), request_origin=RequestOriginType(type=RequestOriginType.GX)) response = client.ActivateFlows(request) _print_rule_mod_results(response.static_rule_results)
def config_apn_details(self, imsi, apn_list): sid = SIDUtils.to_pb(imsi) update_sub = self._get_apn_data(sid, apn_list) fields = update_sub.mask.paths fields.append('non_3gpp') SubscriberDbGrpc._try_to_call( lambda: self._subscriber_stub.UpdateSubscriber(update_sub))
def _find_ip_and_apn_config(self, sid: str) -> (Optional[APNConfiguration]): if '.' in sid: imsi, apn_name = sid.split('.', maxsplit=1) else: imsi, apn_name = sid, '' logging.debug("Find APN config for: %s", sid) data = self.subscriber_client.GetSubscriberData(SIDUtils.to_pb(imsi)) if data and data.non_3gpp and data.non_3gpp.apn_config: selected_apn_conf = None for apn_config in data.non_3gpp.apn_config: logging.debug("APN config: %s", apn_config) if apn_config.assigned_static_ip is None or \ apn_config.assigned_static_ip == "": continue try: ipaddress.ip_address(apn_config.assigned_static_ip) except ValueError: continue if apn_config.service_selection == '*': selected_apn_conf = apn_config elif apn_config.service_selection == apn_name: selected_apn_conf = apn_config break if selected_apn_conf and selected_apn_conf.assigned_static_ip: return selected_apn_conf return None
def test_release_unknown_sid_apn_ip_tuple(self): """ releasing unknown sid-apn-ip tuple should raise NOT_FOUND """ self._stub.AddIPBlock(self._block_msg) alloc_request0 = AllocateIPRequest(sid=self._sid0, version=AllocateIPRequest.IPV4, apn=self._apn0) ip_msg0 = self._stub.AllocateIPAddress(alloc_request0) request = ReleaseIPRequest(sid=SIDUtils.to_pb("IMSI12345"), ip=ip_msg0.ip_list[0], apn=self._apn0) with self.assertRaises(grpc.RpcError) as err: self._stub.ReleaseIPAddress(request) self.assertEqual(err.exception.code(), grpc.StatusCode.NOT_FOUND) ip_bytes = bytes(map(int, '10.0.0.0'.split('.'))) request.ip.CopyFrom(IPAddress(version=IPAddress.IPV4, address=ip_bytes)) with self.assertRaises(grpc.RpcError) as err: self._stub.ReleaseIPAddress(request) self.assertEqual(err.exception.code(), grpc.StatusCode.NOT_FOUND) request = ReleaseIPRequest(sid=self._sid0, ip=ip_msg0.ip_list[0], apn=self._apn1) with self.assertRaises(grpc.RpcError) as err: self._stub.ReleaseIPAddress(request) self.assertEqual(err.exception.code(), grpc.StatusCode.NOT_FOUND)
def pcef_create_session(args): chan = ServiceRegistry.get_rpc_channel(args.pcef, ServiceRegistry.LOCAL) client = LocalSessionManagerStub(chan) request = LocalCreateSessionRequest( sid=SIDUtils.to_pb(args.imsi), ue_ipv4=args.user_ip) client.CreateSession(request)
def ListSubscribers(self, request, context): # pylint:disable=unused-argument """ Returns a list of subscribers from the store """ sids = self._store.list_subscribers() sid_msgs = [SIDUtils.to_pb(sid) for sid in sids] return subscriberdb_pb2.SubscriberIDSet(sids=sid_msgs)
def test_get_invalid_subscriber(self): """ Test if the rpc call returns NOT_FOUND """ with self.assertRaises(grpc.RpcError) as err: self._stub.GetSubscriberData(SIDUtils.to_pb('IMSI123')) self.assertEqual(err.exception.code(), grpc.StatusCode.NOT_FOUND)
def activate_flows(client, args): request = ActivateFlowsRequest( sid=SIDUtils.to_pb(args.imsi), ip_addr=args.ipv4, policies=[ VersionedPolicy( rule=PolicyRule( id=args.rule_id, priority=args.priority, hard_timeout=args.hard_timeout, flow_list=[ FlowDescription( match=FlowMatch( ip_dst=convert_ipv4_str_to_ip_proto(args.ipv4_dst), direction=FlowMatch.UPLINK, ), ), FlowDescription( match=FlowMatch( ip_src=convert_ipv4_str_to_ip_proto(args.ipv4_dst), direction=FlowMatch.DOWNLINK, ), ), ], ), version=1, ), ], request_origin=RequestOriginType(type=RequestOriginType.GX), shard_id=args.shard_id, ) response = client.ActivateFlows(request) _print_rule_mod_results(response.policy_results)
def deactivate_gy_flows(client, args): request = DeactivateFlowsRequest( sid=SIDUtils.to_pb(args.imsi), ip_addr=args.ipv4, rule_ids=args.rule_ids.split(',') if args.rule_ids else [], request_origin=RequestOriginType(type=RequestOriginType.GY)) client.DeactivateFlows(request)
def GetSubscriberIDFromIP(self, ip_addr, context): sent_ip = ipaddress.ip_address(ip_addr.address) sid = self._ipv4_allocator.get_sid_for_ip(sent_ip) if sid is None: context.set_details('IP address %s not found' % str(sent_ip)) context.set_code(grpc.StatusCode.NOT_FOUND) return SubscriberID() return SIDUtils.to_pb(sid)
def add_incomplete_sub(cls, sid: str): sub_db_sid = SIDUtils.to_pb(sid) lte = LTESubscription() lte.state = LTESubscription.ACTIVE state = SubscriberState() state.lte_auth_next_seq = 1 subs_data = SubscriberData(sid=sub_db_sid, lte=lte, state=state) cls.subs[str(sub_db_sid)] = subs_data
def delete_ue_mac_flow(client, args): request = UEMacFlowRequest( sid=SIDUtils.to_pb(args.imsi), mac_addr=args.mac, ) res = client.DeleteUEMacFlow(request) if res is None: print("Error associating MAC to IMSI")
def delete_bearer(client, args): req = DeleteBearerRequest( sid=SIDUtils.to_pb(args.imsi), link_bearer_id=args.lbi, eps_bearer_ids=[args.ebi] ) print("Deleting dedicated bearer for : ", args.imsi) client.DeleteBearer(req)
def delete_bearer(self, imsi, lbi, ebi): """ Sends a DeleteBearer Request to SPGW service """ print("Sending DeleteBearer request to spgw service") req = DeleteBearerRequest( sid=SIDUtils.to_pb(imsi), link_bearer_id=lbi, eps_bearer_ids=[ebi] ) self._stub.DeleteBearer(req)
def deactivate_gy_flows(client, args): policies = [VersionedPolicyID(rule_id=rule_id, version=1) for rule_id in args.rule_ids.split(',') if args.rule_ids] request = DeactivateFlowsRequest( sid=SIDUtils.to_pb(args.imsi), ip_addr=args.ipv4, policies=policies, request_origin=RequestOriginType(type=RequestOriginType.GY)) client.DeactivateFlows(request)