Beispiel #1
0
    def rcv_packet(self, dp_id, in_port, vlan_vid, pkt):
        """Handle a packet from the dataplane (eg to re/learn a host).

        The packet may be sent to us also in response to FAUCET
        initiating IPv6 neighbor discovery, or ARP, to resolve
        a nexthop.

        Args:
            dp_id (int): datapath ID.
            in_port (int): port packet was received on.
            vlan_vid (int): VLAN VID of port packet was received on.
            pkt (ryu.lib.packet.packet): packet received.
        Return:
            list: OpenFlow messages, if any.
        """
        if not self._known_up_dpid_and_port(dp_id, in_port):
            return []

        ofmsgs = []
        eth_pkt = valve_packet.parse_pkt(pkt)
        eth_src = eth_pkt.src
        eth_dst = eth_pkt.dst
        vlan = self.dp.vlans[vlan_vid]
        port = self.dp.ports[in_port]

        if valve_packet.mac_addr_is_unicast(eth_src):
            self.logger.debug(
                'Packet_in %s src:%s in_port:%d vid:%s',
                util.dpid_log(dp_id), eth_src, in_port, vlan_vid)

            ofmsgs.extend(self.control_plane_handler(
                in_port, vlan, eth_src, eth_dst, pkt))

        # ban learning new hosts if max_hosts reached on a VLAN.
        if (vlan.max_hosts is not None and
                len(vlan.host_cache) == vlan.max_hosts and
                eth_src not in vlan.host_cache):
            ofmsgs.append(self.host_manager.temp_ban_host_learning_on_vlan(
                vlan))
            self.logger.info(
                'max hosts %u reached on vlan %u, ' +
                'temporarily banning learning on this vlan, ' +
                'and not learning %s',
                vlan.max_hosts, vlan.vid, eth_src)
        else:
            # TODO: it would be good to be able to notify an external
            # system upon re/learning a host.
            ofmsgs.extend(self.host_manager.learn_host_on_vlan_port(
                port, vlan, eth_src))
            self.logger.info(
                'learned %u hosts on vlan %u',
                len(vlan.host_cache), vlan.vid)
        return ofmsgs
Beispiel #2
0
    def control_plane_handler(self, pkt_meta):
        """Handle a packet probably destined to FAUCET's route managers.

        For example, next hop resolution or ICMP echo requests.

        Args:
            pkt_meta (PacketMeta): packet for control plane.
        Returns:
            list: OpenFlow messages, if any.
        """
        if (pkt_meta.eth_dst == self.FAUCET_MAC or
                not valve_packet.mac_addr_is_unicast(pkt_meta.eth_dst)):
            for handler in (self.ipv4_route_manager.control_plane_handler,
                            self.ipv6_route_manager.control_plane_handler):
                ofmsgs = handler(pkt_meta)
                if ofmsgs:
                    return ofmsgs
        return []
Beispiel #3
0
    def control_plane_handler(self, pkt_meta):
        """Handle a packet probably destined to FAUCET's route managers.

        For example, next hop resolution or ICMP echo requests.

        Args:
            pkt_meta (PacketMeta): packet for control plane.
        Returns:
            list: OpenFlow messages, if any.
        """
        if (pkt_meta.eth_dst == self.FAUCET_MAC or
                not valve_packet.mac_addr_is_unicast(pkt_meta.eth_dst)):
            for handler in (self.ipv4_route_manager.control_plane_handler,
                            self.ipv6_route_manager.control_plane_handler):
                ofmsgs = handler(pkt_meta)
                if ofmsgs:
                    return ofmsgs
        return []
Beispiel #4
0
    def rcv_packet(self, dp_id, valves, in_port, vlan_vid, pkt):
        """Handle a packet from the dataplane (eg to re/learn a host).

        The packet may be sent to us also in response to FAUCET
        initiating IPv6 neighbor discovery, or ARP, to resolve
        a nexthop.

        Args:
            dp_id (int): datapath ID.
            valves (dict): all datapaths, indexed by datapath ID.
            in_port (int): port packet was received on.
            vlan_vid (int): VLAN VID of port packet was received on.
            pkt (ryu.lib.packet.packet): packet received.
        Return:
            list: OpenFlow messages, if any.
        """
        if not self._known_up_dpid_and_port(dp_id, in_port):
            return []

        pkt_meta = self._parse_rcv_packet(in_port, vlan_vid, pkt)
        ofmsgs = []

        if valve_packet.mac_addr_is_unicast(pkt_meta.eth_src):
            self.logger.debug(
                'Packet_in %s src:%s in_port:%d vid:%s',
                util.dpid_log(dp_id),
                pkt_meta.eth_src,
                pkt_meta.port.number,
                pkt_meta.vlan.vid)

            ofmsgs.extend(self.control_plane_handler(pkt_meta))

        if self._rate_limit_packet_ins():
            return ofmsgs

        ban_vlan_rules = self._vlan_learn_ban_rules(pkt_meta)
        if ban_vlan_rules:
            ofmsgs.extend(ban_vlan_rules)
            return ofmsgs

        ofmsgs.extend(self._learn_host(valves, dp_id, pkt_meta))
        return ofmsgs
Beispiel #5
0
    def rcv_packet(self, dp_id, valves, in_port, vlan_vid, pkt):
        """Handle a packet from the dataplane (eg to re/learn a host).

        The packet may be sent to us also in response to FAUCET
        initiating IPv6 neighbor discovery, or ARP, to resolve
        a nexthop.

        Args:
            dp_id (int): datapath ID.
            valves (dict): all datapaths, indexed by datapath ID.
            in_port (int): port packet was received on.
            vlan_vid (int): VLAN VID of port packet was received on.
            pkt (ryu.lib.packet.packet): packet received.
        Return:
            list: OpenFlow messages, if any.
        """
        if not self._known_up_dpid_and_port(dp_id, in_port):
            return []

        pkt_meta = self._parse_rcv_packet(in_port, vlan_vid, pkt)
        ofmsgs = []

        if valve_packet.mac_addr_is_unicast(pkt_meta.eth_src):
            self.logger.debug(
                'Packet_in %s src:%s in_port:%d vid:%s',
                util.dpid_log(dp_id),
                pkt_meta.eth_src,
                pkt_meta.port.number,
                pkt_meta.vlan.vid)

            ofmsgs.extend(self.control_plane_handler(pkt_meta))

        if self._rate_limit_packet_ins():
            return ofmsgs

        ban_vlan_rules = self._vlan_learn_ban_rules(pkt_meta)
        if ban_vlan_rules:
            ofmsgs.extend(ban_vlan_rules)
            return ofmsgs

        ofmsgs.extend(self._learn_host(valves, dp_id, pkt_meta))
        return ofmsgs
Beispiel #6
0
    def control_plane_handler(self, in_port, vlan, eth_src, eth_dst, pkt):
        """Handle a packet probably destined to FAUCET's route managers.

        For example, next hop resolution or ICMP echo requests.

        Args:
            in_port (int): port the packet was received on.
            vlan (vlan): vlan of the port the packet was received on.
            eth_src (str): source Ethernet MAC address.
            eth_dst (str): destination Ethernet MAC address.
            pkt (ryu.lib.packet.ethernet): packet received.
        Returns:
            list: OpenFlow messages, if any.
        """
        if eth_dst == self.FAUCET_MAC or not valve_packet.mac_addr_is_unicast(eth_dst):
            for handler in (self.ipv4_route_manager.control_plane_handler,
                            self.ipv6_route_manager.control_plane_handler):
                ofmsgs = handler(in_port, vlan, eth_src, eth_dst, pkt)
                if ofmsgs:
                    return ofmsgs
        return []
Beispiel #7
0
    def control_plane_handler(self, in_port, vlan, eth_src, eth_dst, pkt):
        """Handle a packet probably destined to FAUCET's route managers.

        For example, next hop resolution or ICMP echo requests.

        Args:
            in_port (int): port the packet was received on.
            vlan (vlan): vlan of the port the packet was received on.
            eth_src (str): source Ethernet MAC address.
            eth_dst (str): destination Ethernet MAC address.
            pkt (ryu.lib.packet.ethernet): packet received.
        Returns:
            list: OpenFlow messages, if any.
        """
        if eth_dst == self.FAUCET_MAC or not valve_packet.mac_addr_is_unicast(eth_dst):
            for handler in (self.ipv4_route_manager.control_plane_handler,
                            self.ipv6_route_manager.control_plane_handler):
                ofmsgs = handler(in_port, vlan, eth_src, eth_dst, pkt)
                if ofmsgs:
                    return ofmsgs
        return []
Beispiel #8
0
    def rcv_packet(self, dp_id, valves, in_port, vlan_vid, pkt):
        """Handle a packet from the dataplane (eg to re/learn a host).

        The packet may be sent to us also in response to FAUCET
        initiating IPv6 neighbor discovery, or ARP, to resolve
        a nexthop.

        Args:
            dp_id (int): datapath ID.
            valves (dict): all datapaths, indexed by datapath ID.
            in_port (int): port packet was received on.
            vlan_vid (int): VLAN VID of port packet was received on.
            pkt (ryu.lib.packet.packet): packet received.
        Return:
            list: OpenFlow messages, if any.
        """
        if not self._known_up_dpid_and_port(dp_id, in_port):
            return []

        ofmsgs = []
        eth_pkt = valve_packet.parse_pkt(pkt)
        eth_src = eth_pkt.src
        eth_dst = eth_pkt.dst
        vlan = self.dp.vlans[vlan_vid]
        port = self.dp.ports[in_port]

        if valve_packet.mac_addr_is_unicast(eth_src):
            self.logger.debug(
                'Packet_in %s src:%s in_port:%d vid:%s',
                util.dpid_log(dp_id), eth_src, in_port, vlan_vid)

            ofmsgs.extend(self.control_plane_handler(
                in_port, vlan, eth_src, eth_dst, pkt))

        # Apply learning packet in rate limit.
        if self.dp.ignore_learn_ins:
            if int(time.time() * 1e3) % self.dp.ignore_learn_ins == 0:
                return ofmsgs

        # ban learning new hosts if max_hosts reached on a VLAN.
        if (vlan.max_hosts is not None and
                len(vlan.host_cache) == vlan.max_hosts and
                eth_src not in vlan.host_cache):
            ofmsgs.append(self.host_manager.temp_ban_host_learning_on_vlan(
                vlan))
            self.logger.info(
                'max hosts %u reached on vlan %u, ' +
                'temporarily banning learning on this vlan, ' +
                'and not learning %s',
                vlan.max_hosts, vlan.vid, eth_src)
        else:
            if port.stack is None:
                learn_port = port
            else:
                # TODO: simplest possible unicast learning.
                # We find just one port that is the shortest unicast path to
                # the destination. We could use other factors (eg we could
                # load balance over multiple ports based on destination MAC).
                # TODO: each DP learns independently. An edge DP could
                # call other valves so they learn immediately without waiting
                # for packet in.
                # TODO: edge DPs could use a different forwarding algorithm
                # (for example, just default switch to a neighbor).
                host_learned_other_dp = None
                # Find port that forwards closer to destination DP that
                # has already learned this host (if any).
                for other_dpid, other_valve in valves.iteritems():
                    if other_dpid == dp_id:
                        continue
                    other_dp = other_valve.dp
                    other_dp_host_cache = other_dp.vlans[vlan_vid].host_cache
                    if eth_src in other_dp_host_cache:
                        host = other_dp_host_cache[eth_src]
                        if host.edge:
                            host_learned_other_dp = other_dp
                            break
                # No edge DP may have learned this host yet.
                if host_learned_other_dp is None:
                    return ofmsgs

                learn_port = self.dp.shortest_path_port(
                    host_learned_other_dp.name)
                self.logger.info(
                    'host learned via stack port to %s',
                    host_learned_other_dp.name)

            # TODO: it would be good to be able to notify an external
            # system upon re/learning a host.
            ofmsgs.extend(self.host_manager.learn_host_on_vlan_port(
                learn_port, vlan, eth_src))
            self.logger.info(
                'learned %u hosts on vlan %u',
                len(vlan.host_cache), vlan.vid)
        return ofmsgs