Пример #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
Пример #2
0
    def _parse_rcv_packet(self, in_port, vlan_vid, pkt):
        """Parse a received packet into a PacketMeta instance.

        Args:
            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.
        Returns:
            PacketMeta instance.
        """
        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]
        return PacketMeta(pkt, eth_pkt, port, vlan, eth_src, eth_dst)
Пример #3
0
    def _parse_rcv_packet(self, in_port, vlan_vid, pkt):
        """Parse a received packet into a PacketMeta instance.

        Args:
            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.
        Returns:
            PacketMeta instance.
        """
        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]
        return PacketMeta(pkt, eth_pkt, port, vlan, eth_src, eth_dst)
Пример #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 []

        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))

        if self._rate_limit_packet_ins():
            return ofmsgs

        ofmsgs.extend(
            self._learn_host(valves, dp_id, vlan, port, pkt, eth_src))
        return ofmsgs
Пример #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 []

        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))

        if self._rate_limit_packet_ins():
            return ofmsgs

        ofmsgs.extend(
            self._learn_host(valves, dp_id, vlan, port, pkt, eth_src))
        return ofmsgs
Пример #6
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