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