Ejemplo n.º 1
0
    def ingress_packet_in_handler(self, event):
        msg = event.msg
        ofproto = self.ofproto

        if msg.reason == ofproto.OFPR_INVALID_TTL:
            LOG.debug("Get an invalid TTL packet at table %s",
                      const.INGRESS_NAT_TABLE)
            if self.ingress_ttl_invalid_handler_rate_limit():
                LOG.warning("Get more than %(rate)s TTL invalid "
                            "packets per second at table %(table)s",
                            {'rate': self.conf.dnat_ttl_invalid_max_rate,
                             'table': const.INGRESS_NAT_TABLE})
                return

            icmp_ttl_pkt = icmp_error_generator.generate(
                icmp.ICMP_TIME_EXCEEDED, icmp.ICMP_TTL_EXPIRED_CODE, msg.data)
            in_port = msg.match.get('in_port')
            self.send_packet(in_port, icmp_ttl_pkt)
            return

        if self.ingress_icmp_error_rate_limit():
            LOG.warning("Get more than %(rate)s ICMP error messages "
                        "per second at table %(table)s",
                        {'rate': self.conf.dnat_icmp_error_max_rate,
                         'table': const.INGRESS_NAT_TABLE})
            return

        pkt = packet.Packet(msg.data)
        reply_pkt = self._revert_nat_for_icmp_embedded_packet(pkt, INGRESS)
        lport_unique_key = msg.match.get('reg7')
        self.dispatch_packet(reply_pkt, lport_unique_key)
Ejemplo n.º 2
0
    def _handle_egress_invalid_ttl(self, event):
        LOG.debug("Get an invalid TTL packet at table %s",
                  const.EGRESS_NAT_TABLE)

        if self.egress_ttl_invalid_handler_rate_limit():
            LOG.warning("Get more than %(rate)s TTL invalid "
                        "packets per second at table %(table)s",
                        {'rate': self.conf.dnat_ttl_invalid_max_rate,
                         'table': const.EGRESS_NAT_TABLE})
            return

        msg = event.msg

        pkt = packet.Packet(msg.data)
        e_pkt = pkt.get_protocol(ethernet.ethernet)
        port_key = msg.match.get('reg6')
        floatingip = self.fip_port_key_cache.get(port_key)
        if floatingip is None:
            LOG.warning("The invalid TTL packet's destination mac %s "
                        "can't be recognized.", e_pkt.src)
            return

        icmp_ttl_pkt = icmp_error_generator.generate(
            icmp.ICMP_TIME_EXCEEDED, icmp.ICMP_TTL_EXPIRED_CODE,
            msg.data, floatingip.floating_ip_address, pkt)
        self.dispatch_packet(icmp_ttl_pkt, port_key)
Ejemplo n.º 3
0
    def _handle_ttl_expired(self, msg):
        if self.ttl_invalid_handler_rate_limit():
            LOG.warning("Get more than %(rate)s TTL invalid packets per "
                        "second at table %(table)s",
                        {'rate': self.conf.router_ttl_invalid_max_rate,
                         'table': const.L3_LOOKUP_TABLE})
            return

        LOG.debug("Get an invalid TTL packet at table %s",
                  const.L3_LOOKUP_TABLE)

        pkt = packet.Packet(msg.data)
        e_pkt = pkt.get_protocol(ethernet.ethernet)
        router_key = msg.match.get('reg5')
        lrouter = self.db_store.get_one(
            l3.LogicalRouter(unique_key=router_key),
            index=l3.LogicalRouter.get_index('unique_key'),
        )
        router_port_ip = None
        for port in lrouter.ports:
            if port.lswitch.unique_key == msg.match.get('metadata'):
                router_port_ip = port.network.ip
                break

        if router_port_ip:
            icmp_ttl_pkt = icmp_error_generator.generate(
                icmp.ICMP_TIME_EXCEEDED, icmp.ICMP_TTL_EXPIRED_CODE,
                msg.data, str(router_port_ip), pkt)
            unique_key = msg.match.get('reg6')
            self.dispatch_packet(icmp_ttl_pkt, unique_key)
        else:
            LOG.warning("The invalid TTL packet's destination mac %s "
                        "can't be recognized.", e_pkt.dst)
Ejemplo n.º 4
0
    def _handle_invalid_dest(self, msg):
        """
        Handle a packet sent to the router interface (by IP). Since only ping
        and ARP are supported, everything else is responded to with a
        Destination Unreachable message.

        :param msg: Packet in message
        :type msg:  ryu.ofproto.ofproto_v<version>_parser.OFPPacketIn
        """
        # If the destination is router interface, the unique key of router
        # interface will be set to reg7 before sending to local controller.
        # Code will hit here only when the router interface is not
        # concrete.
        if self.port_icmp_unreach_respond_rate_limit():
            LOG.warning(
                "Get more than %(rate)s packets to router port "
                "per second at table %(table)s", {
                    'rate': self.conf.router_port_unreach_max_rate,
                    'table': const.L3_LOOKUP_TABLE
                })
            return

        # Response icmp unreachable to udp or tcp.
        pkt = packet.Packet(msg.data)
        tcp_pkt = pkt.get_protocol(tcp.tcp)
        udp_pkt = pkt.get_protocol(udp.udp)
        if tcp_pkt or udp_pkt:
            icmp_dst_unreach = icmp_error_generator.generate(
                icmp.ICMP_DEST_UNREACH,
                icmp.ICMP_PORT_UNREACH_CODE,
                msg.data,
                pkt=pkt)
            unique_key = msg.match.get('reg6')
            self.dispatch_packet(icmp_dst_unreach, unique_key)
Ejemplo n.º 5
0
    def _handle_ingress_invalid_ttl(self, event):
        LOG.debug("Get an invalid TTL packet at table %s",
                  const.INGRESS_NAT_TABLE)

        if self.ingress_ttl_invalid_handler_rate_limit():
            LOG.warning("Get more than %(rate)s TTL invalid "
                        "packets per second at table %(table)s",
                        {'rate': self.conf.dnat_ttl_invalid_max_rate,
                         'table': const.INGRESS_NAT_TABLE})
            return

        msg = event.msg

        icmp_ttl_pkt = icmp_error_generator.generate(
            icmp.ICMP_TIME_EXCEEDED, icmp.ICMP_TTL_EXPIRED_CODE, msg.data)
        network_id = msg.match.get('metadata')
        self.reinject_packet(
            icmp_ttl_pkt,
            table_id=const.L2_LOOKUP_TABLE,
            actions=[self.parser.OFPActionSetField(metadata=network_id)]
        )
Ejemplo n.º 6
0
    def egress_packet_in_handler(self, event):
        msg = event.msg
        ofproto = self.ofproto

        if msg.reason == ofproto.OFPR_INVALID_TTL:
            LOG.debug("Get an invalid TTL packet at table %s",
                      const.EGRESS_NAT_TABLE)
            if self.egress_ttl_invalid_handler_rate_limit():
                LOG.warning("Get more than %(rate)s TTL invalid "
                            "packets per second at table %(table)s",
                            {'rate': self.conf.dnat_ttl_invalid_max_rate,
                             'table': const.EGRESS_NAT_TABLE})
                return

            pkt = packet.Packet(msg.data)
            e_pkt = pkt.get_protocol(ethernet.ethernet)
            mac = netaddr.EUI(e_pkt.src)
            floatingip = self.floatingip_rarp_cache.get(mac)
            if floatingip:
                icmp_ttl_pkt = icmp_error_generator.generate(
                    icmp.ICMP_TIME_EXCEEDED, icmp.ICMP_TTL_EXPIRED_CODE,
                    msg.data, floatingip, pkt)
                unique_key = msg.match.get('reg6')
                self.dispatch_packet(icmp_ttl_pkt, unique_key)
            else:
                LOG.warning("The invalid TTL packet's destination mac %s "
                            "can't be recognized.", e_pkt.src)
            return

        if self.external_bridge_mac:
            if self.ingress_icmp_error_rate_limit():
                LOG.warning("Get more than %(rate)s ICMP error messages "
                            "per second at table %(table)s",
                            {'rate': self.conf.dnat_icmp_error_max_rate,
                             'table': const.INGRESS_NAT_TABLE})
                return

            pkt = packet.Packet(msg.data)
            reply_pkt = self._revert_nat_for_icmp_embedded_packet(pkt, EGRESS)
            self.send_packet(self.external_ofport, reply_pkt)
Ejemplo n.º 7
0
    def _handle_invalid_dest(self, msg):
        # If the destination is router interface, the unique key of router
        # interface will be set to reg7 before sending to local controller.
        # Code will hit here only when the router interface is not
        # concrete.
        if self.port_icmp_unreach_respond_rate_limit():
            LOG.warning(
                "Get more than %(rate)s packets to router port "
                "per second at table %(table)s",
                {'rate': self.conf.router_port_unreach_max_rate,
                 'table': const.L3_LOOKUP_TABLE})
            return

        # Response icmp unreachable to udp or tcp.
        pkt = packet.Packet(msg.data)
        tcp_pkt = pkt.get_protocol(tcp.tcp)
        udp_pkt = pkt.get_protocol(udp.udp)
        if tcp_pkt or udp_pkt:
            icmp_dst_unreach = icmp_error_generator.generate(
                icmp.ICMP_DEST_UNREACH, icmp.ICMP_PORT_UNREACH_CODE,
                msg.data, pkt=pkt)
            unique_key = msg.match.get('reg6')
            self.dispatch_packet(icmp_dst_unreach, unique_key)
Ejemplo n.º 8
0
    def router_function_packet_in_handler(self, msg):
        """React to packet as what a normal router will do.

        TTL invalid and router port response will be handled in this method.
        Return True if the packet is handled, so there is no need for further
        handle.
        """

        if msg.reason == self.ofproto.OFPR_INVALID_TTL:
            LOG.debug("Get an invalid TTL packet at table %s",
                      const.L3_LOOKUP_TABLE)
            if self.ttl_invalid_handler_rate_limit():
                LOG.warning("Get more than %(rate)s TTL invalid packets per "
                            "second at table %(table)s",
                            {'rate': self.conf.router_ttl_invalid_max_rate,
                             'table': const.L3_LOOKUP_TABLE})
                return True

            pkt = packet.Packet(msg.data)
            e_pkt = pkt.get_protocol(ethernet.ethernet)
            mac = netaddr.EUI(e_pkt.dst)
            router_port_ip = self.router_port_rarp_cache.get(mac)
            if router_port_ip:
                icmp_ttl_pkt = icmp_error_generator.generate(
                    icmp.ICMP_TIME_EXCEEDED, icmp.ICMP_TTL_EXPIRED_CODE,
                    msg.data, str(router_port_ip), pkt)
                unique_key = msg.match.get('reg6')
                self.dispatch_packet(icmp_ttl_pkt, unique_key)
            else:
                LOG.warning("The invalid TTL packet's destination mac %s "
                            "can't be recognized.", e_pkt.dst)
            return True

        if msg.match.get('reg7'):
            # If the destination is router interface, the unique key of router
            # interface will be set to reg7 before sending to local controller.
            # Code will hit here only when the router interface is not
            # concrete.
            if self.port_icmp_unreach_respond_rate_limit():
                LOG.warning(
                    "Get more than %(rate)s packets to router port "
                    "per second at table %(table)s",
                    {'rate': self.conf.router_port_unreach_max_rate,
                     'table': const.L3_LOOKUP_TABLE})
                return True

            # Response icmp unreachable to udp or tcp.
            pkt = packet.Packet(msg.data)
            tcp_pkt = pkt.get_protocol(tcp.tcp)
            udp_pkt = pkt.get_protocol(udp.udp)
            if tcp_pkt or udp_pkt:
                icmp_dst_unreach = icmp_error_generator.generate(
                    icmp.ICMP_DEST_UNREACH, icmp.ICMP_PORT_UNREACH_CODE,
                    msg.data, pkt=pkt)
                unique_key = msg.match.get('reg6')
                self.dispatch_packet(icmp_dst_unreach, unique_key)

            # Silently drop packet of other protocol.
            return True

        # No match in previous code.
        return False