def remove_subscriber_flow(self, ue_addr: IPAddress, rule_num: int = -1): """ Remove proxy flows of give policy rule of the subscriber. Args: ue_addr(str): IP address of UE rule_num(int): rule num of the policy rule """ logging.info("Del he rule: ue-ip: %s rule %d", ue_addr, rule_num) # self.set_he_target_urls(ue_addr, ip_dst, urls, imsi, msisdn) if rule_num == -1: ip_match_in = get_ue_ip_match_args(ue_addr, Direction.IN) match_in = MagmaMatch(eth_type=get_eth_type(ue_addr), **ip_match_in) flows.delete_flow(self._datapath, self.tbl_num, match_in) ip_match_out = get_ue_ip_match_args(ue_addr, Direction.OUT) match_out = MagmaMatch(eth_type=get_eth_type(ue_addr), **ip_match_out) flows.delete_flow(self._datapath, self.tbl_num, match_out) else: match = MagmaMatch() flows.delete_flow(self._datapath, self.tbl_num, match, cookie=rule_num, cookie_mask=flows.OVS_COOKIE_MATCH_ALL)
def _deactivate_flow_for_rule(self, imsi, ip_addr, rule_id): """ Deactivate a specific rule using the flow cookie for a subscriber """ try: num = self._rule_mapper.get_rule_num(rule_id) except KeyError: self.logger.error('Could not find rule id %s', rule_id) return cookie, mask = (num, flows.OVS_COOKIE_MATCH_ALL) ip_match_in = get_ue_ip_match_args(ip_addr, Direction.IN) match = MagmaMatch(eth_type=get_eth_type(ip_addr), imsi=encode_imsi(imsi), **ip_match_in) flows.delete_flow(self._datapath, self.tbl_num, match, cookie=cookie, cookie_mask=mask) ip_match_out = get_ue_ip_match_args(ip_addr, Direction.OUT) match = MagmaMatch(eth_type=get_eth_type(ip_addr), imsi=encode_imsi(imsi), **ip_match_out) flows.delete_flow(self._datapath, self.tbl_num, match, cookie=cookie, cookie_mask=mask) self._redirect_manager.deactivate_flow_for_rule( self._datapath, imsi, num) self._qos_mgr.remove_subscriber_qos(imsi, num) self._remove_he_flows(ip_addr, rule_id, num)
def remove_subscriber_he_flows(self, ue_addr: IPAddress, rule_num: int = -1): """ Remove proxy flows of give policy rule of the subscriber. Args: ue_addr(str): IP address of UE rule_num(int): rule num of the policy rule """ logging.info("Del HE rule: ue-ip: %s rule %d", ue_addr, rule_num) ue_ip_str = ipv4_address_to_str(ue_addr) if ue_ip_str not in self._he_enabled_ue_ips: return if rule_num == -1: ip_match_in = get_ue_ip_match_args(ue_addr, Direction.IN) match_in = MagmaMatch(eth_type=get_eth_type(ue_addr), **ip_match_in) flows.delete_flow(self._datapath, self.tbl_num, match_in) ip_match_out = get_ue_ip_match_args(ue_addr, Direction.OUT) match_out = MagmaMatch(eth_type=get_eth_type(ue_addr), **ip_match_out) flows.delete_flow(self._datapath, self.tbl_num, match_out) else: match = MagmaMatch() flows.delete_flow(self._datapath, self.tbl_num, match, cookie=rule_num, cookie_mask=flows.OVS_COOKIE_MATCH_ALL) deactivate_he_urls_for_ue(ue_addr) self._he_enabled_ue_ips.remove(ue_ip_str)
def remove_subscriber_he_flows( self, ue_addr: IPAddress, rule_id: str = "", rule_num: int = -1, ): """ Remove proxy flows of give policy rule of the subscriber. Args: ue_addr(str): IP address of UE rule_id(str) Rule id rule_num(int): rule num of the policy rule """ ue_ip_str = ipv4_address_to_str(ue_addr) if self._ue_rule_counter.get(ue_ip_str) == 0: return logging.info( "Del HE rule: ue-ip: %s rule_id: %s rule %d", ue_addr, rule_id, rule_num, ) if rule_num == -1: ip_match_in = get_ue_ip_match_args(ue_addr, Direction.IN) match_in = MagmaMatch( eth_type=get_eth_type(ue_addr), **ip_match_in, ) flows.delete_flow(self._datapath, self.tbl_num, match_in) ip_match_out = get_ue_ip_match_args(ue_addr, Direction.OUT) match_out = MagmaMatch( eth_type=get_eth_type(ue_addr), **ip_match_out, ) flows.delete_flow(self._datapath, self.tbl_num, match_out) else: match = MagmaMatch() flows.delete_flow( self._datapath, self.tbl_num, match, cookie=rule_num, cookie_mask=flows.OVS_COOKIE_MATCH_ALL, ) success = deactivate_he_urls_for_ue(ue_addr, rule_id) logging.debug("Del HE proxy: %s", success) if success: if rule_num == -1: self._ue_rule_counter.delete(ue_ip_str) else: self._ue_rule_counter.dec(ue_ip_str)
def remove_paging_flow(self, ue_ip_addr: IPAddress = None, ue_ipv6_addr: IPAddress = None): if ue_ip_addr: ip_match_out = get_ue_ip_match_args(ue_ip_addr, Direction.IN) match = MagmaMatch(eth_type=get_eth_type(ue_ip_addr), **ip_match_out) flows.delete_flow(self._datapath, self.tbl_num, match) if ue_ipv6_addr: ip_match_out = get_ue_ip_match_args(ue_ipv6_addr, Direction.IN) match = MagmaMatch(eth_type=get_eth_type(ue_ipv6_addr), **ip_match_out) flows.delete_flow(self._datapath, self.tbl_num, match) return True
def _get_ip_flow_dl_match(self, ip_flow_dl: IPFlowDL, in_port: int): dest_ip = None src_ip = None if ip_flow_dl.dest_ip.address: addr_str = socket.inet_ntop( socket.AF_INET, ip_flow_dl.dest_ip.address, ) dest_ip = IPAddress( version=IPAddress.IPV4, address=addr_str.encode('utf8'), ) if ip_flow_dl.src_ip.address: addr_str = socket.inet_ntop( socket.AF_INET, ip_flow_dl.src_ip.address, ) src_ip = IPAddress( version=IPAddress.IPV4, address=addr_str.encode('utf8'), ) ip_match_dst = get_ue_ip_match_args(dest_ip, Direction.IN) ip_match_src = get_ue_ip_match_args(src_ip, Direction.OUT) if ip_flow_dl.ip_proto == IPPROTO_TCP: match = MagmaMatch( eth_type=get_eth_type(ip_flow_dl.dest_ip), in_port=in_port, **ip_match_dst, **ip_match_src, ip_proto=ip_flow_dl.ip_proto, tcp_src=ip_flow_dl.tcp_src_port, tcp_dst=ip_flow_dl.tcp_dst_port, ) elif ip_flow_dl.ip_proto == IPPROTO_UDP: match = MagmaMatch( eth_type=get_eth_type(ip_flow_dl.dest_ip), in_port=in_port, **ip_match_dst, **ip_match_src, ip_proto=ip_flow_dl.ip_proto, udp_src=ip_flow_dl.udp_src_port, udp_dst=ip_flow_dl.udp_dst_port, ) return match
def _deactivate_flows_for_subscriber(self, imsi, ip_addr): """ Deactivate all rules for specified subscriber session """ ip_match_in = get_ue_ip_match_args(ip_addr, Direction.IN) match = MagmaMatch(eth_type=get_eth_type(ip_addr), imsi=encode_imsi(imsi), **ip_match_in) flows.delete_flow(self._datapath, self.tbl_num, match) ip_match_out = get_ue_ip_match_args(ip_addr, Direction.OUT) match = MagmaMatch(eth_type=get_eth_type(ip_addr), imsi=encode_imsi(imsi), **ip_match_out) flows.delete_flow(self._datapath, self.tbl_num, match) self._redirect_manager.deactivate_flows_for_subscriber(self._datapath, imsi) self._qos_mgr.remove_subscriber_qos(imsi)
def _resume_tunnel_flows(self, i_teid: int, ue_ip_adr: IPAddress, ip_flow_dl: IPFlowDL = None): # resume 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=Utils.RESUME_RULE_PRIORITY, reset_default_register=False, resubmit_table=self.next_table) if ip_flow_dl.set_params: self._resume_tunnel_ip_flow_dl(ip_flow_dl) else: # Forward 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) flows.add_resubmit_next_service_flow(self._datapath, self.tbl_num, match, priority=Utils.RESUME_RULE_PRIORITY, reset_default_register=False, resubmit_table=self.next_table) # Forward flow for 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=Utils.RESUME_RULE_PRIORITY, reset_default_register=False, resubmit_table=self.next_table)
def install_paging_flow(self, ue_ip_addr: IPAddress, local_f_teid: int, ng_flag: bool = True): ofproto = self._datapath.ofproto parser = self._datapath.ofproto_parser ip_match_out = get_ue_ip_match_args(ue_ip_addr, Direction.IN) match = MagmaMatch(eth_type=get_eth_type(ue_ip_addr), **ip_match_out) # Pass Controller ID value as a ACTION classifier_controller_id = 0 if ng_flag: classifier_controller_id = self.config.classifier_controller_id actions = [ parser.NXActionController(0, classifier_controller_id, ofproto.OFPR_ACTION_SET) ] flows.add_output_flow(self._datapath, self.tbl_num, match=match, actions=actions, priority=Utils.PAGING_RULE_PRIORITY, cookie=local_f_teid, output_port=ofproto.OFPP_CONTROLLER, max_len=ofproto.OFPCML_NO_BUFFER) return True
def discard_tunnel_flows(self, i_teid: int, ue_ip_adr: IPAddress, ip_flow_dl: IPFlowDL = None): # discard 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=Utils.DISCARD_RULE_PRIORITY) if ip_flow_dl and ip_flow_dl.set_params: self._discard_tunnel_ip_flow_dl(ip_flow_dl) else: # 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=Utils.DISCARD_RULE_PRIORITY) 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=Utils.DISCARD_RULE_PRIORITY) return True
def _install_downlink_tunnel_flows(self, priority: int, i_teid: int, o_teid: int, in_port: int, ue_ip_adr: IPAddress, enodeb_ip_addr: str, gtp_portno: int, sid: int, ng_flag: bool): parser = self._datapath.ofproto_parser 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=in_port, **ip_match_out) actions = [ parser.OFPActionSetField(tunnel_id=o_teid), parser.OFPActionSetField(tun_ipv4_dst=enodeb_ip_addr), parser.NXActionRegLoad2(dst=TUN_PORT_REG, value=gtp_portno) ] if ng_flag: actions.append(parser.OFPActionSetField(tun_flags=TUNNEL_OAM_FLAG)) 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)
def _get_default_flow_msgs_for_subscriber(self, imsi, ip_addr): ip_match_in = get_ue_ip_match_args(ip_addr, Direction.IN) match_in = MagmaMatch(eth_type=get_eth_type(ip_addr), imsi=encode_imsi(imsi), **ip_match_in) ip_match_out = get_ue_ip_match_args(ip_addr, Direction.OUT) match_out = MagmaMatch(eth_type=get_eth_type(ip_addr), imsi=encode_imsi(imsi), **ip_match_out) actions = [] return [ flows.get_add_drop_flow_msg( self._datapath, self.tbl_num, match_in, actions, priority=Utils.DROP_PRIORITY), flows.get_add_drop_flow_msg( self._datapath, self.tbl_num, match_out, actions, priority=Utils.DROP_PRIORITY)]
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 _delete_downlink_tunnel_flows(self, ue_ip_adr: IPAddress, in_port: int, ue_ipv6_adr: IPAddress = None): if ue_ip_adr: 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=in_port, **ip_match_out, ) flows.delete_flow(self._datapath, self.tbl_num, match) if ue_ipv6_adr: ip_match_out = get_ue_ip_match_args(ue_ipv6_adr, Direction.IN) match = MagmaMatch( eth_type=get_eth_type(ue_ipv6_adr), in_port=in_port, **ip_match_out, ) flows.delete_flow(self._datapath, self.tbl_num, match)
def _generate_rule_match(imsi, ip_addr, rule_num, version, direction): """ Return a MagmaMatch that matches on the rule num and the version. """ ip_match = get_ue_ip_match_args(ip_addr, direction) return MagmaMatch(imsi=encode_imsi(imsi), eth_type=get_eth_type(ip_addr), direction=direction, rule_num=rule_num, rule_version=version, **ip_match)
def _get_ip_flow_dl_match(self, ip_flow_dl: IPFlowDL, in_port: int): ip_match_dst = get_ue_ip_match_args(ip_flow_dl.dest_ip, Direction.IN) ip_match_src = get_ue_ip_match_args(ip_flow_dl.src_ip, Direction.OUT) if ip_flow_dl.ip_proto == IPPROTO_TCP: match = MagmaMatch(eth_type=get_eth_type(ip_flow_dl.dest_ip), in_port=in_port, **ip_match_dst, **ip_match_src, ip_proto=ip_flow_dl.ip_proto, tcp_src=ip_flow_dl.tcp_src_port, tcp_dst=ip_flow_dl.tcp_dst_port) elif ip_flow_dl.ip_proto == IPPROTO_UDP: match = MagmaMatch(eth_type=get_eth_type(ip_flow_dl.dest_ip), in_port=in_port, **ip_match_dst, **ip_match_src, ip_proto=ip_flow_dl.ip_proto, udp_src=ip_flow_dl.udp_src_port, udp_dst=ip_flow_dl.udp_dst_port) return match
def delete_tunnel_flows(self, i_teid: int, ue_ip_adr: IPAddress, enodeb_ip_addr: str = None) -> bool: # Delete flow for gtp port if enodeb_ip_addr: gtp_portno = self._add_gtp_port(enodeb_ip_addr) else: gtp_portno = self.config.gtp_port if i_teid: match = MagmaMatch(tunnel_id=i_teid, in_port=gtp_portno) flows.delete_flow(self._datapath, self.tbl_num, match) # Delete 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) # Delete flow for mtr port 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) # Delete 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'))) flows.delete_flow(self._datapath, self.tbl_num, match) # Delete 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.delete_flow(self._datapath, self.tbl_num, match) return True
def _add_resubmit_next_service_flow( self, ue_ip_adr: IPAddress, in_port: int, priority: int, actions, ): 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=in_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, )
def _add_output_flow( self, local_f_teid: int, ue_ip_addr: IPAddress, output_port: int, max_len: int, actions, ): ip_match_out = get_ue_ip_match_args(ue_ip_addr, Direction.IN) match = MagmaMatch(eth_type=get_eth_type(ue_ip_addr), **ip_match_out) flows.add_output_flow( self._datapath, self.tbl_num, match=match, actions=actions, priority=Utils.PAGING_RULE_PRIORITY, cookie=local_f_teid, output_port=output_port, max_len=max_len, )
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 _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