// Selects a path from the given set that does not lead back to the // specified port. private Path pickForwardPath(Set<Path> paths, PortNumber notToPort) { for (Path path : paths) { if (!path.src().port().equals(notToPort)) { return path; } } return null; }
@Override public void process(PacketContext context) { // Stop processing if the packet has been handled, since we // can't do any more to it. if (context.isHandled()) { return; } InboundPacket pkt = context.inPacket(); Ethernet ethPkt = pkt.parsed(); if (ethPkt == null) { return; } // Bail if this is deemed to be a control packet. if (isControlPacket(ethPkt)) { return; } // Skip IPv6 multicast packet when IPv6 forward is disabled. if (!ipv6Forwarding && isIpv6Multicast(ethPkt)) { return; } HostId id = HostId.hostId(ethPkt.getDestinationMAC()); // Do not process link-local addresses in any way. if (id.mac().isLinkLocal()) { return; } // Do we know who this is for? If not, flood and bail. Host dst = hostService.getHost(id); if (dst == null) { flood(context); return; } // Are we on an edge switch that our destination is on? If so, // simply forward out to the destination and bail. if (pkt.receivedFrom().deviceId().equals(dst.location().deviceId())) { if (!context.inPacket().receivedFrom().port().equals(dst.location().port())) { installRule(context, dst.location().port()); } return; } // Otherwise, get a set of paths that lead from here to the // destination edge switch. Set<Path> paths = topologyService.getPaths( topologyService.currentTopology(), pkt.receivedFrom().deviceId(), dst.location().deviceId()); if (paths.isEmpty()) { // If there are no paths, flood and bail. flood(context); return; } // Otherwise, pick a path that does not lead back to where we // came from; if no such path, flood and bail. Path path = pickForwardPath(paths, pkt.receivedFrom().port()); if (path == null) { log.warn( "Doh... don't know where to go... {} -> {} received on {}", ethPkt.getSourceMAC(), ethPkt.getDestinationMAC(), pkt.receivedFrom()); flood(context); return; } // Otherwise forward and be done with it. installRule(context, path.src().port()); }