def ActivateFlows(self, request, context): """ Activate flows for a subscriber based on the pre-defined rules """ self._log_grpc_payload(request) if not self._service_manager.is_app_enabled( EnforcementController.APP_NAME, ): context.set_code(grpc.StatusCode.UNAVAILABLE) context.set_details('Service not enabled!') return None for controller in [ self._gy_app, self._enforcer_app, self._enforcement_stats, ]: if not controller.is_controller_ready(): context.set_code(grpc.StatusCode.UNAVAILABLE) context.set_details('Enforcement service not initialized!') return ActivateFlowsResult() fut = Future() # type: Future[ActivateFlowsResult] self._loop.call_soon_threadsafe(self._activate_flows, request, fut) try: return fut.result(timeout=self._call_timeout) except concurrent.futures.TimeoutError: logging.error("ActivateFlows request processing timed out") context.set_code(grpc.StatusCode.DEADLINE_EXCEEDED) context.set_details('ActivateFlows processing timed out') deactivate_req = get_deactivate_req(request) self._loop.call_soon_threadsafe( self._deactivate_flows, deactivate_req, ) return ActivateFlowsResult()
def activate_rules(self, imsi, msisdn: bytes, uplink_tunnel: int, ip_addr, apn_ambr, policies): """ Activate the flows for a subscriber based on the rules stored in Redis. During activation, a default flow may be installed for the subscriber. Args: imsi (string): subscriber id msisdn (bytes): subscriber MSISDN uplink_tunnel(int): Tunnel ID of the subscriber session. ip_addr (string): subscriber session ipv4 address policies (VersionedPolicies []): list of versioned policies to activate """ if self._datapath is None: self.logger.error('Datapath not initialized for adding flows') return ActivateFlowsResult( policy_results=[RuleModResult( rule_id=policy.rule.id, version=policy.version, result=RuleModResult.FAILURE, ) for policy in policies], ) policy_results = [] for policy in policies: res = self._install_flow_for_rule(imsi, msisdn, uplink_tunnel, ip_addr, apn_ambr, policy.rule, policy.version) policy_results.append(RuleModResult(rule_id=policy.rule.id, version=policy.version, result=res)) # Install a base flow for when no rule is matched. self._install_default_flow_for_subscriber(imsi, ip_addr) return ActivateFlowsResult( policy_results=policy_results, )
def activate_flows(self, imsi, ip_addr, static_rule_ids, dynamic_rules, fut): """ Activate the flows for a subscriber based on the rules stored in Redis. During activation, another low priority flow is installed for the subscriber in the event that all rules are out of credit. Args: imsi (string): subscriber id ip_addr (string): subscriber session ipv4 address static_rule_ids (string []): list of static rules to activate dynamic_rules (PolicyRule []): list of dynamic rules to activate fut (Future): future to wait on the results of flow activations """ if self._datapath is None: self.logger.error('Datapath not initialized for adding flows') fut.set_result( ActivateFlowsResult( static_rule_results=[ RuleModResult( rule_id=rule_id, result=RuleModResult.FAILURE, ) for rule_id in static_rule_ids ], dynamic_rule_results=[ RuleModResult( rule_id=rule.id, result=RuleModResult.FAILURE, ) for rule in dynamic_rules ], )) return static_results = [] for rule_id in static_rule_ids: res = self._install_flow_for_static_rule(imsi, ip_addr, rule_id) static_results.append(RuleModResult(rule_id=rule_id, result=res)) dyn_results = [] for rule in dynamic_rules: res = self._install_flow_for_rule(imsi, ip_addr, rule) dyn_results.append(RuleModResult(rule_id=rule.id, result=res)) # No matter what, install base flow to drop packets when all other # flows have been deactivated self._install_drop_flow(imsi) fut.set_result( ActivateFlowsResult( static_rule_results=static_results, dynamic_rule_results=dyn_results, ))
def activate_rules(self, imsi, msisdn: bytes, uplink_tunnel: int, ip_addr, apn_ambr, static_rule_ids, dynamic_rules): """ Activate the flows for a subscriber based on the rules stored in Redis. During activation, a default flow may be installed for the subscriber. Args: imsi (string): subscriber id msisdn (bytes): subscriber MSISDN uplink_tunnel(int): Tunnel ID of the subscriber session. ip_addr (string): subscriber session ipv4 address static_rule_ids (string []): list of static rules to activate dynamic_rules (PolicyRule []): list of dynamic rules to activate """ if self._datapath is None: self.logger.error('Datapath not initialized for adding flows') return ActivateFlowsResult( static_rule_results=[ RuleModResult( rule_id=rule_id, result=RuleModResult.FAILURE, ) for rule_id in static_rule_ids ], dynamic_rule_results=[ RuleModResult( rule_id=rule.id, result=RuleModResult.FAILURE, ) for rule in dynamic_rules ], ) static_results = [] for rule_id in static_rule_ids: res = self._install_flow_for_static_rule(imsi, msisdn, uplink_tunnel, ip_addr, apn_ambr, rule_id) static_results.append(RuleModResult(rule_id=rule_id, result=res)) dyn_results = [] for rule in dynamic_rules: res = self._install_flow_for_rule(imsi, msisdn, uplink_tunnel, ip_addr, apn_ambr, rule) dyn_results.append(RuleModResult(rule_id=rule.id, result=res)) # Install a base flow for when no rule is matched. self._install_default_flow_for_subscriber(imsi, ip_addr) return ActivateFlowsResult( static_rule_results=static_results, dynamic_rule_results=dyn_results, )
def _activate_flows( self, request: ActivateFlowsRequest, fut: 'Future[ActivateFlowsResult]', ) -> None: """ Activate flows for ipv4 / ipv6 or both CWF won't have an ip_addr passed """ ret = ActivateFlowsResult() if self._service_config['setup_type'] == 'CWF' or request.ip_addr: ipv4 = convert_ipv4_str_to_ip_proto(request.ip_addr) if request.request_origin.type == RequestOriginType.GX: self._update_version(request, ipv4) ret_ipv4 = self._install_flows_gx(request, ipv4) else: ret_ipv4 = self._install_flows_gy(request, ipv4) ret.policy_results.extend(ret_ipv4.policy_results) if request.ipv6_addr: ipv6 = convert_ipv6_bytes_to_ip_proto(request.ipv6_addr) self._update_ipv6_prefix_store(request.ipv6_addr) if request.request_origin.type == RequestOriginType.GX: self._update_version(request, ipv6) ret_ipv6 = self._install_flows_gx(request, ipv6) else: ret_ipv6 = self._install_flows_gy(request, ipv6) ret.policy_results.extend(ret_ipv6.policy_results) fut.set_result(ret)
def _activate_rules_in_enforcement_stats( self, imsi: str, msisdn: bytes, uplink_tunnel: int, ip_addr: IPAddress, apn_ambr: AggregatedMaximumBitrate, policies: List[VersionedPolicy], shard_id: int, local_f_teid_ng: int = 0, ) -> ActivateFlowsResult: if not self._service_manager.is_app_enabled( EnforcementStatsController.APP_NAME, ): return ActivateFlowsResult() enforcement_stats_res = self._enforcement_stats.activate_rules( imsi, msisdn, uplink_tunnel, ip_addr, apn_ambr, policies, shard_id, local_f_teid_ng, ) _report_enforcement_stats_failures(enforcement_stats_res, imsi) return enforcement_stats_res
def _activate_flows(self, request: ActivateFlowsRequest, fut: 'Future[ActivateFlowsResult]') -> None: """ Activate flows for ipv4 / ipv6 or both CWF won't have an ip_addr passed """ ret = ActivateFlowsResult() if self._service_config['setup_type'] == 'CWF' or request.ip_addr: ipv4 = convert_ipv4_str_to_ip_proto(request.ip_addr) if request.request_origin.type == RequestOriginType.GX: ret_ipv4 = self._install_flows_gx(request, ipv4) else: ret_ipv4 = self._install_flows_gy(request, ipv4) ret.static_rule_results.extend(ret_ipv4.static_rule_results) ret.dynamic_rule_results.extend(ret_ipv4.dynamic_rule_results) if request.ipv6_addr: ipv6 = convert_ipv6_bytes_to_ip_proto(request.ipv6_addr) self._update_ipv6_prefix_store(request.ipv6_addr) if request.request_origin.type == RequestOriginType.GX: ret_ipv6 = self._install_flows_gx(request, ipv6) else: ret_ipv6 = self._install_flows_gy(request, ipv6) ret.static_rule_results.extend(ret_ipv6.static_rule_results) ret.dynamic_rule_results.extend(ret_ipv6.dynamic_rule_results) if request.uplink_tunnel and request.downlink_tunnel: self._update_tunnel_map_store(request.uplink_tunnel, request.downlink_tunnel) fut.set_result(ret)
def _activate_rules_in_enforcement_stats( self, imsi: str, ip_addr: str, static_rule_ids: List[str], dynamic_rules: List[PolicyRule]) -> ActivateFlowsResult: if not self._service_manager.is_app_enabled( EnforcementStatsController.APP_NAME): return ActivateFlowsResult() enforcement_stats_res = self._enforcement_stats.activate_rules( imsi, ip_addr, static_rule_ids, dynamic_rules) _report_enforcement_stats_failures(enforcement_stats_res, imsi) return enforcement_stats_res
def activate_rules(self, imsi, ip_addr, static_rule_ids, dynamic_rules, fut): """ Activate the flows for a subscriber based on the rules stored in Redis. During activation, a default flow may be installed for the subscriber. Args: imsi (string): subscriber id ip_addr (string): subscriber session ipv4 address static_rule_ids (string []): list of static rules to activate dynamic_rules (PolicyRule []): list of dynamic rules to activate fut (Future): future to wait on the results of flow activations """ if self._datapath is None: self.logger.error('Datapath not initialized for adding flows') fut.set_result(ActivateFlowsResult( static_rule_results=[RuleModResult( rule_id=rule_id, result=RuleModResult.FAILURE, ) for rule_id in static_rule_ids], dynamic_rule_results=[RuleModResult( rule_id=rule.id, result=RuleModResult.FAILURE, ) for rule in dynamic_rules], )) return static_results = [] for rule_id in static_rule_ids: res = self._install_flow_for_static_rule(imsi, ip_addr, rule_id) static_results.append(RuleModResult(rule_id=rule_id, result=res)) dyn_results = [] for rule in dynamic_rules: res = self._install_flow_for_rule(imsi, ip_addr, rule) dyn_results.append(RuleModResult(rule_id=rule.id, result=res)) # Install a base flow for when no rule is matched. self._install_default_flow_for_subscriber(imsi) fut.set_result(ActivateFlowsResult( static_rule_results=static_results, dynamic_rule_results=dyn_results, ))
def _activate_rules_in_enforcement_stats( self, imsi: str, msisdn: bytes, uplink_tunnel: int, ip_addr: IPAddress, apn_ambr: AggregatedMaximumBitrate, static_rule_ids: List[str], dynamic_rules: List[PolicyRule]) -> ActivateFlowsResult: if not self._service_manager.is_app_enabled( EnforcementStatsController.APP_NAME): return ActivateFlowsResult() enforcement_stats_res = self._enforcement_stats.activate_rules( imsi, msisdn, uplink_tunnel, ip_addr, apn_ambr, static_rule_ids, dynamic_rules) _report_enforcement_stats_failures(enforcement_stats_res, imsi) return enforcement_stats_res
def _activate_rules_in_enforcement_stats( self, imsi: str, ip_addr: str, static_rule_ids: List[str], dynamic_rules: List[PolicyRule]) -> ActivateFlowsResult: if not self._service_manager.is_app_enabled( EnforcementStatsController.APP_NAME): return ActivateFlowsResult() fut = Future() # type: Future[ActivateFlowsResult] self._loop.call_soon_threadsafe(self._enforcement_stats.activate_rules, imsi, ip_addr, static_rule_ids, dynamic_rules, fut) enforcement_stats_res = fut.result() _report_enforcement_stats_failures(enforcement_stats_res, imsi) return enforcement_stats_res
def ng_update_session_flows( self, request: SessionSet, fut: 'Future(UPFSessionContextState)', ) -> UPFSessionContextState: """ Install PDR, FAR and QER flows for the 5G Session send by SMF """ logging.debug( 'Update 5G Session Flow for SessionID:%s, SessionVersion:%d', request.subscriber_id, request.session_version, ) # Convert message containing PDR to Named Tuple Rules. process_pdr_rules = OrderedDict() response = self._ng_servicer_app.ng_session_message_handler( request, process_pdr_rules, ) # Failure in message processing return failure if response.cause_info.cause_ie == CauseIE.REQUEST_ACCEPTED: for _, pdr_entries in process_pdr_rules.items(): # Create the Tunnel ret = self._ng_tunnel_update( pdr_entries, request.subscriber_id, ) if ret: # Install the Rules failed_policy_rule_results =\ self._ng_qer_update(request, pdr_entries) if (not ret or failed_policy_rule_results): offending_ie = OffendingIE( identifier=pdr_entries.pdr_id, version=pdr_entries.pdr_version, qos_enforce_rule_results=ActivateFlowsResult(\ policy_results=[failed_policy_rule_results], ), ) # Session information is filled already response.cause_info.cause_ie = CauseIE.RULE_CREATION_OR_MODIFICATION_FAILURE response.failure_rule_id.pdr.extend([offending_ie]) break fut.set_result(response)
def ActivateFlows(self, request, context): """ Activate flows for a subscriber based on the pre-defined rules """ self._log_grpc_payload(request) if not self._service_manager.is_app_enabled( EnforcementController.APP_NAME): context.set_code(grpc.StatusCode.UNAVAILABLE) context.set_details('Service not enabled!') return None fut = Future() # type: Future[ActivateFlowsResult] self._loop.call_soon_threadsafe(self._activate_flows, request, fut) try: return fut.result(timeout=self._call_timeout) except concurrent.futures.TimeoutError: logging.error("ActivateFlows request processing timed out") return ActivateFlowsResult()
def DeactivateFlows(self, request, context): """ Deactivate flows for a subscriber """ self._log_grpc_payload(request) if not self._service_manager.is_app_enabled( EnforcementController.APP_NAME): context.set_code(grpc.StatusCode.UNAVAILABLE) context.set_details('Service not enabled!') return None for controller in [self._gy_app, self._enforcer_app, self._enforcement_stats]: if not controller.is_controller_ready(): context.set_code(grpc.StatusCode.UNAVAILABLE) context.set_details('Enforcement service not initialized!') return ActivateFlowsResult() self._loop.call_soon_threadsafe(self._deactivate_flows, request) return DeactivateFlowsResult()