Esempio n. 1
0
    def test_meter_stats(self):
        """
        Test metering stats by sending uplink and downlink packets from 2
        subscribers and making sure the correct statistics are sent to the cloud
        """
        # Set up subscribers
        sub1 = SubContextConfig('IMSI001010000000013', '192.168.128.74',
                                self._tbl_num)
        sub2 = SubContextConfig('IMSI001010000000014', '192.168.128.75',
                                self._tbl_num)

        isolator1 = RyuDirectTableIsolator(
            RyuForwardFlowArgsBuilder.from_subscriber(sub1)
                                     .build_requests(),
            self.testing_controller,
        )
        isolator2 = RyuDirectTableIsolator(
            RyuForwardFlowArgsBuilder.from_subscriber(sub2)
                                     .build_requests(),
            self.testing_controller,
        )

        # Set up packets
        pkt_sender = ScapyPacketInjector(self.BRIDGE)
        pkt_count = 4  # send each packet 4 times
        # sub1: 2 uplink pkts, 1 downlink
        # sub2: 1 uplink pkt
        packets = [
            self._make_default_pkt('45.10.0.1', sub1.ip),
            self._make_default_pkt('45.10.0.2', sub1.ip),
            self._make_default_pkt(sub1.ip, '45.10.0.1'),
            self._make_default_pkt('45.10.0.3', sub2.ip),
        ]
        pkt_size = len(packets[0])
        # These packets are sent at the start to install the meter flows
        initial_packets = [
            self._make_default_pkt('45.10.0.2', sub1.ip),
            self._make_default_pkt('45.10.0.3', sub2.ip),
        ]

        target_usage = {
            # sub1: 2 uplink * 4 packets each = 8
            #       1 downlink * 4 packets each = 4
            sub1.imsi: _create_usage_record(8, 4, pkt_size),
            # sub2: 1 uplink * 4 packets each = 4
            sub2.imsi: _create_usage_record(4, 0, pkt_size),
        }

        # Send packets through pipeline and wait
        with isolator1, isolator2:
            for pkt in initial_packets:
                pkt_sender.send(pkt, 1)
            wait_after_send(self.testing_controller)

            for pkt in packets:
                pkt_sender.send(pkt, pkt_count)
            wait_after_send(self.testing_controller)
            wait_for_meter_stats(self.stats_controller, target_usage)
Esempio n. 2
0
    def test_ocs_failure(self):
        """
        Test that when the OCS fails to respond to an update request, the service
        is cut off until the update can be completed
        """
        sub1 = SubContextConfig('IMSI001010000088888', '192.168.128.74', default_ambr_config, 4)
        quota = 1024

        self.test_util.controller.mock_create_session = Mock(
            return_value=session_manager_pb2.CreateSessionResponse(
                credits=[create_update_response(sub1.imsi, 1, quota)],
                static_rules=[session_manager_pb2.StaticRuleInstall(
                    rule_id="simple_match"
                )],
            ),
        )

        update_complete = hub.Queue()
        self.test_util.controller.mock_update_session = Mock(
            side_effect=get_standard_update_response(
                update_complete, None, quota, success=False),
        )

        self.test_util.controller.mock_terminate_session = Mock(
            return_value=session_manager_pb2.SessionTerminateResponse(),
        )

        self.test_util.sessiond.CreateSession(
            session_manager_pb2.LocalCreateSessionRequest(
                sid=SubscriberID(id=sub1.imsi),
                ue_ipv4=sub1.ip,
            ),
        )
        self.assertEqual(self.test_util.controller.mock_create_session.call_count, 1)

        packets = get_packets_for_flows(
            sub1, self.test_util.static_rules["simple_match"].flow_list)
        packet_count = int(quota / len(packets[0])) + 1
        sender = self.test_util.get_packet_sender([sub1], packets, packet_count)

        # assert after session init, data can flow
        self.assertGreater(self.test_util.thread.run_in_greenthread(sender), 0)

        # wait for failed update
        self.assertIsNotNone(get_from_queue(update_complete))
        hub.sleep(2)

        # assert that no data can be sent anymore
        self.assertEqual(self.test_util.thread.run_in_greenthread(sender), 0)

        self.test_util.controller.mock_update_session = Mock(
            side_effect=get_standard_update_response(
                update_complete, None, quota, success=True),
        )
        # wait for second update cycle to reactivate
        hub.sleep(4)
        self.assertGreater(self.test_util.thread.run_in_greenthread(sender), 0)

        self.test_util.sessiond.EndSession(SubscriberID(id=sub1.imsi))
        self.assertEqual(self.test_util.controller.mock_terminate_session.call_count, 1)
Esempio n. 3
0
 def _setup_subscribers_ipv6(self):
     return SubContextConfig(
         'IMSI001010000000013',
         'ab42::74',
         default_ambr_config,
         self._tbl_num,
     )
Esempio n. 4
0
 def _setup_subscribers(self):
     return SubContextConfig(
         'IMSI001010000000013',
         '192.168.128.74',
         default_ambr_config,
         self._tbl_num,
     )
Esempio n. 5
0
def send_create_session(client, args):
    sub1 = SubContextConfig('IMSI' + args.imsi, '192.168.128.74', 4)

    try:
        create_account_in_PCRF(args.imsi)
    except grpc.RpcError as e:
        print("gRPC failed with %s: %s" % (e.code(), e.details()))

    try:
        create_account_in_OCS(args.imsi)
    except grpc.RpcError as e:
        print("gRPC failed with %s: %s" % (e.code(), e.details()))

    req = LocalCreateSessionRequest(
        sid=SubscriberID(id=sub1.imsi),
        ue_ipv4=sub1.ip,
    )
    print("Sending LocalCreateSessionRequest with following fields:\n %s" %
          req)
    try:
        client.CreateSession(req)
    except grpc.RpcError as e:
        print("gRPC failed with %s: %s" % (e.code(), e.details()))

    req = SubscriberID(id=sub1.imsi)
    print("Sending EndSession with following fields:\n %s" % req)
    try:
        client.EndSession(req)
    except grpc.RpcError as e:
        print("gRPC failed with %s: %s" % (e.code(), e.details()))
Esempio n. 6
0
    def test_conntrack(self):
        """
        Test that conntrack rules are properly setup
        Verifies that 3 new connections are detected (2 tcp, 1 udp)
        """
        sub_ip = '145.254.160.237'  # extracted from pcap don't change
        sub = SubContextConfig(
            'IMSI001010000000013',
            sub_ip,
            default_ambr_config,
            self._tbl_num,
        )

        isolator = RyuDirectTableIsolator(
            RyuForwardFlowArgsBuilder.from_subscriber(sub).build_requests(),
            self.testing_controller,
        )
        pkt_sender = ScapyPacketInjector(self.BRIDGE)

        snapshot_verifier = SnapshotVerifier(
            self,
            self.BRIDGE,
            self.service_manager,
            include_stats=False,
        )

        current_path = \
            str(pathlib.Path(__file__).parent.absolute())

        with isolator, snapshot_verifier:
            pkt_sender.send_pcap(current_path + "/pcaps/http_download.cap")
Esempio n. 7
0
    def test_gre_learn(self):
        """
        Test that uplink packet hits the learn rule and a new flow is created
        in the scratch table(snapshot is checked)
        """
        # Set up subscribers
        sub = SubContextConfig('IMSI001010000000013', '192.168.128.74',
                               self._tbl_num)

        isolator = RyuDirectTableIsolator(
            RyuForwardFlowArgsBuilder.from_subscriber(sub).build_requests(),
            self.testing_controller,
        )

        # Set up packets
        pkt_sender = ScapyPacketInjector(self.BRIDGE)
        pkt = IPPacketBuilder() \
            .set_ip_layer(self.INBOUND_TEST_IP, sub.ip) \
            .set_ether_layer(self.MAC_DEST, "01:02:03:04:05:06") \
            .build()

        with isolator:
            pkt_sender.send(pkt)

        assert_bridge_snapshot_match(self, self.BRIDGE, self.service_manager)
Esempio n. 8
0
    def test_basic_init(self):
        """
        Initiate subscriber, return 1 static policy with monitoring key, send
        traffic to match the policy, verify monitoring update is sent, terminate
        subscriber
        """
        sub1 = SubContextConfig('IMSI001010000088888', '192.168.128.74', default_ambr_config, 4)
        quota = 1024  # bytes

        self.test_util.controller.mock_create_session = Mock(
            return_value=session_manager_pb2.CreateSessionResponse(
                credits=[],
                static_rules=[
                    session_manager_pb2.StaticRuleInstall(
                        rule_id="monitor_rule",
                    ),
                ],
                dynamic_rules=[],
                usage_monitors=[
                    create_monitor_response(
                        sub1.imsi, "mkey1", quota, session_manager_pb2.PCC_RULE_LEVEL,
                    ),
                ],
            ),
        )

        self.test_util.controller.mock_terminate_session = Mock(
            return_value=session_manager_pb2.SessionTerminateResponse(),
        )

        monitor_complete = hub.Queue()
        self.test_util.controller.mock_update_session = Mock(
            side_effect=get_standard_update_response(
                None, monitor_complete, quota,
            ),
        )

        self.test_util.sessiond.CreateSession(
            session_manager_pb2.LocalCreateSessionRequest(
                sid=SubscriberID(id=sub1.imsi),
                ue_ipv4=sub1.ip,
            ),
        )

        self.assertEqual(self.test_util.controller.mock_create_session.call_count, 1)

        packets = get_packets_for_flows(
            sub1, self.test_util.static_rules["monitor_rule"].flow_list,
        )
        packet_count = int(quota / len(packets[0])) + 1

        self.test_util.thread.run_in_greenthread(
            self.test_util.get_packet_sender([sub1], packets, packet_count),
        )
        self.assertIsNotNone(get_from_queue(monitor_complete))
        self.assertEqual(self.test_util.controller.mock_update_session.call_count, 1)

        self.test_util.sessiond.EndSession(SubscriberID(id=sub1.imsi))
        self.assertEqual(self.test_util.controller.mock_terminate_session.call_count, 1)
Esempio n. 9
0
    def test_no_match(self):
        """
        No match test, checks that packets are not matched when
        the there is no match to the ip and direction in the blacklist.

        Assert:
            Both packets are not matched
            Ip match flows are added
        """
        # Set up subscribers
        sub = SubContextConfig('IMSI001010000000013', '192.168.128.74',
                               self._tbl_num)

        isolator = RyuDirectTableIsolator(
            RyuForwardFlowArgsBuilder.from_subscriber(sub).build_requests(),
            self.testing_controller,
        )

        # Set up packets. The directions of the packets are opposite of the
        # installed match flow, so there should not matches.
        pkt_sender = ScapyPacketInjector(self.BRIDGE)
        packets = [
            self._build_default_ip_packet(self.OUTBOUND_TEST_IP, sub.ip),
            self._build_default_ip_packet(sub.ip, self.INBOUND_TEST_IP),
        ]

        # Check if these flows were added (queries should return flows)
        outbound_flow_queries = [
            FlowQuery(self._tbl_num, self.testing_controller,
                      match=MagmaMatch(eth_type=ether_types.ETH_TYPE_IP,
                                       direction=Direction.OUT,
                                       ipv4_dst=self.INBOUND_TEST_IP)),
            FlowQuery(self._tbl_num, self.testing_controller,
                      match=MagmaMatch(eth_type=ether_types.ETH_TYPE_IP,
                                       direction=Direction.IN,
                                       ipv4_src=self.OUTBOUND_TEST_IP)),
        ]

        # =========================== Verification ===========================
        # packets are not matched, ip match flows installed
        flow_verifier = FlowVerifier(
            [
                FlowTest(
                    FlowQuery(self._tbl_num, self.testing_controller), 2),
            ] + [FlowTest(query, 0, flow_count=1) for query in
                 outbound_flow_queries],
            lambda: wait_after_send(
                self.testing_controller)
        )

        with isolator, flow_verifier:
            for packet in packets:
                pkt_sender.send(packet)

        flow_verifier.verify()
        assert_bridge_snapshot_match(self,
                                     self.BRIDGE,
                                     self.service_manager)
Esempio n. 10
0
    def test_inbound_ip_match(self):
        """
        Inbound ip match test, checks that packets are properly matched when
        the inbound traffic matches an ip in the blocklist.

        Assert:
            Both packets are matched
            Ip match flows are added
        """
        # Set up subscribers
        sub = SubContextConfig('IMSI001010000000013', '192.168.128.74',
                               default_ambr_config, self._tbl_num)

        isolator = RyuDirectTableIsolator(
            RyuForwardFlowArgsBuilder.from_subscriber(sub).build_requests(),
            self.testing_controller,
        )

        # Set up packets
        pkt_sender = ScapyPacketInjector(self.BRIDGE)
        packets = [
            self._build_default_ip_packet(self.INBOUND_TEST_IP, sub.ip),
            self._build_default_ip_packet(self.BOTH_DIR_TEST_IP, sub.ip),
        ]

        # Check if these flows were added (queries should return flows)
        inbound_flow_queries = [
            FlowQuery(self._tbl_num, self.testing_controller,
                      match=MagmaMatch(eth_type=ether_types.ETH_TYPE_IP,
                                       direction=Direction.OUT,
                                       ipv4_dst=self.INBOUND_TEST_IP)),
            FlowQuery(self._tbl_num, self.testing_controller,
                      match=MagmaMatch(eth_type=ether_types.ETH_TYPE_IP,
                                       direction=Direction.OUT,
                                       ipv4_dst=self.BOTH_DIR_TEST_IP)),
        ]

        # =========================== Verification ===========================
        # packets matched, ip match flows installed
        flow_verifier = FlowVerifier(
            [
                FlowTest(
                    FlowQuery(self._tbl_num, self.testing_controller), 2),
            ] + [FlowTest(query, 1, flow_count=1) for query in
                 inbound_flow_queries],
            lambda: wait_after_send(
                self.testing_controller)
        )

        with isolator, flow_verifier:
            for packet in packets:
                pkt_sender.send(packet)

        flow_verifier.verify()
        assert_bridge_snapshot_match(self,
                                     self.BRIDGE,
                                     self.service_manager)
Esempio n. 11
0
    def test_rules_with_failed_credit(self):
        """
        Test that when a session is initialized but the OCS either errored out or
        returned 0 GSUs, data is not allowed to flow
        """
        sub1 = SubContextConfig('IMSI001010000088888', '192.168.128.74', default_ambr_config, 4)

        rule2 = create_uplink_rule("rule2", 2, '46.10.0.1')
        rule3 = create_uplink_rule("rule3", 3, '47.10.0.1')
        self.test_util.controller.mock_create_session = Mock(
            return_value=session_manager_pb2.CreateSessionResponse(
                credits=[
                    # failed update
                    create_update_response(sub1.imsi, 1, 0, success=False),
                    # successful update, no credit
                    create_update_response(sub1.imsi, 1, 0, success=True),
                ],
                static_rules=[session_manager_pb2.StaticRuleInstall(
                    rule_id="simple_match"
                )],  # no credit for RG 1
                dynamic_rules=[
                    session_manager_pb2.DynamicRuleInstall(
                        policy_rule=rule2
                    ),
                    session_manager_pb2.DynamicRuleInstall(
                        policy_rule=rule3
                    )
                ],
            ),
        )

        self.test_util.controller.mock_terminate_session = Mock(
            return_value=session_manager_pb2.SessionTerminateResponse(),
        )

        self.test_util.sessiond.CreateSession(
            session_manager_pb2.LocalCreateSessionRequest(
                sid=SubscriberID(id=sub1.imsi),
                ue_ipv4=sub1.ip,
            ),
        )
        self.assertEqual(self.test_util.controller.mock_create_session.call_count, 1)

        flows = [rule.flow_list[0] for rule in [rule2, rule3]]
        packets = get_packets_for_flows(sub1, flows)
        pkt_diff = self.test_util.thread.run_in_greenthread(
            self.test_util.get_packet_sender([sub1], packets, 1),
        )
        self.assertEqual(pkt_diff, 0)

        self.test_util.sessiond.EndSession(SubscriberID(id=sub1.imsi))
        self.assertEqual(self.test_util.controller.mock_terminate_session.call_count, 1)
Esempio n. 12
0
    def test_blocking_ip_match(self):
        """
        Inbound ip match test, checks that packets are properly matched when
        the inbound traffic matches an ip in the blocklist.

        Assert:
            Both packets are matched
            Ip match flows are added
        """
        # Set up subscribers
        sub = SubContextConfig(
            'IMSI001010000000013',
            '192.168.128.74',
            default_ambr_config,
            self._tbl_num,
        )

        isolator = RyuDirectTableIsolator(
            RyuForwardFlowArgsBuilder.from_subscriber(sub).build_requests(),
            self.testing_controller,
        )

        # Set up packets
        pkt_sender = ScapyPacketInjector(self.BRIDGE)
        packets = [
            _build_default_ip_packet(self.MAC_DEST, self.OUTBOUND_TEST_IP1,
                                     sub.ip),
            _build_default_ip_packet(self.MAC_DEST, self.OUTBOUND_TEST_IP2,
                                     sub.ip),
            _build_default_ip_packet(self.MAC_DEST, self.BOTH_DIR_TEST_IP,
                                     sub.ip),
        ]

        with isolator:
            for packet in packets:
                pkt_sender.send(packet)

        assert_bridge_snapshot_match(
            self,
            self.BRIDGE,
            self.service_manager,
        )
Esempio n. 13
0
    def test_rule_with_no_credit(self):
        """
        Test that when a rule is returned that requires OCS tracking but has
        no credit, data is not allowed to pass
        """
        sub1 = SubContextConfig('IMSI001010000088888', '192.168.128.74',
                                default_ambr_config, 4)

        self.test_util.controller.mock_create_session = Mock(
            return_value=session_manager_pb2.CreateSessionResponse(
                static_rules=[
                    session_manager_pb2.StaticRuleInstall(
                        rule_id="simple_match", ),
                ],  # no credit for RG 1
            ), )

        self.test_util.controller.mock_terminate_session = Mock(
            return_value=session_manager_pb2.SessionTerminateResponse(), )

        self.test_util.sessiond.CreateSession(
            session_manager_pb2.LocalCreateSessionRequest(
                sid=SubscriberID(id=sub1.imsi),
                ue_ipv4=sub1.ip,
            ), )
        self.assertEqual(
            self.test_util.controller.mock_create_session.call_count, 1)

        packets = get_packets_for_flows(
            sub1,
            self.test_util.static_rules["simple_match"].flow_list,
        )

        pkt_diff = self.test_util.thread.run_in_greenthread(
            self.test_util.get_packet_sender([sub1], packets, 1), )
        self.assertEqual(pkt_diff, 0)

        self.test_util.sessiond.EndSession(SubscriberID(id=sub1.imsi))
        self.assertEqual(
            self.test_util.controller.mock_terminate_session.call_count, 1)
Esempio n. 14
0
    def test_out_of_credit(self):
        """
        Initiate subscriber, return 1 static policy, send traffic to match the
        policy, verify update is sent, return final credits, use up final
        credits, ensure that no traffic can be sent
        """
        sub1 = SubContextConfig('IMSI001010000088888', '192.168.128.74', 4)
        quota = 1024  # bytes

        self.test_util.controller.mock_create_session = Mock(
            return_value=session_manager_pb2.CreateSessionResponse(
                credits=[
                    session_manager_pb2.CreditUpdateResponse(
                        success=True,
                        sid=sub1.imsi,
                        charging_key=1,
                        credit=session_manager_pb2.ChargingCredit(
                            granted_units=session_manager_pb2.GrantedUnits(
                                total=session_manager_pb2.CreditUnit(
                                    is_valid=True,
                                    volume=quota,
                                ), ), ),
                    )
                ],
                static_rules=[
                    session_manager_pb2.StaticRuleInstall(
                        rule_id="simple_match")
                ],
                dynamic_rules=[],
                usage_monitors=[],
            ), )

        self.test_util.controller.mock_terminate_session = Mock(
            return_value=session_manager_pb2.SessionTerminateResponse(), )

        update_complete = hub.Queue()
        self.test_util.controller.mock_update_session = Mock(
            side_effect=get_standard_update_response(update_complete,
                                                     None,
                                                     quota,
                                                     is_final=True), )

        self.test_util.sessiond.CreateSession(
            session_manager_pb2.LocalCreateSessionRequest(
                sid=SubscriberID(id=sub1.imsi),
                ue_ipv4=sub1.ip,
            ), )
        self.assertEqual(
            self.test_util.controller.mock_create_session.call_count, 1)

        packets = get_packets_for_flows(
            sub1, self.test_util.static_rules["simple_match"].flow_list)
        packet_count = int(quota / len(packets[0])) + 1
        send_packets = self.test_util.get_packet_sender([sub1], packets,
                                                        packet_count)

        self.test_util.thread.run_in_greenthread(send_packets)
        self.assertIsNotNone(get_from_queue(update_complete))
        self.assertEqual(
            self.test_util.controller.mock_update_session.call_count, 1)

        # use up last credits
        self.test_util.thread.run_in_greenthread(send_packets)
        hub.sleep(3)  # wait for sessiond to terminate rule after update

        pkt_diff = self.test_util.thread.run_in_greenthread(send_packets)
        self.assertEqual(pkt_diff, 0)

        self.test_util.proxy_responder.ChargingReAuth(
            session_manager_pb2.ChargingReAuthRequest(
                charging_key=1,
                sid=sub1.imsi,
            ), )
        get_from_queue(update_complete)
        self.assertEqual(
            self.test_util.controller.mock_update_session.call_count, 2)
        # wait for 1 update to trigger credit request, another to trigger
        # rule activation
        # TODO Add future to track when flows are added/deleted
        hub.sleep(5)
        pkt_diff = self.test_util.thread.run_in_greenthread(send_packets)
        self.assertGreater(pkt_diff, 0)

        self.test_util.sessiond.EndSession(SubscriberID(id=sub1.imsi))
        self.assertEqual(
            self.test_util.controller.mock_terminate_session.call_count, 1)
Esempio n. 15
0
    def test_mixed_monitors_and_updates(self):
        """
        Test a mix of usage monitors, session monitors, and charging credits to
        PCRF and OCS.
        """
        sub1 = SubContextConfig('IMSI001010000088888', '192.168.128.74', 4)
        quota = 1024  # bytes

        pcrf_rule = create_uplink_rule("pcrf_rule", 0, '46.10.0.1',
                                                m_key="key1",
                                                tracking=PolicyRule.ONLY_PCRF)
        ocs_rule = create_uplink_rule("ocs_rule", 1, '47.10.0.1',
                                               tracking=PolicyRule.ONLY_OCS)
        both_rule = create_uplink_rule("both_rule", 2, '48.10.0.1',
                                                m_key="key2",
                                                tracking=PolicyRule.OCS_AND_PCRF)

        self.test_util.controller.mock_create_session = Mock(
            return_value=session_manager_pb2.CreateSessionResponse(
                credits=[
                    create_update_response("", 1, quota),
                    create_update_response("", 2, quota),
                ],
                dynamic_rules=[
                    session_manager_pb2.DynamicRuleInstall(
                        policy_rule=pcrf_rule,
                    ),
                    session_manager_pb2.DynamicRuleInstall(
                        policy_rule=ocs_rule,
                    ),
                    session_manager_pb2.DynamicRuleInstall(
                        policy_rule=both_rule,
                    ),
                ],
                usage_monitors=[
                    create_monitor_response(
                        sub1.imsi,
                        "key1",
                        quota,
                        session_manager_pb2.PCC_RULE_LEVEL,
                    ),
                    create_monitor_response(
                        sub1.imsi,
                        "key2",
                        quota,
                        session_manager_pb2.PCC_RULE_LEVEL,
                    ),
                    create_monitor_response(
                        sub1.imsi,
                        "key3",
                        quota,
                        session_manager_pb2.SESSION_LEVEL,
                    ),
                ],
            ),
        )

        self.test_util.controller.mock_terminate_session = Mock(
            return_value=session_manager_pb2.SessionTerminateResponse(),
        )

        charging_complete = hub.Queue()
        monitor_complete = hub.Queue()
        self.test_util.controller.mock_update_session = Mock(
            side_effect=get_standard_update_response(
                charging_complete, monitor_complete, quota),
        )

        self.test_util.sessiond.CreateSession(
            session_manager_pb2.LocalCreateSessionRequest(
                sid=SubscriberID(id=sub1.imsi),
                ue_ipv4=sub1.ip,
            ),
        )

        self.assertEqual(self.test_util.controller.mock_create_session.call_count, 1)
        flows = [rule.flow_list[0] for rule in [pcrf_rule, ocs_rule, both_rule]]
        packets = get_packets_for_flows(sub1, flows)
        packet_count = int(quota / len(packets[0])) + 1
        self.test_util.thread.run_in_greenthread(
            self.test_util.get_packet_sender([sub1], packets, packet_count),
        )

        # Wait for responses for keys 1 and 2 (ocs_rule and both_rule)
        charging_keys = {1, 2}
        for _ in range(len(charging_keys)):
            update = get_from_queue(charging_complete)
            self.assertTrue(update.usage.charging_key in charging_keys)
            charging_keys.remove(update.usage.charging_key)

        # Wait for responses for mkeys key1 (pcrf_rule), key2 (both_rule),
        # key3 (session rule)
        monitoring_keys = ["key1", "key2", "key3"]
        for _ in range(len(monitoring_keys)):
            monitor = get_from_queue(monitor_complete)
            self.assertTrue(monitor.update.monitoring_key in monitoring_keys)
            monitoring_keys.remove(monitor.update.monitoring_key)

        self.test_util.sessiond.EndSession(SubscriberID(id=sub1.imsi))
        self.assertEqual(self.test_util.controller.mock_terminate_session.call_count, 1)
Esempio n. 16
0
    def test_meter_stats(self):
        """
        Test metering stats by sending uplink and downlink packets from 2
        subscribers and making sure the correct statistics are sent to the cloud
        """
        # Set up subscribers
        sub1 = SubContextConfig('IMSI001010000000013', '192.168.128.74',
                                self._tbl_num)
        sub2 = SubContextConfig('IMSI001010000000014', '192.168.128.75',
                                self._tbl_num)

        isolator1 = RyuDirectTableIsolator(
            RyuForwardFlowArgsBuilder.from_subscriber(sub1).build_requests(),
            self.testing_controller,
        )
        isolator2 = RyuDirectTableIsolator(
            RyuForwardFlowArgsBuilder.from_subscriber(sub2).build_requests(),
            self.testing_controller,
        )

        # Set up packets
        pkt_sender = ScapyPacketInjector(self.BRIDGE)
        pkt_count = 4  # send each packet 4 times
        # sub1: 2 uplink pkts, 1 downlink
        # sub2: 1 uplink pkt
        packets = [
            self._make_default_pkt('45.10.0.1', sub1.ip),
            self._make_default_pkt('45.10.0.2', sub1.ip),
            self._make_default_pkt(sub1.ip, '45.10.0.1'),
            self._make_default_pkt('45.10.0.3', sub2.ip),
        ]
        pkt_size = len(packets[0])

        # Send packets through pipeline and wait
        with isolator1, isolator2:
            for pkt in packets:
                pkt_sender.send(pkt, pkt_count)
            wait_after_send(self.testing_controller)
            hub.sleep(3)

        # manually run stats update
        for _, datapath in self.stats_controller.dpset.get_all():
            self.stats_controller._poll_stats(datapath)

        # retrieve the latest statistics
        stats_queue = hub.Queue()

        def mock_sync_stats(*args, **kwargs):
            stats_queue.put(args[0])

        self.stats_controller._sync_stats = MagicMock(
            side_effect=mock_sync_stats, )
        stats_dict = stats_queue.get(block=True, timeout=5)

        self.assertTrue(sub1.imsi in stats_dict)
        self.assertTrue(sub2.imsi in stats_dict)
        # sub1: 2 uplink * 4 packets each - 1 packet in = 3
        #       1 downlink * 4 packets each - 1 packet in = 7
        self._assert_stats_match(stats_dict[sub1.imsi], 7, 3, pkt_size)
        # sub2: 1 uplink * 4 packets each - 1 packet in = 3
        self._assert_stats_match(stats_dict[sub2.imsi], 3, 0, pkt_size)
Esempio n. 17
0
    def test_process_deleted_subscriber(self):
        """
        With usage polling on, send packets to install metering flows and
        delete one of them by removing the subscriber from the subscriber ip
        table.

        Verifies that the metering flows for the subscriber is deleted after
        the correct usage is reported.
        """
        # Set up subscribers
        sub1 = SubContextConfig('IMSI001010000000013', '192.168.128.74',
                                self._tbl_num)
        sub2 = SubContextConfig('IMSI001010000000014', '192.168.128.75',
                                self._tbl_num)

        isolator1 = RyuDirectTableIsolator(
            RyuForwardFlowArgsBuilder.from_subscriber(sub1).build_requests(),
            self.testing_controller,
        )
        isolator2 = RyuDirectTableIsolator(
            RyuForwardFlowArgsBuilder.from_subscriber(sub2).build_requests(),
            self.testing_controller,
        )

        # Set up packets
        pkt_sender = ScapyPacketInjector(self.BRIDGE)
        packets = [
            _make_default_pkt(self.MAC_DEST, '45.10.0.1', sub1.ip),
            _make_default_pkt(self.MAC_DEST, '45.10.0.3', sub2.ip),
        ]

        # Initialize subscriber list in subscriber controller.
        subscriber_ip_table = SubscriberIPTable()
        subscriber_ip_table.entries.extend([
            SubscriberIPTableEntry(sid=SubscriberID(id='IMSI001010000000013')),
            SubscriberIPTableEntry(sid=SubscriberID(id='IMSI001010000000014')),
        ])
        fut = Future()
        fut.set_result(subscriber_ip_table)
        self.subscriber_controller._poll_subscriber_list_done(fut)

        # Verify that after the poll, flows for subscriber 1 and 2 are
        # installed and the second pair of packets sent are matched.
        sub1_query = RyuDirectFlowQuery(
            self._tbl_num,
            self.testing_controller,
            match=MagmaMatch(imsi=encode_imsi('IMSI001010000000013')))
        sub2_query = RyuDirectFlowQuery(
            self._tbl_num,
            self.testing_controller,
            match=MagmaMatch(imsi=encode_imsi('IMSI001010000000014')))
        flow_verifier = FlowVerifier([
            FlowTest(sub1_query, 1, 2),
            FlowTest(sub2_query, 1, 2),
        ], lambda: None)

        # Send packets through pipeline and wait.
        with isolator1, isolator2, flow_verifier:
            # Send packets to create the metering flows. Note that these
            # packets will not be matched because the test setup does not
            # support outputting to port.
            for pkt in packets:
                pkt_sender.send(pkt)
            wait_after_send(self.testing_controller)

            # Update the subscriber list to delete subscriber 2.
            subscriber_ip_table = SubscriberIPTable()
            subscriber_ip_table.entries.extend([
                SubscriberIPTableEntry(sid=SubscriberID(
                    id='IMSI001010000000013')),
            ])
            fut = Future()
            fut.set_result(subscriber_ip_table)
            self.subscriber_controller._poll_subscriber_list_done(fut)

            # Send another pair of packets which will be matched.
            for pkt in packets:
                pkt_sender.send(pkt)
            wait_after_send(self.testing_controller)

            # Temporarily mock out _handle_flow_stats because flow_verifier
            # sends a stats request to the meter table, which will trigger
            # the deletion prematurely.
            handle_flow_stats = self.subscriber_controller._handle_flow_stats
            self.subscriber_controller._handle_flow_stats = MagicMock()

        flow_verifier.verify()
        self.subscriber_controller._handle_flow_stats = handle_flow_stats

        # Verify that after the usage is reported, the flows for subscriber 2
        # are deleted.
        sub1_record = UsageRecord()
        sub1_record.bytes_tx = len(packets[0])
        sub2_record = UsageRecord()
        sub2_record.bytes_tx = len(packets[1])
        target_usage = {
            'IMSI001010000000013': sub1_record,
            'IMSI001010000000014': sub2_record,
        }

        flow_verifier = FlowVerifier([
            FlowTest(sub1_query, 0, 2),
            FlowTest(sub2_query, 0, 0),
        ], lambda: wait_for_meter_stats(self.stats_controller, target_usage))

        with flow_verifier:
            self._poll_stats()

        flow_verifier.verify()
Esempio n. 18
0
    def test_process_deleted_subscriber(self):
        """
        With usage polling off, send packets to install metering flows and
        delete one of them by removing the subscriber from the subscriber ip
        table.

        Verifies that the metering flows for the subscriber is deleted when the
        subscriber is deleted.
        """
        # Set up subscribers
        sub1 = SubContextConfig('IMSI001010000000013', '192.168.128.74',
                                self._tbl_num)
        sub2 = SubContextConfig('IMSI001010000000014', '192.168.128.75',
                                self._tbl_num)

        isolator1 = RyuDirectTableIsolator(
            RyuForwardFlowArgsBuilder.from_subscriber(sub1).build_requests(),
            self.testing_controller,
        )
        isolator2 = RyuDirectTableIsolator(
            RyuForwardFlowArgsBuilder.from_subscriber(sub2).build_requests(),
            self.testing_controller,
        )

        # Set up packets
        pkt_sender = ScapyPacketInjector(self.BRIDGE)
        packets = [
            _make_default_pkt(self.MAC_DEST, '45.10.0.1', sub1.ip),
            _make_default_pkt(self.MAC_DEST, '45.10.0.3', sub2.ip),
        ]

        # Initialize subscriber list in subscriber controller.
        subscriber_ip_table = SubscriberIPTable()
        subscriber_ip_table.entries.extend([
            SubscriberIPTableEntry(sid=SubscriberID(id='IMSI001010000000013')),
            SubscriberIPTableEntry(sid=SubscriberID(id='IMSI001010000000014')),
        ])
        fut = Future()
        fut.set_result(subscriber_ip_table)
        self.subscriber_controller._poll_subscriber_list_done(fut)

        # Verify that after the poll, subscriber 2 flows are deleted while
        # subscriber 1 flows remain.
        sub1_query = RyuDirectFlowQuery(
            self._tbl_num,
            self.testing_controller,
            match=MagmaMatch(imsi=encode_imsi('IMSI001010000000013')))
        sub2_query = RyuDirectFlowQuery(
            self._tbl_num,
            self.testing_controller,
            match=MagmaMatch(imsi=encode_imsi('IMSI001010000000014')))
        flow_verifier = FlowVerifier([
            FlowTest(sub1_query, 0, 2),
            FlowTest(sub2_query, 0, 0),
        ], lambda: None)

        # Send packets through pipeline and wait.
        with isolator1, isolator2, flow_verifier:
            # Send packets to create the metering flows. Note that these
            # packets will not be matched because the test setup does not
            # support outputting to port.
            for pkt in packets:
                pkt_sender.send(pkt)
            wait_after_send(self.testing_controller)

            # Update the subscriber list to delete subscriber 2.
            subscriber_ip_table = SubscriberIPTable()
            subscriber_ip_table.entries.extend([
                SubscriberIPTableEntry(sid=SubscriberID(
                    id='IMSI001010000000013')),
            ])
            fut = Future()
            fut.set_result(subscriber_ip_table)
            self.subscriber_controller._poll_subscriber_list_done(fut)

        flow_verifier.verify()
Esempio n. 19
0
    def test_input_output(self):
        """
        """
        sub1 = SubContextConfig('IMSI001010000088888', '192.168.128.74', 4)
        quota = 1024  # bytes

        # return only rx (downlink) packets
        self.test_util.controller.mock_create_session = Mock(
            return_value=session_manager_pb2.CreateSessionResponse(
                credits=[
                    session_manager_pb2.CreditUpdateResponse(
                        success=True,
                        sid=sub1.imsi,
                        charging_key=1,
                        credit=session_manager_pb2.ChargingCredit(
                            granted_units=session_manager_pb2.GrantedUnits(
                                rx=session_manager_pb2.CreditUnit(
                                    is_valid=True,
                                    volume=quota,
                                ), ), ),
                    )
                ],
                static_rules=[
                    session_manager_pb2.StaticRuleInstall(
                        rule_id="simple_match")
                ],
            ), )

        self.test_util.controller.mock_terminate_session = Mock(
            return_value=session_manager_pb2.SessionTerminateResponse(), )

        update_complete = hub.Queue()
        self.test_util.controller.mock_update_session = Mock(
            side_effect=get_standard_update_response(update_complete,
                                                     None,
                                                     quota,
                                                     is_final=False), )

        self.test_util.sessiond.CreateSession(
            session_manager_pb2.LocalCreateSessionRequest(
                sid=SubscriberID(id=sub1.imsi),
                ue_ipv4=sub1.ip,
            ), )
        self.assertEqual(
            self.test_util.controller.mock_create_session.call_count, 1)

        packets = get_packets_for_flows(
            sub1, self.test_util.static_rules["simple_match"].flow_list)
        packet_count = int(quota / len(packets[0])) + 1

        self.test_util.thread.run_in_greenthread(
            self.test_util.get_packet_sender([sub1], packets, packet_count), )
        self.assertIsNone(get_from_queue(update_complete))
        self.assertEqual(
            self.test_util.controller.mock_update_session.call_count, 0)

        self.test_util.sessiond.EndSession(SubscriberID(id=sub1.imsi))
        self.assertEqual(
            self.test_util.controller.mock_terminate_session.call_count, 1)

        # now attach with tx (uplink packets)
        self.test_util.controller.mock_create_session = Mock(
            return_value=session_manager_pb2.CreateSessionResponse(
                credits=[
                    session_manager_pb2.CreditUpdateResponse(
                        success=True,
                        sid=sub1.imsi,
                        charging_key=1,
                        credit=session_manager_pb2.ChargingCredit(
                            granted_units=session_manager_pb2.GrantedUnits(
                                tx=session_manager_pb2.CreditUnit(
                                    is_valid=True,
                                    volume=quota,
                                ), ), ),
                    )
                ],
                static_rules=[
                    session_manager_pb2.StaticRuleInstall(
                        rule_id="simple_match")
                ],
            ), )
        self.test_util.sessiond.CreateSession(
            session_manager_pb2.LocalCreateSessionRequest(
                sid=SubscriberID(id=sub1.imsi),
                ue_ipv4=sub1.ip,
            ), )
        self.test_util.thread.run_in_greenthread(
            self.test_util.get_packet_sender([sub1], packets, packet_count), )
        self.assertIsNotNone(get_from_queue(update_complete))
        self.assertEqual(
            self.test_util.controller.mock_update_session.call_count, 1)
        self.test_util.sessiond.EndSession(SubscriberID(id=sub1.imsi))
        self.assertEqual(
            self.test_util.controller.mock_terminate_session.call_count, 2)
Esempio n. 20
0
    def test_multiple_subscribers(self):
        """
        Test credit tracking with multiple rules and 32 subscribers, each using
        up their quota and reporting to the OCS
        """
        subs = [
            SubContextConfig(
                'IMSI0010100000888{}'.format(i),
                '192.168.128.{}'.format(i),
                4,
            ) for i in range(32)
        ]
        quota = 1024  # bytes

        # create some rules
        rule1 = create_uplink_rule("rule1", 2, '46.10.0.1')
        rule2 = create_uplink_rule("rule2",
                                   0,
                                   '47.10.0.1',
                                   tracking=PolicyRule.NO_TRACKING)
        rule3 = create_uplink_rule("rule3", 3, '49.10.0.1')
        self.test_util.static_rules["rule1"] = rule1
        self.test_util.static_rules["rule2"] = rule2
        hub.sleep(2)  # wait for policies

        # set up mocks
        self.test_util.controller.mock_create_session = Mock(
            return_value=session_manager_pb2.CreateSessionResponse(
                credits=[
                    create_update_response("", 2, quota),
                    create_update_response("", 3, quota),
                ],
                static_rules=[
                    session_manager_pb2.StaticRuleInstall(rule_id="rule1"),
                    session_manager_pb2.StaticRuleInstall(rule_id="rule2"),
                ],
                dynamic_rules=[
                    session_manager_pb2.DynamicRuleInstall(policy_rule=rule3)
                ],
            ), )
        self.test_util.controller.mock_terminate_session = Mock(
            return_value=session_manager_pb2.SessionTerminateResponse(), )
        update_complete = hub.Queue()
        self.test_util.controller.mock_update_session = Mock(
            side_effect=get_standard_update_response(update_complete,
                                                     None,
                                                     quota,
                                                     is_final=True), )

        # initiate sessions
        for sub in subs:
            self.test_util.sessiond.CreateSession(
                session_manager_pb2.LocalCreateSessionRequest(
                    sid=SubscriberID(id=sub.imsi),
                    ue_ipv4=sub.ip,
                ), )
        self.assertEqual(
            self.test_util.controller.mock_create_session.call_count,
            len(subs))

        # send packets towards all 3 rules
        flows = [rule.flow_list[0] for rule in [rule1, rule2, rule3]]
        packets = []
        for sub in subs:
            packets.extend(get_packets_for_flows(sub, flows))
        packet_count = int(quota / len(packets[0])) + 1
        self.test_util.thread.run_in_greenthread(
            self.test_util.get_packet_sender(subs, packets, packet_count), )

        # wait for responses for keys 2 and 3 (key 1 is not tracked)
        expected_keys = {(sub.imsi, key) for sub in subs for key in [2, 3]}
        for _ in range(len(expected_keys)):
            update = get_from_queue(update_complete)
            self.assertIsNotNone(update)
            imsiKey = (update.sid, update.usage.charging_key)
            self.assertTrue(imsiKey in expected_keys)
            expected_keys.remove(imsiKey)

        for sub in subs:
            self.test_util.sessiond.EndSession(SubscriberID(id=sub.imsi))
        self.assertEqual(
            self.test_util.controller.mock_terminate_session.call_count,
            len(subs))
Esempio n. 21
0
    def test_reauth(self):
        """
        Send a Gx reauth request which installs one new static rule, one new
        dynamic rule, and removes one static and one dynamic rule.
        """
        dynamic_rule1 = create_uplink_rule('dynamic1',
                                           1,
                                           '46.10.10.1',
                                           tracking=PolicyRule.NO_TRACKING)
        dynamic_rule2 = create_uplink_rule('dynamic2',
                                           1,
                                           '46.10.10.2',
                                           tracking=PolicyRule.NO_TRACKING)

        # Initialize sub with 1 static and 1 dynamic rule
        sub = SubContextConfig('IMSI001010000088888', '192.168.128.74',
                               default_ambr_config, 4)
        self.test_util.controller.mock_create_session = Mock(
            return_value=CreateSessionResponse(
                credits=[create_update_response(sub.imsi, 1, 1024)],
                static_rules=[
                    session_manager_pb2.StaticRuleInstall(rule_id='policy1')
                ],
                dynamic_rules=[
                    session_manager_pb2.DynamicRuleInstall(
                        policy_rule=dynamic_rule1)
                ],
                usage_monitors=[],
            ), )
        self.test_util.controller.mock_terminate_session = Mock(
            return_value=SessionTerminateResponse(), )
        self.test_util.sessiond.CreateSession(
            LocalCreateSessionRequest(
                sid=SubscriberID(id=sub.imsi),
                ue_ipv4=sub.ip,
            ))
        self.assertEqual(
            self.test_util.controller.mock_create_session.call_count,
            1,
        )

        # first, send some packets so we know that the uplink rules are
        # accepting traffic
        self._assert_rules(
            sub,
            [
                session_manager_pb2.DynamicRuleInstall(
                    policy_rule=self.test_util.static_rules['policy1']),
                session_manager_pb2.DynamicRuleInstall(
                    policy_rule=dynamic_rule1)
            ],
        )

        # Now via reauth, remove the old rules and install new uplink rules
        # Verify the new uplink rules allow traffic
        reauth_result = self.test_util.proxy_responder.PolicyReAuth(
            PolicyReAuthRequest(
                imsi=sub.imsi,
                rules_to_remove=['dynamic1', 'policy1'],
                rules_to_install=[
                    session_manager_pb2.StaticRuleInstall(rule_id='policy2')
                ],
                dynamic_rules_to_install=[
                    session_manager_pb2.DynamicRuleInstall(
                        policy_rule=dynamic_rule2)
                ],
            ))
        self.assertEqual(
            reauth_result.result,
            session_manager_pb2.UPDATE_INITIATED,
        )
        self.assertEqual(len(reauth_result.failed_rules), 0)
        self._assert_rules(
            sub,
            [
                session_manager_pb2.DynamicRuleInstall(
                    policy_rule=self.test_util.static_rules['policy2']),
                session_manager_pb2.DynamicRuleInstall(
                    policy_rule=dynamic_rule2)
            ],
        )

        # Verify the old rules no longer allow traffic (uninstalled)
        self._assert_rules(
            sub,
            [
                session_manager_pb2.DynamicRuleInstall(
                    policy_rule=self.test_util.static_rules['policy1']),
                session_manager_pb2.DynamicRuleInstall(
                    policy_rule=dynamic_rule1)
            ],
            expected=0,
        )