Example #1
0
    def _get_classify_rule_flow_msgs(self, imsi, ip_addr, apn_ambr, flow,
                                     rule_num, priority, qos, hard_timeout,
                                     rule_id, app_name, app_service_type,
                                     next_table, version, qos_mgr):
        """
        Install a flow from a rule. If the flow action is DENY, then the flow
        will drop the packet. Otherwise, the flow classifies the packet with
        its matched rule and injects the rule num into the packet's register.
        """
        flow_match = flow_match_to_magma_match(flow.match, ip_addr)
        flow_match.imsi = encode_imsi(imsi)
        flow_match_actions, instructions = self._get_action_for_rule(
            flow, rule_num, imsi, ip_addr, apn_ambr, qos, rule_id, version,
            qos_mgr)
        msgs = []
        if app_name:
            # We have to allow initial traffic to pass through, before it gets
            # classified by DPI, flow match set app_id to unclassified
            flow_match.app_id = UNCLASSIFIED_PROTO_ID
            parser = self._datapath.ofproto_parser
            passthrough_actions = flow_match_actions + \
                [parser.NXActionRegLoad2(dst=SCRATCH_REGS[1],
                                         value=IGNORE_STATS)]
            msgs.append(
                flows.get_add_resubmit_current_service_flow_msg(
                    self._datapath,
                    self.tbl_num,
                    flow_match,
                    passthrough_actions,
                    hard_timeout=hard_timeout,
                    priority=self.UNCLASSIFIED_ALLOW_PRIORITY,
                    cookie=rule_num,
                    resubmit_table=next_table))
            flow_match.app_id = get_app_id(
                PolicyRule.AppName.Name(app_name),
                PolicyRule.AppServiceType.Name(app_service_type),
            )

        if flow.action == flow.DENY:
            msgs.append(
                flows.get_add_drop_flow_msg(self._datapath,
                                            self.tbl_num,
                                            flow_match,
                                            flow_match_actions,
                                            hard_timeout=hard_timeout,
                                            priority=priority,
                                            cookie=rule_num))
        else:
            msgs.append(
                flows.get_add_resubmit_current_service_flow_msg(
                    self._datapath,
                    self.tbl_num,
                    flow_match,
                    flow_match_actions,
                    instructions=instructions,
                    hard_timeout=hard_timeout,
                    priority=priority,
                    cookie=rule_num,
                    resubmit_table=next_table))
        return msgs
Example #2
0
    def _get_classify_rule_flow_msg(self, imsi, flow, rule_num, priority,
                                    ul_qos, dl_qos, hard_timeout, rule_id):
        """
        Install a flow from a rule. If the flow action is DENY, then the flow
        will drop the packet. Otherwise, the flow classifies the packet with
        its matched rule and injects the rule num into the packet's register.
        """
        flow_match = flow_match_to_magma_match(flow.match)
        flow_match.imsi = encode_imsi(imsi)
        flow_match_actions = self._get_classify_rule_of_actions(
            flow, rule_num, imsi, ul_qos, dl_qos, rule_id)
        if flow.action == flow.DENY:
            return flows.get_add_drop_flow_msg(self._datapath,
                                               self.tbl_num,
                                               flow_match,
                                               flow_match_actions,
                                               hard_timeout=hard_timeout,
                                               priority=priority,
                                               cookie=rule_num)

        if self._enforcement_stats_scratch:
            return flows.get_add_resubmit_current_service_flow_msg(
                self._datapath,
                self.tbl_num,
                flow_match,
                flow_match_actions,
                hard_timeout=hard_timeout,
                priority=priority,
                cookie=rule_num,
                resubmit_table=self._enforcement_stats_scratch)

        # If enforcement stats has not claimed a scratch table, resubmit
        # directly to the next app.
        return flows.get_add_resubmit_next_service_flow_msg(
            self._datapath,
            self.tbl_num,
            flow_match,
            flow_match_actions,
            hard_timeout=hard_timeout,
            priority=priority,
            cookie=rule_num,
            resubmit_table=self.next_main_table)
Example #3
0
    def _get_classify_rule_flow_msgs(self,
                                     imsi,
                                     msisdn: bytes,
                                     uplink_tunnel: int,
                                     ip_addr,
                                     apn_ambr,
                                     flow,
                                     rule_num,
                                     priority,
                                     qos,
                                     hard_timeout,
                                     rule_id,
                                     app_name,
                                     app_service_type,
                                     next_table,
                                     version,
                                     qos_mgr,
                                     copy_table,
                                     urls: List[str] = None):
        """
        Install a flow from a rule. If the flow action is DENY, then the flow
        will drop the packet. Otherwise, the flow classifies the packet with
        its matched rule and injects the rule num into the packet's register.
        """
        parser = self._datapath.ofproto_parser
        flow_match = flow_match_to_magma_match(flow.match, ip_addr)
        flow_match.imsi = encode_imsi(imsi)
        flow_match_actions, instructions = self._get_action_for_rule(
            flow, rule_num, imsi, ip_addr, apn_ambr, qos, rule_id, version,
            qos_mgr)
        msgs = []
        if app_name:
            # We have to allow initial traffic to pass through, before it gets
            # classified by DPI, flow match set app_id to unclassified
            flow_match.app_id = UNCLASSIFIED_PROTO_ID
            passthrough_actions = flow_match_actions + \
                [parser.NXActionRegLoad2(dst=SCRATCH_REGS[1],
                                         value=IGNORE_STATS)]
            msgs.append(
                flows.get_add_resubmit_current_service_flow_msg(
                    self._datapath,
                    self.tbl_num,
                    flow_match,
                    passthrough_actions,
                    hard_timeout=hard_timeout,
                    priority=Utils.UNCLASSIFIED_ALLOW_PRIORITY,
                    cookie=rule_num,
                    copy_table=copy_table,
                    resubmit_table=next_table))
            flow_match.app_id = get_app_id(
                PolicyRule.AppName.Name(app_name),
                PolicyRule.AppServiceType.Name(app_service_type),
            )

        # For DROP flow just send to stats table, it'll get dropped there
        if flow.action == flow.DENY:
            flow_match_actions = flow_match_actions + \
                [parser.NXActionRegLoad2(dst=SCRATCH_REGS[1],
                                         value=DROP_FLOW_STATS)]
            msgs.append(
                flows.get_add_resubmit_current_service_flow_msg(
                    self._datapath,
                    self.tbl_num,
                    flow_match,
                    flow_match_actions,
                    hard_timeout=hard_timeout,
                    priority=priority,
                    cookie=rule_num,
                    resubmit_table=copy_table))
        else:
            msgs.append(
                flows.get_add_resubmit_current_service_flow_msg(
                    self._datapath,
                    self.tbl_num,
                    flow_match,
                    flow_match_actions,
                    instructions=instructions,
                    hard_timeout=hard_timeout,
                    priority=priority,
                    cookie=rule_num,
                    copy_table=copy_table,
                    resubmit_table=next_table))

        if self.proxy_controller:
            ue_ip = ipv4_address_to_str(ip_addr)
            ip_dst = get_flow_ip_dst(flow.match)
            direction = get_direction_for_match(flow.match)

            proxy_msgs = self.proxy_controller.get_subscriber_he_flows(
                rule_id, direction, ue_ip, uplink_tunnel, ip_dst, rule_num,
                urls, imsi, msisdn)
            msgs.extend(proxy_msgs)
        return msgs
Example #4
0
File: he.py Project: shilawat/magma
    def get_subscriber_flows(self, ue_addr: str, uplink_tunnel: int, ip_dst: str, rule_num: int,
                             urls: List[str], imsi: str, msisdn: bytes):
        """
        Add flow to steer traffic to and from proxy port.
        Args:
            ue_addr(str): IP address of UE
            uplink_tunnel(int) Tunnel ID of the session
            ip_dst(str): HTTP server dst IP (CIDR)
            rule_num(int): rule num of the policy rule
            urls(List[str]): list of HTTP server URLs
            imsi (string): subscriber to install rule for
            msisdn (bytes): subscriber MSISDN
        """
        if not self.config.he_enabled:
            return []

        dp = self._datapath
        parser = dp.ofproto_parser

        try:
            tunnel_id = int(uplink_tunnel)
        except ValueError:
            self.logger.error("parsing tunnel id: [%s], HE might not work in every case", uplink_tunnel)
            tunnel_id = 0

        if urls is None:
            return []

        if ip_dst is None:
            logging.error("Missing dst ip, ignoring HE rule.")
            return []

        logging.info("Add HE: ue_addr %s, uplink_tunnel %s, ip_dst %s, rule_num %s "
                     "urls %s, imsi %s, msisdn %s", ue_addr, uplink_tunnel, ip_dst,
                     str(rule_num), str(urls), imsi, str(msisdn))

        if ip_dst is None or ip_dst == '':
            ip_dst = '0.0.0.0/0'

        self.set_he_target_urls(ue_addr, ip_dst, urls, imsi, msisdn)
        msgs = []
        # 1.a. Going to UE: from uplink send to proxy
        match = MagmaMatch(in_port=self.config.uplink_port,
                           eth_type=ether_types.ETH_TYPE_IP,
                           ipv4_src=ip_dst,
                           ipv4_dst=ue_addr,
                           ip_proto=IPPROTO_TCP,
                           tcp_src=HTTP_PORT,
                           proxy_tag=0)
        actions = [load_direction(parser, Direction.IN),
                   load_passthrough(parser),
                   set_proxy_tag(parser)]
        msgs.append(
            flows.get_add_resubmit_current_service_flow_msg(dp, self.tbl_num,
                                                            match, cookie=rule_num,
                                                            actions=actions,
                                                            priority=flows.DEFAULT_PRIORITY,
                                                            resubmit_table=self.next_table))

        # 1.b. Going to UE: from proxy send to UE
        match = MagmaMatch(in_port=self.config.he_proxy_port,
                           eth_type=ether_types.ETH_TYPE_IP,
                           ipv4_src=ip_dst,
                           ipv4_dst=ue_addr,
                           ip_proto=IPPROTO_TCP,
                           tcp_src=HTTP_PORT)
        actions = [set_in_port(parser, self.config.uplink_port),
                   set_proxy_tag(parser)]
        msgs.append(
            flows.get_add_resubmit_current_service_flow_msg(dp, self.tbl_num,
                                                            match, cookie=rule_num,
                                                            actions=actions,
                                                            priority=flows.DEFAULT_PRIORITY,
                                                            resubmit_table=0))

        # 1.c. continue (1.b) Going to UE: from proxy send to UE
        match = MagmaMatch(in_port=self.config.uplink_port,
                           eth_type=ether_types.ETH_TYPE_IP,
                           ipv4_src=ip_dst,
                           ipv4_dst=ue_addr,
                           ip_proto=IPPROTO_TCP,
                           tcp_src=HTTP_PORT,
                           proxy_tag=PROXY_TAG_TO_PROXY)
        actions = [set_proxy_tag(parser, 0)]
        msgs.append(
            flows.get_add_resubmit_current_service_flow_msg(dp, self.tbl_num,
                                                            match, cookie=rule_num,
                                                            actions=actions,
                                                            priority=flows.DEFAULT_PRIORITY,
                                                            resubmit_table=self.next_table))

        # 2.a. To internet from proxy port, send to uplink
        match = MagmaMatch(in_port=self.config.he_proxy_port,
                           eth_type=ether_types.ETH_TYPE_IP,
                           ipv4_src=ue_addr,
                           ipv4_dst=ip_dst,
                           ip_proto=IPPROTO_TCP,
                           tcp_dst=HTTP_PORT,
                           proxy_tag=0)
        actions = [set_in_port(parser, self.config.gtp_port),
                   set_tun_id(parser, tunnel_id),
                   set_proxy_tag(parser),
                   load_imsi(parser, imsi)]
        msgs.append(
            flows.get_add_resubmit_current_service_flow_msg(dp, self.tbl_num,
                                                            match,
                                                            cookie=rule_num,
                                                            actions=actions,
                                                            priority=flows.MEDIUM_PRIORITY,
                                                            resubmit_table=0))

        # 2.b. Continue from 2.a -> To internet from proxy port, send to uplink
        match = MagmaMatch(in_port=self.config.gtp_port,
                           eth_type=ether_types.ETH_TYPE_IP,
                           ipv4_src=ue_addr,
                           ipv4_dst=ip_dst,
                           ip_proto=IPPROTO_TCP,
                           tcp_dst=HTTP_PORT,
                           proxy_tag=PROXY_TAG_TO_PROXY)
        actions = [set_proxy_tag(parser, 0)]
        msgs.append(
            flows.get_add_resubmit_current_service_flow_msg(dp, self.tbl_num,
                                                            match,
                                                            cookie=rule_num,
                                                            actions=actions,
                                                            priority=flows.DEFAULT_PRIORITY,
                                                            resubmit_table=self.next_table))

        # 2.c. To internet from ue send to proxy, this is coming from HE port
        match = MagmaMatch(eth_type=ether_types.ETH_TYPE_IP,
                           ipv4_src=ue_addr,
                           ipv4_dst=ip_dst,
                           ip_proto=IPPROTO_TCP,
                           tcp_dst=HTTP_PORT,
                           proxy_tag=0)
        actions = [load_direction(parser, Direction.OUT),
                   load_passthrough(parser),
                   set_proxy_tag(parser)]
        msgs.append(
            flows.get_add_resubmit_current_service_flow_msg(dp, self.tbl_num,
                                                            match, cookie=rule_num,
                                                            actions=actions,
                                                            priority=flows.DEFAULT_PRIORITY,
                                                            resubmit_table=self.next_table))
        return msgs