def _add_tunnel_ip_flow_dl( self, i_teid: int, ip_flow_dl: IPFlowDL, gtp_port: int, o_teid: int, enodeb_ip_addr: str, sid: int = None, ): priority = Utils.get_of_priority(ip_flow_dl.precedence) parser = self._datapath.ofproto_parser match = self._get_ip_flow_dl_match(ip_flow_dl, self._uplink_port) actions = [ parser.OFPActionSetField(tunnel_id=o_teid), parser.OFPActionSetField(tun_ipv4_dst=enodeb_ip_addr), parser.NXActionRegLoad2(dst=TUN_PORT_REG, value=gtp_port), ] if i_teid: actions.append(parser.NXActionRegLoad2(dst=INGRESS_TUN_ID_REG, value=i_teid)) if sid: actions.append(parser.OFPActionSetField(metadata=sid)) flows.add_resubmit_next_service_flow( self._datapath, self.tbl_num, match, actions=actions, priority=priority, reset_default_register=False, resubmit_table=self.next_table, ) match = self._get_ip_flow_dl_match(ip_flow_dl, self.config.mtr_port) flows.add_resubmit_next_service_flow( self._datapath, self.tbl_num, match, actions=actions, priority=priority, reset_default_register=False, resubmit_table=self.next_table, )
def _resume_tunnel_flows(self, precedence: int, i_teid: int, ue_ip_adr: str): priority = Utils.get_of_priority(precedence) # Forward flow for gtp port match = MagmaMatch(tunnel_id=i_teid, in_port=self.config.gtp_port) flows.delete_flow(self._datapath, self.tbl_num, match, priority=priority + 1) # Forward flow for LOCAL port match = MagmaMatch(eth_type=ether_types.ETH_TYPE_IP, in_port=self._uplink_port, ipv4_dst=ue_ip_adr) flows.delete_flow(self._datapath, self.tbl_num, match, priority=priority + 1) # Forward flow for mtr port match = MagmaMatch(eth_type=ether_types.ETH_TYPE_IP, in_port=self.config.mtr_port, ipv4_dst=ue_ip_adr) flows.delete_flow(self._datapath, self.tbl_num, match, priority=priority + 1)
def _get_rule_match_flow_msgs(self, imsi, msisdn: bytes, uplink_tunnel: int, ip_addr, apn_ambr, rule): """ Get flow msgs to get stats for a particular rule. Flows will match on IMSI, cookie (the rule num), in/out direction Args: imsi (string): subscriber to install rule for msisdn (bytes): subscriber ISDN ip_addr (string): subscriber session ipv4 address apn_ambr (integer): maximum bandwidth for non-GBR EPS bearers rule (PolicyRule): policy rule proto """ rule_num = self._rule_mapper.get_or_create_rule_num(rule.id) priority = Utils.get_of_priority(rule.priority) flow_adds = [] for flow in rule.flow_list: try: version = self._session_rule_version_mapper.get_version(imsi, ip_addr, rule.id) flow_adds.extend(self._get_classify_rule_flow_msgs( imsi, msisdn, uplink_tunnel, ip_addr, apn_ambr, flow, rule_num, priority, rule.qos, rule.hard_timeout, rule.id, rule.app_name, rule.app_service_type, self.next_service_table, version, self._qos_mgr, self._enforcement_stats_tbl)) except FlowMatchError as err: # invalid match self.logger.error( "Failed to get flow msg '%s' for subscriber %s: %s", rule.id, imsi, err) raise err return flow_adds
def _get_ofport(self, port_name): ovs = Utils.get_ovs_bridge(self._datapath) if ovs is None: return None try: port_no = ovs.get_ofport(port_name) except AssertionError as error: self.logger.debug( 'Cannot get port number for %s: %s', port_name, error, ) return None except Exception as e: # pylint: disable=broad-except self.logger.debug( 'Cannot get port number for %s: %s', port_name, e, ) return None return port_no
def _discard_tunnel_flows(self, precedence: int, i_teid: int, ue_ip_adr: IPAddress): priority = Utils.get_of_priority(precedence) # discard uplink Tunnel match = MagmaMatch(tunnel_id=i_teid, in_port=self.config.gtp_port) flows.delete_flow(self._datapath, self.tbl_num, match, priority=priority + 1) # discard downlink Tunnel for LOCAL port ip_match_out = get_ue_ip_match_args(ue_ip_adr, Direction.IN) match = MagmaMatch(eth_type=get_eth_type(ue_ip_adr), in_port=self._uplink_port, **ip_match_out) flows.delete_flow(self._datapath, self.tbl_num, match, priority=priority + 1) match = MagmaMatch(eth_type=get_eth_type(ue_ip_adr), in_port=self.config.mtr_port, **ip_match_out) flows.delete_flow(self._datapath, self.tbl_num, match, priority=priority + 1)
def _install_redirect_flow(self, imsi, ip_addr, rule, version): rule_num = self._rule_mapper.get_or_create_rule_num(rule.id) priority = Utils.get_of_priority(rule.priority) redirect_request = RedirectionManager.RedirectRequest( imsi=imsi, ip_addr=ip_addr.address.decode('utf-8'), rule=rule, rule_num=rule_num, rule_version=version, priority=priority, ) try: self._redirect_manager.setup_lte_redirect( self._datapath, self.loop, redirect_request, ) return RuleModResult.SUCCESS except RedirectException as err: self.logger.error( 'Redirect Exception for imsi %s, rule.id - %s : %s', imsi, rule.id, err, ) return RuleModResult.FAILURE
def add_s8_tunnel_flows( self, precedence: int, i_teid: int, o_teid: int, ue_ip_adr: IPAddress, enodeb_ip_addr: str, sid: int = None, pgw_ip_addr: str = None, pgw_gtp_port: int = 0, ng_flag: bool = True, unused_ue_ipv6_address: IPAddress = None, unused_vlan: int = 0, ip_flow_dl: IPFlowDL = None, ) -> bool: priority = Utils.get_of_priority(precedence) # Add flow for gtp port if enodeb_ip_addr: gtp_portno = self._add_gtp_port(enodeb_ip_addr) else: gtp_portno = self.config.gtp_port self._install_uplink_s8_tunnel_flows( priority, i_teid, o_teid, pgw_ip_addr, gtp_portno, sid, pgw_gtp_port, ) if ip_flow_dl and ip_flow_dl.set_params: self._add_tunnel_ip_flow_dl( i_teid, ip_flow_dl, gtp_portno, o_teid, enodeb_ip_addr, sid, ) else: gtp_port = pgw_gtp_port if pgw_gtp_port == 0: gtp_port = self.config.gtp_port if o_teid and enodeb_ip_addr: # Add Downlink Tunnel flow for LOCAL port self._install_downlink_tunnel_flows( priority, i_teid, o_teid, gtp_port, ue_ip_adr, enodeb_ip_addr, gtp_portno, sid, ng_flag, ) # Add Downlink Tunnel flow for mtr port self._install_downlink_tunnel_flows( priority, i_teid, o_teid, self.config.mtr_port, ue_ip_adr, enodeb_ip_addr, gtp_portno, sid, ng_flag, ) # Add ARP flow for MTR port if ue_ip_adr.version == IPAddress.IPV4: # Add ARP flow for mtr port self._install_downlink_arp_flows( priority, self.config.mtr_port, ue_ip_adr, sid, ) return True
def _add_tunnel_flows(self, precedence:int, i_teid:int, o_teid:int, ue_ip_adr:str, enodeb_ip_addr:str, sid:int = None): parser = self._datapath.ofproto_parser priority = Utils.get_of_priority(precedence) # Add flow for gtp port match = MagmaMatch(tunnel_id=i_teid, in_port=self.config.gtp_port) actions = [parser.OFPActionSetField(eth_src=GTP_PORT_MAC), parser.OFPActionSetField(eth_dst="ff:ff:ff:ff:ff:ff")] if sid: actions.append(parser.OFPActionSetField(metadata=sid)) flows.add_flow(self._datapath, self.tbl_num, match, actions=actions, priority=priority, goto_table=self.next_table) # Add flow for LOCAL port match = MagmaMatch(eth_type=ether_types.ETH_TYPE_IP,in_port=self._uplink_port, ipv4_dst=ue_ip_adr) actions = [parser.OFPActionSetField(tunnel_id=o_teid), parser.OFPActionSetField(tun_ipv4_dst=enodeb_ip_addr), parser.NXActionRegLoad2(dst=TUN_PORT_REG, value=self.config.gtp_port)] if sid: actions.append(parser.OFPActionSetField(metadata=sid)) flows.add_flow(self._datapath, self.tbl_num, match, actions=actions, priority=priority, goto_table=self.next_table) # Add flow for mtr port match = MagmaMatch(eth_type=ether_types.ETH_TYPE_IP, in_port=self.config.mtr_port, ipv4_dst=ue_ip_adr) flows.add_flow(self._datapath, self.tbl_num, match, actions=actions, priority=priority, goto_table=self.next_table) # Add ARP flow for LOCAL port match = MagmaMatch(eth_type=ether_types.ETH_TYPE_ARP, in_port=self._uplink_port, arp_tpa=ue_ip_adr) actions = [] if sid: actions = [parser.OFPActionSetField(metadata=sid)] flows.add_flow(self._datapath, self.tbl_num, match, actions=actions, priority=priority, goto_table=self.next_table) # Add ARP flow for mtr port match = MagmaMatch(eth_type=ether_types.ETH_TYPE_ARP, in_port=self.config.mtr_port, arp_tpa=ue_ip_adr) flows.add_flow(self._datapath, self.tbl_num, match, actions=actions, priority=priority, goto_table=self.next_table)
def _resume_tunnel_flows(self, precedence: int, i_teid: int, ue_ip_adr: IPAddress = None): priority = Utils.get_of_priority(precedence) # discard uplink Tunnel match = MagmaMatch(tunnel_id=i_teid, in_port=self.config.gtp_port) flows.add_resubmit_next_service_flow(self._datapath, self.tbl_num, match, priority=priority + 1, reset_default_register=False, resubmit_table=self.next_table) # discard downlink Tunnel for LOCAL port if not ue_ip_adr: self.logger.error("ue_ip_address is None") return else: ip_match_out = get_ue_ip_match_args(ue_ip_adr, Direction.IN) match = MagmaMatch(eth_type=get_eth_type(ue_ip_adr), in_port=self._uplink_port, **ip_match_out) flows.add_resubmit_next_service_flow( self._datapath, self.tbl_num, match, priority=priority + 1, reset_default_register=False, resubmit_table=self.next_table) # discard downlink Tunnel for mtr port match = MagmaMatch(eth_type=get_eth_type(ue_ip_adr), in_port=self.config.mtr_port, **ip_match_out) flows.add_resubmit_next_service_flow( self._datapath, self.tbl_num, match, priority=priority + 1, reset_default_register=False, resubmit_table=self.next_table)
def add_tunnel_flows(self, precedence: int, i_teid: int, o_teid: int, ue_ip_adr: IPAddress, enodeb_ip_addr: str, sid: int = None, ng_flag: bool = True) -> bool: priority = Utils.get_of_priority(precedence) # Add flow for gtp port if enodeb_ip_addr: gtp_portno = self._add_gtp_port(enodeb_ip_addr) else: gtp_portno = self.config.gtp_port # Add flow for gtp port for Uplink Tunnel if i_teid: self._install_uplink_tunnel_flows(priority, i_teid, gtp_portno, sid) if o_teid and enodeb_ip_addr: # Add Downlink Tunnel flow for LOCAL port self._install_downlink_tunnel_flows(priority, o_teid, self._uplink_port, ue_ip_adr, enodeb_ip_addr, gtp_portno, sid, ng_flag) # Add Downlink Tunnel flow for mtr port self._install_downlink_tunnel_flows(priority, o_teid, self.config.mtr_port, ue_ip_adr, enodeb_ip_addr, gtp_portno, sid, ng_flag) # Add ARP flow for LOCAL port if ue_ip_adr.version == IPAddress.IPV4: # Add ARP flow for LOCAL port self._install_downlink_arp_flows(priority, self._uplink_port, ue_ip_adr, sid) # Add ARP flow for mtr port self._install_downlink_arp_flows(priority, self.config.mtr_port, ue_ip_adr, sid) return True
def _add_gtp_port(self, gnb_ip): if not self.config.multi_tunnel_flag: return self.config.gtp_port port_name = self._ip_addr_to_gtp_port_name(gnb_ip) # If GTP port already exists, returns OFPort number gtpport = self._get_ofport(port_name) if gtpport is not None: return gtpport ovs = Utils.get_ovs_bridge(self._datapath) if ovs is None: return None port_name = self._ip_addr_to_gtp_port_name(gnb_ip) ovs.add_tunnel_port(port_name, self.ovs_gtp_type, gnb_ip, key="flow") return self._get_ofport(port_name)
def _discard_tunnel_flows(self, precedence: int, i_teid: int, ue_ip_adr: IPAddress = None): priority = Utils.get_of_priority(precedence) # Forward flow for gtp port match = MagmaMatch(tunnel_id=i_teid, in_port=self.config.gtp_port) flows.delete_flow(self._datapath, self.tbl_num, match, priority=priority + 1) # Forward flow for LOCAL port if not ue_ip_adr: self.logger.error("ue_ip_address is None") return else: ip_match_out = get_ue_ip_match_args(ue_ip_adr, Direction.IN) match = MagmaMatch(eth_type=get_eth_type(ue_ip_adr), in_port=self._uplink_port, **ip_match_out) flows.delete_flow(self._datapath, self.tbl_num, match, priority=priority + 1) match = MagmaMatch(eth_type=get_eth_type(ue_ip_adr), in_port=self.config.mtr_port, **ip_match_out) flows.delete_flow(self._datapath, self.tbl_num, match, priority=priority + 1)
def add_tunnel_flows(self, precedence: int, i_teid: int, o_teid: int, ue_ip_adr: IPAddress, enodeb_ip_addr: str, sid: int = None) -> bool: parser = self._datapath.ofproto_parser priority = Utils.get_of_priority(precedence) # Add flow for gtp port if enodeb_ip_addr: gtp_portno = self._add_gtp_port(enodeb_ip_addr) else: gtp_portno = self.config.gtp_port # Add flow for gtp port for Uplink Tunnel actions = [] if i_teid: match = MagmaMatch(tunnel_id=i_teid, in_port=gtp_portno) actions = [ parser.OFPActionSetField(eth_src=GTP_PORT_MAC), parser.OFPActionSetField(eth_dst="ff:ff:ff:ff:ff:ff") ] if sid: actions.append(parser.OFPActionSetField(metadata=sid)) flows.add_resubmit_next_service_flow( self._datapath, self.tbl_num, match, actions=actions, priority=priority, reset_default_register=False, resubmit_table=self.next_table) # Install Downlink Tunnel actions = [] if not ue_ip_adr: self.logger.error("ue_ip_address is None") return else: # Add flow for LOCAL port ip_match_out = get_ue_ip_match_args(ue_ip_adr, Direction.IN) match = MagmaMatch(eth_type=get_eth_type(ue_ip_adr), in_port=self._uplink_port, **ip_match_out) if o_teid and enodeb_ip_addr: actions = [ parser.OFPActionSetField(tunnel_id=o_teid), parser.OFPActionSetField(tun_ipv4_dst=enodeb_ip_addr), parser.OFPActionSetField(tun_flags=TUNNEL_OAM_FLAG), parser.NXActionRegLoad2(dst=TUN_PORT_REG, value=gtp_portno) ] if sid: actions.append(parser.OFPActionSetField(metadata=sid)) flows.add_resubmit_next_service_flow( self._datapath, self.tbl_num, match, actions=actions, priority=priority, reset_default_register=False, resubmit_table=self.next_table) # Add flow for mtr port match = MagmaMatch(eth_type=get_eth_type(ue_ip_adr), in_port=self.config.mtr_port, **ip_match_out) flows.add_resubmit_next_service_flow( self._datapath, self.tbl_num, match, actions=actions, priority=priority, reset_default_register=False, resubmit_table=self.next_table) # Add ARP flow for LOCAL port if ue_ip_adr.version == IPAddress.IPV4: match = MagmaMatch(eth_type=ether_types.ETH_TYPE_ARP, in_port=self._uplink_port, arp_tpa=ipaddress.IPv4Address( ue_ip_adr.address.decode('utf-8'))) actions = [] if sid: actions = [parser.OFPActionSetField(metadata=sid)] flows.add_resubmit_next_service_flow( self._datapath, self.tbl_num, match, actions=actions, priority=priority, reset_default_register=False, resubmit_table=self.next_table) # Add ARP flow for mtr port if ue_ip_adr.version == IPAddress.IPV4: match = MagmaMatch(eth_type=ether_types.ETH_TYPE_ARP, in_port=self.config.mtr_port, arp_tpa=ipaddress.IPv4Address( ue_ip_adr.address.decode('utf-8'))) flows.add_resubmit_next_service_flow( self._datapath, self.tbl_num, match, actions=actions, priority=priority, reset_default_register=False, resubmit_table=self.next_table) return True
def add_tunnel_flows( self, precedence: int, i_teid: int, o_teid: int, enodeb_ip_addr: Union[str, IPAddress], ue_ip_adr: Optional[IPAddress] = None, sid: Optional[int] = None, ng_flag: bool = True, ue_ipv6_address: Optional[IPAddress] = None, unused_apn: Optional[str] = None, unused_vlan: int = 0, ip_flow_dl: Optional[IPFlowDL] = None, session_qfi: QCI = 0, ) -> bool: priority = Utils.get_of_priority(precedence) # Add flow for gtp port if enodeb_ip_addr: gtp_portno = self._add_gtp_port(enodeb_ip_addr) else: gtp_portno = self.config.gtp_port # Add flow for gtp port for Uplink Tunnel if i_teid: self._install_uplink_tunnel_flows( priority, i_teid, gtp_portno, sid, o_teid, ng_flag, session_qfi, ) if ip_flow_dl and ip_flow_dl.set_params: self._add_tunnel_ip_flow_dl( i_teid, ip_flow_dl, gtp_portno, o_teid, enodeb_ip_addr, sid, ) else: if o_teid and enodeb_ip_addr: # Add Downlink Tunnel flow for LOCAL port self._install_downlink_tunnel_flows( priority, i_teid, o_teid, self._uplink_port, ue_ip_adr, enodeb_ip_addr, gtp_portno, sid, ng_flag, ue_ipv6_address, session_qfi, ) # Add Downlink Tunnel flow for mtr port self._install_downlink_tunnel_flows( priority, i_teid, o_teid, self.config.mtr_port, ue_ip_adr, enodeb_ip_addr, gtp_portno, sid, ng_flag, ue_ipv6_address, session_qfi, ) # Add ARP flow for LOCAL port if ue_ip_adr and ue_ip_adr.version == IPAddress.IPV4: # Add ARP flow for LOCAL port self._install_downlink_arp_flows( priority, self._uplink_port, ue_ip_adr, sid, ) # Add ARP flow for mtr port self._install_downlink_arp_flows( priority, self.config.mtr_port, ue_ip_adr, sid, ) return True
def add_tunnel_flows(self, precedence: int, i_teid: int, o_teid: int, ue_ip_adr: str, enodeb_ip_addr: str, sid: int = None) -> bool: parser = self._datapath.ofproto_parser priority = Utils.get_of_priority(precedence) # Add flow for gtp port if enodeb_ip_addr: gtp_portno = self._add_gtp_port(enodeb_ip_addr) else: gtp_portno = self.config.gtp_port # Add flow for gtp port for Uplink Tunnel actions = [] if i_teid: match = MagmaMatch(tunnel_id=i_teid, in_port=gtp_portno) actions = [ parser.OFPActionSetField(eth_src=GTP_PORT_MAC), parser.OFPActionSetField(eth_dst="ff:ff:ff:ff:ff:ff") ] if sid: actions.append(parser.OFPActionSetField(metadata=sid)) flows.add_flow(self._datapath, self.tbl_num, match, actions=actions, priority=priority, goto_table=self.next_table) # Install Downlink Tunnel actions = [] if ue_ip_adr: if o_teid and enodeb_ip_addr: # Add flow for LOCAL port match = MagmaMatch(eth_type=ether_types.ETH_TYPE_IP, in_port=self._uplink_port, ipv4_dst=ue_ip_adr) actions = [ parser.OFPActionSetField(tunnel_id=o_teid), parser.OFPActionSetField(tun_ipv4_dst=enodeb_ip_addr), parser.OFPActionSetField(tun_flags=TUNNEL_OAM_FLAG), parser.NXActionRegLoad2(dst=TUN_PORT_REG, value=gtp_portno) ] if sid: actions.append(parser.OFPActionSetField(metadata=sid)) flows.add_flow(self._datapath, self.tbl_num, match, actions=actions, priority=priority, goto_table=self.next_table) # Add flow for mtr port match = MagmaMatch(eth_type=ether_types.ETH_TYPE_IP, in_port=self.config.mtr_port, ipv4_dst=ue_ip_adr) flows.add_flow(self._datapath, self.tbl_num, match, actions=actions, priority=priority, goto_table=self.next_table) # Add ARP flow for LOCAL port match = MagmaMatch(eth_type=ether_types.ETH_TYPE_ARP, in_port=self._uplink_port, arp_tpa=ue_ip_adr) actions = [] if sid: actions = [parser.OFPActionSetField(metadata=sid)] flows.add_flow(self._datapath, self.tbl_num, match, actions=actions, priority=priority, goto_table=self.next_table) # Add ARP flow for mtr port match = MagmaMatch(eth_type=ether_types.ETH_TYPE_ARP, in_port=self.config.mtr_port, arp_tpa=ue_ip_adr) flows.add_flow(self._datapath, self.tbl_num, match, actions=actions, priority=priority, goto_table=self.next_table) return True