def _install_default_flows_if_not_installed( self, datapath, existing_flows: List[OFPFlowStats]) -> List[OFPFlowStats]: inbound_match = MagmaMatch(eth_type=ether_types.ETH_TYPE_IP, direction=Direction.IN) outbound_match = MagmaMatch(eth_type=ether_types.ETH_TYPE_IP, direction=Direction.OUT) inbound_msg = flows.get_add_resubmit_next_service_flow_msg( datapath, self.tbl_num, inbound_match, [], priority=flows.MINIMUM_PRIORITY, resubmit_table=self.next_main_table) outbound_msg = flows.get_add_resubmit_next_service_flow_msg( datapath, self.tbl_num, outbound_match, [], priority=flows.MINIMUM_PRIORITY, resubmit_table=self.next_main_table) msgs, remaining_flows = self._msg_hub \ .filter_msgs_if_not_in_flow_list([inbound_msg, outbound_msg], existing_flows) if msgs: chan = self._msg_hub.send(msgs, datapath) self._wait_for_responses(chan, len(msgs)) return remaining_flows
def _get_rule_match_flow_msgs(self, imsi, rule_num, rule_id): """ Returns flow add messages used for rule matching. """ version = self._session_rule_version_mapper.get_version(imsi, rule_id) self.logger.debug( 'Installing flow for %s with rule num %s (version %s)', imsi, rule_num, version) inbound_rule_match = _generate_rule_match(imsi, rule_num, version, Direction.IN) outbound_rule_match = _generate_rule_match(imsi, rule_num, version, Direction.OUT) return [ flows.get_add_resubmit_next_service_flow_msg( self._datapath, self.tbl_num, inbound_rule_match, [], priority=flows.DEFAULT_PRIORITY, cookie=rule_num, resubmit_table=self.next_table), flows.get_add_resubmit_next_service_flow_msg( self._datapath, self.tbl_num, outbound_rule_match, [], priority=flows.DEFAULT_PRIORITY, cookie=rule_num, resubmit_table=self.next_table), ]
def _get_rule_match_flow_msgs(self, imsi, rule_num): """ Returns flows used for usage reporting in enforcement_stats. These flows match on reg2, which stores the rule num to get usage for each rule. """ inbound_rule_match = MagmaMatch(imsi=encode_imsi(imsi), direction=Direction.IN, reg2=rule_num) outbound_rule_match = MagmaMatch(imsi=encode_imsi(imsi), direction=Direction.OUT, reg2=rule_num) return [ flows.get_add_resubmit_next_service_flow_msg( self._datapath, self._enforcement_stats_scratch, inbound_rule_match, [], priority=flows.DEFAULT_PRIORITY, cookie=rule_num, resubmit_table=self.next_main_table), flows.get_add_resubmit_next_service_flow_msg( self._datapath, self._enforcement_stats_scratch, outbound_rule_match, [], priority=flows.DEFAULT_PRIORITY, cookie=rule_num, resubmit_table=self.next_main_table), ]
def _get_default_middle_flow_msgs(self, dp): """ Egress table is the last table that a packet touches in the pipeline. Output downlink traffic to gtp port, uplink trafic to LOCAL Raises: MagmaOFError if any of the default flows fail to install. """ msgs = [] next_tbl = self._service_manager.get_next_table_num(PHYSICAL_TO_LOGICAL) # Allow passthrough pkts(skip enforcement and send to egress table) ps_match = MagmaMatch(passthrough=PASSTHROUGH_REG_VAL) msgs.append(flows.get_add_resubmit_next_service_flow_msg(dp, self._midle_tbl_num, ps_match, actions=[], priority=flows.PASSTHROUGH_PRIORITY, resubmit_table=self._egress_tbl_num)) match = MagmaMatch() msgs.append(flows.get_add_resubmit_next_service_flow_msg(dp, self._midle_tbl_num, match, actions=[], priority=flows.DEFAULT_PRIORITY, resubmit_table=next_tbl)) if self._mtr_service_enabled: msgs.extend(_get_vlan_egress_flow_msgs(dp, self._midle_tbl_num, self.config.mtr_ip, self.config.mtr_port, priority=flows.UE_FLOW_PRIORITY, direction=Direction.OUT)) return msgs
def _get_rule_match_flow_msgs(self, imsi, ip_addr, ambr, rule): """ Returns flow add messages used for rule matching. """ rule_num = self._rule_mapper.get_or_create_rule_num(rule.id) version = self._session_rule_version_mapper.get_version(imsi, ip_addr, rule.id) self.logger.debug( 'Installing flow for %s with rule num %s (version %s)', imsi, rule_num, version) inbound_rule_match = _generate_rule_match(imsi, ip_addr, rule_num, version, Direction.IN) outbound_rule_match = _generate_rule_match(imsi, ip_addr, rule_num, version, Direction.OUT) inbound_rule_match._match_kwargs[SCRATCH_REGS[1]] = PROCESS_STATS outbound_rule_match._match_kwargs[SCRATCH_REGS[1]] = PROCESS_STATS msgs = [ flows.get_add_resubmit_next_service_flow_msg( self._datapath, self.tbl_num, inbound_rule_match, [], priority=flows.DEFAULT_PRIORITY, cookie=rule_num, resubmit_table=self.next_table), flows.get_add_resubmit_next_service_flow_msg( self._datapath, self.tbl_num, outbound_rule_match, [], priority=flows.DEFAULT_PRIORITY, cookie=rule_num, resubmit_table=self.next_table), ] if rule.app_name: inbound_rule_match._match_kwargs[SCRATCH_REGS[1]] = IGNORE_STATS outbound_rule_match._match_kwargs[SCRATCH_REGS[1]] = IGNORE_STATS msgs.extend([ flows.get_add_resubmit_next_service_flow_msg( self._datapath, self.tbl_num, inbound_rule_match, [], priority=flows.DEFAULT_PRIORITY, cookie=rule_num, resubmit_table=self.next_table), flows.get_add_resubmit_next_service_flow_msg( self._datapath, self.tbl_num, outbound_rule_match, [], priority=flows.DEFAULT_PRIORITY, cookie=rule_num, resubmit_table=self.next_table), ]) return msgs
def _install_default_flows_if_not_installed(self, datapath, existing_flows: List[OFPFlowStats]) -> List[OFPFlowStats]: """ For each direction set the default flows to just forward to next app. The enforcement flows for each subscriber would be added when the IP session is created, by reaching out to the controller/PCRF. If default flows are already installed, do nothing. Args: datapath: ryu datapath struct Returns: The list of flows that remain after inserting default flows """ match = MagmaMatch() msg = flows.get_add_resubmit_next_service_flow_msg( datapath, self.tbl_num, match, [], priority=flows.MINIMUM_PRIORITY, resubmit_table=self.next_main_table) msgs, remaining_flows = self._msg_hub \ .filter_msgs_if_not_in_flow_list([msg], existing_flows) if msgs: chan = self._msg_hub.send(msgs, datapath) self._wait_for_responses(chan, len(msgs)) return remaining_flows
def _install_default_flows_if_not_installed( self, datapath, existing_flows: List[OFPFlowStats]) -> List[OFPFlowStats]: """ Install default flows(if not already installed) to forward the traffic, If no other flows are matched. Returns: The list of flows that remain after inserting default flows """ match = MagmaMatch() msg = flows.get_add_resubmit_next_service_flow_msg( datapath, self.tbl_num, match, [], priority=flows.MINIMUM_PRIORITY, resubmit_table=self.next_table, cookie=self.DEFAULT_FLOW_COOKIE) msg, remaining_flows = \ self._msg_hub.filter_msgs_if_not_in_flow_list([msg], existing_flows) if msg: chan = self._msg_hub.send(msg, datapath) self._wait_for_responses(chan, 1) return remaining_flows
def _get_default_flow_msgs(self, datapath) -> DefaultMsgsMap: """ Gets the default flow msg that forwards to next service Args: datapath: ryu datapath struct Returns: The list of default msgs to add """ match = MagmaMatch() msg = flows.get_add_resubmit_next_service_flow_msg( datapath, self.tbl_num, match, [], priority=flows.MINIMUM_PRIORITY, resubmit_table=self.next_main_table) return {self.tbl_num: [msg]}
def _get_default_flow_msgs(self, datapath) -> DefaultMsgsMap: """ Gets the default flow msg that forward to stats table(traffic will be dropped because stats table doesn't forward anything) Args: datapath: ryu datapath struct Returns: The list of default msgs to add """ match = MagmaMatch() msg = flows.get_add_resubmit_next_service_flow_msg( datapath, self.tbl_num, match, [], priority=flows.MINIMUM_PRIORITY, resubmit_table=self._enforcement_stats_tbl, cookie=self.DEFAULT_FLOW_COOKIE, ) return {self.tbl_num: [msg]}
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_default_ingress_flow_msgs(self, dp): """ Sets up the ingress table, the first step in the packet processing pipeline. This sets up flow rules to annotate packets with a metadata bit indicating the direction. Incoming packets are defined as packets originating from the LOCAL port, outgoing packets are defined as packets originating from the gtp port. All other packets bypass the pipeline. Note that the ingress rules do *not* install any flows that cause PacketIns (i.e., sends packets to the controller). Raises: MagmaOFError if any of the default flows fail to install. """ parser = dp.ofproto_parser next_table = self._service_manager.get_next_table_num(INGRESS) msgs = [] # set traffic direction bits # set a direction bit for incoming (internet -> UE) traffic. match = MagmaMatch(in_port=OFPP_LOCAL) actions = [load_direction(parser, Direction.IN)] msgs.append( flows.get_add_resubmit_next_service_flow_msg( dp, self._ingress_tbl_num, match, actions=actions, priority=flows.DEFAULT_PRIORITY, resubmit_table=next_table)) # set a direction bit for incoming (internet -> UE) traffic. match = MagmaMatch(in_port=self.config.uplink_port) actions = [load_direction(parser, Direction.IN)] msgs.append( flows.get_add_resubmit_next_service_flow_msg( dp, self._ingress_tbl_num, match, actions=actions, priority=flows.DEFAULT_PRIORITY, resubmit_table=next_table)) # Send RADIUS requests directly to li table if self._li_port: match = MagmaMatch(in_port=self._li_port) actions = [load_direction(parser, Direction.IN)] msgs.append( flows.get_add_resubmit_next_service_flow_msg( dp, self._ingress_tbl_num, match, actions=actions, priority=flows.DEFAULT_PRIORITY, resubmit_table=self._li_table)) # set a direction bit for incoming (mtr -> UE) traffic. if self._mtr_service_enabled: match = MagmaMatch(in_port=self.config.mtr_port) actions = [load_direction(parser, Direction.IN)] msgs.append( flows.get_add_resubmit_next_service_flow_msg( dp, self._ingress_tbl_num, match, actions=actions, priority=flows.DEFAULT_PRIORITY, resubmit_table=next_table)) if self.config.he_proxy_port != 0: match = MagmaMatch(in_port=self.config.he_proxy_port) actions = [load_direction(parser, Direction.IN)] msgs.append( flows.get_add_resubmit_next_service_flow_msg( dp, self._ingress_tbl_num, match, actions=actions, priority=flows.DEFAULT_PRIORITY, resubmit_table=next_table)) if self.config.setup_type == 'CWF': # set a direction bit for outgoing (pn -> inet) traffic for remaining traffic ps_match_out = MagmaMatch() actions = [load_direction(parser, Direction.OUT)] msgs.append( flows.get_add_resubmit_next_service_flow_msg( dp, self._ingress_tbl_num, ps_match_out, actions=actions, priority=flows.MINIMUM_PRIORITY, resubmit_table=next_table)) else: # set a direction bit for outgoing (pn -> inet) traffic for remaining traffic # Passthrough is zero for packets from eNodeB GTP tunnels ps_match_out = MagmaMatch(passthrough=REG_ZERO_VAL) actions = [load_direction(parser, Direction.OUT)] msgs.append( flows.get_add_resubmit_next_service_flow_msg( dp, self._ingress_tbl_num, ps_match_out, actions=actions, priority=flows.MINIMUM_PRIORITY, resubmit_table=next_table)) # Passthrough is one for packets from remote PGW GTP tunnels, set direction # flag to IN for such packets. ps_match_in = MagmaMatch(passthrough=PASSTHROUGH_REG_VAL) actions = [load_direction(parser, Direction.IN)] msgs.append( flows.get_add_resubmit_next_service_flow_msg( dp, self._ingress_tbl_num, ps_match_in, actions=actions, priority=flows.MINIMUM_PRIORITY, resubmit_table=next_table)) return msgs