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
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 []
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
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 []
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