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
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)
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
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