예제 #1
0
 def _install_ip_blacklist_flow(self, datapath):
     """
     Install flows to drop any packets with ip address blocks matching the
     blacklist.
     """
     for entry in self._ip_blacklist:
         ip_network = ipaddress.IPv4Network(entry['ip'])
         direction = entry.get('direction', None)
         if direction is not None and \
                 direction not in [self.CONFIG_INBOUND_DIRECTION,
                                   self.CONFIG_OUTBOUND_DIRECTION]:
             self.logger.error(
                 'Invalid direction found in ip blacklist: %s', direction)
             continue
         # If no direction is specified, both outbound and inbound traffic
         # will be dropped.
         if direction is None or direction == self.CONFIG_INBOUND_DIRECTION:
             match = MagmaMatch(direction=Direction.OUT,
                                eth_type=ether_types.ETH_TYPE_IP,
                                ipv4_dst=(ip_network.network_address,
                                          ip_network.netmask))
             flows.add_flow(datapath,
                            self.tbl_num,
                            match, [],
                            priority=flows.DEFAULT_PRIORITY)
         if direction is None or \
                 direction == self.CONFIG_OUTBOUND_DIRECTION:
             match = MagmaMatch(direction=Direction.IN,
                                eth_type=ether_types.ETH_TYPE_IP,
                                ipv4_src=(ip_network.network_address,
                                          ip_network.netmask))
             flows.add_flow(datapath,
                            self.tbl_num,
                            match, [],
                            priority=flows.DEFAULT_PRIORITY)
예제 #2
0
 def _install_default_flows(self, datapath):
     """
     For every UE IP block, this adds a pair of  0-priority flow-miss rules
     for incoming and outgoing traffic which trigger PACKET IN.
     """
     parser, ofproto = datapath.ofproto_parser, datapath.ofproto
     imsi_match = (0x1, 0x1)  # match on the last bit set
     inbound_match = MagmaMatch(eth_type=ether_types.ETH_TYPE_IP,
                                direction=Direction.IN,
                                imsi=imsi_match)
     outbound_match = MagmaMatch(eth_type=ether_types.ETH_TYPE_IP,
                                 direction=Direction.OUT,
                                 imsi=imsi_match)
     actions = [
         parser.OFPActionOutput(ofproto.OFPP_CONTROLLER,
                                ofproto.OFPCML_NO_BUFFER)
     ]
     flows.add_flow(datapath,
                    self.tbl_num,
                    inbound_match,
                    actions,
                    priority=flows.MINIMUM_PRIORITY,
                    cookie=self.DEFAULT_FLOW_COOKIE)
     flows.add_flow(datapath,
                    self.tbl_num,
                    outbound_match,
                    actions,
                    priority=flows.MINIMUM_PRIORITY,
                    cookie=self.DEFAULT_FLOW_COOKIE)
예제 #3
0
    def _install_not_processed_flows(self, datapath, imsi, rule, rule_num,
                                     priority):
        """
        Redirect all traffic to the scratch table to only allow redirected
        http traffic to go through, the rest will be dropped. reg0 is used as
        a boolean to know whether the drop rule was processed.
        """
        parser = datapath.ofproto_parser
        of_note = parser.NXActionNote(list(rule.id.encode()))

        match = MagmaMatch(imsi=encode_imsi(imsi),
                           direction=Direction.OUT,
                           reg0=self.REDIRECT_NOT_PROCESSED,
                           eth_type=ether_types.ETH_TYPE_IP)
        action = [of_note]
        flows.add_flow(datapath, self.tbl_num, match, action,
                       priority=priority, cookie=rule_num,
                       hard_timeout=rule.hard_timeout,
                       resubmit_table=self.REDIRECT_SCRATCH_TABLE)

        match = MagmaMatch(imsi=encode_imsi(imsi),
                           direction=Direction.OUT,
                           reg0=self.REDIRECT_PROCESSED)
        action = [of_note]
        flows.add_flow(datapath, self.tbl_num, match, action,
                       priority=priority, cookie=rule_num,
                       hard_timeout=rule.hard_timeout,
                       resubmit_table=self.next_table)
예제 #4
0
    def _install_default_flows(self, datapath):
        """
        For each direction set the default flows to just forward to next table.
        The policies for each subscriber would be added when the IP session is
        created, by reaching out to the controller/PCRF.

        Args:
            datapath: ryu datapath struct
        """
        parser = datapath.ofproto_parser
        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)
        if self._dpi_enabled:
            actions = [parser.OFPActionOutput(self._mon_port_number)]
        else:
            actions = []

        flows.add_flow(datapath,
                       self.tbl_num,
                       inbound_match,
                       actions,
                       priority=flows.MINIMUM_PRIORITY,
                       resubmit_table=self.next_table)
        flows.add_flow(datapath,
                       self.tbl_num,
                       outbound_match,
                       actions,
                       priority=flows.MINIMUM_PRIORITY,
                       resubmit_table=self.next_table)
예제 #5
0
    def _install_default_flows(self, datapath):
        """
        For each direction set the default flows to just forward to next table.
        The policies for each subscriber would be added when the IP session is
        created, by reaching out to the controller/PCRF.

        Args:
            datapath: ryu datapath struct
        """
        parser = self._datapath.ofproto_parser

        # Setup flows to classify & mirror to sampling port
        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)

        actions = [
            parser.NXActionResubmitTable(table_id=self._classify_app_tbl_num)
        ]

        if self._dpi_enabled:
            actions.append(parser.OFPActionOutput(self._mon_port_number))

        flows.add_resubmit_next_service_flow(datapath,
                                             self.tbl_num,
                                             inbound_match,
                                             actions,
                                             priority=flows.MINIMUM_PRIORITY,
                                             resubmit_table=self.next_table)
        flows.add_resubmit_next_service_flow(datapath,
                                             self.tbl_num,
                                             outbound_match,
                                             actions,
                                             priority=flows.MINIMUM_PRIORITY,
                                             resubmit_table=self.next_table)

        # Setup flows for internal IPFIX sampling
        actions = [
            parser.NXActionResubmitTable(table_id=self._classify_app_tbl_num)
        ]

        if self._service_manager.is_app_enabled(IPFIXController.APP_NAME):
            flows.add_resubmit_next_service_flow(
                self._datapath,
                self._app_set_tbl_num,
                MagmaMatch(),
                actions,
                priority=flows.MINIMUM_PRIORITY,
                resubmit_table=self._imsi_set_tbl_num)

        # Setup flows for the application reg classifier tbl
        actions = [
            parser.NXActionRegLoad2(dst=DPI_REG, value=UNCLASSIFIED_PROTO_ID)
        ]
        flows.add_flow(datapath,
                       self._classify_app_tbl_num,
                       MagmaMatch(),
                       actions,
                       priority=flows.MINIMUM_PRIORITY)
예제 #6
0
 def _install_default_tunnel_flows(self):
     match = MagmaMatch()
     flows.add_flow(self._datapath,
                    self.tbl_num,
                    match,
                    priority=flows.MINIMUM_PRIORITY,
                    goto_table=self.next_table)
예제 #7
0
    def add_classify_flow(self, flow_match, flow_state, app: str,
                          service_type: str):
        """
        Parse DPI output and set the register for future packets matching this
        flow. APP is split into tokens as the top level app is not supported,
        but the parent protocol might be.
        Example we care about google traffic, but don't neccessarily want to
        classify every specific google service.
        """
        # TODO add error return
        if self._datapath is None:
            return
        parser = self._datapath.ofproto_parser

        app_id = get_app_id(app, service_type)

        try:
            ul_match = flow_match_to_magma_match(flow_match)
            ul_match.direction = None
            dl_match = flow_match_to_magma_match(flip_flow_match(flow_match))
            dl_match.direction = None
        except FlowMatchError as e:
            self.logger.error(e)
            return

        actions = [parser.NXActionRegLoad2(dst=DPI_REG, value=app_id)]
        # No reason to create a flow here
        if flow_state != FlowRequest.FLOW_CREATED:
            flows.add_flow(self._datapath, self._classify_app_tbl_num,
                ul_match, actions, priority=flows.DEFAULT_PRIORITY,
                idle_timeout=self._idle_timeout)
            flows.add_flow(self._datapath, self._classify_app_tbl_num,
                dl_match, actions, priority=flows.DEFAULT_PRIORITY,
                idle_timeout=self._idle_timeout)
예제 #8
0
    def _install_ipv4_bypass_flows(self, datapath, imsi, rule, rule_num,
                                   priority, ips):
        """
        Installs flows for traffic that is allowed to pass through for
        subscriber who has redirection enabled. Allow access to all passed ips.

        Allow UDP traffic(for DNS queries), traffic to/from redirection address
        """
        parser = datapath.ofproto_parser
        of_note = parser.NXActionNote(list(rule.id.encode()))
        actions = [parser.NXActionRegLoad2(dst='reg2', value=rule_num),
                   of_note]

        matches = []
        for ip in ips:
            matches.append(MagmaMatch(
                eth_type=ether_types.ETH_TYPE_IP, direction=Direction.OUT,
                ipv4_dst=ip, imsi=encode_imsi(imsi)
            ))
            matches.append(MagmaMatch(
                eth_type=ether_types.ETH_TYPE_IP, direction=Direction.IN,
                ipv4_src=ip, imsi=encode_imsi(imsi)
            ))
        for match in matches:
            flows.add_flow(datapath, self.tbl_num, match,
                           actions, priority=priority + 1, cookie=rule_num,
                           hard_timeout=rule.hard_timeout,
                           resubmit_table=self.next_table)
예제 #9
0
 def _install_internal_pkt_fwd_flow(self):
     match = MagmaMatch(in_port=self.config.internal_sampling_port)
     flows.add_flow(self._datapath,
                    self.tbl_num,
                    match,
                    priority=flows.MINIMUM_PRIORITY,
                    goto_table=self.config.internal_sampling_fwd_tbl)
예제 #10
0
 def _install_default_flows(self, datapath):
     """
     Default flow is to forward to next table.
     """
     flows.add_flow(datapath,
                    self.tbl_num,
                    MagmaMatch(), [],
                    priority=flows.MINIMUM_PRIORITY,
                    resubmit_table=self.next_table)
예제 #11
0
    def insert_flow(self, ryu_req):
        """ Parse the ryu request and add flow to the ovs table """
        actions = to_instructions(self._datapath, ryu_req["instructions"])

        flows.add_flow(
            self._datapath, ryu_req["table_id"], ryu_req["match"],
            instructions=actions,
            priority=ryu_req["priority"]
        )
예제 #12
0
 def _install_forward_flow(self, datapath):
     """
     Set a simple forward flow for when metering is disabled
     """
     match = MagmaMatch()
     flows.add_flow(datapath,
                    self.tbl_num,
                    match, [],
                    priority=flows.MINIMUM_PRIORITY,
                    resubmit_table=self.next_table)
예제 #13
0
 def _set_default_forward_flow(self, datapath):
     """
     Set a default 0-priority flow to forward to the next table.
     """
     match = MagmaMatch()
     flows.add_flow(datapath,
                    self.table_num,
                    match, [],
                    priority=flows.MINIMUM_PRIORITY,
                    resubmit_table=self.next_table)
예제 #14
0
    def _set_incoming_arp_flows(self, datapath):
        """
        Install a flow rule to respond in incoming ARP requests for UE IPs.
        Drop all other incoming ARPs.
        """
        parser = datapath.ofproto_parser
        ofproto = datapath.ofproto

        # Set up ARP responder using flow rules. Add a rule with the following
        # actions for each UE IP block:
        # 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
        for ip_block in self.config.ue_ip_blocks:
            match = MagmaMatch(eth_type=ether_types.ETH_TYPE_ARP,
                               direction=Direction.IN,
                               arp_tpa=ip_block)
            actions = [
                parser.NXActionRegMove(src_field='eth_src',
                                       dst_field='eth_dst',
                                       n_bits=48),
                parser.OFPActionSetField(eth_src=self.config.virtual_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=self.config.virtual_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),
                parser.OFPActionOutput(ofproto.OFPP_IN_PORT),
            ]
            flows.add_flow(datapath,
                           self.table_num,
                           match,
                           actions,
                           priority=flows.DEFAULT_PRIORITY)

        # Drop all other ARPs
        match = MagmaMatch(eth_type=ether_types.ETH_TYPE_ARP,
                           direction=Direction.IN)
        flows.add_flow(datapath,
                       self.table_num,
                       match, [],
                       priority=flows.MINIMUM_PRIORITY)
예제 #15
0
    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)
예제 #16
0
    def _install_drop_flow(self, imsi):
        """
        Add a low priority flow to drop a subscriber's traffic in the event
        that all rules have been deactivated.

        Args:
            imsi (string): subscriber id
        """
        match = MagmaMatch(imsi=encode_imsi(imsi))
        actions = []  # empty options == drop
        flows.add_flow(self._datapath,
                       self.tbl_num,
                       match,
                       actions,
                       priority=self.ENFORCE_DROP_PRIORITY)
예제 #17
0
    def _install_new_ingress_egress_flows(self, ev):
        """
        For every packet not already matched by a flow rule, install a pair of
        flows to track all packets to/from the corresponding IMSI.
        """
        msg = ev.msg
        datapath = msg.datapath
        parser = datapath.ofproto_parser

        if not self._matches_table(msg):
            # Intended for other application
            return

        try:
            # no need to decode the IMSI. The OFPMatch will
            # give the already-encoded IMSI value, and we can match on that
            imsi = _get_encoded_imsi_from_packetin(msg)
        except MagmaOFError as e:
            # No packet direction, but intended for this table
            self.logging.error("Error obtaining IMSI from pkt-in: %s", e)
            return

        # Set inbound/outbound tracking flows
        flow_id_note = list(bytes(str(uuid.uuid4()), 'utf-8'))
        outbound_match = MagmaMatch(eth_type=ether_types.ETH_TYPE_IP,
                                    direction=Direction.IN,
                                    imsi=imsi)
        outbound_actions = [parser.NXActionNote(note=flow_id_note)]

        inbound_match = MagmaMatch(eth_type=ether_types.ETH_TYPE_IP,
                                   direction=Direction.OUT,
                                   imsi=imsi)
        inbound_actions = [parser.NXActionNote(note=flow_id_note)]

        flows.add_flow(datapath,
                       self.tbl_num,
                       inbound_match,
                       inbound_actions,
                       priority=flows.DEFAULT_PRIORITY,
                       idle_timeout=self.config.idle_timeout,
                       resubmit_table=self.next_table)
        flows.add_flow(datapath,
                       self.tbl_num,
                       outbound_match,
                       outbound_actions,
                       priority=flows.DEFAULT_PRIORITY,
                       idle_timeout=self.config.idle_timeout,
                       resubmit_table=self.next_table)
예제 #18
0
    def _install_default_egress_flows(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.
        """
        parser = dp.ofproto_parser
        downlink_match = MagmaMatch(direction=Direction.IN)
        downlink_actions = [parser.OFPActionOutput(self.config.gtp_port)]
        flows.add_flow(dp, self._service_manager.get_table_num(EGRESS),
                       downlink_match, downlink_actions)

        uplink_match = MagmaMatch(direction=Direction.OUT)
        uplink_actions = [parser.OFPActionOutput(dp.ofproto.OFPP_LOCAL)]
        flows.add_flow(dp, self._service_manager.get_table_num(EGRESS),
                       uplink_match, uplink_actions)
예제 #19
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.IN)]
        flows.add_flow(dp,
                       tbl_num,
                       match,
                       actions=actions,
                       priority=flows.DEFAULT_PRIORITY,
                       resubmit_table=next_table)

        # set a direction bit for incoming (inet -> pn) traffic.
        match = MagmaMatch(in_port=dp.ofproto.OFPP_LOCAL)
        actions = [load_direction(parser, Direction.IN)]
        flows.add_flow(dp,
                       tbl_num,
                       match,
                       actions=actions,
                       priority=flows.DEFAULT_PRIORITY,
                       resubmit_table=next_table)
예제 #20
0
 def _set_default_eth_dst_flow(self, datapath):
     """
     Add lower-pri flow rule to set `eth_dst` on outgoing packets to the
     specified MAC address.
     """
     self.logger.info('Setting default eth_dst to %s',
                      self.config.virtual_iface)
     parser = datapath.ofproto_parser
     match = MagmaMatch(eth_type=ether_types.ETH_TYPE_IP,
                        direction=Direction.OUT)
     actions = [
         parser.NXActionRegLoad2(dst='eth_dst',
                                 value=self.config.virtual_mac),
     ]
     flows.add_flow(datapath,
                    self.table_num,
                    match,
                    actions,
                    priority=flows.MINIMUM_PRIORITY,
                    resubmit_table=self.next_table)
예제 #21
0
    def _discard_tunnel_flows(self, precedence: int, i_teid: int,
                              ue_ip_adr: str):
        priority = Utils.get_of_priority(precedence)
        # discard uplink Tunnel
        match = MagmaMatch(tunnel_id=i_teid, in_port=self.config.gtp_port)

        flows.add_flow(self._datapath,
                       self.tbl_num,
                       match,
                       priority=priority + 1)

        # discard downlink Tunnel for LOCAL port
        match = MagmaMatch(eth_type=ether_types.ETH_TYPE_IP,
                           in_port=self._uplink_port,
                           ipv4_dst=ue_ip_adr)

        flows.add_flow(self._datapath,
                       self.tbl_num,
                       match,
                       priority=priority + 1)

        # discard downlink Tunnel 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,
                       priority=priority + 1)
예제 #22
0
 def _install_dns_flows(self, datapath, imsi, rule, rule_num, priority):
     """
     Installs flows that allow DNS queries to path thorugh.
     """
     parser = datapath.ofproto_parser
     of_note = parser.NXActionNote(list(rule.id.encode()))
     actions = [
         parser.NXActionRegLoad2(dst='reg2', value=rule_num),
         of_note,
     ]
     matches = []
     # Install UDP flows for DNS
     matches.append(MagmaMatch(eth_type=ether_types.ETH_TYPE_IP,
                               ip_proto=IPPROTO_UDP,
                               udp_src=53,
                               direction=Direction.IN,
                               imsi=encode_imsi(imsi)))
     matches.append(MagmaMatch(eth_type=ether_types.ETH_TYPE_IP,
                               ip_proto=IPPROTO_UDP,
                               udp_dst=53,
                               direction=Direction.OUT,
                               imsi=encode_imsi(imsi)))
     # Install TCP flows for DNS
     matches.append(MagmaMatch(eth_type=ether_types.ETH_TYPE_IP,
                               ip_proto=IPPROTO_TCP,
                               tcp_src=53,
                               direction=Direction.IN,
                               imsi=encode_imsi(imsi)))
     matches.append(MagmaMatch(eth_type=ether_types.ETH_TYPE_IP,
                               ip_proto=IPPROTO_TCP,
                               tcp_dst=53,
                               direction=Direction.OUT,
                               imsi=encode_imsi(imsi)))
     for match in matches:
         flows.add_flow(datapath, self.tbl_num, match, actions,
                        priority=priority, cookie=rule_num,
                        hard_timeout=rule.hard_timeout,
                        resubmit_table=self.next_table)
예제 #23
0
    def _install_default_flows(self, datapath):
        """
        For each direction set the default flows to just forward to next table.
        The enforcement flows for each subscriber would be added when the
        IP session is created, by reaching out to the controller/PCRF.

        Args:
            datapath: ryu datapath struct
        """
        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)
        flows.add_flow(datapath,
                       self.tbl_num,
                       inbound_match, [],
                       priority=flows.MINIMUM_PRIORITY,
                       resubmit_table=self.next_table)
        flows.add_flow(datapath,
                       self.tbl_num,
                       outbound_match, [],
                       priority=flows.MINIMUM_PRIORITY,
                       resubmit_table=self.next_table)
예제 #24
0
    def classify_flow(self, match, app):
        ryu_match = {'eth_type': ether_types.ETH_TYPE_IP}

        ryu_match['ipv4_dst'] = self._get_ip_tuple(match.ipv4_dst)
        ryu_match['ipv4_src'] = self._get_ip_tuple(match.ipv4_src)
        ryu_match['ip_proto'] = match.ip_proto
        if match.ip_proto == match.IPProto.IPPROTO_TCP:
            ryu_match['tcp_dst'] = match.tcp_dst
            ryu_match['tcp_src'] = match.tcp_src
        elif match.ip_proto == match.IPProto.IPPROTO_UDP:
            ryu_match['udp_dst'] = match.udp_dst
            ryu_match['udp_src'] = match.udp_src

        parser = self._datapath.ofproto_parser
        app_id = appMap.get(app, 1)  # 1 is returned for unknown apps
        actions = [parser.NXActionRegLoad2(dst='reg3', value=app_id)]

        flows.add_flow(self._datapath,
                       self.tbl_num,
                       MagmaMatch(**ryu_match),
                       actions,
                       priority=flows.DEFAULT_PRIORITY,
                       resubmit_table=self.next_table)
        return True
예제 #25
0
    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
예제 #26
0
    def _install_server_flows(self, datapath, imsi, rule, rule_num, priority):
        """
        The flow action for subcribers that need to be redirected does 2 things
            * Forward requests from subscriber to the internal http server
            * Instantiate a flow that matches response packets from the server
              and sends them back to subscriber

        Match: incoming tcp traffic with port 80, direction out

        Action:
            1) Set reg2 to rule_num
            2) Set ip dst to server ip
            3) Output to table 20

            4) Apply LearnAction:

            LearnAction(adds new flow for every pkt flow that hits this rule)
                1) Match ip packets
                2) Match tcp protocol
                3) Match packets from LOCAL port
                4) Match ip src = server ip
                5) Match ip dst = current flow ip src
                6) Match tcp src = current flow tcp dst
                7) Match tcp dst = current flow tcp src

                8) Load ip src = current flow ip dst

                9) Output through gtp0
        """
        parser = datapath.ofproto_parser
        match_http = MagmaMatch(
            eth_type=ether_types.ETH_TYPE_IP, ip_proto=IPPROTO_TCP,
            tcp_dst=80, imsi=encode_imsi(imsi), direction=Direction.OUT)
        of_note = parser.NXActionNote(list(rule.id.encode()))

        actions = [
            parser.NXActionLearn(
                table_id=self.tbl_num,
                priority=priority,
                cookie=rule_num,
                specs=[
                    parser.NXFlowSpecMatch(
                        src=ether_types.ETH_TYPE_IP, dst=('eth_type_nxm', 0),
                        n_bits=16
                    ),
                    parser.NXFlowSpecMatch(
                        src=IPPROTO_TCP, dst=('ip_proto_nxm', 0), n_bits=8
                    ),
                    parser.NXFlowSpecMatch(
                        src=Direction.IN.value,
                        dst=(DIRECTION_REG, 0),
                        n_bits=32
                    ),
                    parser.NXFlowSpecMatch(
                        src=int(ipaddress.IPv4Address(self._bridge_ip)),
                        dst=('ipv4_src_nxm', 0),
                        n_bits=32
                    ),
                    parser.NXFlowSpecMatch(
                        src=('ipv4_src_nxm', 0),
                        dst=('ipv4_dst_nxm', 0),
                        n_bits=32
                    ),
                    parser.NXFlowSpecMatch(
                        src=('tcp_src_nxm', 0),
                        dst=('tcp_dst_nxm', 0),
                        n_bits=16
                    ),
                    parser.NXFlowSpecMatch(
                        src=self._redirect_port,
                        dst=('tcp_src_nxm', 0),
                        n_bits=16
                    ),
                    parser.NXFlowSpecMatch(
                        src=encode_imsi(imsi),
                        dst=(IMSI_REG, 0),
                        n_bits=64
                    ),
                    parser.NXFlowSpecLoad(
                        src=('ipv4_dst_nxm', 0),
                        dst=('ipv4_src_nxm', 0),
                        n_bits=32
                    ),
                    parser.NXFlowSpecLoad(
                        src=80,
                        dst=('tcp_src_nxm', 0),
                        n_bits=16
                    ),
                    # Learn doesn't support resubmit to table, so send directly
                    parser.NXFlowSpecOutput(
                        src=('in_port', 0), dst="", n_bits=16
                    )
                ]
            ),
            parser.NXActionRegLoad2(dst='reg2', value=rule_num),
            parser.OFPActionSetField(ipv4_dst=self._bridge_ip),
            parser.OFPActionSetField(tcp_dst=self._redirect_port),
            of_note
        ]

        flows.add_flow(datapath, self.tbl_num, match_http, actions,
                       priority=priority, cookie=rule_num,
                       hard_timeout=rule.hard_timeout,
                       resubmit_table=self.next_table)