Example #1
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")
Example #2
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)
Example #3
0
    def test_rest_ip_flow(self):
        """
        Sends an ip packet

        Assert:
            The correct ip rule is matched
            No other rule is matched
        """
        isolator = RyuRestTableIsolator(
            RyuForwardFlowArgsBuilder(self.TID).set_reg_value(
                DIRECTION_REG, 0x1).build_requests())
        flow_query = RyuRestFlowQuery(self.TID,
                                      match={
                                          'eth_type': 2048,
                                          DIRECTION_REG: 1
                                      })
        pkt_sender = ScapyPacketInjector(self.IFACE)
        packet = IPPacketBuilder()\
            .set_ether_layer(self.MAC_DEST, "00:00:00:00:00:04")\
            .set_ip_layer(self.IP_DEST, "10.0.0.0")\
            .build()

        num_pkts = 42
        ip_start = flow_query.lookup()[0].packets
        total_start = _pkt_total(RyuRestFlowQuery(self.TID).lookup())

        with isolator:
            pkt_sender.send(packet, num_pkts)
            time.sleep(2.5)

        total_final = _pkt_total(RyuRestFlowQuery(self.TID).lookup())
        ip_final = flow_query.lookup()[0].packets

        self.assertEqual(ip_final - ip_start, num_pkts)
        self.assertEqual(total_final - total_start, num_pkts)
Example #4
0
    def test_redirect_policy(self):
        """
        Add a redirect policy, verifies that EnforcementStatsController reports
        correct stats to sessiond

        Assert:
            1 Packet is matched and reported
        """
        fake_controller_setup(self.enforcement_controller,
                              self.enforcement_stats_controller)
        redirect_ips = ["185.128.101.5", "185.128.121.4"]
        self.enforcement_controller._redirect_manager._dns_cache.get(
            "about.sha.ddih.org", lambda: redirect_ips, max_age=42)
        imsi = 'IMSI010000000088888'
        sub_ip = '192.168.128.74'
        flow_list = [FlowDescription(match=FlowMatch())]
        policy = PolicyRule(id='redir_test',
                            priority=3,
                            flow_list=flow_list,
                            redirect=RedirectInformation(
                                support=1,
                                address_type=2,
                                server_address="http://about.sha.ddih.org/"))
        stat_name = imsi + '|redir_test' + '|' + sub_ip
        self.service_manager.session_rule_version_mapper.update_version(
            imsi, convert_ipv4_str_to_ip_proto(sub_ip), 'redir_test')
        """ Setup subscriber, setup table_isolation to fwd pkts """
        self._static_rule_dict[policy.id] = policy
        sub_context = RyuDirectSubscriberContext(
            imsi, sub_ip, self.enforcement_controller, self._main_tbl_num,
            self.enforcement_stats_controller).add_dynamic_rule(policy)
        isolator = RyuDirectTableIsolator(
            RyuForwardFlowArgsBuilder.from_subscriber(
                sub_context.cfg).build_requests(), self.testing_controller)
        pkt_sender = ScapyPacketInjector(self.IFACE)
        packet = TCPPacketBuilder() \
            .set_tcp_layer(42132, 80, 321) \
            .set_tcp_flags("S") \
            .set_ip_layer('151.42.41.122', sub_ip) \
            .set_ether_layer(self.MAC_DEST, "00:00:00:00:00:00") \
            .build()

        # =========================== Verification ===========================
        snapshot_verifier = SnapshotVerifier(self, self.BRIDGE,
                                             self.service_manager)
        """ Send packet, wait until pkts are received by ovs and enf stats """
        with isolator, sub_context, snapshot_verifier:
            self.enforcement_stats_controller._report_usage.reset_mock()
            pkt_sender.send(packet)

        wait_for_enforcement_stats(self.enforcement_stats_controller,
                                   [stat_name])
        """ Send packets, wait until pkts are received by ovs and enf stats """
        stats = get_enforcement_stats(
            self.enforcement_stats_controller._report_usage.call_args_list)

        self.assertEqual(stats[stat_name].sid, imsi)
        self.assertEqual(stats[stat_name].rule_id, "redir_test")
        self.assertEqual(stats[stat_name].bytes_rx, 0)
        self.assertEqual(stats[stat_name].bytes_tx, len(packet))
Example #5
0
    def test_ue_to_uplink_arp(self):
        """
        Verify that a UE->UPLINK arp request is dropped
        MME would not set IMSI reg
        """
        pkt_sender = ScapyPacketInjector(self.IFACE)
        arp_packet = ARPPacketBuilder() \
            .set_ether_layer(self.OTHER_MAC, self.UE_MAC) \
            .set_arp_layer(self.OTHER_IP) \
            .set_arp_hwdst(self.OTHER_MAC) \
            .set_arp_src(self.UE_MAC, self.UE_IP) \
            .build()

        uplink_args = RyuForwardFlowArgsBuilder(self._tbl_num) \
            .set_eth_match(eth_src=self.UE_MAC, eth_dst=self.OTHER_MAC) \
            .set_reg_value(DIRECTION_REG, Direction.OUT) \
            .build_requests()
        isolator = RyuDirectTableIsolator(uplink_args, self.testing_controller)

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

        with isolator, snapshot_verifier:
            pkt_sender.send(arp_packet, count=4)
            wait_after_send(self.testing_controller)
Example #6
0
    def test_mtr_arp(self):
        """
        Verify that a MTR arp request is handled in ARP responder
        """
        pkt_sender = ScapyPacketInjector(self.IFACE)
        arp_packet = ARPPacketBuilder() \
            .set_ether_layer(self.OTHER_MAC, self.MAC_DEST) \
            .set_arp_layer(self.MTR_IP) \
            .set_arp_hwdst(self.OTHER_MAC) \
            .set_arp_src(self.UE_MAC, self.UE_IP) \
            .build()

        uplink_args = RyuForwardFlowArgsBuilder(self._tbl_num) \
            .set_eth_type_arp() \
            .set_reg_value(DIRECTION_REG, Direction.IN) \
            .build_requests()
        isolator = RyuDirectTableIsolator(uplink_args, self.testing_controller)
        time.sleep(1)
        snapshot_verifier = SnapshotVerifier(
            self,
            self.BRIDGE,
            self.service_manager,
        )

        with isolator, snapshot_verifier:
            pkt_sender.send(arp_packet, count=4)
            wait_after_send(self.testing_controller)
Example #7
0
    def test_stray_arp_drop(self):
        """
        Verify that an arp that neither UE->UPLINK nor UPLINK->UE is dropped
        """
        pkt_sender = ScapyPacketInjector(self.IFACE)
        arp_packet = ARPPacketBuilder() \
            .set_ether_layer('11:11:11:11:11:1', self.OTHER_MAC) \
            .set_arp_layer(self.OTHER_IP) \
            .set_arp_hwdst(self.OTHER_MAC) \
            .set_arp_src('22:22:22:22:22:22', '1.1.1.1') \
            .build()

        uplink_args = RyuForwardFlowArgsBuilder(self._tbl_num) \
            .set_eth_match(eth_dst='11:11:11:11:11:1', eth_src=self.OTHER_MAC) \
            .set_reg_value(DIRECTION_REG, Direction.OUT) \
            .build_requests()
        isolator = RyuDirectTableIsolator(uplink_args, self.testing_controller)

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

        with isolator, snapshot_verifier:
            pkt_sender.send(arp_packet, count=4)
            wait_after_send(self.testing_controller)
Example #8
0
    def test_uplink_to_ue_arp_router_mode(self):
        """
        Verify that a UPLINK->UE arp request with IMSI set is properly matched
        """
        pkt_sender = ScapyPacketInjector(self.IFACE)
        arp_packet = ARPPacketBuilder() \
            .set_ether_layer(self.UE_MAC, self.OTHER_MAC) \
            .set_arp_layer(self.UE_IP) \
            .set_arp_hwdst(self.UE_MAC) \
            .set_arp_src(self.OTHER_MAC, self.OTHER_IP) \
            .build()

        dlink_args = RyuForwardFlowArgsBuilder(self._tbl_num) \
            .set_eth_match(eth_dst=self.UE_MAC, eth_src=self.OTHER_MAC) \
            .set_reg_value(DIRECTION_REG, Direction.IN) \
            .set_reg_value(IMSI_REG, 123) \
            .build_requests()
        isolator = RyuDirectTableIsolator(dlink_args, self.testing_controller)

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

        with isolator, snapshot_verifier:
            pkt_sender.send(arp_packet, count=4)
            wait_after_send(self.testing_controller)

        clean_to_ip_blocks_list()
    def test_deny_rule_install(self):
        """
        Adds a policy to a subscriber. Verifies that flows are properly
        installed in enforcement and enforcement stats.
        Assert:
            Policy classification flows installed in enforcement
            Policy match flows installed in enforcement_stats
        """
        fake_controller_setup(self.enforcement_controller,
                              self.enforcement_stats_controller)
        imsi = 'IMSI001010000000014'
        sub_ip = '192.16.15.7'
        num_pkt_unmatched = 4096

        flow_list = [
            FlowDescription(match=FlowMatch(
                ip_dst=convert_ipv4_str_to_ip_proto('1.1.0.0/24'),
                direction=FlowMatch.UPLINK),
                            action=FlowDescription.DENY)
        ]
        policy = PolicyRule(id='rule1', priority=3, flow_list=flow_list)
        self.service_manager.session_rule_version_mapper.update_version(
            imsi, convert_ipv4_str_to_ip_proto(sub_ip), 'rule1')
        """ Setup subscriber, setup table_isolation to fwd pkts """
        sub_context = RyuDirectSubscriberContext(
            imsi, sub_ip, self.enforcement_controller, self._main_tbl_num,
            self.enforcement_stats_controller).add_dynamic_rule(policy)

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

        pkt_sender = ScapyPacketInjector(self.IFACE)
        packet = IPPacketBuilder() \
            .set_ip_layer('45.10.0.0/20', sub_ip) \
            .set_ether_layer(self.MAC_DEST, "00:00:00:00:00:00") \
            .build()

        # =========================== Verification ===========================

        # Verifies that 1 flow is installed in enforcement and 2 flows are
        # installed in enforcement stats, one for uplink and one for downlink.
        snapshot_verifier = SnapshotVerifier(self, self.BRIDGE,
                                             self.service_manager)

        with isolator, sub_context, snapshot_verifier:
            pkt_sender.send(packet)

        enf_stat_name = imsi + '|' + self.DEFAULT_DROP_FLOW_NAME + '|' + sub_ip
        wait_for_enforcement_stats(self.enforcement_stats_controller,
                                   [enf_stat_name])
        stats = get_enforcement_stats(
            self.enforcement_stats_controller._report_usage.call_args_list)

        self.assertEqual(stats[enf_stat_name].sid, imsi)
        self.assertEqual(stats[enf_stat_name].rule_id,
                         self.DEFAULT_DROP_FLOW_NAME)
        self.assertEqual(stats[enf_stat_name].dropped_rx, 0)
        self.assertEqual(stats[enf_stat_name].dropped_tx,
                         num_pkt_unmatched * len(packet))
Example #10
0
    def test_subscriber_restrict_policy(self):
        """
        Add restrict policy to subscriber, send 4096 packets

        Assert:
            Packets are properly matched with the 'restrict_match' policy
            Send /20 (4096) packets, match /16 (256) packets
        """
        fake_controller_setup(self.gy_controller)
        imsi = 'IMSI010000000088888'
        sub_ip = '192.168.128.74'
        flow_list1 = [
            FlowDescription(match=FlowMatch(
                ip_dst=convert_ipv4_str_to_ip_proto('8.8.8.0/24'),
                direction=FlowMatch.UPLINK),
                            action=FlowDescription.PERMIT)
        ]
        policies = [
            VersionedPolicy(
                rule=PolicyRule(id='restrict_match',
                                priority=2,
                                flow_list=flow_list1),
                version=1,
            )
        ]
        pkts_matched = 256
        pkts_sent = 4096

        # ============================ Subscriber ============================
        sub_context = RyuDirectSubscriberContext(
            imsi, sub_ip, self.gy_controller,
            self._tbl_num).add_policy(policies[0])
        isolator = RyuDirectTableIsolator(
            RyuForwardFlowArgsBuilder.from_subscriber(
                sub_context.cfg).build_requests(), self.testing_controller)
        pkt_sender = ScapyPacketInjector(self.IFACE)
        packet = IPPacketBuilder()\
            .set_ip_layer('8.8.8.8', sub_ip)\
            .set_ether_layer(self.MAC_DEST, "00:00:00:00:00:00")\
            .build()
        flow_query = FlowQuery(self._tbl_num,
                               self.testing_controller,
                               match=flow_match_to_magma_match(
                                   flow_list1[0].match))

        # =========================== Verification ===========================
        # Verify aggregate table stats, subscriber 1 'simple_match' pkt count
        flow_verifier = FlowVerifier([
            FlowTest(FlowQuery(self._tbl_num, self.testing_controller),
                     pkts_sent),
            FlowTest(flow_query, pkts_matched)
        ], lambda: wait_after_send(self.testing_controller))
        snapshot_verifier = SnapshotVerifier(self,
                                             self.BRIDGE,
                                             self.service_manager,
                                             include_stats=False)

        with isolator, sub_context, flow_verifier, snapshot_verifier:
            pkt_sender.send(packet)
Example #11
0
    def test_add_two_subscribers(self):
        """
           Add UE MAC flows for two subscribers
        """
        imsi_1 = 'IMSI010000000088888'
        imsi_2 = 'IMSI010000000099999'
        other_mac = '5e:cc:cc:b1:aa:aa'

        # Add subscriber with UE MAC address """
        self.ue_mac_controller.add_ue_mac_flow(imsi_1, self.UE_MAC_1)
        self.ue_mac_controller.add_ue_mac_flow(imsi_2, self.UE_MAC_2)

        # Create a set of packets
        pkt_sender = ScapyPacketInjector(self.BRIDGE)

        # Only send downlink as the pkt_sender sends pkts from in_port=LOCAL
        downlink_packet1 = EtherPacketBuilder() \
            .set_ether_layer(self.UE_MAC_1, other_mac) \
            .build()
        downlink_packet2 = EtherPacketBuilder() \
            .set_ether_layer(self.UE_MAC_2, other_mac) \
            .build()

        # Check if these flows were added (queries should return flows)
        flow_queries = [
            FlowQuery(
                self._tbl_num,
                self.testing_controller,
                match=MagmaMatch(eth_dst=self.UE_MAC_1),
            ),
            FlowQuery(
                self._tbl_num,
                self.testing_controller,
                match=MagmaMatch(eth_dst=self.UE_MAC_2),
            ),
        ]

        # =========================== Verification ===========================
        # Verify 5 flows installed and 2 total pkts matched (one for each UE)
        flow_verifier = FlowVerifier(
            [
                FlowTest(FlowQuery(self._tbl_num, self.testing_controller), 2,
                         5)
            ] + [FlowTest(query, 1, 1) for query in flow_queries],
            lambda: wait_after_send(self.testing_controller),
        )

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

        with flow_verifier, snapshot_verifier:
            pkt_sender.send(downlink_packet1)
            pkt_sender.send(downlink_packet2)

        flow_verifier.verify()
Example #12
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)
Example #13
0
    def test_subscriber_ipv6_policy(self):
        """
        Add policy to subscriber, send 4096 packets

        Assert:
            Packets are properly matched with the 'simple_match' policy
            Send /20 (4096) packets, match /16 (256) packets
        """
        fake_controller_setup(self.enforcement_controller)
        imsi = 'IMSI010000000088888'
        sub_ip = 'de34:431d:1bc::'
        flow_list1 = [
            FlowDescription(
                match=FlowMatch(
                    ip_dst=convert_ipv6_bytes_to_ip_proto(
                        'f333:432::dbca'.encode('utf-8'), ),
                    direction=FlowMatch.UPLINK,
                ),
                action=FlowDescription.PERMIT,
            ),
        ]
        policies = [
            VersionedPolicy(
                rule=PolicyRule(id='simple_match',
                                priority=2,
                                flow_list=flow_list1),
                version=1,
            ),
        ]

        # ============================ Subscriber ============================
        sub_context = RyuDirectSubscriberContext(
            imsi,
            sub_ip,
            self.enforcement_controller,
            self._tbl_num,
        ).add_policy(policies[0])
        isolator = RyuDirectTableIsolator(
            RyuForwardFlowArgsBuilder.from_subscriber(
                sub_context.cfg).build_requests(),
            self.testing_controller,
        )
        pkt_sender = ScapyPacketInjector(self.IFACE)
        packet = IPv6PacketBuilder() \
            .set_ip_layer('f333:432::dbca', sub_ip) \
            .set_ether_layer(self.MAC_DEST, "00:00:00:00:00:00") \
            .build()

        # =========================== Verification ===========================
        snapshot_verifier = SnapshotVerifier(
            self,
            self.BRIDGE,
            self.service_manager,
        )

        with isolator, sub_context, snapshot_verifier:
            pkt_sender.send(packet)
Example #14
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)
Example #15
0
    def test_subscriber_policy(self):
        """
        Add policy to subscriber, send 4096 packets

        Assert:
            Packets are properly matched with the 'simple_match' policy
            Send /20 (4096) packets, match /16 (256) packets
        """
        imsi = 'IMSI010000000088888'
        sub_ip = '192.168.128.74'
        flow_list1 = [FlowDescription(
            match=FlowMatch(
                ipv4_dst='45.10.0.0/24', direction=FlowMatch.UPLINK),
            action=FlowDescription.PERMIT)
        ]
        policies = [
            PolicyRule(id='simple_match', priority=2, flow_list=flow_list1)
        ]
        pkts_matched = 256
        pkts_sent = 4096

        self._static_rule_dict[policies[0].id] = policies[0]

        # ============================ Subscriber ============================
        sub_context = RyuDirectSubscriberContext(
            imsi, sub_ip, self.enforcement_controller, self._tbl_num
        ).add_static_rule(policies[0].id)
        isolator = RyuDirectTableIsolator(
            RyuForwardFlowArgsBuilder.from_subscriber(sub_context.cfg)
                                     .build_requests(),
            self.testing_controller
        )
        pkt_sender = ScapyPacketInjector(self.IFACE)
        packet = IPPacketBuilder()\
            .set_ip_layer('45.10.0.0/20', sub_ip)\
            .set_ether_layer(self.MAC_DEST, "00:00:00:00:00:00")\
            .build()
        flow_query = FlowQuery(
            self._tbl_num, self.testing_controller,
            match=flow_match_to_magma_match(flow_list1[0].match)
        )

        # =========================== Verification ===========================
        # Verify aggregate table stats, subscriber 1 'simple_match' pkt count
        flow_verifier = FlowVerifier([
            FlowTest(FlowQuery(self._tbl_num, self.testing_controller),
                     pkts_sent),
            FlowTest(flow_query, pkts_matched)
        ], lambda: wait_after_send(self.testing_controller))

        with isolator, sub_context, flow_verifier:
            pkt_sender.send(packet)

        flow_verifier.verify()
Example #16
0
    def test_subscriber_redirect_policy(self):
        """
        Add redirect policy to subscriber, send 4096 packets

        Assert:
            Packets are properly matched with the 'simple_match' policy
            Send /20 (4096) packets, match /16 (256) packets
        """
        fake_controller_setup(self.gy_controller)
        imsi = 'IMSI010000000088888'
        sub_ip = '192.168.128.74'
        redirect_ips = ["185.128.101.5", "185.128.121.4"]
        self.gy_controller._redirect_manager._dns_cache.get(
            "about.sha.ddih.org", lambda: redirect_ips, max_age=42,
        )
        flow_list = [FlowDescription(match=FlowMatch())]
        policy = VersionedPolicy(
            rule=PolicyRule(
                id='redir_test', priority=3, flow_list=flow_list,
                redirect=RedirectInformation(
                    support=1,
                    address_type=2,
                    server_address="http://about.sha.ddih.org/",
                ),
            ),
            version=1,
        )

        # ============================ Subscriber ============================
        sub_context = RyuDirectSubscriberContext(
            imsi, sub_ip, self.gy_controller, self._tbl_num,
        ).add_policy(policy)
        isolator = RyuDirectTableIsolator(
            RyuForwardFlowArgsBuilder.from_subscriber(sub_context.cfg)
                                     .build_requests(),
            self.testing_controller,
        )
        pkt_sender = ScapyPacketInjector(self.IFACE)
        packet = TCPPacketBuilder()\
            .set_tcp_layer(42132, 80, 2)\
            .set_tcp_flags("S")\
            .set_ip_layer('151.42.41.122', sub_ip)\
            .set_ether_layer(self.MAC_DEST, "01:20:10:20:aa:bb")\
            .build()

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

        with isolator, sub_context, snapshot_verifier:
            pkt_sender.send(packet)
Example #17
0
    def test_traffic_paging_flow(self):
        """
           Add paging flow in table 0
        """
        # Need to delete all default flows in table 0 before
        # install the specific flows test case.
        self.classifier_controller._delete_all_flows()

        ue_ip_addr = "192.168.128.30"
        self.classifier_controller.install_paging_flow(
            IPAddress(version=IPAddress.IPV4,
                      address=ue_ip_addr.encode('utf-8')), 200, True)
        # Create a set of packets
        pkt_sender = ScapyPacketInjector(self.BRIDGE)
        eth = Ether(dst=self.MAC_1, src=self.MAC_2)
        ip = IP(src=self.Dst_nat, dst='192.168.128.30')
        o_udp = UDP(sport=2152, dport=2152)
        i_udp = UDP(sport=1111, dport=2222)
        i_tcp = TCP(seq=1, sport=1111, dport=2222)
        i_ip = IP(src='192.168.60.142', dst=self.EnodeB_IP)

        gtp_packet_udp = eth / ip / o_udp / GTP_U_Header(
            teid=0x1, length=28, gtp_type=255) / i_ip / i_udp
        gtp_packet_tcp = eth / ip / o_udp / GTP_U_Header(
            teid=0x1, length=68, gtp_type=255) / i_ip / i_tcp

        # Check if these flows were added (queries should return flows)
        flow_queries = [
            FlowQuery(self._tbl_num,
                      self.testing_controller,
                      match=MagmaMatch(tunnel_id=1, in_port=32768)),
            FlowQuery(self._tbl_num,
                      self.testing_controller,
                      match=MagmaMatch(ipv4_dst='192.168.128.30'))
        ]
        # =========================== Verification ===========================
        # Verify 2 flows installed for classifier table (2 pkts matched)

        flow_verifier = FlowVerifier([
            FlowTest(FlowQuery(self._tbl_num, self.testing_controller), 2, 2),
        ], lambda: wait_after_send(self.testing_controller))

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

        with flow_verifier, snapshot_verifier:
            pkt_sender.send(gtp_packet_udp)
            pkt_sender.send(gtp_packet_tcp)

        flow_verifier.verify()
Example #18
0
    def test_ipv6_flows(self):
        """
        Verify that a UPLINK->UE arp request is properly matched
        """
        ll_addr = get_if_hwaddr('testing_br')

        pkt_sender = ScapyPacketInjector(self.IFACE)

        pkt_rs = Ether(dst=self.OTHER_MAC, src=self.UE_MAC)
        pkt_rs /= IPv6(
            src='fe80:24c3:d0ff:fef3:9d21:4407:d337:1928',
            dst='ff02::2',
        )
        pkt_rs /= ICMPv6ND_RS()
        pkt_rs /= ICMPv6NDOptSrcLLAddr(lladdr=ll_addr)

        pkt_ns = Ether(dst=self.OTHER_MAC, src=self.UE_MAC)
        pkt_ns /= IPv6(
            src='fe80::9d21:4407:d337:1928',
            dst='ff02::2',
        )
        pkt_ns /= ICMPv6ND_NS(tgt='abcd:87:3::')
        pkt_ns /= ICMPv6NDOptSrcLLAddr(lladdr=ll_addr)

        ipv6_addr = 'ab22:5:6c:9:9d21:4407:d337:1928'
        interface = get_ipv6_interface_id(ipv6_addr)
        prefix = get_ipv6_prefix(ipv6_addr)
        self.service_manager.interface_to_prefix_mapper.save_prefix(
            interface,
            prefix,
        )

        ulink_args = RyuForwardFlowArgsBuilder(self._tbl_num) \
            .set_eth_match(eth_dst=self.OTHER_MAC, eth_src=self.UE_MAC) \
            .set_reg_value(DIRECTION_REG, Direction.OUT) \
            .build_requests()
        isolator = RyuDirectTableIsolator(ulink_args, self.testing_controller)

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

        with isolator, snapshot_verifier:
            pkt_sender.send(pkt_rs)
            pkt_sender.send(pkt_ns)
            wait_after_send(self.testing_controller, wait_time=5)
Example #19
0
    def get_packet_sender(self, subs, packets, count):
        """
        Return a function to call within a greenthread to send packets and
        return the number of packets that went through table 20 (i.e. didn't
        get dropped)
        Args:
            subs ([SubscriberContext]): list of subscribers that may receive
                packets
            packets ([ScapyPacket]): list of packets to send
            count (int): how many of each packet to send
        """
        pkt_sender = ScapyPacketInjector(self.IFACE)

        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

        return packet_sender
Example #20
0
    def test_passthrough_rules(self):
        """
           Add UE MAC flows for two subscribers
        """
        imsi_1 = 'IMSI010000000088888'
        other_mac = '5e:cc:cc:b1:aa:aa'

        # Add subscriber with UE MAC address """
        self.ue_mac_controller.add_ue_mac_flow(imsi_1, self.UE_MAC_1)

        # Create a set of packets
        pkt_sender = ScapyPacketInjector(self.BRIDGE)

        # Only send downlink as the pkt_sender sends pkts from in_port=LOCAL
        downlink_packet1 = EtherPacketBuilder() \
            .set_ether_layer(self.UE_MAC_1, other_mac) \
            .build()
        dhcp_packet = UDPPacketBuilder() \
            .set_ether_layer(self.UE_MAC_1, other_mac) \
            .set_ip_layer('151.42.41.122', '1.1.1.1') \
            .set_udp_layer(67, 68) \
            .build()
        dns_packet = UDPPacketBuilder() \
            .set_ether_layer(self.UE_MAC_1, other_mac) \
            .set_ip_layer('151.42.41.122', '1.1.1.1') \
            .set_udp_layer(53, 32795) \
            .build()

        # Check if these flows were added (queries should return flows)
        flow_queries = [
            FlowQuery(self._tbl_num,
                      self.testing_controller,
                      match=MagmaMatch(eth_dst=self.UE_MAC_1))
        ]

        # =========================== Verification ===========================
        # Verify 8 flows installed for ue_mac table (3 pkts matched)
        #        4 flows installed for inout (3 pkts matched)
        #        2 fliws installed (2 pkts matches)
        flow_verifier = FlowVerifier([
            FlowTest(FlowQuery(self._tbl_num, self.testing_controller), 3, 8),
            FlowTest(FlowQuery(self._ingress_tbl_num, self.testing_controller),
                     3, 4),
            FlowTest(FlowQuery(self._egress_tbl_num, self.testing_controller),
                     2, 2),
            FlowTest(flow_queries[0], 3, 4),
        ], lambda: wait_after_send(self.testing_controller))

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

        with flow_verifier, snapshot_verifier:
            pkt_sender.send(downlink_packet1)
            pkt_sender.send(dhcp_packet)
            pkt_sender.send(dns_packet)

        flow_verifier.verify()
Example #21
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,
        )
Example #22
0
    def test_traffic_flows(self):
        """
           Attach the tunnel flows with UE IP address and
           send GTP and ARP traffic.
        """
        # Need to delete all default flows in table 0 before
        # install the specific flows test case.
        self.test_detach_default_tunnel_flows()

        # Attach the tunnel flows towards UE.
        seid1 = 5000
        self.classifier_controller.add_tunnel_flows(65525, 1, 1000,
                                                    "192.168.128.30",
                                                    self.EnodeB_IP, seid1)
        # Create a set of packets
        pkt_sender = ScapyPacketInjector(self.BRIDGE)
        eth = Ether(dst=self.MAC_1, src=self.MAC_2)
        ip = IP(src=self.Dst_nat, dst='192.168.128.30')
        o_udp = UDP(sport=2152, dport=2152)
        i_udp = UDP(sport=1111, dport=2222)
        i_tcp = TCP(seq=1, sport=1111, dport=2222)
        i_ip = IP(src='192.168.60.142', dst=self.EnodeB_IP)

        arp = ARP(hwdst=self.MAC_1,
                  hwsrc=self.MAC_2,
                  psrc=self.Dst_nat,
                  pdst='192.168.128.30')

        gtp_packet_udp = eth / ip / o_udp / GTP_U_Header(
            teid=0x1, length=28, gtp_type=255) / i_ip / i_udp
        gtp_packet_tcp = eth / ip / o_udp / GTP_U_Header(
            teid=0x1, length=68, gtp_type=255) / i_ip / i_tcp
        arp_packet = eth / arp

        # Check if these flows were added (queries should return flows)
        flow_queries = [
            FlowQuery(self._tbl_num,
                      self.testing_controller,
                      match=MagmaMatch(tunnel_id=1, in_port=32768)),
            FlowQuery(self._tbl_num,
                      self.testing_controller,
                      match=MagmaMatch(ipv4_dst='192.168.128.30'))
        ]
        # =========================== Verification ===========================
        # Verify 5 flows installed for classifier table (3 pkts matched)

        flow_verifier = FlowVerifier([
            FlowTest(FlowQuery(self._tbl_num, self.testing_controller), 3, 5),
            FlowTest(flow_queries[0], 0, 1),
        ], lambda: wait_after_send(self.testing_controller))

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

        with flow_verifier, snapshot_verifier:
            pkt_sender.send(gtp_packet_udp)
            pkt_sender.send(gtp_packet_tcp)
            pkt_sender.send(arp_packet)

        flow_verifier.verify()
Example #23
0
    def test_rest_arp_flow(self):
        """
        Sends an arp request to the ARP table

        Assert:
            The arp rule is matched 2 times for each arp packet
            No other rule is matched
        """
        isolator = RyuRestTableIsolator(
            RyuForwardFlowArgsBuilder(self.TID).set_reg_value(DIRECTION_REG,
                                                              0x10)
                                               .build_requests()
        )
        flow_query = RyuRestFlowQuery(
            self.TID,
            match={
                'eth_type': 2054,
                DIRECTION_REG: 16,
                'arp_tpa': self.IP_DEST + '/255.255.255.0'
            }
        )
        pkt_sender = ScapyPacketInjector(self.IFACE)
        packets = ARPPacketBuilder().set_arp_layer(self.IP_DEST + "/28")\
                                    .build()

        # 16 as the bitmask was /28
        num_pkts = 16
        arp_start = flow_query.lookup()[0].packets
        total_start = _pkt_total(RyuRestFlowQuery(self.TID).lookup())

        with isolator:
            pkt_sender.get_response(packets)
            time.sleep(2.5)

        arp_final = flow_query.lookup()[0].packets
        total_final = _pkt_total(RyuRestFlowQuery(self.TID).lookup())

        self.assertEqual(arp_final - arp_start, num_pkts * 2)
        self.assertEqual(total_final - total_start, num_pkts * 2)
Example #24
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)
Example #25
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
        """
        sub = self._setup_subscribers_ipv6()

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

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

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

        assert_bridge_snapshot_match(
            self,
            self.BRIDGE,
            self.service_manager,
            ipv6_prefix_only=True,
        )
Example #26
0
    def test_delete_one_subscriber(self):
        """
            Delete one of the existing subscribers
        """

        imsi_1 = 'IMSI010000000088888'
        other_mac = '5e:cc:cc:b1:aa:aa'

        # Delete subscriber with UE MAC_1 address
        self.ue_mac_controller.delete_ue_mac_flow(imsi_1, self.UE_MAC_1)

        # Create a set of packets
        pkt_sender = ScapyPacketInjector(self.BRIDGE)

        # Only send downlink as the pkt_sender sends pkts from in_port=LOCAL
        removed_ue_packet = EtherPacketBuilder() \
            .set_ether_layer(self.UE_MAC_1, other_mac) \
            .build()
        remaining_ue_packet = EtherPacketBuilder() \
            .set_ether_layer(self.UE_MAC_2, other_mac) \
            .build()

        # Ensure the first query doesn't match anything
        # And the second query still does
        flow_queries = [
            FlowQuery(self._tbl_num,
                      self.testing_controller,
                      match=MagmaMatch(eth_dst=self.UE_MAC_1)),
            FlowQuery(self._tbl_num,
                      self.testing_controller,
                      match=MagmaMatch(eth_dst=self.UE_MAC_2))
        ]

        # =========================== Verification ===========================
        # Verify 9 flows installed and 1 total pkt matched
        flow_verifier = FlowVerifier([
            FlowTest(FlowQuery(self._tbl_num, self.testing_controller), 1, 9),
            FlowTest(flow_queries[0], 0, 0),
            FlowTest(flow_queries[1], 1, 4),
        ], lambda: wait_after_send(self.testing_controller))

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

        with flow_verifier, snapshot_verifier:
            pkt_sender.send(removed_ue_packet)
            pkt_sender.send(remaining_ue_packet)

        flow_verifier.verify()
Example #27
0
    def test_rule_reactivation(self):
        """
        Adds a policy to a subscriber, deletes it by incrementing the
        version, and add it back. Verifies that the usage stats is correctly
        reported, the old flows are deleted, and the new flows are installed.

        Assert:
            UPLINK policy matches 128 packets (*34 = 4352 bytes)
            Old flows are deleted
            New flows are installed
            No other stats are reported
        """
        fake_controller_setup(self.enforcement_controller,
                              self.enforcement_stats_controller)
        imsi = 'IMSI001010000000013'
        sub_ip = '192.168.128.74'
        num_pkts_tx_match = 128

        flow_list = [
            FlowDescription(match=FlowMatch(ipv4_dst='45.10.0.0/25',
                                            direction=FlowMatch.UPLINK),
                            action=FlowDescription.PERMIT)
        ]
        policy = PolicyRule(id='rule1', priority=3, flow_list=flow_list)
        enf_stat_name = imsi + '|rule1'
        self.service_manager.session_rule_version_mapper.update_version(
            imsi, 'rule1')
        version = \
            self.service_manager.session_rule_version_mapper.get_version(
                imsi, 'rule1')
        """ Setup subscriber, setup table_isolation to fwd pkts """
        self._static_rule_dict[policy.id] = policy
        sub_context = RyuDirectSubscriberContext(
            imsi, sub_ip, self.enforcement_controller, self._main_tbl_num,
            self.enforcement_stats_controller).add_static_rule(policy.id)
        isolator = RyuDirectTableIsolator(
            RyuForwardFlowArgsBuilder.from_subscriber(
                sub_context.cfg).build_requests(), self.testing_controller)
        """ Create a packet """
        pkt_sender = ScapyPacketInjector(self.IFACE)
        packet = IPPacketBuilder() \
            .set_ip_layer('45.10.0.0/20', sub_ip) \
            .set_ether_layer(self.MAC_DEST, "00:00:00:00:00:00") \
            .build()

        # =========================== Verification ===========================
        rule_num = self.enforcement_stats_controller._rule_mapper \
            .get_or_create_rule_num(policy.id)
        enf_query = FlowQuery(self._main_tbl_num,
                              self.testing_controller,
                              match=flow_match_to_magma_match(
                                  FlowMatch(ipv4_dst='45.10.0.0/25',
                                            direction=FlowMatch.UPLINK)),
                              cookie=rule_num)
        es_old_version_query = FlowQuery(self._scratch_tbl_num,
                                         self.testing_controller,
                                         match=MagmaMatch(
                                             imsi=encode_imsi(imsi),
                                             reg2=rule_num,
                                             rule_version=version),
                                         cookie=rule_num)
        es_new_version_query = FlowQuery(self._scratch_tbl_num,
                                         self.testing_controller,
                                         match=MagmaMatch(
                                             imsi=encode_imsi(imsi),
                                             reg2=rule_num,
                                             rule_version=version + 1),
                                         cookie=rule_num)
        packet_wait = FlowVerifier([], self._wait_func([enf_stat_name]))
        """ Verify that flows are properly deleted """
        verifier = FlowVerifier([
            FlowTest(es_old_version_query, 0, flow_count=0),
            FlowTest(es_new_version_query, num_pkts_tx_match, flow_count=2),
            FlowTest(enf_query, num_pkts_tx_match, flow_count=1),
        ], self._wait_func([enf_stat_name]))
        snapshot_verifier = SnapshotVerifier(self, self.BRIDGE,
                                             self.service_manager)
        """
        Send a packet, then deactivate and reactivate the same rule and send a
        packet. Wait until it is received by ovs and enf stats.
        """
        with isolator, sub_context, verifier, snapshot_verifier:
            with packet_wait:
                self.enforcement_stats_controller._report_usage.reset_mock()
                pkt_sender.send(packet)

            self.enforcement_stats_controller._report_usage.reset_mock()
            self.service_manager.session_rule_version_mapper. \
                update_version(imsi, 'rule1')
            self.enforcement_controller.deactivate_rules(imsi, [policy.id])
            self.enforcement_controller.activate_rules(imsi, sub_ip,
                                                       [policy.id], [])
            self.enforcement_stats_controller.activate_rules(
                imsi, sub_ip, [policy.id], [])
            pkt_sender.send(packet)

        verifier.verify()

        stats = get_enforcement_stats(
            self.enforcement_stats_controller._report_usage.call_args_list)
        """
        Verify both packets are reported after reactivation.
        """
        self.assertEqual(stats[enf_stat_name].sid, imsi)
        self.assertEqual(stats[enf_stat_name].rule_id, "rule1")
        self.assertEqual(stats[enf_stat_name].bytes_rx, 0)
        # TODO Figure out why this one fails.
        #self.assertEqual(stats[enf_stat_name].bytes_tx,
        #                 num_pkts_tx_match * len(packet))
        self.assertEqual(len(stats), 1)
Example #28
0
    def test_two_subscribers(self):
        """
        Add 2 subscribers at the same time

        Assert:
            For subcriber1 the packets are matched to the proper policy
            For subcriber2 the packets are matched to the proper policy
            The total packet delta in the table is from the above matches
        """
        fake_controller_setup(self.enforcement_controller)
        pkt_sender = ScapyPacketInjector(self.IFACE)
        ip_match = [
            FlowDescription(match=FlowMatch(
                ip_src=convert_ipv4_str_to_ip_proto('8.8.8.0/24'),
                direction=1),
                            action=1)
        ]
        tcp_match = [
            FlowDescription(match=FlowMatch(ip_proto=6,
                                            direction=FlowMatch.DOWNLINK),
                            action=FlowDescription.DENY)
        ]

        self._static_rule_dict['t'] = PolicyRule(id='t',
                                                 priority=2,
                                                 flow_list=ip_match)

        # =========================== Subscriber 1 ===========================
        sub_context1 = RyuDirectSubscriberContext(
            'IMSI208950001111111', '192.168.128.5',
            self.enforcement_controller, self._tbl_num).add_static_rule('t')
        isolator1 = RyuDirectTableIsolator(
            RyuForwardFlowArgsBuilder.from_subscriber(
                sub_context1.cfg).build_requests(), self.testing_controller)
        packet_ip = IPPacketBuilder()\
            .set_ether_layer(self.MAC_DEST, "00:00:00:00:00:00")\
            .set_ip_layer(sub_context1.cfg.ip, '8.8.8.8')\
            .build()
        s1_pkts_sent = 29
        pkts_to_send = [PktsToSend(packet_ip, s1_pkts_sent)]
        flow_query1 = FlowQuery(self._tbl_num,
                                self.testing_controller,
                                match=flow_match_to_magma_match(
                                    ip_match[0].match))
        s1 = SubTest(sub_context1, isolator1,
                     FlowTest(flow_query1, s1_pkts_sent))

        # =========================== Subscriber 2 ===========================
        sub_context2 = RyuDirectSubscriberContext(
            'IMSI911500451242001', '192.168.128.100',
            self.enforcement_controller, self._tbl_num).add_dynamic_rule(
                PolicyRule(id='qqq', priority=2, flow_list=tcp_match))
        isolator2 = RyuDirectTableIsolator(
            RyuForwardFlowArgsBuilder.from_subscriber(
                sub_context2.cfg).build_requests(), self.testing_controller)
        packet_tcp = TCPPacketBuilder()\
            .set_ether_layer(self.MAC_DEST, "00:00:00:00:00:00")\
            .set_ip_layer(sub_context2.cfg.ip, '15.0.0.8')\
            .build()
        s2_pkts_sent = 18
        pkts_to_send.append(PktsToSend(packet_tcp, s2_pkts_sent))
        flow_query2 = FlowQuery(self._tbl_num,
                                self.testing_controller,
                                match=flow_match_to_magma_match(
                                    tcp_match[0].match))
        s2 = SubTest(sub_context2, isolator2,
                     FlowTest(flow_query2, s2_pkts_sent))

        # =========================== Verification ===========================
        # Verify aggregate table stats, subscriber 1 & 2 flows packet matches
        pkts = s1_pkts_sent + s2_pkts_sent
        flow_verifier = FlowVerifier([
            FlowTest(FlowQuery(self._tbl_num, self.testing_controller), pkts),
            s1.flowtest_list, s2.flowtest_list
        ], lambda: wait_after_send(self.testing_controller))
        snapshot_verifier = SnapshotVerifier(self, self.BRIDGE,
                                             self.service_manager)

        with s1.isolator, s1.context, s2.isolator, s2.context, flow_verifier, \
             snapshot_verifier:
            for pkt in pkts_to_send:
                pkt_sender.send(pkt.pkt, pkt.num)

        flow_verifier.verify()
Example #29
0
    def test_subscriber_policy(self):
        """
        Adds 2 policies to subscriber, verifies that EnforcementStatsController
        reports correct stats to sessiond

        Assert:
            UPLINK policy matches 128 packets (*34 = 4352 bytes)
            DOWNLINK policy matches 256 packets (*34 = 8704 bytes)
            No other stats are reported
        """
        fake_controller_setup(self.enforcement_controller,
                              self.enforcement_stats_controller)
        imsi = 'IMSI001010000000013'
        sub_ip = '192.168.128.74'
        num_pkts_tx_match = 128
        num_pkts_rx_match = 256
        """ Create 2 policy rules for the subscriber """
        flow_list1 = [
            FlowDescription(match=FlowMatch(ipv4_dst='45.10.0.0/25',
                                            direction=FlowMatch.UPLINK),
                            action=FlowDescription.PERMIT)
        ]
        flow_list2 = [
            FlowDescription(match=FlowMatch(ipv4_src='45.10.0.0/24',
                                            direction=FlowMatch.DOWNLINK),
                            action=FlowDescription.PERMIT)
        ]
        policies = [
            PolicyRule(id='tx_match', priority=3, flow_list=flow_list1),
            PolicyRule(id='rx_match', priority=5, flow_list=flow_list2)
        ]
        enf_stat_name = [imsi + '|tx_match', imsi + '|rx_match']
        self.service_manager.session_rule_version_mapper.update_version(
            imsi, 'tx_match')
        self.service_manager.session_rule_version_mapper.update_version(
            imsi, 'rx_match')
        """ Setup subscriber, setup table_isolation to fwd pkts """
        self._static_rule_dict[policies[0].id] = policies[0]
        self._static_rule_dict[policies[1].id] = policies[1]
        sub_context = RyuDirectSubscriberContext(
            imsi, sub_ip, self.enforcement_controller, self._main_tbl_num,
            self.enforcement_stats_controller).add_static_rule(
                policies[0].id).add_static_rule(policies[1].id)
        isolator = RyuDirectTableIsolator(
            RyuForwardFlowArgsBuilder.from_subscriber(
                sub_context.cfg).build_requests(), self.testing_controller)
        """ Create 2 sets of packets, for policry rule1&2 """
        pkt_sender = ScapyPacketInjector(self.IFACE)
        packet1 = IPPacketBuilder()\
            .set_ip_layer('45.10.0.0/20', sub_ip)\
            .set_ether_layer(self.MAC_DEST, "00:00:00:00:00:00")\
            .build()
        packet2 = IPPacketBuilder()\
            .set_ip_layer(sub_ip, '45.10.0.0/20')\
            .set_ether_layer(self.MAC_DEST, "00:00:00:00:00:00")\
            .build()

        # =========================== Verification ===========================
        flow_verifier = FlowVerifier([], self._wait_func(enf_stat_name))
        snapshot_verifier = SnapshotVerifier(self, self.BRIDGE,
                                             self.service_manager)
        """ Send packets, wait until pkts are received by ovs and enf stats """
        with isolator, sub_context, flow_verifier, snapshot_verifier:
            pkt_sender.send(packet1)
            pkt_sender.send(packet2)

        stats = get_enforcement_stats(
            self.enforcement_stats_controller._report_usage.call_args_list)

        self.assertEqual(stats[enf_stat_name[0]].sid, imsi)
        self.assertEqual(stats[enf_stat_name[0]].rule_id, "tx_match")
        self.assertEqual(stats[enf_stat_name[0]].bytes_rx, 0)
        self.assertEqual(stats[enf_stat_name[0]].bytes_tx,
                         num_pkts_tx_match * len(packet1))

        self.assertEqual(stats[enf_stat_name[1]].sid, imsi)
        self.assertEqual(stats[enf_stat_name[1]].rule_id, "rx_match")
        self.assertEqual(stats[enf_stat_name[1]].bytes_tx, 0)

        # downlink packets will discount ethernet header by default
        # so, only count the IP portion
        total_bytes_pkt2 = num_pkts_rx_match * len(packet2[IP])
        self.assertEqual(stats[enf_stat_name[1]].bytes_rx, total_bytes_pkt2)

        self.assertEqual(len(stats), 2)
Example #30
0
    def test_subscriber_two_policies(self):
        """
        Add 2 policies to subscriber

        Assert:
            Packets are properly matched with the 'match' policy
            The total packet delta in the table is from the above match
        """
        fake_controller_setup(self.enforcement_controller)
        imsi = 'IMSI208950000000001'
        sub_ip = '192.168.128.74'
        flow_list1 = [
            FlowDescription(match=FlowMatch(
                ip_src=convert_ipv4_str_to_ip_proto('15.0.0.0/24'),
                direction=FlowMatch.DOWNLINK),
                            action=FlowDescription.DENY)
        ]
        flow_list2 = [
            FlowDescription(match=FlowMatch(ip_proto=6,
                                            direction=FlowMatch.UPLINK),
                            action=FlowDescription.PERMIT)
        ]
        policies = [
            PolicyRule(id='match', priority=2, flow_list=flow_list1),
            PolicyRule(id='no_match', priority=2, flow_list=flow_list2)
        ]
        pkts_sent = 42

        self._static_rule_dict[policies[0].id] = policies[0]
        self._static_rule_dict[policies[1].id] = policies[1]

        # ============================ Subscriber ============================
        sub_context = RyuDirectSubscriberContext(imsi, sub_ip,
                                                 self.enforcement_controller,
                                                 self._tbl_num) \
            .add_static_rule(policies[0].id)\
            .add_static_rule(policies[1].id)
        isolator = RyuDirectTableIsolator(
            RyuForwardFlowArgsBuilder.from_subscriber(
                sub_context.cfg).build_requests(), self.testing_controller)
        pkt_sender = ScapyPacketInjector(self.IFACE)
        packet = IPPacketBuilder()\
            .set_ip_layer(sub_ip, '15.0.0.8')\
            .set_ether_layer(self.MAC_DEST, "00:00:00:00:00:00")\
            .build()
        flow_query = FlowQuery(self._tbl_num,
                               self.testing_controller,
                               match=flow_match_to_magma_match(
                                   flow_list1[0].match))

        # =========================== Verification ===========================
        # Verify aggregate table stats, subscriber 1 'match' rule pkt count
        flow_verifier = FlowVerifier([
            FlowTest(FlowQuery(self._tbl_num, self.testing_controller),
                     pkts_sent),
            FlowTest(flow_query, pkts_sent)
        ], lambda: wait_after_send(self.testing_controller))
        snapshot_verifier = SnapshotVerifier(self, self.BRIDGE,
                                             self.service_manager)

        with isolator, sub_context, flow_verifier, snapshot_verifier:
            pkt_sender.send(packet, pkts_sent)

        flow_verifier.verify()