Example #1
0
    def process_update(
        self,
        stream_name: str,
        updates: List[DataUpdate],
        resync: bool,
    ):
        logging.info('Processing %d SID -> apn -> policy updates',
                     len(updates))
        all_subscriber_rules = []  # type: List[RulesPerSubscriber]
        for update in updates:
            imsi = update.key
            subApnPolicies = SubscriberPolicySet()
            subApnPolicies.ParseFromString(update.value)
            is_updated = self._are_sub_policies_updated(imsi, subApnPolicies)
            if is_updated:
                all_subscriber_rules.append(
                    self._build_sub_rule_set(imsi, subApnPolicies))
                self._apn_rules_by_sid[imsi] = subApnPolicies
        logging.info('Updating %d IMSIs with new APN->policy assignments',
                     len(all_subscriber_rules))
        update = SessionRules(rules_per_subscriber=all_subscriber_rules)

        try:
            self._session_mgr_stub.SetSessionRules(update, timeout=5)
        except grpc.RpcError as e:
            logging.error('Unable to apply apn->policy updates %s', str(e))
Example #2
0
 def setUp(self):
     rating_groups_by_id = {
         1: RatingGroup(
             id=1,
             limit_type=RatingGroup.INFINITE_UNMETERED,
         ),
         2: RatingGroup(
             id=2,
             limit_type=RatingGroup.INFINITE_METERED,
         ),
     }
     basenames_dict = {
         'bn1': ChargingRuleNameSet(RuleNames=['p5']),
         'bn2': ChargingRuleNameSet(RuleNames=['p6']),
     }
     apn_rules_by_sid = {
         "IMSI1234":
         SubscriberPolicySet(rules_per_apn=[
             ApnPolicySet(
                 apn="apn1",
                 assigned_base_names=[],
                 assigned_policies=["redirect"],
             ),
         ], ),
         "IMSI2345":
         SubscriberPolicySet(rules_per_apn=[
             ApnPolicySet(
                 apn="apn1",
                 assigned_base_names=["bn1"],
                 assigned_policies=[],
             ),
             ApnPolicySet(
                 apn="apn2",
                 assigned_base_names=["bn2"],
                 assigned_policies=[],
             ),
         ], ),
         "IMSI3456":
         SubscriberPolicySet(
             global_base_names=["bn1"],
             global_policies=[],
             rules_per_apn=[
                 ApnPolicySet(
                     apn="apn1",
                     assigned_base_names=[],
                     assigned_policies=[],
                 ),
             ],
         ),
     }
     self.servicer = SessionRpcServicer(
         self._get_mconfig(),
         rating_groups_by_id,
         basenames_dict,
         apn_rules_by_sid,
     )
Example #3
0
    def _handle_update(
        self,
        subscriber_id: str,
        assigned_policies: AssignedPolicies,
    ):
        """
        Based on the streamed updates, find the delta in added and removed
        rules. Then make a RAR to send to sessiond. If all goes successfully,
        update Redis with the currently installed policies for the subscriber.
        """
        prev_rules = self._get_prev_policies(subscriber_id)
        desired_rules = self._get_desired_rules(assigned_policies)

        self._apn_rules_by_sid[subscriber_id] = SubscriberPolicySet(
            rules_per_apn=[],
            global_policies=[
                rule_id for rule_id in assigned_policies.assigned_policies
            ],
            global_base_names=[
                basename for basename in assigned_policies.assigned_base_names
            ],
        )

        rar = self._generate_rar(subscriber_id,
                                 list(desired_rules - prev_rules),
                                 list(prev_rules - desired_rules))
        self._reauth_handler.handle_policy_re_auth(rar)
Example #4
0
 def process_update(
     self,
     stream_name: str,
     updates: List[DataUpdate],
     resync: bool,
 ):
     logging.info(
         'Processing %d SID -> apn -> policy updates',
         len(updates),
     )
     all_subscriber_rules = []  # type: List[RulesPerSubscriber]
     found_update = False
     for update in updates:
         imsi = update.key
         subApnPolicies = SubscriberPolicySet()
         subApnPolicies.ParseFromString(update.value)
         is_updated = self._are_sub_policies_updated(imsi, subApnPolicies)
         if is_updated:
             found_update = True
             all_subscriber_rules.append(
                 self._build_sub_rule_set(imsi, subApnPolicies),
             )
             self._apn_rules_by_sid[imsi] = subApnPolicies
     if not found_update:
         logging.debug(
             "No IMSIs with APN->Policy assignments found. "
             "Not sending an update to SessionD",
         )
         return
     logging.info(
         'Updating %d IMSIs with new APN->policy assignments',
         len(all_subscriber_rules),
     )
     update = SessionRules(rules_per_subscriber=all_subscriber_rules)
     try:
         self._session_mgr_stub.SetSessionRules(update, timeout=5)
     except grpc.RpcError as e:
         error_extra = (
             EXCLUDE_FROM_ERROR_MONITORING if indicates_connection_error(e)
             else None
         )
         logging.error(
             "Unable to apply apn->policy updates %s",
             str(e),
             extra=error_extra,
         )
Example #5
0
 def _are_sub_policies_updated(
     self,
     subscriber_id: str,
     subApnPolicies: SubscriberPolicySet,
 ) -> bool:
     if subscriber_id not in self._apn_rules_by_sid:
         return True
     prev = self._apn_rules_by_sid[subscriber_id]
     # TODO: (8/21/2020) repeated fields may not be ordered the same, use a
     #       different method to compare later
     return subApnPolicies.SerializeToString() != prev.SerializeToString()
    def test_Update(self):
        """
        Test the happy path where updates come in for rules, and sessiond
        accepts the SessionRules without issue.
        """

        # Expected call arguments to SetSessionRules
        allow_all_flow_list = [
            FlowDescription(
                match=FlowMatch(
                    direction=FlowMatch.Direction.Value("UPLINK"), ),
                action=FlowDescription.Action.Value("PERMIT"),
            ),
            FlowDescription(
                match=FlowMatch(
                    direction=FlowMatch.Direction.Value("DOWNLINK"), ),
                action=FlowDescription.Action.Value("PERMIT"),
            ),
        ]  # type: List[FlowDescription]
        no_tracking_type = PolicyRule.TrackingType.Value("NO_TRACKING")
        expected = SessionRules(rules_per_subscriber=[
            RulesPerSubscriber(
                imsi='imsi_1',
                rule_set=[
                    RuleSet(
                        apply_subscriber_wide=False,
                        apn="apn1",
                        static_rules=[
                            StaticRuleInstall(rule_id="p1"),
                        ],
                        dynamic_rules=[
                            DynamicRuleInstall(policy_rule=PolicyRule(
                                id="allowlist_sid-imsi_1-apn1",
                                priority=2,
                                flow_list=allow_all_flow_list,
                                tracking_type=no_tracking_type,
                            ))
                        ],
                    ),
                ]),
            RulesPerSubscriber(
                imsi='imsi_2',
                rule_set=[
                    RuleSet(
                        apply_subscriber_wide=False,
                        apn="apn1",
                        static_rules=[
                            StaticRuleInstall(rule_id="p5"),
                        ],
                        dynamic_rules=[
                            DynamicRuleInstall(policy_rule=PolicyRule(
                                id="allowlist_sid-imsi_2-apn1",
                                priority=2,
                                flow_list=allow_all_flow_list,
                                tracking_type=no_tracking_type,
                            ))
                        ],
                    ),
                ])
        ])

        # Setup the test
        apn_rules_dict = {}
        basenames_dict = {
            'bn1': ChargingRuleNameSet(RuleNames=['p5']),
            'bn2': ChargingRuleNameSet(RuleNames=['p6']),
        }
        stub = MockLocalSessionManagerStub()

        stub_call_args = []  # type: List[SessionRules]
        side_effect = get_SetSessionRules_side_effect(stub_call_args)
        stub.SetSessionRules = Mock(side_effect=side_effect)

        callback = ApnRuleMappingsStreamerCallback(
            stub,
            basenames_dict,
            apn_rules_dict,
        )

        # Construct a set of updates, keyed by subscriber ID
        updates = [
            DataUpdate(
                key="imsi_1",
                value=SubscriberPolicySet(rules_per_apn=[
                    ApnPolicySet(
                        apn="apn1",
                        assigned_base_names=[],
                        assigned_policies=["p1"],
                    ),
                ], ).SerializeToString(),
            ),
            DataUpdate(
                key="imsi_2",
                value=SubscriberPolicySet(rules_per_apn=[
                    ApnPolicySet(
                        apn="apn1",
                        assigned_base_names=["bn1"],
                        assigned_policies=[],
                    ),
                ], ).SerializeToString(),
            ),
        ]

        callback.process_update("stream", updates, False)

        # Since we used a stub which always succeeds when a RAR is made,
        # We should expect the assignments_dict to be updated
        imsi_1_policies = apn_rules_dict["imsi_1"]
        self.assertEqual(len(imsi_1_policies.rules_per_apn), 1,
                         'There should be 1 active APNs for imsi_1')
        self.assertEqual(len(stub_call_args), 1,
                         'Stub should have been called once')
        called_with = stub_call_args[0].SerializeToString()
        self.assertEqual(called_with, expected.SerializeToString(),
                         'SetSessionRules call has incorrect arguments')

        # Stream down a second update, and now IMSI_1 gets access to a new APN
        updates_2 = [
            DataUpdate(
                key="imsi_1",
                value=SubscriberPolicySet(rules_per_apn=[
                    ApnPolicySet(
                        apn="apn2",
                        assigned_base_names=["bn1"],
                        assigned_policies=[],
                    ),
                ], ).SerializeToString(),
            ),
            DataUpdate(
                key="imsi_2",
                value=SubscriberPolicySet(
                    global_base_names=["bn2"],
                    global_policies=[],
                    rules_per_apn=[
                        ApnPolicySet(
                            apn="apn1",
                            assigned_base_names=[],
                            assigned_policies=[],
                        ),
                    ],
                ).SerializeToString(),
            ),
        ]
        expected_2 = SessionRules(rules_per_subscriber=[
            RulesPerSubscriber(
                imsi='imsi_1',
                rule_set=[
                    RuleSet(
                        apply_subscriber_wide=False,
                        apn="apn2",
                        static_rules=[
                            StaticRuleInstall(rule_id="p5"),
                        ],
                        dynamic_rules=[
                            DynamicRuleInstall(policy_rule=PolicyRule(
                                id="allowlist_sid-imsi_1-apn2",
                                priority=2,
                                flow_list=allow_all_flow_list,
                                tracking_type=no_tracking_type,
                            ))
                        ],
                    ),
                ]),
            RulesPerSubscriber(
                imsi='imsi_2',
                rule_set=[
                    RuleSet(
                        apply_subscriber_wide=False,
                        apn="apn1",
                        static_rules=[
                            StaticRuleInstall(rule_id="p6"),
                        ],
                        dynamic_rules=[
                            DynamicRuleInstall(policy_rule=PolicyRule(
                                id="allowlist_sid-imsi_2-apn1",
                                priority=2,
                                flow_list=allow_all_flow_list,
                                tracking_type=no_tracking_type,
                            ))
                        ],
                    ),
                ]),
        ])

        callback.process_update("stream", updates_2, False)

        imsi_1_policies = apn_rules_dict["imsi_1"]
        self.assertEqual(len(imsi_1_policies.rules_per_apn), 1,
                         'There should be 1 active APNs for imsi_1')
        self.assertEqual(len(stub_call_args), 2,
                         'Stub should have been called twice')
        called_with = stub_call_args[1].SerializeToString()
        self.assertEqual(called_with, expected_2.SerializeToString(),
                         'SetSessionRules call has incorrect arguments')