// 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; }
/** * Creates a new point-to-point intent with the supplied ingress/egress ports and using the * specified explicit path. * * @param appId application identifier * @param selector traffic selector * @param treatment treatment * @param path traversed links * @param constraints optional list of constraints * @param priority priority to use for the generated flows * @throws NullPointerException {@code path} is null */ protected PathIntent( ApplicationId appId, TrafficSelector selector, TrafficTreatment treatment, Path path, List<Constraint> constraints, int priority) { super(appId, null, resources(path.links()), selector, treatment, constraints, priority); PathIntent.validate(path.links()); this.path = path; }
@Override public boolean validate(Path path, LinkResourceService resourceService) { LinkedList<DeviceId> waypoints = new LinkedList<>(this.waypoints); DeviceId current = waypoints.poll(); // This is safe because Path class ensures the number of links are more than 0 Link firstLink = path.links().get(0); if (firstLink.src().elementId().equals(current)) { current = waypoints.poll(); } for (Link link : path.links()) { if (link.dst().elementId().equals(current)) { current = waypoints.poll(); // Empty waypoints means passing through all waypoints in the specified order if (current == null) { return true; } } } return false; }
// Produces a direct edge-to-edge path. private Path edgeToEdgePath(EdgeLink srcLink, EdgeLink dstLink, Path path) { List<Link> links = Lists.newArrayListWithCapacity(2); // Add source and destination edge links only if they are real and // add the infrastructure path only if it is not null. if (srcLink != NOT_HOST) { links.add(srcLink); } if (path != null) { links.addAll(path.links()); } if (dstLink != NOT_HOST) { links.add(dstLink); } return new DefaultPath(PID, links, 2); }
@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()); }