Пример #1
0
    def _add_dhcp_passthrough_flows(self):
        ofproto, parser = self._datapath.ofproto, self._datapath.ofproto_parser

        # Set so packet skips enforcement controller
        action = load_passthrough(parser)
        uplink_match = MagmaMatch(eth_type=ether_types.ETH_TYPE_IP,
                                  ip_proto=IPPROTO_UDP,
                                  udp_src=68,
                                  udp_dst=67)
        self._add_resubmit_flow(None, uplink_match, action,
                                flows.PASSTHROUGH_PRIORITY,
                                tbl_num=self._passthrough_set_tbl)

        downlink_match = MagmaMatch(eth_type=ether_types.ETH_TYPE_IP,
                                    ip_proto=IPPROTO_UDP,
                                    udp_src=67,
                                    udp_dst=68)
        # Set so triggers packetin and we can learn the ip to do arp response
        self._add_resubmit_flow(None, downlink_match, action,
              flows.PASSTHROUGH_PRIORITY, next_table=self._dhcp_learn_scratch,
              tbl_num=self._passthrough_set_tbl)

        # Install default flow for dhcp learn scratch
        flows.add_output_flow(self._datapath, self._dhcp_learn_scratch,
                              match=MagmaMatch(), actions=[],
                              priority=flows.PASSTHROUGH_PRIORITY,
                              output_port=ofproto.OFPP_CONTROLLER,
                              copy_table=self.next_table,
                              max_len=ofproto.OFPCML_NO_BUFFER)
Пример #2
0
    def _add_dns_passthrough_flows(self, sid, mac_addr):
        parser = self._datapath.ofproto_parser
        # Set so packet skips enforcement and send to egress
        action = load_passthrough(parser)

        # Install UDP flows for DNS
        ulink_match_udp = MagmaMatch(eth_type=ether_types.ETH_TYPE_IP,
                                     ip_proto=IPPROTO_UDP,
                                     udp_dst=53,
                                     eth_src=mac_addr)
        self._add_resubmit_flow(sid, ulink_match_udp, action,
                                flows.PASSTHROUGH_PRIORITY)

        dlink_match_udp = MagmaMatch(eth_type=ether_types.ETH_TYPE_IP,
                                     ip_proto=IPPROTO_UDP,
                                     udp_src=53,
                                     eth_dst=mac_addr)
        self._add_resubmit_flow(sid, dlink_match_udp, action,
                                flows.PASSTHROUGH_PRIORITY)

        # Install TCP flows for DNS
        ulink_match_tcp = MagmaMatch(eth_type=ether_types.ETH_TYPE_IP,
                                     ip_proto=IPPROTO_TCP,
                                     tcp_dst=53,
                                     eth_src=mac_addr)
        self._add_resubmit_flow(sid, ulink_match_tcp, action,
                                flows.PASSTHROUGH_PRIORITY)

        dlink_match_tcp = MagmaMatch(eth_type=ether_types.ETH_TYPE_IP,
                                     ip_proto=IPPROTO_TCP,
                                     tcp_src=53,
                                     eth_dst=mac_addr)
        self._add_resubmit_flow(sid, dlink_match_tcp, action,
                                flows.PASSTHROUGH_PRIORITY)
Пример #3
0
    def _delete_dns_passthrough_flows(self, sid, mac_addr):
        parser = self._datapath.ofproto_parser
        # Set so packet skips enforcement controller
        action = load_passthrough(parser)

        # Install UDP flows for DNS
        ulink_match_udp = MagmaMatch(eth_type=ether_types.ETH_TYPE_IP,
                                     ip_proto=IPPROTO_UDP,
                                     udp_dst=53,
                                     eth_src=mac_addr)
        self._delete_resubmit_flow(sid, ulink_match_udp, action)

        dlink_match_udp = MagmaMatch(eth_type=ether_types.ETH_TYPE_IP,
                                     ip_proto=IPPROTO_UDP,
                                     udp_src=53,
                                     eth_dst=mac_addr)
        self._delete_resubmit_flow(sid, dlink_match_udp, action)

        # Install TCP flows for DNS
        ulink_match_tcp = MagmaMatch(eth_type=ether_types.ETH_TYPE_IP,
                                     ip_proto=IPPROTO_TCP,
                                     tcp_dst=53,
                                     eth_src=mac_addr)
        self._delete_resubmit_flow(sid, ulink_match_tcp, action)

        dlink_match_tcp = MagmaMatch(eth_type=ether_types.ETH_TYPE_IP,
                                     ip_proto=IPPROTO_TCP,
                                     tcp_src=53,
                                     eth_dst=mac_addr)
        self._delete_resubmit_flow(sid, dlink_match_tcp, action)
Пример #4
0
    def set_incoming_arp_flows_res(
        self,
        datapath,
        ip_block,
        flow_priority: int = flows.UE_FLOW_PRIORITY,
    ):
        parser = datapath.ofproto_parser

        arp_resp_match = MagmaMatch(
            eth_type=ether_types.ETH_TYPE_ARP,
            direction=Direction.IN,
            arp_op=arp.ARP_REPLY,
            arp_tpa=ip_block,
        )
        # Set so packet skips enforcement and send to egress
        actions = [load_passthrough(parser)]

        flows.add_resubmit_next_service_flow(
            datapath,
            self.table_num,
            arp_resp_match,
            actions=actions,
            priority=flow_priority,
            resubmit_table=self.next_table,
        )
Пример #5
0
    def set_incoming_arp_flows(self, datapath, ip_block, src_mac,
                               flow_priority: int = flows.UE_FLOW_PRIORITY):
        """
        Install flow rules for incoming ARPs(to UE):
            - For ARP request: respond to incoming ARP requests.
            - For ARP response: pass to next table.
        """
        parser = datapath.ofproto_parser
        ofproto = datapath.ofproto

        arp_resp_match = MagmaMatch(eth_type=ether_types.ETH_TYPE_ARP,
                                    direction=Direction.IN,
                                    arp_op=arp.ARP_REPLY, arp_tpa=ip_block)
        # Set so packet skips enforcement and send to egress
        actions = [load_passthrough(parser)]

        flows.add_resubmit_next_service_flow(datapath, self.table_num,
                                             arp_resp_match, actions=actions,
                                             priority=flow_priority,
                                             resubmit_table=self.next_table)

        # Set up ARP responder using flow rules. Add a rule with the following
        # 1. eth_dst becomes eth_src (back to sender)
        # 2. eth_src becomes the bridge MAC
        # 3. Set ARP op field to reply
        # 4. Target MAC becomes source MAC
        # 5. Source MAC becomes bridge MAC
        # 6. Swap target and source IPs using register 0 as a buffer
        # 7. Send back to the port the packet came on
        arp_req_match = MagmaMatch(eth_type=ether_types.ETH_TYPE_ARP,
                                   direction=Direction.IN,
                                   arp_op=arp.ARP_REQUEST, arp_tpa=ip_block)
        actions = [
            parser.NXActionRegMove(src_field='eth_src',
                                   dst_field='eth_dst',
                                   n_bits=48),
            parser.OFPActionSetField(eth_src=src_mac),
            parser.OFPActionSetField(arp_op=arp.ARP_REPLY),
            parser.NXActionRegMove(src_field='arp_sha',
                                   dst_field='arp_tha',
                                   n_bits=48),
            parser.OFPActionSetField(arp_sha=src_mac),
            parser.NXActionRegMove(src_field='arp_tpa',
                                   dst_field='reg0',
                                   n_bits=32),
            parser.NXActionRegMove(src_field='arp_spa',
                                   dst_field='arp_tpa',
                                   n_bits=32),
            parser.NXActionRegMove(src_field='reg0',
                                   dst_field='arp_spa',
                                   n_bits=32),
        ]
        flows.add_output_flow(datapath, self.table_num, arp_req_match, actions,
                              priority=flow_priority,
                              output_port=ofproto.OFPP_IN_PORT)
Пример #6
0
    def _install_allow_incoming_arp_flow(self, datapath):
        """
        Install a flow rule to allow any ARP packets coming from the UPLINK,
        this will be hit if arp clamping doesn't recognize the address
        """
        parser = datapath.ofproto_parser
        match = MagmaMatch(eth_type=ether_types.ETH_TYPE_ARP,
                           direction=Direction.IN)
        # Set so packet skips enforcement and send to egress
        actions = [load_passthrough(parser)]

        flows.add_resubmit_next_service_flow(datapath, self.table_num, match,
                                             actions=actions, priority=flows.UE_FLOW_PRIORITY - 1,
                                             resubmit_table=self.next_table)
Пример #7
0
    def _add_dns_passthrough_flows(self):
        parser = self._datapath.ofproto_parser
        # Set so packet skips enforcement and send to egress
        action = load_passthrough(parser)

        # Install UDP flows for DNS
        ulink_match_udp = MagmaMatch(eth_type=ether_types.ETH_TYPE_IP,
                                     ip_proto=IPPROTO_UDP,
                                     udp_dst=53)
        self._add_resubmit_flow(None, ulink_match_udp, action,
                                flows.PASSTHROUGH_PRIORITY,
                                tbl_num=self._passthrough_set_tbl)

        dlink_match_udp = MagmaMatch(eth_type=ether_types.ETH_TYPE_IP,
                                     ip_proto=IPPROTO_UDP,
                                     udp_src=53)
        self._add_resubmit_flow(None, dlink_match_udp, action,
                                flows.PASSTHROUGH_PRIORITY,
                                tbl_num=self._passthrough_set_tbl)

        # Install TCP flows for DNS
        ulink_match_tcp = MagmaMatch(eth_type=ether_types.ETH_TYPE_IP,
                                     ip_proto=IPPROTO_TCP,
                                     tcp_dst=53)
        self._add_resubmit_flow(None, ulink_match_tcp, action,
                                flows.PASSTHROUGH_PRIORITY,
                                tbl_num=self._passthrough_set_tbl)

        dlink_match_tcp = MagmaMatch(eth_type=ether_types.ETH_TYPE_IP,
                                     ip_proto=IPPROTO_TCP,
                                     tcp_src=53)
        self._add_resubmit_flow(None, dlink_match_tcp, action,
                                flows.PASSTHROUGH_PRIORITY,
                                tbl_num=self._passthrough_set_tbl)

        # Install TCP flows for DNS over tls
        ulink_match_tcp = MagmaMatch(eth_type=ether_types.ETH_TYPE_IP,
                                     ip_proto=IPPROTO_TCP,
                                     tcp_dst=853)
        self._add_resubmit_flow(None, ulink_match_tcp, action,
                                flows.PASSTHROUGH_PRIORITY,
                                tbl_num=self._passthrough_set_tbl)

        dlink_match_tcp = MagmaMatch(eth_type=ether_types.ETH_TYPE_IP,
                                     ip_proto=IPPROTO_TCP,
                                     tcp_src=853)
        self._add_resubmit_flow(None, dlink_match_tcp, action,
                                flows.PASSTHROUGH_PRIORITY,
                                tbl_num=self._passthrough_set_tbl)
Пример #8
0
    def _set_outgoing_arp_flows(self, datapath, ip_block):
        """
        Install a flow rule to allow any ARP packets coming from the UE
        """
        parser = datapath.ofproto_parser
        match = MagmaMatch(eth_type=ether_types.ETH_TYPE_ARP,
                           direction=Direction.OUT,
                           arp_spa=ip_block)
        # Set so packet skips enforcement and send to egress
        actions = [load_passthrough(parser)]

        flows.add_resubmit_next_service_flow(datapath, self.table_num, match,
                                             actions=actions,
                                             priority=flows.UE_FLOW_PRIORITY,
                                             resubmit_table=self.next_table)
Пример #9
0
    def _delete_dhcp_passthrough_flows(self, sid, mac_addr):
        parser = self._datapath.ofproto_parser

        # Set so packet skips enforcement controller
        action = load_passthrough(parser)
        uplink_match = MagmaMatch(eth_type=ether_types.ETH_TYPE_IP,
                                  ip_proto=IPPROTO_UDP,
                                  udp_src=68,
                                  udp_dst=67,
                                  eth_src=mac_addr)
        self._delete_resubmit_flow(sid, uplink_match, action)

        downlink_match = MagmaMatch(eth_type=ether_types.ETH_TYPE_IP,
                                    ip_proto=IPPROTO_UDP,
                                    udp_src=67,
                                    udp_dst=68,
                                    eth_dst=mac_addr)
        self._delete_resubmit_flow(sid, downlink_match, action)
        imsi_match = MagmaMatch(imsi=encode_imsi(sid))
        flows.delete_flow(self._datapath, self._dhcp_learn_scratch, imsi_match)
Пример #10
0
    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