Exemplo n.º 1
0
    def _install_default_ingress_flows(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
        tbl_num = self._service_manager.get_table_num(INGRESS)
        next_table = self._service_manager.get_next_table_num(INGRESS)

        # set traffic direction bits
        # set a direction bit for outgoing (pn -> inet) traffic.
        match = MagmaMatch(in_port=self.config.gtp_port)
        actions = [load_direction(parser, Direction.OUT)]
        flows.add_resubmit_next_service_flow(dp, 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=OFPP_LOCAL)
        actions = [load_direction(parser, Direction.IN)]
        flows.add_resubmit_next_service_flow(dp, 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._uplink_port)
        actions = [load_direction(parser, Direction.IN)]
        flows.add_resubmit_next_service_flow(dp, tbl_num, match,
                                             actions=actions,
                                             priority=flows.DEFAULT_PRIORITY,
                                             resubmit_table=next_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)]
            flows.add_resubmit_next_service_flow(dp, tbl_num, match,
                actions=actions, priority=flows.DEFAULT_PRIORITY,
                resubmit_table=next_table)
Exemplo n.º 2
0
def flow_match_to_actions(datapath, match):
    '''
    Convert a FlowMatch to list of actions to get the same packet

    Args:
        match: FlowMatch
    '''
    parser = datapath.ofproto_parser
    _check_pkt_protocol(match)
    # Eth type and ip proto are read only, can't set them here (set on pkt init)
    actions = [
        parser.OFPActionSetField(
            ipv4_src=getattr(match, 'ipv4_src', '1.1.1.1')),
        parser.OFPActionSetField(
            ipv4_dst=getattr(match, 'ipv4_dst', '1.2.3.4')),
        load_direction(parser, get_direction_for_match(match)),
        parser.NXActionRegLoad2(dst=DPI_REG, value=getattr(match, 'app_id',
                                                           0)),
    ]
    if match.ip_proto == FlowMatch.IPPROTO_TCP:
        actions.extend([
            parser.OFPActionSetField(tcp_src=getattr(match, 'tcp_src', 0)),
            parser.OFPActionSetField(tcp_dst=getattr(match, 'tcp_dst', 0)),
        ])
    elif match.ip_proto == FlowMatch.IPPROTO_UDP:
        actions.extend([
            parser.OFPActionSetField(udp_src=getattr(match, 'udp_src', 0)),
            parser.OFPActionSetField(udp_dst=getattr(match, 'udp_dst', 0)),
        ])
    return actions
Exemplo n.º 3
0
    def _add_dhcp_passthrough_flows(self, sid, mac_addr):
        ofproto, parser = self._datapath.ofproto, self._datapath.ofproto_parser

        # Set so inout knows to skip tables and send to egress
        action = load_direction(parser, Direction.PASSTHROUGH)
        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._add_resubmit_flow(sid, uplink_match, action,
                                flows.PASSTHROUGH_PRIORITY)

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

        # Install default flow for dhcp learn scratch
        imsi_match = MagmaMatch(imsi=encode_imsi(sid))
        flows.add_output_flow(self._datapath,
                              self._dhcp_learn_scratch,
                              match=imsi_match,
                              actions=[],
                              priority=flows.PASSTHROUGH_PRIORITY,
                              output_port=ofproto.OFPP_CONTROLLER,
                              copy_table=self.next_table,
                              max_len=ofproto.OFPCML_NO_BUFFER)
Exemplo n.º 4
0
    def _delete_dns_passthrough_flows(self, sid, mac_addr):
        parser = self._datapath.ofproto_parser
        # Set so inout knows to skip tables and send to egress
        action = load_direction(parser, Direction.PASSTHROUGH)

        # 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)
Exemplo n.º 5
0
    def _add_arp_passthrough_flows(self):
        parser = self._datapath.ofproto_parser
        next_table = self._service_manager.get_next_table_num(self.APP_NAME)

        # Set so inout knows to skip tables and send to egress
        actions = [load_direction(parser, Direction.PASSTHROUGH)]
        arp_match = MagmaMatch(eth_type=ether_types.ETH_TYPE_ARP)
        flows.add_resubmit_next_service_flow(
            self._datapath,
            self.tbl_num,
            arp_match,
            actions=actions,
            priority=flows.PASSTHROUGH_PRIORITY,
            resubmit_table=next_table)
Exemplo n.º 6
0
    def _delete_dhcp_passthrough_flows(self, sid, mac_addr):
        parser = self._datapath.ofproto_parser

        # Set so inout knows to skip tables and send to egress
        action = load_direction(parser, Direction.PASSTHROUGH)

        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)
Exemplo n.º 7
0
    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
Exemplo n.º 8
0
Arquivo: he.py Projeto: shilawat/magma
    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