def test_invalid_subscriber(self):
        """
        Try to apply an invalid policy to a subscriber, should log and error

        Assert:
            Only 1 flow gets added to the table (drop flow)
        """
        fake_controller_setup(self.enforcement_controller)
        imsi = 'IMSI000000000000001'
        sub_ip = '192.168.128.45'
        flow_list = [FlowDescription(
            match=FlowMatch(
                ip_src=convert_ipv4_str_to_ip_proto('9999.0.0.0/24')),
            action=FlowDescription.DENY
        )]
        policy = PolicyRule(id='invalid', priority=2, flow_list=flow_list)
        invalid_sub_context = RyuDirectSubscriberContext(
            imsi, sub_ip, self.enforcement_controller,
            self._tbl_num).add_dynamic_rule(policy)
        isolator = RyuDirectTableIsolator(
            RyuForwardFlowArgsBuilder.from_subscriber(invalid_sub_context.cfg)
                                     .build_requests(),
            self.testing_controller
        )
        flow_query = FlowQuery(self._tbl_num, self.testing_controller)
        num_flows_start = len(flow_query.lookup())
        snapshot_verifier = SnapshotVerifier(self, self.BRIDGE,
                                             self.service_manager)

        with isolator, invalid_sub_context, snapshot_verifier:
            wait_after_send(self.testing_controller)
            num_flows_final = len(flow_query.lookup())

        self.assertEqual(num_flows_final - num_flows_start, 0)
Beispiel #2
0
def wait_after_send(test_controller, wait_time=1, max_sleep_time=20):
    """
    Wait after sending packets, waits until no packets were received by any
    table in ovs. This will send 2 or more table stat requests to ovs.

    Args:
        test_controller (TestingController): testing controller reference
        wait_time (int): wait time between ovs stat queries
        max_sleep_time (int): max wait time, if exceeded return

    Returns when waiting is done

    Throws a WaitTimeExceeded Exception if max_sleep_time exceeded
    """
    sleep_time = 0
    pkt_cnt_old = -1
    while True:
        hub.sleep(wait_time)

        pkt_cnt_new = sum(
            table.matched_count
            for table in RyuDirectFlowQuery.get_table_stats(test_controller))
        if pkt_cnt_new - pkt_cnt_old == 0:
            return
        else:
            pkt_cnt_old = pkt_cnt_new

        sleep_time = sleep_time + wait_time
        if (sleep_time >= max_sleep_time):
            raise WaitTimeExceeded(
                "Waiting on pkts exceeded the max({}) sleep time".format(
                    max_sleep_time))
Beispiel #3
0
 def packet_sender():
     isolators = [
         RyuDirectTableIsolator(
             RyuForwardFlowArgsBuilder.from_subscriber(
                 sub).build_requests(),
             self.testing_controller,
         ) for sub in subs
     ]
     flow_query = FlowQuery(20, self.testing_controller)
     pkt_start = sum(flow.packets for flow in flow_query.lookup())
     with ExitStack() as es:
         for iso in isolators:
             es.enter_context(iso)
         for packet in packets:
             pkt_sender.send(packet, count=count)
         wait_after_send(self.testing_controller)
         pkt_final = sum(flow.packets for flow in flow_query.lookup())
     return pkt_final - pkt_start
Beispiel #4
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()
Beispiel #5
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()